0744797ecc336282e4f5e364deb6c52b230c4890
[xfstests-dev.git] / tests / btrfs / 187
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (C) 2019 SUSE Linux Products GmbH. All Rights Reserved.
4 #
5 # FSQA Test No. 187
6 #
7 # Stress send running in parallel with balance and deduplication against files
8 # that belong to the snapshots used by send. The goal is to verify that these
9 # operations running in parallel do not lead to send crashing (trigger assertion
10 # failures and BUG_ONs), or send finding an inconsistent snapshot that leads to
11 # a failure (reported in dmesg/syslog). The test needs big trees (snapshots)
12 # with large differences between the parent and send snapshots in order to hit
13 # such issues with a good probability.
14 #
15 seq=`basename $0`
16 seqres=$RESULT_DIR/$seq
17 echo "QA output created by $seq"
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 -f $tmp.*
26 }
27
28 # get standard environment, filters and checks
29 . ./common/rc
30 . ./common/attr
31 . ./common/filter
32 . ./common/reflink
33
34 # real QA test starts here
35 _supported_fs btrfs
36 _supported_os Linux
37 _require_scratch_dedupe
38 _require_attrs
39
40 rm -f $seqres.full
41
42 _scratch_mkfs >>$seqres.full 2>&1
43 _scratch_mount
44
45 dedupe_two_files()
46 {
47         trap "wait; exit" SIGTERM
48
49         local f1=$(find $SCRATCH_MNT/snap1 -type f | shuf -n 1)
50         local f2=$(find $SCRATCH_MNT/snap2 -type f | shuf -n 1)
51
52         if (( RANDOM % 2 )); then
53                 local tmp=$f1
54                 f1=$f2
55                 f2=$tmp
56         fi
57
58         # Ignore errors from dedupe. We just want to test for crashes and
59         # deadlocks.
60         $XFS_IO_PROG -r -c "dedupe $f1 0 0 64K" $f2 &> /dev/null
61 }
62
63 dedupe_files_loop()
64 {
65         trap "wait; exit" SIGTERM
66
67         while true; do
68                 for ((i = 1; i <= 5; i++)); do
69                         dedupe_two_files &
70                 done
71                 wait
72         done
73 }
74
75 balance_loop()
76 {
77         trap "wait; exit" SIGTERM
78
79         while true; do
80                 # Balance only metadata block groups, since this is makes it
81                 # easier to hit problems (crashes and errors) in send.
82                 # Ignore errors from balance. We just want to test for crashes
83                 # and deadlocks.
84                 $BTRFS_UTIL_PROG balance start -f -m $SCRATCH_MNT &> /dev/null
85                 sleep $((RANDOM % 3))
86         done
87 }
88
89 full_send_loop()
90 {
91         trap "wait; exit" SIGTERM
92
93         local count=$1
94
95         for ((i = 1; i <= $count; i++)); do
96                 # Ignore errors from send. We will check for errors later in
97                 # dmesg/syslog.
98                 $BTRFS_UTIL_PROG send -f /dev/null \
99                         $SCRATCH_MNT/snap1 &> /dev/null
100                 sleep $((RANDOM % 3))
101         done
102 }
103
104 inc_send_loop()
105 {
106         trap "wait; exit" SIGTERM
107
108         local count=$1
109
110         for ((i = 1; i <= $count; i++)); do
111                 # Ignore errors from send. We will check for errors later in
112                 # dmesg/syslog.
113                 $BTRFS_UTIL_PROG send -f /dev/null \
114                         -p $SCRATCH_MNT/snap1 $SCRATCH_MNT/snap2 &> /dev/null
115                 sleep $((RANDOM % 3))
116         done
117 }
118
119 write_files_loop()
120 {
121         local count=$1
122         local offset=$2
123
124         for ((i = 1; i <= $count; i++)); do
125                 $XFS_IO_PROG -f -c "pwrite -S 0xea 0 64K" \
126                         $SCRATCH_MNT/file_$((i + offset)) >/dev/null
127         done
128 }
129
130 set_xattrs_loop()
131 {
132         local count=$1
133         local offset=$2
134
135         for ((i = 1; i <= $count; i++)); do
136                 $SETFATTR_PROG -n 'user.x1' -v $xattr_value \
137                         $SCRATCH_MNT/file_$((i + offset))
138         done
139 }
140
141 # Number of files created before first snapshot. Must be divisable by 4.
142 nr_initial_files=40000
143 # Number of files created after the first snapshot. Must be divisable by 4.
144 nr_more_files=40000
145
146 # Create initial files.
147 step=$((nr_initial_files / 4))
148 for ((n = 0; n < 4; n++)); do
149         offset=$((step * $n))
150         write_files_loop $step $offset &
151         create_pids[$n]=$!
152 done
153 wait ${create_pids[@]}
154
155 $BTRFS_UTIL_PROG subvolume snapshot -r $SCRATCH_MNT $SCRATCH_MNT/snap1 \
156         | _filter_scratch
157
158 # Add some more files, so that that are substantial differences between the
159 # two test snapshots used for an incremental send later.
160
161 # Create more files.
162 step=$((nr_more_files / 4))
163 for ((n = 0; n < 4; n++)); do
164         offset=$((nr_initial_files + step * $n))
165         write_files_loop $step $offset &
166         create_pids[$n]=$!
167 done
168 wait ${create_pids[@]}
169
170 # Add some xattrs to all files, so that every leaf and node of the fs tree is
171 # COWed. Adding more files does only adds leafs and nodes to the tree's right
172 # side, since inode numbers are based on a counter and form the first part
173 # (objectid) of btree keys (we only modifying the right most leaf of the tree).
174 # Use large values for the xattrs to quickly increase the height of the tree.
175 xattr_value=$(printf '%0.sX' $(seq 1 3800))
176
177 # Split the work into 4 workers working on consecutive ranges to avoid contention
178 # on the same leafs as much as possible.
179 step=$(((nr_more_files + nr_initial_files) / 4))
180 for ((n = 0; n < 4; n++)); do
181         offset=$((step * $n))
182         set_xattrs_loop $step $offset &
183         setxattr_pids[$n]=$!
184 done
185 wait ${setxattr_pids[@]}
186
187 $BTRFS_UTIL_PROG subvolume snapshot -r $SCRATCH_MNT $SCRATCH_MNT/snap2 \
188         | _filter_scratch
189
190 full_send_loop 5 &
191 full_send_pid=$!
192
193 inc_send_loop 10 &
194 inc_send_pid=$!
195
196 dedupe_files_loop &
197 dedupe_pid=$!
198
199 balance_loop &
200 balance_pid=$!
201
202 wait $full_send_pid
203 wait $inc_send_pid
204
205 kill $dedupe_pid
206 wait $dedupe_pid
207
208 kill $balance_pid
209 wait $balance_pid
210
211 # Check for errors messages that happen due to inconsistent snapshot caused by
212 # deduplication and balance running in parallel with send, causing btree nodes
213 # and leafs to disappear and getting reused while send is using them.
214 #
215 # Example messages:
216 #
217 # BTRFS error (device sdc): did not find backref in send_root. inode=63292, \
218 #     offset=0, disk_byte=5228134400 found extent=5228134400
219 #
220 # BTRFS error (device sdc): parent transid verify failed on 32243712 wanted 24 \
221 #     found 27
222 #
223 _dmesg_since_test_start | egrep -e '\bBTRFS error \(device .*?\):'
224
225 status=0
226 exit