+# Check for and source configuration file otherwise set defaults
+[ -f /etc/sysconfig/lustre ] && . /etc/sysconfig/lustre
+FSCK_ARGS=${FSCK_ARGS:-""}
+MOUNT_OPTIONS=${MOUNT_OPTIONS:-""}
+LOCAL_SRV=${LOCAL_SRV:-"`$LDEV -l 2>/dev/null`"}
+FOREIGN_SRV=${FOREIGN_SRV:-"`$LDEV -f 2>/dev/null`"}
+REQUIRE_MMP_FEATURE=${REQUIRE_MMP_FEATURE:-${FOREIGN_SRV:+"yes"}}
+LOCAL_MOUNT_DIR=${LOCAL_MOUNT_DIR:-"/mnt/lustre/local"}
+FOREIGN_MOUNT_DIR=${FOREIGN_MOUNT_DIR:-"/mnt/lustre/foreign"}
+SETUP_DEVICES=${SETUP_DEVICES:-""}
+ZPOOL_LAYOUT_BUSES=${ZPOOL_LAYOUT_BUSES:-""}
+ZPOOL_LAYOUT_PORTS=${ZPOOL_LAYOUT_PORTS:-""}
+ZPOOL_LAYOUT_MAP=${ZPOOL_LAYOUT_MAP:-""}
+MOUNT_DELAY=${MOUNT_DELAY:-2}
+LOAD_ZFS=${LOAD_ZFS:-""}
+
+if [ -z "$TUNE2FS" ] ; then
+ TUNE2FS=`which tunefs.ldiskfs 2>/dev/null`
+ if [ -z "$TUNE2FS" ] ; then
+ TUNE2FS=`which tune2fs 2>/dev/null`
+ fi
+fi
+
+if [ -z "$PFSCK" ] ; then
+ PFSCK=`which pfsck.ldiskfs 2>/dev/null`
+ if [ -z "$PFSCK" ] ; then
+ PFSCK=`which fsck 2>/dev/null`
+ fi
+fi
+
+shopt -s nullglob
+
+start_zfs_services ()
+{
+ if [ -n "$ZPOOL_LAYOUT_BUSES" -a -n "$ZPOOL_LAYOUT_PORTS" ] ; then
+ MAP_ARG=${ZPOOL_LAYOUT_MAP:+"-m $ZPOOL_LAYOUT_MAP"}
+ $ZPOOL_LAYOUT -t -b "$ZPOOL_LAYOUT_BUSES" \
+ -p "$ZPOOL_LAYOUT_PORTS" $MAP_ARG
+ fi
+ if [ "$LOAD_ZFS" = "yes" ] && ! modprobe zfs ; then
+ echo "Failed to load zfs module. Aborting."
+ exit 1
+ fi
+}
+
+stop_devices ()
+{
+ local labels=$*
+ local label devtype
+ for label in $labels; do
+ devtype=`$LDEV -t $label`
+ if [ "$devtype" = "zfs" ] ; then
+ export_zpool $label
+ elif [ "$devtype" = "md" ] ; then
+ dev=`label_to_device $label`
+ journal=`$LDEV -j $label`
+ stop_md_device $dev
+ stop_md_device $journal
+ fi
+ done
+}
+
+import_zpool ()
+{
+ local result=1
+ local label=$1
+ local pool=`$LDEV -z $label`
+ local args="-N $ZPOOL_IMPORT_ARGS"
+ local cache=`$LDEV -r $label`
+ # -c is incompatible with -d
+ if [ -n "$cache" ] ; then
+ args="$args -c $cache"
+ elif [ -n "$ZPOOL_IMPORT_DIR" ] ; then
+ args="$args -d $ZPOOL_IMPORT_DIR"
+ fi
+
+ if zpool status $pool >/dev/null 2>&1 ; then
+ result=0
+ elif [ -n "$pool" ] ; then
+ zpool import $pool $args 2>/dev/null
+ result=$?
+ fi
+ if [ $result -ne 0 ] ; then
+ echo "Unexpected return code from import of pool $pool: $result"
+ fi
+ return $result
+}
+
+export_zpool ()
+{
+ local label=$1
+ local pool=`$LDEV -z $label`
+ zpool export $pool 2>/dev/null
+}
+
+# Trigger udev and wait for it to settle.
+udev_trigger()
+{
+ if [ -x ${UDEVADM} ]; then
+ ${UDEVADM} trigger --action=change --subsystem-match=block
+ ${UDEVADM} settle
+ else
+ /sbin/udevtrigger
+ /sbin/udevsettle
+ fi
+}
+
+# Usage: run_preexec_check [ start | restart | condrestart ]
+# The single parameter will be passed to the PREEXEC_SCRIPT
+run_preexec_check ()
+{
+ if [ -n "$PREEXEC_CHECK" ] && ! $PREEXEC_CHECK ; then
+ echo "Pre-exec check \"$PREEXEC_CHECK\" failed. Aborting."
+ exit 1
+ fi
+
+ if [ -n "$PREEXEC_SCRIPT" ] && ! "$PREEXEC_SCRIPT" "$1" ; then
+ echo "Pre-exec script \"$PREEXEC_SCRIPT\" failed. Aborting."
+ exit 1
+ fi
+}
+
+# Usage: run_postexec_check [ start | restart | condrestart ]
+# The single parameter will be passed to the PREEXEC_SCRIPT
+run_postexec_check ()
+{
+ if [ -n "$POSTEXEC_CHECK" ] && ! $POSTEXEC_CHECK ; then
+ echo "Post-exec check \"$POSTEXEC_CHECK\" failed. Aborting."
+ exit 1
+ fi
+
+ if [ -n "$POSTEXEC_SCRIPT" ] && ! "$POSTEXEC_SCRIPT" "$1" ; then
+ echo "Post-exec script \"$POSTEXEC_SCRIPT\" failed. Aborting."
+ exit 1
+ fi
+}
+
+# Usage: adjust_scsi_timeout <dev>
+adjust_scsi_timeout ()
+{
+ local dev=$1
+
+ if [ -n "$SCSI_DEVICE_TIMEOUT" ]; then
+ # make sure that it is actually a SCSI (sd) device
+ local name=`basename $dev`
+ local proc=/sys/block/${name}/device/timeout
+ local driver=`readlink /sys/block/${name}/device/driver`
+ if [ -n "$driver" ] && [ "`basename $driver`" == "sd" ]; then
+ if ! echo $SCSI_DEVICE_TIMEOUT >$proc; then
+ echo "FAILED: could not adjust ${dev} timeout"
+ return 1
+ fi
+ fi
+ fi
+ return 0
+}
+
+# Usage: fsck_test <dev> [ <dev> ... ]
+# Checks all devices in parallel if FSCK_ARGS is set.
+fsck_test ()
+{
+ local devices="$*"
+
+ # Filter out non-absolute paths, which are probably ZFS datasets
+ devices=`echo $devices |xargs -n 1|grep '^/'|xargs`
+
+ if [ -n "${FSCK_ARGS}" -a -n "$devices" ]; then
+ if [ -x $PFSCK ] ; then
+ echo "$PFSCK $devices -- ${FSCK_ARGS}"
+ $PFSCK $devices -- ${FSCK_ARGS}
+ if [ $? -ne 0 -a $? -ne 1 ] ; then
+ echo "FAILED: $PFSCK -- ${FSCK_ARGS}: $?"
+ return 1
+ fi
+ else
+ echo "$PFSCK not found"
+ return 1
+ fi
+ fi
+ return 0
+}
+
+# Usage: test_feature_flag <dev> <flag>
+test_feature_flag()
+{
+ local dev=$1
+ local flag=$2
+ local result=1
+ local feature
+
+ for feature in `$TUNE2FS -l $dev 2>/dev/null \
+ | grep features: | sed -e 's/^.*: //'`; do
+ if [ "$feature" == "$flag" ]; then
+ result=0
+ break
+ fi
+ done
+
+ return $result
+}
+
+# Usage: mmp_test <dev>
+# Returns 0 if it is set or not required, 1 if unset and required or error.
+mmp_test ()
+{
+ local dev=$1
+ local result=0
+
+ if [ "$REQUIRE_MMP_FEATURE" == "yes" ]; then
+ if [ -x $TUNE2FS ]; then
+ if ! test_feature_flag $dev "mmp"; then
+ echo "mmp feature flag is not set on $dev"
+ result=1
+ fi
+ else
+ echo "$TUNE2FS not found"
+ result=1
+ fi
+ fi
+
+ return $result
+}
+
+# Usage: label_to_mountpt <label>
+# Prints mount point path, if label matches a local or foreign server.
+label_to_mountpt ()
+{
+ local label=$1
+ local serv
+
+ for serv in $LOCAL_SRV; do
+ if [ "$serv" == "$label" ]; then
+ echo "$LOCAL_MOUNT_DIR/$label"
+ return
+ fi
+ done
+ for serv in $FOREIGN_SRV; do
+ if [ "$serv" == "$label" ]; then
+ echo "$FOREIGN_MOUNT_DIR/$label"
+ return
+ fi
+ done
+}
+
+# Usage: label_to_device <label>
+# Prints canonical device path.
+label_to_device ()
+{
+ local label=$1
+ local path=/dev/disk/by-label/$label
+
+ if [ -h $path ] ; then
+ readlink --canonicalize $path
+ else
+ $LDEV -d $label
+ fi
+}
+
+# helper for mountpt_is_active() and device_is_active()
+declare -r awkprog='BEGIN {rc = 1;}
+ { if ($field == path) {rc = 0;} }
+ END { exit rc;}'
+
+# Usage: mountpt_is_active <label>
+# Return 1 (inactive) on invalid label.
+mountpt_is_active ()
+{
+ local dir=`label_to_mountpt $1`
+ local result=1
+
+ if [ -n "$dir" ]; then
+ cat /proc/mounts | awk "$awkprog" field=2 path=$dir
+ result=$?
+ fi
+ return $result
+}
+
+# Usage: device_is_active <label>
+# Return 1 (inactive) on invalid label.
+device_is_active ()
+{
+ local dev=`label_to_device $1`
+ local result=1
+
+ if [ -n "$dev" ]; then
+ cat /proc/mounts | awk "$awkprog" field=1 path=$dir
+ result=$?
+ fi
+ return $result
+}
+
+# Usage: mount_one_device <label> <successflag> [devtype]
+# Remove <successflag> on error (trick to detect errors after parallel runs).
+mount_one_device ()
+{
+ local label=$1
+ local successflag=$2
+ local devtype=$3
+ local dev=`label_to_device $label`
+ local dir=`label_to_mountpt $label`
+
+ # $dir and $dev have already been checked at ths point
+ if [ ! -d $dir ] && ! mkdir -p $dir; then
+ rm -f $successflag
+ return
+ fi
+ echo "Mounting $dev on $dir"
+ if ! mount -t lustre $MOUNT_OPTIONS $dev $dir; then
+ rm -f $successflag
+ return
+ fi
+}
+
+# Usage: assemble_md_device <device>
+# Assemble the md device backing device.
+# Return 0 if the array is assembled successfully or was already active,
+# otherwise return error code from mdadm.
+assemble_md_device ()
+{
+ local dev=$1
+ local raidtab=$2
+ local args="-Aq"
+ local result=0
+
+ if [ -n "$raidtab" ] ; then
+ args="$args -c $raidtab"
+ fi
+
+ if ! md_array_is_active $dev ; then
+ mdadm $args $dev
+ result=$?
+ fi