1#!/usr/bin/env bash 2# SPDX-License-Identifier: CDDL-1.0 3# shellcheck disable=SC2154 4# shellcheck disable=SC2292 5# 6# CDDL HEADER START 7# 8# The contents of this file are subject to the terms of the 9# Common Development and Distribution License, Version 1.0 only 10# (the "License"). You may not use this file except in compliance 11# with the License. 12# 13# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 14# or https://opensource.org/licenses/CDDL-1.0. 15# See the License for the specific language governing permissions 16# and limitations under the License. 17# 18# When distributing Covered Code, include this CDDL HEADER in each 19# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 20# If applicable, add the following below this CDDL HEADER, with the 21# fields enclosed by brackets "[]" replaced with your own identifying 22# information: Portions Copyright [yyyy] [name of copyright owner] 23# 24# CDDL HEADER END 25# 26 27# 28# Copyright 2020 OmniOS Community Edition (OmniOSce) Association. 29# 30 31SCRIPT_COMMON=${SCRIPT_COMMON:-${0%/*}/common.sh} 32. "${SCRIPT_COMMON}" || exit 33 34PROG=zfs-tests.sh 35VERBOSE="no" 36QUIET="" 37DEBUG="" 38CLEANUP="yes" 39CLEANUPALL="no" 40KMSG="" 41TIMEOUT_DEBUG="" 42LOOPBACK="yes" 43STACK_TRACER="no" 44FILESIZE="4G" 45DEFAULT_RUNFILES="common.run,$(uname | tr '[:upper:]' '[:lower:]').run" 46RUNFILES=${RUNFILES:-$DEFAULT_RUNFILES} 47FILEDIR=${FILEDIR:-/var/tmp} 48DISKS=${DISKS:-""} 49SINGLETEST="" 50SINGLETESTUSER="root" 51TAGS="" 52ITERATIONS=1 53ZFS_DBGMSG="$STF_SUITE/callbacks/zfs_dbgmsg.ksh" 54ZFS_DMESG="$STF_SUITE/callbacks/zfs_dmesg.ksh" 55UNAME=$(uname) 56RERUN="" 57KMEMLEAK="" 58 59# Override some defaults if on FreeBSD 60if [ "$UNAME" = "FreeBSD" ] ; then 61 TESTFAIL_CALLBACKS=${TESTFAIL_CALLBACKS:-"$ZFS_DMESG"} 62 LOSETUP=/sbin/mdconfig 63 DMSETUP=/sbin/gpart 64else 65 ZFS_MMP="$STF_SUITE/callbacks/zfs_mmp.ksh" 66 TESTFAIL_CALLBACKS=${TESTFAIL_CALLBACKS:-"$ZFS_DBGMSG:$ZFS_DMESG:$ZFS_MMP"} 67 LOSETUP=${LOSETUP:-/sbin/losetup} 68 DMSETUP=${DMSETUP:-/sbin/dmsetup} 69fi 70 71# 72# Log an informational message when additional verbosity is enabled. 73# 74msg() { 75 if [ "$VERBOSE" = "yes" ]; then 76 echo "$@" 77 fi 78} 79 80# 81# Log a failure message, cleanup, and return an error. 82# 83fail() { 84 echo "$PROG: $1" >&2 85 cleanup 86 exit 1 87} 88 89cleanup_freebsd_loopback() { 90 for TEST_LOOPBACK in ${LOOPBACKS}; do 91 if [ -c "/dev/${TEST_LOOPBACK}" ]; then 92 sudo "${LOSETUP}" -d -u "${TEST_LOOPBACK}" || 93 echo "Failed to destroy: ${TEST_LOOPBACK}" 94 fi 95 done 96} 97 98cleanup_linux_loopback() { 99 for TEST_LOOPBACK in ${LOOPBACKS}; do 100 LOOP_DEV="${TEST_LOOPBACK##*/}" 101 DM_DEV=$(sudo "${DMSETUP}" ls 2>/dev/null | \ 102 awk -v l="${LOOP_DEV}" '$0 ~ l {print $1}') 103 104 if [ -n "$DM_DEV" ]; then 105 sudo "${DMSETUP}" remove "${DM_DEV}" || 106 echo "Failed to remove: ${DM_DEV}" 107 fi 108 109 if [ -n "${TEST_LOOPBACK}" ]; then 110 sudo "${LOSETUP}" -d "${TEST_LOOPBACK}" || 111 echo "Failed to remove: ${TEST_LOOPBACK}" 112 fi 113 done 114} 115 116# 117# Attempt to remove loopback devices and files which where created earlier 118# by this script to run the test framework. The '-k' option may be passed 119# to the script to suppress cleanup for debugging purposes. 120# 121cleanup() { 122 if [ "$CLEANUP" = "no" ]; then 123 return 0 124 fi 125 126 127 if [ "$LOOPBACK" = "yes" ]; then 128 if [ "$UNAME" = "FreeBSD" ] ; then 129 cleanup_freebsd_loopback 130 else 131 cleanup_linux_loopback 132 fi 133 fi 134 135 # shellcheck disable=SC2086 136 rm -f ${FILES} >/dev/null 2>&1 137 138 if [ "$STF_PATH_REMOVE" = "yes" ] && [ -d "$STF_PATH" ]; then 139 rm -Rf "$STF_PATH" 140 fi 141} 142trap cleanup EXIT 143 144# 145# Attempt to remove all testpools (testpool.XXX), unopened dm devices, 146# loopback devices, and files. This is a useful way to cleanup a previous 147# test run failure which has left the system in an unknown state. This can 148# be dangerous and should only be used in a dedicated test environment. 149# 150cleanup_all() { 151 TEST_POOLS=$(ASAN_OPTIONS=detect_leaks=false "$ZPOOL" list -Ho name | grep testpool) 152 if [ "$UNAME" = "FreeBSD" ] ; then 153 TEST_LOOPBACKS=$(sudo "${LOSETUP}" -l) 154 else 155 TEST_LOOPBACKS=$("${LOSETUP}" -a | awk -F: '/file-vdev/ {print $1}') 156 fi 157 TEST_FILES=$(ls "${FILEDIR}"/file-vdev* 2>/dev/null) 158 159 msg 160 msg "--- Cleanup ---" 161 # shellcheck disable=2116,2086 162 msg "Removing pool(s): $(echo ${TEST_POOLS})" 163 for TEST_POOL in $TEST_POOLS; do 164 sudo env ASAN_OPTIONS=detect_leaks=false "$ZPOOL" destroy "${TEST_POOL}" 165 done 166 167 if [ "$UNAME" != "FreeBSD" ] ; then 168 msg "Removing all dm(s): $(sudo "${DMSETUP}" ls | 169 grep loop | tr '\n' ' ')" 170 sudo "${DMSETUP}" remove_all 171 fi 172 173 # shellcheck disable=2116,2086 174 msg "Removing loopback(s): $(echo ${TEST_LOOPBACKS})" 175 for TEST_LOOPBACK in $TEST_LOOPBACKS; do 176 if [ "$UNAME" = "FreeBSD" ] ; then 177 sudo "${LOSETUP}" -d -u "${TEST_LOOPBACK}" 178 else 179 sudo "${LOSETUP}" -d "${TEST_LOOPBACK}" 180 fi 181 done 182 183 # shellcheck disable=2116,2086 184 msg "Removing files(s): $(echo ${TEST_FILES})" 185 # shellcheck disable=2086 186 sudo rm -f ${TEST_FILES} 187} 188 189# 190# Takes a name as the only arguments and looks for the following variations 191# on that name. If one is found it is returned. 192# 193# $RUNFILE_DIR/<name> 194# $RUNFILE_DIR/<name>.run 195# <name> 196# <name>.run 197# 198find_runfile() { 199 NAME=$1 200 201 if [ -f "$RUNFILE_DIR/$NAME" ]; then 202 echo "$RUNFILE_DIR/$NAME" 203 elif [ -f "$RUNFILE_DIR/$NAME.run" ]; then 204 echo "$RUNFILE_DIR/$NAME.run" 205 elif [ -f "$NAME" ]; then 206 echo "$NAME" 207 elif [ -f "$NAME.run" ]; then 208 echo "$NAME.run" 209 else 210 return 1 211 fi 212} 213 214# Given a TAGS with a format like "1/3" or "2/3" then divide up the test list 215# into portions and print that portion. So "1/3" for "the first third of the 216# test tags". 217# 218# 219split_tags() { 220 # Get numerator and denominator 221 NUM=$(echo "$TAGS" | cut -d/ -f1) 222 DEN=$(echo "$TAGS" | cut -d/ -f2) 223 # At the point this is called, RUNFILES will contain a comma separated 224 # list of full paths to the runfiles, like: 225 # 226 # "/home/hutter/qemu/tests/runfiles/common.run,/home/hutter/qemu/tests/runfiles/linux.run" 227 # 228 # So to get tags for our selected tests we do: 229 # 230 # 1. Remove unneeded chars: [],\ 231 # 2. Print out the last field of each tag line. This will be the tag 232 # for the test (like 'zpool_add'). 233 # 3. Remove duplicates between the runfiles. If the same tag is defined 234 # in multiple runfiles, then when you do '-T <tag>' ZTS is smart 235 # enough to know to run the tag in each runfile. So '-T zpool_add' 236 # will run the zpool_add from common.run and linux.run. 237 # 4. Ignore the 'functional' tag since we only want individual tests 238 # 5. Print out the tests in our faction of all tests. This uses modulus 239 # so "1/3" will run tests 1,3,6,9 etc. That way the tests are 240 # interleaved so, say, "3/4" isn't running all the zpool_* tests that 241 # appear alphabetically at the end. 242 # 6. Remove trailing comma from list 243 # 244 # TAGS will then look like: 245 # 246 # "append,atime,bootfs,cachefile,checksum,cp_files,deadman,dos_attributes, ..." 247 248 # Change the comma to a space for easy processing 249 _RUNFILES=${RUNFILES//","/" "} 250 # shellcheck disable=SC2002,SC2086 251 cat $_RUNFILES | tr -d "[],\'" | awk '/tags = /{print $NF}' | sort | \ 252 uniq | grep -v functional | \ 253 awk -v num="$NUM" -v den="$DEN" '{ if(NR % den == (num - 1)) {printf "%s,",$0}}' | \ 254 sed -E 's/,$//' 255} 256 257# 258# Symlink file if it appears under any of the given paths. 259# 260create_links() { 261 dir_list="$1" 262 file_list="$2" 263 264 [ -n "$STF_PATH" ] || fail "STF_PATH wasn't correctly set" 265 266 for i in $file_list; do 267 for j in $dir_list; do 268 [ ! -e "$STF_PATH/$i" ] || continue 269 270 if [ ! -d "$j/$i" ] && [ -e "$j/$i" ]; then 271 ln -sf "$j/$i" "$STF_PATH/$i" || \ 272 fail "Couldn't link $i" 273 break 274 fi 275 done 276 277 [ ! -e "$STF_PATH/$i" ] && \ 278 STF_MISSING_BIN="$STF_MISSING_BIN $i" 279 done 280 STF_MISSING_BIN=${STF_MISSING_BIN# } 281} 282 283# 284# Constrain the path to limit the available binaries to a known set. 285# When running in-tree a top level ./bin/ directory is created for 286# convenience, otherwise a temporary directory is used. 287# 288constrain_path() { 289 . "$STF_SUITE/include/commands.cfg" 290 291 # On FreeBSD, base system zfs utils are in /sbin and OpenZFS utils 292 # install to /usr/local/sbin. To avoid testing the wrong utils we 293 # need /usr/local to come before / in the path search order. 294 SYSTEM_DIRS="/usr/local/bin /usr/local/sbin" 295 SYSTEM_DIRS="$SYSTEM_DIRS /usr/bin /usr/sbin /bin /sbin $LIBEXEC_DIR" 296 297 if [ "$INTREE" = "yes" ]; then 298 # Constrained path set to $(top_builddir)/tests/zfs-tests/bin 299 STF_PATH="$BIN_DIR" 300 STF_PATH_REMOVE="no" 301 STF_MISSING_BIN="" 302 if [ ! -d "$STF_PATH" ]; then 303 mkdir "$STF_PATH" 304 chmod 755 "$STF_PATH" || fail "Couldn't chmod $STF_PATH" 305 fi 306 307 # Special case links for standard zfs utilities 308 create_links "$CMD_DIR" "$ZFS_FILES" 309 310 # Special case links for zfs test suite utilities 311 create_links "$CMD_DIR/tests/zfs-tests/cmd" "$ZFSTEST_FILES" 312 else 313 # Constrained path set to $FILEDIR/constrained_path.* 314 SYSTEMDIR=${SYSTEMDIR:-$FILEDIR/constrained_path.XXXXXX} 315 STF_PATH=$(mktemp -d "$SYSTEMDIR") 316 STF_PATH_REMOVE="yes" 317 STF_MISSING_BIN="" 318 319 chmod 755 "$STF_PATH" || fail "Couldn't chmod $STF_PATH" 320 321 # Special case links for standard zfs utilities 322 create_links "$SYSTEM_DIRS" "$ZFS_FILES" 323 324 # Special case links for zfs test suite utilities 325 create_links "$STF_SUITE/bin" "$ZFSTEST_FILES" 326 fi 327 328 # Standard system utilities 329 SYSTEM_FILES="$SYSTEM_FILES_COMMON" 330 if [ "$UNAME" = "FreeBSD" ] ; then 331 SYSTEM_FILES="$SYSTEM_FILES $SYSTEM_FILES_FREEBSD" 332 else 333 SYSTEM_FILES="$SYSTEM_FILES $SYSTEM_FILES_LINUX" 334 fi 335 create_links "$SYSTEM_DIRS" "$SYSTEM_FILES" 336 337 # Exceptions 338 if [ "$UNAME" = "Linux" ] ; then 339 ln -fs /sbin/fsck.ext4 "$STF_PATH/fsck" 340 ln -fs /sbin/mkfs.ext4 "$STF_PATH/newfs" 341 ln -fs "$STF_PATH/gzip" "$STF_PATH/compress" 342 ln -fs "$STF_PATH/gunzip" "$STF_PATH/uncompress" 343 elif [ "$UNAME" = "FreeBSD" ] ; then 344 ln -fs /usr/local/bin/ksh93 "$STF_PATH/ksh" 345 fi 346} 347 348# 349# Output a useful usage message. 350# 351usage() { 352cat << EOF 353USAGE: 354$0 [-hvqxkfS] [-s SIZE] [-r RUNFILES] [-t PATH] [-u USER] 355 356DESCRIPTION: 357 ZFS Test Suite launch script 358 359OPTIONS: 360 -h Show this message 361 -v Verbose zfs-tests.sh output 362 -q Quiet test-runner output 363 -D Debug; show all test output immediately (noisy) 364 -x Remove all testpools, dm, lo, and files (unsafe) 365 -k Disable cleanup after test failure 366 -K Log test names to /dev/kmsg 367 -f Use files only, disables block device tests 368 -O Dump debugging info to /dev/kmsg on test timeout 369 -S Enable stack tracer (negative performance impact) 370 -c Only create and populate constrained path 371 -R Automatically rerun failing tests 372 -m Enable kmemleak reporting (Linux only) 373 -n NFSFILE Use the nfsfile to determine the NFS configuration 374 -I NUM Number of iterations 375 -d DIR Use world-writable DIR for files and loopback devices 376 -s SIZE Use vdevs of SIZE (default: 4G) 377 -r RUNFILES Run tests in RUNFILES (default: ${DEFAULT_RUNFILES}) 378 -t PATH|NAME Run single test at PATH relative to test suite, 379 or search for test by NAME 380 -T TAGS Comma separated list of tags (default: 'functional') 381 Alternately, specify a fraction like "1/3" or "2/3" to 382 run the first third of tests or 2nd third of the tests. This 383 is useful for splitting up the test amongst different 384 runners. 385 -u USER Run single test as USER (default: root) 386 387EXAMPLES: 388# Run the default ${DEFAULT_RUNFILES//\.run/} suite of tests and output the configuration used. 389$0 -v 390 391# Run a smaller suite of tests designed to run more quickly. 392$0 -r linux-fast 393 394# Run a single test 395$0 -t tests/functional/cli_root/zfs_bookmark/zfs_bookmark_cliargs.ksh 396 397# Run a single test by name 398$0 -t zfs_bookmark_cliargs 399 400# Cleanup a previous run of the test suite prior to testing, run the 401# default ${DEFAULT_RUNFILES//\.run//} suite of tests and perform no cleanup on exit. 402$0 -x 403 404EOF 405} 406 407while getopts 'hvqxkKfScRmOn:d:Ds:r:?t:T:u:I:' OPTION; do 408 case $OPTION in 409 h) 410 usage 411 exit 1 412 ;; 413 v) 414 VERBOSE="yes" 415 ;; 416 q) 417 QUIET="yes" 418 ;; 419 x) 420 CLEANUPALL="yes" 421 ;; 422 k) 423 CLEANUP="no" 424 ;; 425 K) 426 KMSG="yes" 427 ;; 428 f) 429 LOOPBACK="no" 430 ;; 431 S) 432 STACK_TRACER="yes" 433 ;; 434 c) 435 constrain_path 436 exit 437 ;; 438 R) 439 RERUN="yes" 440 ;; 441 m) 442 KMEMLEAK="yes" 443 ;; 444 n) 445 nfsfile=$OPTARG 446 [ -f "$nfsfile" ] || fail "Cannot read file: $nfsfile" 447 export NFS=1 448 . "$nfsfile" 449 ;; 450 O) 451 TIMEOUT_DEBUG="yes" 452 ;; 453 d) 454 FILEDIR="$OPTARG" 455 ;; 456 D) 457 DEBUG="yes" 458 ;; 459 I) 460 ITERATIONS="$OPTARG" 461 if [ "$ITERATIONS" -le 0 ]; then 462 fail "Iterations must be greater than 0." 463 fi 464 ;; 465 s) 466 FILESIZE="$OPTARG" 467 ;; 468 r) 469 RUNFILES="$OPTARG" 470 ;; 471 t) 472 if [ -n "$SINGLETEST" ]; then 473 fail "-t can only be provided once." 474 fi 475 SINGLETEST="$OPTARG" 476 ;; 477 T) 478 TAGS="$OPTARG" 479 ;; 480 u) 481 SINGLETESTUSER="$OPTARG" 482 ;; 483 ?) 484 usage 485 exit 486 ;; 487 *) 488 ;; 489 esac 490done 491 492shift $((OPTIND-1)) 493 494FILES=${FILES:-"$FILEDIR/file-vdev0 $FILEDIR/file-vdev1 $FILEDIR/file-vdev2"} 495LOOPBACKS=${LOOPBACKS:-""} 496 497if [ -n "$SINGLETEST" ]; then 498 if [ -n "$TAGS" ]; then 499 fail "-t and -T are mutually exclusive." 500 fi 501 RUNFILE_DIR="$FILEDIR" 502 RUNFILES="zfs-tests.$$.run" 503 [ -n "$QUIET" ] && SINGLEQUIET="True" || SINGLEQUIET="False" 504 505 cat >"${RUNFILE_DIR}/${RUNFILES}" << EOF 506[DEFAULT] 507pre = 508quiet = $SINGLEQUIET 509pre_user = root 510user = $SINGLETESTUSER 511timeout = 600 512post_user = root 513post = 514EOF 515 if [ "$SINGLETEST" = "${SINGLETEST%/*}" ] ; then 516 NEWSINGLETEST=$(find "$STF_SUITE" -name "$SINGLETEST*" -print -quit) 517 if [ -z "$NEWSINGLETEST" ] ; then 518 fail "couldn't find test matching '$SINGLETEST'" 519 fi 520 SINGLETEST=$NEWSINGLETEST 521 fi 522 523 SINGLETESTDIR="${SINGLETEST%/*}" 524 SETUPDIR="$SINGLETESTDIR" 525 [ "${SETUPDIR#/}" = "$SETUPDIR" ] && SETUPDIR="$STF_SUITE/$SINGLETESTDIR" 526 [ -x "$SETUPDIR/setup.ksh" ] && SETUPSCRIPT="setup" || SETUPSCRIPT= 527 [ -x "$SETUPDIR/cleanup.ksh" ] && CLEANUPSCRIPT="cleanup" || CLEANUPSCRIPT= 528 529 SINGLETESTFILE="${SINGLETEST##*/}" 530 cat >>"${RUNFILE_DIR}/${RUNFILES}" << EOF 531 532[$SINGLETESTDIR] 533tests = ['$SINGLETESTFILE'] 534pre = $SETUPSCRIPT 535post = $CLEANUPSCRIPT 536tags = ['functional'] 537EOF 538fi 539 540# 541# Use default tag if none was specified 542# 543TAGS=${TAGS:='functional'} 544 545 546 547# 548# Attempt to locate the runfiles describing the test workload. 549# 550R="" 551IFS=, 552for RUNFILE in $RUNFILES; do 553 if [ -n "$RUNFILE" ]; then 554 SAVED_RUNFILE="$RUNFILE" 555 RUNFILE=$(find_runfile "$RUNFILE") || 556 fail "Cannot find runfile: $SAVED_RUNFILE" 557 R="$R,$RUNFILE" 558 fi 559 560 if [ ! -r "$RUNFILE" ]; then 561 fail "Cannot read runfile: $RUNFILE" 562 fi 563done 564unset IFS 565RUNFILES=${R#,} 566 567# The tag can be a fraction to indicate which portion of ZTS to run, Like 568# 569# "1/3": Run first one third of all tests in runfiles 570# "2/3": Run second one third of all test in runfiles 571# "6/10": Run 6th tenth of all tests in runfiles 572# 573# This is useful for splitting up the test across multiple runners. 574# 575# After this code block, TAGS will be transformed from something like 576# "1/3" to a comma separate taglist, like: 577# 578# "append,atime,bootfs,cachefile,checksum,cp_files,deadman,dos_attributes, ..." 579# 580if echo "$TAGS" | grep -Eq '^[0-9]+/[0-9]+$' ; then 581 TAGS=$(split_tags) 582fi 583 584# 585# This script should not be run as root. Instead the test user, which may 586# be a normal user account, needs to be configured such that it can 587# run commands via sudo passwordlessly. 588# 589if [ "$(id -u)" = "0" ]; then 590 fail "This script must not be run as root." 591fi 592 593if [ "$(sudo id -un)" != "root" ]; then 594 fail "Passwordless sudo access required." 595fi 596 597# 598# Constrain the available binaries to a known set. 599# 600constrain_path 601 602# 603# Check if ksh exists 604# 605if [ "$UNAME" = "FreeBSD" ]; then 606 sudo ln -fs /usr/local/bin/ksh93 /bin/ksh 607fi 608[ -e "$STF_PATH/ksh" ] || fail "This test suite requires ksh." 609[ -e "$STF_SUITE/include/default.cfg" ] || fail \ 610 "Missing $STF_SUITE/include/default.cfg file." 611 612# 613# Verify the ZFS module stack is loaded. 614# 615if [ "$STACK_TRACER" = "yes" ]; then 616 sudo "${ZFS_SH}" -S >/dev/null 2>&1 617else 618 sudo "${ZFS_SH}" >/dev/null 2>&1 619fi 620 621# 622# Attempt to cleanup all previous state for a new test run. 623# 624if [ "$CLEANUPALL" = "yes" ]; then 625 cleanup_all 626fi 627 628# 629# By default preserve any existing pools 630# 631if [ -z "${KEEP}" ]; then 632 KEEP="$(ASAN_OPTIONS=detect_leaks=false "$ZPOOL" list -Ho name | tr -s '[:space:]' ' ')" 633 if [ -z "${KEEP}" ]; then 634 KEEP="rpool" 635 fi 636else 637 KEEP="$(echo "$KEEP" | tr -s '[:space:]' ' ')" 638fi 639 640# 641# NOTE: The following environment variables are undocumented 642# and should be used for testing purposes only: 643# 644# __ZFS_POOL_EXCLUDE - don't iterate over the pools it lists 645# __ZFS_POOL_RESTRICT - iterate only over the pools it lists 646# 647# See libzfs/libzfs_config.c for more information. 648# 649__ZFS_POOL_EXCLUDE="$KEEP" 650 651. "$STF_SUITE/include/default.cfg" 652 653# 654# No DISKS have been provided so a basic file or loopback based devices 655# must be created for the test suite to use. 656# 657if [ -z "${DISKS}" ]; then 658 # 659 # If this is a performance run, prevent accidental use of 660 # loopback devices. 661 # 662 [ "$TAGS" = "perf" ] && fail "Running perf tests without disks." 663 664 # 665 # Create sparse files for the test suite. These may be used 666 # directory or have loopback devices layered on them. 667 # 668 for TEST_FILE in ${FILES}; do 669 [ -f "$TEST_FILE" ] && fail "Failed file exists: ${TEST_FILE}" 670 truncate -s "${FILESIZE}" "${TEST_FILE}" || 671 fail "Failed creating: ${TEST_FILE} ($?)" 672 done 673 674 # 675 # If requested setup loopback devices backed by the sparse files. 676 # 677 if [ "$LOOPBACK" = "yes" ]; then 678 test -x "$LOSETUP" || fail "$LOSETUP utility must be installed" 679 680 for TEST_FILE in ${FILES}; do 681 if [ "$UNAME" = "FreeBSD" ] ; then 682 MDDEVICE=$(sudo "${LOSETUP}" -a -t vnode -f "${TEST_FILE}") 683 if [ -z "$MDDEVICE" ] ; then 684 fail "Failed: ${TEST_FILE} -> loopback" 685 fi 686 DISKS="$DISKS $MDDEVICE" 687 LOOPBACKS="$LOOPBACKS $MDDEVICE" 688 else 689 TEST_LOOPBACK=$(sudo "${LOSETUP}" --show -f "${TEST_FILE}") || 690 fail "Failed: ${TEST_FILE} -> ${TEST_LOOPBACK}" 691 BASELOOPBACK="${TEST_LOOPBACK##*/}" 692 DISKS="$DISKS $BASELOOPBACK" 693 LOOPBACKS="$LOOPBACKS $TEST_LOOPBACK" 694 fi 695 done 696 DISKS=${DISKS# } 697 LOOPBACKS=${LOOPBACKS# } 698 else 699 DISKS="$FILES" 700 fi 701fi 702 703# 704# It may be desirable to test with fewer disks than the default when running 705# the performance tests, but the functional tests require at least three. 706# 707NUM_DISKS=$(echo "${DISKS}" | awk '{print NF}') 708if [ "$TAGS" != "perf" ]; then 709 [ "$NUM_DISKS" -lt 3 ] && fail "Not enough disks ($NUM_DISKS/3 minimum)" 710fi 711 712# 713# Disable SELinux until the ZFS Test Suite has been updated accordingly. 714# 715if command -v setenforce >/dev/null; then 716 sudo setenforce permissive >/dev/null 2>&1 717fi 718 719# 720# Enable internal ZFS debug log and clear it. 721# 722if [ -e /sys/module/zfs/parameters/zfs_dbgmsg_enable ]; then 723 sudo sh -c "echo 1 >/sys/module/zfs/parameters/zfs_dbgmsg_enable" 724 sudo sh -c "echo 0 >/proc/spl/kstat/zfs/dbgmsg" 725fi 726 727# 728# Set TMPDIR. Some tests run mktemp, and we want those files contained to 729# the work dir the same as any other. 730# 731export TMPDIR="$FILEDIR" 732 733msg 734msg "--- Configuration ---" 735msg "Runfiles: $RUNFILES" 736msg "STF_TOOLS: $STF_TOOLS" 737msg "STF_SUITE: $STF_SUITE" 738msg "STF_PATH: $STF_PATH" 739msg "FILEDIR: $FILEDIR" 740msg "TMPDIR: $TMPDIR" 741msg "FILES: $FILES" 742msg "LOOPBACKS: $LOOPBACKS" 743msg "DISKS: $DISKS" 744msg "NUM_DISKS: $NUM_DISKS" 745msg "FILESIZE: $FILESIZE" 746msg "ITERATIONS: $ITERATIONS" 747msg "TAGS: $TAGS" 748msg "STACK_TRACER: $STACK_TRACER" 749msg "Keep pool(s): $KEEP" 750msg "Missing util(s): $STF_MISSING_BIN" 751msg "" 752 753export STF_TOOLS 754export STF_SUITE 755export STF_PATH 756export DISKS 757export FILEDIR 758export KEEP 759export __ZFS_POOL_EXCLUDE 760export TESTFAIL_CALLBACKS 761 762mktemp_file() { 763 if [ "$UNAME" = "FreeBSD" ]; then 764 mktemp -u "${FILEDIR}/$1.XXXXXX" 765 else 766 mktemp -ut "$1.XXXXXX" -p "$FILEDIR" 767 fi 768} 769mkdir -p "$FILEDIR" || : 770RESULTS_FILE=$(mktemp_file zts-results) 771REPORT_FILE=$(mktemp_file zts-report) 772 773# 774# Run all the tests as specified. 775# 776msg "${TEST_RUNNER}" \ 777 "${QUIET:+-q}" \ 778 "${DEBUG:+-D}" \ 779 "${KMEMLEAK:+-m}" \ 780 "${KMSG:+-K}" \ 781 "${TIMEOUT_DEBUG:+-O}" \ 782 "-c \"${RUNFILES}\"" \ 783 "-T \"${TAGS}\"" \ 784 "-i \"${STF_SUITE}\"" \ 785 "-I \"${ITERATIONS}\"" 786{ PATH=$STF_PATH \ 787 ${TEST_RUNNER} \ 788 ${QUIET:+-q} \ 789 ${DEBUG:+-D} \ 790 ${KMEMLEAK:+-m} \ 791 ${KMSG:+-K} \ 792 ${TIMEOUT_DEBUG:+-O} \ 793 -c "${RUNFILES}" \ 794 -T "${TAGS}" \ 795 -i "${STF_SUITE}" \ 796 -I "${ITERATIONS}" \ 797 2>&1; echo $? >"$REPORT_FILE"; } | tee "$RESULTS_FILE" 798read -r RUNRESULT <"$REPORT_FILE" 799 800# 801# Analyze the results. 802# 803${ZTS_REPORT} ${RERUN:+--no-maybes} "$RESULTS_FILE" >"$REPORT_FILE" 804RESULT=$? 805 806if [ "$RESULT" -eq "2" ] && [ -n "$RERUN" ]; then 807 MAYBES="$($ZTS_REPORT --list-maybes)" 808 TEMP_RESULTS_FILE=$(mktemp_file zts-results-tmp) 809 TEST_LIST=$(mktemp_file test-list) 810 grep "^Test:.*\[FAIL\]" "$RESULTS_FILE" >"$TEMP_RESULTS_FILE" 811 for test_name in $MAYBES; do 812 grep "$test_name " "$TEMP_RESULTS_FILE" >>"$TEST_LIST" 813 done 814 { PATH=$STF_PATH \ 815 ${TEST_RUNNER} \ 816 ${QUIET:+-q} \ 817 ${DEBUG:+-D} \ 818 ${KMEMLEAK:+-m} \ 819 -c "${RUNFILES}" \ 820 -T "${TAGS}" \ 821 -i "${STF_SUITE}" \ 822 -I "${ITERATIONS}" \ 823 -l "${TEST_LIST}" \ 824 2>&1; echo $? >"$REPORT_FILE"; } | tee "$RESULTS_FILE" 825 read -r RUNRESULT <"$REPORT_FILE" 826 # 827 # Analyze the results. 828 # 829 ${ZTS_REPORT} --no-maybes "$RESULTS_FILE" >"$REPORT_FILE" 830 RESULT=$? 831fi 832 833 834cat "$REPORT_FILE" 835 836RESULTS_DIR=$(awk '/^Log directory/ { print $3 }' "$RESULTS_FILE") 837if [ -d "$RESULTS_DIR" ]; then 838 cat "$RESULTS_FILE" "$REPORT_FILE" >"$RESULTS_DIR/results" 839fi 840 841rm -f "$RESULTS_FILE" "$REPORT_FILE" "$TEST_LIST" "$TEMP_RESULTS_FILE" 842 843if [ -n "$SINGLETEST" ]; then 844 rm -f "$RUNFILES" >/dev/null 2>&1 845fi 846 847[ "$RUNRESULT" -gt 3 ] && exit "$RUNRESULT" || exit "$RESULT" 848