Whamcloud - gitweb
LU-10271 hsm: don't release with wrong size
[fs/lustre-release.git] / lustre / tests / sanity-hsm.sh
1 #!/bin/bash
2 #
3 # Run select tests by setting ONLY, or as arguments to the script.
4 # Skip specific tests by setting EXCEPT.
5 #
6 # exit on error
7 set -e
8 set +o monitor
9
10 SRCDIR=$(dirname $0)
11 export PATH=$PWD/$SRCDIR:$SRCDIR:$PWD/$SRCDIR/utils:$PATH:/sbin:/usr/sbin
12
13 ONLY=${ONLY:-"$*"}
14 # bug number for skipped test:
15 ALWAYS_EXCEPT="$SANITY_HSM_EXCEPT"
16 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
17
18 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
19
20 . $LUSTRE/tests/test-framework.sh
21 init_test_env $@
22 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
23 init_logging
24
25 MULTIOP=${MULTIOP:-multiop}
26 OPENFILE=${OPENFILE:-openfile}
27 MMAP_CAT=${MMAP_CAT:-mmap_cat}
28 MOUNT_2=${MOUNT_2:-"yes"}
29 FAIL_ON_ERROR=false
30
31 # script only handles up to 10 MDTs (because of MDT_PREFIX)
32 [ $MDSCOUNT -gt 9 ] &&
33         error "script cannot handle more than 9 MDTs, please fix" && exit
34
35 check_and_setup_lustre
36
37 if [[ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.4.53) ]]; then
38         skip_env "Need MDS version at least 2.4.53" && exit
39 fi
40
41 # $RUNAS_ID may get set incorrectly somewhere else
42 if [[ $UID -eq 0 && $RUNAS_ID -eq 0 ]]; then
43         skip_env "\$RUNAS_ID set to 0, but \$UID is also 0!" && exit
44 fi
45 check_runas_id $RUNAS_ID $RUNAS_GID $RUNAS
46
47 build_test_filter
48
49 # if there is no CLIENT1 defined, some tests can be ran on localhost
50 CLIENT1=${CLIENT1:-$HOSTNAME}
51 # if CLIENT2 doesn't exist then use CLIENT1 instead
52 # All tests should use CLIENT2 with MOUNT2 only therefore it will work if
53 # $CLIENT2 == CLIENT1
54 # Exception is the test which need two separate nodes
55 CLIENT2=${CLIENT2:-$CLIENT1}
56
57 #
58 # In order to test multiple remote HSM agents, a new facet type named "AGT" and
59 # the following associated variables are added:
60 #
61 # AGTCOUNT: number of agents
62 # AGTDEV{N}: target HSM mount point (root path of the backend)
63 # agt{N}_HOST: hostname of the agent agt{N}
64 # SINGLEAGT: facet of the single agent
65 #
66 # The number of agents is initialized as the number of remote client nodes.
67 # By default, only single copytool is started on a remote client/agent. If there
68 # was no remote client, then the copytool will be started on the local client.
69 #
70 init_agt_vars() {
71         local n
72         local agent
73
74         export AGTCOUNT=${AGTCOUNT:-$((CLIENTCOUNT - 1))}
75         [[ $AGTCOUNT -gt 0 ]] || AGTCOUNT=1
76
77         export SHARED_DIRECTORY=${SHARED_DIRECTORY:-$TMP}
78         if [[ $CLIENTCOUNT -gt 1 ]] &&
79                 ! check_shared_dir $SHARED_DIRECTORY $CLIENTS; then
80                 skip_env "SHARED_DIRECTORY should be accessible"\
81                          "on all client nodes"
82                 exit 0
83         fi
84
85         # We used to put the HSM archive in $SHARED_DIRECTORY but that
86         # meant NFS issues could hose sanity-hsm sessions. So now we
87         # use $TMP instead.
88         for n in $(seq $AGTCOUNT); do
89                 eval export AGTDEV$n=\$\{AGTDEV$n:-"$TMP/arc$n"\}
90                 agent=CLIENT$((n + 1))
91                 if [[ -z "${!agent}" ]]; then
92                         [[ $CLIENTCOUNT -eq 1 ]] && agent=CLIENT1 ||
93                                 agent=CLIENT2
94                 fi
95                 eval export agt${n}_HOST=\$\{agt${n}_HOST:-${!agent}\}
96         done
97
98         export SINGLEAGT=${SINGLEAGT:-agt1}
99
100         export HSMTOOL=${HSMTOOL:-"lhsmtool_posix"}
101         export HSMTOOL_VERBOSE=${HSMTOOL_VERBOSE:-""}
102         export HSMTOOL_UPDATE_INTERVAL=${HSMTOOL_UPDATE_INTERVAL:=""}
103         export HSMTOOL_EVENT_FIFO=${HSMTOOL_EVENT_FIFO:=""}
104         export HSMTOOL_TESTDIR
105         export HSMTOOL_BASE=$(basename "$HSMTOOL" | cut -f1 -d" ")
106         # $hsm_root/$HSMTMP Makes $hsm_root dir path less generic to ensure
107         # rm -rf $hsm_root/* is safe even if $hsm_root becomes unset to avoid
108         # deleting everything in filesystem, independent of any copytool.
109         export HSMTMP=${HSMTMP:-"shsm"}
110
111         HSM_ARCHIVE=$(copytool_device $SINGLEAGT)
112
113         [ -z "${HSM_ARCHIVE// /}" ] && error "HSM_ARCHIVE is empty!"
114         HSM_ARCHIVE=$HSM_ARCHIVE/$HSMTMP
115
116         HSM_ARCHIVE_NUMBER=2
117
118         # The test only support up to 10 MDTs
119         MDT_PREFIX="mdt.$FSNAME-MDT000"
120         HSM_PARAM="${MDT_PREFIX}0.hsm"
121
122         # archive is purged at copytool setup
123         HSM_ARCHIVE_PURGE=true
124
125         # Don't allow copytool error upon start/setup
126         HSMTOOL_NOERROR=false
127 }
128
129 # Get the backend root path for the given agent facet.
130 copytool_device() {
131         local facet=$1
132         local dev=AGTDEV$(facet_number $facet)
133
134         echo -n ${!dev}
135 }
136
137 # Stop copytool and unregister an existing changelog user.
138 cleanup() {
139         copytool_monitor_cleanup
140         copytool_cleanup
141         changelog_cleanup
142         cdt_set_sanity_policy
143 }
144
145 get_mdt_devices() {
146         local mdtno
147         # get MDT device for each mdc
148         for mdtno in $(seq 1 $MDSCOUNT); do
149                 local idx=$(($mdtno - 1))
150                 MDT[$idx]=$($LCTL get_param -n \
151                         mdc.$FSNAME-MDT000${idx}-mdc-*.mds_server_uuid |
152                         awk '{gsub(/_UUID/,""); print $1}' | head -n1)
153         done
154 }
155
156 search_copytools() {
157         local hosts=${1:-$(facet_active_host $SINGLEAGT)}
158         do_nodesv $hosts "pgrep -x $HSMTOOL_BASE"
159 }
160
161 kill_copytools() {
162         local hosts=${1:-$(facet_active_host $SINGLEAGT)}
163
164         echo "Killing existing copytools on $hosts"
165         do_nodesv $hosts "killall -q $HSMTOOL_BASE" || true
166 }
167
168 wait_copytools() {
169         local hosts=${1:-$(facet_active_host $SINGLEAGT)}
170         local wait_timeout=200
171         local wait_start=$SECONDS
172         local wait_end=$((wait_start + wait_timeout))
173         local sleep_time=100000 # 0.1 second
174
175         while ((SECONDS < wait_end)); do
176                 if ! search_copytools $hosts; then
177                         echo "copytools stopped in $((SECONDS - wait_start))s"
178                         return 0
179                 fi
180
181                 echo "copytools still running on $hosts"
182                 usleep $sleep_time
183                 [ $sleep_time -lt 32000000 ] && # 3.2 seconds
184                         sleep_time=$(bc <<< "$sleep_time * 2")
185         done
186
187         # try to dump Copytool's stack
188         do_nodesv $hosts "echo 1 >/proc/sys/kernel/sysrq ; " \
189                          "echo t >/proc/sysrq-trigger"
190
191         echo "copytools failed to stop in ${wait_timeout}s"
192
193         return 1
194 }
195
196 copytool_monitor_setup() {
197         local facet=${1:-$SINGLEAGT}
198         local agent=$(facet_active_host $facet)
199
200         local cmd="mktemp --tmpdir=/tmp -d ${TESTSUITE}.${TESTNAME}.XXXX"
201         local test_dir=$(do_node $agent "$cmd") ||
202                 error "Failed to create tempdir on $agent"
203         export HSMTOOL_MONITOR_DIR=$test_dir
204
205         # Create the fifo and a monitor (cat dies when copytool dies)
206         do_node $agent "mkfifo -m 0644 $test_dir/fifo" ||
207                 error "failed to create copytool fifo on $agent"
208         cmd="cat $test_dir/fifo > $test_dir/events &"
209         cmd+=" echo \\\$! > $test_dir/monitor_pid"
210
211         if [[ $PDSH == *Rmrsh* ]]; then
212                 # This is required for pdsh -Rmrsh and its handling of remote
213                 # shells.
214                 # Regular ssh and pdsh -Rssh work fine without this
215                 # backgrounded subshell nonsense.
216                 (do_node $agent "$cmd") &
217                 export HSMTOOL_MONITOR_PDSH=$!
218
219                 # Slightly racy, but just making a best-effort to catch obvious
220                 # problems.
221                 sleep 1
222                 ps -p $HSMTOOL_MONITOR_PDSH > /dev/null ||
223                         error "Failed to start copytool monitor on $agent"
224         else
225                 do_node $agent "$cmd"
226                 if [ $? != 0 ]; then
227                         error "Failed to start copytool monitor on $agent"
228                 fi
229         fi
230 }
231
232 copytool_monitor_cleanup() {
233         local facet=${1:-$SINGLEAGT}
234         local agent=$(facet_active_host $facet)
235
236         if [ -n "$HSMTOOL_MONITOR_DIR" ]; then
237                 # Should die when the copytool dies, but just in case.
238                 local cmd="kill \\\$(cat $HSMTOOL_MONITOR_DIR/monitor_pid)"
239                 cmd+=" 2>/dev/null || true"
240                 do_node $agent "$cmd"
241                 do_node $agent "rm -fr $HSMTOOL_MONITOR_DIR"
242                 export HSMTOOL_MONITOR_DIR=
243         fi
244
245         # The pdsh should die on its own when the monitor dies. Just
246         # in case, though, try to clean up to avoid any cruft.
247         if [ -n "$HSMTOOL_MONITOR_PDSH" ]; then
248                 kill $HSMTOOL_MONITOR_PDSH 2>/dev/null
249                 export HSMTOOL_MONITOR_PDSH=
250         fi
251 }
252
253 copytool_setup() {
254         local facet=${1:-$SINGLEAGT}
255         # Use MOUNT2 by default if defined
256         local lustre_mntpnt=${2:-${MOUNT2:-$MOUNT}}
257         local arc_id=$3
258         local hsm_root=${4:-$(copytool_device $facet)}
259
260         [ -z "${hsm_root// /}" ] && error "copytool_setup: hsm_root empty!"
261
262         local agent=$(facet_active_host $facet)
263
264         if $HSM_ARCHIVE_PURGE; then
265                 echo "Purging archive on $agent"
266                 do_facet $facet "rm -rf $hsm_root/$HSMTMP/*"
267         fi
268
269         echo "Starting copytool $facet on $agent"
270         do_facet $facet "mkdir -p $hsm_root/$HSMTMP/" ||
271                         error "mkdir '$hsm_root/$HSMTMP' failed"
272         # bandwidth is limited to 1MB/s so the copy time is known and
273         # independent of hardware
274         local cmd="$HSMTOOL $HSMTOOL_VERBOSE --daemon"
275         cmd+=" --hsm-root $hsm_root/$HSMTMP"
276         [[ -z "$arc_id" ]] || cmd+=" --archive $arc_id"
277         [[ -z "$HSMTOOL_UPDATE_INTERVAL" ]] ||
278                 cmd+=" --update-interval $HSMTOOL_UPDATE_INTERVAL"
279         [[ -z "$HSMTOOL_EVENT_FIFO" ]] ||
280                 cmd+=" --event-fifo $HSMTOOL_EVENT_FIFO"
281         cmd+=" --bandwidth 1 $lustre_mntpnt"
282
283         # Redirect the standard output and error to a log file which
284         # can be uploaded to Maloo.
285         local prefix=$TESTLOG_PREFIX
286         [[ -z "$TESTNAME" ]] || prefix=$prefix.$TESTNAME
287         local copytool_log=$prefix.copytool${arc_id}_log.$agent.log
288
289         stack_trap cleanup EXIT
290         do_facet $facet "$cmd < /dev/null > $copytool_log 2>&1"
291         if [[ $? !=  0 ]]; then
292                 [[ $HSMTOOL_NOERROR == true ]] ||
293                         error "start copytool $facet on $agent failed"
294                 echo "start copytool $facet on $agent failed"
295         fi
296 }
297
298 get_copytool_event_log() {
299         local facet=${1:-$SINGLEAGT}
300         local agent=$(facet_active_host $facet)
301
302         [ -z "$HSMTOOL_MONITOR_DIR" ] &&
303                 error "Can't get event log: No monitor directory!"
304
305         do_node $agent "cat $HSMTOOL_MONITOR_DIR/events" ||
306                 error "Could not collect event log from $agent"
307 }
308
309 copytool_cleanup() {
310         trap - EXIT
311         local agt_facet=$SINGLEAGT
312         local agt_hosts=${1:-$(facet_active_host $agt_facet)}
313         local hsm_root=$(copytool_device $agt_facet)
314
315         [ -z "${hsm_root// /}" ] && error "copytool_cleanup: hsm_root empty!"
316
317         local i
318         local facet
319         local param
320         local -a state
321
322         kill_copytools $agt_hosts
323         wait_copytools $agt_hosts || error "copytools failed to stop"
324
325         # Clean all CDTs orphans requests from previous tests that
326         # would otherwise need to timeout to clear.
327         for ((i = 0; i < MDSCOUNT; i++)); do
328                 facet=mds$((i + 1))
329                 param=$(printf 'mdt.%s-MDT%04x.hsm_control' $FSNAME $i)
330                 state[$i]=$(do_facet $facet "$LCTL get_param -n $param")
331
332                 # Skip already stopping or stopped CDTs.
333                 [[ "${state[$i]}" =~ ^stop ]] && continue
334
335                 do_facet $facet "$LCTL set_param $param=shutdown"
336         done
337
338         for ((i = 0; i < MDSCOUNT; i++)); do
339                 # Only check and restore CDTs that we stopped in the first loop.
340                 [[ "${state[$i]}" =~ ^stop ]] && continue
341
342                 facet=mds$((i + 1))
343                 param=$(printf 'mdt.%s-MDT%04x.hsm_control' $FSNAME $i)
344
345                 wait_result $facet "$LCTL get_param -n $param" stopped 20 ||
346                         error "$facet CDT state is not stopped"
347
348                 # Restore old CDT state.
349                 do_facet $facet "$LCTL set_param $param=${state[$i]}"
350         done
351
352         for ((i = 0; i < MDSCOUNT; i++)); do
353                 # Only check CDTs that we stopped in the first loop.
354                 [[ "${state[$i]}" =~ ^stop ]] && continue
355
356                 facet=mds$((i + 1))
357                 param=$(printf 'mdt.%s-MDT%04x.hsm_control' $FSNAME $i)
358
359                 # Check that the old CDT state was restored.
360                 wait_result $facet "$LCTL get_param -n $param" "${state[$i]}" \
361                         20 || error "$facet CDT state is not '${state[$i]}'"
362         done
363
364         if do_facet $agt_facet "df $hsm_root" >/dev/null 2>&1 ; then
365                 do_facet $agt_facet "rm -rf $hsm_root/$HSMTMP/*"
366         fi
367 }
368
369 copytool_suspend() {
370         local agents=${1:-$(facet_active_host $SINGLEAGT)}
371
372         do_nodesv $agents "pkill -STOP -x $HSMTOOL_BASE" || return 0
373         echo "Copytool is suspended on $agents"
374 }
375
376 copytool_continue() {
377         local agents=${1:-$(facet_active_host $SINGLEAGT)}
378
379         do_nodesv $agents "pkill -CONT -x $HSMTOOL_BASE" || return 0
380         echo "Copytool is continued on $agents"
381 }
382
383 copytool_remove_backend() {
384         local fid=$1
385         local be=$(do_facet $SINGLEAGT find $HSM_ARCHIVE -name $fid)
386         echo "Remove from backend: $fid = $be"
387         do_facet $SINGLEAGT rm -f $be
388 }
389
390 import_file() {
391         do_facet $SINGLEAGT \
392                 "$HSMTOOL --archive $HSM_ARCHIVE_NUMBER --hsm-root $HSM_ARCHIVE\
393                 --import $1 $2 $MOUNT" ||
394                 error "import of $1 to $2 failed"
395 }
396
397 file_creation_failure() {
398         local cmd=$1
399         local file=$2
400         local err=$3
401
402         case $err in
403         28)
404                 df $MOUNT $MOUNT2 >&2
405                 error "Not enough space to create $file with $cmd"
406                 ;;
407         *)
408                 error "cannot create $file with $cmd, status=$err"
409                 ;;
410         esac
411 }
412
413 # Creates a file using dd
414 create_file() {
415         local file=$1
416         local bs=$2
417         local count=$3
418         local conv=$4
419         local if=${5:-/dev/zero}
420         local facet=$SINGLEAGT
421
422         local cmd
423         printf -v cmd 'do_facet "%s" dd if="%s" of="%s" count=%s bs=%s' \
424                 "$facet" "$if" "$file" "$count" "$bs"
425         [ -n "$conv" ] && cmd+=" conv=$conv"
426
427         # Create the directory in case it does not exist
428         do_facet "$facet" mkdir -p "$(dirname "$file")"
429         # Delete the file in case it already exist
430         do_facet "$facet" rm -f "$file"
431
432         if eval "$cmd"; then
433                 # print the FID if the file is not an archive
434                 [[ "$file" =~ ^$HSM_ARCHIVE ]] || path2fid "$file" ||
435                         error "cannot get fid on '$file'"
436         else
437                 local err=$?
438                 printf "$cmd failed with $err\n" >&2;
439                 # Let the caller decide what to do on error
440                 return $err;
441         fi
442 }
443
444 create_empty_file() {
445         create_file "${1/$DIR/$DIR2}" 1M 0 ||
446                 file_creation_failure dd "${1/$DIR/$DIR2}" $?
447 }
448
449 create_small_file() {
450         local source_file=/dev/urandom
451         local count=1
452         local bs=1M
453         local conv=${2:-fsync}
454
455         create_file "${1/$DIR/$DIR2}" $bs $count $conv $source_file ||
456                 file_creation_failure dd "${1/$DIR/$DIR2}" $?
457 }
458
459 create_small_sync_file() {
460         create_small_file "$1" sync
461 }
462
463 create_archive_file() {
464         local if=/dev/urandom
465         local count=${2:-39}
466         local bs=1M
467         local facet=$SINGLEAGT
468
469         # Create the counterpart directory of the archive
470         do_facet "$facet" mkdir -p "$DIR2/$(dirname "$1")"
471         create_file "${HSM_ARCHIVE}/$1" $bs $count "" $if ||
472                 file_creation_failure dd "${HSM_ARCHIVE}/$1" $?
473 }
474
475 copy2archive() {
476         local file=$HSM_ARCHIVE/$2
477         do_facet $SINGLEAGT mkdir -p $(dirname $file)
478         do_facet $SINGLEAGT cp -p $1 $file || error "cannot copy $1 to $file"
479 }
480
481 mdts_set_param() {
482         local arg=$1
483         local key=$2
484         local value=$3
485         local mdtno
486         local rc=0
487         if [[ "$value" != "" ]]; then
488                 value="=$value"
489         fi
490         for mdtno in $(seq 1 $MDSCOUNT); do
491                 local idx=$(($mdtno - 1))
492                 local facet=mds${mdtno}
493                 # if $arg include -P option, run 1 set_param per MDT on the MGS
494                 # else, run set_param on each MDT
495                 [[ $arg = *"-P"* ]] && facet=mgs
496                 do_facet $facet $LCTL set_param $arg mdt.${MDT[$idx]}.$key$value
497                 [[ $? != 0 ]] && rc=1
498         done
499         return $rc
500 }
501
502 mdts_check_param() {
503         local key="$1"
504         local target="$2"
505         local timeout="$3"
506         local mdtno
507         for mdtno in $(seq 1 $MDSCOUNT); do
508                 local idx=$(($mdtno - 1))
509                 wait_result mds${mdtno} \
510                         "$LCTL get_param -n $MDT_PREFIX${idx}.$key" "$target" \
511                         $timeout ||
512                         error "$key state is not '$target' on mds${mdtno}"
513         done
514 }
515
516 changelog_setup() {
517         CL_USERS=()
518         local mdtno
519         for mdtno in $(seq 1 $MDSCOUNT); do
520                 local idx=$(($mdtno - 1))
521                 local cl_user=$(do_facet mds${mdtno} $LCTL \
522                              --device ${MDT[$idx]} \
523                              changelog_register -n)
524                 CL_USERS+=($cl_user)
525                 do_facet mds${mdtno} lctl set_param \
526                         mdd.${MDT[$idx]}.changelog_mask="+hsm"
527                 $LFS changelog_clear ${MDT[$idx]} $cl_user 0
528         done
529 }
530
531 changelog_cleanup() {
532         local mdtno
533         for mdtno in $(seq 1 $MDSCOUNT); do
534                 local idx=$(($mdtno - 1))
535                 [[ -z  ${CL_USERS[$idx]} ]] && continue
536                 $LFS changelog_clear ${MDT[$idx]} ${CL_USERS[$idx]} 0
537                 do_facet mds${mdtno} lctl --device ${MDT[$idx]} \
538                         changelog_deregister ${CL_USERS[$idx]}
539         done
540         CL_USERS=()
541 }
542
543 changelog_get_flags() {
544         local mdt=$1
545         local cltype=$2
546         local fid=$3
547
548         $LFS changelog $mdt | awk "/$cltype/ && /t=\[$fid\]/ {print \$5}"
549 }
550
551 get_hsm_param() {
552         local param=$1
553         local val=$(do_facet $SINGLEMDS $LCTL get_param -n $HSM_PARAM.$param)
554         echo $val
555 }
556
557 set_hsm_param() {
558         local param=$1
559         local value=$2
560         local opt=$3
561         mdts_set_param "$opt -n" "hsm.$param" "$value"
562         return $?
563 }
564
565 set_test_state() {
566         local cmd=$1
567         local target=$2
568         mdts_set_param "" hsm_control "$cmd"
569         mdts_check_param hsm_control "$target" 10
570 }
571
572 cdt_set_sanity_policy() {
573         if [[ "$CDT_POLICY_HAD_CHANGED" ]]
574         then
575                 # clear all
576                 mdts_set_param "" hsm.policy "+NRA"
577                 mdts_set_param "" hsm.policy "-NBR"
578                 CDT_POLICY_HAD_CHANGED=
579         fi
580 }
581
582 cdt_set_no_retry() {
583         mdts_set_param "" hsm.policy "+NRA"
584         CDT_POLICY_HAD_CHANGED=true
585 }
586
587 cdt_clear_no_retry() {
588         mdts_set_param "" hsm.policy "-NRA"
589         CDT_POLICY_HAD_CHANGED=true
590 }
591
592 cdt_set_non_blocking_restore() {
593         mdts_set_param "" hsm.policy "+NBR"
594         CDT_POLICY_HAD_CHANGED=true
595 }
596
597 cdt_clear_non_blocking_restore() {
598         mdts_set_param "" hsm.policy "-NBR"
599         CDT_POLICY_HAD_CHANGED=true
600 }
601
602 cdt_clear_mount_state() {
603         mdts_set_param "-P -d" hsm_control ""
604 }
605
606 cdt_set_mount_state() {
607         mdts_set_param "-P" hsm_control "$1"
608         # set_param -P is asynchronous operation and could race with set_param.
609         # In such case configs could be retrieved and applied at mgc after
610         # set_param -P completion. Sleep here to avoid race with set_param.
611         # We need at least 20 seconds. 10 for mgc_requeue_thread to wake up
612         # MGC_TIMEOUT_MIN_SECONDS + MGC_TIMEOUT_RAND_CENTISEC(5 + 5)
613         # and 10 seconds to retrieve config from server.
614         sleep 20
615 }
616
617 cdt_check_state() {
618         mdts_check_param hsm_control "$1" 20
619 }
620
621 cdt_disable() {
622         set_test_state disabled disabled
623 }
624
625 cdt_enable() {
626         set_test_state enabled enabled
627 }
628
629 cdt_shutdown() {
630         set_test_state shutdown stopped
631 }
632
633 cdt_purge() {
634         set_test_state purge enabled
635 }
636
637 cdt_restart() {
638         cdt_shutdown
639         cdt_enable
640         cdt_set_sanity_policy
641 }
642
643 needclients() {
644         local client_count=$1
645         if [[ $CLIENTCOUNT -lt $client_count ]]; then
646                 skip "Need $client_count or more clients, have $CLIENTCOUNT"
647                 return 1
648         fi
649         return 0
650 }
651
652 path2fid() {
653         $LFS path2fid $1 | tr -d '[]'
654         return ${PIPESTATUS[0]}
655 }
656
657 get_hsm_flags() {
658         local f=$1
659         local u=$2
660         local st
661
662         if [[ $u == "user" ]]; then
663                 st=$($RUNAS $LFS hsm_state $f)
664         else
665                 u=root
666                 st=$($LFS hsm_state $f)
667         fi
668
669         [[ $? == 0 ]] || error "$LFS hsm_state $f failed (run as $u)"
670
671         st=$(echo $st | cut -f 2 -d" " | tr -d "()," )
672         echo $st
673 }
674
675 get_hsm_archive_id() {
676         local f=$1
677         local st
678         st=$($LFS hsm_state $f)
679         [[ $? == 0 ]] || error "$LFS hsm_state $f failed"
680
681         local ar=$(echo $st | grep "archive_id" | cut -f5 -d" " |
682                    cut -f2 -d:)
683         echo $ar
684 }
685
686 check_hsm_flags() {
687         local f=$1
688         local fl=$2
689
690         local st=$(get_hsm_flags $f)
691         [[ $st == $fl ]] || error "hsm flags on $f are $st != $fl"
692 }
693
694 check_hsm_flags_user() {
695         local f=$1
696         local fl=$2
697
698         local st=$(get_hsm_flags $f user)
699         [[ $st == $fl ]] || error "hsm flags on $f are $st != $fl"
700 }
701
702 copy_file() {
703         local f=
704
705         if [[ -d $2 ]]; then
706                 f=$2/$(basename $1)
707         else
708                 f=$2
709         fi
710
711         if [[ "$3" != 1 ]]; then
712                 f=${f/$DIR/$DIR2}
713         fi
714         rm -f $f
715         cp $1 $f || file_creation_failure cp $f $?
716
717         path2fid $f || error "cannot get fid on $f"
718 }
719
720 # Delete any file bigger than 10M under $MOUNT and wait for deletes to complete
721 #
722 # Note that this might lead to surprising behaviours such as deleting an
723 # important file for the currently running test
724 delete_large_files() {
725         printf "Deleting large files...\n" >&2
726         find $MOUNT -size +10M -delete
727         wait_delete_completed
728 }
729
730 make_custom_file_for_progress() {
731         local count=${2:-"39"}
732         local bs=$($LCTL get_param -n lov.*-clilov-*.stripesize | head -n1)
733         bs=${3:-$bs}
734
735         [[ $count -gt  0 ]] || error "Invalid file size"
736         [[ $bs -gt 0 ]] || error "Invalid stripe size"
737
738         if ! create_file "${1/$DIR/$DIR2}" $bs $count fsync; then
739                 echo "The creation of '${1/$DIR/$DIR2}' failed" >&2
740                 echo "It might be due to a lack of space in the filesystem" >&2
741                 delete_large_files >&2
742                 create_file "${1/$DIR/$DIR2}" $bs $count fsync ||
743                         file_creation_failure dd "${1/$DIR/$DIR2}" $?
744         fi
745 }
746
747 wait_result() {
748         local facet=$1
749         shift
750         wait_update --verbose $(facet_active_host $facet) "$@"
751 }
752
753 wait_request_state() {
754         local fid=$1
755         local request=$2
756         local state=$3
757         # 4th arg (mdt index) is optional
758         local mdtidx=${4:-0}
759         local mds=mds$(($mdtidx + 1))
760
761         local cmd="$LCTL get_param -n ${MDT_PREFIX}${mdtidx}.hsm.actions"
762         cmd+=" | awk '/'$fid'.*action='$request'/ {print \\\$13}' | cut -f2 -d="
763
764         wait_result $mds "$cmd" $state 200 ||
765                 error "request on $fid is not $state on $mds"
766 }
767
768 get_request_state() {
769         local fid=$1
770         local request=$2
771
772         do_facet $SINGLEMDS "$LCTL get_param -n $HSM_PARAM.actions |"\
773                 "awk '/'$fid'.*action='$request'/ {print \\\$13}' | cut -f2 -d="
774 }
775
776 get_request_count() {
777         local fid=$1
778         local request=$2
779
780         do_facet $SINGLEMDS "$LCTL get_param -n $HSM_PARAM.actions |"\
781                 "awk -vn=0 '/'$fid'.*action='$request'/ {n++}; END {print n}'"
782 }
783
784 # Ensure the number of HSM request for a given FID is correct
785 # assert_request_count FID REQUEST_TYPE COUNT [ERROR_MSG]
786 assert_request_count() {
787         local request_count=$(get_request_count $1 $2)
788         local default_error_msg=("expected $3 '$2' request(s) for '$1', found "
789                                 "'$request_count'")
790         [ $request_count -eq $3 ] || error "${4:-"${default_error_msg[@]}"}"
791 }
792
793 wait_all_done() {
794         local timeout=$1
795         local fid=$2
796
797         local cmd="$LCTL get_param -n $HSM_PARAM.actions"
798         [[ -n $fid ]] && cmd+=" | grep '$fid'"
799         cmd+=" | egrep 'WAITING|STARTED'"
800
801         wait_result $SINGLEMDS "$cmd" "" $timeout ||
802                 error "requests did not complete"
803 }
804
805 wait_for_grace_delay() {
806         local val=$(get_hsm_param grace_delay)
807         sleep $val
808 }
809
810 wait_for_loop_period() {
811         local val=$(get_hsm_param loop_period)
812         sleep $val
813 }
814
815 parse_json_event() {
816         local raw_event=$1
817
818         # python2.6 in EL6 includes an internal json module
819         local json_parser='import json; import fileinput;'
820         json_parser+=' print "\n".join(["local %s=\"%s\"" % tuple for tuple in '
821         json_parser+='json.loads([line for line in '
822         json_parser+='fileinput.input()][0]).items()])'
823
824         echo $raw_event | python -c "$json_parser"
825 }
826
827 get_agent_by_uuid_mdt() {
828         local uuid=$1
829         local mdtidx=$2
830         local mds=mds$(($mdtidx + 1))
831         do_facet $mds "$LCTL get_param -n ${MDT_PREFIX}${mdtidx}.hsm.agents |\
832                  grep $uuid"
833 }
834
835 check_agent_registered_by_mdt() {
836         local uuid=$1
837         local mdtidx=$2
838         local mds=mds$(($mdtidx + 1))
839         local agent=$(get_agent_by_uuid_mdt $uuid $mdtidx)
840         if [[ ! -z "$agent" ]]; then
841                 echo "found agent $agent on $mds"
842         else
843                 error "uuid $uuid not found in agent list on $mds"
844         fi
845 }
846
847 check_agent_unregistered_by_mdt() {
848         local uuid=$1
849         local mdtidx=$2
850         local mds=mds$(($mdtidx + 1))
851         local agent=$(get_agent_by_uuid_mdt $uuid $mdtidx)
852         if [[ -z "$agent" ]]; then
853                 echo "uuid not found in agent list on $mds"
854         else
855                 error "uuid found in agent list on $mds: $agent"
856         fi
857 }
858
859 check_agent_registered() {
860         local uuid=$1
861         local mdsno
862         for mdsno in $(seq 1 $MDSCOUNT); do
863                 check_agent_registered_by_mdt $uuid $((mdsno - 1))
864         done
865 }
866
867 check_agent_unregistered() {
868         local uuid=$1
869         local mdsno
870         for mdsno in $(seq 1 $MDSCOUNT); do
871                 check_agent_unregistered_by_mdt $uuid $((mdsno - 1))
872         done
873 }
874
875 get_agent_uuid() {
876         local agent=${1:-$(facet_active_host $SINGLEAGT)}
877
878         # Lustre mount-point is mandatory and last parameter on
879         # copytool cmd-line.
880         local mntpnt=$(do_rpc_nodes $agent ps -C $HSMTOOL_BASE -o args= |
881                        awk '{print $NF}')
882         [ -n "$mntpnt" ] || error "Found no Agent or with no mount-point "\
883                                   "parameter"
884         do_rpc_nodes $agent get_client_uuid $mntpnt | cut -d' ' -f2
885 }
886
887 # initiate variables
888 init_agt_vars
889
890 # populate MDT device array
891 get_mdt_devices
892
893 # cleanup from previous bad setup
894 kill_copytools
895
896 # for recovery tests, coordinator needs to be started at mount
897 # so force it
898 # the lustre conf must be without hsm on (like for sanity.sh)
899 echo "Set HSM on and start"
900 cdt_set_mount_state enabled
901 cdt_check_state enabled
902
903 echo "Set sanity-hsm HSM policy"
904 cdt_set_sanity_policy
905
906 # finished requests are quickly removed from list
907 set_hsm_param grace_delay 10
908
909 test_1() {
910         mkdir -p $DIR/$tdir
911         chmod 777 $DIR/$tdir
912
913         local f=$DIR/$tdir/$tfile
914         $RUNAS touch $f
915
916         # User flags
917         check_hsm_flags_user $f "0x00000000"
918
919         $RUNAS $LFS hsm_set --norelease $f ||
920                 error "user could not change hsm flags"
921         check_hsm_flags_user $f "0x00000010"
922
923         $RUNAS $LFS hsm_clear --norelease $f ||
924                 error "user could not clear hsm flags"
925         check_hsm_flags_user $f "0x00000000"
926
927         # User could not change those flags...
928         $RUNAS $LFS hsm_set --exists $f &&
929                 error "user should not set this flag"
930         check_hsm_flags_user $f "0x00000000"
931
932         # ...but root can
933         $LFS hsm_set --exists $f ||
934                 error "root could not change hsm flags"
935         check_hsm_flags_user $f "0x00000001"
936
937         $LFS hsm_clear --exists $f ||
938                 error "root could not clear hsm state"
939         check_hsm_flags_user $f "0x00000000"
940
941 }
942 run_test 1 "lfs hsm flags root/non-root access"
943
944 test_1a() {
945         local f=$DIR/$tdir/$tfile
946         local fid=$(create_small_file $f)
947
948         copytool_setup
949
950         $LFS hsm_archive $f || error "could not archive file"
951         wait_request_state $fid ARCHIVE SUCCEED
952
953         # Release and check states
954         $LFS hsm_release $f || error "could not release file"
955         echo -n "Verifying released state: "
956         check_hsm_flags $f "0x0000000d"
957
958         $MMAP_CAT $f > /dev/null || error "failed mmap & cat release file"
959
960         copytool_cleanup
961 }
962 run_test 1a "mmap & cat a HSM released file"
963
964 test_1b() {
965         mkdir -p $DIR/$tdir
966         $LFS setstripe -E 1M -E 64M -c 2 -E -1 -c 4 $DIR/$tdir ||
967                 error "failed to set default stripe"
968         local f=$DIR/$tdir/$tfile
969         rm -f $f
970
971         dd if=/dev/random of=$f bs=1M count=1 conv=sync ||
972                 error "failed to create file"
973         local fid=$(path2fid $f)
974
975         copytool_setup
976
977         echo "archive $f"
978         $LFS hsm_archive $f || error "could not archive file"
979         wait_request_state $fid ARCHIVE SUCCEED
980
981         echo "release $f"
982         $LFS hsm_release $f || error "could not release file"
983         echo "verify released state: "
984         check_hsm_flags $f "0x0000000d" && echo "pass"
985
986         echo "restore $f"
987         $LFS hsm_restore $f || error "could not restore file"
988         wait_request_state $fid RESTORE SUCCEED
989         echo "verify restored state: "
990         check_hsm_flags $f "0x00000009" && echo "pass"
991
992         copytool_cleanup
993 }
994 run_test 1b "Archive, Release & Restore composite file"
995
996 test_2() {
997         local f=$DIR/$tdir/$tfile
998
999         create_empty_file "$f"
1000         # New files are not dirty
1001         check_hsm_flags $f "0x00000000"
1002
1003         # For test, we simulate an archived file.
1004         $LFS hsm_set --exists $f || error "user could not change hsm flags"
1005         check_hsm_flags $f "0x00000001"
1006
1007         # chmod do not put the file dirty
1008         chmod 600 $f || error "could not chmod test file"
1009         check_hsm_flags $f "0x00000001"
1010
1011         # chown do not put the file dirty
1012         chown $RUNAS_ID $f || error "could not chown test file"
1013         check_hsm_flags $f "0x00000001"
1014
1015         # truncate put the file dirty
1016         $TRUNCATE $f 1 || error "could not truncate test file"
1017         check_hsm_flags $f "0x00000003"
1018
1019         $LFS hsm_clear --dirty $f || error "could not clear hsm flags"
1020         check_hsm_flags $f "0x00000001"
1021 }
1022 run_test 2 "Check file dirtyness when doing setattr"
1023
1024 test_3() {
1025         mkdir -p $DIR/$tdir
1026         f=$DIR/$tdir/$tfile
1027
1028         # New files are not dirty
1029         cp -p /etc/passwd $f
1030         check_hsm_flags $f "0x00000000"
1031
1032         # For test, we simulate an archived file.
1033         $LFS hsm_set --exists $f ||
1034                 error "user could not change hsm flags"
1035         check_hsm_flags $f "0x00000001"
1036
1037         # Reading a file, does not set dirty
1038         cat $f > /dev/null || error "could not read file"
1039         check_hsm_flags $f "0x00000001"
1040
1041         # Open for write without modifying data, does not set dirty
1042         openfile -f O_WRONLY $f || error "could not open test file"
1043         check_hsm_flags $f "0x00000001"
1044
1045         # Append to a file sets it dirty
1046         cp -p /etc/passwd $f.append || error "could not create file"
1047         $LFS hsm_set --exists $f.append ||
1048                 error "user could not change hsm flags"
1049         dd if=/etc/passwd of=$f.append bs=1 count=3\
1050            conv=notrunc oflag=append status=noxfer ||
1051                 file_creation_failure dd $f.append $?
1052         check_hsm_flags $f.append "0x00000003"
1053
1054         # Modify a file sets it dirty
1055         cp -p /etc/passwd $f.modify || error "could not create file"
1056         $LFS hsm_set --exists $f.modify ||
1057                 error "user could not change hsm flags"
1058         dd if=/dev/zero of=$f.modify bs=1 count=3\
1059            conv=notrunc status=noxfer ||
1060                 file_creation_failure dd $f.modify $?
1061         check_hsm_flags $f.modify "0x00000003"
1062
1063         # Open O_TRUNC sets dirty
1064         cp -p /etc/passwd $f.trunc || error "could not create file"
1065         $LFS hsm_set --exists $f.trunc ||
1066                 error "user could not change hsm flags"
1067         cp /etc/group $f.trunc || error "could not override a file"
1068         check_hsm_flags $f.trunc "0x00000003"
1069
1070         # Mmapped a file sets dirty
1071         cp -p /etc/passwd $f.mmap || error "could not create file"
1072         $LFS hsm_set --exists $f.mmap ||
1073                 error "user could not change hsm flags"
1074         multiop $f.mmap OSMWUc || error "could not mmap a file"
1075         check_hsm_flags $f.mmap "0x00000003"
1076 }
1077 run_test 3 "Check file dirtyness when opening for write"
1078
1079 test_4() {
1080         local f=$DIR/$tdir/$tfile
1081         local fid=$(create_small_file $f)
1082
1083         $LFS hsm_cancel $f
1084         local st=$(get_request_state $fid CANCEL)
1085         [[ -z "$st" ]] || error "hsm_cancel must not be registered (state=$st)"
1086 }
1087 run_test 4 "Useless cancel must not be registered"
1088
1089 test_8() {
1090         # test needs a running copytool
1091         copytool_setup
1092
1093         mkdir -p $DIR/$tdir
1094         local f=$DIR/$tdir/$tfile
1095         local fid=$(copy_file /etc/passwd $f)
1096         $LFS hsm_archive $f
1097         wait_request_state $fid ARCHIVE SUCCEED
1098
1099         check_hsm_flags $f "0x00000009"
1100
1101         copytool_cleanup
1102 }
1103 run_test 8 "Test default archive number"
1104
1105 test_9() {
1106         # we do not use the default one to be sure
1107         local new_an=$((HSM_ARCHIVE_NUMBER + 1))
1108         copytool_cleanup
1109         copytool_setup $SINGLEAGT $MOUNT $new_an
1110
1111         # give time for CT to register with MDTs
1112         sleep $(($MDSCOUNT*2))
1113         local uuid=$(get_agent_uuid $(facet_active_host $SINGLEAGT))
1114         check_agent_registered $uuid
1115
1116         mkdir -p $DIR/$tdir
1117         local f=$DIR/$tdir/$tfile
1118         local fid=$(copy_file /etc/passwd $f)
1119         $LFS hsm_archive --archive $new_an $f
1120         wait_request_state $fid ARCHIVE SUCCEED
1121
1122         check_hsm_flags $f "0x00000009"
1123
1124         copytool_cleanup
1125 }
1126 run_test 9 "Use of explicit archive number, with dedicated copytool"
1127
1128 test_9a() {
1129         needclients 3 || return 0
1130
1131         local n
1132         local file
1133         local fid
1134
1135         copytool_cleanup $(comma_list $(agts_nodes))
1136
1137         # start all of the copytools
1138         for n in $(seq $AGTCOUNT); do
1139                 copytool_setup agt$n
1140         done
1141
1142         trap "copytool_cleanup $(comma_list $(agts_nodes))" EXIT
1143         # archive files
1144         for n in $(seq $AGTCOUNT); do
1145                 file=$DIR/$tdir/$tfile.$n
1146                 fid=$(create_small_file $file)
1147
1148                 $LFS hsm_archive $file || error "could not archive file $file"
1149                 wait_request_state $fid ARCHIVE SUCCEED
1150                 check_hsm_flags $file "0x00000009"
1151         done
1152
1153         trap - EXIT
1154         copytool_cleanup $(comma_list $(agts_nodes))
1155 }
1156 run_test 9a "Multiple remote agents"
1157
1158 test_10a() {
1159         # test needs a running copytool
1160         copytool_setup
1161
1162         mkdir -p $DIR/$tdir/d1
1163         local f=$DIR/$tdir/$tfile
1164         local fid=$(copy_file /etc/hosts $f)
1165         $LFS hsm_archive -a $HSM_ARCHIVE_NUMBER $f ||
1166                 error "hsm_archive failed"
1167         wait_request_state $fid ARCHIVE SUCCEED
1168
1169         local AFILE=$(do_facet $SINGLEAGT ls $HSM_ARCHIVE'/*/*/*/*/*/*/'$fid) ||
1170                 error "fid $fid not in archive $HSM_ARCHIVE"
1171         echo "Verifying content"
1172         do_facet $SINGLEAGT diff $f $AFILE || error "archived file differs"
1173         echo "Verifying hsm state "
1174         check_hsm_flags $f "0x00000009"
1175
1176         echo "Verifying archive number is $HSM_ARCHIVE_NUMBER"
1177         local st=$(get_hsm_archive_id $f)
1178         [[ $st == $HSM_ARCHIVE_NUMBER ]] ||
1179                 error "Wrong archive number, $st != $HSM_ARCHIVE_NUMBER"
1180
1181         copytool_cleanup
1182
1183 }
1184 run_test 10a "Archive a file"
1185
1186 test_10b() {
1187         # test needs a running copytool
1188         copytool_setup
1189
1190         mkdir -p $DIR/$tdir
1191         local f=$DIR/$tdir/$tfile
1192         local fid=$(copy_file /etc/hosts $f)
1193         $LFS hsm_archive $f || error "archive request failed"
1194         wait_request_state $fid ARCHIVE SUCCEED
1195
1196         $LFS hsm_archive $f || error "archive of non dirty file failed"
1197         local cnt=$(get_request_count $fid ARCHIVE)
1198         [[ "$cnt" == "1" ]] ||
1199                 error "archive of non dirty file must not make a request"
1200
1201         copytool_cleanup
1202 }
1203 run_test 10b "Archive of non dirty file must work without doing request"
1204
1205 test_10c() {
1206         # test needs a running copytool
1207         copytool_setup
1208
1209         mkdir -p $DIR/$tdir
1210         local f=$DIR/$tdir/$tfile
1211         local fid=$(copy_file /etc/hosts $f)
1212         $LFS hsm_set --noarchive $f
1213         $LFS hsm_archive $f && error "archive a noarchive file must fail"
1214
1215         copytool_cleanup
1216 }
1217 run_test 10c "Check forbidden archive"
1218
1219 test_10d() {
1220         # test needs a running copytool
1221         copytool_setup
1222
1223         mkdir -p $DIR/$tdir
1224         local f=$DIR/$tdir/$tfile
1225         local fid=$(copy_file /etc/hosts $f)
1226         $LFS hsm_archive $f || error "cannot archive $f"
1227         wait_request_state $fid ARCHIVE SUCCEED
1228
1229         local ar=$(get_hsm_archive_id $f)
1230         local dflt=$(get_hsm_param default_archive_id)
1231         [[ $ar == $dflt ]] ||
1232                 error "archived file is not on default archive: $ar != $dflt"
1233
1234         copytool_cleanup
1235 }
1236 run_test 10d "Archive a file on the default archive id"
1237
1238 test_11a() {
1239         mkdir -p $DIR/$tdir
1240         copy2archive /etc/hosts $tdir/$tfile
1241         local f=$DIR/$tdir/$tfile
1242
1243         import_file $tdir/$tfile $f
1244         echo -n "Verifying released state: "
1245         check_hsm_flags $f "0x0000000d"
1246
1247         local LSZ=$(stat -c "%s" $f)
1248         local ASZ=$(do_facet $SINGLEAGT stat -c "%s" $HSM_ARCHIVE/$tdir/$tfile)
1249
1250         echo "Verifying imported size $LSZ=$ASZ"
1251         [[ $LSZ -eq $ASZ ]] || error "Incorrect size $LSZ != $ASZ"
1252         echo -n "Verifying released pattern: "
1253         local PTRN=$($GETSTRIPE -L $f)
1254         echo $PTRN
1255         [[ $PTRN == 80000001 ]] || error "Is not released"
1256         local fid=$(path2fid $f)
1257         echo "Verifying new fid $fid in archive"
1258
1259         local AFILE=$(do_facet $SINGLEAGT ls $HSM_ARCHIVE'/*/*/*/*/*/*/'$fid) ||
1260                 error "fid $fid not in archive $HSM_ARCHIVE"
1261 }
1262 run_test 11a "Import a file"
1263
1264 test_11b() {
1265         # test needs a running copytool
1266         copytool_setup
1267
1268         mkdir -p $DIR/$tdir
1269         local f=$DIR/$tdir/$tfile
1270         local fid=$(copy_file /etc/hosts $f)
1271         $LFS hsm_archive -a $HSM_ARCHIVE_NUMBER $f ||
1272                 error "hsm_archive failed"
1273         wait_request_state $fid ARCHIVE SUCCEED
1274
1275         local FILE_HASH=$(md5sum $f)
1276         rm -f $f
1277
1278         import_file $fid $f
1279
1280         echo "$FILE_HASH" | md5sum -c
1281
1282         [[ $? -eq 0 ]] || error "Restored file differs"
1283
1284         copytool_cleanup
1285 }
1286 run_test 11b "Import a deleted file using its FID"
1287
1288 test_12a() {
1289         # test needs a running copytool
1290         copytool_setup
1291
1292         mkdir -p $DIR/$tdir
1293         copy2archive /etc/hosts $tdir/$tfile
1294
1295         local f=$DIR/$tdir/$tfile
1296         import_file $tdir/$tfile $f
1297         local f2=$DIR2/$tdir/$tfile
1298         echo "Verifying released state: "
1299         check_hsm_flags $f2 "0x0000000d"
1300
1301         local fid=$(path2fid $f2)
1302         $LFS hsm_restore $f2
1303         wait_request_state $fid RESTORE SUCCEED
1304
1305         echo "Verifying file state: "
1306         check_hsm_flags $f2 "0x00000009"
1307
1308         do_facet $SINGLEAGT diff -q $HSM_ARCHIVE/$tdir/$tfile $f
1309
1310         [[ $? -eq 0 ]] || error "Restored file differs"
1311
1312         copytool_cleanup
1313 }
1314 run_test 12a "Restore an imported file explicitly"
1315
1316 test_12b() {
1317         # test needs a running copytool
1318         copytool_setup
1319
1320         mkdir -p $DIR/$tdir
1321         copy2archive /etc/hosts $tdir/$tfile
1322
1323         local f=$DIR/$tdir/$tfile
1324         import_file $tdir/$tfile $f
1325         echo "Verifying released state: "
1326         check_hsm_flags $f "0x0000000d"
1327
1328         cat $f > /dev/null || error "File read failed"
1329
1330         echo "Verifying file state after restore: "
1331         check_hsm_flags $f "0x00000009"
1332
1333         do_facet $SINGLEAGT diff -q $HSM_ARCHIVE/$tdir/$tfile $f
1334
1335         [[ $? -eq 0 ]] || error "Restored file differs"
1336
1337         copytool_cleanup
1338 }
1339 run_test 12b "Restore an imported file implicitly"
1340
1341 test_12c() {
1342         [ "$OSTCOUNT" -lt "2" ] && skip_env "needs >= 2 OSTs" && return
1343
1344         # test needs a running copytool
1345         copytool_setup
1346
1347         local f=$DIR/$tdir/$tfile
1348         mkdir -p $DIR/$tdir
1349         $LFS setstripe -c 2 "$f"
1350         local fid
1351         fid=$(make_custom_file_for_progress $f 5)
1352         [ $? != 0 ] && skip "not enough free space" && return
1353
1354         local FILE_CRC=$(md5sum $f)
1355
1356         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1357         wait_request_state $fid ARCHIVE SUCCEED
1358         $LFS hsm_release $f || error "release $f failed"
1359
1360         echo "$FILE_CRC" | md5sum -c
1361
1362         [[ $? -eq 0 ]] || error "Restored file differs"
1363
1364         copytool_cleanup
1365 }
1366 run_test 12c "Restore a file with stripe of 2"
1367
1368 test_12d() {
1369         # test needs a running copytool
1370         copytool_setup
1371
1372         mkdir -p $DIR/$tdir
1373
1374         local f=$DIR/$tdir/$tfile
1375         local fid=$(copy_file /etc/hosts $f)
1376         $LFS hsm_restore $f || error "restore of non archived file failed"
1377         local cnt=$(get_request_count $fid RESTORE)
1378         [[ "$cnt" == "0" ]] ||
1379                 error "restore non archived must not make a request"
1380         $LFS hsm_archive $f ||
1381                 error "archive request failed"
1382         wait_request_state $fid ARCHIVE SUCCEED
1383         $LFS hsm_restore $f ||
1384                 error "restore of non released file failed"
1385         local cnt=$(get_request_count $fid RESTORE)
1386         [[ "$cnt" == "0" ]] ||
1387                 error "restore a non dirty file must not make a request"
1388
1389         copytool_cleanup
1390 }
1391 run_test 12d "Restore of a non archived, non released file must work"\
1392                 " without doing request"
1393
1394 test_12e() {
1395         # test needs a running copytool
1396         copytool_setup
1397
1398         mkdir -p $DIR/$tdir $HSM_ARCHIVE/$tdir
1399         local f=$DIR/$tdir/$tfile
1400         local fid=$(copy_file /etc/hosts $f)
1401         $LFS hsm_archive $f || error "archive request failed"
1402         wait_request_state $fid ARCHIVE SUCCEED
1403
1404         # make file dirty
1405         cat /etc/hosts >> $f
1406         sync
1407         $LFS hsm_state $f
1408
1409         $LFS hsm_restore $f && error "restore a dirty file must fail"
1410
1411         copytool_cleanup
1412 }
1413 run_test 12e "Check forbidden restore"
1414
1415 test_12f() {
1416         # test needs a running copytool
1417         copytool_setup
1418
1419         mkdir -p $DIR/$tdir
1420         local f=$DIR/$tdir/$tfile
1421         local fid=$(copy_file /etc/hosts $f)
1422
1423         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1424         wait_request_state $fid ARCHIVE SUCCEED
1425         $LFS hsm_release $f || error "release of $f failed"
1426         $LFS hsm_restore $f
1427         wait_request_state $fid RESTORE SUCCEED
1428
1429         echo -n "Verifying file state: "
1430         check_hsm_flags $f "0x00000009"
1431
1432         diff -q /etc/hosts $f
1433
1434         [[ $? -eq 0 ]] || error "Restored file differs"
1435
1436         copytool_cleanup
1437 }
1438 run_test 12f "Restore a released file explicitly"
1439
1440 test_12g() {
1441         # test needs a running copytool
1442         copytool_setup
1443
1444         mkdir -p $DIR/$tdir
1445         local f=$DIR/$tdir/$tfile
1446         local fid=$(copy_file /etc/hosts $f)
1447
1448         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1449         wait_request_state $fid ARCHIVE SUCCEED
1450         $LFS hsm_release $f || error "release of $f failed"
1451
1452         diff -q /etc/hosts $f
1453         local st=$?
1454
1455         # we check we had a restore done
1456         wait_request_state $fid RESTORE SUCCEED
1457
1458         [[ $st -eq 0 ]] || error "Restored file differs"
1459
1460         copytool_cleanup
1461 }
1462 run_test 12g "Restore a released file implicitly"
1463
1464 test_12h() {
1465         needclients 2 || return 0
1466
1467         # test needs a running copytool
1468         copytool_setup
1469
1470         mkdir -p $DIR/$tdir
1471         local f=$DIR/$tdir/$tfile
1472         local fid=$(copy_file /etc/hosts $f)
1473
1474         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1475         wait_request_state $fid ARCHIVE SUCCEED
1476         $LFS hsm_release $f || error "release of $f failed"
1477
1478         do_node $CLIENT2 diff -q /etc/hosts $f
1479         local st=$?
1480
1481         # we check we had a restore done
1482         wait_request_state $fid RESTORE SUCCEED
1483
1484         [[ $st -eq 0 ]] || error "Restored file differs"
1485
1486         copytool_cleanup
1487 }
1488 run_test 12h "Restore a released file implicitly from a second node"
1489
1490 test_12m() {
1491         # test needs a running copytool
1492         copytool_setup
1493
1494         mkdir -p $DIR/$tdir
1495         local f=$DIR/$tdir/$tfile
1496         local fid=$(copy_file /etc/passwd $f)
1497         $LFS hsm_archive $f || error "archive of $f failed"
1498         wait_request_state $fid ARCHIVE SUCCEED
1499
1500         $LFS hsm_release $f || error "release of $f failed"
1501
1502         cmp /etc/passwd $f
1503
1504         [[ $? -eq 0 ]] || error "Restored file differs"
1505
1506         copytool_cleanup
1507 }
1508 run_test 12m "Archive/release/implicit restore"
1509
1510 test_12n() {
1511         # test needs a running copytool
1512         copytool_setup
1513
1514         mkdir -p $DIR/$tdir
1515         copy2archive /etc/hosts $tdir/$tfile
1516
1517         local f=$DIR/$tdir/$tfile
1518         import_file $tdir/$tfile $f
1519
1520         do_facet $SINGLEAGT cmp /etc/hosts $f ||
1521                 error "Restored file differs"
1522
1523         $LFS hsm_release $f || error "release of $f failed"
1524
1525         copytool_cleanup
1526 }
1527 run_test 12n "Import/implicit restore/release"
1528
1529 test_12o() {
1530         # test needs a running copytool
1531         copytool_setup
1532
1533         mkdir -p $DIR/$tdir
1534         local f=$DIR/$tdir/$tfile
1535         local fid=$(copy_file /etc/hosts $f)
1536
1537         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1538         wait_request_state $fid ARCHIVE SUCCEED
1539         $LFS hsm_release $f || error "release of $f failed"
1540
1541 #define OBD_FAIL_MDS_HSM_SWAP_LAYOUTS           0x152
1542         do_facet $SINGLEMDS lctl set_param fail_loc=0x152
1543
1544         # set no retry action mode
1545         cdt_set_no_retry
1546
1547         diff -q /etc/hosts $f
1548         local st=$?
1549
1550         # we check we had a restore failure
1551         wait_request_state $fid RESTORE FAILED
1552
1553         [[ $st -eq 0 ]] && error "Restore must fail"
1554
1555         # remove no retry action mode
1556         cdt_clear_no_retry
1557
1558         # check file is still released
1559         check_hsm_flags $f "0x0000000d"
1560
1561         # retry w/o failure injection
1562         do_facet $SINGLEMDS lctl set_param fail_loc=0
1563
1564         # to be sure previous RESTORE result is gone
1565         cdt_purge
1566         wait_for_grace_delay
1567
1568         diff -q /etc/hosts $f
1569         st=$?
1570
1571         # we check we had a restore done
1572         wait_request_state $fid RESTORE SUCCEED
1573
1574         [[ $st -eq 0 ]] || error "Restored file differs"
1575
1576         copytool_cleanup
1577 }
1578 run_test 12o "Layout-swap failure during Restore leaves file released"
1579
1580 test_12p() {
1581         # test needs a running copytool
1582         copytool_setup
1583
1584         mkdir $DIR/$tdir
1585         local f=$DIR/$tdir/$tfile
1586         local fid=$(copy_file /etc/hosts $f)
1587
1588         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1589         wait_request_state $fid ARCHIVE SUCCEED
1590         do_facet $SINGLEAGT cat $f > /dev/null || error "cannot cat $f"
1591         $LFS hsm_release $f || error "cannot release $f"
1592         do_facet $SINGLEAGT cat $f > /dev/null || error "cannot cat $f"
1593         $LFS hsm_release $f || error "cannot release $f"
1594         do_facet $SINGLEAGT cat $f > /dev/null || error "cannot cat $f"
1595
1596         copytool_cleanup
1597 }
1598 run_test 12p "implicit restore of a file on copytool mount point"
1599
1600 cleanup_test_12q() {
1601         trap 0
1602         zconf_umount $(facet_host $SINGLEAGT) $MOUNT3 ||
1603                 error "cannot umount $MOUNT3 on $SINGLEAGT"
1604 }
1605
1606 test_12q() {
1607         [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.7.58) ] &&
1608                 skip "need MDS version at least 2.7.58" && return 0
1609
1610         zconf_mount $(facet_host $SINGLEAGT) $MOUNT3 ||
1611                 error "cannot mount $MOUNT3 on $SINGLEAGT"
1612
1613         trap cleanup_test_12q EXIT
1614
1615         # test needs a running copytool
1616         copytool_setup $SINGLEAGT $MOUNT3
1617
1618         local f=$DIR/$tdir/$tfile
1619         local f2=$DIR2/$tdir/$tfile
1620         local fid=$(create_small_file $f)
1621         local orig_size=$(stat -c "%s" $f)
1622
1623         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1624         wait_request_state $fid ARCHIVE SUCCEED
1625
1626         $LFS hsm_release $f || error "could not release file"
1627         check_hsm_flags $f "0x0000000d"
1628
1629         kill_copytools
1630         wait_copytools || error "copytool failed to stop"
1631
1632         cat $f > /dev/null &
1633
1634         # wait a bit to allow implicit restore request to be handled.
1635         # if not, next stat would also block on layout-lock.
1636         sleep 5
1637
1638         local size=$(stat -c "%s" $f2)
1639         [ $size -eq $orig_size ] ||
1640                 error "$f2: wrong size after archive: $size != $orig_size"
1641
1642         HSM_ARCHIVE_PURGE=false copytool_setup $SINGLEAGT /mnt/lustre3
1643
1644         wait
1645
1646         size=$(stat -c "%s" $f)
1647         [ $size -eq $orig_size ] ||
1648                 error "$f: wrong size after restore: $size != $orig_size"
1649
1650         size=$(stat -c "%s" $f2)
1651         [ $size -eq $orig_size ] ||
1652                 error "$f2: wrong size after restore: $size != $orig_size"
1653
1654         :>$f
1655
1656         size=$(stat -c "%s" $f)
1657         [ $size -eq 0 ] ||
1658                 error "$f: wrong size after overwrite: $size != 0"
1659
1660         size=$(stat -c "%s" $f2)
1661         [ $size -eq 0 ] ||
1662                 error "$f2: wrong size after overwrite: $size != 0"
1663
1664         copytool_cleanup
1665         zconf_umount $(facet_host $SINGLEAGT) $MOUNT3 ||
1666                 error "cannot umount $MOUNT3 on $SINGLEAGT"
1667 }
1668 run_test 12q "file attributes are refreshed after restore"
1669
1670 test_13() {
1671         # test needs a running copytool
1672         copytool_setup
1673
1674         local ARC_SUBDIR="import.orig"
1675         local d=""
1676         local f=""
1677
1678         # populate directory to be imported
1679         for d in $(seq 1 10); do
1680                 local CURR_DIR="$HSM_ARCHIVE/$ARC_SUBDIR/dir.$d"
1681                 do_facet $SINGLEAGT mkdir -p "$CURR_DIR"
1682                 for f in $(seq 1 10); do
1683                         CURR_FILE="$CURR_DIR/$tfile.$f"
1684                         # write file-specific data
1685                         do_facet $SINGLEAGT \
1686                                 "echo d=$d, f=$f, dir=$CURR_DIR, "\
1687                                         "file=$CURR_FILE > $CURR_FILE"
1688                 done
1689         done
1690         # import to Lustre
1691         import_file "$ARC_SUBDIR" $DIR/$tdir
1692         # diff lustre content and origin (triggers file restoration)
1693         # there must be 10x10 identical files, and no difference
1694         local cnt_ok=$(do_facet $SINGLEAGT diff -rs $HSM_ARCHIVE/$ARC_SUBDIR \
1695                        $DIR/$tdir/$ARC_SUBDIR | grep identical | wc -l)
1696         local cnt_diff=$(do_facet $SINGLEAGT diff -r $HSM_ARCHIVE/$ARC_SUBDIR \
1697                          $DIR/$tdir/$ARC_SUBDIR | wc -l)
1698
1699         [ $cnt_diff -eq 0 ] ||
1700                 error "$cnt_diff imported files differ from read data"
1701         [ $cnt_ok -eq 100 ] ||
1702                 error "not enough identical files ($cnt_ok != 100)"
1703
1704         copytool_cleanup
1705 }
1706 run_test 13 "Recursively import and restore a directory"
1707
1708 test_14() {
1709         # test needs a running copytool
1710         copytool_setup
1711
1712         # archive a file
1713         local f=$DIR/$tdir/$tfile
1714         local fid=$(create_small_file $f)
1715         local sum=$(md5sum $f | awk '{print $1}')
1716         $LFS hsm_archive $f || error "could not archive file"
1717         wait_request_state $fid ARCHIVE SUCCEED
1718
1719         # create released file (simulate llapi_hsm_import call)
1720         local fid2=$(create_empty_file "$f")
1721         $LFS hsm_set --archived --exists $f || error "could not force hsm flags"
1722         $LFS hsm_release $f || error "could not release file"
1723
1724         # rebind the archive to the newly created file
1725         echo "rebind $fid to $fid2"
1726
1727         do_facet $SINGLEAGT \
1728                 "$HSMTOOL --archive $HSM_ARCHIVE_NUMBER --hsm-root $HSM_ARCHIVE\
1729                  --rebind $fid $fid2 $DIR" || error "could not rebind file"
1730
1731         # restore file and compare md5sum
1732         local sum2=$(md5sum $f | awk '{print $1}')
1733
1734         [[ $sum == $sum2 ]] || error "md5sum mismatch after restore"
1735
1736         copytool_cleanup
1737 }
1738 run_test 14 "Rebind archived file to a new fid"
1739
1740 test_15() {
1741         # test needs a running copytool
1742         copytool_setup
1743
1744         # archive files
1745         local f=$DIR/$tdir/$tfile
1746         local count=5
1747         local tmpfile=$SHARED_DIRECTORY/tmp.$$
1748
1749         local fids=()
1750         local sums=()
1751         for i in $(seq 1 $count); do
1752                 fids[$i]=$(create_small_file $f.$i)
1753                 sums[$i]=$(md5sum $f.$i | awk '{print $1}')
1754                 $LFS hsm_archive $f.$i || error "could not archive file"
1755         done
1756         wait_all_done $(($count*60))
1757
1758         :>$tmpfile
1759         # delete the files
1760         for i in $(seq 1 $count); do
1761                 local fid2=$(create_empty_file "${f}.${i}")
1762                 # add the rebind operation to the list
1763                 echo ${fids[$i]} $fid2 >> $tmpfile
1764
1765                 # set it released (simulate llapi_hsm_import call)
1766                 $LFS hsm_set --archived --exists $f.$i ||
1767                         error "could not force hsm flags"
1768                 $LFS hsm_release $f.$i || error "could not release file"
1769         done
1770         nl=$(wc -l < $tmpfile)
1771         [[ $nl == $count ]] || error "$nl files in list, $count expected"
1772
1773         echo "rebind list of files"
1774         do_facet $SINGLEAGT \
1775                 "$HSMTOOL --archive $HSM_ARCHIVE_NUMBER --hsm-root $HSM_ARCHIVE\
1776                  --rebind $tmpfile $DIR" || error "could not rebind file list"
1777
1778         # restore files and compare md5sum
1779         for i in $(seq 1 $count); do
1780                 local sum2=$(md5sum $f.$i | awk '{print $1}')
1781                 [[ $sum2 == ${sums[$i]} ]] ||
1782                     error "md5sum mismatch after restore ($sum2 != ${sums[$i]})"
1783         done
1784
1785         rm -f $tmpfile
1786         copytool_cleanup
1787 }
1788 run_test 15 "Rebind a list of files"
1789
1790 test_16() {
1791         # test needs a running copytool
1792         copytool_setup
1793
1794         local ref=/tmp/ref
1795         # create a known size file so we can verify transfer speed
1796         # 20 MB <-> 20s
1797         local goal=20
1798         dd if=/dev/zero of=$ref bs=1M count=20
1799
1800         mkdir -p $DIR/$tdir
1801         local f=$DIR/$tdir/$tfile
1802         local fid=$(copy_file $ref $f)
1803         rm $ref
1804         local start=$(date +%s)
1805         $LFS hsm_archive $f
1806         wait_request_state $fid ARCHIVE SUCCEED
1807         local end=$(date +%s)
1808         # Add 1 to account for rounding errors between start and end (LU-8155)
1809         local duration=$((end - start + 1))
1810
1811         [[ $duration -ge $((goal - 1)) ]] ||
1812                 error "Transfer is too fast $duration < $goal"
1813
1814         copytool_cleanup
1815 }
1816 run_test 16 "Test CT bandwith control option"
1817
1818 test_20() {
1819         local f=$DIR/$tdir/$tfile
1820         create_empty_file "$f"
1821
1822         # Could not release a non-archived file
1823         $LFS hsm_release $f && error "release should not succeed"
1824
1825         # For following tests, we must test them with HS_ARCHIVED set
1826         $LFS hsm_set --exists --archived $f || error "could not add flag"
1827
1828         # Could not release a file if no-release is set
1829         $LFS hsm_set --norelease $f || error "could not add flag"
1830         $LFS hsm_release $f && error "release should not succeed"
1831         $LFS hsm_clear --norelease $f || error "could not remove flag"
1832
1833         # Could not release a file if lost
1834         $LFS hsm_set --lost $f || error "could not add flag"
1835         $LFS hsm_release $f && error "release should not succeed"
1836         $LFS hsm_clear --lost $f || error "could not remove flag"
1837
1838         # Could not release a file if dirty
1839         $LFS hsm_set --dirty $f || error "could not add flag"
1840         $LFS hsm_release $f && error "release should not succeed"
1841         $LFS hsm_clear --dirty $f || error "could not remove flag"
1842 }
1843 run_test 20 "Release is not permitted"
1844
1845 test_21() {
1846         # test needs a running copytool
1847         copytool_setup
1848
1849         local f=$DIR/$tdir/test_release
1850
1851         # Create a file and check its states
1852         local fid=$(create_small_file $f)
1853         check_hsm_flags $f "0x00000000"
1854
1855         # LU-4388/LU-4389 - ZFS does not report full number of blocks
1856         # used until file is flushed to disk
1857         if [  $(facet_fstype ost1) == "zfs" ]; then
1858             # this causes an OST_SYNC rpc to be sent
1859             dd if=/dev/zero of=$f bs=512 count=1 oflag=sync conv=notrunc,fsync
1860             # clear locks to reread file data
1861             cancel_lru_locks osc
1862         fi
1863
1864         local orig_size=$(stat -c "%s" $f)
1865         local orig_blocks=$(stat -c "%b" $f)
1866
1867         start_full_debug_logging
1868
1869         $LFS hsm_archive $f || error "could not archive file"
1870         wait_request_state $fid ARCHIVE SUCCEED
1871
1872         local blocks=$(stat -c "%b" $f)
1873         [ $blocks -eq $orig_blocks ] ||
1874                 error "$f: wrong block number after archive: " \
1875                       "$blocks != $orig_blocks"
1876         local size=$(stat -c "%s" $f)
1877         [ $size -eq $orig_size ] ||
1878                 error "$f: wrong size after archive: $size != $orig_size"
1879
1880         # Release and check states
1881         $LFS hsm_release $f || error "could not release file"
1882         check_hsm_flags $f "0x0000000d"
1883
1884         blocks=$(stat -c "%b" $f)
1885         [ $blocks -gt 5 ] &&
1886                 error "$f: too many blocks after release: $blocks > 5"
1887         size=$(stat -c "%s" $f)
1888         [ $size -ne $orig_size ] &&
1889                 error "$f: wrong size after release: $size != $orig_size"
1890
1891         # Check we can release an file without stripe info
1892         f=$f.nolov
1893         $MCREATE $f
1894         fid=$(path2fid $f)
1895         check_hsm_flags $f "0x00000000"
1896         $LFS hsm_archive $f || error "could not archive file"
1897         wait_request_state $fid ARCHIVE SUCCEED
1898
1899         # Release and check states
1900         $LFS hsm_release $f || error "could not release file"
1901         check_hsm_flags $f "0x0000000d"
1902
1903         # Release again a file that is already released is OK
1904         $LFS hsm_release $f || fail "second release should succeed"
1905         check_hsm_flags $f "0x0000000d"
1906
1907         stop_full_debug_logging
1908
1909         copytool_cleanup
1910 }
1911 run_test 21 "Simple release tests"
1912
1913 test_22() {
1914         # test needs a running copytool
1915         copytool_setup
1916
1917         local f=$DIR/$tdir/test_release
1918         local swap=$DIR/$tdir/test_swap
1919
1920         # Create a file and check its states
1921         local fid=$(create_small_file $f)
1922         check_hsm_flags $f "0x00000000"
1923
1924         $LFS hsm_archive $f || error "could not archive file"
1925         wait_request_state $fid ARCHIVE SUCCEED
1926
1927         # Release and check states
1928         $LFS hsm_release $f || error "could not release file"
1929         check_hsm_flags $f "0x0000000d"
1930
1931         create_small_file $swap
1932         $LFS swap_layouts $swap $f && error "swap_layouts should failed"
1933
1934         true
1935         copytool_cleanup
1936 }
1937 run_test 22 "Could not swap a release file"
1938
1939 test_23() {
1940         # test needs a running copytool
1941         copytool_setup
1942
1943         local f=$DIR/$tdir/test_mtime
1944
1945         # Create a file and check its states
1946         local fid=$(create_small_file $f)
1947         check_hsm_flags $f "0x00000000"
1948
1949         $LFS hsm_archive $f || error "could not archive file"
1950         wait_request_state $fid ARCHIVE SUCCEED
1951
1952         # Set modification time in the past
1953         touch -m -a -d @978261179 $f
1954
1955         # Release and check states
1956         $LFS hsm_release $f || error "could not release file"
1957         check_hsm_flags $f "0x0000000d"
1958
1959         local MTIME=$(stat -c "%Y" $f)
1960         local ATIME=$(stat -c "%X" $f)
1961         [ $MTIME -eq "978261179" ] || fail "bad mtime: $MTIME"
1962         [ $ATIME -eq "978261179" ] || fail "bad atime: $ATIME"
1963
1964         copytool_cleanup
1965 }
1966 run_test 23 "Release does not change a/mtime (utime)"
1967
1968 test_24a() {
1969         local file=$DIR/$tdir/$tfile
1970         local fid
1971         local atime0
1972         local atime1
1973         local mtime0
1974         local mtime1
1975         local ctime0
1976         local ctime1
1977
1978         # test needs a running copytool
1979         copytool_setup
1980
1981         fid=$(create_small_file $file)
1982
1983         # Create a file and check its states
1984         check_hsm_flags $file "0x00000000"
1985
1986         # Ensure atime is less than mtime and ctime.
1987         sleep 1
1988         echo >> $file
1989
1990         atime0=$(stat -c "%X" $file)
1991         mtime0=$(stat -c "%Y" $file)
1992         ctime0=$(stat -c "%Z" $file)
1993
1994         [ $atime0 -lt $mtime0 ] ||
1995                 error "atime $atime0 is not less than mtime $mtime0"
1996
1997         [ $atime0 -lt $ctime0 ] ||
1998                 error "atime $atime0 is not less than ctime $ctime0"
1999
2000         # Archive should not change any timestamps.
2001         $LFS hsm_archive $file || error "cannot archive '$file'"
2002         wait_request_state $fid ARCHIVE SUCCEED
2003
2004         atime1=$(stat -c "%X" $file)
2005         mtime1=$(stat -c "%Y" $file)
2006         ctime1=$(stat -c "%Z" $file)
2007
2008         [ $atime0 -eq $atime1 ] ||
2009                 error "archive changed atime from $atime0 to $atime1"
2010
2011         [ $mtime0 -eq $mtime1 ] ||
2012                 error "archive changed mtime from $mtime0 to $mtime1"
2013
2014         [ $ctime0 -eq $ctime1 ] ||
2015                 error "archive changed ctime from $ctime0 to $ctime1"
2016
2017         # Release should not change any timestamps.
2018         $LFS hsm_release $file || error "cannot release '$file'"
2019         check_hsm_flags $file "0x0000000d"
2020
2021         atime1=$(stat -c "%X" $file)
2022         mtime1=$(stat -c "%Y" $file)
2023         ctime1=$(stat -c "%Z" $file)
2024
2025         [ $atime0 -eq $atime1 ] ||
2026                 error "release changed atime from $atime0 to $atime1"
2027
2028         [ $mtime0 -eq $mtime1 ] ||
2029                 error "release changed mtime from $mtime0 to $mtime1"
2030
2031         [ $ctime0 -eq $ctime1 ] ||
2032                 error "release changed ctime from $ctime0 to $ctime1"
2033
2034         # Restore should not change any timestamps.
2035         $LFS hsm_restore $file
2036         wait_request_state $fid RESTORE SUCCEED
2037
2038         atime1=$(stat -c "%X" $file)
2039         mtime1=$(stat -c "%Y" $file)
2040         ctime1=$(stat -c "%Z" $file)
2041
2042         [ $atime0 -eq $atime1 ] ||
2043                 error "restore changed atime from $atime0 to $atime1"
2044
2045         [ $mtime0 -eq $mtime1 ] ||
2046                 error "restore changed mtime from $mtime0 to $mtime1"
2047
2048         [ $ctime0 -eq $ctime1 ] ||
2049                 error "restore changed ctime from $ctime0 to $ctime1"
2050
2051         copytool_cleanup
2052
2053         # Once more, after unmount and mount.
2054         umount_client $MOUNT || error "cannot unmount '$MOUNT'"
2055         mount_client $MOUNT || error "cannot mount '$MOUNT'"
2056
2057         atime1=$(stat -c "%X" $file)
2058         mtime1=$(stat -c "%Y" $file)
2059         ctime1=$(stat -c "%Z" $file)
2060
2061         [ $atime0 -eq $atime1 ] ||
2062                 error "remount changed atime from $atime0 to $atime1"
2063
2064         [ $mtime0 -eq $mtime1 ] ||
2065                 error "remount changed mtime from $mtime0 to $mtime1"
2066
2067         [ $ctime0 -eq $ctime1 ] ||
2068                 error "remount changed ctime from $ctime0 to $ctime1"
2069 }
2070 run_test 24a "Archive, release, and restore does not change a/mtime (i/o)"
2071
2072 test_24b() {
2073         local file=$DIR/$tdir/$tfile
2074         local fid
2075         local sum0
2076         local sum1
2077         # LU-3811
2078
2079         # Test needs a running copytool.
2080         copytool_setup
2081
2082         # Check that root can do HSM actions on a regular user's file.
2083         fid=$(create_small_file $file)
2084         sum0=$(md5sum $file)
2085
2086         chown $RUNAS_ID:$RUNAS_GID $file ||
2087                 error "cannot chown '$file' to '$RUNAS_ID'"
2088
2089         chmod ugo-w $DIR/$tdir ||
2090                 error "cannot chmod '$DIR/$tdir'"
2091
2092         $LFS hsm_archive $file
2093         wait_request_state $fid ARCHIVE SUCCEED
2094
2095         $LFS hsm_release $file
2096         check_hsm_flags $file "0x0000000d"
2097
2098         $LFS hsm_restore $file
2099         wait_request_state $fid RESTORE SUCCEED
2100
2101         # Check that ordinary user can get HSM state.
2102         $RUNAS $LFS hsm_state $file ||
2103                 error "user '$RUNAS_ID' cannot get HSM state of '$file'"
2104
2105         $LFS hsm_release $file
2106         check_hsm_flags $file "0x0000000d"
2107
2108         # Check that ordinary user can accessed released file.
2109         sum1=$($RUNAS md5sum $file) ||
2110                 error "user '$RUNAS_ID' cannot read '$file'"
2111
2112         [ "$sum0" == "$sum1" ] ||
2113                 error "md5sum mismatch for '$file'"
2114
2115         copytool_cleanup
2116 }
2117 run_test 24b "root can archive, release, and restore user files"
2118
2119 cleanup_test_24c() {
2120         trap 0
2121         set_hsm_param user_request_mask RESTORE
2122         set_hsm_param group_request_mask RESTORE
2123         set_hsm_param other_request_mask RESTORE
2124 }
2125
2126 test_24c() {
2127         local file=$DIR/$tdir/$tfile
2128         local action=archive
2129         local user_save
2130         local group_save
2131         local other_save
2132
2133         # test needs a running copytool
2134         copytool_setup
2135
2136         mkdir -p $DIR/$tdir
2137
2138         # Save the default masks and check that cleanup_24c will
2139         # restore the request masks correctly.
2140         user_save=$(get_hsm_param user_request_mask)
2141         group_save=$(get_hsm_param group_request_mask)
2142         other_save=$(get_hsm_param other_request_mask)
2143
2144         [ "$user_save" == RESTORE ] ||
2145                 error "user_request_mask is '$user_save' expected 'RESTORE'"
2146         [ "$group_save" == RESTORE ] ||
2147                 error "group_request_mask is '$group_save' expected 'RESTORE'"
2148         [ "$other_save" == RESTORE ] ||
2149                 error "other_request_mask is '$other_save' expected 'RESTORE'"
2150
2151         trap cleanup_test_24c EXIT
2152
2153         # User.
2154         create_small_file $file
2155         chown $RUNAS_ID:nobody $file ||
2156                 error "cannot chown '$file' to '$RUNAS_ID:nobody'"
2157
2158         $RUNAS $LFS hsm_$action $file &&
2159                 error "$action by user should fail"
2160
2161         set_hsm_param user_request_mask $action
2162         $RUNAS $LFS hsm_$action $file ||
2163                 error "$action by user should succeed"
2164
2165         # Group.
2166         create_small_file $file
2167         chown nobody:$RUNAS_GID $file ||
2168                 error "cannot chown '$file' to 'nobody:$RUNAS_GID'"
2169
2170         $RUNAS $LFS hsm_$action $file &&
2171                 error "$action by group should fail"
2172
2173         set_hsm_param group_request_mask $action
2174         $RUNAS $LFS hsm_$action $file ||
2175                 error "$action by group should succeed"
2176
2177         # Other.
2178         create_small_file $file
2179         chown nobody:nobody $file ||
2180                 error "cannot chown '$file' to 'nobody:nobody'"
2181
2182         $RUNAS $LFS hsm_$action $file &&
2183                 error "$action by other should fail"
2184
2185         set_hsm_param other_request_mask $action
2186         $RUNAS $LFS hsm_$action $file ||
2187                 error "$action by other should succeed"
2188
2189         copytool_cleanup
2190         cleanup_test_24c
2191 }
2192 run_test 24c "check that user,group,other request masks work"
2193
2194 cleanup_test_24d() {
2195         mount -o remount,rw $MOUNT2
2196         zconf_umount $(facet_host $SINGLEAGT) "$MOUNT3"
2197 }
2198
2199 test_24d() {
2200         local file1=$DIR/$tdir/$tfile
2201         local file2=$DIR2/$tdir/$tfile
2202         local fid1
2203         local fid2
2204
2205         fid1=$(create_small_file $file1)
2206
2207         echo $fid1
2208         $LFS getstripe $file1
2209
2210         trap cleanup_test_24d EXIT
2211         zconf_mount $(facet_host $SINGLEAGT) "$MOUNT3" ||
2212                 error "cannot mount '$MOUNT3' on '$SINGLEAGT'"
2213         copytool_setup $SINGLEAGT "$MOUNT3" ||
2214                 error "unable to setup a copytool for the test"
2215
2216         mount -o remount,ro $MOUNT2
2217
2218         do_nodes $(comma_list $(nodes_list)) $LCTL clear
2219
2220         fid2=$(path2fid $file2)
2221         [ "$fid1" == "$fid2" ] ||
2222                 error "FID mismatch '$fid1' != '$fid2'"
2223
2224         $LFS hsm_archive $file2 &&
2225                 error "archive should fail on read-only mount"
2226         check_hsm_flags $file1 "0x00000000"
2227
2228         $LFS hsm_archive $file1 || error "Fail to archive $file1"
2229         wait_request_state $fid1 ARCHIVE SUCCEED
2230
2231         $LFS hsm_release $file1
2232         $LFS hsm_restore $file2
2233         wait_request_state $fid1 RESTORE SUCCEED
2234
2235         $LFS hsm_release $file1 || error "cannot release '$file1'"
2236         dd if=$file2 of=/dev/null bs=1M || error "cannot read '$file2'"
2237
2238         $LFS hsm_release $file2 &&
2239                 error "release should fail on read-only mount"
2240
2241         return 0
2242 }
2243 run_test 24d "check that read-only mounts are respected"
2244
2245 test_24e() {
2246         copytool_setup
2247
2248         local f=$DIR/$tdir/$tfile
2249         local fid
2250
2251         fid=$(create_small_file $f) || error "cannot create $f"
2252         $LFS hsm_archive $f || error "cannot archive $f"
2253         wait_request_state $fid ARCHIVE SUCCEED
2254         $LFS hsm_release $f || error "cannot release $f"
2255         while ! $LFS hsm_state $f | grep released; do
2256                 sleep 1
2257         done
2258
2259         tar -cf $TMP/$tfile.tar $DIR/$tdir || error "cannot tar $DIR/$tdir"
2260
2261         copytool_cleanup
2262 }
2263 run_test 24e "tar succeeds on HSM released files" # LU-6213
2264
2265 test_24f() {
2266
2267         # test needs a running copytool
2268         copytool_setup
2269
2270         mkdir -p $DIR/$tdir/d1
2271         local f=$DIR/$tdir/$tfile
2272         local fid=$(copy_file /etc/hosts $f)
2273         sum0=$(md5sum $f)
2274         echo $sum0
2275         $LFS hsm_archive -a $HSM_ARCHIVE_NUMBER $f ||
2276                 error "hsm_archive failed"
2277         wait_request_state $fid ARCHIVE SUCCEED
2278         $LFS hsm_release $f || error "cannot release $f"
2279         tar --xattrs -cvf $f.tar -C $DIR/$tdir $tfile
2280         rm -f $f
2281         sync
2282         tar --xattrs -xvf $f.tar -C $DIR/$tdir ||
2283                 error "Can not recover the tar contents"
2284         sum1=$(md5sum $f)
2285         echo "Sum0 = $sum0, sum1 = $sum1"
2286         [ "$sum0" == "$sum1" ] || error "md5sum mismatch for '$tfile'"
2287
2288         copytool_cleanup
2289 }
2290 run_test 24f "root can archive, release, and restore tar files"
2291
2292 test_25a() {
2293         # test needs a running copytool
2294         copytool_setup
2295
2296         mkdir -p $DIR/$tdir
2297         copy2archive /etc/hosts $tdir/$tfile
2298
2299         local f=$DIR/$tdir/$tfile
2300
2301         import_file $tdir/$tfile $f
2302
2303         $LFS hsm_set --lost $f
2304
2305         md5sum $f
2306         local st=$?
2307
2308         [[ $st == 1 ]] || error "lost file access should failed (returns $st)"
2309
2310         copytool_cleanup
2311 }
2312 run_test 25a "Restore lost file (HS_LOST flag) from import"\
2313              " (Operation not permitted)"
2314
2315 test_25b() {
2316         # test needs a running copytool
2317         copytool_setup
2318
2319         mkdir -p $DIR/$tdir
2320
2321         local f=$DIR/$tdir/$tfile
2322         local fid=$(copy_file /etc/passwd $f)
2323
2324         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2325         wait_request_state $fid ARCHIVE SUCCEED
2326
2327         $LFS hsm_release $f
2328         $LFS hsm_set --lost $f
2329         md5sum $f
2330         st=$?
2331
2332         [[ $st == 1 ]] || error "lost file access should failed (returns $st)"
2333
2334         copytool_cleanup
2335 }
2336 run_test 25b "Restore lost file (HS_LOST flag) after release"\
2337              " (Operation not permitted)"
2338
2339 test_26() {
2340         # test needs a running copytool
2341         copytool_setup
2342
2343         local f=$DIR/$tdir/$tfile
2344         local fid
2345         fid=$(make_custom_file_for_progress $f 39 1000000)
2346         [ $? != 0 ] && skip "not enough free space" && return
2347
2348         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2349         wait_request_state $fid ARCHIVE SUCCEED
2350
2351         $LFS hsm_remove $f
2352         wait_request_state $fid REMOVE SUCCEED
2353
2354         check_hsm_flags $f "0x00000000"
2355
2356         copytool_cleanup
2357 }
2358 run_test 26 "Remove the archive of a valid file"
2359
2360 cleanup_test_26a() {
2361         trap 0
2362         set_hsm_param remove_archive_on_last_unlink 0
2363         set_hsm_param loop_period $orig_loop_period
2364         set_hsm_param grace_delay $orig_grace_delay
2365         copytool_cleanup
2366 }
2367
2368 test_26a() {
2369         local raolu=$(get_hsm_param remove_archive_on_last_unlink)
2370         [[ $raolu -eq 0 ]] || error "RAoLU policy should be off"
2371
2372         # test needs a running copytool
2373         copytool_setup
2374
2375         mkdir -p $DIR/$tdir
2376         local f=$DIR/$tdir/$tfile
2377         local fid=$(copy_file /etc/passwd $f)
2378
2379         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2380         wait_request_state $fid ARCHIVE SUCCEED
2381
2382         local f2=$DIR/$tdir/${tfile}_2
2383         local fid2=$(copy_file /etc/passwd $f2)
2384
2385         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f2
2386         wait_request_state $fid2 ARCHIVE SUCCEED
2387
2388         local f3=$DIR/$tdir/${tfile}_3
2389         local fid3=$(copy_file /etc/passwd $f3)
2390
2391         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f3
2392         wait_request_state $fid3 ARCHIVE SUCCEED
2393
2394         trap cleanup_test_26a EXIT
2395
2396         # set a long grace_delay vs short loop_period
2397         local orig_loop_period=$(get_hsm_param loop_period)
2398         local orig_grace_delay=$(get_hsm_param grace_delay)
2399         set_hsm_param loop_period 10
2400         set_hsm_param grace_delay 100
2401
2402         rm -f $f
2403
2404         set_hsm_param remove_archive_on_last_unlink 1
2405
2406         ln "$f3" "$f3"_bis || error "Unable to create hard-link"
2407         rm -f $f3
2408
2409         rm -f $f2
2410
2411         set_hsm_param remove_archive_on_last_unlink 0
2412
2413         wait_request_state $fid2 REMOVE SUCCEED
2414
2415         assert_request_count $fid REMOVE 0 \
2416                 "Unexpected archived data remove request for $f"
2417         assert_request_count $fid3 REMOVE 0 \
2418                 "Unexpected archived data remove request for $f3"
2419
2420         cleanup_test_26a
2421 }
2422 run_test 26a "Remove Archive On Last Unlink (RAoLU) policy"
2423
2424 cleanup_test_26b() {
2425         trap 0
2426         set_hsm_param remove_archive_on_last_unlink 0
2427         copytool_cleanup
2428 }
2429
2430 test_26b() {
2431
2432         # test needs a running copytool
2433         copytool_setup
2434
2435         mkdir -p $DIR/$tdir
2436         local f=$DIR/$tdir/$tfile
2437         local fid=$(copy_file /etc/passwd $f)
2438
2439         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2440         wait_request_state $fid ARCHIVE SUCCEED
2441
2442         trap cleanup_test_26b EXIT
2443
2444         set_hsm_param remove_archive_on_last_unlink 1
2445
2446         cdt_shutdown
2447         cdt_check_state stopped
2448
2449         rm -f $f
2450
2451         set_hsm_param remove_archive_on_last_unlink 0
2452
2453         wait_request_state $fid REMOVE WAITING
2454
2455         cdt_enable
2456         # copytool must re-register
2457         kill_copytools
2458         wait_copytools || error "copytool failed to stop"
2459         HSM_ARCHIVE_PURGE=false copytool_setup
2460
2461         wait_request_state $fid REMOVE SUCCEED
2462
2463         cleanup_test_26b
2464 }
2465 run_test 26b "RAoLU policy when CDT off"
2466
2467 cleanup_test_26c() {
2468         trap 0
2469         set_hsm_param remove_archive_on_last_unlink 0
2470         set_hsm_param loop_period $orig_loop_period
2471         set_hsm_param grace_delay $orig_grace_delay
2472         copytool_cleanup
2473 }
2474
2475 test_26c() {
2476
2477         # test needs a running copytool
2478         copytool_setup
2479
2480         mkdir -p $DIR/$tdir
2481         local f=$DIR/$tdir/$tfile
2482         local fid=$(copy_file /etc/passwd $f)
2483
2484         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2485         wait_request_state $fid ARCHIVE SUCCEED
2486
2487         local f2=$DIR/$tdir/${tfile}_2
2488         local fid2=$(copy_file /etc/passwd $f2)
2489
2490         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f2
2491         wait_request_state $fid2 ARCHIVE SUCCEED
2492
2493         trap cleanup_test_26c EXIT
2494
2495         # set a long grace_delay vs short loop_period
2496         local orig_loop_period=$(get_hsm_param loop_period)
2497         local orig_grace_delay=$(get_hsm_param grace_delay)
2498         set_hsm_param loop_period 10
2499         set_hsm_param grace_delay 100
2500
2501         set_hsm_param remove_archive_on_last_unlink 1
2502
2503         multiop_bg_pause $f O_c || error "open $f failed"
2504         local pid=$!
2505
2506         rm -f $f
2507         rm -f $f2
2508
2509         wait_request_state $fid2 REMOVE SUCCEED
2510         assert_request_count $fid REMOVE 0 \
2511                 "Unexpected archived data remove request for $f"
2512
2513         kill -USR1 $pid || error "multiop early exit"
2514         # should reach autotest timeout if multiop fails to trap
2515         # signal, close file, and exit ...
2516         wait $pid || error
2517
2518         set_hsm_param remove_archive_on_last_unlink 0
2519
2520         wait_request_state $fid REMOVE SUCCEED
2521
2522         cleanup_test_26c
2523 }
2524 run_test 26c "RAoLU effective when file closed"
2525
2526 cleanup_test_26d() {
2527         trap 0
2528         set_hsm_param remove_archive_on_last_unlink 0
2529         set_hsm_param loop_period $orig_loop_period
2530         set_hsm_param grace_delay $orig_grace_delay
2531         copytool_cleanup
2532 }
2533
2534 test_26d() {
2535
2536         # test needs a running copytool
2537         copytool_setup
2538
2539         mkdir -p $DIR/$tdir
2540         local f=$DIR/$tdir/$tfile
2541         local fid=$(copy_file /etc/motd $f 1)
2542
2543         $LFS hsm_archive $f || error "could not archive file"
2544         wait_request_state $fid ARCHIVE SUCCEED
2545
2546         trap cleanup_test_26d EXIT
2547
2548         # set a long grace_delay vs short loop_period
2549         local orig_loop_period=$(get_hsm_param loop_period)
2550         local orig_grace_delay=$(get_hsm_param grace_delay)
2551         set_hsm_param loop_period 10
2552         set_hsm_param grace_delay 100
2553
2554         set_hsm_param remove_archive_on_last_unlink 1
2555
2556         multiop_bg_pause $f O_c || error "multiop failed"
2557         local MULTIPID=$!
2558
2559         rm -f $f
2560
2561         mds_evict_client
2562
2563         set_hsm_param remove_archive_on_last_unlink 0
2564
2565         wait_request_state $fid REMOVE SUCCEED
2566
2567         client_up || client_up || true
2568
2569         kill -USR1 $MULTIPID
2570         wait $MULTIPID || error "multiop close failed"
2571
2572         cleanup_test_26d
2573 }
2574 run_test 26d "RAoLU when Client eviction"
2575
2576 test_27a() {
2577         # test needs a running copytool
2578         copytool_setup
2579
2580         create_archive_file $tdir/$tfile
2581         local f=$DIR/$tdir/$tfile
2582         import_file $tdir/$tfile $f
2583         local fid=$(path2fid $f)
2584
2585         $LFS hsm_remove $f
2586
2587         [[ $? != 0 ]] || error "Remove of a released file should fail"
2588
2589         copytool_cleanup
2590 }
2591 run_test 27a "Remove the archive of an imported file (Operation not permitted)"
2592
2593 test_27b() {
2594         # test needs a running copytool
2595         copytool_setup
2596
2597         local f=$DIR/$tdir/$tfile
2598         local fid
2599         fid=$(make_custom_file_for_progress $f 39 1000000)
2600         [ $? != 0 ] && skip "not enough free space" && return
2601
2602         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2603         wait_request_state $fid ARCHIVE SUCCEED
2604         $LFS hsm_release $f
2605
2606         $LFS hsm_remove $f
2607
2608         [[ $? != 0 ]] || error "Remove of a released file should fail"
2609
2610         copytool_cleanup
2611 }
2612 run_test 27b "Remove the archive of a relased file (Operation not permitted)"
2613
2614 test_28() {
2615         # test needs a running copytool
2616         copytool_setup
2617
2618         local f=$DIR/$tdir/$tfile
2619         local fid
2620         fid=$(make_custom_file_for_progress $f 39 1000000)
2621         [ $? != 0 ] && skip "not enough free space" && return
2622
2623         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2624         wait_request_state $fid ARCHIVE SUCCEED
2625
2626         cdt_disable
2627         $LFS hsm_remove $f
2628
2629         rm -f $f
2630
2631         cdt_enable
2632
2633         wait_request_state $fid REMOVE SUCCEED
2634
2635         copytool_cleanup
2636 }
2637 run_test 28 "Concurrent archive/file remove"
2638
2639 test_29a() {
2640         # Tests --mntpath and --archive options
2641
2642         local archive_id=7
2643         copytool_setup $SINGLEAGT $MOUNT $archive_id
2644
2645         # Bad archive number
2646         $LFS hsm_remove -m $MOUNT -a 33 0x857765760:0x8:0x2 2>&1 |
2647                 grep "Invalid argument" ||
2648                 error "unexpected hsm_remove failure (1)"
2649
2650         # mntpath is present but file is given
2651         $LFS hsm_remove --mntpath $MOUNT --archive 30 /qwerty/uyt 2>&1 |
2652                 grep "hsm: '/qwerty/uyt' is not a valid FID" ||
2653                 error "unexpected hsm_remove failure (2)"
2654
2655         copytool_cleanup
2656 }
2657 run_test 29a "Tests --mntpath and --archive options"
2658
2659 test_29b() {
2660         # test needs a running copytool
2661         copytool_setup
2662
2663         local f=$DIR/$tdir/$tfile
2664         local fid=$(create_small_file $f)
2665
2666         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2667         wait_request_state $fid ARCHIVE SUCCEED
2668
2669         rm -f $f
2670
2671         $LFS hsm_remove -m $MOUNT -a $HSM_ARCHIVE_NUMBER $fid
2672         wait_request_state $fid REMOVE SUCCEED
2673
2674         copytool_cleanup
2675 }
2676 run_test 29b "Archive/delete/remove by FID from the archive."
2677
2678 test_29c() {
2679         # test needs a running copytool
2680         copytool_setup
2681
2682         local fid1=$(create_small_file $DIR/$tdir/$tfile-1)
2683         local fid2=$(create_small_file $DIR/$tdir/$tfile-2)
2684         local fid3=$(create_small_file $DIR/$tdir/$tfile-3)
2685
2686         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $DIR/$tdir/$tfile-[1-3]
2687         wait_request_state $fid1 ARCHIVE SUCCEED
2688         wait_request_state $fid2 ARCHIVE SUCCEED
2689         wait_request_state $fid3 ARCHIVE SUCCEED
2690
2691         rm -f $DIR/$tdir/$tfile-[1-3]
2692
2693         echo $fid1 > $DIR/$tdir/list
2694         echo $fid2 >> $DIR/$tdir/list
2695         echo $fid3 >> $DIR/$tdir/list
2696
2697         $LFS hsm_remove -m $MOUNT -a $HSM_ARCHIVE_NUMBER \
2698                 --filelist $DIR/$tdir/list
2699         wait_request_state $fid1 REMOVE SUCCEED
2700         wait_request_state $fid2 REMOVE SUCCEED
2701         wait_request_state $fid3 REMOVE SUCCEED
2702
2703         copytool_cleanup
2704 }
2705 run_test 29c "Archive/delete/remove by FID, using a file list."
2706
2707 test_29d() {
2708         # test needs more than one CT
2709         needclients 3 || return 0
2710
2711         local n
2712         local file
2713         local fid
2714
2715         copytool_cleanup $(comma_list $(agts_nodes))
2716
2717         # start all of the copytools
2718         for n in $(seq $AGTCOUNT); do
2719                 copytool_setup agt$n $MOUNT2 $n
2720         done
2721
2722         trap "copytool_cleanup $(comma_list $(agts_nodes))" EXIT
2723         # archive files
2724         file=$DIR/$tdir/$tfile
2725         fid=$(create_small_file $file)
2726
2727         $LFS hsm_archive $file
2728         wait_request_state $fid ARCHIVE SUCCEED
2729         check_hsm_flags $file "0x00000009"
2730
2731         rm -f $file
2732
2733         $LFS hsm_remove --mntpath "$MOUNT" -a 0 $fid ||
2734                 error "cannot hsm_remove '$fid'"
2735
2736         # give time for CDT to handle remove request and create broadcasted
2737         sleep 2
2738
2739         # remove request has been broadcasted ?
2740         local cnt=$(get_request_count $fid REMOVE)
2741         # broadcasted requests + original
2742         [[ $cnt -eq $((AGTCOUNT + 1)) ]] ||
2743                 error "remove not broadcasted to all CTs"
2744
2745         # give time for CDT and CTs to handle broadcasted
2746         wait_for_loop_period
2747
2748         # each agent serves one different archive_id, so broadcasted
2749         # hsm_remove request should only succeed once and fail at all others
2750         local res
2751         local scnt=0
2752         local fcnt=0
2753         for n in $(seq $AGTCOUNT); do
2754                 res=$(do_facet $SINGLEMDS "$LCTL get_param -n \
2755                                $HSM_PARAM.actions | awk \
2756                                '/'$fid'.*action=REMOVE archive#='$n'/ \
2757                                {print \\\$13}' | cut -f2 -d=")
2758                 if [[ "$res" == "SUCCEED" ]]; then
2759                         scnt=$((scnt + 1))
2760                 elif [[ "$res" == "FAILED" ]]; then
2761                         fcnt=$((fcnt + 1))
2762                 fi
2763         done
2764
2765         [[ $scnt -ne 1 ]] &&
2766                 error "one and only CT should have removed successfully"
2767
2768         [[ $AGTCOUNT -ne $((scnt + fcnt)) ]] &&
2769                 error "all but one CT should have failed to remove"
2770
2771         trap - EXIT
2772         copytool_cleanup $(comma_list $(agts_nodes))
2773
2774 }
2775 run_test 29d "hsm_remove by FID with archive_id 0 for unlinked file cause "\
2776              "request to be sent once for each registered archive_id"
2777
2778 test_30a() {
2779         # restore at exec cannot work on agent node (because of Linux kernel
2780         # protection of executables)
2781         needclients 2 || return 0
2782
2783         # test needs a running copytool
2784         copytool_setup
2785
2786         mkdir -p $DIR/$tdir
2787         copy2archive /bin/true $tdir/$tfile
2788
2789         local f=$DIR/$tdir/true
2790         import_file $tdir/$tfile $f
2791
2792         local fid=$(path2fid $f)
2793
2794         # set no retry action mode
2795         cdt_set_no_retry
2796         do_node $CLIENT2 $f
2797         local st=$?
2798
2799         # cleanup
2800         # remove no try action mode
2801         cdt_clear_no_retry
2802         $LFS hsm_state $f
2803
2804         [[ $st == 0 ]] || error "Failed to exec a released file"
2805
2806         copytool_cleanup
2807 }
2808 run_test 30a "Restore at exec (import case)"
2809
2810 test_30b() {
2811         # restore at exec cannot work on agent node (because of Linux kernel
2812         # protection of executables)
2813         needclients 2 || return 0
2814
2815         # test needs a running copytool
2816         copytool_setup
2817
2818         mkdir -p $DIR/$tdir
2819         local f=$DIR/$tdir/true
2820         local fid=$(copy_file /bin/true $f)
2821         chmod 755 $f
2822         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2823         wait_request_state $fid ARCHIVE SUCCEED
2824         $LFS hsm_release $f
2825         $LFS hsm_state $f
2826         # set no retry action mode
2827         cdt_set_no_retry
2828         do_node $CLIENT2 $f
2829         local st=$?
2830
2831         # cleanup
2832         # remove no try action mode
2833         cdt_clear_no_retry
2834         $LFS hsm_state $f
2835
2836         [[ $st == 0 ]] || error "Failed to exec a released file"
2837
2838         copytool_cleanup
2839 }
2840 run_test 30b "Restore at exec (release case)"
2841
2842 test_30c() {
2843         needclients 2 || return 0
2844
2845         # test needs a running copytool
2846         copytool_setup
2847
2848         mkdir -p $DIR/$tdir
2849         local f=$DIR/$tdir/SLEEP
2850         local slp_sum1=$(md5sum /bin/sleep)
2851         local fid=$(copy_file /bin/sleep $f)
2852         chmod 755 $f
2853         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2854         wait_request_state $fid ARCHIVE SUCCEED
2855         $LFS hsm_release $f
2856         check_hsm_flags $f "0x0000000d"
2857         # set no retry action mode
2858         cdt_set_no_retry
2859         do_node $CLIENT2 "$f 10" &
2860         local pid=$!
2861         sleep 3
2862         echo 'Hi!' > $f
2863         [[ $? == 0 ]] && error "Update during exec of released file must fail"
2864         wait $pid
2865         [[ $? == 0 ]] || error "Execution failed during run"
2866         cmp /bin/sleep $f
2867         if [[ $? != 0 ]]; then
2868                 local slp_sum2=$(md5sum /bin/sleep)
2869                 # in case sleep file is modified during the test
2870                 [[ $slp_sum1 == $slp_sum2 ]] &&
2871                         error "Binary overwritten during exec"
2872         fi
2873
2874         # cleanup
2875         # remove no try action mode
2876         cdt_clear_no_retry
2877         check_hsm_flags $f "0x00000009"
2878
2879         copytool_cleanup
2880 }
2881 run_test 30c "Update during exec of released file must fail"
2882
2883 restore_and_check_size() {
2884         local f=$1
2885         local fid=$2
2886         local s=$(stat -c "%s" $f)
2887         local n=$s
2888         local st=$(get_hsm_flags $f)
2889         local err=0
2890         local cpt=0
2891         $LFS hsm_restore $f
2892         while [[ "$st" != "0x00000009" && $cpt -le 10 ]]
2893         do
2894                 n=$(stat -c "%s" $f)
2895                 # we echo in both cases to show stat is not hang
2896                 if [[ $n != $s ]]; then
2897                         echo "size seen is $n != $s"
2898                         err=1
2899                 else
2900                         echo "size seen is right: $n == $s"
2901                 fi
2902                 sleep 10
2903                 cpt=$((cpt + 1))
2904                 st=$(get_hsm_flags $f)
2905         done
2906         if [[ "$st" = "0x00000009" ]]; then
2907                 echo " "done
2908         else
2909                 echo " restore is too long"
2910                 wait_request_state $fid RESTORE SUCCEED
2911         fi
2912         return $err
2913 }
2914
2915 test_31a() {
2916         # test needs a running copytool
2917         copytool_setup
2918
2919         create_archive_file $tdir/$tfile
2920         local f=$DIR/$tdir/$tfile
2921         import_file $tdir/$tfile $f
2922         local fid=$($LFS path2fid $f)
2923         HSM_ARCHIVE_PURGE=false copytool_setup
2924
2925         restore_and_check_size $f $fid
2926         local err=$?
2927
2928         [[ $err -eq 0 ]] || error "File size changed during restore"
2929
2930         copytool_cleanup
2931 }
2932 run_test 31a "Import a large file and check size during restore"
2933
2934
2935 test_31b() {
2936         # test needs a running copytool
2937         copytool_setup
2938
2939         local f=$DIR/$tdir/$tfile
2940         local fid
2941         fid=$(make_custom_file_for_progress $f 39 1000000)
2942         [ $? != 0 ] && skip "not enough free space" && return
2943
2944         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2945         wait_request_state $fid ARCHIVE SUCCEED
2946         $LFS hsm_release $f
2947
2948         restore_and_check_size $f $fid
2949         local err=$?
2950
2951         [[ $err -eq 0 ]] || error "File size changed during restore"
2952
2953         copytool_cleanup
2954 }
2955 run_test 31b "Restore a large unaligned file and check size during restore"
2956
2957 test_31c() {
2958         # test needs a running copytool
2959         copytool_setup
2960
2961         local f=$DIR/$tdir/$tfile
2962         local fid
2963         fid=$(make_custom_file_for_progress $f 33 1048576)
2964         [ $? != 0 ] && skip "not enough free space" && return
2965
2966         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2967         wait_request_state $fid ARCHIVE SUCCEED
2968         $LFS hsm_release $f
2969
2970         restore_and_check_size $f $fid
2971         local err=$?
2972
2973         [[ $err -eq 0 ]] || error "File size changed during restore"
2974
2975         copytool_cleanup
2976 }
2977 run_test 31c "Restore a large aligned file and check size during restore"
2978
2979 test_33() {
2980         # test needs a running copytool
2981         copytool_setup
2982
2983         local f=$DIR/$tdir/$tfile
2984         local fid
2985         fid=$(make_custom_file_for_progress $f 39 1000000)
2986         [ $? != 0 ] && skip "not enough free space" && return
2987
2988         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2989         wait_request_state $fid ARCHIVE SUCCEED
2990         $LFS hsm_release $f
2991
2992         # to be sure wait_all_done will not be mislead by previous tests
2993         # and ops.
2994         cdt_purge
2995         wait_for_grace_delay
2996         # Also raise grace_delay significantly so the Canceled
2997         # Restore action will stay enough long avail.
2998         local old_grace=$(get_hsm_param grace_delay)
2999         set_hsm_param grace_delay 100
3000
3001         md5sum $f >/dev/null &
3002         local pid=$!
3003         wait_request_state $fid RESTORE STARTED
3004
3005         kill -15 $pid
3006         sleep 1
3007
3008         # Check restore trigger process was killed
3009         local killed=$(ps -o pid,comm hp $pid >/dev/null)
3010
3011         $LFS hsm_cancel $f
3012
3013         # instead of waiting+checking both Restore and Cancel ops
3014         # sequentially, wait for both to be finished and then check
3015         # each results.
3016         wait_all_done 100 $fid
3017         local rstate=$(get_request_state $fid RESTORE)
3018         local cstate=$(get_request_state $fid CANCEL)
3019
3020         # restore orig grace_delay.
3021         set_hsm_param grace_delay $old_grace
3022
3023         if [[ "$rstate" == "CANCELED" ]] ; then
3024                 [[ "$cstate" == "SUCCEED" ]] ||
3025                         error "Restore state is CANCELED and Cancel state " \
3026                                "is not SUCCEED but $cstate"
3027                 echo "Restore state is CANCELED, Cancel state is SUCCEED"
3028         elif [[ "$rstate" == "SUCCEED" ]] ; then
3029                 [[ "$cstate" == "FAILED" ]] ||
3030                         error "Restore state is SUCCEED and Cancel state " \
3031                                 "is not FAILED but $cstate"
3032                 echo "Restore state is SUCCEED, Cancel state is FAILED"
3033         else
3034                 error "Restore state is $rstate and Cancel state is $cstate"
3035         fi
3036
3037         [ -z $killed ] ||
3038                 error "Cannot kill process waiting for restore ($killed)"
3039
3040         copytool_cleanup
3041 }
3042 run_test 33 "Kill a restore waiting process"
3043
3044 test_34() {
3045         # test needs a running copytool
3046         copytool_setup
3047
3048         local f=$DIR/$tdir/$tfile
3049         local fid
3050         fid=$(make_custom_file_for_progress $f 39 1000000)
3051         [ $? != 0 ] && skip "not enough free space" && return
3052
3053         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3054         wait_request_state $fid ARCHIVE SUCCEED
3055         $LFS hsm_release $f
3056
3057         md5sum $f >/dev/null &
3058         local pid=$!
3059         wait_request_state $fid RESTORE STARTED
3060
3061         rm $f || error "rm $f failed"
3062         # rm must not block during restore
3063         wait_request_state $fid RESTORE STARTED
3064
3065         wait_request_state $fid RESTORE SUCCEED
3066         # check md5sum pgm finished
3067         local there=$(ps -o pid,comm hp $pid >/dev/null)
3068         [[ -z $there ]] || error "Restore initiator does not exit"
3069
3070         wait $pid || error "Restore initiator failed with $?"
3071
3072         copytool_cleanup
3073 }
3074 run_test 34 "Remove file during restore"
3075
3076 test_35() {
3077         # test needs a running copytool
3078         copytool_setup
3079
3080         local f=$DIR/$tdir/$tfile
3081         local f1=$DIR/$tdir/$tfile-1
3082         local fid
3083         fid=$(make_custom_file_for_progress $f 39 1000000)
3084         [ $? != 0 ] && skip "not enough free space" && return
3085
3086         local fid1=$(copy_file /etc/passwd $f1)
3087         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3088         wait_request_state $fid ARCHIVE SUCCEED
3089         $LFS hsm_release $f
3090
3091         md5sum $f >/dev/null &
3092         local pid=$!
3093         wait_request_state $fid RESTORE STARTED
3094
3095         mv $f1 $f || error "mv $f1 $f failed"
3096         # mv must not block during restore
3097         wait_request_state $fid RESTORE STARTED
3098
3099         wait_request_state $fid RESTORE SUCCEED
3100         # check md5sum pgm finished
3101         local there=$(ps -o pid,comm hp $pid >/dev/null)
3102         [[ -z $there ]] || error "Restore initiator does not exit"
3103
3104         wait $pid || error "Restore initiator failed with $?"
3105
3106         fid2=$(path2fid $f)
3107         [[ $fid2 == $fid1 ]] || error "Wrong fid after mv $fid2 != $fid1"
3108
3109         copytool_cleanup
3110 }
3111 run_test 35 "Overwrite file during restore"
3112
3113 test_36() {
3114         # test needs a running copytool
3115         copytool_setup
3116
3117         local f=$DIR/$tdir/$tfile
3118         local fid
3119         fid=$(make_custom_file_for_progress $f 39 1000000)
3120         [ $? != 0 ] && skip "not enough free space" && return
3121
3122         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3123         wait_request_state $fid ARCHIVE SUCCEED
3124         $LFS hsm_release $f
3125
3126         md5sum $f >/dev/null &
3127         local pid=$!
3128         wait_request_state $fid RESTORE STARTED
3129
3130         mv $f $f.new
3131         # rm must not block during restore
3132         wait_request_state $fid RESTORE STARTED
3133
3134         wait_request_state $fid RESTORE SUCCEED
3135         # check md5sum pgm finished
3136         local there=$(ps -o pid,comm hp $pid >/dev/null)
3137         [[ -z $there ]] ||
3138                 error "Restore initiator does not exit"
3139
3140         wait $pid || error "Restore initiator failed with $?"
3141
3142         copytool_cleanup
3143 }
3144 run_test 36 "Move file during restore"
3145
3146 test_37() {
3147         # LU-5683: check that an archived dirty file can be rearchived.
3148         copytool_cleanup
3149         copytool_setup $SINGLEAGT $MOUNT2
3150
3151         local f=$DIR/$tdir/$tfile
3152         local fid
3153
3154         fid=$(create_small_file $f) || error "cannot create small file"
3155
3156         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3157         wait_request_state $fid ARCHIVE SUCCEED
3158         $LFS hsm_release $f || error "cannot release $f"
3159
3160         # Allow previous archive request to expire from the actions log.
3161         wait_for_grace_delay
3162
3163         # Dirty file.
3164         dd if=/dev/urandom of=$f bs=1M count=1 || error "cannot dirty file"
3165
3166         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3167         wait_request_state $fid ARCHIVE SUCCEED
3168
3169         copytool_cleanup
3170 }
3171 run_test 37 "re-archive a dirty file"
3172
3173 multi_archive() {
3174         local prefix=$1
3175         local count=$2
3176         local n=""
3177
3178         for n in $(seq 1 $count); do
3179                 $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $prefix.$n
3180         done
3181         echo "$count archive requests submitted"
3182 }
3183
3184 cleanup_test_40() {
3185         trap 0
3186         set_hsm_param max_requests $max_requests
3187         copytool_cleanup
3188 }
3189
3190 test_40() {
3191         local stream_count=4
3192         local file_count=100
3193         mkdir -p $DIR/$tdir
3194         local f=$DIR/$tdir/$tfile
3195         local i=""
3196         local p=""
3197         local fid=""
3198         local max_requests=$(get_hsm_param max_requests)
3199
3200         # Increase the number of HSM request that can be performed in
3201         # parallel. With the coordinator running once per second, this
3202         # also limits the number of requests per seconds that can be
3203         # performed, so we pick a decent number. But we also need to keep
3204         # that number low because the copytool has no rate limit and will
3205         # fail some requests if if gets too many at once.
3206         set_hsm_param max_requests 300
3207
3208         trap cleanup_test_40 EXIT
3209
3210         for i in $(seq 1 $file_count); do
3211                 for p in $(seq 1 $stream_count); do
3212                         fid=$(copy_file /etc/hosts $f.$p.$i)
3213                 done
3214         done
3215         # force copytool to use a local/temp archive dir to ensure best
3216         # performance vs remote/NFS mounts used in auto-tests
3217         if do_facet $SINGLEAGT "df --local $HSM_ARCHIVE" >/dev/null 2>&1 ; then
3218                 copytool_setup
3219         else
3220                 copytool_setup $SINGLEAGT $MOUNT $HSM_ARCHIVE_NUMBER $TMP/$tdir
3221         fi
3222         # to be sure wait_all_done will not be mislead by previous tests
3223         cdt_purge
3224         wait_for_grace_delay
3225         typeset -a pids
3226         # start archive streams in background (archive files in parallel)
3227         for p in $(seq 1 $stream_count); do
3228                 multi_archive $f.$p $file_count &
3229                 pids[$p]=$!
3230         done
3231         echo -n  "Wait for all requests being enqueued..."
3232         wait ${pids[*]}
3233         echo OK
3234         wait_all_done 100
3235
3236         cleanup_test_40
3237 }
3238 run_test 40 "Parallel archive requests"
3239
3240 test_52() {
3241         # test needs a running copytool
3242         copytool_setup
3243
3244         mkdir -p $DIR/$tdir
3245         local f=$DIR/$tdir/$tfile
3246         local fid=$(copy_file /etc/motd $f 1)
3247
3248         $LFS hsm_archive $f || error "could not archive file"
3249         wait_request_state $fid ARCHIVE SUCCEED
3250         check_hsm_flags $f "0x00000009"
3251
3252         multiop_bg_pause $f O_c || error "multiop failed"
3253         local MULTIPID=$!
3254
3255         mds_evict_client
3256         client_up || client_up || true
3257
3258         kill -USR1 $MULTIPID
3259         wait $MULTIPID || error "multiop close failed"
3260
3261         check_hsm_flags $f "0x0000000b"
3262
3263         copytool_cleanup
3264 }
3265 run_test 52 "Opened for write file on an evicted client should be set dirty"
3266
3267 test_53() {
3268         # test needs a running copytool
3269         copytool_setup
3270
3271         mkdir -p $DIR/$tdir
3272         local f=$DIR/$tdir/$tfile
3273         local fid=$(copy_file /etc/motd $f 1)
3274
3275         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
3276                 error "could not archive file"
3277         wait_request_state $fid ARCHIVE SUCCEED
3278         check_hsm_flags $f "0x00000009"
3279
3280         multiop_bg_pause $f o_c || error "multiop failed"
3281         MULTIPID=$!
3282
3283         mds_evict_client
3284         client_up || client_up || true
3285
3286         kill -USR1 $MULTIPID
3287         wait $MULTIPID || error "multiop close failed"
3288
3289         check_hsm_flags $f "0x00000009"
3290
3291         copytool_cleanup
3292 }
3293 run_test 53 "Opened for read file on an evicted client should not be set dirty"
3294
3295 test_54() {
3296         # test needs a running copytool
3297         copytool_setup
3298
3299         local f=$DIR/$tdir/$tfile
3300         local fid=$(make_custom_file_for_progress $f 39 1000000)
3301
3302         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
3303                 error "could not archive file"
3304         wait_request_state $fid ARCHIVE STARTED
3305
3306         check_hsm_flags $f "0x00000001"
3307
3308         # Avoid coordinator resending this request as soon it has failed.
3309         cdt_set_no_retry
3310
3311         echo "foo" >> $f
3312         sync
3313         wait_request_state $fid ARCHIVE FAILED
3314
3315         check_hsm_flags $f "0x00000003"
3316
3317         cdt_clear_no_retry
3318         copytool_cleanup
3319 }
3320 run_test 54 "Write during an archive cancels it"
3321
3322 test_55() {
3323         # test needs a running copytool
3324         copytool_setup
3325
3326         local f=$DIR/$tdir/$tfile
3327         local fid=$(make_custom_file_for_progress $f 39 1000000)
3328
3329         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
3330                 error "could not archive file"
3331         wait_request_state $fid ARCHIVE STARTED
3332
3333         check_hsm_flags $f "0x00000001"
3334
3335         # Avoid coordinator resending this request as soon it has failed.
3336         cdt_set_no_retry
3337
3338         $TRUNCATE $f 1024 || error "truncate failed"
3339         sync
3340         wait_request_state $fid ARCHIVE FAILED
3341
3342         check_hsm_flags $f "0x00000003"
3343
3344         cdt_clear_no_retry
3345         copytool_cleanup
3346 }
3347 run_test 55 "Truncate during an archive cancels it"
3348
3349 test_56() {
3350         # test needs a running copytool
3351         copytool_setup
3352
3353         local f=$DIR/$tdir/$tfile
3354         local fid
3355         fid=$(make_custom_file_for_progress $f 39 1000000)
3356         [ $? != 0 ] && skip "not enough free space" && return
3357
3358         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
3359                 error "could not archive file"
3360         wait_request_state $fid ARCHIVE STARTED
3361
3362         check_hsm_flags $f "0x00000001"
3363
3364         # Change metadata and sync to be sure we are not changing only
3365         # in memory.
3366         chmod 644 $f
3367         chgrp sys $f
3368         sync
3369         wait_request_state $fid ARCHIVE SUCCEED
3370
3371         check_hsm_flags $f "0x00000009"
3372
3373         copytool_cleanup
3374 }
3375 run_test 56 "Setattr during an archive is ok"
3376
3377 test_57() {
3378         # Need one client for I/O, one for request
3379         needclients 2 || return 0
3380
3381         # test needs a running copytool
3382         copytool_setup
3383
3384         mkdir -p $DIR/$tdir
3385         local f=$DIR/$tdir/test_archive_remote
3386         # Create a file on a remote node
3387         do_node $CLIENT2 "dd if=/dev/urandom of=$f bs=1M "\
3388                 "count=2 conv=fsync"
3389
3390         # And archive it
3391         do_node $CLIENT2 "$LFS hsm_archive -a $HSM_ARCHIVE_NUMBER $f" ||
3392                 error "hsm_archive failed"
3393         local fid=$(path2fid $f)
3394         wait_request_state $fid ARCHIVE SUCCEED
3395
3396         # Release and implicit restore it
3397         do_node $CLIENT2 "$LFS hsm_release $f" ||
3398                 error "hsm_release failed"
3399         do_node $CLIENT2 "md5sum $f" ||
3400                 error "hsm_restore failed"
3401
3402         wait_request_state $fid RESTORE SUCCEED
3403
3404         copytool_cleanup
3405 }
3406 run_test 57 "Archive a file with dirty cache on another node"
3407
3408 truncate_released_file() {
3409         local src_file=$1
3410         local trunc_to=$2
3411
3412         local sz=$(stat -c %s $src_file)
3413         local f=$DIR/$tdir/$tfile
3414         local fid=$(copy_file $1 $f)
3415         local ref=$f-ref
3416         cp $f $f-ref
3417
3418         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
3419                 error "could not archive file"
3420         wait_request_state $fid ARCHIVE SUCCEED
3421
3422         $LFS hsm_release $f || error "could not release file"
3423
3424         $TRUNCATE $f $trunc_to || error "truncate failed"
3425         sync
3426
3427         local sz1=$(stat -c %s $f)
3428         [[ $sz1 == $trunc_to ]] ||
3429                 error "size after trunc: $sz1 expect $trunc_to, original $sz"
3430
3431         $LFS hsm_state $f
3432         check_hsm_flags $f "0x0000000b"
3433
3434         local state=$(get_request_state $fid RESTORE)
3435         [[ "$state" == "SUCCEED" ]] ||
3436                 error "truncate $sz does not trig restore, state = $state"
3437
3438         $TRUNCATE $ref $trunc_to
3439         cmp $ref $f || error "file data wrong after truncate"
3440
3441         rm -f $f $f-ref
3442 }
3443
3444 test_58() {
3445         # test needs a running copytool
3446         copytool_setup
3447
3448         mkdir -p $DIR/$tdir
3449
3450         local sz=$(stat -c %s /etc/passwd)
3451
3452         echo "truncate up from $sz to $((sz*2))"
3453         truncate_released_file /etc/passwd $((sz*2))
3454
3455         echo "truncate down from $sz to $((sz/2))"
3456         truncate_released_file /etc/passwd $((sz/2))
3457
3458         echo "truncate to 0"
3459         truncate_released_file /etc/passwd 0
3460
3461         copytool_cleanup
3462 }
3463 run_test 58 "Truncate a released file will trigger restore"
3464
3465 test_59() {
3466         local fid
3467         local server_version=$(lustre_version_code $SINGLEMDS)
3468         [[ $server_version -lt $(version_code 2.7.63) ]] &&
3469                 skip "Need MDS version at least 2.7.63" && return
3470
3471         copytool_setup
3472         $MCREATE $DIR/$tfile || error "mcreate failed"
3473         $TRUNCATE $DIR/$tfile 42 || error "truncate failed"
3474         $LFS hsm_archive $DIR/$tfile || error "archive request failed"
3475         fid=$(path2fid $DIR/$tfile)
3476         wait_request_state $fid ARCHIVE SUCCEED
3477         $LFS hsm_release $DIR/$tfile || error "release failed"
3478         copytool_cleanup
3479 }
3480 run_test 59 "Release stripeless file with non-zero size"
3481
3482 test_60() {
3483         # This test validates the fix for LU-4512. Ensure that the -u
3484         # option changes the progress reporting interval from the
3485         # default (30 seconds) to the user-specified interval.
3486         local interval=5
3487         local progress_timeout=$((interval * 4))
3488
3489         # test needs a new running copytool
3490         copytool_cleanup
3491         HSMTOOL_UPDATE_INTERVAL=$interval copytool_setup
3492
3493         local f=$DIR/$tdir/$tfile
3494         local fid
3495         fid=$(make_custom_file_for_progress $f 10)
3496         [ $? != 0 ] && skip "not enough free space" && return
3497
3498         local mdtidx=0
3499         local mdt=${MDT_PREFIX}${mdtidx}
3