Files
apfstests/tests/generic/544
T
Darrick J. Wong 830349865e clonerange: test remapping the rainbow
Add some more clone range tests that missed various "wacky" combinations
of file state.  Specifically, we test reflinking into and out of rainbow
ranges (a mix of real, unwritten, hole, delalloc, and shared extents),
and also we test that we can correctly handle double-inode locking no
matter what order of inodes or the filesystem's locking rules.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Eryu Guan <guaneryu@gmail.com>
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
2019-04-14 19:21:52 +08:00

198 lines
5.2 KiB
Bash
Executable File

#! /bin/bash
# SPDX-License-Identifier: GPL-2.0+
# Copyright (c) 2019, Oracle and/or its affiliates. All Rights Reserved.
#
# FS QA Test No. 544
#
# Ensure that we can reflink from a file with a higher inode number to a lower
# inode number and vice versa. Mix it up by doing this test with inodes that
# already share blocks and inodes that don't share blocks. This tests both
# double-inode locking order correctness as well as stressing things like ocfs2
# which have per-inode sharing groups and therefore have to check that we don't
# try to link data between disjoint sharing groups.
seq=`basename $0`
seqres=$RESULT_DIR/$seq
echo "QA output created by $seq"
here=`pwd`
tmp=/tmp/$$
status=1 # failure is the default!
trap "_cleanup; exit \$status" 0 1 2 3 15
_cleanup()
{
cd /
rm -rf $tmp.*
}
# get standard environment, filters and checks
. ./common/rc
. ./common/filter
. ./common/reflink
# real QA test starts here
_supported_os Linux
_supported_fs generic
_require_scratch_reflink
_require_cp_reflink
rm -f $seqres.full
echo "Format and mount"
_scratch_mkfs > $seqres.full 2>&1
_scratch_mount >> $seqres.full 2>&1
blksz=65536
nr=2
filesize=$((blksz * nr))
testdir=$SCRATCH_MNT/test-$seq
dummy_file=$testdir/dummy
low_file=$testdir/low
high_file=$testdir/high
scenario=1
mkdir $testdir
# Return inode number
inum() {
stat -c '%i' $1
}
# Create two test files, make $low_file the file with the lower inode
# number, and make $high_file the file with the higher inode number.
create_files() {
_pwrite_byte 0x60 0 $filesize $testdir/file1 >> $seqres.full
_pwrite_byte 0x61 0 $filesize $testdir/file2 >> $seqres.full
if [ "$(inum $testdir/file1)" -lt "$(inum $testdir/file2)" ]; then
mv $testdir/file1 $low_file
mv $testdir/file2 $high_file
else
mv $testdir/file2 $low_file
mv $testdir/file1 $high_file
fi
}
# Check md5sum of both files, but keep results sorted by inode order
check_files() {
md5sum $low_file | _filter_scratch
md5sum $high_file | _filter_scratch
}
# Test reflinking data from the first file to the second file
test_files() {
local src="$1"
local dest="$2"
local off=$((filesize / 2))
local sz=$((filesize / 2))
check_files
_reflink_range $src $off $dest $off $sz >> $seqres.full
_scratch_cycle_mount
check_files
}
# Make a file shared with a dummy file
dummy_share() {
local which="$2"
test -z "$which" && which=1
local dummy=$dummy_file.$which
rm -f $dummy
_cp_reflink $1 $dummy
}
# Make two files share (different ranges) with a dummy file
mutual_dummy_share() {
rm -f $dummy_file
_cp_reflink $1 $dummy_file
_reflink_range $2 0 $dummy_file $blksz $blksz >> $seqres.full
}
# Announce ourselves, remembering which scenario we've tried
ann() {
echo "$scenario: $@" | tee -a $seqres.full
scenario=$((scenario + 1))
}
# Scenario 1: low to high, neither file shares
ann "low to high, neither share"
create_files
test_files $low_file $high_file
# Scenario 2: high to low, neither file shares
ann "high to low, neither share"
create_files
test_files $high_file $low_file
# Scenario 3: low to high, only source file shares
ann "low to high, only source shares"
create_files
dummy_share $low_file
test_files $low_file $high_file
# Scenario 4: high to low, only source file shares
ann "high to low, only source shares"
create_files
dummy_share $high_file
test_files $high_file $low_file
# Scenario 5: low to high, only dest file shares
ann "low to high, only dest shares"
create_files
dummy_share $high_file
test_files $low_file $high_file
# Scenario 6: high to low, only dest file shares
ann "high to low, only dest shares"
create_files
dummy_share $low_file
test_files $high_file $low_file
# Scenario 7: low to high, both files share with each other
ann "low to high, both files share with each other"
create_files
_reflink_range $low_file 0 $high_file 0 $blksz >> $seqres.full
test_files $low_file $high_file
# Scenario 8: high to low, both files share with each other
ann "high to low, both files share with each other"
create_files
_reflink_range $low_file 0 $high_file 0 $blksz >> $seqres.full
test_files $high_file $low_file
# Scenario 9: low to high, both files share but not with each other
ann "low to high, both files share but not with each other"
create_files
# ocfs2 can only reflink between files sharing a refcount tree, so for
# this test (and #10) we skip the dummy file because we'd rather not split
# the test code just to mask off the /one/ weird fs like this...
if _supports_arbitrary_fileset_reflink; then
dummy_share $low_file 1
dummy_share $high_file 2
fi
test_files $low_file $high_file
# Scenario 10: high to low, both files share but not with each other
ann "high to low, both files share but not with each other"
create_files
if _supports_arbitrary_fileset_reflink; then
dummy_share $low_file 1
dummy_share $high_file 2
fi
test_files $high_file $low_file
# Scenario 11: low to high, both files share mutually
ann "low to high, both files share mutually"
create_files
mutual_dummy_share $low_file $high_file
test_files $low_file $high_file
# Scenario 12: high to low, both files share mutually
ann "high to low, both files share mutually"
create_files
mutual_dummy_share $low_file $high_file
test_files $high_file $low_file
# success, all done
status=0
exit