1dad67a5af
Update Source to upstream version 0.8.5 plus post tag commits * Patches 0001-0102 are from https://github.com/openSUSE/multipath-tools/tree/queue and are already queued for upstream. Rename files * Previous patches 0059-0068 are now patches 0103-0111
261 lines
8.0 KiB
Diff
261 lines
8.0 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Martin Wilck <mwilck@suse.com>
|
|
Date: Wed, 16 Sep 2020 22:22:36 +0200
|
|
Subject: [PATCH] libmultipath: copy mpp->hwe from pp->hwe
|
|
|
|
Since f0462f0 ("libmultipath: use vector for for pp->hwe and mp->hwe"),
|
|
we've been trying to fix issues caused by paths getting freed and mpp->hwe
|
|
dangling. This approach couldn't work because we need mpp->hwe to persist,
|
|
even if all paths are removed from the map. Before f0462f0, a simple
|
|
assignment worked, because the lifetime of the hwe wasn't bound to the
|
|
path. But now, we need to copy the vector. It turns out that we need to set
|
|
mpp->hwe only in two places, add_map_with_path() and setup_map(), and
|
|
that the code is simplified overall.
|
|
|
|
Even now, it can happen that a map is added with add_map_without_paths(),
|
|
and has no paths. In that case, calling do_set_from_hwe() with a NULL
|
|
pointer is not a bug, so remove the message.
|
|
|
|
Fixes: f0462f0 ("libmultipath: use vector for for pp->hwe and mp->hwe")
|
|
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
|
---
|
|
libmultipath/configure.c | 7 +++++
|
|
libmultipath/propsel.c | 4 +--
|
|
libmultipath/structs.c | 15 +++++++++++
|
|
libmultipath/structs.h | 1 +
|
|
libmultipath/structs_vec.c | 54 ++++++++++++++++----------------------
|
|
multipathd/main.c | 10 -------
|
|
6 files changed, 46 insertions(+), 45 deletions(-)
|
|
|
|
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
|
index 6fb477fc..d7afc915 100644
|
|
--- a/libmultipath/configure.c
|
|
+++ b/libmultipath/configure.c
|
|
@@ -311,6 +311,13 @@ int setup_map(struct multipath *mpp, char *params, int params_size,
|
|
if (mpp->disable_queueing && VECTOR_SIZE(mpp->paths) != 0)
|
|
mpp->disable_queueing = 0;
|
|
|
|
+ /*
|
|
+ * If this map was created with add_map_without_path(),
|
|
+ * mpp->hwe might not be set yet.
|
|
+ */
|
|
+ if (!mpp->hwe)
|
|
+ extract_hwe_from_path(mpp);
|
|
+
|
|
/*
|
|
* properties selectors
|
|
*
|
|
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
|
index 7e6e0d68..40201344 100644
|
|
--- a/libmultipath/propsel.c
|
|
+++ b/libmultipath/propsel.c
|
|
@@ -65,9 +65,7 @@ do { \
|
|
__do_set_from_vec(struct hwentry, var, (src)->hwe, dest)
|
|
|
|
#define do_set_from_hwe(var, src, dest, msg) \
|
|
- if (!src->hwe) { \
|
|
- condlog(0, "BUG: do_set_from_hwe called with hwe == NULL"); \
|
|
- } else if (__do_set_from_hwe(var, src, dest)) { \
|
|
+ if (src->hwe && __do_set_from_hwe(var, src, dest)) { \
|
|
origin = msg; \
|
|
goto out; \
|
|
}
|
|
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
|
|
index 464596fc..2efad6f0 100644
|
|
--- a/libmultipath/structs.c
|
|
+++ b/libmultipath/structs.c
|
|
@@ -234,6 +234,17 @@ alloc_multipath (void)
|
|
return mpp;
|
|
}
|
|
|
|
+void *set_mpp_hwe(struct multipath *mpp, const struct path *pp)
|
|
+{
|
|
+ if (!mpp || !pp || !pp->hwe)
|
|
+ return NULL;
|
|
+ if (mpp->hwe)
|
|
+ return mpp->hwe;
|
|
+ mpp->hwe = vector_convert(NULL, pp->hwe,
|
|
+ struct hwentry, identity);
|
|
+ return mpp->hwe;
|
|
+}
|
|
+
|
|
void free_multipath_attributes(struct multipath *mpp)
|
|
{
|
|
if (!mpp)
|
|
@@ -290,6 +301,10 @@ free_multipath (struct multipath * mpp, enum free_path_mode free_paths)
|
|
|
|
free_pathvec(mpp->paths, free_paths);
|
|
free_pgvec(mpp->pg, free_paths);
|
|
+ if (mpp->hwe) {
|
|
+ vector_free(mpp->hwe);
|
|
+ mpp->hwe = NULL;
|
|
+ }
|
|
FREE_PTR(mpp->mpcontext);
|
|
FREE(mpp);
|
|
}
|
|
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
|
index 7de93d6c..4ce30551 100644
|
|
--- a/libmultipath/structs.h
|
|
+++ b/libmultipath/structs.h
|
|
@@ -422,6 +422,7 @@ struct host_group {
|
|
struct path * alloc_path (void);
|
|
struct pathgroup * alloc_pathgroup (void);
|
|
struct multipath * alloc_multipath (void);
|
|
+void *set_mpp_hwe(struct multipath *mpp, const struct path *pp);
|
|
void uninitialize_path(struct path *pp);
|
|
void free_path (struct path *);
|
|
void free_pathvec (vector vec, enum free_path_mode free_paths);
|
|
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
|
|
index 8895fa77..f7f45f11 100644
|
|
--- a/libmultipath/structs_vec.c
|
|
+++ b/libmultipath/structs_vec.c
|
|
@@ -294,11 +294,6 @@ err:
|
|
void orphan_path(struct path *pp, const char *reason)
|
|
{
|
|
condlog(3, "%s: orphan path, %s", pp->dev, reason);
|
|
- if (pp->mpp && pp->hwe && pp->mpp->hwe == pp->hwe) {
|
|
- condlog(0, "BUG: orphaning path %s that holds hwe of %s",
|
|
- pp->dev, pp->mpp->alias);
|
|
- pp->mpp->hwe = NULL;
|
|
- }
|
|
pp->mpp = NULL;
|
|
uninitialize_path(pp);
|
|
}
|
|
@@ -308,8 +303,6 @@ void orphan_paths(vector pathvec, struct multipath *mpp, const char *reason)
|
|
int i;
|
|
struct path * pp;
|
|
|
|
- /* Avoid BUG message from orphan_path() */
|
|
- mpp->hwe = NULL;
|
|
vector_foreach_slot (pathvec, pp, i) {
|
|
if (pp->mpp == mpp) {
|
|
if (pp->initialized == INIT_REMOVED) {
|
|
@@ -397,24 +390,26 @@ extract_hwe_from_path(struct multipath * mpp)
|
|
if (mpp->hwe || !mpp->paths)
|
|
return;
|
|
|
|
- condlog(3, "%s: searching paths for valid hwe", mpp->alias);
|
|
+ condlog(4, "%s: searching paths for valid hwe", mpp->alias);
|
|
/* doing this in two passes seems like paranoia to me */
|
|
vector_foreach_slot(mpp->paths, pp, i) {
|
|
- if (pp->state != PATH_UP)
|
|
- continue;
|
|
- if (pp->hwe) {
|
|
- mpp->hwe = pp->hwe;
|
|
- return;
|
|
- }
|
|
+ if (pp->state == PATH_UP &&
|
|
+ pp->initialized != INIT_REMOVED && pp->hwe)
|
|
+ goto done;
|
|
}
|
|
vector_foreach_slot(mpp->paths, pp, i) {
|
|
- if (pp->state == PATH_UP)
|
|
- continue;
|
|
- if (pp->hwe) {
|
|
- mpp->hwe = pp->hwe;
|
|
- return;
|
|
- }
|
|
+ if (pp->state != PATH_UP &&
|
|
+ pp->initialized != INIT_REMOVED && pp->hwe)
|
|
+ goto done;
|
|
}
|
|
+done:
|
|
+ if (i < VECTOR_SIZE(mpp->paths))
|
|
+ (void)set_mpp_hwe(mpp, pp);
|
|
+
|
|
+ if (mpp->hwe)
|
|
+ condlog(3, "%s: got hwe from path %s", mpp->alias, pp->dev);
|
|
+ else
|
|
+ condlog(2, "%s: no hwe found", mpp->alias);
|
|
}
|
|
|
|
int
|
|
@@ -514,8 +509,6 @@ void sync_paths(struct multipath *mpp, vector pathvec)
|
|
}
|
|
if (!found) {
|
|
condlog(3, "%s dropped path %s", mpp->alias, pp->dev);
|
|
- if (mpp->hwe == pp->hwe)
|
|
- mpp->hwe = NULL;
|
|
vector_del_slot(mpp->paths, i--);
|
|
orphan_path(pp, "path removed externally");
|
|
}
|
|
@@ -524,8 +517,6 @@ void sync_paths(struct multipath *mpp, vector pathvec)
|
|
update_mpp_paths(mpp, pathvec);
|
|
vector_foreach_slot (mpp->paths, pp, i)
|
|
pp->mpp = mpp;
|
|
- if (mpp->hwe == NULL)
|
|
- extract_hwe_from_path(mpp);
|
|
}
|
|
|
|
int
|
|
@@ -701,9 +692,15 @@ struct multipath *add_map_with_path(struct vectors *vecs, struct path *pp,
|
|
|
|
conf = get_multipath_config();
|
|
mpp->mpe = find_mpe(conf->mptable, pp->wwid);
|
|
- mpp->hwe = pp->hwe;
|
|
put_multipath_config(conf);
|
|
|
|
+ /*
|
|
+ * We need to call this before select_alias(),
|
|
+ * because that accesses hwe properties.
|
|
+ */
|
|
+ if (pp->hwe && !set_mpp_hwe(mpp, pp))
|
|
+ goto out;
|
|
+
|
|
strcpy(mpp->wwid, pp->wwid);
|
|
find_existing_alias(mpp, vecs);
|
|
if (select_alias(conf, mpp))
|
|
@@ -754,12 +751,6 @@ int verify_paths(struct multipath *mpp)
|
|
vector_del_slot(mpp->paths, i);
|
|
i--;
|
|
|
|
- /* Make sure mpp->hwe doesn't point to freed memory.
|
|
- * We call extract_hwe_from_path() below to restore
|
|
- * mpp->hwe
|
|
- */
|
|
- if (mpp->hwe == pp->hwe)
|
|
- mpp->hwe = NULL;
|
|
/*
|
|
* Don't delete path from pathvec yet. We'll do this
|
|
* after the path has been removed from the map, in
|
|
@@ -771,7 +762,6 @@ int verify_paths(struct multipath *mpp)
|
|
mpp->alias, pp->dev, pp->dev_t);
|
|
}
|
|
}
|
|
- extract_hwe_from_path(mpp);
|
|
return count;
|
|
}
|
|
|
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
|
index a4abbb27..eedc6c10 100644
|
|
--- a/multipathd/main.c
|
|
+++ b/multipathd/main.c
|
|
@@ -1153,13 +1153,6 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map)
|
|
if (i != -1)
|
|
vector_del_slot(mpp->paths, i);
|
|
|
|
- /*
|
|
- * Make sure mpp->hwe doesn't point to freed memory
|
|
- * We call extract_hwe_from_path() below to restore mpp->hwe
|
|
- */
|
|
- if (mpp->hwe == pp->hwe)
|
|
- mpp->hwe = NULL;
|
|
-
|
|
/*
|
|
* remove the map IF removing the last path
|
|
*/
|
|
@@ -1191,9 +1184,6 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map)
|
|
*/
|
|
}
|
|
|
|
- if (mpp->hwe == NULL)
|
|
- extract_hwe_from_path(mpp);
|
|
-
|
|
if (setup_map(mpp, params, PARAMS_SIZE, vecs)) {
|
|
condlog(0, "%s: failed to setup map for"
|
|
" removal of path %s", mpp->alias, pp->dev);
|
|
--
|
|
2.17.2
|
|
|