Blame SOURCES/0040-libmultipath-limit-reading-0xc9-vpd-page.patch

b7337d
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
b7337d
From: Benjamin Marzinski <bmarzins@redhat.com>
b7337d
Date: Wed, 7 Oct 2020 21:43:02 -0500
b7337d
Subject: [PATCH] libmultipath: limit reading 0xc9 vpd page
b7337d
b7337d
Only rdac arrays support 0xC9 vpd page inquiries. All other arrays will
b7337d
return a failure. Only do the rdac inquiry when detecting array
b7337d
capabilities if the array's path checker is explicitly set to rdac, or
b7337d
the path checker is not set, and the array reports that it supports vpd
b7337d
page 0xC9 in the Supported VPD Pages (0x00) vpd page.
b7337d
b7337d
Multipath was doing the check if either the path checker was set to
b7337d
rdac, or no path checker was set.  This means that for almost all
b7337d
non-rdac arrays, multipath was issuing a bad inquiry. This was annoying
b7337d
users.
b7337d
b7337d
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
b7337d
---
b7337d
 libmultipath/discovery.c | 25 +++++++++++++++++++++++++
b7337d
 libmultipath/discovery.h |  1 +
b7337d
 libmultipath/propsel.c   | 10 ++++++----
b7337d
 3 files changed, 32 insertions(+), 4 deletions(-)
b7337d
b7337d
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
b7337d
index eb1e735d..01aadba9 100644
b7337d
--- a/libmultipath/discovery.c
b7337d
+++ b/libmultipath/discovery.c
b7337d
@@ -1266,6 +1266,31 @@ fetch_vpd_page(int fd, int pg, unsigned char *buff)
b7337d
 	return buff_len;
b7337d
 }
b7337d
 
b7337d
+/* heavily based on sg_inq.c from sg3_utils */
b7337d
+bool
b7337d
+is_vpd_page_supported(int fd, int pg)
b7337d
+{
b7337d
+	int i, len, buff_len;
b7337d
+	unsigned char buff[4096];
b7337d
+
b7337d
+	buff_len = fetch_vpd_page(fd, 0x00, buff);
b7337d
+	if (buff_len < 0)
b7337d
+		return false;
b7337d
+	if (buff_len < 4) {
b7337d
+		condlog(3, "VPD page 00h too short");
b7337d
+		return false;
b7337d
+	}
b7337d
+
b7337d
+	len = buff[3] + 4;
b7337d
+	if (len > buff_len)
b7337d
+		condlog(3, "vpd page 00h trucated, expected %d, have %d",
b7337d
+			len, buff_len);
b7337d
+	for (i = 4; i < len; ++i)
b7337d
+		if (buff[i] == pg)
b7337d
+			return true;
b7337d
+	return false;
b7337d
+}
b7337d
+
b7337d
 int
b7337d
 get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen)
b7337d
 {
b7337d
diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h
b7337d
index 6444887d..d3193daf 100644
b7337d
--- a/libmultipath/discovery.h
b7337d
+++ b/libmultipath/discovery.h
b7337d
@@ -56,6 +56,7 @@ int sysfs_get_asymmetric_access_state(struct path *pp,
b7337d
 				      char *buff, int buflen);
b7337d
 int get_uid(struct path * pp, int path_state, struct udev_device *udev,
b7337d
 	    int allow_fallback);
b7337d
+bool is_vpd_page_supported(int fd, int pg);
b7337d
 
b7337d
 /*
b7337d
  * discovery bitmask
b7337d
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
b7337d
index d362beb4..d7febec6 100644
b7337d
--- a/libmultipath/propsel.c
b7337d
+++ b/libmultipath/propsel.c
b7337d
@@ -496,13 +496,15 @@ check_rdac(struct path * pp)
b7337d
 {
b7337d
 	int len;
b7337d
 	char buff[44];
b7337d
-	const char *checker_name;
b7337d
+	const char *checker_name = NULL;
b7337d
 
b7337d
 	if (pp->bus != SYSFS_BUS_SCSI)
b7337d
 		return 0;
b7337d
-	/* Avoid ioctl if this is likely not an RDAC array */
b7337d
-	if (__do_set_from_hwe(checker_name, pp, checker_name) &&
b7337d
-	    strcmp(checker_name, RDAC))
b7337d
+	/* Avoid checking 0xc9 if this is likely not an RDAC array */
b7337d
+	if (!__do_set_from_hwe(checker_name, pp, checker_name) &&
b7337d
+	    !is_vpd_page_supported(pp->fd, 0xC9))
b7337d
+		return 0;
b7337d
+	if (checker_name && strcmp(checker_name, RDAC))
b7337d
 		return 0;
b7337d
 	len = get_vpd_sgio(pp->fd, 0xC9, 0, buff, 44);
b7337d
 	if (len <= 0)
b7337d
-- 
b7337d
2.17.2
b7337d