Message ID | 8cb7f172ba4c37685955b891ba91f57aa3daea76.1686164800.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> > > When COWing an extent buffer that is not the root node, we need to log in > the tree mod log that we replaced a pointer in the parent node, otherwise > a tree mod log user doing a search on the b+tree can return incorrect > results (that miss something). We are doing the call to > btrfs_tree_mod_log_insert_key() but we totally ignore its return value. > > So fix this by adding the missing error handling, resulting in a > transaction abort and freeing the COWed extent buffer. > > Fixes: f230475e62f7 ("Btrfs: put all block modifications into the tree mod log") > Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: Qu Wenruo <wqu@suse.com> Thanks, Qu > --- > fs/btrfs/ctree.c | 10 ++++++++-- > 1 file changed, 8 insertions(+), 2 deletions(-) > > diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c > index 385524224037..7f7f13965fe9 100644 > --- a/fs/btrfs/ctree.c > +++ b/fs/btrfs/ctree.c > @@ -595,8 +595,14 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, > add_root_to_dirty_list(root); > } else { > WARN_ON(trans->transid != btrfs_header_generation(parent)); > - btrfs_tree_mod_log_insert_key(parent, parent_slot, > - BTRFS_MOD_LOG_KEY_REPLACE); > + ret = btrfs_tree_mod_log_insert_key(parent, parent_slot, > + BTRFS_MOD_LOG_KEY_REPLACE); > + if (ret) { > + btrfs_tree_unlock(cow); > + free_extent_buffer(cow); > + btrfs_abort_transaction(trans, ret); > + return ret; > + } > btrfs_set_node_blockptr(parent, parent_slot, > cow->start); > btrfs_set_node_ptr_generation(parent, parent_slot,
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 385524224037..7f7f13965fe9 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -595,8 +595,14 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, add_root_to_dirty_list(root); } else { WARN_ON(trans->transid != btrfs_header_generation(parent)); - btrfs_tree_mod_log_insert_key(parent, parent_slot, - BTRFS_MOD_LOG_KEY_REPLACE); + ret = btrfs_tree_mod_log_insert_key(parent, parent_slot, + BTRFS_MOD_LOG_KEY_REPLACE); + if (ret) { + btrfs_tree_unlock(cow); + free_extent_buffer(cow); + btrfs_abort_transaction(trans, ret); + return ret; + } btrfs_set_node_blockptr(parent, parent_slot, cow->start); btrfs_set_node_ptr_generation(parent, parent_slot,