Whamcloud - gitweb
LU-8163 hsm: user_request_mask can't be unset in test 24c
[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_large_for_striping() {
685         local file2=${1/$DIR/$DIR2}
686         local sz=$($LCTL get_param -n lov.*-clilov-*.stripesize | head -n1)
687
688         cleanup_large_files
689
690         check_enough_free_space 5 $sz
691         [ $? != 0 ] && return $?
692
693         dd if=/dev/urandom of=$file2 count=5 bs=$sz conv=fsync ||
694                 file_creation_failure dd $file2 $?
695
696         path2fid $1 || error "cannot get fid on $1"
697 }
698
699 make_large_for_progress() {
700         local file2=${1/$DIR/$DIR2}
701
702         cleanup_large_files
703
704         check_enough_free_space 39 1000000
705         [ $? != 0 ] && return $?
706
707         # big file is large enough, so copy time is > 30s
708         # so copytool make 1 progress
709         # size is not a multiple of 1M to avoid stripe
710         # aligment
711         dd if=/dev/urandom of=$file2 count=39 bs=1000000 conv=fsync ||
712                 file_creation_failure dd $file2 $?
713
714         path2fid $1 || error "cannot get fid on $1"
715 }
716
717 make_large_for_progress_aligned() {
718         local file2=${1/$DIR/$DIR2}
719
720         cleanup_large_files
721
722         check_enough_free_space 33 1048576
723         [ $? != 0 ] && return $?
724
725         # big file is large enough, so copy time is > 30s
726         # so copytool make 1 progress
727         # size is a multiple of 1M to have stripe
728         # aligment
729         dd if=/dev/urandom of=$file2 count=33 bs=1M conv=fsync ||
730                 file_creation_failure dd $file2 $?
731         path2fid $1 || error "cannot get fid on $1"
732 }
733
734 make_large_for_cancel() {
735         local file2=${1/$DIR/$DIR2}
736
737         cleanup_large_files
738
739         check_enough_free_space 103 1048576
740         [ $? != 0 ] && return $?
741
742         # Copy timeout is 100s. 105MB => 105s
743         dd if=/dev/urandom of=$file2 count=103 bs=1M conv=fsync ||
744                 file_creation_failure dd $file2 $?
745         path2fid $1 || error "cannot get fid on $1"
746 }
747
748 wait_result() {
749         local facet=$1
750         shift
751         wait_update --verbose $(facet_active_host $facet) "$@"
752 }
753
754 wait_request_state() {
755         local fid=$1
756         local request=$2
757         local state=$3
758         # 4th arg (mdt index) is optional
759         local mdtidx=${4:-0}
760         local mds=mds$(($mdtidx + 1))
761
762         local cmd="$LCTL get_param -n ${MDT_PREFIX}${mdtidx}.hsm.actions"
763         cmd+=" | awk '/'$fid'.*action='$request'/ {print \\\$13}' | cut -f2 -d="
764
765         wait_result $mds "$cmd" $state 200 ||
766                 error "request on $fid is not $state on $mds"
767 }
768
769 get_request_state() {
770         local fid=$1
771         local request=$2
772
773         do_facet $SINGLEMDS "$LCTL get_param -n $HSM_PARAM.actions |"\
774                 "awk '/'$fid'.*action='$request'/ {print \\\$13}' | cut -f2 -d="
775 }
776
777 get_request_count() {
778         local fid=$1
779         local request=$2
780
781         do_facet $SINGLEMDS "$LCTL get_param -n $HSM_PARAM.actions |"\
782                 "awk -vn=0 '/'$fid'.*action='$request'/ {n++}; END {print n}'"
783 }
784
785 wait_all_done() {
786         local timeout=$1
787         local fid=$2
788
789         local cmd="$LCTL get_param -n $HSM_PARAM.actions"
790         [[ -n $fid ]] && cmd+=" | grep '$fid'"
791         cmd+=" | egrep 'WAITING|STARTED'"
792
793         wait_result $SINGLEMDS "$cmd" "" $timeout ||
794                 error "requests did not complete"
795 }
796
797 wait_for_grace_delay() {
798         local val=$(get_hsm_param grace_delay)
799         sleep $val
800 }
801
802 parse_json_event() {
803         local raw_event=$1
804
805         # python2.6 in EL6 includes an internal json module
806         local json_parser='import json; import fileinput;'
807         json_parser+=' print "\n".join(["local %s=\"%s\"" % tuple for tuple in '
808         json_parser+='json.loads([line for line in '
809         json_parser+='fileinput.input()][0]).items()])'
810
811         echo $raw_event | python -c "$json_parser"
812 }
813
814 get_agent_by_uuid_mdt() {
815         local uuid=$1
816         local mdtidx=$2
817         local mds=mds$(($mdtidx + 1))
818         do_facet $mds "$LCTL get_param -n ${MDT_PREFIX}${mdtidx}.hsm.agents |\
819                  grep $uuid"
820 }
821
822 check_agent_registered_by_mdt() {
823         local uuid=$1
824         local mdtidx=$2
825         local mds=mds$(($mdtidx + 1))
826         local agent=$(get_agent_by_uuid_mdt $uuid $mdtidx)
827         if [[ ! -z "$agent" ]]; then
828                 echo "found agent $agent on $mds"
829         else
830                 error "uuid $uuid not found in agent list on $mds"
831         fi
832 }
833
834 check_agent_unregistered_by_mdt() {
835         local uuid=$1
836         local mdtidx=$2
837         local mds=mds$(($mdtidx + 1))
838         local agent=$(get_agent_by_uuid_mdt $uuid $mdtidx)
839         if [[ -z "$agent" ]]; then
840                 echo "uuid not found in agent list on $mds"
841         else
842                 error "uuid found in agent list on $mds: $agent"
843         fi
844 }
845
846 check_agent_registered() {
847         local uuid=$1
848         local mdsno
849         for mdsno in $(seq 1 $MDSCOUNT); do
850                 check_agent_registered_by_mdt $uuid $((mdsno - 1))
851         done
852 }
853
854 check_agent_unregistered() {
855         local uuid=$1
856         local mdsno
857         for mdsno in $(seq 1 $MDSCOUNT); do
858                 check_agent_unregistered_by_mdt $uuid $((mdsno - 1))
859         done
860 }
861
862 get_agent_uuid() {
863         local agent=${1:-$(facet_active_host $SINGLEAGT)}
864
865         # Lustre mount-point is mandatory and last parameter on
866         # copytool cmd-line.
867         local mntpnt=$(do_rpc_nodes $agent ps -C $HSMTOOL_BASE -o args= |
868                        awk '{print $NF}')
869         [ -n "$mntpnt" ] || error "Found no Agent or with no mount-point "\
870                                   "parameter"
871         do_rpc_nodes $agent get_client_uuid $mntpnt | cut -d' ' -f2
872 }
873
874 # initiate variables
875 init_agt_vars
876
877 # populate MDT device array
878 get_mdt_devices
879
880 # cleanup from previous bad setup
881 kill_copytools
882
883 # for recovery tests, coordinator needs to be started at mount
884 # so force it
885 # the lustre conf must be without hsm on (like for sanity.sh)
886 echo "Set HSM on and start"
887 cdt_set_mount_state enabled
888 cdt_check_state enabled
889
890 echo "Start copytool"
891 copytool_setup
892
893 echo "Set sanity-hsm HSM policy"
894 cdt_set_sanity_policy
895
896 # finished requests are quickly removed from list
897 set_hsm_param grace_delay 10
898
899 test_1() {
900         mkdir -p $DIR/$tdir
901         chmod 777 $DIR/$tdir
902
903         local f=$DIR/$tdir/$tfile
904         $RUNAS touch $f
905
906         # User flags
907         check_hsm_flags_user $f "0x00000000"
908
909         $RUNAS $LFS hsm_set --norelease $f ||
910                 error "user could not change hsm flags"
911         check_hsm_flags_user $f "0x00000010"
912
913         $RUNAS $LFS hsm_clear --norelease $f ||
914                 error "user could not clear hsm flags"
915         check_hsm_flags_user $f "0x00000000"
916
917         # User could not change those flags...
918         $RUNAS $LFS hsm_set --exists $f &&
919                 error "user should not set this flag"
920         check_hsm_flags_user $f "0x00000000"
921
922         # ...but root can
923         $LFS hsm_set --exists $f ||
924                 error "root could not change hsm flags"
925         check_hsm_flags_user $f "0x00000001"
926
927         $LFS hsm_clear --exists $f ||
928                 error "root could not clear hsm state"
929         check_hsm_flags_user $f "0x00000000"
930
931 }
932 run_test 1 "lfs hsm flags root/non-root access"
933
934 test_1a() {
935         mkdir -p $DIR/$tdir
936         local f=$DIR/$tdir/$tfile
937         local fid=$(make_small $f)
938
939         $LFS hsm_archive $f || error "could not archive file"
940         wait_request_state $fid ARCHIVE SUCCEED
941
942         # Release and check states
943         $LFS hsm_release $f || error "could not release file"
944         echo -n "Verifying released state: "
945         check_hsm_flags $f "0x0000000d"
946
947         $MMAP_CAT $f > /dev/null || error "failed mmap & cat release file"
948 }
949 run_test 1a "mmap & cat a HSM released file"
950
951 test_2() {
952         mkdir -p $DIR/$tdir
953         local f=$DIR/$tdir/$tfile
954         touch $f
955         # New files are not dirty
956         check_hsm_flags $f "0x00000000"
957
958         # For test, we simulate an archived file.
959         $LFS hsm_set --exists $f || error "user could not change hsm flags"
960         check_hsm_flags $f "0x00000001"
961
962         # chmod do not put the file dirty
963         chmod 600 $f || error "could not chmod test file"
964         check_hsm_flags $f "0x00000001"
965
966         # chown do not put the file dirty
967         chown $RUNAS_ID $f || error "could not chown test file"
968         check_hsm_flags $f "0x00000001"
969
970         # truncate put the file dirty
971         $TRUNCATE $f 1 || error "could not truncate test file"
972         check_hsm_flags $f "0x00000003"
973
974         $LFS hsm_clear --dirty $f || error "could not clear hsm flags"
975         check_hsm_flags $f "0x00000001"
976 }
977 run_test 2 "Check file dirtyness when doing setattr"
978
979 test_3() {
980         mkdir -p $DIR/$tdir
981         f=$DIR/$tdir/$tfile
982
983         # New files are not dirty
984         cp -p /etc/passwd $f
985         check_hsm_flags $f "0x00000000"
986
987         # For test, we simulate an archived file.
988         $LFS hsm_set --exists $f ||
989                 error "user could not change hsm flags"
990         check_hsm_flags $f "0x00000001"
991
992         # Reading a file, does not set dirty
993         cat $f > /dev/null || error "could not read file"
994         check_hsm_flags $f "0x00000001"
995
996         # Open for write without modifying data, does not set dirty
997         openfile -f O_WRONLY $f || error "could not open test file"
998         check_hsm_flags $f "0x00000001"
999
1000         # Append to a file sets it dirty
1001         cp -p /etc/passwd $f.append || error "could not create file"
1002         $LFS hsm_set --exists $f.append ||
1003                 error "user could not change hsm flags"
1004         dd if=/etc/passwd of=$f.append bs=1 count=3\
1005            conv=notrunc oflag=append status=noxfer ||
1006                 file_creation_failure dd $f.append $?
1007         check_hsm_flags $f.append "0x00000003"
1008
1009         # Modify a file sets it dirty
1010         cp -p /etc/passwd $f.modify || error "could not create file"
1011         $LFS hsm_set --exists $f.modify ||
1012                 error "user could not change hsm flags"
1013         dd if=/dev/zero of=$f.modify bs=1 count=3\
1014            conv=notrunc status=noxfer ||
1015                 file_creation_failure dd $f.modify $?
1016         check_hsm_flags $f.modify "0x00000003"
1017
1018         # Open O_TRUNC sets dirty
1019         cp -p /etc/passwd $f.trunc || error "could not create file"
1020         $LFS hsm_set --exists $f.trunc ||
1021                 error "user could not change hsm flags"
1022         cp /etc/group $f.trunc || error "could not override a file"
1023         check_hsm_flags $f.trunc "0x00000003"
1024
1025         # Mmapped a file sets dirty
1026         cp -p /etc/passwd $f.mmap || error "could not create file"
1027         $LFS hsm_set --exists $f.mmap ||
1028                 error "user could not change hsm flags"
1029         multiop $f.mmap OSMWUc || error "could not mmap a file"
1030         check_hsm_flags $f.mmap "0x00000003"
1031 }
1032 run_test 3 "Check file dirtyness when opening for write"
1033
1034 test_4() {
1035         mkdir -p $DIR/$tdir
1036         local f=$DIR/$tdir/$tfile
1037         local fid=$(make_small $f)
1038
1039         $LFS hsm_cancel $f
1040         local st=$(get_request_state $fid CANCEL)
1041         [[ -z "$st" ]] || error "hsm_cancel must not be registered (state=$st)"
1042 }
1043 run_test 4 "Useless cancel must not be registered"
1044
1045 test_8() {
1046         # test needs a running copytool
1047         copytool_setup
1048
1049         mkdir -p $DIR/$tdir
1050         local f=$DIR/$tdir/$tfile
1051         local fid=$(copy_file /etc/passwd $f)
1052         $LFS hsm_archive $f
1053         wait_request_state $fid ARCHIVE SUCCEED
1054
1055         check_hsm_flags $f "0x00000009"
1056
1057         copytool_cleanup
1058 }
1059 run_test 8 "Test default archive number"
1060
1061 test_9() {
1062         # we do not use the default one to be sure
1063         local new_an=$((HSM_ARCHIVE_NUMBER + 1))
1064         copytool_cleanup
1065         copytool_setup $SINGLEAGT $MOUNT $new_an
1066
1067         # give time for CT to register with MDTs
1068         sleep $(($MDSCOUNT*2))
1069         local uuid=$(get_agent_uuid $(facet_active_host $SINGLEAGT))
1070         check_agent_registered $uuid
1071
1072         mkdir -p $DIR/$tdir
1073         local f=$DIR/$tdir/$tfile
1074         local fid=$(copy_file /etc/passwd $f)
1075         $LFS hsm_archive --archive $new_an $f
1076         wait_request_state $fid ARCHIVE SUCCEED
1077
1078         check_hsm_flags $f "0x00000009"
1079
1080         copytool_cleanup
1081 }
1082 run_test 9 "Use of explicit archive number, with dedicated copytool"
1083
1084 test_9a() {
1085         needclients 3 || return 0
1086
1087         local n
1088         local file
1089         local fid
1090
1091         copytool_cleanup $(comma_list $(agts_nodes))
1092
1093         # start all of the copytools
1094         for n in $(seq $AGTCOUNT); do
1095                 copytool_setup agt$n
1096         done
1097
1098         trap "copytool_cleanup $(comma_list $(agts_nodes))" EXIT
1099         # archive files
1100         mkdir -p $DIR/$tdir
1101         for n in $(seq $AGTCOUNT); do
1102                 file=$DIR/$tdir/$tfile.$n
1103                 fid=$(make_small $file)
1104
1105                 $LFS hsm_archive $file || error "could not archive file $file"
1106                 wait_request_state $fid ARCHIVE SUCCEED
1107                 check_hsm_flags $file "0x00000009"
1108         done
1109
1110         trap - EXIT
1111         copytool_cleanup $(comma_list $(agts_nodes))
1112 }
1113 run_test 9a "Multiple remote agents"
1114
1115 test_10a() {
1116         # test needs a running copytool
1117         copytool_setup
1118
1119         mkdir -p $DIR/$tdir/d1
1120         local f=$DIR/$tdir/$tfile
1121         local fid=$(copy_file /etc/hosts $f)
1122         $LFS hsm_archive -a $HSM_ARCHIVE_NUMBER $f ||
1123                 error "hsm_archive failed"
1124         wait_request_state $fid ARCHIVE SUCCEED
1125
1126         local AFILE=$(do_facet $SINGLEAGT ls $HSM_ARCHIVE'/*/*/*/*/*/*/'$fid) ||
1127                 error "fid $fid not in archive $HSM_ARCHIVE"
1128         echo "Verifying content"
1129         do_facet $SINGLEAGT diff $f $AFILE || error "archived file differs"
1130         echo "Verifying hsm state "
1131         check_hsm_flags $f "0x00000009"
1132
1133         echo "Verifying archive number is $HSM_ARCHIVE_NUMBER"
1134         local st=$(get_hsm_archive_id $f)
1135         [[ $st == $HSM_ARCHIVE_NUMBER ]] ||
1136                 error "Wrong archive number, $st != $HSM_ARCHIVE_NUMBER"
1137
1138         copytool_cleanup
1139
1140 }
1141 run_test 10a "Archive a file"
1142
1143 test_10b() {
1144         # test needs a running copytool
1145         copytool_setup
1146
1147         mkdir -p $DIR/$tdir
1148         local f=$DIR/$tdir/$tfile
1149         local fid=$(copy_file /etc/hosts $f)
1150         $LFS hsm_archive $f || error "archive request failed"
1151         wait_request_state $fid ARCHIVE SUCCEED
1152
1153         $LFS hsm_archive $f || error "archive of non dirty file failed"
1154         local cnt=$(get_request_count $fid ARCHIVE)
1155         [[ "$cnt" == "1" ]] ||
1156                 error "archive of non dirty file must not make a request"
1157
1158         copytool_cleanup
1159 }
1160 run_test 10b "Archive of non dirty file must work without doing request"
1161
1162 test_10c() {
1163         # test needs a running copytool
1164         copytool_setup
1165
1166         mkdir -p $DIR/$tdir
1167         local f=$DIR/$tdir/$tfile
1168         local fid=$(copy_file /etc/hosts $f)
1169         $LFS hsm_set --noarchive $f
1170         $LFS hsm_archive $f && error "archive a noarchive file must fail"
1171
1172         copytool_cleanup
1173 }
1174 run_test 10c "Check forbidden archive"
1175
1176 test_10d() {
1177         # test needs a running copytool
1178         copytool_setup
1179
1180         mkdir -p $DIR/$tdir
1181         local f=$DIR/$tdir/$tfile
1182         local fid=$(copy_file /etc/hosts $f)
1183         $LFS hsm_archive $f || error "cannot archive $f"
1184         wait_request_state $fid ARCHIVE SUCCEED
1185
1186         local ar=$(get_hsm_archive_id $f)
1187         local dflt=$(get_hsm_param default_archive_id)
1188         [[ $ar == $dflt ]] ||
1189                 error "archived file is not on default archive: $ar != $dflt"
1190
1191         copytool_cleanup
1192 }
1193 run_test 10d "Archive a file on the default archive id"
1194
1195 test_11a() {
1196         mkdir -p $DIR/$tdir
1197         copy2archive /etc/hosts $tdir/$tfile
1198         local f=$DIR/$tdir/$tfile
1199
1200         import_file $tdir/$tfile $f
1201         echo -n "Verifying released state: "
1202         check_hsm_flags $f "0x0000000d"
1203
1204         local LSZ=$(stat -c "%s" $f)
1205         local ASZ=$(do_facet $SINGLEAGT stat -c "%s" $HSM_ARCHIVE/$tdir/$tfile)
1206
1207         echo "Verifying imported size $LSZ=$ASZ"
1208         [[ $LSZ -eq $ASZ ]] || error "Incorrect size $LSZ != $ASZ"
1209         echo -n "Verifying released pattern: "
1210         local PTRN=$($GETSTRIPE -L $f)
1211         echo $PTRN
1212         [[ $PTRN == 80000001 ]] || error "Is not released"
1213         local fid=$(path2fid $f)
1214         echo "Verifying new fid $fid in archive"
1215
1216         local AFILE=$(do_facet $SINGLEAGT ls $HSM_ARCHIVE'/*/*/*/*/*/*/'$fid) ||
1217                 error "fid $fid not in archive $HSM_ARCHIVE"
1218 }
1219 run_test 11a "Import a file"
1220
1221 test_11b() {
1222         # test needs a running copytool
1223         copytool_setup
1224
1225         mkdir -p $DIR/$tdir
1226         local f=$DIR/$tdir/$tfile
1227         local fid=$(copy_file /etc/hosts $f)
1228         $LFS hsm_archive -a $HSM_ARCHIVE_NUMBER $f ||
1229                 error "hsm_archive failed"
1230         wait_request_state $fid ARCHIVE SUCCEED
1231
1232         local FILE_HASH=$(md5sum $f)
1233         rm -f $f
1234
1235         import_file $fid $f
1236
1237         echo "$FILE_HASH" | md5sum -c
1238
1239         [[ $? -eq 0 ]] || error "Restored file differs"
1240
1241         copytool_cleanup
1242 }
1243 run_test 11b "Import a deleted file using its FID"
1244
1245 test_12a() {
1246         # test needs a running copytool
1247         copytool_setup
1248
1249         mkdir -p $DIR/$tdir
1250         copy2archive /etc/hosts $tdir/$tfile
1251
1252         local f=$DIR/$tdir/$tfile
1253         import_file $tdir/$tfile $f
1254         local f2=$DIR2/$tdir/$tfile
1255         echo "Verifying released state: "
1256         check_hsm_flags $f2 "0x0000000d"
1257
1258         local fid=$(path2fid $f2)
1259         $LFS hsm_restore $f2
1260         wait_request_state $fid RESTORE SUCCEED
1261
1262         echo "Verifying file state: "
1263         check_hsm_flags $f2 "0x00000009"
1264
1265         do_facet $SINGLEAGT diff -q $HSM_ARCHIVE/$tdir/$tfile $f
1266
1267         [[ $? -eq 0 ]] || error "Restored file differs"
1268
1269         copytool_cleanup
1270 }
1271 run_test 12a "Restore an imported file explicitly"
1272
1273 test_12b() {
1274         # test needs a running copytool
1275         copytool_setup
1276
1277         mkdir -p $DIR/$tdir
1278         copy2archive /etc/hosts $tdir/$tfile
1279
1280         local f=$DIR/$tdir/$tfile
1281         import_file $tdir/$tfile $f
1282         echo "Verifying released state: "
1283         check_hsm_flags $f "0x0000000d"
1284
1285         cat $f > /dev/null || error "File read failed"
1286
1287         echo "Verifying file state after restore: "
1288         check_hsm_flags $f "0x00000009"
1289
1290         do_facet $SINGLEAGT diff -q $HSM_ARCHIVE/$tdir/$tfile $f
1291
1292         [[ $? -eq 0 ]] || error "Restored file differs"
1293
1294         copytool_cleanup
1295 }
1296 run_test 12b "Restore an imported file implicitly"
1297
1298 test_12c() {
1299         [ "$OSTCOUNT" -lt "2" ] && skip_env "skipping 2-stripe test" && return
1300
1301         # test needs a running copytool
1302         copytool_setup
1303
1304         mkdir -p $DIR/$tdir
1305         local f=$DIR/$tdir/$tfile
1306         $LFS setstripe -c 2 $f
1307         local fid
1308         fid=$(make_large_for_striping $f)
1309         [ $? != 0 ] && skip "not enough free space" && return
1310
1311         local FILE_CRC=$(md5sum $f)
1312
1313         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1314         wait_request_state $fid ARCHIVE SUCCEED
1315         $LFS hsm_release $f || error "release $f failed"
1316
1317         echo "$FILE_CRC" | md5sum -c
1318
1319         [[ $? -eq 0 ]] || error "Restored file differs"
1320
1321         copytool_cleanup
1322 }
1323 run_test 12c "Restore a file with stripe of 2"
1324
1325 test_12d() {
1326         # test needs a running copytool
1327         copytool_setup
1328
1329         mkdir -p $DIR/$tdir
1330
1331         local f=$DIR/$tdir/$tfile
1332         local fid=$(copy_file /etc/hosts $f)
1333         $LFS hsm_restore $f || error "restore of non archived file failed"
1334         local cnt=$(get_request_count $fid RESTORE)
1335         [[ "$cnt" == "0" ]] ||
1336                 error "restore non archived must not make a request"
1337         $LFS hsm_archive $f ||
1338                 error "archive request failed"
1339         wait_request_state $fid ARCHIVE SUCCEED
1340         $LFS hsm_restore $f ||
1341                 error "restore of non released file failed"
1342         local cnt=$(get_request_count $fid RESTORE)
1343         [[ "$cnt" == "0" ]] ||
1344                 error "restore a non dirty file must not make a request"
1345
1346         copytool_cleanup
1347 }
1348 run_test 12d "Restore of a non archived, non released file must work"\
1349                 " without doing request"
1350
1351 test_12e() {
1352         # test needs a running copytool
1353         copytool_setup
1354
1355         mkdir -p $DIR/$tdir $HSM_ARCHIVE/$tdir
1356         local f=$DIR/$tdir/$tfile
1357         local fid=$(copy_file /etc/hosts $f)
1358         $LFS hsm_archive $f || error "archive request failed"
1359         wait_request_state $fid ARCHIVE SUCCEED
1360
1361         # make file dirty
1362         cat /etc/hosts >> $f
1363         sync
1364         $LFS hsm_state $f
1365
1366         $LFS hsm_restore $f && error "restore a dirty file must fail"
1367
1368         copytool_cleanup
1369 }
1370 run_test 12e "Check forbidden restore"
1371
1372 test_12f() {
1373         # test needs a running copytool
1374         copytool_setup
1375
1376         mkdir -p $DIR/$tdir
1377         local f=$DIR/$tdir/$tfile
1378         local fid=$(copy_file /etc/hosts $f)
1379
1380         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1381         wait_request_state $fid ARCHIVE SUCCEED
1382         $LFS hsm_release $f || error "release of $f failed"
1383         $LFS hsm_restore $f
1384         wait_request_state $fid RESTORE SUCCEED
1385
1386         echo -n "Verifying file state: "
1387         check_hsm_flags $f "0x00000009"
1388
1389         diff -q /etc/hosts $f
1390
1391         [[ $? -eq 0 ]] || error "Restored file differs"
1392
1393         copytool_cleanup
1394 }
1395 run_test 12f "Restore a released file explicitly"
1396
1397 test_12g() {
1398         # test needs a running copytool
1399         copytool_setup
1400
1401         mkdir -p $DIR/$tdir
1402         local f=$DIR/$tdir/$tfile
1403         local fid=$(copy_file /etc/hosts $f)
1404
1405         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1406         wait_request_state $fid ARCHIVE SUCCEED
1407         $LFS hsm_release $f || error "release of $f failed"
1408
1409         diff -q /etc/hosts $f
1410         local st=$?
1411
1412         # we check we had a restore done
1413         wait_request_state $fid RESTORE SUCCEED
1414
1415         [[ $st -eq 0 ]] || error "Restored file differs"
1416
1417         copytool_cleanup
1418 }
1419 run_test 12g "Restore a released file implicitly"
1420
1421 test_12h() {
1422         needclients 2 || return 0
1423
1424         # test needs a running copytool
1425         copytool_setup
1426
1427         mkdir -p $DIR/$tdir
1428         local f=$DIR/$tdir/$tfile
1429         local fid=$(copy_file /etc/hosts $f)
1430
1431         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1432         wait_request_state $fid ARCHIVE SUCCEED
1433         $LFS hsm_release $f || error "release of $f failed"
1434
1435         do_node $CLIENT2 diff -q /etc/hosts $f
1436         local st=$?
1437
1438         # we check we had a restore done
1439         wait_request_state $fid RESTORE SUCCEED
1440
1441         [[ $st -eq 0 ]] || error "Restored file differs"
1442
1443         copytool_cleanup
1444 }
1445 run_test 12h "Restore a released file implicitly from a second node"
1446
1447 test_12m() {
1448         # test needs a running copytool
1449         copytool_setup
1450
1451         mkdir -p $DIR/$tdir
1452         local f=$DIR/$tdir/$tfile
1453         local fid=$(copy_file /etc/passwd $f)
1454         $LFS hsm_archive $f || error "archive of $f failed"
1455         wait_request_state $fid ARCHIVE SUCCEED
1456
1457         $LFS hsm_release $f || error "release of $f failed"
1458
1459         cmp /etc/passwd $f
1460
1461         [[ $? -eq 0 ]] || error "Restored file differs"
1462
1463         copytool_cleanup
1464 }
1465 run_test 12m "Archive/release/implicit restore"
1466
1467 test_12n() {
1468         # test needs a running copytool
1469         copytool_setup
1470
1471         mkdir -p $DIR/$tdir
1472         copy2archive /etc/hosts $tdir/$tfile
1473
1474         local f=$DIR/$tdir/$tfile
1475         import_file $tdir/$tfile $f
1476
1477         do_facet $SINGLEAGT cmp /etc/hosts $f ||
1478                 error "Restored file differs"
1479
1480         $LFS hsm_release $f || error "release of $f failed"
1481
1482         copytool_cleanup
1483 }
1484 run_test 12n "Import/implicit restore/release"
1485
1486 test_12o() {
1487         # test needs a running copytool
1488         copytool_setup
1489
1490         mkdir -p $DIR/$tdir
1491         local f=$DIR/$tdir/$tfile
1492         local fid=$(copy_file /etc/hosts $f)
1493
1494         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1495         wait_request_state $fid ARCHIVE SUCCEED
1496         $LFS hsm_release $f || error "release of $f failed"
1497
1498 #define OBD_FAIL_MDS_HSM_SWAP_LAYOUTS           0x152
1499         do_facet $SINGLEMDS lctl set_param fail_loc=0x152
1500
1501         # set no retry action mode
1502         cdt_set_no_retry
1503
1504         diff -q /etc/hosts $f
1505         local st=$?
1506
1507         # we check we had a restore failure
1508         wait_request_state $fid RESTORE FAILED
1509
1510         [[ $st -eq 0 ]] && error "Restore must fail"
1511
1512         # remove no retry action mode
1513         cdt_clear_no_retry
1514
1515         # check file is still released
1516         check_hsm_flags $f "0x0000000d"
1517
1518         # retry w/o failure injection
1519         do_facet $SINGLEMDS lctl set_param fail_loc=0
1520
1521         # to be sure previous RESTORE result is gone
1522         cdt_purge
1523         wait_for_grace_delay
1524
1525         diff -q /etc/hosts $f
1526         st=$?
1527
1528         # we check we had a restore done
1529         wait_request_state $fid RESTORE SUCCEED
1530
1531         [[ $st -eq 0 ]] || error "Restored file differs"
1532
1533         copytool_cleanup
1534 }
1535 run_test 12o "Layout-swap failure during Restore leaves file released"
1536
1537 test_12p() {
1538         # test needs a running copytool
1539         copytool_setup
1540
1541         mkdir $DIR/$tdir
1542         local f=$DIR/$tdir/$tfile
1543         local fid=$(copy_file /etc/hosts $f)
1544
1545         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1546         wait_request_state $fid ARCHIVE SUCCEED
1547         do_facet $SINGLEAGT cat $f > /dev/null || error "cannot cat $f"
1548         $LFS hsm_release $f || error "cannot release $f"
1549         do_facet $SINGLEAGT cat $f > /dev/null || error "cannot cat $f"
1550         $LFS hsm_release $f || error "cannot release $f"
1551         do_facet $SINGLEAGT cat $f > /dev/null || error "cannot cat $f"
1552
1553         copytool_cleanup
1554 }
1555 run_test 12p "implicit restore of a file on copytool mount point"
1556
1557 cleanup_test_12q() {
1558         trap 0
1559         zconf_umount $(facet_host $SINGLEAGT) $MOUNT3 ||
1560                 error "cannot umount $MOUNT3 on $SINGLEAGT"
1561 }
1562
1563 test_12q() {
1564         [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.7.58) ] &&
1565                 skip "need MDS version at least 2.7.58" && return 0
1566
1567         zconf_mount $(facet_host $SINGLEAGT) $MOUNT3 ||
1568                 error "cannot mount $MOUNT3 on $SINGLEAGT"
1569
1570         trap cleanup_test_12q EXIT
1571
1572         # test needs a running copytool
1573         copytool_setup $SINGLEAGT $MOUNT3
1574
1575         mkdir $DIR/$tdir
1576         local f=$DIR/$tdir/$tfile
1577         local f2=$DIR2/$tdir/$tfile
1578         local fid=$(make_small $f)
1579         local orig_size=$(stat -c "%s" $f)
1580
1581         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
1582         wait_request_state $fid ARCHIVE SUCCEED
1583
1584         $LFS hsm_release $f || error "could not release file"
1585         check_hsm_flags $f "0x0000000d"
1586
1587         kill_copytools
1588         wait_copytools || error "copytool failed to stop"
1589
1590         cat $f > /dev/null &
1591
1592         # wait a bit to allow implicit restore request to be handled.
1593         # if not, next stat would also block on layout-lock.
1594         sleep 5
1595
1596         local size=$(stat -c "%s" $f2)
1597         [ $size -eq $orig_size ] ||
1598                 error "$f2: wrong size after archive: $size != $orig_size"
1599
1600         HSM_ARCHIVE_PURGE=false copytool_setup $SINGLEAGT /mnt/lustre3
1601
1602         wait
1603
1604         size=$(stat -c "%s" $f)
1605         [ $size -eq $orig_size ] ||
1606                 error "$f: wrong size after restore: $size != $orig_size"
1607
1608         size=$(stat -c "%s" $f2)
1609         [ $size -eq $orig_size ] ||
1610                 error "$f2: wrong size after restore: $size != $orig_size"
1611
1612         :>$f
1613
1614         size=$(stat -c "%s" $f)
1615         [ $size -eq 0 ] ||
1616                 error "$f: wrong size after overwrite: $size != 0"
1617
1618         size=$(stat -c "%s" $f2)
1619         [ $size -eq 0 ] ||
1620                 error "$f2: wrong size after overwrite: $size != 0"
1621
1622         copytool_cleanup
1623         zconf_umount $(facet_host $SINGLEAGT) $MOUNT3 ||
1624                 error "cannot umount $MOUNT3 on $SINGLEAGT"
1625 }
1626 run_test 12q "file attributes are refreshed after restore"
1627
1628 test_13() {
1629         # test needs a running copytool
1630         copytool_setup
1631
1632         local ARC_SUBDIR="import.orig"
1633         local d=""
1634         local f=""
1635
1636         # populate directory to be imported
1637         for d in $(seq 1 10); do
1638                 local CURR_DIR="$HSM_ARCHIVE/$ARC_SUBDIR/dir.$d"
1639                 do_facet $SINGLEAGT mkdir -p "$CURR_DIR"
1640                 for f in $(seq 1 10); do
1641                         CURR_FILE="$CURR_DIR/$tfile.$f"
1642                         # write file-specific data
1643                         do_facet $SINGLEAGT \
1644                                 "echo d=$d, f=$f, dir=$CURR_DIR, "\
1645                                         "file=$CURR_FILE > $CURR_FILE"
1646                 done
1647         done
1648         # import to Lustre
1649         import_file "$ARC_SUBDIR" $DIR/$tdir
1650         # diff lustre content and origin (triggers file restoration)
1651         # there must be 10x10 identical files, and no difference
1652         local cnt_ok=$(do_facet $SINGLEAGT diff -rs $HSM_ARCHIVE/$ARC_SUBDIR \
1653                        $DIR/$tdir/$ARC_SUBDIR | grep identical | wc -l)
1654         local cnt_diff=$(do_facet $SINGLEAGT diff -r $HSM_ARCHIVE/$ARC_SUBDIR \
1655                          $DIR/$tdir/$ARC_SUBDIR | wc -l)
1656
1657         [ $cnt_diff -eq 0 ] ||
1658                 error "$cnt_diff imported files differ from read data"
1659         [ $cnt_ok -eq 100 ] ||
1660                 error "not enough identical files ($cnt_ok != 100)"
1661
1662         copytool_cleanup
1663 }
1664 run_test 13 "Recursively import and restore a directory"
1665
1666 test_14() {
1667         # test needs a running copytool
1668         copytool_setup
1669
1670         # archive a file
1671         mkdir -p $DIR/$tdir
1672         local f=$DIR/$tdir/$tfile
1673         local fid=$(make_small $f)
1674         local sum=$(md5sum $f | awk '{print $1}')
1675         $LFS hsm_archive $f || error "could not archive file"
1676         wait_request_state $fid ARCHIVE SUCCEED
1677
1678         # delete the file
1679         rm -f $f
1680         # create released file (simulate llapi_hsm_import call)
1681         touch $f
1682         local fid2=$(path2fid $f)
1683         $LFS hsm_set --archived --exists $f || error "could not force hsm flags"
1684         $LFS hsm_release $f || error "could not release file"
1685
1686         # rebind the archive to the newly created file
1687         echo "rebind $fid to $fid2"
1688
1689         do_facet $SINGLEAGT \
1690                 "$HSMTOOL --archive $HSM_ARCHIVE_NUMBER --hsm-root $HSM_ARCHIVE\
1691                  --rebind $fid $fid2 $DIR" || error "could not rebind file"
1692
1693         # restore file and compare md5sum
1694         local sum2=$(md5sum $f | awk '{print $1}')
1695
1696         [[ $sum == $sum2 ]] || error "md5sum mismatch after restore"
1697
1698         copytool_cleanup
1699 }
1700 run_test 14 "Rebind archived file to a new fid"
1701
1702 test_15() {
1703         # test needs a running copytool
1704         copytool_setup
1705
1706         # archive files
1707         mkdir -p $DIR/$tdir
1708         local f=$DIR/$tdir/$tfile
1709         local count=5
1710         local tmpfile=$SHARED_DIRECTORY/tmp.$$
1711
1712         local fids=()
1713         local sums=()
1714         for i in $(seq 1 $count); do
1715                 fids[$i]=$(make_small $f.$i)
1716                 sums[$i]=$(md5sum $f.$i | awk '{print $1}')
1717                 $LFS hsm_archive $f.$i || error "could not archive file"
1718         done
1719         wait_all_done $(($count*60))
1720
1721         :>$tmpfile
1722         # delete the files
1723         for i in $(seq 1 $count); do
1724                 rm -f $f.$i
1725                 touch $f.$i
1726                 local fid2=$(path2fid $f.$i)
1727                 # add the rebind operation to the list
1728                 echo ${fids[$i]} $fid2 >> $tmpfile
1729
1730                 # set it released (simulate llapi_hsm_import call)
1731                 $LFS hsm_set --archived --exists $f.$i ||
1732                         error "could not force hsm flags"
1733                 $LFS hsm_release $f.$i || error "could not release file"
1734         done
1735         nl=$(wc -l < $tmpfile)
1736         [[ $nl == $count ]] || error "$nl files in list, $count expected"
1737
1738         echo "rebind list of files"
1739         do_facet $SINGLEAGT \
1740                 "$HSMTOOL --archive $HSM_ARCHIVE_NUMBER --hsm-root $HSM_ARCHIVE\
1741                  --rebind $tmpfile $DIR" || error "could not rebind file list"
1742
1743         # restore files and compare md5sum
1744         for i in $(seq 1 $count); do
1745                 local sum2=$(md5sum $f.$i | awk '{print $1}')
1746                 [[ $sum2 == ${sums[$i]} ]] ||
1747                     error "md5sum mismatch after restore ($sum2 != ${sums[$i]})"
1748         done
1749
1750         rm -f $tmpfile
1751         copytool_cleanup
1752 }
1753 run_test 15 "Rebind a list of files"
1754
1755 test_16() {
1756         # test needs a running copytool
1757         copytool_setup
1758
1759         local ref=/tmp/ref
1760         # create a known size file so we can verify transfer speed
1761         # 20 MB <-> 20s
1762         local goal=20
1763         dd if=/dev/zero of=$ref bs=1M count=20
1764
1765         mkdir -p $DIR/$tdir
1766         local f=$DIR/$tdir/$tfile
1767         local fid=$(copy_file $ref $f)
1768         rm $ref
1769         local start=$(date +%s)
1770         $LFS hsm_archive $f
1771         wait_request_state $fid ARCHIVE SUCCEED
1772         local end=$(date +%s)
1773         # Add 1 to account for rounding errors between start and end (LU-8155)
1774         local duration=$((end - start + 1))
1775
1776         [[ $duration -ge $goal ]] ||
1777                 error "Transfer is too fast $duration < $goal"
1778
1779         copytool_cleanup
1780 }
1781 run_test 16 "Test CT bandwith control option"
1782
1783 test_20() {
1784         mkdir -p $DIR/$tdir
1785
1786         local f=$DIR/$tdir/$tfile
1787         touch $f || error "touch $f failed"
1788
1789         # Could not release a non-archived file
1790         $LFS hsm_release $f && error "release should not succeed"
1791
1792         # For following tests, we must test them with HS_ARCHIVED set
1793         $LFS hsm_set --exists --archived $f || error "could not add flag"
1794
1795         # Could not release a file if no-release is set
1796         $LFS hsm_set --norelease $f || error "could not add flag"
1797         $LFS hsm_release $f && error "release should not succeed"
1798         $LFS hsm_clear --norelease $f || error "could not remove flag"
1799
1800         # Could not release a file if lost
1801         $LFS hsm_set --lost $f || error "could not add flag"
1802         $LFS hsm_release $f && error "release should not succeed"
1803         $LFS hsm_clear --lost $f || error "could not remove flag"
1804
1805         # Could not release a file if dirty
1806         $LFS hsm_set --dirty $f || error "could not add flag"
1807         $LFS hsm_release $f && error "release should not succeed"
1808         $LFS hsm_clear --dirty $f || error "could not remove flag"
1809 }
1810 run_test 20 "Release is not permitted"
1811
1812 test_21() {
1813         # test needs a running copytool
1814         copytool_setup
1815
1816         mkdir -p $DIR/$tdir
1817         local f=$DIR/$tdir/test_release
1818
1819         # Create a file and check its states
1820         local fid=$(make_small $f)
1821         check_hsm_flags $f "0x00000000"
1822
1823         # LU-4388/LU-4389 - ZFS does not report full number of blocks
1824         # used until file is flushed to disk
1825         if [  $(facet_fstype ost1) == "zfs" ]; then
1826             # this causes an OST_SYNC rpc to be sent
1827             dd if=/dev/zero of=$f bs=512 count=1 oflag=sync conv=notrunc,fsync
1828             # clear locks to reread file data
1829             cancel_lru_locks osc
1830         fi
1831
1832         local orig_size=$(stat -c "%s" $f)
1833         local orig_blocks=$(stat -c "%b" $f)
1834
1835         start_full_debug_logging
1836
1837         $LFS hsm_archive $f || error "could not archive file"
1838         wait_request_state $fid ARCHIVE SUCCEED
1839
1840         local blocks=$(stat -c "%b" $f)
1841         [ $blocks -eq $orig_blocks ] ||
1842                 error "$f: wrong block number after archive: " \
1843                       "$blocks != $orig_blocks"
1844         local size=$(stat -c "%s" $f)
1845         [ $size -eq $orig_size ] ||
1846                 error "$f: wrong size after archive: $size != $orig_size"
1847
1848         # Release and check states
1849         $LFS hsm_release $f || error "could not release file"
1850         check_hsm_flags $f "0x0000000d"
1851
1852         blocks=$(stat -c "%b" $f)
1853         [ $blocks -gt 5 ] &&
1854                 error "$f: too many blocks after release: $blocks > 5"
1855         size=$(stat -c "%s" $f)
1856         [ $size -ne $orig_size ] &&
1857                 error "$f: wrong size after release: $size != $orig_size"
1858
1859         # Check we can release an file without stripe info
1860         f=$f.nolov
1861         $MCREATE $f
1862         fid=$(path2fid $f)
1863         check_hsm_flags $f "0x00000000"
1864         $LFS hsm_archive $f || error "could not archive file"
1865         wait_request_state $fid ARCHIVE SUCCEED
1866
1867         # Release and check states
1868         $LFS hsm_release $f || error "could not release file"
1869         check_hsm_flags $f "0x0000000d"
1870
1871         # Release again a file that is already released is OK
1872         $LFS hsm_release $f || fail "second release should succeed"
1873         check_hsm_flags $f "0x0000000d"
1874
1875         stop_full_debug_logging
1876
1877         copytool_cleanup
1878 }
1879 run_test 21 "Simple release tests"
1880
1881 test_22() {
1882         # test needs a running copytool
1883         copytool_setup
1884
1885         mkdir -p $DIR/$tdir
1886
1887         local f=$DIR/$tdir/test_release
1888         local swap=$DIR/$tdir/test_swap
1889
1890         # Create a file and check its states
1891         local fid=$(make_small $f)
1892         check_hsm_flags $f "0x00000000"
1893
1894         $LFS hsm_archive $f || error "could not archive file"
1895         wait_request_state $fid ARCHIVE SUCCEED
1896
1897         # Release and check states
1898         $LFS hsm_release $f || error "could not release file"
1899         check_hsm_flags $f "0x0000000d"
1900
1901         make_small $swap
1902         $LFS swap_layouts $swap $f && error "swap_layouts should failed"
1903
1904         true
1905         copytool_cleanup
1906 }
1907 run_test 22 "Could not swap a release file"
1908
1909 test_23() {
1910         # test needs a running copytool
1911         copytool_setup
1912
1913         mkdir -p $DIR/$tdir
1914
1915         local f=$DIR/$tdir/test_mtime
1916
1917         # Create a file and check its states
1918         local fid=$(make_small $f)
1919         check_hsm_flags $f "0x00000000"
1920
1921         $LFS hsm_archive $f || error "could not archive file"
1922         wait_request_state $fid ARCHIVE SUCCEED
1923
1924         # Set modification time in the past
1925         touch -m -a -d @978261179 $f
1926
1927         # Release and check states
1928         $LFS hsm_release $f || error "could not release file"
1929         check_hsm_flags $f "0x0000000d"
1930
1931         local MTIME=$(stat -c "%Y" $f)
1932         local ATIME=$(stat -c "%X" $f)
1933         [ $MTIME -eq "978261179" ] || fail "bad mtime: $MTIME"
1934         [ $ATIME -eq "978261179" ] || fail "bad atime: $ATIME"
1935
1936         copytool_cleanup
1937 }
1938 run_test 23 "Release does not change a/mtime (utime)"
1939
1940 test_24a() {
1941         local file=$DIR/$tdir/$tfile
1942         local fid
1943         local atime0
1944         local atime1
1945         local mtime0
1946         local mtime1
1947         local ctime0
1948         local ctime1
1949
1950         # test needs a running copytool
1951         copytool_setup
1952
1953         mkdir -p $DIR/$tdir
1954         rm -f $file
1955         fid=$(make_small $file)
1956
1957         # Create a file and check its states
1958         check_hsm_flags $file "0x00000000"
1959
1960         # Ensure atime is less than mtime and ctime.
1961         sleep 1
1962         echo >> $file
1963
1964         atime0=$(stat -c "%X" $file)
1965         mtime0=$(stat -c "%Y" $file)
1966         ctime0=$(stat -c "%Z" $file)
1967
1968         [ $atime0 -lt $mtime0 ] ||
1969                 error "atime $atime0 is not less than mtime $mtime0"
1970
1971         [ $atime0 -lt $ctime0 ] ||
1972                 error "atime $atime0 is not less than ctime $ctime0"
1973
1974         # Archive should not change any timestamps.
1975         $LFS hsm_archive $file || error "cannot archive '$file'"
1976         wait_request_state $fid ARCHIVE SUCCEED
1977
1978         atime1=$(stat -c "%X" $file)
1979         mtime1=$(stat -c "%Y" $file)
1980         ctime1=$(stat -c "%Z" $file)
1981
1982         [ $atime0 -eq $atime1 ] ||
1983                 error "archive changed atime from $atime0 to $atime1"
1984
1985         [ $mtime0 -eq $mtime1 ] ||
1986                 error "archive changed mtime from $mtime0 to $mtime1"
1987
1988         [ $ctime0 -eq $ctime1 ] ||
1989                 error "archive changed ctime from $ctime0 to $ctime1"
1990
1991         # Release should not change any timestamps.
1992         $LFS hsm_release $file || error "cannot release '$file'"
1993         check_hsm_flags $file "0x0000000d"
1994
1995         atime1=$(stat -c "%X" $file)
1996         mtime1=$(stat -c "%Y" $file)
1997         ctime1=$(stat -c "%Z" $file)
1998
1999         [ $atime0 -eq $atime1 ] ||
2000                 error "release changed atime from $atime0 to $atime1"
2001
2002         [ $mtime0 -eq $mtime1 ] ||
2003                 error "release changed mtime from $mtime0 to $mtime1"
2004
2005         [ $ctime0 -eq $ctime1 ] ||
2006                 error "release changed ctime from $ctime0 to $ctime1"
2007
2008         # Restore should not change any timestamps.
2009         $LFS hsm_restore $file
2010         wait_request_state $fid RESTORE SUCCEED
2011
2012         atime1=$(stat -c "%X" $file)
2013         mtime1=$(stat -c "%Y" $file)
2014         ctime1=$(stat -c "%Z" $file)
2015
2016         [ $atime0 -eq $atime1 ] ||
2017                 error "restore changed atime from $atime0 to $atime1"
2018
2019         [ $mtime0 -eq $mtime1 ] ||
2020                 error "restore changed mtime from $mtime0 to $mtime1"
2021
2022         [ $ctime0 -eq $ctime1 ] ||
2023                 error "restore changed ctime from $ctime0 to $ctime1"
2024
2025         copytool_cleanup
2026
2027         # Once more, after unmount and mount.
2028         umount_client $MOUNT || error "cannot unmount '$MOUNT'"
2029         mount_client $MOUNT || error "cannot mount '$MOUNT'"
2030
2031         atime1=$(stat -c "%X" $file)
2032         mtime1=$(stat -c "%Y" $file)
2033         ctime1=$(stat -c "%Z" $file)
2034
2035         [ $atime0 -eq $atime1 ] ||
2036                 error "remount changed atime from $atime0 to $atime1"
2037
2038         [ $mtime0 -eq $mtime1 ] ||
2039                 error "remount changed mtime from $mtime0 to $mtime1"
2040
2041         [ $ctime0 -eq $ctime1 ] ||
2042                 error "remount changed ctime from $ctime0 to $ctime1"
2043 }
2044 run_test 24a "Archive, release, and restore does not change a/mtime (i/o)"
2045
2046 test_24b() {
2047         local file=$DIR/$tdir/$tfile
2048         local fid
2049         local sum0
2050         local sum1
2051         # LU-3811
2052
2053         # Test needs a running copytool.
2054         copytool_setup
2055         mkdir -p $DIR/$tdir
2056
2057         # Check that root can do HSM actions on a regular user's file.
2058         rm -f $file
2059         fid=$(make_small $file)
2060         sum0=$(md5sum $file)
2061
2062         chown $RUNAS_ID:$RUNAS_GID $file ||
2063                 error "cannot chown '$file' to '$RUNAS_ID'"
2064
2065         chmod ugo-w $DIR/$tdir ||
2066                 error "cannot chmod '$DIR/$tdir'"
2067
2068         $LFS hsm_archive $file
2069         wait_request_state $fid ARCHIVE SUCCEED
2070
2071         $LFS hsm_release $file
2072         check_hsm_flags $file "0x0000000d"
2073
2074         $LFS hsm_restore $file
2075         wait_request_state $fid RESTORE SUCCEED
2076
2077         # Check that ordinary user can get HSM state.
2078         $RUNAS $LFS hsm_state $file ||
2079                 error "user '$RUNAS_ID' cannot get HSM state of '$file'"
2080
2081         $LFS hsm_release $file
2082         check_hsm_flags $file "0x0000000d"
2083
2084         # Check that ordinary user can accessed released file.
2085         sum1=$($RUNAS md5sum $file) ||
2086                 error "user '$RUNAS_ID' cannot read '$file'"
2087
2088         [ "$sum0" == "$sum1" ] ||
2089                 error "md5sum mismatch for '$file'"
2090
2091         copytool_cleanup
2092 }
2093 run_test 24b "root can archive, release, and restore user files"
2094
2095 cleanup_test_24c() {
2096         trap 0
2097         set_hsm_param user_request_mask RESTORE
2098         set_hsm_param group_request_mask RESTORE
2099         set_hsm_param other_request_mask RESTORE
2100 }
2101
2102 test_24c() {
2103         local file=$DIR/$tdir/$tfile
2104         local action=archive
2105         local user_save
2106         local group_save
2107         local other_save
2108
2109         # test needs a running copytool
2110         copytool_setup
2111
2112         mkdir -p $DIR/$tdir
2113
2114         # Save the default masks and check that cleanup_24c will
2115         # restore the request masks correctly.
2116         user_save=$(get_hsm_param user_request_mask)
2117         group_save=$(get_hsm_param group_request_mask)
2118         other_save=$(get_hsm_param other_request_mask)
2119
2120         [ "$user_save" == RESTORE ] ||
2121                 error "user_request_mask is '$user_save' expected 'RESTORE'"
2122         [ "$group_save" == RESTORE ] ||
2123                 error "group_request_mask is '$group_save' expected 'RESTORE'"
2124         [ "$other_save" == RESTORE ] ||
2125                 error "other_request_mask is '$other_save' expected 'RESTORE'"
2126
2127         trap cleanup_test_24c EXIT
2128
2129         # User.
2130         rm -f $file
2131         make_small $file
2132         chown $RUNAS_ID:nobody $file ||
2133                 error "cannot chown '$file' to '$RUNAS_ID:nobody'"
2134
2135         $RUNAS $LFS hsm_$action $file &&
2136                 error "$action by user should fail"
2137
2138         set_hsm_param user_request_mask $action
2139         $RUNAS $LFS hsm_$action $file ||
2140                 error "$action by user should succeed"
2141
2142         # Group.
2143         rm -f $file
2144         make_small $file
2145         chown nobody:$RUNAS_GID $file ||
2146                 error "cannot chown '$file' to 'nobody:$RUNAS_GID'"
2147
2148         $RUNAS $LFS hsm_$action $file &&
2149                 error "$action by group should fail"
2150
2151         set_hsm_param group_request_mask $action
2152         $RUNAS $LFS hsm_$action $file ||
2153                 error "$action by group should succeed"
2154
2155         # Other.
2156         rm -f $file
2157         make_small $file
2158         chown nobody:nobody $file ||
2159                 error "cannot chown '$file' to 'nobody:nobody'"
2160
2161         $RUNAS $LFS hsm_$action $file &&
2162                 error "$action by other should fail"
2163
2164         set_hsm_param other_request_mask $action
2165         $RUNAS $LFS hsm_$action $file ||
2166                 error "$action by other should succeed"
2167
2168         copytool_cleanup
2169         cleanup_test_24c
2170 }
2171 run_test 24c "check that user,group,other request masks work"
2172
2173 cleanup_test_24d() {
2174         trap 0
2175         mount -o remount,rw $MOUNT2
2176 }
2177
2178 test_24d() {
2179         local file1=$DIR/$tdir/$tfile
2180         local file2=$DIR2/$tdir/$tfile
2181         local fid1
2182         local fid2
2183
2184         copytool_setup
2185
2186         mkdir -p $DIR/$tdir
2187         rm -f $file1
2188         fid1=$(make_small $file1)
2189
2190         trap cleanup_test_24d EXIT
2191
2192         mount -o remount,ro $MOUNT2
2193
2194         fid2=$(path2fid $file2)
2195         [ "$fid1" == "$fid2" ] ||
2196                 error "FID mismatch '$fid1' != '$fid2'"
2197
2198         $LFS hsm_archive $file2 &&
2199                 error "archive should fail on read-only mount"
2200         check_hsm_flags $file1 "0x00000000"
2201
2202         $LFS hsm_archive $file1
2203         wait_request_state $fid1 ARCHIVE SUCCEED
2204
2205         $LFS hsm_release $file1
2206         $LFS hsm_restore $file2
2207         wait_request_state $fid1 RESTORE SUCCEED
2208
2209         $LFS hsm_release $file1 || error "cannot release '$file1'"
2210         dd if=$file2 of=/dev/null bs=1M || "cannot read '$file2'"
2211
2212         $LFS hsm_release $file2 &&
2213                 error "release should fail on read-only mount"
2214
2215         copytool_cleanup
2216         cleanup_test_24d
2217 }
2218 run_test 24d "check that read-only mounts are respected"
2219
2220 test_24e() {
2221         copytool_setup
2222
2223         mkdir -p $DIR/$tdir
2224
2225         local f=$DIR/$tdir/$tfile
2226         local fid
2227
2228         fid=$(make_small $f) || error "cannot create $f"
2229         $LFS hsm_archive $f || error "cannot archive $f"
2230         wait_request_state $fid ARCHIVE SUCCEED
2231         $LFS hsm_release $f || error "cannot release $f"
2232         while ! $LFS hsm_state $f | grep released; do
2233                 sleep 1
2234         done
2235
2236         tar -cf $TMP/$tfile.tar $DIR/$tdir || error "cannot tar $DIR/$tdir"
2237
2238         copytool_cleanup
2239 }
2240 run_test 24e "tar succeeds on HSM released files" # LU-6213
2241
2242 test_24f() {
2243
2244         # test needs a running copytool
2245         copytool_setup
2246
2247         mkdir -p $DIR/$tdir/d1
2248         local f=$DIR/$tdir/$tfile
2249         local fid=$(copy_file /etc/hosts $f)
2250         sum0=$(md5sum $f)
2251         echo $sum0
2252         $LFS hsm_archive -a $HSM_ARCHIVE_NUMBER $f ||
2253                 error "hsm_archive failed"
2254         wait_request_state $fid ARCHIVE SUCCEED
2255         $LFS hsm_release $f || error "cannot release $f"
2256         tar --xattrs -cvf $f.tar -C $DIR/$tdir $tfile
2257         rm -f $f
2258         sync
2259         tar --xattrs -xvf $f.tar -C $DIR/$tdir ||
2260                 error "Can not recover the tar contents"
2261         sum1=$(md5sum $f)
2262         echo "Sum0 = $sum0, sum1 = $sum1"
2263         [ "$sum0" == "$sum1" ] || error "md5sum mismatch for '$tfile'"
2264
2265         copytool_cleanup
2266 }
2267 run_test 24f "root can archive, release, and restore tar files"
2268
2269 test_25a() {
2270         # test needs a running copytool
2271         copytool_setup
2272
2273         mkdir -p $DIR/$tdir
2274         copy2archive /etc/hosts $tdir/$tfile
2275
2276         local f=$DIR/$tdir/$tfile
2277
2278         import_file $tdir/$tfile $f
2279
2280         $LFS hsm_set --lost $f
2281
2282         md5sum $f
2283         local st=$?
2284
2285         [[ $st == 1 ]] || error "lost file access should failed (returns $st)"
2286
2287         copytool_cleanup
2288 }
2289 run_test 25a "Restore lost file (HS_LOST flag) from import"\
2290              " (Operation not permitted)"
2291
2292 test_25b() {
2293         # test needs a running copytool
2294         copytool_setup
2295
2296         mkdir -p $DIR/$tdir
2297
2298         local f=$DIR/$tdir/$tfile
2299         local fid=$(copy_file /etc/passwd $f)
2300
2301         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2302         wait_request_state $fid ARCHIVE SUCCEED
2303
2304         $LFS hsm_release $f
2305         $LFS hsm_set --lost $f
2306         md5sum $f
2307         st=$?
2308
2309         [[ $st == 1 ]] || error "lost file access should failed (returns $st)"
2310
2311         copytool_cleanup
2312 }
2313 run_test 25b "Restore lost file (HS_LOST flag) after release"\
2314              " (Operation not permitted)"
2315
2316 test_26() {
2317         # test needs a running copytool
2318         copytool_setup
2319
2320         mkdir -p $DIR/$tdir
2321         local f=$DIR/$tdir/$tfile
2322         local fid
2323         fid=$(make_large_for_progress $f)
2324         [ $? != 0 ] && skip "not enough free space" && return
2325
2326         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2327         wait_request_state $fid ARCHIVE SUCCEED
2328
2329         $LFS hsm_remove $f
2330         wait_request_state $fid REMOVE SUCCEED
2331
2332         check_hsm_flags $f "0x00000000"
2333
2334         copytool_cleanup
2335 }
2336 run_test 26 "Remove the archive of a valid file"
2337
2338 test_27a() {
2339         # test needs a running copytool
2340         copytool_setup
2341
2342         mkdir -p $DIR/$tdir
2343         make_archive $tdir/$tfile
2344         local f=$DIR/$tdir/$tfile
2345         import_file $tdir/$tfile $f
2346         local fid=$(path2fid $f)
2347
2348         $LFS hsm_remove $f
2349
2350         [[ $? != 0 ]] || error "Remove of a released file should fail"
2351
2352         copytool_cleanup
2353 }
2354 run_test 27a "Remove the archive of an imported file (Operation not permitted)"
2355
2356 test_27b() {
2357         # test needs a running copytool
2358         copytool_setup
2359
2360         mkdir -p $DIR/$tdir
2361         local f=$DIR/$tdir/$tfile
2362         local fid
2363         fid=$(make_large_for_progress $f)
2364         [ $? != 0 ] && skip "not enough free space" && return
2365
2366         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2367         wait_request_state $fid ARCHIVE SUCCEED
2368         $LFS hsm_release $f
2369
2370         $LFS hsm_remove $f
2371
2372         [[ $? != 0 ]] || error "Remove of a released file should fail"
2373
2374         copytool_cleanup
2375 }
2376 run_test 27b "Remove the archive of a relased file (Operation not permitted)"
2377
2378 test_28() {
2379         # test needs a running copytool
2380         copytool_setup
2381
2382         mkdir -p $DIR/$tdir
2383         local f=$DIR/$tdir/$tfile
2384         local fid
2385         fid=$(make_large_for_progress $f)
2386         [ $? != 0 ] && skip "not enough free space" && return
2387
2388         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2389         wait_request_state $fid ARCHIVE SUCCEED
2390
2391         cdt_disable
2392         $LFS hsm_remove $f
2393
2394         rm -f $f
2395
2396         cdt_enable
2397
2398         wait_request_state $fid REMOVE SUCCEED
2399
2400         copytool_cleanup
2401 }
2402 run_test 28 "Concurrent archive/file remove"
2403
2404 test_29a() {
2405         # Tests --mntpath and --archive options
2406
2407         local archive_id=7
2408         copytool_setup $SINGLEAGT $MOUNT $archive_id
2409
2410         # Bad archive number
2411         $LFS hsm_remove -m $MOUNT -a 33 0x857765760:0x8:0x2 2>&1 |
2412                 grep "Invalid argument" ||
2413                 error "unexpected hsm_remove failure (1)"
2414
2415         # mntpath is present but file is given
2416         $LFS hsm_remove --mntpath $MOUNT --archive 30 /qwerty/uyt 2>&1 |
2417                 grep "hsm: '/qwerty/uyt' is not a valid FID" ||
2418                 error "unexpected hsm_remove failure (2)"
2419
2420         copytool_cleanup
2421 }
2422 run_test 29a "Tests --mntpath and --archive options"
2423
2424 test_29b() {
2425         # test needs a running copytool
2426         copytool_setup
2427
2428         mkdir -p $DIR/$tdir
2429         local f=$DIR/$tdir/$tfile
2430         local fid=$(make_small $f)
2431
2432         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2433         wait_request_state $fid ARCHIVE SUCCEED
2434
2435         rm -f $f
2436
2437         $LFS hsm_remove -m $MOUNT -a $HSM_ARCHIVE_NUMBER $fid
2438         wait_request_state $fid REMOVE SUCCEED
2439
2440         copytool_cleanup
2441 }
2442 run_test 29b "Archive/delete/remove by FID from the archive."
2443
2444 test_29c() {
2445         # test needs a running copytool
2446         copytool_setup
2447
2448         mkdir -p $DIR/$tdir
2449         local fid1=$(make_small $DIR/$tdir/$tfile-1)
2450         local fid2=$(make_small $DIR/$tdir/$tfile-2)
2451         local fid3=$(make_small $DIR/$tdir/$tfile-3)
2452
2453         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $DIR/$tdir/$tfile-[1-3]
2454         wait_request_state $fid1 ARCHIVE SUCCEED
2455         wait_request_state $fid2 ARCHIVE SUCCEED
2456         wait_request_state $fid3 ARCHIVE SUCCEED
2457
2458         rm -f $DIR/$tdir/$tfile-[1-3]
2459
2460         echo $fid1 > $DIR/$tdir/list
2461         echo $fid2 >> $DIR/$tdir/list
2462         echo $fid3 >> $DIR/$tdir/list
2463
2464         $LFS hsm_remove -m $MOUNT -a $HSM_ARCHIVE_NUMBER \
2465                 --filelist $DIR/$tdir/list
2466         wait_request_state $fid1 REMOVE SUCCEED
2467         wait_request_state $fid2 REMOVE SUCCEED
2468         wait_request_state $fid3 REMOVE SUCCEED
2469
2470         copytool_cleanup
2471 }
2472 run_test 29c "Archive/delete/remove by FID, using a file list."
2473
2474 test_30a() {
2475         # restore at exec cannot work on agent node (because of Linux kernel
2476         # protection of executables)
2477         needclients 2 || return 0
2478
2479         # test needs a running copytool
2480         copytool_setup
2481
2482         mkdir -p $DIR/$tdir
2483         copy2archive /bin/true $tdir/$tfile
2484
2485         local f=$DIR/$tdir/true
2486         import_file $tdir/$tfile $f
2487
2488         local fid=$(path2fid $f)
2489
2490         # set no retry action mode
2491         cdt_set_no_retry
2492         do_node $CLIENT2 $f
2493         local st=$?
2494
2495         # cleanup
2496         # remove no try action mode
2497         cdt_clear_no_retry
2498         $LFS hsm_state $f
2499
2500         [[ $st == 0 ]] || error "Failed to exec a released file"
2501
2502         copytool_cleanup
2503 }
2504 run_test 30a "Restore at exec (import case)"
2505
2506 test_30b() {
2507         # restore at exec cannot work on agent node (because of Linux kernel
2508         # protection of executables)
2509         needclients 2 || return 0
2510
2511         # test needs a running copytool
2512         copytool_setup
2513
2514         mkdir -p $DIR/$tdir
2515         local f=$DIR/$tdir/true
2516         local fid=$(copy_file /bin/true $f)
2517         chmod 755 $f
2518         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2519         wait_request_state $fid ARCHIVE SUCCEED
2520         $LFS hsm_release $f
2521         $LFS hsm_state $f
2522         # set no retry action mode
2523         cdt_set_no_retry
2524         do_node $CLIENT2 $f
2525         local st=$?
2526
2527         # cleanup
2528         # remove no try action mode
2529         cdt_clear_no_retry
2530         $LFS hsm_state $f
2531
2532         [[ $st == 0 ]] || error "Failed to exec a released file"
2533
2534         copytool_cleanup
2535 }
2536 run_test 30b "Restore at exec (release case)"
2537
2538 test_30c() {
2539         needclients 2 || return 0
2540
2541         # test needs a running copytool
2542         copytool_setup
2543
2544         mkdir -p $DIR/$tdir
2545         local f=$DIR/$tdir/SLEEP
2546         local slp_sum1=$(md5sum /bin/sleep)
2547         local fid=$(copy_file /bin/sleep $f)
2548         chmod 755 $f
2549         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2550         wait_request_state $fid ARCHIVE SUCCEED
2551         $LFS hsm_release $f
2552         check_hsm_flags $f "0x0000000d"
2553         # set no retry action mode
2554         cdt_set_no_retry
2555         do_node $CLIENT2 "$f 10" &
2556         local pid=$!
2557         sleep 3
2558         echo 'Hi!' > $f
2559         [[ $? == 0 ]] && error "Update during exec of released file must fail"
2560         wait $pid
2561         [[ $? == 0 ]] || error "Execution failed during run"
2562         cmp /bin/sleep $f
2563         if [[ $? != 0 ]]; then
2564                 local slp_sum2=$(md5sum /bin/sleep)
2565                 # in case sleep file is modified during the test
2566                 [[ $slp_sum1 == $slp_sum2 ]] &&
2567                         error "Binary overwritten during exec"
2568         fi
2569
2570         # cleanup
2571         # remove no try action mode
2572         cdt_clear_no_retry
2573         check_hsm_flags $f "0x00000009"
2574
2575         copytool_cleanup
2576 }
2577 run_test 30c "Update during exec of released file must fail"
2578
2579 restore_and_check_size() {
2580         local f=$1
2581         local fid=$2
2582         local s=$(stat -c "%s" $f)
2583         local n=$s
2584         local st=$(get_hsm_flags $f)
2585         local err=0
2586         local cpt=0
2587         $LFS hsm_restore $f
2588         while [[ "$st" != "0x00000009" && $cpt -le 10 ]]
2589         do
2590                 n=$(stat -c "%s" $f)
2591                 # we echo in both cases to show stat is not
2592                 # hang
2593                 if [[ $n != $s ]]; then
2594                         echo "size seen is $n != $s"
2595                         err=1
2596                 else
2597                         echo "size seen is right: $n == $s"
2598                 fi
2599                 st=$(get_hsm_flags $f)
2600                 sleep 10
2601                 cpt=$((cpt + 1))
2602         done
2603         if [[ $cpt -lt 10 ]]; then
2604                 echo " "done
2605         else
2606                 echo " restore is too long"
2607                 wait_request_state $fid RESTORE SUCCEED
2608         fi
2609         return $err
2610 }
2611
2612 test_31a() {
2613         # test needs a running copytool
2614         copytool_setup
2615
2616         mkdir -p $DIR/$tdir
2617
2618         make_archive $tdir/$tfile
2619         local f=$DIR/$tdir/$tfile
2620         import_file $tdir/$tfile $f
2621         local fid=$($LFS path2fid $f)
2622         HSM_ARCHIVE_PURGE=false copytool_setup
2623
2624         restore_and_check_size $f $fid
2625         local err=$?
2626
2627         [[ $err -eq 0 ]] || error "File size changed during restore"
2628
2629         copytool_cleanup
2630 }
2631 run_test 31a "Import a large file and check size during restore"
2632
2633
2634 test_31b() {
2635         # test needs a running copytool
2636         copytool_setup
2637
2638         mkdir -p $DIR/$tdir
2639
2640         local f=$DIR/$tdir/$tfile
2641         local fid
2642         fid=$(make_large_for_progress $f)
2643         [ $? != 0 ] && skip "not enough free space" && return
2644
2645         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2646         wait_request_state $fid ARCHIVE SUCCEED
2647         $LFS hsm_release $f
2648
2649         restore_and_check_size $f $fid
2650         local err=$?
2651
2652         [[ $err -eq 0 ]] || error "File size changed during restore"
2653
2654         copytool_cleanup
2655 }
2656 run_test 31b "Restore a large unaligned file and check size during restore"
2657
2658 test_31c() {
2659         # test needs a running copytool
2660         copytool_setup
2661
2662         mkdir -p $DIR/$tdir
2663
2664         local f=$DIR/$tdir/$tfile
2665         local fid
2666         fid=$(make_large_for_progress_aligned $f)
2667         [ $? != 0 ] && skip "not enough free space" && return
2668
2669         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2670         wait_request_state $fid ARCHIVE SUCCEED
2671         $LFS hsm_release $f
2672
2673         restore_and_check_size $f $fid
2674         local err=$?
2675
2676         [[ $err -eq 0 ]] || error "File size changed during restore"
2677
2678         copytool_cleanup
2679 }
2680 run_test 31c "Restore a large aligned file and check size during restore"
2681
2682 test_33() {
2683         # test needs a running copytool
2684         copytool_setup
2685
2686         mkdir -p $DIR/$tdir
2687
2688         local f=$DIR/$tdir/$tfile
2689         local fid
2690         fid=$(make_large_for_progress $f)
2691         [ $? != 0 ] && skip "not enough free space" && return
2692
2693         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2694         wait_request_state $fid ARCHIVE SUCCEED
2695         $LFS hsm_release $f
2696
2697         # to be sure wait_all_done will not be mislead by previous tests
2698         # and ops.
2699         cdt_purge
2700         wait_for_grace_delay
2701         # Also raise grace_delay significantly so the Canceled
2702         # Restore action will stay enough long avail.
2703         local old_grace=$(get_hsm_param grace_delay)
2704         set_hsm_param grace_delay 100
2705
2706         md5sum $f >/dev/null &
2707         local pid=$!
2708         wait_request_state $fid RESTORE STARTED
2709
2710         kill -15 $pid
2711         sleep 1
2712
2713         # Check restore trigger process was killed
2714         local killed=$(ps -o pid,comm hp $pid >/dev/null)
2715
2716         $LFS hsm_cancel $f
2717
2718         # instead of waiting+checking both Restore and Cancel ops
2719         # sequentially, wait for both to be finished and then check
2720         # each results.
2721         wait_all_done 100 $fid
2722         local rstate=$(get_request_state $fid RESTORE)
2723         local cstate=$(get_request_state $fid CANCEL)
2724
2725         # restore orig grace_delay.
2726         set_hsm_param grace_delay $old_grace
2727
2728         if [[ "$rstate" == "CANCELED" ]] ; then
2729                 [[ "$cstate" == "SUCCEED" ]] ||
2730                         error "Restore state is CANCELED and Cancel state " \
2731                                "is not SUCCEED but $cstate"
2732                 echo "Restore state is CANCELED, Cancel state is SUCCEED"
2733         elif [[ "$rstate" == "SUCCEED" ]] ; then
2734                 [[ "$cstate" == "FAILED" ]] ||
2735                         error "Restore state is SUCCEED and Cancel state " \
2736                                 "is not FAILED but $cstate"
2737                 echo "Restore state is SUCCEED, Cancel state is FAILED"
2738         else
2739                 error "Restore state is $rstate and Cancel state is $cstate"
2740         fi
2741
2742         [ -z $killed ] ||
2743                 error "Cannot kill process waiting for restore ($killed)"
2744
2745         copytool_cleanup
2746 }
2747 run_test 33 "Kill a restore waiting process"
2748
2749 test_34() {
2750         # test needs a running copytool
2751         copytool_setup
2752
2753         mkdir -p $DIR/$tdir
2754
2755         local f=$DIR/$tdir/$tfile
2756         local fid
2757         fid=$(make_large_for_progress $f)
2758         [ $? != 0 ] && skip "not enough free space" && return
2759
2760         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2761         wait_request_state $fid ARCHIVE SUCCEED
2762         $LFS hsm_release $f
2763
2764         md5sum $f >/dev/null &
2765         local pid=$!
2766         wait_request_state $fid RESTORE STARTED
2767
2768         rm $f || error "rm $f failed"
2769         # rm must not block during restore
2770         wait_request_state $fid RESTORE STARTED
2771
2772         wait_request_state $fid RESTORE SUCCEED
2773         # check md5sum pgm finished
2774         local there=$(ps -o pid,comm hp $pid >/dev/null)
2775         [[ -z $there ]] || error "Restore initiator does not exit"
2776
2777         local rc=$(wait $pid)
2778         [[ $rc -eq 0 ]] || error "Restore initiator failed with $rc"
2779
2780         copytool_cleanup
2781 }
2782 run_test 34 "Remove file during restore"
2783
2784 test_35() {
2785         # test needs a running copytool
2786         copytool_setup
2787
2788         mkdir -p $DIR/$tdir
2789
2790         local f=$DIR/$tdir/$tfile
2791         local f1=$DIR/$tdir/$tfile-1
2792         local fid
2793         fid=$(make_large_for_progress $f)
2794         [ $? != 0 ] && skip "not enough free space" && return
2795
2796         local fid1=$(copy_file /etc/passwd $f1)
2797         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2798         wait_request_state $fid ARCHIVE SUCCEED
2799         $LFS hsm_release $f
2800
2801         md5sum $f >/dev/null &
2802         local pid=$!
2803         wait_request_state $fid RESTORE STARTED
2804
2805         mv $f1 $f || error "mv $f1 $f failed"
2806         # mv must not block during restore
2807         wait_request_state $fid RESTORE STARTED
2808
2809         wait_request_state $fid RESTORE SUCCEED
2810         # check md5sum pgm finished
2811         local there=$(ps -o pid,comm hp $pid >/dev/null)
2812         [[ -z $there ]] || error "Restore initiator does not exit"
2813
2814         local rc=$(wait $pid)
2815         [[ $rc -eq 0 ]] || error "Restore initiator failed with $rc"
2816
2817         fid2=$(path2fid $f)
2818         [[ $fid2 == $fid1 ]] || error "Wrong fid after mv $fid2 != $fid1"
2819
2820         copytool_cleanup
2821 }
2822 run_test 35 "Overwrite file during restore"
2823
2824 test_36() {
2825         # test needs a running copytool
2826         copytool_setup
2827
2828         mkdir -p $DIR/$tdir
2829
2830         local f=$DIR/$tdir/$tfile
2831         local fid
2832         fid=$(make_large_for_progress $f)
2833         [ $? != 0 ] && skip "not enough free space" && return
2834
2835         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2836         wait_request_state $fid ARCHIVE SUCCEED
2837         $LFS hsm_release $f
2838
2839         md5sum $f >/dev/null &
2840         local pid=$!
2841         wait_request_state $fid RESTORE STARTED
2842
2843         mv $f $f.new
2844         # rm must not block during restore
2845         wait_request_state $fid RESTORE STARTED
2846
2847         wait_request_state $fid RESTORE SUCCEED
2848         # check md5sum pgm finished
2849         local there=$(ps -o pid,comm hp $pid >/dev/null)
2850         [[ -z $there ]] ||
2851                 error "Restore initiator does not exit"
2852
2853         local rc=$(wait $pid)
2854         [[ $rc -eq 0 ]] ||
2855                 error "Restore initiator failed with $rc"
2856
2857         copytool_cleanup
2858 }
2859 run_test 36 "Move file during restore"
2860
2861 test_37() {
2862         # LU-5683: check that an archived dirty file can be rearchived.
2863         copytool_cleanup
2864         copytool_setup $SINGLEAGT $MOUNT2
2865
2866         mkdir -p $DIR/$tdir
2867         local f=$DIR/$tdir/$tfile
2868         local fid
2869
2870         fid=$(make_small $f) || error "cannot create small file"
2871
2872         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2873         wait_request_state $fid ARCHIVE SUCCEED
2874         $LFS hsm_release $f || error "cannot release $f"
2875
2876         # Dirty file.
2877         dd if=/dev/urandom of=$f bs=1M count=1 || error "cannot dirty file"
2878
2879         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
2880         wait_request_state $fid ARCHIVE SUCCEED
2881
2882         copytool_cleanup
2883 }
2884 run_test 37 "re-archive a dirty file"
2885
2886 multi_archive() {
2887         local prefix=$1
2888         local count=$2
2889         local n=""
2890
2891         for n in $(seq 1 $count); do
2892                 $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $prefix.$n
2893         done
2894         echo "$count archive requests submitted"
2895 }
2896
2897 test_40() {
2898         local stream_count=4
2899         local file_count=100
2900         mkdir -p $DIR/$tdir
2901         local f=$DIR/$tdir/$tfile
2902         local i=""
2903         local p=""
2904         local fid=""
2905
2906         for i in $(seq 1 $file_count); do
2907                 for p in $(seq 1 $stream_count); do
2908                         fid=$(copy_file /etc/hosts $f.$p.$i)
2909                 done
2910         done
2911         # force copytool to use a local/temp archive dir to ensure best
2912         # performance vs remote/NFS mounts used in auto-tests
2913         if do_facet $SINGLEAGT "df --local $HSM_ARCHIVE" >/dev/null 2>&1 ; then
2914                 copytool_setup
2915         else
2916                 copytool_setup $SINGLEAGT $MOUNT $HSM_ARCHIVE_NUMBER $TMP/$tdir
2917         fi
2918         # to be sure wait_all_done will not be mislead by previous tests
2919         cdt_purge
2920         wait_for_grace_delay
2921         typeset -a pids
2922         # start archive streams in background (archive files in parallel)
2923         for p in $(seq 1 $stream_count); do
2924                 multi_archive $f.$p $file_count &
2925                 pids[$p]=$!
2926         done
2927         echo -n  "Wait for all requests being enqueued..."
2928         wait ${pids[*]}
2929         echo OK
2930         wait_all_done 100
2931         copytool_cleanup
2932 }
2933 run_test 40 "Parallel archive requests"
2934
2935 test_52() {
2936         # test needs a running copytool
2937         copytool_setup
2938
2939         mkdir -p $DIR/$tdir
2940         local f=$DIR/$tdir/$tfile
2941         local fid=$(copy_file /etc/motd $f 1)
2942
2943         $LFS hsm_archive $f || error "could not archive file"
2944         wait_request_state $fid ARCHIVE SUCCEED
2945         check_hsm_flags $f "0x00000009"
2946
2947         multiop_bg_pause $f O_c || error "multiop failed"
2948         local MULTIPID=$!
2949
2950         mds_evict_client
2951         client_up || client_up || true
2952
2953         kill -USR1 $MULTIPID
2954         wait $MULTIPID || error "multiop close failed"
2955
2956         check_hsm_flags $f "0x0000000b"
2957
2958         copytool_cleanup
2959 }
2960 run_test 52 "Opened for write file on an evicted client should be set dirty"
2961
2962 test_53() {
2963         # test needs a running copytool
2964         copytool_setup
2965
2966         mkdir -p $DIR/$tdir
2967         local f=$DIR/$tdir/$tfile
2968         local fid=$(copy_file /etc/motd $f 1)
2969
2970         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
2971                 error "could not archive file"
2972         wait_request_state $fid ARCHIVE SUCCEED
2973         check_hsm_flags $f "0x00000009"
2974
2975         multiop_bg_pause $f o_c || error "multiop failed"
2976         MULTIPID=$!
2977
2978         mds_evict_client
2979         client_up || client_up || true
2980
2981         kill -USR1 $MULTIPID
2982         wait $MULTIPID || error "multiop close failed"
2983
2984         check_hsm_flags $f "0x00000009"
2985
2986         copytool_cleanup
2987 }
2988 run_test 53 "Opened for read file on an evicted client should not be set dirty"
2989
2990 test_54() {
2991         # test needs a running copytool
2992         copytool_setup
2993
2994         mkdir -p $DIR/$tdir
2995         local f=$DIR/$tdir/$tfile
2996         local fid=$(make_large_for_progress $f)
2997
2998         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
2999                 error "could not archive file"
3000         wait_request_state $fid ARCHIVE STARTED
3001
3002         check_hsm_flags $f "0x00000001"
3003
3004         # Avoid coordinator resending this request as soon it has failed.
3005         cdt_set_no_retry
3006
3007         echo "foo" >> $f
3008         sync
3009         wait_request_state $fid ARCHIVE FAILED
3010
3011         check_hsm_flags $f "0x00000003"
3012
3013         cdt_clear_no_retry
3014         copytool_cleanup
3015 }
3016 run_test 54 "Write during an archive cancels it"
3017
3018 test_55() {
3019         # test needs a running copytool
3020         copytool_setup
3021
3022         mkdir -p $DIR/$tdir
3023         local f=$DIR/$tdir/$tfile
3024         local fid=$(make_large_for_progress $f)
3025
3026         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
3027                 error "could not archive file"
3028         wait_request_state $fid ARCHIVE STARTED
3029
3030         check_hsm_flags $f "0x00000001"
3031
3032         # Avoid coordinator resending this request as soon it has failed.
3033         cdt_set_no_retry
3034
3035         $TRUNCATE $f 1024 || error "truncate failed"
3036         sync
3037         wait_request_state $fid ARCHIVE FAILED
3038
3039         check_hsm_flags $f "0x00000003"
3040
3041         cdt_clear_no_retry
3042         copytool_cleanup
3043 }
3044 run_test 55 "Truncate during an archive cancels it"
3045
3046 test_56() {
3047         # test needs a running copytool
3048         copytool_setup
3049
3050         mkdir -p $DIR/$tdir
3051         local f=$DIR/$tdir/$tfile
3052         local fid
3053         fid=$(make_large_for_progress $f)
3054         [ $? != 0 ] && skip "not enough free space" && return
3055
3056         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
3057                 error "could not archive file"
3058         wait_request_state $fid ARCHIVE STARTED
3059
3060         check_hsm_flags $f "0x00000001"
3061
3062         # Change metadata and sync to be sure we are not changing only
3063         # in memory.
3064         chmod 644 $f
3065         chgrp sys $f
3066         sync
3067         wait_request_state $fid ARCHIVE SUCCEED
3068
3069         check_hsm_flags $f "0x00000009"
3070
3071         copytool_cleanup
3072 }
3073 run_test 56 "Setattr during an archive is ok"
3074
3075 test_57() {
3076         # Need one client for I/O, one for request
3077         needclients 2 || return 0
3078
3079         # test needs a running copytool
3080         copytool_setup
3081
3082         mkdir -p $DIR/$tdir
3083         local f=$DIR/$tdir/test_archive_remote
3084         # Create a file on a remote node
3085         do_node $CLIENT2 "dd if=/dev/urandom of=$f bs=1M "\
3086                 "count=2 conv=fsync"
3087
3088         # And archive it
3089         do_node $CLIENT2 "$LFS hsm_archive -a $HSM_ARCHIVE_NUMBER $f" ||
3090                 error "hsm_archive failed"
3091         local fid=$(path2fid $f)
3092         wait_request_state $fid ARCHIVE SUCCEED
3093
3094         # Release and implicit restore it
3095         do_node $CLIENT2 "$LFS hsm_release $f" ||
3096                 error "hsm_release failed"
3097         do_node $CLIENT2 "md5sum $f" ||
3098                 error "hsm_restore failed"
3099
3100         wait_request_state $fid RESTORE SUCCEED
3101
3102         copytool_cleanup
3103 }
3104 run_test 57 "Archive a file with dirty cache on another node"
3105
3106 truncate_released_file() {
3107         local src_file=$1
3108         local trunc_to=$2
3109
3110         local sz=$(stat -c %s $src_file)
3111         local f=$DIR/$tdir/$tfile
3112         local fid=$(copy_file $1 $f)
3113         local ref=$f-ref
3114         cp $f $f-ref
3115
3116         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
3117                 error "could not archive file"
3118         wait_request_state $fid ARCHIVE SUCCEED
3119
3120         $LFS hsm_release $f || error "could not release file"
3121
3122         $TRUNCATE $f $trunc_to || error "truncate failed"
3123         sync
3124
3125         local sz1=$(stat -c %s $f)
3126         [[ $sz1 == $trunc_to ]] ||
3127                 error "size after trunc: $sz1 expect $trunc_to, original $sz"
3128
3129         $LFS hsm_state $f
3130         check_hsm_flags $f "0x0000000b"
3131
3132         local state=$(get_request_state $fid RESTORE)
3133         [[ "$state" == "SUCCEED" ]] ||
3134                 error "truncate $sz does not trig restore, state = $state"
3135
3136         $TRUNCATE $ref $trunc_to
3137         cmp $ref $f || error "file data wrong after truncate"
3138
3139         rm -f $f $f-ref
3140 }
3141
3142 test_58() {
3143         # test needs a running copytool
3144         copytool_setup
3145
3146         mkdir -p $DIR/$tdir
3147
3148         local sz=$(stat -c %s /etc/passwd)
3149
3150         echo "truncate up from $sz to $((sz*2))"
3151         truncate_released_file /etc/passwd $((sz*2))
3152
3153         echo "truncate down from $sz to $((sz/2))"
3154         truncate_released_file /etc/passwd $((sz/2))
3155
3156         echo "truncate to 0"
3157         truncate_released_file /etc/passwd 0
3158
3159         copytool_cleanup
3160 }
3161 run_test 58 "Truncate a released file will trigger restore"
3162
3163 test_59() {
3164         local fid
3165         local server_version=$(lustre_version_code $SINGLEMDS)
3166         [[ $server_version -lt $(version_code 2.7.63) ]] &&
3167                 skip "Need MDS version at least 2.7.63" && return
3168
3169         copytool_setup
3170         $MCREATE $DIR/$tfile || error "mcreate failed"
3171         $TRUNCATE $DIR/$tfile 42 || error "truncate failed"
3172         $LFS hsm_archive $DIR/$tfile || error "archive request failed"
3173         fid=$(path2fid $DIR/$tfile)
3174         wait_request_state $fid ARCHIVE SUCCEED
3175         $LFS hsm_release $DIR/$tfile || error "release failed"
3176         copytool_cleanup
3177 }
3178 run_test 59 "Release stripeless file with non-zero size"
3179
3180 test_60() {
3181         # This test validates the fix for LU-4512. Ensure that the -u
3182         # option changes the progress reporting interval from the
3183         # default (30 seconds) to the user-specified interval.
3184         local interval=5
3185         local progress_timeout=$((interval * 4))
3186
3187         # test needs a new running copytool
3188         copytool_cleanup
3189         HSMTOOL_UPDATE_INTERVAL=$interval copytool_setup
3190
3191         mkdir -p $DIR/$tdir
3192         local f=$DIR/$tdir/$tfile
3193         local fid
3194         fid=$(make_large_for_progress $f)
3195         [ $? != 0 ] && skip "not enough free space" && return
3196
3197         local mdtidx=0
3198         local mdt=${MDT_PREFIX}${mdtidx}
3199         local mds=mds$((mdtidx + 1))
3200
3201         # Wait for copytool to register
3202         wait_update_facet $mds \
3203                 "$LCTL get_param -n ${mdt}.hsm.agents | grep -o ^uuid" \
3204                 uuid 100 || error "coyptool failed to register with $mdt"
3205
3206         local start_at=$(date +%s)
3207         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
3208                 error "could not archive file"
3209
3210         local agent=$(facet_active_host $SINGLEAGT)
3211         local prefix=$TESTLOG_PREFIX
3212         [[ -z "$TESTNAME" ]] || prefix=$prefix.$TESTNAME
3213         local copytool_log=$prefix.copytool_log.$agent.log
3214
3215
3216         wait_update $agent \
3217             "grep -o start.copy $copytool_log" "start copy" 100 ||
3218                 error "copytool failed to start"
3219
3220         local cmd="$LCTL get_param -n ${mdt}.hsm.active_requests"
3221         cmd+=" | awk '/'$fid'.*action=ARCHIVE/ {print \\\$12}' | cut -f2 -d="
3222
3223         local RESULT
3224         local WAIT=0
3225         local sleep=1
3226
3227         echo -n "Expecting a progress update within $progress_timeout seconds... "
3228         while [ true ]; do
3229                 RESULT=$(do_node $(facet_active_host $mds) "$cmd")
3230                 if [ $RESULT -gt 0 ]; then
3231                         echo "$RESULT bytes copied in $WAIT seconds."
3232                         break
3233                 elif [ $WAIT -ge $progress_timeout ]; then
3234                         error "Timed out waiting for progress update!"
3235                         break
3236                 fi
3237                 WAIT=$((WAIT + sleep))
3238                 sleep $sleep
3239         done
3240
3241         local finish_at=$(date +%s)
3242         local elapsed=$((finish_at - start_at))
3243
3244         # Ensure that the progress update occurred within the expected window.
3245         if [ $elapsed -lt $((interval - 1)) ]; then
3246                 error "Expected progress update after at least $interval seconds"
3247         fi
3248
3249         cdt_clear_no_retry
3250         copytool_cleanup
3251 }
3252 run_test 60 "Changing progress update interval from default"
3253
3254 test_70() {
3255         # test needs a new running copytool
3256         copytool_cleanup
3257         copytool_monitor_setup
3258         HSMTOOL_EVENT_FIFO=$HSMTOOL_MONITOR_DIR/fifo copytool_setup
3259
3260         # Just start and stop the copytool to generate events.
3261         cdt_clear_no_retry
3262
3263         # Wait for the copytool to register.
3264         wait_update --verbose $(facet_active_host mds1) \
3265                 "$LCTL get_param -n ${MDT_PREFIX}0.hsm.agents | grep -o ^uuid" \
3266                 uuid 100 ||
3267                 error "copytool failed to register with MDT0000"
3268
3269         copytool_cleanup
3270
3271         local REGISTER_EVENT
3272         local UNREGISTER_EVENT
3273         while read event; do
3274                 local parsed=$(parse_json_event "$event")
3275                 if [ -z "$parsed" ]; then
3276                         error "Copytool sent malformed event: $event"
3277                 fi
3278                 eval $parsed
3279
3280                 if [ $event_type == "REGISTER" ]; then
3281                         REGISTER_EVENT=$event
3282                 elif [ $event_type == "UNREGISTER" ]; then
3283                         UNREGISTER_EVENT=$event
3284                 fi
3285         done < <(echo $"$(get_copytool_event_log)")
3286
3287         if [ -z "$REGISTER_EVENT" ]; then
3288                 error "Copytool failed to send register event to FIFO"
3289         fi
3290
3291         if [ -z "$UNREGISTER_EVENT" ]; then
3292                 error "Copytool failed to send unregister event to FIFO"
3293         fi
3294
3295         copytool_monitor_cleanup
3296         echo "Register/Unregister events look OK."
3297 }
3298 run_test 70 "Copytool logs JSON register/unregister events to FIFO"
3299
3300 test_71() {
3301         # Bump progress interval for livelier events.
3302         local interval=5
3303
3304         # test needs a new running copytool
3305         copytool_cleanup
3306         copytool_monitor_setup
3307         HSMTOOL_UPDATE_INTERVAL=$interval \
3308         HSMTOOL_EVENT_FIFO=$HSMTOOL_MONITOR_DIR/fifo copytool_setup
3309
3310         mkdir -p $DIR/$tdir
3311         local f=$DIR/$tdir/$tfile
3312         local fid
3313         fid=$(make_large_for_progress $f)
3314         [ $? != 0 ] && skip "not enough free space" && return
3315
3316         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
3317                 error "could not archive file"
3318         wait_request_state $fid ARCHIVE SUCCEED
3319
3320         local expected_fields="event_time data_fid source_fid"
3321         expected_fields+=" total_bytes current_bytes"
3322
3323         local START_EVENT
3324         local FINISH_EVENT
3325         while read event; do
3326                 # Make sure we're not getting anything from previous events.
3327                 for field in $expected_fields; do
3328                         unset $field
3329                 done
3330
3331                 local parsed=$(parse_json_event "$event")
3332                 if [ -z "$parsed" ]; then
3333                         error "Copytool sent malformed event: $event"
3334                 fi
3335                 eval $parsed
3336
3337                 if [ $event_type == "ARCHIVE_START" ]; then
3338                         START_EVENT=$event
3339                         continue
3340                 elif [ $event_type == "ARCHIVE_FINISH" ]; then
3341                         FINISH_EVENT=$event
3342                         continue
3343                 elif [ $event_type != "ARCHIVE_RUNNING" ]; then
3344                         continue
3345                 fi
3346
3347                 # Do some simple checking of the progress update events.
3348                 for expected_field in $expected_fields; do
3349                         if [ -z ${!expected_field+x} ]; then
3350                                 error "Missing $expected_field field in event"
3351                         fi
3352                 done
3353
3354                 if [ $total_bytes -eq 0 ]; then
3355                         error "Expected total_bytes to be > 0"
3356                 fi
3357
3358                 # These should be identical throughout an archive
3359                 # operation.
3360                 if [ $source_fid != $data_fid ]; then
3361                         error "Expected source_fid to equal data_fid"
3362                 fi
3363         done < <(echo $"$(get_copytool_event_log)")
3364
3365         if [ -z "$START_EVENT" ]; then
3366                 error "Copytool failed to send archive start event to FIFO"
3367         fi
3368
3369         if [ -z "$FINISH_EVENT" ]; then
3370                 error "Copytool failed to send archive finish event to FIFO"
3371         fi
3372
3373         echo "Archive events look OK."
3374
3375         cdt_clear_no_retry
3376         copytool_cleanup
3377         copytool_monitor_cleanup
3378 }
3379 run_test 71 "Copytool logs JSON archive events to FIFO"
3380
3381 test_72() {
3382         # Bump progress interval for livelier events.
3383         local interval=5
3384
3385         # test needs a new running copytool
3386         copytool_cleanup
3387         copytool_monitor_setup
3388         HSMTOOL_UPDATE_INTERVAL=$interval \
3389         HSMTOOL_EVENT_FIFO=$HSMTOOL_MONITOR_DIR/fifo copytool_setup
3390         local test_file=$HSMTOOL_MONITOR_DIR/file
3391
3392         local cmd="dd if=/dev/urandom of=$test_file count=16 bs=1000000 "
3393         cmd+="conv=fsync"
3394         do_facet $SINGLEAGT "$cmd" ||
3395                 error "cannot create $test_file on $SINGLEAGT"
3396         copy2archive $test_file $tdir/$tfile
3397
3398         mkdir -p $DIR/$tdir
3399         local f=$DIR/$tdir/$tfile
3400         import_file $tdir/$tfile $f
3401         f=$DIR2/$tdir/$tfile
3402         echo "Verifying released state: "
3403         check_hsm_flags $f "0x0000000d"
3404
3405         local fid=$(path2fid $f)
3406         $LFS hsm_restore $f
3407         wait_request_state $fid RESTORE SUCCEED
3408
3409         local expected_fields="event_time data_fid source_fid"
3410         expected_fields+=" total_bytes current_bytes"
3411
3412         local START_EVENT
3413         local FINISH_EVENT
3414         while read event; do
3415                 # Make sure we're not getting anything from previous events.
3416                 for field in $expected_fields; do
3417                         unset $field
3418                 done
3419
3420                 local parsed=$(parse_json_event "$event")
3421                 if [ -z "$parsed" ]; then
3422                         error "Copytool sent malformed event: $event"
3423                 fi
3424                 eval $parsed
3425
3426                 if [ $event_type == "RESTORE_START" ]; then
3427                         START_EVENT=$event
3428                         if [ $source_fid != $data_fid ]; then
3429                                 error "source_fid should == data_fid at start"
3430                         fi
3431                         continue
3432                 elif [ $event_type == "RESTORE_FINISH" ]; then
3433                         FINISH_EVENT=$event
3434                         if [ $source_fid != $data_fid ]; then
3435                                 error "source_fid should == data_fid at finish"
3436                         fi
3437                         continue
3438                 elif [ $event_type != "RESTORE_RUNNING" ]; then
3439                         continue
3440                 fi
3441
3442                 # Do some simple checking of the progress update events.
3443                 for expected_field in $expected_fields; do
3444                         if [ -z ${!expected_field+x} ]; then
3445                                 error "Missing $expected_field field in event"
3446                         fi
3447                 done
3448
3449                 if [ $total_bytes -eq 0 ]; then
3450                         error "Expected total_bytes to be > 0"
3451                 fi
3452
3453                 # When a restore starts out, the data fid is the same as the
3454                 # source fid. After the restore has gotten going, we learn
3455                 # the new data fid. Once the restore has finished, the source
3456                 # fid is set to the new data fid.
3457                 #
3458                 # We test this because some monitoring software may depend on
3459                 # this behavior. If it changes, then the consumers of these
3460                 # events may need to be modified.
3461                 if [ $source_fid == $data_fid ]; then
3462                         error "source_fid should != data_fid during restore"
3463                 fi
3464         done < <(echo $"$(get_copytool_event_log)")
3465
3466         if [ -z "$START_EVENT" ]; then
3467                 error "Copytool failed to send restore start event to FIFO"
3468         fi
3469
3470         if [ -z "$FINISH_EVENT" ]; then
3471                 error "Copytool failed to send restore finish event to FIFO"
3472         fi
3473
3474         echo "Restore events look OK."
3475
3476         cdt_clear_no_retry