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