zed.d/pool_import-led.sh: fix for current zpool scripts

Also minor clean-up with folding state_to_val() into a case,
unrolling the lesser-available seq into numbers,
ignoring vdev states we don't care about,
and documentation comments

Signed-off-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #11934
Closes #11935
This commit is contained in:
наб 2021-04-23 22:27:50 +02:00 committed by Tony Hutter
parent 110d0ba5ca
commit 586358102e
1 changed files with 45 additions and 45 deletions

View File

@ -1,21 +1,21 @@
#!/bin/sh #!/bin/sh
# #
# Turn off/on the VDEV's enclosure fault LEDs when the pool's state changes. # Turn off/on vdevs' enclosure fault LEDs when their pool's state changes.
# #
# Turn the VDEV's fault LED on if it becomes FAULTED, DEGRADED or UNAVAIL. # Turn a vdev's fault LED on if it becomes FAULTED, DEGRADED or UNAVAIL.
# Turn the LED off when it's back ONLINE again. # Turn its LED off when it's back ONLINE again.
# #
# This script run in two basic modes: # This script run in two basic modes:
# #
# 1. If $ZEVENT_VDEV_ENC_SYSFS_PATH and $ZEVENT_VDEV_STATE_STR are set, then # 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 # only set the LED for that particular vdev. This is the case for statechange
# events and some vdev_* events. # events and some vdev_* events.
# #
# 2. If those vars are not set, then check the state of all VDEVs in the pool # 2. If those vars are not set, then check the state of all vdevs in the pool
# and set the LEDs accordingly. This is the case for pool_import events. # 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 # Note that this script requires that your enclosure be supported by the
# Linux SCSI enclosure services (ses) driver. The script will do nothing # Linux SCSI Enclosure services (SES) driver. The script will do nothing
# if you have no enclosure, or if your enclosure isn't supported. # if you have no enclosure, or if your enclosure isn't supported.
# #
# Exit codes: # Exit codes:
@ -59,6 +59,10 @@ check_and_set_led()
file="$1" file="$1"
val="$2" val="$2"
if [ -z "$val" ]; then
return 0
fi
if [ ! -e "$file" ] ; then if [ ! -e "$file" ] ; then
return 3 return 3
fi fi
@ -66,11 +70,11 @@ check_and_set_led()
# If another process is accessing the LED when we attempt to update it, # If another process is accessing the LED when we attempt to update it,
# the update will be lost so retry until the LED actually changes or we # the update will be lost so retry until the LED actually changes or we
# timeout. # timeout.
for _ in $(seq 1 5); do for _ in 1 2 3 4 5; do
# We want to check the current state first, since writing to the # We want to check the current state first, since writing to the
# 'fault' entry always causes a SES command, even if the # 'fault' entry always causes a SES command, even if the
# current state is already what you want. # current state is already what you want.
current=$(cat "${file}") read -r current < "${file}"
# On some enclosures if you write 1 to fault, and read it back, # 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 # it will return 2. Treat all non-zero values as 1 for
@ -91,21 +95,23 @@ check_and_set_led()
state_to_val() state_to_val()
{ {
state="$1" state="$1"
if [ "$state" = "FAULTED" ] || [ "$state" = "DEGRADED" ] || \ case "$state" in
[ "$state" = "UNAVAIL" ] ; then FAULTED|DEGRADED|UNAVAIL)
echo 1 echo 1
elif [ "$state" = "ONLINE" ] ; then ;;
ONLINE)
echo 0 echo 0
fi ;;
esac
} }
# process_pool ([pool]) # process_pool (pool)
# #
# Iterate through a pool (or pools) and set the VDEV's enclosure slot LEDs to # Iterate through a pool and set the vdevs' enclosure slot LEDs to
# the VDEV's state. # those vdevs' state.
# #
# Arguments # Arguments
# pool: Optional pool name. If not specified, iterate though all pools. # pool: Pool name.
# #
# Return # Return
# 0 on success, 3 on missing sysfs path # 0 on success, 3 on missing sysfs path
@ -113,19 +119,22 @@ state_to_val()
process_pool() process_pool()
{ {
pool="$1" pool="$1"
# The output will be the vdevs only (from "grep '/dev/'"):
#
# U45 ONLINE 0 0 0 /dev/sdk 0
# U46 ONLINE 0 0 0 /dev/sdm 0
# U47 ONLINE 0 0 0 /dev/sdn 0
# U50 ONLINE 0 0 0 /dev/sdbn 0
#
ZPOOL_SCRIPTS_AS_ROOT=1 $ZPOOL status -c upath,fault_led "$pool" | grep '/dev/' | (
rc=0 rc=0
while read -r vdev state _ _ _ therest; do
# Lookup all the current LED values and paths in parallel
#shellcheck disable=SC2016
cmd='echo led_token=$(cat "$VDEV_ENC_SYSFS_PATH/fault"),"$VDEV_ENC_SYSFS_PATH",'
out=$($ZPOOL status -vc "$cmd" "$pool" | grep 'led_token=')
#shellcheck disable=SC2034
echo "$out" | while read -r vdev state read write chksum therest; do
# Read out current LED value and path # Read out current LED value and path
tmp=$(echo "$therest" | sed 's/^.*led_token=//g') # Get dev name (like 'sda')
vdev_enc_sysfs_path=$(echo "$tmp" | awk -F ',' '{print $2}') dev=$(basename "$(echo "$therest" | awk '{print $(NF-1)}')")
current_val=$(echo "$tmp" | awk -F ',' '{print $1}') vdev_enc_sysfs_path=$(realpath "/sys/class/block/$dev/device/enclosure_device"*)
current_val=$(echo "$therest" | awk '{print $NF}')
if [ "$current_val" != "0" ] ; then if [ "$current_val" != "0" ] ; then
current_val=1 current_val=1
@ -137,36 +146,27 @@ process_pool()
fi fi
if [ ! -e "$vdev_enc_sysfs_path/fault" ] ; then if [ ! -e "$vdev_enc_sysfs_path/fault" ] ; then
#shellcheck disable=SC2030 rc=3
rc=1
zed_log_msg "vdev $vdev '$file/fault' doesn't exist" zed_log_msg "vdev $vdev '$file/fault' doesn't exist"
continue; continue
fi fi
val=$(state_to_val "$state") val=$(state_to_val "$state")
if [ "$current_val" = "$val" ] ; then if [ "$current_val" = "$val" ] ; then
# LED is already set correctly # LED is already set correctly
continue; continue
fi fi
if ! check_and_set_led "$vdev_enc_sysfs_path/fault" "$val"; then if ! check_and_set_led "$vdev_enc_sysfs_path/fault" "$val"; then
rc=1 rc=3
fi fi
done done
exit "$rc"; )
#shellcheck disable=SC2031
if [ "$rc" = "0" ] ; then
return 0
else
# We didn't see a sysfs entry that we wanted to set
return 3
fi
} }
if [ -n "$ZEVENT_VDEV_ENC_SYSFS_PATH" ] && [ -n "$ZEVENT_VDEV_STATE_STR" ] ; then if [ -n "$ZEVENT_VDEV_ENC_SYSFS_PATH" ] && [ -n "$ZEVENT_VDEV_STATE_STR" ] ; then
# Got a statechange for an individual VDEV # Got a statechange for an individual vdev
val=$(state_to_val "$ZEVENT_VDEV_STATE_STR") val=$(state_to_val "$ZEVENT_VDEV_STATE_STR")
vdev=$(basename "$ZEVENT_VDEV_PATH") vdev=$(basename "$ZEVENT_VDEV_PATH")
check_and_set_led "$ZEVENT_VDEV_ENC_SYSFS_PATH/fault" "$val" check_and_set_led "$ZEVENT_VDEV_ENC_SYSFS_PATH/fault" "$val"