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