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