#!/bin/bash # # 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). # # 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. # # This script also requires ZFS to be built with libdevmapper support. # # Exit codes: # 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 [ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc" . "${ZED_ZEDLET_DIR}/zed-functions.sh" if [ ! -d /sys/class/enclosure ] ; then exit 1 fi if [ "${ZED_USE_ENCLOSURE_LEDS}" != "1" ] ; then exit 2 fi [ -n "${ZEVENT_VDEV_ENC_SYSFS_PATH}" ] || exit 3 [ -e "${ZEVENT_VDEV_ENC_SYSFS_PATH}/fault" ] || exit 4 # Turn on/off enclosure LEDs function led { file="$1/fault" val=$2 # We want to check the current state first, since writing to the # 'fault' entry always always causes a SES command, even if the # current state is already what you want. current=$(cat "${file}") # 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" != "0" ] ; then current=1 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" fi } # Decide whether to turn on/off an LED based on the state # Pass in path name and fault string ("ONLINE"/"FAULTED"/"DEGRADED"...etc) # # 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 prev=$3 if [ "$fault" == "FAULTED" ] || [ "$fault" == "DEGRADED" ] ; then led "$path" 1 elif [ "$fault" == "UNAVAIL" ] && [ "$prev" != "ONLINE" ] ; then # For the most part, UNAVAIL should turn on the LED. However, # during an autoreplace, we see our new drive go online, # followed by our "old" drive going ONLINE->UNAVAIL. Since the # "old" drive has the same slot information, we want to ignore # the ONLINE->UNAVAIL event. # # NAME STATE READ WRITE CKSUM # mypool3 DEGRADED 0 0 0 # mirror-0 DEGRADED 0 0 0 # A1 ONLINE 0 0 0 # A2 ONLINE 0 880 0 # replacing-3 UNAVAIL 0 0 0 # old UNAVAIL 0 2.93K 0 corrupted data # A3 ONLINE 0 0 156 (resilvering) led "$path" 1 elif [ "$fault" == "ONLINE" ] ; then led "$path" 0 fi } process "$ZEVENT_VDEV_ENC_SYSFS_PATH" "$ZEVENT_VDEV_STATE_STR" \ "$ZEVENT_VDEV_LASTSTATE_STR"