From 6568379eea8f01ad87a6cbcb66111112a1b5665f Mon Sep 17 00:00:00 2001
From: Tony Hutter <hutter2@llnl.gov>
Date: Tue, 25 Oct 2016 11:05:30 -0700
Subject: [PATCH] Fix statechange-led.sh & unnecessary libdevmapper warning

- Fix autoreplace behaviour on statechange-led.sh script.

ZED sends the following events on an auto-replace:

1. statechange: Disk goes UNAVAIL->ONLINE
2. statechange: Disk goes ONLINE->UNAVAIL
3. vdev_attach: Disk goes ONLINE

Events 1-2 happen when ZED first attempts to do an auto-online.  When that
fails, ZED then tries an auto-replace, generating the vdev_attach event in #3.

In the previous code, statechange-led was only looking at the UNAVAIL->ONLINE
transition to turn off the LED.  It ignored the #2 ONLINE->UNAVAIL transition,
assuming it was just the "old" VDEV going offline.  This is problematic, as
a drive can go from ONLINE->UNAVAIL when it's malfunctioning, and we don't want
to ignore that.

This new patch correctly turns on the fault LED every time a drive becomes
UNAVAIL.  It also monitors vdev_attach events to trigger turning off the LED
when an auto-replaced disk comes online.

- Remove unnecessary libdevmapper warning with --with-config=kernel

This fixes an unnecessary libdevmapper warning when building
--with-config=kernel.  Kernel code does not use libdevmapper, so the warning
is not needed.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tony Hutter <hutter2@llnl.gov>
Closes #2375
Closes #5312
Closes #5331
---
 cmd/zed/zed.d/statechange-led.sh | 23 +++--------------------
 cmd/zed/zed.d/vdev_attach-led.sh |  1 +
 configure.ac                     |  5 +++--
 module/zfs/zfs_fm.c              |  8 ++++++++
 4 files changed, 15 insertions(+), 22 deletions(-)
 create mode 120000 cmd/zed/zed.d/vdev_attach-led.sh

diff --git a/cmd/zed/zed.d/statechange-led.sh b/cmd/zed/zed.d/statechange-led.sh
index af1a14a9a..257e4a8a0 100755
--- a/cmd/zed/zed.d/statechange-led.sh
+++ b/cmd/zed/zed.d/statechange-led.sh
@@ -71,29 +71,12 @@ function led
 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)
+	if [ "$fault" == "FAULTED" ] || [ "$fault" == "DEGRADED" ] || \
+	   [ "$fault" == "UNAVAIL" ] ; then
 		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"
+process "$ZEVENT_VDEV_ENC_SYSFS_PATH" "$ZEVENT_VDEV_STATE_STR"
diff --git a/cmd/zed/zed.d/vdev_attach-led.sh b/cmd/zed/zed.d/vdev_attach-led.sh
new file mode 120000
index 000000000..7d7404398
--- /dev/null
+++ b/cmd/zed/zed.d/vdev_attach-led.sh
@@ -0,0 +1 @@
+statechange-led.sh
\ No newline at end of file
diff --git a/configure.ac b/configure.ac
index e9f50f783..39bd54c17 100644
--- a/configure.ac
+++ b/configure.ac
@@ -304,6 +304,7 @@ AC_CONFIG_FILES([
 
 AC_OUTPUT
 
-AS_IF([test "x$user_libdevmapper" != xyes ], [
-    AC_MSG_WARN([Building without libdevmapper.  Auto-replace, auto-online, and statechange-led.sh may not work correctly with device mapper vdevs.])
+AS_IF([test "x$user_libdevmapper" != xyes && test "$ZFS_CONFIG" != kernel ], [
+    AC_MSG_WARN([Building without libdevmapper.  Auto-replace, auto-online, \
+and statechange-led.sh may not work correctly with device mapper vdevs.])
 ])
diff --git a/module/zfs/zfs_fm.c b/module/zfs/zfs_fm.c
index 0f8ac28c1..df37fed2b 100644
--- a/module/zfs/zfs_fm.c
+++ b/module/zfs/zfs_fm.c
@@ -307,6 +307,10 @@ zfs_ereport_start(nvlist_t **ereport_out, nvlist_t **detector_out,
 			fm_payload_set(ereport,
 			    FM_EREPORT_PAYLOAD_ZFS_VDEV_FRU,
 			    DATA_TYPE_STRING, vd->vdev_fru, NULL);
+		if (vd->vdev_enc_sysfs_path != NULL)
+			fm_payload_set(ereport,
+			    FM_EREPORT_PAYLOAD_ZFS_VDEV_ENC_SYSFS_PATH,
+			    DATA_TYPE_STRING, vd->vdev_enc_sysfs_path, NULL);
 		if (vd->vdev_ashift)
 			fm_payload_set(ereport,
 			    FM_EREPORT_PAYLOAD_ZFS_VDEV_ASHIFT,
@@ -928,6 +932,10 @@ zfs_post_common(spa_t *spa, vdev_t *vd, const char *type, const char *name,
 		if (vd->vdev_fru != NULL)
 			VERIFY0(nvlist_add_string(resource,
 			    FM_EREPORT_PAYLOAD_ZFS_VDEV_FRU, vd->vdev_fru));
+		if (vd->vdev_enc_sysfs_path != NULL)
+			VERIFY0(nvlist_add_string(resource,
+			    FM_EREPORT_PAYLOAD_ZFS_VDEV_ENC_SYSFS_PATH,
+			    vd->vdev_enc_sysfs_path));
 		/* also copy any optional payload data */
 		if (aux) {
 			nvpair_t *elem = NULL;
-- 
2.40.0