Index: projects/zfsd/head/tests/sys/cddl/zfs/include/libsas.kshlib =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/include/libsas.kshlib (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/include/libsas.kshlib (revision 292346) @@ -1,208 +1,185 @@ # # Copyright (c) 2010 Spectra Logic Corporation # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions, and the following disclaimer, # without modification. # 2. Redistributions in binary form must reproduce at minimum a disclaimer # substantially similar to the "NO WARRANTY" disclaimer below # ("Disclaimer") and any redistribution must be conditioned upon # including a substantially similar Disclaimer requirement for further # binary redistribution. # # NO WARRANTY # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGES. # # $Id: //SpectraBSD/stable/tests/sys/cddl/zfs/include/libsas.kshlib#2 $ # $FreeBSD$ # +# Get all PHYs for a given expander. +# Returns formatting suitable for iteration. +function get_all_phys +{ + typeset expander=$1 + camcontrol smpphylist $expander -q | awk '{print $1" "$NF}' | \ + tr -d '()' | tr ',' ' ' | tr '\n' ',' +} + # # Given a disk (e.g. /dev/da0 or da0), determine the following: # - Does it exist in CAM? # - Is it attached to an expander and can we find that expander? # Returns two variables: # EXPANDER -- The peripheral we need to talk to to communicate with the # expander that is connected to the given disk. # PHY -- The phy on the expander that we need to talk to. # function find_verify_sas_disk { typeset DISK=${1##*/} typeset i - if [ ! -c /dev/$DISK ]; then - log_fail "Cannot find device \"/dev/$DISK\", arg is \"$1\"" - fi + [ ! -c /dev/$DISK ] && log_fail "\"/dev/$DISK\" is not a char device" # Make sure this device exists. An inquiry should always succeed, # even if there is a pending error. log_must camcontrol inquiry $DISK > /dev/null # Pull the list of every peripheral in the system, except for # peripherals that are attached to the disk we're looking for typeset PASSLIST=`camcontrol devlist |awk '{print $NF}' |\ egrep -v ".*$DISK[^[:digit:]]" |tr -d '()' |awk -F, '{print $1}'` typeset FOUND=0 - for i in $PASSLIST; - do + for i in $PASSLIST; do # Make sure this particular device supports SMP. If not, # no big deal, keep going. camcontrol smprg $i > /dev/null 2>&1 - if [ $? != 0 ]; then - continue - fi + [ $? -ne 0 ] && continue # Make sure this particular device is an Enclosure Services # device. That way, we won't wind up removing the device # we're trying to operate on. # XXX this will need to change once CAM is changed to # include SMP targets in the topology. This merely takes # advantage of the fact that most (all?) expanders include # a SES device. camcontrol inquiry $i |grep "Enclosure Services" > /dev/null - if [ $? != 0 ]; then - continue - fi + [ $? -ne 0 ] && continue # For every peripheral, we go through and pull out the # list of devices and their phys that we can see via this # peripheral. IFS="," - for j in `camcontrol smpphylist $i -q |awk '{print $1" "$NF}' |\ - tr -d '()' |tr ',' ' ' |tr '\n' ','` - do + for j in $(get_all_phys $i); do IFS=", \n" set -A PERIPHLIST $j unset IFS typeset NUMPERIPHS=${#PERIPHLIST[*]} ((k=1)) while [ $k -lt $NUMPERIPHS ]; do if [ "${PERIPHLIST[$k]}" = "$DISK" ]; then # echo "found $DISK PHY = ${PERIPHLIST[0]} on $i" FOUND=1 export EXPANDER=$i export PHY=${PERIPHLIST[0]} break; fi ((k=k+1)) done if [ $FOUND != 0 ]; then break; fi done - unset IFS - if [ $FOUND != 0 ]; then - break; - fi + [ $FOUND -ne 0 ] && break done - - if [ $FOUND = 0 ]; then - log_fail "Could not find PHY for disk $DISK" - fi - + [ $FOUND -eq 0 ] && log_fail "Could not find PHY for disk $DISK" } -# Given an expander and phy number, find the +# +# Given an expander and phy number, find the disk device name. # function find_disk_by_phy { typeset EXPANDER=$1 typeset PHY=$2 typeset FOUND=0 unset FOUNDDISK IFS="," - for j in `camcontrol smpphylist $1 -q |awk '{print $1" "$NF}' |\ - tr -d '()' |tr ',' ' ' |tr '\n' ','` - do + for j in $(get_all_phys $EXPANDER); do IFS=", \n" set -A PERIPHLIST $j unset IFS - if [ ${PERIPHLIST[0]} != $2 ]; then - continue; - fi + [ "${PERIPHLIST[0]}" != "$2" ] && continue typeset NUMPERIPHS=${#PERIPHLIST[*]} - ((k=1)) - while [ $k -lt $NUMPERIPHS ]; do + for ((k=1; $k < $NUMPERIPHS; k=$k + 1)); do ((PSTOP=$NUMPERIPHS-1)) if [ "${PERIPHLIST[$k]%%[0-9]*}" != "pass" ] || \ [ "$k" -eq $PSTOP ]; then export FOUNDDISK=${PERIPHLIST[$k]} break; fi - ((k=k+1)) done FOUND=1 break; done - - if [ "$FOUND" = 0 ]; then - log_fail "could not find peripheral for phy $2 on expander $1" - fi } # Given an expander and phy on that expander, disable the phy. # This function will exit (via log_fail) if it can't send the disable # request. function disable_sas_disk { typeset EXPANDER=$1 typeset PHY=$2 # Disable the phy for this particular device - camcontrol smppc $EXPANDER -v -p $PHY -o disable - if [ $? != 0 ]; then - log_fail "error disabling phy $PHY on $EXPANDER to remove $DISK" - fi - - # Wait for the rescan to happen - if [ -z $NO_SAS_DISK_WAIT ]; then - log_note "waiting 10 seconds for device to go away" - $SLEEP 10 - fi + log_must camcontrol smppc $EXPANDER -v -p $PHY -o disable } # Given an expander and phy on that expander, enable the phy. # This function will exit (via log_fail) if it can't send the link reset # request. -# -# XXX KDM in tests, the link reset doesn't always cause the disk to show -# up. A rescan does seem to work in that situation, however. function enable_sas_disk { typeset EXPANDER=$1 typeset PHY=$2 # Send a link reset to bring the device back - camcontrol smppc $EXPANDER -p $PHY -o linkreset - if [ $? != 0 ]; then - log_fail "error sending a linkreset to phy $PHY on $EXPANDER" - fi + log_must camcontrol smppc $EXPANDER -p $PHY -o linkreset +} - if [ -z $NO_SAS_DISK_WAIT ]; then - $SLEEP 10 +function rescan_disks +{ + if [[ -z "$1" ]]; then + log_must camcontrol rescan all >/dev/null + return fi + + for device in $(echo $* | sort -u); do + log_must camcontrol rescan $device >/dev/null + done } Index: projects/zfsd/head/tests/sys/cddl/zfs/include/libtest.kshlib =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/include/libtest.kshlib (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/include/libtest.kshlib (revision 292346) @@ -1,2871 +1,2932 @@ # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)libtest.kshlib 1.15 09/08/06 SMI" # . ${STF_SUITE}/include/logapi.kshlib ZFS=${ZFS:-/sbin/zfs} ZPOOL=${ZPOOL:-/sbin/zpool} os_name=`uname -s` # Determine if a test has the necessary requirements to run function test_requires { integer unsupported=0 unsupported_list="" until [[ $# -eq 0 ]];do var_name=$1 cmd=$(eval echo \$${1}) if [[ ! "$cmd" != "" ]] ; then print $var_name is not set unsupported_list="$var_name $unsupported_list" ((unsupported=unsupported+1)) fi shift done if [[ unsupported -gt 0 ]] ; then log_unsupported "$unsupported_list commands are unsupported" else log_note "All commands are supported" fi } # Determine whether a dataset is mounted # # $1 dataset name # $2 filesystem type; optional - defaulted to zfs # # Return 0 if dataset is mounted; 1 if unmounted; 2 on error function ismounted { typeset fstype=$2 [[ -z $fstype ]] && fstype=zfs typeset out dir name ret case $fstype in zfs) if [[ "$1" == "/"* ]] ; then for out in $($ZFS mount | $AWK '{print $2}') ; do [[ $1 == $out ]] && return 0 done else for out in $($ZFS mount | $AWK '{print $1}') ; do [[ $1 == $out ]] && return 0 done fi ;; ufs|nfs) # a = device, b = "on", c = mount point", d = flags $MOUNT | $GREP $fstype | while read a b c d do [[ "$1" == "$a" || "$1" == "$c" ]] && return 0 done ;; esac return 1 } # Return 0 if a dataset is mounted; 1 otherwise # # $1 dataset name # $2 filesystem type; optional - defaulted to zfs function mounted { ismounted $1 $2 (( $? == 0 )) && return 0 return 1 } # Return 0 if a dataset is unmounted; 1 otherwise # # $1 dataset name # $2 filesystem type; optional - defaulted to zfs function unmounted { ismounted $1 $2 (( $? == 1 )) && return 0 return 1 } # split line on "," # # $1 - line to split function splitline { $ECHO $1 | $SED "s/,/ /g" } function default_setup { default_setup_noexit "$@" log_pass } # # Given a list of disks, setup storage pools and datasets. # function default_setup_noexit { typeset disklist=$1 typeset container=$2 typeset volume=$3 if is_global_zone; then if poolexists $TESTPOOL ; then destroy_pool $TESTPOOL fi [[ -d /$TESTPOOL ]] && $RM -rf /$TESTPOOL log_must $ZPOOL create -f $TESTPOOL $disklist else reexport_pool fi $RM -rf $TESTDIR || log_unresolved Could not remove $TESTDIR $MKDIR -p $TESTDIR || log_unresolved Could not create $TESTDIR log_must $ZFS create $TESTPOOL/$TESTFS log_must $ZFS set mountpoint=$TESTDIR $TESTPOOL/$TESTFS if [[ -n $container ]]; then $RM -rf $TESTDIR1 || \ log_unresolved Could not remove $TESTDIR1 $MKDIR -p $TESTDIR1 || \ log_unresolved Could not create $TESTDIR1 log_must $ZFS create $TESTPOOL/$TESTCTR log_must $ZFS set canmount=off $TESTPOOL/$TESTCTR log_must $ZFS create $TESTPOOL/$TESTCTR/$TESTFS1 log_must $ZFS set mountpoint=$TESTDIR1 \ $TESTPOOL/$TESTCTR/$TESTFS1 fi if [[ -n $volume ]]; then if is_global_zone ; then log_must $ZFS create -V $VOLSIZE $TESTPOOL/$TESTVOL else log_must $ZFS create $TESTPOOL/$TESTVOL fi fi } # # Given a list of disks, setup a storage pool, file system and # a container. # function default_container_setup { typeset disklist=$1 default_setup "$disklist" "true" } # # Given a list of disks, setup a storage pool,file system # and a volume. # function default_volume_setup { typeset disklist=$1 default_setup "$disklist" "" "true" } # # Given a list of disks, setup a storage pool,file system, # a container and a volume. # function default_container_volume_setup { typeset disklist=$1 default_setup "$disklist" "true" "true" } # # Create a snapshot on a filesystem or volume. Defaultly create a snapshot on # filesystem # # $1 Existing filesystem or volume name. Default, $TESTFS # $2 snapshot name. Default, $TESTSNAP # function create_snapshot { typeset fs_vol=${1:-$TESTFS} typeset snap=${2:-$TESTSNAP} [[ -z $fs_vol ]] && log_fail "Filesystem or volume's name is undefined." [[ -z $snap ]] && log_fail "Snapshot's name is undefined." if snapexists $fs_vol@$snap; then log_fail "$fs_vol@$snap already exists." fi datasetexists $fs_vol || \ log_fail "$fs_vol must exist." log_must $ZFS snapshot $fs_vol@$snap } # # Create a clone from a snapshot, default clone name is $TESTCLONE. # # $1 Existing snapshot, $TESTPOOL/$TESTFS@$TESTSNAP is default. # $2 Clone name, $TESTPOOL/$TESTCLONE is default. # function create_clone # snapshot clone { typeset snap=${1:-$TESTPOOL/$TESTFS@$TESTSNAP} typeset clone=${2:-$TESTPOOL/$TESTCLONE} [[ -z $snap ]] && \ log_fail "Snapshot name is undefined." [[ -z $clone ]] && \ log_fail "Clone name is undefined." log_must $ZFS clone $snap $clone } function default_mirror_setup { default_mirror_setup_noexit $1 $2 $3 log_pass } # # Given a pair of disks, set up a storage pool and dataset for the mirror # @parameters: $1 the primary side of the mirror # $2 the secondary side of the mirror # @uses: ZPOOL ZFS TESTPOOL TESTFS function default_mirror_setup_noexit { readonly func="default_mirror_setup_noexit" typeset primary=$1 typeset secondary=$2 [[ -z $primary ]] && \ log_fail "$func: No parameters passed" [[ -z $secondary ]] && \ log_fail "$func: No secondary partition passed" [[ -d /$TESTPOOL ]] && $RM -rf /$TESTPOOL log_must $ZPOOL create -f $TESTPOOL mirror $@ log_must $ZFS create $TESTPOOL/$TESTFS log_must $ZFS set mountpoint=$TESTDIR $TESTPOOL/$TESTFS } # # create a number of mirrors. # We create a number($1) of 2 way mirrors using the pairs of disks named # on the command line. These mirrors are *not* mounted # @parameters: $1 the number of mirrors to create # $... the devices to use to create the mirrors on # @uses: ZPOOL ZFS TESTPOOL function setup_mirrors { typeset -i nmirrors=$1 shift while (( nmirrors > 0 )); do log_must test -n "$1" -a -n "$2" [[ -d /$TESTPOOL$nmirrors ]] && $RM -rf /$TESTPOOL$nmirrors log_must $ZPOOL create -f $TESTPOOL$nmirrors mirror $1 $2 shift 2 (( nmirrors = nmirrors - 1 )) done } # # create a number of raidz pools. # We create a number($1) of 2 raidz pools using the pairs of disks named # on the command line. These pools are *not* mounted # @parameters: $1 the number of pools to create # $... the devices to use to create the pools on # @uses: ZPOOL ZFS TESTPOOL function setup_raidzs { typeset -i nraidzs=$1 shift while (( nraidzs > 0 )); do log_must test -n "$1" -a -n "$2" [[ -d /$TESTPOOL$nraidzs ]] && $RM -rf /$TESTPOOL$nraidzs log_must $ZPOOL create -f $TESTPOOL$nraidzs raidz $1 $2 shift 2 (( nraidzs = nraidzs - 1 )) done } # # Destroy the configured testpool mirrors. # the mirrors are of the form ${TESTPOOL}{number} # @uses: ZPOOL ZFS TESTPOOL function destroy_mirrors { default_cleanup_noexit log_pass } # # Given a minimum of two disks, set up a storage pool and dataset for the raid-z # $1 the list of disks # function default_raidz_setup { typeset disklist="$*" set -A disks $disklist if [[ ${#disks[*]} -lt 2 ]]; then log_fail "A raid-z requires a minimum of two disks." fi [[ -d /$TESTPOOL ]] && $RM -rf /$TESTPOOL log_must $ZPOOL create -f $TESTPOOL raidz $1 $2 $3 log_must $ZFS create $TESTPOOL/$TESTFS log_must $ZFS set mountpoint=$TESTDIR $TESTPOOL/$TESTFS log_pass } # # Common function used to cleanup storage pools and datasets. # # Invoked at the start of the test suite to ensure the system # is in a known state, and also at the end of each set of # sub-tests to ensure errors from one set of tests doesn't # impact the execution of the next set. function default_cleanup { default_cleanup_noexit log_pass } function all_pools { cmd="$ZPOOL list -H -o name | $GREP -v '$NO_POOLS'" if [[ -n $KEEP ]]; then cmd="$cmd | $EGREP -v '(${KEEP})'" fi eval $cmd } function default_cleanup_noexit { typeset exclude="" typeset pool="" # # Destroying the pool will also destroy any # filesystems it contains. # if is_global_zone; then # Here, we loop through the pools we're allowed to # destroy, only destroying them if it's safe to do # so. for pool in $(all_pools); do if safe_to_destroy_pool $pool; then destroy_pool $pool fi done else typeset fs="" for fs in $($ZFS list -H -o name \ | $GREP "^$ZONE_POOL/$ZONE_CTR[01234]/"); do datasetexists $fs && \ log_must $ZFS destroy -Rf $fs done # Need cleanup here to avoid garbage dir left. for fs in $($ZFS list -H -o name \ ); do [[ $fs == /$ZONE_POOL ]] && continue [[ -d $fs ]] && log_must $RM -rf $fs/* done # # Reset the $ZONE_POOL/$ZONE_CTR[01234] file systems property to # the default value # for fs in $($ZFS list -H -o name \ ); do if [[ $fs == $ZONE_POOL/$ZONE_CTR[01234] ]]; then log_must $ZFS set reservation=none $fs log_must $ZFS set recordsize=128K $fs log_must $ZFS set mountpoint=/$fs $fs typeset enc="" enc=$(get_prop encryption $fs) if [[ $? -ne 0 ]] || [[ -z "$enc" ]] || \ [[ "$enc" == "off" ]]; then log_must $ZFS set checksum=on $fs fi log_must $ZFS set compression=off $fs log_must $ZFS set atime=on $fs log_must $ZFS set devices=off $fs log_must $ZFS set exec=on $fs log_must $ZFS set setuid=on $fs log_must $ZFS set readonly=off $fs log_must $ZFS set snapdir=hidden $fs log_must $ZFS set aclmode=groupmask $fs log_must $ZFS set aclinherit=secure $fs fi done fi [[ -d $TESTDIR ]] && \ log_must $RM -rf $TESTDIR } # # Common function used to cleanup storage pools, file systems # and containers. # function default_container_cleanup { if ! is_global_zone; then reexport_pool fi ismounted $TESTPOOL/$TESTCTR/$TESTFS1 [[ $? -eq 0 ]] && \ log_must $ZFS unmount $TESTPOOL/$TESTCTR/$TESTFS1 datasetexists $TESTPOOL/$TESTCTR/$TESTFS1 && \ log_must $ZFS destroy -R $TESTPOOL/$TESTCTR/$TESTFS1 datasetexists $TESTPOOL/$TESTCTR && \ log_must $ZFS destroy -Rf $TESTPOOL/$TESTCTR [[ -e $TESTDIR1 ]] && \ log_must $RM -rf $TESTDIR1 > /dev/null 2>&1 default_cleanup } # # Common function used to cleanup snapshot of file system or volume. Default to # delete the file system's snapshot # # $1 snapshot name # function destroy_snapshot { typeset snap=${1:-$TESTPOOL/$TESTFS@$TESTSNAP} if ! snapexists $snap; then log_fail "'$snap' does not existed." fi # # For the sake of the value which come from 'get_prop' is not equal # to the really mountpoint when the snapshot is unmounted. So, firstly # check and make sure this snapshot's been mounted in current system. # typeset mtpt="" if ismounted $snap; then mtpt=$(get_prop mountpoint $snap) (( $? != 0 )) && \ log_fail "get_prop mountpoint $snap failed." fi log_must $ZFS destroy $snap [[ $mtpt != "" && -d $mtpt ]] && \ log_must $RM -rf $mtpt } # # Common function used to cleanup clone. # # $1 clone name # function destroy_clone { typeset clone=${1:-$TESTPOOL/$TESTCLONE} if ! datasetexists $clone; then log_fail "'$clone' does not existed." fi # With the same reason in destroy_snapshot typeset mtpt="" if ismounted $clone; then mtpt=$(get_prop mountpoint $clone) (( $? != 0 )) && \ log_fail "get_prop mountpoint $clone failed." fi log_must $ZFS destroy $clone [[ $mtpt != "" && -d $mtpt ]] && \ log_must $RM -rf $mtpt } # Return 0 if a snapshot exists; $? otherwise # # $1 - snapshot name function snapexists { $ZFS list -H -t snapshot "$1" > /dev/null 2>&1 return $? } # # Set a property to a certain value on a dataset. # Sets a property of the dataset to the value as passed in. # @param: # $1 dataset who's property is being set # $2 property to set # $3 value to set property to # @return: # 0 if the property could be set. # non-zero otherwise. # @use: ZFS # function dataset_setprop { typeset fn=dataset_setprop if (( $# < 3 )); then log_note "$fn: Insufficient parameters (need 3, had $#)" return 1 fi typeset output= output=$($ZFS set $2=$3 $1 2>&1) typeset rv=$? if (( rv != 0 )); then log_note "Setting property on $1 failed." log_note "property $2=$3" log_note "Return Code: $rv" log_note "Output: $output" return $rv fi return 0 } # # Assign suite defined dataset properties. # This function is used to apply the suite's defined default set of # properties to a dataset. # @parameters: $1 dataset to use # @uses: ZFS COMPRESSION_PROP CHECKSUM_PROP # @returns: # 0 if the dataset has been altered. # 1 if no pool name was passed in. # 2 if the dataset could not be found. # 3 if the dataset could not have it's properties set. # function dataset_set_defaultproperties { typeset dataset="$1" [[ -z $dataset ]] && return 1 typeset confset= typeset -i found=0 for confset in $($ZFS list); do if [[ $dataset = $confset ]]; then found=1 break fi done [[ $found -eq 0 ]] && return 2 if [[ -n $COMPRESSION_PROP ]]; then dataset_setprop $dataset compression $COMPRESSION_PROP || \ return 3 log_note "Compression set to '$COMPRESSION_PROP' on $dataset" fi if [[ -n $CHECKSUM_PROP && $WRAPPER != *"crypto"* ]]; then dataset_setprop $dataset checksum $CHECKSUM_PROP || \ return 3 log_note "Checksum set to '$CHECKSUM_PROP' on $dataset" fi return 0 } # # Check a numeric assertion # @parameter: $@ the assertion to check # @output: big loud notice if assertion failed # @use: log_fail # function assert { (( $@ )) || log_fail $@ } function wipe_partition_table # [ ...] { while [[ -n $* ]]; do typeset diskname=$1 - $GPART destroy -F $diskname >/dev/null 2>&1 + [ ! -e $diskname ] && log_fail "ERROR: $diskname doesn't exist" + if gpart list $(basename $diskname) >/dev/null 2>&1; then + log_must $GPART destroy -F $diskname + else + log_note "No GPT partitions detected on $diskname" + fi + log_must $GPART create -s gpt $diskname shift done } # # Given a slice, size and disk, this function # formats the slice to the specified size. # Size should be specified with units as per # the `format` command requirements eg. 100mb 3gb # function set_partition # { typeset -i slicenum=$1 typeset start=$2 typeset size=$3 typeset disk=$4 set -A devmap a b c d e f g h [[ -z $slicenum || -z $size || -z $disk ]] && \ log_fail "The slice, size or disk name is unspecified." size=`$ECHO $size| sed s/mb/M/` size=`$ECHO $size| sed s/m/M/` size=`$ECHO $size| sed s/gb/G/` size=`$ECHO $size| sed s/g/G/` [[ -n $start ]] && start="-b $start" - # Ignore the return value; it will fail if $disk is already partitioned - $GPART create -s GPT $disk > /dev/null 2>&1 log_must $GPART add -t efi $start -s $size -i $slicenum $disk return 0 } function get_disk_size # { typeset disk=$1 diskinfo da0 | awk '{print $3}' } function get_available_disk_size # { typeset disk=$1 raw_size=`get_disk_size $disk` (( available_size = raw_size * 95 / 100 )) echo $available_size } # # Get the end cyl of the given slice # #TODO: fix this to be GPT-compatible if we want to use the SMI WRAPPER. This # function is not necessary on FreeBSD # function get_endslice # { log_fail "get_endslice has not been updated for GPT partitions" } # # Get the first LBA that is beyond the end of the given partition function get_partition_end # { typeset disk=$1 typeset partition_index=$2 export partition_index $GPART show $disk | $AWK \ '/^[ \t]/ && $3 ~ ENVIRON["partition_index"] {print $1 + $2}' } # # Given a size,disk and total number of partitions, this function formats the # disk partitions from 0 to the total partition number with the same specified # size. # function partition_disk # { typeset -i i=1 typeset part_size=$1 typeset disk_name=$2 typeset total_parts=$3 typeset cyl wipe_partition_table $disk_name while (( i <= $total_parts )); do set_partition $i "" $part_size $disk_name (( i = i+1 )) done } function size_of_file # fname { typeset fname=$1 sz=`stat -f '%z' $fname` [[ -z "$sz" ]] && log_fail "stat($fname) failed" $ECHO $sz return 0 } # # This function continues to write to a filenum number of files into dirnum # number of directories until either $FILE_WRITE returns an error or the # maximum number of files per directory have been written. # # Usage: # fill_fs [destdir] [dirnum] [filenum] [bytes] [num_writes] [data] # # Return value: 0 on success # non 0 on error # # Where : # destdir: is the directory where everything is to be created under # dirnum: the maximum number of subdirectories to use, -1 no limit # filenum: the maximum number of files per subdirectory # bytes: number of bytes to write # num_writes: numer of types to write out bytes # data: the data that will be writen # # E.g. # file_fs /testdir 20 25 1024 256 0 # # Note: bytes * num_writes equals the size of the testfile # function fill_fs # destdir dirnum filenum bytes num_writes data { typeset destdir=${1:-$TESTDIR} typeset -i dirnum=${2:-50} typeset -i filenum=${3:-50} typeset -i bytes=${4:-8192} typeset -i num_writes=${5:-10240} typeset -i data=${6:-0} typeset -i odirnum=1 typeset -i idirnum=0 typeset -i fn=0 typeset -i retval=0 log_must $MKDIR -p $destdir/$idirnum while (( $odirnum > 0 )); do if (( dirnum >= 0 && idirnum >= dirnum )); then odirnum=0 break fi $FILE_WRITE -o create -f $destdir/$idirnum/$TESTFILE.$fn \ -b $bytes -c $num_writes -d $data retval=$? if (( $retval != 0 )); then odirnum=0 break fi if (( $fn >= $filenum )); then fn=0 (( idirnum = idirnum + 1 )) log_must $MKDIR -p $destdir/$idirnum else (( fn = fn + 1 )) fi done return $retval } # # Simple function to get the specified property. If unable to # get the property then exits. # # Note property is in 'parsable' format (-p) # function get_prop # property dataset { typeset prop_val typeset prop=$1 typeset dataset=$2 prop_val=$($ZFS get -pH -o value $prop $dataset 2>/dev/null) if [[ $? -ne 0 ]]; then log_note "Unable to get $prop property for dataset " \ "$dataset" return 1 fi $ECHO $prop_val return 0 } # # Simple function to return the lesser of two values. # function min { typeset first_arg=$1 typeset second_arg=$2 if (( first_arg < second_arg )); then $ECHO $first_arg else $ECHO $second_arg fi return 0 } # # Simple function to get the specified property of pool. If unable to # get the property then exits. # function get_pool_prop # property pool { typeset prop_val typeset prop=$1 typeset pool=$2 if poolexists $pool ; then prop_val=$($ZPOOL get $prop $pool 2>/dev/null | $TAIL -1 | \ $AWK '{print $3}') if [[ $? -ne 0 ]]; then log_note "Unable to get $prop property for pool " \ "$pool" return 1 fi else log_note "Pool $pool not exists." return 1 fi $ECHO $prop_val return 0 } # Return 0 if a pool exists; $? otherwise # # $1 - pool name function poolexists { typeset pool=$1 if [[ -z $pool ]]; then log_note "No pool name given." return 1 fi $ZPOOL list -H "$pool" > /dev/null 2>&1 return $? } # Return 0 if all the specified datasets exist; $? otherwise # # $1-n dataset name function datasetexists { if (( $# == 0 )); then log_note "No dataset name given." return 1 fi while (( $# > 0 )); do $ZFS list -H -t filesystem,snapshot,volume $1 > /dev/null 2>&1 || \ return $? shift done return 0 } # return 0 if none of the specified datasets exists, otherwise return 1. # # $1-n dataset name function datasetnonexists { if (( $# == 0 )); then log_note "No dataset name given." return 1 fi while (( $# > 0 )); do $ZFS list -H -t filesystem,snapshot,volume $1 > /dev/null 2>&1 && \ return 1 shift done return 0 } # # Given a mountpoint, or a dataset name, determine if it is shared. # # Returns 0 if shared, 1 otherwise. # function is_shared { typeset fs=$1 typeset mtpt if [[ $fs != "/"* ]] ; then if datasetnonexists "$fs" ; then return 1 else mtpt=$(get_prop mountpoint "$fs") case $mtpt in none|legacy|-) return 1 ;; *) fs=$mtpt ;; esac fi fi for mtpt in `$SHARE | $AWK '{print $2}'` ; do if [[ $mtpt == $fs ]] ; then return 0 fi done typeset stat=$($SVCS -H -o STA nfs/server:default) if [[ $stat != "ON" ]]; then log_note "Current nfs/server status: $stat" fi return 1 } # # Given a mountpoint, determine if it is not shared. # # Returns 0 if not shared, 1 otherwise. # function not_shared { typeset fs=$1 is_shared $fs if (( $? == 0)); then return 1 fi return 0 } # # Helper function to unshare a mountpoint. # function unshare_fs #fs { typeset fs=$1 is_shared $fs if (( $? == 0 )); then log_must $ZFS unshare $fs fi return 0 } # # Check NFS server status and trigger it online. # function setup_nfs_server { # Cannot share directory in non-global zone. # if ! is_global_zone; then log_note "Cannot trigger NFS server by sharing in LZ." return fi typeset nfs_fmri="svc:/network/nfs/server:default" if [[ $($SVCS -Ho STA $nfs_fmri) != "ON" ]]; then # # Only really sharing operation can enable NFS server # to online permanently. # typeset dummy=$TMPDIR/dummy if [[ -d $dummy ]]; then log_must $RM -rf $dummy fi log_must $MKDIR $dummy log_must $SHARE $dummy # # Waiting for fmri's status to be the final status. # Otherwise, in transition, an asterisk (*) is appended for # instances, unshare will reverse status to 'DIS' again. # # Waiting for 1's at least. # log_must $SLEEP 1 timeout=10 while [[ timeout -ne 0 && $($SVCS -Ho STA $nfs_fmri) == *'*' ]] do log_must $SLEEP 1 (( timeout -= 1 )) done log_must $UNSHARE $dummy log_must $RM -rf $dummy fi log_note "Current NFS status: '$($SVCS -Ho STA,FMRI $nfs_fmri)'" } # # To verify whether calling process is in global zone # # Return 0 if in global zone, 1 in non-global zone # function is_global_zone { typeset cur_zone=$($ZONENAME 2>/dev/null) # Zones are not supported on FreeBSD. if [[ $os_name == "FreeBSD" ]]; then return 0 fi if [[ $cur_zone != "global" ]]; then return 1 fi return 0 } # # Verify whether test is permit to run from # global zone, local zone, or both # # $1 zone limit, could be "global", "local", or "both"(no limit) # # Return 0 if permit, otherwise exit with log_unsupported # function verify_runnable # zone limit { typeset limit=$1 [[ -z $limit ]] && return 0 if is_global_zone ; then case $limit in global|both) break ;; local) log_unsupported "Test is unable to run from \ global zone." break ;; *) log_note "Warning: unknown limit $limit - use both." ;; esac else case $limit in local|both) break ;; global) log_unsupported "Test is unable to run from \ local zone." break ;; *) log_note "Warning: unknown limit $limit - use both." ;; esac reexport_pool fi return 0 } # Return 0 if create successfully or the pool exists; $? otherwise # Note: In local zones, this function should return 0 silently. # # $1 - pool name # $2-n - [keyword] devs_list function create_pool #pool devs_list { typeset pool=${1%%/*} shift if [[ -z $pool ]]; then log_note "Missing pool name." return 1 fi if poolexists $pool ; then destroy_pool $pool fi if is_global_zone ; then [[ -d /$pool ]] && $RM -rf /$pool log_must $ZPOOL create -f $pool $@ fi return 0 } # Return 0 if destroy successfully or the pool exists; $? otherwise # Note: In local zones, this function should return 0 silently. # # $1 - pool name # Destroy pool with the given parameters. function destroy_pool #pool { typeset pool=${1%%/*} typeset mtpt if [[ -z $pool ]]; then log_note "No pool name given." return 1 fi if is_global_zone ; then if poolexists "$pool" ; then mtpt=$(get_prop mountpoint "$pool") log_must $ZPOOL destroy -f $pool [[ -d $mtpt ]] && \ log_must $RM -rf $mtpt else log_note "Pool $pool does not exist, skipping destroy." return 1 fi fi return 0 } # # Firstly, create a pool with 5 datasets. Then, create a single zone and # export the 5 datasets to it. In addition, we also add a ZFS filesystem # and a zvol device to the zone. # # $1 zone name # $2 zone root directory prefix # $3 zone ip # function zfs_zones_setup #zone_name zone_root zone_ip { typeset zone_name=${1:-$(hostname)-z} typeset zone_root=${2:-"/zone_root"} typeset zone_ip=${3:-"10.1.1.10"} typeset prefix_ctr=$ZONE_CTR typeset pool_name=$ZONE_POOL typeset -i cntctr=5 typeset -i i=0 # Create pool and 5 container within it # [[ -d /$pool_name ]] && $RM -rf /$pool_name log_must $ZPOOL create -f $pool_name $DISKS while (( i < cntctr )); do log_must $ZFS create $pool_name/$prefix_ctr$i (( i += 1 )) done # create a zvol log_must $ZFS create -V 1g $pool_name/zone_zvol # # If current system support slog, add slog device for pool # if verify_slog_support ; then typeset sdevs="$TMPDIR/sdev1 $TMPDIR/sdev2" log_must $MKFILE 100M $sdevs log_must $ZPOOL add $pool_name log mirror $sdevs fi # this isn't supported just yet. # Create a filesystem. In order to add this to # the zone, it must have it's mountpoint set to 'legacy' # log_must $ZFS create $pool_name/zfs_filesystem # log_must $ZFS set mountpoint=legacy $pool_name/zfs_filesystem [[ -d $zone_root ]] && \ log_must $RM -rf $zone_root/$zone_name [[ ! -d $zone_root ]] && \ log_must $MKDIR -p -m 0700 $zone_root/$zone_name # Create zone configure file and configure the zone # typeset zone_conf=$TMPDIR/zone_conf.${TESTCASE_ID} $ECHO "create" > $zone_conf $ECHO "set zonepath=$zone_root/$zone_name" >> $zone_conf $ECHO "set autoboot=true" >> $zone_conf i=0 while (( i < cntctr )); do $ECHO "add dataset" >> $zone_conf $ECHO "set name=$pool_name/$prefix_ctr$i" >> \ $zone_conf $ECHO "end" >> $zone_conf (( i += 1 )) done # add our zvol to the zone $ECHO "add device" >> $zone_conf $ECHO "set match=/dev/zvol/dsk/$pool_name/zone_zvol" >> $zone_conf $ECHO "end" >> $zone_conf # add a corresponding zvol rdsk to the zone $ECHO "add device" >> $zone_conf $ECHO "set match=/dev/zvol/rdsk/$pool_name/zone_zvol" >> $zone_conf $ECHO "end" >> $zone_conf # once it's supported, we'll add our filesystem to the zone # $ECHO "add fs" >> $zone_conf # $ECHO "set type=zfs" >> $zone_conf # $ECHO "set special=$pool_name/zfs_filesystem" >> $zone_conf # $ECHO "set dir=/export/zfs_filesystem" >> $zone_conf # $ECHO "end" >> $zone_conf $ECHO "verify" >> $zone_conf $ECHO "commit" >> $zone_conf log_must $ZONECFG -z $zone_name -f $zone_conf log_must $RM -f $zone_conf # Install the zone $ZONEADM -z $zone_name install if (( $? == 0 )); then log_note "SUCCESS: $ZONEADM -z $zone_name install" else log_fail "FAIL: $ZONEADM -z $zone_name install" fi # Install sysidcfg file # typeset sysidcfg=$zone_root/$zone_name/root/etc/sysidcfg $ECHO "system_locale=C" > $sysidcfg $ECHO "terminal=dtterm" >> $sysidcfg $ECHO "network_interface=primary {" >> $sysidcfg $ECHO "hostname=$zone_name" >> $sysidcfg $ECHO "}" >> $sysidcfg $ECHO "name_service=NONE" >> $sysidcfg $ECHO "root_password=mo791xfZ/SFiw" >> $sysidcfg $ECHO "security_policy=NONE" >> $sysidcfg $ECHO "timezone=US/Eastern" >> $sysidcfg # Boot this zone log_must $ZONEADM -z $zone_name boot } # # Reexport TESTPOOL & TESTPOOL(1-4) # function reexport_pool { typeset -i cntctr=5 typeset -i i=0 while (( i < cntctr )); do if (( i == 0 )); then TESTPOOL=$ZONE_POOL/$ZONE_CTR$i if ! ismounted $TESTPOOL; then log_must $ZFS mount $TESTPOOL fi else eval TESTPOOL$i=$ZONE_POOL/$ZONE_CTR$i if eval ! ismounted \$TESTPOOL$i; then log_must eval $ZFS mount \$TESTPOOL$i fi fi (( i += 1 )) done } # # Verify a given disk is online or offline # # Return 0 is pool/disk matches expected state, 1 otherwise # function check_state # pool disk state{online,offline} { typeset pool=$1 typeset disk=${2#/dev/dsk/} disk=${disk#/dev/rdsk/} disk=${disk#/dev/} typeset state=$3 $ZPOOL status -v $pool | grep "$disk" \ | grep -i "$state" > /dev/null 2>&1 return $? } # # Wait for a given disk to leave a state # function wait_for_state_exit { typeset pool=$1 typeset disk=$2 typeset state=$3 while check_state "$pool" "$disk" "$state"; do $SLEEP 1 done } # # Get the mountpoint of snapshot # as its mountpoint # function snapshot_mountpoint { typeset dataset=${1:-$TESTPOOL/$TESTFS@$TESTSNAP} if [[ $dataset != *@* ]]; then log_fail "Error name of snapshot '$dataset'." fi typeset fs=${dataset%@*} typeset snap=${dataset#*@} if [[ -z $fs || -z $snap ]]; then log_fail "Error name of snapshot '$dataset'." fi $ECHO $(get_prop mountpoint $fs)/$(get_snapdir_name)/$snap } function pool_maps_intact # pool { typeset pool="$1" if ! $ZDB -bcv $pool; then return 1 fi return 0 } function filesys_has_zil # filesystem { typeset filesys="$1" if ! $ZDB -ivv $filesys | $GREP "ZIL header"; then return 1 fi return 0 } # # Given a pool and file system, this function will verify the file system # using the zdb internal tool. Note that the pool is exported and imported # to ensure it has consistent state. # function verify_filesys # pool filesystem dir { typeset pool="$1" typeset filesys="$2" typeset zdbout="$TMPDIR/zdbout.${TESTCASE_ID}" shift shift typeset dirs=$@ typeset search_path="" log_note "Calling $ZDB to verify filesystem '$filesys'" log_must $ZPOOL export $pool if [[ -n $dirs ]] ; then for dir in $dirs ; do search_path="$search_path -d $dir" done fi log_must $ZPOOL import $search_path $pool $ZDB -cudi $filesys > $zdbout 2>&1 if [[ $? != 0 ]]; then log_note "Output: $ZDB -cudi $filesys" $CAT $zdbout log_fail "$ZDB detected errors with: '$filesys'" fi log_must $RM -rf $zdbout } # # Given a pool, and this function list all disks in the pool # function get_disklist # pool { typeset disklist="" disklist=$($ZPOOL iostat -v $1 | $NAWK '(NR >4 ) {print $1}' | \ $GREP -v "\-\-\-\-\-" | \ $EGREP -v -e "^(mirror|raidz1|raidz2|spare|log|cache)$" ) $ECHO $disklist } # # Destroy all existing metadevices and state database # function destroy_metas { typeset metad for metad in $($METASTAT -p | $AWK '{print $1}'); do log_must $METACLEAR -rf $metad done for metad in $($METADB | $CUT -f6 | $GREP dev | $UNIQ); do log_must $METADB -fd $metad done } # /** # This function kills a given list of processes after a time period. We use # this in the stress tests instead of STF_TIMEOUT so that we can have processes # run for a fixed amount of time, yet still pass. Tests that hit STF_TIMEOUT # would be listed as FAIL, which we don't want : we're happy with stress tests # running for a certain amount of time, then finishing. # # @param $1 the time in seconds after which we should terminate these processes # @param $2..$n the processes we wish to terminate. # */ function stress_timeout { typeset -i TIMEOUT=$1 shift typeset cpids="$@" log_note "Waiting for child processes($cpids). " \ "It could last dozens of minutes, please be patient ..." log_must $SLEEP $TIMEOUT log_note "Killing child processes after ${TIMEOUT} stress timeout." typeset pid for pid in $cpids; do $PS -p $pid > /dev/null 2>&1 if (( $? == 0 )); then log_must $KILL -USR1 $pid fi done } # # Check whether current OS support a specified feature or not # # return 0 if current OS version is in unsupported list, 1 otherwise # # $1 unsupported target OS versions # function check_version # { typeset unsupported_vers="$@" typeset ver typeset cur_ver=`$UNAME -r` for ver in $unsupported_vers; do [[ "$cur_ver" == "$ver" ]] && return 0 done return 1 } # # Verify a given hotspare disk is inuse or avail # # Return 0 is pool/disk matches expected state, 1 otherwise # function check_hotspare_state # pool disk state{inuse,avail} { typeset pool=$1 typeset disk=${2#/dev/dsk/} disk=${disk#/dev/rdsk/} disk=${disk#/dev/} typeset state=$3 cur_state=$(get_device_state $pool $disk "spares") if [[ $state != ${cur_state} ]]; then return 1 fi return 0 } # # Verify a given slog disk is inuse or avail # # Return 0 is pool/disk matches expected state, 1 otherwise # function check_slog_state # pool disk state{online,offline,unavail} { typeset pool=$1 typeset disk=${2#/dev/dsk/} disk=${disk#/dev/rdsk/} disk=${disk#/dev/} typeset state=$3 cur_state=$(get_device_state $pool $disk "logs") if [[ $state != ${cur_state} ]]; then return 1 fi return 0 } # # Verify a given vdev disk is inuse or avail # # Return 0 is pool/disk matches expected state, 1 otherwise # function check_vdev_state # pool disk state{online,offline,unavail} { typeset pool=$1 typeset disk=${2#/dev/dsk/} disk=${disk#/dev/rdsk/} disk=${disk#/dev/} typeset state=$3 if [[ $WRAPPER == *"smi"* ]]; then $ECHO $disk | $EGREP "^c[0-F]+([td][0-F]+)+$" > /dev/null 2>&1 if (( $? == 0 )); then disk=${disk}s2 fi fi cur_state=$(get_device_state $pool $disk) if [[ $state != ${cur_state} ]]; then return 1 fi return 0 } # # Check the output of 'zpool status -v ', # and to see if the content of contain the specified. # # Return 0 is contain, 1 otherwise # function check_pool_status # pool token keyword { typeset pool=$1 typeset token=$2 typeset keyword=$3 $ZPOOL status -v "$pool" 2>/dev/null | \ $NAWK -v token="$token:" '($1==token) {print $0}' | \ $GREP -i "$keyword" >/dev/null 2>&1 return $? } # # These 5 following functions are instance of check_pool_status() # is_pool_resilvering - to check if the pool is resilver in progress # is_pool_resilvered - to check if the pool is resilver completed # is_pool_scrubbing - to check if the pool is scrub in progress # is_pool_scrubbed - to check if the pool is scrub completed # is_pool_scrub_stopped - to check if the pool is scrub stopped # function is_pool_resilvering #pool { check_pool_status "$1" "scan" "resilver in progress" return $? } function is_pool_resilvered #pool { check_pool_status "$1" "scan" "resilvered" return $? } function is_pool_scrubbing #pool { check_pool_status "$1" "scan" "scrub in progress" return $? } function is_pool_scrubbed #pool { check_pool_status "$1" "scan" "scrub repaired" return $? } function is_pool_scrub_stopped #pool { check_pool_status "$1" "scan" "scrub canceled" return $? } # # Erase the partition tables and destroy any zfs labels # function cleanup_devices #vdevs { for device in $@; do - wipe_partition_table $device - $ZPOOL labelclear -f $device + # Labelclear must happen first, otherwise it may interfere + # with the teardown/setup of GPT labels. + log_must $ZPOOL labelclear -f $device + # Only wipe partition tables for arguments that are disks, + # as opposed to slices (which are valid arguments here). + if camcontrol inquiry $device >/dev/null 2>&1; then + wipe_partition_table $device + fi done return 0 } # # Verify the rsh connectivity to each remote host in RHOSTS. # # Return 0 if remote host is accessible; otherwise 1. # $1 remote host name # $2 username # function verify_rsh_connect #rhost, username { typeset rhost=$1 typeset username=$2 typeset rsh_cmd="$RSH -n" typeset cur_user= $GETENT hosts $rhost >/dev/null 2>&1 if (( $? != 0 )); then log_note "$rhost cannot be found from" \ "administrative database." return 1 fi $PING $rhost 3 >/dev/null 2>&1 if (( $? != 0 )); then log_note "$rhost is not reachable." return 1 fi if (( ${#username} != 0 )); then rsh_cmd="$rsh_cmd -l $username" cur_user="given user \"$username\"" else cur_user="current user \"`$LOGNAME`\"" fi if ! $rsh_cmd $rhost $TRUE; then log_note "$RSH to $rhost is not accessible" \ "with $cur_user." return 1 fi return 0 } # # Verify the remote host connection via rsh after rebooting # $1 remote host # function verify_remote { rhost=$1 # # The following loop waits for the remote system rebooting. # Each iteration will wait for 150 seconds. there are # total 5 iterations, so the total timeout value will # be 12.5 minutes for the system rebooting. This number # is an approxiate number. # typeset -i count=0 while ! verify_rsh_connect $rhost; do sleep 150 (( count = count + 1 )) if (( count > 5 )); then return 1 fi done return 0 } # # Replacement function for /usr/bin/rsh. This function will include # the /usr/bin/rsh and meanwhile return the execution status of the # last command. # # $1 usrname passing down to -l option of /usr/bin/rsh # $2 remote machine hostname # $3... command string # function rsh_status { typeset ruser=$1 typeset rhost=$2 typeset -i ret=0 typeset cmd_str="" typeset rsh_str="" shift; shift cmd_str="$@" err_file=$TMPDIR/${rhost}.${TESTCASE_ID}.err if (( ${#ruser} == 0 )); then rsh_str="$RSH -n" else rsh_str="$RSH -n -l $ruser" fi $rsh_str $rhost /usr/local/bin/ksh93 -c "'$cmd_str; \ print -u 2 \"status=\$?\"'" \ >/dev/null 2>$err_file ret=$? if (( $ret != 0 )); then $CAT $err_file $RM -f $std_file $err_file log_fail "$RSH itself failed with exit code $ret..." fi ret=$($GREP -v 'print -u 2' $err_file | $GREP 'status=' | \ $CUT -d= -f2) (( $ret != 0 )) && $CAT $err_file >&2 $RM -f $err_file >/dev/null 2>&1 return $ret } # # Get the SUNWstc-fs-zfs package installation path in a remote host # $1 remote host name # function get_remote_pkgpath { typeset rhost=$1 typeset pkgpath="" pkgpath=$($RSH -n $rhost "$PKGINFO -l SUNWstc-fs-zfs | $GREP BASEDIR: |\ $CUT -d: -f2") $ECHO $pkgpath } #/** # A function to find and locate free disks on a system or from given # disks as the parameter. Since the conversion to ATF, this function is # superfluous; it is assumed that the user will supply an accurate list of # disks to use. So we just return the arguments. # # $@ given disks to find which are free # # @return a string containing the list of available disks #*/ function find_disks { (( first=0 )) for disk in $@; do [[ $first == 1 ]] && echo -n " " (( first=1 )) case $disk in /dev/*) echo -n "$disk" ;; *) echo -n "/dev/$disk" ;; esac done } # A function to set convenience variables for disks. function set_disks { set -A disk_array $(find_disks $DISKS) [[ -z "$DISK_ARRAY_LIMIT" ]] && typeset -i DISK_ARRAY_LIMIT=5 if (( ${#disk_array[*]} <= 1 )); then export DISK=${DISKS%% *} else export DISK="" typeset -i i=0 while (( i < ${#disk_array[*]} && i <= $DISK_ARRAY_LIMIT )); do export DISK${i}="${disk_array[$i]}" DISKSARRAY="$DISKSARRAY ${disk_array[$i]}" (( i = i + 1 )) done export DISK_ARRAY_NUM=$i export DISKSARRAY fi if (( $DISK_ARRAY_NUM == 0 )); then export disk=$DISK else export disk=$DISK0 fi } # # Add specified user to specified group # # $1 group name # $2 user name # function add_user # { typeset gname=$1 typeset uname=$2 if (( ${#gname} == 0 || ${#uname} == 0 )); then log_fail "group name or user name are not defined." fi # Check to see if the user exists. $ID $uname > /dev/null 2>&1 && return 0 # Assign 1000 as the base uid typeset -i uid=1000 while true; do typeset -i ret $USERADD -u $uid -g $gname -d /var/tmp/$uname -m $uname ret=$? case $ret in 0) return 0 ;; # The uid is not unique 65) ((uid += 1)) ;; *) return 1 ;; esac if [[ $uid == 65000 ]]; then log_fail "No user id available under 65000 for $uname" fi done return 0 } # # Delete the specified user. # # $1 login name # function del_user # { typeset user=$1 if (( ${#user} == 0 )); then log_fail "login name is necessary." fi if $ID $user > /dev/null 2>&1; then log_must $USERDEL $user fi return 0 } # # Select valid gid and create specified group. # # $1 group name # function add_group # { typeset group=$1 if (( ${#group} == 0 )); then log_fail "group name is necessary." fi # See if the group already exists. $GROUPSHOW $group >/dev/null 2>&1 [[ $? == 0 ]] && return 0 # Assign 100 as the base gid typeset -i gid=100 while true; do $GROUPADD -g $gid $group > /dev/null 2>&1 typeset -i ret=$? case $ret in 0) return 0 ;; # The gid is not unique 65) ((gid += 1)) ;; *) return 1 ;; esac if [[ $gid == 65000 ]]; then log_fail "No user id available under 65000 for $group" fi done } # # Delete the specified group. # # $1 group name # function del_group # { typeset grp=$1 if (( ${#grp} == 0 )); then log_fail "group name is necessary." fi $GROUPDEL -n $grp > /dev/null 2>&1 typeset -i ret=$? case $ret in # Group does not exist, or was deleted successfully. 0|6|65) return 0 ;; # Name already exists as a group name 9) log_must $GROUPDEL $grp ;; *) return 1 ;; esac return 0 } # # This function will return true if it's safe to destroy the pool passed # as argument 1. It checks for pools based on zvols and files, and also # files contained in a pool that may have a different mountpoint. # function safe_to_destroy_pool { # $1 the pool name typeset pool="" typeset DONT_DESTROY="" # We check that by deleting the $1 pool, we're not # going to pull the rug out from other pools. Do this # by looking at all other pools, ensuring that they # aren't built from files or zvols contained in this pool. for pool in $($ZPOOL list -H -o name) do ALTMOUNTPOOL="" # this is a list of the top-level directories in each of the files # that make up the path to the files the pool is based on FILEPOOL=$($ZPOOL status -v $pool | $GREP /$1/ | \ $AWK '{print $1}') # this is a list of the zvols that make up the pool ZVOLPOOL=$($ZPOOL status -v $pool | $GREP "/dev/zvol/dsk/$1$" | \ $AWK '{print $1}') # also want to determine if it's a file-based pool using an # alternate mountpoint... POOL_FILE_DIRS=$($ZPOOL status -v $pool | \ $GREP / | $AWK '{print $1}' | \ $AWK -F/ '{print $2}' | $GREP -v "dev") for pooldir in $POOL_FILE_DIRS do OUTPUT=$($ZFS list -H -r -o mountpoint $1 | \ $GREP "${pooldir}$" | $AWK '{print $1}') ALTMOUNTPOOL="${ALTMOUNTPOOL}${OUTPUT}" done if [ ! -z "$ZVOLPOOL" ] then DONT_DESTROY="true" log_note "Pool $pool is built from $ZVOLPOOL on $1" fi if [ ! -z "$FILEPOOL" ] then DONT_DESTROY="true" log_note "Pool $pool is built from $FILEPOOL on $1" fi if [ ! -z "$ALTMOUNTPOOL" ] then DONT_DESTROY="true" log_note "Pool $pool is built from $ALTMOUNTPOOL on $1" fi done if [ -z "${DONT_DESTROY}" ] then return 0 else log_note "Warning: it is not safe to destroy $1!" return 1 fi } # # Get IP address of hostname # $1 hostname # function getipbyhost { typeset ip ip=`$ARP $1 2>/dev/null | $AWK -F\) '{print $1}' \ | $AWK -F\( '{print $2}'` $ECHO $ip } # # Setup iSCSI initiator to target # $1 target hostname # function iscsi_isetup { # check svc:/network/iscsi_initiator:default state, try to enable it # if the state is not ON typeset ISCSII_FMRI="svc:/network/iscsi_initiator:default" if [[ "ON" != $($SVCS -H -o sta $ISCSII_FMRI) ]]; then log_must $SVCADM enable $ISCSII_FMRI typeset -i retry=20 while [[ "ON" != $($SVCS -H -o sta $ISCSII_FMRI) && \ ( $retry -ne 0 ) ]] do (( retry = retry - 1 )) $SLEEP 1 done if [[ "ON" != $($SVCS -H -o sta $ISCSII_FMRI) ]]; then log_fail "$ISCSII_FMRI service can not be enabled!" fi fi log_must $ISCSIADM add discovery-address $(getipbyhost $1) log_must $ISCSIADM modify discovery --sendtargets enable log_must $DEVFSADM -i iscsi } # # Check whether iscsi parameter is set as remote # # return 0 if iscsi is set as remote, otherwise 1 # function check_iscsi_remote { if [[ $iscsi == "remote" ]] ; then return 0 else return 1 fi } # # Check if a volume is a valide iscsi target # $1 volume name # return 0 if suceeds, otherwise, return 1 # function is_iscsi_target { typeset dataset=$1 typeset target targets [[ -z $dataset ]] && return 1 targets=$($ISCSITADM list target | $GREP "Target:" | $AWK '{print $2}') [[ -z $targets ]] && return 1 for target in $targets; do [[ $dataset == $target ]] && return 0 done return 1 } # # Get the iSCSI name of a target # $1 target name # function iscsi_name { typeset target=$1 typeset name [[ -z $target ]] && log_fail "No parameter." if ! is_iscsi_target $target ; then log_fail "Not a target." fi name=$($ISCSITADM list target $target | $GREP "iSCSI Name:" \ | $AWK '{print $2}') return $name } # # check svc:/system/iscsitgt:default state, try to enable it if the state # is not ON # function iscsitgt_setup { log_must $RM -f $ISCSITGTFILE if [[ "ON" == $($SVCS -H -o sta $ISCSITGT_FMRI) ]]; then log_note "iscsitgt is already enabled" return fi log_must $SVCADM enable -t $ISCSITGT_FMRI typeset -i retry=20 while [[ "ON" != $($SVCS -H -o sta $ISCSITGT_FMRI) && \ ( $retry -ne 0 ) ]] do $SLEEP 1 (( retry = retry - 1 )) done if [[ "ON" != $($SVCS -H -o sta $ISCSITGT_FMRI) ]]; then log_fail "$ISCSITGT_FMRI service can not be enabled!" fi log_must $TOUCH $ISCSITGTFILE } # # set DISABLED state of svc:/system/iscsitgt:default # which is the most suiteable state if $ISCSITGTFILE exists # function iscsitgt_cleanup { if [[ -e $ISCSITGTFILE ]]; then log_must $SVCADM disable $ISCSITGT_FMRI log_must $RM -f $ISCSITGTFILE fi } # # Close iSCSI initiator to target # $1 target hostname # function iscsi_iclose { log_must $ISCSIADM modify discovery --sendtargets disable log_must $ISCSIADM remove discovery-address $(getipbyhost $1) $DEVFSADM -Cv } # # Get the available ZFS compression options # $1 option type zfs_set|zfs_compress # function get_compress_opts { typeset COMPRESS_OPTS typeset GZIP_OPTS="gzip gzip-1 gzip-2 gzip-3 gzip-4 gzip-5 \ gzip-6 gzip-7 gzip-8 gzip-9" if [[ $1 == "zfs_compress" ]] ; then COMPRESS_OPTS="on lzjb" elif [[ $1 == "zfs_set" ]] ; then COMPRESS_OPTS="on off lzjb" fi typeset valid_opts="$COMPRESS_OPTS" $ZFS get 2>&1 | $GREP gzip >/dev/null 2>&1 if [[ $? -eq 0 ]]; then valid_opts="$valid_opts $GZIP_OPTS" fi $ECHO "$valid_opts" } # # Check the subcommand/option is supported # function check_opt_support #command, option { typeset command=$1 typeset option=$2 if [[ -z $command ]]; then return 0 elif [[ -z $option ]]; then eval "$ZFS 2>&1 | $GREP '$command' > /dev/null 2>&1" else eval "$ZFS $command 2>&1 | $GREP -- '$option' | \ $GREP -v -- 'User-defined' > /dev/null 2>&1" fi return $? } # # Check the zpool subcommand/option is supported # function check_zpool_opt_support #command, option { typeset command=$1 typeset option=$2 if [[ -z $command ]]; then return 0 elif [[ -z $option ]]; then eval "$ZPOOL 2>&1 | $GREP '$command' > /dev/null 2>&1" else eval "$ZPOOL $command 2>&1 | $GREP -- '$option' > /dev/null 2>&1" fi return $? } # # Verify zfs operation with -p option work as expected # $1 operation, value could be create, clone or rename # $2 dataset type, value could be fs or vol # $3 dataset name # $4 new dataset name # function verify_opt_p_ops { typeset ops=$1 typeset datatype=$2 typeset dataset=$3 typeset newdataset=$4 if [[ $datatype != "fs" && $datatype != "vol" ]]; then log_fail "$datatype is not supported." fi # check parameters accordingly case $ops in create) newdataset=$dataset dataset="" if [[ $datatype == "vol" ]]; then ops="create -V $VOLSIZE" fi ;; clone) if [[ -z $newdataset ]]; then log_fail "newdataset should not be empty" \ "when ops is $ops." fi log_must datasetexists $dataset log_must snapexists $dataset ;; rename) if [[ -z $newdataset ]]; then log_fail "newdataset should not be empty" \ "when ops is $ops." fi log_must datasetexists $dataset log_mustnot snapexists $dataset ;; *) log_fail "$ops is not supported." ;; esac # make sure the upper level filesystem does not exist if datasetexists ${newdataset%/*} ; then log_must $ZFS destroy -rRf ${newdataset%/*} fi # without -p option, operation will fail log_mustnot $ZFS $ops $dataset $newdataset log_mustnot datasetexists $newdataset ${newdataset%/*} # with -p option, operation should succeed log_must $ZFS $ops -p $dataset $newdataset if ! datasetexists $newdataset ; then log_fail "-p option does not work for $ops" fi # when $ops is create or clone, redo the operation still return zero if [[ $ops != "rename" ]]; then log_must $ZFS $ops -p $dataset $newdataset fi return 0 } function get_disk_guid { typeset diskname=$1 lastcwd=$(pwd) cd /dev guid=$($ZDB -l ${diskname} | ${AWK} '/^ guid:/ {print $2}' | head -1) cd $lastcwd echo $guid } # +# Get cachefile for a pool. +# Prints the cache file, if there is one. +# Returns 0 for a default zpool.cache, 1 for an explicit one, and 2 for none. +# +function cachefile_for_pool +{ + typeset pool=$1 + + cachefile=$(get_pool_prop cachefile $pool) + [[ $? != 0 ]] && return 1 + + case "$cachefile" in + none) ret=2 ;; + "-") + ret=2 + for dir in /boot/zfs /etc/zfs; do + if [[ -f "${dir}/zpool.cache" ]]; then + cachefile="${dir}/zpool.cache" + ret=0 + break + fi + done + ;; + *) ret=1; + esac + [[ $ret -eq 0 || $ret -eq 1 ]] && print "$cachefile" + return $ret +} + +# +# Assert that the pool is in the appropriate cachefile. +# +function assert_pool_in_cachefile +{ + typeset pool=$1 + + cachefile=$(cachefile_for_pool $pool) + [ $? -ne 0 ] && log_fail "ERROR: Cachefile not created for '$pool'?" + log_must test -e "${cachefile}" + log_must zdb -U ${cachefile} -C ${pool} +} + +# +# Get the zdb options given the cachefile state of the pool. +# +function zdb_cachefile_opts +{ + typeset pool=$1 + typeset vdevdir=$2 + typeset opts + + if poolexists "$pool"; then + cachefile=$(cachefile_for_pool $pool) + typeset -i ret=$? + case $ret in + 0) opts="-C" ;; + 1) opts="-U $cachefile -C" ;; + 2) opts="-eC" ;; + *) log_fail "Unknown return '$ret'" ;; + esac + else + opts="-eC" + [[ -n "$vdevdir" ]] && opts="$opts -p $vdevdir" + fi + echo "$opts" +} + +# # Get configuration of pool # $1 pool name # $2 config name # function get_config { typeset pool=$1 typeset config=$2 typeset vdevdir=$3 typeset alt_root typeset zdb_opts - if poolexists "$pool"; then - cachefile=$(get_pool_prop cachefile $pool) - if [[ $? != 0 ]]; then - # Shouldn't get here. Try treating as an exported pool - zdb_opts="-eC" - else - case $cachefile in - none) - # Treat as exported pool - zdb_opts="-eC" - break - ;; - "-") - # Normal pool - zdb_opts="-C" - break - ;; - *) - zdb_opts="-U $cachefile -C" - break - ;; - esac - fi - else - # use -e for exported pools - zdb_opts="-eC" - [[ -n "$vdevdir" ]] && zdb_opts="$zdb_opts -p $vdevdir" - fi - + zdb_opts=$(zdb_cachefile_opts $pool $vdevdir) value=$($ZDB $zdb_opts $pool | $GREP "$config:" | $AWK -F: '{print $2}') if [[ -n $value ]] ; then value=${value#'} value=${value%'} else return 1 fi - print $value + echo $value return 0 } # # Privated function. Random select one of items from arguments. # # $1 count # $2-n string # function _random_get { typeset cnt=$1 shift typeset str="$@" typeset -i ind ((ind = RANDOM % cnt + 1)) typeset ret=$($ECHO "$str" | $CUT -f $ind -d ' ') $ECHO $ret } # # Random select one of item from arguments which include NONE string # function random_get_with_non { typeset -i cnt=$# ((cnt =+ 1)) _random_get "$cnt" "$@" } # # Random select one of item from arguments which doesn't include NONE string # function random_get { _random_get "$#" "$@" } # # Detect if the current system support slog # function verify_slog_support { typeset dir=$TMPDIR/disk.${TESTCASE_ID} typeset pool=foo.${TESTCASE_ID} typeset vdev=$dir/a typeset sdev=$dir/b $MKDIR -p $dir $MKFILE 64M $vdev $sdev typeset -i ret=0 if ! $ZPOOL create -n $pool $vdev log $sdev > /dev/null 2>&1; then ret=1 fi $RM -r $dir return $ret } # # The function will generate a dataset name with specific length # $1, the length of the name # $2, the base string to construct the name # function gen_dataset_name { typeset -i len=$1 typeset basestr="$2" typeset -i baselen=${#basestr} typeset -i iter=0 typeset l_name="" if (( len % baselen == 0 )); then (( iter = len / baselen )) else (( iter = len / baselen + 1 )) fi while (( iter > 0 )); do l_name="${l_name}$basestr" (( iter -= 1 )) done $ECHO $l_name } # # Get cksum tuple of dataset # $1 dataset name # # zdb output is like below # " Dataset pool/fs [ZPL], ID 978, cr_txg 2277, 19.0K, 5 objects, # rootbp [L0 DMU objset] 400L/200P DVA[0]=<0:1880c00:200> # DVA[1]=<0:341880c00:200> fletcher4 lzjb LE contiguous birth=2292 fill=5 # cksum=989930ccf:4014fe00c83:da5e388e58b4:1f7332052252ac " # function datasetcksum { typeset cksum $SYNC cksum=$($ZDB -vvv $1 | $GREP "^Dataset $1 \[" | $GREP "cksum" \ | $AWK -F= '{print $6}') $ECHO $cksum } # # Get cksum of file # #1 file path # function checksum { typeset cksum cksum=$($CKSUM $1 | $AWK '{print $1}') $ECHO $cksum } # # Get the given disk/slice state from the specific field of the pool # function get_device_state #pool disk field("", "spares","logs") { typeset pool=$1 typeset disk=${2#/dev/dsk/} disk=${disk#/dev/rdsk/} disk=${disk#/dev/} typeset field=${3:-$pool} state=$($ZPOOL status -v "$pool" 2>/dev/null | \ $NAWK -v device=$disk -v pool=$pool -v field=$field \ 'BEGIN {startconfig=0; startfield=0; } /config:/ {startconfig=1} (startconfig==1)&&($1==field) {startfield=1; next;} (startfield==1)&&($1==device) {print $2; exit;} (startfield==1)&&(NF>=3)&&($(NF-1)=="was")&&($NF==device) {print $2; exit;} (startfield==1)&&($1==field || $1 ~ "^spares$" || $1 ~ "^logs$") {startfield=0}') print $state } # # print the given directory filesystem type # # $1 directory name # function get_fstype { typeset dir=$1 if [[ -z $dir ]]; then log_fail "Usage: get_fstype " fi # # $ df -n / # / : ufs # $DF -n $dir | $AWK '{print $3}' } # # Given a disk, label it to VTOC regardless what label was on the disk # $1 disk # function labelvtoc { typeset disk=$1 if [[ -z $disk ]]; then log_fail "The disk name is unspecified." fi typeset label_file=$TMPDIR/labelvtoc.${TESTCASE_ID} typeset arch=$($UNAME -p) if [[ $arch == "i386" ]]; then $ECHO "label" > $label_file $ECHO "0" >> $label_file $ECHO "" >> $label_file $ECHO "q" >> $label_file $ECHO "q" >> $label_file $FDISK -B $disk >/dev/null 2>&1 # wait a while for fdisk finishes $SLEEP 60 elif [[ $arch == "sparc" ]]; then $ECHO "label" > $label_file $ECHO "0" >> $label_file $ECHO "" >> $label_file $ECHO "" >> $label_file $ECHO "" >> $label_file $ECHO "q" >> $label_file else log_fail "unknown arch type" fi $FORMAT -e -s -d $disk -f $label_file typeset -i ret_val=$? $RM -f $label_file # # wait the format to finish # $SLEEP 60 if (( ret_val != 0 )); then log_fail "unable to label $disk as VTOC." fi return 0 } # # Detect if the given filesystem property is supported in this release # # 0 Yes, it is supported # !0 No, it is not supported # function fs_prop_exist { typeset prop=$1 if [[ -z $prop ]]; then log_fail "Usage: fs_prop_exist " return 1 fi # # If the property is shortened column name, # convert it to the standard name # case $prop in avail) prop=available ;; refer) prop=referenced ;; volblock) prop=volblocksize ;; compress) prop=compression ;; rdonly) prop=readonly ;; recsize) prop=recordsize ;; reserv) prop=reservation ;; refreserv) prop=refreservation ;; esac # # The zfs get output looks like the following # # # The following properties are supported: # # PROPERTY EDIT INHERIT VALUES # # available NO NO # compressratio NO NO <1.00x or higher if compressed> # creation NO NO # ... ... # zoned YES YES on | off # # Sizes are specified in bytes with standard units such as K, M, G, etc. # # # Start to extract property from the first blank line after 'PROPERTY' # and stop at the next blank line # $ZFS get 2>&1 | \ $AWK '/PROPERTY/ {start=1; next} /Sizes/ {start=0} start==1 {print $1}' | \ $GREP -w "$prop" > /dev/null 2>&1 return $? } # # Detect if the given pool property is supported in this release # # 0 Yes, it is supported # !0 No, it is not supported # function pool_prop_exist { typeset prop=$1 if [[ -z $prop ]]; then log_fail "Usage: pool_prop_exist " return 1 fi # # If the property is shortened column name, # convert it to the standard name # case $prop in avail) prop=available ;; cap) prop=capacity ;; replace) prop=autoreplace ;; esac # # The zpool get output looks like the following # # usage: # get <"all" | property[,...]> ... # # the following properties are supported: # # PROPERTY EDIT VALUES # # available NO # capacity NO # guid NO # health NO # size NO # used NO # altroot YES # autoreplace YES on | off # bootfs YES # cachefile YES | none # delegation YES on | off # failmode YES wait | continue | panic # version YES $ZPOOL get 2>&1 | \ $AWK '/PROPERTY/ {start=1; next} start==1 {print $1}' | \ $GREP -w "$prop" > /dev/null 2>&1 return $? } # # check if the system was installed as zfsroot or not # return: 0 ture, otherwise false # function is_zfsroot { $DF -n / | $GREP zfs > /dev/null 2>&1 return $? } # # get the root filesystem name if it's zfsroot system. # # return: root filesystem name function get_rootfs { typeset rootfs="" rootfs=$($MOUNT | $AWK '$3 == "\/" && $4~/zfs/ {print $1}') if [[ -z "$rootfs" ]]; then log_fail "Can not get rootfs" fi $ZFS list $rootfs > /dev/null 2>&1 if (( $? == 0 )); then $ECHO $rootfs else log_fail "This is not a zfsroot system." fi } # # get the rootfs's pool name # return: # rootpool name # function get_rootpool { typeset rootfs="" typeset rootpool="" rootfs=$(get_rootfs) rootpool=`$ECHO $rootfs | awk -F\/ '{print $1}'` echo $rootpool } # # Get the sub string from specified source string # # $1 source string # $2 start position. Count from 1 # $3 offset # function get_substr #src_str pos offset { typeset pos offset $ECHO $1 | \ $NAWK -v pos=$2 -v offset=$3 '{print substr($0, pos, offset)}' } # # Check if the given device is physical device # function is_physical_device #device { dev_file=`find_disks $1` [ -c "${dev_file}" -o -b "${dev_file}" ] return $? } # # Get the directory path of given device # function get_device_dir #device { typeset device=$1 if ! $(is_physical_device $device) ; then if [[ $device != "/" ]]; then device=${device%/*} fi $ECHO $device else $ECHO "/dev" fi } # # Get the package name # function get_package_name { typeset dirpath=${1:-$STC_NAME} print "SUNWstc-${dirpath}" | /usr/bin/sed -e "s/\//-/g" } # # Get the word numbers from a string separated by white space # function get_word_count { $ECHO $1 | $WC -w } # # To verify if the require numbers of disks is given # function verify_disk_count { typeset -i min=${2:-1} typeset -i count=$(get_word_count "$1") if (( count < min )); then log_untested "A minimum of $min disks is required to run." \ " You specified $count disk(s)" fi } # # bsdmap disk/slice number to a device path # function bsddevmap { typeset arg=$1 echo $arg | egrep "*s[0-9]$" > /dev/null 2>&1 if [ $? -eq 0 ] then n=`echo $arg| wc -c` set -A map a b c d e f g h i j s=`echo $arg | cut -c $((n-1))` arg=${arg%s[0-9]}${map[$s]} fi echo $arg } # # Get the name of the snapshots directory. Traditionally .zfs/snapshots # function get_snapdir_name { if [[ `sysctl -n vfs.zfs.abbreviated_snapdir` = "1" ]]; then echo ".snapshot" else echo ".zfs/snapshot" fi } # # Unmount all ZFS filesystems except for those that are in the KEEP variable # function unmount_all_safe { echo $(all_pools) | \ $XARGS -n 1 $ZFS list -H -o name -t all -r | \ $XARGS -n 1 $ZFS unmount } # # Return the highest pool version that this OS can create # function get_zpool_version { # We assume output from zpool upgrade -v of the form: # # This system is currently running ZFS version 2. # . # . typeset ZPOOL_VERSION=$($ZPOOL upgrade -v | $HEAD -1 | \ $AWK '{print $NF}' | $SED -e 's/\.//g') # Starting with version 5000, the output format changes to: # This system supports ZFS pool feature flags. # . # . if [[ $ZPOOL_VERSION = "flags" ]]; then ZPOOL_VERSION=5000 fi echo $ZPOOL_VERSION } +# Ensures that zfsd is running, starting it if necessary. Every test that +# interacts with zfsd must call this at startup. This is intended primarily +# to eliminate interference from outside the test suite. +function ensure_zfsd_running +{ + if ! service zfsd status > /dev/null 2>&1; then + service zfsd start || service zfsd onestart + service zfsd status > /dev/null 2>&1 || + log_unsupported "Test requires zfsd" + fi +} # Temporarily stops ZFSD, because it can interfere with some tests. If this # function is used, then restart_zfsd _must_ be called in the cleanup routine. function stop_zfsd { $RM -f $TMPDIR/.zfsd_enabled_during_stf_zfs_tests if [[ -n "$ZFSD" && -x "$ZFSD" ]]; then if /etc/rc.d/zfsd status > /dev/null; then log_note "Stopping zfsd" $TOUCH $TMPDIR/.zfsd_enabled_during_stf_zfs_tests /etc/rc.d/zfsd stop || /etc/rc.d/zfsd onestop fi fi } # Restarts zfsd after it has been stopped by stop_zfsd. Intelligently restarts # only iff zfsd was running at the time stop_zfsd was called. function restart_zfsd { if [[ -f $TMPDIR/.zfsd_enabled_during_stf_zfs_tests ]]; then log_note "Restarting zfsd" /etc/rc.d/zfsd start || /etc/rc.d/zfsd onestart fi $RM -f $TMPDIR/.zfsd_enabled_during_stf_zfs_tests } Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/clean_mirror/setup.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/clean_mirror/setup.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/clean_mirror/setup.ksh (revision 292346) @@ -1,48 +1,49 @@ #! /usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)setup.ksh 1.5 09/01/13 SMI" # . $STF_SUITE/include/libtest.kshlib verify_runnable "global" if ! $(is_physical_device $DISKS) ; then log_unsupported "This directory cannot be run on raw files." fi if [[ -n $SINGLE_DISK ]]; then log_note "Partitioning a single disk ($SINGLE_DISK)" else log_note "Partitioning disks ($MIRROR_PRIMARY $MIRROR_SECONDARY)" fi +wipe_partition_table ${SINGLE_DISK} ${MIRROR_PRIMARY} ${MIRROR_SECONDARY} log_must set_partition ${SIDE_PRIMARY##*p} "" $MIRROR_SIZE $MIRROR_PRIMARY log_must set_partition ${SIDE_SECONDARY##*p} "" $MIRROR_SIZE $MIRROR_SECONDARY default_mirror_setup $SIDE_PRIMARY $SIDE_SECONDARY log_pass Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_002_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_002_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_002_pos.ksh (revision 292346) @@ -1,159 +1,164 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)zpool_import_002_pos.ksh 1.3 07/10/09 SMI" # . $STF_SUITE/include/libtest.kshlib . $STF_SUITE/tests/cli_root/zfs_mount/zfs_mount.kshlib ################################################################################ # # __stc_assertion_start # # ID: zpool_import_002_pos # # DESCRIPTION: # Verify that an exported pool cannot be imported # more than once. # # STRATEGY: # 1. Populate the default test directory and unmount it. # 2. Export the default test pool. # 3. Import it using the various combinations. # - Regular import # - Alternate Root Specified # 4. Verify it shows up under 'zpool list'. # 5. Verify it contains a file. # 6. Attempt to import it for a second time. Verify this fails. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING_STATUS: COMPLETED (2005-07-04) # # __stc_assertion_end # ################################################################################ verify_runnable "global" set -A pools "$TESTPOOL" "$TESTPOOL1" set -A devs "" "-d $DEVICE_DIR" set -A options "" "-R $ALTER_ROOT" set -A mtpts "$TESTDIR" "$TESTDIR1" function cleanup { typeset -i i=0 while (( i < ${#pools[*]} )); do poolexists ${pools[i]} && \ log_must $ZPOOL export ${pools[i]} datasetexists "${pools[i]}/$TESTFS" || \ log_must $ZPOOL import ${devs[i]} ${pools[i]} ismounted "${pools[i]}/$TESTFS" || \ log_must $ZFS mount ${pools[i]}/$TESTFS [[ -e ${mtpts[i]}/$TESTFILE0 ]] && \ log_must $RM -rf ${mtpts[i]}/$TESTFILE0 ((i = i + 1)) done cleanup_filesystem $TESTPOOL1 $TESTFS destroy_pool $TESTPOOL1 [[ -d $ALTER_ROOT ]] && \ log_must $RM -rf $ALTER_ROOT } log_onexit cleanup log_assert "Verify that an exported pool cannot be imported more than once." setup_filesystem "$DEVICE_FILES" $TESTPOOL1 $TESTFS $TESTDIR1 checksum1=$($SUM $MYTESTFILE | $AWK '{print $1}') typeset -i i=0 typeset -i j=0 typeset basedir +function inner_test +{ + typeset pool=$1 + typeset target=$2 + typeset devs=$3 + typeset opts=$4 + typeset mtpt=$5 + + log_must $ZPOOL import ${devs} ${opts} $target + log_must poolexists $pool + log_must ismounted $pool/$TESTFS + + basedir=$mtpt + [ -n "$opts" ] && basedir="$ALTER_ROOT/$mtpt" + + [ ! -e "$basedir/$TESTFILE0" ] && \ + log_fail "ERROR: $basedir/$TESTFILE0 missing after import." + + checksum2=$($SUM $basedir/$TESTFILE0 | $AWK '{print $1}') + [[ "$checksum1" != "$checksum2" ]] && \ + log_fail "ERROR: Checksums differ ($checksum1 != $checksum2)" + + log_mustnot $ZPOOL import $devs $target +} + while (( i < ${#pools[*]} )); do log_must $CP $MYTESTFILE ${mtpts[i]}/$TESTFILE0 log_must $ZFS umount ${mtpts[i]} j=0 while (( j < ${#options[*]} )); do typeset pool=${pools[i]} - k=0 - while (( k < 2 )); do - typeset target=$pool - log_must $ZPOOL export $pool + typeset vdevdir="" - if (( k == 1 )); then - typeset vdevdir="" - if [[ "$pool" = "$TESTPOOL1" ]]; then - vdevdir="$DEVICE_DIR" - fi - target=$(get_config $pool pool_guid $vdevdir) - log_must test -n "$target" - log_note "Importing '$pool' by guid '$target'." - fi + log_must $ZPOOL export $pool - log_must $ZPOOL import ${devs[i]} ${options[j]} $target - log_must poolexists $pool - log_must ismounted $pool/$TESTFS + [ "$pool" = "$TESTPOOL1" ] && vdevdir="$DEVICE_DIR" + guid=$(get_config $pool pool_guid $vdevdir) + log_must test -n "$guid" + log_note "Importing '$pool' by guid '$guid'" + inner_test $pool $guid "${devs[i]}" "${options[j]}" ${mtpts[i]} - basedir=${mtpts[i]} - [[ -n ${options[j]} ]] && \ - basedir=$ALTER_ROOT/${mtpts[i]} + log_must $ZPOOL export $pool - [[ ! -e $basedir/$TESTFILE0 ]] && log_fail \ - "$basedir/$TESTFILE0 missing after import." - - checksum2=$($SUM $basedir/$TESTFILE0 | $AWK '{print $1}') - [[ "$checksum1" != "$checksum2" ]] && log_fail \ - "Checksums differ ($checksum1 != $checksum2)" - - log_mustnot $ZPOOL import ${devs[i]} $target - - (( k = k + 1 )) - done + log_note "Importing '$pool' by name." + inner_test $pool $pool "${devs[i]}" "${options[j]}" ${mtpts[i]} ((j = j + 1)) done ((i = i + 1)) done log_pass "Able to import exported pools and import only once." Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_004_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_004_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_004_pos.ksh (revision 292346) @@ -1,99 +1,108 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)zpool_import_004_pos.ksh 1.3 07/10/09 SMI" # . $STF_SUITE/include/libtest.kshlib ################################################################################# # # __stc_assertion_start # # ID: zpool_import_004_pos # # DESCRIPTION: # Destroyed pools devices was moved to another directory, it still can be # imported correctly. # # STRATEGY: # 1. Create test pool A with several devices. # 2. Destroy pool A. # 3. Move devices to another directory. # 4. Verify 'zpool import -D' succeed. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING_STATUS: COMPLETED (2006-06-12) # # __stc_assertion_end # ################################################################################ verify_runnable "global" function cleanup { destroy_pool $TESTPOOL1 - log_must $RM -rf $DEVICE_DIR/* - typeset i=0 - while (( i < $MAX_NUM )); do - log_must $MKFILE $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i - ((i += 1)) - done } +function perform_test +{ + target=$1 + + assert_pool_in_cachefile $TESTPOOL1 + log_must $ZPOOL destroy $TESTPOOL1 + + log_note "Devices was moved to different directories." + log_must $MKDIR -p $DEVICE_DIR/newdir1 $DEVICE_DIR/newdir2 + log_must $MV $VDEV1 $DEVICE_DIR/newdir1 + log_must $MV $VDEV2 $DEVICE_DIR/newdir2 + log_must $ZPOOL import -d $DEVICE_DIR/newdir1 -d $DEVICE_DIR/newdir2 \ + -d $DEVICE_DIR -D -f $target + log_must $ZPOOL destroy -f $TESTPOOL1 + + log_note "Devices was moved to same directory." + log_must $MV $VDEV0 $DEVICE_DIR/newdir2 + log_must $MV $DEVICE_DIR/newdir1/* $DEVICE_DIR/newdir2 + log_must $ZPOOL import -d $DEVICE_DIR/newdir2 -D -f $target + log_must $ZPOOL destroy -f $TESTPOOL1 + + # Revert at the end so this test can be rerun. + log_must $MV $DEVICE_DIR/newdir2/$(basename $VDEV0) $VDEV0 + log_must $MV $DEVICE_DIR/newdir2/$(basename $VDEV1) $VDEV1 + log_must $MV $DEVICE_DIR/newdir2/$(basename $VDEV2) $VDEV2 +} + log_assert "Destroyed pools devices was moved to another directory," \ "it still can be imported correctly." log_onexit cleanup log_must $ZPOOL create $TESTPOOL1 $VDEV0 $VDEV1 $VDEV2 -typeset guid=$(get_config $TESTPOOL1 pool_guid) -typeset target=$TESTPOOL1 -if (( RANDOM % 2 == 0 )) ; then - target=$guid - log_note "Import by guid." -fi -log_must $ZPOOL destroy $TESTPOOL1 +log_note "Testing import by name '$TESTPOOL1'." +perform_test $TESTPOOL1 -log_note "Devices was moved to different directories." -log_must $MKDIR $DEVICE_DIR/newdir1 $DEVICE_DIR/newdir2 -log_must $MV $VDEV1 $DEVICE_DIR/newdir1 -log_must $MV $VDEV2 $DEVICE_DIR/newdir2 -log_must $ZPOOL import -d $DEVICE_DIR/newdir1 -d $DEVICE_DIR/newdir2 \ - -d $DEVICE_DIR -D -f $target -log_must $ZPOOL destroy -f $TESTPOOL1 - -log_note "Devices was moved to same directory." -log_must $MV $VDEV0 $DEVICE_DIR/newdir2 -log_must $MV $DEVICE_DIR/newdir1/* $DEVICE_DIR/newdir2 -log_must $ZPOOL import -d $DEVICE_DIR/newdir2 -D -f $target -log_must $ZPOOL destroy -f $TESTPOOL1 +log_must $ZPOOL create $TESTPOOL1 $VDEV0 $VDEV1 $VDEV2 +log_must $ZPOOL status $TESTPOOL1 +log_must $ZDB -C $TESTPOOL1 +typeset guid=$(get_config $TESTPOOL1 pool_guid) +log_note "Testing import by GUID '${guid}'." +perform_test $guid log_pass "Destroyed pools devices was moved, 'zpool import -D' passed." Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_005_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_005_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_005_pos.ksh (revision 292346) @@ -1,96 +1,110 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)zpool_import_005_pos.ksh 1.3 07/10/09 SMI" # . $STF_SUITE/include/libtest.kshlib ################################################################################# # # __stc_assertion_start # # ID: zpool_import_005_pos # # DESCRIPTION: # Destroyed pools devices was renamed, it still can be imported correctly. # # STRATEGY: # 1. Create test pool A with several devices. # 2. Destroy pool A and rename devices name. # 3. Verify 'zpool import -D' succeed. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING_STATUS: COMPLETED (2006-06-12) # # __stc_assertion_end # ################################################################################ verify_runnable "global" function cleanup { destroy_pool $TESTPOOL1 log_must $RM -rf $DEVICE_DIR/* typeset i=0 while (( i < $MAX_NUM )); do log_must $MKFILE $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i ((i += 1)) done } log_assert "Destroyed pools devices was renamed, it still can be imported " \ "correctly." log_onexit cleanup -log_must $ZPOOL create $TESTPOOL1 $VDEV0 $VDEV1 $VDEV2 -typeset guid=$(get_config $TESTPOOL1 pool_guid) -typeset target=$TESTPOOL1 -if (( RANDOM % 2 == 0 )) ; then - target=$guid - log_note "Import by guid." -fi -log_must $ZPOOL destroy $TESTPOOL1 +function perform_test +{ + typeset target=$1 -log_note "Part of devices was renamed in the same directory." -log_must $MV $VDEV0 $DEVICE_DIR/vdev0-new -log_must $ZPOOL import -d $DEVICE_DIR -D -f $target -log_must $ZPOOL destroy -f $TESTPOOL1 + assert_pool_in_cachefile $TESTPOOL1 + log_must $ZPOOL destroy $TESTPOOL1 -log_note "All of devices was rename to different directories." -log_must $MKDIR $DEVICE_DIR/newdir1 $DEVICE_DIR/newdir2 -log_must $MV $VDEV1 $DEVICE_DIR/newdir1/vdev1-new -log_must $MV $VDEV2 $DEVICE_DIR/newdir2/vdev2-new -log_must $ZPOOL import -d $DEVICE_DIR/newdir1 -d $DEVICE_DIR/newdir2 \ - -d $DEVICE_DIR -D -f $target -log_must $ZPOOL destroy -f $TESTPOOL1 + log_note "Testing some devices renamed in the same directory." + log_must $MV $VDEV0 $DEVICE_DIR/vdev0-new + log_must $ZPOOL import -d $DEVICE_DIR -D -f $target + log_must $ZPOOL destroy -f $TESTPOOL1 + + log_note "Testing all devices moved to different directories." + log_must $MKDIR -p $DEVICE_DIR/newdir1 $DEVICE_DIR/newdir2 + log_must $MV $VDEV1 $DEVICE_DIR/newdir1/vdev1-new + log_must $MV $VDEV2 $DEVICE_DIR/newdir2/vdev2-new + log_must $ZPOOL import -d $DEVICE_DIR/newdir1 -d $DEVICE_DIR/newdir2 \ + -d $DEVICE_DIR -D -f $target + log_must $ZPOOL destroy -f $TESTPOOL1 + + # Restore the vdevs to their old location so this can be re-run + log_note "Restoring vdev files for any further runs." + log_must $MV $DEVICE_DIR/vdev0-new $VDEV0 + log_must $MV $DEVICE_DIR/newdir1/vdev1-new $VDEV1 + log_must $MV $DEVICE_DIR/newdir2/vdev2-new $VDEV2 +} + +log_note "Testing import by name." +log_must $ZPOOL create $TESTPOOL1 $VDEV0 $VDEV1 $VDEV2 +perform_test $TESTPOOL1 + +log_note "Testing import by GUID." +log_must $ZPOOL create $TESTPOOL1 $VDEV0 $VDEV1 $VDEV2 +typeset guid=$(get_config $TESTPOOL1 pool_guid) +perform_test $guid log_pass "Destroyed pools devices was renamed, 'zpool import -D' passed." Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_006_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_006_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_006_pos.ksh (revision 292346) @@ -1,94 +1,105 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)zpool_import_006_pos.ksh 1.3 07/10/09 SMI" # . $STF_SUITE/include/libtest.kshlib ################################################################################# # # __stc_assertion_start # # ID: zpool_import_006_pos # # DESCRIPTION: # For mirror, N-1 destroyed pools devices was removed or used by other # pool, it still can be imported correctly. # # STRATEGY: # 1. Create mirror with N disks. # 2. Destroy this mirror. # 3. Create another pool with N-1 disks which was used by this mirror. # 4. Verify import mirror can succeed. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING_STATUS: COMPLETED (2006-06-12) # # __stc_assertion_end # ################################################################################ verify_runnable "global" function cleanup { destroy_pool $TESTPOOL2 destroy_pool $TESTPOOL1 log_must $RM -rf $DEVICE_DIR/* typeset i=0 while (( i < $MAX_NUM )); do log_must $MKFILE $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i ((i += 1)) done } log_assert "For mirror, N-1 destroyed pools devices was removed or used " \ "by other pool, it still can be imported correctly." log_onexit cleanup -log_must $ZPOOL create $TESTPOOL1 mirror $VDEV0 $VDEV1 $VDEV2 -typeset guid=$(get_config $TESTPOOL1 pool_guid) -typeset target=$TESTPOOL1 -if (( RANDOM % 2 == 0 )) ; then - target=$guid - log_note "Import by guid." -fi -log_must $ZPOOL destroy $TESTPOOL1 +function perform_test +{ + typeset target=$1 -log_must $ZPOOL create $TESTPOOL2 $VDEV0 $VDEV2 -log_must $ZPOOL import -d $DEVICE_DIR -D -f $target -log_must $ZPOOL destroy $TESTPOOL1 + assert_pool_in_cachefile $TESTPOOL1 + log_must $ZPOOL destroy $TESTPOOL1 -log_must $ZPOOL destroy $TESTPOOL2 -log_must $RM -rf $VDEV2 -log_must $ZPOOL import -d $DEVICE_DIR -D -f $target + create_pool $TESTPOOL2 $VDEV0 $VDEV2 + log_must $ZPOOL import -d $DEVICE_DIR -D -f $target + log_must $ZPOOL destroy $TESTPOOL1 + + log_must $ZPOOL destroy $TESTPOOL2 + log_must $RM -rf $VDEV2 + log_must $ZPOOL import -d $DEVICE_DIR -D -f $target + + # Restore the vdev. + log_must $MKFILE $FILE_SIZE $VDEV2 +} + +log_note "Testing import by name." +create_pool $TESTPOOL1 mirror $VDEV0 $VDEV1 $VDEV2 +perform_test $TESTPOOL1 + +log_note "Testing import by GUID." +create_pool $TESTPOOL1 mirror $VDEV0 $VDEV1 $VDEV2 +typeset guid=$(get_config $TESTPOOL1 pool_guid) +perform_test $guid log_pass "zpool import -D mirror passed." Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_007_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_007_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_007_pos.ksh (revision 292346) @@ -1,101 +1,109 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)zpool_import_007_pos.ksh 1.3 07/10/09 SMI" # . $STF_SUITE/include/libtest.kshlib ################################################################################# # # __stc_assertion_start # # ID: zpool_import_007_pos # # DESCRIPTION: # For raidz, one destroyed pools devices was removed or used by other # pool, it still can be imported correctly. # # STRATEGY: # 1. Create a raidz pool A with N disks. # 2. Destroy this pool A. # 3. Create another pool B with 1 disk which was used by pool A. # 4. Verify import this raidz pool can succeed. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING_STATUS: COMPLETED (2006-06-12) # # __stc_assertion_end # ################################################################################ verify_runnable "global" function cleanup { destroy_pool $TESTPOOL2 destroy_pool $TESTPOOL1 log_must $RM -rf $DEVICE_DIR/* typeset i=0 while (( i < $MAX_NUM )); do log_must $MKFILE $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i ((i += 1)) done } log_assert "For raidz, one destroyed pools devices was removed or used by " \ "other pool, it still can be imported correctly." log_onexit cleanup -log_must $ZPOOL create $TESTPOOL1 raidz $VDEV0 $VDEV1 $VDEV2 $VDIV3 -typeset guid=$(get_config $TESTPOOL1 pool_guid) -typeset target=$TESTPOOL1 -if (( RANDOM % 2 == 0 )) ; then - target=$guid - log_note "Import by guid." -fi -log_must $ZPOOL destroy $TESTPOOL1 +function perform_test +{ + typeset target=$1 -log_must $ZPOOL create $TESTPOOL2 $VDEV0 -log_must $ZPOOL import -d $DEVICE_DIR -D -f $target -log_must $ZPOOL destroy $TESTPOOL1 + assert_pool_in_cachefile $TESTPOOL1 + log_must $ZPOOL destroy $TESTPOOL1 -log_must $ZPOOL destroy $TESTPOOL2 -log_must $RM -rf $VDEV0 -log_must $ZPOOL import -d $DEVICE_DIR -D -f $target -log_must $ZPOOL destroy $TESTPOOL1 + log_must $ZPOOL create $TESTPOOL2 $VDEV0 + log_must $ZPOOL import -d $DEVICE_DIR -D -f $target + log_must $ZPOOL destroy $TESTPOOL1 -log_note "For raidz, two destroyed pool's devices were used, import failed." -log_must $MKFILE $FILE_SIZE $VDEV0 -log_must $ZPOOL create $TESTPOOL2 $VDEV0 $VDEV1 -log_mustnot $ZPOOL import -d $DEVICE_DIR -D -f $target -log_must $ZPOOL destroy $TESTPOOL2 + log_must $ZPOOL destroy $TESTPOOL2 + log_must $RM -rf $VDEV0 + log_must $ZPOOL import -d $DEVICE_DIR -D -f $target + log_must $ZPOOL destroy $TESTPOOL1 + + log_note "For raidz, two destroyed pool's devices were used, import failed." + log_must $MKFILE $FILE_SIZE $VDEV0 + log_must $ZPOOL create $TESTPOOL2 $VDEV0 $VDEV1 + log_mustnot $ZPOOL import -d $DEVICE_DIR -D -f $target + log_must $ZPOOL destroy $TESTPOOL2 +} + +log_note "Testing import by name." +log_must $ZPOOL create $TESTPOOL1 raidz $VDEV0 $VDEV1 $VDEV2 $VDIV3 +perform_test $TESTPOOL1 + +log_note "Testing import by GUID." +log_must $ZPOOL create $TESTPOOL1 raidz $VDEV0 $VDEV1 $VDEV2 $VDIV3 +typeset guid=$(get_config $TESTPOOL1 pool_guid) +perform_test $guid log_pass "zpool import -D raidz passed." Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_008_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_008_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_008_pos.ksh (revision 292346) @@ -1,102 +1,110 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)zpool_import_008_pos.ksh 1.3 07/10/09 SMI" # . $STF_SUITE/include/libtest.kshlib ################################################################################# # # __stc_assertion_start # # ID: zpool_import_008_pos # # DESCRIPTION: # For raidz2, two destroyed pool's devices were removed or used by other # pool, it still can be imported correctly. # # STRATEGY: # 1. Create a raidz2 pool A with N disks. # 2. Destroy this pool A. # 3. Create another pool B with two disks which were used by pool A. # 4. Verify import this raidz2 pool can succeed. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING_STATUS: COMPLETED (2006-06-12) # # __stc_assertion_end # ################################################################################ verify_runnable "global" function cleanup { destroy_pool $TESTPOOL2 destroy_pool $TESTPOOL1 log_must $RM -rf $DEVICE_DIR/* typeset i=0 while (( i < $MAX_NUM )); do log_must $MKFILE $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i ((i += 1)) done } +function perform_test +{ + typeset target=$1 + + assert_pool_in_cachefile $TESTPOOL1 + log_must $ZPOOL destroy $TESTPOOL1 + + log_must $ZPOOL create $TESTPOOL2 $VDEV0 $VDEV1 + log_must $ZPOOL import -d $DEVICE_DIR -D -f $target + log_must $ZPOOL destroy $TESTPOOL1 + + log_must $ZPOOL destroy $TESTPOOL2 + log_must $RM -rf $VDEV0 $VDEV1 + log_must $ZPOOL import -d $DEVICE_DIR -D -f $target + log_must $ZPOOL destroy $TESTPOOL1 + + log_note "For raidz2, more than two destroyed pool's devices were used, " \ + "import failed." + log_must $MKFILE $FILE_SIZE $VDEV0 $VDEV1 + log_must $ZPOOL create $TESTPOOL2 $VDEV0 $VDEV1 $VDEV2 + log_mustnot $ZPOOL import -d $DEVICE_DIR -D -f $target + log_must $ZPOOL destroy $TESTPOOL2 +} + log_assert "For raidz2, two destroyed pools devices was removed or used by " \ "other pool, it still can be imported correctly." log_onexit cleanup +log_note "Testing import by name." log_must $ZPOOL create $TESTPOOL1 raidz2 $VDEV0 $VDEV1 $VDEV2 $VDIV3 -typeset guid=$(get_config $TESTPOOL1 pool_guid) -typeset target=$TESTPOOL1 -if (( RANDOM % 2 == 0 )) ; then - target=$guid - log_note "Import by guid." -fi -log_must $ZPOOL destroy $TESTPOOL1 +perform_test $TESTPOOL1 -log_must $ZPOOL create $TESTPOOL2 $VDEV0 $VDEV1 -log_must $ZPOOL import -d $DEVICE_DIR -D -f $target -log_must $ZPOOL destroy $TESTPOOL1 - -log_must $ZPOOL destroy $TESTPOOL2 -log_must $RM -rf $VDEV0 $VDEV1 -log_must $ZPOOL import -d $DEVICE_DIR -D -f $target -log_must $ZPOOL destroy $TESTPOOL1 - -log_note "For raidz2, more than two destroyed pool's devices were used, " \ - "import failed." -log_must $MKFILE $FILE_SIZE $VDEV0 $VDEV1 -log_must $ZPOOL create $TESTPOOL2 $VDEV0 $VDEV1 $VDEV2 -log_mustnot $ZPOOL import -d $DEVICE_DIR -D -f $target -log_must $ZPOOL destroy $TESTPOOL2 +log_note "Testing import by GUID." +log_must $ZPOOL create $TESTPOOL1 raidz2 $VDEV0 $VDEV1 $VDEV2 $VDIV3 +typeset guid=$(get_config $TESTPOOL1 pool_guid) +perform_test $guid log_pass "zpool import -D raidz2 passed." Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_missing_001_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_missing_001_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_missing_001_pos.ksh (revision 292346) @@ -1,213 +1,217 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)zpool_import_missing_001_pos.ksh 1.4 07/10/09 SMI" # . $STF_SUITE/include/libtest.kshlib . $STF_SUITE/tests/cli_root/zfs_mount/zfs_mount.kshlib ################################################################################ # # __stc_assertion_start # # ID: zpool_import_missing_001_pos # # DESCRIPTION: # Once a pool has been exported, and one or more devices are # damaged or missing (d/m), import should handle this kind of situation # as described: # - Regular, report error while any number of devices failing. # - Mirror could withstand (N-1) devices failing # before data integrity is compromised # - Raidz could withstand one devices failing # before data integrity is compromised # Verify those are true. # # STRATEGY: # 1. Create test pool upon device files using the various combinations. # - Regular pool # - Mirror # - Raidz # 2. Create necessary filesystem and test files. # 3. Export the test pool. # 4. Remove one or more devices # 5. Verify 'zpool import' will handle d/m device successfully. # Using the various combinations. # - Regular import # - Alternate Root Specified # It should be succeed with single d/m device upon 'raidz' & 'mirror', # but failed against 'regular' or more d/m devices. # 6. If import succeed, verify following is true: # - The pool shows up under 'zpool list'. # - The pool's health should be DEGRADED. # - It contains the correct test file # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING_STATUS: COMPLETED (2005-08-01) # # __stc_assertion_end # ################################################################################ verify_runnable "global" set -A vdevs "" "mirror" "raidz" set -A options "" "-R $ALTER_ROOT" function cleanup { # recover the vdevs recreate_files [[ -d $ALTER_ROOT ]] && \ log_must $RM -rf $ALTER_ROOT } function recreate_files { if poolexists "$TESTPOOL1" ; then cleanup_filesystem $TESTPOOL1 $TESTFS destroy_pool $TESTPOOL1 fi log_must $RM -rf $DEVICE_DIR/* typeset i=0 while (( i < $MAX_NUM )); do log_must $MKFILE $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i ((i += 1)) done } +function perform_inner_test +{ + typeset action=$1 + typeset import_opts=$2 + typeset target=$3 + + $action $ZPOOL import -d $DEVICE_DIR ${import_opts} $target + [[ $action == "log_mustnot" ]] && return + + log_must poolexists $TESTPOOL1 + + health=$($ZPOOL list -H -o health $TESTPOOL1) + [[ "$health" == "DEGRADED" ]] || \ + log_fail "ERROR: $TESTPOOL1: Incorrect health '$health'" + log_must ismounted $TESTPOOL1/$TESTFS + + basedir=$TESTDIR1 + [[ -n "${import_opts}" ]] && basedir=$ALTER_ROOT/$TESTDIR1 + [[ ! -e "$basedir/$TESTFILE0" ]] && \ + log_fail "ERROR: $basedir/$TESTFILE0 missing after import." + + checksum2=$($SUM $basedir/$TESTFILE0 | $AWK '{print $1}') + [[ "$checksum1" != "$checksum2" ]] && \ + log_fail "ERROR: Checksums differ ($checksum1 != $checksum2)" + + log_must $ZPOOL export $TESTPOOL1 +} + log_onexit cleanup log_assert "Verify that import could handle damaged or missing device." CWD=$PWD -cd $DEVICE_DIR || log_fail "Unable change directory to $DEVICE_DIR" +cd $DEVICE_DIR || log_fail "ERROR: Unable change directory to $DEVICE_DIR" checksum1=$($SUM $MYTESTFILE | $AWK '{print $1}') typeset -i i=0 typeset -i j=0 typeset -i count=0 typeset basedir backup while (( i < ${#vdevs[*]} )); do setup_filesystem "$DEVICE_FILES" \ $TESTPOOL1 $TESTFS $TESTDIR1 \ "" ${vdevs[i]} backup="" guid=$(get_config $TESTPOOL1 pool_guid) log_must $CP $MYTESTFILE $TESTDIR1/$TESTFILE0 log_must $ZFS umount $TESTDIR1 j=0 while (( j < ${#options[*]} )); do count=0 action=log_must # # Restore all device files. # [[ -n $backup ]] && \ log_must $TAR xf $DEVICE_DIR/$DEVICE_ARCHIVE for device in $DEVICE_FILES ; do log_must $RM -f $device poolexists $TESTPOOL1 && \ log_must $ZPOOL export $TESTPOOL1 # # Backup all device files while filesystem prepared. # if [[ -z $backup ]]; then log_must $TAR cf $DEVICE_DIR/$DEVICE_ARCHIVE \ ${DEVICE_FILE}* backup="true" fi (( count = count + 1 )) case "${vdevs[i]}" in 'mirror') (( count == $GROUP_NUM )) && \ action=log_mustnot ;; 'raidz') (( count > 1 )) && \ action=log_mustnot ;; '') action=log_mustnot ;; esac - typeset target=$TESTPOOL1 - if (( RANDOM % 2 == 0 )) ; then - target=$guid - log_note "Import by guid." - fi - $action $ZPOOL import \ - -d $DEVICE_DIR ${options[j]} $target + log_note "Testing import by name." + perform_inner_test $action "${options[j]}" $TESTPOOL1 - [[ $action == "log_mustnot" ]] && continue - - log_must poolexists $TESTPOOL1 - - health=$($ZPOOL list -H -o health $TESTPOOL1) - - [[ $health == "DEGRADED" ]] || \ - log_fail "$TESTPOOL1: Incorrect health($health)" - log_must ismounted $TESTPOOL1/$TESTFS - - basedir=$TESTDIR1 - [[ -n ${options[j]} ]] && \ - basedir=$ALTER_ROOT/$TESTDIR1 - - [[ ! -e $basedir/$TESTFILE0 ]] && \ - log_fail "$basedir/$TESTFILE0 missing after import." - - checksum2=$($SUM $basedir/$TESTFILE0 | $AWK '{print $1}') - [[ "$checksum1" != "$checksum2" ]] && \ - log_fail "Checksums differ ($checksum1 != $checksum2)" - + log_note "Testing import by GUID." + perform_inner_test $action "${options[j]}" $guid done ((j = j + 1)) done recreate_files ((i = i + 1)) done log_pass "Import could handle damaged or missing device." Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_missing_002_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_missing_002_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_missing_002_pos.ksh (revision 292346) @@ -1,207 +1,209 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)zpool_import_missing_002_pos.ksh 1.4 07/10/09 SMI" # . $STF_SUITE/include/libtest.kshlib . $STF_SUITE/tests/cli_root/zfs_mount/zfs_mount.kshlib ################################################################################ # # __stc_assertion_start # # ID: zpool_import_missing_002_pos # # DESCRIPTION: # Once a pool has been exported, and one or more devices are # move to other place, import should handle this kind of situation # as described: # - Regular, report error while any number of devices failing. # - Mirror could withstand (N-1) devices failing # before data integrity is compromised # - Raidz could withstand one devices failing # before data integrity is compromised # Verify that is true. # # STRATEGY: # 1. Create test pool upon device files using the various combinations. # - Regular pool # - Mirror # - Raidz # 2. Create necessary filesystem and test files. # 3. Export the test pool. # 4. Move one or more device files to other directory # 5. Verify 'zpool import -d' with the new directory # will handle moved files successfullly. # Using the various combinations. # - Regular import # - Alternate Root Specified # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING_STATUS: COMPLETED (2005-08-01) # # __stc_assertion_end # ################################################################################ verify_runnable "global" set -A vdevs "" "mirror" "raidz" set -A options "" "-R $ALTER_ROOT" function cleanup { cd $DEVICE_DIR || log_fail "Unable change directory to $DEVICE_DIR" [[ -e $DEVICE_DIR/$DEVICE_ARCHIVE ]] && \ log_must $TAR xf $DEVICE_DIR/$DEVICE_ARCHIVE poolexists $TESTPOOL1 || \ log_must $ZPOOL import -d $DEVICE_DIR $TESTPOOL1 cleanup_filesystem $TESTPOOL1 $TESTFS destroy_pool $TESTPOOL1 } function cleanup_all { cleanup # recover dev files typeset i=0 while (( i < $MAX_NUM )); do typeset dev_file=${DEVICE_DIR}/${DEVICE_FILE}$i - if [[ ! -e ${dev_file} ]]; then - log_must $MKFILE $FILE_SIZE ${dev_file} - fi + [ ! -e ${dev_file} ] && log_must $MKFILE $FILE_SIZE ${dev_file} ((i += 1)) done log_must $RM -f $DEVICE_DIR/$DEVICE_ARCHIVE cd $CWD || log_fail "Unable change directory to $CWD" [[ -d $ALTER_ROOT ]] && \ log_must $RM -rf $ALTER_ROOT [[ -d $BACKUP_DEVICE_DIR ]] && \ log_must $RM -rf $BACKUP_DEVICE_DIR } log_onexit cleanup_all log_assert "Verify that import could handle moving device." CWD=$PWD [[ ! -d $BACKUP_DEVICE_DIR ]] && log_must $MKDIR -p $BACKUP_DEVICE_DIR cd $DEVICE_DIR || log_fail "Unable change directory to $DEVICE_DIR" typeset -i i=0 typeset -i j=0 typeset -i count=0 typeset basedir backup typeset action while (( i < ${#vdevs[*]} )); do (( i != 0 )) && \ log_must $TAR xf $DEVICE_DIR/$DEVICE_ARCHIVE setup_filesystem "$DEVICE_FILES" \ $TESTPOOL1 $TESTFS $TESTDIR1 \ "" ${vdevs[i]} guid=$(get_config $TESTPOOL1 pool_guid) backup="" log_must $CP $MYTESTFILE $TESTDIR1/$TESTFILE0 log_must $ZFS umount $TESTDIR1 j=0 while (( j < ${#options[*]} )); do count=0 # # Restore all device files. # [[ -n $backup ]] && \ log_must $TAR xf $DEVICE_DIR/$DEVICE_ARCHIVE log_must $RM -f $BACKUP_DEVICE_DIR/* for device in $DEVICE_FILES ; do poolexists $TESTPOOL1 && \ log_must $ZPOOL export $TESTPOOL1 # # Backup all device files while filesystem prepared. # if [[ -z $backup ]] ; then log_must $TAR cf $DEVICE_DIR/$DEVICE_ARCHIVE ${DEVICE_FILE}* backup="true" fi log_must $MV $device $BACKUP_DEVICE_DIR (( count = count + 1 )) action=log_mustnot case "${vdevs[i]}" in 'mirror') (( count < $GROUP_NUM )) && \ action=log_must ;; 'raidz') (( count == 1 )) && \ action=log_must ;; esac - typeset target=$TESTPOOL1 - if (( RANDOM % 2 == 0 )) ; then - target=$guid - log_note "Import by guid." - fi + log_note "Testing import by name." $action $ZPOOL import \ - -d $DEVICE_DIR ${options[j]} $target + -d $DEVICE_DIR ${options[j]} $TESTPOOL1 + # We have to test for pool existence since action + # may be 'log_mustnot'. + poolexists $TESTPOOL1 && \ + log_must $ZPOOL export $TESTPOOL1 + + log_note "Testing import by GUID." + $action $ZPOOL import \ + -d $DEVICE_DIR ${options[j]} $guid done ((j = j + 1)) done cleanup ((i = i + 1)) done log_pass "Import could handle moving device." Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_rename_001_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_rename_001_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_import/zpool_import_rename_001_pos.ksh (revision 292346) @@ -1,172 +1,179 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)zpool_import_rename_001_pos.ksh 1.3 07/10/09 SMI" # . $STF_SUITE/include/libtest.kshlib . $STF_SUITE/tests/cli_root/zfs_mount/zfs_mount.kshlib ################################################################################ # # __stc_assertion_start # # ID: zpool_import_rename_001_pos # # DESCRIPTION: # An exported pool can be imported under a different name. Hence # we test that a previously exported pool can be renamed. # # STRATEGY: # 1. Copy a file into the default test directory. # 2. Umount the default directory. # 3. Export the pool. # 4. Import the pool using the name ${TESTPOOL}-new, # and using the various combinations. # - Regular import # - Alternate Root Specified # 5. Verify it exists in the 'zpool list' output. # 6. Verify the default file system is mounted and that the file # from step (1) is present. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING_STATUS: COMPLETED (2005-07-04) # # __stc_assertion_end # ################################################################################ verify_runnable "global" set -A pools "$TESTPOOL" "$TESTPOOL1" set -A devs "" "-d $DEVICE_DIR" set -A options "" "-R $ALTER_ROOT" set -A mtpts "$TESTDIR" "$TESTDIR1" function cleanup { typeset -i i=0 while (( i < ${#pools[*]} )); do if poolexists "${pools[i]}-new" ; then log_must $ZPOOL export "${pools[i]}-new" [[ -d /${pools[i]}-new ]] && \ log_must $RM -rf /${pools[i]}-new log_must $ZPOOL import ${devs[i]} \ "${pools[i]}-new" ${pools[i]} fi datasetexists "${pools[i]}" || \ log_must $ZPOOL import ${devs[i]} ${pools[i]} ismounted "${pools[i]}/$TESTFS" || \ log_must $ZFS mount ${pools[i]}/$TESTFS [[ -e ${mtpts[i]}/$TESTFILE0 ]] && \ log_must $RM -rf ${mtpts[i]}/$TESTFILE0 ((i = i + 1)) done cleanup_filesystem $TESTPOOL1 $TESTFS $TESTDIR1 destroy_pool $TESTPOOL1 [[ -d $ALTER_ROOT ]] && \ log_must $RM -rf $ALTER_ROOT } +function perform_inner_test +{ + target=$1 + + log_must $ZPOOL import ${devs[i]} ${options[j]} \ + $target ${pools[i]}-new + + log_must poolexists "${pools[i]}-new" + + log_must ismounted ${pools[i]}-new/$TESTFS + + basedir=${mtpts[i]} + [[ -n ${options[j]} ]] && \ + basedir=$ALTER_ROOT/${mtpts[i]} + + [[ ! -e $basedir/$TESTFILE0 ]] && \ + log_fail "$basedir/$TESTFILE0 missing after import." + + checksum2=$($SUM $basedir/$TESTFILE0 | $AWK '{print $1}') + [[ "$checksum1" != "$checksum2" ]] && \ + log_fail "Checksums differ ($checksum1 != $checksum2)" + + log_must $ZPOOL export "${pools[i]}-new" + + [[ -d /${pools[i]}-new ]] && \ + log_must $RM -rf /${pools[i]}-new + + target=${pools[i]}-new + if (( RANDOM % 2 == 0 )) ; then + target=$guid + fi + log_must $ZPOOL import ${devs[i]} $target ${pools[i]} +} + log_onexit cleanup log_assert "Verify that an imported pool can be renamed." setup_filesystem "$DEVICE_FILES" $TESTPOOL1 $TESTFS $TESTDIR1 checksum1=$($SUM $MYTESTFILE | $AWK '{print $1}') typeset -i i=0 typeset -i j=0 typeset basedir while (( i < ${#pools[*]} )); do guid=$(get_config ${pools[i]} pool_guid) log_must $CP $MYTESTFILE ${mtpts[i]}/$TESTFILE0 log_must $ZFS umount ${mtpts[i]} j=0 while (( j < ${#options[*]} )); do log_must $ZPOOL export ${pools[i]} [[ -d /${pools[i]} ]] && \ log_must $RM -rf /${pools[i]} - typeset target=${pools[i]} - if (( RANDOM % 2 == 0 )) ; then - target=$guid - log_note "Import by guid." - fi - - log_must $ZPOOL import ${devs[i]} ${options[j]} \ - $target ${pools[i]}-new + log_note "Testing import by name." + perform_inner_test ${pools[i]} - log_must poolexists "${pools[i]}-new" + log_must $ZPOOL export ${pools[i]} - log_must ismounted ${pools[i]}-new/$TESTFS - - basedir=${mtpts[i]} - [[ -n ${options[j]} ]] && \ - basedir=$ALTER_ROOT/${mtpts[i]} - - [[ ! -e $basedir/$TESTFILE0 ]] && \ - log_fail "$basedir/$TESTFILE0 missing after import." - - checksum2=$($SUM $basedir/$TESTFILE0 | $AWK '{print $1}') - [[ "$checksum1" != "$checksum2" ]] && \ - log_fail "Checksums differ ($checksum1 != $checksum2)" - - log_must $ZPOOL export "${pools[i]}-new" - - [[ -d /${pools[i]}-new ]] && \ - log_must $RM -rf /${pools[i]}-new - - target=${pools[i]}-new - if (( RANDOM % 2 == 0 )) ; then - target=$guid - fi - log_must $ZPOOL import ${devs[i]} $target ${pools[i]} + log_note "Testing import by GUID." + perform_inner_test $guid ((j = j + 1)) done ((i = i + 1)) done log_pass "Successfully imported and renamed a ZPOOL" Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_upgrade/zpool_upgrade.kshlib =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_upgrade/zpool_upgrade.kshlib (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/cli_root/zpool_upgrade/zpool_upgrade.kshlib (revision 292346) @@ -1,165 +1,159 @@ # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)zpool_upgrade.kshlib 1.5 08/02/27 SMI" # . $STF_SUITE/include/libtest.kshlib # This part of the test suite relies on variables being setup in the # zpool_upgrade.cfg script. Those variables give us details about which # files make up the pool, and what the pool name is. # A function to import a pool from files we have stored in the test suite # We import the pool, and create some random data in the pool. # $1 a version number we can use to get information about the pool function create_old_pool { VERSION=$1 POOL_FILES=$($ENV | grep "ZPOOL_VERSION_${VERSION}_FILES"\ | $AWK -F= '{print $2}') POOL_NAME=$($ENV|grep "ZPOOL_VERSION_${VERSION}_NAME"\ | $AWK -F= '{print $2}') log_note "Creating $POOL_NAME from $POOL_FILES" for pool_file in $POOL_FILES; do $CP -f $STF_SUITE/tests/cli_root/zpool_upgrade/blockfiles/$pool_file.Z \ $TMPDIR $UNCOMPRESS $TMPDIR/$pool_file.Z done log_must $ZPOOL import -d $TMPDIR $POOL_NAME # Now put some random contents into the pool. COUNT=0 while [ "$COUNT" -lt 1024 ]; do $DD if=/dev/urandom of=/$POOL_NAME/random.$COUNT \ count=1 bs=1024 > /dev/null 2>&1 COUNT=$(( $COUNT + 1 )) done } # A function to check the contents of a pool, upgrade it to the current version # and then verify that the data is consistent after upgrading. Note that we're # not using "zpool status -x" to see if the pool is healthy, as it's possible # to also upgrade faulted, or degraded pools. # $1 a version number we can use to get information about the pool function check_upgrade { VERSION=$1 POOL_NAME=$($ENV| $GREP "ZPOOL_VERSION_${VERSION}_NAME"\ | $AWK -F= '{print $2}') POOL_FILES=$($ENV | $GREP "ZPOOL_VERSION_${VERSION}_FILES"\ | $AWK -F= '{print $2}') log_note "Checking if we can upgrade from ZFS version ${VERSION}." PRE_UPGRADE_CHECKSUM=$(check_pool $POOL_NAME pre ) log_must $ZPOOL upgrade $POOL_NAME > /dev/null POST_UPGRADE_CHECKSUM=$(check_pool $POOL_NAME post ) log_note "Checking that there are no differences between checksum output" log_must $DIFF $PRE_UPGRADE_CHECKSUM $POST_UPGRADE_CHECKSUM $RM $PRE_UPGRADE_CHECKSUM $POST_UPGRADE_CHECKSUM } # A function to destroy an upgraded pool, plus the files it was based on. # $1 a version number we can use to get information about the pool function destroy_upgraded_pool { VERSION=$1 POOL_NAME=$($ENV|grep "ZPOOL_VERSION_${VERSION}_NAME"\ | $AWK -F= '{print $2}') POOL_FILES=$($ENV | grep "ZPOOL_VERSION_${VERSION}_FILES"\ | $AWK -F= '{print $2}') if poolexists "$POOL_NAME"; then log_must $ZPOOL destroy $POOL_NAME fi for file in $POOL_FILES; do if [ -e "$TMPDIR/$file" ]; then $RM $TMPDIR/$file fi done } # This function does a basic sanity check on the pool by computing the # checksums of all files in the pool, printing the name of the file containing # the checksum results. # $1 the name of the pool # $2 a flag we can use to determine when this check is being performed # (ie. pre or post pool-upgrade) function check_pool { # pool state POOL=$1 STATE=$2 $FIND /$POOL -type f -exec $CKSUM {} + > \ $TMPDIR/pool-checksums.$POOL.$STATE print $TMPDIR/pool-checksums.$POOL.$STATE } # This function simply checks that a pool has a particular version number # as reported by zdb and zpool upgrade -v # $1 the name of the pool # $2 the version of the pool we expect to see function check_poolversion { # pool version POOL=$1 VERSION=$2 # check version using zdb - ACTUAL=$($ZDB -eC -p $TMPDIR $POOL | $GREP version: | \ - $SED -e 's/ //g' -e 's/version://g') + ACTUAL=$(get_config $POOL version) + [ "$ACTUAL" != "$VERSION" ] && log_fail \ + "ERROR: $POOL not upgraded: wanted '$VERSION', got '$ACTUAL'" - if [ "$ACTUAL" != "$VERSION" ] - then - log_fail "$POOL not upgraded, ver. $ACTUAL, expected $VERSION" - fi - # check version using zpool upgrade ACTUAL=$($ZPOOL upgrade | $GREP $POOL$ | \ $AWK '{print $1}' | $SED -e 's/ //g') - if [ "$ACTUAL" != "$VERSION" ] - then - log_fail "$POOL reported version $ACTUAL, expected $VERSION" - fi + [ "$ACTUAL" != "$VERSION" ] && + log_fail "$POOL reported version '$ACTUAL', expected '$VERSION'" } # A simple function to get a random number between two bounds # probably not the most efficient for large ranges, but it's okay. # Note since we're using $RANDOM, 32767 is the largest number we # can accept as the upper bound. # $1 lower bound # $2 upper bound function random { # min max typeset MIN=$1 typeset MAX=$2 typeset RAND=0 while [ "$RAND" -lt "$MIN" ] do RAND=$(( $RANDOM % $MAX + 1)) done print $RAND } Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/grow_pool/setup.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/grow_pool/setup.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/grow_pool/setup.ksh (revision 292346) @@ -1,48 +1,49 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)setup.ksh 1.4 09/01/12 SMI" # . $STF_SUITE/include/libtest.kshlib verify_runnable "global" if ! $(is_physical_device $DISKS) ; then log_unsupported "This directory cannot be run on raw files." fi if [[ -n $DISK ]]; then log_note "No spare disks available. Using slices on $DISK" log_must partition_disk $SIZE $DISK 2 tmp=${DISK}p1 else - log_must set_partition $PARTITION "" $SIZE $DISK0 - log_must set_partition $PARTITION "" $SIZE $DISK1 + wipe_partition_table $DISK0 $DISK1 + log_must set_partition $PARTITION "" $SIZE $DISK0 + log_must set_partition $PARTITION "" $SIZE $DISK1 tmp=$DISK0"p"$PARTITION fi default_setup $tmp Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/grow_replicas/setup.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/grow_replicas/setup.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/grow_replicas/setup.ksh (revision 292346) @@ -1,60 +1,61 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)setup.ksh 1.5 09/06/22 SMI" # . $STF_SUITE/include/libtest.kshlib verify_runnable "global" if ! $(is_physical_device $DISKS) ; then log_unsupported "This directory cannot be run on raw files." fi log_note "Creating pool type: $POOLTYPE" if [[ -n $DISK ]]; then - log_note "No spare disks available. Using slices on $DISK" - partition_disk $SIZE $DISK 4 - create_pool $TESTPOOL $POOLTYPE ${DISK}p1 \ + log_note "No spare disks available. Using slices on $DISK" + partition_disk $SIZE $DISK 4 + create_pool $TESTPOOL $POOLTYPE ${DISK}p1 \ ${DISK}p2 else - log_must set_partition $PARTITION "" $SIZE $DISK0 - log_must set_partition $PARTITION "" $SIZE $DISK1 - log_must set_partition $PARTITION "" $SIZE $DISK2 - log_must set_partition $PARTITION "" $SIZE $DISK3 - create_pool $TESTPOOL $POOLTYPE ${DISK0}p${PARTITION} \ + wipe_partition_table $DISK0 $DISK1 $DISK2 $DISK3 + log_must set_partition $PARTITION "" $SIZE $DISK0 + log_must set_partition $PARTITION "" $SIZE $DISK1 + log_must set_partition $PARTITION "" $SIZE $DISK2 + log_must set_partition $PARTITION "" $SIZE $DISK3 + create_pool $TESTPOOL $POOLTYPE ${DISK0}p${PARTITION} \ ${DISK1}p${PARTITION} fi $RM -rf $TESTDIR || log_unresolved Could not remove $TESTDIR $MKDIR -p $TESTDIR || log_unresolved Could not create $TESTDIR log_must $ZFS create $TESTPOOL/$TESTFS log_must $ZFS set mountpoint=$TESTDIR $TESTPOOL/$TESTFS log_pass Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/hotspare/hotspare.kshlib =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/hotspare/hotspare.kshlib (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/hotspare/hotspare.kshlib (revision 292346) @@ -1,124 +1,124 @@ # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)hotspare.kshlib 1.6 09/06/22 SMI" # . $STF_SUITE/include/libtest.kshlib . $STF_SUITE/tests/cli_root/zpool_add/zpool_add.kshlib function cleanup_devices_all { $RM -f ${devarray[*]} - [ -n "$HOTSPARE_TMPDIR" ] && rmdir $HOTSPARE_TMPDIR + [ -d "$HOTSPARE_TMPDIR" ] && rmdir $HOTSPARE_TMPDIR return 0 } typeset -a pooldevs typeset -a sparedevs typeset -a logdevs typeset -a keywords=("" "mirror" "raidz" "raidz2") typeset -a devarray function set_devs { mkdir $HOTSPARE_TMPDIR typeset -i i=0 while (( i < $N_DEVARRAY_FILES )) ; do eval devarray[$i]=$HOTSPARE_TMPDIR/file.$i $MKFILE $SIZE ${devarray[$i]} (( i = i + 1 )) done sparedevs=("${devarray[0]}" "${devarray[1]}") pooldevs=("${devarray[3]}" "${devarray[4]}" "${devarray[5]}") if verify_slog_support ; then logdevs="${devarray[7]}" fi } function partition_cleanup { cleanup_devices_all return 0 } # # $1: keyword, should be "" "mirror" "raidz" "raidz2" # $2: hotspare list, default as $sparedevs # function setup_hotspares # keyword, spares { typeset keyword=$1 shift typeset spares=${@:-${sparedevs[@]}} create_pool "$TESTPOOL" "$keyword" \ ${pooldevs[@]} log_must poolexists "$TESTPOOL" log_must $ZPOOL set autoreplace=on "$TESTPOOL" log_must $ZPOOL add -f "$TESTPOOL" spare $spares log_must iscontained "$TESTPOOL" "$spares" if [[ -n ${logdevs[@]} ]] ; then log_must $ZPOOL add -f "$TESTPOOL" log ${logdevs[@]} log_must iscontained "$TESTPOOL" "${logdevs[@]}" fi } # # $1: the function name that run for all hotspares # $2: hotspare list, default as $sparedevs # function iterate_over_hotspares # function, spares { typeset function=$1 typeset spares=${2:-${sparedevs[@]}} for spare in $spares do $function $spare done } wait_until_resilvered() { typeset -i i=0 typeset -i timeout=60 while [[ $i -lt $timeout ]]; do if is_pool_resilvered $TESTPOOL; then break fi (( i += 1 )) if [[ $i == $timeout ]]; then log_fail "Pool didn't resilver in ${timeout} seconds" fi $SLEEP 1 done } Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/hotspare/hotspare_replace_003_neg.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/hotspare/hotspare_replace_003_neg.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/hotspare/hotspare_replace_003_neg.ksh (revision 292346) @@ -1,175 +1,177 @@ #!/usr/local/bin/ksh93 # # Copyright (c) 2010 Spectra Logic Corporation # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions, and the following disclaimer, # without modification. # 2. Redistributions in binary form must reproduce at minimum a disclaimer # substantially similar to the "NO WARRANTY" disclaimer below # ("Disclaimer") and any redistribution must be conditioned upon # including a substantially similar Disclaimer requirement for further # binary redistribution. # # NO WARRANTY # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGES. # # $Id$ # $FreeBSD$ . $STF_SUITE/include/libtest.kshlib . $STF_SUITE/include/libsas.kshlib . $STF_SUITE/tests/hotspare/hotspare.kshlib # Reproduction script for Rally DE189: # https://rally1.rallydev.com/#/9096795496d/detail/defect/13345916506 # # To reproduce, from Keith's email: # 1. Create a 3 drive raid. # 2. Disable a drive # 3. Let a Spare take over # 4. Disable that Spare when it is done rebuilding. # 5. Let 2nd spare finish rebuilding # 6. Enable the first spare # 7. Enable the original drive # 8. Destroy the pool. cleanup() { + [[ $DISK0_PHY != 0 ]] && enable_sas_disk $DISK0_EXPANDER $DISK0_PHY + [[ $SPARE0_PHY != 0 ]] && enable_sas_disk $SPARE0_EXPANDER $SPARE0_PHY + [[ $SPARE1_PHY != 0 ]] && enable_sas_disk $SPARE1_EXPANDER $SPARE1_PHY + rescan_disks if poolexists $TESTPOOL; then # Test failed, provide something useful. log_note "For reference, here is the final $TESTPOOL status:" zpool status $TESTPOOL log_must destroy_pool $TESTPOOL fi - [[ $DISK0_PHY != 0 ]] && enable_sas_disk $DISK0_EXPANDER $DISK0_PHY - [[ $SPARE0_PHY != 0 ]] && enable_sas_disk $SPARE0_EXPANDER $SPARE0_PHY - [[ $SPARE1_PHY != 0 ]] && enable_sas_disk $SPARE1_EXPANDER $SPARE1_PHY } log_onexit cleanup trap cleanup TERM INT typeset -A MEMBERS typeset -A SPARES typeset DISK0_EXPANDER=0 typeset DISK0_PHY=0 typeset SPARE0_EXPANDER=0 typeset SPARE0_PHY=0 typeset SPARE1_EXPANDER=0 typeset SPARE1_PHY=0 for disk in $DISKS; do if [[ $DISK0_PHY == 0 ]]; then find_verify_sas_disk $disk DISK0_PHY=$PHY DISK0_EXPANDER=$EXPANDER DISK0_NAME=$disk set -A MEMBERS "${MEMBERS[@]}" $disk continue fi if [[ $SPARE0_PHY == 0 ]]; then find_verify_sas_disk $disk SPARE0_PHY=$PHY SPARE0_EXPANDER=$EXPANDER SPARE0_NAME=$disk set -A SPARES "${SPARES[@]}" $disk continue fi if [[ $SPARE1_PHY == 0 ]]; then find_verify_sas_disk $disk SPARE1_PHY=$PHY SPARE1_EXPANDER=$EXPANDER SPARE1_NAME=$disk set -A SPARES "${SPARES[@]}" $disk continue fi # Already filled those positions? Add disks to the raidz. if [[ ${#DISKS[*]} -lt 3 ]]; then find_verify_sas_disk $disk [[ -z "$DISK1_NAME" ]] && DISK1_NAME=$disk DISK1_LONG_NAME=`find_disks ${DISK1_NAME}` DISK1_SHORT_NAME=${DISK1_LONG_NAME##/dev/} set -A MEMBERS "${MEMBERS[@]}" $disk continue fi break done # Remove labels etc. from all the disks we're about to use. poolexists && log_must destroy_pool $TESTPOOL cleanup_devices ${MEMBERS[*]} ${SPARES[*]} log_must $ZPOOL create -f $TESTPOOL raidz1 ${MEMBERS[@]} spare ${SPARES[@]} DISK0_GUID=$(get_disk_guid $DISK0_NAME) log_must disable_sas_disk $DISK0_EXPANDER $DISK0_PHY log_must $ZPOOL replace $TESTPOOL $DISK0_GUID $SPARE0_NAME wait_until_resilvered SPARE0_GUID=$(get_disk_guid $SPARE0_NAME) log_must disable_sas_disk $SPARE0_EXPANDER $SPARE0_PHY log_must $ZPOOL replace $TESTPOOL $SPARE0_GUID $SPARE1_NAME wait_until_resilvered log_must enable_sas_disk $SPARE0_EXPANDER $SPARE0_PHY log_must enable_sas_disk $DISK0_EXPANDER $DISK0_PHY +log_must rescan_disks log_must destroy_pool $TESTPOOL # Screen scrape the 'zpool import' output to ensure that the pool doesn't # show up, since it's been destroyed. badpoolstate=0 $ZPOOL import | \ while read word1 word2 rest; do echo "$word1 $word2 $rest" case "$word1 $word2" in "pool: $TESTPOOL") (( badpoolstate += 1 )) ;; "$DISK1_LONG_NAME ONLINE") (( badpoolstate += 2 )) ;; "$DISK1_SHORT_NAME ONLINE") (( badpoolstate += 2 )) ;; *) ;; esac done case $badpoolstate in 0) log_pass ;; 1) log_note "Destroyed pool visible, but probably another pool" log_pass ;; 2) log_fail "One of our disks is visible but pool is not?!" ;; 3) log_fail "Destroyed pool visible!" ;; *) log_fail "Unexpected output. Update the test" ;; esac # Bad output looks like this: # pool: testpool.2358 # id: 5289863802080396071 # state: UNAVAIL # status: One or more devices are missing from the system. # action: The pool cannot be imported. Attach the missing # devices and try again. # see: http://illumos.org/msg/ZFS-8000-6X # config: # # testpool.2358 UNAVAIL missing device # raidz1-0 DEGRADED # spare-0 UNAVAIL # 4564766431272474500 FAULTED corrupted data # 1988887717739330825 FAULTED corrupted data # da4 ONLINE # da5 ONLINE # spares # 1988887717739330825 # da3 Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/interop/setup.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/interop/setup.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/interop/setup.ksh (revision 292346) @@ -1,80 +1,81 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)setup.ksh 1.5 09/06/22 SMI" # . $STF_SUITE/include/libtest.kshlib verify_runnable "global" case $DISK_COUNT in 0) log_untested "Need at least 1 disk device for test" ;; 1) log_note "Partitioning a single disk ($SINGLE_DISK)" ;; 2) log_note "Partitioning a disks ($SINGLE_DISK) and ($ZFS_DISK2)" ;; 3) log_note "Partitioning disks ($META_DISK0 $META_DISK1 $ZFS_DISK2)" ;; esac +wipe_partition_table $META_DISK0 log_must set_partition ${META_SIDE0##*s} "" $FS_SIZE $META_DISK0 if [[ $WRAPPER == *"smi"* && $META_DISK1 == $META_DISK0 ]]; then typeset i=${META_SIDE0##*s} typeset cyl=$(get_endslice $META_DISK0 $i) log_must set_partition ${META_SIDE1##*s} "$cyl" $FS_SIZE $META_DISK1 else log_must set_partition ${META_SIDE1##*s} "" $FS_SIZE $META_DISK1 fi if [[ $WRAPPER == *"smi"* && $ZFS_DISK2 == $META_DISK1 ]]; then typeset i=${META_SIDE1##*s} typeset cyl=$(get_endslice $META_DISK1 $i) log_must set_partition ${ZFS_SIDE2##*s} "$cyl" $FS_SIZE $ZFS_DISK2 else log_must set_partition ${ZFS_SIDE2##*s} "" $FS_SIZE $ZFS_DISK2 fi create_pool $TESTPOOL $ZFS_SIDE2 $RM -rf $TESTDIR || log_unresolved Could not remove $TESTDIR $MKDIR -p $TESTDIR || log_unresolved Could not create $TESTDIR log_must $ZFS create $TESTPOOL/$TESTFS log_must $ZFS set mountpoint=$TESTDIR $TESTPOOL/$TESTFS log_must $ZFS set compression=off $TESTPOOL/$TESTFS log_note "Configuring metadb with $META_SIDE1" log_must $METADB -a -f -c 3 $META_SIDE1 log_note "Configure $META_DEVICE_ID with $META_SIDE0" log_must $METAINIT $META_DEVICE_ID 1 1 $META_SIDE0 log_pass Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/inuse/inuse_008_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/inuse/inuse_008_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/inuse/inuse_008_pos.ksh (revision 292346) @@ -1,122 +1,123 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)inuse_008_pos.ksh 1.5 09/06/22 SMI" # . $STF_SUITE/include/libtest.kshlib ################################################################################ # # __stc_assertion_start # # ID: inuse_008_pos # # DESCRIPTION: # Newfs will interfere with devices and spare devices that are in use # by exported pool. # # STRATEGY: # 1. Create a regular|mirror|raidz|raidz2 pool with the given disk # 2. Export the pool # 3. Try to newfs against the disk, verify it succeeds as expect. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING_STATUS: COMPLETED (2006-07-11) # # __stc_assertion_end # ################################################################################ verify_runnable "global" function cleanup { poolexists $TESTPOOL1 || $ZPOOL import $TESTPOOL1 >/dev/null 2>&1 poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1 # # Tidy up the disks we used. # cleanup_devices $vdisks $sdisks } function verify_assertion #slices { typeset targets=$1 for t in $targets; do $ECHO "y" | $NEWFS $t > /dev/null 2>&1 (( $? !=0 )) && \ log_fail "newfs over exported pool "\ "fails unexpected." done return 0 } log_assert "Verify newfs over exported pool succeed." log_onexit cleanup set -A vdevs "" "mirror" "raidz" "raidz1" "raidz2" typeset -i i=0 +wipe_partition_table $disk for num in 0 1 2 3 ; do eval typeset partition=\${FS_SIDE$num} disk=${partition%p*} partition=${partition##*p} if [[ $WRAPPER == *"smi"* && \ $disk == ${saved_disk} ]]; then cyl=$(get_endslice $disk ${saved_partition}) log_must set_partition $partition "$cyl" $FS_SIZE $disk else log_must set_partition $partition "" $FS_SIZE $disk fi saved_disk=$disk saved_partition=$partition done while (( i < ${#vdevs[*]} )); do if [[ -n $SINGLE_DISK && -n ${vdevs[i]} ]]; then (( i = i + 1 )) continue fi create_pool $TESTPOOL1 ${vdevs[i]} $vslices spare $sslices log_must $ZPOOL export $TESTPOOL1 verify_assertion "$rawtargets" cleanup_devices $vslices $sslices (( i = i + 1 )) done log_pass "Newfs over exported pool succeed." Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/inuse/inuse_009_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/inuse/inuse_009_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/inuse/inuse_009_pos.ksh (revision 292346) @@ -1,133 +1,134 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)inuse_009_pos.ksh 1.4 09/06/22 SMI" # . $STF_SUITE/include/libtest.kshlib ################################################################################ # # __stc_assertion_start # # ID: inuse_009_pos # # DESCRIPTION: # format command will interfere with devices and spare devices that are in use # by exported pool. # # STRATEGY: # 1. Create a regular|mirror|raidz|raidz2 pool with the given disk # 2. Export the pool # 3. Try to format against the disk, verify it succeeds as expect. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING_STATUS: COMPLETED (2006-09-05) # # __stc_assertion_end # ################################################################################ verify_runnable "global" function cleanup { poolexists $TESTPOOL1 || $ZPOOL import $TESTPOOL1 >/dev/null 2>&1 poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1 # # Tidy up the disks we used. # cleanup_devices $vdisks $sdisks } function verify_assertion #disks { typeset targets=$1 for t in $targets; do log_must wipe_partition_table $t done return 0 } log_assert "Verify format over exported pool succeed." log_onexit cleanup set -A vdevs "" "mirror" "raidz" "raidz1" "raidz2" typeset -i i=0 +wipe_partition_table ${vdisks} while (( i < ${#vdevs[*]} )); do for num in 0 1 2 3 ; do eval typeset partition=\${FS_SIDE$num} disk=${partition%p*} partition=${partition##*p} if [[ $WRAPPER == *"smi"* && \ $disk == ${saved_disk} ]]; then cyl=$(get_endslice $disk ${saved_partition}) log_must set_partition $partition "$cyl" $FS_SIZE $disk else log_must set_partition $partition "" $FS_SIZE $disk fi saved_disk=$disk saved_partition=$partition done if [[ -n $SINGLE_DISK && -n ${vdevs[i]} ]]; then (( i = i + 1 )) continue fi create_pool $TESTPOOL1 ${vdevs[i]} $vslices spare $sslices log_must $ZPOOL export $TESTPOOL1 verify_assertion "$vdisks $sdisks" if [[ ( $FS_DISK0 == $FS_DISK2 ) && -n ${vdevs[i]} ]]; then (( i = i + 1 )) continue fi if [[ ( $FS_DISK0 == $FS_DISK3 ) && ( ${vdevs[i]} == "raidz2" ) ]]; then (( i = i + 1 )) continue fi create_pool $TESTPOOL1 ${vdevs[i]} $vdisks spare $sdisks log_must $ZPOOL export $TESTPOOL1 verify_assertion "$vdisks $sdisks" (( i = i + 1 )) done log_pass "Format over exported pool succeed." Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/migration/setup.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/migration/setup.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/migration/setup.ksh (revision 292346) @@ -1,66 +1,67 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)setup.ksh 1.4 09/06/22 SMI" # . $STF_SUITE/include/libtest.kshlib verify_runnable "global" case $DISK_COUNT in 0) log_untested "Need at least 1 disk device for test" ;; 1) log_note "Partitioning a single disk ($SINGLE_DISK)" ;; *) log_note "Partitioning disks ($ZFS_DISK $NONZFS_DISK)" ;; esac +wipe_partition_table $ZFS_DISK $NONZFS_DISK set_partition ${ZFSSIDE_DISK##*p} "" $FS_SIZE $ZFS_DISK set_partition ${NONZFSSIDE_DISK##*p} "" $FS_SIZE $NONZFS_DISK log_must create_pool $TESTPOOL "$ZFSSIDE_DISK" $RM -rf $TESTDIR || log_unresolved Could not remove $TESTDIR $MKDIR -p $TESTDIR || log_unresolved Could not create $TESTDIR log_must $ZFS create $TESTPOOL/$TESTFS log_must $ZFS set mountpoint=$TESTDIR $TESTPOOL/$TESTFS $RM -rf $NONZFS_TESTDIR || log_unresolved Could not remove $NONZFS_TESTDIR $MKDIR -p $NONZFS_TESTDIR || log_unresolved Could not create $NONZFS_TESTDIR $NEWFS $NONZFSSIDE_DISK (( $? != 0 )) && log_untested "Unable to setup a UFS file system" log_must $MOUNT $NONZFSSIDE_DISK $NONZFS_TESTDIR log_pass Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/no_space/setup.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/no_space/setup.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/no_space/setup.ksh (revision 292346) @@ -1,41 +1,42 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)setup.ksh 1.4 09/01/12 SMI" # . $STF_SUITE/include/libtest.kshlib verify_runnable "global" if ! $(is_physical_device $DISKS) ; then log_unsupported "This directory cannot be run on raw files." fi DISK=${DISKS%% *} +wipe_partition_table $DISK log_must set_partition 1 "" $SIZE $DISK default_setup $DISK"p1" Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/sas_phy_thrash/sas_phy_thrash_001_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/sas_phy_thrash/sas_phy_thrash_001_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/sas_phy_thrash/sas_phy_thrash_001_pos.ksh (revision 292346) @@ -1,161 +1,163 @@ #!/usr/local/bin/ksh93 # # Copyright (c) 2010 Spectra Logic Corporation # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions, and the following disclaimer, # without modification. # 2. Redistributions in binary form must reproduce at minimum a disclaimer # substantially similar to the "NO WARRANTY" disclaimer below # ("Disclaimer") and any redistribution must be conditioned upon # including a substantially similar Disclaimer requirement for further # binary redistribution. # # NO WARRANTY # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGES. # # $Id: //SpectraBSD/stable/tests/sys/cddl/zfs/tests/sas_phy_thrash/sas_phy_thrash_001_pos.ksh#2 $ # $FreeBSD$ # . $STF_SUITE/include/libtest.kshlib . $STF_SUITE/include/libsas.kshlib typeset -i NUM_FAILURES=0 export NUM_FAILURES # Cleanup function. Kill each of the children, they will re-enable the PHY # they're working on. function docleanup { for CPID in $CHILDREN do echo "Killing $CPID" kill $CPID done } # If we get killed, try to re-enable the PHY we were toggling. function diskcleanup { log_note "Got a signal, sending linkreset to $EXPANDER phy $PHY" camcontrol smppc $EXPANDER -o linkreset -p $PHY exit 0 } # Wait for the timeout, and then kill the child processes. function disktimeout { log_note "disktimeout process waiting $1 seconds" sleep $1 docleanup } export CHILDREN="" export FAILFILES="" log_onexit docleanup typeset i=0 typeset -i num_disks_used=0 for i in $DISKS do # See if this disk is attached to a parent that supports SMP # XXX this only works with the current scheme where SMP commands get # sent to a device or its parent, if the device doesn't support SMP camcontrol smprg $i > /dev/null 2>&1 if [ $? != 0 ]; then continue fi # Find the expander and PHY that this disk is attached to, if any. # We will exit from here if there is a failure. find_verify_sas_disk $i typeset -i x=0 log_note "running test on $i on $EXPANDER phy $PHY" export FAILFILE=$TMPDIR/${EXPANDER}.${PHY}.failed trap diskcleanup INT TERM && rm -f $FAILFILE && while `true`; do ((x=x+1)) log_note "attempt number $x on $EXPANDER phy $PHY" camcontrol smppc $EXPANDER -v -o disable -p $PHY if [ $? != 0 ]; then log_note "Failed to disable $EXPANDER phy $PHY" echo "Expander $EXPANDER phy $PHY failed" >> $FAILFILE break fi $SLEEP 10 camcontrol smppc $EXPANDER -v -o linkreset -p $PHY if [ $? != 0 ]; then log_note "Failed to reset $EXPANDER phy $PHY" echo "Expander $EXPANDER phy $PHY failed" >> $FAILFILE break fi $SLEEP 10 find_disk_by_phy $EXPANDER $PHY + [ -z "$FOUNDDISK" ] && \ + log_fail "Disk for ${EXPANDER}:${PHY} didn't return" camcontrol inquiry $FOUNDDISK -v if [ $? != 0 ]; then log_note "Failed on $EXPANDER phy $PHY attempt $x" echo "Expander $EXPANDER phy $PHY failed" >> $FAILFILE break fi done & CHILDREN="$CHILDREN $!" FAILFILES="$FAILFILES $FAILFILE" ((num_disks_used++)) done # The minimum sleep time is 3 minutes for 8 or more disks. For fewer # disks, we need to go longer to generate the number of events necessasry # to trigger the bug. Scale it up by the number of disks we actually have. typeset -i sleep_time=$SAS_DEFAULT_TIME if [ $num_disks_used -lt $SAS_MIN_DEFAULT_DISKS ]; then ((sleep_time *= (SAS_MIN_DEFAULT_DISKS / num_disks_used))) fi # XXX KDM need to stop the entire test as soon as any one of the child # processes fails. How does that work in the test framework? if [ $num_disks_used -gt 0 ]; then log_note "Tests queued on $num_disks_used disks" log_note "Waiting $sleep_time seconds for potential driver failure" disktimeout $sleep_time & wait # sleep $sleep_time for i in $FAILFILES; do typeset FILEBASE=${i%%.failed} FILEBASE=${FILEBASE##$TMPDIR/} if [ -f $i ]; then log_note "Test of $FILEBASE failed" ((NUM_FAILURES=NUM_FAILURES+1)) rm -f $i else log_note "Test of $FILEBASE passed" fi done if [ $NUM_FAILURES -gt 0 ]; then log_fail "Saw $NUM_FAILURES failures" else log_note "Number of failures: $NUM_FAILURES" log_pass fi else log_unsupported "No tests queued, no SMP-capable devices found" fi Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/scrub_mirror/setup.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/scrub_mirror/setup.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/scrub_mirror/setup.ksh (revision 292346) @@ -1,48 +1,49 @@ #! /usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # ident "@(#)setup.ksh 1.5 09/01/12 SMI" # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # . $STF_SUITE/include/libtest.kshlib verify_runnable "global" if ! $(is_physical_device $DISKS) ; then log_unsupported "This directory cannot be run on raw files." fi if [[ -n $SINGLE_DISK ]]; then log_note "Partitioning a single disk ($SINGLE_DISK)" else log_note "Partitioning disks ($MIRROR_PRIMARY $MIRROR_SECONDARY)" fi +wipe_partition_table $SINGLE_DISK $MIRROR_PRIMARY $MIRROR_SECONDARY log_must set_partition ${SIDE_PRIMARY##*p} "" $MIRROR_SIZE $MIRROR_PRIMARY log_must set_partition ${SIDE_SECONDARY##*p} "" $MIRROR_SIZE $MIRROR_SECONDARY default_mirror_setup $SIDE_PRIMARY $SIDE_SECONDARY log_pass Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/write_dirs/setup.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/write_dirs/setup.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/write_dirs/setup.ksh (revision 292346) @@ -1,42 +1,43 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)setup.ksh 1.4 09/01/12 SMI" # . $STF_SUITE/include/libtest.kshlib verify_runnable "global" if ! $(is_physical_device $DISKS) ; then log_unsupported "This directory cannot be run on raw files." fi DISK=${DISKS%% *} +wipe_partition_table $DISK log_must set_partition $PARTITION "" $SIZE $DISK default_setup "$DISK"p"$PARTITION" Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd.kshlib =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd.kshlib (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd.kshlib (revision 292346) @@ -1,156 +1,184 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2013 Spectra Logic. All rights reserved. # Use is subject to license terms. # # Common routines used by multiple zfsd tests +function wait_for_disk_to_reappear +{ + typeset -i timeout=$1 + typeset EXPECTED_DISK=$2 + + for ((; $timeout > 0; timeout=$timeout-1)); do + find_disk_by_phy $EXPANDER $PHY + [ -n "$FOUNDDISK" ] && return + $SLEEP 3 + done + log_fail "ERROR: Disk ${EXPECTED_DISK} never reappeared" +} + +function wait_for_pool_dev_state_change +{ + typeset -i timeout=$1 + typeset disk=$2 + typeset state=$3 + + log_note "Waiting up to $timeout seconds for $disk to become $state ..." + for ((; $timeout > 0; timeout=$timeout-1)); do + check_state $TESTPOOL "$disk" "$state" + [ $? -eq 0 ] && return + $SLEEP 1 + done + log_must $ZPOOL status $TESTPOOL + log_fail "ERROR: Disk $disk not marked as $state in $TESTPOOL" +} + +function wait_for_pool_removal +{ + typeset -i timeout=$1 + wait_for_pool_dev_state_change $timeout $REMOVAL_DISK REMOVED +} + +function wait_until_scrubbed +{ + typeset pool=$1 + + while is_pool_scrubbing $pool; do + log_note "$pool still scrubbing..." + $SLEEP 1 + done +} + +function corrupt_pool_vdev +{ + typeset pool=$1 + typeset vdev=$2 + typeset file=$3 + + # do some IO on the pool + log_must $DD if=/dev/zero of=$file bs=1024k count=16 + # scribble on the underlying file to corrupt the vdev + log_must $DD if=/dev/urandom of=$vdev bs=1024k count=64 conv=notrunc + + # Scrub the pool to detect the corruption + $SYNC + log_must $ZPOOL scrub $pool + wait_until_scrubbed $pool + + # ZFSD can take up to 60 seconds to degrade an array in response to + # errors (though it's usually faster). + wait_for_pool_dev_state_change 60 $vdev DEGRADED +} + # # do_autoreplace # Common code that walks through an autoreplace scenario # Does not verify the final behavior # # $1 spare disk name. Empty if no spare # function do_autoreplace { typeset SPARE_DISK=$1 # Remove a vdev by disabling its SAS phy find_verify_sas_disk $REMOVAL_DISK log_note "Disabling \"$REMOVAL_DISK\" on expander $EXPANDER phy $PHY" disable_sas_disk $EXPANDER $PHY - #Check to make sure the disk is gone - camcontrol inquiry $REMOVAL_DISK > /dev/null 2>&1 - if [ $? = 0 ]; then - log_fail "Disk \"$REMOVAL_DISK\" was not removed" - fi + # Check to make sure the disk is gone + log_mustnot camcontrol inquiry $REMOVAL_DISK # Check to make sure ZFS sees the disk as removed - for ((timeout=0; $timeout<30; timeout=$timeout+1)); do - check_state $TESTPOOL "$REMOVAL_DISK" "REMOVED" - is_removed=$? - if [[ $is_removed == 0 ]]; then - break - fi - $SLEEP 3 - done - log_must check_state $TESTPOOL "$REMOVAL_DISK" "REMOVED" + wait_for_pool_removal 30 if [ -n "$SPARE_DISK" ]; then # Verify that the spare activates for ((timeout=0; $timeout<10; timeout=$timeout+1)); do - if check_state $TESTPOOL $SPARE_DISK "ONLINE"; then - break - fi + check_state $TESTPOOL $SPARE_DISK "ONLINE" && break $SLEEP 6 done log_must check_state $TESTPOOL "$SPARE_DISK" "ONLINE" wait_until_resilvered fi # Export the pool # This is to prevent REMOVAL_DISK from being added to the pool when # we reenable its phy log_must $ZPOOL export $TESTPOOL # Reenable the missing dev's SAS phy log_note "Reenabling phy on expander $EXPANDER phy $PHY" enable_sas_disk $EXPANDER $PHY - # Check that the disk has returned - for ((timeout=0; $timeout<30; timeout=$timeout+1)); do - find_disk_by_phy $EXPANDER $PHY - if [[ -n "$FOUNDDISK" ]]; then - break - fi - $SLEEP 3 - done + rescan_disks $EXPANDER + wait_for_disk_to_reappear 30 $REMOVAL_DISK - if [[ -z "$FOUNDDISK" ]]; then - log_fail "Disk $REMOVAL_DISK never reappeared" - fi - # Erase the missing dev's ZFS label log_must $ZPOOL labelclear -f $( find_disks $FOUNDDISK ) # Disable the missing dev's SAS phy again find_verify_sas_disk $FOUNDDISK log_note "Disabling \"$FOUNDDISK\" on expander $EXPANDER phy $PHY" disable_sas_disk $EXPANDER $PHY - #Check to make sure the disk is gone - camcontrol inquiry $FOUNDDISK > /dev/null 2>&1 - if [ $? = 0 ]; then - log_fail "Disk \"$FOUNDDISK\" was not removed" - fi + # Check to make sure the disk is gone + log_mustnot camcontrol inquiry $REMOVAL_DISK # Import the pool log_must $ZPOOL import $TESTPOOL # Wait 5 seconds before enabling the phy so zfsd.log will be easier # to interpret $SLEEP 5 # Reenable the missing dev's SAS phy log_note "Reenabling phy on expander $EXPANDER phy $PHY" enable_sas_disk $EXPANDER $PHY - # Check that the disk has returned - for ((timeout=0; $timeout<30; timeout=$timeout+1)); do - find_disk_by_phy $EXPANDER $PHY - if [[ -n "$FOUNDDISK" ]]; then - break - fi - $SLEEP 3 - done - - if [[ -z "$FOUNDDISK" ]]; then - log_fail "Disk $FOUNDDISK never reappeared" - fi + rescan_disks $EXPANDER + wait_for_disk_to_reappear 30 $REMOVAL_DISK } function autoreplace_cleanup { - poolexists $TESTPOOL && \ - destroy_pool $TESTPOOL + destroy_pool $TESTPOOL # See if the phy has been disabled, and try to re-enable it if possible. - echo DISK params are "$REMOVAL_DISK" $EXPANDER $PHY - if [ -n "$REMOVAL_DISK" ]; then - if [ -n "$EXPANDER" ] && [ -n "$PHY" ]; then - log_note "Renabling ${EXPANDER}:${PHY} for disk ${REMOVAL_DISK}" - enable_sas_disk $EXPANDER $PHY - # For debugging purposes, log the partial output of - # camcontrol to see if the disk actually came back. - log_note `camcontrol smpphylist ${EXPANDER} | ${GREP} "^ *${PHY}"` - fi + if [ -n "$REMOVAL_DISK" -a -n "$EXPANDER" -a -n "$PHY" ]; then + log_note "Renabling ${EXPANDER}:${PHY} for disk ${REMOVAL_DISK}" + enable_sas_disk $EXPANDER $PHY + rescan_disks $EXPANDER + + # For debugging purposes, log the partial output of + # camcontrol to see if the disk actually came back. + out=$(camcontrol smpphylist ${EXPANDER} | ${GREP} "^ *${PHY}") + log_note "Expander has: ${out}" fi [[ -e $TESTDIR ]] && log_must $RM -rf $TESTDIR/* partition_cleanup + restart_zfsd } - - Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_autoreplace_001_neg.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_autoreplace_001_neg.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_autoreplace_001_neg.ksh (revision 292346) @@ -1,92 +1,93 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2013 Spectra Logic. All rights reserved. # Use is subject to license terms. # # ident "@(#)hotspare_replace_007_pos.ksh 1.0 12/08/10 SL" # . $STF_SUITE/tests/hotspare/hotspare.kshlib . $STF_SUITE/tests/zfsd/zfsd.kshlib . $STF_SUITE/include/libsas.kshlib ################################################################################ # # __stc_assertion_start # # ID: zfsd_autoreplace_001_neg # # DESCRIPTION: # In a pool with the autoreplace property unset, a vdev will not be # replaced by physical path # # STRATEGY: # 1. Create 1 storage pool without hot spares # 2. Remove a vdev by disabling its SAS phy # 3. Export the pool # 4. Reenable the missing dev's SAS phy # 5. Erase the missing dev's ZFS label # 6. Disable the missing dev's SAS phy again # 7. Import the pool # 8. Reenable the missing dev's SAS phy # 9. Verify that it does not get added to the pool. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING STATUS: COMPLETED (2013-02-4) # # __stc_assertion_end # ############################################################################### verify_runnable "global" verify_disk_count "$DISKS" 5 log_assert "A pool with the autoreplace property set will replace disks by physical path" log_onexit autoreplace_cleanup function verify_assertion { do_autoreplace # 9. Verify that it does not get added to the pool for ((timeout=0; timeout<4; timeout=$timeout+1)); do log_mustnot check_state $TESTPOOL $REMOVAL_DISK "ONLINE" $SLEEP 5 done } typeset REMOVAL_DISK=$DISK0 typeset POOLDEVS="$DISK0 $DISK1 $DISK2 $DISK3" set -A MY_KEYWORDS "mirror" "raidz1" "raidz2" +ensure_zfsd_running for keyword in "${MY_KEYWORDS[@]}" ; do log_must create_pool $TESTPOOL $keyword $POOLDEVS log_must poolexists "$TESTPOOL" log_must $ZPOOL set autoreplace=off $TESTPOOL verify_assertion destroy_pool "$TESTPOOL" done Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_autoreplace_002_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_autoreplace_002_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_autoreplace_002_pos.ksh (revision 292346) @@ -1,95 +1,89 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2013 Spectra Logic. All rights reserved. # Use is subject to license terms. # # ident "@(#)hotspare_replace_007_pos.ksh 1.0 12/08/10 SL" # . $STF_SUITE/tests/hotspare/hotspare.kshlib . $STF_SUITE/tests/zfsd/zfsd.kshlib . $STF_SUITE/include/libsas.kshlib ################################################################################ # # __stc_assertion_start # # ID: zfsd_autoreplace_002_pos # # DESCRIPTION: # In a pool with the autoreplace property set, a vdev will be # replaced by physical path # # STRATEGY: # 1. Create 1 storage pool without hot spares # 2. Remove a vdev by disabling its SAS phy # 3. Export the pool # 4. Reenable the missing dev's SAS phy # 5. Erase the missing dev's ZFS label # 6. Disable the missing dev's SAS phy again # 7. Import the pool # 8. Reenable the missing dev's SAS phy # 9. Verify that it does get added to the pool. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING STATUS: COMPLETED (2013-02-4) # # __stc_assertion_end # ############################################################################### verify_runnable "global" verify_disk_count "$DISKS" 5 log_assert "A pool with the autoreplace property will replace disks by physical path" log_onexit autoreplace_cleanup function verify_assertion { do_autoreplace - # 9. Verify that it gets added to the pool - for ((timeout=0; $timeout<10; timeout=$timeout+1)); do - if check_state $TESTPOOL $REMOVAL_DISK "ONLINE"; then - break - fi - $SLEEP 6 - done - log_must check_state $TESTPOOL "$REMOVAL_DISK" "ONLINE" + wait_for_pool_dev_state_change 20 $REMOVAL_DISK ONLINE } typeset REMOVAL_DISK=$DISK0 typeset POOLDEVS="$DISK0 $DISK1 $DISK2 $DISK3" set -A MY_KEYWORDS "mirror" "raidz1" "raidz2" +ensure_zfsd_running for keyword in "${MY_KEYWORDS[@]}" ; do log_must create_pool $TESTPOOL $keyword $POOLDEVS log_must poolexists "$TESTPOOL" log_must $ZPOOL set autoreplace=on $TESTPOOL verify_assertion destroy_pool "$TESTPOOL" done Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_autoreplace_003_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_autoreplace_003_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_autoreplace_003_pos.ksh (revision 292346) @@ -1,104 +1,99 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2014 Spectra Logic. All rights reserved. # Use is subject to license terms. # # . $STF_SUITE/tests/hotspare/hotspare.kshlib . $STF_SUITE/tests/zfsd/zfsd.kshlib . $STF_SUITE/include/libsas.kshlib ################################################################################ # # __stc_assertion_start # # ID: zfsd_autoreplace_003_pos # # DESCRIPTION: # In a pool with the autoreplace property set, a vdev will be # replaced by physical path even if a spare is already active for that # vdev # # STRATEGY: # 1. Create 1 storage pool with a hot spare # 2. Remove a vdev by disabling its SAS phy # 3. Wait for the hotspare to fully resilver # 4. Export the pool # 5. Reenable the missing dev's SAS phy # 6. Erase the missing dev's ZFS label # 7. Disable the missing dev's SAS phy again # 8. Import the pool # 9. Reenable the missing dev's SAS phy # 10. Verify that it does get added to the pool. # 11. Verify that the hotspare gets removed. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING STATUS: COMPLETED (2013-05-13) # # __stc_assertion_end # ############################################################################### verify_runnable "global" verify_disk_count "$DISKS" 5 log_assert "A pool with the autoreplace property will replace disks by physical path" log_onexit autoreplace_cleanup function verify_assertion { do_autoreplace "$SPARE_DISK" # Verify that the original disk gets added to the pool - for ((timeout=0; $timeout<10; timeout=$timeout+1)); do - if check_state $TESTPOOL $REMOVAL_DISK "ONLINE"; then - break - fi - $SLEEP 6 - done - log_must check_state $TESTPOOL "$REMOVAL_DISK" "ONLINE" + wait_for_pool_dev_state_change 20 $REMOVAL_DISK ONLINE # Wait for resilvering to complete wait_until_resilvered # Check that the spare is deactivated log_must check_state $TESTPOOL "$SPARE_DISK" "AVAIL" } typeset SPARE_DISK=$DISK0 typeset REMOVAL_DISK=$DISK1 typeset POOLDEVS="$DISK1 $DISK2 $DISK3 $DISK4" set -A MY_KEYWORDS "mirror" "raidz1" "raidz2" +ensure_zfsd_running for keyword in "${MY_KEYWORDS[@]}" ; do log_must create_pool $TESTPOOL $keyword $POOLDEVS spare $SPARE_DISK log_must poolexists "$TESTPOOL" log_must $ZPOOL set autoreplace=on $TESTPOOL verify_assertion destroy_pool "$TESTPOOL" done Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_degrade_001_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_degrade_001_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_degrade_001_pos.ksh (revision 292346) @@ -1,117 +1,89 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright (c) 2012,2013 Spectra Logic Corporation. All rights reserved. # Use is subject to license terms. # # $Id: $ # $FreeBSD$ . $STF_SUITE/include/libtest.kshlib ################################################################################ # # __stc_assertion_start # # ID: zfsd_degrade_001_pos # # DESCRIPTION: # If a vdev experiences checksum errors, it will become degraded. # # # STRATEGY: # 1. Create a storage pool. Only use the file vdevs because it is easy to # generate checksum errors on them. # 2. Mostly fill the pool with data. # 3. Corrupt it by DDing to the underlying vdev # 4. Verify that the vdev becomes DEGRADED. # 5. ONLINE it and verify that it resilvers and joins the pool. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING STATUS: COMPLETED (2012-08-09) # # __stc_assertion_end # ############################################################################### verify_runnable "global" VDEV0=${TMPDIR}/file0.${TESTCASE_ID} VDEV1=${TMPDIR}/file1.${TESTCASE_ID} VDEVS="${VDEV0} ${VDEV1}" TESTFILE=/$TESTPOOL/testfile function cleanup { destroy_pool $TESTPOOL $RM -f $VDEVS } log_assert "ZFS will degrade a vdev that produces checksum errors" log_onexit cleanup -log_must $MKFILE 100M ${VDEV0} -log_must $MKFILE 100M ${VDEV1} - - +log_must $MKFILE 64M ${VDEV0} ${VDEV1} +ensure_zfsd_running for type in "raidz" "mirror"; do log_note "Testing raid type $type" create_pool $TESTPOOL $type ${VDEVS} - - # do some IO on the pool - log_must $DD if=/dev/random of=$TESTFILE bs=1024 count=32768 - # Scribble on the underlying file to corrupt the vdev - log_must $DD if=/dev/zero bs=1024k count=64 conv=notrunc of=$VDEV1 - - # Scrub the pool to detect the corruption - $SYNC - log_must $ZPOOL scrub $TESTPOOL - while is_pool_scrubbing $TESTPOOL ; do - $SLEEP 2 - done - - # ZFSD can take up to 60 seconds to degrade an array in response to - # errors (though it's usually faster). - for ((timeout=0; $timeout<10; timeout=$timeout+1)); do - check_state $TESTPOOL "$VDEV1" "DEGRADED" - degraded=$? - if [[ $degraded == 0 ]]; then - break - fi - $SLEEP 6 - done - log_must $ZPOOL status $TESTPOOL - log_must check_state $TESTPOOL "$VDEV1" "DEGRADED" - + corrupt_pool $TESTPOOL $VDEV1 $TESTFILE destroy_pool $TESTPOOL done cleanup log_pass - Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_degrade_002_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_degrade_002_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_degrade_002_pos.ksh (revision 292346) @@ -1,137 +1,103 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright (c) 2012-2014 Spectra Logic Corporation. All rights reserved. # Use is subject to license terms. # # $Id: $ # $FreeBSD$ . $STF_SUITE/include/libtest.kshlib ################################################################################ # # __stc_assertion_start # # ID: zfsd_degrade_001_pos # # DESCRIPTION: # If an active hotspare experiences checksum errors, it will become degraded. # # # STRATEGY: # 1. Create a storage pool with a hotspare. Only use the file vdevs because # it is easy to generate checksum errors on them. # 2. fault a vdev to active the hotspare # 3. Mostly fill the pool with data. # 4. Corrupt it by DDing to the hotspare's underlying file. # 5. Verify that the hotspare becomes DEGRADED. # 6. ONLINE it and verify that it resilvers and joins the pool. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING STATUS: COMPLETED (2014-05-13) # # __stc_assertion_end # ############################################################################### verify_runnable "global" VDEV0=${TMPDIR}/file0.${TESTCASE_ID} VDEV1=${TMPDIR}/file1.${TESTCASE_ID} SPARE_VDEV=${TMPDIR}/file2.${TESTCASE_ID} BASIC_VDEVS="${VDEV0} ${VDEV1}" VDEVS="${BASIC_VDEVS} ${SPARE_VDEV}" TESTFILE=/$TESTPOOL/testfile function cleanup { destroy_pool $TESTPOOL $RM -f $VDEVS } log_assert "ZFS will degrade a vdev that produces checksum errors" log_onexit cleanup +ensure_zfsd_running log_must $MKFILE 100M ${VDEV0} log_must $MKFILE 100M ${VDEV1} log_must $MKFILE 100M ${SPARE_VDEV} - for type in "mirror" "raidz"; do log_note "Testing raid type $type" create_pool $TESTPOOL $type ${BASIC_VDEVS} spare ${SPARE_VDEV} # Activate the hotspare $ZINJECT -d ${VDEV0} -A fault $TESTPOOL # ZFSD can take up to 60 seconds to replace a failed device # (though it's usually faster). - for ((timeout=0; $timeout<10; timeout=$timeout+1)); do - check_state $TESTPOOL "$SPARE_VDEV" "INUSE" - spare_inuse=$? - if [[ $spare_inuse == 0 ]]; then - break - fi - $SLEEP 6 - done - log_must $ZPOOL status $TESTPOOL - log_must check_state $TESTPOOL "$SPARE_VDEV" "ONLINE" + wait_for_pool_dev_state_change 60 $SPARE_VDEV INUSE - # do some IO on the pool - log_must $DD if=/dev/random of=$TESTFILE bs=512 count=4096 - # Scribble on the underlying file to corrupt the vdev - log_must $DD if=/dev/zero bs=1024k count=64 conv=notrunc of=$SPARE_VDEV - - # Scrub the pool to detect the corruption - $SYNC - log_must $ZPOOL scrub $TESTPOOL - while is_pool_scrubbing $TESTPOOL ; do - $SLEEP 2 - done - - # ZFSD can take up to 60 seconds to degrade an array in response to - # errors (though it's usually faster). - for ((timeout=0; $timeout<10; timeout=$timeout+1)); do - check_state $TESTPOOL "$SPARE_VDEV" "DEGRADED" - degraded=$? - if [[ $degraded == 0 ]]; then - break - fi - $SLEEP 6 - done - log_must $ZPOOL status $TESTPOOL - log_must check_state $TESTPOOL "$SPARE_VDEV" "DEGRADED" - + corrupt_pool $TESTPOOL $SPARE_VDEV $TESTFILE destroy_pool $TESTPOOL done cleanup log_pass - Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_fault_001_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_fault_001_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_fault_001_pos.ksh (revision 292346) @@ -1,166 +1,166 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright (c) 2012,2013 Spectra Logic Corporation. All rights reserved. # Use is subject to license terms. # # $Id: //depot/SpectraBSD/stable/9/cddl/tools/regression/stc/src/suites/fs/zfs/tests/functional/soft_errors/soft_errors_001_pos.ksh#2 $ # $FreeBSD$ . $STF_SUITE/include/libtest.kshlib ################################################################################ # # __stc_assertion_start # # ID: zfsd_fault_001_pos # # DESCRIPTION: # If a vdev experiences IO errors, it will become faulted. # # # STRATEGY: # 1. Create a storage pool. Only use the da driver (FreeBSD's SCSI disk # driver) because it has a special interface for simulating IO errors. # 2. Inject IO errors while doing IO to the pool. # 3. Verify that the vdev becomes FAULTED. # 4. ONLINE it and verify that it resilvers and joins the pool. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING STATUS: COMPLETED (2012-08-09) # # __stc_assertion_end # ############################################################################### verify_runnable "global" function cleanup { # Disable error injection, if still active sysctl kern.cam.da.$TMPDISKNUM.error_inject=0 > /dev/null if poolexists $TESTPOOL; then # We should not get here if the test passed. Print the output # of zpool status to assist in debugging. $ZPOOL status # Clear out artificially generated errors and destroy the pool $ZPOOL clear $TESTPOOL destroy_pool $TESTPOOL fi } log_assert "ZFS will fault a vdev that produces IO errors" log_onexit cleanup - +ensure_zfsd_running # Make sure that at least one of the disks is using the da driver, and use # that disk for inject errors typeset TMPDISK="" for d in $DISKS do b=`basename $d` if test ${b%%[0-9]*} == da then TMPDISK=$b TMPDISKNUM=${b##da} break fi done if test -z $TMPDISK then log_unsupported "This test requires at least one disk to use the da driver" fi for type in "raidz" "mirror"; do log_note "Testing raid type $type" # Create a pool on the supplied disks create_pool $TESTPOOL $type $DISKS log_must $ZFS create $TESTPOOL/$TESTFS # Cause some IO errors writing to the pool while true do # Running zpool status after every dd operation is too slow. # So we will run several dd's in a row before checking zpool # status. sync between dd operations to ensure that the disk # gets IO for ((i=0; $i<64; i=$i+1)) do sysctl kern.cam.da.$TMPDISKNUM.error_inject=1 > \ /dev/null dd if=/dev/zero bs=128k count=1 >> \ /$TESTPOOL/$TESTFS/$TESTFILE 2> /dev/null $FSYNC /$TESTPOOL/$TESTFS/$TESTFILE done # Check to see if the pool is faulted yet $ZPOOL status $TESTPOOL | grep -q 'state: DEGRADED' if [ $? == 0 ] then log_note "$TESTPOOL got degraded" break fi done log_must check_state $TESTPOOL $TMPDISK "FAULTED" #find the failed disk guid typeset FAILED_VDEV=`$ZPOOL status $TESTPOOL | awk "/^[[:space:]]*$TMPDISK[[:space:]]*FAULTED/ {print \\$1}"` # Reattach the failed disk $ZPOOL online $TESTPOOL $FAILED_VDEV > /dev/null if [ $? != 0 ]; then log_fail "Could not reattach $FAILED_VDEV" fi # Verify that the pool resilvers and goes to the ONLINE state for (( retries=60; $retries>0; retries=$retries+1 )) do $ZPOOL status $TESTPOOL | egrep -q "scan:.*resilvered" RESILVERED=$? $ZPOOL status $TESTPOOL | egrep -q "state:.*ONLINE" ONLINE=$? if test $RESILVERED -a $ONLINE then break fi $SLEEP 2 done if [ $retries == 0 ] then log_fail "$TESTPOOL never resilvered in the allowed time" fi destroy_pool $TESTPOOL log_must $RM -rf /$TESTPOOL done log_pass Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_001_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_001_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_001_pos.ksh (revision 292346) @@ -1,150 +1,150 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Copyright 2014 Spectra Logic Corp. All rights reserved. # Use is subject to license terms. # . $STF_SUITE/tests/hotspare/hotspare.kshlib ################################################################################ # # __stc_assertion_start # # ID: zfsd_hotspare_001_pos # # DESCRIPTION: # If an active spare fails, it will be replaced by an available spare. # # STRATEGY: # 1. Create a storage pool with two hot spares # 2. Fail one vdev # 3. Verify that a spare gets activated # 4. Fail the spare # 5. Verify the failed spare was replaced by the other spare. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING STATUS: COMPLETED (2014-05-13) # # __stc_assertion_end # ############################################################################### verify_runnable "global" function cleanup { if poolexists $TESTPOOL ; then destroy_pool $TESTPOOL fi partition_cleanup } log_onexit cleanup function verify_assertion # type { typeset pool_type=$1 typeset err_dev=${devarray[3]} typeset raidz2_dev="${devarray[4]}" typeset mntp=$(get_prop mountpoint $TESTPOOL) # fail a basic vdev $ZINJECT -d $err_dev -A fault $TESTPOOL # ZFSD can take up to 60 seconds to replace a failed device # (though it's usually faster). for ((timeout=0; $timeout<10; timeout=$timeout+1)); do check_state $TESTPOOL "$fail_spare" "INUSE" spare_inuse=$? if [[ $spare_inuse == 0 ]]; then break fi $SLEEP 6 done log_must $ZPOOL status $TESTPOOL log_must check_state $TESTPOOL "$fail_spare" "INUSE" # The zpool history should log when a spare device becomes active log_must $ZPOOL history -i $TESTPOOL | $GREP "internal vdev attach" | \ $GREP "spare in vdev=$fail_spare for vdev=$err_dev" > /dev/null ###################################################################### # Now fail the active hotspare, and check that the second comes online ###################################################################### # fail the spare vdev $ZINJECT -d $fail_spare -A fault $TESTPOOL # ZFSD can take up to 60 seconds to replace a failed device # (though it's usually faster). for ((timeout=0; $timeout<10; timeout=$timeout+1)); do check_state $TESTPOOL "$standby_spare" "INUSE" spare_inuse=$? if [[ $spare_inuse == 0 ]]; then break fi $SLEEP 6 done log_must $ZPOOL status $TESTPOOL # The standby spare should be in use, while the original spare should # be faulted. log_must check_state $TESTPOOL $standby_spare "online" log_must check_state $TESTPOOL $standby_spare \ "INUSE currently in use" log_mustnot check_state $TESTPOOL $fail_spare "online" # The zpool history should log when a spare device becomes active log_must $ZPOOL history -i $TESTPOOL | $GREP "internal vdev attach" | \ $GREP "spare in vdev=$standby_spare for vdev=$fail_spare" > /dev/null # do cleanup destroy_pool $TESTPOOL } log_onexit cleanup log_assert "An active damaged spare will be replaced by an available spare" +ensure_zfsd_running set_devs typeset fail_spare="${devarray[0]}" typeset standby_spare="${devarray[1]}" typeset spares="$fail_spare $standby_spare" set -A my_keywords "mirror" "raidz1" "raidz2" for keyword in "${my_keywords[@]}"; do setup_hotspares "$keyword" verify_assertion "$keyword" done log_pass "If one of the spare fail, the other available spare will be in use" - Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_002_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_002_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_002_pos.ksh (revision 292346) @@ -1,111 +1,112 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2012 Spectra Logic. All rights reserved. # Use is subject to license terms. # # ident "@(#)hotspare_replace_004_pos.ksh 1.0 12/08/09 SL" # . $STF_SUITE/tests/hotspare/hotspare.kshlib ################################################################################ # # __stc_assertion_start # # ID: zfsd_hotspare_002_pos # # DESCRIPTION: # If a vdev becomes degraded in a pool with a spare, the spare will be # activated. # # # STRATEGY: # 1. Create 1 storage pools with hot spares. # 2. Artificially degrade one vdev in the pool # 3. Verify that the spare is in use. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING STATUS: COMPLETED (2012-08-06) # # __stc_assertion_end # ############################################################################### verify_runnable "global" function cleanup { if poolexists $TESTPOOL ; then destroy_pool $TESTPOOL fi partition_cleanup } log_onexit cleanup function verify_assertion # type { typeset sdev=$1 typeset err_dev=${devarray[3]} typeset mntp=$(get_prop mountpoint $TESTPOOL) # Artificially degrade the vdev log_must $ZINJECT -d $err_dev -A degrade $TESTPOOL log_must check_state $TESTPOOL $err_dev "DEGRADED" # ZFSD can take up to 60 seconds to degrade an array in response to # errors (though it's usually faster). for ((timeout=0; $timeout<10; timeout=$timeout+1)); do check_state $TESTPOOL "$sdev" "INUSE" spare_inuse=$? if [[ $spare_inuse == 0 ]]; then break fi $SLEEP 6 done log_must $ZPOOL status $TESTPOOL log_must check_state $TESTPOOL "$sdev" "INUSE" # do cleanup destroy_pool $TESTPOOL } log_onexit cleanup log_assert "If a vdev becomes degraded, the spare will be activated." +ensure_zfsd_running set_devs typeset sdev="${devarray[0]}" set -A my_keywords "mirror" "raidz1" "raidz2" for keyword in "${my_keywords[@]}"; do setup_hotspares "$keyword" verify_assertion $sdev done Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_003_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_003_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_003_pos.ksh (revision 292346) @@ -1,107 +1,108 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2012 Spectra Logic. All rights reserved. # Use is subject to license terms. # # ident "@(#)hotspare_replace_005_pos.ksh 1.0 12/08/09 SL" # . $STF_SUITE/tests/hotspare/hotspare.kshlib ################################################################################ # # __stc_assertion_start # # ID: zfs_hotspare_003_pos # # DESCRIPTION: # If a vdev becomes faulted in a pool with a spare, the spare will be # activated. # # # STRATEGY: # 1. Create 1 storage pools with hot spares. # 2. Artificially fault one vdev in the pool to make 1 hotspare in use. # 3. Verify that the spare is in use. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING STATUS: COMPLETED (2012-08-06) # # __stc_assertion_end # ############################################################################### verify_runnable "global" verify_disk_count "$DISKS" 5 function cleanup { poolexists $TESTPOOL && \ destroy_pool $TESTPOOL partition_cleanup } function verify_assertion # spare_dev { typeset err_dev=${devarray[3]} typeset sdev=$1 log_must $ZINJECT -d $err_dev -A degrade $TESTPOOL log_must check_state $TESTPOOL $err_dev "DEGRADED" # ZFSD can take up to 60 seconds to degrade an array in response to # errors (though it's usually faster). for ((timeout=0; $timeout<10; timeout=$timeout+1)); do check_state $TESTPOOL "$sdev" "INUSE" spare_inuse=$? if [[ $spare_inuse == 0 ]]; then break fi $SLEEP 6 done log_must $ZPOOL status $TESTPOOL log_must check_state $TESTPOOL "$sdev" "INUSE" # do cleanup destroy_pool $TESTPOOL } log_assert "A faulted vdev will be replaced by an available spare" log_onexit cleanup +ensure_zfsd_running set_devs typeset sdev="${devarray[0]}" set -A my_keywords "mirror" "raidz1" "raidz2" for keyword in "${my_keywords[@]}" ; do setup_hotspares "$keyword" verify_assertion $sdev done log_pass "A faulted vdev will be replaced by an available spare" Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_004_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_004_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_004_pos.ksh (revision 292346) @@ -1,166 +1,115 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2012 Spectra Logic. All rights reserved. # Use is subject to license terms. # # ident "@(#)hotspare_replace_006_pos.ksh 1.0 12/08/10 SL" # . $STF_SUITE/tests/hotspare/hotspare.kshlib . $STF_SUITE/tests/zfsd/zfsd.kshlib . $STF_SUITE/include/libsas.kshlib ################################################################################ # # __stc_assertion_start # # ID: zfs_hotspare_004_pos # # DESCRIPTION: # If a vdev gets removed from a pool with a spare, the spare will be # activated. # # # STRATEGY: # 1. Create 1 storage pools with hot spares. Use disks instead of files # because they can be removed. # 2. Remove one vdev by turning off its SAS phy. # 3. Verify that the spare is in use. # 4. Reinsert the vdev by enabling its phy # 5. Verify that the vdev gets resilvered and the spare gets removed # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING STATUS: COMPLETED (2012-08-10) # # __stc_assertion_end # ############################################################################### verify_runnable "global" verify_disk_count "$DISKS" 5 log_assert "Removing a disk from a pool results in the spare activating" log_onexit autoreplace_cleanup function verify_assertion # spare_dev { - typeset sdev=$1 + typeset spare_dev=$1 find_verify_sas_disk $REMOVAL_DISK log_note "Disabling \"$REMOVAL_DISK\" on expander $EXPANDER phy $PHY" disable_sas_disk $EXPANDER $PHY - #Check to make sure the disk is gone - camcontrol inquiry $REMOVAL_DISK > /dev/null 2>&1 - if [ $? = 0 ]; then - log_fail "Disk \"$REMOVAL_DISK\" was not removed" - fi + # Check to make sure the disk is gone + find_disk_by_phy $EXPANDER $PHY + [ -n "$FOUNDDISK" ] && log_fail "Disk \"$REMOVAL_DISK\" was not removed" # Check to make sure ZFS sees the disk as removed - for ((timeout=0; $timeout<20; timeout=$timeout+1)); do - check_state $TESTPOOL "$REMOVAL_DISK" "REMOVED" - is_removed=$? - if [[ $is_removed == 0 ]]; then - break - fi - $SLEEP 3 - done - log_must check_state $TESTPOOL "$REMOVAL_DISK" "REMOVED" + wait_for_pool_removal 20 # Check that the spare was activated - for ((timeout=0; $timeout<20; timeout=$timeout+1)); do - check_state $TESTPOOL "$sdev" "INUSE" - spare_inuse=$? - if [[ $spare_inuse == 0 ]]; then - break - fi - $SLEEP 3 - done + wait_for_pool_dev_state_change 20 $spare_dev INUSE log_must $ZPOOL status $TESTPOOL - log_must check_state $TESTPOOL "$sdev" "INUSE" # Reenable the missing disk log_note "Reenabling phy on expander $EXPANDER phy $PHY" enable_sas_disk $EXPANDER $PHY + wait_for_disk_to_reappear 20 - # Check that the disk has returned - for ((timeout=0; $timeout<20; timeout=$timeout+1)); do - find_disk_by_phy $EXPANDER $PHY - if [[ -n "$FOUNDDISK" ]]; then - break - fi - $SLEEP 3 - done + # Check that the disk has rejoined the pool & resilvered + wait_for_pool_dev_state_change 20 $REMOVAL_DISK ONLINE + wait_until_resilvered - if [[ -z "$FOUNDDISK" ]]; then - log_fail "Disk $REMOVAL_DISK never reappeared" - fi - - #Check that the disk has rejoined the pool - for ((timeout=0; $timeout<20; timeout=$timeout+1)); do - check_state $TESTPOOL $REMOVAL_DISK ONLINE - rejoined=$? - if [[ $rejoined == 0 ]]; then - break - fi - $SLEEP 3 - done - log_must check_state $TESTPOOL $REMOVAL_DISK ONLINE - - #Check that the pool resilvered - while ! is_pool_resilvered $TESTPOOL; do - $SLEEP 2 - done - log_must is_pool_resilvered $TESTPOOL - log_must $ZPOOL status - - #Finally, check that the spare deactivated - for ((timeout=0; $timeout<20; timeout=$timeout+1)); do - check_state $TESTPOOL "$sdev" "AVAIL" - deactivated=$? - if [[ $deactivated == 0 ]]; then - break - fi - $SLEEP 3 - done - log_must check_state $TESTPOOL "$sdev" "AVAIL" + # Finally, check that the spare deactivated + wait_for_pool_state_change $spare_dev AVAIL } typeset REMOVAL_DISK=$DISK0 typeset SDEV=$DISK4 typeset POOLDEVS="$DISK0 $DISK1 $DISK2 $DISK3" set -A MY_KEYWORDS "mirror" "raidz1" "raidz2" +ensure_zfsd_running for keyword in "${MY_KEYWORDS[@]}" ; do log_must create_pool $TESTPOOL $keyword $POOLDEVS spare $SDEV log_must poolexists "$TESTPOOL" log_must $ZPOOL set autoreplace=on "$TESTPOOL" iterate_over_hotspares verify_assertion $SDEV destroy_pool "$TESTPOOL" done Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_005_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_005_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_005_pos.ksh (revision 292346) @@ -1,109 +1,110 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2012 Spectra Logic. All rights reserved. # Use is subject to license terms. # # ident "@(#)hotspare_replace_007_pos.ksh 1.0 12/08/10 SL" # . $STF_SUITE/tests/hotspare/hotspare.kshlib ################################################################################ # # __stc_assertion_start # # ID: zfsd_hotspare_005_pos # # DESCRIPTION: # If a spare gets added to an already damaged pool, the spare will be # activated # # STRATEGY: # 1. Create 1 storage pool without hot spares # 2. Fail one vdev by using zinject to degrade or fault it # 3. Verify that it gets degraded or faulted, respectively # 4. Add a hotspare # 5. Verify that the spare is in use. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING STATUS: COMPLETED (2012-08-10) # # __stc_assertion_end # ############################################################################### verify_runnable "global" function cleanup { if poolexists $TESTPOOL ; then destroy_pool $TESTPOOL fi partition_cleanup } function verify_assertion # damage_type { typeset damage=$1 typeset err_dev=${devarray[3]} typeset mntp=$(get_prop mountpoint $TESTPOOL) log_must $ZINJECT -d $err_dev -A $damage $TESTPOOL log_must check_state $TESTPOOL $err_dev ${damage_status[$damage]} # Add the spare, and check that it is in use log_must $ZPOOL add $TESTPOOL spare $sdev for ((timeout=0; $timeout<10; timeout=$timeout+1)); do if check_state $TESTPOOL "$sdev" "INUSE"; then break fi $SLEEP 6 done log_must $ZPOOL status $TESTPOOL log_must check_state $TESTPOOL "$sdev" "INUSE" } log_onexit cleanup log_assert "A spare that is added to a degraded pool will be activated" +ensure_zfsd_running set_devs typeset sdev="${sparedevs[0]}" typeset -A damage_status damage_status["degrade"]="DEGRADED" damage_status["fault"]="FAULTED" set -A my_keywords "mirror" "raidz1" "raidz2" for keyword in "${my_keywords[@]}"; do for damage in "degrade" "fault"; do log_must create_pool $TESTPOOL $keyword ${pooldevs[@]} verify_assertion $damage destroy_pool $TESTPOOL done done Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_006_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_006_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_006_pos.ksh (revision 292346) @@ -1,142 +1,143 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2014 Spectra Logic. All rights reserved. # Use is subject to license terms. # # . $STF_SUITE/tests/hotspare/hotspare.kshlib . $STF_SUITE/include/libsas.kshlib ################################################################################ # # __stc_assertion_start # # ID: zfs_hotspare_004_pos # # DESCRIPTION: # If two vdevs get removed from a pool with two spares at the same time, # both spares will be activated. # # # STRATEGY: # 1. Create 1 storage pool with two hot spares. # 2. Stop the zfsd process. # 3. Fault two vdevs # 4. Resume the zfsd process # 5. Verify that the spares are in use. # 6. Pause zfsd # 7. Clear the errors on the faulted vdevs # 8. Resume zfsd # 9. Verify that the vdevs ges resilvered and the spares get removed # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING STATUS: COMPLETED (2014-05-13) # # __stc_assertion_end # ############################################################################### verify_runnable "global" function cleanup { poolexists $TESTPOOL && \ destroy_pool $TESTPOOL partition_cleanup $KILL -s SIGCONT `$PGREP zfsd` } function verify_assertion # spare_dev { typeset err_dev1=${devarray[3]} typeset err_dev2=${devarray[4]} typeset sdev=$1 $KILL -s SIGSTOP `$PGREP zfsd` log_must $ZINJECT -d $err_dev1 -A fault $TESTPOOL log_must $ZINJECT -d $err_dev2 -A fault $TESTPOOL log_must check_state $TESTPOOL $err_dev1 "FAULTED" log_must check_state $TESTPOOL $err_dev2 "FAULTED" $KILL -s SIGCONT `$PGREP zfsd` # ZFSD can take up to 60 seconds to degrade an array in response to # errors (though it's usually faster). for ((timeout=0; $timeout<10; timeout=$timeout+1)); do check_state $TESTPOOL "$sdev0" "INUSE" cond1=$? check_state $TESTPOOL "$sdev1" "INUSE" cond2=$? if [[ $cond1 -eq 0 && $cond2 -eq 0 ]]; then break fi $SLEEP 6 done log_must $ZPOOL status $TESTPOOL log_must check_state $TESTPOOL "$sdev1" "INUSE" log_must check_state $TESTPOOL "$sdev2" "INUSE" $KILL -s SIGSTOP `$PGREP zfsd` $ZPOOL clear $TESTPOOL $KILL -s SIGCONT `$PGREP zfsd` for ((timeout=0; $timeout<10; timeout=$timeout+1)); do check_state $TESTPOOL "$sdev0" "AVAIL" cond1=$? check_state $TESTPOOL "$sdev1" "AVAIL" cond2=$? if [[ $cond1 -eq 0 && $cond2 -eq 0 ]]; then break fi $SLEEP 6 done log_must $ZPOOL status $TESTPOOL log_must check_state $TESTPOOL "$sdev1" "AVAIL" log_must check_state $TESTPOOL "$sdev2" "AVAIL" # do cleanup destroy_pool $TESTPOOL } log_assert "Two simultaneously faulted vdevs will be replaced by available spares" log_onexit cleanup +ensure_zfsd_running set_devs typeset sdev0="${devarray[0]}" typeset sdev1="${devarray[1]}" set -A my_keywords "mirror" "raidz2" for keyword in "${my_keywords[@]}" ; do setup_hotspares "$keyword" verify_assertion $sdev done log_pass Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_007_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_007_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_hotspare_007_pos.ksh (revision 292346) @@ -1,140 +1,109 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2012 Spectra Logic. All rights reserved. # Use is subject to license terms. # # ident "@(#)hotspare_replace_006_pos.ksh 1.0 12/08/10 SL" # . $STF_SUITE/tests/hotspare/hotspare.kshlib . $STF_SUITE/tests/zfsd/zfsd.kshlib . $STF_SUITE/include/libsas.kshlib ################################################################################ # # __stc_assertion_start # # ID: zfs_hotspare_007_pos # # DESCRIPTION: # If a vdev gets removed from a pool with a spare while zfsd is shut # down, then the spare will be activated when zfsd restarts # # # STRATEGY: # 1. Create 1 storage pools with hot spares. Use disks instead of files # because they can be removed. # 2. Turn off zfsd # 3. Remove one vdev by turning off its SAS phy. # 4. Restart zfsd # 5. Verify that the spare is in use. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING STATUS: COMPLETED (2014-09-17) # # __stc_assertion_end # ############################################################################### verify_runnable "global" verify_disk_count "$DISKS" 5 log_assert "zfsd will spare missing drives on startup" log_onexit autoreplace_cleanup function verify_assertion # spare_dev { - typeset sdev=$1 + typeset spare_dev=$1 find_verify_sas_disk $REMOVAL_DISK stop_zfsd log_note "Disabling \"$REMOVAL_DISK\" on expander $EXPANDER phy $PHY" disable_sas_disk $EXPANDER $PHY - #Check to make sure the disk is gone - camcontrol inquiry $REMOVAL_DISK > /dev/null 2>&1 - if [ $? = 0 ]; then - log_fail "Disk \"$REMOVAL_DISK\" was not removed" - fi + # Check to make sure the disk is gone + find_disk_by_phy $EXPANDER $PHY + [ -n "$FOUNDDISK" ] && log_fail "Disk \"$REMOVAL_DISK\" was not removed" # Check to make sure ZFS sees the disk as removed - for ((timeout=0; $timeout<20; timeout=$timeout+1)); do - check_state $TESTPOOL "$REMOVAL_DISK" "REMOVED" - is_removed=$? - if [[ $is_removed == 0 ]]; then - break - fi - $SLEEP 3 - done - log_must check_state $TESTPOOL "$REMOVAL_DISK" "REMOVED" + wait_for_pool_removal 20 restart_zfsd # Check that the spare was activated - for ((timeout=0; $timeout<20; timeout=$timeout+1)); do - check_state $TESTPOOL "$sdev" "INUSE" - spare_inuse=$? - if [[ $spare_inuse == 0 ]]; then - break - fi - $SLEEP 3 - done - log_must $ZPOOL status $TESTPOOL - log_must check_state $TESTPOOL "$sdev" "INUSE" + wait_for_pool_dev_state_change $spare_dev INUSE # Reenable the missing disk log_note "Reenabling phy on expander $EXPANDER phy $PHY" enable_sas_disk $EXPANDER $PHY - - # Check that the disk has returned - for ((timeout=0; $timeout<20; timeout=$timeout+1)); do - find_disk_by_phy $EXPANDER $PHY - if [[ -n "$FOUNDDISK" ]]; then - break - fi - $SLEEP 3 - done - - if [[ -z "$FOUNDDISK" ]]; then - log_fail "Disk $REMOVAL_DISK never reappeared" - fi + wait_for_disk_to_reappear 20 } - typeset REMOVAL_DISK=$DISK0 typeset SDEV=$DISK4 typeset POOLDEVS="$DISK0 $DISK1 $DISK2 $DISK3" set -A MY_KEYWORDS "mirror" "raidz1" "raidz2" +ensure_zfsd_running for keyword in "${MY_KEYWORDS[@]}" ; do log_must create_pool $TESTPOOL $keyword $POOLDEVS spare $SDEV log_must poolexists "$TESTPOOL" iterate_over_hotspares verify_assertion $SDEV destroy_pool "$TESTPOOL" done Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_import_001_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_import_001_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_import_001_pos.ksh (revision 292346) @@ -1,206 +1,161 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2013 Spectra Logic. All rights reserved. # Use is subject to license terms. # # ident "@(#)zfsd_zfsd_002_pos.ksh 1.0 12/08/10 SL" # . $STF_SUITE/tests/hotspare/hotspare.kshlib . $STF_SUITE/tests/zfsd/zfsd.kshlib . $STF_SUITE/include/libsas.kshlib ################################################################################ # # __stc_assertion_start # # ID: zfsd_import_001_pos # # DESCRIPTION: # If a removed drive gets reinserted while the pool is exported, it will # replace its spare when reinserted. # # This also applies to drives that get reinserted while the machine is # powered off. # # # STRATEGY: # 1. Create 1 storage pools with hot spares. Use disks instead of files # because they can be removed. # 2. Remove one disk by turning off its SAS phy. # 3. Verify that the spare is in use. # 4. Reinsert the vdev by enabling its phy # 5. Verify that the vdev gets resilvered and the spare gets removed # 6. Use additional zpool history data to verify that the pool # finished resilvering _before_ zfsd detached the spare. # # TESTABILITY: explicit # # TEST_AUTOMATION_LEVEL: automated # # CODING STATUS: COMPLETED (2012-08-10) # # __stc_assertion_end # ############################################################################### verify_runnable "global" function verify_assertion # spare_dev { - typeset sdev=$1 + typeset spare_dev=$1 find_verify_sas_disk $REMOVAL_DISK log_note "Disabling \"$REMOVAL_DISK\" on expander $EXPANDER phy $PHY" disable_sas_disk $EXPANDER $PHY - #Check to make sure the disk is gone - camcontrol inquiry $REMOVAL_DISK > /dev/null 2>&1 - if [ $? = 0 ]; then - log_fail "Disk \"$REMOVAL_DISK\" was not removed" - fi + # Check to make sure the disk is gone + find_disk_by_phy $EXPANDER $PHY + [ -n "$FOUNDDISK" ] && log_fail "Disk \"$REMOVAL_DISK\" was not removed" # Check to make sure ZFS sees the disk as removed - for ((timeout=0; $timeout<20; timeout=$timeout+1)); do - check_state $TESTPOOL "$REMOVAL_DISK" "REMOVED" - is_removed=$? - if [[ $is_removed == 0 ]]; then - break - fi - $SLEEP 3 - done - log_must check_state $TESTPOOL "$REMOVAL_DISK" "REMOVED" + wait_for_pool_removal 20 # Wait for zfsd to activate the spare - for ((timeout=0; $timeout<20; timeout=$timeout+1)); do - check_state $TESTPOOL "$sdev" "INUSE" - spare_inuse=$? - if [[ $spare_inuse == 0 ]]; then - break - fi - $SLEEP 3 - done - log_must check_state $TESTPOOL "$sdev" "INUSE" - + wait_for_pool_dev_state_change 20 $spare_dev INUSE + log_must $ZPOOL status $TESTPOOL + # Export the pool log_must $ZPOOL export $TESTPOOL # Reenable the missing disk log_note "Reenabling phy on expander $EXPANDER phy $PHY" enable_sas_disk $EXPANDER $PHY # Check that the disk has returned - for ((timeout=0; $timeout<20; timeout=$timeout+1)); do - find_disk_by_phy $EXPANDER $PHY - if [[ -n "$FOUNDDISK" ]]; then - break - fi - $SLEEP 3 - done + wait_for_disk_to_reappear 20 - if [[ -z "$FOUNDDISK" ]]; then - log_fail "Disk $REMOVAL_DISK never reappeared" - fi - # Import the pool log_must $ZPOOL import $TESTPOOL - #Check that the disk has rejoined the pool - for ((timeout=0; $timeout<20; timeout=$timeout+1)); do - check_state $TESTPOOL $REMOVAL_DISK ONLINE - rejoined=$? - if [[ $rejoined == 0 ]]; then - break - fi - $SLEEP 3 - done - log_must check_state $TESTPOOL $REMOVAL_DISK ONLINE + # Check that the disk has rejoined the pool + wait_for_pool_dev_state_change 20 $REMOVAL_DISK ONLINE - #Check that the pool resilvered + # Check that the pool resilvered while ! is_pool_resilvered $TESTPOOL; do $SLEEP 2 done - log_must is_pool_resilvered $TESTPOOL + log_must $ZPOOL status #Finally, check that the spare deactivated - for ((timeout=0; $timeout<20; timeout=$timeout+1)); do - check_state $TESTPOOL "$sdev" "AVAIL" - deactivated=$? - if [[ $deactivated == 0 ]]; then - break - fi - $SLEEP 3 - done - log_must check_state $TESTPOOL "$sdev" "AVAIL" + wait_for_pool_dev_state_change 20 $spare_dev AVAIL # Verify that the spare was detached after the scrub was complete # Note that resilvers and scrubs are recorded identically in zpool # history $ZPOOL history -i $TESTPOOL | awk ' BEGIN { scrub_txg=0; detach_txg=0 } /scrub done/ { split($6, s, "[:\\]]"); t=s[2]; scrub_txg = scrub_txg > t ? scrub_txg : t } /vdev detach/ { split($6, s, "[:\\]]"); t=s[2]; done_txg = done_txg > t ? done_txg : t } END { print("Scrub completed at txg", scrub_txg); print("Spare detached at txg", detach_txg); exit(detach_txg > scrub_txg) }' - if [[ $? -ne 0 ]]; then - log_fail "The spare detached before the resilver completed" - fi + [ $? -ne 0 ] && log_fail "The spare detached before the resilver completed" } - - if ! $(is_physical_device $DISKS) ; then log_unsupported "This directory cannot be run on raw files." fi -log_assert "If a removed drive gets reinserted while the pool is exported, it will replace its spare when reinserted." +log_assert "If a removed drive gets reinserted while the pool is exported, \ + it will replace its spare when reinserted." log_onexit autoreplace_cleanup +ensure_zfsd_running set_devs typeset REMOVAL_DISK=$DISK0 typeset SDEV=$DISK4 typeset POOLDEVS="$DISK0 $DISK1 $DISK2 $DISK3" set -A MY_KEYWORDS "mirror" "raidz1" "raidz2" for keyword in "${MY_KEYWORDS[@]}" ; do log_must create_pool $TESTPOOL $keyword $POOLDEVS spare $SDEV log_must poolexists "$TESTPOOL" iterate_over_hotspares verify_assertion $SDEV destroy_pool "$TESTPOOL" done Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_replace_001_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_replace_001_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_replace_001_pos.ksh (revision 292346) @@ -1,152 +1,93 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright 2012,2013 Spectra Logic Corporation. All rights reserved. # Use is subject to license terms. # # Portions taken from: # ident "@(#)replacement_001_pos.ksh 1.4 08/02/27 SMI" # # $Id: //SpectraBSD/stable/tests/sys/cddl/zfs/tests/zfsd/zfsd_replace_001_pos.ksh#2 $ # $FreeBSD$ . $STF_SUITE/tests/hotspare/hotspare.kshlib . $STF_SUITE/tests/zfsd/zfsd.kshlib . $STF_SUITE/include/libtest.kshlib . $STF_SUITE/include/libsas.kshlib verify_runnable "global" log_assert "Failing a disk from a SAS expander is recognized by ZFS" log_onexit autoreplace_cleanup +ensure_zfsd_running child_pids="" set -A TMPDISKS $DISKS typeset REMOVAL_DISK=${TMPDISKS[0]} REMOVAL_DISK=${REMOVAL_DISK##*/} for type in "raidz" "mirror"; do # Create a pool on the supplied disks create_pool $TESTPOOL $type $DISKS log_must $ZFS create $TESTPOOL/$TESTFS log_must $ZFS set mountpoint=$TESTDIR $TESTPOOL/$TESTFS # Find the first disk, get the expander and phy log_note "Looking for expander and phy information for $REMOVAL_DISK" find_verify_sas_disk $REMOVAL_DISK log_note "Disabling \"$REMOVAL_DISK\" on expander $EXPANDER phy $PHY" # Disable the first disk. We have to do this first, because if # there is I/O active to the disable_sas_disk $EXPANDER $PHY # Check to make sure disk is gone. - camcontrol inquiry $REMOVAL_DISK > /dev/null 2>&1 - if [ $? = 0 ]; then - log_fail "Disk \"$REMOVAL_DISK\" was not removed" - fi + find_disk_by_phy $EXPANDER $PHY + [ -n "$FOUNDDISK" ] && log_fail "Disk \"$REMOVAL_DISK\" was not removed" # Write out data to make sure we can do I/O after the disk failure - # XXX KDM should check the status returned from the dd instances log_must dd if=/dev/zero of=$TESTDIR/$TESTFILE bs=1m count=512 - # We waited for the child processes to complete, so they're done. - child_pids="" - # Check to make sure ZFS sees the disk as removed - $ZPOOL status $TESTPOOL |grep $REMOVAL_DISK |egrep -q 'REMOVED' - if [ $? != 0 ]; then - $ZPOOL status $TESTPOOL - log_fail "disk $REMOVAL_DISK not listed as removed" - fi + wait_for_pool_removal 20 - # Make sure that the pool is degraded - $ZPOOL status $TESTPOOL |grep "state:" |grep DEGRADED > /dev/null - if [ $? != 0 ]; then - $ZPOOL status $TESTPOOL - log_fail "Pool $TESTPOOL not listed as DEGRADED" - fi - # Re-enable the disk, we don't want to leave it turned off log_note "Re-enabling phy $PHY on expander $EXPANDER" enable_sas_disk $EXPANDER $PHY + wait_for_disk_to_reappear 20 - log_note "Checking to see whether disk has reappeared" - # Make sure the disk is back in the topology - find_disk_by_phy $EXPANDER $PHY - ((retries=0)) - while [ -z "$FOUNDDISK" ] && [ "$retries" -lt 10 ]; do - $SLEEP 5 - find_disk_by_phy $EXPANDER $PHY - done - - if [ -z "$FOUNDDISK" ]; then - camcontrol $EXPANDER - log_fail "Disk $REMOVAL_DISK has not appeared at phy $PHY on expander $EXPANDER after 50 seconds" - else - log_note "Disk $REMOVAL_DISK is back as $FOUNDDISK" - fi - - log_note "Raid type is $type" - - #Disk should have auto-joined the zpool. Verify it's status is online. - $ZPOOL status |grep $REMOVAL_DISK |grep ONLINE > /dev/null - if [ $? != 0 ]; then - $ZPOOL status $TESTPOOL - log_fail "disk $REMOVAL_DISK did not automatically join the $TESTPOOL" - else - log_note "After reinsertion, disk is back in pool and online" - fi - - #Make sure auto resilver has begun - ((retries=5)) - $ZPOOL status $TESTPOOL | egrep "scan:.*(resilver.in.progress|resilvered)" > /dev/null - while [ $? != 0 ] && [ "$retries" -gt 0 ]; do - log_note "Waiting for autoresilver to start: Retry $retries" - $SLEEP 2 - ((retries--)) - $ZPOOL status $TESTPOOL | egrep "scan:.*(resilver.in.progress|resilvered)" > /dev/null - done - - $ZPOOL status $TESTPOOL | egrep "scan:.*(resilver.in.progress|resilvered)" > /dev/null - if [ $? != 0 ]; then - $ZPOOL status $TESTPOOL - log_fail "Pool $TESTPOOL did not auto-resilver" - else - log_note "Auto-resilver of disk has started sucessfully." - fi - - #Wait, then verify resilver done, and that pool optimal + # Disk should auto-join the zpool & be resilvered. + wait_for_pool_dev_state_change 20 $REMOVAL_DISK ONLINE wait_until_resilvered $ZPOOL status $TESTPOOL destroy_pool $TESTPOOL log_must $RM -rf /$TESTPOOL done log_pass Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_replace_002_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_replace_002_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_replace_002_pos.ksh (revision 292346) @@ -1,252 +1,241 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright 2012,2013 Spectra Logic Corporation. All rights reserved. # Use is subject to license terms. # # Portions taken from: # ident "@(#)replacement_001_pos.ksh 1.4 08/02/27 SMI" # # $Id$ # $FreeBSD$ . $STF_SUITE/include/libtest.kshlib . $STF_SUITE/include/libsas.kshlib verify_runnable "global" function cleanup { if [[ -n "$child_pids" ]]; then for wait_pid in $child_pids do $KILL $wait_pid done fi if poolexists $TESTPOOL; then destroy_pool $TESTPOOL fi - # Tell the enable/disable SAS disk routines that we don't want to - # wait for the disk to disappear or reappear. We'll do the wait at - # the end. - export NO_SAS_DISK_WAIT=1 - # See if the phy has been disabled, and try to re-enable it if possible. for CURDISK in $TMPDISKS[*] do - if [ ! -z ${EXPANDER_LIST[$CURDISK]} ] && [ ! -z ${PHY_LIST[$CURDISK]} ]; then + if [ ! -z ${EXPANDER_LIST[$CURDISK]} -a ! -z ${PHY_LIST[$CURDISK]} ]; then find_disk_by_phy ${EXPANDER_LIST[$CURDISK]} ${PHY_LIST[$CURDISK]} - if [ ! -z "$FOUNDDISK" ]; then - continue - fi + [ -n "$FOUNDDISK" ] && continue fi enable_sas_disk ${EXPANDER_LIST[$CURDISK]} ${PHY_LIST[$CURDISK]} done + rescan_disks [[ -e $TESTDIR ]] && log_must $RM -rf $TESTDIR/* } -log_assert "A pool can come back online after all disks are failed and reactivated" - -log_unsupported "This test is currently unsupported, ZFS hangs when all drives fail and come back" - -log_onexit cleanup - -child_pids="" - function run_io { typeset -i processes=$1 typeset -i mbcount=$2 typeset i=0 while [[ $i -lt $processes ]]; do log_note "Invoking dd if=/dev/zero of=$TESTDIR/$TESTFILE.$i &" dd if=/dev/zero of=$TESTDIR/$TESTFILE.$i bs=1m count=$mbcount & typeset pid=$! $SLEEP 1 if ! $PS -p $pid > /dev/null 2>&1; then log_fail "dd if=/dev/zero $TESTDIR/$TESTFILE.$i" fi child_pids="$child_pids $pid" ((i = i + 1)) done } +log_assert "A pool can come back online after all disks are failed and reactivated" + +log_unsupported "This test is currently unsupported, ZFS hangs when all drives fail and come back" + +log_onexit cleanup + +child_pids="" + +ensure_zfsd_running set -A TMPDISKS $DISKS NUMDISKS=${#TMPDISKS[*]} # Trim out any /dev prefix on the disk. ((i=0)) while [ $i -lt $NUMDISKS ]; do TMPDISKS[$i]=${TMPDISKS[$i]##*/} ((i++)); done for type in "raidz" "mirror"; do # Create a pool on the supplied disks create_pool $TESTPOOL $type $DISKS log_must $ZFS create $TESTPOOL/$TESTFS log_must $ZFS set mountpoint=$TESTDIR $TESTPOOL/$TESTFS unset EXPANDER_LIST typeset -A EXPANDER_LIST unset PHY_LIST typeset -A PHY_LIST # Tell the enable/disable SAS disk routines that we don't want to # wait for the disk to disappear or reappear. We'll do the wait at # the end. export NO_SAS_DISK_WAIT=1 # First, disable the PHYs for all of the disks. for CURDISK in ${TMPDISKS[*]} do # Find the first disk, get the expander and phy log_note "Looking for expander and phy information for $CURDISK" find_verify_sas_disk $CURDISK # Record the expander and PHY for this particular disk, so # that we can re-enable the disk later, even if it comes # back as a different da(4) instance. EXPANDER_LIST[$CURDISK]=$EXPANDER PHY_LIST[$CURDISK]=$PHY log_note "Disabling \"$CURDISK\" on expander $EXPANDER phy $PHY" # Disable the first disk. We have to do this first, because if # there is I/O active to the disable_sas_disk $EXPANDER $PHY done + rescan_disks - # Wait for 10 seconds to make sure a rescan has happened, and the - # disks have had a chance to go away. - $SLEEP 10 - # Now go through the list of disks, and make sure they are all gone. for CURDISK in ${TMPDISKS[*]} do # Check to make sure disk is gone. camcontrol inquiry $CURDISK > /dev/null 2>&1 if [ $? = 0 ]; then log_fail "Disk \"$CURDISK\" was not removed" fi done # Make sure that the pool status is "UNAVAIL". We have taken all # of the drives offline, so it should be. $ZPOOL status $TESTPOOL |grep "state:" |grep UNAVAIL > /dev/null if [ $? != 0 ]; then log_fail "Pool $TESTPOOL not listed as UNAVAIL" fi # Now we re-enable all of the PHYs. Note that we turned off the # sleep inside enable_sas_disk, so this should quickly. for CURDISK in ${TMPDISKS[*]} do # Re-enable the disk, we don't want to leave it turned off log_note "Re-enabling phy ${PHY_LIST[$CURDISK]} on expander ${EXPANDER_LIST[$CURDISK]}" enable_sas_disk ${EXPANDER_LIST[$CURDISK]} ${PHY_LIST[$CURDISK]} done - - # Wait for 10 seconds to make sure a rescan has happened, and the - # disks have had a chance to reappear. - $SLEEP 10 + rescan_disks unset DISK_FOUND typeset -A DISK_FOUND log_note "Checking to see whether disks have reappeared" ((retries=0)) while [ ${#DISK_FOUND[*]} -lt $NUMDISKS ] && [ $retries -lt 3 ]; do # If this isn't the first time through, give the disk a # little more time to show up. if [ $retries -ne 0 ]; then $SLEEP 5 fi for CURDISK in ${TMPDISKS[*]} do # If we already found this disk, we don't need to # check again. Note that the new name may not be # the same as the name referenced in CURDISK. That # is why we look for the disk by expander and PHY. if [ ! -z ${DISK_FOUND[$CURDISK]} ]; then continue fi # Make sure the disk is back in the topology find_disk_by_phy ${EXPANDER_LIST[$CURDISK]} ${PHY_LIST[$CURDISK]} if [ ! -z "$FOUNDDISK" ]; then # This does serve as a mapping from the old # disk name to the new disk name. DISK_FOUND[$CURDISK]=$FOUNDDISK fi done ((retries++)) done if [ ${#DISK_FOUND[*]} -lt $NUMDISKS ]; then for CURDISK in ${TMPDISKS[*]} do if [ ! -z ${DISK_FOUND[$CURDISK]} ]; then continue fi log_note "Disk $CURDISK has not appeared at phy $PHY_LIST[$CURDISK] on expander $EXPANDER_LIST[$CURDISK] after 20 seconds" done ((num_missing=${NUM_DISKS} - ${#DISK_FOUND[*]})) log_fail "Missing $num_missing Disks out of $NUM_DISKS Disks" else for CURDISK in ${TMPDISKS[*]} do log_note "Disk $CURDISK is back as ${DISK_FOUND[$CURDISK]}" done # Reset our array of disks, because we may have disks that # have come back at a different ID. i.e. da0 may now be da7, # and da0 may no longer be a disk that we are authorized to use. # This is a more generic problem that we may need to tackle # with this test. We may need to reset the DISKS list itself. set -A TMPDISKS ${DISK_FOUND[*]} fi log_note "Raid type is $type" # In theory the pool should be back online. $ZPOOL status $TESTPOOL |grep ONLINE > /dev/null if [ $? != 0 ]; then log_fail "Pool $TESTPOOL is disk $TMPDISK did not automatically join the $TESTPOOL" else log_note "After reinsertion, disk is back in pool and online" fi destroy_pool $TESTPOOL log_must $RM -rf /$TESTPOOL done log_pass Index: projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_replace_003_pos.ksh =================================================================== --- projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_replace_003_pos.ksh (revision 292345) +++ projects/zfsd/head/tests/sys/cddl/zfs/tests/zfsd/zfsd_replace_003_pos.ksh (revision 292346) @@ -1,183 +1,149 @@ #!/usr/local/bin/ksh93 -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright 2012,2013 Spectra Logic Corporation. All rights reserved. # Use is subject to license terms. # # Portions taken from: # ident "@(#)replacement_001_pos.ksh 1.4 08/02/27 SMI" # # $Id: //SpectraBSD/stable/cddl/tools/regression/stc/src/suites/fs/zfs/tests/functional/zfsd/zfsd_replace_003_pos.ksh#1 $ # $FreeBSD$ . $STF_SUITE/include/libtest.kshlib . $STF_SUITE/include/libsas.kshlib verify_runnable "global" function cleanup { # See if the phy has been disabled, and try to re-enable it if possible. - if [[ -n $EXPANDER0 && -n $PHY0 ]]; then - enable_sas_disk $EXPANDER0 $PHY0 - fi - if [[ -n $EXPANDER1 && -n $PHY1 ]]; then - enable_sas_disk $EXPANDER1 $PHY1 - fi - if [[ -n $EXPANDER && -n $PHY ]]; then - enable_sas_disk $EXPANDER $PHY - fi + [ -n "$EXPANDER0" -a -n "$PHY0" ] && enable_sas_disk $EXPANDER0 $PHY0 + [ -n "$EXPANDER1" -a -n "$PHY1" ] && enable_sas_disk $EXPANDER1 $PHY1 + [ -n "$EXPANDER" -a -n "$PHY" ] && enable_sas_disk $EXPANDER $PHY - if poolexists $TESTPOOL; then - destroy_pool $TESTPOOL - fi - + destroy_pool $TESTPOOL [[ -e $TESTDIR ]] && log_must $RM -rf $TESTDIR/* } # arg1: disk devname # Leaves EXPANDER and PHY set appropriately function remove_disk { typeset DISK=$1 # Find the first disk, get the expander and phy log_note "Looking for expander and phy information for $DISK" find_verify_sas_disk $DISK log_note "Disabling \"$DISK\" on expander $EXPANDER phy $PHY" # Disable the first disk. disable_sas_disk $EXPANDER $PHY # Check to make sure disk is gone. - camcontrol inquiry $DISK > /dev/null 2>&1 - if [ $? = 0 ]; then - log_fail "Disk \"$DISK\" was not removed" - fi + find_disk_by_phy $EXPANDER $PHY + [ -n "$FOUNDDISK" ] && log_fail "Disk \"$DISK\" was not removed" # Check to make sure ZFS sees the disk as removed - $ZPOOL status $TESTPOOL |grep $DISK |grep REMOVED > /dev/null - if [ $? != 0 ]; then - log_fail "disk $DISK not listed as removed" - fi + wait_for_pool_removal 20 } # arg1: disk's old devname # arg2: disk's expander's devname # arg3: disk's phy number +# arg4: whether the devname must differ after reconnecting function reconnect_disk { typeset DISK=$1 typeset EXPANDER=$2 typeset PHY=$3 + typeset DEVNAME_DIFFERS=$4 + # Re-enable the disk, we don't want to leave it turned off log_note "Re-enabling phy $PHY on expander $EXPANDER" enable_sas_disk $EXPANDER $PHY log_note "Checking to see whether disk has reappeared" # Make sure the disk is back in the topology - find_disk_by_phy $EXPANDER $PHY - ((retries=0)) - while [ -z "$FOUNDDISK" ] && [ "$retries" -lt 10 ]; do - $SLEEP 5 - find_disk_by_phy $EXPANDER $PHY - done + wait_for_disk_to_reappear 20 - if [ -z "$FOUNDDISK" ]; then - log_fail "A disk has not appeared at phy $PHY on expander $EXPANDER after 50 seconds" - else - log_note "Disk $DISK is back as $FOUNDDISK" - fi - if [[ $(find_disks $FOUNDDISK) = $(find_disks $DISK) ]]; then - log_unsupported "Disk $DISK reappeared with the same devname. The test must be fixed to guarantee that it will reappear with a different name" - fi + if [ -n "$DEVNAME_MUST_DIFFER" ]; then + prev_disks=$(find_disks $FOUNDDISK) + cur_disks=$(find_disks $DISK) - #Disk should have auto-joined the zpool. Verify it's status is online. - if [[ $(get_device_state $TESTPOOL $FOUNDDISK "") != ONLINE ]]; then - log_fail "disk $FOUNDDISK did not automatically join $TESTPOOL" - else - log_note "After reinsertion, disk $FOUNDDISK is back in pool and online" + # If you get this, the test must be fixed to guarantee that + # it will reappear with a different name. + [ "${prev_disk}" = "${cur_disk}" ] && log_unsupported \ + "Disk $DISK reappeared with the same devname." fi + #Disk should have auto-joined the zpool. Verify it's status is online. + wait_for_pool_dev_state_change 20 $DISK ONLINE } -log_assert "ZFSD will correctly replace disks that dissapear and reappear with different devnames" +log_assert "ZFSD will correctly replace disks that disappear and reappear \ + with different devnames" + # Outline # Create a double-parity pool # Remove two disks by disabling their SAS phys # Reenable the phys in the opposite order # Check that the disks's devnames have swapped # Verify that the pool regains its health log_onexit cleanup +ensure_zfsd_running child_pids="" set -A DISKS_ARRAY $DISKS typeset DISK0=${DISKS_ARRAY[0]} typeset DISK1=${DISKS_ARRAY[1]} for type in "raidz2" "mirror"; do # Create a pool on the supplied disks create_pool $TESTPOOL $type $DISKS remove_disk $DISK0 typeset EXPANDER0=$EXPANDER typeset PHY0=$PHY remove_disk $DISK1 typeset EXPANDER1=$EXPANDER typeset PHY1=$PHY # Make sure that the pool is degraded $ZPOOL status $TESTPOOL |grep "state:" |grep DEGRADED > /dev/null if [ $? != 0 ]; then log_fail "Pool $TESTPOOL not listed as DEGRADED" fi reconnect_disk $DISK1 $EXPANDER1 $PHY1 reconnect_disk $DISK0 $EXPANDER0 $PHY0 - - #Wait, then verify resilver done, and that pool is optimal - ((retries=24)) - $ZPOOL status $TESTPOOL |grep "scan:" |grep "resilvered" > /dev/null - while [ $? != 0 ] && [ "$retries" -gt 0 ]; do - log_note "Retry $retries" - $SLEEP 5 - ((retries--)) - $ZPOOL status $TESTPOOL |grep "scan:" |grep "resilvered" > /dev/null - done - - $ZPOOL status $TESTPOOL |grep "scan:" |grep "resilvered" > /dev/null - if [ $? != 0 ]; then - log_fail "Pool $TESTPOOL did not finish resilvering in 120 seconds" - else - log_note "Auto-resilver completed sucessfully" - fi - + wait_until_resilvered destroy_pool $TESTPOOL log_must $RM -rf /$TESTPOOL done log_pass