Whamcloud - gitweb
LU-8995 tests: set debug size correctly
[fs/lustre-release.git] / lustre / tests / test-framework.sh
index 47f65ea..a90beae 100755 (executable)
@@ -17,10 +17,6 @@ export QUOTA_AUTO=1
 # specify environment variable containing batch job name for server statistics
 export JOBID_VAR=${JOBID_VAR:-"procname_uid"}  # or "existing" or "disable"
 
-# LOAD_LLOOP: LU-409: only load llite_lloop module if kernel < 2.6.32 or
-#             LOAD_LLOOP is true. LOAD_LLOOP is false by default.
-export LOAD_LLOOP=${LOAD_LLOOP:-false}
-
 #export PDSH="pdsh -S -Rssh -w"
 export MOUNT_CMD=${MOUNT_CMD:-"mount -t lustre"}
 export UMOUNT=${UMOUNT:-"umount -d"}
@@ -54,16 +50,25 @@ fi
 [ -z "$MODPROBECONF" -a -f /etc/modprobe.conf ] &&
     MODPROBECONF=/etc/modprobe.conf
 
+sanitize_parameters() {
+       for i in DIR DIR1 DIR2 MOUNT MOUNT1 MOUNT2
+       do
+               local path=${!i}
+               if [ -d "$path" ]; then
+                       eval export $i=$(echo $path | sed -r 's/\/+$//g')
+               fi
+       done
+}
 assert_DIR () {
-    local failed=""
-    [[ $DIR/ = $MOUNT/* ]] || \
-        { failed=1 && echo "DIR=$DIR not in $MOUNT. Aborting."; }
-    [[ $DIR1/ = $MOUNT1/* ]] || \
-        { failed=1 && echo "DIR1=$DIR1 not in $MOUNT1. Aborting."; }
-    [[ $DIR2/ = $MOUNT2/* ]] || \
-        { failed=1 && echo "DIR2=$DIR2 not in $MOUNT2. Aborting"; }
+       local failed=""
+       [[ $DIR/ = $MOUNT/* ]] ||
+               { failed=1 && echo "DIR=$DIR not in $MOUNT. Aborting."; }
+       [[ $DIR1/ = $MOUNT1/* ]] ||
+               { failed=1 && echo "DIR1=$DIR1 not in $MOUNT1. Aborting."; }
+       [[ $DIR2/ = $MOUNT2/* ]] ||
+               { failed=1 && echo "DIR2=$DIR2 not in $MOUNT2. Aborting"; }
 
-    [ -n "$failed" ] && exit 99 || true
+       [ -n "$failed" ] && exit 99 || true
 }
 
 usage() {
@@ -133,6 +138,7 @@ init_test_env() {
        export TEST_FAILED=false
        export FAIL_ON_SKIP_ENV=${FAIL_ON_SKIP_ENV:-false}
        export RPC_MODE=${RPC_MODE:-false}
+       export DO_CLEANUP=${DO_CLEANUP:-true}
 
     export MKE2FS=$MKE2FS
     if [ -z "$MKE2FS" ]; then
@@ -260,6 +266,8 @@ init_test_env() {
     fi
     export LL_DECODE_FILTER_FID=${LL_DECODE_FILTER_FID:-"$LUSTRE/utils/ll_decode_filter_fid"}
     [ ! -f "$LL_DECODE_FILTER_FID" ] && export LL_DECODE_FILTER_FID="ll_decode_filter_fid"
+    export LL_DECODE_LINKEA=${LL_DECODE_LINKEA:-"$LUSTRE/utils/ll_decode_linkea"}
+    [ ! -f "$LL_DECODE_LINKEA" ] && export LL_DECODE_LINKEA="ll_decode_linkea"
     export MKFS=${MKFS:-"$LUSTRE/utils/mkfs.lustre"}
     [ ! -f "$MKFS" ] && export MKFS="mkfs.lustre"
     export TUNEFS=${TUNEFS:-"$LUSTRE/utils/tunefs.lustre"}
@@ -284,6 +292,8 @@ init_test_env() {
     export DIR2
     export SAVE_PWD=${SAVE_PWD:-$LUSTRE/tests}
     export AT_MAX_PATH
+    export LDEV=${LDEV:-"$LUSTRE/scripts/ldev"}
+    [ ! -f "$LDEV" ] && export LDEV=$(which ldev 2> /dev/null)
 
     if [ "$ACCEPTOR_PORT" ]; then
         export PORT_OPT="--port $ACCEPTOR_PORT"
@@ -324,20 +334,20 @@ init_test_env() {
        export SHUTDOWN_ATTEMPTS=${SHUTDOWN_ATTEMPTS:-3}
        export OSD_TRACK_DECLARES_LBUG=${OSD_TRACK_DECLARES_LBUG:-"yes"}
 
-    # command line
+       # command line
 
-    while getopts "rvwf:" opt $*; do
-        case $opt in
-            f) CONFIG=$OPTARG;;
-            r) REFORMAT=--reformat;;
-            v) VERBOSE=true;;
-            w) WRITECONF=writeconf;;
-            \?) usage;;
-        esac
-    done
+       while getopts "rvwf:" opt $*; do
+               case $opt in
+                       f) CONFIG=$OPTARG;;
+                       r) REFORMAT=yes;;
+                       v) VERBOSE=true;;
+                       w) WRITECONF=writeconf;;
+                       \?) usage;;
+               esac
+       done
 
-    shift $((OPTIND - 1))
-    ONLY=${ONLY:-$*}
+       shift $((OPTIND - 1))
+       ONLY=${ONLY:-$*}
 
        # print the durations of each test if "true"
        DDETAILS=${DDETAILS:-false}
@@ -392,9 +402,7 @@ export LINUX_VERSION_CODE=$(version_code ${LINUX_VERSION//\./ })
 lustre_build_version() {
        local facet=${1:-client}
 
-       # lustre: 2.6.52
-       # kernel: patchless_client
-       # build: v2_6_92_0-gadb3ee4-2.6.32-431.29.2.el6_lustre.x86_64
+       # lustre: 2.8.52
        local VER=$(do_facet $facet $LCTL get_param -n version 2> /dev/null |
                    awk '/lustre: / { print $2 }')
        # lctl 2.6.50
@@ -484,20 +492,6 @@ load_module() {
        fi
 }
 
-llite_lloop_enabled() {
-    local n1=$(uname -r | cut -d. -f1)
-    local n2=$(uname -r | cut -d. -f2)
-    local n3=$(uname -r | cut -d- -f1 | cut -d. -f3)
-
-    # load the llite_lloop module for < 2.6.32 kernels
-    if [[ $n1 -lt 2 ]] || [[ $n1 -eq 2 && $n2 -lt 6 ]] || \
-       [[ $n1 -eq 2 && $n2 -eq 6 && $n3 -lt 32 ]] || \
-        $LOAD_LLOOP; then
-        return 0
-    fi
-    return 1
-}
-
 load_modules_local() {
        if [ -n "$MODPROBE" ]; then
                # use modprobe
@@ -536,10 +530,12 @@ load_modules_local() {
        fi
 
        load_module ../libcfs/libcfs/libcfs
+       # Prevent local MODOPTS_LIBCFS being passed as part of environment
+       # variable to remote nodes
+       unset MODOPTS_LIBCFS
 
-    [ "$PTLDEBUG" ] && lctl set_param debug="$PTLDEBUG"
-    [ "$SUBSYSTEM" ] && lctl set_param subsystem_debug="${SUBSYSTEM# }"
-    load_module ../lnet/lnet/lnet
+       set_default_debug
+       load_module ../lnet/lnet/lnet
        case $NETTYPE in
        o2ib)
                LNETLND="o2iblnd/ko2iblnd"
@@ -560,13 +556,15 @@ load_modules_local() {
     load_module lov/lov
     load_module mgc/mgc
     load_module obdecho/obdecho
-    if ! client_only; then
-        SYMLIST=/proc/kallsyms
-        grep -q crc16 $SYMLIST || { modprobe crc16 2>/dev/null || true; }
-        grep -q -w jbd $SYMLIST || { modprobe jbd 2>/dev/null || true; }
-        grep -q -w jbd2 $SYMLIST || { modprobe jbd2 2>/dev/null || true; }
+       if ! client_only; then
+               SYMLIST=/proc/kallsyms
+               grep -q crc16 $SYMLIST ||
+                       { modprobe crc16 2>/dev/null || true; }
+               grep -q -w jbd2 $SYMLIST ||
+                       { modprobe jbd2 2>/dev/null || true; }
                load_module lfsck/lfsck
-               [ "$LQUOTA" != "no" ] && load_module quota/lquota $LQUOTAOPTS
+               [ "$LQUOTA" != "no" ] &&
+                       load_module quota/lquota $LQUOTAOPTS
                if [[ $(node_fstypes $HOSTNAME) == *zfs* ]]; then
                        modprobe zfs
                        load_module osd-zfs/osd_zfs
@@ -574,6 +572,8 @@ load_modules_local() {
                if [[ $(node_fstypes $HOSTNAME) == *ldiskfs* ]]; then
                        grep -q exportfs_decode_fh $SYMLIST ||
                                { modprobe exportfs 2> /dev/null || true; }
+                       grep -q -w mbcache $SYMLIST ||
+                               { modprobe mbcache 2>/dev/null || true; }
                        load_module ../ldiskfs/ldiskfs
                        load_module osd-ldiskfs/osd_ldiskfs
                fi
@@ -585,10 +585,9 @@ load_modules_local() {
                load_module osp/osp
                load_module ofd/ofd
                load_module osp/osp
-    fi
+       fi
 
        load_module llite/lustre
-       llite_lloop_enabled && load_module llite/llite_lloop
        [ -d /r ] && OGDB=${OGDB:-"/r/tmp"}
        OGDB=${OGDB:-$TMP}
        rm -f $OGDB/ogdb-$HOSTNAME
@@ -686,6 +685,18 @@ fs_log_size() {
        echo -n $size
 }
 
+fs_inode_ksize() {
+       local facet=${1:-$SINGLEMDS}
+       local fstype=$(facet_fstype $facet)
+       local size=0
+       case $fstype in
+               ldiskfs) size=4;;  # ~4KB per inode
+               zfs)     size=11;; # 10 to 11KB per inode
+       esac
+
+       echo -n $size
+}
+
 check_gss_daemon_nodes() {
     local list=$1
     dname=$2
@@ -817,7 +828,7 @@ facet_type() {
 facet_number() {
        local facet=$1
 
-       if [ $facet == mgs ]; then
+       if [ $facet == mgs ] || [ $facet == client ]; then
                return 1
        fi
 
@@ -964,6 +975,20 @@ facet_vdevice() {
        echo -n $device
 }
 
+running_in_vm() {
+       local virt=$(virt-what 2> /dev/null)
+
+       [ $? -eq 0 ] && [ -n "$virt" ] && { echo $virt; return; }
+
+       virt=$(dmidecode -s system-product-name | awk '{print $1}')
+
+       case $virt in
+               VMware|KVM|VirtualBox|Parallels)
+                       echo $virt | tr '[A-Z]' '[a-z]' ;;
+               *) ;;
+       esac
+}
+
 #
 # Re-read the partition table on failover partner host.
 # After a ZFS storage pool is created on a shared device, the partition table
@@ -1011,7 +1036,8 @@ create_zpool() {
        shift 3
        local opts=${@:-"-o cachefile=none"}
 
-       do_facet $facet "$ZPOOL list -H $poolname >/dev/null 2>&1 ||
+       do_facet $facet "modprobe zfs;
+               $ZPOOL list -H $poolname >/dev/null 2>&1 ||
                $ZPOOL create -f $opts $poolname $vdev"
 }
 
@@ -1077,7 +1103,8 @@ import_zpool() {
 
        if [[ -n "$poolname" ]]; then
                opts+=" -d $(dirname $(facet_vdevice $facet))"
-               do_facet $facet "$ZPOOL list -H $poolname >/dev/null 2>&1 ||
+               do_facet $facet "modprobe zfs;
+                       $ZPOOL list -H $poolname >/dev/null 2>&1 ||
                        $ZPOOL import -f $opts $poolname"
        fi
 }
@@ -1116,7 +1143,7 @@ get_osd_param() {
        local name=$3
 
        do_nodes $nodes "$LCTL get_param -n obdfilter.$device.$name \
-               osd-*.$device.$name 2>&1" | grep -v 'Found no match'
+               osd-*.$device.$name 2>&1" | grep -v 'error:'
 }
 
 set_osd_param() {
@@ -1126,7 +1153,7 @@ set_osd_param() {
        local value=$4
 
        do_nodes $nodes "$LCTL set_param -n obdfilter.$device.$name=$value \
-               osd-*.$device.$name=$value 2>&1" | grep -v 'Found no match'
+               osd-*.$device.$name=$value 2>&1" | grep -v 'error:'
 }
 
 set_debug_size () {
@@ -1135,7 +1162,7 @@ set_debug_size () {
     if [ -f /sys/devices/system/cpu/possible ]; then
         local cpus=$(($(cut -d "-" -f 2 /sys/devices/system/cpu/possible)+1))
     else
-        local cpus=$(getconf _NPROCESSORS_CONF)
+        local cpus=$(getconf _NPROCESSORS_CONF 2>/dev/null)
     fi
 
     # bug 19944, adjust size to be -gt num_possible_cpus()
@@ -1177,6 +1204,15 @@ set_default_debug_facet () {
     set_default_debug_nodes $node
 }
 
+set_hostid () {
+    local hostid=${1:-$(hostid)}
+
+    if [ ! -s /etc/hostid ]; then
+       printf $(echo -n $hostid |
+           sed 's/\(..\)\(..\)\(..\)\(..\)/\\x\4\\x\3\\x\2\\x\1/') >/etc/hostid
+    fi
+}
+
 # Facet functions
 mount_facets () {
        local facets=${1:-$(get_facets)}
@@ -1223,6 +1259,8 @@ mount_facet() {
        local opt=${facet}_opt
        local mntpt=$(facet_mntpt $facet)
        local opts="${!opt} $@"
+       local fstype=$(facet_fstype $facet)
+       local devicelabel
 
        module_loaded lustre || load_modules
 
@@ -1236,6 +1274,16 @@ mount_facet() {
                import_zpool $facet || return ${PIPESTATUS[0]}
        fi
 
+       case $fstype in
+       ldiskfs)
+               devicelabel=$(do_facet ${facet} "$E2LABEL ${!dev}");;
+       zfs)
+               devicelabel=$(do_facet ${facet} "$ZFS get -H -o value \
+                                               lustre:svname ${!dev}");;
+       *)
+               error "unknown fstype!";;
+       esac
+
        echo "Starting ${facet}: $opts ${!dev} $mntpt"
        # for testing LU-482 error handling in mount_facets() and test_0a()
        if [ -f $TMP/test-lu482-trigger ]; then
@@ -1251,6 +1299,11 @@ mount_facet() {
                return $RC
        fi
 
+       health=$(do_facet ${facet} "$LCTL get_param -n health_check")
+       if [[ "$health" != "healthy" ]]; then
+               error "$facet is in a unhealthy state"
+       fi
+
        set_default_debug_facet $facet
 
        if [[ $facet == mds* ]]; then
@@ -1261,7 +1314,6 @@ mount_facet() {
        if [[ $opts =~ .*nosvc.* ]]; then
                echo "Start ${!dev} without service"
        else
-               local fstype=$(facet_fstype $facet)
 
                case $fstype in
                ldiskfs)
@@ -1279,6 +1331,14 @@ mount_facet() {
                esac
        fi
 
+       # commit the device label change to disk
+       if [[ $devicelabel =~ (:[a-zA-Z]{3}[0-9]{4}) ]]; then
+               echo "Commit the device label on ${!dev}"
+               do_facet $facet "sync; sync; sync"
+               sleep 5
+       fi
+
+
        label=$(devicelabel ${facet} ${!dev})
        [ -z "$label" ] && echo no label for ${!dev} && exit 1
        eval export ${facet}_svc=${label}
@@ -1382,70 +1442,6 @@ quota_type() {
        return $rc
 }
 
-# XXX This function is kept for interoperability with old server (< 2.3.50),
-#     it should be removed whenever we drop the interoperability for such
-#     server.
-restore_quota_old() {
-       local mntpt=${1:-$MOUNT}
-       local quota_type=$(quota_type $FSNAME | grep MDT | cut -d "=" -f2)
-       if [ ! "$old_QUOTA_TYPE" ] ||
-               [ "$quota_type" = "$old_QUOTA_TYPE" ]; then
-               return
-       fi
-       quota_save_version $old_QUOTA_TYPE
-}
-
-# XXX This function is kept for interoperability with old server (< 2.3.50),
-#     it should be removed whenever we drop the interoperability for such
-#     server.
-setup_quota_old(){
-       local mntpt=$1
-
-       # no quota enforcement for now and accounting works out of the box
-       return
-
-    # We need save the original quota_type params, and restore them after testing
-
-    # Suppose that quota type the same on mds and ost
-    local quota_type=$(quota_type | grep MDT | cut -d "=" -f2)
-    [ ${PIPESTATUS[0]} -eq 0 ] || error "quota_type failed!"
-    echo "[HOST:$HOSTNAME] [old_quota_type:$quota_type] [new_quota_type:$QUOTA_TYPE]"
-    if [ "$quota_type" != "$QUOTA_TYPE" ]; then
-        export old_QUOTA_TYPE=$quota_type
-        quota_save_version $QUOTA_TYPE
-    else
-        qtype=$(tr -c -d "ug" <<< $QUOTA_TYPE)
-        $LFS quotacheck -$qtype $mntpt || error "quotacheck has failed for $type"
-    fi
-
-    local quota_usrs=$QUOTA_USERS
-
-    # get_filesystem_size
-    local disksz=$(lfs_df $mntpt | grep "summary"  | awk '{print $2}')
-    local blk_soft=$((disksz + 1024))
-    local blk_hard=$((blk_soft + blk_soft / 20)) # Go 5% over
-
-    local Inodes=$(lfs_df -i $mntpt | grep "summary"  | awk '{print $2}')
-    local i_soft=$Inodes
-    local i_hard=$((i_soft + i_soft / 20))
-
-    echo "Total disk size: $disksz  block-softlimit: $blk_soft block-hardlimit:
-        $blk_hard inode-softlimit: $i_soft inode-hardlimit: $i_hard"
-
-    local cmd
-    for usr in $quota_usrs; do
-        echo "Setting up quota on $HOSTNAME:$mntpt for $usr..."
-        for type in u g; do
-            cmd="$LFS setquota -$type $usr -b $blk_soft -B $blk_hard -i $i_soft -I $i_hard $mntpt"
-            echo "+ $cmd"
-            eval $cmd || error "$cmd FAILED!"
-        done
-        # display the quota status
-        echo "Quota settings for $usr : "
-        $LFS quota -v -u $usr $mntpt || true
-    done
-}
-
 # get mdt quota type
 mdt_quota_type() {
        local varsvc=${SINGLEMDS}_svc
@@ -1463,11 +1459,6 @@ ost_quota_type() {
 
 # restore old quota type settings
 restore_quota() {
-       if [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.3.50) ]; then
-               restore_quota_old
-               return
-       fi
-
        if [ "$old_MDT_QUOTA_TYPE" ]; then
                do_facet mgs $LCTL conf_param \
                        $FSNAME.quota.mdt=$old_MDT_QUOTA_TYPE
@@ -1503,11 +1494,6 @@ mdt_free_inodes() {
 }
 
 setup_quota(){
-       if [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.3.50) ]; then
-               setup_quota_old $1
-               return
-       fi
-
        local mntpt=$1
 
        # save old quota type & set new quota type
@@ -1556,32 +1542,44 @@ setup_quota(){
 }
 
 zconf_mount() {
-    local client=$1
-    local mnt=$2
-    local opts=${3:-$MOUNT_OPTS}
-    opts=${opts:+-o $opts}
-    local flags=${4:-$MOUNT_FLAGS}
-
-    local device=$MGSNID:/$FSNAME
-    if [ -z "$mnt" -o -z "$FSNAME" ]; then
-        echo Bad zconf mount command: opt=$flags $opts dev=$device mnt=$mnt
-        exit 1
-    fi
-
-    echo "Starting client: $client: $flags $opts $device $mnt"
-    do_node $client mkdir -p $mnt
-    do_node $client $MOUNT_CMD $flags $opts $device $mnt || return 1
+       local client=$1
+       local mnt=$2
+       local opts=${3:-$MOUNT_OPTS}
+       opts=${opts:+-o $opts}
+       local flags=${4:-$MOUNT_FLAGS}
+
+       local device=$MGSNID:/$FSNAME$FILESET
+       if [ -z "$mnt" -o -z "$FSNAME" ]; then
+               echo "Bad mount command: opt=$flags $opts dev=$device " \
+                    "mnt=$mnt"
+               exit 1
+       fi
+
+       echo "Starting client: $client: $flags $opts $device $mnt"
+       do_node $client mkdir -p $mnt
+       if [ -n "$FILESET" -a -z "$SKIP_FILESET" ];then
+               do_node $client $MOUNT_CMD $flags $opts $MGSNID:/$FSNAME \
+                       $mnt || return 1
+               #disable FILESET if not supported
+               do_nodes $client lctl get_param -n \
+                       mdc.$FSNAME-MDT0000*.import | grep -q subtree ||
+                               device=$MGSNID:/$FSNAME
+               do_node $client mkdir -p $mnt/$FILESET
+               do_node $client "! grep -q $mnt' ' /proc/mounts ||
+                       umount $mnt"
+       fi
+       do_node $client $MOUNT_CMD $flags $opts $device $mnt || return 1
+
+       set_default_debug_nodes $client
 
-    set_default_debug_nodes $client
-
-    return 0
+       return 0
 }
 
 zconf_umount() {
     local client=$1
     local mnt=$2
     local force
-    local busy 
+    local busy
     local need_kill
 
     [ "$3" ] && force=-f
@@ -1622,13 +1620,13 @@ if [ \\\$running -ne \\\$mpts ]; then
     echo \\\$(hostname) env are INSANE!;
     exit 1;
 fi"
-    [ $? -eq 0 ] || rc=1 
+    [ $? -eq 0 ] || rc=1
     done
     return $rc
 }
 
 sanity_mount_check_servers () {
-    [ "$CLIENTONLY" ] && 
+    [ -n "$CLIENTONLY" ] &&
         { echo "CLIENTONLY mode, skip mount_check_servers"; return 0; } || true
     echo Checking servers environments
 
@@ -1664,21 +1662,35 @@ sanity_mount_check () {
 
 # mount clients if not mouted
 zconf_mount_clients() {
-    local clients=$1
-    local mnt=$2
-    local opts=${3:-$MOUNT_OPTS}
-    opts=${opts:+-o $opts}
-    local flags=${4:-$MOUNT_FLAGS}
-
-    local device=$MGSNID:/$FSNAME
-    if [ -z "$mnt" -o -z "$FSNAME" ]; then
-        echo Bad zconf mount command: opt=$flags $opts dev=$device mnt=$mnt
-        exit 1
-    fi
-
-    echo "Starting client $clients: $flags $opts $device $mnt"
-
-    do_nodes $clients "
+       local clients=$1
+       local mnt=$2
+       local opts=${3:-$MOUNT_OPTS}
+       opts=${opts:+-o $opts}
+       local flags=${4:-$MOUNT_FLAGS}
+
+       local device=$MGSNID:/$FSNAME$FILESET
+       if [ -z "$mnt" -o -z "$FSNAME" ]; then
+               echo "Bad conf mount command: opt=$flags $opts dev=$device " \
+                    "mnt=$mnt"
+               exit 1
+       fi
+
+       echo "Starting client $clients: $flags $opts $device $mnt"
+       if [ -n "$FILESET" -a ! -n "$SKIP_FILESET" ]; then
+               do_nodes $clients "! grep -q $mnt' ' /proc/mounts ||
+                       umount $mnt"
+               do_nodes $clients $MOUNT_CMD $flags $opts $MGSNID:/$FSNAME \
+                       $mnt || return 1
+               #disable FILESET if not supported
+               do_nodes $clients lctl get_param -n \
+                       mdc.$FSNAME-MDT0000*.import | grep -q subtree ||
+                               device=$MGSNID:/$FSNAME
+               do_nodes $clients mkdir -p $mnt/$FILESET
+               do_nodes $clients "! grep -q $mnt' ' /proc/mounts ||
+                       umount $mnt"
+       fi
+
+       do_nodes $clients "
 running=\\\$(mount | grep -c $mnt' ');
 rc=0;
 if [ \\\$running -eq 0 ] ; then
@@ -1688,12 +1700,12 @@ if [ \\\$running -eq 0 ] ; then
 fi;
 exit \\\$rc" || return ${PIPESTATUS[0]}
 
-    echo "Started clients $clients: "
-    do_nodes $clients "mount | grep $mnt' '"
+       echo "Started clients $clients: "
+       do_nodes $clients "mount | grep $mnt' '"
 
-    set_default_debug_nodes $clients
+       set_default_debug_nodes $clients
 
-    return 0
+       return 0
 }
 
 zconf_umount_clients() {
@@ -1736,7 +1748,7 @@ shutdown_node_hard () {
         wait_for_function --quiet "! ping -w 3 -c 1 $host" 5 1 && return 0
         echo "waiting for $host to fail attempts=$attempts"
         [ $i -lt $attempts ] || \
-            { echo "$host still pingable after power down! attempts=$attempts" && return 1; } 
+            { echo "$host still pingable after power down! attempts=$attempts" && return 1; }
     done
 }
 
@@ -1907,55 +1919,59 @@ start_client_loads () {
 
 # only for remote client
 check_client_load () {
-    local client=$1
-    local var=$(node_var_name $client)_load
-    local TESTLOAD=run_${!var}.sh
-
-    ps auxww | grep -v grep | grep $client | grep -q "$TESTLOAD" || return 1
-
-    # bug 18914: try to connect several times not only when
-    # check ps, but  while check_catastrophe also
-    local tries=3
-    local RC=254
-    while [ $RC = 254 -a $tries -gt 0 ]; do
-        let tries=$tries-1
-        # assume success
-        RC=0
-        if ! check_catastrophe $client; then
-            RC=${PIPESTATUS[0]}
-            if [ $RC -eq 254 ]; then
-                # FIXME: not sure how long we shuold sleep here
-                sleep 10
-                continue
-            fi
-            echo "check catastrophe failed: RC=$RC "
-            return $RC
-        fi
-    done
-    # We can continue try to connect if RC=254
-    # Just print the warning about this
-    if [ $RC = 254 ]; then
-        echo "got a return status of $RC from do_node while checking catastrophe on $client"
-    fi
-
-    # see if the load is still on the client
-    tries=3
-    RC=254
-    while [ $RC = 254 -a $tries -gt 0 ]; do
-        let tries=$tries-1
-        # assume success
-        RC=0
-        if ! do_node $client "ps auxwww | grep -v grep | grep -q $TESTLOAD"; then
-            RC=${PIPESTATUS[0]}
-            sleep 30
-        fi
-    done
-    if [ $RC = 254 ]; then
-        echo "got a return status of $RC from do_node while checking (catastrophe and 'ps') the client load on $client"
-        # see if we can diagnose a bit why this is
-    fi
+       local client=$1
+       local var=$(node_var_name $client)_load
+       local testload=run_${!var}.sh
+
+       ps auxww | grep -v grep | grep $client | grep -q $testload || return 1
+
+       # bug 18914: try to connect several times not only when
+       # check ps, but  while check_node_health also
+
+       local tries=3
+       local RC=254
+       while [ $RC = 254 -a $tries -gt 0 ]; do
+               let tries=$tries-1
+               # assume success
+               RC=0
+               if ! check_node_health $client; then
+                       RC=${PIPESTATUS[0]}
+                       if [ $RC -eq 254 ]; then
+                               # FIXME: not sure how long we shuold sleep here
+                               sleep 10
+                               continue
+                       fi
+                       echo "check node health failed: RC=$RC "
+                       return $RC
+               fi
+       done
+       # We can continue try to connect if RC=254
+       # Just print the warning about this
+       if [ $RC = 254 ]; then
+               echo "got a return status of $RC from do_node while checking " \
+               "node health on $client"
+       fi
+
+       # see if the load is still on the client
+       tries=3
+       RC=254
+       while [ $RC = 254 -a $tries -gt 0 ]; do
+               let tries=$tries-1
+               # assume success
+               RC=0
+               if ! do_node $client \
+                       "ps auxwww | grep -v grep | grep -q $testload"; then
+                       RC=${PIPESTATUS[0]}
+                       sleep 30
+               fi
+       done
+       if [ $RC = 254 ]; then
+               echo "got a return status of $RC from do_node while checking " \
+               "(node health and 'ps') the client load on $client"
+               # see if we can diagnose a bit why this is
+       fi
 
-    return $RC
+       return $RC
 }
 check_client_loads () {
    local clients=${1//,/ }
@@ -2151,6 +2167,15 @@ sync_all_data() {
                grep -v 'Found no match'
 }
 
+wait_zfs_commit() {
+       # the occupied disk space will be released
+       # only after DMUs are committed
+       if [[ $(facet_fstype $1) == zfs ]]; then
+               echo "sleep $2 for ZFS OSD"
+               sleep $2
+       fi
+}
+
 wait_delete_completed_mds() {
        local MAX_WAIT=${1:-20}
        # for ZFS, waiting more time for DMUs to be committed
@@ -2171,6 +2196,7 @@ wait_delete_completed_mds() {
                mds2sync="$mds2sync $node"
        done
        if [ -z "$mds2sync" ]; then
+               wait_zfs_commit $SINGLEMDS $ZFS_WAIT
                return
        fi
        mds2sync=$(comma_list $mds2sync)
@@ -2188,16 +2214,7 @@ wait_delete_completed_mds() {
                        "$LCTL get_param -n osc.*MDT*.sync_*" | calc_sum)
                #echo "$node: $changes changes on all"
                if [[ $changes -eq 0 ]]; then
-                       etime=$(date +%s)
-                       #echo "delete took $((etime - stime)) seconds"
-
-                       # the occupied disk space will be released
-                       # only after DMUs are committed
-                       if [[ $(facet_fstype $SINGLEMDS) == zfs ]]; then
-                               echo "sleep $ZFS_WAIT for ZFS OSD"
-                               sleep $ZFS_WAIT
-                       fi
-
+                       wait_zfs_commit $SINGLEMDS $ZFS_WAIT
                        return
                fi
                sleep 1
@@ -2404,25 +2421,27 @@ wait_remote_prog () {
     return $rc
 }
 
+lfs_df_check() {
+       local clients=${1:-$CLIENTS}
+
+       if [ -z "$clients" ]; then
+               $LFS df $MOUNT
+       else
+               $PDSH $clients "$LFS df $MOUNT" > /dev/null
+       fi
+}
+
+
 clients_up() {
-    # not every config has many clients
-    sleep 1
-    if [ ! -z "$CLIENTS" ]; then
-        $PDSH $CLIENTS "stat -f $MOUNT" > /dev/null
-    else
-        stat -f $MOUNT > /dev/null
-    fi
+       # not every config has many clients
+       sleep 1
+       lfs_df_check
 }
 
 client_up() {
-    local client=$1
-    # usually checked on particular client or locally
-    sleep 1
-    if [ ! -z "$client" ]; then
-        $PDSH $client "stat -f $MOUNT" > /dev/null
-    else
-        stat -f $MOUNT > /dev/null
-    fi
+       # usually checked on particular client or locally
+       sleep 1
+       lfs_df_check $1
 }
 
 client_evicted() {
@@ -2430,16 +2449,17 @@ client_evicted() {
 }
 
 client_reconnect_try() {
-    uname -n >> $MOUNT/recon
-    if [ -z "$CLIENTS" ]; then
-        df $MOUNT; uname -n >> $MOUNT/recon
-    else
-        do_nodes $CLIENTS "df $MOUNT; uname -n >> $MOUNT/recon" > /dev/null
-    fi
-    echo Connected clients:
-    cat $MOUNT/recon
-    ls -l $MOUNT/recon > /dev/null
-    rm $MOUNT/recon
+       local f=$MOUNT/recon
+
+       uname -n >> $f
+       if [ -z "$CLIENTS" ]; then
+               $LFS df $MOUNT; uname -n >> $f
+       else
+               do_nodes $CLIENTS "$LFS df $MOUNT; uname -n >> $f" > /dev/null
+       fi
+       echo "Connected clients: $(cat $f)"
+       ls -l $f > /dev/null
+       rm $f
 }
 
 client_reconnect() {
@@ -2534,7 +2554,7 @@ obd_name() {
 replay_barrier() {
        local facet=$1
        do_facet $facet "sync; sync; sync"
-       df $MOUNT
+       $LFS df $MOUNT
 
        # make sure there will be no seq change
        local clients=${CLIENTS:-$HOSTNAME}
@@ -2619,7 +2639,7 @@ fail() {
 
        facet_failover $* || error "failover: $?"
        wait_clients_import_state "$clients" "$facets" FULL
-       clients_up || error "post-failover df: $?"
+       clients_up || error "post-failover stat: $?"
 }
 
 fail_nodf() {
@@ -2633,8 +2653,8 @@ fail_abort() {
        change_active $facet
        wait_for_facet $facet
        mount_facet $facet -o abort_recovery
-       clients_up || echo "first df failed: $?"
-       clients_up || error "post-failover df: $?"
+       clients_up || echo "first stat failed: $?"
+       clients_up || error "post-failover stat: $?"
 }
 
 do_lmc() {
@@ -3241,7 +3261,7 @@ facet_mntpt () {
     [[ $facet = mgs ]] && combined_mgs_mds && facet="mds1"
 
     local var=${facet}_MOUNT
-    eval mntpt=${!var:-${MOUNT%/*}/$facet}
+    eval mntpt=${!var:-${MOUNT}-$facet}
 
     echo -n $mntpt
 }
@@ -3249,7 +3269,7 @@ facet_mntpt () {
 mount_ldiskfs() {
        local facet=$1
        local dev=$(facet_device $facet)
-       local mnt=$(facet_mntpt $facet)
+       local mnt=${2:-$(facet_mntpt $facet)}
        local opts
 
        if ! do_facet $facet test -b $dev; then
@@ -3261,7 +3281,7 @@ mount_ldiskfs() {
 unmount_ldiskfs() {
        local facet=$1
        local dev=$(facet_device $facet)
-       local mnt=$(facet_mntpt $facet)
+       local mnt=${2:-$(facet_mntpt $facet)}
 
        do_facet $facet $UMOUNT $mnt
 }
@@ -3273,7 +3293,7 @@ var_name() {
 mount_zfs() {
        local facet=$1
        local ds=$(facet_device $facet)
-       local mnt=$(facet_mntpt $facet)
+       local mnt=${2:-$(facet_mntpt $facet)}
        local canmnt
        local mntpt
 
@@ -3296,7 +3316,7 @@ mount_zfs() {
 unmount_zfs() {
        local facet=$1
        local ds=$(facet_device $facet)
-       local mnt=$(facet_mntpt $facet)
+       local mnt=${2:-$(facet_mntpt $facet)}
        local var_mntpt=mz_$(var_name ${facet}_$ds)_mountpoint
        local var_canmnt=mz_$(var_name ${facet}_$ds)_canmount
        local mntpt=${!var_mntpt}
@@ -3312,16 +3332,18 @@ unmount_zfs() {
 
 mount_fstype() {
        local facet=$1
+       local mnt=$2
        local fstype=$(facet_fstype $facet)
 
-       mount_$fstype $facet
+       mount_$fstype $facet $mnt
 }
 
 unmount_fstype() {
        local facet=$1
+       local mnt=$2
        local fstype=$(facet_fstype $facet)
 
-       unmount_$fstype $facet
+       unmount_$fstype $facet $mnt
 }
 
 ########
@@ -3341,7 +3363,8 @@ stopall() {
     zconf_umount_clients $clients $MOUNT "$*" || true
     [ -n "$MOUNT2" ] && zconf_umount_clients $clients $MOUNT2 "$*" || true
 
-    [ "$CLIENTONLY" ] && return
+    [ -n "$CLIENTONLY" ] && return
+
     # The add fn does rm ${facet}active file, this would be enough
     # if we use do_facet <facet> only after the facet added, but
     # currently we use do_facet mds in local.sh
@@ -3364,12 +3387,14 @@ stopall() {
 }
 
 cleanup_echo_devs () {
-    local devs=$($LCTL dl | grep echo | awk '{print $4}')
+       trap 0
+       local dev
+       local devs=$($LCTL dl | grep echo | awk '{print $4}')
 
-    for dev in $devs; do
-        $LCTL --device $dev cleanup
-        $LCTL --device $dev detach
-    done
+       for dev in $devs; do
+               $LCTL --device $dev cleanup
+               $LCTL --device $dev detach
+       done
 }
 
 cleanupall() {
@@ -3430,7 +3455,6 @@ mkfs_opts() {
        opts+=${LDLM_TIMEOUT:+" --param=sys.ldlm_timeout=$LDLM_TIMEOUT"}
 
        if [ $type == MDS ]; then
-               opts+=${SECLEVEL:+" --param=mdt.sec_level"}
                opts+=${MDSCAPA:+" --param-mdt.capa=$MDSCAPA"}
                opts+=${STRIPE_BYTES:+" --param=lov.stripesize=$STRIPE_BYTES"}
                opts+=${STRIPES_PER_OBJ:+" --param=lov.stripecount=$STRIPES_PER_OBJ"}
@@ -3454,7 +3478,6 @@ mkfs_opts() {
        fi
 
        if [ $type == OST ]; then
-               opts+=${SECLEVEL:+" --param=ost.sec_level"}
                opts+=${OSSCAPA:+" --param=ost.capa=$OSSCAPA"}
 
                if [ $fstype == ldiskfs ]; then
@@ -3549,9 +3572,16 @@ format_ost() {
 
 formatall() {
        stopall
+       # Set hostid for ZFS/SPL zpool import protection
+       # (Assumes MDS version is also OSS version)
+       if [ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.8.54) ];
+       then
+           do_rpc_nodes "$(comma_list $(remote_nodes_list))" set_hostid
+       fi
+
        # We need ldiskfs here, may as well load them all
        load_modules
-       [ "$CLIENTONLY" ] && return
+       [ -n "$CLIENTONLY" ] && return
        echo Formatting mgs, mds, osts
        if ! combined_mgs_mds ; then
                format_mgs
@@ -3641,21 +3671,19 @@ writeconf_all () {
 }
 
 setupall() {
-    nfs_client_mode && return
+       nfs_client_mode && return
        cifs_client_mode && return
 
-    sanity_mount_check ||
-        error "environments are insane!"
+       sanity_mount_check || error "environments are insane!"
 
-    load_modules
+       load_modules
 
-    if [ -z "$CLIENTONLY" ]; then
-        echo Setup mgs, mdt, osts
-        echo $WRITECONF | grep -q "writeconf" && \
-            writeconf_all
-        if ! combined_mgs_mds ; then
+       if [ -z "$CLIENTONLY" ]; then
+               echo Setup mgs, mdt, osts
+               echo $WRITECONF | grep -q "writeconf" && writeconf_all
+               if ! combined_mgs_mds ; then
                        start mgs $(mgsdevname) $MGS_MOUNT_OPTS
-        fi
+               fi
 
         for num in `seq $MDSCOUNT`; do
             DEVNAME=$(mdsdevname $num)
@@ -3724,7 +3752,7 @@ mounted_lustre_filesystems() {
 }
 
 init_facet_vars () {
-       [ "$CLIENTONLY" ] && return 0
+       [ -n "$CLIENTONLY" ] && return 0
        local facet=$1
        shift
        local device=$1
@@ -3849,14 +3877,17 @@ set_conf_param_and_check() {
        do_facet mgs "$LCTL conf_param $PARAM='$FINAL'" ||
                error "conf_param $PARAM failed"
 
-       wait_update $(facet_host $myfacet) "$TEST" "$FINAL" ||
+       wait_update_facet $myfacet "$TEST" "$FINAL" ||
                error "check $PARAM failed!"
 }
 
 init_param_vars () {
-       remote_mds_nodsh ||
-               TIMEOUT=$(do_facet $SINGLEMDS "lctl get_param -n timeout")
+       TIMEOUT=$(lctl get_param -n timeout)
+       TIMEOUT=${TIMEOUT:-20}
 
+       remote_mds_nodsh && log "Using TIMEOUT=$TIMEOUT" && return 0
+
+       TIMEOUT=$(do_facet $SINGLEMDS "lctl get_param -n timeout")
        log "Using TIMEOUT=$TIMEOUT"
 
        osc_ensure_active $SINGLEMDS $TIMEOUT
@@ -3917,14 +3948,14 @@ check_config_client () {
     local mntpt=$1
 
     local mounted=$(mount | grep " $mntpt ")
-    if [ "$CLIENTONLY" ]; then
+    if [ -n "$CLIENTONLY" ]; then
         # bug 18021
         # CLIENTONLY should not depend on *_HOST settings
         local mgc=$($LCTL device_list | awk '/MGC/ {print $4}')
         # in theory someone could create a new,
         # client-only config file that assumed lustre was already
         # configured and didn't set the MGSNID. If MGSNID is not set,
-        # then we should use the mgs nid currently being used 
+        # then we should use the mgs nid currently being used
         # as the default value. bug 18021
         [[ x$MGSNID = x ]] &&
             MGSNID=${mgc//MGC/}
@@ -3939,9 +3970,9 @@ check_config_client () {
         return 0
     fi
 
-    local myMGS_host=$mgs_HOST   
+    local myMGS_host=$mgs_HOST
     if [ "$NETTYPE" = "ptl" ]; then
-        myMGS_host=$(h2ptl $mgs_HOST | sed -e s/@ptl//) 
+        myMGS_host=$(h2ptl $mgs_HOST | sed -e s/@ptl//)
     fi
 
     echo Checking config lustre mounted on $mntpt
@@ -4006,21 +4037,22 @@ is_empty_fs() {
 }
 
 check_and_setup_lustre() {
-    nfs_client_mode && return
+       sanitize_parameters
+       nfs_client_mode && return
        cifs_client_mode && return
 
-    local MOUNTED=$(mounted_lustre_filesystems)
-
-    local do_check=true
-    # 1.
-    # both MOUNT and MOUNT2 are not mounted
-    if ! is_mounted $MOUNT && ! is_mounted $MOUNT2; then
-        [ "$REFORMAT" ] && formatall
-        # setupall mounts both MOUNT and MOUNT2 (if MOUNT_2 is set)
-        setupall
-        is_mounted $MOUNT || error "NAME=$NAME not mounted"
-        export I_MOUNTED=yes
-        do_check=false
+       local MOUNTED=$(mounted_lustre_filesystems)
+
+       local do_check=true
+       # 1.
+       # both MOUNT and MOUNT2 are not mounted
+       if ! is_mounted $MOUNT && ! is_mounted $MOUNT2; then
+               [ "$REFORMAT" = "yes" ] && formatall
+               # setupall mounts both MOUNT and MOUNT2 (if MOUNT_2 is set)
+               setupall
+               is_mounted $MOUNT || error "NAME=$NAME not mounted"
+               export I_MOUNTED=yes
+               do_check=false
     # 2.
     # MOUNT2 is mounted
     elif is_mounted $MOUNT2; then
@@ -4043,7 +4075,7 @@ check_and_setup_lustre() {
                     restore_mount $MOUNT2
                     export I_MOUNTED2=yes
                 fi
-            fi 
+            fi
 
     # 5.
     # MOUNT is mounted MOUNT2 is not mounted
@@ -4064,7 +4096,7 @@ check_and_setup_lustre() {
         set_default_debug_nodes $(comma_list $(nodes_list))
     fi
 
-       if [ $(lower $OSD_TRACK_DECLARES_LBUG) == 'yes' ] ; then
+       if [ -z "$CLIENTONLY" -a $(lower $OSD_TRACK_DECLARES_LBUG) == 'yes' ]; then
                local facets=""
                [ "$(facet_fstype ost1)" = "ldiskfs" ] &&
                        facets="$(get_facets OST)"
@@ -4084,12 +4116,14 @@ check_and_setup_lustre() {
                set_flavor_all $SEC
        fi
 
-       #Enable remote MDT create for testing
-       for num in $(seq $MDSCOUNT); do
-               do_facet mds$num \
-                       lctl set_param -n mdt.${FSNAME}*.enable_remote_dir=1 \
-                               2>/dev/null
-       done
+       if [ -z "$CLIENTONLY" ]; then
+               # Enable remote MDT create for testing
+               for num in $(seq $MDSCOUNT); do
+                       do_facet mds$num \
+                               lctl set_param -n mdt.${FSNAME}*.enable_remote_dir=1 \
+                                       2>/dev/null
+               done
+       fi
 
        if [ "$ONLY" == "setup" ]; then
                exit 0
@@ -4308,8 +4342,12 @@ check_and_cleanup_lustre() {
        fi
 
        if is_mounted $MOUNT; then
-               [ -n "$DIR" ] && rm -rf $DIR/[Rdfs][0-9]* ||
-                       error "remove sub-test dirs failed"
+               if $DO_CLEANUP; then
+                       [ -n "$DIR" ] && rm -rf $DIR/[Rdfs][0-9]* ||
+                               error "remove sub-test dirs failed"
+               else
+                       echo "skip cleanup"
+               fi
                [ "$ENABLE_QUOTA" ] && restore_quota || true
        fi
 
@@ -4632,37 +4670,15 @@ clear_failloc() {
 }
 
 set_nodes_failloc () {
-       do_nodes $(comma_list $1)  lctl set_param fail_val=0 fail_loc=$2
+       local fv=${3:-0}
+       do_nodes $(comma_list $1)  lctl set_param fail_val=$fv fail_loc=$2
 }
 
 cancel_lru_locks() {
-    $LCTL mark "cancel_lru_locks $1 start"
-
-    if [ $1 != "MGC" ]; then
-       for d in $(lctl get_param -N ldlm.namespaces.*.lru_size |
-                egrep -i $1); do
-           $LCTL set_param -n $d=clear
-       done
-       $LCTL get_param ldlm.namespaces.*.lock_unused_count | egrep -i $1 |
-               grep -v '=0'
-    else
-       for d in $(find \
-               /{proc,sys}/fs/lustre/ldlm/namespaces/*$1*/lru_size \
-               2> /dev/null); do
-           echo "clear" > $d
-       done
-
-       for d in $(find \
-               /{proc,sys}/fs/lustre/ldlm/namespaces/*$1*/lock_unused_count \
-               2> /dev/null); do
-           if [ $(cat $d) != 0 ]; then
-               echo "ldlm.namespaces.$(echo "$d" |
-                       cut -f 7 -d'/').lock_unused_count=$(cat $d)"
-           fi
-       done
-    fi
-
-    $LCTL mark "cancel_lru_locks $1 stop"
+       #$LCTL mark "cancel_lru_locks $1 start"
+       $LCTL set_param -n ldlm.namespaces.*$1*.lru_size=clear
+       $LCTL get_param ldlm.namespaces.*$1*.lock_unused_count | grep -v '=0'
+       #$LCTL mark "cancel_lru_locks $1 stop"
 }
 
 default_lru_size()
@@ -4702,13 +4718,21 @@ pgcache_empty() {
 }
 
 debugsave() {
-    DEBUGSAVE="$(lctl get_param -n debug)"
+       DEBUGSAVE="$(lctl get_param -n debug)"
+       DEBUGSAVE_SERVER=$(do_facet $SINGLEMDS "$LCTL get_param -n debug")
 }
 
 debugrestore() {
-    [ -n "$DEBUGSAVE" ] && \
-        do_nodes $(comma_list $(nodes_list)) "$LCTL set_param debug=\\\"${DEBUGSAVE}\\\";"
-    DEBUGSAVE=""
+       [ -n "$DEBUGSAVE" ] &&
+               do_nodes $CLIENTS "$LCTL set_param debug=\\\"${DEBUGSAVE}\\\""||
+               true
+       DEBUGSAVE=""
+
+       [ -n "$DEBUGSAVE_SERVER" ] &&
+               do_nodes $(comma_list $(all_server_nodes)) \
+                        "$LCTL set_param debug=\\\"${DEBUGSAVE_SERVER}\\\"" ||
+                        true
+       DEBUGSAVE_SERVER=""
 }
 
 debug_size_save() {
@@ -4739,20 +4763,17 @@ stop_full_debug_logging() {
 
 # prints bash call stack
 print_stack_trace() {
+       local skip=${1:-1}
        echo "  Trace dump:"
-       for (( i=1; i < ${#BASH_LINENO[*]} ; i++ )) ; do
-               local s=${BASH_SOURCE[$i]}
-               local l=${BASH_LINENO[$i-1]}
-               local f=${FUNCNAME[$i]}
-               echo "  = $s:$l:$f()"
+       for (( i=$skip; i < ${#BASH_LINENO[*]} ; i++ )) ; do
+               local src=${BASH_SOURCE[$i]}
+               local lineno=${BASH_LINENO[$i-1]}
+               local funcname=${FUNCNAME[$i]}
+               echo "  = $src:$lineno:$funcname()"
        done
 }
 
-##################################
-# Test interface
-##################################
-
-error_noexit() {
+report_error() {
        local TYPE=${TYPE:-"FAIL"}
 
        local dump=true
@@ -4762,10 +4783,8 @@ error_noexit() {
                dump=false
        fi
 
-
        log " ${TESTSUITE} ${TESTNAME}: @@@@@@ ${TYPE}: $@ "
-       print_stack_trace >&2
-
+       (print_stack_trace 2) >&2
        mkdir -p $LOGDIR
        # We need to dump the logs on all nodes
        if $dump; then
@@ -4784,6 +4803,17 @@ error_noexit() {
                        echo "$@" > $LOGDIR/err
                fi
        fi
+
+       # cleanup the env for failed tests
+       reset_fail_loc
+}
+
+##################################
+# Test interface
+##################################
+
+error_noexit() {
+       report_error "$@"
 }
 
 exit_status () {
@@ -4795,12 +4825,13 @@ exit_status () {
 }
 
 error() {
-       error_noexit "$@"
+       report_error "$@"
        exit 1
 }
 
 error_exit() {
-       error "$@"
+       report_error "$@"
+       exit 1
 }
 
 # use only if we are ignoring failures for this test, bugno required.
@@ -4810,15 +4841,27 @@ error_exit() {
 error_ignore() {
        local TYPE="IGNORE ($1)"
        shift
-       error_noexit "$@"
+       report_error "$@"
 }
 
 error_and_remount() {
-       error_noexit "$@"
+       report_error "$@"
        remount_client $MOUNT
        exit 1
 }
 
+# Throw an error if it's not running in vm - usually for performance
+# verification
+error_not_in_vm() {
+       local virt=$(running_in_vm)
+       if [[ -n "$virt" ]]; then
+               echo "running in VM '$virt', ignore error"
+               error_ignore env=$virt "$@"
+       else
+               error "$@"
+       fi
+}
+
 skip_env () {
        $FAIL_ON_SKIP_ENV && error false $@ || skip $@
 }
@@ -5004,17 +5047,17 @@ check_mds() {
 }
 
 reset_fail_loc () {
-    echo -n "Resetting fail_loc on all nodes..."
-    do_nodes $(comma_list $(nodes_list)) "lctl set_param -n fail_loc=0 \
-           fail_val=0 2>/dev/null || true"
-    echo done.
+       echo -n "Resetting fail_loc on all nodes..."
+       do_nodes $(comma_list $(nodes_list)) "lctl set_param -n fail_loc=0 \
+           fail_val=0 2>/dev/null" || true
+       echo done.
 }
 
 
 #
-# Log a message (on all nodes) padded with "=" before and after. 
+# Log a message (on all nodes) padded with "=" before and after.
 # Also appends a timestamp and prepends the testsuite name.
-# 
+#
 
 EQUALS="===================================================================================================="
 banner() {
@@ -5026,6 +5069,18 @@ banner() {
     log "$msg== $(date +"%H:%M:%S (%s)")"
 }
 
+check_dmesg_for_errors() {
+       local res
+       local errors="VFS: Busy inodes after unmount of\|\
+ldiskfs_check_descriptors: Checksum for group 0 failed\|\
+group descriptors corrupted"
+
+       res=$(do_nodes $(comma_list $(nodes_list)) "dmesg" | grep "$errors")
+       [ -z "$res" ] && return 0
+       echo "Kernel error detected: $res"
+       return 1
+}
+
 #
 # Run a single test function and cleanup after it.
 #
@@ -5041,12 +5096,17 @@ run_one() {
        local SAVE_UMASK=`umask`
        umask 0022
 
+       if ! grep -q $DIR /proc/mounts; then
+               $SETUP
+       fi
+
        banner "test $testnum: $message"
        test_${testnum} || error "test_$testnum failed with $?"
        cd $SAVE_PWD
        reset_fail_loc
        check_grant ${testnum} || error "check_grant $testnum failed with $?"
-       check_catastrophe || error "LBUG/LASSERT detected"
+       check_node_health
+       check_dmesg_for_errors || error "Error in dmesg detected"
        if [ "$PARALLEL" != "yes" ]; then
                ps auxww | grep -v grep | grep -q multiop &&
                                        error "multiop still running"
@@ -5055,6 +5115,7 @@ run_one() {
        unset tdir
        unset tfile
        umask $SAVE_UMASK
+       $CLEANUP
        return 0
 }
 
@@ -5247,15 +5308,15 @@ remote_mds ()
 
 remote_mds_nodsh()
 {
-    [ "$CLIENTONLY" ] && return 0 || true
-    remote_mds && [ "$PDSH" = "no_dsh" -o -z "$PDSH" -o -z "$mds_HOST" ]
+       [ -n "$CLIENTONLY" ] && return 0 || true
+       remote_mds && [ "$PDSH" = "no_dsh" -o -z "$PDSH" -o -z "$mds_HOST" ]
 }
 
 require_dsh_mds()
 {
-        remote_mds_nodsh && echo "SKIP: $TESTSUITE: remote MDS with nodsh" && \
-            MSKIPPED=1 && return 1
-        return 0
+       remote_mds_nodsh && echo "SKIP: $TESTSUITE: remote MDS with nodsh" &&
+               MSKIPPED=1 && return 1
+       return 0
 }
 
 remote_ost ()
@@ -5269,8 +5330,8 @@ remote_ost ()
 
 remote_ost_nodsh()
 {
-    [ "$CLIENTONLY" ] && return 0 || true 
-    remote_ost && [ "$PDSH" = "no_dsh" -o -z "$PDSH" -o -z "$ost_HOST" ]
+       [ -n "$CLIENTONLY" ] && return 0 || true
+       remote_ost && [ "$PDSH" = "no_dsh" -o -z "$PDSH" -o -z "$ost_HOST" ]
 }
 
 require_dsh_ost()
@@ -5282,10 +5343,10 @@ require_dsh_ost()
 
 remote_mgs_nodsh()
 {
-       [ "$CLIENTONLY" ] && return 0 || true
-    local MGS 
-    MGS=$(facet_host mgs)
-    remote_node $MGS && [ "$PDSH" = "no_dsh" -o -z "$PDSH" -o -z "$ost_HOST" ]
+       [ -n "$CLIENTONLY" ] && return 0 || true
+       local MGS
+       MGS=$(facet_host mgs)
+       remote_node $MGS && [ "$PDSH" = "no_dsh" -o -z "$PDSH" -o -z "$ost_HOST" ]
 }
 
 local_mode ()
@@ -5446,19 +5507,14 @@ get_random_entry () {
     rnodes=${rnodes//,/ }
 
     local -a nodes=($rnodes)
-    local num=${#nodes[@]} 
+    local num=${#nodes[@]}
     local i=$((RANDOM * num * 2 / 65536))
 
     echo ${nodes[i]}
 }
 
 client_only () {
-    [ "$CLIENTONLY" ] || [ "$CLIENTMODSONLY" = yes ]
-}
-
-is_patchless ()
-{
-    lctl get_param version | grep -q patchless
+       [ -n "$CLIENTONLY" ] || [ "x$CLIENTMODSONLY" = "xyes" ]
 }
 
 check_versions () {
@@ -5745,16 +5801,21 @@ restore_lustre_params() {
        done
 }
 
-check_catastrophe() {
+check_node_health() {
        local nodes=${1:-$(comma_list $(nodes_list))}
 
-       do_nodes $nodes "rc=0;
-val=\\\$($LCTL get_param -n catastrophe 2>&1);
-if [[ \\\$? -eq 0 && \\\$val -ne 0 ]]; then
-       echo \\\$(hostname -s): \\\$val;
-       rc=\\\$val;
-fi;
-exit \\\$rc"
+       for node in ${nodes//,/ }; do
+               check_network "$node" 5
+               if [ $? -eq 0 ]; then
+                       do_node $node "rc=0;
+                       val=\\\$($LCTL get_param -n catastrophe 2>&1);
+                       if [[ \\\$? -eq 0 && \\\$val -ne 0 ]]; then
+                               echo \\\$(hostname -s): \\\$val;
+                               rc=\\\$val;
+                       fi;
+                       exit \\\$rc" || error "$node:LBUG/LASSERT detected"
+               fi
+       done
 }
 
 mdsrate_cleanup () {
@@ -6143,79 +6204,99 @@ oos_full() {
        return $OSCFULL
 }
 
-pool_list () {
-   do_facet mgs lctl pool_list $1
+list_pool() {
+       echo -e "$(do_facet $SINGLEMDS $LCTL pool_list $1 | sed '1d')"
+}
+
+check_pool_not_exist() {
+       local fsname=${1%%.*}
+       local poolname=${1##$fsname.}
+       [[ $# -ne 1 ]] && return 0
+       [[ x$poolname = x ]] &&  return 0
+       list_pool $fsname | grep -w $1 && return 1
+       return 0
 }
 
 create_pool() {
-    local fsname=${1%%.*}
-    local poolname=${1##$fsname.}
-
-    do_facet mgs lctl pool_new $1
-    local RC=$?
-    # get param should return err unless pool is created
-    [[ $RC -ne 0 ]] && return $RC
-
-    wait_update $HOSTNAME "lctl get_param -n lov.$fsname-*.pools.$poolname \
-        2>/dev/null || echo foo" "" || RC=1
-    if [[ $RC -eq 0 ]]; then
-        add_pool_to_list $1
-    else
-        error "pool_new failed $1"
-    fi
-    return $RC
+       local fsname=${1%%.*}
+       local poolname=${1##$fsname.}
+
+       do_facet mgs lctl pool_new $1
+       local RC=$?
+       # get param should return err unless pool is created
+       [[ $RC -ne 0 ]] && return $RC
+
+       for mds_id in $(seq $MDSCOUNT); do
+               local mdt_id=$((mds_id-1))
+               local lodname=$fsname-MDT$(printf "%04x" $mdt_id)-mdtlov
+               wait_update_facet mds$mds_id \
+                       "lctl get_param -n lod.$lodname.pools.$poolname \
+                               2>/dev/null || echo foo" "" ||
+                       error "mds$mds_id: pool_new failed $1"
+       done
+       wait_update $HOSTNAME "lctl get_param -n lov.$fsname-*.pools.$poolname \
+               2>/dev/null || echo foo" "" || error "pool_new failed $1"
+
+       add_pool_to_list $1
+       return $RC
 }
 
 add_pool_to_list () {
-    local fsname=${1%%.*}
-    local poolname=${1##$fsname.}
+       local fsname=${1%%.*}
+       local poolname=${1##$fsname.}
 
-    local listvar=${fsname}_CREATED_POOLS
-    eval export ${listvar}=$(expand_list ${!listvar} $poolname)
+       local listvar=${fsname}_CREATED_POOLS
+       local temp=${listvar}=$(expand_list ${!listvar} $poolname)
+       eval export $temp
 }
 
 remove_pool_from_list () {
-    local fsname=${1%%.*}
-    local poolname=${1##$fsname.}
+       local fsname=${1%%.*}
+       local poolname=${1##$fsname.}
 
-    local listvar=${fsname}_CREATED_POOLS
-    eval export ${listvar}=$(exclude_items_from_list ${!listvar} $poolname)
+       local listvar=${fsname}_CREATED_POOLS
+       local temp=${listvar}=$(exclude_items_from_list ${!listvar} $poolname)
+       eval export $temp
 }
 
 destroy_pool_int() {
-    local ost
-    local OSTS=$(do_facet $SINGLEMDS lctl pool_list $1 | \
-        awk '$1 !~ /^Pool:/ {print $1}')
-    for ost in $OSTS; do
-        do_facet mgs lctl pool_remove $1 $ost
-    done
-    do_facet mgs lctl pool_destroy $1
+       local ost
+       local OSTS=$(list_pool $1)
+       for ost in $OSTS; do
+               do_facet mgs lctl pool_remove $1 $ost
+       done
+       do_facet mgs lctl pool_destroy $1
 }
 
 # <fsname>.<poolname> or <poolname>
 destroy_pool() {
-    local fsname=${1%%.*}
-    local poolname=${1##$fsname.}
+       local fsname=${1%%.*}
+       local poolname=${1##$fsname.}
 
-    [[ x$fsname = x$poolname ]] && fsname=$FSNAME
+       [[ x$fsname = x$poolname ]] && fsname=$FSNAME
 
-    local RC
+       local RC
 
-    pool_list $fsname.$poolname || return $?
+       check_pool_not_exist $fsname.$poolname
+       [[ $? -eq 0 ]] && return 0
 
-    destroy_pool_int $fsname.$poolname
-    RC=$?
-    [[ $RC -ne 0 ]] && return $RC
+       destroy_pool_int $fsname.$poolname
+       RC=$?
+       [[ $RC -ne 0 ]] && return $RC
+       for mds_id in $(seq $MDSCOUNT); do
+               local mdt_id=$((mds_id-1))
+               local lodname=$fsname-MDT$(printf "%04x" $mdt_id)-mdtlov
+               wait_update_facet mds$mds_id \
+                       "lctl get_param -n lod.$lodname.pools.$poolname \
+                               2>/dev/null || echo foo" "foo" ||
+                       error "mds$mds_id: destroy pool failed $1"
+       done
+       wait_update $HOSTNAME "lctl get_param -n lov.$fsname-*.pools.$poolname \
+               2>/dev/null || echo foo" "foo" || error "destroy pool failed $1"
 
-    wait_update $HOSTNAME "lctl get_param -n lov.$fsname-*.pools.$poolname \
-      2>/dev/null || echo foo" "foo" || RC=1
+       remove_pool_from_list $fsname.$poolname
 
-    if [[ $RC -eq 0 ]]; then
-        remove_pool_from_list $fsname.$poolname
-    else
-        error "destroy pool failed $1"
-    fi
-    return $RC
+       return $RC
 }
 
 destroy_pools () {
@@ -6223,8 +6304,6 @@ destroy_pools () {
     local poolname
     local listvar=${fsname}_CREATED_POOLS
 
-    pool_list $fsname
-
     [ x${!listvar} = x ] && return 0
 
     echo destroy the created pools: ${!listvar}
@@ -6259,7 +6338,7 @@ gather_logs () {
     suffix="$ts.log"
     echo "Dumping lctl log to ${prefix}.*.${suffix}"
 
-    if [ "$CLIENTONLY" -o "$PDSH" == "no_dsh" ]; then
+    if [ -n "$CLIENTONLY" -o "$PDSH" == "no_dsh" ]; then
         echo "Dumping logs only on local client."
         $LCTL dk > ${prefix}.debug_log.$(hostname -s).${suffix}
         dmesg > ${prefix}.dmesg.$(hostname -s).${suffix}
@@ -6316,6 +6395,31 @@ max_recovery_time() {
        echo -n $service_time
 }
 
+recovery_time_min() {
+       local connection_switch_min=5
+       local connection_switch_inc=5
+       local connection_switch_max
+       local reconnect_delay_max
+       local initial_connect_timeout
+       local max
+       local timout_20
+
+       #connection_switch_max=min(50, max($connection_switch_min,$TIMEOUT)
+       (($connection_switch_min > $TIMEOUT)) &&
+               max=$connection_switch_min || max=$TIMEOUT
+       (($max < 50)) && connection_switch_max=$max || connection_switch_max=50
+
+       #initial_connect_timeout = max(connection_switch_min, obd_timeout/20)
+       timeout_20=$((TIMEOUT/20))
+       (($connection_switch_min > $timeout_20)) &&
+               initial_connect_timeout=$connection_switch_min ||
+               initial_connect_timeout=$timeout_20
+
+       reconnect_delay_max=$((connection_switch_max + connection_switch_inc + \
+                              initial_connect_timeout))
+       echo $((2 * reconnect_delay_max))
+}
+
 get_clients_mount_count () {
     local clients=${CLIENTS:-`hostname`}
 
@@ -6640,29 +6744,36 @@ check_write_access() {
 }
 
 init_logging() {
-    if [[ -n $YAML_LOG ]]; then
-        return
-    fi
-    local SAVE_UMASK=`umask`
-    umask 0000
-
-    export YAML_LOG=${LOGDIR}/results.yml
-    mkdir -p $LOGDIR
-    init_clients_lists
-
-    if [ ! -f $YAML_LOG ]; then       # If the yaml log already exists then we will just append to it
-      if check_shared_dir $LOGDIR; then
-          touch $LOGDIR/shared
-          echo "Logging to shared log directory: $LOGDIR"
-      else
-          echo "Logging to local directory: $LOGDIR"
-      fi
+       [[ -n $YAML_LOG ]] && return
+       local save_umask=$(umask)
+       umask 0000
 
-      yml_nodes_file $LOGDIR >> $YAML_LOG
-      yml_results_file >> $YAML_LOG
-    fi
+       export YAML_LOG=${LOGDIR}/results.yml
+       mkdir -p $LOGDIR
+       init_clients_lists
+
+       # If the yaml log already exists then we will just append to it
+       if [ ! -f $YAML_LOG ]; then
+               if check_shared_dir $LOGDIR; then
+                       touch $LOGDIR/shared
+                       echo "Logging to shared log directory: $LOGDIR"
+               else
+                       echo "Logging to local directory: $LOGDIR"
+               fi
+
+               yml_nodes_file $LOGDIR >> $YAML_LOG
+               yml_results_file >> $YAML_LOG
+       fi
 
-    umask $SAVE_UMASK
+       umask $save_umask
+
+       # If modules are not yet loaded then older "lctl lustre_build_version"
+       # will fail.  Use lctl build version instead.
+       log "Client: $($LCTL lustre_build_version)"
+       log "MDS: $(do_facet $SINGLEMDS $LCTL lustre_build_version 2>/dev/null||
+                   do_facet $SINGLEMDS $LCTL --version)"
+       log "OSS: $(do_facet ost1 $LCTL lustre_build_version 2> /dev/null ||
+                   do_facet ost1 $LCTL --version)"
 }
 
 log_test() {
@@ -6864,11 +6975,10 @@ get_obd_size() {
 #
 get_page_size() {
        local facet=$1
-       local size
+       local size=$(getconf PAGE_SIZE 2>/dev/null)
 
-       size=$(do_facet $facet getconf PAGE_SIZE)
-       [[ ${PIPESTATUS[0]} = 0 && -n "$size" ]] || size=4096
-       echo -n $size
+       [ -z "$CLIENTONLY" ] && size=$(do_facet $facet getconf PAGE_SIZE)
+       echo -n ${size:-4096}
 }
 
 #
@@ -6879,20 +6989,20 @@ get_block_count() {
        local device=$2
        local count
 
-       count=$(do_facet $facet "$DUMPE2FS -h $device 2>&1" |
+       [ -z "$CLIENTONLY" ] && count=$(do_facet $facet "$DUMPE2FS -h $device 2>&1" |
                awk '/^Block count:/ {print $3}')
-       echo -n $count
+       echo -n ${count:-0}
 }
 
 # Get the block size of the filesystem.
 get_block_size() {
-    local facet=$1
-    local device=$2
-    local size
+       local facet=$1
+       local device=$2
+       local size
 
-    size=$(do_facet $facet "$DUMPE2FS -h $device 2>&1" |
-           awk '/^Block size:/ {print $3}')
-    echo $size
+       [ -z "$CLIENTONLY" ] && size=$(do_facet $facet "$DUMPE2FS -h $device 2>&1" |
+               awk '/^Block size:/ {print $3}')
+       echo -n ${size:-0}
 }
 
 # Check whether the "large_xattr" feature is enabled or not.
@@ -7182,6 +7292,18 @@ pool_add_targets() {
        local t=$(for i in $list; do printf "$FSNAME-OST%04x_UUID " $i; done)
        do_facet mgs $LCTL pool_add \
                        $FSNAME.$pool $FSNAME-OST[$first-$last/$step]
+
+       # wait for OSTs to be added to the pool
+       for mds_id in $(seq $MDSCOUNT); do
+               local mdt_id=$((mds_id-1))
+               local lodname=$FSNAME-MDT$(printf "%04x" $mdt_id)-mdtlov
+               wait_update_facet mds$mds_id \
+                       "lctl get_param -n lod.$lodname.pools.$pool |
+                               sort -u | tr '\n' ' ' " "$t" || {
+                       error_noexit "mds$mds_id: Add to pool failed"
+                       return 3
+               }
+       done
        wait_update $HOSTNAME "lctl get_param -n lov.$FSNAME-*.pools.$pool \
                        | sort -u | tr '\n' ' ' " "$t" || {
                error_noexit "Add to pool failed"
@@ -7318,6 +7440,17 @@ pool_remove_first_target() {
        local pname="lov.$FSNAME-*.pools.$pool"
        local t=$($LCTL get_param -n $pname | head -1)
        do_facet mgs $LCTL pool_remove $FSNAME.$pool $t
+       for mds_id in $(seq $MDSCOUNT); do
+               local mdt_id=$((mds_id-1))
+               local lodname=$FSNAME-MDT$(printf "%04x" $mdt_id)-mdtlov
+               wait_update_facet mds$mds_id \
+                       "lctl get_param -n lod.$lodname.pools.$pool |
+                               grep $t" "" || {
+                       error_noexit "mds$mds_id: $t not removed from" \
+                       "$FSNAME.$pool"
+                       return 2
+               }
+       done
        wait_update $HOSTNAME "lctl get_param -n $pname | grep $t" "" || {
                error_noexit "$t not removed from $FSNAME.$pool"
                return 1
@@ -7333,6 +7466,15 @@ pool_remove_all_targets() {
        do
                do_facet mgs $LCTL pool_remove $FSNAME.$pool $t
        done
+       for mds_id in $(seq $MDSCOUNT); do
+               local mdt_id=$((mds_id-1))
+               local lodname=$FSNAME-MDT$(printf "%04x" $mdt_id)-mdtlov
+               wait_update_facet mds$mds_id "lctl get_param -n \
+                       lod.$lodname.pools.$pool" "" || {
+                       error_noexit "mds$mds_id: Pool $pool not drained"
+                       return 4
+               }
+       done
        wait_update $HOSTNAME "lctl get_param -n $pname" "" || {
                error_noexit "Pool $FSNAME.$pool cannot be drained"
                return 1