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