Whamcloud - gitweb
LU-3700 tests: Strengthen and clarify sanity-hsm/test_21
[fs/lustre-release.git] / lustre / tests / sanity-hsm.sh
index ea4c4c3..cd0b98a 100644 (file)
@@ -11,12 +11,11 @@ SRCDIR=$(dirname $0)
 export PATH=$PWD/$SRCDIR:$SRCDIR:$PWD/$SRCDIR/utils:$PATH:/sbin:/usr/sbin
 
 ONLY=${ONLY:-"$*"}
-# bug number for skipped test:
+# bug number for skipped test:    3815     3939
+ALWAYS_EXCEPT="$SANITY_HSM_EXCEPT 34 35 36 40"
+# bug number for skipped test:4178         4176
+ALWAYS_EXCEPT="$ALWAYS_EXCEPT 200 221 223b 31a"
 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
-# skip test cases failed before landing - Jinshan
-
-ALWAYS_EXCEPT="$SANITY_HSM_EXCEPT 31a 34 35 36"
-ALWAYS_EXCEPT="$ALWAYS_EXCEPT 200 201 221 223a 223b 225"
 
 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
 
@@ -31,9 +30,9 @@ MCREATE=${MCREATE:-mcreate}
 MOUNT_2=${MOUNT_2:-"yes"}
 FAIL_ON_ERROR=false
 
-if [[ $MDSCOUNT -ge 2 ]]; then
-       skip_env "Only run with single MDT for now" && exit
-fi
+# script only handles up to 10 MDTs (because of MDT_PREFIX)
+[ $MDSCOUNT -gt 9 ] &&
+       error "script cannot handle more than 9 MDTs, please fix" && exit
 
 check_and_setup_lustre
 
@@ -95,8 +94,9 @@ init_agt_vars() {
        HSM_ARCHIVE=$(copytool_device $SINGLEAGT)
        HSM_ARCHIVE_NUMBER=2
 
-       MDT_PARAM="mdt.$FSNAME-MDT0000"
-       HSM_PARAM="$MDT_PARAM.hsm"
+       # The test only support up to 10 MDTs
+       MDT_PREFIX="mdt.$FSNAME-MDT000"
+       HSM_PARAM="${MDT_PREFIX}0.hsm"
 
        # archive is purged at copytool setup
        HSM_ARCHIVE_PURGE=true
@@ -117,6 +117,17 @@ cleanup() {
        cdt_set_sanity_policy
 }
 
+get_mdt_devices() {
+       local mdtno
+       # get MDT device for each mdc
+       for mdtno in $(seq 1 $MDSCOUNT); do
+               local idx=$(($mdtno - 1))
+               MDT[$idx]=$($LCTL get_param -n \
+                       mdc.$FSNAME-MDT000${idx}-mdc-*.mds_server_uuid |
+                       awk '{gsub(/_UUID/,""); print $1}' | head -1)
+       done
+}
+
 search_and_kill_copytool() {
        local agents=${1:-$(facet_active_host $SINGLEAGT)}
 
@@ -164,10 +175,34 @@ copytool_setup() {
 copytool_cleanup() {
        trap - EXIT
        local agents=${1:-$(facet_active_host $SINGLEAGT)}
+       local mdtno
+       local idx
+       local oldstate
+       local mdt_hsmctrl
 
        do_nodesv $agents "pkill -INT -x $HSMTOOL_BASE" || return 0
        sleep 1
        echo "Copytool is stopped on $agents"
+
+       # clean all CDTs orphans requests from previous tests
+       # that would otherwise need to timeout to clear.
+       for mdtno in $(seq 1 $MDSCOUNT); do
+               idx=$(($mdtno - 1))
+               mdt_hsmctrl="mdt.$FSNAME-MDT000${idx}.hsm_control"
+               oldstate=$(do_facet mds${mdtno} "$LCTL get_param -n " \
+                                  "$mdt_hsmctrl")
+               # skip already stop[ed,ing] CDTs
+               echo $oldstate | grep stop && continue
+
+               do_facet mds${mdtno} "$LCTL set_param $mdt_hsmctrl=shutdown"
+               wait_result mds${mdtno} "$LCTL get_param -n $mdt_hsmctrl" \
+                       "stopped" 20 ||
+                       error "mds${mdtno} cdt state is not stopped"
+               do_facet mds${mdtno} "$LCTL set_param $mdt_hsmctrl=$oldstate"
+               wait_result mds${mdtno} "$LCTL get_param -n $mdt_hsmctrl" \
+                       "$oldstate" 20 ||
+                       error "mds${mdtno} cdt state is not $oldstate"
+       done
 }
 
 copytool_suspend() {
@@ -179,7 +214,7 @@ copytool_suspend() {
 
 copytool_remove_backend() {
        local fid=$1
-       local be=$(find $HSM_ARCHIVE -name $fid)
+       local be=$(do_facet $SINGLEAGT find $HSM_ARCHIVE -name $fid)
        echo "Remove from backend: $fid = $be"
        do_facet $SINGLEAGT rm -f $be
 }
@@ -204,20 +239,66 @@ copy2archive() {
        do_facet $SINGLEAGT cp -p $1 $file || error "cannot copy $1 to $file"
 }
 
+mdts_set_param() {
+       local arg=$1
+       local key=$2
+       local value=$3
+       local mdtno
+       local rc=0
+       if [[ "$value" != "" ]]; then
+               value="=$value"
+       fi
+       for mdtno in $(seq 1 $MDSCOUNT); do
+               local idx=$(($mdtno - 1))
+               local facet=mds${mdtno}
+               # if $arg include -P option, run 1 set_param per MDT on the MGS
+               # else, run set_param on each MDT
+               [[ $arg = *"-P"* ]] && facet=mgs
+               do_facet $facet $LCTL set_param $arg mdt.${MDT[$idx]}.$key$value
+               [[ $? != 0 ]] && rc=1
+       done
+       return $rc
+}
+
+mdts_check_param() {
+       local key="$1"
+       local target="$2"
+       local timeout="$3"
+       local mdtno
+       for mdtno in $(seq 1 $MDSCOUNT); do
+               local idx=$(($mdtno - 1))
+               wait_result mds${mdtno} \
+                       "$LCTL get_param -n $MDT_PREFIX${idx}.$key" "$target" \
+                       $timeout ||
+                       error "$key state is not '$target' on mds${mdtno}"
+       done
+}
+
 changelog_setup() {
-       CL_USER=$(do_facet $SINGLEMDS $LCTL --device $MDT0\
-                 changelog_register -n)
-       do_facet $SINGLEMDS lctl set_param mdd.$MDT0.changelog_mask="+hsm"
-       $LFS changelog_clear $MDT0 $CL_USER 0
+       CL_USERS=()
+       local mdtno
+       for mdtno in $(seq 1 $MDSCOUNT); do
+               local idx=$(($mdtno - 1))
+               local cl_user=$(do_facet mds${mdtno} $LCTL \
+                            --device ${MDT[$idx]} \
+                            changelog_register -n)
+               CL_USERS+=($cl_user)
+               do_facet mds${mdtno} lctl set_param \
+                       mdd.${MDT[$idx]}.changelog_mask="+hsm"
+               $LFS changelog_clear ${MDT[$idx]} $cl_user 0
+       done
 }
 
 changelog_cleanup() {
-#      $LFS changelog $MDT0
-       [[ -n "$CL_USER" ]] || return 0
-
-       $LFS changelog_clear $MDT0 $CL_USER 0
-       do_facet $SINGLEMDS lctl --device $MDT0 changelog_deregister $CL_USER
-       CL_USER=
+       local mdtno
+       for mdtno in $(seq 1 $MDSCOUNT); do
+               local idx=$(($mdtno - 1))
+               [[ -z  ${CL_USERS[$idx]} ]] && continue
+               $LFS changelog_clear ${MDT[$idx]} ${CL_USERS[$idx]} 0
+               do_facet mds${mdtno} lctl --device ${MDT[$idx]} \
+                       changelog_deregister ${CL_USERS[$idx]}
+       done
+       CL_USERS=()
 }
 
 changelog_get_flags() {
@@ -238,64 +319,57 @@ set_hsm_param() {
        local param=$1
        local value=$2
        local opt=$3
-       if [[ "$value" != "" ]]; then
-               value="=$value"
-       fi
-       do_facet $SINGLEMDS $LCTL set_param $opt -n $HSM_PARAM.$param$value
+       mdts_set_param "$opt -n" "hsm.$param" "$value"
        return $?
 }
 
 set_test_state() {
        local cmd=$1
        local target=$2
-       do_facet $SINGLEMDS $LCTL set_param $MDT_PARAM.hsm_control=$cmd
-       wait_result $SINGLEMDS "$LCTL get_param -n $MDT_PARAM.hsm_control"\
-               $target 10 || error "cdt state is not $target"
+       mdts_set_param "" hsm_control "$cmd"
+       mdts_check_param hsm_control "$target" 10
 }
 
 cdt_set_sanity_policy() {
        if [[ "$CDT_POLICY_HAD_CHANGED" ]]
        then
                # clear all
-               do_facet $SINGLEMDS $LCTL set_param $HSM_PARAM.policy=+NRA
-               do_facet $SINGLEMDS $LCTL set_param $HSM_PARAM.policy=-NBR
+               mdts_set_param "" hsm.policy "+NRA"
+               mdts_set_param "" hsm.policy "-NBR"
                CDT_POLICY_HAD_CHANGED=
        fi
 }
 
 cdt_set_no_retry() {
-       do_facet $SINGLEMDS $LCTL set_param $HSM_PARAM.policy=+NRA
+       mdts_set_param "" hsm.policy "+NRA"
        CDT_POLICY_HAD_CHANGED=true
 }
 
 cdt_clear_no_retry() {
-       do_facet $SINGLEMDS $LCTL set_param $HSM_PARAM.policy=-NRA
+       mdts_set_param "" hsm.policy "-NRA"
        CDT_POLICY_HAD_CHANGED=true
 }
 
 cdt_set_non_blocking_restore() {
-       do_facet $SINGLEMDS $LCTL set_param $HSM_PARAM.policy=+NBR
+       mdts_set_param "" hsm.policy "+NBR"
        CDT_POLICY_HAD_CHANGED=true
 }
 
 cdt_clear_non_blocking_restore() {
-       do_facet $SINGLEMDS $LCTL set_param $HSM_PARAM.policy=-NBR
+       mdts_set_param "" hsm.policy "-NBR"
        CDT_POLICY_HAD_CHANGED=true
 }
 
 cdt_clear_mount_state() {
-       do_facet $SINGLEMDS $LCTL set_param -d -P $MDT_PARAM.hsm_control
+       mdts_set_param "-P -d" hsm_control ""
 }
 
 cdt_set_mount_state() {
-       do_facet $SINGLEMDS $LCTL set_param -P $MDT_PARAM.hsm_control=$1
+       mdts_set_param "-P" hsm_control "$1"
 }
 
 cdt_check_state() {
-       local target=$1
-       wait_result $SINGLEMDS\
-               "$LCTL get_param -n $MDT_PARAM.hsm_control" "$target" 20 ||
-                       error "cdt state is not $target"
+       mdts_check_param hsm_control "$1" 20
 }
 
 cdt_disable() {
@@ -401,7 +475,8 @@ make_small() {
 }
 
 cleanup_large_files() {
-       local ratio=$(df $MOUNT |awk '{print $5}' |sed 's/%//g' |grep -v Use)
+       local ratio=$(df -P $MOUNT | tail -1 | awk '{print $5}' |
+                     sed 's/%//g')
        [ $ratio -gt 50 ] && find $MOUNT -size +10M -exec rm -f {} \;
 }
 
@@ -466,7 +541,7 @@ wait_request_state() {
        local request=$2
        local state=$3
 
-       local cmd="$LCTL get_param -n $HSM_PARAM.agent_actions"
+       local cmd="$LCTL get_param -n $HSM_PARAM.actions"
        cmd+=" | awk '/'$fid'.*action='$request'/ {print \\\$13}' | cut -f2 -d="
 
        wait_result $SINGLEMDS "$cmd" $state 100 ||
@@ -477,7 +552,7 @@ get_request_state() {
        local fid=$1
        local request=$2
 
-       do_facet $SINGLEMDS "$LCTL get_param -n $HSM_PARAM.agent_actions |"\
+       do_facet $SINGLEMDS "$LCTL get_param -n $HSM_PARAM.actions |"\
                "awk '/'$fid'.*action='$request'/ {print \\\$13}' | cut -f2 -d="
 }
 
@@ -485,14 +560,14 @@ get_request_count() {
        local fid=$1
        local request=$2
 
-       do_facet $SINGLEMDS "$LCTL get_param -n $HSM_PARAM.agent_actions |"\
+       do_facet $SINGLEMDS "$LCTL get_param -n $HSM_PARAM.actions |"\
                "awk -vn=0 '/'$fid'.*action='$request'/ {n++}; END {print n}'"
 }
 
 wait_all_done() {
        local timeout=$1
 
-       local cmd="$LCTL get_param -n $HSM_PARAM.agent_actions"
+       local cmd="$LCTL get_param -n $HSM_PARAM.actions"
        cmd+=" | egrep 'WAITING|STARTED'"
 
        wait_result $SINGLEMDS "$cmd" "" $timeout ||
@@ -504,8 +579,8 @@ wait_for_grace_delay() {
        sleep $val
 }
 
-MDT0=$($LCTL get_param -n mdc.*.mds_server_uuid |
-       awk '{gsub(/_UUID/,""); print $1}' | head -1)
+# populate MDT device array
+get_mdt_devices
 
 # initiate variables
 init_agt_vars
@@ -812,7 +887,7 @@ test_11() {
        check_hsm_flags $f "0x0000000d"
 
        local LSZ=$(stat -c "%s" $f)
-       local ASZ=$(stat -c "%s" $HSM_ARCHIVE/$tdir/$tfile)
+       local ASZ=$(do_facet $SINGLEAGT stat -c "%s" $HSM_ARCHIVE/$tdir/$tfile)
 
        echo "Verifying imported size $LSZ=$ASZ"
        [[ $LSZ -eq $ASZ ]] || error "Incorrect size $LSZ != $ASZ"
@@ -1082,8 +1157,8 @@ test_13() {
                        CURR_FILE="$CURR_DIR/$tfile.$f"
                        # write file-specific data
                        do_facet $SINGLEAGT \
-                               echo "d=$d, f=$f, dir=$CURR_DIR, "\
-                                    "file=$CURR_FILE" > $CURR_FILE
+                               "echo d=$d, f=$f, dir=$CURR_DIR, "\
+                                       "file=$CURR_FILE > $CURR_FILE"
                done
        done
        # import to Lustre
@@ -1260,19 +1335,32 @@ test_21() {
        local fid=$(make_small $f)
        check_hsm_flags $f "0x00000000"
 
+       local orig_size=$(stat -c "%s" $f)
+       local orig_blocks=$(stat -c "%b" $f)
+
+       start_full_debug_logging
+
        $LFS hsm_archive $f || error "could not archive file"
        wait_request_state $fid ARCHIVE SUCCEED
 
-       [ $(stat -c "%b" $f) -ne "1" ] || error "wrong block number"
-       local sz=$(stat -c "%s" $f)
-       [ $sz -ne "0" ] || error "file size should not be zero"
+       local blocks=$(stat -c "%b" $f)
+       [ $blocks -eq $orig_blocks ] ||
+               error "$f: wrong block number after archive: " \
+                     "$blocks != $orig_blocks"
+       local size=$(stat -c "%s" $f)
+       [ $size -eq $orig_size ] ||
+               error "$f: wrong size after archive: $size != $orig_size"
 
        # Release and check states
        $LFS hsm_release $f || error "could not release file"
        check_hsm_flags $f "0x0000000d"
 
-       [ $(stat -c "%b" $f) -eq "1" ] || error "wrong block number"
-       [ $(stat -c "%s" $f) -eq $sz ] || error "wrong file size"
+       blocks=$(stat -c "%b" $f)
+       [ $blocks -gt 5 ] &&
+               error "$f: too many blocks after release: $blocks > 5"
+       size=$(stat -c "%s" $f)
+       [ $size -ne $orig_size ] &&
+               error "$f: wrong size after release: $size != $orig_size"
 
        # Check we can release an file without stripe info
        f=$f.nolov
@@ -1290,6 +1378,8 @@ test_21() {
        $LFS hsm_release $f || fail "second release should succeed"
        check_hsm_flags $f "0x0000000d"
 
+       stop_full_debug_logging
+
        copytool_cleanup
 }
 run_test 21 "Simple release tests"
@@ -1485,8 +1575,8 @@ test_24b() {
        $LFS hsm_archive $file
        wait_request_state $fid ARCHIVE SUCCEED
 
-       $LFS hsm_release $file ||
-               check_hsm_flags $file "0x0000000d"
+       $LFS hsm_release $file
+       check_hsm_flags $file "0x0000000d"
 
        $LFS hsm_restore $file
        wait_request_state $fid RESTORE SUCCEED
@@ -1495,8 +1585,8 @@ test_24b() {
        $RUNAS $LFS hsm_state $file ||
                error "user '$RUNAS_ID' cannot get HSM state of '$file'"
 
-       $LFS hsm_release $file ||
-               check_hsm_flags $file "0x0000000d"
+       $LFS hsm_release $file
+       check_hsm_flags $file "0x0000000d"
 
        # Check that ordinary user can accessed released file.
        sum1=$($RUNAS md5sum $file) ||
@@ -1509,6 +1599,134 @@ test_24b() {
 }
 run_test 24b "root can archive, release, and restore user files"
 
+cleanup_test_24c() {
+       trap 0
+       set_hsm_param user_request_mask RESTORE
+       set_hsm_param group_request_mask RESTORE
+       set_hsm_param other_request_mask RESTORE
+}
+
+test_24c() {
+       local file=$DIR/$tdir/$tfile
+       local action=archive
+       local user_save
+       local group_save
+       local other_save
+
+       # test needs a running copytool
+       copytool_setup
+
+       mkdir -p $DIR/$tdir
+
+       # Save the default masks and check that cleanup_24c will
+       # restore the request masks correctly.
+       user_save=$(get_hsm_param user_request_mask)
+       group_save=$(get_hsm_param group_request_mask)
+       other_save=$(get_hsm_param other_request_mask)
+
+       [ "$user_save" == RESTORE ] ||
+               error "user_request_mask is '$user_save' expected 'RESTORE'"
+       [ "$group_save" == RESTORE ] ||
+               error "group_request_mask is '$group_save' expected 'RESTORE'"
+       [ "$other_save" == RESTORE ] ||
+               error "other_request_mask is '$other_save' expected 'RESTORE'"
+
+       trap cleanup_test_24c EXIT
+
+       # User.
+       rm -f $file
+       make_small $file
+       chown $RUNAS_ID:nobody $file ||
+               error "cannot chown '$file' to '$RUNAS_ID:nobody'"
+
+       set_hsm_param user_request_mask ""
+       $RUNAS $LFS hsm_$action $file &&
+               error "$action by user should fail"
+
+       set_hsm_param user_request_mask $action
+       $RUNAS $LFS hsm_$action $file ||
+               error "$action by user should succeed"
+
+       # Group.
+       rm -f $file
+       make_small $file
+       chown nobody:$RUNAS_GID $file ||
+               error "cannot chown '$file' to 'nobody:$RUNAS_GID'"
+
+       set_hsm_param group_request_mask ""
+       $RUNAS $LFS hsm_$action $file &&
+               error "$action by group should fail"
+
+       set_hsm_param group_request_mask $action
+       $RUNAS $LFS hsm_$action $file ||
+               error "$action by group should succeed"
+
+       # Other.
+       rm -f $file
+       make_small $file
+       chown nobody:nobody $file ||
+               error "cannot chown '$file' to 'nobody:nobody'"
+
+       set_hsm_param other_request_mask ""
+       $RUNAS $LFS hsm_$action $file &&
+               error "$action by other should fail"
+
+       set_hsm_param other_request_mask $action
+       $RUNAS $LFS hsm_$action $file ||
+               error "$action by other should succeed"
+
+       copytool_cleanup
+       cleanup_test_24c
+}
+run_test 24c "check that user,group,other request masks work"
+
+cleanup_test_24d() {
+       trap 0
+       mount -o remount,rw $MOUNT2
+}
+
+test_24d() {
+       local file1=$DIR/$tdir/$tfile
+       local file2=$DIR2/$tdir/$tfile
+       local fid1
+       local fid2
+
+       copytool_setup
+
+       mkdir -p $DIR/$tdir
+       rm -f $file1
+       fid1=$(make_small $file1)
+
+       trap cleanup_test_24d EXIT
+
+       mount -o remount,ro $MOUNT2
+
+       fid2=$(path2fid $file2)
+       [ "$fid1" == "$fid2" ] ||
+               error "FID mismatch '$fid1' != '$fid2'"
+
+       $LFS hsm_archive $file2 &&
+               error "archive should fail on read-only mount"
+       check_hsm_flags $file1 "0x00000000"
+
+       $LFS hsm_archive $file1
+       wait_request_state $fid1 ARCHIVE SUCCEED
+
+       $LFS hsm_release $file1
+       $LFS hsm_restore $file2
+       wait_request_state $fid1 RESTORE SUCCEED
+
+       $LFS hsm_release $file1 || error "cannot release '$file1'"
+       dd if=$file2 of=/dev/null bs=1M || "cannot read '$file2'"
+
+       $LFS hsm_release $file2 &&
+               error "release should fail on read-only mount"
+
+       copytool_cleanup
+       cleanup_test_24d
+}
+run_test 24d "check that read-only mounts are respected"
+
 test_25a() {
        # test needs a running copytool
        copytool_setup
@@ -1699,6 +1917,41 @@ test_30b() {
 }
 run_test 30b "Restore at exec (release case)"
 
+test_30c() {
+       needclients 2 || return 0
+
+       # test needs a running copytool
+       copytool_setup
+
+       mkdir -p $DIR/$tdir
+       local f=$DIR/$tdir/SLEEP
+       local fid=$(copy_file /bin/sleep $f)
+       chmod 755 $f
+       $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+       wait_request_state $fid ARCHIVE SUCCEED
+       $LFS hsm_release $f
+       check_hsm_flags $f "0x0000000d"
+       # set no retry action mode
+       cdt_set_no_retry
+       do_node $CLIENT2 "$f 10" &
+       local pid=$!
+       sleep 3
+       echo 'Hi!' > $f
+       [[ $? == 0 ]] && error "Update during exec of released file must fail"
+       wait $pid
+       [[ $? == 0 ]] || error "Execution failed during run"
+       cmp /bin/sleep $f
+       [[ $? == 0 ]] || error "Binary overwritten during exec"
+
+       # cleanup
+       # remove no try action mode
+       cdt_clear_no_retry
+       check_hsm_flags $f "0x00000009"
+
+       copytool_cleanup
+}
+run_test 30c "Update during exec of released file must fail"
+
 restore_and_check_size() {
        local f=$1
        local fid=$2
@@ -1724,11 +1977,11 @@ restore_and_check_size() {
                cpt=$((cpt + 1))
        done
        if [[ $cpt -lt 10 ]]; then
-               echo " restore is too long"
-       else
                echo " "done
+       else
+               echo " restore is too long"
+               wait_request_state $fid RESTORE SUCCEED
        fi
-       wait_request_state $fid RESTORE SUCCEED
        return $err
 }
 
@@ -2254,7 +2507,7 @@ double_verify_reset_hsm_param() {
 test_100() {
        double_verify_reset_hsm_param loop_period
        double_verify_reset_hsm_param grace_delay
-       double_verify_reset_hsm_param request_timeout
+       double_verify_reset_hsm_param active_request_timeout
        double_verify_reset_hsm_param max_requests
        double_verify_reset_hsm_param default_archive_id
 }
@@ -2284,7 +2537,7 @@ test_103() {
 
        echo "Current requests"
        local res=$(do_facet $SINGLEMDS "$LCTL get_param -n\
-                       $HSM_PARAM.agent_actions |\
+                       $HSM_PARAM.actions |\
                        grep -v CANCELED | grep -v SUCCEED | grep -v FAILED")
 
        [[ -z "$res" ]] || error "Some request have not been canceled"
@@ -2306,7 +2559,7 @@ test_104() {
        cdt_disable
        $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER --data $DATA $f
        local data1=$(do_facet $SINGLEMDS "$LCTL get_param -n\
-                       $HSM_PARAM.agent_actions |\
+                       $HSM_PARAM.actions |\
                        grep $fid | cut -f16 -d=")
        cdt_enable
 
@@ -2327,12 +2580,12 @@ test_105() {
                $LFS hsm_archive $DIR/$tdir/$i
        done
        local reqcnt1=$(do_facet $SINGLEMDS "$LCTL get_param -n\
-                       $HSM_PARAM.agent_actions |\
+                       $HSM_PARAM.actions |\
                        grep WAITING | wc -l")
        cdt_restart
        cdt_disable
        local reqcnt2=$(do_facet $SINGLEMDS "$LCTL get_param -n\
-                       $HSM_PARAM.agent_actions |\
+                       $HSM_PARAM.actions |\
                        grep WAITING | wc -l")
        cdt_enable
        cdt_purge
@@ -2639,7 +2892,7 @@ test_220() {
        $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
        wait_request_state $fid ARCHIVE SUCCEED
 
-       local flags=$(changelog_get_flags $MDT0 HSM $fid | tail -1)
+       local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
        changelog_cleanup
 
        local target=0x0
@@ -2666,7 +2919,7 @@ test_221() {
        wait_request_state $fid ARCHIVE CANCELED
        wait_request_state $fid CANCEL SUCCEED
 
-       local flags=$(changelog_get_flags $MDT0 HSM $fid | tail -1)
+       local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
 
        local target=0x7d
        [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
@@ -2691,7 +2944,7 @@ test_222a() {
        $LFS hsm_restore $f
        wait_request_state $fid RESTORE SUCCEED
 
-       local flags=$(changelog_get_flags $MDT0 HSM $fid | tail -1)
+       local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
 
        local target=0x80
        [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
@@ -2717,7 +2970,7 @@ test_222b() {
 
        wait_request_state $fid RESTORE SUCCEED
 
-       local flags=$(changelog_get_flags $MDT0 HSM $fid | tail -1)
+       local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
 
        local target=0x80
        [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
@@ -2746,7 +2999,7 @@ test_223a() {
        wait_request_state $fid RESTORE CANCELED
        wait_request_state $fid CANCEL SUCCEED
 
-       local flags=$(changelog_get_flags $MDT0 HSM $fid | tail -1)
+       local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
 
        local target=0xfd
        [[ $flags == $target ]] ||
@@ -2775,7 +3028,7 @@ test_223b() {
        wait_request_state $fid RESTORE CANCELED
        wait_request_state $fid CANCEL SUCCEED
 
-       local flags=$(changelog_get_flags $MDT0 HSM $fid | tail -1)
+       local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
 
        local target=0xfd
        [[ $flags == $target ]] ||
@@ -2801,7 +3054,7 @@ test_224() {
        $LFS hsm_remove $f
        wait_request_state $fid REMOVE SUCCEED
 
-       local flags=$(changelog_get_flags $MDT0 HSM $fid | tail -1)
+       local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -n 1)
 
        local target=0x200
        [[ $flags == $target ]] ||
@@ -2837,9 +3090,9 @@ test_225() {
        wait_request_state $fid REMOVE CANCELED
        wait_request_state $fid CANCEL SUCCEED
 
-       flags=$(changelog_get_flags $MDT0 RENME $fid2)
-       local flags=$($LFS changelog $MDT0 | grep HSM | grep $fid | tail -1 |
-               awk '{print $5}')
+       flags=$(changelog_get_flags ${MDT[0]} RENME $fid2)
+       local flags=$($LFS changelog ${MDT[0]} | grep HSM | grep $fid |
+               tail -n 1 | awk '{print $5}')
 
        local target=0x27d
        [[ $flags == $target ]] ||
@@ -2871,7 +3124,7 @@ test_226() {
 
        rm $f1 || error "rm $f1 failed"
 
-       local flags=$(changelog_get_flags $MDT0 UNLNK $fid1)
+       local flags=$(changelog_get_flags ${MDT[0]} UNLNK $fid1)
 
        local target=0x3
        [[ $flags == $target ]] ||
@@ -2879,7 +3132,7 @@ test_226() {
 
        mv $f3 $f2 || error "mv $f3 $f2 failed"
 
-       flags=$(changelog_get_flags $MDT0 RENME $fid2)
+       flags=$(changelog_get_flags ${MDT[0]} RENME $fid2)
 
        target=0x3
        [[ $flags == $target ]] ||
@@ -2899,7 +3152,7 @@ check_flags_changes() {
        local target=0x280
        $LFS hsm_set --$hsm_flag $f ||
                error "Cannot set $hsm_flag on $f"
-       local flags=($(changelog_get_flags $MDT0 HSM $fid))
+       local flags=($(changelog_get_flags ${MDT[0]} HSM $fid))
        local seen=${#flags[*]}
        cnt=$((fst + cnt))
        [[ $seen == $cnt ]] ||
@@ -2910,7 +3163,7 @@ check_flags_changes() {
 
        $LFS hsm_clear --$hsm_flag $f ||
                error "Cannot clear $hsm_flag on $f"
-       flags=($(changelog_get_flags $MDT0 HSM $fid))
+       flags=($(changelog_get_flags ${MDT[0]} HSM $fid))
        seen=${#flags[*]}
        cnt=$(($cnt + 1))
        [[ $cnt == $seen ]] ||
@@ -2946,6 +3199,41 @@ test_227() {
 }
 run_test 227 "changelog when explicit setting of HSM flags"
 
+test_228() {
+       # test needs a running copytool
+       copytool_setup
+
+       dd if=/dev/urandom of=$DIR/$tfile bs=1M count=1 conv=sync ||
+               error "creating $DIR/$tfile"
+       $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $DIR/$tfile
+       wait_request_state $(path2fid $DIR/$tfile) ARCHIVE SUCCEED
+
+       $LFS hsm_release $DIR/$tfile
+       check_hsm_flags $DIR/$tfile "0x0000000d"
+
+       filefrag $DIR/$tfile | grep " 1 extent found" ||
+               error "filefrag on released file must return only one extent"
+
+       # only newer versions of cp detect sparse files by stat/FIEMAP
+       # (LU-2580)
+       cp --sparse=auto $DIR/$tfile $DIR/$tfile.2 ||
+               error "copying $DIR/$tfile"
+       cmp $DIR/$tfile $DIR/$tfile.2 || error "comparing copied $DIR/$tfile"
+
+       $LFS hsm_release $DIR/$tfile
+       check_hsm_flags $DIR/$tfile "0x0000000d"
+
+       mkdir $DIR/$tdir
+
+       tar cf - --sparse $DIR/$tfile | tar xvf - -C $DIR/$tdir ||
+               error "tar failed"
+       cmp $DIR/$tfile $DIR/$tdir/$DIR/$tfile ||
+               error "comparing untarred $DIR/$tfile"
+
+       copytool_cleanup
+}
+run_test 228 "On released file, return extend to FIEMAP. For [cp,tar] --sparse"
+
 test_250() {
        # test needs a running copytool
        copytool_setup
@@ -2970,12 +3258,12 @@ test_250() {
        while [[ $cnt != 0 || $wt != 0 ]]; do
                sleep 1
                cnt=$(do_facet $SINGLEMDS "$LCTL get_param -n\
-                       $HSM_PARAM.agent_actions |\
+                       $HSM_PARAM.actions |\
                        grep STARTED | grep -v CANCEL | wc -l")
                [[ $cnt -le $maxrequest ]] ||
                        error "$cnt > $maxrequest too many started requests"
                wt=$(do_facet $SINGLEMDS "$LCTL get_param\
-                       $HSM_PARAM.agent_actions |\
+                       $HSM_PARAM.actions |\
                        grep WAITING | wc -l")
                echo "max=$maxrequest started=$cnt waiting=$wt"
        done
@@ -2994,8 +3282,8 @@ test_251() {
 
        cdt_disable
        # to have a short test
-       local old_to=$(get_hsm_param request_timeout)
-       set_hsm_param request_timeout 4
+       local old_to=$(get_hsm_param active_request_timeout)
+       set_hsm_param active_request_timeout 4
        # to be sure the cdt will wake up frequently so
        # it will be able to cancel the "old" request
        local old_loop=$(get_hsm_param loop_period)
@@ -3007,7 +3295,7 @@ test_251() {
        sleep 5
        wait_request_state $fid ARCHIVE CANCELED
 
-       set_hsm_param request_timeout $old_to
+       set_hsm_param active_request_timeout $old_to
        set_hsm_param loop_period $old_loop
 
        copytool_cleanup