Whamcloud - gitweb
Changelog update
[fs/lustre-release.git] / lustre / tests / test-framework.sh
1 #!/bin/bash
2 # vim:expandtab:shiftwidth=4:softtabstop=4:tabstop=4:
3
4 trap 'print_summary && echo "test-framework exiting on error"' ERR
5 set -e
6 #set -x
7
8
9 export REFORMAT=${REFORMAT:-""}
10 export WRITECONF=${WRITECONF:-""}
11 export VERBOSE=false
12 export GMNALNID=${GMNALNID:-/usr/sbin/gmlndnid}
13 export CATASTROPHE=${CATASTROPHE:-/proc/sys/lnet/catastrophe}
14 #export PDSH="pdsh -S -Rssh -w"
15
16 # function used by scripts run on remote nodes
17 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
18 . $LUSTRE/tests/functions.sh
19
20 LUSTRE_TESTS_CFG_DIR=${LUSTRE_TESTS_CFG_DIR:-${LUSTRE}/tests/cfg}
21
22 EXCEPT_LIST_FILE=${EXCEPT_LIST_FILE:-${LUSTRE_TESTS_CFG_DIR}/tests-to-skip.sh}
23
24 if [ -f "$EXCEPT_LIST_FILE" ]; then
25     echo "Reading test skip list from $EXCEPT_LIST_FILE"
26     cat $EXCEPT_LIST_FILE
27     . $EXCEPT_LIST_FILE
28 fi
29
30 assert_DIR () {
31     local failed=""
32     [[ $DIR/ = $MOUNT/* ]] || \
33         { failed=1 && echo "DIR=$DIR not in $MOUNT. Aborting."; }
34     [[ $DIR1/ = $MOUNT1/* ]] || \
35         { failed=1 && echo "DIR1=$DIR1 not in $MOUNT1. Aborting."; }
36     [[ $DIR2/ = $MOUNT2/* ]] || \
37         { failed=1 && echo "DIR2=$DIR2 not in $MOUNT2. Aborting"; }
38
39     [ -n "$failed" ] && exit 99 || true
40 }
41
42 usage() {
43     echo "usage: $0 [-r] [-f cfgfile]"
44     echo "       -r: reformat"
45
46     exit
47 }
48
49 print_summary () {
50     trap 0
51     [ "$TESTSUITE" == "lfscktest" ] && return 0
52     [ -n "$ONLY" ] && echo "WARNING: ONLY is set to ${ONLY}."
53     local form="%-13s %-17s %s\n"
54     printf "$form" "status" "script" "skipped tests E(xcluded) S(low)"
55     echo "------------------------------------------------------------------------------------"
56     for O in $TESTSUITE_LIST; do
57         local skipped=""
58         local slow=""
59         local o=$(echo $O | tr "[:upper:]" "[:lower:]")
60         o=${o//_/-}
61         o=${o//tyn/tyN}
62         local log=${TMP}/${o}.log
63         [ -f $log ] && skipped=$(grep excluded $log | awk '{ printf " %s", $3 }' | sed 's/test_//g')
64         [ -f $log ] && slow=$(grep SLOW $log | awk '{ printf " %s", $3 }' | sed 's/test_//g')
65         [ "${!O}" = "done" ] && \
66             printf "$form" "Done" "$O" "E=$skipped" && \
67             [ -n "$slow" ] && printf "$form" "-" "-" "S=$slow"
68
69     done
70
71     for O in $TESTSUITE_LIST; do
72         if [ "${!O}" = "no" ]; then
73             # FIXME.
74             # only for those tests suits which are run directly from acc-sm script:
75             # bonnie, iozone, etc.
76             if [ -f "$TESTSUITELOG" ] && grep FAIL $TESTSUITELOG | grep -q ' '$O  ; then
77                printf "$form" "UNFINISHED" "$O" ""  
78             else
79                printf "$form" "Skipped" "$O" ""
80             fi
81         fi
82     done
83
84     for O in $TESTSUITE_LIST; do
85         [ "${!O}" = "done" -o "${!O}" = "no" ] || \
86             printf "$form" "UNFINISHED" "$O" ""
87     done
88 }
89
90 init_test_env() {
91     export LUSTRE=`absolute_path $LUSTRE`
92     export TESTSUITE=`basename $0 .sh`
93     export TEST_FAILED=false
94     export FAIL_ON_SKIP_ENV=${FAIL_ON_SKIP_ENV:-false}
95
96     export MKE2FS=${MKE2FS:-mke2fs}
97     export DEBUGFS=${DEBUGFS:-debugfs}
98     export TUNE2FS=${TUNE2FS:-tune2fs}
99     export E2LABEL=${E2LABEL:-e2label}
100     export DUMPE2FS=${DUMPE2FS:-dumpe2fs}
101     export E2FSCK=${E2FSCK:-e2fsck}
102     export LFSCK_BIN=${LFSCK_BIN:-lfsck}
103     export LFSCK_ALWAYS=${LFSCK_ALWAYS:-"no"} # check filesystem after each test suit
104     export SKIP_LFSCK=${SKIP_LFSCK:-"yes"} # bug 13698, change to "no" when fixed
105     export SHARED_DIRECTORY=${SHARED_DIRECTORY:-"/tmp"}
106     export FSCK_MAX_ERR=4   # File system errors left uncorrected
107     if [ "$SKIP_LFSCK" == "no" ]; then
108         if [ ! -x `which $LFSCK_BIN` ]; then
109             log "$($E2FSCK -V)"
110             error_exit "$E2FSCK does not support lfsck"
111         fi
112
113         export MDSDB=${MDSDB:-$SHARED_DIRECTORY/mdsdb}
114         export OSTDB=${OSTDB:-$SHARED_DIRECTORY/ostdb}
115         export MDSDB_OPT="--mdsdb $MDSDB"
116         export OSTDB_OPT="--ostdb $OSTDB-\$ostidx"
117     fi
118     declare -a OSTDEVS
119
120     #[ -d /r ] && export ROOT=${ROOT:-/r}
121     export TMP=${TMP:-$ROOT/tmp}
122     export TESTSUITELOG=${TMP}/${TESTSUITE}.log
123     export HOSTNAME=${HOSTNAME:-`hostname`}
124     if ! echo $PATH | grep -q $LUSTRE/utils; then
125         export PATH=$PATH:$LUSTRE/utils
126     fi
127     if ! echo $PATH | grep -q $LUSTRE/test; then
128         export PATH=$PATH:$LUSTRE/tests
129     fi
130     export LST=${LST:-"$LUSTRE/../lnet/utils/lst"}
131     [ ! -f "$LST" ] && export LST=$(which lst)
132     export SGPDDSURVEY=${SGPDDSURVEY:-$(which sgpdd-survey)}
133     export MDSRATE=${MDSRATE:-"$LUSTRE/tests/mpi/mdsrate"}
134     [ ! -f "$MDSRATE" ] && export MDSRATE=$(which mdsrate 2> /dev/null)
135     if ! echo $PATH | grep -q $LUSTRE/tests/racer; then
136         export PATH=$PATH:$LUSTRE/tests/racer
137     fi
138     if ! echo $PATH | grep -q $LUSTRE/tests/mpi; then
139         export PATH=$PATH:$LUSTRE/tests/mpi
140     fi
141     export RSYNC_RSH=${RSYNC_RSH:-rsh}
142     export LCTL=${LCTL:-"$LUSTRE/utils/lctl"}
143     [ ! -f "$LCTL" ] && export LCTL=$(which lctl)
144     export LFS=${LFS:-"$LUSTRE/utils/lfs"}
145     [ ! -f "$LFS" ] && export LFS=$(which lfs)
146     export MKFS=${MKFS:-"$LUSTRE/utils/mkfs.lustre"}
147     [ ! -f "$MKFS" ] && export MKFS=$(which mkfs.lustre)
148     export TUNEFS=${TUNEFS:-"$LUSTRE/utils/tunefs.lustre"}
149     [ ! -f "$TUNEFS" ] && export TUNEFS=$(which tunefs.lustre)
150     export CHECKSTAT="${CHECKSTAT:-"checkstat -v"} "
151     export LUSTRE_RMMOD=${LUSTRE_RMMOD:-$LUSTRE/scripts/lustre_rmmod}
152     [ ! -f "$LUSTRE_RMMOD" ] && export LUSTRE_RMMOD=$(which lustre_rmmod 2> /dev/null)
153     export FSTYPE=${FSTYPE:-"ldiskfs"}
154     export NAME=${NAME:-local}
155     export DIR2
156     export SAVE_PWD=${SAVE_PWD:-$LUSTRE/tests}
157
158     if [ "$ACCEPTOR_PORT" ]; then
159         export PORT_OPT="--port $ACCEPTOR_PORT"
160     fi
161
162     export LOAD_MODULES_REMOTE=${LOAD_MODULES_REMOTE:-false}
163
164     # Paths on remote nodes, if different
165     export RLUSTRE=${RLUSTRE:-$LUSTRE}
166     export RPWD=${RPWD:-$PWD}
167     export I_MOUNTED=${I_MOUNTED:-"no"}
168     if [ ! -f /lib/modules/$(uname -r)/kernel/fs/lustre/mds.ko -a \
169         ! -f /lib/modules/$(uname -r)/updates/kernel/fs/lustre/mds.ko -a \
170         ! -f `dirname $0`/../mds/mds.ko ]; then
171         export CLIENTMODSONLY=yes
172     fi
173
174     # command line
175
176     while getopts "rvwf:" opt $*; do
177         case $opt in
178             f) CONFIG=$OPTARG;;
179             r) REFORMAT=--reformat;;
180             v) VERBOSE=true;;
181             w) WRITECONF=writeconf;;
182             \?) usage;;
183         esac
184     done
185
186     shift $((OPTIND - 1))
187     ONLY=${ONLY:-$*}
188
189     [ "$TESTSUITELOG" ] && rm -f $TESTSUITELOG || true
190     rm -f $TMP/*active
191 }
192
193 case `uname -r` in
194     *) EXT=".ko"; USE_QUOTA=yes;;
195 esac
196
197 pool_list () {
198    do_facet mgs lctl pool_list $1
199 }
200
201 create_pool() {
202     local fsname=${1%%.*}
203     local poolname=${1##$fsname.}
204
205     do_facet mgs lctl pool_new $1
206     local RC=$?
207     # get param should return err unless pool is created
208     [[ $RC -ne 0 ]] && return $RC
209
210     wait_update $HOSTNAME "lctl get_param -n lov.$fsname-*.pools.$poolname \
211         2>/dev/null || echo foo" "" || RC=1
212     if [[ $RC -eq 0 ]]; then
213         add_pool_to_list $1
214     else
215         error "pool_new failed $1"
216     fi
217     return $RC
218 }
219
220 add_pool_to_list () {
221     local fsname=${1%%.*}
222     local poolname=${1##$fsname.}
223
224     local listvar=${fsname}_CREATED_POOLS
225     eval export ${listvar}=$(expand_list ${!listvar} $poolname)
226 }
227
228 remove_pool_from_list () {
229     local fsname=${1%%.*}
230     local poolname=${1##$fsname.}
231
232     local listvar=${fsname}_CREATED_POOLS
233     eval export ${listvar}=$(exclude_items_from_list ${!listvar} $poolname)
234 }
235
236 module_loaded () {
237    /sbin/lsmod | grep -q $1
238 }
239
240 load_module() {
241     module=$1
242     shift
243     BASE=`basename $module $EXT`
244
245     module_loaded ${BASE} && return
246
247     if [ "$BASE" == "lnet_selftest" ] && \
248             [ -f ${LUSTRE}/../lnet/selftest/${module}${EXT} ]; then
249         insmod ${LUSTRE}/../lnet/selftest/${module}${EXT}
250
251     elif [ -f ${LUSTRE}/${module}${EXT} ]; then
252         insmod ${LUSTRE}/${module}${EXT} $@
253     else
254         # must be testing a "make install" or "rpm" installation
255         modprobe $BASE $@
256     fi
257 }
258
259 load_modules_local() {
260     if [ -n "$MODPROBE" ]; then
261         # use modprobe
262     return 0
263     fi
264     if [ "$HAVE_MODULES" = true ]; then
265     # we already loaded
266         return 0
267     fi
268     HAVE_MODULES=true
269
270     echo Loading modules from $LUSTRE
271     load_module ../lnet/libcfs/libcfs
272     [ "$PTLDEBUG" ] && lctl set_param debug="$PTLDEBUG"
273     [ "$SUBSYSTEM" ] && lctl set_param subsystem_debug="${SUBSYSTEM# }"
274     local MODPROBECONF=
275     [ -f /etc/modprobe.conf ] && MODPROBECONF=/etc/modprobe.conf
276     [ ! "$MODPROBECONF" -a -d /etc/modprobe.d ] && MODPROBECONF=/etc/modprobe.d/Lustre
277     [ -z "$LNETOPTS" -a "$MODPROBECONF" ] && \
278         LNETOPTS=$(awk '/^options lnet/ { print $0}' $MODPROBECONF | sed 's/^options lnet //g')
279     echo $LNETOPTS | grep -q "accept=all"  || LNETOPTS="$LNETOPTS accept=all";
280     # bug 19380
281     # disable it for now since it only hides the stack overflow upon test w/
282     # local servers
283 #    if [ "$NETTYPE" = "tcp" -o "$NETTYPE" = "o2ib" -o "$NETTYPE" = "ptl" ]; then
284 #        echo $LNETOPTS | grep -q "local_nid_dist_zero=0" ||
285 #        LNETOPTS="$LNETOPTS local_nid_dist_zero=0"
286 #    fi
287     echo "lnet options: '$LNETOPTS'"
288     # note that insmod will ignore anything in modprobe.conf
289     load_module ../lnet/lnet/lnet $LNETOPTS
290     LNETLND=${LNETLND:-"socklnd/ksocklnd"}
291     load_module ../lnet/klnds/$LNETLND
292     load_module lvfs/lvfs
293     load_module obdclass/obdclass
294     load_module ptlrpc/ptlrpc
295     [ "$USE_QUOTA" = "yes" ] && load_module quota/lquota $LQUOTAOPTS
296     load_module mdc/mdc
297     load_module osc/osc
298     load_module lov/lov
299     load_module mgc/mgc
300     if ! client_only; then
301         load_module mgs/mgs
302         load_module mds/mds
303         grep -q crc16 /proc/kallsyms || { modprobe crc16 2>/dev/null || true; }
304         grep -q jbd /proc/kallsyms || { modprobe jbd 2>/dev/null || true; }
305         [ "$FSTYPE" = "ldiskfs" ] && load_module ../ldiskfs/ldiskfs/ldiskfs
306         load_module lvfs/fsfilt_$FSTYPE
307         load_module ost/ost
308         load_module obdfilter/obdfilter
309     fi
310
311     load_module llite/lustre
312     load_module llite/llite_lloop
313     rm -f $TMP/ogdb-$HOSTNAME
314     OGDB=$TMP
315     [ -d /r ] && OGDB="/r/tmp"
316     $LCTL modules > $OGDB/ogdb-$HOSTNAME
317     # 'mount' doesn't look in $PATH, just sbin
318     [ -f $LUSTRE/utils/mount.lustre ] && cp $LUSTRE/utils/mount.lustre /sbin/. || true
319 }
320
321 load_modules () {
322     load_modules_local
323     # bug 19124
324     # load modules on remote nodes optionally
325     # lustre-tests have to be installed on these nodes
326     if $LOAD_MODULES_REMOTE ; then
327         local list=$(comma_list $(remote_nodes_list))
328         echo loading modules on $list
329         do_rpc_nodes $list load_modules 
330     fi
331 }
332
333 check_mem_leak () {
334     LEAK_LUSTRE=$(dmesg | tail -n 30 | grep "obd_memory.*leaked" || true)
335     LEAK_PORTALS=$(dmesg | tail -n 20 | grep "Portals memory leaked" || true)
336     if [ "$LEAK_LUSTRE" -o "$LEAK_PORTALS" ]; then
337         echo "$LEAK_LUSTRE" 1>&2
338         echo "$LEAK_PORTALS" 1>&2
339         mv $TMP/debug $TMP/debug-leak.`date +%s` || true
340         echo "Memory leaks detected"
341         [ -n "$IGNORE_LEAK" ] && { echo "ignoring leaks" && return 0; } || true
342         return 1
343     fi
344 }
345
346 unload_modules() {
347     wait_exit_ST client # bug 12845
348
349     if $LOAD_MODULES_REMOTE ; then
350         local list=$(comma_list $(remote_nodes_list))
351         if [ ! -z $list ]; then
352             echo unloading modules on $list
353             do_rpc_nodes $list $LUSTRE_RMMOD $FSTYPE
354             do_rpc_nodes $list check_mem_leak
355         fi
356     fi
357
358     $LUSTRE_RMMOD $FSTYPE || return 2
359
360     HAVE_MODULES=false
361
362     check_mem_leak || return 254
363
364     echo "modules unloaded."
365     return 0
366 }
367
368 # Facet functions
369 mount_facet() {
370     local facet=$1
371     shift
372     local dev=$(facet_active $facet)_dev
373     local opt=${facet}_opt
374     local mntpt=$(facet_mntpt $facet)
375
376     echo "Starting ${facet}: ${!opt} $@ ${!dev} $mntpt"
377     do_facet ${facet} mount -t lustre ${!opt} $@ ${!dev} $mntpt
378     RC=${PIPESTATUS[0]}
379     if [ $RC -ne 0 ]; then
380         echo "mount -t lustre $@ ${!dev} $mntpt"
381         echo "Start of ${!dev} on ${facet} failed ${RC}"
382     else
383         do_facet ${facet} "lctl set_param debug=\\\"$PTLDEBUG\\\"; \
384             lctl set_param subsystem_debug=\\\"${SUBSYSTEM# }\\\"; \
385             lctl set_param debug_mb=${DEBUG_SIZE}; \
386             sync"
387
388         label=$(do_facet ${facet} "$E2LABEL ${!dev}")
389         [ -z "$label" ] && echo no label for ${!dev} && exit 1
390         eval export ${facet}_svc=${label}
391         echo Started ${label}
392     fi
393     return $RC
394 }
395
396 # start facet device options
397 start() {
398     local facet=$1
399     shift
400     local device=$1
401     shift
402     eval export ${facet}_dev=${device}
403     eval export ${facet}_opt=\"$@\"
404
405     local varname=${facet}failover_dev
406     if [ -n "${!varname}" ] ; then
407         eval export ${facet}failover_dev=${!varname}
408     else
409         eval export ${facet}failover_dev=$device
410     fi
411
412     local mntpt=$(facet_mntpt $facet)
413     do_facet ${facet} mkdir -p $mntpt
414     eval export ${facet}_MOUNT=$mntpt
415     mount_facet ${facet}
416     RC=$?
417     return $RC
418 }
419
420 stop() {
421     local running
422     local facet=$1
423     shift
424     local HOST=`facet_active_host $facet`
425     [ -z $HOST ] && echo stop: no host for $facet && return 0
426
427     local mntpt=$(facet_mntpt $facet)
428     running=$(do_facet ${facet} "grep -c $mntpt' ' /proc/mounts") || true
429     if [ ${running} -ne 0 ]; then
430         echo "Stopping $mntpt (opts:$@)"
431         do_facet ${facet} umount -d $@ $mntpt
432     fi
433
434     # umount should block, but we should wait for unrelated obd's
435     # like the MGS or MGC to also stop.
436
437     wait_exit_ST ${facet}
438 }
439
440 # set quota version (both administrative and operational quotas)
441 quota_set_version() {
442         do_facet mds "lctl set_param lquota.${FSNAME}-MDT*.quota_type=$1"
443         local varsvc
444         local osts=$(get_facets OST)
445         for ost in ${osts//,/ }; do
446                 varsvc=${ost}_svc
447                 do_facet $ost "lctl set_param lquota.${!varsvc}.quota_type=$1"
448         done
449 }
450
451 # save quota version (both administrative and operational quotas)
452 # the function will also switch to the new version and the new type
453 quota_save_version() {
454     local spec=$1
455     local ver=$(tr -c -d "123" <<< $spec)
456     local type=$(tr -c -d "ug" <<< $spec)
457
458     local lustre_version=$(get_lustre_version mds)
459     if [[ $lustre_version = 1.8* ]] ; then
460         $LFS quotaoff -ug $MOUNT # just in case
461         [ -n "$ver" ] && quota_set_version $ver
462     else
463         echo mds running $lustre_version 
464         [ -n "$ver" -a "$ver" != "3" ] && error "wrong quota version specifier"
465     fi
466
467     [ -n "$type" ] && { $LFS quotacheck -$type $MOUNT || error "quotacheck has failed"; }
468
469     do_facet mgs "lctl conf_param ${FSNAME}-MDT*.$(get_md_name).quota_type=$spec"
470     local varsvc
471     local osts=$(get_facets OST)
472     for ost in ${osts//,/ }; do
473         varsvc=${ost}_svc
474         do_facet mgs "lctl conf_param ${!varsvc}.ost.quota_type=$spec"
475     done
476 }
477
478 # client could mount several lustre
479 quota_type () {
480     local fsname=${1:-$FSNAME}
481     local rc=0
482     do_facet mgs lctl get_param md*.${fsname}-MDT*.quota_type || rc=$?
483     do_nodes $(comma_list $(osts_nodes)) \
484         lctl get_param obdfilter.${fsname}-OST*.quota_type || rc=$?
485     return $rc
486 }
487
488 restore_quota_type () {
489    local mntpt=${1:-$MOUNT}
490    local quota_type=$(quota_type $FSNAME | grep MDT | cut -d "=" -f2)
491    if [ ! "$old_QUOTA_TYPE" ] || [ "$quota_type" = "$old_QUOTA_TYPE" ]; then
492         return
493    fi
494    quota_save_version $old_QUOTA_TYPE
495 }
496
497 setup_quota(){
498     local mntpt=$1
499
500     # We need:
501     # 1. run quotacheck only if quota is off
502     # 2. save the original quota_type params, restore them after testing
503
504     # Suppose that quota type the same on mds and ost
505     local quota_type=$(quota_type | grep MDT | cut -d "=" -f2)
506     [ ${PIPESTATUS[0]} -eq 0 ] || error "quota_type failed!"
507     echo "[HOST:$HOSTNAME] [old_quota_type:$quota_type] [new_quota_type:$QUOTA_TYPE]"
508     if [ "$quota_type" != "$QUOTA_TYPE" ]; then
509         export old_QUOTA_TYPE=$quota_type
510         quota_save_version $QUOTA_TYPE
511     fi
512
513     local quota_usrs=$QUOTA_USERS
514
515     # get_filesystem_size
516     local disksz=$(lfs df $mntpt | grep "filesystem summary:"  | awk '{print $3}')
517     local blk_soft=$((disksz + 1024))
518     local blk_hard=$((blk_soft + blk_soft / 20)) # Go 5% over
519
520     local Inodes=$(lfs df -i $mntpt | grep "filesystem summary:"  | awk '{print $3}')
521     local i_soft=$Inodes
522     local i_hard=$((i_soft + i_soft / 20))
523
524     echo "Total disk size: $disksz  block-softlimit: $blk_soft block-hardlimit:
525         $blk_hard inode-softlimit: $i_soft inode-hardlimit: $i_hard"
526
527     local cmd
528     for usr in $quota_usrs; do
529         echo "Setting up quota on $client:$mntpt for $usr..."
530         for type in u g; do
531             cmd="$LFS setquota -$type $usr -b $blk_soft -B $blk_hard -i $i_soft -I $i_hard $mntpt"
532             echo "+ $cmd"
533             eval $cmd || error "$cmd FAILED!"
534         done
535         # display the quota status
536         echo "Quota settings for $usr : "
537         $LFS quota -v -u $usr $mntpt || true
538     done
539 }
540
541 zconf_mount() {
542     local OPTIONS
543     local client=$1
544     local mnt=$2
545     # Only supply -o to mount if we have options
546     if [ -n "$MOUNTOPT" ]; then
547         OPTIONS="-o $MOUNTOPT"
548     fi
549     local device=$MGSNID:/$FSNAME
550     if [ -z "$mnt" -o -z "$FSNAME" ]; then
551         echo Bad zconf mount command: opt=$OPTIONS dev=$device mnt=$mnt
552         exit 1
553     fi
554
555     echo "Starting client: $client: $OPTIONS $device $mnt"
556     do_node $client mkdir -p $mnt
557     do_node $client mount -t lustre $OPTIONS $device $mnt || return 1
558     do_node $client "lctl set_param debug=\\\"$PTLDEBUG\\\";
559         lctl set_param subsystem_debug=\\\"${SUBSYSTEM# }\\\";
560         lctl set_param debug_mb=${DEBUG_SIZE}"
561
562     return 0
563 }
564
565 zconf_umount() {
566     local client=$1
567     local mnt=$2
568     local force
569     local busy
570     local need_kill
571
572     [ "$3" ] && force=-f
573     local running=$(do_node $client "grep -c $mnt' ' /proc/mounts") || true
574     if [ $running -ne 0 ]; then
575         echo "Stopping client $client $mnt (opts:$force)"
576         do_node $client lsof -t $mnt || need_kill=no
577         if [ "x$force" != "x" -a "x$need_kill" != "xno" ]; then
578             pids=$(do_node $client lsof -t $mnt | sort -u);
579             if [ -n $pids ]; then
580                 do_node $client kill -9 $pids || true
581             fi
582         fi
583
584         busy=$(do_node $client "umount $force $mnt 2>&1" | grep -c "busy") || true
585         if [ $busy -ne 0 ] ; then
586             echo "$mnt is still busy, wait one second" && sleep 1
587             do_node $client umount $force $mnt
588         fi
589     fi
590 }
591
592 # nodes is comma list
593 sanity_mount_check_nodes () {
594     local nodes=$1
595     shift
596     local mnts="$@"
597     local mnt
598
599     # FIXME: assume that all cluster nodes run the same os
600     [ "$(uname)" = Linux ] || return 0
601
602     local rc=0
603     for mnt in $mnts ; do
604         do_nodes $nodes "running=\\\$(grep -c $mnt' ' /proc/mounts);
605 mpts=\\\$(mount | grep -w -c $mnt);
606 if [ \\\$running -ne \\\$mpts ]; then
607     echo \\\$(hostname) env are INSANE!;
608     exit 1;
609 fi"
610     [ $? -eq 0 ] || rc=1
611     done
612     return $rc
613 }
614
615 sanity_mount_check_servers () {
616     [ "$CLIENTONLY" ] && 
617         { echo "CLIENTONLY mode, skip mount_check_servers"; return 0; } || true
618     echo Checking servers environments
619
620     # FIXME: modify get_facets to display all facets wo params
621     local facets="$(get_facets OST),$(get_facets MDS),mgs"
622     local node
623     local mntpt
624     local facet
625     for facet in ${facets//,/ }; do
626         node=$(facet_host ${facet})
627         mntpt=$(facet_mntpt $facet)
628         sanity_mount_check_nodes $node $mntpt ||
629             { error "server $node environments are insane!"; return 1; }
630     done
631 }
632
633 sanity_mount_check_clients () {
634     local clients=${1:-$CLIENTS}
635     local mntpt=${2:-$MOUNT}
636     local mntpt2=${3:-$MOUNT2}
637
638     [ -z $clients ] && clients=$(hostname)
639     echo Checking clients $clients environments
640
641     sanity_mount_check_nodes $clients $mntpt $mntpt2 ||
642        error "clients environments are insane!"
643 }
644
645 sanity_mount_check () {
646     sanity_mount_check_servers || return 1
647     sanity_mount_check_clients || return 2
648 }
649
650 # mount clients if not mouted
651 zconf_mount_clients() {
652     local clients=$1
653     local mnt=$2
654     local OPTIONS=${3:-$MOUNTOPT}
655
656     # Only supply -o to mount if we have options
657     if [ "$OPTIONS" ]; then
658         OPTIONS="-o $OPTIONS"
659     fi
660     local device=$MGSNID:/$FSNAME
661     if [ -z "$mnt" -o -z "$FSNAME" ]; then
662         echo Bad zconf mount command: opt=$OPTIONS dev=$device mnt=$mnt
663         exit 1
664     fi
665
666     echo "Starting client $clients: $OPTIONS $device $mnt"
667
668     do_nodes $clients "
669 running=\\\$(mount | grep -c $mnt' ');
670 rc=0;
671 if [ \\\$running -eq 0 ] ; then
672     mkdir -p $mnt;
673     mount -t lustre $OPTIONS $device $mnt;
674     rc=$?;
675 fi;
676 exit $rc"
677
678     echo "Started clients $clients: "
679     do_nodes $clients "mount | grep -w $mnt"
680
681     do_nodes $clients "sysctl -w lnet.debug=\\\"$PTLDEBUG\\\";
682         sysctl -w lnet.subsystem_debug=\\\"${SUBSYSTEM# }\\\";
683         sysctl -w lnet.debug_mb=${DEBUG_SIZE};"
684
685     return 0
686 }
687
688 zconf_umount_clients() {
689     local clients=$1
690     local mnt=$2
691     local force
692
693     [ "$3" ] && force=-f
694
695     echo "Stopping clients: $clients $mnt (opts:$force)"
696     do_nodes $clients "running=\\\$(grep -c $mnt' ' /proc/mounts);
697 if [ \\\$running -ne 0 ] ; then
698 echo Stopping client \\\$(hostname) $mnt opts:$force;
699 lsof -t $mnt || need_kill=no;
700 if [ "x$force" != "x" -a "x\\\$need_kill" != "xno" ]; then
701     pids=\\\$(lsof -t $mnt | sort -u);
702     if [ -n \\\"\\\$pids\\\" ]; then
703              kill -9 \\\$pids;
704     fi
705 fi;
706 busy=\\\$(umount $force $mnt 2>&1 | grep -c "busy");
707 if [ \\\$busy -ne 0 ] ; then
708     echo "$mnt is still busy, wait one second" && sleep 1;
709     umount $force $mnt;
710 fi
711 fi"
712 }
713
714 shutdown_node () {
715     local node=$1
716     echo + $POWER_DOWN $node
717     $POWER_DOWN $node
718 }
719
720 shutdown_node_hard () {
721     local host=$1
722     local attempts=3
723
724     for i in $(seq $attempts) ; do
725         shutdown_node $host
726         sleep 1
727         ping -w 3 -c 1 $host > /dev/null 2>&1 || return 0
728         echo "waiting for $host to fail attempts=$attempts"
729         [ $i -lt $attempts ] || \
730             { echo "$host still pingable after power down! attempts=$attempts" && return 1; }
731     done
732 }
733
734 shutdown_client() {
735     local client=$1
736     local mnt=${2:-$MOUNT}
737     local attempts=3
738
739     if [ "$FAILURE_MODE" = HARD ]; then
740         shutdown_node_hard $client
741     else
742        zconf_umount_clients $client $mnt -f
743     fi
744 }
745
746 facets_on_host () {
747     local host=$1
748     local facets="$(get_facets OST),$(get_facets MDS)"
749     local affected
750
751     combined_mgs_mds || facets="$facets,mgs"
752
753     for facet in ${facets//,/ }; do
754         if [ $(facet_active_host $facet) == $host ]; then
755            affected="$affected $facet"
756         fi
757     done
758
759     echo $(comma_list $affected)
760 }
761
762 shutdown_facet() {
763     local facet=$1
764
765     if [ "$FAILURE_MODE" = HARD ]; then
766         shutdown_node_hard $(facet_active_host $facet)
767     else
768         stop $facet
769     fi
770 }
771
772 reboot_node() {
773     local node=$1
774     echo + $POWER_UP $node
775     $POWER_UP $node
776 }
777
778 remount_facet() {
779     local facet=$1
780
781     stop $facet
782     mount_facet $facet
783 }
784
785 reboot_facet() {
786     local facet=$1
787     if [ "$FAILURE_MODE" = HARD ]; then
788         reboot_node $(facet_active_host $facet)
789     else
790         sleep 10
791     fi
792 }
793
794 boot_node() {
795     local node=$1
796     if [ "$FAILURE_MODE" = HARD ]; then
797        reboot_node $node
798        wait_for_host $node
799     fi
800 }
801
802 # recovery-scale functions
803 check_progs_installed () {
804     local clients=$1
805     shift
806     local progs=$@
807
808     do_nodes $clients "PATH=:$PATH; status=true;
809 for prog in $progs; do
810     if ! [ \\\"\\\$(which \\\$prog)\\\"  -o  \\\"\\\${!prog}\\\" ]; then
811        echo \\\$prog missing on \\\$(hostname);
812        status=false;
813     fi
814 done;
815 eval \\\$status"
816 }
817
818 client_var_name() {
819     echo __$(echo $1 | tr '-' 'X')
820 }
821
822 start_client_load() {
823     local client=$1
824     local load=$2
825     local var=$(client_var_name $client)_load
826     eval export ${var}=$load
827
828     do_node $client "PATH=$PATH MOUNT=$MOUNT ERRORS_OK=$ERRORS_OK \
829                               BREAK_ON_ERROR=$BREAK_ON_ERROR \
830                               END_RUN_FILE=$END_RUN_FILE \
831                               LOAD_PID_FILE=$LOAD_PID_FILE \
832                               TESTSUITELOG=$TESTSUITELOG \
833                               run_${load}.sh" &
834     CLIENT_LOAD_PIDS="$CLIENT_LOAD_PIDS $!"
835     log "Started client load: ${load} on $client"
836
837     return 0
838 }
839
840 start_client_loads () {
841     local -a clients=(${1//,/ })
842     local numloads=${#CLIENT_LOADS[@]}
843     local testnum
844
845     for ((nodenum=0; nodenum < ${#clients[@]}; nodenum++ )); do
846         testnum=$((nodenum % numloads))
847         start_client_load ${clients[nodenum]} ${CLIENT_LOADS[testnum]}
848     done
849     # bug 22169: wait the background threads to start
850     sleep 2
851 }
852
853 # only for remote client
854 check_client_load () {
855     local client=$1
856     local var=$(client_var_name $client)_load
857     local TESTLOAD=run_${!var}.sh
858
859     ps auxww | grep -v grep | grep $client | grep -q "$TESTLOAD" || return 1
860
861     # bug 18914: try to connect several times not only when
862     # check ps, but  while check_catastrophe also
863     local tries=3
864     local RC=254
865     while [ $RC = 254 -a $tries -gt 0 ]; do
866         let tries=$tries-1
867         # assume success
868         RC=0
869         if ! check_catastrophe $client; then
870             RC=${PIPESTATUS[0]}
871             if [ $RC -eq 254 ]; then
872                 # FIXME: not sure how long we shuold sleep here
873                 sleep 10
874                 continue
875             fi
876             echo "check catastrophe failed: RC=$RC "
877             return $RC
878         fi
879     done
880
881     # We can continue try to connect if RC=254
882     # Just print the warning about this
883     if [ $RC = 254 ]; then
884         echo "got a return status of $RC from do_node while checking catastrophe on $client"
885     fi
886
887     # see if the load is still on the client
888     tries=3
889     RC=254
890     while [ $RC = 254 -a $tries -gt 0 ]; do
891         let tries=$tries-1
892         # assume success
893         RC=0
894         if ! do_node $client "ps auxwww | grep -v grep | grep -q $TESTLOAD"; then
895             RC=${PIPESTATUS[0]}
896             sleep 30
897         fi
898     done
899     if [ $RC = 254 ]; then
900         echo "got a return status of $RC from do_node while checking (catastrophe and 'ps') the client load on $client"
901         # see if we can diagnose a bit why this is
902     fi
903
904     return $RC
905 }
906 check_client_loads () {
907    local clients=${1//,/ }
908    local client=
909    local rc=0
910
911    for client in $clients; do
912       check_client_load $client
913       rc=${PIPESTATUS[0]}
914       if [ "$rc" != 0 ]; then
915         log "Client load failed on node $client, rc=$rc"
916         return $rc
917       fi
918    done
919 }
920
921 restart_client_loads () {
922     local clients=${1//,/ }
923     local expectedfail=${2:-""}
924     local client=
925     local rc=0
926
927     for client in $clients; do
928         check_client_load $client
929         rc=${PIPESTATUS[0]}
930         if [ "$rc" != 0 -a "$expectedfail" ]; then
931             local var=$(client_var_name $client)_load
932             start_client_load $client ${!var}
933             echo "Restarted client load ${!var}: on $client. Checking ..."
934             check_client_load $client
935             rc=${PIPESTATUS[0]}
936             if [ "$rc" != 0 ]; then
937                 log "Client load failed to restart on node $client, rc=$rc"
938                 # failure one client load means test fail
939                 # we do not need to check other
940                 return $rc
941             fi
942         else
943             return $rc
944         fi
945     done
946 }
947 # End recovery-scale functions
948
949 # verify that lustre actually cleaned up properly
950 cleanup_check() {
951     [ -f $CATASTROPHE ] && [ `cat $CATASTROPHE` -ne 0 ] && \
952         error "LBUG/LASSERT detected"
953     BUSY=`dmesg | grep -i destruct || true`
954     if [ "$BUSY" ]; then
955         echo "$BUSY" 1>&2
956         [ -e $TMP/debug ] && mv $TMP/debug $TMP/debug-busy.`date +%s`
957         exit 205
958     fi
959
960     check_mem_leak || exit 204
961
962     [ "`lctl dl 2> /dev/null | wc -l`" -gt 0 ] && lctl dl && \
963         echo "$0: lustre didn't clean up..." 1>&2 && return 202 || true
964
965     if module_loaded lnet || module_loaded libcfs; then
966         echo "$0: modules still loaded..." 1>&2
967         /sbin/lsmod 1>&2
968         return 203
969     fi
970     return 0
971 }
972
973 wait_update () {
974     local node=$1
975     local TEST=$2
976     local FINAL=$3
977     local MAX=${4:-90}
978
979         local RESULT
980         local WAIT=0
981         local sleep=5
982         while [ true ]; do
983             RESULT=$(do_node $node "$TEST")
984             if [ "$RESULT" == "$FINAL" ]; then
985                 echo "Updated after $WAIT sec: wanted '$FINAL' got '$RESULT'"
986                 return 0
987             fi
988             [ $WAIT -ge $MAX ] && break
989             echo "Waiting $((MAX - WAIT)) secs for update"
990             WAIT=$((WAIT + sleep))
991             sleep $sleep
992         done
993         echo "Update not seen after $MAX sec: wanted '$FINAL' got '$RESULT'"
994         return 3
995 }
996
997 wait_update_facet () {
998     local facet=$1
999     shift
1000     wait_update  $(facet_active_host $facet) "$@"
1001 }
1002
1003 wait_delete_completed () {
1004     local TOTALPREV=`lctl get_param -n osc.*.kbytesavail | \
1005                      awk 'BEGIN{total=0}; {total+=$1}; END{print total}'`
1006
1007     local WAIT=0
1008     local MAX_WAIT=20
1009     while [ "$WAIT" -ne "$MAX_WAIT" ]; do
1010         sleep 1
1011         TOTAL=`lctl get_param -n osc.*.kbytesavail | \
1012                awk 'BEGIN{total=0}; {total+=$1}; END{print total}'`
1013         [ "$TOTAL" -eq "$TOTALPREV" ] && return 0
1014         echo "Waiting delete completed ... prev: $TOTALPREV current: $TOTAL "
1015         TOTALPREV=$TOTAL
1016         WAIT=$(( WAIT + 1))
1017     done
1018     echo "Delete is not completed in $MAX_WAIT sec"
1019     return 1
1020 }
1021
1022 wait_for_host() {
1023     local hostlist=$1
1024
1025     # we can use "for" here because we are waiting the slowest
1026     for host in ${hostlist//,/ }; do
1027         check_network "$host" 900
1028     done
1029     while ! do_nodes $hostlist hostname  > /dev/null; do sleep 5; done
1030 }
1031
1032 wait_for_facet() {
1033     local facetlist=$1
1034     local hostlist
1035
1036     for facet in ${facetlist//,/ }; do
1037         hostlist=$(expand_list $hostlist $(facet_active_host $facet))
1038     done
1039     wait_for_host $hostlist
1040 }
1041
1042 _wait_recovery_complete () {
1043     local param=$1
1044
1045     # Use default policy if $2 is not passed by caller.
1046     local MAX=${2:-$(max_recovery_time)}
1047
1048     local WAIT=0
1049     local STATUS=
1050
1051     while [ $WAIT -lt $MAX ]; do
1052         STATUS=$(lctl get_param -n $param | grep status)
1053         echo $param $STATUS
1054         [[ $STATUS = "status: COMPLETE" || $STATUS = "status: INACTIVE" ]] && return 0
1055         sleep 5
1056         WAIT=$((WAIT + 5))
1057         echo "Waiting $((MAX - WAIT)) secs for $param recovery done. $STATUS"
1058     done
1059     echo "$param recovery not done in $MAX sec. $STATUS"
1060     return 1
1061 }
1062
1063 wait_recovery_complete () {
1064     local facet=$1
1065
1066     # with an assumption that at_max is the same on all nodes
1067     local MAX=${2:-$(max_recovery_time)}
1068
1069     local facets=$facet
1070     if [ "$FAILURE_MODE" = HARD ]; then
1071         facets=$(facets_on_host $(facet_active_host $facet))
1072     fi
1073     echo affected facets: $facets
1074
1075     # we can use "for" here because we are waiting the slowest
1076     for facet in ${facets//,/ }; do
1077         local var_svc=${facet}_svc
1078         local param="*.${!var_svc}.recovery_status"
1079
1080         local host=$(facet_active_host $facet)
1081         do_rpc_nodes $host _wait_recovery_complete $param $MAX
1082     done
1083 }
1084
1085 wait_mds_ost_sync () {
1086     # just because recovery is done doesn't mean we've finished
1087     # orphan cleanup. Wait for llogs to get synchronized.
1088     echo "Waiting for orphan cleanup..."
1089     # MAX value includes time needed for MDS-OST reconnection
1090     local MAX=$(( TIMEOUT * 2 ))
1091     local WAIT=0
1092     while [ $WAIT -lt $MAX ]; do
1093         local -a sync=($(do_nodes $(comma_list $(osts_nodes)) \
1094             "$LCTL get_param -n obdfilter.*.mds_sync"))
1095         local con=1
1096         for ((i=0; i<${#sync[@]}; i++)); do
1097             [ ${sync[$i]} -eq 0 ] && continue
1098             # there is a not finished MDS-OST synchronization
1099             con=0
1100             break;
1101         done
1102         sleep 2 # increase waiting time and cover statfs cache
1103         [ ${con} -eq 1 ] && return 0
1104         echo "Waiting $WAIT secs for $facet mds-ost sync done."
1105         WAIT=$((WAIT + 2))
1106     done
1107     echo "$facet recovery not done in $MAX sec. $STATUS"
1108     return 1
1109 }
1110
1111 wait_destroy_complete () {
1112     echo "Waiting for destroy to be done..."
1113     # MAX value shouldn't be big as this mean server responsiveness
1114     # never increase this just to make test pass but investigate
1115     # why it takes so long time
1116     local MAX=5
1117     local WAIT=0
1118     while [ $WAIT -lt $MAX ]; do
1119         local -a RPCs=($($LCTL get_param -n osc.*.destroys_in_flight))
1120         local con=1
1121         for ((i=0; i<${#RPCs[@]}; i++)); do
1122             [ ${RPCs[$i]} -eq 0 ] && continue
1123             # there are still some destroy RPCs in flight
1124             con=0
1125             break;
1126         done
1127         sleep 1
1128         [ ${con} -eq 1 ] && return 0 # done waiting
1129         echo "Waiting $WAIT secs for destroys to be done."
1130         WAIT=$((WAIT + 1))
1131     done
1132     echo "Destroys weren't done in $MAX sec."
1133     return 1
1134 }
1135
1136 wait_exit_ST () {
1137     local facet=$1
1138
1139     local WAIT=0
1140     local INTERVAL=1
1141     local running
1142     # conf-sanity 31 takes a long time cleanup
1143     while [ $WAIT -lt 300 ]; do
1144         running=$(do_facet ${facet} "lsmod | grep lnet > /dev/null && lctl dl | grep ' ST '") || true
1145         [ -z "${running}" ] && return 0
1146         echo "waited $WAIT for${running}"
1147         [ $INTERVAL -lt 64 ] && INTERVAL=$((INTERVAL + INTERVAL))
1148         sleep $INTERVAL
1149         WAIT=$((WAIT + INTERVAL))
1150     done
1151     echo "service didn't stop after $WAIT seconds.  Still running:"
1152     echo ${running}
1153     return 1
1154 }
1155
1156 wait_remote_prog () {
1157    local prog=$1
1158    local WAIT=0
1159    local INTERVAL=5
1160    local rc=0
1161
1162    [ "$PDSH" = "no_dsh" ] && return 0
1163
1164    while [ $WAIT -lt $2 ]; do
1165         running=$(ps uax | grep "$PDSH.*$prog.*$MOUNT" | grep -v grep) || true
1166         [ -z "${running}" ] && return 0 || true
1167         echo "waited $WAIT for: "
1168         echo "$running"
1169         [ $INTERVAL -lt 60 ] && INTERVAL=$((INTERVAL + INTERVAL))
1170         sleep $INTERVAL
1171         WAIT=$((WAIT + INTERVAL))
1172     done
1173     local pids=$(ps  uax | grep "$PDSH.*$prog.*$MOUNT" | grep -v grep | awk '{print $2}')
1174     [ -z "$pids" ] && return 0
1175     echo "$PDSH processes still exists after $WAIT seconds.  Still running: $pids"
1176     # FIXME: not portable
1177     for pid in $pids; do
1178         cat /proc/${pid}/status || true
1179         cat /proc/${pid}/wchan || true
1180         echo "Killing $pid"
1181         kill -9 $pid || true
1182         sleep 1
1183         ps -P $pid && rc=1
1184     done
1185
1186     return $rc
1187 }
1188
1189 clients_up() {
1190     # not every config has many clients
1191     sleep 1
1192     if [ -n "$CLIENTS" ]; then
1193         $PDSH $CLIENTS "stat -f $MOUNT" > /dev/null
1194     else
1195         stat -f $MOUNT > /dev/null
1196     fi
1197 }
1198
1199 client_up() {
1200     local client=$1
1201     # usually checked on particular client or locally
1202     sleep 1
1203     if [ ! -z "$client" ]; then
1204         $PDSH $client "stat -f $MOUNT" > /dev/null
1205     else
1206         stat -f $MOUNT > /dev/null
1207     fi
1208 }
1209
1210 client_evicted() {
1211     ! client_up $1
1212 }
1213
1214 client_reconnect() {
1215     uname -n >> $MOUNT/recon
1216     if [ -z "$CLIENTS" ]; then
1217         df $MOUNT; uname -n >> $MOUNT/recon
1218     else
1219         do_nodes $CLIENTS "df $MOUNT; uname -n >> $MOUNT/recon" > /dev/null
1220     fi
1221     echo Connected clients:
1222     cat $MOUNT/recon
1223     ls -l $MOUNT/recon > /dev/null
1224     rm $MOUNT/recon
1225 }
1226
1227 facet_failover() {
1228     local facet=$1
1229     local sleep_time=$2
1230     local host=$(facet_active_host $facet)
1231
1232     echo "Failing $facet on node $host"
1233
1234     local affected=$facet
1235
1236     if [ "$FAILURE_MODE" = HARD ]; then
1237         affected=$(facets_on_host $host)
1238     fi
1239
1240     shutdown_facet $facet
1241
1242     echo affected facets: $affected
1243
1244     [ -n "$sleep_time" ] && sleep $sleep_time
1245
1246     reboot_facet $facet
1247     clients_up &
1248     local dfpid=$!
1249     RECOVERY_START_TIME=`date +%s`
1250     echo "df pid is $dfpid"
1251
1252     change_active $affected
1253
1254     wait_for_facet $affected
1255     # start mgs first if it is affected
1256     if ! combined_mgs_mds && list_member $affected mgs; then
1257         mount_facet mgs || error "Restart of mgs failed"
1258     fi
1259     # FIXME; has to be changed to mount all facets concurrently 
1260     affected=$(exclude_items_from_list $affected mgs)
1261     for facet in ${affected//,/ }; do
1262         mount_facet $facet || error "Restart of $facet on node $host failed!"
1263     done
1264 }
1265
1266 obd_name() {
1267     local facet=$1
1268 }
1269
1270 replay_barrier() {
1271     local facet=$1
1272     do_facet $facet sync
1273     df $MOUNT
1274     local svc=${facet}_svc
1275     do_facet $facet $LCTL --device %${!svc} notransno
1276     do_facet $facet $LCTL --device %${!svc} readonly
1277     do_facet $facet $LCTL mark "$facet REPLAY BARRIER on ${!svc}"
1278     $LCTL mark "local REPLAY BARRIER on ${!svc}"
1279 }
1280
1281 replay_barrier_nodf() {
1282     local facet=$1    echo running=${running}
1283     do_facet $facet sync
1284     local svc=${facet}_svc
1285     echo Replay barrier on ${!svc}
1286     do_facet $facet $LCTL --device %${!svc} notransno
1287     do_facet $facet $LCTL --device %${!svc} readonly
1288     do_facet $facet $LCTL mark "$facet REPLAY BARRIER on ${!svc}"
1289     $LCTL mark "local REPLAY BARRIER on ${!svc}"
1290 }
1291
1292 mds_evict_client() {
1293     UUID=`lctl get_param -n mdc.${mds_svc}-mdc-*.uuid`
1294     local mdtdevice=$(get_mds_mdt_device_proc_path)
1295     do_facet mds "lctl set_param -n ${mdtdevice}.${mds_svc}.evict_client $UUID"
1296 }
1297
1298 ost_evict_client() {
1299     UUID=`lctl get_param -n osc.${ost1_svc}-osc-*.uuid`
1300     do_facet ost1 "lctl set_param -n obdfilter.${ost1_svc}.evict_client $UUID"
1301 }
1302
1303 fail() {
1304     facet_failover $* || error "failover: $?"
1305     clients_up || error "post-failover df: $?"
1306 }
1307
1308 fail_nodf() {
1309     local facet=$1
1310     facet_failover $facet
1311 }
1312
1313 fail_abort() {
1314     local facet=$1
1315     stop $facet
1316     change_active $facet
1317     mount_facet $facet -o abort_recovery
1318     clients_up || echo "first df failed: $?"
1319     clients_up || error "post-failover df: $?"
1320 }
1321
1322 do_lmc() {
1323     echo There is no lmc.  This is mountconf, baby.
1324     exit 1
1325 }
1326
1327 h2gm () {
1328     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
1329         ID=`$PDSH $1 $GMNALNID -l | cut -d\  -f2`
1330         echo $ID"@gm"
1331     fi
1332 }
1333
1334 h2name_or_ip() {
1335     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
1336         echo $1"@$2"
1337     fi
1338 }
1339
1340 h2ptl() {
1341    if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
1342        ID=`xtprocadmin -n $1 2>/dev/null | egrep -v 'NID' | awk '{print $1}'`
1343        if [ -z "$ID" ]; then
1344            echo "Could not get a ptl id for $1..."
1345            exit 1
1346        fi
1347        echo $ID"@ptl"
1348    fi
1349 }
1350 declare -fx h2ptl
1351
1352 h2tcp() {
1353     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
1354         echo $1"@tcp"
1355     fi
1356 }
1357 declare -fx h2tcp
1358
1359 h2elan() {
1360     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
1361         if type __h2elan >/dev/null 2>&1; then
1362             ID=$(__h2elan $1)
1363         else
1364             ID=`echo $1 | sed 's/[^0-9]*//g'`
1365         fi
1366         echo $ID"@elan"
1367     fi
1368 }
1369 declare -fx h2elan
1370
1371 h2openib() {
1372     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
1373         ID=`echo $1 | sed 's/[^0-9]*//g'`
1374         echo $ID"@openib"
1375     fi
1376 }
1377 declare -fx h2openib
1378
1379 h2o2ib() {
1380     h2name_or_ip "$1" "o2ib"
1381 }
1382 declare -fx h2o2ib
1383
1384 facet_host() {
1385     local facet=$1
1386
1387     [ "$facet" == client ] && echo -n $HOSTNAME && return
1388     varname=${facet}_HOST
1389     if [ -z "${!varname}" ]; then
1390         if [ "${facet:0:3}" == "ost" ]; then
1391             eval ${facet}_HOST=${ost_HOST}
1392         fi
1393     fi
1394     echo -n ${!varname}
1395 }
1396
1397 facet_active() {
1398     local facet=$1
1399     local activevar=${facet}active
1400
1401     if [ -f $TMP/${facet}active ] ; then
1402         source $TMP/${facet}active
1403     fi
1404
1405     active=${!activevar}
1406     if [ -z "$active" ] ; then
1407         echo -n ${facet}
1408     else
1409         echo -n ${active}
1410     fi
1411 }
1412
1413 facet_active_host() {
1414     local facet=$1
1415     local active=`facet_active $facet`
1416     if [ "$facet" == client ]; then
1417         echo $HOSTNAME
1418     else
1419         echo `facet_host $active`
1420     fi
1421 }
1422
1423 change_active() {
1424     local facetlist=$1
1425     local facet
1426
1427     facetlist=$(exclude_items_from_list $facetlist mgs)
1428
1429     for facet in ${facetlist//,/ }; do
1430     local failover=${facet}failover
1431     local host=`facet_host $failover`
1432     [ -z "$host" ] && return
1433
1434     local curactive=`facet_active $facet`
1435     if [ -z "${curactive}" -o "$curactive" == "$failover" ] ; then
1436         eval export ${facet}active=$facet
1437     else
1438         eval export ${facet}active=$failover
1439     fi
1440     # save the active host for this facet
1441     local activevar=${facet}active
1442     echo "$activevar=${!activevar}" > $TMP/$activevar
1443     local TO=`facet_active_host $facet`
1444     echo "Failover $facet to $TO"
1445     done
1446 }
1447
1448 do_node() {
1449     local verbose=false
1450     # do not stripe off hostname if verbose, bug 19215
1451     if [ x$1 = x--verbose ]; then
1452         shift
1453         verbose=true
1454     fi
1455
1456     local HOST=$1
1457     shift
1458     local myPDSH=$PDSH
1459     if [ "$HOST" = "$HOSTNAME" ]; then
1460         myPDSH="no_dsh"
1461     elif [ -z "$myPDSH" -o "$myPDSH" = "no_dsh" ]; then
1462         echo "cannot run remote command on $HOST with $myPDSH"
1463         return 128
1464     fi
1465     if $VERBOSE; then
1466         echo "CMD: $HOST $@" >&2
1467         $myPDSH $HOST $LCTL mark "$@" > /dev/null 2>&1 || :
1468     fi
1469
1470     if [ "$myPDSH" = "rsh" ]; then
1471 # we need this because rsh does not return exit code of an executed command
1472         local command_status="$TMP/cs"
1473         rsh $HOST ":> $command_status"
1474         rsh $HOST "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin;
1475                     cd $RPWD; sh -c \"$@\") ||
1476                     echo command failed >$command_status"
1477         [ -n "$($myPDSH $HOST cat $command_status)" ] && return 1 || true
1478         return 0
1479     fi
1480
1481     if $verbose ; then
1482         # print HOSTNAME for myPDSH="no_dsh"
1483         if [[ $myPDSH = no_dsh ]]; then
1484             $myPDSH $HOST "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin; cd $RPWD; sh -c \"$@\")" | sed -e "s/^/${HOSTNAME}: /"
1485         else
1486             $myPDSH $HOST "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin; cd $RPWD; sh -c \"$@\")"
1487         fi
1488     else
1489         $myPDSH $HOST "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin; cd $RPWD; sh -c \"$@\")" | sed "s/^${HOST}: //"
1490     fi
1491     return ${PIPESTATUS[0]}
1492 }
1493
1494 do_nodev() {
1495     do_node --verbose "$@"
1496 }
1497
1498 single_local_node () {
1499    [ "$1" = "$HOSTNAME" ]
1500 }
1501
1502 do_nodes() {
1503     local verbose=false
1504     # do not stripe off hostname if verbose, bug 19215
1505     if [ x$1 = x--verbose ]; then
1506         shift
1507         verbose=true
1508     fi
1509
1510     local rnodes=$1
1511     shift
1512
1513     if $(single_local_node $rnodes); then
1514         if $verbose; then
1515            do_nodev $rnodes "$@"
1516         else
1517            do_node $rnodes "$@"
1518         fi
1519         return $?
1520     fi
1521
1522     # This is part from do_node
1523     local myPDSH=$PDSH
1524
1525     [ -z "$myPDSH" -o "$myPDSH" = "no_dsh" -o "$myPDSH" = "rsh" ] && \
1526         echo "cannot run remote command on $rnodes with $myPDSH" && return 128
1527
1528     if $VERBOSE; then
1529         echo "CMD: $rnodes $@" >&2
1530         $myPDSH $rnodes $LCTL mark "$@" > /dev/null 2>&1 || :
1531     fi
1532
1533     # do not replace anything from pdsh output if -N is used
1534     # -N     Disable hostname: prefix on lines of output.
1535     if $verbose || [[ $myPDSH = *-N* ]]; then
1536         $myPDSH $rnodes "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin; cd $RPWD; sh -c \"$@\")"
1537     else
1538         $myPDSH $rnodes "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin; cd $RPWD; sh -c \"$@\")" | sed -re "s/^[^:]*: //g"
1539     fi
1540     return ${PIPESTATUS[0]}
1541 }
1542
1543 do_facet() {
1544     local facet=$1
1545     shift
1546     local HOST=`facet_active_host $facet`
1547     [ -z $HOST ] && echo No host defined for facet ${facet} && exit 1
1548     do_node $HOST "$@"
1549 }
1550
1551 do_nodesv() {
1552     do_nodes --verbose "$@"
1553 }
1554
1555 add() {
1556     local facet=$1
1557     shift
1558     # make sure its not already running
1559     stop ${facet} -f
1560     rm -f $TMP/${facet}active
1561     do_facet ${facet} $MKFS $*
1562 }
1563
1564 ostdevname() {
1565     num=$1
1566     DEVNAME=OSTDEV$num
1567     #if $OSTDEVn isn't defined, default is $OSTDEVBASE + num
1568     eval DEVPTR=${!DEVNAME:=${OSTDEVBASE}${num}}
1569     echo -n $DEVPTR
1570 }
1571
1572 facet_mntpt() {
1573     local facet=$1
1574     if combined_mgs_mds && [[ $facet = "mgs" ]]  ; then
1575         facet="mds"
1576     fi
1577     local var=${facet}_MOUNT
1578     eval mntpt=${!var:-${MOUNT%/*}/$facet}
1579
1580     echo -n $mntpt
1581 }
1582
1583 ########
1584 ## MountConf setup
1585
1586 stopall() {
1587     # make sure we are using the primary server, so test-framework will
1588     # be able to clean up properly.
1589     activemds=`facet_active mds`
1590     if [ $activemds != "mds" ]; then
1591         fail mds
1592     fi
1593
1594     local clients=$CLIENTS
1595     [ -z $clients ] && clients=$(hostname)
1596
1597     zconf_umount_clients $clients $MOUNT "$*" || true
1598     [ -n "$MOUNT2" ] && zconf_umount_clients $clients $MOUNT2 "$*" || true
1599
1600     [ "$CLIENTONLY" ] && return
1601     # The add fn does rm ${facet}active file, this would be enough
1602     # if we use do_facet <facet> only after the facet added, but
1603     # currently we use do_facet mds in local.sh
1604     stop mds -f
1605     rm -f ${TMP}/mdsactive
1606     for num in `seq $OSTCOUNT`; do
1607         stop ost$num -f
1608         rm -f $TMP/ost${num}active
1609     done
1610     if ! combined_mgs_mds ; then
1611         stop mgs 
1612     fi
1613
1614     return 0
1615 }
1616
1617 cleanup_echo_devs () {
1618     local devs=$($LCTL dl | grep echo | awk '{print $4}')
1619
1620     for dev in $devs; do
1621         $LCTL --device $dev cleanup
1622         $LCTL --device $dev detach
1623     done
1624 }
1625
1626 cleanupall() {
1627     nfs_client_mode && return
1628
1629     stopall $*
1630     cleanup_echo_devs
1631
1632     unload_modules
1633 }
1634
1635 combined_mgs_mds () {
1636     [[ $MDSDEV = $MGSDEV ]] && [[ $mds_HOST = $mgs_HOST ]]
1637 }
1638
1639 mkfs_opts () {
1640     local facet=$1
1641
1642     local tgt=$(echo $facet | tr -d [:digit:] | tr "[:lower:]" "[:upper:]")
1643     local optvar=${tgt}_MKFS_OPTS
1644     local opt=${!optvar}
1645
1646     # FIXME: ! combo  mgs/mds + mgsfailover is not supported yet
1647     [[ $facet = mgs ]] && echo $opt && return
1648
1649     # 1.
1650     # --failnode options 
1651     local var=${facet}failover_HOST
1652     if [ x"${!var}" != x ] && [ x"${!var}" != x$(facet_host $facet) ] ; then
1653         local failnode=$(h2$NETTYPE ${!var})
1654         failnode="--failnode=$failnode"
1655         # options does not contain 
1656         # or contains wrong --failnode=
1657         if [[ $opt != *${failnode}* ]]; then
1658             opt=$(echo $opt | sed 's/--failnode=.* / /')
1659             opt="$opt $failnode"
1660         fi
1661     fi
1662
1663     # 2.
1664     # --mgsnode options
1665     # no additional mkfs mds "--mgsnode" option for this configuration
1666     if [[ $facet = mds ]] && combined_mgs_mds; then
1667         echo $opt
1668         return
1669     fi
1670
1671     # additional mkfs "--mgsnode"
1672     local mgsnode="--mgsnode=$MGSNID"
1673     opt=${opt//$mgsnode }
1674     for nid in ${MGSNID//:/ }; do
1675         local mgsnode="--mgsnode=$nid"
1676         # options does not contain
1677         # --mgsnode=$nid
1678         if [[ $opt != *${mgsnode}" "* ]]; then
1679             opt="$opt --mgsnode=$nid"
1680         fi
1681     done
1682
1683     echo $opt
1684 }
1685
1686 formatall() {
1687     [ "$FSTYPE" ] && FSTYPE_OPT="--backfstype $FSTYPE"
1688
1689     stopall
1690     # We need ldiskfs here, may as well load them all
1691     load_modules
1692     [ "$CLIENTONLY" ] && return
1693     echo Formatting mgs, mds, osts
1694     if ! combined_mgs_mds ; then
1695         add mgs $(mkfs_opts mgs) $FSTYPE_OPT --reformat $MGSDEV || exit 10
1696     fi
1697
1698     if $VERBOSE; then
1699         add mds $(mkfs_opts mds) $FSTYPE_OPT --reformat $MDSDEV || exit 10
1700     else
1701         add mds $(mkfs_opts mds) $FSTYPE_OPT --reformat $MDSDEV > /dev/null || exit 10
1702     fi
1703
1704     # the ost-s could have different OST_MKFS_OPTS
1705     # because of different failnode-s
1706     for num in `seq $OSTCOUNT`; do
1707         if $VERBOSE; then
1708             add ost$num $(mkfs_opts ost${num}) $FSTYPE_OPT --reformat `ostdevname $num` || exit 10
1709         else
1710             add ost$num $(mkfs_opts ost${num}) $FSTYPE_OPT --reformat `ostdevname $num` > /dev/null || exit 10
1711         fi
1712     done
1713 }
1714
1715 mount_client() {
1716     grep " $1 " /proc/mounts || zconf_mount $HOSTNAME $*
1717 }
1718
1719 remount_client()
1720 {
1721         zconf_umount `hostname` $1 || error "umount failed"
1722         zconf_mount `hostname` $1 || error "mount failed"
1723 }
1724
1725 writeconf_facet () {
1726     local facet=$1
1727     local dev=$2
1728
1729     do_facet $facet "$TUNEFS --writeconf $dev"
1730 }
1731
1732 writeconf_all () {
1733     writeconf_facet mds $MDSDEV
1734
1735     for num in `seq $OSTCOUNT`; do
1736         DEVNAME=`ostdevname $num`
1737         writeconf_facet ost$num $DEVNAME
1738     done
1739 }
1740
1741 setupall() {
1742     nfs_client_mode && return
1743
1744     sanity_mount_check ||
1745         error "environments are insane!"
1746
1747     load_modules
1748     if [ -z "$CLIENTONLY" ]; then
1749         echo Setup mgs, mdt, osts
1750
1751         echo $WRITECONF | grep -q "writeconf" && \
1752             writeconf_all
1753
1754         if ! combined_mgs_mds ; then
1755             start mgs $MGSDEV $MGS_MOUNT_OPTS
1756         fi
1757
1758         start mds $MDSDEV $MDS_MOUNT_OPTS
1759         # We started mds, now we should set failover variable properly.
1760         # Set mdsfailover_HOST if it is not set (the default failnode).
1761         if [ -z "$mdsfailover_HOST" ]; then
1762            mdsfailover_HOST=$(facet_host mds)
1763         fi
1764
1765         for num in `seq $OSTCOUNT`; do
1766             DEVNAME=`ostdevname $num`
1767             start ost$num $DEVNAME $OST_MOUNT_OPTS
1768
1769             # We started ost$num, now we should set ost${num}failover variable properly.
1770             # Set ost${num}failover_HOST if it is not set (the default failnode).
1771             varname=ost${num}failover_HOST
1772             if [ -z "${!varname}" ]; then
1773                 eval ost${num}failover_HOST=$(facet_host ost${num})
1774             fi
1775
1776         done
1777     fi
1778     [ "$DAEMONFILE" ] && $LCTL debug_daemon start $DAEMONFILE $DAEMONSIZE
1779     mount_client $MOUNT
1780     [ -n "$CLIENTS" ] && zconf_mount_clients $CLIENTS $MOUNT
1781
1782     if [ "$MOUNT_2" ]; then
1783         mount_client $MOUNT2
1784         [ -n "$CLIENTS" ] && zconf_mount_clients $CLIENTS $MOUNT2
1785     fi
1786     sleep 5
1787     init_param_vars
1788 }
1789
1790 mounted_lustre_filesystems() {
1791         awk '($3 ~ "lustre" && $1 ~ ":") { print $2 }' /proc/mounts
1792 }
1793
1794 init_facet_vars () {
1795     [ "$CLIENTONLY" ] && return 0
1796     local facet=$1
1797     shift
1798     local device=$1
1799
1800     shift
1801
1802     eval export ${facet}_dev=${device}
1803     eval export ${facet}_opt=\"$@\"
1804
1805     local dev=${facet}_dev
1806     local label=$(do_facet ${facet} "$E2LABEL ${!dev}")
1807     [ -z "$label" ] && echo no label for ${!dev} && exit 1
1808
1809     eval export ${facet}_svc=${label}
1810
1811     local varname=${facet}failover_HOST
1812     if [ -z "${!varname}" ]; then
1813        eval $varname=$(facet_host $facet)
1814     fi
1815
1816     # ${facet}failover_dev is set in cfg file
1817     varname=${facet}failover_dev
1818     if [ -n "${!varname}" ] ; then
1819         eval export ${facet}failover_dev=${!varname}
1820     else
1821         eval export ${facet}failover_dev=$device
1822     fi
1823
1824     # get mount point of already mounted device
1825     # is facet_dev is already mounted then use the real
1826     #  mount point of this facet; otherwise use $(facet_mntpt $facet)
1827     # i.e. ${facet}_MOUNT if specified by user or default 
1828     local mntpt=$(do_facet ${facet} cat /proc/mounts | \
1829             awk '"'${!dev}'" == $1 && $3 == "lustre" { print $2 }')
1830     if [ -z $mntpt ]; then
1831         mntpt=$(facet_mntpt $facet)
1832     fi
1833     eval export ${facet}_MOUNT=$mntpt
1834 }
1835
1836 init_facets_vars () {
1837     remote_mds_nodsh ||
1838         init_facet_vars mds $MDSDEV $MDS_MOUNT_OPTS
1839
1840     combined_mgs_mds || init_facet_vars mgs $MGSDEV $MGS_MOUNT_OPTS
1841
1842     remote_ost_nodsh && return
1843
1844     for num in `seq $OSTCOUNT`; do
1845         DEVNAME=`ostdevname $num`
1846         init_facet_vars ost$num $DEVNAME $OST_MOUNT_OPTS
1847     done
1848 }
1849
1850 init_param_vars () {
1851     if ! remote_ost_nodsh && ! remote_mds_nodsh; then
1852         export MDSVER=$(do_facet mds "lctl get_param version" | cut -d. -f1,2)
1853         export OSTVER=$(do_facet ost1 "lctl get_param version" | cut -d. -f1,2)
1854         export CLIVER=$(lctl get_param version | cut -d. -f 1,2)
1855     fi
1856
1857     remote_mds_nodsh ||
1858         TIMEOUT=$(do_facet mds "lctl get_param -n timeout")
1859
1860     log "Using TIMEOUT=$TIMEOUT"
1861
1862     if [ "$ENABLE_QUOTA" ]; then
1863         setup_quota $MOUNT  || return 2
1864     fi
1865 }
1866
1867 nfs_client_mode () {
1868     if [ "$NFSCLIENT" ]; then
1869         echo "NFSCLIENT mode: setup, cleanup, check config skipped"
1870         local clients=$CLIENTS
1871         [ -z $clients ] && clients=$(hostname)
1872
1873         # FIXME: remove hostname when 19215 fixed
1874         do_nodes $clients "echo \\\$(hostname); grep ' '$MOUNT' ' /proc/mounts"
1875         declare -a nfsexport=(`grep ' '$MOUNT' ' /proc/mounts | awk '{print $1}' | awk -F: '{print $1 " "  $2}'`)
1876         do_nodes ${nfsexport[0]} "echo \\\$(hostname); df -T  ${nfsexport[1]}"
1877         return
1878     fi
1879     return 1
1880 }
1881
1882 check_config_client () {
1883     local mntpt=$1
1884
1885     local mounted=$(mount | grep " $mntpt ")
1886     if [ "$CLIENTONLY" ]; then
1887         # bug 18021
1888         # CLIENTONLY should not depend on *_HOST settings
1889         local mgc=$($LCTL device_list | awk '/MGC/ {print $4}')
1890         # in theory someone could create a new,
1891         # client-only config file that assumed lustre was already
1892         # configured and didn't set the MGSNID. If MGSNID is not set,
1893         # then we should use the mgs nid currently being used 
1894         # as the default value. bug 18021
1895         [[ x$MGSNID = x ]] &&
1896             MGSNID=${mgc//MGC/}
1897
1898         if [[ x$mgc != xMGC$MGSNID ]]; then
1899             if [ "$mgs_HOST" ]; then
1900                 local mgc_ip=$(ping -q -c1 -w1 $mgs_HOST | grep PING | awk '{print $3}' | sed -e "s/(//g" -e "s/)//g")
1901                 [[ x$mgc = xMGC$mgc_ip@$NETTYPE ]] ||
1902                     error_exit "MGSNID=$MGSNID, mounted: $mounted, MGC : $mgc"
1903             fi
1904         fi
1905         return 0
1906     fi
1907
1908     local myMGS_host=$mgs_HOST
1909     if [ "$NETTYPE" = "ptl" ]; then
1910         myMGS_host=$(h2ptl $mgs_HOST | sed -e s/@ptl//)
1911     fi
1912
1913     echo Checking config lustre mounted on $mntpt
1914     local mgshost=$(mount | grep " $mntpt " | awk -F@ '{print $1}')
1915     mgshost=$(echo $mgshost | awk -F: '{print $1}')
1916
1917 #    if [ "$mgshost" != "$myMGS_host" ]; then
1918 #            error_exit "Bad config file: lustre is mounted with mgs $mgshost, but mgs_HOST=$mgs_HOST, NETTYPE=$NETTYPE
1919 #                   Please use correct config or set mds_HOST correctly!"
1920 #    fi
1921
1922 }
1923
1924 check_config_clients () {
1925     local clients=${CLIENTS:-$HOSTNAME}
1926     local mntpt=$1
1927
1928     nfs_client_mode && return
1929
1930     do_rpc_nodes $clients check_config_client $mntpt
1931
1932     sanity_mount_check ||
1933         error "environments are insane!"
1934 }
1935
1936 check_timeout () {
1937     local mdstimeout=$(do_facet mds "lctl get_param -n timeout")
1938     local cltimeout=$(lctl get_param -n timeout)
1939     if [ $mdstimeout -ne $TIMEOUT ] || [ $mdstimeout -ne $cltimeout ]; then
1940         error "timeouts are wrong! mds: $mdstimeout, client: $cltimeout, TIMEOUT=$TIMEOUT"
1941         return 1
1942     fi
1943 }
1944
1945 is_mounted () {
1946     local mntpt=$1
1947     local mounted=$(mounted_lustre_filesystems)
1948
1949     echo $mounted' ' | grep -w -q $mntpt' '
1950 }
1951
1952 is_empty_dir() {
1953     [ $(find $1 -maxdepth 1 -print | wc -l) = 1 ] && return 0
1954     return 1
1955 }
1956
1957 # empty lustre filesystem may have empty directories lost+found and .lustre
1958 is_empty_fs() {
1959     [ $(find $1 -maxdepth 1 -name lost+found -o -name .lustre -prune -o \
1960        -print | wc -l) = 1 ] || return 1
1961     [ ! -d $1/lost+found ] || is_empty_dir $1/lost+found && return 0
1962     [ ! -d $1/.lustre ] || is_empty_dir $1/.lustre && return 0
1963     return 1
1964 }
1965
1966 check_and_setup_lustre() {
1967     nfs_client_mode && return
1968
1969     local MOUNTED=$(mounted_lustre_filesystems)
1970
1971     local do_check=true
1972     # 1.
1973     # both MOUNT and MOUNT2 are not mounted
1974     if ! is_mounted $MOUNT && ! is_mounted $MOUNT2; then
1975         [ "$REFORMAT" ] && formatall
1976         # setupall mounts both MOUNT and MOUNT2 (if MOUNT_2 is set)
1977         setupall
1978         is_mounted $MOUNT || error "NAME=$NAME not mounted"
1979         export I_MOUNTED=yes
1980         do_check=false
1981     # 2.
1982     # MOUNT2 is mounted
1983     elif is_mounted $MOUNT2; then
1984             # 3.
1985             # MOUNT2 is mounted, while MOUNT_2 is not set
1986             if ! [ "$MOUNT_2" ]; then
1987                 cleanup_mount $MOUNT2
1988                 export I_UMOUNTED2=yes
1989
1990             # 4.
1991             # MOUNT2 is mounted, MOUNT_2 is set
1992             else
1993                 # FIXME: what to do if check_config failed?
1994                 # i.e. if:
1995                 # 1) remote client has mounted other Lustre fs ?
1996                 # 2) it has insane env ?
1997                 # let's try umount MOUNT2 on all clients and mount it again:
1998                 if ! check_config_clients $MOUNT2; then
1999                     cleanup_mount $MOUNT2
2000                     restore_mount $MOUNT2
2001                     export I_MOUNTED2=yes
2002                 fi
2003             fi 
2004
2005     # 5.
2006     # MOUNT is mounted MOUNT2 is not mounted
2007     elif [ "$MOUNT_2" ]; then
2008         restore_mount $MOUNT2
2009         export I_MOUNTED2=yes
2010     fi
2011
2012     if $do_check; then
2013         # FIXME: what to do if check_config failed?
2014         # i.e. if:
2015         # 1) remote client has mounted other Lustre fs?
2016         # 2) lustre is mounted on remote_clients atall ?
2017         check_config_clients $MOUNT
2018         init_facets_vars
2019         init_param_vars
2020
2021         do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=\\\"$PTLDEBUG\\\";
2022             lctl set_param subsystem_debug=\\\"${SUBSYSTEM# }\\\";
2023             lctl set_param debug_mb=${DEBUG_SIZE};
2024             sync"
2025     fi
2026     if [ "$ONLY" == "setup" ]; then
2027         exit 0
2028     fi
2029 }
2030
2031 restore_mount () {
2032    local clients=${CLIENTS:-$HOSTNAME}
2033    local mntpt=$1
2034
2035    zconf_mount_clients $clients $mntpt
2036 }
2037
2038 cleanup_mount () {
2039     local clients=${CLIENTS:-$HOSTNAME}
2040     local mntpt=$1
2041
2042     zconf_umount_clients $clients $mntpt    
2043 }
2044
2045 cleanup_and_setup_lustre() {
2046     if [ "$ONLY" == "cleanup" -o "`mount | grep $MOUNT`" ]; then
2047         lctl set_param debug=0 || true
2048         cleanupall
2049         if [ "$ONLY" == "cleanup" ]; then
2050             exit 0
2051         fi
2052     fi
2053     check_and_setup_lustre
2054 }
2055
2056 # Get all of the server target devices from a given server node and type.
2057 get_mnt_devs() {
2058     local node=$1
2059     local type=$2
2060     local obd_type
2061     local devs
2062     local dev
2063
2064     case $type in
2065     mdt) obd_type="osd" ;;
2066     ost) obd_type="obdfilter" ;; # needs to be fixed when OST also uses an OSD
2067     *) echo "invalid server type" && return 1 ;;
2068     esac
2069
2070     devs=$(do_node $node "lctl get_param -n $obd_type.*.mntdev")
2071     for dev in $devs; do
2072         case $dev in
2073         *loop*) do_node $node "losetup $dev" | \
2074                 sed -e "s/.*(//" -e "s/).*//" ;;
2075         *) echo $dev ;;
2076         esac
2077     done
2078 }
2079
2080 # Get all of the server target devices.
2081 get_svr_devs() {
2082     local i
2083
2084     # OST devices
2085     i=0
2086     for node in $(osts_nodes); do
2087         OSTDEVS[i]=$(get_mnt_devs $node ost)
2088         i=$((i + 1))
2089     done
2090 }
2091
2092 # Run e2fsck on MDT or OST device.
2093 run_e2fsck() {
2094     local node=$1
2095     local target_dev=$2
2096     local ostidx=$3
2097     local ostdb_opt=$4
2098
2099     df > /dev/null      # update statfs data on disk
2100     local cmd="$E2FSCK -d -v -f -n $MDSDB_OPT $ostdb_opt $target_dev"
2101     echo $cmd
2102     local rc=0
2103     do_node $node $cmd || rc=$?
2104     [ $rc -le $FSCK_MAX_ERR ] || \
2105         error_exit "$cmd returned $rc, should be <= $FSCK_MAX_ERR"
2106     return 0
2107 }
2108
2109 # Run e2fsck on MDT and OST(s) to generate databases used for lfsck.
2110 generate_db() {
2111     local i
2112     local ostidx
2113     local dev
2114     local tmp_file
2115
2116     tmp_file=$(mktemp -p $SHARED_DIRECTORY || 
2117         error_exit "fail to create file in $SHARED_DIRECTORY")
2118
2119     # make sure everything gets to the backing store
2120     local list=$(comma_list $CLIENTS $(facet_host mds) $(osts_nodes))
2121     do_nodes $list "sync; sleep 2; sync"
2122
2123     do_nodes $list ls $tmp_file || \
2124         error_exit "$SHARED_DIRECTORY is not a shared directory"
2125     rm $tmp_file
2126
2127     run_e2fsck $(facet_host mds) $MDSDEV
2128
2129     i=0
2130     ostidx=0
2131     OSTDB_LIST=""
2132     for node in $(osts_nodes); do
2133         for dev in ${OSTDEVS[i]}; do
2134             local ostdb_opt=`eval echo $OSTDB_OPT`
2135             run_e2fsck $node $dev $ostidx "$ostdb_opt"
2136             OSTDB_LIST="$OSTDB_LIST $OSTDB-$ostidx"
2137             ostidx=$((ostidx + 1))
2138         done
2139         i=$((i + 1))
2140     done
2141 }
2142
2143 run_lfsck() {
2144     local cmd="$LFSCK_BIN -c -l --mdsdb $MDSDB --ostdb $OSTDB_LIST $MOUNT"
2145     echo $cmd
2146     local rc=0
2147     eval $cmd || rc=$?
2148     [ $rc -le $FSCK_MAX_ERR ] || \
2149         error_exit "$cmd returned $rc, should be <= $FSCK_MAX_ERR"
2150     echo "lfsck finished with rc=$rc"
2151
2152     rm -rvf $MDSDB* $OSTDB* || true
2153     return 0
2154 }
2155
2156 check_and_cleanup_lustre() {
2157     if [ "$LFSCK_ALWAYS" = "yes" ]; then
2158         get_svr_devs
2159         generate_db
2160         if [ "$SKIP_LFSCK" == "no" ]; then
2161             run_lfsck
2162         else
2163             echo "skip lfsck"
2164         fi
2165     fi
2166
2167     if is_mounted $MOUNT; then
2168         [ -n "$DIR" ] && rm -rf $DIR/[Rdfs][0-9]*
2169         [ "$ENABLE_QUOTA" ] && restore_quota_type || true
2170     fi
2171
2172     if [ "$I_UMOUNTED2" = "yes" ]; then
2173         restore_mount $MOUNT2 || error "restore $MOUNT2 failed"
2174     fi
2175
2176     if [ "$I_MOUNTED2" = "yes" ]; then
2177         cleanup_mount $MOUNT2
2178     fi
2179
2180     if [ "$I_MOUNTED" = "yes" ]; then
2181         cleanupall -f || error "cleanup failed"
2182         unset I_MOUNTED
2183     fi
2184 }
2185
2186 #######
2187 # General functions
2188
2189 check_network() {
2190     local NETWORK=0
2191     local WAIT=0
2192     local MAX=$2
2193     while [ $NETWORK -eq 0 ]; do
2194         if ping -c 1 -w 3 $1 > /dev/null; then
2195             NETWORK=1
2196         else
2197             WAIT=$((WAIT + 5))
2198             echo "waiting for $1, $((MAX - WAIT)) secs left"
2199             sleep 5
2200         fi
2201         if [ $WAIT -gt $MAX ]; then
2202             echo "Network not available"
2203             exit 1
2204         fi
2205     done
2206 }
2207 check_port() {
2208     while( !($DSH2 $1 "netstat -tna | grep -q $2") ) ; do
2209         sleep 9
2210     done
2211 }
2212
2213 no_dsh() {
2214     shift
2215     eval $@
2216 }
2217
2218 comma_list() {
2219     # the sed converts spaces to commas, but leaves the last space
2220     # alone, so the line doesn't end with a comma.
2221     echo "$*" | tr -s " " "\n" | sort -b -u | tr "\n" " " | sed 's/ \([^$]\)/,\1/g'
2222 }
2223
2224 list_member () {
2225     local list=$1
2226     local item=$2
2227     echo $list | grep -qw $item  
2228 }
2229
2230 # list, excluded are the comma separated lists
2231 exclude_items_from_list () {
2232     local list=$1
2233     local excluded=$2
2234     local item
2235
2236     list=${list//,/ }
2237     for item in ${excluded//,/ }; do
2238         list=$(echo " $list " | sed -re "s/\s+$item\s+/ /g")
2239     done
2240     echo $(comma_list $list)
2241 }
2242
2243 # list, expand  are the comma separated lists
2244 expand_list () {
2245     local list=${1//,/ }
2246     local expand=${2//,/ }
2247     local expanded=
2248
2249     expanded=$(for i in $list $expand; do echo $i; done | sort -u)
2250     echo $(comma_list $expanded)
2251 }
2252
2253 testslist_filter () {
2254     local script=$LUSTRE/tests/${TESTSUITE}.sh
2255
2256     [ -f $script ] || return 0
2257
2258     local start_at=$START_AT
2259     local stop_at=$STOP_AT
2260
2261     local var=${TESTSUITE//-/_}_START_AT
2262     [ x"${!var}" != x ] && start_at=${!var}
2263     var=${TESTSUITE//-/_}_STOP_AT
2264     [ x"${!var}" != x ] && stop_at=${!var}
2265
2266     sed -n 's/^test_\([^ (]*\).*/\1/p' $script | \
2267         awk ' BEGIN { if ("'${start_at:-0}'" != 0) flag = 1 }
2268             /^'${start_at}'$/ {flag = 0}
2269             {if (flag == 1) print $0}
2270             /^'${stop_at}'$/ { flag = 1 }'
2271 }
2272
2273 absolute_path() {
2274     (cd `dirname $1`; echo $PWD/`basename $1`)
2275 }
2276
2277 get_facets () {
2278     local types=${1:-"OST MDS MGS"}
2279
2280     local list=""
2281     for entry in $types; do
2282         local name=$(echo $entry | tr "[:upper:]" "[:lower:]")
2283         local type=$(echo $entry | tr "[:lower:]" "[:upper:]")
2284
2285         case $type in
2286             MDS|MGS ) list="$list $name";;
2287                 OST ) for ((i=1; i<=$OSTCOUNT; i++)) do
2288                           list="$list ${name}$i"
2289                       done;;
2290                   * ) error "Invalid facet type"
2291                  exit 1;;
2292         esac
2293     done
2294     echo $(comma_list $list)
2295 }
2296
2297 ##################################
2298 # Adaptive Timeouts funcs
2299
2300 at_is_enabled() {
2301     # only check mds, we assume at_max is the same on all nodes
2302     local at_max=$(do_facet mds "lctl get_param -n at_max")
2303     if [ $at_max -eq 0 ]; then
2304         return 1
2305     else
2306         return 0
2307     fi
2308 }
2309
2310 at_max_get() {
2311     local facet=$1
2312
2313     # suppose that all ost-s has the same at_max set
2314     if [ $facet == "ost" ]; then
2315         do_facet ost1 "lctl get_param -n at_max"
2316     else
2317         do_facet $facet "lctl get_param -n at_max"
2318     fi
2319 }
2320
2321 at_max_set() {
2322     local at_max=$1
2323     shift
2324
2325     local facet
2326     for facet in $@; do
2327         if [ $facet == "ost" ]; then
2328             for i in `seq $OSTCOUNT`; do
2329                 do_facet ost$i "lctl set_param at_max=$at_max"
2330             done
2331         else
2332             do_facet $facet "lctl set_param at_max=$at_max"
2333         fi
2334     done
2335 }
2336
2337 ##################################
2338 # OBD_FAIL funcs
2339
2340 drop_request() {
2341 # OBD_FAIL_MDS_ALL_REQUEST_NET
2342     RC=0
2343     do_facet mds lctl set_param fail_loc=0x123
2344     do_facet client "$1" || RC=$?
2345     do_facet mds lctl set_param fail_loc=0
2346     return $RC
2347 }
2348
2349 drop_reply() {
2350 # OBD_FAIL_MDS_ALL_REPLY_NET
2351     RC=0
2352     do_facet mds lctl set_param fail_loc=0x122
2353     do_facet client "$@" || RC=$?
2354     do_facet mds lctl set_param fail_loc=0
2355     return $RC
2356 }
2357
2358 drop_reint_reply() {
2359 # OBD_FAIL_MDS_REINT_NET_REP
2360     RC=0
2361     do_facet mds lctl set_param fail_loc=0x119
2362     do_facet client "$@" || RC=$?
2363     do_facet mds lctl set_param fail_loc=0
2364     return $RC
2365 }
2366
2367 pause_bulk() {
2368 #define OBD_FAIL_OST_BRW_PAUSE_BULK      0x214
2369     RC=0
2370     do_facet ost1 lctl set_param fail_loc=0x214
2371     do_facet client "$1" || RC=$?
2372     do_facet client "sync"
2373     do_facet ost1 lctl set_param fail_loc=0
2374     return $RC
2375 }
2376
2377 drop_ldlm_cancel() {
2378 #define OBD_FAIL_LDLM_CANCEL             0x304
2379     RC=0
2380     do_facet client lctl set_param fail_loc=0x304
2381     do_facet client "$@" || RC=$?
2382     do_facet client lctl set_param fail_loc=0
2383     return $RC
2384 }
2385
2386 drop_bl_callback() {
2387 #define OBD_FAIL_LDLM_BL_CALLBACK        0x305
2388     RC=0
2389     do_facet client lctl set_param fail_loc=0x305
2390     do_facet client "$@" || RC=$?
2391     do_facet client lctl set_param fail_loc=0
2392     return $RC
2393 }
2394
2395 drop_ldlm_reply() {
2396 #define OBD_FAIL_LDLM_REPLY              0x30c
2397     RC=0
2398     do_facet mds lctl set_param fail_loc=0x30c
2399     do_facet client "$@" || RC=$?
2400     do_facet mds lctl set_param fail_loc=0
2401     return $RC
2402 }
2403
2404 clear_failloc() {
2405     facet=$1
2406     pause=$2
2407     sleep $pause
2408     echo "clearing fail_loc on $facet"
2409     do_facet $facet "lctl set_param fail_loc=0 2>/dev/null || true"
2410 }
2411
2412 set_nodes_failloc () {
2413     do_nodes $(comma_list $1)  lctl set_param fail_loc=$2
2414 }
2415
2416 cancel_lru_locks() {
2417     $LCTL mark "cancel_lru_locks $1 start"
2418     for d in `lctl get_param -N ldlm.namespaces.*.lru_size | egrep -i $1`; do
2419         $LCTL set_param -n $d=clear
2420     done
2421     $LCTL get_param ldlm.namespaces.*.lock_unused_count | egrep -i $1 | grep -v '=0'
2422     $LCTL mark "cancel_lru_locks $1 stop"
2423 }
2424
2425 default_lru_size()
2426 {
2427         NR_CPU=$(grep -c "processor" /proc/cpuinfo)
2428         DEFAULT_LRU_SIZE=$((100 * NR_CPU))
2429         echo "$DEFAULT_LRU_SIZE"
2430 }
2431
2432 lru_resize_enable()
2433 {
2434     lctl set_param ldlm.namespaces.*$1*.lru_size=0
2435 }
2436
2437 lru_resize_disable()
2438 {
2439     lctl set_param ldlm.namespaces.*$1*.lru_size $(default_lru_size)
2440 }
2441
2442 pgcache_empty() {
2443     local FILE
2444     for FILE in `lctl get_param -N "llite.*.dump_page_cache"`; do
2445         if [ `lctl get_param -n $FILE | wc -l` -gt 1 ]; then
2446             echo there is still data in page cache $FILE ?
2447             lctl get_param -n $FILE
2448             return 1
2449         fi
2450     done
2451     return 0
2452 }
2453
2454 create_fake_exports () {
2455     local facet=$1
2456     local num=$2
2457 #obd_fail_val = num;
2458 #define OBD_FAIL_TGT_FAKE_EXP 0x708
2459     do_facet $facet "lctl set_param fail_val=$num"
2460     do_facet $facet "lctl set_param fail_loc=0x80000708"
2461     fail $facet
2462 }
2463
2464 debugsave() {
2465     DEBUGSAVE="$(lctl get_param -n debug)"
2466 }
2467
2468 debugrestore() {
2469     [ -n "$DEBUGSAVE" ] && lctl set_param debug="${DEBUGSAVE}"
2470     DEBUGSAVE=""
2471 }
2472
2473 ##################################
2474 # Test interface
2475 ##################################
2476
2477 error_noexit() {
2478     local TYPE=${TYPE:-"FAIL"}
2479     local ERRLOG
2480     local tmp=$TMP
2481     [ -d "$SHARED_DIR_LOGS" ] && tmp=$SHARED_DIR_LOGS
2482
2483     local dump=true
2484     # do not dump logs if $1=false
2485     if [ "x$1" = "xfalse" ]; then
2486         shift
2487         dump=false
2488     fi
2489
2490     log " ${TESTSUITE} ${TESTNAME}: @@@@@@ ${TYPE}: $@ "
2491
2492     if $dump; then
2493         ERRLOG=$tmp/lustre_${TESTSUITE}_${TESTNAME}.$(date +%s)
2494         echo "Dumping lctl log to $ERRLOG"
2495         # We need to dump the logs on all nodes
2496         do_nodes $(comma_list $(nodes_list)) $NODE $LCTL dk $ERRLOG
2497     fi
2498     debugrestore
2499     [ "$TESTSUITELOG" ] && echo "$0: ${TYPE}: $TESTNAME $@" >> $TESTSUITELOG
2500     TEST_FAILED=true
2501 }
2502
2503 error() {
2504     error_noexit "$@"
2505     if $FAIL_ON_ERROR;  then
2506         reset_fail_loc
2507         exit 1
2508     fi
2509 }
2510
2511 error_exit() {
2512     error_noexit "$@"
2513     exit 1
2514 }
2515
2516 # use only if we are ignoring failures for this test, bugno required.
2517 # (like ALWAYS_EXCEPT, but run the test and ignore the results.)
2518 # e.g. error_ignore 5494 "your message"
2519 error_ignore() {
2520     local TYPE="IGNORE (bz$1)"
2521     shift
2522     error_noexit "$@"
2523 }
2524
2525 skip_env () {
2526     $FAIL_ON_SKIP_ENV && error false $@ || skip $@
2527 }
2528
2529 skip () {
2530         log " SKIP: ${TESTSUITE} ${TESTNAME} $@"
2531         [ "$TESTSUITELOG" ] && \
2532                 echo "${TESTSUITE}: SKIP: $TESTNAME $@" >> $TESTSUITELOG || true
2533 }
2534
2535 build_test_filter() {
2536     EXCEPT="$EXCEPT $(testslist_filter)"
2537
2538     [ "$ONLY" ] && log "only running test `echo $ONLY`"
2539     for O in $ONLY; do
2540         eval ONLY_${O}=true
2541     done
2542     [ "$EXCEPT$ALWAYS_EXCEPT" ] && \
2543         log "excepting tests: `echo $EXCEPT $ALWAYS_EXCEPT`"
2544     [ "$EXCEPT_SLOW" ] && \
2545         log "skipping tests SLOW=no: `echo $EXCEPT_SLOW`"
2546     for E in $EXCEPT $ALWAYS_EXCEPT; do
2547         eval EXCEPT_${E}=true
2548     done
2549     for E in $EXCEPT_SLOW; do
2550         eval EXCEPT_SLOW_${E}=true
2551     done
2552     for G in $GRANT_CHECK_LIST; do
2553         eval GCHECK_ONLY_${G}=true
2554         done
2555 }
2556
2557 basetest() {
2558     if [[ $1 = [a-z]* ]]; then
2559         echo $1
2560     else
2561         echo ${1%%[a-z]*}
2562     fi
2563 }
2564
2565 # print a newline if the last test was skipped
2566 export LAST_SKIPPED=
2567 run_test() {
2568     assert_DIR
2569
2570     export base=`basetest $1`
2571     if [ ! -z "$ONLY" ]; then
2572         testname=ONLY_$1
2573         if [ ${!testname}x != x ]; then
2574             [ "$LAST_SKIPPED" ] && echo "" && LAST_SKIPPED=
2575             run_one $1 "$2"
2576             return $?
2577         fi
2578         testname=ONLY_$base
2579         if [ ${!testname}x != x ]; then
2580             [ "$LAST_SKIPPED" ] && echo "" && LAST_SKIPPED=
2581             run_one $1 "$2"
2582             return $?
2583         fi
2584         LAST_SKIPPED="y"
2585         echo -n "."
2586         return 0
2587     fi
2588     testname=EXCEPT_$1
2589     if [ ${!testname}x != x ]; then
2590         LAST_SKIPPED="y"
2591         TESTNAME=test_$1 skip "skipping excluded test $1"
2592         return 0
2593     fi
2594     testname=EXCEPT_$base
2595     if [ ${!testname}x != x ]; then
2596         LAST_SKIPPED="y"
2597         TESTNAME=test_$1 skip "skipping excluded test $1 (base $base)"
2598         return 0
2599     fi
2600     testname=EXCEPT_SLOW_$1
2601     if [ ${!testname}x != x ]; then
2602         LAST_SKIPPED="y"
2603         TESTNAME=test_$1 skip "skipping SLOW test $1"
2604         return 0
2605     fi
2606     testname=EXCEPT_SLOW_$base
2607     if [ ${!testname}x != x ]; then
2608         LAST_SKIPPED="y"
2609         TESTNAME=test_$1 skip "skipping SLOW test $1 (base $base)"
2610         return 0
2611     fi
2612
2613     LAST_SKIPPED=
2614     run_one $1 "$2"
2615
2616     return $?
2617 }
2618
2619 EQUALS="======================================================================"
2620 equals_msg() {
2621     msg="$@"
2622
2623     local suffixlen=$((${#EQUALS} - ${#msg}))
2624     [ $suffixlen -lt 5 ] && suffixlen=5
2625     log `echo $(printf '===== %s %.*s\n' "$msg" $suffixlen $EQUALS)`
2626 }
2627
2628 log() {
2629     echo "$*"
2630     module_loaded lnet || load_modules
2631
2632     local MSG="$*"
2633     # Get rid of '
2634     MSG=${MSG//\'/\\\'}
2635     MSG=${MSG//\(/\\\(}
2636     MSG=${MSG//\)/\\\)}
2637     MSG=${MSG//\;/\\\;}
2638     MSG=${MSG//\|/\\\|}
2639     MSG=${MSG//\>/\\\>}
2640     MSG=${MSG//\</\\\<}
2641     MSG=${MSG//\//\\\/}
2642     do_nodes $(comma_list $(nodes_list)) $LCTL mark "$MSG" 2> /dev/null || true
2643 }
2644
2645 trace() {
2646         log "STARTING: $*"
2647         strace -o $TMP/$1.strace -ttt $*
2648         RC=$?
2649         log "FINISHED: $*: rc $RC"
2650         return 1
2651 }
2652
2653 pass() {
2654     $TEST_FAILED && echo -n "FAIL " || echo -n "PASS "
2655     echo $@
2656 }
2657
2658 check_mds() {
2659     FFREE=`lctl get_param -n mds.*.filesfree`
2660     FTOTAL=`lctl get_param -n mds.*.filestotal`
2661     [ $FFREE -ge $FTOTAL ] && error "files free $FFREE > total $FTOTAL" || true
2662 }
2663
2664 reset_fail_loc () {
2665     echo -n "Resetting fail_loc on all nodes..."
2666     do_nodes $(comma_list $(nodes_list)) "lctl set_param -n fail_loc=0 2>/dev/null || true"
2667     echo done.
2668 }
2669
2670 run_one() {
2671     testnum=$1
2672     message=$2
2673     tfile=f${testnum}
2674     export tdir=d0.${TESTSUITE}/d${base}
2675
2676     local SAVE_UMASK=`umask`
2677     umask 0022
2678
2679     local BEFORE=`date +%s`
2680     echo
2681     log "== test $testnum: $message == `date +%H:%M:%S` ($BEFORE)"
2682     #check_mds
2683     export TESTNAME=test_$testnum
2684     TEST_FAILED=false
2685     test_${testnum} || error "test_$testnum failed with $?"
2686     #check_mds
2687     cd $SAVE_PWD
2688     reset_fail_loc
2689     check_grant ${testnum} || error "check_grant $testnum failed with $?"
2690     check_catastrophe || error "LBUG/LASSERT detected"
2691     ps auxww | grep -v grep | grep -q multiop && error "multiop still running"
2692     pass "($((`date +%s` - $BEFORE))s)"
2693     TEST_FAILED=false
2694     unset TESTNAME
2695     unset tdir
2696     umask $SAVE_UMASK
2697 }
2698
2699 canonical_path() {
2700     (cd `dirname $1`; echo $PWD/`basename $1`)
2701 }
2702
2703 check_grant() {
2704     export base=`basetest $1`
2705     [ "$CHECK_GRANT" == "no" ] && return 0
2706
2707         testname=GCHECK_ONLY_${base}
2708     [ ${!testname}x == x ] && return 0
2709
2710     echo -n "checking grant......"
2711
2712     local clients=$CLIENTS
2713     [ -z $clients ] && clients=$(hostname)
2714
2715     # sync all the data and make sure no pending data on server
2716     do_nodes $clients sync
2717
2718     # get client grant
2719     client_grant=`do_nodes $clients \
2720                     "$LCTL get_param -n osc.${FSNAME}-*.cur_*grant_bytes" | \
2721                     awk '{total += $1} END{print total}'`
2722
2723     # get server grant
2724     server_grant=`do_nodes $(comma_list $(osts_nodes)) \
2725                     "$LCTL get_param -n obdfilter.${FSNAME}-OST*.tot_granted" | \
2726                     awk '{total += $1} END{print total}'`
2727
2728     # check whether client grant == server grant
2729     if [ $client_grant -ne $server_grant ]; then
2730         echo "failed: client:${client_grant} server: ${server_grant}."
2731         do_nodes $(comma_list $(osts_nodes)) \
2732                    "$LCTL get_param obdfilter.${FSNAME}-OST*.tot*"
2733         do_nodes $clients "$LCTL get_param osc.${FSNAME}-*.cur_*_bytes"
2734         return 1
2735     else
2736         echo "pass: client:${client_grant} server: ${server_grant}"
2737     fi
2738 }
2739
2740 ########################
2741 # helper functions
2742
2743 osc_to_ost()
2744 {
2745     osc=$1
2746     ost=`echo $1 | awk -F_ '{print $3}'`
2747     if [ -z $ost ]; then
2748         ost=`echo $1 | sed 's/-osc.*//'`
2749     fi
2750     echo $ost
2751 }
2752
2753 ostuuid_from_index()
2754 {
2755     $LFS osts $2 | awk '/^'$1'/ { print $2 }'
2756 }
2757
2758 remote_node () {
2759     local node=$1
2760     [ "$node" != "$(hostname)" ]
2761 }
2762
2763 remote_mds ()
2764 {
2765     remote_node $mds_HOST
2766 }
2767
2768 remote_mds_nodsh()
2769 {
2770     [ "$CLIENTONLY" ] && return 0 || true
2771     remote_mds && [ "$PDSH" = "no_dsh" -o -z "$PDSH" -o -z "$mds_HOST" ]
2772 }
2773
2774 remote_ost ()
2775 {
2776     local node
2777     for node in $(osts_nodes) ; do
2778         remote_node $node && return 0
2779     done
2780     return 1
2781 }
2782
2783 remote_ost_nodsh()
2784 {
2785     [ "$CLIENTONLY" ] && return 0 || true 
2786     remote_ost && [ "$PDSH" = "no_dsh" -o -z "$PDSH" -o -z "$ost_HOST" ]
2787 }
2788
2789 remote_mgs_nodsh()
2790 {
2791     local MGS
2792     MGS=$(facet_host mgs)
2793     remote_node $MGS && [ "$PDSH" = "no_dsh" -o -z "$PDSH" -o -z "$ost_HOST" ]
2794 }
2795
2796 remote_servers () {
2797     remote_ost && remote_mds
2798 }
2799
2800 local_mode ()
2801 {
2802     remote_mds_nodsh || remote_ost_nodsh || \
2803         $(single_local_node $(comma_list $(nodes_list)))
2804 }
2805
2806 facets_nodes () {
2807     local facets=$1
2808     local nodes
2809     local NODES_sort
2810
2811     for facet in ${facets//,/ }; do
2812         if [ "$FAILURE_MODE" = HARD ]; then
2813             nodes="$nodes $(facet_active_host $facet)"
2814         else
2815             nodes="$nodes $(facet_host $facet)"
2816         fi
2817     done
2818     NODES_sort=$(for i in $nodes; do echo $i; done | sort -u)
2819
2820     echo $NODES_sort
2821 }
2822
2823 osts_nodes () {
2824     local facets=$(get_facets OST)
2825     local nodes=$(facets_nodes $facets)
2826
2827     echo $nodes
2828 }
2829
2830 nodes_list () {
2831     # FIXME. We need a list of clients
2832     local myNODES=$HOSTNAME
2833     local myNODES_sort
2834
2835     # CLIENTS (if specified) contains the local client
2836     [ -n "$CLIENTS" ] && myNODES=${CLIENTS//,/ }
2837
2838     if [ "$PDSH" -a "$PDSH" != "no_dsh" ]; then
2839         myNODES="$myNODES $(facets_nodes $(get_facets))"
2840     fi
2841
2842     myNODES_sort=$(for i in $myNODES; do echo $i; done | sort -u)
2843
2844     echo $myNODES_sort
2845 }
2846
2847 remote_nodes_list () {
2848     local rnodes=$(nodes_list)
2849     rnodes=$(echo " $rnodes " | sed -re "s/\s+$HOSTNAME\s+/ /g")
2850     echo $rnodes
2851 }
2852
2853 init_clients_lists () {
2854     # Sanity check: exclude the local client from RCLIENTS
2855     local rclients=$(echo " $RCLIENTS " | sed -re "s/\s+$HOSTNAME\s+/ /g")
2856
2857     # Sanity check: exclude the dup entries
2858     rclients=$(for i in $rclients; do echo $i; done | sort -u)
2859
2860     local clients="$SINGLECLIENT $HOSTNAME $rclients"
2861
2862     # Sanity check: exclude the dup entries from CLIENTS
2863     # for those configs which has SINGLCLIENT set to local client
2864     clients=$(for i in $clients; do echo $i; done | sort -u)
2865
2866     CLIENTS=`comma_list $clients`
2867     local -a remoteclients=($rclients)
2868     for ((i=0; $i<${#remoteclients[@]}; i++)); do
2869             varname=CLIENT$((i + 2))
2870             eval $varname=${remoteclients[i]}
2871     done
2872
2873     CLIENTCOUNT=$((${#remoteclients[@]} + 1))
2874 }
2875
2876 get_random_entry () {
2877     local rnodes=$1
2878
2879     rnodes=${rnodes//,/ }
2880
2881     local -a nodes=($rnodes)
2882     local num=${#nodes[@]}
2883     local i=$((RANDOM * num * 2 / 65536))
2884
2885     echo ${nodes[i]}
2886 }
2887
2888 client_only () {
2889     [ "$CLIENTONLY" ] || [ "$CLIENTMODSONLY" = yes ]
2890 }
2891
2892 is_patchless ()
2893 {
2894     lctl get_param version | grep -q patchless
2895 }
2896
2897 check_versions () {
2898     [ "$MDSVER" = "$CLIVER" -a "$OSTVER" = "$CLIVER" ]
2899 }
2900
2901 get_node_count() {
2902     local nodes="$@"
2903     echo $nodes | wc -w || true
2904 }
2905
2906 mixed_ost_devs () {
2907     local nodes=$(osts_nodes)
2908     local osscount=$(get_node_count "$nodes")
2909     [ ! "$OSTCOUNT" = "$osscount" ]
2910 }
2911
2912 generate_machine_file() {
2913     local nodes=${1//,/ }
2914     local machinefile=$2
2915     rm -f $machinefile
2916     for node in $nodes; do
2917         echo $node >>$machinefile || \
2918             { echo "can not generate machinefile $machinefile" && return 1; }
2919     done
2920 }
2921
2922 get_stripe () {
2923     local file=$1/stripe
2924     touch $file
2925     $LFS getstripe -v $file || error
2926     rm -f $file
2927 }
2928
2929 setstripe_nfsserver () {
2930     local dir=$1
2931
2932     local nfsserver=$(awk '"'$dir'" ~ $2 && $3 ~ "nfs" && $2 != "/" \
2933                 { print $1 }' /proc/mounts | cut -f 1 -d : | head -1)
2934
2935     [ -z $nfsserver ] && echo "$dir is not nfs mounted" && return 1
2936
2937     do_nodev $nfsserver lfs setstripe "$@"
2938 }
2939
2940 check_runas_id_ret() {
2941     local myRC=0
2942     local myRUNAS_UID=$1
2943     local myRUNAS_GID=$2
2944     shift 2
2945     local myRUNAS=$@
2946     if [ -z "$myRUNAS" ]; then
2947         error_exit "myRUNAS command must be specified for check_runas_id"
2948     fi
2949     mkdir $DIR/d0_runas_test
2950     chmod 0755 $DIR
2951     chown $myRUNAS_UID:$myRUNAS_GID $DIR/d0_runas_test
2952     if ! $myRUNAS touch $DIR/d0_runas_test/f$$ ; then
2953         do_nodesv $(comma_list $(nodes_list)) grep -w $myRUNAS_UID /etc/passwd
2954         myRC=1
2955     fi
2956     rm -rf $DIR/d0_runas_test
2957     return $myRC
2958 }
2959
2960 check_runas_id() {
2961     local myRUNAS_UID=$1
2962     local myRUNAS_GID=$2
2963     shift 2
2964     local myRUNAS=$@
2965     check_runas_id_ret $myRUNAS_UID $myRUNAS_GID $myRUNAS || \
2966         error "unable to write to $DIR/d0_runas_test as UID $myRUNAS_UID.
2967         Please set RUNAS_ID to some UID which exists on MDS and client or
2968         add user $myRUNAS_UID:$myRUNAS_GID on these nodes."
2969 }
2970
2971 # Run multiop in the background, but wait for it to print
2972 # "PAUSING" to its stdout before returning from this function.
2973 multiop_bg_pause() {
2974     MULTIOP_PROG=${MULTIOP_PROG:-multiop}
2975     FILE=$1
2976     ARGS=$2
2977
2978     TMPPIPE=/tmp/multiop_open_wait_pipe.$$
2979     mkfifo $TMPPIPE
2980
2981     echo "$MULTIOP_PROG $FILE v$ARGS"
2982     $MULTIOP_PROG $FILE v$ARGS > $TMPPIPE &
2983
2984     echo "TMPPIPE=${TMPPIPE}"
2985     local multiop_output
2986
2987     read -t 60 multiop_output < $TMPPIPE
2988     if [ $? -ne 0 ]; then
2989         rm -f $TMPPIPE
2990         return 1
2991     fi
2992     rm -f $TMPPIPE
2993     if [ "$multiop_output" != "PAUSING" ]; then
2994         echo "Incorrect multiop output: $multiop_output"
2995         kill -9 $PID
2996         return 1
2997     fi
2998
2999     return 0
3000 }
3001
3002 do_and_time () {
3003     local cmd=$1
3004     local rc
3005
3006     SECONDS=0
3007     eval '$cmd'
3008     
3009     [ ${PIPESTATUS[0]} -eq 0 ] || rc=1
3010
3011     echo $SECONDS
3012     return $rc
3013 }
3014
3015 inodes_available () {
3016     local IFree=$($LFS df -i $MOUNT | grep ^$FSNAME | awk '{print $4}' | sort -un | head -1) || return 1
3017     echo $IFree
3018 }
3019
3020 mdsrate_inodes_available () {
3021     echo $(($(inodes_available) - 1))
3022 }
3023
3024 # reset llite stat counters
3025 clear_llite_stats(){
3026         lctl set_param -n llite.*.stats 0
3027 }
3028
3029 # sum llite stat items
3030 calc_llite_stats() {
3031         local res=$(lctl get_param -n llite.*.stats |
3032                     awk 'BEGIN {s = 0} END {print s} /^'"$1"'/ {s += $2}')
3033         echo $res
3034 }
3035
3036 calc_sum () {
3037         awk 'BEGIN {s = 0}; {s += $1}; END {print s}'
3038 }
3039
3040 calc_osc_kbytes () {
3041         df $MOUNT > /dev/null
3042         $LCTL get_param -n osc.*[oO][sS][cC][-_]*.$1 | calc_sum
3043 }
3044
3045 # save_lustre_params(node, parameter_mask)
3046 # generate a stream of formatted strings (<node> <param name>=<param value>)
3047 save_lustre_params() {
3048         local s
3049         do_nodesv $1 "lctl get_param $2 | while read s; do echo \\\$s; done"
3050 }
3051
3052 # restore lustre parameters from input stream, produces by save_lustre_params
3053 restore_lustre_params() {
3054         local node
3055         local name
3056         local val
3057         while IFS=" =" read node name val; do
3058                 do_node ${node//:/} "lctl set_param -n $name $val"
3059         done
3060 }
3061
3062 check_catastrophe() {
3063     local rnodes=${1:-$(comma_list $(remote_nodes_list))}
3064     local C=$CATASTROPHE
3065     [ -f $C ] && [ $(cat $C) -ne 0 ] && return 1
3066
3067     if [ $rnodes ]; then
3068         do_nodes $rnodes "rc=\\\$([ -f $C ] && echo \\\$(< $C) || echo 0);
3069 if [ \\\$rc -ne 0 ]; then echo \\\$(hostname): \\\$rc; fi
3070 exit \\\$rc;"
3071     fi
3072 }
3073
3074 # $1 node
3075 # $2 file
3076 # $3 $RUNAS
3077 get_stripe_info() {
3078         local tmp_file
3079
3080         stripe_size=0
3081         stripe_count=0
3082         stripe_index=0
3083         tmp_file=$(mktemp)
3084
3085         do_facet $1 $3 lfs getstripe -v $2 > $tmp_file
3086
3087         stripe_size=`awk '$1 ~ /size/ {print $2}' $tmp_file`
3088         stripe_count=`awk '$1 ~ /count/ {print $2}' $tmp_file`
3089         stripe_index=`awk '$1 ~ /stripe_offset/ {print $2}' $tmp_file`
3090         rm -f $tmp_file
3091 }
3092
3093 mdsrate_cleanup () {
3094     mpi_run -np $1 -machinefile $2 ${MDSRATE} --unlink --nfiles $3 --dir $4 --filefmt $5 $6
3095 }
3096
3097 delayed_recovery_enabled () {
3098     do_facet mds "lctl get_param -n mds.${mds_svc}.stale_export_age" > /dev/null 2>&1
3099 }
3100
3101 ################################################################################
3102 # The following functions are used to enable interop testing between
3103 # 1.8 and 2.0. The lprocfs layout changed from 1.8 to 2.0 as the followings:
3104 # mds -> mdt
3105 # {blocksize filesfree filestotal fstype kbytesavail kbytesfree kbytestotal mntdev} moved from mds to osd
3106 # mdt lov: fsname-mdtlov -> fsname-MDTXXXX-mdtlov
3107 # mdt osc: fsname-OSTXXXX-osc -> fsname-OSTXXXX-osc-MDTXXXX
3108 ################################################################################
3109
3110 get_lustre_version () {
3111     local node=${1:-"mds"}
3112     do_facet $node $LCTL get_param -n version |  awk '/^lustre:/ {print $2}'
3113 }
3114
3115 get_mds_version_major () {
3116     local version=$(get_lustre_version mds)
3117     echo $version | awk -F. '{print $1}'
3118 }
3119
3120 get_mds_version_minor () {
3121     local version=$(get_lustre_version mds)
3122     echo $version | awk -F. '{print $2}'
3123 }
3124
3125 get_mds_version_patch () {
3126     local version=$(get_lustre_version mds)
3127     echo $version | awk -F. '{print $3}'
3128 }
3129
3130 get_mds_version_fix () {
3131     local version=$(get_lustre_version mds)
3132     echo $version | awk -F. '{print $4}'
3133 }
3134
3135 get_kernel_version () {
3136     local facet=${1:-"mds"}
3137     do_facet $facet uname -r | awk -F "-" '{print $1}'
3138 }
3139
3140 get_mds_kernel_major () {
3141     local version=$(get_kernel_version mds)
3142     echo $version | awk -F. '{print $1"."$2}'
3143 }
3144
3145 get_mds_kernel_minor () {
3146     local version=$(get_kernel_version mds)
3147     echo $version | awk -F. '{print $3}'
3148 }
3149
3150 get_mds_fsstat_proc_path() {
3151     local major=$(get_mds_version_major)
3152     local minor=$(get_mds_version_minor)
3153     if [ $major -le 1 -a $minor -le 8 ] ; then
3154         echo "mds"
3155     else
3156         echo "osd*"
3157     fi
3158 }
3159
3160 get_mds_mntdev_proc_path() {
3161     local fsstat_dev=$(get_mds_fsstat_proc_path)
3162     echo "$fsstat_dev.*.mntdev"
3163 }
3164
3165 get_mdtlov_proc_path() {
3166     local fsname=$1
3167     local major=$(get_mds_version_major)
3168     local minor=$(get_mds_version_minor)
3169     if [ $major -le 1 -a $minor -le 8 ] ; then
3170         echo "${fsname}-mdtlov"
3171     else
3172         echo "${fsname}-MDT0000-mdtlov"
3173     fi
3174 }
3175
3176 get_mdtosc_proc_path() {
3177     local ost=$1
3178     local major=$(get_mds_version_major)
3179     local minor=$(get_mds_version_minor)
3180     if [ $major -le 1 -a $minor -le 8 ] ; then
3181         echo "${ost}-osc"
3182     else
3183         echo "${ost}-osc-MDT0000"
3184     fi
3185 }
3186
3187 get_mds_mdt_device_proc_path() {
3188     local major=$(get_mds_version_major)
3189     local minor=$(get_mds_version_minor)
3190     if [ $major -le 1 -a $minor -le 8 ] ; then
3191         echo "mds"
3192     else
3193         echo "mdt"
3194     fi
3195 }
3196
3197 get_md_name () {
3198     local major=$(get_mds_version_major)
3199     local minor=$(get_mds_version_minor)
3200     if [ $major -le 1 -a $minor -le 8 ] ; then
3201         echo "mdt"
3202     else
3203         echo "mdd"
3204     fi
3205 }
3206
3207 ########################
3208
3209 convert_facet2label() { 
3210     local facet=$1
3211
3212     if [ x$facet = xost ]; then
3213        facet=ost1
3214     fi
3215
3216     local varsvc=${facet}_svc
3217
3218     if [ -n ${!varsvc} ]; then
3219         echo ${!varsvc}
3220     else  
3221         error "No lablel for $facet!"
3222     fi
3223 }
3224
3225 get_clientosc_proc_path() {
3226     local ost=$1
3227
3228     echo "${1}-osc-*"
3229 }
3230
3231 get_osc_import_name() {
3232     local facet=$1
3233     local ost=$2
3234     local label=$(convert_facet2label $ost)
3235
3236     if [ "$facet" == "mds" ]; then
3237         get_mdtosc_proc_path $label
3238         return 0
3239     fi
3240
3241     get_clientosc_proc_path $label
3242     return 0
3243 }
3244
3245 _wait_import_state () {
3246     local expected=$1
3247     local CONN_PROC=$2
3248     local maxtime=${3:-max_recovery_time}
3249     local CONN_STATE
3250     local i=0
3251
3252     CONN_STATE=$($LCTL get_param -n $CONN_PROC 2>/dev/null | cut -f2)
3253     while [ "${CONN_STATE}" != "${expected}" ]; do
3254         [ $i -ge $maxtime ] && \
3255             error "can't put import for $CONN_PROC into ${expected} state after $i sec, have ${CONN_STATE}" && \
3256             return 1
3257         sleep 1
3258         CONN_STATE=$($LCTL get_param -n $CONN_PROC 2>/dev/null | cut -f2)
3259         i=$(($i + 1))
3260     done
3261
3262     log "$CONN_PROC in ${CONN_STATE} state after $i sec"
3263     return 0
3264 }
3265
3266 wait_import_state() {
3267     local state=$1
3268     local params=$2
3269     local maxtime=${3:-max_recovery_time}
3270     local param
3271
3272     for param in ${params//,/ }; do
3273         _wait_import_state $state $param $maxtime || return
3274     done
3275 }
3276 wait_osc_import_state() {
3277     local facet=$1
3278     local ost_facet=$2
3279     local expected=$3
3280     local ost=$(get_osc_import_name $facet $ost_facet)
3281     local CONN_PROC
3282     local CONN_STATE
3283     local i=0
3284
3285     CONN_PROC="osc.${ost}.ost_server_uuid"
3286     CONN_STATE=$(do_facet $facet lctl get_param -n $CONN_PROC 2>/dev/null | cut -f2)
3287     while [ "${CONN_STATE}" != "${expected}" ]; do
3288         if [ "${expected}" == "DISCONN" ]; then 
3289             # for disconn we can check after proc entry is removed
3290             [ "x${CONN_STATE}" == "x" ] && return 0
3291             #  with AT enabled, we can have connect request timeout near of 
3292             # reconnect timeout and test can't see real disconnect
3293             [ "${CONN_STATE}" == "CONNECTING" ] && return 0
3294         fi
3295         # disconnect rpc should be wait not more obd_timeout
3296         [ $i -ge $(($TIMEOUT * 3 / 2)) ] && \
3297             error "can't put import for ${ost}(${ost_facet}) into ${expected} state" && return 1
3298         sleep 1
3299         CONN_STATE=$(do_facet $facet lctl get_param -n $CONN_PROC 2>/dev/null | cut -f2)
3300         i=$(($i + 1))
3301     done
3302
3303     log "${ost_facet} now in ${CONN_STATE} state"
3304     return 0
3305 }
3306
3307 get_clientmdc_proc_path() {
3308     echo "${1}-mdc-*"
3309 }
3310
3311 do_rpc_nodes () {
3312     local list=$1
3313     shift
3314
3315     local RPATH="PATH=$LUSTRE/tests/:$PATH"
3316     do_nodesv $list "${RPATH} NAME=${NAME} sh rpc.sh $@ "
3317 }
3318
3319 wait_clients_import_state () {
3320     local list=$1
3321     local facet=$2
3322     local expected=$3
3323
3324     local facets=$facet
3325
3326     if [ "$FAILURE_MODE" = HARD ]; then
3327         facets=$(facets_on_host $(facet_active_host $facet))
3328     fi
3329
3330     for facet in ${facets//,/ }; do
3331     local label=$(convert_facet2label $facet)
3332     local proc_path
3333     case $facet in
3334         ost* ) proc_path="osc.$(get_clientosc_proc_path $label).ost_server_uuid" ;;
3335         mds* ) proc_path="mdc.$(get_clientmdc_proc_path $label).mds_server_uuid" ;;
3336         *) error "unknown facet!" ;;
3337     esac
3338     local params=$(expand_list $params $proc_path)
3339     done
3340
3341     if ! do_rpc_nodes $list wait_import_state $expected $params; then
3342         error "import is not in ${expected} state"
3343         return 1
3344     fi
3345 }
3346
3347 destroy_pool_int() {
3348     local ost
3349     local OSTS=$(do_facet mds lctl pool_list $1 | awk '$1 !~ /^Pool:/ {print $1}')
3350     for ost in $OSTS; do
3351         do_facet mgs lctl pool_remove $1 $ost
3352     done
3353     do_facet mgs lctl pool_destroy $1
3354 }
3355
3356 # <fsname>.<poolname> or <poolname>
3357 destroy_pool() {
3358     local fsname=${1%%.*}
3359     local poolname=${1##$fsname.}
3360
3361     [[ x$fsname = x$poolname ]] && fsname=$FSNAME
3362
3363     local RC
3364
3365     pool_list $fsname.$poolname || return $?
3366
3367     destroy_pool_int $fsname.$poolname
3368     RC=$?
3369     [[ $RC -ne 0 ]] && return $RC
3370
3371     wait_update $HOSTNAME "lctl get_param -n lov.$fsname-*.pools.$poolname \
3372       2>/dev/null || echo foo" "foo" || RC=1
3373
3374     if [[ $RC -eq 0 ]]; then
3375         remove_pool_from_list $fsname.$poolname
3376     else
3377         error "destroy pool failed $1"
3378     fi
3379     return $RC
3380 }
3381
3382 destroy_pools () {
3383     local fsname=${1:-$FSNAME}
3384     local poolname
3385     local listvar=${fsname}_CREATED_POOLS
3386
3387     pool_list $fsname
3388
3389     [ x${!listvar} = x ] && return 0
3390
3391     echo destroy the created pools: ${!listvar}
3392     for poolname in ${!listvar//,/ }; do
3393         destroy_pool $fsname.$poolname
3394     done
3395 }
3396
3397 cleanup_pools () {
3398     local fsname=${1:-$FSNAME}
3399     trap 0
3400     destroy_pools $fsname
3401 }
3402
3403 gather_logs () {
3404     local list=$1
3405
3406     local ts=$(date +%s)
3407
3408     # bug 20237, comment 11
3409     # It would also be useful to provide the option
3410     # of writing the file to an NFS directory so it doesn't need to be copied.
3411     local tmp=$TMP
3412     local docp=true
3413     [ -d "$SHARED_DIR_LOGS" ] && tmp=$SHARED_DIR_LOGS && docp=false
3414
3415     # dump lustre logs, dmesg
3416     do_nodes $list "log=$tmp/\\\$(hostname)-debug-$ts.log ;
3417 lctl dk \\\$log >/dev/null;
3418 log=$tmp/\\\$(hostname)-dmesg-$ts.log;
3419 dmesg > \\\$log; "
3420
3421     # FIXME: does it make sense to collect the logs for $ts only, but all
3422     # TESTSUITE logs?
3423     # rsync $TMP/*${TESTSUITE}* to gather the logs dumped by error fn
3424     local logs=$TMP/'*'${TESTSUITE}'*'
3425     if $docp; then
3426         logs=$logs' '$tmp/'*'$ts'*'
3427     fi
3428     for node in ${list//,/ }; do
3429         rsync -az $node:"$logs" $TMP
3430     done
3431
3432     local archive=$TMP/${TESTSUITE}-$ts.tar.bz2
3433     tar -jcf $archive $tmp/*$ts* $TMP/*${TESTSUITE}*
3434
3435     echo $archive
3436 }
3437
3438 cleanup_logs () {
3439     local list=${1:-$(comma_list $(nodes_list))}
3440
3441     [ -n ${TESTSUITE} ] && do_nodes $list "rm -f $TMP/*${TESTSUITE}*" || true
3442 }
3443
3444 do_ls () {
3445     local mntpt_root=$1
3446     local num_mntpts=$2
3447     local dir=$3
3448     local i
3449     local cmd
3450     local pids
3451     local rc=0
3452
3453     for i in $(seq 0 $num_mntpts); do
3454         cmd="ls -laf ${mntpt_root}$i/$dir"
3455         echo + $cmd;
3456         $cmd > /dev/null &
3457         pids="$pids $!"
3458     done
3459     echo pids=$pids
3460     for pid in $pids; do
3461         wait $pid || rc=$?
3462     done
3463
3464     return $rc
3465 }
3466
3467 # target_start_and_reset_recovery_timer()
3468 #        service_time = at_est2timeout(service_time);
3469 #        service_time += 2 * (CONNECTION_SWITCH_MAX + CONNECTION_SWITCH_INC +
3470 #                             INITIAL_CONNECT_TIMEOUT);
3471 # CONNECTION_SWITCH_MAX : min(25U, max(CONNECTION_SWITCH_MIN,obd_timeout))
3472 #define CONNECTION_SWITCH_INC 1
3473 #define INITIAL_CONNECT_TIMEOUT max(CONNECTION_SWITCH_MIN,obd_timeout/20)
3474 #define CONNECTION_SWITCH_MIN 5U
3475
3476 max_recovery_time () {
3477     local init_connect_timeout=$(( TIMEOUT / 20 ))
3478     [[ $init_connect_timeout > 5 ]] || init_connect_timeout=5 
3479
3480     local service_time=$(( $(at_max_get client) + $(( 2 * $(( 25 + 1  + init_connect_timeout)) )) ))
3481
3482     echo $service_time 
3483 }
3484
3485 remove_mdt_files() {
3486     local facet=$1
3487     local mdtdev=$2
3488     shift 2
3489     local files="$@"
3490     local mntpt=${MOUNT%/*}/$facet
3491
3492     echo "removing files from $mdtdev on $facet: $files"
3493     mount -t $FSTYPE $MDS_MOUNT_OPTS $mdtdev $mntpt || return $?
3494     rc=0;
3495     for f in $files; do
3496         rm $mntpt/ROOT/$f || { rc=$?; break; }
3497     done
3498     umount -f $mntpt || return $?
3499     return $rc
3500 }
3501
3502 duplicate_mdt_files() {
3503     local facet=$1
3504     local mdtdev=$2
3505     shift 2
3506     local files="$@"
3507     local mntpt=${MOUNT%/*}/$facet
3508
3509     echo "duplicating files on $mdtdev on $facet: $files"
3510     mkdir -p $mntpt || return $?
3511     mount -t $FSTYPE $MDS_MOUNT_OPTS $mdtdev $mntpt || return $?
3512
3513     do_umount() {
3514         trap 0
3515         popd > /dev/null
3516         rm $tmp
3517         umount -f $mntpt
3518     }
3519     trap do_umount EXIT
3520
3521     tmp=$(mktemp $TMP/setfattr.XXXXXXXXXX)
3522     pushd $mntpt/ROOT > /dev/null || return $?
3523     rc=0
3524     for f in $files; do
3525         touch $f.bad || return $?
3526         getfattr -n trusted.lov $f | sed "s#$f#&.bad#" > $tmp
3527         rc=${PIPESTATUS[0]}
3528         [ $rc -eq 0 ] || return $rc
3529         setfattr --restore $tmp || return $?
3530     done
3531     do_umount
3532 }
3533
3534 run_sgpdd () {
3535     local devs=${1//,/ }
3536     shift
3537     local params=$@
3538     local rslt=$TMP/sgpdd_survey
3539
3540     # sgpdd-survey cleanups ${rslt}.* files
3541
3542     local cmd="rslt=$rslt $params scsidevs=\"$devs\" $SGPDDSURVEY"
3543     echo + $cmd
3544     eval $cmd
3545     cat ${rslt}.detail
3546 }
3547