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