xfs: force file creation to the data device for certain layout tests
[xfstests-dev.git] / tests / generic / 544
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0+
3 # Copyright (c) 2019, Oracle and/or its affiliates.  All Rights Reserved.
4 #
5 # FS QA Test No. 544
6 #
7 # Ensure that we can reflink from a file with a higher inode number to a lower
8 # inode number and vice versa.  Mix it up by doing this test with inodes that
9 # already share blocks and inodes that don't share blocks.  This tests both
10 # double-inode locking order correctness as well as stressing things like ocfs2
11 # which have per-inode sharing groups and therefore have to check that we don't
12 # try to link data between disjoint sharing groups.
13 seq=`basename $0`
14 seqres=$RESULT_DIR/$seq
15 echo "QA output created by $seq"
16
17 here=`pwd`
18 tmp=/tmp/$$
19 status=1    # failure is the default!
20 trap "_cleanup; exit \$status" 0 1 2 3 15
21
22 _cleanup()
23 {
24         cd /
25         rm -rf $tmp.*
26 }
27
28 # get standard environment, filters and checks
29 . ./common/rc
30 . ./common/filter
31 . ./common/reflink
32
33 # real QA test starts here
34 _supported_fs generic
35 _require_scratch_reflink
36 _require_cp_reflink
37
38 rm -f $seqres.full
39
40 echo "Format and mount"
41 _scratch_mkfs > $seqres.full 2>&1
42 _scratch_mount >> $seqres.full 2>&1
43
44 blksz=65536
45 nr=2
46 filesize=$((blksz * nr))
47 testdir=$SCRATCH_MNT/test-$seq
48 dummy_file=$testdir/dummy
49 low_file=$testdir/low
50 high_file=$testdir/high
51 scenario=1
52 mkdir $testdir
53
54 # Return inode number
55 inum() {
56         stat -c '%i' $1
57 }
58
59 # Create two test files, make $low_file the file with the lower inode
60 # number, and make $high_file the file with the higher inode number.
61 create_files() {
62         _pwrite_byte 0x60 0 $filesize $testdir/file1 >> $seqres.full
63         _pwrite_byte 0x61 0 $filesize $testdir/file2 >> $seqres.full
64         if [ "$(inum $testdir/file1)" -lt "$(inum $testdir/file2)" ]; then
65                 mv $testdir/file1 $low_file
66                 mv $testdir/file2 $high_file
67         else
68                 mv $testdir/file2 $low_file
69                 mv $testdir/file1 $high_file
70         fi
71 }
72
73 # Check md5sum of both files, but keep results sorted by inode order
74 check_files() {
75         md5sum $low_file | _filter_scratch
76         md5sum $high_file | _filter_scratch
77 }
78
79 # Test reflinking data from the first file to the second file
80 test_files() {
81         local src="$1"
82         local dest="$2"
83         local off=$((filesize / 2))
84         local sz=$((filesize / 2))
85
86         check_files
87         _reflink_range $src $off $dest $off $sz >> $seqres.full
88         _scratch_cycle_mount
89         check_files
90 }
91
92 # Make a file shared with a dummy file
93 dummy_share() {
94         local which="$2"
95         test -z "$which" && which=1
96         local dummy=$dummy_file.$which
97
98         rm -f $dummy
99         _cp_reflink $1 $dummy
100 }
101
102 # Make two files share (different ranges) with a dummy file
103 mutual_dummy_share() {
104         rm -f $dummy_file
105         _cp_reflink $1 $dummy_file
106         _reflink_range $2 0 $dummy_file $blksz $blksz >> $seqres.full
107 }
108
109 # Announce ourselves, remembering which scenario we've tried
110 ann() {
111         echo "$scenario: $@" | tee -a $seqres.full
112         scenario=$((scenario + 1))
113 }
114
115 # Scenario 1: low to high, neither file shares
116 ann "low to high, neither share"
117 create_files
118 test_files $low_file $high_file
119
120 # Scenario 2: high to low, neither file shares
121 ann "high to low, neither share"
122 create_files
123 test_files $high_file $low_file
124
125 # Scenario 3: low to high, only source file shares
126 ann "low to high, only source shares"
127 create_files
128 dummy_share $low_file
129 test_files $low_file $high_file
130
131 # Scenario 4: high to low, only source file shares
132 ann "high to low, only source shares"
133 create_files
134 dummy_share $high_file
135 test_files $high_file $low_file
136
137 # Scenario 5: low to high, only dest file shares
138 ann "low to high, only dest shares"
139 create_files
140 dummy_share $high_file
141 test_files $low_file $high_file
142
143 # Scenario 6: high to low, only dest file shares
144 ann "high to low, only dest shares"
145 create_files
146 dummy_share $low_file
147 test_files $high_file $low_file
148
149 # Scenario 7: low to high, both files share with each other
150 ann "low to high, both files share with each other"
151 create_files
152 _reflink_range $low_file 0 $high_file 0 $blksz >> $seqres.full
153 test_files $low_file $high_file
154
155 # Scenario 8: high to low, both files share with each other
156 ann "high to low, both files share with each other"
157 create_files
158 _reflink_range $low_file 0 $high_file 0 $blksz >> $seqres.full
159 test_files $high_file $low_file
160
161 # Scenario 9: low to high, both files share but not with each other
162 ann "low to high, both files share but not with each other"
163 create_files
164 # ocfs2 can only reflink between files sharing a refcount tree, so for
165 # this test (and #10) we skip the dummy file because we'd rather not split
166 # the test code just to mask off the /one/ weird fs like this...
167 if _supports_arbitrary_fileset_reflink; then
168         dummy_share $low_file 1
169         dummy_share $high_file 2
170 fi
171 test_files $low_file $high_file
172
173 # Scenario 10: high to low, both files share but not with each other
174 ann "high to low, both files share but not with each other"
175 create_files
176 if _supports_arbitrary_fileset_reflink; then
177         dummy_share $low_file 1
178         dummy_share $high_file 2
179 fi
180 test_files $high_file $low_file
181
182 # Scenario 11: low to high, both files share mutually
183 ann "low to high, both files share mutually"
184 create_files
185 mutual_dummy_share $low_file $high_file
186 test_files $low_file $high_file
187
188 # Scenario 12: high to low, both files share mutually
189 ann "high to low, both files share mutually"
190 create_files
191 mutual_dummy_share $low_file $high_file
192 test_files $high_file $low_file
193
194 # success, all done
195 status=0
196 exit