]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib
Vendor import of openzfs master @ 184df27eef0abdc7ab2105b21257f753834b936b
[FreeBSD/FreeBSD.git] / tests / zfs-tests / tests / functional / redundancy / redundancy.kshlib
1 #
2 # CDDL HEADER START
3 #
4 # The contents of this file are subject to the terms of the
5 # Common Development and Distribution License (the "License").
6 # You may not use this file except in compliance with the License.
7 #
8 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 # or http://www.opensolaris.org/os/licensing.
10 # See the License for the specific language governing permissions
11 # and limitations under the License.
12 #
13 # When distributing Covered Code, include this CDDL HEADER in each
14 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 # If applicable, add the following below this CDDL HEADER, with the
16 # fields enclosed by brackets "[]" replaced with your own identifying
17 # information: Portions Copyright [yyyy] [name of copyright owner]
18 #
19 # CDDL HEADER END
20 #
21
22 #
23 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24 # Use is subject to license terms.
25 #
26
27 #
28 # Copyright (c) 2013, 2016 by Delphix. All rights reserved.
29 #
30
31 . $STF_SUITE/include/libtest.shlib
32 . $STF_SUITE/tests/functional/redundancy/redundancy.cfg
33
34 function cleanup
35 {
36         if poolexists $TESTPOOL; then
37                 destroy_pool $TESTPOOL
38         fi
39         typeset dir
40         for dir in $TESTDIR $BASEDIR; do
41                 if [[ -d $dir ]]; then
42                         log_must rm -rf $dir
43                 fi
44         done
45 }
46
47 #
48 # Get random number between min and max number.
49 #
50 # $1 Minimal value
51 # $2 Maximal value
52 #
53 function random
54 {
55         typeset -i min=$1
56         typeset -i max=$2
57         typeset -i value
58
59         while true; do
60                 ((value = RANDOM % (max + 1)))
61                 if ((value >= min)); then
62                         break
63                 fi
64         done
65
66         echo $value
67 }
68
69 #
70 # Record the directories construction and checksum all the files which reside
71 # within the specified pool
72 #
73 # $1 The specified pool
74 # $2 The file which save the record.
75 #
76 function record_data
77 {
78         typeset pool=$1
79         typeset recordfile=$2
80
81         [[ -z $pool ]] && log_fail "No specified pool."
82         [[ -f $recordfile ]] && log_must rm -f $recordfile
83
84         typeset mntpnt
85         mntpnt=$(get_prop mountpoint $pool)
86         log_must eval "du -a $mntpnt > $recordfile 2>&1"
87         #
88         # When the data was damaged, checksum is failing and return 1
89         # So, will not use log_must
90         #
91         find $mntpnt -type f -exec cksum {} + >> $recordfile 2>&1
92 }
93
94 #
95 # Create test pool and fill with files and directories.
96 #
97 # $1 pool name
98 # $2 pool type
99 # $3 virtual devices number
100 #
101 function setup_test_env
102 {
103         typeset pool=$1
104         typeset keyword=$2
105         typeset -i vdev_cnt=$3
106         typeset vdevs
107
108         typeset -i i=0
109         while (( i < vdev_cnt )); do
110                 vdevs="$vdevs $BASEDIR/vdev$i"
111                 ((i += 1))
112         done
113
114         if [[ ! -d $BASEDIR ]]; then
115                 log_must mkdir $BASEDIR
116         fi
117
118         if poolexists $pool ; then
119                 destroy_pool $pool
120         fi
121
122         log_must mkfile $MINVDEVSIZE $vdevs
123
124         log_must zpool create -m $TESTDIR $pool $keyword $vdevs
125
126         log_note "Filling up the filesystem ..."
127         typeset -i ret=0
128         typeset -i i=0
129         typeset file=$TESTDIR/file
130         while true ; do
131                 file_write -o create -f $file.$i \
132                         -b $BLOCKSZ -c $NUM_WRITES
133                 ret=$?
134                 (( $ret != 0 )) && break
135                 (( i = i + 1 ))
136         done
137         (($ret != 28 )) && log_note "file_write return value($ret) is unexpected."
138
139         record_data $TESTPOOL $PRE_RECORD_FILE
140 }
141
142 #
143 # Check pool status is healthy
144 #
145 # $1 pool
146 #
147 function is_healthy
148 {
149         typeset pool=$1
150
151         typeset healthy_output="pool '$pool' is healthy"
152         typeset real_output=$(zpool status -x $pool)
153
154         if [[ "$real_output" == "$healthy_output" ]]; then
155                 return 0
156         else
157                 typeset -i ret
158                 zpool status -x $pool | grep "state:" | \
159                         grep "FAULTED" >/dev/null 2>&1
160                 ret=$?
161                 (( $ret == 0 )) && return 1
162                 typeset l_scan
163                 typeset errnum
164                 l_scan=$(zpool status -x $pool | grep "scan:")
165                 l_scan=${l_scan##*"with"}
166                 errnum=$(echo $l_scan | awk '{print $1}')
167
168                 return $errnum
169         fi
170 }
171
172 #
173 # Check pool data is valid
174 #
175 # $1 pool
176 #
177 function is_data_valid
178 {
179         typeset pool=$1
180
181         record_data $pool $PST_RECORD_FILE
182         if ! diff $PRE_RECORD_FILE $PST_RECORD_FILE > /dev/null 2>&1; then
183                 return 1
184         fi
185
186         return 0
187 }
188
189 #
190 # Get the specified count devices name
191 #
192 # $1 pool name
193 # $2 devices count
194 #
195 function get_vdevs #pool cnt
196 {
197         typeset pool=$1
198         typeset -i cnt=$2
199
200         typeset all_devs=$(zpool iostat -v $pool | awk '{print $1}'| \
201                 egrep -v "^pool$|^capacity$|^mirror$|^raidz1$|^raidz2$|---" | \
202                 egrep -v "/old$|^$pool$")
203         typeset -i i=0
204         typeset vdevs
205         while ((i < cnt)); do
206                 typeset dev=$(echo $all_devs | awk '{print $1}')
207                 eval all_devs=\${all_devs##*$dev}
208
209                 vdevs="$dev $vdevs"
210                 ((i += 1))
211         done
212
213         echo "$vdevs"
214 }
215
216 #
217 # Create and replace the same name virtual device files
218 #
219 # $1 pool name
220 # $2-n virtual device files
221 #
222 function replace_missing_devs
223 {
224         typeset pool=$1
225         shift
226
227         typeset vdev
228         for vdev in $@; do
229                 log_must gnudd if=/dev/zero of=$vdev \
230                     bs=1024k count=$(($MINDEVSIZE / (1024 * 1024))) \
231                     oflag=fdatasync
232                 log_must zpool replace -wf $pool $vdev $vdev
233         done
234 }
235
236 #
237 # Damage the pool's virtual device files.
238 #
239 # $1 pool name
240 # $2 Failing devices count
241 # $3 damage vdevs method, if not null, we keep
242 #    the label for the vdevs
243 #
244 function damage_devs
245 {
246         typeset pool=$1
247         typeset -i cnt=$2
248         typeset label="$3"
249         typeset vdevs
250         typeset -i bs_count=$((64 * 1024))
251
252         vdevs=$(get_vdevs $pool $cnt)
253         typeset dev
254         if [[ -n $label ]]; then
255                 for dev in $vdevs; do
256                         dd if=/dev/zero of=$dev seek=512 bs=1024 \
257                             count=$bs_count conv=notrunc >/dev/null 2>&1
258                 done
259         else
260                 for dev in $vdevs; do
261                         dd if=/dev/zero of=$dev bs=1024 count=$bs_count \
262                             conv=notrunc >/dev/null 2>&1
263                 done
264         fi
265
266         sync_pool $pool
267 }
268
269 #
270 # Clear errors in the pool caused by data corruptions
271 #
272 # $1 pool name
273 #
274 function clear_errors
275 {
276         typeset pool=$1
277
278         log_must zpool clear $pool
279
280         if ! is_healthy $pool ; then
281                 log_note "$pool should be healthy."
282                 return 1
283         fi
284         if ! is_data_valid $pool ; then
285                 log_note "Data should be valid in $pool."
286                 return 1
287         fi
288
289         return 0
290 }
291
292 #
293 # Remove the specified pool's virtual device files
294 #
295 # $1 Pool name
296 # $2 Missing devices count
297 #
298 function remove_devs
299 {
300         typeset pool=$1
301         typeset -i cnt=$2
302         typeset vdevs
303
304         vdevs=$(get_vdevs $pool $cnt)
305         log_must rm -f $vdevs
306
307         sync_pool $pool
308 }
309
310 #
311 # Recover the bad or missing device files in the pool
312 #
313 # $1 Pool name
314 # $2 Missing devices count
315 #
316 function recover_bad_missing_devs
317 {
318         typeset pool=$1
319         typeset -i cnt=$2
320         typeset vdevs
321
322         vdevs=$(get_vdevs $pool $cnt)
323         replace_missing_devs $pool $vdevs
324
325         if ! is_healthy $pool ; then
326                 log_note "$pool should be healthy."
327                 return 1
328         fi
329         if ! is_data_valid $pool ; then
330                 log_note "Data should be valid in $pool."
331                 return 1
332         fi
333
334         return 0
335 }