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