fstests: move test group info to test files
[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 . ./common/preamble
16 _begin_fstest auto send dedupe clone balance
17
18 # Import common functions.
19 . ./common/attr
20 . ./common/filter
21 . ./common/reflink
22
23 # real QA test starts here
24 _supported_fs btrfs
25 _require_scratch_dedupe
26 _require_attrs
27
28 # We at least need 8GB of free space on $SCRATCH_DEV
29 _require_scratch_size $((8 * 1024 * 1024))
30
31 _scratch_mkfs >>$seqres.full 2>&1
32 _scratch_mount
33
34 dedupe_two_files()
35 {
36         trap "wait; exit" SIGTERM
37
38         local f1=$(find $SCRATCH_MNT/snap1 -type f | shuf -n 1)
39         local f2=$(find $SCRATCH_MNT/snap2 -type f | shuf -n 1)
40
41         if (( RANDOM % 2 )); then
42                 local tmp=$f1
43                 f1=$f2
44                 f2=$tmp
45         fi
46
47         # Ignore errors from dedupe. We just want to test for crashes and
48         # deadlocks.
49         $XFS_IO_PROG -r -c "dedupe $f1 0 0 64K" $f2 &> /dev/null
50 }
51
52 dedupe_files_loop()
53 {
54         local stop=0
55
56         # Avoid executing 'wait' inside the trap, because when we receive
57         # SIGTERM we might be already executing the wait command in the while
58         # loop below. When that is the case, bash 5.0+ with debug enabled prints
59         # a warning message that makes the test fail due to a mismatch with the
60         # golden output. That warning message is the following:
61         #
62         # warning: wait_for: recursively setting old_sigint_handler to wait_sigint_handler: running_trap = 16
63         #
64         trap "stop=1" SIGTERM
65
66         while [ $stop -eq 0 ]; do
67                 for ((i = 1; i <= 5; i++)); do
68                         dedupe_two_files &
69                 done
70                 wait
71         done
72 }
73
74 balance_loop()
75 {
76         trap "wait; exit" SIGTERM
77
78         while true; do
79                 # Balance only metadata block groups, since this is makes it
80                 # easier to hit problems (crashes and errors) in send.
81                 # Ignore errors from balance. We just want to test for crashes
82                 # and deadlocks.
83                 _run_btrfs_balance_start -f -m $SCRATCH_MNT &> /dev/null
84                 sleep $((RANDOM % 3))
85         done
86 }
87
88 full_send_loop()
89 {
90         trap "wait; exit" SIGTERM
91
92         local count=$1
93
94         for ((i = 1; i <= $count; i++)); do
95                 # Ignore errors from send. We will check for errors later in
96                 # dmesg/syslog.
97                 $BTRFS_UTIL_PROG send -f /dev/null \
98                         $SCRATCH_MNT/snap1 &> /dev/null
99                 sleep $((RANDOM % 3))
100         done
101 }
102
103 inc_send_loop()
104 {
105         trap "wait; exit" SIGTERM
106
107         local count=$1
108
109         for ((i = 1; i <= $count; i++)); do
110                 # Ignore errors from send. We will check for errors later in
111                 # dmesg/syslog.
112                 $BTRFS_UTIL_PROG send -f /dev/null \
113                         -p $SCRATCH_MNT/snap1 $SCRATCH_MNT/snap2 &> /dev/null
114                 sleep $((RANDOM % 3))
115         done
116 }
117
118 write_files_loop()
119 {
120         local count=$1
121         local offset=$2
122
123         for ((i = 1; i <= $count; i++)); do
124                 $XFS_IO_PROG -f -c "pwrite -S 0xea 0 64K" \
125                         $SCRATCH_MNT/file_$((i + offset)) >/dev/null
126         done
127 }
128
129 set_xattrs_loop()
130 {
131         local count=$1
132         local offset=$2
133
134         for ((i = 1; i <= $count; i++)); do
135                 $SETFATTR_PROG -n 'user.x1' -v $xattr_value \
136                         $SCRATCH_MNT/file_$((i + offset))
137         done
138 }
139
140 # Number of files created before first snapshot. Must be divisable by 4.
141 nr_initial_files=40000
142 # Number of files created after the first snapshot. Must be divisable by 4.
143 nr_more_files=40000
144
145 # Create initial files.
146 step=$((nr_initial_files / 4))
147 for ((n = 0; n < 4; n++)); do
148         offset=$((step * $n))
149         write_files_loop $step $offset &
150         create_pids[$n]=$!
151 done
152 wait ${create_pids[@]}
153
154 $BTRFS_UTIL_PROG subvolume snapshot -r $SCRATCH_MNT $SCRATCH_MNT/snap1 \
155         | _filter_scratch
156
157 # Add some more files, so that that are substantial differences between the
158 # two test snapshots used for an incremental send later.
159
160 # Create more files.
161 step=$((nr_more_files / 4))
162 for ((n = 0; n < 4; n++)); do
163         offset=$((nr_initial_files + step * $n))
164         write_files_loop $step $offset &
165         create_pids[$n]=$!
166 done
167 wait ${create_pids[@]}
168
169 # Add some xattrs to all files, so that every leaf and node of the fs tree is
170 # COWed. Adding more files does only adds leafs and nodes to the tree's right
171 # side, since inode numbers are based on a counter and form the first part
172 # (objectid) of btree keys (we only modifying the right most leaf of the tree).
173 # Use large values for the xattrs to quickly increase the height of the tree.
174 xattr_value=$(printf '%0.sX' $(seq 1 3800))
175
176 # Split the work into 4 workers working on consecutive ranges to avoid contention
177 # on the same leafs as much as possible.
178 step=$(((nr_more_files + nr_initial_files) / 4))
179 for ((n = 0; n < 4; n++)); do
180         offset=$((step * $n))
181         set_xattrs_loop $step $offset &
182         setxattr_pids[$n]=$!
183 done
184 wait ${setxattr_pids[@]}
185
186 $BTRFS_UTIL_PROG subvolume snapshot -r $SCRATCH_MNT $SCRATCH_MNT/snap2 \
187         | _filter_scratch
188
189 full_send_loop 5 &
190 full_send_pid=$!
191
192 inc_send_loop 10 &
193 inc_send_pid=$!
194
195 dedupe_files_loop &
196 dedupe_pid=$!
197
198 balance_loop &
199 balance_pid=$!
200
201 wait $full_send_pid
202 wait $inc_send_pid
203
204 kill $dedupe_pid
205 wait $dedupe_pid
206
207 kill $balance_pid
208 wait $balance_pid
209
210 # Check for errors messages that happen due to inconsistent snapshot caused by
211 # deduplication and balance running in parallel with send, causing btree nodes
212 # and leafs to disappear and getting reused while send is using them.
213 #
214 # Example messages:
215 #
216 # BTRFS error (device sdc): did not find backref in send_root. inode=63292, \
217 #     offset=0, disk_byte=5228134400 found extent=5228134400
218 #
219 # BTRFS error (device sdc): parent transid verify failed on 32243712 wanted 24 \
220 #     found 27
221 #
222 _dmesg_since_test_start | egrep -e '\bBTRFS error \(device .*?\):'
223
224 status=0
225 exit