1# 2# This file and its contents are supplied under the terms of the 3# Common Development and Distribution License ("CDDL"), version 1.0. 4# You may only use this file in accordance with the terms of version 5# 1.0 of the CDDL. 6# 7# A full copy of the text of the CDDL should have accompanied this 8# source. A copy of the CDDL is also available via the Internet at 9# http://www.illumos.org/license/CDDL. 10# 11 12# 13# Copyright (c) 2016 by Delphix. All rights reserved. 14# 15 16. $STF_SUITE/include/libtest.shlib 17. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg 18 19# 20# Prototype cleanup function for zpool_import tests. 21# 22function cleanup 23{ 24 # clear any remaining zinjections 25 log_must zinject -c all > /dev/null 26 27 destroy_pool $TESTPOOL1 28 29 log_must rm -f $CPATH $CPATHBKP $CPATHBKP2 $MD5FILE $MD5FILE2 30 31 log_must rm -rf $DEVICE_DIR/* 32 typeset i=0 33 while (( i < $MAX_NUM )); do 34 log_must truncate -s $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i 35 ((i += 1)) 36 done 37 is_linux && set_tunable32 TXG_HISTORY 0 38} 39 40# 41# Write a bit of data and sync several times. 42# This function is intended to be used by zpool rewind tests. 43# 44function sync_some_data_a_few_times 45{ 46 typeset pool=$1 47 typeset -i a_few_times=${2:-10} 48 49 typeset file="/$pool/tmpfile" 50 for i in {0..$a_few_times}; do 51 dd if=/dev/urandom of=${file}_$i bs=128k count=10 52 sync_pool "$pool" 53 done 54 55 return 0 56} 57 58# 59# Just write a moderate amount of data to the pool. 60# 61function write_some_data 62{ 63 typeset pool=$1 64 typeset files10mb=${2:-10} 65 66 typeset ds="$pool/fillerds" 67 zfs create $ds 68 [[ $? -ne 0 ]] && return 1 69 70 # Create 100 MB of data 71 typeset file="/$ds/fillerfile" 72 for i in {1..$files10mb}; do 73 dd if=/dev/urandom of=$file.$i bs=128k count=80 74 [[ $? -ne 0 ]] && return 1 75 done 76 77 return 0 78} 79 80# 81# Create/overwrite a few datasets with files. 82# Checksum all the files and store digests in a file. 83# 84# newdata: overwrite existing files if false. 85# md5file: file where to store md5 digests 86# datasetname: base name for datasets 87# 88function _generate_data_common 89{ 90 typeset pool=$1 91 typeset newdata=$2 92 typeset md5file=$3 93 typeset datasetname=$4 94 95 typeset -i datasets=3 96 typeset -i files=5 97 typeset -i blocks=10 98 99 [[ -n $md5file ]] && rm -f $md5file 100 for i in {1..$datasets}; do 101 ( $newdata ) && log_must zfs create "$pool/$datasetname$i" 102 for j in {1..$files}; do 103 typeset file="/$pool/$datasetname$i/file$j" 104 dd if=/dev/urandom of=$file bs=128k count=$blocks > /dev/null 105 if [[ -n $md5file ]]; then 106 typeset cksum=$(md5digest $file) 107 echo $cksum $file >> $md5file 108 fi 109 done 110 ( $newdata ) && sync_pool "$pool" 111 done 112 113 return 0 114} 115 116function generate_data 117{ 118 typeset pool=$1 119 typeset md5file="$2" 120 typeset datasetname=${3:-ds} 121 122 _generate_data_common $pool true "$md5file" $datasetname 123} 124 125function overwrite_data 126{ 127 typeset pool=$1 128 typeset md5file="$2" 129 typeset datasetname=${3:-ds} 130 131 _generate_data_common $1 false "$md5file" $datasetname 132} 133 134# 135# Verify md5sums of every file in md5sum file $1. 136# 137function verify_data_md5sums 138{ 139 typeset md5file=$1 140 141 if [[ ! -f $md5file ]]; then 142 log_note "md5 sums file '$md5file' doesn't exist" 143 return 1 144 fi 145 146 cat $md5file | \ 147 while read digest file; do 148 typeset digest1=$(md5digest $file) 149 if [[ "$digest1" != "$digest" ]]; then 150 return 1 151 fi 152 done 153 154 return 0 155} 156 157# 158# Set devices size in DEVICE_DIR to $1. 159# 160function increase_device_sizes 161{ 162 typeset newfilesize=$1 163 164 typeset -i i=0 165 while (( i < $MAX_NUM )); do 166 log_must truncate -s $newfilesize ${DEVICE_DIR}/${DEVICE_FILE}$i 167 ((i += 1)) 168 done 169} 170 171# 172# Translate vdev names returned by zpool status into more generic names. 173# 174function _translate_vdev 175{ 176 typeset vdev=$1 177 178 # 179 # eg: mirror-2 --> mirror 180 # eg: draid2:4d:12c:1s-0 --> draid2 181 # 182 typeset keywords="mirror replacing raidz1 raidz2 raidz3 indirect draid1 draid2 draid3" 183 for word in $keywords; do 184 echo $vdev | egrep -qE \ 185 "^${word}-[0-9]+\$|^${word}:[0-9]+d:[0-9]c:[0-9]+s-[0-9]+\$" 186 if [[ $? -eq 0 ]]; then 187 vdev=$word 188 break 189 fi 190 done 191 192 [[ $vdev == "logs" ]] && echo "log" && return 0 193 [[ $vdev == "raidz1" ]] && echo "raidz" && return 0 194 [[ $vdev == "draid1" ]] && echo "draid" && return 0 195 196 echo $vdev 197 return 0 198} 199 200# 201# Check that pool configuration returned by zpool status matches expected 202# configuration. Format for the check string is same as the vdev arguments for 203# creating a pool 204# Add -q for quiet mode. 205# 206# eg: check_pool_config pool1 "mirror c0t0d0s0 c0t1d0s0 log c1t1d0s0" 207# 208function check_pool_config 209{ 210 typeset logfailure=true 211 if [[ $1 == '-q' ]]; then 212 logfailure=false 213 shift 214 fi 215 216 typeset poolname=$1 217 typeset expected=$2 218 219 typeset status 220 status=$(zpool status $poolname 2>&1) 221 if [[ $? -ne 0 ]]; then 222 if ( $logfailure ); then 223 log_note "zpool status $poolname failed: $status" 224 fi 225 return 1 226 fi 227 228 typeset actual="" 229 typeset began=false 230 printf "$status\n" | while read line; do 231 typeset vdev=$(echo "$line" | awk '{printf $1}') 232 if ( ! $began ) && [[ $vdev == NAME ]]; then 233 began=true 234 continue 235 fi 236 ( $began ) && [[ -z $vdev ]] && break; 237 238 if ( $began ); then 239 [[ -z $actual ]] && actual="$vdev" && continue 240 vdev=$(_translate_vdev $vdev) 241 actual="$actual $vdev" 242 fi 243 done 244 245 expected="$poolname $expected" 246 247 if [[ "$actual" != "$expected" ]]; then 248 if ( $logfailure ); then 249 log_note "expected pool vdevs:" 250 log_note "> '$expected'" 251 log_note "actual pool vdevs:" 252 log_note "> '$actual'" 253 fi 254 return 1 255 fi 256 257 return 0 258} 259 260# 261# Check that pool configuration returned by zpool status matches expected 262# configuration within a given timeout in seconds. See check_pool_config(). 263# 264# eg: wait_for_pool_config pool1 "mirror c0t0d0s0 c0t1d0s0" 60 265# 266function wait_for_pool_config 267{ 268 typeset poolname=$1 269 typeset expectedconfig="$2" 270 typeset -i timeout=${3:-60} 271 272 timeout=$(( $timeout + $(date +%s) )) 273 274 while (( $(date +%s) < $timeout )); do 275 check_pool_config -q $poolname "$expectedconfig" 276 [[ $? -eq 0 ]] && return 0 277 sleep 3 278 done 279 280 check_pool_config $poolname "$expectedconfig" 281 return $? 282} 283 284# 285# Check that pool status is ONLINE 286# 287function check_pool_healthy 288{ 289 typeset pool=$1 290 291 typeset status 292 status=$(zpool status $pool 2>&1) 293 if [[ $? -ne 0 ]]; then 294 log_note "zpool status $pool failed: $status" 295 return 1 296 fi 297 298 status=$(echo "$status" | grep "$pool" | grep -v "pool:" | \ 299 awk '{print $2}') 300 301 if [[ $status != "ONLINE" ]]; then 302 log_note "Invalid zpool status for '$pool': '$status'" \ 303 "!= 'ONLINE'" 304 return 1 305 fi 306 307 return 0 308} 309 310# 311# Return 0 if a device is currently being replaced in the pool. 312# 313function pool_is_replacing 314{ 315 typeset pool=$1 316 317 zpool status $pool | grep "replacing" | grep "ONLINE" > /dev/null 318 319 return $? 320} 321 322function set_vdev_validate_skip 323{ 324 set_tunable32 VDEV_VALIDATE_SKIP "$1" 325} 326 327function get_zfs_txg_timeout 328{ 329 get_tunable TXG_TIMEOUT 330} 331 332function set_zfs_txg_timeout 333{ 334 set_tunable32 TXG_TIMEOUT "$1" 335} 336 337function set_spa_load_verify_metadata 338{ 339 set_tunable32 SPA_LOAD_VERIFY_METADATA "$1" 340} 341 342function set_spa_load_verify_data 343{ 344 set_tunable32 SPA_LOAD_VERIFY_DATA "$1" 345} 346 347function set_zfs_max_missing_tvds 348{ 349 set_tunable32 MAX_MISSING_TVDS "$1" 350} 351 352# 353# Use zdb to find the last txg that was synced in an active pool. 354# 355function get_last_txg_synced 356{ 357 typeset pool=$1 358 359 zdb -u $pool | awk '$1 == "txg" { print $3 }' | sort -n | tail -n 1 360} 361