Enclosure LED fixes

- Pass $VDEV_ENC_SYSFS_PATH to 'zpool [iostat|status] -c' to include
  enclosure LED sysfs path.

- Set LEDs correctly after import.  This includes clearing any erroniously
  set LEDs prior to the import, and setting the LED for any UNAVAIL drives.

- Include symlink for vdev_attach-led.sh in Makefile.am.

- Print the VDEV path in all-syslog.sh, and fix it so the pool GUID actually
  prints.    

Reviewed-by: Don Brady <don.brady@intel.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tony Hutter <hutter2@llnl.gov>
Closes #5716 
Closes #5751
This commit is contained in:
Tony Hutter
2017-02-10 16:09:45 -08:00
committed by Brian Behlendorf
parent 65a736bc0d
commit b291029e86
8 changed files with 203 additions and 50 deletions
+6 -2
View File
@@ -67,7 +67,9 @@ dist_zedexec_SCRIPTS = \
zed.d/scrub_finish-notify.sh \
zed.d/statechange-led.sh \
zed.d/statechange-notify.sh \
zed.d/vdev_clear-led.sh
zed.d/vdev_clear-led.sh \
zed.d/vdev_attach-led.sh \
zed.d/pool_import-led.sh
zedconfdefaults = \
all-syslog.sh \
@@ -76,7 +78,9 @@ zedconfdefaults = \
scrub_finish-notify.sh \
statechange-led.sh \
statechange-notify.sh \
vdev_clear-led.sh
vdev_clear-led.sh \
vdev_attach-led.sh \
pool_import-led.sh
install-data-hook:
$(MKDIR_P) "$(DESTDIR)$(zedconfdir)"
+2 -1
View File
@@ -6,6 +6,7 @@
. "${ZED_ZEDLET_DIR}/zed-functions.sh"
zed_log_msg "eid=${ZEVENT_EID}" "class=${ZEVENT_SUBCLASS}" \
"${ZEVENT_POOL:+"pool=${ZEVENT_POOL}"}" \
"${ZEVENT_POOL_GUID:+"pool_guid=${ZEVENT_POOL_GUID}"}" \
"${ZEVENT_VDEV_PATH:+"vdev_path=${ZEVENT_VDEV_PATH}"}" \
"${ZEVENT_VDEV_STATE_STR:+"vdev_state=${ZEVENT_VDEV_STATE_STR}"}"
exit 0
+1
View File
@@ -0,0 +1 @@
statechange-led.sh
+137 -32
View File
@@ -2,13 +2,19 @@
#
# Turn off/on the VDEV's enclosure fault LEDs when the pool's state changes.
#
# Turn LED on if the VDEV becomes faulted or degraded, and turn it back off
# when it's online again. It will also turn on the LED (or keep it on) if
# the drive becomes unavailable, unless the drive was in was a previously
# online state (online->unavail is a normal state transition during an
# autoreplace).
# Turn the VDEV's fault LED on if it becomes FAULTED, DEGRADED or UNAVAIL.
# Turn the LED off when it's back ONLINE again.
#
# This script requires that your enclosure be supported by the
# This script run in two basic modes:
#
# 1. If $ZEVENT_VDEV_ENC_SYSFS_PATH and $ZEVENT_VDEV_STATE_STR are set, then
# only set the LED for that particular VDEV. This is the case for statechange
# events and some vdev_* events.
#
# 2. If those vars are not set, then check the state of all VDEVs in the pool,i
# and set the LEDs accordingly. This is the case for pool_import events.
#
# Note that this script requires that your enclosure be supported by the
# Linux SCSI enclosure services (ses) driver. The script will do nothing
# if you have no enclosure, or if your enclosure isn't supported.
#
@@ -16,8 +22,8 @@
# 0: enclosure led successfully set
# 1: enclosure leds not not available
# 2: enclosure leds administratively disabled
# 3: ZED didn't pass enclosure sysfs path
# 4: Enclosure sysfs path doesn't exist
# 3: The led sysfs path passed from ZFS does not exist
# 4: $ZPOOL not set
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
. "${ZED_ZEDLET_DIR}/zed-functions.sh"
@@ -30,15 +36,54 @@ if [ "${ZED_USE_ENCLOSURE_LEDS}" != "1" ] ; then
exit 2
fi
[ -n "${ZEVENT_VDEV_ENC_SYSFS_PATH}" ] || exit 3
zed_check_cmd "$ZPOOL" || exit 4
[ -e "${ZEVENT_VDEV_ENC_SYSFS_PATH}/fault" ] || exit 4
# Global used in set_led debug print
vdev=""
# Turn on/off enclosure LEDs
function led
# set_led (file)
#
# Write an enclosure sysfs file
#
# Arguments
# file: sysfs file to set (like /sys/class/enclosure/0:0:1:0/SLOT 10/fault)
# val: value to set it to
#
# Globals
# vdev: VDEV name for debug printing
#
# Return
# nothing
#
function set_led {
file="$1"
val="$2"
# Set the value twice. I've seen enclosures that were
# flakey about setting it the first time.
echo "$val" > "$file"
echo "$val" > "$file"
zed_log_msg "vdev $vdev set '$file' LED to $val"
}
# check_and_set_led (file, val)
#
# Read an enclosure sysfs file, and write it if it's not already set to 'val'
#
# Arguments
# file: sysfs file to set (like /sys/class/enclosure/0:0:1:0/SLOT 10/fault)
# val: value to set it to
#
# Return
# 0 on success, 3 on missing sysfs path
#
function check_and_set_led
{
file="$1/fault"
val=$2
file="$1"
val="$2"
if [ ! -e "$ZEVENT_VDEV_ENC_SYSFS_PATH/fault" ] ; then
return 3
fi
# We want to check the current state first, since writing to the
# 'fault' entry always always causes a SES command, even if the
@@ -53,28 +98,88 @@ function led
fi
if [ "$current" != "$val" ] ; then
# Set the value twice. I've seen enclosures that were
# flakey about setting it the first time.
echo "$val" > "$file"
echo "$val" > "$file"
set_led "$file" "$val"
fi
}
# Decide whether to turn on/off an LED based on the state
# Pass in path name and fault string ("ONLINE"/"FAULTED"/"DEGRADED"...etc)
function state_to_val {
state="$1"
if [ "$state" == "FAULTED" ] || [ "$state" == "DEGRADED" ] || \
[ "$state" == "UNAVAIL" ] ; then
echo 1
elif [ "$state" == "ONLINE" ] ; then
echo 0
fi
}
# process_pool ([pool])
#
# We only turn on LEDs when a drive becomes FAULTED, DEGRADED, or UNAVAIL and
# only turn it on when it comes back ONLINE. All other states are ignored, and
# keep the previous LED state.
function process {
path="$1"
fault=$2
if [ "$fault" == "FAULTED" ] || [ "$fault" == "DEGRADED" ] || \
[ "$fault" == "UNAVAIL" ] ; then
led "$path" 1
elif [ "$fault" == "ONLINE" ] ; then
led "$path" 0
# Iterate through a pool (or pools) and set the VDEV's enclosure slot LEDs to
# the VDEV's state.
#
# Arguments
# pool: Optional pool name. If not specified, iterate though all pools.
#
# Return
# 0 on success, 3 on missing sysfs path
#
function process_pool
{
pool="$1"
rc=0
# Lookup all the current LED values and paths in parallel
cmd='echo led_token=$(cat "$VDEV_ENC_SYSFS_PATH/fault"),"$VDEV_ENC_SYSFS_PATH",'
out=$($ZPOOL status -vc "$cmd" $pool | grep 'led_token=')
while read -r vdev state read write chksum therest ; do
# Read out current LED value and path
tmp=$(echo "$therest" | sed 's/^.*led_token=//g')
IFS="," read -r current_val vdev_enc_sysfs_path <<< "$tmp"
if [ -z "$vdev_enc_sysfs_path" ] ; then
# Skip anything with no sysfs LED entries
continue
fi
# On some enclosures if you write 1 to fault, and read it back,
# it will return 2. Treat all non-zero values as 1 for
# simplicity.
if [ "$current_val" != "0" ] ; then
current_val=1
fi
val=$(state_to_val "$state")
if [ "$current_val" == "$val" ] ; then
# LED is already set correctly
continue
fi
if [ ! -e "$vdev_enc_sysfs_path/fault" ] ; then
rc=1
zed_log_msg "vdev $vdev '$file/fault' doesn't exist"
continue;
fi
set_led "$vdev_enc_sysfs_path/fault" $val
done <<< "$out"
if [ "$rc" == "0" ] ; then
return 0
else
# We didn't see a sysfs entry that we wanted to set
return 3
fi
}
process "$ZEVENT_VDEV_ENC_SYSFS_PATH" "$ZEVENT_VDEV_STATE_STR"
if [ ! -z "$ZEVENT_VDEV_ENC_SYSFS_PATH" ] && [ ! -z "$ZEVENT_VDEV_STATE_STR" ] ; then
# Got a statechange for an individual VDEV
val=$(state_to_val "$ZEVENT_VDEV_STATE_STR")
vdev="$(basename $ZEVENT_VDEV_PATH)"
check_and_set_led "$ZEVENT_VDEV_ENC_SYSFS_PATH/fault" "$val"
else
# Process the entire pool
process_pool $(zed_guid_to_pool $ZEVENT_POOL_GUID)
fi
+22
View File
@@ -413,3 +413,25 @@ zed_rate_limit()
zed_unlock "${lockfile}" "${lockfile_fd}"
return "${rv}"
}
# zed_guid_to_pool (guid)
#
# Convert a pool GUID into its pool name (like "tank")
# Arguments
# guid: pool GUID (decimal or hex)
#
# Return
# Pool name
#
function zed_guid_to_pool
{
if [ -z "$1" ] ; then
return
fi
guid=$(printf "%llu" $1)
if [ ! -z "$guid" ] ; then
$ZPOOL get -H -ovalue,name guid | awk '$1=='$guid' {print $2}'
fi
}