1# vim: filetype=sh 2# 3# CDDL HEADER START 4# 5# The contents of this file are subject to the terms of the 6# Common Development and Distribution License (the "License"). 7# You may not use this file except in compliance with the License. 8# 9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10# or http://www.opensolaris.org/os/licensing. 11# See the License for the specific language governing permissions 12# and limitations under the License. 13# 14# When distributing Covered Code, include this CDDL HEADER in each 15# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16# If applicable, add the following below this CDDL HEADER, with the 17# fields enclosed by brackets "[]" replaced with your own identifying 18# information: Portions Copyright [yyyy] [name of copyright owner] 19# 20# CDDL HEADER END 21# 22 23# 24# Copyright 2009 Sun Microsystems, Inc. All rights reserved. 25# Use is subject to license terms. 26 27. ${STF_SUITE}/include/libtest.kshlib 28 29function cleanup 30{ 31 # Log the status of the pool to assist failures. 32 poolexists $TESTPOOL && $ZPOOL status -v $TESTPOOL 33 destroy_pool $TESTPOOL 34 typeset dir 35 for dir in $TESTDIR $BASEDIR; do 36 if [[ -d $dir ]]; then 37 log_must $RM -rf $dir 38 fi 39 done 40} 41 42# 43# Record the directories construction and checksum all the files which reside 44# within the specified pool 45# 46# $1 The specified pool 47# $2 The file which save the record. 48# 49function record_data 50{ 51 typeset pool=$1 52 typeset recordfile=$2 53 54 [[ -z $pool ]] && log_fail "No specified pool." 55 [[ -f $recordfile ]] && log_must $RM -f $recordfile 56 57 typeset mntpnt 58 mntpnt=$(get_prop mountpoint $pool) 59 log_must eval "$DU -a $mntpnt > $recordfile 2>&1" 60 # 61 # When the data was damaged, checksum is failing and return 1 62 # So, will not use log_must 63 # 64 $FIND $mntpnt -type f -exec $CKSUM {} + >> $recordfile 2>&1 65} 66 67# 68# Create test pool and fill with files and directories. 69# 70# $1 pool name 71# $2 pool type 72# $3 virtual devices number 73# 74function setup_test_env 75{ 76 typeset pool=$1 77 typeset keyword=$2 78 typeset -i vdev_cnt=$3 79 typeset vdevs 80 81 typeset -i i=0 82 while (( i < vdev_cnt )); do 83 vdevs="$vdevs $BASEDIR/vdev$i" 84 ((i += 1)) 85 done 86 87 log_must $MKDIR -p $BASEDIR 88 destroy_pool $pool 89 log_must create_vdevs $vdevs 90 91 $ECHO $vdevs | tr ' ' '\n' > $BASEDIR/vdevs 92 log_must $ZPOOL create -m $TESTDIR $pool $keyword $vdevs 93 94 typeset file=$TESTDIR/file 95 log_must $FILE_WRITE -o create -f $file -b $BLOCKSZ -c $NUM_WRITES 96 force_sync_path $BASEDIR 97 record_data $TESTPOOL $PRE_RECORD_FILE 98} 99 100# 101# Check pool data is valid 102# 103# $1 pool 104# 105function is_data_valid 106{ 107 typeset pool=$1 108 109 record_data $pool $PST_RECORD_FILE 110 if ! $DIFF $PRE_RECORD_FILE $PST_RECORD_FILE > /dev/null 2>&1; then 111 return 1 112 fi 113 114 return 0 115} 116 117# 118# Get the specified count devices name 119# 120# $1 pool name 121# $2 devices count 122# 123function get_vdevs #pool cnt 124{ 125 typeset pool=$1 126 typeset -i cnt=$2 127 128 head -$cnt $BASEDIR/vdevs | tr '\n' ' ' 129} 130 131# 132# Synchronize all the data in pool 133# 134# $1 pool name 135# 136function sync_pool #pool 137{ 138 typeset pool=$1 139 140 force_sync_path $BASEDIR 141 142 # If the OS has detected corruption on the pool, it will have 143 # automatically initiated a scrub. In that case, our "zpool scrub" 144 # command will fail. So we ignore its exit status and just check that 145 # the pool is scrubbing or has been scrubbed. 146 $ZPOOL scrub $pool >/dev/null 2>&1 147 is_pool_scrubbing $pool || is_pool_scrubbed $pool || \ 148 log_fail "$ZPOOL scrub $pool failed." 149 log_note "$pool: $ZPOOL scrub issued." 150} 151 152# 153# Create and replace the same name virtual device files 154# 155# $1 pool name 156# $2-n virtual device files 157# 158function replace_missing_devs 159{ 160 typeset pool=$1 161 shift 162 163 typeset vdev 164 for vdev in $@; do 165 [ ! -f $vdev ] && log_must create_vdevs $vdev 166 log_must $ZPOOL replace -f $pool $vdev $vdev 167 wait_for 20 1 is_pool_resilvered $pool 168 done 169} 170 171# 172# Damage the labels of the specified devices. Returns 0 if all such devices 173# are UNAVAIL, 1 otherwise. 174# 175function damage_dev_labels # pool <vdev> [vdev ...] 176{ 177 typeset pool=$1 178 typeset -i ret=0 179 shift 180 181 for vdev in $*; do 182 check_state $pool $vdev UNAVAIL && continue 183 log_must create_vdevs $vdev 184 ret=1 185 done 186 [ $ret -eq 0 ] && return $ret 187 sync_pool $pool 188 return $ret 189} 190 191# 192# Damage the pool's virtual device files. 193# 194# $1 pool name 195# $2 Failing devices count 196# $3 damage vdevs method, if not null, we keep the label for the vdevs 197# 198function damage_devs 199{ 200 typeset pool=$1 201 typeset -i cnt=$2 202 typeset label="$3" 203 typeset vdevs 204 typeset -i bs_count 205 206 vdevs=$(get_vdevs $pool $cnt) 207 log_note "Damaging pool $pool devices: $vdevs" 208 if [[ -n $label ]]; then 209 typeset -i i=0 210 log_mustnot pool_has_errors $pool 211 while [ $i -lt $cnt ]; do 212 corrupt_file $TESTPOOL $TESTDIR/file $i 213 (( i += 1 )) 214 done 215 sync_pool $pool 216 wait_for 20 1 is_pool_scrubbed $pool 217 218 log_must pool_has_errors $pool 219 else 220 # The pool can be syncing, thus fixing its labels. So we 221 # have to keep trying until all the devices go offline. 222 wait_for 20 1 damage_dev_labels $pool $vdevs 223 fi 224 225 log_note "Pool $pool vdevs $vdevs damage completed." 226} 227 228# 229# Clear errors in the pool caused by data corruptions 230# 231# $1 pool name 232# 233function clear_errors 234{ 235 typeset pool=$1 236 237 log_must $ZPOOL clear $pool 238 # The pool may need to resilver (issued async by 'zpool clear'), 239 # give it a chance to do so. 240 wait_for 30 1 is_pool_healthy $pool 241 242 if ! is_data_valid $pool ; then 243 $ZPOOL status -x $pool 244 log_note "Data should be valid in $pool." 245 return 1 246 fi 247 248 return 0 249} 250 251# 252# Remove the specified pool's virtual device files 253# 254# $1 Pool name 255# $2 Missing devices count 256# 257function remove_devs 258{ 259 typeset pool=$1 260 typeset -i cnt=$2 261 typeset vdevs 262 263 vdevs=$(get_vdevs $pool $cnt) 264 log_note "Removing pool $pool vdevs: $vdevs" 265 log_must $RM -f $vdevs 266 267 sync_pool $pool 268 for vdev in $vdevs; do 269 wait_for 20 1 check_state $pool $vdev UNAVAIL 270 done 271} 272 273# 274# Recover the bad or missing device files in the pool 275# 276# $1 Pool name 277# $2 Missing devices count 278# 279function recover_bad_missing_devs 280{ 281 typeset pool=$1 282 typeset -i cnt=$2 283 typeset vdevs 284 285 vdevs=$(get_vdevs $pool $cnt) 286 log_note "Replacing missing pool $pool vdevs: $vdevs" 287 replace_missing_devs $pool $vdevs 288 289 if ! is_pool_healthy $pool ; then 290 log_note "$pool should be healthy." 291 return 1 292 fi 293 if ! is_data_valid $pool ; then 294 log_note "Data should be valid in $pool." 295 return 1 296 fi 297 298 return 0 299} 300