X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Ftests%2Ftest-framework.sh;h=a04e20edcfb777fbd70aefe8d88da365b769c5d3;hp=f046b8777477929adf5d983f9b30c9857f965776;hb=87546548eb11584e686f3ba4c3111ca7e35b0159;hpb=ff353fef1eca3cc4d4b492b9591c819c00f4e8dc diff --git a/lustre/tests/test-framework.sh b/lustre/tests/test-framework.sh old mode 100644 new mode 100755 index f046b87..a04e20e --- a/lustre/tests/test-framework.sh +++ b/lustre/tests/test-framework.sh @@ -10,7 +10,6 @@ export EJOURNAL=${EJOURNAL:-""} export REFORMAT=${REFORMAT:-""} export WRITECONF=${WRITECONF:-""} export VERBOSE=${VERBOSE:-false} -export CATASTROPHE=${CATASTROPHE:-/proc/sys/lnet/catastrophe} export GSS=false export GSS_KRB5=false export GSS_PIPEFS=false @@ -24,6 +23,7 @@ export JOBID_VAR=${JOBID_VAR:-"procname_uid"} # or "existing" or "disable" export LOAD_LLOOP=${LOAD_LLOOP:-false} #export PDSH="pdsh -S -Rssh -w" +export MOUNT_CMD=${MOUNT_CMD:-"mount -t lustre"} # function used by scripts run on remote nodes LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)} @@ -90,16 +90,21 @@ print_summary () { local total= local status=Unfinished if [ -f $log ]; then - skipped=$(grep excluded $log | awk '{ printf " %s", $3 }' | sed 's/test_//g') - slow=$(egrep "^PASS|^FAIL" $log | tr -d "("| sed s/s\)$//g | sort -nr -k 3 | head -5 | awk '{ print $2":"$3"s" }') - total=$(grep duration $log | awk '{ print $2}') - if [ "${!O}" = "done" ]; then - status=Done - fi - if $DDETAILS; then - local durations=$(egrep "^PASS|^FAIL" $log | tr -d "("| sed s/s\)$//g | awk '{ print $2":"$3"|" }') - details=$(printf "%s\n%s %s %s\n" "$details" "DDETAILS" "$O" "$(echo $durations)") - fi + skipped=$(grep excluded $log | awk '{ printf " %s", $3 }' | + sed 's/test_//g') + slow=$(egrep "^PASS|^FAIL" $log | tr -d "("| sed s/s\)$//g | + sort -nr -k 3 | head -n5 | awk '{ print $2":"$3"s" }') + total=$(grep duration $log | awk '{ print $2 }') + if [ "${!O}" = "done" ]; then + status=Done + fi + if $DDETAILS; then + local durations=$(egrep "^PASS|^FAIL" $log | + tr -d "("| sed s/s\)$//g | + awk '{ print $2":"$3"|" }') + details=$(printf "%s\n%s %s %s\n" "$details" \ + "DDETAILS" "$O" "$(echo $durations)") + fi fi printf "$form" $status "$O" "${total}" "E=$skipped" printf "$form" "-" "-" "-" "S=$(echo $slow)" @@ -220,6 +225,7 @@ init_test_env() { [ ! -f "$LST" ] && export LST=$(which lst) export SGPDDSURVEY=${SGPDDSURVEY:-"$LUSTRE/../lustre-iokit/sgpdd-survey/sgpdd-survey")} [ ! -f "$SGPDDSURVEY" ] && export SGPDDSURVEY=$(which sgpdd-survey) + export MCREATE=${MCREATE:-mcreate} # Ubuntu, at least, has a truncate command in /usr/bin # so fully path our truncate command. export TRUNCATE=${TRUNCATE:-$LUSTRE/tests/truncate} @@ -355,7 +361,7 @@ version_code() { echo -n "$((($1 << 16) | ($2 << 8) | $3))" } -export LINUX_VERSION=$(uname -r | sed -e "s/[-.]/ /3" -e "s/ .*//") +export LINUX_VERSION=$(uname -r | sed -e "s/\([0-9]*\.[0-9]*\.[0-9]*\).*/\1/") export LINUX_VERSION_CODE=$(version_code ${LINUX_VERSION//\./ }) module_loaded () { @@ -364,7 +370,7 @@ module_loaded () { # Load a module on the system where this is running. # -# Synopsis: load_module module_name [module arguments for insmod/modprobe] +# usage: load_module module_name [module arguments for insmod/modprobe] # # If module arguments are not given but MODOPTS_ is set, then its value # will be used as the arguments. Otherwise arguments will be obtained from @@ -410,22 +416,24 @@ load_module() { [ $# -gt 0 ] && echo "${module} options: '$*'" - # Note that insmod will ignore anything in modprobe.conf, which is why we're - # passing options on the command-line. - if [ "$BASE" == "lnet_selftest" ] && \ - [ -f ${LUSTRE}/../lnet/selftest/${module}${EXT} ]; then - insmod ${LUSTRE}/../lnet/selftest/${module}${EXT} - elif [ -f ${LUSTRE}/${module}${EXT} ]; then - insmod ${LUSTRE}/${module}${EXT} "$@" - else - # must be testing a "make install" or "rpm" installation - # note failed to load ptlrpc_gss is considered not fatal - if [ "$BASE" == "ptlrpc_gss" ]; then - modprobe $BASE "$@" 2>/dev/null || echo "gss/krb5 is not supported" - else - modprobe $BASE "$@" - fi - fi + # Note that insmod will ignore anything in modprobe.conf, which is why + # we're passing options on the command-line. + if [[ "$BASE" == "lnet_selftest" ]] && + [[ -f ${LUSTRE}/../lnet/selftest/${module}${EXT} ]]; then + insmod ${LUSTRE}/../lnet/selftest/${module}${EXT} + elif [[ -f ${LUSTRE}/${module}${EXT} ]]; then + [[ "$BASE" != "ptlrpc_gss" ]] || modprobe sunrpc + insmod ${LUSTRE}/${module}${EXT} "$@" + else + # must be testing a "make install" or "rpm" installation + # note failed to load ptlrpc_gss is considered not fatal + if [[ "$BASE" == "ptlrpc_gss" ]]; then + modprobe $BASE "$@" 2>/dev/null || + echo "gss/krb5 is not supported" + else + modprobe $BASE "$@" + fi + fi } llite_lloop_enabled() { @@ -484,6 +492,13 @@ load_modules_local() { [ "$PTLDEBUG" ] && lctl set_param debug="$PTLDEBUG" [ "$SUBSYSTEM" ] && lctl set_param subsystem_debug="${SUBSYSTEM# }" load_module ../lnet/lnet/lnet + case $NETTYPE in + o2ib) + LNETLND="o2iblnd/ko2iblnd" + ;; + *) + ;; + esac LNETLND=${LNETLND:-"socklnd/ksocklnd"} load_module ../lnet/klnds/$LNETLND load_module obdclass/obdclass @@ -524,20 +539,37 @@ load_modules_local() { load_module osp/osp fi - - load_module llite/lustre - llite_lloop_enabled && load_module llite/llite_lloop - [ -d /r ] && OGDB=${OGDB:-"/r/tmp"} - OGDB=${OGDB:-$TMP} - rm -f $OGDB/ogdb-$HOSTNAME - $LCTL modules > $OGDB/ogdb-$HOSTNAME - - # 'mount' doesn't look in $PATH, just sbin - if [ -f $LUSTRE/utils/mount.lustre ] && \ - ! grep -qe "/sbin/mount\.lustre " /proc/mounts; then - [ ! -f /sbin/mount.lustre ] && touch /sbin/mount.lustre - mount --bind $LUSTRE/utils/mount.lustre /sbin/mount.lustre || true - fi + load_module llite/lustre + llite_lloop_enabled && load_module llite/llite_lloop + [ -d /r ] && OGDB=${OGDB:-"/r/tmp"} + OGDB=${OGDB:-$TMP} + rm -f $OGDB/ogdb-$HOSTNAME + $LCTL modules > $OGDB/ogdb-$HOSTNAME + + # 'mount' doesn't look in $PATH, just sbin + local mount_lustre=$LUSTRE/utils/mount.lustre + if [ -f $mount_lustre ]; then + local sbin_mount=/sbin/mount.lustre + if grep -qw "$sbin_mount" /proc/mounts; then + cmp -s $mount_lustre $sbin_mount || umount $sbin_mount + fi + if ! grep -qw "$sbin_mount" /proc/mounts; then + [ ! -f "$sbin_mount" ] && touch "$sbin_mount" + if [ ! -s "$sbin_mount" -a -w "$sbin_mount" ]; then + cat <<- EOF > "$sbin_mount" + #!/bin/sh + #STUB MARK + echo "This $sbin_mount just a mountpoint." 1>&2 + echo "It is never supposed to be run." 1>&2 + logger -p emerg -- "using stub $sbin_mount $@" + exit 1 + EOF + chmod a+x $sbin_mount + fi + mount --bind $mount_lustre $sbin_mount || + error "can't bind $mount_lustre to $sbin_mount" + fi + fi } load_modules () { @@ -581,16 +613,17 @@ unload_modules() { fi fi - if grep -qe "/sbin/mount\.lustre" /proc/mounts; then - umount /sbin/mount.lustre || true - [ -w /sbin/mount.lustre -a ! -s /sbin/mount.lustre ] && \ - rm -f /sbin/mount.lustre || true - fi + local sbin_mount=/sbin/mount.lustre + if grep -qe "$sbin_mount " /proc/mounts; then + umount $sbin_mount || true + [ -s $sbin_mount ] && ! grep -q "STUB MARK" $sbin_mount || + rm -f $sbin_mount + fi - check_mem_leak || return 254 + check_mem_leak || return 254 - echo "modules unloaded." - return 0 + echo "modules unloaded." + return 0 } fs_log_size() { @@ -648,7 +681,6 @@ start_gss_daemons() { fi local list=$(comma_list $(mdts_nodes)) - echo "Starting gss daemon on mds: $list" do_nodes $list "$LSVCGSSD -v" || return 1 if $GSS_PIPEFS; then @@ -685,7 +717,7 @@ start_gss_daemons() { stop_gss_daemons() { local list=$(comma_list $(mdts_nodes)) - + send_sigint $list lsvcgssd lgssd list=$(comma_list $(osts_nodes)) @@ -702,10 +734,13 @@ init_gss() { module_loaded ptlrpc_gss || error_exit "init_gss : GSS=$GSS, but gss/krb5 is not supported!" fi - start_gss_daemons || error_exit "start gss daemon failed! rc=$?" + if $GSS_KRB5; then + start_gss_daemons || error_exit "start gss daemon failed! rc=$?" + fi if [ -n "$LGSS_KEYRING_DEBUG" ]; then - echo $LGSS_KEYRING_DEBUG > /proc/fs/lustre/sptlrpc/gss/lgss_keyring/debug_level + lctl set_param -n \ + sptlrpc.gss.lgss_keyring.debug_level=$LGSS_KEYRING_DEBUG fi fi } @@ -789,6 +824,25 @@ node_fstypes() { echo -n $fstypes } +facet_index() { + local facet=$1 + local num=$(facet_number $facet) + local index + + if [[ $(facet_type $facet) = OST ]]; then + index=OSTINDEX${num} + if [[ -n "${!index}" ]]; then + echo -n ${!index} + return + fi + + index=${OST_INDICES[num - 1]} + fi + + [[ -n "$index" ]] || index=$((num - 1)) + echo -n $index +} + devicelabel() { local facet=$1 local dev=$2 @@ -900,6 +954,33 @@ zpool_name() { } # +# Create ZFS storage pool. +# +create_zpool() { + local facet=$1 + local poolname=$2 + local vdev=$3 + shift 3 + local opts=${@:-"-o cachefile=none"} + + do_facet $facet "$ZPOOL list -H $poolname >/dev/null 2>&1 || + $ZPOOL create -f $opts $poolname $vdev" +} + +# +# Create ZFS file system. +# +create_zfs() { + local facet=$1 + local dataset=$2 + shift 2 + local opts=${@:-"-o mountpoint=legacy"} + + do_facet $facet "$ZFS list -H $dataset >/dev/null 2>&1 || + $ZFS create $opts $dataset" +} + +# # Export ZFS storage pool. # Before exporting the pool, all datasets within the pool should be unmounted. # @@ -919,6 +1000,22 @@ export_zpool() { } # +# Destroy ZFS storage pool. +# Destroy the given pool and free up any devices for other use. This command +# tries to unmount any active datasets before destroying the pool. +# -f Force any active datasets contained within the pool to be unmounted. +# +destroy_zpool() { + local facet=$1 + local poolname=${2:-$(zpool_name $facet)} + + if [[ -n "$poolname" ]]; then + do_facet $facet "! $ZPOOL list -H $poolname >/dev/null 2>&1 || + $ZPOOL destroy -f $poolname" + fi +} + +# # Import ZFS storage pool. # Force importing, even if the pool appears to be potentially active. # @@ -1094,7 +1191,7 @@ mount_facet() { if [ -f $TMP/test-lu482-trigger ]; then RC=2 else - do_facet ${facet} "mkdir -p $mntpt; mount -t lustre $opts \ + do_facet ${facet} "mkdir -p $mntpt; $MOUNT_CMD $opts \ ${!dev} $mntpt" RC=${PIPESTATUS[0]} fi @@ -1103,6 +1200,12 @@ mount_facet() { else set_default_debug_facet $facet + if [[ $facet == mds* ]]; then + do_facet $facet \ + lctl set_param -n mdt.${FSNAME}*.enable_remote_dir=1 \ + 2>/dev/null + fi + label=$(devicelabel ${facet} ${!dev}) [ -z "$label" ] && echo no label for ${!dev} && exit 1 eval export ${facet}_svc=${label} @@ -1127,12 +1230,19 @@ start() { eval export ${facet}failover_dev=$device fi - local mntpt=$(facet_mntpt $facet) - do_facet ${facet} mkdir -p $mntpt - eval export ${facet}_MOUNT=$mntpt - mount_facet ${facet} - RC=$? - return $RC + local mntpt=$(facet_mntpt $facet) + do_facet ${facet} mkdir -p $mntpt + eval export ${facet}_MOUNT=$mntpt + mount_facet ${facet} + RC=$? + + if [[ $facet == mds* ]]; then + do_facet $facet \ + lctl set_param -n mdt.${FSNAME}*.enable_remote_dir=1 \ + 2>/dev/null + fi + + return $RC } stop() { @@ -1196,7 +1306,7 @@ quota_type() { rc=$? do_nodes $(comma_list $(osts_nodes)) \ lctl get_param obdfilter.${fsname}-OST*.quota_type || rc=$? - return $rc + return $rc } # XXX This function is kept for interoperability with old server (< 2.3.50), @@ -1375,17 +1485,19 @@ setup_quota(){ zconf_mount() { local client=$1 local mnt=$2 - local OPTIONS=${3:-$MOUNTOPT} + local opts=${3:-$MOUNT_OPTS} + opts=${opts:+-o $opts} + local flags=${4:-$MOUNT_FLAGS} local device=$MGSNID:/$FSNAME if [ -z "$mnt" -o -z "$FSNAME" ]; then - echo Bad zconf mount command: opt=$OPTIONS dev=$device mnt=$mnt + echo Bad zconf mount command: opt=$flags $opts dev=$device mnt=$mnt exit 1 fi - echo "Starting client: $client: $OPTIONS $device $mnt" + echo "Starting client: $client: $flags $opts $device $mnt" do_node $client mkdir -p $mnt - do_node $client mount -t lustre $OPTIONS $device $mnt || return 1 + do_node $client $MOUNT_CMD $flags $opts $device $mnt || return 1 set_default_debug_nodes $client @@ -1481,22 +1593,24 @@ sanity_mount_check () { zconf_mount_clients() { local clients=$1 local mnt=$2 - local OPTIONS=${3:-$MOUNTOPT} + local opts=${3:-$MOUNT_OPTS} + opts=${opts:+-o $opts} + local flags=${4:-$MOUNT_FLAGS} local device=$MGSNID:/$FSNAME if [ -z "$mnt" -o -z "$FSNAME" ]; then - echo Bad zconf mount command: opt=$OPTIONS dev=$device mnt=$mnt + echo Bad zconf mount command: opt=$flags $opts dev=$device mnt=$mnt exit 1 fi - echo "Starting client $clients: $OPTIONS $device $mnt" + echo "Starting client $clients: $flags $opts $device $mnt" do_nodes $clients " running=\\\$(mount | grep -c $mnt' '); rc=0; if [ \\\$running -eq 0 ] ; then mkdir -p $mnt; - mount -t lustre $OPTIONS $device $mnt; + $MOUNT_CMD $flags $opts $device $mnt; rc=\\\$?; fi; exit \\\$rc" || return ${PIPESTATUS[0]} @@ -1586,7 +1700,7 @@ facet_up() { local host=${2:-$(facet_host $facet)} local label=$(convert_facet2label $facet) - do_node $host $LCTL dl | awk '{print $4}' | grep -q -x $label + do_node $host $LCTL dl | awk '{ print $4 }' | grep -q "^$label\$" } facets_up_on_host () { @@ -1879,18 +1993,22 @@ stop_client_loads() { # verify that lustre actually cleaned up properly cleanup_check() { - [ -f $CATASTROPHE ] && [ `cat $CATASTROPHE` -ne 0 ] && \ - error "LBUG/LASSERT detected" - BUSY=`dmesg | grep -i destruct || true` - if [ "$BUSY" ]; then - echo "$BUSY" 1>&2 - [ -e $TMP/debug ] && mv $TMP/debug $TMP/debug-busy.`date +%s` - exit 205 - fi + VAR=$(lctl get_param -n catastrophe 2>&1) + if [ $? = 0 ] ; then + if [ $VAR != 0 ]; then + error "LBUG/LASSERT detected" + fi + fi + BUSY=$(dmesg | grep -i destruct || true) + if [ -n "$BUSY" ]; then + echo "$BUSY" 1>&2 + [ -e $TMP/debug ] && mv $TMP/debug $TMP/debug-busy.$(date +%s) + exit 205 + fi - check_mem_leak || exit 204 + check_mem_leak || exit 204 - [ "`lctl dl 2> /dev/null | wc -l`" -gt 0 ] && lctl dl && + [[ $($LCTL dl 2>/dev/null | wc -l) -gt 0 ]] && $LCTL dl && echo "$TESTSUITE: lustre didn't clean up..." 1>&2 && return 202 || true @@ -1919,6 +2037,7 @@ wait_update () { local sleep=1 local print=10 + PREV_RESULT=$(do_node $node "$TEST") while [ true ]; do RESULT=$(do_node $node "$TEST") if [[ "$RESULT" == "$FINAL" ]]; then @@ -1958,50 +2077,60 @@ sync_all_data() { wait_delete_completed_mds() { local MAX_WAIT=${1:-20} + # for ZFS, waiting more time for DMUs to be committed + local ZFS_WAIT=${2:-5} local mds2sync="" - local stime=`date +%s` + local stime=$(date +%s) local etime local node local changes # find MDS with pending deletions for node in $(mdts_nodes); do - changes=$(do_node $node "lctl get_param -n osc.*MDT*.sync_*" \ + changes=$(do_node $node "$LCTL get_param -n osc.*MDT*.sync_*" \ 2>/dev/null | calc_sum) - if [ -z "$changes" ] || [ $changes -eq 0 ]; then + if [[ $changes -eq 0 ]]; then continue fi mds2sync="$mds2sync $node" done - if [ "$mds2sync" == "" ]; then + if [ -z "$mds2sync" ]; then return fi mds2sync=$(comma_list $mds2sync) # sync MDS transactions - do_nodes $mds2sync "lctl set_param -n osd*.*MD*.force_sync 1" + do_nodes $mds2sync "$LCTL set_param -n osd*.*MD*.force_sync 1" # wait till all changes are sent and commmitted by OSTs # for ldiskfs space is released upon execution, but DMU # do this upon commit local WAIT=0 - while [ "$WAIT" -ne "$MAX_WAIT" ]; do - changes=$(do_nodes $mds2sync "lctl get_param -n osc.*MDT*.sync_*" \ - | calc_sum) + while [[ $WAIT -ne $MAX_WAIT ]]; do + changes=$(do_nodes $mds2sync \ + "$LCTL get_param -n osc.*MDT*.sync_*" | calc_sum) #echo "$node: $changes changes on all" - if [ "$changes" -eq "0" ]; then - etime=`date +%s` + if [[ $changes -eq 0 ]]; then + etime=$(date +%s) #echo "delete took $((etime - stime)) seconds" + + # the occupied disk space will be released + # only after DMUs are committed + if [[ $(facet_fstype $SINGLEMDS) == zfs ]]; then + echo "sleep $ZFS_WAIT for ZFS OSD" + sleep $ZFS_WAIT + fi + return fi sleep 1 WAIT=$(( WAIT + 1)) done - etime=`date +%s` + etime=$(date +%s) echo "Delete is not completed in $((etime - stime)) seconds" - do_nodes $mds2sync "lctl get_param osc.*MDT*.sync_*" + do_nodes $mds2sync "$LCTL get_param osc.*MDT*.sync_*" } wait_for_host() { @@ -2224,7 +2353,7 @@ client_evicted() { ! client_up $1 } -client_reconnect() { +client_reconnect_try() { uname -n >> $MOUNT/recon if [ -z "$CLIENTS" ]; then df $MOUNT; uname -n >> $MOUNT/recon @@ -2237,6 +2366,14 @@ client_reconnect() { rm $MOUNT/recon } +client_reconnect() { + # one client_reconnect_try call does not always do the job... + while true ; do + client_reconnect_try && break + sleep 1 + done +} + affected_facets () { local facet=$1 @@ -2547,7 +2684,7 @@ hostlist_expand() { done myList="${myList%* }"; - # We can select an object at a offset in the list + # We can select an object at an offset in the list [ $# -eq 2 ] && { cnt=0 for item in $myList; do @@ -2569,7 +2706,11 @@ facet_host() { varname=${facet}_HOST if [ -z "${!varname}" ]; then if [ "${facet:0:3}" == "ost" ]; then - eval export ${facet}_HOST=${ost_HOST} + local fh=${facet%failover}_HOST + eval export ${facet}_HOST=${!fh} + if [ -z "${!varname}" ]; then + eval export ${facet}_HOST=${ost_HOST} + fi elif [ "${facet:0:3}" == "mdt" -o \ "${facet:0:3}" == "mds" -o \ "${facet:0:3}" == "mgs" ]; then @@ -2737,7 +2878,7 @@ get_env_vars() { local facet for var in ${!MODOPTS_*}; do - value=${!var} + value=${!var//\"/\\\"} echo -n " ${var}=\"$value\"" done @@ -2757,6 +2898,12 @@ get_env_vars() { if [ -n "$FSTYPE" ]; then echo -n " FSTYPE=$FSTYPE" fi + + for var in LNETLND NETTYPE; do + if [ -n "${!var}" ]; then + echo -n " $var=${!var}" + fi + done } do_nodes() { @@ -2891,7 +3038,7 @@ ostvdevname() { eval VDEVPTR="";; zfs ) #if $OSTDEVn isn't defined, default is $OSTDEVBASE{n} - # Device formated by zfs + # Device formatted by zfs DEVNAME=OSTDEV$num eval VDEVPTR=${!DEVNAME:=${OSTDEVBASE}${num}};; * ) @@ -2901,7 +3048,7 @@ ostvdevname() { echo -n $VDEVPTR } -# Logical device formated for lustre +# Logical device formatted for lustre mdsdevname() { local num=$1 local DEVNAME=MDSDEV$num @@ -2935,7 +3082,7 @@ mdsvdevname() { eval VDEVPTR="";; zfs ) # if $MDSDEVn isn't defined, default is $MDSDEVBASE{n} - # Device formated by ZFS + # Device formatted by ZFS local DEVNAME=MDSDEV$num eval VDEVPTR=${!DEVNAME:=${MDSDEVBASE}${num}};; * ) @@ -3160,17 +3307,13 @@ mkfs_opts() { local dev=$2 local fsname=${3:-"$FSNAME"} local type=$(facet_type $facet) - local index=$(($(facet_number $facet) - 1)) + local index=$(facet_index $facet) local fstype=$(facet_fstype $facet) local host=$(facet_host $facet) local opts local fs_mkfs_opts local var - if [ $type == MGS ] && combined_mgs_mds; then - return 1 - fi - if [ $type == MGS ] || ( [ $type == MDS ] && [ "$dev" == $(mgsdevname) ] && [ "$host" == "$(facet_host mgs)" ] ); then @@ -3200,6 +3343,12 @@ mkfs_opts() { opts+=${L_GETIDENTITY:+" --param=mdt.identity_upcall=$L_GETIDENTITY"} if [ $fstype == ldiskfs ]; then + # Check for wide striping + if [ $OSTCOUNT -gt 160 ]; then + MDSJOURNALSIZE=${MDSJOURNALSIZE:-4096} + fs_mkfs_opts+="-O large_xattr" + fi + fs_mkfs_opts+=${MDSJOURNALSIZE:+" -J size=$MDSJOURNALSIZE"} if [ ! -z $EJOURNAL ]; then fs_mkfs_opts+=${MDSJOURNALSIZE:+" device=$EJOURNAL"} @@ -3240,6 +3389,24 @@ mkfs_opts() { echo -n "$opts" } +check_ost_indices() { + local index_count=${#OST_INDICES[@]} + [[ $index_count -eq 0 || $OSTCOUNT -le $index_count ]] && return 0 + + # OST count is greater than the index count in $OST_INDEX_LIST. + # We need check whether there are duplicate indices. + local i + local j + local index + for i in $(seq $((index_count + 1)) $OSTCOUNT); do + index=$(facet_index ost$i) + for j in $(seq 0 $((index_count - 1))); do + [[ $index -ne ${OST_INDICES[j]} ]] || + error "ost$i has the same index $index as ost$((j+1))" + done + done +} + formatall() { local quiet @@ -3266,6 +3433,8 @@ formatall() { ${quiet:+>/dev/null} || exit 10 done + export OST_INDICES=($(hostlist_expand "$OST_INDEX_LIST")) + check_ost_indices for num in $(seq $OSTCOUNT); do echo "Format ost$num: $(ostdevname $num)" add ost$num $(mkfs_opts ost$num $(ostdevname ${num})) \ @@ -3782,6 +3951,13 @@ check_and_setup_lustre() { set_flavor_all $SEC fi + #Enable remote MDT create for testing + for num in $(seq $MDSCOUNT); do + do_facet mds$num \ + lctl set_param -n mdt.${FSNAME}*.enable_remote_dir=1 \ + 2>/dev/null + done + if [ "$ONLY" == "setup" ]; then exit 0 fi @@ -3795,10 +3971,10 @@ restore_mount () { } cleanup_mount () { - local clients=${CLIENTS:-$HOSTNAME} - local mntpt=$1 + local clients=${CLIENTS:-$HOSTNAME} + local mntpt=$1 - zconf_umount_clients $clients $mntpt + zconf_umount_clients $clients $mntpt } cleanup_and_setup_lustre() { @@ -3822,8 +3998,7 @@ get_mnt_devs() { if [ "$type" == ost ]; then devs=$(get_osd_param $node "" mntdev) else - devs=$(do_node $node \ - "lctl get_param -n osd-*.$FSNAME-M*.mntdev") + devs=$(do_node $node $LCTL get_param -n osd-*.$FSNAME-M*.mntdev) fi for dev in $devs; do case $dev in @@ -3836,33 +4011,56 @@ get_mnt_devs() { # Get all of the server target devices. get_svr_devs() { - local i + local node + local i - # MDT device - MDTDEV=$(get_mnt_devs $(mdts_nodes) mdt) + # Master MDS parameters used by lfsck + MDTNODE=$(facet_active_host $SINGLEMDS) + MDTDEV=$(echo $(get_mnt_devs $MDTNODE mdt) | awk '{print $1}') - # OST devices - i=0 - for node in $(osts_nodes); do - OSTDEVS[i]=$(get_mnt_devs $node ost) - i=$((i + 1)) - done + # MDT devices + i=0 + for node in $(mdts_nodes); do + MDTDEVS[i]=$(get_mnt_devs $node mdt) + i=$((i + 1)) + done + + # OST devices + i=0 + for node in $(osts_nodes); do + OSTDEVS[i]=$(get_mnt_devs $node ost) + i=$((i + 1)) + done } # Run e2fsck on MDT or OST device. run_e2fsck() { - local node=$1 - local target_dev=$2 - local extra_opts=$3 + local node=$1 + local target_dev=$2 + local extra_opts=$3 + local cmd="$E2FSCK -d -v -t -t -f $extra_opts $target_dev" + local log=$TMP/e2fsck.log + local rc=0 - df > /dev/null # update statfs data on disk - local cmd="$E2FSCK -d -v -t -t -f $extra_opts $target_dev" - echo $cmd - local rc=0 - do_node $node $cmd || rc=$? - [ $rc -le $FSCK_MAX_ERR ] || \ - error "$cmd returned $rc, should be <= $FSCK_MAX_ERR" - return 0 + echo $cmd + do_node $node $cmd 2>&1 | tee $log + rc=${PIPESTATUS[0]} + if [ -n "$(grep "DNE mode isn't supported" $log)" ]; then + rm -f $log + if [ $MDSCOUNT -gt 1 ]; then + skip "DNE mode isn't supported!" + cleanupall + exit_status + else + error "It's not DNE mode." + fi + fi + rm -f $log + + [ $rc -le $FSCK_MAX_ERR ] || + error "$cmd returned $rc, should be <= $FSCK_MAX_ERR" + + return 0 } # @@ -3891,22 +4089,23 @@ check_shared_dir() { # Run e2fsck on MDT and OST(s) to generate databases used for lfsck. generate_db() { - local i - local ostidx - local dev + local i + local ostidx + local dev + local node [[ $(lustre_version_code $SINGLEMDS) -ne $(version_code 2.2.0) ]] || { skip "Lustre 2.2.0 lacks the patch for LU-1255"; exit 0; } - check_shared_dir $SHARED_DIRECTORY || - error "$SHARED_DIRECTORY isn't a shared directory" - - export MDSDB=$SHARED_DIRECTORY/mdsdb - export OSTDB=$SHARED_DIRECTORY/ostdb + check_shared_dir $SHARED_DIRECTORY || + error "$SHARED_DIRECTORY isn't a shared directory" - [ $MDSCOUNT -eq 1 ] || error "CMD is not supported" + export MDSDB=$SHARED_DIRECTORY/mdsdb + export OSTDB=$SHARED_DIRECTORY/ostdb - run_e2fsck $(mdts_nodes) $MDTDEV "-n --mdsdb $MDSDB" + # DNE is not supported, so when running e2fsck on a DNE filesystem, + # we only pass master MDS parameters. + run_e2fsck $MDTNODE $MDTDEV "-n --mdsdb $MDSDB" i=0 ostidx=0 @@ -3936,7 +4135,7 @@ run_lfsck_remote() { fi #Run lfsck echo $cmd - do_node $node $cmd || rc=$? + do_node $client $cmd || rc=$? #Umount if necessary if ! $mounted; then zconf_umount $client $MOUNT || @@ -3972,6 +4171,60 @@ run_lfsck() { return $rc } +dump_file_contents() { + local nodes=$1 + local dir=$2 + local logname=$3 + local node + + if [ -z "$nodes" -o -z "$dir" -o -z "$logname" ]; then + error_noexit false \ + "Invalid parameters for dump_file_contents()" + return 1 + fi + for node in ${nodes}; do + do_node $node "for i in \\\$(find $dir -type f); do + echo ====\\\${i}=======================; + cat \\\${i}; + done" >> ${logname}.${node}.log + done +} + +dump_command_output() { + local nodes=$1 + local cmd=$2 + local logname=$3 + local node + + if [ -z "$nodes" -o -z "$cmd" -o -z "$logname" ]; then + error_noexit false \ + "Invalid parameters for dump_command_output()" + return 1 + fi + + for node in ${nodes}; do + do_node $node "echo ====${cmd}=======================; + $cmd" >> ${logname}.${node}.log + done +} + +log_zfs_info() { + local logname=$1 + + # dump file contents from /proc/spl in case of zfs test + if [ "$(facet_fstype ost1)" = "zfs" ]; then + dump_file_contents "$(osts_nodes)" "/proc/spl" "${logname}" + dump_command_output \ + "$(osts_nodes)" "zpool events -v" "${logname}" + fi + + if [ "$(facet_fstype $SINGLEMDS)" = "zfs" ]; then + dump_file_contents "$(mdts_nodes)" "/proc/spl" "${logname}" + dump_command_output \ + "$(mdts_nodes)" "zpool events -v" "${logname}" + fi +} + check_and_cleanup_lustre() { if [ "$LFSCK_ALWAYS" = "yes" -a "$TESTSUITE" != "lfsck" ]; then get_svr_devs @@ -3985,18 +4238,18 @@ check_and_cleanup_lustre() { [ "$ENABLE_QUOTA" ] && restore_quota || true fi - if [ "$I_UMOUNTED2" = "yes" ]; then - restore_mount $MOUNT2 || error "restore $MOUNT2 failed" - fi + if [ "$I_UMOUNTED2" = "yes" ]; then + restore_mount $MOUNT2 || error "restore $MOUNT2 failed" + fi - if [ "$I_MOUNTED2" = "yes" ]; then - cleanup_mount $MOUNT2 - fi + if [ "$I_MOUNTED2" = "yes" ]; then + cleanup_mount $MOUNT2 + fi - if [ "$I_MOUNTED" = "yes" ]; then - cleanupall -f || error "cleanup failed" - unset I_MOUNTED - fi + if [ "$I_MOUNTED" = "yes" ]; then + cleanupall -f || error "cleanup failed" + unset I_MOUNTED + fi } ####### @@ -4194,20 +4447,20 @@ drop_request() { drop_reply() { # OBD_FAIL_MDS_ALL_REPLY_NET - RC=0 - do_facet $SINGLEMDS lctl set_param fail_loc=0x122 - do_facet client "$@" || RC=$? - do_facet $SINGLEMDS lctl set_param fail_loc=0 - return $RC + RC=0 + do_facet $SINGLEMDS $LCTL set_param fail_loc=0x122 + eval "$@" || RC=$? + do_facet $SINGLEMDS $LCTL set_param fail_loc=0 + return $RC } drop_reint_reply() { # OBD_FAIL_MDS_REINT_NET_REP - RC=0 - do_facet $SINGLEMDS lctl set_param fail_loc=0x119 - do_facet client "$@" || RC=$? - do_facet $SINGLEMDS lctl set_param fail_loc=0 - return $RC + RC=0 + do_facet $SINGLEMDS $LCTL set_param fail_loc=0x119 + eval "$@" || RC=$? + do_facet $SINGLEMDS $LCTL set_param fail_loc=0 + return $RC } drop_update_reply() { @@ -4223,12 +4476,16 @@ drop_update_reply() { pause_bulk() { #define OBD_FAIL_OST_BRW_PAUSE_BULK 0x214 - RC=0 - do_facet ost1 lctl set_param fail_loc=0x214 - do_facet client "$1" || RC=$? - do_facet client "sync" - do_facet ost1 lctl set_param fail_loc=0 - return $RC + RC=0 + + local timeout=${2:-0} + # default is (obd_timeout / 4) if unspecified + echo "timeout is $timeout/$2" + do_facet ost1 lctl set_param fail_val=$timeout fail_loc=0x80000214 + do_facet client "$1" || RC=$? + do_facet client "sync" + do_facet ost1 lctl set_param fail_loc=0 + return $RC } drop_ldlm_cancel() { @@ -4243,21 +4500,51 @@ drop_ldlm_cancel() { return $RC } -drop_bl_callback() { +drop_bl_callback_once() { + local rc=0 + do_facet client lctl set_param ldlm.namespaces.*.early_lock_cancel=0 #define OBD_FAIL_LDLM_BL_CALLBACK_NET 0x305 - RC=0 do_facet client lctl set_param fail_loc=0x80000305 - do_facet client "$@" || RC=$? + do_facet client "$@" || rc=$? do_facet client lctl set_param fail_loc=0 - return $RC + do_facet client lctl set_param fail_val=0 + do_facet client lctl set_param ldlm.namespaces.*.early_lock_cancel=1 + return $rc +} + +drop_bl_callback() { + rc=0 + do_facet client lctl set_param ldlm.namespaces.*.early_lock_cancel=0 +#define OBD_FAIL_LDLM_BL_CALLBACK_NET 0x305 + do_facet client lctl set_param fail_loc=0x305 + do_facet client "$@" || rc=$? + do_facet client lctl set_param fail_loc=0 + do_facet client lctl set_param fail_val=0 + do_facet client lctl set_param ldlm.namespaces.*.early_lock_cancel=1 + return $rc } drop_ldlm_reply() { #define OBD_FAIL_LDLM_REPLY 0x30c RC=0 - do_facet $SINGLEMDS lctl set_param fail_loc=0x30c + local list=$(comma_list $(mdts_nodes) $(osts_nodes)) + do_nodes $list lctl set_param fail_loc=0x30c + do_facet client "$@" || RC=$? - do_facet $SINGLEMDS lctl set_param fail_loc=0 + + do_nodes $list lctl set_param fail_loc=0 + return $RC +} + +drop_ldlm_reply_once() { +#define OBD_FAIL_LDLM_REPLY 0x30c + RC=0 + local list=$(comma_list $(mdts_nodes) $(osts_nodes)) + do_nodes $list lctl set_param fail_loc=0x8000030c + + do_facet client "$@" || RC=$? + + do_nodes $list lctl set_param fail_loc=0 return $RC } @@ -4270,15 +4557,36 @@ clear_failloc() { } set_nodes_failloc () { - do_nodes $(comma_list $1) lctl set_param fail_loc=$2 + do_nodes $(comma_list $1) lctl set_param fail_val=0 fail_loc=$2 } cancel_lru_locks() { $LCTL mark "cancel_lru_locks $1 start" - for d in `lctl get_param -N ldlm.namespaces.*.lru_size | egrep -i $1`; do - $LCTL set_param -n $d=clear - done - $LCTL get_param ldlm.namespaces.*.lock_unused_count | egrep -i $1 | grep -v '=0' + + if [ $1 != "MGC" ]; then + for d in $(lctl get_param -N ldlm.namespaces.*.lru_size | + egrep -i $1); do + $LCTL set_param -n $d=clear + done + $LCTL get_param ldlm.namespaces.*.lock_unused_count | egrep -i $1 | + grep -v '=0' + else + for d in $(find \ + /{proc,sys}/fs/lustre/ldlm/namespaces/*$1*/lru_size \ + 2> /dev/null); do + echo "clear" > $d + done + + for d in $(find \ + /{proc,sys}/fs/lustre/ldlm/namespaces/*$1*/lock_unused_count \ + 2> /dev/null); do + if [ $(cat $d) != 0 ]; then + echo "ldlm.namespaces.$(echo "$d" | + cut -f 7 -d'/').lock_unused_count=$(cat $d)" + fi + done + fi + $LCTL mark "cancel_lru_locks $1 stop" } @@ -4299,6 +4607,13 @@ lru_resize_disable() lctl set_param ldlm.namespaces.*$1*.lru_size $(default_lru_size) } +flock_is_enabled() +{ + local RC=0 + [ -z "$(mount | grep "$MOUNT.*flock" | grep -v noflock)" ] && RC=1 + return $RC +} + pgcache_empty() { local FILE for FILE in `lctl get_param -N "llite.*.dump_page_cache"`; do @@ -4348,7 +4663,7 @@ stop_full_debug_logging() { } # prints bash call stack -log_trace_dump() { +print_stack_trace() { echo " Trace dump:" for (( i=1; i < ${#BASH_LINENO[*]} ; i++ )) ; do local s=${BASH_SOURCE[$i]} @@ -4374,7 +4689,7 @@ error_noexit() { log " ${TESTSUITE} ${TESTNAME}: @@@@@@ ${TYPE}: $@ " - log_trace_dump + print_stack_trace >&2 mkdir -p $LOGDIR # We need to dump the logs on all nodes @@ -4451,10 +4766,16 @@ skip() { build_test_filter() { EXCEPT="$EXCEPT $(testslist_filter)" - [ "$ONLY" ] && log "only running test `echo $ONLY`" - for O in $ONLY; do - eval ONLY_${O}=true - done + for O in $ONLY; do + if [[ $O = [0-9]*-[0-9]* ]]; then + for num in $(seq $(echo $O | tr '-' ' ')); do + eval ONLY_$num=true + done + else + eval ONLY_${O}=true + fi + done + [ "$EXCEPT$ALWAYS_EXCEPT" ] && \ log "excepting tests: `echo $EXCEPT $ALWAYS_EXCEPT`" [ "$EXCEPT_SLOW" ] && \ @@ -4493,68 +4814,68 @@ export ALWAYS_SKIPPED= # run or not run. These need to be documented... # run_test() { - assert_DIR - - export base=`basetest $1` - if [ ! -z "$ONLY" ]; then - testname=ONLY_$1 - if [ ${!testname}x != x ]; then - [ "$LAST_SKIPPED" ] && echo "" && LAST_SKIPPED= - run_one_logged $1 "$2" - return $? - fi - testname=ONLY_$base - if [ ${!testname}x != x ]; then - [ "$LAST_SKIPPED" ] && echo "" && LAST_SKIPPED= - run_one_logged $1 "$2" - return $? - fi - LAST_SKIPPED="y" - return 0 - fi + assert_DIR + + export base=$(basetest $1) + if [ -n "$ONLY" ]; then + testname=ONLY_$1 + if [ ${!testname}x != x ]; then + [ -n "$LAST_SKIPPED" ] && echo "" && LAST_SKIPPED= + run_one_logged $1 "$2" + return $? + fi + testname=ONLY_$base + if [ ${!testname}x != x ]; then + [ -n "$LAST_SKIPPED" ] && echo "" && LAST_SKIPPED= + run_one_logged $1 "$2" + return $? + fi + LAST_SKIPPED="y" + return 0 + fi LAST_SKIPPED="y" ALWAYS_SKIPPED="y" - testname=EXCEPT_$1 - if [ ${!testname}x != x ]; then - TESTNAME=test_$1 skip "skipping excluded test $1" - return 0 - fi - testname=EXCEPT_$base - if [ ${!testname}x != x ]; then - TESTNAME=test_$1 skip "skipping excluded test $1 (base $base)" - return 0 - fi - testname=EXCEPT_ALWAYS_$1 - if [ ${!testname}x != x ]; then - TESTNAME=test_$1 skip "skipping ALWAYS excluded test $1" - return 0 - fi - testname=EXCEPT_ALWAYS_$base - if [ ${!testname}x != x ]; then - TESTNAME=test_$1 skip "skipping ALWAYS excluded test $1 (base $base)" - return 0 - fi - testname=EXCEPT_SLOW_$1 - if [ ${!testname}x != x ]; then - TESTNAME=test_$1 skip "skipping SLOW test $1" - return 0 - fi - testname=EXCEPT_SLOW_$base - if [ ${!testname}x != x ]; then - TESTNAME=test_$1 skip "skipping SLOW test $1 (base $base)" - return 0 - fi + testname=EXCEPT_$1 + if [ ${!testname}x != x ]; then + TESTNAME=test_$1 skip "skipping excluded test $1" + return 0 + fi + testname=EXCEPT_$base + if [ ${!testname}x != x ]; then + TESTNAME=test_$1 skip "skipping excluded test $1 (base $base)" + return 0 + fi + testname=EXCEPT_ALWAYS_$1 + if [ ${!testname}x != x ]; then + TESTNAME=test_$1 skip "skipping ALWAYS excluded test $1" + return 0 + fi + testname=EXCEPT_ALWAYS_$base + if [ ${!testname}x != x ]; then + TESTNAME=test_$1 skip "skipping ALWAYS excluded test $1 (base $base)" + return 0 + fi + testname=EXCEPT_SLOW_$1 + if [ ${!testname}x != x ]; then + TESTNAME=test_$1 skip "skipping SLOW test $1" + return 0 + fi + testname=EXCEPT_SLOW_$base + if [ ${!testname}x != x ]; then + TESTNAME=test_$1 skip "skipping SLOW test $1 (base $base)" + return 0 + fi - LAST_SKIPPED= - ALWAYS_SKIPPED= - run_one_logged $1 "$2" + LAST_SKIPPED= + ALWAYS_SKIPPED= + run_one_logged $1 "$2" - return $? + return $? } log() { - echo "$*" + echo "$*" >&2 module_loaded lnet || load_modules local MSG="$*" @@ -4609,7 +4930,8 @@ check_mds() { reset_fail_loc () { echo -n "Resetting fail_loc on all nodes..." - do_nodes $(comma_list $(nodes_list)) "lctl set_param -n fail_loc=0 2>/dev/null || true" + do_nodes $(comma_list $(nodes_list)) "lctl set_param -n fail_loc=0 \ + fail_val=0 2>/dev/null || true" echo done. } @@ -4630,34 +4952,35 @@ banner() { } # -# Run a single test function and cleanup after it. +# Run a single test function and cleanup after it. # # This function should be run in a subshell so the test func can # exit() without stopping the whole script. # run_one() { - local testnum=$1 - local message=$2 - tfile=f.${TESTSUITE}.${testnum} - export tdir=d0.${TESTSUITE}/d${base} - export TESTNAME=test_$testnum - local SAVE_UMASK=`umask` - umask 0022 - - banner "test $testnum: $message" - test_${testnum} || error "test_$testnum failed with $?" - cd $SAVE_PWD - reset_fail_loc - check_grant ${testnum} || error "check_grant $testnum failed with $?" - check_catastrophe || error "LBUG/LASSERT detected" + local testnum=$1 + local message=$2 + export tfile=f${testnum}.${TESTSUITE} + export tdir=d${testnum}.${TESTSUITE} + export TESTNAME=test_$testnum + local SAVE_UMASK=`umask` + umask 0022 + + banner "test $testnum: $message" + test_${testnum} || error "test_$testnum failed with $?" + cd $SAVE_PWD + reset_fail_loc + check_grant ${testnum} || error "check_grant $testnum failed with $?" + check_catastrophe || error "LBUG/LASSERT detected" if [ "$PARALLEL" != "yes" ]; then ps auxww | grep -v grep | grep -q multiop && error "multiop still running" fi - unset TESTNAME - unset tdir - umask $SAVE_UMASK - return 0 + unset TESTNAME + unset tdir + unset tfile + umask $SAVE_UMASK + return 0 } # @@ -4667,14 +4990,16 @@ run_one() { # - test result is saved to data file # run_one_logged() { - local BEFORE=`date +%s` + local BEFORE=$(date +%s) local TEST_ERROR local name=${TESTSUITE}.test_${1}.test_log.$(hostname -s).log local test_log=$LOGDIR/$name + local zfs_log_name=${TESTSUITE}.test_${1}.zfs_log + local zfs_debug_log=$LOGDIR/$zfs_log_name rm -rf $LOGDIR/err rm -rf $LOGDIR/ignore rm -rf $LOGDIR/skip - local SAVE_UMASK=`umask` + local SAVE_UMASK=$(umask) umask 0022 echo @@ -4685,7 +5010,7 @@ run_one_logged() { [ $RC -ne 0 ] && [ ! -f $LOGDIR/err ] && echo "test_$1 returned $RC" | tee $LOGDIR/err - duration=$((`date +%s` - $BEFORE)) + duration=$(($(date +%s) - $BEFORE)) pass "$1" "(${duration}s)" if [[ -f $LOGDIR/err ]]; then @@ -4697,7 +5022,12 @@ run_one_logged() { fi log_sub_test_end $TEST_STATUS $duration "$RC" "$TEST_ERROR" + if [[ "$TEST_STATUS" != "SKIP" ]] && [[ -f $TF_SKIP ]]; then + rm -f $TF_SKIP + fi + if [ -f $LOGDIR/err ]; then + log_zfs_info "$zfs_debug_log" $FAIL_ON_ERROR && exit $RC fi @@ -4716,46 +5046,45 @@ skip_logged(){ } canonical_path() { - (cd `dirname $1`; echo $PWD/`basename $1`) + (cd $(dirname $1); echo $PWD/$(basename $1)) } check_grant() { - export base=`basetest $1` - [ "$CHECK_GRANT" == "no" ] && return 0 + export base=$(basetest $1) + [ "$CHECK_GRANT" == "no" ] && return 0 - testname=GCHECK_ONLY_${base} - [ ${!testname}x == x ] && return 0 + testname=GCHECK_ONLY_${base} + [ ${!testname}x == x ] && return 0 - echo -n "checking grant......" + echo -n "checking grant......" - local clients=$CLIENTS - [ -z $clients ] && clients=$(hostname) + local clients=$CLIENTS + [ -z "$clients" ] && clients=$(hostname) - # sync all the data and make sure no pending data on server - do_nodes $clients sync - - # get client grant - client_grant=`do_nodes $clients \ - "$LCTL get_param -n osc.${FSNAME}-*.cur_*grant_bytes" | \ - awk '{total += $1} END{print total}'` - - # get server grant - server_grant=`do_nodes $(comma_list $(osts_nodes)) \ - "$LCTL get_param -n obdfilter.${FSNAME}-OST*.tot_granted" | - awk '{total += $1} END{print total}'` - - # check whether client grant == server grant - if [ $client_grant -ne $server_grant ]; then - echo "failed: client:${client_grant} server: ${server_grant}." - do_nodes $(comma_list $(osts_nodes)) \ - "$LCTL get_param obdfilter.${FSNAME}-OST*.tot*" - do_nodes $clients "$LCTL get_param osc.${FSNAME}-*.cur_*_bytes" - return 1 - else - echo "pass: client:${client_grant} server: ${server_grant}" - fi + # sync all the data and make sure no pending data on server + do_nodes $clients sync + + # get client grant + client_grant=$(do_nodes $clients \ + "$LCTL get_param -n osc.${FSNAME}-*.cur_*grant_bytes" | + awk '{ total += $1 } END { printf("%0.0f", total) }') + + # get server grant + server_grant=$(do_nodes $(comma_list $(osts_nodes)) \ + "$LCTL get_param -n obdfilter.${FSNAME}-OST*.tot_granted" | + awk '{ total += $1 } END { printf("%0.0f", total) }') + # check whether client grant == server grant + if [[ $client_grant -ne $server_grant ]]; then + echo "failed: client:${client_grant} server: ${server_grant}." + do_nodes $(comma_list $(osts_nodes)) \ + "$LCTL get_param obdfilter.${FSNAME}-OST*.tot*" + do_nodes $clients "$LCTL get_param osc.${FSNAME}-*.cur_*_bytes" + return 1 + else + echo "pass: client:${client_grant} server: ${server_grant}" + fi } ######################## @@ -5097,14 +5426,14 @@ get_stripe () { } setstripe_nfsserver () { - local dir=$1 + local dir=$1 - local nfsserver=$(awk '"'$dir'" ~ $2 && $3 ~ "nfs" && $2 != "/" \ - { print $1 }' /proc/mounts | cut -f 1 -d : | head -1) + local nfsserver=$(awk '"'$dir'" ~ $2 && $3 ~ "nfs" && $2 != "/" \ + { print $1 }' /proc/mounts | cut -f 1 -d : | head -n1) - [ -z $nfsserver ] && echo "$dir is not nfs mounted" && return 1 + [ -z $nfsserver ] && echo "$dir is not nfs mounted" && return 1 - do_nodev $nfsserver lfs setstripe "$@" + do_nodev $nfsserver lfs setstripe "$@" } # Check and add a test group. @@ -5260,7 +5589,7 @@ do_and_time () { SECONDS=0 eval '$cmd' - + [ ${PIPESTATUS[0]} -eq 0 ] || rc=1 echo $SECONDS @@ -5268,8 +5597,9 @@ do_and_time () { } inodes_available () { - local IFree=$($LFS df -i $MOUNT | grep ^$FSNAME | awk '{print $4}' | sort -un | head -1) || return 1 - echo $IFree + local IFree=$($LFS df -i $MOUNT | grep ^$FSNAME | awk '{ print $4 }' | + sort -un | head -n1) || return 1 + echo $((IFree)) } mdsrate_inodes_available () { @@ -5284,25 +5614,25 @@ clear_llite_stats(){ # sum llite stat items calc_llite_stats() { - local res=$(lctl get_param -n llite.*.stats | - awk 'BEGIN {s = 0} END {print s} /^'"$1"'/ {s += $2}') - echo $res + local res=$(lctl get_param -n llite.*.stats | + awk '/^'"$1"'/ {sum += $2} END { printf("%0.0f", sum) }') + echo $((res)) } # reset osc stat counters clear_osc_stats(){ - lctl set_param -n osc.*.osc_stats 0 + lctl set_param -n osc.*.osc_stats 0 } # sum osc stat items calc_osc_stats() { - local res=$(lctl get_param -n osc.*.osc_stats | - awk 'BEGIN {s = 0} END {print s} /^'"$1"'/ {s += $2}') - echo $res + local res=$(lctl get_param -n osc.*.osc_stats | + awk '/^'"$1"'/ {sum += $2} END { printf("%0.0f", sum) }') + echo $((res)) } calc_sum () { - awk 'BEGIN {s = 0}; {s += $1}; END {print s}' + awk '{sum += $1} END { printf("%0.0f", sum) }' } calc_osc_kbytes () { @@ -5340,50 +5670,15 @@ restore_lustre_params() { } check_catastrophe() { - local rnodes=${1:-$(comma_list $(remote_nodes_list))} - local C=$CATASTROPHE - [ -f $C ] && [ $(cat $C) -ne 0 ] && return 1 - - [ -z "$rnodes" ] && return 0 - - local data - data=$(do_nodes "$rnodes" "rc=\\\$([ -f $C ] && - echo \\\$(< $C) || echo 0); - if [ \\\$rc -ne 0 ]; then echo \\\$(hostname): \\\$rc; fi - exit \\\$rc") - local rc=$? - if [ -n "$data" ]; then - echo $data - return $rc - fi - return 0 -} - -# CMD: determine mds index where directory inode presents -get_mds_dir () { - local dir=$1 - local file=$dir/f0.get_mds_dir_tmpfile - - mkdir -p $dir - rm -f $file - sleep 1 - local iused=$(lfs df -i $dir | grep MDT | awk '{print $3}') - local -a oldused=($iused) + local nodes=${1:-$(comma_list $(nodes_list))} - openfile -f O_CREAT:O_LOV_DELAY_CREATE -m 0644 $file > /dev/null - sleep 1 - iused=$(lfs df -i $dir | grep MDT | awk '{print $3}') - local -a newused=($iused) - - local num=0 - for ((i=0; i<${#newused[@]}; i++)); do - if [ ${oldused[$i]} -lt ${newused[$i]} ]; then - echo $(( i + 1 )) - rm -f $file - return 0 - fi - done - error "mdt-s : inodes count OLD ${oldused[@]} NEW ${newused[@]}" + do_nodes $nodes "rc=0; +val=\\\$($LCTL get_param -n catastrophe 2>&1); +if [[ \\\$? -eq 0 && \\\$val -ne 0 ]]; then + echo \\\$(hostname -s): \\\$val; + rc=\\\$val; +fi; +exit \\\$rc" } mdsrate_cleanup () { @@ -5564,39 +5859,34 @@ request_timeout () { } _wait_osc_import_state() { - local facet=$1 - local ost_facet=$2 - local expected=$3 - local ost=$(get_osc_import_name $facet $ost_facet) - + local facet=$1 + local ost_facet=$2 + local expected=$3 + local ost=$(get_osc_import_name $facet $ost_facet) local param="osc.${ost}.ost_server_uuid" + local params=$param local i=0 - # 1. wait the deadline of client 1st request (it could be skipped) - # 2. wait the deadline of client 2nd request - local maxtime=$(( 2 * $(request_timeout $facet))) - - #During setup time, the osc might not be setup, it need wait - #until list_param can return valid value. And also if there - #are mulitple osc entries we should list all of them before - #go to wait. - local params=$($LCTL list_param $param 2>/dev/null || true) - while [ -z "$params" ]; do - if [ $i -ge $maxtime ]; then - echo "can't get $param by list_param in $maxtime secs" - if [[ $facet != client* ]]; then - echo "Go with $param directly" - params=$param - break - else + # 1. wait the deadline of client 1st request (it could be skipped) + # 2. wait the deadline of client 2nd request + local maxtime=$(( 2 * $(request_timeout $facet))) + + if [[ $facet == client* ]]; then + # During setup time, the osc might not be setup, it need wait + # until list_param can return valid value. And also if there + # are mulitple osc entries we should list all of them before + # go to wait. + params=$($LCTL list_param $param 2>/dev/null || true) + while [ -z "$params" ]; do + if [ $i -ge $maxtime ]; then + echo "can't get $param in $maxtime secs" return 1 fi - fi - sleep 1 - i=$((i + 1)) - params=$($LCTL list_param $param 2>/dev/null || true) - done - + sleep 1 + i=$((i + 1)) + params=$($LCTL list_param $param 2>/dev/null || true) + done + fi if ! do_rpc_nodes "$(facet_active_host $facet)" \ wait_import_state $expected "$params" $maxtime; then error "import is not in ${expected} state" @@ -5847,22 +6137,23 @@ do_ls () { return $rc } -# target_start_and_reset_recovery_timer() -# service_time = at_est2timeout(service_time); -# service_time += 2 * (CONNECTION_SWITCH_MAX + CONNECTION_SWITCH_INC + -# INITIAL_CONNECT_TIMEOUT); -# CONNECTION_SWITCH_MAX : min(25U, max(CONNECTION_SWITCH_MIN,obd_timeout)) -#define CONNECTION_SWITCH_INC 1 -#define INITIAL_CONNECT_TIMEOUT max(CONNECTION_SWITCH_MIN,obd_timeout/20) -#define CONNECTION_SWITCH_MIN 5U +# check_and_start_recovery_timer() +# service_time = at_est2timeout(service_time); +# service_time += 2 * INITIAL_CONNECT_TIMEOUT; +# service_time += 2 * (CONNECTION_SWITCH_MAX + CONNECTION_SWITCH_INC); -max_recovery_time () { - local init_connect_timeout=$(( TIMEOUT / 20 )) - [[ $init_connect_timeout -ge 5 ]] || init_connect_timeout=5 +#define INITIAL_CONNECT_TIMEOUT max(CONNECTION_SWITCH_MIN, obd_timeout/20) +#define CONNECTION_SWITCH_MAX min(50, max(CONNECTION_SWITCH_MIN, obd_timeout)) +#define CONNECTION_SWITCH_MIN 5 +#define CONNECTION_SWITCH_INC 5 +max_recovery_time() { + local init_connect_timeout=$((TIMEOUT / 20)) + ((init_connect_timeout >= 5)) || init_connect_timeout=5 - local service_time=$(( $(at_max_get client) + $(( 2 * $(( 25 + 1 + init_connect_timeout)) )) )) + local service_time=$(($(at_max_get client) * 9 / 4 + 5)) + service_time=$((service_time + 2 * (init_connect_timeout + 50 + 5))) - echo $service_time + echo -n $service_time } get_clients_mount_count () { @@ -6395,6 +6686,32 @@ min_ost_size () { } # +# Get the available size (KB) of a given obd target. +# +get_obd_size() { + local facet=$1 + local obd=$2 + local size + + [[ $facet != client ]] || return 0 + + size=$(do_facet $facet $LCTL get_param -n *.$obd.kbytesavail | head -n1) + echo -n $size +} + +# +# Get the page size (bytes) on a given facet node. +# +get_page_size() { + local facet=$1 + local size + + size=$(do_facet $facet getconf PAGE_SIZE) + [[ ${PIPESTATUS[0]} = 0 && -n "$size" ]] || size=4096 + echo -n $size +} + +# # Get the block count of the filesystem. # get_block_count() { @@ -6584,49 +6901,46 @@ generate_logname() { # make directory on different MDTs test_mkdir() { - local option - local parent - local child local path - local rc=0 + local p_option + local stripe_count=2 + local stripe_index=-1 + local OPTIND=1 + + while getopts "c:i:p" opt; do + case $opt in + c) stripe_count=$OPTARG;; + i) stripe_index=$OPTARG;; + p) p_option="-p";; + \?) error "only support -i -c -p";; + esac + done - case $# in - 1) path=$1;; - 2) option=$1 - path=$2;; - *) error "Only creating single directory is supported";; - esac + shift $((OPTIND - 1)) + [ $# -eq 1 ] || error "Only creating single directory is supported" + path="$*" - child=$(basename $path) - parent=$(dirname $path) + if [ "$p_option" == "-p" ]; then + local parent=$(dirname $path) - if [ "$option" == "-p" -a -d $parent/$child ]; then - return $rc - fi - - if [ ! -d ${parent} ]; then - if [ "$option" == "-p" ]; then - mkdir -p ${parent} - else - return 1 - fi + [ -d $path ] && return 0 + [ ! -d ${parent} ] && mkdir -p ${parent} fi if [ $MDSCOUNT -le 1 ]; then - mkdir $option $parent/$child || rc=$? + mkdir $path else - local mdt_idx=$($LFS getstripe -M $parent) local test_num=$(echo $testnum | sed -e 's/[^0-9]*//g') + local mdt_index - if [ "$mdt_idx" -ne 0 ]; then - mkdir $option $parent/$child || rc=$? + if [ $stripe_index -eq -1 ]; then + mdt_index=$((test_num % MDSCOUNT)) else - mdt_idx=$((test_num % MDSCOUNT)) - echo "mkdir $mdt_idx for $parent/$child" - $LFS setdirstripe -i $mdt_idx $parent/$child || rc=$? + mdt_index=$stripe_index fi + echo "striped dir -i$mdt_index -c$stripe_count $path" + $LFS setdirstripe -i$mdt_index -c$stripe_count $path fi - return $rc } # find the smallest and not in use file descriptor @@ -6640,3 +6954,332 @@ free_fd() [ $fd -lt $max_fd ] || error "finding free file descriptor failed" echo $fd } + +check_mount_and_prep() +{ + is_mounted $MOUNT || setupall + + rm -rf $DIR/[df][0-9]* || error "Fail to cleanup the env!" + mkdir $DIR/$tdir || error "Fail to mkdir $DIR/$tdir." + for idx in $(seq $MDSCOUNT); do + local name="MDT$(printf '%04x' $((idx - 1)))" + rm -rf $MOUNT/.lustre/lost+found/$name/* + done +} + +# calcule how many ost-objects to be created. +precreated_ost_obj_count() +{ + local mdt_idx=$1 + local ost_idx=$2 + local mdt_name="MDT$(printf '%04x' $mdt_idx)" + local ost_name="OST$(printf '%04x' $ost_idx)" + local proc_path="${FSNAME}-${ost_name}-osc-${mdt_name}" + local last_id=$(do_facet mds$((mdt_idx + 1)) lctl get_param -n \ + osp.$proc_path.prealloc_last_id) + local next_id=$(do_facet mds$((mdt_idx + 1)) lctl get_param -n \ + osp.$proc_path.prealloc_next_id) + echo $((last_id - next_id + 1)) +} + +check_file_in_pool() +{ + local file=$1 + local pool=$2 + local tlist="$3" + local res=$($GETSTRIPE $file | grep 0x | cut -f2) + for i in $res + do + for t in $tlist ; do + [ "$i" -eq "$t" ] && continue 2 + done + + echo "pool list: $tlist" + echo "striping: $res" + error_noexit "$file not allocated in $pool" + return 1 + done + return 0 +} + +pool_add() { + echo "Creating new pool" + local pool=$1 + + create_pool $FSNAME.$pool || + { error_noexit "No pool created, result code $?"; return 1; } + [ $($LFS pool_list $FSNAME | grep -c $pool) -eq 1 ] || + { error_noexit "$pool not in lfs pool_list"; return 2; } +} + +pool_add_targets() { + echo "Adding targets to pool" + local pool=$1 + local first=$2 + local last=$3 + local step=${4:-1} + + local list=$(seq $first $step $last) + + local t=$(for i in $list; do printf "$FSNAME-OST%04x_UUID " $i; done) + do_facet mgs $LCTL pool_add \ + $FSNAME.$pool $FSNAME-OST[$first-$last/$step] + wait_update $HOSTNAME "lctl get_param -n lov.$FSNAME-*.pools.$pool \ + | sort -u | tr '\n' ' ' " "$t" || { + error_noexit "Add to pool failed" + return 1 + } + local lfscount=$($LFS pool_list $FSNAME.$pool | grep -c "\-OST") + local addcount=$(((last - first) / step + 1)) + [ $lfscount -eq $addcount ] || { + error_noexit "lfs pool_list bad ost count" \ + "$lfscount != $addcount" + return 2 + } +} + +pool_set_dir() { + local pool=$1 + local tdir=$2 + echo "Setting pool on directory $tdir" + + $SETSTRIPE -c 2 -p $pool $tdir && return 0 + + error_noexit "Cannot set pool $pool to $tdir" + return 1 +} + +pool_check_dir() { + local pool=$1 + local tdir=$2 + echo "Checking pool on directory $tdir" + + local res=$($GETSTRIPE --pool $tdir | sed "s/\s*$//") + [ "$res" = "$pool" ] && return 0 + + error_noexit "Pool on '$tdir' is '$res', not '$pool'" + return 1 +} + +pool_dir_rel_path() { + echo "Testing relative path works well" + local pool=$1 + local tdir=$2 + local root=$3 + + mkdir -p $root/$tdir/$tdir + cd $root/$tdir + pool_set_dir $pool $tdir || return 1 + pool_set_dir $pool ./$tdir || return 2 + pool_set_dir $pool ../$tdir || return 3 + pool_set_dir $pool ../$tdir/$tdir || return 4 + rm -rf $tdir; cd - > /dev/null +} + +pool_alloc_files() { + echo "Checking files allocation from directory pool" + local pool=$1 + local tdir=$2 + local count=$3 + local tlist="$4" + + local failed=0 + for i in $(seq -w 1 $count) + do + local file=$tdir/file-$i + touch $file + check_file_in_pool $file $pool "$tlist" || \ + failed=$((failed + 1)) + done + [ "$failed" = 0 ] && return 0 + + error_noexit "$failed files not allocated in $pool" + return 1 +} + +pool_create_files() { + echo "Creating files in pool" + local pool=$1 + local tdir=$2 + local count=$3 + local tlist="$4" + + mkdir -p $tdir + local failed=0 + for i in $(seq -w 1 $count) + do + local file=$tdir/spoo-$i + $SETSTRIPE -p $pool $file + check_file_in_pool $file $pool "$tlist" || \ + failed=$((failed + 1)) + done + [ "$failed" = 0 ] && return 0 + + error_noexit "$failed files not allocated in $pool" + return 1 +} + +pool_lfs_df() { + echo "Checking 'lfs df' output" + local pool=$1 + + local t=$($LCTL get_param -n lov.$FSNAME-clilov-*.pools.$pool | + tr '\n' ' ') + local res=$($LFS df --pool $FSNAME.$pool | + awk '{print $1}' | + grep "$FSNAME-OST" | + tr '\n' ' ') + [ "$res" = "$t" ] && return 0 + + error_noexit "Pools OSTs '$t' is not '$res' that lfs df reports" + return 1 +} + +pool_file_rel_path() { + echo "Creating files in a pool with relative pathname" + local pool=$1 + local tdir=$2 + + mkdir -p $tdir || + { error_noexit "unable to create $tdir"; return 1 ; } + local file="/..$tdir/$tfile-1" + $SETSTRIPE -p $pool $file || + { error_noexit "unable to create $file" ; return 2 ; } + + cd $tdir + $SETSTRIPE -p $pool $tfile-2 || { + error_noexit "unable to create $tfile-2 in $tdir" + return 3 + } +} + +pool_remove_first_target() { + echo "Removing first target from a pool" + local pool=$1 + + local pname="lov.$FSNAME-*.pools.$pool" + local t=$($LCTL get_param -n $pname | head -1) + do_facet mgs $LCTL pool_remove $FSNAME.$pool $t + wait_update $HOSTNAME "lctl get_param -n $pname | grep $t" "" || { + error_noexit "$t not removed from $FSNAME.$pool" + return 1 + } +} + +pool_remove_all_targets() { + echo "Removing all targets from pool" + local pool=$1 + local file=$2 + local pname="lov.$FSNAME-*.pools.$pool" + for t in $($LCTL get_param -n $pname | sort -u) + do + do_facet mgs $LCTL pool_remove $FSNAME.$pool $t + done + wait_update $HOSTNAME "lctl get_param -n $pname" "" || { + error_noexit "Pool $FSNAME.$pool cannot be drained" + return 1 + } + # striping on an empty/nonexistant pool should fall back + # to "pool of everything" + touch $file || { + error_noexit "failed to use fallback striping for empty pool" + return 2 + } + # setstripe on an empty pool should fail + $SETSTRIPE -p $pool $file 2>/dev/null && { + error_noexit "expected failure when creating file" \ + "with empty pool" + return 3 + } + return 0 +} + +pool_remove() { + echo "Destroying pool" + local pool=$1 + local file=$2 + + do_facet mgs $LCTL pool_destroy $FSNAME.$pool + + sleep 2 + # striping on an empty/nonexistant pool should fall back + # to "pool of everything" + touch $file || { + error_noexit "failed to use fallback striping for missing pool" + return 1 + } + # setstripe on an empty pool should fail + $SETSTRIPE -p $pool $file 2>/dev/null && { + error_noexit "expected failure when creating file" \ + "with missing pool" + return 2 + } + + # get param should return err once pool is gone + if wait_update $HOSTNAME "lctl get_param -n \ + lov.$FSNAME-*.pools.$pool 2>/dev/null || echo foo" "foo" + then + remove_pool_from_list $FSNAME.$pool + return 0 + fi + error_noexit "Pool $FSNAME.$pool is not destroyed" + return 3 +} + +# Get and check the actual stripe count of one file. +# Usage: check_stripe_count +check_stripe_count() { + local file=$1 + local expected=$2 + local actual + + [[ -z "$file" || -z "$expected" ]] && + error "check_stripe_count: invalid argument" + + local cmd="$GETSTRIPE -c $file" + actual=$($cmd) || error "$cmd failed" + actual=${actual%% *} + + if [[ $actual -ne $expected ]]; then + [[ $expected -eq -1 ]] || + error "$cmd wrong: found $actual, expected $expected" + [[ $actual -eq $OSTCOUNT ]] || + error "$cmd wrong: found $actual, expected $OSTCOUNT" + fi +} + +# Get and check the actual list of OST indices on one file. +# Usage: check_obdidx +check_obdidx() { + local file=$1 + local expected=$2 + local obdidx + + [[ -z "$file" || -z "$expected" ]] && + error "check_obdidx: invalid argument!" + + obdidx=$(comma_list $($GETSTRIPE $file | grep -A $OSTCOUNT obdidx | + grep -v obdidx | awk '{print $1}' | xargs)) + + [[ $obdidx = $expected ]] || + error "list of OST indices on $file is $obdidx," \ + "should be $expected" +} + +# Get and check the actual OST index of the first stripe on one file. +# Usage: check_start_ost_idx +check_start_ost_idx() { + local file=$1 + local expected=$2 + local start_ost_idx + + [[ -z "$file" || -z "$expected" ]] && + error "check_start_ost_idx: invalid argument!" + + start_ost_idx=$($GETSTRIPE $file | grep -A 1 obdidx | grep -v obdidx | + awk '{print $1}') + + [[ $start_ost_idx = $expected ]] || + error "OST index of the first stripe on $file is" \ + "$start_ost_idx, should be $expected" +}