+ return $myRC
+}
+
+check_runas_id() {
+ local myRUNAS_ID=$1
+ shift
+ local myRUNAS=$@
+ check_runas_id_ret $myRUNAS_ID $myRUNAS || \
+ error "unable to write to $DIR/d0_runas_test as UID $myRUNAS_ID.
+ Please set RUNAS_ID to some UID which exists on MDS and client or
+ add user $myRUNAS_ID:$myRUNAS_ID on these nodes."
+}
+
+# Run multiop in the background, but wait for it to print
+# "PAUSING" to its stdout before returning from this function.
+multiop_bg_pause() {
+ MULTIOP_PROG=${MULTIOP_PROG:-multiop}
+ FILE=$1
+ ARGS=$2
+
+ TMPPIPE=/tmp/multiop_open_wait_pipe.$$
+ mkfifo $TMPPIPE
+
+ echo "$MULTIOP_PROG $FILE v$ARGS"
+ $MULTIOP_PROG $FILE v$ARGS > $TMPPIPE &
+
+ echo "TMPPIPE=${TMPPIPE}"
+ read -t 60 multiop_output < $TMPPIPE
+ if [ $? -ne 0 ]; then
+ rm -f $TMPPIPE
+ return 1
+ fi
+ rm -f $TMPPIPE
+ if [ "$multiop_output" != "PAUSING" ]; then
+ echo "Incorrect multiop output: $multiop_output"
+ kill -9 $PID
+ return 1
+ fi
+
+ return 0
+}
+
+check_rate() {
+ local OP=$1
+ local TARGET_RATE=$2
+ local NUM_CLIENTS=$3
+ local LOG=$4
+
+ local RATE=$(awk '/^Rate: [0-9\.]+ '"${OP}"'s\/sec/ { print $2}' ${LOG})
+
+ # We need to use bc since the rate is a floating point number
+ local RES=$(echo "${RATE} < ${TARGET_RATE}" | bc -l )
+ if [ ${RES} -eq 0 ]; then
+ echo "Success: ${RATE} ${OP}s/sec met target rate" \
+ "${TARGET_RATE} ${OP}s/sec for ${NUM_CLIENTS} client(s)."
+ return 0
+ else
+ echo "Failure: ${RATE} ${OP}s/sec did not meet target rate" \
+ "${TARGET_RATE} ${OP}s/sec for ${NUM_CLIENTS} client(s)."
+ return 1
+ fi
+}
+
+# reset llite stat counters
+clear_llite_stats(){
+ lctl set_param -n llite.*.stats 0
+}
+
+# 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
+}
+
+# reset osc stat counters
+clear_osc_stats(){
+ 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
+}
+
+calc_sum () {
+ awk 'BEGIN {s = 0}; {s += $1}; END {print s}'
+}
+
+calc_osc_kbytes () {
+ $LCTL get_param -n osc.*[oO][sS][cC][-_][0-9a-f]*.$1 | calc_sum
+}
+
+# save_lustre_params(node, parameter_mask)
+# generate a stream of formatted strings (<node> <param name>=<param value>)
+save_lustre_params() {
+ local s
+ do_node $1 "lctl get_param $2" | while read s; do echo "$1 $s"; done
+}
+
+# restore lustre parameters from input stream, produces by save_lustre_params
+restore_lustre_params() {
+ local node
+ local name
+ local val
+ while IFS=" =" read node name val; do
+ do_node $node "lctl set_param -n $name $val"
+ done
+}
+
+check_catastrophe () {
+ local rnodes=$(comma_list $(remote_nodes_list))
+
+ [ -f $CATASTROPHE ] && [ `cat $CATASTROPHE` -ne 0 ] && return 1
+ if [ $rnodes ]; then
+ do_nodes $rnodes "[ -f $CATASTROPHE ] && { [ \`cat $CATASTROPHE\` -eq 0 ] || false; } || true"
+ fi
+}
+
+# $1 node
+# $2 file
+get_stripe_info() {
+ local tmp_file
+
+ stripe_size=0
+ stripe_count=0
+ stripe_index=0
+ tmp_file=$(mktemp)
+
+ do_facet $1 lfs getstripe -v $2 > $tmp_file
+
+ stripe_size=`awk '$1 ~ /size/ {print $2}' $tmp_file`
+ stripe_count=`awk '$1 ~ /count/ {print $2}' $tmp_file`
+ stripe_index=`awk '/obdidx/ {start = 1; getline; print $1; exit}' $tmp_file`
+ rm -f $tmp_file