diff --git a/0062-multipathd-factor-out-the-code-to-flush-a-map-with-n.patch b/0062-multipathd-factor-out-the-code-to-flush-a-map-with-n.patch new file mode 100644 index 0000000..6728585 --- /dev/null +++ b/0062-multipathd-factor-out-the-code-to-flush-a-map-with-n.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 9 Aug 2022 16:46:26 -0500 +Subject: [PATCH] multipathd: factor out the code to flush a map with no paths + +The code to flush a multipath device because all of its paths have +been removed will be used by another caller, so factor it out of +ev_remove_path(). + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + multipathd/main.c | 56 ++++++++++++++++++++++++----------------------- + 1 file changed, 29 insertions(+), 27 deletions(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index ed2515e5..b00eae3f 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -488,6 +488,30 @@ int update_multipath (struct vectors *vecs, char *mapname, int reset) + return 0; + } + ++static bool ++flush_map_nopaths(struct multipath *mpp, struct vectors *vecs) { ++ char alias[WWID_SIZE]; ++ ++ /* ++ * flush_map will fail if the device is open ++ */ ++ strlcpy(alias, mpp->alias, WWID_SIZE); ++ if (mpp->flush_on_last_del == FLUSH_ENABLED) { ++ condlog(2, "%s Last path deleted, disabling queueing", ++ mpp->alias); ++ mpp->retry_tick = 0; ++ mpp->no_path_retry = NO_PATH_RETRY_FAIL; ++ mpp->disable_queueing = 1; ++ mpp->stat_map_failures++; ++ dm_queue_if_no_path(mpp->alias, 0); ++ } ++ if (!flush_map(mpp, vecs, 1)) { ++ condlog(2, "%s: removed map after removing all paths", alias); ++ return true; ++ } ++ return false; ++} ++ + static int + update_map (struct multipath *mpp, struct vectors *vecs, int new_map) + { +@@ -1247,34 +1271,12 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map) + vector_del_slot(mpp->paths, i); + + /* +- * remove the map IF removing the last path ++ * remove the map IF removing the last path. If ++ * flush_map_nopaths succeeds, the path has been removed. + */ +- if (VECTOR_SIZE(mpp->paths) == 0) { +- char alias[WWID_SIZE]; +- +- /* +- * flush_map will fail if the device is open +- */ +- strlcpy(alias, mpp->alias, WWID_SIZE); +- if (mpp->flush_on_last_del == FLUSH_ENABLED) { +- condlog(2, "%s Last path deleted, disabling queueing", mpp->alias); +- mpp->retry_tick = 0; +- mpp->no_path_retry = NO_PATH_RETRY_FAIL; +- mpp->disable_queueing = 1; +- mpp->stat_map_failures++; +- dm_queue_if_no_path(mpp->alias, 0); +- } +- if (!flush_map(mpp, vecs, 1)) { +- condlog(2, "%s: removed map after" +- " removing all paths", +- alias); +- /* flush_map() has freed the path */ +- goto out; +- } +- /* +- * Not an error, continue +- */ +- } ++ if (VECTOR_SIZE(mpp->paths) == 0 && ++ flush_map_nopaths(mpp, vecs)) ++ goto out; + + if (setup_map(mpp, ¶ms, vecs)) { + condlog(0, "%s: failed to setup map for" diff --git a/0063-libmultipath-return-success-if-we-raced-to-remove-a-.patch b/0063-libmultipath-return-success-if-we-raced-to-remove-a-.patch new file mode 100644 index 0000000..22b8d7e --- /dev/null +++ b/0063-libmultipath-return-success-if-we-raced-to-remove-a-.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 9 Aug 2022 16:46:27 -0500 +Subject: [PATCH] libmultipath: return success if we raced to remove a map and + lost + +_dm_flush_map() was returning failure if it failed to remove a map, +even if that was because the map had already been removed. Return +success in this case. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + libmultipath/devmapper.c | 4 ++++ + multipathd/main.c | 4 ---- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c +index 1ff75c81..4b2e8a15 100644 +--- a/libmultipath/devmapper.c ++++ b/libmultipath/devmapper.c +@@ -1104,6 +1104,10 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, + } + condlog(4, "multipath map %s removed", mapname); + return 0; ++ } else if (dm_is_mpath(mapname) != 1) { ++ condlog(4, "multipath map %s removed externally", ++ mapname); ++ return 0; /*we raced with someone else removing it */ + } else { + condlog(2, "failed to remove multipath map %s", + mapname); +diff --git a/multipathd/main.c b/multipathd/main.c +index b00eae3f..68ee067b 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -685,10 +685,6 @@ flush_map(struct multipath * mpp, struct vectors * vecs, int nopaths) + * the spurious uevent we may generate with the dm_flush_map call below + */ + if (r) { +- /* +- * May not really be an error -- if the map was already flushed +- * from the device mapper by dmsetup(8) for instance. +- */ + if (r == 1) + condlog(0, "%s: can't flush", mpp->alias); + else { diff --git a/0064-multipathd-Handle-losing-all-path-in-update_map.patch b/0064-multipathd-Handle-losing-all-path-in-update_map.patch new file mode 100644 index 0000000..8045b3d --- /dev/null +++ b/0064-multipathd-Handle-losing-all-path-in-update_map.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 9 Aug 2022 16:46:28 -0500 +Subject: [PATCH] multipathd: Handle losing all path in update_map + +Its possible that when a multipath device is being updated, it will end +up that all the paths for it are gone. This can happen if paths are +added and then removed again before multipathd processes the uevent for +the newly created multipath device. In this case multipathd wasn't +taking the proper action for the case where all the paths had been +removed. If flush_on_last_del was set, multipathd wasn't disabling +flushing and if deferred_remove was set, it wasn't doing a deferred +remove. Multipathd should call flush_map_nopaths(), just like +ev_remove_path() does when the last path is removed. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + multipathd/main.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/multipathd/main.c b/multipathd/main.c +index 68ee067b..d2c48d3b 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -529,6 +529,10 @@ retry: + goto fail; + } + verify_paths(mpp); ++ if (VECTOR_SIZE(mpp->paths) == 0 && ++ flush_map_nopaths(mpp, vecs)) ++ return 1; ++ + mpp->action = ACT_RELOAD; + + if (mpp->prflag) { diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index c137741..dd1f40b 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.8.7 -Release: 12%{?dist} +Release: 13%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ @@ -71,6 +71,9 @@ Patch0058: 0058-libmultipath-unset-detect_checker-for-clariion-Unity.patch Patch0059: 0059-multipathd-Add-missing-ctype-include.patch Patch0060: 0060-multipathd-replace-libreadline-with-libedit.patch Patch0061: 0061-multipath-fix-systemd-timers-in-the-initramfs.patch +Patch0062: 0062-multipathd-factor-out-the-code-to-flush-a-map-with-n.patch +Patch0063: 0063-libmultipath-return-success-if-we-raced-to-remove-a-.patch +Patch0064: 0064-multipathd-Handle-losing-all-path-in-update_map.patch # runtime @@ -271,6 +274,12 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Fri Sep 9 2022 Benjamin Marzinski - 0.8.7-13 +- Add 0062-multipathd-factor-out-the-code-to-flush-a-map-with-n.patch +- Add 0063-libmultipath-return-success-if-we-raced-to-remove-a-.patch +- Add 0064-multipathd-Handle-losing-all-path-in-update_map.patch +- Resolves: bz #2125357 + * Wed Aug 24 2022 Benjamin Marzinski - 0.8.7-12 - Add 0061-multipath-fix-systemd-timers-in-the-initramfs.patch - Resolves: bz #2121277