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