summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2026-02-18 18:07:09 +0300
committerDavid Sterba <dsterba@suse.com>2026-04-07 19:55:58 +0300
commit1fce8eec9f89e3aaa13ced7c7ca625ab427b1bcc (patch)
tree222ca7089207e54bbc63d0c9e45cbd72ace13603
parent13816fd5aa3ca2842be5dba1dcff3b86b174c9c0 (diff)
downloadlinux-1fce8eec9f89e3aaa13ced7c7ca625ab427b1bcc.tar.xz
btrfs: avoid unnecessary root node COW during snapshotting
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>
-rw-r--r--fs/btrfs/transaction.c20
1 files changed, 5 insertions, 15 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index ca780e332a5b..36d0f05b06e0 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -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;