From: Josef Bacik <josef@toxicpanda.com>
To: fdmanana@kernel.org
Cc: linux-btrfs@vger.kernel.org
Subject: Re: [PATCH v2] btrfs: send: fix invalid clone operation for file that got its size decreased
Date: Mon, 30 Sep 2024 14:11:05 -0400 [thread overview]
Message-ID: <20240930181105.GD667556@perftesting> (raw)
In-Reply-To: <794af660cbd6c6fc417a683bfc914bbf9fb34ab0.1727434488.git.fdmanana@suse.com>
On Fri, Sep 27, 2024 at 12:03:55PM +0100, fdmanana@kernel.org wrote:
> From: Filipe Manana <fdmanana@suse.com>
>
> During an incremental send we may end up sending an invalid clone
> operation, for the last extent of a file which ends at an unaligned offset
> that matches the final i_size of the file in the send snapshot, in case
> the file had its initial size (the size in the parent snapshot) decreased
> in the send snapshot. In this case the destination will fail to apply the
> clone operation because its end offset is not sector size aligned and it
> ends before the current size of the file.
>
> Sending the truncate operation always happens when we finish processing an
> inode, after we process all its extents (and xattrs, names, etc). So fix
> this by ensuring the file has a valid size before we send a clone
> operation for an unaligned extent that ends at the final i_size of the
> file. The size we truncate to matches the start offset of the clone range
> but it could be any value between that start offset and the final size of
> the file since the clone operation will expand the i_size if the current
> size is smaller than the end offset. The start offset of the range was
> chosen because it's always sector size aligned and avoids a truncation
> into the middle of a page, which results in dirtying the page due to
> filling part of it with zeroes and then making the clone operation at the
> receiver trigger IO.
>
> The following test reproduces the issue:
>
> $ cat test.sh
> #!/bin/bash
>
> DEV=/dev/sdi
> MNT=/mnt/sdi
>
> mkfs.btrfs -f $DEV
> mount $DEV $MNT
>
> # Create a file with a size of 256K + 5 bytes, having two extents, one
> # with a size of 128K and another one with a size of 128K + 5 bytes.
> last_ext_size=$((128 * 1024 + 5))
> xfs_io -f -d -c "pwrite -S 0xab -b 128K 0 128K" \
> -c "pwrite -S 0xcd -b $last_ext_size 128K $last_ext_size" \
> $MNT/foo
>
> # Another file which we will later clone foo into, but initially with
> # a larger size than foo.
> xfs_io -f -c "pwrite -S 0xef 0 1M" $MNT/bar
>
> btrfs subvolume snapshot -r $MNT/ $MNT/snap1
>
> # Now resize bar and clone foo into it.
> xfs_io -c "truncate 0" \
> -c "reflink $MNT/foo" $MNT/bar
>
> btrfs subvolume snapshot -r $MNT/ $MNT/snap2
>
> rm -f /tmp/send-full /tmp/send-inc
> btrfs send -f /tmp/send-full $MNT/snap1
> btrfs send -p $MNT/snap1 -f /tmp/send-inc $MNT/snap2
>
> umount $MNT
> mkfs.btrfs -f $DEV
> mount $DEV $MNT
>
> btrfs receive -f /tmp/send-full $MNT
> btrfs receive -f /tmp/send-inc $MNT
>
> umount $MNT
>
> Running it before this patch:
>
> $ ./test.sh
> (...)
> At subvol snap1
> At snapshot snap2
> ERROR: failed to clone extents to bar: Invalid argument
>
> A test case for fstests will be sent soon.
>
> Reported-by: Ben Millwood <thebenmachine@gmail.com>
> Link: https://lore.kernel.org/linux-btrfs/CAJhrHS2z+WViO2h=ojYvBPDLsATwLbg+7JaNCyYomv0fUxEpQQ@mail.gmail.com/
> Fixes: 46a6e10a1ab1 ("btrfs: send: allow cloning non-aligned extent if it ends at i_size")
> Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Thanks,
Josef
next prev parent reply other threads:[~2024-09-30 18:11 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-09-27 10:25 [PATCH] btrfs: send: fix invalid clone operation for file that got its size decreased fdmanana
2024-09-27 10:33 ` Qu Wenruo
2024-09-27 10:36 ` Filipe Manana
2024-09-27 10:38 ` Qu Wenruo
2024-09-27 11:03 ` [PATCH v2] " fdmanana
2024-09-30 18:11 ` Josef Bacik [this message]
2024-09-30 22:17 ` Qu Wenruo
2024-11-13 13:07 ` Markus
2024-11-13 15:01 ` Filipe Manana
2024-11-13 16:50 ` Markus
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240930181105.GD667556@perftesting \
--to=josef@toxicpanda.com \
--cc=fdmanana@kernel.org \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.