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