From: Dave Chen Date: Mon, 30 Mar 2026 03:31:48 +0000 (+0800) Subject: btrfs: skip clearing EXTENT_DEFRAG for NOCOW ordered extents X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e0dfaebb8f4a1de59a8b805d600e3b662b235efc;p=thirdparty%2Fkernel%2Flinux.git btrfs: skip clearing EXTENT_DEFRAG for NOCOW ordered extents 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 Signed-off-by: Robbie Ko Reviewed-by: Filipe Manana Signed-off-by: Filipe Manana Signed-off-by: David Sterba --- diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 808e52aa6ef29..40474014c03f1 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -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);