2015-05-14 20:27:53 +10:00
|
|
|
#! /bin/bash
|
2018-06-09 11:35:50 +10:00
|
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
|
|
|
# Copyright (C) 2015 SUSE Linux Products GmbH. All Rights Reserved.
|
|
|
|
|
#
|
2015-05-14 20:27:53 +10:00
|
|
|
# FS QA Test No. btrfs/094
|
|
|
|
|
#
|
|
|
|
|
# Test that an incremental send issues valid clone operations for compressed
|
|
|
|
|
# file extents.
|
|
|
|
|
#
|
|
|
|
|
# For some compressed extents, namely those referred by a file extent item with
|
|
|
|
|
# a non-zero data offset, btrfs could issue a clone operation in the send stream
|
|
|
|
|
# with an offset and length pair that were not entirely contained in the source
|
|
|
|
|
# file's range, causing the receiving side to get -EINVAL errors from the clone
|
|
|
|
|
# ioctl when attempting to perform the clone operations.
|
|
|
|
|
#
|
|
|
|
|
# This issue was fixed by the following linux kernel btrfs patch:
|
|
|
|
|
#
|
|
|
|
|
# Btrfs: incremental send, fix clone operations for compressed extents
|
|
|
|
|
#
|
|
|
|
|
seq=`basename $0`
|
|
|
|
|
seqres=$RESULT_DIR/$seq
|
|
|
|
|
echo "QA output created by $seq"
|
|
|
|
|
|
|
|
|
|
tmp=/tmp/$$
|
|
|
|
|
status=1 # failure is the default!
|
|
|
|
|
trap "_cleanup; exit \$status" 0 1 2 3 15
|
|
|
|
|
|
|
|
|
|
_cleanup()
|
|
|
|
|
{
|
|
|
|
|
rm -fr $send_files_dir
|
|
|
|
|
rm -f $tmp.*
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# get standard environment, filters and checks
|
|
|
|
|
. ./common/rc
|
|
|
|
|
. ./common/filter
|
|
|
|
|
|
|
|
|
|
# real QA test starts here
|
|
|
|
|
_supported_fs btrfs
|
|
|
|
|
_supported_os Linux
|
|
|
|
|
_require_scratch
|
|
|
|
|
_require_cloner
|
|
|
|
|
|
|
|
|
|
send_files_dir=$TEST_DIR/btrfs-test-$seq
|
|
|
|
|
|
|
|
|
|
rm -f $seqres.full
|
|
|
|
|
rm -fr $send_files_dir
|
|
|
|
|
mkdir $send_files_dir
|
|
|
|
|
|
|
|
|
|
_scratch_mkfs >>$seqres.full 2>&1
|
|
|
|
|
_scratch_mount "-o compress"
|
|
|
|
|
|
2017-01-04 17:04:48 -08:00
|
|
|
BLOCK_SIZE=$(_get_block_size $SCRATCH_MNT)
|
2015-05-14 20:27:53 +10:00
|
|
|
|
2015-12-21 18:01:46 +11:00
|
|
|
# Create the file with a single extent of 32 blocks. This creates a metadata
|
|
|
|
|
# file extent item with a data start offset of 0 and a logical length of
|
|
|
|
|
# 32 blocks.
|
|
|
|
|
$XFS_IO_PROG -f -c "pwrite -S 0xaa $((16 * $BLOCK_SIZE)) $((32 * $BLOCK_SIZE))" \
|
|
|
|
|
-c "fsync" $SCRATCH_MNT/foo | _filter_xfs_io_blocks_modified
|
2015-05-14 20:27:53 +10:00
|
|
|
|
2015-12-21 18:01:46 +11:00
|
|
|
# Now rewrite the block range [16, 28[ of our file. This will make
|
|
|
|
|
# the inode's metadata continue to point to the single 32 block extent
|
|
|
|
|
# we created before, but now with an extent item that points to the
|
|
|
|
|
# extent with a data start offset referring to the 28th block and a
|
|
|
|
|
# logical length of 4 blocks.
|
|
|
|
|
# That metadata file extent item is associated with the block range
|
|
|
|
|
# [44, 48[.
|
|
|
|
|
$XFS_IO_PROG -c "pwrite -S 0xbb $((16 * $BLOCK_SIZE)) $((28 * $BLOCK_SIZE))" \
|
|
|
|
|
-c "fsync" $SCRATCH_MNT/foo | _filter_xfs_io_blocks_modified
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Now rewrite the block range [45, 48[. This will make the inode's
|
|
|
|
|
# metadata continue to point the 32 block extent we created earlier,
|
|
|
|
|
# with a single extent item that points to it with a start offset
|
|
|
|
|
# referring to the 28th block and a logical length of 1 block.
|
|
|
|
|
# That metadata file extent item is associated with the block range
|
|
|
|
|
# [44, 45[.
|
|
|
|
|
$XFS_IO_PROG -c "pwrite -S 0xcc $((45 * $BLOCK_SIZE)) $((3 * $BLOCK_SIZE))" \
|
|
|
|
|
-c "fsync" $SCRATCH_MNT/foo | _filter_xfs_io_blocks_modified
|
2015-05-14 20:27:53 +10:00
|
|
|
|
|
|
|
|
_run_btrfs_util_prog subvolume snapshot -r $SCRATCH_MNT $SCRATCH_MNT/mysnap1
|
|
|
|
|
|
2015-12-21 18:01:46 +11:00
|
|
|
# Now clone that same region of the 32 block extent into a new file, so that it
|
2015-05-14 20:27:53 +10:00
|
|
|
# gets referenced twice and the incremental send operation below decides to
|
|
|
|
|
# issue a clone operation instead of copying the data.
|
|
|
|
|
touch $SCRATCH_MNT/bar
|
2015-12-21 18:01:46 +11:00
|
|
|
$CLONER_PROG -s $((44 * $BLOCK_SIZE)) -d $((44 * $BLOCK_SIZE)) -l $BLOCK_SIZE \
|
2015-05-14 20:27:53 +10:00
|
|
|
$SCRATCH_MNT/foo $SCRATCH_MNT/bar
|
|
|
|
|
|
|
|
|
|
_run_btrfs_util_prog subvolume snapshot -r $SCRATCH_MNT $SCRATCH_MNT/mysnap2
|
|
|
|
|
|
2017-03-30 17:20:18 +02:00
|
|
|
_run_btrfs_util_prog send -f $send_files_dir/1.snap $SCRATCH_MNT/mysnap1
|
|
|
|
|
_run_btrfs_util_prog send -p $SCRATCH_MNT/mysnap1 -f $send_files_dir/2.snap \
|
|
|
|
|
$SCRATCH_MNT/mysnap2
|
2015-05-14 20:27:53 +10:00
|
|
|
|
2015-12-21 18:01:46 +11:00
|
|
|
echo "File contents in the original filesystem:"
|
|
|
|
|
echo "mysnap1/foo"
|
|
|
|
|
od -t x1 $SCRATCH_MNT/mysnap1/foo | _filter_od
|
|
|
|
|
echo "mysnap2/foo"
|
|
|
|
|
od -t x1 $SCRATCH_MNT/mysnap2/foo | _filter_od
|
|
|
|
|
echo "mysnap2/bar"
|
|
|
|
|
od -t x1 $SCRATCH_MNT/mysnap2/bar | _filter_od
|
2015-05-14 20:27:53 +10:00
|
|
|
|
|
|
|
|
# Now recreate the filesystem by receiving both send streams and verify we get
|
|
|
|
|
# the same file contents that the original filesystem had.
|
|
|
|
|
_scratch_unmount
|
|
|
|
|
_scratch_mkfs >>$seqres.full 2>&1
|
|
|
|
|
_scratch_mount
|
|
|
|
|
|
2017-03-30 17:20:18 +02:00
|
|
|
_run_btrfs_util_prog receive -f $send_files_dir/1.snap $SCRATCH_MNT
|
|
|
|
|
_run_btrfs_util_prog receive -f $send_files_dir/2.snap $SCRATCH_MNT
|
2015-05-14 20:27:53 +10:00
|
|
|
|
2015-12-21 18:01:46 +11:00
|
|
|
echo "File contents in the new filesystem:"
|
|
|
|
|
echo "mysnap1/foo"
|
|
|
|
|
od -t x1 $SCRATCH_MNT/mysnap1/foo | _filter_od
|
|
|
|
|
echo "mysnap2/foo"
|
|
|
|
|
od -t x1 $SCRATCH_MNT/mysnap2/foo | _filter_od
|
|
|
|
|
echo "mysnap2/bar"
|
|
|
|
|
od -t x1 $SCRATCH_MNT/mysnap2/bar | _filter_od
|
2015-05-14 20:27:53 +10:00
|
|
|
|
|
|
|
|
status=0
|
|
|
|
|
exit
|