]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
btrfs: skip clearing EXTENT_DEFRAG for NOCOW ordered extents
authorDave Chen <davechen@synology.com>
Mon, 30 Mar 2026 03:31:48 +0000 (11:31 +0800)
committerDavid Sterba <dsterba@suse.com>
Tue, 7 Apr 2026 17:43:22 +0000 (19:43 +0200)
In btrfs_finish_one_ordered(), clear_bits is unconditionally initialized
with EXTENT_DEFRAG.  For NOCOW ordered extents this is always a no-op
because should_nocow() already forces the COW path when EXTENT_DEFRAG is
set, so a NOCOW ordered extent can never have EXTENT_DEFRAG on its range.

Although harmless, the unconditional btrfs_clear_extent_bit() call still
performs a cold rbtree lookup under the io tree spinlock on every NOCOW
write completion.  Avoid this by only adding EXTENT_DEFRAG to clear_bits
for non-NOCOW ordered extents, and skip the call entirely when there are
no bits to clear.

Signed-off-by: Dave Chen <davechen@synology.com>
Signed-off-by: Robbie Ko <robbieko@synology.com>
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/inode.c

index 808e52aa6ef290dec0d7f41294446e1cd2c33f3a..40474014c03f1330d80b1cef21b0e752b3258d54 100644 (file)
@@ -3197,7 +3197,7 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
        bool freespace_inode;
        bool truncated = false;
        bool clear_reserved_extent = true;
-       unsigned int clear_bits = EXTENT_DEFRAG;
+       unsigned int clear_bits = 0;
 
        start = ordered_extent->file_offset;
        end = start + ordered_extent->num_bytes - 1;
@@ -3208,6 +3208,9 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
            !test_bit(BTRFS_ORDERED_ENCODED, &ordered_extent->flags))
                clear_bits |= EXTENT_DELALLOC_NEW;
 
+       if (!test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags))
+               clear_bits |= EXTENT_DEFRAG;
+
        freespace_inode = btrfs_is_free_space_inode(inode);
        if (!freespace_inode)
                btrfs_lockdep_acquire(fs_info, btrfs_ordered_extent);
@@ -3339,8 +3342,9 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
                goto out;
        }
 out:
-       btrfs_clear_extent_bit(&inode->io_tree, start, end, clear_bits,
-                              &cached_state);
+       if (clear_bits)
+               btrfs_clear_extent_bit(&inode->io_tree, start, end, clear_bits,
+                                      &cached_state);
 
        if (trans)
                btrfs_end_transaction(trans);