Blame SOURCES/0126-libmultipath-copy-mpp-hwe-from-pp-hwe.patch

9eb812
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
9eb812
From: Martin Wilck <mwilck@suse.com>
9eb812
Date: Wed, 16 Sep 2020 22:22:36 +0200
9eb812
Subject: [PATCH] libmultipath: copy mpp->hwe from pp->hwe
9eb812
9eb812
Since f0462f0 ("libmultipath: use vector for for pp->hwe and mp->hwe"),
9eb812
we've been trying to fix issues caused by paths getting freed and mpp->hwe
9eb812
dangling. This approach couldn't work because we need mpp->hwe to persist,
9eb812
even if all paths are removed from the map. Before f0462f0, a simple
9eb812
assignment worked, because the lifetime of the hwe wasn't bound to the
9eb812
path. But now, we need to copy the vector. It turns out that we need to set
9eb812
mpp->hwe only in two places, add_map_with_path() and setup_map(), and
9eb812
that the code is simplified overall.
9eb812
9eb812
Even now, it can happen that a map is added with add_map_without_paths(),
9eb812
and has no paths. In that case, calling do_set_from_hwe() with a NULL
9eb812
pointer is not a bug, so remove the message.
9eb812
9eb812
Fixes: f0462f0 ("libmultipath: use vector for for pp->hwe and mp->hwe")
9eb812
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
9eb812
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
9eb812
---
9eb812
 libmultipath/configure.c   |  8 ++++++++
9eb812
 libmultipath/propsel.c     |  2 +-
9eb812
 libmultipath/structs.c     | 15 ++++++++++++++
9eb812
 libmultipath/structs.h     |  1 +
9eb812
 libmultipath/structs_vec.c | 41 +++++++++++++++++++-------------------
9eb812
 multipathd/main.c          | 10 ----------
9eb812
 6 files changed, 45 insertions(+), 32 deletions(-)
9eb812
9eb812
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
9eb812
index c341793c..6e06fea2 100644
9eb812
--- a/libmultipath/configure.c
9eb812
+++ b/libmultipath/configure.c
9eb812
@@ -324,6 +324,14 @@ int setup_map(struct multipath *mpp, char *params, int params_size,
9eb812
 	if (mpp->disable_queueing && VECTOR_SIZE(mpp->paths) != 0)
9eb812
 		mpp->disable_queueing = 0;
9eb812
 
9eb812
+	/*
9eb812
+	 * If this map was created with add_map_without_path(),
9eb812
+	 * mpp->hwe might not be set yet.
9eb812
+	 */
9eb812
+	if (!mpp->hwe)
9eb812
+		extract_hwe_from_path(mpp);
9eb812
+
9eb812
+
9eb812
 	/*
9eb812
 	 * properties selectors
9eb812
 	 *
9eb812
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
9eb812
index 3f119dd9..bc5c27ab 100644
9eb812
--- a/libmultipath/propsel.c
9eb812
+++ b/libmultipath/propsel.c
9eb812
@@ -66,7 +66,7 @@ do {									\
9eb812
 	__do_set_from_vec(struct hwentry, var, (src)->hwe, dest)
9eb812
 
9eb812
 #define do_set_from_hwe(var, src, dest, msg)				\
9eb812
-	if (__do_set_from_hwe(var, src, dest)) {			\
9eb812
+	if (src->hwe && __do_set_from_hwe(var, src, dest)) {		\
9eb812
 		origin = msg;						\
9eb812
 		goto out;						\
9eb812
 	}
9eb812
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
9eb812
index 7bdf9152..5bb6caf8 100644
9eb812
--- a/libmultipath/structs.c
9eb812
+++ b/libmultipath/structs.c
9eb812
@@ -242,6 +242,17 @@ alloc_multipath (void)
9eb812
 	return mpp;
9eb812
 }
9eb812
 
9eb812
+void *set_mpp_hwe(struct multipath *mpp, const struct path *pp)
9eb812
+{
9eb812
+	if (!mpp || !pp || !pp->hwe)
9eb812
+		return NULL;
9eb812
+	if (mpp->hwe)
9eb812
+		return mpp->hwe;
9eb812
+	mpp->hwe = vector_convert(NULL, pp->hwe,
9eb812
+				  struct hwentry, identity);
9eb812
+	return mpp->hwe;
9eb812
+}
9eb812
+
9eb812
 void free_multipath_attributes(struct multipath *mpp)
9eb812
 {
9eb812
 	if (!mpp)
9eb812
@@ -283,6 +294,10 @@ free_multipath (struct multipath * mpp, enum free_path_mode free_paths)
9eb812
 
9eb812
 	free_pathvec(mpp->paths, free_paths);
9eb812
 	free_pgvec(mpp->pg, free_paths);
9eb812
+	if (mpp->hwe) {
9eb812
+		vector_free(mpp->hwe);
9eb812
+		mpp->hwe = NULL;
9eb812
+	}
9eb812
 	FREE_PTR(mpp->mpcontext);
9eb812
 	FREE(mpp);
9eb812
 }
9eb812
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
9eb812
index 9130efb5..44980b4e 100644
9eb812
--- a/libmultipath/structs.h
9eb812
+++ b/libmultipath/structs.h
9eb812
@@ -499,6 +499,7 @@ struct host_group {
9eb812
 struct path * alloc_path (void);
9eb812
 struct pathgroup * alloc_pathgroup (void);
9eb812
 struct multipath * alloc_multipath (void);
9eb812
+void *set_mpp_hwe(struct multipath *mpp, const struct path *pp);
9eb812
 void free_path (struct path *);
9eb812
 void free_pathvec (vector vec, enum free_path_mode free_paths);
9eb812
 void free_pathgroup (struct pathgroup * pgp, enum free_path_mode free_paths);
9eb812
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
9eb812
index 24ac022e..9613252f 100644
9eb812
--- a/libmultipath/structs_vec.c
9eb812
+++ b/libmultipath/structs_vec.c
9eb812
@@ -180,24 +180,24 @@ extract_hwe_from_path(struct multipath * mpp)
9eb812
 	if (mpp->hwe || !mpp->paths)
9eb812
 		return;
9eb812
 
9eb812
-	condlog(3, "%s: searching paths for valid hwe", mpp->alias);
9eb812
+	condlog(4, "%s: searching paths for valid hwe", mpp->alias);
9eb812
 	/* doing this in two passes seems like paranoia to me */
9eb812
 	vector_foreach_slot(mpp->paths, pp, i) {
9eb812
-		if (pp->state != PATH_UP)
9eb812
-			continue;
9eb812
-		if (pp->hwe) {
9eb812
-			mpp->hwe = pp->hwe;
9eb812
-			return;
9eb812
-		}
9eb812
+		if (pp->state == PATH_UP && pp->hwe)
9eb812
+			goto done;
9eb812
 	}
9eb812
 	vector_foreach_slot(mpp->paths, pp, i) {
9eb812
-		if (pp->state == PATH_UP)
9eb812
-			continue;
9eb812
-		if (pp->hwe) {
9eb812
-			mpp->hwe = pp->hwe;
9eb812
-			return;
9eb812
-		}
9eb812
+		if (pp->state != PATH_UP && pp->hwe)
9eb812
+			goto done;
9eb812
 	}
9eb812
+done:
9eb812
+	if (i < VECTOR_SIZE(mpp->paths))
9eb812
+		(void)set_mpp_hwe(mpp, pp);
9eb812
+
9eb812
+	if (mpp->hwe)
9eb812
+		condlog(3, "%s: got hwe from path %s", mpp->alias, pp->dev);
9eb812
+	else
9eb812
+		condlog(2, "%s: no hwe found", mpp->alias);
9eb812
 }
9eb812
 
9eb812
 int
9eb812
@@ -445,9 +445,15 @@ struct multipath *add_map_with_path(struct vectors *vecs, struct path *pp,
9eb812
 
9eb812
 	conf = get_multipath_config();
9eb812
 	mpp->mpe = find_mpe(conf->mptable, pp->wwid);
9eb812
-	mpp->hwe = pp->hwe;
9eb812
 	put_multipath_config(conf);
9eb812
 
9eb812
+	/*
9eb812
+	 * We need to call this before select_alias(),
9eb812
+	 * because that accesses hwe properties.
9eb812
+	 */
9eb812
+	if (pp->hwe && !set_mpp_hwe(mpp, pp))
9eb812
+		goto out;
9eb812
+
9eb812
 	strcpy(mpp->wwid, pp->wwid);
9eb812
 	find_existing_alias(mpp, vecs);
9eb812
 	if (select_alias(conf, mpp))
9eb812
@@ -497,12 +503,6 @@ int verify_paths(struct multipath *mpp, struct vectors *vecs)
9eb812
 			vector_del_slot(mpp->paths, i);
9eb812
 			i--;
9eb812
 
9eb812
-			/* Make sure mpp->hwe doesn't point to freed memory.
9eb812
-			 * We call extract_hwe_from_path() below to restore
9eb812
-			 * mpp->hwe
9eb812
-			 */
9eb812
-			if (mpp->hwe == pp->hwe)
9eb812
-				mpp->hwe = NULL;
9eb812
 			if ((j = find_slot(vecs->pathvec,
9eb812
 					   (void *)pp)) != -1)
9eb812
 				vector_del_slot(vecs->pathvec, j);
9eb812
@@ -512,7 +512,6 @@ int verify_paths(struct multipath *mpp, struct vectors *vecs)
9eb812
 				mpp->alias, pp->dev, pp->dev_t);
9eb812
 		}
9eb812
 	}
9eb812
-	extract_hwe_from_path(mpp);
9eb812
 	return count;
9eb812
 }
9eb812
 
9eb812
diff --git a/multipathd/main.c b/multipathd/main.c
9eb812
index cd68a9d2..769dcaee 100644
9eb812
--- a/multipathd/main.c
9eb812
+++ b/multipathd/main.c
9eb812
@@ -1198,13 +1198,6 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map)
9eb812
 			goto fail;
9eb812
 		}
9eb812
 
9eb812
-		/*
9eb812
-		 * Make sure mpp->hwe doesn't point to freed memory
9eb812
-		 * We call extract_hwe_from_path() below to restore mpp->hwe
9eb812
-		 */
9eb812
-		if (mpp->hwe == pp->hwe)
9eb812
-			mpp->hwe = NULL;
9eb812
-
9eb812
 		if ((i = find_slot(mpp->paths, (void *)pp)) != -1)
9eb812
 			vector_del_slot(mpp->paths, i);
9eb812
 
9eb812
@@ -1216,9 +1209,6 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map)
9eb812
 		    flush_map_nopaths(mpp, vecs))
9eb812
 			goto out;
9eb812
 
9eb812
-		if (mpp->hwe == NULL)
9eb812
-			extract_hwe_from_path(mpp);
9eb812
-
9eb812
 		if (setup_map(mpp, params, PARAMS_SIZE, vecs)) {
9eb812
 			condlog(0, "%s: failed to setup map for"
9eb812
 				" removal of path %s", mpp->alias, pp->dev);