Skip to content

Commit

Permalink
btrfs: fix COW handling in run_delalloc_nocow()
Browse files Browse the repository at this point in the history
In run_delalloc_nocow(), when the found btrfs_key's offset > cur_offset,
it indicates a gap between the current processing region and
the next file extent. The original code would directly jump to
the "must_cow" label, which increments the slot and forces a fallback
to COW. This behavior might skip an extent item and result in an
overestimated COW fallback range.

This patch modifies the logic so that when a gap is detected:

- If no COW range is already being recorded (cow_start is unset),
  cow_start is set to cur_offset.

- cur_offset is then advanced to the beginning of the next extent.

- Instead of jumping to "must_cow", control flows directly to
  "next_slot" so that the same extent item can be reexamined properly.

The change ensures that we accurately account for the extent gap and
avoid accidentally extending the range that needs to fallback to COW.

CC: stable@vger.kernel.org # 6.6+
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Dave Chen <davechen@synology.com>
Signed-off-by: David Sterba <dsterba@suse.com>
  • Loading branch information
Dave Chen authored and David Sterba committed Apr 23, 2025
1 parent 866bafa commit be3f193
Showing 1 changed file with 5 additions and 4 deletions.
9 changes: 5 additions & 4 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2129,12 +2129,13 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode,

/*
* If the found extent starts after requested offset, then
* adjust extent_end to be right before this extent begins
* adjust cur_offset to be right before this extent begins.
*/
if (found_key.offset > cur_offset) {
extent_end = found_key.offset;
extent_type = 0;
goto must_cow;
if (cow_start == (u64)-1)
cow_start = cur_offset;
cur_offset = found_key.offset;
goto next_slot;
}

/*
Expand Down

0 comments on commit be3f193

Please sign in to comment.