Compare commits

..

No commits in common. 'c9' and 'i10cs' have entirely different histories.
c9 ... i10cs

@ -1 +1 @@
067d668de8e3a70b7c176bbf0c0616d5835bbe44 SOURCES/multipath-tools-0.8.7.tgz
8470daab6fbb871573523a2c64d4f2c0f906ce86 SOURCES/multipath-tools-0.9.9.tgz

2
.gitignore vendored

@ -1 +1 @@
SOURCES/multipath-tools-0.8.7.tgz
SOURCES/multipath-tools-0.9.9.tgz

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

@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 5 Jun 2024 19:22:48 -0400
Subject: [PATCH] multipathd: fix flush check in flush_map()
Forgot the comparison in the "if" statement.
Fixes 8a3898339 ("multipathd: sync features on flush_map failure corner case")
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 09286dd0..58afe14a 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -813,7 +813,7 @@ flush_map(struct multipath * mpp, struct vectors * vecs)
{
int r = dm_suspend_and_flush_map(mpp->alias, 0);
if (r != DM_FLUSH_OK) {
- if (DM_FLUSH_FAIL_CANT_RESTORE)
+ if (r == DM_FLUSH_FAIL_CANT_RESTORE)
remove_feature(&mpp->features, "queue_if_no_path");
condlog(0, "%s: can't flush", mpp->alias);
return r;

@ -0,0 +1,63 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 13 Apr 2017 07:22:23 -0500
Subject: [PATCH] RH: fixup udev rules for redhat
The multipath rules need to run after scsi_id is run. This means moving
them after 60-persistent-storage.rules for redhat. Redhat also uses a
different naming scheme for partitions than SuSE.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile.inc | 2 +-
kpartx/kpartx.rules | 2 +-
multipath/Makefile | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 81b86cd8..33dbb99c 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -34,7 +34,7 @@ endif
# Paths. All these can be overridden on the "make" command line.
prefix :=
# Prefix for binaries
-exec_prefix := $(prefix)
+exec_prefix := $(prefix)/usr
# Prefix for non-essential libraries (libdmmp)
usr_prefix := $(if $(prefix),$(prefix),/usr)
# Prefix for configuration files (multipath.conf)
diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
index 8dd3369c..7c3c7524 100644
--- a/kpartx/kpartx.rules
+++ b/kpartx/kpartx.rules
@@ -39,6 +39,6 @@ LABEL="mpath_kpartx_end"
GOTO="kpartx_end"
LABEL="run_kpartx"
-RUN+="/sbin/kpartx -un -p -part /dev/$name"
+RUN+="/sbin/kpartx -un /dev/$name"
LABEL="kpartx_end"
diff --git a/multipath/Makefile b/multipath/Makefile
index 67fb5e62..2ea9e528 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -27,7 +27,7 @@ install:
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 99-z-dm-mpath-late.rules $(DESTDIR)$(udevrulesdir)
- $(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/56-multipath.rules
+ $(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(tmpfilesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 tmpfiles.conf $(DESTDIR)$(tmpfilesdir)/multipath.conf
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man8
@@ -50,7 +50,7 @@ uninstall:
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/99-z-dm-mpath-late.rules
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/scsi_dh.conf
- $(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
+ $(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
$(Q)$(RM) $(DESTDIR)$(mandir)/man8/$(EXEC).8
$(Q)$(RM) $(DESTDIR)$(mandir)/man5/$(EXEC).conf.5
$(Q)$(RM) $(DESTDIR)$(tmpfilesdir)/multipath.conf

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

@ -13,26 +13,25 @@ it.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/blacklist.c | 6 ++----
multipath/multipath.conf.5 | 11 ++++++-----
libmultipath/blacklist.c | 5 ++---
multipath/multipath.conf.5.in | 11 ++++++-----
tests/blacklist.c | 7 ++-----
3 files changed, 10 insertions(+), 14 deletions(-)
3 files changed, 10 insertions(+), 13 deletions(-)
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
index 4e315c97..1e463ef6 100644
index 75100b20..0b212078 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))
@@ -230,8 +230,6 @@ setup_default_blist (struct config * conf)
ORIGIN_DEFAULT))
return 1;
}
- if (store_ble(conf->elist_property, "(SCSI_IDENT_|ID_WWN)", 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,
@@ -438,7 +436,8 @@ filter_property(const struct config *conf, struct udev_device *udev,
*uid_attribute != '\0';
bool uid_attr_seen = false;
@ -42,11 +41,11 @@ index 4e315c97..1e463ef6 100644
udev_list_entry_foreach(list_entry,
udev_device_get_properties_list_entry(udev)) {
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index c74129bd..dd9f4dc7 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
diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in
index dacb9b0e..645e8f88 100644
--- a/multipath/multipath.conf.5.in
+++ b/multipath/multipath.conf.5.in
@@ -1468,9 +1468,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 +61,7 @@ index c74129bd..dd9f4dc7 100644
.
.RS
.PP
@@ -1364,10 +1369,6 @@ Blacklisting by missing properties is only applied to devices which do have the
@@ -1481,10 +1486,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,10 +73,10 @@ index c74129bd..dd9f4dc7 100644
.TP
.B protocol
diff --git a/tests/blacklist.c b/tests/blacklist.c
index 882aa3a1..6a22b660 100644
index ba8dfd07..693db3fa 100644
--- a/tests/blacklist.c
+++ b/tests/blacklist.c
@@ -375,9 +375,8 @@ static void test_property_missing(void **state)
@@ -384,9 +384,8 @@ static void test_property_missing(void **state)
{
static struct udev_device udev = { "sdb", { "ID_FOO", "ID_BAZ", "ID_BAR", "ID_SERIAL", NULL } };
conf.blist_property = blist_property_wwn;
@ -88,7 +87,7 @@ index 882aa3a1..6a22b660 100644
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)
@@ -478,9 +477,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;

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

@ -14,20 +14,21 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/config.c | 13 +++++++++++++
libmultipath/config.h | 1 +
multipath/multipath.rules | 1 +
multipathd/multipathd.8 | 2 ++
multipathd/multipathd.service | 1 +
multipath/main.c | 6 ++++++
multipath/multipath.rules.in | 1 +
multipathd/multipathd.8.in | 2 ++
multipathd/multipathd.service.in | 1 +
multipathd/multipathd.socket | 1 +
6 files changed, 19 insertions(+)
7 files changed, 25 insertions(+)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 30046a17..5f35c3d3 100644
index 83fa7369..002027a7 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -895,6 +895,19 @@ int _init_config (const char *file, struct config *conf)
goto out;
@@ -959,6 +959,19 @@ int _init_config (const char *file, struct config *conf)
}
factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
validate_pctable(conf->overrides, 0, file);
+ } else {
+ condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
+ if (conf->blist_devnode == NULL) {
@ -45,10 +46,10 @@ index 30046a17..5f35c3d3 100644
conf->processed_main_config = 1;
diff --git a/libmultipath/config.h b/libmultipath/config.h
index 933fe0d1..5f01c1fc 100644
index 384193ab..158cebf0 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -9,6 +9,7 @@
@@ -10,6 +10,7 @@
#define ORIGIN_DEFAULT 0
#define ORIGIN_CONFIG 1
@ -56,10 +57,39 @@ index 933fe0d1..5f01c1fc 100644
enum devtypes {
DEV_NONE,
diff --git a/multipath/multipath.rules b/multipath/multipath.rules
index 9df11a95..0486bf70 100644
--- a/multipath/multipath.rules
+++ b/multipath/multipath.rules
diff --git a/multipath/main.c b/multipath/main.c
index ce702e7f..c21e3e0b 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -842,11 +842,14 @@ main (int argc, char *argv[])
char *dev = NULL;
struct config *conf;
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))
@@ -1097,6 +1100,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)
diff --git a/multipath/multipath.rules.in b/multipath/multipath.rules.in
index 780bf852..2c518378 100644
--- a/multipath/multipath.rules.in
+++ b/multipath/multipath.rules.in
@@ -9,6 +9,7 @@ IMPORT{cmdline}="nompath"
ENV{nompath}=="?*", GOTO="end_mpath"
IMPORT{cmdline}="multipath"
@ -68,33 +98,33 @@ index 9df11a95..0486bf70 100644
ENV{DEVTYPE}!="partition", GOTO="test_dev"
IMPORT{parent}="DM_MULTIPATH_DEVICE_PATH"
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8
index 048a838d..8bd47a80 100644
--- a/multipathd/multipathd.8
+++ b/multipathd/multipathd.8
@@ -39,6 +39,8 @@ map regains its maximum performance and redundancy.
This daemon executes the external \fBmultipath\fR tool when events occur.
In turn, the multipath tool signals the multipathd daemon when it is done with
devmap reconfiguration, so that it can refresh its failed path list.
diff --git a/multipathd/multipathd.8.in b/multipathd/multipathd.8.in
index 7bc8806e..315884eb 100644
--- a/multipathd/multipathd.8.in
+++ b/multipathd/multipathd.8.in
@@ -49,6 +49,8 @@ map regains its maximum performance and redundancy.
With the \fB-k\fR option, \fBmultipathd\fR acts as a client utility that
sends commands to a running instance of the multipathd daemon (see
\fBCOMMANDS\fR below).
+
+In this Linux distribution, multipathd does not run unless a /etc/multipath.conf file exists.
.
.
.\" ----------------------------------------------------------------------------
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
index 0b2ac814..6d57c7e8 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
After=multipathd.socket systemd-udev-trigger.service systemd-udev-settle.service
diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in
index a63ddd9a..01ceff7d 100644
--- a/multipathd/multipathd.service.in
+++ b/multipathd/multipathd.service.in
@@ -6,6 +6,7 @@ Wants=systemd-udevd-kernel.socket @MODPROBE_UNIT@
After=systemd-udevd-kernel.socket @MODPROBE_UNIT@
After=multipathd.socket systemd-remount-fs.service
Before=initrd-cleanup.service
+ConditionPathExists=/etc/multipath.conf
DefaultDependencies=no
Conflicts=shutdown.target
ConditionKernelCommandLine=!nompath
Conflicts=initrd-cleanup.service
diff --git a/multipathd/multipathd.socket b/multipathd/multipathd.socket
index c777e5e3..3c20a2ff 100644
index 6a62f5fd..263b6b0c 100644
--- a/multipathd/multipathd.socket
+++ b/multipathd/multipathd.socket
@@ -1,6 +1,7 @@

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

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

@ -9,29 +9,23 @@ still being generic.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile.inc | 26 +++++++++++++++++++-------
1 file changed, 19 insertions(+), 7 deletions(-)
Makefile.inc | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 2a75dc9c..5ac660de 100644
index 33dbb99c..94e0ec85 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,)
@@ -95,11 +95,23 @@ SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo
MODPROBE_UNIT := $(shell test "0$(SYSTEMD)" -lt 245 2>/dev/null || \
echo "modprobe@dm_multipath.service")
-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
+ OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4 \
+ -Wall $(FORTIFY_OPT) -fexceptions -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
@ -43,24 +37,19 @@ index 2a75dc9c..5ac660de 100644
+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
- $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS)
-CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \
+ $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) -Wstrict-prototypes
+CPPFLAGS := $(CPPFLAGS) $(D_URCU_VERSION) \
-D_FILE_OFFSET_BITS=64 \
-DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(TGTDIR)$(plugindir)\" \
-DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(TGTDIR)$(configdir)\" \
@@ -109,7 +121,7 @@ CFLAGS := -std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe
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 \
BIN_LDFLAGS := -pie
%.o: %.c
@echo building $@ because of $?
- $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+ $(CC) $(CFLAGS) -c -o $@ $<
# Source code directories. Don't modify.

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

@ -10,22 +10,23 @@ command line. But, mostly it is used to get a multipath.conf file
with the OS defaults, and to enable and disable multipathing via
a single command.
Co-authored-by: Paul Donohue <git@PaulSD.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/config.c | 2 +
multipath/Makefile | 5 +
multipath/mpathconf | 556 ++++++++++++++++++++++++++++++++++++++++++
multipath/mpathconf.8 | 135 ++++++++++
4 files changed, 698 insertions(+)
multipath/Makefile | 4 +
multipath/mpathconf | 658 ++++++++++++++++++++++++++++++++++++++++++
multipath/mpathconf.8 | 151 ++++++++++
4 files changed, 815 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 002027a7..3d5943d3 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -897,6 +897,8 @@ int _init_config (const char *file, struct config *conf)
factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
@@ -961,6 +961,8 @@ int _init_config (const char *file, struct config *conf)
validate_pctable(conf->overrides, 0, file);
} else {
condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
+ condlog(0, "You can run \"/sbin/mpathconf --enable\" to create");
@ -34,45 +35,46 @@ index 5f35c3d3..cee3bbb7 100644
conf->blist_devnode = vector_alloc();
if (!conf->blist_devnode) {
diff --git a/multipath/Makefile b/multipath/Makefile
index b9bbb3cf..e720c7f6 100644
index 2ea9e528..3dc241cc 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -18,10 +18,12 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
$(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS) $(LIBDEPS)
$(GZIP) $(EXEC).8 > $(EXEC).8.gz
$(GZIP) $(EXEC).conf.5 > $(EXEC).conf.5.gz
+ $(GZIP) mpathconf.8 > mpathconf.8.gz
@@ -24,6 +24,7 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
install:
$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
+ $(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/
$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
$(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
@@ -29,13 +31,16 @@ install:
$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(man8dir)
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir)
$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir)
+ $(INSTALL_PROGRAM) -m 644 mpathconf.8.gz $(DESTDIR)$(man8dir)
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
$(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
+ $(Q)$(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 99-z-dm-mpath-late.rules $(DESTDIR)$(udevrulesdir)
@@ -32,6 +33,7 @@ install:
$(Q)$(INSTALL_PROGRAM) -m 644 tmpfiles.conf $(DESTDIR)$(tmpfilesdir)/multipath.conf
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man8
$(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)/man8
+ $(Q)$(INSTALL_PROGRAM) -m 644 mpathconf.8 $(DESTDIR)$(mandir)/man8
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man5
$(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5 $(DESTDIR)$(mandir)/man5
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(modulesloaddir)
@@ -46,12 +48,14 @@ endif
uninstall:
$(RM) $(DESTDIR)$(bindir)/$(EXEC)
$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
$(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
+ $(RM) $(DESTDIR)$(bindir)/mpathconf
$(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz
$(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
+ $(RM) $(DESTDIR)$(man8dir)/mpathconf.8.gz
$(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC)
+ $(Q)$(RM) $(DESTDIR)$(bindir)/mpathconf
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/99-z-dm-mpath-late.rules
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/scsi_dh.conf
$(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
$(Q)$(RM) $(DESTDIR)$(mandir)/man8/$(EXEC).8
+ $(Q)$(RM) $(DESTDIR)$(mandir)/man8/mpathconf.8
$(Q)$(RM) $(DESTDIR)$(mandir)/man5/$(EXEC).conf.5
$(Q)$(RM) $(DESTDIR)$(tmpfilesdir)/multipath.conf
clean: dep_clean
$(RM) core *.o $(EXEC) *.gz
diff --git a/multipath/mpathconf b/multipath/mpathconf
new file mode 100644
index 00000000..c00d2555
index 00000000..ce430075
--- /dev/null
+++ b/multipath/mpathconf
@@ -0,0 +1,556 @@
@@ -0,0 +1,658 @@
+#!/bin/bash
+#
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
@ -92,7 +94,7 @@ index 00000000..c00d2555
+# This program was largely ripped off from lvmconf
+#
+
+unset ENABLE FIND FRIENDLY PROPERTY FOREIGN MODULE MULTIPATHD HAVE_DISABLE HAVE_WWID_DISABLE HAVE_FIND HAVE_BLACKLIST HAVE_EXCEPTIONS HAVE_DEFAULTS HAVE_FRIENDLY HAVE_PROPERTY HAVE_FOREIGN HAVE_MULTIPATHD HAVE_MODULE HAVE_OUTFILE SHOW_STATUS CHANGED_CONFIG WWID_LIST
+unset ENABLE FIND FRIENDLY PROPERTY FOREIGN MODULE MULTIPATHD HAVE_DISABLE HAVE_WWID_DISABLE HAVE_FIND HAVE_BLACKLIST HAVE_EXCEPTIONS HAVE_DEFAULTS HAVE_FRIENDLY HAVE_PROPERTY HAVE_FOREIGN HAVE_MULTIPATHD HAVE_MODULE HAVE_OUTFILE SHOW_STATUS CHANGED_CONFIG WWID_LIST HAVE_OPTION OPTION_NAME OPTION_VALUE HAVE_RECHECK_WWID RECHECK_WWID
+
+DEFAULT_CONFIG="# device-mapper-multipath configuration file
+
@ -106,7 +108,7 @@ index 00000000..c00d2555
+
+defaults {
+ user_friendly_names yes
+ find_multipaths yes
+ find_multipaths on
+}"
+
+CONFIGFILE="/etc/multipath.conf"
@ -124,9 +126,11 @@ 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 find_multipaths (Default on): --find_multipaths <on|yes|y|off|no|n|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>"
+ echo "select output file (Default /etc/multipath.conf): --outfile <FILE>"
@ -219,6 +223,15 @@ index 00000000..c00d2555
+ 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
@ -237,6 +250,20 @@ index 00000000..c00d2555
+ exit 1
+ fi
+ ;;
+ --option)
+ if [ -n "$2" ]; then
+ OPTION_NAME=$(echo $2 | cut -s -f1 -d:)
+ OPTION_VALUE=$(echo $2 | cut -s -f2 -d:)
+ if [ -z "$OPTION_NAME" ]; then
+ usage
+ exit 1
+ fi
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ --enable_foreign)
+ if [ -n "$2" ]; then
+ FOREIGN=$2
@ -283,23 +310,31 @@ index 00000000..c00d2555
+
+function validate_args
+{
+ if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$PROPERTY" -o -n "$MODULE" ]; then
+ if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$PROPERTY" -o -n "$MODULE" -o -n "$FOREIGN" -o -n "$OPTION_NAME" -o -n "$RECHECK_WWID" ]; then
+ echo "ignoring extra parameters on disable"
+ FRIENDLY=""
+ FIND=""
+ PROPERTY=""
+ MODULE=""
+ 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"
+ FIND="on"
+ 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'"
+ FIND="off"
+ elif [ -n "$FIND" ] && [ "$FIND" != "on" -a "$FIND" != "yes" -a "$FIND" != "off" -a "$FIND" != "no" -a "$FIND" != "strict" -a "$FIND" != "greedy" -a "$FIND" != "smart" ]; then
+ echo "--find_multipaths must be one of 'on' 'yes' 'y' 'off' 'no' 'n' 'strict' 'greedy' or 'smart'"
+ exit 1
+ fi
+ if [ -n "$PROPERTY" ] && [ "$PROPERTY" != "y" -a "$PROPERTY" != "n" ]; then
@ -310,7 +345,19 @@ 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 [ -n "$OPTION_NAME" ]; then
+ if [[ $OPTION_NAME =~ [[:space:]]|#|\"|!|\{|\} ]]; then
+ echo "--option name \"$OPTION_NAME\" is invalid"
+ exit 1
+ elif [[ $OPTION_VALUE =~ \"|#|!|\{|\} ]]; then
+ echo "--option value \"$OPTION_VALUE\" is invalid"
+ exit 1
+ fi
+ if [[ $OPTION_VALUE =~ [[:space:]] ]]; then
+ OPTION_VALUE=\"$OPTION_VALUE\"
+ fi
+ fi
+ if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" -a -z "$PROPERTY" -a -z "$FOREIGN" -a -z "$OPTION_NAME" -a -z "$RECHECK_WWID" ]; then
+ SHOW_STATUS=1
+ fi
+ if [ -n "$MODULE" ] && [ "$MODULE" != "y" -a "$MODULE" != "n" ]; then
@ -412,6 +459,11 @@ index 00000000..c00d2555
+ 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
@ -423,6 +475,13 @@ index 00000000..c00d2555
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign" ; then
+ HAVE_FOREIGN=3
+ fi
+ if [ -n "$OPTION_NAME" ]; then
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q '^[[:space:]]*'"$OPTION_NAME"'[[:space:]][[:space:]]*'"$OPTION_VALUE" ; then
+ HAVE_OPTION=1
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q '^[[:space:]]*'"$OPTION_NAME"'\([[:space:]].*\)\?$' ; then
+ HAVE_OPTION=0
+ fi
+ fi
+fi
+
+if [ "$HAVE_EXCEPTIONS" = "1" ]; then
@ -440,7 +499,7 @@ index 00000000..c00d2555
+ echo "multipath is disabled"
+ fi
+ if [ -z "$HAVE_FIND" ]; then
+ echo "find_multipaths is no"
+ echo "find_multipaths is off"
+ else
+ echo "find_multipaths is $HAVE_FIND"
+ fi
@ -449,6 +508,11 @@ index 00000000..c00d2555
+ 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
@ -565,13 +629,38 @@ index 00000000..c00d2555
+ 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
+ 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
@ -599,6 +688,21 @@ index 00000000..c00d2555
+ fi
+fi
+
+if [ -n "$OPTION_NAME" -a -n "$OPTION_VALUE" ]; then
+ if [ -z "$HAVE_OPTION" ]; then
+ sed -i '/^defaults[[:space:]]*{/ a\
+ '"$OPTION_NAME"' '"$OPTION_VALUE"'
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$HAVE_OPTION" = 0 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*'"$OPTION_NAME"'\([[:space:]].*\)\?$/ '"$OPTION_NAME"' '"$OPTION_VALUE"'/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+elif [ -n "$OPTION_NAME" -a -n "$HAVE_OPTION" ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/{/^[[:space:]]*'"$OPTION_NAME"'\([[:space:]].*\)\?$/d}' $TMPFILE
+ CHANGED_CONFIG=1
+fi
+
+if [ -f "$OUTPUTFILE" ]; then
+ cp $OUTPUTFILE $OUTPUTFILE.old
+ if [ $? != 0 ]; then
@ -631,10 +735,10 @@ index 00000000..c00d2555
+fi
diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8
new file mode 100644
index 00000000..a14d831e
index 00000000..ea025f31
--- /dev/null
+++ b/multipath/mpathconf.8
@@ -0,0 +1,135 @@
@@ -0,0 +1,151 @@
+.TH MPATHCONF 8 "June 2010" "" "Linux Administrator's Manual"
+.SH NAME
+mpathconf - A tool for configuring device-mapper-multipath
@ -677,10 +781,10 @@ index 00000000..a14d831e
+.B user_friendly_names
+set and
+.B find_multipaths
+set to \fByes\fP. To disable these, use the
+set to \fBon\fP. To disable these, use the
+.B --user_friendly_names n
+and
+.B --find_multipaths n
+.B --find_multipaths off
+options
+.SH COMMANDS
+.TP
@ -714,7 +818,16 @@ 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 }
+.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 { \fBon\fP | \fByes\fP | \fBy\fP | \fBoff\fP | \fBno\fP | \fBn\fP | \fBstrict\fP | \fBgreedy\fP | \fBsmart\fP }
+If set to \fB<value>\fP, this adds the line
+.B find_multipaths <value>
+to the
@ -738,6 +851,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 --option \fB<option_name>:[<value>]\fP
+Sets the defaults section option \fB<option_name>\fP to \fB<value>\fP. If the
+option was not previously set in the defaults section, it is added. If it was
+set, its value is changed to \fB<value>\fP. If \fB<value>\fP is left blank,
+then the option is removed from the defaults section, if was set there. This
+command can be used along with any other command.
+.TP
+.B --outfile \fB<filename>\fP
+Write the resulting multipath configuration to \fB<filename>\fP instead of
+\fB/etc/multipath.conf\fP.

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

@ -14,16 +14,16 @@ multipathd.service
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/main.c | 54 +++++++++++++++++++++++++++++++++--
multipath/multipath.8 | 7 ++++-
multipathd/multipathd.service | 1 +
multipath/main.c | 54 ++++++++++++++++++++++++++++++--
multipath/multipath.8.in | 7 ++++-
multipathd/multipathd.service.in | 1 +
3 files changed, 59 insertions(+), 3 deletions(-)
diff --git a/multipath/main.c b/multipath/main.c
index 65ece830..748e7902 100644
index c21e3e0b..3f3ac9fb 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -122,7 +122,7 @@ usage (char * progname)
@@ -120,7 +120,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);
@ -32,7 +32,7 @@ index 65ece830..748e7902 100644
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)
@@ -134,6 +134,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"
@ -41,7 +41,7 @@ index 65ece830..748e7902 100644
" -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)
@@ -448,6 +450,50 @@ static void cleanup_vecs(void)
free_pathvec(vecs.pathvec, FREE_PATHS);
}
@ -92,16 +92,16 @@ index 65ece830..748e7902 100644
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[])
conf->retrigger_tries = 0;
conf->force_sync = 1;
atexit(cleanup_vecs);
@@ -861,7 +907,7 @@ main (int argc, char *argv[])
condlog(1, "failed to register cleanup handler for vecs: %m");
if (atexit(cleanup_bindings))
condlog(1, "failed to register cleanup handler for bindings: %m");
- 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 ) {
switch(arg) {
case 1: printf("optarg : %s\n",optarg);
break;
@@ -915,6 +961,10 @@ main (int argc, char *argv[])
case 'v':
if (!isdigit(optarg[0])) {
@@ -932,6 +978,10 @@ main (int argc, char *argv[])
case 'T':
cmd = CMD_DUMP_CONFIG;
break;
@ -112,11 +112,11 @@ index 65ece830..748e7902 100644
case 'h':
usage(argv[0]);
exit(RTVL_OK);
diff --git a/multipath/multipath.8 b/multipath/multipath.8
index 17df59f5..5ca75359 100644
--- a/multipath/multipath.8
+++ b/multipath/multipath.8
@@ -63,7 +63,7 @@ multipath \- Device mapper target autoconfig.
diff --git a/multipath/multipath.8.in b/multipath/multipath.8.in
index b88e9a4c..edd742aa 100644
--- a/multipath/multipath.8.in
+++ b/multipath/multipath.8.in
@@ -64,7 +64,7 @@ multipath \- Device mapper target autoconfig.
.B multipath
.RB [\| \-v\ \c
.IR level \|]
@ -125,7 +125,7 @@ index 17df59f5..5ca75359 100644
.
.LP
.B multipath
@@ -145,6 +145,11 @@ device mapper, path checkers ...).
@@ -146,6 +146,11 @@ device mapper, path checkers ...).
Add the WWID for the specified device to the WWIDs file.
.
.TP
@ -137,14 +137,14 @@ index 17df59f5..5ca75359 100644
.B \-w
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
--- a/multipathd/multipathd.service
+++ b/multipathd/multipathd.service
@@ -16,6 +16,7 @@ Type=notify
diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in
index 01ceff7d..e0c2011b 100644
--- a/multipathd/multipathd.service.in
+++ b/multipathd/multipathd.service.in
@@ -17,6 +17,7 @@ ConditionVirtualization=!container
[Service]
Type=notify
NotifyAccess=main
LimitCORE=infinity
ExecStartPre=-/sbin/modprobe -a scsi_dh_alua scsi_dh_emc scsi_dh_rdac dm-multipath
+ExecStartPre=-/sbin/multipath -A
ExecStart=/sbin/multipathd -d -s
ExecReload=/sbin/multipathd reconfigure

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

@ -6,13 +6,15 @@ Subject: [PATCH] RH: reset default find_mutipaths value to off
Upstream has changed to default find_multipaths to "strict". For now
Redhat will retain the previous default of "off".
Co-authored-by: Paul Donohue <git@PaulSD.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/defaults.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
multipath/multipath.conf.5.in | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index c27946c7..e0dd32ad 100644
index ed08c251..4b033ff9 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -23,7 +23,7 @@
@ -24,3 +26,16 @@ index c27946c7..e0dd32ad 100644
#define DEFAULT_FAST_IO_FAIL 5
#define DEFAULT_DEV_LOSS_TMO 600
#define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_ON
diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in
index 645e8f88..a7543939 100644
--- a/multipath/multipath.conf.5.in
+++ b/multipath/multipath.conf.5.in
@@ -1225,7 +1225,7 @@ as non-multipath and passed on to upper layers.
\fBNote:\fR this may cause delays during device detection if
there are single-path devices which aren\'t blacklisted.
.TP
-The default is: \fBstrict\fR
+The default is: \fBoff\fR
.RE
.
.

@ -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,
},
{

@ -13,7 +13,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/libmultipath/prioritizers/ana.c b/libmultipath/prioritizers/ana.c
index b5c7873d..e139360c 100644
index e9827dca..80a32aa3 100644
--- a/libmultipath/prioritizers/ana.c
+++ b/libmultipath/prioritizers/ana.c
@@ -24,6 +24,7 @@
@ -68,7 +68,7 @@ index b5c7873d..e139360c 100644
static int get_ana_info(struct path * pp)
{
int rc;
@@ -210,8 +234,11 @@ int getprio(struct path *pp, __attribute__((unused)) char *args,
@@ -209,8 +233,11 @@ int getprio(struct path *pp, __attribute__((unused)) char *args)
if (pp->fd < 0)
rc = -ANA_ERR_NO_INFORMATION;

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

@ -9,52 +9,46 @@ that.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/discovery.c | 18 ++----------------
libmultipath/discovery.c | 12 ++----------
tests/vpd.c | 6 ++++++
2 files changed, 8 insertions(+), 16 deletions(-)
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index f25fe9e3..6fb81c28 100644
index e2052422..3bcd94ce 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;
@@ -1221,13 +1221,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
good_len = 8;
break;
case 2:
- /* IEEE Extended: Prio 6 */
- naa_prio = 6;
- new_prio = 6;
- good_len = 8;
- break;
case 3:
- /* IEEE Locally assigned: Prio 1 */
- naa_prio = 1;
- new_prio = 1;
+ /* IEEE Extended or Locally assigned: Prio 6 */
+ naa_prio = 6;
+ new_prio = 6;
good_len = 8;
break;
default:
/* Default: no priority */
@@ -1160,17 +1157,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
vpd = d;
}
@@ -1245,10 +1241,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
break;
- case 0x8:
- /* SCSI Name: Prio 3 */
- if (memcmp(d + 4, "eui.", 4) &&
case 0x8:
/* SCSI Name: Prio 3 */
- invalid = (d[3] < 4 || (memcmp(d + 4, "eui.", 4) &&
- memcmp(d + 4, "naa.", 4) &&
- memcmp(d + 4, "iqn.", 4))
- break;
- if (prio < 3) {
- prio = 3;
- vpd = d;
- }
- break;
- memcmp(d + 4, "iqn.", 4)));
- new_prio = 3;
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
index e3212e61..cdb111bb 100644
--- a/tests/vpd.c
+++ b/tests/vpd.c
@@ -230,11 +230,13 @@ static const char * const str_prefix[] = {
@@ -232,11 +232,13 @@ static const char * const str_prefix[] = {
[STR_IQN] = "iqn.",
};
@ -68,7 +62,7 @@ index 8e730d37..7bf7990f 100644
/**
* create_scsi_string_desc() - create a SCSI name string descriptor.
@@ -659,6 +661,7 @@ make_test_vpd_naa(2, 18);
@@ -767,6 +769,7 @@ make_test_vpd_naa(2, 18);
make_test_vpd_naa(2, 17);
make_test_vpd_naa(2, 16);
@ -76,7 +70,7 @@ index 8e730d37..7bf7990f 100644
/* 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)
@@ -802,6 +805,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)
@ -84,7 +78,7 @@ index 8e730d37..7bf7990f 100644
static int test_vpd(void)
{
@@ -767,6 +771,7 @@ static int test_vpd(void)
@@ -910,6 +914,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),
@ -92,7 +86,7 @@ index 8e730d37..7bf7990f 100644
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)
@@ -934,6 +939,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),

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

@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 25 Mar 2022 18:12:06 -0500
Subject: [PATCH] RH: add scsi device handlers to modules-load.d
Make scsi_dh_alua scsi_dh_emc and scsi_dh_rdac get loaded in early boot.
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 94e0ec85..49514b06 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -16,7 +16,7 @@ READLINE :=
# List of scsi device handler modules to load on boot, e.g.
# SCSI_DH_MODULES_PRELOAD := scsi_dh_alua scsi_dh_rdac
-SCSI_DH_MODULES_PRELOAD :=
+SCSI_DH_MODULES_PRELOAD := scsi_dh_alua scsi_dh_emc scsi_dh_rdac
EXTRAVERSION := $(shell rev=$$(git rev-parse --short=7 HEAD 2>/dev/null); echo $${rev:+-g$$rev})

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

@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 15 Nov 2022 18:03:33 -0600
Subject: [PATCH] RH: compile with libreadline support
Since the license issue has been resolved, and there are problems with
the command completion with libedit, use libreadline.
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 49514b06..a3ed9f28 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -12,7 +12,7 @@
# Readline library to use, libedit, libreadline, or empty
# Caution: Using libreadline may make the multipathd binary undistributable,
# see https://github.com/opensvc/multipath-tools/issues/36
-READLINE :=
+READLINE := libreadline
# List of scsi device handler modules to load on boot, e.g.
# SCSI_DH_MODULES_PRELOAD := scsi_dh_alua scsi_dh_rdac

@ -1,63 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 13 Apr 2017 07:22:23 -0500
Subject: [PATCH] RH: fixup udev rules for redhat
The multipath rules need to run after scsi_id is run. This means moving
them after 60-persistent-storage.rules for redhat. Redhat also uses a
different naming scheme for partitions than SuSE.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile.inc | 2 +-
kpartx/kpartx.rules | 2 +-
multipath/Makefile | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index d0ec9b44..2a75dc9c 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -55,7 +55,7 @@ endif
prefix =
exec_prefix = $(prefix)
usr_prefix = $(prefix)
-bindir = $(exec_prefix)/sbin
+bindir = $(exec_prefix)/usr/sbin
libudevdir = $(prefix)/$(SYSTEMDPATH)/udev
udevrulesdir = $(libudevdir)/rules.d
multipathdir = $(TOPDIR)/libmultipath
diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
index d7527d7d..0e0d70d5 100644
--- a/kpartx/kpartx.rules
+++ b/kpartx/kpartx.rules
@@ -36,6 +36,6 @@ LABEL="mpath_kpartx_end"
GOTO="kpartx_end"
LABEL="run_kpartx"
-RUN+="/sbin/kpartx -un -p -part /dev/$name"
+RUN+="/sbin/kpartx -un /dev/$name"
LABEL="kpartx_end"
diff --git a/multipath/Makefile b/multipath/Makefile
index 0828a8f7..b9bbb3cf 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -24,7 +24,7 @@ install:
$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
- $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
+ $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man8dir)
$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(man8dir)
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir)
@@ -33,7 +33,7 @@ install:
uninstall:
$(RM) $(DESTDIR)$(bindir)/$(EXEC)
$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
- $(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
+ $(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
$(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz
$(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz

@ -14,25 +14,25 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
create mode 100755 multipath/mpathcleanup
diff --git a/multipath/Makefile b/multipath/Makefile
index f3d98012..1fc04c8d 100644
index 3dc241cc..47e82234 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
@@ -25,6 +25,7 @@ install:
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
$(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
$(Q)$(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/
+ $(Q)$(INSTALL_PROGRAM) -m 755 mpathcleanup $(DESTDIR)$(bindir)/
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 99-z-dm-mpath-late.rules $(DESTDIR)$(udevrulesdir)
@@ -49,6 +50,7 @@ endif
uninstall:
$(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC)
$(Q)$(RM) $(DESTDIR)$(bindir)/mpathconf
+ $(Q)$(RM) $(DESTDIR)$(bindir)/mpathcleanup
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/99-z-dm-mpath-late.rules
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf
diff --git a/multipath/mpathcleanup b/multipath/mpathcleanup
new file mode 100755
index 00000000..6fd921e4

@ -0,0 +1,77 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 7 Aug 2024 18:59:10 -0400
Subject: [PATCH] libmultipath: fix ontap prioritizer snprintf limits
The ontap prioritizer functions dump_cdb() and process_sg_error() both
incorrectly set the snprintf() limits larger than the available space.
Instead of multiplying the number of elements to print by the size of an
element to calculate the limit, they multiplied the number of elements
to print by the maximum number of elements that the buffer could hold.
Fix this by making these functions use strbufs instead.
mwilck: removed log message in print_strbuf() failure case.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/prioritizers/ontap.c | 24 +++++++++++-------------
1 file changed, 11 insertions(+), 13 deletions(-)
diff --git a/libmultipath/prioritizers/ontap.c b/libmultipath/prioritizers/ontap.c
index 117886ea..90eaf274 100644
--- a/libmultipath/prioritizers/ontap.c
+++ b/libmultipath/prioritizers/ontap.c
@@ -23,6 +23,7 @@
#include "prio.h"
#include "structs.h"
#include "unaligned.h"
+#include "strbuf.h"
#define INQUIRY_CMD 0x12
#define INQUIRY_CMDLEN 6
@@ -35,32 +36,29 @@
static void dump_cdb(unsigned char *cdb, int size)
{
int i;
- char buf[10*5+1];
- char * p = &buf[0];
+ STRBUF_ON_STACK(buf);
- condlog(0, "- SCSI CDB: ");
- for (i=0; i<size; i++) {
- p += snprintf(p, 10*(size-i), "0x%02x ", cdb[i]);
+ for (i = 0; i < size; i++) {
+ if (print_strbuf(&buf, "0x%02x ", cdb[i]) < 0)
+ return;
}
- condlog(0, "%s", buf);
+ condlog(0, "- SCSI CDB: %s", get_strbuf_str(&buf));
}
static void process_sg_error(struct sg_io_hdr *io_hdr)
{
int i;
- char buf[128*5+1];
- char * p = &buf[0];
+ STRBUF_ON_STACK(buf);
condlog(0, "- masked_status=0x%02x, host_status=0x%02x, "
"driver_status=0x%02x", io_hdr->masked_status,
io_hdr->host_status, io_hdr->driver_status);
if (io_hdr->sb_len_wr > 0) {
- condlog(0, "- SCSI sense data: ");
- for (i=0; i<io_hdr->sb_len_wr; i++) {
- p += snprintf(p, 128*(io_hdr->sb_len_wr-i), "0x%02x ",
- io_hdr->sbp[i]);
+ for (i = 0; i < io_hdr->sb_len_wr; i++) {
+ if (print_strbuf(&buf, "0x%02x ", io_hdr->sbp[i]) < 0)
+ return;
}
- condlog(0, "%s", buf);
+ condlog(0, "- SCSI sense data: %s", get_strbuf_str(&buf));
}
}

@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 16 Sep 2024 19:29:13 -0400
Subject: [PATCH] multipathd: checker port_state before setting it.
If the rport port_state is already Marginal, trying to set it to
Marginal causes an error like the following:
multipathd[365376]: /sys/devices/pci0000:c0/0000:c0:01.1/0000:c4:00.0/host0/rport-0:0-5/fc_remote_ports/rport-0:0-5: failed to set port_state to marginal: Invalid argument
To avoid causing this confusing error message, check if the port_state
is already marginal before trying to set it.
Cc: Muneendra Kumar <muneendra.kumar@broadcom.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/fpin_handlers.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/multipathd/fpin_handlers.c b/multipathd/fpin_handlers.c
index be087ca0..6b56f9b7 100644
--- a/multipathd/fpin_handlers.c
+++ b/multipathd/fpin_handlers.c
@@ -169,9 +169,14 @@ fpin_els_add_li_frame(struct fc_nl_event *fc_event)
/*Sets the rport port_state to marginal*/
static void fpin_set_rport_marginal(struct udev_device *rport_dev)
{
+ char old_value[20]; /* match kernel show_fc_rport_port_state() size */
static const char marginal[] = "Marginal";
ssize_t ret;
+ ret = sysfs_attr_get_value(rport_dev, "port_state",
+ old_value, sizeof(old_value));
+ if (ret == sizeof(marginal) - 1 && strcmp(old_value, marginal) == 0)
+ return;
ret = sysfs_attr_set_value(rport_dev, "port_state",
marginal, sizeof(marginal) - 1);
if (ret != sizeof(marginal) - 1)

@ -1,69 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 23 Sep 2021 14:16:51 -0500
Subject: [PATCH] libmultipath: add section name to invalid keyword output
If users forget the closing brace for a section in multipath.conf,
multipath has no way to detect that. When it sees the keyword at the
start of the next section, it will complain that there is an invalid
keyword, because that keyword doesn't belong in previous section (which
was never ended with a closing brace). This can confuse users. To make
this easier to understand, when multipath prints an invalid keyword
message, it now also prints the current section name, which can give
users a hint that they didn't end the previous section.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/parser.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
index 8ca91bf2..611054f7 100644
--- a/libmultipath/parser.c
+++ b/libmultipath/parser.c
@@ -504,7 +504,7 @@ validate_config_strvec(vector strvec, const char *file)
static int
process_stream(struct config *conf, FILE *stream, vector keywords,
- const char *file)
+ const char *section, const char *file)
{
int i;
int r = 0, t;
@@ -568,16 +568,22 @@ process_stream(struct config *conf, FILE *stream, vector keywords,
if (keyword->sub) {
kw_level++;
r += process_stream(conf, stream,
- keyword->sub, file);
+ keyword->sub,
+ keyword->string,
+ file);
kw_level--;
}
break;
}
}
- if (i >= VECTOR_SIZE(keywords))
- condlog(1, "%s line %d, invalid keyword: %s",
- file, line_nr, str);
-
+ if (i >= VECTOR_SIZE(keywords)) {
+ if (section)
+ condlog(1, "%s line %d, invalid keyword in the %s section: %s",
+ file, line_nr, section, str);
+ else
+ condlog(1, "%s line %d, invalid keyword: %s",
+ file, line_nr, str);
+ }
free_strvec(strvec);
}
if (kw_level == 1)
@@ -608,7 +614,7 @@ process_file(struct config *conf, const char *file)
/* Stream handling */
line_nr = 0;
- r = process_stream(conf, stream, conf->keywords, file);
+ r = process_stream(conf, stream, conf->keywords, NULL, file);
fclose(stream);
//free_keywords(keywords);

@ -1,84 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 23 Sep 2021 21:39:36 -0500
Subject: [PATCH] libmultipath: use typedef for keyword handler function
Don't keep writing out the function type.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/parser.c | 6 +++---
libmultipath/parser.h | 15 ++++++---------
2 files changed, 9 insertions(+), 12 deletions(-)
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
index 611054f7..ebe1cbd9 100644
--- a/libmultipath/parser.c
+++ b/libmultipath/parser.c
@@ -33,7 +33,7 @@ static int line_nr;
int
keyword_alloc(vector keywords, char *string,
- int (*handler) (struct config *, vector),
+ handler_fn *handler,
print_fn *print,
int unique)
{
@@ -72,7 +72,7 @@ install_sublevel_end(void)
int
_install_keyword(vector keywords, char *string,
- int (*handler) (struct config *, vector),
+ handler_fn *handler,
print_fn *print,
int unique)
{
@@ -558,7 +558,7 @@ process_stream(struct config *conf, FILE *stream, vector keywords,
goto out;
}
if (keyword->handler) {
- t = (*keyword->handler) (conf, strvec);
+ t = keyword->handler(conf, strvec);
r += t;
if (t)
condlog(1, "multipath.conf +%d, parsing failed: %s",
diff --git a/libmultipath/parser.h b/libmultipath/parser.h
index b43d46f8..3452bde1 100644
--- a/libmultipath/parser.h
+++ b/libmultipath/parser.h
@@ -43,10 +43,11 @@ struct strbuf;
/* keyword definition */
typedef int print_fn(struct config *, struct strbuf *, const void *);
+typedef int handler_fn(struct config *, vector);
struct keyword {
char *string;
- int (*handler) (struct config *, vector);
+ handler_fn *handler;
print_fn *print;
vector sub;
int unique;
@@ -62,18 +63,14 @@ struct keyword {
for (i = 0; i < (k)->sub->allocated && ((p) = (k)->sub->slot[i]); i++)
/* Prototypes */
-extern int keyword_alloc(vector keywords, char *string,
- int (*handler) (struct config *, vector),
- print_fn *print,
- int unique);
+extern int keyword_alloc(vector keywords, char *string, handler_fn *handler,
+ print_fn *print, int unique);
#define install_keyword_root(str, h) keyword_alloc(keywords, str, h, NULL, 1)
extern void install_sublevel(void);
extern void install_sublevel_end(void);
-extern int _install_keyword(vector keywords, char *string,
- int (*handler) (struct config *, vector),
- print_fn *print,
- int unique);
+extern int _install_keyword(vector keywords, char *string, handler_fn *handler,
+ print_fn *print, int unique);
#define install_keyword(str, vec, pri) _install_keyword(keywords, str, vec, pri, 1)
#define install_keyword_multi(str, vec, pri) _install_keyword(keywords, str, vec, pri, 0)
extern void dump_keywords(vector keydump, int level);

@ -1,27 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 24 Sep 2021 13:13:31 -0500
Subject: [PATCH] libmultipath: print the correct file when parsing fails
Don't assume that parsing failed on multipath.conf
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/parser.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
index ebe1cbd9..d5595fb0 100644
--- a/libmultipath/parser.c
+++ b/libmultipath/parser.c
@@ -561,8 +561,8 @@ process_stream(struct config *conf, FILE *stream, vector keywords,
t = keyword->handler(conf, strvec);
r += t;
if (t)
- condlog(1, "multipath.conf +%d, parsing failed: %s",
- line_nr, buf);
+ condlog(1, "%s line %d, parsing failed: %s",
+ file, line_nr, buf);
}
if (keyword->sub) {

@ -1,527 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 24 Sep 2021 17:59:12 -0500
Subject: [PATCH] libmultipath: pass file and line number to keyword handlers
This will make it possible for the keyword handlers to print more useful
warning messages. It will be used by future patches.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/dict.c | 143 +++++++++++++++++++++++++-----------------
libmultipath/parser.c | 3 +-
libmultipath/parser.h | 2 +-
3 files changed, 90 insertions(+), 58 deletions(-)
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index 7a727389..eb2c44c0 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -29,7 +29,7 @@
#include "strbuf.h"
static int
-set_int(vector strvec, void *ptr)
+set_int(vector strvec, void *ptr, const char *file, int line_nr)
{
int *int_ptr = (int *)ptr;
char *buff, *eptr;
@@ -58,7 +58,7 @@ set_int(vector strvec, void *ptr)
}
static int
-set_uint(vector strvec, void *ptr)
+set_uint(vector strvec, void *ptr, const char *file, int line_nr)
{
unsigned int *uint_ptr = (unsigned int *)ptr;
char *buff, *eptr, *p;
@@ -90,7 +90,7 @@ set_uint(vector strvec, void *ptr)
}
static int
-set_str(vector strvec, void *ptr)
+set_str(vector strvec, void *ptr, const char *file, int line_nr)
{
char **str_ptr = (char **)ptr;
@@ -105,7 +105,7 @@ set_str(vector strvec, void *ptr)
}
static int
-set_yes_no(vector strvec, void *ptr)
+set_yes_no(vector strvec, void *ptr, const char *file, int line_nr)
{
char * buff;
int *int_ptr = (int *)ptr;
@@ -124,7 +124,7 @@ set_yes_no(vector strvec, void *ptr)
}
static int
-set_yes_no_undef(vector strvec, void *ptr)
+set_yes_no_undef(vector strvec, void *ptr, const char *file, int line_nr)
{
char * buff;
int *int_ptr = (int *)ptr;
@@ -187,9 +187,10 @@ static int print_yes_no_undef(struct strbuf *buff, long v)
#define declare_def_handler(option, function) \
static int \
-def_ ## option ## _handler (struct config *conf, vector strvec) \
+def_ ## option ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
{ \
- return function (strvec, &conf->option); \
+ return function (strvec, &conf->option, file, line_nr); \
}
#define declare_def_snprint(option, function) \
@@ -224,12 +225,13 @@ snprint_def_ ## option (struct config *conf, struct strbuf *buff, \
#define declare_hw_handler(option, function) \
static int \
-hw_ ## option ## _handler (struct config *conf, vector strvec) \
+hw_ ## option ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
{ \
struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); \
if (!hwe) \
return 1; \
- return function (strvec, &hwe->option); \
+ return function (strvec, &hwe->option, file, line_nr); \
}
#define declare_hw_snprint(option, function) \
@@ -243,11 +245,12 @@ snprint_hw_ ## option (struct config *conf, struct strbuf *buff, \
#define declare_ovr_handler(option, function) \
static int \
-ovr_ ## option ## _handler (struct config *conf, vector strvec) \
+ovr_ ## option ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
{ \
if (!conf->overrides) \
return 1; \
- return function (strvec, &conf->overrides->option); \
+ return function (strvec, &conf->overrides->option, file, line_nr); \
}
#define declare_ovr_snprint(option, function) \
@@ -260,12 +263,13 @@ snprint_ovr_ ## option (struct config *conf, struct strbuf *buff, \
#define declare_mp_handler(option, function) \
static int \
-mp_ ## option ## _handler (struct config *conf, vector strvec) \
+mp_ ## option ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
{ \
struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable); \
if (!mpe) \
return 1; \
- return function (strvec, &mpe->option); \
+ return function (strvec, &mpe->option, file, line_nr); \
}
#define declare_mp_snprint(option, function) \
@@ -277,9 +281,10 @@ snprint_mp_ ## option (struct config *conf, struct strbuf *buff, \
return function(buff, mpe->option); \
}
-static int checkint_handler(struct config *conf, vector strvec)
+static int checkint_handler(struct config *conf, vector strvec,
+ const char *file, int line_nr)
{
- int rc = set_uint(strvec, &conf->checkint);
+ int rc = set_uint(strvec, &conf->checkint, file, line_nr);
if (rc)
return rc;
@@ -302,9 +307,10 @@ declare_def_snprint(reassign_maps, print_yes_no)
declare_def_handler(multipath_dir, set_str)
declare_def_snprint(multipath_dir, print_str)
-static int def_partition_delim_handler(struct config *conf, vector strvec)
+static int def_partition_delim_handler(struct config *conf, vector strvec,
+ const char *file, int line_nr)
{
- int rc = set_str(strvec, &conf->partition_delim);
+ int rc = set_str(strvec, &conf->partition_delim, file, line_nr);
if (rc != 0)
return rc;
@@ -334,13 +340,13 @@ static const char * const find_multipaths_optvals[] = {
};
static int
-def_find_multipaths_handler(struct config *conf, vector strvec)
+def_find_multipaths_handler(struct config *conf, vector strvec,
+ const char *file, int line_nr)
{
char *buff;
int i;
- if (set_yes_no_undef(strvec, &conf->find_multipaths) == 0 &&
- conf->find_multipaths != FIND_MULTIPATHS_UNDEF)
+ if (set_yes_no_undef(strvec, &conf->find_multipaths, file, line_nr) == 0 && conf->find_multipaths != FIND_MULTIPATHS_UNDEF)
return 0;
buff = set_value(strvec);
@@ -396,7 +402,8 @@ static int snprint_uid_attrs(struct config *conf, struct strbuf *buff,
return total;
}
-static int uid_attrs_handler(struct config *conf, vector strvec)
+static int uid_attrs_handler(struct config *conf, vector strvec,
+ const char *file, int line_nr)
{
char *val;
@@ -597,7 +604,8 @@ declare_hw_handler(skip_kpartx, set_yes_no_undef)
declare_hw_snprint(skip_kpartx, print_yes_no_undef)
declare_mp_handler(skip_kpartx, set_yes_no_undef)
declare_mp_snprint(skip_kpartx, print_yes_no_undef)
-static int def_disable_changed_wwids_handler(struct config *conf, vector strvec)
+static int def_disable_changed_wwids_handler(struct config *conf, vector strvec,
+ const char *file, int line_nr)
{
return 0;
}
@@ -629,20 +637,23 @@ declare_def_snprint_defstr(enable_foreign, print_str,
DEFAULT_ENABLE_FOREIGN)
static int
-def_config_dir_handler(struct config *conf, vector strvec)
+def_config_dir_handler(struct config *conf, vector strvec, const char *file,
+ int line_nr)
{
/* this is only valid in the main config file */
if (conf->processed_main_config)
return 0;
- return set_str(strvec, &conf->config_dir);
+ return set_str(strvec, &conf->config_dir, file, line_nr);
}
declare_def_snprint(config_dir, print_str)
#define declare_def_attr_handler(option, function) \
static int \
-def_ ## option ## _handler (struct config *conf, vector strvec) \
+def_ ## option ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
{ \
- return function (strvec, &conf->option, &conf->attribute_flags);\
+ return function (strvec, &conf->option, &conf->attribute_flags, \
+ file, line_nr); \
}
#define declare_def_attr_snprint(option, function) \
@@ -655,12 +666,14 @@ snprint_def_ ## option (struct config *conf, struct strbuf *buff, \
#define declare_mp_attr_handler(option, function) \
static int \
-mp_ ## option ## _handler (struct config *conf, vector strvec) \
+mp_ ## option ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
{ \
struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable); \
if (!mpe) \
return 1; \
- return function (strvec, &mpe->option, &mpe->attribute_flags); \
+ return function (strvec, &mpe->option, &mpe->attribute_flags, \
+ file, line_nr); \
}
#define declare_mp_attr_snprint(option, function) \
@@ -673,7 +686,7 @@ snprint_mp_ ## option (struct config *conf, struct strbuf *buff, \
}
static int
-set_mode(vector strvec, void *ptr, int *flags)
+set_mode(vector strvec, void *ptr, int *flags, const char *file, int line_nr)
{
mode_t mode;
mode_t *mode_ptr = (mode_t *)ptr;
@@ -694,7 +707,7 @@ set_mode(vector strvec, void *ptr, int *flags)
}
static int
-set_uid(vector strvec, void *ptr, int *flags)
+set_uid(vector strvec, void *ptr, int *flags, const char *file, int line_nr)
{
uid_t uid;
uid_t *uid_ptr = (uid_t *)ptr;
@@ -719,7 +732,7 @@ set_uid(vector strvec, void *ptr, int *flags)
}
static int
-set_gid(vector strvec, void *ptr, int *flags)
+set_gid(vector strvec, void *ptr, int *flags, const char *file, int line_nr)
{
gid_t gid;
gid_t *gid_ptr = (gid_t *)ptr;
@@ -786,7 +799,7 @@ declare_mp_attr_handler(gid, set_gid)
declare_mp_attr_snprint(gid, print_gid)
static int
-set_undef_off_zero(vector strvec, void *ptr)
+set_undef_off_zero(vector strvec, void *ptr, const char *file, int line_nr)
{
char * buff;
int *int_ptr = (int *)ptr;
@@ -827,7 +840,7 @@ declare_hw_handler(fast_io_fail, set_undef_off_zero)
declare_hw_snprint(fast_io_fail, print_undef_off_zero)
static int
-set_dev_loss(vector strvec, void *ptr)
+set_dev_loss(vector strvec, void *ptr, const char *file, int line_nr)
{
char * buff;
unsigned int *uint_ptr = (unsigned int *)ptr;
@@ -870,7 +883,7 @@ declare_hw_handler(eh_deadline, set_undef_off_zero)
declare_hw_snprint(eh_deadline, print_undef_off_zero)
static int
-set_pgpolicy(vector strvec, void *ptr)
+set_pgpolicy(vector strvec, void *ptr, const char *file, int line_nr)
{
char * buff;
int *int_ptr = (int *)ptr;
@@ -936,7 +949,8 @@ get_sys_max_fds(int *max_fds)
static int
-max_fds_handler(struct config *conf, vector strvec)
+max_fds_handler(struct config *conf, vector strvec, const char *file,
+ int line_nr)
{
char * buff;
int r = 0, max_fds;
@@ -981,7 +995,7 @@ snprint_max_fds (struct config *conf, struct strbuf *buff, const void *data)
}
static int
-set_rr_weight(vector strvec, void *ptr)
+set_rr_weight(vector strvec, void *ptr, const char *file, int line_nr)
{
int *int_ptr = (int *)ptr;
char * buff;
@@ -1025,7 +1039,7 @@ declare_mp_handler(rr_weight, set_rr_weight)
declare_mp_snprint(rr_weight, print_rr_weight)
static int
-set_pgfailback(vector strvec, void *ptr)
+set_pgfailback(vector strvec, void *ptr, const char *file, int line_nr)
{
int *int_ptr = (int *)ptr;
char * buff;
@@ -1075,7 +1089,7 @@ declare_mp_handler(pgfailback, set_pgfailback)
declare_mp_snprint(pgfailback, print_pgfailback)
static int
-no_path_retry_helper(vector strvec, void *ptr)
+no_path_retry_helper(vector strvec, void *ptr, const char *file, int line_nr)
{
int *int_ptr = (int *)ptr;
char * buff;
@@ -1120,7 +1134,8 @@ declare_mp_handler(no_path_retry, no_path_retry_helper)
declare_mp_snprint(no_path_retry, print_no_path_retry)
static int
-def_log_checker_err_handler(struct config *conf, vector strvec)
+def_log_checker_err_handler(struct config *conf, vector strvec,
+ const char *file, int line_nr)
{
char * buff;
@@ -1193,7 +1208,8 @@ print_reservation_key(struct strbuf *buff,
}
static int
-def_reservation_key_handler(struct config *conf, vector strvec)
+def_reservation_key_handler(struct config *conf, vector strvec,
+ const char *file, int line_nr)
{
return set_reservation_key(strvec, &conf->reservation_key,
&conf->sa_flags,
@@ -1209,7 +1225,8 @@ snprint_def_reservation_key (struct config *conf, struct strbuf *buff,
}
static int
-mp_reservation_key_handler(struct config *conf, vector strvec)
+mp_reservation_key_handler(struct config *conf, vector strvec, const char *file,
+ int line_nr)
{
struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable);
if (!mpe)
@@ -1229,7 +1246,7 @@ snprint_mp_reservation_key (struct config *conf, struct strbuf *buff,
}
static int
-set_off_int_undef(vector strvec, void *ptr)
+set_off_int_undef(vector strvec, void *ptr, const char *file, int line_nr)
{
int *int_ptr = (int *)ptr;
char * buff;
@@ -1370,7 +1387,8 @@ declare_hw_snprint(recheck_wwid, print_yes_no_undef)
static int
-def_uxsock_timeout_handler(struct config *conf, vector strvec)
+def_uxsock_timeout_handler(struct config *conf, vector strvec, const char *file,
+ int line_nr)
{
unsigned int uxsock_timeout;
char *buff;
@@ -1390,7 +1408,8 @@ def_uxsock_timeout_handler(struct config *conf, vector strvec)
}
static int
-hw_vpd_vendor_handler(struct config *conf, vector strvec)
+hw_vpd_vendor_handler(struct config *conf, vector strvec, const char *file,
+ int line_nr)
{
int i;
char *buff;
@@ -1430,7 +1449,8 @@ snprint_hw_vpd_vendor(struct config *conf, struct strbuf *buff,
* blacklist block handlers
*/
static int
-blacklist_handler(struct config *conf, vector strvec)
+blacklist_handler(struct config *conf, vector strvec, const char*file,
+ int line_nr)
{
if (!conf->blist_devnode)
conf->blist_devnode = vector_alloc();
@@ -1452,7 +1472,8 @@ blacklist_handler(struct config *conf, vector strvec)
}
static int
-blacklist_exceptions_handler(struct config *conf, vector strvec)
+blacklist_exceptions_handler(struct config *conf, vector strvec,
+ const char *file, int line_nr)
{
if (!conf->elist_devnode)
conf->elist_devnode = vector_alloc();
@@ -1475,7 +1496,8 @@ blacklist_exceptions_handler(struct config *conf, vector strvec)
#define declare_ble_handler(option) \
static int \
-ble_ ## option ## _handler (struct config *conf, vector strvec) \
+ble_ ## option ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
{ \
char *buff; \
int rc; \
@@ -1494,7 +1516,8 @@ ble_ ## option ## _handler (struct config *conf, vector strvec) \
#define declare_ble_device_handler(name, option, vend, prod) \
static int \
-ble_ ## option ## _ ## name ## _handler (struct config *conf, vector strvec) \
+ble_ ## option ## _ ## name ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
{ \
char * buff; \
int rc; \
@@ -1536,13 +1559,15 @@ snprint_ble_simple (struct config *conf, struct strbuf *buff, const void *data)
}
static int
-ble_device_handler(struct config *conf, vector strvec)
+ble_device_handler(struct config *conf, vector strvec, const char *file,
+ int line_nr)
{
return alloc_ble_device(conf->blist_device);
}
static int
-ble_except_device_handler(struct config *conf, vector strvec)
+ble_except_device_handler(struct config *conf, vector strvec, const char *file,
+ int line_nr)
{
return alloc_ble_device(conf->elist_device);
}
@@ -1574,7 +1599,8 @@ static int snprint_bled_product(struct config *conf, struct strbuf *buff,
* devices block handlers
*/
static int
-devices_handler(struct config *conf, vector strvec)
+devices_handler(struct config *conf, vector strvec, const char *file,
+ int line_nr)
{
if (!conf->hwtable)
conf->hwtable = vector_alloc();
@@ -1586,7 +1612,8 @@ devices_handler(struct config *conf, vector strvec)
}
static int
-device_handler(struct config *conf, vector strvec)
+device_handler(struct config *conf, vector strvec, const char *file,
+ int line_nr)
{
struct hwentry * hwe;
@@ -1623,7 +1650,8 @@ declare_hw_snprint(hwhandler, print_str)
* overrides handlers
*/
static int
-overrides_handler(struct config *conf, vector strvec)
+overrides_handler(struct config *conf, vector strvec, const char *file,
+ int line_nr)
{
if (!conf->overrides)
conf->overrides = alloc_hwe();
@@ -1640,7 +1668,8 @@ overrides_handler(struct config *conf, vector strvec)
* multipaths block handlers
*/
static int
-multipaths_handler(struct config *conf, vector strvec)
+multipaths_handler(struct config *conf, vector strvec, const char *file,
+ int line_nr)
{
if (!conf->mptable)
conf->mptable = vector_alloc();
@@ -1652,7 +1681,8 @@ multipaths_handler(struct config *conf, vector strvec)
}
static int
-multipath_handler(struct config *conf, vector strvec)
+multipath_handler(struct config *conf, vector strvec, const char *file,
+ int line_nr)
{
struct mpentry * mpe;
@@ -1681,7 +1711,8 @@ declare_mp_snprint(alias, print_str)
*/
static int
-deprecated_handler(struct config *conf, vector strvec)
+deprecated_handler(struct config *conf, vector strvec, const char *file,
+ int line_nr)
{
char * buff;
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
index d5595fb0..68262d0e 100644
--- a/libmultipath/parser.c
+++ b/libmultipath/parser.c
@@ -558,7 +558,8 @@ process_stream(struct config *conf, FILE *stream, vector keywords,
goto out;
}
if (keyword->handler) {
- t = keyword->handler(conf, strvec);
+ t = keyword->handler(conf, strvec, file,
+ line_nr);
r += t;
if (t)
condlog(1, "%s line %d, parsing failed: %s",
diff --git a/libmultipath/parser.h b/libmultipath/parser.h
index 3452bde1..11ea2278 100644
--- a/libmultipath/parser.h
+++ b/libmultipath/parser.h
@@ -43,7 +43,7 @@ struct strbuf;
/* keyword definition */
typedef int print_fn(struct config *, struct strbuf *, const void *);
-typedef int handler_fn(struct config *, vector);
+typedef int handler_fn(struct config *, vector, const char *file, int line_nr);
struct keyword {
char *string;

@ -1,250 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 28 Sep 2021 15:59:19 -0500
Subject: [PATCH] libmultipath: make set_int take a range for valid values
If a value outside of the valid range is passed to set_int, it caps the
value at appropriate limit, and issues a warning.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/dict.c | 121 +++++++++++++++++++++++++++-----------------
1 file changed, 75 insertions(+), 46 deletions(-)
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index eb2c44c0..57b6a7b6 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -29,7 +29,8 @@
#include "strbuf.h"
static int
-set_int(vector strvec, void *ptr, const char *file, int line_nr)
+set_int(vector strvec, void *ptr, int min, int max, const char *file,
+ int line_nr)
{
int *int_ptr = (int *)ptr;
char *buff, *eptr;
@@ -44,11 +45,17 @@ set_int(vector strvec, void *ptr, const char *file, int line_nr)
if (eptr > buff)
while (isspace(*eptr))
eptr++;
- if (*buff == '\0' || *eptr != '\0' || res > INT_MAX || res < INT_MIN) {
- condlog(1, "%s: invalid value for %s: \"%s\"",
- __func__, (char*)VECTOR_SLOT(strvec, 0), buff);
+ if (*buff == '\0' || *eptr != '\0') {
+ condlog(1, "%s line %d, invalid value for %s: \"%s\"",
+ file, line_nr, (char*)VECTOR_SLOT(strvec, 0), buff);
rc = 1;
} else {
+ if (res > max || res < min) {
+ res = (res > max) ? max : min;
+ condlog(1, "%s line %d, value for %s too %s, capping at %ld",
+ file, line_nr, (char*)VECTOR_SLOT(strvec, 0),
+ (res == max)? "large" : "small", res);
+ }
rc = 0;
*int_ptr = res;
}
@@ -77,8 +84,8 @@ set_uint(vector strvec, void *ptr, const char *file, int line_nr)
while (isspace(*eptr))
eptr++;
if (*buff == '\0' || *eptr != '\0' || !isdigit(*p) || res > UINT_MAX) {
- condlog(1, "%s: invalid value for %s: \"%s\"",
- __func__, (char*)VECTOR_SLOT(strvec, 0), buff);
+ condlog(1, "%s line %d, invalid value for %s: \"%s\"",
+ file, line_nr, (char*)VECTOR_SLOT(strvec, 0), buff);
rc = 1;
} else {
rc = 0;
@@ -193,6 +200,14 @@ def_ ## option ## _handler (struct config *conf, vector strvec, \
return function (strvec, &conf->option, file, line_nr); \
}
+#define declare_def_range_handler(option, minval, maxval) \
+static int \
+def_ ## option ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
+{ \
+ return set_int(strvec, &conf->option, minval, maxval, file, line_nr); \
+}
+
#define declare_def_snprint(option, function) \
static int \
snprint_def_ ## option (struct config *conf, struct strbuf *buff, \
@@ -234,6 +249,18 @@ hw_ ## option ## _handler (struct config *conf, vector strvec, \
return function (strvec, &hwe->option, file, line_nr); \
}
+#define declare_hw_range_handler(option, minval, maxval) \
+static int \
+hw_ ## option ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
+{ \
+ struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); \
+ if (!hwe) \
+ return 1; \
+ return set_int(strvec, &hwe->option, minval, maxval, file, line_nr); \
+}
+
+
#define declare_hw_snprint(option, function) \
static int \
snprint_hw_ ## option (struct config *conf, struct strbuf *buff, \
@@ -253,6 +280,17 @@ ovr_ ## option ## _handler (struct config *conf, vector strvec, \
return function (strvec, &conf->overrides->option, file, line_nr); \
}
+#define declare_ovr_range_handler(option, minval, maxval) \
+static int \
+ovr_ ## option ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
+{ \
+ if (!conf->overrides) \
+ return 1; \
+ return set_int(strvec, &conf->overrides->option, minval, maxval, \
+ file, line_nr); \
+}
+
#define declare_ovr_snprint(option, function) \
static int \
snprint_ovr_ ## option (struct config *conf, struct strbuf *buff, \
@@ -272,6 +310,17 @@ mp_ ## option ## _handler (struct config *conf, vector strvec, \
return function (strvec, &mpe->option, file, line_nr); \
}
+#define declare_mp_range_handler(option, minval, maxval) \
+static int \
+mp_ ## option ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
+{ \
+ struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable); \
+ if (!mpe) \
+ return 1; \
+ return set_int(strvec, &mpe->option, minval, maxval, file, line_nr); \
+}
+
#define declare_mp_snprint(option, function) \
static int \
snprint_mp_ ## option (struct config *conf, struct strbuf *buff, \
@@ -298,7 +347,7 @@ declare_def_snprint(checkint, print_int)
declare_def_handler(max_checkint, set_uint)
declare_def_snprint(max_checkint, print_int)
-declare_def_handler(verbosity, set_int)
+declare_def_range_handler(verbosity, 0, MAX_VERBOSITY)
declare_def_snprint(verbosity, print_int)
declare_def_handler(reassign_maps, set_yes_no)
@@ -473,22 +522,22 @@ declare_ovr_snprint(checker_name, print_str)
declare_hw_handler(checker_name, set_str)
declare_hw_snprint(checker_name, print_str)
-declare_def_handler(minio, set_int)
+declare_def_range_handler(minio, 0, INT_MAX)
declare_def_snprint_defint(minio, print_int, DEFAULT_MINIO)
-declare_ovr_handler(minio, set_int)
+declare_ovr_range_handler(minio, 0, INT_MAX)
declare_ovr_snprint(minio, print_nonzero)
-declare_hw_handler(minio, set_int)
+declare_hw_range_handler(minio, 0, INT_MAX)
declare_hw_snprint(minio, print_nonzero)
-declare_mp_handler(minio, set_int)
+declare_mp_range_handler(minio, 0, INT_MAX)
declare_mp_snprint(minio, print_nonzero)
-declare_def_handler(minio_rq, set_int)
+declare_def_range_handler(minio_rq, 0, INT_MAX)
declare_def_snprint_defint(minio_rq, print_int, DEFAULT_MINIO_RQ)
-declare_ovr_handler(minio_rq, set_int)
+declare_ovr_range_handler(minio_rq, 0, INT_MAX)
declare_ovr_snprint(minio_rq, print_nonzero)
-declare_hw_handler(minio_rq, set_int)
+declare_hw_range_handler(minio_rq, 0, INT_MAX)
declare_hw_snprint(minio_rq, print_nonzero)
-declare_mp_handler(minio_rq, set_int)
+declare_mp_range_handler(minio_rq, 0, INT_MAX)
declare_mp_snprint(minio_rq, print_nonzero)
declare_def_handler(queue_without_daemon, set_yes_no)
@@ -512,7 +561,7 @@ snprint_def_queue_without_daemon(struct config *conf, struct strbuf *buff,
return append_strbuf_quoted(buff, qwd);
}
-declare_def_handler(checker_timeout, set_int)
+declare_def_range_handler(checker_timeout, 0, INT_MAX)
declare_def_snprint(checker_timeout, print_nonzero)
declare_def_handler(allow_usb_devices, set_yes_no)
@@ -583,13 +632,13 @@ declare_hw_snprint(deferred_remove, print_yes_no_undef)
declare_mp_handler(deferred_remove, set_yes_no_undef)
declare_mp_snprint(deferred_remove, print_yes_no_undef)
-declare_def_handler(retrigger_tries, set_int)
+declare_def_range_handler(retrigger_tries, 0, INT_MAX)
declare_def_snprint(retrigger_tries, print_int)
-declare_def_handler(retrigger_delay, set_int)
+declare_def_range_handler(retrigger_delay, 0, INT_MAX)
declare_def_snprint(retrigger_delay, print_int)
-declare_def_handler(uev_wait_timeout, set_int)
+declare_def_range_handler(uev_wait_timeout, 0, INT_MAX)
declare_def_snprint(uev_wait_timeout, print_int)
declare_def_handler(strict_timing, set_yes_no)
@@ -616,19 +665,19 @@ static int snprint_def_disable_changed_wwids(struct config *conf,
return print_ignored(buff);
}
-declare_def_handler(remove_retries, set_int)
+declare_def_range_handler(remove_retries, 0, INT_MAX)
declare_def_snprint(remove_retries, print_int)
-declare_def_handler(max_sectors_kb, set_int)
+declare_def_range_handler(max_sectors_kb, 0, INT_MAX)
declare_def_snprint(max_sectors_kb, print_nonzero)
-declare_ovr_handler(max_sectors_kb, set_int)
+declare_ovr_range_handler(max_sectors_kb, 0, INT_MAX)
declare_ovr_snprint(max_sectors_kb, print_nonzero)
-declare_hw_handler(max_sectors_kb, set_int)
+declare_hw_range_handler(max_sectors_kb, 0, INT_MAX)
declare_hw_snprint(max_sectors_kb, print_nonzero)
-declare_mp_handler(max_sectors_kb, set_int)
+declare_mp_range_handler(max_sectors_kb, 0, INT_MAX)
declare_mp_snprint(max_sectors_kb, print_nonzero)
-declare_def_handler(find_multipaths_timeout, set_int)
+declare_def_range_handler(find_multipaths_timeout, INT_MIN, INT_MAX)
declare_def_snprint_defint(find_multipaths_timeout, print_int,
DEFAULT_FIND_MULTIPATHS_TIMEOUT)
@@ -1385,27 +1434,7 @@ declare_ovr_snprint(recheck_wwid, print_yes_no_undef)
declare_hw_handler(recheck_wwid, set_yes_no_undef)
declare_hw_snprint(recheck_wwid, print_yes_no_undef)
-
-static int
-def_uxsock_timeout_handler(struct config *conf, vector strvec, const char *file,
- int line_nr)
-{
- unsigned int uxsock_timeout;
- char *buff;
-
- buff = set_value(strvec);
- if (!buff)
- return 1;
-
- if (sscanf(buff, "%u", &uxsock_timeout) == 1 &&
- uxsock_timeout > DEFAULT_REPLY_TIMEOUT)
- conf->uxsock_timeout = uxsock_timeout;
- else
- conf->uxsock_timeout = DEFAULT_REPLY_TIMEOUT;
-
- free(buff);
- return 0;
-}
+declare_def_range_handler(uxsock_timeout, DEFAULT_REPLY_TIMEOUT, INT_MAX)
static int
hw_vpd_vendor_handler(struct config *conf, vector strvec, const char *file,

@ -1,170 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 29 Sep 2021 12:56:04 -0500
Subject: [PATCH] libmultipath: improve checks for set_str
multipath always requires absolute pathnames, so make sure all file and
directory names start with a slash. Also check that the directories
exist. Finally, some strings, like the alias, will be used in paths.
These must not contain the slash character '/', since it is a forbidden
character in file/directory names. This patch adds seperate handlers for
these three cases. If a config line is invalid, these handlers retain
the existing config string, if any.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/dict.c | 88 +++++++++++++++++++++++++++++++++++++++------
1 file changed, 78 insertions(+), 10 deletions(-)
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index 57b6a7b6..149d3348 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -5,6 +5,8 @@
* Copyright (c) 2005 Kiyoshi Ueda, NEC
*/
#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
#include <pwd.h>
#include <string.h>
#include "checkers.h"
@@ -111,6 +113,72 @@ set_str(vector strvec, void *ptr, const char *file, int line_nr)
return 0;
}
+static int
+set_dir(vector strvec, void *ptr, const char *file, int line_nr)
+{
+ char **str_ptr = (char **)ptr;
+ char *old_str = *str_ptr;
+ struct stat sb;
+
+ *str_ptr = set_value(strvec);
+ if (!*str_ptr) {
+ free(old_str);
+ return 1;
+ }
+ if ((*str_ptr)[0] != '/'){
+ condlog(1, "%s line %d, %s is not an absolute directory path. Ignoring", file, line_nr, *str_ptr);
+ *str_ptr = old_str;
+ } else {
+ if (stat(*str_ptr, &sb) == 0 && S_ISDIR(sb.st_mode))
+ free(old_str);
+ else {
+ condlog(1, "%s line %d, %s is not an existing directory. Ignoring", file, line_nr, *str_ptr);
+ *str_ptr = old_str;
+ }
+ }
+ return 0;
+}
+
+static int
+set_path(vector strvec, void *ptr, const char *file, int line_nr)
+{
+ char **str_ptr = (char **)ptr;
+ char *old_str = *str_ptr;
+
+ *str_ptr = set_value(strvec);
+ if (!*str_ptr) {
+ free(old_str);
+ return 1;
+ }
+ if ((*str_ptr)[0] != '/'){
+ condlog(1, "%s line %d, %s is not an absolute path. Ignoring",
+ file, line_nr, *str_ptr);
+ *str_ptr = old_str;
+ } else
+ free(old_str);
+ return 0;
+}
+
+static int
+set_str_noslash(vector strvec, void *ptr, const char *file, int line_nr)
+{
+ char **str_ptr = (char **)ptr;
+ char *old_str = *str_ptr;
+
+ *str_ptr = set_value(strvec);
+ if (!*str_ptr) {
+ free(old_str);
+ return 1;
+ }
+ if (strchr(*str_ptr, '/')) {
+ condlog(1, "%s line %d, %s cannot contain a slash. Ignoring",
+ file, line_nr, *str_ptr);
+ *str_ptr = old_str;
+ } else
+ free(old_str);
+ return 0;
+}
+
static int
set_yes_no(vector strvec, void *ptr, const char *file, int line_nr)
{
@@ -353,13 +421,13 @@ declare_def_snprint(verbosity, print_int)
declare_def_handler(reassign_maps, set_yes_no)
declare_def_snprint(reassign_maps, print_yes_no)
-declare_def_handler(multipath_dir, set_str)
+declare_def_handler(multipath_dir, set_dir)
declare_def_snprint(multipath_dir, print_str)
static int def_partition_delim_handler(struct config *conf, vector strvec,
const char *file, int line_nr)
{
- int rc = set_str(strvec, &conf->partition_delim, file, line_nr);
+ int rc = set_str_noslash(strvec, &conf->partition_delim, file, line_nr);
if (rc != 0)
return rc;
@@ -490,11 +558,11 @@ declare_hw_snprint(prio_name, print_str)
declare_mp_handler(prio_name, set_str)
declare_mp_snprint(prio_name, print_str)
-declare_def_handler(alias_prefix, set_str)
+declare_def_handler(alias_prefix, set_str_noslash)
declare_def_snprint_defstr(alias_prefix, print_str, DEFAULT_ALIAS_PREFIX)
-declare_ovr_handler(alias_prefix, set_str)
+declare_ovr_handler(alias_prefix, set_str_noslash)
declare_ovr_snprint(alias_prefix, print_str)
-declare_hw_handler(alias_prefix, set_str)
+declare_hw_handler(alias_prefix, set_str_noslash)
declare_hw_snprint(alias_prefix, print_str)
declare_def_handler(prio_args, set_str)
@@ -586,13 +654,13 @@ declare_hw_snprint(user_friendly_names, print_yes_no_undef)
declare_mp_handler(user_friendly_names, set_yes_no_undef)
declare_mp_snprint(user_friendly_names, print_yes_no_undef)
-declare_def_handler(bindings_file, set_str)
+declare_def_handler(bindings_file, set_path)
declare_def_snprint(bindings_file, print_str)
-declare_def_handler(wwids_file, set_str)
+declare_def_handler(wwids_file, set_path)
declare_def_snprint(wwids_file, print_str)
-declare_def_handler(prkeys_file, set_str)
+declare_def_handler(prkeys_file, set_path)
declare_def_snprint(prkeys_file, print_str)
declare_def_handler(retain_hwhandler, set_yes_no_undef)
@@ -692,7 +760,7 @@ def_config_dir_handler(struct config *conf, vector strvec, const char *file,
/* this is only valid in the main config file */
if (conf->processed_main_config)
return 0;
- return set_str(strvec, &conf->config_dir, file, line_nr);
+ return set_path(strvec, &conf->config_dir, file, line_nr);
}
declare_def_snprint(config_dir, print_str)
@@ -1732,7 +1800,7 @@ multipath_handler(struct config *conf, vector strvec, const char *file,
declare_mp_handler(wwid, set_str)
declare_mp_snprint(wwid, print_str)
-declare_mp_handler(alias, set_str)
+declare_mp_handler(alias, set_str_noslash)
declare_mp_snprint(alias, print_str)
/*

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

@ -1,191 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 4 Oct 2021 15:27:36 -0500
Subject: [PATCH] libmultipath: split set_int to enable reuse
Split the code that does the actual value parsing out of set_int(), into
a helper function, do_set_int(), so that it can be used by other
handlers. These functions no longer set the config value at all, when
they have invalid input.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/dict.c | 82 +++++++++++++++++++++++++--------------------
1 file changed, 46 insertions(+), 36 deletions(-)
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index d14be340..68647061 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -31,17 +31,12 @@
#include "strbuf.h"
static int
-set_int(vector strvec, void *ptr, int min, int max, const char *file,
- int line_nr)
+do_set_int(vector strvec, void *ptr, int min, int max, const char *file,
+ int line_nr, char *buff)
{
int *int_ptr = (int *)ptr;
- char *buff, *eptr;
+ char *eptr;
long res;
- int rc;
-
- buff = set_value(strvec);
- if (!buff)
- return 1;
res = strtol(buff, &eptr, 10);
if (eptr > buff)
@@ -50,17 +45,30 @@ set_int(vector strvec, void *ptr, int min, int max, const char *file,
if (*buff == '\0' || *eptr != '\0') {
condlog(1, "%s line %d, invalid value for %s: \"%s\"",
file, line_nr, (char*)VECTOR_SLOT(strvec, 0), buff);
- rc = 1;
- } else {
- if (res > max || res < min) {
- res = (res > max) ? max : min;
- condlog(1, "%s line %d, value for %s too %s, capping at %ld",
+ return 1;
+ }
+ if (res > max || res < min) {
+ res = (res > max) ? max : min;
+ condlog(1, "%s line %d, value for %s too %s, capping at %ld",
file, line_nr, (char*)VECTOR_SLOT(strvec, 0),
- (res == max)? "large" : "small", res);
- }
- rc = 0;
- *int_ptr = res;
+ (res == max)? "large" : "small", res);
}
+ *int_ptr = res;
+ return 0;
+}
+
+static int
+set_int(vector strvec, void *ptr, int min, int max, const char *file,
+ int line_nr)
+{
+ char *buff;
+ int rc;
+
+ buff = set_value(strvec);
+ if (!buff)
+ return 1;
+
+ rc = do_set_int(strvec, ptr, min, max, file, line_nr, buff);
FREE(buff);
return rc;
@@ -929,6 +937,7 @@ declare_mp_attr_snprint(gid, print_gid)
static int
set_undef_off_zero(vector strvec, void *ptr, const char *file, int line_nr)
{
+ int rc = 0;
char * buff;
int *int_ptr = (int *)ptr;
@@ -938,10 +947,10 @@ set_undef_off_zero(vector strvec, void *ptr, const char *file, int line_nr)
if (strcmp(buff, "off") == 0)
*int_ptr = UOZ_OFF;
- else if (sscanf(buff, "%d", int_ptr) != 1 ||
- *int_ptr < UOZ_ZERO)
- *int_ptr = UOZ_UNDEF;
- else if (*int_ptr == 0)
+ else
+ rc = do_set_int(strvec, int_ptr, 0, INT_MAX, file, line_nr,
+ buff);
+ if (rc == 0 && *int_ptr == 0)
*int_ptr = UOZ_ZERO;
FREE(buff);
@@ -1093,14 +1102,12 @@ max_fds_handler(struct config *conf, vector strvec, const char *file,
/* Assume safe limit */
max_fds = 4096;
}
- if (strlen(buff) == 3 &&
- !strcmp(buff, "max"))
- conf->max_fds = max_fds;
- else
- conf->max_fds = atoi(buff);
-
- if (conf->max_fds > max_fds)
+ if (!strcmp(buff, "max")) {
conf->max_fds = max_fds;
+ r = 0;
+ } else
+ r = do_set_int(strvec, &conf->max_fds, 0, max_fds, file,
+ line_nr, buff);
FREE(buff);
@@ -1169,6 +1176,7 @@ declare_mp_snprint(rr_weight, print_rr_weight)
static int
set_pgfailback(vector strvec, void *ptr, const char *file, int line_nr)
{
+ int rc = 0;
int *int_ptr = (int *)ptr;
char * buff;
@@ -1183,11 +1191,11 @@ set_pgfailback(vector strvec, void *ptr, const char *file, int line_nr)
else if (strlen(buff) == 10 && !strcmp(buff, "followover"))
*int_ptr = -FAILBACK_FOLLOWOVER;
else
- *int_ptr = atoi(buff);
+ rc = do_set_int(strvec, ptr, 0, INT_MAX, file, line_nr, buff);
FREE(buff);
- return 0;
+ return rc;
}
int
@@ -1219,6 +1227,7 @@ declare_mp_snprint(pgfailback, print_pgfailback)
static int
no_path_retry_helper(vector strvec, void *ptr, const char *file, int line_nr)
{
+ int rc = 0;
int *int_ptr = (int *)ptr;
char * buff;
@@ -1230,11 +1239,11 @@ no_path_retry_helper(vector strvec, void *ptr, const char *file, int line_nr)
*int_ptr = NO_PATH_RETRY_FAIL;
else if (!strcmp(buff, "queue"))
*int_ptr = NO_PATH_RETRY_QUEUE;
- else if ((*int_ptr = atoi(buff)) < 1)
- *int_ptr = NO_PATH_RETRY_UNDEF;
+ else
+ rc = do_set_int(strvec, ptr, 1, INT_MAX, file, line_nr, buff);
FREE(buff);
- return 0;
+ return rc;
}
int
@@ -1376,6 +1385,7 @@ snprint_mp_reservation_key (struct config *conf, struct strbuf *buff,
static int
set_off_int_undef(vector strvec, void *ptr, const char *file, int line_nr)
{
+ int rc =0;
int *int_ptr = (int *)ptr;
char * buff;
@@ -1385,11 +1395,11 @@ set_off_int_undef(vector strvec, void *ptr, const char *file, int line_nr)
if (!strcmp(buff, "no") || !strcmp(buff, "0"))
*int_ptr = NU_NO;
- else if ((*int_ptr = atoi(buff)) < 1)
- *int_ptr = NU_UNDEF;
+ else
+ rc = do_set_int(strvec, ptr, 1, INT_MAX, file, line_nr, buff);
FREE(buff);
- return 0;
+ return rc;
}
int

@ -1,201 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 4 Oct 2021 16:52:55 -0500
Subject: [PATCH] libmultipath: cleanup invalid config handling
Add error reporting to the remaining config handlers. If the value is
invalid, do not change the existing config option's value. Also print
an error whenever 0 is returned for an invalid value. When the handler
returns 1, config processing already fails with an error message.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/dict.c | 73 +++++++++++++++++++++++++++++++--------------
1 file changed, 51 insertions(+), 22 deletions(-)
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index 68647061..c534d703 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -199,8 +199,11 @@ set_yes_no(vector strvec, void *ptr, const char *file, int line_nr)
if (strcmp(buff, "yes") == 0 || strcmp(buff, "1") == 0)
*int_ptr = YN_YES;
- else
+ else if (strcmp(buff, "no") == 0 || strcmp(buff, "0") == 0)
*int_ptr = YN_NO;
+ else
+ condlog(1, "%s line %d, invalid value for %s: \"%s\"",
+ file, line_nr, (char*)VECTOR_SLOT(strvec, 0), buff);
FREE(buff);
return 0;
@@ -221,7 +224,8 @@ set_yes_no_undef(vector strvec, void *ptr, const char *file, int line_nr)
else if (strcmp(buff, "yes") == 0 || strcmp(buff, "1") == 0)
*int_ptr = YNU_YES;
else
- *int_ptr = YNU_UNDEF;
+ condlog(1, "%s line %d, invalid value for %s: \"%s\"",
+ file, line_nr, (char*)VECTOR_SLOT(strvec, 0), buff);
FREE(buff);
return 0;
@@ -480,9 +484,6 @@ def_find_multipaths_handler(struct config *conf, vector strvec,
char *buff;
int i;
- if (set_yes_no_undef(strvec, &conf->find_multipaths, file, line_nr) == 0 && conf->find_multipaths != FIND_MULTIPATHS_UNDEF)
- return 0;
-
buff = set_value(strvec);
if (!buff)
return 1;
@@ -495,9 +496,14 @@ def_find_multipaths_handler(struct config *conf, vector strvec,
}
}
- if (conf->find_multipaths == YNU_UNDEF) {
- condlog(0, "illegal value for find_multipaths: %s", buff);
- conf->find_multipaths = DEFAULT_FIND_MULTIPATHS;
+ if (i >= __FIND_MULTIPATHS_LAST) {
+ if (strcmp(buff, "no") == 0 || strcmp(buff, "0") == 0)
+ conf->find_multipaths = FIND_MULTIPATHS_OFF;
+ else if (strcmp(buff, "yes") == 0 || strcmp(buff, "1") == 0)
+ conf->find_multipaths = FIND_MULTIPATHS_ON;
+ else
+ condlog(1, "%s line %d, invalid value for find_multipaths: \"%s\"",
+ file, line_nr, buff);
}
FREE(buff);
@@ -546,8 +552,10 @@ static int uid_attrs_handler(struct config *conf, vector strvec,
if (!val)
return 1;
if (parse_uid_attrs(val, conf))
- condlog(1, "error parsing uid_attrs: \"%s\"", val);
- condlog(3, "parsed %d uid_attrs", VECTOR_SIZE(&conf->uid_attrs));
+ condlog(1, "%s line %d,error parsing uid_attrs: \"%s\"", file,
+ line_nr, val);
+ else
+ condlog(4, "parsed %d uid_attrs", VECTOR_SIZE(&conf->uid_attrs));
FREE(val);
return 0;
}
@@ -775,8 +783,11 @@ def_config_dir_handler(struct config *conf, vector strvec, const char *file,
int line_nr)
{
/* this is only valid in the main config file */
- if (conf->processed_main_config)
+ if (conf->processed_main_config) {
+ condlog(1, "%s line %d, config_dir option only valid in /etc/multipath.conf",
+ file, line_nr);
return 0;
+ }
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);
@@ -836,7 +847,9 @@ set_mode(vector strvec, void *ptr, int *flags, const char *file, int line_nr)
if (sscanf(buff, "%o", &mode) == 1 && mode <= 0777) {
*flags |= (1 << ATTR_MODE);
*mode_ptr = mode;
- }
+ } else
+ condlog(1, "%s line %d, invalid value for mode: \"%s\"",
+ file, line_nr, buff);
FREE(buff);
return 0;
@@ -861,7 +874,9 @@ set_uid(vector strvec, void *ptr, int *flags, const char *file, int line_nr)
else if (sscanf(buff, "%u", &uid) == 1){
*flags |= (1 << ATTR_UID);
*uid_ptr = uid;
- }
+ } else
+ condlog(1, "%s line %d, invalid value for uid: \"%s\"",
+ file, line_nr, buff);
FREE(buff);
return 0;
@@ -887,7 +902,9 @@ set_gid(vector strvec, void *ptr, int *flags, const char *file, int line_nr)
else if (sscanf(buff, "%u", &gid) == 1){
*flags |= (1 << ATTR_GID);
*gid_ptr = gid;
- }
+ } else
+ condlog(1, "%s line %d, invalid value for gid: \"%s\"",
+ file, line_nr, buff);
FREE(buff);
return 0;
}
@@ -989,7 +1006,8 @@ set_dev_loss(vector strvec, void *ptr, const char *file, int line_nr)
if (!strcmp(buff, "infinity"))
*uint_ptr = MAX_DEV_LOSS_TMO;
else if (sscanf(buff, "%u", uint_ptr) != 1)
- *uint_ptr = DEV_LOSS_TMO_UNSET;
+ condlog(1, "%s line %d, invalid value for dev_loss_tmo: \"%s\"",
+ file, line_nr, buff);
FREE(buff);
return 0;
@@ -1023,13 +1041,19 @@ static int
set_pgpolicy(vector strvec, void *ptr, const char *file, int line_nr)
{
char * buff;
+ int policy;
int *int_ptr = (int *)ptr;
buff = set_value(strvec);
if (!buff)
return 1;
- *int_ptr = get_pgpolicy_id(buff);
+ policy = get_pgpolicy_id(buff);
+ if (policy != IOPOLICY_UNDEF)
+ *int_ptr = policy;
+ else
+ condlog(1, "%s line %d, invalid value for path_grouping_policy: \"%s\"",
+ file, line_nr, buff);
FREE(buff);
return 0;
@@ -1142,10 +1166,11 @@ set_rr_weight(vector strvec, void *ptr, const char *file, int line_nr)
if (!strcmp(buff, "priorities"))
*int_ptr = RR_WEIGHT_PRIO;
-
- if (!strcmp(buff, "uniform"))
+ else if (!strcmp(buff, "uniform"))
*int_ptr = RR_WEIGHT_NONE;
-
+ else
+ condlog(1, "%s line %d, invalid value for rr_weight: \"%s\"",
+ file, line_nr, buff);
FREE(buff);
return 0;
@@ -1281,10 +1306,13 @@ def_log_checker_err_handler(struct config *conf, vector strvec,
if (!buff)
return 1;
- if (strlen(buff) == 4 && !strcmp(buff, "once"))
+ if (!strcmp(buff, "once"))
conf->log_checker_err = LOG_CHKR_ERR_ONCE;
- else if (strlen(buff) == 6 && !strcmp(buff, "always"))
+ else if (!strcmp(buff, "always"))
conf->log_checker_err = LOG_CHKR_ERR_ALWAYS;
+ else
+ condlog(1, "%s line %d, invalid value for log_checker_err: \"%s\"",
+ file, line_nr, buff);
free(buff);
return 0;
@@ -1545,7 +1573,8 @@ hw_vpd_vendor_handler(struct config *conf, vector strvec, const char *file,
goto out;
}
}
- hwe->vpd_vendor_id = 0;
+ condlog(1, "%s line %d, invalid value for vpd_vendor: \"%s\"",
+ file, line_nr, buff);
out:
FREE(buff);
return 0;

@ -1,218 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 11 Nov 2021 17:37:05 -0600
Subject: [PATCH] libmultipath: don't return error on invalid values
do_set_int and set_uint return 1 for invalid values. This can cause
multipath to fail completely, while reading the config. The config
handlers should only return a non-zero value if there is an internal
error, not if there is just an invalid value.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/dict.c | 64 ++++++++++++++++++---------------------------
1 file changed, 25 insertions(+), 39 deletions(-)
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index c534d703..1b75be47 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -30,7 +30,7 @@
#include "dict.h"
#include "strbuf.h"
-static int
+static void
do_set_int(vector strvec, void *ptr, int min, int max, const char *file,
int line_nr, char *buff)
{
@@ -45,7 +45,7 @@ do_set_int(vector strvec, void *ptr, int min, int max, const char *file,
if (*buff == '\0' || *eptr != '\0') {
condlog(1, "%s line %d, invalid value for %s: \"%s\"",
file, line_nr, (char*)VECTOR_SLOT(strvec, 0), buff);
- return 1;
+ return;
}
if (res > max || res < min) {
res = (res > max) ? max : min;
@@ -54,7 +54,7 @@ do_set_int(vector strvec, void *ptr, int min, int max, const char *file,
(res == max)? "large" : "small", res);
}
*int_ptr = res;
- return 0;
+ return;
}
static int
@@ -62,16 +62,15 @@ set_int(vector strvec, void *ptr, int min, int max, const char *file,
int line_nr)
{
char *buff;
- int rc;
buff = set_value(strvec);
if (!buff)
return 1;
- rc = do_set_int(strvec, ptr, min, max, file, line_nr, buff);
+ do_set_int(strvec, ptr, min, max, file, line_nr, buff);
FREE(buff);
- return rc;
+ return 0;
}
static int
@@ -80,7 +79,6 @@ set_uint(vector strvec, void *ptr, const char *file, int line_nr)
unsigned int *uint_ptr = (unsigned int *)ptr;
char *buff, *eptr, *p;
unsigned long res;
- int rc;
buff = set_value(strvec);
if (!buff)
@@ -93,17 +91,14 @@ set_uint(vector strvec, void *ptr, const char *file, int line_nr)
if (eptr > buff)
while (isspace(*eptr))
eptr++;
- if (*buff == '\0' || *eptr != '\0' || !isdigit(*p) || res > UINT_MAX) {
+ if (*buff == '\0' || *eptr != '\0' || !isdigit(*p) || res > UINT_MAX)
condlog(1, "%s line %d, invalid value for %s: \"%s\"",
file, line_nr, (char*)VECTOR_SLOT(strvec, 0), buff);
- rc = 1;
- } else {
- rc = 0;
+ else
*uint_ptr = res;
- }
FREE(buff);
- return rc;
+ return 0;
}
static int
@@ -954,7 +949,6 @@ declare_mp_attr_snprint(gid, print_gid)
static int
set_undef_off_zero(vector strvec, void *ptr, const char *file, int line_nr)
{
- int rc = 0;
char * buff;
int *int_ptr = (int *)ptr;
@@ -964,11 +958,10 @@ set_undef_off_zero(vector strvec, void *ptr, const char *file, int line_nr)
if (strcmp(buff, "off") == 0)
*int_ptr = UOZ_OFF;
- else
- rc = do_set_int(strvec, int_ptr, 0, INT_MAX, file, line_nr,
- buff);
- if (rc == 0 && *int_ptr == 0)
+ else if (strcmp(buff, "0") == 0)
*int_ptr = UOZ_ZERO;
+ else
+ do_set_int(strvec, int_ptr, 1, INT_MAX, file, line_nr, buff);
FREE(buff);
return 0;
@@ -1114,28 +1107,24 @@ max_fds_handler(struct config *conf, vector strvec, const char *file,
int line_nr)
{
char * buff;
- int r = 0, max_fds;
+ int max_fds;
buff = set_value(strvec);
if (!buff)
return 1;
- r = get_sys_max_fds(&max_fds);
- if (r) {
- /* Assume safe limit */
- max_fds = 4096;
- }
- if (!strcmp(buff, "max")) {
+ if (get_sys_max_fds(&max_fds) != 0)
+ max_fds = 4096; /* Assume safe limit */
+ if (!strcmp(buff, "max"))
conf->max_fds = max_fds;
- r = 0;
- } else
- r = do_set_int(strvec, &conf->max_fds, 0, max_fds, file,
- line_nr, buff);
+ else
+ do_set_int(strvec, &conf->max_fds, 0, max_fds, file, line_nr,
+ buff);
FREE(buff);
- return r;
+ return 0;
}
static int
@@ -1201,7 +1190,6 @@ declare_mp_snprint(rr_weight, print_rr_weight)
static int
set_pgfailback(vector strvec, void *ptr, const char *file, int line_nr)
{
- int rc = 0;
int *int_ptr = (int *)ptr;
char * buff;
@@ -1216,11 +1204,11 @@ set_pgfailback(vector strvec, void *ptr, const char *file, int line_nr)
else if (strlen(buff) == 10 && !strcmp(buff, "followover"))
*int_ptr = -FAILBACK_FOLLOWOVER;
else
- rc = do_set_int(strvec, ptr, 0, INT_MAX, file, line_nr, buff);
+ do_set_int(strvec, ptr, 0, INT_MAX, file, line_nr, buff);
FREE(buff);
- return rc;
+ return 0;
}
int
@@ -1252,7 +1240,6 @@ declare_mp_snprint(pgfailback, print_pgfailback)
static int
no_path_retry_helper(vector strvec, void *ptr, const char *file, int line_nr)
{
- int rc = 0;
int *int_ptr = (int *)ptr;
char * buff;
@@ -1265,10 +1252,10 @@ no_path_retry_helper(vector strvec, void *ptr, const char *file, int line_nr)
else if (!strcmp(buff, "queue"))
*int_ptr = NO_PATH_RETRY_QUEUE;
else
- rc = do_set_int(strvec, ptr, 1, INT_MAX, file, line_nr, buff);
+ do_set_int(strvec, ptr, 1, INT_MAX, file, line_nr, buff);
FREE(buff);
- return rc;
+ return 0;
}
int
@@ -1413,7 +1400,6 @@ snprint_mp_reservation_key (struct config *conf, struct strbuf *buff,
static int
set_off_int_undef(vector strvec, void *ptr, const char *file, int line_nr)
{
- int rc =0;
int *int_ptr = (int *)ptr;
char * buff;
@@ -1424,10 +1410,10 @@ set_off_int_undef(vector strvec, void *ptr, const char *file, int line_nr)
if (!strcmp(buff, "no") || !strcmp(buff, "0"))
*int_ptr = NU_NO;
else
- rc = do_set_int(strvec, ptr, 1, INT_MAX, file, line_nr, buff);
+ do_set_int(strvec, ptr, 1, INT_MAX, file, line_nr, buff);
FREE(buff);
- return rc;
+ return 0;
}
int

@ -1,129 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 15 Nov 2021 10:54:35 -0600
Subject: [PATCH] multipathd: avoid unnecessary path read-only reloads
A mulitpath device can only be reloaded read/write when all paths are
read/write. Also, whenever a read-only device is rescanned, the scsi
subsystem will first unconditionally issue a uevent with DISK_RO=0
before checking the read-only status, and if it the device is still
read-only, issuing another uevent with DISK_RO=1. These uevents cause
pointless reloads when read-only paths are rescanned. To avoid this,
check to see if all paths are read/write before changing a multipath
device from read-only to read/write.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/libmultipath.version | 5 +++++
libmultipath/sysfs.c | 22 ++++++++++++++++++++++
libmultipath/sysfs.h | 1 +
multipathd/main.c | 31 ++++++++++++++++++++++++++++++-
4 files changed, 58 insertions(+), 1 deletion(-)
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index eb5b5b55..dd1b4122 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -287,3 +287,8 @@ global:
local:
*;
};
+
+LIBMULTIPATH_9.1.0 {
+global:
+ sysfs_get_ro;
+} LIBMULTIPATH_9.0.0;
diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c
index 9ff145f2..24c12b6a 100644
--- a/libmultipath/sysfs.c
+++ b/libmultipath/sysfs.c
@@ -236,6 +236,28 @@ sysfs_get_size (struct path *pp, unsigned long long * size)
return 0;
}
+int
+sysfs_get_ro (struct path *pp)
+{
+ int ro;
+ char buff[3]; /* Either "0\n\0" or "1\n\0" */
+
+ if (!pp->udev)
+ return -1;
+
+ if (sysfs_attr_get_value(pp->udev, "ro", buff, sizeof(buff)) <= 0) {
+ condlog(3, "%s: Cannot read ro attribute in sysfs", pp->dev);
+ return -1;
+ }
+
+ if (sscanf(buff, "%d\n", &ro) != 1 || ro < 0 || ro > 1) {
+ condlog(3, "%s: Cannot parse ro attribute", pp->dev);
+ return -1;
+ }
+
+ return ro;
+}
+
int sysfs_check_holders(char * check_devt, char * new_devt)
{
unsigned int major, new_minor, table_minor;
diff --git a/libmultipath/sysfs.h b/libmultipath/sysfs.h
index 72b39ab2..c948c467 100644
--- a/libmultipath/sysfs.h
+++ b/libmultipath/sysfs.h
@@ -13,6 +13,7 @@ ssize_t sysfs_attr_get_value(struct udev_device *dev, const char *attr_name,
ssize_t sysfs_bin_attr_get_value(struct udev_device *dev, const char *attr_name,
unsigned char * value, size_t value_len);
int sysfs_get_size (struct path *pp, unsigned long long * size);
+int sysfs_get_ro(struct path *pp);
int sysfs_check_holders(char * check_devt, char * new_devt);
bool sysfs_is_multipathed(struct path *pp, bool set_wwid);
#endif
diff --git a/multipathd/main.c b/multipathd/main.c
index 1defeaf1..6145e512 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1324,6 +1324,35 @@ fail:
return REMOVE_PATH_MAP_ERROR;
}
+static bool
+needs_ro_update(struct multipath *mpp, int ro)
+{
+ struct pathgroup * pgp;
+ struct path * pp;
+ unsigned int i, j;
+ struct dm_info *dmi = NULL;
+
+ if (!mpp || ro < 0)
+ return false;
+ dm_get_info(mpp->alias, &dmi);
+ if (!dmi) /* assume we do need to reload the device */
+ return true;
+ if (dmi->read_only == ro) {
+ free(dmi);
+ return false;
+ }
+ free(dmi);
+ if (ro == 1)
+ return true;
+ vector_foreach_slot (mpp->pg, pgp, i) {
+ vector_foreach_slot (pgp->paths, pp, j) {
+ if (sysfs_get_ro(pp) == 1)
+ return false;
+ }
+ }
+ return true;
+}
+
static int
uev_update_path (struct uevent *uev, struct vectors * vecs)
{
@@ -1388,7 +1417,7 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
}
ro = uevent_get_disk_ro(uev);
- if (mpp && ro >= 0) {
+ if (needs_ro_update(mpp, ro)) {
condlog(2, "%s: update path write_protect to '%d' (uevent)", uev->kernel, ro);
if (mpp->wait_for_udev)

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

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

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

@ -1,133 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 17 Jan 2022 14:45:38 -0600
Subject: [PATCH] libmultipath: make helper function to trigger path uevents
Pull the code that checks if a path needs to trigger a uevent, and
triggers, out of trigger_paths_udev_change() and into a new function,
trigger_path_udev_change(). This function will be used separately by
a future patch. No functional changes.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/configure.c | 79 +++++++++++++++++++++-------------------
libmultipath/configure.h | 1 +
2 files changed, 43 insertions(+), 37 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 7edb355b..043e4232 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -565,11 +565,8 @@ unref:
}
void
-trigger_paths_udev_change(struct multipath *mpp, bool is_mpath)
+trigger_path_udev_change(struct path *pp, bool is_mpath)
{
- struct pathgroup *pgp;
- struct path *pp;
- int i, j;
/*
* If a path changes from multipath to non-multipath, we must
* synthesize an artificial "add" event, otherwise the LVM2 rules
@@ -577,6 +574,45 @@ trigger_paths_udev_change(struct multipath *mpp, bool is_mpath)
* irritate ourselves with an "add", so use "change".
*/
const char *action = is_mpath ? "change" : "add";
+ const char *env;
+
+ if (!pp->udev)
+ return;
+ /*
+ * Paths that are already classified as multipath
+ * members don't need another uevent.
+ */
+ env = udev_device_get_property_value(
+ pp->udev, "DM_MULTIPATH_DEVICE_PATH");
+
+ if (is_mpath && env != NULL && !strcmp(env, "1")) {
+ /*
+ * If FIND_MULTIPATHS_WAIT_UNTIL is not "0",
+ * path is in "maybe" state and timer is running
+ * Send uevent now (see multipath.rules).
+ */
+ env = udev_device_get_property_value(
+ pp->udev, "FIND_MULTIPATHS_WAIT_UNTIL");
+ if (env == NULL || !strcmp(env, "0"))
+ return;
+ } else if (!is_mpath &&
+ (env == NULL || !strcmp(env, "0")))
+ return;
+
+ condlog(3, "triggering %s uevent for %s (is %smultipath member)",
+ action, pp->dev, is_mpath ? "" : "no ");
+ sysfs_attr_set_value(pp->udev, "uevent",
+ action, strlen(action));
+ trigger_partitions_udev_change(pp->udev, action,
+ strlen(action));
+}
+
+void
+trigger_paths_udev_change(struct multipath *mpp, bool is_mpath)
+{
+ struct pathgroup *pgp;
+ struct path *pp;
+ int i, j;
if (!mpp || !mpp->pg)
return;
@@ -584,39 +620,8 @@ trigger_paths_udev_change(struct multipath *mpp, bool is_mpath)
vector_foreach_slot (mpp->pg, pgp, i) {
if (!pgp->paths)
continue;
- vector_foreach_slot(pgp->paths, pp, j) {
- const char *env;
-
- if (!pp->udev)
- continue;
- /*
- * Paths that are already classified as multipath
- * members don't need another uevent.
- */
- env = udev_device_get_property_value(
- pp->udev, "DM_MULTIPATH_DEVICE_PATH");
-
- if (is_mpath && env != NULL && !strcmp(env, "1")) {
- /*
- * If FIND_MULTIPATHS_WAIT_UNTIL is not "0",
- * path is in "maybe" state and timer is running
- * Send uevent now (see multipath.rules).
- */
- env = udev_device_get_property_value(
- pp->udev, "FIND_MULTIPATHS_WAIT_UNTIL");
- if (env == NULL || !strcmp(env, "0"))
- continue;
- } else if (!is_mpath &&
- (env == NULL || !strcmp(env, "0")))
- continue;
-
- condlog(3, "triggering %s uevent for %s (is %smultipath member)",
- action, pp->dev, is_mpath ? "" : "no ");
- sysfs_attr_set_value(pp->udev, "uevent",
- action, strlen(action));
- trigger_partitions_udev_change(pp->udev, action,
- strlen(action));
- }
+ vector_foreach_slot(pgp->paths, pp, j)
+ trigger_path_udev_change(pp, is_mpath);
}
mpp->needs_paths_uevent = 0;
diff --git a/libmultipath/configure.h b/libmultipath/configure.h
index efe18b7d..2bf73e65 100644
--- a/libmultipath/configure.h
+++ b/libmultipath/configure.h
@@ -56,6 +56,7 @@ int coalesce_paths (struct vectors *vecs, vector curmp, char * refwwid, int forc
int get_refwwid (enum mpath_cmds cmd, const char *dev, enum devtypes dev_type,
vector pathvec, char **wwid);
struct udev_device *get_udev_device(const char *dev, enum devtypes dev_type);
+void trigger_path_udev_change(struct path *pp, bool is_mpath);
void trigger_paths_udev_change(struct multipath *mpp, bool is_mpath);
void trigger_partitions_udev_change(struct udev_device *dev, const char *action,
int len);

@ -1,54 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 17 Jan 2022 16:46:18 -0600
Subject: [PATCH] multipathd: trigger udev change on path addition
When a multipath device is created for the first time, there is a window
where some path devices way be added to the multipath device, but never
claimed in udev. This can allow other device owners, like lvm, to think
they can use the device.
When a multipath device is first created, all the existing paths that
are not claimed by multipath have a uevent triggered so that they can
get claimed. After that, multipath assumes all future paths added to the
multipath device will have been claimed by multipath, since the device's
WWID is now in the wwids file. This doesn't work for any paths that
have already been processed by the multipath.rules udev rules before
the multipath device was created.
To close this window, when path device is added, and a matching
multipath device already exists, multipathd now checks if the device is
claimed by multipath, and if not, triggers a uevent to claim it.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/libmultipath.version | 5 +++++
multipathd/main.c | 2 ++
2 files changed, 7 insertions(+)
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index dd1b4122..0d89e9e1 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -292,3 +292,8 @@ LIBMULTIPATH_9.1.0 {
global:
sysfs_get_ro;
} LIBMULTIPATH_9.0.0;
+
+LIBMULTIPATH_9.1.1 {
+global:
+ trigger_path_udev_change;
+} LIBMULTIPATH_9.1.0;
diff --git a/multipathd/main.c b/multipathd/main.c
index 6145e512..5def5301 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1062,6 +1062,8 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map)
free_path(pp);
return 1;
}
+ if (mpp)
+ trigger_path_udev_change(pp, true);
if (mpp && mpp->wait_for_udev &&
(pathcount(mpp, PATH_UP) > 0 ||
(pathcount(mpp, PATH_GHOST) > 0 &&

@ -1,149 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 2 Feb 2022 17:00:21 -0600
Subject: [PATCH] RH: add support to mpathconf for setting arbitrary default
options
mpathconf now supports --option <name>:[<value>] for setting, changing,
or removing options from the defaults section of multipath.conf.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/mpathconf | 58 ++++++++++++++++++++++++++++++++++++++++---
multipath/mpathconf.8 | 7 ++++++
2 files changed, 62 insertions(+), 3 deletions(-)
diff --git a/multipath/mpathconf b/multipath/mpathconf
index 0de6b121..6e33fb99 100644
--- a/multipath/mpathconf
+++ b/multipath/mpathconf
@@ -17,7 +17,7 @@
# This program was largely ripped off from lvmconf
#
-unset ENABLE FIND FRIENDLY PROPERTY FOREIGN MODULE MULTIPATHD HAVE_DISABLE HAVE_WWID_DISABLE HAVE_FIND HAVE_BLACKLIST HAVE_EXCEPTIONS HAVE_DEFAULTS HAVE_FRIENDLY HAVE_PROPERTY HAVE_FOREIGN HAVE_MULTIPATHD HAVE_MODULE HAVE_OUTFILE SHOW_STATUS CHANGED_CONFIG WWID_LIST
+unset ENABLE FIND FRIENDLY PROPERTY FOREIGN MODULE MULTIPATHD HAVE_DISABLE HAVE_WWID_DISABLE HAVE_FIND HAVE_BLACKLIST HAVE_EXCEPTIONS HAVE_DEFAULTS HAVE_FRIENDLY HAVE_PROPERTY HAVE_FOREIGN HAVE_MULTIPATHD HAVE_MODULE HAVE_OUTFILE SHOW_STATUS CHANGED_CONFIG WWID_LIST HAVE_OPTION OPTION_NAME OPTION_VALUE
DEFAULT_CONFIG="# device-mapper-multipath configuration file
@@ -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 "Add/Change/Remove option in defaults section: --option <option_name>:<value>"
echo "Load the dm-multipath modules on enable (Default y): --with_module <y|n>"
echo "start/stop/reload multipathd (Default n): --with_multipathd <y|n>"
echo "select output file (Default /etc/multipath.conf): --outfile <FILE>"
@@ -162,6 +163,20 @@ function parse_args
exit 1
fi
;;
+ --option)
+ if [ -n "$2" ]; then
+ OPTION_NAME=$(echo $2 | cut -s -f1 -d:)
+ OPTION_VALUE=$(echo $2 | cut -s -f2 -d:)
+ if [ -z "$OPTION_NAME" ]; then
+ usage
+ exit 1
+ fi
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
--enable_foreign)
if [ -n "$2" ]; then
FOREIGN=$2
@@ -208,12 +223,15 @@ function parse_args
function validate_args
{
- if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$PROPERTY" -o -n "$MODULE" ]; then
+ if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$PROPERTY" -o -n "$MODULE" -o -n "$FOREIGN" -o -n "$OPTION_NAME" ]; then
echo "ignoring extra parameters on disable"
FRIENDLY=""
FIND=""
PROPERTY=""
MODULE=""
+ FOREIGN=""
+ OPTION_NAME=""
+ OPTION_VALUE=""
fi
if [ -n "$FRIENDLY" ] && [ "$FRIENDLY" != "y" -a "$FRIENDLY" != "n" ]; then
echo "--user_friendly_names must be either 'y' or 'n'"
@@ -235,7 +253,19 @@ function validate_args
echo "--enable_foreign must be either 'y' or 'n'"
exit 1
fi
- if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" -a -z "$PROPERTY" -a -z "$FOREIGN" ]; then
+ if [ -n "$OPTION_NAME" ]; then
+ if [[ $OPTION_NAME =~ [[:space:]]|#|\"|!|\{|\} ]]; then
+ echo "--option name \"$OPTION_NAME\" is invalid"
+ exit 1
+ elif [[ $OPTION_VALUE =~ \"|#|!|\{|\} ]]; then
+ echo "--option value \"$OPTION_VALUE\" is invalid"
+ exit 1
+ fi
+ if [[ $OPTION_VALUE =~ [[:space:]] ]]; then
+ OPTION_VALUE=\"$OPTION_VALUE\"
+ fi
+ fi
+ if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" -a -z "$PROPERTY" -a -z "$FOREIGN" -a -z "$OPTION_NAME" ]; then
SHOW_STATUS=1
fi
if [ -n "$MODULE" ] && [ "$MODULE" != "y" -a "$MODULE" != "n" ]; then
@@ -348,6 +378,13 @@ if [ "$HAVE_DEFAULTS" = "1" ]; then
elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign" ; then
HAVE_FOREIGN=3
fi
+ if [ -n "$OPTION_NAME" ]; then
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q '^[[:space:]]*'"$OPTION_NAME"'[[:space:]][[:space:]]*'"$OPTION_VALUE" ; then
+ HAVE_OPTION=1
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q '^[[:space:]]*'"$OPTION_NAME"'\([[:space:]].*\)\?$' ; then
+ HAVE_OPTION=0
+ fi
+ fi
fi
if [ "$HAVE_EXCEPTIONS" = "1" ]; then
@@ -532,6 +569,21 @@ elif [ "$FOREIGN" = "y" ]; then
fi
fi
+if [ -n "$OPTION_NAME" -a -n "$OPTION_VALUE" ]; then
+ if [ -z "$HAVE_OPTION" ]; then
+ sed -i '/^defaults[[:space:]]*{/ a\
+ '"$OPTION_NAME"' '"$OPTION_VALUE"'
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$HAVE_OPTION" = 0 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*'"$OPTION_NAME"'\([[:space:]].*\)\?$/ '"$OPTION_NAME"' '"$OPTION_VALUE"'/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+elif [ -n "$OPTION_NAME" -a -n "$HAVE_OPTION" ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/{/^[[:space:]]*'"$OPTION_NAME"'\([[:space:]].*\)\?$/d}' $TMPFILE
+ CHANGED_CONFIG=1
+fi
+
if [ -f "$OUTPUTFILE" ]; then
cp $OUTPUTFILE $OUTPUTFILE.old
if [ $? != 0 ]; then
diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8
index a14d831e..496383b7 100644
--- a/multipath/mpathconf.8
+++ b/multipath/mpathconf.8
@@ -101,6 +101,13 @@ to the
defaults section. if set to \fBn\fP, this removes the line, if present. This
command can be used along with any other command.
.TP
+.B --option \fB<option_name>:[<value>]\fP
+Sets the defaults section option \fB<option_name>\fP to \fB<value>\fP. If the
+option was not previously set in the defaults section, it is added. If it was
+set, its value is changed to \fB<value>\fP. If \fB<value>\fP is left blank,
+then the option is removed from the defaults section, if was set there. This
+command can be used along with any other command.
+.TP
.B --outfile \fB<filename>\fP
Write the resulting multipath configuration to \fB<filename>\fP instead of
\fB/etc/multipath.conf\fP.

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

File diff suppressed because it is too large Load Diff

@ -1,73 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 11 Feb 2022 17:23:39 -0600
Subject: [PATCH] multipathd: disallow changing to/from fpin marginal paths on
reconfig
Setting marginal_pathgroups to fpin causes two new threads to be created
when multipathd starts. Turning it on after multipathd starts up won't
cause the theads to start, and turing it off won't keep the threads from
working. So disallow changing marginal_pathgroups to/from "fpin" on
reconfigure.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/multipath.conf.5 | 13 ++++++++-----
multipathd/main.c | 9 +++++++++
2 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 5ed2cd3c..58ad5c9c 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1102,15 +1102,18 @@ have been tried first. This prevents the possibility of IO errors occuring
while marginal paths are still usable. After the path has been monitored
for the configured time, and is declared healthy, it will be returned to its
normal pathgroup.
-However if this option is set to \fIfpin\fR multipathd will receive fpin
+If this option is set to \fIfpin\fR, multipathd will receive fpin
notifications, set path states to "marginal" accordingly, and regroup paths
-as described for "marginal_pathgroups yes". This option can't be used in combination
-with other options for "Shaky path detection" (see below).If it is set to fpin,
-marginal_path_xyz and san_path_err_xyz parameters are implicitly set to 0.
+as described for \fIon\fR. This option can't be used in combination
+with other options for "Shaky path detection" (see below). \fBNote:\fR If this
+is set to \fIfpin\fR, the \fImarginal_path_*\fR and \fIsan_path_err_*\fR
+options are implicitly set to \fIno\fP. Also, this option cannot be switched
+either to or from \fIfpin\fR on a multipathd reconfigure. multipathd must be
+restarted for the change to take effect.
See "Shaky paths detection" below for more information.
.RS
.TP
-The default is: \fBno\fR
+The default is: \fBoff\fR
.RE
.
.
diff --git a/multipathd/main.c b/multipathd/main.c
index 53be9b95..45b9572f 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -2792,6 +2792,7 @@ int
reconfigure (struct vectors * vecs)
{
struct config * old, *conf;
+ int old_marginal_pathgroups;
conf = load_config(DEFAULT_CONFIGFILE);
if (!conf)
@@ -2819,6 +2820,14 @@ reconfigure (struct vectors * vecs)
uxsock_timeout = conf->uxsock_timeout;
old = rcu_dereference(multipath_conf);
+ old_marginal_pathgroups = old->marginal_pathgroups;
+ if ((old_marginal_pathgroups == MARGINAL_PATHGROUP_FPIN) !=
+ (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN)) {
+ condlog(1, "multipathd must be restarted to turn %s fpin marginal paths",
+ (old_marginal_pathgroups == MARGINAL_PATHGROUP_FPIN)?
+ "off" : "on");
+ conf->marginal_pathgroups = old_marginal_pathgroups;
+ }
conf->sequence_nr = old->sequence_nr + 1;
rcu_assign_pointer(multipath_conf, conf);
call_rcu(&old->rcu, rcu_free_config);

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

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

@ -1,78 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Uday Shankar <ushankar@purestorage.com>
Date: Wed, 9 Mar 2022 13:03:26 -0700
Subject: [PATCH] multipath-tools: update mpp->force_readonly in ev_add_path
When NVMe disks are added to the system, no uevent containing the
DISK_RO property is generated. As a result, dm-* nodes backed by
readonly NVMe disks will not have their RO state set properly. The
result looks like this:
$ multipath -l
eui.00c92c091fd6564424a9376600011bd1 dm-3 NVME,Pure Storage FlashArray
size=1.0T features='0' hwhandler='0' wp=rw
|-+- policy='service-time 0' prio=0 status=active
| `- 0:2:2:72657 nvme0n2 259:4 active undef running
`-+- policy='service-time 0' prio=0 status=enabled
`- 1:0:2:72657 nvme1n2 259:1 active undef running
$ cat /sys/block/dm-3/ro
0
$ cat /sys/block/nvme*n2/ro
1
1
This is not a problem for SCSI disks, since the kernel will emit change
uevents containing the DISK_RO property when the disk is added to the
system. See the following thread for my initial attempt to fix this
issue at the kernel level:
https://lore.kernel.org/linux-block/Yib8GqCA5e3SQYty@infradead.org/T/#t
Fix the issue by picking up the path ro state from sysfs in ev_add_path,
setting the mpp->force_readonly accordingly, and changing
dm_addmap_create to be aware of mpp->force_readonly.
Signed-off-by: Uday Shankar <ushankar@purestorage.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 2 +-
multipathd/main.c | 6 ++++++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index c05dc201..1ff75c81 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -542,7 +542,7 @@ int dm_addmap_create (struct multipath *mpp, char * params)
int ro;
uint16_t udev_flags = build_udev_flags(mpp, 0);
- for (ro = 0; ro <= 1; ro++) {
+ for (ro = mpp->force_readonly ? 1 : 0; ro <= 1; ro++) {
int err;
if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, mpp, params, ro,
diff --git a/multipathd/main.c b/multipathd/main.c
index 45b9572f..ed2515e5 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1048,6 +1048,7 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map)
int retries = 3;
int start_waiter = 0;
int ret;
+ int ro;
/*
* need path UID to go any further
@@ -1112,6 +1113,11 @@ rescan:
/* persistent reservation check*/
mpath_pr_event_handle(pp);
+ /* ro check - if new path is ro, force map to be ro as well */
+ ro = sysfs_get_ro(pp);
+ if (ro == 1)
+ mpp->force_readonly = 1;
+
if (!need_do_map)
return 0;

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 30 Mar 2022 15:14:56 -0500
Subject: [PATCH] multipath: return failure on an invalid remove command
When "multipath -f" is run on a device that doesn't exist or isn't a
multipath device, the command will not remove any device, but it will
still return success. Multiple functions rely on _dm_flush_map()
returning success when called with name that doesn't match any
multipath device. So before calling _dm_flush_map(), call dm_is_mpath(),
to check if the device exists and is a multipath device, and return
failure if it's not.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com
---
multipath/main.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/multipath/main.c b/multipath/main.c
index 80fa68e5..41d01c7e 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -1111,6 +1111,11 @@ main (int argc, char *argv[])
if (retries < 0)
retries = conf->remove_retries;
if (cmd == CMD_FLUSH_ONE) {
+ if (dm_is_mpath(dev) != 1) {
+ condlog(0, "%s is not a multipath device", dev);
+ r = RTVL_FAIL;
+ goto out;
+ }
r = dm_suspend_and_flush_map(dev, retries) ?
RTVL_FAIL : RTVL_OK;
goto out;

@ -1,67 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 13 Apr 2022 23:27:35 -0500
Subject: [PATCH] libmultipath: steal the src string pointer in merge_str()
Instead of allocating a copy when the original string is going to be
freed right after the merge, just steal the pointer. Also, merge_mpe()
can't get called with NULL arguments.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/config.c | 16 +++++-----------
1 file changed, 5 insertions(+), 11 deletions(-)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index cee3bbb7..005d6b54 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -388,9 +388,9 @@ set_param_str(const char * str)
}
#define merge_str(s) \
- if (!dst->s && src->s) { \
- if (!(dst->s = set_param_str(src->s))) \
- return 1; \
+ if (!dst->s && src->s && strlen(src->s)) { \
+ dst->s = src->s; \
+ src->s = NULL; \
}
#define merge_num(s) \
@@ -398,7 +398,7 @@ set_param_str(const char * str)
dst->s = src->s
-static int
+static void
merge_hwe (struct hwentry * dst, struct hwentry * src)
{
char id[SCSI_VENDOR_SIZE+PATH_PRODUCT_SIZE];
@@ -450,15 +450,11 @@ merge_hwe (struct hwentry * dst, struct hwentry * src)
reconcile_features_with_options(id, &dst->features,
&dst->no_path_retry,
&dst->retain_hwhandler);
- return 0;
}
-static int
+static void
merge_mpe(struct mpentry *dst, struct mpentry *src)
{
- if (!dst || !src)
- return 1;
-
merge_str(alias);
merge_str(uid_attribute);
merge_str(getuid);
@@ -500,8 +496,6 @@ merge_mpe(struct mpentry *dst, struct mpentry *src)
merge_num(uid);
merge_num(gid);
merge_num(mode);
-
- return 0;
}
void merge_mptable(vector mptable)

@ -1,74 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Thu, 17 Feb 2022 17:22:32 +0100
Subject: [PATCH] libmultipath: enable linear ordering of bus/proto tuple
We categorized protocols by bus/proto_id, while we only differentiate
protocol IDs for SCSI. Allow transforming this into a linear sequence
of bus/protocol IDs by having non-SCSI first, and follwing up with
the different SCSI protocols.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/structs.c | 10 ++++++++++
libmultipath/structs.h | 13 +++++++++++--
2 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
index 6e5a1038..2b7cde0c 100644
--- a/libmultipath/structs.c
+++ b/libmultipath/structs.c
@@ -758,3 +758,13 @@ out:
return 0;
}
+
+unsigned int bus_protocol_id(const struct path *pp) {
+ if (!pp || pp->bus < 0 || pp->bus > SYSFS_BUS_SCSI)
+ return SYSFS_BUS_UNDEF;
+ if (pp->bus != SYSFS_BUS_SCSI)
+ return pp->bus;
+ if ((int)pp->sg_id.proto_id < 0 || pp->sg_id.proto_id > SCSI_PROTOCOL_UNSPEC)
+ return SYSFS_BUS_UNDEF;
+ return SYSFS_BUS_SCSI + pp->sg_id.proto_id;
+}
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index 1188363e..45294f11 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -56,12 +56,13 @@ enum failback_mode {
FAILBACK_FOLLOWOVER
};
+/* SYSFS_BUS_SCSI should be last, see bus_protocol_id() */
enum sysfs_buses {
SYSFS_BUS_UNDEF,
- SYSFS_BUS_SCSI,
SYSFS_BUS_CCW,
SYSFS_BUS_CCISS,
SYSFS_BUS_NVME,
+ SYSFS_BUS_SCSI,
};
enum pathstates {
@@ -180,9 +181,17 @@ enum scsi_protocol {
SCSI_PROTOCOL_ADT = 7, /* Media Changers */
SCSI_PROTOCOL_ATA = 8,
SCSI_PROTOCOL_USB = 9, /* USB Attached SCSI (UAS), and others */
- SCSI_PROTOCOL_UNSPEC = 0xf, /* No specific protocol */
+ SCSI_PROTOCOL_UNSPEC = 0xa, /* No specific protocol */
};
+/*
+ * Linear ordering of bus/protocol
+ * This assumes that SYSFS_BUS_SCSI is last in enum sysfs_buses
+ * SCSI is the only bus type for which we distinguish protocols.
+ */
+#define LAST_BUS_PROTOCOL_ID (SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC)
+unsigned int bus_protocol_id(const struct path *pp);
+
#define SCSI_INVALID_LUN ~0ULL
enum no_undef_states {

@ -1,84 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Thu, 17 Feb 2022 17:24:25 +0100
Subject: [PATCH] libmultipath: use bus_protocol_id() in
snprint_path_protocol()
Simplify bus_protocol_id() by using the linear ordering.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/print.c | 58 ++++++++++++++++----------------------------
1 file changed, 21 insertions(+), 37 deletions(-)
diff --git a/libmultipath/print.c b/libmultipath/print.c
index 2fb9f4ef..8f1b18db 100644
--- a/libmultipath/print.c
+++ b/libmultipath/print.c
@@ -696,43 +696,27 @@ snprint_path_failures(struct strbuf *buff, const struct path * pp)
int
snprint_path_protocol(struct strbuf *buff, const struct path * pp)
{
- switch (pp->bus) {
- case SYSFS_BUS_SCSI:
- switch (pp->sg_id.proto_id) {
- case SCSI_PROTOCOL_FCP:
- return append_strbuf_str(buff, "scsi:fcp");
- case SCSI_PROTOCOL_SPI:
- return append_strbuf_str(buff, "scsi:spi");
- case SCSI_PROTOCOL_SSA:
- return append_strbuf_str(buff, "scsi:ssa");
- case SCSI_PROTOCOL_SBP:
- return append_strbuf_str(buff, "scsi:sbp");
- case SCSI_PROTOCOL_SRP:
- return append_strbuf_str(buff, "scsi:srp");
- case SCSI_PROTOCOL_ISCSI:
- return append_strbuf_str(buff, "scsi:iscsi");
- case SCSI_PROTOCOL_SAS:
- return append_strbuf_str(buff, "scsi:sas");
- case SCSI_PROTOCOL_ADT:
- return append_strbuf_str(buff, "scsi:adt");
- case SCSI_PROTOCOL_ATA:
- return append_strbuf_str(buff, "scsi:ata");
- case SCSI_PROTOCOL_USB:
- return append_strbuf_str(buff, "scsi:usb");
- case SCSI_PROTOCOL_UNSPEC:
- default:
- return append_strbuf_str(buff, "scsi:unspec");
- }
- case SYSFS_BUS_CCW:
- return append_strbuf_str(buff, "ccw");
- case SYSFS_BUS_CCISS:
- return append_strbuf_str(buff, "cciss");
- case SYSFS_BUS_NVME:
- return append_strbuf_str(buff, "nvme");
- case SYSFS_BUS_UNDEF:
- default:
- return append_strbuf_str(buff, "undef");
- }
+ static const char * const protocol_name[LAST_BUS_PROTOCOL_ID + 1] = {
+ [SYSFS_BUS_UNDEF] = "undef",
+ [SYSFS_BUS_CCW] = "ccw",
+ [SYSFS_BUS_CCISS] = "cciss",
+ [SYSFS_BUS_NVME] = "nvme",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_FCP] = "scsi:fcp",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SPI] = "scsi:spi",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SSA] = "scsi:ssa",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SBP] = "scsi:sbp",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SRP] = "scsi:srp",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ISCSI] = "scsi:iscsi",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SAS] = "scsi:sas",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ADT] = "scsi:adt",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ATA] = "scsi:ata",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_USB] = "scsi:usb",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC] = "scsi:unspec",
+ };
+ const char *pn = protocol_name[bus_protocol_id(pp)];
+
+ assert(pn != NULL);
+ return append_strbuf_str(buff, pn);
}
int

@ -1,85 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 13 Apr 2022 23:27:36 -0500
Subject: [PATCH] libmultipath: make protocol_name global
Future patches will make use of this, so move it out of
snprint_path_protocol()
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/print.c | 17 -----------------
libmultipath/structs.c | 18 ++++++++++++++++++
libmultipath/structs.h | 1 +
3 files changed, 19 insertions(+), 17 deletions(-)
diff --git a/libmultipath/print.c b/libmultipath/print.c
index 8f1b18db..0dbd34e4 100644
--- a/libmultipath/print.c
+++ b/libmultipath/print.c
@@ -696,23 +696,6 @@ snprint_path_failures(struct strbuf *buff, const struct path * pp)
int
snprint_path_protocol(struct strbuf *buff, const struct path * pp)
{
- static const char * const protocol_name[LAST_BUS_PROTOCOL_ID + 1] = {
- [SYSFS_BUS_UNDEF] = "undef",
- [SYSFS_BUS_CCW] = "ccw",
- [SYSFS_BUS_CCISS] = "cciss",
- [SYSFS_BUS_NVME] = "nvme",
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_FCP] = "scsi:fcp",
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SPI] = "scsi:spi",
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SSA] = "scsi:ssa",
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SBP] = "scsi:sbp",
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SRP] = "scsi:srp",
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ISCSI] = "scsi:iscsi",
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SAS] = "scsi:sas",
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ADT] = "scsi:adt",
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ATA] = "scsi:ata",
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_USB] = "scsi:usb",
- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC] = "scsi:unspec",
- };
const char *pn = protocol_name[bus_protocol_id(pp)];
assert(pn != NULL);
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
index 2b7cde0c..d20e1eea 100644
--- a/libmultipath/structs.c
+++ b/libmultipath/structs.c
@@ -20,6 +20,24 @@
#include "prioritizers/alua_spc3.h"
#include "dm-generic.h"
+const char * const protocol_name[LAST_BUS_PROTOCOL_ID + 1] = {
+ [SYSFS_BUS_UNDEF] = "undef",
+ [SYSFS_BUS_CCW] = "ccw",
+ [SYSFS_BUS_CCISS] = "cciss",
+ [SYSFS_BUS_NVME] = "nvme",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_FCP] = "scsi:fcp",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SPI] = "scsi:spi",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SSA] = "scsi:ssa",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SBP] = "scsi:sbp",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SRP] = "scsi:srp",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ISCSI] = "scsi:iscsi",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SAS] = "scsi:sas",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ADT] = "scsi:adt",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ATA] = "scsi:ata",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_USB] = "scsi:usb",
+ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC] = "scsi:unspec",
+};
+
struct adapter_group *
alloc_adaptergroup(void)
{
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index 45294f11..618ff4fb 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -191,6 +191,7 @@ enum scsi_protocol {
*/
#define LAST_BUS_PROTOCOL_ID (SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC)
unsigned int bus_protocol_id(const struct path *pp);
+extern const char * const protocol_name[];
#define SCSI_INVALID_LUN ~0ULL

@ -1,425 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 13 Apr 2022 23:27:37 -0500
Subject: [PATCH] libmultipath: add a protocol subsection to multipath.conf
Some storage arrays can be accessed using multiple protocols at the same
time. In these cases, users may want to set path attributes
differently, depending on the protocol that the path is using. To allow
this, add a protocol subsection to the overrides section in
multipath.conf, which allows select path-specific options to be set.
This commit simply adds the subsection, and handles merging matching
entries. Future patches will make use of the section.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/config.c | 83 ++++++++++++++++++++++++++++++++++++
libmultipath/config.h | 10 +++++
libmultipath/dict.c | 99 +++++++++++++++++++++++++++++++++++++++++++
libmultipath/print.c | 50 ++++++++++++++++++++++
4 files changed, 242 insertions(+)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 005d6b54..8b0e1f72 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -238,6 +238,18 @@ const char *get_mpe_wwid(const struct _vector *mptable, const char *alias)
return NULL;
}
+static void
+free_pctable (vector pctable)
+{
+ int i;
+ struct pcentry *pce;
+
+ vector_foreach_slot(pctable, pce, i)
+ free(pce);
+
+ vector_free(pctable);
+}
+
void
free_hwe (struct hwentry * hwe)
{
@@ -283,6 +295,9 @@ free_hwe (struct hwentry * hwe)
if (hwe->bl_product)
FREE(hwe->bl_product);
+ if (hwe->pctable)
+ free_pctable(hwe->pctable);
+
FREE(hwe);
}
@@ -364,6 +379,15 @@ alloc_hwe (void)
return hwe;
}
+struct pcentry *
+alloc_pce (void)
+{
+ struct pcentry *pce = (struct pcentry *)
+ calloc(1, sizeof(struct pcentry));
+ pce->type = -1;
+ return pce;
+}
+
static char *
set_param_str(const char * str)
{
@@ -397,6 +421,13 @@ set_param_str(const char * str)
if (!dst->s && src->s) \
dst->s = src->s
+static void
+merge_pce(struct pcentry *dst, struct pcentry *src)
+{
+ merge_num(fast_io_fail);
+ merge_num(dev_loss);
+ merge_num(eh_deadline);
+}
static void
merge_hwe (struct hwentry * dst, struct hwentry * src)
@@ -603,6 +634,51 @@ out:
return 1;
}
+static void
+validate_pctable(struct hwentry *ovr, int idx, const char *table_desc)
+{
+ struct pcentry *pce;
+
+ if (!ovr || !ovr->pctable)
+ return;
+
+ vector_foreach_slot_after(ovr->pctable, pce, idx) {
+ if (pce->type < 0) {
+ condlog(0, "protocol section in %s missing type",
+ table_desc);
+ vector_del_slot(ovr->pctable, idx--);
+ free(pce);
+ }
+ }
+
+ if (VECTOR_SIZE(ovr->pctable) == 0) {
+ vector_free(ovr->pctable);
+ ovr->pctable = NULL;
+ }
+}
+
+static void
+merge_pctable(struct hwentry *ovr)
+{
+ struct pcentry *pce1, *pce2;
+ int i, j;
+
+ if (!ovr || !ovr->pctable)
+ return;
+
+ vector_foreach_slot(ovr->pctable, pce1, i) {
+ j = i + 1;
+ vector_foreach_slot_after(ovr->pctable, pce2, j) {
+ if (pce1->type != pce2->type)
+ continue;
+ merge_pce(pce2,pce1);
+ vector_del_slot(ovr->pctable, i--);
+ free(pce1);
+ break;
+ }
+ }
+}
+
static void
factorize_hwtable (vector hw, int n, const char *table_desc)
{
@@ -751,6 +827,7 @@ process_config_dir(struct config *conf, char *dir)
int i, n;
char path[LINE_MAX];
int old_hwtable_size;
+ int old_pctable_size = 0;
if (dir[0] != '/') {
condlog(1, "config_dir '%s' must be a fully qualified path",
@@ -777,11 +854,15 @@ process_config_dir(struct config *conf, char *dir)
continue;
old_hwtable_size = VECTOR_SIZE(conf->hwtable);
+ old_pctable_size = conf->overrides ?
+ VECTOR_SIZE(conf->overrides->pctable) : 0;
snprintf(path, LINE_MAX, "%s/%s", dir, namelist[i]->d_name);
path[LINE_MAX-1] = '\0';
process_file(conf, path);
factorize_hwtable(conf->hwtable, old_hwtable_size,
namelist[i]->d_name);
+ validate_pctable(conf->overrides, old_pctable_size,
+ namelist[i]->d_name);
}
pthread_cleanup_pop(1);
}
@@ -889,6 +970,7 @@ int _init_config (const char *file, struct config *conf)
goto out;
}
factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
+ validate_pctable(conf->overrides, 0, file);
} else {
condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
condlog(0, "You can run \"/sbin/mpathconf --enable\" to create");
@@ -1004,6 +1086,7 @@ int _init_config (const char *file, struct config *conf)
goto out;
}
+ merge_pctable(conf->overrides);
merge_mptable(conf->mptable);
merge_blacklist(conf->blist_devnode);
merge_blacklist(conf->blist_property);
diff --git a/libmultipath/config.h b/libmultipath/config.h
index 5f01c1fc..57992604 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -41,6 +41,13 @@ enum force_reload_types {
FORCE_RELOAD_WEAK,
};
+struct pcentry {
+ int type;
+ int fast_io_fail;
+ unsigned int dev_loss;
+ int eh_deadline;
+};
+
struct hwentry {
char * vendor;
char * product;
@@ -86,6 +93,8 @@ struct hwentry {
int vpd_vendor_id;
int recheck_wwid;
char * bl_product;
+
+ vector pctable;
};
struct mpentry {
@@ -286,6 +295,7 @@ const char *get_mpe_wwid (const struct _vector *mptable, const char *alias);
struct hwentry * alloc_hwe (void);
struct mpentry * alloc_mpe (void);
+struct pcentry * alloc_pce (void);
void free_hwe (struct hwentry * hwe);
void free_hwtable (vector hwtable);
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index eb5a8083..46b9f225 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -414,6 +414,29 @@ snprint_mp_ ## option (struct config *conf, struct strbuf *buff, \
return function(buff, mpe->option); \
}
+#define declare_pc_handler(option, function) \
+static int \
+pc_ ## option ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
+{ \
+ struct pcentry *pce; \
+ if (!conf->overrides || !conf->overrides->pctable) \
+ return 1; \
+ pce = VECTOR_LAST_SLOT(conf->overrides->pctable); \
+ if (!pce) \
+ return 1; \
+ return function (strvec, &pce->option, file, line_nr); \
+}
+
+#define declare_pc_snprint(option, function) \
+static int \
+snprint_pc_ ## option (struct config *conf, struct strbuf *buff, \
+ const void *data) \
+{ \
+ const struct pcentry *pce = (const struct pcentry *)data; \
+ return function(buff, pce->option); \
+}
+
static int checkint_handler(struct config *conf, vector strvec,
const char *file, int line_nr)
{
@@ -1038,6 +1061,8 @@ 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)
+declare_pc_handler(fast_io_fail, set_undef_off_zero)
+declare_pc_snprint(fast_io_fail, print_undef_off_zero)
static int
set_dev_loss(vector strvec, void *ptr, const char *file, int line_nr)
@@ -1075,6 +1100,8 @@ declare_ovr_handler(dev_loss, set_dev_loss)
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_pc_handler(dev_loss, set_dev_loss)
+declare_pc_snprint(dev_loss, print_dev_loss)
declare_def_handler(eh_deadline, set_undef_off_zero)
declare_def_snprint(eh_deadline, print_undef_off_zero)
@@ -1082,6 +1109,8 @@ 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)
+declare_pc_handler(eh_deadline, set_undef_off_zero)
+declare_pc_snprint(eh_deadline, print_undef_off_zero)
static int
set_pgpolicy(vector strvec, void *ptr, const char *file, int line_nr)
@@ -1889,6 +1918,69 @@ declare_mp_snprint(wwid, print_str)
declare_mp_handler(alias, set_str_noslash)
declare_mp_snprint(alias, print_str)
+
+static int
+protocol_handler(struct config *conf, vector strvec, const char *file,
+ int line_nr)
+{
+ struct pcentry *pce;
+
+ if (!conf->overrides)
+ return 1;
+
+ if (!conf->overrides->pctable &&
+ !(conf->overrides->pctable = vector_alloc()))
+ return 1;
+
+ if (!(pce = alloc_pce()))
+ return 1;
+
+ if (!vector_alloc_slot(conf->overrides->pctable)) {
+ free(pce);
+ return 1;
+ }
+ vector_set_slot(conf->overrides->pctable, pce);
+
+ return 0;
+}
+
+static int
+set_protocol_type(vector strvec, void *ptr, const char *file, int line_nr)
+{
+ int *int_ptr = (int *)ptr;
+ char *buff;
+ int i;
+
+ buff = set_value(strvec);
+
+ if (!buff)
+ return 1;
+
+ for (i = 0; i <= LAST_BUS_PROTOCOL_ID; i++) {
+ if (protocol_name[i] && !strcmp(buff, protocol_name[i])) {
+ *int_ptr = i;
+ break;
+ }
+ }
+ if (i > LAST_BUS_PROTOCOL_ID)
+ condlog(1, "%s line %d, invalid value for type: \"%s\"",
+ file, line_nr, buff);
+
+ free(buff);
+ return 0;
+}
+
+static int
+print_protocol_type(struct strbuf *buff, int type)
+{
+ if (type < 0)
+ return 0;
+ return append_strbuf_quoted(buff, protocol_name[type]);
+}
+
+declare_pc_handler(type, set_protocol_type)
+declare_pc_snprint(type, print_protocol_type)
+
/*
* deprecated handlers
*/
@@ -2130,6 +2222,13 @@ init_keywords(vector keywords)
install_keyword("ghost_delay", &ovr_ghost_delay_handler, &snprint_ovr_ghost_delay);
install_keyword("all_tg_pt", &ovr_all_tg_pt_handler, &snprint_ovr_all_tg_pt);
install_keyword("recheck_wwid", &ovr_recheck_wwid_handler, &snprint_ovr_recheck_wwid);
+ install_keyword_multi("protocol", &protocol_handler, NULL);
+ install_sublevel();
+ install_keyword("type", &pc_type_handler, &snprint_pc_type);
+ install_keyword("fast_io_fail_tmo", &pc_fast_io_fail_handler, &snprint_pc_fast_io_fail);
+ install_keyword("dev_loss_tmo", &pc_dev_loss_handler, &snprint_pc_dev_loss);
+ install_keyword("eh_deadline", &pc_eh_deadline_handler, &snprint_pc_eh_deadline);
+ install_sublevel_end();
install_keyword_root("multipaths", &multipaths_handler);
install_keyword_multi("multipath", &multipath_handler, NULL);
diff --git a/libmultipath/print.c b/libmultipath/print.c
index 0dbd34e4..46e3d32e 100644
--- a/libmultipath/print.c
+++ b/libmultipath/print.c
@@ -1318,6 +1318,52 @@ int snprint_multipath_topology_json (struct strbuf *buff,
return get_strbuf_len(buff) - initial_len;
}
+static int
+snprint_pcentry (const struct config *conf, struct strbuf *buff,
+ const struct pcentry *pce)
+{
+ int i, rc;
+ struct keyword *kw;
+ struct keyword * rootkw;
+ size_t initial_len = get_strbuf_len(buff);
+
+ rootkw = find_keyword(conf->keywords, NULL, "overrides");
+ assert(rootkw && rootkw->sub);
+ rootkw = find_keyword(conf->keywords, rootkw->sub, "protocol");
+ assert(rootkw);
+
+ if ((rc = append_strbuf_str(buff, "\tprotocol {\n")) < 0)
+ return rc;
+
+ iterate_sub_keywords(rootkw, kw, i) {
+ if ((rc = snprint_keyword(buff, "\t\t%k %v\n", kw, pce)) < 0)
+ return rc;
+ }
+
+ if ((rc = append_strbuf_str(buff, "\t}\n")) < 0)
+ return rc;
+ return get_strbuf_len(buff) - initial_len;
+}
+
+static int
+snprint_pctable (const struct config *conf, struct strbuf *buff,
+ const struct _vector *pctable)
+{
+ int i, rc;
+ struct pcentry *pce;
+ struct keyword * rootkw;
+ size_t initial_len = get_strbuf_len(buff);
+
+ rootkw = find_keyword(conf->keywords, NULL, "overrides");
+ assert(rootkw);
+
+ vector_foreach_slot(pctable, pce, i) {
+ if ((rc = snprint_pcentry(conf, buff, pce)) < 0)
+ return rc;
+ }
+ return get_strbuf_len(buff) - initial_len;
+}
+
static int
snprint_hwentry (const struct config *conf,
struct strbuf *buff, const struct hwentry * hwe)
@@ -1472,6 +1518,10 @@ static int snprint_overrides(const struct config *conf, struct strbuf *buff,
if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, NULL)) < 0)
return rc;
}
+
+ if (overrides->pctable &&
+ (rc = snprint_pctable(conf, buff, overrides->pctable)) < 0)
+ return rc;
out:
if ((rc = append_strbuf_str(buff, "}\n")) < 0)
return rc;

@ -1,497 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 13 Apr 2022 23:27:38 -0500
Subject: [PATCH] libmultipath: Set the scsi timeout parameters by path
Instead of dev_loss, fast_io_fail, and eh_deadline belonging to the
multipath structure, have them belong to the path structure. This means
that they are selected per path, and that sysfs_set_scsi_tmo() doesn't
assume that all paths of a multipath device will have the same value.
Currently they will all be the same, but a future patch will make it
possible for paths to have different values based on their protocol.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/configure.c | 5 +-
libmultipath/discovery.c | 158 ++++++++++++++++++++-------------------
libmultipath/discovery.h | 2 +-
libmultipath/propsel.c | 42 +++++------
libmultipath/propsel.h | 6 +-
libmultipath/structs.c | 1 -
libmultipath/structs.h | 6 +-
7 files changed, 112 insertions(+), 108 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 043e4232..70049f47 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -365,9 +365,6 @@ int setup_map(struct multipath *mpp, char **params, struct vectors *vecs)
select_mode(conf, mpp);
select_uid(conf, mpp);
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);
@@ -383,7 +380,7 @@ int setup_map(struct multipath *mpp, char **params, struct vectors *vecs)
select_ghost_delay(conf, mpp);
select_flush_on_last_del(conf, mpp);
- sysfs_set_scsi_tmo(mpp, conf->checkint);
+ sysfs_set_scsi_tmo(conf, mpp);
marginal_pathgroups = conf->marginal_pathgroups;
pthread_cleanup_pop(1);
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index 6fb81c28..bcda8b09 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -596,13 +596,13 @@ sysfs_get_asymmetric_access_state(struct path *pp, char *buff, int buflen)
}
static int
-sysfs_set_eh_deadline(struct multipath *mpp, struct path *pp)
+sysfs_set_eh_deadline(struct path *pp)
{
struct udev_device *hostdev;
char host_name[HOST_NAME_LEN], value[16];
int ret, len;
- if (mpp->eh_deadline == EH_DEADLINE_UNSET)
+ if (pp->eh_deadline == EH_DEADLINE_UNSET)
return 0;
sprintf(host_name, "host%d", pp->sg_id.host_no);
@@ -611,12 +611,12 @@ sysfs_set_eh_deadline(struct multipath *mpp, struct path *pp)
if (!hostdev)
return 1;
- if (mpp->eh_deadline == EH_DEADLINE_OFF)
+ if (pp->eh_deadline == EH_DEADLINE_OFF)
len = sprintf(value, "off");
- else if (mpp->eh_deadline == EH_DEADLINE_ZERO)
+ else if (pp->eh_deadline == EH_DEADLINE_ZERO)
len = sprintf(value, "0");
else
- len = sprintf(value, "%d", mpp->eh_deadline);
+ len = sprintf(value, "%d", pp->eh_deadline);
ret = sysfs_attr_set_value(hostdev, "eh_deadline",
value, len + 1);
@@ -640,8 +640,8 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
unsigned int tmo;
int ret;
- if (mpp->dev_loss == DEV_LOSS_TMO_UNSET &&
- mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)
+ if (pp->dev_loss == DEV_LOSS_TMO_UNSET &&
+ pp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)
return;
sprintf(rport_id, "rport-%d:%d-%d",
@@ -683,14 +683,14 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
* then set fast_io_fail, and _then_ set dev_loss_tmo
* to the correct value.
*/
- if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET &&
- mpp->fast_io_fail != MP_FAST_IO_FAIL_ZERO &&
- mpp->fast_io_fail != MP_FAST_IO_FAIL_OFF) {
+ if (pp->fast_io_fail != MP_FAST_IO_FAIL_UNSET &&
+ pp->fast_io_fail != MP_FAST_IO_FAIL_ZERO &&
+ pp->fast_io_fail != MP_FAST_IO_FAIL_OFF) {
/* Check if we need to temporarily increase dev_loss_tmo */
- if ((unsigned int)mpp->fast_io_fail >= tmo) {
+ if ((unsigned int)pp->fast_io_fail >= tmo) {
/* Increase dev_loss_tmo temporarily */
snprintf(value, sizeof(value), "%u",
- (unsigned int)mpp->fast_io_fail + 1);
+ (unsigned int)pp->fast_io_fail + 1);
ret = sysfs_attr_set_value(rport_dev, "dev_loss_tmo",
value, strlen(value));
if (ret <= 0) {
@@ -704,20 +704,20 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
goto out;
}
}
- } else if (mpp->dev_loss > DEFAULT_DEV_LOSS_TMO &&
- mpp->no_path_retry != NO_PATH_RETRY_QUEUE) {
+ } else if (pp->dev_loss > DEFAULT_DEV_LOSS_TMO &&
+ mpp->no_path_retry != NO_PATH_RETRY_QUEUE) {
condlog(2, "%s: limiting dev_loss_tmo to %d, since "
"fast_io_fail is not set",
rport_id, DEFAULT_DEV_LOSS_TMO);
- mpp->dev_loss = DEFAULT_DEV_LOSS_TMO;
+ pp->dev_loss = DEFAULT_DEV_LOSS_TMO;
}
- if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
- if (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
+ if (pp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
+ if (pp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
sprintf(value, "off");
- else if (mpp->fast_io_fail == MP_FAST_IO_FAIL_ZERO)
+ else if (pp->fast_io_fail == MP_FAST_IO_FAIL_ZERO)
sprintf(value, "0");
else
- snprintf(value, 16, "%u", mpp->fast_io_fail);
+ snprintf(value, 16, "%u", pp->fast_io_fail);
ret = sysfs_attr_set_value(rport_dev, "fast_io_fail_tmo",
value, strlen(value));
if (ret <= 0) {
@@ -728,8 +728,8 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
rport_id, value, -ret);
}
}
- if (mpp->dev_loss != DEV_LOSS_TMO_UNSET) {
- snprintf(value, 16, "%u", mpp->dev_loss);
+ if (pp->dev_loss != DEV_LOSS_TMO_UNSET) {
+ snprintf(value, 16, "%u", pp->dev_loss);
ret = sysfs_attr_set_value(rport_dev, "dev_loss_tmo",
value, strlen(value));
if (ret <= 0) {
@@ -745,15 +745,15 @@ out:
}
static void
-sysfs_set_session_tmo(struct multipath *mpp, struct path *pp)
+sysfs_set_session_tmo(struct path *pp)
{
struct udev_device *session_dev = NULL;
char session_id[64];
char value[11];
- if (mpp->dev_loss != DEV_LOSS_TMO_UNSET)
+ if (pp->dev_loss != DEV_LOSS_TMO_UNSET)
condlog(3, "%s: ignoring dev_loss_tmo on iSCSI", pp->dev);
- if (mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)
+ if (pp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)
return;
sprintf(session_id, "session%d", pp->sg_id.transport_id);
@@ -767,15 +767,15 @@ sysfs_set_session_tmo(struct multipath *mpp, struct path *pp)
condlog(4, "target%d:%d:%d -> %s", pp->sg_id.host_no,
pp->sg_id.channel, pp->sg_id.scsi_id, session_id);
- if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
- if (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF) {
+ if (pp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
+ if (pp->fast_io_fail == MP_FAST_IO_FAIL_OFF) {
condlog(3, "%s: can't switch off fast_io_fail_tmo "
"on iSCSI", pp->dev);
- } else if (mpp->fast_io_fail == MP_FAST_IO_FAIL_ZERO) {
+ } else if (pp->fast_io_fail == MP_FAST_IO_FAIL_ZERO) {
condlog(3, "%s: can't set fast_io_fail_tmo to '0'"
"on iSCSI", pp->dev);
} else {
- snprintf(value, 11, "%u", mpp->fast_io_fail);
+ snprintf(value, 11, "%u", pp->fast_io_fail);
if (sysfs_attr_set_value(session_dev, "recovery_tmo",
value, strlen(value)) <= 0) {
condlog(3, "%s: Failed to set recovery_tmo, "
@@ -788,14 +788,14 @@ sysfs_set_session_tmo(struct multipath *mpp, struct path *pp)
}
static void
-sysfs_set_nexus_loss_tmo(struct multipath *mpp, struct path *pp)
+sysfs_set_nexus_loss_tmo(struct path *pp)
{
struct udev_device *parent, *sas_dev = NULL;
const char *end_dev_id = NULL;
char value[11];
static const char ed_str[] = "end_device-";
- if (!pp->udev || mpp->dev_loss == DEV_LOSS_TMO_UNSET)
+ if (!pp->udev || pp->dev_loss == DEV_LOSS_TMO_UNSET)
return;
for (parent = udev_device_get_parent(pp->udev);
@@ -822,8 +822,8 @@ sysfs_set_nexus_loss_tmo(struct multipath *mpp, struct path *pp)
condlog(4, "target%d:%d:%d -> %s", pp->sg_id.host_no,
pp->sg_id.channel, pp->sg_id.scsi_id, end_dev_id);
- if (mpp->dev_loss != DEV_LOSS_TMO_UNSET) {
- snprintf(value, 11, "%u", mpp->dev_loss);
+ if (pp->dev_loss != DEV_LOSS_TMO_UNSET) {
+ snprintf(value, 11, "%u", pp->dev_loss);
if (sysfs_attr_set_value(sas_dev, "I_T_nexus_loss_timeout",
value, strlen(value)) <= 0)
condlog(3, "%s: failed to update "
@@ -835,47 +835,59 @@ sysfs_set_nexus_loss_tmo(struct multipath *mpp, struct path *pp)
}
int
-sysfs_set_scsi_tmo (struct multipath *mpp, unsigned int checkint)
+sysfs_set_scsi_tmo (struct config *conf, struct multipath *mpp)
{
struct path *pp;
int i;
- unsigned int dev_loss_tmo = mpp->dev_loss;
- struct path *err_path = NULL;
+ unsigned int min_dev_loss = 0;
+ bool warn_dev_loss = false;
+ bool warn_fast_io_fail = false;
if (mpp->no_path_retry > 0) {
uint64_t no_path_retry_tmo =
- (uint64_t)mpp->no_path_retry * checkint;
+ (uint64_t)mpp->no_path_retry * conf->checkint;
if (no_path_retry_tmo > MAX_DEV_LOSS_TMO)
- no_path_retry_tmo = MAX_DEV_LOSS_TMO;
- if (no_path_retry_tmo > dev_loss_tmo)
- dev_loss_tmo = no_path_retry_tmo;
- } else if (mpp->no_path_retry == NO_PATH_RETRY_QUEUE) {
- dev_loss_tmo = MAX_DEV_LOSS_TMO;
- }
- if (mpp->dev_loss != DEV_LOSS_TMO_UNSET &&
- mpp->dev_loss != dev_loss_tmo) {
- condlog(2, "%s: Using dev_loss_tmo=%u instead of %u because of no_path_retry setting",
- mpp->alias, dev_loss_tmo, mpp->dev_loss);
- mpp->dev_loss = dev_loss_tmo;
- }
- if (mpp->dev_loss != DEV_LOSS_TMO_UNSET &&
- mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET &&
- (unsigned int)mpp->fast_io_fail >= mpp->dev_loss) {
- condlog(3, "%s: turning off fast_io_fail (%d is not smaller than dev_loss_tmo)",
- mpp->alias, mpp->fast_io_fail);
- mpp->fast_io_fail = MP_FAST_IO_FAIL_OFF;
- }
- if (mpp->dev_loss == DEV_LOSS_TMO_UNSET &&
- mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET &&
- mpp->eh_deadline == EH_DEADLINE_UNSET)
- return 0;
+ min_dev_loss = MAX_DEV_LOSS_TMO;
+ else
+ min_dev_loss = no_path_retry_tmo;
+ } else if (mpp->no_path_retry == NO_PATH_RETRY_QUEUE)
+ min_dev_loss = MAX_DEV_LOSS_TMO;
vector_foreach_slot(mpp->paths, pp, i) {
- if (pp->bus != SYSFS_BUS_SCSI) {
- if (!err_path)
- err_path = pp;
+ select_fast_io_fail(conf, pp);
+ select_dev_loss(conf, pp);
+ select_eh_deadline(conf, pp);
+
+ if (pp->dev_loss == DEV_LOSS_TMO_UNSET &&
+ pp->fast_io_fail == MP_FAST_IO_FAIL_UNSET &&
+ pp->eh_deadline == EH_DEADLINE_UNSET)
+ continue;
+
+ if (pp->bus != SYSFS_BUS_SCSI)
+ continue;
+
+ sysfs_set_eh_deadline(pp);
+
+ if (pp->dev_loss == DEV_LOSS_TMO_UNSET &&
+ pp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)
continue;
+
+ if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP &&
+ pp->sg_id.proto_id != SCSI_PROTOCOL_ISCSI &&
+ pp->sg_id.proto_id != SCSI_PROTOCOL_SAS)
+ continue;
+
+ if (pp->dev_loss != DEV_LOSS_TMO_UNSET &&
+ pp->dev_loss < min_dev_loss) {
+ warn_dev_loss = true;
+ pp->dev_loss = min_dev_loss;
+ }
+ if (pp->dev_loss != DEV_LOSS_TMO_UNSET &&
+ pp->fast_io_fail > 0 &&
+ (unsigned int)pp->fast_io_fail >= pp->dev_loss) {
+ warn_fast_io_fail = true;
+ pp->fast_io_fail = MP_FAST_IO_FAIL_OFF;
}
switch (pp->sg_id.proto_id) {
@@ -883,25 +895,21 @@ sysfs_set_scsi_tmo (struct multipath *mpp, unsigned int checkint)
sysfs_set_rport_tmo(mpp, pp);
break;
case SCSI_PROTOCOL_ISCSI:
- sysfs_set_session_tmo(mpp, pp);
+ sysfs_set_session_tmo(pp);
break;
case SCSI_PROTOCOL_SAS:
- sysfs_set_nexus_loss_tmo(mpp, pp);
+ sysfs_set_nexus_loss_tmo(pp);
break;
default:
- if (!err_path)
- err_path = pp;
+ break;
}
- sysfs_set_eh_deadline(mpp, pp);
- }
-
- if (err_path) {
- STRBUF_ON_STACK(proto_buf);
-
- snprint_path_protocol(&proto_buf, err_path);
- condlog(2, "%s: setting dev_loss_tmo is unsupported for protocol %s",
- mpp->alias, get_strbuf_str(&proto_buf));
}
+ if (warn_dev_loss)
+ condlog(2, "%s: Raising dev_loss_tmo to %u because of no_path_retry setting",
+ mpp->alias, min_dev_loss);
+ if (warn_fast_io_fail)
+ condlog(3, "%s: turning off fast_io_fail (not smaller than dev_loss_tmo)",
+ mpp->alias);
return 0;
}
diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h
index a5446b4d..b6eea258 100644
--- a/libmultipath/discovery.h
+++ b/libmultipath/discovery.h
@@ -42,7 +42,7 @@ int alloc_path_with_pathinfo (struct config *conf, struct udev_device *udevice,
int store_pathinfo (vector pathvec, struct config *conf,
struct udev_device *udevice, int flag,
struct path **pp_ptr);
-int sysfs_set_scsi_tmo (struct multipath *mpp, unsigned int checkint);
+int sysfs_set_scsi_tmo (struct config *conf, struct multipath *mpp);
int sysfs_get_timeout(const struct path *pp, unsigned int *timeout);
int sysfs_get_host_pci_name(const struct path *pp, char *pci_name);
int sysfs_get_iscsi_ip_address(const struct path *pp, char *ip_address);
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
index 677ab9e1..f146fe64 100644
--- a/libmultipath/propsel.c
+++ b/libmultipath/propsel.c
@@ -770,53 +770,53 @@ int select_minio(struct config *conf, struct multipath *mp)
return select_minio_bio(conf, mp);
}
-int select_fast_io_fail(struct config *conf, struct multipath *mp)
+int select_fast_io_fail(struct config *conf, struct path *pp)
{
const char *origin;
STRBUF_ON_STACK(buff);
- mp_set_ovr(fast_io_fail);
- mp_set_hwe(fast_io_fail);
- mp_set_conf(fast_io_fail);
- mp_set_default(fast_io_fail, DEFAULT_FAST_IO_FAIL);
+ pp_set_ovr(fast_io_fail);
+ pp_set_hwe(fast_io_fail);
+ pp_set_conf(fast_io_fail);
+ pp_set_default(fast_io_fail, DEFAULT_FAST_IO_FAIL);
out:
- print_undef_off_zero(&buff, mp->fast_io_fail);
- condlog(3, "%s: fast_io_fail_tmo = %s %s", mp->alias,
+ print_undef_off_zero(&buff, pp->fast_io_fail);
+ condlog(3, "%s: fast_io_fail_tmo = %s %s", pp->dev,
get_strbuf_str(&buff), origin);
return 0;
}
-int select_dev_loss(struct config *conf, struct multipath *mp)
+int select_dev_loss(struct config *conf, struct path *pp)
{
const char *origin;
STRBUF_ON_STACK(buff);
- mp_set_ovr(dev_loss);
- mp_set_hwe(dev_loss);
- mp_set_conf(dev_loss);
- mp->dev_loss = DEV_LOSS_TMO_UNSET;
+ pp_set_ovr(dev_loss);
+ pp_set_hwe(dev_loss);
+ pp_set_conf(dev_loss);
+ pp->dev_loss = DEV_LOSS_TMO_UNSET;
return 0;
out:
- print_dev_loss(&buff, mp->dev_loss);
- condlog(3, "%s: dev_loss_tmo = %s %s", mp->alias,
+ print_dev_loss(&buff, pp->dev_loss);
+ condlog(3, "%s: dev_loss_tmo = %s %s", pp->dev,
get_strbuf_str(&buff), origin);
return 0;
}
-int select_eh_deadline(struct config *conf, struct multipath *mp)
+int select_eh_deadline(struct config *conf, struct path *pp)
{
const char *origin;
STRBUF_ON_STACK(buff);
- mp_set_ovr(eh_deadline);
- mp_set_hwe(eh_deadline);
- mp_set_conf(eh_deadline);
- mp->eh_deadline = EH_DEADLINE_UNSET;
+ pp_set_ovr(eh_deadline);
+ pp_set_hwe(eh_deadline);
+ pp_set_conf(eh_deadline);
+ pp->eh_deadline = EH_DEADLINE_UNSET;
/* not changing sysfs in default cause, so don't print anything */
return 0;
out:
- print_undef_off_zero(&buff, mp->eh_deadline);
- condlog(3, "%s: eh_deadline = %s %s", mp->alias,
+ print_undef_off_zero(&buff, pp->eh_deadline);
+ condlog(3, "%s: eh_deadline = %s %s", pp->dev,
get_strbuf_str(&buff), origin);
return 0;
}
diff --git a/libmultipath/propsel.h b/libmultipath/propsel.h
index 72a7e33c..152ca44c 100644
--- a/libmultipath/propsel.h
+++ b/libmultipath/propsel.h
@@ -16,9 +16,9 @@ int select_minio(struct config *conf, struct multipath *mp);
int select_mode(struct config *conf, struct multipath *mp);
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_fast_io_fail(struct config *conf, struct path *pp);
+int select_dev_loss(struct config *conf, struct path *pp);
+int select_eh_deadline(struct config *conf, struct path *pp);
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.c b/libmultipath/structs.c
index d20e1eea..acd4cbeb 100644
--- a/libmultipath/structs.c
+++ b/libmultipath/structs.c
@@ -246,7 +246,6 @@ alloc_multipath (void)
mpp->bestpg = 1;
mpp->mpcontext = NULL;
mpp->no_path_retry = NO_PATH_RETRY_UNDEF;
- mpp->fast_io_fail = MP_FAST_IO_FAIL_UNSET;
dm_multipath_to_gen(mpp)->ops = &dm_gen_multipath_ops;
}
return mpp;
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index 618ff4fb..8a07d470 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -340,6 +340,9 @@ struct path {
int marginal;
int vpd_vendor_id;
int recheck_wwid;
+ int fast_io_fail;
+ unsigned int dev_loss;
+ int eh_deadline;
/* configlet pointers */
vector hwe;
struct gen_path generic_path;
@@ -367,7 +370,6 @@ struct multipath {
int minio;
int flush_on_last_del;
int attribute_flags;
- int fast_io_fail;
int retain_hwhandler;
int deferred_remove;
bool in_recovery;
@@ -385,8 +387,6 @@ struct multipath {
int needs_paths_uevent;
int ghost_delay;
int ghost_delay_tick;
- unsigned int dev_loss;
- int eh_deadline;
uid_t uid;
gid_t gid;
mode_t mode;

@ -1,84 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 13 Apr 2022 23:27:39 -0500
Subject: [PATCH] libmultipath: check the overrides pctable for path variables
Paths will now also check the pctable when checking for attribtes that
exists in both the overrides section and the protocol subsection. Values
in a matching pcentry will be used in preference to values in the
overrides hwentry.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/propsel.c | 29 ++++++++++++++++++++++++++---
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
index f146fe64..2b47f5f8 100644
--- a/libmultipath/propsel.c
+++ b/libmultipath/propsel.c
@@ -80,6 +80,8 @@ static const char conf_origin[] =
"(setting: multipath.conf defaults/devices section)";
static const char overrides_origin[] =
"(setting: multipath.conf overrides section)";
+static const char overrides_pce_origin[] =
+ "(setting: multipath.conf overrides protocol section)";
static const char cmdline_origin[] =
"(setting: multipath command line [-p] flag)";
static const char autodetect_origin[] =
@@ -147,6 +149,27 @@ do { \
} \
} while (0)
+#define pp_set_ovr_pce(var) \
+do { \
+ struct pcentry *_pce; \
+ int _i; \
+ \
+ if (conf->overrides) { \
+ vector_foreach_slot(conf->overrides->pctable, _pce, _i) { \
+ if (_pce->type == (int)bus_protocol_id(pp) && _pce->var) { \
+ pp->var = _pce->var; \
+ origin = overrides_pce_origin; \
+ goto out; \
+ } \
+ } \
+ if (conf->overrides->var) { \
+ pp->var = conf->overrides->var; \
+ origin = overrides_origin; \
+ goto out; \
+ } \
+ } \
+} while (0)
+
int select_mode(struct config *conf, struct multipath *mp)
{
const char *origin;
@@ -775,7 +798,7 @@ int select_fast_io_fail(struct config *conf, struct path *pp)
const char *origin;
STRBUF_ON_STACK(buff);
- pp_set_ovr(fast_io_fail);
+ pp_set_ovr_pce(fast_io_fail);
pp_set_hwe(fast_io_fail);
pp_set_conf(fast_io_fail);
pp_set_default(fast_io_fail, DEFAULT_FAST_IO_FAIL);
@@ -791,7 +814,7 @@ int select_dev_loss(struct config *conf, struct path *pp)
const char *origin;
STRBUF_ON_STACK(buff);
- pp_set_ovr(dev_loss);
+ pp_set_ovr_pce(dev_loss);
pp_set_hwe(dev_loss);
pp_set_conf(dev_loss);
pp->dev_loss = DEV_LOSS_TMO_UNSET;
@@ -808,7 +831,7 @@ int select_eh_deadline(struct config *conf, struct path *pp)
const char *origin;
STRBUF_ON_STACK(buff);
- pp_set_ovr(eh_deadline);
+ pp_set_ovr_pce(eh_deadline);
pp_set_hwe(eh_deadline);
pp_set_conf(eh_deadline);
pp->eh_deadline = EH_DEADLINE_UNSET;

@ -1,33 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 13 Apr 2022 23:27:40 -0500
Subject: [PATCH] libmultipath: fix eh_deadline documentation
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
multipath/multipath.conf.5 | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 58ad5c9c..47404545 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1637,6 +1637,8 @@ section:
.TP
.B dev_loss_tmo
.TP
+.B eh_deadline
+.TP
.B flush_on_last_del
.TP
.B user_friendly_names
@@ -1723,6 +1725,8 @@ the values are taken from the \fIdevices\fR or \fIdefaults\fR sections:
.TP
.B dev_loss_tmo
.TP
+.B eh_deadline
+.TP
.B user_friendly_names
.TP
.B retain_attached_hw_handler

@ -1,54 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 13 Apr 2022 23:27:41 -0500
Subject: [PATCH] libmultipath: Add documentation for the protocol subsection
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
multipath/multipath.conf.5 | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 47404545..f7de5140 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1765,6 +1765,38 @@ the values are taken from the \fIdevices\fR or \fIdefaults\fR sections:
.RE
.PD
.LP
+The overrides section also recognizes the optional \fIprotocol\fR subsection,
+and can contain multiple protocol subsections. Path devices are matched against
+the protocol subsection using the mandatory \fItype\fR attribute. Attributes
+in a matching protocol subsection take precedence over attributes in the rest
+of the overrides section. If there are multiple matching protocol subsections,
+later entries take precedence.
+.TP
+.B protocol subsection
+The protocol subsection recognizes the following mandatory attribute:
+.RS
+.TP
+.B type
+The protocol string of the path device. The possible values are \fIscsi:fcp\fR,
+\fIscsi:spi\fR, \fIscsi:ssa\fR, \fIscsi:sbp\fR, \fIscsi:srp\fR,
+\fIscsi:iscsi\fR, \fIscsi:sas\fR, \fIscsi:adt\fR, \fIscsi:ata\fR,
+\fIscsi:unspec\fR, \fIccw\fR, \fIcciss\fR, \fInvme\fR, and \fIundef\fR. This is
+\fBnot\fR a regular expression. the path device protcol string must match
+exactly. The protocol that a path is using can be viewed by running
+\fBmultipathd show paths format "%d %P"\fR
+.LP
+The following attributes are optional; if not set, the default values are taken
+from the \fIoverrides\fR, \fIdevices\fR, or \fIdefaults\fR section:
+.sp 1
+.PD .1v
+.RS
+.TP
+.B fast_io_fail_tmo
+.TP
+.B dev_loss_tmo
+.TP
+.B eh_deadline
+.PD
.
.
.\" ----------------------------------------------------------------------------

@ -1,47 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 14 Apr 2022 16:11:10 -0500
Subject: [PATCH] libmultipath: use symbolic value for invalid pcentry
Suggested-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/config.c | 4 ++--
libmultipath/config.h | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 8b0e1f72..61b0dd51 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -384,7 +384,7 @@ alloc_pce (void)
{
struct pcentry *pce = (struct pcentry *)
calloc(1, sizeof(struct pcentry));
- pce->type = -1;
+ pce->type = PCE_INVALID;
return pce;
}
@@ -643,7 +643,7 @@ validate_pctable(struct hwentry *ovr, int idx, const char *table_desc)
return;
vector_foreach_slot_after(ovr->pctable, pce, idx) {
- if (pce->type < 0) {
+ if (pce->type == PCE_INVALID) {
condlog(0, "protocol section in %s missing type",
table_desc);
vector_del_slot(ovr->pctable, idx--);
diff --git a/libmultipath/config.h b/libmultipath/config.h
index 57992604..c1e18363 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -41,6 +41,7 @@ enum force_reload_types {
FORCE_RELOAD_WEAK,
};
+#define PCE_INVALID -1
struct pcentry {
int type;
int fast_io_fail;

@ -1,28 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 29 Apr 2022 15:57:12 -0500
Subject: [PATCH] updated HPE MSA builtin config
Make the config better align to MSA 4th, 5th and 6th Generation systems.
Cc: Jon.Paul@hpe.com
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/hwtable.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index a8ba28e3..d7c487b1 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -182,8 +182,8 @@ static struct hwentry default_hw[] = {
},
{
/* MSA 1040, 1050, 1060, 2040, 2050 and 2060 families */
- .vendor = "HP",
- .product = "MSA [12]0[456]0 SA[NS]",
+ .vendor = "(HP|HPE)",
+ .product = "MSA [12]0[456]0 (SAN|SAS|FC|iSCSI)",
.pgpolicy = GROUP_BY_PRIO,
.pgfailback = -FAILBACK_IMMEDIATE,
.no_path_retry = 18,

@ -1,30 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 10 May 2022 14:17:22 -0500
Subject: [PATCH] libmultipath: unset detect_checker for clariion / Unity
arrays
Dell EMC would like to always use the emc_clariion checker. Currently
detect_checker will switch the checker to TUR for Unity arrays.
This can cause problems on some setups with replicated Unity LUNs,
which are handled correctly the the emc_checker, but not the TUR
checker.
Cc: vincent.chen1@dell.com
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/hwtable.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index d7c487b1..22ff1881 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -343,6 +343,7 @@ static struct hwentry default_hw[] = {
.no_path_retry = (300 / DEFAULT_CHECKINT),
.checker_name = EMC_CLARIION,
.prio_name = PRIO_EMC,
+ .detect_checker = DETECT_CHECKER_OFF,
},
{
/* Invista / VPLEX */

@ -1,26 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bastian Germann <bage@debian.org>
Date: Thu, 14 Oct 2021 00:34:33 +0200
Subject: [PATCH] multipathd: Add missing ctype include
In uxclnt.c, there are isspace calls. Add an explicit include.
Signed-off-by: Bastian Germann <bage@debian.org>
Reviewed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/uxclnt.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/multipathd/uxclnt.c b/multipathd/uxclnt.c
index a76f8e29..f16a7309 100644
--- a/multipathd/uxclnt.c
+++ b/multipathd/uxclnt.c
@@ -8,6 +8,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
+#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>

@ -1,103 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Fri, 12 Aug 2022 18:58:15 +0200
Subject: [PATCH] multipathd: replace libreadline with libedit
Linking multipathd with libreadline may cause a license conflict,
because libreadline is licensed under GPL-3.0-or-later, and
libmultipath contains several files under GPL-2.0.
See:
https://github.com/opensvc/multipath-tools/issues/36
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=979095
https://www.gnu.org/licenses/gpl-faq.html#AllCompatibility
Replace the readline functionality with libedit, which comes under
a BSD license. The readline library can still be enabled (e.g. for
binaries not intended to be distributed) by running
"make READLINE=libreadline".
Signed-off-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile.inc | 5 +++++
multipathd/Makefile | 12 +++++++++++-
multipathd/cli.c | 5 +++++
multipathd/uxclnt.c | 6 ++++++
4 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/Makefile.inc b/Makefile.inc
index 688c4599..05027703 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -14,6 +14,11 @@
#
# Uncomment to disable dmevents polling support
# ENABLE_DMEVENTS_POLL = 0
+#
+# Readline library to use, libedit or libreadline
+# Caution: Using libreadline may make the multipathd binary undistributable,
+# see https://github.com/opensvc/multipath-tools/issues/36
+READLINE = libedit
PKGCONFIG ?= pkg-config
diff --git a/multipathd/Makefile b/multipathd/Makefile
index cd6f7e6d..00342464 100644
--- a/multipathd/Makefile
+++ b/multipathd/Makefile
@@ -19,7 +19,17 @@ CFLAGS += $(BIN_CFLAGS) -I$(multipathdir) -I$(mpathpersistdir) \
LDFLAGS += $(BIN_LDFLAGS)
LIBDEPS += -L$(multipathdir) -lmultipath -L$(mpathpersistdir) -lmpathpersist \
-L$(mpathcmddir) -lmpathcmd -ludev -ldl -lurcu -lpthread \
- -ldevmapper -lreadline
+ -ldevmapper
+
+ifeq ($(READLINE),libedit)
+CFLAGS += -DUSE_LIBEDIT
+LIBDEPS += -ledit
+endif
+ifeq ($(READLINE),libreadline)
+CFLAGS += -DUSE_LIBREADLINE
+LIBDEPS += -lreadline
+endif
+
CFLAGS += $(shell $(PKGCONFIG) --modversion liburcu 2>/dev/null | \
awk -F. '{ printf("-DURCU_VERSION=0x%06x", 256 * ( 256 * $$1 + $$2) + $$3); }')
diff --git a/multipathd/cli.c b/multipathd/cli.c
index 4d6c37c9..cc547e67 100644
--- a/multipathd/cli.c
+++ b/multipathd/cli.c
@@ -11,7 +11,12 @@
#include "parser.h"
#include "util.h"
#include "version.h"
+#ifdef USE_LIBEDIT
+#include <editline/readline.h>
+#endif
+#ifdef USE_LIBREADLINE
#include <readline/readline.h>
+#endif
#include "mpath_cmd.h"
#include "cli.h"
diff --git a/multipathd/uxclnt.c b/multipathd/uxclnt.c
index f16a7309..2c17d8fc 100644
--- a/multipathd/uxclnt.c
+++ b/multipathd/uxclnt.c
@@ -16,8 +16,14 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <poll.h>
+
+#ifdef USE_LIBEDIT
+#include <editline/readline.h>
+#endif
+#ifdef USE_LIBREADLINE
#include <readline/readline.h>
#include <readline/history.h>
+#endif
#include "mpath_cmd.h"
#include "uxsock.h"

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 5 Aug 2022 18:16:03 -0500
Subject: [PATCH] multipath: fix systemd timers in the initramfs
The systemd timers created for "find_multipaths smart" conflict with
shutdown.target, but not with initrd-cleanup.service. This can make
these timers trigger after the inirtd has started shutting down,
restarting multipathd (which then stops initrd-cleanup.service, since it
conflicts). To avoid this, make sure the timers and the unit they
trigger conflict with inird-cleanup.service. Also don't make them start
multipathd. "multipath -u" will not return "maybe" if multipathd isn't
running or set to run, and since we no longer wait for udev-settle,
multipathd starts up pretty quickly, so it shouldn't be a problem to
not trigger it here.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
multipath/multipath.rules | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/multipath/multipath.rules b/multipath/multipath.rules
index 0486bf70..68c30644 100644
--- a/multipath/multipath.rules
+++ b/multipath/multipath.rules
@@ -72,7 +72,7 @@ ENV{.SAVED_FM_WAIT_UNTIL}=="?*", GOTO="pretend_mpath"
#
# We must trigger an "add" event because LVM2 will only act on those.
-RUN+="/usr/bin/systemd-run --unit=cancel-multipath-wait-$kernel --description 'cancel waiting for multipath siblings of $kernel' --no-block --timer-property DefaultDependencies=no --timer-property Conflicts=shutdown.target --timer-property Before=shutdown.target --timer-property AccuracySec=500ms --property DefaultDependencies=no --property Conflicts=shutdown.target --property Before=shutdown.target --property Wants=multipathd.service --property After=multipathd.service --on-active=$env{FIND_MULTIPATHS_WAIT_UNTIL} /usr/bin/udevadm trigger --action=add $sys$devpath"
+RUN+="/usr/bin/systemd-run --unit=cancel-multipath-wait-$kernel --description 'cancel waiting for multipath siblings of $kernel' --no-block --timer-property DefaultDependencies=no --timer-property Conflicts=shutdown.target --timer-property Before=shutdown.target --timer-property Conflicts=initrd-cleanup.service --timer-property Before=initrd-cleanup.service --timer-property AccuracySec=500ms --property DefaultDependencies=no --property Conflicts=shutdown.target --property Before=shutdown.target --property Conflicts=initrd-cleanup.service --property Before=initrd-cleanup.service --on-active=$env{FIND_MULTIPATHS_WAIT_UNTIL} /usr/bin/udevadm trigger --action=add $sys$devpath"
LABEL="pretend_mpath"
ENV{DM_MULTIPATH_DEVICE_PATH}="1"

@ -1,90 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 9 Aug 2022 16:46:26 -0500
Subject: [PATCH] multipathd: factor out the code to flush a map with no paths
The code to flush a multipath device because all of its paths have
been removed will be used by another caller, so factor it out of
ev_remove_path().
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
multipathd/main.c | 56 ++++++++++++++++++++++++-----------------------
1 file changed, 29 insertions(+), 27 deletions(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index ed2515e5..b00eae3f 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -488,6 +488,30 @@ int update_multipath (struct vectors *vecs, char *mapname, int reset)
return 0;
}
+static bool
+flush_map_nopaths(struct multipath *mpp, struct vectors *vecs) {
+ char alias[WWID_SIZE];
+
+ /*
+ * 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);
+ 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->alias, 0);
+ }
+ if (!flush_map(mpp, vecs, 1)) {
+ condlog(2, "%s: removed map after removing all paths", alias);
+ return true;
+ }
+ return false;
+}
+
static int
update_map (struct multipath *mpp, struct vectors *vecs, int new_map)
{
@@ -1247,34 +1271,12 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map)
vector_del_slot(mpp->paths, i);
/*
- * remove the map IF removing the last path
+ * remove the map IF removing the last path. If
+ * flush_map_nopaths succeeds, the path has been removed.
*/
- if (VECTOR_SIZE(mpp->paths) == 0) {
- char alias[WWID_SIZE];
-
- /*
- * 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);
- 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->alias, 0);
- }
- if (!flush_map(mpp, vecs, 1)) {
- condlog(2, "%s: removed map after"
- " removing all paths",
- alias);
- /* flush_map() has freed the path */
- goto out;
- }
- /*
- * Not an error, continue
- */
- }
+ if (VECTOR_SIZE(mpp->paths) == 0 &&
+ flush_map_nopaths(mpp, vecs))
+ goto out;
if (setup_map(mpp, &params, vecs)) {
condlog(0, "%s: failed to setup map for"

@ -1,47 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 9 Aug 2022 16:46:27 -0500
Subject: [PATCH] libmultipath: return success if we raced to remove a map and
lost
_dm_flush_map() was returning failure if it failed to remove a map,
even if that was because the map had already been removed. Return
success in this case.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/devmapper.c | 4 ++++
multipathd/main.c | 4 ----
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 1ff75c81..4b2e8a15 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -1104,6 +1104,10 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove,
}
condlog(4, "multipath map %s removed", mapname);
return 0;
+ } else if (dm_is_mpath(mapname) != 1) {
+ condlog(4, "multipath map %s removed externally",
+ mapname);
+ return 0; /*we raced with someone else removing it */
} else {
condlog(2, "failed to remove multipath map %s",
mapname);
diff --git a/multipathd/main.c b/multipathd/main.c
index b00eae3f..68ee067b 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -685,10 +685,6 @@ flush_map(struct multipath * mpp, struct vectors * vecs, int nopaths)
* the spurious uevent we may generate with the dm_flush_map call below
*/
if (r) {
- /*
- * May not really be an error -- if the map was already flushed
- * from the device mapper by dmsetup(8) for instance.
- */
if (r == 1)
condlog(0, "%s: can't flush", mpp->alias);
else {

@ -1,36 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 9 Aug 2022 16:46:28 -0500
Subject: [PATCH] multipathd: Handle losing all path in update_map
Its possible that when a multipath device is being updated, it will end
up that all the paths for it are gone. This can happen if paths are
added and then removed again before multipathd processes the uevent for
the newly created multipath device. In this case multipathd wasn't
taking the proper action for the case where all the paths had been
removed. If flush_on_last_del was set, multipathd wasn't disabling
flushing and if deferred_remove was set, it wasn't doing a deferred
remove. Multipathd should call flush_map_nopaths(), just like
ev_remove_path() does when the last path is removed.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
multipathd/main.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/multipathd/main.c b/multipathd/main.c
index 68ee067b..d2c48d3b 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -529,6 +529,10 @@ retry:
goto fail;
}
verify_paths(mpp);
+ if (VECTOR_SIZE(mpp->paths) == 0 &&
+ flush_map_nopaths(mpp, vecs))
+ return 1;
+
mpp->action = ACT_RELOAD;
if (mpp->prflag) {

@ -1,153 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 8 Sep 2022 11:54:49 -0500
Subject: [PATCH] multipathd: ignore duplicated multipathd command keys
multipath adds rather than or-s the values of command keys. Fix this.
Also, return an invalid fingerprint if a key is used more than once.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/cli.c | 8 ++--
multipathd/main.c | 106 +++++++++++++++++++++++-----------------------
2 files changed, 58 insertions(+), 56 deletions(-)
diff --git a/multipathd/cli.c b/multipathd/cli.c
index cc547e67..eb2e8c1d 100644
--- a/multipathd/cli.c
+++ b/multipathd/cli.c
@@ -342,9 +342,11 @@ fingerprint(vector vec)
if (!vec)
return 0;
- vector_foreach_slot(vec, kw, i)
- fp += kw->code;
-
+ vector_foreach_slot(vec, kw, i) {
+ if (fp & kw->code)
+ return (uint64_t)-1;
+ fp |= kw->code;
+ }
return fp;
}
diff --git a/multipathd/main.c b/multipathd/main.c
index d2c48d3b..a098f3c2 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1696,62 +1696,62 @@ uxlsnrloop (void * ap)
/* Tell main thread that thread has started */
post_config_state(DAEMON_CONFIGURE);
- set_handler_callback(LIST+PATHS, cli_list_paths);
- set_handler_callback(LIST+PATHS+FMT, cli_list_paths_fmt);
- set_handler_callback(LIST+PATHS+RAW+FMT, cli_list_paths_raw);
- set_handler_callback(LIST+PATH, cli_list_path);
- set_handler_callback(LIST+MAPS, cli_list_maps);
- set_handler_callback(LIST+STATUS, cli_list_status);
- set_unlocked_handler_callback(LIST+DAEMON, cli_list_daemon);
- set_handler_callback(LIST+MAPS+STATUS, cli_list_maps_status);
- set_handler_callback(LIST+MAPS+STATS, cli_list_maps_stats);
- set_handler_callback(LIST+MAPS+FMT, cli_list_maps_fmt);
- set_handler_callback(LIST+MAPS+RAW+FMT, cli_list_maps_raw);
- set_handler_callback(LIST+MAPS+TOPOLOGY, cli_list_maps_topology);
- set_handler_callback(LIST+TOPOLOGY, cli_list_maps_topology);
- set_handler_callback(LIST+MAPS+JSON, cli_list_maps_json);
- set_handler_callback(LIST+MAP+TOPOLOGY, cli_list_map_topology);
- set_handler_callback(LIST+MAP+FMT, cli_list_map_fmt);
- set_handler_callback(LIST+MAP+RAW+FMT, cli_list_map_fmt);
- set_handler_callback(LIST+MAP+JSON, cli_list_map_json);
- set_handler_callback(LIST+CONFIG+LOCAL, cli_list_config_local);
- set_handler_callback(LIST+CONFIG, cli_list_config);
- set_handler_callback(LIST+BLACKLIST, cli_list_blacklist);
- set_handler_callback(LIST+DEVICES, cli_list_devices);
- set_handler_callback(LIST+WILDCARDS, cli_list_wildcards);
- set_handler_callback(RESET+MAPS+STATS, cli_reset_maps_stats);
- set_handler_callback(RESET+MAP+STATS, cli_reset_map_stats);
- set_handler_callback(ADD+PATH, cli_add_path);
- 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_handler_callback(LIST|PATHS, cli_list_paths);
+ set_handler_callback(LIST|PATHS|FMT, cli_list_paths_fmt);
+ set_handler_callback(LIST|PATHS|RAW|FMT, cli_list_paths_raw);
+ set_handler_callback(LIST|PATH, cli_list_path);
+ set_handler_callback(LIST|MAPS, cli_list_maps);
+ set_handler_callback(LIST|STATUS, cli_list_status);
+ set_unlocked_handler_callback(LIST|DAEMON, cli_list_daemon);
+ set_handler_callback(LIST|MAPS|STATUS, cli_list_maps_status);
+ set_handler_callback(LIST|MAPS|STATS, cli_list_maps_stats);
+ set_handler_callback(LIST|MAPS|FMT, cli_list_maps_fmt);
+ set_handler_callback(LIST|MAPS|RAW|FMT, cli_list_maps_raw);
+ set_handler_callback(LIST|MAPS|TOPOLOGY, cli_list_maps_topology);
+ set_handler_callback(LIST|TOPOLOGY, cli_list_maps_topology);
+ set_handler_callback(LIST|MAPS|JSON, cli_list_maps_json);
+ set_handler_callback(LIST|MAP|TOPOLOGY, cli_list_map_topology);
+ set_handler_callback(LIST|MAP|FMT, cli_list_map_fmt);
+ set_handler_callback(LIST|MAP|RAW|FMT, cli_list_map_fmt);
+ set_handler_callback(LIST|MAP|JSON, cli_list_map_json);
+ set_handler_callback(LIST|CONFIG|LOCAL, cli_list_config_local);
+ set_handler_callback(LIST|CONFIG, cli_list_config);
+ set_handler_callback(LIST|BLACKLIST, cli_list_blacklist);
+ set_handler_callback(LIST|DEVICES, cli_list_devices);
+ set_handler_callback(LIST|WILDCARDS, cli_list_wildcards);
+ set_handler_callback(RESET|MAPS|STATS, cli_reset_maps_stats);
+ set_handler_callback(RESET|MAP|STATS, cli_reset_map_stats);
+ set_handler_callback(ADD|PATH, cli_add_path);
+ 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);
- set_handler_callback(RESUME+MAP, cli_resume);
- set_handler_callback(RESIZE+MAP, cli_resize);
- set_handler_callback(RELOAD+MAP, cli_reload);
- set_handler_callback(RESET+MAP, cli_reassign);
- set_handler_callback(REINSTATE+PATH, cli_reinstate);
- set_handler_callback(FAIL+PATH, cli_fail);
- set_handler_callback(DISABLEQ+MAP, cli_disable_queueing);
- set_handler_callback(RESTOREQ+MAP, cli_restore_queueing);
- set_handler_callback(DISABLEQ+MAPS, cli_disable_all_queueing);
- set_handler_callback(RESTOREQ+MAPS, cli_restore_all_queueing);
+ set_handler_callback(SUSPEND|MAP, cli_suspend);
+ set_handler_callback(RESUME|MAP, cli_resume);
+ set_handler_callback(RESIZE|MAP, cli_resize);
+ set_handler_callback(RELOAD|MAP, cli_reload);
+ set_handler_callback(RESET|MAP, cli_reassign);
+ set_handler_callback(REINSTATE|PATH, cli_reinstate);
+ set_handler_callback(FAIL|PATH, cli_fail);
+ set_handler_callback(DISABLEQ|MAP, cli_disable_queueing);
+ set_handler_callback(RESTOREQ|MAP, cli_restore_queueing);
+ set_handler_callback(DISABLEQ|MAPS, cli_disable_all_queueing);
+ set_handler_callback(RESTOREQ|MAPS, cli_restore_all_queueing);
set_unlocked_handler_callback(QUIT, cli_quit);
set_unlocked_handler_callback(SHUTDOWN, cli_shutdown);
- set_handler_callback(GETPRSTATUS+MAP, cli_getprstatus);
- set_handler_callback(SETPRSTATUS+MAP, cli_setprstatus);
- set_handler_callback(UNSETPRSTATUS+MAP, cli_unsetprstatus);
- set_handler_callback(FORCEQ+DAEMON, cli_force_no_daemon_q);
- set_handler_callback(RESTOREQ+DAEMON, cli_restore_no_daemon_q);
- set_handler_callback(GETPRKEY+MAP, cli_getprkey);
- set_handler_callback(SETPRKEY+MAP+KEY, cli_setprkey);
- set_handler_callback(UNSETPRKEY+MAP, cli_unsetprkey);
- set_handler_callback(SETMARGINAL+PATH, cli_set_marginal);
- set_handler_callback(UNSETMARGINAL+PATH, cli_unset_marginal);
- set_handler_callback(UNSETMARGINAL+MAP, cli_unset_all_marginal);
+ set_handler_callback(GETPRSTATUS|MAP, cli_getprstatus);
+ set_handler_callback(SETPRSTATUS|MAP, cli_setprstatus);
+ set_handler_callback(UNSETPRSTATUS|MAP, cli_unsetprstatus);
+ set_handler_callback(FORCEQ|DAEMON, cli_force_no_daemon_q);
+ set_handler_callback(RESTOREQ|DAEMON, cli_restore_no_daemon_q);
+ set_handler_callback(GETPRKEY|MAP, cli_getprkey);
+ set_handler_callback(SETPRKEY|MAP|KEY, cli_setprkey);
+ set_handler_callback(UNSETPRKEY|MAP, cli_unsetprkey);
+ set_handler_callback(SETMARGINAL|PATH, cli_set_marginal);
+ set_handler_callback(UNSETMARGINAL|PATH, cli_unset_marginal);
+ set_handler_callback(UNSETMARGINAL|MAP, cli_unset_all_marginal);
umask(077);
uxsock_listen(&uxsock_trigger, ux_sock, ap);

@ -1,141 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Thu, 1 Sep 2022 19:21:30 +0200
Subject: [PATCH] multipath-tools: use /run instead of /dev/shm
/dev/shm may have unsafe permissions. Use /run instead.
Use systemd's tmpfiles.d mechanism to create /run/multipath
early during boot.
For backward compatibilty, make the runtime directory configurable
via the "runtimedir" make variable.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
.gitignore | 2 ++
Makefile.inc | 4 +++-
libmultipath/defaults.h | 2 +-
multipath/Makefile | 9 +++++++--
multipath/{multipath.rules => multipath.rules.in} | 4 ++--
multipath/tmpfiles.conf.in | 1 +
6 files changed, 16 insertions(+), 6 deletions(-)
rename multipath/{multipath.rules => multipath.rules.in} (96%)
create mode 100644 multipath/tmpfiles.conf.in
diff --git a/.gitignore b/.gitignore
index 087dffc2..6ee4fa09 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,8 @@ cscope.files
cscope.out
kpartx/kpartx
multipath/multipath
+multipath/multipath.rules
+multipath/tmpfiles.conf
multipathd/multipathd
mpathpersist/mpathpersist
.nfs*
diff --git a/Makefile.inc b/Makefile.inc
index 05027703..4c452159 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -62,6 +62,7 @@ exec_prefix = $(prefix)
usr_prefix = $(prefix)
bindir = $(exec_prefix)/usr/sbin
libudevdir = $(prefix)/$(SYSTEMDPATH)/udev
+tmpfilesdir = $(prefix)/$(SYSTEMDPATH)/tmpfiles.d
udevrulesdir = $(libudevdir)/rules.d
multipathdir = $(TOPDIR)/libmultipath
man8dir = $(prefix)/usr/share/man/man8
@@ -79,6 +80,7 @@ libdmmpdir = $(TOPDIR)/libdmmp
nvmedir = $(TOPDIR)/libmultipath/nvme
includedir = $(prefix)/usr/include
pkgconfdir = $(usrlibdir)/pkgconfig
+runtimedir = /$(RUN)
GZIP = gzip -9 -c
RM = rm -f
@@ -120,7 +122,7 @@ WARNFLAGS := -Werror -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implicit-int
$(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}\" \
+ -DBIN_DIR=\"$(bindir)\" -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" -DRUNTIME_DIR=\"$(runtimedir)\" \
-MMD -MP
BIN_CFLAGS = -fPIE -DPIE
LIB_CFLAGS = -fPIC
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index e0dd32ad..cec82f07 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -69,7 +69,7 @@
#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
#define DEFAULT_PRKEYS_FILE "/etc/multipath/prkeys"
#define DEFAULT_CONFIG_DIR "/etc/multipath/conf.d"
-#define MULTIPATH_SHM_BASE "/dev/shm/multipath/"
+#define MULTIPATH_SHM_BASE RUNTIME_DIR "/multipath/"
static inline char *set_default(char *str)
diff --git a/multipath/Makefile b/multipath/Makefile
index e720c7f6..f3d98012 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -12,7 +12,7 @@ EXEC = multipath
OBJS = main.o
-all: $(EXEC)
+all: $(EXEC) multipath.rules tmpfiles.conf
$(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
$(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS) $(LIBDEPS)
@@ -27,6 +27,8 @@ install:
$(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
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(tmpfilesdir)
+ $(INSTALL_PROGRAM) -m 644 tmpfiles.conf $(DESTDIR)$(tmpfilesdir)/multipath.conf
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man8dir)
$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(man8dir)
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir)
@@ -43,9 +45,12 @@ uninstall:
$(RM) $(DESTDIR)$(man8dir)/mpathconf.8.gz
clean: dep_clean
- $(RM) core *.o $(EXEC) *.gz
+ $(RM) core *.o $(EXEC) *.gz multipath.rules tmpfiles.conf
include $(wildcard $(OBJS:.o=.d))
dep_clean:
$(RM) $(OBJS:.o=.d)
+
+%: %.in
+ sed 's,@RUNTIME_DIR@,$(runtimedir),' $< >$@
diff --git a/multipath/multipath.rules b/multipath/multipath.rules.in
similarity index 96%
rename from multipath/multipath.rules
rename to multipath/multipath.rules.in
index 68c30644..5c4447a2 100644
--- a/multipath/multipath.rules
+++ b/multipath/multipath.rules.in
@@ -1,8 +1,8 @@
# Set DM_MULTIPATH_DEVICE_PATH if the device should be handled by multipath
SUBSYSTEM!="block", GOTO="end_mpath"
KERNEL!="sd*|dasd*|nvme*", GOTO="end_mpath"
-ACTION=="remove", TEST=="/dev/shm/multipath/find_multipaths/$major:$minor", \
- RUN+="/usr/bin/rm -f /dev/shm/multipath/find_multipaths/$major:$minor"
+ACTION=="remove", TEST=="@RUNTIME_DIR@/multipath/find_multipaths/$major:$minor", \
+ RUN+="/usr/bin/rm -f @RUNTIME_DIR@/multipath/find_multipaths/$major:$minor"
ACTION!="add|change", GOTO="end_mpath"
IMPORT{cmdline}="nompath"
diff --git a/multipath/tmpfiles.conf.in b/multipath/tmpfiles.conf.in
new file mode 100644
index 00000000..21be438a
--- /dev/null
+++ b/multipath/tmpfiles.conf.in
@@ -0,0 +1 @@
+d @RUNTIME_DIR@/multipath 0700 root root -

@ -1,47 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 19 Oct 2022 12:57:10 -0500
Subject: [PATCH] kpartx: hold device open until partitions have been created
kpartx was closing the whole device after it read the partition
information off it. This allowed a race, where the device could be
removed and another one created with the same major:minor, after kpartx
read the partition information but before it created the partition
devices.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
kpartx/kpartx.c | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c
index 7bc64543..e79fdd4a 100644
--- a/kpartx/kpartx.c
+++ b/kpartx/kpartx.c
@@ -443,12 +443,7 @@ main(int argc, char **argv){
if (n >= 0)
printf("%s: %d slices\n", ptp->type, n);
#endif
-
- if (n > 0) {
- close(fd);
- fd = -1;
- }
- else
+ if (n <= 0)
continue;
switch(what) {
@@ -668,9 +663,9 @@ main(int argc, char **argv){
if (n > 0)
break;
}
+ if (fd != -1)
+ close(fd);
if (what == LIST && loopcreated) {
- if (fd != -1)
- close(fd);
if (del_loop(device)) {
if (verbose)
fprintf(stderr, "can't del loop : %s\n",

@ -1,153 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 7 Oct 2022 12:35:37 -0500
Subject: [PATCH] libmultipath: cleanup remove_feature
remove_feature() didn't correctly handle feature strings that used
whitespace other than spaces, which the kernel allows. It also didn't
check if the feature string to be removed was part of a larger feature
token. Finally, it did a lot of unnecessary work. By failing if the
feature string to be removed contains leading or trailing whitespace,
the function can be significanly simplified.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/structs.c | 82 +++++++++++++++---------------------------
1 file changed, 29 insertions(+), 53 deletions(-)
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
index acd4cbeb..83906ffe 100644
--- a/libmultipath/structs.c
+++ b/libmultipath/structs.c
@@ -6,6 +6,7 @@
#include <unistd.h>
#include <libdevmapper.h>
#include <libudev.h>
+#include <ctype.h>
#include "checkers.h"
#include "memory.h"
@@ -669,7 +670,7 @@ int add_feature(char **f, const char *n)
int remove_feature(char **f, const char *o)
{
- int c = 0, d, l;
+ int c = 0, d;
char *e, *p, *n;
const char *q;
@@ -680,33 +681,35 @@ int remove_feature(char **f, const char *o)
if (!o || *o == '\0')
return 0;
- /* Check if not present */
- if (!strstr(*f, o))
+ d = strlen(o);
+ if (isspace(*o) || isspace(*(o + d - 1))) {
+ condlog(0, "internal error: feature \"%s\" has leading or trailing spaces", o);
+ return 1;
+ }
+
+ /* Check if present and not part of a larger feature token*/
+ p = *f + 1; /* the size must be at the start of the features string */
+ while ((p = strstr(p, o)) != NULL) {
+ if (isspace(*(p - 1)) &&
+ (isspace(*(p + d)) || *(p + d) == '\0'))
+ break;
+ p += d;
+ }
+ if (!p)
return 0;
/* Get feature count */
c = strtoul(*f, &e, 10);
- if (*f == e)
- /* parse error */
+ if (*f == e || !isspace(*e)) {
+ condlog(0, "parse error in feature string \"%s\"", *f);
return 1;
-
- /* Normalize features */
- while (*o == ' ') {
- o++;
}
- /* Just spaces, return */
- if (*o == '\0')
- return 0;
- q = o + strlen(o);
- while (*q == ' ')
- q--;
- d = (int)(q - o);
/* Update feature count */
c--;
q = o;
- while (q[0] != '\0') {
- if (q[0] == ' ' && q[1] != ' ' && q[1] != '\0')
+ while (*q != '\0') {
+ if (isspace(*q) && !isspace(*(q + 1)) && *(q + 1) != '\0')
c--;
q++;
}
@@ -720,15 +723,8 @@ int remove_feature(char **f, const char *o)
goto out;
}
- /* Search feature to be removed */
- e = strstr(*f, o);
- if (!e)
- /* Not found, return */
- return 0;
-
/* Update feature count space */
- l = strlen(*f) - d;
- n = MALLOC(l + 1);
+ n = MALLOC(strlen(*f) - d + 1);
if (!n)
return 1;
@@ -738,36 +734,16 @@ int remove_feature(char **f, const char *o)
* Copy existing features up to the feature
* about to be removed
*/
- p = strchr(*f, ' ');
- if (!p) {
- /* Internal error, feature string inconsistent */
- FREE(n);
- return 1;
- }
- while (*p == ' ')
- p++;
- p--;
- if (e != p) {
- do {
- e--;
- d++;
- } while (*e == ' ');
- e++; d--;
- strncat(n, p, (size_t)(e - p));
- p += (size_t)(e - p);
- }
+ strncat(n, e, (size_t)(p - e));
/* Skip feature to be removed */
p += d;
-
/* Copy remaining features */
- if (strlen(p)) {
- while (*p == ' ')
- p++;
- if (strlen(p)) {
- p--;
- strcat(n, p);
- }
- }
+ while (isspace(*p))
+ p++;
+ if (*p != '\0')
+ strcat(n, p);
+ else
+ strchop(n);
out:
FREE(*f);

@ -1,107 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 7 Oct 2022 12:35:38 -0500
Subject: [PATCH] libmultipath: cleanup add_feature
add_feature() didn't correctly handle feature strings that used
whitespace other than spaces, which the kernel allows. It also didn't
allow adding features with multiple tokens. When it looked to see if the
feature string to be added already existed, it didn't check if the match
was part of a larger token. Finally, it did unnecessary work. By using
asprintf() to create the string, the function can be signifcantly
simplified.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/structs.c | 49 +++++++++++++++++++++---------------------
1 file changed, 24 insertions(+), 25 deletions(-)
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
index 83906ffe..5dfa86a8 100644
--- a/libmultipath/structs.c
+++ b/libmultipath/structs.c
@@ -608,23 +608,33 @@ int add_feature(char **f, const char *n)
{
int c = 0, d, l;
char *e, *t;
+ const char *p;
if (!f)
return 1;
/* Nothing to do */
- if (!n || *n == '0')
+ if (!n || *n == '\0')
return 0;
- if (strchr(n, ' ') != NULL) {
- condlog(0, "internal error: feature \"%s\" contains spaces", n);
+ l = strlen(n);
+ if (isspace(*n) || isspace(*(n + l - 1))) {
+ condlog(0, "internal error: feature \"%s\" has leading or trailing spaces", n);
return 1;
}
+ p = n;
+ d = 1;
+ while (*p != '\0') {
+ if (isspace(*p) && !isspace(*(p + 1)) && *(p + 1) != '\0')
+ d++;
+ p++;
+ }
+
/* default feature is null */
if(!*f)
{
- l = asprintf(&t, "1 %s", n);
+ l = asprintf(&t, "%0d %s", d, n);
if(l == -1)
return 1;
@@ -633,35 +643,24 @@ int add_feature(char **f, const char *n)
}
/* Check if feature is already present */
- if (strstr(*f, n))
- return 0;
+ e = *f;
+ while ((e = strstr(e, n)) != NULL) {
+ if (isspace(*(e - 1)) &&
+ (isspace(*(e + l)) || *(e + l) == '\0'))
+ return 0;
+ e += l;
+ }
/* Get feature count */
c = strtoul(*f, &e, 10);
- if (*f == e || (*e != ' ' && *e != '\0')) {
+ if (*f == e || (!isspace(*e) && *e != '\0')) {
condlog(0, "parse error in feature string \"%s\"", *f);
return 1;
}
-
- /* Add 1 digit and 1 space */
- l = strlen(e) + strlen(n) + 2;
-
- c++;
- /* Check if we need more digits for feature count */
- for (d = c; d >= 10; d /= 10)
- l++;
-
- t = MALLOC(l + 1);
- if (!t)
+ c += d;
+ if (asprintf(&t, "%0d%s %s", c, e, n) < 0)
return 1;
- /* e: old feature string with leading space, or "" */
- if (*e == ' ')
- while (*(e + 1) == ' ')
- e++;
-
- snprintf(t, l + 1, "%0d%s %s", c, e, n);
-
FREE(*f);
*f = t;

@ -1,351 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 7 Oct 2022 12:35:39 -0500
Subject: [PATCH] multipath tests: tests for adding and removing features
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
tests/Makefile | 2 +-
tests/features.c | 319 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 320 insertions(+), 1 deletion(-)
create mode 100644 tests/features.c
diff --git a/tests/Makefile b/tests/Makefile
index 8cbc4b73..972a5e04 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -13,7 +13,7 @@ CFLAGS += $(BIN_CFLAGS) -I$(multipathdir) -I$(mpathcmddir) \
LIBDEPS += -L. -L$(mpathcmddir) -lmultipath -lmpathcmd -lcmocka
TESTS := uevent parser util dmevents hwtable blacklist unaligned vpd pgpolicy \
- alias directio valid devt mpathvalid strbuf
+ alias directio valid devt mpathvalid strbuf features
HELPERS := test-lib.o test-log.o
.SILENT: $(TESTS:%=%.o)
diff --git a/tests/features.c b/tests/features.c
new file mode 100644
index 00000000..4d8f0860
--- /dev/null
+++ b/tests/features.c
@@ -0,0 +1,319 @@
+#include <stddef.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "structs.h"
+#include "globals.c"
+
+static void test_af_null_features_ptr(void **state)
+{
+ assert_int_equal(add_feature(NULL, "test"), 1);
+}
+
+static void af_helper(const char *features_start, const char *addition,
+ const char *features_end, int result)
+{
+ char *f = NULL, *orig = NULL;
+
+ if (features_start) {
+ f = strdup(features_start);
+ assert_non_null(f);
+ orig = f;
+ }
+ assert_int_equal(add_feature(&f, addition), result);
+ if (result != 0 || features_end == NULL)
+ assert_ptr_equal(orig, f);
+ else
+ assert_string_equal(f, features_end);
+ free(f);
+}
+
+static void test_af_null_addition1(void **state)
+{
+ af_helper("0", NULL, NULL, 0);
+}
+
+static void test_af_null_addition2(void **state)
+{
+ af_helper("1 queue_if_no_path", NULL, NULL, 0);
+}
+
+static void test_af_empty_addition(void **state)
+{
+ af_helper("2 pg_init_retries 5", "", NULL, 0);
+}
+
+static void test_af_invalid_addition1(void **state)
+{
+ af_helper("2 pg_init_retries 5", " ", NULL, 1);
+}
+
+static void test_af_invalid_addition2(void **state)
+{
+ af_helper("2 pg_init_retries 5", "\tbad", NULL, 1);
+}
+
+static void test_af_invalid_addition3(void **state)
+{
+ af_helper("2 pg_init_retries 5", "bad ", NULL, 1);
+}
+
+static void test_af_invalid_addition4(void **state)
+{
+ af_helper("2 pg_init_retries 5", " bad ", NULL, 1);
+}
+
+static void test_af_null_features1(void **state)
+{
+ af_helper(NULL, "test", "1 test", 0);
+}
+
+static void test_af_null_features2(void **state)
+{
+ af_helper(NULL, "test\t more", "2 test\t more", 0);
+}
+
+static void test_af_null_features3(void **state)
+{
+ af_helper(NULL, "test\neven\tmore", "3 test\neven\tmore", 0);
+}
+
+static void test_af_already_exists1(void **state)
+{
+ af_helper("4 this is a test", "test", NULL, 0);
+}
+
+static void test_af_already_exists2(void **state)
+{
+ af_helper("5 contest testy intestine test retest", "test", NULL, 0);
+}
+
+static void test_af_almost_exists(void **state)
+{
+ af_helper("3 contest testy intestine", "test",
+ "4 contest testy intestine test", 0);
+}
+
+static void test_af_bad_features1(void **state)
+{
+ af_helper("bad", "test", NULL, 1);
+}
+
+static void test_af_bad_features2(void **state)
+{
+ af_helper("1bad", "test", NULL, 1);
+}
+
+static void test_af_add1(void **state)
+{
+ af_helper("0", "test", "1 test", 0);
+}
+
+static void test_af_add2(void **state)
+{
+ af_helper("0", "this is a test", "4 this is a test", 0);
+}
+
+static void test_af_add3(void **state)
+{
+ af_helper("1 features", "more values", "3 features more values", 0);
+}
+
+static void test_af_add4(void **state)
+{
+ af_helper("2 one\ttwo", "three\t four", "4 one\ttwo three\t four", 0);
+}
+
+static int test_add_features(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_af_null_features_ptr),
+ cmocka_unit_test(test_af_null_addition1),
+ cmocka_unit_test(test_af_null_addition2),
+ cmocka_unit_test(test_af_empty_addition),
+ cmocka_unit_test(test_af_invalid_addition1),
+ cmocka_unit_test(test_af_invalid_addition2),
+ cmocka_unit_test(test_af_invalid_addition3),
+ cmocka_unit_test(test_af_invalid_addition4),
+ cmocka_unit_test(test_af_null_features1),
+ cmocka_unit_test(test_af_null_features2),
+ cmocka_unit_test(test_af_null_features3),
+ cmocka_unit_test(test_af_already_exists1),
+ cmocka_unit_test(test_af_already_exists2),
+ cmocka_unit_test(test_af_almost_exists),
+ cmocka_unit_test(test_af_bad_features1),
+ cmocka_unit_test(test_af_bad_features2),
+ cmocka_unit_test(test_af_add1),
+ cmocka_unit_test(test_af_add2),
+ cmocka_unit_test(test_af_add3),
+ cmocka_unit_test(test_af_add4),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
+
+static void test_rf_null_features_ptr(void **state)
+{
+ assert_int_equal(remove_feature(NULL, "test"), 1);
+}
+
+static void test_rf_null_features(void **state)
+{
+ char *f = NULL;
+ assert_int_equal(remove_feature(&f, "test"), 1);
+}
+
+static void rf_helper(const char *features_start, const char *removal,
+ const char *features_end, int result)
+{
+ char *f = strdup(features_start);
+ char *orig = f;
+
+ assert_non_null(f);
+ assert_int_equal(remove_feature(&f, removal), result);
+ if (result != 0 || features_end == NULL)
+ assert_ptr_equal(orig, f);
+ else
+ assert_string_equal(f, features_end);
+ free(f);
+}
+
+static void test_rf_null_removal(void **state)
+{
+ rf_helper("1 feature", NULL, NULL, 0);
+}
+
+static void test_rf_empty_removal(void **state)
+{
+ rf_helper("1 feature", "", NULL, 0);
+}
+
+static void test_rf_invalid_removal1(void **state)
+{
+ rf_helper("1 feature", " ", NULL, 1);
+}
+
+static void test_rf_invalid_removal2(void **state)
+{
+ rf_helper("1 feature", " bad", NULL, 1);
+}
+
+static void test_rf_invalid_removal3(void **state)
+{
+ rf_helper("1 feature", "bad\n", NULL, 1);
+}
+
+static void test_rf_invalid_removal4(void **state)
+{
+ rf_helper("1 feature", "\tbad \n", NULL, 1);
+}
+
+static void test_rf_bad_features1(void **state)
+{
+ rf_helper("invalid feature test string", "test", NULL, 1);
+}
+
+static void test_rf_bad_features2(void **state)
+{
+ rf_helper("2no space test", "test", NULL, 1);
+}
+
+static void test_rf_missing_removal1(void **state)
+{
+ rf_helper("0", "test", NULL, 0);
+}
+
+static void test_rf_missing_removal2(void **state)
+{
+ rf_helper("1 detest", "test", NULL, 0);
+}
+
+static void test_rf_missing_removal3(void **state)
+{
+ rf_helper("4 testing one two three", "test", NULL, 0);
+}
+
+static void test_rf_missing_removal4(void **state)
+{
+ rf_helper("1 contestant", "test", NULL, 0);
+}
+
+static void test_rf_missing_removal5(void **state)
+{
+ rf_helper("3 testament protest detestable", "test", NULL, 0);
+}
+
+static void test_rf_remove_all_features1(void **state)
+{
+ rf_helper("1 test", "test", "0", 0);
+}
+
+static void test_rf_remove_all_features2(void **state)
+{
+ rf_helper("2 another\t test", "another\t test", "0", 0);
+}
+
+static void test_rf_remove1(void **state)
+{
+ rf_helper("2 feature1 feature2", "feature2", "1 feature1", 0);
+}
+
+static void test_rf_remove2(void **state)
+{
+ rf_helper("2 feature1 feature2", "feature1", "1 feature2", 0);
+}
+
+static void test_rf_remove3(void **state)
+{
+ rf_helper("3 test1 test\ttest2", "test", "2 test1 test2", 0);
+}
+
+static void test_rf_remove4(void **state)
+{
+ rf_helper("4 this\t is a test", "is a", "2 this\t test", 0);
+}
+
+static void test_rf_remove5(void **state)
+{
+ rf_helper("3 one more test", "more test", "1 one", 0);
+}
+
+static int test_remove_features(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_rf_null_features_ptr),
+ cmocka_unit_test(test_rf_null_features),
+ cmocka_unit_test(test_rf_null_removal),
+ cmocka_unit_test(test_rf_empty_removal),
+ cmocka_unit_test(test_rf_invalid_removal1),
+ cmocka_unit_test(test_rf_invalid_removal2),
+ cmocka_unit_test(test_rf_invalid_removal3),
+ cmocka_unit_test(test_rf_invalid_removal4),
+ cmocka_unit_test(test_rf_bad_features1),
+ cmocka_unit_test(test_rf_bad_features2),
+ cmocka_unit_test(test_rf_missing_removal1),
+ cmocka_unit_test(test_rf_missing_removal2),
+ cmocka_unit_test(test_rf_missing_removal3),
+ cmocka_unit_test(test_rf_missing_removal4),
+ cmocka_unit_test(test_rf_missing_removal5),
+ cmocka_unit_test(test_rf_remove_all_features1),
+ cmocka_unit_test(test_rf_remove_all_features2),
+ cmocka_unit_test(test_rf_remove1),
+ cmocka_unit_test(test_rf_remove2),
+ cmocka_unit_test(test_rf_remove3),
+ cmocka_unit_test(test_rf_remove4),
+ cmocka_unit_test(test_rf_remove5),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
+
+int main(void)
+{
+ int ret = 0;
+
+ init_test_verbosity(-1);
+ ret += test_add_features();
+ ret += test_remove_features();
+
+ return ret;
+}

@ -1,177 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 7 Oct 2022 12:35:40 -0500
Subject: [PATCH] libmultipath: fix queue_mode feature handling
device-mapper is not able to change the queue_mode on a table reload.
Make sure that when multipath sets up the map, both on regular reloads
and reconfigures, it keeps the queue_mode the same.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/configure.c | 4 +++
libmultipath/dmparser.c | 2 ++
libmultipath/propsel.c | 55 ++++++++++++++++++++++++++++++++++++++
libmultipath/structs.h | 7 +++++
multipath/multipath.conf.5 | 7 +++--
5 files changed, 73 insertions(+), 2 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 70049f47..cc778a22 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -1118,6 +1118,7 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,
struct config *conf = NULL;
int allow_queueing;
struct bitfield *size_mismatch_seen;
+ struct multipath * cmpp;
/* ignore refwwid if it's empty */
if (refwwid && !strlen(refwwid))
@@ -1227,6 +1228,9 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,
}
verify_paths(mpp);
+ cmpp = find_mp_by_wwid(curmp, mpp->wwid);
+ if (cmpp)
+ mpp->queue_mode = cmpp->queue_mode;
if (setup_map(mpp, &params, vecs)) {
remove_map(mpp, vecs->pathvec, NULL);
continue;
diff --git a/libmultipath/dmparser.c b/libmultipath/dmparser.c
index bc311421..16377c54 100644
--- a/libmultipath/dmparser.c
+++ b/libmultipath/dmparser.c
@@ -152,6 +152,8 @@ int disassemble_map(const struct _vector *pathvec,
FREE(word);
}
+ mpp->queue_mode = strstr(mpp->features, "queue_mode bio") ?
+ QUEUE_MODE_BIO : QUEUE_MODE_RQ;
/*
* hwhandler
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
index 2b47f5f8..9dea6f92 100644
--- a/libmultipath/propsel.c
+++ b/libmultipath/propsel.c
@@ -27,6 +27,7 @@
#include "strbuf.h"
#include <inttypes.h>
#include <libudev.h>
+#include <ctype.h>
pgpolicyfn *pgpolicies[] = {
NULL,
@@ -414,6 +415,59 @@ void reconcile_features_with_options(const char *id, char **features, int* no_pa
}
}
+static void reconcile_features_with_queue_mode(struct multipath *mp)
+{
+ char *space = NULL, *val = NULL, *mode_str = NULL, *feat;
+ int features_mode = QUEUE_MODE_UNDEF;
+
+ if (!mp->features)
+ return;
+
+ pthread_cleanup_push(cleanup_free_ptr, &space);
+ pthread_cleanup_push(cleanup_free_ptr, &val);
+ pthread_cleanup_push(cleanup_free_ptr, &mode_str);
+
+ if (!(feat = strstr(mp->features, "queue_mode")) ||
+ feat == mp->features || !isspace(*(feat - 1)) ||
+ sscanf(feat, "queue_mode%m[ \f\n\r\t\v]%ms", &space, &val) != 2)
+ goto sync_mode;
+ if (asprintf(&mode_str, "queue_mode%s%s", space, val) < 0) {
+ condlog(1, "failed to allocate space for queue_mode feature string");
+ mode_str = NULL; /* value undefined on failure */
+ goto exit;
+ }
+
+ if (!strcmp(val, "rq") || !strcmp(val, "mq"))
+ features_mode = QUEUE_MODE_RQ;
+ else if (!strcmp(val, "bio"))
+ features_mode = QUEUE_MODE_BIO;
+ if (features_mode == QUEUE_MODE_UNDEF) {
+ condlog(2, "%s: ignoring invalid feature '%s'",
+ mp->alias, mode_str);
+ goto sync_mode;
+ }
+
+ if (mp->queue_mode == QUEUE_MODE_UNDEF)
+ mp->queue_mode = features_mode;
+ if (mp->queue_mode == features_mode)
+ goto exit;
+
+ condlog(2,
+ "%s: ignoring feature '%s' because queue_mode is set to '%s'",
+ mp->alias, mode_str,
+ (mp->queue_mode == QUEUE_MODE_RQ)? "rq" : "bio");
+
+sync_mode:
+ if (mode_str)
+ remove_feature(&mp->features, mode_str);
+ if (mp->queue_mode == QUEUE_MODE_BIO)
+ add_feature(&mp->features, "queue_mode bio");
+exit:
+ pthread_cleanup_pop(1);
+ pthread_cleanup_pop(1);
+ pthread_cleanup_pop(1);
+}
+
int select_features(struct config *conf, struct multipath *mp)
{
const char *origin;
@@ -429,6 +483,7 @@ out:
reconcile_features_with_options(mp->alias, &mp->features,
&mp->no_path_retry,
&mp->retain_hwhandler);
+ reconcile_features_with_queue_mode(mp);
condlog(3, "%s: features = \"%s\" %s", mp->alias, mp->features, origin);
return 0;
}
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index 8a07d470..b4f75de0 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -170,6 +170,12 @@ enum max_sectors_kb_states {
MAX_SECTORS_KB_MIN = 4, /* can't be smaller than page size */
};
+enum queue_mode_states {
+ QUEUE_MODE_UNDEF = 0,
+ QUEUE_MODE_BIO,
+ QUEUE_MODE_RQ,
+};
+
enum scsi_protocol {
SCSI_PROTOCOL_FCP = 0, /* Fibre Channel */
SCSI_PROTOCOL_SPI = 1, /* parallel SCSI */
@@ -387,6 +393,7 @@ struct multipath {
int needs_paths_uevent;
int ghost_delay;
int ghost_delay_tick;
+ int queue_mode;
uid_t uid;
gid_t gid;
mode_t mode;
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index f7de5140..e1a787d4 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -468,8 +468,11 @@ precedence. See KNOWN ISSUES.
<mode> can be \fIbio\fR, \fIrq\fR or \fImq\fR, which corresponds to
bio-based, request-based, and block-multiqueue (blk-mq) request-based,
respectively.
-The default depends on the kernel parameter \fBdm_mod.use_blk_mq\fR. It is
-\fImq\fR if the latter is set, and \fIrq\fR otherwise.
+Before kernel 4.20 The default depends on the kernel parameter
+\fBdm_mod.use_blk_mq\fR. It is \fImq\fR if the latter is set, and \fIrq\fR
+otherwise. Since kernel 4.20, \fIrq\fR and \fImq\fR both correspond to
+block-multiqueue. Once a multipath device has been created, its queue_mode
+cannot be changed.
.TP
The default is: \fB<unset>\fR
.RE

@ -1,291 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 7 Oct 2022 12:35:41 -0500
Subject: [PATCH] multipath tests: tests for reconcile_features_with_queue_mode
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
tests/Makefile | 2 +
tests/features.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 233 insertions(+), 1 deletion(-)
diff --git a/tests/Makefile b/tests/Makefile
index 972a5e04..27e3ffa9 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -33,6 +33,7 @@ ifneq ($(DIO_TEST_DEV),)
directio-test_FLAGS := -DDIO_TEST_DEV=\"$(DIO_TEST_DEV)\"
endif
mpathvalid-test_FLAGS := -I$(mpathvaliddir)
+features-test_FLAGS := -I$(multipathdir)/nvme
# test-specific linker flags
# XYZ-test_TESTDEPS: test libraries containing __wrap_xyz functions
@@ -64,6 +65,7 @@ ifneq ($(DIO_TEST_DEV),)
directio-test_LIBDEPS := -laio
endif
strbuf-test_OBJDEPS := ../libmultipath/strbuf.o
+features-test_LIBDEPS := -ludev -lpthread
%.o: %.c
$(CC) $(CFLAGS) $($*-test_FLAGS) -c -o $@ $<
diff --git a/tests/features.c b/tests/features.c
index 4d8f0860..31f978fd 100644
--- a/tests/features.c
+++ b/tests/features.c
@@ -1,9 +1,10 @@
+#define _GNU_SOURCE
#include <stddef.h>
#include <stdarg.h>
#include <setjmp.h>
#include <cmocka.h>
-#include "structs.h"
+#include "../libmultipath/propsel.c"
#include "globals.c"
static void test_af_null_features_ptr(void **state)
@@ -307,6 +308,234 @@ static int test_remove_features(void)
return cmocka_run_group_tests(tests, NULL, NULL);
}
+static void test_cf_null_features(void **state)
+{
+ struct multipath mp = {
+ .alias = "test",
+ };
+ reconcile_features_with_queue_mode(&mp);
+ assert_null(mp.features);
+}
+
+static void cf_helper(const char *features_start, const char *features_end,
+ int queue_mode_start, int queue_mode_end)
+{
+ struct multipath mp = {
+ .alias = "test",
+ .features = strdup(features_start),
+ .queue_mode = queue_mode_start,
+ };
+ char *orig = mp.features;
+
+ assert_non_null(orig);
+ reconcile_features_with_queue_mode(&mp);
+ if (!features_end)
+ assert_ptr_equal(orig, mp.features);
+ else
+ assert_string_equal(mp.features, features_end);
+ free(mp.features);
+ assert_int_equal(mp.queue_mode, queue_mode_end);
+}
+
+static void test_cf_unset_unset1(void **state)
+{
+ cf_helper("0", NULL, QUEUE_MODE_UNDEF, QUEUE_MODE_UNDEF);
+}
+
+static void test_cf_unset_unset2(void **state)
+{
+ cf_helper("1 queue_mode", NULL, QUEUE_MODE_UNDEF, QUEUE_MODE_UNDEF);
+}
+
+static void test_cf_unset_unset3(void **state)
+{
+ cf_helper("queue_mode", NULL, QUEUE_MODE_UNDEF, QUEUE_MODE_UNDEF);
+}
+
+static void test_cf_unset_unset4(void **state)
+{
+ cf_helper("2 queue_model bio", NULL, QUEUE_MODE_UNDEF,
+ QUEUE_MODE_UNDEF);
+}
+
+static void test_cf_unset_unset5(void **state)
+{
+ cf_helper("1 queue_if_no_path", NULL, QUEUE_MODE_UNDEF,
+ QUEUE_MODE_UNDEF);
+}
+
+static void test_cf_invalid_unset1(void **state)
+{
+ cf_helper("2 queue_mode biop", "0", QUEUE_MODE_UNDEF, QUEUE_MODE_UNDEF);
+}
+
+static void test_cf_invalid_unset2(void **state)
+{
+ cf_helper("3 queue_mode rqs queue_if_no_path", "1 queue_if_no_path",
+ QUEUE_MODE_UNDEF, QUEUE_MODE_UNDEF);
+}
+
+static void test_cf_rq_unset1(void **state)
+{
+ cf_helper("2 queue_mode rq", NULL, QUEUE_MODE_UNDEF, QUEUE_MODE_RQ);
+}
+
+static void test_cf_rq_unset2(void **state)
+{
+ cf_helper("2 queue_mode mq", NULL, QUEUE_MODE_UNDEF, QUEUE_MODE_RQ);
+}
+
+static void test_cf_bio_unset(void **state)
+{
+ cf_helper("2 queue_mode bio", NULL, QUEUE_MODE_UNDEF, QUEUE_MODE_BIO);
+}
+
+static void test_cf_unset_bio1(void **state)
+{
+ cf_helper("1 queue_if_no_path", "3 queue_if_no_path queue_mode bio",
+ QUEUE_MODE_BIO, QUEUE_MODE_BIO);
+}
+
+static void test_cf_unset_bio2(void **state)
+{
+ cf_helper("0", "2 queue_mode bio", QUEUE_MODE_BIO, QUEUE_MODE_BIO);
+}
+
+static void test_cf_unset_bio3(void **state)
+{
+ cf_helper("2 pg_init_retries 50", "4 pg_init_retries 50 queue_mode bio",
+ QUEUE_MODE_BIO, QUEUE_MODE_BIO);
+}
+
+static void test_cf_invalid_bio1(void **state)
+{
+ cf_helper("2 queue_mode bad", "2 queue_mode bio",
+ QUEUE_MODE_BIO, QUEUE_MODE_BIO);
+}
+
+static void test_cf_invalid_bio2(void **state)
+{
+ cf_helper("3 queue_if_no_path queue_mode\tbad", "3 queue_if_no_path queue_mode bio",
+ QUEUE_MODE_BIO, QUEUE_MODE_BIO);
+}
+
+static void test_cf_bio_bio1(void **state)
+{
+ cf_helper("2 queue_mode bio", NULL, QUEUE_MODE_BIO, QUEUE_MODE_BIO);
+}
+
+static void test_cf_bio_bio2(void **state)
+{
+ cf_helper("3 queue_if_no_path queue_mode bio", NULL, QUEUE_MODE_BIO, QUEUE_MODE_BIO);
+}
+
+static void test_cf_bio_bio3(void **state)
+{
+ cf_helper("3 queue_mode\nbio queue_if_no_path", NULL, QUEUE_MODE_BIO, QUEUE_MODE_BIO);
+}
+
+static void test_cf_bio_rq1(void **state)
+{
+ cf_helper("2\nqueue_mode\tbio", "0", QUEUE_MODE_RQ, QUEUE_MODE_RQ);
+}
+
+static void test_cf_bio_rq2(void **state)
+{
+ cf_helper("3 queue_if_no_path\nqueue_mode bio", "1 queue_if_no_path",
+ QUEUE_MODE_RQ, QUEUE_MODE_RQ);
+}
+
+static void test_cf_bio_rq3(void **state)
+{
+ cf_helper("4 queue_mode bio pg_init_retries 20", "2 pg_init_retries 20",
+ QUEUE_MODE_RQ, QUEUE_MODE_RQ);
+}
+
+static void test_cf_unset_rq1(void **state)
+{
+ cf_helper("0", NULL, QUEUE_MODE_RQ, QUEUE_MODE_RQ);
+}
+
+static void test_cf_unset_rq2(void **state)
+{
+ cf_helper("2 pg_init_retries 15", NULL, QUEUE_MODE_RQ, QUEUE_MODE_RQ);
+}
+
+static void test_cf_invalid_rq1(void **state)
+{
+ cf_helper("2 queue_mode bionic", "0", QUEUE_MODE_RQ, QUEUE_MODE_RQ);
+}
+
+static void test_cf_invalid_rq2(void **state)
+{
+ cf_helper("3 queue_mode b\nqueue_if_no_path", "1 queue_if_no_path",
+ QUEUE_MODE_RQ, QUEUE_MODE_RQ);
+}
+
+static void test_cf_rq_rq1(void **state)
+{
+ cf_helper("2 queue_mode rq", NULL, QUEUE_MODE_RQ, QUEUE_MODE_RQ);
+}
+
+static void test_cf_rq_rq2(void **state)
+{
+ cf_helper("3 queue_mode\t \trq\nqueue_if_no_path", NULL, QUEUE_MODE_RQ, QUEUE_MODE_RQ);
+}
+
+static void test_cf_rq_bio1(void **state)
+{
+ cf_helper("2 queue_mode rq", "2 queue_mode bio", QUEUE_MODE_BIO,
+ QUEUE_MODE_BIO);
+}
+
+static void test_cf_rq_bio2(void **state)
+{
+ cf_helper("3 queue_if_no_path\nqueue_mode rq", "3 queue_if_no_path queue_mode bio", QUEUE_MODE_BIO, QUEUE_MODE_BIO);
+}
+
+static void test_cf_rq_bio3(void **state)
+{
+ cf_helper("3 queue_mode rq\nqueue_if_no_path", "3 queue_if_no_path queue_mode bio", QUEUE_MODE_BIO, QUEUE_MODE_BIO);
+}
+
+static int test_reconcile_features(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_cf_null_features),
+ cmocka_unit_test(test_cf_unset_unset1),
+ cmocka_unit_test(test_cf_unset_unset2),
+ cmocka_unit_test(test_cf_unset_unset3),
+ cmocka_unit_test(test_cf_unset_unset4),
+ cmocka_unit_test(test_cf_unset_unset5),
+ cmocka_unit_test(test_cf_invalid_unset1),
+ cmocka_unit_test(test_cf_invalid_unset2),
+ cmocka_unit_test(test_cf_rq_unset1),
+ cmocka_unit_test(test_cf_rq_unset2),
+ cmocka_unit_test(test_cf_bio_unset),
+ cmocka_unit_test(test_cf_unset_bio1),
+ cmocka_unit_test(test_cf_unset_bio2),
+ cmocka_unit_test(test_cf_unset_bio3),
+ cmocka_unit_test(test_cf_invalid_bio1),
+ cmocka_unit_test(test_cf_invalid_bio2),
+ cmocka_unit_test(test_cf_bio_bio1),
+ cmocka_unit_test(test_cf_bio_bio2),
+ cmocka_unit_test(test_cf_bio_bio3),
+ cmocka_unit_test(test_cf_bio_rq1),
+ cmocka_unit_test(test_cf_bio_rq2),
+ cmocka_unit_test(test_cf_bio_rq3),
+ cmocka_unit_test(test_cf_unset_rq1),
+ cmocka_unit_test(test_cf_unset_rq2),
+ cmocka_unit_test(test_cf_invalid_rq1),
+ cmocka_unit_test(test_cf_invalid_rq2),
+ cmocka_unit_test(test_cf_rq_rq1),
+ cmocka_unit_test(test_cf_rq_rq2),
+ cmocka_unit_test(test_cf_rq_bio1),
+ cmocka_unit_test(test_cf_rq_bio2),
+ cmocka_unit_test(test_cf_rq_bio3),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
+
int main(void)
{
int ret = 0;
@@ -314,6 +543,7 @@ int main(void)
init_test_verbosity(-1);
ret += test_add_features();
ret += test_remove_features();
+ ret += test_reconcile_features();
return ret;
}

@ -1,143 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 7 Oct 2022 12:35:42 -0500
Subject: [PATCH] libmultipath: prepare proto_id for use by non-scsi devivces
Make sure that when we are checking for a scsi protocol, we are first
checking that we are working with a scsi path.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/configure.c | 9 +++++----
libmultipath/discovery.c | 13 ++++++++-----
libmultipath/print.c | 6 ++++--
libmultipath/structs.c | 2 +-
libmultipath/structs.h | 4 +++-
multipathd/fpin_handlers.c | 2 +-
6 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index cc778a22..c6803b40 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -223,10 +223,11 @@ int rr_optimize_path_order(struct pathgroup *pgp)
total_paths = VECTOR_SIZE(pgp->paths);
vector_foreach_slot(pgp->paths, pp, i) {
- if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP &&
- pp->sg_id.proto_id != SCSI_PROTOCOL_SAS &&
- pp->sg_id.proto_id != SCSI_PROTOCOL_ISCSI &&
- pp->sg_id.proto_id != SCSI_PROTOCOL_SRP) {
+ if (pp->bus != SYSFS_BUS_SCSI ||
+ (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP &&
+ pp->sg_id.proto_id != SCSI_PROTOCOL_SAS &&
+ pp->sg_id.proto_id != SCSI_PROTOCOL_ISCSI &&
+ pp->sg_id.proto_id != SCSI_PROTOCOL_SRP)) {
/* return success as default path order
* is maintained in path group
*/
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index bcda8b09..7f2eb409 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -481,10 +481,11 @@ int sysfs_get_host_adapter_name(const struct path *pp, char *adapter_name)
proto_id = pp->sg_id.proto_id;
- if (proto_id != SCSI_PROTOCOL_FCP &&
- proto_id != SCSI_PROTOCOL_SAS &&
- proto_id != SCSI_PROTOCOL_ISCSI &&
- proto_id != SCSI_PROTOCOL_SRP) {
+ if (pp->bus != SYSFS_BUS_SCSI ||
+ (proto_id != SCSI_PROTOCOL_FCP &&
+ proto_id != SCSI_PROTOCOL_SAS &&
+ proto_id != SCSI_PROTOCOL_ISCSI &&
+ proto_id != SCSI_PROTOCOL_SRP)) {
return 1;
}
/* iscsi doesn't have adapter info in sysfs
@@ -1754,8 +1755,10 @@ sysfs_pathinfo(struct path *pp, const struct _vector *hwtable)
pp->bus = SYSFS_BUS_CCISS;
if (!strncmp(pp->dev,"dasd", 4))
pp->bus = SYSFS_BUS_CCW;
- if (!strncmp(pp->dev,"sd", 2))
+ if (!strncmp(pp->dev,"sd", 2)) {
pp->bus = SYSFS_BUS_SCSI;
+ pp->sg_id.proto_id = SCSI_PROTOCOL_UNSPEC;
+ }
if (!strncmp(pp->dev,"nvme", 4))
pp->bus = SYSFS_BUS_NVME;
diff --git a/libmultipath/print.c b/libmultipath/print.c
index 46e3d32e..082e4e30 100644
--- a/libmultipath/print.c
+++ b/libmultipath/print.c
@@ -592,7 +592,8 @@ snprint_host_attr (struct strbuf *buff, const struct path * pp, char *attr)
const char *value = NULL;
int ret;
- if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP)
+ if (pp->bus != SYSFS_BUS_SCSI ||
+ pp->sg_id.proto_id != SCSI_PROTOCOL_FCP)
return append_strbuf_str(buff, "[undef]");
sprintf(host_id, "host%d", pp->sg_id.host_no);
host_dev = udev_device_new_from_subsystem_sysname(udev, "fc_host",
@@ -631,7 +632,8 @@ snprint_tgt_wwpn (struct strbuf *buff, const struct path * pp)
const char *value = NULL;
int ret;
- if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP)
+ if (pp->bus != SYSFS_BUS_SCSI ||
+ pp->sg_id.proto_id != SCSI_PROTOCOL_FCP)
return append_strbuf_str(buff, "[undef]");
sprintf(rport_id, "rport-%d:%d-%d",
pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id);
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
index 5dfa86a8..be81a83c 100644
--- a/libmultipath/structs.c
+++ b/libmultipath/structs.c
@@ -116,7 +116,7 @@ alloc_path (void)
pp->sg_id.channel = -1;
pp->sg_id.scsi_id = -1;
pp->sg_id.lun = SCSI_INVALID_LUN;
- pp->sg_id.proto_id = SCSI_PROTOCOL_UNSPEC;
+ pp->sg_id.proto_id = PROTOCOL_UNSET;
pp->fd = -1;
pp->tpgs = TPGS_UNDEF;
pp->priority = PRIO_UNDEF;
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index b4f75de0..2525af17 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -176,6 +176,8 @@ enum queue_mode_states {
QUEUE_MODE_RQ,
};
+#define PROTOCOL_UNSET -1
+
enum scsi_protocol {
SCSI_PROTOCOL_FCP = 0, /* Fibre Channel */
SCSI_PROTOCOL_SPI = 1, /* parallel SCSI */
@@ -284,7 +286,7 @@ struct sg_id {
uint64_t lun;
short h_cmd_per_lun;
short d_queue_depth;
- enum scsi_protocol proto_id;
+ int proto_id;
int transport_id;
};
diff --git a/multipathd/fpin_handlers.c b/multipathd/fpin_handlers.c
index aaf5655d..571796e7 100644
--- a/multipathd/fpin_handlers.c
+++ b/multipathd/fpin_handlers.c
@@ -219,7 +219,7 @@ static int fpin_chk_wwn_setpath_marginal(uint16_t host_num, struct vectors *ve
vector_foreach_slot(vecs->pathvec, pp, k) {
/* Checks the host number and also for the SCSI FCP */
- if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP || host_num != pp->sg_id.host_no)
+ if (pp->bus != SYSFS_BUS_SCSI || pp->sg_id.proto_id != SCSI_PROTOCOL_FCP || host_num != pp->sg_id.host_no)
continue;
sprintf(rport_id, "rport-%d:%d-%d",
pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id);

@ -1,194 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 7 Oct 2022 12:35:43 -0500
Subject: [PATCH] libmultipath: get nvme path transport protocol
Read the transport protocol from /sys/block/nvmeXnY/device/transport.
Update protocol_name[] and bus_protocol_id() to store the nvme protocol
names after the scsi protocol names.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/discovery.c | 18 ++++++++++++++++--
libmultipath/structs.c | 22 +++++++++++++++++-----
libmultipath/structs.h | 33 +++++++++++++++++++++------------
multipath/multipath.conf.5 | 10 +++++++---
4 files changed, 61 insertions(+), 22 deletions(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index 7f2eb409..f593a7bf 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1483,6 +1483,7 @@ nvme_sysfs_pathinfo (struct path *pp, const struct _vector *hwtable)
struct udev_device *parent;
const char *attr_path = NULL;
const char *attr;
+ int i;
if (pp->udev)
attr_path = udev_device_get_sysname(pp->udev);
@@ -1505,6 +1506,18 @@ nvme_sysfs_pathinfo (struct path *pp, const struct _vector *hwtable)
attr = udev_device_get_sysattr_value(parent, "cntlid");
pp->sg_id.channel = attr ? atoi(attr) : 0;
+ attr = udev_device_get_sysattr_value(parent, "transport");
+ if (attr) {
+ for (i = 0; i < NVME_PROTOCOL_UNSPEC; i++){
+ if (protocol_name[SYSFS_BUS_NVME + i] &&
+ !strcmp(attr,
+ protocol_name[SYSFS_BUS_NVME + i] + 5)) {
+ pp->sg_id.proto_id = i;
+ break;
+ }
+ }
+ }
+
snprintf(pp->vendor_id, SCSI_VENDOR_SIZE, "NVME");
snprintf(pp->product_id, PATH_PRODUCT_SIZE, "%s",
udev_device_get_sysattr_value(parent, "model"));
@@ -1759,9 +1772,10 @@ sysfs_pathinfo(struct path *pp, const struct _vector *hwtable)
pp->bus = SYSFS_BUS_SCSI;
pp->sg_id.proto_id = SCSI_PROTOCOL_UNSPEC;
}
- if (!strncmp(pp->dev,"nvme", 4))
+ if (!strncmp(pp->dev,"nvme", 4)) {
pp->bus = SYSFS_BUS_NVME;
-
+ pp->sg_id.proto_id = NVME_PROTOCOL_UNSPEC;
+ }
switch (pp->bus) {
case SYSFS_BUS_SCSI:
return scsi_sysfs_pathinfo(pp, hwtable);
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
index be81a83c..a2e56890 100644
--- a/libmultipath/structs.c
+++ b/libmultipath/structs.c
@@ -25,7 +25,6 @@ const char * const protocol_name[LAST_BUS_PROTOCOL_ID + 1] = {
[SYSFS_BUS_UNDEF] = "undef",
[SYSFS_BUS_CCW] = "ccw",
[SYSFS_BUS_CCISS] = "cciss",
- [SYSFS_BUS_NVME] = "nvme",
[SYSFS_BUS_SCSI + SCSI_PROTOCOL_FCP] = "scsi:fcp",
[SYSFS_BUS_SCSI + SCSI_PROTOCOL_SPI] = "scsi:spi",
[SYSFS_BUS_SCSI + SCSI_PROTOCOL_SSA] = "scsi:ssa",
@@ -37,6 +36,13 @@ const char * const protocol_name[LAST_BUS_PROTOCOL_ID + 1] = {
[SYSFS_BUS_SCSI + SCSI_PROTOCOL_ATA] = "scsi:ata",
[SYSFS_BUS_SCSI + SCSI_PROTOCOL_USB] = "scsi:usb",
[SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC] = "scsi:unspec",
+ [SYSFS_BUS_NVME + NVME_PROTOCOL_PCIE] = "nvme:pcie",
+ [SYSFS_BUS_NVME + NVME_PROTOCOL_RDMA] = "nvme:rdma",
+ [SYSFS_BUS_NVME + NVME_PROTOCOL_FC] = "nvme:fc",
+ [SYSFS_BUS_NVME + NVME_PROTOCOL_TCP] = "nvme:tcp",
+ [SYSFS_BUS_NVME + NVME_PROTOCOL_LOOP] = "nvme:loop",
+ [SYSFS_BUS_NVME + NVME_PROTOCOL_APPLE_NVME] = "nvme:apple-nvme",
+ [SYSFS_BUS_NVME + NVME_PROTOCOL_UNSPEC] = "nvme:unspec",
};
struct adapter_group *
@@ -752,11 +758,17 @@ out:
}
unsigned int bus_protocol_id(const struct path *pp) {
- if (!pp || pp->bus < 0 || pp->bus > SYSFS_BUS_SCSI)
+ if (!pp || pp->bus < 0 || pp->bus > SYSFS_BUS_NVME)
return SYSFS_BUS_UNDEF;
- if (pp->bus != SYSFS_BUS_SCSI)
+ if (pp->bus != SYSFS_BUS_SCSI && pp->bus != SYSFS_BUS_NVME)
return pp->bus;
- if ((int)pp->sg_id.proto_id < 0 || pp->sg_id.proto_id > SCSI_PROTOCOL_UNSPEC)
+ if (pp->sg_id.proto_id < 0)
return SYSFS_BUS_UNDEF;
- return SYSFS_BUS_SCSI + pp->sg_id.proto_id;
+ if (pp->bus == SYSFS_BUS_SCSI &&
+ pp->sg_id.proto_id > SCSI_PROTOCOL_UNSPEC)
+ return SYSFS_BUS_UNDEF;
+ if (pp->bus == SYSFS_BUS_NVME &&
+ pp->sg_id.proto_id > NVME_PROTOCOL_UNSPEC)
+ return SYSFS_BUS_UNDEF;
+ return pp->bus + pp->sg_id.proto_id;
}
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index 2525af17..0867b91d 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -56,15 +56,6 @@ enum failback_mode {
FAILBACK_FOLLOWOVER
};
-/* SYSFS_BUS_SCSI should be last, see bus_protocol_id() */
-enum sysfs_buses {
- SYSFS_BUS_UNDEF,
- SYSFS_BUS_CCW,
- SYSFS_BUS_CCISS,
- SYSFS_BUS_NVME,
- SYSFS_BUS_SCSI,
-};
-
enum pathstates {
PSTATE_UNDEF,
PSTATE_FAILED,
@@ -190,14 +181,32 @@ enum scsi_protocol {
SCSI_PROTOCOL_ATA = 8,
SCSI_PROTOCOL_USB = 9, /* USB Attached SCSI (UAS), and others */
SCSI_PROTOCOL_UNSPEC = 0xa, /* No specific protocol */
+ SCSI_PROTOCOL_END = 0xb, /* offset of the next sysfs_buses entry */
+};
+
+/* values from /sys/class/nvme/nvmeX */
+enum nvme_protocol {
+ NVME_PROTOCOL_PCIE = 0,
+ NVME_PROTOCOL_RDMA = 1,
+ NVME_PROTOCOL_FC = 2,
+ NVME_PROTOCOL_TCP = 3,
+ NVME_PROTOCOL_LOOP = 4,
+ NVME_PROTOCOL_APPLE_NVME = 5,
+ NVME_PROTOCOL_UNSPEC = 6, /* unknown protocol */
+};
+
+enum sysfs_buses {
+ SYSFS_BUS_UNDEF,
+ SYSFS_BUS_CCW,
+ SYSFS_BUS_CCISS,
+ SYSFS_BUS_SCSI,
+ SYSFS_BUS_NVME = SYSFS_BUS_SCSI + SCSI_PROTOCOL_END,
};
/*
* Linear ordering of bus/protocol
- * This assumes that SYSFS_BUS_SCSI is last in enum sysfs_buses
- * SCSI is the only bus type for which we distinguish protocols.
*/
-#define LAST_BUS_PROTOCOL_ID (SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC)
+#define LAST_BUS_PROTOCOL_ID (SYSFS_BUS_NVME + NVME_PROTOCOL_UNSPEC)
unsigned int bus_protocol_id(const struct path *pp);
extern const char * const protocol_name[];
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index e1a787d4..7af53588 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1395,7 +1395,9 @@ Regular expression for the protocol of a device to be excluded/included.
The protocol strings that multipath recognizes are \fIscsi:fcp\fR,
\fIscsi:spi\fR, \fIscsi:ssa\fR, \fIscsi:sbp\fR, \fIscsi:srp\fR,
\fIscsi:iscsi\fR, \fIscsi:sas\fR, \fIscsi:adt\fR, \fIscsi:ata\fR,
-\fIscsi:unspec\fR, \fIccw\fR, \fIcciss\fR, \fInvme\fR, and \fIundef\fR.
+\fIscsi:unspec\fR, \fInvme:pcie\fR, \fInvme:rdma\fR, \fInvme:fc\fR,
+\fInvme:tcp\fR, \fInvme:loop\fR, \fInvme:apple-nvme\fR, \fInvme:unspec\fR,
+\fIccw\fR, \fIcciss\fR, and \fIundef\fR.
The protocol that a path is using can be viewed by running
\fBmultipathd show paths format "%d %P"\fR
.RE
@@ -1783,8 +1785,10 @@ The protocol subsection recognizes the following mandatory attribute:
The protocol string of the path device. The possible values are \fIscsi:fcp\fR,
\fIscsi:spi\fR, \fIscsi:ssa\fR, \fIscsi:sbp\fR, \fIscsi:srp\fR,
\fIscsi:iscsi\fR, \fIscsi:sas\fR, \fIscsi:adt\fR, \fIscsi:ata\fR,
-\fIscsi:unspec\fR, \fIccw\fR, \fIcciss\fR, \fInvme\fR, and \fIundef\fR. This is
-\fBnot\fR a regular expression. the path device protcol string must match
+\fIscsi:unspec\fR, \fInvme:pcie\fR, \fInvme:rdma\fR, \fInvme:fc\fR,
+\fInvme:tcp\fR, \fInvme:loop\fR, \fInvme:apple-nvme\fR, \fInvme:unspec\fR,
+\fIccw\fR, \fIcciss\fR, and \fIundef\fR. This is
+\fBnot\fR a regular expression. the path device protocol string must match
exactly. The protocol that a path is using can be viewed by running
\fBmultipathd show paths format "%d %P"\fR
.LP

@ -1,111 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 7 Oct 2022 12:35:44 -0500
Subject: [PATCH] libmultipath: enforce queue_mode bio for nmve:tcp paths
nvme:tcp devices set BLK_MQ_F_BLOCKING (they are the only block devices
which multipath supports that do so), meaning that block_mq expects that
they can block at certain points while servicing a request. However,
due to the way device-mapper sets up its queue, it is not able to set
BLK_MQ_F_BLOCKING when it includes paths that set this flag. Patches
were written to address this issue but they were rejected upstream
https://lore.kernel.org/linux-block/YcH%2FE4JNag0QYYAa@infradead.org/T/#t
The proposed solution was to have multipath use the bio queue_mode for
multipath devices that include nvme:tcp paths.
Multipath devices now automatically add the "queue_mode bio" feature if
they include nvme:tcp paths. If a multipath devices was created with
"queue_mode rq", it will disallow the addition of nvme:tcp paths.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/configure.c | 17 ++++++++++++++++-
libmultipath/structs_vec.c | 7 +++++++
multipath/multipath.conf.5 | 4 +++-
3 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index c6803b40..193bf27d 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -296,6 +296,7 @@ static int wait_for_pending_paths(struct multipath *mpp,
int setup_map(struct multipath *mpp, char **params, struct vectors *vecs)
{
struct pathgroup * pgp;
+ struct path *pp;
struct config *conf;
int i, n_paths, marginal_pathgroups;
char *save_attr;
@@ -311,6 +312,14 @@ int setup_map(struct multipath *mpp, char **params, struct vectors *vecs)
if (mpp->disable_queueing && VECTOR_SIZE(mpp->paths) != 0)
mpp->disable_queueing = 0;
+ /* Force QUEUE_MODE_BIO for maps with nvme:tcp paths */
+ vector_foreach_slot(mpp->paths, pp, i) {
+ if (pp->bus == SYSFS_BUS_NVME &&
+ pp->sg_id.proto_id == NVME_PROTOCOL_TCP) {
+ mpp->queue_mode = QUEUE_MODE_BIO;
+ break;
+ }
+ }
/*
* If this map was created with add_map_without_path(),
* mpp->hwe might not be set yet.
@@ -1191,6 +1200,13 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,
continue;
}
+ cmpp = find_mp_by_wwid(curmp, pp1->wwid);
+ if (cmpp && cmpp->queue_mode == QUEUE_MODE_RQ &&
+ pp1->bus == SYSFS_BUS_NVME && pp1->sg_id.proto_id ==
+ NVME_PROTOCOL_TCP) {
+ orphan_path(pp1, "nvme:tcp path not allowed with request queue_mode multipath device");
+ continue;
+ }
/*
* at this point, we know we really got a new mp
*/
@@ -1229,7 +1245,6 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,
}
verify_paths(mpp);
- cmpp = find_mp_by_wwid(curmp, mpp->wwid);
if (cmpp)
mpp->queue_mode = cmpp->queue_mode;
if (setup_map(mpp, &params, vecs)) {
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index 85d97ac1..4a32b405 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -262,6 +262,13 @@ int adopt_paths(vector pathvec, struct multipath *mpp)
}
if (pp->initialized == INIT_REMOVED)
continue;
+ if (mpp->queue_mode == QUEUE_MODE_RQ &&
+ pp->bus == SYSFS_BUS_NVME &&
+ pp->sg_id.proto_id == NVME_PROTOCOL_TCP) {
+ condlog(2, "%s: mulitpath device %s created with request queue_mode. Unable to add nvme:tcp paths",
+ pp->dev, mpp->alias);
+ continue;
+ }
if (!mpp->paths && !(mpp->paths = vector_alloc()))
goto err;
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 7af53588..01904feb 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -472,7 +472,9 @@ Before kernel 4.20 The default depends on the kernel parameter
\fBdm_mod.use_blk_mq\fR. It is \fImq\fR if the latter is set, and \fIrq\fR
otherwise. Since kernel 4.20, \fIrq\fR and \fImq\fR both correspond to
block-multiqueue. Once a multipath device has been created, its queue_mode
-cannot be changed.
+cannot be changed. \fInvme:tcp\fR paths are only supported in multipath
+devices with queue_mode set to \fIbio\fR. multipath will automatically
+set this when creating a device with \fInvme:tcp\fR paths.
.TP
The default is: \fB<unset>\fR
.RE

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

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 14 Dec 2022 15:38:19 -0600
Subject: [PATCH] libmultipath: don't leak memory on invalid strings
If set_path() or set_str_noslash() are called with a bad value, they
ignore it and continue to use the old value. But they weren't freeing
the bad value, causing a memory leak.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/dict.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index 46b9f225..861d1d17 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -156,6 +156,7 @@ set_path(vector strvec, void *ptr, const char *file, int line_nr)
if ((*str_ptr)[0] != '/'){
condlog(1, "%s line %d, %s is not an absolute path. Ignoring",
file, line_nr, *str_ptr);
+ free(*str_ptr);
*str_ptr = old_str;
} else
free(old_str);
@@ -176,6 +177,7 @@ set_str_noslash(vector strvec, void *ptr, const char *file, int line_nr)
if (strchr(*str_ptr, '/')) {
condlog(1, "%s line %d, %s cannot contain a slash. Ignoring",
file, line_nr, *str_ptr);
+ free(*str_ptr);
*str_ptr = old_str;
} else
free(old_str);

@ -1,195 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 14 Dec 2022 15:38:20 -0600
Subject: [PATCH] libmutipath: validate the argument count of config strings
The features, path_selector, and hardware_handler config options pass
their strings directly into the kernel. If users omit the argument
counts from these strings, or use the wrong value, the kernel's table
parsing gets completely messed up, and the error messages it prints
don't reflect what actully went wrong. To avoid messing up the
kernel table parsing, verify that these strings correctly set the
argument count to the number of arguments they have.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/dict.c | 110 ++++++++++++++++++++++++++++++++++++++++----
1 file changed, 101 insertions(+), 9 deletions(-)
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index 861d1d17..eb2f33a2 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -142,6 +142,58 @@ set_dir(vector strvec, void *ptr, const char *file, int line_nr)
return 0;
}
+static int
+set_arg_str(vector strvec, void *ptr, int count_idx, const char *file,
+ int line_nr)
+{
+ char **str_ptr = (char **)ptr;
+ char *old_str = *str_ptr;
+ const char * const spaces = " \f\r\t\v";
+ char *p, *end;
+ int idx = -1;
+ long int count = -1;
+
+ *str_ptr = set_value(strvec);
+ if (!*str_ptr) {
+ free(old_str);
+ return 1;
+ }
+ p = *str_ptr;
+ while (*p != '\0') {
+ p += strspn(p, spaces);
+ if (*p == '\0')
+ break;
+ idx += 1;
+ if (idx == count_idx) {
+ errno = 0;
+ count = strtol(p, &end, 10);
+ if (errno == ERANGE || end == p ||
+ !(isspace(*end) || *end == '\0')) {
+ count = -1;
+ break;
+ }
+ }
+ p += strcspn(p, spaces);
+ }
+ if (count < 0) {
+ condlog(1, "%s line %d, missing argument count for %s",
+ file, line_nr, (char*)VECTOR_SLOT(strvec, 0));
+ goto fail;
+ }
+ if (count != idx - count_idx) {
+ condlog(1, "%s line %d, invalid argument count for %s:, got '%ld' expected '%d'",
+ file, line_nr, (char*)VECTOR_SLOT(strvec, 0), count,
+ idx - count_idx);
+ goto fail;
+ }
+ free(old_str);
+ return 0;
+fail:
+ free(*str_ptr);
+ *str_ptr = old_str;
+ return 0;
+}
+
static int
set_path(vector strvec, void *ptr, const char *file, int line_nr)
{
@@ -294,6 +346,14 @@ def_ ## option ## _handler (struct config *conf, vector strvec, \
return set_int(strvec, &conf->option, minval, maxval, file, line_nr); \
}
+#define declare_def_arg_str_handler(option, count_idx) \
+static int \
+def_ ## option ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
+{ \
+ return set_arg_str(strvec, &conf->option, count_idx, file, line_nr); \
+}
+
#define declare_def_snprint(option, function) \
static int \
snprint_def_ ## option (struct config *conf, struct strbuf *buff, \
@@ -346,6 +406,17 @@ hw_ ## option ## _handler (struct config *conf, vector strvec, \
return set_int(strvec, &hwe->option, minval, maxval, file, line_nr); \
}
+#define declare_hw_arg_str_handler(option, count_idx) \
+static int \
+hw_ ## option ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
+{ \
+ struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); \
+ if (!hwe) \
+ return 1; \
+ return set_arg_str(strvec, &hwe->option, count_idx, file, line_nr); \
+}
+
#define declare_hw_snprint(option, function) \
static int \
@@ -377,6 +448,16 @@ ovr_ ## option ## _handler (struct config *conf, vector strvec, \
file, line_nr); \
}
+#define declare_ovr_arg_str_handler(option, count_idx) \
+static int \
+ovr_ ## option ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
+{ \
+ if (!conf->overrides) \
+ return 1; \
+ return set_arg_str(strvec, &conf->overrides->option, count_idx, file, line_nr); \
+}
+
#define declare_ovr_snprint(option, function) \
static int \
snprint_ovr_ ## option (struct config *conf, struct strbuf *buff, \
@@ -407,6 +488,17 @@ mp_ ## option ## _handler (struct config *conf, vector strvec, \
return set_int(strvec, &mpe->option, minval, maxval, file, line_nr); \
}
+#define declare_mp_arg_str_handler(option, count_idx) \
+static int \
+mp_ ## option ## _handler (struct config *conf, vector strvec, \
+ const char *file, int line_nr) \
+{ \
+ struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable); \
+ if (!mpe) \
+ return 1; \
+ return set_arg_str(strvec, &mpe->option, count_idx, file, line_nr); \
+}
+
#define declare_mp_snprint(option, function) \
static int \
snprint_mp_ ## option (struct config *conf, struct strbuf *buff, \
@@ -591,13 +683,13 @@ snprint_def_marginal_pathgroups(struct config *conf, struct strbuf *buff,
}
-declare_def_handler(selector, set_str)
+declare_def_arg_str_handler(selector, 1)
declare_def_snprint_defstr(selector, print_str, DEFAULT_SELECTOR)
-declare_hw_handler(selector, set_str)
+declare_hw_arg_str_handler(selector, 1)
declare_hw_snprint(selector, print_str)
-declare_ovr_handler(selector, set_str)
+declare_ovr_arg_str_handler(selector, 1)
declare_ovr_snprint(selector, print_str)
-declare_mp_handler(selector, set_str)
+declare_mp_arg_str_handler(selector, 1)
declare_mp_snprint(selector, print_str)
static int snprint_uid_attrs(struct config *conf, struct strbuf *buff,
@@ -672,13 +764,13 @@ declare_hw_snprint(prio_args, print_str)
declare_mp_handler(prio_args, set_str)
declare_mp_snprint(prio_args, print_str)
-declare_def_handler(features, set_str)
+declare_def_arg_str_handler(features, 0)
declare_def_snprint_defstr(features, print_str, DEFAULT_FEATURES)
-declare_ovr_handler(features, set_str)
+declare_ovr_arg_str_handler(features, 0)
declare_ovr_snprint(features, print_str)
-declare_hw_handler(features, set_str)
+declare_hw_arg_str_handler(features, 0)
declare_hw_snprint(features, print_str)
-declare_mp_handler(features, set_str)
+declare_mp_arg_str_handler(features, 0)
declare_mp_snprint(features, print_str)
declare_def_handler(checker_name, set_str)
@@ -1857,7 +1949,7 @@ declare_hw_snprint(revision, print_str)
declare_hw_handler(bl_product, set_str)
declare_hw_snprint(bl_product, print_str)
-declare_hw_handler(hwhandler, set_str)
+declare_hw_arg_str_handler(hwhandler, 0)
declare_hw_snprint(hwhandler, print_str)
/*

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

@ -1,45 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 31 Jan 2023 09:58:55 -0600
Subject: [PATCH] libmultipath: select resize action even if reload is forced
The ACT_RESIZE action is the same as the ACT_RELOAD action, except that
it flushes outstanding IO because the device size is changing and
the new size might be too small for some of the outstanding IO. If we've
detected a size change, and a forced reload is requested, we still need
to flush the IO because the reload will change the device size.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/configure.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 09d7de0f..c91a8139 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -769,11 +769,6 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
return;
}
- if (force_reload) {
- mpp->force_udev_reload = 1;
- select_reload_action(mpp, "forced by user");
- return;
- }
if (cmpp->size != mpp->size) {
mpp->force_udev_reload = 1;
mpp->action = ACT_RESIZE;
@@ -782,6 +777,12 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
return;
}
+ if (force_reload) {
+ mpp->force_udev_reload = 1;
+ select_reload_action(mpp, "forced by user");
+ return;
+ }
+
if (!is_udev_ready(cmpp) && count_active_paths(mpp) > 0) {
mpp->force_udev_reload = 1;
select_reload_action(mpp, "udev incomplete");

@ -1,67 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 31 Jan 2023 10:35:10 -0600
Subject: [PATCH] libmultipath: cleanup ACT_CREATE code in select_action
Combine the two separate blocks that set ACT_CREATE into one.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/configure.c | 38 +++++++++++++++++---------------------
1 file changed, 17 insertions(+), 21 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index c91a8139..24d051dd 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -728,33 +728,29 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
cmpp = find_mp_by_wwid(curmp, mpp->wwid);
cmpp_by_name = find_mp_by_alias(curmp, mpp->alias);
- if (!cmpp_by_name) {
- if (cmpp) {
- condlog(2, "%s: rename %s to %s", mpp->wwid,
- cmpp->alias, mpp->alias);
- strlcpy(mpp->alias_old, cmpp->alias, WWID_SIZE);
- mpp->action = ACT_RENAME;
- if (force_reload) {
- mpp->force_udev_reload = 1;
- mpp->action = ACT_FORCERENAME;
- }
- return;
+ if (!cmpp) {
+ if (cmpp_by_name) {
+ condlog(1, "%s: can't use alias \"%s\" used by %s, falling back to WWID",
+ mpp->wwid, mpp->alias, cmpp_by_name->wwid);
+ /* We can do this because wwid wasn't found */
+ free(mpp->alias);
+ mpp->alias = strdup(mpp->wwid);
}
mpp->action = ACT_CREATE;
- condlog(3, "%s: set ACT_CREATE (map does not exist)",
- mpp->alias);
+ condlog(3, "%s: set ACT_CREATE (map does not exist%s)",
+ mpp->alias, cmpp_by_name ? ", name changed" : "");
return;
}
- if (!cmpp) {
- condlog(1, "%s: can't use alias \"%s\" used by %s, falling back to WWID",
- mpp->wwid, mpp->alias, cmpp_by_name->wwid);
- /* We can do this because wwid wasn't found */
- free(mpp->alias);
- mpp->alias = strdup(mpp->wwid);
- mpp->action = ACT_CREATE;
- condlog(3, "%s: set ACT_CREATE (map does not exist, name changed)",
+ if (!cmpp_by_name) {
+ condlog(2, "%s: rename %s to %s", mpp->wwid, cmpp->alias,
mpp->alias);
+ strlcpy(mpp->alias_old, cmpp->alias, WWID_SIZE);
+ mpp->action = ACT_RENAME;
+ if (force_reload) {
+ mpp->force_udev_reload = 1;
+ mpp->action = ACT_FORCERENAME;
+ }
return;
}

@ -1,185 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 31 Jan 2023 12:00:31 -0600
Subject: [PATCH] libmultipath: keep renames from stopping other multipath
actions
If select_action() is called and a multipath device needs to be renamed,
the code currently checks if force_reload is set, and if so, does the
reload after the rename. But if force_reload isn't set, only the rename
happens, regardless of what other actions are needed. This can happen if
multipathd starts up and a device needs both a reload and a rename.
Make multipath check for resize, reload, and switch pathgroup along with
rename, and do both if necessary.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/configure.c | 62 +++++++++++++++++-----------------------
libmultipath/configure.h | 4 ++-
2 files changed, 30 insertions(+), 36 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 24d051dd..bbdbb8ca 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -714,7 +714,8 @@ static bool is_udev_ready(struct multipath *cmpp)
static void
select_reload_action(struct multipath *mpp, const char *reason)
{
- mpp->action = ACT_RELOAD;
+ mpp->action = mpp->action == ACT_RENAME ? ACT_RELOAD_RENAME :
+ ACT_RELOAD;
condlog(3, "%s: set ACT_RELOAD (%s)", mpp->alias, reason);
}
@@ -725,6 +726,7 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
struct multipath * cmpp_by_name;
char * mpp_feat, * cmpp_feat;
+ mpp->action = ACT_NOTHING;
cmpp = find_mp_by_wwid(curmp, mpp->wwid);
cmpp_by_name = find_mp_by_alias(curmp, mpp->alias);
@@ -747,14 +749,8 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
mpp->alias);
strlcpy(mpp->alias_old, cmpp->alias, WWID_SIZE);
mpp->action = ACT_RENAME;
- if (force_reload) {
- mpp->force_udev_reload = 1;
- mpp->action = ACT_FORCERENAME;
- }
- return;
- }
-
- if (cmpp != cmpp_by_name) {
+ /* don't return here. Check for other needed actions */
+ } else if (cmpp != cmpp_by_name) {
condlog(2, "%s: unable to rename %s to %s (%s is used by %s)",
mpp->wwid, cmpp->alias, mpp->alias,
mpp->alias, cmpp_by_name->wwid);
@@ -762,12 +758,13 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
FREE(mpp->alias);
mpp->alias = STRDUP(cmpp->alias);
mpp->action = ACT_IMPOSSIBLE;
- return;
+ /* don't return here. Check for other needed actions */
}
if (cmpp->size != mpp->size) {
mpp->force_udev_reload = 1;
- mpp->action = ACT_RESIZE;
+ mpp->action = mpp->action == ACT_RENAME ? ACT_RESIZE_RENAME :
+ ACT_RESIZE;
condlog(3, "%s: set ACT_RESIZE (size change)",
mpp->alias);
return;
@@ -843,14 +840,14 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
return;
}
if (cmpp->nextpg != mpp->bestpg) {
- mpp->action = ACT_SWITCHPG;
+ mpp->action = mpp->action == ACT_RENAME ? ACT_SWITCHPG_RENAME :
+ ACT_SWITCHPG;
condlog(3, "%s: set ACT_SWITCHPG (next path group change)",
mpp->alias);
return;
}
- mpp->action = ACT_NOTHING;
- condlog(3, "%s: set ACT_NOTHING (map unchanged)",
- mpp->alias);
+ if (mpp->action == ACT_NOTHING)
+ condlog(3, "%s: set ACT_NOTHING (map unchanged)", mpp->alias);
return;
}
@@ -951,6 +948,17 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
}
}
+ if (mpp->action == ACT_RENAME || mpp->action == ACT_SWITCHPG_RENAME ||
+ mpp->action == ACT_RELOAD_RENAME ||
+ mpp->action == ACT_RESIZE_RENAME) {
+ conf = get_multipath_config();
+ pthread_cleanup_push(put_multipath_config, conf);
+ r = dm_rename(mpp->alias_old, mpp->alias,
+ conf->partition_delim, mpp->skip_kpartx);
+ pthread_cleanup_pop(1);
+ if (r == DOMAP_FAIL)
+ return r;
+ }
switch (mpp->action) {
case ACT_REJECT:
case ACT_NOTHING:
@@ -958,6 +966,7 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
return DOMAP_EXIST;
case ACT_SWITCHPG:
+ case ACT_SWITCHPG_RENAME:
dm_switchgroup(mpp->alias, mpp->bestpg);
/*
* we may have avoided reinstating paths because there where in
@@ -984,6 +993,7 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
break;
case ACT_RELOAD:
+ case ACT_RELOAD_RENAME:
sysfs_set_max_sectors_kb(mpp, 1);
if (mpp->ghost_delay_tick > 0 && pathcount(mpp, PATH_UP))
mpp->ghost_delay_tick = 0;
@@ -991,6 +1001,7 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
break;
case ACT_RESIZE:
+ case ACT_RESIZE_RENAME:
sysfs_set_max_sectors_kb(mpp, 1);
if (mpp->ghost_delay_tick > 0 && pathcount(mpp, PATH_UP))
mpp->ghost_delay_tick = 0;
@@ -998,29 +1009,10 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
break;
case ACT_RENAME:
- conf = get_multipath_config();
- pthread_cleanup_push(put_multipath_config, conf);
- r = dm_rename(mpp->alias_old, mpp->alias,
- conf->partition_delim, mpp->skip_kpartx);
- pthread_cleanup_pop(1);
- break;
-
- case ACT_FORCERENAME:
- conf = get_multipath_config();
- pthread_cleanup_push(put_multipath_config, conf);
- r = dm_rename(mpp->alias_old, mpp->alias,
- conf->partition_delim, mpp->skip_kpartx);
- pthread_cleanup_pop(1);
- if (r) {
- sysfs_set_max_sectors_kb(mpp, 1);
- if (mpp->ghost_delay_tick > 0 &&
- pathcount(mpp, PATH_UP))
- mpp->ghost_delay_tick = 0;
- r = dm_addmap_reload(mpp, params, 0);
- }
break;
default:
+ r = DOMAP_FAIL;
break;
}
diff --git a/libmultipath/configure.h b/libmultipath/configure.h
index 2bf73e65..9d935db3 100644
--- a/libmultipath/configure.h
+++ b/libmultipath/configure.h
@@ -18,9 +18,11 @@ enum actions {
ACT_RENAME,
ACT_CREATE,
ACT_RESIZE,
- ACT_FORCERENAME,
+ ACT_RELOAD_RENAME,
ACT_DRY_RUN,
ACT_IMPOSSIBLE,
+ ACT_RESIZE_RENAME,
+ ACT_SWITCHPG_RENAME,
};
/*

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

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

@ -1,159 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 20 Dec 2022 17:41:10 -0600
Subject: [PATCH] multipathd: make pr registration consistent
multipathd was inconsistent on what it did with persistent reservations
when a multipath device was created. If a multipath device with a
configured reservation key was created during configure(), multipathd
would try to read the registered keys using an active path. If it saw a
matching key, it would set the prflag, but not attempt to register the
key on any of the other paths. This means that if a new path had
appeared while multipathd was not running, it wouldn't register the key
on this path.
If the multipath device was created during ev_add_path(), multipathd
would used the added path to check if there was a matching key and if
there was, register the key only on the added path and then set the
prflag. This could be problematic if the device was created with
multiple paths, for instance because find_mutipaths was set to "yes" and
a second path just appeared. In this case, if the device happened to be
only registered on the second path, it would not get registered on the
first path.
If the multipath device was added to multipathd during a call to
ev_add_map(), multipathd wouldn't set the prflag or register the key on
any paths.
After a device was created with the prflag set, if a new path appeared
before the creation uevent, and multipathd was forced to delay adding
it, when it finally updated the multipath device, the key would be
registered on all paths, fixing any paths missed during creation.
However, if a new path appeared after the creation uevent, the key would
only be registered on that new path. Any paths that were missed on
creation would stay missed.
persistent key registration needs to be handled consistently. This
patch does so by making sure that however a multipath device is added to
multipathd, it will check to see if the configured key is registered. If
it is, multipathd will set the prflag and register the key on all the
currently active paths.
When a new path is added, multipathd will use it to check for active
keys, as before. But if it finds a matching key and prflag isn't
currently set, it will register the key on all paths.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
multipathd/main.c | 43 +++++++++++++++++++++++++++++--------------
1 file changed, 29 insertions(+), 14 deletions(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index a098f3c2..e7c17182 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -512,13 +512,26 @@ flush_map_nopaths(struct multipath *mpp, struct vectors *vecs) {
return false;
}
+static void
+pr_register_active_paths(struct multipath *mpp)
+{
+ unsigned int i, j;
+ struct path *pp;
+ struct pathgroup *pgp;
+
+ vector_foreach_slot (mpp->pg, pgp, i) {
+ vector_foreach_slot (pgp->paths, pp, j) {
+ if ((pp->state == PATH_UP) || (pp->state == PATH_GHOST))
+ mpath_pr_event_handle(pp);
+ }
+ }
+}
+
static int
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);
@@ -535,15 +548,6 @@ retry:
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;
@@ -569,6 +573,11 @@ fail:
sync_map_state(mpp);
+ if (!mpp->prflag)
+ update_map_pr(mpp);
+ if (mpp->prflag)
+ pr_register_active_paths(mpp);
+
if (retries < 0)
condlog(0, "%s: failed reload in new map update", mpp->alias);
return 0;
@@ -1073,6 +1082,7 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map)
int start_waiter = 0;
int ret;
int ro;
+ unsigned char prflag = 0;
/*
* need path UID to go any further
@@ -1116,6 +1126,8 @@ rescan:
verify_paths(mpp);
mpp->action = ACT_RELOAD;
+ prflag = mpp->prflag;
+ mpath_pr_event_handle(pp);
} else {
if (!should_multipath(pp, vecs->pathvec, vecs->mpvec)) {
orphan_path(pp, "only one path");
@@ -1134,9 +1146,6 @@ rescan:
goto fail; /* leave path added to pathvec */
}
- /* persistent reservation check*/
- mpath_pr_event_handle(pp);
-
/* ro check - if new path is ro, force map to be ro as well */
ro = sysfs_get_ro(pp);
if (ro == 1)
@@ -1201,6 +1210,10 @@ rescan:
sync_map_state(mpp);
if (retries >= 0) {
+ if (start_waiter)
+ update_map_pr(mpp);
+ if (mpp->prflag && !prflag)
+ pr_register_active_paths(mpp);
condlog(2, "%s [%s]: path added to devmap %s",
pp->dev, pp->dev_t, mpp->alias);
return 0;
@@ -2745,6 +2758,8 @@ configure (struct vectors * vecs)
if (remember_wwid(mpp->wwid) == 1)
trigger_paths_udev_change(mpp, true);
update_map_pr(mpp);
+ if (mpp->prflag)
+ pr_register_active_paths(mpp);
}
/*

@ -1,165 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 20 Dec 2022 17:41:11 -0600
Subject: [PATCH] libmultipath: make prflag an enum
In preparation for a future patch, make prflag an enum, and change the
reply of cli_getprstatus() to a string.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmpathpersist/mpath_persist.c | 2 +-
libmultipath/structs.h | 8 +++++++-
multipathd/cli_handlers.c | 16 +++++++++-------
multipathd/main.c | 14 +++++++-------
4 files changed, 24 insertions(+), 16 deletions(-)
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
index 803a2a28..01e8ca25 100644
--- a/libmpathpersist/mpath_persist.c
+++ b/libmpathpersist/mpath_persist.c
@@ -924,7 +924,7 @@ int update_map_pr(struct multipath *mpp)
if (isFound)
{
- mpp->prflag = 1;
+ mpp->prflag = PRFLAG_SET;
condlog(2, "%s: prflag flag set.", mpp->alias );
}
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index 4b308561..5ec591bc 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -368,6 +368,12 @@ struct path {
typedef int (pgpolicyfn) (struct multipath *, vector);
+
+enum prflag_value {
+ PRFLAG_UNSET,
+ PRFLAG_SET,
+};
+
struct multipath {
char wwid[WWID_SIZE];
char alias_old[WWID_SIZE];
@@ -441,7 +447,7 @@ struct multipath {
int prkey_source;
struct be64 reservation_key;
uint8_t sa_flags;
- unsigned char prflag;
+ int prflag;
int all_tg_pt;
struct gen_multipath generic_mp;
bool fpin_must_reload;
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index 6d3a0ae2..90d2c388 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -1304,6 +1304,10 @@ cli_shutdown (void * v, char ** reply, int * len, void * data)
int
cli_getprstatus (void * v, char ** reply, int * len, void * data)
{
+ static const char * const prflag_str[] = {
+ [PRFLAG_UNSET] = "unset\n",
+ [PRFLAG_SET] = "set\n",
+ };
struct multipath * mpp;
struct vectors * vecs = (struct vectors *)data;
char * param = get_keyparam(v, MAP);
@@ -1315,9 +1319,7 @@ cli_getprstatus (void * v, char ** reply, int * len, void * data)
if (!mpp)
return 1;
- condlog(3, "%s: prflag = %u", param, (unsigned int)mpp->prflag);
-
- *len = asprintf(reply, "%d", mpp->prflag);
+ *len = asprintf(reply, "%s", prflag_str[mpp->prflag]);
if (*len < 0)
return 1;
@@ -1340,8 +1342,8 @@ cli_setprstatus(void * v, char ** reply, int * len, void * data)
if (!mpp)
return 1;
- if (!mpp->prflag) {
- mpp->prflag = 1;
+ if (mpp->prflag != PRFLAG_SET) {
+ mpp->prflag = PRFLAG_SET;
condlog(2, "%s: prflag set", param);
}
@@ -1363,8 +1365,8 @@ cli_unsetprstatus(void * v, char ** reply, int * len, void * data)
if (!mpp)
return 1;
- if (mpp->prflag) {
- mpp->prflag = 0;
+ if (mpp->prflag != PRFLAG_UNSET) {
+ mpp->prflag = PRFLAG_UNSET;
condlog(2, "%s: prflag unset", param);
}
diff --git a/multipathd/main.c b/multipathd/main.c
index e7c17182..532ca15b 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -573,9 +573,9 @@ fail:
sync_map_state(mpp);
- if (!mpp->prflag)
+ if (mpp->prflag == PRFLAG_UNSET)
update_map_pr(mpp);
- if (mpp->prflag)
+ if (mpp->prflag == PRFLAG_SET)
pr_register_active_paths(mpp);
if (retries < 0)
@@ -1082,7 +1082,7 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map)
int start_waiter = 0;
int ret;
int ro;
- unsigned char prflag = 0;
+ unsigned char prflag = PRFLAG_UNSET;
/*
* need path UID to go any further
@@ -1212,7 +1212,7 @@ rescan:
if (retries >= 0) {
if (start_waiter)
update_map_pr(mpp);
- if (mpp->prflag && !prflag)
+ if (mpp->prflag == PRFLAG_SET && prflag == PRFLAG_UNSET)
pr_register_active_paths(mpp);
condlog(2, "%s [%s]: path added to devmap %s",
pp->dev, pp->dev_t, mpp->alias);
@@ -2414,7 +2414,7 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
}
if (newstate == PATH_UP || newstate == PATH_GHOST) {
- if (pp->mpp->prflag) {
+ if (pp->mpp->prflag == PRFLAG_SET) {
/*
* Check Persistent Reservation.
*/
@@ -2758,7 +2758,7 @@ configure (struct vectors * vecs)
if (remember_wwid(mpp->wwid) == 1)
trigger_paths_udev_change(mpp, true);
update_map_pr(mpp);
- if (mpp->prflag)
+ if (mpp->prflag == PRFLAG_SET)
pr_register_active_paths(mpp);
}
@@ -3668,7 +3668,7 @@ void * mpath_pr_event_handler_fn (void * pathp )
{
condlog(0,"%s: Reservation registration failed. Error: %d", pp->dev, ret);
}
- mpp->prflag = 1;
+ mpp->prflag = PRFLAG_SET;
free(param);
out:

@ -1,152 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 20 Dec 2022 17:41:12 -0600
Subject: [PATCH] multipathd: handle no active paths in update_map_pr
When a multipath device is first created, if it has a reservation key
configured, update_map_pr() will check for a matching key on the active
paths. If there were no active paths to check with, multipathd was
leaving mpp->prflag in PRFLAG_UNSET, as if there were no matching keys.
It's possible that when update_map_pr() is called, all the paths will be
in the PATH_PENDING state because the checkers haven't completed yet. In
this case, multipathd was treating the device as having no registered
keys without ever checking.
To solve this, multipath devices now start with prflag = PRFLAG_UNKNOWN.
It will remain in this state until multipathd actually tries to get the
registered keys down a path. If the map is in this state, it will check
newly active paths, and if it finds a matching key, it will register
the key down all active paths.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmpathpersist/mpath_persist.c | 8 ++++++++
libmultipath/structs.h | 1 +
multipathd/cli_handlers.c | 1 +
multipathd/main.c | 19 ++++++++++++++-----
4 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
index 01e8ca25..3fc60da2 100644
--- a/libmpathpersist/mpath_persist.c
+++ b/libmpathpersist/mpath_persist.c
@@ -879,6 +879,7 @@ int update_map_pr(struct multipath *mpp)
if (!get_be64(mpp->reservation_key))
{
/* Nothing to do. Assuming pr mgmt feature is disabled*/
+ mpp->prflag = PRFLAG_UNSET;
condlog(4, "%s: reservation_key not set in multipath.conf",
mpp->alias);
return MPATH_PR_SUCCESS;
@@ -890,6 +891,13 @@ int update_map_pr(struct multipath *mpp)
condlog(0,"%s : failed to alloc resp in update_map_pr", mpp->alias);
return MPATH_PR_OTHER;
}
+ if (count_active_paths(mpp) == 0)
+ {
+ condlog(0,"%s: No available paths to check pr status",
+ mpp->alias);
+ return MPATH_PR_OTHER;
+ }
+ mpp->prflag = PRFLAG_UNSET;
ret = mpath_prin_activepath(mpp, MPATH_PRIN_RKEY_SA, resp, noisy);
if (ret != MPATH_PR_SUCCESS )
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index 5ec591bc..c1e93e6e 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -370,6 +370,7 @@ typedef int (pgpolicyfn) (struct multipath *, vector);
enum prflag_value {
+ PRFLAG_UNKNOWN,
PRFLAG_UNSET,
PRFLAG_SET,
};
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index 90d2c388..f322f10f 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -1305,6 +1305,7 @@ int
cli_getprstatus (void * v, char ** reply, int * len, void * data)
{
static const char * const prflag_str[] = {
+ [PRFLAG_UNKNOWN] = "unknown\n",
[PRFLAG_UNSET] = "unset\n",
[PRFLAG_SET] = "set\n",
};
diff --git a/multipathd/main.c b/multipathd/main.c
index 532ca15b..075e7b13 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -573,7 +573,7 @@ fail:
sync_map_state(mpp);
- if (mpp->prflag == PRFLAG_UNSET)
+ if (mpp->prflag != PRFLAG_SET)
update_map_pr(mpp);
if (mpp->prflag == PRFLAG_SET)
pr_register_active_paths(mpp);
@@ -1212,7 +1212,7 @@ rescan:
if (retries >= 0) {
if (start_waiter)
update_map_pr(mpp);
- if (mpp->prflag == PRFLAG_SET && prflag == PRFLAG_UNSET)
+ if (mpp->prflag == PRFLAG_SET && prflag != PRFLAG_SET)
pr_register_active_paths(mpp);
condlog(2, "%s [%s]: path added to devmap %s",
pp->dev, pp->dev_t, mpp->alias);
@@ -2414,13 +2414,17 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
}
if (newstate == PATH_UP || newstate == PATH_GHOST) {
- if (pp->mpp->prflag == PRFLAG_SET) {
+ if (pp->mpp->prflag != PRFLAG_UNSET) {
+ int prflag = pp->mpp->prflag;
/*
* Check Persistent Reservation.
*/
condlog(2, "%s: checking persistent "
"reservation registration", pp->dev);
mpath_pr_event_handle(pp);
+ if (pp->mpp->prflag == PRFLAG_SET &&
+ prflag != PRFLAG_SET)
+ pr_register_active_paths(pp->mpp);
}
}
@@ -3616,6 +3620,7 @@ void * mpath_pr_event_handler_fn (void * pathp )
goto out;
}
+ mpp->prflag = PRFLAG_UNSET;
ret = prin_do_scsi_ioctl(pp->dev, MPATH_PRIN_RKEY_SA, resp, 0);
if (ret != MPATH_PR_SUCCESS )
{
@@ -3686,12 +3691,12 @@ int mpath_pr_event_handle(struct path *pp)
struct multipath * mpp;
if (pp->bus != SYSFS_BUS_SCSI)
- return 0;
+ goto no_pr;
mpp = pp->mpp;
if (!get_be64(mpp->reservation_key))
- return -1;
+ goto no_pr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
@@ -3704,4 +3709,8 @@ int mpath_pr_event_handle(struct path *pp)
pthread_attr_destroy(&attr);
rc = pthread_join(thread, NULL);
return 0;
+
+no_pr:
+ pp->mpp->prflag = PRFLAG_UNSET;
+ return 0;
}

@ -1,68 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Thu, 2 Feb 2023 09:20:35 +0100
Subject: [PATCH] libmpathpersist: fix resource leak in update_map_pr()
The "no available paths" case would leak the memory resp points to.
Found by coverity.
Fixes: 50e2c16 ("multipathd: handle no active paths in update_map_pr")
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmpathpersist/mpath_persist.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
index 3fc60da2..29b64937 100644
--- a/libmpathpersist/mpath_persist.c
+++ b/libmpathpersist/mpath_persist.c
@@ -874,7 +874,7 @@ int update_map_pr(struct multipath *mpp)
int noisy=0;
struct prin_resp *resp;
unsigned int i;
- int ret, isFound;
+ int ret = MPATH_PR_OTHER, isFound;
if (!get_be64(mpp->reservation_key))
{
@@ -895,7 +895,7 @@ int update_map_pr(struct multipath *mpp)
{
condlog(0,"%s: No available paths to check pr status",
mpp->alias);
- return MPATH_PR_OTHER;
+ goto out;
}
mpp->prflag = PRFLAG_UNSET;
ret = mpath_prin_activepath(mpp, MPATH_PRIN_RKEY_SA, resp, noisy);
@@ -903,15 +903,15 @@ int update_map_pr(struct multipath *mpp)
if (ret != MPATH_PR_SUCCESS )
{
condlog(0,"%s : pr in read keys service action failed Error=%d", mpp->alias, ret);
- free(resp);
- return ret;
+ goto out;
}
+ ret = MPATH_PR_SUCCESS;
+
if (resp->prin_descriptor.prin_readkeys.additional_length == 0 )
{
condlog(3,"%s: No key found. Device may not be registered. ", mpp->alias);
- free(resp);
- return MPATH_PR_SUCCESS;
+ goto out;
}
condlog(2, "%s: Multipath reservation_key: 0x%" PRIx64 " ", mpp->alias,
@@ -936,6 +936,7 @@ int update_map_pr(struct multipath *mpp)
condlog(2, "%s: prflag flag set.", mpp->alias );
}
+out:
free(resp);
- return MPATH_PR_SUCCESS;
+ return ret;
}

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

@ -1,114 +1,39 @@
Name: device-mapper-multipath
Version: 0.8.7
Release: 22%{?dist}
Version: 0.9.9
Release: 5%{?dist}
Summary: Tools to manage multipath devices using device-mapper
License: GPLv2
URL: http://christophe.varoqui.free.fr/
# The source for this package was pulled from upstream's git repo. Use the
# following command to generate the tarball
# curl -L https://github.com/opensvc/multipath-tools/archive/0.8.7.tar.gz -o multipath-tools-0.8.7.tgz
Source0: multipath-tools-0.8.7.tgz
# curl -L https://github.com/opensvc/multipath-tools/archive/0.9.9.tar.gz -o multipath-tools-0.9.9.tgz
Source0: multipath-tools-0.9.9.tgz
Source1: multipath.conf
Patch0001: 0001-multipath-tools-add-info-about-IO-affinity-path-sele.patch
Patch0002: 0002-multipathd-fix-missing-persistent-reseravtion-for-ac.patch
Patch0003: 0003-multipath-tools-minor-fixes-to-multipath.conf.5-man-.patch
Patch0004: 0004-multipath-tools-make-IBM-XIV-config-work-with-alua-a.patch
Patch0005: 0005-multipathd.socket-add-missing-conditions-from-servic.patch
Patch0006: 0006-multipath-tools-make-IBM-2107900-DS8000-config-work-.patch
Patch0007: 0007-multipath-tools-make-EMC-SYMMETRIX-config-work-with-.patch
Patch0008: 0008-multipath-tools-make-EMC-Invista-config-work-with-al.patch
Patch0009: 0009-multipath-tools-make-COMPELNT-Compellent-Vol-config-.patch
Patch0010: 0010-multipath-tools-remove-Compellent-maintainer.patch
Patch0011: 0011-Revert-multipath-tools-make-EMC-Invista-config-work-.patch
Patch0012: 0012-Revert-multipath-tools-make-EMC-SYMMETRIX-config-wor.patch
Patch0013: 0013-RH-fixup-udev-rules-for-redhat.patch
Patch0014: 0014-RH-Remove-the-property-blacklist-exception-builtin.patch
Patch0015: 0015-RH-don-t-start-without-a-config-file.patch
Patch0016: 0016-RH-Fix-nvme-function-missing-argument.patch
Patch0017: 0017-RH-use-rpm-optflags-if-present.patch
Patch0018: 0018-RH-add-mpathconf.patch
Patch0019: 0019-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch
Patch0020: 0020-RH-reset-default-find_mutipaths-value-to-off.patch
Patch0021: 0021-RH-attempt-to-get-ANA-info-via-sysfs-first.patch
Patch0022: 0022-RH-make-parse_vpd_pg83-match-scsi_id-output.patch
Patch0023: 0023-libmultipath-add-section-name-to-invalid-keyword-out.patch
Patch0024: 0024-libmultipath-use-typedef-for-keyword-handler-functio.patch
Patch0025: 0025-libmultipath-print-the-correct-file-when-parsing-fai.patch
Patch0026: 0026-libmultipath-pass-file-and-line-number-to-keyword-ha.patch
Patch0027: 0027-libmultipath-make-set_int-take-a-range-for-valid-val.patch
Patch0028: 0028-libmultipath-improve-checks-for-set_str.patch
Patch0029: 0029-libmultipath-deprecate-file-and-directory-config-opt.patch
Patch0030: 0030-libmultipath-split-set_int-to-enable-reuse.patch
Patch0031: 0031-libmultipath-cleanup-invalid-config-handling.patch
Patch0032: 0032-libmultipath-don-t-return-error-on-invalid-values.patch
Patch0033: 0033-multipathd-avoid-unnecessary-path-read-only-reloads.patch
Patch0034: 0034-multipath-fix-exit-status-of-multipath-T.patch
Patch0035: 0035-RH-mpathconf-fix-setting-property_blacklist.patch
Patch0036: 0036-libmultipath-fix-disassemble-status-for-historical-s.patch
Patch0037: 0037-libmultipath-make-helper-function-to-trigger-path-ue.patch
Patch0038: 0038-multipathd-trigger-udev-change-on-path-addition.patch
Patch0039: 0039-RH-add-support-to-mpathconf-for-setting-arbitrary-de.patch
Patch0040: 0040-RH-add-support-to-mpathconf-for-setting-recheck_wwid.patch
Patch0041: 0041-multipathd-handle-fpin-events.patch
Patch0042: 0042-multipathd-disallow-changing-to-from-fpin-marginal-p.patch
Patch0043: 0043-libmultipath-fix-printing-native-nvme-multipath-topo.patch
Patch0044: 0044-multipathd-Don-t-keep-starting-TUR-threads-if-they-a.patch
Patch0045: 0045-multipath-tools-update-mpp-force_readonly-in-ev_add_.patch
Patch0046: 0046-multipath-return-failure-on-an-invalid-remove-comman.patch
Patch0047: 0047-libmultipath-steal-the-src-string-pointer-in-merge_s.patch
Patch0048: 0048-libmultipath-enable-linear-ordering-of-bus-proto-tup.patch
Patch0049: 0049-libmultipath-use-bus_protocol_id-in-snprint_path_pro.patch
Patch0050: 0050-libmultipath-make-protocol_name-global.patch
Patch0051: 0051-libmultipath-add-a-protocol-subsection-to-multipath..patch
Patch0052: 0052-libmultipath-Set-the-scsi-timeout-parameters-by-path.patch
Patch0053: 0053-libmultipath-check-the-overrides-pctable-for-path-va.patch
Patch0054: 0054-libmultipath-fix-eh_deadline-documentation.patch
Patch0055: 0055-libmultipath-Add-documentation-for-the-protocol-subs.patch
Patch0056: 0056-libmultipath-use-symbolic-value-for-invalid-pcentry.patch
Patch0057: 0057-updated-HPE-MSA-builtin-config.patch
Patch0058: 0058-libmultipath-unset-detect_checker-for-clariion-Unity.patch
Patch0059: 0059-multipathd-Add-missing-ctype-include.patch
Patch0060: 0060-multipathd-replace-libreadline-with-libedit.patch
Patch0061: 0061-multipath-fix-systemd-timers-in-the-initramfs.patch
Patch0062: 0062-multipathd-factor-out-the-code-to-flush-a-map-with-n.patch
Patch0063: 0063-libmultipath-return-success-if-we-raced-to-remove-a-.patch
Patch0064: 0064-multipathd-Handle-losing-all-path-in-update_map.patch
Patch0065: 0065-multipathd-ignore-duplicated-multipathd-command-keys.patch
Patch0066: 0066-multipath-tools-use-run-instead-of-dev-shm.patch
Patch0067: 0067-kpartx-hold-device-open-until-partitions-have-been-c.patch
Patch0068: 0068-libmultipath-cleanup-remove_feature.patch
Patch0069: 0069-libmultipath-cleanup-add_feature.patch
Patch0070: 0070-multipath-tests-tests-for-adding-and-removing-featur.patch
Patch0071: 0071-libmultipath-fix-queue_mode-feature-handling.patch
Patch0072: 0072-multipath-tests-tests-for-reconcile_features_with_qu.patch
Patch0073: 0073-libmultipath-prepare-proto_id-for-use-by-non-scsi-de.patch
Patch0074: 0074-libmultipath-get-nvme-path-transport-protocol.patch
Patch0075: 0075-libmultipath-enforce-queue_mode-bio-for-nmve-tcp-pat.patch
Patch0076: 0076-multipath.conf-5-remove-io-affinity-information.patch
Patch0077: 0077-libmultipath-don-t-leak-memory-on-invalid-strings.patch
Patch0078: 0078-libmutipath-validate-the-argument-count-of-config-st.patch
Patch0079: 0079-libmultipath-use-select_reload_action-in-select_acti.patch
Patch0080: 0080-libmultipath-select-resize-action-even-if-reload-is-.patch
Patch0081: 0081-libmultipath-cleanup-ACT_CREATE-code-in-select_actio.patch
Patch0082: 0082-libmultipath-keep-renames-from-stopping-other-multip.patch
Patch0083: 0083-multipath.rules-fix-smart-bug-with-failed-valid-path.patch
Patch0084: 0084-libmultipath-limit-paths-that-can-get-wwid-from-envi.patch
Patch0085: 0085-multipathd-make-pr-registration-consistent.patch
Patch0086: 0086-libmultipath-make-prflag-an-enum.patch
Patch0087: 0087-multipathd-handle-no-active-paths-in-update_map_pr.patch
Patch0088: 0088-libmpathpersist-fix-resource-leak-in-update_map_pr.patch
Patch0089: 0089-RH-Add-mpathcleanup.patch
Patch0090: 0090-RH-make-listing-return-an-error-if-the-config-file-i.patch
Patch0001: 0001-multipathd-fix-flush-check-in-flush_map.patch
Patch0002: 0002-RH-fixup-udev-rules-for-redhat.patch
Patch0003: 0003-RH-Remove-the-property-blacklist-exception-builtin.patch
Patch0004: 0004-RH-don-t-start-without-a-config-file.patch
Patch0005: 0005-RH-Fix-nvme-function-missing-argument.patch
Patch0006: 0006-RH-use-rpm-optflags-if-present.patch
Patch0007: 0007-RH-add-mpathconf.patch
Patch0008: 0008-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch
Patch0009: 0009-RH-reset-default-find_mutipaths-value-to-off.patch
Patch0010: 0010-RH-attempt-to-get-ANA-info-via-sysfs-first.patch
Patch0011: 0011-RH-make-parse_vpd_pg83-match-scsi_id-output.patch
Patch0012: 0012-RH-add-scsi-device-handlers-to-modules-load.d.patch
Patch0013: 0013-RH-compile-with-libreadline-support.patch
Patch0014: 0014-RH-Add-mpathcleanup.patch
Patch0015: 0015-libmultipath-fix-ontap-prioritizer-snprintf-limits.patch
Patch0016: 0016-multipathd-checker-port_state-before-setting-it.patch
# runtime
Requires: %{name}-libs = %{version}-%{release}
Requires: kpartx = %{version}-%{release}
Requires: device-mapper >= 1.02.96
Requires: userspace-rcu
Requires: libedit
Requires: readline
Requires: libmount
Requires(post): systemd-units
Requires(preun): systemd-units
Requires(postun): systemd-units
@ -126,10 +51,11 @@ Conflicts: udisks2 < 2.8.0-2
# build/setup
BuildRequires: libaio-devel, device-mapper-devel >= 1.02.89
BuildRequires: libselinux-devel, libsepol-devel
BuildRequires: libedit-devel, ncurses-devel
BuildRequires: readline-devel, ncurses-devel
BuildRequires: systemd-units, systemd-devel
BuildRequires: json-c-devel, perl-interpreter, pkgconfig, gcc
BuildRequires: userspace-rcu-devel
BuildRequires: libmount-devel
BuildRequires: make
%description
@ -186,7 +112,7 @@ This package contains the files needed to develop applications that use
device-mapper-multipath's libdmmp C API library
%prep
%autosetup -n multipath-tools-0.8.7 -p1
%autosetup -n multipath-tools-0.9.9 -p1
cp %{SOURCE1} .
%build
@ -201,8 +127,8 @@ cp %{SOURCE1} .
bindir=%{_sbindir} \
syslibdir=%{_libdir} \
usrlibdir=%{_libdir} \
libdir=%{_libmpathdir} \
rcdir=%{_initrddir} \
plugindir=%{_libmpathdir} \
mandir=%{_mandir} \
unitdir=%{_unitdir} \
includedir=%{_includedir} \
pkgconfdir=%{_pkgconfdir} \
@ -231,32 +157,38 @@ fi
/bin/systemctl --quiet is-enabled multipathd.service >/dev/null 2>&1 && /bin/systemctl reenable multipathd.service ||:
%files
%license LICENSES/GPL-2.0 LICENSES/LGPL-2.0
%license LICENSES/GPL-2.0 LICENSES/LGPL-2.0 LICENSES/GPL-3.0
%{_sbindir}/multipath
%{_sbindir}/multipathd
%{_sbindir}/multipathc
%{_sbindir}/mpathconf
%{_sbindir}/mpathcleanup
%{_sbindir}/mpathpersist
%{_unitdir}/multipathd.service
%{_unitdir}/multipathd.socket
%{_mandir}/man5/multipath.conf.5.gz
%{_mandir}/man8/multipath.8.gz
%{_mandir}/man8/multipathd.8.gz
%{_mandir}/man8/mpathconf.8.gz
%{_mandir}/man8/mpathpersist.8.gz
%config %{_udevrulesdir}/62-multipath.rules
%config %{_udevrulesdir}/11-dm-mpath.rules
%{_mandir}/man5/multipath.conf.5*
%{_mandir}/man8/multipath.8*
%{_mandir}/man8/multipathd.8*
%{_mandir}/man8/multipathc.8*
%{_mandir}/man8/mpathconf.8*
%{_mandir}/man8/mpathpersist.8*
%config /usr/lib/udev/rules.d/62-multipath.rules
%config /usr/lib/udev/rules.d/11-dm-mpath.rules
%config /usr/lib/udev/rules.d/99-z-dm-mpath-late.rules
%dir %{_modulesloaddir}
%{_modulesloaddir}/scsi_dh.conf
%{_tmpfilesdir}/multipath.conf
%doc README.md
%doc README.alua
%doc multipath.conf
%dir /etc/multipath
%files libs
%license LICENSES/GPL-2.0 LICENSES/LGPL-2.0
%license LICENSES/GPL-2.0 LICENSES/LGPL-2.0 LICENSES/LGPL-2.1
%doc README.md
%{_libdir}/libmultipath.so
%{_libdir}/libmultipath.so.*
%{_libdir}/libmpathutil.so
%{_libdir}/libmpathutil.so.*
%{_libdir}/libmpathpersist.so.*
%{_libdir}/libmpathcmd.so.*
%{_libdir}/libmpathvalid.so.*
@ -273,18 +205,18 @@ fi
%{_includedir}/mpath_cmd.h
%{_includedir}/mpath_persist.h
%{_includedir}/mpath_valid.h
%{_mandir}/man3/mpath_persistent_reserve_in.3.gz
%{_mandir}/man3/mpath_persistent_reserve_out.3.gz
%{_mandir}/man3/mpath_persistent_reserve_in.3*
%{_mandir}/man3/mpath_persistent_reserve_out.3*
%files -n kpartx
%license LICENSES/GPL-2.0
%doc README.md
%{_sbindir}/kpartx
%{_udevrulesdir}/../kpartx_id
%{_mandir}/man8/kpartx.8.gz
%config %{_udevrulesdir}/11-dm-parts.rules
%config %{_udevrulesdir}/66-kpartx.rules
%config %{_udevrulesdir}/68-del-part-nodes.rules
/usr/lib/udev/kpartx_id
%{_mandir}/man8/kpartx.8*
%config /usr/lib/udev/rules.d/11-dm-parts.rules
%config /usr/lib/udev/rules.d/66-kpartx.rules
%config /usr/lib/udev/rules.d/68-del-part-nodes.rules
%files -n libdmmp
%license LICENSES/GPL-3.0
@ -299,239 +231,252 @@ fi
%dir %{_includedir}/libdmmp
%{_includedir}/libdmmp/*
%{_mandir}/man3/dmmp_*
%{_mandir}/man3/libdmmp.h.3.gz
%{_mandir}/man3/libdmmp.h.3*
%{_pkgconfdir}/libdmmp.pc
%changelog
* Fri Jul 28 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-22
- Add 0089-RH-Add-mpathcleanup.patch
* Fixes RHEL-782
- Add 0090-RH-make-listing-return-an-error-if-the-config-file-i.patch
- Install mpathcleanup
* Fixes RHEL-781
- Resolves: #781, #782
* Tue Mar 14 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-21
- Add 0085-multipathd-make-pr-registration-consistent.patch
- Add 0086-libmultipath-make-prflag-an-enum.patch
- Add 0087-multipathd-handle-no-active-paths-in-update_map_pr.patch
- Add 0088-libmpathpersist-fix-resource-leak-in-update_map_pr.patch
- Resolves: bz #2164869
* Thu Feb 9 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-20
- Add 0083-multipath.rules-fix-smart-bug-with-failed-valid-path.patch
- Add 0084-libmultipath-limit-paths-that-can-get-wwid-from-envi.patch
- Change how the installation dir for kpartx_id is specified
- Resolves: bz #1926147
* Fri Feb 3 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-19
- Fix bugzilla linked to the changes (was previously linked to
the wrong bug, 2162536)
- Resolves: bz #2166467
* Wed Feb 1 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-18
- Add 0079-libmultipath-use-select_reload_action-in-select_acti.patch
- Add 0080-libmultipath-select-resize-action-even-if-reload-is-.patch
- Add 0081-libmultipath-cleanup-ACT_CREATE-code-in-select_actio.patch
- Add 0082-libmultipath-keep-renames-from-stopping-other-multip.patch
- Resolves: bz #2166467
* Wed Dec 21 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-17
- Add 0077-libmultipath-don-t-leak-memory-on-invalid-strings.patch
- Add 0078-libmutipath-validate-the-argument-count-of-config-st.patch
- Resolves: bz #2145225
* Wed Nov 30 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-16
- Add 0076-multipath.conf-5-remove-io-affinity-information.patch
- Resolves: bz #2143125
* Thu Nov 10 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-15
- Add 0067-kpartx-hold-device-open-until-partitions-have-been-c.patch
* Fixes bz #2141860
- Add 0068-libmultipath-cleanup-remove_feature.patch
- Add 0069-libmultipath-cleanup-add_feature.patch
- Add 0070-multipath-tests-tests-for-adding-and-removing-featur.patch
- Add 0071-libmultipath-fix-queue_mode-feature-handling.patch
- Add 0072-multipath-tests-tests-for-reconcile_features_with_qu.patch
- Add 0073-libmultipath-prepare-proto_id-for-use-by-non-scsi-de.patch
- Add 0074-libmultipath-get-nvme-path-transport-protocol.patch
- Add 0075-libmultipath-enforce-queue_mode-bio-for-nmve-tcp-pat.patch
* Fixes bz #2033080
- Resolves: bz #2033080, #2141860
* Thu Oct 13 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-14
- Add 0065-multipathd-ignore-duplicated-multipathd-command-keys.patch
* Fixes bz #2133999
- Add 0066-multipath-tools-use-run-instead-of-dev-shm.patch
* Fixes bz #2133989
- Resolves: bz #2133989, #2133999
* Fri Sep 9 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-13
- Add 0062-multipathd-factor-out-the-code-to-flush-a-map-with-n.patch
- Add 0063-libmultipath-return-success-if-we-raced-to-remove-a-.patch
- Add 0064-multipathd-Handle-losing-all-path-in-update_map.patch
- Resolves: bz #2125357
* Wed Aug 24 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-12
- Add 0061-multipath-fix-systemd-timers-in-the-initramfs.patch
- Resolves: bz #2121277
* Fri Aug 19 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-11
- Add 0059-multipathd-Add-missing-ctype-include.patch
- Add 0060-multipathd-replace-libreadline-with-libedit.patch
* replace readline with libedit, to avoid license conflicts
- Resolves: bz #2119896
* Wed Jun 8 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-10
- Add 0058-libmultipath-unset-detect_checker-for-clariion-Unity.patch
- Resolves: bz #2090913
* Mon May 16 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-9
- Add 0045-multipath-tools-update-mpp-force_readonly-in-ev_add_.patch
* Fixes bz #2084356
- Add 0046-multipath-return-failure-on-an-invalid-remove-comman.patch
* Fixes bz #2084358
- Add 0047-libmultipath-steal-the-src-string-pointer-in-merge_s.patch
- Add 0048-libmultipath-enable-linear-ordering-of-bus-proto-tup.patch
- Add 0049-libmultipath-use-bus_protocol_id-in-snprint_path_pro.patch
- Add 0050-libmultipath-make-protocol_name-global.patch
- Add 0051-libmultipath-add-a-protocol-subsection-to-multipath..patch
- Add 0052-libmultipath-Set-the-scsi-timeout-parameters-by-path.patch
- Add 0053-libmultipath-check-the-overrides-pctable-for-path-va.patch
- Add 0054-libmultipath-fix-eh_deadline-documentation.patch
- Add 0055-libmultipath-Add-documentation-for-the-protocol-subs.patch
- Add 0056-libmultipath-use-symbolic-value-for-invalid-pcentry.patch
* The above 10 patches implement the feature from bz #2084365
- Add 0057-updated-HPE-MSA-builtin-config.patch
* Fixes bz #2084357
Resolves: bz #2084365, #2084357, #2084358, #2084365
* Tue May 10 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-8
- Add 0044-multipathd-Don-t-keep-starting-TUR-threads-if-they-a.patch
- Resolves: bz #2070266
* Wed Feb 16 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-7
- Add 0043-libmultipath-fix-printing-native-nvme-multipath-topo.patch
- Resolves: bz #2054839
* Wed Feb 9 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-6
- Add 0041-multipathd-handle-fpin-events.patch
- Add 0042-multipathd-disallow-changing-to-from-fpin-marginal-p.patch
* Add "marginal_pathgroups fpin" for responding to PFIN-Li events
* Fixes bz #2053642
- Modify tests/restate_module
* Always offline the path with the lowest priority
* Fixes bz #2052633
- Resolves: bz #2052633, #2053642
* Mon Feb 7 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-5
- Add 0039-RH-add-support-to-mpathconf-for-setting-arbitrary-de.patch
* Fixes bz #2050421
- Add 0040-RH-add-support-to-mpathconf-for-setting-recheck_wwid.patch
* Fixes bz #2039749
- Resolves: bz #2039749, #2050421
* Tue Jan 18 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-4
- Add 0035-RH-mpathconf-fix-setting-property_blacklist.patch
- Add 0036-libmultipath-fix-disassemble-status-for-historical-s.patch
* Fixes bz #2042032
- Add 0037-libmultipath-make-helper-function-to-trigger-path-ue.patch
- Add 0038-multipathd-trigger-udev-change-on-path-addition.patch
* Fixes bz #2028835
- Resolves: bz #2028835, #2042032
* Fri Nov 19 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-3
- Add 0024-libmultipath-use-typedef-for-keyword-handler-functio.patch
- Add 0025-libmultipath-print-the-correct-file-when-parsing-fai.patch
- Add 0026-libmultipath-pass-file-and-line-number-to-keyword-ha.patch
- Add 0027-libmultipath-make-set_int-take-a-range-for-valid-val.patch
- Add 0028-libmultipath-improve-checks-for-set_str.patch
- Add 0029-libmultipath-deprecate-file-and-directory-config-opt.patch
- Add 0030-libmultipath-split-set_int-to-enable-reuse.patch
- Add 0031-libmultipath-cleanup-invalid-config-handling.patch
- Add 0032-libmultipath-don-t-return-error-on-invalid-values.patch
* The above 9 patches fix bz #2017969
- Add 0033-multipathd-avoid-unnecessary-path-read-only-reloads.patch
* Fixes bz #2017979
- Add 0034-multipath-fix-exit-status-of-multipath-T.patch
- Resolves: bz #2017969, #2017979
* Mon Nov 08 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-2
- Modify 0017-RH-use-rpm-optflags-if-present.patch
* use RPM_LF_FLAGS
- Modify 0018-RH-add-mpathconf.patch
* update default config to match multipath changes
- Modify 0022-RH-make-parse_vpd_pg83-match-scsi_id-output.patch
* fix cmocka vpd tests
- Rename 0023-libmulitpath-add-section-name-to-invalid-keyword-out.patch to
0023-libmultipath-add-section-name-to-invalid-keyword-out.patch
- Resolves: bz#2017592
* Fri Oct 29 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-1
- Update Source to upstream version 0.8.7 plus upstream staged commits
* Previous patches 0011-0016 & 0018-0022 are included in the source tarball
* Fixes bz#2017592
* Mon Nov 11 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.9-5
- Add 0016-multipathd-checker-port_state-before-setting-it.patch
- Resolves: RHEL-53995
* Tue Oct 29 2024 Troy Dawson <tdawson@redhat.com> - 0.9.9-4
- Bump release for October 2024 mass rebuild:
Resolves: RHEL-64018
* Fri Oct 25 2024 MSVSphere Packaging Team <packager@msvsphere-os.ru> - 0.9.9-3
- Rebuilt for MSVSphere 10
* Fri Sep 13 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.9-3
- Add 0015-libmultipath-fix-ontap-prioritizer-snprintf-limits.patch
- Resolves: RHEL-49747
* Thu Sep 12 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.9-2
- Improve multiple OSCI tests
* Fri Jul 26 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.9-1
- Update source to upstream version 0.9.9
* Previous patches 0014-0015 are included in the soruce tarball
* Patch 0001 is from the upstream staging branch
- Rename redhat patches
* Previous patches 0001-0013 are now 0002-0014
- Install /lib/udev/rules.d/99-z-dm-mpath-late.rules
- Resolves: RHEL-50698
* Fri Jun 28 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.7-10
- Fix CI tests
* Mon Jun 24 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.7-9
- Add gating.yaml
* Mon Jun 24 2024 Troy Dawson <tdawson@redhat.com> - 0.9.7-8
- Bump release for June 2024 mass rebuild
* Wed Jan 24 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.7-7
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Fri Jan 19 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.7-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Tue Jan 16 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.7-5
- Add 0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch
* Fix auto_resize code to avoid a segfault
- Add 0015-multipathd-fix-auto-resize-configuration.patch
* Fix auto_resize default value
* Thu Nov 30 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.7-4
- Use modulesloaddir macro for installing scsi_dh.conf
* Wed Nov 29 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.7-3
- Fix multipath_conf_syntax test
- Fix restate_module test
* Tue Nov 28 2023 Paul Donohue <git@PaulSD.com> - 0.9.7-2
- Modify 0006-RH-add-mpathconf.patch
- Modify 0008-RH-reset-default-find_mutipaths-value-to-off.patch
* Fix find_multipaths values in docs and mpathconf
* Tue Nov 21 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.7-1
- Update source to upstream version 0.9.7
* Previous patches 0001-0040 are included in the source tarball
- Rename redhat patches
* Previous patches 0041-0053 are now patches 0001-0013
- Remove /usr/lib/modules-load.d/multipath.conf
* has been replaced with modprobe@dm_multipath.service unit Wants.
* Fri Sep 22 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.6-1
- Update to the head of the upstream staging branch
- Rename redhat patches
* Previous patches 0001-0012 are now patches 0041-0052
- Add 0053-RH-Add-mpathcleanup.patch
* add mpathcleanup program
* Wed Jul 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.5-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
* Tue May 16 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.5-1
- Update to the latest upstream release
* Previous patches 0001-0015 are included in the source tarball
- Rename redhat patches
* Previous patches 0016-0027 are now patches 0001-0012
* Thu Feb 2 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.4-2
- Update to the head of the upstream staging branch
* Patches 0011-0015 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0011-0022 are now patches 0016-0027
* Thu Jan 26 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.4-1
- Update to the head of the upstream staging branch
* Previous patches 0001-0032 are included in the source tarball
* Patches 0001-0010 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0033-0044 are now patches 0011-0022
- Add dependency on libmount
* Thu Jan 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
* Tue Nov 15 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.3-1
- Update to the head of the upstream staging branch
* Previous patches 0001-0042 are included in the source tarball
* Patches 0001-0032 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0043-0053 are now patches 0033-0043
- Change back to using readline instead of libedit
* The code the uses readline has been isolated from the code that
is licensed gpl v2 only.
- Add libmpathutil libraries to spec file
- Add multipathc program to spec file
- Add multipath.conf systemd tempfile configuration to spec file
- Misc spec file cleanups
* Fri Aug 19 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.0-3
- Update to the head of the upstream staging branch
* Patches 0005-0042 are from the upstream staging branch
* Previous patches 0005 & 0006 are now patches 0023 & 0005
- Rename redhat patches
* Previous patches 0007-0017 are now patches 0043-0053
- Change from using readline to libedit
* readline is licensed GPL v3, and multipathd includes code
licensed gpl v2.
- Remove README.alua
* information moved to README.md
* Thu Jul 21 2022 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
* Wed Jul 13 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.0-1
- Update source to upstream version 0.9.0
* Previous patches 0001-0005 are included in the commit.
* This version deprecates multiple options: mutlipath_dir, config_dir, and
getuid_callout, along with the "default_" prefixed alternate names for the
default section parameters.
- Add patches from upstream staging branch
* Patches 0001-0006 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0006-0016 are now patches 0007-0017
* Mon Mar 28 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.9-1
- Update source to upstream version 0.8.9
* Previous patches 0001-0024 & 0035 are included in the commit.
- Add patches from upstream staging branch
* Patches 0001-0005 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0025-0034 are now patches 0006-0015
- Combine redhat patches
* Previous patches 0036 & 0037 are now part of patch 0011
- Add 0016-RH-add-scsi-device-handlers-to-modules-load.d.patch
- Spec file changes
* Install multipath.conf and scsi_dh.conf to /usr/lib/modules-load.d
* Mon Feb 7 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-8
- Add 0036-RH-add-support-to-mpathconf-for-setting-arbitrary-de.patch
* add the ability for mpathconf to set arbitray options with --option
- Add 0037-RH-add-support-to-mpathconf-for-setting-recheck_wwid.patch
* add --recheck_wwid option to mpathconf
* Wed Jan 26 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-7
- Add 0035-libmultipath-use-asprintf-to-allocate-prefixed_uuid.patch
- Resolves: bz #2045309
* Thu Jan 20 2022 Fedora Release Engineering <releng@fedoraproject.org> - 0.8.7-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild
* Thu Jan 6 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-5
- Modify 0030-RH-add-mpathconf.patch
* fix setting property_blacklist with no blacklist_exceptions section
* Mon Dec 13 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-4
- Update to the head of the upstream staging branch
* Patches 0013 - 0024 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0013-0022 are now patches 0025-0034
* Thu Oct 28 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-3
- Update to the head of the upstream staging branch
* Patches 0011 & 0012 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0011-0020 are now patches 0013-0022
* Wed Oct 6 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-2
- Modify 0013-RH-don-t-start-without-a-config-file.patch
* add condtion to multipathd.socket as well
* Wed Oct 6 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-1
- Update source to upstream version 0.8.7
* Previous patches 0001-0023 are included in the commit.
- Add patches from upstream staging branch
* Patches 0001-0010 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0024-0033 are now patches 0011-0020
* Fri Jul 30 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.6-5
- Update to the head of the upstream staging branch plus redhat patches
* Patches 0016-0018 are from the upstream staging branch
* Patches 0019-0024 have been submitted upstream
- Rename files
* Previous patches 0016-0025 are now patches 0024-0033
* Wed Jul 21 2021 Fedora Release Engineering <releng@fedoraproject.org> - 0.8.6-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
* Sat Jul 10 2021 Björn Esser <besser82@fedoraproject.org> - 0.8.6-3
- Rebuild for versioned symbols in json-c
* Thu Jul 1 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.6-2
- Pull in latest upstream post-tag commits
* Patches 0001-0015 are from
https://github.com/openSUSE/multipath-tools/tree/queue and are
already queued for upstream
- Rename files
* Previous patches 0001-0010 are now patches 0013-0022
- Modify 0018-RH-add-mpathconf.patch
* merged with previous patch 0017
- Add 0023-libmulitpath-add-section-name-to-invalid-keyword-out.patch
* Fixes bz#1984303
- Fix multipath_conf_syntax test to work with bz #1984303
- Resolves: bz #1984303, #2017592
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 0.8.6-7
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Fri Jul 23 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.6-6
- Add 0022-multipathd-cli_handlers-cleanup-setting-reply-length.patch
* Found by corosync
- Related: bz #1984921
* Fri Jul 23 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.6-5
- Add 0018-multipath.conf-fix-typo-in-ghost_delay-description.patch
- Add 0019-mpathpersist-fail-commands-when-no-usable-paths-exis.patch
* Fixes bz #1982613
- Add 0020-multipath-print-warning-if-multipathd-is-not-running.patch
* Fixes bz #1982615
- Add 0021-libmultipath-deal-with-dynamic-PTHREAD_STACK_MIN.patch
* Fixes bz #1984921
- Resolves: bz #1982613, #1982615, #1984921
* Mon Jul 12 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.6-4
- Add 0017-RH-mpathconf-correctly-handle-spaces-after-option-na.patch
- Resolves: bz #1981594
* Wed May 19 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.6-3
- Add 0011-multipathd-don-t-fail-to-remove-path-once-the-map-is.patch
- Add 0012-multipathd-remove-duplicate-orphan_paths-in-flush_ma.patch
- Add 0013-multipathd-fix-ev_remove_path-return-code-handling.patch
- Add 0014-multipath-free-vectors-in-configure.patch
- Add 0015-kpartx-Don-t-leak-memory-when-getblock-returns-NULL.patch
- Add 0016-multipathd-don-t-rescan_path-on-wwid-change-in-uev_u.patch
* Above patches Fix bz #1938704
- Resolves: bz #1938704
* Wed Apr 21 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.6-2
- Update spec file
- Related: bz #1951336
* Mon Apr 19 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.6-1
* Previous patches 0001-0010 and now patches 0016-0025
* Wed Jun 23 2021 Cole Robinson <crobinso@redhat.com> - 0.8.6-1.fc35.1
- Rebuild for userspace-rcu soname bump
* Mon Apr 5 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.6-1
- Update Source to upstream version 0.8.6
* Previous patches 0001-0123 are included in the commit
* Fixes bz #1951336
* Previous patches 0001-0146 are included in the commit
- Rename files
* Previous patches 0147-0156 are now patches 0001-0010
- sync tests with RHEL repository
* Fri Mar 26 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.5-6
- Change patch format to remove Git version
* Patches 0001-0122 only have the patch format modified
- Update to the head of the upstream staging branch plus redhat patches
* Patches 0123-0134 & 1036-0142 are from the upstream staging branch
* Patches 0143-1046 have been submitted upstream
* Patch 0156 is a Red Hat only patch. Red Hat udev rules set ID_SERIAL
from 60-persistent-storage.rules instead of 55-scsi-sg3_id.rules.
Multipath's parse_vpd_pg83() function needs to match the ID_SERIAL
value from udev.
- Rename files
* Previous patches 0124-0132 are now patches 0001-0009
- Add 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch
* make scsi wwid fallback code result match the default udev wwid
code result (Red Hat specific patch)
- Sync tests with RHEL-8
- Resolves: bz #1951336
* Thu Apr 15 2021 Mohan Boddu <mboddu@redhat.com> - 0.8.5-5
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Previous patches 0123-0132 are now patches 1035 & 0147-0155
* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 0.8.5-5
- Rebuilt for updated systemd-rpm-macros
See https://pagure.io/fesco/issue/2583.
* Thu Feb 11 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.5-4
- Update Source to upstream version 0.8.5 plus post tag commits

Loading…
Cancel
Save