import device-mapper-multipath-0.8.7-12.el9

This commit is contained in:
CentOS Sources 2022-11-15 01:52:02 -05:00 committed by Stepan Oksanichenko
parent 9370fe9d00
commit 7658e444e2
20 changed files with 1929 additions and 159 deletions

View File

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

View File

@ -1,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 4d6c37c9..2d0ec146 100644
--- a/multipathd/cli.c
+++ b/multipathd/cli.c
@@ -337,9 +337,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 45b9572f..d8db1622 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1688,62 +1688,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);

View File

@ -0,0 +1,78 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Uday Shankar <ushankar@purestorage.com>
Date: Wed, 9 Mar 2022 13:03:26 -0700
Subject: [PATCH] multipath-tools: update mpp->force_readonly in ev_add_path
When NVMe disks are added to the system, no uevent containing the
DISK_RO property is generated. As a result, dm-* nodes backed by
readonly NVMe disks will not have their RO state set properly. The
result looks like this:
$ multipath -l
eui.00c92c091fd6564424a9376600011bd1 dm-3 NVME,Pure Storage FlashArray
size=1.0T features='0' hwhandler='0' wp=rw
|-+- policy='service-time 0' prio=0 status=active
| `- 0:2:2:72657 nvme0n2 259:4 active undef running
`-+- policy='service-time 0' prio=0 status=enabled
`- 1:0:2:72657 nvme1n2 259:1 active undef running
$ cat /sys/block/dm-3/ro
0
$ cat /sys/block/nvme*n2/ro
1
1
This is not a problem for SCSI disks, since the kernel will emit change
uevents containing the DISK_RO property when the disk is added to the
system. See the following thread for my initial attempt to fix this
issue at the kernel level:
https://lore.kernel.org/linux-block/Yib8GqCA5e3SQYty@infradead.org/T/#t
Fix the issue by picking up the path ro state from sysfs in ev_add_path,
setting the mpp->force_readonly accordingly, and changing
dm_addmap_create to be aware of mpp->force_readonly.
Signed-off-by: Uday Shankar <ushankar@purestorage.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 2 +-
multipathd/main.c | 6 ++++++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 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;

View File

@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 30 Mar 2022 15:14:56 -0500
Subject: [PATCH] multipath: return failure on an invalid remove command
When "multipath -f" is run on a device that doesn't exist or isn't a
multipath device, the command will not remove any device, but it will
still return success. Multiple functions rely on _dm_flush_map()
returning success when called with name that doesn't match any
multipath device. So before calling _dm_flush_map(), call dm_is_mpath(),
to check if the device exists and is a multipath device, and return
failure if it's not.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com
---
multipath/main.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/multipath/main.c b/multipath/main.c
index 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;

View File

@ -0,0 +1,67 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 13 Apr 2022 23:27:35 -0500
Subject: [PATCH] libmultipath: steal the src string pointer in merge_str()
Instead of allocating a copy when the original string is going to be
freed right after the merge, just steal the pointer. Also, merge_mpe()
can't get called with NULL arguments.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/config.c | 16 +++++-----------
1 file changed, 5 insertions(+), 11 deletions(-)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 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)

View File

@ -0,0 +1,74 @@
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 {

View File

@ -0,0 +1,84 @@
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

View File

@ -0,0 +1,85 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 13 Apr 2022 23:27:36 -0500
Subject: [PATCH] libmultipath: make protocol_name global
Future patches will make use of this, so move it out of
snprint_path_protocol()
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/print.c | 17 -----------------
libmultipath/structs.c | 18 ++++++++++++++++++
libmultipath/structs.h | 1 +
3 files changed, 19 insertions(+), 17 deletions(-)
diff --git a/libmultipath/print.c b/libmultipath/print.c
index 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

View File

@ -0,0 +1,425 @@
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;

View File

@ -0,0 +1,497 @@
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;

View File

@ -0,0 +1,84 @@
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;

View File

@ -0,0 +1,33 @@
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

View File

@ -0,0 +1,54 @@
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
.
.
.\" ----------------------------------------------------------------------------

View File

@ -0,0 +1,47 @@
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;

View File

@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 29 Apr 2022 15:57:12 -0500
Subject: [PATCH] updated HPE MSA builtin config
Make the config better align to MSA 4th, 5th and 6th Generation systems.
Cc: Jon.Paul@hpe.com
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/hwtable.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index 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,

View File

@ -0,0 +1,30 @@
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 */

View File

@ -0,0 +1,26 @@
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>

View File

@ -0,0 +1,103 @@
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"

View File

@ -0,0 +1,35 @@
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"

View File

@ -1,6 +1,6 @@
Name: device-mapper-multipath
Version: 0.8.7
Release: 7%{?dist}.1
Release: 12%{?dist}
Summary: Tools to manage multipath devices using device-mapper
License: GPLv2
URL: http://christophe.varoqui.free.fr/
@ -53,7 +53,24 @@ 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-ignore-duplicated-multipathd-command-keys.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
# runtime
@ -61,6 +78,7 @@ Requires: %{name}-libs = %{version}-%{release}
Requires: kpartx = %{version}-%{release}
Requires: device-mapper >= 1.02.96
Requires: userspace-rcu
Requires: libedit
Requires(post): systemd-units
Requires(preun): systemd-units
Requires(postun): systemd-units
@ -78,7 +96,7 @@ Conflicts: udisks2 < 2.8.0-2
# build/setup
BuildRequires: libaio-devel, device-mapper-devel >= 1.02.89
BuildRequires: libselinux-devel, libsepol-devel
BuildRequires: readline-devel, ncurses-devel
BuildRequires: libedit-devel, ncurses-devel
BuildRequires: systemd-units, systemd-devel
BuildRequires: json-c-devel, perl-interpreter, pkgconfig, gcc
BuildRequires: userspace-rcu-devel
@ -253,9 +271,43 @@ fi
%{_pkgconfdir}/libdmmp.pc
%changelog
* Thu Oct 13 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-7.1
- Add 0044-multipathd-ignore-duplicated-multipathd-command-keys.patch
- Resolves: bz #2133997
* 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