Whamcloud - gitweb
LU-7169 tests: check disk corruption during failover
[fs/lustre-release.git] / lustre / tests / test-framework.sh
index 96d86bc..2547035 100755 (executable)
@@ -6,7 +6,6 @@ set -e
 #set -x
 
 export LANG=en_US
-export EJOURNAL=${EJOURNAL:-""}
 export REFORMAT=${REFORMAT:-""}
 export WRITECONF=${WRITECONF:-""}
 export VERBOSE=${VERBOSE:-false}
@@ -24,6 +23,11 @@ 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,6 +75,7 @@ usage() {
 
 print_summary () {
     trap 0
+       [ -z "$DEFAULT_SUITES"] && return 0
     [ "$TESTSUITE" == "lfsck" ] && return 0
     [ -n "$ONLY" ] && echo "WARNING: ONLY is set to $(echo $ONLY)"
     local details
@@ -229,6 +234,7 @@ init_test_env() {
     # 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
@@ -267,6 +273,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" ] && \
@@ -338,6 +347,8 @@ init_test_env() {
        if ! $RPC_MODE; then
                rm -f $TMP/*active
        fi
+
+       export TF_FAIL=${TF_FAIL:-$TMP/tf.fail}
 }
 
 check_cpt_number() {
@@ -354,18 +365,57 @@ 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/\([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.
@@ -381,12 +431,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.
@@ -492,6 +542,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
@@ -542,11 +599,11 @@ load_modules_local() {
        # 'mount' doesn't look in $PATH, just sbin
        local mount_lustre=$LUSTRE/utils/mount.lustre
        if [ -f $mount_lustre ]; then
-               local sbin_mount=/sbin/mount.lustre
-               if grep -qe "$sbin_mount " /proc/mounts; then
-                       cmp $mount_lustre $sbin_mount || umount $sbin_mount
+               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 -qe "$sbin_mount " /proc/mounts; then
+               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"
@@ -606,7 +663,7 @@ unload_modules() {
                fi
        fi
 
-       local sbin_mount=/sbin/mount.lustre
+       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 ||
@@ -1188,17 +1245,46 @@ mount_facet() {
                                   ${!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
@@ -1243,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
@@ -2374,6 +2460,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
@@ -2407,6 +2500,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]}
@@ -2671,7 +2767,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
@@ -2749,13 +2845,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.
@@ -2882,9 +2972,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() {
@@ -2929,12 +3031,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
@@ -3019,7 +3128,7 @@ ostvdevname() {
                        eval VDEVPTR="";;
                zfs )
                        #if $OSTDEVn isn't defined, default is $OSTDEVBASE{n}
-                       # Device formated by zfs
+                       # Device formatted by zfs
                        DEVNAME=OSTDEV$num
                        eval VDEVPTR=${!DEVNAME:=${OSTDEVBASE}${num}};;
                * )
@@ -3029,7 +3138,7 @@ ostvdevname() {
        echo -n $VDEVPTR
 }
 
-# Logical device formated for lustre
+# Logical device formatted for lustre
 mdsdevname() {
        local num=$1
        local DEVNAME=MDSDEV$num
@@ -3063,7 +3172,7 @@ mdsvdevname() {
                        eval VDEVPTR="";;
                zfs )
                        # if $MDSDEVn isn't defined, default is $MDSDEVBASE{n}
-                       # Device formated by ZFS
+                       # Device formatted by ZFS
                        local DEVNAME=MDSDEV$num
                        eval VDEVPTR=${!DEVNAME:=${MDSDEVBASE}${num}};;
                * )
@@ -3151,7 +3260,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() {
@@ -3262,6 +3371,7 @@ cleanup_echo_devs () {
 
 cleanupall() {
     nfs_client_mode && return
+       cifs_client_mode && return
 
     stopall $*
     cleanup_echo_devs
@@ -3330,9 +3440,11 @@ mkfs_opts() {
                                fs_mkfs_opts+="-O large_xattr"
                        fi
 
-                       fs_mkfs_opts+=${MDSJOURNALSIZE:+" -J size=$MDSJOURNALSIZE"}
-                       if [ ! -z $EJOURNAL ]; then
-                               fs_mkfs_opts+=${MDSJOURNALSIZE:+" device=$EJOURNAL"}
+                       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
@@ -3343,7 +3455,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
 
@@ -3388,39 +3505,63 @@ check_ost_indices() {
        done
 }
 
-formatall() {
+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
 }
 
@@ -3498,6 +3639,7 @@ writeconf_all () {
 
 setupall() {
     nfs_client_mode && return
+       cifs_client_mode && return
 
     sanity_mount_check ||
         error "environments are insane!"
@@ -3763,6 +3905,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
 
@@ -3810,6 +3957,7 @@ check_config_clients () {
        local mntpt=$1
 
        nfs_client_mode && return
+       cifs_client_mode && return
 
        do_rpc_nodes "$clients" check_config_client $mntpt
 
@@ -3856,6 +4004,7 @@ is_empty_fs() {
 
 check_and_setup_lustre() {
     nfs_client_mode && return
+       cifs_client_mode && return
 
     local MOUNTED=$(mounted_lustre_filesystems)
 
@@ -4445,7 +4594,7 @@ drop_reint_reply() {
 }
 
 drop_update_reply() {
-# OBD_FAIL_UPDATE_OBJ_NET_REP
+# OBD_FAIL_OUT_UPDATE_NET_REP
        local index=$1
        shift 1
        RC=0
@@ -4857,7 +5006,7 @@ run_test() {
 
 log() {
        echo "$*" >&2
-    module_loaded lnet || load_modules
+       load_module ../libcfs/libcfs/libcfs
 
     local MSG="$*"
     # Get rid of '
@@ -5188,6 +5337,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" ]
@@ -5694,17 +5844,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
@@ -5722,19 +5862,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() {
@@ -5755,6 +5897,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
 
@@ -5767,9 +5910,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)
@@ -5784,10 +5930,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
 }
 
@@ -5843,8 +5990,8 @@ _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 target=$(get_osc_import_name $facet $ost_facet)
+       local param="osc.${target}.ost_server_uuid"
        local params=$param
        local i=0
 
@@ -5868,6 +6015,16 @@ _wait_osc_import_state() {
                        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
+               param="osp.${target}.mdt_server_uuid"
+               params=$param
+       fi
+
        if ! do_rpc_nodes "$(facet_active_host $facet)" \
                        wait_import_state $expected "$params" $maxtime; then
                error "import is not in ${expected} state"
@@ -5892,10 +6049,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
@@ -5910,28 +6138,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
 
-       if ! do_rpc_nodes "$list" wait_import_state_mount $expected $params; then
+               local params=$(expand_list $params $proc_path)
+       done
+
+       if ! do_rpc_nodes "$list" wait_import_state_mount $expected $params;
+       then
                error "import is not in ${expected} state"
                return 1
        fi
@@ -6763,12 +6997,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
 }
 
@@ -6808,14 +7044,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
@@ -6828,7 +7060,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
@@ -6868,7 +7100,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.
 }
 
@@ -6882,62 +7114,46 @@ generate_logname() {
 
 # make directory on different MDTs
 test_mkdir() {
-       local option
-       local parent
-       local child
        local path
        local p_option
-       local option2
        local stripe_count=2
-       local rc=0
-
-       case $# in
-               1) path=$1;;
-               2) option=$1
-                  path=$2;;
-               3) option=$1
-                  option2=$2
-                  path=$3;;
-               *) error "Only creating single directory is supported";;
-       esac
-
-       child=$(basename $path)
-       parent=$(dirname $path)
+       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
 
-       if [ "$option" == "-p" -o "$option2" == "-p" ]; then
-               if [ -d $parent/$child ]; then
-                       return $rc
-               fi
-               p_option="-p"
-       fi
+       shift $((OPTIND - 1))
+       [ $# -eq 1 ] || error "Only creating single directory is supported"
+       path="$*"
 
-       if [ "${option:0:2}" == "-c" ]; then
-               stripe_count=$(echo $option | sed 's/^-c//')
-       fi
+       if [ "$p_option" == "-p" ]; then
+               local parent=$(dirname $path)
 
-       if [ "${option2:0:2}" == "-c" ]; then
-               stripe_count=$(echo $option2 | sed 's/^-c//')
-       fi
-
-       if [ ! -d ${parent} ]; then
-               if [ "$p_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 $p_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
 
-               mdt_idx=$((test_num % MDSCOUNT))
-               echo "striped dir -i$mdt_idx -c$stripe_count $path"
-               $LFS setdirstripe -i$mdt_idx -c$stripe_count $path || rc=$?
+               if [ $stripe_index -eq -1 ]; then
+                       mdt_index=$((test_num % MDSCOUNT))
+               else
+                       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
@@ -7005,7 +7221,7 @@ pool_add() {
 
        create_pool $FSNAME.$pool ||
                { error_noexit "No pool created, result code $?"; return 1; }
-       [ $($LFS pool_list $FSNAME | grep -c $pool) -eq 1 ] ||
+       [ $($LFS pool_list $FSNAME | grep -c "$FSNAME.${pool}\$") -eq 1 ] ||
                { error_noexit "$pool not in lfs pool_list"; return 2; }
 }
 
@@ -7280,3 +7496,12 @@ check_start_ost_idx() {
                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"
+}