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 <bmarzins@xxxxxxxxxx> --- libmultipath/config.h | 1 + libmultipath/defaults.h | 1 + libmultipath/dict.c | 38 +++++++++++++++++++++++++++++++++++ libmultipath/dict.h | 1 + libmultipath/structs.h | 7 +++++++ multipath/multipath.conf.5.in | 15 ++++++++++++++ multipathd/main.c | 28 ++++++++++++++++++++++++++ 7 files changed, 91 insertions(+) diff --git a/libmultipath/config.h b/libmultipath/config.h index 417e5834..384193ab 100644 --- a/libmultipath/config.h +++ b/libmultipath/config.h @@ -202,6 +202,7 @@ struct config { int skip_delegate; unsigned int sequence_nr; int recheck_wwid; + int auto_resize; char * selector; struct _vector uid_attrs; diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h index d01f9712..64b633f2 100644 --- a/libmultipath/defaults.h +++ b/libmultipath/defaults.h @@ -56,6 +56,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 e268673f..0a160e92 100644 --- a/libmultipath/dict.c +++ b/libmultipath/dict.c @@ -1664,6 +1664,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) @@ -2140,6 +2177,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 15d9cbac..7e2dfbe0 100644 --- a/libmultipath/dict.h +++ b/libmultipath/dict.h @@ -17,4 +17,5 @@ int print_no_path_retry(struct strbuf *buff, long v); int print_undef_off_zero(struct strbuf *buff, long v); int print_dev_loss(struct strbuf *buff, unsigned long v); 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 63551b80..a1aac1b4 100644 --- a/libmultipath/structs.h +++ b/libmultipath/structs.h @@ -179,6 +179,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.in b/multipath/multipath.conf.5.in index 014d6dd1..eddef0f7 100644 --- a/multipath/multipath.conf.5.in +++ b/multipath/multipath.conf.5.in @@ -1331,6 +1331,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 <name>\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 3b4c5b09..230c9d10 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -1590,6 +1590,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; @@ -1648,6 +1653,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); -- 2.41.0