1eda14cbcSMatt Macy# 2eda14cbcSMatt Macy# CDDL HEADER START 3eda14cbcSMatt Macy# 4eda14cbcSMatt Macy# The contents of this file are subject to the terms of the 5eda14cbcSMatt Macy# Common Development and Distribution License (the "License"). 6eda14cbcSMatt Macy# You may not use this file except in compliance with the License. 7eda14cbcSMatt Macy# 8eda14cbcSMatt Macy# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9271171e0SMartin Matuska# or https://opensource.org/licenses/CDDL-1.0. 10eda14cbcSMatt Macy# See the License for the specific language governing permissions 11eda14cbcSMatt Macy# and limitations under the License. 12eda14cbcSMatt Macy# 13eda14cbcSMatt Macy# When distributing Covered Code, include this CDDL HEADER in each 14eda14cbcSMatt Macy# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15eda14cbcSMatt Macy# If applicable, add the following below this CDDL HEADER, with the 16eda14cbcSMatt Macy# fields enclosed by brackets "[]" replaced with your own identifying 17eda14cbcSMatt Macy# information: Portions Copyright [yyyy] [name of copyright owner] 18eda14cbcSMatt Macy# 19eda14cbcSMatt Macy# CDDL HEADER END 20eda14cbcSMatt Macy# 21eda14cbcSMatt Macy 22eda14cbcSMatt Macy# 23eda14cbcSMatt Macy# Copyright (c) 2009, Sun Microsystems Inc. All rights reserved. 24eda14cbcSMatt Macy# Copyright (c) 2012, 2020, Delphix. All rights reserved. 25eda14cbcSMatt Macy# Copyright (c) 2017, Tim Chase. All rights reserved. 26eda14cbcSMatt Macy# Copyright (c) 2017, Nexenta Systems Inc. All rights reserved. 27eda14cbcSMatt Macy# Copyright (c) 2017, Lawrence Livermore National Security LLC. 28eda14cbcSMatt Macy# Copyright (c) 2017, Datto Inc. All rights reserved. 29eda14cbcSMatt Macy# Copyright (c) 2017, Open-E Inc. All rights reserved. 3021b492edSMartin Matuska# Copyright (c) 2021, The FreeBSD Foundation. 31*c6767dc1SMartin Matuska# Copyright (c) 2025, Klara, Inc. 32eda14cbcSMatt Macy# Use is subject to license terms. 33eda14cbcSMatt Macy# 34eda14cbcSMatt Macy 35716fd348SMartin Matuska. ${STF_SUITE}/include/tunables.cfg 36716fd348SMartin Matuska 37eda14cbcSMatt Macy. ${STF_TOOLS}/include/logapi.shlib 38eda14cbcSMatt Macy. ${STF_SUITE}/include/math.shlib 39eda14cbcSMatt Macy. ${STF_SUITE}/include/blkdev.shlib 40eda14cbcSMatt Macy 41*c6767dc1SMartin Matuska 42a2b560ccSMartin Matuska# On AlmaLinux 9 we will see $PWD = '.' instead of the full path. This causes 43a2b560ccSMartin Matuska# some tests to fail. Fix it up here. 44a2b560ccSMartin Matuskaif [ "$PWD" = "." ] ; then 45a2b560ccSMartin Matuska PWD="$(readlink -f $PWD)" 46a2b560ccSMartin Matuskafi 47a2b560ccSMartin Matuska 48eda14cbcSMatt Macy# 49eda14cbcSMatt Macy# Apply constrained path when available. This is required since the 50eda14cbcSMatt Macy# PATH may have been modified by sudo's secure_path behavior. 51eda14cbcSMatt Macy# 52eda14cbcSMatt Macyif [ -n "$STF_PATH" ]; then 539db44a8eSMartin Matuska export PATH="$STF_PATH" 54eda14cbcSMatt Macyfi 55eda14cbcSMatt Macy 56eda14cbcSMatt Macy# 57eda14cbcSMatt Macy# Generic dot version comparison function 58eda14cbcSMatt Macy# 59eda14cbcSMatt Macy# Returns success when version $1 is greater than or equal to $2. 60eda14cbcSMatt Macy# 61eda14cbcSMatt Macyfunction compare_version_gte 62eda14cbcSMatt Macy{ 63716fd348SMartin Matuska [ "$(printf "$1\n$2" | sort -V | tail -n1)" = "$1" ] 64eda14cbcSMatt Macy} 65eda14cbcSMatt Macy 664fefe1b7SMartin Matuska# Helper function used by linux_version() and freebsd_version() 6775e1fea6SMartin Matuska# $1, if provided, should be a MAJOR, MAJOR.MINOR or MAJOR.MINOR.PATCH 6875e1fea6SMartin Matuska# version number 694fefe1b7SMartin Matuskafunction kernel_version 70eda14cbcSMatt Macy{ 71eda14cbcSMatt Macy typeset ver="$1" 72eda14cbcSMatt Macy 7375e1fea6SMartin Matuska [ -z "$ver" ] && case "$UNAME" in 7475e1fea6SMartin Matuska Linux) 7575e1fea6SMartin Matuska # Linux version numbers are X.Y.Z followed by optional 7675e1fea6SMartin Matuska # vendor/distro specific stuff 7775e1fea6SMartin Matuska # RHEL7: 3.10.0-1160.108.1.el7.x86_64 7875e1fea6SMartin Matuska # Fedora 37: 6.5.12-100.fc37.x86_64 7975e1fea6SMartin Matuska # Debian 12.6: 6.1.0-22-amd64 8075e1fea6SMartin Matuska ver=$(uname -r | grep -Eo "^[0-9]+\.[0-9]+\.[0-9]+") 8175e1fea6SMartin Matuska ;; 8275e1fea6SMartin Matuska FreeBSD) 8375e1fea6SMartin Matuska # FreeBSD version numbers are X.Y-BRANCH-pZ. Depending on 8475e1fea6SMartin Matuska # branch, -pZ may not be present, but this is typically only 8575e1fea6SMartin Matuska # on pre-release or true .0 releases, so can be assumed 0 8675e1fea6SMartin Matuska # if not present. 8775e1fea6SMartin Matuska # eg: 8875e1fea6SMartin Matuska # 13.2-RELEASE-p4 8975e1fea6SMartin Matuska # 14.1-RELEASE 9075e1fea6SMartin Matuska # 15.0-CURRENT 9175e1fea6SMartin Matuska ver=$(uname -r | \ 9275e1fea6SMartin Matuska grep -Eo "[0-9]+\.[0-9]+(-[A-Z0-9]+-p[0-9]+)?" | \ 9375e1fea6SMartin Matuska sed -E "s/-[^-]+-p/./") 9475e1fea6SMartin Matuska ;; 9575e1fea6SMartin Matuska *) 9675e1fea6SMartin Matuska # Unknown system 9775e1fea6SMartin Matuska log_fail "Don't know how to get kernel version for '$UNAME'" 9875e1fea6SMartin Matuska ;; 9975e1fea6SMartin Matuska esac 100eda14cbcSMatt Macy 101716fd348SMartin Matuska typeset version major minor _ 102716fd348SMartin Matuska IFS='.' read -r version major minor _ <<<"$ver" 103eda14cbcSMatt Macy 104716fd348SMartin Matuska [ -z "$version" ] && version=0 105716fd348SMartin Matuska [ -z "$major" ] && major=0 106716fd348SMartin Matuska [ -z "$minor" ] && minor=0 107eda14cbcSMatt Macy 108716fd348SMartin Matuska echo $((version * 100000 + major * 1000 + minor)) 109eda14cbcSMatt Macy} 110eda14cbcSMatt Macy 1114fefe1b7SMartin Matuska# Linux kernel version comparison function 1124fefe1b7SMartin Matuska# 1134fefe1b7SMartin Matuska# $1 Linux version ("4.10", "2.6.32") or blank for installed Linux version 1144fefe1b7SMartin Matuska# 1154fefe1b7SMartin Matuska# Used for comparison: if [ $(linux_version) -ge $(linux_version "2.6.32") ] 1164fefe1b7SMartin Matuskafunction linux_version { 1174fefe1b7SMartin Matuska kernel_version "$1" 1184fefe1b7SMartin Matuska} 1194fefe1b7SMartin Matuska 1204fefe1b7SMartin Matuska# FreeBSD version comparison function 1214fefe1b7SMartin Matuska# 1224fefe1b7SMartin Matuska# $1 FreeBSD version ("13.2", "14.0") or blank for installed FreeBSD version 1234fefe1b7SMartin Matuska# 1244fefe1b7SMartin Matuska# Used for comparison: if [ $(freebsd_version) -ge $(freebsd_version "13.2") ] 1254fefe1b7SMartin Matuskafunction freebsd_version { 1264fefe1b7SMartin Matuska kernel_version "$1" 1274fefe1b7SMartin Matuska} 1284fefe1b7SMartin Matuska 129eda14cbcSMatt Macy# Determine if this is a Linux test system 130eda14cbcSMatt Macy# 131eda14cbcSMatt Macy# Return 0 if platform Linux, 1 if otherwise 132eda14cbcSMatt Macy 133eda14cbcSMatt Macyfunction is_linux 134eda14cbcSMatt Macy{ 135716fd348SMartin Matuska [ "$UNAME" = "Linux" ] 136eda14cbcSMatt Macy} 137eda14cbcSMatt Macy 138eda14cbcSMatt Macy# Determine if this is an illumos test system 139eda14cbcSMatt Macy# 140eda14cbcSMatt Macy# Return 0 if platform illumos, 1 if otherwise 141eda14cbcSMatt Macyfunction is_illumos 142eda14cbcSMatt Macy{ 143716fd348SMartin Matuska [ "$UNAME" = "illumos" ] 144eda14cbcSMatt Macy} 145eda14cbcSMatt Macy 146eda14cbcSMatt Macy# Determine if this is a FreeBSD test system 147eda14cbcSMatt Macy# 148eda14cbcSMatt Macy# Return 0 if platform FreeBSD, 1 if otherwise 149eda14cbcSMatt Macy 150eda14cbcSMatt Macyfunction is_freebsd 151eda14cbcSMatt Macy{ 152716fd348SMartin Matuska [ "$UNAME" = "FreeBSD" ] 153eda14cbcSMatt Macy} 154eda14cbcSMatt Macy 155eda14cbcSMatt Macy# Determine if this is a 32-bit system 156eda14cbcSMatt Macy# 157eda14cbcSMatt Macy# Return 0 if platform is 32-bit, 1 if otherwise 158eda14cbcSMatt Macy 159eda14cbcSMatt Macyfunction is_32bit 160eda14cbcSMatt Macy{ 161716fd348SMartin Matuska [ $(getconf LONG_BIT) = "32" ] 162eda14cbcSMatt Macy} 163eda14cbcSMatt Macy 164eda14cbcSMatt Macy# Determine if kmemleak is enabled 165eda14cbcSMatt Macy# 166eda14cbcSMatt Macy# Return 0 if kmemleak is enabled, 1 if otherwise 167eda14cbcSMatt Macy 168eda14cbcSMatt Macyfunction is_kmemleak 169eda14cbcSMatt Macy{ 170716fd348SMartin Matuska is_linux && [ -e /sys/kernel/debug/kmemleak ] 171eda14cbcSMatt Macy} 172eda14cbcSMatt Macy 173eda14cbcSMatt Macy# Determine whether a dataset is mounted 174eda14cbcSMatt Macy# 175eda14cbcSMatt Macy# $1 dataset name 176eda14cbcSMatt Macy# $2 filesystem type; optional - defaulted to zfs 177eda14cbcSMatt Macy# 178eda14cbcSMatt Macy# Return 0 if dataset is mounted; 1 if unmounted; 2 on error 179eda14cbcSMatt Macy 180eda14cbcSMatt Macyfunction ismounted 181eda14cbcSMatt Macy{ 182eda14cbcSMatt Macy typeset fstype=$2 183eda14cbcSMatt Macy [[ -z $fstype ]] && fstype=zfs 184716fd348SMartin Matuska typeset out dir name 185eda14cbcSMatt Macy 186eda14cbcSMatt Macy case $fstype in 187eda14cbcSMatt Macy zfs) 188eda14cbcSMatt Macy if [[ "$1" == "/"* ]] ; then 189716fd348SMartin Matuska ! zfs mount | awk -v fs="$1" '$2 == fs {exit 1}' 190eda14cbcSMatt Macy else 191716fd348SMartin Matuska ! zfs mount | awk -v ds="$1" '$1 == ds {exit 1}' 192eda14cbcSMatt Macy fi 193eda14cbcSMatt Macy ;; 194eda14cbcSMatt Macy ufs|nfs) 195eda14cbcSMatt Macy if is_freebsd; then 196eda14cbcSMatt Macy mount -pt $fstype | while read dev dir _t _flags; do 197eda14cbcSMatt Macy [[ "$1" == "$dev" || "$1" == "$dir" ]] && return 0 198eda14cbcSMatt Macy done 199eda14cbcSMatt Macy else 200716fd348SMartin Matuska out=$(df -F $fstype $1 2>/dev/null) || return 201eda14cbcSMatt Macy 202eda14cbcSMatt Macy dir=${out%%\(*} 203eda14cbcSMatt Macy dir=${dir%% *} 204eda14cbcSMatt Macy name=${out##*\(} 205eda14cbcSMatt Macy name=${name%%\)*} 206eda14cbcSMatt Macy name=${name%% *} 207eda14cbcSMatt Macy 208eda14cbcSMatt Macy [[ "$1" == "$dir" || "$1" == "$name" ]] && return 0 209eda14cbcSMatt Macy fi 210eda14cbcSMatt Macy ;; 211eda14cbcSMatt Macy ext*) 212716fd348SMartin Matuska df -t $fstype $1 > /dev/null 2>&1 213eda14cbcSMatt Macy ;; 214eda14cbcSMatt Macy zvol) 215eda14cbcSMatt Macy if [[ -L "$ZVOL_DEVDIR/$1" ]]; then 216eda14cbcSMatt Macy link=$(readlink -f $ZVOL_DEVDIR/$1) 217eda14cbcSMatt Macy [[ -n "$link" ]] && \ 218eda14cbcSMatt Macy mount | grep -q "^$link" && \ 219eda14cbcSMatt Macy return 0 220eda14cbcSMatt Macy fi 221eda14cbcSMatt Macy ;; 222716fd348SMartin Matuska *) 223716fd348SMartin Matuska false 224716fd348SMartin Matuska ;; 225eda14cbcSMatt Macy esac 226eda14cbcSMatt Macy} 227eda14cbcSMatt Macy 228eda14cbcSMatt Macy# Return 0 if a dataset is mounted; 1 otherwise 229eda14cbcSMatt Macy# 230eda14cbcSMatt Macy# $1 dataset name 231eda14cbcSMatt Macy# $2 filesystem type; optional - defaulted to zfs 232eda14cbcSMatt Macy 233eda14cbcSMatt Macyfunction mounted 234eda14cbcSMatt Macy{ 235eda14cbcSMatt Macy ismounted $1 $2 236eda14cbcSMatt Macy} 237eda14cbcSMatt Macy 238eda14cbcSMatt Macy# Return 0 if a dataset is unmounted; 1 otherwise 239eda14cbcSMatt Macy# 240eda14cbcSMatt Macy# $1 dataset name 241eda14cbcSMatt Macy# $2 filesystem type; optional - defaulted to zfs 242eda14cbcSMatt Macy 243eda14cbcSMatt Macyfunction unmounted 244eda14cbcSMatt Macy{ 245716fd348SMartin Matuska ! ismounted $1 $2 246eda14cbcSMatt Macy} 247eda14cbcSMatt Macy 248eda14cbcSMatt Macyfunction default_setup 249eda14cbcSMatt Macy{ 250eda14cbcSMatt Macy default_setup_noexit "$@" 251eda14cbcSMatt Macy 252eda14cbcSMatt Macy log_pass 253eda14cbcSMatt Macy} 254eda14cbcSMatt Macy 255eda14cbcSMatt Macyfunction default_setup_no_mountpoint 256eda14cbcSMatt Macy{ 257eda14cbcSMatt Macy default_setup_noexit "$1" "$2" "$3" "yes" 258eda14cbcSMatt Macy 259eda14cbcSMatt Macy log_pass 260eda14cbcSMatt Macy} 261eda14cbcSMatt Macy 262eda14cbcSMatt Macy# 263eda14cbcSMatt Macy# Given a list of disks, setup storage pools and datasets. 264eda14cbcSMatt Macy# 265eda14cbcSMatt Macyfunction default_setup_noexit 266eda14cbcSMatt Macy{ 267eda14cbcSMatt Macy typeset disklist=$1 268eda14cbcSMatt Macy typeset container=$2 269eda14cbcSMatt Macy typeset volume=$3 270eda14cbcSMatt Macy typeset no_mountpoint=$4 271eda14cbcSMatt Macy log_note begin default_setup_noexit 272eda14cbcSMatt Macy 273eda14cbcSMatt Macy if is_global_zone; then 274eda14cbcSMatt Macy if poolexists $TESTPOOL ; then 275eda14cbcSMatt Macy destroy_pool $TESTPOOL 276eda14cbcSMatt Macy fi 277eda14cbcSMatt Macy [[ -d /$TESTPOOL ]] && rm -rf /$TESTPOOL 278eda14cbcSMatt Macy log_must zpool create -f $TESTPOOL $disklist 279eda14cbcSMatt Macy else 280eda14cbcSMatt Macy reexport_pool 281eda14cbcSMatt Macy fi 282eda14cbcSMatt Macy 283eda14cbcSMatt Macy rm -rf $TESTDIR || log_unresolved Could not remove $TESTDIR 284eda14cbcSMatt Macy mkdir -p $TESTDIR || log_unresolved Could not create $TESTDIR 285eda14cbcSMatt Macy 286eda14cbcSMatt Macy log_must zfs create $TESTPOOL/$TESTFS 287eda14cbcSMatt Macy if [[ -z $no_mountpoint ]]; then 288eda14cbcSMatt Macy log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS 289eda14cbcSMatt Macy fi 290eda14cbcSMatt Macy 291eda14cbcSMatt Macy if [[ -n $container ]]; then 292eda14cbcSMatt Macy rm -rf $TESTDIR1 || \ 293eda14cbcSMatt Macy log_unresolved Could not remove $TESTDIR1 294eda14cbcSMatt Macy mkdir -p $TESTDIR1 || \ 295eda14cbcSMatt Macy log_unresolved Could not create $TESTDIR1 296eda14cbcSMatt Macy 297eda14cbcSMatt Macy log_must zfs create $TESTPOOL/$TESTCTR 298eda14cbcSMatt Macy log_must zfs set canmount=off $TESTPOOL/$TESTCTR 299eda14cbcSMatt Macy log_must zfs create $TESTPOOL/$TESTCTR/$TESTFS1 300eda14cbcSMatt Macy if [[ -z $no_mountpoint ]]; then 301eda14cbcSMatt Macy log_must zfs set mountpoint=$TESTDIR1 \ 302eda14cbcSMatt Macy $TESTPOOL/$TESTCTR/$TESTFS1 303eda14cbcSMatt Macy fi 304eda14cbcSMatt Macy fi 305eda14cbcSMatt Macy 306eda14cbcSMatt Macy if [[ -n $volume ]]; then 307eda14cbcSMatt Macy if is_global_zone ; then 308eda14cbcSMatt Macy log_must zfs create -V $VOLSIZE $TESTPOOL/$TESTVOL 309eda14cbcSMatt Macy block_device_wait 310eda14cbcSMatt Macy else 311eda14cbcSMatt Macy log_must zfs create $TESTPOOL/$TESTVOL 312eda14cbcSMatt Macy fi 313eda14cbcSMatt Macy fi 314eda14cbcSMatt Macy} 315eda14cbcSMatt Macy 316eda14cbcSMatt Macy# 317eda14cbcSMatt Macy# Given a list of disks, setup a storage pool, file system and 318eda14cbcSMatt Macy# a container. 319eda14cbcSMatt Macy# 320eda14cbcSMatt Macyfunction default_container_setup 321eda14cbcSMatt Macy{ 322eda14cbcSMatt Macy typeset disklist=$1 323eda14cbcSMatt Macy 324eda14cbcSMatt Macy default_setup "$disklist" "true" 325eda14cbcSMatt Macy} 326eda14cbcSMatt Macy 327eda14cbcSMatt Macy# 328eda14cbcSMatt Macy# Given a list of disks, setup a storage pool,file system 329eda14cbcSMatt Macy# and a volume. 330eda14cbcSMatt Macy# 331eda14cbcSMatt Macyfunction default_volume_setup 332eda14cbcSMatt Macy{ 333eda14cbcSMatt Macy typeset disklist=$1 334eda14cbcSMatt Macy 335eda14cbcSMatt Macy default_setup "$disklist" "" "true" 336eda14cbcSMatt Macy} 337eda14cbcSMatt Macy 338eda14cbcSMatt Macy# 339eda14cbcSMatt Macy# Given a list of disks, setup a storage pool,file system, 340eda14cbcSMatt Macy# a container and a volume. 341eda14cbcSMatt Macy# 342eda14cbcSMatt Macyfunction default_container_volume_setup 343eda14cbcSMatt Macy{ 344eda14cbcSMatt Macy typeset disklist=$1 345eda14cbcSMatt Macy 346eda14cbcSMatt Macy default_setup "$disklist" "true" "true" 347eda14cbcSMatt Macy} 348eda14cbcSMatt Macy 349eda14cbcSMatt Macy# 350eda14cbcSMatt Macy# Create a snapshot on a filesystem or volume. Defaultly create a snapshot on 351eda14cbcSMatt Macy# filesystem 352eda14cbcSMatt Macy# 353eda14cbcSMatt Macy# $1 Existing filesystem or volume name. Default, $TESTPOOL/$TESTFS 354eda14cbcSMatt Macy# $2 snapshot name. Default, $TESTSNAP 355eda14cbcSMatt Macy# 356eda14cbcSMatt Macyfunction create_snapshot 357eda14cbcSMatt Macy{ 358eda14cbcSMatt Macy typeset fs_vol=${1:-$TESTPOOL/$TESTFS} 359eda14cbcSMatt Macy typeset snap=${2:-$TESTSNAP} 360eda14cbcSMatt Macy 361eda14cbcSMatt Macy [[ -z $fs_vol ]] && log_fail "Filesystem or volume's name is undefined." 362eda14cbcSMatt Macy [[ -z $snap ]] && log_fail "Snapshot's name is undefined." 363eda14cbcSMatt Macy 364eda14cbcSMatt Macy if snapexists $fs_vol@$snap; then 365eda14cbcSMatt Macy log_fail "$fs_vol@$snap already exists." 366eda14cbcSMatt Macy fi 367eda14cbcSMatt Macy datasetexists $fs_vol || \ 368eda14cbcSMatt Macy log_fail "$fs_vol must exist." 369eda14cbcSMatt Macy 370eda14cbcSMatt Macy log_must zfs snapshot $fs_vol@$snap 371eda14cbcSMatt Macy} 372eda14cbcSMatt Macy 373eda14cbcSMatt Macy# 374eda14cbcSMatt Macy# Create a clone from a snapshot, default clone name is $TESTCLONE. 375eda14cbcSMatt Macy# 376eda14cbcSMatt Macy# $1 Existing snapshot, $TESTPOOL/$TESTFS@$TESTSNAP is default. 377eda14cbcSMatt Macy# $2 Clone name, $TESTPOOL/$TESTCLONE is default. 378eda14cbcSMatt Macy# 379eda14cbcSMatt Macyfunction create_clone # snapshot clone 380eda14cbcSMatt Macy{ 381eda14cbcSMatt Macy typeset snap=${1:-$TESTPOOL/$TESTFS@$TESTSNAP} 382eda14cbcSMatt Macy typeset clone=${2:-$TESTPOOL/$TESTCLONE} 383eda14cbcSMatt Macy 384eda14cbcSMatt Macy [[ -z $snap ]] && \ 385eda14cbcSMatt Macy log_fail "Snapshot name is undefined." 386eda14cbcSMatt Macy [[ -z $clone ]] && \ 387eda14cbcSMatt Macy log_fail "Clone name is undefined." 388eda14cbcSMatt Macy 389eda14cbcSMatt Macy log_must zfs clone $snap $clone 390eda14cbcSMatt Macy} 391eda14cbcSMatt Macy 392eda14cbcSMatt Macy# 393eda14cbcSMatt Macy# Create a bookmark of the given snapshot. Defaultly create a bookmark on 394eda14cbcSMatt Macy# filesystem. 395eda14cbcSMatt Macy# 396eda14cbcSMatt Macy# $1 Existing filesystem or volume name. Default, $TESTFS 397eda14cbcSMatt Macy# $2 Existing snapshot name. Default, $TESTSNAP 398eda14cbcSMatt Macy# $3 bookmark name. Default, $TESTBKMARK 399eda14cbcSMatt Macy# 400eda14cbcSMatt Macyfunction create_bookmark 401eda14cbcSMatt Macy{ 402eda14cbcSMatt Macy typeset fs_vol=${1:-$TESTFS} 403eda14cbcSMatt Macy typeset snap=${2:-$TESTSNAP} 404eda14cbcSMatt Macy typeset bkmark=${3:-$TESTBKMARK} 405eda14cbcSMatt Macy 406eda14cbcSMatt Macy [[ -z $fs_vol ]] && log_fail "Filesystem or volume's name is undefined." 407eda14cbcSMatt Macy [[ -z $snap ]] && log_fail "Snapshot's name is undefined." 408eda14cbcSMatt Macy [[ -z $bkmark ]] && log_fail "Bookmark's name is undefined." 409eda14cbcSMatt Macy 410eda14cbcSMatt Macy if bkmarkexists $fs_vol#$bkmark; then 411eda14cbcSMatt Macy log_fail "$fs_vol#$bkmark already exists." 412eda14cbcSMatt Macy fi 413eda14cbcSMatt Macy datasetexists $fs_vol || \ 414eda14cbcSMatt Macy log_fail "$fs_vol must exist." 415eda14cbcSMatt Macy snapexists $fs_vol@$snap || \ 416eda14cbcSMatt Macy log_fail "$fs_vol@$snap must exist." 417eda14cbcSMatt Macy 418eda14cbcSMatt Macy log_must zfs bookmark $fs_vol@$snap $fs_vol#$bkmark 419eda14cbcSMatt Macy} 420eda14cbcSMatt Macy 421eda14cbcSMatt Macy# 422eda14cbcSMatt Macy# Create a temporary clone result of an interrupted resumable 'zfs receive' 423eda14cbcSMatt Macy# $1 Destination filesystem name. Must not exist, will be created as the result 424eda14cbcSMatt Macy# of this function along with its %recv temporary clone 425eda14cbcSMatt Macy# $2 Source filesystem name. Must not exist, will be created and destroyed 426eda14cbcSMatt Macy# 427eda14cbcSMatt Macyfunction create_recv_clone 428eda14cbcSMatt Macy{ 429eda14cbcSMatt Macy typeset recvfs="$1" 430eda14cbcSMatt Macy typeset sendfs="${2:-$TESTPOOL/create_recv_clone}" 431eda14cbcSMatt Macy typeset snap="$sendfs@snap1" 432eda14cbcSMatt Macy typeset incr="$sendfs@snap2" 433eda14cbcSMatt Macy typeset mountpoint="$TESTDIR/create_recv_clone" 434eda14cbcSMatt Macy typeset sendfile="$TESTDIR/create_recv_clone.zsnap" 435eda14cbcSMatt Macy 436eda14cbcSMatt Macy [[ -z $recvfs ]] && log_fail "Recv filesystem's name is undefined." 437eda14cbcSMatt Macy 438eda14cbcSMatt Macy datasetexists $recvfs && log_fail "Recv filesystem must not exist." 439eda14cbcSMatt Macy datasetexists $sendfs && log_fail "Send filesystem must not exist." 440eda14cbcSMatt Macy 441c03c5b1cSMartin Matuska log_must zfs create -o compression=off -o mountpoint="$mountpoint" $sendfs 442eda14cbcSMatt Macy log_must zfs snapshot $snap 443eda14cbcSMatt Macy log_must eval "zfs send $snap | zfs recv -u $recvfs" 444eda14cbcSMatt Macy log_must mkfile 1m "$mountpoint/data" 445eda14cbcSMatt Macy log_must zfs snapshot $incr 446eda14cbcSMatt Macy log_must eval "zfs send -i $snap $incr | dd bs=10K count=1 \ 447eda14cbcSMatt Macy iflag=fullblock > $sendfile" 448eda14cbcSMatt Macy log_mustnot eval "zfs recv -su $recvfs < $sendfile" 449eda14cbcSMatt Macy destroy_dataset "$sendfs" "-r" 450eda14cbcSMatt Macy log_must rm -f "$sendfile" 451eda14cbcSMatt Macy 452eda14cbcSMatt Macy if [[ $(get_prop 'inconsistent' "$recvfs/%recv") -ne 1 ]]; then 453eda14cbcSMatt Macy log_fail "Error creating temporary $recvfs/%recv clone" 454eda14cbcSMatt Macy fi 455eda14cbcSMatt Macy} 456eda14cbcSMatt Macy 457eda14cbcSMatt Macyfunction default_mirror_setup 458eda14cbcSMatt Macy{ 459eda14cbcSMatt Macy default_mirror_setup_noexit $1 $2 $3 460eda14cbcSMatt Macy 461eda14cbcSMatt Macy log_pass 462eda14cbcSMatt Macy} 463eda14cbcSMatt Macy 464eda14cbcSMatt Macy# 465eda14cbcSMatt Macy# Given a pair of disks, set up a storage pool and dataset for the mirror 466eda14cbcSMatt Macy# @parameters: $1 the primary side of the mirror 467eda14cbcSMatt Macy# $2 the secondary side of the mirror 468eda14cbcSMatt Macy# @uses: ZPOOL ZFS TESTPOOL TESTFS 469eda14cbcSMatt Macyfunction default_mirror_setup_noexit 470eda14cbcSMatt Macy{ 471eda14cbcSMatt Macy readonly func="default_mirror_setup_noexit" 472eda14cbcSMatt Macy typeset primary=$1 473eda14cbcSMatt Macy typeset secondary=$2 474eda14cbcSMatt Macy 475eda14cbcSMatt Macy [[ -z $primary ]] && \ 476eda14cbcSMatt Macy log_fail "$func: No parameters passed" 477eda14cbcSMatt Macy [[ -z $secondary ]] && \ 478eda14cbcSMatt Macy log_fail "$func: No secondary partition passed" 479eda14cbcSMatt Macy [[ -d /$TESTPOOL ]] && rm -rf /$TESTPOOL 480eda14cbcSMatt Macy log_must zpool create -f $TESTPOOL mirror $@ 481eda14cbcSMatt Macy log_must zfs create $TESTPOOL/$TESTFS 482eda14cbcSMatt Macy log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS 483eda14cbcSMatt Macy} 484eda14cbcSMatt Macy 485eda14cbcSMatt Macy# 486eda14cbcSMatt Macy# Destroy the configured testpool mirrors. 487eda14cbcSMatt Macy# the mirrors are of the form ${TESTPOOL}{number} 488eda14cbcSMatt Macy# @uses: ZPOOL ZFS TESTPOOL 489eda14cbcSMatt Macyfunction destroy_mirrors 490eda14cbcSMatt Macy{ 491eda14cbcSMatt Macy default_cleanup_noexit 492eda14cbcSMatt Macy 493eda14cbcSMatt Macy log_pass 494eda14cbcSMatt Macy} 495eda14cbcSMatt Macy 496c03c5b1cSMartin Matuskafunction default_raidz_setup 497c03c5b1cSMartin Matuska{ 498c03c5b1cSMartin Matuska default_raidz_setup_noexit "$*" 499c03c5b1cSMartin Matuska 500c03c5b1cSMartin Matuska log_pass 501c03c5b1cSMartin Matuska} 502c03c5b1cSMartin Matuska 503eda14cbcSMatt Macy# 504eda14cbcSMatt Macy# Given a minimum of two disks, set up a storage pool and dataset for the raid-z 505eda14cbcSMatt Macy# $1 the list of disks 506eda14cbcSMatt Macy# 507c03c5b1cSMartin Matuskafunction default_raidz_setup_noexit 508eda14cbcSMatt Macy{ 509eda14cbcSMatt Macy typeset disklist="$*" 510eda14cbcSMatt Macy disks=(${disklist[*]}) 511eda14cbcSMatt Macy 512eda14cbcSMatt Macy if [[ ${#disks[*]} -lt 2 ]]; then 513eda14cbcSMatt Macy log_fail "A raid-z requires a minimum of two disks." 514eda14cbcSMatt Macy fi 515eda14cbcSMatt Macy 516eda14cbcSMatt Macy [[ -d /$TESTPOOL ]] && rm -rf /$TESTPOOL 517eda14cbcSMatt Macy log_must zpool create -f $TESTPOOL raidz $disklist 518eda14cbcSMatt Macy log_must zfs create $TESTPOOL/$TESTFS 519eda14cbcSMatt Macy log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS 520eda14cbcSMatt Macy} 521eda14cbcSMatt Macy 522eda14cbcSMatt Macy# 523eda14cbcSMatt Macy# Common function used to cleanup storage pools and datasets. 524eda14cbcSMatt Macy# 525eda14cbcSMatt Macy# Invoked at the start of the test suite to ensure the system 526eda14cbcSMatt Macy# is in a known state, and also at the end of each set of 527eda14cbcSMatt Macy# sub-tests to ensure errors from one set of tests doesn't 528eda14cbcSMatt Macy# impact the execution of the next set. 529eda14cbcSMatt Macy 530eda14cbcSMatt Macyfunction default_cleanup 531eda14cbcSMatt Macy{ 532eda14cbcSMatt Macy default_cleanup_noexit 533eda14cbcSMatt Macy 534eda14cbcSMatt Macy log_pass 535eda14cbcSMatt Macy} 536eda14cbcSMatt Macy 537eda14cbcSMatt Macy# 538eda14cbcSMatt Macy# Utility function used to list all available pool names. 539eda14cbcSMatt Macy# 540eda14cbcSMatt Macy# NOTE: $KEEP is a variable containing pool names, separated by a newline 541eda14cbcSMatt Macy# character, that must be excluded from the returned list. 542eda14cbcSMatt Macy# 543eda14cbcSMatt Macyfunction get_all_pools 544eda14cbcSMatt Macy{ 545eda14cbcSMatt Macy zpool list -H -o name | grep -Fvx "$KEEP" | grep -v "$NO_POOLS" 546eda14cbcSMatt Macy} 547eda14cbcSMatt Macy 548eda14cbcSMatt Macyfunction default_cleanup_noexit 549eda14cbcSMatt Macy{ 550eda14cbcSMatt Macy typeset pool="" 551eda14cbcSMatt Macy # 552eda14cbcSMatt Macy # Destroying the pool will also destroy any 553eda14cbcSMatt Macy # filesystems it contains. 554eda14cbcSMatt Macy # 555eda14cbcSMatt Macy if is_global_zone; then 556eda14cbcSMatt Macy zfs unmount -a > /dev/null 2>&1 557eda14cbcSMatt Macy ALL_POOLS=$(get_all_pools) 558eda14cbcSMatt Macy # Here, we loop through the pools we're allowed to 559eda14cbcSMatt Macy # destroy, only destroying them if it's safe to do 560eda14cbcSMatt Macy # so. 561eda14cbcSMatt Macy while [ ! -z ${ALL_POOLS} ] 562eda14cbcSMatt Macy do 563eda14cbcSMatt Macy for pool in ${ALL_POOLS} 564eda14cbcSMatt Macy do 565eda14cbcSMatt Macy if safe_to_destroy_pool $pool ; 566eda14cbcSMatt Macy then 567eda14cbcSMatt Macy destroy_pool $pool 568eda14cbcSMatt Macy fi 569eda14cbcSMatt Macy done 570eda14cbcSMatt Macy ALL_POOLS=$(get_all_pools) 571eda14cbcSMatt Macy done 572eda14cbcSMatt Macy 573eda14cbcSMatt Macy zfs mount -a 574eda14cbcSMatt Macy else 575eda14cbcSMatt Macy typeset fs="" 576eda14cbcSMatt Macy for fs in $(zfs list -H -o name \ 577eda14cbcSMatt Macy | grep "^$ZONE_POOL/$ZONE_CTR[01234]/"); do 578eda14cbcSMatt Macy destroy_dataset "$fs" "-Rf" 579eda14cbcSMatt Macy done 580eda14cbcSMatt Macy 581eda14cbcSMatt Macy # Need cleanup here to avoid garbage dir left. 582eda14cbcSMatt Macy for fs in $(zfs list -H -o name); do 583eda14cbcSMatt Macy [[ $fs == /$ZONE_POOL ]] && continue 584eda14cbcSMatt Macy [[ -d $fs ]] && log_must rm -rf $fs/* 585eda14cbcSMatt Macy done 586eda14cbcSMatt Macy 587eda14cbcSMatt Macy # 588eda14cbcSMatt Macy # Reset the $ZONE_POOL/$ZONE_CTR[01234] file systems property to 589eda14cbcSMatt Macy # the default value 590eda14cbcSMatt Macy # 591eda14cbcSMatt Macy for fs in $(zfs list -H -o name); do 592eda14cbcSMatt Macy if [[ $fs == $ZONE_POOL/$ZONE_CTR[01234] ]]; then 593eda14cbcSMatt Macy log_must zfs set reservation=none $fs 594eda14cbcSMatt Macy log_must zfs set recordsize=128K $fs 595eda14cbcSMatt Macy log_must zfs set mountpoint=/$fs $fs 596716fd348SMartin Matuska typeset enc=$(get_prop encryption $fs) 597716fd348SMartin Matuska if [ -z "$enc" ] || [ "$enc" = "off" ]; then 598eda14cbcSMatt Macy log_must zfs set checksum=on $fs 599eda14cbcSMatt Macy fi 600eda14cbcSMatt Macy log_must zfs set compression=off $fs 601eda14cbcSMatt Macy log_must zfs set atime=on $fs 602eda14cbcSMatt Macy log_must zfs set devices=off $fs 603eda14cbcSMatt Macy log_must zfs set exec=on $fs 604eda14cbcSMatt Macy log_must zfs set setuid=on $fs 605eda14cbcSMatt Macy log_must zfs set readonly=off $fs 606eda14cbcSMatt Macy log_must zfs set snapdir=hidden $fs 607eda14cbcSMatt Macy log_must zfs set aclmode=groupmask $fs 608eda14cbcSMatt Macy log_must zfs set aclinherit=secure $fs 609eda14cbcSMatt Macy fi 610eda14cbcSMatt Macy done 611eda14cbcSMatt Macy fi 612eda14cbcSMatt Macy 613eda14cbcSMatt Macy [[ -d $TESTDIR ]] && \ 614eda14cbcSMatt Macy log_must rm -rf $TESTDIR 615eda14cbcSMatt Macy 616eda14cbcSMatt Macy disk1=${DISKS%% *} 617eda14cbcSMatt Macy if is_mpath_device $disk1; then 618eda14cbcSMatt Macy delete_partitions 619eda14cbcSMatt Macy fi 620eda14cbcSMatt Macy 621eda14cbcSMatt Macy rm -f $TEST_BASE_DIR/{err,out} 622eda14cbcSMatt Macy} 623eda14cbcSMatt Macy 624eda14cbcSMatt Macy 625eda14cbcSMatt Macy# 626eda14cbcSMatt Macy# Common function used to cleanup storage pools, file systems 627eda14cbcSMatt Macy# and containers. 628eda14cbcSMatt Macy# 629eda14cbcSMatt Macyfunction default_container_cleanup 630eda14cbcSMatt Macy{ 631eda14cbcSMatt Macy if ! is_global_zone; then 632eda14cbcSMatt Macy reexport_pool 633eda14cbcSMatt Macy fi 634eda14cbcSMatt Macy 635716fd348SMartin Matuska ismounted $TESTPOOL/$TESTCTR/$TESTFS1 && 636eda14cbcSMatt Macy log_must zfs unmount $TESTPOOL/$TESTCTR/$TESTFS1 637eda14cbcSMatt Macy 638eda14cbcSMatt Macy destroy_dataset "$TESTPOOL/$TESTCTR/$TESTFS1" "-R" 639eda14cbcSMatt Macy destroy_dataset "$TESTPOOL/$TESTCTR" "-Rf" 640eda14cbcSMatt Macy 641eda14cbcSMatt Macy [[ -e $TESTDIR1 ]] && \ 642716fd348SMartin Matuska log_must rm -rf $TESTDIR1 643eda14cbcSMatt Macy 644eda14cbcSMatt Macy default_cleanup 645eda14cbcSMatt Macy} 646eda14cbcSMatt Macy 647eda14cbcSMatt Macy# 648eda14cbcSMatt Macy# Common function used to cleanup snapshot of file system or volume. Default to 649eda14cbcSMatt Macy# delete the file system's snapshot 650eda14cbcSMatt Macy# 651eda14cbcSMatt Macy# $1 snapshot name 652eda14cbcSMatt Macy# 653eda14cbcSMatt Macyfunction destroy_snapshot 654eda14cbcSMatt Macy{ 655eda14cbcSMatt Macy typeset snap=${1:-$TESTPOOL/$TESTFS@$TESTSNAP} 656eda14cbcSMatt Macy 657eda14cbcSMatt Macy if ! snapexists $snap; then 658eda14cbcSMatt Macy log_fail "'$snap' does not exist." 659eda14cbcSMatt Macy fi 660eda14cbcSMatt Macy 661eda14cbcSMatt Macy # 662eda14cbcSMatt Macy # For the sake of the value which come from 'get_prop' is not equal 663eda14cbcSMatt Macy # to the really mountpoint when the snapshot is unmounted. So, firstly 664eda14cbcSMatt Macy # check and make sure this snapshot's been mounted in current system. 665eda14cbcSMatt Macy # 666eda14cbcSMatt Macy typeset mtpt="" 667eda14cbcSMatt Macy if ismounted $snap; then 668eda14cbcSMatt Macy mtpt=$(get_prop mountpoint $snap) 669eda14cbcSMatt Macy fi 670eda14cbcSMatt Macy 671eda14cbcSMatt Macy destroy_dataset "$snap" 672eda14cbcSMatt Macy [[ $mtpt != "" && -d $mtpt ]] && \ 673eda14cbcSMatt Macy log_must rm -rf $mtpt 674eda14cbcSMatt Macy} 675eda14cbcSMatt Macy 676eda14cbcSMatt Macy# 677eda14cbcSMatt Macy# Common function used to cleanup clone. 678eda14cbcSMatt Macy# 679eda14cbcSMatt Macy# $1 clone name 680eda14cbcSMatt Macy# 681eda14cbcSMatt Macyfunction destroy_clone 682eda14cbcSMatt Macy{ 683eda14cbcSMatt Macy typeset clone=${1:-$TESTPOOL/$TESTCLONE} 684eda14cbcSMatt Macy 685eda14cbcSMatt Macy if ! datasetexists $clone; then 686eda14cbcSMatt Macy log_fail "'$clone' does not existed." 687eda14cbcSMatt Macy fi 688eda14cbcSMatt Macy 689eda14cbcSMatt Macy # With the same reason in destroy_snapshot 690eda14cbcSMatt Macy typeset mtpt="" 691eda14cbcSMatt Macy if ismounted $clone; then 692eda14cbcSMatt Macy mtpt=$(get_prop mountpoint $clone) 693eda14cbcSMatt Macy fi 694eda14cbcSMatt Macy 695eda14cbcSMatt Macy destroy_dataset "$clone" 696eda14cbcSMatt Macy [[ $mtpt != "" && -d $mtpt ]] && \ 697eda14cbcSMatt Macy log_must rm -rf $mtpt 698eda14cbcSMatt Macy} 699eda14cbcSMatt Macy 700eda14cbcSMatt Macy# 701eda14cbcSMatt Macy# Common function used to cleanup bookmark of file system or volume. Default 702eda14cbcSMatt Macy# to delete the file system's bookmark. 703eda14cbcSMatt Macy# 704eda14cbcSMatt Macy# $1 bookmark name 705eda14cbcSMatt Macy# 706eda14cbcSMatt Macyfunction destroy_bookmark 707eda14cbcSMatt Macy{ 708eda14cbcSMatt Macy typeset bkmark=${1:-$TESTPOOL/$TESTFS#$TESTBKMARK} 709eda14cbcSMatt Macy 710eda14cbcSMatt Macy if ! bkmarkexists $bkmark; then 711eda14cbcSMatt Macy log_fail "'$bkmarkp' does not existed." 712eda14cbcSMatt Macy fi 713eda14cbcSMatt Macy 714eda14cbcSMatt Macy destroy_dataset "$bkmark" 715eda14cbcSMatt Macy} 716eda14cbcSMatt Macy 717eda14cbcSMatt Macy# Return 0 if a snapshot exists; $? otherwise 718eda14cbcSMatt Macy# 719eda14cbcSMatt Macy# $1 - snapshot name 720eda14cbcSMatt Macy 721eda14cbcSMatt Macyfunction snapexists 722eda14cbcSMatt Macy{ 723eda14cbcSMatt Macy zfs list -H -t snapshot "$1" > /dev/null 2>&1 724eda14cbcSMatt Macy} 725eda14cbcSMatt Macy 726eda14cbcSMatt Macy# 727eda14cbcSMatt Macy# Return 0 if a bookmark exists; $? otherwise 728eda14cbcSMatt Macy# 729eda14cbcSMatt Macy# $1 - bookmark name 730eda14cbcSMatt Macy# 731eda14cbcSMatt Macyfunction bkmarkexists 732eda14cbcSMatt Macy{ 733eda14cbcSMatt Macy zfs list -H -t bookmark "$1" > /dev/null 2>&1 734eda14cbcSMatt Macy} 735eda14cbcSMatt Macy 736eda14cbcSMatt Macy# 737eda14cbcSMatt Macy# Return 0 if a hold exists; $? otherwise 738eda14cbcSMatt Macy# 739eda14cbcSMatt Macy# $1 - hold tag 740eda14cbcSMatt Macy# $2 - snapshot name 741eda14cbcSMatt Macy# 742eda14cbcSMatt Macyfunction holdexists 743eda14cbcSMatt Macy{ 744716fd348SMartin Matuska ! zfs holds "$2" | awk -v t="$1" '$2 ~ t { exit 1 }' 745eda14cbcSMatt Macy} 746eda14cbcSMatt Macy 747eda14cbcSMatt Macy# 748eda14cbcSMatt Macy# Set a property to a certain value on a dataset. 749eda14cbcSMatt Macy# Sets a property of the dataset to the value as passed in. 750eda14cbcSMatt Macy# @param: 751eda14cbcSMatt Macy# $1 dataset who's property is being set 752eda14cbcSMatt Macy# $2 property to set 753eda14cbcSMatt Macy# $3 value to set property to 754eda14cbcSMatt Macy# @return: 755eda14cbcSMatt Macy# 0 if the property could be set. 756eda14cbcSMatt Macy# non-zero otherwise. 757eda14cbcSMatt Macy# @use: ZFS 758eda14cbcSMatt Macy# 759eda14cbcSMatt Macyfunction dataset_setprop 760eda14cbcSMatt Macy{ 761eda14cbcSMatt Macy typeset fn=dataset_setprop 762eda14cbcSMatt Macy 763eda14cbcSMatt Macy if (($# < 3)); then 764eda14cbcSMatt Macy log_note "$fn: Insufficient parameters (need 3, had $#)" 765eda14cbcSMatt Macy return 1 766eda14cbcSMatt Macy fi 767eda14cbcSMatt Macy typeset output= 768eda14cbcSMatt Macy output=$(zfs set $2=$3 $1 2>&1) 769eda14cbcSMatt Macy typeset rv=$? 770eda14cbcSMatt Macy if ((rv != 0)); then 771eda14cbcSMatt Macy log_note "Setting property on $1 failed." 772eda14cbcSMatt Macy log_note "property $2=$3" 773eda14cbcSMatt Macy log_note "Return Code: $rv" 774eda14cbcSMatt Macy log_note "Output: $output" 775eda14cbcSMatt Macy return $rv 776eda14cbcSMatt Macy fi 777eda14cbcSMatt Macy return 0 778eda14cbcSMatt Macy} 779eda14cbcSMatt Macy 780eda14cbcSMatt Macy# 781eda14cbcSMatt Macy# Check a numeric assertion 782eda14cbcSMatt Macy# @parameter: $@ the assertion to check 783eda14cbcSMatt Macy# @output: big loud notice if assertion failed 784eda14cbcSMatt Macy# @use: log_fail 785eda14cbcSMatt Macy# 786eda14cbcSMatt Macyfunction assert 787eda14cbcSMatt Macy{ 788eda14cbcSMatt Macy (($@)) || log_fail "$@" 789eda14cbcSMatt Macy} 790eda14cbcSMatt Macy 791eda14cbcSMatt Macy# 792eda14cbcSMatt Macy# Function to format partition size of a disk 793eda14cbcSMatt Macy# Given a disk cxtxdx reduces all partitions 794eda14cbcSMatt Macy# to 0 size 795eda14cbcSMatt Macy# 796eda14cbcSMatt Macyfunction zero_partitions #<whole_disk_name> 797eda14cbcSMatt Macy{ 798eda14cbcSMatt Macy typeset diskname=$1 799eda14cbcSMatt Macy typeset i 800eda14cbcSMatt Macy 801eda14cbcSMatt Macy if is_freebsd; then 802eda14cbcSMatt Macy gpart destroy -F $diskname 803eda14cbcSMatt Macy elif is_linux; then 804eda14cbcSMatt Macy DSK=$DEV_DSKDIR/$diskname 805eda14cbcSMatt Macy DSK=$(echo $DSK | sed -e "s|//|/|g") 806eda14cbcSMatt Macy log_must parted $DSK -s -- mklabel gpt 807eda14cbcSMatt Macy blockdev --rereadpt $DSK 2>/dev/null 808eda14cbcSMatt Macy block_device_wait 809eda14cbcSMatt Macy else 810eda14cbcSMatt Macy for i in 0 1 3 4 5 6 7 811eda14cbcSMatt Macy do 812eda14cbcSMatt Macy log_must set_partition $i "" 0mb $diskname 813eda14cbcSMatt Macy done 814eda14cbcSMatt Macy fi 815eda14cbcSMatt Macy 816eda14cbcSMatt Macy return 0 817eda14cbcSMatt Macy} 818eda14cbcSMatt Macy 819eda14cbcSMatt Macy# 820eda14cbcSMatt Macy# Given a slice, size and disk, this function 821eda14cbcSMatt Macy# formats the slice to the specified size. 822eda14cbcSMatt Macy# Size should be specified with units as per 823eda14cbcSMatt Macy# the `format` command requirements eg. 100mb 3gb 824eda14cbcSMatt Macy# 825eda14cbcSMatt Macy# NOTE: This entire interface is problematic for the Linux parted utility 826eda14cbcSMatt Macy# which requires the end of the partition to be specified. It would be 827eda14cbcSMatt Macy# best to retire this interface and replace it with something more flexible. 828eda14cbcSMatt Macy# At the moment a best effort is made. 829eda14cbcSMatt Macy# 830eda14cbcSMatt Macy# arguments: <slice_num> <slice_start> <size_plus_units> <whole_disk_name> 831eda14cbcSMatt Macyfunction set_partition 832eda14cbcSMatt Macy{ 833eda14cbcSMatt Macy typeset -i slicenum=$1 834eda14cbcSMatt Macy typeset start=$2 835eda14cbcSMatt Macy typeset size=$3 836eda14cbcSMatt Macy typeset disk=${4#$DEV_DSKDIR/} 837eda14cbcSMatt Macy disk=${disk#$DEV_RDSKDIR/} 838eda14cbcSMatt Macy 839716fd348SMartin Matuska case "$UNAME" in 840eda14cbcSMatt Macy Linux) 841eda14cbcSMatt Macy if [[ -z $size || -z $disk ]]; then 842eda14cbcSMatt Macy log_fail "The size or disk name is unspecified." 843eda14cbcSMatt Macy fi 844eda14cbcSMatt Macy disk=$DEV_DSKDIR/$disk 845eda14cbcSMatt Macy typeset size_mb=${size%%[mMgG]} 846eda14cbcSMatt Macy 847eda14cbcSMatt Macy size_mb=${size_mb%%[mMgG][bB]} 848eda14cbcSMatt Macy if [[ ${size:1:1} == 'g' ]]; then 849eda14cbcSMatt Macy ((size_mb = size_mb * 1024)) 850eda14cbcSMatt Macy fi 851eda14cbcSMatt Macy 852eda14cbcSMatt Macy # Create GPT partition table when setting slice 0 or 853eda14cbcSMatt Macy # when the device doesn't already contain a GPT label. 854eda14cbcSMatt Macy parted $disk -s -- print 1 >/dev/null 855eda14cbcSMatt Macy typeset ret_val=$? 856eda14cbcSMatt Macy if [[ $slicenum -eq 0 || $ret_val -ne 0 ]]; then 857716fd348SMartin Matuska if ! parted $disk -s -- mklabel gpt; then 858eda14cbcSMatt Macy log_note "Failed to create GPT partition table on $disk" 859eda14cbcSMatt Macy return 1 860eda14cbcSMatt Macy fi 861eda14cbcSMatt Macy fi 862eda14cbcSMatt Macy 863eda14cbcSMatt Macy # When no start is given align on the first cylinder. 864eda14cbcSMatt Macy if [[ -z "$start" ]]; then 865eda14cbcSMatt Macy start=1 866eda14cbcSMatt Macy fi 867eda14cbcSMatt Macy 868eda14cbcSMatt Macy # Determine the cylinder size for the device and using 869eda14cbcSMatt Macy # that calculate the end offset in cylinders. 870eda14cbcSMatt Macy typeset -i cly_size_kb=0 871716fd348SMartin Matuska cly_size_kb=$(parted -m $disk -s -- unit cyl print | 872716fd348SMartin Matuska awk -F '[:k.]' 'NR == 3 {print $4}') 873eda14cbcSMatt Macy ((end = (size_mb * 1024 / cly_size_kb) + start)) 874eda14cbcSMatt Macy 875eda14cbcSMatt Macy parted $disk -s -- \ 876eda14cbcSMatt Macy mkpart part$slicenum ${start}cyl ${end}cyl 877eda14cbcSMatt Macy typeset ret_val=$? 878eda14cbcSMatt Macy if [[ $ret_val -ne 0 ]]; then 879eda14cbcSMatt Macy log_note "Failed to create partition $slicenum on $disk" 880eda14cbcSMatt Macy return 1 881eda14cbcSMatt Macy fi 882eda14cbcSMatt Macy 883eda14cbcSMatt Macy blockdev --rereadpt $disk 2>/dev/null 884eda14cbcSMatt Macy block_device_wait $disk 885eda14cbcSMatt Macy ;; 886eda14cbcSMatt Macy FreeBSD) 887eda14cbcSMatt Macy if [[ -z $size || -z $disk ]]; then 888eda14cbcSMatt Macy log_fail "The size or disk name is unspecified." 889eda14cbcSMatt Macy fi 890eda14cbcSMatt Macy disk=$DEV_DSKDIR/$disk 891eda14cbcSMatt Macy 892eda14cbcSMatt Macy if [[ $slicenum -eq 0 ]] || ! gpart show $disk >/dev/null 2>&1; then 893eda14cbcSMatt Macy gpart destroy -F $disk >/dev/null 2>&1 894716fd348SMartin Matuska if ! gpart create -s GPT $disk; then 895eda14cbcSMatt Macy log_note "Failed to create GPT partition table on $disk" 896eda14cbcSMatt Macy return 1 897eda14cbcSMatt Macy fi 898eda14cbcSMatt Macy fi 899eda14cbcSMatt Macy 900eda14cbcSMatt Macy typeset index=$((slicenum + 1)) 901eda14cbcSMatt Macy 902eda14cbcSMatt Macy if [[ -n $start ]]; then 903eda14cbcSMatt Macy start="-b $start" 904eda14cbcSMatt Macy fi 905eda14cbcSMatt Macy gpart add -t freebsd-zfs $start -s $size -i $index $disk 906eda14cbcSMatt Macy if [[ $ret_val -ne 0 ]]; then 907eda14cbcSMatt Macy log_note "Failed to create partition $slicenum on $disk" 908eda14cbcSMatt Macy return 1 909eda14cbcSMatt Macy fi 910eda14cbcSMatt Macy 911eda14cbcSMatt Macy block_device_wait $disk 912eda14cbcSMatt Macy ;; 913eda14cbcSMatt Macy *) 914eda14cbcSMatt Macy if [[ -z $slicenum || -z $size || -z $disk ]]; then 915eda14cbcSMatt Macy log_fail "The slice, size or disk name is unspecified." 916eda14cbcSMatt Macy fi 917eda14cbcSMatt Macy 918eda14cbcSMatt Macy typeset format_file=/var/tmp/format_in.$$ 919eda14cbcSMatt Macy 920eda14cbcSMatt Macy echo "partition" >$format_file 921eda14cbcSMatt Macy echo "$slicenum" >> $format_file 922eda14cbcSMatt Macy echo "" >> $format_file 923eda14cbcSMatt Macy echo "" >> $format_file 924eda14cbcSMatt Macy echo "$start" >> $format_file 925eda14cbcSMatt Macy echo "$size" >> $format_file 926eda14cbcSMatt Macy echo "label" >> $format_file 927eda14cbcSMatt Macy echo "" >> $format_file 928eda14cbcSMatt Macy echo "q" >> $format_file 929eda14cbcSMatt Macy echo "q" >> $format_file 930eda14cbcSMatt Macy 931eda14cbcSMatt Macy format -e -s -d $disk -f $format_file 932eda14cbcSMatt Macy typeset ret_val=$? 933eda14cbcSMatt Macy rm -f $format_file 934eda14cbcSMatt Macy ;; 935eda14cbcSMatt Macy esac 936eda14cbcSMatt Macy 937eda14cbcSMatt Macy if [[ $ret_val -ne 0 ]]; then 938eda14cbcSMatt Macy log_note "Unable to format $disk slice $slicenum to $size" 939eda14cbcSMatt Macy return 1 940eda14cbcSMatt Macy fi 941eda14cbcSMatt Macy return 0 942eda14cbcSMatt Macy} 943eda14cbcSMatt Macy 944eda14cbcSMatt Macy# 945eda14cbcSMatt Macy# Delete all partitions on all disks - this is specifically for the use of multipath 946eda14cbcSMatt Macy# devices which currently can only be used in the test suite as raw/un-partitioned 947eda14cbcSMatt Macy# devices (ie a zpool cannot be created on a whole mpath device that has partitions) 948eda14cbcSMatt Macy# 949eda14cbcSMatt Macyfunction delete_partitions 950eda14cbcSMatt Macy{ 951eda14cbcSMatt Macy typeset disk 952eda14cbcSMatt Macy 953eda14cbcSMatt Macy if [[ -z $DISKSARRAY ]]; then 954eda14cbcSMatt Macy DISKSARRAY=$DISKS 955eda14cbcSMatt Macy fi 956eda14cbcSMatt Macy 957eda14cbcSMatt Macy if is_linux; then 958eda14cbcSMatt Macy typeset -i part 959eda14cbcSMatt Macy for disk in $DISKSARRAY; do 960eda14cbcSMatt Macy for (( part = 1; part < MAX_PARTITIONS; part++ )); do 961eda14cbcSMatt Macy typeset partition=${disk}${SLICE_PREFIX}${part} 962eda14cbcSMatt Macy parted $DEV_DSKDIR/$disk -s rm $part > /dev/null 2>&1 963eda14cbcSMatt Macy if lsblk | grep -qF ${partition}; then 964eda14cbcSMatt Macy log_fail "Partition ${partition} not deleted" 965eda14cbcSMatt Macy else 966eda14cbcSMatt Macy log_note "Partition ${partition} deleted" 967eda14cbcSMatt Macy fi 968eda14cbcSMatt Macy done 969eda14cbcSMatt Macy done 970eda14cbcSMatt Macy elif is_freebsd; then 971eda14cbcSMatt Macy for disk in $DISKSARRAY; do 972eda14cbcSMatt Macy if gpart destroy -F $disk; then 973eda14cbcSMatt Macy log_note "Partitions for ${disk} deleted" 974eda14cbcSMatt Macy else 975eda14cbcSMatt Macy log_fail "Partitions for ${disk} not deleted" 976eda14cbcSMatt Macy fi 977eda14cbcSMatt Macy done 978eda14cbcSMatt Macy fi 979eda14cbcSMatt Macy} 980eda14cbcSMatt Macy 981eda14cbcSMatt Macy# 982eda14cbcSMatt Macy# Get the end cyl of the given slice 983eda14cbcSMatt Macy# 984eda14cbcSMatt Macyfunction get_endslice #<disk> <slice> 985eda14cbcSMatt Macy{ 986eda14cbcSMatt Macy typeset disk=$1 987eda14cbcSMatt Macy typeset slice=$2 988eda14cbcSMatt Macy if [[ -z $disk || -z $slice ]] ; then 989eda14cbcSMatt Macy log_fail "The disk name or slice number is unspecified." 990eda14cbcSMatt Macy fi 991eda14cbcSMatt Macy 992716fd348SMartin Matuska case "$UNAME" in 993eda14cbcSMatt Macy Linux) 994eda14cbcSMatt Macy endcyl=$(parted -s $DEV_DSKDIR/$disk -- unit cyl print | \ 995dae17134SMartin Matuska awk "/part${slice}/"' {sub(/cyl/, "", $3); print $3}') 996eda14cbcSMatt Macy ((endcyl = (endcyl + 1))) 997eda14cbcSMatt Macy ;; 998eda14cbcSMatt Macy FreeBSD) 999eda14cbcSMatt Macy disk=${disk#/dev/zvol/} 1000eda14cbcSMatt Macy disk=${disk%p*} 1001eda14cbcSMatt Macy slice=$((slice + 1)) 1002eda14cbcSMatt Macy endcyl=$(gpart show $disk | \ 1003eda14cbcSMatt Macy awk -v slice=$slice '$3 == slice { print $1 + $2 }') 1004eda14cbcSMatt Macy ;; 1005eda14cbcSMatt Macy *) 1006eda14cbcSMatt Macy disk=${disk#/dev/dsk/} 1007eda14cbcSMatt Macy disk=${disk#/dev/rdsk/} 1008eda14cbcSMatt Macy disk=${disk%s*} 1009eda14cbcSMatt Macy 1010eda14cbcSMatt Macy typeset -i ratio=0 1011eda14cbcSMatt Macy ratio=$(prtvtoc /dev/rdsk/${disk}s2 | \ 1012716fd348SMartin Matuska awk '/sectors\/cylinder/ {print $2}') 1013eda14cbcSMatt Macy 1014eda14cbcSMatt Macy if ((ratio == 0)); then 1015eda14cbcSMatt Macy return 1016eda14cbcSMatt Macy fi 1017eda14cbcSMatt Macy 1018eda14cbcSMatt Macy typeset -i endcyl=$(prtvtoc -h /dev/rdsk/${disk}s2 | 1019716fd348SMartin Matuska awk -v token="$slice" '$1 == token {print $6}') 1020eda14cbcSMatt Macy 1021eda14cbcSMatt Macy ((endcyl = (endcyl + 1) / ratio)) 1022eda14cbcSMatt Macy ;; 1023eda14cbcSMatt Macy esac 1024eda14cbcSMatt Macy 1025eda14cbcSMatt Macy echo $endcyl 1026eda14cbcSMatt Macy} 1027eda14cbcSMatt Macy 1028eda14cbcSMatt Macy 1029eda14cbcSMatt Macy# 1030eda14cbcSMatt Macy# Given a size,disk and total slice number, this function formats the 1031eda14cbcSMatt Macy# disk slices from 0 to the total slice number with the same specified 1032eda14cbcSMatt Macy# size. 1033eda14cbcSMatt Macy# 1034eda14cbcSMatt Macyfunction partition_disk #<slice_size> <whole_disk_name> <total_slices> 1035eda14cbcSMatt Macy{ 1036eda14cbcSMatt Macy typeset -i i=0 1037eda14cbcSMatt Macy typeset slice_size=$1 1038eda14cbcSMatt Macy typeset disk_name=$2 1039eda14cbcSMatt Macy typeset total_slices=$3 1040eda14cbcSMatt Macy typeset cyl 1041eda14cbcSMatt Macy 1042eda14cbcSMatt Macy zero_partitions $disk_name 1043eda14cbcSMatt Macy while ((i < $total_slices)); do 1044eda14cbcSMatt Macy if ! is_linux; then 1045eda14cbcSMatt Macy if ((i == 2)); then 1046eda14cbcSMatt Macy ((i = i + 1)) 1047eda14cbcSMatt Macy continue 1048eda14cbcSMatt Macy fi 1049eda14cbcSMatt Macy fi 1050eda14cbcSMatt Macy log_must set_partition $i "$cyl" $slice_size $disk_name 1051eda14cbcSMatt Macy cyl=$(get_endslice $disk_name $i) 1052eda14cbcSMatt Macy ((i = i+1)) 1053eda14cbcSMatt Macy done 1054eda14cbcSMatt Macy} 1055eda14cbcSMatt Macy 1056eda14cbcSMatt Macy# 1057eda14cbcSMatt Macy# This function continues to write to a filenum number of files into dirnum 1058eda14cbcSMatt Macy# number of directories until either file_write returns an error or the 1059eda14cbcSMatt Macy# maximum number of files per directory have been written. 1060eda14cbcSMatt Macy# 1061eda14cbcSMatt Macy# Usage: 1062eda14cbcSMatt Macy# fill_fs [destdir] [dirnum] [filenum] [bytes] [num_writes] [data] 1063eda14cbcSMatt Macy# 1064eda14cbcSMatt Macy# Return value: 0 on success 1065eda14cbcSMatt Macy# non 0 on error 1066eda14cbcSMatt Macy# 1067eda14cbcSMatt Macy# Where : 1068eda14cbcSMatt Macy# destdir: is the directory where everything is to be created under 1069eda14cbcSMatt Macy# dirnum: the maximum number of subdirectories to use, -1 no limit 1070eda14cbcSMatt Macy# filenum: the maximum number of files per subdirectory 1071eda14cbcSMatt Macy# bytes: number of bytes to write 1072eda14cbcSMatt Macy# num_writes: number of types to write out bytes 1073eda14cbcSMatt Macy# data: the data that will be written 1074eda14cbcSMatt Macy# 1075eda14cbcSMatt Macy# E.g. 1076eda14cbcSMatt Macy# fill_fs /testdir 20 25 1024 256 0 1077eda14cbcSMatt Macy# 1078eda14cbcSMatt Macy# Note: bytes * num_writes equals the size of the testfile 1079eda14cbcSMatt Macy# 1080eda14cbcSMatt Macyfunction fill_fs # destdir dirnum filenum bytes num_writes data 1081eda14cbcSMatt Macy{ 1082eda14cbcSMatt Macy typeset destdir=${1:-$TESTDIR} 1083eda14cbcSMatt Macy typeset -i dirnum=${2:-50} 1084eda14cbcSMatt Macy typeset -i filenum=${3:-50} 1085eda14cbcSMatt Macy typeset -i bytes=${4:-8192} 1086eda14cbcSMatt Macy typeset -i num_writes=${5:-10240} 1087eda14cbcSMatt Macy typeset data=${6:-0} 1088eda14cbcSMatt Macy 1089eda14cbcSMatt Macy mkdir -p $destdir/{1..$dirnum} 1090eda14cbcSMatt Macy for f in $destdir/{1..$dirnum}/$TESTFILE{1..$filenum}; do 1091eda14cbcSMatt Macy file_write -o create -f $f -b $bytes -c $num_writes -d $data \ 1092716fd348SMartin Matuska || return 1093eda14cbcSMatt Macy done 1094eda14cbcSMatt Macy} 1095eda14cbcSMatt Macy 1096716fd348SMartin Matuska# Get the specified dataset property in parsable format or fail 1097eda14cbcSMatt Macyfunction get_prop # property dataset 1098eda14cbcSMatt Macy{ 1099eda14cbcSMatt Macy typeset prop=$1 1100eda14cbcSMatt Macy typeset dataset=$2 1101eda14cbcSMatt Macy 1102716fd348SMartin Matuska zfs get -Hpo value "$prop" "$dataset" || log_fail "zfs get $prop $dataset" 1103eda14cbcSMatt Macy} 1104eda14cbcSMatt Macy 1105716fd348SMartin Matuska# Get the specified pool property in parsable format or fail 1106eda14cbcSMatt Macyfunction get_pool_prop # property pool 1107eda14cbcSMatt Macy{ 1108eda14cbcSMatt Macy typeset prop=$1 1109eda14cbcSMatt Macy typeset pool=$2 1110eda14cbcSMatt Macy 1111716fd348SMartin Matuska zpool get -Hpo value "$prop" "$pool" || log_fail "zpool get $prop $pool" 1112eda14cbcSMatt Macy} 1113eda14cbcSMatt Macy 1114eda14cbcSMatt Macy# Return 0 if a pool exists; $? otherwise 1115eda14cbcSMatt Macy# 1116eda14cbcSMatt Macy# $1 - pool name 1117eda14cbcSMatt Macy 1118eda14cbcSMatt Macyfunction poolexists 1119eda14cbcSMatt Macy{ 1120eda14cbcSMatt Macy typeset pool=$1 1121eda14cbcSMatt Macy 1122eda14cbcSMatt Macy if [[ -z $pool ]]; then 1123eda14cbcSMatt Macy log_note "No pool name given." 1124eda14cbcSMatt Macy return 1 1125eda14cbcSMatt Macy fi 1126eda14cbcSMatt Macy 1127eda14cbcSMatt Macy zpool get name "$pool" > /dev/null 2>&1 1128eda14cbcSMatt Macy} 1129eda14cbcSMatt Macy 1130eda14cbcSMatt Macy# Return 0 if all the specified datasets exist; $? otherwise 1131eda14cbcSMatt Macy# 1132eda14cbcSMatt Macy# $1-n dataset name 1133eda14cbcSMatt Macyfunction datasetexists 1134eda14cbcSMatt Macy{ 1135eda14cbcSMatt Macy if (($# == 0)); then 1136eda14cbcSMatt Macy log_note "No dataset name given." 1137eda14cbcSMatt Macy return 1 1138eda14cbcSMatt Macy fi 1139eda14cbcSMatt Macy 1140716fd348SMartin Matuska zfs get name "$@" > /dev/null 2>&1 1141eda14cbcSMatt Macy} 1142eda14cbcSMatt Macy 1143eda14cbcSMatt Macy# return 0 if none of the specified datasets exists, otherwise return 1. 1144eda14cbcSMatt Macy# 1145eda14cbcSMatt Macy# $1-n dataset name 1146eda14cbcSMatt Macyfunction datasetnonexists 1147eda14cbcSMatt Macy{ 1148eda14cbcSMatt Macy if (($# == 0)); then 1149eda14cbcSMatt Macy log_note "No dataset name given." 1150eda14cbcSMatt Macy return 1 1151eda14cbcSMatt Macy fi 1152eda14cbcSMatt Macy 1153eda14cbcSMatt Macy while (($# > 0)); do 1154eda14cbcSMatt Macy zfs list -H -t filesystem,snapshot,volume $1 > /dev/null 2>&1 \ 1155eda14cbcSMatt Macy && return 1 1156eda14cbcSMatt Macy shift 1157eda14cbcSMatt Macy done 1158eda14cbcSMatt Macy 1159eda14cbcSMatt Macy return 0 1160eda14cbcSMatt Macy} 1161eda14cbcSMatt Macy 1162716fd348SMartin Matuska# FreeBSD breaks exports(5) at whitespace and doesn't process escapes 1163716fd348SMartin Matuska# Solaris just breaks 1164716fd348SMartin Matuska# 1165716fd348SMartin Matuska# cf. https://github.com/openzfs/zfs/pull/13165#issuecomment-1059845807 1166716fd348SMartin Matuska# 1167716fd348SMartin Matuska# Linux can have spaces (which are \OOO-escaped), 1168716fd348SMartin Matuska# but can't have backslashes because they're parsed recursively 1169716fd348SMartin Matuskafunction shares_can_have_whitespace 1170716fd348SMartin Matuska{ 1171716fd348SMartin Matuska is_linux 1172716fd348SMartin Matuska} 1173716fd348SMartin Matuska 1174eda14cbcSMatt Macyfunction is_shared_freebsd 1175eda14cbcSMatt Macy{ 1176eda14cbcSMatt Macy typeset fs=$1 1177eda14cbcSMatt Macy 1178716fd348SMartin Matuska pgrep -q mountd && showmount -E | grep -qx "$fs" 1179eda14cbcSMatt Macy} 1180eda14cbcSMatt Macy 1181eda14cbcSMatt Macyfunction is_shared_illumos 1182eda14cbcSMatt Macy{ 1183eda14cbcSMatt Macy typeset fs=$1 1184eda14cbcSMatt Macy typeset mtpt 1185eda14cbcSMatt Macy 1186eda14cbcSMatt Macy for mtpt in `share | awk '{print $2}'` ; do 1187eda14cbcSMatt Macy if [[ $mtpt == $fs ]] ; then 1188eda14cbcSMatt Macy return 0 1189eda14cbcSMatt Macy fi 1190eda14cbcSMatt Macy done 1191eda14cbcSMatt Macy 1192eda14cbcSMatt Macy typeset stat=$(svcs -H -o STA nfs/server:default) 1193eda14cbcSMatt Macy if [[ $stat != "ON" ]]; then 1194eda14cbcSMatt Macy log_note "Current nfs/server status: $stat" 1195eda14cbcSMatt Macy fi 1196eda14cbcSMatt Macy 1197eda14cbcSMatt Macy return 1 1198eda14cbcSMatt Macy} 1199eda14cbcSMatt Macy 1200eda14cbcSMatt Macyfunction is_shared_linux 1201eda14cbcSMatt Macy{ 1202eda14cbcSMatt Macy typeset fs=$1 1203716fd348SMartin Matuska ! exportfs -s | awk -v fs="${fs//\\/\\\\}" '/^\// && $1 == fs {exit 1}' 1204eda14cbcSMatt Macy} 1205eda14cbcSMatt Macy 1206eda14cbcSMatt Macy# 1207eda14cbcSMatt Macy# Given a mountpoint, or a dataset name, determine if it is shared via NFS. 1208eda14cbcSMatt Macy# 1209eda14cbcSMatt Macy# Returns 0 if shared, 1 otherwise. 1210eda14cbcSMatt Macy# 1211eda14cbcSMatt Macyfunction is_shared 1212eda14cbcSMatt Macy{ 1213eda14cbcSMatt Macy typeset fs=$1 1214eda14cbcSMatt Macy typeset mtpt 1215eda14cbcSMatt Macy 1216eda14cbcSMatt Macy if [[ $fs != "/"* ]] ; then 1217eda14cbcSMatt Macy if datasetnonexists "$fs" ; then 1218eda14cbcSMatt Macy return 1 1219eda14cbcSMatt Macy else 1220eda14cbcSMatt Macy mtpt=$(get_prop mountpoint "$fs") 1221716fd348SMartin Matuska case "$mtpt" in 1222eda14cbcSMatt Macy none|legacy|-) return 1 1223eda14cbcSMatt Macy ;; 1224eda14cbcSMatt Macy *) fs=$mtpt 1225eda14cbcSMatt Macy ;; 1226eda14cbcSMatt Macy esac 1227eda14cbcSMatt Macy fi 1228eda14cbcSMatt Macy fi 1229eda14cbcSMatt Macy 1230716fd348SMartin Matuska case "$UNAME" in 1231eda14cbcSMatt Macy FreeBSD) is_shared_freebsd "$fs" ;; 1232eda14cbcSMatt Macy Linux) is_shared_linux "$fs" ;; 1233eda14cbcSMatt Macy *) is_shared_illumos "$fs" ;; 1234eda14cbcSMatt Macy esac 1235eda14cbcSMatt Macy} 1236eda14cbcSMatt Macy 1237eda14cbcSMatt Macyfunction is_exported_illumos 1238eda14cbcSMatt Macy{ 1239eda14cbcSMatt Macy typeset fs=$1 1240716fd348SMartin Matuska typeset mtpt _ 1241eda14cbcSMatt Macy 1242716fd348SMartin Matuska while read -r mtpt _; do 1243716fd348SMartin Matuska [ "$mtpt" = "$fs" ] && return 1244716fd348SMartin Matuska done < /etc/dfs/sharetab 1245eda14cbcSMatt Macy 1246eda14cbcSMatt Macy return 1 1247eda14cbcSMatt Macy} 1248eda14cbcSMatt Macy 1249eda14cbcSMatt Macyfunction is_exported_freebsd 1250eda14cbcSMatt Macy{ 1251eda14cbcSMatt Macy typeset fs=$1 1252716fd348SMartin Matuska typeset mtpt _ 1253eda14cbcSMatt Macy 1254716fd348SMartin Matuska while read -r mtpt _; do 1255716fd348SMartin Matuska [ "$mtpt" = "$fs" ] && return 1256716fd348SMartin Matuska done < /etc/zfs/exports 1257eda14cbcSMatt Macy 1258eda14cbcSMatt Macy return 1 1259eda14cbcSMatt Macy} 1260eda14cbcSMatt Macy 1261eda14cbcSMatt Macyfunction is_exported_linux 1262eda14cbcSMatt Macy{ 1263eda14cbcSMatt Macy typeset fs=$1 1264716fd348SMartin Matuska typeset mtpt _ 1265eda14cbcSMatt Macy 1266716fd348SMartin Matuska while read -r mtpt _; do 1267716fd348SMartin Matuska [ "$(printf "$mtpt")" = "$fs" ] && return 1268716fd348SMartin Matuska done < /etc/exports.d/zfs.exports 1269eda14cbcSMatt Macy 1270eda14cbcSMatt Macy return 1 1271eda14cbcSMatt Macy} 1272eda14cbcSMatt Macy 1273eda14cbcSMatt Macy# 1274eda14cbcSMatt Macy# Given a mountpoint, or a dataset name, determine if it is exported via 1275eda14cbcSMatt Macy# the os-specific NFS exports file. 1276eda14cbcSMatt Macy# 1277eda14cbcSMatt Macy# Returns 0 if exported, 1 otherwise. 1278eda14cbcSMatt Macy# 1279eda14cbcSMatt Macyfunction is_exported 1280eda14cbcSMatt Macy{ 1281eda14cbcSMatt Macy typeset fs=$1 1282eda14cbcSMatt Macy typeset mtpt 1283eda14cbcSMatt Macy 1284eda14cbcSMatt Macy if [[ $fs != "/"* ]] ; then 1285eda14cbcSMatt Macy if datasetnonexists "$fs" ; then 1286eda14cbcSMatt Macy return 1 1287eda14cbcSMatt Macy else 1288eda14cbcSMatt Macy mtpt=$(get_prop mountpoint "$fs") 1289eda14cbcSMatt Macy case $mtpt in 1290eda14cbcSMatt Macy none|legacy|-) return 1 1291eda14cbcSMatt Macy ;; 1292eda14cbcSMatt Macy *) fs=$mtpt 1293eda14cbcSMatt Macy ;; 1294eda14cbcSMatt Macy esac 1295eda14cbcSMatt Macy fi 1296eda14cbcSMatt Macy fi 1297eda14cbcSMatt Macy 1298716fd348SMartin Matuska case "$UNAME" in 1299eda14cbcSMatt Macy FreeBSD) is_exported_freebsd "$fs" ;; 1300eda14cbcSMatt Macy Linux) is_exported_linux "$fs" ;; 1301eda14cbcSMatt Macy *) is_exported_illumos "$fs" ;; 1302eda14cbcSMatt Macy esac 1303eda14cbcSMatt Macy} 1304eda14cbcSMatt Macy 1305eda14cbcSMatt Macy# 1306eda14cbcSMatt Macy# Given a dataset name determine if it is shared via SMB. 1307eda14cbcSMatt Macy# 1308eda14cbcSMatt Macy# Returns 0 if shared, 1 otherwise. 1309eda14cbcSMatt Macy# 1310eda14cbcSMatt Macyfunction is_shared_smb 1311eda14cbcSMatt Macy{ 1312eda14cbcSMatt Macy typeset fs=$1 1313eda14cbcSMatt Macy 1314716fd348SMartin Matuska datasetexists "$fs" || return 1315eda14cbcSMatt Macy 1316eda14cbcSMatt Macy if is_linux; then 1317c7046f76SMartin Matuska net usershare list | grep -xFq "${fs//[-\/]/_}" 1318eda14cbcSMatt Macy else 1319716fd348SMartin Matuska log_note "SMB on $UNAME currently unsupported by the test framework" 1320eda14cbcSMatt Macy return 1 1321eda14cbcSMatt Macy fi 1322eda14cbcSMatt Macy} 1323eda14cbcSMatt Macy 1324eda14cbcSMatt Macy# 1325eda14cbcSMatt Macy# Given a mountpoint, determine if it is not shared via NFS. 1326eda14cbcSMatt Macy# 1327eda14cbcSMatt Macy# Returns 0 if not shared, 1 otherwise. 1328eda14cbcSMatt Macy# 1329eda14cbcSMatt Macyfunction not_shared 1330eda14cbcSMatt Macy{ 1331716fd348SMartin Matuska ! is_shared $1 1332eda14cbcSMatt Macy} 1333eda14cbcSMatt Macy 1334eda14cbcSMatt Macy# 1335eda14cbcSMatt Macy# Given a dataset determine if it is not shared via SMB. 1336eda14cbcSMatt Macy# 1337eda14cbcSMatt Macy# Returns 0 if not shared, 1 otherwise. 1338eda14cbcSMatt Macy# 1339eda14cbcSMatt Macyfunction not_shared_smb 1340eda14cbcSMatt Macy{ 1341716fd348SMartin Matuska ! is_shared_smb $1 1342eda14cbcSMatt Macy} 1343eda14cbcSMatt Macy 1344eda14cbcSMatt Macy# 1345eda14cbcSMatt Macy# Helper function to unshare a mountpoint. 1346eda14cbcSMatt Macy# 1347eda14cbcSMatt Macyfunction unshare_fs #fs 1348eda14cbcSMatt Macy{ 1349eda14cbcSMatt Macy typeset fs=$1 1350eda14cbcSMatt Macy 1351716fd348SMartin Matuska if is_shared $fs || is_shared_smb $fs; then 1352716fd348SMartin Matuska log_must zfs unshare $fs 1353eda14cbcSMatt Macy fi 1354eda14cbcSMatt Macy} 1355eda14cbcSMatt Macy 1356eda14cbcSMatt Macy# 1357eda14cbcSMatt Macy# Helper function to share a NFS mountpoint. 1358eda14cbcSMatt Macy# 1359eda14cbcSMatt Macyfunction share_nfs #fs 1360eda14cbcSMatt Macy{ 1361eda14cbcSMatt Macy typeset fs=$1 1362eda14cbcSMatt Macy 1363716fd348SMartin Matuska is_shared "$fs" && return 1364716fd348SMartin Matuska 1365716fd348SMartin Matuska case "$UNAME" in 1366716fd348SMartin Matuska Linux) 1367716fd348SMartin Matuska log_must exportfs "*:$fs" 1368716fd348SMartin Matuska ;; 1369716fd348SMartin Matuska FreeBSD) 1370716fd348SMartin Matuska typeset mountd 1371716fd348SMartin Matuska read -r mountd < /var/run/mountd.pid 1372716fd348SMartin Matuska log_must eval "printf '%s\t\n' \"$fs\" >> /etc/zfs/exports" 1373716fd348SMartin Matuska log_must kill -s HUP "$mountd" 1374716fd348SMartin Matuska ;; 1375716fd348SMartin Matuska *) 1376716fd348SMartin Matuska log_must share -F nfs "$fs" 1377716fd348SMartin Matuska ;; 1378716fd348SMartin Matuska esac 1379eda14cbcSMatt Macy 1380eda14cbcSMatt Macy return 0 1381eda14cbcSMatt Macy} 1382eda14cbcSMatt Macy 1383eda14cbcSMatt Macy# 1384eda14cbcSMatt Macy# Helper function to unshare a NFS mountpoint. 1385eda14cbcSMatt Macy# 1386eda14cbcSMatt Macyfunction unshare_nfs #fs 1387eda14cbcSMatt Macy{ 1388eda14cbcSMatt Macy typeset fs=$1 1389eda14cbcSMatt Macy 1390716fd348SMartin Matuska ! is_shared "$fs" && return 1391716fd348SMartin Matuska 1392716fd348SMartin Matuska case "$UNAME" in 1393716fd348SMartin Matuska Linux) 1394716fd348SMartin Matuska log_must exportfs -u "*:$fs" 1395716fd348SMartin Matuska ;; 1396716fd348SMartin Matuska FreeBSD) 1397716fd348SMartin Matuska typeset mountd 1398716fd348SMartin Matuska read -r mountd < /var/run/mountd.pid 1399716fd348SMartin Matuska awk -v fs="${fs//\\/\\\\}" '$1 != fs' /etc/zfs/exports > /etc/zfs/exports.$$ 1400716fd348SMartin Matuska log_must mv /etc/zfs/exports.$$ /etc/zfs/exports 1401716fd348SMartin Matuska log_must kill -s HUP "$mountd" 1402716fd348SMartin Matuska ;; 1403716fd348SMartin Matuska *) 1404eda14cbcSMatt Macy log_must unshare -F nfs $fs 1405716fd348SMartin Matuska ;; 1406716fd348SMartin Matuska esac 1407eda14cbcSMatt Macy 1408eda14cbcSMatt Macy return 0 1409eda14cbcSMatt Macy} 1410eda14cbcSMatt Macy 1411eda14cbcSMatt Macy# 1412eda14cbcSMatt Macy# Helper function to show NFS shares. 1413eda14cbcSMatt Macy# 1414eda14cbcSMatt Macyfunction showshares_nfs 1415eda14cbcSMatt Macy{ 1416716fd348SMartin Matuska case "$UNAME" in 1417716fd348SMartin Matuska Linux) 1418716fd348SMartin Matuska exportfs -v 1419716fd348SMartin Matuska ;; 1420716fd348SMartin Matuska FreeBSD) 1421716fd348SMartin Matuska showmount 1422716fd348SMartin Matuska ;; 1423716fd348SMartin Matuska *) 1424eda14cbcSMatt Macy share -F nfs 1425716fd348SMartin Matuska ;; 1426716fd348SMartin Matuska esac 1427eda14cbcSMatt Macy} 1428eda14cbcSMatt Macy 1429eda14cbcSMatt Macyfunction check_nfs 1430eda14cbcSMatt Macy{ 1431716fd348SMartin Matuska case "$UNAME" in 1432716fd348SMartin Matuska Linux) 1433716fd348SMartin Matuska exportfs -s 1434716fd348SMartin Matuska ;; 1435716fd348SMartin Matuska FreeBSD) 1436eda14cbcSMatt Macy showmount -e 1437716fd348SMartin Matuska ;; 1438716fd348SMartin Matuska *) 1439eda14cbcSMatt Macy log_unsupported "Unknown platform" 1440716fd348SMartin Matuska ;; 1441716fd348SMartin Matuska esac || log_unsupported "The NFS utilities are not installed" 1442eda14cbcSMatt Macy} 1443eda14cbcSMatt Macy 1444eda14cbcSMatt Macy# 1445eda14cbcSMatt Macy# Check NFS server status and trigger it online. 1446eda14cbcSMatt Macy# 1447eda14cbcSMatt Macyfunction setup_nfs_server 1448eda14cbcSMatt Macy{ 1449eda14cbcSMatt Macy # Cannot share directory in non-global zone. 1450eda14cbcSMatt Macy # 1451eda14cbcSMatt Macy if ! is_global_zone; then 1452eda14cbcSMatt Macy log_note "Cannot trigger NFS server by sharing in LZ." 1453eda14cbcSMatt Macy return 1454eda14cbcSMatt Macy fi 1455eda14cbcSMatt Macy 1456eda14cbcSMatt Macy if is_linux; then 1457eda14cbcSMatt Macy # 1458eda14cbcSMatt Macy # Re-synchronize /var/lib/nfs/etab with /etc/exports and 1459eda14cbcSMatt Macy # /etc/exports.d./* to provide a clean test environment. 1460eda14cbcSMatt Macy # 1461716fd348SMartin Matuska log_must exportfs -r 1462eda14cbcSMatt Macy 1463eda14cbcSMatt Macy log_note "NFS server must be started prior to running ZTS." 1464eda14cbcSMatt Macy return 1465eda14cbcSMatt Macy elif is_freebsd; then 1466716fd348SMartin Matuska log_must kill -s HUP $(</var/run/mountd.pid) 1467eda14cbcSMatt Macy 1468eda14cbcSMatt Macy log_note "NFS server must be started prior to running ZTS." 1469eda14cbcSMatt Macy return 1470eda14cbcSMatt Macy fi 1471eda14cbcSMatt Macy 1472eda14cbcSMatt Macy typeset nfs_fmri="svc:/network/nfs/server:default" 1473eda14cbcSMatt Macy if [[ $(svcs -Ho STA $nfs_fmri) != "ON" ]]; then 1474eda14cbcSMatt Macy # 1475eda14cbcSMatt Macy # Only really sharing operation can enable NFS server 1476eda14cbcSMatt Macy # to online permanently. 1477eda14cbcSMatt Macy # 1478eda14cbcSMatt Macy typeset dummy=/tmp/dummy 1479eda14cbcSMatt Macy 1480eda14cbcSMatt Macy if [[ -d $dummy ]]; then 1481eda14cbcSMatt Macy log_must rm -rf $dummy 1482eda14cbcSMatt Macy fi 1483eda14cbcSMatt Macy 1484eda14cbcSMatt Macy log_must mkdir $dummy 1485eda14cbcSMatt Macy log_must share $dummy 1486eda14cbcSMatt Macy 1487eda14cbcSMatt Macy # 1488eda14cbcSMatt Macy # Waiting for fmri's status to be the final status. 1489eda14cbcSMatt Macy # Otherwise, in transition, an asterisk (*) is appended for 1490eda14cbcSMatt Macy # instances, unshare will reverse status to 'DIS' again. 1491eda14cbcSMatt Macy # 1492eda14cbcSMatt Macy # Waiting for 1's at least. 1493eda14cbcSMatt Macy # 1494eda14cbcSMatt Macy log_must sleep 1 1495eda14cbcSMatt Macy timeout=10 1496eda14cbcSMatt Macy while [[ timeout -ne 0 && $(svcs -Ho STA $nfs_fmri) == *'*' ]] 1497eda14cbcSMatt Macy do 1498eda14cbcSMatt Macy log_must sleep 1 1499eda14cbcSMatt Macy 1500eda14cbcSMatt Macy ((timeout -= 1)) 1501eda14cbcSMatt Macy done 1502eda14cbcSMatt Macy 1503eda14cbcSMatt Macy log_must unshare $dummy 1504eda14cbcSMatt Macy log_must rm -rf $dummy 1505eda14cbcSMatt Macy fi 1506eda14cbcSMatt Macy 1507eda14cbcSMatt Macy log_note "Current NFS status: '$(svcs -Ho STA,FMRI $nfs_fmri)'" 1508eda14cbcSMatt Macy} 1509eda14cbcSMatt Macy 1510eda14cbcSMatt Macy# 1511eda14cbcSMatt Macy# To verify whether calling process is in global zone 1512eda14cbcSMatt Macy# 1513eda14cbcSMatt Macy# Return 0 if in global zone, 1 in non-global zone 1514eda14cbcSMatt Macy# 1515eda14cbcSMatt Macyfunction is_global_zone 1516eda14cbcSMatt Macy{ 1517eda14cbcSMatt Macy if is_linux || is_freebsd; then 1518eda14cbcSMatt Macy return 0 1519eda14cbcSMatt Macy else 1520eda14cbcSMatt Macy typeset cur_zone=$(zonename 2>/dev/null) 1521716fd348SMartin Matuska [ $cur_zone = "global" ] 1522eda14cbcSMatt Macy fi 1523eda14cbcSMatt Macy} 1524eda14cbcSMatt Macy 1525eda14cbcSMatt Macy# 1526eda14cbcSMatt Macy# Verify whether test is permitted to run from 1527eda14cbcSMatt Macy# global zone, local zone, or both 1528eda14cbcSMatt Macy# 1529eda14cbcSMatt Macy# $1 zone limit, could be "global", "local", or "both"(no limit) 1530eda14cbcSMatt Macy# 1531eda14cbcSMatt Macy# Return 0 if permitted, otherwise exit with log_unsupported 1532eda14cbcSMatt Macy# 1533eda14cbcSMatt Macyfunction verify_runnable # zone limit 1534eda14cbcSMatt Macy{ 1535eda14cbcSMatt Macy typeset limit=$1 1536eda14cbcSMatt Macy 1537eda14cbcSMatt Macy [[ -z $limit ]] && return 0 1538eda14cbcSMatt Macy 1539eda14cbcSMatt Macy if is_global_zone ; then 1540eda14cbcSMatt Macy case $limit in 1541eda14cbcSMatt Macy global|both) 1542eda14cbcSMatt Macy ;; 1543eda14cbcSMatt Macy local) log_unsupported "Test is unable to run from "\ 1544eda14cbcSMatt Macy "global zone." 1545eda14cbcSMatt Macy ;; 1546eda14cbcSMatt Macy *) log_note "Warning: unknown limit $limit - " \ 1547eda14cbcSMatt Macy "use both." 1548eda14cbcSMatt Macy ;; 1549eda14cbcSMatt Macy esac 1550eda14cbcSMatt Macy else 1551eda14cbcSMatt Macy case $limit in 1552eda14cbcSMatt Macy local|both) 1553eda14cbcSMatt Macy ;; 1554eda14cbcSMatt Macy global) log_unsupported "Test is unable to run from "\ 1555eda14cbcSMatt Macy "local zone." 1556eda14cbcSMatt Macy ;; 1557eda14cbcSMatt Macy *) log_note "Warning: unknown limit $limit - " \ 1558eda14cbcSMatt Macy "use both." 1559eda14cbcSMatt Macy ;; 1560eda14cbcSMatt Macy esac 1561eda14cbcSMatt Macy 1562eda14cbcSMatt Macy reexport_pool 1563eda14cbcSMatt Macy fi 1564eda14cbcSMatt Macy 1565eda14cbcSMatt Macy return 0 1566eda14cbcSMatt Macy} 1567eda14cbcSMatt Macy 1568eda14cbcSMatt Macy# Return 0 if create successfully or the pool exists; $? otherwise 1569eda14cbcSMatt Macy# Note: In local zones, this function should return 0 silently. 1570eda14cbcSMatt Macy# 1571eda14cbcSMatt Macy# $1 - pool name 1572eda14cbcSMatt Macy# $2-n - [keyword] devs_list 1573eda14cbcSMatt Macy 1574eda14cbcSMatt Macyfunction create_pool #pool devs_list 1575eda14cbcSMatt Macy{ 1576eda14cbcSMatt Macy typeset pool=${1%%/*} 1577eda14cbcSMatt Macy 1578eda14cbcSMatt Macy shift 1579eda14cbcSMatt Macy 1580eda14cbcSMatt Macy if [[ -z $pool ]]; then 1581eda14cbcSMatt Macy log_note "Missing pool name." 1582eda14cbcSMatt Macy return 1 1583eda14cbcSMatt Macy fi 1584eda14cbcSMatt Macy 1585eda14cbcSMatt Macy if poolexists $pool ; then 1586eda14cbcSMatt Macy destroy_pool $pool 1587eda14cbcSMatt Macy fi 1588eda14cbcSMatt Macy 1589eda14cbcSMatt Macy if is_global_zone ; then 1590eda14cbcSMatt Macy [[ -d /$pool ]] && rm -rf /$pool 1591eda14cbcSMatt Macy log_must zpool create -f $pool $@ 1592eda14cbcSMatt Macy fi 1593eda14cbcSMatt Macy 1594eda14cbcSMatt Macy return 0 1595eda14cbcSMatt Macy} 1596eda14cbcSMatt Macy 1597eda14cbcSMatt Macy# Return 0 if destroy successfully or the pool exists; $? otherwise 1598eda14cbcSMatt Macy# Note: In local zones, this function should return 0 silently. 1599eda14cbcSMatt Macy# 1600eda14cbcSMatt Macy# $1 - pool name 1601eda14cbcSMatt Macy# Destroy pool with the given parameters. 1602eda14cbcSMatt Macy 1603eda14cbcSMatt Macyfunction destroy_pool #pool 1604eda14cbcSMatt Macy{ 1605eda14cbcSMatt Macy typeset pool=${1%%/*} 1606eda14cbcSMatt Macy typeset mtpt 1607eda14cbcSMatt Macy 1608eda14cbcSMatt Macy if [[ -z $pool ]]; then 1609eda14cbcSMatt Macy log_note "No pool name given." 1610eda14cbcSMatt Macy return 1 1611eda14cbcSMatt Macy fi 1612eda14cbcSMatt Macy 1613eda14cbcSMatt Macy if is_global_zone ; then 1614eda14cbcSMatt Macy if poolexists "$pool" ; then 1615eda14cbcSMatt Macy mtpt=$(get_prop mountpoint "$pool") 1616eda14cbcSMatt Macy 1617eda14cbcSMatt Macy # At times, syseventd/udev activity can cause attempts 1618eda14cbcSMatt Macy # to destroy a pool to fail with EBUSY. We retry a few 1619eda14cbcSMatt Macy # times allowing failures before requiring the destroy 1620eda14cbcSMatt Macy # to succeed. 1621eda14cbcSMatt Macy log_must_busy zpool destroy -f $pool 1622eda14cbcSMatt Macy 1623eda14cbcSMatt Macy [[ -d $mtpt ]] && \ 1624eda14cbcSMatt Macy log_must rm -rf $mtpt 1625eda14cbcSMatt Macy else 1626eda14cbcSMatt Macy log_note "Pool does not exist. ($pool)" 1627eda14cbcSMatt Macy return 1 1628eda14cbcSMatt Macy fi 1629eda14cbcSMatt Macy fi 1630eda14cbcSMatt Macy 1631eda14cbcSMatt Macy return 0 1632eda14cbcSMatt Macy} 1633eda14cbcSMatt Macy 1634eda14cbcSMatt Macy# Return 0 if created successfully; $? otherwise 1635eda14cbcSMatt Macy# 1636eda14cbcSMatt Macy# $1 - dataset name 1637eda14cbcSMatt Macy# $2-n - dataset options 1638eda14cbcSMatt Macy 1639eda14cbcSMatt Macyfunction create_dataset #dataset dataset_options 1640eda14cbcSMatt Macy{ 1641eda14cbcSMatt Macy typeset dataset=$1 1642eda14cbcSMatt Macy 1643eda14cbcSMatt Macy shift 1644eda14cbcSMatt Macy 1645eda14cbcSMatt Macy if [[ -z $dataset ]]; then 1646eda14cbcSMatt Macy log_note "Missing dataset name." 1647eda14cbcSMatt Macy return 1 1648eda14cbcSMatt Macy fi 1649eda14cbcSMatt Macy 1650eda14cbcSMatt Macy if datasetexists $dataset ; then 1651eda14cbcSMatt Macy destroy_dataset $dataset 1652eda14cbcSMatt Macy fi 1653eda14cbcSMatt Macy 1654eda14cbcSMatt Macy log_must zfs create $@ $dataset 1655eda14cbcSMatt Macy 1656eda14cbcSMatt Macy return 0 1657eda14cbcSMatt Macy} 1658eda14cbcSMatt Macy 1659eda14cbcSMatt Macy# Return 0 if destroy successfully or the dataset exists; $? otherwise 1660eda14cbcSMatt Macy# Note: In local zones, this function should return 0 silently. 1661eda14cbcSMatt Macy# 1662eda14cbcSMatt Macy# $1 - dataset name 1663eda14cbcSMatt Macy# $2 - custom arguments for zfs destroy 1664eda14cbcSMatt Macy# Destroy dataset with the given parameters. 1665eda14cbcSMatt Macy 1666716fd348SMartin Matuskafunction destroy_dataset # dataset [args] 1667eda14cbcSMatt Macy{ 1668eda14cbcSMatt Macy typeset dataset=$1 1669eda14cbcSMatt Macy typeset mtpt 1670eda14cbcSMatt Macy typeset args=${2:-""} 1671eda14cbcSMatt Macy 1672eda14cbcSMatt Macy if [[ -z $dataset ]]; then 1673eda14cbcSMatt Macy log_note "No dataset name given." 1674eda14cbcSMatt Macy return 1 1675eda14cbcSMatt Macy fi 1676eda14cbcSMatt Macy 1677eda14cbcSMatt Macy if is_global_zone ; then 1678eda14cbcSMatt Macy if datasetexists "$dataset" ; then 1679eda14cbcSMatt Macy mtpt=$(get_prop mountpoint "$dataset") 1680eda14cbcSMatt Macy log_must_busy zfs destroy $args $dataset 1681eda14cbcSMatt Macy 1682716fd348SMartin Matuska [ -d $mtpt ] && log_must rm -rf $mtpt 1683eda14cbcSMatt Macy else 1684eda14cbcSMatt Macy log_note "Dataset does not exist. ($dataset)" 1685eda14cbcSMatt Macy return 1 1686eda14cbcSMatt Macy fi 1687eda14cbcSMatt Macy fi 1688eda14cbcSMatt Macy 1689eda14cbcSMatt Macy return 0 1690eda14cbcSMatt Macy} 1691eda14cbcSMatt Macy 1692eda14cbcSMatt Macy# 1693eda14cbcSMatt Macy# Reexport TESTPOOL & TESTPOOL(1-4) 1694eda14cbcSMatt Macy# 1695eda14cbcSMatt Macyfunction reexport_pool 1696eda14cbcSMatt Macy{ 1697eda14cbcSMatt Macy typeset -i cntctr=5 1698eda14cbcSMatt Macy typeset -i i=0 1699eda14cbcSMatt Macy 1700eda14cbcSMatt Macy while ((i < cntctr)); do 1701eda14cbcSMatt Macy if ((i == 0)); then 1702eda14cbcSMatt Macy TESTPOOL=$ZONE_POOL/$ZONE_CTR$i 1703eda14cbcSMatt Macy if ! ismounted $TESTPOOL; then 1704eda14cbcSMatt Macy log_must zfs mount $TESTPOOL 1705eda14cbcSMatt Macy fi 1706eda14cbcSMatt Macy else 1707eda14cbcSMatt Macy eval TESTPOOL$i=$ZONE_POOL/$ZONE_CTR$i 1708eda14cbcSMatt Macy if eval ! ismounted \$TESTPOOL$i; then 1709eda14cbcSMatt Macy log_must eval zfs mount \$TESTPOOL$i 1710eda14cbcSMatt Macy fi 1711eda14cbcSMatt Macy fi 1712eda14cbcSMatt Macy ((i += 1)) 1713eda14cbcSMatt Macy done 1714eda14cbcSMatt Macy} 1715eda14cbcSMatt Macy 1716eda14cbcSMatt Macy# 1717eda14cbcSMatt Macy# Verify a given disk or pool state 1718eda14cbcSMatt Macy# 1719eda14cbcSMatt Macy# Return 0 is pool/disk matches expected state, 1 otherwise 1720eda14cbcSMatt Macy# 1721eda14cbcSMatt Macyfunction check_state # pool disk state{online,offline,degraded} 1722eda14cbcSMatt Macy{ 1723eda14cbcSMatt Macy typeset pool=$1 1724eda14cbcSMatt Macy typeset disk=${2#$DEV_DSKDIR/} 1725eda14cbcSMatt Macy typeset state=$3 1726eda14cbcSMatt Macy 1727eda14cbcSMatt Macy [[ -z $pool ]] || [[ -z $state ]] \ 1728eda14cbcSMatt Macy && log_fail "Arguments invalid or missing" 1729eda14cbcSMatt Macy 1730eda14cbcSMatt Macy if [[ -z $disk ]]; then 1731eda14cbcSMatt Macy #check pool state only 1732716fd348SMartin Matuska zpool get -H -o value health $pool | grep -qi "$state" 1733eda14cbcSMatt Macy else 1734716fd348SMartin Matuska zpool status -v $pool | grep "$disk" | grep -qi "$state" 1735eda14cbcSMatt Macy fi 1736eda14cbcSMatt Macy} 1737eda14cbcSMatt Macy 1738eda14cbcSMatt Macy# 1739eda14cbcSMatt Macy# Get the mountpoint of snapshot 1740eda14cbcSMatt Macy# For the snapshot use <mp_filesystem>/.zfs/snapshot/<snap> 1741eda14cbcSMatt Macy# as its mountpoint 1742eda14cbcSMatt Macy# 1743eda14cbcSMatt Macyfunction snapshot_mountpoint 1744eda14cbcSMatt Macy{ 1745eda14cbcSMatt Macy typeset dataset=${1:-$TESTPOOL/$TESTFS@$TESTSNAP} 1746eda14cbcSMatt Macy 1747eda14cbcSMatt Macy if [[ $dataset != *@* ]]; then 1748eda14cbcSMatt Macy log_fail "Error name of snapshot '$dataset'." 1749eda14cbcSMatt Macy fi 1750eda14cbcSMatt Macy 1751eda14cbcSMatt Macy typeset fs=${dataset%@*} 1752eda14cbcSMatt Macy typeset snap=${dataset#*@} 1753eda14cbcSMatt Macy 1754eda14cbcSMatt Macy if [[ -z $fs || -z $snap ]]; then 1755eda14cbcSMatt Macy log_fail "Error name of snapshot '$dataset'." 1756eda14cbcSMatt Macy fi 1757eda14cbcSMatt Macy 1758eda14cbcSMatt Macy echo $(get_prop mountpoint $fs)/.zfs/snapshot/$snap 1759eda14cbcSMatt Macy} 1760eda14cbcSMatt Macy 1761eda14cbcSMatt Macy# 1762eda14cbcSMatt Macy# Given a device and 'ashift' value verify it's correctly set on every label 1763eda14cbcSMatt Macy# 1764eda14cbcSMatt Macyfunction verify_ashift # device ashift 1765eda14cbcSMatt Macy{ 1766eda14cbcSMatt Macy typeset device="$1" 1767eda14cbcSMatt Macy typeset ashift="$2" 1768eda14cbcSMatt Macy 1769716fd348SMartin Matuska zdb -e -lll $device | awk -v ashift=$ashift ' 1770716fd348SMartin Matuska /ashift: / { 1771eda14cbcSMatt Macy if (ashift != $2) 1772eda14cbcSMatt Macy exit 1; 1773eda14cbcSMatt Macy else 1774eda14cbcSMatt Macy count++; 1775716fd348SMartin Matuska } 1776716fd348SMartin Matuska END { 1777716fd348SMartin Matuska exit (count != 4); 1778eda14cbcSMatt Macy }' 1779eda14cbcSMatt Macy} 1780eda14cbcSMatt Macy 1781eda14cbcSMatt Macy# 1782eda14cbcSMatt Macy# Given a pool and file system, this function will verify the file system 1783eda14cbcSMatt Macy# using the zdb internal tool. Note that the pool is exported and imported 1784eda14cbcSMatt Macy# to ensure it has consistent state. 1785eda14cbcSMatt Macy# 1786eda14cbcSMatt Macyfunction verify_filesys # pool filesystem dir 1787eda14cbcSMatt Macy{ 1788eda14cbcSMatt Macy typeset pool="$1" 1789eda14cbcSMatt Macy typeset filesys="$2" 1790eda14cbcSMatt Macy typeset zdbout="/tmp/zdbout.$$" 1791eda14cbcSMatt Macy 1792eda14cbcSMatt Macy shift 1793eda14cbcSMatt Macy shift 1794eda14cbcSMatt Macy typeset dirs=$@ 1795eda14cbcSMatt Macy typeset search_path="" 1796eda14cbcSMatt Macy 1797eda14cbcSMatt Macy log_note "Calling zdb to verify filesystem '$filesys'" 1798eda14cbcSMatt Macy zfs unmount -a > /dev/null 2>&1 1799eda14cbcSMatt Macy log_must zpool export $pool 1800eda14cbcSMatt Macy 1801eda14cbcSMatt Macy if [[ -n $dirs ]] ; then 1802eda14cbcSMatt Macy for dir in $dirs ; do 1803eda14cbcSMatt Macy search_path="$search_path -d $dir" 1804eda14cbcSMatt Macy done 1805eda14cbcSMatt Macy fi 1806eda14cbcSMatt Macy 1807eda14cbcSMatt Macy log_must zpool import $search_path $pool 1808eda14cbcSMatt Macy 1809716fd348SMartin Matuska if ! zdb -cudi $filesys > $zdbout 2>&1; then 1810eda14cbcSMatt Macy log_note "Output: zdb -cudi $filesys" 1811eda14cbcSMatt Macy cat $zdbout 1812716fd348SMartin Matuska rm -f $zdbout 1813eda14cbcSMatt Macy log_fail "zdb detected errors with: '$filesys'" 1814eda14cbcSMatt Macy fi 1815eda14cbcSMatt Macy 1816eda14cbcSMatt Macy log_must zfs mount -a 1817eda14cbcSMatt Macy log_must rm -rf $zdbout 1818eda14cbcSMatt Macy} 1819eda14cbcSMatt Macy 1820eda14cbcSMatt Macy# 1821eda14cbcSMatt Macy# Given a pool issue a scrub and verify that no checksum errors are reported. 1822eda14cbcSMatt Macy# 1823eda14cbcSMatt Macyfunction verify_pool 1824eda14cbcSMatt Macy{ 1825eda14cbcSMatt Macy typeset pool=${1:-$TESTPOOL} 1826eda14cbcSMatt Macy 1827eda14cbcSMatt Macy log_must zpool scrub $pool 1828eda14cbcSMatt Macy log_must wait_scrubbed $pool 1829eda14cbcSMatt Macy 1830eda14cbcSMatt Macy typeset -i cksum=$(zpool status $pool | awk ' 1831eda14cbcSMatt Macy !NF { isvdev = 0 } 1832eda14cbcSMatt Macy isvdev { errors += $NF } 1833eda14cbcSMatt Macy /CKSUM$/ { isvdev = 1 } 1834eda14cbcSMatt Macy END { print errors } 1835eda14cbcSMatt Macy ') 1836eda14cbcSMatt Macy if [[ $cksum != 0 ]]; then 1837eda14cbcSMatt Macy log_must zpool status -v 1838eda14cbcSMatt Macy log_fail "Unexpected CKSUM errors found on $pool ($cksum)" 1839eda14cbcSMatt Macy fi 1840eda14cbcSMatt Macy} 1841eda14cbcSMatt Macy 1842eda14cbcSMatt Macy# 1843eda14cbcSMatt Macy# Given a pool, and this function list all disks in the pool 1844eda14cbcSMatt Macy# 1845eda14cbcSMatt Macyfunction get_disklist # pool 1846eda14cbcSMatt Macy{ 1847716fd348SMartin Matuska echo $(zpool iostat -v $1 | awk '(NR > 4) {print $1}' | \ 1848716fd348SMartin Matuska grep -vEe '^-----' -e "^(mirror|raidz[1-3]|draid[1-3]|spare|log|cache|special|dedup)|\-[0-9]$") 1849eda14cbcSMatt Macy} 1850eda14cbcSMatt Macy 1851eda14cbcSMatt Macy# 1852eda14cbcSMatt Macy# Given a pool, and this function list all disks in the pool with their full 1853eda14cbcSMatt Macy# path (like "/dev/sda" instead of "sda"). 1854eda14cbcSMatt Macy# 1855eda14cbcSMatt Macyfunction get_disklist_fullpath # pool 1856eda14cbcSMatt Macy{ 1857716fd348SMartin Matuska get_disklist "-P $1" 1858eda14cbcSMatt Macy} 1859eda14cbcSMatt Macy 1860eda14cbcSMatt Macy 1861eda14cbcSMatt Macy 1862eda14cbcSMatt Macy# /** 1863eda14cbcSMatt Macy# This function kills a given list of processes after a time period. We use 1864eda14cbcSMatt Macy# this in the stress tests instead of STF_TIMEOUT so that we can have processes 1865eda14cbcSMatt Macy# run for a fixed amount of time, yet still pass. Tests that hit STF_TIMEOUT 1866eda14cbcSMatt Macy# would be listed as FAIL, which we don't want : we're happy with stress tests 1867eda14cbcSMatt Macy# running for a certain amount of time, then finishing. 1868eda14cbcSMatt Macy# 1869eda14cbcSMatt Macy# @param $1 the time in seconds after which we should terminate these processes 1870eda14cbcSMatt Macy# @param $2..$n the processes we wish to terminate. 1871eda14cbcSMatt Macy# */ 1872eda14cbcSMatt Macyfunction stress_timeout 1873eda14cbcSMatt Macy{ 1874eda14cbcSMatt Macy typeset -i TIMEOUT=$1 1875eda14cbcSMatt Macy shift 1876eda14cbcSMatt Macy typeset cpids="$@" 1877eda14cbcSMatt Macy 1878eda14cbcSMatt Macy log_note "Waiting for child processes($cpids). " \ 1879eda14cbcSMatt Macy "It could last dozens of minutes, please be patient ..." 1880eda14cbcSMatt Macy log_must sleep $TIMEOUT 1881eda14cbcSMatt Macy 1882eda14cbcSMatt Macy log_note "Killing child processes after ${TIMEOUT} stress timeout." 1883eda14cbcSMatt Macy typeset pid 1884eda14cbcSMatt Macy for pid in $cpids; do 1885716fd348SMartin Matuska ps -p $pid > /dev/null 2>&1 && 1886eda14cbcSMatt Macy log_must kill -USR1 $pid 1887eda14cbcSMatt Macy done 1888eda14cbcSMatt Macy} 1889eda14cbcSMatt Macy 1890eda14cbcSMatt Macy# 1891eda14cbcSMatt Macy# Verify a given hotspare disk is inuse or avail 1892eda14cbcSMatt Macy# 1893eda14cbcSMatt Macy# Return 0 is pool/disk matches expected state, 1 otherwise 1894eda14cbcSMatt Macy# 1895eda14cbcSMatt Macyfunction check_hotspare_state # pool disk state{inuse,avail} 1896eda14cbcSMatt Macy{ 1897eda14cbcSMatt Macy typeset pool=$1 1898eda14cbcSMatt Macy typeset disk=${2#$DEV_DSKDIR/} 1899eda14cbcSMatt Macy typeset state=$3 1900eda14cbcSMatt Macy 1901eda14cbcSMatt Macy cur_state=$(get_device_state $pool $disk "spares") 1902eda14cbcSMatt Macy 1903716fd348SMartin Matuska [ $state = $cur_state ] 1904eda14cbcSMatt Macy} 1905eda14cbcSMatt Macy 1906eda14cbcSMatt Macy# 1907eda14cbcSMatt Macy# Wait until a hotspare transitions to a given state or times out. 1908eda14cbcSMatt Macy# 1909eda14cbcSMatt Macy# Return 0 when pool/disk matches expected state, 1 on timeout. 1910eda14cbcSMatt Macy# 1911eda14cbcSMatt Macyfunction wait_hotspare_state # pool disk state timeout 1912eda14cbcSMatt Macy{ 1913eda14cbcSMatt Macy typeset pool=$1 1914eda14cbcSMatt Macy typeset disk=${2#*$DEV_DSKDIR/} 1915eda14cbcSMatt Macy typeset state=$3 1916eda14cbcSMatt Macy typeset timeout=${4:-60} 1917eda14cbcSMatt Macy typeset -i i=0 1918eda14cbcSMatt Macy 1919eda14cbcSMatt Macy while [[ $i -lt $timeout ]]; do 1920eda14cbcSMatt Macy if check_hotspare_state $pool $disk $state; then 1921eda14cbcSMatt Macy return 0 1922eda14cbcSMatt Macy fi 1923eda14cbcSMatt Macy 1924eda14cbcSMatt Macy i=$((i+1)) 1925eda14cbcSMatt Macy sleep 1 1926eda14cbcSMatt Macy done 1927eda14cbcSMatt Macy 1928eda14cbcSMatt Macy return 1 1929eda14cbcSMatt Macy} 1930eda14cbcSMatt Macy 1931eda14cbcSMatt Macy# 1932eda14cbcSMatt Macy# Verify a given vdev disk is inuse or avail 1933eda14cbcSMatt Macy# 1934eda14cbcSMatt Macy# Return 0 is pool/disk matches expected state, 1 otherwise 1935eda14cbcSMatt Macy# 1936be181ee2SMartin Matuskafunction check_vdev_state # pool disk state{online,offline,unavail,removed} 1937eda14cbcSMatt Macy{ 1938eda14cbcSMatt Macy typeset pool=$1 1939eda14cbcSMatt Macy typeset disk=${2#*$DEV_DSKDIR/} 1940eda14cbcSMatt Macy typeset state=$3 1941eda14cbcSMatt Macy 1942eda14cbcSMatt Macy cur_state=$(get_device_state $pool $disk) 1943eda14cbcSMatt Macy 1944716fd348SMartin Matuska [ $state = $cur_state ] 1945eda14cbcSMatt Macy} 1946eda14cbcSMatt Macy 1947eda14cbcSMatt Macy# 1948eda14cbcSMatt Macy# Wait until a vdev transitions to a given state or times out. 1949eda14cbcSMatt Macy# 1950eda14cbcSMatt Macy# Return 0 when pool/disk matches expected state, 1 on timeout. 1951eda14cbcSMatt Macy# 1952eda14cbcSMatt Macyfunction wait_vdev_state # pool disk state timeout 1953eda14cbcSMatt Macy{ 1954eda14cbcSMatt Macy typeset pool=$1 1955eda14cbcSMatt Macy typeset disk=${2#*$DEV_DSKDIR/} 1956eda14cbcSMatt Macy typeset state=$3 1957eda14cbcSMatt Macy typeset timeout=${4:-60} 1958eda14cbcSMatt Macy typeset -i i=0 1959eda14cbcSMatt Macy 1960eda14cbcSMatt Macy while [[ $i -lt $timeout ]]; do 1961eda14cbcSMatt Macy if check_vdev_state $pool $disk $state; then 1962eda14cbcSMatt Macy return 0 1963eda14cbcSMatt Macy fi 1964eda14cbcSMatt Macy 1965eda14cbcSMatt Macy i=$((i+1)) 1966eda14cbcSMatt Macy sleep 1 1967eda14cbcSMatt Macy done 1968eda14cbcSMatt Macy 1969eda14cbcSMatt Macy return 1 1970eda14cbcSMatt Macy} 1971eda14cbcSMatt Macy 1972eda14cbcSMatt Macy# 1973eda14cbcSMatt Macy# Check the output of 'zpool status -v <pool>', 1974eda14cbcSMatt Macy# and to see if the content of <token> contain the <keyword> specified. 1975eda14cbcSMatt Macy# 1976eda14cbcSMatt Macy# Return 0 is contain, 1 otherwise 1977eda14cbcSMatt Macy# 1978eda14cbcSMatt Macyfunction check_pool_status # pool token keyword <verbose> 1979eda14cbcSMatt Macy{ 1980eda14cbcSMatt Macy typeset pool=$1 1981eda14cbcSMatt Macy typeset token=$2 1982eda14cbcSMatt Macy typeset keyword=$3 1983eda14cbcSMatt Macy typeset verbose=${4:-false} 1984eda14cbcSMatt Macy 1985716fd348SMartin Matuska scan=$(zpool status -v "$pool" 2>/dev/null | awk -v token="$token:" '$1==token') 1986eda14cbcSMatt Macy if [[ $verbose == true ]]; then 1987eda14cbcSMatt Macy log_note $scan 1988eda14cbcSMatt Macy fi 1989716fd348SMartin Matuska echo $scan | grep -qi "$keyword" 1990eda14cbcSMatt Macy} 1991eda14cbcSMatt Macy 1992eda14cbcSMatt Macy# 1993eda14cbcSMatt Macy# The following functions are instance of check_pool_status() 1994eda14cbcSMatt Macy# is_pool_resilvering - to check if the pool resilver is in progress 1995eda14cbcSMatt Macy# is_pool_resilvered - to check if the pool resilver is completed 1996eda14cbcSMatt Macy# is_pool_scrubbing - to check if the pool scrub is in progress 1997eda14cbcSMatt Macy# is_pool_scrubbed - to check if the pool scrub is completed 1998eda14cbcSMatt Macy# is_pool_scrub_stopped - to check if the pool scrub is stopped 1999eda14cbcSMatt Macy# is_pool_scrub_paused - to check if the pool scrub has paused 2000eda14cbcSMatt Macy# is_pool_removing - to check if the pool removing is a vdev 2001eda14cbcSMatt Macy# is_pool_removed - to check if the pool remove is completed 2002eda14cbcSMatt Macy# is_pool_discarding - to check if the pool checkpoint is being discarded 2003e639e0d2SMartin Matuska# is_pool_replacing - to check if the pool is performing a replacement 2004eda14cbcSMatt Macy# 2005eda14cbcSMatt Macyfunction is_pool_resilvering #pool <verbose> 2006eda14cbcSMatt Macy{ 2007eda14cbcSMatt Macy check_pool_status "$1" "scan" \ 20087877fdebSMatt Macy "resilver[ ()0-9A-Za-z:_-]* in progress since" $2 2009eda14cbcSMatt Macy} 2010eda14cbcSMatt Macy 2011eda14cbcSMatt Macyfunction is_pool_resilvered #pool <verbose> 2012eda14cbcSMatt Macy{ 2013eda14cbcSMatt Macy check_pool_status "$1" "scan" "resilvered " $2 2014eda14cbcSMatt Macy} 2015eda14cbcSMatt Macy 2016eda14cbcSMatt Macyfunction is_pool_scrubbing #pool <verbose> 2017eda14cbcSMatt Macy{ 2018eda14cbcSMatt Macy check_pool_status "$1" "scan" "scrub in progress since " $2 2019eda14cbcSMatt Macy} 2020eda14cbcSMatt Macy 2021c0a83fe0SMartin Matuskafunction is_pool_error_scrubbing #pool <verbose> 2022c0a83fe0SMartin Matuska{ 2023c0a83fe0SMartin Matuska check_pool_status "$1" "scrub" "error scrub in progress since " $2 2024c0a83fe0SMartin Matuska return $? 2025c0a83fe0SMartin Matuska} 2026c0a83fe0SMartin Matuska 2027eda14cbcSMatt Macyfunction is_pool_scrubbed #pool <verbose> 2028eda14cbcSMatt Macy{ 2029eda14cbcSMatt Macy check_pool_status "$1" "scan" "scrub repaired" $2 2030eda14cbcSMatt Macy} 2031eda14cbcSMatt Macy 2032eda14cbcSMatt Macyfunction is_pool_scrub_stopped #pool <verbose> 2033eda14cbcSMatt Macy{ 2034eda14cbcSMatt Macy check_pool_status "$1" "scan" "scrub canceled" $2 2035eda14cbcSMatt Macy} 2036eda14cbcSMatt Macy 2037c0a83fe0SMartin Matuskafunction is_pool_error_scrub_stopped #pool <verbose> 2038c0a83fe0SMartin Matuska{ 2039c0a83fe0SMartin Matuska check_pool_status "$1" "scrub" "error scrub canceled on " $2 2040c0a83fe0SMartin Matuska return $? 2041c0a83fe0SMartin Matuska} 2042c0a83fe0SMartin Matuska 2043eda14cbcSMatt Macyfunction is_pool_scrub_paused #pool <verbose> 2044eda14cbcSMatt Macy{ 2045eda14cbcSMatt Macy check_pool_status "$1" "scan" "scrub paused since " $2 2046eda14cbcSMatt Macy} 2047eda14cbcSMatt Macy 2048c0a83fe0SMartin Matuskafunction is_pool_error_scrub_paused #pool <verbose> 2049c0a83fe0SMartin Matuska{ 2050c0a83fe0SMartin Matuska check_pool_status "$1" "scrub" "error scrub paused since " $2 2051c0a83fe0SMartin Matuska return $? 2052c0a83fe0SMartin Matuska} 2053c0a83fe0SMartin Matuska 2054eda14cbcSMatt Macyfunction is_pool_removing #pool 2055eda14cbcSMatt Macy{ 2056eda14cbcSMatt Macy check_pool_status "$1" "remove" "in progress since " 2057eda14cbcSMatt Macy} 2058eda14cbcSMatt Macy 2059eda14cbcSMatt Macyfunction is_pool_removed #pool 2060eda14cbcSMatt Macy{ 2061eda14cbcSMatt Macy check_pool_status "$1" "remove" "completed on" 2062eda14cbcSMatt Macy} 2063eda14cbcSMatt Macy 2064eda14cbcSMatt Macyfunction is_pool_discarding #pool 2065eda14cbcSMatt Macy{ 2066eda14cbcSMatt Macy check_pool_status "$1" "checkpoint" "discarding" 2067eda14cbcSMatt Macy} 2068e639e0d2SMartin Matuskafunction is_pool_replacing #pool 2069e639e0d2SMartin Matuska{ 2070e639e0d2SMartin Matuska zpool status "$1" | grep -qE 'replacing-[0-9]+' 2071e639e0d2SMartin Matuska} 2072eda14cbcSMatt Macy 2073eda14cbcSMatt Macyfunction wait_for_degraded 2074eda14cbcSMatt Macy{ 2075eda14cbcSMatt Macy typeset pool=$1 2076eda14cbcSMatt Macy typeset timeout=${2:-30} 2077eda14cbcSMatt Macy typeset t0=$SECONDS 2078eda14cbcSMatt Macy 2079eda14cbcSMatt Macy while :; do 2080eda14cbcSMatt Macy [[ $(get_pool_prop health $pool) == "DEGRADED" ]] && break 2081eda14cbcSMatt Macy log_note "$pool is not yet degraded." 2082eda14cbcSMatt Macy sleep 1 2083eda14cbcSMatt Macy if ((SECONDS - t0 > $timeout)); then 2084eda14cbcSMatt Macy log_note "$pool not degraded after $timeout seconds." 2085eda14cbcSMatt Macy return 1 2086eda14cbcSMatt Macy fi 2087eda14cbcSMatt Macy done 2088eda14cbcSMatt Macy 2089eda14cbcSMatt Macy return 0 2090eda14cbcSMatt Macy} 2091eda14cbcSMatt Macy 2092eda14cbcSMatt Macy# 2093eda14cbcSMatt Macy# Use create_pool()/destroy_pool() to clean up the information in 2094eda14cbcSMatt Macy# in the given disk to avoid slice overlapping. 2095eda14cbcSMatt Macy# 2096eda14cbcSMatt Macyfunction cleanup_devices #vdevs 2097eda14cbcSMatt Macy{ 2098eda14cbcSMatt Macy typeset pool="foopool$$" 2099eda14cbcSMatt Macy 2100eda14cbcSMatt Macy for vdev in $@; do 2101eda14cbcSMatt Macy zero_partitions $vdev 2102eda14cbcSMatt Macy done 2103eda14cbcSMatt Macy 2104eda14cbcSMatt Macy poolexists $pool && destroy_pool $pool 2105eda14cbcSMatt Macy create_pool $pool $@ 2106eda14cbcSMatt Macy destroy_pool $pool 2107eda14cbcSMatt Macy 2108eda14cbcSMatt Macy return 0 2109eda14cbcSMatt Macy} 2110eda14cbcSMatt Macy 2111eda14cbcSMatt Macy#/** 2112eda14cbcSMatt Macy# A function to find and locate free disks on a system or from given 2113eda14cbcSMatt Macy# disks as the parameter. It works by locating disks that are in use 2114eda14cbcSMatt Macy# as swap devices and dump devices, and also disks listed in /etc/vfstab 2115eda14cbcSMatt Macy# 2116eda14cbcSMatt Macy# $@ given disks to find which are free, default is all disks in 2117eda14cbcSMatt Macy# the test system 2118eda14cbcSMatt Macy# 2119eda14cbcSMatt Macy# @return a string containing the list of available disks 2120eda14cbcSMatt Macy#*/ 2121eda14cbcSMatt Macyfunction find_disks 2122eda14cbcSMatt Macy{ 2123eda14cbcSMatt Macy # Trust provided list, no attempt is made to locate unused devices. 2124eda14cbcSMatt Macy if is_linux || is_freebsd; then 2125eda14cbcSMatt Macy echo "$@" 2126eda14cbcSMatt Macy return 2127eda14cbcSMatt Macy fi 2128eda14cbcSMatt Macy 2129eda14cbcSMatt Macy 2130eda14cbcSMatt Macy sfi=/tmp/swaplist.$$ 2131eda14cbcSMatt Macy dmpi=/tmp/dumpdev.$$ 2132eda14cbcSMatt Macy max_finddisksnum=${MAX_FINDDISKSNUM:-6} 2133eda14cbcSMatt Macy 2134eda14cbcSMatt Macy swap -l > $sfi 2135eda14cbcSMatt Macy dumpadm > $dmpi 2>/dev/null 2136eda14cbcSMatt Macy 2137716fd348SMartin Matuska disks=${@:-$(echo "" | format -e 2>/dev/null | awk ' 2138eda14cbcSMatt MacyBEGIN { FS="."; } 2139eda14cbcSMatt Macy 2140eda14cbcSMatt Macy/^Specify disk/{ 2141eda14cbcSMatt Macy searchdisks=0; 2142eda14cbcSMatt Macy} 2143eda14cbcSMatt Macy 2144eda14cbcSMatt Macy{ 2145716fd348SMartin Matuska if (searchdisks && $2 !~ "^$"){ 2146716fd348SMartin Matuska split($2,arr," "); 2147eda14cbcSMatt Macy print arr[1]; 2148eda14cbcSMatt Macy } 2149eda14cbcSMatt Macy} 2150eda14cbcSMatt Macy 2151eda14cbcSMatt Macy/^AVAILABLE DISK SELECTIONS:/{ 2152eda14cbcSMatt Macy searchdisks=1; 2153eda14cbcSMatt Macy} 2154716fd348SMartin Matuska')} 2155eda14cbcSMatt Macy 2156eda14cbcSMatt Macy unused="" 2157eda14cbcSMatt Macy for disk in $disks; do 2158eda14cbcSMatt Macy # Check for mounted 2159716fd348SMartin Matuska grep -q "${disk}[sp]" /etc/mnttab && continue 2160eda14cbcSMatt Macy # Check for swap 2161716fd348SMartin Matuska grep -q "${disk}[sp]" $sfi && continue 2162eda14cbcSMatt Macy # check for dump device 2163716fd348SMartin Matuska grep -q "${disk}[sp]" $dmpi && continue 2164eda14cbcSMatt Macy # check to see if this disk hasn't been explicitly excluded 2165eda14cbcSMatt Macy # by a user-set environment variable 2166716fd348SMartin Matuska echo "${ZFS_HOST_DEVICES_IGNORE}" | grep -q "${disk}" && continue 2167eda14cbcSMatt Macy unused_candidates="$unused_candidates $disk" 2168eda14cbcSMatt Macy done 2169716fd348SMartin Matuska rm $sfi $dmpi 2170eda14cbcSMatt Macy 2171eda14cbcSMatt Macy# now just check to see if those disks do actually exist 2172eda14cbcSMatt Macy# by looking for a device pointing to the first slice in 2173eda14cbcSMatt Macy# each case. limit the number to max_finddisksnum 2174eda14cbcSMatt Macy count=0 2175eda14cbcSMatt Macy for disk in $unused_candidates; do 2176eda14cbcSMatt Macy if is_disk_device $DEV_DSKDIR/${disk}s0 && \ 2177eda14cbcSMatt Macy [ $count -lt $max_finddisksnum ]; then 2178eda14cbcSMatt Macy unused="$unused $disk" 2179eda14cbcSMatt Macy # do not impose limit if $@ is provided 2180eda14cbcSMatt Macy [[ -z $@ ]] && ((count = count + 1)) 2181eda14cbcSMatt Macy fi 2182eda14cbcSMatt Macy done 2183eda14cbcSMatt Macy 2184eda14cbcSMatt Macy# finally, return our disk list 2185eda14cbcSMatt Macy echo $unused 2186eda14cbcSMatt Macy} 2187eda14cbcSMatt Macy 2188eda14cbcSMatt Macyfunction add_user_freebsd #<group_name> <user_name> <basedir> 2189eda14cbcSMatt Macy{ 2190eda14cbcSMatt Macy typeset group=$1 2191eda14cbcSMatt Macy typeset user=$2 2192eda14cbcSMatt Macy typeset basedir=$3 2193eda14cbcSMatt Macy 2194eda14cbcSMatt Macy # Check to see if the user exists. 2195eda14cbcSMatt Macy if id $user > /dev/null 2>&1; then 2196eda14cbcSMatt Macy return 0 2197eda14cbcSMatt Macy fi 2198eda14cbcSMatt Macy 2199eda14cbcSMatt Macy # Assign 1000 as the base uid 2200eda14cbcSMatt Macy typeset -i uid=1000 2201eda14cbcSMatt Macy while true; do 2202eda14cbcSMatt Macy pw useradd -u $uid -g $group -d $basedir/$user -m -n $user 2203716fd348SMartin Matuska case $? in 2204eda14cbcSMatt Macy 0) break ;; 2205eda14cbcSMatt Macy # The uid is not unique 2206eda14cbcSMatt Macy 65) ((uid += 1)) ;; 2207eda14cbcSMatt Macy *) return 1 ;; 2208eda14cbcSMatt Macy esac 2209eda14cbcSMatt Macy if [[ $uid == 65000 ]]; then 2210eda14cbcSMatt Macy log_fail "No user id available under 65000 for $user" 2211eda14cbcSMatt Macy fi 2212eda14cbcSMatt Macy done 2213eda14cbcSMatt Macy 2214eda14cbcSMatt Macy # Silence MOTD 2215eda14cbcSMatt Macy touch $basedir/$user/.hushlogin 2216eda14cbcSMatt Macy 2217eda14cbcSMatt Macy return 0 2218eda14cbcSMatt Macy} 2219eda14cbcSMatt Macy 2220eda14cbcSMatt Macy# 2221eda14cbcSMatt Macy# Delete the specified user. 2222eda14cbcSMatt Macy# 2223eda14cbcSMatt Macy# $1 login name 2224eda14cbcSMatt Macy# 2225eda14cbcSMatt Macyfunction del_user_freebsd #<logname> 2226eda14cbcSMatt Macy{ 2227eda14cbcSMatt Macy typeset user=$1 2228eda14cbcSMatt Macy 2229eda14cbcSMatt Macy if id $user > /dev/null 2>&1; then 2230eda14cbcSMatt Macy log_must pw userdel $user 2231eda14cbcSMatt Macy fi 2232eda14cbcSMatt Macy 2233eda14cbcSMatt Macy return 0 2234eda14cbcSMatt Macy} 2235eda14cbcSMatt Macy 2236eda14cbcSMatt Macy# 2237eda14cbcSMatt Macy# Select valid gid and create specified group. 2238eda14cbcSMatt Macy# 2239eda14cbcSMatt Macy# $1 group name 2240eda14cbcSMatt Macy# 2241eda14cbcSMatt Macyfunction add_group_freebsd #<group_name> 2242eda14cbcSMatt Macy{ 2243eda14cbcSMatt Macy typeset group=$1 2244eda14cbcSMatt Macy 2245eda14cbcSMatt Macy # See if the group already exists. 2246eda14cbcSMatt Macy if pw groupshow $group >/dev/null 2>&1; then 2247eda14cbcSMatt Macy return 0 2248eda14cbcSMatt Macy fi 2249eda14cbcSMatt Macy 2250eda14cbcSMatt Macy # Assign 1000 as the base gid 2251eda14cbcSMatt Macy typeset -i gid=1000 2252eda14cbcSMatt Macy while true; do 2253eda14cbcSMatt Macy pw groupadd -g $gid -n $group > /dev/null 2>&1 2254716fd348SMartin Matuska case $? in 2255eda14cbcSMatt Macy 0) return 0 ;; 2256eda14cbcSMatt Macy # The gid is not unique 2257eda14cbcSMatt Macy 65) ((gid += 1)) ;; 2258eda14cbcSMatt Macy *) return 1 ;; 2259eda14cbcSMatt Macy esac 2260eda14cbcSMatt Macy if [[ $gid == 65000 ]]; then 2261eda14cbcSMatt Macy log_fail "No user id available under 65000 for $group" 2262eda14cbcSMatt Macy fi 2263eda14cbcSMatt Macy done 2264eda14cbcSMatt Macy} 2265eda14cbcSMatt Macy 2266eda14cbcSMatt Macy# 2267eda14cbcSMatt Macy# Delete the specified group. 2268eda14cbcSMatt Macy# 2269eda14cbcSMatt Macy# $1 group name 2270eda14cbcSMatt Macy# 2271eda14cbcSMatt Macyfunction del_group_freebsd #<group_name> 2272eda14cbcSMatt Macy{ 2273eda14cbcSMatt Macy typeset group=$1 2274eda14cbcSMatt Macy 2275eda14cbcSMatt Macy pw groupdel -n $group > /dev/null 2>&1 2276716fd348SMartin Matuska case $? in 2277eda14cbcSMatt Macy # Group does not exist, or was deleted successfully. 2278eda14cbcSMatt Macy 0|6|65) return 0 ;; 2279eda14cbcSMatt Macy # Name already exists as a group name 2280eda14cbcSMatt Macy 9) log_must pw groupdel $group ;; 2281eda14cbcSMatt Macy *) return 1 ;; 2282eda14cbcSMatt Macy esac 2283eda14cbcSMatt Macy 2284eda14cbcSMatt Macy return 0 2285eda14cbcSMatt Macy} 2286eda14cbcSMatt Macy 2287eda14cbcSMatt Macyfunction add_user_illumos #<group_name> <user_name> <basedir> 2288eda14cbcSMatt Macy{ 2289eda14cbcSMatt Macy typeset group=$1 2290eda14cbcSMatt Macy typeset user=$2 2291eda14cbcSMatt Macy typeset basedir=$3 2292eda14cbcSMatt Macy 2293eda14cbcSMatt Macy log_must useradd -g $group -d $basedir/$user -m $user 2294eda14cbcSMatt Macy 2295eda14cbcSMatt Macy return 0 2296eda14cbcSMatt Macy} 2297eda14cbcSMatt Macy 2298eda14cbcSMatt Macyfunction del_user_illumos #<user_name> 2299eda14cbcSMatt Macy{ 2300eda14cbcSMatt Macy typeset user=$1 2301eda14cbcSMatt Macy 2302eda14cbcSMatt Macy if id $user > /dev/null 2>&1; then 2303eda14cbcSMatt Macy log_must_retry "currently used" 6 userdel $user 2304eda14cbcSMatt Macy fi 2305eda14cbcSMatt Macy 2306eda14cbcSMatt Macy return 0 2307eda14cbcSMatt Macy} 2308eda14cbcSMatt Macy 2309eda14cbcSMatt Macyfunction add_group_illumos #<group_name> 2310eda14cbcSMatt Macy{ 2311eda14cbcSMatt Macy typeset group=$1 2312eda14cbcSMatt Macy 2313eda14cbcSMatt Macy typeset -i gid=100 2314eda14cbcSMatt Macy while true; do 2315eda14cbcSMatt Macy groupadd -g $gid $group > /dev/null 2>&1 2316716fd348SMartin Matuska case $? in 2317eda14cbcSMatt Macy 0) return 0 ;; 2318eda14cbcSMatt Macy # The gid is not unique 2319eda14cbcSMatt Macy 4) ((gid += 1)) ;; 2320eda14cbcSMatt Macy *) return 1 ;; 2321eda14cbcSMatt Macy esac 2322eda14cbcSMatt Macy done 2323eda14cbcSMatt Macy} 2324eda14cbcSMatt Macy 2325eda14cbcSMatt Macyfunction del_group_illumos #<group_name> 2326eda14cbcSMatt Macy{ 2327eda14cbcSMatt Macy typeset group=$1 2328eda14cbcSMatt Macy 2329eda14cbcSMatt Macy groupmod -n $grp $grp > /dev/null 2>&1 2330716fd348SMartin Matuska case $? in 2331eda14cbcSMatt Macy # Group does not exist. 2332eda14cbcSMatt Macy 6) return 0 ;; 2333eda14cbcSMatt Macy # Name already exists as a group name 2334eda14cbcSMatt Macy 9) log_must groupdel $grp ;; 2335eda14cbcSMatt Macy *) return 1 ;; 2336eda14cbcSMatt Macy esac 2337eda14cbcSMatt Macy} 2338eda14cbcSMatt Macy 2339eda14cbcSMatt Macyfunction add_user_linux #<group_name> <user_name> <basedir> 2340eda14cbcSMatt Macy{ 2341eda14cbcSMatt Macy typeset group=$1 2342eda14cbcSMatt Macy typeset user=$2 2343eda14cbcSMatt Macy typeset basedir=$3 2344eda14cbcSMatt Macy 2345eda14cbcSMatt Macy log_must useradd -g $group -d $basedir/$user -m $user 2346eda14cbcSMatt Macy 2347eda14cbcSMatt Macy # Add new users to the same group and the command line utils. 2348eda14cbcSMatt Macy # This allows them to be run out of the original users home 2349eda14cbcSMatt Macy # directory as long as it permissioned to be group readable. 2350716fd348SMartin Matuska cmd_group=$(stat --format="%G" $(command -v zfs)) 2351eda14cbcSMatt Macy log_must usermod -a -G $cmd_group $user 2352eda14cbcSMatt Macy 2353eda14cbcSMatt Macy return 0 2354eda14cbcSMatt Macy} 2355eda14cbcSMatt Macy 2356eda14cbcSMatt Macyfunction del_user_linux #<user_name> 2357eda14cbcSMatt Macy{ 2358eda14cbcSMatt Macy typeset user=$1 2359eda14cbcSMatt Macy 2360eda14cbcSMatt Macy if id $user > /dev/null 2>&1; then 2361eda14cbcSMatt Macy log_must_retry "currently used" 6 userdel $user 2362eda14cbcSMatt Macy fi 2363eda14cbcSMatt Macy} 2364eda14cbcSMatt Macy 2365eda14cbcSMatt Macyfunction add_group_linux #<group_name> 2366eda14cbcSMatt Macy{ 2367eda14cbcSMatt Macy typeset group=$1 2368eda14cbcSMatt Macy 2369eda14cbcSMatt Macy # Assign 100 as the base gid, a larger value is selected for 2370eda14cbcSMatt Macy # Linux because for many distributions 1000 and under are reserved. 2371eda14cbcSMatt Macy while true; do 2372eda14cbcSMatt Macy groupadd $group > /dev/null 2>&1 2373716fd348SMartin Matuska case $? in 2374eda14cbcSMatt Macy 0) return 0 ;; 2375eda14cbcSMatt Macy *) return 1 ;; 2376eda14cbcSMatt Macy esac 2377eda14cbcSMatt Macy done 2378eda14cbcSMatt Macy} 2379eda14cbcSMatt Macy 2380eda14cbcSMatt Macyfunction del_group_linux #<group_name> 2381eda14cbcSMatt Macy{ 2382eda14cbcSMatt Macy typeset group=$1 2383eda14cbcSMatt Macy 2384eda14cbcSMatt Macy getent group $group > /dev/null 2>&1 2385716fd348SMartin Matuska case $? in 2386eda14cbcSMatt Macy # Group does not exist. 2387eda14cbcSMatt Macy 2) return 0 ;; 2388eda14cbcSMatt Macy # Name already exists as a group name 2389eda14cbcSMatt Macy 0) log_must groupdel $group ;; 2390eda14cbcSMatt Macy *) return 1 ;; 2391eda14cbcSMatt Macy esac 2392eda14cbcSMatt Macy 2393eda14cbcSMatt Macy return 0 2394eda14cbcSMatt Macy} 2395eda14cbcSMatt Macy 2396eda14cbcSMatt Macy# 2397eda14cbcSMatt Macy# Add specified user to specified group 2398eda14cbcSMatt Macy# 2399eda14cbcSMatt Macy# $1 group name 2400eda14cbcSMatt Macy# $2 user name 2401eda14cbcSMatt Macy# $3 base of the homedir (optional) 2402eda14cbcSMatt Macy# 2403eda14cbcSMatt Macyfunction add_user #<group_name> <user_name> <basedir> 2404eda14cbcSMatt Macy{ 2405eda14cbcSMatt Macy typeset group=$1 2406eda14cbcSMatt Macy typeset user=$2 2407eda14cbcSMatt Macy typeset basedir=${3:-"/var/tmp"} 2408eda14cbcSMatt Macy 2409eda14cbcSMatt Macy if ((${#group} == 0 || ${#user} == 0)); then 2410eda14cbcSMatt Macy log_fail "group name or user name are not defined." 2411eda14cbcSMatt Macy fi 2412eda14cbcSMatt Macy 2413716fd348SMartin Matuska case "$UNAME" in 2414eda14cbcSMatt Macy FreeBSD) 2415eda14cbcSMatt Macy add_user_freebsd "$group" "$user" "$basedir" 2416eda14cbcSMatt Macy ;; 2417eda14cbcSMatt Macy Linux) 2418eda14cbcSMatt Macy add_user_linux "$group" "$user" "$basedir" 2419eda14cbcSMatt Macy ;; 2420eda14cbcSMatt Macy *) 2421eda14cbcSMatt Macy add_user_illumos "$group" "$user" "$basedir" 2422eda14cbcSMatt Macy ;; 2423eda14cbcSMatt Macy esac 2424eda14cbcSMatt Macy 2425eda14cbcSMatt Macy return 0 2426eda14cbcSMatt Macy} 2427eda14cbcSMatt Macy 2428eda14cbcSMatt Macy# 2429eda14cbcSMatt Macy# Delete the specified user. 2430eda14cbcSMatt Macy# 2431eda14cbcSMatt Macy# $1 login name 2432eda14cbcSMatt Macy# $2 base of the homedir (optional) 2433eda14cbcSMatt Macy# 2434eda14cbcSMatt Macyfunction del_user #<logname> <basedir> 2435eda14cbcSMatt Macy{ 2436eda14cbcSMatt Macy typeset user=$1 2437eda14cbcSMatt Macy typeset basedir=${2:-"/var/tmp"} 2438eda14cbcSMatt Macy 2439eda14cbcSMatt Macy if ((${#user} == 0)); then 2440eda14cbcSMatt Macy log_fail "login name is necessary." 2441eda14cbcSMatt Macy fi 2442eda14cbcSMatt Macy 2443716fd348SMartin Matuska case "$UNAME" in 2444eda14cbcSMatt Macy FreeBSD) 2445eda14cbcSMatt Macy del_user_freebsd "$user" 2446eda14cbcSMatt Macy ;; 2447eda14cbcSMatt Macy Linux) 2448eda14cbcSMatt Macy del_user_linux "$user" 2449eda14cbcSMatt Macy ;; 2450eda14cbcSMatt Macy *) 2451eda14cbcSMatt Macy del_user_illumos "$user" 2452eda14cbcSMatt Macy ;; 2453eda14cbcSMatt Macy esac 2454eda14cbcSMatt Macy 2455eda14cbcSMatt Macy [[ -d $basedir/$user ]] && rm -fr $basedir/$user 2456eda14cbcSMatt Macy 2457eda14cbcSMatt Macy return 0 2458eda14cbcSMatt Macy} 2459eda14cbcSMatt Macy 2460eda14cbcSMatt Macy# 2461eda14cbcSMatt Macy# Select valid gid and create specified group. 2462eda14cbcSMatt Macy# 2463eda14cbcSMatt Macy# $1 group name 2464eda14cbcSMatt Macy# 2465eda14cbcSMatt Macyfunction add_group #<group_name> 2466eda14cbcSMatt Macy{ 2467eda14cbcSMatt Macy typeset group=$1 2468eda14cbcSMatt Macy 2469eda14cbcSMatt Macy if ((${#group} == 0)); then 2470eda14cbcSMatt Macy log_fail "group name is necessary." 2471eda14cbcSMatt Macy fi 2472eda14cbcSMatt Macy 2473716fd348SMartin Matuska case "$UNAME" in 2474eda14cbcSMatt Macy FreeBSD) 2475eda14cbcSMatt Macy add_group_freebsd "$group" 2476eda14cbcSMatt Macy ;; 2477eda14cbcSMatt Macy Linux) 2478eda14cbcSMatt Macy add_group_linux "$group" 2479eda14cbcSMatt Macy ;; 2480eda14cbcSMatt Macy *) 2481eda14cbcSMatt Macy add_group_illumos "$group" 2482eda14cbcSMatt Macy ;; 2483eda14cbcSMatt Macy esac 2484eda14cbcSMatt Macy 2485eda14cbcSMatt Macy return 0 2486eda14cbcSMatt Macy} 2487eda14cbcSMatt Macy 2488eda14cbcSMatt Macy# 2489eda14cbcSMatt Macy# Delete the specified group. 2490eda14cbcSMatt Macy# 2491eda14cbcSMatt Macy# $1 group name 2492eda14cbcSMatt Macy# 2493eda14cbcSMatt Macyfunction del_group #<group_name> 2494eda14cbcSMatt Macy{ 2495eda14cbcSMatt Macy typeset group=$1 2496eda14cbcSMatt Macy 2497eda14cbcSMatt Macy if ((${#group} == 0)); then 2498eda14cbcSMatt Macy log_fail "group name is necessary." 2499eda14cbcSMatt Macy fi 2500eda14cbcSMatt Macy 2501716fd348SMartin Matuska case "$UNAME" in 2502eda14cbcSMatt Macy FreeBSD) 2503eda14cbcSMatt Macy del_group_freebsd "$group" 2504eda14cbcSMatt Macy ;; 2505eda14cbcSMatt Macy Linux) 2506eda14cbcSMatt Macy del_group_linux "$group" 2507eda14cbcSMatt Macy ;; 2508eda14cbcSMatt Macy *) 2509eda14cbcSMatt Macy del_group_illumos "$group" 2510eda14cbcSMatt Macy ;; 2511eda14cbcSMatt Macy esac 2512eda14cbcSMatt Macy 2513eda14cbcSMatt Macy return 0 2514eda14cbcSMatt Macy} 2515eda14cbcSMatt Macy 2516eda14cbcSMatt Macy# 2517eda14cbcSMatt Macy# This function will return true if it's safe to destroy the pool passed 2518eda14cbcSMatt Macy# as argument 1. It checks for pools based on zvols and files, and also 2519eda14cbcSMatt Macy# files contained in a pool that may have a different mountpoint. 2520eda14cbcSMatt Macy# 2521eda14cbcSMatt Macyfunction safe_to_destroy_pool { # $1 the pool name 2522eda14cbcSMatt Macy 2523eda14cbcSMatt Macy typeset pool="" 2524eda14cbcSMatt Macy typeset DONT_DESTROY="" 2525eda14cbcSMatt Macy 2526eda14cbcSMatt Macy # We check that by deleting the $1 pool, we're not 2527eda14cbcSMatt Macy # going to pull the rug out from other pools. Do this 2528eda14cbcSMatt Macy # by looking at all other pools, ensuring that they 2529eda14cbcSMatt Macy # aren't built from files or zvols contained in this pool. 2530eda14cbcSMatt Macy 2531eda14cbcSMatt Macy for pool in $(zpool list -H -o name) 2532eda14cbcSMatt Macy do 2533eda14cbcSMatt Macy ALTMOUNTPOOL="" 2534eda14cbcSMatt Macy 2535eda14cbcSMatt Macy # this is a list of the top-level directories in each of the 2536eda14cbcSMatt Macy # files that make up the path to the files the pool is based on 2537716fd348SMartin Matuska FILEPOOL=$(zpool status -v $pool | awk -v pool="/$1/" '$0 ~ pool {print $1}') 2538eda14cbcSMatt Macy 2539eda14cbcSMatt Macy # this is a list of the zvols that make up the pool 2540716fd348SMartin Matuska ZVOLPOOL=$(zpool status -v $pool | awk -v zvols="$ZVOL_DEVDIR/$1$" '$0 ~ zvols {print $1}') 2541eda14cbcSMatt Macy 2542eda14cbcSMatt Macy # also want to determine if it's a file-based pool using an 2543eda14cbcSMatt Macy # alternate mountpoint... 2544eda14cbcSMatt Macy POOL_FILE_DIRS=$(zpool status -v $pool | \ 2545716fd348SMartin Matuska awk '/\// {print $1}' | \ 2546716fd348SMartin Matuska awk -F/ '!/dev/ {print $2}') 2547eda14cbcSMatt Macy 2548eda14cbcSMatt Macy for pooldir in $POOL_FILE_DIRS 2549eda14cbcSMatt Macy do 2550eda14cbcSMatt Macy OUTPUT=$(zfs list -H -r -o mountpoint $1 | \ 2551716fd348SMartin Matuska awk -v pd="${pooldir}$" '$0 ~ pd {print $1}') 2552eda14cbcSMatt Macy 2553eda14cbcSMatt Macy ALTMOUNTPOOL="${ALTMOUNTPOOL}${OUTPUT}" 2554eda14cbcSMatt Macy done 2555eda14cbcSMatt Macy 2556eda14cbcSMatt Macy 2557eda14cbcSMatt Macy if [ ! -z "$ZVOLPOOL" ] 2558eda14cbcSMatt Macy then 2559eda14cbcSMatt Macy DONT_DESTROY="true" 2560eda14cbcSMatt Macy log_note "Pool $pool is built from $ZVOLPOOL on $1" 2561eda14cbcSMatt Macy fi 2562eda14cbcSMatt Macy 2563eda14cbcSMatt Macy if [ ! -z "$FILEPOOL" ] 2564eda14cbcSMatt Macy then 2565eda14cbcSMatt Macy DONT_DESTROY="true" 2566eda14cbcSMatt Macy log_note "Pool $pool is built from $FILEPOOL on $1" 2567eda14cbcSMatt Macy fi 2568eda14cbcSMatt Macy 2569eda14cbcSMatt Macy if [ ! -z "$ALTMOUNTPOOL" ] 2570eda14cbcSMatt Macy then 2571eda14cbcSMatt Macy DONT_DESTROY="true" 2572eda14cbcSMatt Macy log_note "Pool $pool is built from $ALTMOUNTPOOL on $1" 2573eda14cbcSMatt Macy fi 2574eda14cbcSMatt Macy done 2575eda14cbcSMatt Macy 2576eda14cbcSMatt Macy if [ -z "${DONT_DESTROY}" ] 2577eda14cbcSMatt Macy then 2578eda14cbcSMatt Macy return 0 2579eda14cbcSMatt Macy else 2580eda14cbcSMatt Macy log_note "Warning: it is not safe to destroy $1!" 2581eda14cbcSMatt Macy return 1 2582eda14cbcSMatt Macy fi 2583eda14cbcSMatt Macy} 2584eda14cbcSMatt Macy 2585eda14cbcSMatt Macy# 2586eda14cbcSMatt Macy# Verify zfs operation with -p option work as expected 2587eda14cbcSMatt Macy# $1 operation, value could be create, clone or rename 2588eda14cbcSMatt Macy# $2 dataset type, value could be fs or vol 2589eda14cbcSMatt Macy# $3 dataset name 2590eda14cbcSMatt Macy# $4 new dataset name 2591eda14cbcSMatt Macy# 2592eda14cbcSMatt Macyfunction verify_opt_p_ops 2593eda14cbcSMatt Macy{ 2594eda14cbcSMatt Macy typeset ops=$1 2595eda14cbcSMatt Macy typeset datatype=$2 2596eda14cbcSMatt Macy typeset dataset=$3 2597eda14cbcSMatt Macy typeset newdataset=$4 2598eda14cbcSMatt Macy 2599eda14cbcSMatt Macy if [[ $datatype != "fs" && $datatype != "vol" ]]; then 2600eda14cbcSMatt Macy log_fail "$datatype is not supported." 2601eda14cbcSMatt Macy fi 2602eda14cbcSMatt Macy 2603eda14cbcSMatt Macy # check parameters accordingly 2604eda14cbcSMatt Macy case $ops in 2605eda14cbcSMatt Macy create) 2606eda14cbcSMatt Macy newdataset=$dataset 2607eda14cbcSMatt Macy dataset="" 2608eda14cbcSMatt Macy if [[ $datatype == "vol" ]]; then 2609eda14cbcSMatt Macy ops="create -V $VOLSIZE" 2610eda14cbcSMatt Macy fi 2611eda14cbcSMatt Macy ;; 2612eda14cbcSMatt Macy clone) 2613eda14cbcSMatt Macy if [[ -z $newdataset ]]; then 2614eda14cbcSMatt Macy log_fail "newdataset should not be empty" \ 2615eda14cbcSMatt Macy "when ops is $ops." 2616eda14cbcSMatt Macy fi 2617eda14cbcSMatt Macy log_must datasetexists $dataset 2618eda14cbcSMatt Macy log_must snapexists $dataset 2619eda14cbcSMatt Macy ;; 2620eda14cbcSMatt Macy rename) 2621eda14cbcSMatt Macy if [[ -z $newdataset ]]; then 2622eda14cbcSMatt Macy log_fail "newdataset should not be empty" \ 2623eda14cbcSMatt Macy "when ops is $ops." 2624eda14cbcSMatt Macy fi 2625eda14cbcSMatt Macy log_must datasetexists $dataset 2626eda14cbcSMatt Macy ;; 2627eda14cbcSMatt Macy *) 2628eda14cbcSMatt Macy log_fail "$ops is not supported." 2629eda14cbcSMatt Macy ;; 2630eda14cbcSMatt Macy esac 2631eda14cbcSMatt Macy 2632eda14cbcSMatt Macy # make sure the upper level filesystem does not exist 2633eda14cbcSMatt Macy destroy_dataset "${newdataset%/*}" "-rRf" 2634eda14cbcSMatt Macy 2635eda14cbcSMatt Macy # without -p option, operation will fail 2636eda14cbcSMatt Macy log_mustnot zfs $ops $dataset $newdataset 2637eda14cbcSMatt Macy log_mustnot datasetexists $newdataset ${newdataset%/*} 2638eda14cbcSMatt Macy 2639eda14cbcSMatt Macy # with -p option, operation should succeed 2640eda14cbcSMatt Macy log_must zfs $ops -p $dataset $newdataset 2641eda14cbcSMatt Macy block_device_wait 2642eda14cbcSMatt Macy 2643eda14cbcSMatt Macy if ! datasetexists $newdataset ; then 2644eda14cbcSMatt Macy log_fail "-p option does not work for $ops" 2645eda14cbcSMatt Macy fi 2646eda14cbcSMatt Macy 2647eda14cbcSMatt Macy # when $ops is create or clone, redo the operation still return zero 2648eda14cbcSMatt Macy if [[ $ops != "rename" ]]; then 2649eda14cbcSMatt Macy log_must zfs $ops -p $dataset $newdataset 2650eda14cbcSMatt Macy fi 2651eda14cbcSMatt Macy 2652eda14cbcSMatt Macy return 0 2653eda14cbcSMatt Macy} 2654eda14cbcSMatt Macy 2655eda14cbcSMatt Macy# 2656eda14cbcSMatt Macy# Get configuration of pool 2657eda14cbcSMatt Macy# $1 pool name 2658eda14cbcSMatt Macy# $2 config name 2659eda14cbcSMatt Macy# 2660eda14cbcSMatt Macyfunction get_config 2661eda14cbcSMatt Macy{ 2662eda14cbcSMatt Macy typeset pool=$1 2663eda14cbcSMatt Macy typeset config=$2 2664eda14cbcSMatt Macy 2665eda14cbcSMatt Macy if ! poolexists "$pool" ; then 2666eda14cbcSMatt Macy return 1 2667eda14cbcSMatt Macy fi 2668716fd348SMartin Matuska if [ "$(get_pool_prop cachefile "$pool")" = "none" ]; then 2669716fd348SMartin Matuska zdb -e $pool 2670eda14cbcSMatt Macy else 2671716fd348SMartin Matuska zdb -C $pool 2672716fd348SMartin Matuska fi | awk -F: -v cfg="$config:" '$0 ~ cfg {sub(/^'\''/, $2); sub(/'\''$/, $2); print $2}' 2673eda14cbcSMatt Macy} 2674eda14cbcSMatt Macy 2675eda14cbcSMatt Macy# 2676eda14cbcSMatt Macy# Privated function. Random select one of items from arguments. 2677eda14cbcSMatt Macy# 2678eda14cbcSMatt Macy# $1 count 2679eda14cbcSMatt Macy# $2-n string 2680eda14cbcSMatt Macy# 2681eda14cbcSMatt Macyfunction _random_get 2682eda14cbcSMatt Macy{ 2683eda14cbcSMatt Macy typeset cnt=$1 2684eda14cbcSMatt Macy shift 2685eda14cbcSMatt Macy 2686eda14cbcSMatt Macy typeset str="$@" 2687eda14cbcSMatt Macy typeset -i ind 2688eda14cbcSMatt Macy ((ind = RANDOM % cnt + 1)) 2689eda14cbcSMatt Macy 2690716fd348SMartin Matuska echo "$str" | cut -f $ind -d ' ' 2691eda14cbcSMatt Macy} 2692eda14cbcSMatt Macy 2693eda14cbcSMatt Macy# 2694eda14cbcSMatt Macy# Random select one of item from arguments which include NONE string 2695eda14cbcSMatt Macy# 2696eda14cbcSMatt Macyfunction random_get_with_non 2697eda14cbcSMatt Macy{ 2698eda14cbcSMatt Macy typeset -i cnt=$# 2699eda14cbcSMatt Macy ((cnt =+ 1)) 2700eda14cbcSMatt Macy 2701eda14cbcSMatt Macy _random_get "$cnt" "$@" 2702eda14cbcSMatt Macy} 2703eda14cbcSMatt Macy 2704eda14cbcSMatt Macy# 2705eda14cbcSMatt Macy# Random select one of item from arguments which doesn't include NONE string 2706eda14cbcSMatt Macy# 2707eda14cbcSMatt Macyfunction random_get 2708eda14cbcSMatt Macy{ 2709eda14cbcSMatt Macy _random_get "$#" "$@" 2710eda14cbcSMatt Macy} 2711eda14cbcSMatt Macy 2712eda14cbcSMatt Macy# 2713eda14cbcSMatt Macy# The function will generate a dataset name with specific length 2714eda14cbcSMatt Macy# $1, the length of the name 2715eda14cbcSMatt Macy# $2, the base string to construct the name 2716eda14cbcSMatt Macy# 2717eda14cbcSMatt Macyfunction gen_dataset_name 2718eda14cbcSMatt Macy{ 2719eda14cbcSMatt Macy typeset -i len=$1 2720eda14cbcSMatt Macy typeset basestr="$2" 2721eda14cbcSMatt Macy typeset -i baselen=${#basestr} 2722eda14cbcSMatt Macy typeset -i iter=0 2723eda14cbcSMatt Macy typeset l_name="" 2724eda14cbcSMatt Macy 2725eda14cbcSMatt Macy if ((len % baselen == 0)); then 2726eda14cbcSMatt Macy ((iter = len / baselen)) 2727eda14cbcSMatt Macy else 2728eda14cbcSMatt Macy ((iter = len / baselen + 1)) 2729eda14cbcSMatt Macy fi 2730eda14cbcSMatt Macy while ((iter > 0)); do 2731eda14cbcSMatt Macy l_name="${l_name}$basestr" 2732eda14cbcSMatt Macy 2733eda14cbcSMatt Macy ((iter -= 1)) 2734eda14cbcSMatt Macy done 2735eda14cbcSMatt Macy 2736eda14cbcSMatt Macy echo $l_name 2737eda14cbcSMatt Macy} 2738eda14cbcSMatt Macy 2739eda14cbcSMatt Macy# 2740eda14cbcSMatt Macy# Get cksum tuple of dataset 2741eda14cbcSMatt Macy# $1 dataset name 2742eda14cbcSMatt Macy# 2743eda14cbcSMatt Macy# sample zdb output: 2744eda14cbcSMatt Macy# Dataset data/test [ZPL], ID 355, cr_txg 2413856, 31.0K, 7 objects, rootbp 2745eda14cbcSMatt Macy# DVA[0]=<0:803046400:200> DVA[1]=<0:81199000:200> [L0 DMU objset] fletcher4 2746eda14cbcSMatt Macy# lzjb LE contiguous unique double size=800L/200P birth=2413856L/2413856P 2747eda14cbcSMatt Macy# fill=7 cksum=11ce125712:643a9c18ee2:125e25238fca0:254a3f74b59744 2748eda14cbcSMatt Macyfunction datasetcksum 2749eda14cbcSMatt Macy{ 2750eda14cbcSMatt Macy typeset cksum 2751eda14cbcSMatt Macy sync 2752e92ffd9bSMartin Matuska sync_all_pools 2753716fd348SMartin Matuska zdb -vvv $1 | awk -F= -v ds="^Dataset $1 "'\\[' '$0 ~ ds && /cksum/ {print $7}' 2754eda14cbcSMatt Macy} 2755eda14cbcSMatt Macy 2756eda14cbcSMatt Macy# 2757eda14cbcSMatt Macy# Get the given disk/slice state from the specific field of the pool 2758eda14cbcSMatt Macy# 2759eda14cbcSMatt Macyfunction get_device_state #pool disk field("", "spares","logs") 2760eda14cbcSMatt Macy{ 2761eda14cbcSMatt Macy typeset pool=$1 2762eda14cbcSMatt Macy typeset disk=${2#$DEV_DSKDIR/} 2763eda14cbcSMatt Macy typeset field=${3:-$pool} 2764eda14cbcSMatt Macy 2765716fd348SMartin Matuska zpool status -v "$pool" 2>/dev/null | \ 2766716fd348SMartin Matuska awk -v device=$disk -v pool=$pool -v field=$field \ 2767eda14cbcSMatt Macy 'BEGIN {startconfig=0; startfield=0; } 2768eda14cbcSMatt Macy /config:/ {startconfig=1} 2769eda14cbcSMatt Macy (startconfig==1) && ($1==field) {startfield=1; next;} 2770eda14cbcSMatt Macy (startfield==1) && ($1==device) {print $2; exit;} 2771eda14cbcSMatt Macy (startfield==1) && 2772716fd348SMartin Matuska ($1==field || $1 ~ "^spares$" || $1 ~ "^logs$") {startfield=0}' 2773eda14cbcSMatt Macy} 2774eda14cbcSMatt Macy 2775eda14cbcSMatt Macy# 2776eda14cbcSMatt Macy# get the root filesystem name if it's zfsroot system. 2777eda14cbcSMatt Macy# 2778eda14cbcSMatt Macy# return: root filesystem name 2779eda14cbcSMatt Macyfunction get_rootfs 2780eda14cbcSMatt Macy{ 2781eda14cbcSMatt Macy typeset rootfs="" 2782eda14cbcSMatt Macy 2783eda14cbcSMatt Macy if is_freebsd; then 2784eda14cbcSMatt Macy rootfs=$(mount -p | awk '$2 == "/" && $3 == "zfs" {print $1}') 2785eda14cbcSMatt Macy elif ! is_linux; then 2786716fd348SMartin Matuska rootfs=$(awk '$2 == "/" && $3 == "zfs" {print $1}' \ 2787eda14cbcSMatt Macy /etc/mnttab) 2788eda14cbcSMatt Macy fi 2789eda14cbcSMatt Macy if [[ -z "$rootfs" ]]; then 2790eda14cbcSMatt Macy log_fail "Can not get rootfs" 2791eda14cbcSMatt Macy fi 2792716fd348SMartin Matuska if datasetexists $rootfs; then 2793eda14cbcSMatt Macy echo $rootfs 2794eda14cbcSMatt Macy else 2795eda14cbcSMatt Macy log_fail "This is not a zfsroot system." 2796eda14cbcSMatt Macy fi 2797eda14cbcSMatt Macy} 2798eda14cbcSMatt Macy 2799eda14cbcSMatt Macy# 2800eda14cbcSMatt Macy# get the rootfs's pool name 2801eda14cbcSMatt Macy# return: 2802eda14cbcSMatt Macy# rootpool name 2803eda14cbcSMatt Macy# 2804eda14cbcSMatt Macyfunction get_rootpool 2805eda14cbcSMatt Macy{ 2806716fd348SMartin Matuska typeset rootfs=$(get_rootfs) 2807eda14cbcSMatt Macy echo ${rootfs%%/*} 2808eda14cbcSMatt Macy} 2809eda14cbcSMatt Macy 2810eda14cbcSMatt Macy# 2811eda14cbcSMatt Macy# To verify if the require numbers of disks is given 2812eda14cbcSMatt Macy# 2813eda14cbcSMatt Macyfunction verify_disk_count 2814eda14cbcSMatt Macy{ 2815eda14cbcSMatt Macy typeset -i min=${2:-1} 2816eda14cbcSMatt Macy 2817716fd348SMartin Matuska typeset -i count=$(echo "$1" | wc -w) 2818eda14cbcSMatt Macy 2819eda14cbcSMatt Macy if ((count < min)); then 2820eda14cbcSMatt Macy log_untested "A minimum of $min disks is required to run." \ 2821eda14cbcSMatt Macy " You specified $count disk(s)" 2822eda14cbcSMatt Macy fi 2823eda14cbcSMatt Macy} 2824eda14cbcSMatt Macy 2825eda14cbcSMatt Macyfunction ds_is_volume 2826eda14cbcSMatt Macy{ 2827eda14cbcSMatt Macy typeset type=$(get_prop type $1) 2828716fd348SMartin Matuska [ $type = "volume" ] 2829eda14cbcSMatt Macy} 2830eda14cbcSMatt Macy 2831eda14cbcSMatt Macyfunction ds_is_filesystem 2832eda14cbcSMatt Macy{ 2833eda14cbcSMatt Macy typeset type=$(get_prop type $1) 2834716fd348SMartin Matuska [ $type = "filesystem" ] 2835eda14cbcSMatt Macy} 2836eda14cbcSMatt Macy 2837eda14cbcSMatt Macy# 2838eda14cbcSMatt Macy# Check if Trusted Extensions are installed and enabled 2839eda14cbcSMatt Macy# 2840eda14cbcSMatt Macyfunction is_te_enabled 2841eda14cbcSMatt Macy{ 2842716fd348SMartin Matuska svcs -H -o state labeld 2>/dev/null | grep -q "enabled" 2843eda14cbcSMatt Macy} 2844eda14cbcSMatt Macy 28451f1e2261SMartin Matuska# Return the number of CPUs (cross-platform) 28461f1e2261SMartin Matuskafunction get_num_cpus 28471f1e2261SMartin Matuska{ 28481f1e2261SMartin Matuska if is_linux ; then 28491f1e2261SMartin Matuska grep -c '^processor' /proc/cpuinfo 28501f1e2261SMartin Matuska elif is_freebsd; then 28511f1e2261SMartin Matuska sysctl -n kern.smp.cpus 28521f1e2261SMartin Matuska else 28531f1e2261SMartin Matuska psrinfo | wc -l 28541f1e2261SMartin Matuska fi 28551f1e2261SMartin Matuska} 28561f1e2261SMartin Matuska 2857eda14cbcSMatt Macy# Utility function to determine if a system has multiple cpus. 2858eda14cbcSMatt Macyfunction is_mp 2859eda14cbcSMatt Macy{ 28601f1e2261SMartin Matuska [[ $(get_num_cpus) -gt 1 ]] 2861eda14cbcSMatt Macy} 2862eda14cbcSMatt Macy 2863eda14cbcSMatt Macyfunction get_cpu_freq 2864eda14cbcSMatt Macy{ 2865eda14cbcSMatt Macy if is_linux; then 2866eda14cbcSMatt Macy lscpu | awk '/CPU MHz/ { print $3 }' 2867eda14cbcSMatt Macy elif is_freebsd; then 2868eda14cbcSMatt Macy sysctl -n hw.clockrate 2869eda14cbcSMatt Macy else 2870eda14cbcSMatt Macy psrinfo -v 0 | awk '/processor operates at/ {print $6}' 2871eda14cbcSMatt Macy fi 2872eda14cbcSMatt Macy} 2873eda14cbcSMatt Macy 2874eda14cbcSMatt Macy# Run the given command as the user provided. 2875eda14cbcSMatt Macyfunction user_run 2876eda14cbcSMatt Macy{ 2877eda14cbcSMatt Macy typeset user=$1 2878eda14cbcSMatt Macy shift 2879eda14cbcSMatt Macy 28809db44a8eSMartin Matuska log_note "user: $user" 28819db44a8eSMartin Matuska log_note "cmd: $*" 28829db44a8eSMartin Matuska 28839db44a8eSMartin Matuska typeset out=$TEST_BASE_DIR/out 28849db44a8eSMartin Matuska typeset err=$TEST_BASE_DIR/err 28859db44a8eSMartin Matuska 28869db44a8eSMartin Matuska sudo -Eu $user env PATH="$PATH" ksh <<<"$*" >$out 2>$err 28879db44a8eSMartin Matuska typeset res=$? 28889db44a8eSMartin Matuska log_note "out: $(<$out)" 28899db44a8eSMartin Matuska log_note "err: $(<$err)" 28909db44a8eSMartin Matuska return $res 2891eda14cbcSMatt Macy} 2892eda14cbcSMatt Macy 2893eda14cbcSMatt Macy# 2894eda14cbcSMatt Macy# Check if the pool contains the specified vdevs 2895eda14cbcSMatt Macy# 2896eda14cbcSMatt Macy# $1 pool 2897eda14cbcSMatt Macy# $2..n <vdev> ... 2898eda14cbcSMatt Macy# 2899eda14cbcSMatt Macy# Return 0 if the vdevs are contained in the pool, 1 if any of the specified 2900eda14cbcSMatt Macy# vdevs is not in the pool, and 2 if pool name is missing. 2901eda14cbcSMatt Macy# 2902eda14cbcSMatt Macyfunction vdevs_in_pool 2903eda14cbcSMatt Macy{ 2904eda14cbcSMatt Macy typeset pool=$1 2905eda14cbcSMatt Macy typeset vdev 2906eda14cbcSMatt Macy 2907eda14cbcSMatt Macy if [[ -z $pool ]]; then 2908eda14cbcSMatt Macy log_note "Missing pool name." 2909eda14cbcSMatt Macy return 2 2910eda14cbcSMatt Macy fi 2911eda14cbcSMatt Macy 2912eda14cbcSMatt Macy shift 2913eda14cbcSMatt Macy 2914eda14cbcSMatt Macy # We could use 'zpool list' to only get the vdevs of the pool but we 2915eda14cbcSMatt Macy # can't reference a mirror/raidz vdev using its ID (i.e mirror-0), 2916eda14cbcSMatt Macy # therefore we use the 'zpool status' output. 2917eda14cbcSMatt Macy typeset tmpfile=$(mktemp) 2918eda14cbcSMatt Macy zpool status -v "$pool" | grep -A 1000 "config:" >$tmpfile 2919716fd348SMartin Matuska for vdev in "$@"; do 2920716fd348SMartin Matuska grep -wq ${vdev##*/} $tmpfile || return 1 2921eda14cbcSMatt Macy done 2922eda14cbcSMatt Macy 2923eda14cbcSMatt Macy rm -f $tmpfile 2924716fd348SMartin Matuska return 0 2925eda14cbcSMatt Macy} 2926eda14cbcSMatt Macy 2927eda14cbcSMatt Macyfunction get_max 2928eda14cbcSMatt Macy{ 2929eda14cbcSMatt Macy typeset -l i max=$1 2930eda14cbcSMatt Macy shift 2931eda14cbcSMatt Macy 2932eda14cbcSMatt Macy for i in "$@"; do 2933eda14cbcSMatt Macy max=$((max > i ? max : i)) 2934eda14cbcSMatt Macy done 2935eda14cbcSMatt Macy 2936eda14cbcSMatt Macy echo $max 2937eda14cbcSMatt Macy} 2938eda14cbcSMatt Macy 2939eda14cbcSMatt Macy# Write data that can be compressed into a directory 2940eda14cbcSMatt Macyfunction write_compressible 2941eda14cbcSMatt Macy{ 2942eda14cbcSMatt Macy typeset dir=$1 2943eda14cbcSMatt Macy typeset megs=$2 2944eda14cbcSMatt Macy typeset nfiles=${3:-1} 2945eda14cbcSMatt Macy typeset bs=${4:-1024k} 2946eda14cbcSMatt Macy typeset fname=${5:-file} 2947eda14cbcSMatt Macy 2948eda14cbcSMatt Macy [[ -d $dir ]] || log_fail "No directory: $dir" 2949eda14cbcSMatt Macy 2950eda14cbcSMatt Macy # Under Linux fio is not currently used since its behavior can 2951eda14cbcSMatt Macy # differ significantly across versions. This includes missing 2952eda14cbcSMatt Macy # command line options and cases where the --buffer_compress_* 2953eda14cbcSMatt Macy # options fail to behave as expected. 2954eda14cbcSMatt Macy if is_linux; then 2955eda14cbcSMatt Macy typeset file_bytes=$(to_bytes $megs) 2956eda14cbcSMatt Macy typeset bs_bytes=4096 2957eda14cbcSMatt Macy typeset blocks=$(($file_bytes / $bs_bytes)) 2958eda14cbcSMatt Macy 2959eda14cbcSMatt Macy for (( i = 0; i < $nfiles; i++ )); do 2960eda14cbcSMatt Macy truncate -s $file_bytes $dir/$fname.$i 2961eda14cbcSMatt Macy 2962eda14cbcSMatt Macy # Write every third block to get 66% compression. 2963eda14cbcSMatt Macy for (( j = 0; j < $blocks; j += 3 )); do 2964eda14cbcSMatt Macy dd if=/dev/urandom of=$dir/$fname.$i \ 2965eda14cbcSMatt Macy seek=$j bs=$bs_bytes count=1 \ 2966eda14cbcSMatt Macy conv=notrunc >/dev/null 2>&1 2967eda14cbcSMatt Macy done 2968eda14cbcSMatt Macy done 2969eda14cbcSMatt Macy else 2970716fd348SMartin Matuska command -v fio > /dev/null || log_unsupported "fio missing" 2971716fd348SMartin Matuska log_must eval fio \ 2972eda14cbcSMatt Macy --name=job \ 2973eda14cbcSMatt Macy --fallocate=0 \ 2974eda14cbcSMatt Macy --minimal \ 2975eda14cbcSMatt Macy --randrepeat=0 \ 2976eda14cbcSMatt Macy --buffer_compress_percentage=66 \ 2977eda14cbcSMatt Macy --buffer_compress_chunk=4096 \ 2978716fd348SMartin Matuska --directory="$dir" \ 2979716fd348SMartin Matuska --numjobs="$nfiles" \ 2980716fd348SMartin Matuska --nrfiles="$nfiles" \ 2981eda14cbcSMatt Macy --rw=write \ 2982716fd348SMartin Matuska --bs="$bs" \ 2983716fd348SMartin Matuska --filesize="$megs" \ 2984716fd348SMartin Matuska "--filename_format='$fname.\$jobnum' >/dev/null" 2985eda14cbcSMatt Macy fi 2986eda14cbcSMatt Macy} 2987eda14cbcSMatt Macy 2988eda14cbcSMatt Macyfunction get_objnum 2989eda14cbcSMatt Macy{ 2990eda14cbcSMatt Macy typeset pathname=$1 2991eda14cbcSMatt Macy typeset objnum 2992eda14cbcSMatt Macy 2993eda14cbcSMatt Macy [[ -e $pathname ]] || log_fail "No such file or directory: $pathname" 2994eda14cbcSMatt Macy if is_freebsd; then 2995eda14cbcSMatt Macy objnum=$(stat -f "%i" $pathname) 2996eda14cbcSMatt Macy else 2997eda14cbcSMatt Macy objnum=$(stat -c %i $pathname) 2998eda14cbcSMatt Macy fi 2999eda14cbcSMatt Macy echo $objnum 3000eda14cbcSMatt Macy} 3001eda14cbcSMatt Macy 3002eda14cbcSMatt Macy# 3003eda14cbcSMatt Macy# Sync data to the pool 3004eda14cbcSMatt Macy# 3005eda14cbcSMatt Macy# $1 pool name 3006eda14cbcSMatt Macy# $2 boolean to force uberblock (and config including zpool cache file) update 3007eda14cbcSMatt Macy# 3008eda14cbcSMatt Macyfunction sync_pool #pool <force> 3009eda14cbcSMatt Macy{ 3010eda14cbcSMatt Macy typeset pool=${1:-$TESTPOOL} 3011eda14cbcSMatt Macy typeset force=${2:-false} 3012eda14cbcSMatt Macy 3013eda14cbcSMatt Macy if [[ $force == true ]]; then 3014eda14cbcSMatt Macy log_must zpool sync -f $pool 3015eda14cbcSMatt Macy else 3016eda14cbcSMatt Macy log_must zpool sync $pool 3017eda14cbcSMatt Macy fi 3018eda14cbcSMatt Macy 3019eda14cbcSMatt Macy return 0 3020eda14cbcSMatt Macy} 3021eda14cbcSMatt Macy 3022eda14cbcSMatt Macy# 3023e92ffd9bSMartin Matuska# Sync all pools 3024e92ffd9bSMartin Matuska# 3025e92ffd9bSMartin Matuska# $1 boolean to force uberblock (and config including zpool cache file) update 3026e92ffd9bSMartin Matuska# 3027e92ffd9bSMartin Matuskafunction sync_all_pools #<force> 3028e92ffd9bSMartin Matuska{ 3029e92ffd9bSMartin Matuska typeset force=${1:-false} 3030e92ffd9bSMartin Matuska 3031e92ffd9bSMartin Matuska if [[ $force == true ]]; then 3032e92ffd9bSMartin Matuska log_must zpool sync -f 3033e92ffd9bSMartin Matuska else 3034e92ffd9bSMartin Matuska log_must zpool sync 3035e92ffd9bSMartin Matuska fi 3036e92ffd9bSMartin Matuska 3037e92ffd9bSMartin Matuska return 0 3038e92ffd9bSMartin Matuska} 3039e92ffd9bSMartin Matuska 3040e92ffd9bSMartin Matuska# 3041eda14cbcSMatt Macy# Wait for zpool 'freeing' property drops to zero. 3042eda14cbcSMatt Macy# 3043eda14cbcSMatt Macy# $1 pool name 3044eda14cbcSMatt Macy# 3045eda14cbcSMatt Macyfunction wait_freeing #pool 3046eda14cbcSMatt Macy{ 3047eda14cbcSMatt Macy typeset pool=${1:-$TESTPOOL} 3048eda14cbcSMatt Macy while true; do 3049eda14cbcSMatt Macy [[ "0" == "$(zpool list -Ho freeing $pool)" ]] && break 3050eda14cbcSMatt Macy log_must sleep 1 3051eda14cbcSMatt Macy done 3052eda14cbcSMatt Macy} 3053eda14cbcSMatt Macy 3054eda14cbcSMatt Macy# 3055eda14cbcSMatt Macy# Wait for every device replace operation to complete 3056eda14cbcSMatt Macy# 3057eda14cbcSMatt Macy# $1 pool name 3058e639e0d2SMartin Matuska# $2 timeout 3059eda14cbcSMatt Macy# 3060e639e0d2SMartin Matuskafunction wait_replacing #pool timeout 3061eda14cbcSMatt Macy{ 3062e639e0d2SMartin Matuska typeset timeout=${2:-300} 3063eda14cbcSMatt Macy typeset pool=${1:-$TESTPOOL} 3064e639e0d2SMartin Matuska for (( timer = 0; timer < $timeout; timer++ )); do 3065e639e0d2SMartin Matuska is_pool_replacing $pool || break; 3066e639e0d2SMartin Matuska sleep 1; 3067eda14cbcSMatt Macy done 3068eda14cbcSMatt Macy} 3069eda14cbcSMatt Macy 3070eda14cbcSMatt Macy# Wait for a pool to be scrubbed 3071eda14cbcSMatt Macy# 3072eda14cbcSMatt Macy# $1 pool name 3073c03c5b1cSMartin Matuska# $2 timeout 3074eda14cbcSMatt Macy# 3075c03c5b1cSMartin Matuskafunction wait_scrubbed #pool timeout 3076eda14cbcSMatt Macy{ 3077c03c5b1cSMartin Matuska typeset timeout=${2:-300} 3078eda14cbcSMatt Macy typeset pool=${1:-$TESTPOOL} 3079c03c5b1cSMartin Matuska for (( timer = 0; timer < $timeout; timer++ )); do 3080c03c5b1cSMartin Matuska is_pool_scrubbed $pool && break; 3081c03c5b1cSMartin Matuska sleep 1; 3082eda14cbcSMatt Macy done 3083eda14cbcSMatt Macy} 3084eda14cbcSMatt Macy 3085eda14cbcSMatt Macy# Backup the zed.rc in our test directory so that we can edit it for our test. 3086eda14cbcSMatt Macy# 3087eda14cbcSMatt Macy# Returns: Backup file name. You will need to pass this to zed_rc_restore(). 3088eda14cbcSMatt Macyfunction zed_rc_backup 3089eda14cbcSMatt Macy{ 3090eda14cbcSMatt Macy zedrc_backup="$(mktemp)" 3091eda14cbcSMatt Macy cp $ZEDLET_DIR/zed.rc $zedrc_backup 3092eda14cbcSMatt Macy echo $zedrc_backup 3093eda14cbcSMatt Macy} 3094eda14cbcSMatt Macy 3095eda14cbcSMatt Macyfunction zed_rc_restore 3096eda14cbcSMatt Macy{ 3097eda14cbcSMatt Macy mv $1 $ZEDLET_DIR/zed.rc 3098eda14cbcSMatt Macy} 3099eda14cbcSMatt Macy 3100eda14cbcSMatt Macy# 3101eda14cbcSMatt Macy# Setup custom environment for the ZED. 3102eda14cbcSMatt Macy# 3103eda14cbcSMatt Macy# $@ Optional list of zedlets to run under zed. 3104eda14cbcSMatt Macyfunction zed_setup 3105eda14cbcSMatt Macy{ 3106eda14cbcSMatt Macy if ! is_linux; then 3107716fd348SMartin Matuska log_unsupported "No zed on $UNAME" 3108eda14cbcSMatt Macy fi 3109eda14cbcSMatt Macy 3110eda14cbcSMatt Macy if [[ ! -d $ZEDLET_DIR ]]; then 3111eda14cbcSMatt Macy log_must mkdir $ZEDLET_DIR 3112eda14cbcSMatt Macy fi 3113eda14cbcSMatt Macy 3114eda14cbcSMatt Macy if [[ ! -e $VDEVID_CONF ]]; then 3115eda14cbcSMatt Macy log_must touch $VDEVID_CONF 3116eda14cbcSMatt Macy fi 3117eda14cbcSMatt Macy 3118eda14cbcSMatt Macy if [[ -e $VDEVID_CONF_ETC ]]; then 3119eda14cbcSMatt Macy log_fail "Must not have $VDEVID_CONF_ETC file present on system" 3120eda14cbcSMatt Macy fi 3121eda14cbcSMatt Macy EXTRA_ZEDLETS=$@ 3122eda14cbcSMatt Macy 3123eda14cbcSMatt Macy # Create a symlink for /etc/zfs/vdev_id.conf file. 3124eda14cbcSMatt Macy log_must ln -s $VDEVID_CONF $VDEVID_CONF_ETC 3125eda14cbcSMatt Macy 3126eda14cbcSMatt Macy # Setup minimal ZED configuration. Individual test cases should 3127eda14cbcSMatt Macy # add additional ZEDLETs as needed for their specific test. 3128eda14cbcSMatt Macy log_must cp ${ZEDLET_ETC_DIR}/zed.rc $ZEDLET_DIR 3129eda14cbcSMatt Macy log_must cp ${ZEDLET_ETC_DIR}/zed-functions.sh $ZEDLET_DIR 3130eda14cbcSMatt Macy 3131eda14cbcSMatt Macy # Scripts must only be user writable. 3132eda14cbcSMatt Macy if [[ -n "$EXTRA_ZEDLETS" ]] ; then 3133eda14cbcSMatt Macy saved_umask=$(umask) 3134eda14cbcSMatt Macy log_must umask 0022 3135eda14cbcSMatt Macy for i in $EXTRA_ZEDLETS ; do 3136eda14cbcSMatt Macy log_must cp ${ZEDLET_LIBEXEC_DIR}/$i $ZEDLET_DIR 3137eda14cbcSMatt Macy done 3138eda14cbcSMatt Macy log_must umask $saved_umask 3139eda14cbcSMatt Macy fi 3140eda14cbcSMatt Macy 3141eda14cbcSMatt Macy # Customize the zed.rc file to enable the full debug log. 3142eda14cbcSMatt Macy log_must sed -i '/\#ZED_DEBUG_LOG=.*/d' $ZEDLET_DIR/zed.rc 3143eda14cbcSMatt Macy echo "ZED_DEBUG_LOG=$ZED_DEBUG_LOG" >>$ZEDLET_DIR/zed.rc 3144eda14cbcSMatt Macy 3145eda14cbcSMatt Macy} 3146eda14cbcSMatt Macy 3147eda14cbcSMatt Macy# 3148eda14cbcSMatt Macy# Cleanup custom ZED environment. 3149eda14cbcSMatt Macy# 3150eda14cbcSMatt Macy# $@ Optional list of zedlets to remove from our test zed.d directory. 3151eda14cbcSMatt Macyfunction zed_cleanup 3152eda14cbcSMatt Macy{ 3153eda14cbcSMatt Macy if ! is_linux; then 3154eda14cbcSMatt Macy return 3155eda14cbcSMatt Macy fi 3156eda14cbcSMatt Macy 3157716fd348SMartin Matuska for extra_zedlet; do 3158716fd348SMartin Matuska log_must rm -f ${ZEDLET_DIR}/$extra_zedlet 3159eda14cbcSMatt Macy done 3160716fd348SMartin Matuska log_must rm -fd ${ZEDLET_DIR}/zed.rc ${ZEDLET_DIR}/zed-functions.sh ${ZEDLET_DIR}/all-syslog.sh ${ZEDLET_DIR}/all-debug.sh ${ZEDLET_DIR}/state \ 3161716fd348SMartin Matuska $ZED_LOG $ZED_DEBUG_LOG $VDEVID_CONF_ETC $VDEVID_CONF \ 3162716fd348SMartin Matuska $ZEDLET_DIR 3163eda14cbcSMatt Macy} 3164eda14cbcSMatt Macy 3165eda14cbcSMatt Macy# 3166c03c5b1cSMartin Matuska# Check if ZED is currently running; if so, returns PIDs 3167c03c5b1cSMartin Matuska# 3168c03c5b1cSMartin Matuskafunction zed_check 3169c03c5b1cSMartin Matuska{ 3170c03c5b1cSMartin Matuska if ! is_linux; then 3171c03c5b1cSMartin Matuska return 3172c03c5b1cSMartin Matuska fi 3173c03c5b1cSMartin Matuska zedpids="$(pgrep -x zed)" 3174c03c5b1cSMartin Matuska zedpids2="$(pgrep -x lt-zed)" 3175c03c5b1cSMartin Matuska echo ${zedpids} ${zedpids2} 3176c03c5b1cSMartin Matuska} 3177c03c5b1cSMartin Matuska 3178c03c5b1cSMartin Matuska# 3179eda14cbcSMatt Macy# Check if ZED is currently running, if not start ZED. 3180eda14cbcSMatt Macy# 3181eda14cbcSMatt Macyfunction zed_start 3182eda14cbcSMatt Macy{ 3183eda14cbcSMatt Macy if ! is_linux; then 3184eda14cbcSMatt Macy return 3185eda14cbcSMatt Macy fi 3186eda14cbcSMatt Macy 3187eda14cbcSMatt Macy # ZEDLET_DIR=/var/tmp/zed 3188eda14cbcSMatt Macy if [[ ! -d $ZEDLET_DIR ]]; then 3189eda14cbcSMatt Macy log_must mkdir $ZEDLET_DIR 3190eda14cbcSMatt Macy fi 3191eda14cbcSMatt Macy 3192eda14cbcSMatt Macy # Verify the ZED is not already running. 3193c03c5b1cSMartin Matuska zedpids=$(zed_check) 3194c03c5b1cSMartin Matuska if [ -n "$zedpids" ]; then 3195c03c5b1cSMartin Matuska # We never, ever, really want it to just keep going if zed 3196c03c5b1cSMartin Matuska # is already running - usually this implies our test cases 3197c03c5b1cSMartin Matuska # will break very strangely because whatever we wanted to 3198c03c5b1cSMartin Matuska # configure zed for won't be listening to our changes in the 3199c03c5b1cSMartin Matuska # tmpdir 3200c03c5b1cSMartin Matuska log_fail "ZED already running - ${zedpids}" 3201eda14cbcSMatt Macy else 3202eda14cbcSMatt Macy log_note "Starting ZED" 3203eda14cbcSMatt Macy # run ZED in the background and redirect foreground logging 3204eda14cbcSMatt Macy # output to $ZED_LOG. 3205eda14cbcSMatt Macy log_must truncate -s 0 $ZED_DEBUG_LOG 320616038816SMartin Matuska log_must eval "zed -vF -d $ZEDLET_DIR -P $PATH" \ 320716038816SMartin Matuska "-s $ZEDLET_DIR/state -j 1 2>$ZED_LOG &" 3208eda14cbcSMatt Macy fi 3209eda14cbcSMatt Macy 3210eda14cbcSMatt Macy return 0 3211eda14cbcSMatt Macy} 3212eda14cbcSMatt Macy 3213eda14cbcSMatt Macy# 3214eda14cbcSMatt Macy# Kill ZED process 3215eda14cbcSMatt Macy# 3216eda14cbcSMatt Macyfunction zed_stop 3217eda14cbcSMatt Macy{ 3218eda14cbcSMatt Macy if ! is_linux; then 3219c03c5b1cSMartin Matuska return "" 3220eda14cbcSMatt Macy fi 3221eda14cbcSMatt Macy 3222eda14cbcSMatt Macy log_note "Stopping ZED" 322316038816SMartin Matuska while true; do 3224c03c5b1cSMartin Matuska zedpids=$(zed_check) 3225c03c5b1cSMartin Matuska [ ! -n "$zedpids" ] && break 322616038816SMartin Matuska 322716038816SMartin Matuska log_must kill $zedpids 3228eda14cbcSMatt Macy sleep 1 3229eda14cbcSMatt Macy done 3230eda14cbcSMatt Macy return 0 3231eda14cbcSMatt Macy} 3232eda14cbcSMatt Macy 3233eda14cbcSMatt Macy# 3234eda14cbcSMatt Macy# Drain all zevents 3235eda14cbcSMatt Macy# 3236eda14cbcSMatt Macyfunction zed_events_drain 3237eda14cbcSMatt Macy{ 3238eda14cbcSMatt Macy while [ $(zpool events -H | wc -l) -ne 0 ]; do 3239eda14cbcSMatt Macy sleep 1 3240eda14cbcSMatt Macy zpool events -c >/dev/null 3241eda14cbcSMatt Macy done 3242eda14cbcSMatt Macy} 3243eda14cbcSMatt Macy 3244eda14cbcSMatt Macy# Set a variable in zed.rc to something, un-commenting it in the process. 3245eda14cbcSMatt Macy# 3246eda14cbcSMatt Macy# $1 variable 3247eda14cbcSMatt Macy# $2 value 3248eda14cbcSMatt Macyfunction zed_rc_set 3249eda14cbcSMatt Macy{ 3250eda14cbcSMatt Macy var="$1" 3251eda14cbcSMatt Macy val="$2" 3252eda14cbcSMatt Macy # Remove the line 3253eda14cbcSMatt Macy cmd="'/$var/d'" 3254eda14cbcSMatt Macy eval sed -i $cmd $ZEDLET_DIR/zed.rc 3255eda14cbcSMatt Macy 3256eda14cbcSMatt Macy # Add it at the end 3257eda14cbcSMatt Macy echo "$var=$val" >> $ZEDLET_DIR/zed.rc 3258eda14cbcSMatt Macy} 3259eda14cbcSMatt Macy 3260eda14cbcSMatt Macy 3261eda14cbcSMatt Macy# 3262eda14cbcSMatt Macy# Check is provided device is being active used as a swap device. 3263eda14cbcSMatt Macy# 3264eda14cbcSMatt Macyfunction is_swap_inuse 3265eda14cbcSMatt Macy{ 3266eda14cbcSMatt Macy typeset device=$1 3267eda14cbcSMatt Macy 3268eda14cbcSMatt Macy if [[ -z $device ]] ; then 3269eda14cbcSMatt Macy log_note "No device specified." 3270eda14cbcSMatt Macy return 1 3271eda14cbcSMatt Macy fi 3272eda14cbcSMatt Macy 3273716fd348SMartin Matuska case "$UNAME" in 3274716fd348SMartin Matuska Linux) 3275716fd348SMartin Matuska swapon -s | grep -wq $(readlink -f $device) 3276716fd348SMartin Matuska ;; 3277716fd348SMartin Matuska FreeBSD) 3278716fd348SMartin Matuska swapctl -l | grep -wq $device 3279716fd348SMartin Matuska ;; 3280716fd348SMartin Matuska *) 3281716fd348SMartin Matuska swap -l | grep -wq $device 3282716fd348SMartin Matuska ;; 3283716fd348SMartin Matuska esac 3284eda14cbcSMatt Macy} 3285eda14cbcSMatt Macy 3286eda14cbcSMatt Macy# 3287eda14cbcSMatt Macy# Setup a swap device using the provided device. 3288eda14cbcSMatt Macy# 3289eda14cbcSMatt Macyfunction swap_setup 3290eda14cbcSMatt Macy{ 3291eda14cbcSMatt Macy typeset swapdev=$1 3292eda14cbcSMatt Macy 3293716fd348SMartin Matuska case "$UNAME" in 3294716fd348SMartin Matuska Linux) 3295eda14cbcSMatt Macy log_must eval "mkswap $swapdev > /dev/null 2>&1" 3296eda14cbcSMatt Macy log_must swapon $swapdev 3297716fd348SMartin Matuska ;; 3298716fd348SMartin Matuska FreeBSD) 3299eda14cbcSMatt Macy log_must swapctl -a $swapdev 3300716fd348SMartin Matuska ;; 3301716fd348SMartin Matuska *) 3302eda14cbcSMatt Macy log_must swap -a $swapdev 3303716fd348SMartin Matuska ;; 3304716fd348SMartin Matuska esac 3305eda14cbcSMatt Macy 3306eda14cbcSMatt Macy return 0 3307eda14cbcSMatt Macy} 3308eda14cbcSMatt Macy 3309eda14cbcSMatt Macy# 3310eda14cbcSMatt Macy# Cleanup a swap device on the provided device. 3311eda14cbcSMatt Macy# 3312eda14cbcSMatt Macyfunction swap_cleanup 3313eda14cbcSMatt Macy{ 3314eda14cbcSMatt Macy typeset swapdev=$1 3315eda14cbcSMatt Macy 3316eda14cbcSMatt Macy if is_swap_inuse $swapdev; then 3317eda14cbcSMatt Macy if is_linux; then 3318eda14cbcSMatt Macy log_must swapoff $swapdev 3319eda14cbcSMatt Macy elif is_freebsd; then 3320eda14cbcSMatt Macy log_must swapoff $swapdev 3321eda14cbcSMatt Macy else 3322eda14cbcSMatt Macy log_must swap -d $swapdev 3323eda14cbcSMatt Macy fi 3324eda14cbcSMatt Macy fi 3325eda14cbcSMatt Macy 3326eda14cbcSMatt Macy return 0 3327eda14cbcSMatt Macy} 3328eda14cbcSMatt Macy 3329eda14cbcSMatt Macy# 3330eda14cbcSMatt Macy# Set a global system tunable (64-bit value) 3331eda14cbcSMatt Macy# 3332eda14cbcSMatt Macy# $1 tunable name (use a NAME defined in tunables.cfg) 3333eda14cbcSMatt Macy# $2 tunable values 3334eda14cbcSMatt Macy# 3335eda14cbcSMatt Macyfunction set_tunable64 3336eda14cbcSMatt Macy{ 3337eda14cbcSMatt Macy set_tunable_impl "$1" "$2" Z 3338eda14cbcSMatt Macy} 3339eda14cbcSMatt Macy 3340eda14cbcSMatt Macy# 3341eda14cbcSMatt Macy# Set a global system tunable (32-bit value) 3342eda14cbcSMatt Macy# 3343eda14cbcSMatt Macy# $1 tunable name (use a NAME defined in tunables.cfg) 3344eda14cbcSMatt Macy# $2 tunable values 3345eda14cbcSMatt Macy# 3346eda14cbcSMatt Macyfunction set_tunable32 3347eda14cbcSMatt Macy{ 3348eda14cbcSMatt Macy set_tunable_impl "$1" "$2" W 3349eda14cbcSMatt Macy} 3350eda14cbcSMatt Macy 3351eda14cbcSMatt Macyfunction set_tunable_impl 3352eda14cbcSMatt Macy{ 3353eda14cbcSMatt Macy typeset name="$1" 3354eda14cbcSMatt Macy typeset value="$2" 3355eda14cbcSMatt Macy typeset mdb_cmd="$3" 3356eda14cbcSMatt Macy 3357eda14cbcSMatt Macy eval "typeset tunable=\$$name" 3358eda14cbcSMatt Macy case "$tunable" in 3359eda14cbcSMatt Macy UNSUPPORTED) 3360716fd348SMartin Matuska log_unsupported "Tunable '$name' is unsupported on $UNAME" 3361eda14cbcSMatt Macy ;; 3362eda14cbcSMatt Macy "") 3363eda14cbcSMatt Macy log_fail "Tunable '$name' must be added to tunables.cfg" 3364eda14cbcSMatt Macy ;; 3365eda14cbcSMatt Macy *) 3366eda14cbcSMatt Macy ;; 3367eda14cbcSMatt Macy esac 3368eda14cbcSMatt Macy 3369eda14cbcSMatt Macy [[ -z "$value" ]] && return 1 3370eda14cbcSMatt Macy [[ -z "$mdb_cmd" ]] && return 1 3371eda14cbcSMatt Macy 3372716fd348SMartin Matuska case "$UNAME" in 3373eda14cbcSMatt Macy Linux) 3374716fd348SMartin Matuska typeset zfs_tunables="/sys/module/zfs/parameters" 3375716fd348SMartin Matuska echo "$value" >"$zfs_tunables/$tunable" 3376eda14cbcSMatt Macy ;; 3377eda14cbcSMatt Macy FreeBSD) 3378eda14cbcSMatt Macy sysctl vfs.zfs.$tunable=$value 3379eda14cbcSMatt Macy ;; 3380eda14cbcSMatt Macy SunOS) 3381eda14cbcSMatt Macy echo "${tunable}/${mdb_cmd}0t${value}" | mdb -kw 3382eda14cbcSMatt Macy ;; 3383eda14cbcSMatt Macy esac 3384eda14cbcSMatt Macy} 3385eda14cbcSMatt Macy 338647bb16f8SMartin Matuskafunction save_tunable 338747bb16f8SMartin Matuska{ 338847bb16f8SMartin Matuska [[ ! -d $TEST_BASE_DIR ]] && return 1 338947bb16f8SMartin Matuska [[ -e $TEST_BASE_DIR/tunable-$1 ]] && return 2 339047bb16f8SMartin Matuska echo "$(get_tunable """$1""")" > "$TEST_BASE_DIR"/tunable-"$1" 339147bb16f8SMartin Matuska} 339247bb16f8SMartin Matuska 339347bb16f8SMartin Matuskafunction restore_tunable 339447bb16f8SMartin Matuska{ 339547bb16f8SMartin Matuska [[ ! -e $TEST_BASE_DIR/tunable-$1 ]] && return 1 339647bb16f8SMartin Matuska val="$(cat $TEST_BASE_DIR/tunable-"""$1""")" 339747bb16f8SMartin Matuska set_tunable64 "$1" "$val" 339847bb16f8SMartin Matuska rm $TEST_BASE_DIR/tunable-$1 339947bb16f8SMartin Matuska} 340047bb16f8SMartin Matuska 3401eda14cbcSMatt Macy# 3402eda14cbcSMatt Macy# Get a global system tunable 3403eda14cbcSMatt Macy# 3404eda14cbcSMatt Macy# $1 tunable name (use a NAME defined in tunables.cfg) 3405eda14cbcSMatt Macy# 3406eda14cbcSMatt Macyfunction get_tunable 3407eda14cbcSMatt Macy{ 3408eda14cbcSMatt Macy get_tunable_impl "$1" 3409eda14cbcSMatt Macy} 3410eda14cbcSMatt Macy 3411eda14cbcSMatt Macyfunction get_tunable_impl 3412eda14cbcSMatt Macy{ 3413eda14cbcSMatt Macy typeset name="$1" 3414eda14cbcSMatt Macy typeset module="${2:-zfs}" 34151f1e2261SMartin Matuska typeset check_only="$3" 3416eda14cbcSMatt Macy 3417eda14cbcSMatt Macy eval "typeset tunable=\$$name" 3418eda14cbcSMatt Macy case "$tunable" in 3419eda14cbcSMatt Macy UNSUPPORTED) 34201f1e2261SMartin Matuska if [ -z "$check_only" ] ; then 3421716fd348SMartin Matuska log_unsupported "Tunable '$name' is unsupported on $UNAME" 34221f1e2261SMartin Matuska else 34231f1e2261SMartin Matuska return 1 34241f1e2261SMartin Matuska fi 3425eda14cbcSMatt Macy ;; 3426eda14cbcSMatt Macy "") 34271f1e2261SMartin Matuska if [ -z "$check_only" ] ; then 3428eda14cbcSMatt Macy log_fail "Tunable '$name' must be added to tunables.cfg" 34291f1e2261SMartin Matuska else 34301f1e2261SMartin Matuska return 1 34311f1e2261SMartin Matuska fi 3432eda14cbcSMatt Macy ;; 3433eda14cbcSMatt Macy *) 3434eda14cbcSMatt Macy ;; 3435eda14cbcSMatt Macy esac 3436eda14cbcSMatt Macy 3437716fd348SMartin Matuska case "$UNAME" in 3438eda14cbcSMatt Macy Linux) 3439eda14cbcSMatt Macy typeset zfs_tunables="/sys/module/$module/parameters" 3440eda14cbcSMatt Macy cat $zfs_tunables/$tunable 3441eda14cbcSMatt Macy ;; 3442eda14cbcSMatt Macy FreeBSD) 3443eda14cbcSMatt Macy sysctl -n vfs.zfs.$tunable 3444eda14cbcSMatt Macy ;; 3445eda14cbcSMatt Macy SunOS) 3446eda14cbcSMatt Macy [[ "$module" -eq "zfs" ]] || return 1 3447eda14cbcSMatt Macy ;; 3448eda14cbcSMatt Macy esac 3449eda14cbcSMatt Macy} 3450eda14cbcSMatt Macy 34511f1e2261SMartin Matuska# Does a tunable exist? 34521f1e2261SMartin Matuska# 34531f1e2261SMartin Matuska# $1: Tunable name 34541f1e2261SMartin Matuskafunction tunable_exists 34551f1e2261SMartin Matuska{ 34561f1e2261SMartin Matuska get_tunable_impl $1 "zfs" 1 34571f1e2261SMartin Matuska} 34581f1e2261SMartin Matuska 3459eda14cbcSMatt Macy# 34607a7741afSMartin Matuska# Compute xxh128sum for given file or stdin if no file given. 3461eda14cbcSMatt Macy# Note: file path must not contain spaces 3462eda14cbcSMatt Macy# 34637a7741afSMartin Matuskafunction xxh128digest 3464eda14cbcSMatt Macy{ 34657a7741afSMartin Matuska xxh128sum $1 | awk '{print $1}' 3466eda14cbcSMatt Macy} 3467eda14cbcSMatt Macy 3468eda14cbcSMatt Macy# 34697a7741afSMartin Matuska# Compare the xxhash128 digest of two files. 3470eda14cbcSMatt Macy# 34717a7741afSMartin Matuskafunction cmp_xxh128 { 34727a7741afSMartin Matuska typeset file1=$1 34737a7741afSMartin Matuska typeset file2=$2 3474eda14cbcSMatt Macy 34757a7741afSMartin Matuska typeset sum1=$(xxh128digest $file1) 34767a7741afSMartin Matuska typeset sum2=$(xxh128digest $file2) 34777a7741afSMartin Matuska test "$sum1" = "$sum2" 3478eda14cbcSMatt Macy} 3479eda14cbcSMatt Macy 3480eda14cbcSMatt Macyfunction new_fs #<args> 3481eda14cbcSMatt Macy{ 3482716fd348SMartin Matuska case "$UNAME" in 3483eda14cbcSMatt Macy FreeBSD) 3484eda14cbcSMatt Macy newfs "$@" 3485eda14cbcSMatt Macy ;; 3486eda14cbcSMatt Macy *) 3487eda14cbcSMatt Macy echo y | newfs -v "$@" 3488eda14cbcSMatt Macy ;; 3489eda14cbcSMatt Macy esac 3490eda14cbcSMatt Macy} 3491eda14cbcSMatt Macy 3492eda14cbcSMatt Macyfunction stat_size #<path> 3493eda14cbcSMatt Macy{ 3494eda14cbcSMatt Macy typeset path=$1 3495eda14cbcSMatt Macy 3496716fd348SMartin Matuska case "$UNAME" in 3497eda14cbcSMatt Macy FreeBSD) 3498eda14cbcSMatt Macy stat -f %z "$path" 3499eda14cbcSMatt Macy ;; 3500eda14cbcSMatt Macy *) 3501eda14cbcSMatt Macy stat -c %s "$path" 3502eda14cbcSMatt Macy ;; 3503eda14cbcSMatt Macy esac 3504eda14cbcSMatt Macy} 3505eda14cbcSMatt Macy 3506271171e0SMartin Matuskafunction stat_mtime #<path> 3507271171e0SMartin Matuska{ 3508271171e0SMartin Matuska typeset path=$1 3509271171e0SMartin Matuska 3510271171e0SMartin Matuska case "$UNAME" in 3511271171e0SMartin Matuska FreeBSD) 3512271171e0SMartin Matuska stat -f %m "$path" 3513271171e0SMartin Matuska ;; 3514271171e0SMartin Matuska *) 3515271171e0SMartin Matuska stat -c %Y "$path" 3516271171e0SMartin Matuska ;; 3517271171e0SMartin Matuska esac 3518271171e0SMartin Matuska} 3519271171e0SMartin Matuska 35202faf504dSMartin Matuskafunction stat_ctime #<path> 35212faf504dSMartin Matuska{ 35222faf504dSMartin Matuska typeset path=$1 35232faf504dSMartin Matuska 3524716fd348SMartin Matuska case "$UNAME" in 35252faf504dSMartin Matuska FreeBSD) 35262faf504dSMartin Matuska stat -f %c "$path" 35272faf504dSMartin Matuska ;; 35282faf504dSMartin Matuska *) 35292faf504dSMartin Matuska stat -c %Z "$path" 35302faf504dSMartin Matuska ;; 35312faf504dSMartin Matuska esac 35322faf504dSMartin Matuska} 35332faf504dSMartin Matuska 35342faf504dSMartin Matuskafunction stat_crtime #<path> 35352faf504dSMartin Matuska{ 35362faf504dSMartin Matuska typeset path=$1 35372faf504dSMartin Matuska 3538716fd348SMartin Matuska case "$UNAME" in 35392faf504dSMartin Matuska FreeBSD) 35402faf504dSMartin Matuska stat -f %B "$path" 35412faf504dSMartin Matuska ;; 35422faf504dSMartin Matuska *) 35432faf504dSMartin Matuska stat -c %W "$path" 35442faf504dSMartin Matuska ;; 35452faf504dSMartin Matuska esac 35462faf504dSMartin Matuska} 35472faf504dSMartin Matuska 3548e92ffd9bSMartin Matuskafunction stat_generation #<path> 3549e92ffd9bSMartin Matuska{ 3550e92ffd9bSMartin Matuska typeset path=$1 3551e92ffd9bSMartin Matuska 3552716fd348SMartin Matuska case "$UNAME" in 3553e92ffd9bSMartin Matuska Linux) 3554e92ffd9bSMartin Matuska getversion "${path}" 3555e92ffd9bSMartin Matuska ;; 3556e92ffd9bSMartin Matuska *) 3557e92ffd9bSMartin Matuska stat -f %v "${path}" 3558e92ffd9bSMartin Matuska ;; 3559e92ffd9bSMartin Matuska esac 3560e92ffd9bSMartin Matuska} 3561e92ffd9bSMartin Matuska 3562eda14cbcSMatt Macy# Run a command as if it was being run in a TTY. 3563eda14cbcSMatt Macy# 3564eda14cbcSMatt Macy# Usage: 3565eda14cbcSMatt Macy# 3566eda14cbcSMatt Macy# faketty command 3567eda14cbcSMatt Macy# 3568eda14cbcSMatt Macyfunction faketty 3569eda14cbcSMatt Macy{ 3570eda14cbcSMatt Macy if is_freebsd; then 3571eda14cbcSMatt Macy script -q /dev/null env "$@" 3572eda14cbcSMatt Macy else 3573eda14cbcSMatt Macy script --return --quiet -c "$*" /dev/null 3574eda14cbcSMatt Macy fi 3575eda14cbcSMatt Macy} 3576eda14cbcSMatt Macy 3577eda14cbcSMatt Macy# 3578eda14cbcSMatt Macy# Produce a random permutation of the integers in a given range (inclusive). 3579eda14cbcSMatt Macy# 3580eda14cbcSMatt Macyfunction range_shuffle # begin end 3581eda14cbcSMatt Macy{ 3582eda14cbcSMatt Macy typeset -i begin=$1 3583eda14cbcSMatt Macy typeset -i end=$2 3584eda14cbcSMatt Macy 3585eda14cbcSMatt Macy seq ${begin} ${end} | sort -R 3586eda14cbcSMatt Macy} 3587eda14cbcSMatt Macy 3588eda14cbcSMatt Macy# 3589eda14cbcSMatt Macy# Cross-platform xattr helpers 3590eda14cbcSMatt Macy# 3591eda14cbcSMatt Macy 3592eda14cbcSMatt Macyfunction get_xattr # name path 3593eda14cbcSMatt Macy{ 3594eda14cbcSMatt Macy typeset name=$1 3595eda14cbcSMatt Macy typeset path=$2 3596eda14cbcSMatt Macy 3597716fd348SMartin Matuska case "$UNAME" in 3598eda14cbcSMatt Macy FreeBSD) 3599eda14cbcSMatt Macy getextattr -qq user "${name}" "${path}" 3600eda14cbcSMatt Macy ;; 3601eda14cbcSMatt Macy *) 3602eda14cbcSMatt Macy attr -qg "${name}" "${path}" 3603eda14cbcSMatt Macy ;; 3604eda14cbcSMatt Macy esac 3605eda14cbcSMatt Macy} 3606eda14cbcSMatt Macy 3607eda14cbcSMatt Macyfunction set_xattr # name value path 3608eda14cbcSMatt Macy{ 3609eda14cbcSMatt Macy typeset name=$1 3610eda14cbcSMatt Macy typeset value=$2 3611eda14cbcSMatt Macy typeset path=$3 3612eda14cbcSMatt Macy 3613716fd348SMartin Matuska case "$UNAME" in 3614eda14cbcSMatt Macy FreeBSD) 3615eda14cbcSMatt Macy setextattr user "${name}" "${value}" "${path}" 3616eda14cbcSMatt Macy ;; 3617eda14cbcSMatt Macy *) 3618eda14cbcSMatt Macy attr -qs "${name}" -V "${value}" "${path}" 3619eda14cbcSMatt Macy ;; 3620eda14cbcSMatt Macy esac 3621eda14cbcSMatt Macy} 3622eda14cbcSMatt Macy 3623eda14cbcSMatt Macyfunction set_xattr_stdin # name value 3624eda14cbcSMatt Macy{ 3625eda14cbcSMatt Macy typeset name=$1 3626eda14cbcSMatt Macy typeset path=$2 3627eda14cbcSMatt Macy 3628716fd348SMartin Matuska case "$UNAME" in 3629eda14cbcSMatt Macy FreeBSD) 3630eda14cbcSMatt Macy setextattr -i user "${name}" "${path}" 3631eda14cbcSMatt Macy ;; 3632eda14cbcSMatt Macy *) 3633eda14cbcSMatt Macy attr -qs "${name}" "${path}" 3634eda14cbcSMatt Macy ;; 3635eda14cbcSMatt Macy esac 3636eda14cbcSMatt Macy} 3637eda14cbcSMatt Macy 3638eda14cbcSMatt Macyfunction rm_xattr # name path 3639eda14cbcSMatt Macy{ 3640eda14cbcSMatt Macy typeset name=$1 3641eda14cbcSMatt Macy typeset path=$2 3642eda14cbcSMatt Macy 3643716fd348SMartin Matuska case "$UNAME" in 3644eda14cbcSMatt Macy FreeBSD) 3645eda14cbcSMatt Macy rmextattr -q user "${name}" "${path}" 3646eda14cbcSMatt Macy ;; 3647eda14cbcSMatt Macy *) 3648eda14cbcSMatt Macy attr -qr "${name}" "${path}" 3649eda14cbcSMatt Macy ;; 3650eda14cbcSMatt Macy esac 3651eda14cbcSMatt Macy} 3652eda14cbcSMatt Macy 3653eda14cbcSMatt Macyfunction ls_xattr # path 3654eda14cbcSMatt Macy{ 3655eda14cbcSMatt Macy typeset path=$1 3656eda14cbcSMatt Macy 3657716fd348SMartin Matuska case "$UNAME" in 3658eda14cbcSMatt Macy FreeBSD) 3659eda14cbcSMatt Macy lsextattr -qq user "${path}" 3660eda14cbcSMatt Macy ;; 3661eda14cbcSMatt Macy *) 3662eda14cbcSMatt Macy attr -ql "${path}" 3663eda14cbcSMatt Macy ;; 3664eda14cbcSMatt Macy esac 3665eda14cbcSMatt Macy} 3666eda14cbcSMatt Macy 366721b492edSMartin Matuskafunction punch_hole # offset length file 366821b492edSMartin Matuska{ 366921b492edSMartin Matuska typeset offset=$1 367021b492edSMartin Matuska typeset length=$2 367121b492edSMartin Matuska typeset file=$3 367221b492edSMartin Matuska 3673716fd348SMartin Matuska case "$UNAME" in 367421b492edSMartin Matuska FreeBSD) 367521b492edSMartin Matuska truncate -d -o $offset -l $length "$file" 367621b492edSMartin Matuska ;; 367721b492edSMartin Matuska Linux) 367821b492edSMartin Matuska fallocate --punch-hole --offset $offset --length $length "$file" 367921b492edSMartin Matuska ;; 368021b492edSMartin Matuska *) 368121b492edSMartin Matuska false 368221b492edSMartin Matuska ;; 368321b492edSMartin Matuska esac 368421b492edSMartin Matuska} 368521b492edSMartin Matuska 3686716fd348SMartin Matuskafunction zero_range # offset length file 3687716fd348SMartin Matuska{ 3688716fd348SMartin Matuska typeset offset=$1 3689716fd348SMartin Matuska typeset length=$2 3690716fd348SMartin Matuska typeset file=$3 3691716fd348SMartin Matuska 3692716fd348SMartin Matuska case "$UNAME" in 3693716fd348SMartin Matuska Linux) 3694716fd348SMartin Matuska fallocate --zero-range --offset $offset --length $length "$file" 3695716fd348SMartin Matuska ;; 3696716fd348SMartin Matuska *) 3697716fd348SMartin Matuska false 3698716fd348SMartin Matuska ;; 3699716fd348SMartin Matuska esac 3700716fd348SMartin Matuska} 3701716fd348SMartin Matuska 3702eda14cbcSMatt Macy# 37037877fdebSMatt Macy# Wait for the specified arcstat to reach non-zero quiescence. 37047877fdebSMatt Macy# If echo is 1 echo the value after reaching quiescence, otherwise 37057877fdebSMatt Macy# if echo is 0 print the arcstat we are waiting on. 37067877fdebSMatt Macy# 37077877fdebSMatt Macyfunction arcstat_quiescence # stat echo 37087877fdebSMatt Macy{ 37097877fdebSMatt Macy typeset stat=$1 37107877fdebSMatt Macy typeset echo=$2 37117877fdebSMatt Macy typeset do_once=true 37127877fdebSMatt Macy 37137877fdebSMatt Macy if [[ $echo -eq 0 ]]; then 37147877fdebSMatt Macy echo "Waiting for arcstat $1 quiescence." 37157877fdebSMatt Macy fi 37167877fdebSMatt Macy 37177877fdebSMatt Macy while $do_once || [ $stat1 -ne $stat2 ] || [ $stat2 -eq 0 ]; do 3718*c6767dc1SMartin Matuska typeset stat1=$(kstat arcstats.$stat) 3719b7198dcfSMartin Matuska sleep 0.5 3720*c6767dc1SMartin Matuska typeset stat2=$(kstat arcstats.$stat) 37217877fdebSMatt Macy do_once=false 37227877fdebSMatt Macy done 37237877fdebSMatt Macy 37247877fdebSMatt Macy if [[ $echo -eq 1 ]]; then 37257877fdebSMatt Macy echo $stat2 37267877fdebSMatt Macy fi 37277877fdebSMatt Macy} 37287877fdebSMatt Macy 37297877fdebSMatt Macyfunction arcstat_quiescence_noecho # stat 37307877fdebSMatt Macy{ 37317877fdebSMatt Macy typeset stat=$1 37327877fdebSMatt Macy arcstat_quiescence $stat 0 37337877fdebSMatt Macy} 37347877fdebSMatt Macy 37357877fdebSMatt Macyfunction arcstat_quiescence_echo # stat 37367877fdebSMatt Macy{ 37377877fdebSMatt Macy typeset stat=$1 37387877fdebSMatt Macy arcstat_quiescence $stat 1 37397877fdebSMatt Macy} 37407877fdebSMatt Macy 37417877fdebSMatt Macy# 3742eda14cbcSMatt Macy# Given an array of pids, wait until all processes 3743eda14cbcSMatt Macy# have completed and check their return status. 3744eda14cbcSMatt Macy# 3745eda14cbcSMatt Macyfunction wait_for_children #children 3746eda14cbcSMatt Macy{ 3747eda14cbcSMatt Macy rv=0 3748eda14cbcSMatt Macy children=("$@") 3749eda14cbcSMatt Macy for child in "${children[@]}" 3750eda14cbcSMatt Macy do 3751eda14cbcSMatt Macy child_exit=0 3752eda14cbcSMatt Macy wait ${child} || child_exit=$? 3753eda14cbcSMatt Macy if [ $child_exit -ne 0 ]; then 3754eda14cbcSMatt Macy echo "child ${child} failed with ${child_exit}" 3755eda14cbcSMatt Macy rv=1 3756eda14cbcSMatt Macy fi 3757eda14cbcSMatt Macy done 3758eda14cbcSMatt Macy return $rv 3759eda14cbcSMatt Macy} 3760c03c5b1cSMartin Matuska 3761c03c5b1cSMartin Matuska# 3762c03c5b1cSMartin Matuska# Compare two directory trees recursively in a manner similar to diff(1), but 3763c03c5b1cSMartin Matuska# using rsync. If there are any discrepancies, a summary of the differences are 3764c03c5b1cSMartin Matuska# output and a non-zero error is returned. 3765c03c5b1cSMartin Matuska# 3766c03c5b1cSMartin Matuska# If you're comparing a directory after a ZIL replay, you should set 3767c03c5b1cSMartin Matuska# LIBTEST_DIFF_ZIL_REPLAY=1 or use replay_directory_diff which will cause 3768c03c5b1cSMartin Matuska# directory_diff to ignore mtime changes (the ZIL replay won't fix up mtime 3769c03c5b1cSMartin Matuska# information). 3770c03c5b1cSMartin Matuska# 3771c03c5b1cSMartin Matuskafunction directory_diff # dir_a dir_b 3772c03c5b1cSMartin Matuska{ 3773c03c5b1cSMartin Matuska dir_a="$1" 3774c03c5b1cSMartin Matuska dir_b="$2" 3775c03c5b1cSMartin Matuska zil_replay="${LIBTEST_DIFF_ZIL_REPLAY:-0}" 3776c03c5b1cSMartin Matuska 3777c03c5b1cSMartin Matuska # If one of the directories doesn't exist, return 2. This is to match the 3778c03c5b1cSMartin Matuska # semantics of diff. 3779c03c5b1cSMartin Matuska if ! [ -d "$dir_a" -a -d "$dir_b" ]; then 3780c03c5b1cSMartin Matuska return 2 3781c03c5b1cSMartin Matuska fi 3782c03c5b1cSMartin Matuska 3783c03c5b1cSMartin Matuska # Run rsync with --dry-run --itemize-changes to get something akin to diff 3784c03c5b1cSMartin Matuska # output, but rsync is far more thorough in detecting differences (diff 3785c03c5b1cSMartin Matuska # doesn't compare file metadata, and cannot handle special files). 3786c03c5b1cSMartin Matuska # 3787c03c5b1cSMartin Matuska # Also make sure to filter out non-user.* xattrs when comparing. On 3788c03c5b1cSMartin Matuska # SELinux-enabled systems the copied tree will probably have different 3789c03c5b1cSMartin Matuska # SELinux labels. 3790c03c5b1cSMartin Matuska args=("-nicaAHX" '--filter=-x! user.*' "--delete") 3791c03c5b1cSMartin Matuska 3792c03c5b1cSMartin Matuska # NOTE: Quite a few rsync builds do not support --crtimes which would be 3793c03c5b1cSMartin Matuska # necessary to verify that creation times are being maintained properly. 3794c03c5b1cSMartin Matuska # Unfortunately because of this we cannot use it unconditionally but we can 3795c03c5b1cSMartin Matuska # check if this rsync build supports it and use it then. This check is 3796c03c5b1cSMartin Matuska # based on the same check in the rsync test suite (testsuite/crtimes.test). 3797c03c5b1cSMartin Matuska # 3798c03c5b1cSMartin Matuska # We check ctimes even with zil_replay=1 because the ZIL does store 3799c03c5b1cSMartin Matuska # creation times and we should make sure they match (if the creation times 3800c03c5b1cSMartin Matuska # do not match there is a "c" entry in one of the columns). 3801716fd348SMartin Matuska if rsync --version | grep -q "[, ] crtimes"; then 3802c03c5b1cSMartin Matuska args+=("--crtimes") 3803c03c5b1cSMartin Matuska else 3804716fd348SMartin Matuska log_note "This rsync package does not support --crtimes (-N)." 3805c03c5b1cSMartin Matuska fi 3806c03c5b1cSMartin Matuska 3807c03c5b1cSMartin Matuska # If we are testing a ZIL replay, we need to ignore timestamp changes. 3808c03c5b1cSMartin Matuska # Unfortunately --no-times doesn't do what we want -- it will still tell 3809c03c5b1cSMartin Matuska # you if the timestamps don't match but rsync will set the timestamps to 3810c03c5b1cSMartin Matuska # the current time (leading to an itemised change entry). It's simpler to 3811c03c5b1cSMartin Matuska # just filter out those lines. 3812c03c5b1cSMartin Matuska if [ "$zil_replay" -eq 0 ]; then 3813c03c5b1cSMartin Matuska filter=("cat") 3814c03c5b1cSMartin Matuska else 3815c03c5b1cSMartin Matuska # Different rsync versions have different numbers of columns. So just 3816c03c5b1cSMartin Matuska # require that aside from the first two, all other columns must be 3817c03c5b1cSMartin Matuska # blank (literal ".") or a timestamp field ("[tT]"). 3818c03c5b1cSMartin Matuska filter=("grep" "-v" '^\..[.Tt]\+ ') 3819c03c5b1cSMartin Matuska fi 3820c03c5b1cSMartin Matuska 3821c03c5b1cSMartin Matuska diff="$(rsync "${args[@]}" "$dir_a/" "$dir_b/" | "${filter[@]}")" 3822c03c5b1cSMartin Matuska rv=0 3823c03c5b1cSMartin Matuska if [ -n "$diff" ]; then 3824c03c5b1cSMartin Matuska echo "$diff" 3825c03c5b1cSMartin Matuska rv=1 3826c03c5b1cSMartin Matuska fi 3827c03c5b1cSMartin Matuska return $rv 3828c03c5b1cSMartin Matuska} 3829c03c5b1cSMartin Matuska 3830c03c5b1cSMartin Matuska# 3831c03c5b1cSMartin Matuska# Compare two directory trees recursively, without checking whether the mtimes 3832c03c5b1cSMartin Matuska# match (creation times will be checked if the available rsync binary supports 3833c03c5b1cSMartin Matuska# it). This is necessary for ZIL replay checks (because the ZIL does not 3834c03c5b1cSMartin Matuska# contain mtimes and thus after a ZIL replay, mtimes won't match). 3835c03c5b1cSMartin Matuska# 3836c03c5b1cSMartin Matuska# This is shorthand for LIBTEST_DIFF_ZIL_REPLAY=1 directory_diff <...>. 3837c03c5b1cSMartin Matuska# 3838c03c5b1cSMartin Matuskafunction replay_directory_diff # dir_a dir_b 3839c03c5b1cSMartin Matuska{ 3840c03c5b1cSMartin Matuska LIBTEST_DIFF_ZIL_REPLAY=1 directory_diff "$@" 3841716fd348SMartin Matuska} 3842716fd348SMartin Matuska 3843716fd348SMartin Matuska# 3844716fd348SMartin Matuska# Put coredumps into $1/core.{basename} 3845716fd348SMartin Matuska# 3846716fd348SMartin Matuska# Output must be saved and passed to pop_coredump_pattern on cleanup 3847716fd348SMartin Matuska# 3848716fd348SMartin Matuskafunction push_coredump_pattern # dir 3849716fd348SMartin Matuska{ 3850716fd348SMartin Matuska ulimit -c unlimited 3851716fd348SMartin Matuska case "$UNAME" in 3852716fd348SMartin Matuska Linux) 3853716fd348SMartin Matuska cat /proc/sys/kernel/core_pattern /proc/sys/kernel/core_uses_pid 3854716fd348SMartin Matuska echo "$1/core.%e" >/proc/sys/kernel/core_pattern && 3855716fd348SMartin Matuska echo 0 >/proc/sys/kernel/core_uses_pid 3856716fd348SMartin Matuska ;; 3857716fd348SMartin Matuska FreeBSD) 3858716fd348SMartin Matuska sysctl -n kern.corefile 3859716fd348SMartin Matuska sysctl kern.corefile="$1/core.%N" >/dev/null 3860716fd348SMartin Matuska ;; 3861716fd348SMartin Matuska *) 3862716fd348SMartin Matuska # Nothing to output – set only for this shell 3863716fd348SMartin Matuska coreadm -p "$1/core.%f" 3864716fd348SMartin Matuska ;; 3865716fd348SMartin Matuska esac 3866716fd348SMartin Matuska} 3867716fd348SMartin Matuska 3868716fd348SMartin Matuska# 3869716fd348SMartin Matuska# Put coredumps back into the default location 3870716fd348SMartin Matuska# 3871716fd348SMartin Matuskafunction pop_coredump_pattern 3872716fd348SMartin Matuska{ 3873716fd348SMartin Matuska [ -s "$1" ] || return 0 3874716fd348SMartin Matuska case "$UNAME" in 3875716fd348SMartin Matuska Linux) 3876716fd348SMartin Matuska typeset pat pid 3877716fd348SMartin Matuska { read -r pat; read -r pid; } < "$1" 3878716fd348SMartin Matuska echo "$pat" >/proc/sys/kernel/core_pattern && 3879716fd348SMartin Matuska echo "$pid" >/proc/sys/kernel/core_uses_pid 3880716fd348SMartin Matuska ;; 3881716fd348SMartin Matuska FreeBSD) 3882716fd348SMartin Matuska sysctl kern.corefile="$(<"$1")" >/dev/null 3883716fd348SMartin Matuska ;; 3884716fd348SMartin Matuska esac 3885c03c5b1cSMartin Matuska} 3886*c6767dc1SMartin Matuska 3887*c6767dc1SMartin Matuska. ${STF_SUITE}/include/kstat.shlib 3888