Whamcloud - gitweb
d3dbb635b15fd891fc6af65ee93cec64eb114987
[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 export QUOTA_AUTO=1
19
20 #export PDSH="pdsh -S -Rssh -w"
21
22 # function used by scripts run on remote nodes
23 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
24 . $LUSTRE/tests/functions.sh
25
26 LUSTRE_TESTS_CFG_DIR=${LUSTRE_TESTS_CFG_DIR:-${LUSTRE}/tests/cfg}
27
28 EXCEPT_LIST_FILE=${EXCEPT_LIST_FILE:-${LUSTRE_TESTS_CFG_DIR}/tests-to-skip.sh}
29
30 if [ -f "$EXCEPT_LIST_FILE" ]; then
31     echo "Reading test skip list from $EXCEPT_LIST_FILE"
32     cat $EXCEPT_LIST_FILE
33     . $EXCEPT_LIST_FILE
34 fi
35
36 assert_DIR () {
37     local failed=""
38     [[ $DIR/ = $MOUNT/* ]] || \
39         { failed=1 && echo "DIR=$DIR not in $MOUNT. Aborting."; }
40     [[ $DIR1/ = $MOUNT1/* ]] || \
41         { failed=1 && echo "DIR1=$DIR1 not in $MOUNT1. Aborting."; }
42     [[ $DIR2/ = $MOUNT2/* ]] || \
43         { failed=1 && echo "DIR2=$DIR2 not in $MOUNT2. Aborting"; }
44
45     [ -n "$failed" ] && exit 99 || true
46 }
47
48 usage() {
49     echo "usage: $0 [-r] [-f cfgfile]"
50     echo "       -r: reformat"
51
52     exit
53 }
54
55 print_summary () {
56     trap 0
57     [ "$TESTSUITE" == "lfscktest" ] && return 0
58     [ -n "$ONLY" ] && echo "WARNING: ONLY is set to ${ONLY}."
59     local form="%-13s %-17s %s\n"
60     printf "$form" "status" "script" "skipped tests E(xcluded) S(low)"
61     echo "------------------------------------------------------------------------------------"
62     for O in $TESTSUITE_LIST; do
63         local skipped=""
64         local slow=""
65         local o=$(echo $O | tr "[:upper:]" "[:lower:]")
66         o=${o//_/-}
67         o=${o//tyn/tyN}
68         local log=${TMP}/${o}.log
69         [ -f $log ] && skipped=$(grep excluded $log | awk '{ printf " %s", $3 }' | sed 's/test_//g')
70         [ -f $log ] && slow=$(grep SLOW $log | awk '{ printf " %s", $3 }' | sed 's/test_//g')
71         [ "${!O}" = "done" ] && \
72             printf "$form" "Done" "$O" "E=$skipped" && \
73             [ -n "$slow" ] && printf "$form" "-" "-" "S=$slow"
74
75     done
76
77     for O in $TESTSUITE_LIST; do
78         if [ "${!O}" = "no" ]; then
79             # FIXME.
80             # only for those tests suits which are run directly from acc-sm script:
81             # bonnie, iozone, etc.
82             if [ -f "$TESTSUITELOG" ] && grep FAIL $TESTSUITELOG | grep -q ' '$O  ; then
83                printf "$form" "UNFINISHED" "$O" ""  
84             else
85                printf "$form" "Skipped" "$O" ""
86             fi
87         fi
88     done
89
90     for O in $TESTSUITE_LIST; do
91         [ "${!O}" = "done" -o "${!O}" = "no" ] || \
92             printf "$form" "UNFINISHED" "$O" ""
93     done
94 }
95
96 init_test_env() {
97     export LUSTRE=`absolute_path $LUSTRE`
98     export TESTSUITE=`basename $0 .sh`
99     export TEST_FAILED=false
100     export FAIL_ON_SKIP_ENV=${FAIL_ON_SKIP_ENV:-false}
101
102     export MKE2FS=${MKE2FS:-mke2fs}
103     export DEBUGFS=${DEBUGFS:-debugfs}
104     export TUNE2FS=${TUNE2FS:-tune2fs}
105     export E2LABEL=${E2LABEL:-e2label}
106     export DUMPE2FS=${DUMPE2FS:-dumpe2fs}
107     export E2FSCK=${E2FSCK:-e2fsck}
108
109     #[ -d /r ] && export ROOT=${ROOT:-/r}
110     export TMP=${TMP:-$ROOT/tmp}
111     export TESTSUITELOG=${TMP}/${TESTSUITE}.log
112     export HOSTNAME=${HOSTNAME:-`hostname`}
113     if ! echo $PATH | grep -q $LUSTRE/utils; then
114         export PATH=$PATH:$LUSTRE/utils
115     fi
116     if ! echo $PATH | grep -q $LUSTRE/utils/gss; then
117         export PATH=$PATH:$LUSTRE/utils/gss
118     fi
119     if ! echo $PATH | grep -q $LUSTRE/tests; then
120         export PATH=$PATH:$LUSTRE/tests
121     fi
122     export MDSRATE=${MDSRATE:-"$LUSTRE/tests/mpi/mdsrate"}
123     [ ! -f "$MDSRATE" ] && export MDSRATE=$(which mdsrate 2> /dev/null)
124     if ! echo $PATH | grep -q $LUSTRE/tests/racer; then
125         export PATH=$PATH:$LUSTRE/tests/racer
126     fi
127     if ! echo $PATH | grep -q $LUSTRE/tests/mpi; then
128         export PATH=$PATH:$LUSTRE/tests/mpi
129     fi
130     export RSYNC_RSH=${RSYNC_RSH:-rsh}
131     export LCTL=${LCTL:-"$LUSTRE/utils/lctl"}
132     [ ! -f "$LCTL" ] && export LCTL=$(which lctl)
133     export LFS=${LFS:-"$LUSTRE/utils/lfs"}
134     [ ! -f "$LFS" ] && export LFS=$(which lfs)
135     export L_GETIDENTITY=${L_GETIDENTITY:-"$LUSTRE/utils/l_getidentity"}
136     if [ ! -f "$L_GETIDENTITY" ]; then
137         if `which l_getidentity > /dev/null 2>&1`; then
138             export L_GETIDENTITY=$(which l_getidentity)
139         else
140             export L_GETIDENTITY=NONE
141         fi
142     fi
143     export MKFS=${MKFS:-"$LUSTRE/utils/mkfs.lustre"}
144     [ ! -f "$MKFS" ] && export MKFS=$(which mkfs.lustre)
145     export TUNEFS=${TUNEFS:-"$LUSTRE/utils/tunefs.lustre"}
146     [ ! -f "$TUNEFS" ] && export TUNEFS=$(which tunefs.lustre)
147     export CHECKSTAT="${CHECKSTAT:-"checkstat -v"} "
148     export LUSTRE_RMMOD=${LUSTRE_RMMOD:-$LUSTRE/scripts/lustre_rmmod}
149     [ ! -f "$LUSTRE_RMMOD" ] && export LUSTRE_RMMOD=$(which lustre_rmmod 2> /dev/null)
150     export FSTYPE=${FSTYPE:-"ldiskfs"}
151     export NAME=${NAME:-local}
152     export LGSSD=${LGSSD:-"$LUSTRE/utils/gss/lgssd"}
153     [ "$GSS_PIPEFS" = "true" ] && [ ! -f "$LGSSD" ] && \
154         export LGSSD=$(which lgssd)
155     export LSVCGSSD=${LSVCGSSD:-"$LUSTRE/utils/gss/lsvcgssd"}
156     [ ! -f "$LSVCGSSD" ] && export LSVCGSSD=$(which lsvcgssd 2> /dev/null)
157     export KRB5DIR=${KRB5DIR:-"/usr/kerberos"}
158     export DIR2
159     export SAVE_PWD=${SAVE_PWD:-$LUSTRE/tests}
160     export AT_MAX_PATH
161
162     if [ "$ACCEPTOR_PORT" ]; then
163         export PORT_OPT="--port $ACCEPTOR_PORT"
164     fi
165
166     case "x$SEC" in
167         xkrb5*)
168             echo "Using GSS/krb5 ptlrpc security flavor"
169             which lgss_keyring > /dev/null 2>&1 || \
170                 error_exit "built with gss disabled! SEC=$SEC"
171             GSS=true
172             GSS_KRB5=true
173             ;;
174     esac
175
176     case "x$IDUP" in
177         xtrue)
178             IDENTITY_UPCALL=true
179             ;;
180         xfalse)
181             IDENTITY_UPCALL=false
182             ;;
183     esac
184     export LOAD_MODULES_REMOTE=${LOAD_MODULES_REMOTE:-false}
185
186     # Paths on remote nodes, if different
187     export RLUSTRE=${RLUSTRE:-$LUSTRE}
188     export RPWD=${RPWD:-$PWD}
189     export I_MOUNTED=${I_MOUNTED:-"no"}
190     if [ ! -f /lib/modules/$(uname -r)/kernel/fs/lustre/mds.ko -a \
191         ! -f `dirname $0`/../mds/mds.ko ]; then
192         export CLIENTMODSONLY=yes
193     fi
194
195     # command line
196
197     while getopts "rvwf:" opt $*; do
198         case $opt in
199             f) CONFIG=$OPTARG;;
200             r) REFORMAT=--reformat;;
201             v) VERBOSE=true;;
202             w) WRITECONF=writeconf;;
203             \?) usage;;
204         esac
205     done
206
207     shift $((OPTIND - 1))
208     ONLY=${ONLY:-$*}
209
210     [ "$TESTSUITELOG" ] && rm -f $TESTSUITELOG || true
211     rm -f $TMP/*active
212 }
213
214 case `uname -r` in
215 2.4.*) EXT=".o"; USE_QUOTA=no; [ ! "$CLIENTONLY" ] && FSTYPE=ext3;;
216     *) EXT=".ko"; USE_QUOTA=yes;;
217 esac
218
219
220 module_loaded () {
221    /sbin/lsmod | grep -q $1
222 }
223
224 load_module() {
225     EXT=".ko"
226     module=$1
227     shift
228     BASE=`basename $module $EXT`
229
230     module_loaded ${BASE} && return
231
232     if [ -f ${LUSTRE}/${module}${EXT} ]; then
233         insmod ${LUSTRE}/${module}${EXT} $@
234     else
235         # must be testing a "make install" or "rpm" installation
236         # note failed to load ptlrpc_gss is considered not fatal
237         if [ "$BASE" == "ptlrpc_gss" ]; then
238             modprobe $BASE $@ 2>/dev/null || echo "gss/krb5 is not supported"
239         else
240             modprobe $BASE $@
241         fi
242     fi
243 }
244
245 load_modules_local() {
246     if [ -n "$MODPROBE" ]; then
247         # use modprobe
248     return 0
249     fi
250     if [ "$HAVE_MODULES" = true ]; then
251     # we already loaded
252         return 0
253     fi
254     HAVE_MODULES=true
255
256     echo Loading modules from $LUSTRE
257     load_module ../libcfs/libcfs/libcfs
258     [ "$PTLDEBUG" ] && lctl set_param debug="$PTLDEBUG"
259     [ "$SUBSYSTEM" ] && lctl set_param subsystem_debug="${SUBSYSTEM# }"
260     local MODPROBECONF=
261     [ -f /etc/modprobe.conf ] && MODPROBECONF=/etc/modprobe.conf
262     [ ! "$MODPROBECONF" -a -d /etc/modprobe.d ] && MODPROBECONF=/etc/modprobe.d/Lustre
263     [ -z "$LNETOPTS" -a "$MODPROBECONF" ] && \
264         LNETOPTS=$(awk '/^options lnet/ { print $0}' $MODPROBECONF | sed 's/^options lnet //g')
265     echo $LNETOPTS | grep -q "accept=all"  || LNETOPTS="$LNETOPTS accept=all";
266     echo "lnet options: '$LNETOPTS'"
267     # note that insmod will ignore anything in modprobe.conf
268     load_module ../lnet/lnet/lnet $LNETOPTS
269     LNETLND=${LNETLND:-"socklnd/ksocklnd"}
270     load_module ../lnet/klnds/$LNETLND
271     load_module lvfs/lvfs
272     load_module obdclass/obdclass
273     load_module ptlrpc/ptlrpc
274     load_module ptlrpc/gss/ptlrpc_gss
275     [ "$USE_QUOTA" = "yes" -a "$LQUOTA" != "no" ] && load_module quota/lquota
276     load_module fld/fld
277     load_module fid/fid
278     load_module lmv/lmv
279     load_module mdc/mdc
280     load_module osc/osc
281     load_module lov/lov
282     load_module mgc/mgc
283     if ! client_only; then
284         grep -q crc16 /proc/kallsyms || { modprobe crc16 2>/dev/null || true; }
285         grep -q jbd /proc/kallsyms || { modprobe jbd 2>/dev/null || true; }
286         [ "$FSTYPE" = "ldiskfs" ] && load_module ../ldiskfs/ldiskfs/ldiskfs
287         load_module mgs/mgs
288         load_module mds/mds
289         load_module mdd/mdd
290         load_module mdt/mdt
291         load_module lvfs/fsfilt_$FSTYPE
292         load_module cmm/cmm
293         load_module osd/osd
294         load_module ost/ost
295         load_module obdfilter/obdfilter
296     fi
297
298     load_module llite/lustre
299     load_module llite/llite_lloop
300     [ -d /r ] && OGDB=${OGDB:-"/r/tmp"}
301     OGDB=${OGDB:-$TMP}
302     rm -f $OGDB/ogdb-$HOSTNAME
303     $LCTL modules > $OGDB/ogdb-$HOSTNAME
304
305     # 'mount' doesn't look in $PATH, just sbin
306     [ -f $LUSTRE/utils/mount.lustre ] && cp $LUSTRE/utils/mount.lustre /sbin/. || true
307 }
308
309 load_modules () {
310     load_modules_local
311     # bug 19124
312     # load modules on remote nodes optionally
313     # lustre-tests have to be installed on these nodes
314     if $LOAD_MODULES_REMOTE ; then
315         local list=$(comma_list $(remote_nodes_list))
316         echo loading modules on $list
317         do_rpc_nodes $list load_modules 
318     fi
319 }
320
321 check_mem_leak () {
322     LEAK_LUSTRE=$(dmesg | tail -n 30 | grep "obd_memory.*leaked" || true)
323     LEAK_PORTALS=$(dmesg | tail -n 20 | grep "Portals memory leaked" || true)
324     if [ "$LEAK_LUSTRE" -o "$LEAK_PORTALS" ]; then
325         echo "$LEAK_LUSTRE" 1>&2
326         echo "$LEAK_PORTALS" 1>&2
327         mv $TMP/debug $TMP/debug-leak.`date +%s` || true
328         echo "Memory leaks detected"
329         [ -n "$IGNORE_LEAK" ] && { echo "ignoring leaks" && return 0; } || true
330         return 1
331     fi
332 }
333
334 unload_modules() {
335     wait_exit_ST client # bug 12845
336
337     $LUSTRE_RMMOD $FSTYPE || return 2
338
339     if $LOAD_MODULES_REMOTE ; then
340         local list=$(comma_list $(remote_nodes_list))
341         echo unloading modules on $list
342         do_rpc_nodes $list $LUSTRE_RMMOD $FSTYPE
343         do_rpc_nodes $list check_mem_leak
344     fi
345
346     HAVE_MODULES=false
347
348     check_mem_leak || return 254
349
350     echo "modules unloaded."
351     return 0
352 }
353
354 check_gss_daemon_nodes() {
355     local list=$1
356     dname=$2
357
358     do_nodes --verbose $list "num=\\\$(ps -o cmd -C $dname | grep $dname | wc -l);
359 if [ \\\"\\\$num\\\" -ne 1 ]; then
360     echo \\\$num instance of $dname;
361     exit 1;
362 fi; "
363 }
364
365 check_gss_daemon_facet() {
366     facet=$1
367     dname=$2
368
369     num=`do_facet $facet ps -o cmd -C $dname | grep $dname | wc -l`
370     if [ $num -ne 1 ]; then
371         echo "$num instance of $dname on $facet"
372         return 1
373     fi
374     return 0
375 }
376
377 send_sigint() {
378     local list=$1
379     shift
380     echo Stopping $@ on $list
381     do_nodes $list "killall -2 $@ 2>/dev/null || true"
382 }
383
384 # start gss daemons on all nodes, or
385 # "daemon" on "list" if set
386 start_gss_daemons() {
387     local list=$1
388     local daemon=$2
389
390     if [ "$list" ] && [ "$daemon" ] ; then
391         echo "Starting gss daemon on nodes: $list"
392         do_nodes $list "$daemon" || return 8
393         return 0
394     fi
395
396     local list=$(comma_list $(mdts_nodes))
397
398     echo "Starting gss daemon on mds: $list"
399     do_nodes $list "$LSVCGSSD -v" || return 1
400     if $GSS_PIPEFS; then
401         do_nodes $list "$LGSSD -v" || return 2
402     fi
403
404     list=$(comma_list $(osts_nodes))
405     echo "Starting gss daemon on ost: $list"
406     do_nodes $list "$LSVCGSSD -v" || return 3
407     # starting on clients
408
409     local clients=${CLIENTS:-`hostname`}
410     if $GSS_PIPEFS; then
411         echo "Starting $LGSSD on clients $clients "
412         do_nodes $clients  "$LGSSD -v" || return 4
413     fi
414
415     # wait daemons entering "stable" status
416     sleep 5
417
418     #
419     # check daemons are running
420     #
421     list=$(comma_list $(mdts_nodes) $(osts_nodes))
422     check_gss_daemon_nodes $list lsvcgssd || return 5
423     if $GSS_PIPEFS; then
424         list=$(comma_list $(mdts_nodes))
425         check_gss_daemon_nodes $list lgssd || return 6
426     fi
427     if $GSS_PIPEFS; then
428         check_gss_daemon_nodes $clients lgssd || return 7
429     fi
430 }
431
432 stop_gss_daemons() {
433     local list=$(comma_list $(mdts_nodes))
434     
435     send_sigint $list lsvcgssd lgssd
436
437     list=$(comma_list $(osts_nodes))
438     send_sigint $list lsvcgssd
439
440     list=${CLIENTS:-`hostname`}
441     send_sigint $list lgssd
442 }
443
444 init_gss() {
445     if $GSS; then
446         if ! module_loaded ptlrpc_gss; then
447             load_module ptlrpc/gss/ptlrpc_gss
448             module_loaded ptlrpc_gss ||
449                 error_exit "init_gss : GSS=$GSS, but gss/krb5 is not supported!"
450         fi
451         start_gss_daemons || error_exit "start gss daemon failed! rc=$?"
452
453         if [ -n "$LGSS_KEYRING_DEBUG" ]; then
454             echo $LGSS_KEYRING_DEBUG > /proc/fs/lustre/sptlrpc/gss/lgss_keyring/debug_level
455         fi
456     fi
457 }
458
459 cleanup_gss() {
460     if $GSS; then
461         stop_gss_daemons
462         # maybe cleanup credential cache?
463     fi
464 }
465
466 mdsdevlabel() {
467     local num=$1
468     local device=`mdsdevname $num`
469     local label=`do_facet mds$num "e2label ${device}" | grep -v "CMD: "`
470     echo -n $label
471 }
472
473 ostdevlabel() {
474     local num=$1
475     local device=`ostdevname $num`
476     local label=`do_facet ost$num "e2label ${device}" | grep -v "CMD: "`
477     echo -n $label
478 }
479
480 # Facet functions
481 mount_facet() {
482     local facet=$1
483     shift
484     local dev=$(facet_active $facet)_dev
485     local opt=${facet}_opt
486     echo "Starting ${facet}: ${!opt} $@ ${!dev} ${MOUNT%/*}/${facet}"
487     do_facet ${facet} mount -t lustre ${!opt} $@ ${!dev} ${MOUNT%/*}/${facet}
488     RC=${PIPESTATUS[0]}
489     if [ $RC -ne 0 ]; then
490         echo "mount -t lustre $@ ${!dev} ${MOUNT%/*}/${facet}"
491         echo "Start of ${!dev} on ${facet} failed ${RC}"
492     else
493         do_facet ${facet} "lctl set_param debug=\\\"$PTLDEBUG\\\"; \
494             lctl set_param subsystem_debug=\\\"${SUBSYSTEM# }\\\"; \
495             lctl set_param debug_mb=${DEBUG_SIZE}; \
496             sync"
497
498         label=$(do_facet ${facet} "$E2LABEL ${!dev}")
499         [ -z "$label" ] && echo no label for ${!dev} && exit 1
500         eval export ${facet}_svc=${label}
501         echo Started ${label}
502     fi
503     return $RC
504 }
505
506 # start facet device options
507 start() {
508     local facet=$1
509     shift
510     local device=$1
511     shift
512     eval export ${facet}_dev=${device}
513     eval export ${facet}_opt=\"$@\"
514
515     local varname=${facet}failover_dev
516     if [ -n "${!varname}" ] ; then
517         eval export ${facet}failover_dev=${!varname}
518     else
519         eval export ${facet}failover_dev=$device
520     fi
521
522     do_facet ${facet} mkdir -p ${MOUNT%/*}/${facet}
523     mount_facet ${facet}
524     RC=$?
525     return $RC
526 }
527
528 stop() {
529     local running
530     local facet=$1
531     shift
532     HOST=`facet_active_host $facet`
533     [ -z $HOST ] && echo stop: no host for $facet && return 0
534
535     running=$(do_facet ${facet} "grep -c ${MOUNT%/*}/${facet}' ' /proc/mounts") || true
536     if [ ${running} -ne 0 ]; then
537         echo "Stopping ${MOUNT%/*}/${facet} (opts:$@)"
538         do_facet ${facet} umount -d $@ ${MOUNT%/*}/${facet}
539     fi
540
541     # umount should block, but we should wait for unrelated obd's
542     # like the MGS or MGC to also stop.
543     wait_exit_ST ${facet}
544 }
545
546 # save quota version (both administrative and operational quotas)
547 # add an additional parameter if mountpoint is ever different from $MOUNT
548 quota_save_version() {
549     local fsname=${2:-$FSNAME}
550     local spec=$1
551     local ver=$(tr -c -d "123" <<< $spec)
552     local type=$(tr -c -d "ug" <<< $spec)
553
554     [ -n "$ver" -a "$ver" != "3" ] && error "wrong quota version specifier"
555
556     [ -n "$type" ] && { $LFS quotacheck -$type $MOUNT || error "quotacheck has failed"; }
557
558     do_facet mgs "lctl conf_param ${fsname}-MDT*.mdd.quota_type=$spec"
559     local varsvc
560     local osts=$(get_facets OST)
561     for ost in ${osts//,/ }; do
562         varsvc=${ost}_svc
563         do_facet mgs "lctl conf_param ${!varsvc}.ost.quota_type=$spec"
564     done
565 }
566
567 # client could mount several lustre 
568 quota_type () {
569     local fsname=${1:-$FSNAME}
570     local rc=0
571     do_facet mgs lctl get_param mdd.${fsname}-MDT*.quota_type || rc=$?
572     do_nodes $(comma_list $(osts_nodes)) \
573         lctl get_param obdfilter.${fsname}-OST*.quota_type || rc=$?
574     return $rc 
575 }
576
577 restore_quota_type () {
578    local mntpt=${1:-$MOUNT}
579    local quota_type=$(quota_type $FSNAME | grep MDT | cut -d "=" -f2)
580    if [ ! "$old_QUOTA_TYPE" ] || [ "$quota_type" = "$old_QUOTA_TYPE" ]; then
581         return
582    fi
583    quota_save_version $old_QUOTA_TYPE
584 }
585
586 setup_quota(){
587     local mntpt=$1
588
589     # We need save the original quota_type params, and restore them after testing
590
591     # Suppose that quota type the same on mds and ost
592     local quota_type=$(quota_type | grep MDT | cut -d "=" -f2)
593     [ ${PIPESTATUS[0]} -eq 0 ] || error "quota_type failed!"
594     echo "[HOST:$HOSTNAME] [old_quota_type:$quota_type] [new_quota_type:$QUOTA_TYPE]"
595     if [ "$quota_type" != "$QUOTA_TYPE" ]; then
596         export old_QUOTA_TYPE=$quota_type
597         quota_save_version $QUOTA_TYPE
598     else
599         qtype=$(tr -c -d "ug" <<< $QUOTA_TYPE)
600         $LFS quotacheck -$qtype $mntpt || error "quotacheck has failed for $type"
601     fi
602
603     local quota_usrs=$QUOTA_USERS
604
605     # get_filesystem_size
606     local disksz=$(lfs df $mntpt | grep "filesystem summary:"  | awk '{print $3}')
607     local blk_soft=$((disksz + 1024))
608     local blk_hard=$((blk_soft + blk_soft / 20)) # Go 5% over
609
610     local Inodes=$(lfs df -i $mntpt | grep "filesystem summary:"  | awk '{print $3}')
611     local i_soft=$Inodes
612     local i_hard=$((i_soft + i_soft / 20))
613
614     echo "Total disk size: $disksz  block-softlimit: $blk_soft block-hardlimit:
615         $blk_hard inode-softlimit: $i_soft inode-hardlimit: $i_hard"
616
617     local cmd
618     for usr in $quota_usrs; do
619         echo "Setting up quota on $HOSTNAME:$mntpt for $usr..."
620         for type in u g; do
621             cmd="$LFS setquota -$type $usr -b $blk_soft -B $blk_hard -i $i_soft -I $i_hard $mntpt"
622             echo "+ $cmd"
623             eval $cmd || error "$cmd FAILED!"
624         done
625         # display the quota status
626         echo "Quota settings for $usr : "
627         $LFS quota -v -u $usr $mntpt || true
628     done
629 }
630
631 zconf_mount() {
632     local OPTIONS
633     local client=$1
634     local mnt=$2
635     # Only supply -o to mount if we have options
636     if [ -n "$MOUNTOPT" ]; then
637         OPTIONS="-o $MOUNTOPT"
638     fi
639     local device=$MGSNID:/$FSNAME
640     if [ -z "$mnt" -o -z "$FSNAME" ]; then
641         echo Bad zconf mount command: opt=$OPTIONS dev=$device mnt=$mnt
642         exit 1
643     fi
644
645     echo "Starting client: $client: $OPTIONS $device $mnt"
646     do_node $client mkdir -p $mnt
647     do_node $client mount -t lustre $OPTIONS $device $mnt || return 1
648
649     do_node $client "lctl set_param debug=\\\"$PTLDEBUG\\\";
650         lctl set_param subsystem_debug=\\\"${SUBSYSTEM# }\\\";
651         lctl set_param debug_mb=${DEBUG_SIZE}"
652
653     return 0
654 }
655
656 zconf_umount() {
657     local client=$1
658     local mnt=$2
659     local force
660     local busy 
661     local need_kill
662
663     [ "$3" ] && force=-f
664     local running=$(do_node $client "grep -c $mnt' ' /proc/mounts") || true
665     if [ $running -ne 0 ]; then
666         echo "Stopping client $client $mnt (opts:$force)"
667         do_node $client lsof -t $mnt || need_kill=no
668         if [ "x$force" != "x" -a "x$need_kill" != "xno" ]; then
669             pids=$(do_node $client lsof -t $mnt | sort -u);
670             if [ -n $pids ]; then
671                 do_node $client kill -9 $pids || true
672             fi
673         fi
674
675         busy=$(do_node $client "umount $force $mnt 2>&1" | grep -c "busy") || true
676         if [ $busy -ne 0 ] ; then
677             echo "$mnt is still busy, wait one second" && sleep 1
678             do_node $client umount $force $mnt
679         fi
680     fi
681 }
682
683 # nodes is comma list
684 sanity_mount_check_nodes () {
685     local nodes=$1
686     shift
687     local mnts="$@"
688     local mnt
689
690     # FIXME: assume that all cluster nodes run the same os
691     [ "$(uname)" = Linux ] || return 0
692
693     local rc=0
694     for mnt in $mnts ; do
695         do_nodes $nodes "running=\\\$(grep -c $mnt' ' /proc/mounts);
696 mpts=\\\$(mount | grep -w -c $mnt);
697 if [ \\\$running -ne \\\$mpts ]; then
698     echo \\\$(hostname) env are INSANE!;
699     exit 1;
700 fi"
701     [ $? -eq 0 ] || rc=1 
702     done
703     return $rc
704 }
705
706 sanity_mount_check_servers () {
707     [ "$CLIENTONLY" ] && 
708         { echo "CLIENTONLY mode, skip mount_check_servers"; return 0; } || true
709     echo Checking servers environments
710
711     # FIXME: modify get_facets to display all facets wo params
712     local facets="$(get_facets OST),$(get_facets MDS),mgs"
713     local node
714     local mnt
715     local facet
716     for facet in ${facets//,/ }; do
717         node=$(facet_host ${facet})
718         mnt=${MOUNT%/*}/${facet}
719         sanity_mount_check_nodes $node $mnt ||
720             { error "server $node environments are insane!"; return 1; }
721     done
722 }
723
724 sanity_mount_check_clients () {
725     local clients=${1:-$CLIENTS}
726     local mntpt=${2:-$MOUNT}
727     local mntpt2=${3:-$MOUNT2}
728
729     [ -z $clients ] && clients=$(hostname)
730     echo Checking clients $clients environments
731
732     sanity_mount_check_nodes $clients $mntpt $mntpt2 ||
733        error "clients environments are insane!"
734 }
735
736 sanity_mount_check () {
737     sanity_mount_check_servers || return 1
738     sanity_mount_check_clients || return 2
739 }
740
741 # mount clients if not mouted
742 zconf_mount_clients() {
743     local clients=$1
744     local mnt=$2
745     local OPTIONS=${3:-$MOUNTOPT}
746
747     # Only supply -o to mount if we have options
748     if [ "$OPTIONS" ]; then
749         OPTIONS="-o $OPTIONS"
750     fi
751     local device=$MGSNID:/$FSNAME
752     if [ -z "$mnt" -o -z "$FSNAME" ]; then
753         echo Bad zconf mount command: opt=$OPTIONS dev=$device mnt=$mnt
754         exit 1
755     fi
756
757     echo "Starting client $clients: $OPTIONS $device $mnt"
758
759     do_nodes $clients "
760 running=\\\$(mount | grep -c $mnt' ');
761 rc=0;
762 if [ \\\$running -eq 0 ] ; then
763     mkdir -p $mnt;
764     mount -t lustre $OPTIONS $device $mnt;
765     rc=\\\$?;
766 fi;
767 exit \\\$rc" || return ${PIPESTATUS[0]}
768
769     echo "Started clients $clients: "
770     do_nodes $clients "mount | grep -w $mnt"
771
772     do_nodes $clients "lctl set_param debug=\\\"$PTLDEBUG\\\";
773         lctl set_param subsystem_debug=\\\"${SUBSYSTEM# }\\\";
774         lctl set_param debug_mb=${DEBUG_SIZE};"
775
776     return 0
777 }
778
779 zconf_umount_clients() {
780     local clients=$1
781     local mnt=$2
782     local force
783
784     [ "$3" ] && force=-f
785
786     echo "Stopping clients: $clients $mnt (opts:$force)"
787     do_nodes $clients "running=\\\$(grep -c $mnt' ' /proc/mounts);
788 if [ \\\$running -ne 0 ] ; then
789 echo Stopping client \\\$(hostname) $mnt opts:$force;
790 lsof -t $mnt || need_kill=no;
791 if [ "x$force" != "x" -a "x\\\$need_kill" != "xno" ]; then
792     pids=\\\$(lsof -t $mnt | sort -u);
793     if [ -n \\\"\\\$pids\\\" ]; then
794              kill -9 \\\$pids;
795     fi
796 fi;
797 busy=\\\$(umount $force $mnt 2>&1 | grep -c "busy");
798 if [ \\\$busy -ne 0 ] ; then
799     echo "$mnt is still busy, wait one second" && sleep 1;
800     umount $force $mnt;
801 fi
802 fi"
803 }
804
805 shudown_node_hard () {
806     local host=$1
807     local attempts=3
808
809     for i in $(seq $attempts) ; do
810         $POWER_DOWN $host
811         sleep 1
812         ping -w 3 -c 1 $host > /dev/null 2>&1 || return 0
813         echo "waiting for $host to fail attempts=$attempts"
814         [ $i -lt $attempts ] || \
815             { echo "$host still pingable after power down! attempts=$attempts" && return 1; } 
816     done
817 }
818
819 shutdown_client() {
820     local client=$1
821     local mnt=${2:-$MOUNT}
822     local attempts=3
823
824     if [ "$FAILURE_MODE" = HARD ]; then
825         shudown_node_hard $client 
826     else
827        zconf_umount_clients $client $mnt -f
828     fi
829 }
830
831 shutdown_facet() {
832     local facet=$1
833     if [ "$FAILURE_MODE" = HARD ]; then
834         shudown_node_hard $(facet_active_host $facet)
835     elif [ "$FAILURE_MODE" = SOFT ]; then
836         stop $facet
837     fi
838 }
839
840 reboot_facet() {
841     facet=$1
842     if [ "$FAILURE_MODE" = HARD ]; then
843         $POWER_UP `facet_active_host $facet`
844     else
845         sleep 10
846     fi
847 }
848
849 boot_node() {
850     local node=$1
851     if [ "$FAILURE_MODE" = HARD ]; then
852        $POWER_UP $node
853        wait_for_host $node
854     fi
855 }
856
857 # recovery-scale functions
858 check_progs_installed () {
859     local clients=$1
860     shift
861     local progs=$@
862
863     do_nodes $clients "PATH=:$PATH; status=true;
864 for prog in $progs; do
865     if ! [ \\\"\\\$(which \\\$prog)\\\"  -o  \\\"\\\${!prog}\\\" ]; then
866        echo \\\$prog missing on \\\$(hostname);
867        status=false;
868     fi
869 done;
870 eval \\\$status"
871 }
872
873 client_var_name() {
874     echo __$(echo $1 | tr '-' 'X')
875 }
876
877 start_client_load() {
878     local client=$1
879     local load=$2
880     local var=$(client_var_name $client)_load
881     eval export ${var}=$load
882
883     do_node $client "PATH=$PATH MOUNT=$MOUNT ERRORS_OK=$ERRORS_OK \
884                               BREAK_ON_ERROR=$BREAK_ON_ERROR \
885                               END_RUN_FILE=$END_RUN_FILE \
886                               LOAD_PID_FILE=$LOAD_PID_FILE \
887                               TESTSUITELOG=$TESTSUITELOG \
888                               run_${load}.sh" &
889     CLIENT_LOAD_PIDS="$CLIENT_LOAD_PIDS $!"
890     log "Started client load: ${load} on $client"
891
892     return 0
893 }
894
895 start_client_loads () {
896     local -a clients=(${1//,/ })
897     local numloads=${#CLIENT_LOADS[@]}
898     local testnum
899
900     for ((nodenum=0; nodenum < ${#clients[@]}; nodenum++ )); do
901         testnum=$((nodenum % numloads))
902         start_client_load ${clients[nodenum]} ${CLIENT_LOADS[testnum]}
903     done
904 }
905
906 # only for remote client 
907 check_client_load () {
908     local client=$1
909     local var=$(client_var_name $client)_load
910     local TESTLOAD=run_${!var}.sh
911
912     ps auxww | grep -v grep | grep $client | grep -q "$TESTLOAD" || return 1
913     
914     # bug 18914: try to connect several times not only when
915     # check ps, but  while check_catastrophe also
916     local tries=3
917     local RC=254
918     while [ $RC = 254 -a $tries -gt 0 ]; do
919         let tries=$tries-1
920         # assume success
921         RC=0
922         if ! check_catastrophe $client; then
923             RC=${PIPESTATUS[0]}
924             if [ $RC -eq 254 ]; then
925                 # FIXME: not sure how long we shuold sleep here
926                 sleep 10
927                 continue
928             fi
929             echo "check catastrophe failed: RC=$RC "
930             return $RC
931         fi
932     done
933     # We can continue try to connect if RC=254
934     # Just print the warning about this
935     if [ $RC = 254 ]; then
936         echo "got a return status of $RC from do_node while checking catastrophe on $client"
937     fi
938
939     # see if the load is still on the client
940     tries=3
941     RC=254
942     while [ $RC = 254 -a $tries -gt 0 ]; do
943         let tries=$tries-1
944         # assume success
945         RC=0
946         if ! do_node $client "ps auxwww | grep -v grep | grep -q $TESTLOAD"; then
947             RC=${PIPESTATUS[0]}
948             sleep 30
949         fi
950     done
951     if [ $RC = 254 ]; then
952         echo "got a return status of $RC from do_node while checking (catastrophe and 'ps') the client load on $client"
953         # see if we can diagnose a bit why this is
954     fi
955
956     return $RC
957 }
958 check_client_loads () {
959    local clients=${1//,/ }
960    local client=
961    local rc=0
962
963    for client in $clients; do
964       check_client_load $client
965       rc=${PIPESTATUS[0]}
966       if [ "$rc" != 0 ]; then
967         log "Client load failed on node $client, rc=$rc"
968         return $rc
969       fi
970    done
971 }
972
973 restart_client_loads () {
974     local clients=${1//,/ }
975     local expectedfail=${2:-""}
976     local client=
977     local rc=0
978
979     for client in $clients; do
980         check_client_load $client
981         rc=${PIPESTATUS[0]}
982         if [ "$rc" != 0 -a "$expectedfail" ]; then
983             local var=$(client_var_name $client)_load
984             start_client_load $client ${!var}
985             echo "Restarted client load ${!var}: on $client. Checking ..."
986             check_client_load $client
987             rc=${PIPESTATUS[0]}
988             if [ "$rc" != 0 ]; then
989                 log "Client load failed to restart on node $client, rc=$rc"
990                 # failure one client load means test fail
991                 # we do not need to check other 
992                 return $rc
993             fi
994         else
995             return $rc
996         fi
997     done
998 }
999 # End recovery-scale functions
1000
1001 # verify that lustre actually cleaned up properly
1002 cleanup_check() {
1003     [ -f $CATASTROPHE ] && [ `cat $CATASTROPHE` -ne 0 ] && \
1004         error "LBUG/LASSERT detected"
1005     BUSY=`dmesg | grep -i destruct || true`
1006     if [ "$BUSY" ]; then
1007         echo "$BUSY" 1>&2
1008         [ -e $TMP/debug ] && mv $TMP/debug $TMP/debug-busy.`date +%s`
1009         exit 205
1010     fi
1011
1012     check_mem_leak || exit 204
1013
1014     [ "`lctl dl 2> /dev/null | wc -l`" -gt 0 ] && lctl dl && \
1015         echo "$0: lustre didn't clean up..." 1>&2 && return 202 || true
1016
1017     if module_loaded lnet || module_loaded libcfs; then
1018         echo "$0: modules still loaded..." 1>&2
1019         /sbin/lsmod 1>&2
1020         return 203
1021     fi
1022     return 0
1023 }
1024
1025 wait_update () {
1026     local node=$1
1027     local TEST=$2
1028     local FINAL=$3
1029     local MAX=${4:-90}
1030
1031         local RESULT
1032         local WAIT=0
1033         local sleep=5
1034         while [ true ]; do
1035             RESULT=$(do_node $node "$TEST")
1036             if [ "$RESULT" == "$FINAL" ]; then
1037                 echo "Updated after $WAIT sec: wanted '$FINAL' got '$RESULT'"
1038                 return 0
1039             fi
1040             [ $WAIT -ge $MAX ] && break
1041             echo "Waiting $((MAX - WAIT)) secs for update"
1042             WAIT=$((WAIT + sleep))
1043             sleep $sleep
1044         done
1045         echo "Update not seen after $MAX sec: wanted '$FINAL' got '$RESULT'"
1046         return 3
1047 }
1048
1049 wait_update_facet () {
1050     local facet=$1
1051     wait_update  $(facet_active_host $facet) "$@"
1052 }
1053
1054 wait_delete_completed () {
1055     local TOTALPREV=`lctl get_param -n osc.*.kbytesavail | \
1056                      awk 'BEGIN{total=0}; {total+=$1}; END{print total}'`
1057
1058     local WAIT=0
1059     local MAX_WAIT=20
1060     while [ "$WAIT" -ne "$MAX_WAIT" ]; do
1061         sleep 1
1062         TOTAL=`lctl get_param -n osc.*.kbytesavail | \
1063                awk 'BEGIN{total=0}; {total+=$1}; END{print total}'`
1064         [ "$TOTAL" -eq "$TOTALPREV" ] && return 0
1065         echo "Waiting delete completed ... prev: $TOTALPREV current: $TOTAL "
1066         TOTALPREV=$TOTAL
1067         WAIT=$(( WAIT + 1))
1068     done
1069     echo "Delete is not completed in $MAX_WAIT sec"
1070     return 1
1071 }
1072
1073 wait_for_host() {
1074     local host=$1
1075     check_network "$host" 900
1076     while ! do_node $host hostname  > /dev/null; do sleep 5; done
1077 }
1078
1079 wait_for() {
1080     local facet=$1
1081     local host=`facet_active_host $facet`
1082     wait_for_host $host
1083 }
1084
1085 wait_recovery_complete () {
1086     local facet=$1
1087
1088     # Use default policy if $2 is not passed by caller.
1089     #define OBD_RECOVERY_TIMEOUT (obd_timeout * 5 / 2)
1090     # as we are in process of changing obd_timeout in different ways
1091     # let's set MAX longer than that
1092     local MAX=${2:-$(( TIMEOUT * 4 ))}
1093
1094     local var_svc=${facet}_svc
1095     local procfile="*.${!var_svc}.recovery_status"
1096     local WAIT=0
1097     local STATUS=
1098
1099     while [ $WAIT -lt $MAX ]; do
1100         STATUS=$(do_facet $facet lctl get_param -n $procfile | grep status)
1101         [[ $STATUS = "status: COMPLETE" ]] && return 0
1102         sleep 5
1103         WAIT=$((WAIT + 5))
1104         echo "Waiting $((MAX - WAIT)) secs for $facet recovery done. $STATUS"
1105     done
1106     echo "$facet recovery not done in $MAX sec. $STATUS"
1107     return 1
1108 }
1109
1110 wait_mds_ost_sync () {
1111     # just because recovery is done doesn't mean we've finished
1112     # orphan cleanup. Wait for llogs to get synchronized.
1113     echo "Waiting for orphan cleanup..."
1114     # MAX value includes time needed for MDS-OST reconnection
1115     local MAX=$(( TIMEOUT * 2 ))
1116     local WAIT=0
1117     while [ $WAIT -lt $MAX ]; do
1118         local -a sync=($(do_nodes $(comma_list $(osts_nodes)) \
1119             "$LCTL get_param -n obdfilter.*.mds_sync"))
1120         local con=1
1121         for ((i=0; i<${#sync[@]}; i++)); do
1122             [ ${sync[$i]} -eq 0 ] && continue
1123             # there is a not finished MDS-OST synchronization
1124             con=0
1125             break;
1126         done
1127         sleep 2 # increase waiting time and cover statfs cache
1128         [ ${con} -eq 1 ] && return 0
1129         echo "Waiting $WAIT secs for $facet mds-ost sync done."
1130         WAIT=$((WAIT + 2))
1131     done
1132     echo "$facet recovery not done in $MAX sec. $STATUS"
1133     return 1
1134 }
1135
1136 wait_destroy_complete () {
1137     echo "Waiting for destroy to be done..."
1138     # MAX value shouldn't be big as this mean server responsiveness
1139     # never increase this just to make test pass but investigate
1140     # why it takes so long time
1141     local MAX=5
1142     local WAIT=0
1143     while [ $WAIT -lt $MAX ]; do
1144         local -a RPCs=($($LCTL get_param -n osc.*.destroys_in_flight))
1145         local con=1
1146         for ((i=0; i<${#RPCs[@]}; i++)); do
1147             [ ${RPCs[$i]} -eq 0 ] && continue
1148             # there are still some destroy RPCs in flight
1149             con=0
1150             break;
1151         done
1152         sleep 1
1153         [ ${con} -eq 1 ] && return 0 # done waiting
1154         echo "Waiting $WAIT secs for destroys to be done."
1155         WAIT=$((WAIT + 1))
1156     done
1157     echo "Destroys weren't done in $MAX sec."
1158     return 1
1159 }
1160
1161 wait_exit_ST () {
1162     local facet=$1
1163
1164     local WAIT=0
1165     local INTERVAL=1
1166     local running
1167     # conf-sanity 31 takes a long time cleanup
1168     while [ $WAIT -lt 300 ]; do
1169         running=$(do_facet ${facet} "lsmod | grep lnet > /dev/null && lctl dl | grep ' ST '") || true
1170         [ -z "${running}" ] && return 0
1171         echo "waited $WAIT for${running}"
1172         [ $INTERVAL -lt 64 ] && INTERVAL=$((INTERVAL + INTERVAL))
1173         sleep $INTERVAL
1174         WAIT=$((WAIT + INTERVAL))
1175     done
1176     echo "service didn't stop after $WAIT seconds.  Still running:"
1177     echo ${running}
1178     return 1
1179 }
1180
1181 wait_remote_prog () {
1182    local prog=$1
1183    local WAIT=0
1184    local INTERVAL=5
1185    local rc=0
1186
1187    [ "$PDSH" = "no_dsh" ] && return 0
1188
1189    while [ $WAIT -lt $2 ]; do
1190         running=$(ps uax | grep "$PDSH.*$prog.*$MOUNT" | grep -v grep) || true
1191         [ -z "${running}" ] && return 0 || true
1192         echo "waited $WAIT for: "
1193         echo "$running"
1194         [ $INTERVAL -lt 60 ] && INTERVAL=$((INTERVAL + INTERVAL))
1195         sleep $INTERVAL
1196         WAIT=$((WAIT + INTERVAL))
1197     done
1198     local pids=$(ps  uax | grep "$PDSH.*$prog.*$MOUNT" | grep -v grep | awk '{print $2}')
1199     [ -z "$pids" ] && return 0
1200     echo "$PDSH processes still exists after $WAIT seconds.  Still running: $pids"
1201     # FIXME: not portable
1202     for pid in $pids; do
1203         cat /proc/${pid}/status || true
1204         cat /proc/${pid}/wchan || true
1205         echo "Killing $pid"
1206         kill -9 $pid || true
1207         sleep 1
1208         ps -P $pid && rc=1
1209     done
1210
1211     return $rc
1212 }
1213
1214 clients_up() {
1215     # not every config has many clients
1216     sleep 1
1217     if [ ! -z "$CLIENTS" ]; then
1218         $PDSH $CLIENTS "stat -f $MOUNT" > /dev/null
1219     else
1220         stat -f $MOUNT > /dev/null
1221     fi
1222 }
1223
1224 client_up() {
1225     local client=$1
1226     # usually checked on particular client or locally
1227     sleep 1
1228     if [ ! -z "$client" ]; then
1229         $PDSH $client "stat -f $MOUNT" > /dev/null
1230     else
1231         stat -f $MOUNT > /dev/null
1232     fi
1233 }
1234
1235 client_evicted() {
1236     ! client_up $1
1237 }
1238
1239 client_reconnect() {
1240     uname -n >> $MOUNT/recon
1241     if [ -z "$CLIENTS" ]; then
1242         df $MOUNT; uname -n >> $MOUNT/recon
1243     else
1244         do_nodes $CLIENTS "df $MOUNT; uname -n >> $MOUNT/recon" > /dev/null
1245     fi
1246     echo Connected clients:
1247     cat $MOUNT/recon
1248     ls -l $MOUNT/recon > /dev/null
1249     rm $MOUNT/recon
1250 }
1251
1252 facet_failover() {
1253     local facet=$1
1254     local sleep_time=$2
1255     echo "Failing $facet on node `facet_active_host $facet`"
1256     shutdown_facet $facet
1257     [ -n "$sleep_time" ] && sleep $sleep_time
1258     reboot_facet $facet
1259     change_active $facet
1260     local TO=`facet_active_host $facet`
1261     echo "Failover $facet to $TO"
1262     wait_for $facet
1263     mount_facet $facet || error "Restart of $facet failed"
1264 }
1265
1266 obd_name() {
1267     local facet=$1
1268 }
1269
1270 replay_barrier() {
1271     local facet=$1
1272     do_facet $facet sync
1273     df $MOUNT
1274     local svc=${facet}_svc
1275     do_facet $facet $LCTL --device %${!svc} notransno
1276     do_facet $facet $LCTL --device %${!svc} readonly
1277     do_facet $facet $LCTL mark "$facet REPLAY BARRIER on ${!svc}"
1278     $LCTL mark "local REPLAY BARRIER on ${!svc}"
1279 }
1280
1281 replay_barrier_nodf() {
1282     local facet=$1    echo running=${running}
1283     do_facet $facet sync
1284     local svc=${facet}_svc
1285     echo Replay barrier on ${!svc}
1286     do_facet $facet $LCTL --device %${!svc} notransno
1287     do_facet $facet $LCTL --device %${!svc} readonly
1288     do_facet $facet $LCTL mark "$facet REPLAY BARRIER on ${!svc}"
1289     $LCTL mark "local REPLAY BARRIER on ${!svc}"
1290 }
1291
1292 replay_barrier_nosync() {
1293     local facet=$1    echo running=${running}
1294     local svc=${facet}_svc
1295     echo Replay barrier on ${!svc}
1296     do_facet $facet $LCTL --device %${!svc} notransno
1297     do_facet $facet $LCTL --device %${!svc} readonly
1298     do_facet $facet $LCTL mark "$facet REPLAY BARRIER on ${!svc}"
1299     $LCTL mark "local REPLAY BARRIER on ${!svc}"
1300 }
1301
1302 mds_evict_client() {
1303     UUID=`lctl get_param -n mdc.${mds1_svc}-mdc-*.uuid`
1304     do_facet mds1 "lctl set_param -n mdt.${mds1_svc}.evict_client $UUID"
1305 }
1306
1307 ost_evict_client() {
1308     UUID=`lctl get_param -n devices| grep ${ost1_svc}-osc- | egrep -v 'MDT' | awk '{print $5}'`
1309     do_facet ost1 "lctl set_param -n obdfilter.${ost1_svc}.evict_client $UUID"
1310 }
1311
1312 fail() {
1313     facet_failover $* || error "failover: $?"
1314     clients_up || error "post-failover df: $?"
1315 }
1316
1317 fail_nodf() {
1318         local facet=$1
1319         facet_failover $facet
1320 }
1321
1322 fail_abort() {
1323     local facet=$1
1324     stop $facet
1325     change_active $facet
1326     mount_facet $facet -o abort_recovery
1327     clients_up || echo "first df failed: $?"
1328     clients_up || error "post-failover df: $?"
1329 }
1330
1331 do_lmc() {
1332     echo There is no lmc.  This is mountconf, baby.
1333     exit 1
1334 }
1335
1336 h2gm () {
1337     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
1338         ID=`$PDSH $1 $GMNALNID -l | cut -d\  -f2`
1339         echo $ID"@gm"
1340     fi
1341 }
1342
1343 h2name_or_ip() {
1344     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
1345         echo $1"@$2"
1346     fi
1347 }
1348
1349 h2ptl() {
1350    if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
1351        ID=`xtprocadmin -n $1 2>/dev/null | egrep -v 'NID' | awk '{print $1}'`
1352        if [ -z "$ID" ]; then
1353            echo "Could not get a ptl id for $1..."
1354            exit 1
1355        fi
1356        echo $ID"@ptl"
1357    fi
1358 }
1359 declare -fx h2ptl
1360
1361 h2tcp() {
1362     h2name_or_ip "$1" "tcp"
1363 }
1364 declare -fx h2tcp
1365
1366 h2elan() {
1367     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
1368         if type __h2elan >/dev/null 2>&1; then
1369             ID=$(__h2elan $1)
1370         else
1371             ID=`echo $1 | sed 's/[^0-9]*//g'`
1372         fi
1373         echo $ID"@elan"
1374     fi
1375 }
1376 declare -fx h2elan
1377
1378 h2openib() {
1379     h2name_or_ip "$1" "openib"
1380 }
1381 declare -fx h2openib
1382
1383 h2o2ib() {
1384     h2name_or_ip "$1" "o2ib"
1385 }
1386 declare -fx h2o2ib
1387
1388 facet_host() {
1389     local facet=$1
1390
1391     [ "$facet" == client ] && echo -n $HOSTNAME && return
1392     varname=${facet}_HOST
1393     if [ -z "${!varname}" ]; then
1394         if [ "${facet:0:3}" == "ost" ]; then
1395             eval ${facet}_HOST=${ost_HOST}
1396         fi
1397     fi
1398     echo -n ${!varname}
1399 }
1400
1401 facet_active() {
1402     local facet=$1
1403     local activevar=${facet}active
1404
1405     if [ -f $TMP/${facet}active ] ; then
1406         source $TMP/${facet}active
1407     fi
1408
1409     active=${!activevar}
1410     if [ -z "$active" ] ; then
1411         echo -n ${facet}
1412     else
1413         echo -n ${active}
1414     fi
1415 }
1416
1417 facet_active_host() {
1418     local facet=$1
1419     local active=`facet_active $facet`
1420     if [ "$facet" == client ]; then
1421         echo $HOSTNAME
1422     else
1423         echo `facet_host $active`
1424     fi
1425 }
1426
1427 change_active() {
1428     local facet=$1
1429     local failover=${facet}failover
1430     host=`facet_host $failover`
1431     [ -z "$host" ] && return
1432     local curactive=`facet_active $facet`
1433     if [ -z "${curactive}" -o "$curactive" == "$failover" ] ; then
1434         eval export ${facet}active=$facet
1435     else
1436         eval export ${facet}active=$failover
1437     fi
1438     # save the active host for this facet
1439     local activevar=${facet}active
1440     echo "$activevar=${!activevar}" > $TMP/$activevar
1441 }
1442
1443 do_node() {
1444     local verbose=false
1445     # do not stripe off hostname if verbose, bug 19215
1446     if [ x$1 = x--verbose ]; then
1447         shift
1448         verbose=true
1449     fi
1450
1451     local HOST=$1
1452     shift
1453     local myPDSH=$PDSH
1454     if [ "$HOST" = "$HOSTNAME" ]; then
1455         myPDSH="no_dsh"
1456     elif [ -z "$myPDSH" -o "$myPDSH" = "no_dsh" ]; then
1457         echo "cannot run remote command on $HOST with $myPDSH"
1458         return 128
1459     fi
1460     if $VERBOSE; then
1461         echo "CMD: $HOST $@" >&2
1462         $myPDSH $HOST $LCTL mark "$@" > /dev/null 2>&1 || :
1463     fi
1464
1465     if [ "$myPDSH" = "rsh" ]; then
1466 # we need this because rsh does not return exit code of an executed command
1467         local command_status="$TMP/cs"
1468         rsh $HOST ":> $command_status"
1469         rsh $HOST "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin;
1470                     cd $RPWD; LUSTRE=\"$RLUSTRE\" sh -c \"$@\") ||
1471                     echo command failed >$command_status"
1472         [ -n "$($myPDSH $HOST cat $command_status)" ] && return 1 || true
1473         return 0
1474     fi
1475
1476     if $verbose ; then
1477         # print HOSTNAME for myPDSH="no_dsh"
1478         if [[ $myPDSH = no_dsh ]]; then
1479             $myPDSH $HOST "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin; cd $RPWD; LUSTRE=\"$RLUSTRE\" sh -c \"$@\")" | sed -e "s/^/${HOSTNAME}: /"
1480         else
1481             $myPDSH $HOST "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin; cd $RPWD; LUSTRE=\"$RLUSTRE\" sh -c \"$@\")"
1482         fi
1483     else
1484         $myPDSH $HOST "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin; cd $RPWD; LUSTRE=\"$RLUSTRE\" sh -c \"$@\")" | sed "s/^${HOST}: //"
1485     fi
1486     return ${PIPESTATUS[0]}
1487 }
1488
1489 single_local_node () {
1490    [ "$1" = "$HOSTNAME" ]
1491 }
1492
1493 do_nodes() {
1494     local verbose=false
1495     # do not stripe off hostname if verbose, bug 19215
1496     if [ x$1 = x--verbose ]; then
1497         shift
1498         verbose=true
1499     fi
1500
1501     local rnodes=$1
1502     shift
1503
1504     if $(single_local_node $rnodes); then
1505         if $verbose; then
1506            do_node --verbose $rnodes $@
1507         else
1508            do_node $rnodes $@
1509         fi
1510         return $?
1511     fi
1512
1513     # This is part from do_node
1514     local myPDSH=$PDSH
1515
1516     [ -z "$myPDSH" -o "$myPDSH" = "no_dsh" -o "$myPDSH" = "rsh" ] && \
1517         echo "cannot run remote command on $rnodes with $myPDSH" && return 128
1518
1519     if $VERBOSE; then
1520         echo "CMD: $rnodes $@" >&2
1521         $myPDSH $rnodes $LCTL mark "$@" > /dev/null 2>&1 || :
1522     fi
1523
1524     if $verbose ; then
1525         $myPDSH $rnodes "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin; cd $RPWD; LUSTRE=\"$RLUSTRE\" sh -c \"$@\")"
1526     else
1527         $myPDSH $rnodes "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin; cd $RPWD; LUSTRE=\"$RLUSTRE\" sh -c \"$@\")" | sed -re "s/\w+:\s//g"
1528     fi
1529     return ${PIPESTATUS[0]}
1530 }
1531
1532 do_facet() {
1533     local facet=$1
1534     shift
1535     local HOST=`facet_active_host $facet`
1536     [ -z $HOST ] && echo No host defined for facet ${facet} && exit 1
1537     do_node $HOST "$@"
1538 }
1539
1540 add() {
1541     local facet=$1
1542     shift
1543     # make sure its not already running
1544     stop ${facet} -f
1545     rm -f $TMP/${facet}active
1546     do_facet ${facet} $MKFS $*
1547 }
1548
1549 ostdevname() {
1550     num=$1
1551     DEVNAME=OSTDEV$num
1552     #if $OSTDEVn isn't defined, default is $OSTDEVBASE + num
1553     eval DEVPTR=${!DEVNAME:=${OSTDEVBASE}${num}}
1554     echo -n $DEVPTR
1555 }
1556
1557 mdsdevname() {
1558     num=$1
1559     DEVNAME=MDSDEV$num
1560     #if $MDSDEVn isn't defined, default is $MDSDEVBASE + num
1561     eval DEVPTR=${!DEVNAME:=${MDSDEVBASE}${num}}
1562     echo -n $DEVPTR
1563 }
1564
1565 ########
1566 ## MountConf setup
1567
1568 stopall() {
1569     # make sure we are using the primary server, so test-framework will
1570     # be able to clean up properly.
1571     activemds=`facet_active mds1`
1572     if [ $activemds != "mds1" ]; then
1573         fail mds1
1574     fi
1575
1576     local clients=$CLIENTS
1577     [ -z $clients ] && clients=$(hostname)
1578
1579     zconf_umount_clients $clients $MOUNT "$*" || true
1580     [ -n "$MOUNT2" ] && zconf_umount_clients $clients $MOUNT2 "$*" || true
1581
1582     [ "$CLIENTONLY" ] && return
1583     # The add fn does rm ${facet}active file, this would be enough
1584     # if we use do_facet <facet> only after the facet added, but
1585     # currently we use do_facet mds in local.sh
1586     for num in `seq $MDSCOUNT`; do
1587         stop mds$num -f
1588         rm -f ${TMP}/mds${num}active
1589     done
1590
1591     for num in `seq $OSTCOUNT`; do
1592         stop ost$num -f
1593         rm -f $TMP/ost${num}active
1594     done
1595
1596     return 0
1597 }
1598
1599 cleanupall() {
1600     nfs_client_mode && return
1601
1602     stopall $*
1603     unload_modules
1604     cleanup_gss
1605 }
1606
1607 mdsmkfsopts()
1608 {
1609     local nr=$1
1610     test $nr = 1 && echo -n $MDS_MKFS_OPTS || echo -n $MDSn_MKFS_OPTS
1611 }
1612
1613 formatall() {
1614     if [ "$IAMDIR" == "yes" ]; then
1615         MDS_MKFS_OPTS="$MDS_MKFS_OPTS --iam-dir"
1616         MDSn_MKFS_OPTS="$MDSn_MKFS_OPTS --iam-dir"
1617     fi
1618
1619     [ "$FSTYPE" ] && FSTYPE_OPT="--backfstype $FSTYPE"
1620
1621     stopall
1622     # We need ldiskfs here, may as well load them all
1623     load_modules
1624     [ "$CLIENTONLY" ] && return
1625     echo Formatting mgs, mds, osts
1626     if [[ $MDSDEV1 != $MGSDEV ]] || [[ $mds1_HOST != $mgs_HOST ]]; then
1627         add mgs $mgs_MKFS_OPTS $FSTYPE_OPT --reformat $MGSDEV || exit 10
1628     fi
1629
1630     for num in `seq $MDSCOUNT`; do
1631         echo "Format mds$num: $(mdsdevname $num)"
1632         if $VERBOSE; then
1633             add mds$num `mdsmkfsopts $num` $FSTYPE_OPT --reformat `mdsdevname $num` || exit 9
1634         else
1635             add mds$num `mdsmkfsopts $num` $FSTYPE_OPT --reformat `mdsdevname $num` > /dev/null || exit 9
1636         fi
1637     done
1638
1639     for num in `seq $OSTCOUNT`; do
1640         echo "Format ost$num: $(ostdevname $num)"
1641         if $VERBOSE; then
1642             add ost$num $OST_MKFS_OPTS --reformat `ostdevname $num` || exit 10
1643         else
1644             add ost$num $OST_MKFS_OPTS --reformat `ostdevname $num` > /dev/null || exit 10
1645         fi
1646     done
1647 }
1648
1649 mount_client() {
1650     grep " $1 " /proc/mounts || zconf_mount $HOSTNAME $*
1651 }
1652
1653 umount_client() {
1654     grep " $1 " /proc/mounts && zconf_umount `hostname` $*
1655 }
1656
1657 # return value:
1658 # 0: success, the old identity set already.
1659 # 1: success, the old identity does not set.
1660 # 2: fail.
1661 switch_identity() {
1662     local num=$1
1663     local switch=$2
1664     local j=`expr $num - 1`
1665     local MDT="`(do_facet mds$num lctl get_param -N mdt.*MDT*$j 2>/dev/null | cut -d"." -f2 2>/dev/null) || true`"
1666
1667     if [ -z "$MDT" ]; then
1668         return 2
1669     fi
1670
1671     local old="`do_facet mds$num "lctl get_param -n mdt.$MDT.identity_upcall"`"
1672
1673     if $switch; then
1674         do_facet mds$num "lctl set_param -n mdt.$MDT.identity_upcall \"$L_GETIDENTITY\""
1675     else
1676         do_facet mds$num "lctl set_param -n mdt.$MDT.identity_upcall \"NONE\""
1677     fi
1678
1679     do_facet mds$num "lctl set_param -n mdt/$MDT/identity_flush \"-1\""
1680
1681     if [ $old = "NONE" ]; then
1682         return 1
1683     else
1684         return 0
1685     fi
1686 }
1687
1688 remount_client()
1689 {
1690         zconf_umount `hostname` $1 || error "umount failed"
1691         zconf_mount `hostname` $1 || error "mount failed"
1692 }
1693
1694 writeconf_facet () {
1695     local facet=$1
1696     local dev=$2
1697
1698     do_facet $facet "$TUNEFS --writeconf $dev"
1699 }
1700
1701 writeconf_all () {
1702     for num in `seq $MDSCOUNT`; do
1703         DEVNAME=$(mdsdevname $num)
1704         writeconf_facet mds$num $DEVNAME
1705     done
1706
1707     for num in `seq $OSTCOUNT`; do
1708         DEVNAME=$(ostdevname $num)
1709         writeconf_facet ost$num $DEVNAME
1710     done
1711 }
1712
1713 setupall() {
1714     nfs_client_mode && return
1715
1716     sanity_mount_check ||
1717         error "environments are insane!"
1718
1719     load_modules
1720
1721     if [ -z "$CLIENTONLY" ]; then
1722         echo Setup mgs, mdt, osts
1723         echo $WRITECONF | grep -q "writeconf" && \
1724             writeconf_all
1725         if [[ $mds1_HOST != $mgs_HOST ]] || [[ $MDSDEV1 != $MGSDEV ]]; then
1726             start mgs $MGSDEV $mgs_MOUNT_OPTS
1727         fi
1728
1729         for num in `seq $MDSCOUNT`; do
1730             DEVNAME=$(mdsdevname $num)
1731             start mds$num $DEVNAME $MDS_MOUNT_OPTS
1732
1733             # We started mds, now we should set failover variables properly.
1734             # Set mds${num}failover_HOST if it is not set (the default failnode).
1735             local varname=mds${num}failover_HOST
1736             if [ -z "${!varname}" ]; then
1737                 eval mds${num}failover_HOST=$(facet_host mds$num)
1738             fi
1739
1740             if [ $IDENTITY_UPCALL != "default" ]; then
1741                 switch_identity $num $IDENTITY_UPCALL
1742             fi
1743         done
1744         for num in `seq $OSTCOUNT`; do
1745             DEVNAME=$(ostdevname $num)
1746             start ost$num $DEVNAME $OST_MOUNT_OPTS
1747
1748             # We started ost$num, now we should set ost${num}failover variable properly.
1749             # Set ost${num}failover_HOST if it is not set (the default failnode).
1750             varname=ost${num}failover_HOST
1751             if [ -z "${!varname}" ]; then
1752                 eval ost${num}failover_HOST=$(facet_host ost${num})
1753             fi
1754
1755         done
1756     fi
1757
1758     init_gss
1759
1760     # wait a while to allow sptlrpc configuration be propogated to targets,
1761     # only needed when mounting new target devices.
1762     if $GSS; then
1763         sleep 10
1764     fi
1765
1766     [ "$DAEMONFILE" ] && $LCTL debug_daemon start $DAEMONFILE $DAEMONSIZE
1767     mount_client $MOUNT
1768     [ -n "$CLIENTS" ] && zconf_mount_clients $CLIENTS $MOUNT
1769
1770     if [ "$MOUNT_2" ]; then
1771         mount_client $MOUNT2
1772         [ -n "$CLIENTS" ] && zconf_mount_clients $CLIENTS $MOUNT2
1773     fi
1774
1775     init_param_vars
1776
1777     # by remounting mdt before ost, initial connect from mdt to ost might
1778     # timeout because ost is not ready yet. wait some time to its fully
1779     # recovery. initial obd_connect timeout is 5s; in GSS case it's preceeded
1780     # by a context negotiation rpc with $TIMEOUT.
1781     # FIXME better by monitoring import status.
1782     if $GSS; then
1783         set_flavor_all $SEC
1784         sleep $((TIMEOUT + 5))
1785     else
1786         sleep 5
1787     fi
1788 }
1789
1790 mounted_lustre_filesystems() {
1791         awk '($3 ~ "lustre" && $1 ~ ":") { print $2 }' /proc/mounts
1792 }
1793
1794 init_facet_vars () {
1795     [ "$CLIENTONLY" ] && return 0
1796     local facet=$1
1797     shift
1798     local device=$1
1799
1800     shift
1801
1802     eval export ${facet}_dev=${device}
1803     eval export ${facet}_opt=\"$@\"
1804
1805     local dev=${facet}_dev
1806     local label=$(do_facet ${facet} "$E2LABEL ${!dev}")
1807     [ -z "$label" ] && echo no label for ${!dev} && exit 1
1808
1809     eval export ${facet}_svc=${label}
1810
1811     local varname=${facet}failover_HOST
1812     if [ -z "${!varname}" ]; then
1813        eval $varname=$(facet_host $facet) 
1814     fi
1815
1816     # ${facet}failover_dev is set in cfg file
1817     varname=${facet}failover_dev
1818     if [ -n "${!varname}" ] ; then
1819         eval export ${facet}failover_dev=${!varname}
1820     else
1821         eval export ${facet}failover_dev=$device
1822     fi
1823 }
1824
1825 init_facets_vars () {
1826     local DEVNAME
1827
1828     if ! remote_mds_nodsh; then 
1829         for num in `seq $MDSCOUNT`; do
1830             DEVNAME=`mdsdevname $num`
1831             init_facet_vars mds$num $DEVNAME $MDS_MOUNT_OPTS
1832         done
1833     fi
1834
1835     remote_ost_nodsh && return
1836
1837     for num in `seq $OSTCOUNT`; do
1838         DEVNAME=`ostdevname $num`
1839         init_facet_vars ost$num $DEVNAME $OST_MOUNT_OPTS
1840     done
1841 }
1842
1843 osc_ensure_active () {
1844     local facet=$1
1845     local type=$2
1846     local timeout=$3
1847     local period=0
1848
1849     while [ $period -lt $timeout ]; do
1850         count=$(do_facet $facet "lctl dl | grep '${FSNAME}-OST.*-osc-${type}' | grep ' IN ' 2>/dev/null | wc -l")
1851         if [ $count -eq 0 ]; then
1852             break
1853         fi
1854
1855         echo "There are $count OST are inactive, wait $period seconds, and try again"
1856         sleep 3
1857         period=$((period+3))
1858     done
1859
1860     [ $period -lt $timeout ] || log "$count OST are inactive after $timeout seconds, give up"
1861 }
1862
1863 som_check() {
1864     SOM_ENABLED=$(do_facet $SINGLEMDS "$LCTL get_param mdt.*.som" | awk -F= ' {print $2}' | head -n 1)
1865     echo $SOM_ENABLED
1866 }
1867
1868 init_param_vars () {
1869     if ! remote_ost_nodsh && ! remote_mds_nodsh; then
1870         export MDSVER=$(do_facet $SINGLEMDS "lctl get_param version" | cut -d. -f1,2)
1871         export OSTVER=$(do_facet ost1 "lctl get_param version" | cut -d. -f1,2)
1872         export CLIVER=$(lctl get_param version | cut -d. -f 1,2)
1873     fi
1874
1875     remote_mds_nodsh ||
1876         TIMEOUT=$(do_facet $SINGLEMDS "lctl get_param -n timeout")
1877
1878     log "Using TIMEOUT=$TIMEOUT"
1879
1880     osc_ensure_active $SINGLEMDS M $TIMEOUT
1881     osc_ensure_active client c $TIMEOUT
1882
1883     if [ x"$(som_check)" = x"enabled" ]; then
1884         ENABLE_QUOTA=""
1885         echo "disable quota temporary when SOM enabled"
1886     fi
1887     if [ $QUOTA_AUTO -ne 0 ]; then
1888         if [ "$ENABLE_QUOTA" ]; then
1889             echo "enable quota as required"
1890             setup_quota $MOUNT || return 2
1891         else
1892             echo "disable quota as required"
1893             $LFS quotaoff -ug $MOUNT > /dev/null 2>&1
1894         fi
1895     fi
1896
1897     return 0
1898 }
1899
1900 nfs_client_mode () {
1901     if [ "$NFSCLIENT" ]; then
1902         echo "NFSCLIENT mode: setup, cleanup, check config skipped"
1903         local clients=$CLIENTS
1904         [ -z $clients ] && clients=$(hostname)
1905
1906         # FIXME: remove hostname when 19215 fixed
1907         do_nodes $clients "echo \\\$(hostname); grep ' '$MOUNT' ' /proc/mounts"
1908         declare -a nfsexport=(`grep ' '$MOUNT' ' /proc/mounts | awk '{print $1}' | awk -F: '{print $1 " "  $2}'`)
1909         do_nodes ${nfsexport[0]} "echo \\\$(hostname); df -T  ${nfsexport[1]}"
1910         return
1911     fi
1912     return 1
1913 }
1914
1915 check_config_client () {
1916     local mntpt=$1
1917
1918     local mounted=$(mount | grep " $mntpt ")
1919     if [ "$CLIENTONLY" ]; then
1920         # bug 18021
1921         # CLIENTONLY should not depend on *_HOST settings
1922         local mgc=$($LCTL device_list | awk '/MGC/ {print $4}')
1923         # in theory someone could create a new,
1924         # client-only config file that assumed lustre was already
1925         # configured and didn't set the MGSNID. If MGSNID is not set,
1926         # then we should use the mgs nid currently being used 
1927         # as the default value. bug 18021
1928         [[ x$MGSNID = x ]] &&
1929             MGSNID=${mgc//MGC/}
1930
1931         if [[ x$mgc != xMGC$MGSNID ]]; then
1932             if [ "$mgs_HOST" ]; then
1933                 local mgc_ip=$(ping -q -c1 -w1 $mgs_HOST | grep PING | awk '{print $3}' | sed -e "s/(//g" -e "s/)//g")
1934 #                [[ x$mgc = xMGC$mgc_ip@$NETTYPE ]] ||
1935 #                    error_exit "MGSNID=$MGSNID, mounted: $mounted, MGC : $mgc"
1936             fi
1937         fi
1938         return 0
1939     fi
1940
1941     local myMGS_host=$mgs_HOST   
1942     if [ "$NETTYPE" = "ptl" ]; then
1943         myMGS_host=$(h2ptl $mgs_HOST | sed -e s/@ptl//) 
1944     fi
1945
1946     echo Checking config lustre mounted on $mntpt
1947     local mgshost=$(mount | grep " $mntpt " | awk -F@ '{print $1}')
1948     mgshost=$(echo $mgshost | awk -F: '{print $1}')
1949
1950 #    if [ "$mgshost" != "$myMGS_host" ]; then
1951 #            log "Bad config file: lustre is mounted with mgs $mgshost, but mgs_HOST=$mgs_HOST, NETTYPE=$NETTYPE
1952 #                   Please use correct config or set mds_HOST correctly!"
1953 #    fi
1954
1955 }
1956
1957 check_config_clients () {
1958     local clients=${CLIENTS:-$HOSTNAME}
1959     local mntpt=$1
1960
1961     nfs_client_mode && return
1962
1963     do_rpc_nodes $clients check_config_client $mntpt
1964
1965     sanity_mount_check ||
1966         error "environments are insane!"
1967 }
1968
1969 check_timeout () {
1970     local mdstimeout=$(do_facet $SINGLEMDS "lctl get_param -n timeout")
1971     local cltimeout=$(lctl get_param -n timeout)
1972     if [ $mdstimeout -ne $TIMEOUT ] || [ $mdstimeout -ne $cltimeout ]; then
1973         error "timeouts are wrong! mds: $mdstimeout, client: $cltimeout, TIMEOUT=$TIMEOUT"
1974         return 1
1975     fi
1976 }
1977
1978 is_mounted () {
1979     local mntpt=$1
1980     local mounted=$(mounted_lustre_filesystems)
1981
1982     echo $mounted' ' | grep -w -q $mntpt' '
1983 }
1984
1985 check_and_setup_lustre() {
1986     nfs_client_mode && return
1987
1988     local MOUNTED=$(mounted_lustre_filesystems)
1989
1990     local do_check=true
1991     # 1.
1992     # both MOUNT and MOUNT2 are not mounted
1993     if ! is_mounted $MOUNT && ! is_mounted $MOUNT2; then
1994         [ "$REFORMAT" ] && formatall
1995         # setupall mounts both MOUNT and MOUNT2 (if MOUNT_2 is set)
1996         setupall
1997         is_mounted $MOUNT || error "NAME=$NAME not mounted"
1998         export I_MOUNTED=yes
1999         do_check=false
2000     # 2.
2001     # MOUNT2 is mounted
2002     elif is_mounted $MOUNT2; then
2003             # 3.
2004             # MOUNT2 is mounted, while MOUNT_2 is not set
2005             if ! [ "$MOUNT_2" ]; then
2006                 cleanup_mount $MOUNT2
2007                 export I_UMOUNTED2=yes
2008
2009             # 4.
2010             # MOUNT2 is mounted, MOUNT_2 is set
2011             else
2012                 # FIXME: what to do if check_config failed?
2013                 # i.e. if:
2014                 # 1) remote client has mounted other Lustre fs ?
2015                 # 2) it has insane env ?
2016                 # let's try umount MOUNT2 on all clients and mount it again:
2017                 if ! check_config_clients $MOUNT2; then
2018                     cleanup_mount $MOUNT2
2019                     restore_mount $MOUNT2
2020                     export I_MOUNTED2=yes
2021                 fi
2022             fi 
2023
2024     # 5.
2025     # MOUNT is mounted MOUNT2 is not mounted
2026     elif [ "$MOUNT_2" ]; then
2027         restore_mount $MOUNT2
2028         export I_MOUNTED2=yes
2029     fi
2030
2031     if $do_check; then
2032         # FIXME: what to do if check_config failed?
2033         # i.e. if:
2034         # 1) remote client has mounted other Lustre fs?
2035         # 2) lustre is mounted on remote_clients atall ?
2036         check_config_clients $MOUNT
2037         init_facets_vars
2038         init_param_vars
2039
2040         do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=\\\"$PTLDEBUG\\\";
2041             lctl set_param subsystem_debug=\\\"${SUBSYSTEM# }\\\";
2042             lctl set_param debug_mb=${DEBUG_SIZE};
2043             sync"
2044     fi
2045
2046     init_gss
2047     set_flavor_all $SEC
2048
2049     if [ "$ONLY" == "setup" ]; then
2050         exit 0
2051     fi
2052 }
2053
2054 restore_mount () {
2055    local clients=${CLIENTS:-$HOSTNAME}
2056    local mntpt=$1
2057
2058    zconf_mount_clients $clients $mntpt
2059 }
2060
2061 cleanup_mount () {
2062     local clients=${CLIENTS:-$HOSTNAME}
2063     local mntpt=$1
2064
2065     zconf_umount_clients $clients $mntpt    
2066 }
2067
2068 cleanup_and_setup_lustre() {
2069     if [ "$ONLY" == "cleanup" -o "`mount | grep $MOUNT`" ]; then
2070         lctl set_param debug=0 || true
2071         cleanupall
2072         if [ "$ONLY" == "cleanup" ]; then
2073             exit 0
2074         fi
2075     fi
2076     check_and_setup_lustre
2077 }
2078
2079 check_and_cleanup_lustre() {
2080     if is_mounted $MOUNT; then
2081         [ -n "$DIR" ] && rm -rf $DIR/[Rdfs][0-9]*
2082         [ "$ENABLE_QUOTA" ] && restore_quota_type || true
2083     fi
2084
2085     if [ "$I_UMOUNTED2" = "yes" ]; then
2086         restore_mount $MOUNT2 || error "restore $MOUNT2 failed"
2087     fi
2088
2089     if [ "$I_MOUNTED2" = "yes" ]; then
2090         cleanup_mount $MOUNT2
2091     fi
2092
2093     if [ "$I_MOUNTED" = "yes" ]; then
2094         cleanupall -f || error "cleanup failed"
2095         unset I_MOUNTED
2096     fi
2097 }
2098
2099 #######
2100 # General functions
2101
2102 check_network() {
2103     local NETWORK=0
2104     local WAIT=0
2105     local MAX=$2
2106     while [ $NETWORK -eq 0 ]; do
2107         if ping -c 1 -w 3 $1 > /dev/null; then
2108             NETWORK=1
2109         else
2110             WAIT=$((WAIT + 5))
2111             echo "waiting for $1, $((MAX - WAIT)) secs left"
2112             sleep 5
2113         fi
2114         if [ $WAIT -gt $MAX ]; then
2115             echo "Network not available"
2116             exit 1
2117         fi
2118     done
2119 }
2120 check_port() {
2121     while( !($DSH2 $1 "netstat -tna | grep -q $2") ) ; do
2122         sleep 9
2123     done
2124 }
2125
2126 no_dsh() {
2127     shift
2128     eval $@
2129 }
2130
2131 comma_list() {
2132     # the sed converts spaces to commas, but leaves the last space
2133     # alone, so the line doesn't end with a comma.
2134     echo "$*" | tr -s " " "\n" | sort -b -u | tr "\n" " " | sed 's/ \([^$]\)/,\1/g'
2135 }
2136
2137 # list, excluded are the comma separated lists
2138 exclude_items_from_list () {
2139     local list=$1
2140     local excluded=$2
2141     local item
2142
2143     list=${list//,/ }
2144     for item in ${excluded//,/ }; do
2145         list=$(echo " $list " | sed -re "s/\s+$item\s+/ /g")
2146     done
2147     echo $(comma_list $list) 
2148 }
2149
2150 # list, expand  are the comma separated lists
2151 expand_list () {
2152     local list=${1//,/ }
2153     local expand=${2//,/ }
2154     local expanded=
2155
2156     expanded=$(for i in $list $expand; do echo $i; done | sort -u)
2157     echo $(comma_list $expanded)
2158 }
2159
2160 testslist_filter () {
2161     local script=$LUSTRE/tests/${TESTSUITE}.sh
2162
2163     [ -f $script ] || return 0
2164
2165     local start_at=$START_AT
2166     local stop_at=$STOP_AT
2167
2168     local var=${TESTSUITE//-/_}_START_AT
2169     [ x"${!var}" != x ] && start_at=${!var}
2170     var=${TESTSUITE//-/_}_STOP_AT
2171     [ x"${!var}" != x ] && stop_at=${!var}
2172
2173     sed -n 's/^test_\([^ (]*\).*/\1/p' $script | \
2174         awk ' BEGIN { if ("'${start_at:-0}'" != 0) flag = 1 }
2175             /^'${start_at}'$/ {flag = 0}
2176             {if (flag == 1) print $0}
2177             /^'${stop_at}'$/ { flag = 1 }'
2178 }
2179
2180 absolute_path() {
2181     (cd `dirname $1`; echo $PWD/`basename $1`)
2182 }
2183
2184 get_facets () {
2185     local name=$(echo $1 | tr "[:upper:]" "[:lower:]")
2186     local type=$(echo $1 | tr "[:lower:]" "[:upper:]")
2187
2188     local list=""
2189     local count=${type}COUNT
2190     for ((i=1; i<=${!count}; i++)) do
2191         list="$list ${name}$i"
2192     done
2193     echo $(comma_list $list)
2194 }
2195
2196 ##################################
2197 # Adaptive Timeouts funcs
2198
2199 at_is_enabled() {
2200     # only check mds, we assume at_max is the same on all nodes
2201     local at_max=$(do_facet $SINGLEMDS "lctl get_param -n at_max")
2202     if [ $at_max -eq 0 ]; then
2203         return 1
2204     else
2205         return 0
2206     fi
2207 }
2208
2209 at_max_get() {
2210     local facet=$1
2211
2212     # suppose that all ost-s has the same at_max set
2213     if [ $facet == "ost" ]; then
2214         do_facet ost1 "lctl get_param -n at_max"
2215     else
2216         do_facet $facet "lctl get_param -n at_max"
2217     fi
2218 }
2219
2220 at_max_set() {
2221     local at_max=$1
2222     shift
2223
2224     local facet
2225     for facet in $@; do
2226         if [ $facet == "ost" ]; then
2227             for i in `seq $OSTCOUNT`; do
2228                 do_facet ost$i "lctl set_param at_max=$at_max"
2229
2230             done
2231         elif [ $facet == "mds" ]; then
2232             for i in `seq $MDSCOUNT`; do
2233                 do_facet mds$i "lctl set_param at_max=$at_max"
2234             done
2235         else
2236             do_facet $facet "lctl set_param at_max=$at_max"
2237         fi
2238     done
2239 }
2240
2241 ##################################
2242 # OBD_FAIL funcs
2243
2244 drop_request() {
2245 # OBD_FAIL_MDS_ALL_REQUEST_NET
2246     RC=0
2247     do_facet $SINGLEMDS lctl set_param fail_loc=0x123
2248     do_facet client "$1" || RC=$?
2249     do_facet $SINGLEMDS lctl set_param fail_loc=0
2250     return $RC
2251 }
2252
2253 drop_reply() {
2254 # OBD_FAIL_MDS_ALL_REPLY_NET
2255     RC=0
2256     do_facet $SINGLEMDS lctl set_param fail_loc=0x122
2257     do_facet client "$@" || RC=$?
2258     do_facet $SINGLEMDS lctl set_param fail_loc=0
2259     return $RC
2260 }
2261
2262 drop_reint_reply() {
2263 # OBD_FAIL_MDS_REINT_NET_REP
2264     RC=0
2265     do_facet $SINGLEMDS lctl set_param fail_loc=0x119
2266     do_facet client "$@" || RC=$?
2267     do_facet $SINGLEMDS lctl set_param fail_loc=0
2268     return $RC
2269 }
2270
2271 pause_bulk() {
2272 #define OBD_FAIL_OST_BRW_PAUSE_BULK      0x214
2273     RC=0
2274     do_facet ost1 lctl set_param fail_loc=0x214
2275     do_facet client "$1" || RC=$?
2276     do_facet client "sync"
2277     do_facet ost1 lctl set_param fail_loc=0
2278     return $RC
2279 }
2280
2281 drop_ldlm_cancel() {
2282 #define OBD_FAIL_LDLM_CANCEL             0x304
2283     RC=0
2284     do_facet client lctl set_param fail_loc=0x304
2285     do_facet client "$@" || RC=$?
2286     do_facet client lctl set_param fail_loc=0
2287     return $RC
2288 }
2289
2290 drop_bl_callback() {
2291 #define OBD_FAIL_LDLM_BL_CALLBACK        0x305
2292     RC=0
2293     do_facet client lctl set_param fail_loc=0x305
2294     do_facet client "$@" || RC=$?
2295     do_facet client lctl set_param fail_loc=0
2296     return $RC
2297 }
2298
2299 drop_ldlm_reply() {
2300 #define OBD_FAIL_LDLM_REPLY              0x30c
2301     RC=0
2302     do_facet $SINGLEMDS lctl set_param fail_loc=0x30c
2303     do_facet client "$@" || RC=$?
2304     do_facet $SINGLEMDS lctl set_param fail_loc=0
2305     return $RC
2306 }
2307
2308 clear_failloc() {
2309     facet=$1
2310     pause=$2
2311     sleep $pause
2312     echo "clearing fail_loc on $facet"
2313     do_facet $facet "lctl set_param fail_loc=0 2>/dev/null || true"
2314 }
2315
2316 set_nodes_failloc () {
2317     do_nodes $(comma_list $1)  lctl set_param fail_loc=$2
2318 }
2319
2320 cancel_lru_locks() {
2321     $LCTL mark "cancel_lru_locks $1 start"
2322     for d in `lctl get_param -N ldlm.namespaces.*.lru_size | egrep -i $1`; do
2323         $LCTL set_param -n $d=clear
2324     done
2325     $LCTL get_param ldlm.namespaces.*.lock_unused_count | egrep -i $1 | grep -v '=0'
2326     $LCTL mark "cancel_lru_locks $1 stop"
2327 }
2328
2329 default_lru_size()
2330 {
2331         NR_CPU=$(grep -c "processor" /proc/cpuinfo)
2332         DEFAULT_LRU_SIZE=$((100 * NR_CPU))
2333         echo "$DEFAULT_LRU_SIZE"
2334 }
2335
2336 lru_resize_enable()
2337 {
2338     lctl set_param ldlm.namespaces.*$1*.lru_size=0
2339 }
2340
2341 lru_resize_disable()
2342 {
2343     lctl set_param ldlm.namespaces.*$1*.lru_size $(default_lru_size)
2344 }
2345
2346 pgcache_empty() {
2347     local FILE
2348     for FILE in `lctl get_param -N "llite.*.dump_page_cache"`; do
2349         if [ `lctl get_param -n $FILE | wc -l` -gt 1 ]; then
2350             echo there is still data in page cache $FILE ?
2351             lctl get_param -n $FILE
2352             return 1
2353         fi
2354     done
2355     if [[ $MDSDEV1 != $MGSDEV ]]; then
2356         stop mgs 
2357     fi
2358
2359     return 0
2360 }
2361
2362 debugsave() {
2363     DEBUGSAVE="$(lctl get_param -n debug)"
2364 }
2365
2366 debugrestore() {
2367     [ -n "$DEBUGSAVE" ] && \
2368         do_nodes $(comma_list $(nodes_list)) "$LCTL set_param debug=\\\"${DEBUGSAVE}\\\";"
2369     DEBUGSAVE=""
2370 }
2371
2372 debug_size_save() {
2373     DEBUG_SIZE_SAVED="$(lctl get_param -n debug_mb)"
2374 }
2375
2376 debug_size_restore() {
2377     [ -n "$DEBUG_SIZE_SAVED" ] && \
2378         do_nodes $(comma_list $(nodes_list)) "$LCTL set_param debug_mb=$DEBUG_SIZE_SAVED"
2379     DEBUG_SIZE_SAVED=""
2380 }
2381
2382 start_full_debug_logging() {
2383     debugsave
2384     debug_size_save
2385
2386     local FULLDEBUG=-1
2387     local DEBUG_SIZE=150
2388
2389     do_nodes $(comma_list $(nodes_list)) "$LCTL set_param debug_mb=$DEBUG_SIZE"
2390     do_nodes $(comma_list $(nodes_list)) "$LCTL set_param debug=$FULLDEBUG;"
2391 }
2392
2393 stop_full_debug_logging() {
2394     debug_size_restore
2395     debugrestore
2396 }
2397
2398 ##################################
2399 # Test interface
2400 ##################################
2401
2402 error_noexit() {
2403     local TYPE=${TYPE:-"FAIL"}
2404     local ERRLOG
2405
2406     local dump=true
2407     # do not dump logs if $1=false
2408     if [ "x$1" = "xfalse" ]; then
2409         shift
2410         dump=false
2411     fi
2412
2413     log " ${TESTSUITE} ${TESTNAME}: @@@@@@ ${TYPE}: $@ "
2414
2415     if $dump; then
2416         ERRLOG=$TMP/lustre_${TESTSUITE}_${TESTNAME}.$(date +%s)
2417         echo "Dumping lctl log to $ERRLOG"
2418         # We need to dump the logs on all nodes
2419         do_nodes $(comma_list $(nodes_list)) $NODE $LCTL dk $ERRLOG
2420     fi
2421     debugrestore
2422     [ "$TESTSUITELOG" ] && echo "$0: ${TYPE}: $TESTNAME $@" >> $TESTSUITELOG
2423     TEST_FAILED=true
2424 }
2425
2426 error() {
2427     error_noexit "$@"
2428     if $FAIL_ON_ERROR; then
2429         reset_fail_loc
2430         exit 1
2431     fi
2432 }
2433
2434 error_exit() {
2435     error_noexit "$@"
2436     exit 1
2437 }
2438
2439 # use only if we are ignoring failures for this test, bugno required.
2440 # (like ALWAYS_EXCEPT, but run the test and ignore the results.)
2441 # e.g. error_ignore 5494 "your message"
2442 error_ignore() {
2443     local TYPE="IGNORE (bz$1)"
2444     shift
2445     error_noexit "$@"
2446 }
2447
2448 skip_env () {
2449     $FAIL_ON_SKIP_ENV && error false $@ || skip $@
2450 }
2451
2452 skip () {
2453     echo
2454     log " SKIP: ${TESTSUITE} ${TESTNAME} $@"
2455     [ "$TESTSUITELOG" ] && \
2456         echo "${TESTSUITE}: SKIP: $TESTNAME $@" >> $TESTSUITELOG || true
2457 }
2458
2459 build_test_filter() {
2460     EXCEPT="$EXCEPT $(testslist_filter)"
2461
2462     [ "$ONLY" ] && log "only running test `echo $ONLY`"
2463     for O in $ONLY; do
2464         eval ONLY_${O}=true
2465     done
2466     [ "$EXCEPT$ALWAYS_EXCEPT" ] && \
2467         log "excepting tests: `echo $EXCEPT $ALWAYS_EXCEPT`"
2468     [ "$EXCEPT_SLOW" ] && \
2469         log "skipping tests SLOW=no: `echo $EXCEPT_SLOW`"
2470     for E in $EXCEPT $ALWAYS_EXCEPT; do
2471         eval EXCEPT_${E}=true
2472     done
2473     for E in $EXCEPT_SLOW; do
2474         eval EXCEPT_SLOW_${E}=true
2475     done
2476     for G in $GRANT_CHECK_LIST; do
2477         eval GCHECK_ONLY_${G}=true
2478         done
2479 }
2480
2481 basetest() {
2482     if [[ $1 = [a-z]* ]]; then
2483         echo $1
2484     else
2485         echo ${1%%[a-z]*}
2486     fi
2487 }
2488
2489 # print a newline if the last test was skipped
2490 export LAST_SKIPPED=
2491 run_test() {
2492     assert_DIR
2493
2494     export base=`basetest $1`
2495     if [ ! -z "$ONLY" ]; then
2496         testname=ONLY_$1
2497         if [ ${!testname}x != x ]; then
2498             [ "$LAST_SKIPPED" ] && echo "" && LAST_SKIPPED=
2499             run_one $1 "$2"
2500             return $?
2501         fi
2502         testname=ONLY_$base
2503         if [ ${!testname}x != x ]; then
2504             [ "$LAST_SKIPPED" ] && echo "" && LAST_SKIPPED=
2505             run_one $1 "$2"
2506             return $?
2507         fi
2508         LAST_SKIPPED="y"
2509         echo -n "."
2510         return 0
2511     fi
2512     testname=EXCEPT_$1
2513     if [ ${!testname}x != x ]; then
2514         LAST_SKIPPED="y"
2515         TESTNAME=test_$1 skip "skipping excluded test $1"
2516         return 0
2517     fi
2518     testname=EXCEPT_$base
2519     if [ ${!testname}x != x ]; then
2520         LAST_SKIPPED="y"
2521         TESTNAME=test_$1 skip "skipping excluded test $1 (base $base)"
2522         return 0
2523     fi
2524     testname=EXCEPT_SLOW_$1
2525     if [ ${!testname}x != x ]; then
2526         LAST_SKIPPED="y"
2527         TESTNAME=test_$1 skip "skipping SLOW test $1"
2528         return 0
2529     fi
2530     testname=EXCEPT_SLOW_$base
2531     if [ ${!testname}x != x ]; then
2532         LAST_SKIPPED="y"
2533         TESTNAME=test_$1 skip "skipping SLOW test $1 (base $base)"
2534         return 0
2535     fi
2536
2537     LAST_SKIPPED=
2538     run_one $1 "$2"
2539
2540     return $?
2541 }
2542
2543 EQUALS="======================================================================"
2544 equals_msg() {
2545     msg="$@"
2546
2547     local suffixlen=$((${#EQUALS} - ${#msg}))
2548     [ $suffixlen -lt 5 ] && suffixlen=5
2549     log `echo $(printf '===== %s %.*s\n' "$msg" $suffixlen $EQUALS)`
2550 }
2551
2552 log() {
2553     echo "$*"
2554     module_loaded lnet || load_modules
2555
2556     local MSG="$*"
2557     # Get rid of '
2558     MSG=${MSG//\'/\\\'}
2559     MSG=${MSG//\(/\\\(}
2560     MSG=${MSG//\)/\\\)}
2561     MSG=${MSG//\;/\\\;}
2562     MSG=${MSG//\|/\\\|}
2563     MSG=${MSG//\>/\\\>}
2564     MSG=${MSG//\</\\\<}
2565     MSG=${MSG//\//\\\/}
2566     do_nodes $(comma_list $(nodes_list)) $LCTL mark "$MSG" 2> /dev/null || true
2567 }
2568
2569 trace() {
2570         log "STARTING: $*"
2571         strace -o $TMP/$1.strace -ttt $*
2572         RC=$?
2573         log "FINISHED: $*: rc $RC"
2574         return 1
2575 }
2576
2577 pass() {
2578     $TEST_FAILED && echo -n "FAIL " || echo -n "PASS " 
2579     echo $@
2580 }
2581
2582 check_mds() {
2583     FFREE=$(do_node $SINGLEMDS lctl get_param -n osd.*MDT*.filesfree | awk 'BEGIN{avail=0}; {avail+=$1}; END{print avail}')
2584     FTOTAL=$(do_node $SINGLEMDS lctl get_param -n osd.*MDT*.filestotal | awk 'BEGIN{avail=0}; {avail+=$1}; END{print avail}')
2585     [ $FFREE -ge $FTOTAL ] && error "files free $FFREE > total $FTOTAL" || true
2586 }
2587
2588 reset_fail_loc () {
2589     echo -n "Resetting fail_loc on all nodes..."
2590     do_nodes $(comma_list $(nodes_list)) "lctl set_param -n fail_loc=0 2>/dev/null || true"
2591     echo done.
2592 }
2593
2594 run_one() {
2595     testnum=$1
2596     message=$2
2597     tfile=f${testnum}
2598     export tdir=d0.${TESTSUITE}/d${base}
2599
2600     local SAVE_UMASK=`umask`
2601     umask 0022
2602
2603     local BEFORE=`date +%s`
2604     echo
2605     log "== test $testnum: $message == `date +%H:%M:%S` ($BEFORE)"
2606     #check_mds
2607     export TESTNAME=test_$testnum
2608     TEST_FAILED=false
2609     test_${testnum} || error "test_$testnum failed with $?"
2610     #check_mds
2611     cd $SAVE_PWD
2612     reset_fail_loc
2613     check_grant ${testnum} || error "check_grant $testnum failed with $?"
2614     check_catastrophe || error "LBUG/LASSERT detected"
2615     ps auxww | grep -v grep | grep -q multiop && error "multiop still running"
2616     pass "($((`date +%s` - $BEFORE))s)"
2617     TEST_FAILED=false
2618     unset TESTNAME
2619     unset tdir
2620     umask $SAVE_UMASK
2621 }
2622
2623 canonical_path() {
2624     (cd `dirname $1`; echo $PWD/`basename $1`)
2625 }
2626
2627 sync_clients() {
2628     [ -d $DIR1 ] && cd $DIR1 && sync; sleep 1; sync
2629     [ -d $DIR2 ] && cd $DIR2 && sync; sleep 1; sync
2630         cd $SAVE_PWD
2631 }
2632
2633 check_grant() {
2634     export base=`basetest $1`
2635     [ "$CHECK_GRANT" == "no" ] && return 0
2636
2637         testname=GCHECK_ONLY_${base}
2638         [ ${!testname}x == x ] && return 0
2639
2640     echo -n "checking grant......"
2641         cd $SAVE_PWD
2642         # write some data to sync client lost_grant
2643         rm -f $DIR1/${tfile}_check_grant_* 2>&1
2644         for i in `seq $OSTCOUNT`; do
2645                 $LFS setstripe $DIR1/${tfile}_check_grant_$i -i $(($i -1)) -c 1
2646                 dd if=/dev/zero of=$DIR1/${tfile}_check_grant_$i bs=4k \
2647                                               count=1 > /dev/null 2>&1
2648         done
2649         # sync all the data and make sure no pending data on server
2650         sync_clients
2651         
2652         #get client grant and server grant
2653         client_grant=0
2654     for d in `lctl get_param -n osc.*.cur_grant_bytes`; do
2655                 client_grant=$((client_grant + $d))
2656         done
2657         server_grant=0
2658         for d in `lctl get_param -n obdfilter.*.tot_granted`; do
2659                 server_grant=$((server_grant + $d))
2660         done
2661
2662         # cleanup the check_grant file
2663         for i in `seq $OSTCOUNT`; do
2664                 rm $DIR1/${tfile}_check_grant_$i
2665         done
2666
2667         #check whether client grant == server grant
2668         if [ $client_grant != $server_grant ]; then
2669                 echo "failed: client:${client_grant} server: ${server_grant}"
2670                 return 1
2671         else
2672                 echo "pass"
2673         fi
2674 }
2675
2676 ########################
2677 # helper functions
2678
2679 osc_to_ost()
2680 {
2681     osc=$1
2682     ost=`echo $1 | awk -F_ '{print $3}'`
2683     if [ -z $ost ]; then
2684         ost=`echo $1 | sed 's/-osc.*//'`
2685     fi
2686     echo $ost
2687 }
2688
2689 remote_node () {
2690     local node=$1
2691     [ "$node" != "$(hostname)" ]
2692 }
2693
2694 remote_mds ()
2695 {
2696     local node
2697     for node in $(mdts_nodes); do
2698         remote_node $node && return 0
2699     done
2700     return 1
2701 }
2702
2703 remote_mds_nodsh()
2704 {
2705     [ "$CLIENTONLY" ] && return 0 || true
2706     remote_mds && [ "$PDSH" = "no_dsh" -o -z "$PDSH" -o -z "$mds_HOST" ]
2707 }
2708
2709 remote_ost ()
2710 {
2711     local node
2712     for node in $(osts_nodes) ; do
2713         remote_node $node && return 0
2714     done
2715     return 1
2716 }
2717
2718 remote_ost_nodsh()
2719 {
2720     [ "$CLIENTONLY" ] && return 0 || true 
2721     remote_ost && [ "$PDSH" = "no_dsh" -o -z "$PDSH" -o -z "$ost_HOST" ]
2722 }
2723
2724 remote_mgs_nodsh()
2725 {
2726     local MGS 
2727     MGS=$(facet_host mgs)
2728     remote_node $MGS && [ "$PDSH" = "no_dsh" -o -z "$PDSH" -o -z "$ost_HOST" ]
2729 }
2730
2731 mdts_nodes () {
2732     local MDSNODES
2733     local NODES_sort
2734     for num in `seq $MDSCOUNT`; do
2735         MDSNODES="$MDSNODES $(facet_host mds$num)"
2736     done
2737     NODES_sort=$(for i in $MDSNODES; do echo $i; done | sort -u)
2738
2739     echo $NODES_sort
2740 }
2741
2742 remote_servers () {
2743     remote_ost && remote_mds
2744 }
2745
2746 osts_nodes () {
2747     local OSTNODES=$(facet_host ost1)
2748     local NODES_sort
2749
2750     for num in `seq $OSTCOUNT`; do
2751         local myOST=$(facet_host ost$num)
2752         OSTNODES="$OSTNODES $myOST"
2753     done
2754     NODES_sort=$(for i in $OSTNODES; do echo $i; done | sort -u)
2755
2756     echo $NODES_sort
2757 }
2758
2759 nodes_list () {
2760     # FIXME. We need a list of clients
2761     local myNODES=$HOSTNAME
2762     local myNODES_sort
2763
2764     # CLIENTS (if specified) contains the local client
2765     [ -n "$CLIENTS" ] && myNODES=${CLIENTS//,/ }
2766
2767     if [ "$PDSH" -a "$PDSH" != "no_dsh" ]; then
2768         myNODES="$myNODES $(osts_nodes) $(mdts_nodes)"
2769     fi
2770
2771     myNODES_sort=$(for i in $myNODES; do echo $i; done | sort -u)
2772
2773     echo $myNODES_sort
2774 }
2775
2776 remote_nodes_list () {
2777     local rnodes=$(nodes_list)
2778     rnodes=$(echo " $rnodes " | sed -re "s/\s+$HOSTNAME\s+/ /g")
2779     echo $rnodes
2780 }
2781
2782 init_clients_lists () {
2783     # Sanity check: exclude the local client from RCLIENTS
2784     local rclients=$(echo " $RCLIENTS " | sed -re "s/\s+$HOSTNAME\s+/ /g")
2785
2786     # Sanity check: exclude the dup entries
2787     rclients=$(for i in $rclients; do echo $i; done | sort -u)
2788
2789     local clients="$SINGLECLIENT $HOSTNAME $rclients"
2790
2791     # Sanity check: exclude the dup entries from CLIENTS
2792     # for those configs which has SINGLCLIENT set to local client
2793     clients=$(for i in $clients; do echo $i; done | sort -u)
2794
2795     CLIENTS=`comma_list $clients`
2796     local -a remoteclients=($rclients)
2797     for ((i=0; $i<${#remoteclients[@]}; i++)); do
2798             varname=CLIENT$((i + 2))
2799             eval $varname=${remoteclients[i]}
2800     done
2801
2802     CLIENTCOUNT=$((${#remoteclients[@]} + 1))
2803 }
2804
2805 get_random_entry () {
2806     local rnodes=$1
2807
2808     rnodes=${rnodes//,/ }
2809
2810     local -a nodes=($rnodes)
2811     local num=${#nodes[@]} 
2812     local i=$((RANDOM * num * 2 / 65536))
2813
2814     echo ${nodes[i]}
2815 }
2816
2817 client_only () {
2818     [ "$CLIENTONLY" ] || [ "$CLIENTMODSONLY" = yes ]
2819 }
2820
2821 is_patchless ()
2822 {
2823     lctl get_param version | grep -q patchless
2824 }
2825
2826 check_versions () {
2827     [ "$MDSVER" = "$CLIVER" -a "$OSTVER" = "$CLIVER" ]
2828 }
2829
2830 get_node_count() {
2831     local nodes="$@"
2832     echo $nodes | wc -w || true
2833 }
2834
2835 mixed_ost_devs () {
2836     local nodes=$(osts_nodes)
2837     local osscount=$(get_node_count "$nodes")
2838     [ ! "$OSTCOUNT" = "$osscount" ]
2839 }
2840
2841 mixed_mdt_devs () {
2842     local nodes=$(mdts_nodes)
2843     local mdtcount=$(get_node_count "$nodes")
2844     [ ! "$MDSCOUNT" = "$mdtcount" ]
2845 }
2846
2847 generate_machine_file() {
2848     local nodes=${1//,/ }
2849     local machinefile=$2
2850     rm -f $machinefile || error "can't rm $machinefile"
2851     for node in $nodes; do
2852         echo $node >>$machinefile
2853     done
2854 }
2855
2856 get_stripe () {
2857     local file=$1/stripe
2858     touch $file
2859     $LFS getstripe -v $file || error
2860     rm -f $file
2861 }
2862
2863 check_runas_id_ret() {
2864     local myRC=0
2865     local myRUNAS_UID=$1
2866     local myRUNAS_GID=$2
2867     shift 2
2868     local myRUNAS=$@
2869     if [ -z "$myRUNAS" ]; then
2870         error_exit "myRUNAS command must be specified for check_runas_id"
2871     fi
2872     if $GSS_KRB5; then
2873         $myRUNAS krb5_login.sh || \
2874             error "Failed to refresh Kerberos V5 TGT for UID $myRUNAS_ID."
2875     fi
2876     mkdir $DIR/d0_runas_test
2877     chmod 0755 $DIR
2878     chown $myRUNAS_UID:$myRUNAS_GID $DIR/d0_runas_test
2879     $myRUNAS touch $DIR/d0_runas_test/f$$ || myRC=$?
2880     rm -rf $DIR/d0_runas_test
2881     return $myRC
2882 }
2883
2884 check_runas_id() {
2885     local myRUNAS_UID=$1
2886     local myRUNAS_GID=$2
2887     shift 2
2888     local myRUNAS=$@
2889     check_runas_id_ret $myRUNAS_UID $myRUNAS_GID $myRUNAS || \
2890         error "unable to write to $DIR/d0_runas_test as UID $myRUNAS_UID.
2891         Please set RUNAS_ID to some UID which exists on MDS and client or
2892         add user $myRUNAS_UID:$myRUNAS_GID on these nodes."
2893 }
2894
2895 # obtain the UID/GID for MPI_USER
2896 get_mpiuser_id() {
2897     local mpi_user=$1
2898
2899     MPI_USER_UID=$(do_facet client "getent passwd $mpi_user | cut -d: -f3;
2900 exit \\\${PIPESTATUS[0]}") || error_exit "failed to get the UID for $mpi_user"
2901
2902     MPI_USER_GID=$(do_facet client "getent passwd $mpi_user | cut -d: -f4;
2903 exit \\\${PIPESTATUS[0]}") || error_exit "failed to get the GID for $mpi_user"
2904 }
2905
2906 # obtain and cache Kerberos ticket-granting ticket
2907 refresh_krb5_tgt() {
2908     local myRUNAS_UID=$1
2909     local myRUNAS_GID=$2
2910     shift 2
2911     local myRUNAS=$@
2912     if [ -z "$myRUNAS" ]; then
2913         error_exit "myRUNAS command must be specified for refresh_krb5_tgt"
2914     fi
2915
2916     CLIENTS=${CLIENTS:-$HOSTNAME}
2917     do_nodes $CLIENTS "set -x
2918 if ! $myRUNAS krb5_login.sh; then
2919     echo "Failed to refresh Krb5 TGT for UID/GID $myRUNAS_UID/$myRUNAS_GID."
2920     exit 1
2921 fi"
2922 }
2923
2924 # Run multiop in the background, but wait for it to print
2925 # "PAUSING" to its stdout before returning from this function.
2926 multiop_bg_pause() {
2927     MULTIOP_PROG=${MULTIOP_PROG:-multiop}
2928     FILE=$1
2929     ARGS=$2
2930
2931     TMPPIPE=/tmp/multiop_open_wait_pipe.$$
2932     mkfifo $TMPPIPE
2933
2934     echo "$MULTIOP_PROG $FILE v$ARGS"
2935     $MULTIOP_PROG $FILE v$ARGS > $TMPPIPE &
2936
2937     echo "TMPPIPE=${TMPPIPE}"
2938     read -t 60 multiop_output < $TMPPIPE
2939     if [ $? -ne 0 ]; then
2940         rm -f $TMPPIPE
2941         return 1
2942     fi
2943     rm -f $TMPPIPE
2944     if [ "$multiop_output" != "PAUSING" ]; then
2945         echo "Incorrect multiop output: $multiop_output"
2946         kill -9 $PID
2947         return 1
2948     fi
2949
2950     return 0
2951 }
2952
2953 do_and_time () {
2954     local cmd=$1
2955     local rc
2956
2957     SECONDS=0
2958     eval '$cmd'
2959     
2960     [ ${PIPESTATUS[0]} -eq 0 ] || rc=1
2961
2962     echo $SECONDS
2963     return $rc
2964 }
2965
2966 inodes_available () {
2967     local IFree=$($LFS df -i $MOUNT | grep ^$FSNAME | awk '{print $4}' | sort -un | head -1) || return 1
2968     echo $IFree
2969 }
2970
2971 # reset llite stat counters
2972 clear_llite_stats(){
2973         lctl set_param -n llite.*.stats 0
2974 }
2975
2976 # sum llite stat items
2977 calc_llite_stats() {
2978         local res=$(lctl get_param -n llite.*.stats |
2979                     awk 'BEGIN {s = 0} END {print s} /^'"$1"'/ {s += $2}')
2980         echo $res
2981 }
2982
2983 # reset osc stat counters
2984 clear_osc_stats(){
2985         lctl set_param -n osc.*.osc_stats 0
2986 }
2987
2988 # sum osc stat items
2989 calc_osc_stats() {
2990         local res=$(lctl get_param -n osc.*.osc_stats |
2991                     awk 'BEGIN {s = 0} END {print s} /^'"$1"'/ {s += $2}')
2992         echo $res
2993 }
2994
2995 calc_sum () {
2996         awk 'BEGIN {s = 0}; {s += $1}; END {print s}'
2997 }
2998
2999 calc_osc_kbytes () {
3000         df $MOUNT > /dev/null
3001         $LCTL get_param -n osc.*[oO][sS][cC][-_][0-9a-f]*.$1 | calc_sum
3002 }
3003
3004 # save_lustre_params(node, parameter_mask)
3005 # generate a stream of formatted strings (<node> <param name>=<param value>)
3006 save_lustre_params() {
3007         local s
3008         do_nodes --verbose $1 "lctl get_param $2 | while read s; do echo \\\$s; done"
3009 }
3010
3011 # restore lustre parameters from input stream, produces by save_lustre_params
3012 restore_lustre_params() {
3013         local node
3014         local name
3015         local val
3016         while IFS=" =" read node name val; do
3017                 do_node ${node//:/} "lctl set_param -n $name $val"
3018         done
3019 }
3020
3021 check_catastrophe() {
3022     local rnodes=${1:-$(comma_list $(remote_nodes_list))}
3023     local C=$CATASTROPHE
3024     [ -f $C ] && [ $(cat $C) -ne 0 ] && return 1
3025
3026     if [ $rnodes ]; then
3027         do_nodes $rnodes "rc=\\\$([ -f $C ] && echo \\\$(< $C) || echo 0);
3028 if [ \\\$rc -ne 0 ]; then echo \\\$(hostname): \\\$rc; fi
3029 exit \\\$rc;"
3030     fi 
3031 }
3032
3033 # $1 node
3034 # $2 file
3035 # $3 $RUNAS
3036 get_stripe_info() {
3037         local tmp_file
3038
3039         stripe_size=0
3040         stripe_count=0
3041         stripe_index=0
3042         tmp_file=$(mktemp)
3043
3044         do_facet $1 $3 lfs getstripe -v $2 > $tmp_file
3045
3046         stripe_size=`awk '$1 ~ /size/ {print $2}' $tmp_file`
3047         stripe_count=`awk '$1 ~ /count/ {print $2}' $tmp_file`
3048         stripe_index=`awk '$1 ~ /stripe_offset/ {print $2}' $tmp_file`
3049         rm -f $tmp_file
3050 }
3051
3052 # CMD: determine mds index where directory inode presents
3053 get_mds_dir () {
3054     local dir=$1
3055     local file=$dir/f0.get_mds_dir_tmpfile
3056
3057     mkdir -p $dir
3058     rm -f $file
3059     sleep 1
3060     local iused=$(lfs df -i $dir | grep MDT | awk '{print $3}')
3061     local -a oldused=($iused)
3062
3063     openfile -f O_CREAT:O_LOV_DELAY_CREATE -m 0644 $file > /dev/null
3064     sleep 1
3065     iused=$(lfs df -i $dir | grep MDT | awk '{print $3}')
3066     local -a newused=($iused)
3067
3068     local num=0
3069     for ((i=0; i<${#newused[@]}; i++)); do
3070          if [ ${oldused[$i]} -lt ${newused[$i]} ];  then
3071              echo $(( i + 1 ))
3072              rm -f $file
3073              return 0
3074          fi
3075     done
3076     error "mdt-s : inodes count OLD ${oldused[@]} NEW ${newused[@]}"
3077 }
3078
3079 mdsrate_cleanup () {
3080     if [ -d $4 ]; then
3081         mpi_run -np $1 -machinefile $2 ${MDSRATE} --unlink --nfiles $3 --dir $4 --filefmt $5 $6
3082         rmdir $4
3083     fi
3084 }
3085
3086 delayed_recovery_enabled () {
3087     local var=${SINGLEMDS}_svc
3088     do_facet $SINGLEMDS lctl get_param -n mdd.${!var}.stale_export_age > /dev/null 2>&1
3089 }
3090
3091 ########################
3092
3093 convert_facet2label() { 
3094     local facet=$1
3095
3096     if [ x$facet = xost ]; then
3097        facet=ost1
3098     fi
3099
3100     local varsvc=${facet}_svc
3101
3102     if [ -n ${!varsvc} ]; then
3103         echo ${!varsvc}
3104     else  
3105         error "No lablel for $facet!"
3106     fi
3107 }
3108
3109 get_clientosc_proc_path() {
3110     local ost=$1
3111
3112     echo "{$1}-osc-*"
3113 }
3114
3115 get_lustre_version () {
3116     local node=${1:-"mds"}    
3117     do_facet $node $LCTL get_param -n version |  awk '/^lustre:/ {print $2}'
3118 }
3119
3120 get_mds_version_major () {
3121     local version=$(get_lustre_version mds)
3122     echo $version | awk -F. '{print $1}'
3123 }
3124
3125 get_mds_version_minor () {
3126     local version=$(get_lustre_version mds)
3127     echo $version | awk -F. '{print $2}'
3128 }
3129
3130 get_mdtosc_proc_path() {
3131     local ost=$1
3132     local major=$(get_mds_version_major)
3133     local minor=$(get_mds_version_minor)
3134     if [ $major -le 1 -a $minor -le 8 ] ; then
3135         echo "${ost}-osc"
3136     else
3137         echo "${ost}-osc-MDT0000"
3138     fi
3139 }
3140
3141 get_osc_import_name() {
3142     local facet=$1
3143     local ost=$2
3144     local label=$(convert_facet2label $ost)
3145
3146     if [ "$facet" == "mds" ]; then
3147         get_mdtosc_proc_path $label
3148         return 0
3149     fi
3150
3151     get_clientosc_proc_path $label
3152     return 0
3153 }
3154
3155 wait_import_state () {
3156     local expected=$1
3157     local CONN_PROC=$2
3158     local CONN_STATE
3159     local i=0
3160
3161     CONN_STATE=$($LCTL get_param -n $CONN_PROC 2>/dev/null | cut -f2)
3162     while [ "${CONN_STATE}" != "${expected}" ]; do
3163         if [ "${expected}" == "DISCONN" ]; then
3164             # for disconn we can check after proc entry is removed
3165             [ "x${CONN_STATE}" == "x" ] && return 0
3166             #  with AT we can have connect request timeout ~ reconnect timeout
3167             # and test can't see real disconnect
3168             [ "${CONN_STATE}" == "CONNECTING" ] && return 0
3169         fi
3170         # disconnect rpc should be wait not more obd_timeout
3171         [ $i -ge $(($TIMEOUT * 3 / 2)) ] && \
3172             error "can't put import for $CONN_PROC into ${expected} state" && return 1
3173         sleep 1
3174         CONN_STATE=$($LCTL get_param -n $CONN_PROC 2>/dev/null | cut -f2)
3175         i=$(($i + 1))
3176     done
3177
3178     log "$CONN_PROC now in ${CONN_STATE} state"
3179     return 0
3180 }
3181
3182 wait_osc_import_state() {
3183     local facet=$1
3184     local ost_facet=$2
3185     local expected=$3
3186     local ost=$(get_osc_import_name $facet $ost_facet)
3187     local CONN_PROC
3188     local CONN_STATE
3189     local i=0
3190
3191     CONN_PROC="osc.${ost}.ost_server_uuid"
3192     CONN_STATE=$(do_facet $facet lctl get_param -n $CONN_PROC 2>/dev/null | cut -f2)
3193     while [ "${CONN_STATE}" != "${expected}" ]; do
3194         if [ "${expected}" == "DISCONN" ]; then 
3195             # for disconn we can check after proc entry is removed
3196             [ "x${CONN_STATE}" == "x" ] && return 0
3197             #  with AT we can have connect request timeout ~ reconnect timeout
3198             # and test can't see real disconnect
3199             [ "${CONN_STATE}" == "CONNECTING" ] && return 0
3200         fi
3201         # disconnect rpc should be wait not more obd_timeout
3202         [ $i -ge $(($TIMEOUT * 3 / 2)) ] && \
3203             error "can't put import for ${ost}(${ost_facet}) into ${expected} state" && return 1
3204         sleep 1
3205         CONN_STATE=$(do_facet $facet lctl get_param -n $CONN_PROC 2>/dev/null | cut -f2)
3206         i=$(($i + 1))
3207     done
3208
3209     log "${ost_facet} now in ${CONN_STATE} state"
3210     return 0
3211 }
3212
3213 get_clientmdc_proc_path() {
3214     echo "${1}-mdc-*"
3215 }
3216
3217 do_rpc_nodes () {
3218     local list=$1
3219     shift
3220
3221     do_nodes --verbose $list "PATH=$RLUSTRE/tests/:$PATH sh rpc.sh $@ " 
3222 }
3223
3224 wait_clients_import_state () {
3225     local list=$1
3226     local facet=$2
3227     local expected=$3
3228     shift
3229
3230     local label=$(convert_facet2label $facet)
3231     local proc_path
3232     case $facet in
3233         ost* ) proc_path="osc.$(get_clientosc_proc_path $label).ost_server_uuid" ;;
3234         mds* ) proc_path="mdc.$(get_clientmdc_proc_path $label).mds_server_uuid" ;;
3235         *) error "unknown facet!" ;;
3236     esac
3237
3238     if ! do_rpc_nodes $list wait_import_state $expected $proc_path; then
3239         error "import is not in ${expected} state"
3240         return 1
3241     fi
3242 }
3243
3244 oos_full() {
3245         local -a AVAILA
3246         local -a GRANTA
3247         local OSCFULL=1
3248         AVAILA=($(do_nodes $(comma_list $(osts_nodes)) \
3249                   $LCTL get_param obdfilter.*.kbytesavail))
3250         GRANTA=($(do_nodes $(comma_list $(osts_nodes)) \
3251                   $LCTL get_param -n obdfilter.*.tot_granted))
3252         for ((i=0; i<${#AVAILA[@]}; i++)); do
3253                 local -a AVAIL1=(${AVAILA[$i]//=/ })
3254                 GRANT=$((${GRANTA[$i]}/1024))
3255                 echo -n $(echo ${AVAIL1[0]} | cut -d"." -f2) avl=${AVAIL1[1]} grnt=$GRANT diff=$((AVAIL1[1] - GRANT))
3256                 [ $((AVAIL1[1] - GRANT)) -lt 400 ] && OSCFULL=0 && echo " FULL" || echo
3257         done
3258         return $OSCFULL
3259 }
3260
3261 pool_list () {
3262    do_facet mgs lctl pool_list $1
3263 }
3264
3265 create_pool() {
3266     local fsname=${1%%.*}
3267     local poolname=${1##$fsname.}
3268
3269     do_facet mgs lctl pool_new $1
3270     local RC=$?
3271     # get param should return err unless pool is created
3272     [[ $RC -ne 0 ]] && return $RC
3273
3274     wait_update $HOSTNAME "lctl get_param -n lov.$fsname-*.pools.$poolname \
3275         2>/dev/null || echo foo" "" || RC=1
3276     if [[ $RC -eq 0 ]]; then
3277         add_pool_to_list $1
3278     else
3279         error "pool_new failed $1"
3280     fi
3281     return $RC
3282 }
3283
3284 add_pool_to_list () {
3285     local fsname=${1%%.*}
3286     local poolname=${1##$fsname.}
3287
3288     local listvar=${fsname}_CREATED_POOLS
3289     eval export ${listvar}=$(expand_list ${!listvar} $poolname)
3290 }
3291
3292 remove_pool_from_list () {
3293     local fsname=${1%%.*}
3294     local poolname=${1##$fsname.}
3295
3296     local listvar=${fsname}_CREATED_POOLS
3297     eval export ${listvar}=$(exclude_items_from_list ${!listvar} $poolname)
3298 }
3299
3300 destroy_pool_int() {
3301     local ost
3302     local OSTS=$(do_facet $SINGLEMDS lctl pool_list $1 | \
3303         awk '$1 !~ /^Pool:/ {print $1}')
3304     for ost in $OSTS; do
3305         do_facet mgs lctl pool_remove $1 $ost
3306     done
3307     do_facet mgs lctl pool_destroy $1
3308 }
3309
3310 # <fsname>.<poolname> or <poolname>
3311 destroy_pool() {
3312     local fsname=${1%%.*}
3313     local poolname=${1##$fsname.}
3314
3315     [[ x$fsname = x$poolname ]] && fsname=$FSNAME
3316
3317     local RC
3318
3319     pool_list $fsname.$poolname || return $?
3320
3321     destroy_pool_int $fsname.$poolname
3322     RC=$?
3323     [[ $RC -ne 0 ]] && return $RC
3324
3325     wait_update $HOSTNAME "lctl get_param -n lov.$fsname-*.pools.$poolname \
3326       2>/dev/null || echo foo" "foo" || RC=1
3327
3328     if [[ $RC -eq 0 ]]; then
3329         remove_pool_from_list $fsname.$poolname
3330     else
3331         error "destroy pool failed $1"
3332     fi
3333     return $RC
3334 }
3335
3336 destroy_pools () {
3337     local fsname=${1:-$FSNAME}
3338     local poolname
3339     local listvar=${fsname}_CREATED_POOLS
3340
3341     pool_list $fsname
3342
3343     [ x${!listvar} = x ] && return 0
3344
3345     echo destroy the created pools: ${!listvar}
3346     for poolname in ${!listvar//,/ }; do
3347         destroy_pool $fsname.$poolname 
3348     done
3349 }
3350
3351 cleanup_pools () {
3352     local fsname=${1:-$FSNAME}
3353     trap 0
3354     destroy_pools $fsname
3355 }
3356
3357 gather_logs () {
3358     local list=$1
3359
3360     local ts=$(date +%s)
3361
3362     # bug 20237, comment 11
3363     # It would also be useful to provide the option
3364     # of writing the file to an NFS directory so it doesn't need to be copied.
3365     local tmp=$TMP
3366     local docp=true
3367     [ -d "$SHARED_DIR_LOGS" ] && tmp=$SHARED_DIR_LOGS && docp=false
3368
3369     # dump lustre logs, dmesg
3370     do_nodes $list "log=$tmp/\\\$(hostname)-debug-$ts.log ;
3371 lctl dk \\\$log >/dev/null;
3372 log=$tmp/\\\$(hostname)-dmesg-$ts.log;
3373 dmesg > \\\$log; "
3374
3375     # FIXME: does it make sense to collect the logs for $ts only, but all
3376     # TESTSUITE logs?
3377     # rsync $TMP/*${TESTSUITE}* to gather the logs dumped by error fn
3378     local logs=$TMP/'*'${TESTSUITE}'*'
3379     if $docp; then
3380         logs=$logs' '$tmp/'*'$ts'*'
3381     fi
3382     for node in ${list//,/ }; do
3383         rsync -az $node:"$logs" $TMP
3384     done
3385
3386     local archive=$TMP/${TESTSUITE}-$ts.tar.bz2
3387     tar -jcf $archive $tmp/*$ts* $TMP/*${TESTSUITE}*
3388
3389     echo $archive
3390 }
3391
3392 cleanup_logs () {
3393     local list=${1:-$(comma_list $(nodes_list))}
3394
3395     [ -n ${TESTSUITE} ] && do_nodes $list "rm -f $TMP/*${TESTSUITE}*" || true
3396 }
3397
3398 do_ls () {
3399     local mntpt_root=$1
3400     local num_mntpts=$2
3401     local dir=$3
3402     local i
3403     local cmd
3404     local pids
3405     local rc=0
3406
3407     for i in $(seq 0 $num_mntpts); do
3408         cmd="ls -laf ${mntpt_root}$i/$dir"
3409         echo + $cmd;
3410         $cmd > /dev/null &
3411         pids="$pids $!"
3412     done
3413     echo pids=$pids
3414     for pid in $pids; do
3415         wait $pid || rc=$?
3416     done
3417
3418     return $rc
3419 }
3420
3421 get_clients_mount_count () {
3422     local clients=${CLIENTS:-`hostname`}
3423
3424     # we need to take into account the clients mounts and
3425     # exclude mds/ost mounts if any;
3426     do_nodes $clients cat /proc/mounts | grep lustre | grep $MOUNT | wc -l
3427 }
3428
3429 # gss functions
3430 PROC_CLI="srpc_info"
3431
3432 combination()
3433 {
3434     local M=$1
3435     local N=$2
3436     local R=1
3437
3438     if [ $M -lt $N ]; then
3439         R=0
3440     else
3441         N=$((N + 1))
3442         while [ $N -le $M ]; do
3443             R=$((R * N))
3444             N=$((N + 1))
3445         done
3446     fi
3447
3448     echo $R
3449     return 0
3450 }
3451
3452 calc_connection_cnt() {
3453     local dir=$1
3454
3455     # MDT->MDT = 2 * C(M, 2)
3456     # MDT->OST = M * O
3457     # CLI->OST = C * O
3458     # CLI->MDT = C * M
3459     comb_m2=$(combination $MDSCOUNT 2)
3460
3461     local num_clients=$(get_clients_mount_count)
3462
3463     local cnt_mdt2mdt=$((comb_m2 * 2))
3464     local cnt_mdt2ost=$((MDSCOUNT * OSTCOUNT))
3465     local cnt_cli2ost=$((num_clients * OSTCOUNT))
3466     local cnt_cli2mdt=$((num_clients * MDSCOUNT))
3467     local cnt_all2ost=$((cnt_mdt2ost + cnt_cli2ost))
3468     local cnt_all2mdt=$((cnt_mdt2mdt + cnt_cli2mdt))
3469     local cnt_all2all=$((cnt_mdt2ost + cnt_mdt2mdt + cnt_cli2ost + cnt_cli2mdt))
3470
3471     local var=cnt_$dir
3472     local res=${!var}
3473
3474     echo $res
3475 }
3476
3477 set_rule()
3478 {
3479     local tgt=$1
3480     local net=$2
3481     local dir=$3
3482     local flavor=$4
3483     local cmd="$tgt.srpc.flavor"
3484
3485     if [ $net == "any" ]; then
3486         net="default"
3487     fi
3488     cmd="$cmd.$net"
3489
3490     if [ $dir != "any" ]; then
3491         cmd="$cmd.$dir"
3492     fi
3493
3494     cmd="$cmd=$flavor"
3495     log "Setting sptlrpc rule: $cmd"
3496     do_facet mgs "$LCTL conf_param $cmd"
3497 }
3498
3499 count_flvr()
3500 {
3501     local output=$1
3502     local flavor=$2
3503     local count=0
3504
3505     rpc_flvr=`echo $flavor | awk -F - '{ print $1 }'`
3506     bulkspec=`echo $flavor | awk -F - '{ print $2 }'`
3507
3508     count=`echo "$output" | grep "rpc flavor" | grep $rpc_flvr | wc -l`
3509
3510     if [ "x$bulkspec" != "x" ]; then
3511         algs=`echo $bulkspec | awk -F : '{ print $2 }'`
3512
3513         if [ "x$algs" != "x" ]; then
3514             bulk_count=`echo "$output" | grep "bulk flavor" | grep $algs | wc -l`
3515         else
3516             bulk=`echo $bulkspec | awk -F : '{ print $1 }'`
3517             if [ $bulk == "bulkn" ]; then
3518                 bulk_count=`echo "$output" | grep "bulk flavor" \
3519                             | grep "null/null" | wc -l`
3520             elif [ $bulk == "bulki" ]; then
3521                 bulk_count=`echo "$output" | grep "bulk flavor" \
3522                             | grep "/null" | grep -v "null/" | wc -l`
3523             else
3524                 bulk_count=`echo "$output" | grep "bulk flavor" \
3525                             | grep -v "/null" | grep -v "null/" | wc -l`
3526             fi
3527         fi
3528
3529         [ $bulk_count -lt $count ] && count=$bulk_count
3530     fi
3531
3532     echo $count
3533 }
3534
3535 flvr_cnt_cli2mdt()
3536 {
3537     local flavor=$1
3538     local cnt
3539
3540     local clients=${CLIENTS:-`hostname`}
3541
3542     for c in ${clients//,/ }; do
3543         output=`do_node $c lctl get_param -n mdc.*-MDT*-mdc-*.$PROC_CLI 2>/dev/null`
3544         tmpcnt=`count_flvr "$output" $flavor`
3545         cnt=$((cnt + tmpcnt))
3546     done
3547     echo $cnt
3548 }
3549
3550 flvr_cnt_cli2ost()
3551 {
3552     local flavor=$1
3553     local cnt
3554
3555     local clients=${CLIENTS:-`hostname`}
3556
3557     for c in ${clients//,/ }; do
3558         output=`do_node $c lctl get_param -n osc.*OST*-osc-[^M][^D][^T]*.$PROC_CLI 2>/dev/null`
3559         tmpcnt=`count_flvr "$output" $flavor`
3560         cnt=$((cnt + tmpcnt))
3561     done
3562     echo $cnt
3563 }
3564
3565 flvr_cnt_mdt2mdt()
3566 {
3567     local flavor=$1
3568     local cnt=0
3569
3570     if [ $MDSCOUNT -le 1 ]; then
3571         echo 0
3572         return
3573     fi
3574
3575     for num in `seq $MDSCOUNT`; do
3576         output=`do_facet mds$num lctl get_param -n mdc.*-MDT*-mdc[0-9]*.$PROC_CLI 2>/dev/null`
3577         tmpcnt=`count_flvr "$output" $flavor`
3578         cnt=$((cnt + tmpcnt))
3579     done
3580     echo $cnt;
3581 }
3582
3583 flvr_cnt_mdt2ost()
3584 {
3585     local flavor=$1
3586     local cnt=0
3587
3588     for num in `seq $MDSCOUNT`; do
3589         output=`do_facet mds$num lctl get_param -n osc.*OST*-osc-MDT*.$PROC_CLI 2>/dev/null`
3590         tmpcnt=`count_flvr "$output" $flavor`
3591         cnt=$((cnt + tmpcnt))
3592     done
3593     echo $cnt;
3594 }
3595
3596 flvr_cnt_mgc2mgs()
3597 {
3598     local flavor=$1
3599
3600     output=`do_facet client lctl get_param -n mgc.*.$PROC_CLI 2>/dev/null`
3601     count_flvr "$output" $flavor
3602 }
3603
3604 do_check_flavor()
3605 {
3606     local dir=$1        # from to
3607     local flavor=$2     # flavor expected
3608     local res=0
3609
3610     if [ $dir == "cli2mdt" ]; then
3611         res=`flvr_cnt_cli2mdt $flavor`
3612     elif [ $dir == "cli2ost" ]; then
3613         res=`flvr_cnt_cli2ost $flavor`
3614     elif [ $dir == "mdt2mdt" ]; then
3615         res=`flvr_cnt_mdt2mdt $flavor`
3616     elif [ $dir == "mdt2ost" ]; then
3617         res=`flvr_cnt_mdt2ost $flavor`
3618     elif [ $dir == "all2ost" ]; then
3619         res1=`flvr_cnt_mdt2ost $flavor`
3620         res2=`flvr_cnt_cli2ost $flavor`
3621         res=$((res1 + res2))
3622     elif [ $dir == "all2mdt" ]; then
3623         res1=`flvr_cnt_mdt2mdt $flavor`
3624         res2=`flvr_cnt_cli2mdt $flavor`
3625         res=$((res1 + res2))
3626     elif [ $dir == "all2all" ]; then
3627         res1=`flvr_cnt_mdt2ost $flavor`
3628         res2=`flvr_cnt_cli2ost $flavor`
3629         res3=`flvr_cnt_mdt2mdt $flavor`
3630         res4=`flvr_cnt_cli2mdt $flavor`
3631         res=$((res1 + res2 + res3 + res4))
3632     fi
3633
3634     echo $res
3635 }
3636
3637 wait_flavor()
3638 {
3639     local dir=$1        # from to
3640     local flavor=$2     # flavor expected
3641     local expect=${3:-$(calc_connection_cnt $dir)}     # number expected
3642
3643     local res=0
3644
3645     for ((i=0;i<20;i++)); do
3646         echo -n "checking..."
3647         res=$(do_check_flavor $dir $flavor)
3648         if [ $res -eq $expect ]; then
3649             echo "found $res $flavor connections of $dir, OK"
3650             return 0
3651         else
3652             echo "found $res $flavor connections of $dir, not ready ($expect)"
3653             sleep 4
3654         fi
3655     done
3656
3657     echo "Error checking $flavor of $dir: expect $expect, actual $res"
3658     return 1
3659 }
3660
3661 restore_to_default_flavor()
3662 {
3663     local proc="mgs.MGS.live.$FSNAME"
3664
3665     echo "restoring to default flavor..."
3666
3667     nrule=`do_facet mgs lctl get_param -n $proc 2>/dev/null | grep ".srpc.flavor." | wc -l`
3668
3669     # remove all existing rules if any
3670     if [ $nrule -ne 0 ]; then
3671         echo "$nrule existing rules"
3672         for rule in `do_facet mgs lctl get_param -n $proc 2>/dev/null | grep ".srpc.flavor."`; do
3673             echo "remove rule: $rule"
3674             spec=`echo $rule | awk -F = '{print $1}'`
3675             do_facet mgs "$LCTL conf_param $spec="
3676         done
3677     fi
3678
3679     # verify no rules left
3680     nrule=`do_facet mgs lctl get_param -n $proc 2>/dev/null | grep ".srpc.flavor." | wc -l`
3681     [ $nrule -ne 0 ] && error "still $nrule rules left"
3682
3683     # wait for default flavor to be applied
3684     # currently default flavor for all connections are 'null'
3685     wait_flavor all2all null
3686     echo "now at default flavor settings"
3687 }
3688
3689 set_flavor_all()
3690 {
3691     local flavor=${1:-null}
3692
3693     echo "setting all flavor to $flavor"
3694
3695     # FIXME need parameter to this fn
3696     # and remove global vars
3697     local cnt_all2all=$(calc_connection_cnt all2all)
3698
3699     local res=$(do_check_flavor all2all $flavor)
3700     if [ $res -eq $cnt_all2all ]; then
3701         echo "already have total $res $flavor connections"
3702         return
3703     fi
3704
3705     echo "found $res $flavor out of total $cnt_all2all connections"
3706     restore_to_default_flavor
3707
3708     [[ $flavor = null ]] && return 0
3709
3710     set_rule $FSNAME any any $flavor
3711     wait_flavor all2all $flavor
3712 }
3713
3714