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

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