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