Whamcloud - gitweb
14e5e6c2bbc2838631d9d11b54ac7243a234e9ed
[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 # eg, assert_env LUSTRE MDSNODES OSTNODES CLIENTS
17 assert_env() {
18     local failed=""
19     for name in $@; do
20         if [ -z "${!name}" ]; then
21             echo "$0: $name must be set"
22             failed=1
23         fi
24     done
25     [ $failed ] && exit 1 || true
26 }
27
28 assert_DIR () {
29     local failed=""
30     [[ $DIR/ = $MOUNT/* ]] || \
31         { failed=1 && echo "DIR=$DIR not in $MOUNT. Aborting."; }
32     [[ $DIR1/ = $MOUNT1/* ]] || \
33         { failed=1 && echo "DIR1=$DIR1 not in $MOUNT1. Aborting."; }
34     [[ $DIR2/ = $MOUNT2/* ]] || \
35         { failed=1 && echo "DIR2=$DIR2 not in $MOUNT2. Aborting"; }
36
37     [ -n "$failed" ] && exit 99 || true
38 }
39
40 usage() {
41     echo "usage: $0 [-r] [-f cfgfile]"
42     echo "       -r: reformat"
43
44     exit
45 }
46
47 print_summary () {
48     [ "$TESTSUITE" == "lfscktest" ] && return 0
49     [ -n "$ONLY" ] && echo "WARNING: ONLY is set to ${ONLY}."
50     local form="%-13s %-17s %s\n"
51     printf "$form" "status" "script" "skipped tests E(xcluded) S(low)"
52     echo "------------------------------------------------------------------------------------"
53     for O in $TESTSUITE_LIST; do
54         local skipped=""
55         local slow=""
56         local o=$(echo $O | tr "[:upper:]" "[:lower:]")
57         o=${o//_/-}
58         o=${o//tyn/tyN}
59         local log=${TMP}/${o}.log
60         [ -f $log ] && skipped=$(grep excluded $log | awk '{ printf " %s", $3 }' | sed 's/test_//g')
61         [ -f $log ] && slow=$(grep SLOW $log | awk '{ printf " %s", $3 }' | sed 's/test_//g')
62         [ "${!O}" = "done" ] && \
63             printf "$form" "Done" "$O" "E=$skipped" && \
64             [ -n "$slow" ] && printf "$form" "-" "-" "S=$slow"
65
66     done
67
68     for O in $TESTSUITE_LIST; do
69         [ "${!O}" = "no" ] && \
70             printf "$form" "Skipped" "$O" ""
71     done
72
73     for O in $TESTSUITE_LIST; do
74         [ "${!O}" = "done" -o "${!O}" = "no" ] || \
75             printf "$form" "UNFINISHED" "$O" ""
76     done
77 }
78
79 init_test_env() {
80     export LUSTRE=`absolute_path $LUSTRE`
81     export TESTSUITE=`basename $0 .sh`
82     export TEST_FAILED=false
83
84     export MKE2FS=${MKE2FS:-mke2fs}
85     export DEBUGFS=${DEBUGFS:-debugfs}
86     export TUNE2FS=${TUNE2FS:-tune2fs}
87     export E2LABEL=${E2LABEL:-e2label}
88     export DUMPE2FS=${DUMPE2FS:-dumpe2fs}
89     export E2FSCK=${E2FSCK:-e2fsck}
90
91     #[ -d /r ] && export ROOT=${ROOT:-/r}
92     export TMP=${TMP:-$ROOT/tmp}
93     export TESTSUITELOG=${TMP}/${TESTSUITE}.log
94     export HOSTNAME=${HOSTNAME:-`hostname`}
95     if ! echo $PATH | grep -q $LUSTRE/utils; then
96         export PATH=$PATH:$LUSTRE/utils
97     fi
98     if ! echo $PATH | grep -q $LUSTRE/test; then
99         export PATH=$PATH:$LUSTRE/tests
100     fi
101     export MDSRATE=${MDSRATE:-"$LUSTRE/tests/mdsrate"}
102     [ ! -f "$MDSRATE" ] && export MDSRATE=$(which mdsrate 2> /dev/null)
103     if ! echo $PATH | grep -q $LUSTRE/test/racer; then
104         export PATH=$PATH:$LUSTRE/tests/racer
105     fi
106     export LCTL=${LCTL:-"$LUSTRE/utils/lctl"}
107     export LFS=${LFS:-"$LUSTRE/utils/lfs"}
108     [ ! -f "$LCTL" ] && export LCTL=$(which lctl)
109     export LFS=${LFS:-"$LUSTRE/utils/lfs"}
110     [ ! -f "$LFS" ] && export LFS=$(which lfs)
111     export MKFS=${MKFS:-"$LUSTRE/utils/mkfs.lustre"}
112     [ ! -f "$MKFS" ] && export MKFS=$(which mkfs.lustre)
113     export TUNEFS=${TUNEFS:-"$LUSTRE/utils/tunefs.lustre"}
114     [ ! -f "$TUNEFS" ] && export TUNEFS=$(which tunefs.lustre)
115     export CHECKSTAT="${CHECKSTAT:-"checkstat -v"} "
116     export FSYTPE=${FSTYPE:-"ldiskfs"}
117     export NAME=${NAME:-local}
118     export DIR2
119     export AT_MAX_PATH
120     export SAVE_PWD=${SAVE_PWD:-$LUSTRE/tests}
121
122     if [ "$ACCEPTOR_PORT" ]; then
123         export PORT_OPT="--port $ACCEPTOR_PORT"
124     fi
125
126     # Paths on remote nodes, if different
127     export RLUSTRE=${RLUSTRE:-$LUSTRE}
128     export RPWD=${RPWD:-$PWD}
129     export I_MOUNTED=${I_MOUNTED:-"no"}
130
131     # command line
132
133     while getopts "rvwf:" opt $*; do
134         case $opt in
135             f) CONFIG=$OPTARG;;
136             r) REFORMAT=--reformat;;
137             v) VERBOSE=true;;
138             w) WRITECONF=writeconf;;
139             \?) usage;;
140         esac
141     done
142
143     shift $((OPTIND - 1))
144     ONLY=${ONLY:-$*}
145
146     [ "$TESTSUITELOG" ] && rm -f $TESTSUITELOG || true
147     rm -f $TMP/*active
148
149 }
150
151 case `uname -r` in
152     *) EXT=".ko"; USE_QUOTA=yes;;
153 esac
154
155 load_module() {
156     module=$1
157     shift
158     BASE=`basename $module $EXT`
159     lsmod | grep -q ${BASE} || \
160       if [ -f ${LUSTRE}/${module}${EXT} ]; then
161         insmod ${LUSTRE}/${module}${EXT} $@
162     else
163         # must be testing a "make install" or "rpm" installation
164         modprobe $BASE $@
165     fi
166 }
167
168 load_modules() {
169     if [ -n "$MODPROBE" ]; then
170         # use modprobe
171     return 0
172     fi
173     if [ "$HAVE_MODULES" = true ]; then
174     # we already loaded
175         return 0
176     fi
177     HAVE_MODULES=true
178
179     echo Loading modules from $LUSTRE
180     load_module ../lnet/libcfs/libcfs
181     [ "$PTLDEBUG" ] && lctl set_param debug=$PTLDEBUG
182     [ "$SUBSYSTEM" ] && lctl set_param subsystem_debug=${SUBSYSTEM# }
183     local MODPROBECONF=
184     [ -f /etc/modprobe.conf ] && MODPROBECONF=/etc/modprobe.conf
185     [ ! "$MODPROBECONF" -a -d /etc/modprobe.d ] && MODPROBECONF=/etc/modprobe.d/Lustre
186     [ -z "$LNETOPTS" -a "$MODPROBECONF" ] && \
187         LNETOPTS=$(awk '/^options lnet/ { print $0}' $MODPROBECONF | sed 's/^options lnet //g')
188     echo $LNETOPTS | grep -q "accept=all"  || LNETOPTS="$LNETOPTS accept=all";
189     echo "lnet options: '$LNETOPTS'"
190     # note that insmod will ignore anything in modprobe.conf
191     load_module ../lnet/lnet/lnet $LNETOPTS
192     LNETLND=${LNETLND:-"socklnd/ksocklnd"}
193     load_module ../lnet/klnds/$LNETLND
194     load_module lvfs/lvfs
195     load_module obdclass/obdclass
196     load_module ptlrpc/ptlrpc
197     [ "$USE_QUOTA" = "yes" ] && load_module quota/lquota
198     load_module mdc/mdc
199     load_module osc/osc
200     load_module lov/lov
201     load_module mgc/mgc
202     if [ -z "$CLIENTONLY" ] && [ -z "$CLIENTMODSONLY" ]; then
203         load_module mgs/mgs
204         load_module mds/mds
205         grep -q crc16 /proc/kallsyms || { modprobe crc16 2>/dev/null || true; }
206         [ "$FSTYPE" = "ldiskfs" ] && load_module ../ldiskfs/ldiskfs/ldiskfs
207         load_module lvfs/fsfilt_$FSTYPE
208         load_module ost/ost
209         load_module obdfilter/obdfilter
210     fi
211
212     load_module llite/lustre
213     load_module llite/llite_lloop
214     rm -f $TMP/ogdb-$HOSTNAME
215     OGDB=$TMP
216     [ -d /r ] && OGDB="/r/tmp"
217     $LCTL modules > $OGDB/ogdb-$HOSTNAME
218     # 'mount' doesn't look in $PATH, just sbin
219     [ -f $LUSTRE/utils/mount.lustre ] && cp $LUSTRE/utils/mount.lustre /sbin/. || true
220 }
221
222 RMMOD=rmmod
223 if [ `uname -r | cut -c 3` -eq 4 ]; then
224     RMMOD="modprobe -r"
225 fi
226
227 wait_for_lnet() {
228     local UNLOADED=0
229     local WAIT=0
230     local MAX=60
231     MODULES=$($LCTL modules | awk '{ print $2 }')
232     while [ -n "$MODULES" ]; do
233     sleep 5
234     $RMMOD $MODULES >/dev/null 2>&1 || true
235     MODULES=$($LCTL modules | awk '{ print $2 }')
236         if [ -z "$MODULES" ]; then
237         return 0
238         else
239             WAIT=$((WAIT + 5))
240             echo "waiting, $((MAX - WAIT)) secs left"
241         fi
242         if [ $WAIT -eq $MAX ]; then
243             echo "LNET modules $MODULES will not unload"
244         lsmod
245             return 3
246         fi
247     done
248 }
249
250 unload_dep_module() {
251     #lsmod output
252     #libcfs                107852  17 llite_lloop,lustre,obdfilter,ost,...
253     local MODULE=$1
254     local DEPS=$(lsmod | awk '($1 == "'$MODULE'") { print $4 }' | tr ',' ' ')
255     for SUBMOD in $DEPS; do
256         unload_dep_module $SUBMOD
257     done
258     [ "$MODULE" = "libcfs" ] && $LCTL dk $TMP/debug || true
259     $RMMOD $MODULE || true
260 }
261
262 check_mem_leak () {
263     LEAK_LUSTRE=$(dmesg | tail -n 30 | grep "obd_memory.*leaked" || true)
264     LEAK_PORTALS=$(dmesg | tail -n 20 | grep "Portals memory leaked" || true)
265     if [ "$LEAK_LUSTRE" -o "$LEAK_PORTALS" ]; then
266         echo "$LEAK_LUSTRE" 1>&2
267         echo "$LEAK_PORTALS" 1>&2
268         mv $TMP/debug $TMP/debug-leak.`date +%s` || true
269         echo "Memory leaks detected"
270         [ -n "$IGNORE_LEAK" ] && { echo "ignoring leaks" && return 0; } || true
271         return 1
272     fi
273 }
274
275 unload_modules() {
276     wait_exit_ST client # bug 12845
277
278     lsmod | grep libcfs > /dev/null && $LCTL dl
279     [ -z "$CLIENTONLY" ] && unload_dep_module $FSTYPE
280     unload_dep_module libcfs
281
282     local MODULES=$($LCTL modules | awk '{ print $2 }')
283     if [ -n "$MODULES" ]; then
284         echo "Modules still loaded: "
285         echo $MODULES
286         if [ "$(lctl dl)" ]; then
287             echo "Lustre still loaded"
288             lctl dl || true
289             lsmod
290             return 2
291         else
292             echo "Lustre stopped but LNET is still loaded, waiting..."
293             wait_for_lnet || return 3
294         fi
295     fi
296     HAVE_MODULES=false
297
298     check_mem_leak || return 254
299
300     echo "modules unloaded."
301     return 0
302 }
303
304 # Facet functions
305 mount_facet() {
306     local facet=$1
307     shift
308     local dev=${facet}_dev
309     local opt=${facet}_opt
310     echo "Starting ${facet}: ${!opt} $@ ${!dev} ${MOUNT%/*}/${facet}"
311     do_facet ${facet} mount -t lustre ${!opt} $@ ${!dev} ${MOUNT%/*}/${facet}
312     RC=${PIPESTATUS[0]}
313     if [ $RC -ne 0 ]; then
314         echo "mount -t lustre $@ ${!dev} ${MOUNT%/*}/${facet}"
315         echo "Start of ${!dev} on ${facet} failed ${RC}"
316     else
317         do_facet ${facet} "lctl set_param debug=$PTLDEBUG; \
318             lctl set_param subsystem_debug=${SUBSYSTEM# }; \
319             lctl set_param debug_mb=${DEBUG_SIZE}; \
320             sync"
321
322         label=$(do_facet ${facet} "$E2LABEL ${!dev}")
323         [ -z "$label" ] && echo no label for ${!dev} && exit 1
324         eval export ${facet}_svc=${label}
325         echo Started ${label}
326     fi
327     return $RC
328 }
329
330 # start facet device options
331 start() {
332     facet=$1
333     shift
334     device=$1
335     shift
336     eval export ${facet}_dev=${device}
337     eval export ${facet}_opt=\"$@\"
338     do_facet ${facet} mkdir -p ${MOUNT%/*}/${facet}
339     mount_facet ${facet}
340     RC=$?
341     return $RC
342 }
343
344 stop() {
345     local running
346     facet=$1
347     shift
348     HOST=`facet_active_host $facet`
349     [ -z $HOST ] && echo stop: no host for $facet && return 0
350
351     running=$(do_facet ${facet} "grep -c ${MOUNT%/*}/${facet}' ' /proc/mounts") || true
352     if [ ${running} -ne 0 ]; then
353         echo "Stopping ${MOUNT%/*}/${facet} (opts:$@)"
354         do_facet ${facet} umount -d $@ ${MOUNT%/*}/${facet}
355     fi
356
357     # umount should block, but we should wait for unrelated obd's
358     # like the MGS or MGC to also stop.
359
360     wait_exit_ST ${facet}
361 }
362
363 zconf_mount() {
364     local OPTIONS
365     local client=$1
366     local mnt=$2
367     # Only supply -o to mount if we have options
368     if [ -n "$MOUNTOPT" ]; then
369         OPTIONS="-o $MOUNTOPT"
370     fi
371     local device=$MGSNID:/$FSNAME
372     if [ -z "$mnt" -o -z "$FSNAME" ]; then
373         echo Bad zconf mount command: opt=$OPTIONS dev=$device mnt=$mnt
374         exit 1
375     fi
376
377     echo "Starting client: $client: $OPTIONS $device $mnt"
378     do_node $client mkdir -p $mnt
379     do_node $client mount -t lustre $OPTIONS $device $mnt || return 1
380     do_node $client "lctl set_param debug=$PTLDEBUG;
381         lctl set_param subsystem_debug=${SUBSYSTEM# };
382         lctl set_param debug_mb=${DEBUG_SIZE}"
383
384     return 0
385 }
386
387 zconf_umount() {
388     local client=$1
389     local mnt=$2
390     local force
391     local busy 
392     local need_kill
393
394     [ "$3" ] && force=-f
395     local running=$(do_node $client "grep -c $mnt' ' /proc/mounts") || true
396     if [ $running -ne 0 ]; then
397         echo "Stopping client $client $mnt (opts:$force)"
398         do_node $client lsof -t $mnt || need_kill=no
399         if [ "x$force" != "x" -a "x$need_kill" != "xno" ]; then
400             pids=$(do_node $client lsof -t $mnt | sort -u);
401             if [ -n $pids ]; then
402                 do_node $client kill -9 $pids || true
403             fi
404         fi
405
406         busy=$(do_node $client "umount $force $mnt 2>&1" | grep -c "busy") || true
407         if [ $busy -ne 0 ] ; then
408             echo "$mnt is still busy, wait one second" && sleep 1
409             do_node $client umount $force $mnt
410         fi
411     fi
412 }
413
414 # mount clients if not mouted
415 zconf_mount_clients() {
416     local OPTIONS
417     local clients=$1
418     local mnt=$2
419
420     # Only supply -o to mount if we have options
421     if [ -n "$MOUNTOPT" ]; then
422         OPTIONS="-o $MOUNTOPT"
423     fi
424     local device=$MGSNID:/$FSNAME
425     if [ -z "$mnt" -o -z "$FSNAME" ]; then
426         echo Bad zconf mount command: opt=$OPTIONS dev=$device mnt=$mnt
427         exit 1
428     fi
429
430     echo "Starting client $clients: $OPTIONS $device $mnt"
431     do_nodes $clients "mount | grep $mnt || { mkdir -p $mnt && mount -t lustre $OPTIONS $device $mnt || false; }"
432
433     echo "Started clients $clients: "
434     do_nodes $clients "mount | grep $mnt"
435
436     do_nodes $clients "sysctl -w lnet.debug=$PTLDEBUG;
437         sysctl -w lnet.subsystem_debug=${SUBSYSTEM# };
438         sysctl -w lnet.debug_mb=${DEBUG_SIZE};"
439
440     return 0
441 }
442
443 zconf_umount_clients() {
444     local clients=$1
445     local mnt=$2
446     local force
447
448     [ "$3" ] && force=-f
449
450     echo "Stopping clients: $clients $mnt (opts:$force)"
451     do_nodes $clients "set -x; running=\\\$(grep -c $mnt' ' /proc/mounts)
452 if [ \\\$running -ne 0 ] ; then
453 echo Stopping client \\\$(hostname) client $mnt opts:$force
454 lsof -t $mnt || need_kill=no
455 if [ "x$force" != "x" -a "x\\\$need_kill" != "xno" ]; then
456     pids=\\\$(lsof -t $mnt | sort -u);
457     if [ -n \\\$pids ]; then
458              kill -9 \\\$pids
459     fi
460 fi
461 busy=\\\$(umount $force $mnt 2>&1 | grep -c "busy")
462 if [ \\\$busy -ne 0 ] ; then
463     echo "$mnt is still busy, wait one second" && sleep 1
464     umount $force $mnt
465 fi
466 fi"
467 }
468
469 shutdown_facet() {
470     local facet=$1
471     if [ "$FAILURE_MODE" = HARD ]; then
472         $POWER_DOWN `facet_active_host $facet`
473         sleep 2
474     elif [ "$FAILURE_MODE" = SOFT ]; then
475         stop $facet
476     fi
477 }
478
479 reboot_facet() {
480     facet=$1
481     if [ "$FAILURE_MODE" = HARD ]; then
482         $POWER_UP `facet_active_host $facet`
483     else
484         sleep 10
485     fi
486 }
487
488 boot_node() {
489     local node=$1
490     if [ "$FAILURE_MODE" = HARD ]; then
491        $POWER_UP $node
492     fi
493 }
494
495 # recovery-scale functions
496 check_progs_installed () {
497     local clients=$1
498     shift
499     local progs=$@
500
501     do_nodes $clients "set -x ; PATH=:$PATH status=true; for prog in $progs; do
502         which \\\$prog || { echo \\\$prog missing on \\\$(hostname) && status=false; }
503         done;
504         eval \\\$status"
505 }
506
507 start_client_load() {
508     local list=(${1//,/ })
509     local nodenum=$2
510
511     local numloads=${#CLIENT_LOADS[@]}
512     local testnum=$((nodenum % numloads))
513
514     do_node ${list[nodenum]} "PATH=$PATH MOUNT=$MOUNT ERRORS_OK=$ERRORS_OK \
515                               BREAK_ON_ERROR=$BREAK_ON_ERROR \
516                               END_RUN_FILE=$END_RUN_FILE \
517                               LOAD_PID_FILE=$LOAD_PID_FILE \
518                               TESTSUITELOG=$TESTSUITELOG \
519                               run_${CLIENT_LOADS[testnum]}.sh" &
520     CLIENT_LOAD_PIDS="$CLIENT_LOAD_PIDS $!"
521     log "Started client load: ${CLIENT_LOADS[testnum]} on ${list[nodenum]}"
522
523     eval export ${list[nodenum]}_load=${CLIENT_LOADS[testnum]}
524     return 0
525 }
526
527 start_client_loads () {
528     local clients=(${1//,/ })
529
530     for ((num=0; num < ${#clients[@]}; num++ )); do
531         start_client_load $1 $num
532     done
533 }
534
535 # only for remote client 
536 check_client_load () {
537     local client=$1
538     local var=${client}_load
539
540     local TESTLOAD=run_${!var}.sh
541
542     ps auxww | grep -v grep | grep $client | grep -q "$TESTLOAD" || return 1
543
544     check_catastrophe $client || return 2
545
546     # see if the load is still on the client
547     local tries=3
548     local RC=254
549     while [ $RC = 254 -a $tries -gt 0 ]; do
550         let tries=$tries-1
551         # assume success
552         RC=0
553         if ! do_node $client "ps auxwww | grep -v grep | grep -q $TESTLOAD"; then
554             RC=${PIPESTATUS[0]}
555             sleep 30
556         fi
557     done
558     if [ $RC = 254 ]; then
559         echo "got a return status of $RC from do_node while checking (i.e. with 'ps') the client load on the remote system"
560         # see if we can diagnose a bit why this is
561     fi
562
563     return $RC
564 }
565 check_client_loads () {
566    local clients=${1//,/ }
567    local client=
568    local rc=0
569
570    for client in $clients; do
571       check_client_load $client
572       rc=$?
573       if [ "$rc" != 0 ]; then
574         log "Client load failed on node $client, rc=$rc"
575         return $rc
576       fi
577    done
578 }
579 # End recovery-scale functions
580
581 # verify that lustre actually cleaned up properly
582 cleanup_check() {
583     [ -f $CATASTROPHE ] && [ `cat $CATASTROPHE` -ne 0 ] && \
584         error "LBUG/LASSERT detected"
585     BUSY=`dmesg | grep -i destruct || true`
586     if [ "$BUSY" ]; then
587         echo "$BUSY" 1>&2
588         [ -e $TMP/debug ] && mv $TMP/debug $TMP/debug-busy.`date +%s`
589         exit 205
590     fi
591
592     check_mem_leak || exit 204
593
594     [ "`lctl dl 2> /dev/null | wc -l`" -gt 0 ] && lctl dl && \
595         echo "$0: lustre didn't clean up..." 1>&2 && return 202 || true
596
597     if [ "`/sbin/lsmod 2>&1 | egrep 'lnet|libcfs'`" ]; then
598         echo "$0: modules still loaded..." 1>&2
599         /sbin/lsmod 1>&2
600         return 203
601     fi
602     return 0
603 }
604
605 wait_delete_completed () {
606     local TOTALPREV=`lctl get_param -n osc.*.kbytesavail | \
607                      awk 'BEGIN{total=0}; {total+=$1}; END{print total}'`
608
609     local WAIT=0
610     local MAX_WAIT=20
611     while [ "$WAIT" -ne "$MAX_WAIT" ]; do
612         sleep 1
613         TOTAL=`lctl get_param -n osc.*.kbytesavail | \
614                awk 'BEGIN{total=0}; {total+=$1}; END{print total}'`
615         [ "$TOTAL" -eq "$TOTALPREV" ] && break
616         echo "Waiting delete completed ... prev: $TOTALPREV current: $TOTAL "
617         TOTALPREV=$TOTAL
618         WAIT=$(( WAIT + 1))
619     done
620     echo "Delete completed."
621 }
622
623 wait_for_host() {
624     HOST=$1
625     check_network "$HOST" 900
626     while ! do_node $HOST "ls -d $LUSTRE " > /dev/null; do sleep 5; done
627 }
628
629 wait_for() {
630     facet=$1
631     HOST=`facet_active_host $facet`
632     wait_for_host $HOST
633 }
634
635 wait_mds_recovery_done () {
636     local timeout=`do_facet mds lctl get_param  -n timeout`
637 #define OBD_RECOVERY_TIMEOUT (obd_timeout * 5 / 2)
638 # as we are in process of changing obd_timeout in different ways
639 # let's set MAX longer than that
640     MAX=$(( timeout * 4 ))
641     WAIT=0
642     while [ $WAIT -lt $MAX ]; do
643         STATUS=`do_facet mds "lctl get_param -n mds.*-MDT*.recovery_status | grep status"`
644         echo $STATUS | grep COMPLETE && return 0
645         sleep 5
646         WAIT=$((WAIT + 5))
647         echo "Waiting $(($MAX - $WAIT)) secs for MDS recovery done"
648     done
649     echo "MDS recovery not done in $MAX sec"
650     return 1
651 }
652
653 wait_exit_ST () {
654     local facet=$1
655
656     local WAIT=0
657     local INTERVAL=1
658     local running
659     # conf-sanity 31 takes a long time cleanup
660     while [ $WAIT -lt 300 ]; do
661         running=$(do_facet ${facet} "lsmod | grep lnet > /dev/null && lctl dl | grep ' ST '") || true
662         [ -z "${running}" ] && return 0
663         echo "waited $WAIT for${running}"
664         [ $INTERVAL -lt 64 ] && INTERVAL=$((INTERVAL + INTERVAL))
665         sleep $INTERVAL
666         WAIT=$((WAIT + INTERVAL))
667     done
668     echo "service didn't stop after $WAIT seconds.  Still running:"
669     echo ${running}
670     return 1
671 }
672
673 wait_remote_prog () {
674    local prog=$1
675    local WAIT=0
676    local INTERVAL=5
677    local rc=0
678
679    [ "$PDSH" = "no_dsh" ] && return 0
680
681    while [ $WAIT -lt $2 ]; do
682         running=$(ps uax | grep "$PDSH.*$prog.*$MOUNT" | grep -v grep) || true
683         [ -z "${running}" ] && return 0 || true
684         echo "waited $WAIT for: "
685         echo "$running"
686         [ $INTERVAL -lt 60 ] && INTERVAL=$((INTERVAL + INTERVAL))
687         sleep $INTERVAL
688         WAIT=$((WAIT + INTERVAL))
689     done
690     local pids=$(ps  uax | grep "$PDSH.*$prog.*$MOUNT" | grep -v grep | awk '{print $2}')
691     [ -z "$pids" ] && return 0
692     echo "$PDSH processes still exists after $WAIT seconds.  Still running: $pids"
693     for pid in $pids; do
694         cat /proc/${pid}/status || true
695         cat /proc/${pid}/wchan || true
696         echo "Killing $pid"
697         kill -9 $pid || true
698         sleep 1
699         ps -P $pid && rc=1
700     done
701
702     return $rc
703 }
704
705 client_df() {
706     # not every config has many clients
707     if [ -n "$CLIENTS" ]; then
708         $PDSH $CLIENTS "df $MOUNT" > /dev/null
709     else
710         df $MOUNT > /dev/null
711     fi
712 }
713
714 client_reconnect() {
715     uname -n >> $MOUNT/recon
716     if [ -z "$CLIENTS" ]; then
717         df $MOUNT; uname -n >> $MOUNT/recon
718     else
719         do_nodes $CLIENTS "df $MOUNT; uname -n >> $MOUNT/recon" > /dev/null
720     fi
721     echo Connected clients:
722     cat $MOUNT/recon
723     ls -l $MOUNT/recon > /dev/null
724     rm $MOUNT/recon
725 }
726
727 facet_failover() {
728     facet=$1
729     sleep_time=$2
730     echo "Failing $facet on node `facet_active_host $facet`"
731     shutdown_facet $facet
732     [ -n "$sleep_time" ] && sleep $sleep_time
733     reboot_facet $facet
734     client_df &
735     DFPID=$!
736     RECOVERY_START_TIME=`date +%s`
737     echo "df pid is $DFPID"
738     change_active $facet
739     TO=`facet_active_host $facet`
740     echo "Failover $facet to $TO"
741     wait_for $facet
742     mount_facet $facet || error "Restart of $facet failed"
743 }
744
745 obd_name() {
746     local facet=$1
747 }
748
749 replay_barrier() {
750     local facet=$1
751     do_facet $facet sync
752     df $MOUNT
753     local svc=${facet}_svc
754     do_facet $facet $LCTL --device %${!svc} readonly
755     do_facet $facet $LCTL --device %${!svc} notransno
756     do_facet $facet $LCTL mark "$facet REPLAY BARRIER on ${!svc}"
757     $LCTL mark "local REPLAY BARRIER on ${!svc}"
758 }
759
760 replay_barrier_nodf() {
761     local facet=$1    echo running=${running}
762     do_facet $facet sync
763     local svc=${facet}_svc
764     echo Replay barrier on ${!svc}
765     do_facet $facet $LCTL --device %${!svc} readonly
766     do_facet $facet $LCTL --device %${!svc} notransno
767     do_facet $facet $LCTL mark "$facet REPLAY BARRIER on ${!svc}"
768     $LCTL mark "local REPLAY BARRIER on ${!svc}"
769 }
770
771 mds_evict_client() {
772     UUID=`lctl get_param -n mdc.${mds_svc}-mdc-*.uuid`
773     do_facet mds "lctl set_param -n mds.${mds_svc}.evict_client $UUID"
774 }
775
776 ost_evict_client() {
777     UUID=`lctl get_param -n osc.${ost1_svc}-osc-*.uuid`
778     do_facet ost1 "lctl set_param -n obdfilter.${ost1_svc}.evict_client $UUID"
779 }
780
781 fail() {
782     facet_failover $* || error "failover: $?"
783     df $MOUNT || error "post-failover df: $?"
784 }
785
786 fail_nodf() {
787     local facet=$1
788     facet_failover $facet
789 }
790
791 fail_abort() {
792     local facet=$1
793     stop $facet
794     change_active $facet
795     mount_facet $facet -o abort_recovery
796     df $MOUNT || echo "first df failed: $?"
797     sleep 1
798     df $MOUNT || error "post-failover df: $?"
799 }
800
801 do_lmc() {
802     echo There is no lmc.  This is mountconf, baby.
803     exit 1
804 }
805
806 h2gm () {
807     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
808         ID=`$PDSH $1 $GMNALNID -l | cut -d\  -f2`
809         echo $ID"@gm"
810     fi
811 }
812
813 h2name_or_ip() {
814     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
815         echo $1"@$2"
816     fi
817 }
818
819 h2ptl() {
820    if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
821        ID=`xtprocadmin -n $1 2>/dev/null | egrep -v 'NID' | awk '{print $1}'`
822        if [ -z "$ID" ]; then
823            echo "Could not get a ptl id for $1..."
824            exit 1
825        fi
826        echo $ID"@ptl"
827    fi
828 }
829 declare -fx h2ptl
830
831 h2tcp() {
832     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
833         echo $1"@tcp"
834     fi
835 }
836 declare -fx h2tcp
837
838 h2elan() {
839     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
840         if type __h2elan >/dev/null 2>&1; then
841             ID=$(__h2elan $1)
842         else
843             ID=`echo $1 | sed 's/[^0-9]*//g'`
844         fi
845         echo $ID"@elan"
846     fi
847 }
848 declare -fx h2elan
849
850 h2openib() {
851     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
852         ID=`echo $1 | sed 's/[^0-9]*//g'`
853         echo $ID"@openib"
854     fi
855 }
856 declare -fx h2openib
857
858 h2o2ib() {
859     h2name_or_ip "$1" "o2ib"
860 }
861 declare -fx h2o2ib
862
863 facet_host() {
864     local facet=$1
865
866     [ "$facet" == client ] && echo -n $HOSTNAME && return
867     varname=${facet}_HOST
868     if [ -z "${!varname}" ]; then
869         if [ "${facet:0:3}" == "ost" ]; then
870             eval ${facet}_HOST=${ost_HOST}
871         fi
872     fi
873     echo -n ${!varname}
874 }
875
876 facet_active() {
877     local facet=$1
878     local activevar=${facet}active
879
880     if [ -f $TMP/${facet}active ] ; then
881         source $TMP/${facet}active
882     fi
883
884     active=${!activevar}
885     if [ -z "$active" ] ; then
886         echo -n ${facet}
887     else
888         echo -n ${active}
889     fi
890 }
891
892 facet_active_host() {
893     local facet=$1
894     local active=`facet_active $facet`
895     if [ "$facet" == client ]; then
896         echo $HOSTNAME
897     else
898         echo `facet_host $active`
899     fi
900 }
901
902 change_active() {
903     local facet=$1
904     failover=${facet}failover
905     host=`facet_host $failover`
906     [ -z "$host" ] && return
907     curactive=`facet_active $facet`
908     if [ -z "${curactive}" -o "$curactive" == "$failover" ] ; then
909         eval export ${facet}active=$facet
910     else
911         eval export ${facet}active=$failover
912     fi
913     # save the active host for this facet
914     activevar=${facet}active
915     echo "$activevar=${!activevar}" > $TMP/$activevar
916 }
917
918 do_node() {
919     HOST=$1
920     shift
921     local myPDSH=$PDSH
922     if [ "$HOST" = "$HOSTNAME" ]; then
923         myPDSH="no_dsh"
924     elif [ -z "$myPDSH" -o "$myPDSH" = "no_dsh" ]; then
925         echo "cannot run remote command on $HOST with $myPDSH"
926         return 128
927     fi
928     if $VERBOSE; then
929         echo "CMD: $HOST $@" >&2
930         $myPDSH $HOST $LCTL mark "$@" > /dev/null 2>&1 || :
931     fi
932
933     if [ "$myPDSH" = "rsh" ]; then
934 # we need this because rsh does not return exit code of an executed command
935         local command_status="$TMP/cs"
936         rsh $HOST ":> $command_status"
937         rsh $HOST "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin;
938                     cd $RPWD; sh -c \"$@\") ||
939                     echo command failed >$command_status"
940         [ -n "$($myPDSH $HOST cat $command_status)" ] && return 1 || true
941         return 0
942     fi
943     $myPDSH $HOST "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin; cd $RPWD; sh -c \"$@\")" | sed "s/^${HOST}: //"
944     return ${PIPESTATUS[0]}
945 }
946
947 single_local_node () {
948    [ "$1" = "$HOSTNAME" ]
949 }
950
951 do_nodes() {
952     local rnodes=$1
953     shift
954
955     if $(single_local_node $rnodes); then
956         do_node $rnodes $@
957         return $?
958     fi
959
960     # This is part from do_node
961     local myPDSH=$PDSH
962
963     [ -z "$myPDSH" -o "$myPDSH" = "no_dsh" -o "$myPDSH" = "rsh" ] && \
964         echo "cannot run remote command on $rnodes with $myPDSH" && return 128
965
966     if $VERBOSE; then
967         echo "CMD: $rnodes $@" >&2
968         $myPDSH $rnodes $LCTL mark "$@" > /dev/null 2>&1 || :
969     fi
970
971     $myPDSH $rnodes "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin; cd $RPWD; sh -c \"$@\")" | sed -re "s/\w+:\s//g"
972     return ${PIPESTATUS[0]}
973 }
974
975 do_facet() {
976     facet=$1
977     shift
978     HOST=`facet_active_host $facet`
979     [ -z $HOST ] && echo No host defined for facet ${facet} && exit 1
980     do_node $HOST "$@"
981 }
982
983 add() {
984     local facet=$1
985     shift
986     # make sure its not already running
987     stop ${facet} -f
988     rm -f $TMP/${facet}active
989     do_facet ${facet} $MKFS $*
990 }
991
992 ostdevname() {
993     num=$1
994     DEVNAME=OSTDEV$num
995     #if $OSTDEVn isn't defined, default is $OSTDEVBASE + num
996     eval DEVPTR=${!DEVNAME:=${OSTDEVBASE}${num}}
997     echo -n $DEVPTR
998 }
999
1000 ########
1001 ## MountConf setup
1002
1003 stopall() {
1004     # make sure we are using the primary server, so test-framework will
1005     # be able to clean up properly.
1006     activemds=`facet_active mds`
1007     if [ $activemds != "mds" ]; then
1008         fail mds
1009     fi
1010
1011     # assume client mount is local
1012     grep " $MOUNT " /proc/mounts && zconf_umount $HOSTNAME $MOUNT $*
1013     grep " $MOUNT2 " /proc/mounts && zconf_umount $HOSTNAME $MOUNT2 $*
1014
1015     if [ -n "$CLIENTS" ]; then
1016             zconf_umount_clients $CLIENTS $MOUNT "$*" || true
1017             [ -n "$MOUNT2" ] && zconf_umount_clients $CLIENTS $MOUNT2 "$*" || true
1018     fi
1019
1020     [ "$CLIENTONLY" ] && return
1021     # The add fn does rm ${facet}active file, this would be enough
1022     # if we use do_facet <facet> only after the facet added, but
1023     # currently we use do_facet mds in local.sh
1024     stop mds -f
1025     rm -f ${TMP}/mdsactive
1026     for num in `seq $OSTCOUNT`; do
1027         stop ost$num -f
1028         rm -f $TMP/ost${num}active
1029     done
1030     return 0
1031 }
1032
1033 cleanupall() {
1034     stopall $*
1035     unload_modules
1036 }
1037
1038 formatall() {
1039     [ "$FSTYPE" ] && FSTYPE_OPT="--backfstype $FSTYPE"
1040
1041     stopall
1042     # We need ldiskfs here, may as well load them all
1043     load_modules
1044     [ "$CLIENTONLY" ] && return
1045     echo Formatting mds, osts
1046     if $VERBOSE; then
1047         add mds $MDS_MKFS_OPTS $FSTYPE_OPT --reformat $MDSDEV || exit 10
1048     else
1049         add mds $MDS_MKFS_OPTS $FSTYPE_OPT --reformat $MDSDEV > /dev/null || exit 10
1050     fi
1051
1052     for num in `seq $OSTCOUNT`; do
1053         if $VERBOSE; then
1054             add ost$num $OST_MKFS_OPTS $FSTYPE_OPT --reformat `ostdevname $num` || exit 10
1055         else
1056             add ost$num $OST_MKFS_OPTS $FSTYPE_OPT --reformat `ostdevname $num` > /dev/null || exit 10
1057         fi
1058     done
1059 }
1060
1061 mount_client() {
1062     grep " $1 " /proc/mounts || zconf_mount $HOSTNAME $*
1063 }
1064
1065 remount_client()
1066 {
1067         zconf_umount `hostname` $1 || error "umount failed"
1068         zconf_mount `hostname` $1 || error "mount failed"
1069 }
1070
1071 set_obd_timeout() {
1072     local facet=$1
1073     local timeout=$2
1074
1075     do_facet $facet lsmod | grep -q obdclass || \
1076         do_facet $facet "modprobe obdclass"
1077
1078     do_facet $facet "lctl set_param timeout=$timeout"
1079 }
1080
1081 writeconf_facet () {
1082     local facet=$1
1083     local dev=$2
1084
1085     do_facet $facet "$TUNEFS --writeconf $dev"
1086 }
1087
1088 writeconf_all () {
1089     writeconf_facet mds $MDSDEV
1090
1091     for num in `seq $OSTCOUNT`; do
1092         DEVNAME=`ostdevname $num`
1093         writeconf_facet ost$num $DEVNAME
1094     done
1095 }
1096
1097 setupall() {
1098     load_modules
1099     if [ -z "$CLIENTONLY" ]; then
1100         echo Setup mdt, osts
1101
1102         echo $WRITECONF | grep -q "writeconf" && \
1103             writeconf_all
1104
1105         set_obd_timeout mds $TIMEOUT
1106         start mds $MDSDEV $MDS_MOUNT_OPTS
1107         # We started mds, now we should set failover variable properly.
1108         # Set mdsfailover_HOST if it is not set (the default failnode).
1109         mdsfailover_HOST=$(facet_host mds)
1110
1111         for num in `seq $OSTCOUNT`; do
1112             DEVNAME=`ostdevname $num`
1113             set_obd_timeout ost$num $TIMEOUT
1114             start ost$num $DEVNAME $OST_MOUNT_OPTS
1115
1116             # We started ost$num, now we should set ost${num}failover variable properly.
1117             # Set ost${num}failover_HOST if it is not set (the default failnode).
1118             varname=ost${num}failover_HOST
1119             if [ -z "${!varname}" ]; then
1120                 eval ost${num}failover_HOST=$(facet_host ost${num})
1121             fi
1122
1123         done
1124     fi
1125     [ "$DAEMONFILE" ] && $LCTL debug_daemon start $DAEMONFILE $DAEMONSIZE
1126     mount_client $MOUNT
1127     [ -n "$CLIENTS" ] && zconf_mount_clients $CLIENTS $MOUNT
1128
1129     if [ "$MOUNT_2" ]; then
1130         mount_client $MOUNT2
1131         [ -n "$CLIENTS" ] && zconf_mount_clients $CLIENTS $MOUNT2
1132     fi
1133     sleep 5
1134     init_versions_vars
1135 }
1136
1137 mounted_lustre_filesystems() {
1138         awk '($3 ~ "lustre" && $1 ~ ":") { print $2 }' /proc/mounts
1139 }
1140
1141 init_facet_vars () {
1142     local facet=$1
1143     shift
1144     local device=$1
1145
1146     shift
1147
1148     eval export ${facet}_dev=${device}
1149     eval export ${facet}_opt=\"$@\"
1150
1151     local dev=${facet}_dev
1152     local label=$(do_facet ${facet} "$E2LABEL ${!dev}")
1153     [ -z "$label" ] && echo no label for ${!dev} && exit 1
1154
1155     eval export ${facet}_svc=${label}
1156
1157     local varname=${facet}failover_HOST
1158     if [ -z "${!varname}" ]; then
1159        eval $varname=$(facet_host $facet)
1160     fi
1161 }
1162
1163 init_facets_vars () {
1164     init_facet_vars mds $MDSDEV $MDS_MOUNT_OPTS
1165
1166     for num in `seq $OSTCOUNT`; do
1167         DEVNAME=`ostdevname $num`
1168         init_facet_vars ost$num $DEVNAME $OST_MOUNT_OPTS
1169     done
1170 }
1171
1172 init_versions_vars () {
1173     export MDSVER=$(do_facet mds "lctl get_param version" | cut -d. -f1,2)
1174     export OSTVER=$(do_facet ost1 "lctl get_param version" | cut -d. -f1,2)
1175     export CLIVER=$(lctl get_param version | cut -d. -f 1,2)
1176 }
1177
1178 check_config () {
1179     local mntpt=$1
1180     local myMGS_host=$mgs_HOST   
1181     if [ "$NETTYPE" = "ptl" ]; then
1182         myMGS_host=$(h2ptl $mgs_HOST | sed -e s/@ptl//) 
1183     fi
1184
1185     echo Checking config lustre mounted on $mntpt
1186     local mgshost=$(mount | grep " $mntpt " | awk -F@ '{print $1}')
1187     mgshost=$(echo $mgshost | awk -F: '{print $1}')
1188
1189     if [ "$mgshost" != "$myMGS_host" ]; then
1190         FAIL_ON_ERROR=true \
1191             error "Bad config file: lustre is mounted with mgs $mgshost, but mgs_HOST=$mgs_HOST, NETTYPE=$NETTYPE
1192                    Please use correct config or set mds_HOST correctly!"
1193     fi
1194 }
1195
1196 check_and_setup_lustre() {
1197     local MOUNTED=$(mounted_lustre_filesystems)
1198     if [ -z "$MOUNTED" ] || ! $(echo $MOUNTED | grep -w -q $MOUNT); then
1199         [ "$REFORMAT" ] && formatall
1200         setupall
1201         MOUNTED=$(mounted_lustre_filesystems | head -1)
1202         [ -z "$MOUNTED" ] && error "NAME=$NAME not mounted"
1203         export I_MOUNTED=yes
1204     else
1205         check_config $MOUNT
1206         init_facets_vars
1207         init_versions_vars
1208     fi
1209     if [ "$ONLY" == "setup" ]; then
1210         exit 0
1211     fi
1212 }
1213
1214 cleanup_and_setup_lustre() {
1215     if [ "$ONLY" == "cleanup" -o "`mount | grep $MOUNT`" ]; then
1216         lctl set_param debug=0 || true
1217         cleanupall
1218         if [ "$ONLY" == "cleanup" ]; then
1219             exit 0
1220         fi
1221     fi
1222     check_and_setup_lustre
1223 }
1224
1225 check_and_cleanup_lustre() {
1226     if [ "`mount | grep $MOUNT`" ]; then
1227         [ -n "$DIR" ] && rm -rf $DIR/[Rdfs][0-9]*
1228     fi
1229     if [ "$I_MOUNTED" = "yes" ]; then
1230         cleanupall -f || error "cleanup failed"
1231     fi
1232     unset I_MOUNTED
1233 }
1234
1235 #######
1236 # General functions
1237
1238 check_network() {
1239     local NETWORK=0
1240     local WAIT=0
1241     local MAX=$2
1242     while [ $NETWORK -eq 0 ]; do
1243         ping -c 1 -w 3 $1 > /dev/null
1244         if [ $? -eq 0 ]; then
1245             NETWORK=1
1246         else
1247             WAIT=$((WAIT + 5))
1248             echo "waiting for $1, $((MAX - WAIT)) secs left"
1249             sleep 5
1250         fi
1251         if [ $WAIT -gt $MAX ]; then
1252             echo "Network not available"
1253             exit 1
1254         fi
1255     done
1256 }
1257 check_port() {
1258     while( !($DSH2 $1 "netstat -tna | grep -q $2") ) ; do
1259         sleep 9
1260     done
1261 }
1262
1263 no_dsh() {
1264     shift
1265     eval $@
1266 }
1267
1268 comma_list() {
1269     # the sed converts spaces to commas, but leaves the last space
1270     # alone, so the line doesn't end with a comma.
1271     echo "$*" | tr -s " " "\n" | sort -b -u | tr "\n" " " | sed 's/ \([^$]\)/,\1/g'
1272 }
1273
1274 # list is comma separated list
1275 exclude_item_from_list () {
1276     local list=$1
1277     local excluded=$2
1278
1279     list=${list//,/ }
1280     list=$(echo " $list " | sed -re "s/\s+$excluded\s+/ /g")
1281     echo $(comma_list $list) 
1282 }
1283
1284 absolute_path() {
1285     (cd `dirname $1`; echo $PWD/`basename $1`)
1286 }
1287
1288 ##################################
1289 # Adaptive Timeouts funcs
1290
1291 at_is_valid() {
1292     if [ -z "$AT_MAX_PATH" ]; then
1293         AT_MAX_PATH=$(do_facet mds "find /sys/ -name at_max")
1294         [ -z "$AT_MAX_PATH" ] && echo "missing /sys/.../at_max " && return 1
1295     fi
1296     return 0
1297 }
1298
1299 at_is_enabled() {
1300     at_is_valid || error "invalid call"
1301
1302     # only check mds, we assume at_max is the same on all nodes
1303     local at_max=$(do_facet mds "cat $AT_MAX_PATH")
1304     if [ $at_max -eq 0 ]; then
1305         return 1
1306     else
1307         return 0
1308     fi
1309 }
1310
1311 at_max_get() {
1312     local facet=$1
1313
1314     at_is_valid || error "invalid call"
1315
1316     # suppose that all ost-s has the same at_max set
1317     if [ $facet == "ost" ]; then
1318         do_facet ost1 "cat $AT_MAX_PATH"
1319     else
1320         do_facet $facet "cat $AT_MAX_PATH"
1321     fi
1322 }
1323
1324 at_max_set() {
1325     local at_max=$1
1326     shift
1327
1328     at_is_valid || error "invalid call"
1329
1330     local facet
1331     for facet in $@; do
1332         if [ $facet == "ost" ]; then
1333             for i in `seq $OSTCOUNT`; do
1334                 do_facet ost$i "echo $at_max > $AT_MAX_PATH"
1335             done
1336         else
1337             do_facet $facet "echo $at_max > $AT_MAX_PATH"
1338         fi
1339     done
1340 }
1341
1342 ##################################
1343 # OBD_FAIL funcs
1344
1345 drop_request() {
1346 # OBD_FAIL_MDS_ALL_REQUEST_NET
1347     RC=0
1348     do_facet mds lctl set_param fail_loc=0x123
1349     do_facet client "$1" || RC=$?
1350     do_facet mds lctl set_param fail_loc=0
1351     return $RC
1352 }
1353
1354 drop_reply() {
1355 # OBD_FAIL_MDS_ALL_REPLY_NET
1356     RC=0
1357     do_facet mds lctl set_param fail_loc=0x122
1358     do_facet client "$@" || RC=$?
1359     do_facet mds lctl set_param fail_loc=0
1360     return $RC
1361 }
1362
1363 drop_reint_reply() {
1364 # OBD_FAIL_MDS_REINT_NET_REP
1365     RC=0
1366     do_facet mds lctl set_param fail_loc=0x119
1367     do_facet client "$@" || RC=$?
1368     do_facet mds lctl set_param fail_loc=0
1369     return $RC
1370 }
1371
1372 pause_bulk() {
1373 #define OBD_FAIL_OST_BRW_PAUSE_BULK      0x214
1374     RC=0
1375     do_facet ost1 lctl set_param fail_loc=0x214
1376     do_facet client "$1" || RC=$?
1377     do_facet client "sync"
1378     do_facet ost1 lctl set_param fail_loc=0
1379     return $RC
1380 }
1381
1382 drop_ldlm_cancel() {
1383 #define OBD_FAIL_LDLM_CANCEL             0x304
1384     RC=0
1385     do_facet client lctl set_param fail_loc=0x304
1386     do_facet client "$@" || RC=$?
1387     do_facet client lctl set_param fail_loc=0
1388     return $RC
1389 }
1390
1391 drop_bl_callback() {
1392 #define OBD_FAIL_LDLM_BL_CALLBACK        0x305
1393     RC=0
1394     do_facet client lctl set_param fail_loc=0x305
1395     do_facet client "$@" || RC=$?
1396     do_facet client lctl set_param fail_loc=0
1397     return $RC
1398 }
1399
1400 drop_ldlm_reply() {
1401 #define OBD_FAIL_LDLM_REPLY              0x30c
1402     RC=0
1403     do_facet mds lctl set_param fail_loc=0x30c
1404     do_facet client "$@" || RC=$?
1405     do_facet mds lctl set_param fail_loc=0
1406     return $RC
1407 }
1408
1409 clear_failloc() {
1410     facet=$1
1411     pause=$2
1412     sleep $pause
1413     echo "clearing fail_loc on $facet"
1414     do_facet $facet "lctl set_param fail_loc=0 2>/dev/null || true"
1415 }
1416
1417 set_nodes_failloc () {
1418     local nodes=$1
1419     local node
1420
1421     for node in $nodes ; do
1422         do_node $node lctl set_param fail_loc=$2
1423     done
1424 }
1425
1426 cancel_lru_locks() {
1427     $LCTL mark "cancel_lru_locks $1 start"
1428     for d in `lctl get_param -N ldlm.namespaces.*.lru_size | egrep -i $1`; do
1429         $LCTL set_param -n $d=clear
1430     done
1431     $LCTL get_param ldlm.namespaces.*.lock_unused_count | egrep -i $1 | grep -v '=0'
1432     $LCTL mark "cancel_lru_locks $1 stop"
1433 }
1434
1435 default_lru_size()
1436 {
1437         NR_CPU=$(grep -c "processor" /proc/cpuinfo)
1438         DEFAULT_LRU_SIZE=$((100 * NR_CPU))
1439         echo "$DEFAULT_LRU_SIZE"
1440 }
1441
1442 lru_resize_enable()
1443 {
1444     lctl set_param ldlm.namespaces.*$1*.lru_size=0
1445 }
1446
1447 lru_resize_disable()
1448 {
1449     lctl set_param ldlm.namespaces.*$1*.lru_size $(default_lru_size)
1450 }
1451
1452 pgcache_empty() {
1453     local FILE
1454     for FILE in `lctl get_param -N "llite.*.dump_page_cache"`; do
1455         if [ `lctl get_param -n $FILE | wc -l` -gt 1 ]; then
1456             echo there is still data in page cache $FILE ?
1457             lctl get_param -n $FILE
1458             return 1
1459         fi
1460     done
1461     return 0
1462 }
1463
1464 create_fake_exports () {
1465     local facet=$1
1466     local num=$2
1467 #obd_fail_val = num;
1468 #define OBD_FAIL_TGT_FAKE_EXP 0x708
1469     do_facet $facet "lctl set_param fail_val=$num"
1470     do_facet $facet "lctl set_param fail_loc=0x80000708"
1471     fail $facet
1472 }
1473
1474 debugsave() {
1475     DEBUGSAVE="$(lctl get_param -n debug)"
1476 }
1477
1478 debugrestore() {
1479     [ -n "$DEBUGSAVE" ] && lctl set_param debug="${DEBUGSAVE}"
1480     DEBUGSAVE=""
1481 }
1482
1483 ##################################
1484 # Test interface
1485 ##################################
1486
1487 error_noexit() {
1488     local TYPE=${TYPE:-"FAIL"}
1489     local ERRLOG
1490     lctl set_param fail_loc=0 2>/dev/null || true
1491     log " ${TESTSUITE} ${TESTNAME}: @@@@@@ ${TYPE}: $@ "
1492     ERRLOG=$TMP/lustre_${TESTSUITE}_${TESTNAME}.$(date +%s)
1493     echo "Dumping lctl log to $ERRLOG"
1494     # We need to dump the logs on all nodes
1495     local NODES=$(nodes_list)
1496     for NODE in $NODES; do
1497         do_node $NODE $LCTL dk $ERRLOG
1498     done
1499     debugrestore
1500     [ "$TESTSUITELOG" ] && echo "$0: ${TYPE}: $TESTNAME $@" >> $TESTSUITELOG
1501     TEST_FAILED=true
1502 }
1503
1504 error() {
1505     error_noexit "$@"
1506     $FAIL_ON_ERROR && exit 1 || true
1507 }
1508
1509 error_exit() {
1510     error_noexit "$@"
1511     exit 1
1512 }
1513
1514 # use only if we are ignoring failures for this test, bugno required.
1515 # (like ALWAYS_EXCEPT, but run the test and ignore the results.)
1516 # e.g. error_ignore 5494 "your message"
1517 error_ignore() {
1518     local TYPE="IGNORE (bz$1)"
1519     shift
1520     error_noexit "$@"
1521 }
1522
1523 skip () {
1524         log " SKIP: ${TESTSUITE} ${TESTNAME} $@"
1525         [ "$TESTSUITELOG" ] && \
1526                 echo "${TESTSUITE}: SKIP: $TESTNAME $@" >> $TESTSUITELOG || true
1527 }
1528
1529 build_test_filter() {
1530     [ "$ONLY" ] && log "only running test `echo $ONLY`"
1531     for O in $ONLY; do
1532         eval ONLY_${O}=true
1533     done
1534     [ "$EXCEPT$ALWAYS_EXCEPT" ] && \
1535         log "excepting tests: `echo $EXCEPT $ALWAYS_EXCEPT`"
1536     [ "$EXCEPT_SLOW" ] && \
1537         log "skipping tests SLOW=no: `echo $EXCEPT_SLOW`"
1538     for E in $EXCEPT $ALWAYS_EXCEPT; do
1539         eval EXCEPT_${E}=true
1540     done
1541     for E in $EXCEPT_SLOW; do
1542         eval EXCEPT_SLOW_${E}=true
1543     done
1544     for G in $GRANT_CHECK_LIST; do
1545         eval GCHECK_ONLY_${G}=true
1546         done
1547 }
1548
1549 _basetest() {
1550     echo $*
1551 }
1552
1553 basetest() {
1554     IFS=abcdefghijklmnopqrstuvwxyz _basetest $1
1555 }
1556
1557 # print a newline if the last test was skipped
1558 export LAST_SKIPPED=
1559 run_test() {
1560     assert_DIR
1561
1562     export base=`basetest $1`
1563     if [ ! -z "$ONLY" ]; then
1564         testname=ONLY_$1
1565         if [ ${!testname}x != x ]; then
1566             [ "$LAST_SKIPPED" ] && echo "" && LAST_SKIPPED=
1567             run_one $1 "$2"
1568             return $?
1569         fi
1570         testname=ONLY_$base
1571         if [ ${!testname}x != x ]; then
1572             [ "$LAST_SKIPPED" ] && echo "" && LAST_SKIPPED=
1573             run_one $1 "$2"
1574             return $?
1575         fi
1576         LAST_SKIPPED="y"
1577         echo -n "."
1578         return 0
1579     fi
1580     testname=EXCEPT_$1
1581     if [ ${!testname}x != x ]; then
1582         LAST_SKIPPED="y"
1583         TESTNAME=test_$1 skip "skipping excluded test $1"
1584         return 0
1585     fi
1586     testname=EXCEPT_$base
1587     if [ ${!testname}x != x ]; then
1588         LAST_SKIPPED="y"
1589         TESTNAME=test_$1 skip "skipping excluded test $1 (base $base)"
1590         return 0
1591     fi
1592     testname=EXCEPT_SLOW_$1
1593     if [ ${!testname}x != x ]; then
1594         LAST_SKIPPED="y"
1595         TESTNAME=test_$1 skip "skipping SLOW test $1"
1596         return 0
1597     fi
1598     testname=EXCEPT_SLOW_$base
1599     if [ ${!testname}x != x ]; then
1600         LAST_SKIPPED="y"
1601         TESTNAME=test_$1 skip "skipping SLOW test $1 (base $base)"
1602         return 0
1603     fi
1604
1605     LAST_SKIPPED=
1606     run_one $1 "$2"
1607
1608     return $?
1609 }
1610
1611 EQUALS="======================================================================"
1612 equals_msg() {
1613     msg="$@"
1614
1615     local suffixlen=$((${#EQUALS} - ${#msg}))
1616     [ $suffixlen -lt 5 ] && suffixlen=5
1617     log `echo $(printf '===== %s %.*s\n' "$msg" $suffixlen $EQUALS)`
1618 }
1619
1620 log() {
1621     echo "$*"
1622     lsmod | grep lnet > /dev/null || load_modules
1623
1624     local MSG="$*"
1625     # Get rif of '
1626     MSG=${MSG//\'/\\\'}
1627     MSG=${MSG//\(/\\\(}
1628     MSG=${MSG//\)/\\\)}
1629     MSG=${MSG//\;/\\\;}
1630     MSG=${MSG//\|/\\\|}
1631     MSG=${MSG//\>/\\\>}
1632     MSG=${MSG//\</\\\<}
1633     MSG=${MSG//\//\\\/}
1634     local NODES=$(nodes_list)
1635     for NODE in $NODES; do
1636         do_node $NODE $LCTL mark "$MSG" 2> /dev/null || true
1637     done
1638 }
1639
1640 trace() {
1641         log "STARTING: $*"
1642         strace -o $TMP/$1.strace -ttt $*
1643         RC=$?
1644         log "FINISHED: $*: rc $RC"
1645         return 1
1646 }
1647
1648 pass() {
1649     $TEST_FAILED && echo -n "FAIL " || echo -n "PASS " 
1650     echo $@
1651 }
1652
1653 check_mds() {
1654     FFREE=`lctl get_param -n mds.*.filesfree`
1655     FTOTAL=`lctl get_param -n mds.*.filestotal`
1656     [ $FFREE -ge $FTOTAL ] && error "files free $FFREE > total $FTOTAL" || true
1657 }
1658
1659 reset_fail_loc () {
1660     local myNODES=$(nodes_list)
1661     local NODE
1662
1663     for NODE in $myNODES; do
1664         do_node $NODE "lctl set_param fail_loc=0 2>/dev/null || true"
1665     done
1666 }
1667
1668 run_one() {
1669     testnum=$1
1670     message=$2
1671     tfile=f${testnum}
1672     export tdir=d0.${TESTSUITE}/d${base}
1673
1674     local SAVE_UMASK=`umask`
1675     umask 0022
1676
1677     BEFORE=`date +%s`
1678     log "== test $testnum: $message ============ `date +%H:%M:%S` ($BEFORE)"
1679     #check_mds
1680     export TESTNAME=test_$testnum
1681     TEST_FAILED=false
1682     test_${testnum} || error "test_$testnum failed with $?"
1683     #check_mds
1684     cd $SAVE_PWD
1685     reset_fail_loc
1686     check_grant ${testnum} || error "check_grant $testnum failed with $?"
1687     check_catastrophe || error "LBUG/LASSERT detected"
1688     ps auxww | grep -v grep | grep -q multiop && error "multiop still running"
1689     pass "($((`date +%s` - $BEFORE))s)"
1690     TEST_FAILED=false
1691     unset TESTNAME
1692     unset tdir
1693     umask $SAVE_UMASK
1694 }
1695
1696 canonical_path() {
1697     (cd `dirname $1`; echo $PWD/`basename $1`)
1698 }
1699
1700 sync_clients() {
1701     [ -d $DIR1 ] && cd $DIR1 && sync; sleep 1; sync
1702     [ -d $DIR2 ] && cd $DIR2 && sync; sleep 1; sync
1703         cd $SAVE_PWD
1704 }
1705
1706 check_grant() {
1707     export base=`basetest $1`
1708     [ "$CHECK_GRANT" == "no" ] && return 0
1709
1710         testname=GCHECK_ONLY_${base}
1711     [ ${!testname}x == x ] && return 0
1712
1713     echo -n "checking grant......"
1714         cd $SAVE_PWD
1715         # write some data to sync client lost_grant
1716         rm -f $DIR1/${tfile}_check_grant_* 2>&1
1717         for i in `seq $OSTCOUNT`; do
1718                 $LFS setstripe $DIR1/${tfile}_check_grant_$i -i $(($i -1)) -c 1
1719                 dd if=/dev/zero of=$DIR1/${tfile}_check_grant_$i bs=4k \
1720                                               count=1 > /dev/null 2>&1
1721         done
1722     # sync all the data and make sure no pending data on server
1723     sync_clients
1724
1725     #get client grant and server grant
1726     client_grant=0
1727     for d in `lctl get_param -n osc.*.cur_grant_bytes`; do
1728         client_grant=$((client_grant + $d))
1729     done
1730     server_grant=0
1731     for d in `lctl get_param -n obdfilter.*.tot_granted`; do
1732         server_grant=$((server_grant + $d))
1733     done
1734
1735         # cleanup the check_grant file
1736         for i in `seq $OSTCOUNT`; do
1737                 rm $DIR1/${tfile}_check_grant_$i
1738         done
1739
1740         #check whether client grant == server grant
1741         if [ $client_grant != $server_grant ]; then
1742                 echo "failed: client:${client_grant} server: ${server_grant}"
1743                 return 1
1744         else
1745                 echo "pass"
1746         fi
1747 }
1748
1749 ########################
1750 # helper functions
1751
1752 osc_to_ost()
1753 {
1754     osc=$1
1755     ost=`echo $1 | awk -F_ '{print $3}'`
1756     if [ -z $ost ]; then
1757         ost=`echo $1 | sed 's/-osc.*//'`
1758     fi
1759     echo $ost
1760 }
1761
1762 remote_node () {
1763     local node=$1
1764     [ "$node" != "$(hostname)" ]
1765 }
1766
1767 remote_mds ()
1768 {
1769     remote_node $mds_HOST
1770 }
1771
1772 remote_mds_nodsh()
1773 {
1774     remote_mds && [ "$PDSH" = "no_dsh" -o -z "$PDSH" -o -z "$mds_HOST" ]
1775 }
1776
1777 remote_ost ()
1778 {
1779     local node
1780     for node in $(osts_nodes) ; do
1781         remote_node $node && return 0
1782     done
1783     return 1
1784 }
1785
1786 remote_ost_nodsh()
1787 {
1788     remote_ost && [ "$PDSH" = "no_dsh" -o -z "$PDSH" -o -z "$ost_HOST" ]
1789 }
1790
1791 remote_servers () {
1792     remote_ost && remote_mds
1793 }
1794
1795 osts_nodes () {
1796     local OSTNODES=$(facet_host ost1)
1797     local NODES_sort
1798
1799     for num in `seq $OSTCOUNT`; do
1800         local myOST=$(facet_host ost$num)
1801         OSTNODES="$OSTNODES $myOST"
1802     done
1803     NODES_sort=$(for i in $OSTNODES; do echo $i; done | sort -u)
1804
1805     echo $NODES_sort
1806 }
1807
1808 nodes_list () {
1809     # FIXME. We need a list of clients
1810     local myNODES=$HOSTNAME
1811     local myNODES_sort
1812
1813     # CLIENTS (if specified) contains the local client
1814     [ -n "$CLIENTS" ] && myNODES=${CLIENTS//,/ }
1815
1816     if [ "$PDSH" -a "$PDSH" != "no_dsh" ]; then
1817         myNODES="$myNODES $(osts_nodes) $mds_HOST"
1818     fi
1819
1820     myNODES_sort=$(for i in $myNODES; do echo $i; done | sort -u)
1821
1822     echo $myNODES_sort
1823 }
1824
1825 remote_nodes_list () {
1826     local rnodes=$(nodes_list)
1827     rnodes=$(echo " $rnodes " | sed -re "s/\s+$HOSTNAME\s+/ /g")
1828     echo $rnodes
1829 }
1830
1831 init_clients_lists () {
1832     # Sanity check: exclude the local client from RCLIENTS
1833     local rclients=$(echo " $RCLIENTS " | sed -re "s/\s+$HOSTNAME\s+/ /g")
1834
1835     # Sanity check: exclude the dup entries
1836     rclients=$(for i in $rclients; do echo $i; done | sort -u)
1837
1838     local clients="$SINGLECLIENT $HOSTNAME $rclients"
1839
1840     # Sanity check: exclude the dup entries from CLIENTS
1841     # for those configs which has SINGLCLIENT set to local client
1842     clients=$(for i in $clients; do echo $i; done | sort -u)
1843
1844     CLIENTS=`comma_list $clients`
1845     local -a remoteclients=($rclients)
1846     for ((i=0; $i<${#remoteclients[@]}; i++)); do
1847             varname=CLIENT$((i + 2))
1848             eval $varname=${remoteclients[i]}
1849     done
1850
1851     CLIENTCOUNT=$((${#remoteclients[@]} + 1))
1852 }
1853
1854 get_random_entry () {
1855     local rnodes=$1
1856
1857     rnodes=${rnodes//,/ }
1858
1859     local nodes=($rnodes)
1860     local num=${#nodes[@]} 
1861     local i=$((RANDOM * num  / 65536))
1862
1863     echo ${nodes[i]}
1864 }
1865
1866 is_patchless ()
1867 {
1868     lctl get_param version | grep -q patchless
1869 }
1870
1871 check_versions () {
1872     [ "$MDSVER" = "$CLIVER" -a "$OSTVER" = "$CLIVER" ]
1873 }
1874
1875 get_node_count() {
1876     local nodes="$@"
1877     echo $nodes | wc -w || true
1878 }
1879
1880 mixed_ost_devs () {
1881     local nodes=$(osts_nodes)
1882     local osscount=$(get_node_count "$nodes")
1883     [ ! "$OSTCOUNT" = "$osscount" ]
1884 }
1885
1886 generate_machine_file() {
1887     local nodes=${1//,/ }
1888     local machinefile=$2
1889     rm -f $machinefile || error "can't rm $machinefile"
1890     for node in $nodes; do
1891         echo $node >>$machinefile
1892     done
1893 }
1894
1895 get_stripe () {
1896     local file=$1/stripe
1897     touch $file
1898     $LFS getstripe -v $file || error
1899     rm -f $file
1900 }
1901
1902 check_runas_id_ret() {
1903     local myRC=0
1904     local myRUNAS_UID=$1
1905     local myRUNAS_GID=$2
1906     shift 2
1907     local myRUNAS=$@
1908     if [ -z "$myRUNAS" ]; then
1909         error_exit "myRUNAS command must be specified for check_runas_id"
1910     fi
1911     mkdir $DIR/d0_runas_test
1912     chmod 0755 $DIR
1913     chown $myRUNAS_UID:$myRUNAS_GID $DIR/d0_runas_test
1914     $myRUNAS touch $DIR/d0_runas_test/f$$ || myRC=1
1915     rm -rf $DIR/d0_runas_test
1916     return $myRC
1917 }
1918
1919 check_runas_id() {
1920     local myRUNAS_UID=$1
1921     local myRUNAS_GID=$2
1922     shift 2
1923     local myRUNAS=$@
1924     check_runas_id_ret $myRUNAS_UID $myRUNAS_GID $myRUNAS || \
1925         error "unable to write to $DIR/d0_runas_test as UID $myRUNAS_UID.
1926         Please set RUNAS_ID to some UID which exists on MDS and client or
1927         add user $myRUNAS_UID:$myRUNAS_GID on these nodes."
1928 }
1929
1930 # Run multiop in the background, but wait for it to print
1931 # "PAUSING" to its stdout before returning from this function.
1932 multiop_bg_pause() {
1933     MULTIOP_PROG=${MULTIOP_PROG:-multiop}
1934     FILE=$1
1935     ARGS=$2
1936
1937     TMPPIPE=/tmp/multiop_open_wait_pipe.$$
1938     mkfifo $TMPPIPE
1939
1940     echo "$MULTIOP_PROG $FILE v$ARGS"
1941     $MULTIOP_PROG $FILE v$ARGS > $TMPPIPE &
1942
1943     echo "TMPPIPE=${TMPPIPE}"
1944     local multiop_output
1945     local multiop_pid
1946
1947     read -t 60 multiop_output multiop_pid < $TMPPIPE
1948     if [ $? -ne 0 ]; then
1949         rm -f $TMPPIPE
1950         return 1
1951     fi
1952     rm -f $TMPPIPE
1953     if [ "$multiop_output" != "PAUSING" ]; then
1954         echo "Incorrect multiop output: $multiop_output"
1955         kill -9 $PID
1956         return 1
1957     fi
1958
1959     echo $multiop_pid
1960     return 0
1961 }
1962
1963 check_rate() {
1964     local OP=$1
1965     local TARGET_RATE=$2
1966     local NUM_CLIENTS=$3
1967     local LOG=$4
1968
1969     local RATE=$(awk '/^Rate: [0-9\.]+ '"${OP}"'s\/sec/ { print $2}' ${LOG})
1970
1971     # We need to use bc since the rate is a floating point number
1972     local RES=$(echo "${RATE} < ${TARGET_RATE}" | bc -l )
1973     if [ "${RES}" = 0 ]; then
1974         echo "Success: ${RATE} ${OP}s/sec met target rate" \
1975              "${TARGET_RATE} ${OP}s/sec for ${NUM_CLIENTS} client(s)."
1976         return 0
1977     else
1978         echo "Failure: ${RATE} ${OP}s/sec did not meet target rate" \
1979              "${TARGET_RATE} ${OP}s/sec for ${NUM_CLIENTS} client(s)."
1980         return 1
1981     fi
1982 }
1983
1984 # reset llite stat counters
1985 clear_llite_stats(){
1986         lctl set_param -n llite.*.stats 0
1987 }
1988
1989 # sum llite stat items
1990 calc_llite_stats() {
1991         local res=$(lctl get_param -n llite.*.stats |
1992                     awk 'BEGIN {s = 0} END {print s} /^'"$1"'/ {s += $2}')
1993         echo $res
1994 }
1995
1996 calc_sum () {
1997         awk 'BEGIN {s = 0}; {s += $1}; END {print s}'
1998 }
1999
2000 calc_osc_kbytes () {
2001         $LCTL get_param -n osc.*[oO][sS][cC][-_]*.$1 | calc_sum
2002 }
2003
2004 # save_lustre_params(node, parameter_mask)
2005 # generate a stream of formatted strings (<node> <param name>=<param value>)
2006 save_lustre_params() {
2007         local s
2008         do_node $1 "lctl get_param $2" | while read s; do echo "$1 $s"; done
2009 }
2010
2011 # restore lustre parameters from input stream, produces by save_lustre_params
2012 restore_lustre_params() {
2013         local node
2014         local name
2015         local val
2016         while IFS=" =" read node name val; do
2017                 do_node $node "lctl set_param -n $name $val"
2018         done
2019 }
2020
2021 check_catastrophe () {
2022     local rnodes=${1:-$(comma_list $(remote_nodes_list))}
2023
2024     [ -f $CATASTROPHE ] && [ $(cat $CATASTROPHE) -ne 0 ] && return 1
2025     if [ $rnodes ]; then
2026         do_nodes $rnodes "set -x; [ -f $CATASTROPHE ] && { [ \`cat $CATASTROPHE\` -eq 0 ] || false; } || true"
2027     fi
2028 }
2029
2030 # $1 node
2031 # $2 file
2032 # $3 $RUNAS
2033 get_stripe_info() {
2034         local tmp_file
2035
2036         stripe_size=0
2037         stripe_count=0
2038         stripe_index=0
2039         tmp_file=$(mktemp)
2040
2041         do_facet $1 $3 lfs getstripe -v $2 > $tmp_file
2042
2043         stripe_size=`awk '$1 ~ /size/ {print $2}' $tmp_file`
2044         stripe_count=`awk '$1 ~ /count/ {print $2}' $tmp_file`
2045         stripe_index=`awk '/obdidx/ {start = 1; getline; print $1; exit}' $tmp_file`
2046         rm -f $tmp_file
2047 }
2048
2049 mpi_run () {
2050     local mpirun="$MPIRUN $MPIRUN_OPTIONS"
2051     local command="$mpirun $@"
2052
2053     if [ "$MPI_USER" != root -a $mpirun ]; then
2054         echo "+ chmod 0777 $MOUNT"
2055         chmod 0777 $MOUNT
2056         command="su $MPI_USER sh -c \"$command \""
2057     fi
2058
2059     ls -ald $MOUNT
2060     echo "+ $command"
2061     eval $command
2062 }
2063
2064 delayed_recovery_enabled () {
2065     do_facet mds "lctl get_param -n mds.${mds_svc}.stale_export_age" > /dev/null 2>&1
2066 }
2067
2068 ################################################################################
2069 # The following functions are used to enable interop testing between
2070 # 1.8 and 2.0. The lprocfs layout changed from 1.8 to 2.0 as the followings:
2071 # mds -> mdt
2072 # {blocksize filesfree filestotal fstype kbytesavail kbytesfree kbytestotal mntdev} moved from mds to osd
2073 # mdt lov: fsname-mdtlov -> fsname-MDTXXXX-mdtlov
2074 # mdt osc: fsname-OSTXXXX-osc -> fsname-OSTXXXX-osc-MDTXXXX
2075 ################################################################################
2076
2077 get_lustre_version () {
2078     local node=${1:-"mds"}    
2079     do_facet $node $LCTL get_param -n version |  awk '/^lustre:/ {print $2}'
2080 }
2081
2082 get_mds_version_major () {
2083     local version=$(get_lustre_version mds)
2084     echo $version | awk -F. '{print $1}'
2085 }
2086
2087 get_mds_version_minor () {
2088     local version=$(get_lustre_version mds)
2089     echo $version | awk -F. '{print $2}'
2090 }
2091
2092 get_mds_version_patch () {
2093     local version=$(get_lustre_version mds)
2094     echo $version | awk -F. '{print $3}'
2095 }
2096
2097 get_mds_version_fix () {
2098     local version=$(get_lustre_version mds)
2099     echo $version | awk -F. '{print $4}'
2100 }
2101
2102 get_mds_fsstat_proc_path() {
2103     local major=$(get_mds_version_major)
2104     local minor=$(get_mds_version_minor)
2105     if [ $major -le 1 -a $minor -le 8 ] ; then
2106         echo "mds"
2107     else
2108         echo "osd"
2109     fi
2110 }
2111
2112 get_mds_mntdev_proc_path() {
2113     local fsstat_dev=$(get_mds_fsstat_proc_path)
2114     echo "$fsstat_dev.*.mntdev"
2115 }
2116
2117 get_mdtlov_proc_path() {
2118     local fsname=$1
2119     local major=$(get_mds_version_major)
2120     local minor=$(get_mds_version_minor)
2121     if [ $major -le 1 -a $minor -le 8 ] ; then
2122         echo "$fsname-mdtlov"
2123     else
2124         echo "$fsname-MDT0000-mdtlov"
2125     fi
2126 }
2127
2128 get_mdtosc_proc_path() {
2129     local ost=$1
2130     local major=$(get_mds_version_major)
2131     local minor=$(get_mds_version_minor)
2132     if [ $major -le 1 -a $minor -le 8 ] ; then
2133         echo "${ost}-osc"
2134     else
2135         echo "${ost}-osc-MDT0000"
2136     fi
2137 }