generic: test MADV_POPULATE_READ with IO errors
[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 . ./common/preamble
14 _begin_fstest auto quick clone
15
16 # Import common functions.
17 . ./common/filter
18 . ./common/reflink
19
20 # real QA test starts here
21 _supported_fs generic
22 _require_scratch_reflink
23 _require_cp_reflink
24
25 echo "Format and mount"
26 _scratch_mkfs > $seqres.full 2>&1
27 _scratch_mount >> $seqres.full 2>&1
28
29 blksz=65536
30 nr=2
31 filesize=$((blksz * nr))
32 testdir=$SCRATCH_MNT/test-$seq
33 dummy_file=$testdir/dummy
34 low_file=$testdir/low
35 high_file=$testdir/high
36 scenario=1
37 mkdir $testdir
38
39 # Return inode number
40 inum() {
41         stat -c '%i' $1
42 }
43
44 # Create two test files, make $low_file the file with the lower inode
45 # number, and make $high_file the file with the higher inode number.
46 create_files() {
47         touch $testdir/file1
48         touch $testdir/file2
49
50         if [ "$(inum $testdir/file1)" -lt "$(inum $testdir/file2)" ]; then
51                 mv $testdir/file1 $low_file
52                 mv $testdir/file2 $high_file
53         else
54                 mv $testdir/file2 $low_file
55                 mv $testdir/file1 $high_file
56         fi
57
58         _pwrite_byte 0x60 0 $filesize $low_file >> $seqres.full
59         _pwrite_byte 0x61 0 $filesize $high_file >> $seqres.full
60 }
61
62 # Check md5sum of both files, but keep results sorted by inode order
63 check_files() {
64         md5sum $low_file | _filter_scratch
65         md5sum $high_file | _filter_scratch
66 }
67
68 # Test reflinking data from the first file to the second file
69 test_files() {
70         local src="$1"
71         local dest="$2"
72         local off=$((filesize / 2))
73         local sz=$((filesize / 2))
74
75         check_files
76         _reflink_range $src $off $dest $off $sz >> $seqres.full
77         _scratch_cycle_mount
78         check_files
79 }
80
81 # Make a file shared with a dummy file
82 dummy_share() {
83         local which="$2"
84         test -z "$which" && which=1
85         local dummy=$dummy_file.$which
86
87         rm -f $dummy
88         _cp_reflink $1 $dummy
89 }
90
91 # Make two files share (different ranges) with a dummy file
92 mutual_dummy_share() {
93         rm -f $dummy_file
94         _cp_reflink $1 $dummy_file
95         _reflink_range $2 0 $dummy_file $blksz $blksz >> $seqres.full
96 }
97
98 # Announce ourselves, remembering which scenario we've tried
99 ann() {
100         echo "$scenario: $@" | tee -a $seqres.full
101         scenario=$((scenario + 1))
102 }
103
104 # Scenario 1: low to high, neither file shares
105 ann "low to high, neither share"
106 create_files
107 test_files $low_file $high_file
108
109 # Scenario 2: high to low, neither file shares
110 ann "high to low, neither share"
111 create_files
112 test_files $high_file $low_file
113
114 # Scenario 3: low to high, only source file shares
115 ann "low to high, only source shares"
116 create_files
117 dummy_share $low_file
118 test_files $low_file $high_file
119
120 # Scenario 4: high to low, only source file shares
121 ann "high to low, only source shares"
122 create_files
123 dummy_share $high_file
124 test_files $high_file $low_file
125
126 # Scenario 5: low to high, only dest file shares
127 ann "low to high, only dest shares"
128 create_files
129 dummy_share $high_file
130 test_files $low_file $high_file
131
132 # Scenario 6: high to low, only dest file shares
133 ann "high to low, only dest shares"
134 create_files
135 dummy_share $low_file
136 test_files $high_file $low_file
137
138 # Scenario 7: low to high, both files share with each other
139 ann "low to high, both files share with each other"
140 create_files
141 _reflink_range $low_file 0 $high_file 0 $blksz >> $seqres.full
142 test_files $low_file $high_file
143
144 # Scenario 8: high to low, both files share with each other
145 ann "high to low, both files share with each other"
146 create_files
147 _reflink_range $low_file 0 $high_file 0 $blksz >> $seqres.full
148 test_files $high_file $low_file
149
150 # Scenario 9: low to high, both files share but not with each other
151 ann "low to high, both files share but not with each other"
152 create_files
153 # ocfs2 can only reflink between files sharing a refcount tree, so for
154 # this test (and #10) we skip the dummy file because we'd rather not split
155 # the test code just to mask off the /one/ weird fs like this...
156 if _supports_arbitrary_fileset_reflink; then
157         dummy_share $low_file 1
158         dummy_share $high_file 2
159 fi
160 test_files $low_file $high_file
161
162 # Scenario 10: high to low, both files share but not with each other
163 ann "high to low, both files share but not with each other"
164 create_files
165 if _supports_arbitrary_fileset_reflink; then
166         dummy_share $low_file 1
167         dummy_share $high_file 2
168 fi
169 test_files $high_file $low_file
170
171 # Scenario 11: low to high, both files share mutually
172 ann "low to high, both files share mutually"
173 create_files
174 mutual_dummy_share $low_file $high_file
175 test_files $low_file $high_file
176
177 # Scenario 12: high to low, both files share mutually
178 ann "high to low, both files share mutually"
179 create_files
180 mutual_dummy_share $low_file $high_file
181 test_files $high_file $low_file
182
183 # success, all done
184 status=0
185 exit