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