diff mbox series

[v2] btrfs: fix COW handling in run_delalloc_nocow function

Message ID 20250415063342.3033071-1-davechen@synology.com (mailing list archive)
State New
Headers show
Series [v2] btrfs: fix COW handling in run_delalloc_nocow function | expand

Commit Message

davechen April 15, 2025, 6:33 a.m. UTC
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.

Signed-off-by: Dave Chen <davechen@synology.com>
---
 fs/btrfs/inode.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

Comments

Filipe Manana April 15, 2025, 7:49 a.m. UTC | #1
On Tue, Apr 15, 2025 at 7:34 AM davechen <davechen@synology.com> wrote:
>
> 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.
>
> Signed-off-by: Dave Chen <davechen@synology.com>
> ---

In the future, don't forget to add here, after the "---", a
description of what changed in this version of the patch compared to
the previous one (look for examples in the mailing list).


>  fs/btrfs/inode.c | 9 +++++----
>  1 file changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index 5b842276573e..394d5113b6cb 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -2155,12 +2155,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

I'll add punctuation to the end of the sentence to make it comply with
the preferred coding style.

Reviewed-by: Filipe Manana <fdmanana@suse.com>

Patch looks good to me now, I'll add it to for-next, thanks.

>                  */
>                 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;
>                 }
>
>                 /*
> --
> 2.43.0
>
>
diff mbox series

Patch

diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 5b842276573e..394d5113b6cb 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2155,12 +2155,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;
 		}
 
 		/*