On Fri, Sep 27, 2024 at 11:46 AM Qu Wenruo <quwenruo.btrfs@xxxxxxx> wrote: > > > > 在 2024/9/27 19:58, fdmanana@xxxxxxxxxx 写道: > > From: Filipe Manana <fdmanana@xxxxxxxx> > > > > Test that doing an incremental send with a file that had its size > > decreased and became the destination for a clone operation of an extent > > with an unaligned end offset that matches the new file size, works > > correctly. > > > > This tests a bug fixed by the following kernel patch: > > > > "btrfs: send: fix invalid clone operation for file that got its size decreased" > > > > Signed-off-by: Filipe Manana <fdmanana@xxxxxxxx> > > Reviewed-by: Qu Wenruo <wqu@xxxxxxxx> > > Just a small nitpick. > > [...] > > +. ./common/filter > > +. ./common/reflink > > +. ./common/punch # for _filter_fiemap_flags > > + > > +_require_test > > Initially I thought test is not necessary, but later turns out that > we're using TEST_MNT to store the two streams. > > May be we can just reuse $tmp.*? Why? The test device is always present, or are there any setups where there's none? We use this pattern to store in the test mount because such files could be big (not in this case however) and /tmp is usually much smaller. That's the recommendation I once got many years ago. > > Thanks, > Qu > > > +_require_scratch_reflink > > +_require_xfs_io_command "fiemap" > > +_require_odirect > > + > > +_fixed_by_kernel_commit xxxxxxxxxxxx \ > > + "btrfs: send: fix invalid clone operation for file that got its size decreased" > > + > > +check_all_extents_shared() > > +{ > > + local file=$1 > > + local fiemap_output > > + > > + fiemap_output=$($XFS_IO_PROG -r -c "fiemap -v" $file | _filter_fiemap_flags) > > + echo "$fiemap_output" | grep -qv 'shared' > > + if [ $? -eq 0 ]; then > > + echo -e "Found non-shared extents for file $file:\n" > > + echo "$fiemap_output" > > + fi > > +} > > + > > +send_files_dir=$TEST_DIR/btrfs-test-$seq > > +full_send_stream=$send_files_dir/full_snap.stream > > +inc_send_stream=$send_files_dir/inc_snap.stream > > + > > +rm -fr $send_files_dir > > +mkdir $send_files_dir > > + > > +_scratch_mkfs >> $seqres.full 2>&1 || _fail "first mkfs failed" > > +_scratch_mount > > + > > +# Create a file with a size of 256K + 5 bytes, having two extents, the first one > > +# with a size of 128K and the second one with a size of 128K + 5 bytes. > > +last_extent_size=$((128 * 1024 + 5)) > > +$XFS_IO_PROG -f -d -c "pwrite -S 0xab -b 128K 0 128K" \ > > + -c "pwrite -S 0xcd -b $last_extent_size 128K $last_extent_size" \ > > + $SCRATCH_MNT/foo | _filter_xfs_io > > + > > +# Another file which we will later clone foo into, but initially with > > +# a larger size than foo. > > +$XFS_IO_PROG -f -c "pwrite -b 0xef 0 1M" $SCRATCH_MNT/bar | _filter_xfs_io > > + > > +echo "Creating snapshot and the full send stream for it..." > > +_btrfs subvolume snapshot -r $SCRATCH_MNT $SCRATCH_MNT/snap1 > > +$BTRFS_UTIL_PROG send -f $full_send_stream $SCRATCH_MNT/snap1 >> $seqres.full 2>&1 > > + > > +# Now resize bar and clone foo into it. > > +$XFS_IO_PROG -c "truncate 0" \ > > + -c "reflink $SCRATCH_MNT/foo" $SCRATCH_MNT/bar | _filter_xfs_io > > + > > +echo "Creating another snapshot and the incremental send stream for it..." > > +_btrfs subvolume snapshot -r $SCRATCH_MNT $SCRATCH_MNT/snap2 > > +$BTRFS_UTIL_PROG send -p $SCRATCH_MNT/snap1 -f $inc_send_stream \ > > + $SCRATCH_MNT/snap2 >> $seqres.full 2>&1 > > + > > +echo "File digests in the original filesystem:" > > +md5sum $SCRATCH_MNT/snap1/foo | _filter_scratch > > +md5sum $SCRATCH_MNT/snap1/bar | _filter_scratch > > +md5sum $SCRATCH_MNT/snap2/foo | _filter_scratch > > +md5sum $SCRATCH_MNT/snap2/bar | _filter_scratch > > + > > +check_all_extents_shared "$SCRATCH_MNT/snap2/bar" > > +check_all_extents_shared "$SCRATCH_MNT/snap1/foo" > > + > > +echo "Creating a new filesystem to receive the send streams..." > > +_scratch_unmount > > +_scratch_mkfs >> $seqres.full 2>&1 || _fail "second mkfs failed" > > +_scratch_mount > > + > > +$BTRFS_UTIL_PROG receive -f $full_send_stream $SCRATCH_MNT > > +$BTRFS_UTIL_PROG receive -f $inc_send_stream $SCRATCH_MNT > > + > > +echo "File digests in the new filesystem:" > > +md5sum $SCRATCH_MNT/snap1/foo | _filter_scratch > > +md5sum $SCRATCH_MNT/snap1/bar | _filter_scratch > > +md5sum $SCRATCH_MNT/snap2/foo | _filter_scratch > > +md5sum $SCRATCH_MNT/snap2/bar | _filter_scratch > > + > > +check_all_extents_shared "$SCRATCH_MNT/snap2/bar" > > +check_all_extents_shared "$SCRATCH_MNT/snap1/foo" > > + > > +# success, all done > > +status=0 > > +exit > > diff --git a/tests/btrfs/322.out b/tests/btrfs/322.out > > new file mode 100644 > > index 00000000..31e1ee55 > > --- /dev/null > > +++ b/tests/btrfs/322.out > > @@ -0,0 +1,24 @@ > > +QA output created by 322 > > +wrote 131072/131072 bytes at offset 0 > > +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) > > +wrote 131077/131077 bytes at offset 131072 > > +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) > > +wrote 1048576/1048576 bytes at offset 0 > > +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) > > +Creating snapshot and the full send stream for it... > > +linked 0/0 bytes at offset 0 > > +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) > > +Creating another snapshot and the incremental send stream for it... > > +File digests in the original filesystem: > > +c3bb068b7e21d3f009581f047be84f44 SCRATCH_MNT/snap1/foo > > +ca539970d4b1fa1f34213ba675007381 SCRATCH_MNT/snap1/bar > > +c3bb068b7e21d3f009581f047be84f44 SCRATCH_MNT/snap2/foo > > +c3bb068b7e21d3f009581f047be84f44 SCRATCH_MNT/snap2/bar > > +Creating a new filesystem to receive the send streams... > > +At subvol snap1 > > +At snapshot snap2 > > +File digests in the new filesystem: > > +c3bb068b7e21d3f009581f047be84f44 SCRATCH_MNT/snap1/foo > > +ca539970d4b1fa1f34213ba675007381 SCRATCH_MNT/snap1/bar > > +c3bb068b7e21d3f009581f047be84f44 SCRATCH_MNT/snap2/foo > > +c3bb068b7e21d3f009581f047be84f44 SCRATCH_MNT/snap2/bar >