]> git.proxmox.com Git - mirror_zfs.git/blob - tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib
Add the ZFS Test Suite
[mirror_zfs.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 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 $DEV_SIZE $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 # Synchronize all the data in pool
218 #
219 # $1 pool name
220 #
221 function sync_pool #pool
222 {
223 typeset pool=$1
224
225 log_must $SYNC
226 log_must $SLEEP 2
227 # Flush all the pool data.
228 typeset -i ret
229 $ZPOOL scrub $pool >/dev/null 2>&1
230 ret=$?
231 (( $ret != 0 )) && \
232 log_fail "$ZPOOL scrub $pool failed."
233
234 while ! is_pool_scrubbed $pool; do
235 if is_pool_resilvered $pool ; then
236 log_fail "$pool should not be resilver completed."
237 fi
238 log_must $SLEEP 2
239 done
240 }
241
242 #
243 # Create and replace the same name virtual device files
244 #
245 # $1 pool name
246 # $2-n virtual device files
247 #
248 function replace_missing_devs
249 {
250 typeset pool=$1
251 shift
252
253 typeset vdev
254 for vdev in $@; do
255 log_must $MKFILE $DEV_SIZE $vdev
256 log_must $ZPOOL replace -f $pool $vdev $vdev
257 while true; do
258 if ! is_pool_resilvered $pool ; then
259 log_must $SLEEP 2
260 else
261 break
262 fi
263 done
264 done
265 }
266
267 #
268 # Damage the pool's virtual device files.
269 #
270 # $1 pool name
271 # $2 Failing devices count
272 # $3 damage vdevs method, if not null, we keep
273 # the label for the vdevs
274 #
275 function damage_devs
276 {
277 typeset pool=$1
278 typeset -i cnt=$2
279 typeset label="$3"
280 typeset vdevs
281 typeset -i bs_count
282
283 vdevs=$(get_vdevs $pool $cnt)
284 if [[ -n $label ]]; then
285 typeset dev
286 for dev in $vdevs; do
287 bs_count=$($LS -l $dev | $AWK '{print $5}')
288 (( bs_count = bs_count/1024 - 512 ))
289 $DD if=/dev/zero of=$dev seek=512 bs=1024 \
290 count=$bs_count conv=notrunc >/dev/null 2>&1
291 done
292 else
293 log_must $MKFILE $DEV_SIZE $vdevs
294 fi
295
296 sync_pool $pool
297 }
298
299 #
300 # Clear errors in the pool caused by data corruptions
301 #
302 # $1 pool name
303 #
304 function clear_errors
305 {
306 typeset pool=$1
307
308 log_must $ZPOOL clear $pool
309
310 if ! is_healthy $pool ; then
311 log_note "$pool should be healthy."
312 return 1
313 fi
314 if ! is_data_valid $pool ; then
315 log_note "Data should be valid in $pool."
316 return 1
317 fi
318
319 return 0
320 }
321
322 #
323 # Remove the specified pool's virtual device files
324 #
325 # $1 Pool name
326 # $2 Missing devices count
327 #
328 function remove_devs
329 {
330 typeset pool=$1
331 typeset -i cnt=$2
332 typeset vdevs
333
334 vdevs=$(get_vdevs $pool $cnt)
335 log_must $RM -f $vdevs
336
337 sync_pool $pool
338 }
339
340 #
341 # Recover the bad or missing device files in the pool
342 #
343 # $1 Pool name
344 # $2 Missing devices count
345 #
346 function recover_bad_missing_devs
347 {
348 typeset pool=$1
349 typeset -i cnt=$2
350 typeset vdevs
351
352 vdevs=$(get_vdevs $pool $cnt)
353 replace_missing_devs $pool $vdevs
354
355 if ! is_healthy $pool ; then
356 log_note "$pool should be healthy."
357 return 1
358 fi
359 if ! is_data_valid $pool ; then
360 log_note "Data should be valid in $pool."
361 return 1
362 fi
363
364 return 0
365 }