Skip to content

Commit 50b5d1f

Browse files
fdmananakdave
authored andcommitted
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>
1 parent f61aa7b commit 50b5d1f

1 file changed

Lines changed: 52 additions & 19 deletions

File tree

fs/btrfs/ctree.c

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2990,10 +2990,10 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
29902990
* slot and level indicate where you want the key to go, and
29912991
* blocknr is the block the key points to.
29922992
*/
2993-
static void insert_ptr(struct btrfs_trans_handle *trans,
2994-
struct btrfs_path *path,
2995-
struct btrfs_disk_key *key, u64 bytenr,
2996-
int slot, int level)
2993+
static int insert_ptr(struct btrfs_trans_handle *trans,
2994+
struct btrfs_path *path,
2995+
struct btrfs_disk_key *key, u64 bytenr,
2996+
int slot, int level)
29972997
{
29982998
struct extent_buffer *lower;
29992999
int nritems;
@@ -3009,7 +3009,10 @@ static void insert_ptr(struct btrfs_trans_handle *trans,
30093009
if (level) {
30103010
ret = btrfs_tree_mod_log_insert_move(lower, slot + 1,
30113011
slot, nritems - slot);
3012-
BUG_ON(ret < 0);
3012+
if (ret < 0) {
3013+
btrfs_abort_transaction(trans, ret);
3014+
return ret;
3015+
}
30133016
}
30143017
memmove_extent_buffer(lower,
30153018
btrfs_node_key_ptr_offset(lower, slot + 1),
@@ -3019,14 +3022,19 @@ static void insert_ptr(struct btrfs_trans_handle *trans,
30193022
if (level) {
30203023
ret = btrfs_tree_mod_log_insert_key(lower, slot,
30213024
BTRFS_MOD_LOG_KEY_ADD);
3022-
BUG_ON(ret < 0);
3025+
if (ret < 0) {
3026+
btrfs_abort_transaction(trans, ret);
3027+
return ret;
3028+
}
30233029
}
30243030
btrfs_set_node_key(lower, key, slot);
30253031
btrfs_set_node_blockptr(lower, slot, bytenr);
30263032
WARN_ON(trans->transid == 0);
30273033
btrfs_set_node_ptr_generation(lower, slot, trans->transid);
30283034
btrfs_set_header_nritems(lower, nritems + 1);
30293035
btrfs_mark_buffer_dirty(lower);
3036+
3037+
return 0;
30303038
}
30313039

30323040
/*
@@ -3106,8 +3114,13 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
31063114
btrfs_mark_buffer_dirty(c);
31073115
btrfs_mark_buffer_dirty(split);
31083116

3109-
insert_ptr(trans, path, &disk_key, split->start,
3110-
path->slots[level + 1] + 1, level + 1);
3117+
ret = insert_ptr(trans, path, &disk_key, split->start,
3118+
path->slots[level + 1] + 1, level + 1);
3119+
if (ret < 0) {
3120+
btrfs_tree_unlock(split);
3121+
free_extent_buffer(split);
3122+
return ret;
3123+
}
31113124

31123125
if (path->slots[level] >= mid) {
31133126
path->slots[level] -= mid;
@@ -3584,16 +3597,17 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
35843597
* split the path's leaf in two, making sure there is at least data_size
35853598
* available for the resulting leaf level of the path.
35863599
*/
3587-
static noinline void copy_for_split(struct btrfs_trans_handle *trans,
3588-
struct btrfs_path *path,
3589-
struct extent_buffer *l,
3590-
struct extent_buffer *right,
3591-
int slot, int mid, int nritems)
3600+
static noinline int copy_for_split(struct btrfs_trans_handle *trans,
3601+
struct btrfs_path *path,
3602+
struct extent_buffer *l,
3603+
struct extent_buffer *right,
3604+
int slot, int mid, int nritems)
35923605
{
35933606
struct btrfs_fs_info *fs_info = trans->fs_info;
35943607
int data_copy_size;
35953608
int rt_data_off;
35963609
int i;
3610+
int ret;
35973611
struct btrfs_disk_key disk_key;
35983612
struct btrfs_map_token token;
35993613

@@ -3618,7 +3632,9 @@ static noinline void copy_for_split(struct btrfs_trans_handle *trans,
36183632

36193633
btrfs_set_header_nritems(l, mid);
36203634
btrfs_item_key(right, &disk_key, 0);
3621-
insert_ptr(trans, path, &disk_key, right->start, path->slots[1] + 1, 1);
3635+
ret = insert_ptr(trans, path, &disk_key, right->start, path->slots[1] + 1, 1);
3636+
if (ret < 0)
3637+
return ret;
36223638

36233639
btrfs_mark_buffer_dirty(right);
36243640
btrfs_mark_buffer_dirty(l);
@@ -3636,6 +3652,8 @@ static noinline void copy_for_split(struct btrfs_trans_handle *trans,
36363652
}
36373653

36383654
BUG_ON(path->slots[0] < 0);
3655+
3656+
return 0;
36393657
}
36403658

36413659
/*
@@ -3834,17 +3852,27 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
38343852
if (split == 0) {
38353853
if (mid <= slot) {
38363854
btrfs_set_header_nritems(right, 0);
3837-
insert_ptr(trans, path, &disk_key,
3838-
right->start, path->slots[1] + 1, 1);
3855+
ret = insert_ptr(trans, path, &disk_key,
3856+
right->start, path->slots[1] + 1, 1);
3857+
if (ret < 0) {
3858+
btrfs_tree_unlock(right);
3859+
free_extent_buffer(right);
3860+
return ret;
3861+
}
38393862
btrfs_tree_unlock(path->nodes[0]);
38403863
free_extent_buffer(path->nodes[0]);
38413864
path->nodes[0] = right;
38423865
path->slots[0] = 0;
38433866
path->slots[1] += 1;
38443867
} else {
38453868
btrfs_set_header_nritems(right, 0);
3846-
insert_ptr(trans, path, &disk_key,
3847-
right->start, path->slots[1], 1);
3869+
ret = insert_ptr(trans, path, &disk_key,
3870+
right->start, path->slots[1], 1);
3871+
if (ret < 0) {
3872+
btrfs_tree_unlock(right);
3873+
free_extent_buffer(right);
3874+
return ret;
3875+
}
38483876
btrfs_tree_unlock(path->nodes[0]);
38493877
free_extent_buffer(path->nodes[0]);
38503878
path->nodes[0] = right;
@@ -3860,7 +3888,12 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
38603888
return ret;
38613889
}
38623890

3863-
copy_for_split(trans, path, l, right, slot, mid, nritems);
3891+
ret = copy_for_split(trans, path, l, right, slot, mid, nritems);
3892+
if (ret < 0) {
3893+
btrfs_tree_unlock(right);
3894+
free_extent_buffer(right);
3895+
return ret;
3896+
}
38643897

38653898
if (split == 2) {
38663899
BUG_ON(num_doubles != 0);

0 commit comments

Comments
 (0)