Blame SOURCES/0017-BZ-1648397-fix-mpp-hwe-handling-when-paths-are-freed.patch

5c2e41
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
5c2e41
From: Benjamin Marzinski <bmarzins@redhat.com>
5c2e41
Date: Tue, 20 Nov 2018 22:05:43 -0600
5c2e41
Subject: [PATCH] BZ 1648397: fix mpp->hwe handling when paths are freed
5c2e41
5c2e41
Commit 1f962693 didn't deal with all of cases where a path that was part
5c2e41
of a multipath device could be removed. verify_paths() removes any path
5c2e41
that no longer exists in sysfs.  mpp->hwe needs to be updated here as
5c2e41
well, since verify_paths() could remove the path whose hwe vector is
5c2e41
pointed to by mpp->hwe.  Also, now that extract_hwe_from_path() is
5c2e41
called in verify_paths(), the extract_hwe_from_path() calls that
5c2e41
happened immediately after verify_paths() can be dropped.
5c2e41
5c2e41
The other part of this fix is mostly cosmetic. In ev_add_path(), if
5c2e41
domap() fails after the path is added to the multipath device and
5c2e41
verify_paths() is called, the code can loop back to the rescan label. If
5c2e41
the size of the path or the multipath device changed in the interim,
5c2e41
ev_add_path() would remove the path, without updating mpp->hwe; but
5c2e41
there is no way for the size to change. Just to make that clearer in the
5c2e41
code, I've moved the size check to before the rescan label so it only
5c2e41
happens once.
5c2e41
5c2e41
Fixes: 1f962693 "multipathd: fix mpp->hwe handling on path removal"
5c2e41
Cc: Martin Wilck <mwilck@suse.com>
5c2e41
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
5c2e41
---
5c2e41
 libmultipath/structs_vec.c |  7 +++++++
5c2e41
 multipathd/main.c          | 21 ++++++++-------------
5c2e41
 2 files changed, 15 insertions(+), 13 deletions(-)
5c2e41
5c2e41
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
5c2e41
index f87d69d..cd95ad4 100644
5c2e41
--- a/libmultipath/structs_vec.c
5c2e41
+++ b/libmultipath/structs_vec.c
5c2e41
@@ -404,6 +404,12 @@ int verify_paths(struct multipath *mpp, struct vectors *vecs)
5c2e41
 			vector_del_slot(mpp->paths, i);
5c2e41
 			i--;
5c2e41
 
5c2e41
+			/* Make sure mpp->hwe doesn't point to freed memory.
5c2e41
+			 * We call extract_hwe_from_path() below to restore
5c2e41
+			 * mpp->hwe
5c2e41
+			 */
5c2e41
+			if (mpp->hwe == pp->hwe)
5c2e41
+				mpp->hwe = NULL;
5c2e41
 			if ((j = find_slot(vecs->pathvec,
5c2e41
 					   (void *)pp)) != -1)
5c2e41
 				vector_del_slot(vecs->pathvec, j);
5c2e41
@@ -413,6 +419,7 @@ int verify_paths(struct multipath *mpp, struct vectors *vecs)
5c2e41
 				mpp->alias, pp->dev, pp->dev_t);
5c2e41
 		}
5c2e41
 	}
5c2e41
+	extract_hwe_from_path(mpp);
5c2e41
 	return count;
5c2e41
 }
5c2e41
 
5c2e41
diff --git a/multipathd/main.c b/multipathd/main.c
5c2e41
index 2d45d98..4e2835d 100644
5c2e41
--- a/multipathd/main.c
5c2e41
+++ b/multipathd/main.c
5c2e41
@@ -470,7 +470,6 @@ retry:
5c2e41
 	verify_paths(mpp, vecs);
5c2e41
 	mpp->action = ACT_RELOAD;
5c2e41
 
5c2e41
-	extract_hwe_from_path(mpp);
5c2e41
 	if (setup_map(mpp, params, PARAMS_SIZE, vecs)) {
5c2e41
 		condlog(0, "%s: failed to setup new map in update", mpp->alias);
5c2e41
 		retries = -1;
5c2e41
@@ -904,6 +903,14 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map)
5c2e41
 		goto fail; /* leave path added to pathvec */
5c2e41
 	}
5c2e41
 	mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid);
5c2e41
+	if (mpp && pp->size && mpp->size != pp->size) {
5c2e41
+		condlog(0, "%s: failed to add new path %s, device size mismatch", mpp->alias, pp->dev);
5c2e41
+		int i = find_slot(vecs->pathvec, (void *)pp);
5c2e41
+		if (i != -1)
5c2e41
+			vector_del_slot(vecs->pathvec, i);
5c2e41
+		free_path(pp);
5c2e41
+		return 1;
5c2e41
+	}
5c2e41
 	if (mpp && mpp->wait_for_udev &&
5c2e41
 	    (pathcount(mpp, PATH_UP) > 0 ||
5c2e41
 	     (pathcount(mpp, PATH_GHOST) > 0 && pp->tpgs != TPGS_IMPLICIT &&
5c2e41
@@ -919,17 +926,6 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map)
5c2e41
 	pp->mpp = mpp;
5c2e41
 rescan:
5c2e41
 	if (mpp) {
5c2e41
-		if (pp->size && mpp->size != pp->size) {
5c2e41
-			condlog(0, "%s: failed to add new path %s, "
5c2e41
-				"device size mismatch",
5c2e41
-				mpp->alias, pp->dev);
5c2e41
-			int i = find_slot(vecs->pathvec, (void *)pp);
5c2e41
-			if (i != -1)
5c2e41
-				vector_del_slot(vecs->pathvec, i);
5c2e41
-			free_path(pp);
5c2e41
-			return 1;
5c2e41
-		}
5c2e41
-
5c2e41
 		condlog(4,"%s: adopting all paths for path %s",
5c2e41
 			mpp->alias, pp->dev);
5c2e41
 		if (adopt_paths(vecs->pathvec, mpp))
5c2e41
@@ -937,7 +933,6 @@ rescan:
5c2e41
 
5c2e41
 		verify_paths(mpp, vecs);
5c2e41
 		mpp->action = ACT_RELOAD;
5c2e41
-		extract_hwe_from_path(mpp);
5c2e41
 	} else {
5c2e41
 		if (!should_multipath(pp, vecs->pathvec, vecs->mpvec)) {
5c2e41
 			orphan_path(pp, "only one path");
5c2e41
-- 
5c2e41
2.17.2
5c2e41