From e3b961a789af04190aea1fb5b862682091ac4ac2 Mon Sep 17 00:00:00 2001 From: eabdullin Date: Thu, 21 Sep 2023 18:17:40 +0000 Subject: [PATCH] import CS device-mapper-multipath-0.8.7-22.el9 --- ...athd-make-pr-registration-consistent.patch | 159 +++++++++++++++ ...086-libmultipath-make-prflag-an-enum.patch | 165 ++++++++++++++++ ...dle-no-active-paths-in-update_map_pr.patch | 152 ++++++++++++++ ...t-fix-resource-leak-in-update_map_pr.patch | 68 +++++++ SOURCES/0089-RH-Add-mpathcleanup.patch | 186 ++++++++++++++++++ ...return-an-error-if-the-config-file-i.patch | 40 ++++ SPECS/device-mapper-multipath.spec | 25 ++- 7 files changed, 794 insertions(+), 1 deletion(-) create mode 100644 SOURCES/0085-multipathd-make-pr-registration-consistent.patch create mode 100644 SOURCES/0086-libmultipath-make-prflag-an-enum.patch create mode 100644 SOURCES/0087-multipathd-handle-no-active-paths-in-update_map_pr.patch create mode 100644 SOURCES/0088-libmpathpersist-fix-resource-leak-in-update_map_pr.patch create mode 100644 SOURCES/0089-RH-Add-mpathcleanup.patch create mode 100644 SOURCES/0090-RH-make-listing-return-an-error-if-the-config-file-i.patch diff --git a/SOURCES/0085-multipathd-make-pr-registration-consistent.patch b/SOURCES/0085-multipathd-make-pr-registration-consistent.patch new file mode 100644 index 0000000..85315d2 --- /dev/null +++ b/SOURCES/0085-multipathd-make-pr-registration-consistent.patch @@ -0,0 +1,159 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 20 Dec 2022 17:41:10 -0600 +Subject: [PATCH] multipathd: make pr registration consistent + +multipathd was inconsistent on what it did with persistent reservations +when a multipath device was created. If a multipath device with a +configured reservation key was created during configure(), multipathd +would try to read the registered keys using an active path. If it saw a +matching key, it would set the prflag, but not attempt to register the +key on any of the other paths. This means that if a new path had +appeared while multipathd was not running, it wouldn't register the key +on this path. + +If the multipath device was created during ev_add_path(), multipathd +would used the added path to check if there was a matching key and if +there was, register the key only on the added path and then set the +prflag. This could be problematic if the device was created with +multiple paths, for instance because find_mutipaths was set to "yes" and +a second path just appeared. In this case, if the device happened to be +only registered on the second path, it would not get registered on the +first path. + +If the multipath device was added to multipathd during a call to +ev_add_map(), multipathd wouldn't set the prflag or register the key on +any paths. + +After a device was created with the prflag set, if a new path appeared +before the creation uevent, and multipathd was forced to delay adding +it, when it finally updated the multipath device, the key would be +registered on all paths, fixing any paths missed during creation. +However, if a new path appeared after the creation uevent, the key would +only be registered on that new path. Any paths that were missed on +creation would stay missed. + +persistent key registration needs to be handled consistently. This +patch does so by making sure that however a multipath device is added to +multipathd, it will check to see if the configured key is registered. If +it is, multipathd will set the prflag and register the key on all the +currently active paths. + +When a new path is added, multipathd will use it to check for active +keys, as before. But if it finds a matching key and prflag isn't +currently set, it will register the key on all paths. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + multipathd/main.c | 43 +++++++++++++++++++++++++++++-------------- + 1 file changed, 29 insertions(+), 14 deletions(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index a098f3c2..e7c17182 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -512,13 +512,26 @@ flush_map_nopaths(struct multipath *mpp, struct vectors *vecs) { + return false; + } + ++static void ++pr_register_active_paths(struct multipath *mpp) ++{ ++ unsigned int i, j; ++ struct path *pp; ++ struct pathgroup *pgp; ++ ++ vector_foreach_slot (mpp->pg, pgp, i) { ++ vector_foreach_slot (pgp->paths, pp, j) { ++ if ((pp->state == PATH_UP) || (pp->state == PATH_GHOST)) ++ mpath_pr_event_handle(pp); ++ } ++ } ++} ++ + static int + update_map (struct multipath *mpp, struct vectors *vecs, int new_map) + { + int retries = 3; + char *params __attribute__((cleanup(cleanup_charp))) = NULL; +- struct path *pp; +- int i; + + retry: + condlog(4, "%s: updating new map", mpp->alias); +@@ -535,15 +548,6 @@ retry: + + mpp->action = ACT_RELOAD; + +- if (mpp->prflag) { +- vector_foreach_slot(mpp->paths, pp, i) { +- if ((pp->state == PATH_UP) || (pp->state == PATH_GHOST)) { +- /* persistent reseravtion check*/ +- mpath_pr_event_handle(pp); +- } +- } +- } +- + if (setup_map(mpp, ¶ms, vecs)) { + condlog(0, "%s: failed to setup new map in update", mpp->alias); + retries = -1; +@@ -569,6 +573,11 @@ fail: + + sync_map_state(mpp); + ++ if (!mpp->prflag) ++ update_map_pr(mpp); ++ if (mpp->prflag) ++ pr_register_active_paths(mpp); ++ + if (retries < 0) + condlog(0, "%s: failed reload in new map update", mpp->alias); + return 0; +@@ -1073,6 +1082,7 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map) + int start_waiter = 0; + int ret; + int ro; ++ unsigned char prflag = 0; + + /* + * need path UID to go any further +@@ -1116,6 +1126,8 @@ rescan: + + verify_paths(mpp); + mpp->action = ACT_RELOAD; ++ prflag = mpp->prflag; ++ mpath_pr_event_handle(pp); + } else { + if (!should_multipath(pp, vecs->pathvec, vecs->mpvec)) { + orphan_path(pp, "only one path"); +@@ -1134,9 +1146,6 @@ rescan: + goto fail; /* leave path added to pathvec */ + } + +- /* persistent reservation check*/ +- mpath_pr_event_handle(pp); +- + /* ro check - if new path is ro, force map to be ro as well */ + ro = sysfs_get_ro(pp); + if (ro == 1) +@@ -1201,6 +1210,10 @@ rescan: + sync_map_state(mpp); + + if (retries >= 0) { ++ if (start_waiter) ++ update_map_pr(mpp); ++ if (mpp->prflag && !prflag) ++ pr_register_active_paths(mpp); + condlog(2, "%s [%s]: path added to devmap %s", + pp->dev, pp->dev_t, mpp->alias); + return 0; +@@ -2745,6 +2758,8 @@ configure (struct vectors * vecs) + if (remember_wwid(mpp->wwid) == 1) + trigger_paths_udev_change(mpp, true); + update_map_pr(mpp); ++ if (mpp->prflag) ++ pr_register_active_paths(mpp); + } + + /* diff --git a/SOURCES/0086-libmultipath-make-prflag-an-enum.patch b/SOURCES/0086-libmultipath-make-prflag-an-enum.patch new file mode 100644 index 0000000..29a0448 --- /dev/null +++ b/SOURCES/0086-libmultipath-make-prflag-an-enum.patch @@ -0,0 +1,165 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 20 Dec 2022 17:41:11 -0600 +Subject: [PATCH] libmultipath: make prflag an enum + +In preparation for a future patch, make prflag an enum, and change the +reply of cli_getprstatus() to a string. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + libmpathpersist/mpath_persist.c | 2 +- + libmultipath/structs.h | 8 +++++++- + multipathd/cli_handlers.c | 16 +++++++++------- + multipathd/main.c | 14 +++++++------- + 4 files changed, 24 insertions(+), 16 deletions(-) + +diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c +index 803a2a28..01e8ca25 100644 +--- a/libmpathpersist/mpath_persist.c ++++ b/libmpathpersist/mpath_persist.c +@@ -924,7 +924,7 @@ int update_map_pr(struct multipath *mpp) + + if (isFound) + { +- mpp->prflag = 1; ++ mpp->prflag = PRFLAG_SET; + condlog(2, "%s: prflag flag set.", mpp->alias ); + } + +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index 4b308561..5ec591bc 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -368,6 +368,12 @@ struct path { + + typedef int (pgpolicyfn) (struct multipath *, vector); + ++ ++enum prflag_value { ++ PRFLAG_UNSET, ++ PRFLAG_SET, ++}; ++ + struct multipath { + char wwid[WWID_SIZE]; + char alias_old[WWID_SIZE]; +@@ -441,7 +447,7 @@ struct multipath { + int prkey_source; + struct be64 reservation_key; + uint8_t sa_flags; +- unsigned char prflag; ++ int prflag; + int all_tg_pt; + struct gen_multipath generic_mp; + bool fpin_must_reload; +diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c +index 6d3a0ae2..90d2c388 100644 +--- a/multipathd/cli_handlers.c ++++ b/multipathd/cli_handlers.c +@@ -1304,6 +1304,10 @@ cli_shutdown (void * v, char ** reply, int * len, void * data) + int + cli_getprstatus (void * v, char ** reply, int * len, void * data) + { ++ static const char * const prflag_str[] = { ++ [PRFLAG_UNSET] = "unset\n", ++ [PRFLAG_SET] = "set\n", ++ }; + struct multipath * mpp; + struct vectors * vecs = (struct vectors *)data; + char * param = get_keyparam(v, MAP); +@@ -1315,9 +1319,7 @@ cli_getprstatus (void * v, char ** reply, int * len, void * data) + if (!mpp) + return 1; + +- condlog(3, "%s: prflag = %u", param, (unsigned int)mpp->prflag); +- +- *len = asprintf(reply, "%d", mpp->prflag); ++ *len = asprintf(reply, "%s", prflag_str[mpp->prflag]); + if (*len < 0) + return 1; + +@@ -1340,8 +1342,8 @@ cli_setprstatus(void * v, char ** reply, int * len, void * data) + if (!mpp) + return 1; + +- if (!mpp->prflag) { +- mpp->prflag = 1; ++ if (mpp->prflag != PRFLAG_SET) { ++ mpp->prflag = PRFLAG_SET; + condlog(2, "%s: prflag set", param); + } + +@@ -1363,8 +1365,8 @@ cli_unsetprstatus(void * v, char ** reply, int * len, void * data) + if (!mpp) + return 1; + +- if (mpp->prflag) { +- mpp->prflag = 0; ++ if (mpp->prflag != PRFLAG_UNSET) { ++ mpp->prflag = PRFLAG_UNSET; + condlog(2, "%s: prflag unset", param); + } + +diff --git a/multipathd/main.c b/multipathd/main.c +index e7c17182..532ca15b 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -573,9 +573,9 @@ fail: + + sync_map_state(mpp); + +- if (!mpp->prflag) ++ if (mpp->prflag == PRFLAG_UNSET) + update_map_pr(mpp); +- if (mpp->prflag) ++ if (mpp->prflag == PRFLAG_SET) + pr_register_active_paths(mpp); + + if (retries < 0) +@@ -1082,7 +1082,7 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map) + int start_waiter = 0; + int ret; + int ro; +- unsigned char prflag = 0; ++ unsigned char prflag = PRFLAG_UNSET; + + /* + * need path UID to go any further +@@ -1212,7 +1212,7 @@ rescan: + if (retries >= 0) { + if (start_waiter) + update_map_pr(mpp); +- if (mpp->prflag && !prflag) ++ if (mpp->prflag == PRFLAG_SET && prflag == PRFLAG_UNSET) + pr_register_active_paths(mpp); + condlog(2, "%s [%s]: path added to devmap %s", + pp->dev, pp->dev_t, mpp->alias); +@@ -2414,7 +2414,7 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks) + } + + if (newstate == PATH_UP || newstate == PATH_GHOST) { +- if (pp->mpp->prflag) { ++ if (pp->mpp->prflag == PRFLAG_SET) { + /* + * Check Persistent Reservation. + */ +@@ -2758,7 +2758,7 @@ configure (struct vectors * vecs) + if (remember_wwid(mpp->wwid) == 1) + trigger_paths_udev_change(mpp, true); + update_map_pr(mpp); +- if (mpp->prflag) ++ if (mpp->prflag == PRFLAG_SET) + pr_register_active_paths(mpp); + } + +@@ -3668,7 +3668,7 @@ void * mpath_pr_event_handler_fn (void * pathp ) + { + condlog(0,"%s: Reservation registration failed. Error: %d", pp->dev, ret); + } +- mpp->prflag = 1; ++ mpp->prflag = PRFLAG_SET; + + free(param); + out: diff --git a/SOURCES/0087-multipathd-handle-no-active-paths-in-update_map_pr.patch b/SOURCES/0087-multipathd-handle-no-active-paths-in-update_map_pr.patch new file mode 100644 index 0000000..5862a5e --- /dev/null +++ b/SOURCES/0087-multipathd-handle-no-active-paths-in-update_map_pr.patch @@ -0,0 +1,152 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 20 Dec 2022 17:41:12 -0600 +Subject: [PATCH] multipathd: handle no active paths in update_map_pr + +When a multipath device is first created, if it has a reservation key +configured, update_map_pr() will check for a matching key on the active +paths. If there were no active paths to check with, multipathd was +leaving mpp->prflag in PRFLAG_UNSET, as if there were no matching keys. +It's possible that when update_map_pr() is called, all the paths will be +in the PATH_PENDING state because the checkers haven't completed yet. In +this case, multipathd was treating the device as having no registered +keys without ever checking. + +To solve this, multipath devices now start with prflag = PRFLAG_UNKNOWN. +It will remain in this state until multipathd actually tries to get the +registered keys down a path. If the map is in this state, it will check +newly active paths, and if it finds a matching key, it will register +the key down all active paths. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + libmpathpersist/mpath_persist.c | 8 ++++++++ + libmultipath/structs.h | 1 + + multipathd/cli_handlers.c | 1 + + multipathd/main.c | 19 ++++++++++++++----- + 4 files changed, 24 insertions(+), 5 deletions(-) + +diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c +index 01e8ca25..3fc60da2 100644 +--- a/libmpathpersist/mpath_persist.c ++++ b/libmpathpersist/mpath_persist.c +@@ -879,6 +879,7 @@ int update_map_pr(struct multipath *mpp) + if (!get_be64(mpp->reservation_key)) + { + /* Nothing to do. Assuming pr mgmt feature is disabled*/ ++ mpp->prflag = PRFLAG_UNSET; + condlog(4, "%s: reservation_key not set in multipath.conf", + mpp->alias); + return MPATH_PR_SUCCESS; +@@ -890,6 +891,13 @@ int update_map_pr(struct multipath *mpp) + condlog(0,"%s : failed to alloc resp in update_map_pr", mpp->alias); + return MPATH_PR_OTHER; + } ++ if (count_active_paths(mpp) == 0) ++ { ++ condlog(0,"%s: No available paths to check pr status", ++ mpp->alias); ++ return MPATH_PR_OTHER; ++ } ++ mpp->prflag = PRFLAG_UNSET; + ret = mpath_prin_activepath(mpp, MPATH_PRIN_RKEY_SA, resp, noisy); + + if (ret != MPATH_PR_SUCCESS ) +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index 5ec591bc..c1e93e6e 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -370,6 +370,7 @@ typedef int (pgpolicyfn) (struct multipath *, vector); + + + enum prflag_value { ++ PRFLAG_UNKNOWN, + PRFLAG_UNSET, + PRFLAG_SET, + }; +diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c +index 90d2c388..f322f10f 100644 +--- a/multipathd/cli_handlers.c ++++ b/multipathd/cli_handlers.c +@@ -1305,6 +1305,7 @@ int + cli_getprstatus (void * v, char ** reply, int * len, void * data) + { + static const char * const prflag_str[] = { ++ [PRFLAG_UNKNOWN] = "unknown\n", + [PRFLAG_UNSET] = "unset\n", + [PRFLAG_SET] = "set\n", + }; +diff --git a/multipathd/main.c b/multipathd/main.c +index 532ca15b..075e7b13 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -573,7 +573,7 @@ fail: + + sync_map_state(mpp); + +- if (mpp->prflag == PRFLAG_UNSET) ++ if (mpp->prflag != PRFLAG_SET) + update_map_pr(mpp); + if (mpp->prflag == PRFLAG_SET) + pr_register_active_paths(mpp); +@@ -1212,7 +1212,7 @@ rescan: + if (retries >= 0) { + if (start_waiter) + update_map_pr(mpp); +- if (mpp->prflag == PRFLAG_SET && prflag == PRFLAG_UNSET) ++ if (mpp->prflag == PRFLAG_SET && prflag != PRFLAG_SET) + pr_register_active_paths(mpp); + condlog(2, "%s [%s]: path added to devmap %s", + pp->dev, pp->dev_t, mpp->alias); +@@ -2414,13 +2414,17 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks) + } + + if (newstate == PATH_UP || newstate == PATH_GHOST) { +- if (pp->mpp->prflag == PRFLAG_SET) { ++ if (pp->mpp->prflag != PRFLAG_UNSET) { ++ int prflag = pp->mpp->prflag; + /* + * Check Persistent Reservation. + */ + condlog(2, "%s: checking persistent " + "reservation registration", pp->dev); + mpath_pr_event_handle(pp); ++ if (pp->mpp->prflag == PRFLAG_SET && ++ prflag != PRFLAG_SET) ++ pr_register_active_paths(pp->mpp); + } + } + +@@ -3616,6 +3620,7 @@ void * mpath_pr_event_handler_fn (void * pathp ) + goto out; + } + ++ mpp->prflag = PRFLAG_UNSET; + ret = prin_do_scsi_ioctl(pp->dev, MPATH_PRIN_RKEY_SA, resp, 0); + if (ret != MPATH_PR_SUCCESS ) + { +@@ -3686,12 +3691,12 @@ int mpath_pr_event_handle(struct path *pp) + struct multipath * mpp; + + if (pp->bus != SYSFS_BUS_SCSI) +- return 0; ++ goto no_pr; + + mpp = pp->mpp; + + if (!get_be64(mpp->reservation_key)) +- return -1; ++ goto no_pr; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); +@@ -3704,4 +3709,8 @@ int mpath_pr_event_handle(struct path *pp) + pthread_attr_destroy(&attr); + rc = pthread_join(thread, NULL); + return 0; ++ ++no_pr: ++ pp->mpp->prflag = PRFLAG_UNSET; ++ return 0; + } diff --git a/SOURCES/0088-libmpathpersist-fix-resource-leak-in-update_map_pr.patch b/SOURCES/0088-libmpathpersist-fix-resource-leak-in-update_map_pr.patch new file mode 100644 index 0000000..1e3d01c --- /dev/null +++ b/SOURCES/0088-libmpathpersist-fix-resource-leak-in-update_map_pr.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 2 Feb 2023 09:20:35 +0100 +Subject: [PATCH] libmpathpersist: fix resource leak in update_map_pr() + +The "no available paths" case would leak the memory resp points to. +Found by coverity. + +Fixes: 50e2c16 ("multipathd: handle no active paths in update_map_pr") + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmpathpersist/mpath_persist.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c +index 3fc60da2..29b64937 100644 +--- a/libmpathpersist/mpath_persist.c ++++ b/libmpathpersist/mpath_persist.c +@@ -874,7 +874,7 @@ int update_map_pr(struct multipath *mpp) + int noisy=0; + struct prin_resp *resp; + unsigned int i; +- int ret, isFound; ++ int ret = MPATH_PR_OTHER, isFound; + + if (!get_be64(mpp->reservation_key)) + { +@@ -895,7 +895,7 @@ int update_map_pr(struct multipath *mpp) + { + condlog(0,"%s: No available paths to check pr status", + mpp->alias); +- return MPATH_PR_OTHER; ++ goto out; + } + mpp->prflag = PRFLAG_UNSET; + ret = mpath_prin_activepath(mpp, MPATH_PRIN_RKEY_SA, resp, noisy); +@@ -903,15 +903,15 @@ int update_map_pr(struct multipath *mpp) + if (ret != MPATH_PR_SUCCESS ) + { + condlog(0,"%s : pr in read keys service action failed Error=%d", mpp->alias, ret); +- free(resp); +- return ret; ++ goto out; + } + ++ ret = MPATH_PR_SUCCESS; ++ + if (resp->prin_descriptor.prin_readkeys.additional_length == 0 ) + { + condlog(3,"%s: No key found. Device may not be registered. ", mpp->alias); +- free(resp); +- return MPATH_PR_SUCCESS; ++ goto out; + } + + condlog(2, "%s: Multipath reservation_key: 0x%" PRIx64 " ", mpp->alias, +@@ -936,6 +936,7 @@ int update_map_pr(struct multipath *mpp) + condlog(2, "%s: prflag flag set.", mpp->alias ); + } + ++out: + free(resp); +- return MPATH_PR_SUCCESS; ++ return ret; + } diff --git a/SOURCES/0089-RH-Add-mpathcleanup.patch b/SOURCES/0089-RH-Add-mpathcleanup.patch new file mode 100644 index 0000000..8debc13 --- /dev/null +++ b/SOURCES/0089-RH-Add-mpathcleanup.patch @@ -0,0 +1,186 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 7 Jul 2023 15:25:59 -0500 +Subject: [PATCH] RH: Add mpathcleanup + +mpathcleanup is a program that will remove a multipath device as well as +all of the scsi path devices that make it up. + +Signed-off-by: Benjamin Marzinski +--- + multipath/Makefile | 2 + + multipath/mpathcleanup | 145 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 147 insertions(+) + create mode 100755 multipath/mpathcleanup + +diff --git a/multipath/Makefile b/multipath/Makefile +index f3d98012..1fc04c8d 100644 +--- a/multipath/Makefile ++++ b/multipath/Makefile +@@ -24,6 +24,7 @@ install: + $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) + $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/ + $(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/ ++ $(INSTALL_PROGRAM) -m 755 mpathcleanup $(DESTDIR)$(bindir)/ + $(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) + $(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules +@@ -40,6 +41,7 @@ uninstall: + $(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules + $(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules + $(RM) $(DESTDIR)$(bindir)/mpathconf ++ $(RM) $(DESTDIR)$(bindir)/mpathcleanup + $(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz + $(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz + $(RM) $(DESTDIR)$(man8dir)/mpathconf.8.gz +diff --git a/multipath/mpathcleanup b/multipath/mpathcleanup +new file mode 100755 +index 00000000..6fd921e4 +--- /dev/null ++++ b/multipath/mpathcleanup +@@ -0,0 +1,145 @@ ++#!/bin/bash ++# ++# Copyright (C) 2023 Red Hat, Inc. All rights reserved. ++# ++# This file is part of the device-mapper-multipath package. ++# ++# This copyrighted material is made available to anyone wishing to use, ++# modify, copy, or redistribute it subject to the terms and conditions ++# of the GNU General Public License v.2. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software Foundation, ++# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ ++unset PROGRAM FLUSH DEVICE DEVNAME MAJOR MINOR PATHDEVS PATHDEV HAVE_MULTIPATHD QUEUEING ++ ++function usage ++{ ++ echo "usage: $PROGRAM [-h] [--flush] " ++ echo "" ++ echo "remove a multipath device and its scsi path devices" ++ echo "" ++ echo "options:" ++ echo " -h, --help show this help message and exit" ++ echo " --flush disable queuing on the multipath device and" ++ echo " flush the path devices before removing" ++} ++ ++function parse_args ++{ ++ while [ -n "$1" ]; do ++ case $1 in ++ --flush) ++ FLUSH=1 ++ shift ++ ;; ++ --help | -h) ++ usage ++ exit 1 ++ ;; ++ *) ++ if [ -n "$DEVICE" ]; then ++ usage ++ exit 1 ++ fi ++ DEVICE=$1 ++ shift ++ ;; ++ esac ++ done ++} ++ ++function validate_device ++{ ++ if [ -z "$DEVICE" ]; then ++ usage ++ exit 1 ++ fi ++ if [[ "$DEVICE" =~ ^[[:digit:]]+:[[:digit:]]+$ ]]; then ++ MAJOR=${DEVICE%%:*} ++ MINOR=${DEVICE##*:} ++ DEVNAME=`dmsetup ls --target multipath | grep "($MAJOR, $MINOR)$" | awk '{print $1}'` ++ else ++ DEVNAME=`dmsetup ls --target multipath | awk '{print $1}' | grep "^$DEVICE$"` ++ fi ++ if [ -z "$DEVNAME" ]; then ++ DEVNAME=`multipath -v 1 -l $DEVICE 2>/dev/null` ++ if [ -z "$DEVNAME" ]; then ++ echo "$DEVICE is not a multipath device" ++ exit 1 ++ fi ++ # verify that this is not a native nvme multipath device ++ dmsetup ls --target multipath | awk '{print $1}' | grep -q "^$DEVNAME$" ++ if test $? -eq 1; then ++ echo "$DEVICE is not a device-mapper multipath device" ++ exit 1 ++ fi ++ fi ++ if [ -z "$MINOR" ]; then ++ MINOR=`dmsetup info -c --noheadings -o minor $DEVNAME` ++ fi ++} ++ ++function get_paths ++{ ++ PATHDEVS=`ls /sys/block/dm-$MINOR/slaves` ++ for PATHDEV in $PATHDEVS; do ++ if [[ ! "$PATHDEV" =~ ^sd[a-z]+$ ]]; then ++ echo "$PATHDEV is not a scsi device. $PROGRAM only works with scsi devices" ++ exit 1 ++ fi ++ done ++} ++ ++function remove_devs ++{ ++ pidof multipathd > /dev/null ++ HAVE_MULTIPATHD=$? ++ multipath -v2 -l "$DEVNAME" | grep features | grep -q queue_if_no_path ++ QUEUEING=$? ++ if [ -n "$FLUSH" ] && [ "$QUEUEING" -eq 0 ]; then ++ if test $HAVE_MULTIPATHD -eq 0; then ++ multipathd disablequeueing map "$DEVNAME" > /dev/null ++ else ++ dmsetup message "$DEVNAME" 0 fail_if_no_path ++ fi ++ sleep 1 ++ fi ++ if test $HAVE_MULTIPATHD -eq 0; then ++ multipath -f "$DEVNAME" ++ else ++ multipathd -Df "$DEVNAME" ++ fi ++ if test $? -eq 1; then ++ echo "$DEVICE cannot be removed" ++ exit 1 ++ fi ++ for PATHDEV in $PATHDEVS; do ++ if [ -n "$FLUSH" ]; then ++ blockdev --flushbufs /dev/"$PATHDEV" ++ fi ++ echo 1 > /sys/block/"$PATHDEV"/device/delete ++ done ++} ++ ++function verify_removal ++{ ++ multipath -v 1 -d $DEVNAME | grep -q "^$DEVNAME$" ++ if test $? -eq 0; then ++ echo "$DEVICE removed but path devices still exist" ++ exit 1 ++ fi ++ multipath -v 1 -l $DEVNAME | grep -q "^$DEVNAME$" ++ if test $? -eq 0; then ++ echo "$DEVICE removal succeeded, but device still exists" ++ exit 1 ++ fi ++} ++ ++PROGRAM="$0" ++parse_args "$@" ++validate_device ++get_paths ++remove_devs ++verify_removal diff --git a/SOURCES/0090-RH-make-listing-return-an-error-if-the-config-file-i.patch b/SOURCES/0090-RH-make-listing-return-an-error-if-the-config-file-i.patch new file mode 100644 index 0000000..6052ae7 --- /dev/null +++ b/SOURCES/0090-RH-make-listing-return-an-error-if-the-config-file-i.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 12 Jul 2023 12:56:48 -0500 +Subject: [PATCH] RH: make listing return an error if the config file is + missing + +Signed-off-by: Benjamin Marzinski +--- + multipath/main.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/multipath/main.c b/multipath/main.c +index e056c51c..f1077421 100644 +--- a/multipath/main.c ++++ b/multipath/main.c +@@ -874,11 +874,14 @@ main (int argc, char *argv[]) + struct config *conf; + int retries = -1; + bool enable_foreign = false; ++ bool have_config; ++ struct stat buf; + + libmultipath_init(); + if (atexit(dm_lib_exit) || atexit(libmultipath_exit)) + condlog(1, "failed to register cleanup handler for libmultipath: %m"); + logsink = LOGSINK_STDERR_WITH_TIME; ++ have_config = (stat(DEFAULT_CONFIGFILE, &buf) == 0); + if (init_config(DEFAULT_CONFIGFILE)) + exit(RTVL_FAIL); + if (atexit(uninit_config)) +@@ -1129,6 +1132,9 @@ main (int argc, char *argv[]) + while ((r = configure(conf, cmd, dev_type, dev)) == RTVL_RETRY) + condlog(3, "restart multipath configuration process"); + ++ if (!have_config && r == RTVL_OK && ++ (cmd == CMD_LIST_SHORT || cmd == CMD_LIST_LONG)) ++ r = RTVL_FAIL; + out: + put_multipath_config(conf); + if (dev) diff --git a/SPECS/device-mapper-multipath.spec b/SPECS/device-mapper-multipath.spec index 2c8e86f..8863f91 100644 --- a/SPECS/device-mapper-multipath.spec +++ b/SPECS/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.8.7 -Release: 20%{?dist} +Release: 22%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ @@ -94,6 +94,13 @@ Patch0081: 0081-libmultipath-cleanup-ACT_CREATE-code-in-select_actio.patch Patch0082: 0082-libmultipath-keep-renames-from-stopping-other-multip.patch Patch0083: 0083-multipath.rules-fix-smart-bug-with-failed-valid-path.patch Patch0084: 0084-libmultipath-limit-paths-that-can-get-wwid-from-envi.patch +Patch0085: 0085-multipathd-make-pr-registration-consistent.patch +Patch0086: 0086-libmultipath-make-prflag-an-enum.patch +Patch0087: 0087-multipathd-handle-no-active-paths-in-update_map_pr.patch +Patch0088: 0088-libmpathpersist-fix-resource-leak-in-update_map_pr.patch +Patch0089: 0089-RH-Add-mpathcleanup.patch +Patch0090: 0090-RH-make-listing-return-an-error-if-the-config-file-i.patch + # runtime @@ -228,6 +235,7 @@ fi %{_sbindir}/multipath %{_sbindir}/multipathd %{_sbindir}/mpathconf +%{_sbindir}/mpathcleanup %{_sbindir}/mpathpersist %{_unitdir}/multipathd.service %{_unitdir}/multipathd.socket @@ -295,6 +303,21 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Fri Jul 28 2023 Benjamin Marzinski - 0.8.7-22 +- Add 0089-RH-Add-mpathcleanup.patch + * Fixes RHEL-782 +- Add 0090-RH-make-listing-return-an-error-if-the-config-file-i.patch +- Install mpathcleanup + * Fixes RHEL-781 +- Resolves: #781, #782 + +* Tue Mar 14 2023 Benjamin Marzinski - 0.8.7-21 +- Add 0085-multipathd-make-pr-registration-consistent.patch +- Add 0086-libmultipath-make-prflag-an-enum.patch +- Add 0087-multipathd-handle-no-active-paths-in-update_map_pr.patch +- Add 0088-libmpathpersist-fix-resource-leak-in-update_map_pr.patch +- Resolves: bz #2164869 + * Thu Feb 9 2023 Benjamin Marzinski - 0.8.7-20 - Add 0083-multipath.rules-fix-smart-bug-with-failed-valid-path.patch - Add 0084-libmultipath-limit-paths-that-can-get-wwid-from-envi.patch