mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
830349865e
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>
198 lines
5.2 KiB
Bash
Executable File
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
|