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 eval "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 || return 1 68 69 # Create 100 MB of data 70 typeset file="/$ds/fillerfile" 71 for i in {1..$files10mb}; do 72 dd if=/dev/urandom of=$file.$i bs=128k count=80 || return 1 73 done 74} 75 76# 77# Create/overwrite a few datasets with files. 78# Checksum all the files and store digests in a file. 79# 80# newdata: overwrite existing files if false. 81# md5file: file where to store md5 digests 82# datasetname: base name for datasets 83# 84function _generate_data_common 85{ 86 typeset pool=$1 87 typeset newdata=$2 88 typeset md5file=$3 89 typeset datasetname=$4 90 91 typeset -i datasets=3 92 typeset -i files=5 93 typeset -i blocks=10 94 95 [[ -n $md5file ]] && rm -f $md5file 96 for i in {1..$datasets}; do 97 ( $newdata ) && log_must zfs create "$pool/$datasetname$i" 98 for j in {1..$files}; do 99 typeset file="/$pool/$datasetname$i/file$j" 100 dd if=/dev/urandom of=$file bs=128k count=$blocks > /dev/null 101 if [[ -n $md5file ]]; then 102 typeset cksum=$(md5digest $file) 103 echo $cksum $file >> $md5file 104 fi 105 done 106 ( $newdata ) && sync_pool "$pool" 107 done 108 109 return 0 110} 111 112function generate_data 113{ 114 typeset pool=$1 115 typeset md5file="$2" 116 typeset datasetname=${3:-ds} 117 118 _generate_data_common $pool true "$md5file" $datasetname 119} 120 121function overwrite_data 122{ 123 typeset pool=$1 124 typeset md5file="$2" 125 typeset datasetname=${3:-ds} 126 127 _generate_data_common $1 false "$md5file" $datasetname 128} 129 130# 131# Verify md5sums of every file in md5sum file $1. 132# 133function verify_data_md5sums 134{ 135 typeset md5file=$1 136 137 if [[ ! -f $md5file ]]; then 138 log_note "md5 sums file '$md5file' doesn't exist" 139 return 1 140 fi 141 142 while read -r digest file; do 143 typeset digest1=$(md5digest $file) 144 if [[ "$digest1" != "$digest" ]]; then 145 return 1 146 fi 147 done < $md5file 148 149 return 0 150} 151 152# 153# Set devices size in DEVICE_DIR to $1. 154# 155function increase_device_sizes 156{ 157 typeset newfilesize=$1 158 159 typeset -i i=0 160 while (( i < $MAX_NUM )); do 161 log_must truncate -s $newfilesize ${DEVICE_DIR}/${DEVICE_FILE}$i 162 ((i += 1)) 163 done 164} 165 166# 167# Translate vdev names returned by zpool status into more generic names. 168# 169function _translate_vdev 170{ 171 typeset vdev=$1 172 173 # 174 # eg: mirror-2 --> mirror 175 # eg: draid2:4d:12c:1s-0 --> draid2 176 # 177 typeset keywords="mirror replacing raidz1 raidz2 raidz3 indirect draid1 draid2 draid3" 178 for word in $keywords; do 179 if echo $vdev | 180 grep -qE "^${word}-[0-9]+\$|^${word}:[0-9]+d:[0-9]c:[0-9]+s-[0-9]+\$" 181 then 182 vdev=$word 183 break 184 fi 185 done 186 187 case "$vdev" in 188 logs) echo "log" ;; 189 raidz1) echo "raidz" ;; 190 draid1) echo "draid" ;; 191 *) echo $vdev ;; 192 esac 193} 194 195# 196# Check that pool configuration returned by zpool status matches expected 197# configuration. Format for the check string is same as the vdev arguments for 198# creating a pool 199# Add -q for quiet mode. 200# 201# eg: check_pool_config pool1 "mirror c0t0d0s0 c0t1d0s0 log c1t1d0s0" 202# 203function check_pool_config 204{ 205 typeset logfailure=true 206 if [[ $1 == '-q' ]]; then 207 logfailure=false 208 shift 209 fi 210 211 typeset poolname=$1 212 typeset expected=$2 213 214 typeset status 215 if ! status=$(zpool status $poolname 2>&1); then 216 if $logfailure; then 217 log_note "zpool status $poolname failed: $status" 218 fi 219 return 1 220 fi 221 222 typeset actual="" 223 typeset began=false 224 while read -r vdev _; do 225 if ( ! $began ) && [[ $vdev == NAME ]]; then 226 began=true 227 continue 228 fi 229 ( $began ) && [[ -z $vdev ]] && break; 230 231 if ( $began ); then 232 [[ -z $actual ]] && actual="$vdev" && continue 233 vdev=$(_translate_vdev $vdev) 234 actual="$actual $vdev" 235 fi 236 done <<<"$status" 237 238 expected="$poolname $expected" 239 240 if [[ "$actual" != "$expected" ]]; then 241 if $logfailure; then 242 log_note "expected pool vdevs:" 243 log_note "> '$expected'" 244 log_note "actual pool vdevs:" 245 log_note "> '$actual'" 246 fi 247 return 1 248 fi 249 250 return 0 251} 252 253# 254# Check that pool configuration returned by zpool status matches expected 255# configuration within a given timeout in seconds. See check_pool_config(). 256# 257# eg: wait_for_pool_config pool1 "mirror c0t0d0s0 c0t1d0s0" 60 258# 259function wait_for_pool_config 260{ 261 typeset poolname=$1 262 typeset expectedconfig="$2" 263 typeset -i timeout=${3:-60} 264 265 timeout=$(( $timeout + $(date +%s) )) 266 267 while (( $(date +%s) < $timeout )); do 268 check_pool_config -q $poolname "$expectedconfig" && return 0 269 sleep 3 270 done 271 272 check_pool_config $poolname "$expectedconfig" 273} 274 275# 276# Check that pool status is ONLINE 277# 278function check_pool_healthy 279{ 280 typeset pool=$1 281 typeset status 282 283 if ! status=$(zpool status $pool 2>&1); then 284 log_note "zpool status $pool failed: $status" 285 return 1 286 fi 287 288 status=$(echo "$status" | awk -v p="$pool" '!/pool:/ && $0 ~ p {print $2}') 289 290 if [[ $status != "ONLINE" ]]; then 291 log_note "Invalid zpool status for '$pool': '$status'" \ 292 "!= 'ONLINE'" 293 return 1 294 fi 295 296 return 0 297} 298 299# 300# Return 0 if a device is currently being replaced in the pool. 301# 302function pool_is_replacing 303{ 304 typeset pool=$1 305 306 zpool status $pool | grep "replacing" | grep -q "ONLINE" 307} 308 309function set_vdev_validate_skip 310{ 311 set_tunable32 VDEV_VALIDATE_SKIP "$1" 312} 313 314function get_zfs_txg_timeout 315{ 316 get_tunable TXG_TIMEOUT 317} 318 319function set_zfs_txg_timeout 320{ 321 set_tunable32 TXG_TIMEOUT "$1" 322} 323 324function set_spa_load_verify_metadata 325{ 326 set_tunable32 SPA_LOAD_VERIFY_METADATA "$1" 327} 328 329function set_spa_load_verify_data 330{ 331 set_tunable32 SPA_LOAD_VERIFY_DATA "$1" 332} 333 334function set_zfs_max_missing_tvds 335{ 336 set_tunable32 MAX_MISSING_TVDS "$1" 337} 338 339# 340# Use zdb to find the last txg that was synced in an active pool. 341# 342function get_last_txg_synced 343{ 344 typeset pool=$1 345 346 zdb -u $pool | awk '$1 == "txg" { print $3 }' | sort -n | tail -n 1 347} 348