summaryrefslogtreecommitdiffstats
path: root/cmd/zed/zed.d/statechange-led.sh
blob: ca911d2b9e1f20ecb87d26cc257d1729057597a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#!/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/degraded, and turn it back off when
# it's healthy again.  This 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 built without libdevmapper

[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
. "${ZED_ZEDLET_DIR}/zed-functions.sh"

# ZEVENT_VDEV_UPATH will not be present if ZFS is not built with libdevmapper
[ -n "${ZEVENT_VDEV_UPATH}" ] || exit 3

if [ "${ZED_USE_ENCLOSURE_LEDS}" != "1" ] ; then
	exit 2
fi

if [ ! -d /sys/class/enclosure ] ; then
	exit 1
fi

# Turn on/off enclosure LEDs
function led
{
	name=$1
	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.
	if [ -e /sys/block/$name/device/enclosure_device*/fault ] ; then
		# We have to do some monkey business to deal with spaces in
		# enclosure_device names.  I've seen horrible things like this: 
		#
		# '/sys/block/sdfw/device/enclosure_device:SLOT 43 41  /fault'
		#
		# ...so escape all spaces.
		file=`ls /sys/block/$name/device/enclosure_device*/fault | sed 's/\s/\\ /g'`

		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
	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 process {
	# path=/dev/sda, fault=

	path=$1
	fault=$2
	name=`basename $path`

	if [ -z "$name" ] ; then
		return
	fi

	if [ "$fault" == "FAULTED" ] || [ "$fault" == "DEGRADED" ] ; then
		led $name 1
	else
		led $name 0
	fi
}

process "$ZEVENT_VDEV_UPATH" "$ZEVENT_VDEV_STATE_STR"