Whamcloud - gitweb
Branch b1_6
[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 VERBOSE=false
11 export GMNALNID=${GMNALNID:-/usr/sbin/gmlndnid}
12 export CATASTROPHE=${CATASTROPHE:-/proc/sys/lnet/catastrophe}
13 #export PDSH="pdsh -S -Rssh -w"
14
15 # eg, assert_env LUSTRE MDSNODES OSTNODES CLIENTS
16 assert_env() {
17     local failed=""
18     for name in $@; do
19         if [ -z "${!name}" ]; then
20             echo "$0: $name must be set"
21             failed=1
22         fi
23     done
24     [ $failed ] && exit 1 || true
25 }
26
27 usage() {
28     echo "usage: $0 [-r] [-f cfgfile]"
29     echo "       -r: reformat"
30
31     exit
32 }
33
34 print_summary () {
35     [ "$TESTSUITE" == "lfscktest" ] && return 0
36     [ -n "$ONLY" ] && echo "WARNING: ONLY is set to ${ONLY}."
37     local form="%-13s %-17s %s\n"
38     printf "$form" "status" "script" "skipped tests E(xcluded) S(low)"
39     echo "------------------------------------------------------------------------------------"
40     for O in $TESTSUITE_LIST; do
41         local skipped=""
42         local slow=""
43         local o=$(echo $O | tr "[:upper:]" "[:lower:]")
44         o=${o//_/-}
45         o=${o//tyn/tyN}
46         local log=${TMP}/${o}.log 
47         [ -f $log ] && skipped=$(grep excluded $log | awk '{ printf " %s", $3 }' | sed 's/test_//g')
48         [ -f $log ] && slow=$(grep SLOW $log | awk '{ printf " %s", $3 }' | sed 's/test_//g')
49         [ "${!O}" = "done" ] && \
50             printf "$form" "Done" "$O" "E=$skipped" && \
51             [ -n "$slow" ] && printf "$form" "-" "-" "S=$slow"
52
53     done
54
55     for O in $TESTSUITE_LIST; do
56         [ "${!O}" = "no" ] && \
57             printf "$form" "Skipped" "$O" ""
58     done
59
60     for O in $TESTSUITE_LIST; do
61         [ "${!O}" = "done" -o "${!O}" = "no" ] || \
62             printf "$form" "UNFINISHED" "$O" ""
63     done
64 }
65
66 init_test_env() {
67     export LUSTRE=`absolute_path $LUSTRE`
68     export TESTSUITE=`basename $0 .sh`
69     export LTESTDIR=${LTESTDIR:-$LUSTRE/../ltest}
70
71     [ -d /r ] && export ROOT=${ROOT:-/r}
72     export TMP=${TMP:-$ROOT/tmp}
73     export TESTSUITELOG=${TMP}/${TESTSUITE}.log
74
75     export PATH=:$PATH:$LUSTRE/utils:$LUSTRE/tests
76     export LCTL=${LCTL:-"$LUSTRE/utils/lctl"}
77     export LFS=${LFS:-"$LUSTRE/utils/lfs"}
78     [ ! -f "$LCTL" ] && export LCTL=$(which lctl) 
79     export LFS=${LFS:-"$LUSTRE/utils/lfs"}
80     [ ! -f "$LFS" ] && export LFS=$(which lfs) 
81     export MKFS=${MKFS:-"$LUSTRE/utils/mkfs.lustre"}
82     [ ! -f "$MKFS" ] && export MKFS=$(which mkfs.lustre) 
83     export TUNEFS=${TUNEFS:-"$LUSTRE/utils/tunefs.lustre"}
84     [ ! -f "$TUNEFS" ] && export TUNEFS=$(which tunefs.lustre) 
85     export CHECKSTAT="${CHECKSTAT:-"checkstat -v"} "
86     export FSYTPE=${FSTYPE:-"ldiskfs"}
87     export NAME=${NAME:-local}
88     export LPROC=/proc/fs/lustre
89     export DIR2
90
91     if [ "$ACCEPTOR_PORT" ]; then
92         export PORT_OPT="--port $ACCEPTOR_PORT"
93     fi
94
95     # Paths on remote nodes, if different 
96     export RLUSTRE=${RLUSTRE:-$LUSTRE}
97     export RPWD=${RPWD:-$PWD}
98     export I_MOUNTED=${I_MOUNTED:-"no"}
99
100     # command line
101     
102     while getopts "rvf:" opt $*; do 
103         case $opt in
104             f) CONFIG=$OPTARG;;
105             r) REFORMAT=--reformat;;
106             v) VERBOSE=true;;
107             \?) usage;;
108         esac
109     done
110
111     shift $((OPTIND - 1))
112     ONLY=${ONLY:-$*}
113
114     [ "$TESTSUITELOG" ] && rm -f $TESTSUITELOG || true
115
116 }
117
118 case `uname -r` in
119 2.4.*) EXT=".o"; USE_QUOTA=no; [ ! "$CLIENTONLY" ] && FSTYPE=ext3;;
120     *) EXT=".ko"; USE_QUOTA=yes;;
121 esac
122
123 have_modules () {
124     lsmod | grep -q lnet
125 }
126
127 load_module() {
128     module=$1
129     shift
130     BASE=`basename $module $EXT`
131     lsmod | grep -q ${BASE} || \
132       if [ -f ${LUSTRE}/${module}${EXT} ]; then
133         insmod ${LUSTRE}/${module}${EXT} $@
134     else
135         # must be testing a "make install" or "rpm" installation
136         modprobe $BASE $@
137     fi
138 }
139
140 load_modules() {
141     if [ -n "$MODPROBE" ]; then
142         # use modprobe
143     return 0
144     fi
145     # we already loaded ?
146     have_modules && return 0
147
148     echo Loading modules from $LUSTRE
149     load_module ../lnet/libcfs/libcfs
150     [ -f /etc/modprobe.conf ] && MODPROBECONF=/etc/modprobe.conf
151     [ -f /etc/modprobe.d/Lustre ] && MODPROBECONF=/etc/modprobe.d/Lustre
152     [ -z "$LNETOPTS" -a -n "$MODPROBECONF" ] && \
153         LNETOPTS=$(awk '/^options lnet/ { print $0}' $MODPROBECONF | sed 's/^options lnet //g')
154     echo "lnet options: '$LNETOPTS'"
155     # note that insmod will ignore anything in modprobe.conf
156     load_module ../lnet/lnet/lnet $LNETOPTS
157     LNETLND=${LNETLND:-"socklnd/ksocklnd"}
158     load_module ../lnet/klnds/$LNETLND
159     load_module lvfs/lvfs
160     load_module obdclass/obdclass
161     load_module ptlrpc/ptlrpc
162     [ "$USE_QUOTA" = "yes" ] && load_module quota/lquota
163     load_module mdc/mdc
164     load_module osc/osc
165     load_module lov/lov
166     load_module mgc/mgc
167     if [ -z "$CLIENTONLY" ] && [ -z "$CLIENTMODSONLY" ]; then
168         load_module mgs/mgs
169         load_module mds/mds
170         [ "$FSTYPE" = "ldiskfs" ] && load_module ../ldiskfs/ldiskfs/ldiskfs
171         load_module lvfs/fsfilt_$FSTYPE
172         load_module ost/ost
173         load_module obdfilter/obdfilter
174     fi
175
176     load_module llite/lustre
177     load_module llite/llite_lloop
178     rm -f $TMP/ogdb-`hostname`
179     OGDB=$TMP
180     [ -d /r ] && OGDB="/r/tmp"
181     $LCTL modules > $OGDB/ogdb-`hostname`
182     # 'mount' doesn't look in $PATH, just sbin
183     [ -f $LUSTRE/utils/mount.lustre ] && cp $LUSTRE/utils/mount.lustre /sbin/. || true
184 }
185
186 RMMOD=rmmod
187 if [ `uname -r | cut -c 3` -eq 4 ]; then
188     RMMOD="modprobe -r"
189 fi
190
191 wait_for_lnet() {
192     local UNLOADED=0
193     local WAIT=0
194     local MAX=60
195     MODULES=$($LCTL modules | awk '{ print $2 }')
196     while [ -n "$MODULES" ]; do
197     sleep 5
198     $RMMOD $MODULES >/dev/null 2>&1 || true
199     MODULES=$($LCTL modules | awk '{ print $2 }')
200         if [ -z "$MODULES" ]; then
201         return 0
202         else
203             WAIT=$((WAIT + 5))
204             echo "waiting, $((MAX - WAIT)) secs left"
205         fi
206         if [ $WAIT -eq $MAX ]; then
207             echo "LNET modules $MODULES will not unload"
208         lsmod
209             return 3
210         fi
211     done
212 }
213
214 unload_modules() {
215     wait_exit_ST client # bug 12845
216
217     lsmod | grep lnet > /dev/null && $LCTL dl && $LCTL dk $TMP/debug
218     local MODULES=$($LCTL modules | awk '{ print $2 }')
219     $RMMOD $MODULES > /dev/null 2>&1 || true
220      # do it again, in case we tried to unload ksocklnd too early
221     MODULES=$($LCTL modules | awk '{ print $2 }')
222     [ -n "$MODULES" ] && $RMMOD $MODULES > /dev/null 2>&1 || true
223     MODULES=$($LCTL modules | awk '{ print $2 }')
224     if [ -n "$MODULES" ]; then
225     echo "Modules still loaded: "
226     echo $MODULES 
227     if [ -e $LPROC ]; then
228         echo "Lustre still loaded"
229         cat $LPROC/devices || true
230         lsmod
231         return 2
232     else
233         echo "Lustre stopped but LNET is still loaded, waiting..."
234         wait_for_lnet || return 3
235     fi
236     fi
237
238     LEAK_LUSTRE=$(dmesg | tail -n 30 | grep "obd mem.*leaked" || true)
239     LEAK_PORTALS=$(dmesg | tail -n 20 | grep "Portals memory leaked" || true)
240     if [ "$LEAK_LUSTRE" -o "$LEAK_PORTALS" ]; then
241         echo "$LEAK_LUSTRE" 1>&2
242         echo "$LEAK_PORTALS" 1>&2
243         mv $TMP/debug $TMP/debug-leak.`date +%s` || true
244         echo "Memory leaks detected"
245         [ -n "$IGNORE_LEAK" ] && echo "ignoring leaks" && return 0
246         return 254
247     fi
248     echo "modules unloaded."
249     return 0
250 }
251
252 # Facet functions
253 # start facet device options 
254 start() {
255     facet=$1
256     shift
257     device=$1
258     shift
259     echo "Starting ${facet}: $@ ${device} ${MOUNT%/*}/${facet}"
260     do_facet ${facet} mkdir -p ${MOUNT%/*}/${facet}
261     do_facet ${facet} mount -t lustre $@ ${device} ${MOUNT%/*}/${facet} 
262     RC=${PIPESTATUS[0]}
263     if [ $RC -ne 0 ]; then
264         echo "mount -t lustre $@ ${device} ${MOUNT%/*}/${facet}" 
265         echo "Start of ${device} on ${facet} failed ${RC}"
266     else 
267         do_facet ${facet} "sysctl -w lnet.debug=$PTLDEBUG; \
268         sysctl -w lnet.subsystem_debug=${SUBSYSTEM# }; \
269         sysctl -w lnet.debug_mb=${DEBUG_SIZE}"
270
271         do_facet ${facet} sync
272         label=$(do_facet ${facet} "e2label ${device}")
273         [ -z "$label" ] && echo no label for ${device} && exit 1
274         eval export ${facet}_svc=${label}
275         eval export ${facet}_dev=${device}
276         eval export ${facet}_opt=\"$@\"
277         echo Started ${label}
278     fi
279     return $RC
280 }
281
282 stop() {
283     local running
284     facet=$1
285     shift
286     HOST=`facet_active_host $facet`
287     [ -z $HOST ] && echo stop: no host for $facet && return 0
288
289     running=$(do_facet ${facet} "grep -c ${MOUNT%/*}/${facet}' ' /proc/mounts") || true
290     if [ ${running} -ne 0 ]; then
291         echo "Stopping ${MOUNT%/*}/${facet} (opts:$@)"
292         do_facet ${facet} umount -d $@ ${MOUNT%/*}/${facet}
293     fi
294
295     # umount should block, but we should wait for unrelated obd's
296     # like the MGS or MGC to also stop.
297
298     wait_exit_ST ${facet}
299 }
300
301 zconf_mount() {
302     local OPTIONS
303     local client=$1
304     local mnt=$2
305     # Only supply -o to mount if we have options
306     if [ -n "$MOUNTOPT" ]; then
307         OPTIONS="-o $MOUNTOPT"
308     fi
309     local device=$MGSNID:/$FSNAME
310     if [ -z "$mnt" -o -z "$FSNAME" ]; then
311         echo Bad zconf mount command: opt=$OPTIONS dev=$device mnt=$mnt
312         exit 1
313     fi
314
315     echo "Starting client: $OPTIONS $device $mnt" 
316     do_node $client mkdir -p $mnt
317     do_node $client mount -t lustre $OPTIONS $device $mnt || return 1
318
319     do_node $client "sysctl -w lnet.debug=$PTLDEBUG;
320         sysctl -w lnet.subsystem_debug=${SUBSYSTEM# };
321         sysctl -w lnet.debug_mb=${DEBUG_SIZE}"
322     [ -d /r ] && $LCTL modules > /r/tmp/ogdb-`hostname`
323     return 0
324 }
325
326 zconf_umount() {
327     client=$1
328     mnt=$2
329     [ "$3" ] && force=-f
330     local running=$(do_node $client "grep -c $mnt' ' /proc/mounts") || true
331     if [ $running -ne 0 ]; then
332         echo "Stopping client $mnt (opts:$force)"
333         do_node $client umount $force $mnt
334     fi
335 }
336
337 shutdown_facet() {
338     facet=$1
339     if [ "$FAILURE_MODE" = HARD ]; then
340         $POWER_DOWN `facet_active_host $facet`
341         sleep 2 
342     elif [ "$FAILURE_MODE" = SOFT ]; then
343         stop $facet
344     fi
345 }
346
347 reboot_facet() {
348     facet=$1
349     if [ "$FAILURE_MODE" = HARD ]; then
350         $POWER_UP `facet_active_host $facet`
351     else
352         sleep 10
353     fi
354 }
355
356 # verify that lustre actually cleaned up properly
357 cleanup_check() {
358     [ -f $CATASTROPHE ] && [ `cat $CATASTROPHE` -ne 0 ] && \
359         error "LBUG/LASSERT detected"
360     BUSY=`dmesg | grep -i destruct || true`
361     if [ "$BUSY" ]; then
362         echo "$BUSY" 1>&2
363         [ -e $TMP/debug ] && mv $TMP/debug $TMP/debug-busy.`date +%s`
364         exit 205
365     fi
366     LEAK_LUSTRE=`dmesg | tail -n 30 | grep "obd mem.*leaked" || true`
367     LEAK_PORTALS=`dmesg | tail -n 20 | grep "Portals memory leaked" || true`
368     if [ "$LEAK_LUSTRE" -o "$LEAK_PORTALS" ]; then
369         echo "$0: $LEAK_LUSTRE" 1>&2
370         echo "$0: $LEAK_PORTALS" 1>&2
371         echo "$0: Memory leak(s) detected..." 1>&2
372         mv $TMP/debug $TMP/debug-leak.`date +%s`
373         exit 204
374     fi
375
376     [ "`lctl dl 2> /dev/null | wc -l`" -gt 0 ] && lctl dl && \
377         echo "$0: lustre didn't clean up..." 1>&2 && return 202 || true
378
379     if [ "`/sbin/lsmod 2>&1 | egrep 'lnet|libcfs'`" ]; then
380         echo "$0: modules still loaded..." 1>&2
381         /sbin/lsmod 1>&2
382         return 203
383     fi
384     return 0
385 }
386
387 wait_delete_completed () {
388     local TOTALPREV=`awk 'BEGIN{total=0}; {total+=$1}; END{print total}' \
389             $LPROC/osc/*/kbytesavail`
390
391     local WAIT=0
392     local MAX_WAIT=20
393     while [ "$WAIT" -ne "$MAX_WAIT" ]; do
394         sleep 1
395         TOTAL=`awk 'BEGIN{total=0}; {total+=$1}; END{print total}' \
396             $LPROC/osc/*/kbytesavail`
397         [ "$TOTAL" -eq "$TOTALPREV" ] && break
398         echo "Waiting delete completed ... prev: $TOTALPREV current: $TOTAL "
399         TOTALPREV=$TOTAL
400         WAIT=$(( WAIT + 1))
401     done
402     echo "Delete completed."
403 }
404
405 wait_for_host() {
406     HOST=$1
407     check_network "$HOST" 900
408     while ! do_node $HOST "ls -d $LUSTRE " > /dev/null; do sleep 5; done
409 }
410
411 wait_for() {
412     facet=$1
413     HOST=`facet_active_host $facet`
414     wait_for_host $HOST
415 }
416
417 wait_mds_recovery_done () {
418     local timeout=`do_facet mds cat /proc/sys/lustre/timeout`
419 #define OBD_RECOVERY_TIMEOUT (obd_timeout * 5 / 2)
420 # as we are in process of changing obd_timeout in different ways
421 # let's set MAX longer than that
422     MAX=$(( timeout * 4 ))
423     WAIT=0
424     while [ $WAIT -lt $MAX ]; do
425         STATUS=`do_facet mds grep status /proc/fs/lustre/mds/*-MDT*/recovery_status`
426         echo $STATUS | grep COMPLETE && return 0
427         sleep 5
428         WAIT=$((WAIT + 5))
429         echo "Waiting $(($MAX - $WAIT)) secs for MDS recovery done"
430     done
431     echo "MDS recovery not done in $MAX sec"
432     return 1            
433 }
434
435 wait_exit_ST () {
436     local facet=$1
437
438     local WAIT=0
439     local INTERVAL=1
440     # conf-sanity 31 takes a long time cleanup
441     while [ $WAIT -lt 300 ]; do
442         running=$(do_facet ${facet} "[ -e $LPROC ] && grep ST' ' $LPROC/devices") || true
443         [ -z "${running}" ] && return 0
444         echo "waited $WAIT for${running}"
445         [ $INTERVAL -lt 64 ] && INTERVAL=$((INTERVAL + INTERVAL))
446         sleep $INTERVAL
447         WAIT=$((WAIT + INTERVAL))
448     done
449     echo "service didn't stop after $WAIT seconds.  Still running:"
450     echo ${running}
451     return 1
452 }
453
454 client_df() {
455     # not every config has many clients
456     if [ -n "$CLIENTS" ]; then
457         $PDSH $CLIENTS "df $MOUNT" > /dev/null
458     else
459         df $MOUNT > /dev/null
460     fi
461 }
462
463 client_reconnect() {
464     uname -n >> $MOUNT/recon
465     if [ ! -z "$CLIENTS" ]; then
466         $PDSH $CLIENTS "df $MOUNT; uname -n >> $MOUNT/recon" > /dev/null
467     fi
468     echo Connected clients:
469     cat $MOUNT/recon
470     ls -l $MOUNT/recon > /dev/null
471     rm $MOUNT/recon
472 }
473
474 facet_failover() {
475     facet=$1
476     echo "Failing $facet on node `facet_active_host $facet`"
477     shutdown_facet $facet
478     reboot_facet $facet
479     client_df &
480     DFPID=$!
481     echo "df pid is $DFPID"
482     change_active $facet
483     TO=`facet_active_host $facet`
484     echo "Failover $facet to $TO"
485     wait_for $facet
486     local dev=${facet}_dev
487     local opt=${facet}_opt
488     start $facet ${!dev} ${!opt} || error "Restart of $facet failed"
489 }
490
491 obd_name() {
492     local facet=$1
493 }
494
495 replay_barrier() {
496     local facet=$1
497     do_facet $facet sync
498     df $MOUNT
499     local svc=${facet}_svc
500     do_facet $facet $LCTL --device %${!svc} readonly
501     do_facet $facet $LCTL --device %${!svc} notransno
502     do_facet $facet $LCTL mark "$facet REPLAY BARRIER on ${!svc}"
503     $LCTL mark "local REPLAY BARRIER on ${!svc}"
504 }
505
506 replay_barrier_nodf() {
507     local facet=$1    echo running=${running}
508     do_facet $facet sync
509     local svc=${facet}_svc
510     echo Replay barrier on ${!svc}
511     do_facet $facet $LCTL --device %${!svc} readonly
512     do_facet $facet $LCTL --device %${!svc} notransno
513     do_facet $facet $LCTL mark "$facet REPLAY BARRIER on ${!svc}"
514     $LCTL mark "local REPLAY BARRIER on ${!svc}"
515 }
516
517 mds_evict_client() {
518     UUID=`cat /proc/fs/lustre/mdc/${mds_svc}-mdc-*/uuid`
519     do_facet mds "echo $UUID > /proc/fs/lustre/mds/${mds_svc}/evict_client"
520 }
521
522 ost_evict_client() {
523     UUID=`cat /proc/fs/lustre/osc/${ost1_svc}-osc-*/uuid`
524     do_facet ost1 "echo $UUID > /proc/fs/lustre/obdfilter/${ost1_svc}/evict_client"
525 }
526
527 fail() {
528     facet_failover $* || error "failover: $?"
529     df $MOUNT || error "post-failover df: $?"
530 }
531
532 fail_nodf() {
533     local facet=$1
534     facet_failover $facet
535 }
536
537 fail_abort() {
538     local facet=$1
539     stop $facet
540     change_active $facet
541     local svc=${facet}_svc
542     local dev=${facet}_dev
543     local opt=${facet}_opt
544     start $facet ${!dev} ${!opt}
545     do_facet $facet lctl --device %${!svc} abort_recovery
546     df $MOUNT || echo "first df failed: $?"
547     sleep 1
548     df $MOUNT || error "post-failover df: $?"
549 }
550
551 do_lmc() {
552     echo There is no lmc.  This is mountconf, baby.
553     exit 1
554 }
555
556 h2gm () {
557     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
558         ID=`$PDSH $1 $GMNALNID -l | cut -d\  -f2`
559         echo $ID"@gm"
560     fi
561 }
562
563 h2ptl() {
564    if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
565        ID=`xtprocadmin -n $1 2>/dev/null | egrep -v 'NID' | awk '{print $1}'`
566        if [ -z "$ID" ]; then
567            echo "Could not get a ptl id for $1..."
568            exit 1
569        fi
570        echo $ID"@ptl"
571    fi
572 }
573 declare -fx h2ptl
574
575 h2tcp() {
576     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
577         echo $1"@tcp" 
578     fi
579 }
580 declare -fx h2tcp
581
582 h2elan() {
583     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
584         if type __h2elan >/dev/null 2>&1; then
585             ID=$(__h2elan $1)
586         else
587             ID=`echo $1 | sed 's/[^0-9]*//g'`
588         fi
589         echo $ID"@elan"
590     fi
591 }
592 declare -fx h2elan
593
594 h2openib() {
595     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
596         ID=`echo $1 | sed 's/[^0-9]*//g'`
597         echo $ID"@openib"
598     fi
599 }
600 declare -fx h2openib
601
602 facet_host() {
603     local facet=$1
604     varname=${facet}_HOST
605     if [ -z "${!varname}" ]; then
606         if [ "${facet:0:3}" == "ost" ]; then
607             eval ${facet}_HOST=${ost_HOST}
608         fi
609     fi
610     echo -n ${!varname}
611 }
612
613 facet_active() {
614     local facet=$1
615     local activevar=${facet}active
616
617     if [ -f ./${facet}active ] ; then
618         source ./${facet}active
619     fi
620
621     active=${!activevar}
622     if [ -z "$active" ] ; then 
623         echo -n ${facet}
624     else
625         echo -n ${active}
626     fi
627 }
628
629 facet_active_host() {
630     local facet=$1
631     local active=`facet_active $facet`
632     if [ "$facet" == client ]; then
633         hostname
634     else
635         echo `facet_host $active`
636     fi
637 }
638
639 change_active() {
640     local facet=$1
641     failover=${facet}failover 
642     host=`facet_host $failover`
643     [ -z "$host" ] && return
644     curactive=`facet_active $facet`
645     if [ -z "${curactive}" -o "$curactive" == "$failover" ] ; then
646         eval export ${facet}active=$facet
647     else
648         eval export ${facet}active=$failover
649     fi
650     # save the active host for this facet
651     activevar=${facet}active
652     echo "$activevar=${!activevar}" > ./$activevar
653 }
654
655 do_node() {
656     HOST=$1
657     shift
658     local myPDSH=$PDSH
659     if [ "$HOST" = "$(hostname)" ]; then
660         myPDSH="no_dsh"
661     fi
662     if $VERBOSE; then
663         echo "CMD: $HOST $@" >&2
664         $myPDSH $HOST $LCTL mark "$@" > /dev/null 2>&1 || :
665     fi
666     $myPDSH $HOST "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin; cd $RPWD; sh -c \"$@\")" | sed "s/^${HOST}: //"
667     return ${PIPESTATUS[0]}
668 }
669
670 do_facet() {
671     facet=$1
672     shift
673     HOST=`facet_active_host $facet`
674     [ -z $HOST ] && echo No host defined for facet ${facet} && exit 1
675     do_node $HOST "$@"
676 }
677
678 add() {
679     local facet=$1
680     shift
681     # make sure its not already running
682     stop ${facet} -f
683     rm -f ${facet}active
684     do_facet ${facet} $MKFS $*
685 }
686
687 ostdevname() {
688     num=$1
689     DEVNAME=OSTDEV$num
690     #if $OSTDEVn isn't defined, default is $OSTDEVBASE + num
691     eval DEVPTR=${!DEVNAME:=${OSTDEVBASE}${num}}
692     echo -n $DEVPTR
693 }
694
695 ########
696 ## MountConf setup
697
698 stopall() {
699     # make sure we are using the primary server, so test-framework will
700     # be able to clean up properly.
701     activemds=`facet_active mds`
702     if [ $activemds != "mds" ]; then
703         fail mds
704     fi
705     
706     # assume client mount is local 
707     grep " $MOUNT " /proc/mounts && zconf_umount `hostname` $MOUNT $*
708     grep " $MOUNT2 " /proc/mounts && zconf_umount `hostname` $MOUNT2 $*
709     [ "$CLIENTONLY" ] && return
710     stop mds -f
711     for num in `seq $OSTCOUNT`; do
712         stop ost$num -f
713     done
714     return 0
715 }
716
717 cleanupall() {
718     stopall $*
719     unload_modules
720 }
721
722 formatall() {
723     [ "$FSTYPE" ] && FSTYPE_OPT="--backfstype $FSTYPE"
724
725     stopall
726     # We need ldiskfs here, may as well load them all
727     load_modules
728     [ "$CLIENTONLY" ] && return
729     echo Formatting mds, osts
730     if $VERBOSE; then
731         add mds $MDS_MKFS_OPTS $FSTYPE_OPT --reformat $MDSDEV || exit 10
732     else
733         add mds $MDS_MKFS_OPTS $FSTYPE_OPT --reformat $MDSDEV > /dev/null || exit 10
734     fi
735
736     for num in `seq $OSTCOUNT`; do
737         if $VERBOSE; then
738             add ost$num $OST_MKFS_OPTS $FSTYPE_OPT --reformat `ostdevname $num` || exit 10
739         else
740             add ost$num $OST_MKFS_OPTS $FSTYPE_OPT --reformat `ostdevname $num` > /dev/null || exit 10
741         fi
742     done
743 }
744
745 mount_client() {
746     grep " $1 " /proc/mounts || zconf_mount `hostname` $*
747 }
748
749 setupall() {
750     load_modules
751     if [ -z "$CLIENTONLY" ]; then
752         echo Setup mdt, osts
753         echo $REFORMAT | grep -q "reformat" \
754             || do_facet mds "$TUNEFS --writeconf $MDSDEV"
755         start mds $MDSDEV $MDS_MOUNT_OPTS
756         for num in `seq $OSTCOUNT`; do
757             DEVNAME=`ostdevname $num`
758             start ost$num $DEVNAME $OST_MOUNT_OPTS
759         done
760     fi
761     [ "$DAEMONFILE" ] && $LCTL debug_daemon start $DAEMONFILE $DAEMONSIZE
762     mount_client $MOUNT
763     if [ "$MOUNT_2" ]; then
764         mount_client $MOUNT2
765     fi
766     sleep 5
767 }
768
769 mounted_lustre_filesystems() {
770         awk '($3 ~ "lustre" && $1 ~ ":") { print $2 }' /proc/mounts
771 }
772
773 check_and_setup_lustre() {
774     MOUNTED="`mounted_lustre_filesystems`"
775     if [ -z "$MOUNTED" ]; then
776         [ "$REFORMAT" ] && formatall
777         setupall
778         MOUNTED="`mounted_lustre_filesystems`"
779         [ -z "$MOUNTED" ] && error "NAME=$NAME not mounted"
780         export I_MOUNTED=yes
781     fi
782     if [ "$ONLY" == "setup" ]; then
783         exit 0
784     fi
785 }
786
787 cleanup_and_setup_lustre() {
788     if [ "$ONLY" == "cleanup" -o "`mount | grep $MOUNT`" ]; then
789         sysctl -w lnet.debug=0 || true
790         cleanupall
791         if [ "$ONLY" == "cleanup" ]; then 
792             exit 0
793         fi
794     fi
795     check_and_setup_lustre
796 }
797
798 check_and_cleanup_lustre() {
799     if [ "`mount | grep $MOUNT`" ]; then
800         rm -f $DIR/${TESTSUITE}/[Rdfs][0-9]*
801     fi
802     if [ "$I_MOUNTED" = "yes" ]; then
803         cleanupall -f || error "cleanup failed"
804     fi
805     unset I_MOUNTED
806 }
807
808 ####### 
809 # General functions
810
811 check_network() {
812     local NETWORK=0
813     local WAIT=0
814     local MAX=$2
815     while [ $NETWORK -eq 0 ]; do
816         ping -c 1 -w 3 $1 > /dev/null
817         if [ $? -eq 0 ]; then
818             NETWORK=1
819         else
820             WAIT=$((WAIT + 5))
821             echo "waiting for $1, $((MAX - WAIT)) secs left"
822             sleep 5
823         fi
824         if [ $WAIT -gt $MAX ]; then
825             echo "Network not available"
826             exit 1
827         fi
828     done
829 }
830 check_port() {
831     while( !($DSH2 $1 "netstat -tna | grep -q $2") ) ; do
832         sleep 9
833     done
834 }
835
836 no_dsh() {
837     shift
838     eval $@
839 }
840
841 comma_list() {
842     # the sed converts spaces to commas, but leaves the last space
843     # alone, so the line doesn't end with a comma.
844     echo "$*" | tr -s " " "\n" | sort -b -u | tr "\n" " " | sed 's/ \([^$]\)/,\1/g'
845 }
846
847 absolute_path() {
848     (cd `dirname $1`; echo $PWD/`basename $1`)
849 }
850
851 ##################################
852 # OBD_FAIL funcs
853
854 drop_request() {
855 # OBD_FAIL_MDS_ALL_REQUEST_NET
856     RC=0
857     do_facet mds sysctl -w lustre.fail_loc=0x123
858     do_facet client "$1" || RC=$?
859     do_facet mds sysctl -w lustre.fail_loc=0
860     return $RC
861 }
862
863 drop_reply() {
864 # OBD_FAIL_MDS_ALL_REPLY_NET
865     RC=0
866     do_facet mds sysctl -w lustre.fail_loc=0x122
867     do_facet client "$@" || RC=$?
868     do_facet mds sysctl -w lustre.fail_loc=0
869     return $RC
870 }
871
872 drop_reint_reply() {
873 # OBD_FAIL_MDS_REINT_NET_REP
874     RC=0
875     do_facet mds sysctl -w lustre.fail_loc=0x119
876     do_facet client "$@" || RC=$?
877     do_facet mds sysctl -w lustre.fail_loc=0
878     return $RC
879 }
880
881 pause_bulk() {
882 #define OBD_FAIL_OST_BRW_PAUSE_BULK      0x214
883     RC=0
884     do_facet ost1 sysctl -w lustre.fail_loc=0x214
885     do_facet client "$1" || RC=$?
886     do_facet client "sync"
887     do_facet ost1 sysctl -w lustre.fail_loc=0
888     return $RC
889 }
890
891 drop_ldlm_cancel() {
892 #define OBD_FAIL_LDLM_CANCEL             0x304
893     RC=0
894     do_facet client sysctl -w lustre.fail_loc=0x304
895     do_facet client "$@" || RC=$?
896     do_facet client sysctl -w lustre.fail_loc=0
897     return $RC
898 }
899
900 drop_bl_callback() {
901 #define OBD_FAIL_LDLM_BL_CALLBACK        0x305
902     RC=0
903     do_facet client sysctl -w lustre.fail_loc=0x305
904     do_facet client "$@" || RC=$?
905     do_facet client sysctl -w lustre.fail_loc=0
906     return $RC
907 }
908
909 drop_ldlm_reply() {
910 #define OBD_FAIL_LDLM_REPLY              0x30c
911     RC=0
912     do_facet mds sysctl -w lustre.fail_loc=0x30c
913     do_facet client "$@" || RC=$?
914     do_facet mds sysctl -w lustre.fail_loc=0
915     return $RC
916 }
917
918 clear_failloc() {
919     facet=$1
920     pause=$2
921     sleep $pause
922     echo "clearing fail_loc on $facet"
923     do_facet $facet "sysctl -w lustre.fail_loc=0"
924 }
925
926 cancel_lru_locks() {
927     $LCTL mark "cancel_lru_locks $1 start"
928     for d in `find $LPROC/ldlm/namespaces | egrep -i $1`; do
929         [ -f $d/lru_size ] && echo clear > $d/lru_size
930         [ -f $d/lock_unused_count ] && grep [1-9] $d/lock_unused_count /dev/null
931     done
932     $LCTL mark "cancel_lru_locks $1 stop"
933 }
934
935
936 pgcache_empty() {
937     for a in /proc/fs/lustre/llite/*/dump_page_cache; do
938         if [ `wc -l $a | awk '{print $1}'` -gt 1 ]; then
939             echo there is still data in page cache $a ?
940             cat $a;
941             return 1;
942         fi
943     done
944     return 0
945 }
946
947 debugsave() {
948     DEBUGSAVE="$(sysctl -n lnet.debug)"
949 }
950
951 debugrestore() {
952     [ -n "$DEBUGSAVE" ] && sysctl -w lnet.debug="${DEBUGSAVE}"
953     DEBUGSAVE=""
954 }
955
956 ##################################
957 # Test interface 
958 ##################################
959
960 error() {
961     local FAIL_ON_ERROR=${FAIL_ON_ERROR:-true}
962     local TYPE=${TYPE:-"FAIL"}
963     local ERRLOG
964     sysctl -w lustre.fail_loc=0 2> /dev/null || true
965     log " ${TESTSUITE} ${TESTNAME}: @@@@@@ ${TYPE}: $@ "
966     ERRLOG=$TMP/lustre_${TESTSUITE}_${TESTNAME}.$(date +%s)
967     echo "Dumping lctl log to $ERRLOG"
968     # We need to dump the logs on all nodes
969     local NODES=$(nodes_list)
970     for NODE in $NODES; do
971         do_node $NODE $LCTL dk $ERRLOG
972     done
973     debugrestore
974     [ "$TESTSUITELOG" ] && echo "$0: ${TYPE}: $TESTNAME $@" >> $TESTSUITELOG
975     if $FAIL_ON_ERROR; then
976         exit 1
977     fi
978 }
979
980 # use only if we are ignoring failures for this test, bugno required.
981 # (like ALWAYS_EXCEPT, but run the test and ignore the results.)
982 # e.g. error_ignore 5494 "your message"
983 error_ignore() {
984     FAIL_ON_ERROR=false TYPE="IGNORE (bz$1)" error $2
985 }
986
987 skip () {
988         log " SKIP: ${TESTSUITE} ${TESTNAME} $@"
989         [ "$TESTSUITELOG" ] && echo "${TESTSUITE}: SKIP: $TESTNAME $@" >> $TESTSUITELOG
990 }
991
992 build_test_filter() {
993     [ "$ONLY" ] && log "only running test `echo $ONLY`"
994     for O in $ONLY; do
995         eval ONLY_${O}=true
996     done
997     [ "$EXCEPT$ALWAYS_EXCEPT" ] && \
998         log "skipping tests: `echo $EXCEPT $ALWAYS_EXCEPT`"
999     [ "$EXCEPT_SLOW" ] && \
1000         log "skipping tests SLOW=no: `echo $EXCEPT_SLOW`"
1001     for E in $EXCEPT $ALWAYS_EXCEPT; do
1002         eval EXCEPT_${E}=true
1003     done
1004     for E in $EXCEPT_SLOW; do
1005         eval EXCEPT_SLOW_${E}=true
1006     done
1007     for G in $GRANT_CHECK_LIST; do
1008         eval GCHECK_ONLY_${G}=true
1009         done
1010 }
1011
1012 _basetest() {
1013     echo $*
1014 }
1015
1016 basetest() {
1017     IFS=abcdefghijklmnopqrstuvwxyz _basetest $1
1018 }
1019
1020 run_test() {
1021     export base=`basetest $1`
1022     if [ ! -z "$ONLY" ]; then
1023         testname=ONLY_$1
1024         if [ ${!testname}x != x ]; then
1025             run_one $1 "$2"
1026             return $?
1027         fi
1028         testname=ONLY_$base
1029         if [ ${!testname}x != x ]; then
1030             run_one $1 "$2"
1031             return $?
1032         fi
1033         echo -n "."
1034         return 0
1035     fi
1036     testname=EXCEPT_$1
1037     if [ ${!testname}x != x ]; then
1038         TESTNAME=test_$1 skip "skipping excluded test $1"
1039         return 0
1040     fi
1041     testname=EXCEPT_$base
1042     if [ ${!testname}x != x ]; then
1043         TESTNAME=test_$1 skip "skipping excluded test $1 (base $base)"
1044         return 0
1045     fi
1046     testname=EXCEPT_SLOW_$1
1047     if [ ${!testname}x != x ]; then
1048         TESTNAME=test_$1 skip "skipping SLOW test $1"
1049         return 0
1050     fi
1051     testname=EXCEPT_SLOW_$base
1052     if [ ${!testname}x != x ]; then
1053         TESTNAME=test_$1 skip "skipping SLOW test $1 (base $base)"
1054         return 0
1055     fi
1056
1057     run_one $1 "$2"
1058     
1059     return $?
1060 }
1061
1062 EQUALS="======================================================================"
1063 equals_msg() {
1064     msg="$@"
1065
1066     local suffixlen=$((${#EQUALS} - ${#msg}))
1067     [ $suffixlen -lt 5 ] && suffixlen=5
1068     log `echo $(printf '===== %s %.*s\n' "$msg" $suffixlen $EQUALS)`
1069 }
1070
1071 log() {
1072     echo "$*"
1073
1074     local HAVE_MODULES=""
1075     lsmod | grep lnet > /dev/null || { load_modules && HAVE_MODULES="yes"; }
1076
1077     local MSG="$*"
1078     # Get rif of '
1079     MSG=${MSG//\'/\\\'}
1080     MSG=${MSG//\(/\\\(}
1081     MSG=${MSG//\)/\\\)}
1082     MSG=${MSG//\;/\\\;}
1083     MSG=${MSG//\|/\\\|}
1084     MSG=${MSG//\>/\\\>}
1085     MSG=${MSG//\</\\\<}
1086     local NODES=$(nodes_list)
1087     for NODE in $NODES; do
1088         do_node $NODE $LCTL mark "$MSG" 2> /dev/null || true
1089     done
1090
1091     [ -z "$HAVE_MODULES" ] || unload_modules
1092 }
1093
1094 trace() {
1095         log "STARTING: $*"
1096         strace -o $TMP/$1.strace -ttt $*
1097         RC=$?
1098         log "FINISHED: $*: rc $RC"
1099         return 1
1100 }
1101
1102 pass() {
1103     echo PASS $@
1104 }
1105
1106 check_mds() {
1107     FFREE=`cat /proc/fs/lustre/mds/*/filesfree`
1108     FTOTAL=`cat /proc/fs/lustre/mds/*/filestotal`
1109     [ $FFREE -ge $FTOTAL ] && error "files free $FFREE > total $FTOTAL" || true
1110 }
1111
1112 reset_fail_loc () {
1113     local myNODES=$(nodes_list)
1114     local NODE
1115
1116     for NODE in $myNODES; do
1117         do_node $NODE sysctl -w lustre.fail_loc=0 || true
1118     done
1119 }
1120
1121 run_one() {
1122     testnum=$1
1123     message=$2
1124     tfile=f${testnum}
1125     export tdir=d${TESTSUITE}/d${base}
1126     local SAVE_UMASK=`umask`
1127     umask 0022
1128     mkdir -p $DIR/$tdir
1129
1130     BEFORE=`date +%s`
1131     log "== test $testnum: $message ============ `date +%H:%M:%S` ($BEFORE)"
1132     #check_mds
1133     export TESTNAME=test_$testnum
1134     test_${testnum} || error "test_$testnum failed with $?"
1135     #check_mds
1136     reset_fail_loc
1137     check_grant ${testnum} || error "check_grant $testnum failed with $?"
1138     [ -f $CATASTROPHE ] && [ `cat $CATASTROPHE` -ne 0 ] && \
1139         error "LBUG/LASSERT detected"
1140     pass "($((`date +%s` - $BEFORE))s)"
1141     rmdir ${DIR}/$tdir >/dev/null 2>&1 || true
1142     unset TESTNAME
1143     unset tdir
1144     umask $SAVE_UMASK
1145     cd $SAVE_PWD
1146     $CLEANUP
1147 }
1148
1149 canonical_path() {
1150     (cd `dirname $1`; echo $PWD/`basename $1`)
1151 }
1152
1153 sync_clients() {
1154     [ -d $DIR1 ] && cd $DIR1 && sync; sleep 1; sync 
1155     [ -d $DIR2 ] && cd $DIR2 && sync; sleep 1; sync 
1156         cd $SAVE_PWD
1157 }
1158
1159 check_grant() {
1160     export base=`basetest $1`
1161     [ "$CHECK_GRANT" == "no" ] && return 0
1162
1163         testname=GCHECK_ONLY_${base}
1164         [ ${!testname}x == x ] && return 0
1165
1166         echo -n "checking grant......"
1167         cd $SAVE_PWD
1168         # write some data to sync client lost_grant
1169         rm -f $DIR1/${tfile}_check_grant_* 2>&1
1170         for i in `seq $OSTCOUNT`; do
1171                 $LFS setstripe $DIR1/${tfile}_check_grant_$i -i $(($i -1)) -c 1
1172                 dd if=/dev/zero of=$DIR1/${tfile}_check_grant_$i bs=4k \
1173                                               count=1 > /dev/null 2>&1 
1174         done
1175         # sync all the data and make sure no pending data on server
1176         sync_clients
1177         
1178         #get client grant and server grant 
1179         client_grant=0
1180     for d in ${LPROC}/osc/*/cur_grant_bytes; do 
1181                 client_grant=$((client_grant + `cat $d`))
1182         done
1183         server_grant=0
1184         for d in ${LPROC}/obdfilter/*/tot_granted; do
1185                 server_grant=$((server_grant + `cat $d`))
1186         done
1187
1188         # cleanup the check_grant file
1189         for i in `seq $OSTCOUNT`; do
1190                 rm $DIR1/${tfile}_check_grant_$i
1191         done
1192
1193         #check whether client grant == server grant 
1194         if [ $client_grant != $server_grant ]; then
1195                 echo "failed: client:${client_grant} server: ${server_grant}"
1196                 return 1
1197         else
1198                 echo "pass"
1199         fi
1200 }
1201
1202 ########################
1203 # helper functions
1204
1205 osc_to_ost()
1206 {
1207     osc=$1
1208     ost=`echo $1 | awk -F_ '{print $3}'`
1209     if [ -z $ost ]; then
1210         ost=`echo $1 | sed 's/-osc.*//'`
1211     fi
1212     echo $ost
1213 }
1214
1215 remote_mds ()
1216 {
1217     [ ! -e /proc/fs/lustre/mds/*MDT* ]
1218 }
1219
1220 remote_ost ()
1221 {
1222     [ $(grep -c obdfilter $LPROC/devices) -eq 0 ]
1223 }
1224
1225 osts_nodes () {
1226     local OSTNODES=$(facet_host ost1)
1227     local NODES_sort
1228
1229     for num in `seq $OSTCOUNT`; do
1230         local myOST=$(facet_host ost$num)
1231         OSTNODES="$OSTNODES $myOST"
1232     done
1233     NODES_sort=$(for i in $OSTNODES; do echo $i; done | sort -u)
1234
1235     echo $NODES_sort
1236 }
1237
1238 nodes_list () {
1239     # FIXME. We need a list of clients
1240     local myNODES=`hostname`
1241     local myNODES_sort
1242
1243     myNODES="$myNODES $(osts_nodes) $mds_HOST"
1244     myNODES_sort=$(for i in $myNODES; do echo $i; done | sort -u)
1245
1246     echo $myNODES_sort
1247 }
1248
1249 is_patchless ()
1250 {
1251     grep -q patchless $LPROC/version
1252 }
1253
1254 check_runas_id_ret() {
1255     RC=0
1256     local myRUNAS_ID=$1
1257     shift
1258     local myRUNAS=$@
1259     if [ -z "$myRUNAS" ]; then
1260         FAIL_ON_ERROR="true"
1261         error "myRUNAS command must be specified for check_runas_id"
1262     fi
1263     mkdir $DIR/d0_runas_test
1264     chmod 0755 $DIR
1265     chown $myRUNAS_ID:$myRUNAS_ID $DIR/d0_runas_test
1266     $myRUNAS touch $DIR/d0_runas_test/f$$ || RC=1
1267     rm -rf $DIR/d0_runas_test
1268     return $RC
1269 }
1270
1271 check_runas_id() {
1272     local myRUNAS_ID=$1
1273     shift
1274     local myRUNAS=$@
1275     check_runas_id_ret $myRUNAS_ID $myRUNAS || \
1276         error "unable to write to $DIR/d0_runas_test as UID $myRUNAS_ID. 
1277         Please set RUNAS_ID to some UID which exists on MDS and client or 
1278         add user $myRUNAS_ID:$myRUNAS_ID on these nodes."
1279 }