commit
f7a85d25bf
@ -0,0 +1 @@
|
|||||||
|
b52c2be340449664f0a122070838f6d8edd42e4a SOURCES/multipath-tools-0.8.4.tgz
|
@ -0,0 +1 @@
|
|||||||
|
SOURCES/multipath-tools-0.8.4.tgz
|
@ -0,0 +1,66 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Sat, 21 Mar 2020 23:49:59 -0500
|
||||||
|
Subject: [PATCH] libmutipath: don't close fd on dm_lib_release
|
||||||
|
|
||||||
|
If dm_hold_control_open() isn't set, when dm_lib_release() is called, it
|
||||||
|
will close the control fd. The control fd will get re-opened on the next
|
||||||
|
dm_task_run() call, but if there is a dm_task_run() call already
|
||||||
|
in progress in another thread, it can fail. Since many of the
|
||||||
|
device-mapper callouts happen with the vecs lock held, this wasn't too
|
||||||
|
noticeable, but there is code that calls dm_task_run() without the
|
||||||
|
vecs lock held, notably the dmevent waiter code.
|
||||||
|
|
||||||
|
Since, as Martin pointed out, dm_hold_control_open() hasn't always
|
||||||
|
existed in libdevmapper, check if it's supported on compilation,
|
||||||
|
and update the version requirements if so.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/Makefile | 4 ++++
|
||||||
|
libmultipath/devmapper.c | 7 ++++++-
|
||||||
|
2 files changed, 10 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/Makefile b/libmultipath/Makefile
|
||||||
|
index e5651e49..ad690a49 100644
|
||||||
|
--- a/libmultipath/Makefile
|
||||||
|
+++ b/libmultipath/Makefile
|
||||||
|
@@ -36,6 +36,10 @@ ifneq ($(call check_func,dm_task_deferred_remove,/usr/include/libdevmapper.h),0)
|
||||||
|
CFLAGS += -DLIBDM_API_DEFERRED
|
||||||
|
endif
|
||||||
|
|
||||||
|
+ifneq ($(call check_func,dm_hold_control_dev,/usr/include/libdevmapper.h),0)
|
||||||
|
+ CFLAGS += -DLIBDM_API_HOLD_CONTROL
|
||||||
|
+endif
|
||||||
|
+
|
||||||
|
OBJS = memory.o parser.o vector.o devmapper.o callout.o \
|
||||||
|
hwtable.o blacklist.o util.o dmparser.o config.o \
|
||||||
|
structs.o discovery.o propsel.o dict.o \
|
||||||
|
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||||
|
index bed8ddc6..13a1cf53 100644
|
||||||
|
--- a/libmultipath/devmapper.c
|
||||||
|
+++ b/libmultipath/devmapper.c
|
||||||
|
@@ -108,7 +108,9 @@ dm_lib_prereq (void)
|
||||||
|
{
|
||||||
|
char version[64];
|
||||||
|
int v[3];
|
||||||
|
-#if defined(LIBDM_API_DEFERRED)
|
||||||
|
+#if defined(LIBDM_API_HOLD_CONTROL)
|
||||||
|
+ int minv[3] = {1, 2, 111};
|
||||||
|
+#elif defined(LIBDM_API_DEFERRED)
|
||||||
|
int minv[3] = {1, 2, 89};
|
||||||
|
#elif defined(DM_SUBSYSTEM_UDEV_FLAG0)
|
||||||
|
int minv[3] = {1, 2, 82};
|
||||||
|
@@ -254,6 +256,9 @@ void libmp_dm_init(void)
|
||||||
|
memcpy(conf->version, version, sizeof(version));
|
||||||
|
put_multipath_config(conf);
|
||||||
|
dm_init(verbosity);
|
||||||
|
+#ifdef LIBDM_API_HOLD_CONTROL
|
||||||
|
+ dm_hold_control_dev(1);
|
||||||
|
+#endif
|
||||||
|
dm_udev_set_sync_support(libmp_dm_udev_sync);
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,64 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 19 Mar 2020 22:17:51 -0500
|
||||||
|
Subject: [PATCH] libmultipath: allow force reload with no active paths
|
||||||
|
|
||||||
|
If the partition information has changed on multipath devices (say,
|
||||||
|
because it was updated on another node that has access to the same
|
||||||
|
storage), users expect that running "multipathd reconfigure" will update
|
||||||
|
that. However, if the checkers for the multipath device are pending for
|
||||||
|
too long when the the device is reconfigured, multipathd will give up
|
||||||
|
waiting for them, and refuse to reload the device, since there are no
|
||||||
|
active paths. This means that no kpartx update will be triggered.
|
||||||
|
|
||||||
|
Multipath is fully capable of reloading a multipath device that has no
|
||||||
|
active paths. This has been possible for years. If multipath is supposed
|
||||||
|
to reload the device, it should do so, even if there are no active paths.
|
||||||
|
|
||||||
|
Generally, when multipath is force reloaded, kpartx will be updated.
|
||||||
|
However when a device is reloaded with no paths, the udev rules won't
|
||||||
|
run kpartx. But they also weren't running kpartx when the first valid
|
||||||
|
path appeared, even though the dm activation rules get run in this case.
|
||||||
|
This changes 11-dm-mpath.rules to run kpartx when a device goes from no
|
||||||
|
usable paths to having usable paths.
|
||||||
|
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/configure.c | 6 ------
|
||||||
|
multipath/11-dm-mpath.rules | 2 +-
|
||||||
|
2 files changed, 1 insertion(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
||||||
|
index c95848a0..96c79610 100644
|
||||||
|
--- a/libmultipath/configure.c
|
||||||
|
+++ b/libmultipath/configure.c
|
||||||
|
@@ -710,12 +710,6 @@ select_action (struct multipath * mpp, vector curmp, int force_reload)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (pathcount(mpp, PATH_UP) == 0) {
|
||||||
|
- mpp->action = ACT_IMPOSSIBLE;
|
||||||
|
- condlog(3, "%s: set ACT_IMPOSSIBLE (no usable path)",
|
||||||
|
- mpp->alias);
|
||||||
|
- return;
|
||||||
|
- }
|
||||||
|
if (force_reload) {
|
||||||
|
mpp->force_udev_reload = 1;
|
||||||
|
mpp->action = ACT_RELOAD;
|
||||||
|
diff --git a/multipath/11-dm-mpath.rules b/multipath/11-dm-mpath.rules
|
||||||
|
index 07320a14..cd522e8c 100644
|
||||||
|
--- a/multipath/11-dm-mpath.rules
|
||||||
|
+++ b/multipath/11-dm-mpath.rules
|
||||||
|
@@ -75,7 +75,7 @@ ENV{MPATH_DEVICE_READY}=="0", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
|
||||||
|
ENV{MPATH_DEVICE_READY}!="0", ENV{.MPATH_DEVICE_READY_OLD}=="0",\
|
||||||
|
ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="$env{DM_DISABLE_OTHER_RULES_FLAG_OLD}",\
|
||||||
|
ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}="",\
|
||||||
|
- ENV{DM_ACTIVATION}="1"
|
||||||
|
+ ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0"
|
||||||
|
|
||||||
|
# The code to check multipath state ends here. We need to set
|
||||||
|
# properties and symlinks regardless whether the map is usable or
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,31 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hesse <mail@eworm.de>
|
||||||
|
Date: Wed, 6 May 2020 09:35:47 +0200
|
||||||
|
Subject: [PATCH] libmpathpersist: depend on libmultipath
|
||||||
|
|
||||||
|
Without this the build fails with:
|
||||||
|
|
||||||
|
/usr/bin/ld: cannot find -lmultipath
|
||||||
|
|
||||||
|
Signed-off-by: Christian Hesse <mail@eworm.de>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
Makefile | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 1dee3680..ba1d73ba 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -28,7 +28,7 @@ all: $(BUILDDIRS)
|
||||||
|
$(BUILDDIRS):
|
||||||
|
$(MAKE) -C $@
|
||||||
|
|
||||||
|
-multipath multipathd mpathpersist: libmultipath
|
||||||
|
+libmpathpersist multipath multipathd mpathpersist: libmultipath
|
||||||
|
mpathpersist: libmpathpersist
|
||||||
|
|
||||||
|
$(BUILDDIRS.clean):
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,34 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Tue, 12 May 2020 00:39:21 +0200
|
||||||
|
Subject: [PATCH] multipath-tools: Makefile: more dependency fixes for parallel
|
||||||
|
build
|
||||||
|
|
||||||
|
Extend the late fixes from Christian.
|
||||||
|
|
||||||
|
Cc: Christian Hesse <mail@eworm.de>
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
Makefile | 5 +++--
|
||||||
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index ba1d73ba..fec3b73b 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -28,8 +28,9 @@ all: $(BUILDDIRS)
|
||||||
|
$(BUILDDIRS):
|
||||||
|
$(MAKE) -C $@
|
||||||
|
|
||||||
|
-libmpathpersist multipath multipathd mpathpersist: libmultipath
|
||||||
|
-mpathpersist: libmpathpersist
|
||||||
|
+libmultipath libdmmp: libmpathcmd
|
||||||
|
+libmpathpersist multipath multipathd: libmultipath
|
||||||
|
+mpathpersist multipathd: libmpathpersist
|
||||||
|
|
||||||
|
$(BUILDDIRS.clean):
|
||||||
|
$(MAKE) -C ${@:.clean=} clean
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Tue, 12 May 2020 00:39:24 +0200
|
||||||
|
Subject: [PATCH] multipath-tools: Makefile.inc: set -Wno-error=clobbered
|
||||||
|
|
||||||
|
We need to ignore -Wclobbered because gcc has trouble dealing with glibc's
|
||||||
|
implementation of pthread_cleanup_push().
|
||||||
|
|
||||||
|
For some variants of gcc, -Wno-clobbered alone isn't enough if -Werror is also
|
||||||
|
set. Compilation with -Wno-error=clobbered works, though.
|
||||||
|
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
Makefile.inc | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile.inc b/Makefile.inc
|
||||||
|
index d4d1e0dd..9060ac9b 100644
|
||||||
|
--- a/Makefile.inc
|
||||||
|
+++ b/Makefile.inc
|
||||||
|
@@ -91,7 +91,7 @@ TEST_CC_OPTION = $(shell \
|
||||||
|
|
||||||
|
STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)
|
||||||
|
ERROR_DISCARDED_QUALIFIERS := $(call TEST_CC_OPTION,-Werror=discarded-qualifiers,)
|
||||||
|
-WNOCLOBBERED := $(call TEST_CC_OPTION,-Wno-clobbered,)
|
||||||
|
+WNOCLOBBERED := $(call TEST_CC_OPTION,-Wno-clobbered -Wno-error=clobbered,)
|
||||||
|
|
||||||
|
OPTFLAGS = -O2 -g -pipe -Werror -Wall -Wextra -Wformat=2 -Werror=implicit-int \
|
||||||
|
-Werror=implicit-function-declaration -Werror=format-security \
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,91 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Tue, 12 May 2020 00:39:25 +0200
|
||||||
|
Subject: [PATCH] libmultipath: discovery.c: use %z qualifier for size_t
|
||||||
|
|
||||||
|
Otherwise compilation for 32bit targets spits out warnings.
|
||||||
|
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/discovery.c | 16 ++++++++--------
|
||||||
|
1 file changed, 8 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
|
index ee3290cd..ffec5162 100644
|
||||||
|
--- a/libmultipath/discovery.c
|
||||||
|
+++ b/libmultipath/discovery.c
|
||||||
|
@@ -986,7 +986,7 @@ parse_vpd_pg80(const unsigned char *in, char *out, size_t out_len)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len >= out_len) {
|
||||||
|
- condlog(2, "vpd pg80 overflow, %lu/%lu bytes required",
|
||||||
|
+ condlog(2, "vpd pg80 overflow, %zu/%zu bytes required",
|
||||||
|
len + 1, out_len);
|
||||||
|
len = out_len - 1;
|
||||||
|
}
|
||||||
|
@@ -1087,7 +1087,7 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
|
||||||
|
|
||||||
|
len = sprintf(out, "%d", vpd_type);
|
||||||
|
if (2 * vpd_len >= out_len - len) {
|
||||||
|
- condlog(1, "%s: WWID overflow, type %d, %lu/%lu bytes required",
|
||||||
|
+ condlog(1, "%s: WWID overflow, type %d, %zu/%zu bytes required",
|
||||||
|
__func__, vpd_type,
|
||||||
|
2 * vpd_len + len + 1, out_len);
|
||||||
|
vpd_len = (out_len - len - 1) / 2;
|
||||||
|
@@ -1096,7 +1096,7 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
|
||||||
|
len += sprintf(out + len,
|
||||||
|
"%02x", vpd[i]);
|
||||||
|
} else if (vpd_type == 0x8 && vpd_len < 4) {
|
||||||
|
- condlog(1, "%s: VPD length %lu too small for designator type 8",
|
||||||
|
+ condlog(1, "%s: VPD length %zu too small for designator type 8",
|
||||||
|
__func__, vpd_len);
|
||||||
|
return -EINVAL;
|
||||||
|
} else if (vpd_type == 0x8) {
|
||||||
|
@@ -1112,7 +1112,7 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
|
||||||
|
while (len > 2 && vpd[len - 2] == '\0')
|
||||||
|
--len;
|
||||||
|
if (len > out_len - 1) {
|
||||||
|
- condlog(1, "%s: WWID overflow, type 8/%c, %lu/%lu bytes required",
|
||||||
|
+ condlog(1, "%s: WWID overflow, type 8/%c, %zu/%zu bytes required",
|
||||||
|
__func__, out[0], len + 1, out_len);
|
||||||
|
len = out_len - 1;
|
||||||
|
}
|
||||||
|
@@ -1136,7 +1136,7 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
|
||||||
|
while ((p = memchr(vpd, ' ', vpd_len))) {
|
||||||
|
p_len = p - vpd;
|
||||||
|
if (len + p_len > out_len - 1) {
|
||||||
|
- condlog(1, "%s: WWID overflow, type 1, %lu/%lu bytes required",
|
||||||
|
+ condlog(1, "%s: WWID overflow, type 1, %zu/%zu bytes required",
|
||||||
|
__func__, len + p_len, out_len);
|
||||||
|
p_len = out_len - len - 1;
|
||||||
|
}
|
||||||
|
@@ -1162,7 +1162,7 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
|
||||||
|
p_len = vpd_len;
|
||||||
|
if (p_len > 0 && len < out_len - 1) {
|
||||||
|
if (len + p_len > out_len - 1) {
|
||||||
|
- condlog(1, "%s: WWID overflow, type 1, %lu/%lu bytes required",
|
||||||
|
+ condlog(1, "%s: WWID overflow, type 1, %zu/%zu bytes required",
|
||||||
|
__func__, len + p_len + 1, out_len);
|
||||||
|
p_len = out_len - len - 1;
|
||||||
|
}
|
||||||
|
@@ -1186,14 +1186,14 @@ parse_vpd_c0_hp3par(const unsigned char *in, size_t in_len,
|
||||||
|
|
||||||
|
memset(out, 0x0, out_len);
|
||||||
|
if (in_len <= 4 || (in[4] > 3 && in_len < 44)) {
|
||||||
|
- condlog(3, "HP/3PAR vendor specific VPD page length too short: %lu", in_len);
|
||||||
|
+ condlog(3, "HP/3PAR vendor specific VPD page length too short: %zu", in_len);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (in[4] <= 3) /* revision must be > 3 to have Vomlume Name */
|
||||||
|
return -ENODATA;
|
||||||
|
len = get_unaligned_be32(&in[40]);
|
||||||
|
if (len > out_len || len + 44 > in_len) {
|
||||||
|
- condlog(3, "HP/3PAR vendor specific Volume name too long: %lu",
|
||||||
|
+ condlog(3, "HP/3PAR vendor specific Volume name too long: %zu",
|
||||||
|
len);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,185 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Tue, 12 May 2020 00:39:26 +0200
|
||||||
|
Subject: [PATCH] libmultipath: eliminate more signed/unsigned comparisons
|
||||||
|
|
||||||
|
Fix some more compiler warnings about signed/unsigned comparison.
|
||||||
|
I've observed these only on 32bit builds, therefore they went unnoticed
|
||||||
|
before.
|
||||||
|
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/print.c | 12 ++++++------
|
||||||
|
libmultipath/prioritizers/alua_spc3.h | 2 +-
|
||||||
|
multipathd/cli_handlers.c | 20 ++++++++++----------
|
||||||
|
multipathd/main.c | 2 +-
|
||||||
|
4 files changed, 18 insertions(+), 18 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/print.c b/libmultipath/print.c
|
||||||
|
index b944ef32..298b3764 100644
|
||||||
|
--- a/libmultipath/print.c
|
||||||
|
+++ b/libmultipath/print.c
|
||||||
|
@@ -1958,25 +1958,25 @@ char *snprint_config(const struct config *conf, int *len,
|
||||||
|
}
|
||||||
|
|
||||||
|
c = reply + snprint_defaults(conf, reply, maxlen);
|
||||||
|
- if ((c - reply) == maxlen)
|
||||||
|
+ if (c == reply + maxlen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
c += snprint_blacklist(conf, c, reply + maxlen - c);
|
||||||
|
- if ((c - reply) == maxlen)
|
||||||
|
+ if (c == reply + maxlen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
c += snprint_blacklist_except(conf, c, reply + maxlen - c);
|
||||||
|
- if ((c - reply) == maxlen)
|
||||||
|
+ if (c == reply + maxlen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
c += snprint_hwtable(conf, c, reply + maxlen - c,
|
||||||
|
hwtable ? hwtable : conf->hwtable);
|
||||||
|
- if ((c - reply) == maxlen)
|
||||||
|
+ if (c == reply + maxlen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
c += snprint_overrides(conf, c, reply + maxlen - c,
|
||||||
|
conf->overrides);
|
||||||
|
- if ((c - reply) == maxlen)
|
||||||
|
+ if (c == reply + maxlen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (VECTOR_SIZE(conf->mptable) > 0 ||
|
||||||
|
@@ -1984,7 +1984,7 @@ char *snprint_config(const struct config *conf, int *len,
|
||||||
|
c += snprint_mptable(conf, c, reply + maxlen - c,
|
||||||
|
mpvec);
|
||||||
|
|
||||||
|
- if ((c - reply) < maxlen) {
|
||||||
|
+ if (c < reply + maxlen) {
|
||||||
|
if (len)
|
||||||
|
*len = c - reply;
|
||||||
|
return reply;
|
||||||
|
diff --git a/libmultipath/prioritizers/alua_spc3.h b/libmultipath/prioritizers/alua_spc3.h
|
||||||
|
index 18b495ef..7ba2cf4c 100644
|
||||||
|
--- a/libmultipath/prioritizers/alua_spc3.h
|
||||||
|
+++ b/libmultipath/prioritizers/alua_spc3.h
|
||||||
|
@@ -284,7 +284,7 @@ struct rtpg_data {
|
||||||
|
#define RTPG_FOR_EACH_PORT_GROUP(p, g) \
|
||||||
|
for( \
|
||||||
|
g = &(p->data[0]); \
|
||||||
|
- (((char *) g) - ((char *) p)) < get_unaligned_be32(p->length); \
|
||||||
|
+ ((char *) g) < ((char *) p) + get_unaligned_be32(p->length); \
|
||||||
|
g = (struct rtpg_tpg_dscr *) ( \
|
||||||
|
((char *) g) + \
|
||||||
|
sizeof(struct rtpg_tpg_dscr) + \
|
||||||
|
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
|
||||||
|
index 7d878c88..31c3d9fd 100644
|
||||||
|
--- a/multipathd/cli_handlers.c
|
||||||
|
+++ b/multipathd/cli_handlers.c
|
||||||
|
@@ -66,7 +66,7 @@ show_paths (char ** r, int * len, struct vectors * vecs, char * style,
|
||||||
|
c += snprint_foreign_paths(c, reply + maxlen - c,
|
||||||
|
style, pretty);
|
||||||
|
|
||||||
|
- again = ((c - reply) == (maxlen - 1));
|
||||||
|
+ again = (c == reply + maxlen - 1);
|
||||||
|
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
@@ -102,7 +102,7 @@ show_path (char ** r, int * len, struct vectors * vecs, struct path *pp,
|
||||||
|
|
||||||
|
c += snprint_path(c, reply + maxlen - c, style, pp, 0);
|
||||||
|
|
||||||
|
- again = ((c - reply) == (maxlen - 1));
|
||||||
|
+ again = (c == reply + maxlen - 1);
|
||||||
|
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
@@ -131,7 +131,7 @@ show_map_topology (char ** r, int * len, struct multipath * mpp,
|
||||||
|
c = reply;
|
||||||
|
|
||||||
|
c += snprint_multipath_topology(c, reply + maxlen - c, mpp, 2);
|
||||||
|
- again = ((c - reply) == (maxlen - 1));
|
||||||
|
+ again = (c == reply + maxlen - 1);
|
||||||
|
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
@@ -171,7 +171,7 @@ show_maps_topology (char ** r, int * len, struct vectors * vecs)
|
||||||
|
}
|
||||||
|
c += snprint_foreign_topology(c, reply + maxlen - c, 2);
|
||||||
|
|
||||||
|
- again = ((c - reply) == (maxlen - 1));
|
||||||
|
+ again = (c == reply + maxlen - 1);
|
||||||
|
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
@@ -209,7 +209,7 @@ show_maps_json (char ** r, int * len, struct vectors * vecs)
|
||||||
|
c = reply;
|
||||||
|
|
||||||
|
c += snprint_multipath_topology_json(c, maxlen, vecs);
|
||||||
|
- again = ((c - reply) == maxlen);
|
||||||
|
+ again = (c == reply + maxlen);
|
||||||
|
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
@@ -238,7 +238,7 @@ show_map_json (char ** r, int * len, struct multipath * mpp,
|
||||||
|
c = reply;
|
||||||
|
|
||||||
|
c += snprint_multipath_map_json(c, maxlen, mpp);
|
||||||
|
- again = ((c - reply) == maxlen);
|
||||||
|
+ again = (c == reply + maxlen);
|
||||||
|
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
@@ -487,7 +487,7 @@ show_map (char ** r, int *len, struct multipath * mpp, char * style,
|
||||||
|
c += snprint_multipath(c, reply + maxlen - c, style,
|
||||||
|
mpp, pretty);
|
||||||
|
|
||||||
|
- again = ((c - reply) == (maxlen - 1));
|
||||||
|
+ again = (c == reply + maxlen - 1);
|
||||||
|
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
@@ -533,7 +533,7 @@ show_maps (char ** r, int *len, struct vectors * vecs, char * style,
|
||||||
|
}
|
||||||
|
c += snprint_foreign_multipaths(c, reply + maxlen - c,
|
||||||
|
style, pretty);
|
||||||
|
- again = ((c - reply) == (maxlen - 1));
|
||||||
|
+ again = (c == reply + maxlen - 1);
|
||||||
|
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
@@ -1297,7 +1297,7 @@ show_blacklist (char ** r, int * len)
|
||||||
|
|
||||||
|
c = reply;
|
||||||
|
c += snprint_blacklist_report(conf, c, maxlen);
|
||||||
|
- again = ((c - reply) == maxlen);
|
||||||
|
+ again = (c == reply + maxlen);
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
pthread_cleanup_pop(1);
|
||||||
|
@@ -1339,7 +1339,7 @@ show_devices (char ** r, int * len, struct vectors *vecs)
|
||||||
|
|
||||||
|
c = reply;
|
||||||
|
c += snprint_devices(conf, c, maxlen, vecs);
|
||||||
|
- again = ((c - reply) == maxlen);
|
||||||
|
+ again = (c == reply + maxlen);
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
pthread_cleanup_pop(1);
|
||||||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
|
index 8baf9abe..6b7db2c0 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -2374,7 +2374,7 @@ checkerloop (void *ap)
|
||||||
|
conf = get_multipath_config();
|
||||||
|
max_checkint = conf->max_checkint;
|
||||||
|
put_multipath_config(conf);
|
||||||
|
- if (diff_time.tv_sec > max_checkint)
|
||||||
|
+ if (diff_time.tv_sec > (time_t)max_checkint)
|
||||||
|
condlog(1, "path checkers took longer "
|
||||||
|
"than %lu seconds, consider "
|
||||||
|
"increasing max_polling_interval",
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,49 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Tue, 12 May 2020 00:39:27 +0200
|
||||||
|
Subject: [PATCH] libmultipath: set_uint: fix parsing for 32bit
|
||||||
|
|
||||||
|
On architectures where sizeof(long) == sizeof(int), the code wouldn't
|
||||||
|
work as intended. Use strtoul instead. As strtoul happily parses
|
||||||
|
negative numbers as input, require the number to begin with a digit.
|
||||||
|
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/dict.c | 11 +++++++----
|
||||||
|
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||||
|
index 3e25e74f..0e9ea387 100644
|
||||||
|
--- a/libmultipath/dict.c
|
||||||
|
+++ b/libmultipath/dict.c
|
||||||
|
@@ -60,19 +60,22 @@ static int
|
||||||
|
set_uint(vector strvec, void *ptr)
|
||||||
|
{
|
||||||
|
unsigned int *uint_ptr = (unsigned int *)ptr;
|
||||||
|
- char *buff, *eptr;
|
||||||
|
- long res;
|
||||||
|
+ char *buff, *eptr, *p;
|
||||||
|
+ unsigned long res;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
buff = set_value(strvec);
|
||||||
|
if (!buff)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
- res = strtol(buff, &eptr, 10);
|
||||||
|
+ p = buff;
|
||||||
|
+ while (isspace(*p))
|
||||||
|
+ p++;
|
||||||
|
+ res = strtoul(p, &eptr, 10);
|
||||||
|
if (eptr > buff)
|
||||||
|
while (isspace(*eptr))
|
||||||
|
eptr++;
|
||||||
|
- if (*buff == '\0' || *eptr != '\0' || res < 0 || res > UINT_MAX) {
|
||||||
|
+ if (*buff == '\0' || *eptr != '\0' || !isdigit(*p) || res > UINT_MAX) {
|
||||||
|
condlog(1, "%s: invalid value for %s: \"%s\"",
|
||||||
|
__func__, (char*)VECTOR_SLOT(strvec, 0), buff);
|
||||||
|
rc = 1;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Tue, 12 May 2020 22:38:22 +0200
|
||||||
|
Subject: [PATCH] multipath-tools Makefile: add install dependency
|
||||||
|
|
||||||
|
$(libdir) must exist before running "make install" on prioritizer, checker,
|
||||||
|
and foreign libraries.
|
||||||
|
|
||||||
|
Cc: Christian Hesse <mail@eworm.de>
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
Makefile | 4 ++++
|
||||||
|
1 file changed, 4 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index fec3b73b..8bcaba66 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -32,6 +32,10 @@ libmultipath libdmmp: libmpathcmd
|
||||||
|
libmpathpersist multipath multipathd: libmultipath
|
||||||
|
mpathpersist multipathd: libmpathpersist
|
||||||
|
|
||||||
|
+libmultipath/checkers.install \
|
||||||
|
+ libmultipath/prioritizers.install \
|
||||||
|
+ libmultipath/foreign.install: libmultipath.install
|
||||||
|
+
|
||||||
|
$(BUILDDIRS.clean):
|
||||||
|
$(MAKE) -C ${@:.clean=} clean
|
||||||
|
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,66 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 13 Apr 2017 07:22:23 -0500
|
||||||
|
Subject: [PATCH] RH: fixup udev rules for redhat
|
||||||
|
|
||||||
|
The multipath rules need to run after scsi_id is run. This means moving
|
||||||
|
them after 60-persistent-storage.rules for redhat. Redhat also uses a
|
||||||
|
different naming scheme for partitions than SuSE.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
Makefile.inc | 2 +-
|
||||||
|
kpartx/kpartx.rules | 2 +-
|
||||||
|
multipath/Makefile | 4 ++--
|
||||||
|
3 files changed, 4 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile.inc b/Makefile.inc
|
||||||
|
index 9060ac9b..034752d9 100644
|
||||||
|
--- a/Makefile.inc
|
||||||
|
+++ b/Makefile.inc
|
||||||
|
@@ -53,7 +53,7 @@ endif
|
||||||
|
prefix =
|
||||||
|
exec_prefix = $(prefix)
|
||||||
|
usr_prefix = $(prefix)
|
||||||
|
-bindir = $(exec_prefix)/sbin
|
||||||
|
+bindir = $(exec_prefix)/usr/sbin
|
||||||
|
libudevdir = $(prefix)/$(SYSTEMDPATH)/udev
|
||||||
|
udevrulesdir = $(libudevdir)/rules.d
|
||||||
|
multipathdir = $(TOPDIR)/libmultipath
|
||||||
|
diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
|
||||||
|
index 8f990494..8a3a1718 100644
|
||||||
|
--- a/kpartx/kpartx.rules
|
||||||
|
+++ b/kpartx/kpartx.rules
|
||||||
|
@@ -32,6 +32,6 @@ LABEL="mpath_kpartx_end"
|
||||||
|
GOTO="kpartx_end"
|
||||||
|
|
||||||
|
LABEL="run_kpartx"
|
||||||
|
-RUN+="/sbin/kpartx -un -p -part /dev/$name"
|
||||||
|
+RUN+="/sbin/kpartx -un /dev/$name"
|
||||||
|
|
||||||
|
LABEL="kpartx_end"
|
||||||
|
diff --git a/multipath/Makefile b/multipath/Makefile
|
||||||
|
index 0828a8f7..b9bbb3cf 100644
|
||||||
|
--- a/multipath/Makefile
|
||||||
|
+++ b/multipath/Makefile
|
||||||
|
@@ -24,7 +24,7 @@ install:
|
||||||
|
$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
|
||||||
|
$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
|
||||||
|
$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
|
||||||
|
- $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
|
||||||
|
+ $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
|
||||||
|
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man8dir)
|
||||||
|
$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(man8dir)
|
||||||
|
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir)
|
||||||
|
@@ -33,7 +33,7 @@ install:
|
||||||
|
uninstall:
|
||||||
|
$(RM) $(DESTDIR)$(bindir)/$(EXEC)
|
||||||
|
$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
|
||||||
|
- $(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
|
||||||
|
+ $(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
|
||||||
|
$(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz
|
||||||
|
$(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
|
||||||
|
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,105 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 2 Jul 2014 12:49:53 -0500
|
||||||
|
Subject: [PATCH] RH: Remove the property blacklist exception builtin
|
||||||
|
|
||||||
|
Multipath set the default property blacklist exceptions to
|
||||||
|
(ID_SCSI_VPD|ID_WWN). This has the effect of blacklisting some internal
|
||||||
|
devices. These devices may never have multiple paths, but it is nice
|
||||||
|
to be able to set multipath up on them all the same. This patch simply
|
||||||
|
removes the default, and makes it so that if no property
|
||||||
|
blacklist_exception is given, then devices aren't failed for not matching
|
||||||
|
it.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/blacklist.c | 9 ++-------
|
||||||
|
multipath/multipath.conf.5 | 11 ++++++-----
|
||||||
|
tests/blacklist.c | 6 ++----
|
||||||
|
3 files changed, 10 insertions(+), 16 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
|
||||||
|
index 00e8dbdb..d9691b17 100644
|
||||||
|
--- a/libmultipath/blacklist.c
|
||||||
|
+++ b/libmultipath/blacklist.c
|
||||||
|
@@ -204,12 +204,6 @@ setup_default_blist (struct config * conf)
|
||||||
|
if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
- str = STRDUP("(SCSI_IDENT_|ID_WWN)");
|
||||||
|
- if (!str)
|
||||||
|
- return 1;
|
||||||
|
- if (store_ble(conf->elist_property, str, ORIGIN_DEFAULT))
|
||||||
|
- return 1;
|
||||||
|
-
|
||||||
|
vector_foreach_slot (conf->hwtable, hwe, i) {
|
||||||
|
if (hwe->bl_product) {
|
||||||
|
if (find_blacklist_device(conf->blist_device,
|
||||||
|
@@ -411,7 +405,8 @@ filter_property(struct config *conf, struct udev_device *udev, int lvl,
|
||||||
|
*uid_attribute != '\0';
|
||||||
|
bool uid_attr_seen = false;
|
||||||
|
|
||||||
|
- r = MATCH_PROPERTY_BLIST_MISSING;
|
||||||
|
+ if (VECTOR_SIZE(conf->elist_property))
|
||||||
|
+ r = MATCH_PROPERTY_BLIST_MISSING;
|
||||||
|
udev_list_entry_foreach(list_entry,
|
||||||
|
udev_device_get_properties_list_entry(udev)) {
|
||||||
|
|
||||||
|
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
||||||
|
index 05a5e8ff..3455b1cc 100644
|
||||||
|
--- a/multipath/multipath.conf.5
|
||||||
|
+++ b/multipath/multipath.conf.5
|
||||||
|
@@ -1286,9 +1286,14 @@ keywords. Both are regular expressions. For a full description of these keywords
|
||||||
|
Regular expression for an udev property. All
|
||||||
|
devices that have matching udev properties will be excluded/included.
|
||||||
|
The handling of the \fIproperty\fR keyword is special,
|
||||||
|
-because devices \fBmust\fR have at least one whitelisted udev property;
|
||||||
|
+because if a property blacklist_exception is set, devices \fBmust\fR have at
|
||||||
|
+least one whitelisted udev property;
|
||||||
|
otherwise they're treated as blacklisted, and the message
|
||||||
|
"\fIblacklisted, udev property missing\fR" is displayed in the logs.
|
||||||
|
+For example, setting the property blacklist_exception to
|
||||||
|
+\fB(SCSI_IDENT_|ID_WWN)\fR, will cause well-behaved SCSI devices and devices
|
||||||
|
+that provide a WWN (World Wide Number) to be included, and all others to be
|
||||||
|
+excluded. This works to exclude most non-multipathable devices.
|
||||||
|
.
|
||||||
|
.RS
|
||||||
|
.PP
|
||||||
|
@@ -1299,10 +1304,6 @@ Blacklisting by missing properties is only applied to devices which do have the
|
||||||
|
property specified by \fIuid_attribute\fR (e.g. \fIID_SERIAL\fR)
|
||||||
|
set. Previously, it was applied to every device, possibly causing devices to be
|
||||||
|
blacklisted because of temporary I/O error conditions.
|
||||||
|
-.PP
|
||||||
|
-The default \fIblacklist exception\fR is: \fB(SCSI_IDENT_|ID_WWN)\fR, causing
|
||||||
|
-well-behaved SCSI devices and devices that provide a WWN (World Wide Number)
|
||||||
|
-to be included, and all others to be excluded.
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B protocol
|
||||||
|
diff --git a/tests/blacklist.c b/tests/blacklist.c
|
||||||
|
index 6e7c1864..cc8a9a4a 100644
|
||||||
|
--- a/tests/blacklist.c
|
||||||
|
+++ b/tests/blacklist.c
|
||||||
|
@@ -271,7 +271,7 @@ static void test_property_missing(void **state)
|
||||||
|
conf.blist_property = blist_property_wwn;
|
||||||
|
expect_condlog(3, "sdb: blacklisted, udev property missing\n");
|
||||||
|
assert_int_equal(filter_property(&conf, &udev, 3, "ID_SERIAL"),
|
||||||
|
- MATCH_PROPERTY_BLIST_MISSING);
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
assert_int_equal(filter_property(&conf, &udev, 3, "ID_BLAH"),
|
||||||
|
MATCH_NOTHING);
|
||||||
|
assert_int_equal(filter_property(&conf, &udev, 3, ""),
|
||||||
|
@@ -363,9 +363,7 @@ static void test_filter_path_missing1(void **state)
|
||||||
|
conf.blist_device = blist_device_foo_bar;
|
||||||
|
conf.blist_protocol = blist_protocol_fcp;
|
||||||
|
conf.blist_wwid = blist_wwid_xyzzy;
|
||||||
|
- expect_condlog(3, "sdb: blacklisted, udev property missing\n");
|
||||||
|
- assert_int_equal(filter_path(&conf, &miss1_pp),
|
||||||
|
- MATCH_PROPERTY_BLIST_MISSING);
|
||||||
|
+ assert_int_equal(filter_path(&conf, &miss1_pp), MATCH_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This one matches the property whitelist, to test the other missing
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,106 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 15 Oct 2014 10:39:30 -0500
|
||||||
|
Subject: [PATCH] RH: don't start without a config file
|
||||||
|
|
||||||
|
If /etc/multipath.conf doesn't exist, don't start multipathd and blacklist
|
||||||
|
all devices when running multipath. A completely blank configuration file
|
||||||
|
is almost never what users want. Also, people may have the multipath
|
||||||
|
packages installed but don't want to use them. This patch provides a
|
||||||
|
simple way to disable multipath. Simply removing or renaming
|
||||||
|
/etc/multipath.conf will keep multipath from doing anything.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.c | 15 +++++++++++++++
|
||||||
|
libmultipath/config.h | 1 +
|
||||||
|
multipath/multipath.rules | 1 +
|
||||||
|
multipathd/multipathd.8 | 2 ++
|
||||||
|
multipathd/multipathd.service | 1 +
|
||||||
|
5 files changed, 20 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||||
|
index b4d87689..b36778b0 100644
|
||||||
|
--- a/libmultipath/config.c
|
||||||
|
+++ b/libmultipath/config.c
|
||||||
|
@@ -26,6 +26,7 @@
|
||||||
|
#include "devmapper.h"
|
||||||
|
#include "mpath_cmd.h"
|
||||||
|
#include "propsel.h"
|
||||||
|
+#include "version.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
hwe_strmatch (const struct hwentry *hwe1, const struct hwentry *hwe2)
|
||||||
|
@@ -778,6 +779,20 @@ load_config (char * file)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
|
||||||
|
+ } else {
|
||||||
|
+ condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
|
||||||
|
+ if (conf->blist_devnode == NULL) {
|
||||||
|
+ conf->blist_devnode = vector_alloc();
|
||||||
|
+ if (!conf->blist_devnode) {
|
||||||
|
+ condlog(0, "cannot allocate blacklist\n");
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (store_ble(conf->blist_devnode, strdup(".*"),
|
||||||
|
+ ORIGIN_NO_CONFIG)) {
|
||||||
|
+ condlog(0, "cannot store default no-config blacklist\n");
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
conf->processed_main_config = 1;
|
||||||
|
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||||
|
index ceecff2d..3368d8c9 100644
|
||||||
|
--- a/libmultipath/config.h
|
||||||
|
+++ b/libmultipath/config.h
|
||||||
|
@@ -9,6 +9,7 @@
|
||||||
|
|
||||||
|
#define ORIGIN_DEFAULT 0
|
||||||
|
#define ORIGIN_CONFIG 1
|
||||||
|
+#define ORIGIN_NO_CONFIG 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In kernel, fast_io_fail == 0 means immediate failure on rport delete.
|
||||||
|
diff --git a/multipath/multipath.rules b/multipath/multipath.rules
|
||||||
|
index 9df11a95..0486bf70 100644
|
||||||
|
--- a/multipath/multipath.rules
|
||||||
|
+++ b/multipath/multipath.rules
|
||||||
|
@@ -9,6 +9,7 @@ IMPORT{cmdline}="nompath"
|
||||||
|
ENV{nompath}=="?*", GOTO="end_mpath"
|
||||||
|
IMPORT{cmdline}="multipath"
|
||||||
|
ENV{multipath}=="off", GOTO="end_mpath"
|
||||||
|
+TEST!="/etc/multipath.conf", GOTO="end_mpath"
|
||||||
|
|
||||||
|
ENV{DEVTYPE}!="partition", GOTO="test_dev"
|
||||||
|
IMPORT{parent}="DM_MULTIPATH_DEVICE_PATH"
|
||||||
|
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8
|
||||||
|
index 048a838d..8bd47a80 100644
|
||||||
|
--- a/multipathd/multipathd.8
|
||||||
|
+++ b/multipathd/multipathd.8
|
||||||
|
@@ -39,6 +39,8 @@ map regains its maximum performance and redundancy.
|
||||||
|
This daemon executes the external \fBmultipath\fR tool when events occur.
|
||||||
|
In turn, the multipath tool signals the multipathd daemon when it is done with
|
||||||
|
devmap reconfiguration, so that it can refresh its failed path list.
|
||||||
|
+
|
||||||
|
+In this Linux distribution, multipathd does not run unless a /etc/multipath.conf file exists.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.\" ----------------------------------------------------------------------------
|
||||||
|
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
|
||||||
|
index ba24983e..17434cef 100644
|
||||||
|
--- a/multipathd/multipathd.service
|
||||||
|
+++ b/multipathd/multipathd.service
|
||||||
|
@@ -4,6 +4,7 @@ Wants=systemd-udev-trigger.service systemd-udev-settle.service
|
||||||
|
Before=iscsi.service iscsid.service lvm2-activation-early.service
|
||||||
|
Before=local-fs-pre.target blk-availability.service
|
||||||
|
After=multipathd.socket systemd-udev-trigger.service systemd-udev-settle.service
|
||||||
|
+ConditionPathExists=/etc/multipath.conf
|
||||||
|
DefaultDependencies=no
|
||||||
|
Conflicts=shutdown.target
|
||||||
|
ConditionKernelCommandLine=!nompath
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,64 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 19 Apr 2017 06:10:01 -0500
|
||||||
|
Subject: [PATCH] RH: use rpm optflags if present
|
||||||
|
|
||||||
|
Use the passed in optflags when compiling as an RPM, and keep the
|
||||||
|
default flags as close as possible to the current fedora flags, while
|
||||||
|
still being generic.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
Makefile.inc | 29 +++++++++++++++++++++--------
|
||||||
|
1 file changed, 21 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile.inc b/Makefile.inc
|
||||||
|
index 034752d9..c2abd301 100644
|
||||||
|
--- a/Makefile.inc
|
||||||
|
+++ b/Makefile.inc
|
||||||
|
@@ -89,16 +89,29 @@ TEST_CC_OPTION = $(shell \
|
||||||
|
echo "$(2)"; \
|
||||||
|
fi)
|
||||||
|
|
||||||
|
-STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)
|
||||||
|
ERROR_DISCARDED_QUALIFIERS := $(call TEST_CC_OPTION,-Werror=discarded-qualifiers,)
|
||||||
|
WNOCLOBBERED := $(call TEST_CC_OPTION,-Wno-clobbered -Wno-error=clobbered,)
|
||||||
|
+ifndef RPM_OPT_FLAGS
|
||||||
|
+ STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)
|
||||||
|
+ OPTFLAGS = -O2 -g -pipe -Wall -Werror=format-security \
|
||||||
|
+ -Wp,-D_FORTIFY_SOURCE=2 -fexceptions \
|
||||||
|
+ $(STACKPROT) -grecord-gcc-switches \
|
||||||
|
+ -fasynchronous-unwind-tables
|
||||||
|
+ ifeq ($(shell test -f /usr/lib/rpm/redhat/redhat-hardened-cc1 && echo 1),1)
|
||||||
|
+ OPTFLAGS += -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1
|
||||||
|
+ endif
|
||||||
|
+ ifeq ($(shell test -f /usr/lib/rpm/redhat/redhat-annobin-cc1 && echo 1),1)
|
||||||
|
+ OPTFLAGS += -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1
|
||||||
|
+ endif
|
||||||
|
+else
|
||||||
|
+ OPTFLAGS = $(RPM_OPT_FLAGS)
|
||||||
|
+endif
|
||||||
|
+OPTFLAGS += -Werror -Wextra -Wstrict-prototypes -Wformat=2 \
|
||||||
|
+ -Werror=implicit-int -Werror=implicit-function-declaration \
|
||||||
|
+ $(WNOCLOBBERED) \
|
||||||
|
+ -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) \
|
||||||
|
+ --param=ssp-buffer-size=4
|
||||||
|
|
||||||
|
-OPTFLAGS = -O2 -g -pipe -Werror -Wall -Wextra -Wformat=2 -Werror=implicit-int \
|
||||||
|
- -Werror=implicit-function-declaration -Werror=format-security \
|
||||||
|
- $(WNOCLOBBERED) \
|
||||||
|
- -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) \
|
||||||
|
- $(STACKPROT) --param=ssp-buffer-size=4
|
||||||
|
-CPPFLAGS := -Wp,-D_FORTIFY_SOURCE=2
|
||||||
|
CFLAGS := $(OPTFLAGS) -DBIN_DIR=\"$(bindir)\" -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \
|
||||||
|
-MMD -MP $(CFLAGS)
|
||||||
|
BIN_CFLAGS = -fPIE -DPIE
|
||||||
|
@@ -135,4 +148,4 @@ check_file = $(shell \
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
@echo building $@ because of $?
|
||||||
|
- $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
|
||||||
|
+ $(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,774 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 16 Oct 2014 15:49:01 -0500
|
||||||
|
Subject: [PATCH] RH: add mpathconf
|
||||||
|
|
||||||
|
mpathconf is a program (largely based on lvmcomf) to help users
|
||||||
|
configure /etc/multipath.conf and enable or disable multipathing. It
|
||||||
|
has a couple of built-in options that can be set directly from the
|
||||||
|
command line. But, mostly it is used to get a multipath.conf file
|
||||||
|
with the OS defaults, and to enable and disable multipathing via
|
||||||
|
a single command.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.c | 2 +
|
||||||
|
multipath/Makefile | 5 +
|
||||||
|
multipath/mpathconf | 555 ++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
multipath/mpathconf.8 | 135 ++++++++++
|
||||||
|
4 files changed, 697 insertions(+)
|
||||||
|
create mode 100644 multipath/mpathconf
|
||||||
|
create mode 100644 multipath/mpathconf.8
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||||
|
index b36778b0..26f8e050 100644
|
||||||
|
--- a/libmultipath/config.c
|
||||||
|
+++ b/libmultipath/config.c
|
||||||
|
@@ -781,6 +781,8 @@ load_config (char * file)
|
||||||
|
factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
|
||||||
|
} else {
|
||||||
|
condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
|
||||||
|
+ condlog(0, "You can run \"/sbin/mpathconf --enable\" to create");
|
||||||
|
+ condlog(0, "/etc/multipath.conf. See man mpathconf(8) for more details");
|
||||||
|
if (conf->blist_devnode == NULL) {
|
||||||
|
conf->blist_devnode = vector_alloc();
|
||||||
|
if (!conf->blist_devnode) {
|
||||||
|
diff --git a/multipath/Makefile b/multipath/Makefile
|
||||||
|
index b9bbb3cf..e720c7f6 100644
|
||||||
|
--- a/multipath/Makefile
|
||||||
|
+++ b/multipath/Makefile
|
||||||
|
@@ -18,10 +18,12 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
|
||||||
|
$(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS) $(LIBDEPS)
|
||||||
|
$(GZIP) $(EXEC).8 > $(EXEC).8.gz
|
||||||
|
$(GZIP) $(EXEC).conf.5 > $(EXEC).conf.5.gz
|
||||||
|
+ $(GZIP) mpathconf.8 > mpathconf.8.gz
|
||||||
|
|
||||||
|
install:
|
||||||
|
$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
|
||||||
|
$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
|
||||||
|
+ $(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/
|
||||||
|
$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
|
||||||
|
$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
|
||||||
|
$(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
|
||||||
|
@@ -29,13 +31,16 @@ install:
|
||||||
|
$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(man8dir)
|
||||||
|
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir)
|
||||||
|
$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir)
|
||||||
|
+ $(INSTALL_PROGRAM) -m 644 mpathconf.8.gz $(DESTDIR)$(man8dir)
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
$(RM) $(DESTDIR)$(bindir)/$(EXEC)
|
||||||
|
$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
|
||||||
|
$(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
|
||||||
|
+ $(RM) $(DESTDIR)$(bindir)/mpathconf
|
||||||
|
$(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz
|
||||||
|
$(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
|
||||||
|
+ $(RM) $(DESTDIR)$(man8dir)/mpathconf.8.gz
|
||||||
|
|
||||||
|
clean: dep_clean
|
||||||
|
$(RM) core *.o $(EXEC) *.gz
|
||||||
|
diff --git a/multipath/mpathconf b/multipath/mpathconf
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..f34003c9
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/multipath/mpathconf
|
||||||
|
@@ -0,0 +1,555 @@
|
||||||
|
+#!/bin/bash
|
||||||
|
+#
|
||||||
|
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||||
|
+#
|
||||||
|
+# This file is part of the device-mapper-multipath package.
|
||||||
|
+#
|
||||||
|
+# This copyrighted material is made available to anyone wishing to use,
|
||||||
|
+# modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
+# of the GNU General Public License v.2.
|
||||||
|
+#
|
||||||
|
+# You should have received a copy of the GNU General Public License
|
||||||
|
+# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Simple editting of /etc/multipath.conf
|
||||||
|
+# This program was largely ripped off from lvmconf
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+unset ENABLE FIND FRIENDLY PROPERTY FOREIGN MODULE MULTIPATHD HAVE_DISABLE HAVE_WWID_DISABLE HAVE_FIND HAVE_BLACKLIST HAVE_EXCEPTIONS HAVE_DEFAULTS HAVE_FRIENDLY HAVE_PROPERTY HAVE_FOREIGN HAVE_MULTIPATHD HAVE_MODULE HAVE_OUTFILE SHOW_STATUS CHANGED_CONFIG WWID_LIST
|
||||||
|
+
|
||||||
|
+DEFAULT_CONFIG="# device-mapper-multipath configuration file
|
||||||
|
+
|
||||||
|
+# For a complete list of the default configuration values, run either:
|
||||||
|
+# # multipath -t
|
||||||
|
+# or
|
||||||
|
+# # multipathd show config
|
||||||
|
+
|
||||||
|
+# For a list of configuration options with descriptions, see the
|
||||||
|
+# multipath.conf man page.
|
||||||
|
+
|
||||||
|
+defaults {
|
||||||
|
+ user_friendly_names yes
|
||||||
|
+ find_multipaths yes
|
||||||
|
+ enable_foreign \"^$\"
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+blacklist_exceptions {
|
||||||
|
+ property \"(SCSI_IDENT_|ID_WWN)\"
|
||||||
|
+}"
|
||||||
|
+
|
||||||
|
+CONFIGFILE="/etc/multipath.conf"
|
||||||
|
+OUTPUTFILE="/etc/multipath.conf"
|
||||||
|
+MULTIPATHDIR="/etc/multipath"
|
||||||
|
+TMPFILE="/etc/multipath/.multipath.conf.tmp"
|
||||||
|
+WWIDS=0
|
||||||
|
+
|
||||||
|
+function usage
|
||||||
|
+{
|
||||||
|
+ echo "usage: $0 <command>"
|
||||||
|
+ echo ""
|
||||||
|
+ echo "Commands:"
|
||||||
|
+ echo "Enable: --enable "
|
||||||
|
+ echo "Disable: --disable"
|
||||||
|
+ echo "Only allow certain wwids (instead of enable): --allow <WWID>"
|
||||||
|
+ echo "Set user_friendly_names (Default y): --user_friendly_names <y|n>"
|
||||||
|
+ echo "Set find_multipaths (Default y): --find_multipaths <y|n>"
|
||||||
|
+ echo "Set default property blacklist (Default y): --property_blacklist <y|n>"
|
||||||
|
+ echo "Set enable_foreign to show foreign devices (Default n): --enable_foreign <y|n>"
|
||||||
|
+ echo "Load the dm-multipath modules on enable (Default y): --with_module <y|n>"
|
||||||
|
+ echo "start/stop/reload multipathd (Default n): --with_multipathd <y|n>"
|
||||||
|
+ echo "select output file (Default /etc/multipath.conf): --outfile <FILE>"
|
||||||
|
+ echo ""
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function add_wwid
|
||||||
|
+{
|
||||||
|
+ INDEX=0
|
||||||
|
+ while [ "$INDEX" -lt "$WWIDS" ] ; do
|
||||||
|
+ if [ "$1" = "${WWID_LIST[$INDEX]}" ] ; then
|
||||||
|
+ return
|
||||||
|
+ fi
|
||||||
|
+ ((INDEX++))
|
||||||
|
+ done
|
||||||
|
+ WWID_LIST[$WWIDS]="$1"
|
||||||
|
+ ((WWIDS++))
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function get_dm_deps
|
||||||
|
+{
|
||||||
|
+ shift 3
|
||||||
|
+ while [ -n "$1" -a -n "$2" ]; do
|
||||||
|
+ MAJOR=$(echo $1 | tr -d '(,')
|
||||||
|
+ MINOR=$(echo $2 | tr -d ')')
|
||||||
|
+ UUID=`dmsetup info -c --noheadings -o uuid -j $MAJOR -m $MINOR 2> /dev/null`
|
||||||
|
+ if [ -n "$UUID" ] ; then
|
||||||
|
+ set_dm_wwid $UUID
|
||||||
|
+ fi
|
||||||
|
+ shift 2
|
||||||
|
+ done
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function set_dm_wwid
|
||||||
|
+{
|
||||||
|
+ if [[ "$1" =~ ^part[[:digit:]]+-mpath- ]] ; then
|
||||||
|
+ add_wwid "${1##part*-mpath-}"
|
||||||
|
+ elif [[ "$1" =~ ^mpath- ]] ; then
|
||||||
|
+ add_wwid "${1##mpath-}"
|
||||||
|
+ else
|
||||||
|
+ get_dm_deps `dmsetup deps -u $1`
|
||||||
|
+ fi
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function set_wwid
|
||||||
|
+{
|
||||||
|
+ UUID=""
|
||||||
|
+ if [[ "$1" =~ ^[[:digit:]]+:[[:digit:]]+$ ]] ; then
|
||||||
|
+ MAJOR=${1%%:*}
|
||||||
|
+ MINOR=${1##*:}
|
||||||
|
+ UUID=`dmsetup info -c --noheadings -o uuid -j $MAJOR -m $MINOR 2> /dev/null`
|
||||||
|
+ else
|
||||||
|
+ UUID=`dmsetup info -c --noheadings -o uuid $1 2> /dev/null`
|
||||||
|
+ fi
|
||||||
|
+ if [ -n "$UUID" ] ; then
|
||||||
|
+ set_dm_wwid $UUID
|
||||||
|
+ else
|
||||||
|
+ add_wwid "$1"
|
||||||
|
+ fi
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function parse_args
|
||||||
|
+{
|
||||||
|
+ while [ -n "$1" ]; do
|
||||||
|
+ case $1 in
|
||||||
|
+ --enable)
|
||||||
|
+ ENABLE=1
|
||||||
|
+ shift
|
||||||
|
+ ;;
|
||||||
|
+ --disable)
|
||||||
|
+ ENABLE=0
|
||||||
|
+ shift
|
||||||
|
+ ;;
|
||||||
|
+ --allow)
|
||||||
|
+ ENABLE=2
|
||||||
|
+ if [ -n "$2" ]; then
|
||||||
|
+ set_wwid $2
|
||||||
|
+ shift 2
|
||||||
|
+ else
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ ;;
|
||||||
|
+ --user_friendly_names)
|
||||||
|
+ if [ -n "$2" ]; then
|
||||||
|
+ FRIENDLY=$2
|
||||||
|
+ shift 2
|
||||||
|
+ else
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ ;;
|
||||||
|
+ --find_multipaths)
|
||||||
|
+ if [ -n "$2" ]; then
|
||||||
|
+ FIND=$2
|
||||||
|
+ shift 2
|
||||||
|
+ else
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ ;;
|
||||||
|
+ --property_blacklist)
|
||||||
|
+ if [ -n "$2" ]; then
|
||||||
|
+ PROPERTY=$2
|
||||||
|
+ shift 2
|
||||||
|
+ else
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ ;;
|
||||||
|
+ --enable_foreign)
|
||||||
|
+ if [ -n "$2" ]; then
|
||||||
|
+ FOREIGN=$2
|
||||||
|
+ shift 2
|
||||||
|
+ else
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ ;;
|
||||||
|
+ --with_module)
|
||||||
|
+ if [ -n "$2" ]; then
|
||||||
|
+ MODULE=$2
|
||||||
|
+ shift 2
|
||||||
|
+ else
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ ;;
|
||||||
|
+ --with_multipathd)
|
||||||
|
+ if [ -n "$2" ]; then
|
||||||
|
+ MULTIPATHD=$2
|
||||||
|
+ shift 2
|
||||||
|
+ else
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ ;;
|
||||||
|
+ --outfile)
|
||||||
|
+ if [ -n "$2" ]; then
|
||||||
|
+ OUTPUTFILE=$2
|
||||||
|
+ HAVE_OUTFILE=1
|
||||||
|
+ shift 2
|
||||||
|
+ else
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ ;;
|
||||||
|
+ *)
|
||||||
|
+ usage
|
||||||
|
+ exit
|
||||||
|
+ esac
|
||||||
|
+ done
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function validate_args
|
||||||
|
+{
|
||||||
|
+ if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$PROPERTY" -o -n "$MODULE" ]; then
|
||||||
|
+ echo "ignoring extra parameters on disable"
|
||||||
|
+ FRIENDLY=""
|
||||||
|
+ FIND=""
|
||||||
|
+ PROPERTY=""
|
||||||
|
+ MODULE=""
|
||||||
|
+ fi
|
||||||
|
+ if [ -n "$FRIENDLY" ] && [ "$FRIENDLY" != "y" -a "$FRIENDLY" != "n" ]; then
|
||||||
|
+ echo "--user_friendly_names must be either 'y' or 'n'"
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ if [ -n "$FIND" ] && [ "$FIND" != "y" -a "$FIND" != "n" ]; then
|
||||||
|
+ echo "--find_multipaths must be either 'y' or 'n'"
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ if [ -n "$PROPERTY" ] && [ "$PROPERTY" != "y" -a "$PROPERTY" != "n" ]; then
|
||||||
|
+ echo "--property_blacklist must be either 'y' or 'n'"
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ if [ -n "$FOREIGN" ] && [ "$FOREIGN" != "y" -a "$FOREIGN" != "n" ]; then
|
||||||
|
+ echo "--enable_foreign must be either 'y' or 'n'"
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" -a -z "$PROPERTY" ]; then
|
||||||
|
+ SHOW_STATUS=1
|
||||||
|
+ fi
|
||||||
|
+ if [ -n "$MODULE" ] && [ "$MODULE" != "y" -a "$MODULE" != "n" ]; then
|
||||||
|
+ echo "--with_module must be either 'y' or 'n'"
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ if [ -n "$MULTIPATHD" ] && [ "$MULTIPATHD" != "y" -a "$MULTIPATHD" != "n" ]; then
|
||||||
|
+ echo "--with_multipathd must be either 'y' or 'n'"
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ if [ "$ENABLE" = 2 -a -z "$HAVE_OUTFILE" ]; then
|
||||||
|
+ echo "Because --allow makes changes that cannot be automatically reversed,"
|
||||||
|
+ echo "you must set --outfile when you set --allow"
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function add_blacklist_exceptions
|
||||||
|
+{
|
||||||
|
+ INDEX=0
|
||||||
|
+ while [ "$INDEX" -lt "$WWIDS" ] ; do
|
||||||
|
+ sed -i '/^blacklist_exceptions[[:space:]]*{/ a\
|
||||||
|
+ wwid '"\"${WWID_LIST[$INDEX]}\""'
|
||||||
|
+' $TMPFILE
|
||||||
|
+ ((INDEX++))
|
||||||
|
+ done
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+umask 0077
|
||||||
|
+
|
||||||
|
+parse_args "$@"
|
||||||
|
+
|
||||||
|
+validate_args
|
||||||
|
+
|
||||||
|
+if [ ! -d "$MULTIPATHDIR" ]; then
|
||||||
|
+ echo "/etc/multipath/ does not exist. failing"
|
||||||
|
+ exit 1
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+rm $TMPFILE 2> /dev/null
|
||||||
|
+echo "$DEFAULT_CONFIG" > $TMPFILE
|
||||||
|
+if [ -f "$CONFIGFILE" ]; then
|
||||||
|
+ cp $CONFIGFILE $TMPFILE
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if grep -q "^blacklist[[:space:]]*{" $TMPFILE ; then
|
||||||
|
+ HAVE_BLACKLIST=1
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if grep -q "^blacklist_exceptions[[:space:]]*{" $TMPFILE ; then
|
||||||
|
+ HAVE_EXCEPTIONS=1
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if grep -q "^defaults[[:space:]]*{" $TMPFILE ; then
|
||||||
|
+ HAVE_DEFAULTS=1
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ -z "$MODULE" -o "$MODULE" = "y" ]; then
|
||||||
|
+ if lsmod | grep -q "dm_multipath" ; then
|
||||||
|
+ HAVE_MODULE=1
|
||||||
|
+ else
|
||||||
|
+ HAVE_MODULE=0
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$MULTIPATHD" = "y" ]; then
|
||||||
|
+ if /bin/systemctl status multipathd.service > /dev/null 2>&1 ; then
|
||||||
|
+ HAVE_MULTIPATHD=1
|
||||||
|
+ else
|
||||||
|
+ HAVE_MULTIPATHD=0
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$HAVE_BLACKLIST" = "1" ]; then
|
||||||
|
+ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*devnode \"\.\?\*\"" ; then
|
||||||
|
+ HAVE_DISABLE=1
|
||||||
|
+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"" ; then
|
||||||
|
+ HAVE_DISABLE=0
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$HAVE_BLACKLIST" = "1" ]; then
|
||||||
|
+ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*wwid \"\.\?\*\"" ; then
|
||||||
|
+ HAVE_WWID_DISABLE=1
|
||||||
|
+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"" ; then
|
||||||
|
+ HAVE_WWID_DISABLE=0
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$HAVE_DEFAULTS" = "1" ]; then
|
||||||
|
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)" ; then
|
||||||
|
+ HAVE_FIND=1
|
||||||
|
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)" ; then
|
||||||
|
+ HAVE_FIND=0
|
||||||
|
+ fi
|
||||||
|
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)" ; then
|
||||||
|
+ HAVE_FRIENDLY=1
|
||||||
|
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)" ; then
|
||||||
|
+ HAVE_FRIENDLY=0
|
||||||
|
+ fi
|
||||||
|
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*enable_foreign" ; then
|
||||||
|
+ HAVE_FOREIGN=0
|
||||||
|
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign[[:space:]]*\"\^\$\"" ; then
|
||||||
|
+ HAVE_FOREIGN=1
|
||||||
|
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign" ; then
|
||||||
|
+ HAVE_FOREIGN=2
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$HAVE_EXCEPTIONS" = "1" ]; then
|
||||||
|
+ if sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
|
||||||
|
+ HAVE_PROPERTY=1
|
||||||
|
+ elif sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
|
||||||
|
+ HAVE_PROPERTY=0
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ -n "$SHOW_STATUS" ]; then
|
||||||
|
+ if [ -z "$HAVE_DISABLE" -o "$HAVE_DISABLE" = 0 ]; then
|
||||||
|
+ echo "multipath is enabled"
|
||||||
|
+ else
|
||||||
|
+ echo "multipath is disabled"
|
||||||
|
+ fi
|
||||||
|
+ if [ -z "$HAVE_FIND" -o "$HAVE_FIND" = 0 ]; then
|
||||||
|
+ echo "find_multipaths is disabled"
|
||||||
|
+ else
|
||||||
|
+ echo "find_multipaths is enabled"
|
||||||
|
+ fi
|
||||||
|
+ if [ -z "$HAVE_FRIENDLY" -o "$HAVE_FRIENDLY" = 0 ]; then
|
||||||
|
+ echo "user_friendly_names is disabled"
|
||||||
|
+ else
|
||||||
|
+ echo "user_friendly_names is enabled"
|
||||||
|
+ fi
|
||||||
|
+ if [ -z "$HAVE_PROPERTY" -o "$HAVE_PROPERTY" = 0 ]; then
|
||||||
|
+ echo "default property blacklist is disabled"
|
||||||
|
+ else
|
||||||
|
+ echo "default property blacklist is enabled"
|
||||||
|
+ fi
|
||||||
|
+ if [ -z "$HAVE_FOREIGN" -o "$HAVE_FOREIGN" = 0 ]; then
|
||||||
|
+ echo "enable_foreign is not set (all foreign multipath devices will be shown)"
|
||||||
|
+ elif [ "$HAVE_FOREIGN" = 1 ]; then
|
||||||
|
+ echo "enable_foreign is set (no foreign multipath devices will be shown)"
|
||||||
|
+ else
|
||||||
|
+ echo "enable_foreign is set (foreign multipath devices may not be shown)"
|
||||||
|
+ fi
|
||||||
|
+ if [ -n "$HAVE_MODULE" ]; then
|
||||||
|
+ if [ "$HAVE_MODULE" = 1 ]; then
|
||||||
|
+ echo "dm_multipath module is loaded"
|
||||||
|
+ else
|
||||||
|
+ echo "dm_multipath module is not loaded"
|
||||||
|
+ fi
|
||||||
|
+ fi
|
||||||
|
+ if [ -z "$HAVE_MULTIPATHD" ]; then
|
||||||
|
+ if /bin/systemctl status multipathd.service > /dev/null 2>&1 ; then
|
||||||
|
+ HAVE_MULTIPATHD=1
|
||||||
|
+ else
|
||||||
|
+ HAVE_MULTIPATHD=0
|
||||||
|
+ fi
|
||||||
|
+ fi
|
||||||
|
+ if [ "$HAVE_MULTIPATHD" = 1 ]; then
|
||||||
|
+ echo "multipathd is running"
|
||||||
|
+ else
|
||||||
|
+ echo "multipathd is not running"
|
||||||
|
+ fi
|
||||||
|
+ exit 0
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ -z "$HAVE_BLACKLIST" ]; then
|
||||||
|
+ cat >> $TMPFILE <<- _EOF_
|
||||||
|
+
|
||||||
|
+blacklist {
|
||||||
|
+}
|
||||||
|
+_EOF_
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ -z "$HAVE_DEFAULTS" ]; then
|
||||||
|
+ cat >> $TMPFILE <<- _EOF_
|
||||||
|
+
|
||||||
|
+defaults {
|
||||||
|
+}
|
||||||
|
+_EOF_
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$ENABLE" = 2 ]; then
|
||||||
|
+ if [ "$HAVE_DISABLE" = 1 ]; then
|
||||||
|
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE
|
||||||
|
+ fi
|
||||||
|
+ if [ -z "$HAVE_WWID_DISABLE" ]; then
|
||||||
|
+ sed -i '/^blacklist[[:space:]]*{/ a\
|
||||||
|
+ wwid ".*"
|
||||||
|
+' $TMPFILE
|
||||||
|
+ elif [ "$HAVE_WWID_DISABLE" = 0 ]; then
|
||||||
|
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"/ wwid ".*"/' $TMPFILE
|
||||||
|
+ fi
|
||||||
|
+ if [ "$HAVE_EXCEPTIONS" = 1 ]; then
|
||||||
|
+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ {/^[[:space:]]*wwid/ d}' $TMPFILE
|
||||||
|
+ else
|
||||||
|
+ cat >> $TMPFILE <<- _EOF_
|
||||||
|
+
|
||||||
|
+blacklist_exceptions {
|
||||||
|
+}
|
||||||
|
+_EOF_
|
||||||
|
+ fi
|
||||||
|
+ add_blacklist_exceptions
|
||||||
|
+elif [ "$ENABLE" = 1 ]; then
|
||||||
|
+ if [ "$HAVE_DISABLE" = 1 ]; then
|
||||||
|
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE
|
||||||
|
+ fi
|
||||||
|
+elif [ "$ENABLE" = 0 ]; then
|
||||||
|
+ if [ -z "$HAVE_DISABLE" ]; then
|
||||||
|
+ sed -i '/^blacklist[[:space:]]*{/ a\
|
||||||
|
+ devnode ".*"
|
||||||
|
+' $TMPFILE
|
||||||
|
+ elif [ "$HAVE_DISABLE" = 0 ]; then
|
||||||
|
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"/ devnode ".*"/' $TMPFILE
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$FIND" = "n" ]; then
|
||||||
|
+ if [ "$HAVE_FIND" = 1 ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)/ find_multipaths no/' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ fi
|
||||||
|
+elif [ "$FIND" = "y" ]; then
|
||||||
|
+ if [ -z "$HAVE_FIND" ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/ a\
|
||||||
|
+ find_multipaths yes
|
||||||
|
+' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ elif [ "$HAVE_FIND" = 0 ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)/ find_multipaths yes/' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$FRIENDLY" = "n" ]; then
|
||||||
|
+ if [ "$HAVE_FRIENDLY" = 1 ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)/ user_friendly_names no/' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ fi
|
||||||
|
+elif [ "$FRIENDLY" = "y" ]; then
|
||||||
|
+ if [ -z "$HAVE_FRIENDLY" ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/ a\
|
||||||
|
+ user_friendly_names yes
|
||||||
|
+' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ elif [ "$HAVE_FRIENDLY" = 0 ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)/ user_friendly_names yes/' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$PROPERTY" = "n" ]; then
|
||||||
|
+ if [ "$HAVE_PROPERTY" = 1 ]; then
|
||||||
|
+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/# property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ fi
|
||||||
|
+elif [ "$PROPERTY" = "y" ]; then
|
||||||
|
+ if [ -z "$HAVE_PROPERTY" ]; then
|
||||||
|
+ sed -i '/^blacklist_exceptions[[:space:]]*{/ a\
|
||||||
|
+ property "(SCSI_IDENT_|ID_WWN)"
|
||||||
|
+' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ elif [ "$HAVE_PROPERTY" = 0 ]; then
|
||||||
|
+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/ property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$FOREIGN" = "y" ]; then
|
||||||
|
+ if [ "$HAVE_FOREIGN" = 1 -o "$HAVE_FOREIGN" = 2 ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*enable_foreign/# enable_foreign/' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ fi
|
||||||
|
+elif [ "$FOREIGN" = "n" ]; then
|
||||||
|
+ if [ -z "$HAVE_FOREIGN" ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/ a\
|
||||||
|
+ enable_foreign "^$"
|
||||||
|
+' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ elif [ "$HAVE_FOREIGN" = 0 -o "$HAVE_FOREIGN" = 2 ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*#\?[[:space:]]*enable_foreign.*$/ enable_foreign "^$"/' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ -f "$OUTPUTFILE" ]; then
|
||||||
|
+ cp $OUTPUTFILE $OUTPUTFILE.old
|
||||||
|
+ if [ $? != 0 ]; then
|
||||||
|
+ echo "failed to backup old config file, $OUTPUTFILE not updated"
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+cp $TMPFILE $OUTPUTFILE
|
||||||
|
+if [ $? != 0 ]; then
|
||||||
|
+ echo "failed to copy new config file into place, check $OUTPUTFILE is still OK"
|
||||||
|
+ exit 1
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+rm -f $TMPFILE
|
||||||
|
+
|
||||||
|
+if [ "$ENABLE" = 1 ]; then
|
||||||
|
+ if [ "$HAVE_MODULE" = 0 ]; then
|
||||||
|
+ modprobe dm_multipath
|
||||||
|
+ fi
|
||||||
|
+ if [ "$HAVE_MULTIPATHD" = 0 ]; then
|
||||||
|
+ systemctl start multipathd.service
|
||||||
|
+ fi
|
||||||
|
+elif [ "$ENABLE" = 0 ]; then
|
||||||
|
+ if [ "$HAVE_MULTIPATHD" = 1 ]; then
|
||||||
|
+ systemctl stop multipathd.service
|
||||||
|
+ fi
|
||||||
|
+elif [ -n "$CHANGED_CONFIG" -a "$HAVE_MULTIPATHD" = 1 ]; then
|
||||||
|
+ systemctl reload multipathd.service
|
||||||
|
+fi
|
||||||
|
diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..b82961d6
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/multipath/mpathconf.8
|
||||||
|
@@ -0,0 +1,135 @@
|
||||||
|
+.TH MPATHCONF 8 "June 2010" "" "Linux Administrator's Manual"
|
||||||
|
+.SH NAME
|
||||||
|
+mpathconf - A tool for configuring device-mapper-multipath
|
||||||
|
+.SH SYNOPSIS
|
||||||
|
+.B mpathconf
|
||||||
|
+.RB [\| commands \|]
|
||||||
|
+.RB [\| options \|]
|
||||||
|
+.SH DESCRIPTION
|
||||||
|
+.B mpathconf
|
||||||
|
+is a utility that creates or modifies
|
||||||
|
+.B /etc/multipath.conf.
|
||||||
|
+It can enable or disable multipathing and configure some common options.
|
||||||
|
+.B mpathconf
|
||||||
|
+can also load the
|
||||||
|
+.B dm_multipath
|
||||||
|
+module, start and stop the
|
||||||
|
+.B multipathd
|
||||||
|
+daemon, and configure the
|
||||||
|
+.B multipathd
|
||||||
|
+service to start automatically or not. If
|
||||||
|
+.B mpathconf
|
||||||
|
+is called with no commands, it will display the current configuration, but
|
||||||
|
+will not create of modify
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+
|
||||||
|
+The default options for mpathconf are
|
||||||
|
+.B --with_module
|
||||||
|
+The
|
||||||
|
+.B --with_multipathd
|
||||||
|
+option is not set by default. Enabling multipathing will load the
|
||||||
|
+.B dm_multipath
|
||||||
|
+module but it will not immediately start it. This is so
|
||||||
|
+that users can manually edit their config file if necessary, before starting
|
||||||
|
+.B multipathd.
|
||||||
|
+
|
||||||
|
+If
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+already exists, mpathconf will edit it. If it does not exist, mpathconf will
|
||||||
|
+create a default file with
|
||||||
|
+.B user_friendly_names
|
||||||
|
+and
|
||||||
|
+.B find_multipaths
|
||||||
|
+set. To disable these, use the
|
||||||
|
+.B --user_friendly_names n
|
||||||
|
+and
|
||||||
|
+.B --find_multipaths n
|
||||||
|
+options
|
||||||
|
+.SH COMMANDS
|
||||||
|
+.TP
|
||||||
|
+.B --enable
|
||||||
|
+Removes any line that blacklists all device nodes from the
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+blacklist section. Also, creates
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+if it doesn't exist.
|
||||||
|
+.TP
|
||||||
|
+.B --disable
|
||||||
|
+Adds a line that blacklists all device nodes to the
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+blacklist section. If no blacklist section exists, it will create one.
|
||||||
|
+.TP
|
||||||
|
+.B --allow \fB<device>\fP
|
||||||
|
+Modifies the \fB/etc/multipath/conf\fP blacklist to blacklist all
|
||||||
|
+wwids and the blacklist_exceptions to whitelist \fB<device>\fP. \fB<device>\fP
|
||||||
|
+can be in the form of MAJOR:MINOR, a wwid, or the name of a device-mapper
|
||||||
|
+device, either a multipath device, or any device on stacked on top of one or
|
||||||
|
+more multipath devices. This command can be used multiple times to allow
|
||||||
|
+multiple devices. \fBNOTE:\fP This action will create a configuration file that
|
||||||
|
+mpathconf will not be able to revert back to its previous state. Because
|
||||||
|
+of this, \fB--outfile\fP is required when using \fB--allow\fP.
|
||||||
|
+.TP
|
||||||
|
+.B --user_friendly_names \fP { \fBy\fP | \fBn\fP }
|
||||||
|
+If set to \fBy\fP, this adds the line
|
||||||
|
+.B user_friendly_names yes
|
||||||
|
+to the
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+defaults section. If set to \fBn\fP, this removes the line, if present. This
|
||||||
|
+command can be used along with any other command.
|
||||||
|
+.TP
|
||||||
|
+.B --find_multipaths\fP { \fBy\fP | \fBn\fP }
|
||||||
|
+If set to \fBy\fP, this adds the line
|
||||||
|
+.B find_multipaths yes
|
||||||
|
+to the
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+defaults section. If set to \fBn\fP, this removes the line, if present. This
|
||||||
|
+command can be used along with any other command.
|
||||||
|
+.TP
|
||||||
|
+.B --property_blacklist \fP { \fBy\fP | \fBn\fP }
|
||||||
|
+If set to \fBy\fP, this adds the line
|
||||||
|
+.B property "(SCSI_IDENT_|ID_WWN)"
|
||||||
|
+to the
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+blacklist_exceptions section. If set to \fBn\fP, this removes the line, if
|
||||||
|
+present. This command can be used along with any other command.
|
||||||
|
+.TP
|
||||||
|
+.B --enable_foreign\fP { \fBy\fP | \fBn\fP }
|
||||||
|
+If set to \fBn\fP, this adds the line
|
||||||
|
+.B enable_foreign "^$"
|
||||||
|
+to the
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+defaults section. if set to \fBy\fP, this removes the line, if present. This
|
||||||
|
+command can be used along with any other command.
|
||||||
|
+.TP
|
||||||
|
+.B --outfile \fB<filename>\fP
|
||||||
|
+Write the resulting multipath configuration to \fB<filename>\fP instead of
|
||||||
|
+\fB/etc/multipath.conf\fP.
|
||||||
|
+.SH OPTIONS
|
||||||
|
+.TP
|
||||||
|
+.B --with_module\fP { \fBy\fP | \fBn\fP }
|
||||||
|
+If set to \fBy\fP, this runs
|
||||||
|
+.B modprobe dm_multipath
|
||||||
|
+to install the multipath modules. This option only works with the
|
||||||
|
+.B --enable
|
||||||
|
+command. This option is set to \fBy\fP by default.
|
||||||
|
+.TP
|
||||||
|
+.B --with_multipathd { \fBy\fP | \fBn\fP }
|
||||||
|
+If set to \fBy\fP, this runs
|
||||||
|
+.B service multipathd start
|
||||||
|
+to start the multipathd daemon on \fB--enable\fP,
|
||||||
|
+.B service multipathd stop
|
||||||
|
+to stop the multipathd daemon on \fB--disable\fP, and
|
||||||
|
+.B service multipathd reload
|
||||||
|
+to reconfigure multipathd on \fB--user_frindly_names\fP and
|
||||||
|
+\fB--find_multipaths\fP.
|
||||||
|
+This option is set to \fBn\fP by default.
|
||||||
|
+.SH FILES
|
||||||
|
+.BR /etc/multipath.conf
|
||||||
|
+.SH "SEE ALSO"
|
||||||
|
+.BR multipath.conf (5),
|
||||||
|
+.BR modprobe (8),
|
||||||
|
+.BR multipath (8),
|
||||||
|
+.BR multipathd (8),
|
||||||
|
+.BR service (8),
|
||||||
|
+.SH AUTHOR
|
||||||
|
+Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,169 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Fri, 17 Oct 2014 11:20:34 -0500
|
||||||
|
Subject: [PATCH] RH: add wwids from kernel cmdline mpath.wwids with -A
|
||||||
|
|
||||||
|
This patch adds another option to multipath, "-A", which reads
|
||||||
|
/proc/cmdline for mpath.wwid=<WWID> options, and adds any wwids it finds
|
||||||
|
to /etc/multipath/wwids. While this isn't usually important during
|
||||||
|
normal operation, since these wwids should already be added, it can be
|
||||||
|
helpful during installation, to make sure that multipath can claim
|
||||||
|
devices as its own, before LVM or something else makes use of them. The
|
||||||
|
patch also execs "/sbin/multipath -A" before running multipathd in
|
||||||
|
multipathd.service
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/wwids.c | 44 +++++++++++++++++++++++++++++++++++
|
||||||
|
libmultipath/wwids.h | 1 +
|
||||||
|
multipath/main.c | 10 ++++++--
|
||||||
|
multipath/multipath.8 | 7 +++++-
|
||||||
|
multipathd/multipathd.service | 1 +
|
||||||
|
5 files changed, 60 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
|
||||||
|
index 28a2150d..fab6fc8f 100644
|
||||||
|
--- a/libmultipath/wwids.c
|
||||||
|
+++ b/libmultipath/wwids.c
|
||||||
|
@@ -454,3 +454,47 @@ int op ## _wwid(const char *wwid) \
|
||||||
|
declare_failed_wwid_op(is_failed, false)
|
||||||
|
declare_failed_wwid_op(mark_failed, true)
|
||||||
|
declare_failed_wwid_op(unmark_failed, true)
|
||||||
|
+
|
||||||
|
+int remember_cmdline_wwid(void)
|
||||||
|
+{
|
||||||
|
+ FILE *f = NULL;
|
||||||
|
+ char buf[LINE_MAX], *next, *ptr;
|
||||||
|
+ int ret = 0;
|
||||||
|
+
|
||||||
|
+ f = fopen("/proc/cmdline", "re");
|
||||||
|
+ if (!f) {
|
||||||
|
+ condlog(0, "can't open /proc/cmdline : %s", strerror(errno));
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!fgets(buf, sizeof(buf), f)) {
|
||||||
|
+ if (ferror(f))
|
||||||
|
+ condlog(0, "read of /proc/cmdline failed : %s",
|
||||||
|
+ strerror(errno));
|
||||||
|
+ else
|
||||||
|
+ condlog(0, "couldn't read /proc/cmdline");
|
||||||
|
+ fclose(f);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ fclose(f);
|
||||||
|
+ next = buf;
|
||||||
|
+ while((ptr = strstr(next, "mpath.wwid="))) {
|
||||||
|
+ ptr += 11;
|
||||||
|
+ next = strpbrk(ptr, " \t\n");
|
||||||
|
+ if (next) {
|
||||||
|
+ *next = '\0';
|
||||||
|
+ next++;
|
||||||
|
+ }
|
||||||
|
+ if (strlen(ptr)) {
|
||||||
|
+ if (remember_wwid(ptr) != 0)
|
||||||
|
+ ret = -1;
|
||||||
|
+ }
|
||||||
|
+ else {
|
||||||
|
+ condlog(0, "empty mpath.wwid kernel command line option");
|
||||||
|
+ ret = -1;
|
||||||
|
+ }
|
||||||
|
+ if (!next)
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
diff --git a/libmultipath/wwids.h b/libmultipath/wwids.h
|
||||||
|
index 0c6ee54d..e32a0b0e 100644
|
||||||
|
--- a/libmultipath/wwids.h
|
||||||
|
+++ b/libmultipath/wwids.h
|
||||||
|
@@ -17,6 +17,7 @@ int remember_wwid(char *wwid);
|
||||||
|
int check_wwids_file(char *wwid, int write_wwid);
|
||||||
|
int remove_wwid(char *wwid);
|
||||||
|
int replace_wwids(vector mp);
|
||||||
|
+int remember_cmdline_wwid(void);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
WWID_IS_NOT_FAILED = 0,
|
||||||
|
diff --git a/multipath/main.c b/multipath/main.c
|
||||||
|
index cf9d2a28..78822ee1 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -138,7 +138,7 @@ usage (char * progname)
|
||||||
|
fprintf (stderr, " %s [-v level] [-R retries] -F\n", progname);
|
||||||
|
fprintf (stderr, " %s [-v level] [-l|-ll] [device]\n", progname);
|
||||||
|
fprintf (stderr, " %s [-v level] [-a|-w] device\n", progname);
|
||||||
|
- fprintf (stderr, " %s [-v level] -W\n", progname);
|
||||||
|
+ fprintf (stderr, " %s [-v level] [-A|-W]\n", progname);
|
||||||
|
fprintf (stderr, " %s [-v level] [-i] [-c|-C] device\n", progname);
|
||||||
|
fprintf (stderr, " %s [-v level] [-i] [-u|-U]\n", progname);
|
||||||
|
fprintf (stderr, " %s [-h|-t|-T]\n", progname);
|
||||||
|
@@ -151,6 +151,8 @@ usage (char * progname)
|
||||||
|
" -f flush a multipath device map\n"
|
||||||
|
" -F flush all multipath device maps\n"
|
||||||
|
" -a add a device wwid to the wwids file\n"
|
||||||
|
+ " -A add devices from kernel command line mpath.wwids\n"
|
||||||
|
+ " parameters to wwids file\n"
|
||||||
|
" -c check if a device should be a path in a multipath device\n"
|
||||||
|
" -C check if a multipath device has usable paths\n"
|
||||||
|
" -q allow queue_if_no_path when multipathd is not running\n"
|
||||||
|
@@ -907,7 +909,7 @@ main (int argc, char *argv[])
|
||||||
|
multipath_conf = conf;
|
||||||
|
conf->retrigger_tries = 0;
|
||||||
|
conf->force_sync = 1;
|
||||||
|
- while ((arg = getopt(argc, argv, ":adcChl::FfM:v:p:b:BrR:itTquUwW")) != EOF ) {
|
||||||
|
+ while ((arg = getopt(argc, argv, ":aAdcChl::FfM:v:p:b:BrR:itTquUwW")) != EOF ) {
|
||||||
|
switch(arg) {
|
||||||
|
case 1: printf("optarg : %s\n",optarg);
|
||||||
|
break;
|
||||||
|
@@ -977,6 +979,10 @@ main (int argc, char *argv[])
|
||||||
|
case 'T':
|
||||||
|
cmd = CMD_DUMP_CONFIG;
|
||||||
|
break;
|
||||||
|
+ case 'A':
|
||||||
|
+ if (remember_cmdline_wwid() != 0)
|
||||||
|
+ exit(RTVL_FAIL);
|
||||||
|
+ exit(RTVL_OK);
|
||||||
|
case 'h':
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(RTVL_OK);
|
||||||
|
diff --git a/multipath/multipath.8 b/multipath/multipath.8
|
||||||
|
index 9cdd05a3..8befc45a 100644
|
||||||
|
--- a/multipath/multipath.8
|
||||||
|
+++ b/multipath/multipath.8
|
||||||
|
@@ -63,7 +63,7 @@ multipath \- Device mapper target autoconfig.
|
||||||
|
.B multipath
|
||||||
|
.RB [\| \-v\ \c
|
||||||
|
.IR level \|]
|
||||||
|
-.B -W
|
||||||
|
+.RB [\| \-A | \-W \|]
|
||||||
|
.
|
||||||
|
.LP
|
||||||
|
.B multipath
|
||||||
|
@@ -145,6 +145,11 @@ device mapper, path checkers ...).
|
||||||
|
Add the WWID for the specified device to the WWIDs file.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
+.B \-A
|
||||||
|
+Add the WWIDs from any kernel command line \fImpath.wwid\fR parameters to the
|
||||||
|
+WWIDs file.
|
||||||
|
+.
|
||||||
|
+.TP
|
||||||
|
.B \-w
|
||||||
|
Remove the WWID for the specified device from the WWIDs file.
|
||||||
|
.
|
||||||
|
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
|
||||||
|
index 17434cef..0fbcc46b 100644
|
||||||
|
--- a/multipathd/multipathd.service
|
||||||
|
+++ b/multipathd/multipathd.service
|
||||||
|
@@ -15,6 +15,7 @@ Type=notify
|
||||||
|
NotifyAccess=main
|
||||||
|
LimitCORE=infinity
|
||||||
|
ExecStartPre=-/sbin/modprobe -a scsi_dh_alua scsi_dh_emc scsi_dh_rdac dm-multipath
|
||||||
|
+ExecStartPre=-/sbin/multipath -A
|
||||||
|
ExecStart=/sbin/multipathd -d -s
|
||||||
|
ExecReload=/sbin/multipathd reconfigure
|
||||||
|
TasksMax=infinity
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,121 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 6 Nov 2017 21:39:28 -0600
|
||||||
|
Subject: [PATCH] RH: warn on invalid regex instead of failing
|
||||||
|
|
||||||
|
multipath.conf used to allow "*" as a match everything regular expression,
|
||||||
|
instead of requiring ".*". Instead of erroring when the old style
|
||||||
|
regular expressions are used, it should print a warning and convert
|
||||||
|
them.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/dict.c | 27 +++++++++++++++++++++------
|
||||||
|
libmultipath/parser.c | 13 +++++++++++++
|
||||||
|
libmultipath/parser.h | 1 +
|
||||||
|
3 files changed, 35 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||||
|
index 0e9ea387..184d4b22 100644
|
||||||
|
--- a/libmultipath/dict.c
|
||||||
|
+++ b/libmultipath/dict.c
|
||||||
|
@@ -103,6 +103,21 @@ set_str(vector strvec, void *ptr)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+set_regex(vector strvec, void *ptr)
|
||||||
|
+{
|
||||||
|
+ char **str_ptr = (char **)ptr;
|
||||||
|
+
|
||||||
|
+ if (*str_ptr)
|
||||||
|
+ FREE(*str_ptr);
|
||||||
|
+ *str_ptr = set_regex_value(strvec);
|
||||||
|
+
|
||||||
|
+ if (!*str_ptr)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
set_yes_no(vector strvec, void *ptr)
|
||||||
|
{
|
||||||
|
@@ -1504,7 +1519,7 @@ ble_ ## option ## _handler (struct config *conf, vector strvec) \
|
||||||
|
if (!conf->option) \
|
||||||
|
return 1; \
|
||||||
|
\
|
||||||
|
- buff = set_value(strvec); \
|
||||||
|
+ buff = set_regex_value(strvec); \
|
||||||
|
if (!buff) \
|
||||||
|
return 1; \
|
||||||
|
\
|
||||||
|
@@ -1520,7 +1535,7 @@ ble_ ## option ## _ ## name ## _handler (struct config *conf, vector strvec) \
|
||||||
|
if (!conf->option) \
|
||||||
|
return 1; \
|
||||||
|
\
|
||||||
|
- buff = set_value(strvec); \
|
||||||
|
+ buff = set_regex_value(strvec); \
|
||||||
|
if (!buff) \
|
||||||
|
return 1; \
|
||||||
|
\
|
||||||
|
@@ -1623,16 +1638,16 @@ device_handler(struct config *conf, vector strvec)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-declare_hw_handler(vendor, set_str)
|
||||||
|
+declare_hw_handler(vendor, set_regex)
|
||||||
|
declare_hw_snprint(vendor, print_str)
|
||||||
|
|
||||||
|
-declare_hw_handler(product, set_str)
|
||||||
|
+declare_hw_handler(product, set_regex)
|
||||||
|
declare_hw_snprint(product, print_str)
|
||||||
|
|
||||||
|
-declare_hw_handler(revision, set_str)
|
||||||
|
+declare_hw_handler(revision, set_regex)
|
||||||
|
declare_hw_snprint(revision, print_str)
|
||||||
|
|
||||||
|
-declare_hw_handler(bl_product, set_str)
|
||||||
|
+declare_hw_handler(bl_product, set_regex)
|
||||||
|
declare_hw_snprint(bl_product, print_str)
|
||||||
|
|
||||||
|
declare_hw_handler(hwhandler, set_str)
|
||||||
|
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
|
||||||
|
index d478b177..a184511b 100644
|
||||||
|
--- a/libmultipath/parser.c
|
||||||
|
+++ b/libmultipath/parser.c
|
||||||
|
@@ -382,6 +382,19 @@ oom:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void *
|
||||||
|
+set_regex_value(vector strvec)
|
||||||
|
+{
|
||||||
|
+ char *buff = set_value(strvec);
|
||||||
|
+
|
||||||
|
+ if (buff && strcmp("*", buff) == 0) {
|
||||||
|
+ condlog(0, "Invalid regular expression \"*\" in multipath.conf. Using \".*\"");
|
||||||
|
+ FREE(buff);
|
||||||
|
+ return strdup(".*");
|
||||||
|
+ }
|
||||||
|
+ return buff;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* non-recursive configuration stream handler */
|
||||||
|
static int kw_level = 0;
|
||||||
|
|
||||||
|
diff --git a/libmultipath/parser.h b/libmultipath/parser.h
|
||||||
|
index 62906e98..b7917052 100644
|
||||||
|
--- a/libmultipath/parser.h
|
||||||
|
+++ b/libmultipath/parser.h
|
||||||
|
@@ -77,6 +77,7 @@ extern void dump_keywords(vector keydump, int level);
|
||||||
|
extern void free_keywords(vector keywords);
|
||||||
|
extern vector alloc_strvec(char *string);
|
||||||
|
extern void *set_value(vector strvec);
|
||||||
|
+extern void *set_regex_value(vector strvec);
|
||||||
|
extern int process_file(struct config *conf, char *conf_file);
|
||||||
|
extern struct keyword * find_keyword(vector keywords, vector v, char * name);
|
||||||
|
int snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw,
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,29 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 7 Jun 2018 17:43:52 -0500
|
||||||
|
Subject: [PATCH] RH: reset default find_mutipaths value to off
|
||||||
|
|
||||||
|
Upstream has changed to default find_multipaths to "strict". For now
|
||||||
|
Redhat will retain the previous default of "off".
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/defaults.h | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
|
||||||
|
index e5ee6afe..52fe05b9 100644
|
||||||
|
--- a/libmultipath/defaults.h
|
||||||
|
+++ b/libmultipath/defaults.h
|
||||||
|
@@ -22,7 +22,7 @@
|
||||||
|
#define DEFAULT_NO_PATH_RETRY NO_PATH_RETRY_UNDEF
|
||||||
|
#define DEFAULT_VERBOSITY 2
|
||||||
|
#define DEFAULT_REASSIGN_MAPS 0
|
||||||
|
-#define DEFAULT_FIND_MULTIPATHS FIND_MULTIPATHS_STRICT
|
||||||
|
+#define DEFAULT_FIND_MULTIPATHS FIND_MULTIPATHS_OFF
|
||||||
|
#define DEFAULT_FAST_IO_FAIL 5
|
||||||
|
#define DEFAULT_DEV_LOSS_TMO 600
|
||||||
|
#define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_ON
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,26 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Fri, 25 Jan 2019 14:54:56 -0600
|
||||||
|
Subject: [PATCH] RH: Fix nvme compilation warning
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/nvme/argconfig.h | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/nvme/argconfig.h b/libmultipath/nvme/argconfig.h
|
||||||
|
index adb192b6..bfd10ef8 100644
|
||||||
|
--- a/libmultipath/nvme/argconfig.h
|
||||||
|
+++ b/libmultipath/nvme/argconfig.h
|
||||||
|
@@ -76,7 +76,7 @@ struct argconfig_commandline_options {
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-typedef void argconfig_help_func();
|
||||||
|
+typedef void argconfig_help_func(void);
|
||||||
|
void argconfig_append_usage(const char *str);
|
||||||
|
void argconfig_print_help(const char *program_desc,
|
||||||
|
const struct argconfig_commandline_options *options);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,87 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 11 Apr 2019 13:25:42 -0500
|
||||||
|
Subject: [PATCH] RH: attempt to get ANA info via sysfs first
|
||||||
|
|
||||||
|
When the ANA prioritizer is run, first see if the "ana_state" sysfs file
|
||||||
|
exists, and if it does, try to read the state from there. If that fails,
|
||||||
|
fallback to using an ioctl.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/prioritizers/ana.c | 31 +++++++++++++++++++++++++++++--
|
||||||
|
1 file changed, 29 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/prioritizers/ana.c b/libmultipath/prioritizers/ana.c
|
||||||
|
index b5c7873d..e139360c 100644
|
||||||
|
--- a/libmultipath/prioritizers/ana.c
|
||||||
|
+++ b/libmultipath/prioritizers/ana.c
|
||||||
|
@@ -24,6 +24,7 @@
|
||||||
|
#include "prio.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "structs.h"
|
||||||
|
+#include "sysfs.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ANA_ERR_GETCTRL_FAILED = 1,
|
||||||
|
@@ -36,6 +37,7 @@ enum {
|
||||||
|
ANA_ERR_GETNS_FAILED,
|
||||||
|
ANA_ERR_NO_MEMORY,
|
||||||
|
ANA_ERR_NO_INFORMATION,
|
||||||
|
+ ANA_ERR_INVALID_STATE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *ana_errmsg[] = {
|
||||||
|
@@ -49,6 +51,7 @@ static const char *ana_errmsg[] = {
|
||||||
|
[ANA_ERR_GETNS_FAILED] = "couldn't get namespace info",
|
||||||
|
[ANA_ERR_NO_MEMORY] = "out of memory",
|
||||||
|
[ANA_ERR_NO_INFORMATION] = "invalid fd",
|
||||||
|
+ [ANA_ERR_INVALID_STATE] = "invalid state",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *anas_string[] = {
|
||||||
|
@@ -107,6 +110,27 @@ static int get_ana_state(__u32 nsid, __u32 anagrpid, void *ana_log,
|
||||||
|
return -ANA_ERR_GETANAS_NOTFOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int get_ana_info_sysfs(struct path *pp)
|
||||||
|
+{
|
||||||
|
+ char state[32];
|
||||||
|
+
|
||||||
|
+ if (!pp->udev || sysfs_attr_get_value(pp->udev, "ana_state", state,
|
||||||
|
+ sizeof(state)) <= 0)
|
||||||
|
+ return -ANA_ERR_NO_INFORMATION;
|
||||||
|
+
|
||||||
|
+ if (strcmp(state, "optimized") == 0)
|
||||||
|
+ return NVME_ANA_OPTIMIZED;
|
||||||
|
+ if (strcmp(state, "non-optimized") == 0)
|
||||||
|
+ return NVME_ANA_NONOPTIMIZED;
|
||||||
|
+ if (strcmp(state, "inaccessible") == 0)
|
||||||
|
+ return NVME_ANA_INACCESSIBLE;
|
||||||
|
+ if (strcmp(state, "persistent-loss") == 0)
|
||||||
|
+ return NVME_ANA_PERSISTENT_LOSS;
|
||||||
|
+ if (strcmp(state, "change") == 0)
|
||||||
|
+ return NVME_ANA_CHANGE;
|
||||||
|
+ return -ANA_ERR_INVALID_STATE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int get_ana_info(struct path * pp)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
@@ -210,8 +234,11 @@ int getprio(struct path *pp, __attribute__((unused)) char *args,
|
||||||
|
|
||||||
|
if (pp->fd < 0)
|
||||||
|
rc = -ANA_ERR_NO_INFORMATION;
|
||||||
|
- else
|
||||||
|
- rc = get_ana_info(pp);
|
||||||
|
+ else {
|
||||||
|
+ rc = get_ana_info_sysfs(pp);
|
||||||
|
+ if (rc < 0)
|
||||||
|
+ rc = get_ana_info(pp);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
switch (rc) {
|
||||||
|
case NVME_ANA_OPTIMIZED:
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,139 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 8 Jun 2020 14:27:51 -0500
|
||||||
|
Subject: [PATCH] libmultipath: remove _blacklist_exceptions functions
|
||||||
|
|
||||||
|
_blacklist_exceptions() and _blacklist_exceptions_device() are exactly
|
||||||
|
the same as _blacklist() and _blacklist_device(), so remove them, and
|
||||||
|
give the remaining functions to a more general name.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/blacklist.c | 62 ++++++++++------------------------------
|
||||||
|
1 file changed, 15 insertions(+), 47 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
|
||||||
|
index d9691b17..04d3adb9 100644
|
||||||
|
--- a/libmultipath/blacklist.c
|
||||||
|
+++ b/libmultipath/blacklist.c
|
||||||
|
@@ -101,21 +101,8 @@ int set_ble_device(vector blist, char * vendor, char * product, int origin)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int
|
||||||
|
-_blacklist_exceptions (vector elist, const char * str)
|
||||||
|
-{
|
||||||
|
- int i;
|
||||||
|
- struct blentry * ele;
|
||||||
|
-
|
||||||
|
- vector_foreach_slot (elist, ele, i) {
|
||||||
|
- if (!regexec(&ele->regex, str, 0, NULL, 0))
|
||||||
|
- return 1;
|
||||||
|
- }
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-int
|
||||||
|
-_blacklist (vector blist, const char * str)
|
||||||
|
+static int
|
||||||
|
+match_reglist (vector blist, const char * str)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct blentry * ble;
|
||||||
|
@@ -127,28 +114,9 @@ _blacklist (vector blist, const char * str)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int
|
||||||
|
-_blacklist_exceptions_device(const struct _vector *elist, const char * vendor,
|
||||||
|
- const char * product)
|
||||||
|
-{
|
||||||
|
- int i;
|
||||||
|
- struct blentry_device * ble;
|
||||||
|
-
|
||||||
|
- vector_foreach_slot (elist, ble, i) {
|
||||||
|
- if (!ble->vendor && !ble->product)
|
||||||
|
- continue;
|
||||||
|
- if ((!ble->vendor ||
|
||||||
|
- !regexec(&ble->vendor_reg, vendor, 0, NULL, 0)) &&
|
||||||
|
- (!ble->product ||
|
||||||
|
- !regexec(&ble->product_reg, product, 0, NULL, 0)))
|
||||||
|
- return 1;
|
||||||
|
- }
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-int
|
||||||
|
-_blacklist_device (const struct _vector *blist, const char * vendor,
|
||||||
|
- const char * product)
|
||||||
|
+static int
|
||||||
|
+match_reglist_device (const struct _vector *blist, const char * vendor,
|
||||||
|
+ const char * product)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct blentry_device * ble;
|
||||||
|
@@ -294,9 +262,9 @@ filter_device (vector blist, vector elist, char * vendor, char * product,
|
||||||
|
int r = MATCH_NOTHING;
|
||||||
|
|
||||||
|
if (vendor && product) {
|
||||||
|
- if (_blacklist_exceptions_device(elist, vendor, product))
|
||||||
|
+ if (match_reglist_device(elist, vendor, product))
|
||||||
|
r = MATCH_DEVICE_BLIST_EXCEPT;
|
||||||
|
- else if (_blacklist_device(blist, vendor, product))
|
||||||
|
+ else if (match_reglist_device(blist, vendor, product))
|
||||||
|
r = MATCH_DEVICE_BLIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -310,9 +278,9 @@ filter_devnode (vector blist, vector elist, char * dev)
|
||||||
|
int r = MATCH_NOTHING;
|
||||||
|
|
||||||
|
if (dev) {
|
||||||
|
- if (_blacklist_exceptions(elist, dev))
|
||||||
|
+ if (match_reglist(elist, dev))
|
||||||
|
r = MATCH_DEVNODE_BLIST_EXCEPT;
|
||||||
|
- else if (_blacklist(blist, dev))
|
||||||
|
+ else if (match_reglist(blist, dev))
|
||||||
|
r = MATCH_DEVNODE_BLIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -326,9 +294,9 @@ filter_wwid (vector blist, vector elist, char * wwid, char * dev)
|
||||||
|
int r = MATCH_NOTHING;
|
||||||
|
|
||||||
|
if (wwid) {
|
||||||
|
- if (_blacklist_exceptions(elist, wwid))
|
||||||
|
+ if (match_reglist(elist, wwid))
|
||||||
|
r = MATCH_WWID_BLIST_EXCEPT;
|
||||||
|
- else if (_blacklist(blist, wwid))
|
||||||
|
+ else if (match_reglist(blist, wwid))
|
||||||
|
r = MATCH_WWID_BLIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -345,9 +313,9 @@ filter_protocol(vector blist, vector elist, struct path * pp)
|
||||||
|
if (pp) {
|
||||||
|
snprint_path_protocol(buf, sizeof(buf), pp);
|
||||||
|
|
||||||
|
- if (_blacklist_exceptions(elist, buf))
|
||||||
|
+ if (match_reglist(elist, buf))
|
||||||
|
r = MATCH_PROTOCOL_BLIST_EXCEPT;
|
||||||
|
- else if (_blacklist(blist, buf))
|
||||||
|
+ else if (match_reglist(blist, buf))
|
||||||
|
r = MATCH_PROTOCOL_BLIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -417,11 +385,11 @@ filter_property(struct config *conf, struct udev_device *udev, int lvl,
|
||||||
|
if (check_missing_prop && !strcmp(env, uid_attribute))
|
||||||
|
uid_attr_seen = true;
|
||||||
|
|
||||||
|
- if (_blacklist_exceptions(conf->elist_property, env)) {
|
||||||
|
+ if (match_reglist(conf->elist_property, env)) {
|
||||||
|
r = MATCH_PROPERTY_BLIST_EXCEPT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
- if (_blacklist(conf->blist_property, env)) {
|
||||||
|
+ if (match_reglist(conf->blist_property, env)) {
|
||||||
|
r = MATCH_PROPERTY_BLIST;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,95 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 8 Jun 2020 20:23:56 -0500
|
||||||
|
Subject: [PATCH] libmultipath: fix parser issue with comments in strings
|
||||||
|
|
||||||
|
If a quoted string starts with '#' or '!', the parser will stop
|
||||||
|
parsing the line, thinking that it's a comment. It should only
|
||||||
|
be checking for comments outside of quoted strings. Fixed this and
|
||||||
|
added unit tests to verify it.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/parser.c | 4 +++-
|
||||||
|
tests/parser.c | 42 ++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 45 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
|
||||||
|
index a184511b..a7285a35 100644
|
||||||
|
--- a/libmultipath/parser.c
|
||||||
|
+++ b/libmultipath/parser.c
|
||||||
|
@@ -300,8 +300,10 @@ alloc_strvec(char *string)
|
||||||
|
(isspace((int) *cp) || !isascii((int) *cp)))
|
||||||
|
&& *cp != '\0')
|
||||||
|
cp++;
|
||||||
|
- if (*cp == '\0' || *cp == '!' || *cp == '#')
|
||||||
|
+ if (*cp == '\0' ||
|
||||||
|
+ (!in_string && (*cp == '!' || *cp == '#'))) {
|
||||||
|
return strvec;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
vector_free(strvec);
|
||||||
|
diff --git a/tests/parser.c b/tests/parser.c
|
||||||
|
index 29859dac..5772391e 100644
|
||||||
|
--- a/tests/parser.c
|
||||||
|
+++ b/tests/parser.c
|
||||||
|
@@ -440,6 +440,46 @@ static void test18(void **state)
|
||||||
|
free_strvec(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void test19(void **state)
|
||||||
|
+{
|
||||||
|
+#define QUOTED19 "!value"
|
||||||
|
+ vector v = alloc_strvec("key \"" QUOTED19 "\"");
|
||||||
|
+ char *val;
|
||||||
|
+
|
||||||
|
+ assert_int_equal(VECTOR_SIZE(v), 4);
|
||||||
|
+ assert_string_equal(VECTOR_SLOT(v, 0), "key");
|
||||||
|
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));
|
||||||
|
+ assert_string_equal(VECTOR_SLOT(v, 2), QUOTED19);
|
||||||
|
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));
|
||||||
|
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
|
||||||
|
+
|
||||||
|
+ val = set_value(v);
|
||||||
|
+ assert_string_equal(val, QUOTED19);
|
||||||
|
+
|
||||||
|
+ free(val);
|
||||||
|
+ free_strvec(v);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void test20(void **state)
|
||||||
|
+{
|
||||||
|
+#define QUOTED20 "#value"
|
||||||
|
+ vector v = alloc_strvec("key \"" QUOTED20 "\"");
|
||||||
|
+ char *val;
|
||||||
|
+
|
||||||
|
+ assert_int_equal(VECTOR_SIZE(v), 4);
|
||||||
|
+ assert_string_equal(VECTOR_SLOT(v, 0), "key");
|
||||||
|
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));
|
||||||
|
+ assert_string_equal(VECTOR_SLOT(v, 2), QUOTED20);
|
||||||
|
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));
|
||||||
|
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
|
||||||
|
+
|
||||||
|
+ val = set_value(v);
|
||||||
|
+ assert_string_equal(val, QUOTED20);
|
||||||
|
+
|
||||||
|
+ free(val);
|
||||||
|
+ free_strvec(v);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int test_config_parser(void)
|
||||||
|
{
|
||||||
|
const struct CMUnitTest tests[] = {
|
||||||
|
@@ -461,6 +501,8 @@ int test_config_parser(void)
|
||||||
|
cmocka_unit_test(test16),
|
||||||
|
cmocka_unit_test(test17),
|
||||||
|
cmocka_unit_test(test18),
|
||||||
|
+ cmocka_unit_test(test19),
|
||||||
|
+ cmocka_unit_test(test20),
|
||||||
|
};
|
||||||
|
return cmocka_run_group_tests(tests, setup, teardown);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,435 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 8 Jun 2020 13:40:16 -0500
|
||||||
|
Subject: [PATCH] libmultipath: invert regexes that start with exclamation
|
||||||
|
point
|
||||||
|
|
||||||
|
The number of devices that multipath needs to blacklist keeps growing,
|
||||||
|
and the udev rules already have
|
||||||
|
|
||||||
|
KERNEL!="sd*|dasd*|nvme*", GOTO="end_mpath"
|
||||||
|
|
||||||
|
so they only work correctly with these device types. Instead of
|
||||||
|
individually blacklisting every type of device that can't be
|
||||||
|
multipathed, multipath's default blacklist should work like the udev
|
||||||
|
rule, and blacklist all devices that aren't scsi, dasd, or nvme.
|
||||||
|
Unfortunately, the c regex library doesn't support negative lookahead.
|
||||||
|
Instead, multipath should treat "!" at the beginning of
|
||||||
|
blacklist/exceptions regexes as inverse matching the rest of the regex.
|
||||||
|
If users need to match a literal '!' as the first character of their
|
||||||
|
regex, they can use "\!" instead. This allows multipath to change the
|
||||||
|
default devnode blacklist regex to "!^(sd[a-z]|dasd[a-z]|nvme[0-9])".
|
||||||
|
|
||||||
|
Extra tests have been added to the blacklist unit tests to verify the
|
||||||
|
inverse matching code and the new default blacklist.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/blacklist.c | 41 +++++++++-----
|
||||||
|
libmultipath/blacklist.h | 3 +
|
||||||
|
multipath/multipath.conf.5 | 17 ++++--
|
||||||
|
tests/blacklist.c | 110 +++++++++++++++++++++++++++++++++++++
|
||||||
|
tests/test-lib.c | 2 +-
|
||||||
|
5 files changed, 155 insertions(+), 18 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
|
||||||
|
index 04d3adb9..0c58aa32 100644
|
||||||
|
--- a/libmultipath/blacklist.c
|
||||||
|
+++ b/libmultipath/blacklist.c
|
||||||
|
@@ -15,9 +15,24 @@
|
||||||
|
#include "structs_vec.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
+char *check_invert(char *str, bool *invert)
|
||||||
|
+{
|
||||||
|
+ if (str[0] == '!') {
|
||||||
|
+ *invert = true;
|
||||||
|
+ return str + 1;
|
||||||
|
+ }
|
||||||
|
+ if (str[0] == '\\' && str[1] == '!') {
|
||||||
|
+ *invert = false;
|
||||||
|
+ return str + 1;
|
||||||
|
+ }
|
||||||
|
+ *invert = false;
|
||||||
|
+ return str;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int store_ble(vector blist, char * str, int origin)
|
||||||
|
{
|
||||||
|
struct blentry * ble;
|
||||||
|
+ char *regex_str;
|
||||||
|
|
||||||
|
if (!str)
|
||||||
|
return 0;
|
||||||
|
@@ -30,7 +45,8 @@ int store_ble(vector blist, char * str, int origin)
|
||||||
|
if (!ble)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
- if (regcomp(&ble->regex, str, REG_EXTENDED|REG_NOSUB))
|
||||||
|
+ regex_str = check_invert(str, &ble->invert);
|
||||||
|
+ if (regcomp(&ble->regex, regex_str, REG_EXTENDED|REG_NOSUB))
|
||||||
|
goto out1;
|
||||||
|
|
||||||
|
if (!vector_alloc_slot(blist))
|
||||||
|
@@ -66,6 +82,7 @@ int alloc_ble_device(vector blist)
|
||||||
|
int set_ble_device(vector blist, char * vendor, char * product, int origin)
|
||||||
|
{
|
||||||
|
struct blentry_device * ble;
|
||||||
|
+ char *regex_str;
|
||||||
|
|
||||||
|
if (!blist)
|
||||||
|
return 1;
|
||||||
|
@@ -76,7 +93,8 @@ int set_ble_device(vector blist, char * vendor, char * product, int origin)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (vendor) {
|
||||||
|
- if (regcomp(&ble->vendor_reg, vendor,
|
||||||
|
+ regex_str = check_invert(vendor, &ble->vendor_invert);
|
||||||
|
+ if (regcomp(&ble->vendor_reg, regex_str,
|
||||||
|
REG_EXTENDED|REG_NOSUB)) {
|
||||||
|
FREE(vendor);
|
||||||
|
if (product)
|
||||||
|
@@ -86,7 +104,8 @@ int set_ble_device(vector blist, char * vendor, char * product, int origin)
|
||||||
|
ble->vendor = vendor;
|
||||||
|
}
|
||||||
|
if (product) {
|
||||||
|
- if (regcomp(&ble->product_reg, product,
|
||||||
|
+ regex_str = check_invert(product, &ble->product_invert);
|
||||||
|
+ if (regcomp(&ble->product_reg, regex_str,
|
||||||
|
REG_EXTENDED|REG_NOSUB)) {
|
||||||
|
FREE(product);
|
||||||
|
if (vendor) {
|
||||||
|
@@ -108,7 +127,7 @@ match_reglist (vector blist, const char * str)
|
||||||
|
struct blentry * ble;
|
||||||
|
|
||||||
|
vector_foreach_slot (blist, ble, i) {
|
||||||
|
- if (!regexec(&ble->regex, str, 0, NULL, 0))
|
||||||
|
+ if (!!regexec(&ble->regex, str, 0, NULL, 0) == ble->invert)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
@@ -125,9 +144,11 @@ match_reglist_device (const struct _vector *blist, const char * vendor,
|
||||||
|
if (!ble->vendor && !ble->product)
|
||||||
|
continue;
|
||||||
|
if ((!ble->vendor ||
|
||||||
|
- !regexec(&ble->vendor_reg, vendor, 0, NULL, 0)) &&
|
||||||
|
+ !!regexec(&ble->vendor_reg, vendor, 0, NULL, 0) ==
|
||||||
|
+ ble->vendor_invert) &&
|
||||||
|
(!ble->product ||
|
||||||
|
- !regexec(&ble->product_reg, product, 0, NULL, 0)))
|
||||||
|
+ !!regexec(&ble->product_reg, product, 0, NULL, 0) ==
|
||||||
|
+ ble->product_invert))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
@@ -160,13 +181,7 @@ setup_default_blist (struct config * conf)
|
||||||
|
char * str;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
- str = STRDUP("^(ram|zram|raw|loop|fd|md|dm-|sr|scd|st|dcssblk)[0-9]");
|
||||||
|
- if (!str)
|
||||||
|
- return 1;
|
||||||
|
- if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
|
||||||
|
- return 1;
|
||||||
|
-
|
||||||
|
- str = STRDUP("^(td|hd|vd)[a-z]");
|
||||||
|
+ str = STRDUP("!^(sd[a-z]|dasd[a-z]|nvme[0-9])");
|
||||||
|
if (!str)
|
||||||
|
return 1;
|
||||||
|
if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
|
||||||
|
diff --git a/libmultipath/blacklist.h b/libmultipath/blacklist.h
|
||||||
|
index 2d721f60..4305857d 100644
|
||||||
|
--- a/libmultipath/blacklist.h
|
||||||
|
+++ b/libmultipath/blacklist.h
|
||||||
|
@@ -20,6 +20,7 @@
|
||||||
|
struct blentry {
|
||||||
|
char * str;
|
||||||
|
regex_t regex;
|
||||||
|
+ bool invert;
|
||||||
|
int origin;
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -28,6 +29,8 @@ struct blentry_device {
|
||||||
|
char * product;
|
||||||
|
regex_t vendor_reg;
|
||||||
|
regex_t product_reg;
|
||||||
|
+ bool vendor_invert;
|
||||||
|
+ bool product_invert;
|
||||||
|
int origin;
|
||||||
|
};
|
||||||
|
|
||||||
|
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
||||||
|
index 3455b1cc..6dc26f10 100644
|
||||||
|
--- a/multipath/multipath.conf.5
|
||||||
|
+++ b/multipath/multipath.conf.5
|
||||||
|
@@ -1248,6 +1248,16 @@ being handled by multipath-tools.
|
||||||
|
.LP
|
||||||
|
.
|
||||||
|
.
|
||||||
|
+In the \fIblacklist\fR and \fIblacklist_exceptions\fR sections, starting a
|
||||||
|
+quoted value with an exclamation mark \fB"!"\fR will invert the matching
|
||||||
|
+of the rest of the regular expression. For instance, \fB"!^sd[a-z]"\fR will
|
||||||
|
+match all values that do not start with \fB"sd[a-z]"\fR. The exclamation mark
|
||||||
|
+can be escaped \fB"\\!"\fR to match a literal \fB!\fR at the start of a
|
||||||
|
+regular expression. \fBNote:\fR The exclamation mark must be inside quotes,
|
||||||
|
+otherwise it will be treated as starting a comment.
|
||||||
|
+.LP
|
||||||
|
+.
|
||||||
|
+.
|
||||||
|
The \fIblacklist_exceptions\fR section is used to revert the actions of the
|
||||||
|
\fIblacklist\fR section. This allows one to selectively include ("whitelist") devices which
|
||||||
|
would normally be excluded via the \fIblacklist\fR section. A common usage is
|
||||||
|
@@ -1264,10 +1274,9 @@ unless explicitly stated.
|
||||||
|
Regular expression matching the device nodes to be excluded/included.
|
||||||
|
.RS
|
||||||
|
.PP
|
||||||
|
-The default \fIblacklist\fR consists of the regular expressions
|
||||||
|
-"^(ram|zram|raw|loop|fd|md|dm-|sr|scd|st|dcssblk)[0-9]" and
|
||||||
|
-"^(td|hd|vd)[a-z]". This causes virtual devices, non-disk devices, and some other
|
||||||
|
-device types to be excluded from multipath handling by default.
|
||||||
|
+The default \fIblacklist\fR consists of the regular expression
|
||||||
|
+\fB"!^(sd[a-z]|dasd[a-z]|nvme[0-9])"\fR. This causes all device types other
|
||||||
|
+than scsi, dasd, and nvme to be excluded from multipath handling by default.
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B wwid
|
||||||
|
diff --git a/tests/blacklist.c b/tests/blacklist.c
|
||||||
|
index cc8a9a4a..d20e97af 100644
|
||||||
|
--- a/tests/blacklist.c
|
||||||
|
+++ b/tests/blacklist.c
|
||||||
|
@@ -60,20 +60,46 @@ __wrap_udev_list_entry_get_name(struct udev_list_entry *list_entry)
|
||||||
|
return *(const char **)list_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
+vector elist_property_default;
|
||||||
|
+vector blist_devnode_default;
|
||||||
|
vector blist_devnode_sdb;
|
||||||
|
+vector blist_devnode_sdb_inv;
|
||||||
|
vector blist_all;
|
||||||
|
vector blist_device_foo_bar;
|
||||||
|
+vector blist_device_foo_inv_bar;
|
||||||
|
+vector blist_device_foo_bar_inv;
|
||||||
|
vector blist_device_all;
|
||||||
|
vector blist_wwid_xyzzy;
|
||||||
|
+vector blist_wwid_xyzzy_inv;
|
||||||
|
vector blist_protocol_fcp;
|
||||||
|
+vector blist_protocol_fcp_inv;
|
||||||
|
vector blist_property_wwn;
|
||||||
|
+vector blist_property_wwn_inv;
|
||||||
|
|
||||||
|
static int setup(void **state)
|
||||||
|
{
|
||||||
|
+ struct config conf;
|
||||||
|
+
|
||||||
|
+ memset(&conf, 0, sizeof(conf));
|
||||||
|
+ conf.blist_devnode = vector_alloc();
|
||||||
|
+ if (!conf.blist_devnode)
|
||||||
|
+ return -1;
|
||||||
|
+ conf.elist_property = vector_alloc();
|
||||||
|
+ if (!conf.elist_property)
|
||||||
|
+ return -1;
|
||||||
|
+ if (setup_default_blist(&conf) != 0)
|
||||||
|
+ return -1;
|
||||||
|
+ elist_property_default = conf.elist_property;
|
||||||
|
+ blist_devnode_default = conf.blist_devnode;
|
||||||
|
+
|
||||||
|
blist_devnode_sdb = vector_alloc();
|
||||||
|
if (!blist_devnode_sdb ||
|
||||||
|
store_ble(blist_devnode_sdb, strdup("sdb"), ORIGIN_CONFIG))
|
||||||
|
return -1;
|
||||||
|
+ blist_devnode_sdb_inv = vector_alloc();
|
||||||
|
+ if (!blist_devnode_sdb_inv ||
|
||||||
|
+ store_ble(blist_devnode_sdb_inv, strdup("!sdb"), ORIGIN_CONFIG))
|
||||||
|
+ return -1;
|
||||||
|
|
||||||
|
blist_all = vector_alloc();
|
||||||
|
if (!blist_all || store_ble(blist_all, strdup(".*"), ORIGIN_CONFIG))
|
||||||
|
@@ -84,6 +110,18 @@ static int setup(void **state)
|
||||||
|
set_ble_device(blist_device_foo_bar, strdup("foo"), strdup("bar"),
|
||||||
|
ORIGIN_CONFIG))
|
||||||
|
return -1;
|
||||||
|
+ blist_device_foo_inv_bar = vector_alloc();
|
||||||
|
+ if (!blist_device_foo_inv_bar ||
|
||||||
|
+ alloc_ble_device(blist_device_foo_inv_bar) ||
|
||||||
|
+ set_ble_device(blist_device_foo_inv_bar, strdup("!foo"),
|
||||||
|
+ strdup("bar"), ORIGIN_CONFIG))
|
||||||
|
+ return -1;
|
||||||
|
+ blist_device_foo_bar_inv = vector_alloc();
|
||||||
|
+ if (!blist_device_foo_bar_inv ||
|
||||||
|
+ alloc_ble_device(blist_device_foo_bar_inv) ||
|
||||||
|
+ set_ble_device(blist_device_foo_bar_inv, strdup("foo"),
|
||||||
|
+ strdup("!bar"), ORIGIN_CONFIG))
|
||||||
|
+ return -1;
|
||||||
|
|
||||||
|
blist_device_all = vector_alloc();
|
||||||
|
if (!blist_device_all || alloc_ble_device(blist_device_all) ||
|
||||||
|
@@ -95,29 +133,50 @@ static int setup(void **state)
|
||||||
|
if (!blist_wwid_xyzzy ||
|
||||||
|
store_ble(blist_wwid_xyzzy, strdup("xyzzy"), ORIGIN_CONFIG))
|
||||||
|
return -1;
|
||||||
|
+ blist_wwid_xyzzy_inv = vector_alloc();
|
||||||
|
+ if (!blist_wwid_xyzzy_inv ||
|
||||||
|
+ store_ble(blist_wwid_xyzzy_inv, strdup("!xyzzy"), ORIGIN_CONFIG))
|
||||||
|
+ return -1;
|
||||||
|
|
||||||
|
blist_protocol_fcp = vector_alloc();
|
||||||
|
if (!blist_protocol_fcp ||
|
||||||
|
store_ble(blist_protocol_fcp, strdup("scsi:fcp"), ORIGIN_CONFIG))
|
||||||
|
return -1;
|
||||||
|
+ blist_protocol_fcp_inv = vector_alloc();
|
||||||
|
+ if (!blist_protocol_fcp_inv ||
|
||||||
|
+ store_ble(blist_protocol_fcp_inv, strdup("!scsi:fcp"),
|
||||||
|
+ ORIGIN_CONFIG))
|
||||||
|
+ return -1;
|
||||||
|
|
||||||
|
blist_property_wwn = vector_alloc();
|
||||||
|
if (!blist_property_wwn ||
|
||||||
|
store_ble(blist_property_wwn, strdup("ID_WWN"), ORIGIN_CONFIG))
|
||||||
|
return -1;
|
||||||
|
+ blist_property_wwn_inv = vector_alloc();
|
||||||
|
+ if (!blist_property_wwn_inv ||
|
||||||
|
+ store_ble(blist_property_wwn_inv, strdup("!ID_WWN"), ORIGIN_CONFIG))
|
||||||
|
+ return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int teardown(void **state)
|
||||||
|
{
|
||||||
|
+ free_blacklist(elist_property_default);
|
||||||
|
+ free_blacklist(blist_devnode_default);
|
||||||
|
free_blacklist(blist_devnode_sdb);
|
||||||
|
+ free_blacklist(blist_devnode_sdb_inv);
|
||||||
|
free_blacklist(blist_all);
|
||||||
|
free_blacklist_device(blist_device_foo_bar);
|
||||||
|
+ free_blacklist_device(blist_device_foo_inv_bar);
|
||||||
|
+ free_blacklist_device(blist_device_foo_bar_inv);
|
||||||
|
free_blacklist_device(blist_device_all);
|
||||||
|
free_blacklist(blist_wwid_xyzzy);
|
||||||
|
+ free_blacklist(blist_wwid_xyzzy_inv);
|
||||||
|
free_blacklist(blist_protocol_fcp);
|
||||||
|
+ free_blacklist(blist_protocol_fcp_inv);
|
||||||
|
free_blacklist(blist_property_wwn);
|
||||||
|
+ free_blacklist(blist_property_wwn_inv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -141,6 +200,11 @@ static void test_devnode_blacklist(void **state)
|
||||||
|
expect_condlog(3, "sdb: device node name blacklisted\n");
|
||||||
|
assert_int_equal(filter_devnode(blist_devnode_sdb, NULL, "sdb"),
|
||||||
|
MATCH_DEVNODE_BLIST);
|
||||||
|
+ assert_int_equal(filter_devnode(blist_devnode_sdb_inv, NULL, "sdb"),
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
+ expect_condlog(3, "sdc: device node name blacklisted\n");
|
||||||
|
+ assert_int_equal(filter_devnode(blist_devnode_sdb_inv, NULL, "sdc"),
|
||||||
|
+ MATCH_DEVNODE_BLIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_devnode_whitelist(void **state)
|
||||||
|
@@ -159,12 +223,39 @@ static void test_devnode_missing(void **state)
|
||||||
|
MATCH_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void test_devnode_default(void **state)
|
||||||
|
+{
|
||||||
|
+ assert_int_equal(filter_devnode(blist_devnode_default, NULL, "sdaa"),
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
+ assert_int_equal(filter_devnode(blist_devnode_default, NULL, "nvme0n1"),
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
+ assert_int_equal(filter_devnode(blist_devnode_default, NULL, "dasda"),
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
+ expect_condlog(3, "hda: device node name blacklisted\n");
|
||||||
|
+ assert_int_equal(filter_devnode(blist_devnode_default, NULL, "hda"),
|
||||||
|
+ MATCH_DEVNODE_BLIST);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void test_device_blacklist(void **state)
|
||||||
|
{
|
||||||
|
expect_condlog(3, "sdb: (foo:bar) vendor/product blacklisted\n");
|
||||||
|
assert_int_equal(filter_device(blist_device_foo_bar, NULL, "foo",
|
||||||
|
"bar", "sdb"),
|
||||||
|
MATCH_DEVICE_BLIST);
|
||||||
|
+ assert_int_equal(filter_device(blist_device_foo_inv_bar, NULL, "foo",
|
||||||
|
+ "bar", "sdb"),
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
+ assert_int_equal(filter_device(blist_device_foo_bar_inv, NULL, "foo",
|
||||||
|
+ "bar", "sdb"),
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
+ expect_condlog(3, "sdb: (baz:bar) vendor/product blacklisted\n");
|
||||||
|
+ assert_int_equal(filter_device(blist_device_foo_inv_bar, NULL, "baz",
|
||||||
|
+ "bar", "sdb"),
|
||||||
|
+ MATCH_DEVICE_BLIST);
|
||||||
|
+ expect_condlog(3, "sdb: (foo:baz) vendor/product blacklisted\n");
|
||||||
|
+ assert_int_equal(filter_device(blist_device_foo_bar_inv, NULL, "foo",
|
||||||
|
+ "baz", "sdb"),
|
||||||
|
+ MATCH_DEVICE_BLIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_device_whitelist(void **state)
|
||||||
|
@@ -191,6 +282,11 @@ static void test_wwid_blacklist(void **state)
|
||||||
|
expect_condlog(3, "sdb: wwid xyzzy blacklisted\n");
|
||||||
|
assert_int_equal(filter_wwid(blist_wwid_xyzzy, NULL, "xyzzy", "sdb"),
|
||||||
|
MATCH_WWID_BLIST);
|
||||||
|
+ assert_int_equal(filter_wwid(blist_wwid_xyzzy_inv, NULL, "xyzzy",
|
||||||
|
+ "sdb"), MATCH_NOTHING);
|
||||||
|
+ expect_condlog(3, "sdb: wwid plugh blacklisted\n");
|
||||||
|
+ assert_int_equal(filter_wwid(blist_wwid_xyzzy_inv, NULL, "plugh",
|
||||||
|
+ "sdb"), MATCH_WWID_BLIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_wwid_whitelist(void **state)
|
||||||
|
@@ -218,6 +314,12 @@ static void test_protocol_blacklist(void **state)
|
||||||
|
expect_condlog(3, "sdb: protocol scsi:fcp blacklisted\n");
|
||||||
|
assert_int_equal(filter_protocol(blist_protocol_fcp, NULL, &pp),
|
||||||
|
MATCH_PROTOCOL_BLIST);
|
||||||
|
+ assert_int_equal(filter_protocol(blist_protocol_fcp_inv, NULL, &pp),
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
+ pp.sg_id.proto_id = SCSI_PROTOCOL_ATA;
|
||||||
|
+ expect_condlog(3, "sdb: protocol scsi:ata blacklisted\n");
|
||||||
|
+ assert_int_equal(filter_protocol(blist_protocol_fcp_inv, NULL, &pp),
|
||||||
|
+ MATCH_PROTOCOL_BLIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_protocol_whitelist(void **state)
|
||||||
|
@@ -245,10 +347,17 @@ static void test_protocol_missing(void **state)
|
||||||
|
static void test_property_blacklist(void **state)
|
||||||
|
{
|
||||||
|
static struct udev_device udev = { "sdb", { "ID_FOO", "ID_WWN", "ID_BAR", NULL } };
|
||||||
|
+ static struct udev_device udev_inv = { "sdb", { "ID_WWN", NULL } };
|
||||||
|
conf.blist_property = blist_property_wwn;
|
||||||
|
expect_condlog(3, "sdb: udev property ID_WWN blacklisted\n");
|
||||||
|
assert_int_equal(filter_property(&conf, &udev, 3, "ID_SERIAL"),
|
||||||
|
MATCH_PROPERTY_BLIST);
|
||||||
|
+ conf.blist_property = blist_property_wwn_inv;
|
||||||
|
+ expect_condlog(3, "sdb: udev property ID_FOO blacklisted\n");
|
||||||
|
+ assert_int_equal(filter_property(&conf, &udev, 3, "ID_SERIAL"),
|
||||||
|
+ MATCH_PROPERTY_BLIST);
|
||||||
|
+ assert_int_equal(filter_property(&conf, &udev_inv, 3, "ID_SERIAL"),
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the property check works different in that you check all the property
|
||||||
|
@@ -482,6 +591,7 @@ int test_blacklist(void)
|
||||||
|
cmocka_unit_test(test_devnode_blacklist),
|
||||||
|
cmocka_unit_test(test_devnode_whitelist),
|
||||||
|
cmocka_unit_test(test_devnode_missing),
|
||||||
|
+ cmocka_unit_test(test_devnode_default),
|
||||||
|
cmocka_unit_test(test_device_blacklist),
|
||||||
|
cmocka_unit_test(test_device_whitelist),
|
||||||
|
cmocka_unit_test(test_device_missing),
|
||||||
|
diff --git a/tests/test-lib.c b/tests/test-lib.c
|
||||||
|
index 59275163..08ff2d8d 100644
|
||||||
|
--- a/tests/test-lib.c
|
||||||
|
+++ b/tests/test-lib.c
|
||||||
|
@@ -15,7 +15,7 @@
|
||||||
|
#include "test-lib.h"
|
||||||
|
|
||||||
|
const int default_mask = (DI_SYSFS|DI_BLACKLIST|DI_WWID|DI_CHECKER|DI_PRIO);
|
||||||
|
-const char default_devnode[] = "sdTEST";
|
||||||
|
+const char default_devnode[] = "sdxTEST";
|
||||||
|
const char default_wwid[] = "TEST-WWID";
|
||||||
|
/* default_wwid should be a substring of default_wwid_1! */
|
||||||
|
const char default_wwid_1[] = "TEST-WWID-1";
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,322 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 23 Jun 2020 22:17:31 -0500
|
||||||
|
Subject: [PATCH] libmultipath: make dm_get_map/status return codes symbolic
|
||||||
|
|
||||||
|
dm_get_map() and dm_get_status() now use symbolic return codes. They
|
||||||
|
also differentiate between failing to get information from device-mapper
|
||||||
|
and not finding the requested device. These symboilc return codes are
|
||||||
|
also used by update_multipath_* functions.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/devmapper.c | 51 +++++++++++++++++++++++++-------------
|
||||||
|
libmultipath/devmapper.h | 6 +++++
|
||||||
|
libmultipath/structs_vec.c | 45 +++++++++++++++++++--------------
|
||||||
|
multipathd/main.c | 12 ++++-----
|
||||||
|
4 files changed, 72 insertions(+), 42 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||||
|
index 13a1cf53..f6204e5f 100644
|
||||||
|
--- a/libmultipath/devmapper.c
|
||||||
|
+++ b/libmultipath/devmapper.c
|
||||||
|
@@ -525,36 +525,43 @@ int dm_map_present(const char * str)
|
||||||
|
|
||||||
|
int dm_get_map(const char *name, unsigned long long *size, char *outparams)
|
||||||
|
{
|
||||||
|
- int r = 1;
|
||||||
|
+ int r = DMP_ERR;
|
||||||
|
struct dm_task *dmt;
|
||||||
|
uint64_t start, length;
|
||||||
|
char *target_type = NULL;
|
||||||
|
char *params = NULL;
|
||||||
|
|
||||||
|
if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
|
||||||
|
- return 1;
|
||||||
|
+ return r;
|
||||||
|
|
||||||
|
if (!dm_task_set_name(dmt, name))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
dm_task_no_open_count(dmt);
|
||||||
|
|
||||||
|
- if (!dm_task_run(dmt))
|
||||||
|
+ errno = 0;
|
||||||
|
+ if (!dm_task_run(dmt)) {
|
||||||
|
+ if (dm_task_get_errno(dmt) == ENXIO)
|
||||||
|
+ r = DMP_NOT_FOUND;
|
||||||
|
goto out;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
+ r = DMP_NOT_FOUND;
|
||||||
|
/* Fetch 1st target */
|
||||||
|
- dm_get_next_target(dmt, NULL, &start, &length,
|
||||||
|
- &target_type, ¶ms);
|
||||||
|
+ if (dm_get_next_target(dmt, NULL, &start, &length,
|
||||||
|
+ &target_type, ¶ms) != NULL)
|
||||||
|
+ /* more than one target */
|
||||||
|
+ goto out;
|
||||||
|
|
||||||
|
if (size)
|
||||||
|
*size = length;
|
||||||
|
|
||||||
|
if (!outparams) {
|
||||||
|
- r = 0;
|
||||||
|
+ r = DMP_OK;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (snprintf(outparams, PARAMS_SIZE, "%s", params) <= PARAMS_SIZE)
|
||||||
|
- r = 0;
|
||||||
|
+ r = DMP_OK;
|
||||||
|
out:
|
||||||
|
dm_task_destroy(dmt);
|
||||||
|
return r;
|
||||||
|
@@ -628,35 +635,45 @@ is_mpath_part(const char *part_name, const char *map_name)
|
||||||
|
|
||||||
|
int dm_get_status(const char *name, char *outstatus)
|
||||||
|
{
|
||||||
|
- int r = 1;
|
||||||
|
+ int r = DMP_ERR;
|
||||||
|
struct dm_task *dmt;
|
||||||
|
uint64_t start, length;
|
||||||
|
char *target_type = NULL;
|
||||||
|
char *status = NULL;
|
||||||
|
|
||||||
|
if (!(dmt = libmp_dm_task_create(DM_DEVICE_STATUS)))
|
||||||
|
- return 1;
|
||||||
|
+ return r;
|
||||||
|
|
||||||
|
if (!dm_task_set_name(dmt, name))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
dm_task_no_open_count(dmt);
|
||||||
|
|
||||||
|
- if (!dm_task_run(dmt))
|
||||||
|
+ errno = 0;
|
||||||
|
+ if (!dm_task_run(dmt)) {
|
||||||
|
+ if (dm_task_get_errno(dmt) == ENXIO)
|
||||||
|
+ r = DMP_NOT_FOUND;
|
||||||
|
goto out;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
+ r = DMP_NOT_FOUND;
|
||||||
|
/* Fetch 1st target */
|
||||||
|
- dm_get_next_target(dmt, NULL, &start, &length,
|
||||||
|
- &target_type, &status);
|
||||||
|
+ if (dm_get_next_target(dmt, NULL, &start, &length,
|
||||||
|
+ &target_type, &status) != NULL)
|
||||||
|
+ goto out;
|
||||||
|
+
|
||||||
|
+ if (!target_type || strcmp(target_type, TGT_MPATH) != 0)
|
||||||
|
+ goto out;
|
||||||
|
+
|
||||||
|
if (!status) {
|
||||||
|
condlog(2, "get null status.");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snprintf(outstatus, PARAMS_SIZE, "%s", status) <= PARAMS_SIZE)
|
||||||
|
- r = 0;
|
||||||
|
+ r = DMP_OK;
|
||||||
|
out:
|
||||||
|
- if (r)
|
||||||
|
+ if (r != DMP_OK)
|
||||||
|
condlog(0, "%s: error getting map status string", name);
|
||||||
|
|
||||||
|
dm_task_destroy(dmt);
|
||||||
|
@@ -866,7 +883,7 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove,
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (need_suspend &&
|
||||||
|
- !dm_get_map(mapname, &mapsize, params) &&
|
||||||
|
+ dm_get_map(mapname, &mapsize, params) == DMP_OK &&
|
||||||
|
strstr(params, "queue_if_no_path")) {
|
||||||
|
if (!dm_queue_if_no_path(mapname, 0))
|
||||||
|
queue_if_no_path = 1;
|
||||||
|
@@ -1075,7 +1092,7 @@ struct multipath *dm_get_multipath(const char *name)
|
||||||
|
if (!mpp->alias)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
- if (dm_get_map(name, &mpp->size, NULL))
|
||||||
|
+ if (dm_get_map(name, &mpp->size, NULL) != DMP_OK)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
dm_get_uuid(name, mpp->wwid, WWID_SIZE);
|
||||||
|
@@ -1259,7 +1276,7 @@ do_foreach_partmaps (const char * mapname,
|
||||||
|
/*
|
||||||
|
* and we can fetch the map table from the kernel
|
||||||
|
*/
|
||||||
|
- !dm_get_map(names->name, &size, ¶ms[0]) &&
|
||||||
|
+ dm_get_map(names->name, &size, ¶ms[0]) == DMP_OK &&
|
||||||
|
|
||||||
|
/*
|
||||||
|
* and the table maps over the multipath map
|
||||||
|
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
|
||||||
|
index 7557a86b..adb55000 100644
|
||||||
|
--- a/libmultipath/devmapper.h
|
||||||
|
+++ b/libmultipath/devmapper.h
|
||||||
|
@@ -27,6 +27,12 @@
|
||||||
|
#define UUID_PREFIX "mpath-"
|
||||||
|
#define UUID_PREFIX_LEN (sizeof(UUID_PREFIX) - 1)
|
||||||
|
|
||||||
|
+enum {
|
||||||
|
+ DMP_ERR,
|
||||||
|
+ DMP_OK,
|
||||||
|
+ DMP_NOT_FOUND,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
void dm_init(int verbosity);
|
||||||
|
void libmp_dm_init(void);
|
||||||
|
void libmp_udev_set_sync_support(int on);
|
||||||
|
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
|
||||||
|
index 077f2e42..8137ea21 100644
|
||||||
|
--- a/libmultipath/structs_vec.c
|
||||||
|
+++ b/libmultipath/structs_vec.c
|
||||||
|
@@ -196,43 +196,47 @@ extract_hwe_from_path(struct multipath * mpp)
|
||||||
|
int
|
||||||
|
update_multipath_table (struct multipath *mpp, vector pathvec, int is_daemon)
|
||||||
|
{
|
||||||
|
+ int r = DMP_ERR;
|
||||||
|
char params[PARAMS_SIZE] = {0};
|
||||||
|
|
||||||
|
if (!mpp)
|
||||||
|
- return 1;
|
||||||
|
+ return r;
|
||||||
|
|
||||||
|
- if (dm_get_map(mpp->alias, &mpp->size, params)) {
|
||||||
|
- condlog(3, "%s: cannot get map", mpp->alias);
|
||||||
|
- return 1;
|
||||||
|
+ r = dm_get_map(mpp->alias, &mpp->size, params);
|
||||||
|
+ if (r != DMP_OK) {
|
||||||
|
+ condlog(3, "%s: %s", mpp->alias, (r == DMP_ERR)? "error getting table" : "map not present");
|
||||||
|
+ return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disassemble_map(pathvec, params, mpp, is_daemon)) {
|
||||||
|
condlog(3, "%s: cannot disassemble map", mpp->alias);
|
||||||
|
- return 1;
|
||||||
|
+ return DMP_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return 0;
|
||||||
|
+ return DMP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
update_multipath_status (struct multipath *mpp)
|
||||||
|
{
|
||||||
|
+ int r = DMP_ERR;
|
||||||
|
char status[PARAMS_SIZE] = {0};
|
||||||
|
|
||||||
|
if (!mpp)
|
||||||
|
- return 1;
|
||||||
|
+ return r;
|
||||||
|
|
||||||
|
- if (dm_get_status(mpp->alias, status)) {
|
||||||
|
- condlog(3, "%s: cannot get status", mpp->alias);
|
||||||
|
- return 1;
|
||||||
|
+ r = dm_get_status(mpp->alias, status);
|
||||||
|
+ if (r != DMP_OK) {
|
||||||
|
+ condlog(3, "%s: %s", mpp->alias, (r == DMP_ERR)? "error getting status" : "map not present");
|
||||||
|
+ return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disassemble_status(status, mpp)) {
|
||||||
|
condlog(3, "%s: cannot disassemble status", mpp->alias);
|
||||||
|
- return 1;
|
||||||
|
+ return DMP_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return 0;
|
||||||
|
+ return DMP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sync_paths(struct multipath *mpp, vector pathvec)
|
||||||
|
@@ -264,10 +268,10 @@ int
|
||||||
|
update_multipath_strings(struct multipath *mpp, vector pathvec, int is_daemon)
|
||||||
|
{
|
||||||
|
struct pathgroup *pgp;
|
||||||
|
- int i;
|
||||||
|
+ int i, r = DMP_ERR;
|
||||||
|
|
||||||
|
if (!mpp)
|
||||||
|
- return 1;
|
||||||
|
+ return r;
|
||||||
|
|
||||||
|
update_mpp_paths(mpp, pathvec);
|
||||||
|
condlog(4, "%s: %s", mpp->alias, __FUNCTION__);
|
||||||
|
@@ -276,18 +280,21 @@ update_multipath_strings(struct multipath *mpp, vector pathvec, int is_daemon)
|
||||||
|
free_pgvec(mpp->pg, KEEP_PATHS);
|
||||||
|
mpp->pg = NULL;
|
||||||
|
|
||||||
|
- if (update_multipath_table(mpp, pathvec, is_daemon))
|
||||||
|
- return 1;
|
||||||
|
+ r = update_multipath_table(mpp, pathvec, is_daemon);
|
||||||
|
+ if (r != DMP_OK)
|
||||||
|
+ return r;
|
||||||
|
+
|
||||||
|
sync_paths(mpp, pathvec);
|
||||||
|
|
||||||
|
- if (update_multipath_status(mpp))
|
||||||
|
- return 1;
|
||||||
|
+ r = update_multipath_status(mpp);
|
||||||
|
+ if (r != DMP_OK)
|
||||||
|
+ return r;
|
||||||
|
|
||||||
|
vector_foreach_slot(mpp->pg, pgp, i)
|
||||||
|
if (pgp->paths)
|
||||||
|
path_group_prio_update(pgp);
|
||||||
|
|
||||||
|
- return 0;
|
||||||
|
+ return DMP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void enter_recovery_mode(struct multipath *mpp)
|
||||||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
|
index 6b7db2c0..e3427d3d 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -414,7 +414,7 @@ int __setup_multipath(struct vectors *vecs, struct multipath *mpp,
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (update_multipath_strings(mpp, vecs->pathvec, 1)) {
|
||||||
|
+ if (update_multipath_strings(mpp, vecs->pathvec, 1) != DMP_OK) {
|
||||||
|
condlog(0, "%s: failed to setup multipath", mpp->alias);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
@@ -553,9 +553,9 @@ add_map_without_path (struct vectors *vecs, const char *alias)
|
||||||
|
mpp->mpe = find_mpe(conf->mptable, mpp->wwid);
|
||||||
|
put_multipath_config(conf);
|
||||||
|
|
||||||
|
- if (update_multipath_table(mpp, vecs->pathvec, 1))
|
||||||
|
+ if (update_multipath_table(mpp, vecs->pathvec, 1) != DMP_OK)
|
||||||
|
goto out;
|
||||||
|
- if (update_multipath_status(mpp))
|
||||||
|
+ if (update_multipath_status(mpp) != DMP_OK)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!vector_alloc_slot(vecs->mpvec))
|
||||||
|
@@ -1346,8 +1346,8 @@ map_discovery (struct vectors * vecs)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
vector_foreach_slot (vecs->mpvec, mpp, i)
|
||||||
|
- if (update_multipath_table(mpp, vecs->pathvec, 1) ||
|
||||||
|
- update_multipath_status(mpp)) {
|
||||||
|
+ if (update_multipath_table(mpp, vecs->pathvec, 1) != DMP_OK ||
|
||||||
|
+ update_multipath_status(mpp) != DMP_OK) {
|
||||||
|
remove_map(mpp, vecs, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
@@ -2087,7 +2087,7 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||||
|
/*
|
||||||
|
* Synchronize with kernel state
|
||||||
|
*/
|
||||||
|
- if (update_multipath_strings(pp->mpp, vecs->pathvec, 1)) {
|
||||||
|
+ if (update_multipath_strings(pp->mpp, vecs->pathvec, 1) != DMP_OK) {
|
||||||
|
condlog(1, "%s: Could not synchronize with kernel state",
|
||||||
|
pp->dev);
|
||||||
|
pp->dmstate = PSTATE_UNDEF;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,116 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 11 Jun 2020 15:41:18 -0500
|
||||||
|
Subject: [PATCH] multipathd: fix check_path errors with removed map
|
||||||
|
|
||||||
|
If a multipath device is removed during, or immediately before the call
|
||||||
|
to check_path(), multipathd can behave incorrectly. A missing multpath
|
||||||
|
device will cause update_multipath_strings() to fail, setting
|
||||||
|
pp->dmstate to PSTATE_UNDEF. If the path is up, this state will cause
|
||||||
|
reinstate_path() to be called, which will also fail. This will trigger
|
||||||
|
a reload, restoring the recently removed device.
|
||||||
|
|
||||||
|
If update_multipath_strings() fails because there is no multipath
|
||||||
|
device, check_path should just quit, since the remove dmevent and uevent
|
||||||
|
are likely already queued up. Also, I don't see any reason to reload the
|
||||||
|
multipath device if reinstate fails. This code was added by
|
||||||
|
fac68d7a99ef17d496079538a5c6836acd7911ab, which clamined that reinstate
|
||||||
|
could fail if the path was disabled. Looking through the current kernel
|
||||||
|
code, I can't see any reason why a reinstate would fail, where a reload
|
||||||
|
would help. If the path was missing from the multipath device,
|
||||||
|
update_multipath_strings() would already catch that, and quit
|
||||||
|
check_path() early, which make more sense to me than reloading does.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
multipathd/main.c | 44 +++++++++++++++++++-------------------------
|
||||||
|
1 file changed, 19 insertions(+), 25 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
|
index e3427d3d..1d9ce7f7 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -1611,22 +1611,18 @@ fail_path (struct path * pp, int del_active)
|
||||||
|
/*
|
||||||
|
* caller must have locked the path list before calling that function
|
||||||
|
*/
|
||||||
|
-static int
|
||||||
|
+static void
|
||||||
|
reinstate_path (struct path * pp)
|
||||||
|
{
|
||||||
|
- int ret = 0;
|
||||||
|
-
|
||||||
|
if (!pp->mpp)
|
||||||
|
- return 0;
|
||||||
|
+ return;
|
||||||
|
|
||||||
|
- if (dm_reinstate_path(pp->mpp->alias, pp->dev_t)) {
|
||||||
|
+ if (dm_reinstate_path(pp->mpp->alias, pp->dev_t))
|
||||||
|
condlog(0, "%s: reinstate failed", pp->dev_t);
|
||||||
|
- ret = 1;
|
||||||
|
- } else {
|
||||||
|
+ else {
|
||||||
|
condlog(2, "%s: reinstated", pp->dev_t);
|
||||||
|
update_queue_mode_add_path(pp->mpp);
|
||||||
|
}
|
||||||
|
- return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -2087,9 +2083,16 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||||
|
/*
|
||||||
|
* Synchronize with kernel state
|
||||||
|
*/
|
||||||
|
- if (update_multipath_strings(pp->mpp, vecs->pathvec, 1) != DMP_OK) {
|
||||||
|
- condlog(1, "%s: Could not synchronize with kernel state",
|
||||||
|
- pp->dev);
|
||||||
|
+ ret = update_multipath_strings(pp->mpp, vecs->pathvec, 1);
|
||||||
|
+ if (ret != DMP_OK) {
|
||||||
|
+ if (ret == DMP_NOT_FOUND) {
|
||||||
|
+ /* multipath device missing. Likely removed */
|
||||||
|
+ condlog(1, "%s: multipath device '%s' not found",
|
||||||
|
+ pp->dev, pp->mpp->alias);
|
||||||
|
+ return 0;
|
||||||
|
+ } else
|
||||||
|
+ condlog(1, "%s: Couldn't synchronize with kernel state",
|
||||||
|
+ pp->dev);
|
||||||
|
pp->dmstate = PSTATE_UNDEF;
|
||||||
|
}
|
||||||
|
/* if update_multipath_strings orphaned the path, quit early */
|
||||||
|
@@ -2179,12 +2182,8 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||||
|
/*
|
||||||
|
* reinstate this path
|
||||||
|
*/
|
||||||
|
- if (!disable_reinstate && reinstate_path(pp)) {
|
||||||
|
- condlog(3, "%s: reload map", pp->dev);
|
||||||
|
- ev_add_path(pp, vecs, 1);
|
||||||
|
- pp->tick = 1;
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
+ if (!disable_reinstate)
|
||||||
|
+ reinstate_path(pp);
|
||||||
|
new_path_up = 1;
|
||||||
|
|
||||||
|
if (oldchkrstate != PATH_UP && oldchkrstate != PATH_GHOST)
|
||||||
|
@@ -2200,15 +2199,10 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||||
|
else if (newstate == PATH_UP || newstate == PATH_GHOST) {
|
||||||
|
if ((pp->dmstate == PSTATE_FAILED ||
|
||||||
|
pp->dmstate == PSTATE_UNDEF) &&
|
||||||
|
- !disable_reinstate) {
|
||||||
|
+ !disable_reinstate)
|
||||||
|
/* Clear IO errors */
|
||||||
|
- if (reinstate_path(pp)) {
|
||||||
|
- condlog(3, "%s: reload map", pp->dev);
|
||||||
|
- ev_add_path(pp, vecs, 1);
|
||||||
|
- pp->tick = 1;
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
- } else {
|
||||||
|
+ reinstate_path(pp);
|
||||||
|
+ else {
|
||||||
|
LOG_MSG(4, verbosity, pp);
|
||||||
|
if (pp->checkint != max_checkint) {
|
||||||
|
/*
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,45 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 17 Jun 2020 13:31:37 -0500
|
||||||
|
Subject: [PATCH] libmultipath: make dm_flush_maps only return 0 on success
|
||||||
|
|
||||||
|
dm_flush_maps() returned both 0 and 1 on error, depending on which part
|
||||||
|
of the function it was in, but the caller was always treating 0 as a
|
||||||
|
success. Make dm_flush_maps() always return 1 on error and 0 on success.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/devmapper.c | 5 +++--
|
||||||
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||||
|
index f6204e5f..cda83ce4 100644
|
||||||
|
--- a/libmultipath/devmapper.c
|
||||||
|
+++ b/libmultipath/devmapper.c
|
||||||
|
@@ -953,13 +953,13 @@ dm_flush_map_nopaths(const char * mapname, int deferred_remove)
|
||||||
|
|
||||||
|
int dm_flush_maps (int retries)
|
||||||
|
{
|
||||||
|
- int r = 0;
|
||||||
|
+ int r = 1;
|
||||||
|
struct dm_task *dmt;
|
||||||
|
struct dm_names *names;
|
||||||
|
unsigned next = 0;
|
||||||
|
|
||||||
|
if (!(dmt = libmp_dm_task_create (DM_DEVICE_LIST)))
|
||||||
|
- return 0;
|
||||||
|
+ return r;
|
||||||
|
|
||||||
|
dm_task_no_open_count(dmt);
|
||||||
|
|
||||||
|
@@ -972,6 +972,7 @@ int dm_flush_maps (int retries)
|
||||||
|
if (!names->dev)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
+ r = 0;
|
||||||
|
do {
|
||||||
|
r |= dm_suspend_and_flush_map(names->name, retries);
|
||||||
|
next = names->next;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,160 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 15 Jun 2020 17:00:54 -0500
|
||||||
|
Subject: [PATCH] multipathd: add "del maps" multipathd command
|
||||||
|
|
||||||
|
This will flush all multipath devices.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/devmapper.c | 7 +++++--
|
||||||
|
libmultipath/devmapper.h | 2 +-
|
||||||
|
multipath/main.c | 2 +-
|
||||||
|
multipathd/cli.c | 1 +
|
||||||
|
multipathd/cli_handlers.c | 19 +++++++++++++++++++
|
||||||
|
multipathd/cli_handlers.h | 1 +
|
||||||
|
multipathd/main.c | 3 ++-
|
||||||
|
multipathd/main.h | 1 +
|
||||||
|
8 files changed, 31 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||||
|
index cda83ce4..7f98bf9d 100644
|
||||||
|
--- a/libmultipath/devmapper.c
|
||||||
|
+++ b/libmultipath/devmapper.c
|
||||||
|
@@ -951,7 +951,7 @@ dm_flush_map_nopaths(const char * mapname, int deferred_remove)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-int dm_flush_maps (int retries)
|
||||||
|
+int dm_flush_maps (int need_suspend, int retries)
|
||||||
|
{
|
||||||
|
int r = 1;
|
||||||
|
struct dm_task *dmt;
|
||||||
|
@@ -974,7 +974,10 @@ int dm_flush_maps (int retries)
|
||||||
|
|
||||||
|
r = 0;
|
||||||
|
do {
|
||||||
|
- r |= dm_suspend_and_flush_map(names->name, retries);
|
||||||
|
+ if (need_suspend)
|
||||||
|
+ r |= dm_suspend_and_flush_map(names->name, retries);
|
||||||
|
+ else
|
||||||
|
+ r |= dm_flush_map(names->name);
|
||||||
|
next = names->next;
|
||||||
|
names = (void *) names + next;
|
||||||
|
} while (next);
|
||||||
|
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
|
||||||
|
index adb55000..7e8812ad 100644
|
||||||
|
--- a/libmultipath/devmapper.h
|
||||||
|
+++ b/libmultipath/devmapper.h
|
||||||
|
@@ -55,7 +55,7 @@ int dm_flush_map_nopaths(const char * mapname, int deferred_remove);
|
||||||
|
#define dm_suspend_and_flush_map(mapname, retries) \
|
||||||
|
_dm_flush_map(mapname, 1, 0, 1, retries)
|
||||||
|
int dm_cancel_deferred_remove(struct multipath *mpp);
|
||||||
|
-int dm_flush_maps (int retries);
|
||||||
|
+int dm_flush_maps (int need_suspend, int retries);
|
||||||
|
int dm_fail_path(const char * mapname, char * path);
|
||||||
|
int dm_reinstate_path(const char * mapname, char * path);
|
||||||
|
int dm_queue_if_no_path(const char *mapname, int enable);
|
||||||
|
diff --git a/multipath/main.c b/multipath/main.c
|
||||||
|
index 78822ee1..7ab3102f 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -1127,7 +1127,7 @@ main (int argc, char *argv[])
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
else if (conf->remove == FLUSH_ALL) {
|
||||||
|
- r = dm_flush_maps(retries) ? RTVL_FAIL : RTVL_OK;
|
||||||
|
+ r = dm_flush_maps(1, retries) ? RTVL_FAIL : RTVL_OK;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
while ((r = configure(conf, cmd, dev_type, dev)) == RTVL_RETRY)
|
||||||
|
diff --git a/multipathd/cli.c b/multipathd/cli.c
|
||||||
|
index 800c0fbe..bdc9fb10 100644
|
||||||
|
--- a/multipathd/cli.c
|
||||||
|
+++ b/multipathd/cli.c
|
||||||
|
@@ -568,6 +568,7 @@ cli_init (void) {
|
||||||
|
add_handler(DEL+PATH, NULL);
|
||||||
|
add_handler(ADD+MAP, NULL);
|
||||||
|
add_handler(DEL+MAP, NULL);
|
||||||
|
+ add_handler(DEL+MAPS, NULL);
|
||||||
|
add_handler(SWITCH+MAP+GROUP, NULL);
|
||||||
|
add_handler(RECONFIGURE, NULL);
|
||||||
|
add_handler(SUSPEND+MAP, NULL);
|
||||||
|
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
|
||||||
|
index 31c3d9fd..782bb003 100644
|
||||||
|
--- a/multipathd/cli_handlers.c
|
||||||
|
+++ b/multipathd/cli_handlers.c
|
||||||
|
@@ -852,6 +852,25 @@ cli_del_map (void * v, char ** reply, int * len, void * data)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
+int
|
||||||
|
+cli_del_maps (void *v, char **reply, int *len, void *data)
|
||||||
|
+{
|
||||||
|
+ struct vectors * vecs = (struct vectors *)data;
|
||||||
|
+ struct multipath *mpp;
|
||||||
|
+ int i, ret = 0;
|
||||||
|
+
|
||||||
|
+ condlog(2, "remove maps (operator)");
|
||||||
|
+ vector_foreach_slot(vecs->mpvec, mpp, i) {
|
||||||
|
+ if (flush_map(mpp, vecs, 0))
|
||||||
|
+ ret++;
|
||||||
|
+ else
|
||||||
|
+ i--;
|
||||||
|
+ }
|
||||||
|
+ /* flush any multipath maps that aren't currently known by multipathd */
|
||||||
|
+ ret |= dm_flush_maps(0, 0);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int
|
||||||
|
cli_reload(void *v, char **reply, int *len, void *data)
|
||||||
|
{
|
||||||
|
diff --git a/multipathd/cli_handlers.h b/multipathd/cli_handlers.h
|
||||||
|
index 0f451064..6f57b429 100644
|
||||||
|
--- a/multipathd/cli_handlers.h
|
||||||
|
+++ b/multipathd/cli_handlers.h
|
||||||
|
@@ -26,6 +26,7 @@ int cli_add_path (void * v, char ** reply, int * len, void * data);
|
||||||
|
int cli_del_path (void * v, char ** reply, int * len, void * data);
|
||||||
|
int cli_add_map (void * v, char ** reply, int * len, void * data);
|
||||||
|
int cli_del_map (void * v, char ** reply, int * len, void * data);
|
||||||
|
+int cli_del_maps (void * v, char ** reply, int * len, void * data);
|
||||||
|
int cli_switch_group(void * v, char ** reply, int * len, void * data);
|
||||||
|
int cli_reconfigure(void * v, char ** reply, int * len, void * data);
|
||||||
|
int cli_resize(void * v, char ** reply, int * len, void * data);
|
||||||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
|
index 1d9ce7f7..1d0579e9 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -631,7 +631,7 @@ sync_maps_state(vector mpvec)
|
||||||
|
sync_map_state(mpp);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int
|
||||||
|
+int
|
||||||
|
flush_map(struct multipath * mpp, struct vectors * vecs, int nopaths)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
@@ -1551,6 +1551,7 @@ uxlsnrloop (void * ap)
|
||||||
|
set_handler_callback(DEL+PATH, cli_del_path);
|
||||||
|
set_handler_callback(ADD+MAP, cli_add_map);
|
||||||
|
set_handler_callback(DEL+MAP, cli_del_map);
|
||||||
|
+ set_handler_callback(DEL+MAPS, cli_del_maps);
|
||||||
|
set_handler_callback(SWITCH+MAP+GROUP, cli_switch_group);
|
||||||
|
set_unlocked_handler_callback(RECONFIGURE, cli_reconfigure);
|
||||||
|
set_handler_callback(SUSPEND+MAP, cli_suspend);
|
||||||
|
diff --git a/multipathd/main.h b/multipathd/main.h
|
||||||
|
index 7bb8463f..5dff17e5 100644
|
||||||
|
--- a/multipathd/main.h
|
||||||
|
+++ b/multipathd/main.h
|
||||||
|
@@ -28,6 +28,7 @@ int ev_add_path (struct path *, struct vectors *, int);
|
||||||
|
int ev_remove_path (struct path *, struct vectors *, int);
|
||||||
|
int ev_add_map (char *, const char *, struct vectors *);
|
||||||
|
int ev_remove_map (char *, char *, int, struct vectors *);
|
||||||
|
+int flush_map(struct multipath *, struct vectors *, int);
|
||||||
|
int set_config_state(enum daemon_status);
|
||||||
|
void * mpath_alloc_prin_response(int prin_sa);
|
||||||
|
int prin_do_scsi_ioctl(char *, int rq_servact, struct prin_resp * resp,
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,103 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 15 Jun 2020 23:54:29 -0500
|
||||||
|
Subject: [PATCH] multipath: make flushing maps work like other commands
|
||||||
|
|
||||||
|
The config structure doesn't need a special variable just for removes.
|
||||||
|
Multipath can just use the cmd variable, like it does for the other
|
||||||
|
commands.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.h | 3 ++-
|
||||||
|
libmultipath/configure.h | 3 ---
|
||||||
|
multipath/main.c | 20 ++++++++++----------
|
||||||
|
3 files changed, 12 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||||
|
index 3368d8c9..4042eba6 100644
|
||||||
|
--- a/libmultipath/config.h
|
||||||
|
+++ b/libmultipath/config.h
|
||||||
|
@@ -39,6 +39,8 @@ enum mpath_cmds {
|
||||||
|
CMD_ADD_WWID,
|
||||||
|
CMD_USABLE_PATHS,
|
||||||
|
CMD_DUMP_CONFIG,
|
||||||
|
+ CMD_FLUSH_ONE,
|
||||||
|
+ CMD_FLUSH_ALL,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum force_reload_types {
|
||||||
|
@@ -143,7 +145,6 @@ struct config {
|
||||||
|
unsigned int max_checkint;
|
||||||
|
bool use_watchdog;
|
||||||
|
int pgfailback;
|
||||||
|
- int remove;
|
||||||
|
int rr_weight;
|
||||||
|
int no_path_retry;
|
||||||
|
int user_friendly_names;
|
||||||
|
diff --git a/libmultipath/configure.h b/libmultipath/configure.h
|
||||||
|
index d7509000..0e33bf40 100644
|
||||||
|
--- a/libmultipath/configure.h
|
||||||
|
+++ b/libmultipath/configure.h
|
||||||
|
@@ -45,9 +45,6 @@ enum {
|
||||||
|
CP_RETRY,
|
||||||
|
};
|
||||||
|
|
||||||
|
-#define FLUSH_ONE 1
|
||||||
|
-#define FLUSH_ALL 2
|
||||||
|
-
|
||||||
|
struct vectors;
|
||||||
|
|
||||||
|
int setup_map (struct multipath * mpp, char * params, int params_size,
|
||||||
|
diff --git a/multipath/main.c b/multipath/main.c
|
||||||
|
index 7ab3102f..a2080029 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -942,10 +942,10 @@ main (int argc, char *argv[])
|
||||||
|
cmd = CMD_DRY_RUN;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
- conf->remove = FLUSH_ONE;
|
||||||
|
+ cmd = CMD_FLUSH_ONE;
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
- conf->remove = FLUSH_ALL;
|
||||||
|
+ cmd = CMD_FLUSH_ALL;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
if (optarg && !strncmp(optarg, "l", 1))
|
||||||
|
@@ -1084,6 +1084,10 @@ main (int argc, char *argv[])
|
||||||
|
condlog(0, "the -w option requires a device");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
+ if (cmd == CMD_FLUSH_ONE && dev_type != DEV_DEVMAP) {
|
||||||
|
+ condlog(0, "the -f option requires a map name to remove");
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
switch(delegate_to_multipathd(cmd, dev, dev_type, conf)) {
|
||||||
|
case DELEGATE_OK:
|
||||||
|
@@ -1117,16 +1121,12 @@ main (int argc, char *argv[])
|
||||||
|
}
|
||||||
|
if (retries < 0)
|
||||||
|
retries = conf->remove_retries;
|
||||||
|
- if (conf->remove == FLUSH_ONE) {
|
||||||
|
- if (dev_type == DEV_DEVMAP) {
|
||||||
|
- r = dm_suspend_and_flush_map(dev, retries) ?
|
||||||
|
- RTVL_FAIL : RTVL_OK;
|
||||||
|
- } else
|
||||||
|
- condlog(0, "must provide a map name to remove");
|
||||||
|
-
|
||||||
|
+ if (cmd == CMD_FLUSH_ONE) {
|
||||||
|
+ r = dm_suspend_and_flush_map(dev, retries) ?
|
||||||
|
+ RTVL_FAIL : RTVL_OK;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
- else if (conf->remove == FLUSH_ALL) {
|
||||||
|
+ else if (cmd == CMD_FLUSH_ALL) {
|
||||||
|
r = dm_flush_maps(1, retries) ? RTVL_FAIL : RTVL_OK;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,63 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 16 Jun 2020 16:25:34 -0500
|
||||||
|
Subject: [PATCH] multipath: delegate flushing maps to multipathd
|
||||||
|
|
||||||
|
Since there can be problems with removing maps outside of multipathd,
|
||||||
|
multipath should attempt to delegate this command to multipathd.
|
||||||
|
However, multipathd doesn't attempt to suspend the device, in order
|
||||||
|
to avoid potential hangs. If delegating to multipathd fails, multipath
|
||||||
|
should try the remove itself.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
multipath/main.c | 14 ++++++++++++++
|
||||||
|
multipath/multipath.8 | 4 ++--
|
||||||
|
2 files changed, 16 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/multipath/main.c b/multipath/main.c
|
||||||
|
index a2080029..612c6815 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -828,6 +828,20 @@ int delegate_to_multipathd(enum mpath_cmds cmd,
|
||||||
|
if (cmd == CMD_CREATE && conf->force_reload == FORCE_RELOAD_YES) {
|
||||||
|
p += snprintf(p, n, "reconfigure");
|
||||||
|
}
|
||||||
|
+ else if (cmd == CMD_FLUSH_ONE && dev && dev_type == DEV_DEVMAP) {
|
||||||
|
+ p += snprintf(p, n, "del map %s", dev);
|
||||||
|
+ /* multipathd doesn't try as hard, to avoid potentially
|
||||||
|
+ * hanging. If it fails, retry with the regular multipath
|
||||||
|
+ * command */
|
||||||
|
+ r = NOT_DELEGATED;
|
||||||
|
+ }
|
||||||
|
+ else if (cmd == CMD_FLUSH_ALL) {
|
||||||
|
+ p += snprintf(p, n, "del maps");
|
||||||
|
+ /* multipathd doesn't try as hard, to avoid potentially
|
||||||
|
+ * hanging. If it fails, retry with the regular multipath
|
||||||
|
+ * command */
|
||||||
|
+ r = NOT_DELEGATED;
|
||||||
|
+ }
|
||||||
|
/* Add other translations here */
|
||||||
|
|
||||||
|
if (strlen(command) == 0)
|
||||||
|
diff --git a/multipath/multipath.8 b/multipath/multipath.8
|
||||||
|
index 8befc45a..47a33f9b 100644
|
||||||
|
--- a/multipath/multipath.8
|
||||||
|
+++ b/multipath/multipath.8
|
||||||
|
@@ -125,11 +125,11 @@ the system.
|
||||||
|
Other operation modes are chosen by using one of the following command line switches:
|
||||||
|
.TP
|
||||||
|
.B \-f
|
||||||
|
-Flush (remove) a multipath device map specified as parameter, if unused.
|
||||||
|
+Flush (remove) a multipath device map specified as parameter, if unused. This operation is delegated to the multipathd daemon if it's running.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.B \-F
|
||||||
|
-Flush (remove) all unused multipath device maps.
|
||||||
|
+Flush (remove) all unused multipath device maps. This operation is delegated to the multipathd daemon if it's running.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.B \-l
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,62 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 16 Jun 2020 17:36:33 -0500
|
||||||
|
Subject: [PATCH] multipath: add option to skip multipathd delegation
|
||||||
|
|
||||||
|
Add the -D option to allow users to skip delegating commands to
|
||||||
|
multipathd.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.h | 1 +
|
||||||
|
multipath/main.c | 8 +++++++-
|
||||||
|
2 files changed, 8 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||||
|
index 4042eba6..160867cd 100644
|
||||||
|
--- a/libmultipath/config.h
|
||||||
|
+++ b/libmultipath/config.h
|
||||||
|
@@ -191,6 +191,7 @@ struct config {
|
||||||
|
int ghost_delay;
|
||||||
|
int find_multipaths_timeout;
|
||||||
|
int marginal_pathgroups;
|
||||||
|
+ int skip_delegate;
|
||||||
|
unsigned int version[3];
|
||||||
|
unsigned int sequence_nr;
|
||||||
|
|
||||||
|
diff --git a/multipath/main.c b/multipath/main.c
|
||||||
|
index 612c6815..3c3d2398 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -825,6 +825,9 @@ int delegate_to_multipathd(enum mpath_cmds cmd,
|
||||||
|
*p = '\0';
|
||||||
|
n = sizeof(command);
|
||||||
|
|
||||||
|
+ if (conf->skip_delegate)
|
||||||
|
+ return NOT_DELEGATED;
|
||||||
|
+
|
||||||
|
if (cmd == CMD_CREATE && conf->force_reload == FORCE_RELOAD_YES) {
|
||||||
|
p += snprintf(p, n, "reconfigure");
|
||||||
|
}
|
||||||
|
@@ -923,7 +926,7 @@ main (int argc, char *argv[])
|
||||||
|
multipath_conf = conf;
|
||||||
|
conf->retrigger_tries = 0;
|
||||||
|
conf->force_sync = 1;
|
||||||
|
- while ((arg = getopt(argc, argv, ":aAdcChl::FfM:v:p:b:BrR:itTquUwW")) != EOF ) {
|
||||||
|
+ while ((arg = getopt(argc, argv, ":aAdDcChl::FfM:v:p:b:BrR:itTquUwW")) != EOF ) {
|
||||||
|
switch(arg) {
|
||||||
|
case 1: printf("optarg : %s\n",optarg);
|
||||||
|
break;
|
||||||
|
@@ -955,6 +958,9 @@ main (int argc, char *argv[])
|
||||||
|
if (cmd == CMD_CREATE)
|
||||||
|
cmd = CMD_DRY_RUN;
|
||||||
|
break;
|
||||||
|
+ case 'D':
|
||||||
|
+ conf->skip_delegate = 1;
|
||||||
|
+ break;
|
||||||
|
case 'f':
|
||||||
|
cmd = CMD_FLUSH_ONE;
|
||||||
|
break;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,43 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 25 Jun 2020 20:46:08 -0500
|
||||||
|
Subject: [PATCH] libmultipath: fix sysfs dev_loss_tmo parsing
|
||||||
|
|
||||||
|
dev_loss_tmo is a u32 value. However the kernel sysfs code prints it as
|
||||||
|
a signed integer. This means that if dev_loss_tmo is above INT_MAX, the
|
||||||
|
sysfs value will be a negative number. Parsing this was causing
|
||||||
|
sysfs_set_rport_tmo() to fail.
|
||||||
|
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/discovery.c | 6 +++---
|
||||||
|
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
|
index ffec5162..83a41a4a 100644
|
||||||
|
--- a/libmultipath/discovery.c
|
||||||
|
+++ b/libmultipath/discovery.c
|
||||||
|
@@ -583,7 +583,7 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
|
||||||
|
struct udev_device *rport_dev = NULL;
|
||||||
|
char value[16], *eptr;
|
||||||
|
char rport_id[32];
|
||||||
|
- unsigned long long tmo = 0;
|
||||||
|
+ unsigned int tmo;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
sprintf(rport_id, "rport-%d:%d-%d",
|
||||||
|
@@ -607,8 +607,8 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
|
||||||
|
"error %d", rport_id, -ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
- tmo = strtoull(value, &eptr, 0);
|
||||||
|
- if (value == eptr || tmo == ULLONG_MAX) {
|
||||||
|
+ tmo = strtoul(value, &eptr, 0);
|
||||||
|
+ if (value == eptr) {
|
||||||
|
condlog(0, "%s: Cannot parse dev_loss_tmo "
|
||||||
|
"attribute '%s'", rport_id, value);
|
||||||
|
goto out;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,267 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Fri, 26 Jun 2020 20:06:24 -0500
|
||||||
|
Subject: [PATCH] kpartx: read devices with direct IO
|
||||||
|
|
||||||
|
If kpartx is used on top of shared storage, and a device has its
|
||||||
|
partition table changed on one machine, and then kpartx is run on
|
||||||
|
another, it may not see the new data, because the cache still contains
|
||||||
|
the old data, and there is nothing to tell the machine running kpartx to
|
||||||
|
invalidate it. To solve this, kpartx should read the devices using
|
||||||
|
direct io.
|
||||||
|
|
||||||
|
One issue with how this code has been updated is that the original code
|
||||||
|
for getblock() always read 1024 bytes. The new code reads a logical
|
||||||
|
sector size chunk of the device, and returns a pointer to the 512 byte
|
||||||
|
sector that the caller asked for, within that (possibly larger) chunk.
|
||||||
|
This means that if the logical sector size is 512, then the code is now
|
||||||
|
only reading 512 bytes. Looking through the code for the various
|
||||||
|
partition types, I can't see a case where more than 512 bytes is needed
|
||||||
|
and getblock() is used. If anyone has a reason why this code should be
|
||||||
|
reading 1024 bytes at minmum, I can certainly change this. But when I
|
||||||
|
looked, I couldn't find a case where reading 512 bytes would cause a
|
||||||
|
problem.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
kpartx/dasd.c | 7 ++++---
|
||||||
|
kpartx/gpt.c | 22 +++++++++----------
|
||||||
|
kpartx/kpartx.c | 56 +++++++++++++++++++++++++++++++++++++++----------
|
||||||
|
kpartx/kpartx.h | 2 ++
|
||||||
|
4 files changed, 61 insertions(+), 26 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/kpartx/dasd.c b/kpartx/dasd.c
|
||||||
|
index 14b9d3aa..f0398645 100644
|
||||||
|
--- a/kpartx/dasd.c
|
||||||
|
+++ b/kpartx/dasd.c
|
||||||
|
@@ -22,6 +22,7 @@
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
+#define _GNU_SOURCE
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
@@ -117,13 +118,13 @@ read_dasd_pt(int fd, __attribute__((unused)) struct slice all,
|
||||||
|
|
||||||
|
sprintf(pathname, "/dev/.kpartx-node-%u-%u",
|
||||||
|
(unsigned int)major(dev), (unsigned int)minor(dev));
|
||||||
|
- if ((fd_dasd = open(pathname, O_RDONLY)) == -1) {
|
||||||
|
+ if ((fd_dasd = open(pathname, O_RDONLY | O_DIRECT)) == -1) {
|
||||||
|
/* Devicenode does not exist. Try to create one */
|
||||||
|
if (mknod(pathname, 0600 | S_IFBLK, dev) == -1) {
|
||||||
|
/* Couldn't create a device node */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
- fd_dasd = open(pathname, O_RDONLY);
|
||||||
|
+ fd_dasd = open(pathname, O_RDONLY | O_DIRECT);
|
||||||
|
/*
|
||||||
|
* The file will vanish when the last process (we)
|
||||||
|
* has ceased to access it.
|
||||||
|
@@ -175,7 +176,7 @@ read_dasd_pt(int fd, __attribute__((unused)) struct slice all,
|
||||||
|
* Get volume label, extract name and type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
- if (!(data = (unsigned char *)malloc(blocksize)))
|
||||||
|
+ if (aligned_malloc((void **)&data, blocksize, NULL))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/kpartx/gpt.c b/kpartx/gpt.c
|
||||||
|
index 785b34ea..f7fefb70 100644
|
||||||
|
--- a/kpartx/gpt.c
|
||||||
|
+++ b/kpartx/gpt.c
|
||||||
|
@@ -243,8 +243,7 @@ alloc_read_gpt_entries(int fd, gpt_header * gpt)
|
||||||
|
|
||||||
|
if (!count) return NULL;
|
||||||
|
|
||||||
|
- pte = (gpt_entry *)malloc(count);
|
||||||
|
- if (!pte)
|
||||||
|
+ if (aligned_malloc((void **)&pte, get_sector_size(fd), &count))
|
||||||
|
return NULL;
|
||||||
|
memset(pte, 0, count);
|
||||||
|
|
||||||
|
@@ -269,12 +268,11 @@ static gpt_header *
|
||||||
|
alloc_read_gpt_header(int fd, uint64_t lba)
|
||||||
|
{
|
||||||
|
gpt_header *gpt;
|
||||||
|
- gpt = (gpt_header *)
|
||||||
|
- malloc(sizeof (gpt_header));
|
||||||
|
- if (!gpt)
|
||||||
|
+ size_t size = sizeof (gpt_header);
|
||||||
|
+ if (aligned_malloc((void **)&gpt, get_sector_size(fd), &size))
|
||||||
|
return NULL;
|
||||||
|
- memset(gpt, 0, sizeof (*gpt));
|
||||||
|
- if (!read_lba(fd, lba, gpt, sizeof (gpt_header))) {
|
||||||
|
+ memset(gpt, 0, size);
|
||||||
|
+ if (!read_lba(fd, lba, gpt, size)) {
|
||||||
|
free(gpt);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@@ -498,6 +496,7 @@ find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes)
|
||||||
|
gpt_header *pgpt = NULL, *agpt = NULL;
|
||||||
|
gpt_entry *pptes = NULL, *aptes = NULL;
|
||||||
|
legacy_mbr *legacymbr = NULL;
|
||||||
|
+ size_t size = sizeof(legacy_mbr);
|
||||||
|
uint64_t lastlba;
|
||||||
|
if (!gpt || !ptes)
|
||||||
|
return 0;
|
||||||
|
@@ -526,11 +525,10 @@ find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This will be added to the EFI Spec. per Intel after v1.02. */
|
||||||
|
- legacymbr = malloc(sizeof (*legacymbr));
|
||||||
|
- if (legacymbr) {
|
||||||
|
- memset(legacymbr, 0, sizeof (*legacymbr));
|
||||||
|
- read_lba(fd, 0, (uint8_t *) legacymbr,
|
||||||
|
- sizeof (*legacymbr));
|
||||||
|
+ if (aligned_malloc((void **)&legacymbr, get_sector_size(fd),
|
||||||
|
+ &size) == 0) {
|
||||||
|
+ memset(legacymbr, 0, size);
|
||||||
|
+ read_lba(fd, 0, (uint8_t *) legacymbr, size);
|
||||||
|
good_pmbr = is_pmbr_valid(legacymbr);
|
||||||
|
free(legacymbr);
|
||||||
|
legacymbr=NULL;
|
||||||
|
diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c
|
||||||
|
index d3620c5c..c24ad6d9 100644
|
||||||
|
--- a/kpartx/kpartx.c
|
||||||
|
+++ b/kpartx/kpartx.c
|
||||||
|
@@ -19,6 +19,7 @@
|
||||||
|
* cva, 2002-10-26
|
||||||
|
*/
|
||||||
|
|
||||||
|
+#define _GNU_SOURCE
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
@@ -41,7 +42,6 @@
|
||||||
|
|
||||||
|
#define SIZE(a) (sizeof(a)/sizeof((a)[0]))
|
||||||
|
|
||||||
|
-#define READ_SIZE 1024
|
||||||
|
#define MAXTYPES 64
|
||||||
|
#define MAXSLICES 256
|
||||||
|
#define DM_TARGET "linear"
|
||||||
|
@@ -388,7 +388,7 @@ main(int argc, char **argv){
|
||||||
|
set_delimiter(mapname, delim);
|
||||||
|
}
|
||||||
|
|
||||||
|
- fd = open(device, O_RDONLY);
|
||||||
|
+ fd = open(device, O_RDONLY | O_DIRECT);
|
||||||
|
|
||||||
|
if (fd == -1) {
|
||||||
|
perror(device);
|
||||||
|
@@ -690,9 +690,9 @@ xmalloc (size_t size) {
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
-sseek(int fd, unsigned int secnr) {
|
||||||
|
+sseek(int fd, unsigned int secnr, int secsz) {
|
||||||
|
off64_t in, out;
|
||||||
|
- in = ((off64_t) secnr << 9);
|
||||||
|
+ in = ((off64_t) secnr * secsz);
|
||||||
|
out = 1;
|
||||||
|
|
||||||
|
if ((out = lseek64(fd, in, SEEK_SET)) != in)
|
||||||
|
@@ -703,6 +703,31 @@ sseek(int fd, unsigned int secnr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+int
|
||||||
|
+aligned_malloc(void **mem_p, size_t align, size_t *size_p)
|
||||||
|
+{
|
||||||
|
+ static size_t pgsize = 0;
|
||||||
|
+ size_t size;
|
||||||
|
+ int err;
|
||||||
|
+
|
||||||
|
+ if (!mem_p || !align || (size_p && !*size_p))
|
||||||
|
+ return EINVAL;
|
||||||
|
+
|
||||||
|
+ if (!pgsize)
|
||||||
|
+ pgsize = getpagesize();
|
||||||
|
+
|
||||||
|
+ if (size_p)
|
||||||
|
+ size = ((*size_p + align - 1) / align) * align;
|
||||||
|
+ else
|
||||||
|
+ size = pgsize;
|
||||||
|
+
|
||||||
|
+ err = posix_memalign(mem_p, pgsize, size);
|
||||||
|
+ if (!err && size_p)
|
||||||
|
+ *size_p = size;
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* always in sector size blocks */
|
||||||
|
static
|
||||||
|
struct block {
|
||||||
|
unsigned int secnr;
|
||||||
|
@@ -710,30 +735,39 @@ struct block {
|
||||||
|
struct block *next;
|
||||||
|
} *blockhead;
|
||||||
|
|
||||||
|
+/* blknr is always in 512 byte blocks */
|
||||||
|
char *
|
||||||
|
-getblock (int fd, unsigned int secnr) {
|
||||||
|
+getblock (int fd, unsigned int blknr) {
|
||||||
|
+ unsigned int secsz = get_sector_size(fd);
|
||||||
|
+ unsigned int blks_per_sec = secsz / 512;
|
||||||
|
+ unsigned int secnr = blknr / blks_per_sec;
|
||||||
|
+ unsigned int blk_off = (blknr % blks_per_sec) * 512;
|
||||||
|
struct block *bp;
|
||||||
|
|
||||||
|
for (bp = blockhead; bp; bp = bp->next)
|
||||||
|
|
||||||
|
if (bp->secnr == secnr)
|
||||||
|
- return bp->block;
|
||||||
|
+ return bp->block + blk_off;
|
||||||
|
|
||||||
|
- if (sseek(fd, secnr))
|
||||||
|
+ if (sseek(fd, secnr, secsz))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
bp = xmalloc(sizeof(struct block));
|
||||||
|
bp->secnr = secnr;
|
||||||
|
bp->next = blockhead;
|
||||||
|
blockhead = bp;
|
||||||
|
- bp->block = (char *) xmalloc(READ_SIZE);
|
||||||
|
+ if (aligned_malloc((void **)&bp->block, secsz, NULL)) {
|
||||||
|
+ fprintf(stderr, "aligned_malloc failed\n");
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if (read(fd, bp->block, READ_SIZE) != READ_SIZE) {
|
||||||
|
+ if (read(fd, bp->block, secsz) != secsz) {
|
||||||
|
fprintf(stderr, "read error, sector %d\n", secnr);
|
||||||
|
- bp->block = NULL;
|
||||||
|
+ blockhead = bp->next;
|
||||||
|
+ return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return bp->block;
|
||||||
|
+ return bp->block + blk_off;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
diff --git a/kpartx/kpartx.h b/kpartx/kpartx.h
|
||||||
|
index 67edeb82..727632c1 100644
|
||||||
|
--- a/kpartx/kpartx.h
|
||||||
|
+++ b/kpartx/kpartx.h
|
||||||
|
@@ -1,6 +1,7 @@
|
||||||
|
#ifndef _KPARTX_H
|
||||||
|
#define _KPARTX_H
|
||||||
|
|
||||||
|
+#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
@@ -61,6 +62,7 @@ extern ptreader read_mac_pt;
|
||||||
|
extern ptreader read_sun_pt;
|
||||||
|
extern ptreader read_ps3_pt;
|
||||||
|
|
||||||
|
+int aligned_malloc(void **mem_p, size_t align, size_t *size_p);
|
||||||
|
char *getblock(int fd, unsigned int secnr);
|
||||||
|
|
||||||
|
static inline unsigned int
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,52 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 30 Jun 2020 10:49:59 -0500
|
||||||
|
Subject: [PATCH] kpartx: handle alternate bsd disklabel location
|
||||||
|
|
||||||
|
bsd disk labels can either be at the start of the second sector, or 64
|
||||||
|
bytes into the first sector, but kpartx only handled the first case.
|
||||||
|
However the second case is what parted creates, and what the linux
|
||||||
|
kernel partition code expects. kpartx should handle both cases.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
kpartx/bsd.c | 16 ++++++++++++++--
|
||||||
|
1 file changed, 14 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/kpartx/bsd.c b/kpartx/bsd.c
|
||||||
|
index 0e661fbc..950b0f92 100644
|
||||||
|
--- a/kpartx/bsd.c
|
||||||
|
+++ b/kpartx/bsd.c
|
||||||
|
@@ -1,6 +1,7 @@
|
||||||
|
#include "kpartx.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
+#define BSD_LABEL_OFFSET 64
|
||||||
|
#define BSD_DISKMAGIC (0x82564557UL) /* The disk magic number */
|
||||||
|
#define XBSD_MAXPARTITIONS 16
|
||||||
|
#define BSD_FS_UNUSED 0
|
||||||
|
@@ -60,8 +61,19 @@ read_bsd_pt(int fd, struct slice all, struct slice *sp, unsigned int ns) {
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
l = (struct bsd_disklabel *) bp;
|
||||||
|
- if (l->d_magic != BSD_DISKMAGIC)
|
||||||
|
- return -1;
|
||||||
|
+ if (l->d_magic != BSD_DISKMAGIC) {
|
||||||
|
+ /*
|
||||||
|
+ * BSD disklabels can also start 64 bytes offset from the
|
||||||
|
+ * start of the first sector
|
||||||
|
+ */
|
||||||
|
+ bp = getblock(fd, offset);
|
||||||
|
+ if (bp == NULL)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ l = (struct bsd_disklabel *)(bp + 64);
|
||||||
|
+ if (l->d_magic != BSD_DISKMAGIC)
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
max_partitions = 16;
|
||||||
|
if (l->d_npartitions < max_partitions)
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,61 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 30 Jun 2020 13:59:13 -0500
|
||||||
|
Subject: [PATCH] libmultipath: fix checker detection for nvme devices
|
||||||
|
|
||||||
|
In order to fix hwhandler autodetection, commit 8794a776 made
|
||||||
|
detect_alua() differentiate between failures to detect whether alua was
|
||||||
|
supported, and successfully detecting that it was not supported.
|
||||||
|
However, this causes nvme devices to get the TUR checker assigned to
|
||||||
|
them. This is because there is nothing in detect_alua() to make it only
|
||||||
|
work on scsi devices, and select_checker wasn't updated to handle
|
||||||
|
detect_alua() failing without setting pp->tpgs to TPGS_NONE.
|
||||||
|
|
||||||
|
detect_alua() should automatically set pp->tpgs to TPGS_NONE and exit on
|
||||||
|
non-scsi devices. Also, select_checker() should not assume that a
|
||||||
|
devices is ALUA, simply because if failed to detect if alua was
|
||||||
|
supported.
|
||||||
|
|
||||||
|
Fixes: 8794a776 "libmultipath: fix ALUA autodetection when paths are
|
||||||
|
down"
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/discovery.c | 6 ++++++
|
||||||
|
libmultipath/propsel.c | 4 +++-
|
||||||
|
2 files changed, 9 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
|
index 83a41a4a..aa5942c3 100644
|
||||||
|
--- a/libmultipath/discovery.c
|
||||||
|
+++ b/libmultipath/discovery.c
|
||||||
|
@@ -887,6 +887,12 @@ detect_alua(struct path * pp)
|
||||||
|
int tpgs;
|
||||||
|
unsigned int timeout;
|
||||||
|
|
||||||
|
+
|
||||||
|
+ if (pp->bus != SYSFS_BUS_SCSI) {
|
||||||
|
+ pp->tpgs = TPGS_NONE;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (sysfs_get_timeout(pp, &timeout) <= 0)
|
||||||
|
timeout = DEF_TIMEOUT;
|
||||||
|
|
||||||
|
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
||||||
|
index 897e48ca..d362beb4 100644
|
||||||
|
--- a/libmultipath/propsel.c
|
||||||
|
+++ b/libmultipath/propsel.c
|
||||||
|
@@ -521,7 +521,9 @@ int select_checker(struct config *conf, struct path *pp)
|
||||||
|
if (check_rdac(pp)) {
|
||||||
|
ckr_name = RDAC;
|
||||||
|
goto out;
|
||||||
|
- } else if (path_get_tpgs(pp) != TPGS_NONE) {
|
||||||
|
+ }
|
||||||
|
+ path_get_tpgs(pp);
|
||||||
|
+ if (pp->tpgs != TPGS_NONE && pp->tpgs != TPGS_UNDEF) {
|
||||||
|
ckr_name = TUR;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,30 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 6 Jul 2020 13:21:12 -0500
|
||||||
|
Subject: [PATCH] Makefile.inc: trim extra information from systemd version
|
||||||
|
|
||||||
|
Some systemd versions print extra information in the
|
||||||
|
"pkg-config --modversion" output, which confuses make. Trim this
|
||||||
|
off.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
Makefile.inc | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile.inc b/Makefile.inc
|
||||||
|
index c2abd301..220009e0 100644
|
||||||
|
--- a/Makefile.inc
|
||||||
|
+++ b/Makefile.inc
|
||||||
|
@@ -37,7 +37,7 @@ endif
|
||||||
|
|
||||||
|
ifndef SYSTEMD
|
||||||
|
ifeq ($(shell pkg-config --modversion libsystemd >/dev/null 2>&1 && echo 1), 1)
|
||||||
|
- SYSTEMD = $(shell pkg-config --modversion libsystemd)
|
||||||
|
+ SYSTEMD = $(shell pkg-config --modversion libsystemd | awk '{print $$1}')
|
||||||
|
else
|
||||||
|
ifeq ($(shell systemctl --version >/dev/null 2>&1 && echo 1), 1)
|
||||||
|
SYSTEMD = $(shell systemctl --version 2> /dev/null | \
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,26 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 6 Jul 2020 17:28:46 -0500
|
||||||
|
Subject: [PATCH] kpartx: fix -Wsign-compare error
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
kpartx/kpartx.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c
|
||||||
|
index c24ad6d9..653ce0c8 100644
|
||||||
|
--- a/kpartx/kpartx.c
|
||||||
|
+++ b/kpartx/kpartx.c
|
||||||
|
@@ -738,7 +738,7 @@ struct block {
|
||||||
|
/* blknr is always in 512 byte blocks */
|
||||||
|
char *
|
||||||
|
getblock (int fd, unsigned int blknr) {
|
||||||
|
- unsigned int secsz = get_sector_size(fd);
|
||||||
|
+ int secsz = get_sector_size(fd);
|
||||||
|
unsigned int blks_per_sec = secsz / 512;
|
||||||
|
unsigned int secnr = blknr / blks_per_sec;
|
||||||
|
unsigned int blk_off = (blknr % blks_per_sec) * 512;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,86 @@
|
|||||||
|
From 7159242be31dbb3f25aa67920462107bc2bc5fe0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 9 Jul 2020 18:20:18 -0500
|
||||||
|
Subject: [PATCH] libmultipath: count pending paths as active on loads
|
||||||
|
|
||||||
|
When multipath loads a table, it signals to udev if there are no active
|
||||||
|
paths. Multipath wasn't counting pending paths as active. This meant
|
||||||
|
that if all the paths were pending, udev would treat the device as not
|
||||||
|
ready, and not run kpartx on it. Even if the pending paths later
|
||||||
|
because active and were reinstated, the kernel would not send a new
|
||||||
|
uevent, because from its point of view, they were always up.
|
||||||
|
|
||||||
|
The alternative would be to continue to treat them as failed in the udev
|
||||||
|
rules, but then also tell the kernel that they were down, so that it
|
||||||
|
would trigger a uevent when they were reinstated. However, this could
|
||||||
|
lead to newly created multipath devices failing IO, simply because the
|
||||||
|
path checkers hadn't returned yet. Having udev assume that the the
|
||||||
|
device is up, like the kernel does, seems like the safer option.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/devmapper.c | 3 ++-
|
||||||
|
libmultipath/structs.c | 20 ++++++++++++++++++++
|
||||||
|
libmultipath/structs.h | 1 +
|
||||||
|
3 files changed, 23 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||||
|
index 7f98bf9d..91ff0b3d 100644
|
||||||
|
--- a/libmultipath/devmapper.c
|
||||||
|
+++ b/libmultipath/devmapper.c
|
||||||
|
@@ -408,7 +408,8 @@ static uint16_t build_udev_flags(const struct multipath *mpp, int reload)
|
||||||
|
/* DM_UDEV_DISABLE_LIBRARY_FALLBACK is added in dm_addmap */
|
||||||
|
return (mpp->skip_kpartx == SKIP_KPARTX_ON ?
|
||||||
|
MPATH_UDEV_NO_KPARTX_FLAG : 0) |
|
||||||
|
- ((count_active_paths(mpp) == 0 || mpp->ghost_delay_tick > 0) ?
|
||||||
|
+ ((count_active_pending_paths(mpp) == 0 ||
|
||||||
|
+ mpp->ghost_delay_tick > 0) ?
|
||||||
|
MPATH_UDEV_NO_PATHS_FLAG : 0) |
|
||||||
|
(reload && !mpp->force_udev_reload ?
|
||||||
|
MPATH_UDEV_RELOAD_FLAG : 0);
|
||||||
|
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
|
||||||
|
index 2dd378c4..dda9884c 100644
|
||||||
|
--- a/libmultipath/structs.c
|
||||||
|
+++ b/libmultipath/structs.c
|
||||||
|
@@ -500,6 +500,26 @@ int count_active_paths(const struct multipath *mpp)
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
+int count_active_pending_paths(const struct multipath *mpp)
|
||||||
|
+{
|
||||||
|
+ struct pathgroup *pgp;
|
||||||
|
+ struct path *pp;
|
||||||
|
+ int count = 0;
|
||||||
|
+ int i, j;
|
||||||
|
+
|
||||||
|
+ if (!mpp->pg)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ vector_foreach_slot (mpp->pg, pgp, i) {
|
||||||
|
+ vector_foreach_slot (pgp->paths, pp, j) {
|
||||||
|
+ if (pp->state == PATH_UP || pp->state == PATH_GHOST ||
|
||||||
|
+ pp->state == PATH_PENDING)
|
||||||
|
+ count++;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return count;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int pathcmp(const struct pathgroup *pgp, const struct pathgroup *cpgp)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
||||||
|
index 9bd39eb1..8e78b8c0 100644
|
||||||
|
--- a/libmultipath/structs.h
|
||||||
|
+++ b/libmultipath/structs.h
|
||||||
|
@@ -465,6 +465,7 @@ struct path * first_path (const struct multipath *mpp);
|
||||||
|
int pathcountgr (const struct pathgroup *, int);
|
||||||
|
int pathcount (const struct multipath *, int);
|
||||||
|
int count_active_paths(const struct multipath *);
|
||||||
|
+int count_active_pending_paths(const struct multipath *);
|
||||||
|
int pathcmp (const struct pathgroup *, const struct pathgroup *);
|
||||||
|
int add_feature (char **, const char *);
|
||||||
|
int remove_feature (char **, const char *);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,58 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 13 Jul 2020 15:41:15 -0500
|
||||||
|
Subject: [PATCH] multipath: deal with failures flushing maps
|
||||||
|
|
||||||
|
dm_flush_maps() was failing if there were no device-mapper devices at
|
||||||
|
all, instead of returning success, since there is nothing to do.
|
||||||
|
|
||||||
|
delegate_to_multipathd() was returning success, even if the multipathd
|
||||||
|
command failed. Also, if the command was set to fail with NOT_DELEGATED,
|
||||||
|
it shouldn't print any errors, since multipath will try to issue to
|
||||||
|
command itself.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/devmapper.c | 2 +-
|
||||||
|
multipath/main.c | 9 ++++++---
|
||||||
|
2 files changed, 7 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||||
|
index 91ff0b3d..3f70e576 100644
|
||||||
|
--- a/libmultipath/devmapper.c
|
||||||
|
+++ b/libmultipath/devmapper.c
|
||||||
|
@@ -970,10 +970,10 @@ int dm_flush_maps (int need_suspend, int retries)
|
||||||
|
if (!(names = dm_task_get_names (dmt)))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
+ r = 0;
|
||||||
|
if (!names->dev)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
- r = 0;
|
||||||
|
do {
|
||||||
|
if (need_suspend)
|
||||||
|
r |= dm_suspend_and_flush_map(names->name, retries);
|
||||||
|
diff --git a/multipath/main.c b/multipath/main.c
|
||||||
|
index 3c3d2398..607cada2 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -869,9 +869,12 @@ int delegate_to_multipathd(enum mpath_cmds cmd,
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (reply != NULL && *reply != '\0' && strcmp(reply, "ok\n"))
|
||||||
|
- printf("%s", reply);
|
||||||
|
- r = DELEGATE_OK;
|
||||||
|
+ if (reply != NULL && *reply != '\0') {
|
||||||
|
+ if (strcmp(reply, "fail\n"))
|
||||||
|
+ r = DELEGATE_OK;
|
||||||
|
+ if (r != NOT_DELEGATED && strcmp(reply, "ok\n"))
|
||||||
|
+ printf("%s", reply);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
out:
|
||||||
|
FREE(reply);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,54 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 3 Nov 2020 14:27:58 -0600
|
||||||
|
Subject: [PATCH] libmultipath: factor out code to get vpd page data
|
||||||
|
|
||||||
|
A future patch will reuse the code to get the vpd page data, so factor
|
||||||
|
it out from get_vpd_sgio().
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/discovery.c | 19 +++++++++++++++----
|
||||||
|
1 file changed, 15 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
|
index aa5942c3..eb1e735d 100644
|
||||||
|
--- a/libmultipath/discovery.c
|
||||||
|
+++ b/libmultipath/discovery.c
|
||||||
|
@@ -1239,11 +1239,10 @@ get_vpd_sysfs (struct udev_device *parent, int pg, char * str, int maxlen)
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int
|
||||||
|
-get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen)
|
||||||
|
+static int
|
||||||
|
+fetch_vpd_page(int fd, int pg, unsigned char *buff)
|
||||||
|
{
|
||||||
|
- int len, buff_len;
|
||||||
|
- unsigned char buff[4096];
|
||||||
|
+ int buff_len;
|
||||||
|
|
||||||
|
memset(buff, 0x0, 4096);
|
||||||
|
if (sgio_get_vpd(buff, 4096, fd, pg) < 0) {
|
||||||
|
@@ -1264,6 +1263,18 @@ get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen)
|
||||||
|
condlog(3, "vpd pg%02x page truncated", pg);
|
||||||
|
buff_len = 4096;
|
||||||
|
}
|
||||||
|
+ return buff_len;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen)
|
||||||
|
+{
|
||||||
|
+ int len, buff_len;
|
||||||
|
+ unsigned char buff[4096];
|
||||||
|
+
|
||||||
|
+ buff_len = fetch_vpd_page(fd, pg, buff);
|
||||||
|
+ if (buff_len < 0)
|
||||||
|
+ return buff_len;
|
||||||
|
if (pg == 0x80)
|
||||||
|
len = parse_vpd_pg80(buff, str, maxlen);
|
||||||
|
else if (pg == 0x83)
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,98 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 7 Oct 2020 21:43:02 -0500
|
||||||
|
Subject: [PATCH] libmultipath: limit reading 0xc9 vpd page
|
||||||
|
|
||||||
|
Only rdac arrays support 0xC9 vpd page inquiries. All other arrays will
|
||||||
|
return a failure. Only do the rdac inquiry when detecting array
|
||||||
|
capabilities if the array's path checker is explicitly set to rdac, or
|
||||||
|
the path checker is not set, and the array reports that it supports vpd
|
||||||
|
page 0xC9 in the Supported VPD Pages (0x00) vpd page.
|
||||||
|
|
||||||
|
Multipath was doing the check if either the path checker was set to
|
||||||
|
rdac, or no path checker was set. This means that for almost all
|
||||||
|
non-rdac arrays, multipath was issuing a bad inquiry. This was annoying
|
||||||
|
users.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/discovery.c | 25 +++++++++++++++++++++++++
|
||||||
|
libmultipath/discovery.h | 1 +
|
||||||
|
libmultipath/propsel.c | 10 ++++++----
|
||||||
|
3 files changed, 32 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
|
index eb1e735d..01aadba9 100644
|
||||||
|
--- a/libmultipath/discovery.c
|
||||||
|
+++ b/libmultipath/discovery.c
|
||||||
|
@@ -1266,6 +1266,31 @@ fetch_vpd_page(int fd, int pg, unsigned char *buff)
|
||||||
|
return buff_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* heavily based on sg_inq.c from sg3_utils */
|
||||||
|
+bool
|
||||||
|
+is_vpd_page_supported(int fd, int pg)
|
||||||
|
+{
|
||||||
|
+ int i, len, buff_len;
|
||||||
|
+ unsigned char buff[4096];
|
||||||
|
+
|
||||||
|
+ buff_len = fetch_vpd_page(fd, 0x00, buff);
|
||||||
|
+ if (buff_len < 0)
|
||||||
|
+ return false;
|
||||||
|
+ if (buff_len < 4) {
|
||||||
|
+ condlog(3, "VPD page 00h too short");
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ len = buff[3] + 4;
|
||||||
|
+ if (len > buff_len)
|
||||||
|
+ condlog(3, "vpd page 00h trucated, expected %d, have %d",
|
||||||
|
+ len, buff_len);
|
||||||
|
+ for (i = 4; i < len; ++i)
|
||||||
|
+ if (buff[i] == pg)
|
||||||
|
+ return true;
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int
|
||||||
|
get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen)
|
||||||
|
{
|
||||||
|
diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h
|
||||||
|
index 6444887d..d3193daf 100644
|
||||||
|
--- a/libmultipath/discovery.h
|
||||||
|
+++ b/libmultipath/discovery.h
|
||||||
|
@@ -56,6 +56,7 @@ int sysfs_get_asymmetric_access_state(struct path *pp,
|
||||||
|
char *buff, int buflen);
|
||||||
|
int get_uid(struct path * pp, int path_state, struct udev_device *udev,
|
||||||
|
int allow_fallback);
|
||||||
|
+bool is_vpd_page_supported(int fd, int pg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* discovery bitmask
|
||||||
|
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
||||||
|
index d362beb4..d7febec6 100644
|
||||||
|
--- a/libmultipath/propsel.c
|
||||||
|
+++ b/libmultipath/propsel.c
|
||||||
|
@@ -496,13 +496,15 @@ check_rdac(struct path * pp)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
char buff[44];
|
||||||
|
- const char *checker_name;
|
||||||
|
+ const char *checker_name = NULL;
|
||||||
|
|
||||||
|
if (pp->bus != SYSFS_BUS_SCSI)
|
||||||
|
return 0;
|
||||||
|
- /* Avoid ioctl if this is likely not an RDAC array */
|
||||||
|
- if (__do_set_from_hwe(checker_name, pp, checker_name) &&
|
||||||
|
- strcmp(checker_name, RDAC))
|
||||||
|
+ /* Avoid checking 0xc9 if this is likely not an RDAC array */
|
||||||
|
+ if (!__do_set_from_hwe(checker_name, pp, checker_name) &&
|
||||||
|
+ !is_vpd_page_supported(pp->fd, 0xC9))
|
||||||
|
+ return 0;
|
||||||
|
+ if (checker_name && strcmp(checker_name, RDAC))
|
||||||
|
return 0;
|
||||||
|
len = get_vpd_sgio(pp->fd, 0xC9, 0, buff, 44);
|
||||||
|
if (len <= 0)
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,44 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Steve Schremmer <steve.schremmer@netapp.com>
|
||||||
|
Date: Mon, 6 Jul 2020 20:22:35 +0000
|
||||||
|
Subject: [PATCH] libmultipath: add device to hwtable.c
|
||||||
|
|
||||||
|
Add FUJITSU ETERNUS_AHB defaults.
|
||||||
|
|
||||||
|
Signed-off-by: Steve Schremmer <steve.schremmer@netapp.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/hwtable.c | 16 ++++++++++++++++
|
||||||
|
1 file changed, 16 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
|
||||||
|
index d1fcfdb3..d680bdfc 100644
|
||||||
|
--- a/libmultipath/hwtable.c
|
||||||
|
+++ b/libmultipath/hwtable.c
|
||||||
|
@@ -428,6 +428,22 @@ static struct hwentry default_hw[] = {
|
||||||
|
.pgpolicy = MULTIBUS,
|
||||||
|
.no_path_retry = 10,
|
||||||
|
},
|
||||||
|
+ {
|
||||||
|
+ /*
|
||||||
|
+ * ETERNUS AB/HB
|
||||||
|
+ * Maintainer: NetApp RDAC team <ng-eseries-upstream-maintainers@netapp.com>
|
||||||
|
+ */
|
||||||
|
+ .vendor = "FUJITSU",
|
||||||
|
+ .product = "ETERNUS_AHB",
|
||||||
|
+ .bl_product = "Universal Xport",
|
||||||
|
+ .pgpolicy = GROUP_BY_PRIO,
|
||||||
|
+ .checker_name = RDAC,
|
||||||
|
+ .features = "2 pg_init_retries 50",
|
||||||
|
+ .hwhandler = "1 rdac",
|
||||||
|
+ .prio_name = PRIO_RDAC,
|
||||||
|
+ .pgfailback = -FAILBACK_IMMEDIATE,
|
||||||
|
+ .no_path_retry = 30,
|
||||||
|
+ },
|
||||||
|
/*
|
||||||
|
* Hitachi Vantara
|
||||||
|
*
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,159 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 12 Oct 2020 16:06:11 -0500
|
||||||
|
Subject: [PATCH] libmultipath: move fast_io_fail defines to structs.h
|
||||||
|
|
||||||
|
Since fast_io_fail is part of the multipath struct, its symbolic values
|
||||||
|
belong in structs.h. Also, make it an instance of a general enum, which
|
||||||
|
will be used again in future patches, and change the set/print functions
|
||||||
|
which use it to use the general enum instead.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.h | 8 --------
|
||||||
|
libmultipath/dict.c | 30 +++++++++++++++---------------
|
||||||
|
libmultipath/dict.h | 2 +-
|
||||||
|
libmultipath/propsel.c | 2 +-
|
||||||
|
libmultipath/structs.h | 17 +++++++++++++++++
|
||||||
|
5 files changed, 34 insertions(+), 25 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||||
|
index 160867cd..f38c7639 100644
|
||||||
|
--- a/libmultipath/config.h
|
||||||
|
+++ b/libmultipath/config.h
|
||||||
|
@@ -11,14 +11,6 @@
|
||||||
|
#define ORIGIN_CONFIG 1
|
||||||
|
#define ORIGIN_NO_CONFIG 2
|
||||||
|
|
||||||
|
-/*
|
||||||
|
- * In kernel, fast_io_fail == 0 means immediate failure on rport delete.
|
||||||
|
- * OTOH '0' means not-configured in various places in multipath-tools.
|
||||||
|
- */
|
||||||
|
-#define MP_FAST_IO_FAIL_UNSET (0)
|
||||||
|
-#define MP_FAST_IO_FAIL_OFF (-1)
|
||||||
|
-#define MP_FAST_IO_FAIL_ZERO (-2)
|
||||||
|
-
|
||||||
|
enum devtypes {
|
||||||
|
DEV_NONE,
|
||||||
|
DEV_DEVT,
|
||||||
|
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||||
|
index 184d4b22..ce8e1cda 100644
|
||||||
|
--- a/libmultipath/dict.c
|
||||||
|
+++ b/libmultipath/dict.c
|
||||||
|
@@ -834,7 +834,7 @@ declare_mp_attr_handler(gid, set_gid)
|
||||||
|
declare_mp_attr_snprint(gid, print_gid)
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_fast_io_fail(vector strvec, void *ptr)
|
||||||
|
+set_undef_off_zero(vector strvec, void *ptr)
|
||||||
|
{
|
||||||
|
char * buff;
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
@@ -844,36 +844,36 @@ set_fast_io_fail(vector strvec, void *ptr)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (strcmp(buff, "off") == 0)
|
||||||
|
- *int_ptr = MP_FAST_IO_FAIL_OFF;
|
||||||
|
+ *int_ptr = UOZ_OFF;
|
||||||
|
else if (sscanf(buff, "%d", int_ptr) != 1 ||
|
||||||
|
- *int_ptr < MP_FAST_IO_FAIL_ZERO)
|
||||||
|
- *int_ptr = MP_FAST_IO_FAIL_UNSET;
|
||||||
|
+ *int_ptr < UOZ_ZERO)
|
||||||
|
+ *int_ptr = UOZ_UNDEF;
|
||||||
|
else if (*int_ptr == 0)
|
||||||
|
- *int_ptr = MP_FAST_IO_FAIL_ZERO;
|
||||||
|
+ *int_ptr = UOZ_ZERO;
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-print_fast_io_fail(char * buff, int len, long v)
|
||||||
|
+print_undef_off_zero(char * buff, int len, long v)
|
||||||
|
{
|
||||||
|
- if (v == MP_FAST_IO_FAIL_UNSET)
|
||||||
|
+ if (v == UOZ_UNDEF)
|
||||||
|
return 0;
|
||||||
|
- if (v == MP_FAST_IO_FAIL_OFF)
|
||||||
|
+ if (v == UOZ_OFF)
|
||||||
|
return snprintf(buff, len, "\"off\"");
|
||||||
|
- if (v == MP_FAST_IO_FAIL_ZERO)
|
||||||
|
+ if (v == UOZ_ZERO)
|
||||||
|
return snprintf(buff, len, "0");
|
||||||
|
return snprintf(buff, len, "%ld", v);
|
||||||
|
}
|
||||||
|
|
||||||
|
-declare_def_handler(fast_io_fail, set_fast_io_fail)
|
||||||
|
-declare_def_snprint_defint(fast_io_fail, print_fast_io_fail,
|
||||||
|
+declare_def_handler(fast_io_fail, set_undef_off_zero)
|
||||||
|
+declare_def_snprint_defint(fast_io_fail, print_undef_off_zero,
|
||||||
|
DEFAULT_FAST_IO_FAIL)
|
||||||
|
-declare_ovr_handler(fast_io_fail, set_fast_io_fail)
|
||||||
|
-declare_ovr_snprint(fast_io_fail, print_fast_io_fail)
|
||||||
|
-declare_hw_handler(fast_io_fail, set_fast_io_fail)
|
||||||
|
-declare_hw_snprint(fast_io_fail, print_fast_io_fail)
|
||||||
|
+declare_ovr_handler(fast_io_fail, set_undef_off_zero)
|
||||||
|
+declare_ovr_snprint(fast_io_fail, print_undef_off_zero)
|
||||||
|
+declare_hw_handler(fast_io_fail, set_undef_off_zero)
|
||||||
|
+declare_hw_snprint(fast_io_fail, print_undef_off_zero)
|
||||||
|
|
||||||
|
static int
|
||||||
|
set_dev_loss(vector strvec, void *ptr)
|
||||||
|
diff --git a/libmultipath/dict.h b/libmultipath/dict.h
|
||||||
|
index a40ac66f..a917e1ca 100644
|
||||||
|
--- a/libmultipath/dict.h
|
||||||
|
+++ b/libmultipath/dict.h
|
||||||
|
@@ -13,7 +13,7 @@ int print_rr_weight(char *buff, int len, long v);
|
||||||
|
int print_pgfailback(char *buff, int len, long v);
|
||||||
|
int print_pgpolicy(char *buff, int len, long v);
|
||||||
|
int print_no_path_retry(char *buff, int len, long v);
|
||||||
|
-int print_fast_io_fail(char *buff, int len, long v);
|
||||||
|
+int print_undef_off_zero(char *buff, int len, long v);
|
||||||
|
int print_dev_loss(char *buff, int len, unsigned long v);
|
||||||
|
int print_reservation_key(char * buff, int len, struct be64 key, uint8_t
|
||||||
|
flags, int source);
|
||||||
|
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
||||||
|
index d7febec6..725db2b1 100644
|
||||||
|
--- a/libmultipath/propsel.c
|
||||||
|
+++ b/libmultipath/propsel.c
|
||||||
|
@@ -755,7 +755,7 @@ int select_fast_io_fail(struct config *conf, struct multipath *mp)
|
||||||
|
mp_set_conf(fast_io_fail);
|
||||||
|
mp_set_default(fast_io_fail, DEFAULT_FAST_IO_FAIL);
|
||||||
|
out:
|
||||||
|
- print_fast_io_fail(buff, 12, mp->fast_io_fail);
|
||||||
|
+ print_undef_off_zero(buff, 12, mp->fast_io_fail);
|
||||||
|
condlog(3, "%s: fast_io_fail_tmo = %s %s", mp->alias, buff, origin);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
||||||
|
index 8e78b8c0..29209984 100644
|
||||||
|
--- a/libmultipath/structs.h
|
||||||
|
+++ b/libmultipath/structs.h
|
||||||
|
@@ -229,6 +229,23 @@ enum vpd_vendor_ids {
|
||||||
|
VPD_VP_ARRAY_SIZE, /* This must remain the last entry */
|
||||||
|
};
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Multipath treats 0 as undefined for optional config parameters.
|
||||||
|
+ * Use this for cases where 0 is a valid option for systems multipath
|
||||||
|
+ * is communicating with
|
||||||
|
+ */
|
||||||
|
+enum undefined_off_zero {
|
||||||
|
+ UOZ_UNDEF = 0,
|
||||||
|
+ UOZ_OFF = -1,
|
||||||
|
+ UOZ_ZERO = -2,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+enum fast_io_fail_states {
|
||||||
|
+ MP_FAST_IO_FAIL_UNSET = UOZ_UNDEF,
|
||||||
|
+ MP_FAST_IO_FAIL_OFF = UOZ_OFF,
|
||||||
|
+ MP_FAST_IO_FAIL_ZERO = UOZ_ZERO,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
struct vpd_vendor_page {
|
||||||
|
int pg;
|
||||||
|
const char *name;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,295 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 14 Oct 2020 18:38:20 -0500
|
||||||
|
Subject: [PATCH] libmultipath: add eh_deadline multipath.conf parameter
|
||||||
|
|
||||||
|
There are times a fc rport is never lost, meaning that fast_io_fail_tmo
|
||||||
|
and dev_loss_tmo never trigger, but scsi commands still hang. This can
|
||||||
|
cause problems in cases where users have string timing requirements, and
|
||||||
|
the easiest way to solve these issues is to set eh_deadline. Since it's
|
||||||
|
already possible to set fast_io_fail_tmo and dev_loss_tmo from
|
||||||
|
multipath.conf, and have multipath take care of setting it correctly for
|
||||||
|
the scsi devices in sysfs, it makes sense to allow users to set
|
||||||
|
eh_deadline here as well.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.c | 2 ++
|
||||||
|
libmultipath/config.h | 2 ++
|
||||||
|
libmultipath/configure.c | 1 +
|
||||||
|
libmultipath/dict.c | 10 +++++++
|
||||||
|
libmultipath/discovery.c | 58 +++++++++++++++++++++++++++++++++-----
|
||||||
|
libmultipath/propsel.c | 17 +++++++++++
|
||||||
|
libmultipath/propsel.h | 1 +
|
||||||
|
libmultipath/structs.h | 7 +++++
|
||||||
|
multipath/multipath.conf.5 | 16 +++++++++++
|
||||||
|
9 files changed, 107 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||||
|
index 26f8e050..a71db2d0 100644
|
||||||
|
--- a/libmultipath/config.c
|
||||||
|
+++ b/libmultipath/config.c
|
||||||
|
@@ -359,6 +359,7 @@ merge_hwe (struct hwentry * dst, struct hwentry * src)
|
||||||
|
merge_num(flush_on_last_del);
|
||||||
|
merge_num(fast_io_fail);
|
||||||
|
merge_num(dev_loss);
|
||||||
|
+ merge_num(eh_deadline);
|
||||||
|
merge_num(user_friendly_names);
|
||||||
|
merge_num(retain_hwhandler);
|
||||||
|
merge_num(detect_prio);
|
||||||
|
@@ -514,6 +515,7 @@ store_hwe (vector hwtable, struct hwentry * dhwe)
|
||||||
|
hwe->flush_on_last_del = dhwe->flush_on_last_del;
|
||||||
|
hwe->fast_io_fail = dhwe->fast_io_fail;
|
||||||
|
hwe->dev_loss = dhwe->dev_loss;
|
||||||
|
+ hwe->eh_deadline = dhwe->eh_deadline;
|
||||||
|
hwe->user_friendly_names = dhwe->user_friendly_names;
|
||||||
|
hwe->retain_hwhandler = dhwe->retain_hwhandler;
|
||||||
|
hwe->detect_prio = dhwe->detect_prio;
|
||||||
|
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||||
|
index f38c7639..a22c1b4e 100644
|
||||||
|
--- a/libmultipath/config.h
|
||||||
|
+++ b/libmultipath/config.h
|
||||||
|
@@ -64,6 +64,7 @@ struct hwentry {
|
||||||
|
int flush_on_last_del;
|
||||||
|
int fast_io_fail;
|
||||||
|
unsigned int dev_loss;
|
||||||
|
+ int eh_deadline;
|
||||||
|
int user_friendly_names;
|
||||||
|
int retain_hwhandler;
|
||||||
|
int detect_prio;
|
||||||
|
@@ -149,6 +150,7 @@ struct config {
|
||||||
|
int attribute_flags;
|
||||||
|
int fast_io_fail;
|
||||||
|
unsigned int dev_loss;
|
||||||
|
+ int eh_deadline;
|
||||||
|
int log_checker_err;
|
||||||
|
int allow_queueing;
|
||||||
|
int find_multipaths;
|
||||||
|
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
||||||
|
index 96c79610..b7113291 100644
|
||||||
|
--- a/libmultipath/configure.c
|
||||||
|
+++ b/libmultipath/configure.c
|
||||||
|
@@ -340,6 +340,7 @@ int setup_map(struct multipath *mpp, char *params, int params_size,
|
||||||
|
select_gid(conf, mpp);
|
||||||
|
select_fast_io_fail(conf, mpp);
|
||||||
|
select_dev_loss(conf, mpp);
|
||||||
|
+ select_eh_deadline(conf, mpp);
|
||||||
|
select_reservation_key(conf, mpp);
|
||||||
|
select_deferred_remove(conf, mpp);
|
||||||
|
select_marginal_path_err_sample_time(conf, mpp);
|
||||||
|
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||||
|
index ce8e1cda..8fd91d8c 100644
|
||||||
|
--- a/libmultipath/dict.c
|
||||||
|
+++ b/libmultipath/dict.c
|
||||||
|
@@ -911,6 +911,13 @@ declare_ovr_snprint(dev_loss, print_dev_loss)
|
||||||
|
declare_hw_handler(dev_loss, set_dev_loss)
|
||||||
|
declare_hw_snprint(dev_loss, print_dev_loss)
|
||||||
|
|
||||||
|
+declare_def_handler(eh_deadline, set_undef_off_zero)
|
||||||
|
+declare_def_snprint(eh_deadline, print_undef_off_zero)
|
||||||
|
+declare_ovr_handler(eh_deadline, set_undef_off_zero)
|
||||||
|
+declare_ovr_snprint(eh_deadline, print_undef_off_zero)
|
||||||
|
+declare_hw_handler(eh_deadline, set_undef_off_zero)
|
||||||
|
+declare_hw_snprint(eh_deadline, print_undef_off_zero)
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
set_pgpolicy(vector strvec, void *ptr)
|
||||||
|
{
|
||||||
|
@@ -1776,6 +1783,7 @@ init_keywords(vector keywords)
|
||||||
|
install_keyword("gid", &def_gid_handler, &snprint_def_gid);
|
||||||
|
install_keyword("fast_io_fail_tmo", &def_fast_io_fail_handler, &snprint_def_fast_io_fail);
|
||||||
|
install_keyword("dev_loss_tmo", &def_dev_loss_handler, &snprint_def_dev_loss);
|
||||||
|
+ install_keyword("eh_deadline", &def_eh_deadline_handler, &snprint_def_eh_deadline);
|
||||||
|
install_keyword("bindings_file", &def_bindings_file_handler, &snprint_def_bindings_file);
|
||||||
|
install_keyword("wwids_file", &def_wwids_file_handler, &snprint_def_wwids_file);
|
||||||
|
install_keyword("prkeys_file", &def_prkeys_file_handler, &snprint_def_prkeys_file);
|
||||||
|
@@ -1885,6 +1893,7 @@ init_keywords(vector keywords)
|
||||||
|
install_keyword("flush_on_last_del", &hw_flush_on_last_del_handler, &snprint_hw_flush_on_last_del);
|
||||||
|
install_keyword("fast_io_fail_tmo", &hw_fast_io_fail_handler, &snprint_hw_fast_io_fail);
|
||||||
|
install_keyword("dev_loss_tmo", &hw_dev_loss_handler, &snprint_hw_dev_loss);
|
||||||
|
+ install_keyword("eh_deadline", &hw_eh_deadline_handler, &snprint_hw_eh_deadline);
|
||||||
|
install_keyword("user_friendly_names", &hw_user_friendly_names_handler, &snprint_hw_user_friendly_names);
|
||||||
|
install_keyword("retain_attached_hw_handler", &hw_retain_hwhandler_handler, &snprint_hw_retain_hwhandler);
|
||||||
|
install_keyword("detect_prio", &hw_detect_prio_handler, &snprint_hw_detect_prio);
|
||||||
|
@@ -1925,6 +1934,7 @@ init_keywords(vector keywords)
|
||||||
|
install_keyword("flush_on_last_del", &ovr_flush_on_last_del_handler, &snprint_ovr_flush_on_last_del);
|
||||||
|
install_keyword("fast_io_fail_tmo", &ovr_fast_io_fail_handler, &snprint_ovr_fast_io_fail);
|
||||||
|
install_keyword("dev_loss_tmo", &ovr_dev_loss_handler, &snprint_ovr_dev_loss);
|
||||||
|
+ install_keyword("eh_deadline", &ovr_eh_deadline_handler, &snprint_ovr_eh_deadline);
|
||||||
|
install_keyword("user_friendly_names", &ovr_user_friendly_names_handler, &snprint_ovr_user_friendly_names);
|
||||||
|
install_keyword("retain_attached_hw_handler", &ovr_retain_hwhandler_handler, &snprint_ovr_retain_hwhandler);
|
||||||
|
install_keyword("detect_prio", &ovr_detect_prio_handler, &snprint_ovr_detect_prio);
|
||||||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
|
index 01aadba9..a328aafa 100644
|
||||||
|
--- a/libmultipath/discovery.c
|
||||||
|
+++ b/libmultipath/discovery.c
|
||||||
|
@@ -577,6 +577,42 @@ sysfs_get_asymmetric_access_state(struct path *pp, char *buff, int buflen)
|
||||||
|
return !!preferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+sysfs_set_eh_deadline(struct multipath *mpp, struct path *pp)
|
||||||
|
+{
|
||||||
|
+ struct udev_device *hostdev;
|
||||||
|
+ char host_name[HOST_NAME_LEN], value[16];
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ if (mpp->eh_deadline == EH_DEADLINE_UNSET)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ sprintf(host_name, "host%d", pp->sg_id.host_no);
|
||||||
|
+ hostdev = udev_device_new_from_subsystem_sysname(udev,
|
||||||
|
+ "scsi_host", host_name);
|
||||||
|
+ if (!hostdev)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ if (mpp->eh_deadline == EH_DEADLINE_OFF)
|
||||||
|
+ sprintf(value, "off");
|
||||||
|
+ else if (mpp->eh_deadline == EH_DEADLINE_ZERO)
|
||||||
|
+ sprintf(value, "0");
|
||||||
|
+ else
|
||||||
|
+ snprintf(value, 16, "%u", mpp->eh_deadline);
|
||||||
|
+
|
||||||
|
+ ret = sysfs_attr_set_value(hostdev, "eh_deadline",
|
||||||
|
+ value, strlen(value));
|
||||||
|
+ /*
|
||||||
|
+ * not all scsi drivers support setting eh_deadline, so failing
|
||||||
|
+ * is totally reasonable
|
||||||
|
+ */
|
||||||
|
+ if (ret <= 0)
|
||||||
|
+ condlog(4, "%s: failed to set eh_deadline to %s, error %d", udev_device_get_sysname(hostdev), value, -ret);
|
||||||
|
+
|
||||||
|
+ udev_device_unref(hostdev);
|
||||||
|
+ return (ret <= 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
|
||||||
|
{
|
||||||
|
@@ -787,16 +823,24 @@ sysfs_set_scsi_tmo (struct multipath *mpp, unsigned int checkint)
|
||||||
|
mpp->alias, mpp->fast_io_fail);
|
||||||
|
mpp->fast_io_fail = MP_FAST_IO_FAIL_OFF;
|
||||||
|
}
|
||||||
|
- if (!mpp->dev_loss && mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)
|
||||||
|
+ if (!mpp->dev_loss && mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET &&
|
||||||
|
+ mpp->eh_deadline == EH_DEADLINE_UNSET)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
vector_foreach_slot(mpp->paths, pp, i) {
|
||||||
|
- if (pp->sg_id.proto_id == SCSI_PROTOCOL_FCP)
|
||||||
|
- sysfs_set_rport_tmo(mpp, pp);
|
||||||
|
- if (pp->sg_id.proto_id == SCSI_PROTOCOL_ISCSI)
|
||||||
|
- sysfs_set_session_tmo(mpp, pp);
|
||||||
|
- if (pp->sg_id.proto_id == SCSI_PROTOCOL_SAS)
|
||||||
|
- sysfs_set_nexus_loss_tmo(mpp, pp);
|
||||||
|
+ if (pp->bus != SYSFS_BUS_SCSI)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ if (mpp->dev_loss ||
|
||||||
|
+ mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
|
||||||
|
+ if (pp->sg_id.proto_id == SCSI_PROTOCOL_FCP)
|
||||||
|
+ sysfs_set_rport_tmo(mpp, pp);
|
||||||
|
+ else if (pp->sg_id.proto_id == SCSI_PROTOCOL_ISCSI)
|
||||||
|
+ sysfs_set_session_tmo(mpp, pp);
|
||||||
|
+ else if (pp->sg_id.proto_id == SCSI_PROTOCOL_SAS)
|
||||||
|
+ sysfs_set_nexus_loss_tmo(mpp, pp);
|
||||||
|
+ }
|
||||||
|
+ sysfs_set_eh_deadline(mpp, pp);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
||||||
|
index 725db2b1..1150cfe8 100644
|
||||||
|
--- a/libmultipath/propsel.c
|
||||||
|
+++ b/libmultipath/propsel.c
|
||||||
|
@@ -776,6 +776,23 @@ out:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+int select_eh_deadline(struct config *conf, struct multipath *mp)
|
||||||
|
+{
|
||||||
|
+ const char *origin;
|
||||||
|
+ char buff[12];
|
||||||
|
+
|
||||||
|
+ mp_set_ovr(eh_deadline);
|
||||||
|
+ mp_set_hwe(eh_deadline);
|
||||||
|
+ mp_set_conf(eh_deadline);
|
||||||
|
+ mp->eh_deadline = EH_DEADLINE_UNSET;
|
||||||
|
+ /* not changing sysfs in default cause, so don't print anything */
|
||||||
|
+ return 0;
|
||||||
|
+out:
|
||||||
|
+ print_undef_off_zero(buff, 12, mp->eh_deadline);
|
||||||
|
+ condlog(3, "%s: eh_deadline = %s %s", mp->alias, buff, origin);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int select_flush_on_last_del(struct config *conf, struct multipath *mp)
|
||||||
|
{
|
||||||
|
const char *origin;
|
||||||
|
diff --git a/libmultipath/propsel.h b/libmultipath/propsel.h
|
||||||
|
index 3d6edd8a..a68bacf0 100644
|
||||||
|
--- a/libmultipath/propsel.h
|
||||||
|
+++ b/libmultipath/propsel.h
|
||||||
|
@@ -17,6 +17,7 @@ int select_uid(struct config *conf, struct multipath *mp);
|
||||||
|
int select_gid(struct config *conf, struct multipath *mp);
|
||||||
|
int select_fast_io_fail(struct config *conf, struct multipath *mp);
|
||||||
|
int select_dev_loss(struct config *conf, struct multipath *mp);
|
||||||
|
+int select_eh_deadline(struct config *conf, struct multipath *mp);
|
||||||
|
int select_reservation_key(struct config *conf, struct multipath *mp);
|
||||||
|
int select_retain_hwhandler (struct config *conf, struct multipath * mp);
|
||||||
|
int select_detect_prio(struct config *conf, struct path * pp);
|
||||||
|
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
||||||
|
index 29209984..65542dea 100644
|
||||||
|
--- a/libmultipath/structs.h
|
||||||
|
+++ b/libmultipath/structs.h
|
||||||
|
@@ -246,6 +246,12 @@ enum fast_io_fail_states {
|
||||||
|
MP_FAST_IO_FAIL_ZERO = UOZ_ZERO,
|
||||||
|
};
|
||||||
|
|
||||||
|
+enum eh_deadline_states {
|
||||||
|
+ EH_DEADLINE_UNSET = UOZ_UNDEF,
|
||||||
|
+ EH_DEADLINE_OFF = UOZ_OFF,
|
||||||
|
+ EH_DEADLINE_ZERO = UOZ_ZERO,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
struct vpd_vendor_page {
|
||||||
|
int pg;
|
||||||
|
const char *name;
|
||||||
|
@@ -366,6 +372,7 @@ struct multipath {
|
||||||
|
int ghost_delay;
|
||||||
|
int ghost_delay_tick;
|
||||||
|
unsigned int dev_loss;
|
||||||
|
+ int eh_deadline;
|
||||||
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
|
mode_t mode;
|
||||||
|
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
||||||
|
index 6dc26f10..60954574 100644
|
||||||
|
--- a/multipath/multipath.conf.5
|
||||||
|
+++ b/multipath/multipath.conf.5
|
||||||
|
@@ -700,6 +700,22 @@ The default is: \fB600\fR
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
+.B eh_deadline
|
||||||
|
+Specify the maximum number of seconds the SCSI layer will spend doing error
|
||||||
|
+handling when scsi devices fail. After this timeout the scsi layer will perform
|
||||||
|
+a full HBA reset. Setting this may be necessary in cases where the rport is
|
||||||
|
+never lost, so \fIfast_io_fail_tmo\fR and \fIdev_loss_tmo\fR will never
|
||||||
|
+trigger, but (frequently do to load) scsi commands still hang. \fBNote:\fR when
|
||||||
|
+the scsi error handler performs the HBA reset, all target paths on that HBA
|
||||||
|
+will be affected. eh_deadline should only be set in cases where all targets on
|
||||||
|
+the affected HBAs are multipathed.
|
||||||
|
+.RS
|
||||||
|
+.TP
|
||||||
|
+The default is: \fB<unset>\fR
|
||||||
|
+.RE
|
||||||
|
+.
|
||||||
|
+.
|
||||||
|
+.TP
|
||||||
|
.B bindings_file
|
||||||
|
The full pathname of the binding file to be used when the user_friendly_names
|
||||||
|
option is set.
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,89 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Fri, 23 Oct 2020 11:38:24 -0500
|
||||||
|
Subject: [PATCH] libmultipath: don't dlclose tur checker DSO
|
||||||
|
|
||||||
|
The multipathd tur checker thread is designed to be able to finish at
|
||||||
|
any time, even after the tur checker itself has been freed. The
|
||||||
|
multipathd shutdown code makes sure all the checkers have been freed
|
||||||
|
before freeing the checker_class and calling dlclose() to unload the
|
||||||
|
DSO, but this doesn't guarantee that the checker threads have finished.
|
||||||
|
If one hasn't, the DSO will get unloaded while the thread still running
|
||||||
|
code from it, causing a segfault. Unfortunately, it's not possible to be
|
||||||
|
sure that all tur checker threads have ended during shutdown, without
|
||||||
|
making them joinable.
|
||||||
|
|
||||||
|
However, since libmultipath will never be reinitialized after it has
|
||||||
|
been uninitialzed, not dlclosing the tur checker DSO once a thread is
|
||||||
|
started has minimal cost (keeping the DSO code around until the program
|
||||||
|
exits, which usually happens right after freeing the checkers).
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/checkers.c | 10 +++++++++-
|
||||||
|
libmultipath/checkers.h | 1 +
|
||||||
|
libmultipath/checkers/tur.c | 1 +
|
||||||
|
3 files changed, 11 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c
|
||||||
|
index 8d2be8a9..6359e5d8 100644
|
||||||
|
--- a/libmultipath/checkers.c
|
||||||
|
+++ b/libmultipath/checkers.c
|
||||||
|
@@ -21,6 +21,7 @@ struct checker_class {
|
||||||
|
void (*reset)(void); /* to reset the global variables */
|
||||||
|
const char **msgtable;
|
||||||
|
short msgtable_size;
|
||||||
|
+ int keep_dso;
|
||||||
|
};
|
||||||
|
|
||||||
|
char *checker_state_names[] = {
|
||||||
|
@@ -69,7 +70,7 @@ void free_checker_class(struct checker_class *c)
|
||||||
|
list_del(&c->node);
|
||||||
|
if (c->reset)
|
||||||
|
c->reset();
|
||||||
|
- if (c->handle) {
|
||||||
|
+ if (c->handle && !c->keep_dso) {
|
||||||
|
if (dlclose(c->handle) != 0) {
|
||||||
|
condlog(0, "Cannot unload checker %s: %s",
|
||||||
|
c->name, dlerror());
|
||||||
|
@@ -192,6 +193,13 @@ out:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void checker_keep_dso(struct checker * c)
|
||||||
|
+{
|
||||||
|
+ if (!c || !c->cls)
|
||||||
|
+ return;
|
||||||
|
+ c->cls->keep_dso = 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void checker_set_fd (struct checker * c, int fd)
|
||||||
|
{
|
||||||
|
if (!c)
|
||||||
|
diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h
|
||||||
|
index b458118d..f183cff9 100644
|
||||||
|
--- a/libmultipath/checkers.h
|
||||||
|
+++ b/libmultipath/checkers.h
|
||||||
|
@@ -145,6 +145,7 @@ void checker_reset (struct checker *);
|
||||||
|
void checker_set_sync (struct checker *);
|
||||||
|
void checker_set_async (struct checker *);
|
||||||
|
void checker_set_fd (struct checker *, int);
|
||||||
|
+void checker_keep_dso(struct checker *c);
|
||||||
|
void checker_enable (struct checker *);
|
||||||
|
void checker_disable (struct checker *);
|
||||||
|
int checker_check (struct checker *, int);
|
||||||
|
diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c
|
||||||
|
index e886fcf8..fd58d62a 100644
|
||||||
|
--- a/libmultipath/checkers/tur.c
|
||||||
|
+++ b/libmultipath/checkers/tur.c
|
||||||
|
@@ -394,6 +394,7 @@ int libcheck_check(struct checker * c)
|
||||||
|
uatomic_set(&ct->running, 1);
|
||||||
|
tur_set_async_timeout(c);
|
||||||
|
setup_thread_attr(&attr, 32 * 1024, 1);
|
||||||
|
+ checker_keep_dso(c);
|
||||||
|
r = pthread_create(&ct->thread, &attr, tur_thread, ct);
|
||||||
|
pthread_attr_destroy(&attr);
|
||||||
|
if (r) {
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,41 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 16 Nov 2020 13:52:09 -0600
|
||||||
|
Subject: [PATCH] libmultipath: warn about missing braces at end of
|
||||||
|
multipath.conf
|
||||||
|
|
||||||
|
Multipath doesn't warn when multipath.conf is missing closing braces at
|
||||||
|
the end of the file. This has confused people about the correct config
|
||||||
|
file syntax, so add a warning.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/parser.c | 5 +++--
|
||||||
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
|
||||||
|
index a7285a35..48b54e87 100644
|
||||||
|
--- a/libmultipath/parser.c
|
||||||
|
+++ b/libmultipath/parser.c
|
||||||
|
@@ -544,7 +544,7 @@ process_stream(struct config *conf, FILE *stream, vector keywords, char *file)
|
||||||
|
if (!strcmp(str, EOB)) {
|
||||||
|
if (kw_level > 0) {
|
||||||
|
free_strvec(strvec);
|
||||||
|
- break;
|
||||||
|
+ goto out;
|
||||||
|
}
|
||||||
|
condlog(0, "unmatched '%s' at line %d of %s",
|
||||||
|
EOB, line_nr, file);
|
||||||
|
@@ -583,7 +583,8 @@ process_stream(struct config *conf, FILE *stream, vector keywords, char *file)
|
||||||
|
|
||||||
|
free_strvec(strvec);
|
||||||
|
}
|
||||||
|
-
|
||||||
|
+ if (kw_level == 1)
|
||||||
|
+ condlog(1, "missing '%s' at end of %s", EOB, file);
|
||||||
|
out:
|
||||||
|
FREE(buf);
|
||||||
|
free_uniques(uniques);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,36 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 16 Nov 2020 16:38:21 -0600
|
||||||
|
Subject: [PATCH] libmultipath: ignore multipaths sections without wwid option
|
||||||
|
|
||||||
|
"multipathd show config local" was crashing in find_mp_by_wwid() if
|
||||||
|
the multipath configuration included a multipaths section that did
|
||||||
|
not set a wwid option. There is no reason to keep a mpentry that
|
||||||
|
didn't set its wwid. Remove it in merge_mptable().
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.c | 7 +++++++
|
||||||
|
1 file changed, 7 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||||
|
index a71db2d0..dc81c994 100644
|
||||||
|
--- a/libmultipath/config.c
|
||||||
|
+++ b/libmultipath/config.c
|
||||||
|
@@ -444,6 +444,13 @@ void merge_mptable(vector mptable)
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
vector_foreach_slot(mptable, mp1, i) {
|
||||||
|
+ /* drop invalid multipath configs */
|
||||||
|
+ if (!mp1->wwid) {
|
||||||
|
+ condlog(0, "multipaths config section missing wwid");
|
||||||
|
+ vector_del_slot(mptable, i--);
|
||||||
|
+ free_mpe(mp1);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
j = i + 1;
|
||||||
|
vector_foreach_slot_after(mptable, mp2, j) {
|
||||||
|
if (strcmp(mp1->wwid, mp2->wwid))
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,25 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 16 Nov 2020 23:21:41 -0600
|
||||||
|
Subject: [PATCH] tests: fix missing priority blacklist test
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
tests/blacklist.c | 1 -
|
||||||
|
1 file changed, 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/tests/blacklist.c b/tests/blacklist.c
|
||||||
|
index d20e97af..401600d9 100644
|
||||||
|
--- a/tests/blacklist.c
|
||||||
|
+++ b/tests/blacklist.c
|
||||||
|
@@ -378,7 +378,6 @@ static void test_property_missing(void **state)
|
||||||
|
{
|
||||||
|
static struct udev_device udev = { "sdb", { "ID_FOO", "ID_BAZ", "ID_BAR", "ID_SERIAL", NULL } };
|
||||||
|
conf.blist_property = blist_property_wwn;
|
||||||
|
- expect_condlog(3, "sdb: blacklisted, udev property missing\n");
|
||||||
|
assert_int_equal(filter_property(&conf, &udev, 3, "ID_SERIAL"),
|
||||||
|
MATCH_NOTHING);
|
||||||
|
assert_int_equal(filter_property(&conf, &udev, 3, "ID_BLAH"),
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 5 Nov 2020 09:15:43 -0600
|
||||||
|
Subject: [PATCH] mpathpersist: Fix Register and Ignore with 0x00 SARK
|
||||||
|
|
||||||
|
When the Register and Ignore command is run with sg_persist, if a 0x00
|
||||||
|
Service Action Reservation Key is given or the --param-sark option is
|
||||||
|
not used at all, sg_persist will clear the registration. mpathpersist
|
||||||
|
will fail with an error. This patch fixes mpathpersist to work like
|
||||||
|
sg_persist in this case.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmpathpersist/mpath_persist.c | 3 ++-
|
||||||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||||
|
index 3da7a6cf..aa196008 100644
|
||||||
|
--- a/libmpathpersist/mpath_persist.c
|
||||||
|
+++ b/libmpathpersist/mpath_persist.c
|
||||||
|
@@ -321,7 +321,8 @@ int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(paramp->key, &mpp->reservation_key, 8) &&
|
||||||
|
- memcmp(paramp->sa_key, &mpp->reservation_key, 8)) {
|
||||||
|
+ memcmp(paramp->sa_key, &mpp->reservation_key, 8) &&
|
||||||
|
+ (prkey || rq_servact != MPATH_PROUT_REG_IGN_SA)) {
|
||||||
|
condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64, alias, get_be64(mpp->reservation_key));
|
||||||
|
ret = MPATH_PR_SYNTAX_ERROR;
|
||||||
|
goto out1;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,38 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 23 Nov 2020 20:45:50 -0600
|
||||||
|
Subject: [PATCH] mpathpersist: update prkeys file on changing registrations
|
||||||
|
|
||||||
|
When the "reservation_key" option is set to "file" and Register command
|
||||||
|
is run with both the current Reservation Key and a new Service Action
|
||||||
|
Reservation Key, mpathpersist will change the registration, but will not
|
||||||
|
update the prkeys file. This means that future paths that come online
|
||||||
|
will not be able to register, since multipathd is still using the old
|
||||||
|
reservation key. Fix this.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmpathpersist/mpath_persist.c | 7 ++++---
|
||||||
|
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||||
|
index aa196008..a01dfb0b 100644
|
||||||
|
--- a/libmpathpersist/mpath_persist.c
|
||||||
|
+++ b/libmpathpersist/mpath_persist.c
|
||||||
|
@@ -307,9 +307,10 @@ int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||||
|
|
||||||
|
memcpy(&prkey, paramp->sa_key, 8);
|
||||||
|
if (mpp->prkey_source == PRKEY_SOURCE_FILE && prkey &&
|
||||||
|
- ((!get_be64(mpp->reservation_key) &&
|
||||||
|
- rq_servact == MPATH_PROUT_REG_SA) ||
|
||||||
|
- rq_servact == MPATH_PROUT_REG_IGN_SA)) {
|
||||||
|
+ (rq_servact == MPATH_PROUT_REG_IGN_SA ||
|
||||||
|
+ (rq_servact == MPATH_PROUT_REG_SA &&
|
||||||
|
+ (!get_be64(mpp->reservation_key) ||
|
||||||
|
+ memcmp(paramp->key, &mpp->reservation_key, 8) == 0)))) {
|
||||||
|
memcpy(&mpp->reservation_key, paramp->sa_key, 8);
|
||||||
|
if (update_prkey_flags(alias, get_be64(mpp->reservation_key),
|
||||||
|
paramp->sa_flags)) {
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,37 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 14 Dec 2020 14:16:29 -0600
|
||||||
|
Subject: [PATCH] multipathd: Fix multipathd stopping on shutdown
|
||||||
|
|
||||||
|
According to man "systemd.special"
|
||||||
|
|
||||||
|
"shutdown.target: ... Services that shall be terminated on system
|
||||||
|
shutdown shall add Conflicts= and Before= dependencies to this unit for
|
||||||
|
their service unit, which is implicitly done when
|
||||||
|
DefaultDependencies=yes is set (the default)."
|
||||||
|
|
||||||
|
multipathd.service sets DefaultDependencies=no and includes the
|
||||||
|
Conflits= dependency, but not the Before= one. This can cause multipathd
|
||||||
|
to continue running past when it is supposed to during shutdown.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
multipathd/multipathd.service | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
|
||||||
|
index 0fbcc46b..bc8fa07a 100644
|
||||||
|
--- a/multipathd/multipathd.service
|
||||||
|
+++ b/multipathd/multipathd.service
|
||||||
|
@@ -2,7 +2,7 @@
|
||||||
|
Description=Device-Mapper Multipath Device Controller
|
||||||
|
Wants=systemd-udev-trigger.service systemd-udev-settle.service
|
||||||
|
Before=iscsi.service iscsid.service lvm2-activation-early.service
|
||||||
|
-Before=local-fs-pre.target blk-availability.service
|
||||||
|
+Before=local-fs-pre.target blk-availability.service shutdown.target
|
||||||
|
After=multipathd.socket systemd-udev-trigger.service systemd-udev-settle.service
|
||||||
|
ConditionPathExists=/etc/multipath.conf
|
||||||
|
DefaultDependencies=no
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,36 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 15 Dec 2020 12:47:14 -0600
|
||||||
|
Subject: [PATCH] multipath.conf.5: Improve checker_timeout description
|
||||||
|
|
||||||
|
I was asked to explain how checker_timeout works for checkers like
|
||||||
|
directio, that don't issue scsi commands with an explicit timeout
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
multipath/multipath.conf.5 | 9 +++++++--
|
||||||
|
1 file changed, 7 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
||||||
|
index 60954574..a5686090 100644
|
||||||
|
--- a/multipath/multipath.conf.5
|
||||||
|
+++ b/multipath/multipath.conf.5
|
||||||
|
@@ -634,8 +634,13 @@ The default is: \fBno\fR
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.B checker_timeout
|
||||||
|
-Specify the timeout to use for path checkers and prioritizers that issue SCSI
|
||||||
|
-commands with an explicit timeout, in seconds.
|
||||||
|
+Specify the timeout to use for path checkers and prioritizers, in seconds.
|
||||||
|
+Only prioritizers that issue scsi commands use checker_timeout. Checkers
|
||||||
|
+that support an asynchronous mode (\fItur\fR and \fIdirectio\fR), will
|
||||||
|
+return shortly after being called by multipathd, regardless of whether the
|
||||||
|
+storage array responds. If the storage array hasn't responded, mulitpathd will
|
||||||
|
+check for a response every second, until \fIchecker_timeout\fR seconds have
|
||||||
|
+elapsed.
|
||||||
|
.RS
|
||||||
|
.TP
|
||||||
|
The default is: in \fB/sys/block/sd<x>/device/timeout\fR
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,34 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 4 Jan 2021 21:59:54 -0600
|
||||||
|
Subject: [PATCH] libmultipath: check for null wwid before strcmp
|
||||||
|
|
||||||
|
Commit 749aabd0 (libmultipath: ignore multipaths sections without wwid
|
||||||
|
option) removed all mpentries with a NULL wwid, but didn't stop strcmp()
|
||||||
|
from being run on them in merge_mptable(). The result of strcmp() with
|
||||||
|
a NULL parameter is undefined, so fix that.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||||
|
index dc81c994..dd645f17 100644
|
||||||
|
--- a/libmultipath/config.c
|
||||||
|
+++ b/libmultipath/config.c
|
||||||
|
@@ -453,7 +453,7 @@ void merge_mptable(vector mptable)
|
||||||
|
}
|
||||||
|
j = i + 1;
|
||||||
|
vector_foreach_slot_after(mptable, mp2, j) {
|
||||||
|
- if (strcmp(mp1->wwid, mp2->wwid))
|
||||||
|
+ if (!mp2->wwid || strcmp(mp1->wwid, mp2->wwid))
|
||||||
|
continue;
|
||||||
|
condlog(1, "%s: duplicate multipath config section for %s",
|
||||||
|
__func__, mp1->wwid);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,27 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 14 Jan 2021 20:20:22 -0600
|
||||||
|
Subject: [PATCH] libmultipath: make find_err_path_by_dev() static
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
---
|
||||||
|
libmultipath/io_err_stat.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
|
||||||
|
index 1b9cd6c0..449760a0 100644
|
||||||
|
--- a/libmultipath/io_err_stat.c
|
||||||
|
+++ b/libmultipath/io_err_stat.c
|
||||||
|
@@ -89,7 +89,7 @@ static void rcu_unregister(__attribute__((unused)) void *param)
|
||||||
|
rcu_unregister_thread();
|
||||||
|
}
|
||||||
|
|
||||||
|
-struct io_err_stat_path *find_err_path_by_dev(vector pathvec, char *dev)
|
||||||
|
+static struct io_err_stat_path *find_err_path_by_dev(vector pathvec, char *dev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct io_err_stat_path *pp;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,291 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 14 Jan 2021 20:20:23 -0600
|
||||||
|
Subject: [PATCH] multipathd: avoid io_err_stat crash during shutdown
|
||||||
|
|
||||||
|
The checker thread is reponsible for enqueueing paths for the
|
||||||
|
io_err_stat thread to check. During shutdown, the io_err_stat thread is
|
||||||
|
shut down and cleaned up before the checker thread. There is no code
|
||||||
|
to make sure that the checker thread isn't accessing the io_err_stat
|
||||||
|
pathvec or its mutex while they are being freed, which can lead to
|
||||||
|
memory corruption crashes.
|
||||||
|
|
||||||
|
To solve this, get rid of the io_err_stat_pathvec structure, and
|
||||||
|
statically define the mutex. This means that the mutex is always valid
|
||||||
|
to access, and the io_err_stat pathvec can only be accessed while
|
||||||
|
holding it. If the io_err_stat thread has already been cleaned up
|
||||||
|
when the checker tries to access the pathvec, it will be NULL, and the
|
||||||
|
checker will simply fail to enqueue the path.
|
||||||
|
|
||||||
|
This change also fixes a bug in free_io_err_pathvec(), which previously
|
||||||
|
only attempted to free the pathvec if it was not set, instead of when it
|
||||||
|
was set.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
---
|
||||||
|
libmultipath/io_err_stat.c | 112 +++++++++++++++----------------------
|
||||||
|
libmultipath/util.c | 5 ++
|
||||||
|
libmultipath/util.h | 1 +
|
||||||
|
3 files changed, 50 insertions(+), 68 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
|
||||||
|
index 449760a0..f6c564f0 100644
|
||||||
|
--- a/libmultipath/io_err_stat.c
|
||||||
|
+++ b/libmultipath/io_err_stat.c
|
||||||
|
@@ -34,6 +34,7 @@
|
||||||
|
#include "lock.h"
|
||||||
|
#include "time-util.h"
|
||||||
|
#include "io_err_stat.h"
|
||||||
|
+#include "util.h"
|
||||||
|
|
||||||
|
#define IOTIMEOUT_SEC 60
|
||||||
|
#define TIMEOUT_NO_IO_NSEC 10000000 /*10ms = 10000000ns*/
|
||||||
|
@@ -46,12 +47,6 @@
|
||||||
|
#define io_err_stat_log(prio, fmt, args...) \
|
||||||
|
condlog(prio, "io error statistic: " fmt, ##args)
|
||||||
|
|
||||||
|
-
|
||||||
|
-struct io_err_stat_pathvec {
|
||||||
|
- pthread_mutex_t mutex;
|
||||||
|
- vector pathvec;
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
struct dio_ctx {
|
||||||
|
struct timespec io_starttime;
|
||||||
|
unsigned int blksize;
|
||||||
|
@@ -76,9 +71,10 @@ pthread_attr_t io_err_stat_attr;
|
||||||
|
|
||||||
|
static pthread_mutex_t io_err_thread_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static pthread_cond_t io_err_thread_cond = PTHREAD_COND_INITIALIZER;
|
||||||
|
+static pthread_mutex_t io_err_pathvec_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static int io_err_thread_running = 0;
|
||||||
|
|
||||||
|
-static struct io_err_stat_pathvec *paths;
|
||||||
|
+static vector io_err_pathvec;
|
||||||
|
struct vectors *vecs;
|
||||||
|
io_context_t ioctx;
|
||||||
|
|
||||||
|
@@ -208,46 +204,23 @@ static void free_io_err_stat_path(struct io_err_stat_path *p)
|
||||||
|
FREE(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static struct io_err_stat_pathvec *alloc_pathvec(void)
|
||||||
|
-{
|
||||||
|
- struct io_err_stat_pathvec *p;
|
||||||
|
- int r;
|
||||||
|
-
|
||||||
|
- p = (struct io_err_stat_pathvec *)MALLOC(sizeof(*p));
|
||||||
|
- if (!p)
|
||||||
|
- return NULL;
|
||||||
|
- p->pathvec = vector_alloc();
|
||||||
|
- if (!p->pathvec)
|
||||||
|
- goto out_free_struct_pathvec;
|
||||||
|
- r = pthread_mutex_init(&p->mutex, NULL);
|
||||||
|
- if (r)
|
||||||
|
- goto out_free_member_pathvec;
|
||||||
|
-
|
||||||
|
- return p;
|
||||||
|
-
|
||||||
|
-out_free_member_pathvec:
|
||||||
|
- vector_free(p->pathvec);
|
||||||
|
-out_free_struct_pathvec:
|
||||||
|
- FREE(p);
|
||||||
|
- return NULL;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void free_io_err_pathvec(struct io_err_stat_pathvec *p)
|
||||||
|
+static void free_io_err_pathvec(void)
|
||||||
|
{
|
||||||
|
struct io_err_stat_path *path;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
- if (!p)
|
||||||
|
- return;
|
||||||
|
- pthread_mutex_destroy(&p->mutex);
|
||||||
|
- if (!p->pathvec) {
|
||||||
|
- vector_foreach_slot(p->pathvec, path, i) {
|
||||||
|
- destroy_directio_ctx(path);
|
||||||
|
- free_io_err_stat_path(path);
|
||||||
|
- }
|
||||||
|
- vector_free(p->pathvec);
|
||||||
|
+ pthread_mutex_lock(&io_err_pathvec_lock);
|
||||||
|
+ pthread_cleanup_push(cleanup_mutex, &io_err_pathvec_lock);
|
||||||
|
+ if (!io_err_pathvec)
|
||||||
|
+ goto out;
|
||||||
|
+ vector_foreach_slot(io_err_pathvec, path, i) {
|
||||||
|
+ destroy_directio_ctx(path);
|
||||||
|
+ free_io_err_stat_path(path);
|
||||||
|
}
|
||||||
|
- FREE(p);
|
||||||
|
+ vector_free(io_err_pathvec);
|
||||||
|
+ io_err_pathvec = NULL;
|
||||||
|
+out:
|
||||||
|
+ pthread_cleanup_pop(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -259,13 +232,13 @@ static int enqueue_io_err_stat_by_path(struct path *path)
|
||||||
|
{
|
||||||
|
struct io_err_stat_path *p;
|
||||||
|
|
||||||
|
- pthread_mutex_lock(&paths->mutex);
|
||||||
|
- p = find_err_path_by_dev(paths->pathvec, path->dev);
|
||||||
|
+ pthread_mutex_lock(&io_err_pathvec_lock);
|
||||||
|
+ p = find_err_path_by_dev(io_err_pathvec, path->dev);
|
||||||
|
if (p) {
|
||||||
|
- pthread_mutex_unlock(&paths->mutex);
|
||||||
|
+ pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
- pthread_mutex_unlock(&paths->mutex);
|
||||||
|
+ pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||||
|
|
||||||
|
p = alloc_io_err_stat_path();
|
||||||
|
if (!p)
|
||||||
|
@@ -277,18 +250,18 @@ static int enqueue_io_err_stat_by_path(struct path *path)
|
||||||
|
|
||||||
|
if (setup_directio_ctx(p))
|
||||||
|
goto free_ioerr_path;
|
||||||
|
- pthread_mutex_lock(&paths->mutex);
|
||||||
|
- if (!vector_alloc_slot(paths->pathvec))
|
||||||
|
+ pthread_mutex_lock(&io_err_pathvec_lock);
|
||||||
|
+ if (!vector_alloc_slot(io_err_pathvec))
|
||||||
|
goto unlock_destroy;
|
||||||
|
- vector_set_slot(paths->pathvec, p);
|
||||||
|
- pthread_mutex_unlock(&paths->mutex);
|
||||||
|
+ vector_set_slot(io_err_pathvec, p);
|
||||||
|
+ pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||||
|
|
||||||
|
io_err_stat_log(2, "%s: enqueue path %s to check",
|
||||||
|
path->mpp->alias, path->dev);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
unlock_destroy:
|
||||||
|
- pthread_mutex_unlock(&paths->mutex);
|
||||||
|
+ pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||||
|
destroy_directio_ctx(p);
|
||||||
|
free_ioerr_path:
|
||||||
|
free_io_err_stat_path(p);
|
||||||
|
@@ -421,9 +394,9 @@ static int delete_io_err_stat_by_addr(struct io_err_stat_path *p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
- i = find_slot(paths->pathvec, p);
|
||||||
|
+ i = find_slot(io_err_pathvec, p);
|
||||||
|
if (i != -1)
|
||||||
|
- vector_del_slot(paths->pathvec, i);
|
||||||
|
+ vector_del_slot(io_err_pathvec, i);
|
||||||
|
|
||||||
|
destroy_directio_ctx(p);
|
||||||
|
free_io_err_stat_path(p);
|
||||||
|
@@ -594,7 +567,7 @@ static void poll_async_io_timeout(void)
|
||||||
|
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC, &curr_time) != 0)
|
||||||
|
return;
|
||||||
|
- vector_foreach_slot(paths->pathvec, pp, i) {
|
||||||
|
+ vector_foreach_slot(io_err_pathvec, pp, i) {
|
||||||
|
for (j = 0; j < CONCUR_NR_EVENT; j++) {
|
||||||
|
rc = try_to_cancel_timeout_io(pp->dio_ctx_array + j,
|
||||||
|
&curr_time, pp->devname);
|
||||||
|
@@ -640,7 +613,7 @@ static void handle_async_io_done_event(struct io_event *io_evt)
|
||||||
|
int rc = PATH_UNCHECKED;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
- vector_foreach_slot(paths->pathvec, pp, i) {
|
||||||
|
+ vector_foreach_slot(io_err_pathvec, pp, i) {
|
||||||
|
for (j = 0; j < CONCUR_NR_EVENT; j++) {
|
||||||
|
ct = pp->dio_ctx_array + j;
|
||||||
|
if (&ct->io == io_evt->obj) {
|
||||||
|
@@ -674,19 +647,14 @@ static void service_paths(void)
|
||||||
|
struct io_err_stat_path *pp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
- pthread_mutex_lock(&paths->mutex);
|
||||||
|
- vector_foreach_slot(paths->pathvec, pp, i) {
|
||||||
|
+ pthread_mutex_lock(&io_err_pathvec_lock);
|
||||||
|
+ vector_foreach_slot(io_err_pathvec, pp, i) {
|
||||||
|
send_batch_async_ios(pp);
|
||||||
|
process_async_ios_event(TIMEOUT_NO_IO_NSEC, pp->devname);
|
||||||
|
poll_async_io_timeout();
|
||||||
|
poll_io_err_stat(vecs, pp);
|
||||||
|
}
|
||||||
|
- pthread_mutex_unlock(&paths->mutex);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void cleanup_unlock(void *arg)
|
||||||
|
-{
|
||||||
|
- pthread_mutex_unlock((pthread_mutex_t*) arg);
|
||||||
|
+ pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cleanup_exited(__attribute__((unused)) void *arg)
|
||||||
|
@@ -744,12 +712,17 @@ int start_io_err_stat_thread(void *data)
|
||||||
|
io_err_stat_log(4, "io_setup failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
- paths = alloc_pathvec();
|
||||||
|
- if (!paths)
|
||||||
|
+
|
||||||
|
+ pthread_mutex_lock(&io_err_pathvec_lock);
|
||||||
|
+ io_err_pathvec = vector_alloc();
|
||||||
|
+ if (!io_err_pathvec) {
|
||||||
|
+ pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||||
|
goto destroy_ctx;
|
||||||
|
+ }
|
||||||
|
+ pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&io_err_thread_lock);
|
||||||
|
- pthread_cleanup_push(cleanup_unlock, &io_err_thread_lock);
|
||||||
|
+ pthread_cleanup_push(cleanup_mutex, &io_err_thread_lock);
|
||||||
|
|
||||||
|
ret = pthread_create(&io_err_stat_thr, &io_err_stat_attr,
|
||||||
|
io_err_stat_loop, data);
|
||||||
|
@@ -769,7 +742,10 @@ int start_io_err_stat_thread(void *data)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out_free:
|
||||||
|
- free_io_err_pathvec(paths);
|
||||||
|
+ pthread_mutex_lock(&io_err_pathvec_lock);
|
||||||
|
+ vector_free(io_err_pathvec);
|
||||||
|
+ io_err_pathvec = NULL;
|
||||||
|
+ pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||||
|
destroy_ctx:
|
||||||
|
io_destroy(ioctx);
|
||||||
|
io_err_stat_log(0, "failed to start io_error statistic thread");
|
||||||
|
@@ -785,6 +761,6 @@ void stop_io_err_stat_thread(void)
|
||||||
|
pthread_cancel(io_err_stat_thr);
|
||||||
|
|
||||||
|
pthread_join(io_err_stat_thr, NULL);
|
||||||
|
- free_io_err_pathvec(paths);
|
||||||
|
+ free_io_err_pathvec();
|
||||||
|
io_destroy(ioctx);
|
||||||
|
}
|
||||||
|
diff --git a/libmultipath/util.c b/libmultipath/util.c
|
||||||
|
index 51c38c87..dd30a46e 100644
|
||||||
|
--- a/libmultipath/util.c
|
||||||
|
+++ b/libmultipath/util.c
|
||||||
|
@@ -469,3 +469,8 @@ void close_fd(void *arg)
|
||||||
|
{
|
||||||
|
close((long)arg);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+void cleanup_mutex(void *arg)
|
||||||
|
+{
|
||||||
|
+ pthread_mutex_unlock(arg);
|
||||||
|
+}
|
||||||
|
diff --git a/libmultipath/util.h b/libmultipath/util.h
|
||||||
|
index 56bd78c7..ce277680 100644
|
||||||
|
--- a/libmultipath/util.h
|
||||||
|
+++ b/libmultipath/util.h
|
||||||
|
@@ -44,6 +44,7 @@ void set_max_fds(rlim_t max_fds);
|
||||||
|
pthread_cleanup_push(((void (*)(void *))&f), (arg))
|
||||||
|
|
||||||
|
void close_fd(void *arg);
|
||||||
|
+void cleanup_mutex(void *arg);
|
||||||
|
|
||||||
|
struct scandir_result {
|
||||||
|
struct dirent **di;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,146 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 14 Jan 2021 20:20:24 -0600
|
||||||
|
Subject: [PATCH] multipathd: avoid io_err_stat ABBA deadlock
|
||||||
|
|
||||||
|
When the checker thread enqueues paths for the io_err_stat thread to
|
||||||
|
check, it calls enqueue_io_err_stat_by_path() with the vecs lock held.
|
||||||
|
start_io_err_stat_thread() is also called with the vecs lock held.
|
||||||
|
These two functions both lock io_err_pathvec_lock. When the io_err_stat
|
||||||
|
thread updates the paths in vecs->pathvec in poll_io_err_stat(), it has
|
||||||
|
the io_err_pathvec_lock held, and then locks the vecs lock. This can
|
||||||
|
cause an ABBA deadlock.
|
||||||
|
|
||||||
|
To solve this, service_paths() no longer updates the paths in
|
||||||
|
vecs->pathvec with the io_err_pathvec_lock held. It does this by moving
|
||||||
|
the io_err_stat_path from io_err_pathvec to a local vector when it needs
|
||||||
|
to update the path. After releasing the io_err_pathvec_lock, it goes
|
||||||
|
through this temporary vector, updates the paths with the vecs lock
|
||||||
|
held, and then frees everything.
|
||||||
|
|
||||||
|
This change fixes a bug in service_paths() where elements were being
|
||||||
|
deleted from io_err_pathvec, without the index being decremented,
|
||||||
|
causing the loop to skip elements. Also, service_paths() could be
|
||||||
|
cancelled while holding the io_err_pathvec_lock, so it should have a
|
||||||
|
cleanup handler.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
---
|
||||||
|
libmultipath/io_err_stat.c | 56 ++++++++++++++++++++++----------------
|
||||||
|
1 file changed, 32 insertions(+), 24 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
|
||||||
|
index f6c564f0..63ee2e07 100644
|
||||||
|
--- a/libmultipath/io_err_stat.c
|
||||||
|
+++ b/libmultipath/io_err_stat.c
|
||||||
|
@@ -390,20 +390,6 @@ recover:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int delete_io_err_stat_by_addr(struct io_err_stat_path *p)
|
||||||
|
-{
|
||||||
|
- int i;
|
||||||
|
-
|
||||||
|
- i = find_slot(io_err_pathvec, p);
|
||||||
|
- if (i != -1)
|
||||||
|
- vector_del_slot(io_err_pathvec, i);
|
||||||
|
-
|
||||||
|
- destroy_directio_ctx(p);
|
||||||
|
- free_io_err_stat_path(p);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static void account_async_io_state(struct io_err_stat_path *pp, int rc)
|
||||||
|
{
|
||||||
|
switch (rc) {
|
||||||
|
@@ -420,17 +406,26 @@ static void account_async_io_state(struct io_err_stat_path *pp, int rc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int poll_io_err_stat(struct vectors *vecs, struct io_err_stat_path *pp)
|
||||||
|
+static int io_err_stat_time_up(struct io_err_stat_path *pp)
|
||||||
|
{
|
||||||
|
struct timespec currtime, difftime;
|
||||||
|
- struct path *path;
|
||||||
|
- double err_rate;
|
||||||
|
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC, &currtime) != 0)
|
||||||
|
- return 1;
|
||||||
|
+ return 0;
|
||||||
|
timespecsub(&currtime, &pp->start_time, &difftime);
|
||||||
|
if (difftime.tv_sec < pp->total_time)
|
||||||
|
return 0;
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void end_io_err_stat(struct io_err_stat_path *pp)
|
||||||
|
+{
|
||||||
|
+ struct timespec currtime;
|
||||||
|
+ struct path *path;
|
||||||
|
+ double err_rate;
|
||||||
|
+
|
||||||
|
+ if (clock_gettime(CLOCK_MONOTONIC, &currtime) != 0)
|
||||||
|
+ currtime = pp->start_time;
|
||||||
|
|
||||||
|
io_err_stat_log(4, "%s: check end", pp->devname);
|
||||||
|
|
||||||
|
@@ -469,10 +464,6 @@ static int poll_io_err_stat(struct vectors *vecs, struct io_err_stat_path *pp)
|
||||||
|
pp->devname);
|
||||||
|
}
|
||||||
|
lock_cleanup_pop(vecs->lock);
|
||||||
|
-
|
||||||
|
- delete_io_err_stat_by_addr(pp);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int send_each_async_io(struct dio_ctx *ct, int fd, char *dev)
|
||||||
|
@@ -632,6 +623,7 @@ static void process_async_ios_event(int timeout_nsecs, char *dev)
|
||||||
|
struct timespec timeout = { .tv_nsec = timeout_nsecs };
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
+ pthread_testcancel();
|
||||||
|
n = io_getevents(ioctx, 1L, CONCUR_NR_EVENT, events, &timeout);
|
||||||
|
if (n < 0) {
|
||||||
|
io_err_stat_log(3, "%s: async io events returned %d (errno=%s)",
|
||||||
|
@@ -644,17 +636,33 @@ static void process_async_ios_event(int timeout_nsecs, char *dev)
|
||||||
|
|
||||||
|
static void service_paths(void)
|
||||||
|
{
|
||||||
|
+ struct _vector _pathvec = {0};
|
||||||
|
+ /* avoid gcc warnings that &_pathvec will never be NULL in vector ops */
|
||||||
|
+ struct _vector * const tmp_pathvec = &_pathvec;
|
||||||
|
struct io_err_stat_path *pp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&io_err_pathvec_lock);
|
||||||
|
+ pthread_cleanup_push(cleanup_mutex, &io_err_pathvec_lock);
|
||||||
|
vector_foreach_slot(io_err_pathvec, pp, i) {
|
||||||
|
send_batch_async_ios(pp);
|
||||||
|
process_async_ios_event(TIMEOUT_NO_IO_NSEC, pp->devname);
|
||||||
|
poll_async_io_timeout();
|
||||||
|
- poll_io_err_stat(vecs, pp);
|
||||||
|
+ if (io_err_stat_time_up(pp)) {
|
||||||
|
+ if (!vector_alloc_slot(tmp_pathvec))
|
||||||
|
+ continue;
|
||||||
|
+ vector_del_slot(io_err_pathvec, i--);
|
||||||
|
+ vector_set_slot(tmp_pathvec, pp);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
- pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||||
|
+ pthread_cleanup_pop(1);
|
||||||
|
+ vector_foreach_slot_backwards(tmp_pathvec, pp, i) {
|
||||||
|
+ end_io_err_stat(pp);
|
||||||
|
+ vector_del_slot(tmp_pathvec, i);
|
||||||
|
+ destroy_directio_ctx(pp);
|
||||||
|
+ free_io_err_stat_path(pp);
|
||||||
|
+ }
|
||||||
|
+ vector_reset(tmp_pathvec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cleanup_exited(__attribute__((unused)) void *arg)
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,111 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 14 Jan 2021 20:20:25 -0600
|
||||||
|
Subject: [PATCH] multipathd: use get_monotonic_time() in io_err_stat code
|
||||||
|
|
||||||
|
Instead of calling clock_gettime(), and dealing with failure
|
||||||
|
conditions, just call get_monotonic_time().
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
---
|
||||||
|
libmultipath/io_err_stat.c | 34 +++++++++++-----------------------
|
||||||
|
1 file changed, 11 insertions(+), 23 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
|
||||||
|
index 63ee2e07..3389d693 100644
|
||||||
|
--- a/libmultipath/io_err_stat.c
|
||||||
|
+++ b/libmultipath/io_err_stat.c
|
||||||
|
@@ -305,8 +305,7 @@ int io_err_stat_handle_pathfail(struct path *path)
|
||||||
|
* the repeated count threshold and time frame, we assume a path
|
||||||
|
* which fails at least twice within 60 seconds is flaky.
|
||||||
|
*/
|
||||||
|
- if (clock_gettime(CLOCK_MONOTONIC, &curr_time) != 0)
|
||||||
|
- return 1;
|
||||||
|
+ get_monotonic_time(&curr_time);
|
||||||
|
if (path->io_err_pathfail_cnt == 0) {
|
||||||
|
path->io_err_pathfail_cnt++;
|
||||||
|
path->io_err_pathfail_starttime = curr_time.tv_sec;
|
||||||
|
@@ -362,9 +361,9 @@ int need_io_err_check(struct path *pp)
|
||||||
|
}
|
||||||
|
if (pp->io_err_pathfail_cnt != PATH_IO_ERR_WAITING_TO_CHECK)
|
||||||
|
return 1;
|
||||||
|
- if (clock_gettime(CLOCK_MONOTONIC, &curr_time) != 0 ||
|
||||||
|
- (curr_time.tv_sec - pp->io_err_dis_reinstate_time) >
|
||||||
|
- pp->mpp->marginal_path_err_recheck_gap_time) {
|
||||||
|
+ get_monotonic_time(&curr_time);
|
||||||
|
+ if ((curr_time.tv_sec - pp->io_err_dis_reinstate_time) >
|
||||||
|
+ pp->mpp->marginal_path_err_recheck_gap_time) {
|
||||||
|
io_err_stat_log(4, "%s: reschedule checking after %d seconds",
|
||||||
|
pp->dev,
|
||||||
|
pp->mpp->marginal_path_err_recheck_gap_time);
|
||||||
|
@@ -410,8 +409,7 @@ static int io_err_stat_time_up(struct io_err_stat_path *pp)
|
||||||
|
{
|
||||||
|
struct timespec currtime, difftime;
|
||||||
|
|
||||||
|
- if (clock_gettime(CLOCK_MONOTONIC, &currtime) != 0)
|
||||||
|
- return 0;
|
||||||
|
+ get_monotonic_time(&currtime);
|
||||||
|
timespecsub(&currtime, &pp->start_time, &difftime);
|
||||||
|
if (difftime.tv_sec < pp->total_time)
|
||||||
|
return 0;
|
||||||
|
@@ -424,8 +422,7 @@ static void end_io_err_stat(struct io_err_stat_path *pp)
|
||||||
|
struct path *path;
|
||||||
|
double err_rate;
|
||||||
|
|
||||||
|
- if (clock_gettime(CLOCK_MONOTONIC, &currtime) != 0)
|
||||||
|
- currtime = pp->start_time;
|
||||||
|
+ get_monotonic_time(&currtime);
|
||||||
|
|
||||||
|
io_err_stat_log(4, "%s: check end", pp->devname);
|
||||||
|
|
||||||
|
@@ -474,11 +471,7 @@ static int send_each_async_io(struct dio_ctx *ct, int fd, char *dev)
|
||||||
|
ct->io_starttime.tv_sec == 0) {
|
||||||
|
struct iocb *ios[1] = { &ct->io };
|
||||||
|
|
||||||
|
- if (clock_gettime(CLOCK_MONOTONIC, &ct->io_starttime) != 0) {
|
||||||
|
- ct->io_starttime.tv_sec = 0;
|
||||||
|
- ct->io_starttime.tv_nsec = 0;
|
||||||
|
- return rc;
|
||||||
|
- }
|
||||||
|
+ get_monotonic_time(&ct->io_starttime);
|
||||||
|
io_prep_pread(&ct->io, fd, ct->buf, ct->blksize, 0);
|
||||||
|
if (io_submit(ioctx, 1, ios) != 1) {
|
||||||
|
io_err_stat_log(5, "%s: io_submit error %i",
|
||||||
|
@@ -497,8 +490,7 @@ static void send_batch_async_ios(struct io_err_stat_path *pp)
|
||||||
|
struct dio_ctx *ct;
|
||||||
|
struct timespec currtime, difftime;
|
||||||
|
|
||||||
|
- if (clock_gettime(CLOCK_MONOTONIC, &currtime) != 0)
|
||||||
|
- return;
|
||||||
|
+ get_monotonic_time(&currtime);
|
||||||
|
/*
|
||||||
|
* Give a free time for all IO to complete or timeout
|
||||||
|
*/
|
||||||
|
@@ -513,11 +505,8 @@ static void send_batch_async_ios(struct io_err_stat_path *pp)
|
||||||
|
if (!send_each_async_io(ct, pp->fd, pp->devname))
|
||||||
|
pp->io_nr++;
|
||||||
|
}
|
||||||
|
- if (pp->start_time.tv_sec == 0 && pp->start_time.tv_nsec == 0 &&
|
||||||
|
- clock_gettime(CLOCK_MONOTONIC, &pp->start_time)) {
|
||||||
|
- pp->start_time.tv_sec = 0;
|
||||||
|
- pp->start_time.tv_nsec = 0;
|
||||||
|
- }
|
||||||
|
+ if (pp->start_time.tv_sec == 0 && pp->start_time.tv_nsec == 0)
|
||||||
|
+ get_monotonic_time(&pp->start_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int try_to_cancel_timeout_io(struct dio_ctx *ct, struct timespec *t,
|
||||||
|
@@ -556,8 +545,7 @@ static void poll_async_io_timeout(void)
|
||||||
|
int rc = PATH_UNCHECKED;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
- if (clock_gettime(CLOCK_MONOTONIC, &curr_time) != 0)
|
||||||
|
- return;
|
||||||
|
+ get_monotonic_time(&curr_time);
|
||||||
|
vector_foreach_slot(io_err_pathvec, pp, i) {
|
||||||
|
for (j = 0; j < CONCUR_NR_EVENT; j++) {
|
||||||
|
rc = try_to_cancel_timeout_io(pp->dio_ctx_array + j,
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,101 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 14 Jan 2021 20:20:26 -0600
|
||||||
|
Subject: [PATCH] multipathd: combine free_io_err_stat_path and
|
||||||
|
destroy_directio_ctx
|
||||||
|
|
||||||
|
destroy_directio_ctx() is only called from free_io_err_stat_path(), and
|
||||||
|
free_io_err_stat_path() is very short, so combine them.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
---
|
||||||
|
libmultipath/io_err_stat.c | 24 ++++++++++--------------
|
||||||
|
1 file changed, 10 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
|
||||||
|
index 3389d693..bf1d3910 100644
|
||||||
|
--- a/libmultipath/io_err_stat.c
|
||||||
|
+++ b/libmultipath/io_err_stat.c
|
||||||
|
@@ -163,12 +163,15 @@ fail_close:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void destroy_directio_ctx(struct io_err_stat_path *p)
|
||||||
|
+static void free_io_err_stat_path(struct io_err_stat_path *p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
- if (!p || !p->dio_ctx_array)
|
||||||
|
+ if (!p)
|
||||||
|
return;
|
||||||
|
+ if (!p->dio_ctx_array)
|
||||||
|
+ goto free_path;
|
||||||
|
+
|
||||||
|
cancel_inflight_io(p);
|
||||||
|
|
||||||
|
for (i = 0; i < CONCUR_NR_EVENT; i++)
|
||||||
|
@@ -177,6 +180,8 @@ static void destroy_directio_ctx(struct io_err_stat_path *p)
|
||||||
|
|
||||||
|
if (p->fd > 0)
|
||||||
|
close(p->fd);
|
||||||
|
+free_path:
|
||||||
|
+ FREE(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct io_err_stat_path *alloc_io_err_stat_path(void)
|
||||||
|
@@ -199,11 +204,6 @@ static struct io_err_stat_path *alloc_io_err_stat_path(void)
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void free_io_err_stat_path(struct io_err_stat_path *p)
|
||||||
|
-{
|
||||||
|
- FREE(p);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static void free_io_err_pathvec(void)
|
||||||
|
{
|
||||||
|
struct io_err_stat_path *path;
|
||||||
|
@@ -213,10 +213,8 @@ static void free_io_err_pathvec(void)
|
||||||
|
pthread_cleanup_push(cleanup_mutex, &io_err_pathvec_lock);
|
||||||
|
if (!io_err_pathvec)
|
||||||
|
goto out;
|
||||||
|
- vector_foreach_slot(io_err_pathvec, path, i) {
|
||||||
|
- destroy_directio_ctx(path);
|
||||||
|
+ vector_foreach_slot(io_err_pathvec, path, i)
|
||||||
|
free_io_err_stat_path(path);
|
||||||
|
- }
|
||||||
|
vector_free(io_err_pathvec);
|
||||||
|
io_err_pathvec = NULL;
|
||||||
|
out:
|
||||||
|
@@ -252,7 +250,7 @@ static int enqueue_io_err_stat_by_path(struct path *path)
|
||||||
|
goto free_ioerr_path;
|
||||||
|
pthread_mutex_lock(&io_err_pathvec_lock);
|
||||||
|
if (!vector_alloc_slot(io_err_pathvec))
|
||||||
|
- goto unlock_destroy;
|
||||||
|
+ goto unlock_pathvec;
|
||||||
|
vector_set_slot(io_err_pathvec, p);
|
||||||
|
pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||||
|
|
||||||
|
@@ -260,9 +258,8 @@ static int enqueue_io_err_stat_by_path(struct path *path)
|
||||||
|
path->mpp->alias, path->dev);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
-unlock_destroy:
|
||||||
|
+unlock_pathvec:
|
||||||
|
pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||||
|
- destroy_directio_ctx(p);
|
||||||
|
free_ioerr_path:
|
||||||
|
free_io_err_stat_path(p);
|
||||||
|
|
||||||
|
@@ -647,7 +644,6 @@ static void service_paths(void)
|
||||||
|
vector_foreach_slot_backwards(tmp_pathvec, pp, i) {
|
||||||
|
end_io_err_stat(pp);
|
||||||
|
vector_del_slot(tmp_pathvec, i);
|
||||||
|
- destroy_directio_ctx(pp);
|
||||||
|
free_io_err_stat_path(pp);
|
||||||
|
}
|
||||||
|
vector_reset(tmp_pathvec);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,110 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 18 Jan 2021 22:46:04 -0600
|
||||||
|
Subject: [PATCH] multipathd: cleanup logging for marginal paths
|
||||||
|
|
||||||
|
io_err_stat logged at level 2 whenever it enqueued a path to check,
|
||||||
|
which could happen multiple times while a path was marginal. On the
|
||||||
|
other hand if marginal_pathgroups wasn't set, multipathd didn't log when
|
||||||
|
paths were set to marginal. Now io_err_stat only logs at level 2 when
|
||||||
|
something unexpected happens, but multipathd will always log when a
|
||||||
|
path switches its marginal state.
|
||||||
|
|
||||||
|
This patch also fixes an issue where paths in the delayed state could
|
||||||
|
get set to the pending state if they could not be checked in time.
|
||||||
|
Aside from going against the idea the paths should not be set to pending
|
||||||
|
if they already have a valid state, this caused multipathd to log a
|
||||||
|
message whenever the path state switched to from delayed to pending and
|
||||||
|
then back.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
---
|
||||||
|
libmultipath/io_err_stat.c | 7 +++----
|
||||||
|
multipathd/main.c | 20 +++++++++++++-------
|
||||||
|
2 files changed, 16 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
|
||||||
|
index bf1d3910..ee711f7f 100644
|
||||||
|
--- a/libmultipath/io_err_stat.c
|
||||||
|
+++ b/libmultipath/io_err_stat.c
|
||||||
|
@@ -254,7 +254,7 @@ static int enqueue_io_err_stat_by_path(struct path *path)
|
||||||
|
vector_set_slot(io_err_pathvec, p);
|
||||||
|
pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||||
|
|
||||||
|
- io_err_stat_log(2, "%s: enqueue path %s to check",
|
||||||
|
+ io_err_stat_log(3, "%s: enqueue path %s to check",
|
||||||
|
path->mpp->alias, path->dev);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
@@ -353,7 +353,7 @@ int need_io_err_check(struct path *pp)
|
||||||
|
if (uatomic_read(&io_err_thread_running) == 0)
|
||||||
|
return 0;
|
||||||
|
if (count_active_paths(pp->mpp) <= 0) {
|
||||||
|
- io_err_stat_log(2, "%s: recover path early", pp->dev);
|
||||||
|
+ io_err_stat_log(2, "%s: no paths. recovering early", pp->dev);
|
||||||
|
goto recover;
|
||||||
|
}
|
||||||
|
if (pp->io_err_pathfail_cnt != PATH_IO_ERR_WAITING_TO_CHECK)
|
||||||
|
@@ -371,8 +371,7 @@ int need_io_err_check(struct path *pp)
|
||||||
|
* Or else, return 1 to set path state to PATH_SHAKY
|
||||||
|
*/
|
||||||
|
if (r == 1) {
|
||||||
|
- io_err_stat_log(3, "%s: enqueue fails, to recover",
|
||||||
|
- pp->dev);
|
||||||
|
+ io_err_stat_log(2, "%s: enqueue failed. recovering early", pp->dev);
|
||||||
|
goto recover;
|
||||||
|
} else
|
||||||
|
pp->io_err_pathfail_cnt = PATH_IO_ERR_IN_CHECKING;
|
||||||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
|
index 1d0579e9..cc1aeea2 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -2041,8 +2041,8 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||||
|
pathinfo(pp, conf, 0);
|
||||||
|
pthread_cleanup_pop(1);
|
||||||
|
return 1;
|
||||||
|
- } else if ((newstate != PATH_UP && newstate != PATH_GHOST) &&
|
||||||
|
- (pp->state == PATH_DELAYED)) {
|
||||||
|
+ } else if ((newstate != PATH_UP && newstate != PATH_GHOST &&
|
||||||
|
+ newstate != PATH_PENDING) && (pp->state == PATH_DELAYED)) {
|
||||||
|
/* If path state become failed again cancel path delay state */
|
||||||
|
pp->state = newstate;
|
||||||
|
return 1;
|
||||||
|
@@ -2104,8 +2104,9 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||||
|
if ((newstate == PATH_UP || newstate == PATH_GHOST) &&
|
||||||
|
(san_path_check_enabled(pp->mpp) ||
|
||||||
|
marginal_path_check_enabled(pp->mpp))) {
|
||||||
|
- int was_marginal = pp->marginal;
|
||||||
|
if (should_skip_path(pp)) {
|
||||||
|
+ if (!pp->marginal && pp->state != PATH_DELAYED)
|
||||||
|
+ condlog(2, "%s: path is now marginal", pp->dev);
|
||||||
|
if (!marginal_pathgroups) {
|
||||||
|
if (marginal_path_check_enabled(pp->mpp))
|
||||||
|
/* to reschedule as soon as possible,
|
||||||
|
@@ -2115,13 +2116,18 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||||
|
pp->state = PATH_DELAYED;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
- if (!was_marginal) {
|
||||||
|
+ if (!pp->marginal) {
|
||||||
|
pp->marginal = 1;
|
||||||
|
marginal_changed = 1;
|
||||||
|
}
|
||||||
|
- } else if (marginal_pathgroups && was_marginal) {
|
||||||
|
- pp->marginal = 0;
|
||||||
|
- marginal_changed = 1;
|
||||||
|
+ } else {
|
||||||
|
+ if (pp->marginal || pp->state == PATH_DELAYED)
|
||||||
|
+ condlog(2, "%s: path is no longer marginal",
|
||||||
|
+ pp->dev);
|
||||||
|
+ if (marginal_pathgroups && pp->marginal) {
|
||||||
|
+ pp->marginal = 0;
|
||||||
|
+ marginal_changed = 1;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,277 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 25 Jan 2021 23:31:04 -0600
|
||||||
|
Subject: [PATCH] libmpathpersist: fix thread safety of default functions
|
||||||
|
|
||||||
|
commit a839e39e ("libmpathpersist: factor out initialization and
|
||||||
|
teardown") made mpath_presistent_reserve_{in,out} use share variables
|
||||||
|
for curmp and pathvec. There are users of this library that call these
|
||||||
|
functions in a multi-threaded process, and this change causes their
|
||||||
|
application to crash. config and udev are also shared variables, but
|
||||||
|
libmpathpersist doesn't write to the config in
|
||||||
|
mpath_presistent_reserve_{in,out}, and looking into the libudev code, I
|
||||||
|
don't see any place where libmpathpersist uses the udev object in a way
|
||||||
|
that isn't thread-safe.
|
||||||
|
|
||||||
|
This patch makes mpath_presistent_reserve_{in,out} go back to using
|
||||||
|
local variables for curmp and pathvec, so that multiple threads won't
|
||||||
|
be operating on these variables at the same time.
|
||||||
|
|
||||||
|
Fixes: a839e39e ("libmpathpersist: factor out initialization and teardown")
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
---
|
||||||
|
libmpathpersist/mpath_persist.c | 116 +++++++++++++++++++++-----------
|
||||||
|
libmpathpersist/mpath_persist.h | 24 +++++--
|
||||||
|
2 files changed, 94 insertions(+), 46 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||||
|
index a01dfb0b..07a5f17f 100644
|
||||||
|
--- a/libmpathpersist/mpath_persist.c
|
||||||
|
+++ b/libmpathpersist/mpath_persist.c
|
||||||
|
@@ -147,72 +147,60 @@ mpath_prin_activepath (struct multipath *mpp, int rq_servact,
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int mpath_persistent_reserve_in (int fd, int rq_servact,
|
||||||
|
- struct prin_resp *resp, int noisy, int verbose)
|
||||||
|
-{
|
||||||
|
- int ret = mpath_persistent_reserve_init_vecs(verbose);
|
||||||
|
-
|
||||||
|
- if (ret != MPATH_PR_SUCCESS)
|
||||||
|
- return ret;
|
||||||
|
- ret = __mpath_persistent_reserve_in(fd, rq_servact, resp, noisy);
|
||||||
|
- mpath_persistent_reserve_free_vecs();
|
||||||
|
- return ret;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||||
|
- unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, int verbose)
|
||||||
|
-{
|
||||||
|
- int ret = mpath_persistent_reserve_init_vecs(verbose);
|
||||||
|
-
|
||||||
|
- if (ret != MPATH_PR_SUCCESS)
|
||||||
|
- return ret;
|
||||||
|
- ret = __mpath_persistent_reserve_out(fd, rq_servact, rq_scope, rq_type,
|
||||||
|
- paramp, noisy);
|
||||||
|
- mpath_persistent_reserve_free_vecs();
|
||||||
|
- return ret;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static vector curmp;
|
||||||
|
static vector pathvec;
|
||||||
|
|
||||||
|
-void mpath_persistent_reserve_free_vecs(void)
|
||||||
|
+static void __mpath_persistent_reserve_free_vecs(vector curmp, vector pathvec)
|
||||||
|
{
|
||||||
|
free_multipathvec(curmp, KEEP_PATHS);
|
||||||
|
free_pathvec(pathvec, FREE_PATHS);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void mpath_persistent_reserve_free_vecs(void)
|
||||||
|
+{
|
||||||
|
+ __mpath_persistent_reserve_free_vecs(curmp, pathvec);
|
||||||
|
curmp = pathvec = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int mpath_persistent_reserve_init_vecs(int verbose)
|
||||||
|
+static int __mpath_persistent_reserve_init_vecs(vector *curmp_p,
|
||||||
|
+ vector *pathvec_p, int verbose)
|
||||||
|
{
|
||||||
|
struct config *conf = get_multipath_config();
|
||||||
|
|
||||||
|
conf->verbosity = verbose;
|
||||||
|
put_multipath_config(conf);
|
||||||
|
|
||||||
|
- if (curmp)
|
||||||
|
+ if (*curmp_p)
|
||||||
|
return MPATH_PR_SUCCESS;
|
||||||
|
/*
|
||||||
|
* allocate core vectors to store paths and multipaths
|
||||||
|
*/
|
||||||
|
- curmp = vector_alloc ();
|
||||||
|
- pathvec = vector_alloc ();
|
||||||
|
+ *curmp_p = vector_alloc ();
|
||||||
|
+ *pathvec_p = vector_alloc ();
|
||||||
|
|
||||||
|
- if (!curmp || !pathvec){
|
||||||
|
+ if (!*curmp_p || !*pathvec_p){
|
||||||
|
condlog (0, "vector allocation failed.");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (dm_get_maps(curmp))
|
||||||
|
+ if (dm_get_maps(*curmp_p))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return MPATH_PR_SUCCESS;
|
||||||
|
|
||||||
|
err:
|
||||||
|
- mpath_persistent_reserve_free_vecs();
|
||||||
|
+ __mpath_persistent_reserve_free_vecs(*curmp_p, *pathvec_p);
|
||||||
|
+ *curmp_p = *pathvec_p = NULL;
|
||||||
|
return MPATH_PR_DMMP_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int mpath_get_map(int fd, char **palias, struct multipath **pmpp)
|
||||||
|
+int mpath_persistent_reserve_init_vecs(int verbose)
|
||||||
|
+{
|
||||||
|
+ return __mpath_persistent_reserve_init_vecs(&curmp, &pathvec, verbose);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int mpath_get_map(vector curmp, vector pathvec, int fd, char **palias,
|
||||||
|
+ struct multipath **pmpp)
|
||||||
|
{
|
||||||
|
int ret = MPATH_PR_DMMP_ERROR;
|
||||||
|
struct stat info;
|
||||||
|
@@ -272,13 +260,13 @@ out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int __mpath_persistent_reserve_in (int fd, int rq_servact,
|
||||||
|
- struct prin_resp *resp, int noisy)
|
||||||
|
+static int do_mpath_persistent_reserve_in (vector curmp, vector pathvec,
|
||||||
|
+ int fd, int rq_servact, struct prin_resp *resp, int noisy)
|
||||||
|
{
|
||||||
|
struct multipath *mpp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
- ret = mpath_get_map(fd, NULL, &mpp);
|
||||||
|
+ ret = mpath_get_map(curmp, pathvec, fd, NULL, &mpp);
|
||||||
|
if (ret != MPATH_PR_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
@@ -287,8 +275,17 @@ int __mpath_persistent_reserve_in (int fd, int rq_servact,
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||||
|
- unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy)
|
||||||
|
+
|
||||||
|
+int __mpath_persistent_reserve_in (int fd, int rq_servact,
|
||||||
|
+ struct prin_resp *resp, int noisy)
|
||||||
|
+{
|
||||||
|
+ return do_mpath_persistent_reserve_in(curmp, pathvec, fd, rq_servact,
|
||||||
|
+ resp, noisy);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd,
|
||||||
|
+ int rq_servact, int rq_scope, unsigned int rq_type,
|
||||||
|
+ struct prout_param_descriptor *paramp, int noisy)
|
||||||
|
{
|
||||||
|
struct multipath *mpp;
|
||||||
|
char *alias;
|
||||||
|
@@ -296,7 +293,7 @@ int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||||
|
uint64_t prkey;
|
||||||
|
struct config *conf;
|
||||||
|
|
||||||
|
- ret = mpath_get_map(fd, &alias, &mpp);
|
||||||
|
+ ret = mpath_get_map(curmp, pathvec, fd, &alias, &mpp);
|
||||||
|
if (ret != MPATH_PR_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
@@ -366,6 +363,45 @@ out1:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+
|
||||||
|
+int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||||
|
+ unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy)
|
||||||
|
+{
|
||||||
|
+ return do_mpath_persistent_reserve_out(curmp, pathvec, fd, rq_servact,
|
||||||
|
+ rq_scope, rq_type, paramp,
|
||||||
|
+ noisy);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int mpath_persistent_reserve_in (int fd, int rq_servact,
|
||||||
|
+ struct prin_resp *resp, int noisy, int verbose)
|
||||||
|
+{
|
||||||
|
+ vector curmp = NULL, pathvec;
|
||||||
|
+ int ret = __mpath_persistent_reserve_init_vecs(&curmp, &pathvec,
|
||||||
|
+ verbose);
|
||||||
|
+
|
||||||
|
+ if (ret != MPATH_PR_SUCCESS)
|
||||||
|
+ return ret;
|
||||||
|
+ ret = do_mpath_persistent_reserve_in(curmp, pathvec, fd, rq_servact,
|
||||||
|
+ resp, noisy);
|
||||||
|
+ __mpath_persistent_reserve_free_vecs(curmp, pathvec);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||||
|
+ unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, int verbose)
|
||||||
|
+{
|
||||||
|
+ vector curmp = NULL, pathvec;
|
||||||
|
+ int ret = __mpath_persistent_reserve_init_vecs(&curmp, &pathvec,
|
||||||
|
+ verbose);
|
||||||
|
+
|
||||||
|
+ if (ret != MPATH_PR_SUCCESS)
|
||||||
|
+ return ret;
|
||||||
|
+ ret = do_mpath_persistent_reserve_out(curmp, pathvec, fd, rq_servact,
|
||||||
|
+ rq_scope, rq_type, paramp, noisy);
|
||||||
|
+ __mpath_persistent_reserve_free_vecs(curmp, pathvec);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int
|
||||||
|
get_mpvec (vector curmp, vector pathvec, char * refwwid)
|
||||||
|
{
|
||||||
|
diff --git a/libmpathpersist/mpath_persist.h b/libmpathpersist/mpath_persist.h
|
||||||
|
index 7cf4faf9..0e4e0e53 100644
|
||||||
|
--- a/libmpathpersist/mpath_persist.h
|
||||||
|
+++ b/libmpathpersist/mpath_persist.h
|
||||||
|
@@ -215,9 +215,13 @@ extern int mpath_persistent_reserve_in (int fd, int rq_servact, struct prin_resp
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DESCRIPTION :
|
||||||
|
- * This function is like mpath_persistent_reserve_in(), except that it doesn't call
|
||||||
|
- * mpath_persistent_reserve_init_vecs() and mpath_persistent_reserve_free_vecs()
|
||||||
|
- * before and after the actual PR call.
|
||||||
|
+ * This function is like mpath_persistent_reserve_in(), except that it
|
||||||
|
+ * requires mpath_persistent_reserve_init_vecs() to be called before the
|
||||||
|
+ * PR call to set up internal variables. These must later be cleanup up
|
||||||
|
+ * by calling mpath_persistent_reserve_free_vecs().
|
||||||
|
+ *
|
||||||
|
+ * RESTRICTIONS:
|
||||||
|
+ * This function uses static internal variables, and is not thread-safe.
|
||||||
|
*/
|
||||||
|
extern int __mpath_persistent_reserve_in(int fd, int rq_servact,
|
||||||
|
struct prin_resp *resp, int noisy);
|
||||||
|
@@ -249,9 +253,13 @@ extern int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||||
|
int verbose);
|
||||||
|
/*
|
||||||
|
* DESCRIPTION :
|
||||||
|
- * This function is like mpath_persistent_reserve_out(), except that it doesn't call
|
||||||
|
- * mpath_persistent_reserve_init_vecs() and mpath_persistent_reserve_free_vecs()
|
||||||
|
- * before and after the actual PR call.
|
||||||
|
+ * This function is like mpath_persistent_reserve_out(), except that it
|
||||||
|
+ * requires mpath_persistent_reserve_init_vecs() to be called before the
|
||||||
|
+ * PR call to set up internal variables. These must later be cleanup up
|
||||||
|
+ * by calling mpath_persistent_reserve_free_vecs().
|
||||||
|
+ *
|
||||||
|
+ * RESTRICTIONS:
|
||||||
|
+ * This function uses static internal variables, and is not thread-safe.
|
||||||
|
*/
|
||||||
|
extern int __mpath_persistent_reserve_out( int fd, int rq_servact, int rq_scope,
|
||||||
|
unsigned int rq_type, struct prout_param_descriptor *paramp,
|
||||||
|
@@ -265,6 +273,7 @@ extern int __mpath_persistent_reserve_out( int fd, int rq_servact, int rq_scope,
|
||||||
|
* @verbose: Set verbosity level. Input argument. value:0 to 3. 0->disabled, 3->Max verbose
|
||||||
|
*
|
||||||
|
* RESTRICTIONS:
|
||||||
|
+ * This function uses static internal variables, and is not thread-safe.
|
||||||
|
*
|
||||||
|
* RETURNS: MPATH_PR_SUCCESS if successful else returns any of the status specified
|
||||||
|
* above in RETURN_STATUS.
|
||||||
|
@@ -275,6 +284,9 @@ int mpath_persistent_reserve_init_vecs(int verbose);
|
||||||
|
* DESCRIPTION :
|
||||||
|
* This function frees data structures allocated by
|
||||||
|
* mpath_persistent_reserve_init_vecs().
|
||||||
|
+ *
|
||||||
|
+ * RESTRICTIONS:
|
||||||
|
+ * This function uses static internal variables, and is not thread-safe.
|
||||||
|
*/
|
||||||
|
void mpath_persistent_reserve_free_vecs(void);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,61 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 9 Feb 2021 17:16:04 -0600
|
||||||
|
Subject: [PATCH] kpartx: free loop device after listing partitions
|
||||||
|
|
||||||
|
If "kpartx -l" is run on a file that doesn't already have a loop device
|
||||||
|
associated with it, it will create a loop device to run the command.
|
||||||
|
Starting with da59d15c6 ("Fix loopback file with kpartx -av"), it will
|
||||||
|
not free the loop device when exitting. This is because it checks if the
|
||||||
|
the file it stat()ed is a regular file, before freeing the loop device.
|
||||||
|
However, after da59d15c6, stat() is rerun on the loop device itself, so
|
||||||
|
the check fails. There is no need to check this, if loopcreated is
|
||||||
|
true, then the file will be a kpartx created loop device, and should be
|
||||||
|
freed.
|
||||||
|
|
||||||
|
Also, keep kpartx from printing that the loop device has been removed
|
||||||
|
at normal verbosity.
|
||||||
|
|
||||||
|
Fixes: da59d15c6 ("Fix loopback file with kpartx -av")
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
kpartx/kpartx.c | 9 +++++----
|
||||||
|
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c
|
||||||
|
index 653ce0c8..a337a07b 100644
|
||||||
|
--- a/kpartx/kpartx.c
|
||||||
|
+++ b/kpartx/kpartx.c
|
||||||
|
@@ -407,7 +407,7 @@ main(int argc, char **argv){
|
||||||
|
fprintf(stderr, "can't del loop : %s\n",
|
||||||
|
loopdev);
|
||||||
|
r = 1;
|
||||||
|
- } else
|
||||||
|
+ } else if (verbose)
|
||||||
|
fprintf(stderr, "loop deleted : %s\n", loopdev);
|
||||||
|
}
|
||||||
|
goto end;
|
||||||
|
@@ -649,16 +649,17 @@ main(int argc, char **argv){
|
||||||
|
if (n > 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
- if (what == LIST && loopcreated && S_ISREG (buf.st_mode)) {
|
||||||
|
+ if (what == LIST && loopcreated) {
|
||||||
|
if (fd != -1)
|
||||||
|
close(fd);
|
||||||
|
if (del_loop(device)) {
|
||||||
|
if (verbose)
|
||||||
|
- printf("can't del loop : %s\n",
|
||||||
|
+ fprintf(stderr, "can't del loop : %s\n",
|
||||||
|
device);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
- printf("loop deleted : %s\n", device);
|
||||||
|
+ if (verbose)
|
||||||
|
+ fprintf(stderr, "loop deleted : %s\n", device);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,134 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 10 Feb 2021 15:42:42 -0600
|
||||||
|
Subject: [PATCH] RH: fix find_multipaths in mpathconf
|
||||||
|
|
||||||
|
mpathconf wasn't correctly dealing with the new rhel-8 values for
|
||||||
|
find_multipaths
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
multipath/mpathconf | 38 +++++++++++++++++++-------------------
|
||||||
|
multipath/mpathconf.8 | 14 +++++++-------
|
||||||
|
2 files changed, 26 insertions(+), 26 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/multipath/mpathconf b/multipath/mpathconf
|
||||||
|
index f34003c9..2f4f3eaf 100644
|
||||||
|
--- a/multipath/mpathconf
|
||||||
|
+++ b/multipath/mpathconf
|
||||||
|
@@ -54,7 +54,7 @@ function usage
|
||||||
|
echo "Disable: --disable"
|
||||||
|
echo "Only allow certain wwids (instead of enable): --allow <WWID>"
|
||||||
|
echo "Set user_friendly_names (Default y): --user_friendly_names <y|n>"
|
||||||
|
- echo "Set find_multipaths (Default y): --find_multipaths <y|n>"
|
||||||
|
+ echo "Set find_multipaths (Default y): --find_multipaths <yes|no|strict|greedy|smart>"
|
||||||
|
echo "Set default property blacklist (Default y): --property_blacklist <y|n>"
|
||||||
|
echo "Set enable_foreign to show foreign devices (Default n): --enable_foreign <y|n>"
|
||||||
|
echo "Load the dm-multipath modules on enable (Default y): --with_module <y|n>"
|
||||||
|
@@ -224,8 +224,12 @@ function validate_args
|
||||||
|
echo "--user_friendly_names must be either 'y' or 'n'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
- if [ -n "$FIND" ] && [ "$FIND" != "y" -a "$FIND" != "n" ]; then
|
||||||
|
- echo "--find_multipaths must be either 'y' or 'n'"
|
||||||
|
+ if [ "$FIND" = "y" ]; then
|
||||||
|
+ FIND="yes"
|
||||||
|
+ elif [ "$FIND" = "n" ]; then
|
||||||
|
+ FIND="no"
|
||||||
|
+ elif [ -n "$FIND" ] && [ "$FIND" != "yes" -a "$FIND" != "no" -a "$FIND" != "strict" -a "$FIND" != "greedy" -a "$FIND" != "smart" ]; then
|
||||||
|
+ echo "--find_multipaths must be one of 'yes' 'no' 'strict' 'greedy' or 'smart'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ -n "$PROPERTY" ] && [ "$PROPERTY" != "y" -a "$PROPERTY" != "n" ]; then
|
||||||
|
@@ -327,10 +331,11 @@ if [ "$HAVE_BLACKLIST" = "1" ]; then
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$HAVE_DEFAULTS" = "1" ]; then
|
||||||
|
- if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)" ; then
|
||||||
|
- HAVE_FIND=1
|
||||||
|
- elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)" ; then
|
||||||
|
- HAVE_FIND=0
|
||||||
|
+ HAVE_FIND=`sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | sed -n 's/^[[:blank:]]*find_multipaths[[:blank:]]*\([^[:blank:]]*\).*$/\1/p' | sed -n 1p`
|
||||||
|
+ if [ "$HAVE_FIND" = "1" ]; then
|
||||||
|
+ HAVE_FIND="yes"
|
||||||
|
+ elif [ "$HAVE_FIND" = "0" ]; then
|
||||||
|
+ HAVE_FIND="no"
|
||||||
|
fi
|
||||||
|
if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)" ; then
|
||||||
|
HAVE_FRIENDLY=1
|
||||||
|
@@ -360,10 +365,10 @@ if [ -n "$SHOW_STATUS" ]; then
|
||||||
|
else
|
||||||
|
echo "multipath is disabled"
|
||||||
|
fi
|
||||||
|
- if [ -z "$HAVE_FIND" -o "$HAVE_FIND" = 0 ]; then
|
||||||
|
- echo "find_multipaths is disabled"
|
||||||
|
+ if [ -z "$HAVE_FIND" ]; then
|
||||||
|
+ echo "find_multipaths is no"
|
||||||
|
else
|
||||||
|
- echo "find_multipaths is enabled"
|
||||||
|
+ echo "find_multipaths is $HAVE_FIND"
|
||||||
|
fi
|
||||||
|
if [ -z "$HAVE_FRIENDLY" -o "$HAVE_FRIENDLY" = 0 ]; then
|
||||||
|
echo "user_friendly_names is disabled"
|
||||||
|
@@ -455,19 +460,14 @@ elif [ "$ENABLE" = 0 ]; then
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
-if [ "$FIND" = "n" ]; then
|
||||||
|
- if [ "$HAVE_FIND" = 1 ]; then
|
||||||
|
- sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)/ find_multipaths no/' $TMPFILE
|
||||||
|
- CHANGED_CONFIG=1
|
||||||
|
- fi
|
||||||
|
-elif [ "$FIND" = "y" ]; then
|
||||||
|
+if [ -n "$FIND" ]; then
|
||||||
|
if [ -z "$HAVE_FIND" ]; then
|
||||||
|
sed -i '/^defaults[[:space:]]*{/ a\
|
||||||
|
- find_multipaths yes
|
||||||
|
+ find_multipaths '"$FIND"'
|
||||||
|
' $TMPFILE
|
||||||
|
CHANGED_CONFIG=1
|
||||||
|
- elif [ "$HAVE_FIND" = 0 ]; then
|
||||||
|
- sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)/ find_multipaths yes/' $TMPFILE
|
||||||
|
+ elif [ "$FIND" != "$HAVE_FIND" ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:blank:]]*find_multipaths[[:blank:]]*[^[:blank:]]*/ find_multipaths '"$FIND"'/' $TMPFILE
|
||||||
|
CHANGED_CONFIG=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8
|
||||||
|
index b82961d6..83515eb4 100644
|
||||||
|
--- a/multipath/mpathconf.8
|
||||||
|
+++ b/multipath/mpathconf.8
|
||||||
|
@@ -38,9 +38,9 @@ If
|
||||||
|
already exists, mpathconf will edit it. If it does not exist, mpathconf will
|
||||||
|
create a default file with
|
||||||
|
.B user_friendly_names
|
||||||
|
-and
|
||||||
|
+set and
|
||||||
|
.B find_multipaths
|
||||||
|
-set. To disable these, use the
|
||||||
|
+set to \fByes\fP. To disable these, use the
|
||||||
|
.B --user_friendly_names n
|
||||||
|
and
|
||||||
|
.B --find_multipaths n
|
||||||
|
@@ -77,13 +77,13 @@ to the
|
||||||
|
defaults section. If set to \fBn\fP, this removes the line, if present. This
|
||||||
|
command can be used along with any other command.
|
||||||
|
.TP
|
||||||
|
-.B --find_multipaths\fP { \fBy\fP | \fBn\fP }
|
||||||
|
-If set to \fBy\fP, this adds the line
|
||||||
|
-.B find_multipaths yes
|
||||||
|
+.B --find_multipaths\fP { \fByes\fP | \fBno\fP | \fBstrict\fP | \fBgreedy\fP | \fBsmart\fP }
|
||||||
|
+If set to \fB<value>\fP, this adds the line
|
||||||
|
+.B find_multipaths <value>
|
||||||
|
to the
|
||||||
|
.B /etc/multipath.conf
|
||||||
|
-defaults section. If set to \fBn\fP, this removes the line, if present. This
|
||||||
|
-command can be used along with any other command.
|
||||||
|
+defaults section. This command can be used along with any other command.
|
||||||
|
+\fBy\fP and \fBn\fP can be used instead of \fByes\fP and \fBno\fP.
|
||||||
|
.TP
|
||||||
|
.B --property_blacklist \fP { \fBy\fP | \fBn\fP }
|
||||||
|
If set to \fBy\fP, this adds the line
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,45 @@
|
|||||||
|
From 7a7b96246b84ccf533a6f4dc0424830792fdb96a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Fri, 3 Jul 2020 15:17:09 +0200
|
||||||
|
Subject: [PATCH] libmultipath: select_action(): don't drop map if alias
|
||||||
|
clashes
|
||||||
|
|
||||||
|
If for a given map, if we find that the requested alias is already
|
||||||
|
used by a map with different WWID, while the map's own WWID is
|
||||||
|
not used yet, give up the alias and use the WWID instead. This
|
||||||
|
is safer than trying to destroy the existing map, which is likely
|
||||||
|
to fail.
|
||||||
|
|
||||||
|
This allows us to make use const for the "curmp" parameter.
|
||||||
|
|
||||||
|
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/configure.c | 11 ++++++-----
|
||||||
|
1 file changed, 6 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
||||||
|
index b7113291..2e8f34f9 100644
|
||||||
|
--- a/libmultipath/configure.c
|
||||||
|
+++ b/libmultipath/configure.c
|
||||||
|
@@ -690,12 +690,13 @@ select_action (struct multipath * mpp, vector curmp, int force_reload)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cmpp) {
|
||||||
|
- condlog(2, "%s: remove (wwid changed)", mpp->alias);
|
||||||
|
- dm_flush_map(mpp->alias);
|
||||||
|
- strlcpy(cmpp_by_name->wwid, mpp->wwid, WWID_SIZE);
|
||||||
|
- drop_multipath(curmp, cmpp_by_name->wwid, KEEP_PATHS);
|
||||||
|
+ condlog(1, "%s: can't use alias \"%s\" used by %s, falling back to WWID",
|
||||||
|
+ mpp->wwid, mpp->alias, cmpp_by_name->wwid);
|
||||||
|
+ /* We can do this because wwid wasn't found */
|
||||||
|
+ free(mpp->alias);
|
||||||
|
+ mpp->alias = strdup(mpp->wwid);
|
||||||
|
mpp->action = ACT_CREATE;
|
||||||
|
- condlog(3, "%s: set ACT_CREATE (map wwid change)",
|
||||||
|
+ condlog(3, "%s: set ACT_CREATE (map does not exist, name changed)",
|
||||||
|
mpp->alias);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,231 @@
|
|||||||
|
From e714eb26fddc8768a8de279d1de3ffedab35929e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Fri, 5 Mar 2021 21:40:57 -0600
|
||||||
|
Subject: [PATCH] libmultipath: check if user_friendly_name is in use
|
||||||
|
|
||||||
|
If there are multipath devices that have user_friendly_names but do not
|
||||||
|
have their bindings in the bindings_file, get_user_friendly_alias() can
|
||||||
|
currently give out those names again. This can result in an incorrect
|
||||||
|
entry in the bindings file, and a device that gets created with a WWID
|
||||||
|
alias instead of a user_friendly_name. This situation can happen after
|
||||||
|
the pivot root, if a multipath device is created in the initramfs. If
|
||||||
|
this device doesn't have a binding in the regular filesystem
|
||||||
|
bindings_file and a new multipath device is created before it can add
|
||||||
|
its binding, the new device can steal that user_friendly_name during
|
||||||
|
multipathd's initial configure.
|
||||||
|
|
||||||
|
To solve this, get_user_friendly_alias() now calls lookup_binding() with
|
||||||
|
a new paramter, telling it to check if the id it found is already in use
|
||||||
|
by a diffent device. If so, lookup_binding() will continue to check open
|
||||||
|
ids, until it finds one that it not currently in use by a dm device.
|
||||||
|
---
|
||||||
|
libmultipath/alias.c | 48 +++++++++++++++++++++++++++++++++++++++++---
|
||||||
|
tests/alias.c | 22 ++++++++++----------
|
||||||
|
2 files changed, 56 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
|
||||||
|
index 14401cae..01f737f4 100644
|
||||||
|
--- a/libmultipath/alias.c
|
||||||
|
+++ b/libmultipath/alias.c
|
||||||
|
@@ -17,6 +17,7 @@
|
||||||
|
#include "vector.h"
|
||||||
|
#include "checkers.h"
|
||||||
|
#include "structs.h"
|
||||||
|
+#include "devmapper.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -104,6 +105,28 @@ scan_devname(const char *alias, const char *prefix)
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+id_already_taken(int id, const char *prefix, const char *map_wwid)
|
||||||
|
+{
|
||||||
|
+ char alias[LINE_MAX];
|
||||||
|
+
|
||||||
|
+ if (format_devname(alias, id, LINE_MAX, prefix) < 0)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ if (dm_map_present(alias)) {
|
||||||
|
+ char wwid[WWID_SIZE];
|
||||||
|
+
|
||||||
|
+ /* If both the name and the wwid match, then it's fine.*/
|
||||||
|
+ if (dm_get_uuid(alias, wwid, sizeof(wwid)) == 0 &&
|
||||||
|
+ strncmp(map_wwid, wwid, sizeof(wwid)) == 0)
|
||||||
|
+ return 0;
|
||||||
|
+ condlog(3, "%s: alias '%s' already taken, but not in bindings file. reselecting alias", map_wwid, alias);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Returns: 0 if matching entry in WWIDs file found
|
||||||
|
* -1 if an error occurs
|
||||||
|
@@ -113,7 +136,7 @@ scan_devname(const char *alias, const char *prefix)
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
lookup_binding(FILE *f, const char *map_wwid, char **map_alias,
|
||||||
|
- const char *prefix)
|
||||||
|
+ const char *prefix, int check_if_taken)
|
||||||
|
{
|
||||||
|
char buf[LINE_MAX];
|
||||||
|
unsigned int line_nr = 0;
|
||||||
|
@@ -168,12 +191,31 @@ lookup_binding(FILE *f, const char *map_wwid, char **map_alias,
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ if (!prefix && check_if_taken)
|
||||||
|
+ id = -1;
|
||||||
|
if (id >= smallest_bigger_id) {
|
||||||
|
if (biggest_id < INT_MAX)
|
||||||
|
id = biggest_id + 1;
|
||||||
|
else
|
||||||
|
id = -1;
|
||||||
|
}
|
||||||
|
+ if (id > 0 && check_if_taken) {
|
||||||
|
+ while(id_already_taken(id, prefix, map_wwid)) {
|
||||||
|
+ if (id == INT_MAX) {
|
||||||
|
+ id = -1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ id++;
|
||||||
|
+ if (id == smallest_bigger_id) {
|
||||||
|
+ if (biggest_id == INT_MAX) {
|
||||||
|
+ id = -1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ if (biggest_id >= smallest_bigger_id)
|
||||||
|
+ id = biggest_id + 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
if (id < 0) {
|
||||||
|
condlog(0, "no more available user_friendly_names");
|
||||||
|
return -1;
|
||||||
|
@@ -316,7 +358,7 @@ use_existing_alias (const char *wwid, const char *file, const char *alias_old,
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- id = lookup_binding(f, wwid, &alias, NULL);
|
||||||
|
+ id = lookup_binding(f, wwid, &alias, NULL, 0);
|
||||||
|
if (alias) {
|
||||||
|
condlog(3, "Use existing binding [%s] for WWID [%s]",
|
||||||
|
alias, wwid);
|
||||||
|
@@ -373,7 +415,7 @@ get_user_friendly_alias(const char *wwid, const char *file, const char *prefix,
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- id = lookup_binding(f, wwid, &alias, prefix);
|
||||||
|
+ id = lookup_binding(f, wwid, &alias, prefix, 1);
|
||||||
|
if (id < 0) {
|
||||||
|
fclose(f);
|
||||||
|
return NULL;
|
||||||
|
diff --git a/tests/alias.c b/tests/alias.c
|
||||||
|
index 30414db0..ab1a9325 100644
|
||||||
|
--- a/tests/alias.c
|
||||||
|
+++ b/tests/alias.c
|
||||||
|
@@ -356,7 +356,7 @@ static void lb_empty(void **state)
|
||||||
|
|
||||||
|
will_return(__wrap_fgets, NULL);
|
||||||
|
expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n");
|
||||||
|
- rc = lookup_binding(NULL, "WWID0", &alias, NULL);
|
||||||
|
+ rc = lookup_binding(NULL, "WWID0", &alias, NULL, 0);
|
||||||
|
assert_int_equal(rc, 1);
|
||||||
|
assert_ptr_equal(alias, NULL);
|
||||||
|
}
|
||||||
|
@@ -369,7 +369,7 @@ static void lb_match_a(void **state)
|
||||||
|
will_return(__wrap_fgets, "MPATHa WWID0\n");
|
||||||
|
expect_condlog(3, "Found matching wwid [WWID0] in bindings file."
|
||||||
|
" Setting alias to MPATHa\n");
|
||||||
|
- rc = lookup_binding(NULL, "WWID0", &alias, "MPATH");
|
||||||
|
+ rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 0);
|
||||||
|
assert_int_equal(rc, 0);
|
||||||
|
assert_ptr_not_equal(alias, NULL);
|
||||||
|
assert_string_equal(alias, "MPATHa");
|
||||||
|
@@ -384,7 +384,7 @@ static void lb_nomatch_a(void **state)
|
||||||
|
will_return(__wrap_fgets, "MPATHa WWID0\n");
|
||||||
|
will_return(__wrap_fgets, NULL);
|
||||||
|
expect_condlog(3, "No matching wwid [WWID1] in bindings file.\n");
|
||||||
|
- rc = lookup_binding(NULL, "WWID1", &alias, "MPATH");
|
||||||
|
+ rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 0);
|
||||||
|
assert_int_equal(rc, 2);
|
||||||
|
assert_ptr_equal(alias, NULL);
|
||||||
|
}
|
||||||
|
@@ -398,7 +398,7 @@ static void lb_match_c(void **state)
|
||||||
|
will_return(__wrap_fgets, "MPATHc WWID1\n");
|
||||||
|
expect_condlog(3, "Found matching wwid [WWID1] in bindings file."
|
||||||
|
" Setting alias to MPATHc\n");
|
||||||
|
- rc = lookup_binding(NULL, "WWID1", &alias, "MPATH");
|
||||||
|
+ rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 0);
|
||||||
|
assert_int_equal(rc, 0);
|
||||||
|
assert_ptr_not_equal(alias, NULL);
|
||||||
|
assert_string_equal(alias, "MPATHc");
|
||||||
|
@@ -414,7 +414,7 @@ static void lb_nomatch_a_c(void **state)
|
||||||
|
will_return(__wrap_fgets, "MPATHc WWID1\n");
|
||||||
|
will_return(__wrap_fgets, NULL);
|
||||||
|
expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
|
||||||
|
- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH");
|
||||||
|
+ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
|
||||||
|
assert_int_equal(rc, 2);
|
||||||
|
assert_ptr_equal(alias, NULL);
|
||||||
|
}
|
||||||
|
@@ -428,7 +428,7 @@ static void lb_nomatch_c_a(void **state)
|
||||||
|
will_return(__wrap_fgets, "MPATHa WWID0\n");
|
||||||
|
will_return(__wrap_fgets, NULL);
|
||||||
|
expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
|
||||||
|
- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH");
|
||||||
|
+ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
|
||||||
|
assert_int_equal(rc, 2);
|
||||||
|
assert_ptr_equal(alias, NULL);
|
||||||
|
}
|
||||||
|
@@ -443,7 +443,7 @@ static void lb_nomatch_a_b(void **state)
|
||||||
|
will_return(__wrap_fgets, "MPATHb WWID1\n");
|
||||||
|
will_return(__wrap_fgets, NULL);
|
||||||
|
expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
|
||||||
|
- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH");
|
||||||
|
+ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
|
||||||
|
assert_int_equal(rc, 3);
|
||||||
|
assert_ptr_equal(alias, NULL);
|
||||||
|
}
|
||||||
|
@@ -459,7 +459,7 @@ static void lb_nomatch_a_b_bad(void **state)
|
||||||
|
will_return(__wrap_fgets, NULL);
|
||||||
|
expect_condlog(3, "Ignoring malformed line 3 in bindings file\n");
|
||||||
|
expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
|
||||||
|
- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH");
|
||||||
|
+ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
|
||||||
|
assert_int_equal(rc, 3);
|
||||||
|
assert_ptr_equal(alias, NULL);
|
||||||
|
}
|
||||||
|
@@ -474,7 +474,7 @@ static void lb_nomatch_b_a(void **state)
|
||||||
|
will_return(__wrap_fgets, "MPATHa WWID0\n");
|
||||||
|
will_return(__wrap_fgets, NULL);
|
||||||
|
expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
|
||||||
|
- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH");
|
||||||
|
+ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
|
||||||
|
assert_int_equal(rc, 27);
|
||||||
|
assert_ptr_equal(alias, NULL);
|
||||||
|
}
|
||||||
|
@@ -490,7 +490,7 @@ static void lb_nomatch_int_max(void **state)
|
||||||
|
will_return(__wrap_fgets, "MPATHa WWID0\n");
|
||||||
|
will_return(__wrap_fgets, NULL);
|
||||||
|
expect_condlog(0, "no more available user_friendly_names\n");
|
||||||
|
- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH");
|
||||||
|
+ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
|
||||||
|
assert_int_equal(rc, -1);
|
||||||
|
assert_ptr_equal(alias, NULL);
|
||||||
|
}
|
||||||
|
@@ -505,7 +505,7 @@ static void lb_nomatch_int_max_m1(void **state)
|
||||||
|
will_return(__wrap_fgets, "MPATHa WWID0\n");
|
||||||
|
will_return(__wrap_fgets, NULL);
|
||||||
|
expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
|
||||||
|
- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH");
|
||||||
|
+ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
|
||||||
|
assert_int_equal(rc, INT_MAX);
|
||||||
|
assert_ptr_equal(alias, NULL);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,129 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: lixiaokeng <lixiaokeng@huawei.com>
|
||||||
|
Date: Mon, 21 Sep 2020 12:00:39 +0800
|
||||||
|
Subject: [PATCH] libmultipath: check udev_device_get_* return value to avoid
|
||||||
|
segfault
|
||||||
|
|
||||||
|
The udev_device_get_* function may return NULL, and it will be
|
||||||
|
deregerenced in str* and sscanf func. We check the return value
|
||||||
|
to avoid segfault. Fix all.
|
||||||
|
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by:Lixiaokeng<lixiaokeng@huawei.com>
|
||||||
|
Signed-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
|
||||||
|
Signed-off-by: Linfeilong <linfeilong@huawei.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/configure.c | 4 +++-
|
||||||
|
libmultipath/discovery.c | 9 +++++++--
|
||||||
|
libmultipath/foreign/nvme.c | 10 +++++++---
|
||||||
|
3 files changed, 17 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
||||||
|
index 2e8f34f9..a6893d8d 100644
|
||||||
|
--- a/libmultipath/configure.c
|
||||||
|
+++ b/libmultipath/configure.c
|
||||||
|
@@ -511,6 +511,7 @@ static void trigger_partitions_udev_change(struct udev_device *dev,
|
||||||
|
{
|
||||||
|
struct udev_enumerate *part_enum;
|
||||||
|
struct udev_list_entry *item;
|
||||||
|
+ const char *devtype;
|
||||||
|
|
||||||
|
part_enum = udev_enumerate_new(udev);
|
||||||
|
if (!part_enum)
|
||||||
|
@@ -531,7 +532,8 @@ static void trigger_partitions_udev_change(struct udev_device *dev,
|
||||||
|
if (!part)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
- if (!strcmp("partition", udev_device_get_devtype(part))) {
|
||||||
|
+ devtype = udev_device_get_devtype(part);
|
||||||
|
+ if (devtype && !strcmp("partition", devtype)) {
|
||||||
|
condlog(4, "%s: triggering %s event for %s", __func__,
|
||||||
|
action, syspath);
|
||||||
|
sysfs_attr_set_value(part, "uevent", action, len);
|
||||||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
|
index a328aafa..74abf34d 100644
|
||||||
|
--- a/libmultipath/discovery.c
|
||||||
|
+++ b/libmultipath/discovery.c
|
||||||
|
@@ -353,7 +353,7 @@ sysfs_get_tgt_nodename(struct path *pp, char *node)
|
||||||
|
tgtdev = udev_device_get_parent(parent);
|
||||||
|
while (tgtdev) {
|
||||||
|
tgtname = udev_device_get_sysname(tgtdev);
|
||||||
|
- if (sscanf(tgtname, "end_device-%d:%d",
|
||||||
|
+ if (tgtname && sscanf(tgtname, "end_device-%d:%d",
|
||||||
|
&host, &tgtid) == 2)
|
||||||
|
break;
|
||||||
|
tgtdev = udev_device_get_parent(tgtdev);
|
||||||
|
@@ -386,7 +386,7 @@ sysfs_get_tgt_nodename(struct path *pp, char *node)
|
||||||
|
/* Check for FibreChannel */
|
||||||
|
tgtdev = udev_device_get_parent(parent);
|
||||||
|
value = udev_device_get_sysname(tgtdev);
|
||||||
|
- if (sscanf(value, "rport-%d:%d-%d",
|
||||||
|
+ if (value && sscanf(value, "rport-%d:%d-%d",
|
||||||
|
&host, &channel, &tgtid) == 3) {
|
||||||
|
tgtdev = udev_device_new_from_subsystem_sysname(udev,
|
||||||
|
"fc_remote_ports", value);
|
||||||
|
@@ -516,6 +516,9 @@ int sysfs_get_host_pci_name(const struct path *pp, char *pci_name)
|
||||||
|
*/
|
||||||
|
value = udev_device_get_sysname(parent);
|
||||||
|
|
||||||
|
+ if (!value)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
strncpy(pci_name, value, SLOT_NAME_SIZE);
|
||||||
|
udev_device_unref(hostdev);
|
||||||
|
return 0;
|
||||||
|
@@ -1518,6 +1521,8 @@ ccw_sysfs_pathinfo (struct path * pp, vector hwtable)
|
||||||
|
* host / bus / target / lun
|
||||||
|
*/
|
||||||
|
attr_path = udev_device_get_sysname(parent);
|
||||||
|
+ if (!attr_path)
|
||||||
|
+ return PATHINFO_FAILED;
|
||||||
|
pp->sg_id.lun = 0;
|
||||||
|
if (sscanf(attr_path, "%i.%i.%x",
|
||||||
|
&pp->sg_id.host_no,
|
||||||
|
diff --git a/libmultipath/foreign/nvme.c b/libmultipath/foreign/nvme.c
|
||||||
|
index 09cdddf0..5feb1e95 100644
|
||||||
|
--- a/libmultipath/foreign/nvme.c
|
||||||
|
+++ b/libmultipath/foreign/nvme.c
|
||||||
|
@@ -482,6 +482,7 @@ _find_path_by_syspath(struct nvme_map *map, const char *syspath)
|
||||||
|
struct nvme_pathgroup *pg;
|
||||||
|
char real[PATH_MAX];
|
||||||
|
const char *ppath;
|
||||||
|
+ const char *psyspath;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ppath = realpath(syspath, real);
|
||||||
|
@@ -493,8 +494,8 @@ _find_path_by_syspath(struct nvme_map *map, const char *syspath)
|
||||||
|
vector_foreach_slot(&map->pgvec, pg, i) {
|
||||||
|
struct nvme_path *path = nvme_pg_to_path(pg);
|
||||||
|
|
||||||
|
- if (!strcmp(ppath,
|
||||||
|
- udev_device_get_syspath(path->udev)))
|
||||||
|
+ psyspath = udev_device_get_syspath(path->udev);
|
||||||
|
+ if (psyspath && !strcmp(ppath, psyspath))
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
condlog(4, "%s: %s: %s not found", __func__, THIS, ppath);
|
||||||
|
@@ -538,6 +539,7 @@ struct udev_device *get_ctrl_blkdev(const struct context *ctx,
|
||||||
|
struct udev_list_entry *item;
|
||||||
|
struct udev_device *blkdev = NULL;
|
||||||
|
struct udev_enumerate *enm = udev_enumerate_new(ctx->udev);
|
||||||
|
+ const char *devtype;
|
||||||
|
|
||||||
|
if (enm == NULL)
|
||||||
|
return NULL;
|
||||||
|
@@ -562,7 +564,9 @@ struct udev_device *get_ctrl_blkdev(const struct context *ctx,
|
||||||
|
udev_list_entry_get_name(item));
|
||||||
|
if (tmp == NULL)
|
||||||
|
continue;
|
||||||
|
- if (!strcmp(udev_device_get_devtype(tmp), "disk")) {
|
||||||
|
+
|
||||||
|
+ devtype = udev_device_get_devtype(tmp);
|
||||||
|
+ if (devtype && !strcmp(devtype, "disk")) {
|
||||||
|
blkdev = tmp;
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,47 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 24 Feb 2021 00:33:20 -0600
|
||||||
|
Subject: [PATCH] libmultipath: cleanup code to strip wwid trailing spaces
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
---
|
||||||
|
libmultipath/discovery.c | 11 ++++-------
|
||||||
|
1 file changed, 4 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
|
index 74abf34d..126a70b3 100644
|
||||||
|
--- a/libmultipath/discovery.c
|
||||||
|
+++ b/libmultipath/discovery.c
|
||||||
|
@@ -2062,11 +2062,11 @@ int
|
||||||
|
get_uid (struct path * pp, int path_state, struct udev_device *udev,
|
||||||
|
int allow_fallback)
|
||||||
|
{
|
||||||
|
- char *c;
|
||||||
|
const char *origin = "unknown";
|
||||||
|
ssize_t len = 0;
|
||||||
|
struct config *conf;
|
||||||
|
int used_fallback = 0;
|
||||||
|
+ size_t i;
|
||||||
|
|
||||||
|
if (!pp->uid_attribute && !pp->getuid) {
|
||||||
|
conf = get_multipath_config();
|
||||||
|
@@ -2119,12 +2119,9 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev,
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
/* Strip any trailing blanks */
|
||||||
|
- c = strchr(pp->wwid, '\0');
|
||||||
|
- c--;
|
||||||
|
- while (c && c >= pp->wwid && *c == ' ') {
|
||||||
|
- *c = '\0';
|
||||||
|
- c--;
|
||||||
|
- }
|
||||||
|
+ for (i = strlen(pp->wwid); i > 0 && pp->wwid[i-1] == ' '; i--);
|
||||||
|
+ /* no-op */
|
||||||
|
+ pp->wwid[i] = '\0';
|
||||||
|
}
|
||||||
|
condlog((used_fallback)? 1 : 3, "%s: uid = %s (%s)", pp->dev,
|
||||||
|
*pp->wwid == '\0' ? "<empty>" : pp->wwid, origin);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,429 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 24 Feb 2021 00:33:22 -0600
|
||||||
|
Subject: [PATCH] multipathd: add recheck_wwid option to verify the path wwid
|
||||||
|
|
||||||
|
There are cases where the wwid of a path changes due to LUN remapping
|
||||||
|
without triggering uevent for the changed path. Multipathd has no method
|
||||||
|
for trying to catch these cases, and corruption has resulted because of
|
||||||
|
it.
|
||||||
|
|
||||||
|
In order to have a better chance at catching these cases, multipath now
|
||||||
|
has a recheck_wwid option. If this is set to "yes", when a failed path
|
||||||
|
has become active again, multipathd will recheck its wwid. If multipathd
|
||||||
|
notices that a path's wwid has changed, it will remove and re-add the
|
||||||
|
path, just like the existing wwid checking code for change events does.
|
||||||
|
In cases where the no uevent occurs, both the udev database entry and
|
||||||
|
sysfs will have the old wwid, so the only way to get a current wwid is
|
||||||
|
to ask the device directly. Currently multipath only has code to
|
||||||
|
directly get the wwid for scsi devices, so this option only effects scsi
|
||||||
|
devices, and they must be configured to be able to use the uid_fallback
|
||||||
|
methods. To make sure both the sysfs and udev database values are
|
||||||
|
updated, multipathd triggers a both a rescan of the device and a udev
|
||||||
|
add event.
|
||||||
|
|
||||||
|
Co-developed-by: Chongyun Wu <wucy11@chinatelecom.cn>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.c | 2 +
|
||||||
|
libmultipath/config.h | 2 +
|
||||||
|
libmultipath/configure.c | 4 +-
|
||||||
|
libmultipath/configure.h | 2 +
|
||||||
|
libmultipath/defaults.h | 1 +
|
||||||
|
libmultipath/dict.c | 11 ++++++
|
||||||
|
libmultipath/discovery.c | 3 +-
|
||||||
|
libmultipath/discovery.h | 1 +
|
||||||
|
libmultipath/propsel.c | 21 ++++++++++
|
||||||
|
libmultipath/propsel.h | 1 +
|
||||||
|
libmultipath/structs.h | 7 ++++
|
||||||
|
multipath/multipath.conf.5 | 14 +++++++
|
||||||
|
multipathd/cli_handlers.c | 9 +++++
|
||||||
|
multipathd/main.c | 78 ++++++++++++++++++++++++++++++++++++++
|
||||||
|
multipathd/main.h | 2 +
|
||||||
|
15 files changed, 155 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||||
|
index dd645f17..abbddaf1 100644
|
||||||
|
--- a/libmultipath/config.c
|
||||||
|
+++ b/libmultipath/config.c
|
||||||
|
@@ -371,6 +371,7 @@ merge_hwe (struct hwentry * dst, struct hwentry * src)
|
||||||
|
merge_num(max_sectors_kb);
|
||||||
|
merge_num(ghost_delay);
|
||||||
|
merge_num(all_tg_pt);
|
||||||
|
+ merge_num(recheck_wwid);
|
||||||
|
merge_num(vpd_vendor_id);
|
||||||
|
merge_num(san_path_err_threshold);
|
||||||
|
merge_num(san_path_err_forget_rate);
|
||||||
|
@@ -762,6 +763,7 @@ load_config (char * file)
|
||||||
|
conf->remove_retries = 0;
|
||||||
|
conf->ghost_delay = DEFAULT_GHOST_DELAY;
|
||||||
|
conf->all_tg_pt = DEFAULT_ALL_TG_PT;
|
||||||
|
+ conf->recheck_wwid = DEFAULT_RECHECK_WWID;
|
||||||
|
/*
|
||||||
|
* preload default hwtable
|
||||||
|
*/
|
||||||
|
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||||
|
index a22c1b4e..e2e3f143 100644
|
||||||
|
--- a/libmultipath/config.h
|
||||||
|
+++ b/libmultipath/config.h
|
||||||
|
@@ -84,6 +84,7 @@ struct hwentry {
|
||||||
|
int ghost_delay;
|
||||||
|
int all_tg_pt;
|
||||||
|
int vpd_vendor_id;
|
||||||
|
+ int recheck_wwid;
|
||||||
|
char * bl_product;
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -188,6 +189,7 @@ struct config {
|
||||||
|
int skip_delegate;
|
||||||
|
unsigned int version[3];
|
||||||
|
unsigned int sequence_nr;
|
||||||
|
+ int recheck_wwid;
|
||||||
|
|
||||||
|
char * multipath_dir;
|
||||||
|
char * selector;
|
||||||
|
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
||||||
|
index a6893d8d..f24d9283 100644
|
||||||
|
--- a/libmultipath/configure.c
|
||||||
|
+++ b/libmultipath/configure.c
|
||||||
|
@@ -506,8 +506,8 @@ trigger_udev_change(const struct multipath *mpp)
|
||||||
|
udev_device_unref(udd);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void trigger_partitions_udev_change(struct udev_device *dev,
|
||||||
|
- const char *action, int len)
|
||||||
|
+void trigger_partitions_udev_change(struct udev_device *dev,
|
||||||
|
+ const char *action, int len)
|
||||||
|
{
|
||||||
|
struct udev_enumerate *part_enum;
|
||||||
|
struct udev_list_entry *item;
|
||||||
|
diff --git a/libmultipath/configure.h b/libmultipath/configure.h
|
||||||
|
index 0e33bf40..81090dd4 100644
|
||||||
|
--- a/libmultipath/configure.h
|
||||||
|
+++ b/libmultipath/configure.h
|
||||||
|
@@ -57,3 +57,5 @@ int get_refwwid (enum mpath_cmds cmd, char * dev, enum devtypes dev_type,
|
||||||
|
int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh, int is_daemon);
|
||||||
|
struct udev_device *get_udev_device(const char *dev, enum devtypes dev_type);
|
||||||
|
void trigger_paths_udev_change(struct multipath *mpp, bool is_mpath);
|
||||||
|
+void trigger_partitions_udev_change(struct udev_device *dev, const char *action,
|
||||||
|
+ int len);
|
||||||
|
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
|
||||||
|
index 52fe05b9..f1cb000d 100644
|
||||||
|
--- a/libmultipath/defaults.h
|
||||||
|
+++ b/libmultipath/defaults.h
|
||||||
|
@@ -50,6 +50,7 @@
|
||||||
|
#define DEFAULT_FIND_MULTIPATHS_TIMEOUT -10
|
||||||
|
#define DEFAULT_UNKNOWN_FIND_MULTIPATHS_TIMEOUT 1
|
||||||
|
#define DEFAULT_ALL_TG_PT ALL_TG_PT_OFF
|
||||||
|
+#define DEFAULT_RECHECK_WWID RECHECK_WWID_OFF
|
||||||
|
/* Enable all foreign libraries by default */
|
||||||
|
#define DEFAULT_ENABLE_FOREIGN ""
|
||||||
|
|
||||||
|
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||||
|
index 8fd91d8c..13698b76 100644
|
||||||
|
--- a/libmultipath/dict.c
|
||||||
|
+++ b/libmultipath/dict.c
|
||||||
|
@@ -1413,6 +1413,14 @@ declare_hw_snprint(all_tg_pt, print_yes_no_undef)
|
||||||
|
declare_def_handler(marginal_pathgroups, set_yes_no)
|
||||||
|
declare_def_snprint(marginal_pathgroups, print_yes_no)
|
||||||
|
|
||||||
|
+declare_def_handler(recheck_wwid, set_yes_no_undef)
|
||||||
|
+declare_def_snprint_defint(recheck_wwid, print_yes_no_undef, DEFAULT_RECHECK_WWID)
|
||||||
|
+declare_ovr_handler(recheck_wwid, set_yes_no_undef)
|
||||||
|
+declare_ovr_snprint(recheck_wwid, print_yes_no_undef)
|
||||||
|
+declare_hw_handler(recheck_wwid, set_yes_no_undef)
|
||||||
|
+declare_hw_snprint(recheck_wwid, print_yes_no_undef)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
def_uxsock_timeout_handler(struct config *conf, vector strvec)
|
||||||
|
{
|
||||||
|
@@ -1824,6 +1832,7 @@ init_keywords(vector keywords)
|
||||||
|
install_keyword("enable_foreign", &def_enable_foreign_handler,
|
||||||
|
&snprint_def_enable_foreign);
|
||||||
|
install_keyword("marginal_pathgroups", &def_marginal_pathgroups_handler, &snprint_def_marginal_pathgroups);
|
||||||
|
+ install_keyword("recheck_wwid", &def_recheck_wwid_handler, &snprint_def_recheck_wwid);
|
||||||
|
__deprecated install_keyword("default_selector", &def_selector_handler, NULL);
|
||||||
|
__deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
|
||||||
|
__deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL);
|
||||||
|
@@ -1913,6 +1922,7 @@ init_keywords(vector keywords)
|
||||||
|
install_keyword("ghost_delay", &hw_ghost_delay_handler, &snprint_hw_ghost_delay);
|
||||||
|
install_keyword("all_tg_pt", &hw_all_tg_pt_handler, &snprint_hw_all_tg_pt);
|
||||||
|
install_keyword("vpd_vendor", &hw_vpd_vendor_handler, &snprint_hw_vpd_vendor);
|
||||||
|
+ install_keyword("recheck_wwid", &hw_recheck_wwid_handler, &snprint_hw_recheck_wwid);
|
||||||
|
install_sublevel_end();
|
||||||
|
|
||||||
|
install_keyword_root("overrides", &overrides_handler);
|
||||||
|
@@ -1954,6 +1964,7 @@ init_keywords(vector keywords)
|
||||||
|
install_keyword("max_sectors_kb", &ovr_max_sectors_kb_handler, &snprint_ovr_max_sectors_kb);
|
||||||
|
install_keyword("ghost_delay", &ovr_ghost_delay_handler, &snprint_ovr_ghost_delay);
|
||||||
|
install_keyword("all_tg_pt", &ovr_all_tg_pt_handler, &snprint_ovr_all_tg_pt);
|
||||||
|
+ install_keyword("recheck_wwid", &ovr_recheck_wwid_handler, &snprint_ovr_recheck_wwid);
|
||||||
|
|
||||||
|
install_keyword_root("multipaths", &multipaths_handler);
|
||||||
|
install_keyword_multi("multipath", &multipath_handler, NULL);
|
||||||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
|
index 126a70b3..bc267609 100644
|
||||||
|
--- a/libmultipath/discovery.c
|
||||||
|
+++ b/libmultipath/discovery.c
|
||||||
|
@@ -2040,7 +2040,7 @@ static ssize_t uid_fallback(struct path *pp, int path_state,
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static bool has_uid_fallback(struct path *pp)
|
||||||
|
+bool has_uid_fallback(struct path *pp)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Falling back to direct WWID determination is dangerous
|
||||||
|
@@ -2072,6 +2072,7 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev,
|
||||||
|
conf = get_multipath_config();
|
||||||
|
pthread_cleanup_push(put_multipath_config, conf);
|
||||||
|
select_getuid(conf, pp);
|
||||||
|
+ select_recheck_wwid(conf, pp);
|
||||||
|
pthread_cleanup_pop(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h
|
||||||
|
index d3193daf..a5446b4d 100644
|
||||||
|
--- a/libmultipath/discovery.h
|
||||||
|
+++ b/libmultipath/discovery.h
|
||||||
|
@@ -54,6 +54,7 @@ ssize_t sysfs_get_inquiry(struct udev_device *udev,
|
||||||
|
unsigned char *buff, size_t len);
|
||||||
|
int sysfs_get_asymmetric_access_state(struct path *pp,
|
||||||
|
char *buff, int buflen);
|
||||||
|
+bool has_uid_fallback(struct path *pp);
|
||||||
|
int get_uid(struct path * pp, int path_state, struct udev_device *udev,
|
||||||
|
int allow_fallback);
|
||||||
|
bool is_vpd_page_supported(int fd, int pg);
|
||||||
|
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
||||||
|
index 1150cfe8..127b3370 100644
|
||||||
|
--- a/libmultipath/propsel.c
|
||||||
|
+++ b/libmultipath/propsel.c
|
||||||
|
@@ -581,6 +581,27 @@ out:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* must be called after select_getuid */
|
||||||
|
+int select_recheck_wwid(struct config *conf, struct path * pp)
|
||||||
|
+{
|
||||||
|
+ const char *origin;
|
||||||
|
+
|
||||||
|
+ pp_set_ovr(recheck_wwid);
|
||||||
|
+ pp_set_hwe(recheck_wwid);
|
||||||
|
+ pp_set_conf(recheck_wwid);
|
||||||
|
+ pp_set_default(recheck_wwid, DEFAULT_RECHECK_WWID);
|
||||||
|
+out:
|
||||||
|
+ if (pp->recheck_wwid == RECHECK_WWID_ON &&
|
||||||
|
+ (pp->bus != SYSFS_BUS_SCSI || pp->getuid != NULL ||
|
||||||
|
+ !has_uid_fallback(pp))) {
|
||||||
|
+ pp->recheck_wwid = RECHECK_WWID_OFF;
|
||||||
|
+ origin = "(setting: unsupported by device type/config)";
|
||||||
|
+ }
|
||||||
|
+ condlog(3, "%s: recheck_wwid = %i %s", pp->dev, pp->recheck_wwid,
|
||||||
|
+ origin);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
detect_prio(struct config *conf, struct path * pp)
|
||||||
|
{
|
||||||
|
diff --git a/libmultipath/propsel.h b/libmultipath/propsel.h
|
||||||
|
index a68bacf0..72a7e33c 100644
|
||||||
|
--- a/libmultipath/propsel.h
|
||||||
|
+++ b/libmultipath/propsel.h
|
||||||
|
@@ -7,6 +7,7 @@ int select_features (struct config *conf, struct multipath * mp);
|
||||||
|
int select_hwhandler (struct config *conf, struct multipath * mp);
|
||||||
|
int select_checker(struct config *conf, struct path *pp);
|
||||||
|
int select_getuid (struct config *conf, struct path * pp);
|
||||||
|
+int select_recheck_wwid(struct config *conf, struct path * pp);
|
||||||
|
int select_prio (struct config *conf, struct path * pp);
|
||||||
|
int select_find_multipaths_timeout(struct config *conf, struct path *pp);
|
||||||
|
int select_no_path_retry(struct config *conf, struct multipath *mp);
|
||||||
|
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
||||||
|
index 65542dea..a5dbad5b 100644
|
||||||
|
--- a/libmultipath/structs.h
|
||||||
|
+++ b/libmultipath/structs.h
|
||||||
|
@@ -252,6 +252,12 @@ enum eh_deadline_states {
|
||||||
|
EH_DEADLINE_ZERO = UOZ_ZERO,
|
||||||
|
};
|
||||||
|
|
||||||
|
+enum recheck_wwid_states {
|
||||||
|
+ RECHECK_WWID_UNDEF = YNU_UNDEF,
|
||||||
|
+ RECHECK_WWID_OFF = YNU_NO,
|
||||||
|
+ RECHECK_WWID_ON = YNU_YES,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
struct vpd_vendor_page {
|
||||||
|
int pg;
|
||||||
|
const char *name;
|
||||||
|
@@ -326,6 +332,7 @@ struct path {
|
||||||
|
int find_multipaths_timeout;
|
||||||
|
int marginal;
|
||||||
|
int vpd_vendor_id;
|
||||||
|
+ int recheck_wwid;
|
||||||
|
/* configlet pointers */
|
||||||
|
vector hwe;
|
||||||
|
struct gen_path generic_path;
|
||||||
|
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
||||||
|
index a5686090..6da15aad 100644
|
||||||
|
--- a/multipath/multipath.conf.5
|
||||||
|
+++ b/multipath/multipath.conf.5
|
||||||
|
@@ -1256,6 +1256,20 @@ The default is: \fB\(dq\(dq\fR (the empty regular expression)
|
||||||
|
.RE
|
||||||
|
.
|
||||||
|
.
|
||||||
|
+.TP
|
||||||
|
+.B recheck_wwid
|
||||||
|
+If set to \fIyes\fR, when a failed path is restored, its wwid is rechecked. If
|
||||||
|
+the wwid has changed, the path is removed from the current multipath device,
|
||||||
|
+and re-added as a new path. Multipathd will also recheck a path's wwid if it is
|
||||||
|
+manually re-added. This option only works for SCSI devices that are configured
|
||||||
|
+to use the default uid_attribute, \fIID_SERIAL\fR, or sysfs for getting their
|
||||||
|
+wwid.
|
||||||
|
+.RS
|
||||||
|
+.TP
|
||||||
|
+The default is \fBno\fR
|
||||||
|
+.RE
|
||||||
|
+.
|
||||||
|
+.
|
||||||
|
|
||||||
|
.
|
||||||
|
.\" ----------------------------------------------------------------------------
|
||||||
|
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
|
||||||
|
index 782bb003..8b4bd187 100644
|
||||||
|
--- a/multipathd/cli_handlers.c
|
||||||
|
+++ b/multipathd/cli_handlers.c
|
||||||
|
@@ -715,6 +715,15 @@ cli_add_path (void * v, char ** reply, int * len, void * data)
|
||||||
|
pp = find_path_by_dev(vecs->pathvec, param);
|
||||||
|
if (pp) {
|
||||||
|
condlog(2, "%s: path already in pathvec", param);
|
||||||
|
+
|
||||||
|
+ if (pp->recheck_wwid == RECHECK_WWID_ON &&
|
||||||
|
+ check_path_wwid_change(pp)) {
|
||||||
|
+ condlog(0, "%s: wwid changed. Removing device",
|
||||||
|
+ pp->dev);
|
||||||
|
+ handle_path_wwid_change(pp, vecs);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (pp->mpp)
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
|
index cc1aeea2..1fbc31eb 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -822,6 +822,73 @@ ev_remove_map (char * devname, char * alias, int minor, struct vectors * vecs)
|
||||||
|
return flush_map(mpp, vecs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+rescan_path(struct udev_device *parent)
|
||||||
|
+{
|
||||||
|
+ while(parent) {
|
||||||
|
+ const char *subsys = udev_device_get_subsystem(parent);
|
||||||
|
+ if (subsys && !strncmp(subsys, "scsi", 4))
|
||||||
|
+ break;
|
||||||
|
+ parent = udev_device_get_parent(parent);
|
||||||
|
+ }
|
||||||
|
+ if (parent)
|
||||||
|
+ sysfs_attr_set_value(parent, "rescan", "1", strlen("1"));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+handle_path_wwid_change(struct path *pp, struct vectors *vecs)
|
||||||
|
+{
|
||||||
|
+ struct udev_device *udd;
|
||||||
|
+
|
||||||
|
+ if (!pp || !pp->udev)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ udd = udev_device_ref(pp->udev);
|
||||||
|
+ if (ev_remove_path(pp, vecs, 1) != 0 && pp->mpp) {
|
||||||
|
+ pp->dmstate = PSTATE_FAILED;
|
||||||
|
+ dm_fail_path(pp->mpp->alias, pp->dev_t);
|
||||||
|
+ }
|
||||||
|
+ rescan_path(udd);
|
||||||
|
+ sysfs_attr_set_value(udd, "uevent", "add", strlen("add"));
|
||||||
|
+ trigger_partitions_udev_change(udd, "add", strlen("add"));
|
||||||
|
+ udev_device_unref(udd);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+bool
|
||||||
|
+check_path_wwid_change(struct path *pp)
|
||||||
|
+{
|
||||||
|
+ char wwid[WWID_SIZE];
|
||||||
|
+ int len = 0;
|
||||||
|
+ size_t i;
|
||||||
|
+
|
||||||
|
+ if (!strlen(pp->wwid))
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ /* Get the real fresh device wwid by sgio. sysfs still has old
|
||||||
|
+ * data, so only get_vpd_sgio will work to get the new wwid */
|
||||||
|
+ len = get_vpd_sgio(pp->fd, 0x83, 0, wwid, WWID_SIZE);
|
||||||
|
+
|
||||||
|
+ if (len <= 0) {
|
||||||
|
+ condlog(2, "%s: failed to check wwid by sgio: len = %d",
|
||||||
|
+ pp->dev, len);
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*Strip any trailing blanks */
|
||||||
|
+ for (i = strlen(pp->wwid); i > 0 && pp->wwid[i-1] == ' '; i--);
|
||||||
|
+ /* no-op */
|
||||||
|
+ pp->wwid[i] = '\0';
|
||||||
|
+ condlog(4, "%s: Got wwid %s by sgio", pp->dev, wwid);
|
||||||
|
+
|
||||||
|
+ if (strncmp(wwid, pp->wwid, WWID_SIZE)) {
|
||||||
|
+ condlog(0, "%s: wwid '%s' doesn't match wwid '%s' from device",
|
||||||
|
+ pp->dev, pp->wwid, wwid);
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
uev_add_path (struct uevent *uev, struct vectors * vecs, int need_do_map)
|
||||||
|
{
|
||||||
|
@@ -1241,6 +1308,7 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
|
||||||
|
condlog(0, "%s: path wwid changed from '%s' to '%s'",
|
||||||
|
uev->kernel, wwid, pp->wwid);
|
||||||
|
ev_remove_path(pp, vecs, 1);
|
||||||
|
+ rescan_path(uev->udev);
|
||||||
|
needs_reinit = 1;
|
||||||
|
goto out;
|
||||||
|
} else {
|
||||||
|
@@ -2101,6 +2169,16 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||||
|
return 0;
|
||||||
|
set_no_path_retry(pp->mpp);
|
||||||
|
|
||||||
|
+ if (pp->recheck_wwid == RECHECK_WWID_ON &&
|
||||||
|
+ (newstate == PATH_UP || newstate == PATH_GHOST) &&
|
||||||
|
+ ((pp->state != PATH_UP && pp->state != PATH_GHOST) ||
|
||||||
|
+ pp->dmstate == PSTATE_FAILED) &&
|
||||||
|
+ check_path_wwid_change(pp)) {
|
||||||
|
+ condlog(0, "%s: path wwid change detected. Removing", pp->dev);
|
||||||
|
+ handle_path_wwid_change(pp, vecs);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if ((newstate == PATH_UP || newstate == PATH_GHOST) &&
|
||||||
|
(san_path_check_enabled(pp->mpp) ||
|
||||||
|
marginal_path_check_enabled(pp->mpp))) {
|
||||||
|
diff --git a/multipathd/main.h b/multipathd/main.h
|
||||||
|
index 5dff17e5..8f0028a9 100644
|
||||||
|
--- a/multipathd/main.h
|
||||||
|
+++ b/multipathd/main.h
|
||||||
|
@@ -49,4 +49,6 @@ int update_multipath (struct vectors *vecs, char *mapname, int reset);
|
||||||
|
int update_path_groups(struct multipath *mpp, struct vectors *vecs,
|
||||||
|
int refresh);
|
||||||
|
|
||||||
|
+void handle_path_wwid_change(struct path *pp, struct vectors *vecs);
|
||||||
|
+bool check_path_wwid_change(struct path *pp);
|
||||||
|
#endif /* MAIN_H */
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 25 Mar 2021 19:52:43 -0500
|
||||||
|
Subject: [PATCH] libmultipath: avoid infinite loop with bad vpd page 83
|
||||||
|
identifier
|
||||||
|
|
||||||
|
If a device with a scsi name identifier has an unknown prefix,
|
||||||
|
parse_vpd_pg83() needs to advance to the next identifier, instead of
|
||||||
|
simply trying the same one again in an infinite loop.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
---
|
||||||
|
libmultipath/discovery.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
|
index bc267609..8c2ab073 100644
|
||||||
|
--- a/libmultipath/discovery.c
|
||||||
|
+++ b/libmultipath/discovery.c
|
||||||
|
@@ -1101,7 +1101,7 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
|
||||||
|
if (memcmp(d + 4, "eui.", 4) &&
|
||||||
|
memcmp(d + 4, "naa.", 4) &&
|
||||||
|
memcmp(d + 4, "iqn.", 4))
|
||||||
|
- continue;
|
||||||
|
+ break;
|
||||||
|
if (prio < 4) {
|
||||||
|
prio = 4;
|
||||||
|
vpd = d;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,50 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 25 Mar 2021 19:52:44 -0500
|
||||||
|
Subject: [PATCH] libmultipath: fix priorities in parse_vpd_pg83
|
||||||
|
|
||||||
|
The priorities for the EUI-64 (0x02) and NAME (0x08) scsi identifiers in
|
||||||
|
parse_vpd_pg83() don't match their priorities in 55-scsi-sg3_id.rules.
|
||||||
|
Switch them so that they match.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
---
|
||||||
|
libmultipath/discovery.c | 16 ++++++++--------
|
||||||
|
1 file changed, 8 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
|
index 8c2ab073..5e988631 100644
|
||||||
|
--- a/libmultipath/discovery.c
|
||||||
|
+++ b/libmultipath/discovery.c
|
||||||
|
@@ -1096,19 +1096,19 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
|
||||||
|
vpd = d;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
- case 0x8:
|
||||||
|
- /* SCSI Name: Prio 4 */
|
||||||
|
- if (memcmp(d + 4, "eui.", 4) &&
|
||||||
|
- memcmp(d + 4, "naa.", 4) &&
|
||||||
|
- memcmp(d + 4, "iqn.", 4))
|
||||||
|
- break;
|
||||||
|
+ case 0x2:
|
||||||
|
+ /* EUI-64: Prio 4 */
|
||||||
|
if (prio < 4) {
|
||||||
|
prio = 4;
|
||||||
|
vpd = d;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
- case 0x2:
|
||||||
|
- /* EUI-64: Prio 3 */
|
||||||
|
+ case 0x8:
|
||||||
|
+ /* SCSI Name: Prio 3 */
|
||||||
|
+ if (memcmp(d + 4, "eui.", 4) &&
|
||||||
|
+ memcmp(d + 4, "naa.", 4) &&
|
||||||
|
+ memcmp(d + 4, "iqn.", 4))
|
||||||
|
+ break;
|
||||||
|
if (prio < 3) {
|
||||||
|
prio = 3;
|
||||||
|
vpd = d;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,54 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 25 Mar 2021 13:05:10 -0500
|
||||||
|
Subject: [PATCH] RH: make parse_vpd_pg83 match scsi_id output
|
||||||
|
|
||||||
|
Red Hat sets ID_SERIAL based on the result of scsi_id, instead of using
|
||||||
|
the result of sg_inq and 55-scsi-sg3_id.rules. Make parse_vpd_pg83 match
|
||||||
|
that.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/discovery.c | 18 ++----------------
|
||||||
|
1 file changed, 2 insertions(+), 16 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
|
index 5e988631..2404cb87 100644
|
||||||
|
--- a/libmultipath/discovery.c
|
||||||
|
+++ b/libmultipath/discovery.c
|
||||||
|
@@ -1079,12 +1079,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
|
||||||
|
naa_prio = 7;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
- /* IEEE Extended: Prio 6 */
|
||||||
|
- naa_prio = 6;
|
||||||
|
- break;
|
||||||
|
case 3:
|
||||||
|
- /* IEEE Locally assigned: Prio 1 */
|
||||||
|
- naa_prio = 1;
|
||||||
|
+ /* IEEE Extended or Locally assigned: Prio 6 */
|
||||||
|
+ naa_prio = 6;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Default: no priority */
|
||||||
|
@@ -1103,17 +1100,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
|
||||||
|
vpd = d;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
- case 0x8:
|
||||||
|
- /* SCSI Name: Prio 3 */
|
||||||
|
- if (memcmp(d + 4, "eui.", 4) &&
|
||||||
|
- memcmp(d + 4, "naa.", 4) &&
|
||||||
|
- memcmp(d + 4, "iqn.", 4))
|
||||||
|
- break;
|
||||||
|
- if (prio < 3) {
|
||||||
|
- prio = 3;
|
||||||
|
- vpd = d;
|
||||||
|
- }
|
||||||
|
- break;
|
||||||
|
case 0x1:
|
||||||
|
/* T-10 Vendor ID: Prio 2 */
|
||||||
|
if (prio < 2) {
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,44 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 25 Mar 2021 19:52:45 -0500
|
||||||
|
Subject: [PATCH] multipathd: improve getting parent udevice in rescan_path
|
||||||
|
|
||||||
|
Instead of looping through parents and checking, just call
|
||||||
|
udev_device_get_parent_with_subsystem_devtype() to get the
|
||||||
|
right one.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
---
|
||||||
|
multipathd/main.c | 14 +++++---------
|
||||||
|
1 file changed, 5 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
|
index 1fbc31eb..4598d354 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -823,16 +823,12 @@ ev_remove_map (char * devname, char * alias, int minor, struct vectors * vecs)
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
-rescan_path(struct udev_device *parent)
|
||||||
|
+rescan_path(struct udev_device *ud)
|
||||||
|
{
|
||||||
|
- while(parent) {
|
||||||
|
- const char *subsys = udev_device_get_subsystem(parent);
|
||||||
|
- if (subsys && !strncmp(subsys, "scsi", 4))
|
||||||
|
- break;
|
||||||
|
- parent = udev_device_get_parent(parent);
|
||||||
|
- }
|
||||||
|
- if (parent)
|
||||||
|
- sysfs_attr_set_value(parent, "rescan", "1", strlen("1"));
|
||||||
|
+ ud = udev_device_get_parent_with_subsystem_devtype(ud, "scsi",
|
||||||
|
+ "scsi_device");
|
||||||
|
+ if (ud)
|
||||||
|
+ sysfs_attr_set_value(ud, "rescan", "1", strlen("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,30 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 25 Mar 2021 19:52:46 -0500
|
||||||
|
Subject: [PATCH] multipathd: don't trigger uevent for partitions on wwid
|
||||||
|
change
|
||||||
|
|
||||||
|
If the wwid changed, the device is no longer the same, so sending add
|
||||||
|
events to the devices partitions doesn't make any sense.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
---
|
||||||
|
multipathd/main.c | 1 -
|
||||||
|
1 file changed, 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
|
index 4598d354..e6c19ab2 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -846,7 +846,6 @@ handle_path_wwid_change(struct path *pp, struct vectors *vecs)
|
||||||
|
}
|
||||||
|
rescan_path(udd);
|
||||||
|
sysfs_attr_set_value(udd, "uevent", "add", strlen("add"));
|
||||||
|
- trigger_partitions_udev_change(udd, "add", strlen("add"));
|
||||||
|
udev_device_unref(udd);
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,165 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Fri, 9 Jul 2021 14:30:10 -0500
|
||||||
|
Subject: [PATCH] RH: mpathconf: correctly handle spaces after option names
|
||||||
|
|
||||||
|
mpathconf was either accepting any number of spaces, including zero,
|
||||||
|
after option names, or it was only accepting one space. It should
|
||||||
|
accept one or more spaces.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
multipath/mpathconf | 40 ++++++++++++++++++++--------------------
|
||||||
|
1 file changed, 20 insertions(+), 20 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/multipath/mpathconf b/multipath/mpathconf
|
||||||
|
index 2f4f3eaf..5f2285ab 100644
|
||||||
|
--- a/multipath/mpathconf
|
||||||
|
+++ b/multipath/mpathconf
|
||||||
|
@@ -240,7 +240,7 @@ function validate_args
|
||||||
|
echo "--enable_foreign must be either 'y' or 'n'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
- if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" -a -z "$PROPERTY" ]; then
|
||||||
|
+ if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" -a -z "$PROPERTY" -a -z "$FOREIGN" ]; then
|
||||||
|
SHOW_STATUS=1
|
||||||
|
fi
|
||||||
|
if [ -n "$MODULE" ] && [ "$MODULE" != "y" -a "$MODULE" != "n" ]; then
|
||||||
|
@@ -315,36 +315,36 @@ if [ "$MULTIPATHD" = "y" ]; then
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$HAVE_BLACKLIST" = "1" ]; then
|
||||||
|
- if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*devnode \"\.\?\*\"" ; then
|
||||||
|
+ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"" ; then
|
||||||
|
HAVE_DISABLE=1
|
||||||
|
- elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"" ; then
|
||||||
|
+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"" ; then
|
||||||
|
HAVE_DISABLE=0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$HAVE_BLACKLIST" = "1" ]; then
|
||||||
|
- if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*wwid \"\.\?\*\"" ; then
|
||||||
|
+ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*wwid[[:space:]][[:space:]]*\"\.\?\*\"" ; then
|
||||||
|
HAVE_WWID_DISABLE=1
|
||||||
|
- elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"" ; then
|
||||||
|
+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*wwid[[:space:]][[:space:]]*\"\.\?\*\"" ; then
|
||||||
|
HAVE_WWID_DISABLE=0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$HAVE_DEFAULTS" = "1" ]; then
|
||||||
|
- HAVE_FIND=`sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | sed -n 's/^[[:blank:]]*find_multipaths[[:blank:]]*\([^[:blank:]]*\).*$/\1/p' | sed -n 1p`
|
||||||
|
+ HAVE_FIND=`sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | sed -n 's/^[[:blank:]]*find_multipaths[[:blank:]][[:blank:]]*\([^[:blank:]]*\).*$/\1/p' | sed -n 1p`
|
||||||
|
if [ "$HAVE_FIND" = "1" ]; then
|
||||||
|
HAVE_FIND="yes"
|
||||||
|
elif [ "$HAVE_FIND" = "0" ]; then
|
||||||
|
HAVE_FIND="no"
|
||||||
|
fi
|
||||||
|
- if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)" ; then
|
||||||
|
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]][[:space:]]*\(yes\|1\)" ; then
|
||||||
|
HAVE_FRIENDLY=1
|
||||||
|
- elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)" ; then
|
||||||
|
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]][[:space:]]*\(no\|0\)" ; then
|
||||||
|
HAVE_FRIENDLY=0
|
||||||
|
fi
|
||||||
|
if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*enable_foreign" ; then
|
||||||
|
HAVE_FOREIGN=0
|
||||||
|
- elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign[[:space:]]*\"\^\$\"" ; then
|
||||||
|
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign[[:space:]][[:space:]]*\"\^\$\"" ; then
|
||||||
|
HAVE_FOREIGN=1
|
||||||
|
elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign" ; then
|
||||||
|
HAVE_FOREIGN=2
|
||||||
|
@@ -352,9 +352,9 @@ if [ "$HAVE_DEFAULTS" = "1" ]; then
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$HAVE_EXCEPTIONS" = "1" ]; then
|
||||||
|
- if sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
|
||||||
|
+ if sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
|
||||||
|
HAVE_PROPERTY=1
|
||||||
|
- elif sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
|
||||||
|
+ elif sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
|
||||||
|
HAVE_PROPERTY=0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
@@ -427,14 +427,14 @@ fi
|
||||||
|
|
||||||
|
if [ "$ENABLE" = 2 ]; then
|
||||||
|
if [ "$HAVE_DISABLE" = 1 ]; then
|
||||||
|
- sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE
|
||||||
|
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"/# devnode ".*"/' $TMPFILE
|
||||||
|
fi
|
||||||
|
if [ -z "$HAVE_WWID_DISABLE" ]; then
|
||||||
|
sed -i '/^blacklist[[:space:]]*{/ a\
|
||||||
|
wwid ".*"
|
||||||
|
' $TMPFILE
|
||||||
|
elif [ "$HAVE_WWID_DISABLE" = 0 ]; then
|
||||||
|
- sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"/ wwid ".*"/' $TMPFILE
|
||||||
|
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*wwid[[:space:]][[:space:]]*\"\.\?\*\"/ wwid ".*"/' $TMPFILE
|
||||||
|
fi
|
||||||
|
if [ "$HAVE_EXCEPTIONS" = 1 ]; then
|
||||||
|
sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ {/^[[:space:]]*wwid/ d}' $TMPFILE
|
||||||
|
@@ -448,7 +448,7 @@ _EOF_
|
||||||
|
add_blacklist_exceptions
|
||||||
|
elif [ "$ENABLE" = 1 ]; then
|
||||||
|
if [ "$HAVE_DISABLE" = 1 ]; then
|
||||||
|
- sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE
|
||||||
|
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"/# devnode ".*"/' $TMPFILE
|
||||||
|
fi
|
||||||
|
elif [ "$ENABLE" = 0 ]; then
|
||||||
|
if [ -z "$HAVE_DISABLE" ]; then
|
||||||
|
@@ -456,7 +456,7 @@ elif [ "$ENABLE" = 0 ]; then
|
||||||
|
devnode ".*"
|
||||||
|
' $TMPFILE
|
||||||
|
elif [ "$HAVE_DISABLE" = 0 ]; then
|
||||||
|
- sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"/ devnode ".*"/' $TMPFILE
|
||||||
|
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"/ devnode ".*"/' $TMPFILE
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
@@ -467,14 +467,14 @@ if [ -n "$FIND" ]; then
|
||||||
|
' $TMPFILE
|
||||||
|
CHANGED_CONFIG=1
|
||||||
|
elif [ "$FIND" != "$HAVE_FIND" ]; then
|
||||||
|
- sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:blank:]]*find_multipaths[[:blank:]]*[^[:blank:]]*/ find_multipaths '"$FIND"'/' $TMPFILE
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:blank:]]*find_multipaths[[:blank:]][[:blank:]]*[^[:blank:]]*/ find_multipaths '"$FIND"'/' $TMPFILE
|
||||||
|
CHANGED_CONFIG=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$FRIENDLY" = "n" ]; then
|
||||||
|
if [ "$HAVE_FRIENDLY" = 1 ]; then
|
||||||
|
- sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)/ user_friendly_names no/' $TMPFILE
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]][[:space:]]*\(yes\|1\)/ user_friendly_names no/' $TMPFILE
|
||||||
|
CHANGED_CONFIG=1
|
||||||
|
fi
|
||||||
|
elif [ "$FRIENDLY" = "y" ]; then
|
||||||
|
@@ -484,14 +484,14 @@ elif [ "$FRIENDLY" = "y" ]; then
|
||||||
|
' $TMPFILE
|
||||||
|
CHANGED_CONFIG=1
|
||||||
|
elif [ "$HAVE_FRIENDLY" = 0 ]; then
|
||||||
|
- sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)/ user_friendly_names yes/' $TMPFILE
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]][[:space:]]*\(no\|0\)/ user_friendly_names yes/' $TMPFILE
|
||||||
|
CHANGED_CONFIG=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$PROPERTY" = "n" ]; then
|
||||||
|
if [ "$HAVE_PROPERTY" = 1 ]; then
|
||||||
|
- sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/# property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
|
||||||
|
+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/# property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
|
||||||
|
CHANGED_CONFIG=1
|
||||||
|
fi
|
||||||
|
elif [ "$PROPERTY" = "y" ]; then
|
||||||
|
@@ -501,7 +501,7 @@ elif [ "$PROPERTY" = "y" ]; then
|
||||||
|
' $TMPFILE
|
||||||
|
CHANGED_CONFIG=1
|
||||||
|
elif [ "$HAVE_PROPERTY" = 0 ]; then
|
||||||
|
- sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/ property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
|
||||||
|
+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/ property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
|
||||||
|
CHANGED_CONFIG=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
--
|
||||||
|
2.30.2
|
||||||
|
|
@ -0,0 +1,23 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 15 Jul 2021 14:48:15 -0500
|
||||||
|
Subject: [PATCH] multipath.conf: fix typo in checker_timeout description
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
multipath/multipath.conf.5 | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
||||||
|
index 6da15aad..0c04c7e4 100644
|
||||||
|
--- a/multipath/multipath.conf.5
|
||||||
|
+++ b/multipath/multipath.conf.5
|
||||||
|
@@ -638,7 +638,7 @@ Specify the timeout to use for path checkers and prioritizers, in seconds.
|
||||||
|
Only prioritizers that issue scsi commands use checker_timeout. Checkers
|
||||||
|
that support an asynchronous mode (\fItur\fR and \fIdirectio\fR), will
|
||||||
|
return shortly after being called by multipathd, regardless of whether the
|
||||||
|
-storage array responds. If the storage array hasn't responded, mulitpathd will
|
||||||
|
+storage array responds. If the storage array hasn't responded, multipathd will
|
||||||
|
check for a response every second, until \fIchecker_timeout\fR seconds have
|
||||||
|
elapsed.
|
||||||
|
.RS
|
@ -0,0 +1,41 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 22 Jul 2021 17:48:06 -0500
|
||||||
|
Subject: [PATCH] mpathpersist: fail commands when no usable paths exist
|
||||||
|
|
||||||
|
"mpathpersist -oCK <reservation_key> <device>" will return success if it
|
||||||
|
is run on devices with no usable paths, but nothing is actually done.
|
||||||
|
The -L command will fail, but it should give up sooner, and with a more
|
||||||
|
helpful error message.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmpathpersist/mpath_persist.c | 8 +++++++-
|
||||||
|
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||||
|
index 07a5f17f..d0744773 100644
|
||||||
|
--- a/libmpathpersist/mpath_persist.c
|
||||||
|
+++ b/libmpathpersist/mpath_persist.c
|
||||||
|
@@ -629,7 +629,8 @@ int mpath_prout_common(struct multipath *mpp,int rq_servact, int rq_scope,
|
||||||
|
return ret ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- return MPATH_PR_SUCCESS;
|
||||||
|
+ condlog (0, "%s: no path available", mpp->wwid);
|
||||||
|
+ return MPATH_PR_DMMP_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int send_prout_activepath(char * dev, int rq_servact, int rq_scope,
|
||||||
|
@@ -688,6 +689,11 @@ int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
|
||||||
|
|
||||||
|
active_pathcount = pathcount (mpp, PATH_UP) + pathcount (mpp, PATH_GHOST);
|
||||||
|
|
||||||
|
+ if (active_pathcount == 0) {
|
||||||
|
+ condlog (0, "%s: no path available", mpp->wwid);
|
||||||
|
+ return MPATH_PR_DMMP_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
struct threadinfo thread[active_pathcount];
|
||||||
|
memset(thread, 0, sizeof(thread));
|
||||||
|
for (i = 0; i < active_pathcount; i++){
|
@ -0,0 +1,107 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Fri, 16 Jul 2021 12:39:17 -0500
|
||||||
|
Subject: [PATCH] multipath: print warning if multipathd is not running.
|
||||||
|
|
||||||
|
If multipath notices that multipath devices exist or were created, and
|
||||||
|
multipathd is not running, it now prints a warning message, so users are
|
||||||
|
notified of the issue.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/configure.c | 13 +++++++++++--
|
||||||
|
libmultipath/configure.h | 1 +
|
||||||
|
multipath/main.c | 5 +++++
|
||||||
|
3 files changed, 17 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
||||||
|
index f24d9283..9c8d3e34 100644
|
||||||
|
--- a/libmultipath/configure.c
|
||||||
|
+++ b/libmultipath/configure.c
|
||||||
|
@@ -1043,7 +1043,8 @@ deadmap (struct multipath * mpp)
|
||||||
|
return 1; /* dead */
|
||||||
|
}
|
||||||
|
|
||||||
|
-int check_daemon(void)
|
||||||
|
+extern int
|
||||||
|
+check_daemon(void)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
char *reply;
|
||||||
|
@@ -1097,6 +1098,8 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
|
||||||
|
struct config *conf;
|
||||||
|
int allow_queueing;
|
||||||
|
uint64_t *size_mismatch_seen;
|
||||||
|
+ bool map_processed = false;
|
||||||
|
+ bool no_daemon = false;
|
||||||
|
|
||||||
|
/* ignore refwwid if it's empty */
|
||||||
|
if (refwwid && !strlen(refwwid))
|
||||||
|
@@ -1239,7 +1242,9 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
|
||||||
|
conf = get_multipath_config();
|
||||||
|
allow_queueing = conf->allow_queueing;
|
||||||
|
put_multipath_config(conf);
|
||||||
|
- if (!is_daemon && !allow_queueing && !check_daemon()) {
|
||||||
|
+ if (!is_daemon && !allow_queueing &&
|
||||||
|
+ (no_daemon || !check_daemon())) {
|
||||||
|
+ no_daemon = true;
|
||||||
|
if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
|
||||||
|
mpp->no_path_retry != NO_PATH_RETRY_FAIL)
|
||||||
|
condlog(3, "%s: multipathd not running, unset "
|
||||||
|
@@ -1267,6 +1272,7 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
|
||||||
|
else
|
||||||
|
remove_map(mpp, vecs, 0);
|
||||||
|
}
|
||||||
|
+ map_processed = true;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Flush maps with only dead paths (ie not in sysfs)
|
||||||
|
@@ -1292,6 +1298,9 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
|
||||||
|
condlog(2, "%s: remove (dead)", alias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ if (map_processed && !is_daemon && (no_daemon || !check_daemon()))
|
||||||
|
+ condlog(2, "multipath devices exist, but multipathd service is not running");
|
||||||
|
+
|
||||||
|
ret = CP_OK;
|
||||||
|
out:
|
||||||
|
free(size_mismatch_seen);
|
||||||
|
diff --git a/libmultipath/configure.h b/libmultipath/configure.h
|
||||||
|
index 81090dd4..8a266d31 100644
|
||||||
|
--- a/libmultipath/configure.h
|
||||||
|
+++ b/libmultipath/configure.h
|
||||||
|
@@ -59,3 +59,4 @@ struct udev_device *get_udev_device(const char *dev, enum devtypes dev_type);
|
||||||
|
void trigger_paths_udev_change(struct multipath *mpp, bool is_mpath);
|
||||||
|
void trigger_partitions_udev_change(struct udev_device *dev, const char *action,
|
||||||
|
int len);
|
||||||
|
+int check_daemon(void);
|
||||||
|
diff --git a/multipath/main.c b/multipath/main.c
|
||||||
|
index 607cada2..14d045c9 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -254,6 +254,7 @@ get_dm_mpvec (enum mpath_cmds cmd, vector curmp, vector pathvec, char * refwwid)
|
||||||
|
int i;
|
||||||
|
struct multipath * mpp;
|
||||||
|
char params[PARAMS_SIZE], status[PARAMS_SIZE];
|
||||||
|
+ bool maps_present = false;
|
||||||
|
|
||||||
|
if (dm_get_maps(curmp))
|
||||||
|
return 1;
|
||||||
|
@@ -302,6 +303,8 @@ get_dm_mpvec (enum mpath_cmds cmd, vector curmp, vector pathvec, char * refwwid)
|
||||||
|
|
||||||
|
if (cmd == CMD_CREATE)
|
||||||
|
reinstate_paths(mpp);
|
||||||
|
+
|
||||||
|
+ maps_present = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == CMD_LIST_SHORT || cmd == CMD_LIST_LONG) {
|
||||||
|
@@ -311,6 +314,8 @@ get_dm_mpvec (enum mpath_cmds cmd, vector curmp, vector pathvec, char * refwwid)
|
||||||
|
put_multipath_config(conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (maps_present && !check_daemon())
|
||||||
|
+ condlog(2, "multipath devices exist, but multipathd service is not running");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,64 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Fri, 23 Jul 2021 14:10:06 -0500
|
||||||
|
Subject: [PATCH] multipathd: don't access path if it was deleted
|
||||||
|
|
||||||
|
ev_remove_path() could fail and still delete the path. This could cause
|
||||||
|
problems for handle_path_wwid_change(), which expected that a failure
|
||||||
|
meant that the path still existed. ev_remove_path now returns a
|
||||||
|
different error code for failure to reload the multipath device, so that
|
||||||
|
it can be differentiated from cases where the path was no removed.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
multipathd/main.c | 11 +++++++----
|
||||||
|
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
|
index e6c19ab2..823b53a2 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -86,6 +86,9 @@
|
||||||
|
#define FILE_NAME_SIZE 256
|
||||||
|
#define CMDSIZE 160
|
||||||
|
|
||||||
|
+#define PATH_REMOVE_FAILED 1
|
||||||
|
+#define MAP_RELOAD_FAILED 2
|
||||||
|
+
|
||||||
|
#define LOG_MSG(lvl, verb, pp) \
|
||||||
|
do { \
|
||||||
|
if (pp->mpp && checker_selected(&pp->checker) && \
|
||||||
|
@@ -840,7 +843,7 @@ handle_path_wwid_change(struct path *pp, struct vectors *vecs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
udd = udev_device_ref(pp->udev);
|
||||||
|
- if (ev_remove_path(pp, vecs, 1) != 0 && pp->mpp) {
|
||||||
|
+ if (ev_remove_path(pp, vecs, 1) == PATH_REMOVE_FAILED && pp->mpp) {
|
||||||
|
pp->dmstate = PSTATE_FAILED;
|
||||||
|
dm_fail_path(pp->mpp->alias, pp->dev_t);
|
||||||
|
}
|
||||||
|
@@ -1226,13 +1229,13 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map)
|
||||||
|
condlog(0, "%s: failed in domap for "
|
||||||
|
"removal of path %s",
|
||||||
|
mpp->alias, pp->dev);
|
||||||
|
- retval = 1;
|
||||||
|
+ retval = MAP_RELOAD_FAILED;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* update our state from kernel
|
||||||
|
*/
|
||||||
|
if (setup_multipath(vecs, mpp))
|
||||||
|
- return 1;
|
||||||
|
+ return PATH_REMOVE_FAILED;
|
||||||
|
sync_map_state(mpp);
|
||||||
|
|
||||||
|
condlog(2, "%s [%s]: path removed from map %s",
|
||||||
|
@@ -1250,7 +1253,7 @@ out:
|
||||||
|
|
||||||
|
fail:
|
||||||
|
remove_map_and_stop_waiter(mpp, vecs);
|
||||||
|
- return 1;
|
||||||
|
+ return PATH_REMOVE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
@ -0,0 +1,43 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Luca BRUNO <luca.bruno@coreos.com>
|
||||||
|
Date: Fri, 24 Sep 2021 09:34:01 +0000
|
||||||
|
Subject: [PATCH] multipathd.socket: add missing conditions from service unit
|
||||||
|
|
||||||
|
Upstream Status: https://github.com/openSUSE/multipath-tools.git
|
||||||
|
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2008101
|
||||||
|
Conflicts: Match the conditions with RHEL-8 multipathd.service unit
|
||||||
|
|
||||||
|
commit 345ccf564ce7d904641bd32baf4fc53c2283d95c
|
||||||
|
Author: Luca BRUNO <luca.bruno@coreos.com>
|
||||||
|
Date: Fri Sep 24 09:34:01 2021 +0000
|
||||||
|
|
||||||
|
multipathd.socket: add missing conditions from service unit
|
||||||
|
|
||||||
|
This aligns 'multipathd' socket and service units, by adding the
|
||||||
|
start conditions that are set on the service but not on the socket.
|
||||||
|
It should help avoiding situations where the socket unit ends up
|
||||||
|
marked as failed after hitting its retry-limit.
|
||||||
|
|
||||||
|
Fixes: https://github.com/opensvc/multipath-tools/issues/15
|
||||||
|
Signed-off-by: Luca BRUNO <luca.bruno@coreos.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
multipathd/multipathd.socket | 3 +++
|
||||||
|
1 file changed, 3 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/multipathd/multipathd.socket b/multipathd/multipathd.socket
|
||||||
|
index 0ed4a1f7..c62c0fc8 100644
|
||||||
|
--- a/multipathd/multipathd.socket
|
||||||
|
+++ b/multipathd/multipathd.socket
|
||||||
|
@@ -1,6 +1,9 @@
|
||||||
|
[Unit]
|
||||||
|
Description=multipathd control socket
|
||||||
|
DefaultDependencies=no
|
||||||
|
+ConditionPathExists=/etc/multipath.conf
|
||||||
|
+ConditionKernelCommandLine=!nompath
|
||||||
|
+ConditionKernelCommandLine=!multipath=off
|
||||||
|
Before=sockets.target
|
||||||
|
|
||||||
|
[Socket]
|
@ -0,0 +1,70 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 23 Sep 2021 14:16:51 -0500
|
||||||
|
Subject: [PATCH] libmulitpath: add section name to invalid keyword output
|
||||||
|
|
||||||
|
If users forget the closing brace for a section in multipath.conf,
|
||||||
|
multipath has no way to detect that. When it sees the keyword at the
|
||||||
|
start of the next section, it will complain that there is an invalid
|
||||||
|
keyword, because that keyword doesn't belong in previous section (which
|
||||||
|
was never ended with a closing brace). This can confuse users. To make
|
||||||
|
this easier to understand, when multipath prints and invalid keyword
|
||||||
|
message, it now also prints the current section name, which can give
|
||||||
|
users a hint that they didn't end the previous section.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/parser.c | 21 ++++++++++++++-------
|
||||||
|
1 file changed, 14 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
|
||||||
|
index 48b54e87..96b95936 100644
|
||||||
|
--- a/libmultipath/parser.c
|
||||||
|
+++ b/libmultipath/parser.c
|
||||||
|
@@ -507,7 +507,8 @@ validate_config_strvec(vector strvec, char *file)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-process_stream(struct config *conf, FILE *stream, vector keywords, char *file)
|
||||||
|
+process_stream(struct config *conf, FILE *stream, vector keywords,
|
||||||
|
+ const char *section, char *file)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int r = 0, t;
|
||||||
|
@@ -571,16 +572,22 @@ process_stream(struct config *conf, FILE *stream, vector keywords, char *file)
|
||||||
|
if (keyword->sub) {
|
||||||
|
kw_level++;
|
||||||
|
r += process_stream(conf, stream,
|
||||||
|
- keyword->sub, file);
|
||||||
|
+ keyword->sub,
|
||||||
|
+ keyword->string,
|
||||||
|
+ file);
|
||||||
|
kw_level--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- if (i >= VECTOR_SIZE(keywords))
|
||||||
|
- condlog(1, "%s line %d, invalid keyword: %s",
|
||||||
|
- file, line_nr, str);
|
||||||
|
-
|
||||||
|
+ if (i >= VECTOR_SIZE(keywords)) {
|
||||||
|
+ if (section)
|
||||||
|
+ condlog(1, "%s line %d, invalid keyword in the %s section: %s",
|
||||||
|
+ file, line_nr, section, str);
|
||||||
|
+ else
|
||||||
|
+ condlog(1, "%s line %d, invalid keyword: %s",
|
||||||
|
+ file, line_nr, str);
|
||||||
|
+ }
|
||||||
|
free_strvec(strvec);
|
||||||
|
}
|
||||||
|
if (kw_level == 1)
|
||||||
|
@@ -611,7 +618,7 @@ process_file(struct config *conf, char *file)
|
||||||
|
|
||||||
|
/* Stream handling */
|
||||||
|
line_nr = 0;
|
||||||
|
- r = process_stream(conf, stream, conf->keywords, file);
|
||||||
|
+ r = process_stream(conf, stream, conf->keywords, NULL, file);
|
||||||
|
fclose(stream);
|
||||||
|
//free_keywords(keywords);
|
||||||
|
|
@ -0,0 +1,97 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 23 Sep 2021 21:39:36 -0500
|
||||||
|
Subject: [PATCH] libmultipath: use typedef for keyword handler and print
|
||||||
|
functions
|
||||||
|
|
||||||
|
Don't keep writing out the function type.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/parser.c | 10 +++++-----
|
||||||
|
libmultipath/parser.h | 25 ++++++++++++-------------
|
||||||
|
2 files changed, 17 insertions(+), 18 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
|
||||||
|
index 96b95936..e511acf9 100644
|
||||||
|
--- a/libmultipath/parser.c
|
||||||
|
+++ b/libmultipath/parser.c
|
||||||
|
@@ -32,8 +32,8 @@ static int line_nr;
|
||||||
|
|
||||||
|
int
|
||||||
|
keyword_alloc(vector keywords, char *string,
|
||||||
|
- int (*handler) (struct config *, vector),
|
||||||
|
- int (*print) (struct config *, char *, int, const void*),
|
||||||
|
+ handler_fn *handler,
|
||||||
|
+ print_fn *print,
|
||||||
|
int unique)
|
||||||
|
{
|
||||||
|
struct keyword *keyword;
|
||||||
|
@@ -71,8 +71,8 @@ install_sublevel_end(void)
|
||||||
|
|
||||||
|
int
|
||||||
|
_install_keyword(vector keywords, char *string,
|
||||||
|
- int (*handler) (struct config *, vector),
|
||||||
|
- int (*print) (struct config *, char *, int, const void*),
|
||||||
|
+ handler_fn *handler,
|
||||||
|
+ print_fn *print,
|
||||||
|
int unique)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
@@ -562,7 +562,7 @@ process_stream(struct config *conf, FILE *stream, vector keywords,
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (keyword->handler) {
|
||||||
|
- t = (*keyword->handler) (conf, strvec);
|
||||||
|
+ t = keyword->handler(conf, strvec);
|
||||||
|
r += t;
|
||||||
|
if (t)
|
||||||
|
condlog(1, "multipath.conf +%d, parsing failed: %s",
|
||||||
|
diff --git a/libmultipath/parser.h b/libmultipath/parser.h
|
||||||
|
index b7917052..e8d89607 100644
|
||||||
|
--- a/libmultipath/parser.h
|
||||||
|
+++ b/libmultipath/parser.h
|
||||||
|
@@ -39,11 +39,15 @@
|
||||||
|
#define EOB "}"
|
||||||
|
#define MAXBUF 1024
|
||||||
|
|
||||||
|
-/* ketword definition */
|
||||||
|
+
|
||||||
|
+/* keyword definition */
|
||||||
|
+typedef int print_fn(struct config *, char *, int, const void *);
|
||||||
|
+typedef int handler_fn(struct config *, vector);
|
||||||
|
+
|
||||||
|
struct keyword {
|
||||||
|
char *string;
|
||||||
|
- int (*handler) (struct config *, vector);
|
||||||
|
- int (*print) (struct config *, char *, int, const void *);
|
||||||
|
+ handler_fn *handler;
|
||||||
|
+ print_fn *print;
|
||||||
|
vector sub;
|
||||||
|
int unique;
|
||||||
|
};
|
||||||
|
@@ -58,19 +62,14 @@ struct keyword {
|
||||||
|
for (i = 0; i < (k)->sub->allocated && ((p) = (k)->sub->slot[i]); i++)
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
-extern int keyword_alloc(vector keywords, char *string,
|
||||||
|
- int (*handler) (struct config *, vector),
|
||||||
|
- int (*print) (struct config *, char *, int,
|
||||||
|
- const void *),
|
||||||
|
- int unique);
|
||||||
|
+extern int keyword_alloc(vector keywords, char *string, handler_fn *handler,
|
||||||
|
+ print_fn *print, int unique);
|
||||||
|
#define install_keyword_root(str, h) keyword_alloc(keywords, str, h, NULL, 1)
|
||||||
|
extern void install_sublevel(void);
|
||||||
|
extern void install_sublevel_end(void);
|
||||||
|
-extern int _install_keyword(vector keywords, char *string,
|
||||||
|
- int (*handler) (struct config *, vector),
|
||||||
|
- int (*print) (struct config *, char *, int,
|
||||||
|
- const void *),
|
||||||
|
- int unique);
|
||||||
|
+
|
||||||
|
+extern int _install_keyword(vector keywords, char *string, handler_fn *handler,
|
||||||
|
+ print_fn *print, int unique);
|
||||||
|
#define install_keyword(str, vec, pri) _install_keyword(keywords, str, vec, pri, 1)
|
||||||
|
#define install_keyword_multi(str, vec, pri) _install_keyword(keywords, str, vec, pri, 0)
|
||||||
|
extern void dump_keywords(vector keydump, int level);
|
@ -0,0 +1,27 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Fri, 24 Sep 2021 13:13:31 -0500
|
||||||
|
Subject: [PATCH] libmultipath: print the correct file when parsing fails
|
||||||
|
|
||||||
|
Don't assume that parsing failed on multipath.conf
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/parser.c | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
|
||||||
|
index e511acf9..341f2b80 100644
|
||||||
|
--- a/libmultipath/parser.c
|
||||||
|
+++ b/libmultipath/parser.c
|
||||||
|
@@ -565,8 +565,8 @@ process_stream(struct config *conf, FILE *stream, vector keywords,
|
||||||
|
t = keyword->handler(conf, strvec);
|
||||||
|
r += t;
|
||||||
|
if (t)
|
||||||
|
- condlog(1, "multipath.conf +%d, parsing failed: %s",
|
||||||
|
- line_nr, buf);
|
||||||
|
+ condlog(1, "%s line %d, parsing failed: %s",
|
||||||
|
+ file, line_nr, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyword->sub) {
|
@ -0,0 +1,536 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Fri, 24 Sep 2021 17:59:12 -0500
|
||||||
|
Subject: [PATCH] libmultipath: pass file and line number to keyword handlers
|
||||||
|
|
||||||
|
This will make it possible for the keyword handlers to print more useful
|
||||||
|
warning messages. It will be used by future patches.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/dict.c | 145 +++++++++++++++++++++++++-----------------
|
||||||
|
libmultipath/parser.c | 3 +-
|
||||||
|
libmultipath/parser.h | 2 +-
|
||||||
|
3 files changed, 91 insertions(+), 59 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||||
|
index 13698b76..a8872da7 100644
|
||||||
|
--- a/libmultipath/dict.c
|
||||||
|
+++ b/libmultipath/dict.c
|
||||||
|
@@ -28,7 +28,7 @@
|
||||||
|
#include "dict.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_int(vector strvec, void *ptr)
|
||||||
|
+set_int(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
char *buff, *eptr;
|
||||||
|
@@ -57,7 +57,7 @@ set_int(vector strvec, void *ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_uint(vector strvec, void *ptr)
|
||||||
|
+set_uint(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
unsigned int *uint_ptr = (unsigned int *)ptr;
|
||||||
|
char *buff, *eptr, *p;
|
||||||
|
@@ -89,7 +89,7 @@ set_uint(vector strvec, void *ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_str(vector strvec, void *ptr)
|
||||||
|
+set_str(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
char **str_ptr = (char **)ptr;
|
||||||
|
|
||||||
|
@@ -104,7 +104,7 @@ set_str(vector strvec, void *ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_regex(vector strvec, void *ptr)
|
||||||
|
+set_regex(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
char **str_ptr = (char **)ptr;
|
||||||
|
|
||||||
|
@@ -119,7 +119,7 @@ set_regex(vector strvec, void *ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_yes_no(vector strvec, void *ptr)
|
||||||
|
+set_yes_no(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
char * buff;
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
@@ -138,7 +138,7 @@ set_yes_no(vector strvec, void *ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_yes_no_undef(vector strvec, void *ptr)
|
||||||
|
+set_yes_no_undef(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
char * buff;
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
@@ -240,9 +240,10 @@ print_yes_no_undef (char *buff, int len, long v)
|
||||||
|
|
||||||
|
#define declare_def_handler(option, function) \
|
||||||
|
static int \
|
||||||
|
-def_ ## option ## _handler (struct config *conf, vector strvec) \
|
||||||
|
+def_ ## option ## _handler (struct config *conf, vector strvec, \
|
||||||
|
+ const char *file, int line_nr) \
|
||||||
|
{ \
|
||||||
|
- return function (strvec, &conf->option); \
|
||||||
|
+ return function (strvec, &conf->option, file, line_nr); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define declare_def_snprint(option, function) \
|
||||||
|
@@ -277,12 +278,13 @@ snprint_def_ ## option (struct config *conf, char * buff, int len, \
|
||||||
|
|
||||||
|
#define declare_hw_handler(option, function) \
|
||||||
|
static int \
|
||||||
|
-hw_ ## option ## _handler (struct config *conf, vector strvec) \
|
||||||
|
+hw_ ## option ## _handler (struct config *conf, vector strvec, \
|
||||||
|
+ const char *file, int line_nr) \
|
||||||
|
{ \
|
||||||
|
struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); \
|
||||||
|
if (!hwe) \
|
||||||
|
return 1; \
|
||||||
|
- return function (strvec, &hwe->option); \
|
||||||
|
+ return function (strvec, &hwe->option, file, line_nr); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define declare_hw_snprint(option, function) \
|
||||||
|
@@ -296,11 +298,12 @@ snprint_hw_ ## option (struct config *conf, char * buff, int len, \
|
||||||
|
|
||||||
|
#define declare_ovr_handler(option, function) \
|
||||||
|
static int \
|
||||||
|
-ovr_ ## option ## _handler (struct config *conf, vector strvec) \
|
||||||
|
+ovr_ ## option ## _handler (struct config *conf, vector strvec, \
|
||||||
|
+ const char *file, int line_nr) \
|
||||||
|
{ \
|
||||||
|
if (!conf->overrides) \
|
||||||
|
return 1; \
|
||||||
|
- return function (strvec, &conf->overrides->option); \
|
||||||
|
+ return function (strvec, &conf->overrides->option, file, line_nr); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define declare_ovr_snprint(option, function) \
|
||||||
|
@@ -313,12 +316,13 @@ snprint_ovr_ ## option (struct config *conf, char * buff, int len, \
|
||||||
|
|
||||||
|
#define declare_mp_handler(option, function) \
|
||||||
|
static int \
|
||||||
|
-mp_ ## option ## _handler (struct config *conf, vector strvec) \
|
||||||
|
+mp_ ## option ## _handler (struct config *conf, vector strvec, \
|
||||||
|
+ const char *file, int line_nr) \
|
||||||
|
{ \
|
||||||
|
struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable); \
|
||||||
|
if (!mpe) \
|
||||||
|
return 1; \
|
||||||
|
- return function (strvec, &mpe->option); \
|
||||||
|
+ return function (strvec, &mpe->option, file, line_nr); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define declare_mp_snprint(option, function) \
|
||||||
|
@@ -330,9 +334,10 @@ snprint_mp_ ## option (struct config *conf, char * buff, int len, \
|
||||||
|
return function (buff, len, mpe->option); \
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int checkint_handler(struct config *conf, vector strvec)
|
||||||
|
+static int checkint_handler(struct config *conf, vector strvec,
|
||||||
|
+ const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
- int rc = set_uint(strvec, &conf->checkint);
|
||||||
|
+ int rc = set_uint(strvec, &conf->checkint, file, line_nr);
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
@@ -355,9 +360,10 @@ declare_def_snprint(reassign_maps, print_yes_no)
|
||||||
|
declare_def_handler(multipath_dir, set_str)
|
||||||
|
declare_def_snprint(multipath_dir, print_str)
|
||||||
|
|
||||||
|
-static int def_partition_delim_handler(struct config *conf, vector strvec)
|
||||||
|
+static int def_partition_delim_handler(struct config *conf, vector strvec,
|
||||||
|
+ const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
- int rc = set_str(strvec, &conf->partition_delim);
|
||||||
|
+ int rc = set_str(strvec, &conf->partition_delim, file, line_nr);
|
||||||
|
|
||||||
|
if (rc != 0)
|
||||||
|
return rc;
|
||||||
|
@@ -387,13 +393,13 @@ static const char * const find_multipaths_optvals[] = {
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
-def_find_multipaths_handler(struct config *conf, vector strvec)
|
||||||
|
+def_find_multipaths_handler(struct config *conf, vector strvec,
|
||||||
|
+ const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
char *buff;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
- if (set_yes_no_undef(strvec, &conf->find_multipaths) == 0 &&
|
||||||
|
- conf->find_multipaths != FIND_MULTIPATHS_UNDEF)
|
||||||
|
+ if (set_yes_no_undef(strvec, &conf->find_multipaths, file, line_nr) == 0 && conf->find_multipaths != FIND_MULTIPATHS_UNDEF)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
buff = set_value(strvec);
|
||||||
|
@@ -451,7 +457,8 @@ static int snprint_uid_attrs(struct config *conf, char *buff, int len,
|
||||||
|
return p - buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int uid_attrs_handler(struct config *conf, vector strvec)
|
||||||
|
+static int uid_attrs_handler(struct config *conf, vector strvec,
|
||||||
|
+ const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
char *val;
|
||||||
|
|
||||||
|
@@ -644,7 +651,8 @@ declare_hw_handler(skip_kpartx, set_yes_no_undef)
|
||||||
|
declare_hw_snprint(skip_kpartx, print_yes_no_undef)
|
||||||
|
declare_mp_handler(skip_kpartx, set_yes_no_undef)
|
||||||
|
declare_mp_snprint(skip_kpartx, print_yes_no_undef)
|
||||||
|
-static int def_disable_changed_wwids_handler(struct config *conf, vector strvec)
|
||||||
|
+static int def_disable_changed_wwids_handler(struct config *conf, vector strvec,
|
||||||
|
+ const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -675,20 +683,23 @@ declare_def_snprint_defstr(enable_foreign, print_str,
|
||||||
|
DEFAULT_ENABLE_FOREIGN)
|
||||||
|
|
||||||
|
static int
|
||||||
|
-def_config_dir_handler(struct config *conf, vector strvec)
|
||||||
|
+def_config_dir_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
+ int line_nr)
|
||||||
|
{
|
||||||
|
/* this is only valid in the main config file */
|
||||||
|
if (conf->processed_main_config)
|
||||||
|
return 0;
|
||||||
|
- return set_str(strvec, &conf->config_dir);
|
||||||
|
+ return set_str(strvec, &conf->config_dir, file, line_nr);
|
||||||
|
}
|
||||||
|
declare_def_snprint(config_dir, print_str)
|
||||||
|
|
||||||
|
#define declare_def_attr_handler(option, function) \
|
||||||
|
static int \
|
||||||
|
-def_ ## option ## _handler (struct config *conf, vector strvec) \
|
||||||
|
+def_ ## option ## _handler (struct config *conf, vector strvec, \
|
||||||
|
+ const char *file, int line_nr) \
|
||||||
|
{ \
|
||||||
|
- return function (strvec, &conf->option, &conf->attribute_flags);\
|
||||||
|
+ return function (strvec, &conf->option, &conf->attribute_flags, \
|
||||||
|
+ file, line_nr); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define declare_def_attr_snprint(option, function) \
|
||||||
|
@@ -702,12 +713,14 @@ snprint_def_ ## option (struct config *conf, char * buff, int len, \
|
||||||
|
|
||||||
|
#define declare_mp_attr_handler(option, function) \
|
||||||
|
static int \
|
||||||
|
-mp_ ## option ## _handler (struct config *conf, vector strvec) \
|
||||||
|
+mp_ ## option ## _handler (struct config *conf, vector strvec, \
|
||||||
|
+ const char *file, int line_nr) \
|
||||||
|
{ \
|
||||||
|
struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable); \
|
||||||
|
if (!mpe) \
|
||||||
|
return 1; \
|
||||||
|
- return function (strvec, &mpe->option, &mpe->attribute_flags); \
|
||||||
|
+ return function (strvec, &mpe->option, &mpe->attribute_flags, \
|
||||||
|
+ file, line_nr); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define declare_mp_attr_snprint(option, function) \
|
||||||
|
@@ -721,7 +734,7 @@ snprint_mp_ ## option (struct config *conf, char * buff, int len, \
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_mode(vector strvec, void *ptr, int *flags)
|
||||||
|
+set_mode(vector strvec, void *ptr, int *flags, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
mode_t mode;
|
||||||
|
mode_t *mode_ptr = (mode_t *)ptr;
|
||||||
|
@@ -742,7 +755,7 @@ set_mode(vector strvec, void *ptr, int *flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_uid(vector strvec, void *ptr, int *flags)
|
||||||
|
+set_uid(vector strvec, void *ptr, int *flags, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
uid_t uid;
|
||||||
|
uid_t *uid_ptr = (uid_t *)ptr;
|
||||||
|
@@ -767,7 +780,7 @@ set_uid(vector strvec, void *ptr, int *flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_gid(vector strvec, void *ptr, int *flags)
|
||||||
|
+set_gid(vector strvec, void *ptr, int *flags, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
gid_t gid;
|
||||||
|
gid_t *gid_ptr = (gid_t *)ptr;
|
||||||
|
@@ -834,7 +847,7 @@ declare_mp_attr_handler(gid, set_gid)
|
||||||
|
declare_mp_attr_snprint(gid, print_gid)
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_undef_off_zero(vector strvec, void *ptr)
|
||||||
|
+set_undef_off_zero(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
char * buff;
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
@@ -876,7 +889,7 @@ declare_hw_handler(fast_io_fail, set_undef_off_zero)
|
||||||
|
declare_hw_snprint(fast_io_fail, print_undef_off_zero)
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_dev_loss(vector strvec, void *ptr)
|
||||||
|
+set_dev_loss(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
char * buff;
|
||||||
|
unsigned int *uint_ptr = (unsigned int *)ptr;
|
||||||
|
@@ -919,7 +932,7 @@ declare_hw_handler(eh_deadline, set_undef_off_zero)
|
||||||
|
declare_hw_snprint(eh_deadline, print_undef_off_zero)
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_pgpolicy(vector strvec, void *ptr)
|
||||||
|
+set_pgpolicy(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
char * buff;
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
@@ -985,7 +998,8 @@ get_sys_max_fds(int *max_fds)
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
-max_fds_handler(struct config *conf, vector strvec)
|
||||||
|
+max_fds_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
+ int line_nr)
|
||||||
|
{
|
||||||
|
char * buff;
|
||||||
|
int r = 0, max_fds;
|
||||||
|
@@ -1030,7 +1044,7 @@ snprint_max_fds (struct config *conf, char * buff, int len, const void * data)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_rr_weight(vector strvec, void *ptr)
|
||||||
|
+set_rr_weight(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
char * buff;
|
||||||
|
@@ -1074,7 +1088,7 @@ declare_mp_handler(rr_weight, set_rr_weight)
|
||||||
|
declare_mp_snprint(rr_weight, print_rr_weight)
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_pgfailback(vector strvec, void *ptr)
|
||||||
|
+set_pgfailback(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
char * buff;
|
||||||
|
@@ -1124,7 +1138,7 @@ declare_mp_handler(pgfailback, set_pgfailback)
|
||||||
|
declare_mp_snprint(pgfailback, print_pgfailback)
|
||||||
|
|
||||||
|
static int
|
||||||
|
-no_path_retry_helper(vector strvec, void *ptr)
|
||||||
|
+no_path_retry_helper(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
char * buff;
|
||||||
|
@@ -1169,7 +1183,8 @@ declare_mp_handler(no_path_retry, no_path_retry_helper)
|
||||||
|
declare_mp_snprint(no_path_retry, print_no_path_retry)
|
||||||
|
|
||||||
|
static int
|
||||||
|
-def_log_checker_err_handler(struct config *conf, vector strvec)
|
||||||
|
+def_log_checker_err_handler(struct config *conf, vector strvec,
|
||||||
|
+ const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
char * buff;
|
||||||
|
|
||||||
|
@@ -1243,7 +1258,8 @@ print_reservation_key(char * buff, int len, struct be64 key, uint8_t flags,
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-def_reservation_key_handler(struct config *conf, vector strvec)
|
||||||
|
+def_reservation_key_handler(struct config *conf, vector strvec,
|
||||||
|
+ const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
return set_reservation_key(strvec, &conf->reservation_key,
|
||||||
|
&conf->sa_flags,
|
||||||
|
@@ -1260,7 +1276,8 @@ snprint_def_reservation_key (struct config *conf, char * buff, int len,
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-mp_reservation_key_handler(struct config *conf, vector strvec)
|
||||||
|
+mp_reservation_key_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
+ int line_nr)
|
||||||
|
{
|
||||||
|
struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable);
|
||||||
|
if (!mpe)
|
||||||
|
@@ -1281,7 +1298,7 @@ snprint_mp_reservation_key (struct config *conf, char * buff, int len,
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_off_int_undef(vector strvec, void *ptr)
|
||||||
|
+set_off_int_undef(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
char * buff;
|
||||||
|
@@ -1422,7 +1439,8 @@ declare_hw_snprint(recheck_wwid, print_yes_no_undef)
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
-def_uxsock_timeout_handler(struct config *conf, vector strvec)
|
||||||
|
+def_uxsock_timeout_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
+ int line_nr)
|
||||||
|
{
|
||||||
|
unsigned int uxsock_timeout;
|
||||||
|
char *buff;
|
||||||
|
@@ -1442,7 +1460,8 @@ def_uxsock_timeout_handler(struct config *conf, vector strvec)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-hw_vpd_vendor_handler(struct config *conf, vector strvec)
|
||||||
|
+hw_vpd_vendor_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
+ int line_nr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *buff;
|
||||||
|
@@ -1482,7 +1501,8 @@ snprint_hw_vpd_vendor(struct config *conf, char * buff, int len,
|
||||||
|
* blacklist block handlers
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
-blacklist_handler(struct config *conf, vector strvec)
|
||||||
|
+blacklist_handler(struct config *conf, vector strvec, const char*file,
|
||||||
|
+ int line_nr)
|
||||||
|
{
|
||||||
|
if (!conf->blist_devnode)
|
||||||
|
conf->blist_devnode = vector_alloc();
|
||||||
|
@@ -1504,7 +1524,8 @@ blacklist_handler(struct config *conf, vector strvec)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-blacklist_exceptions_handler(struct config *conf, vector strvec)
|
||||||
|
+blacklist_exceptions_handler(struct config *conf, vector strvec,
|
||||||
|
+ const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
if (!conf->elist_devnode)
|
||||||
|
conf->elist_devnode = vector_alloc();
|
||||||
|
@@ -1527,7 +1548,8 @@ blacklist_exceptions_handler(struct config *conf, vector strvec)
|
||||||
|
|
||||||
|
#define declare_ble_handler(option) \
|
||||||
|
static int \
|
||||||
|
-ble_ ## option ## _handler (struct config *conf, vector strvec) \
|
||||||
|
+ble_ ## option ## _handler (struct config *conf, vector strvec, \
|
||||||
|
+ const char *file, int line_nr) \
|
||||||
|
{ \
|
||||||
|
char * buff; \
|
||||||
|
\
|
||||||
|
@@ -1543,7 +1565,8 @@ ble_ ## option ## _handler (struct config *conf, vector strvec) \
|
||||||
|
|
||||||
|
#define declare_ble_device_handler(name, option, vend, prod) \
|
||||||
|
static int \
|
||||||
|
-ble_ ## option ## _ ## name ## _handler (struct config *conf, vector strvec) \
|
||||||
|
+ble_ ## option ## _ ## name ## _handler (struct config *conf, vector strvec, \
|
||||||
|
+ const char *file, int line_nr) \
|
||||||
|
{ \
|
||||||
|
char * buff; \
|
||||||
|
\
|
||||||
|
@@ -1583,13 +1606,15 @@ snprint_ble_simple (struct config *conf, char * buff, int len,
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-ble_device_handler(struct config *conf, vector strvec)
|
||||||
|
+ble_device_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
+ int line_nr)
|
||||||
|
{
|
||||||
|
return alloc_ble_device(conf->blist_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-ble_except_device_handler(struct config *conf, vector strvec)
|
||||||
|
+ble_except_device_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
+ int line_nr)
|
||||||
|
{
|
||||||
|
return alloc_ble_device(conf->elist_device);
|
||||||
|
}
|
||||||
|
@@ -1623,7 +1648,8 @@ snprint_bled_product (struct config *conf, char * buff, int len,
|
||||||
|
* devices block handlers
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
-devices_handler(struct config *conf, vector strvec)
|
||||||
|
+devices_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
+ int line_nr)
|
||||||
|
{
|
||||||
|
if (!conf->hwtable)
|
||||||
|
conf->hwtable = vector_alloc();
|
||||||
|
@@ -1635,7 +1661,8 @@ devices_handler(struct config *conf, vector strvec)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-device_handler(struct config *conf, vector strvec)
|
||||||
|
+device_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
+ int line_nr)
|
||||||
|
{
|
||||||
|
struct hwentry * hwe;
|
||||||
|
|
||||||
|
@@ -1672,7 +1699,8 @@ declare_hw_snprint(hwhandler, print_str)
|
||||||
|
* overrides handlers
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
-overrides_handler(struct config *conf, vector strvec)
|
||||||
|
+overrides_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
+ int line_nr)
|
||||||
|
{
|
||||||
|
if (!conf->overrides)
|
||||||
|
conf->overrides = alloc_hwe();
|
||||||
|
@@ -1689,7 +1717,8 @@ overrides_handler(struct config *conf, vector strvec)
|
||||||
|
* multipaths block handlers
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
-multipaths_handler(struct config *conf, vector strvec)
|
||||||
|
+multipaths_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
+ int line_nr)
|
||||||
|
{
|
||||||
|
if (!conf->mptable)
|
||||||
|
conf->mptable = vector_alloc();
|
||||||
|
@@ -1701,7 +1730,8 @@ multipaths_handler(struct config *conf, vector strvec)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-multipath_handler(struct config *conf, vector strvec)
|
||||||
|
+multipath_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
+ int line_nr)
|
||||||
|
{
|
||||||
|
struct mpentry * mpe;
|
||||||
|
|
||||||
|
@@ -1730,7 +1760,8 @@ declare_mp_snprint(alias, print_str)
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
-deprecated_handler(struct config *conf, vector strvec)
|
||||||
|
+deprecated_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
+ int line_nr)
|
||||||
|
{
|
||||||
|
char * buff;
|
||||||
|
|
||||||
|
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
|
||||||
|
index 341f2b80..29e8cee0 100644
|
||||||
|
--- a/libmultipath/parser.c
|
||||||
|
+++ b/libmultipath/parser.c
|
||||||
|
@@ -562,7 +562,8 @@ process_stream(struct config *conf, FILE *stream, vector keywords,
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (keyword->handler) {
|
||||||
|
- t = keyword->handler(conf, strvec);
|
||||||
|
+ t = keyword->handler(conf, strvec, file,
|
||||||
|
+ line_nr);
|
||||||
|
r += t;
|
||||||
|
if (t)
|
||||||
|
condlog(1, "%s line %d, parsing failed: %s",
|
||||||
|
diff --git a/libmultipath/parser.h b/libmultipath/parser.h
|
||||||
|
index e8d89607..8b424b7a 100644
|
||||||
|
--- a/libmultipath/parser.h
|
||||||
|
+++ b/libmultipath/parser.h
|
||||||
|
@@ -42,7 +42,7 @@
|
||||||
|
|
||||||
|
/* keyword definition */
|
||||||
|
typedef int print_fn(struct config *, char *, int, const void *);
|
||||||
|
-typedef int handler_fn(struct config *, vector);
|
||||||
|
+typedef int handler_fn(struct config *, vector, const char *file, int line_nr);
|
||||||
|
|
||||||
|
struct keyword {
|
||||||
|
char *string;
|
@ -0,0 +1,250 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 28 Sep 2021 15:59:19 -0500
|
||||||
|
Subject: [PATCH] libmultipath: make set_int take a range for valid values
|
||||||
|
|
||||||
|
If a value outside of the valid range is passed to set_int, it caps the
|
||||||
|
value at appropriate limit, and issues a warning.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/dict.c | 121 +++++++++++++++++++++++++++-----------------
|
||||||
|
1 file changed, 75 insertions(+), 46 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||||
|
index a8872da7..686f4d5c 100644
|
||||||
|
--- a/libmultipath/dict.c
|
||||||
|
+++ b/libmultipath/dict.c
|
||||||
|
@@ -28,7 +28,8 @@
|
||||||
|
#include "dict.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_int(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
+set_int(vector strvec, void *ptr, int min, int max, const char *file,
|
||||||
|
+ int line_nr)
|
||||||
|
{
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
char *buff, *eptr;
|
||||||
|
@@ -43,11 +44,17 @@ set_int(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
if (eptr > buff)
|
||||||
|
while (isspace(*eptr))
|
||||||
|
eptr++;
|
||||||
|
- if (*buff == '\0' || *eptr != '\0' || res > INT_MAX || res < INT_MIN) {
|
||||||
|
- condlog(1, "%s: invalid value for %s: \"%s\"",
|
||||||
|
- __func__, (char*)VECTOR_SLOT(strvec, 0), buff);
|
||||||
|
+ if (*buff == '\0' || *eptr != '\0') {
|
||||||
|
+ condlog(1, "%s line %d, invalid value for %s: \"%s\"",
|
||||||
|
+ file, line_nr, (char*)VECTOR_SLOT(strvec, 0), buff);
|
||||||
|
rc = 1;
|
||||||
|
} else {
|
||||||
|
+ if (res > max || res < min) {
|
||||||
|
+ res = (res > max) ? max : min;
|
||||||
|
+ condlog(1, "%s line %d, value for %s too %s, capping at %ld",
|
||||||
|
+ file, line_nr, (char*)VECTOR_SLOT(strvec, 0),
|
||||||
|
+ (res == max)? "large" : "small", res);
|
||||||
|
+ }
|
||||||
|
rc = 0;
|
||||||
|
*int_ptr = res;
|
||||||
|
}
|
||||||
|
@@ -76,8 +83,8 @@ set_uint(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
while (isspace(*eptr))
|
||||||
|
eptr++;
|
||||||
|
if (*buff == '\0' || *eptr != '\0' || !isdigit(*p) || res > UINT_MAX) {
|
||||||
|
- condlog(1, "%s: invalid value for %s: \"%s\"",
|
||||||
|
- __func__, (char*)VECTOR_SLOT(strvec, 0), buff);
|
||||||
|
+ condlog(1, "%s line %d, invalid value for %s: \"%s\"",
|
||||||
|
+ file, line_nr, (char*)VECTOR_SLOT(strvec, 0), buff);
|
||||||
|
rc = 1;
|
||||||
|
} else {
|
||||||
|
rc = 0;
|
||||||
|
@@ -246,6 +253,14 @@ def_ ## option ## _handler (struct config *conf, vector strvec, \
|
||||||
|
return function (strvec, &conf->option, file, line_nr); \
|
||||||
|
}
|
||||||
|
|
||||||
|
+#define declare_def_range_handler(option, minval, maxval) \
|
||||||
|
+static int \
|
||||||
|
+def_ ## option ## _handler (struct config *conf, vector strvec, \
|
||||||
|
+ const char *file, int line_nr) \
|
||||||
|
+{ \
|
||||||
|
+ return set_int(strvec, &conf->option, minval, maxval, file, line_nr); \
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
#define declare_def_snprint(option, function) \
|
||||||
|
static int \
|
||||||
|
snprint_def_ ## option (struct config *conf, char * buff, int len, \
|
||||||
|
@@ -287,6 +302,18 @@ hw_ ## option ## _handler (struct config *conf, vector strvec, \
|
||||||
|
return function (strvec, &hwe->option, file, line_nr); \
|
||||||
|
}
|
||||||
|
|
||||||
|
+#define declare_hw_range_handler(option, minval, maxval) \
|
||||||
|
+static int \
|
||||||
|
+hw_ ## option ## _handler (struct config *conf, vector strvec, \
|
||||||
|
+ const char *file, int line_nr) \
|
||||||
|
+{ \
|
||||||
|
+ struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); \
|
||||||
|
+ if (!hwe) \
|
||||||
|
+ return 1; \
|
||||||
|
+ return set_int(strvec, &hwe->option, minval, maxval, file, line_nr); \
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
#define declare_hw_snprint(option, function) \
|
||||||
|
static int \
|
||||||
|
snprint_hw_ ## option (struct config *conf, char * buff, int len, \
|
||||||
|
@@ -306,6 +333,17 @@ ovr_ ## option ## _handler (struct config *conf, vector strvec, \
|
||||||
|
return function (strvec, &conf->overrides->option, file, line_nr); \
|
||||||
|
}
|
||||||
|
|
||||||
|
+#define declare_ovr_range_handler(option, minval, maxval) \
|
||||||
|
+static int \
|
||||||
|
+ovr_ ## option ## _handler (struct config *conf, vector strvec, \
|
||||||
|
+ const char *file, int line_nr) \
|
||||||
|
+{ \
|
||||||
|
+ if (!conf->overrides) \
|
||||||
|
+ return 1; \
|
||||||
|
+ return set_int(strvec, &conf->overrides->option, minval, maxval, \
|
||||||
|
+ file, line_nr); \
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
#define declare_ovr_snprint(option, function) \
|
||||||
|
static int \
|
||||||
|
snprint_ovr_ ## option (struct config *conf, char * buff, int len, \
|
||||||
|
@@ -325,6 +363,17 @@ mp_ ## option ## _handler (struct config *conf, vector strvec, \
|
||||||
|
return function (strvec, &mpe->option, file, line_nr); \
|
||||||
|
}
|
||||||
|
|
||||||
|
+#define declare_mp_range_handler(option, minval, maxval) \
|
||||||
|
+static int \
|
||||||
|
+mp_ ## option ## _handler (struct config *conf, vector strvec, \
|
||||||
|
+ const char *file, int line_nr) \
|
||||||
|
+{ \
|
||||||
|
+ struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable); \
|
||||||
|
+ if (!mpe) \
|
||||||
|
+ return 1; \
|
||||||
|
+ return set_int(strvec, &mpe->option, minval, maxval, file, line_nr); \
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
#define declare_mp_snprint(option, function) \
|
||||||
|
static int \
|
||||||
|
snprint_mp_ ## option (struct config *conf, char * buff, int len, \
|
||||||
|
@@ -351,7 +400,7 @@ declare_def_snprint(checkint, print_int)
|
||||||
|
declare_def_handler(max_checkint, set_uint)
|
||||||
|
declare_def_snprint(max_checkint, print_int)
|
||||||
|
|
||||||
|
-declare_def_handler(verbosity, set_int)
|
||||||
|
+declare_def_range_handler(verbosity, 0, MAX_VERBOSITY)
|
||||||
|
declare_def_snprint(verbosity, print_int)
|
||||||
|
|
||||||
|
declare_def_handler(reassign_maps, set_yes_no)
|
||||||
|
@@ -528,22 +577,22 @@ declare_ovr_snprint(checker_name, print_str)
|
||||||
|
declare_hw_handler(checker_name, set_str)
|
||||||
|
declare_hw_snprint(checker_name, print_str)
|
||||||
|
|
||||||
|
-declare_def_handler(minio, set_int)
|
||||||
|
+declare_def_range_handler(minio, 0, INT_MAX)
|
||||||
|
declare_def_snprint_defint(minio, print_int, DEFAULT_MINIO)
|
||||||
|
-declare_ovr_handler(minio, set_int)
|
||||||
|
+declare_ovr_range_handler(minio, 0, INT_MAX)
|
||||||
|
declare_ovr_snprint(minio, print_nonzero)
|
||||||
|
-declare_hw_handler(minio, set_int)
|
||||||
|
+declare_hw_range_handler(minio, 0, INT_MAX)
|
||||||
|
declare_hw_snprint(minio, print_nonzero)
|
||||||
|
-declare_mp_handler(minio, set_int)
|
||||||
|
+declare_mp_range_handler(minio, 0, INT_MAX)
|
||||||
|
declare_mp_snprint(minio, print_nonzero)
|
||||||
|
|
||||||
|
-declare_def_handler(minio_rq, set_int)
|
||||||
|
+declare_def_range_handler(minio_rq, 0, INT_MAX)
|
||||||
|
declare_def_snprint_defint(minio_rq, print_int, DEFAULT_MINIO_RQ)
|
||||||
|
-declare_ovr_handler(minio_rq, set_int)
|
||||||
|
+declare_ovr_range_handler(minio_rq, 0, INT_MAX)
|
||||||
|
declare_ovr_snprint(minio_rq, print_nonzero)
|
||||||
|
-declare_hw_handler(minio_rq, set_int)
|
||||||
|
+declare_hw_range_handler(minio_rq, 0, INT_MAX)
|
||||||
|
declare_hw_snprint(minio_rq, print_nonzero)
|
||||||
|
-declare_mp_handler(minio_rq, set_int)
|
||||||
|
+declare_mp_range_handler(minio_rq, 0, INT_MAX)
|
||||||
|
declare_mp_snprint(minio_rq, print_nonzero)
|
||||||
|
|
||||||
|
declare_def_handler(queue_without_daemon, set_yes_no)
|
||||||
|
@@ -562,7 +611,7 @@ snprint_def_queue_without_daemon (struct config *conf,
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-declare_def_handler(checker_timeout, set_int)
|
||||||
|
+declare_def_range_handler(checker_timeout, 0, INT_MAX)
|
||||||
|
declare_def_snprint(checker_timeout, print_nonzero)
|
||||||
|
|
||||||
|
declare_def_handler(flush_on_last_del, set_yes_no_undef)
|
||||||
|
@@ -630,13 +679,13 @@ declare_hw_snprint(deferred_remove, print_yes_no_undef)
|
||||||
|
declare_mp_handler(deferred_remove, set_yes_no_undef)
|
||||||
|
declare_mp_snprint(deferred_remove, print_yes_no_undef)
|
||||||
|
|
||||||
|
-declare_def_handler(retrigger_tries, set_int)
|
||||||
|
+declare_def_range_handler(retrigger_tries, 0, INT_MAX)
|
||||||
|
declare_def_snprint(retrigger_tries, print_int)
|
||||||
|
|
||||||
|
-declare_def_handler(retrigger_delay, set_int)
|
||||||
|
+declare_def_range_handler(retrigger_delay, 0, INT_MAX)
|
||||||
|
declare_def_snprint(retrigger_delay, print_int)
|
||||||
|
|
||||||
|
-declare_def_handler(uev_wait_timeout, set_int)
|
||||||
|
+declare_def_range_handler(uev_wait_timeout, 0, INT_MAX)
|
||||||
|
declare_def_snprint(uev_wait_timeout, print_int)
|
||||||
|
|
||||||
|
declare_def_handler(strict_timing, set_yes_no)
|
||||||
|
@@ -662,19 +711,19 @@ static int snprint_def_disable_changed_wwids(struct config *conf, char *buff,
|
||||||
|
return print_ignored(buff, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
-declare_def_handler(remove_retries, set_int)
|
||||||
|
+declare_def_range_handler(remove_retries, 0, INT_MAX)
|
||||||
|
declare_def_snprint(remove_retries, print_int)
|
||||||
|
|
||||||
|
-declare_def_handler(max_sectors_kb, set_int)
|
||||||
|
+declare_def_range_handler(max_sectors_kb, 0, INT_MAX)
|
||||||
|
declare_def_snprint(max_sectors_kb, print_nonzero)
|
||||||
|
-declare_ovr_handler(max_sectors_kb, set_int)
|
||||||
|
+declare_ovr_range_handler(max_sectors_kb, 0, INT_MAX)
|
||||||
|
declare_ovr_snprint(max_sectors_kb, print_nonzero)
|
||||||
|
-declare_hw_handler(max_sectors_kb, set_int)
|
||||||
|
+declare_hw_range_handler(max_sectors_kb, 0, INT_MAX)
|
||||||
|
declare_hw_snprint(max_sectors_kb, print_nonzero)
|
||||||
|
-declare_mp_handler(max_sectors_kb, set_int)
|
||||||
|
+declare_mp_range_handler(max_sectors_kb, 0, INT_MAX)
|
||||||
|
declare_mp_snprint(max_sectors_kb, print_nonzero)
|
||||||
|
|
||||||
|
-declare_def_handler(find_multipaths_timeout, set_int)
|
||||||
|
+declare_def_range_handler(find_multipaths_timeout, INT_MIN, INT_MAX)
|
||||||
|
declare_def_snprint_defint(find_multipaths_timeout, print_int,
|
||||||
|
DEFAULT_FIND_MULTIPATHS_TIMEOUT)
|
||||||
|
|
||||||
|
@@ -1437,27 +1486,7 @@ declare_ovr_snprint(recheck_wwid, print_yes_no_undef)
|
||||||
|
declare_hw_handler(recheck_wwid, set_yes_no_undef)
|
||||||
|
declare_hw_snprint(recheck_wwid, print_yes_no_undef)
|
||||||
|
|
||||||
|
-
|
||||||
|
-static int
|
||||||
|
-def_uxsock_timeout_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
- int line_nr)
|
||||||
|
-{
|
||||||
|
- unsigned int uxsock_timeout;
|
||||||
|
- char *buff;
|
||||||
|
-
|
||||||
|
- buff = set_value(strvec);
|
||||||
|
- if (!buff)
|
||||||
|
- return 1;
|
||||||
|
-
|
||||||
|
- if (sscanf(buff, "%u", &uxsock_timeout) == 1 &&
|
||||||
|
- uxsock_timeout > DEFAULT_REPLY_TIMEOUT)
|
||||||
|
- conf->uxsock_timeout = uxsock_timeout;
|
||||||
|
- else
|
||||||
|
- conf->uxsock_timeout = DEFAULT_REPLY_TIMEOUT;
|
||||||
|
-
|
||||||
|
- free(buff);
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
+declare_def_range_handler(uxsock_timeout, DEFAULT_REPLY_TIMEOUT, INT_MAX)
|
||||||
|
|
||||||
|
static int
|
||||||
|
hw_vpd_vendor_handler(struct config *conf, vector strvec, const char *file,
|
@ -0,0 +1,177 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 29 Sep 2021 12:56:04 -0500
|
||||||
|
Subject: [PATCH] libmultipath: improve checks for set_str
|
||||||
|
|
||||||
|
multipath always requires absolute pathnames, so make sure all file and
|
||||||
|
directory names start with a slash. Also check that the directories
|
||||||
|
exist. Finally, some strings, like the alias, will be used in paths.
|
||||||
|
These must not contain the slash character '/', since it is a forbidden
|
||||||
|
character in file/directory names. This patch adds seperate handlers for
|
||||||
|
these three cases. If a config line is invalid, these handlers retain
|
||||||
|
the existing config string, if any.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/dict.c | 89 +++++++++++++++++++++++++++++++++++++++------
|
||||||
|
1 file changed, 78 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||||
|
index 686f4d5c..d547d898 100644
|
||||||
|
--- a/libmultipath/dict.c
|
||||||
|
+++ b/libmultipath/dict.c
|
||||||
|
@@ -5,6 +5,8 @@
|
||||||
|
* Copyright (c) 2005 Kiyoshi Ueda, NEC
|
||||||
|
*/
|
||||||
|
#include <sys/types.h>
|
||||||
|
+#include <sys/stat.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "checkers.h"
|
||||||
|
@@ -121,7 +123,72 @@ set_regex(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
|
||||||
|
if (!*str_ptr)
|
||||||
|
return 1;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+set_dir(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
+{
|
||||||
|
+ char **str_ptr = (char **)ptr;
|
||||||
|
+ char *old_str = *str_ptr;
|
||||||
|
+ struct stat sb;
|
||||||
|
+
|
||||||
|
+ *str_ptr = set_value(strvec);
|
||||||
|
+ if (!*str_ptr) {
|
||||||
|
+ free(old_str);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ if ((*str_ptr)[0] != '/'){
|
||||||
|
+ condlog(1, "%s line %d, %s is not an absolute directory path. Ignoring", file, line_nr, *str_ptr);
|
||||||
|
+ *str_ptr = old_str;
|
||||||
|
+ } else {
|
||||||
|
+ if (stat(*str_ptr, &sb) == 0 && S_ISDIR(sb.st_mode))
|
||||||
|
+ free(old_str);
|
||||||
|
+ else {
|
||||||
|
+ condlog(1, "%s line %d, %s is not an existing directory. Ignoring", file, line_nr, *str_ptr);
|
||||||
|
+ *str_ptr = old_str;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+set_path(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
+{
|
||||||
|
+ char **str_ptr = (char **)ptr;
|
||||||
|
+ char *old_str = *str_ptr;
|
||||||
|
+
|
||||||
|
+ *str_ptr = set_value(strvec);
|
||||||
|
+ if (!*str_ptr) {
|
||||||
|
+ free(old_str);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ if ((*str_ptr)[0] != '/'){
|
||||||
|
+ condlog(1, "%s line %d, %s is not an absolute path. Ignoring",
|
||||||
|
+ file, line_nr, *str_ptr);
|
||||||
|
+ *str_ptr = old_str;
|
||||||
|
+ } else
|
||||||
|
+ free(old_str);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+set_str_noslash(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
+{
|
||||||
|
+ char **str_ptr = (char **)ptr;
|
||||||
|
+ char *old_str = *str_ptr;
|
||||||
|
+
|
||||||
|
+ *str_ptr = set_value(strvec);
|
||||||
|
+ if (!*str_ptr) {
|
||||||
|
+ free(old_str);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ if (strchr(*str_ptr, '/')) {
|
||||||
|
+ condlog(1, "%s line %d, %s cannot contain a slash. Ignoring",
|
||||||
|
+ file, line_nr, *str_ptr);
|
||||||
|
+ *str_ptr = old_str;
|
||||||
|
+ } else
|
||||||
|
+ free(old_str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -400,19 +467,19 @@ declare_def_snprint(checkint, print_int)
|
||||||
|
declare_def_handler(max_checkint, set_uint)
|
||||||
|
declare_def_snprint(max_checkint, print_int)
|
||||||
|
|
||||||
|
-declare_def_range_handler(verbosity, 0, MAX_VERBOSITY)
|
||||||
|
+declare_def_range_handler(verbosity, 0, 4)
|
||||||
|
declare_def_snprint(verbosity, print_int)
|
||||||
|
|
||||||
|
declare_def_handler(reassign_maps, set_yes_no)
|
||||||
|
declare_def_snprint(reassign_maps, print_yes_no)
|
||||||
|
|
||||||
|
-declare_def_handler(multipath_dir, set_str)
|
||||||
|
+declare_def_handler(multipath_dir, set_dir)
|
||||||
|
declare_def_snprint(multipath_dir, print_str)
|
||||||
|
|
||||||
|
static int def_partition_delim_handler(struct config *conf, vector strvec,
|
||||||
|
const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
- int rc = set_str(strvec, &conf->partition_delim, file, line_nr);
|
||||||
|
+ int rc = set_str_noslash(strvec, &conf->partition_delim, file, line_nr);
|
||||||
|
|
||||||
|
if (rc != 0)
|
||||||
|
return rc;
|
||||||
|
@@ -545,11 +612,11 @@ declare_hw_snprint(prio_name, print_str)
|
||||||
|
declare_mp_handler(prio_name, set_str)
|
||||||
|
declare_mp_snprint(prio_name, print_str)
|
||||||
|
|
||||||
|
-declare_def_handler(alias_prefix, set_str)
|
||||||
|
+declare_def_handler(alias_prefix, set_str_noslash)
|
||||||
|
declare_def_snprint_defstr(alias_prefix, print_str, DEFAULT_ALIAS_PREFIX)
|
||||||
|
-declare_ovr_handler(alias_prefix, set_str)
|
||||||
|
+declare_ovr_handler(alias_prefix, set_str_noslash)
|
||||||
|
declare_ovr_snprint(alias_prefix, print_str)
|
||||||
|
-declare_hw_handler(alias_prefix, set_str)
|
||||||
|
+declare_hw_handler(alias_prefix, set_str_noslash)
|
||||||
|
declare_hw_snprint(alias_prefix, print_str)
|
||||||
|
|
||||||
|
declare_def_handler(prio_args, set_str)
|
||||||
|
@@ -633,13 +700,13 @@ declare_hw_snprint(user_friendly_names, print_yes_no_undef)
|
||||||
|
declare_mp_handler(user_friendly_names, set_yes_no_undef)
|
||||||
|
declare_mp_snprint(user_friendly_names, print_yes_no_undef)
|
||||||
|
|
||||||
|
-declare_def_handler(bindings_file, set_str)
|
||||||
|
+declare_def_handler(bindings_file, set_path)
|
||||||
|
declare_def_snprint(bindings_file, print_str)
|
||||||
|
|
||||||
|
-declare_def_handler(wwids_file, set_str)
|
||||||
|
+declare_def_handler(wwids_file, set_path)
|
||||||
|
declare_def_snprint(wwids_file, print_str)
|
||||||
|
|
||||||
|
-declare_def_handler(prkeys_file, set_str)
|
||||||
|
+declare_def_handler(prkeys_file, set_path)
|
||||||
|
declare_def_snprint(prkeys_file, print_str)
|
||||||
|
|
||||||
|
declare_def_handler(retain_hwhandler, set_yes_no_undef)
|
||||||
|
@@ -738,7 +805,7 @@ def_config_dir_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
/* this is only valid in the main config file */
|
||||||
|
if (conf->processed_main_config)
|
||||||
|
return 0;
|
||||||
|
- return set_str(strvec, &conf->config_dir, file, line_nr);
|
||||||
|
+ return set_path(strvec, &conf->config_dir, file, line_nr);
|
||||||
|
}
|
||||||
|
declare_def_snprint(config_dir, print_str)
|
||||||
|
|
||||||
|
@@ -1781,7 +1848,7 @@ multipath_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
declare_mp_handler(wwid, set_str)
|
||||||
|
declare_mp_snprint(wwid, print_str)
|
||||||
|
|
||||||
|
-declare_mp_handler(alias, set_str)
|
||||||
|
+declare_mp_handler(alias, set_str_noslash)
|
||||||
|
declare_mp_snprint(alias, print_str)
|
||||||
|
|
||||||
|
/*
|
@ -0,0 +1,191 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 4 Oct 2021 15:27:36 -0500
|
||||||
|
Subject: [PATCH] libmultipath: split set_int to enable reuse
|
||||||
|
|
||||||
|
Split the code that does the actual value parsing out of set_int(), into
|
||||||
|
a helper function, do_set_int(), so that it can be used by other
|
||||||
|
handlers. These functions no longer set the config value at all, when
|
||||||
|
they have invalid input.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/dict.c | 82 +++++++++++++++++++++++++--------------------
|
||||||
|
1 file changed, 46 insertions(+), 36 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||||
|
index d547d898..6330836a 100644
|
||||||
|
--- a/libmultipath/dict.c
|
||||||
|
+++ b/libmultipath/dict.c
|
||||||
|
@@ -30,17 +30,12 @@
|
||||||
|
#include "dict.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
-set_int(vector strvec, void *ptr, int min, int max, const char *file,
|
||||||
|
- int line_nr)
|
||||||
|
+do_set_int(vector strvec, void *ptr, int min, int max, const char *file,
|
||||||
|
+ int line_nr, char *buff)
|
||||||
|
{
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
- char *buff, *eptr;
|
||||||
|
+ char *eptr;
|
||||||
|
long res;
|
||||||
|
- int rc;
|
||||||
|
-
|
||||||
|
- buff = set_value(strvec);
|
||||||
|
- if (!buff)
|
||||||
|
- return 1;
|
||||||
|
|
||||||
|
res = strtol(buff, &eptr, 10);
|
||||||
|
if (eptr > buff)
|
||||||
|
@@ -49,17 +44,30 @@ set_int(vector strvec, void *ptr, int min, int max, const char *file,
|
||||||
|
if (*buff == '\0' || *eptr != '\0') {
|
||||||
|
condlog(1, "%s line %d, invalid value for %s: \"%s\"",
|
||||||
|
file, line_nr, (char*)VECTOR_SLOT(strvec, 0), buff);
|
||||||
|
- rc = 1;
|
||||||
|
- } else {
|
||||||
|
- if (res > max || res < min) {
|
||||||
|
- res = (res > max) ? max : min;
|
||||||
|
- condlog(1, "%s line %d, value for %s too %s, capping at %ld",
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ if (res > max || res < min) {
|
||||||
|
+ res = (res > max) ? max : min;
|
||||||
|
+ condlog(1, "%s line %d, value for %s too %s, capping at %ld",
|
||||||
|
file, line_nr, (char*)VECTOR_SLOT(strvec, 0),
|
||||||
|
- (res == max)? "large" : "small", res);
|
||||||
|
- }
|
||||||
|
- rc = 0;
|
||||||
|
- *int_ptr = res;
|
||||||
|
+ (res == max)? "large" : "small", res);
|
||||||
|
}
|
||||||
|
+ *int_ptr = res;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+set_int(vector strvec, void *ptr, int min, int max, const char *file,
|
||||||
|
+ int line_nr)
|
||||||
|
+{
|
||||||
|
+ char *buff;
|
||||||
|
+ int rc;
|
||||||
|
+
|
||||||
|
+ buff = set_value(strvec);
|
||||||
|
+ if (!buff)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ rc = do_set_int(strvec, ptr, min, max, file, line_nr, buff);
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
return rc;
|
||||||
|
@@ -965,6 +973,7 @@ declare_mp_attr_snprint(gid, print_gid)
|
||||||
|
static int
|
||||||
|
set_undef_off_zero(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
+ int rc = 0;
|
||||||
|
char * buff;
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
|
||||||
|
@@ -974,10 +983,10 @@ set_undef_off_zero(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
|
||||||
|
if (strcmp(buff, "off") == 0)
|
||||||
|
*int_ptr = UOZ_OFF;
|
||||||
|
- else if (sscanf(buff, "%d", int_ptr) != 1 ||
|
||||||
|
- *int_ptr < UOZ_ZERO)
|
||||||
|
- *int_ptr = UOZ_UNDEF;
|
||||||
|
- else if (*int_ptr == 0)
|
||||||
|
+ else
|
||||||
|
+ rc = do_set_int(strvec, int_ptr, 0, INT_MAX, file, line_nr,
|
||||||
|
+ buff);
|
||||||
|
+ if (rc == 0 && *int_ptr == 0)
|
||||||
|
*int_ptr = UOZ_ZERO;
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
@@ -1130,14 +1139,12 @@ max_fds_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
/* Assume safe limit */
|
||||||
|
max_fds = 4096;
|
||||||
|
}
|
||||||
|
- if (strlen(buff) == 3 &&
|
||||||
|
- !strcmp(buff, "max"))
|
||||||
|
- conf->max_fds = max_fds;
|
||||||
|
- else
|
||||||
|
- conf->max_fds = atoi(buff);
|
||||||
|
-
|
||||||
|
- if (conf->max_fds > max_fds)
|
||||||
|
+ if (!strcmp(buff, "max")) {
|
||||||
|
conf->max_fds = max_fds;
|
||||||
|
+ r = 0;
|
||||||
|
+ } else
|
||||||
|
+ r = do_set_int(strvec, &conf->max_fds, 0, max_fds, file,
|
||||||
|
+ line_nr, buff);
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
|
||||||
|
@@ -1206,6 +1213,7 @@ declare_mp_snprint(rr_weight, print_rr_weight)
|
||||||
|
static int
|
||||||
|
set_pgfailback(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
+ int rc = 0;
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
char * buff;
|
||||||
|
|
||||||
|
@@ -1220,11 +1228,11 @@ set_pgfailback(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
else if (strlen(buff) == 10 && !strcmp(buff, "followover"))
|
||||||
|
*int_ptr = -FAILBACK_FOLLOWOVER;
|
||||||
|
else
|
||||||
|
- *int_ptr = atoi(buff);
|
||||||
|
+ rc = do_set_int(strvec, ptr, 0, INT_MAX, file, line_nr, buff);
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
|
||||||
|
- return 0;
|
||||||
|
+ return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
@@ -1256,6 +1264,7 @@ declare_mp_snprint(pgfailback, print_pgfailback)
|
||||||
|
static int
|
||||||
|
no_path_retry_helper(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
+ int rc = 0;
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
char * buff;
|
||||||
|
|
||||||
|
@@ -1267,11 +1276,11 @@ no_path_retry_helper(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
*int_ptr = NO_PATH_RETRY_FAIL;
|
||||||
|
else if (!strcmp(buff, "queue"))
|
||||||
|
*int_ptr = NO_PATH_RETRY_QUEUE;
|
||||||
|
- else if ((*int_ptr = atoi(buff)) < 1)
|
||||||
|
- *int_ptr = NO_PATH_RETRY_UNDEF;
|
||||||
|
+ else
|
||||||
|
+ rc = do_set_int(strvec, ptr, 1, INT_MAX, file, line_nr, buff);
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
- return 0;
|
||||||
|
+ return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
@@ -1416,6 +1425,7 @@ snprint_mp_reservation_key (struct config *conf, char * buff, int len,
|
||||||
|
static int
|
||||||
|
set_off_int_undef(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
+ int rc =0;
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
char * buff;
|
||||||
|
|
||||||
|
@@ -1425,11 +1435,11 @@ set_off_int_undef(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
|
||||||
|
if (!strcmp(buff, "no") || !strcmp(buff, "0"))
|
||||||
|
*int_ptr = NU_NO;
|
||||||
|
- else if ((*int_ptr = atoi(buff)) < 1)
|
||||||
|
- *int_ptr = NU_UNDEF;
|
||||||
|
+ else
|
||||||
|
+ rc = do_set_int(strvec, ptr, 1, INT_MAX, file, line_nr, buff);
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
- return 0;
|
||||||
|
+ return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
@ -0,0 +1,201 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 4 Oct 2021 16:52:55 -0500
|
||||||
|
Subject: [PATCH] libmultipath: cleanup invalid config handling
|
||||||
|
|
||||||
|
Add error reporting to the remaining config handlers. If the value is
|
||||||
|
invalid, do not change the existing config option's value. Also print
|
||||||
|
an error whenever 0 is returned for an invalid value. When the handler
|
||||||
|
returns 1, config processing already fails with an error message.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/dict.c | 73 +++++++++++++++++++++++++++++++--------------
|
||||||
|
1 file changed, 51 insertions(+), 22 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||||
|
index 6330836a..b255322e 100644
|
||||||
|
--- a/libmultipath/dict.c
|
||||||
|
+++ b/libmultipath/dict.c
|
||||||
|
@@ -212,8 +212,11 @@ set_yes_no(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
|
||||||
|
if (strcmp(buff, "yes") == 0 || strcmp(buff, "1") == 0)
|
||||||
|
*int_ptr = YN_YES;
|
||||||
|
- else
|
||||||
|
+ else if (strcmp(buff, "no") == 0 || strcmp(buff, "0") == 0)
|
||||||
|
*int_ptr = YN_NO;
|
||||||
|
+ else
|
||||||
|
+ condlog(1, "%s line %d, invalid value for %s: \"%s\"",
|
||||||
|
+ file, line_nr, (char*)VECTOR_SLOT(strvec, 0), buff);
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
return 0;
|
||||||
|
@@ -234,7 +237,8 @@ set_yes_no_undef(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
else if (strcmp(buff, "yes") == 0 || strcmp(buff, "1") == 0)
|
||||||
|
*int_ptr = YNU_YES;
|
||||||
|
else
|
||||||
|
- *int_ptr = YNU_UNDEF;
|
||||||
|
+ condlog(1, "%s line %d, invalid value for %s: \"%s\"",
|
||||||
|
+ file, line_nr, (char*)VECTOR_SLOT(strvec, 0), buff);
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
return 0;
|
||||||
|
@@ -523,9 +527,6 @@ def_find_multipaths_handler(struct config *conf, vector strvec,
|
||||||
|
char *buff;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
- if (set_yes_no_undef(strvec, &conf->find_multipaths, file, line_nr) == 0 && conf->find_multipaths != FIND_MULTIPATHS_UNDEF)
|
||||||
|
- return 0;
|
||||||
|
-
|
||||||
|
buff = set_value(strvec);
|
||||||
|
if (!buff)
|
||||||
|
return 1;
|
||||||
|
@@ -538,9 +539,14 @@ def_find_multipaths_handler(struct config *conf, vector strvec,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (conf->find_multipaths == YNU_UNDEF) {
|
||||||
|
- condlog(0, "illegal value for find_multipaths: %s", buff);
|
||||||
|
- conf->find_multipaths = DEFAULT_FIND_MULTIPATHS;
|
||||||
|
+ if (i >= __FIND_MULTIPATHS_LAST) {
|
||||||
|
+ if (strcmp(buff, "no") == 0 || strcmp(buff, "0") == 0)
|
||||||
|
+ conf->find_multipaths = FIND_MULTIPATHS_OFF;
|
||||||
|
+ else if (strcmp(buff, "yes") == 0 || strcmp(buff, "1") == 0)
|
||||||
|
+ conf->find_multipaths = FIND_MULTIPATHS_ON;
|
||||||
|
+ else
|
||||||
|
+ condlog(1, "%s line %d, invalid value for find_multipaths: \"%s\"",
|
||||||
|
+ file, line_nr, buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
@@ -591,8 +597,10 @@ static int uid_attrs_handler(struct config *conf, vector strvec,
|
||||||
|
if (!val)
|
||||||
|
return 1;
|
||||||
|
if (parse_uid_attrs(val, conf))
|
||||||
|
- condlog(1, "error parsing uid_attrs: \"%s\"", val);
|
||||||
|
- condlog(3, "parsed %d uid_attrs", VECTOR_SIZE(&conf->uid_attrs));
|
||||||
|
+ condlog(1, "%s line %d,error parsing uid_attrs: \"%s\"", file,
|
||||||
|
+ line_nr, val);
|
||||||
|
+ else
|
||||||
|
+ condlog(4, "parsed %d uid_attrs", VECTOR_SIZE(&conf->uid_attrs));
|
||||||
|
FREE(val);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -811,8 +819,11 @@ def_config_dir_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
int line_nr)
|
||||||
|
{
|
||||||
|
/* this is only valid in the main config file */
|
||||||
|
- if (conf->processed_main_config)
|
||||||
|
+ if (conf->processed_main_config) {
|
||||||
|
+ condlog(1, "%s line %d, config_dir option only valid in /etc/multipath.conf",
|
||||||
|
+ file, line_nr);
|
||||||
|
return 0;
|
||||||
|
+ }
|
||||||
|
return set_path(strvec, &conf->config_dir, file, line_nr);
|
||||||
|
}
|
||||||
|
declare_def_snprint(config_dir, print_str)
|
||||||
|
@@ -872,7 +883,9 @@ set_mode(vector strvec, void *ptr, int *flags, const char *file, int line_nr)
|
||||||
|
if (sscanf(buff, "%o", &mode) == 1 && mode <= 0777) {
|
||||||
|
*flags |= (1 << ATTR_MODE);
|
||||||
|
*mode_ptr = mode;
|
||||||
|
- }
|
||||||
|
+ } else
|
||||||
|
+ condlog(1, "%s line %d, invalid value for mode: \"%s\"",
|
||||||
|
+ file, line_nr, buff);
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
return 0;
|
||||||
|
@@ -897,7 +910,9 @@ set_uid(vector strvec, void *ptr, int *flags, const char *file, int line_nr)
|
||||||
|
else if (sscanf(buff, "%u", &uid) == 1){
|
||||||
|
*flags |= (1 << ATTR_UID);
|
||||||
|
*uid_ptr = uid;
|
||||||
|
- }
|
||||||
|
+ } else
|
||||||
|
+ condlog(1, "%s line %d, invalid value for uid: \"%s\"",
|
||||||
|
+ file, line_nr, buff);
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
return 0;
|
||||||
|
@@ -923,7 +938,9 @@ set_gid(vector strvec, void *ptr, int *flags, const char *file, int line_nr)
|
||||||
|
else if (sscanf(buff, "%u", &gid) == 1){
|
||||||
|
*flags |= (1 << ATTR_GID);
|
||||||
|
*gid_ptr = gid;
|
||||||
|
- }
|
||||||
|
+ } else
|
||||||
|
+ condlog(1, "%s line %d, invalid value for gid: \"%s\"",
|
||||||
|
+ file, line_nr, buff);
|
||||||
|
FREE(buff);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -1026,7 +1043,8 @@ set_dev_loss(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
if (!strcmp(buff, "infinity"))
|
||||||
|
*uint_ptr = MAX_DEV_LOSS_TMO;
|
||||||
|
else if (sscanf(buff, "%u", uint_ptr) != 1)
|
||||||
|
- *uint_ptr = 0;
|
||||||
|
+ condlog(1, "%s line %d, invalid value for dev_loss_tmo: \"%s\"",
|
||||||
|
+ file, line_nr, buff);
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
return 0;
|
||||||
|
@@ -1060,13 +1078,19 @@ static int
|
||||||
|
set_pgpolicy(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
char * buff;
|
||||||
|
+ int policy;
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
|
||||||
|
buff = set_value(strvec);
|
||||||
|
if (!buff)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
- *int_ptr = get_pgpolicy_id(buff);
|
||||||
|
+ policy = get_pgpolicy_id(buff);
|
||||||
|
+ if (policy != IOPOLICY_UNDEF)
|
||||||
|
+ *int_ptr = policy;
|
||||||
|
+ else
|
||||||
|
+ condlog(1, "%s line %d, invalid value for path_grouping_policy: \"%s\"",
|
||||||
|
+ file, line_nr, buff);
|
||||||
|
FREE(buff);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
@@ -1179,10 +1203,11 @@ set_rr_weight(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
|
||||||
|
if (!strcmp(buff, "priorities"))
|
||||||
|
*int_ptr = RR_WEIGHT_PRIO;
|
||||||
|
-
|
||||||
|
- if (!strcmp(buff, "uniform"))
|
||||||
|
+ else if (!strcmp(buff, "uniform"))
|
||||||
|
*int_ptr = RR_WEIGHT_NONE;
|
||||||
|
-
|
||||||
|
+ else
|
||||||
|
+ condlog(1, "%s line %d, invalid value for rr_weight: \"%s\"",
|
||||||
|
+ file, line_nr, buff);
|
||||||
|
FREE(buff);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
@@ -1318,10 +1343,13 @@ def_log_checker_err_handler(struct config *conf, vector strvec,
|
||||||
|
if (!buff)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
- if (strlen(buff) == 4 && !strcmp(buff, "once"))
|
||||||
|
+ if (!strcmp(buff, "once"))
|
||||||
|
conf->log_checker_err = LOG_CHKR_ERR_ONCE;
|
||||||
|
- else if (strlen(buff) == 6 && !strcmp(buff, "always"))
|
||||||
|
+ else if (!strcmp(buff, "always"))
|
||||||
|
conf->log_checker_err = LOG_CHKR_ERR_ALWAYS;
|
||||||
|
+ else
|
||||||
|
+ condlog(1, "%s line %d, invalid value for log_checker_err: \"%s\"",
|
||||||
|
+ file, line_nr, buff);
|
||||||
|
|
||||||
|
free(buff);
|
||||||
|
return 0;
|
||||||
|
@@ -1585,7 +1613,8 @@ hw_vpd_vendor_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- hwe->vpd_vendor_id = 0;
|
||||||
|
+ condlog(1, "%s line %d, invalid value for vpd_vendor: \"%s\"",
|
||||||
|
+ file, line_nr, buff);
|
||||||
|
out:
|
||||||
|
FREE(buff);
|
||||||
|
return 0;
|
@ -0,0 +1,218 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 11 Nov 2021 17:37:05 -0600
|
||||||
|
Subject: [PATCH] libmultipath: don't return error on invalid values
|
||||||
|
|
||||||
|
do_set_int and set_uint return 1 for invalid values. This can cause
|
||||||
|
multipath to fail completely, while reading the config. The config
|
||||||
|
handlers should only return a non-zero value if there is an internal
|
||||||
|
error, not if there is just an invalid value.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/dict.c | 64 ++++++++++++++++++---------------------------
|
||||||
|
1 file changed, 25 insertions(+), 39 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||||
|
index b255322e..5a0255b0 100644
|
||||||
|
--- a/libmultipath/dict.c
|
||||||
|
+++ b/libmultipath/dict.c
|
||||||
|
@@ -29,7 +29,7 @@
|
||||||
|
#include "mpath_cmd.h"
|
||||||
|
#include "dict.h"
|
||||||
|
|
||||||
|
-static int
|
||||||
|
+static void
|
||||||
|
do_set_int(vector strvec, void *ptr, int min, int max, const char *file,
|
||||||
|
int line_nr, char *buff)
|
||||||
|
{
|
||||||
|
@@ -44,7 +44,7 @@ do_set_int(vector strvec, void *ptr, int min, int max, const char *file,
|
||||||
|
if (*buff == '\0' || *eptr != '\0') {
|
||||||
|
condlog(1, "%s line %d, invalid value for %s: \"%s\"",
|
||||||
|
file, line_nr, (char*)VECTOR_SLOT(strvec, 0), buff);
|
||||||
|
- return 1;
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
if (res > max || res < min) {
|
||||||
|
res = (res > max) ? max : min;
|
||||||
|
@@ -53,7 +53,7 @@ do_set_int(vector strvec, void *ptr, int min, int max, const char *file,
|
||||||
|
(res == max)? "large" : "small", res);
|
||||||
|
}
|
||||||
|
*int_ptr = res;
|
||||||
|
- return 0;
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
@@ -61,16 +61,15 @@ set_int(vector strvec, void *ptr, int min, int max, const char *file,
|
||||||
|
int line_nr)
|
||||||
|
{
|
||||||
|
char *buff;
|
||||||
|
- int rc;
|
||||||
|
|
||||||
|
buff = set_value(strvec);
|
||||||
|
if (!buff)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
- rc = do_set_int(strvec, ptr, min, max, file, line_nr, buff);
|
||||||
|
+ do_set_int(strvec, ptr, min, max, file, line_nr, buff);
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
- return rc;
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
@@ -79,7 +78,6 @@ set_uint(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
unsigned int *uint_ptr = (unsigned int *)ptr;
|
||||||
|
char *buff, *eptr, *p;
|
||||||
|
unsigned long res;
|
||||||
|
- int rc;
|
||||||
|
|
||||||
|
buff = set_value(strvec);
|
||||||
|
if (!buff)
|
||||||
|
@@ -92,17 +90,14 @@ set_uint(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
if (eptr > buff)
|
||||||
|
while (isspace(*eptr))
|
||||||
|
eptr++;
|
||||||
|
- if (*buff == '\0' || *eptr != '\0' || !isdigit(*p) || res > UINT_MAX) {
|
||||||
|
+ if (*buff == '\0' || *eptr != '\0' || !isdigit(*p) || res > UINT_MAX)
|
||||||
|
condlog(1, "%s line %d, invalid value for %s: \"%s\"",
|
||||||
|
file, line_nr, (char*)VECTOR_SLOT(strvec, 0), buff);
|
||||||
|
- rc = 1;
|
||||||
|
- } else {
|
||||||
|
- rc = 0;
|
||||||
|
+ else
|
||||||
|
*uint_ptr = res;
|
||||||
|
- }
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
- return rc;
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
@@ -990,7 +985,6 @@ declare_mp_attr_snprint(gid, print_gid)
|
||||||
|
static int
|
||||||
|
set_undef_off_zero(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
- int rc = 0;
|
||||||
|
char * buff;
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
|
||||||
|
@@ -1000,11 +994,10 @@ set_undef_off_zero(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
|
||||||
|
if (strcmp(buff, "off") == 0)
|
||||||
|
*int_ptr = UOZ_OFF;
|
||||||
|
- else
|
||||||
|
- rc = do_set_int(strvec, int_ptr, 0, INT_MAX, file, line_nr,
|
||||||
|
- buff);
|
||||||
|
- if (rc == 0 && *int_ptr == 0)
|
||||||
|
+ else if (strcmp(buff, "0") == 0)
|
||||||
|
*int_ptr = UOZ_ZERO;
|
||||||
|
+ else
|
||||||
|
+ do_set_int(strvec, int_ptr, 1, INT_MAX, file, line_nr, buff);
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
return 0;
|
||||||
|
@@ -1151,28 +1144,24 @@ max_fds_handler(struct config *conf, vector strvec, const char *file,
|
||||||
|
int line_nr)
|
||||||
|
{
|
||||||
|
char * buff;
|
||||||
|
- int r = 0, max_fds;
|
||||||
|
+ int max_fds;
|
||||||
|
|
||||||
|
buff = set_value(strvec);
|
||||||
|
|
||||||
|
if (!buff)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
- r = get_sys_max_fds(&max_fds);
|
||||||
|
- if (r) {
|
||||||
|
- /* Assume safe limit */
|
||||||
|
- max_fds = 4096;
|
||||||
|
- }
|
||||||
|
- if (!strcmp(buff, "max")) {
|
||||||
|
+ if (get_sys_max_fds(&max_fds) != 0)
|
||||||
|
+ max_fds = 4096; /* Assume safe limit */
|
||||||
|
+ if (!strcmp(buff, "max"))
|
||||||
|
conf->max_fds = max_fds;
|
||||||
|
- r = 0;
|
||||||
|
- } else
|
||||||
|
- r = do_set_int(strvec, &conf->max_fds, 0, max_fds, file,
|
||||||
|
- line_nr, buff);
|
||||||
|
+ else
|
||||||
|
+ do_set_int(strvec, &conf->max_fds, 0, max_fds, file, line_nr,
|
||||||
|
+ buff);
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
|
||||||
|
- return r;
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
@@ -1238,7 +1227,6 @@ declare_mp_snprint(rr_weight, print_rr_weight)
|
||||||
|
static int
|
||||||
|
set_pgfailback(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
- int rc = 0;
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
char * buff;
|
||||||
|
|
||||||
|
@@ -1253,11 +1241,11 @@ set_pgfailback(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
else if (strlen(buff) == 10 && !strcmp(buff, "followover"))
|
||||||
|
*int_ptr = -FAILBACK_FOLLOWOVER;
|
||||||
|
else
|
||||||
|
- rc = do_set_int(strvec, ptr, 0, INT_MAX, file, line_nr, buff);
|
||||||
|
+ do_set_int(strvec, ptr, 0, INT_MAX, file, line_nr, buff);
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
|
||||||
|
- return rc;
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
@@ -1289,7 +1277,6 @@ declare_mp_snprint(pgfailback, print_pgfailback)
|
||||||
|
static int
|
||||||
|
no_path_retry_helper(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
- int rc = 0;
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
char * buff;
|
||||||
|
|
||||||
|
@@ -1302,10 +1289,10 @@ no_path_retry_helper(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
else if (!strcmp(buff, "queue"))
|
||||||
|
*int_ptr = NO_PATH_RETRY_QUEUE;
|
||||||
|
else
|
||||||
|
- rc = do_set_int(strvec, ptr, 1, INT_MAX, file, line_nr, buff);
|
||||||
|
+ do_set_int(strvec, ptr, 1, INT_MAX, file, line_nr, buff);
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
- return rc;
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
@@ -1453,7 +1440,6 @@ snprint_mp_reservation_key (struct config *conf, char * buff, int len,
|
||||||
|
static int
|
||||||
|
set_off_int_undef(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
{
|
||||||
|
- int rc =0;
|
||||||
|
int *int_ptr = (int *)ptr;
|
||||||
|
char * buff;
|
||||||
|
|
||||||
|
@@ -1464,10 +1450,10 @@ set_off_int_undef(vector strvec, void *ptr, const char *file, int line_nr)
|
||||||
|
if (!strcmp(buff, "no") || !strcmp(buff, "0"))
|
||||||
|
*int_ptr = NU_NO;
|
||||||
|
else
|
||||||
|
- rc = do_set_int(strvec, ptr, 1, INT_MAX, file, line_nr, buff);
|
||||||
|
+ do_set_int(strvec, ptr, 1, INT_MAX, file, line_nr, buff);
|
||||||
|
|
||||||
|
FREE(buff);
|
||||||
|
- return rc;
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
@ -0,0 +1,115 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 15 Nov 2021 10:54:35 -0600
|
||||||
|
Subject: [PATCH] multipathd: avoid unnecessary path read-only reloads
|
||||||
|
|
||||||
|
A mulitpath device can only be reloaded read/write when all paths are
|
||||||
|
read/write. Also, whenever a read-only device is rescanned, the scsi
|
||||||
|
subsystem will first unconditionally issue a uevent with DISK_RO=0
|
||||||
|
before checking the read-only status, and if it the device is still
|
||||||
|
read-only, issuing another uevent with DISK_RO=1. These uevents cause
|
||||||
|
pointless reloads when read-only paths are rescanned. To avoid this,
|
||||||
|
check to see if all paths are read/write before changing a multipath
|
||||||
|
device from read-only to read/write.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/sysfs.c | 22 ++++++++++++++++++++++
|
||||||
|
libmultipath/sysfs.h | 1 +
|
||||||
|
multipathd/main.c | 31 ++++++++++++++++++++++++++++++-
|
||||||
|
3 files changed, 53 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c
|
||||||
|
index 62ec2ed7..a57bd60e 100644
|
||||||
|
--- a/libmultipath/sysfs.c
|
||||||
|
+++ b/libmultipath/sysfs.c
|
||||||
|
@@ -236,6 +236,28 @@ sysfs_get_size (struct path *pp, unsigned long long * size)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+int
|
||||||
|
+sysfs_get_ro (struct path *pp)
|
||||||
|
+{
|
||||||
|
+ int ro;
|
||||||
|
+ char buff[3]; /* Either "0\n\0" or "1\n\0" */
|
||||||
|
+
|
||||||
|
+ if (!pp->udev)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ if (sysfs_attr_get_value(pp->udev, "ro", buff, sizeof(buff)) <= 0) {
|
||||||
|
+ condlog(3, "%s: Cannot read ro attribute in sysfs", pp->dev);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (sscanf(buff, "%d\n", &ro) != 1 || ro < 0 || ro > 1) {
|
||||||
|
+ condlog(3, "%s: Cannot parse ro attribute", pp->dev);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return ro;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int sysfs_check_holders(char * check_devt, char * new_devt)
|
||||||
|
{
|
||||||
|
unsigned int major, new_minor, table_minor;
|
||||||
|
diff --git a/libmultipath/sysfs.h b/libmultipath/sysfs.h
|
||||||
|
index 9ae30b39..91092e44 100644
|
||||||
|
--- a/libmultipath/sysfs.h
|
||||||
|
+++ b/libmultipath/sysfs.h
|
||||||
|
@@ -13,6 +13,7 @@ ssize_t sysfs_attr_get_value(struct udev_device *dev, const char *attr_name,
|
||||||
|
ssize_t sysfs_bin_attr_get_value(struct udev_device *dev, const char *attr_name,
|
||||||
|
unsigned char * value, size_t value_len);
|
||||||
|
int sysfs_get_size (struct path *pp, unsigned long long * size);
|
||||||
|
+int sysfs_get_ro(struct path *pp);
|
||||||
|
int sysfs_check_holders(char * check_devt, char * new_devt);
|
||||||
|
bool sysfs_is_multipathed(const struct path *pp);
|
||||||
|
#endif
|
||||||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
|
index 823b53a2..e2b9d546 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -1256,6 +1256,35 @@ fail:
|
||||||
|
return PATH_REMOVE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static bool
|
||||||
|
+needs_ro_update(struct multipath *mpp, int ro)
|
||||||
|
+{
|
||||||
|
+ struct pathgroup * pgp;
|
||||||
|
+ struct path * pp;
|
||||||
|
+ unsigned int i, j;
|
||||||
|
+ struct dm_info *dmi = NULL;
|
||||||
|
+
|
||||||
|
+ if (!mpp || ro < 0)
|
||||||
|
+ return false;
|
||||||
|
+ dm_get_info(mpp->alias, &dmi);
|
||||||
|
+ if (!dmi) /* assume we do need to reload the device */
|
||||||
|
+ return true;
|
||||||
|
+ if (dmi->read_only == ro) {
|
||||||
|
+ free(dmi);
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ free(dmi);
|
||||||
|
+ if (ro == 1)
|
||||||
|
+ return true;
|
||||||
|
+ vector_foreach_slot (mpp->pg, pgp, i) {
|
||||||
|
+ vector_foreach_slot (pgp->paths, pp, j) {
|
||||||
|
+ if (sysfs_get_ro(pp) == 1)
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
uev_update_path (struct uevent *uev, struct vectors * vecs)
|
||||||
|
{
|
||||||
|
@@ -1321,7 +1350,7 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
|
||||||
|
}
|
||||||
|
|
||||||
|
ro = uevent_get_disk_ro(uev);
|
||||||
|
- if (mpp && ro >= 0) {
|
||||||
|
+ if (needs_ro_update(mpp, ro)) {
|
||||||
|
condlog(2, "%s: update path write_protect to '%d' (uevent)", uev->kernel, ro);
|
||||||
|
|
||||||
|
if (mpp->wait_for_udev)
|
@ -0,0 +1,133 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 17 Jan 2022 14:45:38 -0600
|
||||||
|
Subject: [PATCH] libmultipath: make helper function to trigger path uevents
|
||||||
|
|
||||||
|
Pull the code that checks if a path needs to trigger a uevent, and
|
||||||
|
triggers, out of trigger_paths_udev_change() and into a new function,
|
||||||
|
trigger_path_udev_change(). This function will be used separately by
|
||||||
|
a future patch. No functional changes.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/configure.c | 79 +++++++++++++++++++++-------------------
|
||||||
|
libmultipath/configure.h | 1 +
|
||||||
|
2 files changed, 43 insertions(+), 37 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
||||||
|
index 9c8d3e34..9a9890f5 100644
|
||||||
|
--- a/libmultipath/configure.c
|
||||||
|
+++ b/libmultipath/configure.c
|
||||||
|
@@ -545,11 +545,8 @@ unref:
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
-trigger_paths_udev_change(struct multipath *mpp, bool is_mpath)
|
||||||
|
+trigger_path_udev_change(struct path *pp, bool is_mpath)
|
||||||
|
{
|
||||||
|
- struct pathgroup *pgp;
|
||||||
|
- struct path *pp;
|
||||||
|
- int i, j;
|
||||||
|
/*
|
||||||
|
* If a path changes from multipath to non-multipath, we must
|
||||||
|
* synthesize an artificial "add" event, otherwise the LVM2 rules
|
||||||
|
@@ -557,6 +554,45 @@ trigger_paths_udev_change(struct multipath *mpp, bool is_mpath)
|
||||||
|
* irritate ourselves with an "add", so use "change".
|
||||||
|
*/
|
||||||
|
const char *action = is_mpath ? "change" : "add";
|
||||||
|
+ const char *env;
|
||||||
|
+
|
||||||
|
+ if (!pp->udev)
|
||||||
|
+ return;
|
||||||
|
+ /*
|
||||||
|
+ * Paths that are already classified as multipath
|
||||||
|
+ * members don't need another uevent.
|
||||||
|
+ */
|
||||||
|
+ env = udev_device_get_property_value(
|
||||||
|
+ pp->udev, "DM_MULTIPATH_DEVICE_PATH");
|
||||||
|
+
|
||||||
|
+ if (is_mpath && env != NULL && !strcmp(env, "1")) {
|
||||||
|
+ /*
|
||||||
|
+ * If FIND_MULTIPATHS_WAIT_UNTIL is not "0",
|
||||||
|
+ * path is in "maybe" state and timer is running
|
||||||
|
+ * Send uevent now (see multipath.rules).
|
||||||
|
+ */
|
||||||
|
+ env = udev_device_get_property_value(
|
||||||
|
+ pp->udev, "FIND_MULTIPATHS_WAIT_UNTIL");
|
||||||
|
+ if (env == NULL || !strcmp(env, "0"))
|
||||||
|
+ return;
|
||||||
|
+ } else if (!is_mpath &&
|
||||||
|
+ (env == NULL || !strcmp(env, "0")))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ condlog(3, "triggering %s uevent for %s (is %smultipath member)",
|
||||||
|
+ action, pp->dev, is_mpath ? "" : "no ");
|
||||||
|
+ sysfs_attr_set_value(pp->udev, "uevent",
|
||||||
|
+ action, strlen(action));
|
||||||
|
+ trigger_partitions_udev_change(pp->udev, action,
|
||||||
|
+ strlen(action));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+trigger_paths_udev_change(struct multipath *mpp, bool is_mpath)
|
||||||
|
+{
|
||||||
|
+ struct pathgroup *pgp;
|
||||||
|
+ struct path *pp;
|
||||||
|
+ int i, j;
|
||||||
|
|
||||||
|
if (!mpp || !mpp->pg)
|
||||||
|
return;
|
||||||
|
@@ -564,39 +600,8 @@ trigger_paths_udev_change(struct multipath *mpp, bool is_mpath)
|
||||||
|
vector_foreach_slot (mpp->pg, pgp, i) {
|
||||||
|
if (!pgp->paths)
|
||||||
|
continue;
|
||||||
|
- vector_foreach_slot(pgp->paths, pp, j) {
|
||||||
|
- const char *env;
|
||||||
|
-
|
||||||
|
- if (!pp->udev)
|
||||||
|
- continue;
|
||||||
|
- /*
|
||||||
|
- * Paths that are already classified as multipath
|
||||||
|
- * members don't need another uevent.
|
||||||
|
- */
|
||||||
|
- env = udev_device_get_property_value(
|
||||||
|
- pp->udev, "DM_MULTIPATH_DEVICE_PATH");
|
||||||
|
-
|
||||||
|
- if (is_mpath && env != NULL && !strcmp(env, "1")) {
|
||||||
|
- /*
|
||||||
|
- * If FIND_MULTIPATHS_WAIT_UNTIL is not "0",
|
||||||
|
- * path is in "maybe" state and timer is running
|
||||||
|
- * Send uevent now (see multipath.rules).
|
||||||
|
- */
|
||||||
|
- env = udev_device_get_property_value(
|
||||||
|
- pp->udev, "FIND_MULTIPATHS_WAIT_UNTIL");
|
||||||
|
- if (env == NULL || !strcmp(env, "0"))
|
||||||
|
- continue;
|
||||||
|
- } else if (!is_mpath &&
|
||||||
|
- (env == NULL || !strcmp(env, "0")))
|
||||||
|
- continue;
|
||||||
|
-
|
||||||
|
- condlog(3, "triggering %s uevent for %s (is %smultipath member)",
|
||||||
|
- action, pp->dev, is_mpath ? "" : "no ");
|
||||||
|
- sysfs_attr_set_value(pp->udev, "uevent",
|
||||||
|
- action, strlen(action));
|
||||||
|
- trigger_partitions_udev_change(pp->udev, action,
|
||||||
|
- strlen(action));
|
||||||
|
- }
|
||||||
|
+ vector_foreach_slot(pgp->paths, pp, j)
|
||||||
|
+ trigger_path_udev_change(pp, is_mpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpp->needs_paths_uevent = 0;
|
||||||
|
diff --git a/libmultipath/configure.h b/libmultipath/configure.h
|
||||||
|
index 8a266d31..5cf08d45 100644
|
||||||
|
--- a/libmultipath/configure.h
|
||||||
|
+++ b/libmultipath/configure.h
|
||||||
|
@@ -56,6 +56,7 @@ int get_refwwid (enum mpath_cmds cmd, char * dev, enum devtypes dev_type,
|
||||||
|
vector pathvec, char **wwid);
|
||||||
|
int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh, int is_daemon);
|
||||||
|
struct udev_device *get_udev_device(const char *dev, enum devtypes dev_type);
|
||||||
|
+void trigger_path_udev_change(struct path *pp, bool is_mpath);
|
||||||
|
void trigger_paths_udev_change(struct multipath *mpp, bool is_mpath);
|
||||||
|
void trigger_partitions_udev_change(struct udev_device *dev, const char *action,
|
||||||
|
int len);
|
@ -0,0 +1,40 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 17 Jan 2022 16:46:18 -0600
|
||||||
|
Subject: [PATCH] multipathd: trigger udev change on path addition
|
||||||
|
|
||||||
|
When a multipath device is created for the first time, there is a window
|
||||||
|
where some path devices way be added to the multipath device, but never
|
||||||
|
claimed in udev. This can allow other device owners, like lvm, to think
|
||||||
|
they can use the device.
|
||||||
|
|
||||||
|
When a multipath device is first created, all the existing paths that
|
||||||
|
are not claimed by multipath have a uevent triggered so that they can
|
||||||
|
get claimed. After that, multipath assumes all future paths added to the
|
||||||
|
multipath device will have been claimed by multipath, since the device's
|
||||||
|
WWID is now in the wwids file. This doesn't work for any paths that
|
||||||
|
have already been processed by the multipath.rules udev rules before
|
||||||
|
the multipath device was created.
|
||||||
|
|
||||||
|
To close this window, when path device is added, and a matching
|
||||||
|
multipath device already exists, multipathd now checks if the device is
|
||||||
|
claimed by multipath, and if not, triggers a uevent to claim it.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
multipathd/main.c | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
|
index e2b9d546..f4b79882 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -1005,6 +1005,8 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map)
|
||||||
|
free_path(pp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
+ if (mpp)
|
||||||
|
+ trigger_path_udev_change(pp, true);
|
||||||
|
if (mpp && mpp->wait_for_udev &&
|
||||||
|
(pathcount(mpp, PATH_UP) > 0 ||
|
||||||
|
(pathcount(mpp, PATH_GHOST) > 0 &&
|
@ -0,0 +1,149 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 2 Feb 2022 17:00:21 -0600
|
||||||
|
Subject: [PATCH] RH: add support to mpathconf for setting arbitrary default
|
||||||
|
options
|
||||||
|
|
||||||
|
mpathconf now supports --option <name>:[<value>] for setting, changing,
|
||||||
|
or removing options from the defaults section of multipath.conf.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
multipath/mpathconf | 58 ++++++++++++++++++++++++++++++++++++++++---
|
||||||
|
multipath/mpathconf.8 | 7 ++++++
|
||||||
|
2 files changed, 62 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/multipath/mpathconf b/multipath/mpathconf
|
||||||
|
index 5f2285ab..870512c0 100644
|
||||||
|
--- a/multipath/mpathconf
|
||||||
|
+++ b/multipath/mpathconf
|
||||||
|
@@ -17,7 +17,7 @@
|
||||||
|
# This program was largely ripped off from lvmconf
|
||||||
|
#
|
||||||
|
|
||||||
|
-unset ENABLE FIND FRIENDLY PROPERTY FOREIGN MODULE MULTIPATHD HAVE_DISABLE HAVE_WWID_DISABLE HAVE_FIND HAVE_BLACKLIST HAVE_EXCEPTIONS HAVE_DEFAULTS HAVE_FRIENDLY HAVE_PROPERTY HAVE_FOREIGN HAVE_MULTIPATHD HAVE_MODULE HAVE_OUTFILE SHOW_STATUS CHANGED_CONFIG WWID_LIST
|
||||||
|
+unset ENABLE FIND FRIENDLY PROPERTY FOREIGN MODULE MULTIPATHD HAVE_DISABLE HAVE_WWID_DISABLE HAVE_FIND HAVE_BLACKLIST HAVE_EXCEPTIONS HAVE_DEFAULTS HAVE_FRIENDLY HAVE_PROPERTY HAVE_FOREIGN HAVE_MULTIPATHD HAVE_MODULE HAVE_OUTFILE SHOW_STATUS CHANGED_CONFIG WWID_LIST HAVE_OPTION OPTION_NAME OPTION_VALUE
|
||||||
|
|
||||||
|
DEFAULT_CONFIG="# device-mapper-multipath configuration file
|
||||||
|
|
||||||
|
@@ -57,6 +57,7 @@ function usage
|
||||||
|
echo "Set find_multipaths (Default y): --find_multipaths <yes|no|strict|greedy|smart>"
|
||||||
|
echo "Set default property blacklist (Default y): --property_blacklist <y|n>"
|
||||||
|
echo "Set enable_foreign to show foreign devices (Default n): --enable_foreign <y|n>"
|
||||||
|
+ echo "Add/Change/Remove option in defaults section: --option <option_name>:<value>"
|
||||||
|
echo "Load the dm-multipath modules on enable (Default y): --with_module <y|n>"
|
||||||
|
echo "start/stop/reload multipathd (Default n): --with_multipathd <y|n>"
|
||||||
|
echo "select output file (Default /etc/multipath.conf): --outfile <FILE>"
|
||||||
|
@@ -167,6 +168,20 @@ function parse_args
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
+ --option)
|
||||||
|
+ if [ -n "$2" ]; then
|
||||||
|
+ OPTION_NAME=$(echo $2 | cut -s -f1 -d:)
|
||||||
|
+ OPTION_VALUE=$(echo $2 | cut -s -f2 -d:)
|
||||||
|
+ if [ -z "$OPTION_NAME" ]; then
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ shift 2
|
||||||
|
+ else
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ ;;
|
||||||
|
--enable_foreign)
|
||||||
|
if [ -n "$2" ]; then
|
||||||
|
FOREIGN=$2
|
||||||
|
@@ -213,12 +228,15 @@ function parse_args
|
||||||
|
|
||||||
|
function validate_args
|
||||||
|
{
|
||||||
|
- if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$PROPERTY" -o -n "$MODULE" ]; then
|
||||||
|
+ if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$PROPERTY" -o -n "$MODULE" -o -n "$FOREIGN" -o -n "$OPTION_NAME" ]; then
|
||||||
|
echo "ignoring extra parameters on disable"
|
||||||
|
FRIENDLY=""
|
||||||
|
FIND=""
|
||||||
|
PROPERTY=""
|
||||||
|
MODULE=""
|
||||||
|
+ FOREIGN=""
|
||||||
|
+ OPTION_NAME=""
|
||||||
|
+ OPTION_VALUE=""
|
||||||
|
fi
|
||||||
|
if [ -n "$FRIENDLY" ] && [ "$FRIENDLY" != "y" -a "$FRIENDLY" != "n" ]; then
|
||||||
|
echo "--user_friendly_names must be either 'y' or 'n'"
|
||||||
|
@@ -240,7 +258,19 @@ function validate_args
|
||||||
|
echo "--enable_foreign must be either 'y' or 'n'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
- if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" -a -z "$PROPERTY" -a -z "$FOREIGN" ]; then
|
||||||
|
+ if [ -n "$OPTION_NAME" ]; then
|
||||||
|
+ if [[ $OPTION_NAME =~ [[:space:]]|#|\"|!|\{|\} ]]; then
|
||||||
|
+ echo "--option name \"$OPTION_NAME\" is invalid"
|
||||||
|
+ exit 1
|
||||||
|
+ elif [[ $OPTION_VALUE =~ \"|#|!|\{|\} ]]; then
|
||||||
|
+ echo "--option value \"$OPTION_VALUE\" is invalid"
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ if [[ $OPTION_VALUE =~ [[:space:]] ]]; then
|
||||||
|
+ OPTION_VALUE=\"$OPTION_VALUE\"
|
||||||
|
+ fi
|
||||||
|
+ fi
|
||||||
|
+ if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" -a -z "$PROPERTY" -a -z "$FOREIGN" -a -z "$OPTION_NAME" ]; then
|
||||||
|
SHOW_STATUS=1
|
||||||
|
fi
|
||||||
|
if [ -n "$MODULE" ] && [ "$MODULE" != "y" -a "$MODULE" != "n" ]; then
|
||||||
|
@@ -349,6 +379,13 @@ if [ "$HAVE_DEFAULTS" = "1" ]; then
|
||||||
|
elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign" ; then
|
||||||
|
HAVE_FOREIGN=2
|
||||||
|
fi
|
||||||
|
+ if [ -n "$OPTION_NAME" ]; then
|
||||||
|
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q '^[[:space:]]*'"$OPTION_NAME"'[[:space:]][[:space:]]*'"$OPTION_VALUE" ; then
|
||||||
|
+ HAVE_OPTION=1
|
||||||
|
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q '^[[:space:]]*'"$OPTION_NAME"'\([[:space:]].*\)\?$' ; then
|
||||||
|
+ HAVE_OPTION=0
|
||||||
|
+ fi
|
||||||
|
+ fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$HAVE_EXCEPTIONS" = "1" ]; then
|
||||||
|
@@ -523,6 +560,21 @@ elif [ "$FOREIGN" = "n" ]; then
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
+if [ -n "$OPTION_NAME" -a -n "$OPTION_VALUE" ]; then
|
||||||
|
+ if [ -z "$HAVE_OPTION" ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/ a\
|
||||||
|
+ '"$OPTION_NAME"' '"$OPTION_VALUE"'
|
||||||
|
+' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ elif [ "$HAVE_OPTION" = 0 ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*'"$OPTION_NAME"'\([[:space:]].*\)\?$/ '"$OPTION_NAME"' '"$OPTION_VALUE"'/' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ fi
|
||||||
|
+elif [ -n "$OPTION_NAME" -a -n "$HAVE_OPTION" ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/{/^[[:space:]]*'"$OPTION_NAME"'\([[:space:]].*\)\?$/d}' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
if [ -f "$OUTPUTFILE" ]; then
|
||||||
|
cp $OUTPUTFILE $OUTPUTFILE.old
|
||||||
|
if [ $? != 0 ]; then
|
||||||
|
diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8
|
||||||
|
index 83515eb4..63fe633e 100644
|
||||||
|
--- a/multipath/mpathconf.8
|
||||||
|
+++ b/multipath/mpathconf.8
|
||||||
|
@@ -101,6 +101,13 @@ to the
|
||||||
|
defaults section. if set to \fBy\fP, this removes the line, if present. This
|
||||||
|
command can be used along with any other command.
|
||||||
|
.TP
|
||||||
|
+.B --option \fB<option_name>:[<value>]\fP
|
||||||
|
+Sets the defaults section option \fB<option_name>\fP to \fB<value>\fP. If the
|
||||||
|
+option was not previously set in the defaults section, it is added. If it was
|
||||||
|
+set, its value is changed to \fB<value>\fP. If \fB<value>\fP is left blank,
|
||||||
|
+then the option is removed from the defaults section, if was set there. This
|
||||||
|
+command can be used along with any other command.
|
||||||
|
+.TP
|
||||||
|
.B --outfile \fB<filename>\fP
|
||||||
|
Write the resulting multipath configuration to \fB<filename>\fP instead of
|
||||||
|
\fB/etc/multipath.conf\fP.
|
@ -0,0 +1,31 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Xose Vazquez Perez <xose.vazquez@gmail.com>
|
||||||
|
Date: Wed, 9 Sep 2020 17:48:05 +0200
|
||||||
|
Subject: [PATCH] multipath-tools: add HPE MSA 1060/2060 to hwtable
|
||||||
|
|
||||||
|
Cc: Martin Wilck <mwilck@suse.com>
|
||||||
|
Cc: Christophe Varoqui <christophe.varoqui@opensvc.com>
|
||||||
|
Cc: DM-DEVEL ML <dm-devel@redhat.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Xose Vazquez Perez <xose.vazquez@gmail.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/hwtable.c | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
|
||||||
|
index d680bdfc..59bc0d6e 100644
|
||||||
|
--- a/libmultipath/hwtable.c
|
||||||
|
+++ b/libmultipath/hwtable.c
|
||||||
|
@@ -181,9 +181,9 @@ static struct hwentry default_hw[] = {
|
||||||
|
.prio_name = PRIO_ALUA,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
- /* MSA 1040, 1050, 2040 and 2050 families */
|
||||||
|
+ /* MSA 1040, 1050, 1060, 2040, 2050 and 2060 families */
|
||||||
|
.vendor = "HP",
|
||||||
|
- .product = "MSA [12]0[45]0 SA[NS]",
|
||||||
|
+ .product = "MSA [12]0[456]0 SA[NS]",
|
||||||
|
.pgpolicy = GROUP_BY_PRIO,
|
||||||
|
.pgfailback = -FAILBACK_IMMEDIATE,
|
||||||
|
.no_path_retry = 18,
|
@ -0,0 +1,78 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Uday Shankar <ushankar@purestorage.com>
|
||||||
|
Date: Wed, 9 Mar 2022 13:03:26 -0700
|
||||||
|
Subject: [PATCH] multipath-tools: update mpp->force_readonly in ev_add_path
|
||||||
|
|
||||||
|
When NVMe disks are added to the system, no uevent containing the
|
||||||
|
DISK_RO property is generated. As a result, dm-* nodes backed by
|
||||||
|
readonly NVMe disks will not have their RO state set properly. The
|
||||||
|
result looks like this:
|
||||||
|
|
||||||
|
$ multipath -l
|
||||||
|
eui.00c92c091fd6564424a9376600011bd1 dm-3 NVME,Pure Storage FlashArray
|
||||||
|
size=1.0T features='0' hwhandler='0' wp=rw
|
||||||
|
|-+- policy='service-time 0' prio=0 status=active
|
||||||
|
| `- 0:2:2:72657 nvme0n2 259:4 active undef running
|
||||||
|
`-+- policy='service-time 0' prio=0 status=enabled
|
||||||
|
`- 1:0:2:72657 nvme1n2 259:1 active undef running
|
||||||
|
$ cat /sys/block/dm-3/ro
|
||||||
|
0
|
||||||
|
$ cat /sys/block/nvme*n2/ro
|
||||||
|
1
|
||||||
|
1
|
||||||
|
|
||||||
|
This is not a problem for SCSI disks, since the kernel will emit change
|
||||||
|
uevents containing the DISK_RO property when the disk is added to the
|
||||||
|
system. See the following thread for my initial attempt to fix this
|
||||||
|
issue at the kernel level:
|
||||||
|
https://lore.kernel.org/linux-block/Yib8GqCA5e3SQYty@infradead.org/T/#t
|
||||||
|
|
||||||
|
Fix the issue by picking up the path ro state from sysfs in ev_add_path,
|
||||||
|
setting the mpp->force_readonly accordingly, and changing
|
||||||
|
dm_addmap_create to be aware of mpp->force_readonly.
|
||||||
|
|
||||||
|
Signed-off-by: Uday Shankar <ushankar@purestorage.com>
|
||||||
|
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/devmapper.c | 2 +-
|
||||||
|
multipathd/main.c | 6 ++++++
|
||||||
|
2 files changed, 7 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||||
|
index 3f70e576..e3c3c119 100644
|
||||||
|
--- a/libmultipath/devmapper.c
|
||||||
|
+++ b/libmultipath/devmapper.c
|
||||||
|
@@ -420,7 +420,7 @@ int dm_addmap_create (struct multipath *mpp, char * params)
|
||||||
|
int ro;
|
||||||
|
uint16_t udev_flags = build_udev_flags(mpp, 0);
|
||||||
|
|
||||||
|
- for (ro = 0; ro <= 1; ro++) {
|
||||||
|
+ for (ro = mpp->force_readonly ? 1 : 0; ro <= 1; ro++) {
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, mpp, params, ro,
|
||||||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
|
index f4b79882..eeded52b 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -988,6 +988,7 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map)
|
||||||
|
int retries = 3;
|
||||||
|
int start_waiter = 0;
|
||||||
|
int ret;
|
||||||
|
+ int ro;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* need path UID to go any further
|
||||||
|
@@ -1051,6 +1052,11 @@ rescan:
|
||||||
|
/* persistent reservation check*/
|
||||||
|
mpath_pr_event_handle(pp);
|
||||||
|
|
||||||
|
+ /* ro check - if new path is ro, force map to be ro as well */
|
||||||
|
+ ro = sysfs_get_ro(pp);
|
||||||
|
+ if (ro == 1)
|
||||||
|
+ mpp->force_readonly = 1;
|
||||||
|
+
|
||||||
|
if (!need_do_map)
|
||||||
|
return 0;
|
||||||
|
|
@ -0,0 +1,28 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Fri, 29 Apr 2022 15:57:12 -0500
|
||||||
|
Subject: [PATCH] updated HPE MSA builtin config
|
||||||
|
|
||||||
|
Make the config better align to MSA 4th, 5th and 6th Generation systems.
|
||||||
|
|
||||||
|
Cc: Jon.Paul@hpe.com
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/hwtable.c | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
|
||||||
|
index 59bc0d6e..d6325864 100644
|
||||||
|
--- a/libmultipath/hwtable.c
|
||||||
|
+++ b/libmultipath/hwtable.c
|
||||||
|
@@ -182,8 +182,8 @@ static struct hwentry default_hw[] = {
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* MSA 1040, 1050, 1060, 2040, 2050 and 2060 families */
|
||||||
|
- .vendor = "HP",
|
||||||
|
- .product = "MSA [12]0[456]0 SA[NS]",
|
||||||
|
+ .vendor = "(HP|HPE)",
|
||||||
|
+ .product = "MSA [12]0[456]0 (SAN|SAS|FC|iSCSI)",
|
||||||
|
.pgpolicy = GROUP_BY_PRIO,
|
||||||
|
.pgfailback = -FAILBACK_IMMEDIATE,
|
||||||
|
.no_path_retry = 18,
|
@ -0,0 +1,35 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 30 Mar 2022 15:14:56 -0500
|
||||||
|
Subject: [PATCH] multipath: return failure on an invalid remove command
|
||||||
|
|
||||||
|
When "multipath -f" is run on a device that doesn't exist or isn't a
|
||||||
|
multipath device, the command will not remove any device, but it will
|
||||||
|
still return success. Multiple functions rely on _dm_flush_map()
|
||||||
|
returning success when called with name that doesn't match any
|
||||||
|
multipath device. So before calling _dm_flush_map(), call dm_is_mpath(),
|
||||||
|
to check if the device exists and is a multipath device, and return
|
||||||
|
failure if it's not.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com
|
||||||
|
---
|
||||||
|
multipath/main.c | 5 +++++
|
||||||
|
1 file changed, 5 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/multipath/main.c b/multipath/main.c
|
||||||
|
index 14d045c9..d5e6499c 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -1150,6 +1150,11 @@ main (int argc, char *argv[])
|
||||||
|
if (retries < 0)
|
||||||
|
retries = conf->remove_retries;
|
||||||
|
if (cmd == CMD_FLUSH_ONE) {
|
||||||
|
+ if (dm_is_mpath(dev) != 1) {
|
||||||
|
+ condlog(0, "%s is not a multipath device", dev);
|
||||||
|
+ r = RTVL_FAIL;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
r = dm_suspend_and_flush_map(dev, retries) ?
|
||||||
|
RTVL_FAIL : RTVL_OK;
|
||||||
|
goto out;
|
@ -0,0 +1,67 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 13 Apr 2022 23:27:35 -0500
|
||||||
|
Subject: [PATCH] libmultipath: steal the src string pointer in merge_str()
|
||||||
|
|
||||||
|
Instead of allocating a copy when the original string is going to be
|
||||||
|
freed right after the merge, just steal the pointer. Also, merge_mpe()
|
||||||
|
can't get called with NULL arguments.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.c | 16 +++++-----------
|
||||||
|
1 file changed, 5 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||||
|
index abbddaf1..aa79561e 100644
|
||||||
|
--- a/libmultipath/config.c
|
||||||
|
+++ b/libmultipath/config.c
|
||||||
|
@@ -323,9 +323,9 @@ set_param_str(const char * str)
|
||||||
|
}
|
||||||
|
|
||||||
|
#define merge_str(s) \
|
||||||
|
- if (!dst->s && src->s) { \
|
||||||
|
- if (!(dst->s = set_param_str(src->s))) \
|
||||||
|
- return 1; \
|
||||||
|
+ if (!dst->s && src->s && strlen(src->s)) { \
|
||||||
|
+ dst->s = src->s; \
|
||||||
|
+ src->s = NULL; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define merge_num(s) \
|
||||||
|
@@ -333,7 +333,7 @@ set_param_str(const char * str)
|
||||||
|
dst->s = src->s
|
||||||
|
|
||||||
|
|
||||||
|
-static int
|
||||||
|
+static void
|
||||||
|
merge_hwe (struct hwentry * dst, struct hwentry * src)
|
||||||
|
{
|
||||||
|
char id[SCSI_VENDOR_SIZE+PATH_PRODUCT_SIZE];
|
||||||
|
@@ -385,15 +385,11 @@ merge_hwe (struct hwentry * dst, struct hwentry * src)
|
||||||
|
reconcile_features_with_options(id, &dst->features,
|
||||||
|
&dst->no_path_retry,
|
||||||
|
&dst->retain_hwhandler);
|
||||||
|
- return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int
|
||||||
|
+static void
|
||||||
|
merge_mpe(struct mpentry *dst, struct mpentry *src)
|
||||||
|
{
|
||||||
|
- if (!dst || !src)
|
||||||
|
- return 1;
|
||||||
|
-
|
||||||
|
merge_str(alias);
|
||||||
|
merge_str(uid_attribute);
|
||||||
|
merge_str(getuid);
|
||||||
|
@@ -435,8 +431,6 @@ merge_mpe(struct mpentry *dst, struct mpentry *src)
|
||||||
|
merge_num(uid);
|
||||||
|
merge_num(gid);
|
||||||
|
merge_num(mode);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void merge_mptable(vector mptable)
|
@ -0,0 +1,75 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Thu, 17 Feb 2022 17:22:32 +0100
|
||||||
|
Subject: [PATCH] libmultipath: enable linear ordering of bus/proto tuple
|
||||||
|
|
||||||
|
We categorized protocols by bus/proto_id, while we only differentiate
|
||||||
|
protocol IDs for SCSI. Allow transforming this into a linear sequence
|
||||||
|
of bus/protocol IDs by having non-SCSI first, and follwing up with
|
||||||
|
the different SCSI protocols.
|
||||||
|
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/structs.c | 10 ++++++++++
|
||||||
|
libmultipath/structs.h | 14 ++++++++++++--
|
||||||
|
2 files changed, 22 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
|
||||||
|
index dda9884c..aaf85297 100644
|
||||||
|
--- a/libmultipath/structs.c
|
||||||
|
+++ b/libmultipath/structs.c
|
||||||
|
@@ -722,3 +722,13 @@ out:
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+unsigned int bus_protocol_id(const struct path *pp) {
|
||||||
|
+ if (!pp || pp->bus < 0 || pp->bus > SYSFS_BUS_SCSI)
|
||||||
|
+ return SYSFS_BUS_UNDEF;
|
||||||
|
+ if (pp->bus != SYSFS_BUS_SCSI)
|
||||||
|
+ return pp->bus;
|
||||||
|
+ if ((int)pp->sg_id.proto_id < 0 || pp->sg_id.proto_id > SCSI_PROTOCOL_UNSPEC)
|
||||||
|
+ return SYSFS_BUS_UNDEF;
|
||||||
|
+ return SYSFS_BUS_SCSI + pp->sg_id.proto_id;
|
||||||
|
+}
|
||||||
|
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
||||||
|
index a5dbad5b..5e29ae38 100644
|
||||||
|
--- a/libmultipath/structs.h
|
||||||
|
+++ b/libmultipath/structs.h
|
||||||
|
@@ -57,12 +57,13 @@ enum failback_mode {
|
||||||
|
FAILBACK_FOLLOWOVER
|
||||||
|
};
|
||||||
|
|
||||||
|
+/* SYSFS_BUS_SCSI should be last, see bus_protocol_id() */
|
||||||
|
enum sysfs_buses {
|
||||||
|
SYSFS_BUS_UNDEF,
|
||||||
|
- SYSFS_BUS_SCSI,
|
||||||
|
SYSFS_BUS_CCW,
|
||||||
|
SYSFS_BUS_CCISS,
|
||||||
|
SYSFS_BUS_NVME,
|
||||||
|
+ SYSFS_BUS_SCSI,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum pathstates {
|
||||||
|
@@ -190,9 +191,18 @@ enum scsi_protocol {
|
||||||
|
SCSI_PROTOCOL_SAS = 6,
|
||||||
|
SCSI_PROTOCOL_ADT = 7, /* Media Changers */
|
||||||
|
SCSI_PROTOCOL_ATA = 8,
|
||||||
|
- SCSI_PROTOCOL_UNSPEC = 0xf, /* No specific protocol */
|
||||||
|
+ SCSI_PROTOCOL_USB = 9, /* USB Attached SCSI (UAS), and others */
|
||||||
|
+ SCSI_PROTOCOL_UNSPEC = 0xa, /* No specific protocol */
|
||||||
|
};
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Linear ordering of bus/protocol
|
||||||
|
+ * This assumes that SYSFS_BUS_SCSI is last in enum sysfs_buses
|
||||||
|
+ * SCSI is the only bus type for which we distinguish protocols.
|
||||||
|
+ */
|
||||||
|
+#define LAST_BUS_PROTOCOL_ID (SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC)
|
||||||
|
+unsigned int bus_protocol_id(const struct path *pp);
|
||||||
|
+
|
||||||
|
enum no_undef_states {
|
||||||
|
NU_NO = -1,
|
||||||
|
NU_UNDEF = 0,
|
@ -0,0 +1,82 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Thu, 17 Feb 2022 17:24:25 +0100
|
||||||
|
Subject: [PATCH] libmultipath: use bus_protocol_id() in
|
||||||
|
snprint_path_protocol()
|
||||||
|
|
||||||
|
Simplify bus_protocol_id() by using the linear ordering.
|
||||||
|
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/print.c | 56 +++++++++++++++++---------------------------
|
||||||
|
1 file changed, 21 insertions(+), 35 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/print.c b/libmultipath/print.c
|
||||||
|
index 298b3764..ff4d1854 100644
|
||||||
|
--- a/libmultipath/print.c
|
||||||
|
+++ b/libmultipath/print.c
|
||||||
|
@@ -662,41 +662,27 @@ snprint_path_failures(char * buff, size_t len, const struct path * pp)
|
||||||
|
int
|
||||||
|
snprint_path_protocol(char * buff, size_t len, const struct path * pp)
|
||||||
|
{
|
||||||
|
- switch (pp->bus) {
|
||||||
|
- case SYSFS_BUS_SCSI:
|
||||||
|
- switch (pp->sg_id.proto_id) {
|
||||||
|
- case SCSI_PROTOCOL_FCP:
|
||||||
|
- return snprintf(buff, len, "scsi:fcp");
|
||||||
|
- case SCSI_PROTOCOL_SPI:
|
||||||
|
- return snprintf(buff, len, "scsi:spi");
|
||||||
|
- case SCSI_PROTOCOL_SSA:
|
||||||
|
- return snprintf(buff, len, "scsi:ssa");
|
||||||
|
- case SCSI_PROTOCOL_SBP:
|
||||||
|
- return snprintf(buff, len, "scsi:sbp");
|
||||||
|
- case SCSI_PROTOCOL_SRP:
|
||||||
|
- return snprintf(buff, len, "scsi:srp");
|
||||||
|
- case SCSI_PROTOCOL_ISCSI:
|
||||||
|
- return snprintf(buff, len, "scsi:iscsi");
|
||||||
|
- case SCSI_PROTOCOL_SAS:
|
||||||
|
- return snprintf(buff, len, "scsi:sas");
|
||||||
|
- case SCSI_PROTOCOL_ADT:
|
||||||
|
- return snprintf(buff, len, "scsi:adt");
|
||||||
|
- case SCSI_PROTOCOL_ATA:
|
||||||
|
- return snprintf(buff, len, "scsi:ata");
|
||||||
|
- case SCSI_PROTOCOL_UNSPEC:
|
||||||
|
- default:
|
||||||
|
- return snprintf(buff, len, "scsi:unspec");
|
||||||
|
- }
|
||||||
|
- case SYSFS_BUS_CCW:
|
||||||
|
- return snprintf(buff, len, "ccw");
|
||||||
|
- case SYSFS_BUS_CCISS:
|
||||||
|
- return snprintf(buff, len, "cciss");
|
||||||
|
- case SYSFS_BUS_NVME:
|
||||||
|
- return snprintf(buff, len, "nvme");
|
||||||
|
- case SYSFS_BUS_UNDEF:
|
||||||
|
- default:
|
||||||
|
- return snprintf(buff, len, "undef");
|
||||||
|
- }
|
||||||
|
+ static const char * const protocol_name[LAST_BUS_PROTOCOL_ID + 1] = {
|
||||||
|
+ [SYSFS_BUS_UNDEF] = "undef",
|
||||||
|
+ [SYSFS_BUS_CCW] = "ccw",
|
||||||
|
+ [SYSFS_BUS_CCISS] = "cciss",
|
||||||
|
+ [SYSFS_BUS_NVME] = "nvme",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_FCP] = "scsi:fcp",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SPI] = "scsi:spi",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SSA] = "scsi:ssa",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SBP] = "scsi:sbp",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SRP] = "scsi:srp",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ISCSI] = "scsi:iscsi",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SAS] = "scsi:sas",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ADT] = "scsi:adt",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ATA] = "scsi:ata",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_USB] = "scsi:usb",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC] = "scsi:unspec",
|
||||||
|
+ };
|
||||||
|
+ const char *pn = protocol_name[bus_protocol_id(pp)];
|
||||||
|
+
|
||||||
|
+ assert(pn != NULL);
|
||||||
|
+ return snprintf(buff, len, "%s", pn);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
@ -0,0 +1,85 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 13 Apr 2022 23:27:36 -0500
|
||||||
|
Subject: [PATCH] libmultipath: make protocol_name global
|
||||||
|
|
||||||
|
Future patches will make use of this, so move it out of
|
||||||
|
snprint_path_protocol()
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
---
|
||||||
|
libmultipath/print.c | 17 -----------------
|
||||||
|
libmultipath/structs.c | 18 ++++++++++++++++++
|
||||||
|
libmultipath/structs.h | 1 +
|
||||||
|
3 files changed, 19 insertions(+), 17 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/print.c b/libmultipath/print.c
|
||||||
|
index ff4d1854..1f6d27bd 100644
|
||||||
|
--- a/libmultipath/print.c
|
||||||
|
+++ b/libmultipath/print.c
|
||||||
|
@@ -662,23 +662,6 @@ snprint_path_failures(char * buff, size_t len, const struct path * pp)
|
||||||
|
int
|
||||||
|
snprint_path_protocol(char * buff, size_t len, const struct path * pp)
|
||||||
|
{
|
||||||
|
- static const char * const protocol_name[LAST_BUS_PROTOCOL_ID + 1] = {
|
||||||
|
- [SYSFS_BUS_UNDEF] = "undef",
|
||||||
|
- [SYSFS_BUS_CCW] = "ccw",
|
||||||
|
- [SYSFS_BUS_CCISS] = "cciss",
|
||||||
|
- [SYSFS_BUS_NVME] = "nvme",
|
||||||
|
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_FCP] = "scsi:fcp",
|
||||||
|
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SPI] = "scsi:spi",
|
||||||
|
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SSA] = "scsi:ssa",
|
||||||
|
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SBP] = "scsi:sbp",
|
||||||
|
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SRP] = "scsi:srp",
|
||||||
|
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ISCSI] = "scsi:iscsi",
|
||||||
|
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SAS] = "scsi:sas",
|
||||||
|
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ADT] = "scsi:adt",
|
||||||
|
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ATA] = "scsi:ata",
|
||||||
|
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_USB] = "scsi:usb",
|
||||||
|
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC] = "scsi:unspec",
|
||||||
|
- };
|
||||||
|
const char *pn = protocol_name[bus_protocol_id(pp)];
|
||||||
|
|
||||||
|
assert(pn != NULL);
|
||||||
|
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
|
||||||
|
index aaf85297..19099bed 100644
|
||||||
|
--- a/libmultipath/structs.c
|
||||||
|
+++ b/libmultipath/structs.c
|
||||||
|
@@ -20,6 +20,24 @@
|
||||||
|
#include "prioritizers/alua_spc3.h"
|
||||||
|
#include "dm-generic.h"
|
||||||
|
|
||||||
|
+const char * const protocol_name[LAST_BUS_PROTOCOL_ID + 1] = {
|
||||||
|
+ [SYSFS_BUS_UNDEF] = "undef",
|
||||||
|
+ [SYSFS_BUS_CCW] = "ccw",
|
||||||
|
+ [SYSFS_BUS_CCISS] = "cciss",
|
||||||
|
+ [SYSFS_BUS_NVME] = "nvme",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_FCP] = "scsi:fcp",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SPI] = "scsi:spi",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SSA] = "scsi:ssa",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SBP] = "scsi:sbp",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SRP] = "scsi:srp",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ISCSI] = "scsi:iscsi",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SAS] = "scsi:sas",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ADT] = "scsi:adt",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ATA] = "scsi:ata",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_USB] = "scsi:usb",
|
||||||
|
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC] = "scsi:unspec",
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
struct adapter_group *
|
||||||
|
alloc_adaptergroup(void)
|
||||||
|
{
|
||||||
|
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
||||||
|
index 5e29ae38..ab99852f 100644
|
||||||
|
--- a/libmultipath/structs.h
|
||||||
|
+++ b/libmultipath/structs.h
|
||||||
|
@@ -202,6 +202,7 @@ enum scsi_protocol {
|
||||||
|
*/
|
||||||
|
#define LAST_BUS_PROTOCOL_ID (SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC)
|
||||||
|
unsigned int bus_protocol_id(const struct path *pp);
|
||||||
|
+extern const char * const protocol_name[];
|
||||||
|
|
||||||
|
enum no_undef_states {
|
||||||
|
NU_NO = -1,
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue