diff --git a/SOURCES/0064-libmultipath-check-udev_device_get_-return-value-to-.patch b/SOURCES/0064-libmultipath-check-udev_device_get_-return-value-to-.patch new file mode 100644 index 0000000..20afb10 --- /dev/null +++ b/SOURCES/0064-libmultipath-check-udev_device_get_-return-value-to-.patch @@ -0,0 +1,129 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lixiaokeng +Date: Mon, 21 Sep 2020 12:00:39 +0800 +Subject: [PATCH] libmultipath: check udev_device_get_* return value to avoid + segfault + +The udev_device_get_* function may return NULL, and it will be +deregerenced in str* and sscanf func. We check the return value +to avoid segfault. Fix all. + +Reviewed-by: Martin Wilck +Signed-off-by:Lixiaokeng +Signed-off-by: Zhiqiang Liu +Signed-off-by: Linfeilong +Signed-off-by: Benjamin Marzinski +--- + libmultipath/configure.c | 4 +++- + libmultipath/discovery.c | 9 +++++++-- + libmultipath/foreign/nvme.c | 10 +++++++--- + 3 files changed, 17 insertions(+), 6 deletions(-) + +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index 2e8f34f9..a6893d8d 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -511,6 +511,7 @@ static void trigger_partitions_udev_change(struct udev_device *dev, + { + struct udev_enumerate *part_enum; + struct udev_list_entry *item; ++ const char *devtype; + + part_enum = udev_enumerate_new(udev); + if (!part_enum) +@@ -531,7 +532,8 @@ static void trigger_partitions_udev_change(struct udev_device *dev, + if (!part) + continue; + +- if (!strcmp("partition", udev_device_get_devtype(part))) { ++ devtype = udev_device_get_devtype(part); ++ if (devtype && !strcmp("partition", devtype)) { + condlog(4, "%s: triggering %s event for %s", __func__, + action, syspath); + sysfs_attr_set_value(part, "uevent", action, len); +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index a328aafa..74abf34d 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -353,7 +353,7 @@ sysfs_get_tgt_nodename(struct path *pp, char *node) + tgtdev = udev_device_get_parent(parent); + while (tgtdev) { + tgtname = udev_device_get_sysname(tgtdev); +- if (sscanf(tgtname, "end_device-%d:%d", ++ if (tgtname && sscanf(tgtname, "end_device-%d:%d", + &host, &tgtid) == 2) + break; + tgtdev = udev_device_get_parent(tgtdev); +@@ -386,7 +386,7 @@ sysfs_get_tgt_nodename(struct path *pp, char *node) + /* Check for FibreChannel */ + tgtdev = udev_device_get_parent(parent); + value = udev_device_get_sysname(tgtdev); +- if (sscanf(value, "rport-%d:%d-%d", ++ if (value && sscanf(value, "rport-%d:%d-%d", + &host, &channel, &tgtid) == 3) { + tgtdev = udev_device_new_from_subsystem_sysname(udev, + "fc_remote_ports", value); +@@ -516,6 +516,9 @@ int sysfs_get_host_pci_name(const struct path *pp, char *pci_name) + */ + value = udev_device_get_sysname(parent); + ++ if (!value) ++ return 1; ++ + strncpy(pci_name, value, SLOT_NAME_SIZE); + udev_device_unref(hostdev); + return 0; +@@ -1518,6 +1521,8 @@ ccw_sysfs_pathinfo (struct path * pp, vector hwtable) + * host / bus / target / lun + */ + attr_path = udev_device_get_sysname(parent); ++ if (!attr_path) ++ return PATHINFO_FAILED; + pp->sg_id.lun = 0; + if (sscanf(attr_path, "%i.%i.%x", + &pp->sg_id.host_no, +diff --git a/libmultipath/foreign/nvme.c b/libmultipath/foreign/nvme.c +index 09cdddf0..5feb1e95 100644 +--- a/libmultipath/foreign/nvme.c ++++ b/libmultipath/foreign/nvme.c +@@ -482,6 +482,7 @@ _find_path_by_syspath(struct nvme_map *map, const char *syspath) + struct nvme_pathgroup *pg; + char real[PATH_MAX]; + const char *ppath; ++ const char *psyspath; + int i; + + ppath = realpath(syspath, real); +@@ -493,8 +494,8 @@ _find_path_by_syspath(struct nvme_map *map, const char *syspath) + vector_foreach_slot(&map->pgvec, pg, i) { + struct nvme_path *path = nvme_pg_to_path(pg); + +- if (!strcmp(ppath, +- udev_device_get_syspath(path->udev))) ++ psyspath = udev_device_get_syspath(path->udev); ++ if (psyspath && !strcmp(ppath, psyspath)) + return path; + } + condlog(4, "%s: %s: %s not found", __func__, THIS, ppath); +@@ -538,6 +539,7 @@ struct udev_device *get_ctrl_blkdev(const struct context *ctx, + struct udev_list_entry *item; + struct udev_device *blkdev = NULL; + struct udev_enumerate *enm = udev_enumerate_new(ctx->udev); ++ const char *devtype; + + if (enm == NULL) + return NULL; +@@ -562,7 +564,9 @@ struct udev_device *get_ctrl_blkdev(const struct context *ctx, + udev_list_entry_get_name(item)); + if (tmp == NULL) + continue; +- if (!strcmp(udev_device_get_devtype(tmp), "disk")) { ++ ++ devtype = udev_device_get_devtype(tmp); ++ if (devtype && !strcmp(devtype, "disk")) { + blkdev = tmp; + break; + } else +-- +2.17.2 + diff --git a/SOURCES/0065-libmultipath-cleanup-code-to-strip-wwid-trailing-spa.patch b/SOURCES/0065-libmultipath-cleanup-code-to-strip-wwid-trailing-spa.patch new file mode 100644 index 0000000..41aed73 --- /dev/null +++ b/SOURCES/0065-libmultipath-cleanup-code-to-strip-wwid-trailing-spa.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 24 Feb 2021 00:33:20 -0600 +Subject: [PATCH] libmultipath: cleanup code to strip wwid trailing spaces + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + libmultipath/discovery.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 74abf34d..126a70b3 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -2062,11 +2062,11 @@ int + get_uid (struct path * pp, int path_state, struct udev_device *udev, + int allow_fallback) + { +- char *c; + const char *origin = "unknown"; + ssize_t len = 0; + struct config *conf; + int used_fallback = 0; ++ size_t i; + + if (!pp->uid_attribute && !pp->getuid) { + conf = get_multipath_config(); +@@ -2119,12 +2119,9 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev, + return 1; + } else { + /* Strip any trailing blanks */ +- c = strchr(pp->wwid, '\0'); +- c--; +- while (c && c >= pp->wwid && *c == ' ') { +- *c = '\0'; +- c--; +- } ++ for (i = strlen(pp->wwid); i > 0 && pp->wwid[i-1] == ' '; i--); ++ /* no-op */ ++ pp->wwid[i] = '\0'; + } + condlog((used_fallback)? 1 : 3, "%s: uid = %s (%s)", pp->dev, + *pp->wwid == '\0' ? "" : pp->wwid, origin); +-- +2.17.2 + diff --git a/SOURCES/0066-multipathd-add-recheck_wwid-option-to-verify-the-pat.patch b/SOURCES/0066-multipathd-add-recheck_wwid-option-to-verify-the-pat.patch new file mode 100644 index 0000000..500c1ce --- /dev/null +++ b/SOURCES/0066-multipathd-add-recheck_wwid-option-to-verify-the-pat.patch @@ -0,0 +1,429 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 24 Feb 2021 00:33:22 -0600 +Subject: [PATCH] multipathd: add recheck_wwid option to verify the path wwid + +There are cases where the wwid of a path changes due to LUN remapping +without triggering uevent for the changed path. Multipathd has no method +for trying to catch these cases, and corruption has resulted because of +it. + +In order to have a better chance at catching these cases, multipath now +has a recheck_wwid option. If this is set to "yes", when a failed path +has become active again, multipathd will recheck its wwid. If multipathd +notices that a path's wwid has changed, it will remove and re-add the +path, just like the existing wwid checking code for change events does. +In cases where the no uevent occurs, both the udev database entry and +sysfs will have the old wwid, so the only way to get a current wwid is +to ask the device directly. Currently multipath only has code to +directly get the wwid for scsi devices, so this option only effects scsi +devices, and they must be configured to be able to use the uid_fallback +methods. To make sure both the sysfs and udev database values are +updated, multipathd triggers a both a rescan of the device and a udev +add event. + +Co-developed-by: Chongyun Wu +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck Reviewed-by: Martin Wilck +--- + libmultipath/config.c | 2 + + libmultipath/config.h | 2 + + libmultipath/configure.c | 4 +- + libmultipath/configure.h | 2 + + libmultipath/defaults.h | 1 + + libmultipath/dict.c | 11 ++++++ + libmultipath/discovery.c | 3 +- + libmultipath/discovery.h | 1 + + libmultipath/propsel.c | 21 ++++++++++ + libmultipath/propsel.h | 1 + + libmultipath/structs.h | 7 ++++ + multipath/multipath.conf.5 | 14 +++++++ + multipathd/cli_handlers.c | 9 +++++ + multipathd/main.c | 78 ++++++++++++++++++++++++++++++++++++++ + multipathd/main.h | 2 + + 15 files changed, 155 insertions(+), 3 deletions(-) + +diff --git a/libmultipath/config.c b/libmultipath/config.c +index dd645f17..abbddaf1 100644 +--- a/libmultipath/config.c ++++ b/libmultipath/config.c +@@ -371,6 +371,7 @@ merge_hwe (struct hwentry * dst, struct hwentry * src) + merge_num(max_sectors_kb); + merge_num(ghost_delay); + merge_num(all_tg_pt); ++ merge_num(recheck_wwid); + merge_num(vpd_vendor_id); + merge_num(san_path_err_threshold); + merge_num(san_path_err_forget_rate); +@@ -762,6 +763,7 @@ load_config (char * file) + conf->remove_retries = 0; + conf->ghost_delay = DEFAULT_GHOST_DELAY; + conf->all_tg_pt = DEFAULT_ALL_TG_PT; ++ conf->recheck_wwid = DEFAULT_RECHECK_WWID; + /* + * preload default hwtable + */ +diff --git a/libmultipath/config.h b/libmultipath/config.h +index a22c1b4e..e2e3f143 100644 +--- a/libmultipath/config.h ++++ b/libmultipath/config.h +@@ -84,6 +84,7 @@ struct hwentry { + int ghost_delay; + int all_tg_pt; + int vpd_vendor_id; ++ int recheck_wwid; + char * bl_product; + }; + +@@ -188,6 +189,7 @@ struct config { + int skip_delegate; + unsigned int version[3]; + unsigned int sequence_nr; ++ int recheck_wwid; + + char * multipath_dir; + char * selector; +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index a6893d8d..f24d9283 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -506,8 +506,8 @@ trigger_udev_change(const struct multipath *mpp) + udev_device_unref(udd); + } + +-static void trigger_partitions_udev_change(struct udev_device *dev, +- const char *action, int len) ++void trigger_partitions_udev_change(struct udev_device *dev, ++ const char *action, int len) + { + struct udev_enumerate *part_enum; + struct udev_list_entry *item; +diff --git a/libmultipath/configure.h b/libmultipath/configure.h +index 0e33bf40..81090dd4 100644 +--- a/libmultipath/configure.h ++++ b/libmultipath/configure.h +@@ -57,3 +57,5 @@ int get_refwwid (enum mpath_cmds cmd, char * dev, enum devtypes dev_type, + int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh, int is_daemon); + struct udev_device *get_udev_device(const char *dev, enum devtypes dev_type); + void trigger_paths_udev_change(struct multipath *mpp, bool is_mpath); ++void trigger_partitions_udev_change(struct udev_device *dev, const char *action, ++ int len); +diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h +index 52fe05b9..f1cb000d 100644 +--- a/libmultipath/defaults.h ++++ b/libmultipath/defaults.h +@@ -50,6 +50,7 @@ + #define DEFAULT_FIND_MULTIPATHS_TIMEOUT -10 + #define DEFAULT_UNKNOWN_FIND_MULTIPATHS_TIMEOUT 1 + #define DEFAULT_ALL_TG_PT ALL_TG_PT_OFF ++#define DEFAULT_RECHECK_WWID RECHECK_WWID_OFF + /* Enable all foreign libraries by default */ + #define DEFAULT_ENABLE_FOREIGN "" + +diff --git a/libmultipath/dict.c b/libmultipath/dict.c +index 8fd91d8c..13698b76 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -1413,6 +1413,14 @@ declare_hw_snprint(all_tg_pt, print_yes_no_undef) + declare_def_handler(marginal_pathgroups, set_yes_no) + declare_def_snprint(marginal_pathgroups, print_yes_no) + ++declare_def_handler(recheck_wwid, set_yes_no_undef) ++declare_def_snprint_defint(recheck_wwid, print_yes_no_undef, DEFAULT_RECHECK_WWID) ++declare_ovr_handler(recheck_wwid, set_yes_no_undef) ++declare_ovr_snprint(recheck_wwid, print_yes_no_undef) ++declare_hw_handler(recheck_wwid, set_yes_no_undef) ++declare_hw_snprint(recheck_wwid, print_yes_no_undef) ++ ++ + static int + def_uxsock_timeout_handler(struct config *conf, vector strvec) + { +@@ -1824,6 +1832,7 @@ init_keywords(vector keywords) + install_keyword("enable_foreign", &def_enable_foreign_handler, + &snprint_def_enable_foreign); + install_keyword("marginal_pathgroups", &def_marginal_pathgroups_handler, &snprint_def_marginal_pathgroups); ++ install_keyword("recheck_wwid", &def_recheck_wwid_handler, &snprint_def_recheck_wwid); + __deprecated install_keyword("default_selector", &def_selector_handler, NULL); + __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); + __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL); +@@ -1913,6 +1922,7 @@ init_keywords(vector keywords) + install_keyword("ghost_delay", &hw_ghost_delay_handler, &snprint_hw_ghost_delay); + install_keyword("all_tg_pt", &hw_all_tg_pt_handler, &snprint_hw_all_tg_pt); + install_keyword("vpd_vendor", &hw_vpd_vendor_handler, &snprint_hw_vpd_vendor); ++ install_keyword("recheck_wwid", &hw_recheck_wwid_handler, &snprint_hw_recheck_wwid); + install_sublevel_end(); + + install_keyword_root("overrides", &overrides_handler); +@@ -1954,6 +1964,7 @@ init_keywords(vector keywords) + install_keyword("max_sectors_kb", &ovr_max_sectors_kb_handler, &snprint_ovr_max_sectors_kb); + 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_root("multipaths", &multipaths_handler); + install_keyword_multi("multipath", &multipath_handler, NULL); +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 126a70b3..bc267609 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -2040,7 +2040,7 @@ static ssize_t uid_fallback(struct path *pp, int path_state, + return len; + } + +-static bool has_uid_fallback(struct path *pp) ++bool has_uid_fallback(struct path *pp) + { + /* + * Falling back to direct WWID determination is dangerous +@@ -2072,6 +2072,7 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev, + conf = get_multipath_config(); + pthread_cleanup_push(put_multipath_config, conf); + select_getuid(conf, pp); ++ select_recheck_wwid(conf, pp); + pthread_cleanup_pop(1); + } + +diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h +index d3193daf..a5446b4d 100644 +--- a/libmultipath/discovery.h ++++ b/libmultipath/discovery.h +@@ -54,6 +54,7 @@ ssize_t sysfs_get_inquiry(struct udev_device *udev, + unsigned char *buff, size_t len); + int sysfs_get_asymmetric_access_state(struct path *pp, + char *buff, int buflen); ++bool has_uid_fallback(struct path *pp); + int get_uid(struct path * pp, int path_state, struct udev_device *udev, + int allow_fallback); + bool is_vpd_page_supported(int fd, int pg); +diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c +index 1150cfe8..127b3370 100644 +--- a/libmultipath/propsel.c ++++ b/libmultipath/propsel.c +@@ -581,6 +581,27 @@ out: + return 0; + } + ++/* must be called after select_getuid */ ++int select_recheck_wwid(struct config *conf, struct path * pp) ++{ ++ const char *origin; ++ ++ pp_set_ovr(recheck_wwid); ++ pp_set_hwe(recheck_wwid); ++ pp_set_conf(recheck_wwid); ++ pp_set_default(recheck_wwid, DEFAULT_RECHECK_WWID); ++out: ++ if (pp->recheck_wwid == RECHECK_WWID_ON && ++ (pp->bus != SYSFS_BUS_SCSI || pp->getuid != NULL || ++ !has_uid_fallback(pp))) { ++ pp->recheck_wwid = RECHECK_WWID_OFF; ++ origin = "(setting: unsupported by device type/config)"; ++ } ++ condlog(3, "%s: recheck_wwid = %i %s", pp->dev, pp->recheck_wwid, ++ origin); ++ return 0; ++} ++ + void + detect_prio(struct config *conf, struct path * pp) + { +diff --git a/libmultipath/propsel.h b/libmultipath/propsel.h +index a68bacf0..72a7e33c 100644 +--- a/libmultipath/propsel.h ++++ b/libmultipath/propsel.h +@@ -7,6 +7,7 @@ int select_features (struct config *conf, struct multipath * mp); + int select_hwhandler (struct config *conf, struct multipath * mp); + int select_checker(struct config *conf, struct path *pp); + int select_getuid (struct config *conf, struct path * pp); ++int select_recheck_wwid(struct config *conf, struct path * pp); + int select_prio (struct config *conf, struct path * pp); + int select_find_multipaths_timeout(struct config *conf, struct path *pp); + int select_no_path_retry(struct config *conf, struct multipath *mp); +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index 65542dea..a5dbad5b 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -252,6 +252,12 @@ enum eh_deadline_states { + EH_DEADLINE_ZERO = UOZ_ZERO, + }; + ++enum recheck_wwid_states { ++ RECHECK_WWID_UNDEF = YNU_UNDEF, ++ RECHECK_WWID_OFF = YNU_NO, ++ RECHECK_WWID_ON = YNU_YES, ++}; ++ + struct vpd_vendor_page { + int pg; + const char *name; +@@ -326,6 +332,7 @@ struct path { + int find_multipaths_timeout; + int marginal; + int vpd_vendor_id; ++ int recheck_wwid; + /* configlet pointers */ + vector hwe; + struct gen_path generic_path; +diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 +index a5686090..6da15aad 100644 +--- a/multipath/multipath.conf.5 ++++ b/multipath/multipath.conf.5 +@@ -1256,6 +1256,20 @@ The default is: \fB\(dq\(dq\fR (the empty regular expression) + .RE + . + . ++.TP ++.B recheck_wwid ++If set to \fIyes\fR, when a failed path is restored, its wwid is rechecked. If ++the wwid has changed, the path is removed from the current multipath device, ++and re-added as a new path. Multipathd will also recheck a path's wwid if it is ++manually re-added. This option only works for SCSI devices that are configured ++to use the default uid_attribute, \fIID_SERIAL\fR, or sysfs for getting their ++wwid. ++.RS ++.TP ++The default is \fBno\fR ++.RE ++. ++. + + . + .\" ---------------------------------------------------------------------------- +diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c +index 782bb003..8b4bd187 100644 +--- a/multipathd/cli_handlers.c ++++ b/multipathd/cli_handlers.c +@@ -715,6 +715,15 @@ cli_add_path (void * v, char ** reply, int * len, void * data) + pp = find_path_by_dev(vecs->pathvec, param); + if (pp) { + condlog(2, "%s: path already in pathvec", param); ++ ++ if (pp->recheck_wwid == RECHECK_WWID_ON && ++ check_path_wwid_change(pp)) { ++ condlog(0, "%s: wwid changed. Removing device", ++ pp->dev); ++ handle_path_wwid_change(pp, vecs); ++ return 1; ++ } ++ + if (pp->mpp) + return 0; + } else { +diff --git a/multipathd/main.c b/multipathd/main.c +index cc1aeea2..1fbc31eb 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -822,6 +822,73 @@ ev_remove_map (char * devname, char * alias, int minor, struct vectors * vecs) + return flush_map(mpp, vecs, 0); + } + ++static void ++rescan_path(struct udev_device *parent) ++{ ++ while(parent) { ++ const char *subsys = udev_device_get_subsystem(parent); ++ if (subsys && !strncmp(subsys, "scsi", 4)) ++ break; ++ parent = udev_device_get_parent(parent); ++ } ++ if (parent) ++ sysfs_attr_set_value(parent, "rescan", "1", strlen("1")); ++} ++ ++void ++handle_path_wwid_change(struct path *pp, struct vectors *vecs) ++{ ++ struct udev_device *udd; ++ ++ if (!pp || !pp->udev) ++ return; ++ ++ udd = udev_device_ref(pp->udev); ++ if (ev_remove_path(pp, vecs, 1) != 0 && pp->mpp) { ++ pp->dmstate = PSTATE_FAILED; ++ dm_fail_path(pp->mpp->alias, pp->dev_t); ++ } ++ rescan_path(udd); ++ sysfs_attr_set_value(udd, "uevent", "add", strlen("add")); ++ trigger_partitions_udev_change(udd, "add", strlen("add")); ++ udev_device_unref(udd); ++} ++ ++bool ++check_path_wwid_change(struct path *pp) ++{ ++ char wwid[WWID_SIZE]; ++ int len = 0; ++ size_t i; ++ ++ if (!strlen(pp->wwid)) ++ return false; ++ ++ /* Get the real fresh device wwid by sgio. sysfs still has old ++ * data, so only get_vpd_sgio will work to get the new wwid */ ++ len = get_vpd_sgio(pp->fd, 0x83, 0, wwid, WWID_SIZE); ++ ++ if (len <= 0) { ++ condlog(2, "%s: failed to check wwid by sgio: len = %d", ++ pp->dev, len); ++ return false; ++ } ++ ++ /*Strip any trailing blanks */ ++ for (i = strlen(pp->wwid); i > 0 && pp->wwid[i-1] == ' '; i--); ++ /* no-op */ ++ pp->wwid[i] = '\0'; ++ condlog(4, "%s: Got wwid %s by sgio", pp->dev, wwid); ++ ++ if (strncmp(wwid, pp->wwid, WWID_SIZE)) { ++ condlog(0, "%s: wwid '%s' doesn't match wwid '%s' from device", ++ pp->dev, pp->wwid, wwid); ++ return true; ++ } ++ ++ return false; ++} ++ + static int + uev_add_path (struct uevent *uev, struct vectors * vecs, int need_do_map) + { +@@ -1241,6 +1308,7 @@ uev_update_path (struct uevent *uev, struct vectors * vecs) + condlog(0, "%s: path wwid changed from '%s' to '%s'", + uev->kernel, wwid, pp->wwid); + ev_remove_path(pp, vecs, 1); ++ rescan_path(uev->udev); + needs_reinit = 1; + goto out; + } else { +@@ -2101,6 +2169,16 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks) + return 0; + set_no_path_retry(pp->mpp); + ++ if (pp->recheck_wwid == RECHECK_WWID_ON && ++ (newstate == PATH_UP || newstate == PATH_GHOST) && ++ ((pp->state != PATH_UP && pp->state != PATH_GHOST) || ++ pp->dmstate == PSTATE_FAILED) && ++ check_path_wwid_change(pp)) { ++ condlog(0, "%s: path wwid change detected. Removing", pp->dev); ++ handle_path_wwid_change(pp, vecs); ++ return 0; ++ } ++ + if ((newstate == PATH_UP || newstate == PATH_GHOST) && + (san_path_check_enabled(pp->mpp) || + marginal_path_check_enabled(pp->mpp))) { +diff --git a/multipathd/main.h b/multipathd/main.h +index 5dff17e5..8f0028a9 100644 +--- a/multipathd/main.h ++++ b/multipathd/main.h +@@ -49,4 +49,6 @@ int update_multipath (struct vectors *vecs, char *mapname, int reset); + int update_path_groups(struct multipath *mpp, struct vectors *vecs, + int refresh); + ++void handle_path_wwid_change(struct path *pp, struct vectors *vecs); ++bool check_path_wwid_change(struct path *pp); + #endif /* MAIN_H */ +-- +2.17.2 + diff --git a/SOURCES/0067-libmultipath-avoid-infinite-loop-with-bad-vpd-page-8.patch b/SOURCES/0067-libmultipath-avoid-infinite-loop-with-bad-vpd-page-8.patch new file mode 100644 index 0000000..c261ee2 --- /dev/null +++ b/SOURCES/0067-libmultipath-avoid-infinite-loop-with-bad-vpd-page-8.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 25 Mar 2021 19:52:43 -0500 +Subject: [PATCH] libmultipath: avoid infinite loop with bad vpd page 83 + identifier + +If a device with a scsi name identifier has an unknown prefix, +parse_vpd_pg83() needs to advance to the next identifier, instead of +simply trying the same one again in an infinite loop. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + libmultipath/discovery.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index bc267609..8c2ab073 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1101,7 +1101,7 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, + if (memcmp(d + 4, "eui.", 4) && + memcmp(d + 4, "naa.", 4) && + memcmp(d + 4, "iqn.", 4)) +- continue; ++ break; + if (prio < 4) { + prio = 4; + vpd = d; +-- +2.17.2 + diff --git a/SOURCES/0068-libmultipath-fix-priorities-in-parse_vpd_pg83.patch b/SOURCES/0068-libmultipath-fix-priorities-in-parse_vpd_pg83.patch new file mode 100644 index 0000000..d4ab400 --- /dev/null +++ b/SOURCES/0068-libmultipath-fix-priorities-in-parse_vpd_pg83.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 25 Mar 2021 19:52:44 -0500 +Subject: [PATCH] libmultipath: fix priorities in parse_vpd_pg83 + +The priorities for the EUI-64 (0x02) and NAME (0x08) scsi identifiers in +parse_vpd_pg83() don't match their priorities in 55-scsi-sg3_id.rules. +Switch them so that they match. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + libmultipath/discovery.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 8c2ab073..5e988631 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1096,19 +1096,19 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, + vpd = d; + } + break; +- case 0x8: +- /* SCSI Name: Prio 4 */ +- if (memcmp(d + 4, "eui.", 4) && +- memcmp(d + 4, "naa.", 4) && +- memcmp(d + 4, "iqn.", 4)) +- break; ++ case 0x2: ++ /* EUI-64: Prio 4 */ + if (prio < 4) { + prio = 4; + vpd = d; + } + break; +- case 0x2: +- /* EUI-64: Prio 3 */ ++ case 0x8: ++ /* SCSI Name: Prio 3 */ ++ if (memcmp(d + 4, "eui.", 4) && ++ memcmp(d + 4, "naa.", 4) && ++ memcmp(d + 4, "iqn.", 4)) ++ break; + if (prio < 3) { + prio = 3; + vpd = d; +-- +2.17.2 + diff --git a/SOURCES/0069-RH-make-parse_vpd_pg83-match-scsi_id-output.patch b/SOURCES/0069-RH-make-parse_vpd_pg83-match-scsi_id-output.patch new file mode 100644 index 0000000..d8f7ac1 --- /dev/null +++ b/SOURCES/0069-RH-make-parse_vpd_pg83-match-scsi_id-output.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 25 Mar 2021 13:05:10 -0500 +Subject: [PATCH] RH: make parse_vpd_pg83 match scsi_id output + +Red Hat sets ID_SERIAL based on the result of scsi_id, instead of using +the result of sg_inq and 55-scsi-sg3_id.rules. Make parse_vpd_pg83 match +that. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/discovery.c | 18 ++---------------- + 1 file changed, 2 insertions(+), 16 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 5e988631..2404cb87 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1079,12 +1079,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, + naa_prio = 7; + break; + case 2: +- /* IEEE Extended: Prio 6 */ +- naa_prio = 6; +- break; + case 3: +- /* IEEE Locally assigned: Prio 1 */ +- naa_prio = 1; ++ /* IEEE Extended or Locally assigned: Prio 6 */ ++ naa_prio = 6; + break; + default: + /* Default: no priority */ +@@ -1103,17 +1100,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, + vpd = d; + } + break; +- case 0x8: +- /* SCSI Name: Prio 3 */ +- if (memcmp(d + 4, "eui.", 4) && +- memcmp(d + 4, "naa.", 4) && +- memcmp(d + 4, "iqn.", 4)) +- break; +- if (prio < 3) { +- prio = 3; +- vpd = d; +- } +- break; + case 0x1: + /* T-10 Vendor ID: Prio 2 */ + if (prio < 2) { +-- +2.17.2 + diff --git a/SOURCES/0070-multipathd-improve-getting-parent-udevice-in-rescan_.patch b/SOURCES/0070-multipathd-improve-getting-parent-udevice-in-rescan_.patch new file mode 100644 index 0000000..6bb94fd --- /dev/null +++ b/SOURCES/0070-multipathd-improve-getting-parent-udevice-in-rescan_.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 25 Mar 2021 19:52:45 -0500 +Subject: [PATCH] multipathd: improve getting parent udevice in rescan_path + +Instead of looping through parents and checking, just call +udev_device_get_parent_with_subsystem_devtype() to get the +right one. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + multipathd/main.c | 14 +++++--------- + 1 file changed, 5 insertions(+), 9 deletions(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index 1fbc31eb..4598d354 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -823,16 +823,12 @@ ev_remove_map (char * devname, char * alias, int minor, struct vectors * vecs) + } + + static void +-rescan_path(struct udev_device *parent) ++rescan_path(struct udev_device *ud) + { +- while(parent) { +- const char *subsys = udev_device_get_subsystem(parent); +- if (subsys && !strncmp(subsys, "scsi", 4)) +- break; +- parent = udev_device_get_parent(parent); +- } +- if (parent) +- sysfs_attr_set_value(parent, "rescan", "1", strlen("1")); ++ ud = udev_device_get_parent_with_subsystem_devtype(ud, "scsi", ++ "scsi_device"); ++ if (ud) ++ sysfs_attr_set_value(ud, "rescan", "1", strlen("1")); + } + + void +-- +2.17.2 + diff --git a/SOURCES/0071-multipathd-don-t-trigger-uevent-for-partitions-on-ww.patch b/SOURCES/0071-multipathd-don-t-trigger-uevent-for-partitions-on-ww.patch new file mode 100644 index 0000000..b96d496 --- /dev/null +++ b/SOURCES/0071-multipathd-don-t-trigger-uevent-for-partitions-on-ww.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 25 Mar 2021 19:52:46 -0500 +Subject: [PATCH] multipathd: don't trigger uevent for partitions on wwid + change + +If the wwid changed, the device is no longer the same, so sending add +events to the devices partitions doesn't make any sense. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + multipathd/main.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index 4598d354..e6c19ab2 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -846,7 +846,6 @@ handle_path_wwid_change(struct path *pp, struct vectors *vecs) + } + rescan_path(udd); + sysfs_attr_set_value(udd, "uevent", "add", strlen("add")); +- trigger_partitions_udev_change(udd, "add", strlen("add")); + udev_device_unref(udd); + } + +-- +2.17.2 + diff --git a/SOURCES/0072-RH-mpathconf-correctly-handle-spaces-after-option-na.patch b/SOURCES/0072-RH-mpathconf-correctly-handle-spaces-after-option-na.patch new file mode 100644 index 0000000..0d39a77 --- /dev/null +++ b/SOURCES/0072-RH-mpathconf-correctly-handle-spaces-after-option-na.patch @@ -0,0 +1,165 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 9 Jul 2021 14:30:10 -0500 +Subject: [PATCH] RH: mpathconf: correctly handle spaces after option names + +mpathconf was either accepting any number of spaces, including zero, +after option names, or it was only accepting one space. It should +accept one or more spaces. + +Signed-off-by: Benjamin Marzinski +--- + multipath/mpathconf | 40 ++++++++++++++++++++-------------------- + 1 file changed, 20 insertions(+), 20 deletions(-) + +diff --git a/multipath/mpathconf b/multipath/mpathconf +index 2f4f3eaf..5f2285ab 100644 +--- a/multipath/mpathconf ++++ b/multipath/mpathconf +@@ -240,7 +240,7 @@ function validate_args + echo "--enable_foreign must be either 'y' or 'n'" + exit 1 + fi +- if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" -a -z "$PROPERTY" ]; then ++ if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" -a -z "$PROPERTY" -a -z "$FOREIGN" ]; then + SHOW_STATUS=1 + fi + if [ -n "$MODULE" ] && [ "$MODULE" != "y" -a "$MODULE" != "n" ]; then +@@ -315,36 +315,36 @@ if [ "$MULTIPATHD" = "y" ]; then + fi + + if [ "$HAVE_BLACKLIST" = "1" ]; then +- if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*devnode \"\.\?\*\"" ; then ++ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"" ; then + HAVE_DISABLE=1 +- elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"" ; then ++ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"" ; then + HAVE_DISABLE=0 + fi + fi + + if [ "$HAVE_BLACKLIST" = "1" ]; then +- if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*wwid \"\.\?\*\"" ; then ++ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*wwid[[:space:]][[:space:]]*\"\.\?\*\"" ; then + HAVE_WWID_DISABLE=1 +- elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"" ; then ++ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*wwid[[:space:]][[:space:]]*\"\.\?\*\"" ; then + HAVE_WWID_DISABLE=0 + fi + fi + + if [ "$HAVE_DEFAULTS" = "1" ]; then +- HAVE_FIND=`sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | sed -n 's/^[[:blank:]]*find_multipaths[[:blank:]]*\([^[:blank:]]*\).*$/\1/p' | sed -n 1p` ++ HAVE_FIND=`sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | sed -n 's/^[[:blank:]]*find_multipaths[[:blank:]][[:blank:]]*\([^[:blank:]]*\).*$/\1/p' | sed -n 1p` + if [ "$HAVE_FIND" = "1" ]; then + HAVE_FIND="yes" + elif [ "$HAVE_FIND" = "0" ]; then + HAVE_FIND="no" + fi +- if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)" ; then ++ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]][[:space:]]*\(yes\|1\)" ; then + HAVE_FRIENDLY=1 +- elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)" ; then ++ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]][[:space:]]*\(no\|0\)" ; then + HAVE_FRIENDLY=0 + fi + if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*enable_foreign" ; then + HAVE_FOREIGN=0 +- elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign[[:space:]]*\"\^\$\"" ; then ++ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign[[:space:]][[:space:]]*\"\^\$\"" ; then + HAVE_FOREIGN=1 + elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign" ; then + HAVE_FOREIGN=2 +@@ -352,9 +352,9 @@ if [ "$HAVE_DEFAULTS" = "1" ]; then + fi + + if [ "$HAVE_EXCEPTIONS" = "1" ]; then +- if sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then ++ if sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then + HAVE_PROPERTY=1 +- elif sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then ++ elif sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then + HAVE_PROPERTY=0 + fi + fi +@@ -427,14 +427,14 @@ fi + + if [ "$ENABLE" = 2 ]; then + if [ "$HAVE_DISABLE" = 1 ]; then +- sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE ++ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"/# devnode ".*"/' $TMPFILE + fi + if [ -z "$HAVE_WWID_DISABLE" ]; then + sed -i '/^blacklist[[:space:]]*{/ a\ + wwid ".*" + ' $TMPFILE + elif [ "$HAVE_WWID_DISABLE" = 0 ]; then +- sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"/ wwid ".*"/' $TMPFILE ++ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*wwid[[:space:]][[:space:]]*\"\.\?\*\"/ wwid ".*"/' $TMPFILE + fi + if [ "$HAVE_EXCEPTIONS" = 1 ]; then + sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ {/^[[:space:]]*wwid/ d}' $TMPFILE +@@ -448,7 +448,7 @@ _EOF_ + add_blacklist_exceptions + elif [ "$ENABLE" = 1 ]; then + if [ "$HAVE_DISABLE" = 1 ]; then +- sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE ++ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"/# devnode ".*"/' $TMPFILE + fi + elif [ "$ENABLE" = 0 ]; then + if [ -z "$HAVE_DISABLE" ]; then +@@ -456,7 +456,7 @@ elif [ "$ENABLE" = 0 ]; then + devnode ".*" + ' $TMPFILE + elif [ "$HAVE_DISABLE" = 0 ]; then +- sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"/ devnode ".*"/' $TMPFILE ++ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"/ devnode ".*"/' $TMPFILE + fi + fi + +@@ -467,14 +467,14 @@ if [ -n "$FIND" ]; then + ' $TMPFILE + CHANGED_CONFIG=1 + elif [ "$FIND" != "$HAVE_FIND" ]; then +- sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:blank:]]*find_multipaths[[:blank:]]*[^[:blank:]]*/ find_multipaths '"$FIND"'/' $TMPFILE ++ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:blank:]]*find_multipaths[[:blank:]][[:blank:]]*[^[:blank:]]*/ find_multipaths '"$FIND"'/' $TMPFILE + CHANGED_CONFIG=1 + fi + fi + + if [ "$FRIENDLY" = "n" ]; then + if [ "$HAVE_FRIENDLY" = 1 ]; then +- sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)/ user_friendly_names no/' $TMPFILE ++ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]][[:space:]]*\(yes\|1\)/ user_friendly_names no/' $TMPFILE + CHANGED_CONFIG=1 + fi + elif [ "$FRIENDLY" = "y" ]; then +@@ -484,14 +484,14 @@ elif [ "$FRIENDLY" = "y" ]; then + ' $TMPFILE + CHANGED_CONFIG=1 + elif [ "$HAVE_FRIENDLY" = 0 ]; then +- sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)/ user_friendly_names yes/' $TMPFILE ++ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]][[:space:]]*\(no\|0\)/ user_friendly_names yes/' $TMPFILE + CHANGED_CONFIG=1 + fi + fi + + if [ "$PROPERTY" = "n" ]; then + if [ "$HAVE_PROPERTY" = 1 ]; then +- sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/# property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE ++ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/# property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE + CHANGED_CONFIG=1 + fi + elif [ "$PROPERTY" = "y" ]; then +@@ -501,7 +501,7 @@ elif [ "$PROPERTY" = "y" ]; then + ' $TMPFILE + CHANGED_CONFIG=1 + elif [ "$HAVE_PROPERTY" = 0 ]; then +- sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/ property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE ++ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/ property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE + CHANGED_CONFIG=1 + fi + fi +-- +2.30.2 + diff --git a/SOURCES/0073-multipath.conf-fix-typo-in-checker_timeout-descripti.patch b/SOURCES/0073-multipath.conf-fix-typo-in-checker_timeout-descripti.patch new file mode 100644 index 0000000..849186f --- /dev/null +++ b/SOURCES/0073-multipath.conf-fix-typo-in-checker_timeout-descripti.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 15 Jul 2021 14:48:15 -0500 +Subject: [PATCH] multipath.conf: fix typo in checker_timeout description + +Signed-off-by: Benjamin Marzinski +--- + multipath/multipath.conf.5 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 +index 6da15aad..0c04c7e4 100644 +--- a/multipath/multipath.conf.5 ++++ b/multipath/multipath.conf.5 +@@ -638,7 +638,7 @@ Specify the timeout to use for path checkers and prioritizers, in seconds. + Only prioritizers that issue scsi commands use checker_timeout. Checkers + that support an asynchronous mode (\fItur\fR and \fIdirectio\fR), will + return shortly after being called by multipathd, regardless of whether the +-storage array responds. If the storage array hasn't responded, mulitpathd will ++storage array responds. If the storage array hasn't responded, multipathd will + check for a response every second, until \fIchecker_timeout\fR seconds have + elapsed. + .RS diff --git a/SOURCES/0074-mpathpersist-fail-commands-when-no-usable-paths-exis.patch b/SOURCES/0074-mpathpersist-fail-commands-when-no-usable-paths-exis.patch new file mode 100644 index 0000000..0834837 --- /dev/null +++ b/SOURCES/0074-mpathpersist-fail-commands-when-no-usable-paths-exis.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 22 Jul 2021 17:48:06 -0500 +Subject: [PATCH] mpathpersist: fail commands when no usable paths exist + +"mpathpersist -oCK " will return success if it +is run on devices with no usable paths, but nothing is actually done. +The -L command will fail, but it should give up sooner, and with a more +helpful error message. + +Signed-off-by: Benjamin Marzinski +--- + libmpathpersist/mpath_persist.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c +index 07a5f17f..d0744773 100644 +--- a/libmpathpersist/mpath_persist.c ++++ b/libmpathpersist/mpath_persist.c +@@ -629,7 +629,8 @@ int mpath_prout_common(struct multipath *mpp,int rq_servact, int rq_scope, + return ret ; + } + } +- return MPATH_PR_SUCCESS; ++ condlog (0, "%s: no path available", mpp->wwid); ++ return MPATH_PR_DMMP_ERROR; + } + + int send_prout_activepath(char * dev, int rq_servact, int rq_scope, +@@ -688,6 +689,11 @@ int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope, + + active_pathcount = pathcount (mpp, PATH_UP) + pathcount (mpp, PATH_GHOST); + ++ if (active_pathcount == 0) { ++ condlog (0, "%s: no path available", mpp->wwid); ++ return MPATH_PR_DMMP_ERROR; ++ } ++ + struct threadinfo thread[active_pathcount]; + memset(thread, 0, sizeof(thread)); + for (i = 0; i < active_pathcount; i++){ diff --git a/SOURCES/0075-multipath-print-warning-if-multipathd-is-not-running.patch b/SOURCES/0075-multipath-print-warning-if-multipathd-is-not-running.patch new file mode 100644 index 0000000..3c42a01 --- /dev/null +++ b/SOURCES/0075-multipath-print-warning-if-multipathd-is-not-running.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 16 Jul 2021 12:39:17 -0500 +Subject: [PATCH] multipath: print warning if multipathd is not running. + +If multipath notices that multipath devices exist or were created, and +multipathd is not running, it now prints a warning message, so users are +notified of the issue. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/configure.c | 13 +++++++++++-- + libmultipath/configure.h | 1 + + multipath/main.c | 5 +++++ + 3 files changed, 17 insertions(+), 2 deletions(-) + +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index f24d9283..9c8d3e34 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -1043,7 +1043,8 @@ deadmap (struct multipath * mpp) + return 1; /* dead */ + } + +-int check_daemon(void) ++extern int ++check_daemon(void) + { + int fd; + char *reply; +@@ -1097,6 +1098,8 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, + struct config *conf; + int allow_queueing; + uint64_t *size_mismatch_seen; ++ bool map_processed = false; ++ bool no_daemon = false; + + /* ignore refwwid if it's empty */ + if (refwwid && !strlen(refwwid)) +@@ -1239,7 +1242,9 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, + conf = get_multipath_config(); + allow_queueing = conf->allow_queueing; + put_multipath_config(conf); +- if (!is_daemon && !allow_queueing && !check_daemon()) { ++ if (!is_daemon && !allow_queueing && ++ (no_daemon || !check_daemon())) { ++ no_daemon = true; + if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF && + mpp->no_path_retry != NO_PATH_RETRY_FAIL) + condlog(3, "%s: multipathd not running, unset " +@@ -1267,6 +1272,7 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, + else + remove_map(mpp, vecs, 0); + } ++ map_processed = true; + } + /* + * Flush maps with only dead paths (ie not in sysfs) +@@ -1292,6 +1298,9 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, + condlog(2, "%s: remove (dead)", alias); + } + } ++ if (map_processed && !is_daemon && (no_daemon || !check_daemon())) ++ condlog(2, "multipath devices exist, but multipathd service is not running"); ++ + ret = CP_OK; + out: + free(size_mismatch_seen); +diff --git a/libmultipath/configure.h b/libmultipath/configure.h +index 81090dd4..8a266d31 100644 +--- a/libmultipath/configure.h ++++ b/libmultipath/configure.h +@@ -59,3 +59,4 @@ struct udev_device *get_udev_device(const char *dev, enum devtypes dev_type); + void trigger_paths_udev_change(struct multipath *mpp, bool is_mpath); + void trigger_partitions_udev_change(struct udev_device *dev, const char *action, + int len); ++int check_daemon(void); +diff --git a/multipath/main.c b/multipath/main.c +index 607cada2..14d045c9 100644 +--- a/multipath/main.c ++++ b/multipath/main.c +@@ -254,6 +254,7 @@ get_dm_mpvec (enum mpath_cmds cmd, vector curmp, vector pathvec, char * refwwid) + int i; + struct multipath * mpp; + char params[PARAMS_SIZE], status[PARAMS_SIZE]; ++ bool maps_present = false; + + if (dm_get_maps(curmp)) + return 1; +@@ -302,6 +303,8 @@ get_dm_mpvec (enum mpath_cmds cmd, vector curmp, vector pathvec, char * refwwid) + + if (cmd == CMD_CREATE) + reinstate_paths(mpp); ++ ++ maps_present = true; + } + + if (cmd == CMD_LIST_SHORT || cmd == CMD_LIST_LONG) { +@@ -311,6 +314,8 @@ get_dm_mpvec (enum mpath_cmds cmd, vector curmp, vector pathvec, char * refwwid) + put_multipath_config(conf); + } + ++ if (maps_present && !check_daemon()) ++ condlog(2, "multipath devices exist, but multipathd service is not running"); + return 0; + } + diff --git a/SOURCES/0076-multipathd-don-t-access-path-if-it-was-deleted.patch b/SOURCES/0076-multipathd-don-t-access-path-if-it-was-deleted.patch new file mode 100644 index 0000000..88aa305 --- /dev/null +++ b/SOURCES/0076-multipathd-don-t-access-path-if-it-was-deleted.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 23 Jul 2021 14:10:06 -0500 +Subject: [PATCH] multipathd: don't access path if it was deleted + +ev_remove_path() could fail and still delete the path. This could cause +problems for handle_path_wwid_change(), which expected that a failure +meant that the path still existed. ev_remove_path now returns a +different error code for failure to reload the multipath device, so that +it can be differentiated from cases where the path was no removed. + +Signed-off-by: Benjamin Marzinski +--- + multipathd/main.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index e6c19ab2..823b53a2 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -86,6 +86,9 @@ + #define FILE_NAME_SIZE 256 + #define CMDSIZE 160 + ++#define PATH_REMOVE_FAILED 1 ++#define MAP_RELOAD_FAILED 2 ++ + #define LOG_MSG(lvl, verb, pp) \ + do { \ + if (pp->mpp && checker_selected(&pp->checker) && \ +@@ -840,7 +843,7 @@ handle_path_wwid_change(struct path *pp, struct vectors *vecs) + return; + + udd = udev_device_ref(pp->udev); +- if (ev_remove_path(pp, vecs, 1) != 0 && pp->mpp) { ++ if (ev_remove_path(pp, vecs, 1) == PATH_REMOVE_FAILED && pp->mpp) { + pp->dmstate = PSTATE_FAILED; + dm_fail_path(pp->mpp->alias, pp->dev_t); + } +@@ -1226,13 +1229,13 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map) + condlog(0, "%s: failed in domap for " + "removal of path %s", + mpp->alias, pp->dev); +- retval = 1; ++ retval = MAP_RELOAD_FAILED; + } else { + /* + * update our state from kernel + */ + if (setup_multipath(vecs, mpp)) +- return 1; ++ return PATH_REMOVE_FAILED; + sync_map_state(mpp); + + condlog(2, "%s [%s]: path removed from map %s", +@@ -1250,7 +1253,7 @@ out: + + fail: + remove_map_and_stop_waiter(mpp, vecs); +- return 1; ++ return PATH_REMOVE_FAILED; + } + + static int diff --git a/SPECS/device-mapper-multipath.spec b/SPECS/device-mapper-multipath.spec index 5104f8f..88faf9d 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: 10%{?dist} +Release: 17%{?dist} License: GPLv2 Group: System Environment/Base URL: http://christophe.varoqui.free.fr/ @@ -74,6 +74,19 @@ Patch00060: 0060-kpartx-free-loop-device-after-listing-partitions.patch Patch00061: 0061-RH-fix-find_multipaths-in-mpathconf.patch Patch00062: 0062-libmultipath-select_action-don-t-drop-map-if-alias-c.patch Patch00063: 0063-libmultipath-check-if-user_friendly_name-is-in-use.patch +Patch00064: 0064-libmultipath-check-udev_device_get_-return-value-to-.patch +Patch00065: 0065-libmultipath-cleanup-code-to-strip-wwid-trailing-spa.patch +Patch00066: 0066-multipathd-add-recheck_wwid-option-to-verify-the-pat.patch +Patch00067: 0067-libmultipath-avoid-infinite-loop-with-bad-vpd-page-8.patch +Patch00068: 0068-libmultipath-fix-priorities-in-parse_vpd_pg83.patch +Patch00069: 0069-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +Patch00070: 0070-multipathd-improve-getting-parent-udevice-in-rescan_.patch +Patch00071: 0071-multipathd-don-t-trigger-uevent-for-partitions-on-ww.patch +Patch00072: 0072-RH-mpathconf-correctly-handle-spaces-after-option-na.patch +Patch00073: 0073-multipath.conf-fix-typo-in-checker_timeout-descripti.patch +Patch00074: 0074-mpathpersist-fail-commands-when-no-usable-paths-exis.patch +Patch00075: 0075-multipath-print-warning-if-multipathd-is-not-running.patch +Patch00076: 0076-multipathd-don-t-access-path-if-it-was-deleted.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -275,14 +288,53 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog -* Sun Mar 7 2021 Benjamin Marzinski 0.8.4-10 +* Fri Jul 23 2021 Benjamin Marzinski 0.8.4-17 +- Add 0074-mpathpersist-fail-commands-when-no-usable-paths-exis.patch + * Fixes bz #1984723 +- Add 0075-multipath-print-warning-if-multipathd-is-not-running.patch + * Fixes bz #1973592 +- Add 0076-multipathd-don-t-access-path-if-it-was-deleted.patch + * Found by coverity +- Resolves: bz #1973592, #1984723 + +* Thu Jul 22 2021 Benjamin Marzinski 0.8.4-16 +- Add missing patch +- Related: bz #1982598 + +* Thu Jul 22 2021 Benjamin Marzinski 0.8.4-15 +- Add 0073-multipath.conf-fix-typo-in-checker_timeout-descripti.patch +- Resolves: bz #1982598 + +* Mon Jul 12 2021 Benjamin Marzinski 0.8.4-14 +- Add 0072-RH-mpathconf-correctly-handle-spaces-after-option-na.patch +- Resolves: bz #1979470 + +* Wed Apr 28 2021 Benjamin Marzinski 0.8.4-13 +- Add 0065-libmultipath-cleanup-code-to-strip-wwid-trailing-spa.patch +- Add 0066-multipathd-add-recheck_wwid-option-to-verify-the-pat.patch +- Add 0067-libmultipath-avoid-infinite-loop-with-bad-vpd-page-8.patch +- Add 0068-libmultipath-fix-priorities-in-parse_vpd_pg83.patch +- Add 0069-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +- Add 0070-multipathd-improve-getting-parent-udevice-in-rescan_.patch +- Add 0071-multipathd-don-t-trigger-uevent-for-partitions-on-ww.patch + * add recheck_wwid option + * Fixes bz #1907904 +- Resolves: bz #1907904 + +* Wed Apr 21 2021 Benjamin Marzinski 0.8.4-12 +- Add 0064-libmultipath-check-udev_device_get_-return-value-to-.patch + * Fixes bz #1946940 +- Resolves: bz #1946940 + +* Fri Mar 12 2021 Benjamin Marzinski 0.8.4-11 - Add 0062-libmultipath-select_action-don-t-drop-map-if-alias-c.patch * Fall back to WWID names instead of removing existing device - Add 0063-libmultipath-check-if-user_friendly_name-is-in-use.patch * make sure to choose a user_friendly_name that isn't in use - * Fixes bz #1923777 + * Fixes bz #1937832 - Add alias_clash CI test -- Resolves: bz #1923777 +- Remove unused multipath.conf +- Resolves: bz #1937832 * Wed Feb 10 2021 Benjamin Marzinski 0.8.4-9 - Add 0060-kpartx-free-loop-device-after-listing-partitions.patch @@ -561,7 +613,7 @@ fi * mpathpersist now accepts --param-alltgpt - Add 0005-libmutipath-remove-unused-IDE-bus-type.patch - Add 0006-multipathd-add-new-protocol-path-wildcard.patch - * multipathd show paths format now accepts %P for the path protocol/transport + * multipathd show paths format now accepts %%P for the path protocol/transport - Add 0007-libmultipath-add-protocol-blacklist-option.patch * You can now use the "protocol" blacklist section parameter to blacklist by protocol/transport