Whamcloud - gitweb
97fc46e85c031f9a4dffeb0c0f2b874116c1cf99
[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 -lt $interval ]; then
2669                 error "Expected progress update after at least $interval seconds"
2670         fi
2671
2672         cdt_clear_no_retry
2673         copytool_cleanup
2674 }
2675 run_test 60 "Changing progress update interval from default"
2676
2677 test_70() {
2678         # test needs a new running copytool
2679         copytool_cleanup
2680         copytool_monitor_setup
2681         HSMTOOL_EVENT_FIFO=$HSMTOOL_MONITOR_DIR/fifo copytool_setup
2682
2683         # Just start and stop the copytool to generate events.
2684         cdt_clear_no_retry
2685         copytool_cleanup
2686
2687         local REGISTER_EVENT
2688         local UNREGISTER_EVENT
2689         while read event; do
2690                 local parsed=$(parse_json_event "$event")
2691                 if [ -z "$parsed" ]; then
2692                         error "Copytool sent malformed event: $event"
2693                 fi
2694                 eval $parsed
2695
2696                 if [ $event_type == "REGISTER" ]; then
2697                         REGISTER_EVENT=$event
2698                 elif [ $event_type == "UNREGISTER" ]; then
2699                         UNREGISTER_EVENT=$event
2700                 fi
2701         done < <(echo $"$(get_copytool_event_log)")
2702
2703         if [ -z "$REGISTER_EVENT" ]; then
2704                 error "Copytool failed to send register event to FIFO"
2705         fi
2706
2707         if [ -z "$UNREGISTER_EVENT" ]; then
2708                 error "Copytool failed to send unregister event to FIFO"
2709         fi
2710
2711         copytool_monitor_cleanup
2712         echo "Register/Unregister events look OK."
2713 }
2714 run_test 70 "Copytool logs JSON register/unregister events to FIFO"
2715
2716 test_71() {
2717         # Bump progress interval for livelier events.
2718         local interval=5
2719
2720         # test needs a new running copytool
2721         copytool_cleanup
2722         copytool_monitor_setup
2723         HSMTOOL_UPDATE_INTERVAL=$interval \
2724         HSMTOOL_EVENT_FIFO=$HSMTOOL_MONITOR_DIR/fifo copytool_setup
2725
2726         mkdir -p $DIR/$tdir
2727         local f=$DIR/$tdir/$tfile
2728         local fid=$(make_large_for_progress $f)
2729
2730         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f ||
2731                 error "could not archive file"
2732         wait_request_state $fid ARCHIVE SUCCEED
2733
2734         local expected_fields="event_time data_fid source_fid"
2735         expected_fields+=" total_bytes current_bytes"
2736
2737         local START_EVENT
2738         local FINISH_EVENT
2739         while read event; do
2740                 # Make sure we're not getting anything from previous events.
2741                 for field in $expected_fields; do
2742                         unset $field
2743                 done
2744
2745                 local parsed=$(parse_json_event "$event")
2746                 if [ -z "$parsed" ]; then
2747                         error "Copytool sent malformed event: $event"
2748                 fi
2749                 eval $parsed
2750
2751                 if [ $event_type == "ARCHIVE_START" ]; then
2752                         START_EVENT=$event
2753                         continue
2754                 elif [ $event_type == "ARCHIVE_FINISH" ]; then
2755                         FINISH_EVENT=$event
2756                         continue
2757                 elif [ $event_type != "ARCHIVE_RUNNING" ]; then
2758                         continue
2759                 fi
2760
2761                 # Do some simple checking of the progress update events.
2762                 for expected_field in $expected_fields; do
2763                         if [ -z ${!expected_field+x} ]; then
2764                                 error "Missing $expected_field field in event"
2765                         fi
2766                 done
2767
2768                 if [ $total_bytes -eq 0 ]; then
2769                         error "Expected total_bytes to be > 0"
2770                 fi
2771
2772                 # These should be identical throughout an archive
2773                 # operation.
2774                 if [ $source_fid != $data_fid ]; then
2775                         error "Expected source_fid to equal data_fid"
2776                 fi
2777         done < <(echo $"$(get_copytool_event_log)")
2778
2779         if [ -z "$START_EVENT" ]; then
2780                 error "Copytool failed to send archive start event to FIFO"
2781         fi
2782
2783         if [ -z "$FINISH_EVENT" ]; then
2784                 error "Copytool failed to send archive finish event to FIFO"
2785         fi
2786
2787         echo "Archive events look OK."
2788
2789         cdt_clear_no_retry
2790         copytool_cleanup
2791         copytool_monitor_cleanup
2792 }
2793 run_test 71 "Copytool logs JSON archive events to FIFO"
2794
2795 test_72() {
2796         # Bump progress interval for livelier events.
2797         local interval=5
2798
2799         # test needs a new running copytool
2800         copytool_cleanup
2801         copytool_monitor_setup
2802         HSMTOOL_UPDATE_INTERVAL=$interval \
2803         HSMTOOL_EVENT_FIFO=$HSMTOOL_MONITOR_DIR/fifo copytool_setup
2804         local test_file=$HSMTOOL_MONITOR_DIR/file
2805
2806         local cmd="dd if=/dev/urandom of=$test_file count=16 bs=1000000 "
2807         cmd+="conv=fsync"
2808         do_facet $SINGLEAGT "$cmd" ||
2809                 error "cannot create $test_file on $SINGLEAGT"
2810         copy2archive $test_file $tdir/$tfile
2811
2812         mkdir -p $DIR/$tdir
2813         local f=$DIR/$tdir/$tfile
2814         import_file $tdir/$tfile $f
2815         f=$DIR2/$tdir/$tfile
2816         echo "Verifying released state: "
2817         check_hsm_flags $f "0x0000000d"
2818
2819         local fid=$(path2fid $f)
2820         $LFS hsm_restore $f
2821         wait_request_state $fid RESTORE SUCCEED
2822
2823         local expected_fields="event_time data_fid source_fid"
2824         expected_fields+=" total_bytes current_bytes"
2825
2826         local START_EVENT
2827         local FINISH_EVENT
2828         while read event; do
2829                 # Make sure we're not getting anything from previous events.
2830                 for field in $expected_fields; do
2831                         unset $field
2832                 done
2833
2834                 local parsed=$(parse_json_event "$event")
2835                 if [ -z "$parsed" ]; then
2836                         error "Copytool sent malformed event: $event"
2837                 fi
2838                 eval $parsed
2839
2840                 if [ $event_type == "RESTORE_START" ]; then
2841                         START_EVENT=$event
2842                         if [ $source_fid != $data_fid ]; then
2843                                 error "source_fid should == data_fid at start"
2844                         fi
2845                         continue
2846                 elif [ $event_type == "RESTORE_FINISH" ]; then
2847                         FINISH_EVENT=$event
2848                         if [ $source_fid != $data_fid ]; then
2849                                 error "source_fid should == data_fid at finish"
2850                         fi
2851                         continue
2852                 elif [ $event_type != "RESTORE_RUNNING" ]; then
2853                         continue
2854                 fi
2855
2856                 # Do some simple checking of the progress update events.
2857                 for expected_field in $expected_fields; do
2858                         if [ -z ${!expected_field+x} ]; then
2859                                 error "Missing $expected_field field in event"
2860                         fi
2861                 done
2862
2863                 if [ $total_bytes -eq 0 ]; then
2864                         error "Expected total_bytes to be > 0"
2865                 fi
2866
2867                 # When a restore starts out, the data fid is the same as the
2868                 # source fid. After the restore has gotten going, we learn
2869                 # the new data fid. Once the restore has finished, the source
2870                 # fid is set to the new data fid.
2871                 #
2872                 # We test this because some monitoring software may depend on
2873                 # this behavior. If it changes, then the consumers of these
2874                 # events may need to be modified.
2875                 if [ $source_fid == $data_fid ]; then
2876                         error "source_fid should != data_fid during restore"
2877                 fi
2878         done < <(echo $"$(get_copytool_event_log)")
2879
2880         if [ -z "$START_EVENT" ]; then
2881                 error "Copytool failed to send restore start event to FIFO"
2882         fi
2883
2884         if [ -z "$FINISH_EVENT" ]; then
2885                 error "Copytool failed to send restore finish event to FIFO"
2886         fi
2887
2888         echo "Restore events look OK."
2889
2890         cdt_clear_no_retry
2891         copytool_cleanup
2892         copytool_monitor_cleanup
2893
2894         rm -rf $test_dir
2895 }
2896 run_test 72 "Copytool logs JSON restore events to FIFO"
2897
2898 test_90() {
2899         file_count=51 # Max number of files constrained by LNET message size
2900         mkdir $DIR/$tdir || error "mkdir $DIR/$tdir failed"
2901         local f=$DIR/$tdir/$tfile
2902         local FILELIST=/tmp/filelist.txt
2903         local i=""
2904
2905         rm -f $FILELIST
2906         for i in $(seq 1 $file_count); do
2907                 fid=$(copy_file /etc/hosts $f.$i)
2908                 echo $f.$i >> $FILELIST
2909         done
2910         copytool_setup
2911         # to be sure wait_all_done will not be mislead by previous tests
2912         cdt_purge
2913         wait_for_grace_delay
2914         $LFS hsm_archive --filelist $FILELIST ||
2915                 error "cannot archive a file list"
2916         wait_all_done 100
2917         $LFS hsm_release --filelist $FILELIST ||
2918                 error "cannot release a file list"
2919         $LFS hsm_restore --filelist $FILELIST ||
2920                 error "cannot restore a file list"
2921         wait_all_done 100
2922         copytool_cleanup
2923 }
2924 run_test 90 "Archive/restore a file list"
2925
2926 double_verify_reset_hsm_param() {
2927         local p=$1
2928         echo "Testing $HSM_PARAM.$p"
2929         local val=$(get_hsm_param $p)
2930         local save=$val
2931         local val2=$(($val * 2))
2932         set_hsm_param $p $val2
2933         val=$(get_hsm_param $p)
2934         [[ $val == $val2 ]] ||
2935                 error "$HSM_PARAM.$p: $val != $val2 should be (2 * $save)"
2936         echo "Set $p to 0 must failed"
2937         set_hsm_param $p 0
2938         local rc=$?
2939         # restore value
2940         set_hsm_param $p $save
2941
2942         if [[ $rc == 0 ]]; then
2943                 error "we must not be able to set $HSM_PARAM.$p to 0"
2944         fi
2945 }
2946
2947 test_100() {
2948         double_verify_reset_hsm_param loop_period
2949         double_verify_reset_hsm_param grace_delay
2950         double_verify_reset_hsm_param active_request_timeout
2951         double_verify_reset_hsm_param max_requests
2952         double_verify_reset_hsm_param default_archive_id
2953 }
2954 run_test 100 "Set coordinator /proc tunables"
2955
2956 test_102() {
2957         cdt_disable
2958         cdt_enable
2959         cdt_restart
2960 }
2961 run_test 102 "Verify coordinator control"
2962
2963 test_103() {
2964         # test needs a running copytool
2965         copytool_setup
2966
2967         local i=""
2968         local fid=""
2969
2970         mkdir -p $DIR/$tdir
2971         for i in $(seq 1 20); do
2972                 fid=$(copy_file /etc/passwd $DIR/$tdir/$i)
2973         done
2974         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $DIR/$tdir/*
2975
2976         cdt_purge
2977
2978         echo "Current requests"
2979         local res=$(do_facet $SINGLEMDS "$LCTL get_param -n\
2980                         $HSM_PARAM.actions |\
2981                         grep -v CANCELED | grep -v SUCCEED | grep -v FAILED")
2982
2983         [[ -z "$res" ]] || error "Some request have not been canceled"
2984
2985         copytool_cleanup
2986 }
2987 run_test 103 "Purge all requests"
2988
2989 DATA=CEA
2990 DATAHEX='[434541]'
2991 test_104() {
2992         # test needs a running copytool
2993         copytool_setup
2994
2995         mkdir -p $DIR/$tdir
2996         local f=$DIR/$tdir/$tfile
2997         local fid=$(make_large_for_progress $f)
2998         # if cdt is on, it can serve too quickly the request
2999         cdt_disable
3000         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER --data $DATA $f
3001         local data1=$(do_facet $SINGLEMDS "$LCTL get_param -n\
3002                         $HSM_PARAM.actions |\
3003                         grep $fid | cut -f16 -d=")
3004         cdt_enable
3005
3006         [[ "$data1" == "$DATAHEX" ]] ||
3007                 error "Data field in records is ($data1) and not ($DATAHEX)"
3008
3009         copytool_cleanup
3010 }
3011 run_test 104 "Copy tool data field"
3012
3013 test_105() {
3014         mkdir -p $DIR/$tdir
3015         local i=""
3016
3017         cdt_disable
3018         for i in $(seq -w 1 10); do
3019                 cp /etc/passwd $DIR/$tdir/$i
3020                 $LFS hsm_archive $DIR/$tdir/$i
3021         done
3022         local reqcnt1=$(do_facet $SINGLEMDS "$LCTL get_param -n\
3023                         $HSM_PARAM.actions |\
3024                         grep WAITING | wc -l")
3025         cdt_restart
3026         cdt_disable
3027         local reqcnt2=$(do_facet $SINGLEMDS "$LCTL get_param -n\
3028                         $HSM_PARAM.actions |\
3029                         grep WAITING | wc -l")
3030         cdt_enable
3031         cdt_purge
3032         [[ "$reqcnt1" == "$reqcnt2" ]] ||
3033                 error "Requests count after shutdown $reqcnt2 != "\
3034                       "before shutdown $reqcnt1"
3035 }
3036 run_test 105 "Restart of coordinator"
3037
3038 get_agent_by_uuid_mdt() {
3039         local uuid=$1
3040         local mdtidx=$2
3041         local mds=mds$(($mdtidx + 1))
3042         do_facet $mds "$LCTL get_param -n ${MDT_PREFIX}${mdtidx}.hsm.agents |\
3043                  grep $uuid"
3044 }
3045
3046 check_agent_registered_by_mdt() {
3047         local uuid=$1
3048         local mdtidx=$2
3049         local mds=mds$(($mdtidx + 1))
3050         local agent=$(get_agent_by_uuid_mdt $uuid $mdtidx)
3051         if [[ ! -z "$agent" ]]; then
3052                 echo "found agent $agent on $mds"
3053         else
3054                 error "uuid $uuid not found in agent list on $mds"
3055         fi
3056 }
3057
3058 check_agent_unregistered_by_mdt() {
3059         local uuid=$1
3060         local mdtidx=$2
3061         local mds=mds$(($mdtidx + 1))
3062         local agent=$(get_agent_by_uuid_mdt $uuid $mdtidx)
3063         if [[ -z "$agent" ]]; then
3064                 echo "uuid not found in agent list on $mds"
3065         else
3066                 error "uuid found in agent list on $mds: $agent"
3067         fi
3068 }
3069
3070 check_agent_registered() {
3071         local uuid=$1
3072         local mdsno
3073         for mdsno in $(seq 1 $MDSCOUNT); do
3074                 check_agent_registered_by_mdt $uuid $((mdsno - 1))
3075         done
3076 }
3077
3078 check_agent_unregistered() {
3079         local uuid=$1
3080         local mdsno
3081         for mdsno in $(seq 1 $MDSCOUNT); do
3082                 check_agent_unregistered_by_mdt $uuid $((mdsno - 1))
3083         done
3084 }
3085
3086 test_106() {
3087         local uuid=$(do_rpc_nodes $(facet_active_host $SINGLEAGT) \
3088                 get_client_uuid $MOUNT | cut -d' ' -f2)
3089
3090         copytool_setup
3091         check_agent_registered $uuid
3092
3093         search_copytools || error "No copytool found"
3094
3095         copytool_cleanup
3096         check_agent_unregistered $uuid
3097
3098         copytool_setup
3099         check_agent_registered $uuid
3100
3101         copytool_cleanup
3102 }
3103 run_test 106 "Copytool register/unregister"
3104
3105 test_107() {
3106         # test needs a running copytool
3107         copytool_setup
3108         # create and archive file
3109         mkdir -p $DIR/$tdir
3110         local f1=$DIR/$tdir/$tfile
3111         local fid=$(copy_file /etc/passwd $f1)
3112         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f1
3113         wait_request_state $fid ARCHIVE SUCCEED
3114         # shutdown and restart MDS
3115         fail $SINGLEMDS
3116         # check the copytool still gets messages from MDT
3117         local f2=$DIR/$tdir/2
3118         local fid=$(copy_file /etc/passwd $f2)
3119         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f2
3120         # main check of this sanity: this request MUST succeed
3121         wait_request_state $fid ARCHIVE SUCCEED
3122         copytool_cleanup
3123 }
3124 run_test 107 "Copytool re-register after MDS restart"
3125
3126 policy_set_and_test()
3127 {
3128         local change="$1"
3129         local target="$2"
3130         do_facet $SINGLEMDS $LCTL set_param "$HSM_PARAM.policy=\\\"$change\\\""
3131         local policy=$(do_facet $SINGLEMDS $LCTL get_param -n $HSM_PARAM.policy)
3132         [[ "$policy" == "$target" ]] ||
3133                 error "Wrong policy after '$change': '$policy' != '$target'"
3134 }
3135
3136 test_109() {
3137         # to force default policy setting if error
3138         CDT_POLICY_HAD_CHANGED=true
3139
3140         local policy=$(do_facet $SINGLEMDS $LCTL get_param -n $HSM_PARAM.policy)
3141         local default="NonBlockingRestore [NoRetryAction]"
3142         [[ "$policy" == "$default" ]] ||
3143                 error "default policy has changed,"\
3144                       " '$policy' != '$default' update the test"
3145         policy_set_and_test "+NBR" "[NonBlockingRestore] [NoRetryAction]"
3146         policy_set_and_test "+NRA" "[NonBlockingRestore] [NoRetryAction]"
3147         policy_set_and_test "-NBR" "NonBlockingRestore [NoRetryAction]"
3148         policy_set_and_test "-NRA" "NonBlockingRestore NoRetryAction"
3149         policy_set_and_test "NRA NBR" "[NonBlockingRestore] [NoRetryAction]"
3150         # useless bacause we know but safer for futur changes to use real value
3151         local policy=$(do_facet $SINGLEMDS $LCTL get_param -n $HSM_PARAM.policy)
3152         echo "Next set_param must failed"
3153         policy_set_and_test "wrong" "$policy"
3154
3155         # return to default
3156         echo "Back to default policy"
3157         cdt_set_sanity_policy
3158 }
3159 run_test 109 "Policy display/change"
3160
3161 test_110a() {
3162         # test needs a running copytool
3163         copytool_setup
3164
3165         mkdir -p $DIR/$tdir
3166
3167         copy2archive /etc/passwd $tdir/$tfile
3168
3169         local f=$DIR/$tdir/$tfile
3170         import_file $tdir/$tfile $f
3171         local fid=$(path2fid $f)
3172
3173         cdt_set_non_blocking_restore
3174         md5sum $f
3175         local st=$?
3176
3177         # cleanup
3178         wait_request_state $fid RESTORE SUCCEED
3179         cdt_clear_non_blocking_restore
3180
3181         # Test result
3182         [[ $st == 1 ]] ||
3183                 error "md5sum returns $st != 1, "\
3184                         "should also perror ENODATA (No data available)"
3185
3186         copytool_cleanup
3187 }
3188 run_test 110a "Non blocking restore policy (import case)"
3189
3190 test_110b() {
3191         # test needs a running copytool
3192         copytool_setup
3193
3194         mkdir -p $DIR/$tdir
3195         local f=$DIR/$tdir/$tfile
3196         local fid=$(copy_file /etc/passwd $f)
3197         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3198         wait_request_state $fid ARCHIVE SUCCEED
3199         $LFS hsm_release $f
3200
3201         cdt_set_non_blocking_restore
3202         md5sum $f
3203         local st=$?
3204
3205         # cleanup
3206         wait_request_state $fid RESTORE SUCCEED
3207         cdt_clear_non_blocking_restore
3208
3209         # Test result
3210         [[ $st == 1 ]] ||
3211                 error "md5sum returns $st != 1, "\
3212                         "should also perror ENODATA (No data available)"
3213
3214         copytool_cleanup
3215 }
3216 run_test 110b "Non blocking restore policy (release case)"
3217
3218 test_111a() {
3219         # test needs a running copytool
3220         copytool_setup
3221
3222         mkdir -p $DIR/$tdir
3223         copy2archive /etc/passwd $tdir/$tfile
3224
3225         local f=$DIR/$tdir/$tfile
3226
3227         import_file $tdir/$tfile $f
3228         local fid=$(path2fid $f)
3229
3230         cdt_set_no_retry
3231
3232         copytool_remove_backend $fid
3233
3234         $LFS hsm_restore $f
3235         wait_request_state $fid RESTORE FAILED
3236         local st=$?
3237
3238         # cleanup
3239         cdt_clear_no_retry
3240
3241         # Test result
3242         [[ $st == 0 ]] || error "Restore does not failed"
3243
3244         copytool_cleanup
3245 }
3246 run_test 111a "No retry policy (import case), restore will error"\
3247               " (No such file or directory)"
3248
3249 test_111b() {
3250         # test needs a running copytool
3251         copytool_setup
3252
3253         mkdir -p $DIR/$tdir
3254         local f=$DIR/$tdir/$tfile
3255         local fid=$(copy_file /etc/passwd $f)
3256         cdt_set_no_retry
3257         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3258         wait_request_state $fid ARCHIVE SUCCEED
3259         $LFS hsm_release $f
3260
3261         copytool_remove_backend $fid
3262
3263         $LFS hsm_restore $f
3264         wait_request_state $fid RESTORE FAILED
3265         local st=$?
3266
3267         # cleanup
3268         cdt_clear_no_retry
3269
3270         # Test result
3271         [[ $st == 0 ]] || error "Restore does not failed"
3272
3273         copytool_cleanup
3274 }
3275 run_test 111b "No retry policy (release case), restore will error"\
3276               " (No such file or directory)"
3277
3278 test_112() {
3279         # test needs a running copytool
3280         copytool_setup
3281
3282         mkdir -p $DIR/$tdir
3283         local f=$DIR/$tdir/$tfile
3284         local fid=$(copy_file /etc/passwd $f)
3285         cdt_disable
3286         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3287         local l=$($LFS hsm_action $f)
3288         echo $l
3289         local res=$(echo $l | cut -f 2- -d" " | grep ARCHIVE)
3290
3291         # cleanup
3292         cdt_enable
3293         wait_request_state $fid ARCHIVE SUCCEED
3294
3295         # Test result
3296         [[ ! -z "$res" ]] || error "action is $l which is not an ARCHIVE"
3297
3298         copytool_cleanup
3299 }
3300 run_test 112 "State of recorded request"
3301
3302 test_200() {
3303         # test needs a running copytool
3304         copytool_setup
3305
3306         mkdir -p $DIR/$tdir
3307         local f=$DIR/$tdir/$tfile
3308         local fid=$(make_large_for_cancel $f)
3309         # test with cdt on is made in test_221
3310         cdt_disable
3311         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3312         $LFS hsm_cancel $f
3313         cdt_enable
3314         wait_request_state $fid ARCHIVE CANCELED
3315         wait_request_state $fid CANCEL SUCCEED
3316
3317         copytool_cleanup
3318 }
3319 run_test 200 "Register/Cancel archive"
3320
3321 test_201() {
3322         # test needs a running copytool
3323         copytool_setup
3324
3325         mkdir -p $DIR/$tdir
3326         local f=$DIR/$tdir/$tfile
3327         make_archive $tdir/$tfile
3328         import_file $tdir/$tfile $f
3329         local fid=$(path2fid $f)
3330
3331         # test with cdt on is made in test_222
3332         cdt_disable
3333         $LFS hsm_restore $f
3334         $LFS hsm_cancel $f
3335         cdt_enable
3336         wait_request_state $fid RESTORE CANCELED
3337         wait_request_state $fid CANCEL SUCCEED
3338
3339         copytool_cleanup
3340 }
3341 run_test 201 "Register/Cancel restore"
3342
3343 test_202() {
3344         # test needs a running copytool
3345         copytool_setup
3346
3347         mkdir -p $DIR/$tdir
3348         local f=$DIR/$tdir/$tfile
3349         local fid=$(make_large_for_progress $f)
3350         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3351         wait_request_state $fid ARCHIVE SUCCEED
3352
3353         cdt_disable
3354         $LFS hsm_remove $f
3355         $LFS hsm_cancel $f
3356         cdt_enable
3357         wait_request_state $fid REMOVE CANCELED
3358
3359         copytool_cleanup
3360 }
3361 run_test 202 "Register/Cancel remove"
3362
3363 test_220() {
3364         # test needs a running copytool
3365         copytool_setup
3366
3367         mkdir -p $DIR/$tdir
3368
3369         local f=$DIR/$tdir/$tfile
3370         local fid=$(copy_file /etc/passwd $f)
3371
3372         changelog_setup
3373
3374         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3375         wait_request_state $fid ARCHIVE SUCCEED
3376
3377         local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
3378         changelog_cleanup
3379
3380         local target=0x0
3381         [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
3382
3383         copytool_cleanup
3384 }
3385 run_test 220 "Changelog for archive"
3386
3387 test_221() {
3388         # test needs a running copytool
3389         copytool_setup
3390
3391         mkdir -p $DIR/$tdir
3392
3393         local f=$DIR/$tdir/$tfile
3394         local fid=$(make_large_for_cancel $f)
3395
3396         changelog_setup
3397
3398         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3399         wait_request_state $fid ARCHIVE STARTED
3400         $LFS hsm_cancel $f
3401         wait_request_state $fid ARCHIVE CANCELED
3402         wait_request_state $fid CANCEL SUCCEED
3403
3404         local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
3405
3406         local target=0x7d
3407         [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
3408
3409         cleanup
3410 }
3411 run_test 221 "Changelog for archive canceled"
3412
3413 test_222a() {
3414         # test needs a running copytool
3415         copytool_setup
3416
3417         mkdir -p $DIR/$tdir
3418         copy2archive /etc/passwd $tdir/$tfile
3419
3420         local f=$DIR/$tdir/$tfile
3421         import_file $tdir/$tfile $f
3422         local fid=$(path2fid $f)
3423
3424         changelog_setup
3425
3426         $LFS hsm_restore $f
3427         wait_request_state $fid RESTORE SUCCEED
3428
3429         local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
3430
3431         local target=0x80
3432         [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
3433
3434         cleanup
3435 }
3436 run_test 222a "Changelog for explicit restore"
3437
3438 test_222b() {
3439         # test needs a running copytool
3440         copytool_setup
3441
3442         mkdir -p $DIR/$tdir
3443         local f=$DIR/$tdir/$tfile
3444         local fid=$(copy_file /etc/passwd $f)
3445
3446         changelog_setup
3447         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3448         wait_request_state $fid ARCHIVE SUCCEED
3449         $LFS hsm_release $f
3450
3451         md5sum $f
3452
3453         wait_request_state $fid RESTORE SUCCEED
3454
3455         local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
3456
3457         local target=0x80
3458         [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
3459
3460         cleanup
3461 }
3462 run_test 222b "Changelog for implicit restore"
3463
3464 test_223a() {
3465         # test needs a running copytool
3466         copytool_setup
3467
3468         mkdir -p $DIR/$tdir
3469
3470         local f=$DIR/$tdir/$tfile
3471         make_archive $tdir/$tfile
3472
3473         changelog_setup
3474
3475         import_file $tdir/$tfile $f
3476         local fid=$(path2fid $f)
3477
3478         $LFS hsm_restore $f
3479         wait_request_state $fid RESTORE STARTED
3480         $LFS hsm_cancel $f
3481         wait_request_state $fid RESTORE CANCELED
3482         wait_request_state $fid CANCEL SUCCEED
3483
3484         local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
3485
3486         local target=0xfd
3487         [[ $flags == $target ]] ||
3488                 error "Changelog flag is $flags not $target"
3489
3490         cleanup
3491 }
3492 run_test 223a "Changelog for restore canceled (import case)"
3493
3494 test_223b() {
3495         # test needs a running copytool
3496         copytool_setup
3497
3498         mkdir -p $DIR/$tdir
3499
3500         local f=$DIR/$tdir/$tfile
3501         local fid=$(make_large_for_progress $f)
3502
3503         changelog_setup
3504         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3505         wait_request_state $fid ARCHIVE SUCCEED
3506         $LFS hsm_release $f
3507         $LFS hsm_restore $f
3508         wait_request_state $fid RESTORE STARTED
3509         $LFS hsm_cancel $f
3510         wait_request_state $fid RESTORE CANCELED
3511         wait_request_state $fid CANCEL SUCCEED
3512
3513         local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
3514
3515         local target=0xfd
3516         [[ $flags == $target ]] ||
3517                 error "Changelog flag is $flags not $target"
3518
3519         cleanup
3520 }
3521 run_test 223b "Changelog for restore canceled (release case)"
3522
3523 test_224() {
3524         # test needs a running copytool
3525         copytool_setup
3526
3527         mkdir -p $DIR/$tdir
3528
3529         local f=$DIR/$tdir/$tfile
3530         local fid=$(copy_file /etc/passwd $f)
3531
3532         changelog_setup
3533         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3534         wait_request_state $fid ARCHIVE SUCCEED
3535
3536         $LFS hsm_remove $f
3537         wait_request_state $fid REMOVE SUCCEED
3538
3539         local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -n 1)
3540
3541         local target=0x200
3542         [[ $flags == $target ]] ||
3543                 error "Changelog flag is $flags not $target"
3544
3545         cleanup
3546 }
3547 run_test 224 "Changelog for remove"
3548
3549 test_225() {
3550         # test needs a running copytool
3551         copytool_setup
3552
3553         # test is not usable because remove request is too fast
3554         # so it is always finished before cancel can be done ...
3555         echo "Test disabled"
3556         copytool_cleanup
3557         return 0
3558
3559         mkdir -p $DIR/$tdir
3560         local f=$DIR/$tdir/$tfile
3561         local fid=$(make_large_for_progress $f)
3562
3563         changelog_setup
3564         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3565         wait_request_state $fid ARCHIVE SUCCEED
3566
3567         # if cdt is on, it can serve too quickly the request
3568         cdt_disable
3569         $LFS hsm_remove $f
3570         $LFS hsm_cancel $f
3571         cdt_enable
3572         wait_request_state $fid REMOVE CANCELED
3573         wait_request_state $fid CANCEL SUCCEED
3574
3575         flags=$(changelog_get_flags ${MDT[0]} RENME $fid2)
3576         local flags=$($LFS changelog ${MDT[0]} | grep HSM | grep $fid |
3577                 tail -n 1 | awk '{print $5}')
3578
3579         local target=0x27d
3580         [[ $flags == $target ]] ||
3581                 error "Changelog flag is $flags not $target"
3582
3583         cleanup
3584 }
3585 run_test 225 "Changelog for remove canceled"
3586
3587 test_226() {
3588         # test needs a running copytool
3589         copytool_setup
3590
3591         mkdir -p $DIR/$tdir
3592
3593         local f1=$DIR/$tdir/$tfile-1
3594         local f2=$DIR/$tdir/$tfile-2
3595         local f3=$DIR/$tdir/$tfile-3
3596         local fid1=$(copy_file /etc/passwd $f1)
3597         local fid2=$(copy_file /etc/passwd $f2)
3598         copy_file /etc/passwd $f3
3599
3600         changelog_setup
3601         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f1
3602         wait_request_state $fid1 ARCHIVE SUCCEED
3603
3604         $LFS hsm_archive $f2
3605         wait_request_state $fid2 ARCHIVE SUCCEED
3606
3607         rm $f1 || error "rm $f1 failed"
3608
3609         local flags=$(changelog_get_flags ${MDT[0]} UNLNK $fid1)
3610
3611         local target=0x3
3612         [[ $flags == $target ]] ||
3613                 error "Changelog flag is $flags not $target"
3614
3615         mv $f3 $f2 || error "mv $f3 $f2 failed"
3616
3617         flags=$(changelog_get_flags ${MDT[0]} RENME $fid2)
3618
3619         target=0x3
3620         [[ $flags == $target ]] ||
3621                 error "Changelog flag is $flags not $target"
3622
3623         cleanup
3624 }
3625 run_test 226 "changelog for last rm/mv with exiting archive"
3626
3627 check_flags_changes() {
3628         local f=$1
3629         local fid=$2
3630         local hsm_flag=$3
3631         local fst=$4
3632         local cnt=$5
3633
3634         local target=0x280
3635         $LFS hsm_set --$hsm_flag $f ||
3636                 error "Cannot set $hsm_flag on $f"
3637         local flags=($(changelog_get_flags ${MDT[0]} HSM $fid))
3638         local seen=${#flags[*]}
3639         cnt=$((fst + cnt))
3640         [[ $seen == $cnt ]] ||
3641                 error "set $hsm_flag: Changelog events $seen != $cnt"
3642         [[ ${flags[$((cnt - 1))]} == $target ]] ||
3643                 error "set $hsm_flag: Changelog flags are "\
3644                         "${flags[$((cnt - 1))]} not $target"
3645
3646         $LFS hsm_clear --$hsm_flag $f ||
3647                 error "Cannot clear $hsm_flag on $f"
3648         flags=($(changelog_get_flags ${MDT[0]} HSM $fid))
3649         seen=${#flags[*]}
3650         cnt=$(($cnt + 1))
3651         [[ $cnt == $seen ]] ||
3652                 error "clear $hsm_flag: Changelog events $seen != $cnt"
3653
3654         [[ ${flags[$((cnt - 1))]} == $target ]] ||
3655                 error "clear $hsm_flag: Changelog flag is "\
3656                         "${flags[$((cnt - 1))]} not $target"
3657 }
3658
3659 test_227() {
3660         # test needs a running copytool
3661         copytool_setup
3662         changelog_setup
3663
3664         mkdir -p $DIR/$tdir
3665         typeset -a flags
3666
3667         for i in norelease noarchive exists archived
3668         do
3669                 local f=$DIR/$tdir/$tfile-$i
3670                 local fid=$(copy_file /etc/passwd $f)
3671                 check_flags_changes $f $fid $i 0 1
3672         done
3673
3674         f=$DIR/$tdir/$tfile---lost
3675         fid=$(copy_file /etc/passwd $f)
3676         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3677         wait_request_state $fid ARCHIVE SUCCEED
3678         check_flags_changes $f $fid lost 3 1
3679
3680         cleanup
3681 }
3682 run_test 227 "changelog when explicit setting of HSM flags"
3683
3684 test_228() {
3685         # test needs a running copytool
3686         copytool_setup
3687
3688         local fid=$(make_small_sync $DIR/$tfile)
3689         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $DIR/$tfile
3690         wait_request_state $fid ARCHIVE SUCCEED
3691
3692         $LFS hsm_release $DIR/$tfile
3693         check_hsm_flags $DIR/$tfile "0x0000000d"
3694
3695         filefrag $DIR/$tfile | grep " 1 extent found" ||
3696                 error "filefrag on released file must return only one extent"
3697
3698         # only newer versions of cp detect sparse files by stat/FIEMAP
3699         # (LU-2580)
3700         cp --sparse=auto $DIR/$tfile $DIR/$tfile.2 ||
3701                 error "copying $DIR/$tfile"
3702         cmp $DIR/$tfile $DIR/$tfile.2 || error "comparing copied $DIR/$tfile"
3703
3704         $LFS hsm_release $DIR/$tfile
3705         check_hsm_flags $DIR/$tfile "0x0000000d"
3706
3707         mkdir -p $DIR/$tdir || error "mkdir $tdir failed"
3708
3709         tar cf - --sparse $DIR/$tfile | tar xvf - -C $DIR/$tdir ||
3710                 error "tar failed"
3711         cmp $DIR/$tfile $DIR/$tdir/$DIR/$tfile ||
3712                 error "comparing untarred $DIR/$tfile"
3713
3714         rm -f $DIR/$tfile $DIR/$tfile.2 ||
3715                 error "rm $DIR/$tfile or $DIR/$tfile.2 failed"
3716         copytool_cleanup
3717 }
3718 run_test 228 "On released file, return extend to FIEMAP. For [cp,tar] --sparse"
3719
3720 test_250() {
3721         # test needs a running copytool
3722         copytool_setup
3723
3724         mkdir -p $DIR/$tdir
3725         local maxrequest=$(get_hsm_param max_requests)
3726         local rqcnt=$(($maxrequest * 3))
3727         local i=""
3728
3729         cdt_disable
3730         for i in $(seq -w 1 $rqcnt); do
3731                 rm -f $DIR/$tdir/$i
3732                 dd if=/dev/urandom of=$DIR/$tdir/$i bs=1M count=10 conv=fsync
3733         done
3734         # we do it in 2 steps, so all requests arrive at the same time
3735         for i in $(seq -w 1 $rqcnt); do
3736                 $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $DIR/$tdir/$i
3737         done
3738         cdt_enable
3739         local cnt=$rqcnt
3740         local wt=$rqcnt
3741         while [[ $cnt != 0 || $wt != 0 ]]; do
3742                 sleep 1
3743                 cnt=$(do_facet $SINGLEMDS "$LCTL get_param -n\
3744                         $HSM_PARAM.actions |\
3745                         grep STARTED | grep -v CANCEL | wc -l")
3746                 [[ $cnt -le $maxrequest ]] ||
3747                         error "$cnt > $maxrequest too many started requests"
3748                 wt=$(do_facet $SINGLEMDS "$LCTL get_param\
3749                         $HSM_PARAM.actions |\
3750                         grep WAITING | wc -l")
3751                 echo "max=$maxrequest started=$cnt waiting=$wt"
3752         done
3753
3754         copytool_cleanup
3755 }
3756 run_test 250 "Coordinator max request"
3757
3758 test_251() {
3759         # test needs a running copytool
3760         copytool_setup
3761
3762         mkdir -p $DIR/$tdir
3763         local f=$DIR/$tdir/$tfile
3764         local fid=$(make_large_for_cancel $f)
3765
3766         cdt_disable
3767         # to have a short test
3768         local old_to=$(get_hsm_param active_request_timeout)
3769         set_hsm_param active_request_timeout 4
3770         # to be sure the cdt will wake up frequently so
3771         # it will be able to cancel the "old" request
3772         local old_loop=$(get_hsm_param loop_period)
3773         set_hsm_param loop_period 2
3774         cdt_enable
3775
3776         $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
3777         wait_request_state $fid ARCHIVE STARTED
3778         sleep 5
3779         wait_request_state $fid ARCHIVE CANCELED
3780
3781         set_hsm_param active_request_timeout $old_to
3782         set_hsm_param loop_period $old_loop
3783
3784         copytool_cleanup
3785 }
3786 run_test 251 "Coordinator request timeout"
3787
3788 test_300() {
3789         # the only way to test ondisk conf is to restart MDS ...
3790         echo "Stop coordinator and remove coordinator state at mount"
3791         # stop coordinator
3792         cdt_shutdown
3793         # clean on disk conf set by default
3794         cdt_clear_mount_state
3795         cdt_check_state stopped
3796
3797         # check cdt still off after umount/remount
3798         fail $SINGLEMDS
3799         cdt_check_state stopped
3800
3801         echo "Set coordinator start at mount, and start coordinator"
3802         cdt_set_mount_state enabled
3803
3804         # check cdt is on
3805         cdt_check_state enabled
3806
3807         # check cdt still on after umount/remount
3808         fail $SINGLEMDS
3809         cdt_check_state enabled
3810
3811         # we are back to original state (cdt started at mount)
3812 }
3813 run_test 300 "On disk coordinator state kept between MDT umount/mount"
3814
3815 test_301() {
3816         local ai=$(get_hsm_param default_archive_id)
3817         local new=$((ai + 1))
3818
3819         set_hsm_param default_archive_id $new -P
3820         fail $SINGLEMDS
3821         local res=$(get_hsm_param default_archive_id)
3822
3823         # clear value
3824         set_hsm_param default_archive_id "" "-P -d"
3825
3826         [[ $new == $res ]] || error "Value after MDS restart is $res != $new"
3827 }
3828 run_test 301 "HSM tunnable are persistent"
3829
3830 test_302() {
3831         local ai=$(get_hsm_param default_archive_id)
3832         local new=$((ai + 1))
3833
3834         # stop coordinator
3835         cdt_shutdown
3836
3837         set_hsm_param default_archive_id $new -P
3838
3839         local mdtno
3840         for mdtno in $(seq 1 $MDSCOUNT); do
3841                 fail mds${mdtno}
3842         done
3843
3844         # check cdt is on
3845         cdt_check_state enabled
3846
3847         local res=$(get_hsm_param default_archive_id)
3848
3849         # clear value
3850         set_hsm_param default_archive_id "" "-P -d"
3851
3852         [[ $new == $res ]] || error "Value after MDS restart is $res != $new"
3853 }
3854 run_test 302 "HSM tunnable are persistent when CDT is off"
3855
3856 test_400() {
3857         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
3858
3859         copytool_setup
3860
3861         mkdir -p $DIR/$tdir
3862
3863         local dir_mdt0=$DIR/$tdir/mdt0
3864         local dir_mdt1=$DIR/$tdir/mdt1
3865
3866         # create 1 dir per MDT
3867         $LFS mkdir -i 0 $dir_mdt0 || error "lfs mkdir"
3868         $LFS mkdir -i 1 $dir_mdt1 || error "lfs mkdir"
3869
3870         # create 1 file in each MDT
3871         local fid1=$(make_small $dir_mdt0/$tfile)
3872         local fid2=$(make_small $dir_mdt1/$tfile)
3873
3874         # check that hsm request on mdt0 is sent to the right MDS
3875         $LFS hsm_archive $dir_mdt0/$tfile || error "lfs hsm_archive"
3876         wait_request_state $fid1 ARCHIVE SUCCEED 0 &&
3877                 echo "archive successful on mdt0"
3878
3879         # check that hsm request on mdt1 is sent to the right MDS
3880         $LFS hsm_archive $dir_mdt1/$tfile || error "lfs hsm_archive"
3881         wait_request_state $fid2 ARCHIVE SUCCEED 1 &&
3882                 echo "archive successful on mdt1"
3883
3884         copytool_cleanup
3885         # clean test files and directories
3886         rm -rf $dir_mdt0 $dir_mdt1
3887 }
3888 run_test 400 "Single request is sent to the right MDT"
3889
3890 test_401() {
3891         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
3892
3893         copytool_setup
3894
3895         mkdir -p $DIR/$tdir
3896
3897         local dir_mdt0=$DIR/$tdir/mdt0
3898         local dir_mdt1=$DIR/$tdir/mdt1
3899
3900         # create 1 dir per MDT
3901         $LFS mkdir -i 0 $dir_mdt0 || error "lfs mkdir"
3902         $LFS mkdir -i 1 $dir_mdt1 || error "lfs mkdir"
3903
3904         # create 1 file in each MDT
3905         local fid1=$(make_small $dir_mdt0/$tfile)
3906         local fid2=$(make_small $dir_mdt1/$tfile)
3907
3908         # check that compound requests are shunt to the rights MDTs
3909         $LFS hsm_archive $dir_mdt0/$tfile $dir_mdt1/$tfile ||
3910                 error "lfs hsm_archive"
3911         wait_request_state $fid1 ARCHIVE SUCCEED 0 &&
3912                 echo "archive successful on mdt0"
3913         wait_request_state $fid2 ARCHIVE SUCCEED 1 &&
3914                 echo "archive successful on mdt1"
3915
3916         copytool_cleanup
3917         # clean test files and directories
3918         rm -rf $dir_mdt0 $dir_mdt1
3919 }
3920 run_test 401 "Compound requests split and sent to their respective MDTs"
3921
3922 mdc_change_state() # facet, MDT_pattern, activate|deactivate
3923 {
3924         local facet=$1
3925         local pattern="$2"
3926         local state=$3
3927         local node=$(facet_active_host $facet)
3928         local mdc
3929         for mdc in $(do_facet $facet "$LCTL dl | grep -E ${pattern}-mdc" |
3930                         awk '{print $4}'); do
3931                 echo "$3 $mdc on $node"
3932                 do_facet $facet "$LCTL --device $mdc $state" || return 1
3933         done
3934 }
3935
3936 test_402() {
3937         # make sure there is no running copytool
3938         copytool_cleanup
3939
3940         # deactivate all mdc on agent1
3941         mdc_change_state $SINGLEAGT "MDT000." "deactivate"
3942
3943         copytool_setup $SINGLEAGT
3944
3945         check_agent_unregistered "uuid" # match any agent
3946
3947         # no expected running copytool
3948         search_copytools $agent && error "Copytool start should have failed"
3949
3950         # reactivate MDCs
3951         mdc_change_state $SINGLEAGT "MDT000." "activate"
3952 }
3953 run_test 402 "Copytool start fails if all MDTs are inactive"
3954
3955 test_403() {
3956         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
3957
3958         # make sure there is no running copytool
3959         copytool_cleanup
3960
3961         local agent=$(facet_active_host $SINGLEAGT)
3962         local uuid=$(do_rpc_nodes $agent get_client_uuid | cut -d' ' -f2)
3963
3964         # deactivate all mdc for MDT0001
3965         mdc_change_state $SINGLEAGT "MDT0001" "deactivate"
3966
3967         copytool_setup
3968         # check the agent is registered on MDT0000, and not on MDT0001
3969         check_agent_registered_by_mdt $uuid 0
3970         check_agent_unregistered_by_mdt $uuid 1
3971
3972         # check running copytool process
3973         search_copytools $agent || error "No running copytools on $agent"
3974
3975         # reactivate all mdc for MDT0001
3976         mdc_change_state $SINGLEAGT "MDT0001" "activate"
3977
3978         # make sure the copytool is now registered to all MDTs
3979         check_agent_registered $uuid
3980
3981         copytool_cleanup
3982 }
3983 run_test 403 "Copytool starts with inactive MDT and register on reconnect"
3984
3985 test_404() {
3986         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
3987
3988         copytool_setup
3989
3990         # create files on both MDT0000 and MDT0001
3991         mkdir -p $DIR/$tdir
3992
3993         local dir_mdt0=$DIR/$tdir/mdt0
3994         $LFS mkdir -i 0 $dir_mdt0 || error "lfs mkdir"
3995
3996         # create 1 file on mdt0
3997         local fid1=$(make_small $dir_mdt0/$tfile)
3998
3999         # deactivate all mdc for MDT0001
4000         mdc_change_state $SINGLEAGT "MDT0001" "deactivate"
4001
4002         # send an HSM request for files in MDT0000
4003         $LFS hsm_archive $dir_mdt0/$tfile || error "lfs hsm_archive"
4004
4005         # check for completion of files in MDT0000
4006         wait_request_state $fid1 ARCHIVE SUCCEED 0 &&
4007                 echo "archive successful on mdt0"
4008
4009         # reactivate all mdc for MDT0001
4010         mdc_change_state $SINGLEAGT "MDT0001" "activate"
4011
4012         copytool_cleanup
4013         # clean test files and directories
4014         rm -rf $dir_mdt0
4015 }
4016 run_test 404 "Inactive MDT does not block requests for active MDTs"
4017
4018 copytool_cleanup
4019
4020 complete $SECONDS
4021 check_and_cleanup_lustre
4022 exit_status