Add 0142-multipathd-monitor-new-multipath-dev-even-if-we-can-.patch Add 0143-libmultipath-add-helper-function-check_path_wwid_cha.patch Add 0144-multipathd-re-add-paths-skipped-because-they-were-of.patch * Fixes RHEL-82534 ("multipathd does not monitor multipath devices created externally while there are offline paths.") Resolves: RHEL-82534
202 lines
6.3 KiB
Diff
202 lines
6.3 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
|
Date: Wed, 2 Apr 2025 19:13:21 -0400
|
|
Subject: [PATCH] multipathd: re-add paths skipped because they were offline
|
|
|
|
When a new device is added by the multipath command, multipathd may know
|
|
of other paths that cannot be added to the device because they are
|
|
currently offline. Instead of ignoring these paths, multipathd will now
|
|
re-add them when they come back online. To do this, it multipathd needs
|
|
a new path variable add_when_online, to track devices that could not be
|
|
added to an existing multipath device because they were offline. These
|
|
paths are handled along with the other uninitialized paths.
|
|
|
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
|
---
|
|
libmultipath/libmultipath.version | 5 +++
|
|
libmultipath/print.c | 5 ++-
|
|
libmultipath/structs.h | 1 +
|
|
libmultipath/structs_vec.c | 5 +++
|
|
multipathd/main.c | 53 ++++++++++++++++++++++++++++++-
|
|
multipathd/multipathd.8 | 4 ++-
|
|
6 files changed, 70 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
|
|
index e2cce8c7..46907278 100644
|
|
--- a/libmultipath/libmultipath.version
|
|
+++ b/libmultipath/libmultipath.version
|
|
@@ -313,3 +313,8 @@ global:
|
|
cleanup_udev_enumerate_ptr;
|
|
cleanup_udev_device_ptr;
|
|
} LIBMULTIPATH_9.1.3;
|
|
+
|
|
+LIBMULTIPATH_9.1.5 {
|
|
+global:
|
|
+ can_recheck_wwid;
|
|
+} LIBMULTIPATH_9.1.4;
|
|
diff --git a/libmultipath/print.c b/libmultipath/print.c
|
|
index 4552fd43..ff224bc4 100644
|
|
--- a/libmultipath/print.c
|
|
+++ b/libmultipath/print.c
|
|
@@ -584,8 +584,11 @@ snprint_path_serial (struct strbuf *buff, const struct path * pp)
|
|
static int
|
|
snprint_path_mpp (struct strbuf *buff, const struct path * pp)
|
|
{
|
|
- if (!pp->mpp)
|
|
+ if (!pp->mpp) {
|
|
+ if (pp->add_when_online)
|
|
+ return append_strbuf_str(buff, "[offline]");
|
|
return append_strbuf_str(buff, "[orphan]");
|
|
+ }
|
|
if (!pp->mpp->alias)
|
|
return append_strbuf_str(buff, "[unknown]");
|
|
return snprint_str(buff, pp->mpp->alias);
|
|
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
|
index 4bf8c93a..0846e833 100644
|
|
--- a/libmultipath/structs.h
|
|
+++ b/libmultipath/structs.h
|
|
@@ -374,6 +374,7 @@ struct path {
|
|
unsigned int dev_loss;
|
|
int eh_deadline;
|
|
bool can_use_env_uid;
|
|
+ bool add_when_online;
|
|
/* configlet pointers */
|
|
vector hwe;
|
|
struct gen_path generic_path;
|
|
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
|
|
index b8e304e0..7086781a 100644
|
|
--- a/libmultipath/structs_vec.c
|
|
+++ b/libmultipath/structs_vec.c
|
|
@@ -319,6 +319,9 @@ void orphan_paths(vector pathvec, struct multipath *mpp, const char *reason)
|
|
free_path(pp);
|
|
} else
|
|
orphan_path(pp, reason);
|
|
+ } else if (pp->add_when_online &&
|
|
+ strncmp(mpp->wwid, pp->wwid, WWID_SIZE) == 0) {
|
|
+ pp->add_when_online = false;
|
|
}
|
|
}
|
|
}
|
|
@@ -496,6 +499,8 @@ void sync_paths(struct multipath *mpp, vector pathvec)
|
|
found = 0;
|
|
vector_foreach_slot(mpp->pg, pgp, j) {
|
|
if (find_slot(pgp->paths, (void *)pp) != -1) {
|
|
+ if (pp->add_when_online)
|
|
+ pp->add_when_online = false;
|
|
found = 1;
|
|
break;
|
|
}
|
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
|
index c5f458b9..4119ad79 100644
|
|
--- a/multipathd/main.c
|
|
+++ b/multipathd/main.c
|
|
@@ -558,11 +558,44 @@ pr_register_active_paths(struct multipath *mpp)
|
|
}
|
|
}
|
|
|
|
+static void
|
|
+save_offline_paths(const struct multipath *mpp, vector offline_paths)
|
|
+{
|
|
+ unsigned int i, j;
|
|
+ struct path *pp;
|
|
+ struct pathgroup *pgp;
|
|
+
|
|
+ vector_foreach_slot (mpp->pg, pgp, i)
|
|
+ vector_foreach_slot (pgp->paths, pp, j)
|
|
+ if (pp->initialized == INIT_OK && pp->offline)
|
|
+ /* ignore failures storing the paths. */
|
|
+ store_path(offline_paths, pp);
|
|
+}
|
|
+
|
|
+static void
|
|
+handle_orphaned_offline_paths(vector offline_paths)
|
|
+{
|
|
+ unsigned int i;
|
|
+ struct path *pp;
|
|
+
|
|
+ vector_foreach_slot (offline_paths, pp, i)
|
|
+ if (pp->mpp == NULL)
|
|
+ pp->add_when_online = true;
|
|
+}
|
|
+
|
|
+static void
|
|
+cleanup_reset_vec(struct _vector **v)
|
|
+{
|
|
+ vector_reset(*v);
|
|
+}
|
|
+
|
|
static int
|
|
update_map (struct multipath *mpp, struct vectors *vecs, int new_map)
|
|
{
|
|
int retries = 3;
|
|
char *params __attribute__((cleanup(cleanup_charp))) = NULL;
|
|
+ struct _vector offline_paths_vec = { .allocated = 0 };
|
|
+ vector offline_paths __attribute__((cleanup(cleanup_reset_vec))) = &offline_paths_vec;
|
|
|
|
retry:
|
|
condlog(4, "%s: updating new map", mpp->alias);
|
|
@@ -599,6 +632,9 @@ fail:
|
|
return 1;
|
|
}
|
|
|
|
+ if (new_map && retries < 0)
|
|
+ save_offline_paths(mpp, offline_paths);
|
|
+
|
|
if (setup_multipath(vecs, mpp))
|
|
return 1;
|
|
|
|
@@ -609,6 +645,9 @@ fail:
|
|
if (mpp->prflag == PRFLAG_SET)
|
|
pr_register_active_paths(mpp);
|
|
|
|
+ if (VECTOR_SIZE(offline_paths) != 0)
|
|
+ handle_orphaned_offline_paths(offline_paths);
|
|
+
|
|
if (retries < 0)
|
|
condlog(0, "%s: failed reload in new map update", mpp->alias);
|
|
return 0;
|
|
@@ -2253,7 +2292,8 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
|
int ret;
|
|
|
|
if (((pp->initialized == INIT_OK ||
|
|
- pp->initialized == INIT_REQUESTED_UDEV) && !pp->mpp) ||
|
|
+ pp->initialized == INIT_REQUESTED_UDEV) && !pp->mpp &&
|
|
+ !pp->add_when_online) ||
|
|
pp->initialized == INIT_REMOVED)
|
|
return 0;
|
|
|
|
@@ -2367,6 +2407,17 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
|
*/
|
|
pp->checkint = max_checkint;
|
|
}
|
|
+ } else if (pp->initialized == INIT_OK && pp->add_when_online &&
|
|
+ (newstate == PATH_UP || newstate == PATH_GHOST)) {
|
|
+ pp->add_when_online = false;
|
|
+ if (can_recheck_wwid(pp) &&
|
|
+ check_path_wwid_change(pp)) {
|
|
+ condlog(0, "%s: path wwid change detected. Removing", pp->dev);
|
|
+ handle_path_wwid_change(pp, vecs);
|
|
+ return 0;
|
|
+ }
|
|
+ ev_add_path(pp, vecs, 1);
|
|
+ pp->tick = 1;
|
|
}
|
|
return 0;
|
|
}
|
|
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8
|
|
index d3aa7a73..2ed036d4 100644
|
|
--- a/multipathd/multipathd.8
|
|
+++ b/multipathd/multipathd.8
|
|
@@ -529,7 +529,9 @@ The device serial number.
|
|
The device marginal state, either \fImarginal\fR or \fInormal\fR.
|
|
.TP
|
|
.B %m
|
|
-The multipath device that this device is a path of.
|
|
+The multipath device that this device is a path of, or \fI[offline]\fR
|
|
+if this device could not be added to a device because it is offline or
|
|
+\fI[orphan]\fR if it is not part of any multipath device.
|
|
.TP
|
|
.B %N
|
|
The host World Wide Node Name (WWNN) of the device.
|