From 88821a8d1175256f79f2fa20791712dc86b6815b Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Mon, 20 Nov 2023 15:07:49 -0500 Subject: [PATCH] device-mapper-multipath-0.8.7-25 Add 0094-libmultipath-Add-max_retries-config-option.patch * Fixes RHEL-1729 ("Allow multipathd to set the max_retries of the scsi_device for paths") Add 0095-libmutipath-Retain-device-size-if-sysfs_get_size-fai.patch Add 0096-multipathd-check-and-update-all-paths-when-in-cli_re.patch Add 0097-multipathd-move-post-reloading-commands-into-resize_.patch Add 0098-multipathd-move-resize_map-to-multipathd-main.c.patch Add 0099-multipathd-Add-auto_resize-config-option.patch * Fixes RHEL-986 ("Add option to allow multipathd to detect device resizes and autoresize.") Resolves: RHEL-986 Resolves: RHEL-1729 --- ...tipath-Add-max_retries-config-option.patch | 182 ++++++++++++++++ ...in-device-size-if-sysfs_get_size-fai.patch | 29 +++ ...-and-update-all-paths-when-in-cli_re.patch | 68 ++++++ ...post-reloading-commands-into-resize_.patch | 58 +++++ ...move-resize_map-to-multipathd-main.c.patch | 106 +++++++++ ...ipathd-Add-auto_resize-config-option.patch | 202 ++++++++++++++++++ device-mapper-multipath.spec | 22 +- 7 files changed, 666 insertions(+), 1 deletion(-) create mode 100644 0094-libmultipath-Add-max_retries-config-option.patch create mode 100644 0095-libmutipath-Retain-device-size-if-sysfs_get_size-fai.patch create mode 100644 0096-multipathd-check-and-update-all-paths-when-in-cli_re.patch create mode 100644 0097-multipathd-move-post-reloading-commands-into-resize_.patch create mode 100644 0098-multipathd-move-resize_map-to-multipathd-main.c.patch create mode 100644 0099-multipathd-Add-auto_resize-config-option.patch diff --git a/0094-libmultipath-Add-max_retries-config-option.patch b/0094-libmultipath-Add-max_retries-config-option.patch new file mode 100644 index 0000000..9d52675 --- /dev/null +++ b/0094-libmultipath-Add-max_retries-config-option.patch @@ -0,0 +1,182 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 9 Nov 2023 18:46:11 -0500 +Subject: [PATCH] libmultipath: Add max_retries config option + +This option lets multipath set a scsi disk's max_retries sysfs value. +Setting this can be helpful for cases where the path checker succeeds, +but IO commands hang and timeout. By default, the SCSI layer will retry +IOs 5 times. Reducing this value will allow multipath to retry the IO +down another path sooner. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + libmultipath/config.h | 1 + + libmultipath/dict.c | 25 ++++++++++++++++++++++++ + libmultipath/discovery.c | 40 +++++++++++++++++++++++++++++++++++++- + libmultipath/structs.h | 6 ++++++ + multipath/multipath.conf.5 | 14 +++++++++++++ + 5 files changed, 85 insertions(+), 1 deletion(-) + +diff --git a/libmultipath/config.h b/libmultipath/config.h +index c1e18363..b0ee8241 100644 +--- a/libmultipath/config.h ++++ b/libmultipath/config.h +@@ -162,6 +162,7 @@ struct config { + int fast_io_fail; + unsigned int dev_loss; + int eh_deadline; ++ int max_retries; + int log_checker_err; + int allow_queueing; + int allow_usb_devices; +diff --git a/libmultipath/dict.c b/libmultipath/dict.c +index eb2f33a2..0c66c1e1 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -1206,6 +1206,30 @@ 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 ++def_max_retries_handler(struct config *conf, vector strvec, const char *file, ++ int line_nr) ++{ ++ char * buff; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ if (strcmp(buff, "off") == 0) ++ conf->max_retries = MAX_RETRIES_OFF; ++ else if (strcmp(buff, "0") == 0) ++ conf->max_retries = MAX_RETRIES_ZERO; ++ else ++ do_set_int(strvec, &conf->max_retries, 1, 5, file, line_nr, ++ buff); ++ ++ free(buff); ++ return 0; ++} ++ ++declare_def_snprint(max_retries, print_undef_off_zero) ++ + static int + set_pgpolicy(vector strvec, void *ptr, const char *file, int line_nr) + { +@@ -2143,6 +2167,7 @@ init_keywords(vector keywords) + install_keyword("fast_io_fail_tmo", &def_fast_io_fail_handler, &snprint_def_fast_io_fail); + install_keyword("dev_loss_tmo", &def_dev_loss_handler, &snprint_def_dev_loss); + install_keyword("eh_deadline", &def_eh_deadline_handler, &snprint_def_eh_deadline); ++ install_keyword("max_retries", &def_max_retries_handler, &snprint_def_max_retries); + install_keyword("bindings_file", &def_bindings_file_handler, &snprint_def_bindings_file); + install_keyword("wwids_file", &def_wwids_file_handler, &snprint_def_wwids_file); + install_keyword("prkeys_file", &def_prkeys_file_handler, &snprint_def_prkeys_file); +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index a592a54e..adf8bbaa 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -632,6 +632,42 @@ sysfs_set_eh_deadline(struct path *pp) + return (ret <= 0); + } + ++static int ++sysfs_set_max_retries(struct config *conf, struct path *pp) ++{ ++ struct udev_device *parent; ++ char value[16]; ++ STRBUF_ON_STACK(buf); ++ int ret, len; ++ ++ if (conf->max_retries == MAX_RETRIES_UNSET) ++ return 0; ++ ++ if (!pp->udev || pp->sg_id.host_no < 0) ++ return 1; ++ ++ len = sprintf(value, "%d", (conf->max_retries == MAX_RETRIES_OFF)? -1 : ++ (conf->max_retries == MAX_RETRIES_ZERO)? 0 : ++ conf->max_retries); ++ ++ parent = udev_device_get_parent_with_subsystem_devtype(pp->udev, ++ "scsi", "scsi_device"); ++ if (!parent) ++ return 1; ++ ++ if (print_strbuf(&buf, "scsi_disk/%i:%i:%i:%" PRIu64 "/max_retries", ++ pp->sg_id.host_no, pp->sg_id.channel, ++ pp->sg_id.scsi_id, pp->sg_id.lun) < 0) ++ return 1; ++ ++ ret = sysfs_attr_set_value(parent, get_strbuf_str(&buf), value, len); ++ if (len != ret) ++ condlog(3, "%s/%s: failed to set value to %s: %s", ++ udev_device_get_sysname(parent), get_strbuf_str(&buf), ++ value, (ret < 0)? strerror(-ret) : "write underflow"); ++ return (len != ret); ++} ++ + static void + sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp) + { +@@ -862,13 +898,15 @@ sysfs_set_scsi_tmo (struct config *conf, struct multipath *mpp) + + if (pp->dev_loss == DEV_LOSS_TMO_UNSET && + pp->fast_io_fail == MP_FAST_IO_FAIL_UNSET && +- pp->eh_deadline == EH_DEADLINE_UNSET) ++ pp->eh_deadline == EH_DEADLINE_UNSET && ++ conf->max_retries == MAX_RETRIES_UNSET) + continue; + + if (pp->bus != SYSFS_BUS_SCSI) + continue; + + sysfs_set_eh_deadline(pp); ++ sysfs_set_max_retries(conf, pp); + + if (pp->dev_loss == DEV_LOSS_TMO_UNSET && + pp->fast_io_fail == MP_FAST_IO_FAIL_UNSET) +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index c1e93e6e..b4252ab5 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -276,6 +276,12 @@ enum eh_deadline_states { + EH_DEADLINE_ZERO = UOZ_ZERO, + }; + ++enum max_retries_states { ++ MAX_RETRIES_UNSET = UOZ_UNDEF, ++ MAX_RETRIES_OFF = UOZ_OFF, ++ MAX_RETRIES_ZERO = UOZ_ZERO, ++}; ++ + enum recheck_wwid_states { + RECHECK_WWID_UNDEF = YNU_UNDEF, + RECHECK_WWID_OFF = YNU_NO, +diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 +index 5e447e67..789f0bfc 100644 +--- a/multipath/multipath.conf.5 ++++ b/multipath/multipath.conf.5 +@@ -743,6 +743,20 @@ The default is: \fB\fR + . + . + .TP ++.B max_retries ++Specify the maximum number of times the SCSI layer will retry IO commands for ++some types of SCSI errors before returning failure. Setting this can be helpful ++for cases where IO commands hang and timeout. By default, the SCSI layer will ++retry IOs 5 times. Reducing this value will allow multipath to retry the IO ++down another path sooner. Valid values are ++\fB0\fR through \fB5\fR. ++.RS ++.TP ++The default is: \fB\fR ++.RE ++. ++. ++.TP + .B bindings_file + This option is deprecated, and will be removed in a future release. + The full pathname of the binding file to be used when the user_friendly_names diff --git a/0095-libmutipath-Retain-device-size-if-sysfs_get_size-fai.patch b/0095-libmutipath-Retain-device-size-if-sysfs_get_size-fai.patch new file mode 100644 index 0000000..32eab9a --- /dev/null +++ b/0095-libmutipath-Retain-device-size-if-sysfs_get_size-fai.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 9 Nov 2023 18:46:12 -0500 +Subject: [PATCH] libmutipath: Retain device size if sysfs_get_size fails. + +When paths are allocated their size is initialized to 0. If they've +already set a size, and a future call to sysfs_get_size() fails during +the parsing, assume that the size hasn't changed, instead of setting it +to 0. All other failures in sysfs_get_size() already retain the existing +size. + +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/sysfs.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c +index 24c12b6a..41354f91 100644 +--- a/libmultipath/sysfs.c ++++ b/libmultipath/sysfs.c +@@ -229,7 +229,6 @@ sysfs_get_size (struct path *pp, unsigned long long * size) + + if (r != 1) { + condlog(3, "%s: Cannot parse size attribute", pp->dev); +- *size = 0; + return 1; + } + diff --git a/0096-multipathd-check-and-update-all-paths-when-in-cli_re.patch b/0096-multipathd-check-and-update-all-paths-when-in-cli_re.patch new file mode 100644 index 0000000..114c1a5 --- /dev/null +++ b/0096-multipathd-check-and-update-all-paths-when-in-cli_re.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 9 Nov 2023 18:46:13 -0500 +Subject: [PATCH] multipathd: check and update all paths when in cli_resize + +When resizing a multipath device, make sure that all the paths have +been updated to the new size first. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + multipathd/cli_handlers.c | 31 ++++++++++++++++++------------- + 1 file changed, 18 insertions(+), 13 deletions(-) + +diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c +index f322f10f..93c32c5b 100644 +--- a/multipathd/cli_handlers.c ++++ b/multipathd/cli_handlers.c +@@ -866,9 +866,11 @@ cli_resize(void *v, char **reply, int *len, void *data) + char * mapname = get_keyparam(v, MAP); + struct multipath *mpp; + int minor; +- unsigned long long size; ++ unsigned long long size = 0; + struct pathgroup *pgp; + struct path *pp; ++ unsigned int i, j; ++ bool mismatch = false; + + mapname = convert_dev(mapname, 0); + condlog(2, "%s: resize map (operator)", mapname); +@@ -888,21 +890,24 @@ cli_resize(void *v, char **reply, int *len, void *data) + return 1; + } + +- pgp = VECTOR_SLOT(mpp->pg, 0); +- +- if (!pgp){ +- condlog(0, "%s: couldn't get path group. cannot resize", +- mapname); +- return 1; ++ vector_foreach_slot(mpp->pg, pgp, i) { ++ vector_foreach_slot (pgp->paths, pp, j) { ++ sysfs_get_size(pp, &pp->size); ++ if (!pp->size) ++ continue; ++ if (!size) ++ size = pp->size; ++ else if (pp->size != size) ++ mismatch = true; ++ } + } +- pp = VECTOR_SLOT(pgp->paths, 0); +- +- if (!pp){ +- condlog(0, "%s: couldn't get path. cannot resize", mapname); ++ if (!size) { ++ condlog(0, "%s: couldn't get size from sysfs. cannot resize", ++ mapname); + return 1; + } +- if (!pp->udev || sysfs_get_size(pp, &size)) { +- condlog(0, "%s: couldn't get size for sysfs. cannot resize", ++ if (mismatch) { ++ condlog(0, "%s: path size not consistent. cannot resize", + mapname); + return 1; + } diff --git a/0097-multipathd-move-post-reloading-commands-into-resize_.patch b/0097-multipathd-move-post-reloading-commands-into-resize_.patch new file mode 100644 index 0000000..1feb11d --- /dev/null +++ b/0097-multipathd-move-post-reloading-commands-into-resize_.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 9 Nov 2023 18:46:14 -0500 +Subject: [PATCH] multipathd: move post-reloading commands into resize_map() + +In preparation for reusing resize_map() in other code, move all code +necessary to resize the map to the resize_map() function. Also track if +map was removed in the function. + +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + multipathd/cli_handlers.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c +index 93c32c5b..b08b248f 100644 +--- a/multipathd/cli_handlers.c ++++ b/multipathd/cli_handlers.c +@@ -856,6 +856,10 @@ int resize_map(struct multipath *mpp, unsigned long long size, + mpp->size = orig_size; + return 1; + } ++ if (setup_multipath(vecs, mpp) != 0) ++ return 2; ++ sync_map_state(mpp); ++ + return 0; + } + +@@ -869,7 +873,7 @@ cli_resize(void *v, char **reply, int *len, void *data) + unsigned long long size = 0; + struct pathgroup *pgp; + struct path *pp; +- unsigned int i, j; ++ unsigned int i, j, ret; + bool mismatch = false; + + mapname = convert_dev(mapname, 0); +@@ -919,14 +923,12 @@ cli_resize(void *v, char **reply, int *len, void *data) + condlog(3, "%s old size is %llu, new size is %llu", mapname, mpp->size, + size); + +- if (resize_map(mpp, size, vecs) != 0) +- return 1; ++ ret = resize_map(mpp, size, vecs); + +- if (setup_multipath(vecs, mpp) != 0) +- return 1; +- sync_map_state(mpp); ++ if (ret == 2) ++ condlog(0, "%s: map removed while trying to resize", mapname); + +- return 0; ++ return (ret != 0); + } + + int diff --git a/0098-multipathd-move-resize_map-to-multipathd-main.c.patch b/0098-multipathd-move-resize_map-to-multipathd-main.c.patch new file mode 100644 index 0000000..2be9228 --- /dev/null +++ b/0098-multipathd-move-resize_map-to-multipathd-main.c.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 10 Nov 2023 17:59:42 -0500 +Subject: [PATCH] multipathd: move resize_map() to multipathd/main.c + +No functional changes. + +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + multipathd/cli_handlers.c | 29 ----------------------------- + multipathd/main.c | 29 +++++++++++++++++++++++++++++ + multipathd/main.h | 2 ++ + 3 files changed, 31 insertions(+), 29 deletions(-) + +diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c +index b08b248f..53bebc8d 100644 +--- a/multipathd/cli_handlers.c ++++ b/multipathd/cli_handlers.c +@@ -834,35 +834,6 @@ cli_reload(void *v, char **reply, int *len, void *data) + return reload_and_sync_map(mpp, vecs, 0); + } + +-int resize_map(struct multipath *mpp, unsigned long long size, +- struct vectors * vecs) +-{ +- char *params __attribute__((cleanup(cleanup_charp))) = NULL; +- unsigned long long orig_size = mpp->size; +- +- mpp->size = size; +- update_mpp_paths(mpp, vecs->pathvec); +- if (setup_map(mpp, ¶ms, vecs) != 0) { +- condlog(0, "%s: failed to setup map for resize : %s", +- mpp->alias, strerror(errno)); +- mpp->size = orig_size; +- return 1; +- } +- mpp->action = ACT_RESIZE; +- mpp->force_udev_reload = 1; +- if (domap(mpp, params, 1) == DOMAP_FAIL) { +- condlog(0, "%s: failed to resize map : %s", mpp->alias, +- strerror(errno)); +- mpp->size = orig_size; +- return 1; +- } +- if (setup_multipath(vecs, mpp) != 0) +- return 2; +- sync_map_state(mpp); +- +- return 0; +-} +- + int + cli_resize(void *v, char **reply, int *len, void *data) + { +diff --git a/multipathd/main.c b/multipathd/main.c +index 075e7b13..d99cad72 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -1379,6 +1379,35 @@ needs_ro_update(struct multipath *mpp, int ro) + return true; + } + ++int resize_map(struct multipath *mpp, unsigned long long size, ++ struct vectors * vecs) ++{ ++ char *params __attribute__((cleanup(cleanup_charp))) = NULL; ++ unsigned long long orig_size = mpp->size; ++ ++ mpp->size = size; ++ update_mpp_paths(mpp, vecs->pathvec); ++ if (setup_map(mpp, ¶ms, vecs) != 0) { ++ condlog(0, "%s: failed to setup map for resize : %s", ++ mpp->alias, strerror(errno)); ++ mpp->size = orig_size; ++ return 1; ++ } ++ mpp->action = ACT_RESIZE; ++ mpp->force_udev_reload = 1; ++ if (domap(mpp, params, 1) == DOMAP_FAIL) { ++ condlog(0, "%s: failed to resize map : %s", mpp->alias, ++ strerror(errno)); ++ mpp->size = orig_size; ++ return 1; ++ } ++ if (setup_multipath(vecs, mpp) != 0) ++ return 2; ++ sync_map_state(mpp); ++ ++ return 0; ++} ++ + static int + uev_update_path (struct uevent *uev, struct vectors * vecs) + { +diff --git a/multipathd/main.h b/multipathd/main.h +index bc1f938f..dbae4935 100644 +--- a/multipathd/main.h ++++ b/multipathd/main.h +@@ -66,4 +66,6 @@ int reload_and_sync_map(struct multipath *mpp, struct vectors *vecs, + + void handle_path_wwid_change(struct path *pp, struct vectors *vecs); + bool check_path_wwid_change(struct path *pp); ++int resize_map(struct multipath *mpp, unsigned long long size, ++ struct vectors *vecs); + #endif /* MAIN_H */ diff --git a/0099-multipathd-Add-auto_resize-config-option.patch b/0099-multipathd-Add-auto_resize-config-option.patch new file mode 100644 index 0000000..9da16f5 --- /dev/null +++ b/0099-multipathd-Add-auto_resize-config-option.patch @@ -0,0 +1,202 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 9 Nov 2023 18:46:16 -0500 +Subject: [PATCH] multipathd: Add auto_resize config option + +This option gives multipathd the ability to automatically resize a +device when it detects that all of the path devices have changed. By +default it is set to never, and multipathd will continue to work like it +always has, where a users must manually resize a multipath device. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + libmultipath/config.h | 1 + + libmultipath/defaults.h | 1 + + libmultipath/dict.c | 38 ++++++++++++++++++++++++++++++++++++++ + libmultipath/dict.h | 1 + + libmultipath/structs.h | 7 +++++++ + multipath/multipath.conf.5 | 15 +++++++++++++++ + multipathd/main.c | 28 ++++++++++++++++++++++++++++ + 7 files changed, 91 insertions(+) + +diff --git a/libmultipath/config.h b/libmultipath/config.h +index b0ee8241..5807ac68 100644 +--- a/libmultipath/config.h ++++ b/libmultipath/config.h +@@ -201,6 +201,7 @@ struct config { + int skip_delegate; + unsigned int sequence_nr; + int recheck_wwid; ++ int auto_resize; + + char * multipath_dir; + char * selector; +diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h +index cec82f07..c3788bbc 100644 +--- a/libmultipath/defaults.h ++++ b/libmultipath/defaults.h +@@ -54,6 +54,7 @@ + #define DEFAULT_UNKNOWN_FIND_MULTIPATHS_TIMEOUT 1 + #define DEFAULT_ALL_TG_PT ALL_TG_PT_OFF + #define DEFAULT_RECHECK_WWID RECHECK_WWID_OFF ++#define DEFAULT_AUTO_RESIZE AUTO_RESIZE_NEVER + /* Enable no foreign libraries by default */ + #define DEFAULT_ENABLE_FOREIGN "NONE" + +diff --git a/libmultipath/dict.c b/libmultipath/dict.c +index 0c66c1e1..c4db60df 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -1736,6 +1736,43 @@ declare_hw_snprint(recheck_wwid, print_yes_no_undef) + + declare_def_range_handler(uxsock_timeout, DEFAULT_REPLY_TIMEOUT, INT_MAX) + ++static int ++def_auto_resize_handler(struct config *conf, vector strvec, const char *file, ++ int line_nr) ++{ ++ char * buff; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ if (strcmp(buff, "never") == 0) ++ conf->auto_resize = AUTO_RESIZE_NEVER; ++ else if (strcmp(buff, "grow_only") == 0) ++ conf->auto_resize = AUTO_RESIZE_GROW_ONLY; ++ else if (strcmp(buff, "grow_shrink") == 0) ++ conf->auto_resize = AUTO_RESIZE_GROW_SHRINK; ++ else ++ condlog(1, "%s line %d, invalid value for auto_resize: \"%s\"", ++ file, line_nr, buff); ++ ++ free(buff); ++ return 0; ++} ++ ++int ++print_auto_resize(struct strbuf *buff, long v) ++{ ++ if (!v) ++ return 0; ++ return append_strbuf_quoted(buff, ++ v == AUTO_RESIZE_GROW_ONLY ? "grow_only" : ++ v == AUTO_RESIZE_GROW_SHRINK ? "grow_shrink" : ++ "never"); ++} ++ ++declare_def_snprint(auto_resize, print_auto_resize) ++ + static int + hw_vpd_vendor_handler(struct config *conf, vector strvec, const char *file, + int line_nr) +@@ -2202,6 +2239,7 @@ init_keywords(vector keywords) + install_keyword("remove_retries", &def_remove_retries_handler, &snprint_def_remove_retries); + install_keyword("max_sectors_kb", &def_max_sectors_kb_handler, &snprint_def_max_sectors_kb); + install_keyword("ghost_delay", &def_ghost_delay_handler, &snprint_def_ghost_delay); ++ install_keyword("auto_resize", &def_auto_resize_handler, &snprint_def_auto_resize); + install_keyword("find_multipaths_timeout", + &def_find_multipaths_timeout_handler, + &snprint_def_find_multipaths_timeout); +diff --git a/libmultipath/dict.h b/libmultipath/dict.h +index d80f990a..d963b4ad 100644 +--- a/libmultipath/dict.h ++++ b/libmultipath/dict.h +@@ -19,4 +19,5 @@ int print_dev_loss(struct strbuf *buff, unsigned long v); + int print_reservation_key(struct strbuf *buff, + struct be64 key, uint8_t flags, int source); + int print_off_int_undef(struct strbuf *buff, long v); ++int print_auto_resize(struct strbuf *buff, long v); + #endif /* _DICT_H */ +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index b4252ab5..8c2d7131 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -167,6 +167,13 @@ enum queue_mode_states { + QUEUE_MODE_RQ, + }; + ++enum auto_resize_state { ++ AUTO_RESIZE_UNDEF = 0, ++ AUTO_RESIZE_NEVER, ++ AUTO_RESIZE_GROW_ONLY, ++ AUTO_RESIZE_GROW_SHRINK, ++}; ++ + #define PROTOCOL_UNSET -1 + + enum scsi_protocol { +diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 +index 789f0bfc..38eb5c90 100644 +--- a/multipath/multipath.conf.5 ++++ b/multipath/multipath.conf.5 +@@ -1293,6 +1293,21 @@ The default is: \fBno\fR + . + . + .TP ++.B auto_resize ++Controls when multipathd will automatically resize a multipath device. If set ++to \fInever\fR, multipath devices must always be manually resized by either ++running \fBmultipathd resize map \fR. If set to \fIgrow_only\fR, when ++multipathd detects that all of a multipath device's paths have increased in ++size, it will automatically grow the multipath device to the new size. If set ++to \fIgrow_shrink\fR, multipathd will also automatically shrink the device ++once it detects all of its paths have decreased in size. ++.RS ++.TP ++The default is: \fBnever\fR ++.RE ++. ++. ++.TP + .B enable_foreign + Enables or disables foreign libraries (see section + .I FOREIGN MULTIPATH SUPPORT +diff --git a/multipathd/main.c b/multipathd/main.c +index d99cad72..6d1a5e4e 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -1439,6 +1439,11 @@ uev_update_path (struct uevent *uev, struct vectors * vecs) + if (pp) { + struct multipath *mpp = pp->mpp; + char wwid[WWID_SIZE]; ++ int auto_resize; ++ ++ conf = get_multipath_config(); ++ auto_resize = conf->auto_resize; ++ put_multipath_config(conf); + + if (pp->initialized == INIT_REQUESTED_UDEV) { + needs_reinit = 1; +@@ -1489,6 +1494,29 @@ uev_update_path (struct uevent *uev, struct vectors * vecs) + } + } + } ++ if (auto_resize != AUTO_RESIZE_NEVER && ++ !mpp->wait_for_udev) { ++ struct pathgroup *pgp; ++ struct path *pp2; ++ unsigned int i, j; ++ unsigned long long orig_size = mpp->size; ++ ++ if (!pp->size || pp->size == mpp->size || ++ (pp->size < mpp->size && ++ auto_resize == AUTO_RESIZE_GROW_ONLY)) ++ goto out; ++ ++ vector_foreach_slot(mpp->pg, pgp, i) ++ vector_foreach_slot (pgp->paths, pp2, j) ++ if (pp2->size && pp2->size != pp->size) ++ goto out; ++ retval = resize_map(mpp, pp->size, vecs); ++ if (retval == 2) ++ condlog(2, "%s: map removed during resize", pp->dev); ++ else if (retval == 0) ++ condlog(2, "%s: resized map from %llu to %llu", ++ mpp->alias, orig_size, pp->size); ++ } + } + out: + lock_cleanup_pop(vecs->lock); diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index d78931a..ed73eb1 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.8.7 -Release: 24%{?dist} +Release: 25%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ @@ -103,6 +103,12 @@ Patch0090: 0090-RH-make-listing-return-an-error-if-the-config-file-i.patch Patch0091: 0091-multipathd-Added-support-to-handle-FPIN-Li-events-fo.patch Patch0092: 0092-multipath-tools-add-HPE-Alletra-9000-NVMe-to-hardwar.patch Patch0093: 0093-RH-multipath-add-mpathcleanup-man-page.patch +Patch0094: 0094-libmultipath-Add-max_retries-config-option.patch +Patch0095: 0095-libmutipath-Retain-device-size-if-sysfs_get_size-fai.patch +Patch0096: 0096-multipathd-check-and-update-all-paths-when-in-cli_re.patch +Patch0097: 0097-multipathd-move-post-reloading-commands-into-resize_.patch +Patch0098: 0098-multipathd-move-resize_map-to-multipathd-main.c.patch +Patch0099: 0099-multipathd-Add-auto_resize-config-option.patch # runtime @@ -306,6 +312,20 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Mon Nov 20 2023 Benjamin Marzinski - 0.8.7-25 +- Add 0094-libmultipath-Add-max_retries-config-option.patch + * Fixes RHEL-1729 ("Allow multipathd to set the max_retries of the + scsi_device for paths") +- Add 0095-libmutipath-Retain-device-size-if-sysfs_get_size-fai.patch +- Add 0096-multipathd-check-and-update-all-paths-when-in-cli_re.patch +- Add 0097-multipathd-move-post-reloading-commands-into-resize_.patch +- Add 0098-multipathd-move-resize_map-to-multipathd-main.c.patch +- Add 0099-multipathd-Add-auto_resize-config-option.patch + * Fixes RHEL-986 ("Add option to allow multipathd to detect device + resizes and autoresize.") +- Resolves: RHEL-986 +- Resolves: RHEL-1729 + * Fri Nov 3 2023 Benjamin Marzinski - 0.8.7-24 - Add 0093-RH-multipath-add-mpathcleanup-man-page.patch * Fixes RHEL-1266 ("There is no man page for mpathcleanup")