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