2
2
#
3
3
# Turn off/on the VDEV's enclosure fault LEDs when the pool's state changes.
4
4
#
5
- # Turn LED on if the VDEV becomes faulted or degraded, and turn it back off
6
- # when it's online again. It will also turn on the LED (or keep it on) if
7
- # the drive becomes unavailable, unless the drive was in was a previously
8
- # online state (online->unavail is a normal state transition during an
9
- # autoreplace).
5
+ # Turn the VDEV's fault LED on if it becomes FAULTED, DEGRADED or UNAVAIL.
6
+ # Turn the LED off when it's back ONLINE again.
10
7
#
11
- # This script requires that your enclosure be supported by the
8
+ # This script run in two basic modes:
9
+ #
10
+ # 1. If $ZEVENT_VDEV_ENC_SYSFS_PATH and $ZEVENT_VDEV_STATE_STR are set, then
11
+ # only set the LED for that particular VDEV. This is the case for statechange
12
+ # events and some vdev_* events.
13
+ #
14
+ # 2. If those vars are not set, then check the state of all VDEVs in the pool,i
15
+ # and set the LEDs accordingly. This is the case for pool_import events.
16
+ #
17
+ # Note that this script requires that your enclosure be supported by the
12
18
# Linux SCSI enclosure services (ses) driver. The script will do nothing
13
19
# if you have no enclosure, or if your enclosure isn't supported.
14
20
#
15
21
# Exit codes:
16
22
# 0: enclosure led successfully set
17
23
# 1: enclosure leds not not available
18
24
# 2: enclosure leds administratively disabled
19
- # 3: ZED didn't pass enclosure sysfs path
20
- # 4: Enclosure sysfs path doesn't exist
25
+ # 3: The led sysfs path passed from ZFS does not exist
26
+ # 4: $ZPOOL not set
21
27
22
28
[ -f " ${ZED_ZEDLET_DIR} /zed.rc" ] && . " ${ZED_ZEDLET_DIR} /zed.rc"
23
29
. " ${ZED_ZEDLET_DIR} /zed-functions.sh"
@@ -30,15 +36,54 @@ if [ "${ZED_USE_ENCLOSURE_LEDS}" != "1" ] ; then
30
36
exit 2
31
37
fi
32
38
33
- [ -n " ${ZEVENT_VDEV_ENC_SYSFS_PATH} " ] || exit 3
39
+ zed_check_cmd " $ZPOOL " || exit 4
40
+
41
+ # Global used in set_led debug print
42
+ vdev=" "
43
+
44
+ # set_led (file)
45
+ #
46
+ # Write an enclosure sysfs file
47
+ #
48
+ # Arguments
49
+ # file: sysfs file to set (like /sys/class/enclosure/0:0:1:0/SLOT 10/fault)
50
+ # val: value to set it to
51
+ #
52
+ # Globals
53
+ # vdev: VDEV name for debug printing
54
+ #
55
+ # Return
56
+ # nothing
57
+ #
58
+ function set_led {
59
+ file=" $1 "
60
+ val=" $2 "
34
61
35
- [ -e " ${ZEVENT_VDEV_ENC_SYSFS_PATH} /fault" ] || exit 4
62
+ # Set the value twice. I've seen enclosures that were
63
+ # flakey about setting it the first time.
64
+ echo " $val " > " $file "
65
+ echo " $val " > " $file "
66
+ zed_log_msg " vdev $vdev set '$file ' LED to $val "
67
+ }
36
68
37
- # Turn on/off enclosure LEDs
38
- function led
69
+ # check_and_set_led (file, val)
70
+ #
71
+ # Read an enclosure sysfs file, and write it if it's not already set to 'val'
72
+ #
73
+ # Arguments
74
+ # file: sysfs file to set (like /sys/class/enclosure/0:0:1:0/SLOT 10/fault)
75
+ # val: value to set it to
76
+ #
77
+ # Return
78
+ # 0 on success, 3 on missing sysfs path
79
+ #
80
+ function check_and_set_led
39
81
{
40
- file=" $1 /fault"
41
- val=$2
82
+ file=" $1 "
83
+ val=" $2 "
84
+ if [ ! -e " $ZEVENT_VDEV_ENC_SYSFS_PATH /fault" ] ; then
85
+ return 3
86
+ fi
42
87
43
88
# We want to check the current state first, since writing to the
44
89
# 'fault' entry always always causes a SES command, even if the
@@ -53,28 +98,88 @@ function led
53
98
fi
54
99
55
100
if [ " $current " != " $val " ] ; then
56
- # Set the value twice. I've seen enclosures that were
57
- # flakey about setting it the first time.
58
- echo " $val " > " $file "
59
- echo " $val " > " $file "
101
+ set_led " $file " " $val "
60
102
fi
61
103
}
62
104
63
- # Decide whether to turn on/off an LED based on the state
64
- # Pass in path name and fault string ("ONLINE"/"FAULTED"/"DEGRADED"...etc)
65
- #
66
- # We only turn on LEDs when a drive becomes FAULTED, DEGRADED, or UNAVAIL and
67
- # only turn it on when it comes back ONLINE. All other states are ignored, and
68
- # keep the previous LED state.
69
- function process {
70
- path=" $1 "
71
- fault=$2
72
- if [ " $fault " == " FAULTED" ] || [ " $fault " == " DEGRADED" ] || \
73
- [ " $fault " == " UNAVAIL" ] ; then
74
- led " $path " 1
75
- elif [ " $fault " == " ONLINE" ] ; then
76
- led " $path " 0
105
+ function state_to_val {
106
+ state=" $1 "
107
+ if [ " $state " == " FAULTED" ] || [ " $state " == " DEGRADED" ] || \
108
+ [ " $state " == " UNAVAIL" ] ; then
109
+ echo 1
110
+ elif [ " $state " == " ONLINE" ] ; then
111
+ echo 0
77
112
fi
78
113
}
79
114
80
- process " $ZEVENT_VDEV_ENC_SYSFS_PATH " " $ZEVENT_VDEV_STATE_STR "
115
+ # process_pool ([pool])
116
+ #
117
+ # Iterate through a pool (or pools) and set the VDEV's enclosure slot LEDs to
118
+ # the VDEV's state.
119
+ #
120
+ # Arguments
121
+ # pool: Optional pool name. If not specified, iterate though all pools.
122
+ #
123
+ # Return
124
+ # 0 on success, 3 on missing sysfs path
125
+ #
126
+ function process_pool
127
+ {
128
+ pool=" $1 "
129
+ rc=0
130
+
131
+ # Lookup all the current LED values and paths in parallel
132
+ cmd=' echo led_token=$(cat "$VDEV_ENC_SYSFS_PATH/fault"),"$VDEV_ENC_SYSFS_PATH",'
133
+ out=$( $ZPOOL status -vc " $cmd " $pool | grep ' led_token=' )
134
+ while read -r vdev state read write chksum therest ; do
135
+
136
+ # Read out current LED value and path
137
+ tmp=$( echo " $therest " | sed ' s/^.*led_token=//g' )
138
+ IFS=" ," read -r current_val vdev_enc_sysfs_path <<< " $tmp"
139
+
140
+ if [ -z " $vdev_enc_sysfs_path " ] ; then
141
+ # Skip anything with no sysfs LED entries
142
+ continue
143
+ fi
144
+
145
+ # On some enclosures if you write 1 to fault, and read it back,
146
+ # it will return 2. Treat all non-zero values as 1 for
147
+ # simplicity.
148
+ if [ " $current_val " != " 0" ] ; then
149
+ current_val=1
150
+ fi
151
+
152
+ val=$( state_to_val " $state " )
153
+
154
+ if [ " $current_val " == " $val " ] ; then
155
+ # LED is already set correctly
156
+ continue
157
+ fi
158
+
159
+ if [ ! -e " $vdev_enc_sysfs_path /fault" ] ; then
160
+ rc=1
161
+ zed_log_msg " vdev $vdev '$file /fault' doesn't exist"
162
+ continue ;
163
+ fi
164
+
165
+ set_led " $vdev_enc_sysfs_path /fault" $val
166
+
167
+ done <<< " $out"
168
+ if [ " $rc " == " 0" ] ; then
169
+ return 0
170
+ else
171
+ # We didn't see a sysfs entry that we wanted to set
172
+ return 3
173
+ fi
174
+ }
175
+
176
+ if [ ! -z " $ZEVENT_VDEV_ENC_SYSFS_PATH " ] && [ ! -z " $ZEVENT_VDEV_STATE_STR " ] ; then
177
+ # Got a statechange for an individual VDEV
178
+ val=$( state_to_val " $ZEVENT_VDEV_STATE_STR " )
179
+
180
+ vdev=" $( basename $ZEVENT_VDEV_PATH ) "
181
+ check_and_set_led " $ZEVENT_VDEV_ENC_SYSFS_PATH /fault" " $val "
182
+ else
183
+ # Process the entire pool
184
+ process_pool $( zed_guid_to_pool $ZEVENT_POOL_GUID )
185
+ fi
0 commit comments