summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Makefile.am10
-rw-r--r--scripts/Makefile.in10
-rw-r--r--scripts/common.sh.in196
-rwxr-xr-xscripts/zconfig.sh1
-rwxr-xr-xscripts/zfault.sh951
-rw-r--r--scripts/zpool-config/Makefile.am63
-rw-r--r--scripts/zpool-config/Makefile.in63
-rw-r--r--scripts/zpool-config/lo-faulty-raid0.sh78
-rw-r--r--scripts/zpool-config/lo-faulty-raid10.sh84
-rw-r--r--scripts/zpool-config/lo-faulty-raidz.sh72
-rw-r--r--scripts/zpool-config/lo-faulty-raidz2.sh72
-rw-r--r--scripts/zpool-config/lo-faulty-raidz3.sh72
-rw-r--r--scripts/zpool-config/lo-raid0.sh2
-rw-r--r--scripts/zpool-config/lo-raid10.sh2
-rw-r--r--scripts/zpool-config/lo-raidz.sh2
-rw-r--r--scripts/zpool-config/lo-raidz2.sh2
-rw-r--r--scripts/zpool-config/scsi_debug-noraid.sh46
-rw-r--r--scripts/zpool-config/scsi_debug-raid0.sh79
-rw-r--r--scripts/zpool-config/scsi_debug-raid10.sh93
-rw-r--r--scripts/zpool-config/scsi_debug-raidz.sh79
-rw-r--r--scripts/zpool-config/scsi_debug-raidz2.sh79
-rw-r--r--scripts/zpool-config/scsi_debug-raidz3.sh79
22 files changed, 2069 insertions, 66 deletions
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 4df4b277c..cc910bab5 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -4,6 +4,7 @@ pkglibexecdir = $(libexecdir)/@PACKAGE@
dist_pkglibexec_SCRIPTS = \
$(top_builddir)/scripts/common.sh \
$(top_srcdir)/scripts/zconfig.sh \
+ $(top_srcdir)/scripts/zfault.sh \
$(top_srcdir)/scripts/zfs.sh \
$(top_srcdir)/scripts/zpool-create.sh \
$(top_srcdir)/scripts/zpios.sh \
@@ -12,6 +13,7 @@ dist_pkglibexec_SCRIPTS = \
ZFS=$(top_builddir)/scripts/zfs.sh
ZCONFIG=$(top_builddir)/scripts/zconfig.sh
+ZFAULT=$(top_builddir)/scripts/zfault.sh
ZTEST=$(top_builddir)/cmd/ztest/ztest
ZPIOS_SANITY=$(top_builddir)/scripts/zpios-sanity.sh
@@ -48,7 +50,13 @@ check:
@echo -n " ZCONFIG "
@echo "==================================="
@echo
- @$(ZCONFIG)
+ @$(ZCONFIG) -c
+ @echo
+ @echo -n "==================================="
+ @echo -n " ZFAULT "
+ @echo "==================================="
+ @echo
+ @$(ZFAULT) -c
@echo
@echo -n "===================================="
@echo -n " ZPIOS "
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
index 2a1a4509e..8c6e67d54 100644
--- a/scripts/Makefile.in
+++ b/scripts/Makefile.in
@@ -316,6 +316,7 @@ SUBDIRS = zpool-config zpool-layout zpios-test zpios-profile
dist_pkglibexec_SCRIPTS = \
$(top_builddir)/scripts/common.sh \
$(top_srcdir)/scripts/zconfig.sh \
+ $(top_srcdir)/scripts/zfault.sh \
$(top_srcdir)/scripts/zfs.sh \
$(top_srcdir)/scripts/zpool-create.sh \
$(top_srcdir)/scripts/zpios.sh \
@@ -324,6 +325,7 @@ dist_pkglibexec_SCRIPTS = \
ZFS = $(top_builddir)/scripts/zfs.sh
ZCONFIG = $(top_builddir)/scripts/zconfig.sh
+ZFAULT = $(top_builddir)/scripts/zfault.sh
ZTEST = $(top_builddir)/cmd/ztest/ztest
ZPIOS_SANITY = $(top_builddir)/scripts/zpios-sanity.sh
all: all-recursive
@@ -744,7 +746,13 @@ check:
@echo -n " ZCONFIG "
@echo "==================================="
@echo
- @$(ZCONFIG)
+ @$(ZCONFIG) -c
+ @echo
+ @echo -n "==================================="
+ @echo -n " ZFAULT "
+ @echo "==================================="
+ @echo
+ @$(ZFAULT) -c
@echo
@echo -n "===================================="
@echo -n " ZPIOS "
diff --git a/scripts/common.sh.in b/scripts/common.sh.in
index 57508be9f..09ca818c3 100644
--- a/scripts/common.sh.in
+++ b/scripts/common.sh.in
@@ -61,6 +61,11 @@ LSMOD=${LSMOD:-/sbin/lsmod}
RMMOD=${RMMOD:-/sbin/rmmod}
INFOMOD=${INFOMOD:-/sbin/modinfo}
LOSETUP=${LOSETUP:-/sbin/losetup}
+MDADM=${MDADM:-/sbin/mdadm}
+PARTED=${PARTED:-/sbin/parted}
+BLOCKDEV=${BLOCKDEV:-/sbin/blockdev}
+LSSCSI=${LSSCSI:-/usr/bin/lsscsi}
+SCSIRESCAN=${SCSIRESCAN:-/usr/bin/scsi-rescan}
SYSCTL=${SYSCTL:-/sbin/sysctl}
UDEVADM=${UDEVADM:-/sbin/udevadm}
AWK=${AWK:-/usr/bin/awk}
@@ -225,8 +230,19 @@ unload_modules() {
return 0
}
+#
+# Check that the mdadm utilities are installed.
+#
+check_loop_utils() {
+ test -f ${LOSETUP} || die "${LOSETUP} utility must be installed"
+}
+
+
+#
+# Find and return an unused loopback device.
+#
unused_loop_device() {
- for DEVICE in `ls -1 /dev/loop*`; do
+ for DEVICE in `ls -1 /dev/loop* 2>/dev/null`; do
${LOSETUP} ${DEVICE} &>/dev/null
if [ $? -ne 0 ]; then
echo ${DEVICE}
@@ -239,7 +255,7 @@ unused_loop_device() {
#
# This can be slightly dangerous because the loop devices we are
-# cleanup up may not be ours. However, if the devices are currently
+# cleaning up may not be ours. However, if the devices are currently
# in use we will not be able to remove them, and we only remove
# devices which include 'zpool' in the name. So any damage we might
# do should be limited to other zfs related testing.
@@ -256,6 +272,168 @@ cleanup_loop_devices() {
}
#
+# Destroy the passed loopback devices, this is used when you know
+# the names of the loopback devices.
+#
+destroy_loop_devices() {
+ local LODEVICES="$1"
+
+ msg "Destroying ${LODEVICES}"
+ ${LOSETUP} -d ${LODEVICES} || \
+ die "Error $? destroying ${FILE} -> ${DEVICE} loopback"
+
+ rm -f ${FILES}
+ return 0
+}
+
+#
+# Check that the mdadm utilities are installed.
+#
+check_md_utils() {
+ test -f ${MDADM} || die "${MDADM} utility must be installed"
+ test -f ${PARTED} || die "${PARTED} utility must be installed"
+}
+
+check_md_partitionable() {
+ local LOFILE=`mktemp -p /tmp zpool-lo.XXXXXXXX`
+ local LODEVICE=`unused_loop_device`
+ local MDDEVICE=`unused_md_device`
+ local RESULT=1
+
+ check_md_utils
+
+ rm -f ${LOFILE}
+ dd if=/dev/zero of=${LOFILE} bs=1M count=0 seek=16 \
+ &>/dev/null || return ${RESULT}
+
+ msg "Creating ${LODEVICE} using ${LOFILE}"
+ ${LOSETUP} ${LODEVICE} ${LOFILE}
+ if [ $? -ne 0 ]; then
+ rm -f ${LOFILE}
+ return ${RESULT}
+ fi
+
+ msg "Creating ${MDDEVICE} using ${LODEVICE}"
+ ${MDADM} --build ${MDDEVICE} --level=faulty \
+ --raid-devices=1 ${LODEVICE} &>/dev/null
+ if [ $? -ne 0 ]; then
+ destroy_loop_devices ${LODEVICE}
+ rm -f ${LOFILE}
+ return ${RESULT}
+ fi
+ wait_udev ${MDDEVICE} 30
+
+ ${BLOCKDEV} --rereadpt ${MDDEVICE} 2>/dev/null
+ RESULT=$?
+
+ destroy_md_devices ${MDDEVICE}
+ destroy_loop_devices ${LODEVICE}
+ rm -f ${LOFILE}
+
+ return ${RESULT}
+}
+
+#
+# Find and return an unused md device.
+#
+unused_md_device() {
+ for (( i=0; i<32; i++ )); do
+ MDDEVICE=md${i}
+
+ # Skip active devicesudo in /proc/mdstat.
+ grep -q "${MDDEVICE} " /proc/mdstat && continue
+
+ # Device doesn't exist, use it.
+ if [ ! -e $/dev/{MDDEVICE} ]; then
+ echo /dev/${MDDEVICE}
+ return
+ fi
+
+ # Device exists but may not be in use.
+ if [ -b /dev/${MDDEVICE} ]; then
+ ${MDADM} --detail /dev/${MDDEVICE} &>/dev/null
+ if [ $? -eq 1 ]; then
+ echo /dev/${MDDEVICE}
+ return
+ fi
+ fi
+ done
+
+ die "Error: Unable to find unused md device"
+}
+
+#
+# This can be slightly dangerous because it is possible the md devices
+# we are cleaning up may not be ours. However, if the devices are
+# currently in use we will not be able to remove them, and even if
+# we remove devices which were not out we do not zero the super block
+# so you should be able to reconstruct them.
+#
+cleanup_md_devices() {
+ destroy_md_devices "`ls /dev/md* 2>/dev/null | grep -v p`"
+ udev_trigger
+}
+
+#
+# Destroy the passed md devices, this is used when you know
+# the names of the md devices.
+#
+destroy_md_devices() {
+ local MDDEVICES="$1"
+
+ msg "Destroying ${MDDEVICES}"
+ for MDDEVICE in ${MDDEVICES}; do
+ ${MDADM} --stop ${MDDEVICE} &>/dev/null
+ ${MDADM} --remove ${MDDEVICE} &>/dev/null
+ ${MDADM} --detail ${MDDEVICE} &>/dev/null
+ done
+
+ return 0
+}
+
+#
+# Check that the scsi utilities are installed.
+#
+check_sd_utils() {
+ ${INFOMOD} scsi_debug &>/dev/null || die "scsi_debug module required"
+ test -f ${LSSCSI} || die "${LSSCSI} utility must be installed"
+}
+
+#
+# Rescan the scsi bus for scsi_debug devices. It is preferable to use the
+# scsi-rescan tool if it is installed, but if it's not we can fall back to
+# removing and readding the device manually. This rescan will only effect
+# the first scsi_debug device if scsi-rescan is missing.
+#
+scsi_rescan() {
+ local AWK_SCRIPT="/scsi_debug/ { print \$1; exit }"
+
+ if [ -f ${SCSIRESCAN} ]; then
+ ${SCSIRESCAN} --forcerescan --remove &>/dev/null
+ else
+ local SCSIID=`${LSSCSI} | ${AWK} "${AWK_SCRIPT}" | tr -d '[]'`
+ local SCSIHOST=`echo ${SCSIID} | cut -f1 -d':'`
+ echo 1 >"/sys/class/scsi_device/${SCSIID}/device/delete"
+ udev_trigger
+ echo "- - -" >/sys/class/scsi_host/host${SCSIHOST}/scan
+ udev_trigger
+ fi
+}
+
+#
+# Trigger udev and wait for it to settle.
+#
+udev_trigger() {
+ if [ -f ${UDEVADM} ]; then
+ ${UDEVADM} trigger
+ ${UDEVADM} settle
+ else
+ /sbin/udevtrigger
+ /sbin/udevsettle
+ fi
+}
+
+#
# The following udev helper functions assume that the provided
# udev rules file will create a /dev/disk/zpool/<CHANNEL><RANK>
# disk mapping. In this mapping each CHANNEL is represented by
@@ -292,14 +470,7 @@ udev_setup() {
fi
cp ${SRC_PATH} ${DST_PATH}
-
- if [ -f ${UDEVADM} ]; then
- ${UDEVADM} trigger
- ${UDEVADM} settle
- else
- /sbin/udevtrigger
- /sbin/udevsettle
- fi
+ udev_trigger
fi
return 0
@@ -405,7 +576,7 @@ run_one_test() {
local TEST_NUM=$1
local TEST_NAME=$2
- printf "%-4d %-36s " ${TEST_NUM} "${TEST_NAME}"
+ printf "%-4d %-34s " ${TEST_NUM} "${TEST_NAME}"
test_${TEST_NUM}
}
@@ -413,7 +584,7 @@ skip_one_test() {
local TEST_NUM=$1
local TEST_NAME=$2
- printf "%-4d %-36s " ${TEST_NUM} "${TEST_NAME}"
+ printf "%-4d %-34s " ${TEST_NUM} "${TEST_NAME}"
skip
}
@@ -447,6 +618,7 @@ wait_udev() {
local DELAY=$2
local COUNT=0
+ udev_trigger
while [ ! -e ${DEVICE} ]; do
if [ ${COUNT} -gt ${DELAY} ]; then
return 1
diff --git a/scripts/zconfig.sh b/scripts/zconfig.sh
index 3d965bbca..7a23d790e 100755
--- a/scripts/zconfig.sh
+++ b/scripts/zconfig.sh
@@ -60,6 +60,7 @@ fi
# Perform pre-cleanup is requested
if [ ${CLEANUP} ]; then
+ cleanup_md_devices
cleanup_loop_devices
rm -f /tmp/zpool.cache.*
fi
diff --git a/scripts/zfault.sh b/scripts/zfault.sh
new file mode 100755
index 000000000..08d822538
--- /dev/null
+++ b/scripts/zfault.sh
@@ -0,0 +1,951 @@
+#!/bin/bash
+#
+# ZPOOL fault verification test script.
+#
+# The current suite of fault tests should not be thought of an exhaustive
+# list of failure modes. Rather it is simply an starting point which trys
+# to cover the bulk the of the 'easy' and hopefully common, failure modes.
+#
+# Additional tests should be added but the current suite as new interesting
+# failures modes are observed. Additional failure modes I'd like to see
+# tests for include, but are not limited too:
+#
+# * Slow but successful IO.
+# * SCSI sense codes generated as zevents.
+# * 4k sectors
+# * noise
+# * medium error
+# * recovered error
+#
+# The current infrastructure using the 'mdadm' faulty device and the
+# 'scsi_debug' simulated scsi devices. The idea is to inject the error
+# below the zfs stack to validate all the error paths. More targeted
+# failure testing should be added using the 'zinject' command line util.
+#
+# Requires the following packages:
+# * mdadm
+# * lsscsi
+# * sg3-utils
+#
+
+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
+
+PROG=zfault.sh
+
+usage() {
+cat << EOF
+USAGE:
+$0 [hvc]
+
+DESCRIPTION:
+ ZPOOL fault verification tests
+
+OPTIONS:
+ -h Show this message
+ -v Verbose
+ -c Cleanup md+lo+file devices at start
+ -t <#> Run listed tests
+ -s <#> Skip listed tests
+
+EOF
+}
+
+while getopts 'hvct:s:?' OPTION; do
+ case $OPTION in
+ h)
+ usage
+ exit 1
+ ;;
+ v)
+ VERBOSE=1
+ ;;
+ c)
+ CLEANUP=1
+ ;;
+ t)
+ TESTS_RUN=($OPTARG)
+ ;;
+ s)
+ TESTS_SKIP=($OPTARG)
+ ;;
+ ?)
+ usage
+ exit
+ ;;
+ esac
+done
+
+if [ $(id -u) != 0 ]; then
+ die "Must run as root"
+fi
+
+# Perform pre-cleanup is requested
+if [ ${CLEANUP} ]; then
+ cleanup_md_devices
+ cleanup_loop_devices
+ rm -f /tmp/zpool.cache.*
+fi
+
+# Check if we need to skip all md based tests.
+MD_PARTITIONABLE=0
+check_md_partitionable && MD_PARTITIONABLE=1
+if [ ${MD_PARTITIONABLE} -eq 0 ]; then
+ echo "Skipping tests 1-7 which require partitionable md devices"
+fi
+
+# Check if we need to skip all the scsi_debug tests.
+SCSI_DEBUG=0
+${INFOMOD} scsi_debug &>/dev/null && SCSI_DEBUG=1
+if [ ${SCSI_DEBUG} -eq 0 ]; then
+ echo "Skipping tests 8-9 which require the scsi_debug module"
+fi
+
+if [ ${MD_PARTITIONABLE} -eq 0 ] || [ ${SCSI_DEBUG} -eq 0 ]; then
+ echo
+fi
+
+printf "%40s%s\t%s\t%s\t%s\t%s\n" "" "raid0" "raid10" "raidz" "raidz2" "raidz3"
+
+pass_nonewline() {
+ echo -n -e "${COLOR_GREEN}Pass${COLOR_RESET}\t"
+}
+
+skip_nonewline() {
+ echo -n -e "${COLOR_BROWN}Skip${COLOR_RESET}\t"
+}
+
+nth_zpool_vdev() {
+ local POOL_NAME=$1
+ local DEVICE_TYPE=$2
+ local DEVICE_NTH=$3
+
+ ${ZPOOL} status ${POOL_NAME} | grep ${DEVICE_TYPE} ${TMP_STATUS} | \
+ head -n${DEVICE_NTH} | tail -n1 | ${AWK} "{ print \$1 }"
+}
+
+vdev_status() {
+ local POOL_NAME=$1
+ local VDEV_NAME=$2
+
+ ${ZPOOL} status ${POOL_NAME} | ${AWK} "/${VDEV_NAME}/ { print \$2 }"
+}
+
+# Required format is x.yz[KMGTP]
+expand_numeric_suffix() {
+ local VALUE=$1
+
+ VALUE=`echo "${VALUE/%K/*1000}"`
+ VALUE=`echo "${VALUE/%M/*1000000}"`
+ VALUE=`echo "${VALUE/%G/*1000000000}"`
+ VALUE=`echo "${VALUE/%T/*1000000000000}"`
+ VALUE=`echo "${VALUE/%P/*1000000000000000}"`
+ VALUE=`echo "${VALUE}" | bc | cut -d'.' -f1`
+
+ echo "${VALUE}"
+}
+
+vdev_read_errors() {
+ local POOL_NAME=$1
+ local VDEV_NAME=$2
+ local VDEV_ERRORS=`${ZPOOL} status ${POOL_NAME} |
+ ${AWK} "/${VDEV_NAME}/ { print \\$3 }"`
+
+ expand_numeric_suffix ${VDEV_ERRORS}
+}
+
+vdev_write_errors() {
+ local POOL_NAME=$1
+ local VDEV_NAME=$2
+ local VDEV_ERRORS=`${ZPOOL} status ${POOL_NAME} |
+ ${AWK} "/${VDEV_NAME}/ { print \\$4 }"`
+
+ expand_numeric_suffix ${VDEV_ERRORS}
+}
+
+vdev_cksum_errors() {
+ local POOL_NAME=$1
+ local VDEV_NAME=$2
+ local VDEV_ERRORS=`${ZPOOL} status ${POOL_NAME} |
+ ${AWK} "/${VDEV_NAME}/ { print \\$5 }"`
+
+ expand_numeric_suffix ${VDEV_ERRORS}
+}
+
+zpool_state() {
+ local POOL_NAME=$1
+
+ ${ZPOOL} status ${POOL_NAME} | ${AWK} "/state/ { print \$2; exit }"
+}
+
+zpool_event() {
+ local EVENT_NAME=$1
+ local EVENT_KEY=$2
+
+ SCRIPT1="BEGIN {RS=\"\"; FS=\"\n\"} /${EVENT_NAME}/ { print \$0; exit }"
+ SCRIPT2="BEGIN {FS=\"=\"} /${EVENT_KEY}/ { print \$2; exit }"
+
+ ${ZPOOL} events -vH | ${AWK} "${SCRIPT1}" | ${AWK} "${SCRIPT2}"
+}
+
+zpool_scan_errors() {
+ local POOL_NAME=$1
+
+ ${ZPOOL} status ${POOL_NAME} | ${AWK} "/scan: scrub/ { print \$8 }"
+ ${ZPOOL} status ${POOL_NAME} | ${AWK} "/scan: resilver/ { print \$7 }"
+}
+
+pattern_create() {
+ local PATTERN_BLOCK_SIZE=$1
+ local PATTERN_BLOCK_COUNT=$2
+ local PATTERN_NAME=`mktemp -p /tmp zpool.pattern.XXXXXXXX`
+
+ echo ${PATTERN_NAME}
+ dd if=/dev/urandom of=${PATTERN_NAME} bs=${PATTERN_BLOCK_SIZE} \
+ count=${PATTERN_BLOCK_COUNT} &>/dev/null
+ return $?
+}
+
+pattern_write() {
+ local PATTERN_NAME=$1
+ local PATTERN_BLOCK_SIZE=$2
+ local PATTERN_BLOCK_COUNT=$3
+ local DEVICE_NAME=$4
+
+ dd if=${PATTERN_NAME} of=${DEVICE_NAME} bs=${PATTERN_BLOCK_SIZE} \
+ count=${PATTERN_BLOCK_COUNT} oflag=direct &>/dev/null
+ return $?
+}
+
+pattern_write_bg() {
+ local PATTERN_NAME=$1
+ local PATTERN_BLOCK_SIZE=$2
+ local PATTERN_BLOCK_COUNT=$3
+ local DEVICE_NAME=$4
+
+ dd if=${PATTERN_NAME} of=${DEVICE_NAME} bs=${PATTERN_BLOCK_SIZE} \
+ count=${PATTERN_BLOCK_COUNT} oflag=direct &>/dev/null &
+ return $?
+}
+
+pattern_verify() {
+ local PATTERN_NAME=$1
+ local PATTERN_BLOCK_SIZE=$2
+ local PATTERN_BLOCK_COUNT=$3
+ local DEVICE_NAME=$4
+ local DEVICE_FILE=`mktemp -p /tmp zpool.pattern.XXXXXXXX`
+
+ dd if=${DEVICE_NAME} of=${DEVICE_FILE} bs=${PATTERN_BLOCK_SIZE} \
+ count=${PATTERN_BLOCK_COUNT} iflag=direct &>/dev/null
+ cmp -s ${PATTERN_NAME} ${DEVICE_FILE}
+ RC=$?
+ rm -f ${DEVICE_FILE}
+
+ return ${RC}
+}
+
+pattern_remove() {
+ local PATTERN_NAME=$1
+
+ rm -f ${PATTERN_NAME}
+ return $?
+}
+
+fault_set_md() {
+ local VDEV_FAULTY=$1
+ local FAULT_TYPE=$2
+
+ ${MDADM} /dev/${VDEV_FAULTY} --grow --level=faulty \
+ --layout=${FAULT_TYPE} >/dev/null
+ return $?
+}
+
+fault_clear_md() {
+ local VDEV_FAULTY=$1
+
+ # Clear all failure injection.
+ ${MDADM} /dev/${VDEV_FAULTY} --grow --level=faulty \
+ --layout=clear >/dev/null || return $?
+ ${MDADM} /dev/${VDEV_FAULTY} --grow --level=faulty \
+ --layout=flush >/dev/null || return $?
+ return $?
+}
+
+fault_set_sd() {
+ local OPTS=$1
+ local NTH=$2
+
+ echo ${OPTS} >/sys/bus/pseudo/drivers/scsi_debug/opts
+ echo ${NTH} >/sys/bus/pseudo/drivers/scsi_debug/every_nth
+}
+
+fault_clear_sd() {
+ echo 0 >/sys/bus/pseudo/drivers/scsi_debug/every_nth
+ echo 0 >/sys/bus/pseudo/drivers/scsi_debug/opts
+}
+
+test_setup() {
+ local POOL_NAME=$1
+ local POOL_CONFIG=$2
+ local ZVOL_NAME=$3
+ local TMP_CACHE=$4
+
+ ${ZFS_SH} zfs="spa_config_path=${TMP_CACHE}" || fail 1
+ ${ZPOOL_CREATE_SH} -p ${POOL_NAME} -c ${POOL_CONFIG} || fail 2
+ ${ZFS} create -V 64M ${POOL_NAME}/${ZVOL_NAME} || fail 3
+
+ # Trigger udev and re-read the partition table to ensure all of
+ # this IO is out of the way before we begin injecting failures.
+ udev_trigger || fail 4
+ ${BLOCKDEV} --rereadpt /dev/${POOL_NAME}/${ZVOL_NAME} || fail 5
+}
+
+test_cleanup() {
+ local POOL_NAME=$1
+ local POOL_CONFIG=$2
+ local ZVOL_NAME=$3
+ local TMP_CACHE=$4
+
+ ${ZFS} destroy ${POOL_NAME}/${ZVOL_NAME} || fail 101
+ ${ZPOOL_CREATE_SH} -p ${POOL_NAME} -c ${POOL_CONFIG} -d || fail 102
+ ${ZFS_SH} -u || fail 103
+ rm -f ${TMP_CACHE} || fail 104
+}
+
+test_write_soft() {
+ local POOL_NAME=$1
+ local POOL_CONFIG=$2
+ local POOL_REDUNDANT=$3
+ local ZVOL_NAME="zvol"
+ local ZVOL_DEVICE="/dev/${POOL_NAME}/${ZVOL_NAME}"
+
+ if [ ${MD_PARTITIONABLE} -eq 0 ]; then
+ skip_nonewline
+ return
+ fi
+
+ local TMP_CACHE=`mktemp -p /tmp zpool.cache.XXXXXXXX`
+ test_setup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+
+ # Set soft write failure for first vdev device.
+ local VDEV_FAULTY=`nth_zpool_vdev ${POOL_NAME} md 1`
+ fault_set_md ${VDEV_FAULTY} write-transient
+
+ # The application must not observe an error.
+ local TMP_PATTERN=`pattern_create 1M 8` || fail 11
+ pattern_write ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 12
+ fault_clear_md ${VDEV_FAULTY}
+
+ # Soft errors will not be logged to 'zpool status'
+ local WRITE_ERRORS=`vdev_write_errors ${POOL_NAME} ${VDEV_FAULTY}`
+ test ${WRITE_ERRORS} -eq 0 || fail 13
+
+ # Soft errors will still generate an EIO (5) event.
+ test `zpool_event "zfs.io" "zio_err"` = "0x5" || fail 14
+
+ # Verify the known pattern.
+ pattern_verify ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 15
+ pattern_remove ${TMP_PATTERN} || fail 16
+
+ test_cleanup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+ pass_nonewline
+}
+
+# Soft write error.
+test_1() {
+ test_write_soft tank lo-faulty-raid0 0
+ test_write_soft tank lo-faulty-raid10 1
+ test_write_soft tank lo-faulty-raidz 1
+ test_write_soft tank lo-faulty-raidz2 1
+ test_write_soft tank lo-faulty-raidz3 1
+ echo
+}
+run_test 1 "soft write error"
+
+test_write_hard() {
+ local POOL_NAME=$1
+ local POOL_CONFIG=$2
+ local POOL_REDUNDANT=$3
+ local ZVOL_NAME="zvol"
+ local ZVOL_DEVICE="/dev/${POOL_NAME}/${ZVOL_NAME}"
+
+ if [ ${MD_PARTITIONABLE} -eq 0 ]; then
+ skip_nonewline
+ return
+ fi
+
+ local TMP_CACHE=`mktemp -p /tmp zpool.cache.XXXXXXXX`
+ test_setup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+
+ # Set hard write failure for first vdev device.
+ local VDEV_FAULTY=`nth_zpool_vdev ${POOL_NAME} md 1`
+ fault_set_md ${VDEV_FAULTY} write-persistent
+
+ # The application must not observe an error.
+ local TMP_PATTERN=`pattern_create 1M 8` || fail 11
+ pattern_write ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 12
+ fault_clear_md ${VDEV_FAULTY}
+
+ local WRITE_ERRORS=`vdev_write_errors ${POOL_NAME} ${VDEV_FAULTY}`
+ if [ ${POOL_REDUNDANT} -eq 1 ]; then
+ # For redundant configurations hard errors will not be
+ # logged to 'zpool status' but will generate EIO events.
+ test ${WRITE_ERRORS} -eq 0 || fail 21
+ test `zpool_event "zfs.io" "zio_err"` = "0x5" || fail 22
+ else
+ # For non-redundant configurations hard errors will be
+ # logged to 'zpool status' and generate EIO events. They
+ # will also trigger a scrub of the impacted sectors.
+ sleep 10
+ test ${WRITE_ERRORS} -gt 0 || fail 31
+ test `zpool_event "zfs.io" "zio_err"` = "0x5" || fail 32
+ test `zpool_event "zfs.resilver.start" "ena"` != "" || fail 33
+ test `zpool_event "zfs.resilver.finish" "ena"` != "" || fail 34
+ test `zpool_scan_errors ${POOL_NAME}` -eq 0 || fail 35
+ fi
+
+ # Verify the known pattern.
+ pattern_verify ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 41
+ pattern_remove ${TMP_PATTERN} || fail 42
+
+ test_cleanup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+ pass_nonewline
+}
+
+# Hard write error.
+test_2() {
+ test_write_hard tank lo-faulty-raid0 0
+ test_write_hard tank lo-faulty-raid10 1
+ test_write_hard tank lo-faulty-raidz 1
+ test_write_hard tank lo-faulty-raidz2 1
+ test_write_hard tank lo-faulty-raidz3 1
+ echo
+}
+run_test 2 "hard write error"
+
+test_write_all() {
+ local POOL_NAME=$1
+ local POOL_CONFIG=$2
+ local POOL_REDUNDANT=$3
+ local ZVOL_NAME="zvol"
+ local ZVOL_DEVICE="/dev/${POOL_NAME}/${ZVOL_NAME}"
+
+ if [ ${MD_PARTITIONABLE} -eq 0 ]; then
+ skip_nonewline
+ return
+ fi
+
+ local TMP_CACHE=`mktemp -p /tmp zpool.cache.XXXXXXXX`
+ test_setup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+
+ # Set all write failures for first vdev device.
+ local VDEV_FAULTY=`nth_zpool_vdev ${POOL_NAME} md 1`
+ fault_set_md ${VDEV_FAULTY} write-all
+
+ local TMP_PATTERN=`pattern_create 1M 8` || fail 11
+ if [ ${POOL_REDUNDANT} -eq 1 ]; then
+ # The application must not observe an error.
+ pattern_write ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 12
+ else
+ # The application is expected to hang in the background until
+ # the faulty device is repaired and 'zpool clear' is run.
+ pattern_write_bg ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 13
+ sleep 10
+ fi
+ fault_clear_md ${VDEV_FAULTY}
+
+ local WRITE_ERRORS=`vdev_write_errors ${POOL_NAME} ${VDEV_FAULTY}`
+ local VDEV_STATUS=`vdev_status ${POOL_NAME} ${VDEV_FAULTY}`
+ local POOL_STATE=`zpool_state ${POOL_NAME}`
+ # For all configurations write errors are logged to 'zpool status',
+ # and EIO events are generated. However, only a redundant config
+ # will cause the vdev to be FAULTED and pool DEGRADED. In a non-
+ # redundant config the IO will hang until 'zpool clear' is run.
+ test ${WRITE_ERRORS} -gt 0 || fail 14
+ test `zpool_event "zfs.io" "zio_err"` = "0x5" || fail 15
+
+ if [ ${POOL_REDUNDANT} -eq 1 ]; then
+ test "${VDEV_STATUS}" = "FAULTED" || fail 21
+ test "${POOL_STATE}" = "DEGRADED" || fail 22
+ else
+ BLOCKED=`ps a | grep "${ZVOL_DEVICE}" | grep -c -v "grep"`
+ ${ZPOOL} clear ${POOL_NAME} || fail 31
+ test ${BLOCKED} -eq 1 || fail 32
+ wait
+ fi
+
+ # Verify the known pattern.
+ pattern_verify ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 41
+ pattern_remove ${TMP_PATTERN} || fail 42
+
+ test_cleanup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+ pass_nonewline
+}
+
+# All write errors.
+test_3() {
+ test_write_all tank lo-faulty-raid0 0
+ test_write_all tank lo-faulty-raid10 1
+ test_write_all tank lo-faulty-raidz 1
+ test_write_all tank lo-faulty-raidz2 1
+ test_write_all tank lo-faulty-raidz3 1
+ echo
+}
+run_test 3 "all write errors"
+
+test_read_soft() {
+ local POOL_NAME=$1
+ local POOL_CONFIG=$2
+ local POOL_REDUNDANT=$3
+ local ZVOL_NAME="zvol"
+ local ZVOL_DEVICE="/dev/${POOL_NAME}/${ZVOL_NAME}"
+ local READ_ERRORS=0
+
+ if [ ${MD_PARTITIONABLE} -eq 0 ]; then
+ skip_nonewline
+ return
+ fi
+
+ local TMP_CACHE=`mktemp -p /tmp zpool.cache.XXXXXXXX`
+ test_setup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+
+ # Create a pattern to be verified during a read error.
+ local TMP_PATTERN=`pattern_create 1M 8` || fail 11
+ pattern_write ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 12
+
+ # Set soft read failure for all the vdevs to ensure we hit it.
+ for (( i=1; i<=4; i++ )); do
+ fault_set_md `nth_zpool_vdev ${POOL_NAME} md $i` read-transient
+ done
+
+ pattern_verify ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 13
+ pattern_remove ${TMP_PATTERN} || fail 14
+
+ # Clear all failure injection and sum read errors.
+ for (( i=1; i<=4; i++ )); do
+ local VDEV_FAULTY=`nth_zpool_vdev ${POOL_NAME} md $i`
+ local VDEV_ERRORS=`vdev_read_errors ${POOL_NAME} ${VDEV_FAULTY}`
+ let READ_ERRORS=${READ_ERRORS}+${VDEV_ERRORS}
+ fault_clear_md ${VDEV_FAULTY}
+ done
+
+ # Soft errors will not be logged to 'zpool status'.
+ test ${READ_ERRORS} -eq 0 || fail 15
+
+ # Soft errors will still generate an EIO (5) event.
+ test `zpool_event "zfs.io" "zio_err"` = "0x5" || fail 16
+
+ test_cleanup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+ pass_nonewline
+}
+
+# Soft read error.
+test_4() {
+ test_read_soft tank lo-faulty-raid0 0
+ test_read_soft tank lo-faulty-raid10 1
+ test_read_soft tank lo-faulty-raidz 1
+ test_read_soft tank lo-faulty-raidz2 1
+ test_read_soft tank lo-faulty-raidz3 1
+ echo
+}
+run_test 4 "soft read error"
+
+test_read_hard() {
+ local POOL_NAME=$1
+ local POOL_CONFIG=$2
+ local POOL_REDUNDANT=$3
+ local ZVOL_NAME="zvol"
+ local ZVOL_DEVICE="/dev/${POOL_NAME}/${ZVOL_NAME}"
+ local READ_ERRORS=0
+
+ if [ ${MD_PARTITIONABLE} -eq 0 ]; then
+ skip_nonewline
+ return
+ fi
+
+ local TMP_CACHE=`mktemp -p /tmp zpool.cache.XXXXXXXX`
+ test_setup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+
+ # Create a pattern to be verified during a read error.
+ local TMP_PATTERN=`pattern_create 1M 8` || fail 11
+ pattern_write ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 12
+
+ # Set hard read failure for the fourth vdev.
+ local VDEV_FAULTY=`nth_zpool_vdev ${POOL_NAME} md 4`
+ fault_set_md ${VDEV_FAULTY} read-persistent
+
+ # For a redundant pool there must be no IO error, for a non-redundant
+ # pool we expect permanent damage and an IO error during verify, unless
+ # we get exceptionally lucky and have just damaged redundant metadata.
+ if [ ${POOL_REDUNDANT} -eq 1 ]; then
+ pattern_verify ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 21
+ local READ_ERRORS=`vdev_read_errors ${POOL_NAME} ${VDEV_FAULTY}`
+ test ${READ_ERRORS} -eq 0 || fail 22
+ else
+ pattern_verify ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE}
+ ${ZPOOL} scrub ${POOL_NAME} || fail 32
+ local READ_ERRORS=`vdev_read_errors ${POOL_NAME} ${VDEV_FAULTY}`
+ test ${READ_ERRORS} -gt 0 || fail 33
+ ${ZPOOL} status -v ${POOL_NAME} | \
+ grep -A8 "Permanent errors" | \
+ grep -q "${POOL_NAME}" || fail 34
+ fi
+ pattern_remove ${TMP_PATTERN} || fail 41
+
+ # Clear all failure injection and sum read errors.
+ fault_clear_md ${VDEV_FAULTY}
+
+ # Hard errors will generate an EIO (5) event.
+ test `zpool_event "zfs.io" "zio_err"` = "0x5" || fail 42
+
+ test_cleanup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+ pass_nonewline
+}
+
+# Hard read error.
+test_5() {
+ test_read_hard tank lo-faulty-raid0 0
+ test_read_hard tank lo-faulty-raid10 1
+ test_read_hard tank lo-faulty-raidz 1
+ test_read_hard tank lo-faulty-raidz2 1
+ test_read_hard tank lo-faulty-raidz3 1
+ echo
+}
+run_test 5 "hard read error"
+
+# Fixable read error.
+test_read_fixable() {
+ local POOL_NAME=$1
+ local POOL_CONFIG=$2
+ local POOL_REDUNDANT=$3
+ local ZVOL_NAME="zvol"
+ local ZVOL_DEVICE="/dev/${POOL_NAME}/${ZVOL_NAME}"
+ local READ_ERRORS=0
+
+ if [ ${MD_PARTITIONABLE} -eq 0 ]; then
+ skip_nonewline
+ return
+ fi
+
+ local TMP_CACHE=`mktemp -p /tmp zpool.cache.XXXXXXXX`
+ test_setup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+
+ # Create a pattern to be verified during a read error.
+ local TMP_PATTERN=`pattern_create 1M 8` || fail 11
+ pattern_write ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 12
+
+ # Set hard read failure for the fourth vdev.
+ local VDEV_FAULTY=`nth_zpool_vdev ${POOL_NAME} md 4`
+ fault_set_md ${VDEV_FAULTY} read-fixable
+
+ # For a redundant pool there must be no IO error, for a non-redundant
+ # pool we expect permanent damage and an IO error during verify, unless
+ # we get exceptionally lucky and have just damaged redundant metadata.
+ if [ ${POOL_REDUNDANT} -eq 1 ]; then
+ pattern_verify ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 21
+ local READ_ERRORS=`vdev_read_errors ${POOL_NAME} ${VDEV_FAULTY}`
+ test ${READ_ERRORS} -eq 0 || fail 22
+ else
+ pattern_verify ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE}
+ ${ZPOOL} scrub ${POOL_NAME} || fail 32
+ local READ_ERRORS=`vdev_read_errors ${POOL_NAME} ${VDEV_FAULTY}`
+ test ${READ_ERRORS} -gt 0 || fail 33
+ ${ZPOOL} status -v ${POOL_NAME} | \
+ grep -A8 "Permanent errors" | \
+ grep -q "${POOL_NAME}" || fail 34
+ fi
+ pattern_remove ${TMP_PATTERN} || fail 41
+
+ # Clear all failure injection and sum read errors.
+ fault_clear_md ${VDEV_FAULTY}
+
+ # Hard errors will generate an EIO (5) event.
+ test `zpool_event "zfs.io" "zio_err"` = "0x5" || fail 42
+
+ test_cleanup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+ pass_nonewline
+}
+
+# Read errors fixable with a write.
+test_6() {
+ test_read_fixable tank lo-faulty-raid0 0
+ test_read_fixable tank lo-faulty-raid10 1
+ test_read_fixable tank lo-faulty-raidz 1
+ test_read_fixable tank lo-faulty-raidz2 1
+ test_read_fixable tank lo-faulty-raidz3 1
+ echo
+}
+run_test 6 "fixable read error"
+
+test_cksum() {
+ local POOL_NAME=$1
+ local POOL_CONFIG=$2
+ local POOL_REDUNDANT=$3
+ local VDEV_DAMAGE="$4"
+ local ZVOL_NAME="zvol"
+ local ZVOL_DEVICE="/dev/${POOL_NAME}/${ZVOL_NAME}"
+
+ if [ ${MD_PARTITIONABLE} -eq 0 ]; then
+ skip_nonewline
+ return
+ fi
+
+ local TMP_CACHE=`mktemp -p /tmp zpool.cache.XXXXXXXX`
+ test_setup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+
+ # Create a pattern to be verified.
+ local TMP_PATTERN=`pattern_create 1M 8` || fail 11
+ pattern_write ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 12
+
+ # Verify the pattern and that no vdev has cksum errors.
+ pattern_verify ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 13
+ for (( i=1; i<4; i++ )); do
+ VDEV_FAULTY=`nth_zpool_vdev ${POOL_NAME} md ${i}`
+ CKSUM_ERRORS=`vdev_cksum_errors ${POOL_NAME} ${VDEV_FAULTY}`
+ test ${CKSUM_ERRORS} -eq 0 || fail 14
+ done
+
+ # Corrupt the bulk of a vdev with random garbage, we damage as many
+ # vdevs as we have levels of redundancy. For example for a raidz3
+ # configuration we can trash 3 vdevs and still expect correct data.
+ # This improves the odds that we read one of the damaged vdevs.
+ for VDEV in ${VDEV_DAMAGE}; do
+ VDEV_FAULTY=`nth_zpool_vdev ${POOL_NAME} md $VDEV`
+ pattern_write /dev/urandom 1M 64 /dev/${VDEV_FAULTY}p1
+ done
+
+ # Verify the pattern is still correct. For non-redundant pools
+ # expect failure and for redundant pools success due to resilvering.
+ if [ ${POOL_REDUNDANT} -eq 1 ]; then
+ pattern_verify ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 16
+ else
+ pattern_verify ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} && fail 17
+ fi
+
+ CKSUM_ERRORS=`vdev_cksum_errors ${POOL_NAME} ${VDEV_FAULTY}`
+ test ${CKSUM_ERRORS} -gt 0 || fail 18
+ STATUS=`vdev_status ${POOL_NAME} ${VDEV_FAULTY}`
+ test "${STATUS}" = "ONLINE" || fail 19
+
+ # The checksum errors must be logged as an event.
+ local CKSUM_ERRORS=`zpool_event "zfs.checksum" "zio_err"`
+ test ${CKSUM_ERRORS} = "0x34" || test ${CKSUM_ERRORS} = "0x0" || fail 20
+
+ # Verify permant errors for non-redundant pools, and for redundant
+ # pools trigger a scrub and check that all checksums have been fixed.
+ if [ ${POOL_REDUNDANT} -eq 1 ]; then
+ # Scrub the checksum errors and clear the faults.
+ ${ZPOOL} scrub ${POOL_NAME} || fail 21
+ sleep 3
+ ${ZPOOL} clear ${POOL_NAME} || fail 22
+
+ # Re-verify the pattern for fixed checksums.
+ pattern_verify ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 23
+ CKSUM_ERRORS=`vdev_cksum_errors ${POOL_NAME} ${VDEV_FAULTY}`
+ test ${CKSUM_ERRORS} -eq 0 || fail 24
+
+ # Re-verify the entire pool for fixed checksums.
+ ${ZPOOL} scrub ${POOL_NAME} || fail 25
+ CKSUM_ERRORS=`vdev_cksum_errors ${POOL_NAME} ${VDEV_FAULTY}`
+ test ${CKSUM_ERRORS} -eq 0 || fail 26
+ else
+ ${ZPOOL} status -v ${POOL_NAME} | \
+ grep -A8 "Permanent errors" | \
+ grep -q "${POOL_NAME}/${ZVOL_NAME}" || fail 31
+ ${ZPOOL} clear ${POOL_NAME} || fail 32
+ fi
+ pattern_remove ${TMP_PATTERN} || fail 41
+
+ test_cleanup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+ pass_nonewline
+}
+
+# Silent data corruption
+test_7() {
+ test_cksum tank lo-faulty-raid0 0 "1"
+ test_cksum tank lo-faulty-raid10 1 "1 3"
+ test_cksum tank lo-faulty-raidz 1 "4"
+ test_cksum tank lo-faulty-raidz2 1 "3 4"
+ test_cksum tank lo-faulty-raidz3 1 "2 3 4"
+ echo
+}
+run_test 7 "silent data corruption"
+
+# Soft write timeout at the scsi device layer.
+test_write_timeout_soft() {
+ local POOL_NAME=$1
+ local POOL_CONFIG=$2
+ local POOL_REDUNDANT=$3
+ local POOL_NTH=$4
+ local ZVOL_NAME="zvol"
+ local ZVOL_DEVICE="/dev/${POOL_NAME}/${ZVOL_NAME}"
+
+ if [ ${SCSI_DEBUG} -eq 0 ]; then
+ skip_nonewline
+ return
+ fi
+
+ local TMP_CACHE=`mktemp -p /tmp zpool.cache.XXXXXXXX`
+ test_setup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+
+ # Set timeout(0x4) for every nth command.
+ fault_set_sd 4 ${POOL_NTH}
+
+ # The application must not observe an error.
+ local TMP_PATTERN=`pattern_create 1M 8` || fail 11
+ pattern_write ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 12
+ fault_clear_sd
+
+ # Intermittent write timeouts even with FAILFAST set may not cause
+ # an EIO (5) event. This is because how FAILFAST is handled depends
+ # a log on the low level driver and the exact nature of the failure.
+ # We will however see a 'zfs.delay' event logged due to the timeout.
+ VDEV_DELAY=`zpool_event "zfs.delay" "zio_delay"`
+ test `printf "%d" ${VDEV_DELAY}` -ge 30000 || fail 13
+
+ # Verify the known pattern.
+ pattern_verify ${TMP_PATTERN} 1M 8 ${ZVOL_DEVICE} || fail 14
+ pattern_remove ${TMP_PATTERN} || fail 15
+
+ test_cleanup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+ pass_nonewline
+}
+
+test_8() {
+ test_write_timeout_soft tank scsi_debug-raid0 0 50
+ test_write_timeout_soft tank scsi_debug-raid10 1 100
+ test_write_timeout_soft tank scsi_debug-raidz 1 75
+ test_write_timeout_soft tank scsi_debug-raidz2 1 150
+ test_write_timeout_soft tank scsi_debug-raidz3 1 300
+ echo
+}
+run_test 8 "soft write timeout"
+
+# Persistent write timeout at the scsi device layer.
+test_write_timeout_hard() {
+ local POOL_NAME=$1
+ local POOL_CONFIG=$2
+ local POOL_REDUNDANT=$3
+ local POOL_NTH=$4
+ local ZVOL_NAME="zvol"
+ local ZVOL_DEVICE="/dev/${POOL_NAME}/${ZVOL_NAME}"
+ local RESCAN=1
+
+ if [ ${SCSI_DEBUG} -eq 0 ]; then
+ skip_nonewline
+ return
+ fi
+
+ local TMP_CACHE=`mktemp -p /tmp zpool.cache.XXXXXXXX`
+ test_setup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+
+ local TMP_PATTERN1=`pattern_create 1M 8`
+ local TMP_PATTERN2=`pattern_create 1M 8`
+ local TMP_PATTERN3=`pattern_create 1M 8`
+
+ # Create three partitions each one gets a unique pattern. The first
+ # pattern is written before the failure, the second pattern during
+ # the failure, and the third pattern while the vdev is degraded.
+ # All three patterns are verified while the vdev is degraded and
+ # then again once it is brought back online.
+ ${PARTED} -s ${ZVOL_DEVICE} mklabel gpt || fail 11
+ ${PARTED} -s ${ZVOL_DEVICE} mkpart primary 1M 16M || fail 12
+ ${PARTED} -s ${ZVOL_DEVICE} mkpart primary 16M 32M || fail 13
+ ${PARTED} -s ${ZVOL_DEVICE} mkpart primary 32M 48M || fail 14
+
+ wait_udev ${ZVOL_DEVICE}1 30
+ wait_udev ${ZVOL_DEVICE}2 30
+ wait_udev ${ZVOL_DEVICE}3 30
+
+ # Before the failure.
+ pattern_write ${TMP_PATTERN1} 1M 8 ${ZVOL_DEVICE}1 || fail 15
+
+ # Get the faulty vdev name.
+ local VDEV_FAULTY=`nth_zpool_vdev ${POOL_NAME} sd 1`
+
+ # Set timeout(0x4) for every nth command.
+ fault_set_sd 4 ${POOL_NTH}
+
+ # During the failure.
+ pattern_write ${TMP_PATTERN2} 1M 8 ${ZVOL_DEVICE}2 || fail 21
+
+ # Expect write errors to be logged to 'zpool status'
+ local WRITE_ERRORS=`vdev_write_errors ${POOL_NAME} ${VDEV_FAULTY}`
+ test ${WRITE_ERRORS} -gt 0 || fail 22
+
+ local VDEV_STATUS=`vdev_status ${POOL_NAME} ${VDEV_FAULTY}`
+ test "${VDEV_STATUS}" = "UNAVAIL" || fail 23
+
+ # Clear the error and remove it from /dev/.
+ fault_clear_sd
+ rm -f /dev/${VDEV_FAULTY}[0-9]
+
+ # Verify the first two patterns and write out the third.
+ pattern_write ${TMP_PATTERN3} 1M 8 ${ZVOL_DEVICE}3 || fail 31
+ pattern_verify ${TMP_PATTERN1} 1M 8 ${ZVOL_DEVICE}1 || fail 32
+ pattern_verify ${TMP_PATTERN2} 1M 8 ${ZVOL_DEVICE}2 || fail 33
+ pattern_verify ${TMP_PATTERN3} 1M 8 ${ZVOL_DEVICE}3 || fail 34
+
+ # Bring the device back online by rescanning for it. It must appear
+ # in lsscsi and be available to dd before allowing ZFS to bring it
+ # online. This is not required but provides additional sanity.
+ while [ ${RESCAN} -eq 1 ]; do
+ scsi_rescan
+ wait_udev /dev/${VDEV_FAULTY} 30
+
+ if [ `${LSSCSI} | grep -c "/dev/${VDEV_FAULTY}"` -eq 0 ]; then
+ continue
+ fi
+
+ dd if=/dev/${VDEV_FAULTY} of=/dev/null bs=8M count=1 &>/dev/null
+ if [ $? -ne 0 ]; then
+ continue
+ fi
+
+ RESCAN=0
+ done
+
+ # Bring the device back online. We expect it to be automatically
+ # resilvered without error and we should see minimally the zfs.io,
+ # zfs.statechange (VDEV_STATE_HEALTHY (0x7)), and zfs.resilver.*
+ # events posted.
+ ${ZPOOL} online ${POOL_NAME} ${VDEV_FAULTY}1 || fail 51
+ sleep 3
+ test `zpool_event "zfs.io" "zio_err"` = "0x5" || fail 52
+ test `zpool_event "zfs.statechange" "vdev_state"` = "0x7" || fail 53
+ test `zpool_event "zfs.resilver.start" "ena"` != "" || fail 54
+ test `zpool_event "zfs.resilver.finish" "ena"` != "" || fail 55
+ test `zpool_scan_errors ${POOL_NAME}` -eq 0 || fail 56
+
+ local VDEV_STATUS=`vdev_status ${POOL_NAME} ${VDEV_FAULTY}`
+ test "${VDEV_STATUS}" = "ONLINE" || fail 57
+
+ # Verify the known pattern.
+ pattern_verify ${TMP_PATTERN1} 1M 8 ${ZVOL_DEVICE}1 || fail 61
+ pattern_verify ${TMP_PATTERN2} 1M 8 ${ZVOL_DEVICE}2 || fail 62
+ pattern_verify ${TMP_PATTERN3} 1M 8 ${ZVOL_DEVICE}3 || fail 63
+ pattern_remove ${TMP_PATTERN1} || fail 64
+ pattern_remove ${TMP_PATTERN2} || fail 65
+ pattern_remove ${TMP_PATTERN3} || fail 66
+
+ test_cleanup ${POOL_NAME} ${POOL_CONFIG} ${ZVOL_NAME} ${TMP_CACHE}
+ pass_nonewline
+}
+
+test_9() {
+ skip_nonewline # Skip non-redundant config
+ test_write_timeout_hard tank scsi_debug-raid10 1 -50
+ test_write_timeout_hard tank scsi_debug-raidz 1 -50
+ test_write_timeout_hard tank scsi_debug-raidz2 1 -50
+ test_write_timeout_hard tank scsi_debug-raidz3 1 -50
+ echo
+}
+run_test 9 "hard write timeout"
+
+exit 0
diff --git a/scripts/zpool-config/Makefile.am b/scripts/zpool-config/Makefile.am
index 0c7e0714b..5af373bec 100644
--- a/scripts/zpool-config/Makefile.am
+++ b/scripts/zpool-config/Makefile.am
@@ -1,31 +1,42 @@
pkglibexecdir = $(libexecdir)/@PACKAGE@/zpool-config
dist_pkglibexec_SCRIPTS = \
- $(top_srcdir)/scripts/zpool-config/dm0-raid0.sh \
- $(top_srcdir)/scripts/zpool-config/dragon-raid0-1x70.sh \
- $(top_srcdir)/scripts/zpool-config/dragon-raid10-35x2.sh \
- $(top_srcdir)/scripts/zpool-config/dragon-raidz2-7x10.sh \
- $(top_srcdir)/scripts/zpool-config/dragon-raidz-7x10.sh \
- $(top_srcdir)/scripts/zpool-config/file-raid0.sh \
- $(top_srcdir)/scripts/zpool-config/file-raid10.sh \
- $(top_srcdir)/scripts/zpool-config/file-raidz2.sh \
- $(top_srcdir)/scripts/zpool-config/file-raidz.sh \
- $(top_srcdir)/scripts/zpool-config/hda-raid0.sh \
- $(top_srcdir)/scripts/zpool-config/lo-raid0.sh \
- $(top_srcdir)/scripts/zpool-config/lo-raid10.sh \
- $(top_srcdir)/scripts/zpool-config/lo-raidz2.sh \
- $(top_srcdir)/scripts/zpool-config/lo-raidz.sh \
- $(top_srcdir)/scripts/zpool-config/md0-raid10.sh \
- $(top_srcdir)/scripts/zpool-config/md0-raid5.sh \
- $(top_srcdir)/scripts/zpool-config/ram0-raid0.sh \
- $(top_srcdir)/scripts/zpool-config/sda-raid0.sh \
- $(top_srcdir)/scripts/zpool-config/supermicro-raid0-1x16.sh \
- $(top_srcdir)/scripts/zpool-config/supermicro-raid10-8x2.sh \
- $(top_srcdir)/scripts/zpool-config/supermicro-raidz2-4x4.sh \
- $(top_srcdir)/scripts/zpool-config/supermicro-raidz-4x4.sh \
- $(top_srcdir)/scripts/zpool-config/x4550-raid0-1x48.sh \
- $(top_srcdir)/scripts/zpool-config/x4550-raid10-24x2.sh \
- $(top_srcdir)/scripts/zpool-config/x4550-raidz2-8x6.sh \
- $(top_srcdir)/scripts/zpool-config/x4550-raidz-8x6.sh
+ $(top_srcdir)/scripts/zpool-config/dm0-raid0.sh \
+ $(top_srcdir)/scripts/zpool-config/dragon-raid0-1x70.sh \
+ $(top_srcdir)/scripts/zpool-config/dragon-raid10-35x2.sh \
+ $(top_srcdir)/scripts/zpool-config/dragon-raidz2-7x10.sh \
+ $(top_srcdir)/scripts/zpool-config/dragon-raidz-7x10.sh \
+ $(top_srcdir)/scripts/zpool-config/file-raid0.sh \
+ $(top_srcdir)/scripts/zpool-config/file-raid10.sh \
+ $(top_srcdir)/scripts/zpool-config/file-raidz2.sh \
+ $(top_srcdir)/scripts/zpool-config/file-raidz.sh \
+ $(top_srcdir)/scripts/zpool-config/hda-raid0.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-raid0.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-raid10.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-raidz2.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-raidz.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-faulty-raid0.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-faulty-raid10.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-faulty-raidz.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-faulty-raidz2.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-faulty-raidz3.sh \
+ $(top_srcdir)/scripts/zpool-config/md0-raid10.sh \
+ $(top_srcdir)/scripts/zpool-config/md0-raid5.sh \
+ $(top_srcdir)/scripts/zpool-config/ram0-raid0.sh \
+ $(top_srcdir)/scripts/zpool-config/scsi_debug-noraid.sh \
+ $(top_srcdir)/scripts/zpool-config/scsi_debug-raid0.sh \
+ $(top_srcdir)/scripts/zpool-config/scsi_debug-raid10.sh \
+ $(top_srcdir)/scripts/zpool-config/scsi_debug-raidz.sh \
+ $(top_srcdir)/scripts/zpool-config/scsi_debug-raidz2.sh \
+ $(top_srcdir)/scripts/zpool-config/scsi_debug-raidz3.sh \
+ $(top_srcdir)/scripts/zpool-config/sda-raid0.sh \
+ $(top_srcdir)/scripts/zpool-config/supermicro-raid0-1x16.sh \
+ $(top_srcdir)/scripts/zpool-config/supermicro-raid10-8x2.sh \
+ $(top_srcdir)/scripts/zpool-config/supermicro-raidz2-4x4.sh \
+ $(top_srcdir)/scripts/zpool-config/supermicro-raidz-4x4.sh \
+ $(top_srcdir)/scripts/zpool-config/x4550-raid0-1x48.sh \
+ $(top_srcdir)/scripts/zpool-config/x4550-raid10-24x2.sh \
+ $(top_srcdir)/scripts/zpool-config/x4550-raidz2-8x6.sh \
+ $(top_srcdir)/scripts/zpool-config/x4550-raidz-8x6.sh
all:
@list='$(dist_pkglibexec_SCRIPTS)'; \
diff --git a/scripts/zpool-config/Makefile.in b/scripts/zpool-config/Makefile.in
index a312c948c..61f54ca0a 100644
--- a/scripts/zpool-config/Makefile.in
+++ b/scripts/zpool-config/Makefile.in
@@ -273,32 +273,43 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
dist_pkglibexec_SCRIPTS = \
- $(top_srcdir)/scripts/zpool-config/dm0-raid0.sh \
- $(top_srcdir)/scripts/zpool-config/dragon-raid0-1x70.sh \
- $(top_srcdir)/scripts/zpool-config/dragon-raid10-35x2.sh \
- $(top_srcdir)/scripts/zpool-config/dragon-raidz2-7x10.sh \
- $(top_srcdir)/scripts/zpool-config/dragon-raidz-7x10.sh \
- $(top_srcdir)/scripts/zpool-config/file-raid0.sh \
- $(top_srcdir)/scripts/zpool-config/file-raid10.sh \
- $(top_srcdir)/scripts/zpool-config/file-raidz2.sh \
- $(top_srcdir)/scripts/zpool-config/file-raidz.sh \
- $(top_srcdir)/scripts/zpool-config/hda-raid0.sh \
- $(top_srcdir)/scripts/zpool-config/lo-raid0.sh \
- $(top_srcdir)/scripts/zpool-config/lo-raid10.sh \
- $(top_srcdir)/scripts/zpool-config/lo-raidz2.sh \
- $(top_srcdir)/scripts/zpool-config/lo-raidz.sh \
- $(top_srcdir)/scripts/zpool-config/md0-raid10.sh \
- $(top_srcdir)/scripts/zpool-config/md0-raid5.sh \
- $(top_srcdir)/scripts/zpool-config/ram0-raid0.sh \
- $(top_srcdir)/scripts/zpool-config/sda-raid0.sh \
- $(top_srcdir)/scripts/zpool-config/supermicro-raid0-1x16.sh \
- $(top_srcdir)/scripts/zpool-config/supermicro-raid10-8x2.sh \
- $(top_srcdir)/scripts/zpool-config/supermicro-raidz2-4x4.sh \
- $(top_srcdir)/scripts/zpool-config/supermicro-raidz-4x4.sh \
- $(top_srcdir)/scripts/zpool-config/x4550-raid0-1x48.sh \
- $(top_srcdir)/scripts/zpool-config/x4550-raid10-24x2.sh \
- $(top_srcdir)/scripts/zpool-config/x4550-raidz2-8x6.sh \
- $(top_srcdir)/scripts/zpool-config/x4550-raidz-8x6.sh
+ $(top_srcdir)/scripts/zpool-config/dm0-raid0.sh \
+ $(top_srcdir)/scripts/zpool-config/dragon-raid0-1x70.sh \
+ $(top_srcdir)/scripts/zpool-config/dragon-raid10-35x2.sh \
+ $(top_srcdir)/scripts/zpool-config/dragon-raidz2-7x10.sh \
+ $(top_srcdir)/scripts/zpool-config/dragon-raidz-7x10.sh \
+ $(top_srcdir)/scripts/zpool-config/file-raid0.sh \
+ $(top_srcdir)/scripts/zpool-config/file-raid10.sh \
+ $(top_srcdir)/scripts/zpool-config/file-raidz2.sh \
+ $(top_srcdir)/scripts/zpool-config/file-raidz.sh \
+ $(top_srcdir)/scripts/zpool-config/hda-raid0.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-raid0.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-raid10.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-raidz2.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-raidz.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-faulty-raid0.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-faulty-raid10.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-faulty-raidz.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-faulty-raidz2.sh \
+ $(top_srcdir)/scripts/zpool-config/lo-faulty-raidz3.sh \
+ $(top_srcdir)/scripts/zpool-config/md0-raid10.sh \
+ $(top_srcdir)/scripts/zpool-config/md0-raid5.sh \
+ $(top_srcdir)/scripts/zpool-config/ram0-raid0.sh \
+ $(top_srcdir)/scripts/zpool-config/scsi_debug-noraid.sh \
+ $(top_srcdir)/scripts/zpool-config/scsi_debug-raid0.sh \
+ $(top_srcdir)/scripts/zpool-config/scsi_debug-raid10.sh \
+ $(top_srcdir)/scripts/zpool-config/scsi_debug-raidz.sh \
+ $(top_srcdir)/scripts/zpool-config/scsi_debug-raidz2.sh \
+ $(top_srcdir)/scripts/zpool-config/scsi_debug-raidz3.sh \
+ $(top_srcdir)/scripts/zpool-config/sda-raid0.sh \
+ $(top_srcdir)/scripts/zpool-config/supermicro-raid0-1x16.sh \
+ $(top_srcdir)/scripts/zpool-config/supermicro-raid10-8x2.sh \
+ $(top_srcdir)/scripts/zpool-config/supermicro-raidz2-4x4.sh \
+ $(top_srcdir)/scripts/zpool-config/supermicro-raidz-4x4.sh \
+ $(top_srcdir)/scripts/zpool-config/x4550-raid0-1x48.sh \
+ $(top_srcdir)/scripts/zpool-config/x4550-raid10-24x2.sh \
+ $(top_srcdir)/scripts/zpool-config/x4550-raidz2-8x6.sh \
+ $(top_srcdir)/scripts/zpool-config/x4550-raidz-8x6.sh
all: all-am
diff --git a/scripts/zpool-config/lo-faulty-raid0.sh b/scripts/zpool-config/lo-faulty-raid0.sh
new file mode 100644
index 000000000..10b8f88bc
--- /dev/null
+++ b/scripts/zpool-config/lo-faulty-raid0.sh
@@ -0,0 +1,78 @@
+#!/bin/bash
+#
+# 4 loopback devices using the md faulty level for easy
+# fault injection on top of which is layered raid0 (striped).
+#
+# zpool-vdev0 zpool-vdev1 zpool-vdev2 zpool-vdev3
+# loop0 loop1 loop2 loop3
+# md0 (faulty) md1 (faulty) md2 (faulty) md3 (faulty)
+# <--------------------- raid0 zpool --------------------->
+#
+
+FILES="/tmp/zpool-vdev0 \
+ /tmp/zpool-vdev1 \
+ /tmp/zpool-vdev2 \
+ /tmp/zpool-vdev3"
+LODEVICES=""
+MDDEVICES=""
+
+zpool_create() {
+ check_loop_utils
+ check_md_utils
+ check_md_partitionable || die "Error non-partitionable md devices"
+
+ for FILE in ${FILES}; do
+ LODEVICE=`unused_loop_device`
+ MDDEVICE=`unused_md_device`
+
+ rm -f ${FILE} || exit 1
+ dd if=/dev/zero of=${FILE} bs=1M count=0 seek=256 \
+ &>/dev/null || die "Error $? creating ${FILE}"
+
+ # Setup the loopback device on the file.
+ msg "Creating ${LODEVICE} using ${FILE}"
+ ${LOSETUP} ${LODEVICE} ${FILE} || \
+ die "Error $? creating ${LODEVICE} using ${FILE}"
+
+ LODEVICES="${LODEVICES} ${LODEVICE}"
+
+ # Setup the md device on the loopback device.
+ msg "Creating ${MDDEVICE} using ${LODEVICE}"
+ ${MDADM} --build ${MDDEVICE} --level=faulty \
+ --raid-devices=1 ${LODEVICE} &>/dev/null || \
+ (destroy_md_devices "${MDDEVICES}" && \
+ destroy_loop_devices "${LODEVICES}" && \
+ die "Error $? creating ${MDDEVICE} using ${LODEVICE}")
+ wait_udev ${MDDEVICE} 30 || \
+ (destroy_md_devices "${MDDEVICES}" && \
+ destroy_loop_devices "${LODEVICES}" && \
+ die "Error udev never created ${MDDEVICE}")
+
+ # Check if the md device support partitions
+ ${BLOCKDEV} --rereadpt ${MDDEVICE} 2>/dev/null || \
+ (destroy_md_devices "${MDDEVICES}" && \
+ destroy_loop_devices "${LODEVICES}" && \
+ die "Error ${MDDEVICE} does not support partitions")
+
+ # Create a GPT/EFI partition table for ZFS to use.
+ ${PARTED} --script ${MDDEVICE} mklabel gpt
+ MDDEVICES="${MDDEVICES} ${MDDEVICE}"
+ done
+
+ msg ${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} ${MDDEVICES}
+ ${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} ${MDDEVICES} || \
+ (destroy_md_devices "${MDDEVICES}" && \
+ destroy_loop_devices "${LODEVICES}" && exit 1)
+
+ echo "$LODEVICES" >/tmp/zpool-lo.txt
+ echo "$MDDEVICES" >/tmp/zpool-md.txt
+}
+
+zpool_destroy() {
+ msg ${ZPOOL} destroy ${ZPOOL_NAME}
+ ${ZPOOL} destroy ${ZPOOL_NAME}
+ destroy_md_devices "`cat /tmp/zpool-md.txt`"
+ destroy_loop_devices "`cat /tmp/zpool-lo.txt`"
+
+ rm -f /tmp/zpool-md.txt /tmp/zpool-lo.txt
+}
diff --git a/scripts/zpool-config/lo-faulty-raid10.sh b/scripts/zpool-config/lo-faulty-raid10.sh
new file mode 100644
index 000000000..ef81abb9d
--- /dev/null
+++ b/scripts/zpool-config/lo-faulty-raid10.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+#
+# 4 loopback devices using the md faulty level for easy
+# fault injection on top of which is layered raid10 (mirrored).
+#
+# zpool-vdev0 zpool-vdev1 zpool-vdev2 zpool-vdev3
+# loop0 loop1 loop2 loop3
+# md0 (faulty) md1 (faulty) md2 (faulty) md3 (faulty)
+# <--------------------- raid10 zpool --------------------->
+#
+
+FILES="/tmp/zpool-vdev0 \
+ /tmp/zpool-vdev1 \
+ /tmp/zpool-vdev2 \
+ /tmp/zpool-vdev3"
+LODEVICES=""
+MDDEVICES=""
+MDDEVICES_M1=""
+MDDEVICES_M2=""
+
+zpool_create() {
+ local COUNT=0
+
+ check_loop_utils
+ check_md_utils
+ check_md_partitionable || die "Error non-partitionable md devices"
+
+ for FILE in ${FILES}; do
+ LODEVICE=`unused_loop_device`
+ MDDEVICE=`unused_md_device`
+ let COUNT=${COUNT}+1
+
+ rm -f ${FILE} || exit 1
+ dd if=/dev/zero of=${FILE} bs=1M count=0 seek=256 \
+ &>/dev/null || die "Error $? creating ${FILE}"
+
+ # Setup the loopback device on the file.
+ msg "Creating ${LODEVICE} using ${FILE}"
+ ${LOSETUP} ${LODEVICE} ${FILE} || \
+ die "Error $? creating ${LODEVICE} using ${FILE}"
+
+ LODEVICES="${LODEVICES} ${LODEVICE}"
+
+ # Setup the md device on the loopback device.
+ msg "Creating ${MDDEVICE} using ${LODEVICE}"
+ ${MDADM} --build ${MDDEVICE} --level=faulty \
+ --raid-devices=1 ${LODEVICE} &>/dev/null || \
+ (destroy_md_devices "${MDDEVICES}" && \
+ destroy_loop_devices "${LODEVICES}" && \
+ die "Error $? creating ${MDDEVICE} using ${LODEVICE}")
+ wait_udev ${MDDEVICE} 30 || \
+ (destroy_md_devices "${MDDEVICES}" && \
+ destroy_loop_devices "${LODEVICES}" && \
+ die "Error udev never created ${MDDEVICE}")
+
+ # Create empty GPT/EFI partition table.
+ ${PARTED} --script ${MDDEVICE} mklabel gpt
+ MDDEVICES="${MDDEVICES} ${MDDEVICE}"
+ if [ $((COUNT % 2)) -eq 0 ]; then
+ MDDEVICES_M2="${MDDEVICES_M2} ${MDDEVICE}"
+ else
+ MDDEVICES_M1="${MDDEVICES_M1} ${MDDEVICE}"
+ fi
+ done
+
+ msg ${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} \
+ mirror ${MDDEVICES_M1} mirror ${MDDEVICES_M2}
+ ${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} \
+ mirror ${MDDEVICES_M1} mirror ${MDDEVICES_M2} || \
+ (destroy_md_devices "${MDDEVICES}" && \
+ destroy_loop_devices "${LODEVICES}" && exit 1)
+
+ echo "$LODEVICES" >/tmp/zpool-lo.txt
+ echo "$MDDEVICES" >/tmp/zpool-md.txt
+}
+
+zpool_destroy() {
+ msg ${ZPOOL} destroy ${ZPOOL_NAME}
+ ${ZPOOL} destroy ${ZPOOL_NAME}
+ destroy_md_devices "`cat /tmp/zpool-md.txt`"
+ destroy_loop_devices "`cat /tmp/zpool-lo.txt`"
+
+ rm -f /tmp/zpool-md.txt /tmp/zpool-lo.txt
+}
diff --git a/scripts/zpool-config/lo-faulty-raidz.sh b/scripts/zpool-config/lo-faulty-raidz.sh
new file mode 100644
index 000000000..2f1f08aa6
--- /dev/null
+++ b/scripts/zpool-config/lo-faulty-raidz.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+#
+# 4 loopback devices using the md faulty level for easy
+# fault injection on top of which is layered raidz.
+#
+# zpool-vdev0 zpool-vdev1 zpool-vdev2 zpool-vdev3
+# loop0 loop1 loop2 loop3
+# md0 (faulty) md1 (faulty) md2 (faulty) md3 (faulty)
+# <--------------------- raidz zpool --------------------->
+#
+
+FILES="/tmp/zpool-vdev0 \
+ /tmp/zpool-vdev1 \
+ /tmp/zpool-vdev2 \
+ /tmp/zpool-vdev3"
+LODEVICES=""
+MDDEVICES=""
+
+zpool_create() {
+ check_loop_utils
+ check_md_utils
+ check_md_partitionable || die "Error non-partitionable md devices"
+
+ for FILE in ${FILES}; do
+ LODEVICE=`unused_loop_device`
+ MDDEVICE=`unused_md_device`
+
+ rm -f ${FILE} || exit 1
+ dd if=/dev/zero of=${FILE} bs=1M count=0 seek=256 \
+ &>/dev/null || die "Error $? creating ${FILE}"
+
+ # Setup the loopback device on the file.
+ msg "Creating ${LODEVICE} using ${FILE}"
+ ${LOSETUP} ${LODEVICE} ${FILE} || \
+ die "Error $? creating ${LODEVICE} using ${FILE}"
+
+ LODEVICES="${LODEVICES} ${LODEVICE}"
+
+ # Setup the md device on the loopback device.
+ msg "Creating ${MDDEVICE} using ${LODEVICE}"
+ ${MDADM} --build ${MDDEVICE} --level=faulty \
+ --raid-devices=1 ${LODEVICE} &>/dev/null || \
+ (destroy_md_devices "${MDDEVICES}" && \
+ destroy_loop_devices "${LODEVICES}" && \
+ die "Error $? creating ${MDDEVICE} using ${LODEVICE}")
+ wait_udev ${MDDEVICE} 30 || \
+ (destroy_md_devices "${MDDEVICES}" && \
+ destroy_loop_devices "${LODEVICES}" && \
+ die "Error udev never created ${MDDEVICE}")
+
+ # Create empty GPT/EFI partition table.
+ ${PARTED} --script ${MDDEVICE} mklabel gpt
+ MDDEVICES="${MDDEVICES} ${MDDEVICE}"
+ done
+
+ msg ${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} raidz ${MDDEVICES}
+ ${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} raidz ${MDDEVICES} || \
+ (destroy_md_devices "${MDDEVICES}" && \
+ destroy_loop_devices "${LODEVICES}" && exit 1)
+
+ echo "$LODEVICES" >/tmp/zpool-lo.txt
+ echo "$MDDEVICES" >/tmp/zpool-md.txt
+}
+
+zpool_destroy() {
+ msg ${ZPOOL} destroy ${ZPOOL_NAME}
+ ${ZPOOL} destroy ${ZPOOL_NAME}
+ destroy_md_devices "`cat /tmp/zpool-md.txt`"
+ destroy_loop_devices "`cat /tmp/zpool-lo.txt`"
+
+ rm -f /tmp/zpool-md.txt /tmp/zpool-lo.txt
+}
diff --git a/scripts/zpool-config/lo-faulty-raidz2.sh b/scripts/zpool-config/lo-faulty-raidz2.sh
new file mode 100644
index 000000000..2522fa7e7
--- /dev/null
+++ b/scripts/zpool-config/lo-faulty-raidz2.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+#
+# 4 loopback devices using the md faulty level for easy
+# fault injection on top of which is layered raidz2.
+#
+# zpool-vdev0 zpool-vdev1 zpool-vdev2 zpool-vdev3
+# loop0 loop1 loop2 loop3
+# md0 (faulty) md1 (faulty) md2 (faulty) md3 (faulty)
+# <--------------------- raidz2 zpool -------------------->
+#
+
+FILES="/tmp/zpool-vdev0 \
+ /tmp/zpool-vdev1 \
+ /tmp/zpool-vdev2 \
+ /tmp/zpool-vdev3"
+LODEVICES=""
+MDDEVICES=""
+
+zpool_create() {
+ check_loop_utils
+ check_md_utils
+ check_md_partitionable || die "Error non-partitionable md devices"
+
+ for FILE in ${FILES}; do
+ LODEVICE=`unused_loop_device`
+ MDDEVICE=`unused_md_device`
+
+ rm -f ${FILE} || exit 1
+ dd if=/dev/zero of=${FILE} bs=1M count=0 seek=256 \
+ &>/dev/null || die "Error $? creating ${FILE}"
+
+ # Setup the loopback device on the file.
+ msg "Creating ${LODEVICE} using ${FILE}"
+ ${LOSETUP} ${LODEVICE} ${FILE} || \
+ die "Error $? creating ${LODEVICE} using ${FILE}"
+
+ LODEVICES="${LODEVICES} ${LODEVICE}"
+
+ # Setup the md device on the loopback device.
+ msg "Creating ${MDDEVICE} using ${LODEVICE}"
+ ${MDADM} --build ${MDDEVICE} --level=faulty \
+ --raid-devices=1 ${LODEVICE} &>/dev/null || \
+ (destroy_md_devices "${MDDEVICES}" && \
+ destroy_loop_devices "${LODEVICES}" && \
+ die "Error $? creating ${MDDEVICE} using ${LODEVICE}")
+ wait_udev ${MDDEVICE} 30 || \
+ (destroy_md_devices "${MDDEVICES}" && \
+ destroy_loop_devices "${LODEVICES}" && \
+ die "Error udev never created ${MDDEVICE}")
+
+ # Create empty GPT/EFI partition table.
+ ${PARTED} --script ${MDDEVICE} mklabel gpt
+ MDDEVICES="${MDDEVICES} ${MDDEVICE}"
+ done
+
+ msg ${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} raidz2 ${MDDEVICES}
+ ${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} raidz2 ${MDDEVICES} || \
+ (destroy_md_devices "${MDDEVICES}" && \
+ destroy_loop_devices "${LODEVICES}" && exit 1)
+
+ echo "$LODEVICES" >/tmp/zpool-lo.txt
+ echo "$MDDEVICES" >/tmp/zpool-md.txt
+}
+
+zpool_destroy() {
+ msg ${ZPOOL} destroy ${ZPOOL_NAME}
+ ${ZPOOL} destroy ${ZPOOL_NAME}
+ destroy_md_devices "`cat /tmp/zpool-md.txt`"
+ destroy_loop_devices "`cat /tmp/zpool-lo.txt`"
+
+ rm -f /tmp/zpool-md.txt /tmp/zpool-lo.txt
+}
diff --git a/scripts/zpool-config/lo-faulty-raidz3.sh b/scripts/zpool-config/lo-faulty-raidz3.sh
new file mode 100644
index 000000000..e5adaafc4
--- /dev/null
+++ b/scripts/zpool-config/lo-faulty-raidz3.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+#
+# 4 loopback devices using the md faulty level for easy
+# fault injection on top of which is layered raidz3.
+#
+# zpool-vdev0 zpool-vdev1 zpool-vdev2 zpool-vdev3
+# loop0 loop1 loop2 loop3
+# md0 (faulty) md1 (faulty) md2 (faulty) md3 (faulty)
+# <--------------------- raidz3 zpool -------------------->
+#
+
+FILES="/tmp/zpool-vdev0 \
+ /tmp/zpool-vdev1 \
+ /tmp/zpool-vdev2 \
+ /tmp/zpool-vdev3"
+LODEVICES=""
+MDDEVICES=""
+
+zpool_create() {
+ check_loop_utils
+ check_md_utils
+ check_md_partitionable || die "Error non-partitionable md devices"
+
+ for FILE in ${FILES}; do
+ LODEVICE=`unused_loop_device`
+ MDDEVICE=`unused_md_device`
+
+ rm -f ${FILE} || exit 1
+ dd if=/dev/zero of=${FILE} bs=1M count=0 seek=256 \
+ &>/dev/null || die "Error $? creating ${FILE}"
+
+ # Setup the loopback device on the file.
+ msg "Creating ${LODEVICE} using ${FILE}"
+ ${LOSETUP} ${LODEVICE} ${FILE} || \
+ die "Error $? creating ${LODEVICE} using ${FILE}"
+
+ LODEVICES="${LODEVICES} ${LODEVICE}"
+
+ # Setup the md device on the loopback device.
+ msg "Creating ${MDDEVICE} using ${LODEVICE}"
+ ${MDADM} --build ${MDDEVICE} --level=faulty \
+ --raid-devices=1 ${LODEVICE} &>/dev/null || \
+ (destroy_md_devices "${MDDEVICES}" && \
+ destroy_loop_devices "${LODEVICES}" && \
+ die "Error $? creating ${MDDEVICE} using ${LODEVICE}")
+ wait_udev ${MDDEVICE} 30 || \
+ (destroy_md_devices "${MDDEVICES}" && \
+ destroy_loop_devices "${LODEVICES}" && \
+ die "Error udev never created ${MDDEVICE}")
+
+ # Create empty GPT/EFI partition table.
+ ${PARTED} --script ${MDDEVICE} mklabel gpt
+ MDDEVICES="${MDDEVICES} ${MDDEVICE}"
+ done
+
+ msg ${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} raidz3 ${MDDEVICES}
+ ${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} raidz3 ${MDDEVICES} || \
+ (destroy_md_devices "${MDDEVICES}" && \
+ destroy_loop_devices "${LODEVICES}" && exit 1)
+
+ echo "$LODEVICES" >/tmp/zpool-lo.txt
+ echo "$MDDEVICES" >/tmp/zpool-md.txt
+}
+
+zpool_destroy() {
+ msg ${ZPOOL} destroy ${ZPOOL_NAME}
+ ${ZPOOL} destroy ${ZPOOL_NAME}
+ destroy_md_devices "`cat /tmp/zpool-md.txt`"
+ destroy_loop_devices "`cat /tmp/zpool-lo.txt`"
+
+ rm -f /tmp/zpool-md.txt /tmp/zpool-lo.txt
+}
diff --git a/scripts/zpool-config/lo-raid0.sh b/scripts/zpool-config/lo-raid0.sh
index 321d9b1f7..f7eb77d7b 100644
--- a/scripts/zpool-config/lo-raid0.sh
+++ b/scripts/zpool-config/lo-raid0.sh
@@ -10,6 +10,8 @@ FILES="/tmp/zpool-vdev0 \
DEVICES=""
zpool_create() {
+ check_loop_utils
+
for FILE in ${FILES}; do
DEVICE=`unused_loop_device`
msg "Creating ${FILE} using loopback device ${DEVICE}"
diff --git a/scripts/zpool-config/lo-raid10.sh b/scripts/zpool-config/lo-raid10.sh
index f9c47cd1e..5350930bb 100644
--- a/scripts/zpool-config/lo-raid10.sh
+++ b/scripts/zpool-config/lo-raid10.sh
@@ -12,6 +12,8 @@ DEVICES_M1=""
DEVICES_M2=""
zpool_create() {
+ check_loop_utils
+
for FILE in ${FILES_M1}; do
DEVICE=`unused_loop_device`
msg "Creating ${FILE} using loopback device ${DEVICE}"
diff --git a/scripts/zpool-config/lo-raidz.sh b/scripts/zpool-config/lo-raidz.sh
index 509f6ee1d..e83e4a838 100644
--- a/scripts/zpool-config/lo-raidz.sh
+++ b/scripts/zpool-config/lo-raidz.sh
@@ -10,6 +10,8 @@ FILES="/tmp/zpool-vdev0 \
DEVICES=""
zpool_create() {
+ check_loop_utils
+
for FILE in ${FILES}; do
DEVICE=`unused_loop_device`
msg "Creating ${FILE} using loopback device ${DEVICE}"
diff --git a/scripts/zpool-config/lo-raidz2.sh b/scripts/zpool-config/lo-raidz2.sh
index 6e61293c0..c6381eaff 100644
--- a/scripts/zpool-config/lo-raidz2.sh
+++ b/scripts/zpool-config/lo-raidz2.sh
@@ -10,6 +10,8 @@ FILES="/tmp/zpool-vdev0 \
DEVICES=""
zpool_create() {
+ check_loop_utils
+
for FILE in ${FILES}; do
DEVICE=`unused_loop_device`
msg "Creating ${FILE} using loopback device ${DEVICE}"
diff --git a/scripts/zpool-config/scsi_debug-noraid.sh b/scripts/zpool-config/scsi_debug-noraid.sh
new file mode 100644
index 000000000..dfcf1586c
--- /dev/null
+++ b/scripts/zpool-config/scsi_debug-noraid.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+#
+# 1 scsi_debug devices on top of which is layered no raid.
+#
+
+SDSIZE=${SDSIZE:-128}
+SDHOSTS=${SDHOSTS:-1}
+SDTGTS=${SDTGTS:-1}
+SDLUNS=${SDLUNS:-1}
+LDMOD=/sbin/modprobe
+
+zpool_create() {
+ check_sd_utils
+
+ test `${LSMOD} | grep -c scsi_debug` -gt 0 && \
+ (echo 0 >/sys/module/scsi_debug/parameters/every_nth && \
+ ${RMMOD} scsi_debug || exit 1)
+ udev_trigger
+
+ msg "${LDMOD} scsi_debug dev_size_mb=${SDSIZE} " \
+ "add_host=${SDHOSTS} num_tgts=${SDTGTS} " \
+ "max_luns=${SDLUNS}"
+ ${LDMOD} scsi_debug \
+ dev_size_mb=${SDSIZE} \
+ add_host=${SDHOSTS} \
+ num_tgts=${SDTGTS} \
+ max_luns=${SDLUNS} || \
+ die "Error $? creating scsi_debug devices"
+ udev_trigger
+ SDDEVICE=`${LSSCSI}|${AWK} '/scsi_debug/ { print $6; exit }'`
+
+ msg "${PARTED} -s ${SDDEVICE} mklabel gpt"
+ ${PARTED} -s ${SDDEVICE} mklabel gpt || \
+ (${RMMOD} scsi_debug && die "Error $? creating gpt label")
+
+ msg "${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} ${SDDEVICE}"
+ ${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} ${SDDEVICE} || \
+ (${RMMOD} scsi_debug && exit 1)
+}
+
+zpool_destroy() {
+ msg ${ZPOOL} destroy ${ZPOOL_NAME}
+ ${ZPOOL} destroy ${ZPOOL_NAME}
+ msg "${RMMOD} scsi_debug"
+ ${RMMOD} scsi_debug || die "Error $? removing scsi_debug devices"
+}
diff --git a/scripts/zpool-config/scsi_debug-raid0.sh b/scripts/zpool-config/scsi_debug-raid0.sh
new file mode 100644
index 000000000..797ea8019
--- /dev/null
+++ b/scripts/zpool-config/scsi_debug-raid0.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+#
+# 1 scsi_debug device for fault injection and 3 loopback devices
+# on top of which is layered raid0 (striped).
+#
+
+SDSIZE=${SDSIZE:-256}
+SDHOSTS=${SDHOSTS:-1}
+SDTGTS=${SDTGTS:-1}
+SDLUNS=${SDLUNS:-1}
+LDMOD=/sbin/modprobe
+FILES="/tmp/zpool-vdev0 \
+ /tmp/zpool-vdev1 \
+ /tmp/zpool-vdev2"
+DEVICES=""
+
+zpool_create() {
+ check_loop_utils
+ check_sd_utils
+
+ test `${LSMOD} | grep -c scsi_debug` -gt 0 && \
+ (echo 0 >/sys/module/scsi_debug/parameters/every_nth && \
+ ${RMMOD} scsi_debug || exit 1)
+ udev_trigger
+
+ msg "${LDMOD} scsi_debug dev_size_mb=${SDSIZE} " \
+ "add_host=${SDHOSTS} num_tgts=${SDTGTS} " \
+ "max_luns=${SDLUNS}"
+ ${LDMOD} scsi_debug \
+ dev_size_mb=${SDSIZE} \
+ add_host=${SDHOSTS} \
+ num_tgts=${SDTGTS} \
+ max_luns=${SDLUNS} || \
+ die "Error $? creating scsi_debug devices"
+ udev_trigger
+
+ SDDEVICE=`${LSSCSI} | ${AWK} '/scsi_debug/ { print $6; exit }'`
+ msg "${PARTED} -s ${SDDEVICE} mklabel gpt"
+ ${PARTED} -s ${SDDEVICE} mklabel gpt || \
+ (${RMMOD} scsi_debug && die "Error $? creating gpt label")
+
+ for FILE in ${FILES}; do
+ LODEVICE=`unused_loop_device`
+
+ rm -f ${FILE} || exit 1
+ dd if=/dev/zero of=${FILE} bs=1024k count=0 seek=256 \
+ &>/dev/null || (${RMMOD} scsi_debug && \
+ die "Error $? creating ${FILE}")
+
+ # Setup the loopback device on the file.
+ msg "Creating ${LODEVICE} using ${FILE}"
+ ${LOSETUP} ${LODEVICE} ${FILE} || (${RMMOD} scsi_debug \
+ die "Error $? creating ${LODEVICE} using ${FILE}")
+
+ DEVICES="${DEVICES} ${LODEVICE}"
+ done
+
+ DEVICES="${DEVICES} ${SDDEVICE}"
+
+ msg "${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} ${DEVICES}"
+ ${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} ${DEVICES} || \
+ (${RMMOD} scsi_debug && exit 1)
+}
+
+zpool_destroy() {
+ msg ${ZPOOL} destroy ${ZPOOL_NAME}
+ ${ZPOOL} destroy ${ZPOOL_NAME}
+
+ for FILE in ${FILES}; do
+ LODEVICE=`${LOSETUP} -a | grep ${FILE} | head -n1|cut -f1 -d:`
+ msg "Removing ${LODEVICE} using ${FILE}"
+ ${LOSETUP} -d ${LODEVICE} ||
+ die "Error $? destroying ${LODEVICE} using ${FILE}"
+ rm -f ${FILE} || exit 1
+ done
+
+ msg "${RMMOD} scsi_debug"
+ ${RMMOD} scsi_debug || die "Error $? removing scsi_debug devices"
+}
diff --git a/scripts/zpool-config/scsi_debug-raid10.sh b/scripts/zpool-config/scsi_debug-raid10.sh
new file mode 100644
index 000000000..4ec205b8b
--- /dev/null
+++ b/scripts/zpool-config/scsi_debug-raid10.sh
@@ -0,0 +1,93 @@
+#!/bin/bash
+#
+# 1 scsi_debug device for fault injection and 3 loopback devices
+# on top of which is layered raid10 (mirrored).
+#
+
+SDSIZE=${SDSIZE:-256}
+SDHOSTS=${SDHOSTS:-1}
+SDTGTS=${SDTGTS:-1}
+SDLUNS=${SDLUNS:-1}
+LDMOD=/sbin/modprobe
+FILES="/tmp/zpool-vdev0 \
+ /tmp/zpool-vdev1 \
+ /tmp/zpool-vdev2"
+DEVICES_M1=""
+DEVICES_M2=""
+
+zpool_create() {
+ local COUNT=0
+
+ check_loop_utils
+ check_sd_utils
+
+ test `${LSMOD} | grep -c scsi_debug` -gt 0 && \
+ (echo 0 >/sys/module/scsi_debug/parameters/every_nth && \
+ ${RMMOD} scsi_debug || exit 1)
+ udev_trigger
+
+ msg "${LDMOD} scsi_debug dev_size_mb=${SDSIZE} " \
+ "add_host=${SDHOSTS} num_tgts=${SDTGTS} " \
+ "max_luns=${SDLUNS}"
+ ${LDMOD} scsi_debug \
+ dev_size_mb=${SDSIZE} \
+ add_host=${SDHOSTS} \
+ num_tgts=${SDTGTS} \
+ max_luns=${SDLUNS} || \
+ die "Error $? creating scsi_debug devices"
+ udev_trigger
+ SDDEVICE=`${LSSCSI}|${AWK} '/scsi_debug/ { print $6; exit }'`
+ msg "${PARTED} -s ${SDDEVICE} mklabel gpt"
+ ${PARTED} -s ${SDDEVICE} mklabel gpt || \
+ (${RMMOD} scsi_debug && die "Error $? creating gpt label")
+
+ for FILE in ${FILES}; do
+ LODEVICE=`unused_loop_device`
+
+ rm -f ${FILE} || exit 1
+ dd if=/dev/zero of=${FILE} bs=1024k count=0 seek=256 \
+ &>/dev/null || (${RMMOD} scsi_debug && \
+ die "Error $? creating ${FILE}")
+
+ # Setup the loopback device on the file.
+ msg "Creating ${LODEVICE} using ${FILE}"
+ ${LOSETUP} ${LODEVICE} ${FILE} || (${RMMOD} scsi_debug \
+ die "Error $? creating ${LODEVICE} using ${FILE}")
+
+ DEVICES="${DEVICES} ${LODEVICE}"
+ done
+
+ DEVICES="${DEVICES} ${SDDEVICE}"
+
+ for DEVICE in ${DEVICES}; do
+ let COUNT=${COUNT}+1
+
+ if [ $((COUNT % 2)) -eq 0 ]; then
+ DEVICES_M2="${DEVICES_M2} ${DEVICE}"
+ else
+ DEVICES_M1="${DEVICES_M1} ${DEVICE}"
+ fi
+ done
+
+ msg "${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} " \
+ "mirror ${DEVICES_M1} mirror ${DEVICES_M2}"
+ ${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} \
+ mirror ${DEVICES_M1} mirror ${DEVICES_M2} || \
+ (${RMMOD} scsi_debug && exit 1)
+}
+
+zpool_destroy() {
+ msg ${ZPOOL} destroy ${ZPOOL_NAME}
+ ${ZPOOL} destroy ${ZPOOL_NAME}
+
+ for FILE in ${FILES}; do
+ LODEVICE=`${LOSETUP} -a | grep ${FILE} | head -n1|cut -f1 -d:`
+ msg "Removing ${LODEVICE} using ${FILE}"
+ ${LOSETUP} -d ${LODEVICE} ||
+ die "Error $? destroying ${LODEVICE} using ${FILE}"
+ rm -f ${FILE} || exit 1
+ done
+
+ msg "${RMMOD} scsi_debug"
+ ${RMMOD} scsi_debug || die "Error $? removing scsi_debug devices"
+}
diff --git a/scripts/zpool-config/scsi_debug-raidz.sh b/scripts/zpool-config/scsi_debug-raidz.sh
new file mode 100644
index 000000000..c811a0182
--- /dev/null
+++ b/scripts/zpool-config/scsi_debug-raidz.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+#
+# 1 scsi_debug device for fault injection and 3 loopback devices
+# on top of which is layered raidz.
+#
+
+SDSIZE=${SDSIZE:-256}
+SDHOSTS=${SDHOSTS:-1}
+SDTGTS=${SDTGTS:-1}
+SDLUNS=${SDLUNS:-1}
+LDMOD=/sbin/modprobe
+FILES="/tmp/zpool-vdev0 \
+ /tmp/zpool-vdev1 \
+ /tmp/zpool-vdev2"
+DEVICES=""
+
+zpool_create() {
+ check_loop_utils
+ check_sd_utils
+
+ test `${LSMOD} | grep -c scsi_debug` -gt 0 && \
+ (echo 0 >/sys/module/scsi_debug/parameters/every_nth && \
+ ${RMMOD} scsi_debug || exit 1)
+ udev_trigger
+
+ msg "${LDMOD} scsi_debug dev_size_mb=${SDSIZE} " \
+ "add_host=${SDHOSTS} num_tgts=${SDTGTS} " \
+ "max_luns=${SDLUNS}"
+ ${LDMOD} scsi_debug \
+ dev_size_mb=${SDSIZE} \
+ add_host=${SDHOSTS} \
+ num_tgts=${SDTGTS} \
+ max_luns=${SDLUNS} || \
+ die "Error $? creating scsi_debug devices"
+ udev_trigger
+
+ SDDEVICE=`${LSSCSI} | ${AWK} '/scsi_debug/ { print $6; exit }'`
+ msg "${PARTED} -s ${SDDEVICE} mklabel gpt"
+ ${PARTED} -s ${SDDEVICE} mklabel gpt || \
+ (${RMMOD} scsi_debug && die "Error $? creating gpt label")
+
+ for FILE in ${FILES}; do
+ LODEVICE=`unused_loop_device`
+
+ rm -f ${FILE} || exit 1
+ dd if=/dev/zero of=${FILE} bs=1024k count=0 seek=256 \
+ &>/dev/null || (${RMMOD} scsi_debug && \
+ die "Error $? creating ${FILE}")
+
+ # Setup the loopback device on the file.
+ msg "Creating ${LODEVICE} using ${FILE}"
+ ${LOSETUP} ${LODEVICE} ${FILE} || (${RMMOD} scsi_debug \
+ die "Error $? creating ${LODEVICE} using ${FILE}")
+
+ DEVICES="${DEVICES} ${LODEVICE}"
+ done
+
+ DEVICES="${DEVICES} ${SDDEVICE}"
+
+ msg "${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} raidz ${DEVICES}"
+ ${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} raidz ${DEVICES} || \
+ (${RMMOD} scsi_debug && exit 1)
+}
+
+zpool_destroy() {
+ msg ${ZPOOL} destroy ${ZPOOL_NAME}
+ ${ZPOOL} destroy ${ZPOOL_NAME}
+
+ for FILE in ${FILES}; do
+ LODEVICE=`${LOSETUP} -a | grep ${FILE} | head -n1|cut -f1 -d:`
+ msg "Removing ${LODEVICE} using ${FILE}"
+ ${LOSETUP} -d ${LODEVICE} ||
+ die "Error $? destroying ${LODEVICE} using ${FILE}"
+ rm -f ${FILE} || exit 1
+ done
+
+ msg "${RMMOD} scsi_debug"
+ ${RMMOD} scsi_debug || die "Error $? removing scsi_debug devices"
+}
diff --git a/scripts/zpool-config/scsi_debug-raidz2.sh b/scripts/zpool-config/scsi_debug-raidz2.sh
new file mode 100644
index 000000000..429a84143
--- /dev/null
+++ b/scripts/zpool-config/scsi_debug-raidz2.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+#
+# 1 scsi_debug device for fault injection and 3 loopback devices
+# on top of which is layered raidz2.
+#
+
+SDSIZE=${SDSIZE:-256}
+SDHOSTS=${SDHOSTS:-1}
+SDTGTS=${SDTGTS:-1}
+SDLUNS=${SDLUNS:-1}
+LDMOD=/sbin/modprobe
+FILES="/tmp/zpool-vdev0 \
+ /tmp/zpool-vdev1 \
+ /tmp/zpool-vdev2"
+DEVICES=""
+
+zpool_create() {
+ check_loop_utils
+ check_sd_utils
+
+ test `${LSMOD} | grep -c scsi_debug` -gt 0 && \
+ (echo 0 >/sys/module/scsi_debug/parameters/every_nth && \
+ ${RMMOD} scsi_debug || exit 1)
+ udev_trigger
+
+ msg "${LDMOD} scsi_debug dev_size_mb=${SDSIZE} " \
+ "add_host=${SDHOSTS} num_tgts=${SDTGTS} " \
+ "max_luns=${SDLUNS}"
+ ${LDMOD} scsi_debug \
+ dev_size_mb=${SDSIZE} \
+ add_host=${SDHOSTS} \
+ num_tgts=${SDTGTS} \
+ max_luns=${SDLUNS} || \
+ die "Error $? creating scsi_debug devices"
+ udev_trigger
+
+ SDDEVICE=`${LSSCSI} | ${AWK} '/scsi_debug/ { print $6; exit }'`
+ msg "${PARTED} -s ${SDDEVICE} mklabel gpt"
+ ${PARTED} -s ${SDDEVICE} mklabel gpt || \
+ (${RMMOD} scsi_debug && die "Error $? creating gpt label")
+
+ for FILE in ${FILES}; do
+ LODEVICE=`unused_loop_device`
+
+ rm -f ${FILE} || exit 1
+ dd if=/dev/zero of=${FILE} bs=1024k count=0 seek=256 \
+ &>/dev/null || (${RMMOD} scsi_debug && \
+ die "Error $? creating ${FILE}")
+
+ # Setup the loopback device on the file.
+ msg "Creating ${LODEVICE} using ${FILE}"
+ ${LOSETUP} ${LODEVICE} ${FILE} || (${RMMOD} scsi_debug \
+ die "Error $? creating ${LODEVICE} using ${FILE}")
+
+ DEVICES="${DEVICES} ${LODEVICE}"
+ done
+
+ DEVICES="${DEVICES} ${SDDEVICE}"
+
+ msg "${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} raidz2 ${DEVICES}"
+ ${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} raidz2 ${DEVICES} || \
+ (${RMMOD} scsi_debug && exit 1)
+}
+
+zpool_destroy() {
+ msg ${ZPOOL} destroy ${ZPOOL_NAME}
+ ${ZPOOL} destroy ${ZPOOL_NAME}
+
+ for FILE in ${FILES}; do
+ LODEVICE=`${LOSETUP} -a | grep ${FILE} | head -n1|cut -f1 -d:`
+ msg "Removing ${LODEVICE} using ${FILE}"
+ ${LOSETUP} -d ${LODEVICE} ||
+ die "Error $? destroying ${LODEVICE} using ${FILE}"
+ rm -f ${FILE} || exit 1
+ done
+
+ msg "${RMMOD} scsi_debug"
+ ${RMMOD} scsi_debug || die "Error $? removing scsi_debug devices"
+}
diff --git a/scripts/zpool-config/scsi_debug-raidz3.sh b/scripts/zpool-config/scsi_debug-raidz3.sh
new file mode 100644
index 000000000..34654b5a8
--- /dev/null
+++ b/scripts/zpool-config/scsi_debug-raidz3.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+#
+# 1 scsi_debug device for fault injection and 3 loopback devices
+# on top of which is layered raidz3.
+#
+
+SDSIZE=${SDSIZE:-256}
+SDHOSTS=${SDHOSTS:-1}
+SDTGTS=${SDTGTS:-1}
+SDLUNS=${SDLUNS:-1}
+LDMOD=/sbin/modprobe
+FILES="/tmp/zpool-vdev0 \
+ /tmp/zpool-vdev1 \
+ /tmp/zpool-vdev2"
+DEVICES=""
+
+zpool_create() {
+ check_loop_utils
+ check_sd_utils
+
+ test `${LSMOD} | grep -c scsi_debug` -gt 0 && \
+ (echo 0 >/sys/module/scsi_debug/parameters/every_nth && \
+ ${RMMOD} scsi_debug || exit 1)
+ udev_trigger
+
+ msg "${LDMOD} scsi_debug dev_size_mb=${SDSIZE} " \
+ "add_host=${SDHOSTS} num_tgts=${SDTGTS} " \
+ "max_luns=${SDLUNS}"
+ ${LDMOD} scsi_debug \
+ dev_size_mb=${SDSIZE} \
+ add_host=${SDHOSTS} \
+ num_tgts=${SDTGTS} \
+ max_luns=${SDLUNS} || \
+ die "Error $? creating scsi_debug devices"
+ udev_trigger
+
+ SDDEVICE=`${LSSCSI} | ${AWK} '/scsi_debug/ { print $6; exit }'`
+ msg "${PARTED} -s ${SDDEVICE} mklabel gpt"
+ ${PARTED} -s ${SDDEVICE} mklabel gpt || \
+ (${RMMOD} scsi_debug && die "Error $? creating gpt label")
+
+ for FILE in ${FILES}; do
+ LODEVICE=`unused_loop_device`
+
+ rm -f ${FILE} || exit 1
+ dd if=/dev/zero of=${FILE} bs=1024k count=0 seek=256 \
+ &>/dev/null || (${RMMOD} scsi_debug && \
+ die "Error $? creating ${FILE}")
+
+ # Setup the loopback device on the file.
+ msg "Creating ${LODEVICE} using ${FILE}"
+ ${LOSETUP} ${LODEVICE} ${FILE} || (${RMMOD} scsi_debug \
+ die "Error $? creating ${LODEVICE} using ${FILE}")
+
+ DEVICES="${DEVICES} ${LODEVICE}"
+ done
+
+ DEVICES="${DEVICES} ${SDDEVICE}"
+
+ msg "${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} raidz3 ${DEVICES}"
+ ${ZPOOL} create ${FORCE_FLAG} ${ZPOOL_NAME} raidz3 ${DEVICES} || \
+ (${RMMOD} scsi_debug && exit 1)
+}
+
+zpool_destroy() {
+ msg ${ZPOOL} destroy ${ZPOOL_NAME}
+ ${ZPOOL} destroy ${ZPOOL_NAME}
+
+ for FILE in ${FILES}; do
+ LODEVICE=`${LOSETUP} -a | grep ${FILE} | head -n1|cut -f1 -d:`
+ msg "Removing ${LODEVICE} using ${FILE}"
+ ${LOSETUP} -d ${LODEVICE} ||
+ die "Error $? destroying ${LODEVICE} using ${FILE}"
+ rm -f ${FILE} || exit 1
+ done
+
+ msg "${RMMOD} scsi_debug"
+ ${RMMOD} scsi_debug || die "Error $? removing scsi_debug devices"
+}