#!/bin/bash # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License, Version 1.0 only # (the "License"). You may not use this file except in compliance # with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # basedir="$(dirname $0)" SCRIPT_COMMON=common.sh if [ -f "${basedir}/${SCRIPT_COMMON}" ]; then . "${basedir}/${SCRIPT_COMMON}" else echo "Missing helper script ${SCRIPT_COMMON}" && exit 1 fi . $STF_SUITE/include/default.cfg PROG=zfs-tests.sh SUDO=/usr/bin/sudo SETENFORCE=/usr/sbin/setenforce VERBOSE= QUIET= CLEANUP=1 CLEANUPALL=0 LOOPBACK=1 FILESIZE="2G" RUNFILE=${RUNFILE:-"linux.run"} FILEDIR=${FILEDIR:-/var/tmp} DISKS=${DISKS:-""} # # Attempt to remove loopback devices and files which where created earlier # by this script to run the test framework. The '-k' option may be passed # to the script to suppress cleanup for debugging purposes. # cleanup() { if [ $CLEANUP -eq 0 ]; then return 0 fi if [ $LOOPBACK -eq 1 ]; then for TEST_LOOPBACK in ${LOOPBACKS}; do LOOP_DEV=$(basename $TEST_LOOPBACK) DM_DEV=$(${SUDO} ${DMSETUP} ls 2>/dev/null | \ grep ${LOOP_DEV} | cut -f1) if [ -n "$DM_DEV" ]; then ${SUDO} ${DMSETUP} remove ${DM_DEV} || echo "Failed to remove: ${DM_DEV}" fi if [ -n "${TEST_LOOPBACK}" ]; then ${SUDO} ${LOSETUP} -d ${TEST_LOOPBACK} || echo "Failed to remove: ${TEST_LOOPBACK}" fi done fi for TEST_FILE in ${FILES}; do rm -f ${TEST_FILE} &>/dev/null done } trap cleanup EXIT # # Attempt to remove all testpools (testpool.XXX), unopened dm devices, # loopback devices, and files. This is a useful way to cleanup a previous # test run failure which has left the system in an unknown state. This can # be dangerous and should only be used in a dedicated test environment. # cleanup_all() { local TEST_POOLS=$(${SUDO} ${ZPOOL} list -H -o name | grep testpool) local TEST_LOOPBACKS=$(${SUDO} ${LOSETUP} -a|grep file-vdev|cut -f1 -d:) local TEST_FILES=$(ls /var/tmp/file-vdev* 2>/dev/null) msg msg "--- Cleanup ---" msg "Removing pool(s): $(echo ${TEST_POOLS} | tr '\n' ' ')" for TEST_POOL in $TEST_POOLS; do ${SUDO} ${ZPOOL} destroy ${TEST_POOL} done msg "Removing dm(s): $(${SUDO} ${DMSETUP} ls | grep loop | tr '\n' ' ')" ${SUDO} ${DMSETUP} remove_all msg "Removing loopback(s): $(echo ${TEST_LOOPBACKS} | tr '\n' ' ')" for TEST_LOOPBACK in $TEST_LOOPBACKS; do ${SUDO} ${LOSETUP} -d ${TEST_LOOPBACK} done msg "Removing files(s): $(echo ${TEST_FILES} | tr '\n' ' ')" for TEST_FILE in $TEST_FILES; do ${SUDO} rm -f ${TEST_FILE} done } # # Log a failure message, cleanup, and return an error. # fail() { echo -e "${PROG}: $1" >&2 cleanup exit 1 } # # Takes a name as the only arguments and looks for the following variations # on that name. If one is found it is returned. # # $RUNFILEDIR/ # $RUNFILEDIR/.run # # .run # find_runfile() { local NAME=$1 local RESULT="" if [ -f "$RUNFILEDIR/$NAME" ]; then RESULT="$RUNFILEDIR/$NAME" elif [ -f "$RUNFILEDIR/$NAME.run" ]; then RESULT="$RUNFILEDIR/$NAME.run" elif [ -f "$NAME" ]; then RESULT="$NAME" elif [ -f "$NAME.run" ]; then RESULT="$NAME.run" fi echo "$RESULT" } # # Output a useful usage message. # usage() { cat << EOF USAGE: $0 [hvqxkf] [-s SIZE] [-r RUNFILE] DESCRIPTION: ZFS Test Suite launch script OPTIONS: -h Show this message -v Verbose zfs-tests.sh output -q Quiet test-runner output -x Remove all testpools, dm, lo, and files (unsafe) -k Disable cleanup after test failure -f Use files only, disables block device tests -d DIR Use DIR for files and loopback devices -s SIZE Use vdevs of SIZE (default: 2G) -r RUNFILE Run tests in RUNFILE (default: linux.run) EXAMPLES: # Run the default (linux) suite of tests and output the configuration used. $0 -v # Run a smaller suite of tests designed to run more quickly. $0 -r linux-fast # Cleanup a previous run of the test suite prior to testing, run the # default (linux) suite of tests and perform no cleanup on exit. $0 -x EOF } while getopts 'hvqxkfd:s:r:?' OPTION; do case $OPTION in h) usage exit 1 ;; v) VERBOSE=1 ;; q) QUIET="-q" ;; x) CLEANUPALL=1 ;; k) CLEANUP=0 ;; f) LOOPBACK=0 ;; d) FILEDIR="$OPTARG" ;; s) FILESIZE="$OPTARG" ;; r) RUNFILE="$OPTARG" ;; ?) usage exit ;; esac done shift $((OPTIND-1)) FILES=${FILES:-"$FILEDIR/file-vdev0 $FILEDIR/file-vdev1 $FILEDIR/file-vdev2"} LOOPBACKS=${LOOPBACKS:-""} # # Attempt to locate the runfile describing the test workload. # if [ -n "$RUNFILE" ]; then SAVED_RUNFILE="$RUNFILE" RUNFILE=$(find_runfile "$RUNFILE") [ -z "$RUNFILE" ] && fail "Cannot find runfile: $SAVED_RUNFILE" fi if [ ! -r "$RUNFILE" ]; then fail "Cannot read runfile: $RUNFILE" fi # # This script should not be run as root. Instead the test user, which may # be a normal user account, needs to be configured such that it can # run commands via sudo passwordlessly. # if [ $(id -u) = "0" ]; then fail "This script must not be run as root." fi if [ $(sudo whoami) != "root" ]; then fail "Passwordless sudo access required." fi # # Check if ksh exists # if [ -z "$(which ksh 2>/dev/null)" ]; then fail "This test suite requires ksh." fi # # Verify the ZFS module stack if loaded. # ${SUDO} ${ZFS_SH} &>/dev/null # # Attempt to cleanup all previous state for a new test run. # if [ $CLEANUPALL -ne 0 ]; then cleanup_all fi # # By default preserve any existing pools # if [ -z "${KEEP}" ]; then KEEP=$(${SUDO} ${ZPOOL} list -H -o name) if [ -z "${KEEP}" ]; then KEEP="rpool" fi fi msg msg "--- Configuration ---" msg "Runfile: $RUNFILE" msg "STF_TOOLS: $STF_TOOLS" msg "STF_SUITE: $STF_SUITE" # # No DISKS have been provided so a basic file or loopback based devices # must be created for the test suite to use. # if [ -z "${DISKS}" ]; then # # Create sparse files for the test suite. These may be used # directory or have loopback devices layered on them. # for TEST_FILE in ${FILES}; do [ -f "$TEST_FILE" ] && fail "Failed file exists: ${TEST_FILE}" truncate -s ${FILESIZE} ${TEST_FILE} || fail "Failed creating: ${TEST_FILE} ($?)" DISKS="$DISKS$TEST_FILE " done # # If requested setup loopback devices backed by the sparse files. # if [ $LOOPBACK -eq 1 ]; then DISKS="" check_loop_utils for TEST_FILE in ${FILES}; do TEST_LOOPBACK=$(${SUDO} ${LOSETUP} -f) ${SUDO} ${LOSETUP} ${TEST_LOOPBACK} ${TEST_FILE} || fail "Failed: ${TEST_FILE} -> ${TEST_LOOPBACK}" LOOPBACKS="${LOOPBACKS}${TEST_LOOPBACK} " DISKS="$DISKS$(basename $TEST_LOOPBACK) " done fi fi NUM_DISKS=$(echo ${DISKS} | $AWK '{print NF}') [ $NUM_DISKS -lt 3 ] && fail "Not enough disks ($NUM_DISKS/3 minimum)" # # Disable SELinux until the ZFS Test Suite has been updated accordingly. # if [ -x ${SETENFORCE} ]; then ${SUDO} ${SETENFORCE} permissive &>/dev/null fi msg "FILEDIR: $FILEDIR" msg "FILES: $FILES" msg "LOOPBACKS: $LOOPBACKS" msg "DISKS: $DISKS" msg "NUM_DISKS: $NUM_DISKS" msg "FILESIZE: $FILESIZE" msg "Keep pool(s): $KEEP" msg "" export STF_TOOLS export STF_SUITE export DISKS export KEEP msg "${TEST_RUNNER} ${QUIET} -c ${RUNFILE} -i ${STF_SUITE}" ${TEST_RUNNER} ${QUIET} -c ${RUNFILE} -i ${STF_SUITE} RESULT=$? echo exit ${RESULT}