Whamcloud - gitweb
LU-6966 test: Dash in FSNAME causes warning in testframework
[fs/lustre-release.git] / lustre / tests / test-framework.sh
old mode 100644 (file)
new mode 100755 (executable)
index a7dcc28..48795c0
@@ -6,11 +6,9 @@ set -e
 #set -x
 
 export LANG=en_US
-export EJOURNAL=${EJOURNAL:-""}
 export REFORMAT=${REFORMAT:-""}
 export WRITECONF=${WRITECONF:-""}
 export VERBOSE=${VERBOSE:-false}
-export CATASTROPHE=${CATASTROPHE:-/proc/sys/lnet/catastrophe}
 export GSS=false
 export GSS_KRB5=false
 export GSS_PIPEFS=false
@@ -24,6 +22,12 @@ export JOBID_VAR=${JOBID_VAR:-"procname_uid"}  # or "existing" or "disable"
 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"}
+# sles12 umount has a issue with -d option
+[ -e /etc/SuSE-release ] && grep -w VERSION /etc/SuSE-release | grep -wq 12 && {
+       export UMOUNT="umount"
+}
 
 # function used by scripts run on remote nodes
 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
@@ -71,7 +75,7 @@ usage() {
 
 print_summary () {
     trap 0
-    [ "$TESTSUITE" == "lfsck" ] && return 0
+       [ -z "$DEFAULT_SUITES"] && return 0
     [ -n "$ONLY" ] && echo "WARNING: ONLY is set to $(echo $ONLY)"
     local details
     local form="%-13s %-17s %-9s %s %s\n"
@@ -90,16 +94,21 @@ print_summary () {
         local total=
         local status=Unfinished
         if [ -f $log ]; then
-            skipped=$(grep excluded $log | awk '{ printf " %s", $3 }' | sed 's/test_//g')
-            slow=$(egrep "^PASS|^FAIL" $log | tr -d "("| sed s/s\)$//g | sort -nr -k 3  | head -5 |  awk '{ print $2":"$3"s" }')
-            total=$(grep duration $log | awk '{ print $2}')
-            if [ "${!O}" = "done" ]; then
-                status=Done
-            fi
-            if $DDETAILS; then
-                local durations=$(egrep "^PASS|^FAIL" $log |  tr -d "("| sed s/s\)$//g | awk '{ print $2":"$3"|" }')
-                details=$(printf "%s\n%s %s %s\n" "$details" "DDETAILS" "$O" "$(echo $durations)")
-            fi
+               skipped=$(grep excluded $log | awk '{ printf " %s", $3 }' |
+                       sed 's/test_//g')
+               slow=$(egrep "^PASS|^FAIL" $log | tr -d "("| sed s/s\)$//g |
+                       sort -nr -k 3  | head -n5 |  awk '{ print $2":"$3"s" }')
+               total=$(grep duration $log | awk '{ print $2 }')
+               if [ "${!O}" = "done" ]; then
+                       status=Done
+               fi
+               if $DDETAILS; then
+                       local durations=$(egrep "^PASS|^FAIL" $log |
+                               tr -d "("| sed s/s\)$//g |
+                               awk '{ print $2":"$3"|" }')
+                       details=$(printf "%s\n%s %s %s\n" "$details" \
+                               "DDETAILS" "$O" "$(echo $durations)")
+               fi
         fi
         printf "$form" $status "$O" "${total}" "E=$skipped"
         printf "$form" "-" "-" "-" "S=$(echo $slow)"
@@ -188,9 +197,8 @@ init_test_env() {
                fi
        fi
 
-    export LFSCK_BIN=${LFSCK_BIN:-lfsck}
-    export LFSCK_ALWAYS=${LFSCK_ALWAYS:-"no"} # check fs after each test suite
-    export FSCK_MAX_ERR=4   # File system errors left uncorrected
+       export LFSCK_ALWAYS=${LFSCK_ALWAYS:-"no"} # check fs after test suite
+       export FSCK_MAX_ERR=4   # File system errors left uncorrected
 
        export ZFS=${ZFS:-zfs}
        export ZPOOL=${ZPOOL:-zpool}
@@ -220,9 +228,11 @@ init_test_env() {
     [ ! -f "$LST" ] && export LST=$(which lst)
     export SGPDDSURVEY=${SGPDDSURVEY:-"$LUSTRE/../lustre-iokit/sgpdd-survey/sgpdd-survey")}
     [ ! -f "$SGPDDSURVEY" ] && export SGPDDSURVEY=$(which sgpdd-survey)
+       export MCREATE=${MCREATE:-mcreate}
     # Ubuntu, at least, has a truncate command in /usr/bin
     # so fully path our truncate command.
     export TRUNCATE=${TRUNCATE:-$LUSTRE/tests/truncate}
+       export FSX=${FSX:-$LUSTRE/tests/fsx}
     export MDSRATE=${MDSRATE:-"$LUSTRE/tests/mpi/mdsrate"}
     [ ! -f "$MDSRATE" ] && export MDSRATE=$(which mdsrate 2> /dev/null)
     if ! echo $PATH | grep -q $LUSTRE/tests/racer; then
@@ -261,6 +271,9 @@ init_test_env() {
     export LFS_MIGRATE=${LFS_MIGRATE:-$LUSTRE/scripts/lfs_migrate}
     [ ! -f "$LFS_MIGRATE" ] &&
         export LFS_MIGRATE=$(which lfs_migrate 2> /dev/null)
+    export LR_READER=${LR_READER:-"$LUSTRE/utils/lr_reader"}
+    [ ! -f "$LR_READER" ] && export LR_READER=$(which lr_reader 2> /dev/null)
+    [ -z "$LR_READER" ] && export LR_READER="/usr/sbin/lr_reader"
     export NAME=${NAME:-local}
     export LGSSD=${LGSSD:-"$LUSTRE/utils/gss/lgssd"}
     [ "$GSS_PIPEFS" = "true" ] && [ ! -f "$LGSSD" ] && \
@@ -303,6 +316,7 @@ init_test_env() {
     export I_MOUNTED=${I_MOUNTED:-"no"}
        if [ ! -f /lib/modules/$(uname -r)/kernel/fs/lustre/mdt.ko -a \
             ! -f /lib/modules/$(uname -r)/updates/kernel/fs/lustre/mdt.ko -a \
+            ! -f /lib/modules/$(uname -r)/extra/kernel/fs/lustre/mdt.ko -a \
             ! -f $LUSTRE/mdt/mdt.ko ]; then
            export CLIENTMODSONLY=yes
        fi
@@ -331,6 +345,8 @@ init_test_env() {
        if ! $RPC_MODE; then
                rm -f $TMP/*active
        fi
+
+       export TF_FAIL=${TF_FAIL:-$TMP/tf.fail}
 }
 
 check_cpt_number() {
@@ -347,23 +363,62 @@ check_cpt_number() {
        fi
 }
 
+# Return a numeric version code based on a version string.  The version
+# code is useful for comparison two version strings to see which is newer.
 version_code() {
-    # split arguments like "1.8.6-wc3" into "1", "8", "6", "wc3"
-    eval set -- $(tr "[:punct:]" " " <<< $*)
+       # split arguments like "1.8.6-wc3" into "1", "8", "6", "wc3"
+       eval set -- $(tr "[:punct:]" " " <<< $*)
 
-    echo -n "$((($1 << 16) | ($2 << 8) | $3))"
+       echo -n "$((($1 << 16) | ($2 << 8) | $3))"
 }
 
-export LINUX_VERSION=$(uname -r | sed -e "s/[-.]/ /3" -e "s/ .*//")
+export LINUX_VERSION=$(uname -r | sed -e "s/\([0-9]*\.[0-9]*\.[0-9]*\).*/\1/")
 export LINUX_VERSION_CODE=$(version_code ${LINUX_VERSION//\./ })
 
+# Report the Lustre build version string (e.g. 1.8.7.3 or 2.4.1).
+#
+# usage: lustre_build_version
+#
+# All Lustre versions support "lctl get_param" to report the version of the
+# code running in the kernel (what our tests are interested in), but it
+# doesn't work without modules loaded.  If that fails, use "lctl version"
+# instead, which is easy to parse and works without the kernel modules,
+# but was only added in 2.6.50.  If that also fails, fall back to calling
+# "lctl lustre_build_version" which prints either (or both) the userspace
+# and kernel build versions, but is deprecated and should eventually be
+# removed.
+#
+# output: prints version string to stdout in dotted-decimal format
+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
+       local VER=$(do_facet $facet $LCTL get_param -n version 2> /dev/null |
+                   awk '/lustre: / { print $2 }')
+       # lctl 2.6.50
+       [ -z "$VER" ] && VER=$(do_facet $facet $LCTL --version 2>/dev/null |
+                              awk '{ print $2 }')
+       # Lustre version: 2.5.3-gfcfd782-CHANGED-2.6.32.26-175.fc12.x86_64
+       # lctl   version: 2.5.3-gfcfd782-CHANGED-2.6.32.26-175.fc12.x86_64
+       [ -z "$VER" ] && VER=$(do_facet $facet $LCTL lustre_build_version |
+                              awk '/version:/ { print $3; exit; }')
+       sed -e 's/^v//' -e 's/-.*//' -e 's/_/./g' <<<$VER
+}
+
+# Report the Lustre numeric build version code for the supplied facet.
+lustre_version_code() {
+       version_code $(lustre_build_version $1)
+}
+
 module_loaded () {
-   /sbin/lsmod | grep -q "^\<$1\>"
+       /sbin/lsmod | grep -q "^\<$1\>"
 }
 
 # Load a module on the system where this is running.
 #
-# Synopsis: load_module module_name [module arguments for insmod/modprobe]
+# usage: load_module module_name [module arguments for insmod/modprobe]
 #
 # If module arguments are not given but MODOPTS_<MODULE> is set, then its value
 # will be used as the arguments.  Otherwise arguments will be obtained from
@@ -374,12 +429,12 @@ load_module() {
     EXT=".ko"
     module=$1
     shift
-    BASE=`basename $module $EXT`
+    BASE=$(basename $module $EXT)
 
     module_loaded ${BASE} && return
 
-    # If no module arguments were passed, get them from $MODOPTS_<MODULE>, else from
-    # modprobe.conf
+    # If no module arguments were passed, get them from $MODOPTS_<MODULE>,
+    # else from modprobe.conf
     if [ $# -eq 0 ]; then
         # $MODOPTS_<MODULE>; we could use associative arrays, but that's not in
         # Bash until 4.x, so we resort to eval.
@@ -409,22 +464,24 @@ load_module() {
 
     [ $# -gt 0 ] && echo "${module} options: '$*'"
 
-    # Note that insmod will ignore anything in modprobe.conf, which is why we're
-    # passing options on the command-line.
-    if [ "$BASE" == "lnet_selftest" ] && \
-            [ -f ${LUSTRE}/../lnet/selftest/${module}${EXT} ]; then
-        insmod ${LUSTRE}/../lnet/selftest/${module}${EXT}
-    elif [ -f ${LUSTRE}/${module}${EXT} ]; then
-        insmod ${LUSTRE}/${module}${EXT} "$@"
-    else
-        # must be testing a "make install" or "rpm" installation
-        # note failed to load ptlrpc_gss is considered not fatal
-        if [ "$BASE" == "ptlrpc_gss" ]; then
-            modprobe $BASE "$@" 2>/dev/null || echo "gss/krb5 is not supported"
-        else
-            modprobe $BASE "$@"
-        fi
-    fi
+       # Note that insmod will ignore anything in modprobe.conf, which is why
+       # we're passing options on the command-line.
+       if [[ "$BASE" == "lnet_selftest" ]] &&
+               [[ -f ${LUSTRE}/../lnet/selftest/${module}${EXT} ]]; then
+               insmod ${LUSTRE}/../lnet/selftest/${module}${EXT}
+       elif [[ -f ${LUSTRE}/${module}${EXT} ]]; then
+               [[ "$BASE" != "ptlrpc_gss" ]] || modprobe sunrpc
+               insmod ${LUSTRE}/${module}${EXT} "$@"
+       else
+               # must be testing a "make install" or "rpm" installation
+               # note failed to load ptlrpc_gss is considered not fatal
+               if [[ "$BASE" == "ptlrpc_gss" ]]; then
+                       modprobe $BASE "$@" 2>/dev/null ||
+                               echo "gss/krb5 is not supported"
+               else
+                       modprobe $BASE "$@"
+               fi
+       fi
 }
 
 llite_lloop_enabled() {
@@ -483,6 +540,13 @@ load_modules_local() {
     [ "$PTLDEBUG" ] && lctl set_param debug="$PTLDEBUG"
     [ "$SUBSYSTEM" ] && lctl set_param subsystem_debug="${SUBSYSTEM# }"
     load_module ../lnet/lnet/lnet
+       case $NETTYPE in
+       o2ib)
+               LNETLND="o2iblnd/ko2iblnd"
+               ;;
+       *)
+               ;;
+       esac
     LNETLND=${LNETLND:-"socklnd/ksocklnd"}
     load_module ../lnet/klnds/$LNETLND
     load_module obdclass/obdclass
@@ -523,20 +587,37 @@ load_modules_local() {
                load_module osp/osp
     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
-    $LCTL modules > $OGDB/ogdb-$HOSTNAME
-
-    # 'mount' doesn't look in $PATH, just sbin
-    if [ -f $LUSTRE/utils/mount.lustre ] && \
-       ! grep -qe "/sbin/mount\.lustre " /proc/mounts; then
-        [ ! -f /sbin/mount.lustre ] && touch /sbin/mount.lustre
-        mount --bind $LUSTRE/utils/mount.lustre /sbin/mount.lustre || true
-    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
+       $LCTL modules > $OGDB/ogdb-$HOSTNAME
+
+       # 'mount' doesn't look in $PATH, just sbin
+       local mount_lustre=$LUSTRE/utils/mount.lustre
+       if [ -f $mount_lustre ]; then
+               local sbin_mount=$(readlink -f /sbin)/mount.lustre
+               if grep -qw "$sbin_mount" /proc/mounts; then
+                       cmp -s $mount_lustre $sbin_mount || umount $sbin_mount
+               fi
+               if ! grep -qw "$sbin_mount" /proc/mounts; then
+                       [ ! -f "$sbin_mount" ] && touch "$sbin_mount"
+                       if [ ! -s "$sbin_mount" -a -w "$sbin_mount" ]; then
+                               cat <<- EOF > "$sbin_mount"
+                               #!/bin/sh
+                               #STUB MARK
+                               echo "This $sbin_mount just a mountpoint." 1>&2
+                               echo "It is never supposed to be run." 1>&2
+                               logger -p emerg -- "using stub $sbin_mount $@"
+                               exit 1
+                               EOF
+                               chmod a+x $sbin_mount
+                       fi
+                       mount --bind $mount_lustre $sbin_mount ||
+                               error "can't bind $mount_lustre to $sbin_mount"
+               fi
+       fi
 }
 
 load_modules () {
@@ -580,16 +661,17 @@ unload_modules() {
                fi
        fi
 
-    if grep -qe "/sbin/mount\.lustre" /proc/mounts; then
-        umount /sbin/mount.lustre || true
-        [ -w /sbin/mount.lustre -a ! -s /sbin/mount.lustre ] && \
-            rm -f /sbin/mount.lustre || true
-    fi
+       local sbin_mount=$(readlink -f /sbin)/mount.lustre
+       if grep -qe "$sbin_mount " /proc/mounts; then
+               umount $sbin_mount || true
+               [ -s $sbin_mount ] && ! grep -q "STUB MARK" $sbin_mount ||
+                       rm -f $sbin_mount
+       fi
 
-    check_mem_leak || return 254
+       check_mem_leak || return 254
 
-    echo "modules unloaded."
-    return 0
+       echo "modules unloaded."
+       return 0
 }
 
 fs_log_size() {
@@ -647,7 +729,6 @@ start_gss_daemons() {
     fi
 
     local list=$(comma_list $(mdts_nodes))
-
     echo "Starting gss daemon on mds: $list"
     do_nodes $list "$LSVCGSSD -v" || return 1
     if $GSS_PIPEFS; then
@@ -684,7 +765,7 @@ start_gss_daemons() {
 
 stop_gss_daemons() {
     local list=$(comma_list $(mdts_nodes))
-    
+
     send_sigint $list lsvcgssd lgssd
 
     list=$(comma_list $(osts_nodes))
@@ -701,10 +782,13 @@ init_gss() {
             module_loaded ptlrpc_gss ||
                 error_exit "init_gss : GSS=$GSS, but gss/krb5 is not supported!"
         fi
-        start_gss_daemons || error_exit "start gss daemon failed! rc=$?"
+        if $GSS_KRB5; then
+                start_gss_daemons || error_exit "start gss daemon failed! rc=$?"
+        fi
 
         if [ -n "$LGSS_KEYRING_DEBUG" ]; then
-            echo $LGSS_KEYRING_DEBUG > /proc/fs/lustre/sptlrpc/gss/lgss_keyring/debug_level
+               lctl set_param -n \
+                   sptlrpc.gss.lgss_keyring.debug_level=$LGSS_KEYRING_DEBUG
         fi
     fi
 }
@@ -788,6 +872,25 @@ node_fstypes() {
        echo -n $fstypes
 }
 
+facet_index() {
+       local facet=$1
+       local num=$(facet_number $facet)
+       local index
+
+       if [[ $(facet_type $facet) = OST ]]; then
+               index=OSTINDEX${num}
+               if [[ -n "${!index}" ]]; then
+                       echo -n ${!index}
+                       return
+               fi
+
+               index=${OST_INDICES[num - 1]}
+       fi
+
+       [[ -n "$index" ]] || index=$((num - 1))
+       echo -n $index
+}
+
 devicelabel() {
        local facet=$1
        local dev=$2
@@ -899,6 +1002,33 @@ zpool_name() {
 }
 
 #
+# Create ZFS storage pool.
+#
+create_zpool() {
+       local facet=$1
+       local poolname=$2
+       local vdev=$3
+       shift 3
+       local opts=${@:-"-o cachefile=none"}
+
+       do_facet $facet "$ZPOOL list -H $poolname >/dev/null 2>&1 ||
+               $ZPOOL create -f $opts $poolname $vdev"
+}
+
+#
+# Create ZFS file system.
+#
+create_zfs() {
+       local facet=$1
+       local dataset=$2
+       shift 2
+       local opts=${@:-"-o mountpoint=legacy"}
+
+       do_facet $facet "$ZFS list -H $dataset >/dev/null 2>&1 ||
+               $ZFS create $opts $dataset"
+}
+
+#
 # Export ZFS storage pool.
 # Before exporting the pool, all datasets within the pool should be unmounted.
 #
@@ -918,6 +1048,22 @@ export_zpool() {
 }
 
 #
+# Destroy ZFS storage pool.
+# Destroy the given pool and free up any devices for other use. This command
+# tries to unmount any active datasets before destroying the pool.
+# -f    Force any active datasets contained within the pool to be unmounted.
+#
+destroy_zpool() {
+       local facet=$1
+       local poolname=${2:-$(zpool_name $facet)}
+
+       if [[ -n "$poolname" ]]; then
+               do_facet $facet "! $ZPOOL list -H $poolname >/dev/null 2>&1 ||
+                       $ZPOOL destroy -f $poolname"
+       fi
+}
+
+#
 # Import ZFS storage pool.
 # Force importing, even if the pool appears to be potentially active.
 #
@@ -970,7 +1116,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() {
@@ -980,7 +1126,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 () {
@@ -1078,6 +1224,8 @@ mount_facet() {
        local mntpt=$(facet_mntpt $facet)
        local opts="${!opt} $@"
 
+       module_loaded lustre || load_modules
+
        if [ $(facet_fstype $facet) == ldiskfs ] &&
           ! do_facet $facet test -b ${!dev}; then
                opts=$(csa_add "$opts" -o loop)
@@ -1093,45 +1241,81 @@ mount_facet() {
        if [ -f $TMP/test-lu482-trigger ]; then
                RC=2
        else
-               do_facet ${facet} "mkdir -p $mntpt; mount -t lustre $opts \
+               do_facet ${facet} "mkdir -p $mntpt; $MOUNT_CMD $opts \
                                   ${!dev} $mntpt"
                RC=${PIPESTATUS[0]}
        fi
+
        if [ $RC -ne 0 ]; then
                echo "Start of ${!dev} on ${facet} failed ${RC}"
-    else
-        set_default_debug_facet $facet
+               return $RC
+       fi
 
-               label=$(devicelabel ${facet} ${!dev})
-        [ -z "$label" ] && echo no label for ${!dev} && exit 1
-        eval export ${facet}_svc=${label}
-        echo Started ${label}
-    fi
-    return $RC
+       set_default_debug_facet $facet
+
+       if [[ $facet == mds* ]]; then
+               do_facet $facet \
+               lctl set_param -n mdt.${FSNAME}*.enable_remote_dir=1 2>/dev/null
+       fi
+
+       if [[ $opts =~ .*nosvc.* ]]; then
+               echo "Start ${!dev} without service"
+       else
+               local fstype=$(facet_fstype $facet)
+
+               case $fstype in
+               ldiskfs)
+                       wait_update_facet ${facet} "$E2LABEL ${!dev} \
+                               2>/dev/null | grep -E ':[a-zA-Z]{3}[0-9]{4}'" \
+                               "" || error "${!dev} failed to initialize!";;
+               zfs)
+                       wait_update_facet ${facet} "$ZFS get -H -o value \
+                               lustre:svname ${!dev} 2>/dev/null | \
+                               grep -E ':[a-zA-Z]{3}[0-9]{4}'" "" ||
+                               error "${!dev} failed to initialize!";;
+
+               *)
+                       error "unknown fstype!";;
+               esac
+       fi
+
+       label=$(devicelabel ${facet} ${!dev})
+       [ -z "$label" ] && echo no label for ${!dev} && exit 1
+       eval export ${facet}_svc=${label}
+       echo Started ${label}
+
+       return $RC
 }
 
 # start facet device options
 start() {
-    local facet=$1
-    shift
-    local device=$1
-    shift
-    eval export ${facet}_dev=${device}
-    eval export ${facet}_opt=\"$@\"
+       local facet=$1
+       shift
+       local device=$1
+       shift
+       eval export ${facet}_dev=${device}
+       eval export ${facet}_opt=\"$@\"
 
-    local varname=${facet}failover_dev
-    if [ -n "${!varname}" ] ; then
-        eval export ${facet}failover_dev=${!varname}
-    else
-        eval export ${facet}failover_dev=$device
-    fi
+       local varname=${facet}failover_dev
+       if [ -n "${!varname}" ] ; then
+               eval export ${facet}failover_dev=${!varname}
+       else
+               eval export ${facet}failover_dev=$device
+       fi
 
-    local mntpt=$(facet_mntpt $facet)
-    do_facet ${facet} mkdir -p $mntpt
-    eval export ${facet}_MOUNT=$mntpt
-    mount_facet ${facet}
-    RC=$?
-    return $RC
+       local mntpt=$(facet_mntpt $facet)
+       do_facet ${facet} mkdir -p $mntpt
+       eval export ${facet}_MOUNT=$mntpt
+       mount_facet ${facet}
+       RC=$?
+
+       if [[ $facet == mds* ]]; then
+               do_facet $facet \
+                       lctl set_param -n mdt.${FSNAME}*.enable_remote_dir=1 \
+                               2>/dev/null
+       fi
+
+       return $RC
 }
 
 stop() {
@@ -1145,7 +1329,7 @@ stop() {
     running=$(do_facet ${facet} "grep -c $mntpt' ' /proc/mounts") || true
     if [ ${running} -ne 0 ]; then
         echo "Stopping $mntpt (opts:$@) on $HOST"
-        do_facet ${facet} umount -d $@ $mntpt
+       do_facet ${facet} $UMOUNT $@ $mntpt
     fi
 
        # umount should block, but we should wait for unrelated obd's
@@ -1195,71 +1379,7 @@ quota_type() {
                rc=$?
        do_nodes $(comma_list $(osts_nodes)) \
                lctl get_param obdfilter.${fsname}-OST*.quota_type || rc=$?
-       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
+       return $rc
 }
 
 # get mdt quota type
@@ -1279,11 +1399,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
@@ -1319,11 +1434,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
@@ -1374,17 +1484,19 @@ setup_quota(){
 zconf_mount() {
     local client=$1
     local mnt=$2
-    local OPTIONS=${3:-$MOUNTOPT}
+    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=$OPTIONS dev=$device mnt=$mnt
+        echo Bad zconf mount command: opt=$flags $opts dev=$device mnt=$mnt
         exit 1
     fi
 
-    echo "Starting client: $client: $OPTIONS $device $mnt"
+    echo "Starting client: $client: $flags $opts $device $mnt"
     do_node $client mkdir -p $mnt
-    do_node $client mount -t lustre $OPTIONS $device $mnt || return 1
+    do_node $client $MOUNT_CMD $flags $opts $device $mnt || return 1
 
     set_default_debug_nodes $client
 
@@ -1480,22 +1592,24 @@ sanity_mount_check () {
 zconf_mount_clients() {
     local clients=$1
     local mnt=$2
-    local OPTIONS=${3:-$MOUNTOPT}
+    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=$OPTIONS dev=$device mnt=$mnt
+        echo Bad zconf mount command: opt=$flags $opts dev=$device mnt=$mnt
         exit 1
     fi
 
-    echo "Starting client $clients: $OPTIONS $device $mnt"
+    echo "Starting client $clients: $flags $opts $device $mnt"
 
     do_nodes $clients "
 running=\\\$(mount | grep -c $mnt' ');
 rc=0;
 if [ \\\$running -eq 0 ] ; then
     mkdir -p $mnt;
-    mount -t lustre $OPTIONS $device $mnt;
+    $MOUNT_CMD $flags $opts $device $mnt;
     rc=\\\$?;
 fi;
 exit \\\$rc" || return ${PIPESTATUS[0]}
@@ -1585,7 +1699,7 @@ facet_up() {
        local host=${2:-$(facet_host $facet)}
 
        local label=$(convert_facet2label $facet)
-       do_node $host $LCTL dl | awk '{print $4}' | grep -q -x $label
+       do_node $host $LCTL dl | awk '{ print $4 }' | grep -q "^$label\$"
 }
 
 facets_up_on_host () {
@@ -1878,18 +1992,22 @@ stop_client_loads() {
 
 # verify that lustre actually cleaned up properly
 cleanup_check() {
-    [ -f $CATASTROPHE ] && [ `cat $CATASTROPHE` -ne 0 ] && \
-        error "LBUG/LASSERT detected"
-    BUSY=`dmesg | grep -i destruct || true`
-    if [ "$BUSY" ]; then
-        echo "$BUSY" 1>&2
-        [ -e $TMP/debug ] && mv $TMP/debug $TMP/debug-busy.`date +%s`
-        exit 205
-    fi
+       VAR=$(lctl get_param -n catastrophe 2>&1)
+       if [ $? = 0 ] ; then
+               if [ $VAR != 0 ]; then
+                       error "LBUG/LASSERT detected"
+               fi
+       fi
+       BUSY=$(dmesg | grep -i destruct || true)
+       if [ -n "$BUSY" ]; then
+               echo "$BUSY" 1>&2
+               [ -e $TMP/debug ] && mv $TMP/debug $TMP/debug-busy.$(date +%s)
+               exit 205
+       fi
 
-    check_mem_leak || exit 204
+       check_mem_leak || exit 204
 
-       [ "`lctl dl 2> /dev/null | wc -l`" -gt 0 ] && lctl dl &&
+       [[ $($LCTL dl 2>/dev/null | wc -l) -gt 0 ]] && $LCTL dl &&
                echo "$TESTSUITE: lustre didn't clean up..." 1>&2 &&
                return 202 || true
 
@@ -1918,6 +2036,7 @@ wait_update () {
        local sleep=1
        local print=10
 
+       PREV_RESULT=$(do_node $node "$TEST")
        while [ true ]; do
                RESULT=$(do_node $node "$TEST")
                if [[ "$RESULT" == "$FINAL" ]]; then
@@ -1942,65 +2061,78 @@ wait_update () {
 }
 
 wait_update_facet() {
+       local verbose=
+       [ "$1" = "--verbose" ] && verbose="$1" && shift
+
        local facet=$1
        shift
-       wait_update $(facet_active_host $facet) "$@"
+       wait_update $verbose $(facet_active_host $facet) "$@"
 }
 
 sync_all_data() {
        do_nodes $(comma_list $(mdts_nodes)) \
-           "lctl set_param -n osd*.*MDT*.force_sync 1"
+           "lctl set_param -n osd*.*MDT*.force_sync=1"
        do_nodes $(comma_list $(osts_nodes)) \
-           "lctl set_param -n osd*.*OS*.force_sync 1" 2>&1 |
+           "lctl set_param -n osd*.*OS*.force_sync=1" 2>&1 |
                grep -v 'Found no match'
 }
 
 wait_delete_completed_mds() {
        local MAX_WAIT=${1:-20}
+       # for ZFS, waiting more time for DMUs to be committed
+       local ZFS_WAIT=${2:-5}
        local mds2sync=""
-       local stime=`date +%s`
+       local stime=$(date +%s)
        local etime
        local node
        local changes
 
        # find MDS with pending deletions
        for node in $(mdts_nodes); do
-               changes=$(do_node $node "lctl get_param -n osc.*MDT*.sync_*" \
+               changes=$(do_node $node "$LCTL get_param -n osc.*MDT*.sync_*" \
                        2>/dev/null | calc_sum)
-               if [ -z "$changes" ] || [ $changes -eq 0 ]; then
+               if [[ $changes -eq 0 ]]; then
                        continue
                fi
                mds2sync="$mds2sync $node"
        done
-       if [ "$mds2sync" == "" ]; then
+       if [ -z "$mds2sync" ]; then
                return
        fi
        mds2sync=$(comma_list $mds2sync)
 
        # sync MDS transactions
-       do_nodes $mds2sync "lctl set_param -n osd*.*MD*.force_sync 1"
+       do_nodes $mds2sync "$LCTL set_param -n osd*.*MD*.force_sync 1"
 
        # wait till all changes are sent and commmitted by OSTs
        # for ldiskfs space is released upon execution, but DMU
        # do this upon commit
 
        local WAIT=0
-       while [ "$WAIT" -ne "$MAX_WAIT" ]; do
-               changes=$(do_nodes $mds2sync "lctl get_param -n osc.*MDT*.sync_*" \
-                       | calc_sum)
+       while [[ $WAIT -ne $MAX_WAIT ]]; do
+               changes=$(do_nodes $mds2sync \
+                       "$LCTL get_param -n osc.*MDT*.sync_*" | calc_sum)
                #echo "$node: $changes changes on all"
-               if [ "$changes" -eq "0" ]; then
-                       etime=`date +%s`
+               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
+
                        return
                fi
                sleep 1
                WAIT=$(( WAIT + 1))
        done
 
-       etime=`date +%s`
+       etime=$(date +%s)
        echo "Delete is not completed in $((etime - stime)) seconds"
-       do_nodes $mds2sync "lctl get_param osc.*MDT*.sync_*"
+       do_nodes $mds2sync "$LCTL get_param osc.*MDT*.sync_*"
 }
 
 wait_for_host() {
@@ -2223,7 +2355,7 @@ client_evicted() {
     ! client_up $1
 }
 
-client_reconnect() {
+client_reconnect_try() {
     uname -n >> $MOUNT/recon
     if [ -z "$CLIENTS" ]; then
         df $MOUNT; uname -n >> $MOUNT/recon
@@ -2236,6 +2368,14 @@ client_reconnect() {
     rm $MOUNT/recon
 }
 
+client_reconnect() {
+       # one client_reconnect_try call does not always do the job...
+       while true ; do
+               client_reconnect_try && break
+               sleep 1
+       done
+}
+
 affected_facets () {
     local facet=$1
 
@@ -2249,6 +2389,13 @@ affected_facets () {
 }
 
 facet_failover() {
+       local E2FSCK_ON_MDT0=false
+       if [ "$1" == "--fsck" ]; then
+               shift
+               [ $(facet_fstype $SINGLEMDS) == ldiskfs ] &&
+                       E2FSCK_ON_MDT0=true
+       fi
+
        local facets=$1
        local sleep_time=$2
        local -a affecteds
@@ -2282,6 +2429,9 @@ facet_failover() {
                shutdown_facet $facet
        done
 
+       $E2FSCK_ON_MDT0 && (run_e2fsck $(facet_active_host $SINGLEMDS) \
+               $(mdsdevname 1) "-n" || error "Running e2fsck")
+
        for ((index=0; index<$total; index++)); do
                facet=$(echo ${affecteds[index]} | tr -s " " | cut -d"," -f 1)
                echo reboot facets: ${affecteds[index]}
@@ -2546,7 +2696,7 @@ hostlist_expand() {
     done
     myList="${myList%* }";
 
-    # We can select an object at a offset in the list
+    # We can select an object at an offset in the list
     [ $# -eq 2 ] && {
         cnt=0
         for item in $myList; do
@@ -2568,7 +2718,11 @@ facet_host() {
        varname=${facet}_HOST
        if [ -z "${!varname}" ]; then
                if [ "${facet:0:3}" == "ost" ]; then
-                       eval export ${facet}_HOST=${ost_HOST}
+                       local fh=${facet%failover}_HOST
+                       eval export ${facet}_HOST=${!fh}
+                       if [ -z "${!varname}" ]; then
+                               eval export ${facet}_HOST=${ost_HOST}
+                       fi
                elif [ "${facet:0:3}" == "mdt" -o \
                        "${facet:0:3}" == "mds" -o \
                        "${facet:0:3}" == "mgs" ]; then
@@ -2620,13 +2774,7 @@ facet_active() {
 }
 
 facet_active_host() {
-    local facet=$1
-    local active=`facet_active $facet`
-    if [ "$facet" == client ]; then
-        echo $HOSTNAME
-    else
-        echo `facet_host $active`
-    fi
+       facet_host $(facet_active $1)
 }
 
 # Get the passive failover partner host of facet.
@@ -2736,7 +2884,7 @@ get_env_vars() {
        local facet
 
        for var in ${!MODOPTS_*}; do
-               value=${!var}
+               value=${!var//\"/\\\"}
                echo -n " ${var}=\"$value\""
        done
 
@@ -2753,9 +2901,21 @@ get_env_vars() {
                fi
        done
 
+       for var in VERBOSE; do
+               if [ -n "${!var}" ]; then
+                       echo -n " $var=${!var}"
+               fi
+       done
+
        if [ -n "$FSTYPE" ]; then
                echo -n " FSTYPE=$FSTYPE"
        fi
+
+       for var in LNETLND NETTYPE; do
+               if [ -n "${!var}" ]; then
+                       echo -n " $var=${!var}"
+               fi
+       done
 }
 
 do_nodes() {
@@ -2800,12 +2960,19 @@ do_nodes() {
     return ${PIPESTATUS[0]}
 }
 
+##
+# Execute commands on a single service's host
+#
+# The \a facet (service) may be on a local or remote node, which is
+# determined at the time the command is run.
+#
+# usage: do_facet $facet command [arg ...]
 do_facet() {
-    local facet=$1
-    shift
-    local HOST=`facet_active_host $facet`
-    [ -z $HOST ] && echo No host defined for facet ${facet} && exit 1
-    do_node $HOST "$@"
+       local facet=$1
+       shift
+       local HOST=$(facet_active_host $facet)
+       [ -z $HOST ] && echo "No host defined for facet ${facet}" && exit 1
+       do_node $HOST "$@"
 }
 
 # Function: do_facet_random_file $FACET $FILE $SIZE
@@ -2854,9 +3021,10 @@ add() {
        fi
 }
 
+# Device formatted as ost
 ostdevname() {
-    num=$1
-    DEVNAME=OSTDEV$num
+       local num=$1
+       local DEVNAME=OSTDEV$num
 
        local fstype=$(facet_fstype ost$num)
 
@@ -2865,8 +3033,9 @@ ostdevname() {
                        #if $OSTDEVn isn't defined, default is $OSTDEVBASE + num
                        eval DEVPTR=${!DEVNAME:=${OSTDEVBASE}${num}};;
                zfs )
-                       #dataset name is independent of vdev device names
-                       eval DEVPTR=${FSNAME}-ost${num}/ost${num};;
+                       #try $OSTZFSDEVn - independent of vdev
+                       DEVNAME=OSTZFSDEV$num
+                       eval DEVPTR=${!DEVNAME:=${FSNAME}-ost${num}/ost${num}};;
                * )
                        error "unknown fstype!";;
        esac
@@ -2874,9 +3043,11 @@ ostdevname() {
     echo -n $DEVPTR
 }
 
+# Physical device location of data
 ostvdevname() {
-       num=$1
-       DEVNAME=OSTDEV$num
+       local num=$1
+       local DEVNAME
+       local VDEVPTR
 
        local fstype=$(facet_fstype ost$num)
 
@@ -2885,7 +3056,9 @@ ostvdevname() {
                        # vdevs are not supported by ldiskfs
                        eval VDEVPTR="";;
                zfs )
-                       #if $OSTDEVn isn't defined, default is $OSTDEVBASE + num
+                       #if $OSTDEVn isn't defined, default is $OSTDEVBASE{n}
+                       # Device formatted by zfs
+                       DEVNAME=OSTDEV$num
                        eval VDEVPTR=${!DEVNAME:=${OSTDEVBASE}${num}};;
                * )
                        error "unknown fstype!";;
@@ -2894,19 +3067,21 @@ ostvdevname() {
        echo -n $VDEVPTR
 }
 
+# Logical device formatted for lustre
 mdsdevname() {
-    num=$1
-    DEVNAME=MDSDEV$num
+       local num=$1
+       local DEVNAME=MDSDEV$num
 
        local fstype=$(facet_fstype mds$num)
 
        case $fstype in
                ldiskfs )
-                       #if $MDSDEVn isn't defined, default is $MDSDEVBASE + num
+                       #if $MDSDEVn isn't defined, default is $MDSDEVBASE{n}
                        eval DEVPTR=${!DEVNAME:=${MDSDEVBASE}${num}};;
                zfs )
-                       #dataset name is independent of vdev device names
-                       eval DEVPTR=${FSNAME}-mdt${num}/mdt${num};;
+                       # try $MDSZFSDEVn - independent of vdev
+                       DEVNAME=MDSZFSDEV$num
+                       eval DEVPTR=${!DEVNAME:=${FSNAME}-mdt${num}/mdt${num}};;
                * )
                        error "unknown fstype!";;
        esac
@@ -2914,10 +3089,10 @@ mdsdevname() {
        echo -n $DEVPTR
 }
 
+# Physical location of data
 mdsvdevname() {
-       num=$1
-       DEVNAME=MDSDEV$num
-
+       local VDEVPTR=""
+       local num=$1
        local fstype=$(facet_fstype mds$num)
 
        case $fstype in
@@ -2925,7 +3100,9 @@ mdsvdevname() {
                        # vdevs are not supported by ldiskfs
                        eval VDEVPTR="";;
                zfs )
-                       #if $MDSDEVn isn't defined, default is $MDSDEVBASE + num
+                       # if $MDSDEVn isn't defined, default is $MDSDEVBASE{n}
+                       # Device formatted by ZFS
+                       local DEVNAME=MDSDEV$num
                        eval VDEVPTR=${!DEVNAME:=${MDSDEVBASE}${num}};;
                * )
                        error "unknown fstype!";;
@@ -2948,10 +3125,11 @@ mgsdevname() {
                fi;;
        zfs )
                if [ $(facet_host mgs) = $(facet_host mds1) ] &&
-                  ( [ -z "$MGSDEV" ] || [ $MGSDEV = $(mdsvdevname 1) ] ); then
+                   ( [ -z "$MGSZFSDEV" ] &&
+                       [ -z "$MGSDEV" -o "$MGSDEV" = $(mdsvdevname 1) ] ); then
                        DEVPTR=$(mdsdevname 1)
                else
-                       DEVPTR=${FSNAME}-mgs/mgs
+                       DEVPTR=${MGSZFSDEV:-${FSNAME}-mgs/mgs}
                fi;;
        * )
                error "unknown fstype!";;
@@ -2961,8 +3139,7 @@ mgsdevname() {
 }
 
 mgsvdevname() {
-       local VDEVPTR
-       DEVNAME=MGSDEV
+       local VDEVPTR=""
 
        local fstype=$(facet_fstype mgs)
 
@@ -2972,9 +3149,10 @@ mgsvdevname() {
                ;;
        zfs )
                if [ $(facet_host mgs) = $(facet_host mds1) ] &&
-                  ( [ -z "$MGSDEV" ] || [ $MGSDEV = $(mdsvdevname 1) ] ); then
+                  ( [ -z "$MGSDEV" ] &&
+                      [ -z "$MGSZFSDEV" -o "$MGSZFSDEV" = $(mdsdevname 1) ]); then
                        VDEVPTR=$(mdsvdevname 1)
-               else
+               elif [ -n "$MGSDEV" ]; then
                        VDEVPTR=$MGSDEV
                fi;;
        * )
@@ -3011,7 +3189,7 @@ unmount_ldiskfs() {
        local dev=$(facet_device $facet)
        local mnt=$(facet_mntpt $facet)
 
-       do_facet $facet umount -d $mnt
+       do_facet $facet $UMOUNT $mnt
 }
 
 var_name() {
@@ -3122,6 +3300,7 @@ cleanup_echo_devs () {
 
 cleanupall() {
     nfs_client_mode && return
+       cifs_client_mode && return
 
     stopall $*
     cleanup_echo_devs
@@ -3148,17 +3327,13 @@ mkfs_opts() {
        local dev=$2
        local fsname=${3:-"$FSNAME"}
        local type=$(facet_type $facet)
-       local index=$(($(facet_number $facet) - 1))
+       local index=$(facet_index $facet)
        local fstype=$(facet_fstype $facet)
        local host=$(facet_host $facet)
        local opts
        local fs_mkfs_opts
        local var
 
-       if [ $type == MGS ] && combined_mgs_mds; then
-               return 1
-       fi
-
        if [ $type == MGS ] || ( [ $type == MDS ] &&
                                  [ "$dev" == $(mgsdevname) ] &&
                                 [ "$host" == "$(facet_host mgs)" ] ); then
@@ -3188,9 +3363,17 @@ mkfs_opts() {
                opts+=${L_GETIDENTITY:+" --param=mdt.identity_upcall=$L_GETIDENTITY"}
 
                if [ $fstype == ldiskfs ]; then
-                       fs_mkfs_opts+=${MDSJOURNALSIZE:+" -J size=$MDSJOURNALSIZE"}
-                       if [ ! -z $EJOURNAL ]; then
-                               fs_mkfs_opts+=${MDSJOURNALSIZE:+" device=$EJOURNAL"}
+                       # Check for wide striping
+                       if [ $OSTCOUNT -gt 160 ]; then
+                               MDSJOURNALSIZE=${MDSJOURNALSIZE:-4096}
+                               fs_mkfs_opts+="-O large_xattr"
+                       fi
+
+                       var=${facet}_JRN
+                       if [ -n "${!var}" ]; then
+                               fs_mkfs_opts+=" -J device=${!var}"
+                       else
+                               fs_mkfs_opts+=${MDSJOURNALSIZE:+" -J size=$MDSJOURNALSIZE"}
                        fi
                        fs_mkfs_opts+=${MDSISIZE:+" -i $MDSISIZE"}
                fi
@@ -3201,7 +3384,12 @@ mkfs_opts() {
                opts+=${OSSCAPA:+" --param=ost.capa=$OSSCAPA"}
 
                if [ $fstype == ldiskfs ]; then
-                       fs_mkfs_opts+=${OSTJOURNALSIZE:+" -J size=$OSTJOURNALSIZE"}
+                       var=${facet}_JRN
+                       if [ -n "${!var}" ]; then
+                               fs_mkfs_opts+=" -J device=${!var}"
+                       else
+                               fs_mkfs_opts+=${OSTJOURNALSIZE:+" -J size=$OSTJOURNALSIZE"}
+                       fi
                fi
        fi
 
@@ -3228,37 +3416,81 @@ mkfs_opts() {
        echo -n "$opts"
 }
 
-formatall() {
+check_ost_indices() {
+       local index_count=${#OST_INDICES[@]}
+       [[ $index_count -eq 0 || $OSTCOUNT -le $index_count ]] && return 0
+
+       # OST count is greater than the index count in $OST_INDEX_LIST.
+       # We need check whether there are duplicate indices.
+       local i
+       local j
+       local index
+       for i in $(seq $((index_count + 1)) $OSTCOUNT); do
+               index=$(facet_index ost$i)
+               for j in $(seq 0 $((index_count - 1))); do
+                       [[ $index -ne ${OST_INDICES[j]} ]] ||
+                       error "ost$i has the same index $index as ost$((j+1))"
+               done
+       done
+}
+
+format_mgs() {
+       local quiet
+
+       if ! $VERBOSE; then
+               quiet=yes
+       fi
+       echo "Format mgs: $(mgsdevname)"
+       reformat_external_journal mgs
+       add mgs $(mkfs_opts mgs $(mgsdevname)) --reformat \
+               $(mgsdevname) $(mgsvdevname) ${quiet:+>/dev/null} || exit 10
+}
+
+format_mdt() {
+       local num=$1
        local quiet
 
        if ! $VERBOSE; then
                quiet=yes
        fi
+       echo "Format mds$num: $(mdsdevname $num)"
+       reformat_external_journal mds$num
+       add mds$num $(mkfs_opts mds$num $(mdsdevname ${num})) \
+               --reformat $(mdsdevname $num) $(mdsvdevname $num) \
+               ${quiet:+>/dev/null} || exit 10
+}
+
+format_ost() {
+       local num=$1
+
+       if ! $VERBOSE; then
+               quiet=yes
+       fi
+       echo "Format ost$num: $(ostdevname $num)"
+       reformat_external_journal ost$num
+       add ost$num $(mkfs_opts ost$num $(ostdevname ${num})) \
+               --reformat $(ostdevname $num) $(ostvdevname ${num}) \
+               ${quiet:+>/dev/null} || exit 10
+}
 
+formatall() {
        stopall
        # We need ldiskfs here, may as well load them all
        load_modules
        [ "$CLIENTONLY" ] && return
        echo Formatting mgs, mds, osts
        if ! combined_mgs_mds ; then
-               echo "Format mgs: $(mgsdevname)"
-               add mgs $(mkfs_opts mgs $(mgsdevname)) --reformat \
-                       $(mgsdevname) $(mgsvdevname) ${quiet:+>/dev/null} ||
-                       exit 10
+               format_mgs
        fi
 
        for num in $(seq $MDSCOUNT); do
-               echo "Format mds$num: $(mdsdevname $num)"
-               add mds$num $(mkfs_opts mds$num $(mdsdevname ${num})) \
-                       --reformat $(mdsdevname $num) $(mdsvdevname $num) \
-                       ${quiet:+>/dev/null} || exit 10
+               format_mdt $num
        done
 
+       export OST_INDICES=($(hostlist_expand "$OST_INDEX_LIST"))
+       check_ost_indices
        for num in $(seq $OSTCOUNT); do
-               echo "Format ost$num: $(ostdevname $num)"
-               add ost$num $(mkfs_opts ost$num $(ostdevname ${num})) \
-                       --reformat $(ostdevname $num) $(ostvdevname ${num}) \
-                       ${quiet:+>/dev/null} || exit 10
+               format_ost $num
        done
 }
 
@@ -3336,6 +3568,7 @@ writeconf_all () {
 
 setupall() {
     nfs_client_mode && return
+       cifs_client_mode && return
 
     sanity_mount_check ||
         error "environments are insane!"
@@ -3601,6 +3834,11 @@ nfs_client_mode () {
     return 1
 }
 
+cifs_client_mode () {
+       [ x$CIFSCLIENT = xyes ] &&
+               echo "CIFSCLIENT=$CIFSCLIENT mode: setup, cleanup, check config skipped"
+}
+
 check_config_client () {
     local mntpt=$1
 
@@ -3648,6 +3886,7 @@ check_config_clients () {
        local mntpt=$1
 
        nfs_client_mode && return
+       cifs_client_mode && return
 
        do_rpc_nodes "$clients" check_config_client $mntpt
 
@@ -3694,6 +3933,7 @@ is_empty_fs() {
 
 check_and_setup_lustre() {
     nfs_client_mode && return
+       cifs_client_mode && return
 
     local MOUNTED=$(mounted_lustre_filesystems)
 
@@ -3770,6 +4010,13 @@ 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 [ "$ONLY" == "setup" ]; then
                exit 0
        fi
@@ -3783,10 +4030,10 @@ restore_mount () {
 }
 
 cleanup_mount () {
-    local clients=${CLIENTS:-$HOSTNAME}
-    local mntpt=$1
+       local clients=${CLIENTS:-$HOSTNAME}
+       local mntpt=$1
 
-    zconf_umount_clients $clients $mntpt    
+       zconf_umount_clients $clients $mntpt
 }
 
 cleanup_and_setup_lustre() {
@@ -3810,8 +4057,7 @@ get_mnt_devs() {
        if [ "$type" == ost ]; then
                devs=$(get_osd_param $node "" mntdev)
        else
-               devs=$(do_node $node \
-                      "lctl get_param -n osd-*.$FSNAME-M*.mntdev")
+               devs=$(do_node $node $LCTL get_param -n osd-*.$FSNAME-M*.mntdev)
        fi
        for dev in $devs; do
                case $dev in
@@ -3824,37 +4070,60 @@ get_mnt_devs() {
 
 # Get all of the server target devices.
 get_svr_devs() {
-    local i
+       local node
+       local i
 
-    # MDT device
-    MDTDEV=$(get_mnt_devs $(mdts_nodes) mdt)
+       # Master MDS parameters used by lfsck
+       MDTNODE=$(facet_active_host $SINGLEMDS)
+       MDTDEV=$(echo $(get_mnt_devs $MDTNODE mdt) | awk '{print $1}')
 
-    # OST devices
-    i=0
-    for node in $(osts_nodes); do
-        OSTDEVS[i]=$(get_mnt_devs $node ost)
-        i=$((i + 1))
-    done
+       # MDT devices
+       i=0
+       for node in $(mdts_nodes); do
+               MDTDEVS[i]=$(get_mnt_devs $node mdt)
+               i=$((i + 1))
+       done
+
+       # OST devices
+       i=0
+       for node in $(osts_nodes); do
+               OSTDEVS[i]=$(get_mnt_devs $node ost)
+               i=$((i + 1))
+       done
 }
 
 # Run e2fsck on MDT or OST device.
 run_e2fsck() {
-    local node=$1
-    local target_dev=$2
-    local extra_opts=$3
-
-    df > /dev/null      # update statfs data on disk
-    local cmd="$E2FSCK -d -v -t -t -f $extra_opts $target_dev"
-    echo $cmd
-    local rc=0
-    do_node $node $cmd || rc=$?
-    [ $rc -le $FSCK_MAX_ERR ] || \
-        error "$cmd returned $rc, should be <= $FSCK_MAX_ERR"
-    return 0
-}
+       local node=$1
+       local target_dev=$2
+       local extra_opts=$3
+       local cmd="$E2FSCK -d -v -t -t -f $extra_opts $target_dev"
+       local log=$TMP/e2fsck.log
+       local rc=0
 
-#
-# Run resize2fs on MDT or OST device.
+       echo $cmd
+       do_node $node $cmd 2>&1 | tee $log
+       rc=${PIPESTATUS[0]}
+       if [ -n "$(grep "DNE mode isn't supported" $log)" ]; then
+               rm -f $log
+               if [ $MDSCOUNT -gt 1 ]; then
+                       skip "DNE mode isn't supported!"
+                       cleanupall
+                       exit_status
+               else
+                       error "It's not DNE mode."
+               fi
+       fi
+       rm -f $log
+
+       [ $rc -le $FSCK_MAX_ERR ] ||
+               error "$cmd returned $rc, should be <= $FSCK_MAX_ERR"
+
+       return 0
+}
+
+#
+# Run resize2fs on MDT or OST device.
 #
 run_resize2fs() {
        local facet=$1
@@ -3877,95 +4146,92 @@ check_shared_dir() {
        return 0
 }
 
-# Run e2fsck on MDT and OST(s) to generate databases used for lfsck.
-generate_db() {
-    local i
-    local ostidx
-    local dev
-
-       [[ $(lustre_version_code $SINGLEMDS) -ne $(version_code 2.2.0) ]] ||
-               { skip "Lustre 2.2.0 lacks the patch for LU-1255"; exit 0; }
-
-    check_shared_dir $SHARED_DIRECTORY ||
-        error "$SHARED_DIRECTORY isn't a shared directory"
-
-    export MDSDB=$SHARED_DIRECTORY/mdsdb
-    export OSTDB=$SHARED_DIRECTORY/ostdb
-
-    [ $MDSCOUNT -eq 1 ] || error "CMD is not supported"
-
-    run_e2fsck $(mdts_nodes) $MDTDEV "-n --mdsdb $MDSDB"
+run_lfsck() {
+       do_nodes $(comma_list $(mdts_nodes) $(osts_nodes)) \
+               $LCTL set_param printk=+lfsck
+       do_facet $SINGLEMDS "$LCTL lfsck_start -M $FSNAME-MDT0000 -r -A -t all"
+
+       for k in $(seq $MDSCOUNT); do
+               # wait up to 10+1 minutes for LFSCK to complete
+               wait_update_facet --verbose mds${k} "$LCTL get_param -n \
+                       mdd.$(facet_svc mds${k}).lfsck_layout |
+                       awk '/^status/ { print \\\$2 }'" "completed" 600 ||
+                       error "MDS${k} layout isn't the expected 'completed'"
+               wait_update_facet --verbose mds${k} "$LCTL get_param -n \
+                       mdd.$(facet_svc mds${k}).lfsck_namespace |
+                       awk '/^status/ { print \\\$2 }'" "completed" 60 ||
+                       error "MDS${k} namespace isn't the expected 'completed'"
+       done
+       local rep_mdt=$(do_nodes $(comma_list $(mdts_nodes)) \
+                       $LCTL get_param -n mdd.$FSNAME-*.lfsck_* |
+                       awk '/repaired/ { print $2 }' | calc_sum)
+       local rep_ost=$(do_nodes $(comma_list $(osts_nodes)) \
+                       $LCTL get_param -n obdfilter.$FSNAME-*.lfsck_* |
+                       awk '/repaired/ { print $2 }' | calc_sum)
+       local repaired=$((rep_mdt + rep_ost))
+       [ $repaired -eq 0 ] ||
+               error "lfsck repaired $rep_mdt MDT and $rep_ost OST errors"
+}
+
+dump_file_contents() {
+       local nodes=$1
+       local dir=$2
+       local logname=$3
+       local node
 
-    i=0
-    ostidx=0
-    OSTDB_LIST=""
-    for node in $(osts_nodes); do
-        for dev in ${OSTDEVS[i]}; do
-            run_e2fsck $node $dev "-n --mdsdb $MDSDB --ostdb $OSTDB-$ostidx"
-            OSTDB_LIST="$OSTDB_LIST $OSTDB-$ostidx"
-            ostidx=$((ostidx + 1))
-        done
-        i=$((i + 1))
-    done
+       if [ -z "$nodes" -o -z "$dir" -o -z "$logname" ]; then
+               error_noexit false \
+                       "Invalid parameters for dump_file_contents()"
+               return 1
+       fi
+       for node in ${nodes}; do
+               do_node $node "for i in \\\$(find $dir -type f); do
+                               echo ====\\\${i}=======================;
+                               cat \\\${i};
+                               done" >> ${logname}.${node}.log
+       done
 }
 
-# Run lfsck on server node if lfsck can't be found on client (LU-2571)
-run_lfsck_remote() {
-       local cmd="$LFSCK_BIN -c -l --mdsdb $MDSDB --ostdb $OSTDB_LIST $MOUNT"
-       local client=$1
-       local mounted=true
-       local rc=0
+dump_command_output() {
+       local nodes=$1
+       local cmd=$2
+       local logname=$3
+       local node
 
-       #Check if lustre is already mounted
-       do_rpc_nodes $client is_mounted $MOUNT || mounted=false
-       if ! $mounted; then
-               zconf_mount $client $MOUNT ||
-                       error "failed to mount Lustre on $client"
-       fi
-       #Run lfsck
-       echo $cmd
-       do_node $node $cmd || rc=$?
-       #Umount if necessary
-       if ! $mounted; then
-               zconf_umount $client $MOUNT ||
-                       error "failed to unmount Lustre on $client"
+       if [ -z "$nodes" -o -z "$cmd" -o -z "$logname" ]; then
+               error_noexit false \
+                       "Invalid parameters for dump_command_output()"
+               return 1
        fi
 
-       [ $rc -le $FSCK_MAX_ERR ] ||
-               error "$cmd returned $rc, should be <= $FSCK_MAX_ERR"
-       echo "lfsck finished with rc=$rc"
-
-       return $rc
+       for node in ${nodes}; do
+               do_node $node "echo ====${cmd}=======================;
+                               $cmd" >> ${logname}.${node}.log
+       done
 }
 
-run_lfsck() {
-       local facets="client $SINGLEMDS"
-       local found=false
-       local facet
-       local node
-       local rc=0
-
-       for facet in $facets; do
-               node=$(facet_active_host $facet)
-               if check_progs_installed $node $LFSCK_BIN; then
-                       found=true
-                       break
-               fi
-       done
-       ! $found && error "None of \"$facets\" supports lfsck"
+log_zfs_info() {
+       local logname=$1
 
-       run_lfsck_remote $node || rc=$?
+       # dump file contents from /proc/spl in case of zfs test
+       if [ "$(facet_fstype ost1)" = "zfs" ]; then
+               dump_file_contents "$(osts_nodes)" "/proc/spl" "${logname}"
+               dump_command_output \
+                       "$(osts_nodes)" "zpool events -v" "${logname}"
+       fi
 
-       rm -rvf $MDSDB* $OSTDB* || true
-       return $rc
+       if [ "$(facet_fstype $SINGLEMDS)" = "zfs" ]; then
+               dump_file_contents "$(mdts_nodes)" "/proc/spl" "${logname}"
+               dump_command_output \
+                       "$(mdts_nodes)" "zpool events -v" "${logname}"
+       fi
 }
 
 check_and_cleanup_lustre() {
-    if [ "$LFSCK_ALWAYS" = "yes" -a "$TESTSUITE" != "lfsck" ]; then
-        get_svr_devs
-        generate_db
-        run_lfsck
-    fi
+       if [ "$LFSCK_ALWAYS" = "yes" -a "$TESTSUITE" != "sanity-lfsck" -a \
+            "$TESTSUITE" != "sanity-scrub" ]; then
+               run_lfsck
+       fi
 
        if is_mounted $MOUNT; then
                [ -n "$DIR" ] && rm -rf $DIR/[Rdfs][0-9]* ||
@@ -3973,18 +4239,18 @@ check_and_cleanup_lustre() {
                [ "$ENABLE_QUOTA" ] && restore_quota || true
        fi
 
-    if [ "$I_UMOUNTED2" = "yes" ]; then
-        restore_mount $MOUNT2 || error "restore $MOUNT2 failed"
-    fi
+       if [ "$I_UMOUNTED2" = "yes" ]; then
+               restore_mount $MOUNT2 || error "restore $MOUNT2 failed"
+       fi
 
-    if [ "$I_MOUNTED2" = "yes" ]; then
-        cleanup_mount $MOUNT2
-    fi
+       if [ "$I_MOUNTED2" = "yes" ]; then
+               cleanup_mount $MOUNT2
+       fi
 
-    if [ "$I_MOUNTED" = "yes" ]; then
-        cleanupall -f || error "cleanup failed"
-        unset I_MOUNTED
-    fi
+       if [ "$I_MOUNTED" = "yes" ]; then
+               cleanupall -f || error "cleanup failed"
+               unset I_MOUNTED
+       fi
 }
 
 #######
@@ -4182,24 +4448,24 @@ drop_request() {
 
 drop_reply() {
 # OBD_FAIL_MDS_ALL_REPLY_NET
-    RC=0
-    do_facet $SINGLEMDS lctl set_param fail_loc=0x122
-    do_facet client "$@" || RC=$?
-    do_facet $SINGLEMDS lctl set_param fail_loc=0
-    return $RC
+       RC=0
+       do_facet $SINGLEMDS $LCTL set_param fail_loc=0x122
+       eval "$@" || RC=$?
+       do_facet $SINGLEMDS $LCTL set_param fail_loc=0
+       return $RC
 }
 
 drop_reint_reply() {
 # OBD_FAIL_MDS_REINT_NET_REP
-    RC=0
-    do_facet $SINGLEMDS lctl set_param fail_loc=0x119
-    do_facet client "$@" || RC=$?
-    do_facet $SINGLEMDS lctl set_param fail_loc=0
-    return $RC
+       RC=0
+       do_facet $SINGLEMDS $LCTL set_param fail_loc=0x119
+       eval "$@" || RC=$?
+       do_facet $SINGLEMDS $LCTL set_param fail_loc=0
+       return $RC
 }
 
 drop_update_reply() {
-# OBD_FAIL_UPDATE_OBJ_NET_REP
+# OBD_FAIL_OUT_UPDATE_NET_REP
        local index=$1
        shift 1
        RC=0
@@ -4211,12 +4477,16 @@ drop_update_reply() {
 
 pause_bulk() {
 #define OBD_FAIL_OST_BRW_PAUSE_BULK      0x214
-    RC=0
-    do_facet ost1 lctl set_param fail_loc=0x214
-    do_facet client "$1" || RC=$?
-    do_facet client "sync"
-    do_facet ost1 lctl set_param fail_loc=0
-    return $RC
+       RC=0
+
+       local timeout=${2:-0}
+       # default is (obd_timeout / 4) if unspecified
+       echo "timeout is $timeout/$2"
+       do_facet ost1 lctl set_param fail_val=$timeout fail_loc=0x80000214
+       do_facet client "$1" || RC=$?
+       do_facet client "sync"
+       do_facet ost1 lctl set_param fail_loc=0
+       return $RC
 }
 
 drop_ldlm_cancel() {
@@ -4231,21 +4501,51 @@ drop_ldlm_cancel() {
        return $RC
 }
 
-drop_bl_callback() {
+drop_bl_callback_once() {
+       local rc=0
+       do_facet client lctl set_param ldlm.namespaces.*.early_lock_cancel=0
 #define OBD_FAIL_LDLM_BL_CALLBACK_NET                  0x305
-       RC=0
        do_facet client lctl set_param fail_loc=0x80000305
-       do_facet client "$@" || RC=$?
+       do_facet client "$@" || rc=$?
        do_facet client lctl set_param fail_loc=0
-       return $RC
+       do_facet client lctl set_param fail_val=0
+       do_facet client lctl set_param ldlm.namespaces.*.early_lock_cancel=1
+       return $rc
+}
+
+drop_bl_callback() {
+       rc=0
+       do_facet client lctl set_param ldlm.namespaces.*.early_lock_cancel=0
+#define OBD_FAIL_LDLM_BL_CALLBACK_NET                  0x305
+       do_facet client lctl set_param fail_loc=0x305
+       do_facet client "$@" || rc=$?
+       do_facet client lctl set_param fail_loc=0
+       do_facet client lctl set_param fail_val=0
+       do_facet client lctl set_param ldlm.namespaces.*.early_lock_cancel=1
+       return $rc
 }
 
 drop_ldlm_reply() {
 #define OBD_FAIL_LDLM_REPLY              0x30c
     RC=0
-    do_facet $SINGLEMDS lctl set_param fail_loc=0x30c
+    local list=$(comma_list $(mdts_nodes) $(osts_nodes))
+    do_nodes $list lctl set_param fail_loc=0x30c
+
     do_facet client "$@" || RC=$?
-    do_facet $SINGLEMDS lctl set_param fail_loc=0
+
+    do_nodes $list lctl set_param fail_loc=0
+    return $RC
+}
+
+drop_ldlm_reply_once() {
+#define OBD_FAIL_LDLM_REPLY              0x30c
+    RC=0
+    local list=$(comma_list $(mdts_nodes) $(osts_nodes))
+    do_nodes $list lctl set_param fail_loc=0x8000030c
+
+    do_facet client "$@" || RC=$?
+
+    do_nodes $list lctl set_param fail_loc=0
     return $RC
 }
 
@@ -4258,16 +4558,14 @@ clear_failloc() {
 }
 
 set_nodes_failloc () {
-    do_nodes $(comma_list $1)  lctl set_param fail_loc=$2
+       do_nodes $(comma_list $1)  lctl set_param fail_val=0 fail_loc=$2
 }
 
 cancel_lru_locks() {
-    $LCTL mark "cancel_lru_locks $1 start"
-    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'
-    $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()
@@ -4287,6 +4585,13 @@ lru_resize_disable()
     lctl set_param ldlm.namespaces.*$1*.lru_size $(default_lru_size)
 }
 
+flock_is_enabled()
+{
+       local RC=0
+       [ -z "$(mount | grep "$MOUNT.*flock" | grep -v noflock)" ] && RC=1
+       return $RC
+}
+
 pgcache_empty() {
     local FILE
     for FILE in `lctl get_param -N "llite.*.dump_page_cache"`; do
@@ -4336,7 +4641,7 @@ stop_full_debug_logging() {
 }
 
 # prints bash call stack
-log_trace_dump() {
+print_stack_trace() {
        echo "  Trace dump:"
        for (( i=1; i < ${#BASH_LINENO[*]} ; i++ )) ; do
                local s=${BASH_SOURCE[$i]}
@@ -4362,7 +4667,7 @@ error_noexit() {
 
 
        log " ${TESTSUITE} ${TESTNAME}: @@@@@@ ${TYPE}: $@ "
-       log_trace_dump
+       print_stack_trace >&2
 
        mkdir -p $LOGDIR
        # We need to dump the logs on all nodes
@@ -4382,6 +4687,9 @@ error_noexit() {
                        echo "$@" > $LOGDIR/err
                fi
        fi
+
+       # cleanup the env for failed tests
+       reset_fail_loc
 }
 
 exit_status () {
@@ -4439,10 +4747,16 @@ skip() {
 build_test_filter() {
     EXCEPT="$EXCEPT $(testslist_filter)"
 
-    [ "$ONLY" ] && log "only running test `echo $ONLY`"
-    for O in $ONLY; do
-        eval ONLY_${O}=true
-    done
+       for O in $ONLY; do
+               if [[ $O = [0-9]*-[0-9]* ]]; then
+                       for num in $(seq $(echo $O | tr '-' ' ')); do
+                               eval ONLY_$num=true
+                       done
+               else
+                       eval ONLY_${O}=true
+               fi
+       done
+
     [ "$EXCEPT$ALWAYS_EXCEPT" ] && \
         log "excepting tests: `echo $EXCEPT $ALWAYS_EXCEPT`"
     [ "$EXCEPT_SLOW" ] && \
@@ -4481,69 +4795,69 @@ export ALWAYS_SKIPPED=
 # run or not run.  These need to be documented...
 #
 run_test() {
-    assert_DIR
-
-    export base=`basetest $1`
-    if [ ! -z "$ONLY" ]; then
-        testname=ONLY_$1
-        if [ ${!testname}x != x ]; then
-            [ "$LAST_SKIPPED" ] && echo "" && LAST_SKIPPED=
-            run_one_logged $1 "$2"
-            return $?
-        fi
-        testname=ONLY_$base
-        if [ ${!testname}x != x ]; then
-            [ "$LAST_SKIPPED" ] && echo "" && LAST_SKIPPED=
-            run_one_logged $1 "$2"
-            return $?
-        fi
-        LAST_SKIPPED="y"
-        return 0
-    fi
+       assert_DIR
+
+       export base=$(basetest $1)
+       if [ -n "$ONLY" ]; then
+               testname=ONLY_$1
+               if [ ${!testname}x != x ]; then
+                       [ -n "$LAST_SKIPPED" ] && echo "" && LAST_SKIPPED=
+                       run_one_logged $1 "$2"
+                       return $?
+               fi
+               testname=ONLY_$base
+               if [ ${!testname}x != x ]; then
+                       [ -n "$LAST_SKIPPED" ] && echo "" && LAST_SKIPPED=
+                       run_one_logged $1 "$2"
+                       return $?
+               fi
+               LAST_SKIPPED="y"
+               return 0
+       fi
 
        LAST_SKIPPED="y"
        ALWAYS_SKIPPED="y"
-    testname=EXCEPT_$1
-    if [ ${!testname}x != x ]; then
-        TESTNAME=test_$1 skip "skipping excluded test $1"
-        return 0
-    fi
-    testname=EXCEPT_$base
-    if [ ${!testname}x != x ]; then
-        TESTNAME=test_$1 skip "skipping excluded test $1 (base $base)"
-        return 0
-    fi
-    testname=EXCEPT_ALWAYS_$1
-    if [ ${!testname}x != x ]; then
-        TESTNAME=test_$1 skip "skipping ALWAYS excluded test $1"
-        return 0
-    fi
-    testname=EXCEPT_ALWAYS_$base
-    if [ ${!testname}x != x ]; then
-        TESTNAME=test_$1 skip "skipping ALWAYS excluded test $1 (base $base)"
-        return 0
-    fi
-    testname=EXCEPT_SLOW_$1
-    if [ ${!testname}x != x ]; then
-        TESTNAME=test_$1 skip "skipping SLOW test $1"
-        return 0
-    fi
-    testname=EXCEPT_SLOW_$base
-    if [ ${!testname}x != x ]; then
-        TESTNAME=test_$1 skip "skipping SLOW test $1 (base $base)"
-        return 0
-    fi
+       testname=EXCEPT_$1
+       if [ ${!testname}x != x ]; then
+               TESTNAME=test_$1 skip "skipping excluded test $1"
+               return 0
+       fi
+       testname=EXCEPT_$base
+       if [ ${!testname}x != x ]; then
+               TESTNAME=test_$1 skip "skipping excluded test $1 (base $base)"
+               return 0
+       fi
+       testname=EXCEPT_ALWAYS_$1
+       if [ ${!testname}x != x ]; then
+               TESTNAME=test_$1 skip "skipping ALWAYS excluded test $1"
+               return 0
+       fi
+       testname=EXCEPT_ALWAYS_$base
+       if [ ${!testname}x != x ]; then
+               TESTNAME=test_$1 skip "skipping ALWAYS excluded test $1 (base $base)"
+               return 0
+       fi
+       testname=EXCEPT_SLOW_$1
+       if [ ${!testname}x != x ]; then
+               TESTNAME=test_$1 skip "skipping SLOW test $1"
+               return 0
+       fi
+       testname=EXCEPT_SLOW_$base
+       if [ ${!testname}x != x ]; then
+               TESTNAME=test_$1 skip "skipping SLOW test $1 (base $base)"
+               return 0
+       fi
 
-    LAST_SKIPPED=
-    ALWAYS_SKIPPED=
-    run_one_logged $1 "$2"
+       LAST_SKIPPED=
+       ALWAYS_SKIPPED=
+       run_one_logged $1 "$2"
 
-    return $?
+       return $?
 }
 
 log() {
-    echo "$*"
-    module_loaded lnet || load_modules
+       echo "$*" >&2
+       load_module ../libcfs/libcfs/libcfs
 
     local MSG="$*"
     # Get rid of '
@@ -4597,7 +4911,8 @@ 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 2>/dev/null || true"
+    do_nodes $(comma_list $(nodes_list)) "lctl set_param -n fail_loc=0 \
+           fail_val=0 2>/dev/null || true"
     echo done.
 }
 
@@ -4618,34 +4933,35 @@ banner() {
 }
 
 #
-# Run a single test function and cleanup after it.  
+# Run a single test function and cleanup after it.
 #
 # This function should be run in a subshell so the test func can
 # exit() without stopping the whole script.
 #
 run_one() {
-    local testnum=$1
-    local message=$2
-    tfile=f.${TESTSUITE}.${testnum}
-    export tdir=d0.${TESTSUITE}/d${base}
-    export TESTNAME=test_$testnum
-    local SAVE_UMASK=`umask`
-    umask 0022
-
-    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"
+       local testnum=$1
+       local message=$2
+       export tfile=f${testnum}.${TESTSUITE}
+       export tdir=d${testnum}.${TESTSUITE}
+       export TESTNAME=test_$testnum
+       local SAVE_UMASK=`umask`
+       umask 0022
+
+       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"
        if [ "$PARALLEL" != "yes" ]; then
                ps auxww | grep -v grep | grep -q multiop &&
                                        error "multiop still running"
        fi
-    unset TESTNAME
-    unset tdir
-    umask $SAVE_UMASK
-    return 0
+       unset TESTNAME
+       unset tdir
+       unset tfile
+       umask $SAVE_UMASK
+       return 0
 }
 
 #
@@ -4655,14 +4971,16 @@ run_one() {
 #  - test result is saved to data file
 #
 run_one_logged() {
-       local BEFORE=`date +%s`
+       local BEFORE=$(date +%s)
        local TEST_ERROR
        local name=${TESTSUITE}.test_${1}.test_log.$(hostname -s).log
        local test_log=$LOGDIR/$name
+       local zfs_log_name=${TESTSUITE}.test_${1}.zfs_log
+       local zfs_debug_log=$LOGDIR/$zfs_log_name
        rm -rf $LOGDIR/err
        rm -rf $LOGDIR/ignore
        rm -rf $LOGDIR/skip
-       local SAVE_UMASK=`umask`
+       local SAVE_UMASK=$(umask)
        umask 0022
 
        echo
@@ -4673,7 +4991,7 @@ run_one_logged() {
        [ $RC -ne 0 ] && [ ! -f $LOGDIR/err ] &&
                echo "test_$1 returned $RC" | tee $LOGDIR/err
 
-       duration=$((`date +%s` - $BEFORE))
+       duration=$(($(date +%s) - $BEFORE))
        pass "$1" "(${duration}s)"
 
        if [[ -f $LOGDIR/err ]]; then
@@ -4685,7 +5003,12 @@ run_one_logged() {
        fi
        log_sub_test_end $TEST_STATUS $duration "$RC" "$TEST_ERROR"
 
+       if [[ "$TEST_STATUS" != "SKIP" ]] && [[ -f $TF_SKIP ]]; then
+               rm -f $TF_SKIP
+       fi
+
        if [ -f $LOGDIR/err ]; then
+               log_zfs_info "$zfs_debug_log"
                $FAIL_ON_ERROR && exit $RC
        fi
 
@@ -4704,46 +5027,45 @@ skip_logged(){
 }
 
 canonical_path() {
-    (cd `dirname $1`; echo $PWD/`basename $1`)
+       (cd $(dirname $1); echo $PWD/$(basename $1))
 }
 
 
 check_grant() {
-    export base=`basetest $1`
-    [ "$CHECK_GRANT" == "no" ] && return 0
+       export base=$(basetest $1)
+       [ "$CHECK_GRANT" == "no" ] && return 0
 
-        testname=GCHECK_ONLY_${base}
-        [ ${!testname}x == x ] && return 0
+       testname=GCHECK_ONLY_${base}
+       [ ${!testname}x == x ] && return 0
 
-    echo -n "checking grant......"
+       echo -n "checking grant......"
 
-        local clients=$CLIENTS
-        [ -z $clients ] && clients=$(hostname)
+       local clients=$CLIENTS
+       [ -z "$clients" ] && clients=$(hostname)
 
-    # sync all the data and make sure no pending data on server
-    do_nodes $clients sync
-
-    # get client grant
-    client_grant=`do_nodes $clients \
-                    "$LCTL get_param -n osc.${FSNAME}-*.cur_*grant_bytes" | \
-                    awk '{total += $1} END{print total}'`
-
-    # get server grant
-    server_grant=`do_nodes $(comma_list $(osts_nodes)) \
-                    "$LCTL get_param -n obdfilter.${FSNAME}-OST*.tot_granted" |
-                    awk '{total += $1} END{print total}'`
-
-    # check whether client grant == server grant
-    if [ $client_grant -ne $server_grant ]; then
-        echo "failed: client:${client_grant} server: ${server_grant}."
-        do_nodes $(comma_list $(osts_nodes)) \
-                   "$LCTL get_param obdfilter.${FSNAME}-OST*.tot*"
-        do_nodes $clients "$LCTL get_param osc.${FSNAME}-*.cur_*_bytes"
-        return 1
-    else
-        echo "pass: client:${client_grant} server: ${server_grant}"
-    fi
+       # sync all the data and make sure no pending data on server
+       do_nodes $clients sync
+
+       # get client grant
+       client_grant=$(do_nodes $clients \
+               "$LCTL get_param -n osc.${FSNAME}-*.cur_*grant_bytes" |
+               awk '{ total += $1 } END { printf("%0.0f", total) }')
+
+       # get server grant
+       server_grant=$(do_nodes $(comma_list $(osts_nodes)) \
+               "$LCTL get_param -n obdfilter.${FSNAME}-OST*.tot_granted" |
+               awk '{ total += $1 } END { printf("%0.0f", total) }')
 
+       # check whether client grant == server grant
+       if [[ $client_grant -ne $server_grant ]]; then
+               echo "failed: client:${client_grant} server: ${server_grant}."
+               do_nodes $(comma_list $(osts_nodes)) \
+                       "$LCTL get_param obdfilter.${FSNAME}-OST*.tot*"
+               do_nodes $clients "$LCTL get_param osc.${FSNAME}-*.cur_*_bytes"
+               return 1
+       else
+               echo "pass: client:${client_grant} server: ${server_grant}"
+       fi
 }
 
 ########################
@@ -4866,6 +5188,7 @@ 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" ]
@@ -5085,14 +5408,14 @@ get_stripe () {
 }
 
 setstripe_nfsserver () {
-    local dir=$1
+       local dir=$1
 
-    local nfsserver=$(awk '"'$dir'" ~ $2 && $3 ~ "nfs" && $2 != "/" \
-                { print $1 }' /proc/mounts | cut -f 1 -d : | head -1)
+       local nfsserver=$(awk '"'$dir'" ~ $2 && $3 ~ "nfs" && $2 != "/" \
+               { print $1 }' /proc/mounts | cut -f 1 -d : | head -n1)
 
-    [ -z $nfsserver ] && echo "$dir is not nfs mounted" && return 1
+       [ -z $nfsserver ] && echo "$dir is not nfs mounted" && return 1
 
-    do_nodev $nfsserver lfs setstripe "$@"
+       do_nodev $nfsserver lfs setstripe "$@"
 }
 
 # Check and add a test group.
@@ -5248,7 +5571,7 @@ do_and_time () {
 
     SECONDS=0
     eval '$cmd'
-    
+
     [ ${PIPESTATUS[0]} -eq 0 ] || rc=1
 
     echo $SECONDS
@@ -5256,8 +5579,9 @@ do_and_time () {
 }
 
 inodes_available () {
-    local IFree=$($LFS df -i $MOUNT | grep ^$FSNAME | awk '{print $4}' | sort -un | head -1) || return 1
-    echo $IFree
+       local IFree=$($LFS df -i $MOUNT | grep ^$FSNAME | awk '{ print $4 }' |
+               sort -un | head -n1) || return 1
+       echo $((IFree))
 }
 
 mdsrate_inodes_available () {
@@ -5272,25 +5596,25 @@ clear_llite_stats(){
 
 # sum llite stat items
 calc_llite_stats() {
-        local res=$(lctl get_param -n llite.*.stats |
-                    awk 'BEGIN {s = 0} END {print s} /^'"$1"'/ {s += $2}')
-        echo $res
+       local res=$(lctl get_param -n llite.*.stats |
+               awk '/^'"$1"'/ {sum += $2} END { printf("%0.0f", sum) }')
+       echo $((res))
 }
 
 # reset osc stat counters
 clear_osc_stats(){
-        lctl set_param -n osc.*.osc_stats 0
+       lctl set_param -n osc.*.osc_stats 0
 }
 
 # sum osc stat items
 calc_osc_stats() {
-        local res=$(lctl get_param -n osc.*.osc_stats |
-                    awk 'BEGIN {s = 0} END {print s} /^'"$1"'/ {s += $2}')
-        echo $res
+       local res=$(lctl get_param -n osc.*.osc_stats |
+               awk '/^'"$1"'/ {sum += $2} END { printf("%0.0f", sum) }')
+       echo $((res))
 }
 
 calc_sum () {
-        awk 'BEGIN {s = 0}; {s += $1}; END {print s}'
+       awk '{sum += $1} END { printf("%0.0f", sum) }'
 }
 
 calc_osc_kbytes () {
@@ -5328,50 +5652,15 @@ restore_lustre_params() {
 }
 
 check_catastrophe() {
-       local rnodes=${1:-$(comma_list $(remote_nodes_list))}
-       local C=$CATASTROPHE
-       [ -f $C ] && [ $(cat $C) -ne 0 ] && return 1
-
-       [ -z "$rnodes" ] && return 0
-
-       local data
-       data=$(do_nodes "$rnodes" "rc=\\\$([ -f $C ] &&
-               echo \\\$(< $C) || echo 0);
-               if [ \\\$rc -ne 0 ]; then echo \\\$(hostname): \\\$rc; fi
-               exit \\\$rc")
-       local rc=$?
-       if [ -n "$data" ]; then
-           echo $data
-           return $rc
-       fi
-       return 0
-}
+       local nodes=${1:-$(comma_list $(nodes_list))}
 
-# CMD: determine mds index where directory inode presents
-get_mds_dir () {
-    local dir=$1
-    local file=$dir/f0.get_mds_dir_tmpfile
-
-    mkdir -p $dir
-    rm -f $file
-    sleep 1
-    local iused=$(lfs df -i $dir | grep MDT | awk '{print $3}')
-    local -a oldused=($iused)
-
-    openfile -f O_CREAT:O_LOV_DELAY_CREATE -m 0644 $file > /dev/null
-    sleep 1
-    iused=$(lfs df -i $dir | grep MDT | awk '{print $3}')
-    local -a newused=($iused)
-
-    local num=0
-    for ((i=0; i<${#newused[@]}; i++)); do
-         if [ ${oldused[$i]} -lt ${newused[$i]} ];  then
-             echo $(( i + 1 ))
-             rm -f $file
-             return 0
-         fi
-    done
-    error "mdt-s : inodes count OLD ${oldused[@]} NEW ${newused[@]}"
+       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"
 }
 
 mdsrate_cleanup () {
@@ -5406,17 +5695,7 @@ convert_facet2label() {
 }
 
 get_clientosc_proc_path() {
-    echo "${1}-osc-*"
-}
-
-get_lustre_version () {
-    local facet=${1:-"$SINGLEMDS"}    
-    do_facet $facet $LCTL get_param -n version | awk '/^lustre:/ {print $2}'
-}
-
-lustre_version_code() {
-    local facet=${1:-"$SINGLEMDS"}
-    version_code $(get_lustre_version $1)
+       echo "${1}-osc-*"
 }
 
 # If the 2.0 MDS was mounted on 1.8 device, then the OSC and LOV names
@@ -5434,19 +5713,21 @@ mds_on_old_device() {
 }
 
 get_mdtosc_proc_path() {
-    local mds_facet=$1
-    local ost_label=${2:-"*OST*"}
-
-    [ "$mds_facet" = "mds" ] && mds_facet=$SINGLEMDS
-    local mdt_label=$(convert_facet2label $mds_facet)
-    local mdt_index=$(echo $mdt_label | sed -e 's/^.*-//')
-
-    if [ $(lustre_version_code $mds_facet) -le $(version_code 1.8.0) ] ||
-       mds_on_old_device $mds_facet; then
-        echo "${ost_label}-osc"
-    else
-        echo "${ost_label}-osc-${mdt_index}"
-    fi
+       local mds_facet=$1
+       local ost_label=${2:-"*OST*"}
+
+       [ "$mds_facet" = "mds" ] && mds_facet=$SINGLEMDS
+       local mdt_label=$(convert_facet2label $mds_facet)
+       local mdt_index=$(echo $mdt_label | sed -e 's/^.*-//')
+
+       if [ $(lustre_version_code $mds_facet) -le $(version_code 1.8.0) ] ||
+          mds_on_old_device $mds_facet; then
+               echo "${ost_label}-osc"
+       elif [[ $ost_label = *OST* ]]; then
+               echo "${ost_label}-osc-${mdt_index}"
+       else
+               echo "${ost_label}-osp-${mdt_index}"
+       fi
 }
 
 get_osc_import_name() {
@@ -5467,6 +5748,7 @@ _wait_import_state () {
     local expected=$1
     local CONN_PROC=$2
     local maxtime=${3:-$(max_recovery_time)}
+    local error_on_failure=${4:-1}
     local CONN_STATE
     local i=0
 
@@ -5479,9 +5761,12 @@ _wait_import_state () {
             # reconnect timeout and test can't see real disconnect
             [ "${CONN_STATE}" == "CONNECTING" ] && return 0
         fi
-        [ $i -ge $maxtime ] && \
-            error "can't put import for $CONN_PROC into ${expected} state after $i sec, have ${CONN_STATE}" && \
+       if [ $i -ge $maxtime ]; then
+           [ $error_on_failure -ne 0 ] && \
+               error "can't put import for $CONN_PROC into ${expected}" \
+                     "state after $i sec, have ${CONN_STATE}"
             return 1
+       fi
         sleep 1
        # Add uniq for multi-mount case
        CONN_STATE=$($LCTL get_param -n $CONN_PROC 2>/dev/null | cut -f2 | uniq)
@@ -5496,10 +5781,11 @@ wait_import_state() {
     local state=$1
     local params=$2
     local maxtime=${3:-$(max_recovery_time)}
+    local error_on_failure=${4:-1}
     local param
 
     for param in ${params//,/ }; do
-        _wait_import_state $state $param $maxtime || return
+       _wait_import_state $state $param $maxtime $error_on_failure || return
     done
 }
 
@@ -5552,38 +5838,43 @@ request_timeout () {
 }
 
 _wait_osc_import_state() {
-    local facet=$1
-    local ost_facet=$2
-    local expected=$3
-    local ost=$(get_osc_import_name $facet $ost_facet)
-
-       local param="osc.${ost}.ost_server_uuid"
+       local facet=$1
+       local ost_facet=$2
+       local expected=$3
+       local target=$(get_osc_import_name $facet $ost_facet)
+       local param="osc.${target}.ost_server_uuid"
+       local params=$param
        local i=0
 
-    # 1. wait the deadline of client 1st request (it could be skipped)
-    # 2. wait the deadline of client 2nd request
-    local maxtime=$(( 2 * $(request_timeout $facet)))
-
-       #During setup time, the osc might not be setup, it need wait
-       #until list_param can return valid value. And also if there
-       #are mulitple osc entries we should list all of them before
-       #go to wait.
-       local params=$($LCTL list_param $param 2>/dev/null || true)
-       while [ -z "$params" ]; do
-               if [ $i -ge $maxtime ]; then
-                       echo "can't get $param by list_param in $maxtime secs"
-                       if [[ $facet != client* ]]; then
-                               echo "Go with $param directly"
-                               params=$param
-                               break
-                       else
+       # 1. wait the deadline of client 1st request (it could be skipped)
+       # 2. wait the deadline of client 2nd request
+       local maxtime=$(( 2 * $(request_timeout $facet)))
+
+       if [[ $facet == client* ]]; then
+               # During setup time, the osc might not be setup, it need wait
+               # until list_param can return valid value. And also if there
+               # are mulitple osc entries we should list all of them before
+               # go to wait.
+               params=$($LCTL list_param $param 2>/dev/null || true)
+               while [ -z "$params" ]; do
+                       if [ $i -ge $maxtime ]; then
+                               echo "can't get $param in $maxtime secs"
                                return 1
                        fi
+                       sleep 1
+                       i=$((i + 1))
+                       params=$($LCTL list_param $param 2>/dev/null || true)
+               done
+       fi
+
+       if [[ $ost_facet = mds* ]]; then
+               # no OSP connection to itself
+               if [[ $facet = $ost_facet ]]; then
+                       return 0
                fi
-               sleep 1
-               i=$((i + 1))
-               params=$($LCTL list_param $param 2>/dev/null || true)
-       done
+               param="osp.${target}.mdt_server_uuid"
+               params=$param
+       fi
 
        if ! do_rpc_nodes "$(facet_active_host $facet)" \
                        wait_import_state $expected "$params" $maxtime; then
@@ -5609,10 +5900,81 @@ wait_osc_import_state() {
        fi
 }
 
+_wait_mgc_import_state() {
+       local facet=$1
+       local expected=$2
+       local error_on_failure=${3:-1}
+       local param="mgc.*.mgs_server_uuid"
+       local params=$param
+       local i=0
+
+       # 1. wait the deadline of client 1st request (it could be skipped)
+       # 2. wait the deadline of client 2nd request
+       local maxtime=$(( 2 * $(request_timeout $facet)))
+
+       if [[ $facet == client* ]]; then
+               # During setup time, the osc might not be setup, it need wait
+               # until list_param can return valid value. And also if there
+               # are mulitple osc entries we should list all of them before
+               # go to wait.
+               params=$($LCTL list_param $param 2>/dev/null || true)
+               while [ -z "$params" ]; do
+                       if [ $i -ge $maxtime ]; then
+                               echo "can't get $param in $maxtime secs"
+                               return 1
+                       fi
+                       sleep 1
+                       i=$((i + 1))
+                       params=$($LCTL list_param $param 2>/dev/null || true)
+               done
+       fi
+       if ! do_rpc_nodes "$(facet_active_host $facet)" \
+                       wait_import_state $expected "$params" $maxtime \
+                                         $error_on_failure; then
+               if [ $error_on_failure -ne 0 ]; then
+                   error "import is not in ${expected} state"
+               fi
+               return 1
+       fi
+
+       return 0
+}
+
+wait_mgc_import_state() {
+       local facet=$1
+       local expected=$2
+       local error_on_failure=${3:-1}
+       local num
+
+       if [[ $facet = mds ]]; then
+               for num in $(seq $MDSCOUNT); do
+                       _wait_mgc_import_state mds$num "$expected" \
+                                              $error_on_failure || return
+               done
+       else
+               _wait_mgc_import_state "$facet" "$expected"
+                                      $error_on_failure || return
+       fi
+}
+
+wait_dne_interconnect() {
+       local num
+
+       if [ $MDSCOUNT -gt 1 ]; then
+               for num in $(seq $MDSCOUNT); do
+                       wait_osc_import_state mds mds$num FULL
+               done
+       fi
+}
+
 get_clientmdc_proc_path() {
     echo "${1}-mdc-*"
 }
 
+get_clientmgc_proc_path() {
+    echo "*"
+}
+
 do_rpc_nodes () {
        local list=$1
        shift
@@ -5627,28 +5989,34 @@ do_rpc_nodes () {
 }
 
 wait_clients_import_state () {
-    local list=$1
-    local facet=$2
-    local expected=$3
+       local list=$1
+       local facet=$2
+       local expected=$3
 
-    local facets=$facet
+       local facets=$facet
 
-    if [ "$FAILURE_MODE" = HARD ]; then
-        facets=$(facets_on_host $(facet_active_host $facet))
-    fi
+       if [ "$FAILURE_MODE" = HARD ]; then
+               facets=$(facets_on_host $(facet_active_host $facet))
+       fi
 
-    for facet in ${facets//,/ }; do
-    local label=$(convert_facet2label $facet)
-    local proc_path
-    case $facet in
-        ost* ) proc_path="osc.$(get_clientosc_proc_path $label).ost_server_uuid" ;;
-        mds* ) proc_path="mdc.$(get_clientmdc_proc_path $label).mds_server_uuid" ;;
-        *) error "unknown facet!" ;;
-    esac
-    local params=$(expand_list $params $proc_path)
-    done
+       for facet in ${facets//,/ }; do
+               local label=$(convert_facet2label $facet)
+               local proc_path
+               case $facet in
+               ost* ) proc_path="osc.$(get_clientosc_proc_path \
+                                 $label).ost_server_uuid" ;;
+               mds* ) proc_path="mdc.$(get_clientmdc_proc_path \
+                                 $label).mds_server_uuid" ;;
+               mgs* ) proc_path="mgc.$(get_clientmgc_proc_path \
+                                 $label).mgs_server_uuid" ;;
+               *) error "unknown facet!" ;;
+               esac
+
+               local params=$(expand_list $params $proc_path)
+       done
 
-       if ! do_rpc_nodes "$list" wait_import_state_mount $expected $params; then
+       if ! do_rpc_nodes "$list" wait_import_state_mount $expected $params;
+       then
                error "import is not in ${expected} state"
                return 1
        fi
@@ -5705,19 +6073,21 @@ create_pool() {
 }
 
 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() {
@@ -5835,22 +6205,48 @@ do_ls () {
     return $rc
 }
 
-# target_start_and_reset_recovery_timer()
-#        service_time = at_est2timeout(service_time);
-#        service_time += 2 * (CONNECTION_SWITCH_MAX + CONNECTION_SWITCH_INC +
-#                             INITIAL_CONNECT_TIMEOUT);
-# CONNECTION_SWITCH_MAX : min(25U, max(CONNECTION_SWITCH_MIN,obd_timeout))
-#define CONNECTION_SWITCH_INC 1
-#define INITIAL_CONNECT_TIMEOUT max(CONNECTION_SWITCH_MIN,obd_timeout/20)
-#define CONNECTION_SWITCH_MIN 5U
+# check_and_start_recovery_timer()
+#      service_time = at_est2timeout(service_time);
+#      service_time += 2 * INITIAL_CONNECT_TIMEOUT;
+#      service_time += 2 * (CONNECTION_SWITCH_MAX + CONNECTION_SWITCH_INC);
 
-max_recovery_time () {
-    local init_connect_timeout=$(( TIMEOUT / 20 ))
-    [[ $init_connect_timeout -ge 5 ]] || init_connect_timeout=5
+#define INITIAL_CONNECT_TIMEOUT max(CONNECTION_SWITCH_MIN, obd_timeout/20)
+#define CONNECTION_SWITCH_MAX min(50, max(CONNECTION_SWITCH_MIN, obd_timeout))
+#define CONNECTION_SWITCH_MIN 5
+#define CONNECTION_SWITCH_INC 5
+max_recovery_time() {
+       local init_connect_timeout=$((TIMEOUT / 20))
+       ((init_connect_timeout >= 5)) || init_connect_timeout=5
+
+       local service_time=$(($(at_max_get client) * 9 / 4 + 5))
+       service_time=$((service_time + 2 * (init_connect_timeout + 50 + 5)))
+
+       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
 
-    local service_time=$(( $(at_max_get client) + $(( 2 * $(( 25 + 1  + init_connect_timeout)) )) ))
+       #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
 
-    echo $service_time 
+       #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 () {
@@ -6166,7 +6562,7 @@ check_write_access() {
        local file
 
        for node in ${list//,/ }; do
-               file=$dir/check_file.$(short_hostname $node)
+               file=$dir/check_file.$(short_nodename $node)
                if [[ ! -f "$file" ]]; then
                        # Logdir not accessible/writable from this node.
                        return 1
@@ -6383,6 +6779,32 @@ min_ost_size () {
 }
 
 #
+# Get the available size (KB) of a given obd target.
+#
+get_obd_size() {
+       local facet=$1
+       local obd=$2
+       local size
+
+       [[ $facet != client ]] || return 0
+
+       size=$(do_facet $facet $LCTL get_param -n *.$obd.kbytesavail | head -n1)
+       echo -n $size
+}
+
+#
+# Get the page size (bytes) on a given facet node.
+#
+get_page_size() {
+       local facet=$1
+       local size
+
+       size=$(do_facet $facet getconf PAGE_SIZE)
+       [[ ${PIPESTATUS[0]} = 0 && -n "$size" ]] || size=4096
+       echo -n $size
+}
+
+#
 # Get the block count of the filesystem.
 #
 get_block_count() {
@@ -6453,12 +6875,14 @@ generate_string() {
 
 reformat_external_journal() {
        local facet=$1
+       local var
 
-       if [ ! -z ${EJOURNAL} ]; then
+       var=${facet}_JRN
+       if [ -n "${!var}" ]; then
                local rcmd="do_facet $facet"
 
-               echo "reformat external journal on $facet:${EJOURNAL}"
-               ${rcmd} mke2fs -O journal_dev ${EJOURNAL} || return 1
+               echo "reformat external journal on $facet:${!var}"
+               ${rcmd} mke2fs -O journal_dev ${!var} || return 1
        fi
 }
 
@@ -6498,14 +6922,10 @@ mds_backup_restore() {
        echo "backup data"
        ${rcmd} tar zcf $metadata -C $mntpt/ . > /dev/null 2>&1 || return 3
        # step 6: umount
-       ${rcmd} umount -d $mntpt || return 4
-       # step 7: reformat external journal if needed
-       reformat_external_journal $facet || return 5
+       ${rcmd} $UMOUNT $mntpt || return 4
        # step 8: reformat dev
        echo "reformat new device"
-       add $facet $(mkfs_opts $facet ${devname}) --backfstype ldiskfs \
-               --reformat ${devname} $(mdsvdevname $(facet_number $facet)) \
-               > /dev/null || exit 6
+       format_mdt $(facet_number $facet)
        # step 9: mount dev
        ${rcmd} mount -t ldiskfs $opts $devname $mntpt || return 7
        # step 10: restore metadata
@@ -6518,7 +6938,7 @@ mds_backup_restore() {
        echo "remove recovery logs"
        ${rcmd} rm -fv $mntpt/OBJECTS/* $mntpt/CATALOGS
        # step 13: umount dev
-       ${rcmd} umount -d $mntpt || return 10
+       ${rcmd} $UMOUNT $mntpt || return 10
        # step 14: cleanup tmp backup
        ${rcmd} rm -f $metaea $metadata
        # step 15: reset device label - it's not virgin on
@@ -6558,7 +6978,7 @@ mds_remove_ois() {
                done
        fi
        # step 4: umount
-       ${rcmd} umount -d $mntpt || return 2
+       ${rcmd} $UMOUNT $mntpt || return 2
        # OI files will be recreated when mounted as lustre next time.
 }
 
@@ -6572,47 +6992,394 @@ generate_logname() {
 
 # make directory on different MDTs
 test_mkdir() {
-       local option
-       local parent
-       local child
        local path
-       local rc=0
-
-       case $# in
-               1) path=$1;;
-               2) option=$1
-                  path=$2;;
-               *) error "Only creating single directory is supported";;
-       esac
+       local p_option
+       local stripe_count=2
+       local stripe_index=-1
+       local OPTIND=1
+
+       while getopts "c:i:p" opt; do
+               case $opt in
+                       c) stripe_count=$OPTARG;;
+                       i) stripe_index=$OPTARG;;
+                       p) p_option="-p";;
+                       \?) error "only support -i -c -p";;
+               esac
+       done
 
-       child=$(basename $path)
-       parent=$(dirname $path)
+       shift $((OPTIND - 1))
+       [ $# -eq 1 ] || error "Only creating single directory is supported"
+       path="$*"
 
-       if [ "$option" == "-p" -a -d $parent/$child ]; then
-               return $rc
-       fi
+       if [ "$p_option" == "-p" ]; then
+               local parent=$(dirname $path)
 
-       if [ ! -d ${parent} ]; then
-               if [ "$option" == "-p" ]; then
-                       mkdir -p ${parent}
-               else
-                       return 1
-               fi
+               [ -d $path ] && return 0
+               [ ! -d ${parent} ] && mkdir -p ${parent}
        fi
 
        if [ $MDSCOUNT -le 1 ]; then
-               mkdir $option $parent/$child || rc=$?
+               mkdir $path
        else
-               local mdt_idx=$($LFS getstripe -M $parent)
                local test_num=$(echo $testnum | sed -e 's/[^0-9]*//g')
+               local mdt_index
 
-               if [ "$mdt_idx" -ne 0 ]; then
-                       mkdir $option $parent/$child || rc=$?
+               if [ $stripe_index -eq -1 ]; then
+                       mdt_index=$((test_num % MDSCOUNT))
                else
-                       mdt_idx=$((test_num % MDSCOUNT))
-                       echo "mkdir $mdt_idx for $parent/$child"
-                       $LFS setdirstripe -i $mdt_idx $parent/$child || rc=$?
+                       mdt_index=$stripe_index
                fi
+               echo "striped dir -i$mdt_index -c$stripe_count $path"
+               $LFS setdirstripe -i$mdt_index -c$stripe_count $path
        fi
-       return $rc
+}
+
+# find the smallest and not in use file descriptor
+free_fd()
+{
+        local max_fd=$(ulimit -n)
+        local fd=3
+        while [[ $fd -le $max_fd && -e /proc/self/fd/$fd ]]; do
+                ((++fd))
+        done
+        [ $fd -lt $max_fd ] || error "finding free file descriptor failed"
+        echo $fd
+}
+
+check_mount_and_prep()
+{
+       is_mounted $MOUNT || setupall
+
+       rm -rf $DIR/[df][0-9]* || error "Fail to cleanup the env!"
+       mkdir $DIR/$tdir || error "Fail to mkdir $DIR/$tdir."
+       for idx in $(seq $MDSCOUNT); do
+               local name="MDT$(printf '%04x' $((idx - 1)))"
+               rm -rf $MOUNT/.lustre/lost+found/$name/*
+       done
+}
+
+# calcule how many ost-objects to be created.
+precreated_ost_obj_count()
+{
+       local mdt_idx=$1
+       local ost_idx=$2
+       local mdt_name="MDT$(printf '%04x' $mdt_idx)"
+       local ost_name="OST$(printf '%04x' $ost_idx)"
+       local proc_path="${FSNAME}-${ost_name}-osc-${mdt_name}"
+       local last_id=$(do_facet mds$((mdt_idx + 1)) lctl get_param -n \
+                       osp.$proc_path.prealloc_last_id)
+       local next_id=$(do_facet mds$((mdt_idx + 1)) lctl get_param -n \
+                       osp.$proc_path.prealloc_next_id)
+       echo $((last_id - next_id + 1))
+}
+
+check_file_in_pool()
+{
+       local file=$1
+       local pool=$2
+       local tlist="$3"
+       local res=$($GETSTRIPE $file | grep 0x | cut -f2)
+       for i in $res
+       do
+               for t in $tlist ; do
+                       [ "$i" -eq "$t" ] && continue 2
+               done
+
+               echo "pool list: $tlist"
+               echo "striping: $res"
+               error_noexit "$file not allocated in $pool"
+               return 1
+       done
+       return 0
+}
+
+pool_add() {
+       echo "Creating new pool"
+       local pool=$1
+
+       create_pool $FSNAME.$pool ||
+               { error_noexit "No pool created, result code $?"; return 1; }
+       [ $($LFS pool_list $FSNAME | grep -c "$FSNAME.${pool}\$") -eq 1 ] ||
+               { error_noexit "$pool not in lfs pool_list"; return 2; }
+}
+
+pool_add_targets() {
+       echo "Adding targets to pool"
+       local pool=$1
+       local first=$2
+       local last=$3
+       local step=${4:-1}
+
+       local list=$(seq $first $step $last)
+
+       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_update $HOSTNAME "lctl get_param -n lov.$FSNAME-*.pools.$pool \
+                       | sort -u | tr '\n' ' ' " "$t" || {
+               error_noexit "Add to pool failed"
+               return 1
+       }
+       local lfscount=$($LFS pool_list $FSNAME.$pool | grep -c "\-OST")
+       local addcount=$(((last - first) / step + 1))
+       [ $lfscount -eq $addcount ] || {
+               error_noexit "lfs pool_list bad ost count" \
+                                               "$lfscount != $addcount"
+               return 2
+       }
+}
+
+pool_set_dir() {
+       local pool=$1
+       local tdir=$2
+       echo "Setting pool on directory $tdir"
+
+       $SETSTRIPE -c 2 -p $pool $tdir && return 0
+
+       error_noexit "Cannot set pool $pool to $tdir"
+       return 1
+}
+
+pool_check_dir() {
+       local pool=$1
+       local tdir=$2
+       echo "Checking pool on directory $tdir"
+
+       local res=$($GETSTRIPE --pool $tdir | sed "s/\s*$//")
+       [ "$res" = "$pool" ] && return 0
+
+       error_noexit "Pool on '$tdir' is '$res', not '$pool'"
+       return 1
+}
+
+pool_dir_rel_path() {
+       echo "Testing relative path works well"
+       local pool=$1
+       local tdir=$2
+       local root=$3
+
+       mkdir -p $root/$tdir/$tdir
+       cd $root/$tdir
+       pool_set_dir $pool $tdir          || return 1
+       pool_set_dir $pool ./$tdir        || return 2
+       pool_set_dir $pool ../$tdir       || return 3
+       pool_set_dir $pool ../$tdir/$tdir || return 4
+       rm -rf $tdir; cd - > /dev/null
+}
+
+pool_alloc_files() {
+       echo "Checking files allocation from directory pool"
+       local pool=$1
+       local tdir=$2
+       local count=$3
+       local tlist="$4"
+
+       local failed=0
+       for i in $(seq -w 1 $count)
+       do
+               local file=$tdir/file-$i
+               touch $file
+               check_file_in_pool $file $pool "$tlist" || \
+                       failed=$((failed + 1))
+       done
+       [ "$failed" = 0 ] && return 0
+
+       error_noexit "$failed files not allocated in $pool"
+       return 1
+}
+
+pool_create_files() {
+       echo "Creating files in pool"
+       local pool=$1
+       local tdir=$2
+       local count=$3
+       local tlist="$4"
+
+       mkdir -p $tdir
+       local failed=0
+       for i in $(seq -w 1 $count)
+       do
+               local file=$tdir/spoo-$i
+               $SETSTRIPE -p $pool $file
+               check_file_in_pool $file $pool "$tlist" || \
+                       failed=$((failed + 1))
+       done
+       [ "$failed" = 0 ] && return 0
+
+       error_noexit "$failed files not allocated in $pool"
+       return 1
+}
+
+pool_lfs_df() {
+       echo "Checking 'lfs df' output"
+       local pool=$1
+
+       local t=$($LCTL get_param -n lov.$FSNAME-clilov-*.pools.$pool |
+                       tr '\n' ' ')
+       local res=$($LFS df --pool $FSNAME.$pool |
+                       awk '{print $1}' |
+                       grep "$FSNAME-OST" |
+                       tr '\n' ' ')
+       [ "$res" = "$t" ] && return 0
+
+       error_noexit "Pools OSTs '$t' is not '$res' that lfs df reports"
+       return 1
+}
+
+pool_file_rel_path() {
+       echo "Creating files in a pool with relative pathname"
+       local pool=$1
+       local tdir=$2
+
+       mkdir -p $tdir ||
+               { error_noexit "unable to create $tdir"; return 1 ; }
+       local file="/..$tdir/$tfile-1"
+       $SETSTRIPE -p $pool $file ||
+               { error_noexit "unable to create $file" ; return 2 ; }
+
+       cd $tdir
+       $SETSTRIPE -p $pool $tfile-2 || {
+               error_noexit "unable to create $tfile-2 in $tdir"
+               return 3
+       }
+}
+
+pool_remove_first_target() {
+       echo "Removing first target from a pool"
+       local pool=$1
+
+       local pname="lov.$FSNAME-*.pools.$pool"
+       local t=$($LCTL get_param -n $pname | head -1)
+       do_facet mgs $LCTL pool_remove $FSNAME.$pool $t
+       wait_update $HOSTNAME "lctl get_param -n $pname | grep $t" "" || {
+               error_noexit "$t not removed from $FSNAME.$pool"
+               return 1
+       }
+}
+
+pool_remove_all_targets() {
+       echo "Removing all targets from pool"
+       local pool=$1
+       local file=$2
+       local pname="lov.$FSNAME-*.pools.$pool"
+       for t in $($LCTL get_param -n $pname | sort -u)
+       do
+               do_facet mgs $LCTL pool_remove $FSNAME.$pool $t
+       done
+       wait_update $HOSTNAME "lctl get_param -n $pname" "" || {
+               error_noexit "Pool $FSNAME.$pool cannot be drained"
+               return 1
+       }
+       # striping on an empty/nonexistant pool should fall back
+       # to "pool of everything"
+       touch $file || {
+               error_noexit "failed to use fallback striping for empty pool"
+               return 2
+       }
+       # setstripe on an empty pool should fail
+       $SETSTRIPE -p $pool $file 2>/dev/null && {
+               error_noexit "expected failure when creating file" \
+                                                       "with empty pool"
+               return 3
+       }
+       return 0
+}
+
+pool_remove() {
+       echo "Destroying pool"
+       local pool=$1
+       local file=$2
+
+       do_facet mgs $LCTL pool_destroy $FSNAME.$pool
+
+       sleep 2
+       # striping on an empty/nonexistant pool should fall back
+       # to "pool of everything"
+       touch $file || {
+               error_noexit "failed to use fallback striping for missing pool"
+               return 1
+       }
+       # setstripe on an empty pool should fail
+       $SETSTRIPE -p $pool $file 2>/dev/null && {
+               error_noexit "expected failure when creating file" \
+                                                       "with missing pool"
+               return 2
+       }
+
+       # get param should return err once pool is gone
+       if wait_update $HOSTNAME "lctl get_param -n \
+               lov.$FSNAME-*.pools.$pool 2>/dev/null || echo foo" "foo"
+       then
+               remove_pool_from_list $FSNAME.$pool
+               return 0
+       fi
+       error_noexit "Pool $FSNAME.$pool is not destroyed"
+       return 3
+}
+
+# Get and check the actual stripe count of one file.
+# Usage: check_stripe_count <file> <expected_stripe_count>
+check_stripe_count() {
+       local file=$1
+       local expected=$2
+       local actual
+
+       [[ -z "$file" || -z "$expected" ]] &&
+               error "check_stripe_count: invalid argument"
+
+       local cmd="$GETSTRIPE -c $file"
+       actual=$($cmd) || error "$cmd failed"
+       actual=${actual%% *}
+
+       if [[ $actual -ne $expected ]]; then
+               [[ $expected -eq -1 ]] ||
+                       error "$cmd wrong: found $actual, expected $expected"
+               [[ $actual -eq $OSTCOUNT ]] ||
+                       error "$cmd wrong: found $actual, expected $OSTCOUNT"
+       fi
+}
+
+# Get and check the actual list of OST indices on one file.
+# Usage: check_obdidx <file> <expected_comma_separated_list_of_ost_indices>
+check_obdidx() {
+       local file=$1
+       local expected=$2
+       local obdidx
+
+       [[ -z "$file" || -z "$expected" ]] &&
+               error "check_obdidx: invalid argument!"
+
+       obdidx=$(comma_list $($GETSTRIPE $file | grep -A $OSTCOUNT obdidx |
+                             grep -v obdidx | awk '{print $1}' | xargs))
+
+       [[ $obdidx = $expected ]] ||
+               error "list of OST indices on $file is $obdidx," \
+                     "should be $expected"
+}
+
+# Get and check the actual OST index of the first stripe on one file.
+# Usage: check_start_ost_idx <file> <expected_start_ost_idx>
+check_start_ost_idx() {
+       local file=$1
+       local expected=$2
+       local start_ost_idx
+
+       [[ -z "$file" || -z "$expected" ]] &&
+               error "check_start_ost_idx: invalid argument!"
+
+       start_ost_idx=$($GETSTRIPE $file | grep -A 1 obdidx | grep -v obdidx |
+                       awk '{print $1}')
+
+       [[ $start_ost_idx = $expected ]] ||
+               error "OST index of the first stripe on $file is" \
+                     "$start_ost_idx, should be $expected"
+}
+
+killall_process () {
+       local clients=${1:-$(hostname)}
+       local name=$2
+       local signal=$3
+       local rc=0
+
+       do_nodes $clients "killall $signal $name"
 }