]>
Commit | Line | Data |
---|---|---|
c9c0d073 BB |
1 | #!/bin/bash |
2 | # | |
6283f55e | 3 | # Common support functions for testing scripts. If a script-config |
c9c0d073 | 4 | # files is available it will be sourced so in-tree kernel modules and |
6283f55e | 5 | # utilities will be used. If no script-config can be found then the |
c9c0d073 BB |
6 | # installed kernel modules and utilities will be used. |
7 | ||
8 | basedir="$(dirname $0)" | |
9 | ||
6283f55e | 10 | SCRIPT_CONFIG=zfs-script-config.sh |
c9c0d073 BB |
11 | if [ -f "${basedir}/../${SCRIPT_CONFIG}" ]; then |
12 | . "${basedir}/../${SCRIPT_CONFIG}" | |
13 | else | |
cf47fad6 | 14 | KERNEL_MODULES=(zlib_deflate zlib_inflate) |
0b04990a | 15 | MODULES=(spl splat zavl znvpair zunicode zcommon icp zfs) |
c9c0d073 BB |
16 | fi |
17 | ||
18 | PROG="<define PROG>" | |
19 | CLEANUP= | |
20 | VERBOSE= | |
21 | VERBOSE_FLAG= | |
22 | FORCE= | |
23 | FORCE_FLAG= | |
c9c0d073 BB |
24 | ERROR= |
25 | RAID0S=() | |
26 | RAID10S=() | |
27 | RAIDZS=() | |
28 | RAIDZ2S=() | |
325f0235 BB |
29 | TESTS_RUN=${TESTS_RUN:-'*'} |
30 | TESTS_SKIP=${TESTS_SKIP:-} | |
c9c0d073 BB |
31 | |
32 | prefix=@prefix@ | |
33 | exec_prefix=@exec_prefix@ | |
48c028f5 | 34 | pkgdatadir=@datarootdir@/@PACKAGE@ |
c9c0d073 BB |
35 | bindir=@bindir@ |
36 | sbindir=@sbindir@ | |
5cbf6db9 BB |
37 | udevdir=@udevdir@ |
38 | udevruledir=@udevruledir@ | |
f00828e5 | 39 | mounthelperdir=@mounthelperdir@ |
5cbf6db9 | 40 | sysconfdir=@sysconfdir@ |
9e246ac3 | 41 | localstatedir=@localstatedir@ |
c9c0d073 BB |
42 | |
43 | ETCDIR=${ETCDIR:-/etc} | |
dbf763b3 | 44 | DEVDIR=${DEVDIR:-/dev/disk/by-vdev} |
48c028f5 BB |
45 | ZPOOLDIR=${ZPOOLDIR:-${pkgdatadir}/zpool-config} |
46 | ZPIOSDIR=${ZPIOSDIR:-${pkgdatadir}/zpios-test} | |
47 | ZPIOSPROFILEDIR=${ZPIOSPROFILEDIR:-${pkgdatadir}/zpios-profile} | |
6bb24f4d BB |
48 | TESTSDIR=${TESTSDIR:-${pkgdatadir}/zfs-tests} |
49 | RUNFILEDIR=${RUNFILEDIR:-${pkgdatadir}/runfiles} | |
c9c0d073 BB |
50 | |
51 | ZDB=${ZDB:-${sbindir}/zdb} | |
52 | ZFS=${ZFS:-${sbindir}/zfs} | |
53 | ZINJECT=${ZINJECT:-${sbindir}/zinject} | |
6bb24f4d | 54 | ZHACK=${ZHACK:-${sbindir}/zhack} |
c9c0d073 | 55 | ZPOOL=${ZPOOL:-${sbindir}/zpool} |
c9c0d073 | 56 | ZTEST=${ZTEST:-${sbindir}/ztest} |
302ef151 | 57 | ZPIOS=${ZPIOS:-${sbindir}/zpios} |
c9c0d073 | 58 | |
48c028f5 BB |
59 | COMMON_SH=${COMMON_SH:-${pkgdatadir}/common.sh} |
60 | ZFS_SH=${ZFS_SH:-${pkgdatadir}/zfs.sh} | |
61 | ZPOOL_CREATE_SH=${ZPOOL_CREATE_SH:-${pkgdatadir}/zpool-create.sh} | |
62 | ZPIOS_SH=${ZPIOS_SH:-${pkgdatadir}/zpios.sh} | |
63 | ZPIOS_SURVEY_SH=${ZPIOS_SURVEY_SH:-${pkgdatadir}/zpios-survey.sh} | |
6bb24f4d BB |
64 | TEST_RUNNER=${TEST_RUNNER:-${pkgdatadir}/test-runner/bin/test-runner.py} |
65 | STF_TOOLS=${STF_TOOLS:-${pkgdatadir}/test-runner} | |
66 | STF_SUITE=${STF_SUITE:-${pkgdatadir}/zfs-tests} | |
c9c0d073 BB |
67 | |
68 | LDMOD=${LDMOD:-/sbin/modprobe} | |
69 | LSMOD=${LSMOD:-/sbin/lsmod} | |
70 | RMMOD=${RMMOD:-/sbin/rmmod} | |
71 | INFOMOD=${INFOMOD:-/sbin/modinfo} | |
72 | LOSETUP=${LOSETUP:-/sbin/losetup} | |
0ee8118b | 73 | MDADM=${MDADM:-/sbin/mdadm} |
6bb24f4d | 74 | DMSETUP=${DMSETUP:-/sbin/dmsetup} |
0ee8118b BB |
75 | PARTED=${PARTED:-/sbin/parted} |
76 | BLOCKDEV=${BLOCKDEV:-/sbin/blockdev} | |
77 | LSSCSI=${LSSCSI:-/usr/bin/lsscsi} | |
78 | SCSIRESCAN=${SCSIRESCAN:-/usr/bin/scsi-rescan} | |
c9c0d073 BB |
79 | SYSCTL=${SYSCTL:-/sbin/sysctl} |
80 | UDEVADM=${UDEVADM:-/sbin/udevadm} | |
81 | AWK=${AWK:-/usr/bin/awk} | |
541a0901 | 82 | GDB=${GDB:-/usr/bin/gdb} |
c9c0d073 | 83 | |
9e246ac3 CD |
84 | ZED_PIDFILE=${ZED_PIDFILE:-${localstatedir}/run/zed.pid} |
85 | ||
325f0235 BB |
86 | COLOR_BLACK="\033[0;30m" |
87 | COLOR_DK_GRAY="\033[1;30m" | |
88 | COLOR_BLUE="\033[0;34m" | |
89 | COLOR_LT_BLUE="\033[1;34m" | |
90 | COLOR_GREEN="\033[0;32m" | |
91 | COLOR_LT_GREEN="\033[1;32m" | |
92 | COLOR_CYAN="\033[0;36m" | |
93 | COLOR_LT_CYAN="\033[1;36m" | |
94 | COLOR_RED="\033[0;31m" | |
95 | COLOR_LT_RED="\033[1;31m" | |
96 | COLOR_PURPLE="\033[0;35m" | |
97 | COLOR_LT_PURPLE="\033[1;35m" | |
98 | COLOR_BROWN="\033[0;33m" | |
99 | COLOR_YELLOW="\033[1;33m" | |
100 | COLOR_LT_GRAY="\033[0;37m" | |
101 | COLOR_WHITE="\033[1;37m" | |
102 | COLOR_RESET="\033[0m" | |
103 | ||
c9c0d073 BB |
104 | die() { |
105 | echo -e "${PROG}: $1" >&2 | |
106 | exit 1 | |
107 | } | |
108 | ||
109 | msg() { | |
110 | if [ ${VERBOSE} ]; then | |
111 | echo "$@" | |
112 | fi | |
113 | } | |
114 | ||
115 | pass() { | |
325f0235 | 116 | echo -e "${COLOR_GREEN}Pass${COLOR_RESET}" |
c9c0d073 BB |
117 | } |
118 | ||
119 | fail() { | |
325f0235 | 120 | echo -e "${COLOR_RED}Fail${COLOR_RESET} ($1)" |
c9c0d073 BB |
121 | exit $1 |
122 | } | |
123 | ||
325f0235 BB |
124 | skip() { |
125 | echo -e "${COLOR_BROWN}Skip${COLOR_RESET}" | |
126 | } | |
127 | ||
930b6fec BB |
128 | populate() { |
129 | local ROOT=$1 | |
130 | local MAX_DIR_SIZE=$2 | |
131 | local MAX_FILE_SIZE=$3 | |
132 | ||
133 | mkdir -p $ROOT/{a,b,c,d,e,f,g}/{h,i} | |
134 | DIRS=`find $ROOT` | |
135 | ||
136 | for DIR in $DIRS; do | |
137 | COUNT=$(($RANDOM % $MAX_DIR_SIZE)) | |
138 | ||
139 | for i in `seq $COUNT`; do | |
140 | FILE=`mktemp -p ${DIR}` | |
141 | SIZE=$(($RANDOM % $MAX_FILE_SIZE)) | |
142 | dd if=/dev/urandom of=$FILE bs=1k count=$SIZE &>/dev/null | |
143 | done | |
144 | done | |
145 | ||
146 | return 0 | |
147 | } | |
148 | ||
5cbf6db9 | 149 | init() { |
930b6fec BB |
150 | # Create a random directory tree of files and sub-directories to |
151 | # to act as a copy source for the various regression tests. | |
152 | SRC_DIR=`mktemp -d -p /var/tmp/ zfs.src.XXXXXXXX` | |
153 | trap "rm -Rf $SRC_DIR" INT TERM EXIT | |
154 | populate $SRC_DIR 10 100 | |
5cbf6db9 BB |
155 | } |
156 | ||
c9c0d073 BB |
157 | check_modules() { |
158 | local LOADED_MODULES=() | |
159 | local MISSING_MODULES=() | |
160 | ||
161 | for MOD in ${MODULES[*]}; do | |
162 | local NAME=`basename $MOD .ko` | |
163 | ||
164 | if ${LSMOD} | egrep -q "^${NAME}"; then | |
165 | LOADED_MODULES=(${NAME} ${LOADED_MODULES[*]}) | |
166 | fi | |
167 | ||
168 | if [ ${INFOMOD} ${MOD} 2>/dev/null ]; then | |
169 | MISSING_MODULES=("\t${MOD}\n" ${MISSING_MODULES[*]}) | |
170 | fi | |
171 | done | |
172 | ||
173 | if [ ${#LOADED_MODULES[*]} -gt 0 ]; then | |
174 | ERROR="Unload these modules with '${PROG} -u':\n" | |
175 | ERROR="${ERROR}${LOADED_MODULES[*]}" | |
176 | return 1 | |
177 | fi | |
178 | ||
179 | if [ ${#MISSING_MODULES[*]} -gt 0 ]; then | |
180 | ERROR="The following modules can not be found," | |
181 | ERROR="${ERROR} ensure your source trees are built:\n" | |
182 | ERROR="${ERROR}${MISSING_MODULES[*]}" | |
183 | return 1 | |
184 | fi | |
185 | ||
186 | return 0 | |
187 | } | |
188 | ||
189 | load_module() { | |
190 | local NAME=`basename $1 .ko` | |
191 | ||
192 | if [ ${VERBOSE} ]; then | |
193 | echo "Loading ${NAME} ($@)" | |
194 | fi | |
195 | ||
443c3f73 BB |
196 | ${LDMOD} $* &>/dev/null |
197 | if [ $? -ne 0 ]; then | |
198 | echo "Failed to load ${NAME} ($@)" | |
199 | return 1 | |
200 | fi | |
c9c0d073 BB |
201 | |
202 | return 0 | |
203 | } | |
204 | ||
205 | load_modules() { | |
206 | mkdir -p /etc/zfs | |
207 | ||
cf47fad6 | 208 | for MOD in ${KERNEL_MODULES[*]}; do |
443c3f73 | 209 | load_module ${MOD} >/dev/null |
cf47fad6 BB |
210 | done |
211 | ||
c9c0d073 BB |
212 | for MOD in ${MODULES[*]}; do |
213 | local NAME=`basename ${MOD} .ko` | |
214 | local VALUE= | |
215 | ||
216 | for OPT in "$@"; do | |
217 | OPT_NAME=`echo ${OPT} | cut -f1 -d'='` | |
218 | ||
219 | if [ ${NAME} = "${OPT_NAME}" ]; then | |
220 | VALUE=`echo ${OPT} | cut -f2- -d'='` | |
221 | fi | |
222 | done | |
223 | ||
224 | load_module ${MOD} ${VALUE} || return 1 | |
225 | done | |
226 | ||
227 | if [ ${VERBOSE} ]; then | |
228 | echo "Successfully loaded ZFS module stack" | |
229 | fi | |
230 | ||
231 | return 0 | |
232 | } | |
233 | ||
234 | unload_module() { | |
235 | local NAME=`basename $1 .ko` | |
236 | ||
237 | if [ ${VERBOSE} ]; then | |
238 | echo "Unloading ${NAME} ($@)" | |
239 | fi | |
240 | ||
241 | ${RMMOD} ${NAME} || ERROR="Failed to unload ${NAME}" return 1 | |
242 | ||
243 | return 0 | |
244 | } | |
245 | ||
246 | unload_modules() { | |
247 | local MODULES_REVERSE=( $(echo ${MODULES[@]} | | |
248 | ${AWK} '{for (i=NF;i>=1;i--) printf $i" "} END{print ""}') ) | |
249 | ||
250 | for MOD in ${MODULES_REVERSE[*]}; do | |
251 | local NAME=`basename ${MOD} .ko` | |
252 | local USE_COUNT=`${LSMOD} | | |
253 | egrep "^${NAME} "| ${AWK} '{print $3}'` | |
254 | ||
255 | if [ "${USE_COUNT}" = 0 ] ; then | |
c9c0d073 BB |
256 | unload_module ${MOD} || return 1 |
257 | fi | |
258 | done | |
259 | ||
260 | if [ ${VERBOSE} ]; then | |
261 | echo "Successfully unloaded ZFS module stack" | |
262 | fi | |
263 | ||
264 | return 0 | |
265 | } | |
266 | ||
0ee8118b BB |
267 | # |
268 | # Check that the mdadm utilities are installed. | |
269 | # | |
270 | check_loop_utils() { | |
271 | test -f ${LOSETUP} || die "${LOSETUP} utility must be installed" | |
272 | } | |
273 | ||
274 | ||
275 | # | |
cc9ee13e BB |
276 | # Find and return an unused loop device. A new /dev/loopN node will be |
277 | # created if required. The kernel loop driver will automatically register | |
278 | # the minor as long as it's less than /sys/module/loop/parameters/max_loop. | |
0ee8118b | 279 | # |
c9c0d073 | 280 | unused_loop_device() { |
6bb24f4d | 281 | local DEVICE=$(${LOSETUP} -f) |
cc9ee13e BB |
282 | local MAX_LOOP_PATH="/sys/module/loop/parameters/max_loop" |
283 | local MAX_LOOP; | |
284 | ||
285 | # An existing /dev/loopN device was available. | |
286 | if [ -n "${DEVICE}" ]; then | |
287 | echo "${DEVICE}" | |
288 | return 0 | |
289 | fi | |
290 | ||
291 | # Create a new /dev/loopN provided we are not at MAX_LOOP. | |
292 | if [ -f "${MAX_LOOP_PATH}" ]; then | |
293 | MAX_LOOP=`cat /sys/module/loop/parameters/max_loop` | |
294 | if [ ${MAX_LOOP} -eq 0 ]; then | |
295 | MAX_LOOP=255 | |
c9c0d073 | 296 | fi |
c9c0d073 | 297 | |
cc9ee13e BB |
298 | for (( i=0; i<=${MAX_LOOP}; i++ )); do |
299 | DEVICE="/dev/loop$i" | |
300 | ||
301 | if [ -b "${DEVICE}" ]; then | |
302 | continue | |
303 | else | |
304 | mknod -m660 "${DEVICE}" b 7 $i | |
305 | chown root.disk "${DEVICE}" | |
306 | chmod 666 "${DEVICE}" | |
307 | ||
308 | echo "${DEVICE}" | |
309 | return 0 | |
310 | fi | |
311 | done | |
312 | fi | |
313 | ||
314 | die "Error: Unable to create new loopback device" | |
c9c0d073 BB |
315 | } |
316 | ||
317 | # | |
318 | # This can be slightly dangerous because the loop devices we are | |
0ee8118b | 319 | # cleaning up may not be ours. However, if the devices are currently |
c9c0d073 | 320 | # in use we will not be able to remove them, and we only remove |
cc9ee13e BB |
321 | # devices which include 'zpool' or 'deleted' in the name. So any |
322 | # damage we might do should be limited to other zfs related testing. | |
c9c0d073 BB |
323 | # |
324 | cleanup_loop_devices() { | |
325 | local TMP_FILE=`mktemp` | |
326 | ||
327 | ${LOSETUP} -a | tr -d '()' >${TMP_FILE} | |
328 | ${AWK} -F":" -v losetup="$LOSETUP" \ | |
cc9ee13e BB |
329 | '/zpool/ || /deleted/ { system("losetup -d "$1) }' ${TMP_FILE} |
330 | ${AWK} -F" " '/zpool/ || /deleted/ { system("rm -f "$3) }' ${TMP_FILE} | |
c9c0d073 BB |
331 | |
332 | rm -f ${TMP_FILE} | |
333 | } | |
334 | ||
0ee8118b BB |
335 | # |
336 | # Destroy the passed loopback devices, this is used when you know | |
337 | # the names of the loopback devices. | |
338 | # | |
339 | destroy_loop_devices() { | |
340 | local LODEVICES="$1" | |
341 | ||
342 | msg "Destroying ${LODEVICES}" | |
6bb24f4d | 343 | ${LOSETUP} -d ${LODEVICES} || \ |
0ee8118b BB |
344 | die "Error $? destroying ${FILE} -> ${DEVICE} loopback" |
345 | ||
346 | rm -f ${FILES} | |
347 | return 0 | |
348 | } | |
349 | ||
93648f31 | 350 | # |
ba6a2402 | 351 | # Create a device label taking care to briefly wait if udev needs to settle. |
93648f31 BB |
352 | # |
353 | label() { | |
354 | local DEVICE=$1 | |
355 | local LABEL=$2 | |
356 | ||
ba6a2402 BB |
357 | wait_udev ${DEVICE} 30 || return 1 |
358 | ${PARTED} ${DEVICE} --script -- mklabel ${LABEL} || return 2 | |
93648f31 BB |
359 | |
360 | return 0 | |
361 | } | |
362 | ||
363 | # | |
364 | # Create a primary partition on a block device. | |
365 | # | |
366 | partition() { | |
367 | local DEVICE=$1 | |
368 | local TYPE=$2 | |
369 | local START=$3 | |
370 | local END=$4 | |
371 | ||
372 | ${PARTED} --align optimal ${DEVICE} --script -- \ | |
373 | mkpart ${TYPE} ${START} ${END} || return 1 | |
374 | udev_trigger | |
375 | ||
376 | return 0 | |
377 | } | |
378 | ||
379 | # | |
380 | # Create a filesystem on the block device | |
381 | # | |
382 | format() { | |
383 | local DEVICE=$1 | |
384 | local FSTYPE=$2 | |
385 | ||
2f342404 ED |
386 | # Force 4K blocksize, else mkfs.ext2 tries to use 8K, which |
387 | # won't mount | |
ff5b1c80 | 388 | /sbin/mkfs.${FSTYPE} -b 4096 -F -q ${DEVICE} >/dev/null || return 1 |
93648f31 BB |
389 | |
390 | return 0 | |
391 | } | |
392 | ||
0ee8118b BB |
393 | # |
394 | # Check that the mdadm utilities are installed. | |
395 | # | |
396 | check_md_utils() { | |
397 | test -f ${MDADM} || die "${MDADM} utility must be installed" | |
398 | test -f ${PARTED} || die "${PARTED} utility must be installed" | |
399 | } | |
400 | ||
401 | check_md_partitionable() { | |
402 | local LOFILE=`mktemp -p /tmp zpool-lo.XXXXXXXX` | |
403 | local LODEVICE=`unused_loop_device` | |
404 | local MDDEVICE=`unused_md_device` | |
405 | local RESULT=1 | |
406 | ||
407 | check_md_utils | |
408 | ||
409 | rm -f ${LOFILE} | |
410 | dd if=/dev/zero of=${LOFILE} bs=1M count=0 seek=16 \ | |
411 | &>/dev/null || return ${RESULT} | |
412 | ||
413 | msg "Creating ${LODEVICE} using ${LOFILE}" | |
414 | ${LOSETUP} ${LODEVICE} ${LOFILE} | |
415 | if [ $? -ne 0 ]; then | |
416 | rm -f ${LOFILE} | |
417 | return ${RESULT} | |
418 | fi | |
419 | ||
420 | msg "Creating ${MDDEVICE} using ${LODEVICE}" | |
421 | ${MDADM} --build ${MDDEVICE} --level=faulty \ | |
422 | --raid-devices=1 ${LODEVICE} &>/dev/null | |
423 | if [ $? -ne 0 ]; then | |
424 | destroy_loop_devices ${LODEVICE} | |
425 | rm -f ${LOFILE} | |
426 | return ${RESULT} | |
427 | fi | |
428 | wait_udev ${MDDEVICE} 30 | |
429 | ||
430 | ${BLOCKDEV} --rereadpt ${MDDEVICE} 2>/dev/null | |
431 | RESULT=$? | |
432 | ||
433 | destroy_md_devices ${MDDEVICE} | |
434 | destroy_loop_devices ${LODEVICE} | |
435 | rm -f ${LOFILE} | |
436 | ||
437 | return ${RESULT} | |
438 | } | |
439 | ||
440 | # | |
441 | # Find and return an unused md device. | |
442 | # | |
443 | unused_md_device() { | |
444 | for (( i=0; i<32; i++ )); do | |
445 | MDDEVICE=md${i} | |
446 | ||
447 | # Skip active devicesudo in /proc/mdstat. | |
448 | grep -q "${MDDEVICE} " /proc/mdstat && continue | |
449 | ||
450 | # Device doesn't exist, use it. | |
451 | if [ ! -e $/dev/{MDDEVICE} ]; then | |
452 | echo /dev/${MDDEVICE} | |
453 | return | |
454 | fi | |
455 | ||
456 | # Device exists but may not be in use. | |
457 | if [ -b /dev/${MDDEVICE} ]; then | |
458 | ${MDADM} --detail /dev/${MDDEVICE} &>/dev/null | |
459 | if [ $? -eq 1 ]; then | |
460 | echo /dev/${MDDEVICE} | |
461 | return | |
462 | fi | |
463 | fi | |
464 | done | |
465 | ||
466 | die "Error: Unable to find unused md device" | |
467 | } | |
468 | ||
469 | # | |
470 | # This can be slightly dangerous because it is possible the md devices | |
471 | # we are cleaning up may not be ours. However, if the devices are | |
472 | # currently in use we will not be able to remove them, and even if | |
473 | # we remove devices which were not out we do not zero the super block | |
474 | # so you should be able to reconstruct them. | |
475 | # | |
476 | cleanup_md_devices() { | |
477 | destroy_md_devices "`ls /dev/md* 2>/dev/null | grep -v p`" | |
478 | udev_trigger | |
479 | } | |
480 | ||
481 | # | |
482 | # Destroy the passed md devices, this is used when you know | |
483 | # the names of the md devices. | |
484 | # | |
485 | destroy_md_devices() { | |
486 | local MDDEVICES="$1" | |
487 | ||
488 | msg "Destroying ${MDDEVICES}" | |
489 | for MDDEVICE in ${MDDEVICES}; do | |
490 | ${MDADM} --stop ${MDDEVICE} &>/dev/null | |
491 | ${MDADM} --remove ${MDDEVICE} &>/dev/null | |
492 | ${MDADM} --detail ${MDDEVICE} &>/dev/null | |
493 | done | |
494 | ||
495 | return 0 | |
496 | } | |
497 | ||
498 | # | |
499 | # Check that the scsi utilities are installed. | |
500 | # | |
501 | check_sd_utils() { | |
502 | ${INFOMOD} scsi_debug &>/dev/null || die "scsi_debug module required" | |
503 | test -f ${LSSCSI} || die "${LSSCSI} utility must be installed" | |
504 | } | |
505 | ||
506 | # | |
507 | # Rescan the scsi bus for scsi_debug devices. It is preferable to use the | |
508 | # scsi-rescan tool if it is installed, but if it's not we can fall back to | |
509 | # removing and readding the device manually. This rescan will only effect | |
510 | # the first scsi_debug device if scsi-rescan is missing. | |
511 | # | |
512 | scsi_rescan() { | |
513 | local AWK_SCRIPT="/scsi_debug/ { print \$1; exit }" | |
514 | ||
515 | if [ -f ${SCSIRESCAN} ]; then | |
516 | ${SCSIRESCAN} --forcerescan --remove &>/dev/null | |
517 | else | |
518 | local SCSIID=`${LSSCSI} | ${AWK} "${AWK_SCRIPT}" | tr -d '[]'` | |
519 | local SCSIHOST=`echo ${SCSIID} | cut -f1 -d':'` | |
520 | echo 1 >"/sys/class/scsi_device/${SCSIID}/device/delete" | |
521 | udev_trigger | |
522 | echo "- - -" >/sys/class/scsi_host/host${SCSIHOST}/scan | |
523 | udev_trigger | |
524 | fi | |
525 | } | |
526 | ||
527 | # | |
528 | # Trigger udev and wait for it to settle. | |
529 | # | |
530 | udev_trigger() { | |
531 | if [ -f ${UDEVADM} ]; then | |
fa417e57 | 532 | ${UDEVADM} trigger --action=change --subsystem-match=block |
0ee8118b BB |
533 | ${UDEVADM} settle |
534 | else | |
535 | /sbin/udevtrigger | |
536 | /sbin/udevsettle | |
537 | fi | |
538 | } | |
539 | ||
c9c0d073 BB |
540 | # |
541 | # The following udev helper functions assume that the provided | |
dbf763b3 | 542 | # udev rules file will create a /dev/disk/by-vdev/<CHANNEL><RANK> |
c9c0d073 BB |
543 | # disk mapping. In this mapping each CHANNEL is represented by |
544 | # the letters a-z, and the RANK is represented by the numbers | |
545 | # 1-n. A CHANNEL should identify a group of RANKS which are all | |
546 | # attached to a single controller, each RANK represents a disk. | |
547 | # This provides a simply mechanism to locate a specific drive | |
548 | # given a known hardware configuration. | |
549 | # | |
550 | udev_setup() { | |
551 | local SRC_PATH=$1 | |
552 | ||
4e33ba4c | 553 | # When running in tree manually construct symlinks in tree to |
554 | # the proper devices. Symlinks are installed for all entries | |
c9c0d073 BB |
555 | # in the config file regardless of if that device actually |
556 | # exists. When installed as a package udev can be relied on for | |
557 | # this and it will only create links for devices which exist. | |
558 | if [ ${INTREE} ]; then | |
559 | PWD=`pwd` | |
560 | mkdir -p ${DEVDIR}/ | |
561 | cd ${DEVDIR}/ | |
562 | ${AWK} '!/^#/ && /./ { system( \ | |
563 | "ln -f -s /dev/disk/by-path/"$2" "$1";" \ | |
564 | "ln -f -s /dev/disk/by-path/"$2"-part1 "$1"p1;" \ | |
565 | "ln -f -s /dev/disk/by-path/"$2"-part9 "$1"p9;" \ | |
566 | ) }' $SRC_PATH | |
567 | cd ${PWD} | |
568 | else | |
569 | DST_FILE=`basename ${SRC_PATH} | cut -f1-2 -d'.'` | |
570 | DST_PATH=/etc/zfs/${DST_FILE} | |
571 | ||
572 | if [ -e ${DST_PATH} ]; then | |
573 | die "Error: Config ${DST_PATH} already exists" | |
574 | fi | |
575 | ||
576 | cp ${SRC_PATH} ${DST_PATH} | |
0ee8118b | 577 | udev_trigger |
c9c0d073 BB |
578 | fi |
579 | ||
580 | return 0 | |
581 | } | |
582 | ||
583 | udev_cleanup() { | |
584 | local SRC_PATH=$1 | |
585 | ||
586 | if [ ${INTREE} ]; then | |
587 | PWD=`pwd` | |
588 | cd ${DEVDIR}/ | |
589 | ${AWK} '!/^#/ && /./ { system( \ | |
590 | "rm -f "$1" "$1"p1 "$1"p9") }' $SRC_PATH | |
591 | cd ${PWD} | |
592 | fi | |
593 | ||
594 | return 0 | |
595 | } | |
596 | ||
597 | udev_cr2d() { | |
598 | local CHANNEL=`echo "obase=16; $1+96" | bc` | |
599 | local RANK=$2 | |
600 | ||
601 | printf "\x${CHANNEL}${RANK}" | |
602 | } | |
603 | ||
604 | udev_raid0_setup() { | |
605 | local RANKS=$1 | |
606 | local CHANNELS=$2 | |
607 | local IDX=0 | |
608 | ||
609 | RAID0S=() | |
610 | for RANK in `seq 1 ${RANKS}`; do | |
611 | for CHANNEL in `seq 1 ${CHANNELS}`; do | |
612 | DISK=`udev_cr2d ${CHANNEL} ${RANK}` | |
613 | RAID0S[${IDX}]="${DEVDIR}/${DISK}" | |
614 | let IDX=IDX+1 | |
615 | done | |
616 | done | |
617 | ||
618 | return 0 | |
619 | } | |
620 | ||
621 | udev_raid10_setup() { | |
622 | local RANKS=$1 | |
623 | local CHANNELS=$2 | |
624 | local IDX=0 | |
625 | ||
626 | RAID10S=() | |
627 | for RANK in `seq 1 ${RANKS}`; do | |
628 | for CHANNEL1 in `seq 1 2 ${CHANNELS}`; do | |
629 | let CHANNEL2=CHANNEL1+1 | |
630 | DISK1=`udev_cr2d ${CHANNEL1} ${RANK}` | |
631 | DISK2=`udev_cr2d ${CHANNEL2} ${RANK}` | |
632 | GROUP="${DEVDIR}/${DISK1} ${DEVDIR}/${DISK2}" | |
633 | RAID10S[${IDX}]="mirror ${GROUP}" | |
634 | let IDX=IDX+1 | |
635 | done | |
636 | done | |
637 | ||
638 | return 0 | |
639 | } | |
640 | ||
641 | udev_raidz_setup() { | |
642 | local RANKS=$1 | |
643 | local CHANNELS=$2 | |
644 | ||
645 | RAIDZS=() | |
646 | for RANK in `seq 1 ${RANKS}`; do | |
647 | RAIDZ=("raidz") | |
648 | ||
649 | for CHANNEL in `seq 1 ${CHANNELS}`; do | |
650 | DISK=`udev_cr2d ${CHANNEL} ${RANK}` | |
651 | RAIDZ[${CHANNEL}]="${DEVDIR}/${DISK}" | |
652 | done | |
653 | ||
654 | RAIDZS[${RANK}]="${RAIDZ[*]}" | |
655 | done | |
656 | ||
657 | return 0 | |
658 | } | |
659 | ||
660 | udev_raidz2_setup() { | |
661 | local RANKS=$1 | |
662 | local CHANNELS=$2 | |
663 | ||
664 | RAIDZ2S=() | |
665 | for RANK in `seq 1 ${RANKS}`; do | |
666 | RAIDZ2=("raidz2") | |
667 | ||
668 | for CHANNEL in `seq 1 ${CHANNELS}`; do | |
669 | DISK=`udev_cr2d ${CHANNEL} ${RANK}` | |
670 | RAIDZ2[${CHANNEL}]="${DEVDIR}/${DISK}" | |
671 | done | |
672 | ||
673 | RAIDZ2S[${RANK}]="${RAIDZ2[*]}" | |
674 | done | |
675 | ||
676 | return 0 | |
677 | } | |
325f0235 BB |
678 | |
679 | run_one_test() { | |
680 | local TEST_NUM=$1 | |
681 | local TEST_NAME=$2 | |
682 | ||
0ee8118b | 683 | printf "%-4d %-34s " ${TEST_NUM} "${TEST_NAME}" |
325f0235 BB |
684 | test_${TEST_NUM} |
685 | } | |
686 | ||
687 | skip_one_test() { | |
688 | local TEST_NUM=$1 | |
689 | local TEST_NAME=$2 | |
690 | ||
0ee8118b | 691 | printf "%-4d %-34s " ${TEST_NUM} "${TEST_NAME}" |
325f0235 BB |
692 | skip |
693 | } | |
694 | ||
695 | run_test() { | |
696 | local TEST_NUM=$1 | |
697 | local TEST_NAME=$2 | |
698 | ||
699 | for i in ${TESTS_SKIP[@]}; do | |
700 | if [[ $i == ${TEST_NUM} ]] ; then | |
701 | skip_one_test ${TEST_NUM} "${TEST_NAME}" | |
702 | return 0 | |
703 | fi | |
704 | done | |
705 | ||
706 | if [ "${TESTS_RUN[0]}" = "*" ]; then | |
707 | run_one_test ${TEST_NUM} "${TEST_NAME}" | |
708 | else | |
709 | for i in ${TESTS_RUN[@]}; do | |
710 | if [[ $i == ${TEST_NUM} ]] ; then | |
711 | run_one_test ${TEST_NUM} "${TEST_NAME}" | |
712 | return 0 | |
713 | fi | |
714 | done | |
715 | ||
716 | skip_one_test ${TEST_NUM} "${TEST_NAME}" | |
717 | fi | |
718 | } | |
2c4834f8 BB |
719 | |
720 | wait_udev() { | |
721 | local DEVICE=$1 | |
722 | local DELAY=$2 | |
723 | local COUNT=0 | |
724 | ||
0ee8118b | 725 | udev_trigger |
2c4834f8 BB |
726 | while [ ! -e ${DEVICE} ]; do |
727 | if [ ${COUNT} -gt ${DELAY} ]; then | |
728 | return 1 | |
729 | fi | |
730 | ||
731 | let COUNT=${COUNT}+1 | |
732 | sleep 1 | |
733 | done | |
734 | ||
735 | return 0 | |
736 | } | |
10715a01 BB |
737 | |
738 | stack_clear() { | |
739 | local STACK_MAX_SIZE=/sys/kernel/debug/tracing/stack_max_size | |
740 | local STACK_TRACER_ENABLED=/proc/sys/kernel/stack_tracer_enabled | |
741 | ||
742 | if [ -e $STACK_MAX_SIZE ]; then | |
743 | echo 1 >$STACK_TRACER_ENABLED | |
744 | echo 0 >$STACK_MAX_SIZE | |
745 | fi | |
746 | } | |
747 | ||
748 | stack_check() { | |
749 | local STACK_MAX_SIZE=/sys/kernel/debug/tracing/stack_max_size | |
750 | local STACK_TRACE=/sys/kernel/debug/tracing/stack_trace | |
751 | local STACK_LIMIT=7000 | |
752 | ||
753 | if [ -e $STACK_MAX_SIZE ]; then | |
754 | STACK_SIZE=`cat $STACK_MAX_SIZE` | |
755 | ||
756 | if [ $STACK_SIZE -ge $STACK_LIMIT ]; then | |
757 | echo | |
758 | echo "Warning: max stack size $STACK_SIZE bytes" | |
759 | cat $STACK_TRACE | |
760 | fi | |
761 | fi | |
762 | } | |
9e246ac3 CD |
763 | |
764 | kill_zed() { | |
765 | if [ -f $ZED_PIDFILE ]; then | |
766 | kill $(cat $ZED_PIDFILE) | |
767 | fi | |
768 | } |