Message ID | 4d83a67f420c7e8f6ceb4535ab5431fde9ecc82f.1686164810.git.fdmanana@suse.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | btrfs: some fixes and updates around handling errors for tree mod log operations | expand |
On 2023/6/8 03:24, fdmanana@kernel.org wrote: > From: Filipe Manana <fdmanana@suse.com> > > At balance_level(), 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 this context, 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. > > Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: Qu Wenruo <wqu@suse.com> Thanks, Qu > --- > fs/btrfs/ctree.c | 17 ++++++++++++++--- > 1 file changed, 14 insertions(+), 3 deletions(-) > > diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c > index d6c29564ce49..d60b28c6bd1b 100644 > --- a/fs/btrfs/ctree.c > +++ b/fs/btrfs/ctree.c > @@ -1054,7 +1054,12 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, > } > > ret = btrfs_tree_mod_log_insert_root(root->node, child, true); > - BUG_ON(ret < 0); > + if (ret < 0) { > + btrfs_tree_unlock(child); > + free_extent_buffer(child); > + btrfs_abort_transaction(trans, ret); > + goto enospc; > + } > rcu_assign_pointer(root->node, child); > > add_root_to_dirty_list(root); > @@ -1142,7 +1147,10 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, > btrfs_node_key(right, &right_key, 0); > ret = btrfs_tree_mod_log_insert_key(parent, pslot + 1, > BTRFS_MOD_LOG_KEY_REPLACE); > - BUG_ON(ret < 0); > + if (ret < 0) { > + btrfs_abort_transaction(trans, ret); > + goto enospc; > + } > btrfs_set_node_key(parent, &right_key, pslot + 1); > btrfs_mark_buffer_dirty(parent); > } > @@ -1188,7 +1196,10 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, > btrfs_node_key(mid, &mid_key, 0); > ret = btrfs_tree_mod_log_insert_key(parent, pslot, > BTRFS_MOD_LOG_KEY_REPLACE); > - BUG_ON(ret < 0); > + if (ret < 0) { > + btrfs_abort_transaction(trans, ret); > + goto enospc; > + } > btrfs_set_node_key(parent, &mid_key, pslot); > btrfs_mark_buffer_dirty(parent); > }
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index d6c29564ce49..d60b28c6bd1b 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -1054,7 +1054,12 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, } ret = btrfs_tree_mod_log_insert_root(root->node, child, true); - BUG_ON(ret < 0); + if (ret < 0) { + btrfs_tree_unlock(child); + free_extent_buffer(child); + btrfs_abort_transaction(trans, ret); + goto enospc; + } rcu_assign_pointer(root->node, child); add_root_to_dirty_list(root); @@ -1142,7 +1147,10 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, btrfs_node_key(right, &right_key, 0); ret = btrfs_tree_mod_log_insert_key(parent, pslot + 1, BTRFS_MOD_LOG_KEY_REPLACE); - BUG_ON(ret < 0); + if (ret < 0) { + btrfs_abort_transaction(trans, ret); + goto enospc; + } btrfs_set_node_key(parent, &right_key, pslot + 1); btrfs_mark_buffer_dirty(parent); } @@ -1188,7 +1196,10 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, btrfs_node_key(mid, &mid_key, 0); ret = btrfs_tree_mod_log_insert_key(parent, pslot, BTRFS_MOD_LOG_KEY_REPLACE); - BUG_ON(ret < 0); + if (ret < 0) { + btrfs_abort_transaction(trans, ret); + goto enospc; + } btrfs_set_node_key(parent, &mid_key, pslot); btrfs_mark_buffer_dirty(parent); }