Compare commits

..

No commits in common. "c9s" and "c8" have entirely different histories.
c9s ... c8

241 changed files with 8911 additions and 14871 deletions

View File

@ -1,2 +1 @@
067d668de8e3a70b7c176bbf0c0616d5835bbe44 multipath-tools-0.8.7.tgz
5d5e16cccc83fd78cf9b95e5c52cc41dbbeb1da7 multipath.conf
b52c2be340449664f0a122070838f6d8edd42e4a SOURCES/multipath-tools-0.8.4.tgz

26
.gitignore vendored
View File

@ -1,25 +1 @@
multipath-tools-091027.tar.gz
/multipath-tools-120123.tgz
/multipath-tools-120613.tgz
/multipath-tools-120821.tgz
/multipath-tools-130222.tgz
/multipath-tools-f21166a.tgz
/multipath.conf
/multipath-tools-git847cc43.tgz
/multipath-tools-0.7.3.tgz
/multipath-tools-07e7bd5.tgz
/multipath-tools-1cb704b.tgz
/multipath-tools-0.7.7.tgz
/multipath-tools-ef6d98b.tgz
/multipath-tools-1a8625a.tgz
/multipath-tools-b80318b.tgz
/multipath-tools-0.7.8.tgz
/multipath-tools-0.7.9.tgz
/multipath-tools-17a6101.tgz
/multipath-tools-2df6110.tgz
/multipath-tools-0.8.0.tgz
/multipath-tools-0.8.2.tgz
/multipath-tools-0.8.4.tgz
/multipath-tools-0.8.5.tgz
/multipath-tools-0.8.6.tgz
/multipath-tools-0.8.7.tgz
SOURCES/multipath-tools-0.8.4.tgz

View File

@ -1,45 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Xose Vazquez Perez <xose.vazquez@gmail.com>
Date: Wed, 8 Sep 2021 22:33:54 +0200
Subject: [PATCH] multipath-tools: add info about IO affinity path selector to
manpage
Added in 5.11: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e4d2e82b2300b03f66b3ca8417590c86e661fab1
Cc: Mike Christie <michael.christie@oracle.com>
Cc: Martin Wilck <mwilck@suse.com>
Cc: Benjamin Marzinski <bmarzins@redhat.com>
Cc: Christophe Varoqui <christophe.varoqui@opensvc.com>
Cc: DM-DEVEL ML <dm-devel@redhat.com>
Signed-off-by: Xose Vazquez Perez <xose.vazquez@gmail.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/multipath.conf.5 | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index d6b8c7f6..42a15ffd 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -6,7 +6,7 @@
.\"
.\" ----------------------------------------------------------------------------
.
-.TH MULTIPATH.CONF 5 2018-05-21 Linux
+.TH MULTIPATH.CONF 5 2021-09-08 Linux
.
.
.\" ----------------------------------------------------------------------------
@@ -210,6 +210,10 @@ of outstanding I/O to the path and its relative throughput.
estimation of future service time based on the history of previous I/O submitted
to each path.
.TP
+.I "io-affinity 0"
+(Since 5.11 kernel) Choose the path for the next bunch of I/O based on a CPU to
+path mapping the user passes in and what CPU we are executing on.
+.TP
The default is: \fBservice-time 0\fR
.RE
.

View File

@ -1,52 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: lixiaokeng <lixiaokeng@huawei.com>
Date: Mon, 13 Sep 2021 10:43:14 +0800
Subject: [PATCH] multipathd: fix missing persistent reseravtion for active
path
There are two paths(sucu as sda and adb) for one LUN. The two
paths log in, but before the two uevents have been processed
(for example there are many uevent), users use multipathd add
path /dev/sda to cause mpatha and use mpathpersist -o -I to
register prkey for mpatha. The add map uevent is after add path
uevent, the the uevent(add sdb) will delay and missing persistent
reseravtion check.
Here, we add persistent reseravtion check in update_map() which
is called ev_add_map().
Signed-off-by: Lixiaokeng <lixiaokeng@huawei.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/main.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/multipathd/main.c b/multipathd/main.c
index 3aff241d..1defeaf1 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -490,6 +490,8 @@ update_map (struct multipath *mpp, struct vectors *vecs, int new_map)
{
int retries = 3;
char *params __attribute__((cleanup(cleanup_charp))) = NULL;
+ struct path *pp;
+ int i;
retry:
condlog(4, "%s: updating new map", mpp->alias);
@@ -502,6 +504,15 @@ retry:
verify_paths(mpp);
mpp->action = ACT_RELOAD;
+ if (mpp->prflag) {
+ vector_foreach_slot(mpp->paths, pp, i) {
+ if ((pp->state == PATH_UP) || (pp->state == PATH_GHOST)) {
+ /* persistent reseravtion check*/
+ mpath_pr_event_handle(pp);
+ }
+ }
+ }
+
if (setup_map(mpp, &params, vecs)) {
condlog(0, "%s: failed to setup new map in update", mpp->alias);
retries = -1;

View File

@ -1,48 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Xose Vazquez Perez <xose.vazquez@gmail.com>
Date: Thu, 16 Sep 2021 00:44:49 +0200
Subject: [PATCH] multipath-tools: minor fixes to multipath.conf.5 man page
Cc: Martin Wilck <mwilck@suse.com>
Cc: Benjamin Marzinski <bmarzins@redhat.com>
Cc: Christophe Varoqui <christophe.varoqui@opensvc.com>
Cc: DM-DEVEL ML <dm-devel@redhat.com>
Signed-off-by: Xose Vazquez Perez <xose.vazquez@gmail.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/multipath.conf.5 | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 42a15ffd..c74129bd 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1,9 +1,9 @@
.\" ----------------------------------------------------------------------------
-.\" Update the date below if you make any significant change.
.\" Make sure there are no errors with:
.\" groff -z -wall -b -e -t multipath/multipath.conf.5
.\" man --warnings -E UTF-8 -l -Tutf8 -Z multipath/multipath.conf.5 >/dev/null
.\"
+.\" Update the date below if you make any significant change.
.\" ----------------------------------------------------------------------------
.
.TH MULTIPATH.CONF 5 2021-09-08 Linux
@@ -189,7 +189,7 @@ The default is: \fB<system dependent>\fR
.TP
.B path_selector
The default path selector algorithm to use; they are offered by the
-kernel multipath target. There are three selector algorithms:
+kernel multipath target:
.RS
.TP 12
.I "round-robin 0"
@@ -206,7 +206,7 @@ of outstanding I/O to the path.
of outstanding I/O to the path and its relative throughput.
.TP
.I "historical-service-time 0"
-(Since 5.8 kernel) Choose the path for the next bunch of IOs based on the
+(Since 5.8 kernel) Choose the path for the next bunch of I/O based on the
estimation of future service time based on the history of previous I/O submitted
to each path.
.TP

View File

@ -1,39 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Xose Vazquez Perez <xose.vazquez@gmail.com>
Date: Sat, 25 Sep 2021 00:27:36 +0200
Subject: [PATCH] multipath-tools: make IBM/XIV config work with alua and
multibus
And add recommended pgfailback value.
ALUA is supported since XIV_Gen2 and microcode 10.2.1
(All ports across all controllers in single Target Port Group)
https://www.ibm.com/support/pages/ibm-flashsystem%C2%AE-a9000-and-a9000r-hyperswap-solution-deployment-linux%C2%AE-ibm-z-systems%C2%AE
https://www.google.com/search?q=%222810XIV%22+%22path_grouping_policy%22+site%3Aibm.com
Cc: Martin Wilck <mwilck@suse.com>
Cc: Benjamin Marzinski <bmarzins@redhat.com>
Cc: Christophe Varoqui <christophe.varoqui@opensvc.com>
Cc: DM-DEVEL ML <dm-devel@redhat.com>
Signed-off-by: Xose Vazquez Perez <xose.vazquez@gmail.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/hwtable.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index 0caac0da..72f81c60 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -712,7 +712,8 @@ static struct hwentry default_hw[] = {
.vendor = "(XIV|IBM)",
.product = "(NEXTRA|2810XIV)",
.no_path_retry = NO_PATH_RETRY_QUEUE,
- .pgpolicy = MULTIBUS,
+ .pgpolicy = GROUP_BY_PRIO,
+ .pgfailback = 15,
},
{
/* TMS RamSan / FlashSystem 710/720/810/820/840/900 */

View File

@ -1,32 +0,0 @@
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
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..c777e5e3 100644
--- a/multipathd/multipathd.socket
+++ b/multipathd/multipathd.socket
@@ -1,6 +1,9 @@
[Unit]
Description=multipathd control socket
DefaultDependencies=no
+ConditionKernelCommandLine=!nompath
+ConditionKernelCommandLine=!multipath=off
+ConditionVirtualization=!container
Before=sockets.target
[Socket]

View File

@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Xose Vazquez Perez <xose.vazquez@gmail.com>
Date: Tue, 28 Sep 2021 18:52:10 +0200
Subject: [PATCH] multipath-tools: make IBM/2107900 (DS8000) config work with
alua and multibus
ALUA is supported since the beginning:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/scsi/device_handler/scsi_dh_alua.c?id=057ea7c9683c3d684128cced796f03c179ecf1c2#n683
... the DS8000 is an Asymmetric Logical Unit Access (ALUA) capable storage array,
pag#160(144): https://www.redbooks.ibm.com/redbooks/pdfs/sg248887.pdf
kernel log:
https://marc.info/?l=linux-scsi&m=156407413807511&q=mbox
Cc: Martin Wilck <mwilck@suse.com>
Cc: Benjamin Marzinski <bmarzins@redhat.com>
Cc: Christophe Varoqui <christophe.varoqui@opensvc.com>
Cc: DM-DEVEL ML <dm-devel@redhat.com>
Signed-off-by: Xose Vazquez Perez <xose.vazquez@gmail.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/hwtable.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index 72f81c60..f115c4f9 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -656,7 +656,8 @@ static struct hwentry default_hw[] = {
.vendor = "IBM",
.product = "^2107900",
.no_path_retry = NO_PATH_RETRY_QUEUE,
- .pgpolicy = MULTIBUS,
+ .pgpolicy = GROUP_BY_PRIO,
+ .pgfailback = -FAILBACK_IMMEDIATE,
},
{
// Storwize V5000 and V7000 lines / SAN Volume Controller (SVC) / Flex System V7000 /

View File

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Xose Vazquez Perez <xose.vazquez@gmail.com>
Date: Tue, 28 Sep 2021 19:20:59 +0200
Subject: [PATCH] multipath-tools: make EMC/SYMMETRIX config work with alua and
multibus
ALUA is supported since VMAX3 and HYPERMAX OS 5977.811.784, pag#113:
https://www.delltechnologies.com/en-us/collaterals/unauth/technical-guides-support-information/products/storage-2/docu5128.pdf
Cc: Martin Wilck <mwilck@suse.com>
Cc: Benjamin Marzinski <bmarzins@redhat.com>
Cc: Christophe Varoqui <christophe.varoqui@opensvc.com>
Cc: DM-DEVEL ML <dm-devel@redhat.com>
Signed-off-by: Xose Vazquez Perez <xose.vazquez@gmail.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/hwtable.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index f115c4f9..7095aaf1 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -329,8 +329,9 @@ static struct hwentry default_hw[] = {
/* Symmetrix / DMX / VMAX / PowerMax */
.vendor = "EMC",
.product = "SYMMETRIX",
- .pgpolicy = MULTIBUS,
+ .pgpolicy = GROUP_BY_PRIO,
.no_path_retry = 6,
+ .pgfailback = -FAILBACK_IMMEDIATE,
},
{
/* DGC CLARiiON CX/AX / VNX and Unity */

View File

@ -1,37 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Xose Vazquez Perez <xose.vazquez@gmail.com>
Date: Tue, 28 Sep 2021 19:31:21 +0200
Subject: [PATCH] multipath-tools: make EMC/Invista config work with alua and
multibus
Optimal Path Management (OPM) was introduced with VPLEX 5.5 to improve VPLEX
performance. OPM uses the ALUA mechanism to spread the I/O load across VPLEX directors
while gaining cache locality, pag #187:
https://www.delltechnologies.com/en-us/collaterals/unauth/technical-guides-support-information/products/storage-2/docu5128.pdf
Cc: Martin Wilck <mwilck@suse.com>
Cc: Benjamin Marzinski <bmarzins@redhat.com>
Cc: Christophe Varoqui <christophe.varoqui@opensvc.com>
Cc: DM-DEVEL ML <dm-devel@redhat.com>
Signed-off-by: Xose Vazquez Perez <xose.vazquez@gmail.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/hwtable.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index 7095aaf1..4e8b52ff 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -350,8 +350,9 @@ static struct hwentry default_hw[] = {
.vendor = "EMC",
.product = "Invista",
.bl_product = "LUNZ",
- .pgpolicy = MULTIBUS,
+ .pgpolicy = GROUP_BY_PRIO,
.no_path_retry = 5,
+ .pgfailback = -FAILBACK_IMMEDIATE,
},
{
/* XtremIO */

View File

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Xose Vazquez Perez <xose.vazquez@gmail.com>
Date: Tue, 28 Sep 2021 22:15:56 +0200
Subject: [PATCH] multipath-tools: make "COMPELNT/Compellent Vol" config work
with alua and multibus
ALUA is needed by SAS arrays, pag#124:
https://downloads.dell.com/manuals/all-products/esuprt_solutions_int/esuprt_solutions_int_solutions_resources/general-solution-resources_white-papers2_en-us.pdf
Cc: Sean McGinnis <sean_mcginnis@dell.com>
Cc: Martin Wilck <mwilck@suse.com>
Cc: Benjamin Marzinski <bmarzins@redhat.com>
Cc: Christophe Varoqui <christophe.varoqui@opensvc.com>
Cc: DM-DEVEL ML <dm-devel@redhat.com>
Signed-off-by: Xose Vazquez Perez <xose.vazquez@gmail.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/hwtable.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index 4e8b52ff..7fc5bc04 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -368,7 +368,8 @@ static struct hwentry default_hw[] = {
*/
.vendor = "COMPELNT",
.product = "Compellent Vol",
- .pgpolicy = MULTIBUS,
+ .pgpolicy = GROUP_BY_PRIO,
+ .pgfailback = -FAILBACK_IMMEDIATE,
.no_path_retry = NO_PATH_RETRY_QUEUE,
},
{

View File

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Xose Vazquez Perez <xose.vazquez@gmail.com>
Date: Tue, 28 Sep 2021 22:39:17 +0200
Subject: [PATCH] multipath-tools: remove Compellent maintainer
e-mail was bounced: 550 5.1.1 User Unknown
Cc: Martin Wilck <mwilck@suse.com>
Cc: Benjamin Marzinski <bmarzins@redhat.com>
Cc: Christophe Varoqui <christophe.varoqui@opensvc.com>
Cc: DM-DEVEL ML <dm-devel@redhat.com>
Signed-off-by: Xose Vazquez Perez <xose.vazquez@gmail.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/hwtable.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index 7fc5bc04..763982cd 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -361,11 +361,7 @@ static struct hwentry default_hw[] = {
.pgpolicy = MULTIBUS,
},
{
- /*
- * SC Series, formerly Compellent
- *
- * Maintainer: Sean McGinnis <sean_mcginnis@dell.com>
- */
+ /* SC Series, formerly Compellent */
.vendor = "COMPELNT",
.product = "Compellent Vol",
.pgpolicy = GROUP_BY_PRIO,

View File

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Wed, 20 Oct 2021 20:44:54 +0200
Subject: [PATCH] Revert "multipath-tools: make EMC/Invista config work with
alua and multibus"
This reverts commit 309ff281aaa07e862540d3d645a8263f3e9baaed.
Mail from <Wayne.Berthiaume@dell.com>, 20210930:
"OPM is no longer supported in the Dell VPLEX product. If we at Dell had
wished to change the default device stanzas for any of our products they
would have been done when the product and/or feature is released.
Please remove this patch as well. It is not needed."
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/hwtable.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index 763982cd..211087ad 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -350,9 +350,8 @@ static struct hwentry default_hw[] = {
.vendor = "EMC",
.product = "Invista",
.bl_product = "LUNZ",
- .pgpolicy = GROUP_BY_PRIO,
+ .pgpolicy = MULTIBUS,
.no_path_retry = 5,
- .pgfailback = -FAILBACK_IMMEDIATE,
},
{
/* XtremIO */

View File

@ -1,38 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Wed, 20 Oct 2021 20:46:09 +0200
Subject: [PATCH] Revert "multipath-tools: make EMC/SYMMETRIX config work with
alua and multibus"
This reverts commit 831af0dbfa171cd39d968ba6174669f11a278be9.
Mail from "berthiaume, wayne" <Wayne.Berthiaume@dell.com>, 210930:
"As a representative of Dell I request this patch be withdrawn. If we had
wanted the default stanza changed we would have already implemented it.
Also for your information we only advertise the entire enterprise storage
product line (DMX, VMAX, VMAX AFA, PowerMax) as SYMMETRIX in the VPD page.
The ALUA capability is only used for mobility devices in an SRDF/Metro
configuration and the current device stanza still works well in all of our
testing."
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/hwtable.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index 211087ad..a8ba28e3 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -329,9 +329,8 @@ static struct hwentry default_hw[] = {
/* Symmetrix / DMX / VMAX / PowerMax */
.vendor = "EMC",
.product = "SYMMETRIX",
- .pgpolicy = GROUP_BY_PRIO,
+ .pgpolicy = MULTIBUS,
.no_path_retry = 6,
- .pgfailback = -FAILBACK_IMMEDIATE,
},
{
/* DGC CLARiiON CX/AX / VNX and Unity */

View File

@ -1,66 +0,0 @@
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 | 26 +++++++++++++++++++-------
1 file changed, 19 insertions(+), 7 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 2a75dc9c..5ac660de 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -92,23 +92,35 @@ 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,)
WFORMATOVERFLOW := $(call TEST_CC_OPTION,-Wformat-overflow=2,)
-OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4
-WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implicit-int \
+ifndef RPM_OPT_FLAGS
+ STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)
+ OPTFLAGS := -O2 -g -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions \
+ $(STACKPROT) -grecord-gcc-switches \
+ -fasynchronous-unwind-tables --param=ssp-buffer-size=4
+ 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) --param=ssp-buffer-size=4
+endif
+WARNFLAGS := -Werror -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implicit-int \
-Werror=implicit-function-declaration -Werror=format-security \
- $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS)
-CPPFLAGS := -Wp,-D_FORTIFY_SOURCE=2
+ $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) \
+ -Wstrict-prototypes
CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \
-DBIN_DIR=\"$(bindir)\" -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \
-MMD -MP
BIN_CFLAGS = -fPIE -DPIE
LIB_CFLAGS = -fPIC
SHARED_FLAGS = -shared
-LDFLAGS := $(LDFLAGS) -Wl,-z,relro -Wl,-z,now -Wl,-z,defs
+LDFLAGS := $(LDFLAGS) $(RPM_LD_FLAGS) -Wl,-z,relro -Wl,-z,now -Wl,-z,defs
BIN_LDFLAGS = -pie
# Check whether a function with name $1 has been declared in header file $2.
@@ -139,4 +151,4 @@ check_file = $(shell \
%.o: %.c
@echo building $@ because of $?
- $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+ $(CC) $(CFLAGS) -c -o $@ $<

View File

@ -1,102 +0,0 @@
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 ++----------------
tests/vpd.c | 6 ++++++
2 files changed, 8 insertions(+), 16 deletions(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index f25fe9e3..6fb81c28 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1136,12 +1136,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 */
@@ -1160,17 +1157,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) {
diff --git a/tests/vpd.c b/tests/vpd.c
index 8e730d37..7bf7990f 100644
--- a/tests/vpd.c
+++ b/tests/vpd.c
@@ -230,11 +230,13 @@ static const char * const str_prefix[] = {
[STR_IQN] = "iqn.",
};
+#if 0
static const char byte0[] = {
[STR_EUI] = '2',
[STR_NAA] = '3',
[STR_IQN] = '8',
};
+#endif
/**
* create_scsi_string_desc() - create a SCSI name string descriptor.
@@ -659,6 +661,7 @@ make_test_vpd_naa(2, 18);
make_test_vpd_naa(2, 17);
make_test_vpd_naa(2, 16);
+#if 0
/* SCSI Name string: EUI64, WWID size: 17 */
make_test_vpd_str(0, 20, 18)
make_test_vpd_str(0, 20, 17)
@@ -694,6 +697,7 @@ make_test_vpd_str(18, 20, 18)
make_test_vpd_str(18, 20, 17)
make_test_vpd_str(18, 20, 16)
make_test_vpd_str(18, 20, 15)
+#endif
static int test_vpd(void)
{
@@ -767,6 +771,7 @@ static int test_vpd(void)
cmocka_unit_test(test_vpd_naa_2_18),
cmocka_unit_test(test_vpd_naa_2_17),
cmocka_unit_test(test_vpd_naa_2_16),
+/*
cmocka_unit_test(test_vpd_str_0_20_18),
cmocka_unit_test(test_vpd_str_0_20_17),
cmocka_unit_test(test_vpd_str_0_20_16),
@@ -791,6 +796,7 @@ static int test_vpd(void)
cmocka_unit_test(test_vpd_str_18_20_17),
cmocka_unit_test(test_vpd_str_18_20_16),
cmocka_unit_test(test_vpd_str_18_20_15),
+*/
};
return cmocka_run_group_tests(tests, setup, teardown);
}

View File

@ -1,114 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 10 Nov 2021 18:34:08 -0600
Subject: [PATCH] libmultipath: deprecate file and directory config options
Having multipath able to select pathnames for the files and directories
it needs causes unnecessary maintainer headaches. Mark these as
deprecated, but still support them for now.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/dict.c | 19 +++++++++++++++----
multipath/multipath.conf.5 | 5 +++++
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index 149d3348..d14be340 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -268,6 +268,15 @@ def_ ## option ## _handler (struct config *conf, vector strvec, \
return function (strvec, &conf->option, file, line_nr); \
}
+#define declare_def_warn_handler(option, function) \
+static int \
+def_ ## option ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
+{ \
+ condlog(2, "%s line %d, \"" #option "\" is deprecated and will be disabled in a future release", file, line_nr); \
+ 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, \
@@ -421,7 +430,7 @@ 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_dir)
+declare_def_warn_handler(multipath_dir, set_dir)
declare_def_snprint(multipath_dir, print_str)
static int def_partition_delim_handler(struct config *conf, vector strvec,
@@ -654,13 +663,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_path)
+declare_def_warn_handler(bindings_file, set_path)
declare_def_snprint(bindings_file, print_str)
-declare_def_handler(wwids_file, set_path)
+declare_def_warn_handler(wwids_file, set_path)
declare_def_snprint(wwids_file, print_str)
-declare_def_handler(prkeys_file, set_path)
+declare_def_warn_handler(prkeys_file, set_path)
declare_def_snprint(prkeys_file, print_str)
declare_def_handler(retain_hwhandler, set_yes_no_undef)
@@ -760,6 +769,8 @@ 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;
+ condlog(2, "%s line %d, \"config_dir\" is deprecated and will be disabled in a future release",
+ file, line_nr);
return set_path(strvec, &conf->config_dir, file, line_nr);
}
declare_def_snprint(config_dir, print_str)
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index dd9f4dc7..7f85f766 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -178,6 +178,7 @@ The default is: \fBno\fR
.
.TP
.B multipath_dir
+This option is deprecated, and will be removed in a future release.
Directory where the dynamic shared objects are stored. Defined at compile time,
commonly \fI/lib64/multipath/\fR or \fI/lib/multipath/\fR.
.RS
@@ -742,6 +743,7 @@ The default is: \fB<unset>\fR
.
.TP
.B bindings_file
+This option is deprecated, and will be removed in a future release.
The full pathname of the binding file to be used when the user_friendly_names
option is set.
.RS
@@ -752,6 +754,7 @@ The default is: \fB/etc/multipath/bindings\fR
.
.TP
.B wwids_file
+This option is deprecated, and will be removed in a future release.
The full pathname of the WWIDs file, which is used by multipath to keep track
of the WWIDs for LUNs it has created multipath devices on in the past.
.RS
@@ -762,6 +765,7 @@ The default is: \fB/etc/multipath/wwids\fR
.
.TP
.B prkeys_file
+This option is deprecated, and will be removed in a future release.
The full pathname of the prkeys file, which is used by multipathd to keep
track of the persistent reservation key used for a specific WWID, when
\fIreservation_key\fR is set to \fBfile\fR.
@@ -933,6 +937,7 @@ The default is: \fB<unset>\fR
.
.TP
.B config_dir
+This option is deprecated, and will be removed in a future release.
If set to anything other than "", multipath will search this directory
alphabetically for file ending in ".conf" and it will read configuration
information from them, just as if it was in \fI/etc/multipath.conf\fR.

View File

@ -1,26 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Fri, 22 Oct 2021 12:58:11 +0200
Subject: [PATCH] multipath: fix exit status of multipath -T
We must set the return value in configure().
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/main.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/multipath/main.c b/multipath/main.c
index 748e7902..80fa68e5 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -606,6 +606,7 @@ configure (struct config *conf, enum mpath_cmds cmd,
dump_config(conf, hwes, curmp);
vector_free(hwes);
+ r = RTVL_OK;
goto out;
}

View File

@ -1,34 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 13 Dec 2021 14:26:30 -0600
Subject: [PATCH] RH: mpathconf: fix setting property_blacklist
If there was no blacklist_exceptions section, setting property_blacklist
didn't work correctly. Fix it.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/mpathconf | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/multipath/mpathconf b/multipath/mpathconf
index c00d2555..0de6b121 100644
--- a/multipath/mpathconf
+++ b/multipath/mpathconf
@@ -496,7 +496,15 @@ if [ "$PROPERTY" = "n" ]; then
CHANGED_CONFIG=1
fi
elif [ "$PROPERTY" = "y" ]; then
- if [ -z "$HAVE_PROPERTY" ]; then
+ if [ -z "$HAVE_PROPERTY" -a -z "$HAVE_EXCEPTIONS" ]; then
+ cat >> $TMPFILE << _EOF_
+
+blacklist_exceptions {
+ property "(SCSI_IDENT_|ID_WWN)"
+}
+_EOF_
+ CHANGED_CONFIG=1
+ elif [ -z "$HAVE_PROPERTY" ]; then
sed -i '/^blacklist_exceptions[[:space:]]*{/ a\
property "(SCSI_IDENT_|ID_WWN)"
' $TMPFILE

View File

@ -1,45 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 12 Jan 2022 12:26:12 -0600
Subject: [PATCH] libmultipath: fix disassemble status for
historical-service-time PS
The historical-service-time path selector prints out 2 path group status
arguments. This is the only path selector that uses the group status
arguments. All the others only have path status arguments.
disassemble_status() was expecting the number of group status arguments
to always be zero, causing it to fail at disassembling the status of
devices that use historical-service-time path selector. Now multipath
actually checks the number of group arguments, and skips them.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/dmparser.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/libmultipath/dmparser.c b/libmultipath/dmparser.c
index 4ba7f339..bc311421 100644
--- a/libmultipath/dmparser.c
+++ b/libmultipath/dmparser.c
@@ -437,9 +437,19 @@ int disassemble_status(const char *params, struct multipath *mpp)
FREE(word);
/*
- * PG Status (discarded, would be '0' anyway)
+ * Path Selector Group Arguments
*/
- p += get_word(p, NULL);
+ p += get_word(p, &word);
+
+ if (!word)
+ return 1;
+
+ num_pg_args = atoi(word);
+ free(word);
+
+ /* Ignore ps group arguments */
+ for (j = 0; j < num_pg_args; j++)
+ p += get_word(p, NULL);
p += get_word(p, &word);

View File

@ -1,154 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 3 Feb 2022 13:26:18 -0600
Subject: [PATCH] RH: add support to mpathconf for setting recheck_wwid
mpathconf now supports --recheck_wwid <y|n> for setthing the
recheck_wwid option
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/mpathconf | 48 ++++++++++++++++++++++++++++++++++++++++---
multipath/mpathconf.8 | 9 ++++++++
2 files changed, 54 insertions(+), 3 deletions(-)
diff --git a/multipath/mpathconf b/multipath/mpathconf
index 6e33fb99..319664b1 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 HAVE_OPTION OPTION_NAME OPTION_VALUE
+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 HAVE_RECHECK_WWID RECHECK_WWID
DEFAULT_CONFIG="# device-mapper-multipath configuration file
@@ -52,6 +52,7 @@ function usage
echo "Set find_multipaths (Default y): --find_multipaths <yes|no|strict|greedy|smart>"
echo "Set default property blacklist (Default n): --property_blacklist <y|n>"
echo "Set enable_foreign to show foreign devices (Default n): --enable_foreign <y|n>"
+ echo "Set recheck_wwid (Defaut n): --recheck_wwid <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>"
@@ -145,6 +146,15 @@ function parse_args
exit 1
fi
;;
+ --recheck_wwid)
+ if [ -n "$2" ]; then
+ RECHECK_WWID=$2
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
--find_multipaths)
if [ -n "$2" ]; then
FIND=$2
@@ -223,7 +233,7 @@ function parse_args
function validate_args
{
- if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$PROPERTY" -o -n "$MODULE" -o -n "$FOREIGN" -o -n "$OPTION_NAME" ]; then
+ if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$PROPERTY" -o -n "$MODULE" -o -n "$FOREIGN" -o -n "$OPTION_NAME" -o -n "$RECHECK_WWID" ]; then
echo "ignoring extra parameters on disable"
FRIENDLY=""
FIND=""
@@ -232,11 +242,16 @@ function validate_args
FOREIGN=""
OPTION_NAME=""
OPTION_VALUE=""
+ RECHECK_WWID=""
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 "$RECHECK_WWID" ] && [ "$RECHECK_WWID" != "y" -a "$RECHECK_WWID" != "n" ]; then
+ echo "--recheck_wwid must be either 'y' or 'n'"
+ exit 1
+ fi
if [ "$FIND" = "y" ]; then
FIND="yes"
elif [ "$FIND" = "n" ]; then
@@ -265,7 +280,7 @@ function validate_args
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
+ if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" -a -z "$PROPERTY" -a -z "$FOREIGN" -a -z "$OPTION_NAME" -a -z "$RECHECK_WWID" ]; then
SHOW_STATUS=1
fi
if [ -n "$MODULE" ] && [ "$MODULE" != "y" -a "$MODULE" != "n" ]; then
@@ -367,6 +382,11 @@ if [ "$HAVE_DEFAULTS" = "1" ]; 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:]]*recheck_wwid[[:space:]][[:space:]]*\(yes\|1\)" ; then
+ HAVE_RECHECK_WWID=1
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*recheck_wwid[[:space:]][[:space:]]*\(no\|0\)" ; then
+ HAVE_RECHECK_WWID=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:]][[:space:]]*\"\.\*\"" ; then
@@ -411,6 +431,11 @@ if [ -n "$SHOW_STATUS" ]; then
else
echo "user_friendly_names is enabled"
fi
+ if [ -z "$HAVE_RECHECK_WWID" -o "$HAVE_RECHECK_WWID" = 0 ]; then
+ echo "recheck_wwid is disabled"
+ else
+ echo "recheck_wwid is enabled"
+ fi
if [ -z "$HAVE_PROPERTY" -o "$HAVE_PROPERTY" = 0 ]; then
echo "default property blacklist is disabled"
else
@@ -527,6 +552,23 @@ elif [ "$FRIENDLY" = "y" ]; then
fi
fi
+if [ "$RECHECK_WWID" = "n" ]; then
+ if [ "$HAVE_RECHECK_WWID" = 1 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*recheck_wwid[[:space:]][[:space:]]*\(yes\|1\)/ recheck_wwid no/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+elif [ "$RECHECK_WWID" = "y" ]; then
+ if [ -z "$HAVE_RECHECK_WWID" ]; then
+ sed -i '/^defaults[[:space:]]*{/ a\
+ recheck_wwid yes
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$HAVE_RECHECK_WWID" = 0 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*recheck_wwid[[:space:]][[:space:]]*\(no\|0\)/ recheck_wwid 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:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/# property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8
index 496383b7..9c2fb835 100644
--- a/multipath/mpathconf.8
+++ b/multipath/mpathconf.8
@@ -77,6 +77,15 @@ 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 --recheck_wwid \fP { \fBy\fP | \fBn\fP }
+If set to \fBy\fP, this adds the line
+.B recheck_wwid yes
+to the
+.B /etc/multipath.conf
+defaults section, or sets an existing line to \fByes\fP. If set to \fBn\fP, this
+sets an existing \fBrecheck_wwid\fP line to \fBno\fP. This command can be used
+along with any other command.
+.TP
.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>

View File

@ -1,33 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 16 Feb 2022 00:12:29 -0600
Subject: [PATCH] libmultipath: fix printing native nvme multipath topology.
Since commit 2f05df4 ("libmultipath: use strbuf in print.c"), when
multipath prints the topology of native nvme devices, instead of
printing the multipath device information, it prints "w [G]:d s". This
is because nvme_style() switched from calling snprintf(), which supports
format specifiers, to append_strbuf_str(), which doesn't, while still
keeping the same string, "%%w [%%G]:%%d %%s". Remove the extra percent
signs, since they don't need to be escaped in append_strbuf_str().
Fixes: 2f05df4 ("libmultipath: use strbuf in print.c")
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/foreign/nvme.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/foreign/nvme.c b/libmultipath/foreign/nvme.c
index d40c0869..23355ca5 100644
--- a/libmultipath/foreign/nvme.c
+++ b/libmultipath/foreign/nvme.c
@@ -335,7 +335,7 @@ static int snprint_nvme_pg(const struct gen_pathgroup *gmp,
static int nvme_style(__attribute__((unused)) const struct gen_multipath* gm,
struct strbuf *buf, __attribute__((unused)) int verbosity)
{
- return append_strbuf_str(buf, "%%w [%%G]:%%d %%s");
+ return append_strbuf_str(buf, "%w [%G]:%d %s");
}
static const struct gen_multipath_ops nvme_map_ops = {

View File

@ -1,86 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 29 Mar 2022 22:22:10 -0500
Subject: [PATCH] multipathd: Don't keep starting TUR threads, if they always
hang.
If tur thead hangs, multipathd was simply creating a new thread, and
assuming that the old thread would get cleaned up eventually. I have
seen a case recently where there were 26000 multipathd threads on a
system, all stuck trying to send TUR commands to path devices. The root
cause of the issue was a scsi kernel issue, but it shows that the way
multipathd currently deals with stuck threads could use some refinement.
Now, when one tur thread hangs, multipathd will act as it did before.
If a second one in a row hangs, multipathd will instead wait for it to
complete before starting another thread. Once the thread completes, the
count is reset.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com
---
libmultipath/checkers/tur.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c
index a4b4a213..d82f7dbc 100644
--- a/libmultipath/checkers/tur.c
+++ b/libmultipath/checkers/tur.c
@@ -27,6 +27,7 @@
#define TUR_CMD_LEN 6
#define HEAVY_CHECK_COUNT 10
+#define MAX_NR_TIMEOUTS 1
enum {
MSG_TUR_RUNNING = CHECKER_FIRST_MSGID,
@@ -55,6 +56,7 @@ struct tur_checker_context {
int holders; /* uatomic access only */
int msgid;
struct checker_context ctx;
+ unsigned int nr_timeouts;
};
int libcheck_init (struct checker * c)
@@ -359,8 +361,23 @@ int libcheck_check(struct checker * c)
}
} else {
if (uatomic_read(&ct->holders) > 1) {
+ /* The thread has been cancelled but hasn't quit. */
+ if (ct->nr_timeouts == MAX_NR_TIMEOUTS) {
+ condlog(2, "%d:%d : waiting for stalled tur thread to finish",
+ major(ct->devt), minor(ct->devt));
+ ct->nr_timeouts++;
+ }
/*
- * The thread has been cancelled but hasn't quit.
+ * Don't start new threads until the last once has
+ * finished.
+ */
+ if (ct->nr_timeouts > MAX_NR_TIMEOUTS) {
+ c->msgid = MSG_TUR_TIMEOUT;
+ return PATH_TIMEOUT;
+ }
+ ct->nr_timeouts++;
+ /*
+ * Start a new thread while the old one is stalled.
* We have to prevent it from interfering with the new
* thread. We create a new context and leave the old
* one with the stale thread, hoping it will clean up
@@ -376,13 +393,15 @@ int libcheck_check(struct checker * c)
*/
if (libcheck_init(c) != 0)
return PATH_UNCHECKED;
+ ((struct tur_checker_context *)c->context)->nr_timeouts = ct->nr_timeouts;
if (!uatomic_sub_return(&ct->holders, 1))
/* It did terminate, eventually */
cleanup_context(ct);
ct = c->context;
- }
+ } else
+ ct->nr_timeouts = 0;
/* Start new TUR checker */
pthread_mutex_lock(&ct->lock);
tur_status = ct->state = PATH_PENDING;

View File

@ -1,33 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 29 Nov 2022 19:56:37 -0600
Subject: [PATCH] multipath.conf(5): remove io-affinity information
The multpath-tools do not support the io-affinity path selector. We
always add a repeat count as the path argument. The io-affinity selector
doesn't take one. Instead it takes a bit map of CPUs that a path can
run on. This isn't something that lends itself to the kind of
auto-assembling that multipathd does. But even if we did want to
try to support this path-selector, until we do, we shouldn't be listing
it in the multipath.conf documentation.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/multipath.conf.5 | 4 ----
1 file changed, 4 deletions(-)
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 01904feb..5e447e67 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -211,10 +211,6 @@ of outstanding I/O to the path and its relative throughput.
estimation of future service time based on the history of previous I/O submitted
to each path.
.TP
-.I "io-affinity 0"
-(Since 5.11 kernel) Choose the path for the next bunch of I/O based on a CPU to
-path mapping the user passes in and what CPU we are executing on.
-.TP
The default is: \fBservice-time 0\fR
.RE
.

View File

@ -1,38 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 30 Jan 2023 19:54:19 -0600
Subject: [PATCH] libmultipath: use select_reload_action in select_action
Since we have a function to set the action to reload, use it.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/configure.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 193bf27d..09d7de0f 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -771,9 +771,7 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
if (force_reload) {
mpp->force_udev_reload = 1;
- mpp->action = ACT_RELOAD;
- condlog(3, "%s: set ACT_RELOAD (forced by user)",
- mpp->alias);
+ select_reload_action(mpp, "forced by user");
return;
}
if (cmpp->size != mpp->size) {
@@ -786,9 +784,7 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
if (!is_udev_ready(cmpp) && count_active_paths(mpp) > 0) {
mpp->force_udev_reload = 1;
- mpp->action = ACT_RELOAD;
- condlog(3, "%s: set ACT_RELOAD (udev incomplete)",
- mpp->alias);
+ select_reload_action(mpp, "udev incomplete");
return;
}

View File

@ -1,70 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 7 Feb 2023 15:39:26 -0600
Subject: [PATCH] multipath.rules: fix "smart" bug with failed valid path check
If "multipath -u" fails, udev doesn't import any values from the
program. This means that multipath.rules will continue to use the values
for DM_MULTIPATH_DEVICE_PATH and FIND_MULTIPATHS_WAIT_UNTIL that it has
already imported from the database. This is the correct thing to do for
every case except the MAYBE case for "find_multipaths smart". In that
case, DM_MULTIPATH_DEVICE_PATH will be set to 1, and the rules will
assume that the device has been definitively claimed.
In this case, we know that the device shouldn't have been claimed
before, but we don't know if it should be claimed now, or if we have hit
the timeout and it should be released, since we didn't get any
information from multipath. The safest thing to do is assume that this
was the timeout, and the device shouldn't be claimed. The only time when
this could be the wrong answer is when we first see a new multipath
device, and it could only cause problems if there is metadata on the
device that will cause it to get autoassembled by something else, before
multipathd can autoassemble it. If we assume that it is a multipath
device, or we assume that this wasn't actually the timeout uevent, we
can keep a necessary device from getting released to the reset of the
system.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/multipath.rules.in | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/multipath/multipath.rules.in b/multipath/multipath.rules.in
index 5c4447a2..70b69a06 100644
--- a/multipath/multipath.rules.in
+++ b/multipath/multipath.rules.in
@@ -32,7 +32,8 @@ IMPORT{db}="DM_MULTIPATH_DEVICE_PATH"
# multipath -u sets DM_MULTIPATH_DEVICE_PATH and,
# if "find_multipaths smart", also FIND_MULTIPATHS_WAIT_UNTIL.
-IMPORT{program}="$env{MPATH_SBIN_PATH}/multipath -u %k"
+IMPORT{program}=="$env{MPATH_SBIN_PATH}/multipath -u %k", \
+ ENV{.MPATH_CHECK_PASSED}="1"
# case 1: this is definitely multipath
ENV{DM_MULTIPATH_DEVICE_PATH}=="1", \
@@ -83,10 +84,19 @@ LABEL="stop_wait"
# If timeout hasn't expired but we're not in "maybe" state any more, stop timer
# Do this only once, and only if the timer has been started before
IMPORT{db}="FIND_MULTIPATHS_WAIT_CANCELLED"
-ENV{FIND_MULTIPATHS_WAIT_CANCELLED}!="?*", \
- ENV{FIND_MULTIPATHS_WAIT_UNTIL}=="?*", \
- ENV{FIND_MULTIPATHS_WAIT_UNTIL}!="0", \
- ENV{FIND_MULTIPATHS_WAIT_CANCELLED}="1", \
- RUN+="/usr/bin/systemctl stop cancel-multipath-wait-$kernel.timer"
+ENV{FIND_MULTIPATHS_WAIT_CANCELLED}=="?*", GOTO="end_mpath"
+ENV{FIND_MULTIPATHS_WAIT_UNTIL}!="?*", GOTO="end_mpath"
+ENV{FIND_MULTIPATHS_WAIT_UNTIL}=="0", GOTO="end_mpath"
+
+ENV{FIND_MULTIPATHS_WAIT_CANCELLED}="1"
+RUN+="/usr/bin/systemctl stop cancel-multipath-wait-$kernel.timer"
+
+# If "multipath -u" failed, no values are imported from the program,
+# and we are still using the values for DM_MULTIPATH_DEVICE_PATH and
+# FIND_MULTIPATHS_WAIT_UNTIL that were imported from the database.
+# If we are in "smart" mode, we need to give up on the path now,
+# since this may have been the timeout event. Without the imports
+# from "multipath -u", we can't tell.
+ENV{.MPATH_CHECK_PASSED}!="?*", ENV{DM_MULTIPATH_DEVICE_PATH}="0"
LABEL="end_mpath"

View File

@ -1,64 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 8 Feb 2023 19:31:02 -0600
Subject: [PATCH] libmultipath: limit paths that can get wwid from environment
Currently, whenever getting the uid_attribute from udev database fails,
multipath will try to get it from the environment variables. This
normally isn't a problem, since either multipath -u is getting called
from a uevent, and the environment will have the correct value in that
variable, or that variable won't be set. However, when find_multipaths
is configured to "smart", this causes problems. For maybe devices,
multipath needs to get the WWIDs of all the other block devices, to see
if they match the maybe device wwid. If one of those devices doesn't
have uid_attribute set in its udev database, multipath will check the
environment for it, and it will find that variable set to the WWID
of the maybe device that this uevent is for. This means that all
devices with no WWID will end up appearing to have the same WWID as
the maybe device, causing multipath to incorrectly claim it.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/discovery.c | 2 +-
libmultipath/structs.h | 1 +
multipath/main.c | 2 ++
3 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index f593a7bf..a592a54e 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -2032,7 +2032,7 @@ get_udev_uid(struct path * pp, char *uid_attribute, struct udev_device *udev)
const char *value;
value = udev_device_get_property_value(udev, uid_attribute);
- if (!value || strlen(value) == 0)
+ if ((!value || strlen(value) == 0) && pp->can_use_env_uid)
value = getenv(uid_attribute);
if (value && strlen(value)) {
len = strlcpy(pp->wwid, value, WWID_SIZE);
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index 0867b91d..4b308561 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -360,6 +360,7 @@ struct path {
int fast_io_fail;
unsigned int dev_loss;
int eh_deadline;
+ bool can_use_env_uid;
/* configlet pointers */
vector hwe;
struct gen_path generic_path;
diff --git a/multipath/main.c b/multipath/main.c
index 41d01c7e..e056c51c 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -653,6 +653,8 @@ check_path_valid(const char *name, struct config *conf, bool is_uevent)
pp = alloc_path();
if (!pp)
return RTVL_FAIL;
+ if (is_uevent)
+ pp->can_use_env_uid = true;
r = is_path_valid(name, conf, pp, is_uevent);
if (r <= PATH_IS_ERROR || r >= PATH_MAX_VALID_RESULT)

View File

@ -1,186 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 7 Jul 2023 15:25:59 -0500
Subject: [PATCH] RH: Add mpathcleanup
mpathcleanup is a program that will remove a multipath device as well as
all of the scsi path devices that make it up.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/Makefile | 2 +
multipath/mpathcleanup | 145 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 147 insertions(+)
create mode 100755 multipath/mpathcleanup
diff --git a/multipath/Makefile b/multipath/Makefile
index f3d98012..1fc04c8d 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -24,6 +24,7 @@ install:
$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
$(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/
+ $(INSTALL_PROGRAM) -m 755 mpathcleanup $(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
@@ -40,6 +41,7 @@ uninstall:
$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
$(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
$(RM) $(DESTDIR)$(bindir)/mpathconf
+ $(RM) $(DESTDIR)$(bindir)/mpathcleanup
$(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz
$(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
$(RM) $(DESTDIR)$(man8dir)/mpathconf.8.gz
diff --git a/multipath/mpathcleanup b/multipath/mpathcleanup
new file mode 100755
index 00000000..6fd921e4
--- /dev/null
+++ b/multipath/mpathcleanup
@@ -0,0 +1,145 @@
+#!/bin/bash
+#
+# Copyright (C) 2023 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
+
+unset PROGRAM FLUSH DEVICE DEVNAME MAJOR MINOR PATHDEVS PATHDEV HAVE_MULTIPATHD QUEUEING
+
+function usage
+{
+ echo "usage: $PROGRAM [-h] [--flush] <device>"
+ echo ""
+ echo "remove a multipath device and its scsi path devices"
+ echo ""
+ echo "options:"
+ echo " -h, --help show this help message and exit"
+ echo " --flush disable queuing on the multipath device and"
+ echo " flush the path devices before removing"
+}
+
+function parse_args
+{
+ while [ -n "$1" ]; do
+ case $1 in
+ --flush)
+ FLUSH=1
+ shift
+ ;;
+ --help | -h)
+ usage
+ exit 1
+ ;;
+ *)
+ if [ -n "$DEVICE" ]; then
+ usage
+ exit 1
+ fi
+ DEVICE=$1
+ shift
+ ;;
+ esac
+ done
+}
+
+function validate_device
+{
+ if [ -z "$DEVICE" ]; then
+ usage
+ exit 1
+ fi
+ if [[ "$DEVICE" =~ ^[[:digit:]]+:[[:digit:]]+$ ]]; then
+ MAJOR=${DEVICE%%:*}
+ MINOR=${DEVICE##*:}
+ DEVNAME=`dmsetup ls --target multipath | grep "($MAJOR, $MINOR)$" | awk '{print $1}'`
+ else
+ DEVNAME=`dmsetup ls --target multipath | awk '{print $1}' | grep "^$DEVICE$"`
+ fi
+ if [ -z "$DEVNAME" ]; then
+ DEVNAME=`multipath -v 1 -l $DEVICE 2>/dev/null`
+ if [ -z "$DEVNAME" ]; then
+ echo "$DEVICE is not a multipath device"
+ exit 1
+ fi
+ # verify that this is not a native nvme multipath device
+ dmsetup ls --target multipath | awk '{print $1}' | grep -q "^$DEVNAME$"
+ if test $? -eq 1; then
+ echo "$DEVICE is not a device-mapper multipath device"
+ exit 1
+ fi
+ fi
+ if [ -z "$MINOR" ]; then
+ MINOR=`dmsetup info -c --noheadings -o minor $DEVNAME`
+ fi
+}
+
+function get_paths
+{
+ PATHDEVS=`ls /sys/block/dm-$MINOR/slaves`
+ for PATHDEV in $PATHDEVS; do
+ if [[ ! "$PATHDEV" =~ ^sd[a-z]+$ ]]; then
+ echo "$PATHDEV is not a scsi device. $PROGRAM only works with scsi devices"
+ exit 1
+ fi
+ done
+}
+
+function remove_devs
+{
+ pidof multipathd > /dev/null
+ HAVE_MULTIPATHD=$?
+ multipath -v2 -l "$DEVNAME" | grep features | grep -q queue_if_no_path
+ QUEUEING=$?
+ if [ -n "$FLUSH" ] && [ "$QUEUEING" -eq 0 ]; then
+ if test $HAVE_MULTIPATHD -eq 0; then
+ multipathd disablequeueing map "$DEVNAME" > /dev/null
+ else
+ dmsetup message "$DEVNAME" 0 fail_if_no_path
+ fi
+ sleep 1
+ fi
+ if test $HAVE_MULTIPATHD -eq 0; then
+ multipath -f "$DEVNAME"
+ else
+ multipathd -Df "$DEVNAME"
+ fi
+ if test $? -eq 1; then
+ echo "$DEVICE cannot be removed"
+ exit 1
+ fi
+ for PATHDEV in $PATHDEVS; do
+ if [ -n "$FLUSH" ]; then
+ blockdev --flushbufs /dev/"$PATHDEV"
+ fi
+ echo 1 > /sys/block/"$PATHDEV"/device/delete
+ done
+}
+
+function verify_removal
+{
+ multipath -v 1 -d $DEVNAME | grep -q "^$DEVNAME$"
+ if test $? -eq 0; then
+ echo "$DEVICE removed but path devices still exist"
+ exit 1
+ fi
+ multipath -v 1 -l $DEVNAME | grep -q "^$DEVNAME$"
+ if test $? -eq 0; then
+ echo "$DEVICE removal succeeded, but device still exists"
+ exit 1
+ fi
+}
+
+PROGRAM="$0"
+parse_args "$@"
+validate_device
+get_paths
+remove_devs
+verify_removal

View File

@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 12 Jul 2023 12:56:48 -0500
Subject: [PATCH] RH: make listing return an error if the config file is
missing
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/main.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/multipath/main.c b/multipath/main.c
index e056c51c..f1077421 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -874,11 +874,14 @@ main (int argc, char *argv[])
struct config *conf;
int retries = -1;
bool enable_foreign = false;
+ bool have_config;
+ struct stat buf;
libmultipath_init();
if (atexit(dm_lib_exit) || atexit(libmultipath_exit))
condlog(1, "failed to register cleanup handler for libmultipath: %m");
logsink = LOGSINK_STDERR_WITH_TIME;
+ have_config = (stat(DEFAULT_CONFIGFILE, &buf) == 0);
if (init_config(DEFAULT_CONFIGFILE))
exit(RTVL_FAIL);
if (atexit(uninit_config))
@@ -1129,6 +1132,9 @@ main (int argc, char *argv[])
while ((r = configure(conf, cmd, dev_type, dev)) == RTVL_RETRY)
condlog(3, "restart multipath configuration process");
+ if (!have_config && r == RTVL_OK &&
+ (cmd == CMD_LIST_SHORT || cmd == CMD_LIST_LONG))
+ r = RTVL_FAIL;
out:
put_multipath_config(conf);
if (dev)

View File

@ -1,31 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 26 Oct 2023 13:24:34 -0400
Subject: [PATCH] multipath-tools: add HPE Alletra 9000 NVMe to hardware table
Add config to match configuration in 0.9.6 release
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/hwtable.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index 22ff1881..78ac7988 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -119,6 +119,14 @@ static struct hwentry default_hw[] = {
.dev_loss = MAX_DEV_LOSS_TMO,
.vpd_vendor_id = VPD_VP_HP3PAR,
},
+ {
+ /* Alletra 9000 NVMe */
+ .vendor = "NVME",
+ .product = "HPE Alletra",
+ .pgpolicy = GROUP_BY_PRIO,
+ .pgfailback = -FAILBACK_IMMEDIATE,
+ .no_path_retry = NO_PATH_RETRY_QUEUE,
+ },
{
/* RA8000 / ESA12000 */
.vendor = "DEC",

View File

@ -1,70 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 3 Nov 2023 11:13:04 -0400
Subject: [PATCH] RH: multipath: add mpathcleanup man page
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/Makefile | 3 +++
multipath/mpathcleanup.8 | 24 ++++++++++++++++++++++++
2 files changed, 27 insertions(+)
create mode 100644 multipath/mpathcleanup.8
diff --git a/multipath/Makefile b/multipath/Makefile
index 1fc04c8d..cdfa160b 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -19,6 +19,7 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
$(GZIP) $(EXEC).8 > $(EXEC).8.gz
$(GZIP) $(EXEC).conf.5 > $(EXEC).conf.5.gz
$(GZIP) mpathconf.8 > mpathconf.8.gz
+ $(GZIP) mpathcleanup.8 > mpathcleanup.8.gz
install:
$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
@@ -35,6 +36,7 @@ install:
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir)
$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir)
$(INSTALL_PROGRAM) -m 644 mpathconf.8.gz $(DESTDIR)$(man8dir)
+ $(INSTALL_PROGRAM) -m 644 mpathcleanup.8.gz $(DESTDIR)$(man8dir)
uninstall:
$(RM) $(DESTDIR)$(bindir)/$(EXEC)
@@ -45,6 +47,7 @@ uninstall:
$(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz
$(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
$(RM) $(DESTDIR)$(man8dir)/mpathconf.8.gz
+ $(RM) $(DESTDIR)$(man8dir)/mpathcleanup.8.gz
clean: dep_clean
$(RM) core *.o $(EXEC) *.gz multipath.rules tmpfiles.conf
diff --git a/multipath/mpathcleanup.8 b/multipath/mpathcleanup.8
new file mode 100644
index 00000000..184c35c9
--- /dev/null
+++ b/multipath/mpathcleanup.8
@@ -0,0 +1,24 @@
+.TH MPATHCLEANUP 8 "November 2023" "" "Linux Administrator's Manual"
+.SH NAME
+mpathcleanup - A tool to remove a multipath device and its scsi path devices
+.SH SYNOPSIS
+.B mpathcleanup
+[\fB\-h\fR] [\fB\-\-flush\fR] \fBdevice\fR
+.SH DESCRIPTION
+\fBmpathcleanup\fR is a utility that attempts to remove a multipath device and
+its underlying paths. It only works for multipath devices built on top of scsi
+devices.
+.SH OPTIONS
+.TP
+.B \-\-flush
+Disable queueing on the multipath device and flush the path devices before
+removing.
+.TP
+\fB\-h\fR|\fB\-\-help\fR
+Display help text.
+.SH "SEE ALSO"
+.BR multipath.conf (5),
+.BR multipath (8),
+.BR multipathd (8)
+.SH AUTHOR
+Benjamin Marzinski <bmarzins@redhat.com>

View File

@ -1,182 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 9 Nov 2023 18:46:11 -0500
Subject: [PATCH] libmultipath: Add max_retries config option
This option lets multipath set a scsi disk's max_retries sysfs value.
Setting this can be helpful for cases where the path checker succeeds,
but IO commands hang and timeout. By default, the SCSI layer will retry
IOs 5 times. Reducing this value will allow multipath to retry the IO
down another path sooner.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/config.h | 1 +
libmultipath/dict.c | 25 ++++++++++++++++++++++++
libmultipath/discovery.c | 40 +++++++++++++++++++++++++++++++++++++-
libmultipath/structs.h | 6 ++++++
multipath/multipath.conf.5 | 14 +++++++++++++
5 files changed, 85 insertions(+), 1 deletion(-)
diff --git a/libmultipath/config.h b/libmultipath/config.h
index c1e18363..b0ee8241 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -162,6 +162,7 @@ struct config {
int fast_io_fail;
unsigned int dev_loss;
int eh_deadline;
+ int max_retries;
int log_checker_err;
int allow_queueing;
int allow_usb_devices;
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index eb2f33a2..0c66c1e1 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -1206,6 +1206,30 @@ declare_hw_snprint(eh_deadline, print_undef_off_zero)
declare_pc_handler(eh_deadline, set_undef_off_zero)
declare_pc_snprint(eh_deadline, print_undef_off_zero)
+static int
+def_max_retries_handler(struct config *conf, vector strvec, const char *file,
+ int line_nr)
+{
+ char * buff;
+
+ buff = set_value(strvec);
+ if (!buff)
+ return 1;
+
+ if (strcmp(buff, "off") == 0)
+ conf->max_retries = MAX_RETRIES_OFF;
+ else if (strcmp(buff, "0") == 0)
+ conf->max_retries = MAX_RETRIES_ZERO;
+ else
+ do_set_int(strvec, &conf->max_retries, 1, 5, file, line_nr,
+ buff);
+
+ free(buff);
+ return 0;
+}
+
+declare_def_snprint(max_retries, print_undef_off_zero)
+
static int
set_pgpolicy(vector strvec, void *ptr, const char *file, int line_nr)
{
@@ -2143,6 +2167,7 @@ init_keywords(vector keywords)
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("max_retries", &def_max_retries_handler, &snprint_def_max_retries);
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);
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index a592a54e..adf8bbaa 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -632,6 +632,42 @@ sysfs_set_eh_deadline(struct path *pp)
return (ret <= 0);
}
+static int
+sysfs_set_max_retries(struct config *conf, struct path *pp)
+{
+ struct udev_device *parent;
+ char value[16];
+ STRBUF_ON_STACK(buf);
+ int ret, len;
+
+ if (conf->max_retries == MAX_RETRIES_UNSET)
+ return 0;
+
+ if (!pp->udev || pp->sg_id.host_no < 0)
+ return 1;
+
+ len = sprintf(value, "%d", (conf->max_retries == MAX_RETRIES_OFF)? -1 :
+ (conf->max_retries == MAX_RETRIES_ZERO)? 0 :
+ conf->max_retries);
+
+ parent = udev_device_get_parent_with_subsystem_devtype(pp->udev,
+ "scsi", "scsi_device");
+ if (!parent)
+ return 1;
+
+ if (print_strbuf(&buf, "scsi_disk/%i:%i:%i:%" PRIu64 "/max_retries",
+ pp->sg_id.host_no, pp->sg_id.channel,
+ pp->sg_id.scsi_id, pp->sg_id.lun) < 0)
+ return 1;
+
+ ret = sysfs_attr_set_value(parent, get_strbuf_str(&buf), value, len);
+ if (len != ret)
+ condlog(3, "%s/%s: failed to set value to %s: %s",
+ udev_device_get_sysname(parent), get_strbuf_str(&buf),
+ value, (ret < 0)? strerror(-ret) : "write underflow");
+ return (len != ret);
+}
+
static void
sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
{
@@ -862,13 +898,15 @@ sysfs_set_scsi_tmo (struct config *conf, struct multipath *mpp)
if (pp->dev_loss == DEV_LOSS_TMO_UNSET &&
pp->fast_io_fail == MP_FAST_IO_FAIL_UNSET &&
- pp->eh_deadline == EH_DEADLINE_UNSET)
+ pp->eh_deadline == EH_DEADLINE_UNSET &&
+ conf->max_retries == MAX_RETRIES_UNSET)
continue;
if (pp->bus != SYSFS_BUS_SCSI)
continue;
sysfs_set_eh_deadline(pp);
+ sysfs_set_max_retries(conf, pp);
if (pp->dev_loss == DEV_LOSS_TMO_UNSET &&
pp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index c1e93e6e..b4252ab5 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -276,6 +276,12 @@ enum eh_deadline_states {
EH_DEADLINE_ZERO = UOZ_ZERO,
};
+enum max_retries_states {
+ MAX_RETRIES_UNSET = UOZ_UNDEF,
+ MAX_RETRIES_OFF = UOZ_OFF,
+ MAX_RETRIES_ZERO = UOZ_ZERO,
+};
+
enum recheck_wwid_states {
RECHECK_WWID_UNDEF = YNU_UNDEF,
RECHECK_WWID_OFF = YNU_NO,
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 5e447e67..789f0bfc 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -743,6 +743,20 @@ The default is: \fB<unset>\fR
.
.
.TP
+.B max_retries
+Specify the maximum number of times the SCSI layer will retry IO commands for
+some types of SCSI errors before returning failure. Setting this can be helpful
+for cases where IO commands hang and timeout. By default, the SCSI layer will
+retry IOs 5 times. Reducing this value will allow multipath to retry the IO
+down another path sooner. Valid values are
+\fB0\fR through \fB5\fR.
+.RS
+.TP
+The default is: \fB<unset>\fR
+.RE
+.
+.
+.TP
.B bindings_file
This option is deprecated, and will be removed in a future release.
The full pathname of the binding file to be used when the user_friendly_names

View File

@ -1,29 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 9 Nov 2023 18:46:12 -0500
Subject: [PATCH] libmutipath: Retain device size if sysfs_get_size fails.
When paths are allocated their size is initialized to 0. If they've
already set a size, and a future call to sysfs_get_size() fails during
the parsing, assume that the size hasn't changed, instead of setting it
to 0. All other failures in sysfs_get_size() already retain the existing
size.
Reviewed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/sysfs.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c
index 24c12b6a..41354f91 100644
--- a/libmultipath/sysfs.c
+++ b/libmultipath/sysfs.c
@@ -229,7 +229,6 @@ sysfs_get_size (struct path *pp, unsigned long long * size)
if (r != 1) {
condlog(3, "%s: Cannot parse size attribute", pp->dev);
- *size = 0;
return 1;
}

View File

@ -1,68 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 9 Nov 2023 18:46:13 -0500
Subject: [PATCH] multipathd: check and update all paths when in cli_resize
When resizing a multipath device, make sure that all the paths have
been updated to the new size first.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
multipathd/cli_handlers.c | 31 ++++++++++++++++++-------------
1 file changed, 18 insertions(+), 13 deletions(-)
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index f322f10f..93c32c5b 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -866,9 +866,11 @@ cli_resize(void *v, char **reply, int *len, void *data)
char * mapname = get_keyparam(v, MAP);
struct multipath *mpp;
int minor;
- unsigned long long size;
+ unsigned long long size = 0;
struct pathgroup *pgp;
struct path *pp;
+ unsigned int i, j;
+ bool mismatch = false;
mapname = convert_dev(mapname, 0);
condlog(2, "%s: resize map (operator)", mapname);
@@ -888,21 +890,24 @@ cli_resize(void *v, char **reply, int *len, void *data)
return 1;
}
- pgp = VECTOR_SLOT(mpp->pg, 0);
-
- if (!pgp){
- condlog(0, "%s: couldn't get path group. cannot resize",
- mapname);
- return 1;
+ vector_foreach_slot(mpp->pg, pgp, i) {
+ vector_foreach_slot (pgp->paths, pp, j) {
+ sysfs_get_size(pp, &pp->size);
+ if (!pp->size)
+ continue;
+ if (!size)
+ size = pp->size;
+ else if (pp->size != size)
+ mismatch = true;
+ }
}
- pp = VECTOR_SLOT(pgp->paths, 0);
-
- if (!pp){
- condlog(0, "%s: couldn't get path. cannot resize", mapname);
+ if (!size) {
+ condlog(0, "%s: couldn't get size from sysfs. cannot resize",
+ mapname);
return 1;
}
- if (!pp->udev || sysfs_get_size(pp, &size)) {
- condlog(0, "%s: couldn't get size for sysfs. cannot resize",
+ if (mismatch) {
+ condlog(0, "%s: path size not consistent. cannot resize",
mapname);
return 1;
}

View File

@ -1,58 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 9 Nov 2023 18:46:14 -0500
Subject: [PATCH] multipathd: move post-reloading commands into resize_map()
In preparation for reusing resize_map() in other code, move all code
necessary to resize the map to the resize_map() function. Also track if
map was removed in the function.
Reviewed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/cli_handlers.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index 93c32c5b..b08b248f 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -856,6 +856,10 @@ int resize_map(struct multipath *mpp, unsigned long long size,
mpp->size = orig_size;
return 1;
}
+ if (setup_multipath(vecs, mpp) != 0)
+ return 2;
+ sync_map_state(mpp);
+
return 0;
}
@@ -869,7 +873,7 @@ cli_resize(void *v, char **reply, int *len, void *data)
unsigned long long size = 0;
struct pathgroup *pgp;
struct path *pp;
- unsigned int i, j;
+ unsigned int i, j, ret;
bool mismatch = false;
mapname = convert_dev(mapname, 0);
@@ -919,14 +923,12 @@ cli_resize(void *v, char **reply, int *len, void *data)
condlog(3, "%s old size is %llu, new size is %llu", mapname, mpp->size,
size);
- if (resize_map(mpp, size, vecs) != 0)
- return 1;
+ ret = resize_map(mpp, size, vecs);
- if (setup_multipath(vecs, mpp) != 0)
- return 1;
- sync_map_state(mpp);
+ if (ret == 2)
+ condlog(0, "%s: map removed while trying to resize", mapname);
- return 0;
+ return (ret != 0);
}
int

View File

@ -1,106 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 10 Nov 2023 17:59:42 -0500
Subject: [PATCH] multipathd: move resize_map() to multipathd/main.c
No functional changes.
Reviewed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/cli_handlers.c | 29 -----------------------------
multipathd/main.c | 29 +++++++++++++++++++++++++++++
multipathd/main.h | 2 ++
3 files changed, 31 insertions(+), 29 deletions(-)
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index b08b248f..53bebc8d 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -834,35 +834,6 @@ cli_reload(void *v, char **reply, int *len, void *data)
return reload_and_sync_map(mpp, vecs, 0);
}
-int resize_map(struct multipath *mpp, unsigned long long size,
- struct vectors * vecs)
-{
- char *params __attribute__((cleanup(cleanup_charp))) = NULL;
- unsigned long long orig_size = mpp->size;
-
- mpp->size = size;
- update_mpp_paths(mpp, vecs->pathvec);
- if (setup_map(mpp, &params, vecs) != 0) {
- condlog(0, "%s: failed to setup map for resize : %s",
- mpp->alias, strerror(errno));
- mpp->size = orig_size;
- return 1;
- }
- mpp->action = ACT_RESIZE;
- mpp->force_udev_reload = 1;
- if (domap(mpp, params, 1) == DOMAP_FAIL) {
- condlog(0, "%s: failed to resize map : %s", mpp->alias,
- strerror(errno));
- mpp->size = orig_size;
- return 1;
- }
- if (setup_multipath(vecs, mpp) != 0)
- return 2;
- sync_map_state(mpp);
-
- return 0;
-}
-
int
cli_resize(void *v, char **reply, int *len, void *data)
{
diff --git a/multipathd/main.c b/multipathd/main.c
index 075e7b13..d99cad72 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1379,6 +1379,35 @@ needs_ro_update(struct multipath *mpp, int ro)
return true;
}
+int resize_map(struct multipath *mpp, unsigned long long size,
+ struct vectors * vecs)
+{
+ char *params __attribute__((cleanup(cleanup_charp))) = NULL;
+ unsigned long long orig_size = mpp->size;
+
+ mpp->size = size;
+ update_mpp_paths(mpp, vecs->pathvec);
+ if (setup_map(mpp, &params, vecs) != 0) {
+ condlog(0, "%s: failed to setup map for resize : %s",
+ mpp->alias, strerror(errno));
+ mpp->size = orig_size;
+ return 1;
+ }
+ mpp->action = ACT_RESIZE;
+ mpp->force_udev_reload = 1;
+ if (domap(mpp, params, 1) == DOMAP_FAIL) {
+ condlog(0, "%s: failed to resize map : %s", mpp->alias,
+ strerror(errno));
+ mpp->size = orig_size;
+ return 1;
+ }
+ if (setup_multipath(vecs, mpp) != 0)
+ return 2;
+ sync_map_state(mpp);
+
+ return 0;
+}
+
static int
uev_update_path (struct uevent *uev, struct vectors * vecs)
{
diff --git a/multipathd/main.h b/multipathd/main.h
index bc1f938f..dbae4935 100644
--- a/multipathd/main.h
+++ b/multipathd/main.h
@@ -66,4 +66,6 @@ int reload_and_sync_map(struct multipath *mpp, struct vectors *vecs,
void handle_path_wwid_change(struct path *pp, struct vectors *vecs);
bool check_path_wwid_change(struct path *pp);
+int resize_map(struct multipath *mpp, unsigned long long size,
+ struct vectors *vecs);
#endif /* MAIN_H */

View File

@ -1,202 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 9 Nov 2023 18:46:16 -0500
Subject: [PATCH] multipathd: Add auto_resize config option
This option gives multipathd the ability to automatically resize a
device when it detects that all of the path devices have changed. By
default it is set to never, and multipathd will continue to work like it
always has, where a users must manually resize a multipath device.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/config.h | 1 +
libmultipath/defaults.h | 1 +
libmultipath/dict.c | 38 ++++++++++++++++++++++++++++++++++++++
libmultipath/dict.h | 1 +
libmultipath/structs.h | 7 +++++++
multipath/multipath.conf.5 | 15 +++++++++++++++
multipathd/main.c | 28 ++++++++++++++++++++++++++++
7 files changed, 91 insertions(+)
diff --git a/libmultipath/config.h b/libmultipath/config.h
index b0ee8241..5807ac68 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -201,6 +201,7 @@ struct config {
int skip_delegate;
unsigned int sequence_nr;
int recheck_wwid;
+ int auto_resize;
char * multipath_dir;
char * selector;
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index cec82f07..c3788bbc 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -54,6 +54,7 @@
#define DEFAULT_UNKNOWN_FIND_MULTIPATHS_TIMEOUT 1
#define DEFAULT_ALL_TG_PT ALL_TG_PT_OFF
#define DEFAULT_RECHECK_WWID RECHECK_WWID_OFF
+#define DEFAULT_AUTO_RESIZE AUTO_RESIZE_NEVER
/* Enable no foreign libraries by default */
#define DEFAULT_ENABLE_FOREIGN "NONE"
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index 0c66c1e1..c4db60df 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -1736,6 +1736,43 @@ declare_hw_snprint(recheck_wwid, print_yes_no_undef)
declare_def_range_handler(uxsock_timeout, DEFAULT_REPLY_TIMEOUT, INT_MAX)
+static int
+def_auto_resize_handler(struct config *conf, vector strvec, const char *file,
+ int line_nr)
+{
+ char * buff;
+
+ buff = set_value(strvec);
+ if (!buff)
+ return 1;
+
+ if (strcmp(buff, "never") == 0)
+ conf->auto_resize = AUTO_RESIZE_NEVER;
+ else if (strcmp(buff, "grow_only") == 0)
+ conf->auto_resize = AUTO_RESIZE_GROW_ONLY;
+ else if (strcmp(buff, "grow_shrink") == 0)
+ conf->auto_resize = AUTO_RESIZE_GROW_SHRINK;
+ else
+ condlog(1, "%s line %d, invalid value for auto_resize: \"%s\"",
+ file, line_nr, buff);
+
+ free(buff);
+ return 0;
+}
+
+int
+print_auto_resize(struct strbuf *buff, long v)
+{
+ if (!v)
+ return 0;
+ return append_strbuf_quoted(buff,
+ v == AUTO_RESIZE_GROW_ONLY ? "grow_only" :
+ v == AUTO_RESIZE_GROW_SHRINK ? "grow_shrink" :
+ "never");
+}
+
+declare_def_snprint(auto_resize, print_auto_resize)
+
static int
hw_vpd_vendor_handler(struct config *conf, vector strvec, const char *file,
int line_nr)
@@ -2202,6 +2239,7 @@ init_keywords(vector keywords)
install_keyword("remove_retries", &def_remove_retries_handler, &snprint_def_remove_retries);
install_keyword("max_sectors_kb", &def_max_sectors_kb_handler, &snprint_def_max_sectors_kb);
install_keyword("ghost_delay", &def_ghost_delay_handler, &snprint_def_ghost_delay);
+ install_keyword("auto_resize", &def_auto_resize_handler, &snprint_def_auto_resize);
install_keyword("find_multipaths_timeout",
&def_find_multipaths_timeout_handler,
&snprint_def_find_multipaths_timeout);
diff --git a/libmultipath/dict.h b/libmultipath/dict.h
index d80f990a..d963b4ad 100644
--- a/libmultipath/dict.h
+++ b/libmultipath/dict.h
@@ -19,4 +19,5 @@ int print_dev_loss(struct strbuf *buff, unsigned long v);
int print_reservation_key(struct strbuf *buff,
struct be64 key, uint8_t flags, int source);
int print_off_int_undef(struct strbuf *buff, long v);
+int print_auto_resize(struct strbuf *buff, long v);
#endif /* _DICT_H */
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index b4252ab5..8c2d7131 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -167,6 +167,13 @@ enum queue_mode_states {
QUEUE_MODE_RQ,
};
+enum auto_resize_state {
+ AUTO_RESIZE_UNDEF = 0,
+ AUTO_RESIZE_NEVER,
+ AUTO_RESIZE_GROW_ONLY,
+ AUTO_RESIZE_GROW_SHRINK,
+};
+
#define PROTOCOL_UNSET -1
enum scsi_protocol {
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 789f0bfc..38eb5c90 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1293,6 +1293,21 @@ The default is: \fBno\fR
.
.
.TP
+.B auto_resize
+Controls when multipathd will automatically resize a multipath device. If set
+to \fInever\fR, multipath devices must always be manually resized by either
+running \fBmultipathd resize map <name>\fR. If set to \fIgrow_only\fR, when
+multipathd detects that all of a multipath device's paths have increased in
+size, it will automatically grow the multipath device to the new size. If set
+to \fIgrow_shrink\fR, multipathd will also automatically shrink the device
+once it detects all of its paths have decreased in size.
+.RS
+.TP
+The default is: \fBnever\fR
+.RE
+.
+.
+.TP
.B enable_foreign
Enables or disables foreign libraries (see section
.I FOREIGN MULTIPATH SUPPORT
diff --git a/multipathd/main.c b/multipathd/main.c
index d99cad72..6d1a5e4e 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1439,6 +1439,11 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
if (pp) {
struct multipath *mpp = pp->mpp;
char wwid[WWID_SIZE];
+ int auto_resize;
+
+ conf = get_multipath_config();
+ auto_resize = conf->auto_resize;
+ put_multipath_config(conf);
if (pp->initialized == INIT_REQUESTED_UDEV) {
needs_reinit = 1;
@@ -1489,6 +1494,29 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
}
}
}
+ if (auto_resize != AUTO_RESIZE_NEVER &&
+ !mpp->wait_for_udev) {
+ struct pathgroup *pgp;
+ struct path *pp2;
+ unsigned int i, j;
+ unsigned long long orig_size = mpp->size;
+
+ if (!pp->size || pp->size == mpp->size ||
+ (pp->size < mpp->size &&
+ auto_resize == AUTO_RESIZE_GROW_ONLY))
+ goto out;
+
+ vector_foreach_slot(mpp->pg, pgp, i)
+ vector_foreach_slot (pgp->paths, pp2, j)
+ if (pp2->size && pp2->size != pp->size)
+ goto out;
+ retval = resize_map(mpp, pp->size, vecs);
+ if (retval == 2)
+ condlog(2, "%s: map removed during resize", pp->dev);
+ else if (retval == 0)
+ condlog(2, "%s: resized map from %llu to %llu",
+ mpp->alias, orig_size, pp->size);
+ }
}
out:
lock_cleanup_pop(vecs->lock);

View File

@ -1,42 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Mon, 18 Dec 2023 16:30:42 -0500
Subject: [PATCH] libmultipath: avoid temporarily enabling queueing on reload
Instead of always enabling queueing when a map is reloaded with
no_path_retry set to a positive number, check if the map has timed out
in recovery mode, and only enable queueing if it has not. This saves
multipathd from having to disable queueing on the map immediately after
the reload.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/dmparser.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/libmultipath/dmparser.c b/libmultipath/dmparser.c
index 16377c54..1ea2d619 100644
--- a/libmultipath/dmparser.c
+++ b/libmultipath/dmparser.c
@@ -61,9 +61,19 @@ int assemble_map(struct multipath *mp, char **params)
nr_priority_groups = VECTOR_SIZE(mp->pg);
initial_pg_nr = (nr_priority_groups ? mp->bestpg : 0);
- if (mp->no_path_retry != NO_PATH_RETRY_UNDEF &&
- mp->no_path_retry != NO_PATH_RETRY_FAIL) {
+ switch (mp->no_path_retry) {
+ case NO_PATH_RETRY_UNDEF:
+ case NO_PATH_RETRY_FAIL:
+ break;
+ default:
+ /* don't enable queueing if no_path_retry has timed out */
+ if (mp->in_recovery && mp->retry_tick == 0 &&
+ count_active_paths(mp) == 0)
+ break;
+ /* fallthrough */
+ case NO_PATH_RETRY_QUEUE:
add_feature(&mp->features, no_path_retry);
+ break;
}
if (mp->retain_hwhandler == RETAIN_HWHANDLER_ON &&
get_linux_version_code() < KERNEL_VERSION(4, 3, 0))

View File

@ -1,131 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 6 Dec 2023 17:22:02 -0500
Subject: [PATCH] multipathd: remove nopath flushing code from flush_map()
Instead of flush_map() handling both user requested flushes and
automatic flushes when the last path has been deleted, make
flush_map_nopaths() handle the automatic flushes itself, since a later
patch will change the behavior of flush_map().
Reviewed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/cli_handlers.c | 2 +-
multipathd/main.c | 45 +++++++++++++++++----------------------
multipathd/main.h | 2 +-
3 files changed, 21 insertions(+), 28 deletions(-)
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index 53bebc8d..f04fb558 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -796,7 +796,7 @@ cli_del_maps (void *v, char **reply, int *len, void *data)
condlog(2, "remove maps (operator)");
vector_foreach_slot(vecs->mpvec, mpp, i) {
- if (flush_map(mpp, vecs, 0))
+ if (flush_map(mpp, vecs))
ret++;
else
i--;
diff --git a/multipathd/main.c b/multipathd/main.c
index 6d1a5e4e..1b5f82e7 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -490,12 +490,11 @@ int update_multipath (struct vectors *vecs, char *mapname, int reset)
static bool
flush_map_nopaths(struct multipath *mpp, struct vectors *vecs) {
- char alias[WWID_SIZE];
+ int r;
/*
* flush_map will fail if the device is open
*/
- strlcpy(alias, mpp->alias, WWID_SIZE);
if (mpp->flush_on_last_del == FLUSH_ENABLED) {
condlog(2, "%s Last path deleted, disabling queueing",
mpp->alias);
@@ -505,11 +504,20 @@ flush_map_nopaths(struct multipath *mpp, struct vectors *vecs) {
mpp->stat_map_failures++;
dm_queue_if_no_path(mpp->alias, 0);
}
- if (!flush_map(mpp, vecs, 1)) {
- condlog(2, "%s: removed map after removing all paths", alias);
- return true;
+ r = dm_flush_map_nopaths(mpp->alias, mpp->deferred_remove);
+ if (r) {
+ if (r == 1)
+ condlog(0, "%s: can't flush", mpp->alias);
+ else {
+ condlog(2, "%s: devmap deferred remove", mpp->alias);
+ mpp->deferred_remove = DEFERRED_REMOVE_IN_PROGRESS;
+ }
+ return false;
}
- return false;
+
+ condlog(2, "%s: map flushed after removing all paths", mpp->alias);
+ remove_map_and_stop_waiter(mpp, vecs);
+ return true;
}
static void
@@ -685,30 +693,15 @@ sync_maps_state(vector mpvec)
}
int
-flush_map(struct multipath * mpp, struct vectors * vecs, int nopaths)
+flush_map(struct multipath * mpp, struct vectors * vecs)
{
- int r;
-
- if (nopaths)
- r = dm_flush_map_nopaths(mpp->alias, mpp->deferred_remove);
- else
- r = dm_flush_map(mpp->alias);
- /*
- * clear references to this map before flushing so we can ignore
- * the spurious uevent we may generate with the dm_flush_map call below
- */
+ int r = dm_flush_map(mpp->alias);
if (r) {
- if (r == 1)
- condlog(0, "%s: can't flush", mpp->alias);
- else {
- condlog(2, "%s: devmap deferred remove", mpp->alias);
- mpp->deferred_remove = DEFERRED_REMOVE_IN_PROGRESS;
- }
+ condlog(0, "%s: can't flush", mpp->alias);
return r;
}
- else
- condlog(2, "%s: map flushed", mpp->alias);
+ condlog(2, "%s: map flushed", mpp->alias);
remove_map_and_stop_waiter(mpp, vecs);
return 0;
@@ -866,7 +859,7 @@ ev_remove_map (char * devname, char * alias, int minor, struct vectors * vecs)
mpp->alias, mpp->dmi->minor, minor);
return 1;
}
- return flush_map(mpp, vecs, 0);
+ return flush_map(mpp, vecs);
}
static void
diff --git a/multipathd/main.h b/multipathd/main.h
index dbae4935..4138faa4 100644
--- a/multipathd/main.h
+++ b/multipathd/main.h
@@ -43,7 +43,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 flush_map(struct multipath *, struct vectors *);
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,

View File

@ -1,39 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 7 Dec 2023 11:23:18 -0500
Subject: [PATCH] multipathd: make flush_map() delete maps like the multipath
command
When the multipath command tries to delete a multipath device, it first
disables queueing and then suspends the device to force the IOs to get
flushed. Then it attempts to delete the device and any kpartx
partitions. multipathd, on the other hand, simply tries to delete the
device and kpartx partitions, without disabling queueing or suspending.
If there are no paths but there is outstanding IO, multipathd will hang
trying to delete the last kpartx device. This is because it must be the
last opener of the multipath device (multipath won't try to delete the
device if it has any openers besides the kpartx devices) and the kernel
will not allow the last opener of a block device to close until all the
outstanding IO is flushed. This hang can be avoided if multipathd calls
dm_suspend_and_flush_map() like the multipath command does, instead of
dm_flush_map().
Reviewed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index 1b5f82e7..3eeca82f 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -695,7 +695,7 @@ sync_maps_state(vector mpvec)
int
flush_map(struct multipath * mpp, struct vectors * vecs)
{
- int r = dm_flush_map(mpp->alias);
+ int r = dm_suspend_and_flush_map(mpp->alias, 0);
if (r) {
condlog(0, "%s: can't flush", mpp->alias);
return r;

View File

@ -1,83 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 8 Dec 2023 14:50:31 -0500
Subject: [PATCH] multipathd: disable queueing when removing unknown maps
Make cli_del_maps() call dm_suspend_and_flush_map() for the unknown
multipath devices as well.
After this change, all callers of cli_del_maps() set need_suspend, so
simplify dm_flush_maps().
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 7 ++-----
libmultipath/devmapper.h | 2 +-
multipath/main.c | 2 +-
multipathd/cli_handlers.c | 2 +-
4 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 4b2e8a15..f9de3358 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -1145,7 +1145,7 @@ dm_flush_map_nopaths(const char * mapname,
#endif
-int dm_flush_maps (int need_suspend, int retries)
+int dm_flush_maps (int retries)
{
int r = 1;
struct dm_task *dmt;
@@ -1170,10 +1170,7 @@ int dm_flush_maps (int need_suspend, int retries)
goto out;
do {
- if (need_suspend)
- r |= dm_suspend_and_flush_map(names->name, retries);
- else
- r |= dm_flush_map(names->name);
+ r |= dm_suspend_and_flush_map(names->name, retries);
next = names->next;
names = (void *) names + next;
} while (next);
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 45a676de..808da28d 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 need_suspend, int retries);
+int dm_flush_maps (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 f1077421..e296be6e 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -1126,7 +1126,7 @@ main (int argc, char *argv[])
goto out;
}
else if (cmd == CMD_FLUSH_ALL) {
- r = dm_flush_maps(1, retries) ? RTVL_FAIL : RTVL_OK;
+ r = dm_flush_maps(retries) ? RTVL_FAIL : RTVL_OK;
goto out;
}
while ((r = configure(conf, cmd, dev_type, dev)) == RTVL_RETRY)
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index f04fb558..aca8e2df 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -802,7 +802,7 @@ cli_del_maps (void *v, char **reply, int *len, void *data)
i--;
}
/* flush any multipath maps that aren't currently known by multipathd */
- ret |= dm_flush_maps(0, 0);
+ ret |= dm_flush_maps(0);
return ret;
}

View File

@ -1,28 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 16 Jan 2024 20:19:11 -0500
Subject: [PATCH] multipathd: fix null pointer dereference in uev_update_path
The Auto-resize code added a check that deferences pp->mpp without
checking that it's non-NULL. Fix it.
Fixes: 981b83ad1 ("multipathd: Add auto_resize config option")
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
multipathd/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index 3eeca82f..26be6dc3 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1487,7 +1487,7 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
}
}
}
- if (auto_resize != AUTO_RESIZE_NEVER &&
+ if (auto_resize != AUTO_RESIZE_NEVER && mpp &&
!mpp->wait_for_udev) {
struct pathgroup *pgp;
struct path *pp2;

View File

@ -1,43 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 16 Jan 2024 20:19:12 -0500
Subject: [PATCH] multipathd: fix auto-resize configuration
The code acted like AUTO_RESIZE_UNDEFINED didn't exist, but since
conf->auto_resize was never set to AUTO_RESIZE_NEVER, the default was in
fact AUTO_RESIZE_UNDEFINED, which ended up getting treated like
AUTO_RESIZE_GROW_SHRINK. Remove AUTO_RESIZE_UNDEFINED and explicitly
default auto_resize tp AUTO_RESIZE_NEVER.
Fixes: 981b83ad1 ("multipathd: Add auto_resize config option")
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/config.c | 1 +
libmultipath/structs.h | 1 -
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 61b0dd51..f31200a3 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -940,6 +940,7 @@ int _init_config (const char *file, struct config *conf)
conf->retrigger_tries = DEFAULT_RETRIGGER_TRIES;
conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY;
conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT;
+ conf->auto_resize = DEFAULT_AUTO_RESIZE;
conf->remove_retries = 0;
conf->ghost_delay = DEFAULT_GHOST_DELAY;
conf->all_tg_pt = DEFAULT_ALL_TG_PT;
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index 8c2d7131..d2ad4867 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -168,7 +168,6 @@ enum queue_mode_states {
};
enum auto_resize_state {
- AUTO_RESIZE_UNDEF = 0,
AUTO_RESIZE_NEVER,
AUTO_RESIZE_GROW_ONLY,
AUTO_RESIZE_GROW_SHRINK,

View File

@ -1,28 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 26 Jan 2024 15:40:42 -0500
Subject: [PATCH] libmultipath: fix displaying auto_resize config setting
When 56476ebd3 ("multipathd: fix auto-resize configuration") removed
AUTO_RESIZE_UNDEFINED, it didn't update print_auto_resize() to print
a value for when it was set to 0 (which is now AUTO_RESIZE_NEVER).
Fixes: 56476ebd3 ("multipathd: fix auto-resize configuration")
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/dict.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index c4db60df..ce1b6c99 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -1763,8 +1763,6 @@ def_auto_resize_handler(struct config *conf, vector strvec, const char *file,
int
print_auto_resize(struct strbuf *buff, long v)
{
- if (!v)
- return 0;
return append_strbuf_quoted(buff,
v == AUTO_RESIZE_GROW_ONLY ? "grow_only" :
v == AUTO_RESIZE_GROW_SHRINK ? "grow_shrink" :

View File

@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 9 Apr 2024 14:09:49 -0400
Subject: [PATCH] libmultipath: actually truncate too-large vpd page.
When multipath notices that the vpd page is too large, it needs to
actually truncate it. Also, whe calling parse_vpd_pg83() with a possibly
truncated page, multipath needs to check that it actually has a whole
vpd entry, before trying to use it.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/discovery.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index adf8bbaa..ae7eb7e6 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1164,7 +1164,7 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
int vpd_type, prio = -1, naa_prio;
d = in + 4;
- while (d < in + in_len) {
+ while (d + 4 <= in + in_len && d + d[3] + 4 <= in + in_len) {
/* Select 'association: LUN' */
if ((d[1] & 0x30) != 0) {
d += d[3] + 4;
@@ -1363,8 +1363,10 @@ get_vpd_sysfs (struct udev_device *parent, int pg, char * str, int maxlen)
return -ENODATA;
}
buff_len = get_unaligned_be16(&buff[2]) + 4;
- if (buff_len > 4096)
+ if (buff_len > 4096) {
condlog(3, "vpd pg%02x page truncated", pg);
+ buff_len = 4096;
+ }
if (pg == 0x80)
len = parse_vpd_pg80(buff, str, maxlen);

View File

@ -1,23 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 9 Apr 2024 14:13:34 -0400
Subject: [PATCH] kpartx: fix theoretical overflow in loop device name
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
kpartx/lopart.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kpartx/lopart.c b/kpartx/lopart.c
index 9b652554..80ce1312 100644
--- a/kpartx/lopart.c
+++ b/kpartx/lopart.c
@@ -159,7 +159,7 @@ char *find_loop_by_file(const char *filename)
char *find_unused_loop_device(void)
{
- char dev[20], *next_loop_dev = NULL;
+ char dev[21], *next_loop_dev = NULL;
int fd, next_loop = 0, somedev = 0, someloop = 0, loop_known = 0;
struct stat statbuf;
struct loop_info loopinfo;

View File

@ -1,194 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 19 Dec 2023 17:51:50 -0500
Subject: [PATCH] libmultipath: keep track of queueing state in features
Make multipathd update mpp->features when in enables or disables
queuing. This patch handles all the cases except failed removes by
dm_suspend_and_flush_map(), which is never called by multipathd.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/configure.c | 4 +---
libmultipath/devmapper.c | 23 +++++++++++++++++++----
libmultipath/devmapper.h | 2 +-
libmultipath/structs_vec.c | 10 +++++-----
multipathd/main.c | 8 ++++----
5 files changed, 30 insertions(+), 17 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index bbdbb8ca..71acb968 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -1279,9 +1279,7 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,
mpp->no_path_retry != NO_PATH_RETRY_FAIL)
condlog(3, "%s: multipathd not running, unset "
"queue_if_no_path feature", mpp->alias);
- if (!dm_queue_if_no_path(mpp->alias, 0))
- remove_feature(&mpp->features,
- "queue_if_no_path");
+ dm_queue_if_no_path(mpp, 0);
}
if (!is_daemon && mpp->action != ACT_NOTHING)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index f9de3358..5711f0ee 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -57,6 +57,7 @@ static int dm_cancel_remove_partmaps(const char * mapname);
static int do_foreach_partmaps(const char * mapname,
int (*partmap_func)(const char *, void *),
void *data);
+static int _dm_queue_if_no_path(const char *mapname, int enable);
#ifndef LIBDM_API_COOKIE
static inline int dm_task_set_cookie(struct dm_task *dmt, uint32_t *c, int a)
@@ -1072,7 +1073,7 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove,
if (need_suspend &&
dm_get_map(mapname, &mapsize, &params) == DMP_OK &&
strstr(params, "queue_if_no_path")) {
- if (!dm_queue_if_no_path(mapname, 0))
+ if (!_dm_queue_if_no_path(mapname, 0))
queue_if_no_path = 1;
else
/* Leave queue_if_no_path alone if unset failed */
@@ -1121,7 +1122,7 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove,
} while (retries-- > 0);
if (queue_if_no_path == 1)
- dm_queue_if_no_path(mapname, 1);
+ _dm_queue_if_no_path(mapname, 1);
return 1;
}
@@ -1236,8 +1237,8 @@ dm_reinstate_path(const char * mapname, char * path)
return dm_message(mapname, message);
}
-int
-dm_queue_if_no_path(const char *mapname, int enable)
+static int
+_dm_queue_if_no_path(const char *mapname, int enable)
{
char *message;
@@ -1249,6 +1250,20 @@ dm_queue_if_no_path(const char *mapname, int enable)
return dm_message(mapname, message);
}
+int dm_queue_if_no_path(struct multipath *mpp, int enable)
+{
+ int r;
+ static const char no_path_retry[] = "queue_if_no_path";
+
+ if ((r = _dm_queue_if_no_path(mpp->alias, enable)) == 0) {
+ if (enable)
+ add_feature(&mpp->features, no_path_retry);
+ else
+ remove_feature(&mpp->features, no_path_retry);
+ }
+ return r;
+}
+
static int
dm_groupmsg (const char * msg, const char * mapname, int index)
{
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 808da28d..41b8c31d 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -58,7 +58,7 @@ int dm_cancel_deferred_remove(struct multipath *mpp);
int dm_flush_maps (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);
+int dm_queue_if_no_path(struct multipath *mpp, int enable);
int dm_switchgroup(const char * mapname, int index);
int dm_enablegroup(const char * mapname, int index);
int dm_disablegroup(const char * mapname, int index);
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index 86ad89ca..56915e96 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -579,7 +579,7 @@ static void leave_recovery_mode(struct multipath *mpp)
*/
if (recovery && (mpp->no_path_retry == NO_PATH_RETRY_QUEUE ||
mpp->no_path_retry > 0)) {
- dm_queue_if_no_path(mpp->alias, 1);
+ dm_queue_if_no_path(mpp, 1);
condlog(2, "%s: queue_if_no_path enabled", mpp->alias);
condlog(1, "%s: Recovered to normal mode", mpp->alias);
}
@@ -598,11 +598,11 @@ void __set_no_path_retry(struct multipath *mpp, bool check_features)
break;
case NO_PATH_RETRY_FAIL:
if (!check_features || is_queueing)
- dm_queue_if_no_path(mpp->alias, 0);
+ dm_queue_if_no_path(mpp, 0);
break;
case NO_PATH_RETRY_QUEUE:
if (!check_features || !is_queueing)
- dm_queue_if_no_path(mpp->alias, 1);
+ dm_queue_if_no_path(mpp, 1);
break;
default:
if (count_active_paths(mpp) > 0) {
@@ -612,7 +612,7 @@ void __set_no_path_retry(struct multipath *mpp, bool check_features)
*/
if ((!check_features || !is_queueing) &&
!mpp->in_recovery)
- dm_queue_if_no_path(mpp->alias, 1);
+ dm_queue_if_no_path(mpp, 1);
leave_recovery_mode(mpp);
} else {
/*
@@ -623,7 +623,7 @@ void __set_no_path_retry(struct multipath *mpp, bool check_features)
*/
if ((!check_features || is_queueing) &&
mpp->in_recovery && mpp->retry_tick == 0)
- dm_queue_if_no_path(mpp->alias, 0);
+ dm_queue_if_no_path(mpp, 0);
if (pathcount(mpp, PATH_PENDING) == 0)
enter_recovery_mode(mpp);
}
diff --git a/multipathd/main.c b/multipathd/main.c
index 26be6dc3..74f8114c 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -502,7 +502,7 @@ flush_map_nopaths(struct multipath *mpp, struct vectors *vecs) {
mpp->no_path_retry = NO_PATH_RETRY_FAIL;
mpp->disable_queueing = 1;
mpp->stat_map_failures++;
- dm_queue_if_no_path(mpp->alias, 0);
+ dm_queue_if_no_path(mpp, 0);
}
r = dm_flush_map_nopaths(mpp->alias, mpp->deferred_remove);
if (r) {
@@ -833,7 +833,7 @@ uev_remove_map (struct uevent * uev, struct vectors * vecs)
goto out;
}
- dm_queue_if_no_path(alias, 0);
+ dm_queue_if_no_path(mpp, 0);
remove_map_and_stop_waiter(mpp, vecs);
out:
lock_cleanup_pop(vecs->lock);
@@ -2015,7 +2015,7 @@ retry_count_tick(vector mpvec)
condlog(4, "%s: Retrying.. No active path", mpp->alias);
if(--mpp->retry_tick == 0) {
mpp->stat_map_failures++;
- dm_queue_if_no_path(mpp->alias, 0);
+ dm_queue_if_no_path(mpp, 0);
condlog(2, "%s: Disable queueing", mpp->alias);
}
}
@@ -3110,7 +3110,7 @@ static void cleanup_maps(struct vectors *vecs)
put_multipath_config(conf);
if (queue_without_daemon == QUE_NO_DAEMON_OFF)
vector_foreach_slot(vecs->mpvec, mpp, i)
- dm_queue_if_no_path(mpp->alias, 0);
+ dm_queue_if_no_path(mpp, 0);
remove_maps_and_stop_waiters(vecs);
vecs->mpvec = NULL;
}

View File

@ -1,54 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 25 Apr 2024 19:35:13 -0400
Subject: [PATCH] libmultipath: export partmap_in_use
A future commit will make use of this function
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 2 +-
libmultipath/devmapper.h | 1 +
libmultipath/libmultipath.version | 5 +++++
3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 5711f0ee..4a66e2c4 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -1028,7 +1028,7 @@ has_partmap(const char *name __attribute__((unused)),
return 1;
}
-static int
+int
partmap_in_use(const char *name, void *data)
{
int part_count, *ret_count = (int *)data;
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 41b8c31d..88e0b114 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -48,6 +48,7 @@ int dm_get_map(const char *, unsigned long long *, char **);
int dm_get_status(const char *, char **);
int dm_type(const char *, char *);
int dm_is_mpath(const char *);
+int partmap_in_use(const char *name, void *data);
int _dm_flush_map (const char *, int, int, int, int);
int dm_flush_map_nopaths(const char * mapname, int deferred_remove);
#define dm_flush_map(mapname) _dm_flush_map(mapname, 1, 0, 0, 0)
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index 1d018eab..40d9246d 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -302,3 +302,8 @@ LIBMULTIPATH_9.1.2 {
global:
cleanup_mutex;
} LIBMULTIPATH_9.1.1;
+
+LIBMULTIPATH_9.1.3 {
+global:
+ partmap_in_use;
+} LIBMULTIPATH_9.1.2;

View File

@ -1,346 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 25 Apr 2024 19:35:14 -0400
Subject: [PATCH] libmultipath: change flush_on_last_del to fix a multipathd
hang
Commit 9bd3482e ("multipathd: make flush_map() delete maps like the
multipath command") fixed an issue where deleting a queueing multipath
device through multipathd could hang because the multipath device had
outstanding IO, even though the only openers of it at the time of
deletion were the kpartx partition devices. However it is still possible
to hang multipathd, because autoremoving the device when all paths have
been deleted doesn't disable queueing. To reproduce this hang:
1. create a multipath device with a kpartx partition on top of it and
no_path_retry set to either "queue" or something long enough to run all
the commands in the reproducer before it disables queueing.
2. disable all the paths to the device with something like:
# echo offline > /sys/block/<path_dev>/device/state
3. Write directly to the multipath device with something like:
# dd if=/dev/zero of=/dev/mapper/<mpath_dev> bs=4K count=1
4. delete all the paths to the device with something like:
# echo 1 > /sys/block/<path_dev>/device/delete
Multipathd will hang trying to delete the kpartx device because, as the
last opener, it must flush the multipath device before closing it.
Because it hangs holding the vecs_lock, multipathd will never disable
queueing on the device, so it will hang forever, even if no_path_retry
is set to a number.
This hang can occur, even if deferred_remove is set. Since nothing has
the kpartx device opened, device-mapper does an immediate remove, which
will still hang. This means that even if deferred_remove is set,
multipathd still cannot delete a map while queueing is enabled. It must
either disable queueing or skip the autoremove.
Mulitpath can currently be configured to avoid this hang by setting
flush_on_last_del yes
However there are good reasons why users wouldn't want to set that. They
may need to be able to survive having all paths getting temporarily
deleted. I should note that this is a pretty rare corner case, since
multipath automatically sets dev_loss_tmo so that it should not trigger
before queueing is disabled.
This commit avoids the hang by changing the possible values for
flush_on_last_del to "never", "unused", and "always", and sets the
default to "unused". "always" works like "yes" did, "never" will not
disable queueing, and "unused" will only disable queueing if nothing has
the kpartx devices or the multipath device open. In order to be safe, if
the device has queue_if_no_paths set (and in case of "unused", the
device is in-use) the autoremove will be skipped. Also, instead of just
trusting the lack of "queue_if_no_paths" in the current mpp->features,
multipathd will tell the kernel to disable queueing, just to be sure it
actually is.
I chose "unused" as the default because this should generally only cause
multipathd to work differently from the users perspective when nothing
has the multipath device open but it is queueing and there is
outstanding IO. Without this change, it would have hung instead of
failing the outstanding IO. However, I do understand that an argument
could be made that "never" makes more sense as default, even though it
will cause multipathd to skip autoremoves in cases where it wouldn't
before. The change to the behavior of deffered_remove will be
noticeable, but skipping an autoremove is much better than hanging.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/defaults.h | 2 +-
libmultipath/dict.c | 72 +++++++++++++++++++++++++++++++++-----
libmultipath/dict.h | 1 +
libmultipath/hwtable.c | 6 ++--
libmultipath/propsel.c | 4 ++-
libmultipath/structs.h | 7 ++--
multipath/multipath.conf.5 | 20 ++++++++---
multipathd/main.c | 39 ++++++++++++++++-----
8 files changed, 122 insertions(+), 29 deletions(-)
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index c3788bbc..5e77387e 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -41,7 +41,7 @@
#define DEFAULT_PRIO PRIO_CONST
#define DEFAULT_PRIO_ARGS ""
#define DEFAULT_CHECKER TUR
-#define DEFAULT_FLUSH FLUSH_DISABLED
+#define DEFAULT_FLUSH FLUSH_UNUSED
#define DEFAULT_USER_FRIENDLY_NAMES USER_FRIENDLY_NAMES_OFF
#define DEFAULT_FORCE_SYNC 0
#define UNSET_PARTITION_DELIM "/UNSET/"
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index ce1b6c99..3c011ece 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -825,14 +825,70 @@ declare_def_snprint(checker_timeout, print_nonzero)
declare_def_handler(allow_usb_devices, set_yes_no)
declare_def_snprint(allow_usb_devices, print_yes_no)
-declare_def_handler(flush_on_last_del, set_yes_no_undef)
-declare_def_snprint_defint(flush_on_last_del, print_yes_no_undef, DEFAULT_FLUSH)
-declare_ovr_handler(flush_on_last_del, set_yes_no_undef)
-declare_ovr_snprint(flush_on_last_del, print_yes_no_undef)
-declare_hw_handler(flush_on_last_del, set_yes_no_undef)
-declare_hw_snprint(flush_on_last_del, print_yes_no_undef)
-declare_mp_handler(flush_on_last_del, set_yes_no_undef)
-declare_mp_snprint(flush_on_last_del, print_yes_no_undef)
+
+static const char * const flush_on_last_del_optvals[] = {
+ [FLUSH_NEVER] = "never",
+ [FLUSH_ALWAYS] = "always",
+ [FLUSH_UNUSED] = "unused",
+};
+
+static int
+set_flush_on_last_del(vector strvec, void *ptr, const char *file, int line_nr)
+{
+ int i;
+ int *flush_val_ptr = (int *)ptr;
+ char *buff;
+
+ buff = set_value(strvec);
+ if (!buff)
+ return 1;
+
+ for (i = FLUSH_NEVER; i <= FLUSH_UNUSED; i++) {
+ if (flush_on_last_del_optvals[i] != NULL &&
+ !strcmp(buff, flush_on_last_del_optvals[i])) {
+ *flush_val_ptr = i;
+ break;
+ }
+ }
+
+ if (i > FLUSH_UNUSED) {
+ bool deprecated = true;
+ if (strcmp(buff, "no") == 0 || strcmp(buff, "0") == 0)
+ *flush_val_ptr = FLUSH_UNUSED;
+ else if (strcmp(buff, "yes") == 0 || strcmp(buff, "1") == 0)
+ *flush_val_ptr = FLUSH_ALWAYS;
+ else {
+ deprecated = false;
+ condlog(1, "%s line %d, invalid value for flush_on_last_del: \"%s\"",
+ file, line_nr, buff);
+ }
+ if (deprecated)
+ condlog(3, "%s line %d, \"%s\" is a deprecated value for flush_on_last_del and is treated as \"%s\"",
+ file, line_nr, buff,
+ flush_on_last_del_optvals[*flush_val_ptr]);
+ }
+
+ free(buff);
+ return 0;
+}
+
+int
+print_flush_on_last_del(struct strbuf *buff, long v)
+{
+ if (v == FLUSH_UNDEF)
+ return 0;
+ return append_strbuf_quoted(buff, flush_on_last_del_optvals[(int)v]);
+}
+
+declare_def_handler(flush_on_last_del, set_flush_on_last_del)
+declare_def_snprint_defint(flush_on_last_del, print_flush_on_last_del,
+ DEFAULT_FLUSH)
+declare_ovr_handler(flush_on_last_del, set_flush_on_last_del)
+declare_ovr_snprint(flush_on_last_del, print_flush_on_last_del)
+declare_hw_handler(flush_on_last_del, set_flush_on_last_del)
+declare_hw_snprint(flush_on_last_del, print_flush_on_last_del)
+declare_mp_handler(flush_on_last_del, set_flush_on_last_del)
+declare_mp_snprint(flush_on_last_del, print_flush_on_last_del)
declare_def_handler(user_friendly_names, set_yes_no_undef)
declare_def_snprint_defint(user_friendly_names, print_yes_no_undef,
diff --git a/libmultipath/dict.h b/libmultipath/dict.h
index d963b4ad..6b1aae5c 100644
--- a/libmultipath/dict.h
+++ b/libmultipath/dict.h
@@ -20,4 +20,5 @@ int print_reservation_key(struct strbuf *buff,
struct be64 key, uint8_t flags, int source);
int print_off_int_undef(struct strbuf *buff, long v);
int print_auto_resize(struct strbuf *buff, long v);
+int print_flush_on_last_del(struct strbuf *buff, long v);
#endif /* _DICT_H */
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index 78ac7988..94012d50 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -60,7 +60,7 @@
.no_path_retry = NO_PATH_RETRY_UNDEF,
.minio = 1000,
.minio_rq = 1,
- .flush_on_last_del = FLUSH_DISABLED,
+ .flush_on_last_del = FLUSH_UNUSED,
.user_friendly_names = USER_FRIENDLY_NAMES_OFF,
.fast_io_fail = 5,
.dev_loss = 600,
@@ -800,7 +800,7 @@ static struct hwentry default_hw[] = {
.no_path_retry = NO_PATH_RETRY_QUEUE,
.pgpolicy = GROUP_BY_PRIO,
.pgfailback = -FAILBACK_IMMEDIATE,
- .flush_on_last_del = FLUSH_ENABLED,
+ .flush_on_last_del = FLUSH_ALWAYS,
.dev_loss = MAX_DEV_LOSS_TMO,
.prio_name = PRIO_ONTAP,
.user_friendly_names = USER_FRIENDLY_NAMES_OFF,
@@ -1122,7 +1122,7 @@ static struct hwentry default_hw[] = {
.no_path_retry = NO_PATH_RETRY_FAIL,
.minio = 1,
.minio_rq = 1,
- .flush_on_last_del = FLUSH_ENABLED,
+ .flush_on_last_del = FLUSH_ALWAYS,
.fast_io_fail = 15,
.dev_loss = 15,
},
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
index 9dea6f92..be781ff7 100644
--- a/libmultipath/propsel.c
+++ b/libmultipath/propsel.c
@@ -902,6 +902,7 @@ out:
int select_flush_on_last_del(struct config *conf, struct multipath *mp)
{
const char *origin;
+ STRBUF_ON_STACK(buff);
mp_set_mpe(flush_on_last_del);
mp_set_ovr(flush_on_last_del);
@@ -909,8 +910,9 @@ int select_flush_on_last_del(struct config *conf, struct multipath *mp)
mp_set_conf(flush_on_last_del);
mp_set_default(flush_on_last_del, DEFAULT_FLUSH);
out:
+ print_flush_on_last_del(&buff, mp->flush_on_last_del);
condlog(3, "%s: flush_on_last_del = %s %s", mp->alias,
- (mp->flush_on_last_del == FLUSH_ENABLED)? "yes" : "no", origin);
+ get_strbuf_str(&buff), origin);
return 0;
}
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index d2ad4867..4bf8c93a 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -109,9 +109,10 @@ enum marginal_pathgroups_mode {
};
enum flush_states {
- FLUSH_UNDEF = YNU_UNDEF,
- FLUSH_DISABLED = YNU_NO,
- FLUSH_ENABLED = YNU_YES,
+ FLUSH_UNDEF,
+ FLUSH_NEVER,
+ FLUSH_ALWAYS,
+ FLUSH_UNUSED,
};
enum log_checker_err_states {
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 38eb5c90..10eddc0c 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -672,12 +672,22 @@ The default is: \fBno\fR
.TP
.B flush_on_last_del
If set to
-.I yes
+.I always
, multipathd will disable queueing when the last path to a device has been
-deleted.
-.RS
-.TP
-The default is: \fBno\fR
+deleted. If set to
+.I never
+, multipathd will not disable queueing when the last path to a device has
+been deleted. Since multipath cannot safely remove a device while queueing
+is enabled, setting this to \fInever\fR means that multipathd will not
+automatically remove an unused multipath device whose paths are all deleted if
+it is currently set to queue_if_no_path. If set to
+.I unused
+, multipathd will only disable queueing when the last path is removed if
+nothing currently has the multipath device or any of the kpartx partition
+devices on top of it open.
+.RS
+.TP
+The default is: \fBunused\fR
.RE
.
.
diff --git a/multipathd/main.c b/multipathd/main.c
index 74f8114c..8ec58f5d 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -491,19 +491,42 @@ int update_multipath (struct vectors *vecs, char *mapname, int reset)
static bool
flush_map_nopaths(struct multipath *mpp, struct vectors *vecs) {
int r;
+ bool is_queueing = true;
+ if (mpp->features)
+ is_queueing = strstr(mpp->features, "queue_if_no_path");
+
+ /* It's not safe to do a remove of a map that has "queue_if_no_path"
+ * set, since there could be outstanding IO which will cause
+ * multipathd to hang while attempting the remove */
+ if (mpp->flush_on_last_del == FLUSH_NEVER && is_queueing) {
+ condlog(2, "%s: map is queueing, can't remove", mpp->alias);
+ return false;
+ }
+ if (mpp->flush_on_last_del == FLUSH_UNUSED &&
+ partmap_in_use(mpp->alias, NULL) && is_queueing) {
+ condlog(2, "%s: map in use and queueing, can't remove",
+ mpp->alias);
+ return false;
+ }
/*
- * flush_map will fail if the device is open
+ * This will flush FLUSH_NEVER devices and FLUSH_UNUSED devices
+ * that are in use, but only if they are already marked as not
+ * queueing. That is just to make absolutely certain that they
+ * really are not queueing, like they claim.
*/
- if (mpp->flush_on_last_del == FLUSH_ENABLED) {
- condlog(2, "%s Last path deleted, disabling queueing",
+ condlog(is_queueing ? 2 : 3, "%s Last path deleted, disabling queueing",
+ mpp->alias);
+ mpp->retry_tick = 0;
+ mpp->no_path_retry = NO_PATH_RETRY_FAIL;
+ mpp->disable_queueing = 1;
+ mpp->stat_map_failures++;
+ if (dm_queue_if_no_path(mpp, 0) != 0) {
+ condlog(0, "%s: failed to disable queueing. Not removing",
mpp->alias);
- mpp->retry_tick = 0;
- mpp->no_path_retry = NO_PATH_RETRY_FAIL;
- mpp->disable_queueing = 1;
- mpp->stat_map_failures++;
- dm_queue_if_no_path(mpp, 0);
+ return false;
}
+
r = dm_flush_map_nopaths(mpp->alias, mpp->deferred_remove);
if (r) {
if (r == 1)

View File

@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 25 Apr 2024 19:35:16 -0400
Subject: [PATCH] libmultipath: pad dev_loss_tmo to avoid race with
no_path_retry
Currently multipath makes sure that dev_loss_tmo is at least as long as
the configured no path queueing time. The goal is to make sure that path
devices aren't removed while the multipath device is still queueing in
hopes that they will become usable again.
This is racy. Multipathd may take longer to check the paths than
configured. If strict_timing isn't set, it will definitely take longer.
To account for this, pad the minimum dev_loss_tmo value by five seconds
(one default checker interval) plus one second per minute of no path
queueing time.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/discovery.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index ae7eb7e6..b24594cd 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -884,6 +884,11 @@ sysfs_set_scsi_tmo (struct config *conf, struct multipath *mpp)
uint64_t no_path_retry_tmo =
(uint64_t)mpp->no_path_retry * conf->checkint;
+ /* pad no_path_retry_tmo by one standard check interval
+ * plus one second per minute to account for timing
+ * issues with the rechecks */
+ no_path_retry_tmo += no_path_retry_tmo / 60 + DEFAULT_CHECKINT;
+
if (no_path_retry_tmo > MAX_DEV_LOSS_TMO)
min_dev_loss = MAX_DEV_LOSS_TMO;
else

View File

@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nitin Yewale <nyewale@redhat.com>
Date: Thu, 12 Jan 2023 14:28:49 -0600
Subject: [PATCH] libmultipath: remove pathgroup wildcard options
The multipathd command "multipathd show wildcards" shows the pathgroup
format wildcards, but there is no way to use them in a multipathd
command.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/print.c | 7 -------
1 file changed, 7 deletions(-)
diff --git a/libmultipath/print.c b/libmultipath/print.c
index 082e4e30..a6e4c774 100644
--- a/libmultipath/print.c
+++ b/libmultipath/print.c
@@ -803,13 +803,6 @@ int snprint_wildcards(struct strbuf *buff)
pd[i].wildcard, pd[i].header)) < 0)
return rc;
- if ((rc = append_strbuf_str(buff, "\npathgroup format wildcards:\n")) < 0)
- return rc;
- for (i = 0; pgd[i].header; i++)
- if ((rc = print_strbuf(buff, "%%%c %s\n",
- pgd[i].wildcard, pgd[i].header)) < 0)
- return rc;
-
return get_strbuf_len(buff) - initial_len;
}

View File

@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 8 May 2024 19:02:30 -0400
Subject: [PATCH] libmultipath: print all values in snprint_failback
Add the missing output for manual failback and print the defferral time
for deferred failbacks, if one isn't currently in progress.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/print.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/libmultipath/print.c b/libmultipath/print.c
index a6e4c774..535e0271 100644
--- a/libmultipath/print.c
+++ b/libmultipath/print.c
@@ -199,9 +199,13 @@ snprint_failback (struct strbuf *buff, const struct multipath * mpp)
return append_strbuf_str(buff, "immediate");
if (mpp->pgfailback == -FAILBACK_FOLLOWOVER)
return append_strbuf_str(buff, "followover");
+ if (mpp->pgfailback == -FAILBACK_MANUAL)
+ return append_strbuf_str(buff, "manual");
+ if (mpp->pgfailback == FAILBACK_UNDEF)
+ return append_strbuf_str(buff, "undef");
if (!mpp->failback_tick)
- return append_strbuf_str(buff, "-");
+ return print_strbuf(buff, "%i", mpp->pgfailback);
else
return snprint_progress(buff, mpp->failback_tick,
mpp->pgfailback);

View File

@ -1,34 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 9 May 2024 12:58:11 -0400
Subject: [PATCH] multipathd: Stop double counting map failures for
no_path_retry > 0
If no_path_retry was greater than 0, multipathd was counting a map
failure when recovery mode was entered, and again when queueing was
disabled. The first one is incorrect, since the map is still queueing.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/structs_vec.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index 56915e96..b8e304e0 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -781,10 +781,13 @@ int verify_paths(struct multipath *mpp)
void update_queue_mode_del_path(struct multipath *mpp)
{
int active = count_active_paths(mpp);
+ bool is_queueing = mpp->features &&
+ strstr(mpp->features, "queue_if_no_path");
if (active == 0) {
enter_recovery_mode(mpp);
- if (mpp->no_path_retry != NO_PATH_RETRY_QUEUE)
+ if (mpp->no_path_retry == NO_PATH_RETRY_FAIL ||
+ (mpp->no_path_retry == NO_PATH_RETRY_UNDEF && !is_queueing))
mpp->stat_map_failures++;
}
condlog(2, "%s: remaining active paths: %d", mpp->alias, active);

View File

@ -1,102 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 9 May 2024 17:15:34 -0400
Subject: [PATCH] multipath-tools man pages: add missing multipathd commands
Also, the description for "del map $map" was incorrect.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/multipathd.8 | 42 ++++++++++++++++++++++++++++++++++++-----
1 file changed, 37 insertions(+), 5 deletions(-)
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8
index 8bd47a80..40a8dc6d 100644
--- a/multipathd/multipathd.8
+++ b/multipathd/multipathd.8
@@ -100,18 +100,24 @@ The following commands can be used in interactive mode:
Show the paths that multipathd is monitoring, and their state.
.
.TP
-.B list|show paths format $format
+.B list|show paths [raw] format $format
Show the paths that multipathd is monitoring, using a format string with path
-format wildcards.
+format wildcards. Adding \fIraw\fR will remove the headers and alignment
+padding from the ouput.
+.
+.TP
+.B list|show path $path
+Show whether path $path is offline or running.
.
.TP
.B list|show maps|multipaths
Show the multipath devices that the multipathd is monitoring.
.
.TP
-.B list|show maps|multipaths format $format
+.B list|show maps|multipaths [raw] format $format
Show the status of all multipath devices that the multipathd is monitoring,
-using a format string with multipath format wildcards.
+using a format string with multipath format wildcards. Adding \fIraw\fR will
+remove the headers and alignment padding from the output.
.
.TP
.B list|show maps|multipaths status
@@ -124,6 +130,10 @@ Show some statistics of all multipath devices that the multipathd is monitoring.
.TP
.B list|show maps|multipaths topology
Show the current multipath topology. Same as '\fImultipath \-ll\fR'.
+.TP
+.
+.B list|show maps|multipaths json
+Show information about all multipath devices in JSON format.
.
.TP
.B list|show topology
@@ -135,6 +145,16 @@ Show topology of a single multipath device specified by $map, for example
36005076303ffc56200000000000010aa. This map could be obtained from '\fIlist maps\fR'.
.
.TP
+.B list|show map|multipath $map [raw] format $format.
+Show the status of multipath device $map, using a format string with multipath
+format wildcards. Adding \fIraw\fR will remove the headers and alignment
+padding from the output.
+.
+.TP
+.B list|show map|multipath $map json
+Show information about multipath device $map in JSON format.
+.
+.TP
.B list|show wildcards
Show the format wildcards used in interactive commands taking $format.
.
@@ -168,6 +188,14 @@ paths, and whether multipathd is currently handling a uevent.
Show the current state of the multipathd daemon.
.
.TP
+.B reset maps|multipaths stats
+Reset the statistics of all multipath devices.
+.
+.TP
+.B reset map|multipath $map stats
+Reset the statistics of multipath device $map.
+.
+.TP
.B add path $path
Add a path to the list of monitored paths. $path is as listed in /sys/block (e.g. sda).
.
@@ -183,8 +211,12 @@ for the multipath device (e.g. mpath1) or the uid of the multipath device
(e.g. 36005076303ffc56200000000000010aa).
.
.TP
+.B remove|del maps|multipaths
+Remove all multipath devices.
+.
+.TP
.B remove|del map|multipath $map
-Stop monitoring a multipath device.
+Remove the multipath device $map.
.
.TP
.B resize map|multipath $map

View File

@ -1,54 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 10 May 2024 15:36:10 -0400
Subject: [PATCH] libmultipath: change the vend/prod/rev printing
The %s multipath and path wildcards both say they print the device
vend/prod/rev string, but neither of them do. The multipath wildcards
already provide a way to print the revision string and the %s wildcard
is used in the multipath -l output, so leave the wildcard output alone,
and change the description to only mention the vendor and product. There
is no other way to print the revision by path, and the path %s wildcard
is only used in the verbose multipath output, so make it actually print
the revision. Also check for unset strings, and print "##" instead of
nothing.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/print.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/libmultipath/print.c b/libmultipath/print.c
index 535e0271..4552fd43 100644
--- a/libmultipath/print.c
+++ b/libmultipath/print.c
@@ -309,7 +309,7 @@ snprint_multipath_uuid (struct strbuf *buff, const struct multipath * mpp)
}
static int
-snprint_multipath_vpr (struct strbuf *buff, const struct multipath * mpp)
+snprint_multipath_vp (struct strbuf *buff, const struct multipath * mpp)
{
struct pathgroup * pgp;
struct path * pp;
@@ -511,7 +511,10 @@ snprint_dm_path_state (struct strbuf *buff, const struct path * pp)
static int
snprint_vpr (struct strbuf *buff, const struct path * pp)
{
- return print_strbuf(buff, "%s,%s", pp->vendor_id, pp->product_id);
+ return print_strbuf(buff, "%s,%s,%s",
+ strlen(pp->vendor_id) ? pp->vendor_id : "##",
+ strlen(pp->product_id) ? pp->product_id : "##",
+ strlen(pp->rev) ? pp->rev : "##");
}
static int
@@ -743,7 +746,7 @@ struct multipath_data mpd[] = {
{'2', "map_loads", 0, snprint_map_loads},
{'3', "total_q_time", 0, snprint_total_q_time},
{'4', "q_timeouts", 0, snprint_q_timeouts},
- {'s', "vend/prod/rev", 0, snprint_multipath_vpr},
+ {'s', "vend/prod", 0, snprint_multipath_vp},
{'v', "vend", 0, snprint_multipath_vend},
{'p', "prod", 0, snprint_multipath_prod},
{'e', "rev", 0, snprint_multipath_rev},

View File

@ -1,243 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 10 May 2024 20:53:33 -0400
Subject: [PATCH] multipath-tools man pages: Add format wildcard descriptions
Suggested-by: Nitin Yewale <nyewale@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/multipathd.8 | 193 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 189 insertions(+), 4 deletions(-)
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8
index 40a8dc6d..d834f89e 100644
--- a/multipathd/multipathd.8
+++ b/multipathd/multipathd.8
@@ -103,7 +103,7 @@ Show the paths that multipathd is monitoring, and their state.
.B list|show paths [raw] format $format
Show the paths that multipathd is monitoring, using a format string with path
format wildcards. Adding \fIraw\fR will remove the headers and alignment
-padding from the ouput.
+padding from the output. See "Path format wildcards" below.
.
.TP
.B list|show path $path
@@ -117,7 +117,8 @@ Show the multipath devices that the multipathd is monitoring.
.B list|show maps|multipaths [raw] format $format
Show the status of all multipath devices that the multipathd is monitoring,
using a format string with multipath format wildcards. Adding \fIraw\fR will
-remove the headers and alignment padding from the output.
+remove the headers and alignment padding from the output. See "Multipath
+format wildcards" below.
.
.TP
.B list|show maps|multipaths status
@@ -148,7 +149,7 @@ Show topology of a single multipath device specified by $map, for example
.B list|show map|multipath $map [raw] format $format.
Show the status of multipath device $map, using a format string with multipath
format wildcards. Adding \fIraw\fR will remove the headers and alignment
-padding from the output.
+padding from the output. See "Multipath format wildcards" below.
.
.TP
.B list|show map|multipath $map json
@@ -156,7 +157,8 @@ Show information about multipath device $map in JSON format.
.
.TP
.B list|show wildcards
-Show the format wildcards used in interactive commands taking $format.
+Show the format wildcards used in interactive commands taking $format. See
+"Format Wildcards" below.
.
.TP
.B list|show config
@@ -339,6 +341,189 @@ Stop multipathd.
.
.
.\" ----------------------------------------------------------------------------
+.SH "Format Wildcards"
+.\" ----------------------------------------------------------------------------
+.
+Multipathd commands that take a $format option require a format string. This
+string controls how a device is printed and should include format wildcards.
+When the devices are printed, these wildcards will be replaced by the
+appropriate device information. The following wildcards are supported.
+.TP
+.B Multipath format wildcards
+.RS
+.TP 12
+.B %n
+The device name.
+.TP
+.B %w
+The device WWID (uuid).
+.TP
+.B %d
+The device sysfs name (dm-<minor_nr>).
+.TP
+.B %F
+The device \fBfailback\fR setting. For deferred failbacks, it will either
+print the configured time if a deferred failback is not in progress, or
+it will show the current progress of a deferred failback.
+.TP
+.B %Q
+The device \fBno_path_retry\fR setting. If no_path_retry is set to a
+number of retires, it will either print the configured number of checker
+retries if the device is not in recovery mode, the number of seconds until
+queueing is disabled if the device is queueing in recovery mode, or \fIoff\fR
+if the device has disabled queueing.
+.TP
+.B %N
+The number of active paths for the device.
+.TP
+.B %r
+The device write-protect setting, either \fIro\fR or \fIrw\fR.
+.TP
+.B %t
+The device-mapper state of the device, either \fIsuspend\fR or \fIactive\fR.
+.TP
+.B %S
+The device size.
+.TP
+.B %f
+The device table features string.
+.TP
+.B %x
+The number of times the device has entered a state where it will fail IO.
+This is an alias for the \fB%4\fR wildcard.
+This value can be reset with the '\fIreset map $map stats\fR' command.
+.TP
+.B %h
+The device table hardware handler string.
+.TP
+.B %A
+The last action multipathd took on the device. This wildcard is for debugging
+use, as understanding its meaning requires looking at the code.
+.TP
+.B %0
+The number of times a path in the device has failed.
+This value can be reset with the '\fIreset map $map stats\fR' command.
+.TP
+.B %1
+The number of times multipathd has initiated a pathgroup switch for the device.
+This value can be reset with the '\fIreset map $map stats\fR' command.
+.TP
+.B %2
+The number of times multipathd has loaded a new table for the device.
+This value can be reset with the '\fIreset map $map stats\fR' command.
+.TP
+.B %3
+The approximate number of seconds that multipathd has spent queueing with
+no usable paths. This value can be reset with the '\fIreset map $map stats\fR'
+command.
+.TP
+.B %4
+The number of times the device has entered a state where it will fail IO.
+This is an alias for the \fB%x\fR wildcard.
+This value can be reset with the '\fIreset map $map stats\fR' command.
+.TP
+.B %s
+The vendor/product string for the device.
+.TP
+.B %v
+The array vendor string for the device.
+.TP
+.B %p
+The array product string for the device.
+.TP
+.B %e
+The array firmware revision string for the device.
+.TP
+.B %G
+The foreign library used for the device, or \fB--\fR for native device-mapper
+multipath devices.
+.TP
+.B %g
+Data from vendor specific vpd pages for the device, if any.
+.RE
+.
+.
+.TP
+.B Path format wildcards
+.RS
+.TP 12
+.B %w
+The device WWID (uuid).
+.TP
+.B %i
+The device Host:Channel:Id:Lun
+.TP
+.B %d
+The device sysfs name.
+.TP
+.B %D
+The device major:minor
+.TP
+.B %t
+The device-mapper state of the device, either \fIactive\fR or \fIfailed\fR.
+.TP
+.B %o
+Whether the device is \fIoffline\fR or \fIrunning\fR.
+.TP
+.B %T
+The multipathd path checker state of the device.
+.TP
+.B %s
+The vendor/product/revision string for the device.
+.TP
+.B %c
+The device's path checker name.
+.TP
+.B %C
+The progress towards the next path checker run on the device.
+.TP
+.B %p
+The device priority.
+.TP
+.B %S
+The device size.
+.TP
+.B %z
+The device serial number.
+.TP
+.B %M
+The device marginal state, either \fImarginal\fR or \fInormal\fR.
+.TP
+.B %m
+The multipath device that this device is a path of.
+.TP
+.B %N
+The host World Wide Node Name (WWNN) of the device.
+.TP
+.B %n
+The target World Wide Node Name (WWNN) of the device.
+.TP
+.B %R
+The host World Wide Port Name (WWPN) of the device.
+.TP
+.B %r
+The target World Wide Port Name (WWPN) of the device.
+.TP
+.B %a
+The host adapter name for the device (only SCSI devices).
+.TP
+.B %G
+The foreign library used for the device, or \fB--\fR for paths of native
+device-mapper multipath devices.
+.TP
+.B %g
+Data from vendor specific vpd pages for the device, if any.
+.TP
+.B %0
+The number of times this device has failed.
+.TP
+.B %P
+The device protocol. This output can be used for \fIprotocol\fR blacklist
+entries.
+.RE
+.
+.
+.\" ----------------------------------------------------------------------------
.SH "SYSTEMD INTEGRATION"
.\" ----------------------------------------------------------------------------
.

View File

@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 17 Mar 2020 17:28:24 -0500
Subject: [PATCH] libmultipath: assign variable to make gcc happy
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
There is nothing wrong with is_queueing not being set at the start
of __set_no_path_retry(), it will always get set before it is accessed,
but gcc 8.2.1 is failing with
structs_vec.c: In function __set_no_path_retry:
structs_vec.c:339:7: error: is_queueing may be used uninitialized in
this function [-Werror=maybe-uninitialized]
bool is_queueing;
^~~~~~~~~~~
so, assign a value to make it happy.
Reviewed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/structs_vec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index 3dbbaa0f..077f2e42 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -336,7 +336,7 @@ static void leave_recovery_mode(struct multipath *mpp)
void __set_no_path_retry(struct multipath *mpp, bool check_features)
{
- bool is_queueing;
+ bool is_queueing = false; /* assign a value to make gcc happy */
check_features = check_features && mpp->features != NULL;
if (check_features)
--
2.17.2

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -15,10 +15,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index d0ec9b44..2a75dc9c 100644
index 9060ac9b..034752d9 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -55,7 +55,7 @@ endif
@@ -53,7 +53,7 @@ endif
prefix =
exec_prefix = $(prefix)
usr_prefix = $(prefix)
@ -28,10 +28,10 @@ index d0ec9b44..2a75dc9c 100644
udevrulesdir = $(libudevdir)/rules.d
multipathdir = $(TOPDIR)/libmultipath
diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
index d7527d7d..0e0d70d5 100644
index 8f990494..8a3a1718 100644
--- a/kpartx/kpartx.rules
+++ b/kpartx/kpartx.rules
@@ -36,6 +36,6 @@ LABEL="mpath_kpartx_end"
@@ -32,6 +32,6 @@ LABEL="mpath_kpartx_end"
GOTO="kpartx_end"
LABEL="run_kpartx"
@ -61,3 +61,6 @@ index 0828a8f7..b9bbb3cf 100644
$(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz
$(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
--
2.17.2

View File

@ -13,26 +13,29 @@ it.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/blacklist.c | 6 ++----
libmultipath/blacklist.c | 9 ++-------
multipath/multipath.conf.5 | 11 ++++++-----
tests/blacklist.c | 7 ++-----
3 files changed, 10 insertions(+), 14 deletions(-)
tests/blacklist.c | 6 ++----
3 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
index 4e315c97..1e463ef6 100644
index 00e8dbdb..d9691b17 100644
--- a/libmultipath/blacklist.c
+++ b/libmultipath/blacklist.c
@@ -202,9 +202,6 @@ setup_default_blist (struct config * conf)
if (store_ble(conf->blist_devnode, "!^(sd[a-z]|dasd[a-z]|nvme[0-9])", ORIGIN_DEFAULT))
@@ -204,12 +204,6 @@ setup_default_blist (struct config * conf)
if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
return 1;
- if (store_ble(conf->elist_property, "(SCSI_IDENT_|ID_WWN)", ORIGIN_DEFAULT))
- 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,
@@ -410,7 +407,8 @@ filter_property(const struct config *conf, struct udev_device *udev,
@@ -411,7 +405,8 @@ filter_property(struct config *conf, struct udev_device *udev, int lvl,
*uid_attribute != '\0';
bool uid_attr_seen = false;
@ -43,10 +46,10 @@ index 4e315c97..1e463ef6 100644
udev_device_get_properties_list_entry(udev)) {
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index c74129bd..dd9f4dc7 100644
index 05a5e8ff..3455b1cc 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1351,9 +1351,14 @@ keywords. Both are regular expressions. For a full description of these keywords
@@ -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,
@ -62,7 +65,7 @@ index c74129bd..dd9f4dc7 100644
.
.RS
.PP
@@ -1364,10 +1369,6 @@ Blacklisting by missing properties is only applied to devices which do have the
@@ -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.
@ -74,21 +77,19 @@ index c74129bd..dd9f4dc7 100644
.TP
.B protocol
diff --git a/tests/blacklist.c b/tests/blacklist.c
index 882aa3a1..6a22b660 100644
index 6e7c1864..cc8a9a4a 100644
--- a/tests/blacklist.c
+++ b/tests/blacklist.c
@@ -375,9 +375,8 @@ static void test_property_missing(void **state)
{
static struct udev_device udev = { "sdb", { "ID_FOO", "ID_BAZ", "ID_BAR", "ID_SERIAL", NULL } };
@@ -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");
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, ""),
@@ -469,9 +468,7 @@ static void test_filter_path_missing1(void **state)
@@ -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;
@ -99,3 +100,6 @@ index 882aa3a1..6a22b660 100644
}
/* This one matches the property whitelist, to test the other missing
--
2.17.2

View File

@ -12,19 +12,26 @@ simple way to disable multipath. Simply removing or renaming
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/config.c | 13 +++++++++++++
libmultipath/config.c | 15 +++++++++++++++
libmultipath/config.h | 1 +
multipath/multipath.rules | 1 +
multipathd/multipathd.8 | 2 ++
multipathd/multipathd.service | 1 +
multipathd/multipathd.socket | 1 +
6 files changed, 19 insertions(+)
5 files changed, 20 insertions(+)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 30046a17..5f35c3d3 100644
index b4d87689..b36778b0 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -895,6 +895,19 @@ int _init_config (const char *file, struct config *conf)
@@ -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);
@ -37,7 +44,8 @@ index 30046a17..5f35c3d3 100644
+ goto out;
+ }
+ }
+ if (store_ble(conf->blist_devnode, ".*", ORIGIN_NO_CONFIG)) {
+ if (store_ble(conf->blist_devnode, strdup(".*"),
+ ORIGIN_NO_CONFIG)) {
+ condlog(0, "cannot store default no-config blacklist\n");
+ goto out;
+ }
@ -45,7 +53,7 @@ index 30046a17..5f35c3d3 100644
conf->processed_main_config = 1;
diff --git a/libmultipath/config.h b/libmultipath/config.h
index 933fe0d1..5f01c1fc 100644
index ceecff2d..3368d8c9 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -9,6 +9,7 @@
@ -54,8 +62,8 @@ index 933fe0d1..5f01c1fc 100644
#define ORIGIN_CONFIG 1
+#define ORIGIN_NO_CONFIG 2
enum devtypes {
DEV_NONE,
/*
* 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
@ -82,26 +90,17 @@ index 048a838d..8bd47a80 100644
.
.\" ----------------------------------------------------------------------------
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
index 0b2ac814..6d57c7e8 100644
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 shutdown.target
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
diff --git a/multipathd/multipathd.socket b/multipathd/multipathd.socket
index c777e5e3..3c20a2ff 100644
--- a/multipathd/multipathd.socket
+++ b/multipathd/multipathd.socket
@@ -1,6 +1,7 @@
[Unit]
Description=multipathd control socket
DefaultDependencies=no
+ConditionPathExists=/etc/multipath.conf
ConditionKernelCommandLine=!nompath
ConditionKernelCommandLine=!multipath=off
ConditionVirtualization=!container
--
2.17.2

View File

@ -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

View File

@ -14,17 +14,17 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/config.c | 2 +
multipath/Makefile | 5 +
multipath/mpathconf | 556 ++++++++++++++++++++++++++++++++++++++++++
multipath/mpathconf | 555 ++++++++++++++++++++++++++++++++++++++++++
multipath/mpathconf.8 | 135 ++++++++++
4 files changed, 698 insertions(+)
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 5f35c3d3..cee3bbb7 100644
index b36778b0..26f8e050 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -897,6 +897,8 @@ int _init_config (const char *file, struct config *conf)
@@ -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.");
@ -69,10 +69,10 @@ index b9bbb3cf..e720c7f6 100644
$(RM) core *.o $(EXEC) *.gz
diff --git a/multipath/mpathconf b/multipath/mpathconf
new file mode 100644
index 00000000..c00d2555
index 00000000..f34003c9
--- /dev/null
+++ b/multipath/mpathconf
@@ -0,0 +1,556 @@
@@ -0,0 +1,555 @@
+#!/bin/bash
+#
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
@ -107,6 +107,11 @@ index 00000000..c00d2555
+defaults {
+ user_friendly_names yes
+ find_multipaths yes
+ enable_foreign \"^$\"
+}
+
+blacklist_exceptions {
+ property \"(SCSI_IDENT_|ID_WWN)\"
+}"
+
+CONFIGFILE="/etc/multipath.conf"
@ -124,8 +129,8 @@ index 00000000..c00d2555
+ 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 <yes|no|strict|greedy|smart>"
+ echo "Set default property blacklist (Default n): --property_blacklist <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>"
@ -294,12 +299,8 @@ index 00000000..c00d2555
+ echo "--user_friendly_names must be either 'y' or 'n'"
+ exit 1
+ fi
+ 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'"
+ 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
@ -310,7 +311,7 @@ index 00000000..c00d2555
+ 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 [ -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
@ -385,50 +386,45 @@ index 00000000..c00d2555
+fi
+
+if [ "$HAVE_BLACKLIST" = "1" ]; then
+ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"" ; 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[[:space:]][[:space:]]*\"\.\?\*\"" ; then
+ 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[[:space:]][[:space:]]*\"\.\?\*\"" ; 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[[:space:]][[:space:]]*\"\.\?\*\"" ; then
+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"" ; 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:]]*\([^[:blank:]]*\).*$/\1/p' | sed -n 1p`
+ if [ "$HAVE_FIND" = "1" ]; then
+ HAVE_FIND="yes"
+ elif [ "$HAVE_FIND" = "0" ]; then
+ HAVE_FIND="no"
+ 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:]][[:space:]]*\(yes\|1\)" ; then
+ 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:]][[:space:]]*\(no\|0\)" ; then
+ 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:]][[:space:]]*\"\.\*\"" ; then
+ 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[[:space:]][[:space:]]*\"\^\$\"" ; then
+ HAVE_FOREIGN=2
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign[[:space:]][[:space:]]*\"NONE\"" ; then
+ HAVE_FOREIGN=2
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign" ; then
+ HAVE_FOREIGN=3
+ HAVE_FOREIGN=2
+ fi
+fi
+
+if [ "$HAVE_EXCEPTIONS" = "1" ]; then
+ if sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; 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:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
+ elif sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
+ HAVE_PROPERTY=0
+ fi
+fi
@ -439,10 +435,10 @@ index 00000000..c00d2555
+ else
+ echo "multipath is disabled"
+ fi
+ if [ -z "$HAVE_FIND" ]; then
+ echo "find_multipaths is no"
+ if [ -z "$HAVE_FIND" -o "$HAVE_FIND" = 0 ]; then
+ echo "find_multipaths is disabled"
+ else
+ echo "find_multipaths is $HAVE_FIND"
+ echo "find_multipaths is enabled"
+ fi
+ if [ -z "$HAVE_FRIENDLY" -o "$HAVE_FRIENDLY" = 0 ]; then
+ echo "user_friendly_names is disabled"
@ -455,10 +451,8 @@ index 00000000..c00d2555
+ echo "default property blacklist is enabled"
+ fi
+ if [ -z "$HAVE_FOREIGN" -o "$HAVE_FOREIGN" = 0 ]; then
+ echo "enable_foreign is not set (no foreign multipath devices will be shown)"
+ echo "enable_foreign is not set (all foreign multipath devices will be shown)"
+ elif [ "$HAVE_FOREIGN" = 1 ]; then
+ echo "enable_foreign is set (all foreign multipath devices will be shown)"
+ elif [ "$HAVE_FOREIGN" = 2 ]; 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)"
@ -503,14 +497,14 @@ index 00000000..c00d2555
+
+if [ "$ENABLE" = 2 ]; then
+ if [ "$HAVE_DISABLE" = 1 ]; then
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"/# devnode ".*"/' $TMPFILE
+ 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[[:space:]][[:space:]]*\"\.\?\*\"/ wwid ".*"/' $TMPFILE
+ 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
@ -524,7 +518,7 @@ index 00000000..c00d2555
+ add_blacklist_exceptions
+elif [ "$ENABLE" = 1 ]; then
+ if [ "$HAVE_DISABLE" = 1 ]; then
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"/# devnode ".*"/' $TMPFILE
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE
+ fi
+elif [ "$ENABLE" = 0 ]; then
+ if [ -z "$HAVE_DISABLE" ]; then
@ -532,25 +526,30 @@ index 00000000..c00d2555
+ devnode ".*"
+' $TMPFILE
+ elif [ "$HAVE_DISABLE" = 0 ]; then
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"/ devnode ".*"/' $TMPFILE
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"/ devnode ".*"/' $TMPFILE
+ fi
+fi
+
+if [ -n "$FIND" ]; then
+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 '"$FIND"'
+ find_multipaths yes
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$FIND" != "$HAVE_FIND" ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:blank:]]*find_multipaths[[:blank:]][[:blank:]]*[^[:blank:]]*/ find_multipaths '"$FIND"'/' $TMPFILE
+ 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:]][[:space:]]*\(yes\|1\)/ user_friendly_names no/' $TMPFILE
+ 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
@ -560,14 +559,14 @@ index 00000000..c00d2555
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$HAVE_FRIENDLY" = 0 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]][[:space:]]*\(no\|0\)/ user_friendly_names yes/' $TMPFILE
+ 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:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/# property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
+ 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
@ -577,24 +576,24 @@ index 00000000..c00d2555
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$HAVE_PROPERTY" = 0 ]; then
+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/ property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
+ 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" = "n" ]; then
+ if [ "$HAVE_FOREIGN" = 1 -o "$HAVE_FOREIGN" = 3 ]; then
+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" = "y" ]; then
+elif [ "$FOREIGN" = "n" ]; then
+ if [ -z "$HAVE_FOREIGN" ]; then
+ sed -i '/^defaults[[:space:]]*{/ a\
+ enable_foreign ".*"
+ enable_foreign "^$"
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$HAVE_FOREIGN" = 0 -o "$HAVE_FOREIGN" = 2 -o "$HAVE_FOREIGN" = 3 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*#\?[[:space:]]*enable_foreign.*$/ enable_foreign ".*"/' $TMPFILE
+ 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
@ -631,7 +630,7 @@ index 00000000..c00d2555
+fi
diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8
new file mode 100644
index 00000000..a14d831e
index 00000000..b82961d6
--- /dev/null
+++ b/multipath/mpathconf.8
@@ -0,0 +1,135 @@
@ -675,9 +674,9 @@ index 00000000..a14d831e
+already exists, mpathconf will edit it. If it does not exist, mpathconf will
+create a default file with
+.B user_friendly_names
+set and
+and
+.B find_multipaths
+set to \fByes\fP. To disable these, use the
+set. To disable these, use the
+.B --user_friendly_names n
+and
+.B --find_multipaths n
@ -714,13 +713,13 @@ index 00000000..a14d831e
+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 { \fByes\fP | \fBno\fP | \fBstrict\fP | \fBgreedy\fP | \fBsmart\fP }
+If set to \fB<value>\fP, this adds the line
+.B find_multipaths <value>
+.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. 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.
+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
@ -731,11 +730,11 @@ index 00000000..a14d831e
+present. This command can be used along with any other command.
+.TP
+.B --enable_foreign\fP { \fBy\fP | \fBn\fP }
+If set to \fBy\fP, this adds the line
+.B enable_foreign ".*"
+If set to \fBn\fP, this adds the line
+.B enable_foreign "^$"
+to the
+.B /etc/multipath.conf
+defaults section. if set to \fBn\fP, this removes the line, if present. This
+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
@ -770,3 +769,6 @@ index 00000000..a14d831e
+.BR service (8),
+.SH AUTHOR
+Benjamin Marzinski <bmarzins@redhat.com>
--
2.17.2

View File

@ -14,38 +14,23 @@ multipathd.service
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/main.c | 54 +++++++++++++++++++++++++++++++++--
multipath/multipath.8 | 7 ++++-
libmultipath/wwids.c | 44 +++++++++++++++++++++++++++++++++++
libmultipath/wwids.h | 1 +
multipath/main.c | 10 ++++++--
multipath/multipath.8 | 7 +++++-
multipathd/multipathd.service | 1 +
3 files changed, 59 insertions(+), 3 deletions(-)
5 files changed, 60 insertions(+), 3 deletions(-)
diff --git a/multipath/main.c b/multipath/main.c
index 65ece830..748e7902 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -122,7 +122,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);
@@ -136,6 +136,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"
@@ -450,6 +452,50 @@ static void cleanup_vecs(void)
free_pathvec(vecs.pathvec, FREE_PATHS);
}
+static int remember_cmdline_wwid(void)
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;
@ -88,20 +73,50 @@ index 65ece830..748e7902 100644
+ }
+ return ret;
+}
+
static int
configure (struct config *conf, enum mpath_cmds cmd,
enum devtypes dev_type, char *devpath)
@@ -838,7 +884,7 @@ main (int argc, char *argv[])
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;
atexit(cleanup_vecs);
- while ((arg = getopt(argc, argv, ":adDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
+ while ((arg = getopt(argc, argv, ":aAdDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
- 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;
@@ -915,6 +961,10 @@ main (int argc, char *argv[])
@@ -977,6 +979,10 @@ main (int argc, char *argv[])
case 'T':
cmd = CMD_DUMP_CONFIG;
break;
@ -113,7 +128,7 @@ index 65ece830..748e7902 100644
usage(argv[0]);
exit(RTVL_OK);
diff --git a/multipath/multipath.8 b/multipath/multipath.8
index 17df59f5..5ca75359 100644
index 9cdd05a3..8befc45a 100644
--- a/multipath/multipath.8
+++ b/multipath/multipath.8
@@ -63,7 +63,7 @@ multipath \- Device mapper target autoconfig.
@ -138,10 +153,10 @@ index 17df59f5..5ca75359 100644
Remove the WWID for the specified device from the WWIDs file.
.
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
index 6d57c7e8..dfc1e962 100644
index 17434cef..0fbcc46b 100644
--- a/multipathd/multipathd.service
+++ b/multipathd/multipathd.service
@@ -16,6 +16,7 @@ Type=notify
@@ -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
@ -149,3 +164,6 @@ index 6d57c7e8..dfc1e962 100644
ExecStart=/sbin/multipathd -d -s
ExecReload=/sbin/multipathd reconfigure
TasksMax=infinity
--
2.17.2

View File

@ -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

View File

@ -12,10 +12,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index c27946c7..e0dd32ad 100644
index e5ee6afe..52fe05b9 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -23,7 +23,7 @@
@@ -22,7 +22,7 @@
#define DEFAULT_NO_PATH_RETRY NO_PATH_RETRY_UNDEF
#define DEFAULT_VERBOSITY 2
#define DEFAULT_REASSIGN_MAPS 0
@ -24,3 +24,6 @@ index c27946c7..e0dd32ad 100644
#define DEFAULT_FAST_IO_FAIL 5
#define DEFAULT_DEV_LOSS_TMO 600
#define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_ON
--
2.17.2

View File

@ -1,10 +1,7 @@
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 function missing argument
A future patch will change the compilation options to error when
function declarations have unspecified arguments.
Subject: [PATCH] RH: Fix nvme compilation warning
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
@ -24,3 +21,6 @@ index adb192b6..bfd10ef8 100644
void argconfig_append_usage(const char *str);
void argconfig_print_help(const char *program_desc,
const struct argconfig_commandline_options *options);
--
2.17.2

View File

@ -82,3 +82,6 @@ index b5c7873d..e139360c 100644
switch (rc) {
case NVME_ANA_OPTIMIZED:
--
2.17.2

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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, &params);
+ if (dm_get_next_target(dmt, NULL, &start, &length,
+ &target_type, &params) != 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, &params[0]) &&
+ dm_get_map(names->name, &size, &params[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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

Some files were not shown because too many files have changed in this diff Show More