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

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