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