Blame SOURCES/0025-multipathd-fix-check_path-errors-with-removed-map.patch

785c99
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
785c99
From: Benjamin Marzinski <bmarzins@redhat.com>
785c99
Date: Thu, 11 Jun 2020 15:41:18 -0500
785c99
Subject: [PATCH] multipathd: fix check_path errors with removed map
785c99
785c99
If a multipath device is removed during, or immediately before the call
785c99
to check_path(), multipathd can behave incorrectly. A missing multpath
785c99
device will cause update_multipath_strings() to fail, setting
785c99
pp->dmstate to PSTATE_UNDEF.  If the path is up, this state will cause
785c99
reinstate_path() to be called, which will also fail.  This will trigger
785c99
a reload, restoring the recently removed device.
785c99
785c99
If update_multipath_strings() fails because there is no multipath
785c99
device, check_path should just quit, since the remove dmevent and uevent
785c99
are likely already queued up. Also, I don't see any reason to reload the
785c99
multipath device if reinstate fails. This code was added by
785c99
fac68d7a99ef17d496079538a5c6836acd7911ab, which clamined that reinstate
785c99
could fail if the path was disabled.  Looking through the current kernel
785c99
code, I can't see any reason why a reinstate would fail, where a reload
785c99
would help. If the path was missing from the multipath device,
785c99
update_multipath_strings() would already catch that, and quit
785c99
check_path() early, which make more sense to me than reloading does.
785c99
785c99
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
785c99
---
785c99
 multipathd/main.c | 44 +++++++++++++++++++-------------------------
785c99
 1 file changed, 19 insertions(+), 25 deletions(-)
785c99
785c99
diff --git a/multipathd/main.c b/multipathd/main.c
785c99
index e3427d3d..1d9ce7f7 100644
785c99
--- a/multipathd/main.c
785c99
+++ b/multipathd/main.c
785c99
@@ -1611,22 +1611,18 @@ fail_path (struct path * pp, int del_active)
785c99
 /*
785c99
  * caller must have locked the path list before calling that function
785c99
  */
785c99
-static int
785c99
+static void
785c99
 reinstate_path (struct path * pp)
785c99
 {
785c99
-	int ret = 0;
785c99
-
785c99
 	if (!pp->mpp)
785c99
-		return 0;
785c99
+		return;
785c99
 
785c99
-	if (dm_reinstate_path(pp->mpp->alias, pp->dev_t)) {
785c99
+	if (dm_reinstate_path(pp->mpp->alias, pp->dev_t))
785c99
 		condlog(0, "%s: reinstate failed", pp->dev_t);
785c99
-		ret = 1;
785c99
-	} else {
785c99
+	else {
785c99
 		condlog(2, "%s: reinstated", pp->dev_t);
785c99
 		update_queue_mode_add_path(pp->mpp);
785c99
 	}
785c99
-	return ret;
785c99
 }
785c99
 
785c99
 static void
785c99
@@ -2087,9 +2083,16 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
785c99
 	/*
785c99
 	 * Synchronize with kernel state
785c99
 	 */
785c99
-	if (update_multipath_strings(pp->mpp, vecs->pathvec, 1) != DMP_OK) {
785c99
-		condlog(1, "%s: Could not synchronize with kernel state",
785c99
-			pp->dev);
785c99
+	ret = update_multipath_strings(pp->mpp, vecs->pathvec, 1);
785c99
+	if (ret != DMP_OK) {
785c99
+		if (ret == DMP_NOT_FOUND) {
785c99
+			/* multipath device missing. Likely removed */
785c99
+			condlog(1, "%s: multipath device '%s' not found",
785c99
+				pp->dev, pp->mpp->alias);
785c99
+			return 0;
785c99
+		} else
785c99
+			condlog(1, "%s: Couldn't synchronize with kernel state",
785c99
+				pp->dev);
785c99
 		pp->dmstate = PSTATE_UNDEF;
785c99
 	}
785c99
 	/* if update_multipath_strings orphaned the path, quit early */
785c99
@@ -2179,12 +2182,8 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
785c99
 		/*
785c99
 		 * reinstate this path
785c99
 		 */
785c99
-		if (!disable_reinstate && reinstate_path(pp)) {
785c99
-			condlog(3, "%s: reload map", pp->dev);
785c99
-			ev_add_path(pp, vecs, 1);
785c99
-			pp->tick = 1;
785c99
-			return 0;
785c99
-		}
785c99
+		if (!disable_reinstate)
785c99
+			reinstate_path(pp);
785c99
 		new_path_up = 1;
785c99
 
785c99
 		if (oldchkrstate != PATH_UP && oldchkrstate != PATH_GHOST)
785c99
@@ -2200,15 +2199,10 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
785c99
 	else if (newstate == PATH_UP || newstate == PATH_GHOST) {
785c99
 		if ((pp->dmstate == PSTATE_FAILED ||
785c99
 		    pp->dmstate == PSTATE_UNDEF) &&
785c99
-		    !disable_reinstate) {
785c99
+		    !disable_reinstate)
785c99
 			/* Clear IO errors */
785c99
-			if (reinstate_path(pp)) {
785c99
-				condlog(3, "%s: reload map", pp->dev);
785c99
-				ev_add_path(pp, vecs, 1);
785c99
-				pp->tick = 1;
785c99
-				return 0;
785c99
-			}
785c99
-		} else {
785c99
+			reinstate_path(pp);
785c99
+		else {
785c99
 			LOG_MSG(4, verbosity, pp);
785c99
 			if (pp->checkint != max_checkint) {
785c99
 				/*
785c99
-- 
785c99
2.17.2
785c99