Commit 50b5d1fc authored by Filipe Manana's avatar Filipe Manana Committed by David Sterba

btrfs: do not BUG_ON() on tree mod log failures at insert_ptr()

At insert_ptr(), instead of doing a BUG_ON() in case we fail to record
tree mod log operations, do a transaction abort and return the error to
the callers. There's really no need for the BUG_ON() as we can release all
resources in the context of all callers, and we have to abort because other
future tree searches that use the tree mod log (btrfs_search_old_slot())
may get inconsistent results if other operations modify the tree after
that failure and before the tree mod log based search.

This implies making insert_ptr() return an int instead of void, and making
all callers check for returned errors.
Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent f61aa7ba
...@@ -2990,7 +2990,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans, ...@@ -2990,7 +2990,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
* slot and level indicate where you want the key to go, and * slot and level indicate where you want the key to go, and
* blocknr is the block the key points to. * blocknr is the block the key points to.
*/ */
static void insert_ptr(struct btrfs_trans_handle *trans, static int insert_ptr(struct btrfs_trans_handle *trans,
struct btrfs_path *path, struct btrfs_path *path,
struct btrfs_disk_key *key, u64 bytenr, struct btrfs_disk_key *key, u64 bytenr,
int slot, int level) int slot, int level)
...@@ -3009,7 +3009,10 @@ static void insert_ptr(struct btrfs_trans_handle *trans, ...@@ -3009,7 +3009,10 @@ static void insert_ptr(struct btrfs_trans_handle *trans,
if (level) { if (level) {
ret = btrfs_tree_mod_log_insert_move(lower, slot + 1, ret = btrfs_tree_mod_log_insert_move(lower, slot + 1,
slot, nritems - slot); slot, nritems - slot);
BUG_ON(ret < 0); if (ret < 0) {
btrfs_abort_transaction(trans, ret);
return ret;
}
} }
memmove_extent_buffer(lower, memmove_extent_buffer(lower,
btrfs_node_key_ptr_offset(lower, slot + 1), btrfs_node_key_ptr_offset(lower, slot + 1),
...@@ -3019,7 +3022,10 @@ static void insert_ptr(struct btrfs_trans_handle *trans, ...@@ -3019,7 +3022,10 @@ static void insert_ptr(struct btrfs_trans_handle *trans,
if (level) { if (level) {
ret = btrfs_tree_mod_log_insert_key(lower, slot, ret = btrfs_tree_mod_log_insert_key(lower, slot,
BTRFS_MOD_LOG_KEY_ADD); BTRFS_MOD_LOG_KEY_ADD);
BUG_ON(ret < 0); if (ret < 0) {
btrfs_abort_transaction(trans, ret);
return ret;
}
} }
btrfs_set_node_key(lower, key, slot); btrfs_set_node_key(lower, key, slot);
btrfs_set_node_blockptr(lower, slot, bytenr); btrfs_set_node_blockptr(lower, slot, bytenr);
...@@ -3027,6 +3033,8 @@ static void insert_ptr(struct btrfs_trans_handle *trans, ...@@ -3027,6 +3033,8 @@ static void insert_ptr(struct btrfs_trans_handle *trans,
btrfs_set_node_ptr_generation(lower, slot, trans->transid); btrfs_set_node_ptr_generation(lower, slot, trans->transid);
btrfs_set_header_nritems(lower, nritems + 1); btrfs_set_header_nritems(lower, nritems + 1);
btrfs_mark_buffer_dirty(lower); btrfs_mark_buffer_dirty(lower);
return 0;
} }
/* /*
...@@ -3106,8 +3114,13 @@ static noinline int split_node(struct btrfs_trans_handle *trans, ...@@ -3106,8 +3114,13 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
btrfs_mark_buffer_dirty(c); btrfs_mark_buffer_dirty(c);
btrfs_mark_buffer_dirty(split); btrfs_mark_buffer_dirty(split);
insert_ptr(trans, path, &disk_key, split->start, ret = insert_ptr(trans, path, &disk_key, split->start,
path->slots[level + 1] + 1, level + 1); path->slots[level + 1] + 1, level + 1);
if (ret < 0) {
btrfs_tree_unlock(split);
free_extent_buffer(split);
return ret;
}
if (path->slots[level] >= mid) { if (path->slots[level] >= mid) {
path->slots[level] -= mid; path->slots[level] -= mid;
...@@ -3584,7 +3597,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -3584,7 +3597,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
* split the path's leaf in two, making sure there is at least data_size * split the path's leaf in two, making sure there is at least data_size
* available for the resulting leaf level of the path. * available for the resulting leaf level of the path.
*/ */
static noinline void copy_for_split(struct btrfs_trans_handle *trans, static noinline int copy_for_split(struct btrfs_trans_handle *trans,
struct btrfs_path *path, struct btrfs_path *path,
struct extent_buffer *l, struct extent_buffer *l,
struct extent_buffer *right, struct extent_buffer *right,
...@@ -3594,6 +3607,7 @@ static noinline void copy_for_split(struct btrfs_trans_handle *trans, ...@@ -3594,6 +3607,7 @@ static noinline void copy_for_split(struct btrfs_trans_handle *trans,
int data_copy_size; int data_copy_size;
int rt_data_off; int rt_data_off;
int i; int i;
int ret;
struct btrfs_disk_key disk_key; struct btrfs_disk_key disk_key;
struct btrfs_map_token token; struct btrfs_map_token token;
...@@ -3618,7 +3632,9 @@ static noinline void copy_for_split(struct btrfs_trans_handle *trans, ...@@ -3618,7 +3632,9 @@ static noinline void copy_for_split(struct btrfs_trans_handle *trans,
btrfs_set_header_nritems(l, mid); btrfs_set_header_nritems(l, mid);
btrfs_item_key(right, &disk_key, 0); btrfs_item_key(right, &disk_key, 0);
insert_ptr(trans, path, &disk_key, right->start, path->slots[1] + 1, 1); ret = insert_ptr(trans, path, &disk_key, right->start, path->slots[1] + 1, 1);
if (ret < 0)
return ret;
btrfs_mark_buffer_dirty(right); btrfs_mark_buffer_dirty(right);
btrfs_mark_buffer_dirty(l); btrfs_mark_buffer_dirty(l);
...@@ -3636,6 +3652,8 @@ static noinline void copy_for_split(struct btrfs_trans_handle *trans, ...@@ -3636,6 +3652,8 @@ static noinline void copy_for_split(struct btrfs_trans_handle *trans,
} }
BUG_ON(path->slots[0] < 0); BUG_ON(path->slots[0] < 0);
return 0;
} }
/* /*
...@@ -3834,8 +3852,13 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, ...@@ -3834,8 +3852,13 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
if (split == 0) { if (split == 0) {
if (mid <= slot) { if (mid <= slot) {
btrfs_set_header_nritems(right, 0); btrfs_set_header_nritems(right, 0);
insert_ptr(trans, path, &disk_key, ret = insert_ptr(trans, path, &disk_key,
right->start, path->slots[1] + 1, 1); right->start, path->slots[1] + 1, 1);
if (ret < 0) {
btrfs_tree_unlock(right);
free_extent_buffer(right);
return ret;
}
btrfs_tree_unlock(path->nodes[0]); btrfs_tree_unlock(path->nodes[0]);
free_extent_buffer(path->nodes[0]); free_extent_buffer(path->nodes[0]);
path->nodes[0] = right; path->nodes[0] = right;
...@@ -3843,8 +3866,13 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, ...@@ -3843,8 +3866,13 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
path->slots[1] += 1; path->slots[1] += 1;
} else { } else {
btrfs_set_header_nritems(right, 0); btrfs_set_header_nritems(right, 0);
insert_ptr(trans, path, &disk_key, ret = insert_ptr(trans, path, &disk_key,
right->start, path->slots[1], 1); right->start, path->slots[1], 1);
if (ret < 0) {
btrfs_tree_unlock(right);
free_extent_buffer(right);
return ret;
}
btrfs_tree_unlock(path->nodes[0]); btrfs_tree_unlock(path->nodes[0]);
free_extent_buffer(path->nodes[0]); free_extent_buffer(path->nodes[0]);
path->nodes[0] = right; path->nodes[0] = right;
...@@ -3860,7 +3888,12 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, ...@@ -3860,7 +3888,12 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
return ret; return ret;
} }
copy_for_split(trans, path, l, right, slot, mid, nritems); ret = copy_for_split(trans, path, l, right, slot, mid, nritems);
if (ret < 0) {
btrfs_tree_unlock(right);
free_extent_buffer(right);
return ret;
}
if (split == 2) { if (split == 2) {
BUG_ON(num_doubles != 0); BUG_ON(num_doubles != 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment