btrfs: convert tests to SPDX license tags
[xfstests-dev.git] / tests / btrfs / 011
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (C) 2013 STRATO.  All rights reserved.
4 #
5 # FSQA Test No. btrfs/011
6 #
7 # Test of the btrfs replace operation.
8 #
9 # The amount of tests done depends on the number of devices in the
10 # SCRATCH_DEV_POOL. For full test coverage, at least 5 devices should
11 # be available (e.g. 5 partitions).
12 #
13 # The source and target devices for the replace operation are
14 # arbitrarily chosen out of SCRATCH_DEV_POOl. Since the target device
15 # mustn't be smaller than the source device, the requirement for this
16 # test is that all devices have _exactly_ the same size. If this is
17 # not the case, this test is not run.
18 #
19 # To check the filesystems after replacing a device, a scrub run is
20 # performed, a btrfsck run, and finally the filesystem is remounted.
21 #
22 seq=`basename $0`
23 seqres=$RESULT_DIR/$seq
24 echo "QA output created by $seq"
25
26 here=`pwd`
27 tmp=/tmp/$$
28 status=1
29 noise_pid=0
30
31 _cleanup()
32 {
33         if [ $noise_pid -ne 0 ] && ps -p $noise_pid | grep -q $noise_pid; then
34                 kill -TERM $noise_pid
35         fi
36         wait
37         rm -f $tmp.tmp
38         # we need this umount and couldn't rely on _require_scratch to umount
39         # it from next test, because we would replace SCRATCH_DEV, which is
40         # needed by _require_scratch, and make it umounted.
41         _scratch_unmount > /dev/null 2>&1
42 }
43 trap "_cleanup; exit \$status" 0 1 2 3 15
44
45 # get standard environment, filters and checks
46 . ./common/rc
47 . ./common/filter
48
49 # real QA test starts here
50 _supported_fs btrfs
51 _require_scratch_nocheck
52 _require_scratch_dev_pool 5
53 _require_scratch_dev_pool_equal_size
54 _require_command "$WIPEFS_PROG" wipefs
55
56 rm -f $seqres.full
57 rm -f $tmp.tmp
58
59 echo "*** test btrfs replace"
60
61 fill_scratch()
62 {
63         local fssize=$1
64
65         # Fill inline extents.
66         for i in `seq 1 500`; do
67                 _ddt of=$SCRATCH_MNT/s$i bs=3800 count=1
68         done > /dev/null 2>&1
69
70         # Fill data extents.
71         for i in `seq 1 500`; do
72                 _ddt of=$SCRATCH_MNT/l$i bs=16385 count=1
73         done > /dev/null 2>&1
74         _ddt of=$SCRATCH_MNT/t0 bs=1M count=1 > /dev/null 2>&1
75         for i in `seq $fssize`; do
76                 cp $SCRATCH_MNT/t0 $SCRATCH_MNT/t$i || _fail "cp failed"
77         done > /dev/null 2>> $seqres.full
78         sync; sync
79 }
80
81 workout()
82 {
83         local mkfs_options="$1"
84         local num_devs4raid="$2"
85         local with_cancel="$3"
86         local fssize="$4"
87         local source_dev="`echo ${SCRATCH_DEV_POOL} | awk '{print $1}'`"
88         local quick="quick"
89
90         [[ $fssize != 64 ]] && quick="thorough"
91
92         echo -e "\\n---------workout \"$1\" $2 $3 $4-----------" >> $seqres.full
93
94         $WIPEFS_PROG -a $SCRATCH_DEV_POOL > /dev/null 2>&1
95         _scratch_dev_pool_get $num_devs4raid
96         _spare_dev_get
97
98         _scratch_pool_mkfs $mkfs_options >> $seqres.full 2>&1 ||\
99                 _fail "mkfs failed"
100
101         _scratch_mount
102         _require_fs_space $SCRATCH_MNT $((2 * 512 * 1024)) #2.5G
103
104         fill_scratch $fssize
105         _run_btrfs_util_prog filesystem show -m $SCRATCH_MNT
106
107         echo -e "Replace from $source_dev to $SPARE_DEV\\n" >> $seqres.full
108         btrfs_replace_test $source_dev $SPARE_DEV "" $with_cancel $quick
109
110         _run_btrfs_util_prog filesystem show -m $SCRATCH_MNT
111
112         # Skip -r test for configs without mirror OR replace cancel
113         if echo $mkfs_options | egrep -qv "raid1|raid5|raid6|raid10" || \
114            [ "${with_cancel}Q" = "cancelQ" ]; then
115                 _scratch_unmount > /dev/null 2>&1
116                 _scratch_dev_pool_put
117                 _spare_dev_put
118                 return 0
119         fi
120
121         # Due to above replace, now SPARE_DEV is part of the FS, check that.
122         $BTRFS_UTIL_PROG filesystem show -m $SCRATCH_MNT |\
123                 grep -qs $SPARE_DEV$ ||\
124                 _fail "$SPARE_DEV is not part of SCRATCH_FS"
125
126         btrfs_replace_test $SPARE_DEV $source_dev "-r" $with_cancel $quick
127
128         _scratch_unmount > /dev/null 2>&1
129         _scratch_dev_pool_put
130         _spare_dev_put
131 }
132
133 btrfs_replace_test()
134 {
135         local source_dev="$1"
136         local target_dev="$2"
137         local replace_options="$3"
138         local with_cancel="$4"
139         local quick="$5"
140
141         # generate some (slow) background traffic in parallel to the
142         # replace operation. It is not a problem if cat fails early
143         # with ENOSPC.
144         cat /dev/urandom | od > $SCRATCH_MNT/noise 2>> $seqres.full &
145         noise_pid=$!
146
147         if [ "${with_cancel}Q" = "cancelQ" ]; then
148                 # background the replace operation (no '-B' option given)
149                 _run_btrfs_util_prog replace start -f $replace_options $source_dev $target_dev $SCRATCH_MNT
150                 sleep 1
151                 _run_btrfs_util_prog replace cancel $SCRATCH_MNT
152
153                 # 'replace status' waits for the replace operation to finish
154                 # before the status is printed
155                 $BTRFS_UTIL_PROG replace status $SCRATCH_MNT > $tmp.tmp 2>&1
156                 cat $tmp.tmp >> $seqres.full
157                 grep -q canceled $tmp.tmp || _fail "btrfs replace status (canceled) failed"
158         else
159                 if [ "${quick}Q" = "thoroughQ" ]; then
160                         # On current hardware, the thorough test runs
161                         # more than a second. This is a chance to force
162                         # a sync in the middle of the replace operation.
163                         (sleep 1; sync) > /dev/null 2>&1 &
164                 fi
165                 _run_btrfs_util_prog replace start -Bf $replace_options $source_dev $target_dev $SCRATCH_MNT
166
167                 $BTRFS_UTIL_PROG replace status $SCRATCH_MNT > $tmp.tmp 2>&1
168                 cat $tmp.tmp >> $seqres.full
169                 grep -q finished $tmp.tmp || _fail "btrfs replace status (finished) failed"
170         fi
171
172         if ps -p $noise_pid | grep -q $noise_pid; then
173                 kill -TERM $noise_pid 2> /dev/null
174         fi
175         noise_pid=0
176         wait
177
178         # scrub tests on-disk data, that's the reason for the sync.
179         # With the '-B' option (don't background), any type of error causes
180         # exit values != 0, including detected correctable and uncorrectable
181         # errors on the device.
182         sync; sync
183         _run_btrfs_util_prog scrub start -B $SCRATCH_MNT
184
185         # Two tests are performed, the 1st is to btrfsck the filesystem,
186         # and the 2nd test is to mount the filesystem.
187         # Usually _check_btrfs_filesystem would perform the mount test,
188         # but it gets confused by the mount output that shows SCRATCH_MNT
189         # mounted but not being mounted to SCRATCH_DEV. This happens
190         # because in /proc/mounts the 2nd device of the filesystem is
191         # shown after the replace operation. Let's just do the mount
192         # test manually after _check_btrfs_filesystem is finished.
193         _scratch_unmount > /dev/null 2>&1
194         if [ "${with_cancel}Q" != "cancelQ" ]; then
195                 # after the replace operation, use the target_dev for everything
196                 echo "_check_btrfs_filesystem $target_dev" >> $seqres.full
197                 _check_btrfs_filesystem $target_dev
198                 _mount -t $FSTYP `_scratch_mount_options | sed "s&${SCRATCH_DEV}&${target_dev}&"`
199         else
200                 _check_btrfs_filesystem $source_dev
201                 _scratch_mount
202         fi
203 }
204
205 workout "-m single -d single" 1 no 64
206 workout "-m single -d single -M" 1 no 64
207 workout "-m dup -d single" 1 no 64
208 workout "-m dup -d single" 1 cancel 1024
209 workout "-m dup -d dup -M" 1 no 64
210 workout "-m raid0 -d raid0" 2 no 64
211 workout "-m raid1 -d raid1" 2 no 2048
212 workout "-m raid5 -d raid5" 2 no 64
213 workout "-m raid6 -d raid6" 3 no 64
214 workout "-m raid10 -d raid10" 4 no 64
215
216 echo "*** done"
217 status=0
218 exit