]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
btrfs: avoid unnecessary root node COW during snapshotting
authorFilipe Manana <fdmanana@suse.com>
Wed, 18 Feb 2026 15:07:09 +0000 (15:07 +0000)
committerDavid Sterba <dsterba@suse.com>
Tue, 7 Apr 2026 16:55:58 +0000 (18:55 +0200)
There's no need to COW the root node of the subvolume we are snapshotting
because we then call btrfs_copy_root(), which creates a copy of the root
node and sets its generation to the current transaction. So remove this
redundant COW right before calling btrfs_copy_root(), saving one extent
allocation, memory allocation, copying things, etc, and making the code
less confusing. Also rename the extent buffer variable from "old" to
"root_eb" since that name no longer makes any sense after removing the
unnecessary COW operation.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/transaction.c

index ca780e332a5bfe220a4ff85c581faf422bbac30f..36d0f05b06e025774320ea5e4ed83f9cd4bade8b 100644 (file)
@@ -1669,7 +1669,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        BTRFS_PATH_AUTO_FREE(path);
        struct btrfs_dir_item *dir_item;
        struct extent_buffer *tmp;
-       struct extent_buffer *old;
+       struct extent_buffer *root_eb;
        struct timespec64 cur_time;
        int ret = 0;
        u64 to_reserve = 0;
@@ -1807,20 +1807,10 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        btrfs_set_stack_timespec_nsec(&new_root_item->otime, cur_time.tv_nsec);
        btrfs_set_root_otransid(new_root_item, trans->transid);
 
-       old = btrfs_lock_root_node(root);
-       ret = btrfs_cow_block(trans, root, old, NULL, 0, &old,
-                             BTRFS_NESTING_COW);
-       if (unlikely(ret)) {
-               btrfs_tree_unlock(old);
-               free_extent_buffer(old);
-               btrfs_abort_transaction(trans, ret);
-               goto fail;
-       }
-
-       ret = btrfs_copy_root(trans, root, old, &tmp, objectid);
-       /* clean up in any case */
-       btrfs_tree_unlock(old);
-       free_extent_buffer(old);
+       root_eb = btrfs_lock_root_node(root);
+       ret = btrfs_copy_root(trans, root, root_eb, &tmp, objectid);
+       btrfs_tree_unlock(root_eb);
+       free_extent_buffer(root_eb);
        if (unlikely(ret)) {
                btrfs_abort_transaction(trans, ret);
                goto fail;