Blame SOURCES/0253-RHBZ-1618549-mix-hw-handler.patch

4728c8
---
4728c8
 libmultipath/configure.c |    2 -
4728c8
 libmultipath/propsel.c   |   58 +++++++++++++++++++++++++++++++++++++++++++++++
4728c8
 2 files changed, 59 insertions(+), 1 deletion(-)
4728c8
4728c8
Index: multipath-tools-130222/libmultipath/configure.c
4728c8
===================================================================
4728c8
--- multipath-tools-130222.orig/libmultipath/configure.c
4728c8
+++ multipath-tools-130222/libmultipath/configure.c
4728c8
@@ -282,6 +282,7 @@ setup_map (struct multipath * mpp, char
4728c8
 	select_pgpolicy(mpp);
4728c8
 	select_selector(mpp);
4728c8
 	select_features(mpp);
4728c8
+	select_retain_hwhandler(mpp);
4728c8
 	select_hwhandler(mpp);
4728c8
 	select_rr_weight(mpp);
4728c8
 	select_minio(mpp);
4728c8
@@ -293,7 +294,6 @@ setup_map (struct multipath * mpp, char
4728c8
 	select_fast_io_fail(mpp);
4728c8
 	select_dev_loss(mpp);
4728c8
 	select_reservation_key(mpp);
4728c8
-	select_retain_hwhandler(mpp);
4728c8
 	select_deferred_remove(mpp);
4728c8
 	select_delay_watch_checks(mpp);
4728c8
 	select_delay_wait_checks(mpp);
4728c8
Index: multipath-tools-130222/libmultipath/propsel.c
4728c8
===================================================================
4728c8
--- multipath-tools-130222.orig/libmultipath/propsel.c
4728c8
+++ multipath-tools-130222/libmultipath/propsel.c
4728c8
@@ -19,6 +19,8 @@
4728c8
 #include "discovery.h"
4728c8
 #include "prioritizers/alua_rtpg.h"
4728c8
 #include "prkey.h"
4728c8
+#include "sysfs.h"
4728c8
+#include "util.h"
4728c8
 #include <inttypes.h>
4728c8
 #include <libudev.h>
4728c8
 #include <mpath_persist.h>
4728c8
@@ -317,9 +319,65 @@ select_features (struct multipath * mp)
4728c8
 	return 0;
4728c8
 }
4728c8
 
4728c8
+static int get_dh_state(struct path *pp, char *value, size_t value_len)
4728c8
+{
4728c8
+	int ret;
4728c8
+	struct udev_device *ud;
4728c8
+
4728c8
+	if (pp->udev == NULL)
4728c8
+		return -1;
4728c8
+
4728c8
+	ud = udev_device_get_parent_with_subsystem_devtype(pp->udev, "scsi",
4728c8
+							   "scsi_device");
4728c8
+	if (ud == NULL)
4728c8
+		return -1;
4728c8
+
4728c8
+	ret = sysfs_attr_get_value(ud, "dh_state", value, value_len);
4728c8
+	if (ret > 0)
4728c8
+		strchop(value);
4728c8
+	return ret;
4728c8
+}
4728c8
+
4728c8
+static int
4728c8
+use_attached_hwhandler(struct multipath * mp)
4728c8
+{
4728c8
+	int i;
4728c8
+	struct path *pp;
4728c8
+	int attached_hwhandler = 0;
4728c8
+	/* dh_state is no longer than "detached" */
4728c8
+	char dh_state[10];
4728c8
+
4728c8
+	vector_foreach_slot (mp->paths, pp, i) {
4728c8
+		if (get_dh_state(pp, dh_state, sizeof(dh_state)) > 0 &&
4728c8
+		    strcmp(dh_state, "detached") != 0) {
4728c8
+			if (!attached_hwhandler) {
4728c8
+				if (asprintf(&mp->hwhandler, "1 %s",
4728c8
+					     dh_state) < 0)
4728c8
+					return 0;
4728c8
+				attached_hwhandler = 1;
4728c8
+			/* if we find 2 different hardware handlers, disable
4728c8
+			 * retain_attached_hw_handler, and use the configured
4728c8
+			 * handler */
4728c8
+			} else if (strcmp(dh_state, &mp->hwhandler[2]) != 0) {
4728c8
+				FREE(mp->hwhandler);
4728c8
+				mp->hwhandler = NULL;
4728c8
+				mp->retain_hwhandler = RETAIN_HWHANDLER_OFF;
4728c8
+				condlog(0, "%s: retain_attached_hw_hander disabled (inconsistent handlers on paths)", mp->alias);
4728c8
+				return 0;
4728c8
+			}
4728c8
+		}
4728c8
+	}
4728c8
+	return attached_hwhandler;
4728c8
+}
4728c8
+
4728c8
 extern int
4728c8
 select_hwhandler (struct multipath * mp)
4728c8
 {
4728c8
+	if (mp->retain_hwhandler == RETAIN_HWHANDLER_ON &&
4728c8
+	    use_attached_hwhandler(mp)) {
4728c8
+		condlog(3, "%s: hwhandler = %s (setting: retained by kernel driver)", mp->alias, mp->hwhandler);
4728c8
+		return 0;
4728c8
+	}
4728c8
 	if (mp->hwe && mp->hwe->hwhandler) {
4728c8
 		mp->hwhandler = mp->hwe->hwhandler;
4728c8
 		condlog(3, "%s: hwhandler = %s (controller setting)",