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