]> git.proxmox.com Git - mirror_zfs-debian.git/blame - scripts/common.sh.in
Add linux user util support
[mirror_zfs-debian.git] / scripts / common.sh.in
CommitLineData
c9c0d073
BB
1#!/bin/bash
2#
3# Common support functions for testing scripts. If a .script-config
4# files is available it will be sourced so in-tree kernel modules and
5# utilities will be used. If no .script-config can be found then the
6# installed kernel modules and utilities will be used.
7
8basedir="$(dirname $0)"
9
10SCRIPT_CONFIG=.script-config
11if [ -f "${basedir}/../${SCRIPT_CONFIG}" ]; then
12. "${basedir}/../${SCRIPT_CONFIG}"
13else
14MODULES=(zlib_deflate spl splat zavl znvpair zunicode zcommon zfs)
15fi
16
17PROG="<define PROG>"
18CLEANUP=
19VERBOSE=
20VERBOSE_FLAG=
21FORCE=
22FORCE_FLAG=
23DUMP_LOG=
24ERROR=
25RAID0S=()
26RAID10S=()
27RAIDZS=()
28RAIDZ2S=()
325f0235
BB
29TESTS_RUN=${TESTS_RUN:-'*'}
30TESTS_SKIP=${TESTS_SKIP:-}
c9c0d073
BB
31
32prefix=@prefix@
33exec_prefix=@exec_prefix@
34libexecdir=@libexecdir@
35pkglibexecdir=${libexecdir}/@PACKAGE@
36bindir=@bindir@
37sbindir=@sbindir@
38
39ETCDIR=${ETCDIR:-/etc}
40DEVDIR=${DEVDIR:-/dev/disk/zpool}
41ZPOOLDIR=${ZPOOLDIR:-${pkglibexecdir}/zpool-config}
42
43ZDB=${ZDB:-${sbindir}/zdb}
44ZFS=${ZFS:-${sbindir}/zfs}
45ZINJECT=${ZINJECT:-${sbindir}/zinject}
46ZPOOL=${ZPOOL:-${sbindir}/zpool}
47ZPOOL_ID=${ZPOOL_ID:-${bindir}/zpool_id}
48ZTEST=${ZTEST:-${sbindir}/ztest}
49
50COMMON_SH=${COMMON_SH:-${pkglibexecdir}/common.sh}
51ZFS_SH=${ZFS_SH:-${pkglibexecdir}/zfs.sh}
52ZPOOL_CREATE_SH=${ZPOOL_CREATE_SH:-${pkglibexecdir}/zpool-create.sh}
53
54LDMOD=${LDMOD:-/sbin/modprobe}
55LSMOD=${LSMOD:-/sbin/lsmod}
56RMMOD=${RMMOD:-/sbin/rmmod}
57INFOMOD=${INFOMOD:-/sbin/modinfo}
58LOSETUP=${LOSETUP:-/sbin/losetup}
59SYSCTL=${SYSCTL:-/sbin/sysctl}
60UDEVADM=${UDEVADM:-/sbin/udevadm}
61AWK=${AWK:-/usr/bin/awk}
62
325f0235
BB
63COLOR_BLACK="\033[0;30m"
64COLOR_DK_GRAY="\033[1;30m"
65COLOR_BLUE="\033[0;34m"
66COLOR_LT_BLUE="\033[1;34m"
67COLOR_GREEN="\033[0;32m"
68COLOR_LT_GREEN="\033[1;32m"
69COLOR_CYAN="\033[0;36m"
70COLOR_LT_CYAN="\033[1;36m"
71COLOR_RED="\033[0;31m"
72COLOR_LT_RED="\033[1;31m"
73COLOR_PURPLE="\033[0;35m"
74COLOR_LT_PURPLE="\033[1;35m"
75COLOR_BROWN="\033[0;33m"
76COLOR_YELLOW="\033[1;33m"
77COLOR_LT_GRAY="\033[0;37m"
78COLOR_WHITE="\033[1;37m"
79COLOR_RESET="\033[0m"
80
c9c0d073
BB
81die() {
82 echo -e "${PROG}: $1" >&2
83 exit 1
84}
85
86msg() {
87 if [ ${VERBOSE} ]; then
88 echo "$@"
89 fi
90}
91
92pass() {
325f0235 93 echo -e "${COLOR_GREEN}Pass${COLOR_RESET}"
c9c0d073
BB
94}
95
96fail() {
325f0235 97 echo -e "${COLOR_RED}Fail${COLOR_RESET} ($1)"
c9c0d073
BB
98 exit $1
99}
100
325f0235
BB
101skip() {
102 echo -e "${COLOR_BROWN}Skip${COLOR_RESET}"
103}
104
c9c0d073
BB
105spl_dump_log() {
106 ${SYSCTL} -w kernel.spl.debug.dump=1 &>/dev/null
107 local NAME=`dmesg | tail -n 1 | cut -f5 -d' '`
108 ${SPLBUILD}/cmd/spl ${NAME} >${NAME}.log
109 echo
110 echo "Dumped debug log: ${NAME}.log"
111 tail -n1 ${NAME}.log
112 echo
113 return 0
114}
115
116check_modules() {
117 local LOADED_MODULES=()
118 local MISSING_MODULES=()
119
120 for MOD in ${MODULES[*]}; do
121 local NAME=`basename $MOD .ko`
122
123 if ${LSMOD} | egrep -q "^${NAME}"; then
124 LOADED_MODULES=(${NAME} ${LOADED_MODULES[*]})
125 fi
126
127 if [ ${INFOMOD} ${MOD} 2>/dev/null ]; then
128 MISSING_MODULES=("\t${MOD}\n" ${MISSING_MODULES[*]})
129 fi
130 done
131
132 if [ ${#LOADED_MODULES[*]} -gt 0 ]; then
133 ERROR="Unload these modules with '${PROG} -u':\n"
134 ERROR="${ERROR}${LOADED_MODULES[*]}"
135 return 1
136 fi
137
138 if [ ${#MISSING_MODULES[*]} -gt 0 ]; then
139 ERROR="The following modules can not be found,"
140 ERROR="${ERROR} ensure your source trees are built:\n"
141 ERROR="${ERROR}${MISSING_MODULES[*]}"
142 return 1
143 fi
144
145 return 0
146}
147
148load_module() {
149 local NAME=`basename $1 .ko`
150
151 if [ ${VERBOSE} ]; then
152 echo "Loading ${NAME} ($@)"
153 fi
154
155 ${LDMOD} $* || ERROR="Failed to load $1" return 1
156
157 return 0
158}
159
160load_modules() {
161 mkdir -p /etc/zfs
162
163 for MOD in ${MODULES[*]}; do
164 local NAME=`basename ${MOD} .ko`
165 local VALUE=
166
167 for OPT in "$@"; do
168 OPT_NAME=`echo ${OPT} | cut -f1 -d'='`
169
170 if [ ${NAME} = "${OPT_NAME}" ]; then
171 VALUE=`echo ${OPT} | cut -f2- -d'='`
172 fi
173 done
174
175 load_module ${MOD} ${VALUE} || return 1
176 done
177
178 if [ ${VERBOSE} ]; then
179 echo "Successfully loaded ZFS module stack"
180 fi
181
182 return 0
183}
184
185unload_module() {
186 local NAME=`basename $1 .ko`
187
188 if [ ${VERBOSE} ]; then
189 echo "Unloading ${NAME} ($@)"
190 fi
191
192 ${RMMOD} ${NAME} || ERROR="Failed to unload ${NAME}" return 1
193
194 return 0
195}
196
197unload_modules() {
198 local MODULES_REVERSE=( $(echo ${MODULES[@]} |
199 ${AWK} '{for (i=NF;i>=1;i--) printf $i" "} END{print ""}') )
200
201 for MOD in ${MODULES_REVERSE[*]}; do
202 local NAME=`basename ${MOD} .ko`
203 local USE_COUNT=`${LSMOD} |
204 egrep "^${NAME} "| ${AWK} '{print $3}'`
205
206 if [ "${USE_COUNT}" = 0 ] ; then
207
208 if [ "${DUMP_LOG}" -a ${NAME} = "spl" ]; then
209 spl_dump_log
210 fi
211
212 unload_module ${MOD} || return 1
213 fi
214 done
215
216 if [ ${VERBOSE} ]; then
217 echo "Successfully unloaded ZFS module stack"
218 fi
219
220 return 0
221}
222
223unused_loop_device() {
224 for DEVICE in `ls -1 /dev/loop*`; do
225 ${LOSETUP} ${DEVICE} &>/dev/null
226 if [ $? -ne 0 ]; then
227 echo ${DEVICE}
228 return
229 fi
230 done
231
232 die "Error: Unable to find unused loopback device"
233}
234
235#
236# This can be slightly dangerous because the loop devices we are
237# cleanup up may not be ours. However, if the devices are currently
238# in use we will not be able to remove them, and we only remove
239# devices which include 'zpool' in the name. So any damage we might
240# do should be limited to other zfs related testing.
241#
242cleanup_loop_devices() {
243 local TMP_FILE=`mktemp`
244
245 ${LOSETUP} -a | tr -d '()' >${TMP_FILE}
246 ${AWK} -F":" -v losetup="$LOSETUP" \
247 '/zpool/ { system("losetup -d "$1) }' ${TMP_FILE}
248 ${AWK} -F" " '/zpool/ { system("rm -f "$3) }' ${TMP_FILE}
249
250 rm -f ${TMP_FILE}
251}
252
253#
254# The following udev helper functions assume that the provided
255# udev rules file will create a /dev/disk/zpool/<CHANNEL><RANK>
256# disk mapping. In this mapping each CHANNEL is represented by
257# the letters a-z, and the RANK is represented by the numbers
258# 1-n. A CHANNEL should identify a group of RANKS which are all
259# attached to a single controller, each RANK represents a disk.
260# This provides a simply mechanism to locate a specific drive
261# given a known hardware configuration.
262#
263udev_setup() {
264 local SRC_PATH=$1
265
266 # When running in tree manually contruct symlinks in tree to
267 # the proper devices. Symlinks are installed for all entires
268 # in the config file regardless of if that device actually
269 # exists. When installed as a package udev can be relied on for
270 # this and it will only create links for devices which exist.
271 if [ ${INTREE} ]; then
272 PWD=`pwd`
273 mkdir -p ${DEVDIR}/
274 cd ${DEVDIR}/
275 ${AWK} '!/^#/ && /./ { system( \
276 "ln -f -s /dev/disk/by-path/"$2" "$1";" \
277 "ln -f -s /dev/disk/by-path/"$2"-part1 "$1"p1;" \
278 "ln -f -s /dev/disk/by-path/"$2"-part9 "$1"p9;" \
279 ) }' $SRC_PATH
280 cd ${PWD}
281 else
282 DST_FILE=`basename ${SRC_PATH} | cut -f1-2 -d'.'`
283 DST_PATH=/etc/zfs/${DST_FILE}
284
285 if [ -e ${DST_PATH} ]; then
286 die "Error: Config ${DST_PATH} already exists"
287 fi
288
289 cp ${SRC_PATH} ${DST_PATH}
290
291 if [ -f ${UDEVADM} ]; then
292 ${UDEVADM} trigger
293 ${UDEVADM} settle
294 else
295 /sbin/udevtrigger
296 /sbin/udevsettle
297 fi
298 fi
299
300 return 0
301}
302
303udev_cleanup() {
304 local SRC_PATH=$1
305
306 if [ ${INTREE} ]; then
307 PWD=`pwd`
308 cd ${DEVDIR}/
309 ${AWK} '!/^#/ && /./ { system( \
310 "rm -f "$1" "$1"p1 "$1"p9") }' $SRC_PATH
311 cd ${PWD}
312 fi
313
314 return 0
315}
316
317udev_cr2d() {
318 local CHANNEL=`echo "obase=16; $1+96" | bc`
319 local RANK=$2
320
321 printf "\x${CHANNEL}${RANK}"
322}
323
324udev_raid0_setup() {
325 local RANKS=$1
326 local CHANNELS=$2
327 local IDX=0
328
329 RAID0S=()
330 for RANK in `seq 1 ${RANKS}`; do
331 for CHANNEL in `seq 1 ${CHANNELS}`; do
332 DISK=`udev_cr2d ${CHANNEL} ${RANK}`
333 RAID0S[${IDX}]="${DEVDIR}/${DISK}"
334 let IDX=IDX+1
335 done
336 done
337
338 return 0
339}
340
341udev_raid10_setup() {
342 local RANKS=$1
343 local CHANNELS=$2
344 local IDX=0
345
346 RAID10S=()
347 for RANK in `seq 1 ${RANKS}`; do
348 for CHANNEL1 in `seq 1 2 ${CHANNELS}`; do
349 let CHANNEL2=CHANNEL1+1
350 DISK1=`udev_cr2d ${CHANNEL1} ${RANK}`
351 DISK2=`udev_cr2d ${CHANNEL2} ${RANK}`
352 GROUP="${DEVDIR}/${DISK1} ${DEVDIR}/${DISK2}"
353 RAID10S[${IDX}]="mirror ${GROUP}"
354 let IDX=IDX+1
355 done
356 done
357
358 return 0
359}
360
361udev_raidz_setup() {
362 local RANKS=$1
363 local CHANNELS=$2
364
365 RAIDZS=()
366 for RANK in `seq 1 ${RANKS}`; do
367 RAIDZ=("raidz")
368
369 for CHANNEL in `seq 1 ${CHANNELS}`; do
370 DISK=`udev_cr2d ${CHANNEL} ${RANK}`
371 RAIDZ[${CHANNEL}]="${DEVDIR}/${DISK}"
372 done
373
374 RAIDZS[${RANK}]="${RAIDZ[*]}"
375 done
376
377 return 0
378}
379
380udev_raidz2_setup() {
381 local RANKS=$1
382 local CHANNELS=$2
383
384 RAIDZ2S=()
385 for RANK in `seq 1 ${RANKS}`; do
386 RAIDZ2=("raidz2")
387
388 for CHANNEL in `seq 1 ${CHANNELS}`; do
389 DISK=`udev_cr2d ${CHANNEL} ${RANK}`
390 RAIDZ2[${CHANNEL}]="${DEVDIR}/${DISK}"
391 done
392
393 RAIDZ2S[${RANK}]="${RAIDZ2[*]}"
394 done
395
396 return 0
397}
325f0235
BB
398
399run_one_test() {
400 local TEST_NUM=$1
401 local TEST_NAME=$2
402
403 printf "%-4d %-36s " ${TEST_NUM} "${TEST_NAME}"
404 test_${TEST_NUM}
405}
406
407skip_one_test() {
408 local TEST_NUM=$1
409 local TEST_NAME=$2
410
411 printf "%-4d %-36s " ${TEST_NUM} "${TEST_NAME}"
412 skip
413}
414
415run_test() {
416 local TEST_NUM=$1
417 local TEST_NAME=$2
418
419 for i in ${TESTS_SKIP[@]}; do
420 if [[ $i == ${TEST_NUM} ]] ; then
421 skip_one_test ${TEST_NUM} "${TEST_NAME}"
422 return 0
423 fi
424 done
425
426 if [ "${TESTS_RUN[0]}" = "*" ]; then
427 run_one_test ${TEST_NUM} "${TEST_NAME}"
428 else
429 for i in ${TESTS_RUN[@]}; do
430 if [[ $i == ${TEST_NUM} ]] ; then
431 run_one_test ${TEST_NUM} "${TEST_NAME}"
432 return 0
433 fi
434 done
435
436 skip_one_test ${TEST_NUM} "${TEST_NAME}"
437 fi
438}