Whamcloud - gitweb
LU-13284 tests: few tests miss MDS_MOUNT_OPTS/OST_MOUNT_OPTS
[fs/lustre-release.git] / lustre / tests / test-framework.sh
index 6cfde4d..0a34e25 100755 (executable)
@@ -293,6 +293,8 @@ init_test_env() {
        fi
        export RSYNC_RSH=${RSYNC_RSH:-rsh}
 
+       export LNETCTL=${LNETCTL:-"$LUSTRE/../lnet/utils/lnetctl"}
+       [ ! -f "$LNETCTL" ] && export LNETCTL=$(which lnetctl 2> /dev/null)
        export LCTL=${LCTL:-"$LUSTRE/utils/lctl"}
        [ ! -f "$LCTL" ] && export LCTL=$(which lctl)
        export LFS=${LFS:-"$LUSTRE/utils/lfs"}
@@ -432,8 +434,11 @@ init_test_env() {
        get_lustre_env
 
        # use localrecov to enable recovery for local clients, LU-12722
-       [[ $MDS1_VERSION -lt $(version_code 2.13.52) ]] ||
+       [[ $MDS1_VERSION -lt $(version_code 2.13.52) ]] || {
                export MDS_MOUNT_OPTS=${MDS_MOUNT_OPTS:-"-o localrecov"}
+               export MGS_MOUNT_OPTS=${MGS_MOUNT_OPTS:-"-o localrecov"}
+       }
+
        [[ $OST1_VERSION -lt $(version_code 2.13.52) ]] ||
                export OST_MOUNT_OPTS=${OST_MOUNT_OPTS:-"-o localrecov"}
 }
@@ -455,10 +460,10 @@ check_cpt_number() {
 # 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", "3"
+       eval set -- $(tr "[:punct:][a-z]" " " <<< $*)
 
-       echo -n $(((${1:-0} << 16) | (${2:-0} << 8) | ${3:-0}))
+       echo -n $(((${1:-0}<<24) | (${2:-0}<<16) | (${3:-0}<<8) | (${4:-0})))
 }
 
 export LINUX_VERSION=$(uname -r | sed -e "s/\([0-9]*\.[0-9]*\.[0-9]*\).*/\1/")
@@ -821,9 +826,7 @@ check_mem_leak () {
        fi
 }
 
-unload_modules() {
-       wait_exit_ST client # bug 12845
-
+unload_modules_local() {
        $LUSTRE_RMMOD ldiskfs || return 2
 
        [ -f /etc/udev/rules.d/99-lustre-test.rules ] &&
@@ -831,15 +834,23 @@ unload_modules() {
        udevadm control --reload-rules
        udevadm trigger
 
+       check_mem_leak || return 254
+
+       return 0
+}
+
+unload_modules() {
+       local rc=0
+
+       wait_exit_ST client # bug 12845
+
+       unload_modules_local || rc=$?
+
        if $LOAD_MODULES_REMOTE; then
                local list=$(comma_list $(remote_nodes_list))
                if [ -n "$list" ]; then
                        echo "unloading modules on: '$list'"
-                       do_rpc_nodes "$list" $LUSTRE_RMMOD ldiskfs
-                       do_rpc_nodes "$list" check_mem_leak
-                       do_rpc_nodes "$list" "rm -f /etc/udev/rules.d/99-lustre-test.rules"
-                       do_rpc_nodes "$list" "udevadm control --reload-rules"
-                       do_rpc_nodes "$list" "udevadm trigger"
+                       do_rpc_nodes "$list" unload_modules_local
                fi
        fi
 
@@ -850,10 +861,9 @@ unload_modules() {
                        rm -f $sbin_mount
        fi
 
-       check_mem_leak || return 254
+       [[ $rc -eq 0 ]] && echo "modules unloaded."
 
-       echo "modules unloaded."
-       return 0
+       return $rc
 }
 
 fs_log_size() {
@@ -1033,6 +1043,16 @@ init_gss() {
                start_gss_daemons || error_exit "start gss daemon failed! rc=$?"
        fi
 
+       if $GSS_SK && ! $SK_NO_KEY; then
+               echo "Loading basic SSK keys on all servers"
+               do_nodes $(comma_list $(all_server_nodes)) \
+                       "lgss_sk -t server -l $SK_PATH/$FSNAME.key || true"
+               do_nodes $(comma_list $(all_server_nodes)) \
+                               "keyctl show | grep lustre | cut -c1-11 |
+                               sed -e 's/ //g;' |
+                               xargs -IX keyctl setperm X 0x3f3f3f3f"
+       fi
+
        if $GSS_SK && $SK_NO_KEY; then
                local numclients=${1:-$CLIENTCOUNT}
                local clients=${CLIENTS:-$HOSTNAME}
@@ -1301,20 +1321,6 @@ devicelabel() {
        echo -n $label
 }
 
-mdsdevlabel() {
-       local num=$1
-       local device=$(mdsdevname $num)
-       local label=$(devicelabel mds$num ${device} | grep -v "CMD: ")
-       echo -n $label
-}
-
-ostdevlabel() {
-       local num=$1
-       local device=$(ostdevname $num)
-       local label=$(devicelabel ost$num ${device} | grep -v "CMD: ")
-       echo -n $label
-}
-
 #
 # Get the device of a facet.
 #
@@ -2979,35 +2985,6 @@ stop_client_loads() {
 }
 # End recovery-scale functions
 
-# verify that lustre actually cleaned up properly
-cleanup_check() {
-       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
-
-       [[ $($LCTL dl 2>/dev/null | wc -l) -gt 0 ]] && $LCTL dl &&
-               echo "$TESTSUITE: lustre didn't clean up..." 1>&2 &&
-               return 202 || true
-
-       if module_loaded lnet || module_loaded libcfs; then
-               echo "$TESTSUITE: modules still loaded..." 1>&2
-               /sbin/lsmod 1>&2
-               return 203
-       fi
-       return 0
-}
-
 ##
 # wait for a command to return the expected result
 #
@@ -3660,10 +3637,6 @@ facet_failover() {
        done
 }
 
-obd_name() {
-    local facet=$1
-}
-
 replay_barrier() {
        local facet=$1
        do_facet $facet "sync; sync; sync"
@@ -3763,16 +3736,19 @@ fail() {
 }
 
 fail_nodf() {
-        local facet=$1
-        facet_failover $facet
+       local facet=$1
+
+       facet_failover $facet
 }
 
 fail_abort() {
        local facet=$1
+       local abort_type=${2:-"abort_recovery"}
+
        stop $facet
        change_active $facet
        wait_for_facet $facet
-       mount_facet $facet -o abort_recovery
+       mount_facet $facet -o $abort_type
        clients_up || echo "first stat failed: $?"
        clients_up || error "post-failover stat: $?"
 }
@@ -4217,6 +4193,12 @@ add() {
        stop ${facet} -f
        rm -f $TMP/${facet}active
        [[ $facet = mds1 ]] && combined_mgs_mds && rm -f $TMP/mgsactive
+
+       # make sure in-tree ldiskfs is loaded before mkfs
+       if local_mode && [[ $(node_fstypes $HOSTNAME) == *ldiskfs* ]]; then
+               load_module ../ldiskfs/ldiskfs
+       fi
+
        do_facet ${facet} $MKFS $* || return ${PIPESTATUS[0]}
 
        if [[ $(facet_fstype $facet) == zfs ]]; then
@@ -5404,27 +5386,6 @@ is_mounted () {
        echo $mounted' ' | grep -w -q $mntpt' '
 }
 
-is_empty_dir() {
-       [ $(find $1 -maxdepth 1 -print | wc -l) = 1 ] && return 0
-       return 1
-}
-
-# empty lustre filesystem may have empty directories lost+found and .lustre
-is_empty_fs() {
-       # exclude .lustre & lost+found
-       [ $(find $1 -maxdepth 1 -name lost+found -o -name .lustre -prune -o \
-               -print | wc -l) = 1 ] || return 1
-       [ ! -d $1/lost+found ] || is_empty_dir $1/lost+found || return 1
-       if [ $(lustre_version_code $SINGLEMDS) -gt $(version_code 2.4.0) ]; then
-               # exclude .lustre/fid (LU-2780)
-               [ $(find $1/.lustre -maxdepth 1 -name fid -prune -o \
-                       -print | wc -l) = 1 ] || return 1
-       else
-               [ ! -d $1/.lustre ] || is_empty_dir $1/.lustre || return 1
-       fi
-       return 0
-}
-
 check_and_setup_lustre() {
        sanitize_parameters
        nfs_client_mode && return
@@ -5540,51 +5501,6 @@ cleanup_and_setup_lustre() {
     check_and_setup_lustre
 }
 
-# Get all of the server target devices from a given server node and type.
-get_mnt_devs() {
-       local node=$1
-       local type=$2
-       local devs
-       local dev
-
-       if [ "$type" == ost ]; then
-               devs=$(get_osd_param $node "" mntdev)
-       else
-               devs=$(do_node $node $LCTL get_param -n osd-*.$FSNAME-M*.mntdev)
-       fi
-       for dev in $devs; do
-               case $dev in
-               *loop*) do_node $node "losetup $dev" | \
-                               sed -e "s/.*(//" -e "s/).*//" ;;
-               *) echo $dev ;;
-               esac
-       done
-}
-
-# Get all of the server target devices.
-get_svr_devs() {
-       local node
-       local i
-
-       # Master MDS parameters used by lfsck
-       MDTNODE=$(facet_active_host $SINGLEMDS)
-       MDTDEV=$(echo $(get_mnt_devs $MDTNODE mdt) | awk '{print $1}')
-
-       # 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
@@ -5910,10 +5826,6 @@ at_max_get() {
     at_get $1 at_max
 }
 
-at_min_get() {
-       at_get $1 at_min
-}
-
 at_max_set() {
     local at_max=$1
     shift
@@ -6599,7 +6511,7 @@ run_one_logged() {
 
                # remove temp files between repetitions to avoid test failures
                [ -n "$append" -a -n "$DIR" -a -n "$tdir" -a -n "$tfile" ] &&
-                       rm -rf $DIR/$tdir* $DIR/$tfile*
+                       rm -rvf $DIR/$tdir* $DIR/$tfile*
                # loop around subshell so stack_trap EXIT triggers each time
                (run_one $testnum "$testmsg") 2>&1 | tee -i $append $test_log
                rc=${PIPESTATUS[0]}
@@ -6654,10 +6566,6 @@ skip_logged(){
        log_sub_test_end "SKIP" "0" "0" "$@"
 }
 
-canonical_path() {
-       (cd $(dirname $1); echo $PWD/$(basename $1))
-}
-
 grant_from_clients() {
        local nodes="$1"
 
@@ -6777,7 +6685,7 @@ host_id() {
 # Description:
 #   Returns list of ip addresses for each interface
 local_addr_list() {
-       ip addr | awk '/inet\ / {print $2}' | awk -F\/ '{print $1}'
+       ip addr | awk '/inet / {print $2}' | awk -F/ '{print $1}'
 }
 
 is_local_addr() {
@@ -6901,11 +6809,6 @@ osts_nodes () {
        echo -n $(facets_nodes $(get_facets OST))
 }
 
-# Get all of the active AGT (HSM agent) nodes.
-agts_nodes () {
-       echo -n $(facets_nodes $(get_facets AGT))
-}
-
 # Get all of the client nodes and active server nodes.
 nodes_list () {
        local nodes=$HOSTNAME
@@ -7045,12 +6948,6 @@ get_node_count() {
     echo $nodes | wc -w || true
 }
 
-mixed_ost_devs () {
-    local nodes=$(osts_nodes)
-    local osscount=$(get_node_count "$nodes")
-    [ ! "$OSTCOUNT" = "$osscount" ]
-}
-
 mixed_mdt_devs () {
     local nodes=$(mdts_nodes)
     local mdtcount=$(get_node_count "$nodes")
@@ -7075,23 +6972,6 @@ get_stripe () {
        rm -f $file
 }
 
-setstripe_nfsserver () {
-       local dir=$1
-       local nfsexportdir=$2
-       shift
-       shift
-
-       local -a nfsexport=($(awk '"'$dir'" ~ $2 && $3 ~ "nfs" && $2 != "/" \
-               { print $1 }' /proc/mounts | cut -f 1 -d :))
-
-       # check that only one nfs mounted
-       [[ -z $nfsexport ]] && echo "$dir is not nfs mounted" && return 1
-       (( ${#nfsexport[@]} == 1 )) ||
-               error "several nfs mounts found for $dir: ${nfsexport[@]} !"
-
-       do_nodev ${nfsexport[0]} lfs setstripe $nfsexportdir "$@"
-}
-
 # Check and add a test group.
 add_group() {
        local group_id=$1
@@ -7150,35 +7030,46 @@ add_user() {
 }
 
 check_runas_id_ret() {
-    local myRC=0
-    local myRUNAS_UID=$1
-    local myRUNAS_GID=$2
-    shift 2
-    local myRUNAS=$@
-    if [ -z "$myRUNAS" ]; then
-        error_exit "myRUNAS command must be specified for check_runas_id"
-    fi
-    if $GSS_KRB5; then
-        $myRUNAS krb5_login.sh || \
-            error "Failed to refresh Kerberos V5 TGT for UID $myRUNAS_ID."
-    fi
-    mkdir $DIR/d0_runas_test
-    chmod 0755 $DIR
-    chown $myRUNAS_UID:$myRUNAS_GID $DIR/d0_runas_test
-    $myRUNAS touch $DIR/d0_runas_test/f$$ || myRC=$?
-    rm -rf $DIR/d0_runas_test
-    return $myRC
+       local myRC=0
+       local myRUNAS_UID=$1
+       local myRUNAS_GID=$2
+       shift 2
+       local myRUNAS=$@
+
+       if [ -z "$myRUNAS" ]; then
+               error_exit "check_runas_id_ret requires myRUNAS argument"
+       fi
+
+       $myRUNAS true ||
+               error "Unable to execute $myRUNAS"
+
+       id $myRUNAS_UID > /dev/null ||
+               error "Invalid RUNAS_ID $myRUNAS_UID. Please set RUNAS_ID to " \
+                     "some UID which exists on MDS and client or add user " \
+                     "$myRUNAS_UID:$myRUNAS_GID on these nodes."
+
+       if $GSS_KRB5; then
+               $myRUNAS krb5_login.sh ||
+                       error "Failed to refresh krb5 TGT for UID $myRUNAS_ID."
+       fi
+       mkdir $DIR/d0_runas_test
+       chmod 0755 $DIR
+       chown $myRUNAS_UID:$myRUNAS_GID $DIR/d0_runas_test
+       $myRUNAS -u $myRUNAS_UID -g $myRUNAS_GID touch $DIR/d0_runas_test/f$$ ||
+               myRC=$?
+       rm -rf $DIR/d0_runas_test
+       return $myRC
 }
 
 check_runas_id() {
-    local myRUNAS_UID=$1
-    local myRUNAS_GID=$2
-    shift 2
-    local myRUNAS=$@
-    check_runas_id_ret $myRUNAS_UID $myRUNAS_GID $myRUNAS || \
-        error "unable to write to $DIR/d0_runas_test as UID $myRUNAS_UID.
-        Please set RUNAS_ID to some UID which exists on MDS and client or
-        add user $myRUNAS_UID:$myRUNAS_GID on these nodes."
+       local myRUNAS_UID=$1
+       local myRUNAS_GID=$2
+       shift 2
+       local myRUNAS=$@
+
+       check_runas_id_ret $myRUNAS_UID $myRUNAS_GID $myRUNAS || \
+               error "unable to write to $DIR/d0_runas_test as " \
+                     "UID $myRUNAS_UID."
 }
 
 # obtain the UID/GID for MPI_USER
@@ -7337,11 +7228,6 @@ mdsrate_cleanup () {
        fi
 }
 
-delayed_recovery_enabled () {
-    local var=${SINGLEMDS}_svc
-    do_facet $SINGLEMDS lctl get_param -n mdd.${!var}.stale_export_age > /dev/null 2>&1
-}
-
 ########################
 
 convert_facet2label() {
@@ -7366,20 +7252,6 @@ get_clientosc_proc_path() {
        echo "${1}-osc-[-0-9a-f]*"
 }
 
-# If the 2.0 MDS was mounted on 1.8 device, then the OSC and LOV names
-# used by MDT would not be changed.
-# mdt lov: fsname-mdtlov
-# mdt osc: fsname-OSTXXXX-osc
-mds_on_old_device() {
-    local mds=${1:-"$SINGLEMDS"}
-
-    if [ $(lustre_version_code $mds) -gt $(version_code 1.9.0) ]; then
-        do_facet $mds "lctl list_param osc.$FSNAME-OST*-osc \
-            > /dev/null 2>&1" && return 0
-    fi
-    return 1
-}
-
 get_mdtosc_proc_path() {
        local mds_facet=$1
        local ost_label=${2:-"*OST*"}
@@ -7539,8 +7411,9 @@ _wait_osc_import_state() {
                params=$param
        fi
 
+       local plist=$(comma_list $params)
        if ! do_rpc_nodes "$(facet_active_host $facet)" \
-                       wait_import_state $expected "$params" $maxtime; then
+                       wait_import_state $expected $plist $maxtime; then
                error "$facet: import is not in $expected state after $maxtime"
                return 1
        fi
@@ -7595,8 +7468,9 @@ _wait_mgc_import_state() {
                        params=$($LCTL list_param $param 2>/dev/null || true)
                done
        fi
+       local plist=$(comma_list $params)
        if ! do_rpc_nodes "$(facet_active_host $facet)" \
-                       wait_import_state $expected "$params" $maxtime \
+                       wait_import_state $expected $plist $maxtime \
                                          $error_on_failure; then
                if [ $error_on_failure -ne 0 ]; then
                    error "import is not in ${expected} state"
@@ -7928,8 +7802,11 @@ gather_logs () {
        fi
 
        if [ ! -f $LOGDIR/shared ]; then
-               do_nodes $list rsync -az "${prefix}.*.${suffix}" \
-                        $HOSTNAME:$LOGDIR
+               local remote_nodes=$(exclude_items_from_list $list $HOSTNAME)
+
+               for node in ${remote_nodes//,/ }; do
+                       rsync -az -e ssh $node:${prefix}.'*'.${suffix} $LOGDIR &
+               done
        fi
 }
 
@@ -8499,94 +8376,6 @@ run_llverfs()
         llverfs $partial_arg $llverfs_opts $dir
 }
 
-#Remove objects from OST
-remove_ost_objects() {
-       local facet=$1
-       local ostdev=$2
-       local group=$3
-       shift 3
-       local objids="$@"
-       local mntpt=$(facet_mntpt $facet)
-       local opts=$OST_MOUNT_OPTS
-       local i
-       local rc
-
-       echo "removing objects from $ostdev on $facet: $objids"
-       if ! test -b $ostdev; then
-               opts=$(csa_add "$opts" -o loop)
-       fi
-       mount -t $(facet_fstype $facet) $opts $ostdev $mntpt ||
-               return $?
-       rc=0
-       for i in $objids; do
-               rm $mntpt/O/$group/d$((i % 32))/$i || { rc=$?; break; }
-       done
-       umount -f $mntpt || return $?
-       return $rc
-}
-
-#Remove files from MDT
-remove_mdt_files() {
-       local facet=$1
-       local mdtdev=$2
-       shift 2
-       local files="$@"
-       local mntpt=$(facet_mntpt $facet)
-       local opts=$MDS_MOUNT_OPTS
-
-       echo "removing files from $mdtdev on $facet: $files"
-       if [ $(facet_fstype $facet) == ldiskfs ] &&
-          ! do_facet $facet test -b $mdtdev; then
-               opts=$(csa_add "$opts" -o loop)
-       fi
-       mount -t $(facet_fstype $facet) $opts $mdtdev $mntpt ||
-               return $?
-       rc=0
-       for f in $files; do
-               rm $mntpt/ROOT/$f || { rc=$?; break; }
-       done
-       umount -f $mntpt || return $?
-       return $rc
-}
-
-duplicate_mdt_files() {
-       local facet=$1
-       local mdtdev=$2
-       shift 2
-       local files="$@"
-       local mntpt=$(facet_mntpt $facet)
-       local opts=$MDS_MOUNT_OPTS
-
-       echo "duplicating files on $mdtdev on $facet: $files"
-       mkdir -p $mntpt || return $?
-       if [ $(facet_fstype $facet) == ldiskfs ] &&
-          ! do_facet $facet test -b $mdtdev; then
-               opts=$(csa_add "$opts" -o loop)
-       fi
-       mount -t $(facet_fstype $facet) $opts $mdtdev $mntpt ||
-               return $?
-
-    do_umount() {
-        trap 0
-        popd > /dev/null
-        rm $tmp
-        umount -f $mntpt
-    }
-    trap do_umount EXIT
-
-    tmp=$(mktemp $TMP/setfattr.XXXXXXXXXX)
-    pushd $mntpt/ROOT > /dev/null || return $?
-    rc=0
-    for f in $files; do
-        touch $f.bad || return $?
-        getfattr -n trusted.lov $f | sed "s#$f#&.bad#" > $tmp
-        rc=${PIPESTATUS[0]}
-        [ $rc -eq 0 ] || return $rc
-        setfattr --restore $tmp || return $?
-    done
-    do_umount
-}
-
 run_sgpdd () {
     local devs=${1//,/ }
     shift
@@ -8674,17 +8463,6 @@ get_block_count() {
        echo -n ${count:-0}
 }
 
-# Get the block size of the filesystem.
-get_block_size() {
-       local facet=$1
-       local device=$2
-       local size
-
-       [ -z "$CLIENTONLY" ] && size=$(do_facet $facet "$DUMPE2FS -h $device 2>&1" |
-               awk '/^Block size:/ {print $3}')
-       echo -n ${size:-0}
-}
-
 # Check whether the "ea_inode" feature is enabled or not, to allow
 # ldiskfs xattrs over one block in size.  Allow both the historical
 # Lustre feature name (large_xattr) and the upstream name (ea_inode).
@@ -8986,8 +8764,18 @@ pool_add_targets() {
        fi
 
        local t=$(for i in $list; do printf "$FSNAME-OST%04x_UUID " $i; done)
+       local tg=$(for i in $list;
+               do printf -- "-e $FSNAME-OST%04x_UUID " $i; done)
+       local firstx=$(printf "%04x" $first)
+       local lastx=$(printf "%04x" $last)
+
        do_facet mgs $LCTL pool_add \
-                       $FSNAME.$pool $FSNAME-OST[$first-$last/$step]
+               $FSNAME.$pool $FSNAME-OST[$firstx-$lastx/$step]
+       # ignore EEXIST(17)
+       if (( $? != 0 && $? != 17 )); then
+               error_noexit "pool_add $FSNAME-OST[$firstx-$lastx/$step] failed"
+               return 3
+       fi
 
        # wait for OSTs to be added to the pool
        for mds_id in $(seq $MDSCOUNT); do
@@ -8995,23 +8783,16 @@ pool_add_targets() {
                local lodname=$FSNAME-MDT$(printf "%04x" $mdt_id)-mdtlov
                wait_update_facet mds$mds_id \
                        "lctl get_param -n lod.$lodname.pools.$pool |
-                               sort -u | tr '\n' ' ' " "$t" || {
+                               grep $tg | sort -u | tr '\n' ' '" "$t" || {
                        error_noexit "mds$mds_id: Add to pool failed"
-                       return 3
+                       return 2
                }
        done
-       wait_update $HOSTNAME "lctl get_param -n lov.$FSNAME-*.pools.$pool \
-                       | sort -u | tr '\n' ' ' " "$t" || {
+       wait_update $HOSTNAME "lctl get_param -n lov.$FSNAME-*.pools.$pool |
+                       grep $tg | 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() {
@@ -9534,14 +9315,17 @@ check_clients_evicted() {
        local rc=0
 
        for osc in $oscs; do
-               ((rc++))
                echo "Check state for $osc"
                local evicted=$(do_facet client $LCTL get_param osc.$osc.state |
-                       tail -n 3 | awk -F"[ [,]" \
-                       '/EVICTED ]$/ { if (mx<$5) {mx=$5;} } END { print mx }')
+                       tail -n 5 | awk -F"[ ,]" \
+                       '/EVICTED/ { if (mx<$4) { mx=$4; } } END { print mx }')
                if (($? == 0)) && (($evicted > $before)); then
                        echo "$osc is evicted at $evicted"
-                       ((rc--))
+               else
+                       ((rc++))
+                       echo "$osc was not evicted after $before:"
+                       do_facet client $LCTL get_param osc.$osc.state |
+                               tail -n 8
                fi
        done
 
@@ -10063,10 +9847,16 @@ init_agt_vars() {
        export SINGLEAGT=${SINGLEAGT:-agt1}
 
        export HSMTOOL=${HSMTOOL:-"lhsmtool_posix"}
+       export HSMTOOL_PID_FILE=${HSMTOOL_PID_FILE:-"/var/run/lhsmtool_posix.pid"}
        export HSMTOOL_VERBOSE=${HSMTOOL_VERBOSE:-""}
        export HSMTOOL_UPDATE_INTERVAL=${HSMTOOL_UPDATE_INTERVAL:=""}
        export HSMTOOL_EVENT_FIFO=${HSMTOOL_EVENT_FIFO:=""}
        export HSMTOOL_TESTDIR
+       export HSMTOOL_ARCHIVE_FORMAT=${HSMTOOL_ARCHIVE_FORMAT:-v2}
+
+       if ! [[ $HSMTOOL =~ hsmtool ]]; then
+               echo "HSMTOOL = '$HSMTOOL' does not contain 'hsmtool', GLWT" >&2
+       fi
 
        HSM_ARCHIVE_NUMBER=2
 
@@ -10100,10 +9890,17 @@ get_mdt_devices() {
        done
 }
 
+pkill_copytools() {
+       local hosts="$1"
+       local signal="$2"
+
+       do_nodes "$hosts" "pkill --pidfile=$HSMTOOL_PID_FILE --signal=$signal hsmtool"
+}
+
 copytool_continue() {
        local agents=${1:-$(facet_active_host $SINGLEAGT)}
 
-       do_nodesv $agents "libtool execute pkill -CONT -x $HSMTOOL" || return 0
+       pkill_copytools "$agents" CONT || return 0
        echo "Copytool is continued on $agents"
 }
 
@@ -10111,7 +9908,7 @@ kill_copytools() {
        local hosts=${1:-$(facet_active_host $SINGLEAGT)}
 
        echo "Killing existing copytools on $hosts"
-       do_nodesv $hosts "libtool execute killall -q $HSMTOOL" || true
+       pkill_copytools "$hosts" TERM || return 0
        copytool_continue "$hosts"
 }
 
@@ -10147,28 +9944,29 @@ copytool_logfile()
 
 __lhsmtool_rebind()
 {
-       do_facet $facet $HSMTOOL -p "$hsm_root" --rebind "$@" "$mountpoint"
+       do_facet $facet $HSMTOOL "${hsmtool_options[@]}" --rebind "$@" "$mountpoint"
 }
 
 __lhsmtool_import()
 {
        mkdir -p "$(dirname "$2")" ||
                error "cannot create directory '$(dirname "$2")'"
-       do_facet $facet $HSMTOOL -p "$hsm_root" --import "$@" "$mountpoint"
+       do_facet $facet $HSMTOOL "${hsmtool_options[@]}" --import "$@" "$mountpoint"
 }
 
 __lhsmtool_setup()
 {
-       local cmd="$HSMTOOL $HSMTOOL_VERBOSE --daemon --hsm-root \"$hsm_root\""
+       local host="$(facet_host "$facet")"
+       local cmd="$HSMTOOL ${hsmtool_options[@]} --daemon --pid-file=$HSMTOOL_PID_FILE"
        [ -n "$bandwidth" ] && cmd+=" --bandwidth $bandwidth"
        [ -n "$archive_id" ] && cmd+=" --archive $archive_id"
-       [ ${#misc_options[@]} -gt 0 ] &&
-               cmd+=" $(IFS=" " echo "$@")"
-       cmd+=" \"$mountpoint\""
+#      [ ${#misc_options[@]} -gt 0 ] &&
+#              cmd+=" $(IFS=" " echo "$@")"
+       cmd+=" $@ \"$mountpoint\""
 
-       echo "Starting copytool $facet on $(facet_host $facet)"
-       stack_trap "do_facet $facet libtool execute pkill -x '$HSMTOOL' || true" EXIT
-       do_facet $facet "$cmd < /dev/null > \"$(copytool_logfile $facet)\" 2>&1"
+       echo "Starting copytool '$facet' on '$host' with cmdline '$cmd'"
+       stack_trap "pkill_copytools $host TERM || true" EXIT
+       do_node "$host" "$cmd < /dev/null > \"$(copytool_logfile $facet)\" 2>&1"
 }
 
 hsm_root() {
@@ -10201,7 +9999,17 @@ copytool()
 
        # Parse arguments
        local fail_on_error=true
-       local -a misc_options
+       local -a hsmtool_options=("--hsm-root=$hsm_root")
+       local -a action_options=()
+
+       if [[ -n "$HSMTOOL_ARCHIVE_FORMAT" ]]; then
+               hsmtool_options+=("--archive-format=$HSMTOOL_ARCHIVE_FORMAT")
+       fi
+
+       if [[ -n "$HSMTOOL_VERBOSE" ]]; then
+               hsmtool_options+=("$HSMTOOL_VERBOSE")
+       fi
+
        while [ $# -gt 0 ]; do
                case "$1" in
                -f|--facet)
@@ -10229,7 +10037,7 @@ copytool()
                        ;;
                *)
                        # Uncommon(/copytool dependent) option
-                       misc_options+=("$1")
+                       action_options+=("$1")
                        ;;
                esac
                shift
@@ -10245,7 +10053,7 @@ copytool()
                ;;
        esac
 
-       __${copytool}_${action} "${misc_options[@]}"
+       __${copytool}_${action} "${action_options[@]}"
        if [ $? -ne 0 ]; then
                local error_msg
 
@@ -10255,8 +10063,8 @@ copytool()
                        error_msg="Failed to start copytool $facet on '$host'"
                        ;;
                import)
-                       local src="${misc_options[0]}"
-                       local dest="${misc_options[1]}"
+                       local src="${action_options[0]}"
+                       local dest="${action_options[1]}"
                        error_msg="Failed to import '$src' to '$dest'"
                        ;;
                rebind)
@@ -10503,12 +10311,12 @@ function createmany() {
                local saved_debug=$($LCTL get_param -n debug)
                local list=$(comma_list $(all_nodes))
 
-               do_nodes $list $LCTL set_param debug=0
+               do_nodes $list $LCTL set_param -n debug=0
        }
        $LUSTRE/tests/createmany $*
        local rc=$?
        (( count > 100 )) &&
-               do_nodes $list "$LCTL set_param debug=\\\"$saved_debug\\\""
+               do_nodes $list "$LCTL set_param -n debug=\\\"$saved_debug\\\""
        return $rc
 }
 
@@ -10519,11 +10327,72 @@ function unlinkmany() {
                local saved_debug=$($LCTL get_param -n debug)
                local list=$(comma_list $(all_nodes))
 
-               do_nodes $list $LCTL set_param debug=0
+               do_nodes $list $LCTL set_param -n debug=0
        }
        $LUSTRE/tests/unlinkmany $*
        local rc=$?
        (( count > 100 )) &&
-               do_nodes $list "$LCTL set_param debug=\\\"$saved_debug\\\""
+               do_nodes $list "$LCTL set_param -n debug=\\\"$saved_debug\\\""
        return $rc
 }
+
+# Check if fallocate supported on OSTs, enable if unset, default mode=0
+# Optionally pass the OST fallocate mode (0=unwritten extents, 1=zero extents)
+function check_set_fallocate()
+{
+       local new_mode="$1"
+       local osts=$(comma_list $(osts_nodes))
+       local fa_mode="osd-ldiskfs.*.fallocate_zero_blocks"
+       local old_mode=$(do_facet ost1 $LCTL get_param -n $fa_mode 2>/dev/null|
+                        head -n 1)
+
+       [[ -n "$old_mode" ]] || { echo "fallocate not supported"; return 1; }
+       [[ -z "$new_mode" && "$old_mode" != "-1" ]] &&
+               { echo "keep default fallocate mode: $old_mode"; return 0; }
+       [[ "$new_mode" && "$old_mode" == "$new_mode" ]] &&
+               { echo "keep current fallocate mode: $old_mode"; return 0; }
+
+       stack_trap "do_nodes $osts $LCTL set_param $fa_mode=$old_mode"
+       do_nodes $osts $LCTL set_param $fa_mode=${new_mode:-0} ||
+               error "set $fa_mode=$new_mode"
+}
+
+# Check if fallocate supported on OSTs, enable if unset, skip if unavailable
+function check_set_fallocate_or_skip()
+{
+       [ "$ost1_FSTYPE" != ldiskfs ] && skip "non-ldiskfs backend"
+       check_set_fallocate || skip "need at least 2.13.57 for fallocate"
+}
+
+function disable_opencache()
+{
+       local state=$($LCTL get_param -n "llite.*.opencache_threshold_count" | head -1)
+
+       test -z "${saved_OPENCACHE_value}" &&
+                                       export saved_OPENCACHE_value="$state"
+
+       [[ "$state" = "off" ]] && return
+
+       $LCTL set_param -n "llite.*.opencache_threshold_count"=off
+}
+
+function set_opencache()
+{
+       local newvalue="$1"
+       local state=$($LCTL get_param -n "llite.*.opencache_threshold_count")
+
+       [[ -n "$newvalue" ]] || return
+
+       [[ -n "${saved_OPENCACHE_value}" ]] ||
+                                       export saved_OPENCACHE_value="$state"
+
+       $LCTL set_param -n "llite.*.opencache_threshold_count"=$newvalue
+}
+
+
+
+function restore_opencache()
+{
+       [[ -z "${saved_OPENCACHE_value}" ]] ||
+               $LCTL set_param -n "llite.*.opencache_threshold_count"=${saved_OPENCACHE_value}
+}