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 SYSTEM_FILES="$SYSTEM_FILES_COMMON" 298 ZFSTEST_FILES="$ZFSTEST_FILES_COMMON" 299 if [ "$UNAME" = "FreeBSD" ] ; then 300 SYSTEM_FILES="$SYSTEM_FILES $SYSTEM_FILES_FREEBSD" 301 ZFSTEST_FILES="$ZFSTEST_FILES $ZFSTEST_FILES_FREEBSD" 302 else 303 SYSTEM_FILES="$SYSTEM_FILES $SYSTEM_FILES_LINUX" 304 ZFSTEST_FILES="$ZFSTEST_FILES $ZFSTEST_FILES_LINUX" 305 fi 306 307 if [ "$INTREE" = "yes" ]; then 308 # Constrained path set to $(top_builddir)/tests/zfs-tests/bin 309 STF_PATH="$BIN_DIR" 310 STF_PATH_REMOVE="no" 311 STF_MISSING_BIN="" 312 if [ ! -d "$STF_PATH" ]; then 313 mkdir "$STF_PATH" 314 chmod 755 "$STF_PATH" || fail "Couldn't chmod $STF_PATH" 315 fi 316 317 # Special case links for standard zfs utilities 318 create_links "$CMD_DIR" "$ZFS_FILES" 319 320 # Special case links for zfs test suite utilities 321 create_links "$CMD_DIR/tests/zfs-tests/cmd" "$ZFSTEST_FILES" 322 else 323 # Constrained path set to $FILEDIR/constrained_path.* 324 SYSTEMDIR=${SYSTEMDIR:-$FILEDIR/constrained_path.XXXXXX} 325 STF_PATH=$(mktemp -d "$SYSTEMDIR") 326 STF_PATH_REMOVE="yes" 327 STF_MISSING_BIN="" 328 329 chmod 755 "$STF_PATH" || fail "Couldn't chmod $STF_PATH" 330 331 # Special case links for standard zfs utilities 332 create_links "$SYSTEM_DIRS" "$ZFS_FILES" 333 334 # Special case links for zfs test suite utilities 335 create_links "$STF_SUITE/bin" "$ZFSTEST_FILES" 336 fi 337 338 # Standard system utilities 339 create_links "$SYSTEM_DIRS" "$SYSTEM_FILES" 340 341 # Exceptions 342 if [ "$UNAME" = "Linux" ] ; then 343 ln -fs /sbin/fsck.ext4 "$STF_PATH/fsck" 344 ln -fs /sbin/mkfs.ext4 "$STF_PATH/newfs" 345 ln -fs "$STF_PATH/gzip" "$STF_PATH/compress" 346 ln -fs "$STF_PATH/gunzip" "$STF_PATH/uncompress" 347 elif [ "$UNAME" = "FreeBSD" ] ; then 348 ln -fs /usr/local/bin/ksh93 "$STF_PATH/ksh" 349 fi 350} 351 352# 353# Output a useful usage message. 354# 355usage() { 356cat << EOF 357USAGE: 358$0 [-hvqxkfS] [-s SIZE] [-r RUNFILES] [-t PATH] [-u USER] 359 360DESCRIPTION: 361 ZFS Test Suite launch script 362 363OPTIONS: 364 -h Show this message 365 -v Verbose zfs-tests.sh output 366 -q Quiet test-runner output 367 -D Debug; show all test output immediately (noisy) 368 -x Remove all testpools, dm, lo, and files (unsafe) 369 -k Disable cleanup after test failure 370 -K Log test names to /dev/kmsg 371 -f Use files only, disables block device tests 372 -O Dump debugging info to /dev/kmsg on test timeout 373 -S Enable stack tracer (negative performance impact) 374 -c Only create and populate constrained path 375 -R Automatically rerun failing tests 376 -m Enable kmemleak reporting (Linux only) 377 -n NFSFILE Use the nfsfile to determine the NFS configuration 378 -I NUM Number of iterations 379 -d DIR Use world-writable DIR for files and loopback devices 380 -s SIZE Use vdevs of SIZE (default: 4G) 381 -r RUNFILES Run tests in RUNFILES (default: ${DEFAULT_RUNFILES}) 382 -t PATH|NAME Run single test at PATH relative to test suite, 383 or search for test by NAME 384 -T TAGS Comma separated list of tags (default: 'functional') 385 Alternately, specify a fraction like "1/3" or "2/3" to 386 run the first third of tests or 2nd third of the tests. This 387 is useful for splitting up the test amongst different 388 runners. 389 -u USER Run single test as USER (default: root) 390 391EXAMPLES: 392# Run the default ${DEFAULT_RUNFILES//\.run/} suite of tests and output the configuration used. 393$0 -v 394 395# Run a smaller suite of tests designed to run more quickly. 396$0 -r linux-fast 397 398# Run a single test 399$0 -t tests/functional/cli_root/zfs_bookmark/zfs_bookmark_cliargs.ksh 400 401# Run a single test by name 402$0 -t zfs_bookmark_cliargs 403 404# Cleanup a previous run of the test suite prior to testing, run the 405# default ${DEFAULT_RUNFILES//\.run//} suite of tests and perform no cleanup on exit. 406$0 -x 407 408EOF 409} 410 411while getopts 'hvqxkKfScRmOn:d:Ds:r:?t:T:u:I:' OPTION; do 412 case $OPTION in 413 h) 414 usage 415 exit 1 416 ;; 417 v) 418 VERBOSE="yes" 419 ;; 420 q) 421 QUIET="yes" 422 ;; 423 x) 424 CLEANUPALL="yes" 425 ;; 426 k) 427 CLEANUP="no" 428 ;; 429 K) 430 KMSG="yes" 431 ;; 432 f) 433 LOOPBACK="no" 434 ;; 435 S) 436 STACK_TRACER="yes" 437 ;; 438 c) 439 constrain_path 440 exit 441 ;; 442 R) 443 RERUN="yes" 444 ;; 445 m) 446 KMEMLEAK="yes" 447 ;; 448 n) 449 nfsfile=$OPTARG 450 [ -f "$nfsfile" ] || fail "Cannot read file: $nfsfile" 451 export NFS=1 452 . "$nfsfile" 453 ;; 454 O) 455 TIMEOUT_DEBUG="yes" 456 ;; 457 d) 458 FILEDIR="$OPTARG" 459 ;; 460 D) 461 DEBUG="yes" 462 ;; 463 I) 464 ITERATIONS="$OPTARG" 465 if [ "$ITERATIONS" -le 0 ]; then 466 fail "Iterations must be greater than 0." 467 fi 468 ;; 469 s) 470 FILESIZE="$OPTARG" 471 ;; 472 r) 473 RUNFILES="$OPTARG" 474 ;; 475 t) 476 if [ -n "$SINGLETEST" ]; then 477 fail "-t can only be provided once." 478 fi 479 SINGLETEST="$OPTARG" 480 ;; 481 T) 482 TAGS="$OPTARG" 483 ;; 484 u) 485 SINGLETESTUSER="$OPTARG" 486 ;; 487 ?) 488 usage 489 exit 490 ;; 491 *) 492 ;; 493 esac 494done 495 496shift $((OPTIND-1)) 497 498FILES=${FILES:-"$FILEDIR/file-vdev0 $FILEDIR/file-vdev1 $FILEDIR/file-vdev2"} 499LOOPBACKS=${LOOPBACKS:-""} 500 501if [ -n "$SINGLETEST" ]; then 502 if [ -n "$TAGS" ]; then 503 fail "-t and -T are mutually exclusive." 504 fi 505 RUNFILE_DIR="$FILEDIR" 506 RUNFILES="zfs-tests.$$.run" 507 [ -n "$QUIET" ] && SINGLEQUIET="True" || SINGLEQUIET="False" 508 509 cat >"${RUNFILE_DIR}/${RUNFILES}" << EOF 510[DEFAULT] 511pre = 512quiet = $SINGLEQUIET 513pre_user = root 514user = $SINGLETESTUSER 515timeout = 600 516post_user = root 517post = 518EOF 519 if [ "$SINGLETEST" = "${SINGLETEST%/*}" ] ; then 520 NEWSINGLETEST=$(find "$STF_SUITE" -name "$SINGLETEST*" -print -quit) 521 if [ -z "$NEWSINGLETEST" ] ; then 522 fail "couldn't find test matching '$SINGLETEST'" 523 fi 524 SINGLETEST=$NEWSINGLETEST 525 fi 526 527 SINGLETESTDIR="${SINGLETEST%/*}" 528 SETUPDIR="$SINGLETESTDIR" 529 [ "${SETUPDIR#/}" = "$SETUPDIR" ] && SETUPDIR="$STF_SUITE/$SINGLETESTDIR" 530 [ -x "$SETUPDIR/setup.ksh" ] && SETUPSCRIPT="setup" || SETUPSCRIPT= 531 [ -x "$SETUPDIR/cleanup.ksh" ] && CLEANUPSCRIPT="cleanup" || CLEANUPSCRIPT= 532 533 SINGLETESTFILE="${SINGLETEST##*/}" 534 cat >>"${RUNFILE_DIR}/${RUNFILES}" << EOF 535 536[$SINGLETESTDIR] 537tests = ['$SINGLETESTFILE'] 538pre = $SETUPSCRIPT 539post = $CLEANUPSCRIPT 540tags = ['functional'] 541EOF 542fi 543 544# 545# Use default tag if none was specified 546# 547TAGS=${TAGS:='functional'} 548 549 550 551# 552# Attempt to locate the runfiles describing the test workload. 553# 554R="" 555IFS=, 556for RUNFILE in $RUNFILES; do 557 if [ -n "$RUNFILE" ]; then 558 SAVED_RUNFILE="$RUNFILE" 559 RUNFILE=$(find_runfile "$RUNFILE") || 560 fail "Cannot find runfile: $SAVED_RUNFILE" 561 R="$R,$RUNFILE" 562 fi 563 564 if [ ! -r "$RUNFILE" ]; then 565 fail "Cannot read runfile: $RUNFILE" 566 fi 567done 568unset IFS 569RUNFILES=${R#,} 570 571# The tag can be a fraction to indicate which portion of ZTS to run, Like 572# 573# "1/3": Run first one third of all tests in runfiles 574# "2/3": Run second one third of all test in runfiles 575# "6/10": Run 6th tenth of all tests in runfiles 576# 577# This is useful for splitting up the test across multiple runners. 578# 579# After this code block, TAGS will be transformed from something like 580# "1/3" to a comma separate taglist, like: 581# 582# "append,atime,bootfs,cachefile,checksum,cp_files,deadman,dos_attributes, ..." 583# 584if echo "$TAGS" | grep -Eq '^[0-9]+/[0-9]+$' ; then 585 TAGS=$(split_tags) 586fi 587 588# 589# This script should not be run as root. Instead the test user, which may 590# be a normal user account, needs to be configured such that it can 591# run commands via sudo passwordlessly. 592# 593if [ "$(id -u)" = "0" ]; then 594 fail "This script must not be run as root." 595fi 596 597if [ "$(sudo id -un)" != "root" ]; then 598 fail "Passwordless sudo access required." 599fi 600 601# 602# Constrain the available binaries to a known set. 603# 604constrain_path 605 606# 607# Check if ksh exists 608# 609if [ "$UNAME" = "FreeBSD" ]; then 610 sudo ln -fs /usr/local/bin/ksh93 /bin/ksh 611fi 612[ -e "$STF_PATH/ksh" ] || fail "This test suite requires ksh." 613[ -e "$STF_SUITE/include/default.cfg" ] || fail \ 614 "Missing $STF_SUITE/include/default.cfg file." 615 616# 617# Verify the ZFS module stack is loaded. 618# 619if [ "$STACK_TRACER" = "yes" ]; then 620 sudo "${ZFS_SH}" -S >/dev/null 2>&1 621else 622 sudo "${ZFS_SH}" >/dev/null 2>&1 623fi 624 625# 626# Attempt to cleanup all previous state for a new test run. 627# 628if [ "$CLEANUPALL" = "yes" ]; then 629 cleanup_all 630fi 631 632# 633# By default preserve any existing pools 634# 635if [ -z "${KEEP}" ]; then 636 KEEP="$(ASAN_OPTIONS=detect_leaks=false "$ZPOOL" list -Ho name | tr -s '[:space:]' ' ')" 637 if [ -z "${KEEP}" ]; then 638 KEEP="rpool" 639 fi 640else 641 KEEP="$(echo "$KEEP" | tr -s '[:space:]' ' ')" 642fi 643 644# 645# NOTE: The following environment variables are undocumented 646# and should be used for testing purposes only: 647# 648# __ZFS_POOL_EXCLUDE - don't iterate over the pools it lists 649# __ZFS_POOL_RESTRICT - iterate only over the pools it lists 650# 651# See libzfs/libzfs_config.c for more information. 652# 653__ZFS_POOL_EXCLUDE="$KEEP" 654 655. "$STF_SUITE/include/default.cfg" 656 657# 658# No DISKS have been provided so a basic file or loopback based devices 659# must be created for the test suite to use. 660# 661if [ -z "${DISKS}" ]; then 662 # 663 # If this is a performance run, prevent accidental use of 664 # loopback devices. 665 # 666 [ "$TAGS" = "perf" ] && fail "Running perf tests without disks." 667 668 # 669 # Create sparse files for the test suite. These may be used 670 # directory or have loopback devices layered on them. 671 # 672 for TEST_FILE in ${FILES}; do 673 [ -f "$TEST_FILE" ] && fail "Failed file exists: ${TEST_FILE}" 674 truncate -s "${FILESIZE}" "${TEST_FILE}" || 675 fail "Failed creating: ${TEST_FILE} ($?)" 676 done 677 678 # 679 # If requested setup loopback devices backed by the sparse files. 680 # 681 if [ "$LOOPBACK" = "yes" ]; then 682 test -x "$LOSETUP" || fail "$LOSETUP utility must be installed" 683 684 for TEST_FILE in ${FILES}; do 685 if [ "$UNAME" = "FreeBSD" ] ; then 686 MDDEVICE=$(sudo "${LOSETUP}" -a -t vnode -f "${TEST_FILE}") 687 if [ -z "$MDDEVICE" ] ; then 688 fail "Failed: ${TEST_FILE} -> loopback" 689 fi 690 DISKS="$DISKS $MDDEVICE" 691 LOOPBACKS="$LOOPBACKS $MDDEVICE" 692 else 693 TEST_LOOPBACK=$(sudo "${LOSETUP}" --show -f "${TEST_FILE}") || 694 fail "Failed: ${TEST_FILE} -> ${TEST_LOOPBACK}" 695 BASELOOPBACK="${TEST_LOOPBACK##*/}" 696 DISKS="$DISKS $BASELOOPBACK" 697 LOOPBACKS="$LOOPBACKS $TEST_LOOPBACK" 698 fi 699 done 700 DISKS=${DISKS# } 701 LOOPBACKS=${LOOPBACKS# } 702 else 703 DISKS="$FILES" 704 fi 705fi 706 707# 708# It may be desirable to test with fewer disks than the default when running 709# the performance tests, but the functional tests require at least three. 710# 711NUM_DISKS=$(echo "${DISKS}" | awk '{print NF}') 712if [ "$TAGS" != "perf" ]; then 713 [ "$NUM_DISKS" -lt 3 ] && fail "Not enough disks ($NUM_DISKS/3 minimum)" 714fi 715 716# 717# Disable SELinux until the ZFS Test Suite has been updated accordingly. 718# 719if command -v setenforce >/dev/null; then 720 sudo setenforce permissive >/dev/null 2>&1 721fi 722 723# 724# Enable internal ZFS debug log and clear it. 725# 726if [ -e /sys/module/zfs/parameters/zfs_dbgmsg_enable ]; then 727 sudo sh -c "echo 1 >/sys/module/zfs/parameters/zfs_dbgmsg_enable" 728 sudo sh -c "echo 0 >/proc/spl/kstat/zfs/dbgmsg" 729fi 730 731# 732# Set TMPDIR. Some tests run mktemp, and we want those files contained to 733# the work dir the same as any other. 734# 735export TMPDIR="$FILEDIR" 736 737msg 738msg "--- Configuration ---" 739msg "Runfiles: $RUNFILES" 740msg "STF_TOOLS: $STF_TOOLS" 741msg "STF_SUITE: $STF_SUITE" 742msg "STF_PATH: $STF_PATH" 743msg "FILEDIR: $FILEDIR" 744msg "TMPDIR: $TMPDIR" 745msg "FILES: $FILES" 746msg "LOOPBACKS: $LOOPBACKS" 747msg "DISKS: $DISKS" 748msg "NUM_DISKS: $NUM_DISKS" 749msg "FILESIZE: $FILESIZE" 750msg "ITERATIONS: $ITERATIONS" 751msg "TAGS: $TAGS" 752msg "STACK_TRACER: $STACK_TRACER" 753msg "Keep pool(s): $KEEP" 754msg "Missing util(s): $STF_MISSING_BIN" 755msg "" 756 757export STF_TOOLS 758export STF_SUITE 759export STF_PATH 760export DISKS 761export FILEDIR 762export KEEP 763export __ZFS_POOL_EXCLUDE 764export TESTFAIL_CALLBACKS 765 766mktemp_file() { 767 if [ "$UNAME" = "FreeBSD" ]; then 768 mktemp -u "${FILEDIR}/$1.XXXXXX" 769 else 770 mktemp -ut "$1.XXXXXX" -p "$FILEDIR" 771 fi 772} 773mkdir -p "$FILEDIR" || : 774RESULTS_FILE=$(mktemp_file zts-results) 775REPORT_FILE=$(mktemp_file zts-report) 776 777# 778# Run all the tests as specified. 779# 780msg "${TEST_RUNNER}" \ 781 "${QUIET:+-q}" \ 782 "${DEBUG:+-D}" \ 783 "${KMEMLEAK:+-m}" \ 784 "${KMSG:+-K}" \ 785 "${TIMEOUT_DEBUG:+-O}" \ 786 "-c \"${RUNFILES}\"" \ 787 "-T \"${TAGS}\"" \ 788 "-i \"${STF_SUITE}\"" \ 789 "-I \"${ITERATIONS}\"" 790{ PATH=$STF_PATH \ 791 ${TEST_RUNNER} \ 792 ${QUIET:+-q} \ 793 ${DEBUG:+-D} \ 794 ${KMEMLEAK:+-m} \ 795 ${KMSG:+-K} \ 796 ${TIMEOUT_DEBUG:+-O} \ 797 -c "${RUNFILES}" \ 798 -T "${TAGS}" \ 799 -i "${STF_SUITE}" \ 800 -I "${ITERATIONS}" \ 801 2>&1; echo $? >"$REPORT_FILE"; } | tee "$RESULTS_FILE" 802read -r RUNRESULT <"$REPORT_FILE" 803 804if [[ "$RUNRESULT" -eq "255" ]] ; then 805 fail "$TEST_RUNNER failed, test aborted." 806fi 807 808# 809# Analyze the results. 810# 811${ZTS_REPORT} ${RERUN:+--no-maybes} "$RESULTS_FILE" >"$REPORT_FILE" 812RESULT=$? 813 814if [ "$RESULT" -eq "2" ] && [ -n "$RERUN" ]; then 815 MAYBES="$($ZTS_REPORT --list-maybes)" 816 TEMP_RESULTS_FILE=$(mktemp_file zts-results-tmp) 817 TEST_LIST=$(mktemp_file test-list) 818 grep "^Test:.*\[FAIL\]" "$RESULTS_FILE" >"$TEMP_RESULTS_FILE" 819 for test_name in $MAYBES; do 820 grep "$test_name " "$TEMP_RESULTS_FILE" >>"$TEST_LIST" 821 done 822 { PATH=$STF_PATH \ 823 ${TEST_RUNNER} \ 824 ${QUIET:+-q} \ 825 ${DEBUG:+-D} \ 826 ${KMEMLEAK:+-m} \ 827 -c "${RUNFILES}" \ 828 -T "${TAGS}" \ 829 -i "${STF_SUITE}" \ 830 -I "${ITERATIONS}" \ 831 -l "${TEST_LIST}" \ 832 2>&1; echo $? >"$REPORT_FILE"; } | tee "$RESULTS_FILE" 833 read -r RUNRESULT <"$REPORT_FILE" 834 # 835 # Analyze the results. 836 # 837 ${ZTS_REPORT} --no-maybes "$RESULTS_FILE" >"$REPORT_FILE" 838 RESULT=$? 839fi 840 841 842cat "$REPORT_FILE" 843 844RESULTS_DIR=$(awk '/^Log directory/ { print $3 }' "$RESULTS_FILE") 845if [ -d "$RESULTS_DIR" ]; then 846 cat "$RESULTS_FILE" "$REPORT_FILE" >"$RESULTS_DIR/results" 847fi 848 849rm -f "$RESULTS_FILE" "$REPORT_FILE" "$TEST_LIST" "$TEMP_RESULTS_FILE" 850 851if [ -n "$SINGLETEST" ]; then 852 rm -f "$RUNFILES" >/dev/null 2>&1 853fi 854 855[ "$RUNRESULT" -gt 3 ] && exit "$RUNRESULT" || exit "$RESULT" 856