diff --git a/SOURCES/0112-libmultipath-copy-mpp-hwe-from-pp-hwe.patch b/SOURCES/0112-libmultipath-copy-mpp-hwe-from-pp-hwe.patch new file mode 100644 index 0000000..a06a1e1 --- /dev/null +++ b/SOURCES/0112-libmultipath-copy-mpp-hwe-from-pp-hwe.patch @@ -0,0 +1,215 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 16 Sep 2020 22:22:36 +0200 +Subject: [PATCH] libmultipath: copy mpp->hwe from pp->hwe + +Since f0462f0 ("libmultipath: use vector for for pp->hwe and mp->hwe"), +we've been trying to fix issues caused by paths getting freed and mpp->hwe +dangling. This approach couldn't work because we need mpp->hwe to persist, +even if all paths are removed from the map. Before f0462f0, a simple +assignment worked, because the lifetime of the hwe wasn't bound to the +path. But now, we need to copy the vector. It turns out that we need to set +mpp->hwe only in two places, add_map_with_path() and setup_map(), and +that the code is simplified overall. + +Even now, it can happen that a map is added with add_map_without_paths(), +and has no paths. In that case, calling do_set_from_hwe() with a NULL +pointer is not a bug, so remove the message. + +Fixes: f0462f0 ("libmultipath: use vector for for pp->hwe and mp->hwe") +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/configure.c | 8 ++++++++ + libmultipath/propsel.c | 2 +- + libmultipath/structs.c | 15 ++++++++++++++ + libmultipath/structs.h | 1 + + libmultipath/structs_vec.c | 41 +++++++++++++++++++------------------- + multipathd/main.c | 10 ---------- + 6 files changed, 45 insertions(+), 32 deletions(-) + +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index 6cad0468..cd810ba0 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -314,6 +314,14 @@ int setup_map(struct multipath *mpp, char *params, int params_size, + if (mpp->disable_queueing && VECTOR_SIZE(mpp->paths) != 0) + mpp->disable_queueing = 0; + ++ /* ++ * If this map was created with add_map_without_path(), ++ * mpp->hwe might not be set yet. ++ */ ++ if (!mpp->hwe) ++ extract_hwe_from_path(mpp); ++ ++ + /* + * properties selectors + * +diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c +index be79902f..3764398e 100644 +--- a/libmultipath/propsel.c ++++ b/libmultipath/propsel.c +@@ -65,7 +65,7 @@ do { \ + __do_set_from_vec(struct hwentry, var, (src)->hwe, dest) + + #define do_set_from_hwe(var, src, dest, msg) \ +- if (__do_set_from_hwe(var, src, dest)) { \ ++ if (src->hwe && __do_set_from_hwe(var, src, dest)) { \ + origin = msg; \ + goto out; \ + } +diff --git a/libmultipath/structs.c b/libmultipath/structs.c +index 9f86eb69..8316cde0 100644 +--- a/libmultipath/structs.c ++++ b/libmultipath/structs.c +@@ -235,6 +235,17 @@ alloc_multipath (void) + return mpp; + } + ++void *set_mpp_hwe(struct multipath *mpp, const struct path *pp) ++{ ++ if (!mpp || !pp || !pp->hwe) ++ return NULL; ++ if (mpp->hwe) ++ return mpp->hwe; ++ mpp->hwe = vector_convert(NULL, pp->hwe, ++ struct hwentry, identity); ++ return mpp->hwe; ++} ++ + void free_multipath_attributes(struct multipath *mpp) + { + if (!mpp) +@@ -276,6 +287,10 @@ free_multipath (struct multipath * mpp, enum free_path_mode free_paths) + + free_pathvec(mpp->paths, free_paths); + free_pgvec(mpp->pg, free_paths); ++ if (mpp->hwe) { ++ vector_free(mpp->hwe); ++ mpp->hwe = NULL; ++ } + FREE_PTR(mpp->mpcontext); + FREE(mpp); + } +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index 3ed5cfc1..7bfc5b95 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -481,6 +481,7 @@ struct host_group { + struct path * alloc_path (void); + struct pathgroup * alloc_pathgroup (void); + struct multipath * alloc_multipath (void); ++void *set_mpp_hwe(struct multipath *mpp, const struct path *pp); + void free_path (struct path *); + void free_pathvec (vector vec, enum free_path_mode free_paths); + void free_pathgroup (struct pathgroup * pgp, enum free_path_mode free_paths); +diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c +index 8137ea21..5156c584 100644 +--- a/libmultipath/structs_vec.c ++++ b/libmultipath/structs_vec.c +@@ -173,24 +173,24 @@ extract_hwe_from_path(struct multipath * mpp) + if (mpp->hwe || !mpp->paths) + return; + +- condlog(3, "%s: searching paths for valid hwe", mpp->alias); ++ condlog(4, "%s: searching paths for valid hwe", mpp->alias); + /* doing this in two passes seems like paranoia to me */ + vector_foreach_slot(mpp->paths, pp, i) { +- if (pp->state != PATH_UP) +- continue; +- if (pp->hwe) { +- mpp->hwe = pp->hwe; +- return; +- } ++ if (pp->state == PATH_UP && pp->hwe) ++ goto done; + } + vector_foreach_slot(mpp->paths, pp, i) { +- if (pp->state == PATH_UP) +- continue; +- if (pp->hwe) { +- mpp->hwe = pp->hwe; +- return; +- } ++ if (pp->state != PATH_UP && pp->hwe) ++ goto done; + } ++done: ++ if (i < VECTOR_SIZE(mpp->paths)) ++ (void)set_mpp_hwe(mpp, pp); ++ ++ if (mpp->hwe) ++ condlog(3, "%s: got hwe from path %s", mpp->alias, pp->dev); ++ else ++ condlog(2, "%s: no hwe found", mpp->alias); + } + + int +@@ -438,9 +438,15 @@ struct multipath *add_map_with_path(struct vectors *vecs, struct path *pp, + + conf = get_multipath_config(); + mpp->mpe = find_mpe(conf->mptable, pp->wwid); +- mpp->hwe = pp->hwe; + put_multipath_config(conf); + ++ /* ++ * We need to call this before select_alias(), ++ * because that accesses hwe properties. ++ */ ++ if (pp->hwe && !set_mpp_hwe(mpp, pp)) ++ goto out; ++ + strcpy(mpp->wwid, pp->wwid); + find_existing_alias(mpp, vecs); + if (select_alias(conf, mpp)) +@@ -490,12 +496,6 @@ int verify_paths(struct multipath *mpp, struct vectors *vecs) + vector_del_slot(mpp->paths, i); + i--; + +- /* Make sure mpp->hwe doesn't point to freed memory. +- * We call extract_hwe_from_path() below to restore +- * mpp->hwe +- */ +- if (mpp->hwe == pp->hwe) +- mpp->hwe = NULL; + if ((j = find_slot(vecs->pathvec, + (void *)pp)) != -1) + vector_del_slot(vecs->pathvec, j); +@@ -505,7 +505,6 @@ int verify_paths(struct multipath *mpp, struct vectors *vecs) + mpp->alias, pp->dev, pp->dev_t); + } + } +- extract_hwe_from_path(mpp); + return count; + } + +diff --git a/multipathd/main.c b/multipathd/main.c +index 7cdab5a0..8f4ba8ec 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -1174,13 +1174,6 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map) + goto fail; + } + +- /* +- * Make sure mpp->hwe doesn't point to freed memory +- * We call extract_hwe_from_path() below to restore mpp->hwe +- */ +- if (mpp->hwe == pp->hwe) +- mpp->hwe = NULL; +- + if ((i = find_slot(mpp->paths, (void *)pp)) != -1) + vector_del_slot(mpp->paths, i); + +@@ -1214,9 +1207,6 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map) + */ + } + +- if (mpp->hwe == NULL) +- extract_hwe_from_path(mpp); +- + if (setup_map(mpp, params, PARAMS_SIZE, vecs)) { + condlog(0, "%s: failed to setup map for" + " removal of path %s", mpp->alias, pp->dev); diff --git a/SPECS/device-mapper-multipath.spec b/SPECS/device-mapper-multipath.spec index f2b24d0..c900c90 100644 --- a/SPECS/device-mapper-multipath.spec +++ b/SPECS/device-mapper-multipath.spec @@ -1,7 +1,7 @@ Summary: Tools to manage multipath devices using device-mapper Name: device-mapper-multipath Version: 0.8.4 -Release: 28%{?dist}.1 +Release: 28%{?dist}.3 License: GPLv2 Group: System Environment/Base URL: http://christophe.varoqui.free.fr/ @@ -122,6 +122,7 @@ Patch00108: 0108-multipathd-Add-missing-ctype-include.patch Patch00109: 0109-multipathd-replace-libreadline-with-libedit.patch Patch00110: 0110-multipath-fix-systemd-timers-in-the-initramfs.patch Patch00111: 0111-multipathd-ignore-duplicated-multipathd-command-keys.patch +Patch00112: 0112-libmultipath-copy-mpp-hwe-from-pp-hwe.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -324,6 +325,14 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Tue Jan 17 2023 Benjamin Marzinski 0.8.4-28.3 +- Add 0112-libmultipath-copy-mpp-hwe-from-pp-hwe.patch +- Resolves: bz #2161393 + +* Thu Oct 20 2022 Benjamin Marzinski 0.8.4-28.2 +- Rebuild for rhel-8.7.0 +- Related: bz #2133995 + * Thu Oct 13 2022 Benjamin Marzinski 0.8.4-28.1 - Add 0111-multipathd-ignore-duplicated-multipathd-command-keys.patch - Resolves: bz #2133995