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