cleanup() {
copytool_monitor_cleanup
copytool_cleanup
- changelog_cleanup
cdt_set_sanity_policy
}
done
}
-changelog_setup() {
- _CL_USERS=()
- local mdtno
- for mdtno in $(seq 1 $MDSCOUNT); do
- local idx=$(($mdtno - 1))
- local cl_user=$(do_facet mds${mdtno} $LCTL \
- --device ${MDT[$idx]} \
- changelog_register -n)
- _CL_USERS+=($cl_user)
- do_facet mds${mdtno} lctl set_param \
- mdd.${MDT[$idx]}.changelog_mask="+hsm"
- $LFS changelog_clear ${MDT[$idx]} $cl_user 0
- done
-}
-
-changelog_cleanup() {
- local mdtno
- for mdtno in $(seq 1 $MDSCOUNT); do
- local idx=$(($mdtno - 1))
- [[ -z ${_CL_USERS[$idx]} ]] && continue
- $LFS changelog_clear ${MDT[$idx]} ${_CL_USERS[$idx]} 0
- do_facet mds${mdtno} lctl --device ${MDT[$idx]} \
- changelog_deregister ${_CL_USERS[$idx]}
- done
- _CL_USERS=()
-}
-
-changelog_get_flags() {
- local mdt=$1
- local cltype=$2
- local fid=$3
-
- $LFS changelog $mdt | awk "/$cltype/ && /t=\[$fid\]/ {print \$5}"
-}
-
get_hsm_param() {
local param=$1
local val=$(do_facet $SINGLEMDS $LCTL get_param -n $HSM_PARAM.$param)
local f=$DIR/$tdir/$tfile
local fid=$(copy_file /etc/passwd $f)
- changelog_setup
+ changelog_register
$LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
wait_request_state $fid ARCHIVE SUCCEED
- local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
- changelog_cleanup
-
- local target=0x0
- [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
+ changelog_find -type HSM -target-fid $fid -flags 0x0 ||
+ error "The expected changelog was not emitted"
}
run_test 220A "Changelog for archive"
local f=$DIR/$tdir/$tfile
local fid=$(copy_file /etc/passwd $f)
- changelog_setup
+ changelog_register
# block copytool operations to allow for HSM request to be
# submitted and file be unlinked (CDT will find object removed)
wait_request_state $fid ARCHIVE FAILED
- local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
- changelog_cleanup
-
# HE_ARCHIVE|ENOENT
- local target=0x2
- [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
+ changelog_find -type HSM -target-fid $fid -flags 0x2 ||
+ error "The expected changelog was not emitted"
}
run_test 220a "Changelog for failed archive"
fid=$(make_custom_file_for_progress $f 103 1048576)
[ $? != 0 ] && skip "not enough free space" && return
- changelog_setup
+ changelog_register
$LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
wait_request_state $fid ARCHIVE STARTED
wait_request_state $fid ARCHIVE CANCELED
wait_request_state $fid CANCEL SUCCEED
- local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
-
- local target=0x7d
- [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
+ changelog_find -type HSM -target-fid $fid -flags 0x7d ||
+ error "The expected changelog was not emitted"
}
run_test 221 "Changelog for archive canceled"
import_file $tdir/$tfile $f
local fid=$(path2fid $f)
- changelog_setup
+ changelog_register
$LFS hsm_restore $f
wait_request_state $fid RESTORE SUCCEED
- local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
-
- local target=0x80
- [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
+ changelog_find -type HSM -target-fid $fid -flags 0x80 ||
+ error "The expected changelog was not emitted"
copytool_cleanup
}
local f=$DIR/$tdir/$tfile
local fid=$(copy_file /etc/passwd $f)
- changelog_setup
+ changelog_register
$LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
wait_request_state $fid ARCHIVE SUCCEED
$LFS hsm_release $f
wait_request_state $fid RESTORE SUCCEED
- local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
-
- local target=0x80
- [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
+ changelog_find -type HSM -target-fid $fid -flags 0x80 ||
+ error "The expected changelog was not emitted"
}
run_test 222b "Changelog for implicit restore"
import_file $tdir/$tfile $f
local fid=$(path2fid $f)
- changelog_setup
+ changelog_register
# block copytool operations to allow for HSM request to be
# submitted and file be unlinked (CDT will find object removed)
wait_request_state $fid RESTORE FAILED
- local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
-
# HE_RESTORE|ENOENT
- local target=0x82
- [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
+ changelog_find -type HSM -target-fid $fid -flags 0x82 ||
+ error "The expected changelog was not emitted"
copytool_cleanup
}
local f=$DIR/$tdir/$tfile
local fid=$(copy_file /etc/passwd $f)
- changelog_setup
+ changelog_register
$LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
wait_request_state $fid ARCHIVE SUCCEED
$LFS hsm_release $f
wait_request_state $fid RESTORE FAILED
- local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
-
# HE_RESTORE|ENOENT
- local target=0x82
- [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
+ changelog_find -type HSM -target-fid $fid -flags 0x82 ||
+ error "The expected changelog was not emitted"
copytool_cleanup
}
local f=$DIR/$tdir/$tfile
create_archive_file $tdir/$tfile
- changelog_setup
+ changelog_register
import_file $tdir/$tfile $f
local fid=$(path2fid $f)
wait_request_state $fid RESTORE CANCELED
wait_request_state $fid CANCEL SUCCEED
- local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
-
- local target=0xfd
- [[ $flags == $target ]] ||
- error "Changelog flag is $flags not $target"
+ changelog_find -type HSM -target-fid $fid -flags 0xfd ||
+ error "The expected changelog was not emitted"
cleanup
}
fid=$(make_custom_file_for_progress $f 39 1000000)
[ $? != 0 ] && skip "not enough free space" && return
- changelog_setup
+ changelog_register
$LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
wait_request_state $fid ARCHIVE SUCCEED
$LFS hsm_release $f
wait_request_state $fid RESTORE CANCELED
wait_request_state $fid CANCEL SUCCEED
- local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
-
- local target=0xfd
- [[ $flags == $target ]] ||
- error "Changelog flag is $flags not $target"
+ changelog_find -type HSM -target-fid $fid -flags 0xfd ||
+ error "The expected changelog was not emitted"
copytool_cleanup
}
local f=$DIR/$tdir/$tfile
local fid=$(copy_file /etc/passwd $f)
- changelog_setup
+ changelog_register
$LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
wait_request_state $fid ARCHIVE SUCCEED
$LFS hsm_remove $f
wait_request_state $fid REMOVE SUCCEED
- local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -n 1)
-
- local target=0x200
- [[ $flags == $target ]] ||
- error "Changelog flag is $flags not $target"
+ changelog_find -type HSM -target-fid $fid -flags 0x200 ||
+ error "The expected changelog was not emitted"
}
run_test 224A "Changelog for remove"
local f=$DIR/$tdir/$tfile
local fid=$(copy_file /etc/passwd $f)
- changelog_setup
+ changelog_register
$LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
wait_request_state $fid ARCHIVE SUCCEED
wait_request_state $fid REMOVE FAILED
- local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -n 1)
-
- # HE_REMOVE|ENOENT
- local target=0x202
- [[ $flags == $target ]] ||
- error "Changelog flag is $flags not $target"
+ # HE_REMOVE|ENOENT=0x202
+ changelog_find -type HSM -target-fid $fid -flags 0x202 ||
+ error "The expected changelog was not emitted"
cleanup
}
fid=$(make_custom_file_for_progress $f 39 1000000)
[ $? != 0 ] && skip "not enough free space" && return
- changelog_setup
+ changelog_register
$LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
wait_request_state $fid ARCHIVE SUCCEED
wait_request_state $fid REMOVE CANCELED
wait_request_state $fid CANCEL SUCCEED
- flags=$(changelog_get_flags ${MDT[0]} RENME $fid2)
- local flags=$($LFS changelog ${MDT[0]} | grep HSM | grep $fid |
- tail -n 1 | awk '{print $5}')
-
- local target=0x27d
- [[ $flags == $target ]] ||
- error "Changelog flag is $flags not $target"
+ changelog_find -type HSM -target-fid $fid -flags 0x27d
+ error "The expected changelog was not emitted"
}
run_test 225 "Changelog for remove canceled"
local fid2=$(copy_file /etc/passwd $f2)
copy_file /etc/passwd $f3
- changelog_setup
+ changelog_register
$LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f1
wait_request_state $fid1 ARCHIVE SUCCEED
rm $f1 || error "rm $f1 failed"
- local flags=$(changelog_get_flags ${MDT[0]} UNLNK $fid1)
-
- local target=0x3
- [[ $flags == $target ]] ||
- error "Changelog flag is $flags not $target"
+ changelog_dump
+ changelog_find -type UNLNK -target-fid $fid1 -flags 0x3 ||
+ error "The expected changelog was not emitted"
mv $f3 $f2 || error "mv $f3 $f2 failed"
- flags=$(changelog_get_flags ${MDT[0]} RENME $fid2)
-
- target=0x3
- [[ $flags == $target ]] ||
- error "Changelog flag is $flags not $target"
+ changelog_find -type RENME -target-fid $fid2 -flags 0x3 ||
+ error "The expected changelog was not emitted"
}
run_test 226 "changelog for last rm/mv with exiting archive"
-check_flags_changes() {
- local f=$1
- local fid=$2
- local hsm_flag=$3
- local fst=$4
- local cnt=$5
-
+# This is just a utility function to clarify what test_227 does
+__test_227()
+{
local target=0x280
- $LFS hsm_set --$hsm_flag $f ||
- error "Cannot set $hsm_flag on $f"
- local flags=($(changelog_get_flags ${MDT[0]} HSM $fid))
- local seen=${#flags[*]}
- cnt=$((fst + cnt))
- [[ $seen == $cnt ]] ||
- error "set $hsm_flag: Changelog events $seen != $cnt"
- [[ ${flags[$((cnt - 1))]} == $target ]] ||
- error "set $hsm_flag: Changelog flags are "\
- "${flags[$((cnt - 1))]} not $target"
-
- $LFS hsm_clear --$hsm_flag $f ||
- error "Cannot clear $hsm_flag on $f"
- flags=($(changelog_get_flags ${MDT[0]} HSM $fid))
- seen=${#flags[*]}
- cnt=$(($cnt + 1))
- [[ $cnt == $seen ]] ||
- error "clear $hsm_flag: Changelog events $seen != $cnt"
-
- [[ ${flags[$((cnt - 1))]} == $target ]] ||
- error "clear $hsm_flag: Changelog flag is "\
- "${flags[$((cnt - 1))]} not $target"
+
+ "$LFS" "$action" --$flag "$file" ||
+ error "Cannot ${action#hsm_} $flag on '$file'"
+
+ # Only one changelog should be produced
+ local entries="$(changelog_find -type HSM -target-fid $fid)"
+ [ $(wc -l <<< "$entries") -eq $((++count)) ] ||
+ error "lfs $action --$flag '$file' produced more than one" \
+ "changelog record"
+
+ # Parse the last changelog record
+ local entry="$(tail -n 1 <<< "$entries")"
+ eval local -A changelog=$(changelog2array $entry)
+
+ # Also check the flags match what is expected
+ [[ ${changelog[flags]} == $target ]] ||
+ error "Changelog flag is '${changelog[flags]}', not $target"
}
test_227() {
- # test needs a running copytool
- copytool setup
- changelog_setup
+ local file="$DIR/$tdir/$tfile"
+ local fid=$(create_empty_file "$file")
+ local count=0
- mkdir -p $DIR/$tdir
- typeset -a flags
+ changelog_register
- for i in norelease noarchive exists archived
- do
- local f=$DIR/$tdir/$tfile-$i
- local fid=$(copy_file /etc/passwd $f)
- check_flags_changes $f $fid $i 0 1
- done
+ for flag in norelease noarchive exists archived lost; do
+ if [ "$flag" == lost ]; then
+ # The flag "lost" only works on an archived file
+ "$LFS" hsm_set --archived "$file"
+ ((count++))
+ fi
- f=$DIR/$tdir/$tfile---lost
- fid=$(copy_file /etc/passwd $f)
- $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
- wait_request_state $fid ARCHIVE SUCCEED
- check_flags_changes $f $fid lost 3 1
+ action="hsm_set" __test_227
+ action="hsm_clear" __test_227
+ done
}
run_test 227 "changelog when explicit setting of HSM flags"
local LIBPATH="/usr/lib/lustre/tests:/usr/lib64/lustre/tests:"
local TESTPATH="$RLUSTRE/tests:"
local RPATH="PATH=${TESTPATH}${LIBPATH}${PATH}:/sbin:/bin:/usr/sbin:"
- do_nodesv $list "${RPATH} NAME=${NAME} sh rpc.sh $@ "
+ do_nodesv $list "${RPATH} NAME=${NAME} bash rpc.sh $@ "
}
wait_clients_import_state () {
tail -1
}
+# Prints a changelog record produced by "lfs changelog" as an associative array
+#
+# Example:
+# $> changelog2array 16 01CREAT 10:28:46.968438800 2018.03.09 0x0 \
+# t=[0x200000401:0x10:0x0] j=touch.501 ef=0xf u=501:501 \
+# nid=0@lo p=[0x200000007:0x1:0x0] blob
+# ([index]='16' [type]='CREAT' [time]='10:28:46.968438800'
+# [date]='2018.03.09' [flags]=0x0 ['target-fid']='[0x200000401:0x10:0x0]'
+# ['jobid']='touch.501' ['extra-flags']='0x0f' [uid]='0' ['gid']='0'
+# ['nid']='0@lo' ['parent-fid']='[0x200000007:0x1:0x0]')
+#
+# Note that the changelog record is not quoted
+# Also note that the line breaks in the output were only added for readability
+#
+# Typically, you want to eval the output of the command to fill an actual
+# associative array, like this:
+# $> eval declare -A changelog=$(changelog2array $entry)
+#
+# It can then be accessed like any bash associative array:
+# $> echo "${changelog[index]}" "${changelog[type]}" "${changelog[flags]}"
+# 16 CREAT 0x0
+# $> echo "${changelog[uid]}":"${changelog[gid]}"
+# 501:501
+#
+changelog2array()
+{
+ # Start the array
+ printf '('
+
+ # A changelog, as printed by "lfs changelog" typically looks like this:
+ # <index> <type> <time> <date> <flags> <key1=value1> <key2=value2> ...
+
+ # Parse the positional part of the changelog
+
+ # changelog_dump() prefixes records with their mdt's name
+ local index="${1##*.}"
+
+ printf "[index]='%s' [type]='%s' [time]='%s' [date]='%s' [flags]='%s'" \
+ "$index" "${2:2}" "$3" "$4" "$5"
+
+ # Parse the key/value part of the changelog
+ for arg in "${@:5}"; do
+ # Check it matches a key=value syntax
+ [[ "$arg" =~ ^[[:alpha:]]+= ]] || continue
+
+ local key="${arg%%=*}"
+ local value="${arg#*=}"
+
+ case "$key" in
+ u)
+ # u is actually for uid AND gid: u=UID:GID
+ printf " [uid]='%s'" "${value%:*}"
+ key=gid
+ value="${value#*:}"
+ ;;
+ t)
+ key=target-fid
+ value="${value#[}"
+ value="${value%]}"
+ ;;
+ j)
+ key=jobid
+ ;;
+ p)
+ key=parent-fid
+ value="${value#[}"
+ value="${value%]}"
+ ;;
+ ef)
+ key=extra-flags
+ ;;
+ *)
+ ;;
+ esac
+
+ printf " ['%s']='%s'" "$key" "$value"
+ done
+
+ # end the array
+ printf ')'
+}
+
+# Format and print a changelog record
+#
+# Interpreted sequences are:
+# %% a single %
+# %f the "flags" attribute of a changelog record
+__changelog_printf()
+{
+ local format="$1"
+
+ local -i i
+ for ((i = 0; i < ${#format}; i++)); do
+ local char="${format:$i:1}"
+ if [ "$char" != % ]; then
+ printf '%c' "$char"
+ continue
+ fi
+
+ i+=1
+ char="${format:$i:1}"
+ case "$char" in
+ f)
+ printf '%s' "${changelog[flags]}"
+ ;;
+ %)
+ printf '%'
+ ;;
+ esac
+ done
+ printf '\n'
+}
+
+# Filter changelog records
+changelog_find()
+{
+ local -A filter
+ local action='print'
+ local format
+
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ -print)
+ action='print'
+ ;;
+ -printf)
+ action='printf'
+ format="$2"
+ shift
+ ;;
+ -*)
+ filter[${1#-}]="$2"
+ shift
+ ;;
+ esac
+ shift
+ done
+
+ local found=false
+ local record
+ changelog_dump | { while read -r record; do
+ eval local -A changelog=$(changelog2array $record)
+ for key in "${!filter[@]}"; do
+ case "$key" in
+ *)
+ [ "${changelog[$key]}" == "${filter[$key]}" ]
+ ;;
+ esac || continue 2
+ done
+
+ found=true
+
+ case "${action:-print}" in
+ print)
+ printf '%s\n' "$record"
+ ;;
+ printf)
+ __changelog_printf "$format"
+ ;;
+ esac
+ done; $found; }
+}
+
restore_layout() {
local dir=$1
local layout=$2