Whamcloud - gitweb
b=12499
[fs/lustre-release.git] / lustre / tests / test-framework.sh
1 #!/bin/bash
2 # vim:expandtab:shiftwidth=4:softtabstop=4:tabstop=4:
3
4 trap '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 init_test_env() {
35     export LUSTRE=`absolute_path $LUSTRE`
36     export TESTSUITE=`basename $0 .sh`
37     export LTESTDIR=${LTESTDIR:-$LUSTRE/../ltest}
38
39     [ -d /r ] && export ROOT=${ROOT:-/r}
40     export TMP=${TMP:-$ROOT/tmp}
41
42     export PATH=:$PATH:$LUSTRE/utils:$LUSTRE/tests
43     export LCTL=${LCTL:-"$LUSTRE/utils/lctl"}
44     [ ! -f "$LCTL" ] && export LCTL=$(which lctl) 
45     export LFS=${LFS:-"$LUSTRE/utils/lfs"}
46     [ ! -f "$LFS" ] && export LFS=$(which lfs) 
47     export MKFS=${MKFS:-"$LUSTRE/utils/mkfs.lustre"}
48     [ ! -f "$MKFS" ] && export MKFS=$(which mkfs.lustre) 
49     export TUNEFS=${TUNEFS:-"$LUSTRE/utils/tunefs.lustre"}
50     [ ! -f "$TUNEFS" ] && export TUNEFS=$(which tunefs.lustre) 
51     export CHECKSTAT="${CHECKSTAT:-checkstat} "
52     export NAME=${NAME:-local}
53     export LPROC=/proc/fs/lustre
54
55     if [ "$ACCEPTOR_PORT" ]; then
56         export PORT_OPT="--port $ACCEPTOR_PORT"
57     fi
58
59     # Paths on remote nodes, if different 
60     export RLUSTRE=${RLUSTRE:-$LUSTRE}
61     export RPWD=${RPWD:-$PWD}
62
63     # command line
64     
65     while getopts "rvf:" opt $*; do 
66         case $opt in
67             f) CONFIG=$OPTARG;;
68             r) REFORMAT=--reformat;;
69             v) VERBOSE=true;;
70             \?) usage;;
71         esac
72     done
73
74     shift $((OPTIND - 1))
75     ONLY=${ONLY:-$*}
76 }
77
78 case `uname -r` in
79 2.4.*) EXT=".o"; USE_QUOTA=no;;
80     *) EXT=".ko"; USE_QUOTA=yes;;
81 esac
82
83 load_module() {
84     module=$1
85     shift
86     BASE=`basename $module $EXT`
87     lsmod | grep -q ${BASE} || \
88       if [ -f ${LUSTRE}/${module}${EXT} ]; then
89         insmod ${LUSTRE}/${module}${EXT} $@
90     else
91         # must be testing a "make install" or "rpm" installation
92         modprobe $BASE $@
93     fi
94 }
95
96 load_modules() {
97     if [ -n "$MODPROBE" ]; then
98         # use modprobe
99     return 0
100     fi
101     if [ "$HAVE_MODULES" = true ]; then
102     # we already loaded
103         return 0
104     fi
105     HAVE_MODULES=true
106
107     echo Loading modules from $LUSTRE
108     load_module ../lnet/libcfs/libcfs
109     [ -z "$LNETOPTS" ] && \
110         LNETOPTS=$(awk '/^options lnet/ { print $0}' /etc/modprobe.conf | sed 's/^options lnet //g')
111     echo "lnet options: '$LNETOPTS'"
112     # note that insmod will ignore anything in modprobe.conf
113     load_module ../lnet/lnet/lnet $LNETOPTS
114     LNETLND=${LNETLND:-"socklnd/ksocklnd"}
115     load_module ../lnet/klnds/$LNETLND
116     load_module lvfs/lvfs
117     load_module obdclass/obdclass
118     load_module ptlrpc/ptlrpc
119     [ "$USE_QUOTA" = "yes" ] && load_module quota/lquota
120     load_module mdc/mdc
121     load_module osc/osc
122     load_module lov/lov
123     load_module mds/mds
124     [ "$FSTYPE" = "ldiskfs" ] && load_module ../ldiskfs/ldiskfs/ldiskfs
125     load_module lvfs/fsfilt_$FSTYPE
126     load_module ost/ost
127     load_module obdfilter/obdfilter
128     load_module llite/lustre
129     load_module mgc/mgc
130     load_module mgs/mgs
131     rm -f $TMP/ogdb-`hostname`
132     OGDB=$TMP
133     [ -d /r ] && OGDB="/r/tmp"
134     $LCTL modules > $OGDB/ogdb-`hostname`
135     # 'mount' doesn't look in $PATH, just sbin
136     [ -f $LUSTRE/utils/mount.lustre ] && cp $LUSTRE/utils/mount.lustre /sbin/. || true
137 }
138
139 RMMOD=rmmod
140 if [ `uname -r | cut -c 3` -eq 4 ]; then
141     RMMOD="modprobe -r"
142 fi
143
144 wait_for_lnet() {
145     local UNLOADED=0
146     local WAIT=0
147     local MAX=60
148     MODULES=$($LCTL modules | awk '{ print $2 }')
149     while [ -n "$MODULES" ]; do
150     sleep 5
151     $RMMOD $MODULES >/dev/null 2>&1 || true
152     MODULES=$($LCTL modules | awk '{ print $2 }')
153         if [ -z "$MODULES" ]; then
154         return 0
155         else
156             WAIT=$((WAIT + 5))
157             echo "waiting, $((MAX - WAIT)) secs left"
158         fi
159         if [ $WAIT -eq $MAX ]; then
160             echo "LNET modules $MODULES will not unload"
161         lsmod
162             return 3
163         fi
164     done
165 }
166
167 unload_modules() {
168     lsmod | grep lnet > /dev/null && $LCTL dl && $LCTL dk $TMP/debug
169     local MODULES=$($LCTL modules | awk '{ print $2 }')
170     $RMMOD $MODULES > /dev/null 2>&1 || true
171      # do it again, in case we tried to unload ksocklnd too early
172     MODULES=$($LCTL modules | awk '{ print $2 }')
173     [ -n "$MODULES" ] && $RMMOD $MODULES > /dev/null 2>&1 || true
174     MODULES=$($LCTL modules | awk '{ print $2 }')
175     if [ -n "$MODULES" ]; then
176     echo "Modules still loaded: "
177     echo $MODULES 
178     if [ -e $LPROC ]; then
179         echo "Lustre still loaded"
180         cat $LPROC/devices || true
181         lsmod
182         return 2
183     else
184         echo "Lustre stopped but LNET is still loaded, waiting..."
185         wait_for_lnet || return 3
186     fi
187     fi
188     HAVE_MODULES=false
189
190     LEAK_LUSTRE=$(dmesg | tail -n 30 | grep "obd mem.*leaked" || true)
191     LEAK_PORTALS=$(dmesg | tail -n 20 | grep "Portals memory leaked" || true)
192     if [ "$LEAK_LUSTRE" -o "$LEAK_PORTALS" ]; then
193         echo "$LEAK_LUSTRE" 1>&2
194         echo "$LEAK_PORTALS" 1>&2
195         mv $TMP/debug $TMP/debug-leak.`date +%s` || true
196         echo "Memory leaks detected"
197         [ -n "$IGNORE_LEAK" ] && echo "ignoring leaks" && return 0
198         return 254
199     fi
200     echo "modules unloaded."
201     return 0
202 }
203
204 # Facet functions
205 # start facet device options 
206 start() {
207     facet=$1
208     shift
209     device=$1
210     shift
211     echo "Starting ${facet}: $@ ${device} ${MOUNT%/*}/${facet}"
212     do_facet ${facet} mkdir -p ${MOUNT%/*}/${facet}
213     do_facet ${facet} mount -t lustre $@ ${device} ${MOUNT%/*}/${facet} 
214     RC=${PIPESTATUS[0]}
215     if [ $RC -ne 0 ]; then
216         echo mount -t lustre $@ ${device} ${MOUNT%/*}/${facet} 
217         echo Start of ${device} on ${facet} failed ${RC}
218     else 
219         do_facet ${facet} sync
220         label=$(do_facet ${facet} "e2label ${device}")
221         [ -z "$label" ] && echo no label for ${device} && exit 1
222         eval export ${facet}_svc=${label}
223         eval export ${facet}_dev=${device}
224         eval export ${facet}_opt=\"$@\"
225         echo Started ${label}
226     fi
227     return $RC
228 }
229
230 stop() {
231     local running
232     facet=$1
233     shift
234     HOST=`facet_active_host $facet`
235     [ -z $HOST ] && echo stop: no host for $facet && return 0
236
237     running=$(do_facet ${facet} "grep -c ${MOUNT%/*}/${facet}' ' /proc/mounts") || true
238     if [ ${running} -ne 0 ]; then
239         echo "Stopping ${MOUNT%/*}/${facet} (opts:$@)"
240         do_facet ${facet} umount -d $@ ${MOUNT%/*}/${facet}
241     fi
242
243     # umount should block, but we should wait for unrelated obd's
244     # like the MGS or MGC to also stop.
245     local WAIT=0
246     local INTERVAL=1
247     # conf-sanity 31 takes a long time cleanup
248     while [ $WAIT -lt 300 ]; do
249         running=$(do_facet ${facet} "[ -e $LPROC ] && grep ST' ' $LPROC/devices") || true
250         if [ -z "${running}" ]; then
251             return 0
252         fi
253         echo "waited $WAIT for${running}"
254         if [ $INTERVAL -lt 64 ]; then 
255             INTERVAL=$((INTERVAL + INTERVAL))
256         fi
257         sleep $INTERVAL
258         WAIT=$((WAIT + INTERVAL))
259     done
260     echo "service didn't stop after $WAIT seconds.  Still running:"
261     echo ${running}
262     exit 1
263 }
264
265 zconf_mount() {
266     local OPTIONS
267     local client=$1
268     local mnt=$2
269     # Only supply -o to mount if we have options
270     if [ -n "$MOUNTOPT" ]; then
271         OPTIONS="-o $MOUNTOPT"
272     fi
273     local device=$MGSNID:/$FSNAME
274     if [ -z "$mnt" -o -z "$FSNAME" ]; then
275         echo Bad zconf mount command: opt=$OPTIONS dev=$device mnt=$mnt
276         exit 1
277     fi
278
279     echo "Starting client: $OPTIONS $device $mnt" 
280     do_node $client mkdir -p $mnt
281     do_node $client mount -t lustre $OPTIONS $device $mnt || return 1
282
283     do_node $client "sysctl -w lnet.debug=$PTLDEBUG; sysctl -w lnet.subsystem_debug=${SUBSYSTEM# }"
284     [ -d /r ] && $LCTL modules > /r/tmp/ogdb-`hostname`
285     return 0
286 }
287
288 zconf_umount() {
289     client=$1
290     mnt=$2
291     [ "$3" ] && force=-f
292     local running=$(do_node $client "grep -c $mnt' ' /proc/mounts") || true
293     if [ $running -ne 0 ]; then
294         echo "Stopping client $mnt (opts:$force)"
295         do_node $client umount $force $mnt
296     fi
297 }
298
299 shutdown_facet() {
300     facet=$1
301     if [ "$FAILURE_MODE" = HARD ]; then
302         $POWER_DOWN `facet_active_host $facet`
303         sleep 2 
304     elif [ "$FAILURE_MODE" = SOFT ]; then
305         stop $facet
306     fi
307 }
308
309 reboot_facet() {
310     facet=$1
311     if [ "$FAILURE_MODE" = HARD ]; then
312         $POWER_UP `facet_active_host $facet`
313     else
314         sleep 10
315     fi
316 }
317
318 # verify that lustre actually cleaned up properly
319 cleanup_check() {
320     [ -f $CATASTROPHE ] && [ `cat $CATASTROPHE` -ne 0 ] && \
321         error "LBUG/LASSERT detected"
322     BUSY=`dmesg | grep -i destruct || true`
323     if [ "$BUSY" ]; then
324         echo "$BUSY" 1>&2
325         [ -e $TMP/debug ] && mv $TMP/debug $TMP/debug-busy.`date +%s`
326         exit 205
327     fi
328     LEAK_LUSTRE=`dmesg | tail -n 30 | grep "obd mem.*leaked" || true`
329     LEAK_PORTALS=`dmesg | tail -n 20 | grep "Portals memory leaked" || true`
330     if [ "$LEAK_LUSTRE" -o "$LEAK_PORTALS" ]; then
331         echo "$0: $LEAK_LUSTRE" 1>&2
332         echo "$0: $LEAK_PORTALS" 1>&2
333         echo "$0: Memory leak(s) detected..." 1>&2
334         mv $TMP/debug $TMP/debug-leak.`date +%s`
335         exit 204
336     fi
337
338     [ "`lctl dl 2> /dev/null | wc -l`" -gt 0 ] && lctl dl && \
339         echo "$0: lustre didn't clean up..." 1>&2 && return 202 || true
340
341     if [ "`/sbin/lsmod 2>&1 | egrep 'lnet|libcfs'`" ]; then
342         echo "$0: modules still loaded..." 1>&2
343         /sbin/lsmod 1>&2
344         return 203
345     fi
346     return 0
347 }
348
349 wait_for_host() {
350     HOST=$1
351     check_network "$HOST" 900
352     while ! do_node $HOST "ls -d $LUSTRE " > /dev/null; do sleep 5; done
353 }
354
355 wait_for() {
356     facet=$1
357     HOST=`facet_active_host $facet`
358     wait_for_host $HOST
359 }
360
361 client_df() {
362     # not every config has many clients
363     if [ ! -z "$CLIENTS" ]; then
364         $PDSH $CLIENTS "df $MOUNT" > /dev/null
365     fi
366 }
367
368 client_reconnect() {
369     uname -n >> $MOUNT/recon
370     if [ ! -z "$CLIENTS" ]; then
371         $PDSH $CLIENTS "df $MOUNT; uname -n >> $MOUNT/recon" > /dev/null
372     fi
373     echo Connected clients:
374     cat $MOUNT/recon
375     ls -l $MOUNT/recon > /dev/null
376     rm $MOUNT/recon
377 }
378
379 facet_failover() {
380     facet=$1
381     echo "Failing $facet on node `facet_active_host $facet`"
382     shutdown_facet $facet
383     reboot_facet $facet
384     client_df &
385     DFPID=$!
386     echo "df pid is $DFPID"
387     change_active $facet
388     TO=`facet_active_host $facet`
389     echo "Failover $facet to $TO"
390     wait_for $facet
391     local dev=${facet}_dev
392     local opt=${facet}_opt
393     start $facet ${!dev} ${!opt}
394 }
395
396 obd_name() {
397     local facet=$1
398 }
399
400 replay_barrier() {
401     local facet=$1
402     do_facet $facet sync
403     df $MOUNT
404     local svc=${facet}_svc
405     do_facet $facet $LCTL --device %${!svc} readonly
406     do_facet $facet $LCTL --device %${!svc} notransno
407     do_facet $facet $LCTL mark "$facet REPLAY BARRIER on ${!svc}"
408     $LCTL mark "local REPLAY BARRIER on ${!svc}"
409 }
410
411 replay_barrier_nodf() {
412     local facet=$1    echo running=${running}
413     do_facet $facet sync
414     local svc=${facet}_svc
415     echo Replay barrier on ${!svc}
416     do_facet $facet $LCTL --device %${!svc} readonly
417     do_facet $facet $LCTL --device %${!svc} notransno
418     do_facet $facet $LCTL mark "$facet REPLAY BARRIER on ${!svc}"
419     $LCTL mark "local REPLAY BARRIER on ${!svc}"
420 }
421
422 mds_evict_client() {
423     UUID=`cat /proc/fs/lustre/mdc/${mds_svc}-mdc-*/uuid`
424     do_facet mds "echo $UUID > /proc/fs/lustre/mds/${mds_svc}/evict_client"
425 }
426
427 ost_evict_client() {
428     UUID=`cat /proc/fs/lustre/osc/${ost1_svc}-osc-*/uuid`
429     do_facet ost1 "echo $UUID > /proc/fs/lustre/obdfilter/${ost1_svc}/evict_client"
430 }
431
432 fail() {
433     facet_failover $* || error "failover: $?"
434     df $MOUNT || error "post-failover df: $?"
435 }
436
437 fail_abort() {
438     local facet=$1
439     stop $facet
440     change_active $facet
441     local svc=${facet}_svc
442     local dev=${facet}_dev
443     local opt=${facet}_opt
444     start $facet ${!dev} ${!opt}
445     do_facet $facet lctl --device %${!svc} abort_recovery
446     df $MOUNT || echo "first df failed: $?"
447     sleep 1
448     df $MOUNT || error "post-failover df: $?"
449 }
450
451 do_lmc() {
452     echo There is no lmc.  This is mountconf, baby.
453     exit 1
454 }
455
456 h2gm () {
457     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
458         ID=`$PDSH $1 $GMNALNID -l | cut -d\  -f2`
459         echo $ID"@gm"
460     fi
461 }
462
463 h2ptl() {
464    if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
465        ID=`xtprocadmin -n $1 2>/dev/null | egrep -v 'NID' | awk '{print $1}'`
466        if [ -z "$ID" ]; then
467            echo "Could not get a ptl id for $1..."
468            exit 1
469        fi
470        echo $ID"@ptl"
471    fi
472 }
473 declare -fx h2ptl
474
475 h2tcp() {
476     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
477         echo $1"@tcp" 
478     fi
479 }
480 declare -fx h2tcp
481
482 h2elan() {
483     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
484         if type __h2elan >/dev/null 2>&1; then
485             ID=$(__h2elan $1)
486         else
487             ID=`echo $1 | sed 's/[^0-9]*//g'`
488         fi
489         echo $ID"@elan"
490     fi
491 }
492 declare -fx h2elan
493
494 h2openib() {
495     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
496         ID=`echo $1 | sed 's/[^0-9]*//g'`
497         echo $ID"@openib"
498     fi
499 }
500 declare -fx h2openib
501
502 facet_host() {
503     local facet=$1
504     varname=${facet}_HOST
505     if [ -z "${!varname}" ]; then
506         if [ "${facet:0:3}" == "ost" ]; then
507             eval ${facet}_HOST=${ost_HOST}
508         fi
509     fi
510     echo -n ${!varname}
511 }
512
513 facet_active() {
514     local facet=$1
515     local activevar=${facet}active
516
517     if [ -f ./${facet}active ] ; then
518         source ./${facet}active
519     fi
520
521     active=${!activevar}
522     if [ -z "$active" ] ; then 
523         echo -n ${facet}
524     else
525         echo -n ${active}
526     fi
527 }
528
529 facet_active_host() {
530     local facet=$1
531     local active=`facet_active $facet`
532     if [ "$facet" == client ]; then
533         hostname
534     else
535         echo `facet_host $active`
536     fi
537 }
538
539 change_active() {
540     local facet=$1
541     failover=${facet}failover 
542     host=`facet_host $failover`
543     [ -z "$host" ] && return
544     curactive=`facet_active $facet`
545     if [ -z "${curactive}" -o "$curactive" == "$failover" ] ; then
546         eval export ${facet}active=$facet
547     else
548         eval export ${facet}active=$failover
549     fi
550     # save the active host for this facet
551     activevar=${facet}active
552     echo "$activevar=${!activevar}" > ./$activevar
553 }
554
555 do_node() {
556     HOST=$1
557     shift
558     local myPDSH=$PDSH
559     if [ "$HOST" = "$(hostname)" ]; then
560         myPDSH="no_dsh"
561     fi
562     if $VERBOSE; then
563         echo "CMD: $HOST $@" >&2
564         $myPDSH $HOST $LCTL mark "$@" > /dev/null 2>&1 || :
565     fi
566     $myPDSH $HOST "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin; cd $RPWD; sh -c \"$@\")" | sed "s/^${HOST}: //"
567     return ${PIPESTATUS[0]}
568 }
569
570 do_facet() {
571     facet=$1
572     shift
573     HOST=`facet_active_host $facet`
574     [ -z $HOST ] && echo No host defined for facet ${facet} && exit 1
575     do_node $HOST $@
576 }
577
578 add() {
579     local facet=$1
580     shift
581     # make sure its not already running
582     stop ${facet} -f
583     rm -f ${facet}active
584     do_facet ${facet} $MKFS $*
585 }
586
587 ostdevname() {
588     num=$1
589     DEVNAME=OSTDEV$num
590     #if $OSTDEVn isn't defined, default is $OSTDEVBASE + num
591     eval DEVPTR=${!DEVNAME:=${OSTDEVBASE}${num}}
592     echo -n $DEVPTR
593 }
594
595 ########
596 ## MountConf setup
597
598 stopall() {
599     # make sure we are using the primary server, so test-framework will
600     # be able to clean up properly.
601     activemds=`facet_active mds`
602     if [ $activemds != "mds" ]; then
603         fail mds
604     fi
605     
606     # assume client mount is local 
607     grep " $MOUNT " /proc/mounts && zconf_umount `hostname` $MOUNT $*
608     grep " $MOUNT2 " /proc/mounts && zconf_umount `hostname` $MOUNT2 $*
609     stop mds -f
610     for num in `seq $OSTCOUNT`; do
611         stop ost$num -f
612     done
613     return 0
614 }
615
616 cleanupall() {
617     stopall $*
618     unload_modules
619 }
620
621 formatall() {
622     [ "$FSTYPE" ] && FSTYPE_OPT="--backfstype $FSTYPE"
623
624     stopall
625     # We need ldiskfs here, may as well load them all
626     load_modules
627     [ "$CLIENTONLY" ] && return
628     echo Formatting mds, osts
629     if $VERBOSE; then
630         add mds $MDS_MKFS_OPTS $FSTYPE_OPT --reformat $MDSDEV || exit 10
631     else
632         add mds $MDS_MKFS_OPTS $FSTYPE_OPT --reformat $MDSDEV > /dev/null || exit 10
633     fi
634
635     for num in `seq $OSTCOUNT`; do
636         if $VERBOSE; then
637             add ost$num $OST_MKFS_OPTS $FSTYPE_OPT --reformat `ostdevname $num` || exit 10
638         else
639             add ost$num $OST_MKFS_OPTS $FSTYPE_OPT --reformat `ostdevname $num` > /dev/null || exit 10
640         fi
641     done
642 }
643
644 mount_client() {
645     grep " $1 " /proc/mounts || zconf_mount `hostname` $*
646 }
647
648 setupall() {
649     load_modules
650     if [ -z "$CLIENTONLY" ]; then
651         echo Setup mdt, osts
652         echo $REFORMAT | grep -q "reformat" \
653             || do_facet mds "$TUNEFS --writeconf $MDSDEV"
654         start mds $MDSDEV $MDS_MOUNT_OPTS
655         for num in `seq $OSTCOUNT`; do
656             DEVNAME=`ostdevname $num`
657             start ost$num $DEVNAME $OST_MOUNT_OPTS
658         done
659     fi
660     [ "$DAEMONFILE" ] && $LCTL debug_daemon start $DAEMONFILE $DAEMONSIZE
661     mount_client $MOUNT
662     if [ "$MOUNT_2" ]; then
663         mount_client $MOUNT2
664     fi
665     sleep 5
666 }
667
668
669 ####### 
670 # General functions
671
672 check_network() {
673     local NETWORK=0
674     local WAIT=0
675     local MAX=$2
676     while [ $NETWORK -eq 0 ]; do
677         ping -c 1 -w 3 $1 > /dev/null
678         if [ $? -eq 0 ]; then
679             NETWORK=1
680         else
681             WAIT=$((WAIT + 5))
682             echo "waiting for $1, $((MAX - WAIT)) secs left"
683             sleep 5
684         fi
685         if [ $WAIT -gt $MAX ]; then
686             echo "Network not available"
687             exit 1
688         fi
689     done
690 }
691 check_port() {
692     while( !($DSH2 $1 "netstat -tna | grep -q $2") ) ; do
693         sleep 9
694     done
695 }
696
697 no_dsh() {
698     shift
699     eval $@
700 }
701
702 comma_list() {
703     # the sed converts spaces to commas, but leaves the last space
704     # alone, so the line doesn't end with a comma.
705     echo "$*" | tr -s " " "\n" | sort -b -u | tr "\n" " " | sed 's/ \([^$]\)/,\1/g'
706 }
707
708 absolute_path() {
709     (cd `dirname $1`; echo $PWD/`basename $1`)
710 }
711
712 ##################################
713 # OBD_FAIL funcs
714
715 drop_request() {
716 # OBD_FAIL_MDS_ALL_REQUEST_NET
717     RC=0
718     do_facet mds sysctl -w lustre.fail_loc=0x123
719     do_facet client "$1" || RC=$?
720     do_facet mds sysctl -w lustre.fail_loc=0
721     return $RC
722 }
723
724 drop_reply() {
725 # OBD_FAIL_MDS_ALL_REPLY_NET
726     RC=0
727     do_facet mds sysctl -w lustre.fail_loc=0x122
728     do_facet client "$@" || RC=$?
729     do_facet mds sysctl -w lustre.fail_loc=0
730     return $RC
731 }
732
733 drop_reint_reply() {
734 # OBD_FAIL_MDS_REINT_NET_REP
735     RC=0
736     do_facet mds sysctl -w lustre.fail_loc=0x119
737     do_facet client "$@" || RC=$?
738     do_facet mds sysctl -w lustre.fail_loc=0
739     return $RC
740 }
741
742 pause_bulk() {
743 #define OBD_FAIL_OST_BRW_PAUSE_BULK      0x214
744     RC=0
745     do_facet ost1 sysctl -w lustre.fail_loc=0x214
746     do_facet client "$1" || RC=$?
747     do_facet client "sync"
748     do_facet ost1 sysctl -w lustre.fail_loc=0
749     return $RC
750 }
751
752 drop_ldlm_cancel() {
753 #define OBD_FAIL_LDLM_CANCEL             0x304
754     RC=0
755     do_facet client sysctl -w lustre.fail_loc=0x304
756     do_facet client "$@" || RC=$?
757     do_facet client sysctl -w lustre.fail_loc=0
758     return $RC
759 }
760
761 drop_bl_callback() {
762 #define OBD_FAIL_LDLM_BL_CALLBACK        0x305
763     RC=0
764     do_facet client sysctl -w lustre.fail_loc=0x305
765     do_facet client "$@" || RC=$?
766     do_facet client sysctl -w lustre.fail_loc=0
767     return $RC
768 }
769
770 drop_ldlm_reply() {
771 #define OBD_FAIL_LDLM_REPLY              0x30c
772     RC=0
773     do_facet mds sysctl -w lustre.fail_loc=0x30c
774     do_facet client "$@" || RC=$?
775     do_facet mds sysctl -w lustre.fail_loc=0
776     return $RC
777 }
778
779 clear_failloc() {
780     facet=$1
781     pause=$2
782     sleep $pause
783     echo "clearing fail_loc on $facet"
784     do_facet $facet "sysctl -w lustre.fail_loc=0"
785 }
786
787 cancel_lru_locks() {
788     $LCTL mark "cancel_lru_locks $1 start"
789     for d in `find $LPROC/ldlm/namespaces | egrep -i $1`; do
790         [ -f $d/lru_size ] && echo clear > $d/lru_size
791         [ -f $d/lock_unused_count ] && grep [1-9] $d/lock_unused_count /dev/null
792     done
793     $LCTL mark "cancel_lru_locks $1 stop"
794 }
795
796
797 pgcache_empty() {
798     for a in /proc/fs/lustre/llite/*/dump_page_cache; do
799         if [ `wc -l $a | awk '{print $1}'` -gt 1 ]; then
800             echo there is still data in page cache $a ?
801             cat $a;
802             return 1;
803         fi
804     done
805     return 0
806 }
807
808 debugsave() {
809     DEBUGSAVE="$(sysctl -n lnet.debug)"
810 }
811
812 debugrestore() {
813     [ -n "$DEBUGSAVE" ] && sysctl -w lnet.debug=\"$DEBUGSAVE\"
814     DEBUGSAVE=""
815 }
816
817 ##################################
818 # Test interface 
819 error() {
820     local ERRLOG
821     sysctl -w lustre.fail_loc=0 2> /dev/null || true
822     log "${TESTSUITE} ${TESTNAME}: **** FAIL:" $@
823     ERRLOG=$TMP/lustre_${TESTSUITE}_${TESTNAME}.$(date +%s)
824     echo "Dumping lctl log to $ERRLOG"
825     $LCTL dk $ERRLOG
826     debugrestore
827     exit 1
828 }
829
830 build_test_filter() {
831     [ "$ONLY" ] && log "only running test `echo $ONLY`"
832     for O in $ONLY; do
833         eval ONLY_${O}=true
834     done
835     [ "$EXCEPT$ALWAYS_EXCEPT" ] && \
836         log "skipping tests: `echo $EXCEPT $ALWAYS_EXCEPT`"
837     for E in $EXCEPT $ALWAYS_EXCEPT; do
838         eval EXCEPT_${E}=true
839     done
840 }
841
842 _basetest() {
843     echo $*
844 }
845
846 basetest() {
847     IFS=abcdefghijklmnopqrstuvwxyz _basetest $1
848 }
849
850 run_test() {
851     export base=`basetest $1`
852     if [ ! -z "$ONLY" ]; then
853         testname=ONLY_$1
854         if [ ${!testname}x != x ]; then
855             run_one $1 "$2"
856             return $?
857         fi
858         testname=ONLY_$base
859         if [ ${!testname}x != x ]; then
860             run_one $1 "$2"
861             return $?
862         fi
863         echo -n "."
864         return 0
865     fi
866     testname=EXCEPT_$1
867     if [ ${!testname}x != x ]; then
868         log "skipping excluded test $1"
869         return 0
870     fi
871     testname=EXCEPT_$base
872     if [ ${!testname}x != x ]; then
873         log "skipping excluded test $1 (base $base)"
874         return 0
875     fi
876     run_one $1 "$2"
877     
878     return $?
879 }
880
881 EQUALS="======================================================================"
882 equals_msg() {
883     msg="$@"
884
885     local suffixlen=$((${#EQUALS} - ${#msg}))
886     [ $suffixlen -lt 5 ] && suffixlen=5
887     printf '===== %s %.*s\n' "$msg" $suffixlen $EQUALS
888 }
889
890 log() {
891     echo "$*"
892     lsmod | grep lnet > /dev/null || load_modules
893     $LCTL mark "$*" 2> /dev/null || true
894 }
895
896 pass() {
897     echo PASS $@
898 }
899
900 check_mds() {
901     FFREE=`cat /proc/fs/lustre/mds/*/filesfree`
902     FTOTAL=`cat /proc/fs/lustre/mds/*/filestotal`
903     [ $FFREE -ge $FTOTAL ] && error "files free $FFREE > total $FTOTAL" || true
904 }
905
906 run_one() {
907     testnum=$1
908     message=$2
909     tfile=f${testnum}
910     tdir=d${base}
911
912     # Pretty tests run faster.
913     equals_msg $testnum: $message
914
915     BEFORE=`date +%s`
916     log "== test $testnum: $message ============ `date +%H:%M:%S` ($BEFORE)"
917     #check_mds
918     export TESTNAME=test_$testnum
919     test_${testnum} || error "test_$testnum failed with $?"
920     #check_mds
921     [ -f $CATASTROPHE ] && [ `cat $CATASTROPHE` -ne 0 ] && \
922         error "LBUG/LASSERT detected"
923     pass "($((`date +%s` - $BEFORE))s)"
924     unset TESTNAME
925 }
926
927 canonical_path() {
928     (cd `dirname $1`; echo $PWD/`basename $1`)
929 }
930