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