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