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