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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).