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