xref: /freebsd/tests/sys/cddl/zfs/include/libtest.kshlib (revision ac00d4d59b18a76c6148ca5d7439bb446d38da5c)
12fae26bdSAlan Somers# vim: filetype=sh
22fae26bdSAlan Somers#
32fae26bdSAlan Somers# CDDL HEADER START
42fae26bdSAlan Somers#
52fae26bdSAlan Somers# The contents of this file are subject to the terms of the
62fae26bdSAlan Somers# Common Development and Distribution License (the "License").
72fae26bdSAlan Somers# You may not use this file except in compliance with the License.
82fae26bdSAlan Somers#
92fae26bdSAlan Somers# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
102fae26bdSAlan Somers# or http://www.opensolaris.org/os/licensing.
112fae26bdSAlan Somers# See the License for the specific language governing permissions
122fae26bdSAlan Somers# and limitations under the License.
132fae26bdSAlan Somers#
142fae26bdSAlan Somers# When distributing Covered Code, include this CDDL HEADER in each
152fae26bdSAlan Somers# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
162fae26bdSAlan Somers# If applicable, add the following below this CDDL HEADER, with the
172fae26bdSAlan Somers# fields enclosed by brackets "[]" replaced with your own identifying
182fae26bdSAlan Somers# information: Portions Copyright [yyyy] [name of copyright owner]
192fae26bdSAlan Somers#
202fae26bdSAlan Somers# CDDL HEADER END
212fae26bdSAlan Somers#
222fae26bdSAlan Somers
232fae26bdSAlan Somers#
242fae26bdSAlan Somers# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
252fae26bdSAlan Somers# Use is subject to license terms.
262fae26bdSAlan Somers
272fae26bdSAlan Somers. ${STF_SUITE}/include/logapi.kshlib
282fae26bdSAlan Somers
292fae26bdSAlan SomersZFS=${ZFS:-/sbin/zfs}
302fae26bdSAlan SomersZPOOL=${ZPOOL:-/sbin/zpool}
312fae26bdSAlan Somersos_name=`uname -s`
322fae26bdSAlan Somers
332fae26bdSAlan Somers# Determine if a test has the necessary requirements to run
342fae26bdSAlan Somers
352fae26bdSAlan Somersfunction test_requires
362fae26bdSAlan Somers{
372fae26bdSAlan Somers        integer unsupported=0
382fae26bdSAlan Somers        unsupported_list=""
392fae26bdSAlan Somers        until [[ $# -eq 0 ]];do
402fae26bdSAlan Somers                var_name=$1
412fae26bdSAlan Somers                cmd=$(eval echo \$${1})
422fae26bdSAlan Somers                if [[ ! "$cmd" != "" ]] ; then
432fae26bdSAlan Somers                        print $var_name is not set
442fae26bdSAlan Somers                        unsupported_list="$var_name $unsupported_list"
452fae26bdSAlan Somers                        ((unsupported=unsupported+1))
462fae26bdSAlan Somers                fi
472fae26bdSAlan Somers                shift
482fae26bdSAlan Somers        done
492fae26bdSAlan Somers        if [[ unsupported -gt 0 ]] ; then
502fae26bdSAlan Somers                log_unsupported "$unsupported_list commands are unsupported"
512fae26bdSAlan Somers        else
522fae26bdSAlan Somers                log_note "All commands are supported"
532fae26bdSAlan Somers        fi
542fae26bdSAlan Somers}
552fae26bdSAlan Somers
562fae26bdSAlan Somers# Determine whether a dataset is mounted
572fae26bdSAlan Somers#
582fae26bdSAlan Somers# $1 dataset name
592fae26bdSAlan Somers# $2 filesystem type; optional - defaulted to zfs
602fae26bdSAlan Somers#
612fae26bdSAlan Somers# Return 0 if dataset is mounted; 1 if unmounted; 2 on error
622fae26bdSAlan Somers
632fae26bdSAlan Somersfunction ismounted
642fae26bdSAlan Somers{
652fae26bdSAlan Somers	typeset fstype=$2
662fae26bdSAlan Somers	[[ -z $fstype ]] && fstype=zfs
672fae26bdSAlan Somers	typeset out dir name ret
682fae26bdSAlan Somers
692fae26bdSAlan Somers	case $fstype in
702fae26bdSAlan Somers		zfs)
712fae26bdSAlan Somers			if [[ "$1" == "/"* ]] ; then
722fae26bdSAlan Somers				for out in $($ZFS mount | $AWK '{print $2}') ; do
732fae26bdSAlan Somers					[[ $1 == $out ]] && return 0
742fae26bdSAlan Somers				done
752fae26bdSAlan Somers			else
762fae26bdSAlan Somers				for out in $($ZFS mount | $AWK '{print $1}') ; do
772fae26bdSAlan Somers					[[ $1 == $out ]] && return 0
782fae26bdSAlan Somers				done
792fae26bdSAlan Somers			fi
802fae26bdSAlan Somers		;;
812fae26bdSAlan Somers		ufs|nfs)
822fae26bdSAlan Somers			# a = device, b = "on", c = mount point", d = flags
832fae26bdSAlan Somers			$MOUNT | $GREP $fstype | while read a b c d
842fae26bdSAlan Somers			do
852fae26bdSAlan Somers				[[ "$1" == "$a" || "$1" == "$c" ]] && return 0
862fae26bdSAlan Somers			done
872fae26bdSAlan Somers		;;
882fae26bdSAlan Somers	esac
892fae26bdSAlan Somers
902fae26bdSAlan Somers	return 1
912fae26bdSAlan Somers}
922fae26bdSAlan Somers
932fae26bdSAlan Somers# Return 0 if a dataset is mounted; 1 otherwise
942fae26bdSAlan Somers#
952fae26bdSAlan Somers# $1 dataset name
962fae26bdSAlan Somers# $2 filesystem type; optional - defaulted to zfs
972fae26bdSAlan Somers
982fae26bdSAlan Somersfunction mounted
992fae26bdSAlan Somers{
1002fae26bdSAlan Somers	ismounted $1 $2
1012fae26bdSAlan Somers	(( $? == 0 )) && return 0
1022fae26bdSAlan Somers	return 1
1032fae26bdSAlan Somers}
1042fae26bdSAlan Somers
1052fae26bdSAlan Somers# Return 0 if a dataset is unmounted; 1 otherwise
1062fae26bdSAlan Somers#
1072fae26bdSAlan Somers# $1 dataset name
1082fae26bdSAlan Somers# $2 filesystem type; optional - defaulted to zfs
1092fae26bdSAlan Somers
1102fae26bdSAlan Somersfunction unmounted
1112fae26bdSAlan Somers{
1122fae26bdSAlan Somers	ismounted $1 $2
1132fae26bdSAlan Somers	(( $? == 1 )) && return 0
1142fae26bdSAlan Somers	return 1
1152fae26bdSAlan Somers}
1162fae26bdSAlan Somers
1172fae26bdSAlan Somers# split line on ","
1182fae26bdSAlan Somers#
1192fae26bdSAlan Somers# $1 - line to split
1202fae26bdSAlan Somers
1212fae26bdSAlan Somersfunction splitline
1222fae26bdSAlan Somers{
1232fae26bdSAlan Somers	$ECHO $1 | $SED "s/,/ /g"
1242fae26bdSAlan Somers}
1252fae26bdSAlan Somers
1262fae26bdSAlan Somersfunction default_setup
1272fae26bdSAlan Somers{
1282fae26bdSAlan Somers	default_setup_noexit "$@"
1292fae26bdSAlan Somers
1302fae26bdSAlan Somers	log_pass
1312fae26bdSAlan Somers}
1322fae26bdSAlan Somers
1332fae26bdSAlan Somers#
1342fae26bdSAlan Somers# Given a list of disks, setup storage pools and datasets.
1352fae26bdSAlan Somers#
1362fae26bdSAlan Somersfunction default_setup_noexit
1372fae26bdSAlan Somers{
1382fae26bdSAlan Somers	typeset disklist=$1
1392fae26bdSAlan Somers	typeset container=$2
1402fae26bdSAlan Somers	typeset volume=$3
1412fae26bdSAlan Somers
1422fae26bdSAlan Somers	if is_global_zone; then
1432fae26bdSAlan Somers		if poolexists $TESTPOOL ; then
1442fae26bdSAlan Somers			destroy_pool $TESTPOOL
1452fae26bdSAlan Somers		fi
1462fae26bdSAlan Somers		[[ -d /$TESTPOOL ]] && $RM -rf /$TESTPOOL
1472fae26bdSAlan Somers		log_must $ZPOOL create -f $TESTPOOL $disklist
1482fae26bdSAlan Somers	else
1492fae26bdSAlan Somers		reexport_pool
1502fae26bdSAlan Somers	fi
1512fae26bdSAlan Somers
1522fae26bdSAlan Somers	$RM -rf $TESTDIR  || log_unresolved Could not remove $TESTDIR
1532fae26bdSAlan Somers	$MKDIR -p $TESTDIR || log_unresolved Could not create $TESTDIR
1542fae26bdSAlan Somers
1552fae26bdSAlan Somers	log_must $ZFS create $TESTPOOL/$TESTFS
1562fae26bdSAlan Somers	log_must $ZFS set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
1572fae26bdSAlan Somers
1582fae26bdSAlan Somers	if [[ -n $container ]]; then
1592fae26bdSAlan Somers		$RM -rf $TESTDIR1  || \
1602fae26bdSAlan Somers			log_unresolved Could not remove $TESTDIR1
1612fae26bdSAlan Somers		$MKDIR -p $TESTDIR1 || \
1622fae26bdSAlan Somers			log_unresolved Could not create $TESTDIR1
1632fae26bdSAlan Somers
1642fae26bdSAlan Somers		log_must $ZFS create $TESTPOOL/$TESTCTR
1652fae26bdSAlan Somers		log_must $ZFS set canmount=off $TESTPOOL/$TESTCTR
1662fae26bdSAlan Somers		log_must $ZFS create $TESTPOOL/$TESTCTR/$TESTFS1
1672fae26bdSAlan Somers		log_must $ZFS set mountpoint=$TESTDIR1 \
1682fae26bdSAlan Somers		    $TESTPOOL/$TESTCTR/$TESTFS1
1692fae26bdSAlan Somers	fi
1702fae26bdSAlan Somers
1712fae26bdSAlan Somers	if [[ -n $volume ]]; then
1722fae26bdSAlan Somers		if is_global_zone ; then
1732fae26bdSAlan Somers			log_must $ZFS create -V $VOLSIZE $TESTPOOL/$TESTVOL
1742fae26bdSAlan Somers		else
1752fae26bdSAlan Somers			log_must $ZFS create $TESTPOOL/$TESTVOL
1762fae26bdSAlan Somers		fi
1772fae26bdSAlan Somers
1782fae26bdSAlan Somers	fi
1792fae26bdSAlan Somers}
1802fae26bdSAlan Somers
1812fae26bdSAlan Somers#
1822fae26bdSAlan Somers# Given a list of disks, setup a storage pool, file system and
1832fae26bdSAlan Somers# a container.
1842fae26bdSAlan Somers#
1852fae26bdSAlan Somersfunction default_container_setup
1862fae26bdSAlan Somers{
1872fae26bdSAlan Somers	typeset disklist=$1
1882fae26bdSAlan Somers
1892fae26bdSAlan Somers	default_setup "$disklist" "true"
1902fae26bdSAlan Somers}
1912fae26bdSAlan Somers
1922fae26bdSAlan Somers#
1932fae26bdSAlan Somers# Given a list of disks, setup a storage pool,file system
1942fae26bdSAlan Somers# and a volume.
1952fae26bdSAlan Somers#
1962fae26bdSAlan Somersfunction default_volume_setup
1972fae26bdSAlan Somers{
1982fae26bdSAlan Somers	typeset disklist=$1
1992fae26bdSAlan Somers
2002fae26bdSAlan Somers	default_setup "$disklist" "" "true"
2012fae26bdSAlan Somers}
2022fae26bdSAlan Somers
2032fae26bdSAlan Somers#
2042fae26bdSAlan Somers# Given a list of disks, setup a storage pool,file system,
2052fae26bdSAlan Somers# a container and a volume.
2062fae26bdSAlan Somers#
2072fae26bdSAlan Somersfunction default_container_volume_setup
2082fae26bdSAlan Somers{
2092fae26bdSAlan Somers	typeset disklist=$1
2102fae26bdSAlan Somers
2112fae26bdSAlan Somers	default_setup "$disklist" "true" "true"
2122fae26bdSAlan Somers}
2132fae26bdSAlan Somers
2142fae26bdSAlan Somers#
2152fae26bdSAlan Somers# Create a snapshot on a filesystem or volume. Defaultly create a snapshot on
2162fae26bdSAlan Somers# filesystem
2172fae26bdSAlan Somers#
2182fae26bdSAlan Somers# $1 Existing filesystem or volume name. Default, $TESTFS
2192fae26bdSAlan Somers# $2 snapshot name. Default, $TESTSNAP
2202fae26bdSAlan Somers#
2212fae26bdSAlan Somersfunction create_snapshot
2222fae26bdSAlan Somers{
2232fae26bdSAlan Somers	typeset fs_vol=${1:-$TESTFS}
2242fae26bdSAlan Somers	typeset snap=${2:-$TESTSNAP}
2252fae26bdSAlan Somers
2262fae26bdSAlan Somers	[[ -z $fs_vol ]] && log_fail "Filesystem or volume's name is undefined."
2272fae26bdSAlan Somers	[[ -z $snap ]] && log_fail "Snapshot's name is undefined."
2282fae26bdSAlan Somers
2292fae26bdSAlan Somers	if snapexists $fs_vol@$snap; then
2302fae26bdSAlan Somers		log_fail "$fs_vol@$snap already exists."
2312fae26bdSAlan Somers	fi
2322fae26bdSAlan Somers	datasetexists $fs_vol || \
2332fae26bdSAlan Somers		log_fail "$fs_vol must exist."
2342fae26bdSAlan Somers
2352fae26bdSAlan Somers	log_must $ZFS snapshot $fs_vol@$snap
2362fae26bdSAlan Somers}
2372fae26bdSAlan Somers
2382fae26bdSAlan Somers#
2392fae26bdSAlan Somers# Create a clone from a snapshot, default clone name is $TESTCLONE.
2402fae26bdSAlan Somers#
2412fae26bdSAlan Somers# $1 Existing snapshot, $TESTPOOL/$TESTFS@$TESTSNAP is default.
2422fae26bdSAlan Somers# $2 Clone name, $TESTPOOL/$TESTCLONE is default.
2432fae26bdSAlan Somers#
2442fae26bdSAlan Somersfunction create_clone   # snapshot clone
2452fae26bdSAlan Somers{
2462fae26bdSAlan Somers	typeset snap=${1:-$TESTPOOL/$TESTFS@$TESTSNAP}
2472fae26bdSAlan Somers	typeset clone=${2:-$TESTPOOL/$TESTCLONE}
2482fae26bdSAlan Somers
2492fae26bdSAlan Somers	[[ -z $snap ]] && \
2502fae26bdSAlan Somers		log_fail "Snapshot name is undefined."
2512fae26bdSAlan Somers	[[ -z $clone ]] && \
2522fae26bdSAlan Somers		log_fail "Clone name is undefined."
2532fae26bdSAlan Somers
2542fae26bdSAlan Somers	log_must $ZFS clone $snap $clone
2552fae26bdSAlan Somers}
2562fae26bdSAlan Somers
2572fae26bdSAlan Somersfunction default_mirror_setup
2582fae26bdSAlan Somers{
2592fae26bdSAlan Somers	default_mirror_setup_noexit $1 $2 $3
2602fae26bdSAlan Somers
2612fae26bdSAlan Somers	log_pass
2622fae26bdSAlan Somers}
2632fae26bdSAlan Somers
2642fae26bdSAlan Somers#
2652fae26bdSAlan Somers# Given a pair of disks, set up a storage pool and dataset for the mirror
2662fae26bdSAlan Somers# @parameters: $1 the primary side of the mirror
2672fae26bdSAlan Somers#   $2 the secondary side of the mirror
2682fae26bdSAlan Somers# @uses: ZPOOL ZFS TESTPOOL TESTFS
2692fae26bdSAlan Somersfunction default_mirror_setup_noexit
2702fae26bdSAlan Somers{
2712fae26bdSAlan Somers	readonly func="default_mirror_setup_noexit"
2722fae26bdSAlan Somers	typeset primary=$1
2732fae26bdSAlan Somers	typeset secondary=$2
2742fae26bdSAlan Somers
2752fae26bdSAlan Somers	[[ -z $primary ]] && \
2762fae26bdSAlan Somers		log_fail "$func: No parameters passed"
2772fae26bdSAlan Somers	[[ -z $secondary ]] && \
2782fae26bdSAlan Somers		log_fail "$func: No secondary partition passed"
2792fae26bdSAlan Somers	[[ -d /$TESTPOOL ]] && $RM -rf /$TESTPOOL
2802fae26bdSAlan Somers	log_must $ZPOOL create -f $TESTPOOL mirror $@
2812fae26bdSAlan Somers	log_must $ZFS create $TESTPOOL/$TESTFS
2822fae26bdSAlan Somers	log_must $ZFS set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
2832fae26bdSAlan Somers}
2842fae26bdSAlan Somers
2852fae26bdSAlan Somers#
2862fae26bdSAlan Somers# create a number of mirrors.
2872fae26bdSAlan Somers# We create a number($1) of 2 way mirrors using the pairs of disks named
2882fae26bdSAlan Somers# on the command line. These mirrors are *not* mounted
2892fae26bdSAlan Somers# @parameters: $1 the number of mirrors to create
2902fae26bdSAlan Somers#  $... the devices to use to create the mirrors on
2912fae26bdSAlan Somers# @uses: ZPOOL ZFS TESTPOOL
2922fae26bdSAlan Somersfunction setup_mirrors
2932fae26bdSAlan Somers{
2942fae26bdSAlan Somers	typeset -i nmirrors=$1
2952fae26bdSAlan Somers
2962fae26bdSAlan Somers	shift
2972fae26bdSAlan Somers	while (( nmirrors > 0 )); do
2982fae26bdSAlan Somers		log_must test -n "$1" -a -n "$2"
2992fae26bdSAlan Somers		[[ -d /$TESTPOOL$nmirrors ]] && $RM -rf /$TESTPOOL$nmirrors
3002fae26bdSAlan Somers		log_must $ZPOOL create -f $TESTPOOL$nmirrors mirror $1 $2
3012fae26bdSAlan Somers		shift 2
3022fae26bdSAlan Somers		(( nmirrors = nmirrors - 1 ))
3032fae26bdSAlan Somers	done
3042fae26bdSAlan Somers}
3052fae26bdSAlan Somers
3062fae26bdSAlan Somers#
3072fae26bdSAlan Somers# create a number of raidz pools.
3082fae26bdSAlan Somers# We create a number($1) of 2 raidz pools  using the pairs of disks named
3092fae26bdSAlan Somers# on the command line. These pools are *not* mounted
3102fae26bdSAlan Somers# @parameters: $1 the number of pools to create
3112fae26bdSAlan Somers#  $... the devices to use to create the pools on
3122fae26bdSAlan Somers# @uses: ZPOOL ZFS TESTPOOL
3132fae26bdSAlan Somersfunction setup_raidzs
3142fae26bdSAlan Somers{
3152fae26bdSAlan Somers	typeset -i nraidzs=$1
3162fae26bdSAlan Somers
3172fae26bdSAlan Somers	shift
3182fae26bdSAlan Somers	while (( nraidzs > 0 )); do
3192fae26bdSAlan Somers		log_must test -n "$1" -a -n "$2"
3202fae26bdSAlan Somers		[[ -d /$TESTPOOL$nraidzs ]] && $RM -rf /$TESTPOOL$nraidzs
3212fae26bdSAlan Somers		log_must $ZPOOL create -f $TESTPOOL$nraidzs raidz $1 $2
3222fae26bdSAlan Somers		shift 2
3232fae26bdSAlan Somers		(( nraidzs = nraidzs - 1 ))
3242fae26bdSAlan Somers	done
3252fae26bdSAlan Somers}
3262fae26bdSAlan Somers
3272fae26bdSAlan Somers#
3282fae26bdSAlan Somers# Destroy the configured testpool mirrors.
3292fae26bdSAlan Somers# the mirrors are of the form ${TESTPOOL}{number}
3302fae26bdSAlan Somers# @uses: ZPOOL ZFS TESTPOOL
3312fae26bdSAlan Somersfunction destroy_mirrors
3322fae26bdSAlan Somers{
3332fae26bdSAlan Somers	default_cleanup_noexit
3342fae26bdSAlan Somers
3352fae26bdSAlan Somers	log_pass
3362fae26bdSAlan Somers}
3372fae26bdSAlan Somers
3382fae26bdSAlan Somers#
3392fae26bdSAlan Somers# Given a minimum of two disks, set up a storage pool and dataset for the raid-z
3402fae26bdSAlan Somers# $1 the list of disks
3412fae26bdSAlan Somers#
3422fae26bdSAlan Somersfunction default_raidz_setup
3432fae26bdSAlan Somers{
3442fae26bdSAlan Somers	typeset disklist="$*"
3452fae26bdSAlan Somers	set -A disks $disklist
3462fae26bdSAlan Somers
3472fae26bdSAlan Somers	if [[ ${#disks[*]} -lt 2 ]]; then
3482fae26bdSAlan Somers		log_fail "A raid-z requires a minimum of two disks."
3492fae26bdSAlan Somers	fi
3502fae26bdSAlan Somers
3512fae26bdSAlan Somers	[[ -d /$TESTPOOL ]] && $RM -rf /$TESTPOOL
3522fae26bdSAlan Somers	log_must $ZPOOL create -f $TESTPOOL raidz $1 $2 $3
3532fae26bdSAlan Somers	log_must $ZFS create $TESTPOOL/$TESTFS
3542fae26bdSAlan Somers	log_must $ZFS set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
3552fae26bdSAlan Somers
3562fae26bdSAlan Somers	log_pass
3572fae26bdSAlan Somers}
3582fae26bdSAlan Somers
3592fae26bdSAlan Somers#
3602fae26bdSAlan Somers# Common function used to cleanup storage pools and datasets.
3612fae26bdSAlan Somers#
3622fae26bdSAlan Somers# Invoked at the start of the test suite to ensure the system
3632fae26bdSAlan Somers# is in a known state, and also at the end of each set of
3642fae26bdSAlan Somers# sub-tests to ensure errors from one set of tests doesn't
3652fae26bdSAlan Somers# impact the execution of the next set.
3662fae26bdSAlan Somers
3672fae26bdSAlan Somersfunction default_cleanup
3682fae26bdSAlan Somers{
3692fae26bdSAlan Somers	default_cleanup_noexit
3702fae26bdSAlan Somers
3712fae26bdSAlan Somers	log_pass
3722fae26bdSAlan Somers}
3732fae26bdSAlan Somers
3742fae26bdSAlan Somersfunction all_pools
3752fae26bdSAlan Somers{
3762fae26bdSAlan Somers	cmd="$ZPOOL list -H -o name | $GREP 'testpool'"
3772fae26bdSAlan Somers	eval $cmd
3782fae26bdSAlan Somers}
3792fae26bdSAlan Somers
3802fae26bdSAlan Somers#
3812fae26bdSAlan Somers# Returns 0 if the system contains any pools that must not be modified by the
3822fae26bdSAlan Somers# ZFS tests.
3832fae26bdSAlan Somers#
3842fae26bdSAlan Somersfunction other_pools_exist
3852fae26bdSAlan Somers{
3862fae26bdSAlan Somers	typeset pool_count=`$ZPOOL list -H | $GREP -v '^testpool' | $WC -l`
3872fae26bdSAlan Somers	[ "$pool_count" -ne 0 ]
3882fae26bdSAlan Somers}
3892fae26bdSAlan Somers
3902fae26bdSAlan Somersfunction default_cleanup_noexit
3912fae26bdSAlan Somers{
3922fae26bdSAlan Somers	typeset exclude=""
3932fae26bdSAlan Somers	typeset pool=""
3942fae26bdSAlan Somers	#
3952fae26bdSAlan Somers	# Destroying the pool will also destroy any
3962fae26bdSAlan Somers	# filesystems it contains.
3972fae26bdSAlan Somers	#
3982fae26bdSAlan Somers	if is_global_zone; then
3992fae26bdSAlan Somers		# Here, we loop through the pools we're allowed to
4002fae26bdSAlan Somers		# destroy, only destroying them if it's safe to do
4012fae26bdSAlan Somers		# so.
4022fae26bdSAlan Somers		for pool in $(all_pools); do
4032fae26bdSAlan Somers			if safe_to_destroy_pool $pool; then
4042fae26bdSAlan Somers				destroy_pool $pool
4052fae26bdSAlan Somers			fi
4062fae26bdSAlan Somers		done
4072fae26bdSAlan Somers	else
4082fae26bdSAlan Somers		typeset fs=""
4092fae26bdSAlan Somers		for fs in $($ZFS list -H -o name \
4102fae26bdSAlan Somers		    | $GREP "^$ZONE_POOL/$ZONE_CTR[01234]/"); do
4112fae26bdSAlan Somers			datasetexists $fs && \
4122fae26bdSAlan Somers				log_must $ZFS destroy -Rf $fs
4132fae26bdSAlan Somers		done
4142fae26bdSAlan Somers
4152fae26bdSAlan Somers		# Need cleanup here to avoid garbage dir left.
4162fae26bdSAlan Somers		for fs in $($ZFS list -H -o name \
4172fae26bdSAlan Somers		    ); do
4182fae26bdSAlan Somers			[[ $fs == /$ZONE_POOL ]] && continue
4192fae26bdSAlan Somers			[[ -d $fs ]] && log_must $RM -rf $fs/*
4202fae26bdSAlan Somers		done
4212fae26bdSAlan Somers
4222fae26bdSAlan Somers		#
4232fae26bdSAlan Somers		# Reset the $ZONE_POOL/$ZONE_CTR[01234] file systems property to
4242fae26bdSAlan Somers		# the default value
4252fae26bdSAlan Somers		#
4262fae26bdSAlan Somers		for fs in $($ZFS list -H -o name \
4272fae26bdSAlan Somers		    ); do
4282fae26bdSAlan Somers			if [[ $fs == $ZONE_POOL/$ZONE_CTR[01234] ]]; then
4292fae26bdSAlan Somers				log_must $ZFS set reservation=none $fs
4302fae26bdSAlan Somers				log_must $ZFS set recordsize=128K $fs
4312fae26bdSAlan Somers				log_must $ZFS set mountpoint=/$fs $fs
4322fae26bdSAlan Somers				typeset enc=""
4332fae26bdSAlan Somers				enc=$(get_prop encryption $fs)
4342fae26bdSAlan Somers				if [[ $? -ne 0 ]] || [[ -z "$enc" ]] || \
4352fae26bdSAlan Somers					[[ "$enc" == "off" ]]; then
4362fae26bdSAlan Somers					log_must $ZFS set checksum=on $fs
4372fae26bdSAlan Somers				fi
4382fae26bdSAlan Somers				log_must $ZFS set compression=off $fs
4392fae26bdSAlan Somers				log_must $ZFS set atime=on $fs
4402fae26bdSAlan Somers				log_must $ZFS set devices=off $fs
4412fae26bdSAlan Somers				log_must $ZFS set exec=on $fs
4422fae26bdSAlan Somers				log_must $ZFS set setuid=on $fs
4432fae26bdSAlan Somers				log_must $ZFS set readonly=off $fs
4442fae26bdSAlan Somers				log_must $ZFS set snapdir=hidden $fs
4452fae26bdSAlan Somers				log_must $ZFS set aclmode=groupmask $fs
4462fae26bdSAlan Somers				log_must $ZFS set aclinherit=secure $fs
4472fae26bdSAlan Somers			fi
4482fae26bdSAlan Somers		done
4492fae26bdSAlan Somers	fi
4502fae26bdSAlan Somers
4512fae26bdSAlan Somers	[[ -d $TESTDIR ]] && \
4522fae26bdSAlan Somers		log_must $RM -rf $TESTDIR
4532fae26bdSAlan Somers}
4542fae26bdSAlan Somers
4552fae26bdSAlan Somers
4562fae26bdSAlan Somers#
4572fae26bdSAlan Somers# Common function used to cleanup storage pools, file systems
4582fae26bdSAlan Somers# and containers.
4592fae26bdSAlan Somers#
4602fae26bdSAlan Somersfunction default_container_cleanup
4612fae26bdSAlan Somers{
4622fae26bdSAlan Somers	if ! is_global_zone; then
4632fae26bdSAlan Somers		reexport_pool
4642fae26bdSAlan Somers	fi
4652fae26bdSAlan Somers
4662fae26bdSAlan Somers	ismounted $TESTPOOL/$TESTCTR/$TESTFS1
4672fae26bdSAlan Somers	[[ $? -eq 0 ]] && \
4682fae26bdSAlan Somers	    log_must $ZFS unmount $TESTPOOL/$TESTCTR/$TESTFS1
4692fae26bdSAlan Somers
4702fae26bdSAlan Somers	datasetexists $TESTPOOL/$TESTCTR/$TESTFS1 && \
4712fae26bdSAlan Somers	    log_must $ZFS destroy -R $TESTPOOL/$TESTCTR/$TESTFS1
4722fae26bdSAlan Somers
4732fae26bdSAlan Somers	datasetexists $TESTPOOL/$TESTCTR && \
4742fae26bdSAlan Somers	    log_must $ZFS destroy -Rf $TESTPOOL/$TESTCTR
4752fae26bdSAlan Somers
4762fae26bdSAlan Somers	[[ -e $TESTDIR1 ]] && \
4772fae26bdSAlan Somers	    log_must $RM -rf $TESTDIR1 > /dev/null 2>&1
4782fae26bdSAlan Somers
4792fae26bdSAlan Somers	default_cleanup
4802fae26bdSAlan Somers}
4812fae26bdSAlan Somers
4822fae26bdSAlan Somers#
4832fae26bdSAlan Somers# Common function used to cleanup snapshot of file system or volume. Default to
4842fae26bdSAlan Somers# delete the file system's snapshot
4852fae26bdSAlan Somers#
4862fae26bdSAlan Somers# $1 snapshot name
4872fae26bdSAlan Somers#
4882fae26bdSAlan Somersfunction destroy_snapshot
4892fae26bdSAlan Somers{
4902fae26bdSAlan Somers	typeset snap=${1:-$TESTPOOL/$TESTFS@$TESTSNAP}
4912fae26bdSAlan Somers
4922fae26bdSAlan Somers	if ! snapexists $snap; then
4932fae26bdSAlan Somers		log_fail "'$snap' does not existed."
4942fae26bdSAlan Somers	fi
4952fae26bdSAlan Somers
4962fae26bdSAlan Somers	#
4972fae26bdSAlan Somers	# For the sake of the value which come from 'get_prop' is not equal
4982fae26bdSAlan Somers	# to the really mountpoint when the snapshot is unmounted. So, firstly
4992fae26bdSAlan Somers	# check and make sure this snapshot's been mounted in current system.
5002fae26bdSAlan Somers	#
5012fae26bdSAlan Somers	typeset mtpt=""
5022fae26bdSAlan Somers	if ismounted $snap; then
5032fae26bdSAlan Somers		mtpt=$(get_prop mountpoint $snap)
5042fae26bdSAlan Somers		(( $? != 0 )) && \
5052fae26bdSAlan Somers			log_fail "get_prop mountpoint $snap failed."
5062fae26bdSAlan Somers	fi
5072fae26bdSAlan Somers
5082fae26bdSAlan Somers	log_must $ZFS destroy $snap
5092fae26bdSAlan Somers	[[ $mtpt != "" && -d $mtpt ]] && \
5102fae26bdSAlan Somers		log_must $RM -rf $mtpt
5112fae26bdSAlan Somers}
5122fae26bdSAlan Somers
5132fae26bdSAlan Somers#
5142fae26bdSAlan Somers# Common function used to cleanup clone.
5152fae26bdSAlan Somers#
5162fae26bdSAlan Somers# $1 clone name
5172fae26bdSAlan Somers#
5182fae26bdSAlan Somersfunction destroy_clone
5192fae26bdSAlan Somers{
5202fae26bdSAlan Somers	typeset clone=${1:-$TESTPOOL/$TESTCLONE}
5212fae26bdSAlan Somers
5222fae26bdSAlan Somers	if ! datasetexists $clone; then
5232fae26bdSAlan Somers		log_fail "'$clone' does not existed."
5242fae26bdSAlan Somers	fi
5252fae26bdSAlan Somers
5262fae26bdSAlan Somers	# With the same reason in destroy_snapshot
5272fae26bdSAlan Somers	typeset mtpt=""
5282fae26bdSAlan Somers	if ismounted $clone; then
5292fae26bdSAlan Somers		mtpt=$(get_prop mountpoint $clone)
5302fae26bdSAlan Somers		(( $? != 0 )) && \
5312fae26bdSAlan Somers			log_fail "get_prop mountpoint $clone failed."
5322fae26bdSAlan Somers	fi
5332fae26bdSAlan Somers
5342fae26bdSAlan Somers	log_must $ZFS destroy $clone
5352fae26bdSAlan Somers	[[ $mtpt != "" && -d $mtpt ]] && \
5362fae26bdSAlan Somers		log_must $RM -rf $mtpt
5372fae26bdSAlan Somers}
5382fae26bdSAlan Somers
5392fae26bdSAlan Somers# Return 0 if a snapshot exists; $? otherwise
5402fae26bdSAlan Somers#
5412fae26bdSAlan Somers# $1 - snapshot name
5422fae26bdSAlan Somers
5432fae26bdSAlan Somersfunction snapexists
5442fae26bdSAlan Somers{
5452fae26bdSAlan Somers	$ZFS list -H -t snapshot "$1" > /dev/null 2>&1
5462fae26bdSAlan Somers	return $?
5472fae26bdSAlan Somers}
5482fae26bdSAlan Somers
5492fae26bdSAlan Somers#
5502fae26bdSAlan Somers# Set a property to a certain value on a dataset.
5512fae26bdSAlan Somers# Sets a property of the dataset to the value as passed in.
5522fae26bdSAlan Somers# @param:
5532fae26bdSAlan Somers#	$1 dataset who's property is being set
5542fae26bdSAlan Somers# 	$2 property to set
5552fae26bdSAlan Somers#	$3 value to set property to
5562fae26bdSAlan Somers# @return:
5572fae26bdSAlan Somers#	0 if the property could be set.
5582fae26bdSAlan Somers#	non-zero otherwise.
5592fae26bdSAlan Somers# @use: ZFS
5602fae26bdSAlan Somers#
5612fae26bdSAlan Somersfunction dataset_setprop
5622fae26bdSAlan Somers{
5632fae26bdSAlan Somers	typeset fn=dataset_setprop
5642fae26bdSAlan Somers
5652fae26bdSAlan Somers	if (( $# < 3 )); then
5662fae26bdSAlan Somers		log_note "$fn: Insufficient parameters (need 3, had $#)"
5672fae26bdSAlan Somers		return 1
5682fae26bdSAlan Somers	fi
5692fae26bdSAlan Somers	typeset output=
5702fae26bdSAlan Somers	output=$($ZFS set $2=$3 $1 2>&1)
5712fae26bdSAlan Somers	typeset rv=$?
5722fae26bdSAlan Somers	if (( rv != 0 )); then
5732fae26bdSAlan Somers		log_note "Setting property on $1 failed."
5742fae26bdSAlan Somers		log_note "property $2=$3"
5752fae26bdSAlan Somers		log_note "Return Code: $rv"
5762fae26bdSAlan Somers		log_note "Output: $output"
5772fae26bdSAlan Somers		return $rv
5782fae26bdSAlan Somers	fi
5792fae26bdSAlan Somers	return 0
5802fae26bdSAlan Somers}
5812fae26bdSAlan Somers
5822fae26bdSAlan Somers#
5832fae26bdSAlan Somers# Assign suite defined dataset properties.
5842fae26bdSAlan Somers# This function is used to apply the suite's defined default set of
5852fae26bdSAlan Somers# properties to a dataset.
5862fae26bdSAlan Somers# @parameters: $1 dataset to use
5872fae26bdSAlan Somers# @uses: ZFS COMPRESSION_PROP CHECKSUM_PROP
5882fae26bdSAlan Somers# @returns:
5892fae26bdSAlan Somers#   0 if the dataset has been altered.
5902fae26bdSAlan Somers#   1 if no pool name was passed in.
5912fae26bdSAlan Somers#   2 if the dataset could not be found.
5922fae26bdSAlan Somers#   3 if the dataset could not have it's properties set.
5932fae26bdSAlan Somers#
5942fae26bdSAlan Somersfunction dataset_set_defaultproperties
5952fae26bdSAlan Somers{
5962fae26bdSAlan Somers	typeset dataset="$1"
5972fae26bdSAlan Somers
5982fae26bdSAlan Somers	[[ -z $dataset ]] && return 1
5992fae26bdSAlan Somers
6002fae26bdSAlan Somers	typeset confset=
6012fae26bdSAlan Somers	typeset -i found=0
6022fae26bdSAlan Somers	for confset in $($ZFS list); do
6032fae26bdSAlan Somers		if [[ $dataset = $confset ]]; then
6042fae26bdSAlan Somers			found=1
6052fae26bdSAlan Somers			break
6062fae26bdSAlan Somers		fi
6072fae26bdSAlan Somers	done
6082fae26bdSAlan Somers	[[ $found -eq 0 ]] && return 2
6092fae26bdSAlan Somers	if [[ -n $COMPRESSION_PROP ]]; then
6102fae26bdSAlan Somers		dataset_setprop $dataset compression $COMPRESSION_PROP || \
6112fae26bdSAlan Somers			return 3
6122fae26bdSAlan Somers		log_note "Compression set to '$COMPRESSION_PROP' on $dataset"
6132fae26bdSAlan Somers	fi
6142fae26bdSAlan Somers	if [[ -n $CHECKSUM_PROP && $WRAPPER != *"crypto"* ]]; then
6152fae26bdSAlan Somers		dataset_setprop $dataset checksum $CHECKSUM_PROP || \
6162fae26bdSAlan Somers			return 3
6172fae26bdSAlan Somers		log_note "Checksum set to '$CHECKSUM_PROP' on $dataset"
6182fae26bdSAlan Somers	fi
6192fae26bdSAlan Somers	return 0
6202fae26bdSAlan Somers}
6212fae26bdSAlan Somers
6222fae26bdSAlan Somers#
6232fae26bdSAlan Somers# Check a numeric assertion
6242fae26bdSAlan Somers# @parameter: $@ the assertion to check
6252fae26bdSAlan Somers# @output: big loud notice if assertion failed
6262fae26bdSAlan Somers# @use: log_fail
6272fae26bdSAlan Somers#
6282fae26bdSAlan Somersfunction assert
6292fae26bdSAlan Somers{
6302fae26bdSAlan Somers	(( $@ )) || log_fail $@
6312fae26bdSAlan Somers}
6322fae26bdSAlan Somers
6332fae26bdSAlan Somersfunction wipe_partition_table #<whole_disk_name> [<whole_disk_name> ...]
6342fae26bdSAlan Somers{
6352fae26bdSAlan Somers	while [[ -n $* ]]; do
6362fae26bdSAlan Somers		typeset diskname=$1
6372fae26bdSAlan Somers		[ ! -e $diskname ] && log_fail "ERROR: $diskname doesn't exist"
638a7478ad1SAndriy Gapon		if gpart list ${diskname#/dev/} >/dev/null 2>&1; then
6392fae26bdSAlan Somers			wait_for 5 1 $GPART destroy -F $diskname
6402fae26bdSAlan Somers		else
6412fae26bdSAlan Somers			log_note "No GPT partitions detected on $diskname"
6422fae26bdSAlan Somers		fi
6432fae26bdSAlan Somers		log_must $GPART create -s gpt $diskname
6442fae26bdSAlan Somers		shift
6452fae26bdSAlan Somers	done
6462fae26bdSAlan Somers}
6472fae26bdSAlan Somers
6482fae26bdSAlan Somers#
6492fae26bdSAlan Somers# Given a slice, size and disk, this function
6502fae26bdSAlan Somers# formats the slice to the specified size.
6512fae26bdSAlan Somers# Size should be specified with units as per
6522fae26bdSAlan Somers# the `format` command requirements eg. 100mb 3gb
6532fae26bdSAlan Somers#
6542fae26bdSAlan Somersfunction set_partition #<slice_num> <slice_start> <size_plus_units>  <whole_disk_name>
6552fae26bdSAlan Somers{
6562fae26bdSAlan Somers	typeset -i slicenum=$1
6572fae26bdSAlan Somers	typeset start=$2
6582fae26bdSAlan Somers	typeset size=$3
6592fae26bdSAlan Somers	typeset disk=$4
6602fae26bdSAlan Somers	set -A devmap a b c d e f g h
6612fae26bdSAlan Somers	[[ -z $slicenum || -z $size || -z $disk ]] && \
6622fae26bdSAlan Somers		log_fail "The slice, size or disk name is unspecified."
6632fae26bdSAlan Somers
6642fae26bdSAlan Somers	size=`$ECHO $size| sed s/mb/M/`
6652fae26bdSAlan Somers	size=`$ECHO $size| sed s/m/M/`
6662fae26bdSAlan Somers	size=`$ECHO $size| sed s/gb/G/`
6672fae26bdSAlan Somers	size=`$ECHO $size| sed s/g/G/`
6682fae26bdSAlan Somers	[[ -n $start ]] && start="-b $start"
6692fae26bdSAlan Somers	log_must $GPART add -t efi $start -s $size -i $slicenum $disk
6702fae26bdSAlan Somers	return 0
6712fae26bdSAlan Somers}
6722fae26bdSAlan Somers
6732fae26bdSAlan Somersfunction get_disk_size #<disk>
6742fae26bdSAlan Somers{
6752fae26bdSAlan Somers	typeset disk=$1
676ee00e55cSAndriy Gapon	diskinfo $disk | awk '{print $3}'
6772fae26bdSAlan Somers}
6782fae26bdSAlan Somers
6792fae26bdSAlan Somersfunction get_available_disk_size #<disk>
6802fae26bdSAlan Somers{
6812fae26bdSAlan Somers	typeset disk=$1
6822fae26bdSAlan Somers	raw_size=`get_disk_size $disk`
6832fae26bdSAlan Somers	(( available_size = raw_size * 95 / 100 ))
6842fae26bdSAlan Somers	echo $available_size
6852fae26bdSAlan Somers}
6862fae26bdSAlan Somers
6872fae26bdSAlan Somers#
6882fae26bdSAlan Somers# Get the end cyl of the given slice
6892fae26bdSAlan Somers# #TODO: fix this to be GPT-compatible if we want to use the SMI WRAPPER.  This
6902fae26bdSAlan Somers# function is not necessary on FreeBSD
6912fae26bdSAlan Somers#
6922fae26bdSAlan Somersfunction get_endslice #<disk> <slice>
6932fae26bdSAlan Somers{
6942fae26bdSAlan Somers	log_fail "get_endslice has not been updated for GPT partitions"
6952fae26bdSAlan Somers}
6962fae26bdSAlan Somers
6972fae26bdSAlan Somers#
6982fae26bdSAlan Somers# Get the first LBA that is beyond the end of the given partition
6992fae26bdSAlan Somersfunction get_partition_end #<disk> <partition_index>
7002fae26bdSAlan Somers{
7012fae26bdSAlan Somers	typeset disk=$1
7022fae26bdSAlan Somers	typeset partition_index=$2
7032fae26bdSAlan Somers	export partition_index
7042fae26bdSAlan Somers	$GPART show $disk | $AWK \
7052fae26bdSAlan Somers		'/^[ \t]/ && $3 ~ ENVIRON["partition_index"] {print $1 + $2}'
7062fae26bdSAlan Somers}
7072fae26bdSAlan Somers
7082fae26bdSAlan Somers
7092fae26bdSAlan Somers#
7102fae26bdSAlan Somers# Given a size,disk and total number of partitions,  this function formats the
7112fae26bdSAlan Somers# disk partitions from 0 to the total partition number with the same specified
7122fae26bdSAlan Somers# size.
7132fae26bdSAlan Somers#
7142fae26bdSAlan Somersfunction partition_disk	#<part_size> <whole_disk_name>	<total_parts>
7152fae26bdSAlan Somers{
7162fae26bdSAlan Somers	typeset -i i=1
7172fae26bdSAlan Somers	typeset part_size=$1
7182fae26bdSAlan Somers	typeset disk_name=$2
7192fae26bdSAlan Somers	typeset total_parts=$3
7202fae26bdSAlan Somers	typeset cyl
7212fae26bdSAlan Somers
7222fae26bdSAlan Somers	wipe_partition_table $disk_name
7232fae26bdSAlan Somers	while (( i <= $total_parts )); do
7242fae26bdSAlan Somers		set_partition $i "" $part_size $disk_name
7252fae26bdSAlan Somers		(( i = i+1 ))
7262fae26bdSAlan Somers	done
7272fae26bdSAlan Somers}
7282fae26bdSAlan Somers
7292fae26bdSAlan Somersfunction size_of_file # fname
7302fae26bdSAlan Somers{
7312fae26bdSAlan Somers	typeset fname=$1
7322fae26bdSAlan Somers	sz=`stat -f '%z' $fname`
7332fae26bdSAlan Somers	[[ -z "$sz" ]] && log_fail "stat($fname) failed"
7342fae26bdSAlan Somers	$ECHO $sz
7352fae26bdSAlan Somers	return 0
7362fae26bdSAlan Somers}
7372fae26bdSAlan Somers
7382fae26bdSAlan Somers#
7392fae26bdSAlan Somers# This function continues to write to a filenum number of files into dirnum
7402fae26bdSAlan Somers# number of directories until either $FILE_WRITE returns an error or the
7412fae26bdSAlan Somers# maximum number of files per directory have been written.
7422fae26bdSAlan Somers#
7432fae26bdSAlan Somers# Usage:
7442fae26bdSAlan Somers# fill_fs [destdir] [dirnum] [filenum] [bytes] [num_writes] [data]
7452fae26bdSAlan Somers#
7462fae26bdSAlan Somers# Return value: 0 on success
7472fae26bdSAlan Somers#		non 0 on error
7482fae26bdSAlan Somers#
7492fae26bdSAlan Somers# Where :
7502fae26bdSAlan Somers#	destdir:    is the directory where everything is to be created under
7512fae26bdSAlan Somers#	dirnum:	    the maximum number of subdirectories to use, -1 no limit
7522fae26bdSAlan Somers#	filenum:    the maximum number of files per subdirectory
7532fae26bdSAlan Somers#	blocksz:    number of bytes per block
7542fae26bdSAlan Somers#	num_writes: number of blocks to write
7552fae26bdSAlan Somers#	data:	    the data that will be written
7562fae26bdSAlan Somers#
7572fae26bdSAlan Somers#	E.g.
7582fae26bdSAlan Somers#	file_fs /testdir 20 25 1024 256 0
7592fae26bdSAlan Somers#
7602fae26bdSAlan Somers# Note: blocksz * num_writes equals the size of the testfile
7612fae26bdSAlan Somers#
7622fae26bdSAlan Somersfunction fill_fs # destdir dirnum filenum blocksz num_writes data
7632fae26bdSAlan Somers{
7642fae26bdSAlan Somers	typeset destdir=${1:-$TESTDIR}
7652fae26bdSAlan Somers	typeset -i dirnum=${2:-50}
7662fae26bdSAlan Somers	typeset -i filenum=${3:-50}
7672fae26bdSAlan Somers	typeset -i blocksz=${4:-8192}
7682fae26bdSAlan Somers	typeset -i num_writes=${5:-10240}
7692fae26bdSAlan Somers	typeset -i data=${6:-0}
7702fae26bdSAlan Somers
7712fae26bdSAlan Somers	typeset -i retval=0
7722fae26bdSAlan Somers	typeset -i dn=0 # current dir number
7732fae26bdSAlan Somers	typeset -i fn=0 # current file number
7742fae26bdSAlan Somers	while (( retval == 0 )); do
7752fae26bdSAlan Somers		(( dirnum >= 0 && dn >= dirnum )) && break
7762fae26bdSAlan Somers		typeset curdir=$destdir/$dn
7772fae26bdSAlan Somers		log_must $MKDIR -p $curdir
7782fae26bdSAlan Somers		for (( fn = 0; $fn < $filenum && $retval == 0; fn++ )); do
7792fae26bdSAlan Somers			log_cmd $FILE_WRITE -o create -f $curdir/$TESTFILE.$fn \
7802fae26bdSAlan Somers			    -b $blocksz -c $num_writes -d $data
7812fae26bdSAlan Somers			retval=$?
7822fae26bdSAlan Somers		done
7832fae26bdSAlan Somers		(( dn = dn + 1 ))
7842fae26bdSAlan Somers	done
7852fae26bdSAlan Somers	return $retval
7862fae26bdSAlan Somers}
7872fae26bdSAlan Somers
7882fae26bdSAlan Somers#
7892fae26bdSAlan Somers# Simple function to get the specified property. If unable to
7902fae26bdSAlan Somers# get the property then exits.
7912fae26bdSAlan Somers#
7922fae26bdSAlan Somers# Note property is in 'parsable' format (-p)
7932fae26bdSAlan Somers#
7942fae26bdSAlan Somersfunction get_prop # property dataset
7952fae26bdSAlan Somers{
7962fae26bdSAlan Somers	typeset prop_val
7972fae26bdSAlan Somers	typeset prop=$1
7982fae26bdSAlan Somers	typeset dataset=$2
7992fae26bdSAlan Somers
8002fae26bdSAlan Somers	prop_val=$($ZFS get -pH -o value $prop $dataset 2>/dev/null)
8012fae26bdSAlan Somers	if [[ $? -ne 0 ]]; then
8022fae26bdSAlan Somers		log_note "Unable to get $prop property for dataset $dataset"
8032fae26bdSAlan Somers		return 1
8042fae26bdSAlan Somers	fi
8052fae26bdSAlan Somers
8062fae26bdSAlan Somers	$ECHO $prop_val
8072fae26bdSAlan Somers	return 0
8082fae26bdSAlan Somers}
8092fae26bdSAlan Somers
8102fae26bdSAlan Somers#
8112fae26bdSAlan Somers# Simple function to return the lesser of two values.
8122fae26bdSAlan Somers#
8132fae26bdSAlan Somersfunction min
8142fae26bdSAlan Somers{
8152fae26bdSAlan Somers	typeset first_arg=$1
8162fae26bdSAlan Somers	typeset second_arg=$2
8172fae26bdSAlan Somers
8182fae26bdSAlan Somers	if (( first_arg < second_arg )); then
8192fae26bdSAlan Somers		$ECHO $first_arg
8202fae26bdSAlan Somers	else
8212fae26bdSAlan Somers		$ECHO $second_arg
8222fae26bdSAlan Somers	fi
8232fae26bdSAlan Somers	return 0
8242fae26bdSAlan Somers}
8252fae26bdSAlan Somers
8262fae26bdSAlan Somers#
8272fae26bdSAlan Somers# Simple function to get the specified property of pool. If unable to
8282fae26bdSAlan Somers# get the property then exits.
8292fae26bdSAlan Somers#
8302fae26bdSAlan Somersfunction get_pool_prop # property pool
8312fae26bdSAlan Somers{
8322fae26bdSAlan Somers	typeset prop_val
8332fae26bdSAlan Somers	typeset prop=$1
8342fae26bdSAlan Somers	typeset pool=$2
8352fae26bdSAlan Somers
8362fae26bdSAlan Somers	if poolexists $pool ; then
8372fae26bdSAlan Somers		prop_val=$($ZPOOL get $prop $pool 2>/dev/null | $TAIL -1 | \
8382fae26bdSAlan Somers			$AWK '{print $3}')
8392fae26bdSAlan Somers		if [[ $? -ne 0 ]]; then
8402fae26bdSAlan Somers			log_note "Unable to get $prop property for pool " \
8412fae26bdSAlan Somers			"$pool"
8422fae26bdSAlan Somers			return 1
8432fae26bdSAlan Somers		fi
8442fae26bdSAlan Somers	else
8452fae26bdSAlan Somers		log_note "Pool $pool not exists."
8462fae26bdSAlan Somers		return 1
8472fae26bdSAlan Somers	fi
8482fae26bdSAlan Somers
8492fae26bdSAlan Somers	$ECHO $prop_val
8502fae26bdSAlan Somers	return 0
8512fae26bdSAlan Somers}
8522fae26bdSAlan Somers
8532fae26bdSAlan Somers# Return 0 if a pool exists; $? otherwise
8542fae26bdSAlan Somers#
8552fae26bdSAlan Somers# $1 - pool name
8562fae26bdSAlan Somers
8572fae26bdSAlan Somersfunction poolexists
8582fae26bdSAlan Somers{
8592fae26bdSAlan Somers	typeset pool=$1
8602fae26bdSAlan Somers
8612fae26bdSAlan Somers	if [[ -z $pool ]]; then
8622fae26bdSAlan Somers		log_note "No pool name given."
8632fae26bdSAlan Somers		return 1
8642fae26bdSAlan Somers	fi
8652fae26bdSAlan Somers
8662fae26bdSAlan Somers	$ZPOOL list -H "$pool" > /dev/null 2>&1
8672fae26bdSAlan Somers	return $?
8682fae26bdSAlan Somers}
8692fae26bdSAlan Somers
8702fae26bdSAlan Somers# Return 0 if all the specified datasets exist; $? otherwise
8712fae26bdSAlan Somers#
8722fae26bdSAlan Somers# $1-n  dataset name
8732fae26bdSAlan Somersfunction datasetexists
8742fae26bdSAlan Somers{
8752fae26bdSAlan Somers	if (( $# == 0 )); then
8762fae26bdSAlan Somers		log_note "No dataset name given."
8772fae26bdSAlan Somers		return 1
8782fae26bdSAlan Somers	fi
8792fae26bdSAlan Somers
8802fae26bdSAlan Somers	while (( $# > 0 )); do
8812fae26bdSAlan Somers		$ZFS list -H -t filesystem,snapshot,volume $1 > /dev/null 2>&1 || \
8822fae26bdSAlan Somers			return $?
8832fae26bdSAlan Somers		shift
8842fae26bdSAlan Somers	done
8852fae26bdSAlan Somers
8862fae26bdSAlan Somers	return 0
8872fae26bdSAlan Somers}
8882fae26bdSAlan Somers
8892fae26bdSAlan Somers# return 0 if none of the specified datasets exists, otherwise return 1.
8902fae26bdSAlan Somers#
8912fae26bdSAlan Somers# $1-n  dataset name
8922fae26bdSAlan Somersfunction datasetnonexists
8932fae26bdSAlan Somers{
8942fae26bdSAlan Somers	if (( $# == 0 )); then
8952fae26bdSAlan Somers		log_note "No dataset name given."
8962fae26bdSAlan Somers		return 1
8972fae26bdSAlan Somers	fi
8982fae26bdSAlan Somers
8992fae26bdSAlan Somers	while (( $# > 0 )); do
9002fae26bdSAlan Somers		$ZFS list -H -t filesystem,snapshot,volume $1 > /dev/null 2>&1 && \
9012fae26bdSAlan Somers			return 1
9022fae26bdSAlan Somers		shift
9032fae26bdSAlan Somers	done
9042fae26bdSAlan Somers
9052fae26bdSAlan Somers	return 0
9062fae26bdSAlan Somers}
9072fae26bdSAlan Somers
9082fae26bdSAlan Somers#
9092fae26bdSAlan Somers# Given a mountpoint, or a dataset name, determine if it is shared.
9102fae26bdSAlan Somers#
9112fae26bdSAlan Somers# Returns 0 if shared, 1 otherwise.
9122fae26bdSAlan Somers#
9132fae26bdSAlan Somersfunction is_shared
9142fae26bdSAlan Somers{
9152fae26bdSAlan Somers	typeset fs=$1
9162fae26bdSAlan Somers	typeset mtpt
9172fae26bdSAlan Somers
9182fae26bdSAlan Somers	if [[ $fs != "/"* ]] ; then
9192fae26bdSAlan Somers		if datasetnonexists "$fs" ; then
9202fae26bdSAlan Somers			return 1
9212fae26bdSAlan Somers		else
9222fae26bdSAlan Somers			mtpt=$(get_prop mountpoint "$fs")
9232fae26bdSAlan Somers			case $mtpt in
9242fae26bdSAlan Somers				none|legacy|-) return 1
9252fae26bdSAlan Somers					;;
9262fae26bdSAlan Somers				*)	fs=$mtpt
9272fae26bdSAlan Somers					;;
9282fae26bdSAlan Somers			esac
9292fae26bdSAlan Somers		fi
9302fae26bdSAlan Somers	fi
9312fae26bdSAlan Somers
9322fae26bdSAlan Somers	for mtpt in `$SHARE | $AWK '{print $2}'` ; do
9332fae26bdSAlan Somers		if [[ $mtpt == $fs ]] ; then
9342fae26bdSAlan Somers			return 0
9352fae26bdSAlan Somers		fi
9362fae26bdSAlan Somers	done
9372fae26bdSAlan Somers
9382fae26bdSAlan Somers	typeset stat=$($SVCS -H -o STA nfs/server:default)
9392fae26bdSAlan Somers	if [[ $stat != "ON" ]]; then
9402fae26bdSAlan Somers		log_note "Current nfs/server status: $stat"
9412fae26bdSAlan Somers	fi
9422fae26bdSAlan Somers
9432fae26bdSAlan Somers	return 1
9442fae26bdSAlan Somers}
9452fae26bdSAlan Somers
9462fae26bdSAlan Somers#
9472fae26bdSAlan Somers# Given a mountpoint, determine if it is not shared.
9482fae26bdSAlan Somers#
9492fae26bdSAlan Somers# Returns 0 if not shared, 1 otherwise.
9502fae26bdSAlan Somers#
9512fae26bdSAlan Somersfunction not_shared
9522fae26bdSAlan Somers{
9532fae26bdSAlan Somers	typeset fs=$1
9542fae26bdSAlan Somers
9552fae26bdSAlan Somers	is_shared $fs
9562fae26bdSAlan Somers	if (( $? == 0)); then
9572fae26bdSAlan Somers		return 1
9582fae26bdSAlan Somers	fi
9592fae26bdSAlan Somers
9602fae26bdSAlan Somers	return 0
9612fae26bdSAlan Somers}
9622fae26bdSAlan Somers
9632fae26bdSAlan Somers#
9642fae26bdSAlan Somers# Helper function to unshare a mountpoint.
9652fae26bdSAlan Somers#
9662fae26bdSAlan Somersfunction unshare_fs #fs
9672fae26bdSAlan Somers{
9682fae26bdSAlan Somers	typeset fs=$1
9692fae26bdSAlan Somers
9702fae26bdSAlan Somers	is_shared $fs
9712fae26bdSAlan Somers	if (( $? == 0 )); then
9722fae26bdSAlan Somers		log_must $ZFS unshare $fs
9732fae26bdSAlan Somers	fi
9742fae26bdSAlan Somers
9752fae26bdSAlan Somers	return 0
9762fae26bdSAlan Somers}
9772fae26bdSAlan Somers
9782fae26bdSAlan Somers#
9792fae26bdSAlan Somers# Check NFS server status and trigger it online.
9802fae26bdSAlan Somers#
9812fae26bdSAlan Somersfunction setup_nfs_server
9822fae26bdSAlan Somers{
9832fae26bdSAlan Somers	# Cannot share directory in non-global zone.
9842fae26bdSAlan Somers	#
9852fae26bdSAlan Somers	if ! is_global_zone; then
9862fae26bdSAlan Somers		log_note "Cannot trigger NFS server by sharing in LZ."
9872fae26bdSAlan Somers		return
9882fae26bdSAlan Somers	fi
9892fae26bdSAlan Somers
9902fae26bdSAlan Somers	typeset nfs_fmri="svc:/network/nfs/server:default"
9912fae26bdSAlan Somers	if [[ $($SVCS -Ho STA $nfs_fmri) != "ON" ]]; then
9922fae26bdSAlan Somers		#
9932fae26bdSAlan Somers		# Only really sharing operation can enable NFS server
9942fae26bdSAlan Somers		# to online permanently.
9952fae26bdSAlan Somers		#
9962fae26bdSAlan Somers		typeset dummy=$TMPDIR/dummy
9972fae26bdSAlan Somers
9982fae26bdSAlan Somers		if [[ -d $dummy ]]; then
9992fae26bdSAlan Somers			log_must $RM -rf $dummy
10002fae26bdSAlan Somers		fi
10012fae26bdSAlan Somers
10022fae26bdSAlan Somers		log_must $MKDIR $dummy
10032fae26bdSAlan Somers		log_must $SHARE $dummy
10042fae26bdSAlan Somers
10052fae26bdSAlan Somers		#
10062fae26bdSAlan Somers		# Waiting for fmri's status to be the final status.
10072fae26bdSAlan Somers		# Otherwise, in transition, an asterisk (*) is appended for
10082fae26bdSAlan Somers		# instances, unshare will reverse status to 'DIS' again.
10092fae26bdSAlan Somers		#
10102fae26bdSAlan Somers		# Waiting for 1's at least.
10112fae26bdSAlan Somers		#
10122fae26bdSAlan Somers		log_must $SLEEP 1
10132fae26bdSAlan Somers		timeout=10
10142fae26bdSAlan Somers		while [[ timeout -ne 0 && $($SVCS -Ho STA $nfs_fmri) == *'*' ]]
10152fae26bdSAlan Somers		do
10162fae26bdSAlan Somers			log_must $SLEEP 1
10172fae26bdSAlan Somers
10182fae26bdSAlan Somers			(( timeout -= 1 ))
10192fae26bdSAlan Somers		done
10202fae26bdSAlan Somers
10212fae26bdSAlan Somers		log_must $UNSHARE $dummy
10222fae26bdSAlan Somers		log_must $RM -rf $dummy
10232fae26bdSAlan Somers	fi
10242fae26bdSAlan Somers
10252fae26bdSAlan Somers	log_note "Current NFS status: '$($SVCS -Ho STA,FMRI $nfs_fmri)'"
10262fae26bdSAlan Somers}
10272fae26bdSAlan Somers
10282fae26bdSAlan Somers#
10292fae26bdSAlan Somers# To verify whether calling process is in global zone
10302fae26bdSAlan Somers#
10312fae26bdSAlan Somers# Return 0 if in global zone, 1 in non-global zone
10322fae26bdSAlan Somers#
10332fae26bdSAlan Somersfunction is_global_zone
10342fae26bdSAlan Somers{
10352fae26bdSAlan Somers	typeset cur_zone=$($ZONENAME 2>/dev/null)
10362fae26bdSAlan Somers
10372fae26bdSAlan Somers	# Zones are not supported on FreeBSD.
10382fae26bdSAlan Somers	if [[ $os_name == "FreeBSD" ]]; then
10392fae26bdSAlan Somers		return 0
10402fae26bdSAlan Somers	fi
10412fae26bdSAlan Somers
10422fae26bdSAlan Somers	if [[ $cur_zone != "global" ]]; then
10432fae26bdSAlan Somers		return 1
10442fae26bdSAlan Somers	fi
10452fae26bdSAlan Somers	return 0
10462fae26bdSAlan Somers}
10472fae26bdSAlan Somers
10482fae26bdSAlan Somers#
10492fae26bdSAlan Somers# Verify whether test is permit to run from
10502fae26bdSAlan Somers# global zone, local zone, or both
10512fae26bdSAlan Somers#
10522fae26bdSAlan Somers# $1 zone limit, could be "global", "local", or "both"(no limit)
10532fae26bdSAlan Somers#
10542fae26bdSAlan Somers# Return 0 if permit, otherwise exit with log_unsupported
10552fae26bdSAlan Somers#
10562fae26bdSAlan Somersfunction verify_runnable # zone limit
10572fae26bdSAlan Somers{
10582fae26bdSAlan Somers	typeset limit=$1
10592fae26bdSAlan Somers
10602fae26bdSAlan Somers	[[ -z $limit ]] && return 0
10612fae26bdSAlan Somers
10622fae26bdSAlan Somers	if is_global_zone ; then
10632fae26bdSAlan Somers		case $limit in
10642fae26bdSAlan Somers			global|both)
10652fae26bdSAlan Somers				break
10662fae26bdSAlan Somers				;;
10672fae26bdSAlan Somers			local)  log_unsupported "Test is unable to run from \
10682fae26bdSAlan Somers					global zone."
10692fae26bdSAlan Somers				break
10702fae26bdSAlan Somers				;;
10712fae26bdSAlan Somers			*)      log_note "Warning: unknown limit $limit - use both."
10722fae26bdSAlan Somers				;;
10732fae26bdSAlan Somers		esac
10742fae26bdSAlan Somers	else
10752fae26bdSAlan Somers		case $limit in
10762fae26bdSAlan Somers			local|both)
10772fae26bdSAlan Somers				break
10782fae26bdSAlan Somers				;;
10792fae26bdSAlan Somers			global) log_unsupported "Test is unable to run from \
10802fae26bdSAlan Somers					local zone."
10812fae26bdSAlan Somers				break
10822fae26bdSAlan Somers				;;
10832fae26bdSAlan Somers			*)      log_note "Warning: unknown limit $limit - use both."
10842fae26bdSAlan Somers				;;
10852fae26bdSAlan Somers		esac
10862fae26bdSAlan Somers
10872fae26bdSAlan Somers		reexport_pool
10882fae26bdSAlan Somers	fi
10892fae26bdSAlan Somers
10902fae26bdSAlan Somers	return 0
10912fae26bdSAlan Somers}
10922fae26bdSAlan Somers
10932fae26bdSAlan Somers# Return 0 if create successfully or the pool exists; $? otherwise
10942fae26bdSAlan Somers# Note: In local zones, this function should return 0 silently.
10952fae26bdSAlan Somers#
10962fae26bdSAlan Somers# $1 - pool name
10972fae26bdSAlan Somers# $2-n - [keyword] devs_list
10982fae26bdSAlan Somers
10992fae26bdSAlan Somersfunction create_pool #pool devs_list
11002fae26bdSAlan Somers{
11012fae26bdSAlan Somers	typeset pool=${1%%/*}
11022fae26bdSAlan Somers
11032fae26bdSAlan Somers	shift
11042fae26bdSAlan Somers
11052fae26bdSAlan Somers	if [[ -z $pool ]]; then
11062fae26bdSAlan Somers		log_note "Missing pool name."
11072fae26bdSAlan Somers		return 1
11082fae26bdSAlan Somers	fi
11092fae26bdSAlan Somers
11102fae26bdSAlan Somers	if poolexists $pool ; then
11112fae26bdSAlan Somers		destroy_pool $pool
11122fae26bdSAlan Somers	fi
11132fae26bdSAlan Somers
11142fae26bdSAlan Somers	if is_global_zone ; then
11152fae26bdSAlan Somers		[[ -d /$pool ]] && $RM -rf /$pool
11162fae26bdSAlan Somers		log_must $ZPOOL create -f $pool $@
11172fae26bdSAlan Somers	fi
11182fae26bdSAlan Somers
11192fae26bdSAlan Somers	return 0
11202fae26bdSAlan Somers}
11212fae26bdSAlan Somers
11222fae26bdSAlan Somers# Return 0 if destroy successfully or the pool exists; $? otherwise
11232fae26bdSAlan Somers# Note: In local zones, this function should return 0 silently.
11242fae26bdSAlan Somers#
11252fae26bdSAlan Somers# $1 - pool name
11262fae26bdSAlan Somers# Destroy pool with the given parameters.
11272fae26bdSAlan Somers
11282fae26bdSAlan Somersfunction destroy_pool #pool
11292fae26bdSAlan Somers{
11302fae26bdSAlan Somers	typeset pool=${1%%/*}
11312fae26bdSAlan Somers	typeset mtpt
11322fae26bdSAlan Somers
11332fae26bdSAlan Somers	if [[ -z $pool ]]; then
11342fae26bdSAlan Somers		log_note "No pool name given."
11352fae26bdSAlan Somers		return 1
11362fae26bdSAlan Somers	fi
11372fae26bdSAlan Somers
11382fae26bdSAlan Somers	if is_global_zone ; then
11392fae26bdSAlan Somers		if poolexists "$pool" ; then
11402fae26bdSAlan Somers			mtpt=$(get_prop mountpoint "$pool")
11412fae26bdSAlan Somers			log_must $ZPOOL destroy -f $pool
11422fae26bdSAlan Somers
11432fae26bdSAlan Somers			[[ -d $mtpt ]] && \
11442fae26bdSAlan Somers				log_must $RM -rf $mtpt
11452fae26bdSAlan Somers		else
11462fae26bdSAlan Somers			log_note "Pool $pool does not exist, skipping destroy."
11472fae26bdSAlan Somers			return 1
11482fae26bdSAlan Somers		fi
11492fae26bdSAlan Somers	fi
11502fae26bdSAlan Somers
11512fae26bdSAlan Somers	return 0
11522fae26bdSAlan Somers}
11532fae26bdSAlan Somers
11542fae26bdSAlan Somers#
11552fae26bdSAlan Somers# Create file vdevs.
11562fae26bdSAlan Somers# By default this generates sparse vdevs 10GB in size, for performance.
11572fae26bdSAlan Somers#
11582fae26bdSAlan Somersfunction create_vdevs # vdevs
11592fae26bdSAlan Somers{
11602fae26bdSAlan Somers	typeset vdsize=10G
11612fae26bdSAlan Somers
11622fae26bdSAlan Somers	[ -n "$VDEV_SIZE" ] && vdsize=$VDEV_SIZE
11632fae26bdSAlan Somers	rm -f $@ || return 1
11642fae26bdSAlan Somers	truncate -s $vdsize $@
11652fae26bdSAlan Somers}
11662fae26bdSAlan Somers
11672fae26bdSAlan Somers#
11682fae26bdSAlan Somers# Firstly, create a pool with 5 datasets. Then, create a single zone and
11692fae26bdSAlan Somers# export the 5 datasets to it. In addition, we also add a ZFS filesystem
11702fae26bdSAlan Somers# and a zvol device to the zone.
11712fae26bdSAlan Somers#
11722fae26bdSAlan Somers# $1 zone name
11732fae26bdSAlan Somers# $2 zone root directory prefix
11742fae26bdSAlan Somers# $3 zone ip
11752fae26bdSAlan Somers#
11762fae26bdSAlan Somersfunction zfs_zones_setup #zone_name zone_root zone_ip
11772fae26bdSAlan Somers{
11782fae26bdSAlan Somers	typeset zone_name=${1:-$(hostname)-z}
11792fae26bdSAlan Somers	typeset zone_root=${2:-"/zone_root"}
11802fae26bdSAlan Somers	typeset zone_ip=${3:-"10.1.1.10"}
11812fae26bdSAlan Somers	typeset prefix_ctr=$ZONE_CTR
11822fae26bdSAlan Somers	typeset pool_name=$ZONE_POOL
11832fae26bdSAlan Somers	typeset -i cntctr=5
11842fae26bdSAlan Somers	typeset -i i=0
11852fae26bdSAlan Somers
11862fae26bdSAlan Somers	# Create pool and 5 container within it
11872fae26bdSAlan Somers	#
11882fae26bdSAlan Somers	[[ -d /$pool_name ]] && $RM -rf /$pool_name
11892fae26bdSAlan Somers	log_must $ZPOOL create -f $pool_name $DISKS
11902fae26bdSAlan Somers	while (( i < cntctr )); do
11912fae26bdSAlan Somers		log_must $ZFS create $pool_name/$prefix_ctr$i
11922fae26bdSAlan Somers		(( i += 1 ))
11932fae26bdSAlan Somers	done
11942fae26bdSAlan Somers
11952fae26bdSAlan Somers	# create a zvol
11962fae26bdSAlan Somers	log_must $ZFS create -V 1g $pool_name/zone_zvol
11972fae26bdSAlan Somers
11982fae26bdSAlan Somers	#
11992fae26bdSAlan Somers	# If current system support slog, add slog device for pool
12002fae26bdSAlan Somers	#
12012fae26bdSAlan Somers	typeset sdevs="$TMPDIR/sdev1 $TMPDIR/sdev2"
12022fae26bdSAlan Somers	log_must create_vdevs $sdevs
12032fae26bdSAlan Somers	log_must $ZPOOL add $pool_name log mirror $sdevs
12042fae26bdSAlan Somers
12052fae26bdSAlan Somers	# this isn't supported just yet.
12062fae26bdSAlan Somers	# Create a filesystem. In order to add this to
12072fae26bdSAlan Somers	# the zone, it must have it's mountpoint set to 'legacy'
12082fae26bdSAlan Somers	# log_must $ZFS create $pool_name/zfs_filesystem
12092fae26bdSAlan Somers	# log_must $ZFS set mountpoint=legacy $pool_name/zfs_filesystem
12102fae26bdSAlan Somers
12112fae26bdSAlan Somers	[[ -d $zone_root ]] && \
12122fae26bdSAlan Somers		log_must $RM -rf $zone_root/$zone_name
12132fae26bdSAlan Somers	[[ ! -d $zone_root ]] && \
12142fae26bdSAlan Somers		log_must $MKDIR -p -m 0700 $zone_root/$zone_name
12152fae26bdSAlan Somers
12162fae26bdSAlan Somers	# Create zone configure file and configure the zone
12172fae26bdSAlan Somers	#
12182fae26bdSAlan Somers	typeset zone_conf=$TMPDIR/zone_conf.${TESTCASE_ID}
12192fae26bdSAlan Somers	$ECHO "create" > $zone_conf
12202fae26bdSAlan Somers	$ECHO "set zonepath=$zone_root/$zone_name" >> $zone_conf
12212fae26bdSAlan Somers	$ECHO "set autoboot=true" >> $zone_conf
12222fae26bdSAlan Somers	i=0
12232fae26bdSAlan Somers	while (( i < cntctr )); do
12242fae26bdSAlan Somers		$ECHO "add dataset" >> $zone_conf
12252fae26bdSAlan Somers		$ECHO "set name=$pool_name/$prefix_ctr$i" >> \
12262fae26bdSAlan Somers			$zone_conf
12272fae26bdSAlan Somers		$ECHO "end" >> $zone_conf
12282fae26bdSAlan Somers		(( i += 1 ))
12292fae26bdSAlan Somers	done
12302fae26bdSAlan Somers
12312fae26bdSAlan Somers	# add our zvol to the zone
12322fae26bdSAlan Somers	$ECHO "add device" >> $zone_conf
12335a2fc464SAndriy Gapon	$ECHO "set match=/dev/zvol/$pool_name/zone_zvol" >> $zone_conf
12342fae26bdSAlan Somers	$ECHO "end" >> $zone_conf
12352fae26bdSAlan Somers
12365a2fc464SAndriy Gapon	# add a corresponding zvol to the zone
12372fae26bdSAlan Somers	$ECHO "add device" >> $zone_conf
12385a2fc464SAndriy Gapon	$ECHO "set match=/dev/zvol/$pool_name/zone_zvol" >> $zone_conf
12392fae26bdSAlan Somers	$ECHO "end" >> $zone_conf
12402fae26bdSAlan Somers
12412fae26bdSAlan Somers	# once it's supported, we'll add our filesystem to the zone
12422fae26bdSAlan Somers	# $ECHO "add fs" >> $zone_conf
12432fae26bdSAlan Somers	# $ECHO "set type=zfs" >> $zone_conf
12442fae26bdSAlan Somers	# $ECHO "set special=$pool_name/zfs_filesystem" >> $zone_conf
12452fae26bdSAlan Somers	# $ECHO "set dir=/export/zfs_filesystem" >> $zone_conf
12462fae26bdSAlan Somers	# $ECHO "end" >> $zone_conf
12472fae26bdSAlan Somers
12482fae26bdSAlan Somers	$ECHO "verify" >> $zone_conf
12492fae26bdSAlan Somers	$ECHO "commit" >> $zone_conf
12502fae26bdSAlan Somers	log_must $ZONECFG -z $zone_name -f $zone_conf
12512fae26bdSAlan Somers	log_must $RM -f $zone_conf
12522fae26bdSAlan Somers
12532fae26bdSAlan Somers	# Install the zone
12542fae26bdSAlan Somers	$ZONEADM -z $zone_name install
12552fae26bdSAlan Somers	if (( $? == 0 )); then
12562fae26bdSAlan Somers		log_note "SUCCESS: $ZONEADM -z $zone_name install"
12572fae26bdSAlan Somers	else
12582fae26bdSAlan Somers		log_fail "FAIL: $ZONEADM -z $zone_name install"
12592fae26bdSAlan Somers	fi
12602fae26bdSAlan Somers
12612fae26bdSAlan Somers	# Install sysidcfg file
12622fae26bdSAlan Somers	#
12632fae26bdSAlan Somers	typeset sysidcfg=$zone_root/$zone_name/root/etc/sysidcfg
12642fae26bdSAlan Somers  	$ECHO "system_locale=C" > $sysidcfg
12652fae26bdSAlan Somers  	$ECHO  "terminal=dtterm" >> $sysidcfg
12662fae26bdSAlan Somers  	$ECHO  "network_interface=primary {" >> $sysidcfg
12672fae26bdSAlan Somers  	$ECHO  "hostname=$zone_name" >> $sysidcfg
12682fae26bdSAlan Somers  	$ECHO  "}" >> $sysidcfg
12692fae26bdSAlan Somers  	$ECHO  "name_service=NONE" >> $sysidcfg
12702fae26bdSAlan Somers  	$ECHO  "root_password=mo791xfZ/SFiw" >> $sysidcfg
12712fae26bdSAlan Somers  	$ECHO  "security_policy=NONE" >> $sysidcfg
12722fae26bdSAlan Somers  	$ECHO  "timezone=US/Eastern" >> $sysidcfg
12732fae26bdSAlan Somers
12742fae26bdSAlan Somers	# Boot this zone
12752fae26bdSAlan Somers	log_must $ZONEADM -z $zone_name boot
12762fae26bdSAlan Somers}
12772fae26bdSAlan Somers
12782fae26bdSAlan Somers#
12792fae26bdSAlan Somers# Reexport TESTPOOL & TESTPOOL(1-4)
12802fae26bdSAlan Somers#
12812fae26bdSAlan Somersfunction reexport_pool
12822fae26bdSAlan Somers{
12832fae26bdSAlan Somers	typeset -i cntctr=5
12842fae26bdSAlan Somers	typeset -i i=0
12852fae26bdSAlan Somers
12862fae26bdSAlan Somers	while (( i < cntctr )); do
12872fae26bdSAlan Somers		if (( i == 0 )); then
12882fae26bdSAlan Somers			TESTPOOL=$ZONE_POOL/$ZONE_CTR$i
12892fae26bdSAlan Somers			if ! ismounted $TESTPOOL; then
12902fae26bdSAlan Somers				log_must $ZFS mount $TESTPOOL
12912fae26bdSAlan Somers			fi
12922fae26bdSAlan Somers		else
12932fae26bdSAlan Somers			eval TESTPOOL$i=$ZONE_POOL/$ZONE_CTR$i
12942fae26bdSAlan Somers			if eval ! ismounted \$TESTPOOL$i; then
12952fae26bdSAlan Somers				log_must eval $ZFS mount \$TESTPOOL$i
12962fae26bdSAlan Somers			fi
12972fae26bdSAlan Somers		fi
12982fae26bdSAlan Somers		(( i += 1 ))
12992fae26bdSAlan Somers	done
13002fae26bdSAlan Somers}
13012fae26bdSAlan Somers
13022fae26bdSAlan Somers#
13032fae26bdSAlan Somers# Wait for something to return true, checked by the caller.
13042fae26bdSAlan Somers#
13052fae26bdSAlan Somersfunction wait_for_checked # timeout dt <method> [args...]
13062fae26bdSAlan Somers{
13072fae26bdSAlan Somers	typeset timeout=$1
13082fae26bdSAlan Somers	typeset dt=$2
13092fae26bdSAlan Somers	shift; shift
13102fae26bdSAlan Somers	typeset -i start=$(date '+%s')
13112fae26bdSAlan Somers	typeset -i endtime
13122fae26bdSAlan Somers
13132fae26bdSAlan Somers	log_note "Waiting $timeout seconds (checked every $dt seconds) for: $*"
13142fae26bdSAlan Somers	((endtime = start + timeout))
13152fae26bdSAlan Somers	while :; do
13162fae26bdSAlan Somers		$*
13172fae26bdSAlan Somers		[ $? -eq 0 ] && return
13182fae26bdSAlan Somers		curtime=$(date '+%s')
13192fae26bdSAlan Somers		[ $curtime -gt $endtime ] && return 1
13202fae26bdSAlan Somers		sleep $dt
13212fae26bdSAlan Somers	done
13222fae26bdSAlan Somers	return 0
13232fae26bdSAlan Somers}
13242fae26bdSAlan Somers
13252fae26bdSAlan Somers#
13262fae26bdSAlan Somers# Wait for something to return true.
13272fae26bdSAlan Somers#
13282fae26bdSAlan Somersfunction wait_for # timeout dt <method> [args...]
13292fae26bdSAlan Somers{
13302fae26bdSAlan Somers	typeset timeout=$1
13312fae26bdSAlan Somers	typeset dt=$2
13322fae26bdSAlan Somers	shift; shift
13332fae26bdSAlan Somers
13342fae26bdSAlan Somers	wait_for_checked $timeout $dt $* || \
13352fae26bdSAlan Somers		log_fail "ERROR: Timed out waiting for: $*"
13362fae26bdSAlan Somers}
13372fae26bdSAlan Somers
13382fae26bdSAlan Somers#
13392fae26bdSAlan Somers# Verify a given disk is online or offline
13402fae26bdSAlan Somers#
13412fae26bdSAlan Somers# Return 0 is pool/disk matches expected state, 1 otherwise
13422fae26bdSAlan Somers# stateexpr is a regex like ONLINE or REMOVED|UNAVAIL
13432fae26bdSAlan Somers#
13442fae26bdSAlan Somersfunction check_state # pool disk stateexpr
13452fae26bdSAlan Somers{
13462fae26bdSAlan Somers	typeset pool=$1
13475a2fc464SAndriy Gapon	typeset disk=${2#/dev/}
13485a2fc464SAndriy Gapon	disk=${disk#/dev/}
13492fae26bdSAlan Somers	disk=${disk#/dev/}
13502fae26bdSAlan Somers	typeset stateexpr=$3
13512fae26bdSAlan Somers
13522fae26bdSAlan Somers	$ZPOOL status -v $pool | grep "$disk"  \
13532fae26bdSAlan Somers	    | egrep -i "$stateexpr" > /dev/null 2>&1
13542fae26bdSAlan Somers
13552fae26bdSAlan Somers	return $?
13562fae26bdSAlan Somers}
13572fae26bdSAlan Somers
13582fae26bdSAlan Somers#
13592fae26bdSAlan Somers# Wait for a given disk to leave a state
13602fae26bdSAlan Somers#
13612fae26bdSAlan Somersfunction wait_for_state_exit
13622fae26bdSAlan Somers{
13632fae26bdSAlan Somers	typeset pool=$1
13642fae26bdSAlan Somers	typeset disk=$2
13652fae26bdSAlan Somers	typeset state=$3
13662fae26bdSAlan Somers
13672fae26bdSAlan Somers	while check_state "$pool" "$disk" "$state"; do
13682fae26bdSAlan Somers		$SLEEP 1
13692fae26bdSAlan Somers	done
13702fae26bdSAlan Somers}
13712fae26bdSAlan Somers
13722fae26bdSAlan Somers#
13732fae26bdSAlan Somers# Wait for a given disk to enter a state
13742fae26bdSAlan Somers#
13752fae26bdSAlan Somersfunction wait_for_state_enter
13762fae26bdSAlan Somers{
13772fae26bdSAlan Somers	typeset -i timeout=$1
13782fae26bdSAlan Somers	typeset pool=$2
13792fae26bdSAlan Somers	typeset disk=$3
13802fae26bdSAlan Somers	typeset state=$4
13812fae26bdSAlan Somers
13822fae26bdSAlan Somers	log_note "Waiting up to $timeout seconds for $disk to become $state ..."
13832fae26bdSAlan Somers	for ((; $timeout > 0; timeout=$timeout-1)); do
13842fae26bdSAlan Somers		check_state $pool "$disk" "$state"
13852fae26bdSAlan Somers		[ $? -eq 0 ] && return
13862fae26bdSAlan Somers		$SLEEP 1
13872fae26bdSAlan Somers	done
13882fae26bdSAlan Somers	log_must $ZPOOL status $pool
13892fae26bdSAlan Somers	log_fail "ERROR: Disk $disk not marked as $state in $pool"
13902fae26bdSAlan Somers}
13912fae26bdSAlan Somers
13922fae26bdSAlan Somers#
13932fae26bdSAlan Somers# Get the mountpoint of snapshot
13942fae26bdSAlan Somers# as its mountpoint
13952fae26bdSAlan Somers#
13962fae26bdSAlan Somersfunction snapshot_mountpoint
13972fae26bdSAlan Somers{
13982fae26bdSAlan Somers	typeset dataset=${1:-$TESTPOOL/$TESTFS@$TESTSNAP}
13992fae26bdSAlan Somers
14002fae26bdSAlan Somers	if [[ $dataset != *@* ]]; then
14012fae26bdSAlan Somers		log_fail "Error name of snapshot '$dataset'."
14022fae26bdSAlan Somers	fi
14032fae26bdSAlan Somers
14042fae26bdSAlan Somers	typeset fs=${dataset%@*}
14052fae26bdSAlan Somers	typeset snap=${dataset#*@}
14062fae26bdSAlan Somers
14072fae26bdSAlan Somers	if [[ -z $fs || -z $snap ]]; then
14082fae26bdSAlan Somers		log_fail "Error name of snapshot '$dataset'."
14092fae26bdSAlan Somers	fi
14102fae26bdSAlan Somers
14112fae26bdSAlan Somers	$ECHO $(get_prop mountpoint $fs)/$(get_snapdir_name)/$snap
14122fae26bdSAlan Somers}
14132fae26bdSAlan Somers
14142fae26bdSAlan Somersfunction pool_maps_intact # pool
14152fae26bdSAlan Somers{
14162fae26bdSAlan Somers	typeset pool="$1"
14172fae26bdSAlan Somers
14182fae26bdSAlan Somers	if ! $ZDB -bcv $pool; then
14192fae26bdSAlan Somers		return 1
14202fae26bdSAlan Somers	fi
14212fae26bdSAlan Somers	return 0
14222fae26bdSAlan Somers}
14232fae26bdSAlan Somers
14242fae26bdSAlan Somersfunction filesys_has_zil # filesystem
14252fae26bdSAlan Somers{
14262fae26bdSAlan Somers	typeset filesys="$1"
14272fae26bdSAlan Somers
14282fae26bdSAlan Somers	if ! $ZDB -ivv $filesys | $GREP "ZIL header"; then
14292fae26bdSAlan Somers		return 1
14302fae26bdSAlan Somers	fi
14312fae26bdSAlan Somers	return 0
14322fae26bdSAlan Somers}
14332fae26bdSAlan Somers
14342fae26bdSAlan Somers#
14352fae26bdSAlan Somers# Given a pool and file system, this function will verify the file system
14362fae26bdSAlan Somers# using the zdb internal tool. Note that the pool is exported and imported
14372fae26bdSAlan Somers# to ensure it has consistent state.
14382fae26bdSAlan Somers#
14392fae26bdSAlan Somersfunction verify_filesys # pool filesystem dir
14402fae26bdSAlan Somers{
14412fae26bdSAlan Somers	typeset pool="$1"
14422fae26bdSAlan Somers	typeset filesys="$2"
14432fae26bdSAlan Somers	typeset zdbout="$TMPDIR/zdbout.${TESTCASE_ID}"
14442fae26bdSAlan Somers
14452fae26bdSAlan Somers	shift
14462fae26bdSAlan Somers	shift
14472fae26bdSAlan Somers	typeset dirs=$@
14482fae26bdSAlan Somers	typeset search_path=""
14492fae26bdSAlan Somers
14502fae26bdSAlan Somers	log_note "Calling $ZDB to verify filesystem '$filesys'"
14512fae26bdSAlan Somers	log_must $ZPOOL export $pool
14522fae26bdSAlan Somers
14532fae26bdSAlan Somers	if [[ -n $dirs ]] ; then
14542fae26bdSAlan Somers		for dir in $dirs ; do
14552fae26bdSAlan Somers			search_path="$search_path -d $dir"
14562fae26bdSAlan Somers		done
14572fae26bdSAlan Somers	fi
14582fae26bdSAlan Somers
14592fae26bdSAlan Somers	log_must $ZPOOL import $search_path $pool
14602fae26bdSAlan Somers
14612fae26bdSAlan Somers	$ZDB -cudi $filesys > $zdbout 2>&1
14622fae26bdSAlan Somers	if [[ $? != 0 ]]; then
14632fae26bdSAlan Somers		log_note "Output: $ZDB -cudi $filesys"
14642fae26bdSAlan Somers		$CAT $zdbout
14652fae26bdSAlan Somers		log_fail "$ZDB detected errors with: '$filesys'"
14662fae26bdSAlan Somers	fi
14672fae26bdSAlan Somers
14682fae26bdSAlan Somers	log_must $RM -rf $zdbout
14692fae26bdSAlan Somers}
14702fae26bdSAlan Somers
14712fae26bdSAlan Somers#
14722fae26bdSAlan Somers# Given a pool, and this function list all disks in the pool
14732fae26bdSAlan Somers#
14742fae26bdSAlan Somersfunction get_disklist # pool
14752fae26bdSAlan Somers{
14762fae26bdSAlan Somers	typeset disklist=""
14772fae26bdSAlan Somers
14782fae26bdSAlan Somers	disklist=$($ZPOOL iostat -v $1 | $NAWK '(NR >4 ) {print $1}' | \
14792fae26bdSAlan Somers 		$GREP -v "\-\-\-\-\-" | \
14802fae26bdSAlan Somers		$EGREP -v -e "^(mirror|raidz1|raidz2|spare|log|cache)$" )
14812fae26bdSAlan Somers
14822fae26bdSAlan Somers	$ECHO $disklist
14832fae26bdSAlan Somers}
14842fae26bdSAlan Somers
14852fae26bdSAlan Somers#
14862fae26bdSAlan Somers# Destroy all existing metadevices and state database
14872fae26bdSAlan Somers#
14882fae26bdSAlan Somersfunction destroy_metas
14892fae26bdSAlan Somers{
14902fae26bdSAlan Somers	typeset metad
14912fae26bdSAlan Somers
14922fae26bdSAlan Somers	for metad in $($METASTAT -p | $AWK '{print $1}'); do
14932fae26bdSAlan Somers		log_must $METACLEAR -rf $metad
14942fae26bdSAlan Somers	done
14952fae26bdSAlan Somers
14962fae26bdSAlan Somers	for metad in $($METADB | $CUT -f6 | $GREP dev | $UNIQ); do
14972fae26bdSAlan Somers		log_must $METADB -fd $metad
14982fae26bdSAlan Somers	done
14992fae26bdSAlan Somers}
15002fae26bdSAlan Somers
15012fae26bdSAlan Somers# /**
15022fae26bdSAlan Somers#  This function kills a given list of processes after a time period. We use
15032fae26bdSAlan Somers#  this in the stress tests instead of STF_TIMEOUT so that we can have processes
15042fae26bdSAlan Somers#  run for a fixed amount of time, yet still pass. Tests that hit STF_TIMEOUT
15052fae26bdSAlan Somers#  would be listed as FAIL, which we don't want : we're happy with stress tests
15062fae26bdSAlan Somers#  running for a certain amount of time, then finishing.
15072fae26bdSAlan Somers#
15082fae26bdSAlan Somers# @param $1 the time in seconds after which we should terminate these processes
15092fae26bdSAlan Somers# @param $2..$n the processes we wish to terminate.
15102fae26bdSAlan Somers# */
15112fae26bdSAlan Somersfunction stress_timeout
15122fae26bdSAlan Somers{
15132fae26bdSAlan Somers	typeset -i TIMEOUT=$1
15142fae26bdSAlan Somers	shift
15152fae26bdSAlan Somers	typeset cpids="$@"
15162fae26bdSAlan Somers
15172fae26bdSAlan Somers	log_note "Waiting for child processes($cpids). " \
15182fae26bdSAlan Somers		"It could last dozens of minutes, please be patient ..."
15192fae26bdSAlan Somers	log_must $SLEEP $TIMEOUT
15202fae26bdSAlan Somers
15212fae26bdSAlan Somers	log_note "Killing child processes after ${TIMEOUT} stress timeout."
15222fae26bdSAlan Somers	typeset pid
15232fae26bdSAlan Somers	for pid in $cpids; do
15242fae26bdSAlan Somers		$PS -p $pid > /dev/null 2>&1
15252fae26bdSAlan Somers		if (( $? == 0 )); then
15262fae26bdSAlan Somers			log_must $KILL -USR1 $pid
15272fae26bdSAlan Somers		fi
15282fae26bdSAlan Somers	done
15292fae26bdSAlan Somers}
15302fae26bdSAlan Somers
15312fae26bdSAlan Somers#
15322fae26bdSAlan Somers# Check whether current OS support a specified feature or not
15332fae26bdSAlan Somers#
15342fae26bdSAlan Somers# return 0 if current OS version is in unsupported list, 1 otherwise
15352fae26bdSAlan Somers#
15362fae26bdSAlan Somers# $1 unsupported target OS versions
15372fae26bdSAlan Somers#
15382fae26bdSAlan Somersfunction check_version # <OS version>
15392fae26bdSAlan Somers{
15402fae26bdSAlan Somers	typeset unsupported_vers="$@"
15412fae26bdSAlan Somers	typeset ver
15422fae26bdSAlan Somers	typeset cur_ver=`$UNAME -r`
15432fae26bdSAlan Somers
15442fae26bdSAlan Somers	for ver in $unsupported_vers; do
15452fae26bdSAlan Somers		[[ "$cur_ver" == "$ver" ]] && return 0
15462fae26bdSAlan Somers	done
15472fae26bdSAlan Somers
15482fae26bdSAlan Somers	return 1
15492fae26bdSAlan Somers}
15502fae26bdSAlan Somers
15512fae26bdSAlan Somers#
15522fae26bdSAlan Somers# Verify a given hotspare disk is inuse or avail
15532fae26bdSAlan Somers#
15542fae26bdSAlan Somers# Return 0 is pool/disk matches expected state, 1 otherwise
15552fae26bdSAlan Somers#
15562fae26bdSAlan Somersfunction check_hotspare_state # pool disk state{inuse,avail}
15572fae26bdSAlan Somers{
15582fae26bdSAlan Somers	typeset pool=$1
15595a2fc464SAndriy Gapon	typeset disk=${2#/dev/}
15605a2fc464SAndriy Gapon	disk=${disk#/dev/}
15612fae26bdSAlan Somers	disk=${disk#/dev/}
15622fae26bdSAlan Somers	typeset state=$3
15632fae26bdSAlan Somers
15642fae26bdSAlan Somers	cur_state=$(get_device_state $pool $disk "spares")
15652fae26bdSAlan Somers
15662fae26bdSAlan Somers	if [[ $state != ${cur_state} ]]; then
15672fae26bdSAlan Somers		return 1
15682fae26bdSAlan Somers	fi
15692fae26bdSAlan Somers	return 0
15702fae26bdSAlan Somers}
15712fae26bdSAlan Somers
15722fae26bdSAlan Somers#
15732fae26bdSAlan Somers# Verify a given slog disk is inuse or avail
15742fae26bdSAlan Somers#
15752fae26bdSAlan Somers# Return 0 is pool/disk matches expected state, 1 otherwise
15762fae26bdSAlan Somers#
15772fae26bdSAlan Somersfunction check_slog_state # pool disk state{online,offline,unavail}
15782fae26bdSAlan Somers{
15792fae26bdSAlan Somers	typeset pool=$1
15805a2fc464SAndriy Gapon	typeset disk=${2#/dev/}
15815a2fc464SAndriy Gapon	disk=${disk#/dev/}
15822fae26bdSAlan Somers	disk=${disk#/dev/}
15832fae26bdSAlan Somers	typeset state=$3
15842fae26bdSAlan Somers
15852fae26bdSAlan Somers	cur_state=$(get_device_state $pool $disk "logs")
15862fae26bdSAlan Somers
15872fae26bdSAlan Somers	if [[ $state != ${cur_state} ]]; then
15882fae26bdSAlan Somers		return 1
15892fae26bdSAlan Somers	fi
15902fae26bdSAlan Somers	return 0
15912fae26bdSAlan Somers}
15922fae26bdSAlan Somers
15932fae26bdSAlan Somers#
15942fae26bdSAlan Somers# Verify a given vdev disk is inuse or avail
15952fae26bdSAlan Somers#
15962fae26bdSAlan Somers# Return 0 is pool/disk matches expected state, 1 otherwise
15972fae26bdSAlan Somers#
15982fae26bdSAlan Somersfunction check_vdev_state # pool disk state{online,offline,unavail}
15992fae26bdSAlan Somers{
16002fae26bdSAlan Somers	typeset pool=$1
16015a2fc464SAndriy Gapon	typeset disk=${2#/dev/}
16025a2fc464SAndriy Gapon	disk=${disk#/dev/}
16032fae26bdSAlan Somers	disk=${disk#/dev/}
16042fae26bdSAlan Somers	typeset state=$3
16052fae26bdSAlan Somers
16062fae26bdSAlan Somers	if [[ $WRAPPER == *"smi"* ]]; then
16072fae26bdSAlan Somers		$ECHO $disk | $EGREP "^c[0-F]+([td][0-F]+)+$" > /dev/null 2>&1
16082fae26bdSAlan Somers		if (( $? == 0 )); then
16092fae26bdSAlan Somers			disk=${disk}s2
16102fae26bdSAlan Somers		fi
16112fae26bdSAlan Somers	fi
16122fae26bdSAlan Somers
16132fae26bdSAlan Somers	cur_state=$(get_device_state $pool $disk)
16142fae26bdSAlan Somers
16152fae26bdSAlan Somers	if [[ $state != ${cur_state} ]]; then
16162fae26bdSAlan Somers		return 1
16172fae26bdSAlan Somers	fi
16182fae26bdSAlan Somers	return 0
16192fae26bdSAlan Somers}
16202fae26bdSAlan Somers
16212fae26bdSAlan Somers#
16222fae26bdSAlan Somers# Check the output of 'zpool status -v <pool>',
16232fae26bdSAlan Somers# and to see if the content of <token> contain the <keyword> specified.
16242fae26bdSAlan Somers#
16252fae26bdSAlan Somers# Return 0 is contain, 1 otherwise
16262fae26bdSAlan Somers#
16272fae26bdSAlan Somersfunction check_pool_status # pool token keyword
16282fae26bdSAlan Somers{
16292fae26bdSAlan Somers	typeset pool=$1
16302fae26bdSAlan Somers	typeset token=$2
16312fae26bdSAlan Somers	typeset keyword=$3
16322fae26bdSAlan Somers
16332fae26bdSAlan Somers	$ZPOOL status -v "$pool" 2>/dev/null | \
16342fae26bdSAlan Somers		$NAWK -v token="$token:" '($1==token) {print $0}' | \
16352fae26bdSAlan Somers		$GREP -i "$keyword" >/dev/null 2>&1
16362fae26bdSAlan Somers
16372fae26bdSAlan Somers	return $?
16382fae26bdSAlan Somers}
16392fae26bdSAlan Somers
16402fae26bdSAlan Somersfunction vdev_pool_error_count
16412fae26bdSAlan Somers{
16422fae26bdSAlan Somers	typeset errs=$1
16432fae26bdSAlan Somers	if [ -z "$2" ]; then
16442fae26bdSAlan Somers		test $errs -gt 0; ret=$?
16452fae26bdSAlan Somers	else
16462fae26bdSAlan Somers		test $errs -eq $2; ret=$?
16472fae26bdSAlan Somers	fi
16482fae26bdSAlan Somers	log_debug "vdev_pool_error_count: errs='$errs' \$2='$2' ret='$ret'"
16492fae26bdSAlan Somers	return $ret
16502fae26bdSAlan Somers}
16512fae26bdSAlan Somers
16522fae26bdSAlan Somers#
16532fae26bdSAlan Somers# Generate a pool status error file suitable for pool_errors_from_file.
16542fae26bdSAlan Somers# If the pool is healthy, returns 0.  Otherwise, the caller must handle the
16552fae26bdSAlan Somers# returned temporarily file appropriately.
16562fae26bdSAlan Somers#
16572fae26bdSAlan Somersfunction pool_error_file # <pool>
16582fae26bdSAlan Somers{
16592fae26bdSAlan Somers	typeset pool="$1"
16602fae26bdSAlan Somers
16612fae26bdSAlan Somers	typeset tmpfile=$TMPDIR/pool_status.${TESTCASE_ID}
16622fae26bdSAlan Somers	$ZPOOL status -x $pool > ${tmpfile}
16632fae26bdSAlan Somers	echo $tmpfile
16642fae26bdSAlan Somers}
16652fae26bdSAlan Somers
16662fae26bdSAlan Somers#
16672fae26bdSAlan Somers# Evaluates <file> counting the number of errors.  If vdev specified, only
16682fae26bdSAlan Somers# that vdev's errors are counted.  Returns the total number.  <file> will be
16692fae26bdSAlan Somers# deleted on exit.
16702fae26bdSAlan Somers#
16712fae26bdSAlan Somersfunction pool_errors_from_file # <file> [vdev]
16722fae26bdSAlan Somers{
16732fae26bdSAlan Somers	typeset file=$1
16742fae26bdSAlan Somers	shift
16752fae26bdSAlan Somers	typeset checkvdev="$2"
16762fae26bdSAlan Somers
16772fae26bdSAlan Somers	typeset line
16782fae26bdSAlan Somers	typeset -i fetchbegin=1
16792fae26bdSAlan Somers	typeset -i errnum=0
16802fae26bdSAlan Somers	typeset -i c_read=0
16812fae26bdSAlan Somers	typeset -i c_write=0
16822fae26bdSAlan Somers	typeset -i c_cksum=0
16832fae26bdSAlan Somers
16842fae26bdSAlan Somers	cat ${file} | $EGREP -v "pool:" | while read line; do
16852fae26bdSAlan Somers	 	if (( $fetchbegin != 0 )); then
16862fae26bdSAlan Somers                        $ECHO $line | $GREP "NAME" >/dev/null 2>&1
16872fae26bdSAlan Somers                        (( $? == 0 )) && (( fetchbegin = 0 ))
16882fae26bdSAlan Somers                         continue
16892fae26bdSAlan Somers                fi
16902fae26bdSAlan Somers
16912fae26bdSAlan Somers		if [[ -n $checkvdev ]]; then
16922fae26bdSAlan Somers			$ECHO $line | $GREP $checkvdev >/dev/null 2>&1
16932fae26bdSAlan Somers			(( $? != 0 )) && continue
16942fae26bdSAlan Somers			c_read=`$ECHO $line | $AWK '{print $3}'`
16952fae26bdSAlan Somers			c_write=`$ECHO $line | $AWK '{print $4}'`
16962fae26bdSAlan Somers			c_cksum=`$ECHO $line | $AWK '{print $5}'`
16972fae26bdSAlan Somers			if [ $c_read != 0 ] || [ $c_write != 0 ] || \
16982fae26bdSAlan Somers		   	   [ $c_cksum != 0 ]
16992fae26bdSAlan Somers			then
17002fae26bdSAlan Somers				(( errnum = errnum + 1 ))
17012fae26bdSAlan Somers			fi
17022fae26bdSAlan Somers			break
17032fae26bdSAlan Somers		fi
17042fae26bdSAlan Somers
17052fae26bdSAlan Somers		c_read=`$ECHO $line | $AWK '{print $3}'`
17062fae26bdSAlan Somers		c_write=`$ECHO $line | $AWK '{print $4}'`
17072fae26bdSAlan Somers		c_cksum=`$ECHO $line | $AWK '{print $5}'`
17082fae26bdSAlan Somers		if [ $c_read != 0 ] || [ $c_write != 0 ] || \
17092fae26bdSAlan Somers		    [ $c_cksum != 0 ]
17102fae26bdSAlan Somers		then
17112fae26bdSAlan Somers			(( errnum = errnum + 1 ))
17122fae26bdSAlan Somers		fi
17132fae26bdSAlan Somers	done
17142fae26bdSAlan Somers
17152fae26bdSAlan Somers	rm -f $file
17162fae26bdSAlan Somers	echo $errnum
17172fae26bdSAlan Somers}
17182fae26bdSAlan Somers
17192fae26bdSAlan Somers#
17202fae26bdSAlan Somers# Returns whether the vdev has the given number of errors.
17212fae26bdSAlan Somers# If the number is unspecified, any non-zero number returns true.
17222fae26bdSAlan Somers#
17232fae26bdSAlan Somersfunction vdev_has_errors # pool vdev [errors]
17242fae26bdSAlan Somers{
17252fae26bdSAlan Somers	typeset pool=$1
17262fae26bdSAlan Somers	typeset vdev=$2
17272fae26bdSAlan Somers	typeset tmpfile=$(pool_error_file $pool)
17282fae26bdSAlan Somers	log_note "Original pool status:"
17292fae26bdSAlan Somers	cat $tmpfile
17302fae26bdSAlan Somers
17312fae26bdSAlan Somers	typeset -i errs=$(pool_errors_from_file $tmpfile $vdev)
17322fae26bdSAlan Somers	vdev_pool_error_count $errs $3
17332fae26bdSAlan Somers}
17342fae26bdSAlan Somers
17352fae26bdSAlan Somers#
17362fae26bdSAlan Somers# Returns whether the pool has the given number of errors.
17372fae26bdSAlan Somers# If the number is unspecified, any non-zero number returns true.
17382fae26bdSAlan Somers#
17392fae26bdSAlan Somersfunction pool_has_errors # pool [errors]
17402fae26bdSAlan Somers{
17412fae26bdSAlan Somers	typeset pool=$1
17422fae26bdSAlan Somers	typeset tmpfile=$(pool_error_file $pool)
17432fae26bdSAlan Somers	log_note "Original pool status:"
17442fae26bdSAlan Somers	cat $tmpfile
17452fae26bdSAlan Somers
17462fae26bdSAlan Somers	typeset -i errs=$(pool_errors_from_file $tmpfile)
17472fae26bdSAlan Somers	vdev_pool_error_count $errs $2
17482fae26bdSAlan Somers}
17492fae26bdSAlan Somers
17502fae26bdSAlan Somers#
17512fae26bdSAlan Somers# Returns whether clearing $pool at $vdev (if given) succeeds.
17522fae26bdSAlan Somers#
17532fae26bdSAlan Somersfunction pool_clear_succeeds
17542fae26bdSAlan Somers{
17552fae26bdSAlan Somers	typeset pool="$1"
17562fae26bdSAlan Somers	typeset vdev=$2
17572fae26bdSAlan Somers
17582fae26bdSAlan Somers	$ZPOOL clear $pool $vdev
17592fae26bdSAlan Somers	! pool_has_errors $pool
17602fae26bdSAlan Somers}
17612fae26bdSAlan Somers
17622fae26bdSAlan Somers#
17632fae26bdSAlan Somers# Return whether the pool is healthy
17642fae26bdSAlan Somers#
17652fae26bdSAlan Somersfunction is_pool_healthy # pool
17662fae26bdSAlan Somers{
17672fae26bdSAlan Somers	typeset pool=$1
17682fae26bdSAlan Somers
17692fae26bdSAlan Somers	typeset healthy_output="pool '$pool' is healthy"
17702fae26bdSAlan Somers	typeset real_output=$($ZPOOL status -x $pool)
17712fae26bdSAlan Somers
17722fae26bdSAlan Somers	if [[ "$real_output" == "$healthy_output" ]]; then
17732fae26bdSAlan Somers		return 0
17742fae26bdSAlan Somers	else
17752fae26bdSAlan Somers		typeset -i ret
17762fae26bdSAlan Somers		$ZPOOL status -x $pool | $GREP "state:" | \
17772fae26bdSAlan Somers			$GREP "FAULTED" >/dev/null 2>&1
17782fae26bdSAlan Somers		ret=$?
17792fae26bdSAlan Somers		(( $ret == 0 )) && return 1
17802fae26bdSAlan Somers		typeset l_scan
17812fae26bdSAlan Somers		typeset errnum
17822fae26bdSAlan Somers		l_scan=$($ZPOOL status -x $pool | $GREP "scan:")
17832fae26bdSAlan Somers		l_scan=${l_scan##*"with"}
17842fae26bdSAlan Somers		errnum=$($ECHO $l_scan | $AWK '{print $1}')
17852fae26bdSAlan Somers		if [ "$errnum" != "0" ]; then
17862fae26bdSAlan Somers		 	return 1
17872fae26bdSAlan Somers		else
17882fae26bdSAlan Somers			return 0
17892fae26bdSAlan Somers		fi
17902fae26bdSAlan Somers	fi
17912fae26bdSAlan Somers}
17922fae26bdSAlan Somers
17932fae26bdSAlan Somers#
17942fae26bdSAlan Somers# These 5 following functions are instance of check_pool_status()
17952fae26bdSAlan Somers#	is_pool_resilvering - to check if the pool is resilver in progress
17962fae26bdSAlan Somers#	is_pool_resilvered - to check if the pool is resilver completed
17972fae26bdSAlan Somers#	is_pool_scrubbing - to check if the pool is scrub in progress
17982fae26bdSAlan Somers#	is_pool_scrubbed - to check if the pool is scrub completed
17992fae26bdSAlan Somers#	is_pool_scrub_stopped - to check if the pool is scrub stopped
18002fae26bdSAlan Somers#
18012fae26bdSAlan Somersfunction is_pool_resilvering #pool
18022fae26bdSAlan Somers{
18032fae26bdSAlan Somers	check_pool_status "$1" "scan" "resilver in progress"
18042fae26bdSAlan Somers	return $?
18052fae26bdSAlan Somers}
18062fae26bdSAlan Somers
18072fae26bdSAlan Somersfunction is_pool_resilvered #pool
18082fae26bdSAlan Somers{
18092fae26bdSAlan Somers	check_pool_status "$1" "scan" "resilvered"
18102fae26bdSAlan Somers	return $?
18112fae26bdSAlan Somers}
18122fae26bdSAlan Somers
18132fae26bdSAlan Somersfunction resilver_happened # pool
18142fae26bdSAlan Somers{
18152fae26bdSAlan Somers	typeset pool=$1
18162fae26bdSAlan Somers	is_pool_resilvering "$pool" || is_pool_resilvered "$pool"
18172fae26bdSAlan Somers}
18182fae26bdSAlan Somers
18192fae26bdSAlan Somersfunction is_pool_scrubbing #pool
18202fae26bdSAlan Somers{
18212fae26bdSAlan Somers	check_pool_status "$1" "scan" "scrub in progress"
18222fae26bdSAlan Somers	return $?
18232fae26bdSAlan Somers}
18242fae26bdSAlan Somers
18252fae26bdSAlan Somersfunction is_pool_scrubbed #pool
18262fae26bdSAlan Somers{
18272fae26bdSAlan Somers	check_pool_status "$1" "scan" "scrub repaired"
18282fae26bdSAlan Somers	return $?
18292fae26bdSAlan Somers}
18302fae26bdSAlan Somers
18312fae26bdSAlan Somersfunction is_pool_scrub_stopped #pool
18322fae26bdSAlan Somers{
18332fae26bdSAlan Somers	check_pool_status "$1" "scan" "scrub canceled"
18342fae26bdSAlan Somers	return $?
18352fae26bdSAlan Somers}
18362fae26bdSAlan Somers
18372fae26bdSAlan Somersfunction is_pool_state # pool state
18382fae26bdSAlan Somers{
18392fae26bdSAlan Somers	check_pool_status "$1" "state" "$2"
18402fae26bdSAlan Somers	return $?
18412fae26bdSAlan Somers}
18422fae26bdSAlan Somers
18432fae26bdSAlan Somers#
18442fae26bdSAlan Somers# Erase the partition tables and destroy any zfs labels
18452fae26bdSAlan Somers#
18462fae26bdSAlan Somersfunction cleanup_devices #vdevs
18472fae26bdSAlan Somers{
18482fae26bdSAlan Somers	for device in $@; do
18492fae26bdSAlan Somers		# Labelclear must happen first, otherwise it may interfere
18502fae26bdSAlan Somers		# with the teardown/setup of GPT labels.
18512fae26bdSAlan Somers		$ZPOOL labelclear -f $device
18522fae26bdSAlan Somers		# Only wipe partition tables for arguments that are disks,
18532fae26bdSAlan Somers		# as opposed to slices (which are valid arguments here).
1854*11ed0a95SEric van Gyzen		if geom disk list | grep -qx "Geom name: ${device#/dev/}"; then
18552fae26bdSAlan Somers			wipe_partition_table $device
18562fae26bdSAlan Somers		fi
18572fae26bdSAlan Somers	done
18582fae26bdSAlan Somers	return 0
18592fae26bdSAlan Somers}
18602fae26bdSAlan Somers
18612fae26bdSAlan Somers#
18622fae26bdSAlan Somers# Verify the rsh connectivity to each remote host in RHOSTS.
18632fae26bdSAlan Somers#
18642fae26bdSAlan Somers# Return 0 if remote host is accessible; otherwise 1.
18652fae26bdSAlan Somers# $1 remote host name
18662fae26bdSAlan Somers# $2 username
18672fae26bdSAlan Somers#
18682fae26bdSAlan Somersfunction verify_rsh_connect #rhost, username
18692fae26bdSAlan Somers{
18702fae26bdSAlan Somers	typeset rhost=$1
18712fae26bdSAlan Somers	typeset username=$2
18722fae26bdSAlan Somers	typeset rsh_cmd="$RSH -n"
18732fae26bdSAlan Somers	typeset cur_user=
18742fae26bdSAlan Somers
18752fae26bdSAlan Somers	$GETENT hosts $rhost >/dev/null 2>&1
18762fae26bdSAlan Somers	if (( $? != 0 )); then
18772fae26bdSAlan Somers		log_note "$rhost cannot be found from" \
18782fae26bdSAlan Somers			"administrative database."
18792fae26bdSAlan Somers		return 1
18802fae26bdSAlan Somers	fi
18812fae26bdSAlan Somers
18822fae26bdSAlan Somers	$PING $rhost 3 >/dev/null 2>&1
18832fae26bdSAlan Somers	if (( $? != 0 )); then
18842fae26bdSAlan Somers		log_note "$rhost is not reachable."
18852fae26bdSAlan Somers		return 1
18862fae26bdSAlan Somers	fi
18872fae26bdSAlan Somers
18882fae26bdSAlan Somers	if (( ${#username} != 0 )); then
18892fae26bdSAlan Somers		rsh_cmd="$rsh_cmd -l $username"
18902fae26bdSAlan Somers		cur_user="given user \"$username\""
18912fae26bdSAlan Somers	else
18922fae26bdSAlan Somers		cur_user="current user \"`$LOGNAME`\""
18932fae26bdSAlan Somers	fi
18942fae26bdSAlan Somers
18952fae26bdSAlan Somers	 if ! $rsh_cmd $rhost $TRUE; then
18962fae26bdSAlan Somers		log_note "$RSH to $rhost is not accessible" \
18972fae26bdSAlan Somers			"with $cur_user."
18982fae26bdSAlan Somers		return 1
18992fae26bdSAlan Somers	fi
19002fae26bdSAlan Somers
19012fae26bdSAlan Somers	return 0
19022fae26bdSAlan Somers}
19032fae26bdSAlan Somers
19042fae26bdSAlan Somers#
19052fae26bdSAlan Somers# Verify the remote host connection via rsh after rebooting
19062fae26bdSAlan Somers# $1 remote host
19072fae26bdSAlan Somers#
19082fae26bdSAlan Somersfunction verify_remote
19092fae26bdSAlan Somers{
19102fae26bdSAlan Somers	rhost=$1
19112fae26bdSAlan Somers
19122fae26bdSAlan Somers	#
19132fae26bdSAlan Somers	# The following loop waits for the remote system rebooting.
19142fae26bdSAlan Somers	# Each iteration will wait for 150 seconds. there are
19152fae26bdSAlan Somers	# total 5 iterations, so the total timeout value will
19162fae26bdSAlan Somers	# be 12.5  minutes for the system rebooting. This number
19172fae26bdSAlan Somers	# is an approxiate number.
19182fae26bdSAlan Somers	#
19192fae26bdSAlan Somers	typeset -i count=0
19202fae26bdSAlan Somers	while ! verify_rsh_connect $rhost; do
19212fae26bdSAlan Somers		sleep 150
19222fae26bdSAlan Somers		(( count = count + 1 ))
19232fae26bdSAlan Somers		if (( count > 5 )); then
19242fae26bdSAlan Somers			return 1
19252fae26bdSAlan Somers		fi
19262fae26bdSAlan Somers	done
19272fae26bdSAlan Somers	return 0
19282fae26bdSAlan Somers}
19292fae26bdSAlan Somers
19302fae26bdSAlan Somers#
19312fae26bdSAlan Somers# Replacement function for /usr/bin/rsh. This function will include
19322fae26bdSAlan Somers# the /usr/bin/rsh and meanwhile return the execution status of the
19332fae26bdSAlan Somers# last command.
19342fae26bdSAlan Somers#
19352fae26bdSAlan Somers# $1 usrname passing down to -l option of /usr/bin/rsh
19362fae26bdSAlan Somers# $2 remote machine hostname
19372fae26bdSAlan Somers# $3... command string
19382fae26bdSAlan Somers#
19392fae26bdSAlan Somers
19402fae26bdSAlan Somersfunction rsh_status
19412fae26bdSAlan Somers{
19422fae26bdSAlan Somers	typeset ruser=$1
19432fae26bdSAlan Somers	typeset rhost=$2
19442fae26bdSAlan Somers	typeset -i ret=0
19452fae26bdSAlan Somers	typeset cmd_str=""
19462fae26bdSAlan Somers	typeset rsh_str=""
19472fae26bdSAlan Somers
19482fae26bdSAlan Somers	shift; shift
19492fae26bdSAlan Somers	cmd_str="$@"
19502fae26bdSAlan Somers
19512fae26bdSAlan Somers	err_file=$TMPDIR/${rhost}.${TESTCASE_ID}.err
19522fae26bdSAlan Somers	if (( ${#ruser} == 0 )); then
19532fae26bdSAlan Somers		rsh_str="$RSH -n"
19542fae26bdSAlan Somers	else
19552fae26bdSAlan Somers		rsh_str="$RSH -n -l $ruser"
19562fae26bdSAlan Somers	fi
19572fae26bdSAlan Somers
19582fae26bdSAlan Somers	$rsh_str $rhost /usr/local/bin/ksh93 -c "'$cmd_str; \
19592fae26bdSAlan Somers		print -u 2 \"status=\$?\"'" \
19602fae26bdSAlan Somers		>/dev/null 2>$err_file
19612fae26bdSAlan Somers	ret=$?
19622fae26bdSAlan Somers	if (( $ret != 0 )); then
19632fae26bdSAlan Somers		$CAT $err_file
19642fae26bdSAlan Somers		$RM -f $std_file $err_file
19652fae26bdSAlan Somers		log_fail  "$RSH itself failed with exit code $ret..."
19662fae26bdSAlan Somers	fi
19672fae26bdSAlan Somers
19682fae26bdSAlan Somers	 ret=$($GREP -v 'print -u 2' $err_file | $GREP 'status=' | \
19692fae26bdSAlan Somers		$CUT -d= -f2)
19702fae26bdSAlan Somers	(( $ret != 0 )) && $CAT $err_file >&2
19712fae26bdSAlan Somers
19722fae26bdSAlan Somers	$RM -f $err_file >/dev/null 2>&1
19732fae26bdSAlan Somers	return $ret
19742fae26bdSAlan Somers}
19752fae26bdSAlan Somers
19762fae26bdSAlan Somers#
19772fae26bdSAlan Somers# Get the SUNWstc-fs-zfs package installation path in a remote host
19782fae26bdSAlan Somers# $1 remote host name
19792fae26bdSAlan Somers#
19802fae26bdSAlan Somersfunction get_remote_pkgpath
19812fae26bdSAlan Somers{
19822fae26bdSAlan Somers	typeset rhost=$1
19832fae26bdSAlan Somers	typeset pkgpath=""
19842fae26bdSAlan Somers
19852fae26bdSAlan Somers	pkgpath=$($RSH -n $rhost "$PKGINFO -l SUNWstc-fs-zfs | $GREP BASEDIR: |\
19862fae26bdSAlan Somers			$CUT -d: -f2")
19872fae26bdSAlan Somers
19882fae26bdSAlan Somers	$ECHO $pkgpath
19892fae26bdSAlan Somers}
19902fae26bdSAlan Somers
19912fae26bdSAlan Somers#/**
19922fae26bdSAlan Somers# A function to find and locate free disks on a system or from given
19932fae26bdSAlan Somers# disks as the parameter.  Since the conversion to ATF, this function is
19942fae26bdSAlan Somers# superfluous; it is assumed that the user will supply an accurate list of
19952fae26bdSAlan Somers# disks to use.  So we just return the arguments.
19962fae26bdSAlan Somers#
19972fae26bdSAlan Somers# $@ given disks to find which are free
19982fae26bdSAlan Somers#
19992fae26bdSAlan Somers# @return a string containing the list of available disks
20002fae26bdSAlan Somers#*/
20012fae26bdSAlan Somersfunction find_disks
20022fae26bdSAlan Somers{
20032fae26bdSAlan Somers	(( first=0 ))
20042fae26bdSAlan Somers	for disk in $@; do
20052fae26bdSAlan Somers		[[ $first == 1 ]] && echo -n " "
20062fae26bdSAlan Somers		(( first=1 ))
20072fae26bdSAlan Somers		case $disk in
20082fae26bdSAlan Somers		/dev/*)	echo -n "$disk" ;;
20092fae26bdSAlan Somers		*)	echo -n "/dev/$disk" ;;
20102fae26bdSAlan Somers		esac
20112fae26bdSAlan Somers	done
20122fae26bdSAlan Somers}
20132fae26bdSAlan Somers
20142fae26bdSAlan Somers# A function to set convenience variables for disks.
20152fae26bdSAlan Somersfunction set_disks
20162fae26bdSAlan Somers{
20172fae26bdSAlan Somers	set -A disk_array $(find_disks $DISKS)
20182fae26bdSAlan Somers	[[ -z "$DISK_ARRAY_LIMIT" ]] && typeset -i DISK_ARRAY_LIMIT=5
20192fae26bdSAlan Somers
20202fae26bdSAlan Somers	export DISK=""
20212fae26bdSAlan Somers	typeset -i i=0
20222fae26bdSAlan Somers	while (( i < ${#disk_array[*]} && i <= $DISK_ARRAY_LIMIT )); do
20232fae26bdSAlan Somers		export DISK${i}="${disk_array[$i]}"
20242fae26bdSAlan Somers		DISKSARRAY="$DISKSARRAY ${disk_array[$i]}"
20252fae26bdSAlan Somers		(( i = i + 1 ))
20262fae26bdSAlan Somers	done
20272fae26bdSAlan Somers	export DISK_ARRAY_NUM=$i
20282fae26bdSAlan Somers	export DISKSARRAY
20292fae26bdSAlan Somers	export disk=$DISK0
20302fae26bdSAlan Somers}
20312fae26bdSAlan Somers
20322fae26bdSAlan Somers#
20332fae26bdSAlan Somers# Add specified user to specified group
20342fae26bdSAlan Somers#
20352fae26bdSAlan Somers# $1 group name
20362fae26bdSAlan Somers# $2 user name
20372fae26bdSAlan Somers#
20382fae26bdSAlan Somersfunction add_user #<group_name> <user_name>
20392fae26bdSAlan Somers{
20402fae26bdSAlan Somers	typeset gname=$1
20412fae26bdSAlan Somers	typeset uname=$2
20422fae26bdSAlan Somers
20432fae26bdSAlan Somers	if (( ${#gname} == 0 || ${#uname} == 0 )); then
20442fae26bdSAlan Somers		log_fail "group name or user name are not defined."
20452fae26bdSAlan Somers	fi
20462fae26bdSAlan Somers
20472fae26bdSAlan Somers	# Check to see if the user exists.
20482fae26bdSAlan Somers	$ID $uname > /dev/null 2>&1 && return 0
20492fae26bdSAlan Somers
20502fae26bdSAlan Somers	# Assign 1000 as the base uid
20512fae26bdSAlan Somers	typeset -i uid=1000
20522fae26bdSAlan Somers	while true; do
20532fae26bdSAlan Somers		typeset -i ret
20542fae26bdSAlan Somers		$USERADD -u $uid -g $gname -d /var/tmp/$uname -m $uname
20552fae26bdSAlan Somers		ret=$?
20562fae26bdSAlan Somers		case $ret in
20572fae26bdSAlan Somers			0) return 0 ;;
20582fae26bdSAlan Somers			# The uid is not unique
20592fae26bdSAlan Somers			65) ((uid += 1)) ;;
20602fae26bdSAlan Somers			*) return 1 ;;
20612fae26bdSAlan Somers		esac
20622fae26bdSAlan Somers		if [[ $uid == 65000 ]]; then
20632fae26bdSAlan Somers			log_fail "No user id available under 65000 for $uname"
20642fae26bdSAlan Somers		fi
20652fae26bdSAlan Somers	done
20662fae26bdSAlan Somers
20672fae26bdSAlan Somers	return 0
20682fae26bdSAlan Somers}
20692fae26bdSAlan Somers
20702fae26bdSAlan Somers#
20712fae26bdSAlan Somers# Delete the specified user.
20722fae26bdSAlan Somers#
20732fae26bdSAlan Somers# $1 login name
20742fae26bdSAlan Somers#
20752fae26bdSAlan Somersfunction del_user #<logname>
20762fae26bdSAlan Somers{
20772fae26bdSAlan Somers	typeset user=$1
20782fae26bdSAlan Somers
20792fae26bdSAlan Somers	if (( ${#user} == 0 )); then
20802fae26bdSAlan Somers		log_fail "login name is necessary."
20812fae26bdSAlan Somers	fi
20822fae26bdSAlan Somers
20832fae26bdSAlan Somers	if $ID $user > /dev/null 2>&1; then
20842fae26bdSAlan Somers		log_must $USERDEL $user
20852fae26bdSAlan Somers	fi
20862fae26bdSAlan Somers
20872fae26bdSAlan Somers	return 0
20882fae26bdSAlan Somers}
20892fae26bdSAlan Somers
20902fae26bdSAlan Somers#
20912fae26bdSAlan Somers# Select valid gid and create specified group.
20922fae26bdSAlan Somers#
20932fae26bdSAlan Somers# $1 group name
20942fae26bdSAlan Somers#
20952fae26bdSAlan Somersfunction add_group #<group_name>
20962fae26bdSAlan Somers{
20972fae26bdSAlan Somers	typeset group=$1
20982fae26bdSAlan Somers
20992fae26bdSAlan Somers	if (( ${#group} == 0 )); then
21002fae26bdSAlan Somers		log_fail "group name is necessary."
21012fae26bdSAlan Somers	fi
21022fae26bdSAlan Somers
21032fae26bdSAlan Somers	# See if the group already exists.
21042fae26bdSAlan Somers	$GROUPSHOW $group >/dev/null 2>&1
21052fae26bdSAlan Somers	[[ $? == 0 ]] && return 0
21062fae26bdSAlan Somers
21072fae26bdSAlan Somers	# Assign 100 as the base gid
21082fae26bdSAlan Somers	typeset -i gid=100
21092fae26bdSAlan Somers	while true; do
21102fae26bdSAlan Somers		$GROUPADD -g $gid $group > /dev/null 2>&1
21112fae26bdSAlan Somers		typeset -i ret=$?
21122fae26bdSAlan Somers		case $ret in
21132fae26bdSAlan Somers			0) return 0 ;;
21142fae26bdSAlan Somers			# The gid is not  unique
21152fae26bdSAlan Somers			65) ((gid += 1)) ;;
21162fae26bdSAlan Somers			*) return 1 ;;
21172fae26bdSAlan Somers		esac
21182fae26bdSAlan Somers		if [[ $gid == 65000 ]]; then
21192fae26bdSAlan Somers			log_fail "No user id available under 65000 for $group"
21202fae26bdSAlan Somers		fi
21212fae26bdSAlan Somers	done
21222fae26bdSAlan Somers}
21232fae26bdSAlan Somers
21242fae26bdSAlan Somers#
21252fae26bdSAlan Somers# Delete the specified group.
21262fae26bdSAlan Somers#
21272fae26bdSAlan Somers# $1 group name
21282fae26bdSAlan Somers#
21292fae26bdSAlan Somersfunction del_group #<group_name>
21302fae26bdSAlan Somers{
21312fae26bdSAlan Somers	typeset grp=$1
21322fae26bdSAlan Somers	if (( ${#grp} == 0 )); then
21332fae26bdSAlan Somers		log_fail "group name is necessary."
21342fae26bdSAlan Somers	fi
21352fae26bdSAlan Somers
21362fae26bdSAlan Somers	$GROUPDEL -n $grp > /dev/null 2>&1
21372fae26bdSAlan Somers	typeset -i ret=$?
21382fae26bdSAlan Somers	case $ret in
21392fae26bdSAlan Somers		# Group does not exist, or was deleted successfully.
21402fae26bdSAlan Somers		0|6|65) return 0 ;;
21412fae26bdSAlan Somers		# Name already exists as a group name
21422fae26bdSAlan Somers		9) log_must $GROUPDEL $grp ;;
21432fae26bdSAlan Somers		*) return 1 ;;
21442fae26bdSAlan Somers	esac
21452fae26bdSAlan Somers
21462fae26bdSAlan Somers	return 0
21472fae26bdSAlan Somers}
21482fae26bdSAlan Somers
21492fae26bdSAlan Somers#
21502fae26bdSAlan Somers# This function will return true if it's safe to destroy the pool passed
21512fae26bdSAlan Somers# as argument 1. It checks for pools based on zvols and files, and also
21522fae26bdSAlan Somers# files contained in a pool that may have a different mountpoint.
21532fae26bdSAlan Somers#
21542fae26bdSAlan Somersfunction safe_to_destroy_pool { # $1 the pool name
21552fae26bdSAlan Somers
21562fae26bdSAlan Somers	typeset pool=""
21572fae26bdSAlan Somers	typeset DONT_DESTROY=""
21582fae26bdSAlan Somers
21592fae26bdSAlan Somers	# We check that by deleting the $1 pool, we're not
21602fae26bdSAlan Somers	# going to pull the rug out from other pools. Do this
21612fae26bdSAlan Somers	# by looking at all other pools, ensuring that they
21622fae26bdSAlan Somers	# aren't built from files or zvols contained in this pool.
21632fae26bdSAlan Somers
21642fae26bdSAlan Somers	for pool in $($ZPOOL list -H -o name)
21652fae26bdSAlan Somers	do
21662fae26bdSAlan Somers		ALTMOUNTPOOL=""
21672fae26bdSAlan Somers
21682fae26bdSAlan Somers		# this is a list of the top-level directories in each of the files
21692fae26bdSAlan Somers		# that make up the path to the files the pool is based on
21702fae26bdSAlan Somers		FILEPOOL=$($ZPOOL status -v $pool | $GREP /$1/ | \
21712fae26bdSAlan Somers			$AWK '{print $1}')
21722fae26bdSAlan Somers
21732fae26bdSAlan Somers		# this is a list of the zvols that make up the pool
21745a2fc464SAndriy Gapon		ZVOLPOOL=$($ZPOOL status -v $pool | $GREP "/dev/zvol/$1$" | \
21752fae26bdSAlan Somers			$AWK '{print $1}')
21762fae26bdSAlan Somers
21772fae26bdSAlan Somers		# also want to determine if it's a file-based pool using an
21782fae26bdSAlan Somers		# alternate mountpoint...
21792fae26bdSAlan Somers		POOL_FILE_DIRS=$($ZPOOL status -v $pool | \
21802fae26bdSAlan Somers					$GREP / | $AWK '{print $1}' | \
21812fae26bdSAlan Somers					$AWK -F/ '{print $2}' | $GREP -v "dev")
21822fae26bdSAlan Somers
21832fae26bdSAlan Somers		for pooldir in $POOL_FILE_DIRS
21842fae26bdSAlan Somers		do
21852fae26bdSAlan Somers			OUTPUT=$($ZFS list -H -r -o mountpoint $1 | \
21862fae26bdSAlan Somers					$GREP "${pooldir}$" | $AWK '{print $1}')
21872fae26bdSAlan Somers
21882fae26bdSAlan Somers			ALTMOUNTPOOL="${ALTMOUNTPOOL}${OUTPUT}"
21892fae26bdSAlan Somers		done
21902fae26bdSAlan Somers
21912fae26bdSAlan Somers
21922fae26bdSAlan Somers		if [ ! -z "$ZVOLPOOL" ]
21932fae26bdSAlan Somers		then
21942fae26bdSAlan Somers			DONT_DESTROY="true"
21952fae26bdSAlan Somers			log_note "Pool $pool is built from $ZVOLPOOL on $1"
21962fae26bdSAlan Somers		fi
21972fae26bdSAlan Somers
21982fae26bdSAlan Somers		if [ ! -z "$FILEPOOL" ]
21992fae26bdSAlan Somers		then
22002fae26bdSAlan Somers			DONT_DESTROY="true"
22012fae26bdSAlan Somers			log_note "Pool $pool is built from $FILEPOOL on $1"
22022fae26bdSAlan Somers		fi
22032fae26bdSAlan Somers
22042fae26bdSAlan Somers		if [ ! -z "$ALTMOUNTPOOL" ]
22052fae26bdSAlan Somers		then
22062fae26bdSAlan Somers			DONT_DESTROY="true"
22072fae26bdSAlan Somers			log_note "Pool $pool is built from $ALTMOUNTPOOL on $1"
22082fae26bdSAlan Somers		fi
22092fae26bdSAlan Somers	done
22102fae26bdSAlan Somers
22112fae26bdSAlan Somers	if [ -z "${DONT_DESTROY}" ]
22122fae26bdSAlan Somers	then
22132fae26bdSAlan Somers		return 0
22142fae26bdSAlan Somers	else
22152fae26bdSAlan Somers		log_note "Warning: it is not safe to destroy $1!"
22162fae26bdSAlan Somers		return 1
22172fae26bdSAlan Somers	fi
22182fae26bdSAlan Somers}
22192fae26bdSAlan Somers
22202fae26bdSAlan Somers#
22212fae26bdSAlan Somers# Get IP address of hostname
22222fae26bdSAlan Somers# $1 hostname
22232fae26bdSAlan Somers#
22242fae26bdSAlan Somersfunction getipbyhost
22252fae26bdSAlan Somers{
22262fae26bdSAlan Somers	typeset ip
22272fae26bdSAlan Somers	ip=`$ARP $1 2>/dev/null | $AWK -F\) '{print $1}' \
22282fae26bdSAlan Somers		| $AWK -F\( '{print $2}'`
22292fae26bdSAlan Somers	$ECHO $ip
22302fae26bdSAlan Somers}
22312fae26bdSAlan Somers
22322fae26bdSAlan Somers#
22332fae26bdSAlan Somers# Setup iSCSI initiator to target
22342fae26bdSAlan Somers# $1 target hostname
22352fae26bdSAlan Somers#
22362fae26bdSAlan Somersfunction iscsi_isetup
22372fae26bdSAlan Somers{
22382fae26bdSAlan Somers	# check svc:/network/iscsi_initiator:default state, try to enable it
22392fae26bdSAlan Somers	# if the state is not ON
22402fae26bdSAlan Somers	typeset ISCSII_FMRI="svc:/network/iscsi_initiator:default"
22412fae26bdSAlan Somers	if [[ "ON" != $($SVCS -H -o sta $ISCSII_FMRI) ]]; then
22422fae26bdSAlan Somers		log_must $SVCADM enable $ISCSII_FMRI
22432fae26bdSAlan Somers
22442fae26bdSAlan Somers		typeset -i retry=20
22452fae26bdSAlan Somers		while [[ "ON" != $($SVCS -H -o sta $ISCSII_FMRI) && \
22462fae26bdSAlan Somers			( $retry -ne 0 ) ]]
22472fae26bdSAlan Somers		do
22482fae26bdSAlan Somers			(( retry = retry - 1 ))
22492fae26bdSAlan Somers			$SLEEP 1
22502fae26bdSAlan Somers		done
22512fae26bdSAlan Somers
22522fae26bdSAlan Somers		if [[ "ON" != $($SVCS -H -o sta $ISCSII_FMRI) ]]; then
22532fae26bdSAlan Somers			log_fail "$ISCSII_FMRI service can not be enabled!"
22542fae26bdSAlan Somers		fi
22552fae26bdSAlan Somers	fi
22562fae26bdSAlan Somers
22572fae26bdSAlan Somers	log_must $ISCSIADM add discovery-address $(getipbyhost $1)
22582fae26bdSAlan Somers	log_must $ISCSIADM modify discovery --sendtargets enable
22592fae26bdSAlan Somers	log_must $DEVFSADM -i iscsi
22602fae26bdSAlan Somers}
22612fae26bdSAlan Somers
22622fae26bdSAlan Somers#
22632fae26bdSAlan Somers# Check whether iscsi parameter is set as remote
22642fae26bdSAlan Somers#
22652fae26bdSAlan Somers# return 0 if iscsi is set as remote, otherwise 1
22662fae26bdSAlan Somers#
22672fae26bdSAlan Somersfunction check_iscsi_remote
22682fae26bdSAlan Somers{
22692fae26bdSAlan Somers	if [[ $iscsi == "remote" ]] ; then
22702fae26bdSAlan Somers		return 0
22712fae26bdSAlan Somers	else
22722fae26bdSAlan Somers		return 1
22732fae26bdSAlan Somers	fi
22742fae26bdSAlan Somers}
22752fae26bdSAlan Somers
22762fae26bdSAlan Somers#
22772fae26bdSAlan Somers# Check if a volume is a valide iscsi target
22782fae26bdSAlan Somers# $1 volume name
22792fae26bdSAlan Somers# return 0 if suceeds, otherwise, return 1
22802fae26bdSAlan Somers#
22812fae26bdSAlan Somersfunction is_iscsi_target
22822fae26bdSAlan Somers{
22832fae26bdSAlan Somers	typeset dataset=$1
22842fae26bdSAlan Somers	typeset target targets
22852fae26bdSAlan Somers
22862fae26bdSAlan Somers	[[ -z $dataset ]] && return 1
22872fae26bdSAlan Somers
22882fae26bdSAlan Somers	targets=$($ISCSITADM list target | $GREP "Target:" | $AWK '{print $2}')
22892fae26bdSAlan Somers	[[ -z $targets ]] && return 1
22902fae26bdSAlan Somers
22912fae26bdSAlan Somers	for target in $targets; do
22922fae26bdSAlan Somers		[[ $dataset == $target ]] && return 0
22932fae26bdSAlan Somers	done
22942fae26bdSAlan Somers
22952fae26bdSAlan Somers	return 1
22962fae26bdSAlan Somers}
22972fae26bdSAlan Somers
22982fae26bdSAlan Somers#
22992fae26bdSAlan Somers# Get the iSCSI name of a target
23002fae26bdSAlan Somers# $1 target name
23012fae26bdSAlan Somers#
23022fae26bdSAlan Somersfunction iscsi_name
23032fae26bdSAlan Somers{
23042fae26bdSAlan Somers	typeset target=$1
23052fae26bdSAlan Somers	typeset name
23062fae26bdSAlan Somers
23072fae26bdSAlan Somers	[[ -z $target ]] && log_fail "No parameter."
23082fae26bdSAlan Somers
23092fae26bdSAlan Somers	if ! is_iscsi_target $target ; then
23102fae26bdSAlan Somers		log_fail "Not a target."
23112fae26bdSAlan Somers	fi
23122fae26bdSAlan Somers
23132fae26bdSAlan Somers	name=$($ISCSITADM list target $target | $GREP "iSCSI Name:" \
23142fae26bdSAlan Somers		| $AWK '{print $2}')
23152fae26bdSAlan Somers
23162fae26bdSAlan Somers	return $name
23172fae26bdSAlan Somers}
23182fae26bdSAlan Somers
23192fae26bdSAlan Somers#
23202fae26bdSAlan Somers# check svc:/system/iscsitgt:default state, try to enable it if the state
23212fae26bdSAlan Somers# is not ON
23222fae26bdSAlan Somers#
23232fae26bdSAlan Somersfunction iscsitgt_setup
23242fae26bdSAlan Somers{
23252fae26bdSAlan Somers	log_must $RM -f $ISCSITGTFILE
23262fae26bdSAlan Somers	if [[ "ON" == $($SVCS -H -o sta $ISCSITGT_FMRI) ]]; then
23272fae26bdSAlan Somers		log_note "iscsitgt is already enabled"
23282fae26bdSAlan Somers		return
23292fae26bdSAlan Somers	fi
23302fae26bdSAlan Somers
23312fae26bdSAlan Somers    	log_must $SVCADM enable -t $ISCSITGT_FMRI
23322fae26bdSAlan Somers
23332fae26bdSAlan Somers	typeset -i retry=20
23342fae26bdSAlan Somers	while [[ "ON" != $($SVCS -H -o sta $ISCSITGT_FMRI) && \
23352fae26bdSAlan Somers		( $retry -ne 0 ) ]]
23362fae26bdSAlan Somers	do
23372fae26bdSAlan Somers		$SLEEP 1
23382fae26bdSAlan Somers		(( retry = retry - 1 ))
23392fae26bdSAlan Somers	done
23402fae26bdSAlan Somers
23412fae26bdSAlan Somers	if [[ "ON" != $($SVCS -H -o sta $ISCSITGT_FMRI) ]]; then
23422fae26bdSAlan Somers		log_fail "$ISCSITGT_FMRI service can not be enabled!"
23432fae26bdSAlan Somers	fi
23442fae26bdSAlan Somers
23452fae26bdSAlan Somers	log_must $TOUCH $ISCSITGTFILE
23462fae26bdSAlan Somers}
23472fae26bdSAlan Somers
23482fae26bdSAlan Somers#
23492fae26bdSAlan Somers# set DISABLED state of svc:/system/iscsitgt:default
23502fae26bdSAlan Somers# which is the most suiteable state if $ISCSITGTFILE exists
23512fae26bdSAlan Somers#
23522fae26bdSAlan Somersfunction iscsitgt_cleanup
23532fae26bdSAlan Somers{
23542fae26bdSAlan Somers	if [[ -e $ISCSITGTFILE ]]; then
23552fae26bdSAlan Somers		log_must $SVCADM disable $ISCSITGT_FMRI
23562fae26bdSAlan Somers		log_must $RM -f $ISCSITGTFILE
23572fae26bdSAlan Somers	fi
23582fae26bdSAlan Somers}
23592fae26bdSAlan Somers
23602fae26bdSAlan Somers#
23612fae26bdSAlan Somers# Close iSCSI initiator to target
23622fae26bdSAlan Somers# $1 target hostname
23632fae26bdSAlan Somers#
23642fae26bdSAlan Somersfunction iscsi_iclose
23652fae26bdSAlan Somers{
23662fae26bdSAlan Somers	log_must $ISCSIADM modify discovery --sendtargets disable
23672fae26bdSAlan Somers	log_must $ISCSIADM remove discovery-address $(getipbyhost $1)
23682fae26bdSAlan Somers	$DEVFSADM -Cv
23692fae26bdSAlan Somers}
23702fae26bdSAlan Somers
23712fae26bdSAlan Somers#
23722fae26bdSAlan Somers# Get the available ZFS compression options
23732fae26bdSAlan Somers# $1 option type zfs_set|zfs_compress
23742fae26bdSAlan Somers#
23752fae26bdSAlan Somersfunction get_compress_opts
23762fae26bdSAlan Somers{
23772fae26bdSAlan Somers	typeset COMPRESS_OPTS
23782fae26bdSAlan Somers	typeset GZIP_OPTS="gzip gzip-1 gzip-2 gzip-3 gzip-4 gzip-5 \
23792fae26bdSAlan Somers			gzip-6 gzip-7 gzip-8 gzip-9"
23802fae26bdSAlan Somers
23812fae26bdSAlan Somers	if [[ $1 == "zfs_compress" ]] ; then
23822fae26bdSAlan Somers		COMPRESS_OPTS="on lzjb"
23832fae26bdSAlan Somers	elif [[ $1 == "zfs_set" ]] ; then
23842fae26bdSAlan Somers		COMPRESS_OPTS="on off lzjb"
23852fae26bdSAlan Somers	fi
23862fae26bdSAlan Somers	typeset valid_opts="$COMPRESS_OPTS"
23872fae26bdSAlan Somers	$ZFS get 2>&1 | $GREP gzip >/dev/null 2>&1
23882fae26bdSAlan Somers	if [[ $? -eq 0 ]]; then
23892fae26bdSAlan Somers		valid_opts="$valid_opts $GZIP_OPTS"
23902fae26bdSAlan Somers	fi
23912fae26bdSAlan Somers	$ECHO "$valid_opts"
23922fae26bdSAlan Somers}
23932fae26bdSAlan Somers
23942fae26bdSAlan Somers#
23952fae26bdSAlan Somers# Check the subcommand/option is supported
23962fae26bdSAlan Somers#
23972fae26bdSAlan Somersfunction check_opt_support #command, option
23982fae26bdSAlan Somers{
23992fae26bdSAlan Somers	typeset command=$1
24002fae26bdSAlan Somers	typeset option=$2
24012fae26bdSAlan Somers
24022fae26bdSAlan Somers	if [[ -z $command ]]; then
24032fae26bdSAlan Somers		return 0
24042fae26bdSAlan Somers	elif [[ -z $option ]]; then
24052fae26bdSAlan Somers		eval "$ZFS 2>&1 | $GREP '$command' > /dev/null 2>&1"
24062fae26bdSAlan Somers	else
24072fae26bdSAlan Somers		eval "$ZFS $command 2>&1 | $GREP -- '$option' | \
24082fae26bdSAlan Somers			$GREP -v -- 'User-defined' > /dev/null 2>&1"
24092fae26bdSAlan Somers	fi
24102fae26bdSAlan Somers	return $?
24112fae26bdSAlan Somers}
24122fae26bdSAlan Somers
24132fae26bdSAlan Somers#
24142fae26bdSAlan Somers# Check the zpool subcommand/option is supported
24152fae26bdSAlan Somers#
24162fae26bdSAlan Somersfunction check_zpool_opt_support #command, option
24172fae26bdSAlan Somers{
24182fae26bdSAlan Somers	typeset command=$1
24192fae26bdSAlan Somers	typeset option=$2
24202fae26bdSAlan Somers
24212fae26bdSAlan Somers	if [[ -z $command ]]; then
24222fae26bdSAlan Somers		return 0
24232fae26bdSAlan Somers	elif [[ -z $option ]]; then
24242fae26bdSAlan Somers		eval "$ZPOOL 2>&1 | $GREP '$command' > /dev/null 2>&1"
24252fae26bdSAlan Somers	else
24262fae26bdSAlan Somers		eval "$ZPOOL $command 2>&1 | $GREP -- '$option' > /dev/null 2>&1"
24272fae26bdSAlan Somers	fi
24282fae26bdSAlan Somers	return $?
24292fae26bdSAlan Somers}
24302fae26bdSAlan Somers
24312fae26bdSAlan Somers#
24322fae26bdSAlan Somers# Verify zfs operation with -p option work as expected
24332fae26bdSAlan Somers# $1 operation, value could be create, clone or rename
24342fae26bdSAlan Somers# $2 dataset type, value could be fs or vol
24352fae26bdSAlan Somers# $3 dataset name
24362fae26bdSAlan Somers# $4 new dataset name
24372fae26bdSAlan Somers#
24382fae26bdSAlan Somersfunction verify_opt_p_ops
24392fae26bdSAlan Somers{
24402fae26bdSAlan Somers	typeset ops=$1
24412fae26bdSAlan Somers	typeset datatype=$2
24422fae26bdSAlan Somers	typeset dataset=$3
24432fae26bdSAlan Somers	typeset newdataset=$4
24442fae26bdSAlan Somers
24452fae26bdSAlan Somers	if [[ $datatype != "fs" && $datatype != "vol" ]]; then
24462fae26bdSAlan Somers		log_fail "$datatype is not supported."
24472fae26bdSAlan Somers	fi
24482fae26bdSAlan Somers
24492fae26bdSAlan Somers	# check parameters accordingly
24502fae26bdSAlan Somers	case $ops in
24512fae26bdSAlan Somers		create)
24522fae26bdSAlan Somers			newdataset=$dataset
24532fae26bdSAlan Somers			dataset=""
24542fae26bdSAlan Somers			if [[ $datatype == "vol" ]]; then
24552fae26bdSAlan Somers				ops="create -V $VOLSIZE"
24562fae26bdSAlan Somers			fi
24572fae26bdSAlan Somers			;;
24582fae26bdSAlan Somers		clone)
24592fae26bdSAlan Somers			if [[ -z $newdataset ]]; then
24602fae26bdSAlan Somers				log_fail "newdataset should not be empty" \
24612fae26bdSAlan Somers					"when ops is $ops."
24622fae26bdSAlan Somers			fi
24632fae26bdSAlan Somers			log_must datasetexists $dataset
24642fae26bdSAlan Somers			log_must snapexists $dataset
24652fae26bdSAlan Somers			;;
24662fae26bdSAlan Somers		rename)
24672fae26bdSAlan Somers			if [[ -z $newdataset ]]; then
24682fae26bdSAlan Somers				log_fail "newdataset should not be empty" \
24692fae26bdSAlan Somers					"when ops is $ops."
24702fae26bdSAlan Somers			fi
24712fae26bdSAlan Somers			log_must datasetexists $dataset
24722fae26bdSAlan Somers			log_mustnot snapexists $dataset
24732fae26bdSAlan Somers			;;
24742fae26bdSAlan Somers		*)
24752fae26bdSAlan Somers			log_fail "$ops is not supported."
24762fae26bdSAlan Somers			;;
24772fae26bdSAlan Somers	esac
24782fae26bdSAlan Somers
24792fae26bdSAlan Somers	# make sure the upper level filesystem does not exist
24802fae26bdSAlan Somers	if datasetexists ${newdataset%/*} ; then
24812fae26bdSAlan Somers		log_must $ZFS destroy -rRf ${newdataset%/*}
24822fae26bdSAlan Somers	fi
24832fae26bdSAlan Somers
24842fae26bdSAlan Somers	# without -p option, operation will fail
24852fae26bdSAlan Somers	log_mustnot $ZFS $ops $dataset $newdataset
24862fae26bdSAlan Somers	log_mustnot datasetexists $newdataset ${newdataset%/*}
24872fae26bdSAlan Somers
24882fae26bdSAlan Somers	# with -p option, operation should succeed
24892fae26bdSAlan Somers	log_must $ZFS $ops -p $dataset $newdataset
24902fae26bdSAlan Somers	if ! datasetexists $newdataset ; then
24912fae26bdSAlan Somers		log_fail "-p option does not work for $ops"
24922fae26bdSAlan Somers	fi
24932fae26bdSAlan Somers
24942fae26bdSAlan Somers	# when $ops is create or clone, redo the operation still return zero
24952fae26bdSAlan Somers	if [[ $ops != "rename" ]]; then
24962fae26bdSAlan Somers		log_must $ZFS $ops -p $dataset $newdataset
24972fae26bdSAlan Somers	fi
24982fae26bdSAlan Somers
24992fae26bdSAlan Somers	return 0
25002fae26bdSAlan Somers}
25012fae26bdSAlan Somers
25022fae26bdSAlan Somersfunction get_disk_guid
25032fae26bdSAlan Somers{
25042fae26bdSAlan Somers	typeset diskname=$1
25052fae26bdSAlan Somers	lastcwd=$(pwd)
25062fae26bdSAlan Somers	cd /dev
25072fae26bdSAlan Somers	guid=$($ZDB -l ${diskname} | ${AWK} '/^    guid:/ {print $2}' | head -1)
25082fae26bdSAlan Somers	cd $lastcwd
25092fae26bdSAlan Somers	echo $guid
25102fae26bdSAlan Somers}
25112fae26bdSAlan Somers
25122fae26bdSAlan Somers#
25132fae26bdSAlan Somers# Get cachefile for a pool.
25142fae26bdSAlan Somers# Prints the cache file, if there is one.
25152fae26bdSAlan Somers# Returns 0 for a default zpool.cache, 1 for an explicit one, and 2 for none.
25162fae26bdSAlan Somers#
25172fae26bdSAlan Somersfunction cachefile_for_pool
25182fae26bdSAlan Somers{
25192fae26bdSAlan Somers	typeset pool=$1
25202fae26bdSAlan Somers
25212fae26bdSAlan Somers	cachefile=$(get_pool_prop cachefile $pool)
25222fae26bdSAlan Somers	[[ $? != 0 ]] && return 1
25232fae26bdSAlan Somers
25242fae26bdSAlan Somers	case "$cachefile" in
25252fae26bdSAlan Somers		none)	ret=2 ;;
25262fae26bdSAlan Somers		"-")
25272fae26bdSAlan Somers			ret=2
25282fae26bdSAlan Somers			for dir in /boot/zfs /etc/zfs; do
25292fae26bdSAlan Somers				if [[ -f "${dir}/zpool.cache" ]]; then
25302fae26bdSAlan Somers					cachefile="${dir}/zpool.cache"
25312fae26bdSAlan Somers					ret=0
25322fae26bdSAlan Somers					break
25332fae26bdSAlan Somers				fi
25342fae26bdSAlan Somers			done
25352fae26bdSAlan Somers			;;
25362fae26bdSAlan Somers		*)	ret=1;
25372fae26bdSAlan Somers	esac
25382fae26bdSAlan Somers	[[ $ret -eq 0 || $ret -eq 1 ]] && print "$cachefile"
25392fae26bdSAlan Somers	return $ret
25402fae26bdSAlan Somers}
25412fae26bdSAlan Somers
25422fae26bdSAlan Somers#
25432fae26bdSAlan Somers# Assert that the pool is in the appropriate cachefile.
25442fae26bdSAlan Somers#
25452fae26bdSAlan Somersfunction assert_pool_in_cachefile
25462fae26bdSAlan Somers{
25472fae26bdSAlan Somers	typeset pool=$1
25482fae26bdSAlan Somers
25492fae26bdSAlan Somers	cachefile=$(cachefile_for_pool $pool)
25502fae26bdSAlan Somers	[ $? -ne 0 ] && log_fail "ERROR: Cachefile not created for '$pool'?"
25512fae26bdSAlan Somers	log_must test -e "${cachefile}"
25522fae26bdSAlan Somers	log_must zdb -U ${cachefile} -C ${pool}
25532fae26bdSAlan Somers}
25542fae26bdSAlan Somers
25552fae26bdSAlan Somers#
25562fae26bdSAlan Somers# Get the zdb options given the cachefile state of the pool.
25572fae26bdSAlan Somers#
25582fae26bdSAlan Somersfunction zdb_cachefile_opts
25592fae26bdSAlan Somers{
25602fae26bdSAlan Somers	typeset pool=$1
25612fae26bdSAlan Somers	typeset vdevdir=$2
25622fae26bdSAlan Somers	typeset opts
25632fae26bdSAlan Somers
25642fae26bdSAlan Somers	if poolexists "$pool"; then
25652fae26bdSAlan Somers		cachefile=$(cachefile_for_pool $pool)
25662fae26bdSAlan Somers		typeset -i ret=$?
25672fae26bdSAlan Somers		case $ret in
25682fae26bdSAlan Somers			0)	opts="-C" ;;
25692fae26bdSAlan Somers			1)	opts="-U $cachefile -C" ;;
25702fae26bdSAlan Somers			2)	opts="-eC" ;;
25712fae26bdSAlan Somers			*)	log_fail "Unknown return '$ret'" ;;
25722fae26bdSAlan Somers		esac
25732fae26bdSAlan Somers	else
25742fae26bdSAlan Somers		opts="-eC"
25752fae26bdSAlan Somers		[[ -n "$vdevdir" ]] && opts="$opts -p $vdevdir"
25762fae26bdSAlan Somers	fi
25772fae26bdSAlan Somers	echo "$opts"
25782fae26bdSAlan Somers}
25792fae26bdSAlan Somers
25802fae26bdSAlan Somers#
25812fae26bdSAlan Somers# Get configuration of pool
25822fae26bdSAlan Somers# $1 pool name
25832fae26bdSAlan Somers# $2 config name
25842fae26bdSAlan Somers#
25852fae26bdSAlan Somersfunction get_config
25862fae26bdSAlan Somers{
25872fae26bdSAlan Somers	typeset pool=$1
25882fae26bdSAlan Somers	typeset config=$2
25892fae26bdSAlan Somers	typeset vdevdir=$3
25902fae26bdSAlan Somers	typeset alt_root
25912fae26bdSAlan Somers	typeset zdb_opts
25922fae26bdSAlan Somers
25932fae26bdSAlan Somers	zdb_opts=$(zdb_cachefile_opts $pool $vdevdir)
25942fae26bdSAlan Somers	value=$($ZDB $zdb_opts $pool | $GREP "$config:" | $AWK -F: '{print $2}')
25952fae26bdSAlan Somers	if [[ -n $value ]] ; then
25962fae26bdSAlan Somers		value=${value#'}
25972fae26bdSAlan Somers		value=${value%'}
25982fae26bdSAlan Somers	else
25992fae26bdSAlan Somers		return 1
26002fae26bdSAlan Somers	fi
26012fae26bdSAlan Somers	echo $value
26022fae26bdSAlan Somers
26032fae26bdSAlan Somers	return 0
26042fae26bdSAlan Somers}
26052fae26bdSAlan Somers
26062fae26bdSAlan Somers#
26072fae26bdSAlan Somers# Privated function. Random select one of items from arguments.
26082fae26bdSAlan Somers#
26092fae26bdSAlan Somers# $1 count
26102fae26bdSAlan Somers# $2-n string
26112fae26bdSAlan Somers#
26122fae26bdSAlan Somersfunction _random_get
26132fae26bdSAlan Somers{
26142fae26bdSAlan Somers	typeset cnt=$1
26152fae26bdSAlan Somers	shift
26162fae26bdSAlan Somers
26172fae26bdSAlan Somers	typeset str="$@"
26182fae26bdSAlan Somers	typeset -i ind
26192fae26bdSAlan Somers	((ind = RANDOM % cnt + 1))
26202fae26bdSAlan Somers
26212fae26bdSAlan Somers	typeset ret=$($ECHO "$str" | $CUT -f $ind -d ' ')
26222fae26bdSAlan Somers	$ECHO $ret
26232fae26bdSAlan Somers}
26242fae26bdSAlan Somers
26252fae26bdSAlan Somers#
26262fae26bdSAlan Somers# Random select one of item from arguments which include NONE string
26272fae26bdSAlan Somers#
26282fae26bdSAlan Somersfunction random_get_with_non
26292fae26bdSAlan Somers{
26302fae26bdSAlan Somers	typeset -i cnt=$#
26312fae26bdSAlan Somers	((cnt =+ 1))
26322fae26bdSAlan Somers
26332fae26bdSAlan Somers	_random_get "$cnt" "$@"
26342fae26bdSAlan Somers}
26352fae26bdSAlan Somers
26362fae26bdSAlan Somers#
26372fae26bdSAlan Somers# Random select one of item from arguments which doesn't include NONE string
26382fae26bdSAlan Somers#
26392fae26bdSAlan Somersfunction random_get
26402fae26bdSAlan Somers{
26412fae26bdSAlan Somers	_random_get "$#" "$@"
26422fae26bdSAlan Somers}
26432fae26bdSAlan Somers
26442fae26bdSAlan Somers#
26452fae26bdSAlan Somers# The function will generate a dataset name with specific length
26462fae26bdSAlan Somers# $1, the length of the name
26472fae26bdSAlan Somers# $2, the base string to construct the name
26482fae26bdSAlan Somers#
26492fae26bdSAlan Somersfunction gen_dataset_name
26502fae26bdSAlan Somers{
26512fae26bdSAlan Somers	typeset -i len=$1
26522fae26bdSAlan Somers	typeset basestr="$2"
26532fae26bdSAlan Somers	typeset -i baselen=${#basestr}
26542fae26bdSAlan Somers	typeset -i iter=0
26552fae26bdSAlan Somers	typeset l_name=""
26562fae26bdSAlan Somers
26572fae26bdSAlan Somers	if (( len % baselen == 0 )); then
26582fae26bdSAlan Somers		(( iter = len / baselen ))
26592fae26bdSAlan Somers	else
26602fae26bdSAlan Somers		(( iter = len / baselen + 1 ))
26612fae26bdSAlan Somers	fi
26622fae26bdSAlan Somers	while (( iter > 0 )); do
26632fae26bdSAlan Somers		l_name="${l_name}$basestr"
26642fae26bdSAlan Somers
26652fae26bdSAlan Somers		(( iter -= 1 ))
26662fae26bdSAlan Somers	done
26672fae26bdSAlan Somers
26682fae26bdSAlan Somers	$ECHO $l_name
26692fae26bdSAlan Somers}
26702fae26bdSAlan Somers
26712fae26bdSAlan Somers#
26722fae26bdSAlan Somers# Ensure that a given path has been synced, not just ZIL committed.
26732fae26bdSAlan Somers#
2674c43f30eeSAlan Somers# XXX On FreeBSD, the sync(8) command (via $SYNC) calls zfs_sync() which just
26752fae26bdSAlan Somers#     does a zil_commit(), as opposed to a txg_wait_synced().  For things that
26762fae26bdSAlan Somers#     require writing to their final destination (e.g. for intentional
26772fae26bdSAlan Somers#     corruption purposes), zil_commit() is not good enough.
26782fae26bdSAlan Somers#
26792fae26bdSAlan Somersfunction force_sync_path # path
26802fae26bdSAlan Somers{
26812fae26bdSAlan Somers	typeset path="$1"
26822fae26bdSAlan Somers
2683c43f30eeSAlan Somers	log_must $ZPOOL export $TESTPOOL
2684c43f30eeSAlan Somers	log_must $ZPOOL import -d $path $TESTPOOL
26852fae26bdSAlan Somers}
26862fae26bdSAlan Somers
26872fae26bdSAlan Somers#
26882fae26bdSAlan Somers# Get cksum tuple of dataset
26892fae26bdSAlan Somers# $1 dataset name
26902fae26bdSAlan Somers#
26912fae26bdSAlan Somers# zdb output is like below
26922fae26bdSAlan Somers# " Dataset pool/fs [ZPL], ID 978, cr_txg 2277, 19.0K, 5 objects,
26932fae26bdSAlan Somers# rootbp [L0 DMU objset] 400L/200P DVA[0]=<0:1880c00:200>
26942fae26bdSAlan Somers# DVA[1]=<0:341880c00:200> fletcher4 lzjb LE contiguous birth=2292 fill=5
26952fae26bdSAlan Somers# cksum=989930ccf:4014fe00c83:da5e388e58b4:1f7332052252ac "
26962fae26bdSAlan Somers#
26972fae26bdSAlan Somersfunction datasetcksum
26982fae26bdSAlan Somers{
26992fae26bdSAlan Somers	typeset cksum
27002fae26bdSAlan Somers	$SYNC
27012fae26bdSAlan Somers	cksum=$($ZDB -vvv $1 | $GREP "^Dataset $1 \[" | $GREP "cksum" \
27022fae26bdSAlan Somers		| $AWK -F= '{print $6}')
27032fae26bdSAlan Somers	$ECHO $cksum
27042fae26bdSAlan Somers}
27052fae26bdSAlan Somers
27062fae26bdSAlan Somers#
27072fae26bdSAlan Somers# Get cksum of file
27082fae26bdSAlan Somers# #1 file path
27092fae26bdSAlan Somers#
27102fae26bdSAlan Somersfunction checksum
27112fae26bdSAlan Somers{
27122fae26bdSAlan Somers	typeset cksum
27132fae26bdSAlan Somers	cksum=$($CKSUM $1 | $AWK '{print $1}')
27142fae26bdSAlan Somers	$ECHO $cksum
27152fae26bdSAlan Somers}
27162fae26bdSAlan Somers
27172fae26bdSAlan Somers#
27182fae26bdSAlan Somers# Get the given disk/slice state from the specific field of the pool
27192fae26bdSAlan Somers#
27202fae26bdSAlan Somersfunction get_device_state #pool disk field("", "spares","logs")
27212fae26bdSAlan Somers{
27222fae26bdSAlan Somers	typeset pool=$1
27235a2fc464SAndriy Gapon	typeset disk=${2#/dev/}
27245a2fc464SAndriy Gapon	disk=${disk#/dev/}
27252fae26bdSAlan Somers	disk=${disk#/dev/}
27262fae26bdSAlan Somers	typeset field=${3:-$pool}
27272fae26bdSAlan Somers
27282fae26bdSAlan Somers	state=$($ZPOOL status -v "$pool" 2>/dev/null | \
27292fae26bdSAlan Somers		$NAWK -v device=$disk -v pool=$pool -v field=$field \
27302fae26bdSAlan Somers		'BEGIN {startconfig=0; startfield=0; }
27312fae26bdSAlan Somers		/config:/ {startconfig=1}
27322fae26bdSAlan Somers		(startconfig==1)&&($1==field) {startfield=1; next;}
27332fae26bdSAlan Somers		(startfield==1)&&($1==device) {print $2; exit;}
27342fae26bdSAlan Somers		(startfield==1)&&(NF>=3)&&($(NF-1)=="was")&&($NF==device) {print $2; exit;}
27352fae26bdSAlan Somers		(startfield==1)&&($1==field || $1 ~ "^spares$" || $1 ~ "^logs$") {startfield=0}')
27362fae26bdSAlan Somers	print $state
27372fae26bdSAlan Somers}
27382fae26bdSAlan Somers
27392fae26bdSAlan Somers
27402fae26bdSAlan Somers#
27412fae26bdSAlan Somers# print the given directory filesystem type
27422fae26bdSAlan Somers#
27432fae26bdSAlan Somers# $1 directory name
27442fae26bdSAlan Somers#
27452fae26bdSAlan Somersfunction get_fstype
27462fae26bdSAlan Somers{
27472fae26bdSAlan Somers	typeset dir=$1
27482fae26bdSAlan Somers
27492fae26bdSAlan Somers	if [[ -z $dir ]]; then
27502fae26bdSAlan Somers		log_fail "Usage: get_fstype <directory>"
27512fae26bdSAlan Somers	fi
27522fae26bdSAlan Somers
27532fae26bdSAlan Somers	$DF -T $dir | $AWK '{print $2}'
27542fae26bdSAlan Somers}
27552fae26bdSAlan Somers
27562fae26bdSAlan Somers#
27572fae26bdSAlan Somers# Given a disk, label it to VTOC regardless what label was on the disk
27582fae26bdSAlan Somers# $1 disk
27592fae26bdSAlan Somers#
27602fae26bdSAlan Somersfunction labelvtoc
27612fae26bdSAlan Somers{
27622fae26bdSAlan Somers	typeset disk=$1
27632fae26bdSAlan Somers	if [[ -z $disk ]]; then
27642fae26bdSAlan Somers		log_fail "The disk name is unspecified."
27652fae26bdSAlan Somers	fi
27662fae26bdSAlan Somers	typeset label_file=$TMPDIR/labelvtoc.${TESTCASE_ID}
27672fae26bdSAlan Somers	typeset arch=$($UNAME -p)
27682fae26bdSAlan Somers
27692fae26bdSAlan Somers	if [[ $arch == "i386" ]]; then
27702fae26bdSAlan Somers		 $ECHO "label" > $label_file
27712fae26bdSAlan Somers		 $ECHO "0" >> $label_file
27722fae26bdSAlan Somers		 $ECHO "" >> $label_file
27732fae26bdSAlan Somers		 $ECHO "q" >> $label_file
27742fae26bdSAlan Somers		 $ECHO "q" >> $label_file
27752fae26bdSAlan Somers
27762fae26bdSAlan Somers		 $FDISK -B $disk >/dev/null 2>&1
27772fae26bdSAlan Somers		 # wait a while for fdisk finishes
27782fae26bdSAlan Somers		 $SLEEP 60
27792fae26bdSAlan Somers	elif [[ $arch == "sparc" ]]; then
27802fae26bdSAlan Somers	     	 $ECHO "label" > $label_file
27812fae26bdSAlan Somers		 $ECHO "0" >> $label_file
27822fae26bdSAlan Somers		 $ECHO "" >> $label_file
27832fae26bdSAlan Somers		 $ECHO "" >> $label_file
27842fae26bdSAlan Somers		 $ECHO "" >> $label_file
27852fae26bdSAlan Somers		 $ECHO "q" >> $label_file
27862fae26bdSAlan Somers	else
27872fae26bdSAlan Somers		log_fail "unknown arch type"
27882fae26bdSAlan Somers	fi
27892fae26bdSAlan Somers
27902fae26bdSAlan Somers	$FORMAT -e -s -d $disk -f $label_file
27912fae26bdSAlan Somers	typeset -i ret_val=$?
27922fae26bdSAlan Somers	$RM -f $label_file
27932fae26bdSAlan Somers	#
27942fae26bdSAlan Somers	# wait the format to finish
27952fae26bdSAlan Somers	#
27962fae26bdSAlan Somers	$SLEEP 60
27972fae26bdSAlan Somers	if (( ret_val != 0 )); then
27982fae26bdSAlan Somers		log_fail "unable to label $disk as VTOC."
27992fae26bdSAlan Somers	fi
28002fae26bdSAlan Somers
28012fae26bdSAlan Somers	return 0
28022fae26bdSAlan Somers}
28032fae26bdSAlan Somers
28042fae26bdSAlan Somers#
28052fae26bdSAlan Somers# Detect if the given filesystem property is supported in this release
28062fae26bdSAlan Somers#
28072fae26bdSAlan Somers# 0	Yes, it is supported
28082fae26bdSAlan Somers# !0	No, it is not supported
28092fae26bdSAlan Somers#
28102fae26bdSAlan Somersfunction fs_prop_exist
28112fae26bdSAlan Somers{
28122fae26bdSAlan Somers	typeset prop=$1
28132fae26bdSAlan Somers
28142fae26bdSAlan Somers	if [[ -z $prop ]]; then
28152fae26bdSAlan Somers		log_fail "Usage: fs_prop_exist <property>"
28162fae26bdSAlan Somers
28172fae26bdSAlan Somers		return 1
28182fae26bdSAlan Somers	fi
28192fae26bdSAlan Somers
28202fae26bdSAlan Somers	#
28212fae26bdSAlan Somers	# If the property is shortened column name,
28222fae26bdSAlan Somers	# convert it to the standard name
28232fae26bdSAlan Somers	#
28242fae26bdSAlan Somers	case $prop in
28252fae26bdSAlan Somers		avail)		prop=available		;;
28262fae26bdSAlan Somers		refer)		prop=referenced		;;
28272fae26bdSAlan Somers		volblock)	prop=volblocksize	;;
28282fae26bdSAlan Somers		compress)	prop=compression	;;
28292fae26bdSAlan Somers		rdonly)		prop=readonly		;;
28302fae26bdSAlan Somers		recsize)	prop=recordsize		;;
28312fae26bdSAlan Somers		reserv)		prop=reservation	;;
28322fae26bdSAlan Somers		refreserv)	prop=refreservation	;;
28332fae26bdSAlan Somers	esac
28342fae26bdSAlan Somers
28352fae26bdSAlan Somers	#
28362fae26bdSAlan Somers	# The zfs get output looks like the following
28372fae26bdSAlan Somers	#
28382fae26bdSAlan Somers
28392fae26bdSAlan Somers	#
28402fae26bdSAlan Somers	# The following properties are supported:
28412fae26bdSAlan Somers	#
28422fae26bdSAlan Somers	#	PROPERTY       EDIT  INHERIT   VALUES
28432fae26bdSAlan Somers	#
28442fae26bdSAlan Somers	#	available	NO	NO	<size>
28452fae26bdSAlan Somers	#	compressratio	NO	NO	<1.00x or higher if compressed>
28462fae26bdSAlan Somers	#	creation	NO	NO	<date>
28472fae26bdSAlan Somers	#	 ... ...
28482fae26bdSAlan Somers	#	zoned		YES	YES	on | off
28492fae26bdSAlan Somers	#
28502fae26bdSAlan Somers	# Sizes are specified in bytes with standard units such as K, M, G, etc.
28512fae26bdSAlan Somers	#
28522fae26bdSAlan Somers
28532fae26bdSAlan Somers	#
28542fae26bdSAlan Somers	# Start to extract property from the first blank line after 'PROPERTY'
28552fae26bdSAlan Somers	# and stop at the next blank line
28562fae26bdSAlan Somers	#
28572fae26bdSAlan Somers	$ZFS get 2>&1 | \
28582fae26bdSAlan Somers		$AWK '/PROPERTY/ {start=1; next}
28592fae26bdSAlan Somers			/Sizes/ {start=0}
28602fae26bdSAlan Somers		  	start==1 {print $1}' | \
28612fae26bdSAlan Somers		$GREP -w "$prop" > /dev/null 2>&1
28622fae26bdSAlan Somers
28632fae26bdSAlan Somers	return $?
28642fae26bdSAlan Somers}
28652fae26bdSAlan Somers
28662fae26bdSAlan Somers#
28672fae26bdSAlan Somers# Detect if the given pool property is supported in this release
28682fae26bdSAlan Somers#
28692fae26bdSAlan Somers# 0	Yes, it is supported
28702fae26bdSAlan Somers# !0	No, it is not supported
28712fae26bdSAlan Somers#
28722fae26bdSAlan Somersfunction pool_prop_exist
28732fae26bdSAlan Somers{
28742fae26bdSAlan Somers	typeset prop=$1
28752fae26bdSAlan Somers	if [[ -z $prop ]]; then
28762fae26bdSAlan Somers		log_fail "Usage: pool_prop_exist <property>"
28772fae26bdSAlan Somers
28782fae26bdSAlan Somers		return 1
28792fae26bdSAlan Somers	fi
28802fae26bdSAlan Somers	#
28812fae26bdSAlan Somers	# If the property is shortened column name,
28822fae26bdSAlan Somers	# convert it to the standard name
28832fae26bdSAlan Somers	#
28842fae26bdSAlan Somers	case $prop in
28852fae26bdSAlan Somers		avail)		prop=available		;;
28862fae26bdSAlan Somers		cap)		prop=capacity		;;
28872fae26bdSAlan Somers		replace)	prop=autoreplace	;;
28882fae26bdSAlan Somers	esac
28892fae26bdSAlan Somers
28902fae26bdSAlan Somers	#
28912fae26bdSAlan Somers	# The zpool get output looks like the following
28922fae26bdSAlan Somers	#
28932fae26bdSAlan Somers
28942fae26bdSAlan Somers	# usage:
28952fae26bdSAlan Somers	#	get <"all" | property[,...]> <pool> ...
28962fae26bdSAlan Somers	#
28972fae26bdSAlan Somers	# the following properties are supported:
28982fae26bdSAlan Somers	#
28992fae26bdSAlan Somers	#	PROPERTY       EDIT  VALUES
29002fae26bdSAlan Somers	#
29012fae26bdSAlan Somers	#	available	NO	<size>
29022fae26bdSAlan Somers	#	capacity	NO	<size>
29032fae26bdSAlan Somers	#	guid		NO	<guid>
29042fae26bdSAlan Somers	#	health		NO	<state>
29052fae26bdSAlan Somers	#	size		NO	<size>
29062fae26bdSAlan Somers	#	used		NO	<size>
29072fae26bdSAlan Somers	#	altroot		YES	<path>
29082fae26bdSAlan Somers	#	autoreplace	YES	on | off
29092fae26bdSAlan Somers	#	bootfs		YES	<filesystem>
29102fae26bdSAlan Somers	#	cachefile       YES	<file> | none
29112fae26bdSAlan Somers	#	delegation      YES	on | off
29122fae26bdSAlan Somers	#	failmode	YES	wait | continue | panic
29132fae26bdSAlan Somers	#	version		YES	<version>
29142fae26bdSAlan Somers
29152fae26bdSAlan Somers	$ZPOOL get 2>&1 | \
29162fae26bdSAlan Somers		$AWK '/PROPERTY/ {start=1; next}
29172fae26bdSAlan Somers			start==1 {print $1}' | \
29182fae26bdSAlan Somers		$GREP -w "$prop" > /dev/null 2>&1
29192fae26bdSAlan Somers
29202fae26bdSAlan Somers	return $?
29212fae26bdSAlan Somers}
29222fae26bdSAlan Somers
29232fae26bdSAlan Somers#
29242fae26bdSAlan Somers# check if the system was installed as zfsroot or not
29252fae26bdSAlan Somers# return: 0 ture, otherwise false
29262fae26bdSAlan Somers#
29272fae26bdSAlan Somersfunction is_zfsroot
29282fae26bdSAlan Somers{
29292fae26bdSAlan Somers	$DF -T / | $GREP -q zfs
29302fae26bdSAlan Somers}
29312fae26bdSAlan Somers
29322fae26bdSAlan Somers#
29332fae26bdSAlan Somers# get the root filesystem name if it's zfsroot system.
29342fae26bdSAlan Somers#
29352fae26bdSAlan Somers# return: root filesystem name
29362fae26bdSAlan Somersfunction get_rootfs
29372fae26bdSAlan Somers{
29382fae26bdSAlan Somers	typeset rootfs=""
29392fae26bdSAlan Somers	rootfs=$($MOUNT | $AWK '$3 == "\/" && $4~/zfs/ {print $1}')
29402fae26bdSAlan Somers	if [[ -z "$rootfs" ]]; then
29412fae26bdSAlan Somers		log_fail "Can not get rootfs"
29422fae26bdSAlan Somers	fi
29432fae26bdSAlan Somers	$ZFS list $rootfs > /dev/null 2>&1
29442fae26bdSAlan Somers	if (( $? == 0 )); then
29452fae26bdSAlan Somers		$ECHO $rootfs
29462fae26bdSAlan Somers	else
29472fae26bdSAlan Somers		log_fail "This is not a zfsroot system."
29482fae26bdSAlan Somers	fi
29492fae26bdSAlan Somers}
29502fae26bdSAlan Somers
29512fae26bdSAlan Somers#
29522fae26bdSAlan Somers# get the rootfs's pool name
29532fae26bdSAlan Somers# return:
29542fae26bdSAlan Somers#       rootpool name
29552fae26bdSAlan Somers#
29562fae26bdSAlan Somersfunction get_rootpool
29572fae26bdSAlan Somers{
29582fae26bdSAlan Somers	typeset rootfs=""
29592fae26bdSAlan Somers	typeset rootpool=""
29602fae26bdSAlan Somers	rootfs=$(get_rootfs)
29612fae26bdSAlan Somers	rootpool=`$ECHO $rootfs | awk -F\/ '{print $1}'`
29622fae26bdSAlan Somers	echo $rootpool
29632fae26bdSAlan Somers}
29642fae26bdSAlan Somers
29652fae26bdSAlan Somers#
29662fae26bdSAlan Somers# Get the sub string from specified source string
29672fae26bdSAlan Somers#
29682fae26bdSAlan Somers# $1 source string
29692fae26bdSAlan Somers# $2 start position. Count from 1
29702fae26bdSAlan Somers# $3 offset
29712fae26bdSAlan Somers#
29722fae26bdSAlan Somersfunction get_substr #src_str pos offset
29732fae26bdSAlan Somers{
29742fae26bdSAlan Somers	typeset pos offset
29752fae26bdSAlan Somers
29762fae26bdSAlan Somers	$ECHO $1 | \
29772fae26bdSAlan Somers		$NAWK -v pos=$2 -v offset=$3 '{print substr($0, pos, offset)}'
29782fae26bdSAlan Somers}
29792fae26bdSAlan Somers
29802fae26bdSAlan Somers#
29812fae26bdSAlan Somers# Get the directory path of given device
29822fae26bdSAlan Somers#
29832fae26bdSAlan Somersfunction get_device_dir #device
29842fae26bdSAlan Somers{
29852fae26bdSAlan Somers	typeset device=$1
29862fae26bdSAlan Somers
29872fae26bdSAlan Somers	$ECHO "/dev"
29882fae26bdSAlan Somers}
29892fae26bdSAlan Somers
29902fae26bdSAlan Somers#
29912fae26bdSAlan Somers# Get the package name
29922fae26bdSAlan Somers#
29932fae26bdSAlan Somersfunction get_package_name
29942fae26bdSAlan Somers{
29952fae26bdSAlan Somers	typeset dirpath=${1:-$STC_NAME}
29962fae26bdSAlan Somers
29972fae26bdSAlan Somers	print "SUNWstc-${dirpath}" | /usr/bin/sed -e "s/\//-/g"
29982fae26bdSAlan Somers}
29992fae26bdSAlan Somers
30002fae26bdSAlan Somers#
30012fae26bdSAlan Somers# Get the word numbers from a string separated by white space
30022fae26bdSAlan Somers#
30032fae26bdSAlan Somersfunction get_word_count
30042fae26bdSAlan Somers{
30052fae26bdSAlan Somers	$ECHO $1 | $WC -w
30062fae26bdSAlan Somers}
30072fae26bdSAlan Somers
30082fae26bdSAlan Somers#
30092fae26bdSAlan Somers# To verify if the require numbers of disks is given
30102fae26bdSAlan Somers#
30112fae26bdSAlan Somersfunction verify_disk_count
30122fae26bdSAlan Somers{
30132fae26bdSAlan Somers	typeset -i min=${2:-1}
30142fae26bdSAlan Somers
30152fae26bdSAlan Somers	typeset -i count=$(get_word_count "$1")
30162fae26bdSAlan Somers
30172fae26bdSAlan Somers	if (( count < min )); then
30182fae26bdSAlan Somers		atf_skip "A minimum of $min disks is required to run." \
30192fae26bdSAlan Somers			" You specified $count disk(s)"
30202fae26bdSAlan Somers	fi
30212fae26bdSAlan Somers}
30222fae26bdSAlan Somers
30232fae26bdSAlan Somers#
30242fae26bdSAlan Somers# Verify that vfs.zfs.vol.recursive is set, so pools can be created using zvols
30252fae26bdSAlan Somers# as backing stores.
30262fae26bdSAlan Somers#
30272fae26bdSAlan Somersfunction verify_zvol_recursive
30282fae26bdSAlan Somers{
30292fae26bdSAlan Somers	if [ "`sysctl -n vfs.zfs.vol.recursive`" -ne 1 ]; then
30302fae26bdSAlan Somers		atf_skip "Recursive ZVOLs not enabled"
30312fae26bdSAlan Somers	fi
30322fae26bdSAlan Somers}
30332fae26bdSAlan Somers
30342fae26bdSAlan Somers#
30352fae26bdSAlan Somers# bsdmap disk/slice number to a device path
30362fae26bdSAlan Somers#
30372fae26bdSAlan Somersfunction bsddevmap
30382fae26bdSAlan Somers{
30392fae26bdSAlan Somers	typeset arg=$1
30402fae26bdSAlan Somers	echo $arg | egrep "*s[0-9]$" > /dev/null 2>&1
30412fae26bdSAlan Somers	if [ $? -eq 0 ]
30422fae26bdSAlan Somers	then
30432fae26bdSAlan Somers		n=`echo $arg| wc -c`
30442fae26bdSAlan Somers		set -A map a b c d e f g h i j
30452fae26bdSAlan Somers		s=`echo $arg | cut -c $((n-1))`
30462fae26bdSAlan Somers		arg=${arg%s[0-9]}${map[$s]}
30472fae26bdSAlan Somers	fi
30482fae26bdSAlan Somers	echo $arg
30492fae26bdSAlan Somers}
30502fae26bdSAlan Somers
30512fae26bdSAlan Somers#
30522fae26bdSAlan Somers# Get the name of the snapshots directory.  Traditionally .zfs/snapshots
30532fae26bdSAlan Somers#
30542fae26bdSAlan Somersfunction get_snapdir_name
30552fae26bdSAlan Somers{
30562fae26bdSAlan Somers	echo ".zfs/snapshot"
30572fae26bdSAlan Somers}
30582fae26bdSAlan Somers
30592fae26bdSAlan Somers#
30602fae26bdSAlan Somers# Unmount all ZFS filesystems except for those that are in the KEEP variable
30612fae26bdSAlan Somers#
30622fae26bdSAlan Somersfunction unmount_all_safe
30632fae26bdSAlan Somers{
30642fae26bdSAlan Somers	echo $(all_pools) | \
30652fae26bdSAlan Somers		$XARGS -n 1 $ZFS list -H -o name -t all -r | \
30662fae26bdSAlan Somers		$XARGS -n 1 $ZFS unmount
30672fae26bdSAlan Somers}
30682fae26bdSAlan Somers
30692fae26bdSAlan Somers#
30702fae26bdSAlan Somers# Return the highest pool version that this OS can create
30712fae26bdSAlan Somers#
30722fae26bdSAlan Somersfunction get_zpool_version
30732fae26bdSAlan Somers{
30742fae26bdSAlan Somers	# We assume output from zpool upgrade -v of the form:
30752fae26bdSAlan Somers	#
30762fae26bdSAlan Somers	# This system is currently running ZFS version 2.
30772fae26bdSAlan Somers	# .
30782fae26bdSAlan Somers	# .
30792fae26bdSAlan Somers	typeset ZPOOL_VERSION=$($ZPOOL upgrade -v | $HEAD -1 | \
30802fae26bdSAlan Somers		$AWK '{print $NF}' | $SED -e 's/\.//g')
30812fae26bdSAlan Somers	# Starting with version 5000, the output format changes to:
30822fae26bdSAlan Somers	# This system supports ZFS pool feature flags.
30832fae26bdSAlan Somers	# .
30842fae26bdSAlan Somers	# .
30852fae26bdSAlan Somers	if [[ $ZPOOL_VERSION = "flags" ]]; then
30862fae26bdSAlan Somers		ZPOOL_VERSION=5000
30872fae26bdSAlan Somers	fi
30882fae26bdSAlan Somers	echo $ZPOOL_VERSION
30892fae26bdSAlan Somers}
30902fae26bdSAlan Somers
30912fae26bdSAlan Somers# Ensures that zfsd is running, starting it if necessary.  Every test that
30922fae26bdSAlan Somers# interacts with zfsd must call this at startup.  This is intended primarily
30932fae26bdSAlan Somers# to eliminate interference from outside the test suite.
30942fae26bdSAlan Somersfunction ensure_zfsd_running
30952fae26bdSAlan Somers{
30962fae26bdSAlan Somers	if ! service zfsd status > /dev/null 2>&1; then
30972fae26bdSAlan Somers		service zfsd start || service zfsd onestart
30982fae26bdSAlan Somers		service zfsd status > /dev/null 2>&1 ||
30992fae26bdSAlan Somers			log_unsupported "Test requires zfsd"
31002fae26bdSAlan Somers	fi
31012fae26bdSAlan Somers}
31022fae26bdSAlan Somers
31032fae26bdSAlan Somers# Temporarily stops ZFSD, because it can interfere with some tests.  If this
31042fae26bdSAlan Somers# function is used, then restart_zfsd _must_ be called in the cleanup routine.
31052fae26bdSAlan Somersfunction stop_zfsd
31062fae26bdSAlan Somers{
31072fae26bdSAlan Somers	$RM -f $TMPDIR/.zfsd_enabled_during_stf_zfs_tests
31082fae26bdSAlan Somers	if [[ -n "$ZFSD" && -x "$ZFSD" ]]; then
31092fae26bdSAlan Somers		if /etc/rc.d/zfsd status > /dev/null; then
31102fae26bdSAlan Somers			log_note "Stopping zfsd"
31112fae26bdSAlan Somers			$TOUCH $TMPDIR/.zfsd_enabled_during_stf_zfs_tests
31122fae26bdSAlan Somers			/etc/rc.d/zfsd stop || /etc/rc.d/zfsd onestop
31132fae26bdSAlan Somers		fi
31142fae26bdSAlan Somers	fi
31152fae26bdSAlan Somers}
31162fae26bdSAlan Somers
31172fae26bdSAlan Somers# Restarts zfsd after it has been stopped by stop_zfsd.  Intelligently restarts
31182fae26bdSAlan Somers# only iff zfsd was running at the time stop_zfsd was called.
31192fae26bdSAlan Somersfunction restart_zfsd
31202fae26bdSAlan Somers{
31212fae26bdSAlan Somers	if [[ -f $TMPDIR/.zfsd_enabled_during_stf_zfs_tests ]]; then
31222fae26bdSAlan Somers		log_note "Restarting zfsd"
31232fae26bdSAlan Somers		/etc/rc.d/zfsd start || /etc/rc.d/zfsd onestart
31242fae26bdSAlan Somers	fi
31252fae26bdSAlan Somers	$RM -f $TMPDIR/.zfsd_enabled_during_stf_zfs_tests
31262fae26bdSAlan Somers}
31272fae26bdSAlan Somers
31282fae26bdSAlan Somers#
31292fae26bdSAlan Somers# Using the given <vdev>, obtain the value of the property <propname> for
31302fae26bdSAlan Somers# the given <tvd> identified by numeric id.
31312fae26bdSAlan Somers#
31322fae26bdSAlan Somersfunction get_tvd_prop # vdev tvd propname
31332fae26bdSAlan Somers{
31342fae26bdSAlan Somers	typeset vdev=$1
31352fae26bdSAlan Somers	typeset -i tvd=$2
31362fae26bdSAlan Somers	typeset propname=$3
31372fae26bdSAlan Somers
31382fae26bdSAlan Somers	$ZDB -l $vdev | $AWK -v tvd=$tvd -v prop="${propname}:" '
31392fae26bdSAlan Somers		BEGIN { start = 0; }
31402fae26bdSAlan Somers		/^        id:/ && ($2==tvd) { start = 1; next; }
31412fae26bdSAlan Somers		(start==0) { next; }
31422fae26bdSAlan Somers		/^        [a-z]+/ && ($1==prop) { print $2; exit; }
31432fae26bdSAlan Somers		/^        children/ { exit; }
31442fae26bdSAlan Somers		'
31452fae26bdSAlan Somers}
31462fae26bdSAlan Somers
31472fae26bdSAlan Somers#
31482fae26bdSAlan Somers# Convert a DVA into a physical block address.  Prints number of blocks.
31492fae26bdSAlan Somers# This takes the usual printed form, in which offsets are left shifted so
31502fae26bdSAlan Somers# they represent bytes rather than the native sector count.
31512fae26bdSAlan Somers#
31522fae26bdSAlan Somersfunction dva_to_block_addr # dva
31532fae26bdSAlan Somers{
31542fae26bdSAlan Somers	typeset dva=$1
31552fae26bdSAlan Somers
31562fae26bdSAlan Somers	typeset offcol=$(echo $dva | cut -f2 -d:)
31572fae26bdSAlan Somers	typeset -i offset="0x${offcol}"
31582fae26bdSAlan Somers	# First add 4MB to skip the boot blocks and first two vdev labels,
31592fae26bdSAlan Somers	# then convert to 512 byte blocks (for use with dd).  Note that this
31602fae26bdSAlan Somers	# differs from simply adding 8192 blocks, since the input offset is
31612fae26bdSAlan Somers	# given in bytes and has the actual ashift baked in.
31622fae26bdSAlan Somers	(( offset += 4*1024*1024 ))
31632fae26bdSAlan Somers	(( offset >>= 9 ))
31642fae26bdSAlan Somers	echo "$offset"
31652fae26bdSAlan Somers}
31662fae26bdSAlan Somers
31672fae26bdSAlan Somers#
31682fae26bdSAlan Somers# Convert a RAIDZ DVA into a physical block address.  This has the same
31692fae26bdSAlan Somers# output as dva_to_block_addr (number of blocks from beginning of device), but
31702fae26bdSAlan Somers# is more complicated due to RAIDZ.  ashift is normally always 9, but RAIDZ
31712fae26bdSAlan Somers# uses the actual tvd ashift instead.  Furthermore, the number of vdevs changes
31722fae26bdSAlan Somers# the actual block for each device.
31732fae26bdSAlan Somers#
31742fae26bdSAlan Somersfunction raidz_dva_to_block_addr # dva ncols ashift
31752fae26bdSAlan Somers{
31762fae26bdSAlan Somers	typeset dva=$1
31772fae26bdSAlan Somers	typeset -i ncols=$2
31782fae26bdSAlan Somers        typeset -i ashift=$3
31792fae26bdSAlan Somers
31802fae26bdSAlan Somers	typeset -i offset=0x$(echo $dva | cut -f2 -d:)
31812fae26bdSAlan Somers	(( offset >>= ashift ))
31822fae26bdSAlan Somers
31832fae26bdSAlan Somers	typeset -i ioff=$(( (offset + ncols - 1) / ncols  ))
31842fae26bdSAlan Somers
31852fae26bdSAlan Somers	# Now add the front 4MB and return.
31862fae26bdSAlan Somers	(( ioff += ( 4194304 >> $ashift ) ))
31872fae26bdSAlan Somers	echo "$ioff"
31882fae26bdSAlan Somers}
31892fae26bdSAlan Somers
31902fae26bdSAlan Somers#
31912fae26bdSAlan Somers# Return the vdevs for the given toplevel vdev number.
31922fae26bdSAlan Somers# Child vdevs will only be included if they are ONLINE.  Output format:
31932fae26bdSAlan Somers#
31942fae26bdSAlan Somers#   <toplevel vdev type> <nchildren> <child1>[:<child2> ...]
31952fae26bdSAlan Somers#
31962fae26bdSAlan Somers# Valid toplevel vdev types are mirror, raidz[1-3], leaf (which can be a
31972fae26bdSAlan Somers# disk or a file).  Note that 'nchildren' can be larger than the number of
31982fae26bdSAlan Somers# returned children; it represents the number of children regardless of how
31992fae26bdSAlan Somers# many are actually online.
32002fae26bdSAlan Somers#
32012fae26bdSAlan Somersfunction vdevs_for_tvd # pool tvd
32022fae26bdSAlan Somers{
32032fae26bdSAlan Somers	typeset pool=$1
32042fae26bdSAlan Somers	typeset -i tvd=$2
32052fae26bdSAlan Somers
32062fae26bdSAlan Somers	$ZPOOL status $pool | $AWK -v want_tvd=$tvd '
32072fae26bdSAlan Somers		BEGIN {
32082fae26bdSAlan Somers			 start = 0; tvd = -1; lvd = -1;
32092fae26bdSAlan Somers			 type = "UNKNOWN"; disks = ""; disk = "";
32102fae26bdSAlan Somers			 nchildren = 0;
32112fae26bdSAlan Somers		}
32122fae26bdSAlan Somers		/NAME.*STATE/ { start = 1; next; }
32132fae26bdSAlan Somers		(start==0) { next; }
32142fae26bdSAlan Somers
32152fae26bdSAlan Somers		(tvd > want_tvd) { exit; }
32162fae26bdSAlan Somers		END { print type " " nchildren " " disks; }
32172fae26bdSAlan Somers
32182fae26bdSAlan Somers		length(disk) > 0 {
32192fae26bdSAlan Somers			if (length(disks) > 0) { disks = disks " "; }
32202fae26bdSAlan Somers			if (substr(disk, 0, 1) == "/") {
32212fae26bdSAlan Somers				disks = disks disk;
32222fae26bdSAlan Somers			} else {
32232fae26bdSAlan Somers				disks = disks "/dev/" disk;
32242fae26bdSAlan Somers			}
32252fae26bdSAlan Somers			disk = "";
32262fae26bdSAlan Somers		}
32272fae26bdSAlan Somers
32282fae26bdSAlan Somers		/^\t(spares|logs)/ { tvd = want_tvd + 1; next; }
32292fae26bdSAlan Somers		/^\t  (mirror|raidz[1-3])-[0-9]+/ {
32302fae26bdSAlan Somers			tvd += 1;
32312fae26bdSAlan Somers			(tvd == want_tvd) && type = substr($1, 0, 6);
32322fae26bdSAlan Somers			next;
32332fae26bdSAlan Somers		}
32342fae26bdSAlan Somers		/^\t  [\/A-Za-z]+/ {
32352fae26bdSAlan Somers			tvd += 1;
32362fae26bdSAlan Somers			if (tvd == want_tvd) {
32372fae26bdSAlan Somers				(( nchildren += 1 ))
32382fae26bdSAlan Somers				type = "leaf";
32392fae26bdSAlan Somers				($2 == "ONLINE") && disk = $1;
32402fae26bdSAlan Somers			}
32412fae26bdSAlan Somers			next;
32422fae26bdSAlan Somers		}
32432fae26bdSAlan Somers
32442fae26bdSAlan Somers		(tvd < want_tvd) { next; }
32452fae26bdSAlan Somers
32462fae26bdSAlan Somers		/^\t    spare-[0-9]+/ { next; }
32472fae26bdSAlan Somers		/^\t      [\/A-Za-z]+/ {
32482fae26bdSAlan Somers			(( nchildren += 1 ))
32492fae26bdSAlan Somers			($2 == "ONLINE") && disk = $1;
32502fae26bdSAlan Somers			next;
32512fae26bdSAlan Somers		}
32522fae26bdSAlan Somers
32532fae26bdSAlan Somers		/^\t    [\/A-Za-z]+/ {
32542fae26bdSAlan Somers			(( nchildren += 1 ))
32552fae26bdSAlan Somers			($2 == "ONLINE") && disk = $1;
32562fae26bdSAlan Somers			next;
32572fae26bdSAlan Somers		}
32582fae26bdSAlan Somers		'
32592fae26bdSAlan Somers}
32602fae26bdSAlan Somers
32612fae26bdSAlan Somers#
32622fae26bdSAlan Somers# Get a vdev path, ashift & offset for a given pool/dataset and DVA.
32632fae26bdSAlan Somers# If desired, can also select the toplevel vdev child number.
32642fae26bdSAlan Somers#
32652fae26bdSAlan Somersfunction dva_to_vdev_ashift_off # pool/dataset dva [leaf_vdev_num]
32662fae26bdSAlan Somers{
32672fae26bdSAlan Somers	typeset poollike=$1
32682fae26bdSAlan Somers	typeset dva=$2
32692fae26bdSAlan Somers	typeset -i leaf_vdev_num=$3
32702fae26bdSAlan Somers
32712fae26bdSAlan Somers	# vdevs are normally 0-indexed while arguments are 1-indexed.
32722fae26bdSAlan Somers	(( leaf_vdev_num += 1 ))
32732fae26bdSAlan Somers
32742fae26bdSAlan Somers	# Strip any child datasets or snapshots.
32752fae26bdSAlan Somers	pool=$(echo $poollike | sed -e 's,[/@].*,,g')
32762fae26bdSAlan Somers	tvd=$(echo $dva | cut -d: -f1)
32772fae26bdSAlan Somers
32782fae26bdSAlan Somers	set -- $(vdevs_for_tvd $pool $tvd)
32792fae26bdSAlan Somers	log_debug "vdevs_for_tvd: $* <EOM>"
32802fae26bdSAlan Somers	tvd_type=$1; shift
32812fae26bdSAlan Somers	nchildren=$1; shift
32822fae26bdSAlan Somers
32832fae26bdSAlan Somers	lvd=$(eval echo \$$leaf_vdev_num)
32842fae26bdSAlan Somers	log_debug "type='$tvd_type' children='$nchildren' lvd='$lvd' dva='$dva'"
32852fae26bdSAlan Somers	case $tvd_type in
32862fae26bdSAlan Somers	raidz*)
32872fae26bdSAlan Somers		ashift=$(get_tvd_prop $lvd $tvd ashift)
32882fae26bdSAlan Somers		log_debug "raidz: ashift='${ashift}'"
32892fae26bdSAlan Somers		off=$(raidz_dva_to_block_addr $dva $nchildren $ashift)
32902fae26bdSAlan Somers		;;
32912fae26bdSAlan Somers	*)
32922fae26bdSAlan Somers		ashift=9
32932fae26bdSAlan Somers		off=$(dva_to_block_addr $dva)
32942fae26bdSAlan Somers		;;
32952fae26bdSAlan Somers	esac
32962fae26bdSAlan Somers	echo "${lvd}:${ashift}:${off}"
32972fae26bdSAlan Somers}
32982fae26bdSAlan Somers
32992fae26bdSAlan Somers#
33002fae26bdSAlan Somers# Get the DVA for the specified dataset's given filepath.
33012fae26bdSAlan Somers#
33022fae26bdSAlan Somersfunction file_dva # dataset filepath [level] [offset] [dva_num]
33032fae26bdSAlan Somers{
33042fae26bdSAlan Somers	typeset dataset=$1
33052fae26bdSAlan Somers	typeset filepath=$2
33062fae26bdSAlan Somers	typeset -i level=$3
33072fae26bdSAlan Somers	typeset -i offset=$4
33082fae26bdSAlan Somers	typeset -i dva_num=$5
33092fae26bdSAlan Somers
33102fae26bdSAlan Somers	typeset -li blksz=0
33112fae26bdSAlan Somers	typeset -li blknum=0
33122fae26bdSAlan Somers	typeset -li startoff
33132fae26bdSAlan Somers	typeset -li inode
33142fae26bdSAlan Somers
33152fae26bdSAlan Somers	eval `$STAT -s "$filepath"`
33162fae26bdSAlan Somers	inode="$st_ino"
33172fae26bdSAlan Somers
33182fae26bdSAlan Somers	# The inner match is for 'DVA[0]=<0:1b412600:200>', in which the
33192fae26bdSAlan Somers	# text surrounding the actual DVA is a fixed size with 8 characters
33202fae26bdSAlan Somers	# before it and 1 after.
3321c43f30eeSAlan Somers	$ZDB -P -vvvvv "$dataset/" $inode | \
33222fae26bdSAlan Somers	    $AWK -v level=${level} -v dva_num=${dva_num} '
33232fae26bdSAlan Somers		BEGIN { stage = 0; }
33242fae26bdSAlan Somers		(stage == 0) && ($1=="Object") { stage = 1; next; }
33252fae26bdSAlan Somers
33262fae26bdSAlan Somers		(stage == 1) {
33272fae26bdSAlan Somers			print $3 " " $4;
33282fae26bdSAlan Somers			stage = 2; next;
33292fae26bdSAlan Somers		}
33302fae26bdSAlan Somers
33312fae26bdSAlan Somers		(stage == 2) && /^Indirect blocks/ { stage=3; next; }
33322fae26bdSAlan Somers		(stage < 3) { next; }
33332fae26bdSAlan Somers
33342fae26bdSAlan Somers		match($2, /L[0-9]/) {
33352fae26bdSAlan Somers			if (substr($2, RSTART+1, RLENGTH-1) != level) { next; }
33362fae26bdSAlan Somers		}
33372fae26bdSAlan Somers		match($3, /DVA\[.*>/) {
33382fae26bdSAlan Somers			dva = substr($3, RSTART+8, RLENGTH-9);
33392fae26bdSAlan Somers			if (substr($3, RSTART+4, 1) == dva_num) {
33402fae26bdSAlan Somers				print $1 " " dva;
33412fae26bdSAlan Somers			}
33422fae26bdSAlan Somers		}
33432fae26bdSAlan Somers		' | \
33442fae26bdSAlan Somers	while read line; do
33452fae26bdSAlan Somers		log_debug "params='$blksz/$blknum/$startoff' line='$line'"
33462fae26bdSAlan Somers		if (( blksz == 0 )); then
33472fae26bdSAlan Somers			typeset -i iblksz=$(echo $line | cut -d " " -f1)
33482fae26bdSAlan Somers			typeset -i dblksz=$(echo $line | cut -d " " -f2)
33492fae26bdSAlan Somers
33502fae26bdSAlan Somers			# Calculate the actual desired block starting offset.
33512fae26bdSAlan Somers			if (( level > 0 )); then
33522fae26bdSAlan Somers				typeset -i nbps_per_level
33532fae26bdSAlan Somers				typeset -i indsz
33542fae26bdSAlan Somers				typeset -i i=0
33552fae26bdSAlan Somers
33562fae26bdSAlan Somers				(( nbps_per_level = iblksz / 128 ))
33572fae26bdSAlan Somers				(( blksz = dblksz ))
33582fae26bdSAlan Somers				for (( i = 0; $i < $level; i++ )); do
33592fae26bdSAlan Somers					(( blksz *= nbps_per_level ))
33602fae26bdSAlan Somers				done
33612fae26bdSAlan Somers			else
33622fae26bdSAlan Somers				blksz=$dblksz
33632fae26bdSAlan Somers			fi
33642fae26bdSAlan Somers
33652fae26bdSAlan Somers			(( blknum = offset / blksz ))
33662fae26bdSAlan Somers			(( startoff = blknum * blksz ))
33672fae26bdSAlan Somers			continue
33682fae26bdSAlan Somers		fi
33692fae26bdSAlan Somers
33702fae26bdSAlan Somers		typeset lineoffstr=$(echo $line | cut -d " " -f1)
33712fae26bdSAlan Somers		typeset -i lineoff=$(printf "%d" "0x${lineoffstr}")
33722fae26bdSAlan Somers		typeset dva="$(echo $line | cut -d " " -f2)"
33732fae26bdSAlan Somers		log_debug "str='$lineoffstr' lineoff='$lineoff' dva='$dva'"
33742fae26bdSAlan Somers		if [[ -n "$dva" ]] && (( lineoff == startoff )); then
33752fae26bdSAlan Somers			echo $line | cut -d " " -f2
33762fae26bdSAlan Somers			return 0
33772fae26bdSAlan Somers		fi
33782fae26bdSAlan Somers	done
33792fae26bdSAlan Somers	return 1
33802fae26bdSAlan Somers}
33812fae26bdSAlan Somers
33822fae26bdSAlan Somers#
33832fae26bdSAlan Somers# Corrupt the given dataset's filepath file.  This will obtain the first
33842fae26bdSAlan Somers# level 0 block's DVA and scribble random bits on it.
33852fae26bdSAlan Somers#
33862fae26bdSAlan Somersfunction corrupt_file # dataset filepath [leaf_vdev_num]
33872fae26bdSAlan Somers{
33882fae26bdSAlan Somers	typeset dataset=$1
33892fae26bdSAlan Somers	typeset filepath=$2
33902fae26bdSAlan Somers	typeset -i leaf_vdev_num="$3"
33912fae26bdSAlan Somers
33922fae26bdSAlan Somers	dva=$(file_dva $dataset $filepath)
33932fae26bdSAlan Somers	[ $? -ne 0 ] && log_fail "ERROR: Can't find file $filepath on $dataset"
33942fae26bdSAlan Somers
33952fae26bdSAlan Somers	vdoff=$(dva_to_vdev_ashift_off $dataset $dva $leaf_vdev_num)
33962fae26bdSAlan Somers	vdev=$(echo $vdoff | cut -d: -f1)
33972fae26bdSAlan Somers	ashift=$(echo $vdoff | cut -d: -f2)
33982fae26bdSAlan Somers	off=$(echo $vdoff | cut -d: -f3)
33992fae26bdSAlan Somers	blocksize=$(( 1 << $ashift ))
34002fae26bdSAlan Somers
34012fae26bdSAlan Somers	log_note "Corrupting ${dataset}'s $filepath on $vdev at DVA $dva with ashift $ashift"
34022fae26bdSAlan Somers	log_must $DD if=/dev/urandom bs=$blocksize of=$vdev seek=$off count=1 conv=notrunc
34032fae26bdSAlan Somers}
34042fae26bdSAlan Somers
34052fae26bdSAlan Somers#
34062fae26bdSAlan Somers# Given a number of files, this function will iterate through
34072fae26bdSAlan Somers# the loop creating the specified number of files, whose names
34082fae26bdSAlan Somers# will start with <basename>.
34092fae26bdSAlan Somers#
34102fae26bdSAlan Somers# The <data> argument is special: it can be "ITER", in which case
34112fae26bdSAlan Somers# the -d argument will be the value of the current iteration.  It
34122fae26bdSAlan Somers# can be 0, in which case it will always be 0.  Otherwise, it will
34132fae26bdSAlan Somers# always be the given value.
34142fae26bdSAlan Somers#
34152fae26bdSAlan Somers# If <snapbase> is specified, a snapshot will be taken using the
34162fae26bdSAlan Somers# argument as the snapshot basename.
34172fae26bdSAlan Somers#
34182fae26bdSAlan Somersfunction populate_dir # basename num_files write_count blocksz data snapbase
34192fae26bdSAlan Somers{
34202fae26bdSAlan Somers	typeset basename=$1
34212fae26bdSAlan Somers	typeset -i num_files=$2
34222fae26bdSAlan Somers	typeset -i write_count=$3
34232fae26bdSAlan Somers	typeset -i blocksz=$4
34242fae26bdSAlan Somers	typeset -i i
34252fae26bdSAlan Somers	typeset data=$5
34262fae26bdSAlan Somers	typeset snapbase="$6"
34272fae26bdSAlan Somers
34282fae26bdSAlan Somers	log_note "populate_dir: data='$data'"
34292fae26bdSAlan Somers	for (( i = 0; i < num_files; i++ )); do
34302fae26bdSAlan Somers		case "$data" in
34312fae26bdSAlan Somers		0)	d=0	;;
34322fae26bdSAlan Somers		ITER)	d=$i ;;
34332fae26bdSAlan Somers		*)	d=$data	;;
34342fae26bdSAlan Somers		esac
34352fae26bdSAlan Somers
34362fae26bdSAlan Somers        	log_must $FILE_WRITE -o create -c $write_count \
34372fae26bdSAlan Somers		    -f ${basename}.$i -b $blocksz -d $d
34382fae26bdSAlan Somers
34392fae26bdSAlan Somers		[ -n "$snapbase" ] && log_must $ZFS snapshot ${snapbase}.${i}
34402fae26bdSAlan Somers	done
34412fae26bdSAlan Somers}
34422fae26bdSAlan Somers
34432fae26bdSAlan Somers# Reap all children registered in $child_pids.
34442fae26bdSAlan Somersfunction reap_children
34452fae26bdSAlan Somers{
34462fae26bdSAlan Somers	[ -z "$child_pids" ] && return
34472fae26bdSAlan Somers	for wait_pid in $child_pids; do
34482fae26bdSAlan Somers		log_must $KILL $wait_pid
34492fae26bdSAlan Somers	done
34502fae26bdSAlan Somers	child_pids=""
34512fae26bdSAlan Somers}
34522fae26bdSAlan Somers
34532fae26bdSAlan Somers# Busy a path.  Expects to be reaped via reap_children.  Tries to run as
34542fae26bdSAlan Somers# long and slowly as possible.  [num] is taken as a hint; if such a file
34552fae26bdSAlan Somers# already exists a different one will be chosen.
34562fae26bdSAlan Somersfunction busy_path # <path> [num]
34572fae26bdSAlan Somers{
34582fae26bdSAlan Somers	typeset busypath=$1
34592fae26bdSAlan Somers	typeset -i num=$2
34602fae26bdSAlan Somers
34612fae26bdSAlan Somers	while :; do
34622fae26bdSAlan Somers		busyfile="$busypath/busyfile.${num}"
34632fae26bdSAlan Somers		[ ! -f "$busyfile" ] && break
34642fae26bdSAlan Somers	done
34652fae26bdSAlan Somers
34662fae26bdSAlan Somers	cmd="$DD if=/dev/urandom of=$busyfile bs=512"
34672fae26bdSAlan Somers	( cd $busypath && $cmd ) &
34682fae26bdSAlan Somers	typeset pid=$!
34692fae26bdSAlan Somers	$SLEEP 1
34702fae26bdSAlan Somers	log_must $PS -p $pid
34712fae26bdSAlan Somers	child_pids="$child_pids $pid"
34722fae26bdSAlan Somers}
3473