mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 12:53:04 -04:00
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: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
committed by
David Sterba
parent
f61aa7ba08
commit
50b5d1fc41
@@ -2990,10 +2990,10 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
|
||||
* slot and level indicate where you want the key to go, and
|
||||
* blocknr is the block the key points to.
|
||||
*/
|
||||
static void insert_ptr(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_path *path,
|
||||
struct btrfs_disk_key *key, u64 bytenr,
|
||||
int slot, int level)
|
||||
static int insert_ptr(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_path *path,
|
||||
struct btrfs_disk_key *key, u64 bytenr,
|
||||
int slot, int level)
|
||||
{
|
||||
struct extent_buffer *lower;
|
||||
int nritems;
|
||||
@@ -3009,7 +3009,10 @@ static void insert_ptr(struct btrfs_trans_handle *trans,
|
||||
if (level) {
|
||||
ret = btrfs_tree_mod_log_insert_move(lower, slot + 1,
|
||||
slot, nritems - slot);
|
||||
BUG_ON(ret < 0);
|
||||
if (ret < 0) {
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
memmove_extent_buffer(lower,
|
||||
btrfs_node_key_ptr_offset(lower, slot + 1),
|
||||
@@ -3019,7 +3022,10 @@ static void insert_ptr(struct btrfs_trans_handle *trans,
|
||||
if (level) {
|
||||
ret = btrfs_tree_mod_log_insert_key(lower, slot,
|
||||
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_blockptr(lower, slot, bytenr);
|
||||
@@ -3027,6 +3033,8 @@ static void insert_ptr(struct btrfs_trans_handle *trans,
|
||||
btrfs_set_node_ptr_generation(lower, slot, trans->transid);
|
||||
btrfs_set_header_nritems(lower, nritems + 1);
|
||||
btrfs_mark_buffer_dirty(lower);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3106,8 +3114,13 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
|
||||
btrfs_mark_buffer_dirty(c);
|
||||
btrfs_mark_buffer_dirty(split);
|
||||
|
||||
insert_ptr(trans, path, &disk_key, split->start,
|
||||
path->slots[level + 1] + 1, level + 1);
|
||||
ret = insert_ptr(trans, path, &disk_key, split->start,
|
||||
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) {
|
||||
path->slots[level] -= mid;
|
||||
@@ -3584,16 +3597,17 @@ 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
|
||||
* available for the resulting leaf level of the path.
|
||||
*/
|
||||
static noinline void copy_for_split(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_path *path,
|
||||
struct extent_buffer *l,
|
||||
struct extent_buffer *right,
|
||||
int slot, int mid, int nritems)
|
||||
static noinline int copy_for_split(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_path *path,
|
||||
struct extent_buffer *l,
|
||||
struct extent_buffer *right,
|
||||
int slot, int mid, int nritems)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = trans->fs_info;
|
||||
int data_copy_size;
|
||||
int rt_data_off;
|
||||
int i;
|
||||
int ret;
|
||||
struct btrfs_disk_key disk_key;
|
||||
struct btrfs_map_token token;
|
||||
|
||||
@@ -3618,7 +3632,9 @@ static noinline void copy_for_split(struct btrfs_trans_handle *trans,
|
||||
|
||||
btrfs_set_header_nritems(l, mid);
|
||||
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(l);
|
||||
@@ -3636,6 +3652,8 @@ static noinline void copy_for_split(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
|
||||
BUG_ON(path->slots[0] < 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3834,8 +3852,13 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
|
||||
if (split == 0) {
|
||||
if (mid <= slot) {
|
||||
btrfs_set_header_nritems(right, 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) {
|
||||
btrfs_tree_unlock(right);
|
||||
free_extent_buffer(right);
|
||||
return ret;
|
||||
}
|
||||
btrfs_tree_unlock(path->nodes[0]);
|
||||
free_extent_buffer(path->nodes[0]);
|
||||
path->nodes[0] = right;
|
||||
@@ -3843,8 +3866,13 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
|
||||
path->slots[1] += 1;
|
||||
} else {
|
||||
btrfs_set_header_nritems(right, 0);
|
||||
insert_ptr(trans, path, &disk_key,
|
||||
right->start, path->slots[1], 1);
|
||||
ret = insert_ptr(trans, path, &disk_key,
|
||||
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]);
|
||||
free_extent_buffer(path->nodes[0]);
|
||||
path->nodes[0] = right;
|
||||
@@ -3860,7 +3888,12 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
|
||||
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) {
|
||||
BUG_ON(num_doubles != 0);
|
||||
|
||||
Reference in New Issue
Block a user