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