+ # Release and check states
+ $LFS hsm_release $f || error "could not release file"
+ check_hsm_flags $f "0x0000000d"
+
+ local MTIME=$(stat -c "%Y" $f)
+ local ATIME=$(stat -c "%X" $f)
+ [ $MTIME -eq "978261179" ] || fail "bad mtime: $MTIME"
+ [ $ATIME -eq "978261179" ] || fail "bad atime: $ATIME"
+
+ copytool_cleanup
+}
+run_test 23 "Release does not change a/mtime (utime)"
+
+test_24a() {
+ local file=$DIR/$tdir/$tfile
+ local fid
+ local atime0
+ local atime1
+ local mtime0
+ local mtime1
+ local ctime0
+ local ctime1
+
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ rm -f $file
+ fid=$(make_small $file)
+
+ # Create a file and check its states
+ check_hsm_flags $file "0x00000000"
+
+ # Ensure atime is less than mtime and ctime.
+ sleep 1
+ echo >> $file
+
+ atime0=$(stat -c "%X" $file)
+ mtime0=$(stat -c "%Y" $file)
+ ctime0=$(stat -c "%Z" $file)
+
+ [ $atime0 -lt $mtime0 ] ||
+ error "atime $atime0 is not less than mtime $mtime0"
+
+ [ $atime0 -lt $ctime0 ] ||
+ error "atime $atime0 is not less than ctime $ctime0"
+
+ # Archive should not change any timestamps.
+ $LFS hsm_archive $file || error "cannot archive '$file'"
+ wait_request_state $fid ARCHIVE SUCCEED
+
+ atime1=$(stat -c "%X" $file)
+ mtime1=$(stat -c "%Y" $file)
+ ctime1=$(stat -c "%Z" $file)
+
+ [ $atime0 -eq $atime1 ] ||
+ error "archive changed atime from $atime0 to $atime1"
+
+ [ $mtime0 -eq $mtime1 ] ||
+ error "archive changed mtime from $mtime0 to $mtime1"
+
+ [ $ctime0 -eq $ctime1 ] ||
+ error "archive changed ctime from $ctime0 to $ctime1"
+
+ # Release should not change any timestamps.
+ $LFS hsm_release $file || error "cannot release '$file'"
+ check_hsm_flags $file "0x0000000d"
+
+ atime1=$(stat -c "%X" $file)
+ mtime1=$(stat -c "%Y" $file)
+ ctime1=$(stat -c "%Z" $file)
+
+ [ $atime0 -eq $atime1 ] ||
+ error "release changed atime from $atime0 to $atime1"
+
+ [ $mtime0 -eq $mtime1 ] ||
+ error "release changed mtime from $mtime0 to $mtime1"
+
+ [ $ctime0 -eq $ctime1 ] ||
+ error "release changed ctime from $ctime0 to $ctime1"
+
+ # Restore should not change atime or mtime and should not
+ # decrease ctime.
+ $LFS hsm_restore $file
+ wait_request_state $fid RESTORE SUCCEED
+
+ atime1=$(stat -c "%X" $file)
+ mtime1=$(stat -c "%Y" $file)
+ ctime1=$(stat -c "%Z" $file)
+
+ [ $atime0 -eq $atime1 ] ||
+ error "restore changed atime from $atime0 to $atime1"
+
+ [ $mtime0 -eq $mtime1 ] ||
+ error "restore changed mtime from $mtime0 to $mtime1"
+
+ [ $ctime0 -le $ctime1 ] ||
+ error "restore changed ctime from $ctime0 to $ctime1"
+
+ copytool_cleanup
+
+ # Once more, after unmount and mount.
+ umount_client $MOUNT || error "cannot unmount '$MOUNT'"
+ mount_client $MOUNT || error "cannot mount '$MOUNT'"
+
+ atime1=$(stat -c "%X" $file)
+ mtime1=$(stat -c "%Y" $file)
+ ctime1=$(stat -c "%Z" $file)
+
+ [ $atime0 -eq $atime1 ] ||
+ error "remount changed atime from $atime0 to $atime1"
+
+ [ $mtime0 -eq $mtime1 ] ||
+ error "remount changed mtime from $mtime0 to $mtime1"
+
+ [ $ctime0 -le $ctime1 ] ||
+ error "remount changed ctime from $ctime0 to $ctime1"
+}
+run_test 24a "Archive, release, and restore does not change a/mtime (i/o)"
+
+test_24b() {
+ local file=$DIR/$tdir/$tfile
+ local fid
+ local sum0
+ local sum1
+ # LU-3811
+
+ # Test needs a running copytool.
+ copytool_setup
+ mkdir -p $DIR/$tdir
+
+ # Check that root can do HSM actions on a ordinary user's file.
+ rm -f $file
+ fid=$(make_small $file)
+ sum0=$(md5sum $file)
+
+ chown $RUNAS_ID:$RUNAS_GID $file ||
+ error "cannot chown '$file' to '$RUNAS_ID'"
+
+ chmod ugo-w $DIR/$tdir ||
+ error "cannot chmod '$DIR/$tdir'"
+
+ $LFS hsm_archive $file
+ wait_request_state $fid ARCHIVE SUCCEED
+
+ $LFS hsm_release $file
+ check_hsm_flags $file "0x0000000d"
+
+ $LFS hsm_restore $file
+ wait_request_state $fid RESTORE SUCCEED
+
+ # Check that ordinary user can get HSM state.
+ $RUNAS $LFS hsm_state $file ||
+ error "user '$RUNAS_ID' cannot get HSM state of '$file'"
+
+ $LFS hsm_release $file
+ check_hsm_flags $file "0x0000000d"
+
+ # Check that ordinary user can accessed released file.
+ sum1=$($RUNAS md5sum $file) ||
+ error "user '$RUNAS_ID' cannot read '$file'"
+
+ [ "$sum0" == "$sum1" ] ||
+ error "md5sum mismatch for '$file'"
+
+ copytool_cleanup
+}
+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
+
+ mkdir -p $DIR/$tdir
+ copy2archive /etc/hosts $tdir/$tfile
+
+ local f=$DIR/$tdir/$tfile
+
+ import_file $tdir/$tfile $f
+
+ $LFS hsm_set --lost $f
+
+ md5sum $f
+ local st=$?
+
+ [[ $st == 1 ]] || error "lost file access should failed (returns $st)"
+
+ copytool_cleanup
+}
+run_test 25a "Restore lost file (HS_LOST flag) from import"\
+ " (Operation not permitted)"
+
+test_25b() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+
+ local f=$DIR/$tdir/$tfile
+ local fid=$(copy_file /etc/passwd $f)
+
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+ wait_request_state $fid ARCHIVE SUCCEED
+
+ $LFS hsm_release $f
+ $LFS hsm_set --lost $f
+ md5sum $f
+ st=$?
+
+ [[ $st == 1 ]] || error "lost file access should failed (returns $st)"
+
+ copytool_cleanup
+}
+run_test 25b "Restore lost file (HS_LOST flag) after release"\
+ " (Operation not permitted)"
+
+test_26() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/$tfile
+ local fid=$(make_large_for_progress $f)
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+ wait_request_state $fid ARCHIVE SUCCEED
+
+ $LFS hsm_remove $f
+ wait_request_state $fid REMOVE SUCCEED
+
+ check_hsm_flags $f "0x00000000"
+
+ copytool_cleanup
+}
+run_test 26 "Remove the archive of a valid file"
+
+test_27a() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ make_archive $tdir/$tfile
+ local f=$DIR/$tdir/$tfile
+ import_file $tdir/$tfile $f
+ local fid=$(path2fid $f)
+
+ $LFS hsm_remove $f
+
+ [[ $? != 0 ]] || error "Remove of a released file should fail"
+
+ copytool_cleanup
+}
+run_test 27a "Remove the archive of an imported file (Operation not permitted)"
+
+test_27b() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/$tfile
+ local fid=$(make_large_for_progress $f)
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+ wait_request_state $fid ARCHIVE SUCCEED
+ $LFS hsm_release $f
+
+ $LFS hsm_remove $f
+
+ [[ $? != 0 ]] || error "Remove of a released file should fail"
+
+ copytool_cleanup
+}
+run_test 27b "Remove the archive of a relased file (Operation not permitted)"
+
+test_28() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/$tfile
+ local fid=$(make_large_for_progress $f)
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+ wait_request_state $fid ARCHIVE SUCCEED
+
+ cdt_disable
+ $LFS hsm_remove $f
+
+ rm -f $f
+
+ cdt_enable
+
+ wait_request_state $fid REMOVE SUCCEED
+
+ copytool_cleanup
+}
+run_test 28 "Concurrent archive/file remove"
+
+test_30a() {
+ # restore at exec cannot work on agent node (because of Linux kernel
+ # protection of executables)
+ needclients 2 || return 0
+
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ copy2archive /bin/true $tdir/$tfile
+
+ local f=$DIR/$tdir/true
+ import_file $tdir/$tfile $f
+
+ local fid=$(path2fid $f)
+
+ # set no retry action mode
+ cdt_set_no_retry
+ do_node $CLIENT2 $f
+ local st=$?
+
+ # cleanup
+ # remove no try action mode
+ cdt_clear_no_retry
+ $LFS hsm_state $f
+
+ [[ $st == 0 ]] || error "Failed to exec a released file"
+
+ copytool_cleanup
+}
+run_test 30a "Restore at exec (import case)"
+
+test_30b() {
+ # restore at exec cannot work on agent node (because of Linux kernel
+ # protection of executables)
+ needclients 2 || return 0
+
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/true
+ local fid=$(copy_file /bin/true $f)
+ chmod 755 $f
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+ wait_request_state $fid ARCHIVE SUCCEED
+ $LFS hsm_release $f
+ $LFS hsm_state $f
+ # set no retry action mode
+ cdt_set_no_retry
+ do_node $CLIENT2 $f
+ local st=$?
+
+ # cleanup
+ # remove no try action mode
+ cdt_clear_no_retry
+ $LFS hsm_state $f
+
+ [[ $st == 0 ]] || error "Failed to exec a released file"
+
+ copytool_cleanup
+}
+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
+ local s=$(stat -c "%s" $f)
+ local n=$s
+ local st=$(get_hsm_flags $f)
+ local err=0
+ local cpt=0
+ $LFS hsm_restore $f
+ while [[ "$st" != "0x00000009" && $cpt -le 10 ]]
+ do
+ n=$(stat -c "%s" $f)
+ # we echo in both cases to show stat is not
+ # hang
+ if [[ $n != $s ]]; then
+ echo "size seen is $n != $s"
+ err=1
+ else
+ echo "size seen is right: $n == $s"
+ fi
+ st=$(get_hsm_flags $f)
+ sleep 10
+ cpt=$((cpt + 1))
+ done
+ if [[ $cpt -lt 10 ]]; then
+ echo " "done
+ else
+ echo " restore is too long"
+ wait_request_state $fid RESTORE SUCCEED
+ fi
+ return $err
+}
+
+test_31a() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+
+ make_archive $tdir/$tfile
+ local f=$DIR/$tdir/$tfile
+ import_file $tdir/$tfile $f
+ local fid=$($LFS path2fid $f)
+ HSM_ARCHIVE_PURGE=false copytool_setup
+
+ restore_and_check_size $f $fid
+ local err=$?
+
+ [[ $err -eq 0 ]] || error "File size changed during restore"
+
+ copytool_cleanup
+}
+run_test 31a "Import a large file and check size during restore"
+
+
+test_31b() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+
+ local f=$DIR/$tdir/$tfile
+ local fid=$(make_large_for_progress $f)
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+ wait_request_state $fid ARCHIVE SUCCEED
+ $LFS hsm_release $f
+
+ restore_and_check_size $f $fid
+ local err=$?
+
+ [[ $err -eq 0 ]] || error "File size changed during restore"
+
+ copytool_cleanup
+}
+run_test 31b "Restore a large unaligned file and check size during restore"
+
+test_31c() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+
+ local f=$DIR/$tdir/$tfile
+ local fid=$(make_large_for_progress_aligned $f)
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+ wait_request_state $fid ARCHIVE SUCCEED
+ $LFS hsm_release $f
+
+ restore_and_check_size $f $fid
+ local err=$?
+
+ [[ $err -eq 0 ]] || error "File size changed during restore"
+
+ copytool_cleanup
+}
+run_test 31c "Restore a large aligned file and check size during restore"
+
+test_33() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+
+ local f=$DIR/$tdir/$tfile
+ local fid=$(make_large_for_progress $f)
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+ wait_request_state $fid ARCHIVE SUCCEED
+ $LFS hsm_release $f
+
+ md5sum $f >/dev/null &
+ local pid=$!
+ wait_request_state $fid RESTORE STARTED
+
+ kill -15 $pid
+ sleep 1
+
+ # Check restore trigger process was killed
+ local killed=$(ps -o pid,comm hp $pid >/dev/null)
+
+ $LFS hsm_cancel $f
+
+ wait_request_state $fid RESTORE CANCELED
+ wait_request_state $fid CANCEL SUCCEED
+
+ [ -z $killed ] ||
+ error "Cannot kill process waiting for restore ($killed)"
+
+ copytool_cleanup
+}
+run_test 33 "Kill a restore waiting process"
+
+test_34() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+
+ local f=$DIR/$tdir/$tfile
+ local fid=$(make_large_for_progress $f)
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+ wait_request_state $fid ARCHIVE SUCCEED
+ $LFS hsm_release $f
+
+ md5sum $f >/dev/null &
+ local pid=$!
+ wait_request_state $fid RESTORE STARTED
+
+ rm $f || error "rm $f failed"
+ # rm must not block during restore
+ wait_request_state $fid RESTORE STARTED
+
+ wait_request_state $fid RESTORE SUCCEED
+ # check md5sum pgm finished
+ local there=$(ps -o pid,comm hp $pid >/dev/null)
+ [[ -z $there ]] || error "Restore initiator does not exit"
+
+ local rc=$(wait $pid)
+ [[ $rc -eq 0 ]] || error "Restore initiator failed with $rc"
+
+ copytool_cleanup
+}
+run_test 34 "Remove file during restore"
+
+test_35() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+
+ local f=$DIR/$tdir/$tfile
+ local f1=$DIR/$tdir/$tfile-1
+ local fid=$(make_large_for_progress $f)
+ local fid1=$(copy_file /etc/passwd $f1)
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+ wait_request_state $fid ARCHIVE SUCCEED
+ $LFS hsm_release $f
+
+ md5sum $f >/dev/null &
+ local pid=$!
+ wait_request_state $fid RESTORE STARTED
+
+ mv $f1 $f || error "mv $f1 $f failed"
+ # mv must not block during restore
+ wait_request_state $fid RESTORE STARTED
+
+ wait_request_state $fid RESTORE SUCCEED
+ # check md5sum pgm finished
+ local there=$(ps -o pid,comm hp $pid >/dev/null)
+ [[ -z $there ]] || error "Restore initiator does not exit"
+
+ local rc=$(wait $pid)
+ [[ $rc -eq 0 ]] || error "Restore initiator failed with $rc"
+
+ fid2=$(path2fid $f)
+ [[ $fid2 == $fid1 ]] || error "Wrong fid after mv $fid2 != $fid1"
+
+ copytool_cleanup
+}
+run_test 35 "Overwrite file during restore"
+
+test_36() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+
+ local f=$DIR/$tdir/$tfile
+ local fid=$(make_large_for_progress $f)
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+ wait_request_state $fid ARCHIVE SUCCEED
+ $LFS hsm_release $f
+
+ md5sum $f >/dev/null &
+ local pid=$!
+ wait_request_state $fid RESTORE STARTED
+
+ mv $f $f.new
+ # rm must not block during restore
+ wait_request_state $fid RESTORE STARTED
+
+ wait_request_state $fid RESTORE SUCCEED
+ # check md5sum pgm finished
+ local there=$(ps -o pid,comm hp $pid >/dev/null)
+ [[ -z $there ]] ||
+ error "Restore initiator does not exit"
+
+ local rc=$(wait $pid)
+ [[ $rc -eq 0 ]] ||
+ error "Restore initiator failed with $rc"
+
+ copytool_cleanup
+}
+run_test 36 "Move file during restore"
+
+multi_archive() {
+ local prefix=$1
+ local count=$2
+ local n=""
+
+ for n in $(seq 1 $count); do
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $prefix.$n
+ done
+ echo "$count archive requests submitted"
+}
+
+test_40() {
+ local stream_count=4
+ local file_count=100
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/$tfile
+ local i=""
+ local p=""
+ local fid=""
+
+ for i in $(seq 1 $file_count); do
+ for p in $(seq 1 $stream_count); do
+ fid=$(copy_file /etc/hosts $f.$p.$i)
+ done
+ done
+ # force copytool to use a local/temp archive dir to ensure best
+ # performance vs remote/NFS mounts used in auto-tests
+ if df --local $HSM_ARCHIVE >/dev/null 2>&1 ; then
+ copytool_setup
+ else
+ copytool_setup $SINGLEAGT $MOUNT $HSM_ARCHIVE_NUMBER $TMP/$tdir
+ fi
+ # to be sure wait_all_done will not be mislead by previous tests
+ cdt_purge
+ wait_for_grace_delay
+ typeset -a pids
+ # start archive streams in background (archive files in parallel)
+ for p in $(seq 1 $stream_count); do
+ multi_archive $f.$p $file_count &
+ pids[$p]=$!
+ done
+ echo -n "Wait for all requests being enqueued..."
+ wait ${pids[*]}
+ echo OK
+ wait_all_done 100
+ copytool_cleanup
+}
+run_test 40 "Parallel archive requests"
+
+test_52() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/$tfile
+ local fid=$(copy_file /etc/motd $f 1)
+
+ $LFS hsm_archive $f || error "could not archive file"
+ wait_request_state $fid ARCHIVE SUCCEED
+ check_hsm_flags $f "0x00000009"
+
+ multiop_bg_pause $f O_c || error "multiop failed"
+ local MULTIPID=$!
+
+ mds_evict_client
+ client_up || client_up || true
+
+ kill -USR1 $MULTIPID
+ wait $MULTIPID || error "multiop close failed"
+
+ check_hsm_flags $f "0x0000000b"
+
+ copytool_cleanup
+}
+run_test 52 "Opened for write file on an evicted client should be set dirty"
+
+test_53() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/$tfile
+ local fid=$(copy_file /etc/motd $f 1)
+
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
+ error "could not archive file"
+ wait_request_state $fid ARCHIVE SUCCEED
+ check_hsm_flags $f "0x00000009"
+
+ multiop_bg_pause $f o_c || error "multiop failed"
+ MULTIPID=$!
+
+ mds_evict_client
+ client_up || client_up || true
+
+ kill -USR1 $MULTIPID
+ wait $MULTIPID || error "multiop close failed"
+
+ check_hsm_flags $f "0x00000009"
+
+ copytool_cleanup
+}
+run_test 53 "Opened for read file on an evicted client should not be set dirty"
+
+test_54() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/$tfile
+ local fid=$(make_small $f)
+
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
+ error "could not archive file"
+ wait_request_state $fid ARCHIVE STARTED
+
+ check_hsm_flags $f "0x00000001"
+
+ # Avoid coordinator resending this request as soon it has failed.
+ cdt_set_no_retry
+
+ echo "foo" >> $f
+ sync
+ wait_request_state $fid ARCHIVE FAILED
+
+ check_hsm_flags $f "0x00000003"
+
+ cdt_clear_no_retry
+ copytool_cleanup
+}
+run_test 54 "Write during an archive cancels it"
+
+test_55() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/$tfile
+ local fid=$(make_small $f)
+
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
+ error "could not archive file"
+ wait_request_state $fid ARCHIVE STARTED
+
+ check_hsm_flags $f "0x00000001"
+
+ # Avoid coordinator resending this request as soon it has failed.
+ cdt_set_no_retry
+
+ $TRUNCATE $f 1024 || error "truncate failed"
+ sync
+ wait_request_state $fid ARCHIVE FAILED
+
+ check_hsm_flags $f "0x00000003"
+
+ cdt_clear_no_retry
+ copytool_cleanup
+}
+run_test 55 "Truncate during an archive cancels it"
+
+test_56() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/$tfile
+ local fid=$(make_large_for_progress $f)
+
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
+ error "could not archive file"
+ wait_request_state $fid ARCHIVE STARTED
+
+ check_hsm_flags $f "0x00000001"
+
+ # Change metadata and sync to be sure we are not changing only
+ # in memory.
+ chmod 644 $f
+ chgrp sys $f
+ sync
+ wait_request_state $fid ARCHIVE SUCCEED
+
+ check_hsm_flags $f "0x00000009"
+
+ copytool_cleanup
+}
+run_test 56 "Setattr during an archive is ok"
+
+test_57() {
+ # Need one client for I/O, one for request
+ needclients 2 || return 0
+
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/test_archive_remote
+ # Create a file on a remote node
+ do_node $CLIENT2 "dd if=/dev/urandom of=$f bs=1M "\
+ "count=2 conv=fsync"
+
+ # And archive it
+ do_node $CLIENT2 "$LFS hsm_archive -a $HSM_ARCHIVE_NUMBER $f" ||
+ error "hsm_archive failed"
+ local fid=$(path2fid $f)
+ wait_request_state $fid ARCHIVE SUCCEED
+
+ # Release and implicit restore it
+ do_node $CLIENT2 "$LFS hsm_release $f" ||
+ error "hsm_release failed"
+ do_node $CLIENT2 "md5sum $f" ||
+ error "hsm_restore failed"
+
+ wait_request_state $fid RESTORE SUCCEED
+
+ copytool_cleanup
+}
+run_test 57 "Archive a file with dirty cache on another node"
+
+truncate_released_file() {
+ local src_file=$1
+ local trunc_to=$2
+
+ local sz=$(stat -c %s $src_file)
+ local f=$DIR/$tdir/$tfile
+ local fid=$(copy_file $1 $f)
+ local ref=$f-ref
+ cp $f $f-ref
+
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
+ error "could not archive file"
+ wait_request_state $fid ARCHIVE SUCCEED
+
+ $LFS hsm_release $f || error "could not release file"
+
+ $TRUNCATE $f $trunc_to || error "truncate failed"
+ sync
+
+ local sz1=$(stat -c %s $f)
+ [[ $sz1 == $trunc_to ]] ||
+ error "size after trunc: $sz1 expect $trunc_to, original $sz"
+
+ $LFS hsm_state $f
+ check_hsm_flags $f "0x0000000b"
+
+ local state=$(get_request_state $fid RESTORE)
+ [[ "$state" == "SUCCEED" ]] ||
+ error "truncate $sz does not trig restore, state = $state"
+
+ $TRUNCATE $ref $trunc_to
+ cmp $ref $f || error "file data wrong after truncate"
+
+ rm -f $f $f-ref
+}
+
+test_58() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+
+ local sz=$(stat -c %s /etc/passwd)
+
+ echo "truncate up from $sz to $((sz*2))"
+ truncate_released_file /etc/passwd $((sz*2))
+
+ echo "truncate down from $sz to $((sz/2))"
+ truncate_released_file /etc/passwd $((sz/2))
+
+ echo "truncate to 0"
+ truncate_released_file /etc/passwd 0
+
+ copytool_cleanup
+}
+run_test 58 "Truncate a released file will trigger restore"
+
+test_60() {
+ local interval=5
+ local progress_timeout=$((interval * 2))
+
+ # test needs a new running copytool
+ copytool_cleanup
+ HSMTOOL_UPDATE_INTERVAL=$interval copytool_setup
+
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/$tfile
+ local fid=$(make_large_for_progress $f)
+
+ local start_at=$(date +%s)
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
+ error "could not archive file"
+ wait_request_progress $fid ARCHIVE 5242880
+ local finish_at=$(date +%s)
+ local elapsed=$((finish_at - start_at))
+
+ if [ $elapsed -gt $progress_timeout ]; then
+ error "Expected progress update within $progress_timeout seconds"
+ elif [ $elapsed -lt $interval ]; then
+ error "Expected progress update after at least $interval seconds"
+ fi
+
+ cdt_clear_no_retry
+ copytool_cleanup
+}
+run_test 60 "Changing progress update interval from default"
+
+test_90() {
+ file_count=57
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/$tfile
+ local FILELIST=/tmp/filelist.txt
+ local i=""
+
+ rm -f $FILELIST
+ for i in $(seq 1 $file_count); do
+ fid=$(copy_file /etc/hosts $f.$i)
+ echo $f.$i >> $FILELIST
+ done
+ copytool_setup
+ # to be sure wait_all_done will not be mislead by previous tests
+ cdt_purge
+ wait_for_grace_delay
+ $LFS hsm_archive --filelist $FILELIST ||
+ error "cannot archive a file list"
+ wait_all_done 100
+ $LFS hsm_release --filelist $FILELIST ||
+ error "cannot release a file list"
+ $LFS hsm_restore --filelist $FILELIST ||
+ error "cannot restore a file list"
+ wait_all_done 100
+ copytool_cleanup
+}
+run_test 90 "Archive/restore a file list"
+
+double_verify_reset_hsm_param() {
+ local p=$1
+ echo "Testing $HSM_PARAM.$p"
+ local val=$(get_hsm_param $p)
+ local save=$val
+ local val2=$(($val * 2))
+ set_hsm_param $p $val2
+ val=$(get_hsm_param $p)
+ [[ $val == $val2 ]] ||
+ error "$HSM_PARAM.$p: $val != $val2 should be (2 * $save)"
+ echo "Set $p to 0 must failed"
+ set_hsm_param $p 0
+ local rc=$?
+ # restore value
+ set_hsm_param $p $save
+
+ if [[ $rc == 0 ]]; then
+ error "we must not be able to set $HSM_PARAM.$p to 0"
+ fi
+}
+
+test_100() {
+ double_verify_reset_hsm_param loop_period
+ double_verify_reset_hsm_param grace_delay
+ double_verify_reset_hsm_param active_request_timeout
+ double_verify_reset_hsm_param max_requests
+ double_verify_reset_hsm_param default_archive_id
+}
+run_test 100 "Set coordinator /proc tunables"
+
+test_102() {
+ cdt_disable
+ cdt_enable
+ cdt_restart
+}
+run_test 102 "Verify coordinator control"
+
+test_103() {
+ # test needs a running copytool
+ copytool_setup
+
+ local i=""
+ local fid=""
+
+ mkdir -p $DIR/$tdir
+ for i in $(seq 1 20); do
+ fid=$(copy_file /etc/passwd $DIR/$tdir/$i)
+ done
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $DIR/$tdir/*
+
+ cdt_purge
+
+ echo "Current requests"
+ local res=$(do_facet $SINGLEMDS "$LCTL get_param -n\
+ $HSM_PARAM.actions |\
+ grep -v CANCELED | grep -v SUCCEED | grep -v FAILED")
+
+ [[ -z "$res" ]] || error "Some request have not been canceled"
+
+ copytool_cleanup
+}
+run_test 103 "Purge all requests"
+
+DATA=CEA
+DATAHEX='[434541]'
+test_104() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/$tfile
+ local fid=$(make_large_for_progress $f)
+ # if cdt is on, it can serve too quickly the request
+ cdt_disable
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER --data $DATA $f
+ local data1=$(do_facet $SINGLEMDS "$LCTL get_param -n\
+ $HSM_PARAM.actions |\
+ grep $fid | cut -f16 -d=")
+ cdt_enable
+
+ [[ "$data1" == "$DATAHEX" ]] ||
+ error "Data field in records is ($data1) and not ($DATAHEX)"
+
+ copytool_cleanup
+}
+run_test 104 "Copy tool data field"
+
+test_105() {
+ mkdir -p $DIR/$tdir
+ local i=""
+
+ cdt_disable
+ for i in $(seq -w 1 10); do
+ cp /etc/passwd $DIR/$tdir/$i
+ $LFS hsm_archive $DIR/$tdir/$i
+ done
+ local reqcnt1=$(do_facet $SINGLEMDS "$LCTL get_param -n\
+ $HSM_PARAM.actions |\
+ grep WAITING | wc -l")
+ cdt_restart
+ cdt_disable
+ local reqcnt2=$(do_facet $SINGLEMDS "$LCTL get_param -n\
+ $HSM_PARAM.actions |\
+ grep WAITING | wc -l")
+ cdt_enable
+ cdt_purge
+ [[ "$reqcnt1" == "$reqcnt2" ]] ||
+ error "Requests count after shutdown $reqcnt2 != "\
+ "before shutdown $reqcnt1"
+}
+run_test 105 "Restart of coordinator"
+
+get_agent_by_uuid_mdt() {
+ local uuid=$1
+ local mdtidx=$2
+ local mds=mds$(($mdtidx + 1))
+ do_facet $mds "$LCTL get_param -n ${MDT_PREFIX}${mdtidx}.hsm.agents |\
+ grep $uuid"
+}
+
+check_agent_registered_by_mdt() {
+ local uuid=$1
+ local mdtidx=$2
+ local mds=mds$(($mdtidx + 1))
+ local agent=$(get_agent_by_uuid_mdt $uuid $mdtidx)
+ if [[ ! -z "$agent" ]]; then
+ echo "found agent $agent on $mds"
+ else
+ error "uuid $uuid not found in agent list on $mds"
+ fi
+}
+
+check_agent_unregistered_by_mdt() {
+ local uuid=$1
+ local mdtidx=$2
+ local mds=mds$(($mdtidx + 1))
+ local agent=$(get_agent_by_uuid_mdt $uuid $mdtidx)
+ if [[ -z "$agent" ]]; then
+ echo "uuid not found in agent list on $mds"
+ else
+ error "uuid found in agent list on $mds: $agent"
+ fi
+}
+
+check_agent_registered() {
+ local uuid=$1
+ local mdsno
+ for mdsno in $(seq 1 $MDSCOUNT); do
+ check_agent_registered_by_mdt $uuid $((mdsno - 1))
+ done
+}
+
+check_agent_unregistered() {
+ local uuid=$1
+ local mdsno
+ for mdsno in $(seq 1 $MDSCOUNT); do
+ check_agent_unregistered_by_mdt $uuid $((mdsno - 1))
+ done
+}
+
+test_106() {
+ local uuid=$(do_rpc_nodes $(facet_active_host $SINGLEAGT) \
+ get_client_uuid $MOUNT | cut -d' ' -f2)
+
+ copytool_setup
+ check_agent_registered $uuid
+
+ search_copytools || error "No copytool found"
+
+ copytool_cleanup
+ check_agent_unregistered $uuid
+
+ copytool_setup
+ check_agent_registered $uuid
+
+ copytool_cleanup
+}
+run_test 106 "Copytool register/unregister"
+
+test_107() {
+ # test needs a running copytool
+ copytool_setup
+ # create and archive file
+ mkdir -p $DIR/$tdir
+ local f1=$DIR/$tdir/$tfile
+ local fid=$(copy_file /etc/passwd $f1)
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f1
+ wait_request_state $fid ARCHIVE SUCCEED
+ # shutdown and restart MDS
+ fail $SINGLEMDS
+ # check the copytool still gets messages from MDT
+ local f2=$DIR/$tdir/2
+ local fid=$(copy_file /etc/passwd $f2)
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f2
+ # main check of this sanity: this request MUST succeed
+ wait_request_state $fid ARCHIVE SUCCEED
+ copytool_cleanup
+}
+run_test 107 "Copytool re-register after MDS restart"
+
+policy_set_and_test()
+{
+ local change="$1"
+ local target="$2"
+ do_facet $SINGLEMDS $LCTL set_param "$HSM_PARAM.policy=\\\"$change\\\""
+ local policy=$(do_facet $SINGLEMDS $LCTL get_param -n $HSM_PARAM.policy)
+ [[ "$policy" == "$target" ]] ||
+ error "Wrong policy after '$change': '$policy' != '$target'"
+}
+
+test_109() {
+ # to force default policy setting if error
+ CDT_POLICY_HAD_CHANGED=true
+
+ local policy=$(do_facet $SINGLEMDS $LCTL get_param -n $HSM_PARAM.policy)
+ local default="NonBlockingRestore [NoRetryAction]"
+ [[ "$policy" == "$default" ]] ||
+ error "default policy has changed,"\
+ " '$policy' != '$default' update the test"
+ policy_set_and_test "+NBR" "[NonBlockingRestore] [NoRetryAction]"
+ policy_set_and_test "+NRA" "[NonBlockingRestore] [NoRetryAction]"
+ policy_set_and_test "-NBR" "NonBlockingRestore [NoRetryAction]"
+ policy_set_and_test "-NRA" "NonBlockingRestore NoRetryAction"
+ policy_set_and_test "NRA NBR" "[NonBlockingRestore] [NoRetryAction]"
+ # useless bacause we know but safer for futur changes to use real value
+ local policy=$(do_facet $SINGLEMDS $LCTL get_param -n $HSM_PARAM.policy)
+ echo "Next set_param must failed"
+ policy_set_and_test "wrong" "$policy"
+
+ # return to default
+ echo "Back to default policy"
+ cdt_set_sanity_policy
+}
+run_test 109 "Policy display/change"
+
+test_110a() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+
+ copy2archive /etc/passwd $tdir/$tfile
+
+ local f=$DIR/$tdir/$tfile
+ import_file $tdir/$tfile $f
+ local fid=$(path2fid $f)
+
+ cdt_set_non_blocking_restore
+ md5sum $f
+ local st=$?
+
+ # cleanup
+ wait_request_state $fid RESTORE SUCCEED
+ cdt_clear_non_blocking_restore
+
+ # Test result
+ [[ $st == 1 ]] ||
+ error "md5sum returns $st != 1, "\
+ "should also perror ENODATA (No data available)"
+
+ copytool_cleanup
+}
+run_test 110a "Non blocking restore policy (import case)"
+
+test_110b() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/$tfile
+ local fid=$(copy_file /etc/passwd $f)
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+ wait_request_state $fid ARCHIVE SUCCEED
+ $LFS hsm_release $f
+
+ cdt_set_non_blocking_restore
+ md5sum $f
+ local st=$?
+
+ # cleanup
+ wait_request_state $fid RESTORE SUCCEED
+ cdt_clear_non_blocking_restore
+
+ # Test result
+ [[ $st == 1 ]] ||
+ error "md5sum returns $st != 1, "\
+ "should also perror ENODATA (No data available)"
+
+ copytool_cleanup
+}
+run_test 110b "Non blocking restore policy (release case)"
+
+test_111a() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ copy2archive /etc/passwd $tdir/$tfile
+
+ local f=$DIR/$tdir/$tfile
+
+ import_file $tdir/$tfile $f
+ local fid=$(path2fid $f)
+
+ cdt_set_no_retry
+
+ copytool_remove_backend $fid
+
+ $LFS hsm_restore $f
+ wait_request_state $fid RESTORE FAILED
+ local st=$?
+
+ # cleanup
+ cdt_clear_no_retry
+
+ # Test result
+ [[ $st == 0 ]] || error "Restore does not failed"
+
+ copytool_cleanup
+}
+run_test 111a "No retry policy (import case), restore will error"\
+ " (No such file or directory)"
+
+test_111b() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/$tfile
+ local fid=$(copy_file /etc/passwd $f)
+ cdt_set_no_retry
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+ wait_request_state $fid ARCHIVE SUCCEED
+ $LFS hsm_release $f
+
+ copytool_remove_backend $fid
+
+ $LFS hsm_restore $f
+ wait_request_state $fid RESTORE FAILED
+ local st=$?
+
+ # cleanup
+ cdt_clear_no_retry
+
+ # Test result
+ [[ $st == 0 ]] || error "Restore does not failed"
+
+ copytool_cleanup
+}
+run_test 111b "No retry policy (release case), restore will error"\
+ " (No such file or directory)"
+
+test_112() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/$tfile
+ local fid=$(copy_file /etc/passwd $f)
+ cdt_disable
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+ local l=$($LFS hsm_action $f)
+ echo $l
+ local res=$(echo $l | cut -f 2- -d" " | grep ARCHIVE)
+
+ # cleanup
+ cdt_enable
+ wait_request_state $fid ARCHIVE SUCCEED
+
+ # Test result
+ [[ ! -z "$res" ]] || error "action is $l which is not an ARCHIVE"
+
+ copytool_cleanup
+}
+run_test 112 "State of recorded request"
+
+test_200() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/$tfile
+ local fid=$(make_large_for_cancel $f)
+ # test with cdt on is made in test_221
+ cdt_disable
+ $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+ $LFS hsm_cancel $f
+ cdt_enable
+ wait_request_state $fid ARCHIVE CANCELED
+ wait_request_state $fid CANCEL SUCCEED
+
+ copytool_cleanup
+}
+run_test 200 "Register/Cancel archive"
+
+test_201() {
+ # test needs a running copytool
+ copytool_setup
+
+ mkdir -p $DIR/$tdir
+ local f=$DIR/$tdir/$tfile
+ make_archive $tdir/$tfile
+ import_file $tdir/$tfile $f
+ local fid=$(path2fid $f)
+
+ # test with cdt on is made in test_222
+ cdt_disable
+ $LFS hsm_restore $f
+ $LFS hsm_cancel $f
+ cdt_enable
+ wait_request_state $fid RESTORE CANCELED
+ wait_request_state $fid CANCEL SUCCEED