203 lines
6.5 KiB
Diff
203 lines
6.5 KiB
Diff
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||
|
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 <bmarzins@redhat.com>
|
||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||
|
---
|
||
|
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 <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 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);
|