Whamcloud - gitweb
LU-8203 tests: Wait for archive operation to be completed.
[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:    LU-3815
15 ALWAYS_EXCEPT="$SANITY_HSM_EXCEPT 34 35 36"
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
174         while ((SECONDS < wait_end)); do
175                 sleep 2
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         done
183
184         # try to dump Copytool's stack
185         do_nodesv $hosts "echo 1 >/proc/sys/kernel/sysrq ; " \
186                          "echo t >/proc/sysrq-trigger"
187
188         echo "copytools failed to stop in ${wait_timeout}s"
189
190         return 1
191 }
192
193 copytool_monitor_setup() {
194         local facet=${1:-$SINGLEAGT}
195         local agent=$(facet_active_host $facet)
196
197         local cmd="mktemp --tmpdir=/tmp -d ${TESTSUITE}.${TESTNAME}.XXXX"
198         local test_dir=$(do_node $agent "$cmd") ||
199                 error "Failed to create tempdir on $agent"
200         export HSMTOOL_MONITOR_DIR=$test_dir
201
202         # Create the fifo and a monitor (cat dies when copytool dies)
203         do_node $agent "mkfifo -m 0644 $test_dir/fifo" ||
204                 error "failed to create copytool fifo on $agent"
205         cmd="cat $test_dir/fifo > $test_dir/events &"
206         cmd+=" echo \\\$! > $test_dir/monitor_pid"
207
208         if [[ $PDSH == *Rmrsh* ]]; then
209                 # This is required for pdsh -Rmrsh and its handling of remote
210                 # shells.
211                 # Regular ssh and pdsh -Rssh work fine without this
212                 # backgrounded subshell nonsense.
213                 (do_node $agent "$cmd") &
214                 export HSMTOOL_MONITOR_PDSH=$!
215
216                 # Slightly racy, but just making a best-effort to catch obvious
217                 # problems.
218                 sleep 1
219                 ps -p $HSMTOOL_MONITOR_PDSH > /dev/null ||
220                         error "Failed to start copytool monitor on $agent"
221         else
222                 do_node $agent "$cmd"
223                 if [ $? != 0 ]; then
224                         error "Failed to start copytool monitor on $agent"
225                 fi
226         fi
227 }
228
229 copytool_monitor_cleanup() {
230         local facet=${1:-$SINGLEAGT}
231         local agent=$(facet_active_host $facet)
232
233         if [ -n "$HSMTOOL_MONITOR_DIR" ]; then
234                 # Should die when the copytool dies, but just in case.
235                 local cmd="kill \\\$(cat $HSMTOOL_MONITOR_DIR/monitor_pid)"
236                 cmd+=" 2>/dev/null || true"
237                 do_node $agent "$cmd"
238                 do_node $agent "rm -fr $HSMTOOL_MONITOR_DIR"
239                 export HSMTOOL_MONITOR_DIR=
240         fi
241
242         # The pdsh should die on its own when the monitor dies. Just
243         # in case, though, try to clean up to avoid any cruft.
244         if [ -n "$HSMTOOL_MONITOR_PDSH" ]; then
245                 kill $HSMTOOL_MONITOR_PDSH 2>/dev/null
246                 export HSMTOOL_MONITOR_PDSH=
247         fi
248 }
249
250 copytool_setup() {
251         local facet=${1:-$SINGLEAGT}
252         # Use MOUNT2 by default if defined
253         local lustre_mntpnt=${2:-${MOUNT2:-$MOUNT}}
254         local arc_id=$3
255         local hsm_root=${4:-$(copytool_device $facet)}
256
257         [ -z "${hsm_root// /}" ] && error "copytool_setup: hsm_root empty!"
258
259         local agent=$(facet_active_host $facet)
260
261         if [[ -z "$arc_id" ]] &&
262                 do_facet $facet "pkill -CONT -x $HSMTOOL_BASE"; then
263                         echo "Only wakeup running copytool $facet on $agent"
264                         return 0
265         fi
266
267         if $HSM_ARCHIVE_PURGE; then
268                 echo "Purging archive on $agent"
269                 do_facet $facet "rm -rf $hsm_root/$HSMTMP/*"
270         fi
271
272         echo "Starting copytool $facet on $agent"
273         do_facet $facet "mkdir -p $hsm_root/$HSMTMP/" ||
274                         error "mkdir '$hsm_root/$HSMTMP' failed"
275         # bandwidth is limited to 1MB/s so the copy time is known and
276         # independent of hardware
277         local cmd="$HSMTOOL $HSMTOOL_VERBOSE --daemon"
278         cmd+=" --hsm-root $hsm_root/$HSMTMP"
279         [[ -z "$arc_id" ]] || cmd+=" --archive $arc_id"
280         [[ -z "$HSMTOOL_UPDATE_INTERVAL" ]] ||
281                 cmd+=" --update-interval $HSMTOOL_UPDATE_INTERVAL"
282         [[ -z "$HSMTOOL_EVENT_FIFO" ]] ||
283                 cmd+=" --event-fifo $HSMTOOL_EVENT_FIFO"
284         cmd+=" --bandwidth 1 $lustre_mntpnt"
285
286         # Redirect the standard output and error to a log file which
287         # can be uploaded to Maloo.
288         local prefix=$TESTLOG_PREFIX
289         [[ -z "$TESTNAME" ]] || prefix=$prefix.$TESTNAME
290         local copytool_log=$prefix.copytool${arc_id}_log.$agent.log
291
292         do_facet $facet "$cmd < /dev/null > $copytool_log 2>&1"
293         if [[ $? !=  0 ]]; then
294                 [[ $HSMTOOL_NOERROR == true ]] ||
295                         error "start copytool $facet on $agent failed"
296                 echo "start copytool $facet on $agent failed"
297         fi
298
299         trap cleanup EXIT
300 }
301
302 get_copytool_event_log() {
303         local facet=${1:-$SINGLEAGT}
304         local agent=$(facet_active_host $facet)
305
306         [ -z "$HSMTOOL_MONITOR_DIR" ] &&
307                 error "Can't get event log: No monitor directory!"
308
309         do_node $agent "cat $HSMTOOL_MONITOR_DIR/events" ||
310                 error "Could not collect event log from $agent"
311 }
312
313 copytool_cleanup() {
314         trap - EXIT
315         local agt_facet=$SINGLEAGT
316         local agt_hosts=${1:-$(facet_active_host $agt_facet)}
317         local hsm_root=$(copytool_device $agt_facet)
318
319         [ -z "${hsm_root// /}" ] && error "copytool_cleanup: hsm_root empty!"
320
321         local i
322         local facet
323         local param
324         local -a state
325
326         kill_copytools $agt_hosts
327         wait_copytools $agt_hosts || error "copytools failed to stop"
328
329         # Clean all CDTs orphans requests from previous tests that
330         # would otherwise need to timeout to clear.
331         for ((i = 0; i < MDSCOUNT; i++)); do
332                 facet=mds$((i + 1))
333                 param=$(printf 'mdt.%s-MDT%04x.hsm_control' $FSNAME $i)
334                 state[$i]=$(do_facet $facet "$LCTL get_param -n $param")
335
336                 # Skip already stopping or stopped CDTs.
337                 [[ "${state[$i]}" =~ ^stop ]] && continue
338
339                 do_facet $facet "$LCTL set_param $param=shutdown"
340         done
341
342         for ((i = 0; i < MDSCOUNT; i++)); do
343                 # Only check and restore CDTs that we stopped in the first loop.
344                 [[ "${state[$i]}" =~ ^stop ]] && continue
345
346                 facet=mds$((i + 1))
347                 param=$(printf 'mdt.%s-MDT%04x.hsm_control' $FSNAME $i)
348
349                 wait_result $facet "$LCTL get_param -n $param" stopped 20 ||
350                         error "$facet CDT state is not stopped"
351
352                 # Restore old CDT state.
353                 do_facet $facet "$LCTL set_param $param=${state[$i]}"
354         done
355
356         for ((i = 0; i < MDSCOUNT; i++)); do
357                 # Only check CDTs that we stopped in the first loop.
358                 [[ "${state[$i]}" =~ ^stop ]] && continue
359
360                 facet=mds$((i + 1))
361                 param=$(printf 'mdt.%s-MDT%04x.hsm_control' $FSNAME $i)
362
363                 # Check that the old CDT state was restored.
364                 wait_result $facet "$LCTL get_param -n $param" "${state[$i]}" \
365                         20 || error "$facet CDT state is not '${state[$i]}'"
366         done
367
368         if do_facet $agt_facet "df $hsm_root" >/dev/null 2>&1 ; then
369                 do_facet $agt_facet "rm -rf $hsm_root/$HSMTMP/*"
370         fi
371 }
372
373 copytool_suspend() {
374         local agents=${1:-$(facet_active_host $SINGLEAGT)}
375
376         do_nodesv $agents "pkill -STOP -x $HSMTOOL_BASE" || return 0
377         echo "Copytool is suspended on $agents"
378 }
379
380 copytool_remove_backend() {
381         local fid=$1
382         local be=$(do_facet $SINGLEAGT find $HSM_ARCHIVE -name $fid)
383         echo "Remove from backend: $fid = $be"
384         do_facet $SINGLEAGT rm -f $be
385 }
386
387 import_file() {
388         do_facet $SINGLEAGT \
389                 "$HSMTOOL --archive $HSM_ARCHIVE_NUMBER --hsm-root $HSM_ARCHIVE\
390                 --import $1 $2 $MOUNT" ||
391                 error "import of $1 to $2 failed"
392 }
393
394 make_archive() {
395         local file=$HSM_ARCHIVE/$1
396         do_facet $SINGLEAGT mkdir -p $(dirname $file)
397         do_facet $SINGLEAGT dd if=/dev/urandom of=$file count=32 bs=1000000 ||
398                 file_creation_failure dd $file $?
399 }
400
401 copy2archive() {
402         local file=$HSM_ARCHIVE/$2
403         do_facet $SINGLEAGT mkdir -p $(dirname $file)
404         do_facet $SINGLEAGT cp -p $1 $file || error "cannot copy $1 to $file"
405 }
406
407 mdts_set_param() {
408         local arg=$1
409         local key=$2
410         local value=$3
411         local mdtno
412         local rc=0
413         if [[ "$value" != "" ]]; then
414                 value="=$value"
415         fi
416         for mdtno in $(seq 1 $MDSCOUNT); do
417                 local idx=$(($mdtno - 1))
418                 local facet=mds${mdtno}
419                 # if $arg include -P option, run 1 set_param per MDT on the MGS
420                 # else, run set_param on each MDT
421                 [[ $arg = *"-P"* ]] && facet=mgs
422                 do_facet $facet $LCTL set_param $arg mdt.${MDT[$idx]}.$key$value
423                 [[ $? != 0 ]] && rc=1
424         done
425         return $rc
426 }
427
428 mdts_check_param() {
429         local key="$1"
430         local target="$2"
431         local timeout="$3"
432         local mdtno
433         for mdtno in $(seq 1 $MDSCOUNT); do
434                 local idx=$(($mdtno - 1))
435                 wait_result mds${mdtno} \
436                         "$LCTL get_param -n $MDT_PREFIX${idx}.$key" "$target" \
437                         $timeout ||
438                         error "$key state is not '$target' on mds${mdtno}"
439         done
440 }
441
442 changelog_setup() {
443         CL_USERS=()
444         local mdtno
445         for mdtno in $(seq 1 $MDSCOUNT); do
446                 local idx=$(($mdtno - 1))
447                 local cl_user=$(do_facet mds${mdtno} $LCTL \
448                              --device ${MDT[$idx]} \
449                              changelog_register -n)
450                 CL_USERS+=($cl_user)
451                 do_facet mds${mdtno} lctl set_param \
452                         mdd.${MDT[$idx]}.changelog_mask="+hsm"
453                 $LFS changelog_clear ${MDT[$idx]} $cl_user 0
454         done
455 }
456
457 changelog_cleanup() {
458         local mdtno
459         for mdtno in $(seq 1 $MDSCOUNT); do
460                 local idx=$(($mdtno - 1))
461                 [[ -z  ${CL_USERS[$idx]} ]] && continue
462                 $LFS changelog_clear ${MDT[$idx]} ${CL_USERS[$idx]} 0
463                 do_facet mds${mdtno} lctl --device ${MDT[$idx]} \
464                         changelog_deregister ${CL_USERS[$idx]}
465         done
466         CL_USERS=()
467 }
468
469 changelog_get_flags() {
470         local mdt=$1
471         local cltype=$2
472         local fid=$3
473
474         $LFS changelog $mdt | awk "/$cltype/ && /t=\[$fid\]/ {print \$5}"
475 }
476
477 get_hsm_param() {
478         local param=$1
479         local val=$(do_facet $SINGLEMDS $LCTL get_param -n $HSM_PARAM.$param)
480         echo $val
481 }
482
483 set_hsm_param() {
484         local param=$1
485         local value=$2
486         local opt=$3
487         mdts_set_param "$opt -n" "hsm.$param" "$value"
488         return $?
489 }
490
491 set_test_state() {
492         local cmd=$1
493         local target=$2
494         mdts_set_param "" hsm_control "$cmd"
495         mdts_check_param hsm_control "$target" 10
496 }
497
498 cdt_set_sanity_policy() {
499         if [[ "$CDT_POLICY_HAD_CHANGED" ]]
500         then
501                 # clear all
502                 mdts_set_param "" hsm.policy "+NRA"
503                 mdts_set_param "" hsm.policy "-NBR"
504                 CDT_POLICY_HAD_CHANGED=
505         fi
506 }
507
508 cdt_set_no_retry() {
509         mdts_set_param "" hsm.policy "+NRA"
510         CDT_POLICY_HAD_CHANGED=true
511 }
512
513 cdt_clear_no_retry() {
514         mdts_set_param "" hsm.policy "-NRA"
515         CDT_POLICY_HAD_CHANGED=true
516 }
517
518 cdt_set_non_blocking_restore() {
519         mdts_set_param "" hsm.policy "+NBR"
520         CDT_POLICY_HAD_CHANGED=true
521 }
522
523 cdt_clear_non_blocking_restore() {
524         mdts_set_param "" hsm.policy "-NBR"
525         CDT_POLICY_HAD_CHANGED=true
526 }
527
528 cdt_clear_mount_state() {
529         mdts_set_param "-P -d" hsm_control ""
530 }
531
532 cdt_set_mount_state() {
533         mdts_set_param "-P" hsm_control "$1"
534         # set_param -P is asynchronous operation and could race with set_param.
535         # In such case configs could be retrieved and applied at mgc after
536         # set_param -P completion. Sleep here to avoid race with set_param.
537         # We need at least 20 seconds. 10 for mgc_requeue_thread to wake up
538         # MGC_TIMEOUT_MIN_SECONDS + MGC_TIMEOUT_RAND_CENTISEC(5 + 5)
539         # and 10 seconds to retrieve config from server.
540         sleep 20
541 }
542
543 cdt_check_state() {
544         mdts_check_param hsm_control "$1" 20
545 }
546
547 cdt_disable() {
548         set_test_state disabled disabled
549 }
550
551 cdt_enable() {
552         set_test_state enabled enabled
553 }
554
555 cdt_shutdown() {
556         set_test_state shutdown stopped
557 }
558
559 cdt_purge() {
560         set_test_state purge enabled
561 }
562
563 cdt_restart() {
564         cdt_shutdown
565         cdt_enable
566         cdt_set_sanity_policy
567 }
568
569 needclients() {
570         local client_count=$1
571         if [[ $CLIENTCOUNT -lt $client_count ]]; then
572                 skip "Need $client_count or more clients, have $CLIENTCOUNT"
573                 return 1
574         fi
575         return 0
576 }
577
578 path2fid() {
579         $LFS path2fid $1 | tr -d '[]'
580         return ${PIPESTATUS[0]}
581 }
582
583 get_hsm_flags() {
584         local f=$1
585         local u=$2
586         local st
587
588         if [[ $u == "user" ]]; then
589                 st=$($RUNAS $LFS hsm_state $f)
590         else
591                 u=root
592                 st=$($LFS hsm_state $f)
593         fi
594
595         [[ $? == 0 ]] || error "$LFS hsm_state $f failed (run as $u)"
596
597         st=$(echo $st | cut -f 2 -d" " | tr -d "()," )
598         echo $st
599 }
600
601 get_hsm_archive_id() {
602         local f=$1
603         local st
604         st=$($LFS hsm_state $f)
605         [[ $? == 0 ]] || error "$LFS hsm_state $f failed"
606
607         local ar=$(echo $st | grep "archive_id" | cut -f5 -d" " |
608                    cut -f2 -d:)
609         echo $ar
610 }
611
612 check_hsm_flags() {
613         local f=$1
614         local fl=$2
615
616         local st=$(get_hsm_flags $f)
617         [[ $st == $fl ]] || error "hsm flags on $f are $st != $fl"
618 }
619
620 check_hsm_flags_user() {
621         local f=$1
622         local fl=$2
623
624         local st=$(get_hsm_flags $f user)
625         [[ $st == $fl ]] || error "hsm flags on $f are $st != $fl"
626 }
627
628 file_creation_failure() {
629         local cmd=$1
630         local f=$2
631         local err=$3
632
633         df $MOUNT $MOUNT2 >&2
634         error "cannot create $f with $cmd, status=$err"
635 }
636
637 copy_file() {
638         local f=
639
640         if [[ -d $2 ]]; then
641                 f=$2/$(basename $1)
642         else
643                 f=$2
644         fi
645
646         if [[ "$3" != 1 ]]; then
647                 f=${f/$DIR/$DIR2}
648         fi
649         rm -f $f
650         cp $1 $f || file_creation_failure cp $f $?
651
652         path2fid $f || error "cannot get fid on $f"
653 }
654
655 make_small() {
656         local file2=${1/$DIR/$DIR2}
657         dd if=/dev/urandom of=$file2 count=2 bs=1M conv=fsync ||
658                 file_creation_failure dd $file2 $?
659
660         path2fid $1 || error "cannot get fid on $1"
661 }
662
663 make_small_sync() {
664         dd if=/dev/urandom of=$1 count=1 bs=1M conv=sync ||
665                 file_creation_failure dd $1 $?
666         path2fid $1 || error "cannot get fid on $1"
667 }
668
669 cleanup_large_files() {
670         local ratio=$(df -P $MOUNT | tail -1 | awk '{print $5}' |
671                       sed 's/%//g')
672         [ $ratio -gt 50 ] && find $MOUNT -size +10M -exec rm -f {} \;
673 }
674
675 check_enough_free_space() {
676         local nb=$1
677         local unit=$2
678         local need=$((nb * unit /1024))
679         local free=$(df -kP $MOUNT | tail -1 | awk '{print $4}')
680         (( $need >= $free )) && return 1
681         return 0
682 }
683
684 make_custom_file_for_progress() {
685         local file2=${1/$DIR/$DIR2}
686         local fsize=${2:-"39"}
687         local blksz=$($LCTL get_param -n lov.*-clilov-*.stripesize | head -n1)
688         blksz=${3:-$blksz}
689
690         [[ $fsize -gt  0 ]] || error "Invalid file size"
691         [[ $blksz -gt 0 ]] || error "Invalid stripe size"
692
693         cleanup_large_files
694         check_enough_free_space $fsize $blksz
695         [ $? != 0 ] && return $?
696         dd if=/dev/zero of=$file2 count=$fsize bs=$blksz conv=fsync ||
697                 file_creation_failure dd $file2 $?
698         path2fid $1 || error "cannot get fid on $1"
699 }
700
701 wait_result() {
702         local facet=$1
703         shift
704         wait_update --verbose $(facet_active_host $facet) "$@"
705 }
706
707 wait_request_state() {
708         local fid=$1
709         local request=$2
710         local state=$3
711         # 4th arg (mdt index) is optional
712         local mdtidx=${4:-0}
713         local mds=mds$(($mdtidx + 1))
714
715         local cmd="$LCTL get_param -n ${MDT_PREFIX}${mdtidx}.hsm.actions"
716         cmd+=" | awk '/'$fid'.*action='$request'/ {print \\\$13}' | cut -f2 -d="
717
718         wait_result $mds "$cmd" $state 200 ||
719                 error "request on $fid is not $state on $mds"
720 }
721
722 get_request_state() {
723         local fid=$1
724         local request=$2
725
726         do_facet $SINGLEMDS "$LCTL get_param -n $HSM_PARAM.actions |"\
727                 "awk '/'$fid'.*action='$request'/ {print \\\$13}' | cut -f2 -d="
728 }
729
730 get_request_count() {
731         local fid=$1
732         local request=$2
733
734         do_facet $SINGLEMDS "$LCTL get_param -n $HSM_PARAM.actions |"\
735                 "awk -vn=0 '/'$fid'.*action='$request'/ {n++}; END {print n}'"
736 }
737
738 wait_all_done() {
739         local timeout=$1
740         local fid=$2
741
742         local cmd="$LCTL get_param -n $HSM_PARAM.actions"
743         [[ -n $fid ]] && cmd+=" | grep '$fid'"
744         cmd+=" | egrep 'WAITING|STARTED'"
745
746         wait_result $SINGLEMDS "$cmd" "" $timeout ||
747                 error "requests did not complete"
748 }
749
750 wait_for_grace_delay() {
751         local val=$(get_hsm_param grace_delay)
752         sleep $val
753 }
754
755 parse_json_event() {
756         local raw_event=$1
757
758         # python2.6 in EL6 includes an internal json module
759         local json_parser='import json; import fileinput;'
760         json_parser+=' print "\n".join(["local %s=\"%s\"" % tuple for tuple in '
761         json_parser+='json.loads([line for line in '
762         json_parser+='fileinput.input()][0]).items()])'
763
764         echo $raw_event | python -c "$json_parser"
765 }
766
767 get_agent_by_uuid_mdt() {
768         local uuid=$1
769         local mdtidx=$2
770         local mds=mds$(($mdtidx + 1))
771         do_facet $mds "$LCTL get_param -n ${MDT_PREFIX}${mdtidx}.hsm.agents |\
772                  grep $uuid"
773 }
774
775 check_agent_registered_by_mdt() {
776         local uuid=$1
777         local mdtidx=$2
778         local mds=mds$(($mdtidx + 1))
779         local agent=$(get_agent_by_uuid_mdt $uuid $mdtidx)
780         if [[ ! -z "$agent" ]]; then
781                 echo "found agent $agent on $mds"
782         else
783                 error "uuid $uuid not found in agent list on $mds"
784         fi
785 }
786
787 check_agent_unregistered_by_mdt() {
788         local uuid=$1
789         local mdtidx=$2
790         local mds=mds$(($mdtidx + 1))
791         local agent=$(get_agent_by_uuid_mdt $uuid $mdtidx)
792         if [[ -z "$agent" ]]; then
793                 echo "uuid not found in agent list on $mds"
794         else
795                 error "uuid found in agent list on $mds: $agent"
796         fi
797 }
798
799 check_agent_registered() {
800         local uuid=$1
801         local mdsno
802         for mdsno in $(seq 1 $MDSCOUNT); do
803                 check_agent_registered_by_mdt $uuid $((mdsno - 1))
804         done
805 }
806
807 check_agent_unregistered() {
808         local uuid=$1
809         local mdsno
810         for mdsno in $(seq 1 $MDSCOUNT); do
811                 check_agent_unregistered_by_mdt $uuid $((mdsno - 1))
812         done
813 }
814
815 get_agent_uuid() {
816         local agent=${1:-$(facet_active_host $SINGLEAGT)}
817
818         # Lustre mount-point is mandatory and last parameter on
819         # copytool cmd-line.
820         local mntpnt=$(do_rpc_nodes $agent ps -C $HSMTOOL_BASE -o args= |
821                        awk '{print $NF}')
822         [ -n "$mntpnt" ] || error "Found no Agent or with no mount-point "\
823                                   "parameter"
824         do_rpc_nodes $agent get_client_uuid $mntpnt | cut -d' ' -f2
825 }
826
827 # initiate variables
828 init_agt_vars
829
830 # populate MDT device array
831 get_mdt_devices
832
833 # cleanup from previous bad setup
834 kill_copytools
835
836 # for recovery tests, coordinator needs to be started at mount
837 # so force it
838 # the lustre conf must be without hsm on (like for sanity.sh)
839 echo "Set HSM on and start"
840 cdt_set_mount_state enabled
841 cdt_check_state enabled
842
843 echo "Start copytool"
844 copytool_setup
845
846 echo "Set sanity-hsm HSM policy"
847 cdt_set_sanity_policy
848
849 # finished requests are quickly removed from list
850 set_hsm_param grace_delay 10
851
852 test_1() {
853         mkdir -p $DIR/$tdir
854         chmod 777 $DIR/$tdir
855
856         local f=$DIR/$tdir/$tfile
857         $RUNAS touch $f
858
859         # User flags
860         check_hsm_flags_user $f "0x00000000"
861
862         $RUNAS $LFS hsm_set --norelease $f ||
863                 error "user could not change hsm flags"
864         check_hsm_flags_user $f "0x00000010"
865
866         $RUNAS $LFS hsm_clear --norelease $f ||
867                 error "user could not clear hsm flags"
868         check_hsm_flags_user $f "0x00000000"
869
870         # User could not change those flags...
871         $RUNAS $LFS hsm_set --exists $f &&
872                 error "user should not set this flag"
873         check_hsm_flags_user $f "0x00000000"
874
875         # ...but root can
876         $LFS hsm_set --exists $f ||
877                 error "root could not change hsm flags"
878         check_hsm_flags_user $f "0x00000001"
879
880         $LFS hsm_clear --exists $f ||
881                 error "root could not clear hsm state"
882         check_hsm_flags_user $f "0x00000000"
883
884 }
885 run_test 1 "lfs hsm flags root/non-root access"
886
887 test_1a() {
888         mkdir -p $DIR/$tdir
889         local f=$DIR/$tdir/$tfile
890         local fid=$(make_small $f)
891
892         $LFS hsm_archive $f || error "could not archive file"
893         wait_request_state $fid ARCHIVE SUCCEED
894
895         # Release and check states
896         $LFS hsm_release $f || error "could not release file"
897         echo -n "Verifying released state: "
898         check_hsm_flags $f "0x0000000d"
899
900         $MMAP_CAT $f > /dev/null || error "failed mmap & cat release file"
901 }
902 run_test 1a "mmap & cat a HSM released file"
903
904 test_2() {
905         mkdir -p $DIR/$tdir
906         local f=$DIR/$tdir/$tfile
907         touch $f
908         # New files are not dirty
909         check_hsm_flags $f "0x00000000"
910
911         # For test, we simulate an archived file.
912         $LFS hsm_set --exists $f || error "user could not change hsm flags"
913         check_hsm_flags $f "0x00000001"
914
915         # chmod do not put the file dirty
916         chmod 600 $f || error "could not chmod test file"
917         check_hsm_flags $f "0x00000001"
918
919         # chown do not put the file dirty
920         chown $RUNAS_ID $f || error "could not chown test file"
921         check_hsm_flags $f "0x00000001"
922
923         # truncate put the file dirty
924         $TRUNCATE $f 1 || error "could not truncate test file"
925         check_hsm_flags $f "0x00000003"
926
927         $LFS hsm_clear --dirty $f || error "could not clear hsm flags"
928         check_hsm_flags $f "0x00000001"
929 }
930 run_test 2 "Check file dirtyness when doing setattr"
931
932 test_3() {
933         mkdir -p $DIR/$tdir
934         f=$DIR/$tdir/$tfile
935
936         # New files are not dirty
937         cp -p /etc/passwd $f
938         check_hsm_flags $f "0x00000000"
939
940         # For test, we simulate an archived file.
941         $LFS hsm_set --exists $f ||
942                 error "user could not change hsm flags"
943         check_hsm_flags $f "0x00000001"
944
945         # Reading a file, does not set dirty
946         cat $f > /dev/null || error "could not read file"
947         check_hsm_flags $f "0x00000001"
948
949         # Open for write without modifying data, does not set dirty
950         openfile -f O_WRONLY $f || error "could not open test file"
951         check_hsm_flags $f "0x00000001"
952
953         # Append to a file sets it dirty
954         cp -p /etc/passwd $f.append || error "could not create file"
955         $LFS hsm_set --exists $f.append ||
956                 error "user could not change hsm flags"
957         dd if=/etc/passwd of=$f.append bs=1 count=3\
958            conv=notrunc oflag=append status=noxfer ||
959                 file_creation_failure dd $f.append $?
960         check_hsm_flags $f.append "0x00000003"
961
962         # Modify a file sets it dirty
963         cp -p /etc/passwd $f.modify || error "could not create file"
964         $LFS hsm_set --exists $f.modify ||
965                 error "user could not change hsm flags"
966         dd if=/dev/zero of=$f.modify bs=1 count=3\
967            conv=notrunc status=noxfer ||
968                 file_creation_failure dd $f.modify $?
969         check_hsm_flags $f.modify "0x00000003"
970
971         # Open O_TRUNC sets dirty
972         cp -p /etc/passwd $f.trunc || error "could not create file"
973         $LFS hsm_set --exists $f.trunc ||
974                 error "user could not change hsm flags"
975         cp /etc/group $f.trunc || error "could not override a file"
976         check_hsm_flags $f.trunc "0x00000003"
977
978         # Mmapped a file sets dirty
979         cp -p /etc/passwd $f.mmap || error "could not create file"
980         $LFS hsm_set --exists $f.mmap ||
981                 error "user could not change hsm flags"
982         multiop $f.mmap OSMWUc || error "could not mmap a file"
983         check_hsm_flags $f.mmap "0x00000003"
984 }
985 run_test 3 "Check file dirtyness when opening for write"
986
987 test_4() {
988         mkdir -p $DIR/$tdir
989         local f=$DIR/$tdir/$tfile
990         local fid=$(make_small $f)
991
992         $LFS hsm_cancel $f
993         local st=$(get_request_state $fid CANCEL)
994         [[ -z "$st" ]] || error "hsm_cancel must not be registered (state=$st)"
995 }
996 run_test 4 "Useless cancel must not be registered"
997
998 test_8() {
999         # test needs a running copytool
1000         copytool_setup
1001
1002         mkdir -p $DIR/$tdir
1003         local f=$DIR/$tdir/$tfile
1004         local fid=$(copy_file /etc/passwd $f)
1005         $LFS hsm_archive $f
1006         wait_request_state $fid ARCHIVE SUCCEED
1007
1008         check_hsm_flags $f "0x00000009"
1009
1010         copytool_cleanup
1011 }
1012 run_test 8 "Test default archive number"
1013
1014 test_9() {
1015         # we do not use the default one to be sure
1016         local new_an=$((HSM_ARCHIVE_NUMBER + 1))
1017         copytool_cleanup
1018         copytool_setup $SINGLEAGT $MOUNT $new_an
1019
1020         # give time for CT to register with MDTs
1021         sleep $(($MDSCOUNT*2))
1022         local uuid=$(get_agent_uuid $(facet_active_host $SINGLEAGT))
1023         check_agent_registered $uuid
1024
1025         mkdir -p $DIR/$tdir
1026         local f=$DIR/$tdir/$tfile
1027         local fid=$(copy_file /etc/passwd $f)
1028         $LFS hsm_archive --archive $new_an $f
1029         wait_request_state $fid ARCHIVE SUCCEED
1030
1031         check_hsm_flags $f "0x00000009"
1032
1033         copytool_cleanup
1034 }
1035 run_test 9 "Use of explicit archive number, with dedicated copytool"
1036
1037 test_9a() {
1038         needclients 3 || return 0
1039
1040         local n
1041         local file
1042         local fid
1043
1044         copytool_cleanup $(comma_list $(agts_nodes))
1045
1046         # start all of the copytools
1047         for n in $(seq $AGTCOUNT); do
1048                 copytool_setup agt$n
1049         done
1050
1051         trap "copytool_cleanup $(comma_list $(agts_nodes))" EXIT
1052         # archive files
1053         mkdir -p $DIR/$tdir
1054         for n in $(seq $AGTCOUNT); do
1055                 file=$DIR/$tdir/$tfile.$n
1056                 fid=$(make_small $file)
1057
1058                 $LFS hsm_archive $file || error "could not archive file $file"
1059                 wait_request_state $fid ARCHIVE SUCCEED
1060                 check_hsm_flags $file "0x00000009"
1061         done
1062
1063         trap - EXIT
1064         copytool_cleanup $(comma_list $(agts_nodes))
1065 }
1066 run_test 9a "Multiple remote agents"
1067
1068 test_10a() {
1069         # test needs a running copytool
1070         copytool_setup
1071
1072         mkdir -p $DIR/$tdir/d1
1073         local f=$DIR/$tdir/$tfile
1074         local fid=$(copy_file /etc/hosts $f)
1075         $LFS hsm_archive -a $HSM_ARCHIVE_NUMBER $f ||
1076                 error "hsm_archive failed"
1077         wait_request_state $fid ARCHIVE SUCCEED
1078
1079         local AFILE=$(do_facet $SINGLEAGT ls $HSM_ARCHIVE'/*/*/*/*/*/*/'$fid) ||
1080                 error "fid $fid not in archive $HSM_ARCHIVE"
1081         echo "Verifying content"
1082         do_facet $SINGLEAGT diff $f $AFILE || error "archived file differs"
1083         echo "Verifying hsm state "
1084         check_hsm_flags $f "0x00000009"
1085
1086         echo "Verifying archive number is $HSM_ARCHIVE_NUMBER"
1087         local st=$(get_hsm_archive_id $f)
1088         [[ $st == $HSM_ARCHIVE_NUMBER ]] ||
1089                 error "Wrong archive number, $st != $HSM_ARCHIVE_NUMBER"
1090
1091         copytool_cleanup
1092
1093 }
1094 run_test 10a "Archive a file"
1095
1096 test_10b() {
1097         # test needs a running copytool
1098         copytool_setup
1099
1100         mkdir -p $DIR/$tdir
1101         local f=$DIR/$tdir/$tfile
1102         local fid=$(copy_file /etc/hosts $f)
1103         $LFS hsm_archive $f || error "archive request failed"
1104         wait_request_state $fid ARCHIVE SUCCEED
1105
1106         $LFS hsm_archive $f || error "archive of non dirty file failed"
1107         local cnt=$(get_request_count $fid ARCHIVE)
1108         [[ "$cnt" == "1" ]] ||
1109                 error "archive of non dirty file must not make a request"
1110
1111         copytool_cleanup
1112 }
1113 run_test 10b "Archive of non dirty file must work without doing request"
1114
1115 test_10c() {
1116         # test needs a running copytool
1117         copytool_setup
1118
1119         mkdir -p $DIR/$tdir
1120         local f=$DIR/$tdir/$tfile
1121         local fid=$(copy_file /etc/hosts $f)
1122         $LFS hsm_set --noarchive $f
1123         $LFS hsm_archive $f && error "archive a noarchive file must fail"
1124
1125         copytool_cleanup
1126 }
1127 run_test 10c "Check forbidden archive"
1128
1129 test_10d() {
1130         # test needs a running copytool
1131         copytool_setup
1132
1133         mkdir -p $DIR/$tdir
1134         local f=$DIR/$tdir/$tfile
1135         local fid=$(copy_file /etc/hosts $f)
1136         $LFS hsm_archive $f || error "cannot archive $f"
1137         wait_request_state $fid ARCHIVE SUCCEED
1138
1139         local ar=$(get_hsm_archive_id $f)
1140         local dflt=$(get_hsm_param default_archive_id)
1141         [[ $ar == $dflt ]] ||
1142                 error "archived file is not on default archive: $ar != $dflt"
1143
1144         copytool_cleanup
1145 }
1146 run_test 10d "Archive a file on the default archive id"
1147
1148 test_11a() {
1149         mkdir -p $DIR/$tdir
1150         copy2archive /etc/hosts $tdir/$tfile
1151         local f=$DIR/$tdir/$tfile
1152
1153         import_file $tdir/$tfile $f
1154         echo -n "Verifying released state: "
1155         check_hsm_flags $f "0x0000000d"
1156
1157         local LSZ=$(stat -c "%s" $f)
1158         local ASZ=$(do_facet $SINGLEAGT stat -c "%s" $HSM_ARCHIVE/$tdir/$tfile)
1159
1160         echo "Verifying imported size $LSZ=$ASZ"
1161         [[ $LSZ -eq $ASZ ]] || error "Incorrect size $LSZ != $ASZ"
1162         echo -n "Verifying released pattern: "
1163         local PTRN=$($GETSTRIPE -L $f)
1164         echo $PTRN
1165         [[ $PTRN == 80000001 ]] || error "Is not released"
1166         local fid=$(path2fid $f)
1167         echo "Verifying new fid $fid in archive"
1168
1169         local AFILE=$(do_facet $SINGLEAGT ls $HSM_ARCHIVE'/*/*/*/*/*/*/'$fid) ||
1170                 error "fid $fid not in archive $HSM_ARCHIVE"
1171 }
1172 run_test 11a "Import a file"
1173
1174 test_11b() {
1175         # test needs a running copytool
1176         copytool_setup
1177
1178         mkdir -p $DIR/$tdir
1179         local f=$DIR/$tdir/$tfile
1180         local fid=$(copy_file /etc/hosts $f)
1181         $LFS hsm_archive -a $HSM_ARCHIVE_NUMBER $f ||
1182                 error "hsm_archive failed"
1183         wait_request_state $fid ARCHIVE SUCCEED
1184
1185         local FILE_HASH=$(md5sum $f)
1186         rm -f $f
1187
1188         import_file $fid $f
1189
1190         echo "$FILE_HASH" | md5sum -c
1191
1192         [[ $? -eq 0 ]] || error "Restored file differs"
1193
1194         copytool_cleanup
1195 }
1196 run_test 11b "Import a deleted file using its FID"
1197
1198 test_12a() {
1199         # test needs a running copytool
1200         copytool_setup
1201
1202         mkdir -p $DIR/$tdir
1203         copy2archive /etc/hosts $tdir/$tfile
1204
1205         local f=$DIR/$tdir/$tfile
1206         import_file $tdir/$tfile $f
1207         local f2=$DIR2/$tdir/$tfile
1208         echo "Verifying released state: "
1209         check_hsm_flags $f2 "0x0000000d"
1210
1211         local fid=$(path2fid $f2)
1212         $LFS hsm_restore $f2
1213         wait_request_state $fid RESTORE SUCCEED
1214
1215         echo "Verifying file state: "
1216         check_hsm_flags $f2 "0x00000009"
1217
1218         do_facet $SINGLEAGT diff -q $HSM_ARCHIVE/$tdir/$tfile $f
1219
1220         [[ $? -eq 0 ]] || error "Restored file differs"
1221
1222         copytool_cleanup
1223 }
1224 run_test 12a "Restore an imported file explicitly"
1225
1226 test_12b() {
1227         # test needs a running copytool
1228         copytool_setup
1229
1230         mkdir -p $DIR/$tdir
1231         copy2archive /etc/hosts $tdir/$tfile
1232
1233         local f=$DIR/$tdir/$tfile
1234         import_file $tdir/$tfile $f
1235         echo "Verifying released state: "
1236         check_hsm_flags $f "0x0000000d"
1237
1238         cat $f > /dev/null || error "File read failed"
1239
1240         echo "Verifying file state after restore: "
1241         check_hsm_flags $f "0x00000009"
1242
1243         do_facet $SINGLEAGT diff -q $HSM_ARCHIVE/$tdir/$tfile $f
1244
1245         [[ $? -eq 0 ]] || error "Restored file differs"
1246
1247         copytool_cleanup
1248 }
1249 run_test 12b "Restore an imported file implicitly"
1250
1251 test_12c() {
1252         [ "$OSTCOUNT" -lt "2" ] && skip_env "skipping 2-stripe test" && return
1253
1254         # test needs a running copytool
1255         copytool_setup
1256
1257         mkdir -p $DIR/$tdir
1258         local f=$DIR/$tdir/$tfile
1259         $LFS setstripe -c 2 $f
1260         local fid
1261         fid=$(make_custom_file_for_progress $f 5)
1262         [ $? != 0 ] && skip "not enough free space" && return
1263
1264         local FILE_CRC=$(md5sum $f)
1265
1266         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1267         wait_request_state $fid ARCHIVE SUCCEED
1268         $LFS hsm_release $f || error "release $f failed"
1269
1270         echo "$FILE_CRC" | md5sum -c
1271
1272         [[ $? -eq 0 ]] || error "Restored file differs"
1273
1274         copytool_cleanup
1275 }
1276 run_test 12c "Restore a file with stripe of 2"
1277
1278 test_12d() {
1279         # test needs a running copytool
1280         copytool_setup
1281
1282         mkdir -p $DIR/$tdir
1283
1284         local f=$DIR/$tdir/$tfile
1285         local fid=$(copy_file /etc/hosts $f)
1286         $LFS hsm_restore $f || error "restore of non archived file failed"
1287         local cnt=$(get_request_count $fid RESTORE)
1288         [[ "$cnt" == "0" ]] ||
1289                 error "restore non archived must not make a request"
1290         $LFS hsm_archive $f ||
1291                 error "archive request failed"
1292         wait_request_state $fid ARCHIVE SUCCEED
1293         $LFS hsm_restore $f ||
1294                 error "restore of non released file failed"
1295         local cnt=$(get_request_count $fid RESTORE)
1296         [[ "$cnt" == "0" ]] ||
1297                 error "restore a non dirty file must not make a request"
1298
1299         copytool_cleanup
1300 }
1301 run_test 12d "Restore of a non archived, non released file must work"\
1302                 " without doing request"
1303
1304 test_12e() {
1305         # test needs a running copytool
1306         copytool_setup
1307
1308         mkdir -p $DIR/$tdir $HSM_ARCHIVE/$tdir
1309         local f=$DIR/$tdir/$tfile
1310         local fid=$(copy_file /etc/hosts $f)
1311         $LFS hsm_archive $f || error "archive request failed"
1312         wait_request_state $fid ARCHIVE SUCCEED
1313
1314         # make file dirty
1315         cat /etc/hosts >> $f
1316         sync
1317         $LFS hsm_state $f
1318
1319         $LFS hsm_restore $f && error "restore a dirty file must fail"
1320
1321         copytool_cleanup
1322 }
1323 run_test 12e "Check forbidden restore"
1324
1325 test_12f() {
1326         # test needs a running copytool
1327         copytool_setup
1328
1329         mkdir -p $DIR/$tdir
1330         local f=$DIR/$tdir/$tfile
1331         local fid=$(copy_file /etc/hosts $f)
1332
1333         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1334         wait_request_state $fid ARCHIVE SUCCEED
1335         $LFS hsm_release $f || error "release of $f failed"
1336         $LFS hsm_restore $f
1337         wait_request_state $fid RESTORE SUCCEED
1338
1339         echo -n "Verifying file state: "
1340         check_hsm_flags $f "0x00000009"
1341
1342         diff -q /etc/hosts $f
1343
1344         [[ $? -eq 0 ]] || error "Restored file differs"
1345
1346         copytool_cleanup
1347 }
1348 run_test 12f "Restore a released file explicitly"
1349
1350 test_12g() {
1351         # test needs a running copytool
1352         copytool_setup
1353
1354         mkdir -p $DIR/$tdir
1355         local f=$DIR/$tdir/$tfile
1356         local fid=$(copy_file /etc/hosts $f)
1357
1358         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1359         wait_request_state $fid ARCHIVE SUCCEED
1360         $LFS hsm_release $f || error "release of $f failed"
1361
1362         diff -q /etc/hosts $f
1363         local st=$?
1364
1365         # we check we had a restore done
1366         wait_request_state $fid RESTORE SUCCEED
1367
1368         [[ $st -eq 0 ]] || error "Restored file differs"
1369
1370         copytool_cleanup
1371 }
1372 run_test 12g "Restore a released file implicitly"
1373
1374 test_12h() {
1375         needclients 2 || return 0
1376
1377         # test needs a running copytool
1378         copytool_setup
1379
1380         mkdir -p $DIR/$tdir
1381         local f=$DIR/$tdir/$tfile
1382         local fid=$(copy_file /etc/hosts $f)
1383
1384         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1385         wait_request_state $fid ARCHIVE SUCCEED
1386         $LFS hsm_release $f || error "release of $f failed"
1387
1388         do_node $CLIENT2 diff -q /etc/hosts $f
1389         local st=$?
1390
1391         # we check we had a restore done
1392         wait_request_state $fid RESTORE SUCCEED
1393
1394         [[ $st -eq 0 ]] || error "Restored file differs"
1395
1396         copytool_cleanup
1397 }
1398 run_test 12h "Restore a released file implicitly from a second node"
1399
1400 test_12m() {
1401         # test needs a running copytool
1402         copytool_setup
1403
1404         mkdir -p $DIR/$tdir
1405         local f=$DIR/$tdir/$tfile
1406         local fid=$(copy_file /etc/passwd $f)
1407         $LFS hsm_archive $f || error "archive of $f failed"
1408         wait_request_state $fid ARCHIVE SUCCEED
1409
1410         $LFS hsm_release $f || error "release of $f failed"
1411
1412         cmp /etc/passwd $f
1413
1414         [[ $? -eq 0 ]] || error "Restored file differs"
1415
1416         copytool_cleanup
1417 }
1418 run_test 12m "Archive/release/implicit restore"
1419
1420 test_12n() {
1421         # test needs a running copytool
1422         copytool_setup
1423
1424         mkdir -p $DIR/$tdir
1425         copy2archive /etc/hosts $tdir/$tfile
1426
1427         local f=$DIR/$tdir/$tfile
1428         import_file $tdir/$tfile $f
1429
1430         do_facet $SINGLEAGT cmp /etc/hosts $f ||
1431                 error "Restored file differs"
1432
1433         $LFS hsm_release $f || error "release of $f failed"
1434
1435         copytool_cleanup
1436 }
1437 run_test 12n "Import/implicit restore/release"
1438
1439 test_12o() {
1440         # test needs a running copytool
1441         copytool_setup
1442
1443         mkdir -p $DIR/$tdir
1444         local f=$DIR/$tdir/$tfile
1445         local fid=$(copy_file /etc/hosts $f)
1446
1447         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1448         wait_request_state $fid ARCHIVE SUCCEED
1449         $LFS hsm_release $f || error "release of $f failed"
1450
1451 #define OBD_FAIL_MDS_HSM_SWAP_LAYOUTS           0x152
1452         do_facet $SINGLEMDS lctl set_param fail_loc=0x152
1453
1454         # set no retry action mode
1455         cdt_set_no_retry
1456
1457         diff -q /etc/hosts $f
1458         local st=$?
1459
1460         # we check we had a restore failure
1461         wait_request_state $fid RESTORE FAILED
1462
1463         [[ $st -eq 0 ]] && error "Restore must fail"
1464
1465         # remove no retry action mode
1466         cdt_clear_no_retry
1467
1468         # check file is still released
1469         check_hsm_flags $f "0x0000000d"
1470
1471         # retry w/o failure injection
1472         do_facet $SINGLEMDS lctl set_param fail_loc=0
1473
1474         # to be sure previous RESTORE result is gone
1475         cdt_purge
1476         wait_for_grace_delay
1477
1478         diff -q /etc/hosts $f
1479         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 12o "Layout-swap failure during Restore leaves file released"
1489
1490 test_12p() {
1491         # test needs a running copytool
1492         copytool_setup
1493
1494         mkdir $DIR/$tdir
1495         local f=$DIR/$tdir/$tfile
1496         local fid=$(copy_file /etc/hosts $f)
1497
1498         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1499         wait_request_state $fid ARCHIVE SUCCEED
1500         do_facet $SINGLEAGT cat $f > /dev/null || error "cannot cat $f"
1501         $LFS hsm_release $f || error "cannot release $f"
1502         do_facet $SINGLEAGT cat $f > /dev/null || error "cannot cat $f"
1503         $LFS hsm_release $f || error "cannot release $f"
1504         do_facet $SINGLEAGT cat $f > /dev/null || error "cannot cat $f"
1505
1506         copytool_cleanup
1507 }
1508 run_test 12p "implicit restore of a file on copytool mount point"
1509
1510 cleanup_test_12q() {
1511         trap 0
1512         zconf_umount $(facet_host $SINGLEAGT) $MOUNT3 ||
1513                 error "cannot umount $MOUNT3 on $SINGLEAGT"
1514 }
1515
1516 test_12q() {
1517         [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.7.58) ] &&
1518                 skip "need MDS version at least 2.7.58" && return 0
1519
1520         zconf_mount $(facet_host $SINGLEAGT) $MOUNT3 ||
1521                 error "cannot mount $MOUNT3 on $SINGLEAGT"
1522
1523         trap cleanup_test_12q EXIT
1524
1525         # test needs a running copytool
1526         copytool_setup $SINGLEAGT $MOUNT3
1527
1528         mkdir $DIR/$tdir
1529         local f=$DIR/$tdir/$tfile
1530         local f2=$DIR2/$tdir/$tfile
1531         local fid=$(make_small $f)
1532         local orig_size=$(stat -c "%s" $f)
1533
1534         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1535         wait_request_state $fid ARCHIVE SUCCEED
1536
1537         $LFS hsm_release $f || error "could not release file"
1538         check_hsm_flags $f "0x0000000d"
1539
1540         kill_copytools
1541         wait_copytools || error "copytool failed to stop"
1542
1543         cat $f > /dev/null &
1544
1545         # wait a bit to allow implicit restore request to be handled.
1546         # if not, next stat would also block on layout-lock.
1547         sleep 5
1548
1549         local size=$(stat -c "%s" $f2)
1550         [ $size -eq $orig_size ] ||
1551                 error "$f2: wrong size after archive: $size != $orig_size"
1552
1553         HSM_ARCHIVE_PURGE=false copytool_setup $SINGLEAGT /mnt/lustre3
1554
1555         wait
1556
1557         size=$(stat -c "%s" $f)
1558         [ $size -eq $orig_size ] ||
1559                 error "$f: wrong size after restore: $size != $orig_size"
1560
1561         size=$(stat -c "%s" $f2)
1562         [ $size -eq $orig_size ] ||
1563                 error "$f2: wrong size after restore: $size != $orig_size"
1564
1565         :>$f
1566
1567         size=$(stat -c "%s" $f)
1568         [ $size -eq 0 ] ||
1569                 error "$f: wrong size after overwrite: $size != 0"
1570
1571         size=$(stat -c "%s" $f2)
1572         [ $size -eq 0 ] ||
1573                 error "$f2: wrong size after overwrite: $size != 0"
1574
1575         copytool_cleanup
1576         zconf_umount $(facet_host $SINGLEAGT) $MOUNT3 ||
1577                 error "cannot umount $MOUNT3 on $SINGLEAGT"
1578 }
1579 run_test 12q "file attributes are refreshed after restore"
1580
1581 test_13() {
1582         # test needs a running copytool
1583         copytool_setup
1584
1585         local ARC_SUBDIR="import.orig"
1586         local d=""
1587         local f=""
1588
1589         # populate directory to be imported
1590         for d in $(seq 1 10); do
1591                 local CURR_DIR="$HSM_ARCHIVE/$ARC_SUBDIR/dir.$d"
1592                 do_facet $SINGLEAGT mkdir -p "$CURR_DIR"
1593                 for f in $(seq 1 10); do
1594                         CURR_FILE="$CURR_DIR/$tfile.$f"
1595                         # write file-specific data
1596                         do_facet $SINGLEAGT \
1597                                 "echo d=$d, f=$f, dir=$CURR_DIR, "\
1598                                         "file=$CURR_FILE > $CURR_FILE"
1599                 done
1600         done
1601         # import to Lustre
1602         import_file "$ARC_SUBDIR" $DIR/$tdir
1603         # diff lustre content and origin (triggers file restoration)
1604         # there must be 10x10 identical files, and no difference
1605         local cnt_ok=$(do_facet $SINGLEAGT diff -rs $HSM_ARCHIVE/$ARC_SUBDIR \
1606                        $DIR/$tdir/$ARC_SUBDIR | grep identical | wc -l)
1607         local cnt_diff=$(do_facet $SINGLEAGT diff -r $HSM_ARCHIVE/$ARC_SUBDIR \
1608                          $DIR/$tdir/$ARC_SUBDIR | wc -l)
1609
1610         [ $cnt_diff -eq 0 ] ||
1611                 error "$cnt_diff imported files differ from read data"
1612         [ $cnt_ok -eq 100 ] ||
1613                 error "not enough identical files ($cnt_ok != 100)"
1614
1615         copytool_cleanup
1616 }
1617 run_test 13 "Recursively import and restore a directory"
1618
1619 test_14() {
1620         # test needs a running copytool
1621         copytool_setup
1622
1623         # archive a file
1624         mkdir -p $DIR/$tdir
1625         local f=$DIR/$tdir/$tfile
1626         local fid=$(make_small $f)
1627         local sum=$(md5sum $f | awk '{print $1}')
1628         $LFS hsm_archive $f || error "could not archive file"
1629         wait_request_state $fid ARCHIVE SUCCEED
1630
1631         # delete the file
1632         rm -f $f
1633         # create released file (simulate llapi_hsm_import call)
1634         touch $f
1635         local fid2=$(path2fid $f)
1636         $LFS hsm_set --archived --exists $f || error "could not force hsm flags"
1637         $LFS hsm_release $f || error "could not release file"
1638
1639         # rebind the archive to the newly created file
1640         echo "rebind $fid to $fid2"
1641
1642         do_facet $SINGLEAGT \
1643                 "$HSMTOOL --archive $HSM_ARCHIVE_NUMBER --hsm-root $HSM_ARCHIVE\
1644                  --rebind $fid $fid2 $DIR" || error "could not rebind file"
1645
1646         # restore file and compare md5sum
1647         local sum2=$(md5sum $f | awk '{print $1}')
1648
1649         [[ $sum == $sum2 ]] || error "md5sum mismatch after restore"
1650
1651         copytool_cleanup
1652 }
1653 run_test 14 "Rebind archived file to a new fid"
1654
1655 test_15() {
1656         # test needs a running copytool
1657         copytool_setup
1658
1659         # archive files
1660         mkdir -p $DIR/$tdir
1661         local f=$DIR/$tdir/$tfile
1662         local count=5
1663         local tmpfile=$SHARED_DIRECTORY/tmp.$$
1664
1665         local fids=()
1666         local sums=()
1667         for i in $(seq 1 $count); do
1668                 fids[$i]=$(make_small $f.$i)
1669                 sums[$i]=$(md5sum $f.$i | awk '{print $1}')
1670                 $LFS hsm_archive $f.$i || error "could not archive file"
1671         done
1672         wait_all_done $(($count*60))
1673
1674         :>$tmpfile
1675         # delete the files
1676         for i in $(seq 1 $count); do
1677                 rm -f $f.$i
1678                 touch $f.$i
1679                 local fid2=$(path2fid $f.$i)
1680                 # add the rebind operation to the list
1681                 echo ${fids[$i]} $fid2 >> $tmpfile
1682
1683                 # set it released (simulate llapi_hsm_import call)
1684                 $LFS hsm_set --archived --exists $f.$i ||
1685                         error "could not force hsm flags"
1686                 $LFS hsm_release $f.$i || error "could not release file"
1687         done
1688         nl=$(wc -l < $tmpfile)
1689         [[ $nl == $count ]] || error "$nl files in list, $count expected"
1690
1691         echo "rebind list of files"
1692         do_facet $SINGLEAGT \
1693                 "$HSMTOOL --archive $HSM_ARCHIVE_NUMBER --hsm-root $HSM_ARCHIVE\
1694                  --rebind $tmpfile $DIR" || error "could not rebind file list"
1695
1696         # restore files and compare md5sum
1697         for i in $(seq 1 $count); do
1698                 local sum2=$(md5sum $f.$i | awk '{print $1}')
1699                 [[ $sum2 == ${sums[$i]} ]] ||
1700                     error "md5sum mismatch after restore ($sum2 != ${sums[$i]})"
1701         done
1702
1703         rm -f $tmpfile
1704         copytool_cleanup
1705 }
1706 run_test 15 "Rebind a list of files"
1707
1708 test_16() {
1709         # test needs a running copytool
1710         copytool_setup
1711
1712         local ref=/tmp/ref
1713         # create a known size file so we can verify transfer speed
1714         # 20 MB <-> 20s
1715         local goal=20
1716         dd if=/dev/zero of=$ref bs=1M count=20
1717
1718         mkdir -p $DIR/$tdir
1719         local f=$DIR/$tdir/$tfile
1720         local fid=$(copy_file $ref $f)
1721         rm $ref
1722         local start=$(date +%s)
1723         $LFS hsm_archive $f
1724         wait_request_state $fid ARCHIVE SUCCEED
1725         local end=$(date +%s)
1726         # Add 1 to account for rounding errors between start and end (LU-8155)
1727         local duration=$((end - start + 1))
1728
1729         [[ $duration -ge $goal ]] ||
1730                 error "Transfer is too fast $duration < $goal"
1731
1732         copytool_cleanup
1733 }
1734 run_test 16 "Test CT bandwith control option"
1735
1736 test_20() {
1737         mkdir -p $DIR/$tdir
1738
1739         local f=$DIR/$tdir/$tfile
1740         touch $f || error "touch $f failed"
1741
1742         # Could not release a non-archived file
1743         $LFS hsm_release $f && error "release should not succeed"
1744
1745         # For following tests, we must test them with HS_ARCHIVED set
1746         $LFS hsm_set --exists --archived $f || error "could not add flag"
1747
1748         # Could not release a file if no-release is set
1749         $LFS hsm_set --norelease $f || error "could not add flag"
1750         $LFS hsm_release $f && error "release should not succeed"
1751         $LFS hsm_clear --norelease $f || error "could not remove flag"
1752
1753         # Could not release a file if lost
1754         $LFS hsm_set --lost $f || error "could not add flag"
1755         $LFS hsm_release $f && error "release should not succeed"
1756         $LFS hsm_clear --lost $f || error "could not remove flag"
1757
1758         # Could not release a file if dirty
1759         $LFS hsm_set --dirty $f || error "could not add flag"
1760         $LFS hsm_release $f && error "release should not succeed"
1761         $LFS hsm_clear --dirty $f || error "could not remove flag"
1762 }
1763 run_test 20 "Release is not permitted"
1764
1765 test_21() {
1766         # test needs a running copytool
1767         copytool_setup
1768
1769         mkdir -p $DIR/$tdir
1770         local f=$DIR/$tdir/test_release
1771
1772         # Create a file and check its states
1773         local fid=$(make_small $f)
1774         check_hsm_flags $f "0x00000000"
1775
1776         # LU-4388/LU-4389 - ZFS does not report full number of blocks
1777         # used until file is flushed to disk
1778         if [  $(facet_fstype ost1) == "zfs" ]; then
1779             # this causes an OST_SYNC rpc to be sent
1780             dd if=/dev/zero of=$f bs=512 count=1 oflag=sync conv=notrunc,fsync
1781             # clear locks to reread file data
1782             cancel_lru_locks osc
1783         fi
1784
1785         local orig_size=$(stat -c "%s" $f)
1786         local orig_blocks=$(stat -c "%b" $f)
1787
1788         start_full_debug_logging
1789
1790         $LFS hsm_archive $f || error "could not archive file"
1791         wait_request_state $fid ARCHIVE SUCCEED
1792
1793         local blocks=$(stat -c "%b" $f)
1794         [ $blocks -eq $orig_blocks ] ||
1795                 error "$f: wrong block number after archive: " \
1796                       "$blocks != $orig_blocks"
1797         local size=$(stat -c "%s" $f)
1798         [ $size -eq $orig_size ] ||
1799                 error "$f: wrong size after archive: $size != $orig_size"
1800
1801         # Release and check states
1802         $LFS hsm_release $f || error "could not release file"
1803         check_hsm_flags $f "0x0000000d"
1804
1805         blocks=$(stat -c "%b" $f)
1806         [ $blocks -gt 5 ] &&
1807                 error "$f: too many blocks after release: $blocks > 5"
1808         size=$(stat -c "%s" $f)
1809         [ $size -ne $orig_size ] &&
1810                 error "$f: wrong size after release: $size != $orig_size"
1811
1812         # Check we can release an file without stripe info
1813         f=$f.nolov
1814         $MCREATE $f
1815         fid=$(path2fid $f)
1816         check_hsm_flags $f "0x00000000"
1817         $LFS hsm_archive $f || error "could not archive file"
1818         wait_request_state $fid ARCHIVE SUCCEED
1819
1820         # Release and check states
1821         $LFS hsm_release $f || error "could not release file"
1822         check_hsm_flags $f "0x0000000d"
1823
1824         # Release again a file that is already released is OK
1825         $LFS hsm_release $f || fail "second release should succeed"
1826         check_hsm_flags $f "0x0000000d"
1827
1828         stop_full_debug_logging
1829
1830         copytool_cleanup
1831 }
1832 run_test 21 "Simple release tests"
1833
1834 test_22() {
1835         # test needs a running copytool
1836         copytool_setup
1837
1838         mkdir -p $DIR/$tdir
1839
1840         local f=$DIR/$tdir/test_release
1841         local swap=$DIR/$tdir/test_swap
1842
1843         # Create a file and check its states
1844         local fid=$(make_small $f)
1845         check_hsm_flags $f "0x00000000"
1846
1847         $LFS hsm_archive $f || error "could not archive file"
1848         wait_request_state $fid ARCHIVE SUCCEED
1849
1850         # Release and check states
1851         $LFS hsm_release $f || error "could not release file"
1852         check_hsm_flags $f "0x0000000d"
1853
1854         make_small $swap
1855         $LFS swap_layouts $swap $f && error "swap_layouts should failed"
1856
1857         true
1858         copytool_cleanup
1859 }
1860 run_test 22 "Could not swap a release file"
1861
1862 test_23() {
1863         # test needs a running copytool
1864         copytool_setup
1865
1866         mkdir -p $DIR/$tdir
1867
1868         local f=$DIR/$tdir/test_mtime
1869
1870         # Create a file and check its states
1871         local fid=$(make_small $f)
1872         check_hsm_flags $f "0x00000000"
1873
1874         $LFS hsm_archive $f || error "could not archive file"
1875         wait_request_state $fid ARCHIVE SUCCEED
1876
1877         # Set modification time in the past
1878         touch -m -a -d @978261179 $f
1879
1880         # Release and check states
1881         $LFS hsm_release $f || error "could not release file"
1882         check_hsm_flags $f "0x0000000d"
1883
1884         local MTIME=$(stat -c "%Y" $f)
1885         local ATIME=$(stat -c "%X" $f)
1886         [ $MTIME -eq "978261179" ] || fail "bad mtime: $MTIME"
1887         [ $ATIME -eq "978261179" ] || fail "bad atime: $ATIME"
1888
1889         copytool_cleanup
1890 }
1891 run_test 23 "Release does not change a/mtime (utime)"
1892
1893 test_24a() {
1894         local file=$DIR/$tdir/$tfile
1895         local fid
1896         local atime0
1897         local atime1
1898         local mtime0
1899         local mtime1
1900         local ctime0
1901         local ctime1
1902
1903         # test needs a running copytool
1904         copytool_setup
1905
1906         mkdir -p $DIR/$tdir
1907         rm -f $file
1908         fid=$(make_small $file)
1909
1910         # Create a file and check its states
1911         check_hsm_flags $file "0x00000000"
1912
1913         # Ensure atime is less than mtime and ctime.
1914         sleep 1
1915         echo >> $file
1916
1917         atime0=$(stat -c "%X" $file)
1918         mtime0=$(stat -c "%Y" $file)
1919         ctime0=$(stat -c "%Z" $file)
1920
1921         [ $atime0 -lt $mtime0 ] ||
1922                 error "atime $atime0 is not less than mtime $mtime0"
1923
1924         [ $atime0 -lt $ctime0 ] ||
1925                 error "atime $atime0 is not less than ctime $ctime0"
1926
1927         # Archive should not change any timestamps.
1928         $LFS hsm_archive $file || error "cannot archive '$file'"
1929         wait_request_state $fid ARCHIVE SUCCEED
1930
1931         atime1=$(stat -c "%X" $file)
1932         mtime1=$(stat -c "%Y" $file)
1933         ctime1=$(stat -c "%Z" $file)
1934
1935         [ $atime0 -eq $atime1 ] ||
1936                 error "archive changed atime from $atime0 to $atime1"
1937
1938         [ $mtime0 -eq $mtime1 ] ||
1939                 error "archive changed mtime from $mtime0 to $mtime1"
1940
1941         [ $ctime0 -eq $ctime1 ] ||
1942                 error "archive changed ctime from $ctime0 to $ctime1"
1943
1944         # Release should not change any timestamps.
1945         $LFS hsm_release $file || error "cannot release '$file'"
1946         check_hsm_flags $file "0x0000000d"
1947
1948         atime1=$(stat -c "%X" $file)
1949         mtime1=$(stat -c "%Y" $file)
1950         ctime1=$(stat -c "%Z" $file)
1951
1952         [ $atime0 -eq $atime1 ] ||
1953                 error "release changed atime from $atime0 to $atime1"
1954
1955         [ $mtime0 -eq $mtime1 ] ||
1956                 error "release changed mtime from $mtime0 to $mtime1"
1957
1958         [ $ctime0 -eq $ctime1 ] ||
1959                 error "release changed ctime from $ctime0 to $ctime1"
1960
1961         # Restore should not change any timestamps.
1962         $LFS hsm_restore $file
1963         wait_request_state $fid RESTORE SUCCEED
1964
1965         atime1=$(stat -c "%X" $file)
1966         mtime1=$(stat -c "%Y" $file)
1967         ctime1=$(stat -c "%Z" $file)
1968
1969         [ $atime0 -eq $atime1 ] ||
1970                 error "restore changed atime from $atime0 to $atime1"
1971
1972         [ $mtime0 -eq $mtime1 ] ||
1973                 error "restore changed mtime from $mtime0 to $mtime1"
1974
1975         [ $ctime0 -eq $ctime1 ] ||
1976                 error "restore changed ctime from $ctime0 to $ctime1"
1977
1978         copytool_cleanup
1979
1980         # Once more, after unmount and mount.
1981         umount_client $MOUNT || error "cannot unmount '$MOUNT'"
1982         mount_client $MOUNT || error "cannot mount '$MOUNT'"
1983
1984         atime1=$(stat -c "%X" $file)
1985         mtime1=$(stat -c "%Y" $file)
1986         ctime1=$(stat -c "%Z" $file)
1987
1988         [ $atime0 -eq $atime1 ] ||
1989                 error "remount changed atime from $atime0 to $atime1"
1990
1991         [ $mtime0 -eq $mtime1 ] ||
1992                 error "remount changed mtime from $mtime0 to $mtime1"
1993
1994         [ $ctime0 -eq $ctime1 ] ||
1995                 error "remount changed ctime from $ctime0 to $ctime1"
1996 }
1997 run_test 24a "Archive, release, and restore does not change a/mtime (i/o)"
1998
1999 test_24b() {
2000         local file=$DIR/$tdir/$tfile
2001         local fid
2002         local sum0
2003         local sum1
2004         # LU-3811
2005
2006         # Test needs a running copytool.
2007         copytool_setup
2008         mkdir -p $DIR/$tdir
2009
2010         # Check that root can do HSM actions on a regular user's file.
2011         rm -f $file
2012         fid=$(make_small $file)
2013         sum0=$(md5sum $file)
2014
2015         chown $RUNAS_ID:$RUNAS_GID $file ||
2016                 error "cannot chown '$file' to '$RUNAS_ID'"
2017
2018         chmod ugo-w $DIR/$tdir ||
2019                 error "cannot chmod '$DIR/$tdir'"
2020
2021         $LFS hsm_archive $file
2022         wait_request_state $fid ARCHIVE SUCCEED
2023
2024         $LFS hsm_release $file
2025         check_hsm_flags $file "0x0000000d"
2026
2027         $LFS hsm_restore $file
2028         wait_request_state $fid RESTORE SUCCEED
2029
2030         # Check that ordinary user can get HSM state.
2031         $RUNAS $LFS hsm_state $file ||
2032                 error "user '$RUNAS_ID' cannot get HSM state of '$file'"
2033
2034         $LFS hsm_release $file
2035         check_hsm_flags $file "0x0000000d"
2036
2037         # Check that ordinary user can accessed released file.
2038         sum1=$($RUNAS md5sum $file) ||
2039                 error "user '$RUNAS_ID' cannot read '$file'"
2040
2041         [ "$sum0" == "$sum1" ] ||
2042                 error "md5sum mismatch for '$file'"
2043
2044         copytool_cleanup
2045 }
2046 run_test 24b "root can archive, release, and restore user files"
2047
2048 cleanup_test_24c() {
2049         trap 0
2050         set_hsm_param user_request_mask RESTORE
2051         set_hsm_param group_request_mask RESTORE
2052         set_hsm_param other_request_mask RESTORE
2053 }
2054
2055 test_24c() {
2056         local file=$DIR/$tdir/$tfile
2057         local action=archive
2058         local user_save
2059         local group_save
2060         local other_save
2061
2062         # test needs a running copytool
2063         copytool_setup
2064
2065         mkdir -p $DIR/$tdir
2066
2067         # Save the default masks and check that cleanup_24c will
2068         # restore the request masks correctly.
2069         user_save=$(get_hsm_param user_request_mask)
2070         group_save=$(get_hsm_param group_request_mask)
2071         other_save=$(get_hsm_param other_request_mask)
2072
2073         [ "$user_save" == RESTORE ] ||
2074                 error "user_request_mask is '$user_save' expected 'RESTORE'"
2075         [ "$group_save" == RESTORE ] ||
2076                 error "group_request_mask is '$group_save' expected 'RESTORE'"
2077         [ "$other_save" == RESTORE ] ||
2078                 error "other_request_mask is '$other_save' expected 'RESTORE'"
2079
2080         trap cleanup_test_24c EXIT
2081
2082         # User.
2083         rm -f $file
2084         make_small $file
2085         chown $RUNAS_ID:nobody $file ||
2086                 error "cannot chown '$file' to '$RUNAS_ID:nobody'"
2087
2088         $RUNAS $LFS hsm_$action $file &&
2089                 error "$action by user should fail"
2090
2091         set_hsm_param user_request_mask $action
2092         $RUNAS $LFS hsm_$action $file ||
2093                 error "$action by user should succeed"
2094
2095         # Group.
2096         rm -f $file
2097         make_small $file
2098         chown nobody:$RUNAS_GID $file ||
2099                 error "cannot chown '$file' to 'nobody:$RUNAS_GID'"
2100
2101         $RUNAS $LFS hsm_$action $file &&
2102                 error "$action by group should fail"
2103
2104         set_hsm_param group_request_mask $action
2105         $RUNAS $LFS hsm_$action $file ||
2106                 error "$action by group should succeed"
2107
2108         # Other.
2109         rm -f $file
2110         make_small $file
2111         chown nobody:nobody $file ||
2112                 error "cannot chown '$file' to 'nobody:nobody'"
2113
2114         $RUNAS $LFS hsm_$action $file &&
2115                 error "$action by other should fail"
2116
2117         set_hsm_param other_request_mask $action
2118         $RUNAS $LFS hsm_$action $file ||
2119                 error "$action by other should succeed"
2120
2121         copytool_cleanup
2122         cleanup_test_24c
2123 }
2124 run_test 24c "check that user,group,other request masks work"
2125
2126 cleanup_test_24d() {
2127         trap 0
2128         mount -o remount,rw $MOUNT2
2129 }
2130
2131 test_24d() {
2132         local file1=$DIR/$tdir/$tfile
2133         local file2=$DIR2/$tdir/$tfile
2134         local fid1
2135         local fid2
2136
2137         copytool_setup
2138
2139         mkdir -p $DIR/$tdir
2140         rm -f $file1
2141         fid1=$(make_small $file1)
2142
2143         trap cleanup_test_24d EXIT
2144
2145         mount -o remount,ro $MOUNT2
2146
2147         fid2=$(path2fid $file2)
2148         [ "$fid1" == "$fid2" ] ||
2149                 error "FID mismatch '$fid1' != '$fid2'"
2150
2151         $LFS hsm_archive $file2 &&
2152                 error "archive should fail on read-only mount"
2153         check_hsm_flags $file1 "0x00000000"
2154
2155         $LFS hsm_archive $file1
2156         wait_request_state $fid1 ARCHIVE SUCCEED
2157
2158         $LFS hsm_release $file1
2159         $LFS hsm_restore $file2
2160         wait_request_state $fid1 RESTORE SUCCEED
2161
2162         $LFS hsm_release $file1 || error "cannot release '$file1'"
2163         dd if=$file2 of=/dev/null bs=1M || "cannot read '$file2'"
2164
2165         $LFS hsm_release $file2 &&
2166                 error "release should fail on read-only mount"
2167
2168         copytool_cleanup
2169         cleanup_test_24d
2170 }
2171 run_test 24d "check that read-only mounts are respected"
2172
2173 test_24e() {
2174         copytool_setup
2175
2176         mkdir -p $DIR/$tdir
2177
2178         local f=$DIR/$tdir/$tfile
2179         local fid
2180
2181         fid=$(make_small $f) || error "cannot create $f"
2182         $LFS hsm_archive $f || error "cannot archive $f"
2183         wait_request_state $fid ARCHIVE SUCCEED
2184         $LFS hsm_release $f || error "cannot release $f"
2185         while ! $LFS hsm_state $f | grep released; do
2186                 sleep 1
2187         done
2188
2189         tar -cf $TMP/$tfile.tar $DIR/$tdir || error "cannot tar $DIR/$tdir"
2190
2191         copytool_cleanup
2192 }
2193 run_test 24e "tar succeeds on HSM released files" # LU-6213
2194
2195 test_24f() {
2196
2197         # test needs a running copytool
2198         copytool_setup
2199
2200         mkdir -p $DIR/$tdir/d1
2201         local f=$DIR/$tdir/$tfile
2202         local fid=$(copy_file /etc/hosts $f)
2203         sum0=$(md5sum $f)
2204         echo $sum0
2205         $LFS hsm_archive -a $HSM_ARCHIVE_NUMBER $f ||
2206                 error "hsm_archive failed"
2207         wait_request_state $fid ARCHIVE SUCCEED
2208         $LFS hsm_release $f || error "cannot release $f"
2209         tar --xattrs -cvf $f.tar -C $DIR/$tdir $tfile
2210         rm -f $f
2211         sync
2212         tar --xattrs -xvf $f.tar -C $DIR/$tdir ||
2213                 error "Can not recover the tar contents"
2214         sum1=$(md5sum $f)
2215         echo "Sum0 = $sum0, sum1 = $sum1"
2216         [ "$sum0" == "$sum1" ] || error "md5sum mismatch for '$tfile'"
2217
2218         copytool_cleanup
2219 }
2220 run_test 24f "root can archive, release, and restore tar files"
2221
2222 test_25a() {
2223         # test needs a running copytool
2224         copytool_setup
2225
2226         mkdir -p $DIR/$tdir
2227         copy2archive /etc/hosts $tdir/$tfile
2228
2229         local f=$DIR/$tdir/$tfile
2230
2231         import_file $tdir/$tfile $f
2232
2233         $LFS hsm_set --lost $f
2234
2235         md5sum $f
2236         local st=$?
2237
2238         [[ $st == 1 ]] || error "lost file access should failed (returns $st)"
2239
2240         copytool_cleanup
2241 }
2242 run_test 25a "Restore lost file (HS_LOST flag) from import"\
2243              " (Operation not permitted)"
2244
2245 test_25b() {
2246         # test needs a running copytool
2247         copytool_setup
2248
2249         mkdir -p $DIR/$tdir
2250
2251         local f=$DIR/$tdir/$tfile
2252         local fid=$(copy_file /etc/passwd $f)
2253
2254         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2255         wait_request_state $fid ARCHIVE SUCCEED
2256
2257         $LFS hsm_release $f
2258         $LFS hsm_set --lost $f
2259         md5sum $f
2260         st=$?
2261
2262         [[ $st == 1 ]] || error "lost file access should failed (returns $st)"
2263
2264         copytool_cleanup
2265 }
2266 run_test 25b "Restore lost file (HS_LOST flag) after release"\
2267              " (Operation not permitted)"
2268
2269 test_26() {
2270         # test needs a running copytool
2271         copytool_setup
2272
2273         mkdir -p $DIR/$tdir
2274         local f=$DIR/$tdir/$tfile
2275         local fid
2276         fid=$(make_custom_file_for_progress $f 39 1000000)
2277         [ $? != 0 ] && skip "not enough free space" && return
2278
2279         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2280         wait_request_state $fid ARCHIVE SUCCEED
2281
2282         $LFS hsm_remove $f
2283         wait_request_state $fid REMOVE SUCCEED
2284
2285         check_hsm_flags $f "0x00000000"
2286
2287         copytool_cleanup
2288 }
2289 run_test 26 "Remove the archive of a valid file"
2290
2291 test_27a() {
2292         # test needs a running copytool
2293         copytool_setup
2294
2295         mkdir -p $DIR/$tdir
2296         make_archive $tdir/$tfile
2297         local f=$DIR/$tdir/$tfile
2298         import_file $tdir/$tfile $f
2299         local fid=$(path2fid $f)
2300
2301         $LFS hsm_remove $f
2302
2303         [[ $? != 0 ]] || error "Remove of a released file should fail"
2304
2305         copytool_cleanup
2306 }
2307 run_test 27a "Remove the archive of an imported file (Operation not permitted)"
2308
2309 test_27b() {
2310         # test needs a running copytool
2311         copytool_setup
2312
2313         mkdir -p $DIR/$tdir
2314         local f=$DIR/$tdir/$tfile
2315         local fid
2316         fid=$(make_custom_file_for_progress $f 39 1000000)
2317         [ $? != 0 ] && skip "not enough free space" && return
2318
2319         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2320         wait_request_state $fid ARCHIVE SUCCEED
2321         $LFS hsm_release $f
2322
2323         $LFS hsm_remove $f
2324
2325         [[ $? != 0 ]] || error "Remove of a released file should fail"
2326
2327         copytool_cleanup
2328 }
2329 run_test 27b "Remove the archive of a relased file (Operation not permitted)"
2330
2331 test_28() {
2332         # test needs a running copytool
2333         copytool_setup
2334
2335         mkdir -p $DIR/$tdir
2336         local f=$DIR/$tdir/$tfile
2337         local fid
2338         fid=$(make_custom_file_for_progress $f 39 1000000)
2339         [ $? != 0 ] && skip "not enough free space" && return
2340
2341         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2342         wait_request_state $fid ARCHIVE SUCCEED
2343
2344         cdt_disable
2345         $LFS hsm_remove $f
2346
2347         rm -f $f
2348
2349         cdt_enable
2350
2351         wait_request_state $fid REMOVE SUCCEED
2352
2353         copytool_cleanup
2354 }
2355 run_test 28 "Concurrent archive/file remove"
2356
2357 test_29a() {
2358         # Tests --mntpath and --archive options
2359
2360         local archive_id=7
2361         copytool_setup $SINGLEAGT $MOUNT $archive_id
2362
2363         # Bad archive number
2364         $LFS hsm_remove -m $MOUNT -a 33 0x857765760:0x8:0x2 2>&1 |
2365                 grep "Invalid argument" ||
2366                 error "unexpected hsm_remove failure (1)"
2367
2368         # mntpath is present but file is given
2369         $LFS hsm_remove --mntpath $MOUNT --archive 30 /qwerty/uyt 2>&1 |
2370                 grep "hsm: '/qwerty/uyt' is not a valid FID" ||
2371                 error "unexpected hsm_remove failure (2)"
2372
2373         copytool_cleanup
2374 }
2375 run_test 29a "Tests --mntpath and --archive options"
2376
2377 test_29b() {
2378         # test needs a running copytool
2379         copytool_setup
2380
2381         mkdir -p $DIR/$tdir
2382         local f=$DIR/$tdir/$tfile
2383         local fid=$(make_small $f)
2384
2385         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2386         wait_request_state $fid ARCHIVE SUCCEED
2387
2388         rm -f $f
2389
2390         $LFS hsm_remove -m $MOUNT -a $HSM_ARCHIVE_NUMBER $fid
2391         wait_request_state $fid REMOVE SUCCEED
2392
2393         copytool_cleanup
2394 }
2395 run_test 29b "Archive/delete/remove by FID from the archive."
2396
2397 test_29c() {
2398         # test needs a running copytool
2399         copytool_setup
2400
2401         mkdir -p $DIR/$tdir
2402         local fid1=$(make_small $DIR/$tdir/$tfile-1)
2403         local fid2=$(make_small $DIR/$tdir/$tfile-2)
2404         local fid3=$(make_small $DIR/$tdir/$tfile-3)
2405
2406         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $DIR/$tdir/$tfile-[1-3]
2407         wait_request_state $fid1 ARCHIVE SUCCEED
2408         wait_request_state $fid2 ARCHIVE SUCCEED
2409         wait_request_state $fid3 ARCHIVE SUCCEED
2410
2411         rm -f $DIR/$tdir/$tfile-[1-3]
2412
2413         echo $fid1 > $DIR/$tdir/list
2414         echo $fid2 >> $DIR/$tdir/list
2415         echo $fid3 >> $DIR/$tdir/list
2416
2417         $LFS hsm_remove -m $MOUNT -a $HSM_ARCHIVE_NUMBER \
2418                 --filelist $DIR/$tdir/list
2419         wait_request_state $fid1 REMOVE SUCCEED
2420         wait_request_state $fid2 REMOVE SUCCEED
2421         wait_request_state $fid3 REMOVE SUCCEED
2422
2423         copytool_cleanup
2424 }
2425 run_test 29c "Archive/delete/remove by FID, using a file list."
2426
2427 test_30a() {
2428         # restore at exec cannot work on agent node (because of Linux kernel
2429         # protection of executables)
2430         needclients 2 || return 0
2431
2432         # test needs a running copytool
2433         copytool_setup
2434
2435         mkdir -p $DIR/$tdir
2436         copy2archive /bin/true $tdir/$tfile
2437
2438         local f=$DIR/$tdir/true
2439         import_file $tdir/$tfile $f
2440
2441         local fid=$(path2fid $f)
2442
2443         # set no retry action mode
2444         cdt_set_no_retry
2445         do_node $CLIENT2 $f
2446         local st=$?
2447
2448         # cleanup
2449         # remove no try action mode
2450         cdt_clear_no_retry
2451         $LFS hsm_state $f
2452
2453         [[ $st == 0 ]] || error "Failed to exec a released file"
2454
2455         copytool_cleanup
2456 }
2457 run_test 30a "Restore at exec (import case)"
2458
2459 test_30b() {
2460         # restore at exec cannot work on agent node (because of Linux kernel
2461         # protection of executables)
2462         needclients 2 || return 0
2463
2464         # test needs a running copytool
2465         copytool_setup
2466
2467         mkdir -p $DIR/$tdir
2468         local f=$DIR/$tdir/true
2469         local fid=$(copy_file /bin/true $f)
2470         chmod 755 $f
2471         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2472         wait_request_state $fid ARCHIVE SUCCEED
2473         $LFS hsm_release $f
2474         $LFS hsm_state $f
2475         # set no retry action mode
2476         cdt_set_no_retry
2477         do_node $CLIENT2 $f
2478         local st=$?
2479
2480         # cleanup
2481         # remove no try action mode
2482         cdt_clear_no_retry
2483         $LFS hsm_state $f
2484
2485         [[ $st == 0 ]] || error "Failed to exec a released file"
2486
2487         copytool_cleanup
2488 }
2489 run_test 30b "Restore at exec (release case)"
2490
2491 test_30c() {
2492         needclients 2 || return 0
2493
2494         # test needs a running copytool
2495         copytool_setup
2496
2497         mkdir -p $DIR/$tdir
2498         local f=$DIR/$tdir/SLEEP
2499         local slp_sum1=$(md5sum /bin/sleep)
2500         local fid=$(copy_file /bin/sleep $f)
2501         chmod 755 $f
2502         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2503         wait_request_state $fid ARCHIVE SUCCEED
2504         $LFS hsm_release $f
2505         check_hsm_flags $f "0x0000000d"
2506         # set no retry action mode
2507         cdt_set_no_retry
2508         do_node $CLIENT2 "$f 10" &
2509         local pid=$!
2510         sleep 3
2511         echo 'Hi!' > $f
2512         [[ $? == 0 ]] && error "Update during exec of released file must fail"
2513         wait $pid
2514         [[ $? == 0 ]] || error "Execution failed during run"
2515         cmp /bin/sleep $f
2516         if [[ $? != 0 ]]; then
2517                 local slp_sum2=$(md5sum /bin/sleep)
2518                 # in case sleep file is modified during the test
2519                 [[ $slp_sum1 == $slp_sum2 ]] &&
2520                         error "Binary overwritten during exec"
2521         fi
2522
2523         # cleanup
2524         # remove no try action mode
2525         cdt_clear_no_retry
2526         check_hsm_flags $f "0x00000009"
2527
2528         copytool_cleanup
2529 }
2530 run_test 30c "Update during exec of released file must fail"
2531
2532 restore_and_check_size() {
2533         local f=$1
2534         local fid=$2
2535         local s=$(stat -c "%s" $f)
2536         local n=$s
2537         local st=$(get_hsm_flags $f)
2538         local err=0
2539         local cpt=0
2540         $LFS hsm_restore $f
2541         while [[ "$st" != "0x00000009" && $cpt -le 10 ]]
2542         do
2543                 n=$(stat -c "%s" $f)
2544                 # we echo in both cases to show stat is not
2545                 # hang
2546                 if [[ $n != $s ]]; then
2547                         echo "size seen is $n != $s"
2548                         err=1
2549                 else
2550                         echo "size seen is right: $n == $s"
2551                 fi
2552                 st=$(get_hsm_flags $f)
2553                 sleep 10
2554                 cpt=$((cpt + 1))
2555         done
2556         if [[ $cpt -lt 10 ]]; then
2557                 echo " "done
2558         else
2559                 echo " restore is too long"
2560                 wait_request_state $fid RESTORE SUCCEED
2561         fi
2562         return $err
2563 }
2564
2565 test_31a() {
2566         # test needs a running copytool
2567         copytool_setup
2568
2569         mkdir -p $DIR/$tdir
2570
2571         make_archive $tdir/$tfile
2572         local f=$DIR/$tdir/$tfile
2573         import_file $tdir/$tfile $f
2574         local fid=$($LFS path2fid $f)
2575         HSM_ARCHIVE_PURGE=false copytool_setup
2576
2577         restore_and_check_size $f $fid
2578         local err=$?
2579
2580         [[ $err -eq 0 ]] || error "File size changed during restore"
2581
2582         copytool_cleanup
2583 }
2584 run_test 31a "Import a large file and check size during restore"
2585
2586
2587 test_31b() {
2588         # test needs a running copytool
2589         copytool_setup
2590
2591         mkdir -p $DIR/$tdir
2592
2593         local f=$DIR/$tdir/$tfile
2594         local fid
2595         fid=$(make_custom_file_for_progress $f 39 1000000)
2596         [ $? != 0 ] && skip "not enough free space" && return
2597
2598         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2599         wait_request_state $fid ARCHIVE SUCCEED
2600         $LFS hsm_release $f
2601
2602         restore_and_check_size $f $fid
2603         local err=$?
2604
2605         [[ $err -eq 0 ]] || error "File size changed during restore"
2606
2607         copytool_cleanup
2608 }
2609 run_test 31b "Restore a large unaligned file and check size during restore"
2610
2611 test_31c() {
2612         # test needs a running copytool
2613         copytool_setup
2614
2615         mkdir -p $DIR/$tdir
2616
2617         local f=$DIR/$tdir/$tfile
2618         local fid
2619         fid=$(make_custom_file_for_progress $f 33 1048576)
2620         [ $? != 0 ] && skip "not enough free space" && return
2621
2622         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2623         wait_request_state $fid ARCHIVE SUCCEED
2624         $LFS hsm_release $f
2625
2626         restore_and_check_size $f $fid
2627         local err=$?
2628
2629         [[ $err -eq 0 ]] || error "File size changed during restore"
2630
2631         copytool_cleanup
2632 }
2633 run_test 31c "Restore a large aligned file and check size during restore"
2634
2635 test_33() {
2636         # test needs a running copytool
2637         copytool_setup
2638
2639         mkdir -p $DIR/$tdir
2640
2641         local f=$DIR/$tdir/$tfile
2642         local fid
2643         fid=$(make_custom_file_for_progress $f 39 1000000)
2644         [ $? != 0 ] && skip "not enough free space" && return
2645
2646         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2647         wait_request_state $fid ARCHIVE SUCCEED
2648         $LFS hsm_release $f
2649
2650         # to be sure wait_all_done will not be mislead by previous tests
2651         # and ops.
2652         cdt_purge
2653         wait_for_grace_delay
2654         # Also raise grace_delay significantly so the Canceled
2655         # Restore action will stay enough long avail.
2656         local old_grace=$(get_hsm_param grace_delay)
2657         set_hsm_param grace_delay 100
2658
2659         md5sum $f >/dev/null &
2660         local pid=$!
2661         wait_request_state $fid RESTORE STARTED
2662
2663         kill -15 $pid
2664         sleep 1
2665
2666         # Check restore trigger process was killed
2667         local killed=$(ps -o pid,comm hp $pid >/dev/null)
2668
2669         $LFS hsm_cancel $f
2670
2671         # instead of waiting+checking both Restore and Cancel ops
2672         # sequentially, wait for both to be finished and then check
2673         # each results.
2674         wait_all_done 100 $fid
2675         local rstate=$(get_request_state $fid RESTORE)
2676         local cstate=$(get_request_state $fid CANCEL)
2677
2678         # restore orig grace_delay.
2679         set_hsm_param grace_delay $old_grace
2680
2681         if [[ "$rstate" == "CANCELED" ]] ; then
2682                 [[ "$cstate" == "SUCCEED" ]] ||
2683                         error "Restore state is CANCELED and Cancel state " \
2684                                "is not SUCCEED but $cstate"
2685                 echo "Restore state is CANCELED, Cancel state is SUCCEED"
2686         elif [[ "$rstate" == "SUCCEED" ]] ; then
2687                 [[ "$cstate" == "FAILED" ]] ||
2688                         error "Restore state is SUCCEED and Cancel state " \
2689                                 "is not FAILED but $cstate"
2690                 echo "Restore state is SUCCEED, Cancel state is FAILED"
2691         else
2692                 error "Restore state is $rstate and Cancel state is $cstate"
2693         fi
2694
2695         [ -z $killed ] ||
2696                 error "Cannot kill process waiting for restore ($killed)"
2697
2698         copytool_cleanup
2699 }
2700 run_test 33 "Kill a restore waiting process"
2701
2702 test_34() {
2703         # test needs a running copytool
2704         copytool_setup
2705
2706         mkdir -p $DIR/$tdir
2707
2708         local f=$DIR/$tdir/$tfile
2709         local fid
2710         fid=$(make_custom_file_for_progress $f 39 1000000)
2711         [ $? != 0 ] && skip "not enough free space" && return
2712
2713         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2714         wait_request_state $fid ARCHIVE SUCCEED
2715         $LFS hsm_release $f
2716
2717         md5sum $f >/dev/null &
2718         local pid=$!
2719         wait_request_state $fid RESTORE STARTED
2720
2721         rm $f || error "rm $f failed"
2722         # rm must not block during restore
2723         wait_request_state $fid RESTORE STARTED
2724
2725         wait_request_state $fid RESTORE SUCCEED
2726         # check md5sum pgm finished
2727         local there=$(ps -o pid,comm hp $pid >/dev/null)
2728         [[ -z $there ]] || error "Restore initiator does not exit"
2729
2730         local rc=$(wait $pid)
2731         [[ $rc -eq 0 ]] || error "Restore initiator failed with $rc"
2732
2733         copytool_cleanup
2734 }
2735 run_test 34 "Remove file during restore"
2736
2737 test_35() {
2738         # test needs a running copytool
2739         copytool_setup
2740
2741         mkdir -p $DIR/$tdir
2742
2743         local f=$DIR/$tdir/$tfile
2744         local f1=$DIR/$tdir/$tfile-1
2745         local fid
2746         fid=$(make_custom_file_for_progress $f 39 1000000)
2747         [ $? != 0 ] && skip "not enough free space" && return
2748
2749         local fid1=$(copy_file /etc/passwd $f1)
2750         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2751         wait_request_state $fid ARCHIVE SUCCEED
2752         $LFS hsm_release $f
2753
2754         md5sum $f >/dev/null &
2755         local pid=$!
2756         wait_request_state $fid RESTORE STARTED
2757
2758         mv $f1 $f || error "mv $f1 $f failed"
2759         # mv must not block during restore
2760         wait_request_state $fid RESTORE STARTED
2761
2762         wait_request_state $fid RESTORE SUCCEED
2763         # check md5sum pgm finished
2764         local there=$(ps -o pid,comm hp $pid >/dev/null)
2765         [[ -z $there ]] || error "Restore initiator does not exit"
2766
2767         local rc=$(wait $pid)
2768         [[ $rc -eq 0 ]] || error "Restore initiator failed with $rc"
2769
2770         fid2=$(path2fid $f)
2771         [[ $fid2 == $fid1 ]] || error "Wrong fid after mv $fid2 != $fid1"
2772
2773         copytool_cleanup
2774 }
2775 run_test 35 "Overwrite file during restore"
2776
2777 test_36() {
2778         # test needs a running copytool
2779         copytool_setup
2780
2781         mkdir -p $DIR/$tdir
2782
2783         local f=$DIR/$tdir/$tfile
2784         local fid
2785         fid=$(make_custom_file_for_progress $f 39 1000000)
2786         [ $? != 0 ] && skip "not enough free space" && return
2787
2788         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2789         wait_request_state $fid ARCHIVE SUCCEED
2790         $LFS hsm_release $f
2791
2792         md5sum $f >/dev/null &
2793         local pid=$!
2794         wait_request_state $fid RESTORE STARTED
2795
2796         mv $f $f.new
2797         # rm must not block during restore
2798         wait_request_state $fid RESTORE STARTED
2799
2800         wait_request_state $fid RESTORE SUCCEED
2801         # check md5sum pgm finished
2802         local there=$(ps -o pid,comm hp $pid >/dev/null)
2803         [[ -z $there ]] ||
2804                 error "Restore initiator does not exit"
2805
2806         local rc=$(wait $pid)
2807         [[ $rc -eq 0 ]] ||
2808                 error "Restore initiator failed with $rc"
2809
2810         copytool_cleanup
2811 }
2812 run_test 36 "Move file during restore"
2813
2814 test_37() {
2815         # LU-5683: check that an archived dirty file can be rearchived.
2816         copytool_cleanup
2817         copytool_setup $SINGLEAGT $MOUNT2
2818
2819         mkdir -p $DIR/$tdir
2820         local f=$DIR/$tdir/$tfile
2821         local fid
2822
2823         fid=$(make_small $f) || error "cannot create small file"
2824
2825         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2826         wait_request_state $fid ARCHIVE SUCCEED
2827         $LFS hsm_release $f || error "cannot release $f"
2828
2829         # Dirty file.
2830         dd if=/dev/urandom of=$f bs=1M count=1 || error "cannot dirty file"
2831
2832         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2833         wait_request_state $fid ARCHIVE SUCCEED
2834
2835         copytool_cleanup
2836 }
2837 run_test 37 "re-archive a dirty file"
2838
2839 multi_archive() {
2840         local prefix=$1
2841         local count=$2
2842         local n=""
2843
2844         for n in $(seq 1 $count); do
2845                 $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $prefix.$n
2846         done
2847         echo "$count archive requests submitted"
2848 }
2849
2850 test_40() {
2851         local stream_count=4
2852         local file_count=100
2853         mkdir -p $DIR/$tdir
2854         local f=$DIR/$tdir/$tfile
2855         local i=""
2856         local p=""
2857         local fid=""
2858
2859         for i in $(seq 1 $file_count); do
2860                 for p in $(seq 1 $stream_count); do
2861                         fid=$(copy_file /etc/hosts $f.$p.$i)
2862                 done
2863         done
2864         # force copytool to use a local/temp archive dir to ensure best
2865         # performance vs remote/NFS mounts used in auto-tests
2866         if do_facet $SINGLEAGT "df --local $HSM_ARCHIVE" >/dev/null 2>&1 ; then
2867                 copytool_setup
2868         else
2869                 copytool_setup $SINGLEAGT $MOUNT $HSM_ARCHIVE_NUMBER $TMP/$tdir
2870         fi
2871         # to be sure wait_all_done will not be mislead by previous tests
2872         cdt_purge
2873         wait_for_grace_delay
2874         typeset -a pids
2875         # start archive streams in background (archive files in parallel)
2876         for p in $(seq 1 $stream_count); do
2877                 multi_archive $f.$p $file_count &
2878                 pids[$p]=$!
2879         done
2880         echo -n  "Wait for all requests being enqueued..."
2881         wait ${pids[*]}
2882         echo OK
2883         wait_all_done 100
2884         copytool_cleanup
2885 }
2886 run_test 40 "Parallel archive requests"
2887
2888 test_52() {
2889         # test needs a running copytool
2890         copytool_setup
2891
2892         mkdir -p $DIR/$tdir
2893         local f=$DIR/$tdir/$tfile
2894         local fid=$(copy_file /etc/motd $f 1)
2895
2896         $LFS hsm_archive $f || error "could not archive file"
2897         wait_request_state $fid ARCHIVE SUCCEED
2898         check_hsm_flags $f "0x00000009"
2899
2900         multiop_bg_pause $f O_c || error "multiop failed"
2901         local MULTIPID=$!
2902
2903         mds_evict_client
2904         client_up || client_up || true
2905
2906         kill -USR1 $MULTIPID
2907         wait $MULTIPID || error "multiop close failed"
2908
2909         check_hsm_flags $f "0x0000000b"
2910
2911         copytool_cleanup
2912 }
2913 run_test 52 "Opened for write file on an evicted client should be set dirty"
2914
2915 test_53() {
2916         # test needs a running copytool
2917         copytool_setup
2918
2919         mkdir -p $DIR/$tdir
2920         local f=$DIR/$tdir/$tfile
2921         local fid=$(copy_file /etc/motd $f 1)
2922
2923         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
2924                 error "could not archive file"
2925         wait_request_state $fid ARCHIVE SUCCEED
2926         check_hsm_flags $f "0x00000009"
2927
2928         multiop_bg_pause $f o_c || error "multiop failed"
2929         MULTIPID=$!
2930
2931         mds_evict_client
2932         client_up || client_up || true
2933
2934         kill -USR1 $MULTIPID
2935         wait $MULTIPID || error "multiop close failed"
2936
2937         check_hsm_flags $f "0x00000009"
2938
2939         copytool_cleanup
2940 }
2941 run_test 53 "Opened for read file on an evicted client should not be set dirty"
2942
2943 test_54() {
2944         # test needs a running copytool
2945         copytool_setup
2946
2947         mkdir -p $DIR/$tdir
2948         local f=$DIR/$tdir/$tfile
2949         local fid=$(make_custom_file_for_progress $f 39 1000000)
2950
2951         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
2952                 error "could not archive file"
2953         wait_request_state $fid ARCHIVE STARTED
2954
2955         check_hsm_flags $f "0x00000001"
2956
2957         # Avoid coordinator resending this request as soon it has failed.
2958         cdt_set_no_retry
2959
2960         echo "foo" >> $f
2961         sync
2962         wait_request_state $fid ARCHIVE FAILED
2963
2964         check_hsm_flags $f "0x00000003"
2965
2966         cdt_clear_no_retry
2967         copytool_cleanup
2968 }
2969 run_test 54 "Write during an archive cancels it"
2970
2971 test_55() {
2972         # test needs a running copytool
2973         copytool_setup
2974
2975         mkdir -p $DIR/$tdir
2976         local f=$DIR/$tdir/$tfile
2977         local fid=$(make_custom_file_for_progress $f 39 1000000)
2978
2979         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
2980                 error "could not archive file"
2981         wait_request_state $fid ARCHIVE STARTED
2982
2983         check_hsm_flags $f "0x00000001"
2984
2985         # Avoid coordinator resending this request as soon it has failed.
2986         cdt_set_no_retry
2987
2988         $TRUNCATE $f 1024 || error "truncate failed"
2989         sync
2990         wait_request_state $fid ARCHIVE FAILED
2991
2992         check_hsm_flags $f "0x00000003"
2993
2994         cdt_clear_no_retry
2995         copytool_cleanup
2996 }
2997 run_test 55 "Truncate during an archive cancels it"
2998
2999 test_56() {
3000         # test needs a running copytool
3001         copytool_setup
3002
3003         mkdir -p $DIR/$tdir
3004         local f=$DIR/$tdir/$tfile
3005         local fid
3006         fid=$(make_custom_file_for_progress $f 39 1000000)
3007         [ $? != 0 ] && skip "not enough free space" && return
3008
3009         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
3010                 error "could not archive file"
3011         wait_request_state $fid ARCHIVE STARTED
3012
3013         check_hsm_flags $f "0x00000001"
3014
3015         # Change metadata and sync to be sure we are not changing only
3016         # in memory.
3017         chmod 644 $f
3018         chgrp sys $f
3019         sync
3020         wait_request_state $fid ARCHIVE SUCCEED
3021
3022         check_hsm_flags $f "0x00000009"
3023
3024         copytool_cleanup
3025 }
3026 run_test 56 "Setattr during an archive is ok"
3027
3028 test_57() {
3029         # Need one client for I/O, one for request
3030         needclients 2 || return 0
3031
3032         # test needs a running copytool
3033         copytool_setup
3034
3035         mkdir -p $DIR/$tdir
3036         local f=$DIR/$tdir/test_archive_remote
3037         # Create a file on a remote node
3038         do_node $CLIENT2 "dd if=/dev/urandom of=$f bs=1M "\
3039                 "count=2 conv=fsync"
3040
3041         # And archive it
3042         do_node $CLIENT2 "$LFS hsm_archive -a $HSM_ARCHIVE_NUMBER $f" ||
3043                 error "hsm_archive failed"
3044         local fid=$(path2fid $f)
3045         wait_request_state $fid ARCHIVE SUCCEED
3046
3047         # Release and implicit restore it
3048         do_node $CLIENT2 "$LFS hsm_release $f" ||
3049                 error "hsm_release failed"
3050         do_node $CLIENT2 "md5sum $f" ||
3051                 error "hsm_restore failed"
3052
3053         wait_request_state $fid RESTORE SUCCEED
3054
3055         copytool_cleanup
3056 }
3057 run_test 57 "Archive a file with dirty cache on another node"
3058
3059 truncate_released_file() {
3060         local src_file=$1
3061         local trunc_to=$2
3062
3063         local sz=$(stat -c %s $src_file)
3064         local f=$DIR/$tdir/$tfile
3065         local fid=$(copy_file $1 $f)
3066         local ref=$f-ref
3067         cp $f $f-ref
3068
3069         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
3070                 error "could not archive file"
3071         wait_request_state $fid ARCHIVE SUCCEED
3072
3073         $LFS hsm_release $f || error "could not release file"
3074
3075         $TRUNCATE $f $trunc_to || error "truncate failed"
3076         sync
3077
3078         local sz1=$(stat -c %s $f)
3079         [[ $sz1 == $trunc_to ]] ||
3080                 error "size after trunc: $sz1 expect $trunc_to, original $sz"
3081
3082         $LFS hsm_state $f
3083         check_hsm_flags $f "0x0000000b"
3084
3085         local state=$(get_request_state $fid RESTORE)
3086         [[ "$state" == "SUCCEED" ]] ||
3087                 error "truncate $sz does not trig restore, state = $state"
3088
3089         $TRUNCATE $ref $trunc_to
3090         cmp $ref $f || error "file data wrong after truncate"
3091
3092         rm -f $f $f-ref
3093 }
3094
3095 test_58() {
3096         # test needs a running copytool
3097         copytool_setup
3098
3099         mkdir -p $DIR/$tdir
3100
3101         local sz=$(stat -c %s /etc/passwd)
3102
3103         echo "truncate up from $sz to $((sz*2))"
3104         truncate_released_file /etc/passwd $((sz*2))
3105
3106         echo "truncate down from $sz to $((sz/2))"
3107         truncate_released_file /etc/passwd $((sz/2))
3108
3109         echo "truncate to 0"
3110         truncate_released_file /etc/passwd 0
3111
3112         copytool_cleanup
3113 }
3114 run_test 58 "Truncate a released file will trigger restore"
3115
3116 test_59() {
3117         local fid
3118         local server_version=$(lustre_version_code $SINGLEMDS)
3119         [[ $server_version -lt $(version_code 2.7.63) ]] &&
3120                 skip "Need MDS version at least 2.7.63" && return
3121
3122         copytool_setup
3123         $MCREATE $DIR/$tfile || error "mcreate failed"
3124         $TRUNCATE $DIR/$tfile 42 || error "truncate failed"
3125         $LFS hsm_archive $DIR/$tfile || error "archive request failed"
3126         fid=$(path2fid $DIR/$tfile)
3127         wait_request_state $fid ARCHIVE SUCCEED
3128         $LFS hsm_release $DIR/$tfile || error "release failed"
3129         copytool_cleanup
3130 }
3131 run_test 59 "Release stripeless file with non-zero size"
3132
3133 test_60() {
3134         # This test validates the fix for LU-4512. Ensure that the -u
3135         # option changes the progress reporting interval from the
3136         # default (30 seconds) to the user-specified interval.
3137         local interval=5
3138         local progress_timeout=$((interval * 4))
3139
3140         # test needs a new running copytool
3141         copytool_cleanup
3142         HSMTOOL_UPDATE_INTERVAL=$interval copytool_setup
3143
3144         mkdir -p $DIR/$tdir
3145         local f=$DIR/$tdir/$tfile
3146         local fid
3147         fid=$(make_custom_file_for_progress $f 10)
3148         [ $? != 0 ] && skip "not enough free space" && return
3149
3150         local mdtidx=0
3151         local mdt=${MDT_PREFIX}${mdtidx}
3152         local mds=mds$((mdtidx + 1))
3153
3154         # Wait for copytool to register
3155         wait_update_facet $mds \
3156                 "$LCTL get_param -n ${mdt}.hsm.agents | grep -o ^uuid" \
3157                 uuid 100 || error "coyptool failed to register with $mdt"
3158
3159         local start_at=$(date +%s)
3160         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
3161                 error "could not archive file"
3162
3163         local agent=$(facet_active_host $SINGLEAGT)
3164         local prefix=$TESTLOG_PREFIX
3165         [[ -z "$TESTNAME" ]] || prefix=$prefix.$TESTNAME
3166         local copytool_log=$prefix.copytool_log.$agent.log
3167
3168
3169         wait_update $agent \
3170             "grep -o start.copy $copytool_log" "start copy" 100 ||
3171                 error "copytool failed to start"
3172
3173         local cmd="$LCTL get_param -n ${mdt}.hsm.active_requests"
3174         cmd+=" | awk '/'$fid'.*action=ARCHIVE/ {print \\\$12}' | cut -f2 -d="
3175
3176         local RESULT
3177         local WAIT=0
3178         local sleep=1
3179
3180         echo -n "Expecting a progress update within $progress_timeout seconds... "
3181         while [ true ]; do
3182                 RESULT=$(do_node $(facet_active_host $mds) "$cmd")
3183                 if [ $RESULT -gt 0 ]; then
3184                         echo "$RESULT bytes copied in $WAIT seconds."
3185                         break
3186                 elif [ $WAIT -ge $progress_timeout ]; then
3187                         error "Timed out waiting for progress update!"
3188                         break
3189                 fi
3190                 WAIT=$((WAIT + sleep))
3191                 sleep $sleep
3192         done
3193
3194         local finish_at=$(date +%s)
3195         local elapsed=$((finish_at - start_at))
3196
3197         # Ensure that the progress update occurred within the expected window.
3198         if [ $elapsed -lt $((interval - 1)) ]; then
3199                 error "Expected progress update after at least $interval seconds"
3200         fi
3201
3202         echo "Wait for on going archive hsm action to complete"
3203         wait_update $agent "grep -o copied $copytool_log" "copied" 10 ||
3204                 echo "File archiving not completed even after 10 secs"
3205
3206         cdt_clear_no_retry
3207         copytool_cleanup
3208 }
3209 run_test 60 "Changing progress update interval from default"
3210
3211 test_70() {
3212         # test needs a new running copytool
3213         copytool_cleanup
3214         copytool_monitor_setup
3215         HSMTOOL_EVENT_FIFO=$HSMTOOL_MONITOR_DIR/fifo copytool_setup
3216
3217         # Just start and stop the copytool to generate events.
3218         cdt_clear_no_retry
3219
3220         # Wait for the copytool to register.
3221         wait_update --verbose $(facet_active_host mds1) \
3222                 "$LCTL get_param -n ${MDT_PREFIX}0.hsm.agents | grep -o ^uuid" \
3223                 uuid 100 ||
3224                 error "copytool failed to register with MDT0000"
3225
3226         copytool_cleanup
3227
3228         local REGISTER_EVENT
3229         local UNREGISTER_EVENT
3230         while read event; do
3231                 local parsed=$(parse_json_event "$event")
3232                 if [ -z "$parsed" ]; then
3233                         error "Copytool sent malformed event: $event"
3234                 fi
3235                 eval $parsed
3236
3237                 if [ $event_type == "REGISTER" ]; then
3238                         REGISTER_EVENT=$event
3239                 elif [ $event_type == "UNREGISTER" ]; then
3240                         UNREGISTER_EVENT=$event
3241                 fi
3242         done < <(echo $"$(get_copytool_event_log)")
3243
3244         if [ -z "$REGISTER_EVENT" ]; then
3245                 error "Copytool failed to send register event to FIFO"
3246         fi
3247
3248         if [ -z "$UNREGISTER_EVENT" ]; then
3249                 error "Copytool failed to send unregister event to FIFO"
3250         fi
3251
3252         copytool_monitor_cleanup
3253         echo "Register/Unregister events look OK."
3254 }
3255 run_test 70 "Copytool logs JSON register/unregister events to FIFO"
3256
3257 test_71() {
3258         # Bump progress interval for livelier events.
3259         local interval=5
3260
3261         # test needs a new running copytool
3262         copytool_cleanup
3263         copytool_monitor_setup
3264         HSMTOOL_UPDATE_INTERVAL=$interval \
3265         HSMTOOL_EVENT_FIFO=$HSMTOOL_MONITOR_DIR/fifo copytool_setup
3266
3267         mkdir -p $DIR/$tdir
3268         local f=$DIR/$tdir/$tfile
3269         local fid
3270         fid=$(make_custom_file_for_progress $f 39 1000000)
3271         [ $? != 0 ] && skip "not enough free space" && return
3272
3273         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
3274                 error "could not archive file"
3275         wait_request_state $fid ARCHIVE SUCCEED
3276
3277         local expected_fields="event_time data_fid source_fid"
3278         expected_fields+=" total_bytes current_bytes"
3279
3280         local START_EVENT
3281         local FINISH_EVENT
3282         while read event; do
3283                 # Make sure we're not getting anything from previous events.
3284                 for field in $expected_fields; do
3285                         unset $field
3286                 done
3287
3288                 local parsed=$(parse_json_event "$event")
3289                 if [ -z "$parsed" ]; then
3290                         error "Copytool sent malformed event: $event"
3291                 fi
3292                 eval $parsed
3293
3294                 if [ $event_type == "ARCHIVE_START" ]; then
3295                         START_EVENT=$event
3296                         continue
3297                 elif [ $event_type == "ARCHIVE_FINISH" ]; then
3298                         FINISH_EVENT=$event
3299                         continue
3300                 elif [ $event_type != "ARCHIVE_RUNNING" ]; then
3301                         continue
3302                 fi
3303
3304                 # Do some simple checking of the progress update events.
3305                 for expected_field in $expected_fields; do
3306                         if [ -z ${!expected_field+x} ]; then
3307                                 error "Missing $expected_field field in event"
3308                         fi
3309                 done
3310
3311                 if [ $total_bytes -eq 0 ]; then
3312                         error "Expected total_bytes to be > 0"
3313                 fi
3314
3315                 # These should be identical throughout an archive
3316                 # operation.
3317                 if [ $source_fid != $data_fid ]; then
3318                         error "Expected source_fid to equal data_fid"
3319                 fi
3320         done < <(echo $"$(get_copytool_event_log)")
3321
3322         if [ -z "$START_EVENT" ]; then
3323                 error "Copytool failed to send archive start event to FIFO"
3324         fi
3325
3326         if [ -z "$FINISH_EVENT" ]; then
3327                 error "Copytool failed to send archive finish event to FIFO"
3328         fi
3329
3330         echo "Archive events look OK."
3331
3332         cdt_clear_no_retry
3333         copytool_cleanup
3334         copytool_monitor_cleanup
3335 }
3336 run_test 71 "Copytool logs JSON archive events to FIFO"
3337
3338 test_72() {
3339         # Bump progress interval for livelier events.
3340         local interval=5
3341
3342         # test needs a new running copytool
3343         copytool_cleanup
3344         copytool_monitor_setup
3345         HSMTOOL_UPDATE_INTERVAL=$interval \
3346         HSMTOOL_EVENT_FIFO=$HSMTOOL_MONITOR_DIR/fifo copytool_setup
3347         local test_file=$HSMTOOL_MONITOR_DIR/file
3348
3349         local cmd="dd if=/dev/urandom of=$test_file count=16 bs=1000000 "
3350         cmd+="conv=fsync"
3351         do_facet $SINGLEAGT "$cmd" ||
3352                 error "cannot create $test_file on $SINGLEAGT"
3353         copy2archive $test_file $tdir/$tfile
3354
3355         mkdir -p $DIR/$tdir
3356         local f=$DIR/$tdir/$tfile
3357         import_file $tdir/$tfile $f
3358         f=$DIR2/$tdir/$tfile
3359         echo "Verifying released state: "
3360         check_hsm_flags $f "0x0000000d"
3361
3362         local fid=$(path2fid $f)
3363         $LFS hsm_restore $f
3364         wait_request_state $fid RESTORE SUCCEED
3365
3366         local expected_fields="event_time data_fid source_fid"
3367         expected_fields+=" total_bytes current_bytes"
3368
3369         local START_EVENT
3370         local FINISH_EVENT
3371         while read event; do
3372                 # Make sure we're not getting anything from previous events.
3373                 for field in $expected_fields; do
3374                         unset $field
3375                 done
3376
3377                 local parsed=$(parse_json_event "$event")
3378                 if [ -z "$parsed" ]; then
3379                         error "Copytool sent malformed event: $event"
3380                 fi
3381                 eval $parsed
3382
3383                 if [ $event_type == "RESTORE_START" ]; then
3384                         START_EVENT=$event
3385                         if [ $source_fid != $data_fid ]; then
3386                                 error "source_fid should == data_fid at start"
3387                         fi
3388                         continue
3389                 elif [ $event_type == "RESTORE_FINISH" ]; then
3390                         FINISH_EVENT=$event
3391                         if [ $source_fid != $data_fid ]; then
3392                                 error "source_fid should == data_fid at finish"
3393                         fi
3394                         continue
3395                 elif [ $event_type != "RESTORE_RUNNING" ]; then
3396                         continue
3397                 fi
3398
3399                 # Do some simple checking of the progress update events.
3400                 for expected_field in $expected_fields; do
3401                         if [ -z ${!expected_field+x} ]; then
3402                                 error "Missing $expected_field field in event"
3403                         fi
3404                 done
3405
3406                 if [ $total_bytes -eq 0 ]; then
3407                         error "Expected total_bytes to be > 0"
3408                 fi
3409
3410                 # When a restore starts out, the data fid is the same as the
3411                 # source fid. After the restore has gotten going, we learn
3412                 # the new data fid. Once the restore has finished, the source
3413                 # fid is set to the new data fid.
3414                 #
3415                 # We test this because some monitoring software may depend on
3416                 # this behavior. If it changes, then the consumers of these
3417                 # events may need to be modified.
3418                 if [ $source_fid == $data_fid ]; then
3419                         error "source_fid should != data_fid during restore"
3420                 fi
3421         done < <(echo $"$(get_copytool_event_log)")
3422
3423         if [ -z "$START_EVENT" ]; then
3424                 error "Copytool failed to send restore start event to FIFO"
3425         fi
3426
3427         if [ -z "$FINISH_EVENT" ]; then
3428                 error "Copytool failed to send restore finish event to FIFO"
3429         fi
3430
3431         echo "Restore events look OK."
3432
3433         cdt_clear_no_retry
3434         copytool_cleanup
3435         copytool_monitor_cleanup
3436
3437         rm -rf $test_dir
3438 }
3439 run_test 72 "Copytool logs JSON restore events to FIFO"
3440
3441 test_90() {
3442         file_count=51 # Max number of files constrained by LNET message size
3443         mkdir $DIR/$tdir || error "mkdir $DIR/$tdir failed"
3444         local f=$DIR/$tdir/$tfile
3445         local FILELIST=/tmp/filelist.txt
3446         local i=""
3447
3448         rm -f $FILELIST
3449         for i in $(seq 1 $file_count); do
3450                 fid=$(copy_file /etc/hosts $f.$i)
3451                 echo $f.$i >> $FILELIST
3452         done
3453         # force copytool to use a local/temp archive dir to ensure best
3454         # performance vs remote/NFS mounts used in auto-tests
3455         if do_facet $SINGLEAGT "df --local $HSM_ARCHIVE" >/dev/null 2>&1 ; then
3456                 copytool_setup
3457         else
3458                 local dai=$(get_hsm_param default_archive_id)
3459                 copytool_setup $SINGLEAGT $MOUNT $dai $TMP/$tdir
3460         fi
3461         # to be sure wait_all_done will not be mislead by previous tests
3462         cdt_purge
3463         wait_for_grace_delay
3464         $LFS hsm_archive --filelist $FILELIST ||
3465                 error "cannot archive a file list"
3466         wait_all_done 100
3467         $LFS hsm_release --filelist $FILELIST ||
3468                 error "cannot release a file list"
3469         $LFS hsm_restore --filelist $FILELIST ||
3470                 error "cannot restore a file list"
3471         wait_all_done 100
3472         copytool_cleanup
3473 }
3474 run_test 90 "Archive/restore a file list"
3475
3476 double_verify_reset_hsm_param() {
3477         local p=$1
3478         echo "Testing $HSM_PARAM.$p"
3479         local val=$(get_hsm_param $p)
3480         local save=$val
3481         local val2=$(($val * 2))
3482         set_hsm_param $p $val2
3483         val=$(get_hsm_param $p)
3484         [[ $val == $val2 ]] ||
3485                 error "$HSM_PARAM.$p: $val != $val2 should be (2 * $save)"
3486         echo "Set $p to 0 must failed"
3487         set_hsm_param $p 0
3488         local rc=$?
3489         # restore value
3490         set_hsm_param $p $save
3491
3492         if [[ $rc == 0 ]]; then
3493                 error "we must not be able to set $HSM_PARAM.$p to 0"
3494         fi
3495 }
3496
3497 test_100() {
3498         double_verify_reset_hsm_param loop_period
3499         double_verify_reset_hsm_param grace_delay
3500         double_verify_reset_hsm_param active_request_timeout
3501         double_verify_reset_hsm_param max_requests
3502         double_verify_reset_hsm_param default_archive_id
3503 }
3504 run_test 100 "Set coordinator /proc tunables"
3505
3506 test_102() {
3507         cdt_disable
3508         cdt_enable
3509         cdt_restart
3510 }
3511 run_test 102 "Verify coordinator control"
3512
3513 test_103() {
3514         # test needs a running copytool
3515         copytool_setup
3516
3517         local i=""
3518         local fid=""
3519
3520         mkdir -p $DIR/$tdir
3521         for i in $(seq 1 20); do
3522                 fid=$(copy_file /etc/passwd $DIR/$tdir/$i)
3523         done
3524         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $DIR/$tdir/*
3525
3526         cdt_purge
3527
3528         echo "Current requests"
3529         local res=$(do_facet $SINGLEMDS "$LCTL get_param -n\
3530                         $HSM_PARAM.actions |\
3531                         grep -v CANCELED | grep -v SUCCEED | grep -v FAILED")
3532
3533         [[ -z "$res" ]] || error "Some request have not been canceled"
3534
3535         copytool_cleanup
3536 }
3537 run_test 103 "Purge all requests"
3538
3539 DATA=CEA
3540 DATAHEX='[434541]'
3541 test_104() {
3542         # test needs a running copytool
3543         copytool_setup
3544
3545         mkdir -p $DIR/$tdir
3546         local f=$DIR/$tdir/$tfile
3547         local fid
3548         fid=$(make_custom_file_for_progress $f 39 1000000)
3549         [ $? != 0 ] && skip "not enough free space" && return
3550
3551         # if cdt is on, it can serve too quickly the request
3552         cdt_disable
3553         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER --data $DATA $f
3554         local data1=$(do_facet $SINGLEMDS "$LCTL get_param -n\
3555                         $HSM_PARAM.actions |\
3556                         grep $fid | cut -f16 -d=")
3557         cdt_enable
3558
3559         [[ "$data1" == "$DATAHEX" ]] ||
3560                 error "Data field in records is ($data1) and not ($DATAHEX)"
3561
3562         copytool_cleanup
3563 }
3564 run_test 104 "Copy tool data field"
3565
3566 test_105() {
3567         mkdir -p $DIR/$tdir
3568         local i=""
3569
3570         cdt_disable
3571         for i in $(seq -w 1 10); do
3572                 cp /etc/passwd $DIR/$tdir/$i
3573                 $LFS hsm_archive $DIR/$tdir/$i
3574         done
3575         local reqcnt1=$(do_facet $SINGLEMDS "$LCTL get_param -n\
3576                         $HSM_PARAM.actions |\
3577                         grep WAITING | wc -l")
3578         cdt_restart
3579         cdt_disable
3580         local reqcnt2=$(do_facet $SINGLEMDS "$LCTL get_param -n\
3581                         $HSM_PARAM.actions |\
3582                         grep WAITING | wc -l")
3583         cdt_enable
3584         cdt_purge
3585         [[ "$reqcnt1" == "$reqcnt2" ]] ||
3586                 error "Requests count after shutdown $reqcnt2 != "\
3587                       "before shutdown $reqcnt1"
3588 }
3589 run_test 105 "Restart of coordinator"
3590
3591 test_106() {
3592         # test needs a running copytool
3593         copytool_setup
3594
3595         local uuid=$(get_agent_uuid $(facet_active_host $SINGLEAGT))
3596
3597         check_agent_registered $uuid
3598
3599         search_copytools || error "No copytool found"
3600
3601         copytool_cleanup
3602         check_agent_unregistered $uuid
3603
3604         copytool_setup
3605         uuid=$(get_agent_uuid $(facet_active_host $SINGLEAGT))
3606         check_agent_registered $uuid
3607
3608         copytool_cleanup
3609 }
3610 run_test 106 "Copytool register/unregister"
3611
3612 test_107() {
3613         # test needs a running copytool
3614         copytool_setup
3615         # create and archive file
3616         mkdir -p $DIR/$tdir
3617         local f1=$DIR/$tdir/$tfile
3618         local fid=$(copy_file /etc/passwd $f1)
3619         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f1
3620         wait_request_state $fid ARCHIVE SUCCEED
3621         # shutdown and restart MDS
3622         fail $SINGLEMDS
3623         # check the copytool still gets messages from MDT
3624         local f2=$DIR/$tdir/2
3625         local fid=$(copy_file /etc/passwd $f2)
3626         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f2
3627         # main check of this sanity: this request MUST succeed
3628         wait_request_state $fid ARCHIVE SUCCEED
3629         copytool_cleanup
3630 }
3631 run_test 107 "Copytool re-register after MDS restart"
3632
3633 policy_set_and_test()
3634 {
3635         local change="$1"
3636         local target="$2"
3637         do_facet $SINGLEMDS $LCTL set_param "$HSM_PARAM.policy=\\\"$change\\\""
3638         local policy=$(do_facet $SINGLEMDS $LCTL get_param -n $HSM_PARAM.policy)
3639         [[ "$policy" == "$target" ]] ||
3640                 error "Wrong policy after '$change': '$policy' != '$target'"
3641 }
3642
3643 test_109() {
3644         # to force default policy setting if error
3645         CDT_POLICY_HAD_CHANGED=true
3646
3647         local policy=$(do_facet $SINGLEMDS $LCTL get_param -n $HSM_PARAM.policy)
3648         local default="NonBlockingRestore [NoRetryAction]"
3649         [[ "$policy" == "$default" ]] ||
3650                 error "default policy has changed,"\
3651                       " '$policy' != '$default' update the test"
3652         policy_set_and_test "+NBR" "[NonBlockingRestore] [NoRetryAction]"
3653         policy_set_and_test "+NRA" "[NonBlockingRestore] [NoRetryAction]"
3654         policy_set_and_test "-NBR" "NonBlockingRestore [NoRetryAction]"
3655         policy_set_and_test "-NRA" "NonBlockingRestore NoRetryAction"
3656         policy_set_and_test "NRA NBR" "[NonBlockingRestore] [NoRetryAction]"
3657         # useless bacause we know but safer for futur changes to use real value
3658         local policy=$(do_facet $SINGLEMDS $LCTL get_param -n $HSM_PARAM.policy)
3659         echo "Next set_param must failed"
3660         policy_set_and_test "wrong" "$policy"
3661
3662         # return to default
3663         echo "Back to default policy"
3664         cdt_set_sanity_policy
3665 }
3666 run_test 109 "Policy display/change"
3667
3668 test_110a() {
3669         # test needs a running copytool
3670         copytool_setup
3671
3672         mkdir -p $DIR/$tdir
3673
3674         copy2archive /etc/passwd $tdir/$tfile
3675
3676         local f=$DIR/$tdir/$tfile
3677         import_file $tdir/$tfile $f
3678         local fid=$(path2fid $f)
3679
3680         cdt_set_non_blocking_restore
3681         md5sum $f
3682         local st=$?
3683
3684         # cleanup
3685         wait_request_state $fid RESTORE SUCCEED
3686         cdt_clear_non_blocking_restore
3687
3688         # Test result
3689         [[ $st == 1 ]] ||
3690                 error "md5sum returns $st != 1, "\
3691                         "should also perror ENODATA (No data available)"
3692
3693         copytool_cleanup
3694 }
3695 run_test 110a "Non blocking restore policy (import case)"
3696
3697 test_110b() {
3698         # test needs a running copytool
3699         copytool_setup
3700
3701         mkdir -p $DIR/$tdir
3702         local f=$DIR/$tdir/$tfile
3703         local fid=$(copy_file /etc/passwd $f)
3704         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3705         wait_request_state $fid ARCHIVE SUCCEED
3706         $LFS hsm_release $f
3707
3708         cdt_set_non_blocking_restore
3709         md5sum $f
3710         local st=$?
3711
3712         # cleanup
3713         wait_request_state $fid RESTORE SUCCEED
3714         cdt_clear_non_blocking_restore
3715
3716         # Test result
3717         [[ $st == 1 ]] ||
3718                 error "md5sum returns $st != 1, "\
3719                         "should also perror ENODATA (No data available)"
3720
3721         copytool_cleanup
3722 }
3723 run_test 110b "Non blocking restore policy (release case)"
3724
3725 test_111a() {
3726         # test needs a running copytool
3727         copytool_setup
3728
3729         mkdir -p $DIR/$tdir
3730         copy2archive /etc/passwd $tdir/$tfile
3731
3732         local f=$DIR/$tdir/$tfile
3733
3734         import_file $tdir/$tfile $f
3735         local fid=$(path2fid $f)
3736
3737         cdt_set_no_retry
3738
3739         copytool_remove_backend $fid
3740
3741         $LFS hsm_restore $f
3742         wait_request_state $fid RESTORE FAILED
3743         local st=$?
3744
3745         # cleanup
3746         cdt_clear_no_retry
3747
3748         # Test result
3749         [[ $st == 0 ]] || error "Restore does not failed"
3750
3751         copytool_cleanup
3752 }
3753 run_test 111a "No retry policy (import case), restore will error"\
3754               " (No such file or directory)"
3755
3756 test_111b() {
3757         # test needs a running copytool
3758         copytool_setup
3759
3760         mkdir -p $DIR/$tdir
3761         local f=$DIR/$tdir/$tfile
3762         local fid=$(copy_file /etc/passwd $f)
3763         cdt_set_no_retry
3764         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3765         wait_request_state $fid ARCHIVE SUCCEED
3766         $LFS hsm_release $f
3767
3768         copytool_remove_backend $fid
3769
3770         $LFS hsm_restore $f
3771         wait_request_state $fid RESTORE FAILED
3772         local st=$?
3773
3774         # cleanup
3775         cdt_clear_no_retry
3776
3777         # Test result
3778         [[ $st == 0 ]] || error "Restore does not failed"
3779
3780         copytool_cleanup
3781 }
3782 run_test 111b "No retry policy (release case), restore will error"\
3783               " (No such file or directory)"
3784
3785 test_112() {
3786         # test needs a running copytool
3787         copytool_setup
3788
3789         mkdir -p $DIR/$tdir
3790         local f=$DIR/$tdir/$tfile
3791         local fid=$(copy_file /etc/passwd $f)
3792         cdt_disable
3793         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3794         local l=$($LFS hsm_action $f)
3795         echo $l
3796         local res=$(echo $l | cut -f 2- -d" " | grep ARCHIVE)
3797
3798         # cleanup
3799         cdt_enable
3800         wait_request_state $fid ARCHIVE SUCCEED
3801
3802         # Test result
3803         [[ ! -z "$res" ]] || error "action is $l which is not an ARCHIVE"
3804
3805         copytool_cleanup
3806 }
3807 run_test 112 "State of recorded request"
3808
3809 test_200() {
3810         # test needs a running copytool
3811         copytool_setup
3812
3813         mkdir -p $DIR/$tdir
3814         local f=$DIR/$tdir/$tfile
3815         local fid
3816         fid=$(make_custom_file_for_progress $f 103 1048576)
3817         [ $? != 0 ] && skip "not enough free space" && return
3818
3819         # test with cdt on is made in test_221
3820         cdt_disable
3821         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3822         # wait archive to register at CDT
3823         wait_request_state $fid ARCHIVE WAITING
3824         $LFS hsm_cancel $f
3825         cdt_enable
3826         wait_request_state $fid ARCHIVE CANCELED
3827         wait_request_state $fid CANCEL SUCCEED
3828
3829         copytool_cleanup
3830 }
3831 run_test 200 "Register/Cancel archive"
3832
3833 test_201() {
3834         # test needs a running copytool
3835         copytool_setup
3836
3837         mkdir -p $DIR/$tdir
3838         local f=$DIR/$tdir/$tfile
3839         make_archive $tdir/$tfile
3840         import_file $tdir/$tfile $f
3841         local fid=$(path2fid $f)
3842
3843         # test with cdt on is made in test_222
3844         cdt_disable
3845         $LFS hsm_restore $f
3846         # wait restore to register at CDT
3847         wait_request_state $fid RESTORE WAITING
3848         $LFS hsm_cancel $f
3849         cdt_enable
3850         wait_request_state $fid RESTORE CANCELED
3851         wait_request_state $fid CANCEL SUCCEED
3852
3853         copytool_cleanup
3854 }
3855 run_test 201 "Register/Cancel restore"
3856
3857 test_202() {
3858         # test needs a running copytool
3859         copytool_setup
3860
3861         mkdir -p $DIR/$tdir
3862         local f=$DIR/$tdir/$tfile
3863         local fid
3864         fid=$(make_custom_file_for_progress $f 39 1000000)
3865         [ $? != 0 ] && skip "not enough free space" && return
3866
3867         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3868         wait_request_state $fid ARCHIVE SUCCEED
3869
3870         cdt_disable
3871         $LFS hsm_remove $f
3872         # wait remove to register at CDT
3873         wait_request_state $fid REMOVE WAITING
3874         $LFS hsm_cancel $f
3875         cdt_enable
3876         wait_request_state $fid REMOVE CANCELED
3877
3878         copytool_cleanup
3879 }
3880 run_test 202 "Register/Cancel remove"
3881
3882 test_220() {
3883         # test needs a running copytool
3884         copytool_setup
3885
3886         mkdir -p $DIR/$tdir
3887
3888         local f=$DIR/$tdir/$tfile
3889         local fid=$(copy_file /etc/passwd $f)
3890
3891         changelog_setup
3892
3893         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3894         wait_request_state $fid ARCHIVE SUCCEED
3895
3896         local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
3897         changelog_cleanup
3898
3899         local target=0x0
3900         [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
3901
3902         copytool_cleanup
3903 }
3904 run_test 220 "Changelog for archive"
3905
3906 test_221() {
3907         # test needs a running copytool
3908         copytool_setup
3909
3910         mkdir -p $DIR/$tdir
3911
3912         local f=$DIR/$tdir/$tfile
3913         local fid
3914         fid=$(make_custom_file_for_progress $f 103 1048576)
3915         [ $? != 0 ] && skip "not enough free space" && return
3916
3917         changelog_setup
3918
3919         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3920         wait_request_state $fid ARCHIVE STARTED
3921         $LFS hsm_cancel $f
3922         wait_request_state $fid ARCHIVE CANCELED
3923         wait_request_state $fid CANCEL SUCCEED
3924
3925         local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
3926
3927         local target=0x7d
3928         [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
3929
3930         cleanup
3931 }
3932 run_test 221 "Changelog for archive canceled"
3933
3934 test_222a() {
3935         # test needs a running copytool
3936         copytool_setup
3937
3938         mkdir -p $DIR/$tdir
3939         copy2archive /etc/passwd $tdir/$tfile
3940
3941         local f=$DIR/$tdir/$tfile
3942         import_file $tdir/$tfile $f
3943         local fid=$(path2fid $f)
3944
3945         changelog_setup
3946
3947         $LFS hsm_restore $f
3948         wait_request_state $fid RESTORE SUCCEED
3949
3950         local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
3951
3952         local target=0x80
3953         [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
3954
3955         cleanup
3956 }
3957 run_test 222a "Changelog for explicit restore"
3958
3959 test_222b() {
3960         # test needs a running copytool
3961         copytool_setup
3962
3963         mkdir -p $DIR/$tdir
3964         local f=$DIR/$tdir/$tfile
3965         local fid=$(copy_file /etc/passwd $f)
3966
3967         changelog_setup
3968         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3969         wait_request_state $fid ARCHIVE SUCCEED
3970         $LFS hsm_release $f
3971
3972         md5sum $f
3973
3974         wait_request_state $fid RESTORE SUCCEED
3975
3976         local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
3977
3978         local target=0x80
3979         [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
3980
3981         cleanup
3982 }
3983 run_test 222b "Changelog for implicit restore"
3984
3985 test_223a() {
3986         # test needs a running copytool
3987         copytool_setup
3988
3989         mkdir -p $DIR/$tdir
3990
3991         local f=$DIR/$tdir/$tfile
3992         make_archive $tdir/$tfile
3993
3994         changelog_setup
3995
3996         import_file $tdir/$tfile $f
3997         local fid=$(path2fid $f)
3998
3999         $LFS hsm_restore $f
4000         wait_request_state $fid RESTORE STARTED
4001         $LFS hsm_cancel $f
4002         wait_request_state $fid RESTORE CANCELED
4003         wait_request_state $fid CANCEL SUCCEED
4004
4005         local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
4006
4007         local target=0xfd
4008         [[ $flags == $target ]] ||
4009                 error "Changelog flag is $flags not $target"
4010
4011         cleanup
4012 }
4013 run_test 223a "Changelog for restore canceled (import case)"
4014
4015 test_223b() {
4016         # test needs a running copytool
4017         copytool_setup
4018
4019         mkdir -p $DIR/$tdir
4020
4021         local f=$DIR/$tdir/$tfile
4022         local fid
4023         fid=$(make_custom_file_for_progress $f 39 1000000)
4024         [ $? != 0 ] && skip "not enough free space" && return
4025
4026         changelog_setup
4027         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
4028         wait_request_state $fid ARCHIVE SUCCEED
4029         $LFS hsm_release $f
4030         $LFS hsm_restore $f
4031         wait_request_state $fid RESTORE STARTED
4032         $LFS hsm_cancel $f
4033         wait_request_state $fid RESTORE CANCELED
4034         wait_request_state $fid CANCEL SUCCEED
4035
4036         local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
4037
4038         local target=0xfd
4039         [[ $flags == $target ]] ||
4040                 error "Changelog flag is $flags not $target"
4041
4042         cleanup
4043 }
4044 run_test 223b "Changelog for restore canceled (release case)"
4045
4046 test_224() {
4047         # test needs a running copytool
4048         copytool_setup
4049
4050         mkdir -p $DIR/$tdir
4051
4052         local f=$DIR/$tdir/$tfile
4053         local fid=$(copy_file /etc/passwd $f)
4054
4055         changelog_setup
4056         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
4057         wait_request_state $fid ARCHIVE SUCCEED
4058
4059         $LFS hsm_remove $f
4060         wait_request_state $fid REMOVE SUCCEED
4061
4062         local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -n 1)
4063
4064         local target=0x200
4065         [[ $flags == $target ]] ||
4066                 error "Changelog flag is $flags not $target"
4067
4068         cleanup
4069 }
4070 run_test 224 "Changelog for remove"
4071
4072 test_225() {
4073         # test needs a running copytool
4074         copytool_setup
4075
4076         # test is not usable because remove request is too fast
4077         # so it is always finished before cancel can be done ...
4078         echo "Test disabled"
4079         copytool_cleanup
4080         return 0
4081
4082         mkdir -p $DIR/$tdir
4083         local f=$DIR/$tdir/$tfile
4084         local fid
4085         fid=$(make_custom_file_for_progress $f 39 1000000)
4086         [ $? != 0 ] && skip "not enough free space" && return
4087
4088         changelog_setup
4089         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
4090         wait_request_state $fid ARCHIVE SUCCEED
4091
4092         # if cdt is on, it can serve too quickly the request
4093         cdt_disable
4094         $LFS hsm_remove $f
4095         $LFS hsm_cancel $f
4096         cdt_enable
4097         wait_request_state $fid REMOVE CANCELED
4098         wait_request_state $fid CANCEL SUCCEED
4099
4100         flags=$(changelog_get_flags ${MDT[0]} RENME $fid2)
4101         local flags=$($LFS changelog ${MDT[0]} | grep HSM | grep $fid |
4102                 tail -n 1 | awk '{print $5}')
4103
4104         local target=0x27d
4105         [[ $flags == $target ]] ||
4106                 error "Changelog flag is $flags not $target"
4107
4108         cleanup
4109 }
4110 run_test 225 "Changelog for remove canceled"
4111
4112 test_226() {
4113         # test needs a running copytool
4114         copytool_setup
4115
4116         mkdir -p $DIR/$tdir
4117
4118         local f1=$DIR/$tdir/$tfile-1
4119         local f2=$DIR/$tdir/$tfile-2
4120         local f3=$DIR/$tdir/$tfile-3
4121         local fid1=$(copy_file /etc/passwd $f1)
4122         local fid2=$(copy_file /etc/passwd $f2)
4123         copy_file /etc/passwd $f3
4124
4125         changelog_setup
4126         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f1
4127         wait_request_state $fid1 ARCHIVE SUCCEED
4128
4129         $LFS hsm_archive $f2
4130         wait_request_state $fid2 ARCHIVE SUCCEED
4131
4132         rm $f1 || error "rm $f1 failed"
4133
4134         local flags=$(changelog_get_flags ${MDT[0]} UNLNK $fid1)
4135
4136         local target=0x3
4137         [[ $flags == $target ]] ||
4138                 error "Changelog flag is $flags not $target"
4139
4140         mv $f3 $f2 || error "mv $f3 $f2 failed"
4141
4142         flags=$(changelog_get_flags ${MDT[0]} RENME $fid2)
4143
4144         target=0x3
4145         [[ $flags == $target ]] ||
4146                 error "Changelog flag is $flags not $target"
4147
4148         cleanup
4149 }
4150 run_test 226 "changelog for last rm/mv with exiting archive"
4151
4152 check_flags_changes() {
4153         local f=$1
4154         local fid=$2
4155         local hsm_flag=$3
4156         local fst=$4
4157         local cnt=$5
4158
4159         local target=0x280
4160         $LFS hsm_set --$hsm_flag $f ||
4161                 error "Cannot set $hsm_flag on $f"
4162         local flags=($(changelog_get_flags ${MDT[0]} HSM $fid))
4163         local seen=${#flags[*]}
4164         cnt=$((fst + cnt))
4165         [[ $seen == $cnt ]] ||
4166                 error "set $hsm_flag: Changelog events $seen != $cnt"
4167         [[ ${flags[$((cnt - 1))]} == $target ]] ||
4168                 error "set $hsm_flag: Changelog flags are "\
4169                         "${flags[$((cnt - 1))]} not $target"
4170
4171         $LFS hsm_clear --$hsm_flag $f ||
4172                 error "Cannot clear $hsm_flag on $f"
4173         flags=($(changelog_get_flags ${MDT[0]} HSM $fid))
4174         seen=${#flags[*]}
4175         cnt=$(($cnt + 1))
4176         [[ $cnt == $seen ]] ||
4177                 error "clear $hsm_flag: Changelog events $seen != $cnt"
4178
4179         [[ ${flags[$((cnt - 1))]} == $target ]] ||
4180                 error "clear $hsm_flag: Changelog flag is "\
4181                         "${flags[$((cnt - 1))]} not $target"
4182 }
4183
4184 test_227() {
4185         # test needs a running copytool
4186         copytool_setup
4187         changelog_setup
4188
4189         mkdir -p $DIR/$tdir
4190         typeset -a flags
4191
4192         for i in norelease noarchive exists archived
4193         do
4194                 local f=$DIR/$tdir/$tfile-$i
4195                 local fid=$(copy_file /etc/passwd $f)
4196                 check_flags_changes $f $fid $i 0 1
4197         done
4198
4199         f=$DIR/$tdir/$tfile---lost
4200         fid=$(copy_file /etc/passwd $f)
4201         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
4202         wait_request_state $fid ARCHIVE SUCCEED
4203         check_flags_changes $f $fid lost 3 1
4204
4205         cleanup
4206 }
4207 run_test 227 "changelog when explicit setting of HSM flags"
4208
4209 test_228() {
4210         # test needs a running copytool
4211         copytool_setup
4212
4213         local fid=$(make_small_sync $DIR/$tfile)
4214         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $DIR/$tfile
4215         wait_request_state $fid ARCHIVE SUCCEED
4216
4217         $LFS hsm_release $DIR/$tfile
4218         check_hsm_flags $DIR/$tfile "0x0000000d"
4219
4220         filefrag $DIR/$tfile | grep " 1 extent found" ||
4221                 error "filefrag on released file must return only one extent"
4222
4223         # only newer versions of cp detect sparse files by stat/FIEMAP
4224         # (LU-2580)
4225         cp --sparse=auto $DIR/$tfile $DIR/$tfile.2 ||
4226                 error "copying $DIR/$tfile"
4227         cmp $DIR/$tfile $DIR/$tfile.2 || error "comparing copied $DIR/$tfile"
4228
4229         $LFS hsm_release $DIR/$tfile
4230         check_hsm_flags $DIR/$tfile "0x0000000d"
4231
4232         mkdir -p $DIR/$tdir || error "mkdir $tdir failed"
4233
4234         tar cf - --sparse $DIR/$tfile | tar xvf - -C $DIR/$tdir ||
4235                 error "tar failed"
4236         cmp $DIR/$tfile $DIR/$tdir/$DIR/$tfile ||
4237                 error "comparing untarred $DIR/$tfile"
4238
4239         rm -f $DIR/$tfile $DIR/$tfile.2 ||
4240                 error "rm $DIR/$tfile or $DIR/$tfile.2 failed"
4241         copytool_cleanup
4242 }
4243 run_test 228 "On released file, return extend to FIEMAP. For [cp,tar] --sparse"
4244
4245 test_250() {
4246         # test needs a running copytool
4247         copytool_setup
4248
4249         mkdir -p $DIR/$tdir
4250         local maxrequest=$(get_hsm_param max_requests)
4251         local rqcnt=$(($maxrequest * 3))
4252         local i=""
4253
4254         cdt_disable
4255         for i in $(seq -w 1 $rqcnt); do
4256                 rm -f $DIR/$tdir/$i
4257                 dd if=/dev/urandom of=$DIR/$tdir/$i bs=1M count=10 conv=fsync
4258         done
4259         # we do it in 2 steps, so all requests arrive at the same time
4260         for i in $(seq -w 1 $rqcnt); do
4261                 $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $DIR/$tdir/$i
4262         done
4263         cdt_enable
4264         local cnt=$rqcnt
4265         local wt=$rqcnt
4266         while [[ $cnt != 0 || $wt != 0 ]]; do
4267                 sleep 1
4268                 cnt=$(do_facet $SINGLEMDS "$LCTL get_param -n\
4269                         $HSM_PARAM.actions |\
4270                         grep STARTED | grep -v CANCEL | wc -l")
4271                 [[ $cnt -le $maxrequest ]] ||
4272                         error "$cnt > $maxrequest too many started requests"
4273                 wt=$(do_facet $SINGLEMDS "$LCTL get_param\
4274                         $HSM_PARAM.actions |\
4275                         grep WAITING | wc -l")
4276                 echo "max=$maxrequest started=$cnt waiting=$wt"
4277         done
4278
4279         copytool_cleanup
4280 }
4281 run_test 250 "Coordinator max request"
4282
4283 test_251() {
4284         # test needs a running copytool
4285         copytool_setup
4286
4287         mkdir -p $DIR/$tdir
4288         local f=$DIR/$tdir/$tfile
4289         local fid
4290         fid=$(make_custom_file_for_progress $f 103 1048576)
4291         [ $? != 0 ] && skip "not enough free space" && return
4292
4293         cdt_disable
4294         # to have a short test
4295         local old_to=$(get_hsm_param active_request_timeout)
4296         set_hsm_param active_request_timeout 4
4297         # to be sure the cdt will wake up frequently so
4298         # it will be able to cancel the "old" request
4299         local old_loop=$(get_hsm_param loop_period)
4300         set_hsm_param loop_period 2
4301         cdt_enable
4302
4303         # clear locks to avoid extra delay caused by flush/cancel
4304         # and thus prevent early copytool death to timeout.
4305         cancel_lru_locks osc
4306
4307         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
4308         wait_request_state $fid ARCHIVE STARTED
4309         sleep 5
4310         wait_request_state $fid ARCHIVE CANCELED
4311
4312         set_hsm_param active_request_timeout $old_to
4313         set_hsm_param loop_period $old_loop
4314
4315         copytool_cleanup
4316 }
4317 run_test 251 "Coordinator request timeout"
4318
4319 test_300() {
4320         # the only way to test ondisk conf is to restart MDS ...
4321         echo "Stop coordinator and remove coordinator state at mount"
4322         # stop coordinator
4323         cdt_shutdown
4324         # clean on disk conf set by default
4325         cdt_clear_mount_state
4326         cdt_check_state stopped
4327
4328         # check cdt still off after umount/remount
4329         fail $SINGLEMDS
4330         cdt_check_state stopped
4331
4332         echo "Set coordinator start at mount, and start coordinator"
4333         cdt_set_mount_state enabled
4334
4335         # check cdt is on
4336         cdt_check_state enabled
4337
4338         # check cdt still on after umount/remount
4339         fail $SINGLEMDS
4340         cdt_check_state enabled
4341
4342         # we are back to original state (cdt started at mount)
4343 }
4344 run_test 300 "On disk coordinator state kept between MDT umount/mount"
4345
4346 test_301() {
4347         local ai=$(get_hsm_param default_archive_id)
4348         local new=$((ai + 1))
4349
4350         set_hsm_param default_archive_id $new -P
4351         fail $SINGLEMDS
4352         local res=$(get_hsm_param default_archive_id)
4353
4354         # clear value
4355         set_hsm_param default_archive_id "" "-P -d"
4356
4357         [[ $new == $res ]] || error "Value after MDS restart is $res != $new"
4358 }
4359 run_test 301 "HSM tunnable are persistent"
4360
4361 test_302() {
4362         local ai=$(get_hsm_param default_archive_id)
4363         local new=$((ai + 1))
4364
4365         # stop coordinator
4366         cdt_shutdown
4367
4368         set_hsm_param default_archive_id $new -P
4369
4370         local mdtno
4371         for mdtno in $(seq 1 $MDSCOUNT); do
4372                 fail mds${mdtno}
4373         done
4374
4375         # check cdt is on
4376         cdt_check_state enabled
4377
4378         local res=$(get_hsm_param default_archive_id)
4379
4380         # clear value
4381         set_hsm_param default_archive_id "" "-P -d"
4382
4383         [[ $new == $res ]] || error "Value after MDS restart is $res != $new"
4384 }
4385 run_test 302 "HSM tunnable are persistent when CDT is off"
4386
4387 test_400() {
4388         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
4389
4390         copytool_setup
4391
4392         mkdir -p $DIR/$tdir
4393
4394         local dir_mdt0=$DIR/$tdir/mdt0
4395         local dir_mdt1=$DIR/$tdir/mdt1
4396
4397         # create 1 dir per MDT
4398         $LFS mkdir -i 0 $dir_mdt0 || error "lfs mkdir"
4399         $LFS mkdir -i 1 $dir_mdt1 || error "lfs mkdir"
4400
4401         # create 1 file in each MDT
4402         local fid1=$(make_small $dir_mdt0/$tfile)
4403         local fid2=$(make_small $dir_mdt1/$tfile)
4404
4405         # check that hsm request on mdt0 is sent to the right MDS
4406         $LFS hsm_archive $dir_mdt0/$tfile || error "lfs hsm_archive"
4407         wait_request_state $fid1 ARCHIVE SUCCEED 0 &&
4408                 echo "archive successful on mdt0"
4409
4410         # check that hsm request on mdt1 is sent to the right MDS
4411         $LFS hsm_archive $dir_mdt1/$tfile || error "lfs hsm_archive"
4412         wait_request_state $fid2 ARCHIVE SUCCEED 1 &&
4413                 echo "archive successful on mdt1"
4414
4415         copytool_cleanup
4416         # clean test files and directories
4417         rm -rf $dir_mdt0 $dir_mdt1
4418 }
4419 run_test 400 "Single request is sent to the right MDT"
4420
4421 test_401() {
4422         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
4423
4424         copytool_setup
4425
4426         mkdir -p $DIR/$tdir
4427
4428         local dir_mdt0=$DIR/$tdir/mdt0
4429         local dir_mdt1=$DIR/$tdir/mdt1
4430
4431         # create 1 dir per MDT
4432         $LFS mkdir -i 0 $dir_mdt0 || error "lfs mkdir"
4433         $LFS mkdir -i 1 $dir_mdt1 || error "lfs mkdir"
4434
4435         # create 1 file in each MDT
4436         local fid1=$(make_small $dir_mdt0/$tfile)
4437         local fid2=$(make_small $dir_mdt1/$tfile)
4438
4439         # check that compound requests are shunt to the rights MDTs
4440         $LFS hsm_archive $dir_mdt0/$tfile $dir_mdt1/$tfile ||
4441                 error "lfs hsm_archive"
4442         wait_request_state $fid1 ARCHIVE SUCCEED 0 &&
4443                 echo "archive successful on mdt0"
4444         wait_request_state $fid2 ARCHIVE SUCCEED 1 &&
4445                 echo "archive successful on mdt1"
4446
4447         copytool_cleanup
4448         # clean test files and directories
4449         rm -rf $dir_mdt0 $dir_mdt1
4450 }
4451 run_test 401 "Compound requests split and sent to their respective MDTs"
4452
4453 mdc_change_state() # facet, MDT_pattern, activate|deactivate
4454 {
4455         local facet=$1
4456         local pattern="$2"
4457         local state=$3
4458         local node=$(facet_active_host $facet)
4459         local mdc
4460         for mdc in $(do_facet $facet "$LCTL dl | grep -E ${pattern}-mdc" |
4461                         awk '{print $4}'); do
4462                 echo "$3 $mdc on $node"
4463                 do_facet $facet "$LCTL --device $mdc $state" || return 1
4464         done
4465 }
4466
4467 test_402() {
4468         # make sure there is no running copytool
4469         copytool_cleanup
4470
4471         # deactivate all mdc on agent1
4472         mdc_change_state $SINGLEAGT "$FSNAME-MDT000." "deactivate"
4473
4474         HSMTOOL_NOERROR=true copytool_setup $SINGLEAGT
4475
4476         check_agent_unregistered "uuid" # match any agent
4477
4478         # no expected running copytool
4479         search_copytools $agent && error "Copytool start should have failed"
4480
4481         # reactivate MDCs
4482         mdc_change_state $SINGLEAGT "$FSNAME-MDT000." "activate"
4483 }
4484 run_test 402 "Copytool start fails if all MDTs are inactive"
4485
4486 test_403() {
4487         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
4488
4489         # make sure there is no running copytool
4490         copytool_cleanup
4491
4492         local agent=$(facet_active_host $SINGLEAGT)
4493
4494         # deactivate all mdc for MDT0001
4495         mdc_change_state $SINGLEAGT "$FSNAME-MDT0001" "deactivate"
4496
4497         copytool_setup
4498         local uuid=$(get_agent_uuid $agent)
4499         # check the agent is registered on MDT0000, and not on MDT0001
4500         check_agent_registered_by_mdt $uuid 0
4501         check_agent_unregistered_by_mdt $uuid 1
4502
4503         # check running copytool process
4504         search_copytools $agent || error "No running copytools on $agent"
4505
4506         # reactivate all mdc for MDT0001
4507         mdc_change_state $SINGLEAGT "$FSNAME-MDT0001" "activate"
4508
4509         # make sure the copytool is now registered to all MDTs
4510         check_agent_registered $uuid
4511
4512         copytool_cleanup
4513 }
4514 run_test 403 "Copytool starts with inactive MDT and register on reconnect"
4515
4516 test_404() {
4517         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
4518
4519         copytool_setup
4520
4521         # create files on both MDT0000 and MDT0001
4522         mkdir -p $DIR/$tdir
4523
4524         local dir_mdt0=$DIR/$tdir/mdt0
4525         $LFS mkdir -i 0 $dir_mdt0 || error "lfs mkdir"
4526
4527         # create 1 file on mdt0
4528         local fid1=$(make_small $dir_mdt0/$tfile)
4529
4530         # deactivate all mdc for MDT0001
4531         mdc_change_state $SINGLEAGT "$FSNAME-MDT0001" "deactivate"
4532
4533         # send an HSM request for files in MDT0000
4534         $LFS hsm_archive $dir_mdt0/$tfile || error "lfs hsm_archive"
4535
4536         # check for completion of files in MDT0000
4537         wait_request_state $fid1 ARCHIVE SUCCEED 0 &&
4538                 echo "archive successful on mdt0"
4539
4540         # reactivate all mdc for MDT0001
4541         mdc_change_state $SINGLEAGT "$FSNAME-MDT0001" "activate"
4542
4543         copytool_cleanup
4544         # clean test files and directories
4545         rm -rf $dir_mdt0
4546 }
4547 run_test 404 "Inactive MDT does not block requests for active MDTs"
4548
4549 test_405() {
4550         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
4551
4552         copytool_setup
4553
4554         mkdir -p $DIR/$tdir
4555
4556         local striped_dir=$DIR/$tdir/striped_dir
4557
4558         # create striped dir on all of MDTs
4559         $LFS mkdir -i 0 -c $MDSCOUNT $striped_dir || error "lfs mkdir"
4560
4561         local fid1=$(make_small_sync $striped_dir/${tfile}_0)
4562         local fid2=$(make_small_sync $striped_dir/${tfile}_1)
4563         local fid3=$(make_small_sync $striped_dir/${tfile}_2)
4564         local fid4=$(make_small_sync $striped_dir/${tfile}_3)
4565
4566         local idx1=$($LFS getstripe -M $striped_dir/${tfile}_0)
4567         local idx2=$($LFS getstripe -M $striped_dir/${tfile}_1)
4568         local idx3=$($LFS getstripe -M $striped_dir/${tfile}_2)
4569         local idx4=$($LFS getstripe -M $striped_dir/${tfile}_3)
4570
4571         # check that compound requests are shunt to the rights MDTs
4572         $LFS hsm_archive $striped_dir/${tfile}_0 $striped_dir/${tfile}_1  \
4573                          $striped_dir/${tfile}_2 $striped_dir/${tfile}_3 ||
4574                 error "lfs hsm_archive"
4575
4576         wait_request_state $fid1 ARCHIVE SUCCEED $idx1 &&
4577                 echo "archive successful on $fid1"
4578         wait_request_state $fid2 ARCHIVE SUCCEED $idx2 &&
4579                 echo "archive successful on $fid2"
4580         wait_request_state $fid3 ARCHIVE SUCCEED $idx3 &&
4581                 echo "archive successful on $fid3"
4582         wait_request_state $fid4 ARCHIVE SUCCEED $idx4 &&
4583                 echo "archive successful on $fid4"
4584
4585         $LFS hsm_release $striped_dir/${tfile}_0 || error "lfs hsm_release 1"
4586         $LFS hsm_release $striped_dir/${tfile}_1 || error "lfs hsm_release 2"
4587         $LFS hsm_release $striped_dir/${tfile}_2 || error "lfs hsm_release 3"
4588         $LFS hsm_release $striped_dir/${tfile}_3 || error "lfs hsm_release 4"
4589
4590         cat $striped_dir/${tfile}_0 > /dev/null || error "cat ${tfile}_0 failed"
4591         cat $striped_dir/${tfile}_1 > /dev/null || error "cat ${tfile}_1 failed"
4592         cat $striped_dir/${tfile}_2 > /dev/null || error "cat ${tfile}_2 failed"
4593         cat $striped_dir/${tfile}_3 > /dev/null || error "cat ${tfile}_3 failed"
4594
4595         copytool_cleanup
4596 }
4597 run_test 405 "archive and release under striped directory"
4598
4599 test_406() {
4600         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return 0
4601
4602         [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.7.64) ] &&
4603                 skip "need MDS version at least 2.7.64" && return 0
4604
4605         local fid
4606         local mdt_index
4607
4608         copytool_setup
4609         mkdir -p $DIR/$tdir
4610         fid=$(make_small $DIR/$tdir/$tfile)
4611         echo "old fid $fid"
4612
4613         $LFS hsm_archive $DIR/$tdir/$tfile
4614         wait_request_state "$fid" ARCHIVE SUCCEED
4615         $LFS hsm_release $DIR/$tdir/$tfile
4616
4617         # Should migrate $tdir but not $tfile.
4618         $LFS mv -M1 $DIR/$tdir &&
4619                 error "migrating HSM an archived file should fail"
4620
4621         $LFS hsm_restore $DIR/$tdir/$tfile
4622         wait_request_state "$fid" RESTORE SUCCEED
4623
4624         $LFS hsm_remove $DIR/$tdir/$tfile
4625         wait_request_state "$fid" REMOVE SUCCEED
4626
4627         cat $DIR/$tdir/$tfile > /dev/null ||
4628                 error "cannot read $DIR/$tdir/$tfile"
4629
4630         $LFS mv -M1 $DIR/$tdir ||
4631                 error "cannot complete migration after HSM remove"
4632
4633         mdt_index=$($LFS getstripe -M $DIR/$tdir)
4634         if ((mdt_index != 1)); then
4635                 error "expected MDT index 1, got $mdt_index"
4636         fi
4637
4638         # Refresh fid after migration.
4639         fid=$(path2fid $DIR/$tdir/$tfile)
4640         echo "new fid $fid"
4641
4642         $LFS hsm_archive $DIR/$tdir/$tfile
4643         wait_request_state "$fid" ARCHIVE SUCCEED 1
4644
4645         lctl set_param debug=+trace
4646         $LFS hsm_release $DIR/$tdir/$tfile ||
4647                 error "cannot release $DIR/$tdir/$tfile"
4648
4649         $LFS hsm_restore $DIR/$tdir/$tfile
4650         wait_request_state "$fid" RESTORE SUCCEED 1
4651
4652         cat $DIR/$tdir/$tfile > /dev/null ||
4653                 error "cannot read $DIR/$tdir/$tfile"
4654
4655         copytool_cleanup
4656 }
4657 run_test 406 "attempting to migrate HSM archived files is safe"
4658
4659 test_500()
4660 {
4661         [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.6.92) ] &&
4662                 skip "HSM migrate is not supported" && return
4663
4664         # Stop the existing copytool
4665         copytool_cleanup
4666
4667         test_mkdir -p $DIR/$tdir
4668         llapi_hsm_test -d $DIR/$tdir || error "One llapi HSM test failed"
4669 }
4670 run_test 500 "various LLAPI HSM tests"
4671
4672 copytool_cleanup
4673
4674 complete $SECONDS
4675 check_and_cleanup_lustre
4676 exit_status