Whamcloud - gitweb
LU-5759 tests: use lfs getstripe -M instead of get_mds_num
[fs/lustre-release.git] / lustre / tests / test-framework.sh
index 816078a..13d02b9 100755 (executable)
@@ -10,7 +10,6 @@ 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
@@ -226,6 +225,7 @@ 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}
@@ -370,7 +370,7 @@ module_loaded () {
 
 # 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
@@ -416,22 +416,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() {
@@ -520,7 +522,6 @@ load_modules_local() {
                        load_module ../ldiskfs/ldiskfs
                        load_module osd-ldiskfs/osd_ldiskfs
                fi
-               load_module nodemap/nodemap
                load_module mgs/mgs
                load_module mdd/mdd
                load_module mdt/mdt
@@ -539,15 +540,27 @@ load_modules_local() {
        $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
-               if grep -qe "/sbin/mount\.lustre " /proc/mounts; then
-                       cmp $MOUNT_LUSTRE /sbin/mount.lustre ||
-                               umount /sbin/mount.lustre
+       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
                fi
-               if ! grep -qe "/sbin/mount\.lustre " /proc/mounts; then
-                       [ ! -f /sbin/mount.lustre ] && touch /sbin/mount.lustre
-                       mount --bind $MOUNT_LUSTRE /sbin/mount.lustre
+               if ! grep -qe "$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
 }
@@ -593,16 +606,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=/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() {
@@ -718,7 +732,8 @@ init_gss() {
         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
 }
@@ -802,6 +817,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
@@ -1183,12 +1217,19 @@ start() {
         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() {
@@ -1431,17 +1472,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_CMD $OPTIONS $device $mnt || return 1
+    do_node $client $MOUNT_CMD $flags $opts $device $mnt || return 1
 
     set_default_debug_nodes $client
 
@@ -1537,22 +1580,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_CMD $OPTIONS $device $mnt;
+    $MOUNT_CMD $flags $opts $device $mnt;
     rc=\\\$?;
 fi;
 exit \\\$rc" || return ${PIPESTATUS[0]}
@@ -1935,8 +1980,12 @@ stop_client_loads() {
 
 # verify that lustre actually cleaned up properly
 cleanup_check() {
-       [ -f "$CATASTROPHE" ] && [[ $(< $CATASTROPHE) -ne 0 ]] &&
-               error "LBUG/LASSERT detected"
+       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
@@ -2015,6 +2064,8 @@ sync_all_data() {
 
 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 etime
@@ -2050,6 +2101,14 @@ wait_delete_completed_mds() {
                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
@@ -2806,7 +2865,7 @@ get_env_vars() {
        local facet
 
        for var in ${!MODOPTS_*}; do
-               value=${!var}
+               value=${!var//\"/\\\"}
                echo -n " ${var}=\"$value\""
        done
 
@@ -3229,7 +3288,7 @@ 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
@@ -3315,6 +3374,24 @@ mkfs_opts() {
        echo -n "$opts"
 }
 
+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
+}
+
 formatall() {
        local quiet
 
@@ -3341,6 +3418,8 @@ formatall() {
                        ${quiet:+>/dev/null} || exit 10
        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})) \
@@ -3857,6 +3936,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
@@ -4070,6 +4156,60 @@ run_lfsck() {
        return $rc
 }
 
+dump_file_contents() {
+       local nodes=$1
+       local dir=$2
+       local logname=$3
+       local node
+
+       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
+}
+
+dump_command_output() {
+       local nodes=$1
+       local cmd=$2
+       local logname=$3
+       local node
+
+       if [ -z "$nodes" -o -z "$cmd" -o -z "$logname" ]; then
+               error_noexit false \
+                       "Invalid parameters for dump_command_output()"
+               return 1
+       fi
+
+       for node in ${nodes}; do
+               do_node $node "echo ====${cmd}=======================;
+                               $cmd" >> ${logname}.${node}.log
+       done
+}
+
+log_zfs_info() {
+       local logname=$1
+
+       # 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
+
+       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
@@ -4095,10 +4235,6 @@ check_and_cleanup_lustre() {
                cleanupall -f || error "cleanup failed"
                unset I_MOUNTED
        fi
-
-       if grep -qe "/sbin/mount\.lustre " /proc/mounts; then
-               umount /sbin/mount.lustre
-       fi
 }
 
 #######
@@ -4296,20 +4432,20 @@ 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() {
@@ -4349,21 +4485,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
 }
 
@@ -4381,10 +4547,31 @@ set_nodes_failloc () {
 
 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'
+
+    if [ $1 != "MGC" ]; then
+       for d in $(lctl get_param -N ldlm.namespaces.*.lru_size |
+                egrep -i $1); do
+           $LCTL set_param -n $d=clear
+       done
+       $LCTL get_param ldlm.namespaces.*.lock_unused_count | egrep -i $1 |
+               grep -v '=0'
+    else
+       for d in $(find \
+               /{proc,sys}/fs/lustre/ldlm/namespaces/*$1*/lru_size \
+               2> /dev/null); do
+           echo "clear" > $d
+       done
+
+       for d in $(find \
+               /{proc,sys}/fs/lustre/ldlm/namespaces/*$1*/lock_unused_count \
+               2> /dev/null); do
+           if [ $(cat $d) != 0 ]; then
+               echo "ldlm.namespaces.$(echo "$d" |
+                       cut -f 7 -d'/').lock_unused_count=$(cat $d)"
+           fi
+       done
+    fi
+
     $LCTL mark "cancel_lru_locks $1 stop"
 }
 
@@ -4461,7 +4648,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]}
@@ -4487,7 +4674,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
@@ -4673,7 +4860,7 @@ run_test() {
 }
 
 log() {
-    echo "$*"
+       echo "$*" >&2
     module_loaded lnet || load_modules
 
     local MSG="$*"
@@ -4728,7 +4915,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.
 }
 
@@ -4791,6 +4979,8 @@ run_one_logged() {
        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
@@ -4822,6 +5012,7 @@ run_one_logged() {
        fi
 
        if [ -f $LOGDIR/err ]; then
+               log_zfs_info "$zfs_debug_log"
                $FAIL_ON_ERROR && exit $RC
        fi
 
@@ -5464,50 +5655,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
-}
-
-# CMD: determine mds index where directory inode presents
-get_mds_dir () {
-    local dir=$1
-    local file=$dir/f0.get_mds_dir_tmpfile
+       local nodes=${1:-$(comma_list $(nodes_list))}
 
-    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 () {
@@ -5966,22 +6122,23 @@ 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) + $(( 2 * $(( 25 + 1  + init_connect_timeout)) )) ))
+       local service_time=$(($(at_max_get client) * 9 / 4 + 5))
+       service_time=$((service_time + 2 * (init_connect_timeout + 50 + 5)))
 
-    echo $service_time 
+       echo -n $service_time
 }
 
 get_clients_mount_count () {
@@ -6805,6 +6962,10 @@ check_mount_and_prep()
 
        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.
@@ -6815,10 +6976,311 @@ precreated_ost_obj_count()
        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} lctl get_param -n \
+       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} lctl get_param -n \
+       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 $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"
+}