diff --git a/SOURCES/0044-multipathd-Don-t-keep-starting-TUR-threads-if-they-a.patch b/SOURCES/0044-multipathd-Don-t-keep-starting-TUR-threads-if-they-a.patch new file mode 100644 index 0000000..1f48fe2 --- /dev/null +++ b/SOURCES/0044-multipathd-Don-t-keep-starting-TUR-threads-if-they-a.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +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 +Reviewed-by: Martin Wilck 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; diff --git a/SOURCES/0044-multipathd-ignore-duplicated-multipathd-command-keys.patch b/SOURCES/0044-multipathd-ignore-duplicated-multipathd-command-keys.patch deleted file mode 100644 index 4f92ace..0000000 --- a/SOURCES/0044-multipathd-ignore-duplicated-multipathd-command-keys.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -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 ---- - 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); diff --git a/SOURCES/0045-multipath-tools-update-mpp-force_readonly-in-ev_add_.patch b/SOURCES/0045-multipath-tools-update-mpp-force_readonly-in-ev_add_.patch new file mode 100644 index 0000000..8db1982 --- /dev/null +++ b/SOURCES/0045-multipath-tools-update-mpp-force_readonly-in-ev_add_.patch @@ -0,0 +1,78 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Uday Shankar +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 +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + 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; + diff --git a/SOURCES/0046-multipath-return-failure-on-an-invalid-remove-comman.patch b/SOURCES/0046-multipath-return-failure-on-an-invalid-remove-comman.patch new file mode 100644 index 0000000..be522b0 --- /dev/null +++ b/SOURCES/0046-multipath-return-failure-on-an-invalid-remove-comman.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +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 +Reviewed-by: Martin Wilck 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; diff --git a/SOURCES/0047-libmultipath-steal-the-src-string-pointer-in-merge_s.patch b/SOURCES/0047-libmultipath-steal-the-src-string-pointer-in-merge_s.patch new file mode 100644 index 0000000..c8f4adf --- /dev/null +++ b/SOURCES/0047-libmultipath-steal-the-src-string-pointer-in-merge_s.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +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 +Reviewed-by: Martin Wilck +--- + 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) diff --git a/SOURCES/0048-libmultipath-enable-linear-ordering-of-bus-proto-tup.patch b/SOURCES/0048-libmultipath-enable-linear-ordering-of-bus-proto-tup.patch new file mode 100644 index 0000000..6e29119 --- /dev/null +++ b/SOURCES/0048-libmultipath-enable-linear-ordering-of-bus-proto-tup.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +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 +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + 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 { diff --git a/SOURCES/0049-libmultipath-use-bus_protocol_id-in-snprint_path_pro.patch b/SOURCES/0049-libmultipath-use-bus_protocol_id-in-snprint_path_pro.patch new file mode 100644 index 0000000..f616a5a --- /dev/null +++ b/SOURCES/0049-libmultipath-use-bus_protocol_id-in-snprint_path_pro.patch @@ -0,0 +1,84 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +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 +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + 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 diff --git a/SOURCES/0050-libmultipath-make-protocol_name-global.patch b/SOURCES/0050-libmultipath-make-protocol_name-global.patch new file mode 100644 index 0000000..0ce58a3 --- /dev/null +++ b/SOURCES/0050-libmultipath-make-protocol_name-global.patch @@ -0,0 +1,85 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +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 +Reviewed-by: Martin Wilck +--- + 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 + diff --git a/SOURCES/0051-libmultipath-add-a-protocol-subsection-to-multipath..patch b/SOURCES/0051-libmultipath-add-a-protocol-subsection-to-multipath..patch new file mode 100644 index 0000000..70ca3d7 --- /dev/null +++ b/SOURCES/0051-libmultipath-add-a-protocol-subsection-to-multipath..patch @@ -0,0 +1,425 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +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 +Reviewed-by: Martin Wilck +--- + 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; diff --git a/SOURCES/0052-libmultipath-Set-the-scsi-timeout-parameters-by-path.patch b/SOURCES/0052-libmultipath-Set-the-scsi-timeout-parameters-by-path.patch new file mode 100644 index 0000000..c82fd4f --- /dev/null +++ b/SOURCES/0052-libmultipath-Set-the-scsi-timeout-parameters-by-path.patch @@ -0,0 +1,497 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +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 +Reviewed-by: Martin Wilck +--- + 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; diff --git a/SOURCES/0053-libmultipath-check-the-overrides-pctable-for-path-va.patch b/SOURCES/0053-libmultipath-check-the-overrides-pctable-for-path-va.patch new file mode 100644 index 0000000..30235af --- /dev/null +++ b/SOURCES/0053-libmultipath-check-the-overrides-pctable-for-path-va.patch @@ -0,0 +1,84 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +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 +Reviewed-by: Martin Wilck +--- + 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; diff --git a/SOURCES/0054-libmultipath-fix-eh_deadline-documentation.patch b/SOURCES/0054-libmultipath-fix-eh_deadline-documentation.patch new file mode 100644 index 0000000..b20799d --- /dev/null +++ b/SOURCES/0054-libmultipath-fix-eh_deadline-documentation.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 13 Apr 2022 23:27:40 -0500 +Subject: [PATCH] libmultipath: fix eh_deadline documentation + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + 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 diff --git a/SOURCES/0055-libmultipath-Add-documentation-for-the-protocol-subs.patch b/SOURCES/0055-libmultipath-Add-documentation-for-the-protocol-subs.patch new file mode 100644 index 0000000..bf3d9a3 --- /dev/null +++ b/SOURCES/0055-libmultipath-Add-documentation-for-the-protocol-subs.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 13 Apr 2022 23:27:41 -0500 +Subject: [PATCH] libmultipath: Add documentation for the protocol subsection + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + 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 + . + . + .\" ---------------------------------------------------------------------------- diff --git a/SOURCES/0056-libmultipath-use-symbolic-value-for-invalid-pcentry.patch b/SOURCES/0056-libmultipath-use-symbolic-value-for-invalid-pcentry.patch new file mode 100644 index 0000000..9127c90 --- /dev/null +++ b/SOURCES/0056-libmultipath-use-symbolic-value-for-invalid-pcentry.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 14 Apr 2022 16:11:10 -0500 +Subject: [PATCH] libmultipath: use symbolic value for invalid pcentry + +Suggested-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + 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; diff --git a/SOURCES/0057-updated-HPE-MSA-builtin-config.patch b/SOURCES/0057-updated-HPE-MSA-builtin-config.patch new file mode 100644 index 0000000..7615fc0 --- /dev/null +++ b/SOURCES/0057-updated-HPE-MSA-builtin-config.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +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 +--- + 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, diff --git a/SOURCES/0058-libmultipath-unset-detect_checker-for-clariion-Unity.patch b/SOURCES/0058-libmultipath-unset-detect_checker-for-clariion-Unity.patch new file mode 100644 index 0000000..2186f82 --- /dev/null +++ b/SOURCES/0058-libmultipath-unset-detect_checker-for-clariion-Unity.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +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 +--- + 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 */ diff --git a/SOURCES/0059-multipathd-Add-missing-ctype-include.patch b/SOURCES/0059-multipathd-Add-missing-ctype-include.patch new file mode 100644 index 0000000..7e2d464 --- /dev/null +++ b/SOURCES/0059-multipathd-Add-missing-ctype-include.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Bastian Germann +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 +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + 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 + #include + #include ++#include + #include + #include + #include diff --git a/SOURCES/0060-multipathd-replace-libreadline-with-libedit.patch b/SOURCES/0060-multipathd-replace-libreadline-with-libedit.patch new file mode 100644 index 0000000..20d67b7 --- /dev/null +++ b/SOURCES/0060-multipathd-replace-libreadline-with-libedit.patch @@ -0,0 +1,103 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +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 +Signed-off-by: Benjamin Marzinski +--- + 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 ++#endif ++#ifdef USE_LIBREADLINE + #include ++#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 + #include + #include ++ ++#ifdef USE_LIBEDIT ++#include ++#endif ++#ifdef USE_LIBREADLINE + #include + #include ++#endif + + #include "mpath_cmd.h" + #include "uxsock.h" diff --git a/SOURCES/0061-multipath-fix-systemd-timers-in-the-initramfs.patch b/SOURCES/0061-multipath-fix-systemd-timers-in-the-initramfs.patch new file mode 100644 index 0000000..2d7f6d7 --- /dev/null +++ b/SOURCES/0061-multipath-fix-systemd-timers-in-the-initramfs.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +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 +Reviewed-by: Martin Wilck +--- + 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" diff --git a/SPECS/device-mapper-multipath.spec b/SPECS/device-mapper-multipath.spec index d18a442..c137741 100644 --- a/SPECS/device-mapper-multipath.spec +++ b/SPECS/device-mapper-multipath.spec @@ -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 - 0.8.7-7.1 -- Add 0044-multipathd-ignore-duplicated-multipathd-command-keys.patch -- Resolves: bz #2133997 +* Wed Aug 24 2022 Benjamin Marzinski - 0.8.7-12 +- Add 0061-multipath-fix-systemd-timers-in-the-initramfs.patch +- Resolves: bz #2121277 + +* Fri Aug 19 2022 Benjamin Marzinski - 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 - 0.8.7-10 +- Add 0058-libmultipath-unset-detect_checker-for-clariion-Unity.patch +- Resolves: bz #2090913 + +* Mon May 16 2022 Benjamin Marzinski - 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 - 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 - 0.8.7-7 - Add 0043-libmultipath-fix-printing-native-nvme-multipath-topo.patch