diff --git a/SOURCES/0094-multipath-return-failure-on-an-invalid-remove-comman.patch b/SOURCES/0094-multipath-return-failure-on-an-invalid-remove-comman.patch new file mode 100644 index 0000000..add7207 --- /dev/null +++ b/SOURCES/0094-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/0095-libmultipath-steal-the-src-string-pointer-in-merge_s.patch b/SOURCES/0095-libmultipath-steal-the-src-string-pointer-in-merge_s.patch new file mode 100644 index 0000000..5de4eaf --- /dev/null +++ b/SOURCES/0095-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 abbddaf1..aa79561e 100644 +--- a/libmultipath/config.c ++++ b/libmultipath/config.c +@@ -323,9 +323,9 @@ set_param_str(const char * str) + } + + #define merge_str(s) \ +- if (!dst->s && src->s) { \ +- if (!(dst->s = set_param_str(src->s))) \ +- return 1; \ ++ if (!dst->s && src->s && strlen(src->s)) { \ ++ dst->s = src->s; \ ++ src->s = NULL; \ + } + + #define merge_num(s) \ +@@ -333,7 +333,7 @@ set_param_str(const char * str) + dst->s = src->s + + +-static int ++static void + merge_hwe (struct hwentry * dst, struct hwentry * src) + { + char id[SCSI_VENDOR_SIZE+PATH_PRODUCT_SIZE]; +@@ -385,15 +385,11 @@ merge_hwe (struct hwentry * dst, struct hwentry * src) + reconcile_features_with_options(id, &dst->features, + &dst->no_path_retry, + &dst->retain_hwhandler); +- return 0; + } + +-static int ++static void + merge_mpe(struct mpentry *dst, struct mpentry *src) + { +- if (!dst || !src) +- return 1; +- + merge_str(alias); + merge_str(uid_attribute); + merge_str(getuid); +@@ -435,8 +431,6 @@ merge_mpe(struct mpentry *dst, struct mpentry *src) + merge_num(uid); + merge_num(gid); + merge_num(mode); +- +- return 0; + } + + void merge_mptable(vector mptable) diff --git a/SOURCES/0096-libmultipath-enable-linear-ordering-of-bus-proto-tup.patch b/SOURCES/0096-libmultipath-enable-linear-ordering-of-bus-proto-tup.patch new file mode 100644 index 0000000..76a9407 --- /dev/null +++ b/SOURCES/0096-libmultipath-enable-linear-ordering-of-bus-proto-tup.patch @@ -0,0 +1,75 @@ +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 | 14 ++++++++++++-- + 2 files changed, 22 insertions(+), 2 deletions(-) + +diff --git a/libmultipath/structs.c b/libmultipath/structs.c +index dda9884c..aaf85297 100644 +--- a/libmultipath/structs.c ++++ b/libmultipath/structs.c +@@ -722,3 +722,13 @@ out: + + return 0; + } ++ ++unsigned int bus_protocol_id(const struct path *pp) { ++ if (!pp || pp->bus < 0 || pp->bus > SYSFS_BUS_SCSI) ++ return SYSFS_BUS_UNDEF; ++ if (pp->bus != SYSFS_BUS_SCSI) ++ return pp->bus; ++ if ((int)pp->sg_id.proto_id < 0 || pp->sg_id.proto_id > SCSI_PROTOCOL_UNSPEC) ++ return SYSFS_BUS_UNDEF; ++ return SYSFS_BUS_SCSI + pp->sg_id.proto_id; ++} +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index a5dbad5b..5e29ae38 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -57,12 +57,13 @@ enum failback_mode { + FAILBACK_FOLLOWOVER + }; + ++/* SYSFS_BUS_SCSI should be last, see bus_protocol_id() */ + enum sysfs_buses { + SYSFS_BUS_UNDEF, +- SYSFS_BUS_SCSI, + SYSFS_BUS_CCW, + SYSFS_BUS_CCISS, + SYSFS_BUS_NVME, ++ SYSFS_BUS_SCSI, + }; + + enum pathstates { +@@ -190,9 +191,18 @@ enum scsi_protocol { + SCSI_PROTOCOL_SAS = 6, + SCSI_PROTOCOL_ADT = 7, /* Media Changers */ + SCSI_PROTOCOL_ATA = 8, +- SCSI_PROTOCOL_UNSPEC = 0xf, /* No specific protocol */ ++ SCSI_PROTOCOL_USB = 9, /* USB Attached SCSI (UAS), and others */ ++ SCSI_PROTOCOL_UNSPEC = 0xa, /* No specific protocol */ + }; + ++/* ++ * Linear ordering of bus/protocol ++ * This assumes that SYSFS_BUS_SCSI is last in enum sysfs_buses ++ * SCSI is the only bus type for which we distinguish protocols. ++ */ ++#define LAST_BUS_PROTOCOL_ID (SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC) ++unsigned int bus_protocol_id(const struct path *pp); ++ + enum no_undef_states { + NU_NO = -1, + NU_UNDEF = 0, diff --git a/SOURCES/0097-libmultipath-use-bus_protocol_id-in-snprint_path_pro.patch b/SOURCES/0097-libmultipath-use-bus_protocol_id-in-snprint_path_pro.patch new file mode 100644 index 0000000..31976e7 --- /dev/null +++ b/SOURCES/0097-libmultipath-use-bus_protocol_id-in-snprint_path_pro.patch @@ -0,0 +1,82 @@ +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 | 56 +++++++++++++++++--------------------------- + 1 file changed, 21 insertions(+), 35 deletions(-) + +diff --git a/libmultipath/print.c b/libmultipath/print.c +index 298b3764..ff4d1854 100644 +--- a/libmultipath/print.c ++++ b/libmultipath/print.c +@@ -662,41 +662,27 @@ snprint_path_failures(char * buff, size_t len, const struct path * pp) + int + snprint_path_protocol(char * buff, size_t len, const struct path * pp) + { +- switch (pp->bus) { +- case SYSFS_BUS_SCSI: +- switch (pp->sg_id.proto_id) { +- case SCSI_PROTOCOL_FCP: +- return snprintf(buff, len, "scsi:fcp"); +- case SCSI_PROTOCOL_SPI: +- return snprintf(buff, len, "scsi:spi"); +- case SCSI_PROTOCOL_SSA: +- return snprintf(buff, len, "scsi:ssa"); +- case SCSI_PROTOCOL_SBP: +- return snprintf(buff, len, "scsi:sbp"); +- case SCSI_PROTOCOL_SRP: +- return snprintf(buff, len, "scsi:srp"); +- case SCSI_PROTOCOL_ISCSI: +- return snprintf(buff, len, "scsi:iscsi"); +- case SCSI_PROTOCOL_SAS: +- return snprintf(buff, len, "scsi:sas"); +- case SCSI_PROTOCOL_ADT: +- return snprintf(buff, len, "scsi:adt"); +- case SCSI_PROTOCOL_ATA: +- return snprintf(buff, len, "scsi:ata"); +- case SCSI_PROTOCOL_UNSPEC: +- default: +- return snprintf(buff, len, "scsi:unspec"); +- } +- case SYSFS_BUS_CCW: +- return snprintf(buff, len, "ccw"); +- case SYSFS_BUS_CCISS: +- return snprintf(buff, len, "cciss"); +- case SYSFS_BUS_NVME: +- return snprintf(buff, len, "nvme"); +- case SYSFS_BUS_UNDEF: +- default: +- return snprintf(buff, len, "undef"); +- } ++ static const char * const protocol_name[LAST_BUS_PROTOCOL_ID + 1] = { ++ [SYSFS_BUS_UNDEF] = "undef", ++ [SYSFS_BUS_CCW] = "ccw", ++ [SYSFS_BUS_CCISS] = "cciss", ++ [SYSFS_BUS_NVME] = "nvme", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_FCP] = "scsi:fcp", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SPI] = "scsi:spi", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SSA] = "scsi:ssa", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SBP] = "scsi:sbp", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SRP] = "scsi:srp", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ISCSI] = "scsi:iscsi", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SAS] = "scsi:sas", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ADT] = "scsi:adt", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ATA] = "scsi:ata", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_USB] = "scsi:usb", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC] = "scsi:unspec", ++ }; ++ const char *pn = protocol_name[bus_protocol_id(pp)]; ++ ++ assert(pn != NULL); ++ return snprintf(buff, len, "%s", pn); + } + + int diff --git a/SOURCES/0098-libmultipath-make-protocol_name-global.patch b/SOURCES/0098-libmultipath-make-protocol_name-global.patch new file mode 100644 index 0000000..9d6a329 --- /dev/null +++ b/SOURCES/0098-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 ff4d1854..1f6d27bd 100644 +--- a/libmultipath/print.c ++++ b/libmultipath/print.c +@@ -662,23 +662,6 @@ snprint_path_failures(char * buff, size_t len, const struct path * pp) + int + snprint_path_protocol(char * buff, size_t len, const struct path * pp) + { +- static const char * const protocol_name[LAST_BUS_PROTOCOL_ID + 1] = { +- [SYSFS_BUS_UNDEF] = "undef", +- [SYSFS_BUS_CCW] = "ccw", +- [SYSFS_BUS_CCISS] = "cciss", +- [SYSFS_BUS_NVME] = "nvme", +- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_FCP] = "scsi:fcp", +- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SPI] = "scsi:spi", +- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SSA] = "scsi:ssa", +- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SBP] = "scsi:sbp", +- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SRP] = "scsi:srp", +- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ISCSI] = "scsi:iscsi", +- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SAS] = "scsi:sas", +- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ADT] = "scsi:adt", +- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ATA] = "scsi:ata", +- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_USB] = "scsi:usb", +- [SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC] = "scsi:unspec", +- }; + const char *pn = protocol_name[bus_protocol_id(pp)]; + + assert(pn != NULL); +diff --git a/libmultipath/structs.c b/libmultipath/structs.c +index aaf85297..19099bed 100644 +--- a/libmultipath/structs.c ++++ b/libmultipath/structs.c +@@ -20,6 +20,24 @@ + #include "prioritizers/alua_spc3.h" + #include "dm-generic.h" + ++const char * const protocol_name[LAST_BUS_PROTOCOL_ID + 1] = { ++ [SYSFS_BUS_UNDEF] = "undef", ++ [SYSFS_BUS_CCW] = "ccw", ++ [SYSFS_BUS_CCISS] = "cciss", ++ [SYSFS_BUS_NVME] = "nvme", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_FCP] = "scsi:fcp", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SPI] = "scsi:spi", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SSA] = "scsi:ssa", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SBP] = "scsi:sbp", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SRP] = "scsi:srp", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ISCSI] = "scsi:iscsi", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SAS] = "scsi:sas", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ADT] = "scsi:adt", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ATA] = "scsi:ata", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_USB] = "scsi:usb", ++ [SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC] = "scsi:unspec", ++}; ++ + struct adapter_group * + alloc_adaptergroup(void) + { +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index 5e29ae38..ab99852f 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -202,6 +202,7 @@ enum scsi_protocol { + */ + #define LAST_BUS_PROTOCOL_ID (SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC) + unsigned int bus_protocol_id(const struct path *pp); ++extern const char * const protocol_name[]; + + enum no_undef_states { + NU_NO = -1, diff --git a/SOURCES/0099-libmultipath-add-a-protocol-subsection-to-multipath..patch b/SOURCES/0099-libmultipath-add-a-protocol-subsection-to-multipath..patch new file mode 100644 index 0000000..ae16fa9 --- /dev/null +++ b/SOURCES/0099-libmultipath-add-a-protocol-subsection-to-multipath..patch @@ -0,0 +1,419 @@ +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 | 44 +++++++++++++++++++ + 4 files changed, 236 insertions(+) + +diff --git a/libmultipath/config.c b/libmultipath/config.c +index aa79561e..88975323 100644 +--- a/libmultipath/config.c ++++ b/libmultipath/config.c +@@ -173,6 +173,18 @@ char *get_mpe_wwid(vector mptable, 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) + { +@@ -218,6 +230,9 @@ free_hwe (struct hwentry * hwe) + if (hwe->bl_product) + FREE(hwe->bl_product); + ++ if (hwe->pctable) ++ free_pctable(hwe->pctable); ++ + FREE(hwe); + } + +@@ -299,6 +314,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) + { +@@ -332,6 +356,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) +@@ -538,6 +569,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) + { +@@ -666,6 +742,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", +@@ -692,11 +769,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); + } +@@ -784,6 +865,7 @@ load_config (char * file) + 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"); +@@ -898,6 +980,7 @@ load_config (char * file) + 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 e2e3f143..143116b3 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 { +@@ -240,6 +249,7 @@ char * get_mpe_wwid (vector mptable, 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 5a0255b0..8321ec1e 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -457,6 +457,29 @@ snprint_mp_ ## option (struct config *conf, char * buff, int len, \ + return function (buff, len, 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, char * buff, int len, \ ++ const void *data) \ ++{ \ ++ const struct pcentry *pce = (const struct pcentry *)data; \ ++ return function(buff, len, pce->option); \ ++} ++ + static int checkint_handler(struct config *conf, vector strvec, + const char *file, int line_nr) + { +@@ -1022,6 +1045,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) +@@ -1059,6 +1084,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) +@@ -1066,6 +1093,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) +@@ -1876,6 +1905,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(char *buff, int len, int type) ++{ ++ if (type < 0) ++ return 0; ++ return snprintf(buff, len, "\"%s\"", protocol_name[type]); ++} ++ ++declare_pc_handler(type, set_protocol_type) ++declare_pc_snprint(type, print_protocol_type) ++ + /* + * deprecated handlers + */ +@@ -2117,6 +2209,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 1f6d27bd..8a6fbe83 100644 +--- a/libmultipath/print.c ++++ b/libmultipath/print.c +@@ -1392,6 +1392,39 @@ snprint_multipath_topology_json (char * buff, int len, const struct vectors * ve + return fwd; + } + ++static int ++snprint_pcentry (const struct config *conf, char *buff, int len, ++ const struct pcentry *pce) ++{ ++ int i; ++ int fwd = 0; ++ struct keyword *kw; ++ struct keyword *rootkw; ++ ++ rootkw = find_keyword(conf->keywords, NULL, "overrides"); ++ if (!rootkw || !rootkw->sub) ++ return 0; ++ ++ rootkw = find_keyword(conf->keywords, rootkw->sub, "protocol"); ++ if (!rootkw) ++ return 0; ++ ++ fwd += snprintf(buff + fwd, len - fwd, "\tprotocol {\n"); ++ if (fwd >= len) ++ return len; ++ ++ iterate_sub_keywords(rootkw, kw, i) { ++ fwd += snprint_keyword(buff + fwd, len - fwd, "\t\t%k %v\n", ++ kw, pce); ++ if (fwd >= len) ++ return len; ++ } ++ fwd += snprintf(buff + fwd, len - fwd, "\t}\n"); ++ if (fwd >= len) ++ return len; ++ return fwd; ++} ++ + static int + snprint_hwentry (const struct config *conf, + char * buff, int len, const struct hwentry * hwe) +@@ -1575,6 +1608,17 @@ static int snprint_overrides(const struct config *conf, char * buff, int len, + if (fwd >= len) + return len; + } ++ ++ if (overrides->pctable) { ++ struct pcentry *pce; ++ ++ vector_foreach_slot(overrides->pctable, pce, i) { ++ fwd += snprint_pcentry(conf, buff + fwd, len - fwd, ++ pce); ++ if (fwd >= len) ++ return len; ++ } ++ } + out: + fwd += snprintf(buff + fwd, len - fwd, "}\n"); + if (fwd >= len) diff --git a/SOURCES/0100-libmultipath-Set-the-scsi-timeout-parameters-by-path.patch b/SOURCES/0100-libmultipath-Set-the-scsi-timeout-parameters-by-path.patch new file mode 100644 index 0000000..368e52e --- /dev/null +++ b/SOURCES/0100-libmultipath-Set-the-scsi-timeout-parameters-by-path.patch @@ -0,0 +1,472 @@ +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 | 149 +++++++++++++++++++++++---------------- + libmultipath/discovery.h | 2 +- + libmultipath/propsel.c | 42 +++++------ + libmultipath/propsel.h | 6 +- + libmultipath/structs.c | 1 - + libmultipath/structs.h | 6 +- + 7 files changed, 118 insertions(+), 93 deletions(-) + +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index 9a9890f5..6cad0468 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -338,9 +338,6 @@ int setup_map(struct multipath *mpp, char *params, int params_size, + 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); +@@ -356,7 +353,7 @@ int setup_map(struct multipath *mpp, char *params, int params_size, + 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 2404cb87..36cc389e 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -581,13 +581,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; + +- 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); +@@ -596,12 +596,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) + sprintf(value, "off"); +- else if (mpp->eh_deadline == EH_DEADLINE_ZERO) ++ else if (pp->eh_deadline == EH_DEADLINE_ZERO) + sprintf(value, "0"); + else +- snprintf(value, 16, "%u", mpp->eh_deadline); ++ snprintf(value, 16, "%u", pp->eh_deadline); + + ret = sysfs_attr_set_value(hostdev, "eh_deadline", + value, strlen(value)); +@@ -625,6 +625,9 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp) + unsigned int tmo; + int ret; + ++ if (!pp->dev_loss && pp->fast_io_fail == MP_FAST_IO_FAIL_UNSET) ++ return; ++ + sprintf(rport_id, "rport-%d:%d-%d", + pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id); + rport_dev = udev_device_new_from_subsystem_sysname(udev, +@@ -664,14 +667,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) { +@@ -685,20 +688,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(3, "%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) { +@@ -709,8 +712,8 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp) + rport_id, value, -ret); + } + } +- if (mpp->dev_loss > 0) { +- snprintf(value, 16, "%u", mpp->dev_loss); ++ if (pp->dev_loss > 0) { ++ snprintf(value, 16, "%u", pp->dev_loss); + ret = sysfs_attr_set_value(rport_dev, "dev_loss_tmo", + value, strlen(value)); + if (ret <= 0) { +@@ -726,7 +729,7 @@ 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]; +@@ -743,18 +746,18 @@ 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->dev_loss) { ++ if (pp->dev_loss) { + condlog(3, "%s: ignoring dev_loss_tmo on iSCSI", pp->dev); + } +- 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, " +@@ -767,12 +770,15 @@ 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 *sas_dev = NULL; + char end_dev_id[64]; + char value[11]; + ++ if (!pp->udev || !pp->dev_loss) ++ return; ++ + sprintf(end_dev_id, "end_device-%d:%d", + pp->sg_id.host_no, pp->sg_id.transport_id); + sas_dev = udev_device_new_from_subsystem_sysname(udev, +@@ -785,8 +791,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) { +- snprintf(value, 11, "%u", mpp->dev_loss); ++ if (pp->dev_loss) { ++ 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 " +@@ -798,53 +804,76 @@ 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; ++ 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; +- condlog(3, "%s: update dev_loss_tmo to %u", +- mpp->alias, dev_loss_tmo); +- } else if (mpp->no_path_retry == NO_PATH_RETRY_QUEUE) { +- dev_loss_tmo = MAX_DEV_LOSS_TMO; +- condlog(3, "%s: update dev_loss_tmo to %u", +- mpp->alias, dev_loss_tmo); +- } +- mpp->dev_loss = dev_loss_tmo; +- if (mpp->dev_loss && mpp->fast_io_fail > 0 && +- (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 && 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) { ++ select_fast_io_fail(conf, pp); ++ select_dev_loss(conf, pp); ++ select_eh_deadline(conf, pp); ++ ++ if (!pp->dev_loss && pp->eh_deadline == EH_DEADLINE_UNSET && ++ pp->fast_io_fail == MP_FAST_IO_FAIL_UNSET) ++ continue; ++ + if (pp->bus != SYSFS_BUS_SCSI) + continue; ++ sysfs_set_eh_deadline(pp); ++ ++ if (!pp->dev_loss && 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 > 0 && pp->dev_loss < min_dev_loss) { ++ warn_dev_loss = true; ++ pp->dev_loss = min_dev_loss; ++ } ++ if (pp->dev_loss > 0 && 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; ++ } + +- if (mpp->dev_loss || +- mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) { +- if (pp->sg_id.proto_id == SCSI_PROTOCOL_FCP) +- sysfs_set_rport_tmo(mpp, pp); +- else if (pp->sg_id.proto_id == SCSI_PROTOCOL_ISCSI) +- sysfs_set_session_tmo(mpp, pp); +- else if (pp->sg_id.proto_id == SCSI_PROTOCOL_SAS) +- sysfs_set_nexus_loss_tmo(mpp, pp); ++ switch (pp->sg_id.proto_id) { ++ case SCSI_PROTOCOL_FCP: ++ sysfs_set_rport_tmo(mpp, pp); ++ break; ++ case SCSI_PROTOCOL_ISCSI: ++ sysfs_set_session_tmo(pp); ++ break; ++ case SCSI_PROTOCOL_SAS: ++ sysfs_set_nexus_loss_tmo(pp); ++ break; ++ default: ++ break; + } +- sysfs_set_eh_deadline(mpp, pp); + } ++ 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 127b3370..25326eb6 100644 +--- a/libmultipath/propsel.c ++++ b/libmultipath/propsel.c +@@ -766,51 +766,51 @@ 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; + char buff[12]; + +- 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, 12, mp->fast_io_fail); +- condlog(3, "%s: fast_io_fail_tmo = %s %s", mp->alias, buff, origin); ++ print_undef_off_zero(buff, 12, pp->fast_io_fail); ++ condlog(3, "%s: fast_io_fail_tmo = %s %s", pp->dev, 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; + char buff[12]; + +- mp_set_ovr(dev_loss); +- mp_set_hwe(dev_loss); +- mp_set_conf(dev_loss); +- mp->dev_loss = 0; ++ pp_set_ovr(dev_loss); ++ pp_set_hwe(dev_loss); ++ pp_set_conf(dev_loss); ++ pp->dev_loss = 0; + return 0; + out: +- print_dev_loss(buff, 12, mp->dev_loss); +- condlog(3, "%s: dev_loss_tmo = %s %s", mp->alias, buff, origin); ++ print_dev_loss(buff, 12, pp->dev_loss); ++ condlog(3, "%s: dev_loss_tmo = %s %s", pp->dev, 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; + char buff[12]; + +- 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, 12, mp->eh_deadline); +- condlog(3, "%s: eh_deadline = %s %s", mp->alias, buff, origin); ++ print_undef_off_zero(buff, 12, pp->eh_deadline); ++ condlog(3, "%s: eh_deadline = %s %s", pp->dev, 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 19099bed..9f86eb69 100644 +--- a/libmultipath/structs.c ++++ b/libmultipath/structs.c +@@ -230,7 +230,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 ab99852f..875e726e 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -344,6 +344,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; +@@ -371,7 +374,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; +@@ -389,8 +391,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/0101-libmultipath-check-the-overrides-pctable-for-path-va.patch b/SOURCES/0101-libmultipath-check-the-overrides-pctable-for-path-va.patch new file mode 100644 index 0000000..369ab5a --- /dev/null +++ b/SOURCES/0101-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 25326eb6..209c1d67 100644 +--- a/libmultipath/propsel.c ++++ b/libmultipath/propsel.c +@@ -79,6 +79,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[] = +@@ -144,6 +146,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; +@@ -771,7 +794,7 @@ int select_fast_io_fail(struct config *conf, struct path *pp) + const char *origin; + char buff[12]; + +- 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); +@@ -786,7 +809,7 @@ int select_dev_loss(struct config *conf, struct path *pp) + const char *origin; + char buff[12]; + +- pp_set_ovr(dev_loss); ++ pp_set_ovr_pce(dev_loss); + pp_set_hwe(dev_loss); + pp_set_conf(dev_loss); + pp->dev_loss = 0; +@@ -802,7 +825,7 @@ int select_eh_deadline(struct config *conf, struct path *pp) + const char *origin; + char buff[12]; + +- 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/0102-libmultipath-fix-eh_deadline-documentation.patch b/SOURCES/0102-libmultipath-fix-eh_deadline-documentation.patch new file mode 100644 index 0000000..167590b --- /dev/null +++ b/SOURCES/0102-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 0c04c7e4..b14fd215 100644 +--- a/multipath/multipath.conf.5 ++++ b/multipath/multipath.conf.5 +@@ -1602,6 +1602,8 @@ section: + .TP + .B dev_loss_tmo + .TP ++.B eh_deadline ++.TP + .B flush_on_last_del + .TP + .B user_friendly_names +@@ -1688,6 +1690,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/0103-libmultipath-Add-documentation-for-the-protocol-subs.patch b/SOURCES/0103-libmultipath-Add-documentation-for-the-protocol-subs.patch new file mode 100644 index 0000000..114f02e --- /dev/null +++ b/SOURCES/0103-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 b14fd215..abbc89af 100644 +--- a/multipath/multipath.conf.5 ++++ b/multipath/multipath.conf.5 +@@ -1730,6 +1730,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/0104-libmultipath-use-symbolic-value-for-invalid-pcentry.patch b/SOURCES/0104-libmultipath-use-symbolic-value-for-invalid-pcentry.patch new file mode 100644 index 0000000..da6eb9d --- /dev/null +++ b/SOURCES/0104-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 88975323..bcd8b541 100644 +--- a/libmultipath/config.c ++++ b/libmultipath/config.c +@@ -319,7 +319,7 @@ alloc_pce (void) + { + struct pcentry *pce = (struct pcentry *) + calloc(1, sizeof(struct pcentry)); +- pce->type = -1; ++ pce->type = PCE_INVALID; + return pce; + } + +@@ -578,7 +578,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 143116b3..477f8bfa 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/SPECS/device-mapper-multipath.spec b/SPECS/device-mapper-multipath.spec index 03835fc..f4c385f 100644 --- a/SPECS/device-mapper-multipath.spec +++ b/SPECS/device-mapper-multipath.spec @@ -1,7 +1,7 @@ Summary: Tools to manage multipath devices using device-mapper Name: device-mapper-multipath Version: 0.8.4 -Release: 23%{?dist} +Release: 24%{?dist} License: GPLv2 Group: System Environment/Base URL: http://christophe.varoqui.free.fr/ @@ -104,6 +104,17 @@ Patch00090: 0090-RH-add-support-to-mpathconf-for-setting-arbitrary-de.patch Patch00091: 0091-multipath-tools-add-HPE-MSA-1060-2060-to-hwtable.patch Patch00092: 0092-multipath-tools-update-mpp-force_readonly-in-ev_add_.patch Patch00093: 0093-updated-HPE-MSA-builtin-config.patch +Patch00094: 0094-multipath-return-failure-on-an-invalid-remove-comman.patch +Patch00095: 0095-libmultipath-steal-the-src-string-pointer-in-merge_s.patch +Patch00096: 0096-libmultipath-enable-linear-ordering-of-bus-proto-tup.patch +Patch00097: 0097-libmultipath-use-bus_protocol_id-in-snprint_path_pro.patch +Patch00098: 0098-libmultipath-make-protocol_name-global.patch +Patch00099: 0099-libmultipath-add-a-protocol-subsection-to-multipath..patch +Patch00100: 0100-libmultipath-Set-the-scsi-timeout-parameters-by-path.patch +Patch00101: 0101-libmultipath-check-the-overrides-pctable-for-path-va.patch +Patch00102: 0102-libmultipath-fix-eh_deadline-documentation.patch +Patch00103: 0103-libmultipath-Add-documentation-for-the-protocol-subs.patch +Patch00104: 0104-libmultipath-use-symbolic-value-for-invalid-pcentry.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -305,6 +316,22 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Mon May 16 2022 Benjamin Marzinski 0.8.4-23 +- Add 0094-multipath-return-failure-on-an-invalid-remove-comman.patch + * Fixes bz #2052054 +- Add 0095-libmultipath-steal-the-src-string-pointer-in-merge_s.patch +- Add 0096-libmultipath-enable-linear-ordering-of-bus-proto-tup.patch +- Add 0097-libmultipath-use-bus_protocol_id-in-snprint_path_pro.patch +- Add 0098-libmultipath-make-protocol_name-global.patch +- Add 0099-libmultipath-add-a-protocol-subsection-to-multipath..patch +- Add 0100-libmultipath-Set-the-scsi-timeout-parameters-by-path.patch +- Add 0101-libmultipath-check-the-overrides-pctable-for-path-va.patch +- Add 0102-libmultipath-fix-eh_deadline-documentation.patch +- Add 0103-libmultipath-Add-documentation-for-the-protocol-subs.patch +- Add 0104-libmultipath-use-symbolic-value-for-invalid-pcentry.patch + * The above 10 patches implement feature from bz #2065477 +- Resolves: bz #2052054, #2065477 + * Tue May 10 2022 Benjamin Marzinski 0.8.4-23 - Add 0091-multipath-tools-add-HPE-MSA-1060-2060-to-hwtable.patch * Partial fix for bz #2058222