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