|
|
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 |
|