From 0761930b9e78736f3fe8d59b79f35a5754ea2929 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Tue, 16 May 2023 17:02:58 -0500 Subject: [PATCH 01/29] device-mapper-multipath-0.9.5-1 Update to the latest upstream release * Previous patches 0001-0015 are included in the source tarball Rename redhat patches * Previous patches 0016-0027 are now patches 0001-0012 --- .gitignore | 1 + ... 0001-RH-fixup-udev-rules-for-redhat.patch | 0 ...athd-make-pr-registration-consistent.patch | 159 ----- ...property-blacklist-exception-builtin.patch | 0 0002-libmultipath-make-prflag-an-enum.patch | 166 ----- ...RH-don-t-start-without-a-config-file.patch | 4 +- ...dle-no-active-paths-in-update_map_pr.patch | 152 ----- ...H-Fix-nvme-function-missing-argument.patch | 0 ...missing-newline-to-cli_del_map-reply.patch | 24 - ... 0005-RH-use-rpm-optflags-if-present.patch | 0 ...kip-extra-vector-work-in-remove_maps.patch | 33 - ...hconf.patch => 0006-RH-add-mpathconf.patch | 0 ...han-paths-if-coalesce_paths-frees-ne.patch | 41 -- ...om-kernel-cmdline-mpath.wwids-with-A.patch | 8 +- ...path_valid-check-if-device-is-in-use.patch | 609 ------------------ ...-default-find_mutipaths-value-to-off.patch | 0 ...use-conf-timeout-for-updating-persis.patch | 55 -- ...empt-to-get-ANA-info-via-sysfs-first.patch | 0 ...hinfo-don-t-fail-for-devices-lacking.patch | 77 --- ...-parse_vpd_pg83-match-scsi_id-output.patch | 4 +- ...multipath-bump-ABI-version-to-18.0.0.patch | 26 - ...si-device-handlers-to-modules-load.d.patch | 0 ...-select_reload_action-in-select_acti.patch | 39 -- ...-RH-compile-with-libreadline-support.patch | 0 ...ect-resize-action-even-if-reload-is-.patch | 46 -- ...anup-ACT_CREATE-code-in-select_actio.patch | 68 -- ...p-renames-from-stopping-other-multip.patch | 186 ------ ...t-fix-resource-leak-in-update_map_pr.patch | 68 -- device-mapper-multipath.spec | 55 +- sources | 2 +- 30 files changed, 33 insertions(+), 1790 deletions(-) rename 0016-RH-fixup-udev-rules-for-redhat.patch => 0001-RH-fixup-udev-rules-for-redhat.patch (100%) delete mode 100644 0001-multipathd-make-pr-registration-consistent.patch rename 0017-RH-Remove-the-property-blacklist-exception-builtin.patch => 0002-RH-Remove-the-property-blacklist-exception-builtin.patch (100%) delete mode 100644 0002-libmultipath-make-prflag-an-enum.patch rename 0018-RH-don-t-start-without-a-config-file.patch => 0003-RH-don-t-start-without-a-config-file.patch (98%) delete mode 100644 0003-multipathd-handle-no-active-paths-in-update_map_pr.patch rename 0019-RH-Fix-nvme-function-missing-argument.patch => 0004-RH-Fix-nvme-function-missing-argument.patch (100%) delete mode 100644 0004-multipathd-add-missing-newline-to-cli_del_map-reply.patch rename 0020-RH-use-rpm-optflags-if-present.patch => 0005-RH-use-rpm-optflags-if-present.patch (100%) delete mode 100644 0005-libmultipath-skip-extra-vector-work-in-remove_maps.patch rename 0021-RH-add-mpathconf.patch => 0006-RH-add-mpathconf.patch (100%) delete mode 100644 0006-libmultipath-orphan-paths-if-coalesce_paths-frees-ne.patch rename 0022-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch => 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch (96%) delete mode 100644 0007-libmultipath-is_path_valid-check-if-device-is-in-use.patch rename 0023-RH-reset-default-find_mutipaths-value-to-off.patch => 0008-RH-reset-default-find_mutipaths-value-to-off.patch (100%) delete mode 100644 0008-libmpathpersist-use-conf-timeout-for-updating-persis.patch rename 0024-RH-attempt-to-get-ANA-info-via-sysfs-first.patch => 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch (100%) delete mode 100644 0009-libmultipath-pathinfo-don-t-fail-for-devices-lacking.patch rename 0025-RH-make-parse_vpd_pg83-match-scsi_id-output.patch => 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch (97%) delete mode 100644 0010-libmultipath-bump-ABI-version-to-18.0.0.patch rename 0026-RH-add-scsi-device-handlers-to-modules-load.d.patch => 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch (100%) delete mode 100644 0011-libmultipath-use-select_reload_action-in-select_acti.patch rename 0027-RH-compile-with-libreadline-support.patch => 0012-RH-compile-with-libreadline-support.patch (100%) delete mode 100644 0012-libmultipath-select-resize-action-even-if-reload-is-.patch delete mode 100644 0013-libmultipath-cleanup-ACT_CREATE-code-in-select_actio.patch delete mode 100644 0014-libmultipath-keep-renames-from-stopping-other-multip.patch delete mode 100644 0015-libmpathpersist-fix-resource-leak-in-update_map_pr.patch diff --git a/.gitignore b/.gitignore index 1ca930c..18226b9 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ multipath-tools-091027.tar.gz /multipath-tools-0.9.0.tgz /multipath-tools-0.9.3.tgz /multipath-tools-0.9.4.tgz +/multipath-tools-0.9.5.tgz diff --git a/0016-RH-fixup-udev-rules-for-redhat.patch b/0001-RH-fixup-udev-rules-for-redhat.patch similarity index 100% rename from 0016-RH-fixup-udev-rules-for-redhat.patch rename to 0001-RH-fixup-udev-rules-for-redhat.patch diff --git a/0001-multipathd-make-pr-registration-consistent.patch b/0001-multipathd-make-pr-registration-consistent.patch deleted file mode 100644 index 47c380a..0000000 --- a/0001-multipathd-make-pr-registration-consistent.patch +++ /dev/null @@ -1,159 +0,0 @@ -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 1e1b254f..f7212d7b 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -586,13 +586,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); -@@ -609,15 +622,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 reservation 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; -@@ -643,6 +647,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; -@@ -1191,6 +1200,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 -@@ -1234,6 +1244,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"); -@@ -1252,9 +1264,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) -@@ -1319,6 +1328,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; -@@ -2852,6 +2865,8 @@ configure (struct vectors * vecs, enum force_reload_types reload_type) - 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/0017-RH-Remove-the-property-blacklist-exception-builtin.patch b/0002-RH-Remove-the-property-blacklist-exception-builtin.patch similarity index 100% rename from 0017-RH-Remove-the-property-blacklist-exception-builtin.patch rename to 0002-RH-Remove-the-property-blacklist-exception-builtin.patch diff --git a/0002-libmultipath-make-prflag-an-enum.patch b/0002-libmultipath-make-prflag-an-enum.patch deleted file mode 100644 index 304f731..0000000 --- a/0002-libmultipath-make-prflag-an-enum.patch +++ /dev/null @@ -1,166 +0,0 @@ -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_int.c | 2 +- - libmultipath/structs.h | 8 +++++++- - multipathd/cli_handlers.c | 17 +++++++++-------- - multipathd/main.c | 14 +++++++------- - 4 files changed, 24 insertions(+), 17 deletions(-) - -diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c -index 6924b379..a84d9474 100644 ---- a/libmpathpersist/mpath_persist_int.c -+++ b/libmpathpersist/mpath_persist_int.c -@@ -783,7 +783,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 9e2c1ab0..f2265300 100644 ---- a/libmultipath/structs.h -+++ b/libmultipath/structs.h -@@ -375,6 +375,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]; -@@ -449,7 +455,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 e65fb75c..7ee2729f 100644 ---- a/multipathd/cli_handlers.c -+++ b/multipathd/cli_handlers.c -@@ -1277,6 +1277,10 @@ cli_shutdown (void * v, struct strbuf *reply, void * data) - static int - cli_getprstatus (void * v, struct strbuf *reply, 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, KEY_MAP); -@@ -1287,10 +1291,7 @@ cli_getprstatus (void * v, struct strbuf *reply, void * data) - if (!mpp) - return 1; - -- condlog(3, "%s: prflag = %u", param, (unsigned int)mpp->prflag); -- -- if (print_strbuf(reply, "%d", mpp->prflag) < 0) -- return 1; -+ append_strbuf_str(reply, prflag_str[mpp->prflag]); - - condlog(3, "%s: reply = %s", param, get_strbuf_str(reply)); - -@@ -1310,8 +1311,8 @@ cli_setprstatus(void * v, struct strbuf *reply, 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); - } - -@@ -1332,8 +1333,8 @@ cli_unsetprstatus(void * v, struct strbuf *reply, 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 f7212d7b..722235c7 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -647,9 +647,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) -@@ -1200,7 +1200,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 -@@ -1330,7 +1330,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); -@@ -2492,7 +2492,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. - */ -@@ -2865,7 +2865,7 @@ configure (struct vectors * vecs, enum force_reload_types reload_type) - 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); - } - -@@ -3840,7 +3840,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/0018-RH-don-t-start-without-a-config-file.patch b/0003-RH-don-t-start-without-a-config-file.patch similarity index 98% rename from 0018-RH-don-t-start-without-a-config-file.patch rename to 0003-RH-don-t-start-without-a-config-file.patch index c957e2f..e6e03b4 100644 --- a/0018-RH-don-t-start-without-a-config-file.patch +++ b/0003-RH-don-t-start-without-a-config-file.patch @@ -57,7 +57,7 @@ index 87947469..0dc89c16 100644 enum devtypes { DEV_NONE, diff --git a/multipath/multipath.rules.in b/multipath/multipath.rules.in -index 8d3cf33a..5c4447a2 100644 +index 6f123760..70b69a06 100644 --- a/multipath/multipath.rules.in +++ b/multipath/multipath.rules.in @@ -9,6 +9,7 @@ IMPORT{cmdline}="nompath" @@ -82,7 +82,7 @@ index bdf102eb..a16a0bd5 100644 . .\" ---------------------------------------------------------------------------- diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service -index aec62dbb..d76f94f9 100644 +index 5a9cde12..311f49c7 100644 --- a/multipathd/multipathd.service +++ b/multipathd/multipathd.service @@ -6,6 +6,7 @@ Wants=systemd-udevd-kernel.socket diff --git a/0003-multipathd-handle-no-active-paths-in-update_map_pr.patch b/0003-multipathd-handle-no-active-paths-in-update_map_pr.patch deleted file mode 100644 index 59dd10f..0000000 --- a/0003-multipathd-handle-no-active-paths-in-update_map_pr.patch +++ /dev/null @@ -1,152 +0,0 @@ -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_int.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_int.c b/libmpathpersist/mpath_persist_int.c -index a84d9474..8b52b746 100644 ---- a/libmpathpersist/mpath_persist_int.c -+++ b/libmpathpersist/mpath_persist_int.c -@@ -738,6 +738,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; -@@ -749,6 +750,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 f2265300..e2294323 100644 ---- a/libmultipath/structs.h -+++ b/libmultipath/structs.h -@@ -377,6 +377,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 7ee2729f..ec5db1b8 100644 ---- a/multipathd/cli_handlers.c -+++ b/multipathd/cli_handlers.c -@@ -1278,6 +1278,7 @@ static int - cli_getprstatus (void * v, struct strbuf *reply, 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 722235c7..bdeffe76 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -647,7 +647,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); -@@ -1330,7 +1330,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); -@@ -2492,13 +2492,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); - } - } - -@@ -3788,6 +3792,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 ) - { -@@ -3858,12 +3863,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); -@@ -3876,4 +3881,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/0019-RH-Fix-nvme-function-missing-argument.patch b/0004-RH-Fix-nvme-function-missing-argument.patch similarity index 100% rename from 0019-RH-Fix-nvme-function-missing-argument.patch rename to 0004-RH-Fix-nvme-function-missing-argument.patch diff --git a/0004-multipathd-add-missing-newline-to-cli_del_map-reply.patch b/0004-multipathd-add-missing-newline-to-cli_del_map-reply.patch deleted file mode 100644 index 085fd70..0000000 --- a/0004-multipathd-add-missing-newline-to-cli_del_map-reply.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Tue, 20 Dec 2022 17:41:13 -0600 -Subject: [PATCH] multipathd: add missing newline to cli_del_map reply - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck ---- - multipathd/cli_handlers.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c -index ec5db1b8..44bf43df 100644 ---- a/multipathd/cli_handlers.c -+++ b/multipathd/cli_handlers.c -@@ -760,7 +760,7 @@ cli_del_map (void * v, struct strbuf *reply, void * data) - } - rc = ev_remove_map(param, alias, minor, vecs); - if (rc == 2) -- append_strbuf_str(reply, "delayed"); -+ append_strbuf_str(reply, "delayed\n"); - - free(alias); - return rc; diff --git a/0020-RH-use-rpm-optflags-if-present.patch b/0005-RH-use-rpm-optflags-if-present.patch similarity index 100% rename from 0020-RH-use-rpm-optflags-if-present.patch rename to 0005-RH-use-rpm-optflags-if-present.patch diff --git a/0005-libmultipath-skip-extra-vector-work-in-remove_maps.patch b/0005-libmultipath-skip-extra-vector-work-in-remove_maps.patch deleted file mode 100644 index ee08327..0000000 --- a/0005-libmultipath-skip-extra-vector-work-in-remove_maps.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Tue, 20 Dec 2022 17:41:14 -0600 -Subject: [PATCH] libmultipath: skip extra vector work in remove_maps - -Instead of repeatedly removing the first vector element, and shifting -the rest to fill in, call remove_map() without a vector, so it just -frees the devices. The vector will be completely cleaned up by -vector_free() immediately afterwards. - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck ---- - libmultipath/structs_vec.c | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - -diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c -index 5a618767..f3fdc5a6 100644 ---- a/libmultipath/structs_vec.c -+++ b/libmultipath/structs_vec.c -@@ -392,10 +392,8 @@ remove_maps(struct vectors * vecs) - if (!vecs) - return; - -- vector_foreach_slot (vecs->mpvec, mpp, i) { -- remove_map(mpp, vecs->pathvec, vecs->mpvec); -- i--; -- } -+ vector_foreach_slot (vecs->mpvec, mpp, i) -+ remove_map(mpp, vecs->pathvec, NULL); - - vector_free(vecs->mpvec); - vecs->mpvec = NULL; diff --git a/0021-RH-add-mpathconf.patch b/0006-RH-add-mpathconf.patch similarity index 100% rename from 0021-RH-add-mpathconf.patch rename to 0006-RH-add-mpathconf.patch diff --git a/0006-libmultipath-orphan-paths-if-coalesce_paths-frees-ne.patch b/0006-libmultipath-orphan-paths-if-coalesce_paths-frees-ne.patch deleted file mode 100644 index f545df7..0000000 --- a/0006-libmultipath-orphan-paths-if-coalesce_paths-frees-ne.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Tue, 20 Dec 2022 17:41:15 -0600 -Subject: [PATCH] libmultipath: orphan paths if coalesce_paths frees newmp - -If coalesce_paths() is called without a mpvec, it will free all the -multipath devices on newmp at the end. This will clear pp->mpp from the -path, but it doesn't completely unitialize them. cli_add_map() can call -coalsce_paths() this way, when adding a device that doesn't currently -exist. cli_add_map() first creates the device in the kernel, and then -calls ev_add_map() to add it to multipathd. If something goes wrong in -ev_add_map(), the paths will still be initialized, even though they're -orphans. - -Fix this by calling remove_map() to orphan the paths that belong to -the multipath devices being deleted by coalesce_paths(). - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck ---- - libmultipath/configure.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index e551047a..e689f8a7 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -1273,8 +1273,11 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid, - ret = CP_OK; - out: - free(size_mismatch_seen); -- if (!mpvec) -- free_multipathvec(newmp, KEEP_PATHS); -+ if (!mpvec) { -+ vector_foreach_slot (newmp, mpp, i) -+ remove_map(mpp, vecs->pathvec, NULL); -+ vector_free(newmp); -+ } - return ret; - } - diff --git a/0022-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch b/0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch similarity index 96% rename from 0022-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch rename to 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch index c98543b..714a1bb 100644 --- a/0022-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +++ b/0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch @@ -20,7 +20,7 @@ Signed-off-by: Benjamin Marzinski 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/multipath/main.c b/multipath/main.c -index b9f360b4..5eb752ee 100644 +index 90f940f1..3549740a 100644 --- a/multipath/main.c +++ b/multipath/main.c @@ -120,7 +120,7 @@ usage (char * progname) @@ -92,7 +92,7 @@ index b9f360b4..5eb752ee 100644 static int configure (struct config *conf, enum mpath_cmds cmd, enum devtypes dev_type, char *devpath) -@@ -840,7 +886,7 @@ main (int argc, char *argv[]) +@@ -842,7 +888,7 @@ main (int argc, char *argv[]) conf->force_sync = 1; if (atexit(cleanup_vecs)) condlog(1, "failed to register cleanup handler for vecs: %m"); @@ -101,7 +101,7 @@ index b9f360b4..5eb752ee 100644 switch(arg) { case 'v': if (!isdigit(optarg[0])) { -@@ -911,6 +957,10 @@ main (int argc, char *argv[]) +@@ -913,6 +959,10 @@ main (int argc, char *argv[]) case 'T': cmd = CMD_DUMP_CONFIG; break; @@ -138,7 +138,7 @@ index 88149d53..072a03ee 100644 Remove the WWID for the specified device from the WWIDs file. . diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service -index d76f94f9..bb5f383a 100644 +index 311f49c7..5324f4bc 100644 --- a/multipathd/multipathd.service +++ b/multipathd/multipathd.service @@ -17,6 +17,7 @@ ConditionVirtualization=!container diff --git a/0007-libmultipath-is_path_valid-check-if-device-is-in-use.patch b/0007-libmultipath-is_path_valid-check-if-device-is-in-use.patch deleted file mode 100644 index 6ffa6fc..0000000 --- a/0007-libmultipath-is_path_valid-check-if-device-is-in-use.patch +++ /dev/null @@ -1,609 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Wed, 9 Nov 2022 21:20:58 +0100 -Subject: [PATCH] libmultipath: is_path_valid(): check if device is in use - -To check whether we will be able to add a given device can be part -of a multipath map, we have two tests in check_path_valid(): -released_to_systemd() and the O_EXCL test. The former isn't helpful -if "multipath -u" is called for the first time for a given device, -and the latter is only used in the "find_multipaths smart" case, because -actively opening the device with O_EXCL, even for a very short time, is prone -to races with other processes. - -It turns out that this may cause issues in some scenarios. We saw problems in -once case where "find_multipaths greedy" was used with a single -non-multipahted root disk and a very large number of multipath LUNs. -The root disk would first be classified as multipath device. multipathd -would try to create a map, fail (because the disk was mounted) and -trigger another uevent. But because of the very large number of multipath -devices, this event was queued up behind thousands of other events, and -the root device timed out eventually. - -While a simple workaround for the given problem would be proper blacklisting -or using a different find_multipaths mode, I am proposing a different -solution here. An additional test is added in is_path_valid() which -checks whether the given device is currently in use by 1. sysfs holders, -2. mounts (from /proc/self/mountinfo) or 3. swaps (from /proc/swaps). 2. -and 3. are similar to systemd's device detection after switching root. -This must not only be done for the device itself, but also for all its -partitions. For mountinfo and swaps, libmount is utilized. - -With this patch, "multipath -u" will make devices with mounted or otherwise -used partitions available to systemd early, without waiting for multipathd -to fail setting up the map and re-triggering an uevent. This should avoid -the issue described above even without blacklisting. The downside of it -is a longer runtime of "multipath -u" for almost all devices, in particular -for real multipath devices. The runtime required for the new checks was in the -order of 0.1ms-1ms in my tests. Moreover, there is a certain risk that devices may -wrongly classified as non-multipath because of transient mounts or holders -created by other processes. - -To make this code compile on older distributions, we need some additional -checks in create-config.mk. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - .github/workflows/build-and-unittest.yaml | 2 +- - create-config.mk | 11 +- - libmpathutil/libmpathutil.version | 6 + - libmpathutil/util.c | 12 + - libmpathutil/util.h | 2 + - libmultipath/Makefile | 2 +- - libmultipath/alias.c | 11 - - libmultipath/valid.c | 270 ++++++++++++++++++++++ - tests/Makefile | 2 +- - tests/valid.c | 48 ++++ - 10 files changed, 351 insertions(+), 15 deletions(-) - -diff --git a/.github/workflows/build-and-unittest.yaml b/.github/workflows/build-and-unittest.yaml -index abf17bf0..9e6c0e89 100644 ---- a/.github/workflows/build-and-unittest.yaml -+++ b/.github/workflows/build-and-unittest.yaml -@@ -31,7 +31,7 @@ jobs: - sudo apt-get install --yes gcc - make perl-base pkg-config valgrind - libdevmapper-dev libreadline-dev libaio-dev libsystemd-dev -- libudev-dev libjson-c-dev liburcu-dev libcmocka-dev libedit-dev -+ libudev-dev libjson-c-dev liburcu-dev libcmocka-dev libedit-dev libmount-dev - - name: build - run: make -Orecurse -j$(grep -c ^processor /proc/cpuinfo) READLINE=${{ matrix.rl }} - - name: test -diff --git a/create-config.mk b/create-config.mk -index 2a95ec56..f128375f 100644 ---- a/create-config.mk -+++ b/create-config.mk -@@ -23,7 +23,7 @@ check_cmd = $(shell \ - - # Check whether a function with name $1 has been declared in header file $2. - check_func = $(shell \ -- if grep -Eq "^[^[:blank:]]+[[:blank:]]+$1[[:blank:]]*(.*)*" "$2"; then \ -+ if grep -Eq "^(extern[[:blank:]]+)?[^[:blank:]]+[[:blank:]]+$1[[:blank:]]*(.*)*" "$2"; then \ - found=1; \ - status="yes"; \ - else \ -@@ -104,6 +104,15 @@ ifneq ($(call check_var,ELS_DTAG_LNK_INTEGRITY,$(kernel_incdir)/scsi/fc/fc_els.h - FPIN_SUPPORT = 1 - endif - -+libmount_h := $(shell $(PKGCONFIG) --variable=includedir mount)/libmount/libmount.h -+ifneq ($(call check_func,mnt_unref_cache,$(libmount_h)),0) -+ DEFINES += LIBMOUNT_HAS_MNT_UNREF_CACHE -+endif -+ -+ifneq ($(call check_func,mnt_table_parse_swaps,$(libmount_h)),0) -+ DEFINES += LIBMOUNT_SUPPORTS_SWAP -+endif -+ - ifneq ($(call check_file,$(kernel_incdir)/linux/nvme_ioctl.h),0) - ANA_SUPPORT := 1 - endif -diff --git a/libmpathutil/libmpathutil.version b/libmpathutil/libmpathutil.version -index 1238fc93..dd007be4 100644 ---- a/libmpathutil/libmpathutil.version -+++ b/libmpathutil/libmpathutil.version -@@ -133,3 +133,9 @@ LIBMPATHUTIL_1.1 { - global: - cleanup_fd_ptr; - } LIBMPATHUTIL_1.0; -+ -+LIBMPATHUTIL_1.2 { -+global: -+ cleanup_vector_free; -+ cleanup_fclose; -+} LIBMPATHUTIL_1.0; -diff --git a/libmpathutil/util.c b/libmpathutil/util.c -index 9662e1ed..92f25a50 100644 ---- a/libmpathutil/util.c -+++ b/libmpathutil/util.c -@@ -386,6 +386,18 @@ void cleanup_mutex(void *arg) - pthread_mutex_unlock(arg); - } - -+void cleanup_vector_free(void *arg) -+{ -+ if (arg) -+ vector_free((vector)arg); -+} -+ -+void cleanup_fclose(void *p) -+{ -+ if (p) -+ fclose(p); -+} -+ - struct bitfield *alloc_bitfield(unsigned int maxbit) - { - unsigned int n; -diff --git a/libmpathutil/util.h b/libmpathutil/util.h -index 75e20fd8..99a471d0 100644 ---- a/libmpathutil/util.h -+++ b/libmpathutil/util.h -@@ -48,6 +48,8 @@ int should_exit(void); - void cleanup_fd_ptr(void *arg); - void cleanup_free_ptr(void *arg); - void cleanup_mutex(void *arg); -+void cleanup_vector_free(void *arg); -+void cleanup_fclose(void *p); - - struct scandir_result { - struct dirent **di; -diff --git a/libmultipath/Makefile b/libmultipath/Makefile -index 3df851e2..61aa611f 100644 ---- a/libmultipath/Makefile -+++ b/libmultipath/Makefile -@@ -7,7 +7,7 @@ DEVLIB := libmultipath.so - CPPFLAGS += -I$(mpathutildir) -I$(mpathcmddir) -I$(nvmedir) -D_GNU_SOURCE $(SYSTEMD_CPPFLAGS) - CFLAGS += $(LIB_CFLAGS) - LIBDEPS += -lpthread -ldl -ldevmapper -ludev -L$(mpathutildir) -lmpathutil -L$(mpathcmddir) -lmpathcmd \ -- -lurcu -laio $(SYSTEMD_LIBDEPS) -+ -lmount -lurcu -laio $(SYSTEMD_LIBDEPS) - - # object files referencing MULTIPATH_DIR or CONFIG_DIR - # they need to be recompiled for unit tests -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index 05201224..c0139a2e 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -667,11 +667,6 @@ static int _check_bindings_file(const struct config *conf, FILE *file, - return rc; - } - --static void cleanup_fclose(void *p) --{ -- fclose(p); --} -- - static int alias_compar(const void *p1, const void *p2) - { - const char *alias1 = (*(struct mpentry * const *)p1)->alias; -@@ -684,12 +679,6 @@ static int alias_compar(const void *p1, const void *p2) - return alias1 ? -1 : alias2 ? 1 : 0; - } - --static void cleanup_vector_free(void *arg) --{ -- if (arg) -- vector_free((vector)arg); --} -- - /* - * check_alias_settings(): test for inconsistent alias configuration - * -diff --git a/libmultipath/valid.c b/libmultipath/valid.c -index a6aa9215..d4dae3ed 100644 ---- a/libmultipath/valid.c -+++ b/libmultipath/valid.c -@@ -17,6 +17,8 @@ - #include - #include - #include -+#include -+#include - - #include "vector.h" - #include "config.h" -@@ -30,12 +32,271 @@ - #include "mpath_cmd.h" - #include "valid.h" - -+static int subdir_filter(const struct dirent *ent) -+{ -+ unsigned int j; -+ static char const *const skip[] = { -+ ".", -+ "..", -+ "holders", -+ "integrity", -+ "mq", -+ "power", -+ "queue", -+ "slaves", -+ "trace", -+ }; -+ -+ if (ent->d_type != DT_DIR) -+ return 0; -+ -+ for (j = 0; j < ARRAY_SIZE(skip); j++) -+ if (!strcmp(skip[j], ent->d_name)) -+ return 0; -+ return 1; -+} -+ -+static int read_partitions(const char *syspath, vector parts) -+{ -+ struct scandir_result sr = { .n = 0 }; -+ char path[PATH_MAX], *last; -+ char *prop; -+ int i; -+ -+ strlcpy(path, syspath, sizeof(path)); -+ sr.n = scandir(path, &sr.di, subdir_filter, NULL); -+ if (sr.n == -1) -+ return -errno; -+ -+ pthread_cleanup_push_cast(free_scandir_result, &sr); -+ -+ /* parts[0] is the whole disk */ -+ if ((prop = strdup(strrchr(path, '/') + 1)) != NULL) { -+ if (vector_alloc_slot(parts)) -+ vector_set_slot(parts, prop); -+ else -+ free(prop); -+ } -+ -+ last = path + strlen(path); -+ for (i = 0; i < sr.n; i++) { -+ struct stat st; -+ -+ /* only add dirs that have the "partition" attribute */ -+ snprintf(last, sizeof(path) - (last - path), "/%s/partition", -+ sr.di[i]->d_name); -+ -+ if (stat(path, &st) == 0 && -+ (prop = strdup(sr.di[i]->d_name)) != NULL) { -+ if (vector_alloc_slot(parts)) -+ vector_set_slot(parts, prop); -+ else -+ free(prop); -+ } -+ } -+ -+ pthread_cleanup_pop(1); -+ return 0; -+} -+ -+static int no_dots(const struct dirent *ent) -+{ -+ const char *name = ent->d_name; -+ -+ if (name[0] == '.' && -+ (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) -+ return 0; -+ return 1; -+} -+ -+static int check_holders(const char *syspath) -+{ -+ struct scandir_result __attribute__((cleanup(free_scandir_result))) -+ sr = { .n = 0 }; -+ -+ sr.n = scandir(syspath, &sr.di, no_dots, NULL); -+ if (sr.n > 0) -+ condlog(4, "%s: found holders under %s", __func__, syspath); -+ return sr.n; -+} -+ -+static int check_all_holders(const struct _vector *parts) -+{ -+ char syspath[PATH_MAX]; -+ const char *sysname; -+ unsigned int j; -+ -+ if (VECTOR_SIZE(parts) == 0) -+ return 0; -+ -+ if (safe_sprintf(syspath, "/sys/class/block/%s/holders", -+ (const char *)VECTOR_SLOT(parts, 0))) -+ return -EOVERFLOW; -+ -+ if (check_holders(syspath) > 0) -+ return 1; -+ -+ j = 1; -+ vector_foreach_slot_after(parts, sysname, j) { -+ if (safe_sprintf(syspath, "/sys/class/block/%s/%s/holders", -+ (const char *)VECTOR_SLOT(parts, 0), sysname)) -+ return -EOVERFLOW; -+ if (check_holders(syspath) > 0) -+ return 1; -+ } -+ return 0; -+} -+ -+static void cleanup_table(void *arg) -+{ -+ if (arg) -+ mnt_free_table((struct libmnt_table *)arg); -+} -+ -+static void cleanup_cache(void *arg) -+{ -+ if (arg) -+#ifdef LIBMOUNT_HAS_MNT_UNREF_CACHE -+ mnt_unref_cache((struct libmnt_cache *)arg); -+#else -+ mnt_free_cache((struct libmnt_cache *)arg); -+#endif -+} -+ -+/* -+ * Passed a vector of partitions and a libmount table, -+ * check if any of the partitions in the vector is referenced in the table. -+ * Note that mnt_table_find_srcpath() also resolves mounts by symlinks. -+ */ -+static int check_mnt_table(const struct _vector *parts, -+ struct libmnt_table *tbl, -+ const char *table_name) -+{ -+ unsigned int i; -+ const char *sysname; -+ char devpath[PATH_MAX]; -+ -+ vector_foreach_slot(parts, sysname, i) { -+ if (!safe_sprintf(devpath, "/dev/%s", sysname) && -+ mnt_table_find_srcpath(tbl, devpath, -+ MNT_ITER_FORWARD) != NULL) { -+ condlog(4, "%s: found %s in %s", __func__, -+ sysname, table_name); -+ return 1; -+ } -+ } -+ return 0; -+} -+ -+static int check_mountinfo(const struct _vector *parts) -+{ -+ static const char mountinfo[] = "/proc/self/mountinfo"; -+ struct libmnt_table *tbl; -+ struct libmnt_cache *cache; -+ FILE *stream; -+ int used = 0, ret; -+ -+ tbl = mnt_new_table(); -+ if (!tbl ) -+ return -errno; -+ -+ pthread_cleanup_push(cleanup_table, tbl); -+ cache = mnt_new_cache(); -+ if (cache) { -+ pthread_cleanup_push(cleanup_cache, cache); -+ if (mnt_table_set_cache(tbl, cache) == 0) { -+ stream = fopen(mountinfo, "r"); -+ if (stream != NULL) { -+ pthread_cleanup_push(cleanup_fclose, stream); -+ ret = mnt_table_parse_stream(tbl, stream, mountinfo); -+ pthread_cleanup_pop(1); -+ -+ if (ret == 0) -+ used = check_mnt_table(parts, tbl, -+ "mountinfo"); -+ } -+ } -+ pthread_cleanup_pop(1); -+ } -+ pthread_cleanup_pop(1); -+ return used; -+} -+ -+#ifdef LIBMOUNT_SUPPORTS_SWAP -+static int check_swaps(const struct _vector *parts) -+{ -+ struct libmnt_table *tbl; -+ struct libmnt_cache *cache; -+ int used = 0, ret; -+ -+ tbl = mnt_new_table(); -+ if (!tbl ) -+ return -errno; -+ -+ pthread_cleanup_push(cleanup_table, tbl); -+ cache = mnt_new_cache(); -+ if (cache) { -+ pthread_cleanup_push(cleanup_cache, cache); -+ if (mnt_table_set_cache(tbl, cache) == 0) { -+ ret = mnt_table_parse_swaps(tbl, NULL); -+ if (ret == 0) -+ used = check_mnt_table(parts, tbl, "swaps"); -+ } -+ pthread_cleanup_pop(1); -+ } -+ pthread_cleanup_pop(1); -+ return used; -+} -+#else -+static int check_swaps(const struct _vector *parts __attribute__((unused))) -+{ -+ return 0; -+} -+#endif -+ -+ -+/* -+ * Given a block device, check if the device itself or any of its -+ * partitions is in use -+ * - by sysfs holders (e.g. LVM) -+ * - mounted according to /proc/self/mountinfo -+ * - used as swap -+ */ -+static int is_device_in_use(struct udev_device *udevice) -+{ -+ const char *syspath; -+ vector parts; -+ int used = 0, ret; -+ -+ syspath = udev_device_get_syspath(udevice); -+ if (!syspath) -+ return -ENOMEM; -+ -+ parts = vector_alloc(); -+ if (!parts) -+ return -ENOMEM; -+ -+ pthread_cleanup_push_cast(free_strvec, parts); -+ if ((ret = read_partitions(syspath, parts)) == 0) -+ used = check_all_holders(parts) > 0 || -+ check_mountinfo(parts) > 0 || -+ check_swaps(parts) > 0; -+ pthread_cleanup_pop(1); -+ -+ if (ret < 0) -+ return ret; -+ -+ condlog(3, "%s: %s is %sin use", __func__, syspath, used ? "" : "not "); -+ return used; -+} -+ - int - is_path_valid(const char *name, struct config *conf, struct path *pp, - bool check_multipathd) - { - int r; - int fd; -+ const char *prop; - - if (!pp || !name || !conf) - return PATH_IS_ERROR; -@@ -80,6 +341,10 @@ is_path_valid(const char *name, struct config *conf, struct path *pp, - if (!pp->udev) - return PATH_IS_ERROR; - -+ prop = udev_device_get_property_value(pp->udev, "DEVTYPE"); -+ if (prop == NULL || strcmp(prop, "disk")) -+ return PATH_IS_NOT_VALID; -+ - r = pathinfo(pp, conf, DI_SYSFS | DI_WWID | DI_BLACKLIST); - if (r == PATHINFO_SKIPPED) - return PATH_IS_NOT_VALID; -@@ -96,6 +361,11 @@ is_path_valid(const char *name, struct config *conf, struct path *pp, - return PATH_IS_ERROR; - } - -+ if ((conf->find_multipaths == FIND_MULTIPATHS_GREEDY || -+ conf->find_multipaths == FIND_MULTIPATHS_SMART) && -+ is_device_in_use(pp->udev) > 0) -+ return PATH_IS_NOT_VALID; -+ - if (conf->find_multipaths == FIND_MULTIPATHS_GREEDY) - return PATH_IS_VALID; - -diff --git a/tests/Makefile b/tests/Makefile -index 860338b2..1648ab9d 100644 ---- a/tests/Makefile -+++ b/tests/Makefile -@@ -55,7 +55,7 @@ vpd-test_LIBDEPS := -ludev -lpthread -ldl - alias-test_TESTDEPS := test-log.o - alias-test_LIBDEPS := -lpthread -ldl - valid-test_OBJDEPS := $(multipathdir)/valid.o $(multipathdir)/discovery.o --valid-test_LIBDEPS := -ludev -lpthread -ldl -+valid-test_LIBDEPS := -lmount -ludev -lpthread -ldl - devt-test_LIBDEPS := -ludev - mpathvalid-test_LIBDEPS := -ludev -lpthread -ldl - mpathvalid-test_OBJDEPS := $(mpathvaliddir)/mpath_valid.o -diff --git a/tests/valid.c b/tests/valid.c -index 398b771e..70329324 100644 ---- a/tests/valid.c -+++ b/tests/valid.c -@@ -83,6 +83,13 @@ struct udev_device *__wrap_udev_device_new_from_subsystem_sysname(struct udev *u - return NULL; - } - -+/* For devtype check */ -+const char *__wrap_udev_device_get_property_value(struct udev_device *udev_device, const char *property) -+{ -+ check_expected(property); -+ return mock_ptr_type(char *); -+} -+ - /* For the "hidden" check in pathinfo() */ - const char *__wrap_udev_device_get_sysattr_value(struct udev_device *udev_device, - const char *sysattr) -@@ -97,6 +104,12 @@ int __wrap_add_foreign(struct udev_device *udev_device) - return mock_type(int); - } - -+/* For is_device_used() */ -+const char *__wrap_udev_device_get_sysname(struct udev_device *udev_device) -+{ -+ return mock_ptr_type(char *); -+} -+ - /* called from pathinfo() */ - int __wrap_filter_devnode(struct config *conf, const struct _vector *elist, - const char *vendor, const char * product, const char *dev) -@@ -165,6 +178,11 @@ int __wrap_is_failed_wwid(const char *wwid) - return ret; - } - -+const char *__wrap_udev_device_get_syspath(struct udev_device *udevice) -+{ -+ return mock_ptr_type(char *); -+} -+ - int __wrap_check_wwids_file(char *wwid, int write_wwid) - { - bool passed = mock_type(bool); -@@ -225,6 +243,8 @@ static void setup_passing(char *name, char *wwid, unsigned int check_multipathd, - will_return(__wrap_udev_device_new_from_subsystem_sysname, true); - will_return(__wrap_udev_device_new_from_subsystem_sysname, - name); -+ expect_string(__wrap_udev_device_get_property_value, property, "DEVTYPE"); -+ will_return(__wrap_udev_device_get_property_value, "disk"); - if (stage == STAGE_GET_UDEV_DEVICE) - return; - if (stage == STAGE_PATHINFO_REAL) { -@@ -250,6 +270,10 @@ static void setup_passing(char *name, char *wwid, unsigned int check_multipathd, - return; - will_return(__wrap_is_failed_wwid, WWID_IS_NOT_FAILED); - will_return(__wrap_is_failed_wwid, wwid); -+ /* avoid real is_device_in_use() check */ -+ if (conf.find_multipaths == FIND_MULTIPATHS_GREEDY || -+ conf.find_multipaths == FIND_MULTIPATHS_SMART) -+ will_return(__wrap_udev_device_get_syspath, NULL); - if (stage == STAGE_IS_FAILED) - return; - will_return(__wrap_check_wwids_file, false); -@@ -347,6 +371,30 @@ static void test_check_multipathd(void **state) - assert_int_equal(is_path_valid(name, &conf, &pp, true), - PATH_IS_ERROR); - assert_string_equal(pp.dev, name); -+ -+ /* test pass because connect succeeded. succeed getting udev. Wrong DEVTYPE */ -+ memset(&pp, 0, sizeof(pp)); -+ setup_passing(name, NULL, CHECK_MPATHD_RUNNING, STAGE_CHECK_MULTIPATHD); -+ will_return(__wrap_udev_device_new_from_subsystem_sysname, true); -+ will_return(__wrap_udev_device_new_from_subsystem_sysname, -+ name); -+ expect_string(__wrap_udev_device_get_property_value, property, "DEVTYPE"); -+ will_return(__wrap_udev_device_get_property_value, "partition"); -+ assert_int_equal(is_path_valid(name, &conf, &pp, true), -+ PATH_IS_NOT_VALID); -+ assert_string_equal(pp.dev, name); -+ -+ /* test pass because connect succeeded. succeed getting udev. Bad DEVTYPE */ -+ memset(&pp, 0, sizeof(pp)); -+ setup_passing(name, NULL, CHECK_MPATHD_RUNNING, STAGE_CHECK_MULTIPATHD); -+ will_return(__wrap_udev_device_new_from_subsystem_sysname, true); -+ will_return(__wrap_udev_device_new_from_subsystem_sysname, -+ name); -+ expect_string(__wrap_udev_device_get_property_value, property, "DEVTYPE"); -+ will_return(__wrap_udev_device_get_property_value, NULL); -+ assert_int_equal(is_path_valid(name, &conf, &pp, true), -+ PATH_IS_NOT_VALID); -+ assert_string_equal(pp.dev, name); - } - - static void test_pathinfo(void **state) diff --git a/0023-RH-reset-default-find_mutipaths-value-to-off.patch b/0008-RH-reset-default-find_mutipaths-value-to-off.patch similarity index 100% rename from 0023-RH-reset-default-find_mutipaths-value-to-off.patch rename to 0008-RH-reset-default-find_mutipaths-value-to-off.patch diff --git a/0008-libmpathpersist-use-conf-timeout-for-updating-persis.patch b/0008-libmpathpersist-use-conf-timeout-for-updating-persis.patch deleted file mode 100644 index 9f3dcb2..0000000 --- a/0008-libmpathpersist-use-conf-timeout-for-updating-persis.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Mon, 2 Jan 2023 12:39:36 +0100 -Subject: [PATCH] libmpathpersist: use conf->timeout for updating persistent - reservations - -On systems with many LUNs, multipathd may fail to respond within the -default timeout to a "setprkey" command because the vecs lock is held -by the path checker. Honor the globally configured uxsock timeout in -libmpathpersist. - -Reported-by: boposki (github.com/opensvc/multipath-tools/pull/58) -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmpathpersist/mpath_updatepr.c | 11 ++++++++++- - 1 file changed, 10 insertions(+), 1 deletion(-) - -diff --git a/libmpathpersist/mpath_updatepr.c b/libmpathpersist/mpath_updatepr.c -index 4529a82b..36bd777e 100644 ---- a/libmpathpersist/mpath_updatepr.c -+++ b/libmpathpersist/mpath_updatepr.c -@@ -14,6 +14,9 @@ - #include - #include "debug.h" - #include "mpath_cmd.h" -+#include "vector.h" -+#include "globals.h" -+#include "config.h" - #include "uxsock.h" - #include "mpathpr.h" - -@@ -24,6 +27,12 @@ static int do_update_pr(char *alias, char *cmd, char *key) - char str[256]; - char *reply; - int ret = 0; -+ int timeout; -+ struct config *conf; -+ -+ conf = get_multipath_config(); -+ timeout = conf->uxsock_timeout; -+ put_multipath_config(conf); - - fd = mpath_connect(); - if (fd == -1) { -@@ -41,7 +50,7 @@ static int do_update_pr(char *alias, char *cmd, char *key) - mpath_disconnect(fd); - return -1; - } -- ret = recv_packet(fd, &reply, DEFAULT_REPLY_TIMEOUT); -+ ret = recv_packet(fd, &reply, timeout); - if (ret < 0) { - condlog(2, "%s: message=%s recv error=%d", alias, str, errno); - ret = -1; diff --git a/0024-RH-attempt-to-get-ANA-info-via-sysfs-first.patch b/0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch similarity index 100% rename from 0024-RH-attempt-to-get-ANA-info-via-sysfs-first.patch rename to 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch diff --git a/0009-libmultipath-pathinfo-don-t-fail-for-devices-lacking.patch b/0009-libmultipath-pathinfo-don-t-fail-for-devices-lacking.patch deleted file mode 100644 index fe7f001..0000000 --- a/0009-libmultipath-pathinfo-don-t-fail-for-devices-lacking.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Wed, 30 Nov 2022 21:07:45 +0100 -Subject: [PATCH] libmultipath: pathinfo: don't fail for devices lacking - INQUIRY properties -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Some SAS devices (e.g. Seagate factory recertified 'white label' drives) may -come with the Vendor field blank. This causes Multipath to fail to -complete the discovery of those devices. - -Such devices violate the SCSI Spec. From the SPC-6, ยง6.7.2: -"The T10 VENDOR IDENTIFICATION field contains eight bytes of left-aligned -ASCII data (see 4.3.1) identifying the manufacturer of the logical unit. The -T10 vendor identification shall be one assigned by INCITS.". - -But as we don't identify WWIDs by vendor and product, we don't need to discard -these devices right away. We can go ahead fingers crossed, and hope that the -the other VPD pages for the device are correct. - -We obviously can't look up reasonable device properties for such devices in -our hwtable. It would be up to the user to deal with that. - -Reported by: Allyn Malventano (github.com/opensvc/multipath-tools/issues/56) -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/discovery.c | 22 +++++++++++++--------- - 1 file changed, 13 insertions(+), 9 deletions(-) - -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index d9ee2cb9..67ac0e6d 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -1472,6 +1472,7 @@ scsi_sysfs_pathinfo (struct path *pp, const struct _vector *hwtable) - { - struct udev_device *parent; - const char *attr_path = NULL; -+ static const char unknown[] = "UNKNOWN"; - - parent = pp->udev; - while (parent) { -@@ -1492,19 +1493,22 @@ scsi_sysfs_pathinfo (struct path *pp, const struct _vector *hwtable) - if (!attr_path || pp->sg_id.host_no == -1) - return PATHINFO_FAILED; - -- if (sysfs_get_vendor(parent, pp->vendor_id, SCSI_VENDOR_SIZE) <= 0) -- return PATHINFO_FAILED;; -- -+ if (sysfs_get_vendor(parent, pp->vendor_id, SCSI_VENDOR_SIZE) <= 0) { -+ condlog(1, "%s: broken device without vendor ID", pp->dev); -+ strlcpy(pp->vendor_id, unknown, SCSI_VENDOR_SIZE); -+ } - condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id); - -- if (sysfs_get_model(parent, pp->product_id, PATH_PRODUCT_SIZE) <= 0) -- return PATHINFO_FAILED;; -- -+ if (sysfs_get_model(parent, pp->product_id, PATH_PRODUCT_SIZE) <= 0) { -+ condlog(1, "%s: broken device without product ID", pp->dev); -+ strlcpy(pp->product_id, unknown, PATH_PRODUCT_SIZE); -+ } - condlog(3, "%s: product = %s", pp->dev, pp->product_id); - -- if (sysfs_get_rev(parent, pp->rev, PATH_REV_SIZE) < 0) -- return PATHINFO_FAILED;; -- -+ if (sysfs_get_rev(parent, pp->rev, PATH_REV_SIZE) < 0) { -+ condlog(2, "%s: broken device without revision", pp->dev); -+ strlcpy(pp->rev, unknown, PATH_REV_SIZE); -+ } - condlog(3, "%s: rev = %s", pp->dev, pp->rev); - - /* diff --git a/0025-RH-make-parse_vpd_pg83-match-scsi_id-output.patch b/0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch similarity index 97% rename from 0025-RH-make-parse_vpd_pg83-match-scsi_id-output.patch rename to 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch index 824c747..4e0b116 100644 --- a/0025-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +++ b/0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch @@ -14,7 +14,7 @@ Signed-off-by: Benjamin Marzinski 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index 67ac0e6d..7fdbc1c3 100644 +index 6865cd92..72825829 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -1177,13 +1177,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, @@ -45,7 +45,7 @@ index 67ac0e6d..7fdbc1c3 100644 case 0x1: /* T-10 Vendor ID: Prio 2 */ diff --git a/tests/vpd.c b/tests/vpd.c -index a7d2092c..2366cfba 100644 +index 1b2d62d6..7309b5c5 100644 --- a/tests/vpd.c +++ b/tests/vpd.c @@ -231,11 +231,13 @@ static const char * const str_prefix[] = { diff --git a/0010-libmultipath-bump-ABI-version-to-18.0.0.patch b/0010-libmultipath-bump-ABI-version-to-18.0.0.patch deleted file mode 100644 index 0d9a3c1..0000000 --- a/0010-libmultipath-bump-ABI-version-to-18.0.0.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Wed, 25 Jan 2023 11:35:38 +0100 -Subject: [PATCH] libmultipath: bump ABI version to 18.0.0 - -Commit 6b81153 ("libmultipath: make prflag an enum") changed -the size and member offsets of struct multipath. - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/libmultipath.version | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version -index faef2a2d..015623cc 100644 ---- a/libmultipath/libmultipath.version -+++ b/libmultipath/libmultipath.version -@@ -43,7 +43,7 @@ LIBMPATHCOMMON_1.0.0 { - put_multipath_config; - }; - --LIBMULTIPATH_17.0.0 { -+LIBMULTIPATH_18.0.0 { - global: - /* symbols referenced by multipath and multipathd */ - add_foreign; diff --git a/0026-RH-add-scsi-device-handlers-to-modules-load.d.patch b/0011-RH-add-scsi-device-handlers-to-modules-load.d.patch similarity index 100% rename from 0026-RH-add-scsi-device-handlers-to-modules-load.d.patch rename to 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch diff --git a/0011-libmultipath-use-select_reload_action-in-select_acti.patch b/0011-libmultipath-use-select_reload_action-in-select_acti.patch deleted file mode 100644 index 05cc2ce..0000000 --- a/0011-libmultipath-use-select_reload_action-in-select_acti.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Tue, 31 Jan 2023 13:34:18 -0600 -Subject: [PATCH] libmultipath: use select_reload_action in select_action - -Since we have a function to set the action to reload, use it. - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck ---- - libmultipath/configure.c | 8 ++------ - 1 file changed, 2 insertions(+), 6 deletions(-) - -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index e689f8a7..050b984a 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -729,9 +729,7 @@ void select_action (struct multipath *mpp, const struct _vector *curmp, - - if (force_reload) { - mpp->force_udev_reload = 1; -- mpp->action = ACT_RELOAD; -- condlog(3, "%s: set ACT_RELOAD (forced by user)", -- mpp->alias); -+ select_reload_action(mpp, "forced by user"); - return; - } - if (cmpp->size != mpp->size) { -@@ -744,9 +742,7 @@ void select_action (struct multipath *mpp, const struct _vector *curmp, - - if (!is_udev_ready(cmpp) && count_active_paths(mpp) > 0) { - mpp->force_udev_reload = 1; -- mpp->action = ACT_RELOAD; -- condlog(3, "%s: set ACT_RELOAD (udev incomplete)", -- mpp->alias); -+ select_reload_action(mpp, "udev incomplete"); - return; - } - diff --git a/0027-RH-compile-with-libreadline-support.patch b/0012-RH-compile-with-libreadline-support.patch similarity index 100% rename from 0027-RH-compile-with-libreadline-support.patch rename to 0012-RH-compile-with-libreadline-support.patch diff --git a/0012-libmultipath-select-resize-action-even-if-reload-is-.patch b/0012-libmultipath-select-resize-action-even-if-reload-is-.patch deleted file mode 100644 index 39518c4..0000000 --- a/0012-libmultipath-select-resize-action-even-if-reload-is-.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Tue, 31 Jan 2023 13:34:19 -0600 -Subject: [PATCH] libmultipath: select resize action even if reload is forced - -The ACT_RESIZE action is the same as the ACT_RELOAD action, except that -it flushes outstanding IO because the device size is changing and -the new size might be too small for some of the outstanding IO. If we've -detected a size change, and a forced reload is requested, we still need -to flush the IO because the reload will change the device size. - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck ---- - libmultipath/configure.c | 11 ++++++----- - 1 file changed, 6 insertions(+), 5 deletions(-) - -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index 050b984a..6811e661 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -727,11 +727,6 @@ void select_action (struct multipath *mpp, const struct _vector *curmp, - return; - } - -- if (force_reload) { -- mpp->force_udev_reload = 1; -- select_reload_action(mpp, "forced by user"); -- return; -- } - if (cmpp->size != mpp->size) { - mpp->force_udev_reload = 1; - mpp->action = ACT_RESIZE; -@@ -740,6 +735,12 @@ void select_action (struct multipath *mpp, const struct _vector *curmp, - return; - } - -+ if (force_reload) { -+ mpp->force_udev_reload = 1; -+ select_reload_action(mpp, "forced by user"); -+ return; -+ } -+ - if (!is_udev_ready(cmpp) && count_active_paths(mpp) > 0) { - mpp->force_udev_reload = 1; - select_reload_action(mpp, "udev incomplete"); diff --git a/0013-libmultipath-cleanup-ACT_CREATE-code-in-select_actio.patch b/0013-libmultipath-cleanup-ACT_CREATE-code-in-select_actio.patch deleted file mode 100644 index 3574bac..0000000 --- a/0013-libmultipath-cleanup-ACT_CREATE-code-in-select_actio.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Tue, 31 Jan 2023 13:34:20 -0600 -Subject: [PATCH] libmultipath: cleanup ACT_CREATE code in select_action - -Combine the two separate blocks that set ACT_CREATE into one. - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck ---- - libmultipath/configure.c | 38 +++++++++++++++++--------------------- - 1 file changed, 17 insertions(+), 21 deletions(-) - -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index 6811e661..e870e0f6 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -686,33 +686,29 @@ void select_action (struct multipath *mpp, const struct _vector *curmp, - if (mpp->need_reload || (cmpp && cmpp->need_reload)) - force_reload = 1; - -- if (!cmpp_by_name) { -- if (cmpp) { -- condlog(2, "%s: rename %s to %s", mpp->wwid, -- cmpp->alias, mpp->alias); -- strlcpy(mpp->alias_old, cmpp->alias, WWID_SIZE); -- mpp->action = ACT_RENAME; -- if (force_reload) { -- mpp->force_udev_reload = 1; -- mpp->action = ACT_FORCERENAME; -- } -- return; -+ if (!cmpp) { -+ if (cmpp_by_name) { -+ condlog(1, "%s: can't use alias \"%s\" used by %s, falling back to WWID", -+ mpp->wwid, mpp->alias, cmpp_by_name->wwid); -+ /* We can do this because wwid wasn't found */ -+ free(mpp->alias); -+ mpp->alias = strdup(mpp->wwid); - } - mpp->action = ACT_CREATE; -- condlog(3, "%s: set ACT_CREATE (map does not exist)", -- mpp->alias); -+ condlog(3, "%s: set ACT_CREATE (map does not exist%s)", -+ mpp->alias, cmpp_by_name ? ", name changed" : ""); - return; - } - -- if (!cmpp) { -- condlog(1, "%s: can't use alias \"%s\" used by %s, falling back to WWID", -- mpp->wwid, mpp->alias, cmpp_by_name->wwid); -- /* We can do this because wwid wasn't found */ -- free(mpp->alias); -- mpp->alias = strdup(mpp->wwid); -- mpp->action = ACT_CREATE; -- condlog(3, "%s: set ACT_CREATE (map does not exist, name changed)", -+ if (!cmpp_by_name) { -+ condlog(2, "%s: rename %s to %s", mpp->wwid, cmpp->alias, - mpp->alias); -+ strlcpy(mpp->alias_old, cmpp->alias, WWID_SIZE); -+ mpp->action = ACT_RENAME; -+ if (force_reload) { -+ mpp->force_udev_reload = 1; -+ mpp->action = ACT_FORCERENAME; -+ } - return; - } - diff --git a/0014-libmultipath-keep-renames-from-stopping-other-multip.patch b/0014-libmultipath-keep-renames-from-stopping-other-multip.patch deleted file mode 100644 index f597e61..0000000 --- a/0014-libmultipath-keep-renames-from-stopping-other-multip.patch +++ /dev/null @@ -1,186 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Tue, 31 Jan 2023 13:34:21 -0600 -Subject: [PATCH] libmultipath: keep renames from stopping other multipath - actions - -If select_action() is called and a multipath device needs to be renamed, -the code currently checks if force_reload is set, and if so, does the -reload after the rename. But if force_reload isn't set, only the rename -happens, regardless of what other actions are needed. This can happen if -multipathd starts up and a device needs both a reload and a rename. - -Make multipath check for resize, reload, and switch pathgroup along with -rename, and do both if necessary. - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck ---- - libmultipath/configure.c | 62 +++++++++++++++++----------------------- - libmultipath/configure.h | 4 ++- - 2 files changed, 30 insertions(+), 36 deletions(-) - -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index e870e0f6..4a1c28bb 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -670,7 +670,8 @@ static bool is_udev_ready(struct multipath *cmpp) - static void - select_reload_action(struct multipath *mpp, const char *reason) - { -- mpp->action = ACT_RELOAD; -+ mpp->action = mpp->action == ACT_RENAME ? ACT_RELOAD_RENAME : -+ ACT_RELOAD; - condlog(3, "%s: set ACT_RELOAD (%s)", mpp->alias, reason); - } - -@@ -681,6 +682,7 @@ void select_action (struct multipath *mpp, const struct _vector *curmp, - struct multipath * cmpp_by_name; - char * mpp_feat, * cmpp_feat; - -+ mpp->action = ACT_NOTHING; - cmpp = find_mp_by_wwid(curmp, mpp->wwid); - cmpp_by_name = find_mp_by_alias(curmp, mpp->alias); - if (mpp->need_reload || (cmpp && cmpp->need_reload)) -@@ -705,14 +707,8 @@ void select_action (struct multipath *mpp, const struct _vector *curmp, - mpp->alias); - strlcpy(mpp->alias_old, cmpp->alias, WWID_SIZE); - mpp->action = ACT_RENAME; -- if (force_reload) { -- mpp->force_udev_reload = 1; -- mpp->action = ACT_FORCERENAME; -- } -- return; -- } -- -- if (cmpp != cmpp_by_name) { -+ /* don't return here. Check for other needed actions */ -+ } else if (cmpp != cmpp_by_name) { - condlog(2, "%s: unable to rename %s to %s (%s is used by %s)", - mpp->wwid, cmpp->alias, mpp->alias, - mpp->alias, cmpp_by_name->wwid); -@@ -720,12 +716,13 @@ void select_action (struct multipath *mpp, const struct _vector *curmp, - free(mpp->alias); - mpp->alias = strdup(cmpp->alias); - mpp->action = ACT_IMPOSSIBLE; -- return; -+ /* don't return here. Check for other needed actions */ - } - - if (cmpp->size != mpp->size) { - mpp->force_udev_reload = 1; -- mpp->action = ACT_RESIZE; -+ mpp->action = mpp->action == ACT_RENAME ? ACT_RESIZE_RENAME : -+ ACT_RESIZE; - condlog(3, "%s: set ACT_RESIZE (size change)", - mpp->alias); - return; -@@ -801,14 +798,14 @@ void select_action (struct multipath *mpp, const struct _vector *curmp, - return; - } - if (cmpp->nextpg != mpp->bestpg) { -- mpp->action = ACT_SWITCHPG; -+ mpp->action = mpp->action == ACT_RENAME ? ACT_SWITCHPG_RENAME : -+ ACT_SWITCHPG; - condlog(3, "%s: set ACT_SWITCHPG (next path group change)", - mpp->alias); - return; - } -- mpp->action = ACT_NOTHING; -- condlog(3, "%s: set ACT_NOTHING (map unchanged)", -- mpp->alias); -+ if (mpp->action == ACT_NOTHING) -+ condlog(3, "%s: set ACT_NOTHING (map unchanged)", mpp->alias); - return; - } - -@@ -909,6 +906,17 @@ int domap(struct multipath *mpp, char *params, int is_daemon) - } - } - -+ if (mpp->action == ACT_RENAME || mpp->action == ACT_SWITCHPG_RENAME || -+ mpp->action == ACT_RELOAD_RENAME || -+ mpp->action == ACT_RESIZE_RENAME) { -+ conf = get_multipath_config(); -+ pthread_cleanup_push(put_multipath_config, conf); -+ r = dm_rename(mpp->alias_old, mpp->alias, -+ conf->partition_delim, mpp->skip_kpartx); -+ pthread_cleanup_pop(1); -+ if (r == DOMAP_FAIL) -+ return r; -+ } - switch (mpp->action) { - case ACT_REJECT: - case ACT_NOTHING: -@@ -916,6 +924,7 @@ int domap(struct multipath *mpp, char *params, int is_daemon) - return DOMAP_EXIST; - - case ACT_SWITCHPG: -+ case ACT_SWITCHPG_RENAME: - dm_switchgroup(mpp->alias, mpp->bestpg); - /* - * we may have avoided reinstating paths because there where in -@@ -942,6 +951,7 @@ int domap(struct multipath *mpp, char *params, int is_daemon) - break; - - case ACT_RELOAD: -+ case ACT_RELOAD_RENAME: - sysfs_set_max_sectors_kb(mpp, 1); - if (mpp->ghost_delay_tick > 0 && pathcount(mpp, PATH_UP)) - mpp->ghost_delay_tick = 0; -@@ -949,6 +959,7 @@ int domap(struct multipath *mpp, char *params, int is_daemon) - break; - - case ACT_RESIZE: -+ case ACT_RESIZE_RENAME: - sysfs_set_max_sectors_kb(mpp, 1); - if (mpp->ghost_delay_tick > 0 && pathcount(mpp, PATH_UP)) - mpp->ghost_delay_tick = 0; -@@ -956,29 +967,10 @@ int domap(struct multipath *mpp, char *params, int is_daemon) - break; - - case ACT_RENAME: -- conf = get_multipath_config(); -- pthread_cleanup_push(put_multipath_config, conf); -- r = dm_rename(mpp->alias_old, mpp->alias, -- conf->partition_delim, mpp->skip_kpartx); -- pthread_cleanup_pop(1); -- break; -- -- case ACT_FORCERENAME: -- conf = get_multipath_config(); -- pthread_cleanup_push(put_multipath_config, conf); -- r = dm_rename(mpp->alias_old, mpp->alias, -- conf->partition_delim, mpp->skip_kpartx); -- pthread_cleanup_pop(1); -- if (r) { -- sysfs_set_max_sectors_kb(mpp, 1); -- if (mpp->ghost_delay_tick > 0 && -- pathcount(mpp, PATH_UP)) -- mpp->ghost_delay_tick = 0; -- r = dm_addmap_reload(mpp, params, 0); -- } - break; - - default: -+ r = DOMAP_FAIL; - break; - } - -diff --git a/libmultipath/configure.h b/libmultipath/configure.h -index 2bf73e65..9d935db3 100644 ---- a/libmultipath/configure.h -+++ b/libmultipath/configure.h -@@ -18,9 +18,11 @@ enum actions { - ACT_RENAME, - ACT_CREATE, - ACT_RESIZE, -- ACT_FORCERENAME, -+ ACT_RELOAD_RENAME, - ACT_DRY_RUN, - ACT_IMPOSSIBLE, -+ ACT_RESIZE_RENAME, -+ ACT_SWITCHPG_RENAME, - }; - - /* diff --git a/0015-libmpathpersist-fix-resource-leak-in-update_map_pr.patch b/0015-libmpathpersist-fix-resource-leak-in-update_map_pr.patch deleted file mode 100644 index 866080f..0000000 --- a/0015-libmpathpersist-fix-resource-leak-in-update_map_pr.patch +++ /dev/null @@ -1,68 +0,0 @@ -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_int.c | 15 ++++++++------- - 1 file changed, 8 insertions(+), 7 deletions(-) - -diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c -index 8b52b746..178c2f54 100644 ---- a/libmpathpersist/mpath_persist_int.c -+++ b/libmpathpersist/mpath_persist_int.c -@@ -733,7 +733,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)) - { -@@ -754,7 +754,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); -@@ -762,15 +762,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, -@@ -795,6 +795,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/device-mapper-multipath.spec b/device-mapper-multipath.spec index a6fe03c..ca8b8aa 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,42 +1,27 @@ Name: device-mapper-multipath -Version: 0.9.4 -Release: 2%{?dist} +Version: 0.9.5 +Release: 1%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ # The source for this package was pulled from upstream's git repo. Use the # following command to generate the tarball -# curl -L https://github.com/opensvc/multipath-tools/archive/0.9.4.tar.gz -o multipath-tools-0.9.4.tgz -Source0: multipath-tools-0.9.4.tgz +# curl -L https://github.com/opensvc/multipath-tools/archive/0.9.5.tar.gz -o multipath-tools-0.9.5.tgz +Source0: multipath-tools-0.9.5.tgz Source1: multipath.conf -Patch0001: 0001-multipathd-make-pr-registration-consistent.patch -Patch0002: 0002-libmultipath-make-prflag-an-enum.patch -Patch0003: 0003-multipathd-handle-no-active-paths-in-update_map_pr.patch -Patch0004: 0004-multipathd-add-missing-newline-to-cli_del_map-reply.patch -Patch0005: 0005-libmultipath-skip-extra-vector-work-in-remove_maps.patch -Patch0006: 0006-libmultipath-orphan-paths-if-coalesce_paths-frees-ne.patch -Patch0007: 0007-libmultipath-is_path_valid-check-if-device-is-in-use.patch -Patch0008: 0008-libmpathpersist-use-conf-timeout-for-updating-persis.patch -Patch0009: 0009-libmultipath-pathinfo-don-t-fail-for-devices-lacking.patch -Patch0010: 0010-libmultipath-bump-ABI-version-to-18.0.0.patch -Patch0011: 0011-libmultipath-use-select_reload_action-in-select_acti.patch -Patch0012: 0012-libmultipath-select-resize-action-even-if-reload-is-.patch -Patch0013: 0013-libmultipath-cleanup-ACT_CREATE-code-in-select_actio.patch -Patch0014: 0014-libmultipath-keep-renames-from-stopping-other-multip.patch -Patch0015: 0015-libmpathpersist-fix-resource-leak-in-update_map_pr.patch -Patch0016: 0016-RH-fixup-udev-rules-for-redhat.patch -Patch0017: 0017-RH-Remove-the-property-blacklist-exception-builtin.patch -Patch0018: 0018-RH-don-t-start-without-a-config-file.patch -Patch0019: 0019-RH-Fix-nvme-function-missing-argument.patch -Patch0020: 0020-RH-use-rpm-optflags-if-present.patch -Patch0021: 0021-RH-add-mpathconf.patch -Patch0022: 0022-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch -Patch0023: 0023-RH-reset-default-find_mutipaths-value-to-off.patch -Patch0024: 0024-RH-attempt-to-get-ANA-info-via-sysfs-first.patch -Patch0025: 0025-RH-make-parse_vpd_pg83-match-scsi_id-output.patch -Patch0026: 0026-RH-add-scsi-device-handlers-to-modules-load.d.patch -Patch0027: 0027-RH-compile-with-libreadline-support.patch +Patch0001: 0001-RH-fixup-udev-rules-for-redhat.patch +Patch0002: 0002-RH-Remove-the-property-blacklist-exception-builtin.patch +Patch0003: 0003-RH-don-t-start-without-a-config-file.patch +Patch0004: 0004-RH-Fix-nvme-function-missing-argument.patch +Patch0005: 0005-RH-use-rpm-optflags-if-present.patch +Patch0006: 0006-RH-add-mpathconf.patch +Patch0007: 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +Patch0008: 0008-RH-reset-default-find_mutipaths-value-to-off.patch +Patch0009: 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch +Patch0010: 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +Patch0011: 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch +Patch0012: 0012-RH-compile-with-libreadline-support.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -123,7 +108,7 @@ This package contains the files needed to develop applications that use device-mapper-multipath's libdmmp C API library %prep -%autosetup -n multipath-tools-0.9.4 -p1 +%autosetup -n multipath-tools-0.9.5 -p1 cp %{SOURCE1} . %build @@ -245,6 +230,12 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Tue May 16 2023 Benjamin Marzinski - 0.9.5-1 +- Update to the latest upstream release + * Previous patches 0001-0015 are included in the source tarball +- Rename redhat patches + * Previous patches 0016-0027 are now patches 0001-0012 + * Thu Feb 2 2023 Benjamin Marzinski - 0.9.4-2 - Update to the head of the upstream staging branch * Patches 0011-0015 are from the upstream staging branch diff --git a/sources b/sources index 462cab6..ece6ffe 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (multipath-tools-0.9.4.tgz) = 5e0dcea610fc215e345444c04453a38f39c73e493c2bc53f6b3a90cd701266aabdf7c4693dfc321099af836d0019bf27355e265ad5db5deff48f8bb94ed4719d +SHA512 (multipath-tools-0.9.5.tgz) = 39c2e5d45542c6076eb3b17b9994629b4c1f74347aa43e0119001fa2d07d3a606fd5e617962906a11b313afb37a115bd8eec2ef24447e980e61b5900625f9146 SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942 From d88fe4b9560ffa9bd363b3e344f82e0705cbd169 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Wed, 19 Jul 2023 17:19:23 +0000 Subject: [PATCH 02/29] Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- device-mapper-multipath.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index ca8b8aa..268e4b9 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.9.5 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ @@ -230,6 +230,9 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Wed Jul 19 2023 Fedora Release Engineering - 0.9.5-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + * Tue May 16 2023 Benjamin Marzinski - 0.9.5-1 - Update to the latest upstream release * Previous patches 0001-0015 are included in the source tarball From e5eddaae1a3d86387da90d35f7c9fddac02d03a4 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Fri, 22 Sep 2023 15:29:43 -0500 Subject: [PATCH 03/29] device-mapper-multipath-0.9.6-1 Update to the head of the upstream staging branch Rename redhat patches * Previous patches 0001-0012 are now patches 0041-0052 Add 0053-RH-Add-mpathcleanup.patch * add mpathcleanup program --- .gitignore | 1 + ...fs_set_scsi_tmo-do-nothing-for-ACT_D.patch | 51 + ...libmultipath-add-alias_already_taken.patch | 75 + ...fy-use_existing_alias-and-get_user_f.patch | 207 ++ ...er-allocate-an-alias-that-s-already-.patch | 101 + ...kup_binding-add-comment-about-the-al.patch | 61 + ...test-simplify-debugging-for-condlog-.patch | 35 + ...tests-add-tests-for-get_user_friendl.patch | 493 +++++ ...test-consistent-use-of-macros-in-ali.patch | 365 ++++ ...tests-convert-mock_-failed-used-_ali.patch | 246 +++ ...test-use-mock_bindings_file-consiste.patch | 500 +++++ ...-global-variable-for-current-binding.patch | 109 ++ ...ame-fix_bindings_file-to-update_bind.patch | 40 + ...lias.c-move-bindings-related-code-up.patch | 285 +++ ...ate_bindings_file-take-filename-argu.patch | 61 + ...ate_bindings_file-use-a-single-write.patch | 59 + ...ate_bindings_file-don-t-log-temp-fil.patch | 29 + ...path-alias.c-factor-out-read_binding.patch | 94 + ...libmultipath-keep-bindings-in-memory.patch | 545 ++++++ ...ultipath-tools-tests-fix-alias-tests.patch | 1698 +++++++++++++++++ ...get_uuid-return-emtpy-UUID-for-non-e.patch | 53 + ...dapt-to-new-semantics-of-dm_get_uuid.patch | 158 ++ ...th-sort-aliases-by-length-and-strcmp.patch | 98 + ...tests-fix-alias-test-after-sort-orde.patch | 90 + ...plify-get_free_id-assuming-total-ord.patch | 122 ++ ...tests-adapt-alias-tests-for-total-or.patch | 203 ++ ...tests-add-test-for-ordering-of-bindi.patch | 275 +++ ...-bindings-file-with-inotify-timestam.patch | 597 ++++++ ...tests-mock-pthread_mutex_-lock-unloc.patch | 102 + ...Makefile-sanitize-paths-for-configur.patch | 73 + ...add-compile-time-configuration-for-e.patch | 58 + ...man-pages-generate-with-correct-path.patch | 366 ++++ ...-Makefile-fix-bug-in-install-section.patch | 25 + ...README.md-improve-documentation-for-.patch | 75 + ...nt-built-in-values-for-deprecated-op.patch | 55 + 0035-multipath-add-a-missing-newline.patch | 25 + ...allow-prefixes-with-and-w-o-trailing.patch | 66 + ...recate-bindings_file-wwids_file-prke.patch | 897 +++++++++ ...id-Warray-bounds-error-in-uatomic-op.patch | 158 ++ 0039-multipath-tools-fix-spelling.patch | 52 + ...-support-to-handle-FPIN-Li-events-fo.patch | 300 +++ ... 0041-RH-fixup-udev-rules-for-redhat.patch | 14 +- ...property-blacklist-exception-builtin.patch | 41 +- ...RH-don-t-start-without-a-config-file.patch | 50 +- ...H-Fix-nvme-function-missing-argument.patch | 0 ... 0045-RH-use-rpm-optflags-if-present.patch | 14 +- ...hconf.patch => 0046-RH-add-mpathconf.patch | 14 +- ...om-kernel-cmdline-mpath.wwids-with-A.patch | 26 +- ...-default-find_mutipaths-value-to-off.patch | 2 +- ...empt-to-get-ANA-info-via-sysfs-first.patch | 4 +- ...-parse_vpd_pg83-match-scsi_id-output.patch | 2 +- ...si-device-handlers-to-modules-load.d.patch | 2 +- ...-RH-compile-with-libreadline-support.patch | 2 +- 0053-RH-Add-mpathcleanup.patch | 186 ++ device-mapper-multipath.spec | 83 +- sources | 2 +- 56 files changed, 9256 insertions(+), 89 deletions(-) create mode 100644 0001-libmultipath-sysfs_set_scsi_tmo-do-nothing-for-ACT_D.patch create mode 100644 0002-libmultipath-add-alias_already_taken.patch create mode 100644 0003-libmultipath-unify-use_existing_alias-and-get_user_f.patch create mode 100644 0004-libmultipath-never-allocate-an-alias-that-s-already-.patch create mode 100644 0005-libmultipath-lookup_binding-add-comment-about-the-al.patch create mode 100644 0006-multipath-tools-test-simplify-debugging-for-condlog-.patch create mode 100644 0007-multipath-tools-tests-add-tests-for-get_user_friendl.patch create mode 100644 0008-multipath-tools-test-consistent-use-of-macros-in-ali.patch create mode 100644 0009-multipath-tools-tests-convert-mock_-failed-used-_ali.patch create mode 100644 0010-multipath-tools-test-use-mock_bindings_file-consiste.patch create mode 100644 0011-libmultipath-add-global-variable-for-current-binding.patch create mode 100644 0012-libmultipath-rename-fix_bindings_file-to-update_bind.patch create mode 100644 0013-libmultipath-alias.c-move-bindings-related-code-up.patch create mode 100644 0014-libmultipath-update_bindings_file-take-filename-argu.patch create mode 100644 0015-libmultipath-update_bindings_file-use-a-single-write.patch create mode 100644 0016-libmultipath-update_bindings_file-don-t-log-temp-fil.patch create mode 100644 0017-libmultipath-alias.c-factor-out-read_binding.patch create mode 100644 0018-libmultipath-keep-bindings-in-memory.patch create mode 100644 0019-multipath-tools-tests-fix-alias-tests.patch create mode 100644 0020-libmultipath-dm_get_uuid-return-emtpy-UUID-for-non-e.patch create mode 100644 0021-libmultipath-adapt-to-new-semantics-of-dm_get_uuid.patch create mode 100644 0022-libmultipath-sort-aliases-by-length-and-strcmp.patch create mode 100644 0023-multipath-tools-tests-fix-alias-test-after-sort-orde.patch create mode 100644 0024-libmultipath-simplify-get_free_id-assuming-total-ord.patch create mode 100644 0025-multipath-tools-tests-adapt-alias-tests-for-total-or.patch create mode 100644 0026-multipath-tools-tests-add-test-for-ordering-of-bindi.patch create mode 100644 0027-multipathd-watch-bindings-file-with-inotify-timestam.patch create mode 100644 0028-multipath-tools-tests-mock-pthread_mutex_-lock-unloc.patch create mode 100644 0029-multipath-tools-Makefile-sanitize-paths-for-configur.patch create mode 100644 0030-multipath-tools-add-compile-time-configuration-for-e.patch create mode 100644 0031-multipath-tools-man-pages-generate-with-correct-path.patch create mode 100644 0032-libdmmp-Makefile-fix-bug-in-install-section.patch create mode 100644 0033-multipath-tools-README.md-improve-documentation-for-.patch create mode 100644 0034-libmultipath-print-built-in-values-for-deprecated-op.patch create mode 100644 0035-multipath-add-a-missing-newline.patch create mode 100644 0036-multipath-tools-allow-prefixes-with-and-w-o-trailing.patch create mode 100644 0037-libmultipath-deprecate-bindings_file-wwids_file-prke.patch create mode 100644 0038-libmultipath-avoid-Warray-bounds-error-in-uatomic-op.patch create mode 100644 0039-multipath-tools-fix-spelling.patch create mode 100644 0040-multipathd-Added-support-to-handle-FPIN-Li-events-fo.patch rename 0001-RH-fixup-udev-rules-for-redhat.patch => 0041-RH-fixup-udev-rules-for-redhat.patch (89%) rename 0002-RH-Remove-the-property-blacklist-exception-builtin.patch => 0042-RH-Remove-the-property-blacklist-exception-builtin.patch (79%) rename 0003-RH-don-t-start-without-a-config-file.patch => 0043-RH-don-t-start-without-a-config-file.patch (71%) rename 0004-RH-Fix-nvme-function-missing-argument.patch => 0044-RH-Fix-nvme-function-missing-argument.patch (100%) rename 0005-RH-use-rpm-optflags-if-present.patch => 0045-RH-use-rpm-optflags-if-present.patch (83%) rename 0006-RH-add-mpathconf.patch => 0046-RH-add-mpathconf.patch (98%) rename 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch => 0047-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch (87%) rename 0008-RH-reset-default-find_mutipaths-value-to-off.patch => 0048-RH-reset-default-find_mutipaths-value-to-off.patch (96%) rename 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch => 0049-RH-attempt-to-get-ANA-info-via-sysfs-first.patch (95%) rename 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch => 0050-RH-make-parse_vpd_pg83-match-scsi_id-output.patch (98%) rename 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch => 0051-RH-add-scsi-device-handlers-to-modules-load.d.patch (96%) rename 0012-RH-compile-with-libreadline-support.patch => 0052-RH-compile-with-libreadline-support.patch (96%) create mode 100644 0053-RH-Add-mpathcleanup.patch diff --git a/.gitignore b/.gitignore index 18226b9..75c4abc 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ multipath-tools-091027.tar.gz /multipath-tools-0.9.3.tgz /multipath-tools-0.9.4.tgz /multipath-tools-0.9.5.tgz +/multipath-tools-0.9.6.tgz diff --git a/0001-libmultipath-sysfs_set_scsi_tmo-do-nothing-for-ACT_D.patch b/0001-libmultipath-sysfs_set_scsi_tmo-do-nothing-for-ACT_D.patch new file mode 100644 index 0000000..9b8a486 --- /dev/null +++ b/0001-libmultipath-sysfs_set_scsi_tmo-do-nothing-for-ACT_D.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 22 Aug 2023 16:21:43 +0200 +Subject: [PATCH] libmultipath: sysfs_set_scsi_tmo: do nothing for ACT_DRY_RUN + +"multipath -d" might change sysfs timeouts of SCSI devices. +Make sure it doesn't. + +Signed-off-by: Martin Wilck +Cc: Jehan Singh +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/configure.c | 4 ++-- + libmultipath/discovery.c | 3 +++ + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index 9513baae..029fbbd2 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -1193,13 +1193,13 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid, + + if (cmpp) + mpp->queue_mode = cmpp->queue_mode; ++ if (cmd == CMD_DRY_RUN && mpp->action == ACT_UNDEF) ++ mpp->action = ACT_DRY_RUN; + if (setup_map(mpp, ¶ms, vecs)) { + remove_map(mpp, vecs->pathvec, NULL); + continue; + } + +- if (cmd == CMD_DRY_RUN) +- mpp->action = ACT_DRY_RUN; + if (mpp->action == ACT_UNDEF) + select_action(mpp, curmp, + force_reload == FORCE_RELOAD_YES ? 1 : 0); +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index e4de48e7..84ce5fe7 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -857,6 +857,9 @@ sysfs_set_scsi_tmo (struct config *conf, struct multipath *mpp) + bool warn_dev_loss = false; + bool warn_fast_io_fail = false; + ++ if (mpp->action == ACT_DRY_RUN || mpp->action == ACT_REJECT) ++ return 0; ++ + if (mpp->no_path_retry > 0) { + uint64_t no_path_retry_tmo = + (uint64_t)mpp->no_path_retry * conf->checkint; diff --git a/0002-libmultipath-add-alias_already_taken.patch b/0002-libmultipath-add-alias_already_taken.patch new file mode 100644 index 0000000..8ed3c7b --- /dev/null +++ b/0002-libmultipath-add-alias_already_taken.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 22 Aug 2023 21:36:11 +0200 +Subject: [PATCH] libmultipath: add alias_already_taken() + +Factor out a trivial helper function. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/alias.c | 32 +++++++++++++++++++------------- + 1 file changed, 19 insertions(+), 13 deletions(-) + +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index c0139a2e..83ded886 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + + #include "debug.h" + #include "util.h" +@@ -109,30 +110,35 @@ scan_devname(const char *alias, const char *prefix) + return n; + } + +-static int +-id_already_taken(int id, const char *prefix, const char *map_wwid) ++static bool alias_already_taken(const char *alias, const char *map_wwid) + { +- STRBUF_ON_STACK(buf); +- const char *alias; +- +- if (append_strbuf_str(&buf, prefix) < 0 || +- format_devname(&buf, id) < 0) +- return 0; + +- alias = get_strbuf_str(&buf); + if (dm_map_present(alias)) { + char wwid[WWID_SIZE]; + + /* If both the name and the wwid match, then it's fine.*/ + if (dm_get_uuid(alias, wwid, sizeof(wwid)) == 0 && + strncmp(map_wwid, wwid, sizeof(wwid)) == 0) +- return 0; +- condlog(3, "%s: alias '%s' already taken, but not in bindings file. reselecting alias", map_wwid, alias); +- return 1; ++ return false; ++ condlog(3, "%s: alias '%s' already taken, but not in bindings file. reselecting alias", ++ map_wwid, alias); ++ return true; + } +- return 0; ++ return false; + } + ++static bool id_already_taken(int id, const char *prefix, const char *map_wwid) ++{ ++ STRBUF_ON_STACK(buf); ++ const char *alias; ++ ++ if (append_strbuf_str(&buf, prefix) < 0 || ++ format_devname(&buf, id) < 0) ++ return false; ++ ++ alias = get_strbuf_str(&buf); ++ return alias_already_taken(alias, map_wwid); ++} + + /* + * Returns: 0 if matching entry in WWIDs file found diff --git a/0003-libmultipath-unify-use_existing_alias-and-get_user_f.patch b/0003-libmultipath-unify-use_existing_alias-and-get_user_f.patch new file mode 100644 index 0000000..5beb1fe --- /dev/null +++ b/0003-libmultipath-unify-use_existing_alias-and-get_user_f.patch @@ -0,0 +1,207 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 22 Aug 2023 22:00:58 +0200 +Subject: [PATCH] libmultipath: unify use_existing_alias() and + get_user_friendly_alias() + +These functions are only called from select_alias(). The logic +is more obvious when unified in a single function. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/alias.c | 82 ++++++++++++------------------------------ + libmultipath/alias.h | 9 ++--- + libmultipath/propsel.c | 19 +++++----- + 3 files changed, 34 insertions(+), 76 deletions(-) + +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index 83ded886..68f5d848 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -329,13 +329,13 @@ allocate_binding(int fd, const char *wwid, int id, const char *prefix) + return alias; + } + +-char * +-use_existing_alias (const char *wwid, const char *file, const char *alias_old, +- const char *prefix, int bindings_read_only) ++char *get_user_friendly_alias(const char *wwid, const char *file, const char *alias_old, ++ const char *prefix, bool bindings_read_only) + { + char *alias = NULL; + int id = 0; + int fd, can_write; ++ bool new_binding = false; + char buff[WWID_SIZE]; + FILE *f; + +@@ -349,6 +349,10 @@ use_existing_alias (const char *wwid, const char *file, const char *alias_old, + close(fd); + return NULL; + } ++ ++ if (!strlen(alias_old)) ++ goto new_alias; ++ + /* lookup the binding. if it exists, the wwid will be in buff + * either way, id contains the id for the alias + */ +@@ -358,14 +362,14 @@ use_existing_alias (const char *wwid, const char *file, const char *alias_old, + /* if buff is our wwid, it's already + * allocated correctly + */ +- if (strcmp(buff, wwid) == 0) ++ if (strcmp(buff, wwid) == 0) { + alias = strdup(alias_old); +- else { +- alias = NULL; ++ goto out; ++ } else { + condlog(0, "alias %s already bound to wwid %s, cannot reuse", + alias_old, buff); ++ goto new_alias; + } +- goto out; + } + + id = lookup_binding(f, wwid, &alias, NULL, 0); +@@ -377,8 +381,15 @@ use_existing_alias (const char *wwid, const char *file, const char *alias_old, + + /* allocate the existing alias in the bindings file */ + id = scan_devname(alias_old, prefix); +- if (id <= 0) +- goto out; ++ ++new_alias: ++ if (id <= 0) { ++ id = lookup_binding(f, wwid, &alias, prefix, 1); ++ if (id <= 0) ++ goto out; ++ else ++ new_binding = true; ++ } + + if (fflush(f) != 0) { + condlog(0, "cannot fflush bindings file stream : %s", +@@ -388,8 +399,9 @@ use_existing_alias (const char *wwid, const char *file, const char *alias_old, + + if (can_write && !bindings_read_only) { + alias = allocate_binding(fd, wwid, id, prefix); +- condlog(0, "Allocated existing binding [%s] for WWID [%s]", +- alias, wwid); ++ if (alias && !new_binding) ++ condlog(2, "Allocated existing binding [%s] for WWID [%s]", ++ alias, wwid); + } + + out: +@@ -399,54 +411,6 @@ out: + return alias; + } + +-char * +-get_user_friendly_alias(const char *wwid, const char *file, const char *prefix, +- int bindings_read_only) +-{ +- char *alias; +- int fd, id; +- FILE *f; +- int can_write; +- +- if (!wwid || *wwid == '\0') { +- condlog(3, "Cannot find binding for empty WWID"); +- return NULL; +- } +- +- fd = open_file(file, &can_write, bindings_file_header); +- if (fd < 0) +- return NULL; +- +- f = fdopen(fd, "r"); +- if (!f) { +- condlog(0, "cannot fdopen on bindings file descriptor : %s", +- strerror(errno)); +- close(fd); +- return NULL; +- } +- +- id = lookup_binding(f, wwid, &alias, prefix, 1); +- if (id < 0) { +- fclose(f); +- return NULL; +- } +- +- pthread_cleanup_push(free, alias); +- +- if (fflush(f) != 0) { +- condlog(0, "cannot fflush bindings file stream : %s", +- strerror(errno)); +- free(alias); +- alias = NULL; +- } else if (can_write && !bindings_read_only && !alias) +- alias = allocate_binding(fd, wwid, id, prefix); +- +- fclose(f); +- +- pthread_cleanup_pop(0); +- return alias; +-} +- + int + get_user_friendly_wwid(const char *alias, char *buff, const char *file) + { +diff --git a/libmultipath/alias.h b/libmultipath/alias.h +index dbc950c4..fa332233 100644 +--- a/libmultipath/alias.h ++++ b/libmultipath/alias.h +@@ -2,13 +2,10 @@ + #define _ALIAS_H + + int valid_alias(const char *alias); +-char *get_user_friendly_alias(const char *wwid, const char *file, +- const char *prefix, +- int bindings_readonly); + int get_user_friendly_wwid(const char *alias, char *buff, const char *file); +-char *use_existing_alias (const char *wwid, const char *file, +- const char *alias_old, +- const char *prefix, int bindings_read_only); ++char *get_user_friendly_alias(const char *wwid, const char *file, ++ const char *alias_old, ++ const char *prefix, bool bindings_read_only); + + struct config; + int check_alias_settings(const struct config *); +diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c +index d6bce129..354e883f 100644 +--- a/libmultipath/propsel.c ++++ b/libmultipath/propsel.c +@@ -401,19 +401,16 @@ int select_alias(struct config *conf, struct multipath * mp) + + select_alias_prefix(conf, mp); + +- if (strlen(mp->alias_old) > 0) { +- mp->alias = use_existing_alias(mp->wwid, conf->bindings_file, +- mp->alias_old, mp->alias_prefix, +- conf->bindings_read_only); +- memset (mp->alias_old, 0, WWID_SIZE); +- origin = "(setting: using existing alias)"; +- } ++ mp->alias = get_user_friendly_alias(mp->wwid, conf->bindings_file, ++ mp->alias_old, mp->alias_prefix, ++ conf->bindings_read_only); + +- if (mp->alias == NULL) { +- mp->alias = get_user_friendly_alias(mp->wwid, +- conf->bindings_file, mp->alias_prefix, conf->bindings_read_only); ++ if (mp->alias && !strncmp(mp->alias, mp->alias_old, WWID_SIZE)) ++ origin = "(setting: using existing alias)"; ++ else if (mp->alias) + origin = "(setting: user_friendly_name)"; +- } ++ memset (mp->alias_old, 0, WWID_SIZE); ++ + out: + if (mp->alias == NULL) { + mp->alias = strdup(mp->wwid); diff --git a/0004-libmultipath-never-allocate-an-alias-that-s-already-.patch b/0004-libmultipath-never-allocate-an-alias-that-s-already-.patch new file mode 100644 index 0000000..3d05b85 --- /dev/null +++ b/0004-libmultipath-never-allocate-an-alias-that-s-already-.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 22 Aug 2023 22:23:29 +0200 +Subject: [PATCH] libmultipath: never allocate an alias that's already taken + +If the bindings file is changed in a way that multipathd can't handle +(e.g. by swapping the aliases of two maps), multipathd must not try +to re-use an alias that is already used by another map. Creating +or renaming a map with such an alias will fail. We already avoid +this for some cases, but not for all. Fix it. + +Signed-off-by: Martin Wilck +Cc: David Bond +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/alias.c | 31 +++++++++++++++++++++++-------- + tests/alias.c | 2 +- + 2 files changed, 24 insertions(+), 9 deletions(-) + +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index 68f5d848..3e3dfe98 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -120,7 +120,7 @@ static bool alias_already_taken(const char *alias, const char *map_wwid) + if (dm_get_uuid(alias, wwid, sizeof(wwid)) == 0 && + strncmp(map_wwid, wwid, sizeof(wwid)) == 0) + return false; +- condlog(3, "%s: alias '%s' already taken, but not in bindings file. reselecting alias", ++ condlog(3, "%s: alias '%s' already taken, reselecting alias", + map_wwid, alias); + return true; + } +@@ -359,12 +359,11 @@ char *get_user_friendly_alias(const char *wwid, const char *file, const char *al + rlookup_binding(f, buff, alias_old); + + if (strlen(buff) > 0) { +- /* if buff is our wwid, it's already +- * allocated correctly +- */ ++ /* If buff is our wwid, it's already allocated correctly. */ + if (strcmp(buff, wwid) == 0) { + alias = strdup(alias_old); + goto out; ++ + } else { + condlog(0, "alias %s already bound to wwid %s, cannot reuse", + alias_old, buff); +@@ -372,19 +371,35 @@ char *get_user_friendly_alias(const char *wwid, const char *file, const char *al + } + } + +- id = lookup_binding(f, wwid, &alias, NULL, 0); ++ /* ++ * Look for an existing alias in the bindings file. ++ * Pass prefix = NULL, so lookup_binding() won't try to allocate a new id. ++ */ ++ lookup_binding(f, wwid, &alias, NULL, 0); + if (alias) { +- condlog(3, "Use existing binding [%s] for WWID [%s]", +- alias, wwid); ++ if (alias_already_taken(alias, wwid)) { ++ free(alias); ++ alias = NULL; ++ } else ++ condlog(3, "Use existing binding [%s] for WWID [%s]", ++ alias, wwid); + goto out; + } + +- /* allocate the existing alias in the bindings file */ ++ /* alias_old is already taken by our WWID, update bindings file. */ + id = scan_devname(alias_old, prefix); + + new_alias: + if (id <= 0) { ++ /* ++ * no existing alias was provided, or allocating it ++ * failed. Try a new one. ++ */ + id = lookup_binding(f, wwid, &alias, prefix, 1); ++ if (id == 0 && alias_already_taken(alias, wwid)) { ++ free(alias); ++ alias = NULL; ++ } + if (id <= 0) + goto out; + else +diff --git a/tests/alias.c b/tests/alias.c +index 3ca6c28b..11f209e0 100644 +--- a/tests/alias.c ++++ b/tests/alias.c +@@ -398,7 +398,7 @@ static void mock_self_alias(const char *alias, const char *wwid) + will_return(__wrap_dm_get_uuid, wwid); + } + +-#define USED_STR(alias_str, wwid_str) wwid_str ": alias '" alias_str "' already taken, but not in bindings file. reselecting alias\n" ++#define USED_STR(alias_str, wwid_str) wwid_str ": alias '" alias_str "' already taken, reselecting alias\n" + + static void mock_failed_alias(const char *alias, char *msg) + { diff --git a/0005-libmultipath-lookup_binding-add-comment-about-the-al.patch b/0005-libmultipath-lookup_binding-add-comment-about-the-al.patch new file mode 100644 index 0000000..71d077a --- /dev/null +++ b/0005-libmultipath-lookup_binding-add-comment-about-the-al.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 22 Aug 2023 22:30:16 +0200 +Subject: [PATCH] libmultipath: lookup_binding: add comment about the algorithm + +When I read this code, I always get confused. Adding comments to +explain the algorithm. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/alias.c | 35 +++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index 3e3dfe98..9e9ac563 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -172,6 +172,41 @@ lookup_binding(FILE *f, const char *map_wwid, char **map_alias, + alias = strtok_r(buf, " \t", &saveptr); + if (!alias) /* blank line */ + continue; ++ ++ /* ++ * Find an unused index - explanation of the algorithm ++ * ++ * ID: 1 = mpatha, 2 = mpathb, ... ++ * ++ * We assume the bindings are unsorted. The only constraint ++ * is that no ID occurs more than once. IDs that occur in the ++ * bindings are called "used". ++ * ++ * We call the list 1,2,3,..., exactly in this order, the list ++ * of "expected" IDs. The variable "id" always holds the next ++ * "expected" ID, IOW the last "expected" ID encountered plus 1. ++ * Thus all IDs below "id" are known to be used. However, at the ++ * end of the loop, the value of "id" isn't necessarily unused. ++ * ++ * "smallest_bigger_id" is the smallest used ID that was ++ * encountered while it was larger than the next "expected" ID ++ * at that iteration. Let X be some used ID. If all IDs below X ++ * are used and encountered in the right sequence before X, "id" ++ * will be > X when the loop ends. Otherwise, X was encountered ++ * "out of order", the condition (X > id) holds when X is ++ * encountered, and "smallest_bigger_id" will be set to X; i.e. ++ * it will be less or equal than X when the loop ends. ++ * ++ * At the end of the loop, (id < smallest_bigger_id) means that ++ * the value of "id" had been encountered neither in order nor ++ * out of order, and is thus unused. (id >= smallest_bigger_id) ++ * means that "id"'s value is in use. In this case, we play safe ++ * and use "biggest_id + 1" as the next value to try. ++ * ++ * biggest_id is always > smallest_bigger_id, except in the ++ * "perfectly ordered" case. ++ */ ++ + curr_id = scan_devname(alias, prefix); + if (curr_id == id) { + if (id < INT_MAX) diff --git a/0006-multipath-tools-test-simplify-debugging-for-condlog-.patch b/0006-multipath-tools-test-simplify-debugging-for-condlog-.patch new file mode 100644 index 0000000..a206358 --- /dev/null +++ b/0006-multipath-tools-test-simplify-debugging-for-condlog-.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 23 Aug 2023 22:56:41 +0200 +Subject: [PATCH] multipath-tools test: simplify debugging for condlog mismatch + +If there's a mismatch between expected and actual log message, +print both messages. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + tests/test-log.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tests/test-log.c b/tests/test-log.c +index c1745872..63516999 100644 +--- a/tests/test-log.c ++++ b/tests/test-log.c +@@ -16,12 +16,14 @@ void __wrap_dlog (int prio, const char * fmt, ...) + va_list ap; + char *expected; + +- check_expected(prio); + va_start(ap, fmt); + vsnprintf(buff, MAX_MSG_SIZE, fmt, ap); + va_end(ap); + fprintf(stderr, "%s(%d): %s", __func__, prio, buff); + expected = mock_ptr_type(char *); ++ if (memcmp(expected, buff, strlen(expected))) ++ fprintf(stderr, "%s(expected): %s", __func__, expected); ++ check_expected(prio); + assert_memory_equal(buff, expected, strlen(expected)); + } + diff --git a/0007-multipath-tools-tests-add-tests-for-get_user_friendl.patch b/0007-multipath-tools-tests-add-tests-for-get_user_friendl.patch new file mode 100644 index 0000000..f829db4 --- /dev/null +++ b/0007-multipath-tools-tests-add-tests-for-get_user_friendl.patch @@ -0,0 +1,493 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 23 Aug 2023 22:57:29 +0200 +Subject: [PATCH] multipath-tools tests: add tests for + get_user_friendly_alias() + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + tests/alias.c | 441 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 441 insertions(+) + +diff --git a/tests/alias.c b/tests/alias.c +index 11f209e0..7e443b06 100644 +--- a/tests/alias.c ++++ b/tests/alias.c +@@ -81,6 +81,35 @@ int __wrap_dm_get_uuid(const char *name, char *uuid, int uuid_len) + return ret; + } + ++#define TEST_FDNO 1234 ++#define TEST_FPTR ((FILE *) 0xaffe) ++ ++int __wrap_open_file(const char *file, int *can_write, const char *header) ++{ ++ int cw = mock_type(int); ++ ++ *can_write = cw; ++ return TEST_FDNO; ++} ++ ++FILE *__wrap_fdopen(int fd, const char *mode) ++{ ++ assert_int_equal(fd, TEST_FDNO); ++ return TEST_FPTR; ++} ++ ++int __wrap_fflush(FILE *f) ++{ ++ assert_ptr_equal(f, TEST_FPTR); ++ return 0; ++} ++ ++int __wrap_fclose(FILE *f) ++{ ++ assert_ptr_equal(f, TEST_FPTR); ++ return 0; ++} ++ + /* strbuf wrapper for the old format_devname() */ + static int __format_devname(char *name, int id, size_t len, const char *prefix) + { +@@ -399,6 +428,22 @@ static void mock_self_alias(const char *alias, const char *wwid) + } + + #define USED_STR(alias_str, wwid_str) wwid_str ": alias '" alias_str "' already taken, reselecting alias\n" ++#define NOMATCH_STR(alias_str) ("No matching alias [" alias_str "] in bindings file.\n") ++#define FOUND_STR(alias_str, wwid_str) \ ++ "Found matching wwid [" wwid_str "] in bindings file." \ ++ " Setting alias to " alias_str "\n" ++#define FOUND_ALIAS_STR(alias_str, wwid_str) \ ++ "Found matching alias [" alias_str "] in bindings file." \ ++ " Setting wwid to " wwid_str "\n" ++#define NOMATCH_WWID_STR(wwid_str) ("No matching wwid [" wwid_str "] in bindings file.\n") ++#define NEW_STR(alias_str, wwid_str) ("Created new binding [" alias_str "] for WWID [" wwid_str "]\n") ++#define EXISTING_STR(alias_str, wwid_str) ("Use existing binding [" alias_str "] for WWID [" wwid_str "]\n") ++#define ALLOC_STR(alias_str, wwid_str) ("Allocated existing binding [" alias_str "] for WWID [" wwid_str "]\n") ++#define BINDING_STR(alias_str, wwid_str) (alias_str " " wwid_str "\n") ++#define BOUND_STR(alias_str, wwid_str) ("alias "alias_str " already bound to wwid " wwid_str ", cannot reuse") ++#define ERR_STR(alias_str, wwid_str) ("ERROR: old alias [" alias_str "] for wwid [" wwid_str "] is used by other map\n") ++#define REUSE_STR(alias_str, wwid_str) ("alias " alias_str " already bound to wwid " wwid_str ", cannot reuse\n") ++#define NOMORE_STR "no more available user_friendly_names\n" + + static void mock_failed_alias(const char *alias, char *msg) + { +@@ -421,6 +466,24 @@ static void mock_used_alias(const char *alias, char *msg) + expect_condlog(3, msg); + } + ++static void mock_bindings_file(const char *content, int match_line) ++{ ++ static char cnt[1024]; ++ char *token; ++ int i; ++ ++ assert_in_range(strlcpy(cnt, content, sizeof(cnt)), 0, sizeof(cnt) - 1); ++ ++ for (token = strtok(cnt, "\n"), i = 0; ++ token && *token; ++ token = strtok(NULL, "\n"), i++) { ++ will_return(__wrap_fgets, token); ++ if (match_line == i) ++ return; ++ } ++ will_return(__wrap_fgets, NULL); ++} ++ + static void lb_empty(void **state) + { + int rc; +@@ -1147,6 +1210,382 @@ static int test_allocate_binding(void) + return cmocka_run_group_tests(tests, NULL, NULL); + } + ++#define mock_allocate_binding(alias, wwid) \ ++ do { \ ++ static const char ln[] = BINDING_STR(alias, wwid); \ ++ \ ++ will_return(__wrap_lseek, 0); \ ++ expect_value(__wrap_write, count, strlen(ln)); \ ++ expect_string(__wrap_write, buf, ln); \ ++ will_return(__wrap_write, strlen(ln)); \ ++ expect_condlog(3, NEW_STR(alias, wwid)); \ ++ } while (0) ++ ++static void gufa_empty_new_rw(void **state) { ++ char *alias; ++ ++ will_return(__wrap_open_file, true); ++ ++ will_return(__wrap_fgets, NULL); ++ mock_unused_alias("MPATHa"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); ++ ++ mock_allocate_binding("MPATHa", "WWID0"); ++ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false); ++ assert_string_equal(alias, "MPATHa"); ++ free(alias); ++} ++ ++static void gufa_empty_new_ro_1(void **state) { ++ char *alias; ++ will_return(__wrap_open_file, false); ++ will_return(__wrap_fgets, NULL); ++ mock_unused_alias("MPATHa"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); ++ ++ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false); ++ assert_ptr_equal(alias, NULL); ++} ++ ++static void gufa_empty_new_ro_2(void **state) { ++ char *alias; ++ ++ will_return(__wrap_open_file, true); ++ ++ will_return(__wrap_fgets, NULL); ++ mock_unused_alias("MPATHa"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); ++ ++ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); ++ assert_ptr_equal(alias, NULL); ++} ++ ++static void gufa_match_a_unused(void **state) { ++ char *alias; ++ ++ will_return(__wrap_open_file, true); ++ ++ will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0")); ++ expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); ++ mock_unused_alias("MPATHa"); ++ ++ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); ++ assert_string_equal(alias, "MPATHa"); ++ free(alias); ++} ++ ++static void gufa_match_a_self(void **state) { ++ char *alias; ++ ++ will_return(__wrap_open_file, true); ++ ++ will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0")); ++ expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); ++ mock_self_alias("MPATHa", "WWID0"); ++ ++ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); ++ assert_string_equal(alias, "MPATHa"); ++ free(alias); ++} ++ ++static void gufa_match_a_used(void **state) { ++ char *alias; ++ ++ will_return(__wrap_open_file, true); ++ ++ will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0")); ++ expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); ++ mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); ++ ++ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); ++ assert_ptr_equal(alias, NULL); ++} ++ ++static void gufa_nomatch_a_c(void **state) { ++ char *alias; ++ will_return(__wrap_open_file, true); ++ ++ mock_bindings_file("MPATHa WWID0\n" ++ "MPATHc WWID2", ++ -1); ++ mock_unused_alias("MPATHb"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID1")); ++ ++ mock_allocate_binding("MPATHb", "WWID1"); ++ ++ alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false); ++ assert_string_equal(alias, "MPATHb"); ++ free(alias); ++} ++ ++static void gufa_nomatch_c_a(void **state) { ++ char *alias; ++ will_return(__wrap_open_file, true); ++ ++ mock_bindings_file("MPATHc WWID2\n" ++ "MPATHa WWID0", ++ -1); ++ mock_unused_alias("MPATHb"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID1")); ++ ++ mock_allocate_binding("MPATHb", "WWID1"); ++ ++ alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false); ++ assert_string_equal(alias, "MPATHb"); ++ free(alias); ++} ++ ++static void gufa_nomatch_c_b(void **state) { ++ char *alias; ++ will_return(__wrap_open_file, true); ++ ++ mock_bindings_file("MPATHc WWID2\n" ++ "MPATHb WWID1\n", ++ -1); ++ mock_unused_alias("MPATHa"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); ++ ++ mock_allocate_binding("MPATHa", "WWID0"); ++ ++ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false); ++ assert_string_equal(alias, "MPATHa"); ++ free(alias); ++} ++ ++static void gufa_nomatch_c_b_used(void **state) { ++ char *alias; ++ will_return(__wrap_open_file, true); ++ ++ mock_bindings_file("MPATHc WWID2\n" ++ "MPATHb WWID1", ++ -1); ++ mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID4")); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID4")); ++ mock_unused_alias("MPATHd"); ++ ++ mock_allocate_binding("MPATHd", "WWID4"); ++ ++ alias = get_user_friendly_alias("WWID4", "x", "", "MPATH", false); ++ assert_string_equal(alias, "MPATHd"); ++ free(alias); ++} ++ ++static void gufa_nomatch_b_f_a(void **state) { ++ char *alias; ++ will_return(__wrap_open_file, true); ++ ++ mock_bindings_file("MPATHb WWID1\n" ++ "MPATHf WWID6\n" ++ "MPATHa WWID0\n", ++ -1); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID7")); ++ mock_unused_alias("MPATHg"); ++ ++ mock_allocate_binding("MPATHg", "WWID7"); ++ ++ alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false); ++ assert_string_equal(alias, "MPATHg"); ++ free(alias); ++} ++ ++static void gufa_old_empty(void **state) { ++ char *alias; ++ will_return(__wrap_open_file, true); ++ ++ /* rlookup_binding for ALIAS */ ++ will_return(__wrap_fgets, NULL); ++ expect_condlog(3, NOMATCH_STR("MPATHz")); ++ ++ /* lookup_binding */ ++ will_return(__wrap_fgets, NULL); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); ++ ++ mock_allocate_binding("MPATHz", "WWID0"); ++ expect_condlog(2, ALLOC_STR("MPATHz", "WWID0")); ++ ++ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); ++ assert_string_equal(alias, "MPATHz"); ++ free(alias); ++} ++ ++static void gufa_old_match(void **state) { ++ char *alias; ++ will_return(__wrap_open_file, true); ++ ++ mock_bindings_file("MPATHb WWID1\n" ++ "MPATHz WWID0", ++ 1); ++ expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID0")); ++ ++ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); ++ assert_string_equal(alias, "MPATHz"); ++ free(alias); ++} ++ ++static void gufa_old_match_other(void **state) { ++ char *alias; ++ static const char bindings[] = "MPATHz WWID9"; ++ ++ will_return(__wrap_open_file, true); ++ ++ mock_bindings_file(bindings, 0); ++ expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9")); ++ expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); ++ ++ mock_bindings_file(bindings, -1); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); ++ mock_unused_alias("MPATHa"); ++ ++ mock_allocate_binding("MPATHa", "WWID0"); ++ ++ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); ++ assert_string_equal(alias, "MPATHa"); ++ free(alias); ++} ++ ++static void gufa_old_match_other_used(void **state) { ++ char *alias; ++ static const char bindings[] = "MPATHz WWID9"; ++ ++ will_return(__wrap_open_file, true); ++ ++ mock_bindings_file(bindings, 0); ++ expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9")); ++ expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); ++ ++ mock_bindings_file(bindings, -1); ++ mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); ++ mock_unused_alias("MPATHb"); ++ ++ mock_allocate_binding("MPATHb", "WWID0"); ++ ++ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); ++ assert_string_equal(alias, "MPATHb"); ++ free(alias); ++} ++ ++static void gufa_old_match_other_wwidmatch(void **state) { ++ char *alias; ++ static const char bindings[] = ("MPATHz WWID9\n" ++ "MPATHc WWID2"); ++ will_return(__wrap_open_file, true); ++ ++ mock_bindings_file(bindings, 0); ++ expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9")); ++ expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); ++ ++ mock_bindings_file(bindings, 1); ++ expect_condlog(3, FOUND_STR("MPATHc", "WWID2")); ++ mock_unused_alias("MPATHc"); ++ ++ alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false); ++ assert_string_equal(alias, "MPATHc"); ++ free(alias); ++} ++ ++static void gufa_old_match_other_wwidmatch_used(void **state) { ++ char *alias; ++ static const char bindings[] = ("MPATHz WWID9\n" ++ "MPATHc WWID2"); ++ ++ will_return(__wrap_open_file, true); ++ ++ mock_bindings_file(bindings, 0); ++ expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9")); ++ expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); ++ ++ mock_bindings_file(bindings, 1); ++ expect_condlog(3, FOUND_STR("MPATHc", "WWID2")); ++ mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2")); ++ ++ alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false); ++ assert_ptr_equal(alias, NULL); ++} ++ ++static void gufa_old_nomatch_wwidmatch(void **state) { ++ char *alias; ++ static const char bindings[] = "MPATHa WWID0"; ++ ++ will_return(__wrap_open_file, true); ++ ++ mock_bindings_file(bindings, -1); ++ expect_condlog(3, NOMATCH_STR("MPATHz")); ++ ++ mock_bindings_file(bindings, 0); ++ expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); ++ mock_unused_alias("MPATHa"); ++ expect_condlog(3, EXISTING_STR("MPATHa", "WWID0")); ++ ++ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); ++ assert_string_equal(alias, "MPATHa"); ++ free(alias); ++} ++ ++static void gufa_old_nomatch_wwidmatch_used(void **state) { ++ char *alias; ++ static const char bindings[] = "MPATHa WWID0"; ++ will_return(__wrap_open_file, true); ++ ++ mock_bindings_file(bindings, -1); ++ expect_condlog(3, NOMATCH_STR("MPATHz")); ++ ++ mock_bindings_file(bindings, 0); ++ expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); ++ mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); ++ ++ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); ++ assert_ptr_equal(alias, NULL); ++} ++ ++static void gufa_old_nomatch_nowwidmatch(void **state) { ++ char *alias; ++ static const char bindings[] = "MPATHb WWID1"; ++ ++ will_return(__wrap_open_file, true); ++ ++ mock_bindings_file(bindings, -1); ++ expect_condlog(3, NOMATCH_STR("MPATHz")); ++ ++ mock_bindings_file(bindings, -1); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); ++ ++ mock_allocate_binding("MPATHz", "WWID0"); ++ expect_condlog(2, ALLOC_STR("MPATHz", "WWID0")); ++ ++ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); ++ assert_string_equal(alias, "MPATHz"); ++ free(alias); ++} ++ ++static int test_get_user_friendly_alias() ++{ ++ const struct CMUnitTest tests[] = { ++ cmocka_unit_test(gufa_empty_new_rw), ++ cmocka_unit_test(gufa_empty_new_ro_1), ++ cmocka_unit_test(gufa_empty_new_ro_2), ++ cmocka_unit_test(gufa_match_a_unused), ++ cmocka_unit_test(gufa_match_a_self), ++ cmocka_unit_test(gufa_match_a_used), ++ cmocka_unit_test(gufa_nomatch_a_c), ++ cmocka_unit_test(gufa_nomatch_c_a), ++ cmocka_unit_test(gufa_nomatch_c_b), ++ cmocka_unit_test(gufa_nomatch_c_b_used), ++ cmocka_unit_test(gufa_nomatch_b_f_a), ++ cmocka_unit_test(gufa_old_empty), ++ cmocka_unit_test(gufa_old_match), ++ cmocka_unit_test(gufa_old_match_other), ++ cmocka_unit_test(gufa_old_match_other_used), ++ cmocka_unit_test(gufa_old_match_other_wwidmatch), ++ cmocka_unit_test(gufa_old_match_other_wwidmatch_used), ++ cmocka_unit_test(gufa_old_nomatch_wwidmatch), ++ cmocka_unit_test(gufa_old_nomatch_wwidmatch_used), ++ cmocka_unit_test(gufa_old_nomatch_nowwidmatch), ++ }; ++ ++ return cmocka_run_group_tests(tests, NULL, NULL); ++} ++ + int main(void) + { + int ret = 0; +@@ -1157,6 +1596,8 @@ int main(void) + ret += test_lookup_binding(); + ret += test_rlookup_binding(); + ret += test_allocate_binding(); ++ ret += test_allocate_binding(); ++ ret += test_get_user_friendly_alias(); + + return ret; + } diff --git a/0008-multipath-tools-test-consistent-use-of-macros-in-ali.patch b/0008-multipath-tools-test-consistent-use-of-macros-in-ali.patch new file mode 100644 index 0000000..430ceaf --- /dev/null +++ b/0008-multipath-tools-test-consistent-use-of-macros-in-ali.patch @@ -0,0 +1,365 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 24 Aug 2023 10:40:32 +0200 +Subject: [PATCH] multipath-tools test: consistent use of macros in alias test + +Use the macros introduced with the tests for get_user_friendly_alias() +also in the previously existing tests. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + tests/alias.c | 80 ++++++++++++++++++++++++--------------------------- + 1 file changed, 38 insertions(+), 42 deletions(-) + +diff --git a/tests/alias.c b/tests/alias.c +index 7e443b06..427b2814 100644 +--- a/tests/alias.c ++++ b/tests/alias.c +@@ -490,7 +490,7 @@ static void lb_empty(void **state) + char *alias; + + will_return(__wrap_fgets, NULL); +- expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + rc = lookup_binding(NULL, "WWID0", &alias, NULL, 0); + assert_int_equal(rc, 1); + assert_ptr_equal(alias, NULL); +@@ -503,7 +503,7 @@ static void lb_empty_unused(void **state) + + will_return(__wrap_fgets, NULL); + mock_unused_alias("MPATHa"); +- expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); + assert_int_equal(rc, 1); + assert_ptr_equal(alias, NULL); +@@ -518,7 +518,7 @@ static void lb_empty_failed(void **state) + will_return(__wrap_fgets, NULL); + mock_failed_alias("MPATHa", USED_STR("MPATHa", "WWID0")); + mock_unused_alias("MPATHb"); +- expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); + assert_int_equal(rc, 2); + assert_ptr_equal(alias, NULL); +@@ -533,7 +533,7 @@ static void lb_empty_1_used(void **state) + will_return(__wrap_fgets, NULL); + mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); + mock_unused_alias("MPATHb"); +- expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); + assert_int_equal(rc, 2); + assert_ptr_equal(alias, NULL); +@@ -548,7 +548,7 @@ static void lb_empty_1_used_self(void **state) + will_return(__wrap_fgets, NULL); + mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); + mock_self_alias("MPATHb", "WWID0"); +- expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); + assert_int_equal(rc, 2); + assert_ptr_equal(alias, NULL); +@@ -561,8 +561,7 @@ static void lb_match_a(void **state) + char *alias; + + will_return(__wrap_fgets, "MPATHa WWID0\n"); +- expect_condlog(3, "Found matching wwid [WWID0] in bindings file." +- " Setting alias to MPATHa\n"); ++ expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); + rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 0); + assert_int_equal(rc, 0); + assert_ptr_not_equal(alias, NULL); +@@ -577,7 +576,7 @@ static void lb_nomatch_a(void **state) + + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, NULL); +- expect_condlog(3, "No matching wwid [WWID1] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID1")); + rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 0); + assert_int_equal(rc, 2); + assert_ptr_equal(alias, NULL); +@@ -590,7 +589,7 @@ static void lb_nomatch_a_bad_check(void **state) + + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, NULL); +- expect_condlog(0, "no more available user_friendly_names\n"); ++ expect_condlog(0, NOMORE_STR); + rc = lookup_binding(NULL, "WWID1", &alias, NULL, 1); + assert_int_equal(rc, -1); + assert_ptr_equal(alias, NULL); +@@ -604,7 +603,7 @@ static void lb_nomatch_a_unused(void **state) + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, NULL); + mock_unused_alias("MPATHb"); +- expect_condlog(3, "No matching wwid [WWID1] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID1")); + rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); + assert_int_equal(rc, 2); + assert_ptr_equal(alias, NULL); +@@ -622,7 +621,7 @@ static void lb_nomatch_a_3_used_failed_self(void **state) + mock_used_alias("MPATHd", USED_STR("MPATHd", "WWID1")); + mock_failed_alias("MPATHe", USED_STR("MPATHe", "WWID1")); + mock_self_alias("MPATHf", "WWID1"); +- expect_condlog(3, "No matching wwid [WWID1] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID1")); + rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); + assert_int_equal(rc, 6); + assert_ptr_equal(alias, NULL); +@@ -635,8 +634,7 @@ static void do_lb_match_c(void **state, int check_if_taken) + + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, "MPATHc WWID1\n"); +- expect_condlog(3, "Found matching wwid [WWID1] in bindings file." +- " Setting alias to MPATHc\n"); ++ expect_condlog(3, FOUND_STR("MPATHc", "WWID1")); + rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", check_if_taken); + assert_int_equal(rc, 0); + assert_ptr_not_equal(alias, NULL); +@@ -662,7 +660,7 @@ static void lb_nomatch_a_c(void **state) + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, "MPATHc WWID1\n"); + will_return(__wrap_fgets, NULL); +- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); + assert_int_equal(rc, 2); + assert_ptr_equal(alias, NULL); +@@ -677,7 +675,7 @@ static void lb_nomatch_a_d_unused(void **state) + will_return(__wrap_fgets, "MPATHd WWID1\n"); + will_return(__wrap_fgets, NULL); + mock_unused_alias("MPATHb"); +- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, 2); + assert_ptr_equal(alias, NULL); +@@ -693,7 +691,7 @@ static void lb_nomatch_a_d_1_used(void **state) + will_return(__wrap_fgets, NULL); + mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2")); + mock_unused_alias("MPATHc"); +- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, 3); + assert_ptr_equal(alias, NULL); +@@ -710,7 +708,7 @@ static void lb_nomatch_a_d_2_used(void **state) + mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2")); + mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2")); + mock_unused_alias("MPATHe"); +- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, 5); + assert_ptr_equal(alias, NULL); +@@ -728,7 +726,7 @@ static void lb_nomatch_a_d_3_used(void **state) + mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2")); + mock_used_alias("MPATHe", USED_STR("MPATHe", "WWID2")); + mock_unused_alias("MPATHf"); +- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, 6); + assert_ptr_equal(alias, NULL); +@@ -742,7 +740,7 @@ static void lb_nomatch_c_a(void **state) + will_return(__wrap_fgets, "MPATHc WWID1\n"); + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, NULL); +- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); + assert_int_equal(rc, 2); + assert_ptr_equal(alias, NULL); +@@ -758,7 +756,7 @@ static void lb_nomatch_d_a_unused(void **state) + will_return(__wrap_fgets, "MPATHd WWID0\n"); + will_return(__wrap_fgets, NULL); + mock_unused_alias("MPATHb"); +- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, 2); + assert_ptr_equal(alias, NULL); +@@ -775,7 +773,7 @@ static void lb_nomatch_d_a_1_used(void **state) + will_return(__wrap_fgets, NULL); + mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2")); + mock_unused_alias("MPATHe"); +- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, 5); + assert_ptr_equal(alias, NULL); +@@ -790,7 +788,7 @@ static void lb_nomatch_a_b(void **state) + will_return(__wrap_fgets, "MPATHz WWID26\n"); + will_return(__wrap_fgets, "MPATHb WWID1\n"); + will_return(__wrap_fgets, NULL); +- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); + assert_int_equal(rc, 3); + assert_ptr_equal(alias, NULL); +@@ -806,7 +804,7 @@ static void lb_nomatch_a_b_bad(void **state) + will_return(__wrap_fgets, "MPATHb\n"); + will_return(__wrap_fgets, NULL); + expect_condlog(3, "Ignoring malformed line 3 in bindings file\n"); +- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); + assert_int_equal(rc, 3); + assert_ptr_equal(alias, NULL); +@@ -823,7 +821,7 @@ static void lb_nomatch_a_b_bad_self(void **state) + will_return(__wrap_fgets, NULL); + expect_condlog(3, "Ignoring malformed line 3 in bindings file\n"); + mock_self_alias("MPATHc", "WWID2"); +- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, 3); + assert_ptr_equal(alias, NULL); +@@ -838,7 +836,7 @@ static void lb_nomatch_b_a(void **state) + will_return(__wrap_fgets, "MPATHz WWID26\n"); + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, NULL); +- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); + assert_int_equal(rc, 27); + assert_ptr_equal(alias, NULL); +@@ -857,7 +855,7 @@ static void lb_nomatch_b_a_3_used(void **state) + mock_used_alias("MPATHab", USED_STR("MPATHab", "WWID2")); + mock_used_alias("MPATHac", USED_STR("MPATHac", "WWID2")); + mock_unused_alias("MPATHad"); +- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, 30); + assert_ptr_equal(alias, NULL); +@@ -873,7 +871,7 @@ static void do_lb_nomatch_int_max(void **state, int check_if_taken) + will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n"); + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, NULL); +- expect_condlog(0, "no more available user_friendly_names\n"); ++ expect_condlog(0, NOMORE_STR); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", check_if_taken); + assert_int_equal(rc, -1); + assert_ptr_equal(alias, NULL); +@@ -898,7 +896,7 @@ static void lb_nomatch_int_max_used(void **state) + will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n"); + will_return(__wrap_fgets, NULL); + mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2")); +- expect_condlog(0, "no more available user_friendly_names\n"); ++ expect_condlog(0, NOMORE_STR); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, -1); + assert_ptr_equal(alias, NULL); +@@ -913,7 +911,7 @@ static void lb_nomatch_int_max_m1(void **state) + will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, NULL); +- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); + assert_int_equal(rc, INT_MAX); + assert_ptr_equal(alias, NULL); +@@ -929,7 +927,7 @@ static void lb_nomatch_int_max_m1_used(void **state) + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, NULL); + mock_used_alias("MPATH" MPATH_ID_INT_MAX, USED_STR("MPATH" MPATH_ID_INT_MAX, "WWID2")); +- expect_condlog(0, "no more available user_friendly_names\n"); ++ expect_condlog(0, NOMORE_STR); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, -1); + assert_ptr_equal(alias, NULL); +@@ -945,7 +943,7 @@ static void lb_nomatch_int_max_m1_1_used(void **state) + will_return(__wrap_fgets, NULL); + mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2")); + mock_unused_alias("MPATH" MPATH_ID_INT_MAX); +- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, INT_MAX); + assert_ptr_equal(alias, NULL); +@@ -961,7 +959,7 @@ static void lb_nomatch_int_max_m1_2_used(void **state) + will_return(__wrap_fgets, NULL); + mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2")); + mock_used_alias("MPATH" MPATH_ID_INT_MAX, USED_STR("MPATH" MPATH_ID_INT_MAX, "WWID2")); +- expect_condlog(0, "no more available user_friendly_names\n"); ++ expect_condlog(0, NOMORE_STR); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, -1); + assert_ptr_equal(alias, NULL); +@@ -1017,7 +1015,7 @@ static void rl_empty(void **state) + + buf[0] = '\0'; + will_return(__wrap_fgets, NULL); +- expect_condlog(3, "No matching alias [MPATHa] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_STR("MPATHa")); + rc = rlookup_binding(NULL, buf, "MPATHa"); + assert_int_equal(rc, -1); + assert_string_equal(buf, ""); +@@ -1030,8 +1028,7 @@ static void rl_match_a(void **state) + + buf[0] = '\0'; + will_return(__wrap_fgets, "MPATHa WWID0\n"); +- expect_condlog(3, "Found matching alias [MPATHa] in bindings file. " +- "Setting wwid to WWID0\n"); ++ expect_condlog(3, FOUND_ALIAS_STR("MPATHa", "WWID0")); + rc = rlookup_binding(NULL, buf, "MPATHa"); + assert_int_equal(rc, 0); + assert_string_equal(buf, "WWID0"); +@@ -1045,7 +1042,7 @@ static void rl_nomatch_a(void **state) + buf[0] = '\0'; + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, NULL); +- expect_condlog(3, "No matching alias [MPATHb] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_STR("MPATHb")); + rc = rlookup_binding(NULL, buf, "MPATHb"); + assert_int_equal(rc, -1); + assert_string_equal(buf, ""); +@@ -1060,7 +1057,7 @@ static void rl_malformed_a(void **state) + will_return(__wrap_fgets, "MPATHa \n"); + will_return(__wrap_fgets, NULL); + expect_condlog(3, "Ignoring malformed line 1 in bindings file\n"); +- expect_condlog(3, "No matching alias [MPATHa] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_STR("MPATHa")); + rc = rlookup_binding(NULL, buf, "MPATHa"); + assert_int_equal(rc, -1); + assert_string_equal(buf, ""); +@@ -1080,7 +1077,7 @@ static void rl_overlong_a(void **state) + will_return(__wrap_fgets, line); + will_return(__wrap_fgets, NULL); + expect_condlog(3, "Ignoring too large wwid at 1 in bindings file\n"); +- expect_condlog(3, "No matching alias [MPATHa] in bindings file.\n"); ++ expect_condlog(3, NOMATCH_STR("MPATHa")); + rc = rlookup_binding(NULL, buf, "MPATHa"); + assert_int_equal(rc, -1); + assert_string_equal(buf, ""); +@@ -1095,8 +1092,7 @@ static void rl_match_b(void **state) + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, "MPATHz WWID26\n"); + will_return(__wrap_fgets, "MPATHb WWID2\n"); +- expect_condlog(3, "Found matching alias [MPATHb] in bindings file. " +- "Setting wwid to WWID2\n"); ++ expect_condlog(3, FOUND_ALIAS_STR("MPATHb", "WWID2")); + rc = rlookup_binding(NULL, buf, "MPATHb"); + assert_int_equal(rc, 0); + assert_string_equal(buf, "WWID2"); +@@ -1125,7 +1121,7 @@ static void al_a(void **state) + expect_value(__wrap_write, count, strlen(ln)); + expect_string(__wrap_write, buf, ln); + will_return(__wrap_write, strlen(ln)); +- expect_condlog(3, "Created new binding [MPATHa] for WWID [WWIDa]\n"); ++ expect_condlog(3, NEW_STR("MPATHa", "WWIDa")); + + alias = allocate_binding(0, "WWIDa", 1, "MPATH"); + assert_ptr_not_equal(alias, NULL); +@@ -1142,7 +1138,7 @@ static void al_zz(void **state) + expect_value(__wrap_write, count, strlen(ln)); + expect_string(__wrap_write, buf, ln); + will_return(__wrap_write, strlen(ln)); +- expect_condlog(3, "Created new binding [MPATHzz] for WWID [WWIDzz]\n"); ++ expect_condlog(3, NEW_STR("MPATHzz", "WWIDzz")); + + alias = allocate_binding(0, "WWIDzz", 26*26 + 26, "MPATH"); + assert_ptr_not_equal(alias, NULL); diff --git a/0009-multipath-tools-tests-convert-mock_-failed-used-_ali.patch b/0009-multipath-tools-tests-convert-mock_-failed-used-_ali.patch new file mode 100644 index 0000000..9d71adf --- /dev/null +++ b/0009-multipath-tools-tests-convert-mock_-failed-used-_ali.patch @@ -0,0 +1,246 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 24 Aug 2023 10:49:32 +0200 +Subject: [PATCH] multipath-tools tests: convert mock_{failed,used}_alias to + macros + +This way we can further improve readability of the individual test +cases. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + tests/alias.c | 92 +++++++++++++++++++++++++-------------------------- + 1 file changed, 46 insertions(+), 46 deletions(-) + +diff --git a/tests/alias.c b/tests/alias.c +index 427b2814..a32b43e8 100644 +--- a/tests/alias.c ++++ b/tests/alias.c +@@ -445,26 +445,26 @@ static void mock_self_alias(const char *alias, const char *wwid) + #define REUSE_STR(alias_str, wwid_str) ("alias " alias_str " already bound to wwid " wwid_str ", cannot reuse\n") + #define NOMORE_STR "no more available user_friendly_names\n" + +-static void mock_failed_alias(const char *alias, char *msg) +-{ +- expect_string(__wrap_dm_map_present, str, alias); +- will_return(__wrap_dm_map_present, 1); +- expect_string(__wrap_dm_get_uuid, name, alias); +- expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); +- will_return(__wrap_dm_get_uuid, 1); +- expect_condlog(3, msg); +-} ++#define mock_failed_alias(alias, wwid) \ ++ do { \ ++ expect_string(__wrap_dm_map_present, str, alias); \ ++ will_return(__wrap_dm_map_present, 1); \ ++ expect_string(__wrap_dm_get_uuid, name, alias); \ ++ expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); \ ++ will_return(__wrap_dm_get_uuid, 1); \ ++ expect_condlog(3, USED_STR(alias, wwid)); \ ++ } while (0) + +-static void mock_used_alias(const char *alias, char *msg) +-{ +- expect_string(__wrap_dm_map_present, str, alias); +- will_return(__wrap_dm_map_present, 1); +- expect_string(__wrap_dm_get_uuid, name, alias); +- expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); +- will_return(__wrap_dm_get_uuid, 0); +- will_return(__wrap_dm_get_uuid, "WWID_USED"); +- expect_condlog(3, msg); +-} ++#define mock_used_alias(alias, wwid) \ ++ do { \ ++ expect_string(__wrap_dm_map_present, str, alias); \ ++ will_return(__wrap_dm_map_present, 1); \ ++ expect_string(__wrap_dm_get_uuid, name, alias); \ ++ expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); \ ++ will_return(__wrap_dm_get_uuid, 0); \ ++ will_return(__wrap_dm_get_uuid, "WWID_USED"); \ ++ expect_condlog(3, USED_STR(alias, wwid)); \ ++ } while(0) + + static void mock_bindings_file(const char *content, int match_line) + { +@@ -516,7 +516,7 @@ static void lb_empty_failed(void **state) + char *alias; + + will_return(__wrap_fgets, NULL); +- mock_failed_alias("MPATHa", USED_STR("MPATHa", "WWID0")); ++ mock_failed_alias("MPATHa", "WWID0"); + mock_unused_alias("MPATHb"); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); +@@ -531,7 +531,7 @@ static void lb_empty_1_used(void **state) + char *alias; + + will_return(__wrap_fgets, NULL); +- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); ++ mock_used_alias("MPATHa", "WWID0"); + mock_unused_alias("MPATHb"); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); +@@ -546,7 +546,7 @@ static void lb_empty_1_used_self(void **state) + char *alias; + + will_return(__wrap_fgets, NULL); +- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); ++ mock_used_alias("MPATHa", "WWID0"); + mock_self_alias("MPATHb", "WWID0"); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); +@@ -616,10 +616,10 @@ static void lb_nomatch_a_3_used_failed_self(void **state) + + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, NULL); +- mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID1")); +- mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID1")); +- mock_used_alias("MPATHd", USED_STR("MPATHd", "WWID1")); +- mock_failed_alias("MPATHe", USED_STR("MPATHe", "WWID1")); ++ mock_used_alias("MPATHb", "WWID1"); ++ mock_used_alias("MPATHc", "WWID1"); ++ mock_used_alias("MPATHd", "WWID1"); ++ mock_failed_alias("MPATHe", "WWID1"); + mock_self_alias("MPATHf", "WWID1"); + expect_condlog(3, NOMATCH_WWID_STR("WWID1")); + rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); +@@ -689,7 +689,7 @@ static void lb_nomatch_a_d_1_used(void **state) + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, "MPATHd WWID1\n"); + will_return(__wrap_fgets, NULL); +- mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2")); ++ mock_used_alias("MPATHb", "WWID2"); + mock_unused_alias("MPATHc"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); +@@ -705,8 +705,8 @@ static void lb_nomatch_a_d_2_used(void **state) + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, "MPATHd WWID1\n"); + will_return(__wrap_fgets, NULL); +- mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2")); +- mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2")); ++ mock_used_alias("MPATHb", "WWID2"); ++ mock_used_alias("MPATHc", "WWID2"); + mock_unused_alias("MPATHe"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); +@@ -722,9 +722,9 @@ static void lb_nomatch_a_d_3_used(void **state) + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, "MPATHd WWID1\n"); + will_return(__wrap_fgets, NULL); +- mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2")); +- mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2")); +- mock_used_alias("MPATHe", USED_STR("MPATHe", "WWID2")); ++ mock_used_alias("MPATHb", "WWID2"); ++ mock_used_alias("MPATHc", "WWID2"); ++ mock_used_alias("MPATHe", "WWID2"); + mock_unused_alias("MPATHf"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); +@@ -771,7 +771,7 @@ static void lb_nomatch_d_a_1_used(void **state) + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, "MPATHd WWID0\n"); + will_return(__wrap_fgets, NULL); +- mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2")); ++ mock_used_alias("MPATHb", "WWID2"); + mock_unused_alias("MPATHe"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); +@@ -851,9 +851,9 @@ static void lb_nomatch_b_a_3_used(void **state) + will_return(__wrap_fgets, "MPATHz WWID26\n"); + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, NULL); +- mock_used_alias("MPATHaa", USED_STR("MPATHaa", "WWID2")); +- mock_used_alias("MPATHab", USED_STR("MPATHab", "WWID2")); +- mock_used_alias("MPATHac", USED_STR("MPATHac", "WWID2")); ++ mock_used_alias("MPATHaa", "WWID2"); ++ mock_used_alias("MPATHab", "WWID2"); ++ mock_used_alias("MPATHac", "WWID2"); + mock_unused_alias("MPATHad"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); +@@ -895,7 +895,7 @@ static void lb_nomatch_int_max_used(void **state) + will_return(__wrap_fgets, "MPATHb WWID1\n"); + will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n"); + will_return(__wrap_fgets, NULL); +- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2")); ++ mock_used_alias("MPATHa", "WWID2"); + expect_condlog(0, NOMORE_STR); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, -1); +@@ -926,7 +926,7 @@ static void lb_nomatch_int_max_m1_used(void **state) + will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); + will_return(__wrap_fgets, "MPATHa WWID0\n"); + will_return(__wrap_fgets, NULL); +- mock_used_alias("MPATH" MPATH_ID_INT_MAX, USED_STR("MPATH" MPATH_ID_INT_MAX, "WWID2")); ++ mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2"); + expect_condlog(0, NOMORE_STR); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, -1); +@@ -941,7 +941,7 @@ static void lb_nomatch_int_max_m1_1_used(void **state) + will_return(__wrap_fgets, "MPATHb WWID1\n"); + will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); + will_return(__wrap_fgets, NULL); +- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2")); ++ mock_used_alias("MPATHa", "WWID2"); + mock_unused_alias("MPATH" MPATH_ID_INT_MAX); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); +@@ -957,8 +957,8 @@ static void lb_nomatch_int_max_m1_2_used(void **state) + will_return(__wrap_fgets, "MPATHb WWID1\n"); + will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); + will_return(__wrap_fgets, NULL); +- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2")); +- mock_used_alias("MPATH" MPATH_ID_INT_MAX, USED_STR("MPATH" MPATH_ID_INT_MAX, "WWID2")); ++ mock_used_alias("MPATHa", "WWID2"); ++ mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2"); + expect_condlog(0, NOMORE_STR); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, -1); +@@ -1291,7 +1291,7 @@ static void gufa_match_a_used(void **state) { + + will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0")); + expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); +- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); ++ mock_used_alias("MPATHa", "WWID0"); + + alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); + assert_ptr_equal(alias, NULL); +@@ -1355,7 +1355,7 @@ static void gufa_nomatch_c_b_used(void **state) { + mock_bindings_file("MPATHc WWID2\n" + "MPATHb WWID1", + -1); +- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID4")); ++ mock_used_alias("MPATHa", "WWID4"); + expect_condlog(3, NOMATCH_WWID_STR("WWID4")); + mock_unused_alias("MPATHd"); + +@@ -1450,7 +1450,7 @@ static void gufa_old_match_other_used(void **state) { + expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); + + mock_bindings_file(bindings, -1); +- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); ++ mock_used_alias("MPATHa", "WWID0"); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + mock_unused_alias("MPATHb"); + +@@ -1493,7 +1493,7 @@ static void gufa_old_match_other_wwidmatch_used(void **state) { + + mock_bindings_file(bindings, 1); + expect_condlog(3, FOUND_STR("MPATHc", "WWID2")); +- mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2")); ++ mock_used_alias("MPATHc", "WWID2"); + + alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false); + assert_ptr_equal(alias, NULL); +@@ -1528,7 +1528,7 @@ static void gufa_old_nomatch_wwidmatch_used(void **state) { + + mock_bindings_file(bindings, 0); + expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); +- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); ++ mock_used_alias("MPATHa", "WWID0"); + + alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); + assert_ptr_equal(alias, NULL); diff --git a/0010-multipath-tools-test-use-mock_bindings_file-consiste.patch b/0010-multipath-tools-test-use-mock_bindings_file-consiste.patch new file mode 100644 index 0000000..2105f5a --- /dev/null +++ b/0010-multipath-tools-test-use-mock_bindings_file-consiste.patch @@ -0,0 +1,500 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 24 Aug 2023 11:13:44 +0200 +Subject: [PATCH] multipath-tools test: use mock_bindings_file() consistently + +Further improve test readablity. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + tests/alias.c | 178 +++++++++++++++++++++----------------------------- + 1 file changed, 76 insertions(+), 102 deletions(-) + +diff --git a/tests/alias.c b/tests/alias.c +index a32b43e8..f334f928 100644 +--- a/tests/alias.c ++++ b/tests/alias.c +@@ -489,7 +489,7 @@ static void lb_empty(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("", -1); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + rc = lookup_binding(NULL, "WWID0", &alias, NULL, 0); + assert_int_equal(rc, 1); +@@ -501,7 +501,7 @@ static void lb_empty_unused(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("", -1); + mock_unused_alias("MPATHa"); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); +@@ -515,7 +515,7 @@ static void lb_empty_failed(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("", -1); + mock_failed_alias("MPATHa", "WWID0"); + mock_unused_alias("MPATHb"); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); +@@ -530,7 +530,7 @@ static void lb_empty_1_used(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("", -1); + mock_used_alias("MPATHa", "WWID0"); + mock_unused_alias("MPATHb"); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); +@@ -545,7 +545,7 @@ static void lb_empty_1_used_self(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("", -1); + mock_used_alias("MPATHa", "WWID0"); + mock_self_alias("MPATHb", "WWID0"); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); +@@ -560,7 +560,7 @@ static void lb_match_a(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHa WWID0\n"); ++ mock_bindings_file("MPATHa WWID0\n", 0); + expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); + rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 0); + assert_int_equal(rc, 0); +@@ -574,8 +574,7 @@ static void lb_nomatch_a(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHa WWID0\n", -1); + expect_condlog(3, NOMATCH_WWID_STR("WWID1")); + rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 0); + assert_int_equal(rc, 2); +@@ -587,8 +586,7 @@ static void lb_nomatch_a_bad_check(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHa WWID0\n", -1); + expect_condlog(0, NOMORE_STR); + rc = lookup_binding(NULL, "WWID1", &alias, NULL, 1); + assert_int_equal(rc, -1); +@@ -600,8 +598,7 @@ static void lb_nomatch_a_unused(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHa WWID0\n", -1); + mock_unused_alias("MPATHb"); + expect_condlog(3, NOMATCH_WWID_STR("WWID1")); + rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); +@@ -614,8 +611,7 @@ static void lb_nomatch_a_3_used_failed_self(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHa WWID0\n", -1); + mock_used_alias("MPATHb", "WWID1"); + mock_used_alias("MPATHc", "WWID1"); + mock_used_alias("MPATHd", "WWID1"); +@@ -632,8 +628,8 @@ static void do_lb_match_c(void **state, int check_if_taken) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, "MPATHc WWID1\n"); ++ mock_bindings_file("MPATHa WWID0\n" ++ "MPATHc WWID1", 1); + expect_condlog(3, FOUND_STR("MPATHc", "WWID1")); + rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", check_if_taken); + assert_int_equal(rc, 0); +@@ -657,9 +653,8 @@ static void lb_nomatch_a_c(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, "MPATHc WWID1\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHa WWID0\n" ++ "MPATHc WWID1", -1); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); + assert_int_equal(rc, 2); +@@ -671,9 +666,8 @@ static void lb_nomatch_a_d_unused(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, "MPATHd WWID1\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHa WWID0\n" ++ "MPATHd WWID1", -1); + mock_unused_alias("MPATHb"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); +@@ -686,9 +680,8 @@ static void lb_nomatch_a_d_1_used(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, "MPATHd WWID1\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHa WWID0\n" ++ "MPATHd WWID1", -1); + mock_used_alias("MPATHb", "WWID2"); + mock_unused_alias("MPATHc"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); +@@ -702,9 +695,8 @@ static void lb_nomatch_a_d_2_used(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, "MPATHd WWID1\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHa WWID0\n" ++ "MPATHd WWID1", -1); + mock_used_alias("MPATHb", "WWID2"); + mock_used_alias("MPATHc", "WWID2"); + mock_unused_alias("MPATHe"); +@@ -719,9 +711,8 @@ static void lb_nomatch_a_d_3_used(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, "MPATHd WWID1\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHa WWID0\n" ++ "MPATHd WWID1", -1); + mock_used_alias("MPATHb", "WWID2"); + mock_used_alias("MPATHc", "WWID2"); + mock_used_alias("MPATHe", "WWID2"); +@@ -737,9 +728,8 @@ static void lb_nomatch_c_a(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHc WWID1\n"); +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHc WWID1\n" ++ "MPATHa WWID0\n", -1); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); + assert_int_equal(rc, 2); +@@ -751,10 +741,9 @@ static void lb_nomatch_d_a_unused(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHc WWID1\n"); +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, "MPATHd WWID0\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHc WWID1\n" ++ "MPATHa WWID0\n" ++ "MPATHd WWID0\n", -1); + mock_unused_alias("MPATHb"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); +@@ -767,10 +756,9 @@ static void lb_nomatch_d_a_1_used(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHc WWID1\n"); +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, "MPATHd WWID0\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHc WWID1\n" ++ "MPATHa WWID0\n" ++ "MPATHd WWID0\n", -1); + mock_used_alias("MPATHb", "WWID2"); + mock_unused_alias("MPATHe"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); +@@ -784,10 +772,9 @@ static void lb_nomatch_a_b(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, "MPATHz WWID26\n"); +- will_return(__wrap_fgets, "MPATHb WWID1\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHa WWID0\n" ++ "MPATHz WWID26\n" ++ "MPATHb WWID1\n", -1); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); + assert_int_equal(rc, 3); +@@ -799,10 +786,9 @@ static void lb_nomatch_a_b_bad(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, "MPATHz WWID26\n"); +- will_return(__wrap_fgets, "MPATHb\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHa WWID0\n" ++ "MPATHz WWID26\n" ++ "MPATHb\n", -1); + expect_condlog(3, "Ignoring malformed line 3 in bindings file\n"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); +@@ -815,10 +801,9 @@ static void lb_nomatch_a_b_bad_self(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, "MPATHz WWID26\n"); +- will_return(__wrap_fgets, "MPATHb\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHa WWID0\n" ++ "MPATHz WWID26\n" ++ "MPATHb\n", -1); + expect_condlog(3, "Ignoring malformed line 3 in bindings file\n"); + mock_self_alias("MPATHc", "WWID2"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); +@@ -832,10 +817,9 @@ static void lb_nomatch_b_a(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHb WWID1\n"); +- will_return(__wrap_fgets, "MPATHz WWID26\n"); +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHb WWID1\n" ++ "MPATHz WWID26\n" ++ "MPATHa WWID0\n", -1); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); + assert_int_equal(rc, 27); +@@ -847,10 +831,9 @@ static void lb_nomatch_b_a_3_used(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHb WWID1\n"); +- will_return(__wrap_fgets, "MPATHz WWID26\n"); +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHb WWID1\n" ++ "MPATHz WWID26\n" ++ "MPATHa WWID0\n", -1); + mock_used_alias("MPATHaa", "WWID2"); + mock_used_alias("MPATHab", "WWID2"); + mock_used_alias("MPATHac", "WWID2"); +@@ -867,10 +850,9 @@ static void do_lb_nomatch_int_max(void **state, int check_if_taken) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHb WWID1\n"); +- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n"); +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHb WWID1\n" ++ "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n" ++ "MPATHa WWID0\n", -1); + expect_condlog(0, NOMORE_STR); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", check_if_taken); + assert_int_equal(rc, -1); +@@ -892,9 +874,8 @@ static void lb_nomatch_int_max_used(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHb WWID1\n"); +- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHb WWID1\n" ++ "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n", -1); + mock_used_alias("MPATHa", "WWID2"); + expect_condlog(0, NOMORE_STR); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); +@@ -907,10 +888,9 @@ static void lb_nomatch_int_max_m1(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHb WWID1\n"); +- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHb WWID1\n" ++ "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n" ++ "MPATHa WWID0\n", -1); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); + assert_int_equal(rc, INT_MAX); +@@ -922,10 +902,9 @@ static void lb_nomatch_int_max_m1_used(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHb WWID1\n"); +- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHb WWID1\n" ++ "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n" ++ "MPATHa WWID0\n", -1); + mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2"); + expect_condlog(0, NOMORE_STR); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); +@@ -938,9 +917,8 @@ static void lb_nomatch_int_max_m1_1_used(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHb WWID1\n"); +- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHb WWID1\n" ++ "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n", -1); + mock_used_alias("MPATHa", "WWID2"); + mock_unused_alias("MPATH" MPATH_ID_INT_MAX); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); +@@ -954,9 +932,8 @@ static void lb_nomatch_int_max_m1_2_used(void **state) + int rc; + char *alias; + +- will_return(__wrap_fgets, "MPATHb WWID1\n"); +- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHb WWID1\n" ++ "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n", -1); + mock_used_alias("MPATHa", "WWID2"); + mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2"); + expect_condlog(0, NOMORE_STR); +@@ -1014,7 +991,7 @@ static void rl_empty(void **state) + char buf[WWID_SIZE]; + + buf[0] = '\0'; +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("", -1); + expect_condlog(3, NOMATCH_STR("MPATHa")); + rc = rlookup_binding(NULL, buf, "MPATHa"); + assert_int_equal(rc, -1); +@@ -1027,7 +1004,7 @@ static void rl_match_a(void **state) + char buf[WWID_SIZE]; + + buf[0] = '\0'; +- will_return(__wrap_fgets, "MPATHa WWID0\n"); ++ mock_bindings_file("MPATHa WWID0\n", 0); + expect_condlog(3, FOUND_ALIAS_STR("MPATHa", "WWID0")); + rc = rlookup_binding(NULL, buf, "MPATHa"); + assert_int_equal(rc, 0); +@@ -1040,8 +1017,7 @@ static void rl_nomatch_a(void **state) + char buf[WWID_SIZE]; + + buf[0] = '\0'; +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHa WWID0\n", -1); + expect_condlog(3, NOMATCH_STR("MPATHb")); + rc = rlookup_binding(NULL, buf, "MPATHb"); + assert_int_equal(rc, -1); +@@ -1054,8 +1030,7 @@ static void rl_malformed_a(void **state) + char buf[WWID_SIZE]; + + buf[0] = '\0'; +- will_return(__wrap_fgets, "MPATHa \n"); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("MPATHa \n", -1); + expect_condlog(3, "Ignoring malformed line 1 in bindings file\n"); + expect_condlog(3, NOMATCH_STR("MPATHa")); + rc = rlookup_binding(NULL, buf, "MPATHa"); +@@ -1074,8 +1049,7 @@ static void rl_overlong_a(void **state) + snprintf(line + sizeof(line) - 2, 2, "\n"); + + buf[0] = '\0'; +- will_return(__wrap_fgets, line); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file(line, -1); + expect_condlog(3, "Ignoring too large wwid at 1 in bindings file\n"); + expect_condlog(3, NOMATCH_STR("MPATHa")); + rc = rlookup_binding(NULL, buf, "MPATHa"); +@@ -1089,9 +1063,9 @@ static void rl_match_b(void **state) + char buf[WWID_SIZE]; + + buf[0] = '\0'; +- will_return(__wrap_fgets, "MPATHa WWID0\n"); +- will_return(__wrap_fgets, "MPATHz WWID26\n"); +- will_return(__wrap_fgets, "MPATHb WWID2\n"); ++ mock_bindings_file("MPATHa WWID0\n" ++ "MPATHz WWID26\n" ++ "MPATHb WWID2\n", 2); + expect_condlog(3, FOUND_ALIAS_STR("MPATHb", "WWID2")); + rc = rlookup_binding(NULL, buf, "MPATHb"); + assert_int_equal(rc, 0); +@@ -1222,7 +1196,7 @@ static void gufa_empty_new_rw(void **state) { + + will_return(__wrap_open_file, true); + +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("", -1); + mock_unused_alias("MPATHa"); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + +@@ -1235,7 +1209,7 @@ static void gufa_empty_new_rw(void **state) { + static void gufa_empty_new_ro_1(void **state) { + char *alias; + will_return(__wrap_open_file, false); +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("", -1); + mock_unused_alias("MPATHa"); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + +@@ -1248,7 +1222,7 @@ static void gufa_empty_new_ro_2(void **state) { + + will_return(__wrap_open_file, true); + +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("", -1); + mock_unused_alias("MPATHa"); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + +@@ -1261,7 +1235,7 @@ static void gufa_match_a_unused(void **state) { + + will_return(__wrap_open_file, true); + +- will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0")); ++ mock_bindings_file("MPATHa WWID0", 0); + expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); + mock_unused_alias("MPATHa"); + +@@ -1275,7 +1249,7 @@ static void gufa_match_a_self(void **state) { + + will_return(__wrap_open_file, true); + +- will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0")); ++ mock_bindings_file("MPATHa WWID0", 0); + expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); + mock_self_alias("MPATHa", "WWID0"); + +@@ -1289,7 +1263,7 @@ static void gufa_match_a_used(void **state) { + + will_return(__wrap_open_file, true); + +- will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0")); ++ mock_bindings_file("MPATHa WWID0", 0); + expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); + mock_used_alias("MPATHa", "WWID0"); + +@@ -1389,11 +1363,11 @@ static void gufa_old_empty(void **state) { + will_return(__wrap_open_file, true); + + /* rlookup_binding for ALIAS */ +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("", -1); + expect_condlog(3, NOMATCH_STR("MPATHz")); + + /* lookup_binding */ +- will_return(__wrap_fgets, NULL); ++ mock_bindings_file("", -1); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + + mock_allocate_binding("MPATHz", "WWID0"); diff --git a/0011-libmultipath-add-global-variable-for-current-binding.patch b/0011-libmultipath-add-global-variable-for-current-binding.patch new file mode 100644 index 0000000..c91259d --- /dev/null +++ b/0011-libmultipath-add-global-variable-for-current-binding.patch @@ -0,0 +1,109 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 22 Aug 2023 15:32:17 +0200 +Subject: [PATCH] libmultipath: add global variable for current bindings + +Add a variable global_bindings that holds the currently active vector of +bindings. This variable is freed at program exit. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/alias.c | 11 +++++++++-- + libmultipath/alias.h | 1 + + libmultipath/libmultipath.version | 1 + + multipath/main.c | 2 ++ + multipathd/main.c | 1 + + 5 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index 9e9ac563..dd363fd8 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -511,6 +511,7 @@ static void _free_binding(struct binding *bdg) + * an abstract type. + */ + typedef struct _vector Bindings; ++static Bindings global_bindings = { .allocated = 0 }; + + static void free_bindings(Bindings *bindings) + { +@@ -522,6 +523,11 @@ static void free_bindings(Bindings *bindings) + vector_reset(bindings); + } + ++void cleanup_bindings(void) ++{ ++ free_bindings(&global_bindings); ++} ++ + enum { + BINDING_EXISTS, + BINDING_CONFLICT, +@@ -751,7 +757,6 @@ int check_alias_settings(const struct config *conf) + pthread_cleanup_pop(1); + pthread_cleanup_pop(1); + +- pthread_cleanup_push_cast(free_bindings, &bindings); + fd = open_file(conf->bindings_file, &can_write, BINDINGS_FILE_HEADER); + if (fd != -1) { + FILE *file = fdopen(fd, "r"); +@@ -771,6 +776,8 @@ int check_alias_settings(const struct config *conf) + close(fd); + } + } +- pthread_cleanup_pop(1); ++ ++ cleanup_bindings(); ++ global_bindings = bindings; + return rc; + } +diff --git a/libmultipath/alias.h b/libmultipath/alias.h +index fa332233..37b49d9c 100644 +--- a/libmultipath/alias.h ++++ b/libmultipath/alias.h +@@ -9,5 +9,6 @@ char *get_user_friendly_alias(const char *wwid, const char *file, + + struct config; + int check_alias_settings(const struct config *); ++void cleanup_bindings(void); + + #endif /* _ALIAS_H */ +diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version +index a7b8c337..ddd302f5 100644 +--- a/libmultipath/libmultipath.version ++++ b/libmultipath/libmultipath.version +@@ -64,6 +64,7 @@ global: + checker_name; + checker_state_name; + check_foreign; ++ cleanup_bindings; + cleanup_lock; + coalesce_paths; + count_active_paths; +diff --git a/multipath/main.c b/multipath/main.c +index b78f3162..45e9745f 100644 +--- a/multipath/main.c ++++ b/multipath/main.c +@@ -843,6 +843,8 @@ main (int argc, char *argv[]) + conf->force_sync = 1; + if (atexit(cleanup_vecs)) + condlog(1, "failed to register cleanup handler for vecs: %m"); ++ if (atexit(cleanup_bindings)) ++ condlog(1, "failed to register cleanup handler for bindings: %m"); + while ((arg = getopt(argc, argv, ":adDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) { + switch(arg) { + case 'v': +diff --git a/multipathd/main.c b/multipathd/main.c +index 2e02a548..214ed4ae 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -3325,6 +3325,7 @@ static void cleanup_child(void) + { + cleanup_threads(); + cleanup_vecs(); ++ cleanup_bindings(); + if (poll_dmevents) + cleanup_dmevent_waiter(); + diff --git a/0012-libmultipath-rename-fix_bindings_file-to-update_bind.patch b/0012-libmultipath-rename-fix_bindings_file-to-update_bind.patch new file mode 100644 index 0000000..e0f8673 --- /dev/null +++ b/0012-libmultipath-rename-fix_bindings_file-to-update_bind.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 22 Aug 2023 15:37:15 +0200 +Subject: [PATCH] libmultipath: rename fix_bindings_file() to + update_bindings_file() + +We will use this function in a more generic way, give it a more +generic name. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/alias.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index dd363fd8..0aac2393 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -595,8 +595,8 @@ static int write_bindings_file(const Bindings *bindings, int fd) + return 0; + } + +-static int fix_bindings_file(const struct config *conf, +- const Bindings *bindings) ++static int update_bindings_file(const struct config *conf, ++ const Bindings *bindings) + { + int rc; + int fd = -1; +@@ -766,7 +766,7 @@ int check_alias_settings(const struct config *conf) + rc = _check_bindings_file(conf, file, &bindings); + pthread_cleanup_pop(1); + if (rc == -1 && can_write && !conf->bindings_read_only) +- rc = fix_bindings_file(conf, &bindings); ++ rc = update_bindings_file(conf, &bindings); + else if (rc == -1) + condlog(0, "ERROR: bad settings in read-only bindings file %s", + conf->bindings_file); diff --git a/0013-libmultipath-alias.c-move-bindings-related-code-up.patch b/0013-libmultipath-alias.c-move-bindings-related-code-up.patch new file mode 100644 index 0000000..1ad7b9e --- /dev/null +++ b/0013-libmultipath-alias.c-move-bindings-related-code-up.patch @@ -0,0 +1,285 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 22 Aug 2023 16:54:54 +0200 +Subject: [PATCH] libmultipath: alias.c: move bindings related code up + +No code changes, just moving code. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/alias.c | 239 ++++++++++++++++++++++--------------------- + 1 file changed, 120 insertions(+), 119 deletions(-) + +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index 0aac2393..7af403da 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + + #include "debug.h" + #include "util.h" +@@ -51,6 +52,125 @@ + + static const char bindings_file_header[] = BINDINGS_FILE_HEADER; + ++struct binding { ++ char *alias; ++ char *wwid; ++}; ++ ++/* ++ * Perhaps one day we'll implement this more efficiently, thus use ++ * an abstract type. ++ */ ++typedef struct _vector Bindings; ++static Bindings global_bindings = { .allocated = 0 }; ++ ++enum { ++ BINDING_EXISTS, ++ BINDING_CONFLICT, ++ BINDING_ADDED, ++ BINDING_DELETED, ++ BINDING_NOTFOUND, ++ BINDING_ERROR, ++}; ++ ++static void _free_binding(struct binding *bdg) ++{ ++ free(bdg->wwid); ++ free(bdg->alias); ++ free(bdg); ++} ++ ++static int add_binding(Bindings *bindings, const char *alias, const char *wwid) ++{ ++ struct binding *bdg; ++ int i, cmp = 0; ++ ++ /* ++ * Keep the bindings array sorted by alias. ++ * Optimization: Search backwards, assuming that the bindings file is ++ * sorted already. ++ */ ++ vector_foreach_slot_backwards(bindings, bdg, i) { ++ if ((cmp = strcmp(bdg->alias, alias)) <= 0) ++ break; ++ } ++ ++ /* Check for exact match */ ++ if (i >= 0 && cmp == 0) ++ return strcmp(bdg->wwid, wwid) ? ++ BINDING_CONFLICT : BINDING_EXISTS; ++ ++ i++; ++ bdg = calloc(1, sizeof(*bdg)); ++ if (bdg) { ++ bdg->wwid = strdup(wwid); ++ bdg->alias = strdup(alias); ++ if (bdg->wwid && bdg->alias && ++ vector_insert_slot(bindings, i, bdg)) ++ return BINDING_ADDED; ++ else ++ _free_binding(bdg); ++ } ++ ++ return BINDING_ERROR; ++} ++ ++static int write_bindings_file(const Bindings *bindings, int fd) ++{ ++ struct binding *bnd; ++ STRBUF_ON_STACK(line); ++ int i; ++ ++ if (write(fd, BINDINGS_FILE_HEADER, sizeof(BINDINGS_FILE_HEADER) - 1) ++ != sizeof(BINDINGS_FILE_HEADER) - 1) ++ return -1; ++ ++ vector_foreach_slot(bindings, bnd, i) { ++ int len; ++ ++ if ((len = print_strbuf(&line, "%s %s\n", ++ bnd->alias, bnd->wwid)) < 0) ++ return -1; ++ if (write(fd, get_strbuf_str(&line), len) != len) ++ return -1; ++ truncate_strbuf(&line, 0); ++ } ++ return 0; ++} ++ ++static int update_bindings_file(const struct config *conf, ++ const Bindings *bindings) ++{ ++ int rc; ++ int fd = -1; ++ char tempname[PATH_MAX]; ++ mode_t old_umask; ++ ++ if (safe_sprintf(tempname, "%s.XXXXXX", conf->bindings_file)) ++ return -1; ++ /* coverity: SECURE_TEMP */ ++ old_umask = umask(0077); ++ if ((fd = mkstemp(tempname)) == -1) { ++ condlog(1, "%s: mkstemp: %m", __func__); ++ return -1; ++ } ++ umask(old_umask); ++ pthread_cleanup_push(cleanup_fd_ptr, &fd); ++ rc = write_bindings_file(bindings, fd); ++ pthread_cleanup_pop(1); ++ if (rc == -1) { ++ condlog(1, "failed to write new bindings file %s", ++ tempname); ++ unlink(tempname); ++ return rc; ++ } ++ if ((rc = rename(tempname, conf->bindings_file)) == -1) ++ condlog(0, "%s: rename: %m", __func__); ++ else ++ condlog(1, "updated bindings file %s", conf->bindings_file); ++ return rc; ++} ++ + int + valid_alias(const char *alias) + { +@@ -494,25 +614,6 @@ get_user_friendly_wwid(const char *alias, char *buff, const char *file) + return 0; + } + +-struct binding { +- char *alias; +- char *wwid; +-}; +- +-static void _free_binding(struct binding *bdg) +-{ +- free(bdg->wwid); +- free(bdg->alias); +- free(bdg); +-} +- +-/* +- * Perhaps one day we'll implement this more efficiently, thus use +- * an abstract type. +- */ +-typedef struct _vector Bindings; +-static Bindings global_bindings = { .allocated = 0 }; +- + static void free_bindings(Bindings *bindings) + { + struct binding *bdg; +@@ -528,106 +629,6 @@ void cleanup_bindings(void) + free_bindings(&global_bindings); + } + +-enum { +- BINDING_EXISTS, +- BINDING_CONFLICT, +- BINDING_ADDED, +- BINDING_DELETED, +- BINDING_NOTFOUND, +- BINDING_ERROR, +-}; +- +-static int add_binding(Bindings *bindings, const char *alias, const char *wwid) +-{ +- struct binding *bdg; +- int i, cmp = 0; +- +- /* +- * Keep the bindings array sorted by alias. +- * Optimization: Search backwards, assuming that the bindings file is +- * sorted already. +- */ +- vector_foreach_slot_backwards(bindings, bdg, i) { +- if ((cmp = strcmp(bdg->alias, alias)) <= 0) +- break; +- } +- +- /* Check for exact match */ +- if (i >= 0 && cmp == 0) +- return strcmp(bdg->wwid, wwid) ? +- BINDING_CONFLICT : BINDING_EXISTS; +- +- i++; +- bdg = calloc(1, sizeof(*bdg)); +- if (bdg) { +- bdg->wwid = strdup(wwid); +- bdg->alias = strdup(alias); +- if (bdg->wwid && bdg->alias && +- vector_insert_slot(bindings, i, bdg)) +- return BINDING_ADDED; +- else +- _free_binding(bdg); +- } +- +- return BINDING_ERROR; +-} +- +-static int write_bindings_file(const Bindings *bindings, int fd) +-{ +- struct binding *bnd; +- STRBUF_ON_STACK(line); +- int i; +- +- if (write(fd, BINDINGS_FILE_HEADER, sizeof(BINDINGS_FILE_HEADER) - 1) +- != sizeof(BINDINGS_FILE_HEADER) - 1) +- return -1; +- +- vector_foreach_slot(bindings, bnd, i) { +- int len; +- +- if ((len = print_strbuf(&line, "%s %s\n", +- bnd->alias, bnd->wwid)) < 0) +- return -1; +- if (write(fd, get_strbuf_str(&line), len) != len) +- return -1; +- truncate_strbuf(&line, 0); +- } +- return 0; +-} +- +-static int update_bindings_file(const struct config *conf, +- const Bindings *bindings) +-{ +- int rc; +- int fd = -1; +- char tempname[PATH_MAX]; +- mode_t old_umask; +- +- if (safe_sprintf(tempname, "%s.XXXXXX", conf->bindings_file)) +- return -1; +- /* coverity: SECURE_TEMP */ +- old_umask = umask(0077); +- if ((fd = mkstemp(tempname)) == -1) { +- condlog(1, "%s: mkstemp: %m", __func__); +- return -1; +- } +- umask(old_umask); +- pthread_cleanup_push(cleanup_fd_ptr, &fd); +- rc = write_bindings_file(bindings, fd); +- pthread_cleanup_pop(1); +- if (rc == -1) { +- condlog(1, "failed to write new bindings file %s", +- tempname); +- unlink(tempname); +- return rc; +- } +- if ((rc = rename(tempname, conf->bindings_file)) == -1) +- condlog(0, "%s: rename: %m", __func__); +- else +- condlog(1, "updated bindings file %s", conf->bindings_file); +- return rc; +-} +- + static int _check_bindings_file(const struct config *conf, FILE *file, + Bindings *bindings) + { diff --git a/0014-libmultipath-update_bindings_file-take-filename-argu.patch b/0014-libmultipath-update_bindings_file-take-filename-argu.patch new file mode 100644 index 0000000..6b9d2e8 --- /dev/null +++ b/0014-libmultipath-update_bindings_file-take-filename-argu.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 24 Aug 2023 15:53:49 +0200 +Subject: [PATCH] libmultipath: update_bindings_file: take filename argument + +This function just uses the file name, no other configuration +parameters. Also, pass the Bindings argument first to use the +same convention as the other functions in this file. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/alias.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index 7af403da..9bd3875e 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -138,15 +138,15 @@ static int write_bindings_file(const Bindings *bindings, int fd) + return 0; + } + +-static int update_bindings_file(const struct config *conf, +- const Bindings *bindings) ++static int update_bindings_file(const Bindings *bindings, ++ const char *bindings_file) + { + int rc; + int fd = -1; + char tempname[PATH_MAX]; + mode_t old_umask; + +- if (safe_sprintf(tempname, "%s.XXXXXX", conf->bindings_file)) ++ if (safe_sprintf(tempname, "%s.XXXXXX", bindings_file)) + return -1; + /* coverity: SECURE_TEMP */ + old_umask = umask(0077); +@@ -164,10 +164,10 @@ static int update_bindings_file(const struct config *conf, + unlink(tempname); + return rc; + } +- if ((rc = rename(tempname, conf->bindings_file)) == -1) ++ if ((rc = rename(tempname, bindings_file)) == -1) + condlog(0, "%s: rename: %m", __func__); + else +- condlog(1, "updated bindings file %s", conf->bindings_file); ++ condlog(1, "updated bindings file %s", bindings_file); + return rc; + } + +@@ -767,7 +767,7 @@ int check_alias_settings(const struct config *conf) + rc = _check_bindings_file(conf, file, &bindings); + pthread_cleanup_pop(1); + if (rc == -1 && can_write && !conf->bindings_read_only) +- rc = update_bindings_file(conf, &bindings); ++ rc = update_bindings_file(&bindings, conf->bindings_file); + else if (rc == -1) + condlog(0, "ERROR: bad settings in read-only bindings file %s", + conf->bindings_file); diff --git a/0015-libmultipath-update_bindings_file-use-a-single-write.patch b/0015-libmultipath-update_bindings_file-use-a-single-write.patch new file mode 100644 index 0000000..1e1fd15 --- /dev/null +++ b/0015-libmultipath-update_bindings_file-use-a-single-write.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 24 Aug 2023 15:54:45 +0200 +Subject: [PATCH] libmultipath: update_bindings_file: use a single write() + +Save code and syscalls by assembling the content in memory first. +write() may return less bytes written than expected. Deal with it. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/alias.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index 9bd3875e..92f90f05 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -118,22 +118,30 @@ static int add_binding(Bindings *bindings, const char *alias, const char *wwid) + static int write_bindings_file(const Bindings *bindings, int fd) + { + struct binding *bnd; +- STRBUF_ON_STACK(line); ++ STRBUF_ON_STACK(content); + int i; ++ size_t len; + +- if (write(fd, BINDINGS_FILE_HEADER, sizeof(BINDINGS_FILE_HEADER) - 1) +- != sizeof(BINDINGS_FILE_HEADER) - 1) ++ if (__append_strbuf_str(&content, BINDINGS_FILE_HEADER, ++ sizeof(BINDINGS_FILE_HEADER) - 1) == -1) + return -1; + + vector_foreach_slot(bindings, bnd, i) { +- int len; +- +- if ((len = print_strbuf(&line, "%s %s\n", +- bnd->alias, bnd->wwid)) < 0) ++ if (print_strbuf(&content, "%s %s\n", ++ bnd->alias, bnd->wwid) < 0) + return -1; +- if (write(fd, get_strbuf_str(&line), len) != len) ++ } ++ len = get_strbuf_len(&content); ++ while (len > 0) { ++ ssize_t n = write(fd, get_strbuf_str(&content), len); ++ ++ if (n < 0) ++ return n; ++ else if (n == 0) { ++ condlog(2, "%s: short write", __func__); + return -1; +- truncate_strbuf(&line, 0); ++ } ++ len -= n; + } + return 0; + } diff --git a/0016-libmultipath-update_bindings_file-don-t-log-temp-fil.patch b/0016-libmultipath-update_bindings_file-don-t-log-temp-fil.patch new file mode 100644 index 0000000..1126b95 --- /dev/null +++ b/0016-libmultipath-update_bindings_file-don-t-log-temp-fil.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 24 Aug 2023 22:33:39 +0200 +Subject: [PATCH] libmultipath: update_bindings_file: don't log temp file name + +The name of the temp file is unlikely to be helpful for users, +and hard to predict in the unit test. Omit it. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/alias.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index 92f90f05..afa5879e 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -167,8 +167,7 @@ static int update_bindings_file(const Bindings *bindings, + rc = write_bindings_file(bindings, fd); + pthread_cleanup_pop(1); + if (rc == -1) { +- condlog(1, "failed to write new bindings file %s", +- tempname); ++ condlog(1, "failed to write new bindings file"); + unlink(tempname); + return rc; + } diff --git a/0017-libmultipath-alias.c-factor-out-read_binding.patch b/0017-libmultipath-alias.c-factor-out-read_binding.patch new file mode 100644 index 0000000..8c9cb08 --- /dev/null +++ b/0017-libmultipath-alias.c-factor-out-read_binding.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 24 Aug 2023 21:17:25 +0200 +Subject: [PATCH] libmultipath: alias.c: factor out read_binding() + +This way we can test the parsing of input lines from the bindings +file more easily. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/alias.c | 58 ++++++++++++++++++++++++++++++-------------- + 1 file changed, 40 insertions(+), 18 deletions(-) + +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index afa5879e..ecf4a2ac 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -636,6 +636,43 @@ void cleanup_bindings(void) + free_bindings(&global_bindings); + } + ++enum { ++ READ_BINDING_OK, ++ READ_BINDING_SKIP, ++}; ++ ++static int read_binding(char *line, unsigned int linenr, char **alias, ++ char **wwid) { ++ char *c, *saveptr; ++ ++ c = strpbrk(line, "#\n\r"); ++ if (c) ++ *c = '\0'; ++ ++ *alias = strtok_r(line, " \t", &saveptr); ++ if (!*alias) /* blank line */ ++ return READ_BINDING_SKIP; ++ ++ *wwid = strtok_r(NULL, " \t", &saveptr); ++ if (!*wwid) { ++ condlog(1, "invalid line %u in bindings file, missing WWID", ++ linenr); ++ return READ_BINDING_SKIP; ++ } ++ if (strlen(*wwid) > WWID_SIZE - 1) { ++ condlog(3, ++ "Ignoring too large wwid at %u in bindings file", ++ linenr); ++ return READ_BINDING_SKIP; ++ } ++ c = strtok_r(NULL, " \t", &saveptr); ++ if (c) ++ /* This is non-fatal */ ++ condlog(1, "invalid line %d in bindings file, extra args \"%s\"", ++ linenr, c); ++ return READ_BINDING_OK; ++} ++ + static int _check_bindings_file(const struct config *conf, FILE *file, + Bindings *bindings) + { +@@ -647,27 +684,12 @@ static int _check_bindings_file(const struct config *conf, FILE *file, + + pthread_cleanup_push(cleanup_free_ptr, &line); + while ((n = getline(&line, &line_len, file)) >= 0) { +- char *c, *alias, *wwid, *saveptr; ++ char *alias, *wwid; + const char *mpe_wwid; + +- linenr++; +- c = strpbrk(line, "#\n\r"); +- if (c) +- *c = '\0'; +- alias = strtok_r(line, " \t", &saveptr); +- if (!alias) /* blank line */ +- continue; +- wwid = strtok_r(NULL, " \t", &saveptr); +- if (!wwid) { +- condlog(1, "invalid line %d in bindings file, missing WWID", +- linenr); ++ if (read_binding(line, ++linenr, &alias, &wwid) ++ == READ_BINDING_SKIP) + continue; +- } +- c = strtok_r(NULL, " \t", &saveptr); +- if (c) +- /* This is non-fatal */ +- condlog(1, "invalid line %d in bindings file, extra args \"%s\"", +- linenr, c); + + mpe_wwid = get_mpe_wwid(conf->mptable, alias); + if (mpe_wwid && strcmp(mpe_wwid, wwid)) { diff --git a/0018-libmultipath-keep-bindings-in-memory.patch b/0018-libmultipath-keep-bindings-in-memory.patch new file mode 100644 index 0000000..bb26ea2 --- /dev/null +++ b/0018-libmultipath-keep-bindings-in-memory.patch @@ -0,0 +1,545 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 22 Aug 2023 21:14:51 +0200 +Subject: [PATCH] libmultipath: keep bindings in memory + +Rather than opening the bindings file every time we must retrieve +a binding, keep the contents in memory and write the file only +if additions have been made. This simplifies the code, and should speed up +alias lookups significantly. As a side effect, the aliases will be stored +sorted by alias, which changes the way aliases are allocated if there are +unused "holes" in the sequence of aliases. For example, if the bindings file +contains mpathb, mpathy, and mpatha, in this order, the next new alias used to +be mpathz and is now mpathc. + +Another side effect is that multipathd will not automatically pick up changes +to the bindings file at runtime without a reconfigure operation. It is +questionable whether these on-the-fly changes were a good idea in the first +place, as inconsistent configurations may easily come to pass. It desired, +it would be feasible to implement automatic update of the bindings using the +existing inotify approach. + +The new implementation of get_user_friendly_alias() is slightly different +than before. The logic is summarized in a comment in the code. Unit tests +will be provided that illustrate the changes. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/alias.c | 351 ++++++++++++++++----------------------- + libmultipath/alias.h | 2 +- + libmultipath/configure.c | 3 +- + 3 files changed, 144 insertions(+), 212 deletions(-) + +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index ecf4a2ac..d6563749 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -50,8 +50,6 @@ + "# alias wwid\n" \ + "#\n" + +-static const char bindings_file_header[] = BINDINGS_FILE_HEADER; +- + struct binding { + char *alias; + char *wwid; +@@ -80,6 +78,45 @@ static void _free_binding(struct binding *bdg) + free(bdg); + } + ++static const struct binding *get_binding_for_alias(const Bindings *bindings, ++ const char *alias) ++{ ++ const struct binding *bdg; ++ int i; ++ ++ if (!alias) ++ return NULL; ++ vector_foreach_slot(bindings, bdg, i) { ++ if (!strncmp(bdg->alias, alias, WWID_SIZE)) { ++ condlog(3, "Found matching alias [%s] in bindings file." ++ " Setting wwid to %s", alias, bdg->wwid); ++ return bdg; ++ } ++ } ++ ++ condlog(3, "No matching alias [%s] in bindings file.", alias); ++ return NULL; ++} ++ ++static const struct binding *get_binding_for_wwid(const Bindings *bindings, ++ const char *wwid) ++{ ++ const struct binding *bdg; ++ int i; ++ ++ if (!wwid) ++ return NULL; ++ vector_foreach_slot(bindings, bdg, i) { ++ if (!strncmp(bdg->wwid, wwid, WWID_SIZE)) { ++ condlog(3, "Found matching wwid [%s] in bindings file." ++ " Setting alias to %s", wwid, bdg->alias); ++ return bdg; ++ } ++ } ++ condlog(3, "No matching wwid [%s] in bindings file.", wwid); ++ return NULL; ++} ++ + static int add_binding(Bindings *bindings, const char *alias, const char *wwid) + { + struct binding *bdg; +@@ -115,6 +152,24 @@ static int add_binding(Bindings *bindings, const char *alias, const char *wwid) + return BINDING_ERROR; + } + ++static int delete_binding(Bindings *bindings, const char *wwid) ++{ ++ struct binding *bdg; ++ int i; ++ ++ vector_foreach_slot(bindings, bdg, i) { ++ if (!strncmp(bdg->wwid, wwid, WWID_SIZE)) { ++ _free_binding(bdg); ++ break; ++ } ++ } ++ if (i >= VECTOR_SIZE(bindings)) ++ return BINDING_NOTFOUND; ++ ++ vector_del_slot(bindings, i); ++ return BINDING_DELETED; ++} ++ + static int write_bindings_file(const Bindings *bindings, int fd) + { + struct binding *bnd; +@@ -267,38 +322,15 @@ static bool id_already_taken(int id, const char *prefix, const char *map_wwid) + return alias_already_taken(alias, map_wwid); + } + +-/* +- * Returns: 0 if matching entry in WWIDs file found +- * -1 if an error occurs +- * >0 a free ID that could be used for the WWID at hand +- * *map_alias is set to a freshly allocated string with the matching alias if +- * the function returns 0, or to NULL otherwise. +- */ +-static int +-lookup_binding(FILE *f, const char *map_wwid, char **map_alias, +- const char *prefix, int check_if_taken) ++int get_free_id(const Bindings *bindings, const char *prefix, const char *map_wwid) + { +- char buf[LINE_MAX]; +- unsigned int line_nr = 0; +- int id = 1; ++ const struct binding *bdg; ++ int i, id = 1; + int biggest_id = 1; + int smallest_bigger_id = INT_MAX; + +- *map_alias = NULL; +- +- rewind(f); +- while (fgets(buf, LINE_MAX, f)) { +- const char *alias, *wwid; +- char *c, *saveptr; +- int curr_id; +- +- line_nr++; +- c = strpbrk(buf, "#\n\r"); +- if (c) +- *c = '\0'; +- alias = strtok_r(buf, " \t", &saveptr); +- if (!alias) /* blank line */ +- continue; ++ vector_foreach_slot(bindings, bdg, i) { ++ int curr_id = scan_devname(bdg->alias, prefix); + + /* + * Find an unused index - explanation of the algorithm +@@ -333,8 +365,6 @@ lookup_binding(FILE *f, const char *map_wwid, char **map_alias, + * biggest_id is always > smallest_bigger_id, except in the + * "perfectly ordered" case. + */ +- +- curr_id = scan_devname(alias, prefix); + if (curr_id == id) { + if (id < INT_MAX) + id++; +@@ -345,36 +375,15 @@ lookup_binding(FILE *f, const char *map_wwid, char **map_alias, + } + if (curr_id > biggest_id) + biggest_id = curr_id; ++ + if (curr_id > id && curr_id < smallest_bigger_id) + smallest_bigger_id = curr_id; +- wwid = strtok_r(NULL, " \t", &saveptr); +- if (!wwid){ +- condlog(3, +- "Ignoring malformed line %u in bindings file", +- line_nr); +- continue; +- } +- if (strcmp(wwid, map_wwid) == 0){ +- condlog(3, "Found matching wwid [%s] in bindings file." +- " Setting alias to %s", wwid, alias); +- *map_alias = strdup(alias); +- if (*map_alias == NULL) { +- condlog(0, "Cannot copy alias from bindings " +- "file: out of memory"); +- return -1; +- } +- return 0; +- } +- } +- if (!prefix && check_if_taken) +- id = -1; +- if (id >= smallest_bigger_id) { +- if (biggest_id < INT_MAX) +- id = biggest_id + 1; +- else +- id = -1; + } +- if (id > 0 && check_if_taken) { ++ ++ if (id >= smallest_bigger_id) ++ id = biggest_id < INT_MAX ? biggest_id + 1 : -1; ++ ++ if (id > 0) { + while(id_already_taken(id, prefix, map_wwid)) { + if (id == INT_MAX) { + id = -1; +@@ -391,64 +400,17 @@ lookup_binding(FILE *f, const char *map_wwid, char **map_alias, + } + } + } +- if (id < 0) { ++ ++ if (id < 0) + condlog(0, "no more available user_friendly_names"); +- return -1; +- } else +- condlog(3, "No matching wwid [%s] in bindings file.", map_wwid); + return id; + } + +-static int +-rlookup_binding(FILE *f, char *buff, const char *map_alias) +-{ +- char line[LINE_MAX]; +- unsigned int line_nr = 0; +- +- buff[0] = '\0'; +- +- while (fgets(line, LINE_MAX, f)) { +- char *c, *saveptr; +- const char *alias, *wwid; +- +- line_nr++; +- c = strpbrk(line, "#\n\r"); +- if (c) +- *c = '\0'; +- alias = strtok_r(line, " \t", &saveptr); +- if (!alias) /* blank line */ +- continue; +- wwid = strtok_r(NULL, " \t", &saveptr); +- if (!wwid){ +- condlog(3, +- "Ignoring malformed line %u in bindings file", +- line_nr); +- continue; +- } +- if (strlen(wwid) > WWID_SIZE - 1) { +- condlog(3, +- "Ignoring too large wwid at %u in bindings file", line_nr); +- continue; +- } +- if (strcmp(alias, map_alias) == 0){ +- condlog(3, "Found matching alias [%s] in bindings file." +- " Setting wwid to %s", alias, wwid); +- strlcpy(buff, wwid, WWID_SIZE); +- return 0; +- } +- } +- condlog(3, "No matching alias [%s] in bindings file.", map_alias); +- +- return -1; +-} +- + static char * +-allocate_binding(int fd, const char *wwid, int id, const char *prefix) ++allocate_binding(const char *filename, const char *wwid, int id, const char *prefix) + { + STRBUF_ON_STACK(buf); +- off_t offset; +- ssize_t len; +- char *alias, *c; ++ char *alias; + + if (id <= 0) { + condlog(0, "%s: cannot allocate new binding for id %d", +@@ -460,164 +422,135 @@ allocate_binding(int fd, const char *wwid, int id, const char *prefix) + format_devname(&buf, id) == -1) + return NULL; + +- if (print_strbuf(&buf, " %s\n", wwid) < 0) +- return NULL; ++ alias = steal_strbuf_str(&buf); + +- offset = lseek(fd, 0, SEEK_END); +- if (offset < 0){ +- condlog(0, "Cannot seek to end of bindings file : %s", +- strerror(errno)); ++ if (add_binding(&global_bindings, alias, wwid) != BINDING_ADDED) { ++ condlog(0, "%s: cannot allocate new binding %s for %s", ++ __func__, alias, wwid); ++ free(alias); + return NULL; + } + +- len = get_strbuf_len(&buf); +- alias = steal_strbuf_str(&buf); +- +- if (write(fd, alias, len) != len) { +- condlog(0, "Cannot write binding to bindings file : %s", +- strerror(errno)); +- /* clear partial write */ +- if (ftruncate(fd, offset)) +- condlog(0, "Cannot truncate the header : %s", +- strerror(errno)); ++ if (update_bindings_file(&global_bindings, filename) == -1) { ++ condlog(1, "%s: deleting binding %s for %s", __func__, alias, wwid); ++ delete_binding(&global_bindings, wwid); + free(alias); + return NULL; + } +- c = strchr(alias, ' '); +- if (c) +- *c = '\0'; + + condlog(3, "Created new binding [%s] for WWID [%s]", alias, wwid); + return alias; + } + ++/* ++ * get_user_friendly_alias() action table ++ * ++ * The table shows the various cases, the actions taken, and the CI ++ * functions from tests/alias.c that represent them. ++ * ++ * - O: old alias given ++ * - A: old alias in table (y: yes, correct WWID; X: yes, wrong WWID) ++ * - W: wwid in table ++ * ++ * | No | O | A | W | action | function gufa_X | ++ * |----+---+---+---+--------------------------------------------+------------------------------| ++ * | 1 | n | - | n | get new alias | nomatch_Y | ++ * | 2 | n | - | y | use alias from bindings | match_a_Y | ++ * | 3 | y | n | n | add binding for old alias | old_nomatch_nowwidmatch | ++ * | 4 | y | n | y | use alias from bindings (avoid duplicates) | old_nomatch_wwidmatch | ++ * | 5 | y | y | n | [ impossible ] | - | ++ * | 6 | y | y | y | use old alias == alias from bindings | old_match | ++ * | 7 | y | X | n | get new alias | old_match_other | ++ * | 8 | y | X | y | use alias from bindings | old_match_other_wwidmatch | ++ * ++ * Notes: ++ * - "use alias from bindings" means that the alias from the bindings file will ++ * be tried; if it is in use, the alias selection will fail. No other ++ * bindings will be attempted. ++ * - "get new alias" fails if all aliases are used up, or if writing the ++ * bindings file fails. ++ * - if "alias_old" is set, it can't be bound to a different map. alias_old is ++ * initialized in find_existing_alias() by scanning the mpvec. We trust ++ * that the mpvec corrcectly represents kernel state. ++ */ ++ + char *get_user_friendly_alias(const char *wwid, const char *file, const char *alias_old, + const char *prefix, bool bindings_read_only) + { + char *alias = NULL; + int id = 0; +- int fd, can_write; + bool new_binding = false; +- char buff[WWID_SIZE]; +- FILE *f; +- +- fd = open_file(file, &can_write, bindings_file_header); +- if (fd < 0) +- return NULL; +- +- f = fdopen(fd, "r"); +- if (!f) { +- condlog(0, "cannot fdopen on bindings file descriptor"); +- close(fd); +- return NULL; +- } ++ const struct binding *bdg; + +- if (!strlen(alias_old)) ++ if (!*alias_old) + goto new_alias; + +- /* lookup the binding. if it exists, the wwid will be in buff +- * either way, id contains the id for the alias +- */ +- rlookup_binding(f, buff, alias_old); +- +- if (strlen(buff) > 0) { +- /* If buff is our wwid, it's already allocated correctly. */ +- if (strcmp(buff, wwid) == 0) { ++ /* See if there's a binding matching both alias_old and wwid */ ++ bdg = get_binding_for_alias(&global_bindings, alias_old); ++ if (bdg) { ++ if (!strcmp(bdg->wwid, wwid)) { + alias = strdup(alias_old); + goto out; +- + } else { + condlog(0, "alias %s already bound to wwid %s, cannot reuse", +- alias_old, buff); ++ alias_old, bdg->wwid); + goto new_alias; + } + } + +- /* +- * Look for an existing alias in the bindings file. +- * Pass prefix = NULL, so lookup_binding() won't try to allocate a new id. +- */ +- lookup_binding(f, wwid, &alias, NULL, 0); +- if (alias) { +- if (alias_already_taken(alias, wwid)) { +- free(alias); +- alias = NULL; +- } else ++ /* allocate the existing alias in the bindings file */ ++ id = scan_devname(alias_old, prefix); ++ ++new_alias: ++ /* Check for existing binding of WWID */ ++ bdg = get_binding_for_wwid(&global_bindings, wwid); ++ if (bdg) { ++ if (!alias_already_taken(bdg->alias, wwid)) { + condlog(3, "Use existing binding [%s] for WWID [%s]", +- alias, wwid); ++ bdg->alias, wwid); ++ alias = strdup(bdg->alias); ++ } + goto out; + } + +- /* alias_old is already taken by our WWID, update bindings file. */ +- id = scan_devname(alias_old, prefix); +- +-new_alias: + if (id <= 0) { + /* + * no existing alias was provided, or allocating it + * failed. Try a new one. + */ +- id = lookup_binding(f, wwid, &alias, prefix, 1); +- if (id == 0 && alias_already_taken(alias, wwid)) { +- free(alias); +- alias = NULL; +- } ++ id = get_free_id(&global_bindings, prefix, wwid); + if (id <= 0) + goto out; + else + new_binding = true; + } + +- if (fflush(f) != 0) { +- condlog(0, "cannot fflush bindings file stream : %s", +- strerror(errno)); +- goto out; +- } ++ if (!bindings_read_only && id > 0) ++ alias = allocate_binding(file, wwid, id, prefix); + +- if (can_write && !bindings_read_only) { +- alias = allocate_binding(fd, wwid, id, prefix); +- if (alias && !new_binding) +- condlog(2, "Allocated existing binding [%s] for WWID [%s]", +- alias, wwid); +- } ++ if (alias && !new_binding) ++ condlog(2, "Allocated existing binding [%s] for WWID [%s]", ++ alias, wwid); + + out: +- pthread_cleanup_push(free, alias); +- fclose(f); +- pthread_cleanup_pop(0); + return alias; + } + +-int +-get_user_friendly_wwid(const char *alias, char *buff, const char *file) ++int get_user_friendly_wwid(const char *alias, char *buff) + { +- int fd, unused; +- FILE *f; ++ const struct binding *bdg; + + if (!alias || *alias == '\0') { + condlog(3, "Cannot find binding for empty alias"); + return -1; + } + +- fd = open_file(file, &unused, bindings_file_header); +- if (fd < 0) +- return -1; +- +- f = fdopen(fd, "r"); +- if (!f) { +- condlog(0, "cannot fdopen on bindings file descriptor : %s", +- strerror(errno)); +- close(fd); ++ bdg = get_binding_for_alias(&global_bindings, alias); ++ if (!bdg) { ++ *buff = '\0'; + return -1; + } +- +- rlookup_binding(f, buff, alias); +- if (!strlen(buff)) { +- fclose(f); +- return -1; +- } +- +- fclose(f); ++ strlcpy(buff, bdg->wwid, WWID_SIZE); + return 0; + } + +diff --git a/libmultipath/alias.h b/libmultipath/alias.h +index 37b49d9c..5ef6720b 100644 +--- a/libmultipath/alias.h ++++ b/libmultipath/alias.h +@@ -2,7 +2,7 @@ + #define _ALIAS_H + + int valid_alias(const char *alias); +-int get_user_friendly_wwid(const char *alias, char *buff, const char *file); ++int get_user_friendly_wwid(const char *alias, char *buff); + char *get_user_friendly_alias(const char *wwid, const char *file, + const char *alias_old, + const char *prefix, bool bindings_read_only); +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index 029fbbd2..d8094903 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -1378,8 +1378,7 @@ static int _get_refwwid(enum mpath_cmds cmd, const char *dev, + refwwid = tmpwwid; + + /* or may be a binding */ +- else if (get_user_friendly_wwid(dev, tmpwwid, +- conf->bindings_file) == 0) ++ else if (get_user_friendly_wwid(dev, tmpwwid) == 0) + refwwid = tmpwwid; + + /* or may be an alias */ diff --git a/0019-multipath-tools-tests-fix-alias-tests.patch b/0019-multipath-tools-tests-fix-alias-tests.patch new file mode 100644 index 0000000..da618f6 --- /dev/null +++ b/0019-multipath-tools-tests-fix-alias-tests.patch @@ -0,0 +1,1698 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 25 Aug 2023 17:55:55 +0200 +Subject: [PATCH] multipath-tools tests: fix alias tests + +The different implementation of get_user_friendly_alias() and its helpers +necessitates changes in the unit tests. It would be nice if it didn't, but the +unit tests are too closely bound to the implementation to make this possible. + +- The bindings table is held in memory in alphabetically sorted order, which + may change the result of looking for free alias IDs if the entries in the + bindings file were unordered initially. In particular, if only a small + number of bindings exists, "holes" in the file will be detected more easily. + But because the sort order of the aliases differs from simple alphabetic + sorting ("mpathz" precedes "mpathaa"), a bindings file that contains all + bindings from "a" to "aa" (or more) will appear unsorted. + As an extra check, some of the unit tests deliberately use a different + implementation of add_binding() that does not order the bindings + table. + +- Broken lines in the bindings file never make it to the in-memory + representation. An alias that appeard "used" because it occurred in a broken + line will not appear used any more. Warnings about malformed lines will only + be printed while the bindings file is read, not from get_user_friendly_alias(). + +- The match_line argument of mock_bindings_file() is obsolete. + +- lookup_binding() and rlookup_binding() have been removed from + libmultipath. They are now emulated in the unit test code. + +- lookup_binding() didn't check for used alias in all cases previously, but it does now. + +- prefix != NULL and check_if_taken == false is not supported any more + in lookup_binding(). + +- allocate_binding() uses a very different sequence of systems calls now, as + it's implemented using update_bindings_file(). In particular, it's now more + difficult to predict the content of the write() call that creates the + bindings file. See comments for __wrap_write(). + +- some unit tests for get_user_friendly_alias() had to call + mock_bindings_file() twice, because the old implementation would read the + file twice (first rlookup_binding() and then lookup_binding()). This is not + necessary any more. + +- The unit tests need a teardown function to clear the bindings table in memory. + +- Minor changes are necessary because of changed ordering of the log messages. + Previously, lookup_binding() combined check for an existing entry and the + search for a new ID. The new algorithm does this in two separate steps and + tests for used aliases in between, which causes a change in the order in which + log messages are emitted. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + tests/alias.c | 957 ++++++++++++++++++++++++++++++++------------------ + 1 file changed, 614 insertions(+), 343 deletions(-) + +diff --git a/tests/alias.c b/tests/alias.c +index f334f928..50a21ecf 100644 +--- a/tests/alias.c ++++ b/tests/alias.c +@@ -3,10 +3,12 @@ + #include + #include + #include ++#include "strbuf.h" + #include "util.h" + #include "alias.h" + #include "test-log.h" + #include ++#include + + #include "globals.c" + #include "../libmultipath/alias.c" +@@ -20,18 +22,6 @@ + #define MPATH_ID_INT_MAX_p1 "fxshrxx" + #endif + +-void __wrap_rewind(FILE *stream) +-{} +- +-char *__wrap_fgets(char *buf, int n, FILE *stream) +-{ +- char *val = mock_ptr_type(char *); +- if (!val) +- return NULL; +- strlcpy(buf, val, n); +- return buf; +-} +- + static int __set_errno(int err) + { + if (err >= 0) { +@@ -43,23 +33,44 @@ static int __set_errno(int err) + } + } + +-off_t __wrap_lseek(int fd, off_t offset, int whence) ++/* ++ * allocate_binding -> write_bindings_file() writes the entire file, i.e. the ++ * header, any pre-existing bindings, and the new binding. The complete content ++ * depends on history and is different to predict here. Therefore we check only ++ * the newly added binding. Because add_binding() sorts entries, this new ++ * binding isn't necessarily the last one; receive it from will_return() and ++ * search for it with strstr(). ++ * If the string to be written doesn't start with the bindings file ++ * header, it's a test of a partial write. ++ */ ++ssize_t __wrap_write(int fd, const void *buf, size_t count) + { +- return __set_errno(mock_type(int)); ++ const char *binding, *start; + ++#if DEBUG_WRITE ++ fprintf(stderr, "%s: %zx exp %zx\n===\n%s\n===\n", __func__, strlen(buf), ++ count, (const char *)buf); ++#endif ++ if (!strncmp((const char *)buf, BINDINGS_FILE_HEADER, ++ sizeof(BINDINGS_FILE_HEADER) - 1)) ++ start = (const char *)buf + sizeof(BINDINGS_FILE_HEADER) - 1; ++ else ++ start = buf; ++ binding = mock_ptr_type(char *); ++ start = strstr(start, binding); ++ check_expected(count); ++ assert_ptr_not_equal(start, NULL); ++ return __set_errno(mock_type(int)); + } + +-ssize_t __wrap_write(int fd, const void *buf, size_t count) ++int __wrap_rename(const char *old, const char *new) + { +- check_expected(count); +- check_expected(buf); + return __set_errno(mock_type(int)); + } + +-int __wrap_ftruncate(int fd, off_t length) ++int __wrap_mkstemp(char *template) + { +- check_expected(length); +- return __set_errno(mock_type(int)); ++ return 10; + } + + int __wrap_dm_map_present(const char * str) +@@ -84,32 +95,6 @@ int __wrap_dm_get_uuid(const char *name, char *uuid, int uuid_len) + #define TEST_FDNO 1234 + #define TEST_FPTR ((FILE *) 0xaffe) + +-int __wrap_open_file(const char *file, int *can_write, const char *header) +-{ +- int cw = mock_type(int); +- +- *can_write = cw; +- return TEST_FDNO; +-} +- +-FILE *__wrap_fdopen(int fd, const char *mode) +-{ +- assert_int_equal(fd, TEST_FDNO); +- return TEST_FPTR; +-} +- +-int __wrap_fflush(FILE *f) +-{ +- assert_ptr_equal(f, TEST_FPTR); +- return 0; +-} +- +-int __wrap_fclose(FILE *f) +-{ +- assert_ptr_equal(f, TEST_FPTR); +- return 0; +-} +- + /* strbuf wrapper for the old format_devname() */ + static int __format_devname(char *name, int id, size_t len, const char *prefix) + { +@@ -466,22 +451,85 @@ static void mock_self_alias(const char *alias, const char *wwid) + expect_condlog(3, USED_STR(alias, wwid)); \ + } while(0) + +-static void mock_bindings_file(const char *content, int match_line) ++static int add_binding_unsorted(Bindings *bindings, ++ const char *alias, const char *wwid) ++{ ++ struct binding *bdg = calloc(1, sizeof(*bdg)); ++ ++ if (!bdg) ++ return -1; ++ bdg->wwid = strdup(wwid); ++ bdg->alias = strdup(alias); ++ if (!bdg->wwid || !bdg->alias || !vector_alloc_slot(bindings)) { ++ free(bdg->alias); ++ free(bdg->wwid); ++ free(bdg); ++ return BINDING_ERROR; ++ } ++ vector_set_slot(bindings, bdg); ++ return BINDING_ADDED; ++} ++ ++static void __mock_bindings_file(const char *content, ++ int (*add)(Bindings *, const char *, const char *)) + { +- static char cnt[1024]; +- char *token; ++ char *cnt __attribute__((cleanup(cleanup_charp))) = NULL; ++ char *token, *savep = NULL; + int i; + +- assert_in_range(strlcpy(cnt, content, sizeof(cnt)), 0, sizeof(cnt) - 1); ++ cnt = strdup(content); ++ assert_ptr_not_equal(cnt, NULL); + +- for (token = strtok(cnt, "\n"), i = 0; ++ for (token = strtok_r(cnt, "\n", &savep), i = 0; + token && *token; +- token = strtok(NULL, "\n"), i++) { +- will_return(__wrap_fgets, token); +- if (match_line == i) +- return; ++ token = strtok_r(NULL, "\n", &savep), i++) { ++ char *alias, *wwid; ++ int rc; ++ ++ if (read_binding(token, i + 1, &alias, &wwid) ++ == READ_BINDING_SKIP) ++ continue; ++ ++ rc = add(&global_bindings, alias, wwid); ++ assert_int_equal(rc, BINDING_ADDED); + } +- will_return(__wrap_fgets, NULL); ++} ++ ++static void mock_bindings_file(const char *content) { ++ return __mock_bindings_file(content, add_binding); ++} ++ ++static void mock_bindings_file_unsorted(const char *content) { ++ return __mock_bindings_file(content, add_binding_unsorted); ++} ++ ++static int teardown_bindings(void **state) ++{ ++ cleanup_bindings(); ++ return 0; ++} ++ ++static int lookup_binding(FILE *dummy, const char *wwid, char **alias, ++ const char *prefix, int check_if_taken) ++{ ++ const struct binding *bdg; ++ int id; ++ ++ /* ++ * get_free_id() always checks if aliases are taken. ++ * Therefore if prefix is non-null, check_if_taken must be true. ++ */ ++ assert_true(!prefix || check_if_taken); ++ *alias = NULL; ++ bdg = get_binding_for_wwid(&global_bindings, wwid); ++ if (bdg) { ++ *alias = strdup(bdg->alias); ++ return 0; ++ } else if (!prefix && check_if_taken) ++ return -1; ++ ++ id = get_free_id(&global_bindings, prefix, wwid); ++ return id; + } + + static void lb_empty(void **state) +@@ -489,7 +537,7 @@ static void lb_empty(void **state) + int rc; + char *alias; + +- mock_bindings_file("", -1); ++ mock_bindings_file(""); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + rc = lookup_binding(NULL, "WWID0", &alias, NULL, 0); + assert_int_equal(rc, 1); +@@ -501,7 +549,7 @@ static void lb_empty_unused(void **state) + int rc; + char *alias; + +- mock_bindings_file("", -1); ++ mock_bindings_file(""); + mock_unused_alias("MPATHa"); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); +@@ -515,10 +563,10 @@ static void lb_empty_failed(void **state) + int rc; + char *alias; + +- mock_bindings_file("", -1); ++ mock_bindings_file(""); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + mock_failed_alias("MPATHa", "WWID0"); + mock_unused_alias("MPATHb"); +- expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); + assert_int_equal(rc, 2); + assert_ptr_equal(alias, NULL); +@@ -530,10 +578,10 @@ static void lb_empty_1_used(void **state) + int rc; + char *alias; + +- mock_bindings_file("", -1); ++ mock_bindings_file(""); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + mock_used_alias("MPATHa", "WWID0"); + mock_unused_alias("MPATHb"); +- expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); + assert_int_equal(rc, 2); + assert_ptr_equal(alias, NULL); +@@ -545,10 +593,10 @@ static void lb_empty_1_used_self(void **state) + int rc; + char *alias; + +- mock_bindings_file("", -1); ++ mock_bindings_file(""); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + mock_used_alias("MPATHa", "WWID0"); + mock_self_alias("MPATHb", "WWID0"); +- expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); + assert_int_equal(rc, 2); + assert_ptr_equal(alias, NULL); +@@ -560,9 +608,9 @@ static void lb_match_a(void **state) + int rc; + char *alias; + +- mock_bindings_file("MPATHa WWID0\n", 0); ++ mock_bindings_file("MPATHa WWID0\n"); + expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); +- rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 0); ++ rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); + assert_int_equal(rc, 0); + assert_ptr_not_equal(alias, NULL); + assert_string_equal(alias, "MPATHa"); +@@ -574,9 +622,10 @@ static void lb_nomatch_a(void **state) + int rc; + char *alias; + +- mock_bindings_file("MPATHa WWID0\n", -1); ++ mock_bindings_file("MPATHa WWID0\n"); + expect_condlog(3, NOMATCH_WWID_STR("WWID1")); +- rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 0); ++ mock_unused_alias("MPATHb"); ++ rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); + assert_int_equal(rc, 2); + assert_ptr_equal(alias, NULL); + } +@@ -586,8 +635,8 @@ static void lb_nomatch_a_bad_check(void **state) + int rc; + char *alias; + +- mock_bindings_file("MPATHa WWID0\n", -1); +- expect_condlog(0, NOMORE_STR); ++ mock_bindings_file("MPATHa WWID0\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID1")); + rc = lookup_binding(NULL, "WWID1", &alias, NULL, 1); + assert_int_equal(rc, -1); + assert_ptr_equal(alias, NULL); +@@ -598,7 +647,7 @@ static void lb_nomatch_a_unused(void **state) + int rc; + char *alias; + +- mock_bindings_file("MPATHa WWID0\n", -1); ++ mock_bindings_file("MPATHa WWID0\n"); + mock_unused_alias("MPATHb"); + expect_condlog(3, NOMATCH_WWID_STR("WWID1")); + rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); +@@ -611,27 +660,27 @@ static void lb_nomatch_a_3_used_failed_self(void **state) + int rc; + char *alias; + +- mock_bindings_file("MPATHa WWID0\n", -1); ++ mock_bindings_file("MPATHa WWID0\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID1")); + mock_used_alias("MPATHb", "WWID1"); + mock_used_alias("MPATHc", "WWID1"); + mock_used_alias("MPATHd", "WWID1"); + mock_failed_alias("MPATHe", "WWID1"); + mock_self_alias("MPATHf", "WWID1"); +- expect_condlog(3, NOMATCH_WWID_STR("WWID1")); + rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); + assert_int_equal(rc, 6); + assert_ptr_equal(alias, NULL); + } + +-static void do_lb_match_c(void **state, int check_if_taken) ++static void do_lb_match_c(void **state) + { + int rc; + char *alias; + + mock_bindings_file("MPATHa WWID0\n" +- "MPATHc WWID1", 1); ++ "MPATHc WWID1"); + expect_condlog(3, FOUND_STR("MPATHc", "WWID1")); +- rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", check_if_taken); ++ rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); + assert_int_equal(rc, 0); + assert_ptr_not_equal(alias, NULL); + assert_string_equal(alias, "MPATHc"); +@@ -640,12 +689,12 @@ static void do_lb_match_c(void **state, int check_if_taken) + + static void lb_match_c(void **state) + { +- do_lb_match_c(state, 0); ++ do_lb_match_c(state); + } + + static void lb_match_c_check(void **state) + { +- do_lb_match_c(state, 1); ++ do_lb_match_c(state); + } + + static void lb_nomatch_a_c(void **state) +@@ -654,9 +703,10 @@ static void lb_nomatch_a_c(void **state) + char *alias; + + mock_bindings_file("MPATHa WWID0\n" +- "MPATHc WWID1", -1); ++ "MPATHc WWID1"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); +- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); ++ mock_unused_alias("MPATHb"); ++ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, 2); + assert_ptr_equal(alias, NULL); + } +@@ -667,7 +717,7 @@ static void lb_nomatch_a_d_unused(void **state) + char *alias; + + mock_bindings_file("MPATHa WWID0\n" +- "MPATHd WWID1", -1); ++ "MPATHd WWID1"); + mock_unused_alias("MPATHb"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); +@@ -681,10 +731,10 @@ static void lb_nomatch_a_d_1_used(void **state) + char *alias; + + mock_bindings_file("MPATHa WWID0\n" +- "MPATHd WWID1", -1); ++ "MPATHd WWID1"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + mock_used_alias("MPATHb", "WWID2"); + mock_unused_alias("MPATHc"); +- expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, 3); + assert_ptr_equal(alias, NULL); +@@ -696,11 +746,11 @@ static void lb_nomatch_a_d_2_used(void **state) + char *alias; + + mock_bindings_file("MPATHa WWID0\n" +- "MPATHd WWID1", -1); ++ "MPATHd WWID1"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + mock_used_alias("MPATHb", "WWID2"); + mock_used_alias("MPATHc", "WWID2"); + mock_unused_alias("MPATHe"); +- expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, 5); + assert_ptr_equal(alias, NULL); +@@ -712,12 +762,12 @@ static void lb_nomatch_a_d_3_used(void **state) + char *alias; + + mock_bindings_file("MPATHa WWID0\n" +- "MPATHd WWID1", -1); ++ "MPATHd WWID1"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + mock_used_alias("MPATHb", "WWID2"); + mock_used_alias("MPATHc", "WWID2"); + mock_used_alias("MPATHe", "WWID2"); + mock_unused_alias("MPATHf"); +- expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, 6); + assert_ptr_equal(alias, NULL); +@@ -729,9 +779,10 @@ static void lb_nomatch_c_a(void **state) + char *alias; + + mock_bindings_file("MPATHc WWID1\n" +- "MPATHa WWID0\n", -1); ++ "MPATHa WWID0\n"); ++ mock_unused_alias("MPATHb"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); +- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); ++ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, 2); + assert_ptr_equal(alias, NULL); + } +@@ -743,7 +794,7 @@ static void lb_nomatch_d_a_unused(void **state) + + mock_bindings_file("MPATHc WWID1\n" + "MPATHa WWID0\n" +- "MPATHd WWID0\n", -1); ++ "MPATHd WWID0\n"); + mock_unused_alias("MPATHb"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); +@@ -758,10 +809,10 @@ static void lb_nomatch_d_a_1_used(void **state) + + mock_bindings_file("MPATHc WWID1\n" + "MPATHa WWID0\n" +- "MPATHd WWID0\n", -1); ++ "MPATHd WWID0\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + mock_used_alias("MPATHb", "WWID2"); + mock_unused_alias("MPATHe"); +- expect_condlog(3, NOMATCH_WWID_STR("WWID2")); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, 5); + assert_ptr_equal(alias, NULL); +@@ -774,9 +825,10 @@ static void lb_nomatch_a_b(void **state) + + mock_bindings_file("MPATHa WWID0\n" + "MPATHz WWID26\n" +- "MPATHb WWID1\n", -1); ++ "MPATHb WWID1\n"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); +- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); ++ mock_unused_alias("MPATHc"); ++ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); + assert_int_equal(rc, 3); + assert_ptr_equal(alias, NULL); + } +@@ -786,13 +838,19 @@ static void lb_nomatch_a_b_bad(void **state) + int rc; + char *alias; + ++ expect_condlog(1, "invalid line 3 in bindings file, missing WWID\n"); ++ /* ++ * The broken line will be ignored when constructing the bindings vector. ++ * Thus in lookup_binding() MPATHb is never encountered, ++ * and MPATHb appears usable. ++ */ + mock_bindings_file("MPATHa WWID0\n" + "MPATHz WWID26\n" +- "MPATHb\n", -1); +- expect_condlog(3, "Ignoring malformed line 3 in bindings file\n"); ++ "MPATHb\n"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); +- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); +- assert_int_equal(rc, 3); ++ mock_unused_alias("MPATHb"); ++ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); ++ assert_int_equal(rc, 2); + assert_ptr_equal(alias, NULL); + } + +@@ -801,84 +859,200 @@ static void lb_nomatch_a_b_bad_self(void **state) + int rc; + char *alias; + ++ expect_condlog(1, "invalid line 3 in bindings file, missing WWID\n"); + mock_bindings_file("MPATHa WWID0\n" + "MPATHz WWID26\n" +- "MPATHb\n", -1); +- expect_condlog(3, "Ignoring malformed line 3 in bindings file\n"); +- mock_self_alias("MPATHc", "WWID2"); ++ "MPATHb\n"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); ++ mock_self_alias("MPATHb", "WWID2"); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); +- assert_int_equal(rc, 3); ++ assert_int_equal(rc, 2); + assert_ptr_equal(alias, NULL); + } + +-static void lb_nomatch_b_a(void **state) ++static void lb_nomatch_b_z_a(void **state) + { + int rc; + char *alias; + ++ /* ++ * add_bindings() sorts alphabetically. Therefore get_free_id() ++ * finds MPATHc as a free entry. ++ */ + mock_bindings_file("MPATHb WWID1\n" + "MPATHz WWID26\n" +- "MPATHa WWID0\n", -1); ++ "MPATHa WWID0\n"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); +- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); +- assert_int_equal(rc, 27); ++ mock_unused_alias("MPATHc"); ++ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); ++ assert_int_equal(rc, 3); + assert_ptr_equal(alias, NULL); + } + +-static void lb_nomatch_b_a_3_used(void **state) ++static void lb_nomatch_b_aa_a(void **state) + { + int rc; + char *alias; + ++ /* ++ * add_bindings() sorts alphabetically. ("a", "aa", b"). ++ * The get_free_id() algorithm finds the "hole" after "b". ++ */ + mock_bindings_file("MPATHb WWID1\n" + "MPATHz WWID26\n" +- "MPATHa WWID0\n", -1); +- mock_used_alias("MPATHaa", "WWID2"); +- mock_used_alias("MPATHab", "WWID2"); +- mock_used_alias("MPATHac", "WWID2"); +- mock_unused_alias("MPATHad"); ++ "MPATHa WWID0\n"); + expect_condlog(3, NOMATCH_WWID_STR("WWID2")); ++ mock_unused_alias("MPATHc"); + rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); +- assert_int_equal(rc, 30); ++ assert_int_equal(rc, 3); + assert_ptr_equal(alias, NULL); + } + +-#ifdef MPATH_ID_INT_MAX +-static void do_lb_nomatch_int_max(void **state, int check_if_taken) ++static void fill_bindings(struct strbuf *buf, int start, int end) ++{ ++ int i; ++ ++ for (i = start; i <= end; i++) { ++ print_strbuf(buf, "MPATH"); ++ format_devname(buf, i + 1); ++ print_strbuf(buf, " WWID%d\n", i); ++ } ++} ++ ++static void lb_nomatch_b_a_aa(void **state) ++{ ++ int rc; ++ char *alias; ++ STRBUF_ON_STACK(buf); ++ ++ /* ++ * add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...) ++ * lookup_binding finds MPATHac as next free entry. ++ */ ++ fill_bindings(&buf, 0, 26); ++ mock_bindings_file(get_strbuf_str(&buf)); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID28")); ++ mock_unused_alias("MPATHab"); ++ rc = lookup_binding(NULL, "WWID28", &alias, "MPATH", 1); ++ assert_int_equal(rc, 28); ++ assert_ptr_equal(alias, NULL); ++} ++ ++static void lb_nomatch_b_a_aa_zz(void **state) ++{ ++ int rc, i; ++ char *alias; ++ STRBUF_ON_STACK(buf); ++ ++ /* ++ * add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...) ++ * lookup_binding finds MPATHaaa as next free entry, because MPATHaa is ++ * found before MPATHb, and MPATHzz was in the bindings, too. ++ */ ++ for (i = 0; i <= 26; i++) { ++ print_strbuf(&buf, "MPATH"); ++ format_devname(&buf, i + 1); ++ print_strbuf(&buf, " WWID%d\n", i); ++ } ++ print_strbuf(&buf, "MPATHzz WWID676\n"); ++ mock_bindings_file(get_strbuf_str(&buf)); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID703")); ++ mock_unused_alias("MPATHaaa"); ++ rc = lookup_binding(NULL, "WWID703", &alias, "MPATH", 1); ++ assert_int_equal(rc, 703); ++ assert_ptr_equal(alias, NULL); ++} ++ ++static void lb_nomatch_b_z_a_unsorted(void **state) ++{ ++ int rc; ++ char *alias; ++ ++ /* ++ * With unsorted bindings (shouldn't happen normally), get_free_id() ++ * plays safe and returns MPATHaa as first free entry. ++ */ ++ mock_bindings_file_unsorted("MPATHb WWID1\n" ++ "MPATHz WWID26\n" ++ "MPATHa WWID0\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); ++ mock_unused_alias("MPATHaa"); ++ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); ++ assert_int_equal(rc, 27); ++ assert_ptr_equal(alias, NULL); ++} ++ ++static void lb_nomatch_b_a(void **state) + { + int rc; + char *alias; + + mock_bindings_file("MPATHb WWID1\n" +- "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n" +- "MPATHa WWID0\n", -1); +- expect_condlog(0, NOMORE_STR); +- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", check_if_taken); +- assert_int_equal(rc, -1); ++ "MPATHa WWID0\n"); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); ++ mock_unused_alias("MPATHc"); ++ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); ++ assert_int_equal(rc, 3); + assert_ptr_equal(alias, NULL); + } + +-static void lb_nomatch_int_max(void **state) ++static void lb_nomatch_b_a_3_used(void **state) + { +- do_lb_nomatch_int_max(state, 0); ++ int rc; ++ char *alias; ++ STRBUF_ON_STACK(buf); ++ ++ fill_bindings(&buf, 0, 26); ++ mock_bindings_file(get_strbuf_str(&buf)); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID31")); ++ mock_used_alias("MPATHab", "WWID31"); ++ mock_used_alias("MPATHac", "WWID31"); ++ mock_used_alias("MPATHad", "WWID31"); ++ mock_unused_alias("MPATHae"); ++ rc = lookup_binding(NULL, "WWID31", &alias, "MPATH", 1); ++ assert_int_equal(rc, 31); ++ assert_ptr_equal(alias, NULL); + } + +-static void lb_nomatch_int_max_check(void **state) ++#ifdef MPATH_ID_INT_MAX ++/* ++ * The bindings will be sorted by alias, alphabetically, which is not ++ * the same as the "numeric" sort order for user-friendly aliases. ++ * get_free_id() selects the highest used ID + 1 if an unsorted entry ++ * is encountered in the bindings table and it's id is equal to the ++ * next "expected" id. This happens if all IDs from "a" to "aa" are ++ * in the table. If the INT_MAX entry is in the table, too, it will ++ * overflow. ++ */ ++static void lb_nomatch_int_max(void **state) + { +- do_lb_nomatch_int_max(state, 1); ++ int rc; ++ char *alias; ++ STRBUF_ON_STACK(buf); ++ ++ fill_bindings(&buf, 0, 26); ++ print_strbuf(&buf, "MPATH%s WWIDMAX\n", MPATH_ID_INT_MAX); ++ mock_bindings_file(get_strbuf_str(&buf)); ++ expect_condlog(3, NOMATCH_WWID_STR("WWIDNOMORE")); ++ expect_condlog(0, NOMORE_STR); ++ rc = lookup_binding(NULL, "WWIDNOMORE", &alias, "MPATH", 1); ++ assert_int_equal(rc, -1); ++ assert_ptr_equal(alias, NULL); + } + + static void lb_nomatch_int_max_used(void **state) + { + int rc; + char *alias; ++ STRBUF_ON_STACK(buf); + +- mock_bindings_file("MPATHb WWID1\n" +- "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n", -1); +- mock_used_alias("MPATHa", "WWID2"); ++ fill_bindings(&buf, 1, 26); ++ print_strbuf(&buf, "MPATH%s WWIDMAX\n", MPATH_ID_INT_MAX); ++ mock_bindings_file(get_strbuf_str(&buf)); ++ expect_condlog(3, NOMATCH_WWID_STR("WWIDNOMORE")); ++ mock_used_alias("MPATHa", "WWIDNOMORE"); + expect_condlog(0, NOMORE_STR); +- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); ++ rc = lookup_binding(NULL, "WWIDNOMORE", &alias, "MPATH", 1); + assert_int_equal(rc, -1); + assert_ptr_equal(alias, NULL); + } +@@ -887,12 +1061,14 @@ static void lb_nomatch_int_max_m1(void **state) + { + int rc; + char *alias; ++ STRBUF_ON_STACK(buf); + +- mock_bindings_file("MPATHb WWID1\n" +- "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n" +- "MPATHa WWID0\n", -1); +- expect_condlog(3, NOMATCH_WWID_STR("WWID2")); +- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); ++ fill_bindings(&buf, 0, 26); ++ print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1); ++ mock_bindings_file(get_strbuf_str(&buf)); ++ expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); ++ mock_unused_alias("MPATH" MPATH_ID_INT_MAX); ++ rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); + assert_int_equal(rc, INT_MAX); + assert_ptr_equal(alias, NULL); + } +@@ -901,13 +1077,15 @@ static void lb_nomatch_int_max_m1_used(void **state) + { + int rc; + char *alias; ++ STRBUF_ON_STACK(buf); + +- mock_bindings_file("MPATHb WWID1\n" +- "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n" +- "MPATHa WWID0\n", -1); +- mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2"); ++ fill_bindings(&buf, 0, 26); ++ print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1); ++ mock_bindings_file(get_strbuf_str(&buf)); ++ expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); ++ mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWIDMAX"); + expect_condlog(0, NOMORE_STR); +- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); ++ rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); + assert_int_equal(rc, -1); + assert_ptr_equal(alias, NULL); + } +@@ -916,13 +1094,15 @@ static void lb_nomatch_int_max_m1_1_used(void **state) + { + int rc; + char *alias; ++ STRBUF_ON_STACK(buf); + +- mock_bindings_file("MPATHb WWID1\n" +- "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n", -1); +- mock_used_alias("MPATHa", "WWID2"); ++ fill_bindings(&buf, 1, 26); ++ print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1); ++ mock_bindings_file(get_strbuf_str(&buf)); ++ expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); ++ mock_used_alias("MPATHa", "WWIDMAX"); + mock_unused_alias("MPATH" MPATH_ID_INT_MAX); +- expect_condlog(3, NOMATCH_WWID_STR("WWID2")); +- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); ++ rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); + assert_int_equal(rc, INT_MAX); + assert_ptr_equal(alias, NULL); + } +@@ -931,13 +1111,17 @@ static void lb_nomatch_int_max_m1_2_used(void **state) + { + int rc; + char *alias; ++ STRBUF_ON_STACK(buf); + +- mock_bindings_file("MPATHb WWID1\n" +- "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n", -1); +- mock_used_alias("MPATHa", "WWID2"); +- mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2"); ++ fill_bindings(&buf, 1, 26); ++ print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1); ++ mock_bindings_file(get_strbuf_str(&buf)); ++ ++ expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); ++ mock_used_alias("MPATHa", "WWIDMAX"); ++ mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWIDMAX"); + expect_condlog(0, NOMORE_STR); +- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); ++ rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); + assert_int_equal(rc, -1); + assert_ptr_equal(alias, NULL); + } +@@ -946,52 +1130,68 @@ static void lb_nomatch_int_max_m1_2_used(void **state) + static int test_lookup_binding(void) + { + const struct CMUnitTest tests[] = { +- cmocka_unit_test(lb_empty), +- cmocka_unit_test(lb_empty_unused), +- cmocka_unit_test(lb_empty_failed), +- cmocka_unit_test(lb_empty_1_used), +- cmocka_unit_test(lb_empty_1_used_self), +- cmocka_unit_test(lb_match_a), +- cmocka_unit_test(lb_nomatch_a), +- cmocka_unit_test(lb_nomatch_a_bad_check), +- cmocka_unit_test(lb_nomatch_a_unused), +- cmocka_unit_test(lb_nomatch_a_3_used_failed_self), +- cmocka_unit_test(lb_match_c), +- cmocka_unit_test(lb_match_c_check), +- cmocka_unit_test(lb_nomatch_a_c), +- cmocka_unit_test(lb_nomatch_a_d_unused), +- cmocka_unit_test(lb_nomatch_a_d_1_used), +- cmocka_unit_test(lb_nomatch_a_d_2_used), +- cmocka_unit_test(lb_nomatch_a_d_3_used), +- cmocka_unit_test(lb_nomatch_c_a), +- cmocka_unit_test(lb_nomatch_d_a_unused), +- cmocka_unit_test(lb_nomatch_d_a_1_used), +- cmocka_unit_test(lb_nomatch_a_b), +- cmocka_unit_test(lb_nomatch_a_b_bad), +- cmocka_unit_test(lb_nomatch_a_b_bad_self), +- cmocka_unit_test(lb_nomatch_b_a), +- cmocka_unit_test(lb_nomatch_b_a_3_used), ++ cmocka_unit_test_teardown(lb_empty, teardown_bindings), ++ cmocka_unit_test_teardown(lb_empty_unused, teardown_bindings), ++ cmocka_unit_test_teardown(lb_empty_failed, teardown_bindings), ++ cmocka_unit_test_teardown(lb_empty_1_used, teardown_bindings), ++ cmocka_unit_test_teardown(lb_empty_1_used_self, teardown_bindings), ++ cmocka_unit_test_teardown(lb_match_a, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_a, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_a_bad_check, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_a_unused, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_a_3_used_failed_self, teardown_bindings), ++ cmocka_unit_test_teardown(lb_match_c, teardown_bindings), ++ cmocka_unit_test_teardown(lb_match_c_check, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_a_c, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_a_d_unused, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_a_d_1_used, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_a_d_2_used, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_a_d_3_used, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_c_a, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_d_a_unused, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_d_a_1_used, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_a_b, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_a_b_bad, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_a_b_bad_self, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_b_z_a, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_b_aa_a, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_b_a_aa, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_b_a_aa_zz, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_b_z_a_unsorted, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_b_a, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_b_a_3_used, teardown_bindings), + #ifdef MPATH_ID_INT_MAX +- cmocka_unit_test(lb_nomatch_int_max), +- cmocka_unit_test(lb_nomatch_int_max_check), +- cmocka_unit_test(lb_nomatch_int_max_used), +- cmocka_unit_test(lb_nomatch_int_max_m1), +- cmocka_unit_test(lb_nomatch_int_max_m1_used), +- cmocka_unit_test(lb_nomatch_int_max_m1_1_used), +- cmocka_unit_test(lb_nomatch_int_max_m1_2_used), ++ cmocka_unit_test_teardown(lb_nomatch_int_max, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_int_max_used, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_int_max_m1, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_int_max_m1_used, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_int_max_m1_1_used, teardown_bindings), ++ cmocka_unit_test_teardown(lb_nomatch_int_max_m1_2_used, teardown_bindings), + #endif + }; + + return cmocka_run_group_tests(tests, NULL, NULL); + } + ++static int rlookup_binding(FILE *dummy, char *buf, const char *alias) { ++ ++ const struct binding *bdg; ++ ++ bdg = get_binding_for_alias(&global_bindings, alias); ++ if (!bdg) { ++ return -1; ++ } ++ strlcpy(buf, bdg->wwid, WWID_SIZE); ++ return 0; ++} ++ + static void rl_empty(void **state) + { + int rc; + char buf[WWID_SIZE]; + + buf[0] = '\0'; +- mock_bindings_file("", -1); ++ mock_bindings_file(""); + expect_condlog(3, NOMATCH_STR("MPATHa")); + rc = rlookup_binding(NULL, buf, "MPATHa"); + assert_int_equal(rc, -1); +@@ -1004,7 +1204,7 @@ static void rl_match_a(void **state) + char buf[WWID_SIZE]; + + buf[0] = '\0'; +- mock_bindings_file("MPATHa WWID0\n", 0); ++ mock_bindings_file("MPATHa WWID0\n"); + expect_condlog(3, FOUND_ALIAS_STR("MPATHa", "WWID0")); + rc = rlookup_binding(NULL, buf, "MPATHa"); + assert_int_equal(rc, 0); +@@ -1017,7 +1217,7 @@ static void rl_nomatch_a(void **state) + char buf[WWID_SIZE]; + + buf[0] = '\0'; +- mock_bindings_file("MPATHa WWID0\n", -1); ++ mock_bindings_file("MPATHa WWID0\n"); + expect_condlog(3, NOMATCH_STR("MPATHb")); + rc = rlookup_binding(NULL, buf, "MPATHb"); + assert_int_equal(rc, -1); +@@ -1030,8 +1230,8 @@ static void rl_malformed_a(void **state) + char buf[WWID_SIZE]; + + buf[0] = '\0'; +- mock_bindings_file("MPATHa \n", -1); +- expect_condlog(3, "Ignoring malformed line 1 in bindings file\n"); ++ expect_condlog(1, "invalid line 1 in bindings file, missing WWID\n"); ++ mock_bindings_file("MPATHa \n"); + expect_condlog(3, NOMATCH_STR("MPATHa")); + rc = rlookup_binding(NULL, buf, "MPATHa"); + assert_int_equal(rc, -1); +@@ -1049,8 +1249,8 @@ static void rl_overlong_a(void **state) + snprintf(line + sizeof(line) - 2, 2, "\n"); + + buf[0] = '\0'; +- mock_bindings_file(line, -1); + expect_condlog(3, "Ignoring too large wwid at 1 in bindings file\n"); ++ mock_bindings_file(line); + expect_condlog(3, NOMATCH_STR("MPATHa")); + rc = rlookup_binding(NULL, buf, "MPATHa"); + assert_int_equal(rc, -1); +@@ -1065,7 +1265,7 @@ static void rl_match_b(void **state) + buf[0] = '\0'; + mock_bindings_file("MPATHa WWID0\n" + "MPATHz WWID26\n" +- "MPATHb WWID2\n", 2); ++ "MPATHb WWID2\n"); + expect_condlog(3, FOUND_ALIAS_STR("MPATHb", "WWID2")); + rc = rlookup_binding(NULL, buf, "MPATHb"); + assert_int_equal(rc, 0); +@@ -1075,31 +1275,41 @@ static void rl_match_b(void **state) + static int test_rlookup_binding(void) + { + const struct CMUnitTest tests[] = { +- cmocka_unit_test(rl_empty), +- cmocka_unit_test(rl_match_a), +- cmocka_unit_test(rl_nomatch_a), +- cmocka_unit_test(rl_malformed_a), +- cmocka_unit_test(rl_overlong_a), +- cmocka_unit_test(rl_match_b), ++ cmocka_unit_test_teardown(rl_empty, teardown_bindings), ++ cmocka_unit_test_teardown(rl_match_a, teardown_bindings), ++ cmocka_unit_test_teardown(rl_nomatch_a, teardown_bindings), ++ cmocka_unit_test_teardown(rl_malformed_a, teardown_bindings), ++ cmocka_unit_test_teardown(rl_overlong_a, teardown_bindings), ++ cmocka_unit_test_teardown(rl_match_b, teardown_bindings), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); + } + ++void check_bindings_size(int n) ++{ ++ /* avoid -Waddress problem */ ++ Bindings *bindings = &global_bindings; ++ ++ assert_int_equal(VECTOR_SIZE(bindings), n); ++} ++ + static void al_a(void **state) + { + static const char ln[] = "MPATHa WWIDa\n"; + char *alias; + +- will_return(__wrap_lseek, 0); +- expect_value(__wrap_write, count, strlen(ln)); +- expect_string(__wrap_write, buf, ln); +- will_return(__wrap_write, strlen(ln)); ++ expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); ++ will_return(__wrap_write, ln); ++ will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); ++ will_return(__wrap_rename, 0); ++ expect_condlog(1, "updated bindings file foo"); + expect_condlog(3, NEW_STR("MPATHa", "WWIDa")); + +- alias = allocate_binding(0, "WWIDa", 1, "MPATH"); ++ alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); + assert_ptr_not_equal(alias, NULL); + assert_string_equal(alias, "MPATHa"); ++ check_bindings_size(1); + free(alias); + } + +@@ -1108,15 +1318,17 @@ static void al_zz(void **state) + static const char ln[] = "MPATHzz WWIDzz\n"; + char *alias; + +- will_return(__wrap_lseek, 0); +- expect_value(__wrap_write, count, strlen(ln)); +- expect_string(__wrap_write, buf, ln); +- will_return(__wrap_write, strlen(ln)); ++ expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); ++ will_return(__wrap_write, ln); ++ will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); ++ will_return(__wrap_rename, 0); ++ expect_condlog(1, "updated bindings file foo"); + expect_condlog(3, NEW_STR("MPATHzz", "WWIDzz")); + +- alias = allocate_binding(0, "WWIDzz", 26*26 + 26, "MPATH"); ++ alias = allocate_binding("foo", "WWIDzz", 26*26 + 26, "MPATH"); + assert_ptr_not_equal(alias, NULL); + assert_string_equal(alias, "MPATHzz"); ++ check_bindings_size(1); + free(alias); + } + +@@ -1127,6 +1339,7 @@ static void al_0(void **state) + expect_condlog(0, "allocate_binding: cannot allocate new binding for id 0\n"); + alias = allocate_binding(0, "WWIDa", 0, "MPATH"); + assert_ptr_equal(alias, NULL); ++ check_bindings_size(0); + } + + static void al_m2(void **state) +@@ -1136,67 +1349,133 @@ static void al_m2(void **state) + expect_condlog(0, "allocate_binding: cannot allocate new binding for id -2\n"); + alias = allocate_binding(0, "WWIDa", -2, "MPATH"); + assert_ptr_equal(alias, NULL); ++ check_bindings_size(0); ++} ++ ++static void al_write_partial(void **state) ++{ ++ static const char ln[] = "MPATHa WWIDa\n"; ++ char *alias; ++ ++ expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); ++ will_return(__wrap_write, ln); ++ will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln) - 1); ++ expect_value(__wrap_write, count, 1); ++ will_return(__wrap_write, ln + sizeof(ln) - 2); ++ will_return(__wrap_write, 1); ++ will_return(__wrap_rename, 0); ++ expect_condlog(1, "updated bindings file foo"); ++ expect_condlog(3, "Created new binding [MPATHa] for WWID [WWIDa]\n"); ++ ++ alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); ++ assert_ptr_not_equal(alias, NULL); ++ assert_string_equal(alias, "MPATHa"); ++ check_bindings_size(1); ++ free(alias); + } + +-static void al_lseek_err(void **state) ++static void al_write_short(void **state) + { ++ static const char ln[] = "MPATHa WWIDa\n"; + char *alias; + +- will_return(__wrap_lseek, -ENODEV); +- expect_condlog(0, "Cannot seek to end of bindings file : No such device\n"); +- alias = allocate_binding(0, "WWIDa", 1, "MPATH"); ++ expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); ++ will_return(__wrap_write, ln); ++ will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln) - 1); ++ expect_value(__wrap_write, count, 1); ++ will_return(__wrap_write, ln + sizeof(ln) - 2); ++ will_return(__wrap_write, 0); ++ expect_condlog(2, "write_bindings_file: short write"); ++ expect_condlog(1, "failed to write new bindings file"); ++ expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa"); ++ ++ alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); + assert_ptr_equal(alias, NULL); ++ check_bindings_size(0); + } + + static void al_write_err(void **state) + { + static const char ln[] = "MPATHa WWIDa\n"; +- const int offset = 20; + char *alias; + +- will_return(__wrap_lseek, offset); +- expect_value(__wrap_write, count, strlen(ln)); +- expect_string(__wrap_write, buf, ln); +- will_return(__wrap_write, strlen(ln) - 1); +- expect_value(__wrap_ftruncate, length, offset); +- will_return(__wrap_ftruncate, 0); +- expect_condlog(0, "Cannot write binding to bindings file :"); ++ expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); ++ will_return(__wrap_write, ln); ++ will_return(__wrap_write, -EPERM); ++ expect_condlog(1, "failed to write new bindings file"); ++ expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa"); + +- alias = allocate_binding(0, "WWIDa", 1, "MPATH"); ++ alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); + assert_ptr_equal(alias, NULL); ++ check_bindings_size(0); ++} ++ ++static void al_rename_err(void **state) ++{ ++ static const char ln[] = "MPATHa WWIDa\n"; ++ char *alias; ++ ++ expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); ++ will_return(__wrap_write, ln); ++ will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); ++ will_return(__wrap_rename, -EROFS); ++ ++ expect_condlog(0, "update_bindings_file: rename: Read-only file system"); ++ expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa"); ++ alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); ++ assert_ptr_equal(alias, NULL); ++ check_bindings_size(0); + } + + static int test_allocate_binding(void) + { + const struct CMUnitTest tests[] = { +- cmocka_unit_test(al_a), +- cmocka_unit_test(al_zz), +- cmocka_unit_test(al_0), +- cmocka_unit_test(al_m2), +- cmocka_unit_test(al_lseek_err), +- cmocka_unit_test(al_write_err), ++ cmocka_unit_test_teardown(al_a, teardown_bindings), ++ cmocka_unit_test_teardown(al_zz, teardown_bindings), ++ cmocka_unit_test_teardown(al_0, teardown_bindings), ++ cmocka_unit_test_teardown(al_m2, teardown_bindings), ++ cmocka_unit_test_teardown(al_write_partial, teardown_bindings), ++ cmocka_unit_test_teardown(al_write_short, teardown_bindings), ++ cmocka_unit_test_teardown(al_write_err, teardown_bindings), ++ cmocka_unit_test_teardown(al_rename_err, teardown_bindings), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); + } + +-#define mock_allocate_binding(alias, wwid) \ ++#define mock_allocate_binding_err_len(alias, wwid, len, err, msg) \ + do { \ + static const char ln[] = BINDING_STR(alias, wwid); \ + \ +- will_return(__wrap_lseek, 0); \ +- expect_value(__wrap_write, count, strlen(ln)); \ +- expect_string(__wrap_write, buf, ln); \ +- will_return(__wrap_write, strlen(ln)); \ +- expect_condlog(3, NEW_STR(alias, wwid)); \ ++ expect_value(__wrap_write, count, \ ++ strlen(BINDINGS_FILE_HEADER) + (len) + strlen(ln)); \ ++ will_return(__wrap_write, ln); \ ++ will_return(__wrap_write, \ ++ strlen(BINDINGS_FILE_HEADER) + (len) + strlen(ln)); \ ++ will_return(__wrap_rename, err); \ ++ if (err == 0) { \ ++ expect_condlog(1, "updated bindings file x\n"); \ ++ expect_condlog(3, NEW_STR(alias, wwid)); \ ++ } else { \ ++ expect_condlog(0, "update_bindings_file: rename: " msg "\n"); \ ++ expect_condlog(1, "allocate_binding: deleting binding " \ ++ alias " for " wwid "\n"); \ ++ } \ + } while (0) + ++#define mock_allocate_binding_err(alias, wwid, err, msg) \ ++ mock_allocate_binding_err_len(alias, wwid, 0, err, msg) ++ ++#define mock_allocate_binding(alias, wwid) \ ++ mock_allocate_binding_err(alias, wwid, 0, "") ++ ++#define mock_allocate_binding_len(alias, wwid, len) \ ++ mock_allocate_binding_err_len(alias, wwid, len, 0, "") ++ + static void gufa_empty_new_rw(void **state) { + char *alias; + +- will_return(__wrap_open_file, true); +- +- mock_bindings_file("", -1); ++ mock_bindings_file(""); + mock_unused_alias("MPATHa"); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + +@@ -1208,10 +1487,11 @@ static void gufa_empty_new_rw(void **state) { + + static void gufa_empty_new_ro_1(void **state) { + char *alias; +- will_return(__wrap_open_file, false); +- mock_bindings_file("", -1); ++ ++ mock_bindings_file(""); + mock_unused_alias("MPATHa"); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); ++ mock_allocate_binding_err("MPATHa", "WWID0", -EROFS, "Read-only file system"); + + alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false); + assert_ptr_equal(alias, NULL); +@@ -1220,11 +1500,9 @@ static void gufa_empty_new_ro_1(void **state) { + static void gufa_empty_new_ro_2(void **state) { + char *alias; + +- will_return(__wrap_open_file, true); +- +- mock_bindings_file("", -1); +- mock_unused_alias("MPATHa"); ++ mock_bindings_file(""); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); ++ mock_unused_alias("MPATHa"); + + alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); + assert_ptr_equal(alias, NULL); +@@ -1233,11 +1511,10 @@ static void gufa_empty_new_ro_2(void **state) { + static void gufa_match_a_unused(void **state) { + char *alias; + +- will_return(__wrap_open_file, true); +- +- mock_bindings_file("MPATHa WWID0", 0); ++ mock_bindings_file("MPATHa WWID0"); + expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); + mock_unused_alias("MPATHa"); ++ expect_condlog(3, EXISTING_STR("MPATHa", "WWID0")); + + alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); + assert_string_equal(alias, "MPATHa"); +@@ -1247,11 +1524,10 @@ static void gufa_match_a_unused(void **state) { + static void gufa_match_a_self(void **state) { + char *alias; + +- will_return(__wrap_open_file, true); +- +- mock_bindings_file("MPATHa WWID0", 0); ++ mock_bindings_file("MPATHa WWID0"); + expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); + mock_self_alias("MPATHa", "WWID0"); ++ expect_condlog(3, EXISTING_STR("MPATHa", "WWID0")); + + alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); + assert_string_equal(alias, "MPATHa"); +@@ -1261,9 +1537,8 @@ static void gufa_match_a_self(void **state) { + static void gufa_match_a_used(void **state) { + char *alias; + +- will_return(__wrap_open_file, true); + +- mock_bindings_file("MPATHa WWID0", 0); ++ mock_bindings_file("MPATHa WWID0"); + expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); + mock_used_alias("MPATHa", "WWID0"); + +@@ -1273,15 +1548,14 @@ static void gufa_match_a_used(void **state) { + + static void gufa_nomatch_a_c(void **state) { + char *alias; +- will_return(__wrap_open_file, true); ++ static const char bindings[] = ("MPATHa WWID0\n" ++ "MPATHc WWID2\n"); + +- mock_bindings_file("MPATHa WWID0\n" +- "MPATHc WWID2", +- -1); ++ mock_bindings_file(bindings); + mock_unused_alias("MPATHb"); + expect_condlog(3, NOMATCH_WWID_STR("WWID1")); + +- mock_allocate_binding("MPATHb", "WWID1"); ++ mock_allocate_binding_len("MPATHb", "WWID1", strlen(bindings)); + + alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false); + assert_string_equal(alias, "MPATHb"); +@@ -1290,15 +1564,14 @@ static void gufa_nomatch_a_c(void **state) { + + static void gufa_nomatch_c_a(void **state) { + char *alias; +- will_return(__wrap_open_file, true); ++ const char bindings[] = ("MPATHc WWID2\n" ++ "MPATHa WWID0\n"); + +- mock_bindings_file("MPATHc WWID2\n" +- "MPATHa WWID0", +- -1); ++ mock_bindings_file(bindings); + mock_unused_alias("MPATHb"); + expect_condlog(3, NOMATCH_WWID_STR("WWID1")); + +- mock_allocate_binding("MPATHb", "WWID1"); ++ mock_allocate_binding_len("MPATHb", "WWID1", sizeof(bindings) - 1); + + alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false); + assert_string_equal(alias, "MPATHb"); +@@ -1307,15 +1580,14 @@ static void gufa_nomatch_c_a(void **state) { + + static void gufa_nomatch_c_b(void **state) { + char *alias; +- will_return(__wrap_open_file, true); ++ const char bindings[] = ("MPATHc WWID2\n" ++ "MPATHb WWID1\n"); + +- mock_bindings_file("MPATHc WWID2\n" +- "MPATHb WWID1\n", +- -1); +- mock_unused_alias("MPATHa"); ++ mock_bindings_file(bindings); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); ++ mock_unused_alias("MPATHa"); + +- mock_allocate_binding("MPATHa", "WWID0"); ++ mock_allocate_binding_len("MPATHa", "WWID0", sizeof(bindings) - 1); + + alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false); + assert_string_equal(alias, "MPATHa"); +@@ -1324,16 +1596,15 @@ static void gufa_nomatch_c_b(void **state) { + + static void gufa_nomatch_c_b_used(void **state) { + char *alias; +- will_return(__wrap_open_file, true); ++ const char bindings[] = ("MPATHc WWID2\n" ++ "MPATHb WWID1\n"); + +- mock_bindings_file("MPATHc WWID2\n" +- "MPATHb WWID1", +- -1); +- mock_used_alias("MPATHa", "WWID4"); ++ mock_bindings_file(bindings); + expect_condlog(3, NOMATCH_WWID_STR("WWID4")); ++ mock_used_alias("MPATHa", "WWID4"); + mock_unused_alias("MPATHd"); + +- mock_allocate_binding("MPATHd", "WWID4"); ++ mock_allocate_binding_len("MPATHd", "WWID4", sizeof(bindings) - 1); + + alias = get_user_friendly_alias("WWID4", "x", "", "MPATH", false); + assert_string_equal(alias, "MPATHd"); +@@ -1342,32 +1613,59 @@ static void gufa_nomatch_c_b_used(void **state) { + + static void gufa_nomatch_b_f_a(void **state) { + char *alias; +- will_return(__wrap_open_file, true); ++ const char bindings[] = ("MPATHb WWID1\n" ++ "MPATHf WWID6\n" ++ "MPATHa WWID0\n"); + +- mock_bindings_file("MPATHb WWID1\n" +- "MPATHf WWID6\n" +- "MPATHa WWID0\n", +- -1); ++ mock_bindings_file_unsorted(bindings); + expect_condlog(3, NOMATCH_WWID_STR("WWID7")); + mock_unused_alias("MPATHg"); + +- mock_allocate_binding("MPATHg", "WWID7"); ++ mock_allocate_binding_len("MPATHg", "WWID7", sizeof(bindings) - 1); + + alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false); + assert_string_equal(alias, "MPATHg"); + free(alias); + } + ++static void gufa_nomatch_b_aa_a(void **state) { ++ char *alias; ++ STRBUF_ON_STACK(buf); ++ ++ fill_bindings(&buf, 0, 26); ++ mock_bindings_file(get_strbuf_str(&buf)); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID28")); ++ mock_unused_alias("MPATHab"); ++ mock_allocate_binding_len("MPATHab", "WWID28", get_strbuf_len(&buf)); ++ ++ alias = get_user_friendly_alias("WWID28", "x", "", "MPATH", false); ++ assert_string_equal(alias, "MPATHab"); ++ free(alias); ++} ++ ++static void gufa_nomatch_b_f_a_sorted(void **state) { ++ char *alias; ++ const char bindings[] = ("MPATHb WWID1\n" ++ "MPATHf WWID6\n" ++ "MPATHa WWID0\n"); ++ ++ mock_bindings_file(bindings); ++ expect_condlog(3, NOMATCH_WWID_STR("WWID7")); ++ mock_unused_alias("MPATHc"); ++ ++ mock_allocate_binding_len("MPATHc", "WWID7", sizeof(bindings) - 1); ++ ++ alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false); ++ assert_string_equal(alias, "MPATHc"); ++ free(alias); ++} ++ + static void gufa_old_empty(void **state) { + char *alias; +- will_return(__wrap_open_file, true); + + /* rlookup_binding for ALIAS */ +- mock_bindings_file("", -1); ++ mock_bindings_file(""); + expect_condlog(3, NOMATCH_STR("MPATHz")); +- +- /* lookup_binding */ +- mock_bindings_file("", -1); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + + mock_allocate_binding("MPATHz", "WWID0"); +@@ -1380,11 +1678,9 @@ static void gufa_old_empty(void **state) { + + static void gufa_old_match(void **state) { + char *alias; +- will_return(__wrap_open_file, true); + + mock_bindings_file("MPATHb WWID1\n" +- "MPATHz WWID0", +- 1); ++ "MPATHz WWID0"); + expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID0")); + + alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); +@@ -1394,19 +1690,15 @@ static void gufa_old_match(void **state) { + + static void gufa_old_match_other(void **state) { + char *alias; +- static const char bindings[] = "MPATHz WWID9"; +- +- will_return(__wrap_open_file, true); ++ static const char bindings[] = "MPATHz WWID9\n"; + +- mock_bindings_file(bindings, 0); ++ mock_bindings_file(bindings); + expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9")); + expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); +- +- mock_bindings_file(bindings, -1); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + mock_unused_alias("MPATHa"); + +- mock_allocate_binding("MPATHa", "WWID0"); ++ mock_allocate_binding_len("MPATHa", "WWID0", sizeof(bindings) - 1); + + alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); + assert_string_equal(alias, "MPATHa"); +@@ -1415,21 +1707,16 @@ static void gufa_old_match_other(void **state) { + + static void gufa_old_match_other_used(void **state) { + char *alias; +- static const char bindings[] = "MPATHz WWID9"; ++ static const char bindings[] = "MPATHz WWID9\n"; + +- will_return(__wrap_open_file, true); +- +- mock_bindings_file(bindings, 0); ++ mock_bindings_file(bindings); + expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9")); + expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); +- +- mock_bindings_file(bindings, -1); +- mock_used_alias("MPATHa", "WWID0"); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); ++ mock_used_alias("MPATHa", "WWID0"); + mock_unused_alias("MPATHb"); + +- mock_allocate_binding("MPATHb", "WWID0"); +- ++ mock_allocate_binding_len("MPATHb", "WWID0", sizeof(bindings) - 1); + alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); + assert_string_equal(alias, "MPATHb"); + free(alias); +@@ -1439,15 +1726,13 @@ static void gufa_old_match_other_wwidmatch(void **state) { + char *alias; + static const char bindings[] = ("MPATHz WWID9\n" + "MPATHc WWID2"); +- will_return(__wrap_open_file, true); + +- mock_bindings_file(bindings, 0); ++ mock_bindings_file(bindings); + expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9")); + expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); +- +- mock_bindings_file(bindings, 1); + expect_condlog(3, FOUND_STR("MPATHc", "WWID2")); + mock_unused_alias("MPATHc"); ++ expect_condlog(3, EXISTING_STR("MPATHc", "WWID2")); + + alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false); + assert_string_equal(alias, "MPATHc"); +@@ -1459,13 +1744,9 @@ static void gufa_old_match_other_wwidmatch_used(void **state) { + static const char bindings[] = ("MPATHz WWID9\n" + "MPATHc WWID2"); + +- will_return(__wrap_open_file, true); +- +- mock_bindings_file(bindings, 0); ++ mock_bindings_file(bindings); + expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9")); + expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); +- +- mock_bindings_file(bindings, 1); + expect_condlog(3, FOUND_STR("MPATHc", "WWID2")); + mock_used_alias("MPATHc", "WWID2"); + +@@ -1477,12 +1758,8 @@ static void gufa_old_nomatch_wwidmatch(void **state) { + char *alias; + static const char bindings[] = "MPATHa WWID0"; + +- will_return(__wrap_open_file, true); +- +- mock_bindings_file(bindings, -1); ++ mock_bindings_file(bindings); + expect_condlog(3, NOMATCH_STR("MPATHz")); +- +- mock_bindings_file(bindings, 0); + expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); + mock_unused_alias("MPATHa"); + expect_condlog(3, EXISTING_STR("MPATHa", "WWID0")); +@@ -1495,12 +1772,9 @@ static void gufa_old_nomatch_wwidmatch(void **state) { + static void gufa_old_nomatch_wwidmatch_used(void **state) { + char *alias; + static const char bindings[] = "MPATHa WWID0"; +- will_return(__wrap_open_file, true); + +- mock_bindings_file(bindings, -1); ++ mock_bindings_file(bindings); + expect_condlog(3, NOMATCH_STR("MPATHz")); +- +- mock_bindings_file(bindings, 0); + expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); + mock_used_alias("MPATHa", "WWID0"); + +@@ -1510,17 +1784,13 @@ static void gufa_old_nomatch_wwidmatch_used(void **state) { + + static void gufa_old_nomatch_nowwidmatch(void **state) { + char *alias; +- static const char bindings[] = "MPATHb WWID1"; +- +- will_return(__wrap_open_file, true); ++ static const char bindings[] = "MPATHb WWID1\n"; + +- mock_bindings_file(bindings, -1); ++ mock_bindings_file(bindings); + expect_condlog(3, NOMATCH_STR("MPATHz")); +- +- mock_bindings_file(bindings, -1); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + +- mock_allocate_binding("MPATHz", "WWID0"); ++ mock_allocate_binding_len("MPATHz", "WWID0", sizeof(bindings) - 1); + expect_condlog(2, ALLOC_STR("MPATHz", "WWID0")); + + alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); +@@ -1531,26 +1801,28 @@ static void gufa_old_nomatch_nowwidmatch(void **state) { + static int test_get_user_friendly_alias() + { + const struct CMUnitTest tests[] = { +- cmocka_unit_test(gufa_empty_new_rw), +- cmocka_unit_test(gufa_empty_new_ro_1), +- cmocka_unit_test(gufa_empty_new_ro_2), +- cmocka_unit_test(gufa_match_a_unused), +- cmocka_unit_test(gufa_match_a_self), +- cmocka_unit_test(gufa_match_a_used), +- cmocka_unit_test(gufa_nomatch_a_c), +- cmocka_unit_test(gufa_nomatch_c_a), +- cmocka_unit_test(gufa_nomatch_c_b), +- cmocka_unit_test(gufa_nomatch_c_b_used), +- cmocka_unit_test(gufa_nomatch_b_f_a), +- cmocka_unit_test(gufa_old_empty), +- cmocka_unit_test(gufa_old_match), +- cmocka_unit_test(gufa_old_match_other), +- cmocka_unit_test(gufa_old_match_other_used), +- cmocka_unit_test(gufa_old_match_other_wwidmatch), +- cmocka_unit_test(gufa_old_match_other_wwidmatch_used), +- cmocka_unit_test(gufa_old_nomatch_wwidmatch), +- cmocka_unit_test(gufa_old_nomatch_wwidmatch_used), +- cmocka_unit_test(gufa_old_nomatch_nowwidmatch), ++ cmocka_unit_test_teardown(gufa_empty_new_rw, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_empty_new_ro_1, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_empty_new_ro_2, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_match_a_unused, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_match_a_self, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_match_a_used, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_nomatch_a_c, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_nomatch_c_a, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_nomatch_c_b, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_nomatch_c_b_used, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_nomatch_b_f_a, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_nomatch_b_aa_a, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_nomatch_b_f_a_sorted, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_old_empty, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_old_match, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_old_match_other, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_old_match_other_used, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_old_match_other_wwidmatch, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_old_match_other_wwidmatch_used, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_old_nomatch_wwidmatch, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_old_nomatch_wwidmatch_used, teardown_bindings), ++ cmocka_unit_test_teardown(gufa_old_nomatch_nowwidmatch, teardown_bindings), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +@@ -1566,7 +1838,6 @@ int main(void) + ret += test_lookup_binding(); + ret += test_rlookup_binding(); + ret += test_allocate_binding(); +- ret += test_allocate_binding(); + ret += test_get_user_friendly_alias(); + + return ret; diff --git a/0020-libmultipath-dm_get_uuid-return-emtpy-UUID-for-non-e.patch b/0020-libmultipath-dm_get_uuid-return-emtpy-UUID-for-non-e.patch new file mode 100644 index 0000000..c105b01 --- /dev/null +++ b/0020-libmultipath-dm_get_uuid-return-emtpy-UUID-for-non-e.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 25 Aug 2023 20:35:19 +0200 +Subject: [PATCH] libmultipath: dm_get_uuid(): return emtpy UUID for + non-existing maps + +libdevmapper will most probably not return a UUID for non-existing +maps anyway. But it's cheap to double-check here. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/devmapper.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c +index 248c3734..9be82f4e 100644 +--- a/libmultipath/devmapper.c ++++ b/libmultipath/devmapper.c +@@ -706,12 +706,16 @@ dm_get_prefixed_uuid(const char *name, char *uuid, int uuid_len) + { + struct dm_task *dmt; + const char *uuidtmp; ++ struct dm_info info; + int r = 1; + + dmt = libmp_dm_task_create(DM_DEVICE_INFO); + if (!dmt) + return 1; + ++ if (uuid_len > 0) ++ uuid[0] = '\0'; ++ + if (!dm_task_set_name (dmt, name)) + goto uuidout; + +@@ -720,11 +724,13 @@ dm_get_prefixed_uuid(const char *name, char *uuid, int uuid_len) + goto uuidout; + } + ++ if (!dm_task_get_info(dmt, &info) || ++ !info.exists) ++ goto uuidout; ++ + uuidtmp = dm_task_get_uuid(dmt); + if (uuidtmp) + strlcpy(uuid, uuidtmp, uuid_len); +- else +- uuid[0] = '\0'; + + r = 0; + uuidout: diff --git a/0021-libmultipath-adapt-to-new-semantics-of-dm_get_uuid.patch b/0021-libmultipath-adapt-to-new-semantics-of-dm_get_uuid.patch new file mode 100644 index 0000000..4d15554 --- /dev/null +++ b/0021-libmultipath-adapt-to-new-semantics-of-dm_get_uuid.patch @@ -0,0 +1,158 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 28 Aug 2023 12:26:37 +0200 +Subject: [PATCH] libmultipath: adapt to new semantics of dm_get_uuid() + +dm_get_uuid() will return 1 for non-existing maps. Thus we don't need +to call dm_map_present() any more in alias_already_taken(). This changes +our semantics: previously we'd avoid using an alias for which dm_get_uuid() +had failed. Now we treat failure in dm_get_uuid() as indication that the +map doesn't exist. This is not dangerous because dm_task_get_uuid() cannot +fail, and thus the modified dm_get_uuid() will fail if and only if +dm_map_present() would return false. + +This makes the "failed alias" test mostly obsolete, as "failed" is now +treated as "unused". + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/alias.c | 25 +++++++++++++------------ + tests/alias.c | 32 +++++++------------------------- + 2 files changed, 20 insertions(+), 37 deletions(-) + +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index d6563749..58436ec0 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -295,18 +295,19 @@ scan_devname(const char *alias, const char *prefix) + static bool alias_already_taken(const char *alias, const char *map_wwid) + { + +- if (dm_map_present(alias)) { +- char wwid[WWID_SIZE]; +- +- /* If both the name and the wwid match, then it's fine.*/ +- if (dm_get_uuid(alias, wwid, sizeof(wwid)) == 0 && +- strncmp(map_wwid, wwid, sizeof(wwid)) == 0) +- return false; +- condlog(3, "%s: alias '%s' already taken, reselecting alias", +- map_wwid, alias); +- return true; +- } +- return false; ++ char wwid[WWID_SIZE]; ++ ++ /* If the map doesn't exist, it's fine */ ++ if (dm_get_uuid(alias, wwid, sizeof(wwid)) != 0) ++ return false; ++ ++ /* If both the name and the wwid match, it's fine.*/ ++ if (strncmp(map_wwid, wwid, sizeof(wwid)) == 0) ++ return false; ++ ++ condlog(3, "%s: alias '%s' already taken, reselecting alias", ++ map_wwid, alias); ++ return true; + } + + static bool id_already_taken(int id, const char *prefix, const char *map_wwid) +diff --git a/tests/alias.c b/tests/alias.c +index 50a21ecf..d1cc487b 100644 +--- a/tests/alias.c ++++ b/tests/alias.c +@@ -73,12 +73,6 @@ int __wrap_mkstemp(char *template) + return 10; + } + +-int __wrap_dm_map_present(const char * str) +-{ +- check_expected(str); +- return mock_type(int); +-} +- + int __wrap_dm_get_uuid(const char *name, char *uuid, int uuid_len) + { + int ret; +@@ -398,14 +392,13 @@ static int test_scan_devname(void) + + static void mock_unused_alias(const char *alias) + { +- expect_string(__wrap_dm_map_present, str, alias); +- will_return(__wrap_dm_map_present, 0); ++ expect_string(__wrap_dm_get_uuid, name, alias); ++ expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); ++ will_return(__wrap_dm_get_uuid, 1); + } + + static void mock_self_alias(const char *alias, const char *wwid) + { +- expect_string(__wrap_dm_map_present, str, alias); +- will_return(__wrap_dm_map_present, 1); + expect_string(__wrap_dm_get_uuid, name, alias); + expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); + will_return(__wrap_dm_get_uuid, 0); +@@ -432,18 +425,13 @@ static void mock_self_alias(const char *alias, const char *wwid) + + #define mock_failed_alias(alias, wwid) \ + do { \ +- expect_string(__wrap_dm_map_present, str, alias); \ +- will_return(__wrap_dm_map_present, 1); \ + expect_string(__wrap_dm_get_uuid, name, alias); \ + expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); \ + will_return(__wrap_dm_get_uuid, 1); \ +- expect_condlog(3, USED_STR(alias, wwid)); \ + } while (0) + + #define mock_used_alias(alias, wwid) \ + do { \ +- expect_string(__wrap_dm_map_present, str, alias); \ +- will_return(__wrap_dm_map_present, 1); \ + expect_string(__wrap_dm_get_uuid, name, alias); \ + expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); \ + will_return(__wrap_dm_get_uuid, 0); \ +@@ -566,9 +554,8 @@ static void lb_empty_failed(void **state) + mock_bindings_file(""); + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + mock_failed_alias("MPATHa", "WWID0"); +- mock_unused_alias("MPATHb"); + rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); +- assert_int_equal(rc, 2); ++ assert_int_equal(rc, 1); + assert_ptr_equal(alias, NULL); + free(alias); + } +@@ -666,9 +653,8 @@ static void lb_nomatch_a_3_used_failed_self(void **state) + mock_used_alias("MPATHc", "WWID1"); + mock_used_alias("MPATHd", "WWID1"); + mock_failed_alias("MPATHe", "WWID1"); +- mock_self_alias("MPATHf", "WWID1"); + rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); +- assert_int_equal(rc, 6); ++ assert_int_equal(rc, 5); + assert_ptr_equal(alias, NULL); + } + +@@ -940,7 +926,7 @@ static void lb_nomatch_b_a_aa(void **state) + + static void lb_nomatch_b_a_aa_zz(void **state) + { +- int rc, i; ++ int rc; + char *alias; + STRBUF_ON_STACK(buf); + +@@ -949,11 +935,7 @@ static void lb_nomatch_b_a_aa_zz(void **state) + * lookup_binding finds MPATHaaa as next free entry, because MPATHaa is + * found before MPATHb, and MPATHzz was in the bindings, too. + */ +- for (i = 0; i <= 26; i++) { +- print_strbuf(&buf, "MPATH"); +- format_devname(&buf, i + 1); +- print_strbuf(&buf, " WWID%d\n", i); +- } ++ fill_bindings(&buf, 0, 26); + print_strbuf(&buf, "MPATHzz WWID676\n"); + mock_bindings_file(get_strbuf_str(&buf)); + expect_condlog(3, NOMATCH_WWID_STR("WWID703")); diff --git a/0022-libmultipath-sort-aliases-by-length-and-strcmp.patch b/0022-libmultipath-sort-aliases-by-length-and-strcmp.patch new file mode 100644 index 0000000..1504bec --- /dev/null +++ b/0022-libmultipath-sort-aliases-by-length-and-strcmp.patch @@ -0,0 +1,98 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 8 Sep 2023 15:19:54 +0200 +Subject: [PATCH] libmultipath: sort aliases by length and strcmp + +The current sort order of aliases is alphabetical, which is does not match +the actual order of aliases, where "mpathaa" > "mpathz". Change the ordering as +follows: first sort by string length, then alphabetically. This will make +sure that for aliases with the same prefix, alias order is correct ("mpathaaa" +will be sorted after "mpathzz", etc). Even for mixed prefixes, the alias +order will be correct for every individual prefix, even though aliases with +different prefixes may alternate in the file. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/alias.c | 45 +++++++++++++++++++++++++++++++++----------- + 1 file changed, 34 insertions(+), 11 deletions(-) + +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index 58436ec0..af6565b1 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -117,6 +117,35 @@ static const struct binding *get_binding_for_wwid(const Bindings *bindings, + return NULL; + } + ++/* ++ * Sort order for aliases. ++ * ++ * The "numeric" ordering of aliases for a given prefix P is ++ * Pa, ..., Pz, Paa, ..., Paz, Pba, ... , Pzz, Paaa, ..., Pzzz, Paaaa, ... ++ * We use the fact that for equal prefix, longer strings are always ++ * higher than shorter ones. Strings of equal length are sorted alphabetically. ++ * This is achieved by sorting be length first, then using strcmp(). ++ * If multiple prefixes are in use, the aliases with a given prefix will ++ * not necessarily be in a contiguous range of the vector, but they will ++ * be ordered such that for a given prefix, numercally higher aliases will ++ * always be sorted after lower ones. ++ */ ++static int alias_compar(const void *p1, const void *p2) ++{ ++ const char *alias1 = *((char * const *)p1); ++ const char *alias2 = *((char * const *)p2); ++ ++ if (alias1 && alias2) { ++ ssize_t ldif = strlen(alias1) - strlen(alias2); ++ ++ if (ldif) ++ return ldif; ++ return strcmp(alias1, alias2); ++ } else ++ /* Move NULL alias to the end */ ++ return alias1 ? -1 : alias2 ? 1 : 0; ++} ++ + static int add_binding(Bindings *bindings, const char *alias, const char *wwid) + { + struct binding *bdg; +@@ -128,7 +157,7 @@ static int add_binding(Bindings *bindings, const char *alias, const char *wwid) + * sorted already. + */ + vector_foreach_slot_backwards(bindings, bdg, i) { +- if ((cmp = strcmp(bdg->alias, alias)) <= 0) ++ if ((cmp = alias_compar(&bdg->alias, &alias)) <= 0) + break; + } + +@@ -657,16 +686,10 @@ static int _check_bindings_file(const struct config *conf, FILE *file, + return rc; + } + +-static int alias_compar(const void *p1, const void *p2) ++static int mp_alias_compar(const void *p1, const void *p2) + { +- const char *alias1 = (*(struct mpentry * const *)p1)->alias; +- const char *alias2 = (*(struct mpentry * const *)p2)->alias; +- +- if (alias1 && alias2) +- return strcmp(alias1, alias2); +- else +- /* Move NULL alias to the end */ +- return alias1 ? -1 : alias2 ? 1 : 0; ++ return alias_compar(&((*(struct mpentry * const *)p1)->alias), ++ &((*(struct mpentry * const *)p2)->alias)); + } + + /* +@@ -700,7 +723,7 @@ int check_alias_settings(const struct config *conf) + pthread_cleanup_push_cast(free_bindings, &bindings); + pthread_cleanup_push(cleanup_vector_free, mptable); + +- vector_sort(mptable, alias_compar); ++ vector_sort(mptable, mp_alias_compar); + vector_foreach_slot(mptable, mpe, i) { + if (!mpe->alias) + /* diff --git a/0023-multipath-tools-tests-fix-alias-test-after-sort-orde.patch b/0023-multipath-tools-tests-fix-alias-test-after-sort-orde.patch new file mode 100644 index 0000000..dd0f29d --- /dev/null +++ b/0023-multipath-tools-tests-fix-alias-test-after-sort-orde.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 8 Sep 2023 15:46:02 +0200 +Subject: [PATCH] multipath-tools tests: fix alias test after sort order change + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + tests/alias.c | 30 ++++++++++++------------------ + 1 file changed, 12 insertions(+), 18 deletions(-) + +diff --git a/tests/alias.c b/tests/alias.c +index d1cc487b..8ed95d7a 100644 +--- a/tests/alias.c ++++ b/tests/alias.c +@@ -932,16 +932,15 @@ static void lb_nomatch_b_a_aa_zz(void **state) + + /* + * add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...) +- * lookup_binding finds MPATHaaa as next free entry, because MPATHaa is +- * found before MPATHb, and MPATHzz was in the bindings, too. ++ * lookup_binding finds MPATHab as next free entry. + */ + fill_bindings(&buf, 0, 26); + print_strbuf(&buf, "MPATHzz WWID676\n"); + mock_bindings_file(get_strbuf_str(&buf)); + expect_condlog(3, NOMATCH_WWID_STR("WWID703")); +- mock_unused_alias("MPATHaaa"); ++ mock_unused_alias("MPATHab"); + rc = lookup_binding(NULL, "WWID703", &alias, "MPATH", 1); +- assert_int_equal(rc, 703); ++ assert_int_equal(rc, 28); + assert_ptr_equal(alias, NULL); + } + +@@ -998,13 +997,8 @@ static void lb_nomatch_b_a_3_used(void **state) + + #ifdef MPATH_ID_INT_MAX + /* +- * The bindings will be sorted by alias, alphabetically, which is not +- * the same as the "numeric" sort order for user-friendly aliases. +- * get_free_id() selects the highest used ID + 1 if an unsorted entry +- * is encountered in the bindings table and it's id is equal to the +- * next "expected" id. This happens if all IDs from "a" to "aa" are +- * in the table. If the INT_MAX entry is in the table, too, it will +- * overflow. ++ * The bindings will be sorted by alias. Therefore we have no chance to ++ * simulate a "full" table. + */ + static void lb_nomatch_int_max(void **state) + { +@@ -1016,9 +1010,9 @@ static void lb_nomatch_int_max(void **state) + print_strbuf(&buf, "MPATH%s WWIDMAX\n", MPATH_ID_INT_MAX); + mock_bindings_file(get_strbuf_str(&buf)); + expect_condlog(3, NOMATCH_WWID_STR("WWIDNOMORE")); +- expect_condlog(0, NOMORE_STR); ++ mock_unused_alias("MPATHab"); + rc = lookup_binding(NULL, "WWIDNOMORE", &alias, "MPATH", 1); +- assert_int_equal(rc, -1); ++ assert_int_equal(rc, 28); + assert_ptr_equal(alias, NULL); + } + +@@ -1049,9 +1043,9 @@ static void lb_nomatch_int_max_m1(void **state) + print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1); + mock_bindings_file(get_strbuf_str(&buf)); + expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); +- mock_unused_alias("MPATH" MPATH_ID_INT_MAX); ++ mock_unused_alias("MPATHab"); + rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); +- assert_int_equal(rc, INT_MAX); ++ assert_int_equal(rc, 28); + assert_ptr_equal(alias, NULL); + } + +@@ -1065,10 +1059,10 @@ static void lb_nomatch_int_max_m1_used(void **state) + print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1); + mock_bindings_file(get_strbuf_str(&buf)); + expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); +- mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWIDMAX"); +- expect_condlog(0, NOMORE_STR); ++ mock_used_alias("MPATHab", "WWIDMAX"); ++ mock_unused_alias("MPATHac"); + rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); +- assert_int_equal(rc, -1); ++ assert_int_equal(rc, 29); + assert_ptr_equal(alias, NULL); + } + diff --git a/0024-libmultipath-simplify-get_free_id-assuming-total-ord.patch b/0024-libmultipath-simplify-get_free_id-assuming-total-ord.patch new file mode 100644 index 0000000..b16b3da --- /dev/null +++ b/0024-libmultipath-simplify-get_free_id-assuming-total-ord.patch @@ -0,0 +1,122 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 8 Sep 2023 19:50:51 +0200 +Subject: [PATCH] libmultipath: simplify get_free_id() assuming total ordering + +If we can assume that the bindings array is totally ordered for every +prefix, which the previous patch guarantees, the search for a free ID can be +simplified. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/alias.c | 85 ++++++++++---------------------------------- + 1 file changed, 18 insertions(+), 67 deletions(-) + +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index af6565b1..66e34e31 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -356,83 +356,34 @@ int get_free_id(const Bindings *bindings, const char *prefix, const char *map_ww + { + const struct binding *bdg; + int i, id = 1; +- int biggest_id = 1; +- int smallest_bigger_id = INT_MAX; + + vector_foreach_slot(bindings, bdg, i) { + int curr_id = scan_devname(bdg->alias, prefix); + +- /* +- * Find an unused index - explanation of the algorithm +- * +- * ID: 1 = mpatha, 2 = mpathb, ... +- * +- * We assume the bindings are unsorted. The only constraint +- * is that no ID occurs more than once. IDs that occur in the +- * bindings are called "used". +- * +- * We call the list 1,2,3,..., exactly in this order, the list +- * of "expected" IDs. The variable "id" always holds the next +- * "expected" ID, IOW the last "expected" ID encountered plus 1. +- * Thus all IDs below "id" are known to be used. However, at the +- * end of the loop, the value of "id" isn't necessarily unused. +- * +- * "smallest_bigger_id" is the smallest used ID that was +- * encountered while it was larger than the next "expected" ID +- * at that iteration. Let X be some used ID. If all IDs below X +- * are used and encountered in the right sequence before X, "id" +- * will be > X when the loop ends. Otherwise, X was encountered +- * "out of order", the condition (X > id) holds when X is +- * encountered, and "smallest_bigger_id" will be set to X; i.e. +- * it will be less or equal than X when the loop ends. +- * +- * At the end of the loop, (id < smallest_bigger_id) means that +- * the value of "id" had been encountered neither in order nor +- * out of order, and is thus unused. (id >= smallest_bigger_id) +- * means that "id"'s value is in use. In this case, we play safe +- * and use "biggest_id + 1" as the next value to try. +- * +- * biggest_id is always > smallest_bigger_id, except in the +- * "perfectly ordered" case. +- */ +- if (curr_id == id) { +- if (id < INT_MAX) +- id++; +- else { +- id = -1; +- break; +- } ++ if (curr_id == -1) ++ continue; ++ if (id > curr_id) { ++ condlog(0, "%s: ERROR: bindings are not sorted", __func__); ++ return -1; + } +- if (curr_id > biggest_id) +- biggest_id = curr_id; +- +- if (curr_id > id && curr_id < smallest_bigger_id) +- smallest_bigger_id = curr_id; ++ while (id < curr_id && id_already_taken(id, prefix, map_wwid)) ++ id++; ++ if (id < curr_id) ++ return id; ++ id++; ++ if (id <= 0) ++ break; + } + +- if (id >= smallest_bigger_id) +- id = biggest_id < INT_MAX ? biggest_id + 1 : -1; +- +- if (id > 0) { +- while(id_already_taken(id, prefix, map_wwid)) { +- if (id == INT_MAX) { +- id = -1; +- break; +- } +- id++; +- if (id == smallest_bigger_id) { +- if (biggest_id == INT_MAX) { +- id = -1; +- break; +- } +- if (biggest_id >= smallest_bigger_id) +- id = biggest_id + 1; +- } +- } ++ for (; id > 0; id++) { ++ if (!id_already_taken(id, prefix, map_wwid)) ++ break; + } + +- if (id < 0) ++ if (id <= 0) { ++ id = -1; + condlog(0, "no more available user_friendly_names"); ++ } + return id; + } + diff --git a/0025-multipath-tools-tests-adapt-alias-tests-for-total-or.patch b/0025-multipath-tools-tests-adapt-alias-tests-for-total-or.patch new file mode 100644 index 0000000..b1d6b15 --- /dev/null +++ b/0025-multipath-tools-tests-adapt-alias-tests-for-total-or.patch @@ -0,0 +1,203 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 8 Sep 2023 19:58:03 +0200 +Subject: [PATCH] multipath-tools tests: adapt alias tests for total ordering + +The "unsorted" test fail now, and are removed. The algorithm is now +better at finding "gaps". + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + tests/alias.c | 88 ++++++++------------------------------------------- + 1 file changed, 14 insertions(+), 74 deletions(-) + +diff --git a/tests/alias.c b/tests/alias.c +index 8ed95d7a..dff5f93b 100644 +--- a/tests/alias.c ++++ b/tests/alias.c +@@ -439,27 +439,7 @@ static void mock_self_alias(const char *alias, const char *wwid) + expect_condlog(3, USED_STR(alias, wwid)); \ + } while(0) + +-static int add_binding_unsorted(Bindings *bindings, +- const char *alias, const char *wwid) +-{ +- struct binding *bdg = calloc(1, sizeof(*bdg)); +- +- if (!bdg) +- return -1; +- bdg->wwid = strdup(wwid); +- bdg->alias = strdup(alias); +- if (!bdg->wwid || !bdg->alias || !vector_alloc_slot(bindings)) { +- free(bdg->alias); +- free(bdg->wwid); +- free(bdg); +- return BINDING_ERROR; +- } +- vector_set_slot(bindings, bdg); +- return BINDING_ADDED; +-} +- +-static void __mock_bindings_file(const char *content, +- int (*add)(Bindings *, const char *, const char *)) ++static void __mock_bindings_file(const char *content) + { + char *cnt __attribute__((cleanup(cleanup_charp))) = NULL; + char *token, *savep = NULL; +@@ -478,17 +458,13 @@ static void __mock_bindings_file(const char *content, + == READ_BINDING_SKIP) + continue; + +- rc = add(&global_bindings, alias, wwid); ++ rc = add_binding(&global_bindings, alias, wwid); + assert_int_equal(rc, BINDING_ADDED); + } + } + + static void mock_bindings_file(const char *content) { +- return __mock_bindings_file(content, add_binding); +-} +- +-static void mock_bindings_file_unsorted(const char *content) { +- return __mock_bindings_file(content, add_binding_unsorted); ++ return __mock_bindings_file(content); + } + + static int teardown_bindings(void **state) +@@ -861,10 +837,6 @@ static void lb_nomatch_b_z_a(void **state) + int rc; + char *alias; + +- /* +- * add_bindings() sorts alphabetically. Therefore get_free_id() +- * finds MPATHc as a free entry. +- */ + mock_bindings_file("MPATHb WWID1\n" + "MPATHz WWID26\n" + "MPATHa WWID0\n"); +@@ -880,10 +852,6 @@ static void lb_nomatch_b_aa_a(void **state) + int rc; + char *alias; + +- /* +- * add_bindings() sorts alphabetically. ("a", "aa", b"). +- * The get_free_id() algorithm finds the "hole" after "b". +- */ + mock_bindings_file("MPATHb WWID1\n" + "MPATHz WWID26\n" + "MPATHa WWID0\n"); +@@ -911,10 +879,6 @@ static void lb_nomatch_b_a_aa(void **state) + char *alias; + STRBUF_ON_STACK(buf); + +- /* +- * add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...) +- * lookup_binding finds MPATHac as next free entry. +- */ + fill_bindings(&buf, 0, 26); + mock_bindings_file(get_strbuf_str(&buf)); + expect_condlog(3, NOMATCH_WWID_STR("WWID28")); +@@ -930,10 +894,6 @@ static void lb_nomatch_b_a_aa_zz(void **state) + char *alias; + STRBUF_ON_STACK(buf); + +- /* +- * add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...) +- * lookup_binding finds MPATHab as next free entry. +- */ + fill_bindings(&buf, 0, 26); + print_strbuf(&buf, "MPATHzz WWID676\n"); + mock_bindings_file(get_strbuf_str(&buf)); +@@ -944,25 +904,6 @@ static void lb_nomatch_b_a_aa_zz(void **state) + assert_ptr_equal(alias, NULL); + } + +-static void lb_nomatch_b_z_a_unsorted(void **state) +-{ +- int rc; +- char *alias; +- +- /* +- * With unsorted bindings (shouldn't happen normally), get_free_id() +- * plays safe and returns MPATHaa as first free entry. +- */ +- mock_bindings_file_unsorted("MPATHb WWID1\n" +- "MPATHz WWID26\n" +- "MPATHa WWID0\n"); +- expect_condlog(3, NOMATCH_WWID_STR("WWID2")); +- mock_unused_alias("MPATHaa"); +- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); +- assert_int_equal(rc, 27); +- assert_ptr_equal(alias, NULL); +-} +- + static void lb_nomatch_b_a(void **state) + { + int rc; +@@ -1027,9 +968,9 @@ static void lb_nomatch_int_max_used(void **state) + mock_bindings_file(get_strbuf_str(&buf)); + expect_condlog(3, NOMATCH_WWID_STR("WWIDNOMORE")); + mock_used_alias("MPATHa", "WWIDNOMORE"); +- expect_condlog(0, NOMORE_STR); ++ mock_unused_alias("MPATHab"); + rc = lookup_binding(NULL, "WWIDNOMORE", &alias, "MPATH", 1); +- assert_int_equal(rc, -1); ++ assert_int_equal(rc, 28); + assert_ptr_equal(alias, NULL); + } + +@@ -1077,9 +1018,9 @@ static void lb_nomatch_int_max_m1_1_used(void **state) + mock_bindings_file(get_strbuf_str(&buf)); + expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); + mock_used_alias("MPATHa", "WWIDMAX"); +- mock_unused_alias("MPATH" MPATH_ID_INT_MAX); ++ mock_unused_alias("MPATHab"); + rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); +- assert_int_equal(rc, INT_MAX); ++ assert_int_equal(rc, 28); + assert_ptr_equal(alias, NULL); + } + +@@ -1095,10 +1036,10 @@ static void lb_nomatch_int_max_m1_2_used(void **state) + + expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); + mock_used_alias("MPATHa", "WWIDMAX"); +- mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWIDMAX"); +- expect_condlog(0, NOMORE_STR); ++ mock_used_alias("MPATHab", "WWIDMAX"); ++ mock_unused_alias("MPATHac"); + rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); +- assert_int_equal(rc, -1); ++ assert_int_equal(rc, 29); + assert_ptr_equal(alias, NULL); + } + #endif +@@ -1133,7 +1074,6 @@ static int test_lookup_binding(void) + cmocka_unit_test_teardown(lb_nomatch_b_aa_a, teardown_bindings), + cmocka_unit_test_teardown(lb_nomatch_b_a_aa, teardown_bindings), + cmocka_unit_test_teardown(lb_nomatch_b_a_aa_zz, teardown_bindings), +- cmocka_unit_test_teardown(lb_nomatch_b_z_a_unsorted, teardown_bindings), + cmocka_unit_test_teardown(lb_nomatch_b_a, teardown_bindings), + cmocka_unit_test_teardown(lb_nomatch_b_a_3_used, teardown_bindings), + #ifdef MPATH_ID_INT_MAX +@@ -1593,14 +1533,14 @@ static void gufa_nomatch_b_f_a(void **state) { + "MPATHf WWID6\n" + "MPATHa WWID0\n"); + +- mock_bindings_file_unsorted(bindings); ++ mock_bindings_file(bindings); + expect_condlog(3, NOMATCH_WWID_STR("WWID7")); +- mock_unused_alias("MPATHg"); ++ mock_unused_alias("MPATHc"); + +- mock_allocate_binding_len("MPATHg", "WWID7", sizeof(bindings) - 1); ++ mock_allocate_binding_len("MPATHc", "WWID7", sizeof(bindings) - 1); + + alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false); +- assert_string_equal(alias, "MPATHg"); ++ assert_string_equal(alias, "MPATHc"); + free(alias); + } + diff --git a/0026-multipath-tools-tests-add-test-for-ordering-of-bindi.patch b/0026-multipath-tools-tests-add-test-for-ordering-of-bindi.patch new file mode 100644 index 0000000..5317ef9 --- /dev/null +++ b/0026-multipath-tools-tests-add-test-for-ordering-of-bindi.patch @@ -0,0 +1,275 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 8 Sep 2023 21:39:44 +0200 +Subject: [PATCH] multipath-tools tests: add test for ordering of bindings + +As the assignment of free aliases now relies on the bindings being +properly sorted, add some unit tests to make sure the sorting algorithm +works. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + tests/alias.c | 212 +++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 209 insertions(+), 3 deletions(-) + +diff --git a/tests/alias.c b/tests/alias.c +index dff5f93b..7f3ff38a 100644 +--- a/tests/alias.c ++++ b/tests/alias.c +@@ -13,6 +13,9 @@ + #include "globals.c" + #include "../libmultipath/alias.c" + ++/* For verbose printing of all aliases in the ordering tests */ ++#define ALIAS_DEBUG 0 ++ + #if INT_MAX == 0x7fffffff + /* user_friendly_name for map #INT_MAX */ + #define MPATH_ID_INT_MAX "fxshrxw" +@@ -439,11 +442,12 @@ static void mock_self_alias(const char *alias, const char *wwid) + expect_condlog(3, USED_STR(alias, wwid)); \ + } while(0) + +-static void __mock_bindings_file(const char *content) ++static void __mock_bindings_file(const char *content, bool conflict_ok) + { + char *cnt __attribute__((cleanup(cleanup_charp))) = NULL; + char *token, *savep = NULL; + int i; ++ uintmax_t values[] = { BINDING_ADDED, BINDING_CONFLICT }; + + cnt = strdup(content); + assert_ptr_not_equal(cnt, NULL); +@@ -459,12 +463,12 @@ static void __mock_bindings_file(const char *content) + continue; + + rc = add_binding(&global_bindings, alias, wwid); +- assert_int_equal(rc, BINDING_ADDED); ++ assert_in_set(rc, values, conflict_ok ? 2 : 1); + } + } + + static void mock_bindings_file(const char *content) { +- return __mock_bindings_file(content); ++ return __mock_bindings_file(content, false); + } + + static int teardown_bindings(void **state) +@@ -1744,6 +1748,207 @@ static int test_get_user_friendly_alias() + return cmocka_run_group_tests(tests, NULL, NULL); + } + ++/* Numbers 1-1000, randomly shuffled */ ++static const int random_numbers[1000] = { ++ 694, 977, 224, 178, 841, 818, 914, 549, 831, 942, 263, 834, 919, 800, ++ 111, 517, 719, 297, 988, 98, 332, 516, 754, 772, 495, 488, 331, 529, ++ 142, 747, 848, 618, 375, 624, 74, 753, 782, 944, 623, 468, 862, 997, ++ 417, 258, 298, 774, 673, 904, 883, 766, 867, 400, 11, 950, 14, 784, ++ 655, 155, 396, 9, 743, 93, 651, 245, 968, 306, 785, 581, 880, 486, ++ 168, 631, 203, 4, 663, 294, 702, 762, 619, 684, 48, 181, 21, 443, 643, ++ 863, 1000, 327, 26, 126, 382, 765, 586, 76, 49, 925, 319, 865, 797, ++ 876, 693, 334, 433, 243, 419, 901, 854, 326, 985, 347, 874, 527, 282, ++ 290, 380, 167, 95, 3, 257, 936, 60, 426, 227, 345, 577, 492, 467, 580, ++ 967, 422, 823, 718, 610, 64, 700, 412, 163, 288, 506, 828, 432, 51, ++ 356, 348, 539, 478, 17, 945, 602, 123, 450, 660, 429, 113, 310, 358, ++ 512, 758, 508, 19, 542, 304, 286, 446, 918, 723, 333, 603, 731, 978, ++ 230, 697, 109, 872, 175, 853, 947, 965, 121, 222, 101, 811, 117, 601, ++ 191, 752, 384, 415, 938, 278, 915, 715, 240, 552, 912, 838, 150, 840, ++ 627, 29, 636, 464, 861, 481, 992, 249, 934, 82, 368, 724, 807, 593, ++ 157, 147, 199, 637, 41, 62, 902, 505, 621, 342, 174, 260, 729, 961, ++ 219, 311, 629, 789, 81, 739, 860, 712, 223, 165, 741, 981, 485, 363, ++ 346, 709, 125, 369, 279, 634, 399, 162, 193, 769, 149, 314, 868, 612, ++ 524, 675, 341, 343, 476, 606, 388, 613, 850, 264, 903, 451, 908, 779, ++ 453, 148, 497, 46, 132, 43, 885, 955, 269, 395, 72, 128, 767, 989, ++ 929, 423, 742, 55, 13, 79, 924, 182, 295, 563, 668, 169, 974, 154, ++ 970, 54, 674, 52, 437, 570, 550, 531, 554, 793, 678, 218, 367, 105, ++ 197, 315, 958, 892, 86, 47, 284, 37, 561, 522, 198, 689, 817, 573, ++ 877, 201, 803, 501, 881, 546, 530, 523, 780, 579, 953, 135, 23, 620, ++ 84, 698, 303, 656, 357, 323, 494, 58, 131, 913, 995, 120, 70, 1, 195, ++ 365, 210, 25, 898, 173, 307, 239, 77, 418, 952, 963, 92, 455, 425, 12, ++ 536, 161, 328, 933, 401, 251, 735, 725, 362, 322, 557, 681, 302, 53, ++ 786, 801, 391, 946, 748, 133, 717, 851, 7, 372, 993, 387, 906, 373, ++ 667, 33, 670, 389, 209, 611, 896, 652, 69, 999, 344, 845, 633, 36, ++ 487, 192, 180, 45, 640, 427, 707, 805, 188, 152, 905, 217, 30, 252, ++ 386, 665, 299, 541, 410, 787, 5, 857, 751, 392, 44, 595, 146, 745, ++ 641, 957, 866, 773, 806, 815, 659, 102, 704, 430, 106, 296, 129, 847, ++ 130, 990, 669, 236, 225, 680, 159, 213, 438, 189, 447, 600, 232, 594, ++ 32, 56, 390, 647, 855, 428, 330, 714, 738, 706, 666, 461, 469, 482, ++ 558, 814, 559, 177, 575, 538, 309, 383, 261, 156, 420, 761, 630, 893, ++ 10, 116, 940, 844, 71, 377, 662, 312, 520, 244, 143, 759, 119, 186, ++ 592, 909, 864, 376, 768, 254, 265, 394, 511, 760, 574, 6, 436, 514, ++ 59, 226, 644, 956, 578, 825, 548, 145, 736, 597, 378, 821, 987, 897, ++ 354, 144, 722, 895, 589, 503, 826, 498, 543, 617, 763, 231, 808, 528, ++ 89, 479, 607, 737, 170, 404, 371, 65, 103, 340, 283, 141, 313, 858, ++ 289, 124, 971, 687, 954, 732, 39, 926, 176, 100, 267, 519, 890, 535, ++ 276, 448, 27, 457, 899, 385, 184, 275, 770, 544, 614, 449, 160, 658, ++ 259, 973, 108, 604, 24, 207, 562, 757, 744, 324, 444, 962, 591, 480, ++ 398, 409, 998, 253, 325, 445, 979, 8, 35, 118, 73, 683, 208, 85, 190, ++ 791, 408, 871, 657, 179, 18, 556, 496, 475, 20, 894, 484, 775, 889, ++ 463, 241, 730, 57, 907, 551, 859, 943, 185, 416, 870, 590, 435, 471, ++ 932, 268, 381, 626, 502, 565, 273, 534, 672, 778, 292, 473, 566, 104, ++ 172, 285, 832, 411, 329, 628, 397, 472, 271, 910, 711, 690, 969, 585, ++ 809, 941, 923, 555, 228, 685, 242, 94, 96, 211, 140, 61, 922, 795, ++ 869, 34, 255, 38, 984, 676, 15, 560, 632, 434, 921, 355, 582, 351, ++ 212, 200, 819, 960, 649, 852, 75, 771, 361, 996, 238, 316, 720, 671, ++ 462, 112, 569, 171, 664, 625, 588, 405, 553, 270, 533, 353, 842, 114, ++ 972, 83, 937, 63, 194, 237, 537, 980, 802, 916, 959, 688, 839, 350, ++ 917, 650, 545, 615, 151, 352, 686, 726, 266, 509, 439, 491, 935, 608, ++ 518, 653, 339, 609, 277, 635, 836, 88, 407, 440, 642, 927, 229, 727, ++ 360, 477, 846, 413, 454, 616, 28, 598, 567, 540, 790, 424, 247, 317, ++ 746, 911, 798, 321, 547, 248, 734, 829, 220, 138, 756, 500, 691, 196, ++ 740, 930, 843, 733, 221, 827, 50, 813, 949, 525, 349, 474, 134, 875, ++ 695, 513, 414, 515, 638, 99, 366, 490, 975, 246, 465, 206, 281, 583, ++ 256, 587, 749, 2, 951, 679, 215, 364, 458, 402, 646, 991, 335, 982, ++ 835, 300, 900, 703, 994, 983, 234, 888, 532, 804, 584, 305, 792, 442, ++ 291, 964, 158, 370, 452, 250, 521, 166, 948, 812, 794, 272, 699, 205, ++ 183, 507, 301, 920, 781, 233, 824, 137, 489, 833, 887, 966, 856, 78, ++ 830, 153, 359, 696, 526, 216, 66, 701, 403, 891, 849, 571, 308, 483, ++ 164, 293, 928, 677, 320, 837, 441, 639, 564, 510, 648, 274, 336, 661, ++ 878, 777, 816, 976, 493, 810, 67, 87, 91, 187, 882, 986, 80, 22, 499, ++ 90, 705, 139, 136, 122, 708, 716, 886, 572, 127, 40, 721, 764, 16, ++ 379, 692, 645, 456, 710, 460, 783, 97, 776, 713, 884, 115, 466, 596, ++ 374, 406, 110, 568, 68, 214, 622, 470, 107, 504, 682, 31, 421, 576, ++ 654, 605, 788, 799, 280, 338, 931, 873, 204, 287, 459, 755, 939, 599, ++ 431, 796, 235, 42, 750, 262, 318, 393, 202, 822, 879, 820, 728, 337, ++}; ++ ++static void fill_bindings_random(struct strbuf *buf, int start, int end, ++ const char *prefix) ++{ ++ int i; ++ ++ for (i = start; i < end; i++) { ++ print_strbuf(buf, "%s", prefix); ++ format_devname(buf, random_numbers[i]); ++ print_strbuf(buf, " WWID%d\n", random_numbers[i]); ++ } ++} ++ ++struct random_aliases { ++ int start; ++ int end; ++ const char *prefix; ++}; ++ ++static void order_test(int n, const struct random_aliases ra[], bool conflict_ok) ++{ ++ STRBUF_ON_STACK(buf); ++ int i, j, prev, curr, tmp; ++ struct binding *bdg; ++ Bindings *bindings = &global_bindings; ++ ++ for (j = 0; j < n; j++) ++ fill_bindings_random(&buf, ra[j].start, ra[j].end, ra[j].prefix); ++ __mock_bindings_file(get_strbuf_str(&buf), conflict_ok); ++ ++ for (j = 0; j < n; j++) { ++ bdg = VECTOR_SLOT(bindings, 0); ++ if (ALIAS_DEBUG && j == 0) ++ printf("%d: %s\n", 0, bdg->alias); ++ prev = scan_devname(bdg->alias, ra[j].prefix); ++ i = 1; ++ vector_foreach_slot_after(bindings, bdg, i) { ++ if (ALIAS_DEBUG && j == 0) ++ printf("%d: %s\n", i, bdg->alias); ++ tmp = scan_devname(bdg->alias, ra[j].prefix); ++ if (tmp == -1) ++ continue; ++ curr = tmp; ++ if (prev > 0) { ++ if (curr <= prev) ++ printf("ERROR: %d (%s) %d >= %d\n", ++ i, bdg->alias, prev, curr); ++ assert_true(curr > prev); ++ } ++ prev = curr; ++ } ++ } ++} ++ ++static void order_01(void **state) ++{ ++ const struct random_aliases ra[] = { ++ { 0, 1000, "MPATH" }, ++ }; ++ ++ order_test(ARRAY_SIZE(ra), ra, false); ++} ++ ++static void order_02(void **state) ++{ ++ const struct random_aliases ra[] = { ++ { 0, 500, "MPATH" }, ++ { 200, 700, "mpath" }, ++ }; ++ order_test(ARRAY_SIZE(ra), ra, false); ++} ++ ++static void order_03(void **state) ++{ ++ const struct random_aliases ra[] = { ++ { 500, 1000, "MPTH" }, ++ { 0, 500, "MPATH" }, ++ }; ++ order_test(ARRAY_SIZE(ra), ra, false); ++} ++ ++static void order_04(void **state) ++{ ++ const struct random_aliases ra[] = { ++ { 0, 500, "mpa" }, ++ { 250, 750, "mp" }, ++ }; ++ order_test(ARRAY_SIZE(ra), ra, true); ++} ++ ++static void order_05(void **state) ++{ ++ const struct random_aliases ra[] = { ++ { 0, 100, "A" }, ++ { 0, 100, "B" }, ++ { 0, 100, "C" }, ++ { 0, 100, "D" }, ++ }; ++ order_test(ARRAY_SIZE(ra), ra, false); ++} ++ ++static void order_06(void **state) ++{ ++ const struct random_aliases ra[] = { ++ { 0, 100, "" }, ++ { 0, 100, "a" }, ++ { 0, 100, "aa" }, ++ { 0, 100, "ab" }, ++ { 0, 100, "aaa" }, ++ }; ++ order_test(ARRAY_SIZE(ra), ra, true); ++} ++ ++static int test_bindings_order() ++{ ++ const struct CMUnitTest tests[] = { ++ cmocka_unit_test_teardown(order_01, teardown_bindings), ++ cmocka_unit_test_teardown(order_02, teardown_bindings), ++ cmocka_unit_test_teardown(order_03, teardown_bindings), ++ cmocka_unit_test_teardown(order_04, teardown_bindings), ++ cmocka_unit_test_teardown(order_05, teardown_bindings), ++ cmocka_unit_test_teardown(order_06, teardown_bindings), ++ }; ++ ++ return cmocka_run_group_tests(tests, NULL, NULL); ++} ++ + int main(void) + { + int ret = 0; +@@ -1755,6 +1960,7 @@ int main(void) + ret += test_rlookup_binding(); + ret += test_allocate_binding(); + ret += test_get_user_friendly_alias(); ++ ret += test_bindings_order(); + + return ret; + } diff --git a/0027-multipathd-watch-bindings-file-with-inotify-timestam.patch b/0027-multipathd-watch-bindings-file-with-inotify-timestam.patch new file mode 100644 index 0000000..af21b74 --- /dev/null +++ b/0027-multipathd-watch-bindings-file-with-inotify-timestam.patch @@ -0,0 +1,597 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 7 Sep 2023 22:22:43 +0200 +Subject: [PATCH] multipathd: watch bindings file with inotify + timestamp + +Since "libmultipath: keep bindings in memory", we don't re-read the +bindings file after every modification. Add a notification mechanism +that makes multipathd aware of changes to the bindings file. Because +multipathd itself will change the bindings file, it must compare +timestamps in order to avoid reading the file repeatedly. + +Because select_alias() can be called from multiple thread contexts (uxlsnr, +uevent handler), we need to add locking for the bindings file. The +timestamp must also be protected by a lock, because it can't be read +or written atomically. + +Note: The notification mechanism expects the bindings file to be +atomically replaced by rename(2). Changes must be made in a temporary file and +applied using rename(2), as in update_bindings_file(). The inotify +mechanism deliberately does not listen to close-after-write events +that would be generated by editing the bindings file directly. This + +Note also: new bindings will only be read from add_map_with_path(), +i.e. either during reconfigure(), or when a new map is created during +runtime. Existing maps will not be renamed if the binding file changes, +unless the user runs "multipathd reconfigure". This is not a change +wrt the previous code, but it should be mentioned anyway. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/alias.c | 256 +++++++++++++++++++++++++----- + libmultipath/alias.h | 3 +- + libmultipath/libmultipath.version | 5 + + multipathd/uxlsnr.c | 36 ++++- + tests/alias.c | 3 + + 5 files changed, 256 insertions(+), 47 deletions(-) + +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index 66e34e31..964b8a7b 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + #include "debug.h" + #include "util.h" +@@ -22,6 +23,7 @@ + #include "config.h" + #include "devmapper.h" + #include "strbuf.h" ++#include "time-util.h" + + /* + * significant parts of this file were taken from iscsi-bindings.c of the +@@ -50,6 +52,12 @@ + "# alias wwid\n" \ + "#\n" + ++/* uatomic access only */ ++static int bindings_file_changed = 1; ++ ++static pthread_mutex_t timestamp_mutex = PTHREAD_MUTEX_INITIALIZER; ++static struct timespec bindings_last_updated; ++ + struct binding { + char *alias; + char *wwid; +@@ -60,6 +68,9 @@ struct binding { + * an abstract type. + */ + typedef struct _vector Bindings; ++ ++/* Protect global_bindings */ ++static pthread_mutex_t bindings_mutex = PTHREAD_MUTEX_INITIALIZER; + static Bindings global_bindings = { .allocated = 0 }; + + enum { +@@ -78,6 +89,27 @@ static void _free_binding(struct binding *bdg) + free(bdg); + } + ++static void free_bindings(Bindings *bindings) ++{ ++ struct binding *bdg; ++ int i; ++ ++ vector_foreach_slot(bindings, bdg, i) ++ _free_binding(bdg); ++ vector_reset(bindings); ++} ++ ++static void set_global_bindings(Bindings *bindings) ++{ ++ Bindings old_bindings; ++ ++ pthread_mutex_lock(&bindings_mutex); ++ old_bindings = global_bindings; ++ global_bindings = *bindings; ++ pthread_mutex_unlock(&bindings_mutex); ++ free_bindings(&old_bindings); ++} ++ + static const struct binding *get_binding_for_alias(const Bindings *bindings, + const char *alias) + { +@@ -199,7 +231,8 @@ static int delete_binding(Bindings *bindings, const char *wwid) + return BINDING_DELETED; + } + +-static int write_bindings_file(const Bindings *bindings, int fd) ++static int write_bindings_file(const Bindings *bindings, int fd, ++ struct timespec *ts) + { + struct binding *bnd; + STRBUF_ON_STACK(content); +@@ -227,9 +260,56 @@ static int write_bindings_file(const Bindings *bindings, int fd) + } + len -= n; + } ++ fsync(fd); ++ if (ts) { ++ struct stat st; ++ ++ if (fstat(fd, &st) == 0) ++ *ts = st.st_mtim; ++ else ++ clock_gettime(CLOCK_REALTIME_COARSE, ts); ++ } + return 0; + } + ++void handle_bindings_file_inotify(const struct inotify_event *event) ++{ ++ struct config *conf; ++ const char *base; ++ bool changed = false; ++ struct stat st; ++ struct timespec ts = { 0, 0 }; ++ int ret; ++ ++ if (!(event->mask & IN_MOVED_TO)) ++ return; ++ ++ conf = get_multipath_config(); ++ base = strrchr(conf->bindings_file, '/'); ++ changed = base && base > conf->bindings_file && ++ !strcmp(base + 1, event->name); ++ ret = stat(conf->bindings_file, &st); ++ put_multipath_config(conf); ++ ++ if (!changed) ++ return; ++ ++ pthread_mutex_lock(×tamp_mutex); ++ if (ret == 0) { ++ ts = st.st_mtim; ++ changed = timespeccmp(&ts, &bindings_last_updated) > 0; ++ } ++ pthread_mutex_unlock(×tamp_mutex); ++ ++ if (changed) { ++ uatomic_xchg(&bindings_file_changed, 1); ++ condlog(3, "%s: bindings file must be re-read, new timestamp: %ld.%06ld", ++ __func__, (long)ts.tv_sec, (long)ts.tv_nsec / 1000); ++ } else ++ condlog(3, "%s: bindings file is up-to-date, timestamp: %ld.%06ld", ++ __func__, (long)ts.tv_sec, (long)ts.tv_nsec / 1000); ++} ++ + static int update_bindings_file(const Bindings *bindings, + const char *bindings_file) + { +@@ -237,6 +317,7 @@ static int update_bindings_file(const Bindings *bindings, + int fd = -1; + char tempname[PATH_MAX]; + mode_t old_umask; ++ struct timespec ts; + + if (safe_sprintf(tempname, "%s.XXXXXX", bindings_file)) + return -1; +@@ -248,7 +329,7 @@ static int update_bindings_file(const Bindings *bindings, + } + umask(old_umask); + pthread_cleanup_push(cleanup_fd_ptr, &fd); +- rc = write_bindings_file(bindings, fd); ++ rc = write_bindings_file(bindings, fd, &ts); + pthread_cleanup_pop(1); + if (rc == -1) { + condlog(1, "failed to write new bindings file"); +@@ -257,8 +338,12 @@ static int update_bindings_file(const Bindings *bindings, + } + if ((rc = rename(tempname, bindings_file)) == -1) + condlog(0, "%s: rename: %m", __func__); +- else ++ else { ++ pthread_mutex_lock(×tamp_mutex); ++ bindings_last_updated = ts; ++ pthread_mutex_unlock(×tamp_mutex); + condlog(1, "updated bindings file %s", bindings_file); ++ } + return rc; + } + +@@ -387,6 +472,7 @@ int get_free_id(const Bindings *bindings, const char *prefix, const char *map_ww + return id; + } + ++/* Called with binding_mutex held */ + static char * + allocate_binding(const char *filename, const char *wwid, int id, const char *prefix) + { +@@ -423,6 +509,30 @@ allocate_binding(const char *filename, const char *wwid, int id, const char *pre + return alias; + } + ++enum { ++ BINDINGS_FILE_UP2DATE, ++ BINDINGS_FILE_READ, ++ BINDINGS_FILE_ERROR, ++ BINDINGS_FILE_BAD, ++}; ++ ++static int _read_bindings_file(const struct config *conf, Bindings *bindings, ++ bool force); ++ ++static void read_bindings_file(void) ++{ ++ struct config *conf; ++ Bindings bindings = {.allocated = 0, }; ++ int rc; ++ ++ conf = get_multipath_config(); ++ pthread_cleanup_push(put_multipath_config, conf); ++ rc = _read_bindings_file(conf, &bindings, false); ++ pthread_cleanup_pop(1); ++ if (rc == BINDINGS_FILE_READ) ++ set_global_bindings(&bindings); ++} ++ + /* + * get_user_friendly_alias() action table + * +@@ -463,6 +573,11 @@ char *get_user_friendly_alias(const char *wwid, const char *file, const char *al + bool new_binding = false; + const struct binding *bdg; + ++ read_bindings_file(); ++ ++ pthread_mutex_lock(&bindings_mutex); ++ pthread_cleanup_push(cleanup_mutex, &bindings_mutex); ++ + if (!*alias_old) + goto new_alias; + +@@ -514,40 +629,40 @@ new_alias: + alias, wwid); + + out: ++ /* unlock bindings_mutex */ ++ pthread_cleanup_pop(1); + return alias; + } + + int get_user_friendly_wwid(const char *alias, char *buff) + { + const struct binding *bdg; ++ int rc = -1; + + if (!alias || *alias == '\0') { + condlog(3, "Cannot find binding for empty alias"); + return -1; + } + ++ read_bindings_file(); ++ ++ pthread_mutex_lock(&bindings_mutex); ++ pthread_cleanup_push(cleanup_mutex, &bindings_mutex); + bdg = get_binding_for_alias(&global_bindings, alias); +- if (!bdg) { ++ if (bdg) { ++ strlcpy(buff, bdg->wwid, WWID_SIZE); ++ rc = 0; ++ } else + *buff = '\0'; +- return -1; +- } +- strlcpy(buff, bdg->wwid, WWID_SIZE); +- return 0; +-} +- +-static void free_bindings(Bindings *bindings) +-{ +- struct binding *bdg; +- int i; +- +- vector_foreach_slot(bindings, bdg, i) +- _free_binding(bdg); +- vector_reset(bindings); ++ pthread_cleanup_pop(1); ++ return rc; + } + + void cleanup_bindings(void) + { ++ pthread_mutex_lock(&bindings_mutex); + free_bindings(&global_bindings); ++ pthread_mutex_unlock(&bindings_mutex); + } + + enum { +@@ -595,7 +710,20 @@ static int _check_bindings_file(const struct config *conf, FILE *file, + char *line = NULL; + size_t line_len = 0; + ssize_t n; +- ++ char header[sizeof(BINDINGS_FILE_HEADER)]; ++ ++ header[sizeof(BINDINGS_FILE_HEADER) - 1] = '\0'; ++ if (fread(header, sizeof(BINDINGS_FILE_HEADER) - 1, 1, file) < 1) { ++ condlog(2, "%s: failed to read header from %s", __func__, ++ conf->bindings_file); ++ fseek(file, 0, SEEK_SET); ++ rc = -1; ++ } else if (strcmp(header, BINDINGS_FILE_HEADER)) { ++ condlog(2, "%s: invalid header in %s", __func__, ++ conf->bindings_file); ++ fseek(file, 0, SEEK_SET); ++ rc = -1; ++ } + pthread_cleanup_push(cleanup_free_ptr, &line); + while ((n = getline(&line, &line_len, file)) >= 0) { + char *alias, *wwid; +@@ -643,6 +771,68 @@ static int mp_alias_compar(const void *p1, const void *p2) + &((*(struct mpentry * const *)p2)->alias)); + } + ++static int _read_bindings_file(const struct config *conf, Bindings *bindings, ++ bool force) ++{ ++ int can_write; ++ int rc = 0, ret, fd; ++ FILE *file; ++ struct stat st; ++ int has_changed = uatomic_xchg(&bindings_file_changed, 0); ++ ++ if (!force) { ++ if (!has_changed) { ++ condlog(4, "%s: bindings are unchanged", __func__); ++ return BINDINGS_FILE_UP2DATE; ++ } ++ } ++ ++ fd = open_file(conf->bindings_file, &can_write, BINDINGS_FILE_HEADER); ++ if (fd == -1) ++ return BINDINGS_FILE_ERROR; ++ ++ file = fdopen(fd, "r"); ++ if (file != NULL) { ++ condlog(3, "%s: reading %s", __func__, conf->bindings_file); ++ ++ pthread_cleanup_push(cleanup_fclose, file); ++ ret = _check_bindings_file(conf, file, bindings); ++ if (ret == 0) { ++ struct timespec ts; ++ ++ rc = BINDINGS_FILE_READ; ++ ret = fstat(fd, &st); ++ if (ret == 0) ++ ts = st.st_mtim; ++ else { ++ condlog(1, "%s: fstat failed (%m), using current time", __func__); ++ clock_gettime(CLOCK_REALTIME_COARSE, &ts); ++ } ++ pthread_mutex_lock(×tamp_mutex); ++ bindings_last_updated = ts; ++ pthread_mutex_unlock(×tamp_mutex); ++ } else if (ret == -1 && can_write && !conf->bindings_read_only) { ++ ret = update_bindings_file(bindings, conf->bindings_file); ++ if (ret == 0) ++ rc = BINDINGS_FILE_READ; ++ else ++ rc = BINDINGS_FILE_BAD; ++ } else { ++ condlog(0, "ERROR: bad settings in read-only bindings file %s", ++ conf->bindings_file); ++ rc = BINDINGS_FILE_BAD; ++ } ++ pthread_cleanup_pop(1); ++ } else { ++ condlog(1, "failed to fdopen %s: %m", ++ conf->bindings_file); ++ close(fd); ++ rc = BINDINGS_FILE_ERROR; ++ } ++ ++ return rc; ++} ++ + /* + * check_alias_settings(): test for inconsistent alias configuration + * +@@ -661,8 +851,7 @@ static int mp_alias_compar(const void *p1, const void *p2) + */ + int check_alias_settings(const struct config *conf) + { +- int can_write; +- int rc = 0, i, fd; ++ int i, rc; + Bindings bindings = {.allocated = 0, }; + vector mptable = NULL; + struct mpentry *mpe; +@@ -695,27 +884,12 @@ int check_alias_settings(const struct config *conf) + pthread_cleanup_pop(1); + pthread_cleanup_pop(1); + +- fd = open_file(conf->bindings_file, &can_write, BINDINGS_FILE_HEADER); +- if (fd != -1) { +- FILE *file = fdopen(fd, "r"); +- +- if (file != NULL) { +- pthread_cleanup_push(cleanup_fclose, file); +- rc = _check_bindings_file(conf, file, &bindings); +- pthread_cleanup_pop(1); +- if (rc == -1 && can_write && !conf->bindings_read_only) +- rc = update_bindings_file(&bindings, conf->bindings_file); +- else if (rc == -1) +- condlog(0, "ERROR: bad settings in read-only bindings file %s", +- conf->bindings_file); +- } else { +- condlog(1, "failed to fdopen %s: %m", +- conf->bindings_file); +- close(fd); +- } ++ rc = _read_bindings_file(conf, &bindings, true); ++ ++ if (rc == BINDINGS_FILE_READ) { ++ set_global_bindings(&bindings); ++ rc = 0; + } + +- cleanup_bindings(); +- global_bindings = bindings; + return rc; + } +diff --git a/libmultipath/alias.h b/libmultipath/alias.h +index 5ef6720b..ca8911f4 100644 +--- a/libmultipath/alias.h ++++ b/libmultipath/alias.h +@@ -10,5 +10,6 @@ char *get_user_friendly_alias(const char *wwid, const char *file, + struct config; + int check_alias_settings(const struct config *); + void cleanup_bindings(void); +- ++struct inotify_event; ++void handle_bindings_file_inotify(const struct inotify_event *event); + #endif /* _ALIAS_H */ +diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version +index ddd302f5..57e50c12 100644 +--- a/libmultipath/libmultipath.version ++++ b/libmultipath/libmultipath.version +@@ -238,3 +238,8 @@ global: + local: + *; + }; ++ ++LIBMULTIPATH_20.1.0 { ++global: ++ handle_bindings_file_inotify; ++}; +diff --git a/multipathd/uxlsnr.c b/multipathd/uxlsnr.c +index 02e89fb4..d1f8f234 100644 +--- a/multipathd/uxlsnr.c ++++ b/multipathd/uxlsnr.c +@@ -41,6 +41,7 @@ + #include "cli.h" + #include "uxlsnr.h" + #include "strbuf.h" ++#include "alias.h" + + /* state of client connection */ + enum { +@@ -190,6 +191,7 @@ void wakeup_cleanup(void *arg) + struct watch_descriptors { + int conf_wd; + int dir_wd; ++ int mp_wd; /* /etc/multipath; for bindings file */ + }; + + /* failing to set the watch descriptor is o.k. we just miss a warning +@@ -200,6 +202,8 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds, + struct config *conf; + int dir_reset = 0; + int conf_reset = 0; ++ int mp_reset = 0; ++ char *bindings_file __attribute__((cleanup(cleanup_charp))) = NULL; + + if (notify_fd == -1) + return; +@@ -214,7 +218,10 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds, + conf_reset = 1; + if (wds->dir_wd == -1) + dir_reset = 1; ++ if (wds->mp_wd == -1) ++ mp_reset = 1; + } ++ bindings_file = strdup(conf->bindings_file); + put_multipath_config(conf); + + if (dir_reset) { +@@ -235,7 +242,18 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds, + if (wds->conf_wd == -1) + condlog(3, "didn't set up notifications on /etc/multipath.conf: %m"); + } +- return; ++ if (mp_reset && bindings_file) { ++ char *slash = strrchr(bindings_file, '/'); ++ ++ if (slash && slash > bindings_file) { ++ *slash = '\0'; ++ wds->mp_wd = inotify_add_watch(notify_fd, bindings_file, ++ IN_MOVED_TO|IN_ONLYDIR); ++ if (wds->mp_wd == -1) ++ condlog(3, "didn't set up notifications on %s: %m", ++ bindings_file); ++ } ++ } + } + + static void handle_inotify(int fd, struct watch_descriptors *wds) +@@ -256,12 +274,13 @@ static void handle_inotify(int fd, struct watch_descriptors *wds) + inotify_rm_watch(fd, wds->conf_wd); + if (wds->dir_wd != -1) + inotify_rm_watch(fd, wds->dir_wd); +- wds->conf_wd = wds->dir_wd = -1; ++ if (wds->mp_wd != -1) ++ inotify_rm_watch(fd, wds->mp_wd); ++ wds->conf_wd = wds->dir_wd = wds->mp_wd = -1; + } + break; + } + +- got_notify = 1; + for (ptr = buff; ptr < buff + len; + ptr += sizeof(struct inotify_event) + event->len) { + event = (const struct inotify_event *) ptr; +@@ -273,7 +292,13 @@ static void handle_inotify(int fd, struct watch_descriptors *wds) + wds->conf_wd = inotify_add_watch(notify_fd, DEFAULT_CONFIGFILE, IN_CLOSE_WRITE); + else if (wds->dir_wd == event->wd) + wds->dir_wd = -1; ++ else if (wds->mp_wd == event->wd) ++ wds->mp_wd = -1; + } ++ if (wds->mp_wd != -1 && wds->mp_wd == event->wd) ++ handle_bindings_file_inotify(event); ++ else ++ got_notify = 1; + } + } + if (got_notify) +@@ -599,7 +624,7 @@ void *uxsock_listen(long ux_sock, void *trigger_data) + int max_pfds = MIN_POLLS + POLLFDS_BASE; + /* conf->sequence_nr will be 1 when uxsock_listen is first called */ + unsigned int sequence_nr = 0; +- struct watch_descriptors wds = { .conf_wd = -1, .dir_wd = -1 }; ++ struct watch_descriptors wds = { .conf_wd = -1, .dir_wd = -1, .mp_wd = -1, }; + struct vectors *vecs = trigger_data; + + condlog(3, "uxsock: startup listener"); +@@ -666,7 +691,8 @@ void *uxsock_listen(long ux_sock, void *trigger_data) + + reset_watch(notify_fd, &wds, &sequence_nr); + polls[POLLFD_NOTIFY].fd = notify_fd; +- if (notify_fd == -1 || (wds.conf_wd == -1 && wds.dir_wd == -1)) ++ if (notify_fd == -1 || (wds.conf_wd == -1 && wds.dir_wd == -1 ++ && wds.mp_wd == -1)) + polls[POLLFD_NOTIFY].events = 0; + else + polls[POLLFD_NOTIFY].events = POLLIN; +diff --git a/tests/alias.c b/tests/alias.c +index 7f3ff38a..9ae27567 100644 +--- a/tests/alias.c ++++ b/tests/alias.c +@@ -1954,6 +1954,9 @@ int main(void) + int ret = 0; + init_test_verbosity(3); + ++ /* avoid open_file() call in _read_bindings_file */ ++ bindings_file_changed = 0; ++ + ret += test_format_devname(); + ret += test_scan_devname(); + ret += test_lookup_binding(); diff --git a/0028-multipath-tools-tests-mock-pthread_mutex_-lock-unloc.patch b/0028-multipath-tools-tests-mock-pthread_mutex_-lock-unloc.patch new file mode 100644 index 0000000..bba92f3 --- /dev/null +++ b/0028-multipath-tools-tests-mock-pthread_mutex_-lock-unloc.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 8 Sep 2023 19:54:07 +0200 +Subject: [PATCH] multipath-tools tests: mock pthread_mutex_{lock,unlock} + +If some test fails with a lock held, cmocka doesn't deal well with +pthread_cleanup_pop(). Such tests can cause deadlock with the locking +primitives in the alias code, because locks don't get properly unlocked. Just +mock the lock/unlock functions and generate an error if they weren't paired at +the end of the test. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + tests/Makefile | 1 + + tests/alias.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 47 insertions(+) + +diff --git a/tests/Makefile b/tests/Makefile +index c777d07a..7dac8a8f 100644 +--- a/tests/Makefile ++++ b/tests/Makefile +@@ -52,6 +52,7 @@ blacklist-test_LIBDEPS := -ludev + vpd-test_OBJDEPS := $(multipathdir)/discovery.o + vpd-test_LIBDEPS := -ludev -lpthread -ldl + alias-test_TESTDEPS := test-log.o ++alias-test_OBJDEPS := $(mpathutildir)/util.o + alias-test_LIBDEPS := -lpthread -ldl + valid-test_OBJDEPS := $(multipathdir)/valid.o $(multipathdir)/discovery.o + valid-test_LIBDEPS := -lmount -ludev -lpthread -ldl +diff --git a/tests/alias.c b/tests/alias.c +index 9ae27567..94df36d8 100644 +--- a/tests/alias.c ++++ b/tests/alias.c +@@ -89,6 +89,47 @@ int __wrap_dm_get_uuid(const char *name, char *uuid, int uuid_len) + return ret; + } + ++static int lock_errors; ++static int bindings_locked; ++static int timestamp_locked; ++int __wrap_pthread_mutex_lock(pthread_mutex_t *mutex) ++{ ++ if (mutex == &bindings_mutex) { ++ if (bindings_locked) { ++ fprintf(stderr, "%s: bindings_mutex LOCKED\n", __func__); ++ lock_errors++; ++ } ++ bindings_locked = 1; ++ } else if (mutex == ×tamp_mutex) { ++ if (timestamp_locked) { ++ fprintf(stderr, "%s: timestamp_mutex LOCKED\n", __func__); ++ lock_errors++; ++ } ++ timestamp_locked = 1; ++ } else ++ fprintf(stderr, "%s called for unknown mutex %p\n", __func__, mutex); ++ return 0; ++} ++ ++int __wrap_pthread_mutex_unlock(pthread_mutex_t *mutex) ++{ ++ if (mutex == &bindings_mutex) { ++ if (!bindings_locked) { ++ fprintf(stderr, "%s: bindings_mutex UNLOCKED\n", __func__); ++ lock_errors++; ++ } ++ bindings_locked = 0; ++ } else if (mutex == ×tamp_mutex) { ++ if (!timestamp_locked) { ++ fprintf(stderr, "%s: timestamp_mutex UNLOCKED\n", __func__); ++ lock_errors++; ++ } ++ timestamp_locked = 0; ++ } else ++ fprintf(stderr, "%s called for unknown mutex %p\n", __func__, mutex); ++ return 0; ++} ++ + #define TEST_FDNO 1234 + #define TEST_FPTR ((FILE *) 0xaffe) + +@@ -1718,6 +1759,10 @@ static void gufa_old_nomatch_nowwidmatch(void **state) { + free(alias); + } + ++static void gufa_check_locking(void **state) { ++ assert_int_equal(lock_errors, 0); ++} ++ + static int test_get_user_friendly_alias() + { + const struct CMUnitTest tests[] = { +@@ -1743,6 +1788,7 @@ static int test_get_user_friendly_alias() + cmocka_unit_test_teardown(gufa_old_nomatch_wwidmatch, teardown_bindings), + cmocka_unit_test_teardown(gufa_old_nomatch_wwidmatch_used, teardown_bindings), + cmocka_unit_test_teardown(gufa_old_nomatch_nowwidmatch, teardown_bindings), ++ cmocka_unit_test(gufa_check_locking), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/0029-multipath-tools-Makefile-sanitize-paths-for-configur.patch b/0029-multipath-tools-Makefile-sanitize-paths-for-configur.patch new file mode 100644 index 0000000..26b79a8 --- /dev/null +++ b/0029-multipath-tools-Makefile-sanitize-paths-for-configur.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 8 Sep 2023 22:13:51 +0200 +Subject: [PATCH] multipath-tools Makefile: sanitize paths for configuration + files + +Make the path to multipath.conf configurable, and use the same prefix +by default for multipath.conf and multipath/conf.d. For "usr-merged" +distributions with immutable /usr, we'll want to have the configuration +under a different prefix. This can be achieved by using e.g. + + make prefix=/usr etc_prefix="" + +Note that with prefix=/usr, before this patch the code would use +/usr/etc/multipath/conf.d, but /etc/multipath.conf. If this (rather +inconsistent) behavior is desired, use the following command line: + + make prefix=/usr configfile=/etc/multipath.conf + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + Makefile.inc | 9 ++++++--- + libmultipath/defaults.h | 1 - + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/Makefile.inc b/Makefile.inc +index 502cd0f1..39972d93 100644 +--- a/Makefile.inc ++++ b/Makefile.inc +@@ -37,6 +37,8 @@ prefix := + exec_prefix := $(prefix) + # Prefix for non-essential libraries (libdmmp) + usr_prefix := $(prefix) ++# Prefix for configfuration files (multipath.conf) ++etc_prefix := $(prefix) + # Where to install systemd-related files. systemd is usually installed under /usr + # Note: some systemd installations use separate "prefix" and "rootprefix". + # In this case, override only unitdir to use systemd's "rootprefix" instead of $(systemd_prefix) +@@ -54,7 +56,8 @@ usrlibdir := $(usr_prefix)/$(LIB) + includedir := $(usr_prefix)/include + pkgconfdir := $(usrlibdir)/pkgconfig + plugindir := $(prefix)/$(LIB)/multipath +-configdir := $(prefix)/etc/multipath/conf.d ++configdir := $(etc_prefix)/etc/multipath/conf.d ++configfile := $(etc_prefix)/etc/multipath.conf + runtimedir := $(if $(shell test -L /var/run -o ! -d /var/run && echo 1),/run,/var/run) + devmapper_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir devmapper),/usr/include) + libudev_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir libudev),/usr/include) +@@ -84,8 +87,8 @@ WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implici + $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) + CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) \ + -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \ +- -DRUNTIME_DIR=\"$(runtimedir)\" \ +- -DCONFIG_DIR=\"$(configdir)\" -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP ++ -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \ ++ -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP + CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe + BIN_CFLAGS := -fPIE -DPIE + LIB_CFLAGS := -fPIC +diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h +index b3f11d4c..bc2d6388 100644 +--- a/libmultipath/defaults.h ++++ b/libmultipath/defaults.h +@@ -66,7 +66,6 @@ + #define MAX_DEV_LOSS_TMO UINT_MAX + #define DEFAULT_PIDFILE RUNTIME_DIR "/multipathd.pid" + #define DEFAULT_SOCKET "/org/kernel/linux/storage/multipathd" +-#define DEFAULT_CONFIGFILE "/etc/multipath.conf" + #define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings" + #define DEFAULT_WWIDS_FILE "/etc/multipath/wwids" + #define DEFAULT_PRKEYS_FILE "/etc/multipath/prkeys" diff --git a/0030-multipath-tools-add-compile-time-configuration-for-e.patch b/0030-multipath-tools-add-compile-time-configuration-for-e.patch new file mode 100644 index 0000000..afdf833 --- /dev/null +++ b/0030-multipath-tools-add-compile-time-configuration-for-e.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 8 Sep 2023 22:26:22 +0200 +Subject: [PATCH] multipath-tools: add compile time configuration for + "/etc/multipath" + +Instead of hard-conding "/etc/multipath" as the path for the state +files "bindings", "prkeys", and "wwids", make this path configurable +via the "statedir" compile-time option. The default is currently still +/etc, it might change to /var/lib or similar in the future. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + Makefile.inc | 4 +++- + libmultipath/defaults.h | 6 +++--- + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/Makefile.inc b/Makefile.inc +index 39972d93..96206b2f 100644 +--- a/Makefile.inc ++++ b/Makefile.inc +@@ -58,6 +58,7 @@ pkgconfdir := $(usrlibdir)/pkgconfig + plugindir := $(prefix)/$(LIB)/multipath + configdir := $(etc_prefix)/etc/multipath/conf.d + configfile := $(etc_prefix)/etc/multipath.conf ++statedir := $(etc_prefix)/etc/multipath + runtimedir := $(if $(shell test -L /var/run -o ! -d /var/run && echo 1),/run,/var/run) + devmapper_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir devmapper),/usr/include) + libudev_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir libudev),/usr/include) +@@ -88,7 +89,8 @@ WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implici + CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) \ + -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \ + -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \ +- -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP ++ -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DSTATE_DIR=\"$(statedir)\" \ ++ -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP + CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe + BIN_CFLAGS := -fPIE -DPIE + LIB_CFLAGS := -fPIC +diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h +index bc2d6388..d01f9712 100644 +--- a/libmultipath/defaults.h ++++ b/libmultipath/defaults.h +@@ -66,9 +66,9 @@ + #define MAX_DEV_LOSS_TMO UINT_MAX + #define DEFAULT_PIDFILE RUNTIME_DIR "/multipathd.pid" + #define DEFAULT_SOCKET "/org/kernel/linux/storage/multipathd" +-#define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings" +-#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids" +-#define DEFAULT_PRKEYS_FILE "/etc/multipath/prkeys" ++#define DEFAULT_BINDINGS_FILE STATE_DIR "/bindings" ++#define DEFAULT_WWIDS_FILE STATE_DIR "/wwids" ++#define DEFAULT_PRKEYS_FILE STATE_DIR "/prkeys" + #define MULTIPATH_SHM_BASE RUNTIME_DIR "/multipath/" + + diff --git a/0031-multipath-tools-man-pages-generate-with-correct-path.patch b/0031-multipath-tools-man-pages-generate-with-correct-path.patch new file mode 100644 index 0000000..65fc077 --- /dev/null +++ b/0031-multipath-tools-man-pages-generate-with-correct-path.patch @@ -0,0 +1,366 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 8 Sep 2023 22:48:16 +0200 +Subject: [PATCH] multipath-tools man pages: generate with correct paths + +Generate the man pages using the compile-time settings for paths +to multipath.conf etc. + +Add a paragraph about the CONFIGDIR (/etc/multipath/conf.d) +and the drop-in configuration files in the multipath.conf man page. + +Also, make sure all generated man pages and other files are correctly +removed by "make clean". + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + .gitignore | 4 +++ + Makefile.inc | 3 +++ + mpathpersist/Makefile | 5 ++-- + .../{mpathpersist.8 => mpathpersist.8.in} | 2 +- + multipath/Makefile | 13 +++++---- + multipath/{multipath.8 => multipath.8.in} | 10 +++---- + .../{multipath.conf.5 => multipath.conf.5.in} | 27 ++++++++++++------- + multipathd/Makefile | 9 ++++--- + multipathd/{multipathd.8 => multipathd.8.in} | 8 +++--- + 9 files changed, 49 insertions(+), 32 deletions(-) + rename mpathpersist/{mpathpersist.8 => mpathpersist.8.in} (99%) + rename multipath/{multipath.8 => multipath.8.in} (97%) + rename multipath/{multipath.conf.5 => multipath.conf.5.in} (98%) + rename multipathd/{multipathd.8 => multipathd.8.in} (97%) + +diff --git a/.gitignore b/.gitignore +index 535353e5..2986578f 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -13,11 +13,15 @@ cscope.files + cscope.out + kpartx/kpartx + multipath/multipath ++multipath/multipath.8 ++multipath/multipath.conf.5 + multipath/multipath.rules + multipath/tmpfiles.conf + multipathd/multipathd ++multipathd/multipathd.8 + multipathd/multipathc + mpathpersist/mpathpersist ++mpathpersist/mpathpersist.8 + abi.tar.gz + abi + abi-test +diff --git a/Makefile.inc b/Makefile.inc +index 96206b2f..79e521e1 100644 +--- a/Makefile.inc ++++ b/Makefile.inc +@@ -133,3 +133,6 @@ NV_VERSION_SCRIPT = $(DEVLIB:%.so=%-nv.version) + @grep -P '^[ \t]+[a-zA-Z_][a-zA-Z0-9_]*;' $< >>$@ + @printf 'local:\n\t*;\n};\n' >>$@ + ++%: %.in ++ @echo creating $@ ++ $(Q)sed 's:@CONFIGFILE@:'$(configfile)':g;s:@CONFIGDIR@:'$(configdir)':g;s:@STATE_DIR@:'$(statedir)':g;s:@RUNTIME_DIR@:'$(runtimedir)':g' $< >$@ +diff --git a/mpathpersist/Makefile b/mpathpersist/Makefile +index f57c105c..f3749467 100644 +--- a/mpathpersist/Makefile ++++ b/mpathpersist/Makefile +@@ -8,10 +8,11 @@ LIBDEPS += -L$(mpathpersistdir) -lmpathpersist -L$(multipathdir) -lmultipath \ + -L$(mpathutildir) -lmpathutil -L$(mpathcmddir) -lmpathcmd -lpthread -ldevmapper -ludev + + EXEC = mpathpersist ++MANPAGES := mpathpersist.8 + + OBJS = main.o + +-all: $(EXEC) ++all: $(EXEC) $(MANPAGES) + + $(EXEC): $(OBJS) + $(Q)$(CC) $(OBJS) -o $(EXEC) $(LDFLAGS) $(CFLAGS) $(LIBDEPS) +@@ -23,7 +24,7 @@ install: + $(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)/man8 + + clean: dep_clean +- $(Q)$(RM) core *.o $(EXEC) ++ $(Q)$(RM) core *.o $(EXEC) $(MANPAGES) + + include $(wildcard $(OBJS:.o=.d)) + +diff --git a/mpathpersist/mpathpersist.8 b/mpathpersist/mpathpersist.8.in +similarity index 99% +rename from mpathpersist/mpathpersist.8 +rename to mpathpersist/mpathpersist.8.in +index 8d26b37c..fecef0d6 100644 +--- a/mpathpersist/mpathpersist.8 ++++ b/mpathpersist/mpathpersist.8.in +@@ -31,7 +31,7 @@ mpathpersist \- Manages SCSI persistent reservations on dm multipath devices. + . + This utility is used to manage SCSI persistent reservations on Device Mapper + Multipath devices. To be able to use this functionality, the \fIreservation_key\fR +-attribute must be defined in the \fI/etc/multipath.conf\fR file. Otherwise the ++attribute must be defined in the \fI@CONFIGFILE@\fR file. Otherwise the + \fBmultipathd\fR daemon will not check for persistent reservation for newly + discovered paths or reinstated paths. + . +diff --git a/multipath/Makefile b/multipath/Makefile +index 73db991a..68cb5ce7 100644 +--- a/multipath/Makefile ++++ b/multipath/Makefile +@@ -3,7 +3,9 @@ + # + include ../Makefile.inc + +-EXEC := multipath ++EXEC := multipath ++MANPAGES := multipath.8 multipath.conf.5 ++GENERATED := $(MANPAGES) multipath.rules tmpfiles.conf + + CPPFLAGS += -I$(multipathdir) -I$(mpathutildir) -I$(mpathcmddir) + CFLAGS += $(BIN_CFLAGS) +@@ -13,7 +15,7 @@ LIBDEPS += -L$(multipathdir) -lmultipath -L$(mpathutildir) -lmpathutil \ + + OBJS := main.o + +-all: $(EXEC) multipath.rules tmpfiles.conf ++all: $(EXEC) $(GENERATED) + + $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so + @echo building $@ because of $? +@@ -47,15 +49,12 @@ uninstall: + $(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules + $(Q)$(RM) $(DESTDIR)$(mandir)/man8/$(EXEC).8 + $(Q)$(RM) $(DESTDIR)$(mandir)/man5/$(EXEC).conf.5 ++ $(Q)$(RM) $(DESTDIR)$(tmpfilesdir)/multipath.conf + + clean: dep_clean +- $(Q)$(RM) core *.o $(EXEC) multipath.rules tmpfiles.conf ++ $(Q)$(RM) core *.o $(EXEC) $(GENERATED) + + include $(wildcard $(OBJS:.o=.d)) + + dep_clean: + $(Q)$(RM) $(OBJS:.o=.d) +- +-%: %.in +- @echo creating $@ +- $(Q)sed 's,@RUNTIME_DIR@,$(runtimedir),' $< >$@ +diff --git a/multipath/multipath.8 b/multipath/multipath.8.in +similarity index 97% +rename from multipath/multipath.8 +rename to multipath/multipath.8.in +index 5fed6df7..348eb220 100644 +--- a/multipath/multipath.8 ++++ b/multipath/multipath.8.in +@@ -185,7 +185,7 @@ Display the currently used multipathd configuration. + .B \-T + Display the currently used multipathd configuration, limiting the output to + those devices actually present in the system. This can be used a template for +-creating \fImultipath.conf\fR. ++creating \fI@CONFIGFILE@\fR. + . + .\" ---------------------------------------------------------------------------- + .SH OPTIONS +@@ -233,11 +233,11 @@ option from \fBmultipath.conf(5)\fR. + .B \-i + Ignore WWIDs file when processing devices. If + \fIfind_multipaths strict\fR or \fIfind_multipaths no\fR is set in +-\fImultipath.conf\fR, multipath only considers devices that are ++\fI@CONFIGFILE@\fR, multipath only considers devices that are + listed in the WWIDs file. This option overrides that behavior. For other values + of \fIfind_multipaths\fR, this option has no effect. See the description of + \fIfind_multipaths\fR in +-.BR multipath.conf (5). ++.BR @CONFIGFILE@ (5). + This option should only be used in rare circumstances. + . + .TP +@@ -246,8 +246,8 @@ Treat the bindings file as read only. + . + .TP + .BI \-b " file" +-Set \fIuser_friendly_names\fR bindings file location. The default is +-\fI/etc/multipath/bindings\fR. ++(\fBdeprecated, do not use\fR) Set \fIuser_friendly_names\fR bindings file location. The default is ++\fI@STATE_DIR@/bindings\fR. + . + .TP + .B \-q +diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5.in +similarity index 98% +rename from multipath/multipath.conf.5 +rename to multipath/multipath.conf.5.in +index 93af17db..20df2232 100644 +--- a/multipath/multipath.conf.5 ++++ b/multipath/multipath.conf.5.in +@@ -13,14 +13,14 @@ + .SH NAME + .\" ---------------------------------------------------------------------------- + . +-multipath.conf \- multipath daemon configuration file. ++@CONFIGFILE@, @CONFIGDIR@/*.conf \- multipath daemon configuration file. + . + . + .\" ---------------------------------------------------------------------------- + .SH DESCRIPTION + .\" ---------------------------------------------------------------------------- + . +-.B "/etc/multipath.conf" ++.B "@CONFIGFILE@" + is the configuration file for the multipath daemon. It is used to + overwrite the built-in configuration table of \fBmultipathd\fP. + Any line whose first non-white-space character is a '#' is considered +@@ -29,6 +29,15 @@ a comment line. Empty lines are ignored. + Currently used multipathd configuration can be displayed with the \fBmultipath -t\fR + or \fBmultipathd show config\fR command. + . ++.PP ++Additional configuration can be made in drop-in files under ++.B @CONFIGDIR@. ++Files ending in \fI.conf\fR in this directory are read ++in alphabetical order, after reading \fI@CONFIGFILE@\fR. ++They use the same syntax as \fI@CONFIGFILE@\fR itself, ++and support all sections and keywords. If a keyword occurs in the same section ++in multiple files, the last occurence will take precedence over all others. ++. + . + .\" ---------------------------------------------------------------------------- + .SH SYNTAX +@@ -85,7 +94,7 @@ not mandatory. + . + .LP + .B Note on regular expressions: +-The \fImultipath.conf\fR syntax allows many attribute values to be specified as POSIX ++The \fI@CONFIGFILE@\fR syntax allows many attribute values to be specified as POSIX + Extended Regular Expressions (see \fBregex\fR(7)). These regular expressions + are \fBcase sensitive\fR and \fBnot anchored\fR, thus the expression "bar" matches "barbie", + "rhabarber", and "wunderbar", but not "Barbie". To avoid unwanted substring +@@ -711,7 +720,7 @@ The default is: \fBno\fR + .B user_friendly_names + If set to + .I yes +-, using the bindings file \fI/etc/multipath/bindings\fR to assign a persistent ++, using the bindings file \fI@STATE_DIR@/bindings\fR to assign a persistent + and unique alias to the multipath, in the form of mpath. If set to + .I no + use the WWID as the alias. In either case this be will +@@ -790,7 +799,7 @@ The full pathname of the binding file to be used when the user_friendly_names + option is set. + .RS + .TP +-The default is: \fB/etc/multipath/bindings\fR ++The default is: \fB@STATE_DIR@/bindings\fR + .RE + . + . +@@ -801,7 +810,7 @@ The full pathname of the WWIDs file, which is used by multipath to keep track + of the WWIDs for LUNs it has created multipath devices on in the past. + .RS + .TP +-The default is: \fB/etc/multipath/wwids\fR ++The default is: \fB@STATE_DIR@/wwids\fR + .RE + . + . +@@ -813,7 +822,7 @@ track of the persistent reservation key used for a specific WWID, when + \fIreservation_key\fR is set to \fBfile\fR. + .RS + .TP +-The default is: \fB/etc/multipath/prkeys\fR ++The default is: \fB@STATE_DIR@/prkeys\fR + .RE + . + . +@@ -872,7 +881,7 @@ The default is: \fBno\fR + .I yes + and the SCSI layer has already attached a hardware_handler to the device, + multipath will not force the device to use the hardware_handler specified by +-multipath.conf. If the SCSI layer has not attached a hardware handler, ++@CONFIGFILE@. If the SCSI layer has not attached a hardware handler, + multipath will continue to use its configured hardware handler. + .RS + .PP +@@ -1559,7 +1568,7 @@ given device, the attributes of all matching entries are applied to it. + If an attribute is specified in several matching device subsections, + later entries take precedence. Thus, entries in files under \fIconfig_dir\fR (in + reverse alphabetical order) have the highest precedence, followed by entries +-in \fImultipath.conf\fR; the built-in hardware table has the lowest ++in \fI@CONFIGFILE@\fR; the built-in hardware table has the lowest + precedence. Inside a configuration file, later entries have higher precedence + than earlier ones. + .LP +diff --git a/multipathd/Makefile b/multipathd/Makefile +index 0d0146c5..cdba3db1 100644 +--- a/multipathd/Makefile ++++ b/multipathd/Makefile +@@ -1,7 +1,8 @@ + include ../Makefile.inc + +-EXEC := multipathd +-CLI := multipathc ++EXEC := multipathd ++CLI := multipathc ++MANPAGES := multipathd.8 + + CPPFLAGS += -I$(multipathdir) -I$(mpathutildir) -I$(mpathpersistdir) -I$(mpathcmddir) -I$(thirdpartydir) \ + $(shell $(PKG_CONFIG) --modversion liburcu 2>/dev/null | \ +@@ -42,7 +43,7 @@ ifeq ($(FPIN_SUPPORT),1) + OBJS += fpin_handlers.o + endif + +-all : $(EXEC) $(CLI) ++all : $(EXEC) $(CLI) $(MANPAGES) + + $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so + @echo building $@ because of $? +@@ -79,7 +80,7 @@ uninstall: + $(Q)$(RM) $(DESTDIR)$(unitdir)/$(EXEC).socket + + clean: dep_clean +- $(Q)$(RM) core *.o $(EXEC) $(CLI) ++ $(Q)$(RM) core *.o $(EXEC) $(CLI) $(MANPAGES) + + include $(wildcard $(OBJS:.o=.d) $(CLI_OBJS:.o=.d)) + +diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8.in +similarity index 97% +rename from multipathd/multipathd.8 +rename to multipathd/multipathd.8.in +index cc72b775..e98c27fd 100644 +--- a/multipathd/multipathd.8 ++++ b/multipathd/multipathd.8.in +@@ -155,7 +155,7 @@ Show the format wildcards used in interactive commands taking $format. + .TP + .B list|show config + Show the currently used configuration, derived from default values and values +-specified within the configuration file \fI/etc/multipath.conf\fR. ++specified within the configuration file \fI@CONFIGFILE@\fR. + . + .TP + .B list|show config local +@@ -165,7 +165,7 @@ the devices section to those devices that are actually present in the system. + .TP + .B list|show blacklist + Show the currently used blacklist rules, derived from default values and values +-specified within the configuration file \fI/etc/multipath.conf\fR. ++specified within the configuration file \fI@CONFIGFILE@\fR. + . + .TP + .B list|show devices +@@ -290,13 +290,13 @@ Get the current persistent reservation key associated with $map. + .B map|multipath $map setprkey key $key + Set the persistent reservation key associated with $map to $key in the + \fIprkeys_file\fR. This key will only be used by multipathd if +-\fIreservation_key\fR is set to \fBfile\fR in \fI/etc/multipath.conf\fR. ++\fIreservation_key\fR is set to \fBfile\fR in \fI@CONFIGFILE@\fR. + . + .TP + .B map|multipath $map unsetprkey + Remove the persistent reservation key associated with $map from the + \fIprkeys_file\fR. This will only unset the key used by multipathd if +-\fIreservation_key\fR is set to \fBfile\fR in \fI/etc/multipath.conf\fR. ++\fIreservation_key\fR is set to \fBfile\fR in \fI@CONFIGFILE@\fR. + . + .TP + .B path $path setmarginal diff --git a/0032-libdmmp-Makefile-fix-bug-in-install-section.patch b/0032-libdmmp-Makefile-fix-bug-in-install-section.patch new file mode 100644 index 0000000..a3f2470 --- /dev/null +++ b/0032-libdmmp-Makefile-fix-bug-in-install-section.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 11 Sep 2023 09:30:13 +0200 +Subject: [PATCH] libdmmp/Makefile: fix bug in install section + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libdmmp/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libdmmp/Makefile b/libdmmp/Makefile +index 078eca8f..172ba045 100644 +--- a/libdmmp/Makefile ++++ b/libdmmp/Makefile +@@ -44,7 +44,7 @@ install: + $(DESTDIR)$(pkgconfdir)/$(PKGFILE) + $(Q)sed -i 's|__INCLUDEDIR__|$(includedir)|g' \ + $(DESTDIR)$(pkgconfdir)/$(PKGFILE) +- $(Q)$(INSTALL_PROGRAM) -d 755 $(DESTDIR)$(mandir)/man3 ++ $(Q)$(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(mandir)/man3 + $(Q)$(INSTALL_PROGRAM) -m 644 -t $(DESTDIR)$(mandir)/man3 docs/man/*.3 + + uninstall: diff --git a/0033-multipath-tools-README.md-improve-documentation-for-.patch b/0033-multipath-tools-README.md-improve-documentation-for-.patch new file mode 100644 index 0000000..3c7edd0 --- /dev/null +++ b/0033-multipath-tools-README.md-improve-documentation-for-.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 11 Sep 2023 10:22:13 +0200 +Subject: [PATCH] multipath-tools: README.md: improve documentation for + compile-time options + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + README.md | 38 ++++++++++++++++++++++++++------------ + 1 file changed, 26 insertions(+), 12 deletions(-) + +diff --git a/README.md b/README.md +index a7f994ae..679e55bf 100644 +--- a/README.md ++++ b/README.md +@@ -89,9 +89,17 @@ The following variables can be passed to the `make` command line: + * `plugindir="/some/path"`: directory where libmultipath plugins (path + checkers, prioritizers, and foreign multipath support) will be looked up. + This used to be the run-time option `multipath_dir` in earlier versions. +- * `configdir="/some/path"` : directory to search for configuration files. ++ The default is `$(prefix)/$(LIB)/multipath`, where `$(LIB)` is `lib64` on ++ systems that have `/lib64`, and `lib` otherwise. ++ * `configfile="/some/path`": The path to the main configuration file. ++ The defalt is `$(etc_prefix)/etc/multipath.conf`. ++ * `configdir="/some/path"` : directory to search for additional configuration files. + This used to be the run-time option `config_dir` in earlier versions. +- The default is `/etc/multipath/conf.d`. ++ The default is `$(etc_prefix)/etc/multipath/conf.d`. ++ * `statedir="/some/path"`: The path of the directory where multipath-tools ++ stores run-time settings that need persist between reboots, such as known ++ WWIDs, user-friendly names, and persistent reservation keys. ++ The default is `$(etc_prefix)/etc/multipath`. + * `READLINE=libedit` or `READLINE=libreadline`: enable command line history + and TAB completion in the interactive mode *(which is entered with `multipathd -k` or `multipathc`)*. + The respective development package will be required for building. +@@ -119,21 +127,27 @@ The following variables can be passed to the `make` command line: + ### Installation Paths + + * `prefix`: The directory prefix for (almost) all files to be installed. +- Distributions may want to set this to `/usr`. +- **Note**: for multipath-tools, unlike many other packages, `prefix` +- defaults to the empty string, which resolves to the root directory (`/`). ++ "Usr-merged" distributions[^systemd] may want to set this to `/usr`. The ++ default is empty (`""`). + * `usr_prefix`: where to install those parts of the code that aren't necessary +- for booting. You may want to set this to `/usr` if `prefix` is empty. +- * `systemd_prefix`: Prefix for systemd-related files. It defaults to `/usr`. +- Some systemd installations use separate `prefix` and `rootprefix`. On such +- a distribution, set `prefix`, and override `unitdir` to use systemd's +- `rootprefix`. ++ for booting. Non-usr-merged distributions[^systemd] may want to set this to ++ `/usr`. The default is `$(prefix)`. ++ * `systemd_prefix`: Prefix for systemd-related files[^systemd]. The default is `/usr`. ++ * `etc_prefix`: The prefix for configuration files. "Usr-merged" ++ distributions with immutable `/usr`[^systemd] may want to set this to ++ `/etc`. The default is `$(prefix)`. + * `LIB`: the subdirectory under `prefix` where shared libraries will be + installed. By default, the makefile uses `/lib64` if this directory is + found on the build system, and `/lib` otherwise. + +-See also `configdir` and `plugindir` above. See `Makefile.inc` for more +-fine-grained control. ++The options `configdir`, `plugindir`, `configfile`, and `statedir` above can ++be used for setting indvidual paths where the `prefix` variables don't provide ++sufficient control. See `Makefile.inc` for even more fine-grained control. ++ ++[^systemd]: Some systemd installations use separate `prefix` and `rootprefix`. ++ On such a distribution, set `prefix`, and override `unitdir` to use systemd's ++ `rootprefix`. Recent systemd releases generally require everything to be ++ installed under `/usr` (so-called "usr-merged" distribution). On "usr- + + ### Compiler Options + diff --git a/0034-libmultipath-print-built-in-values-for-deprecated-op.patch b/0034-libmultipath-print-built-in-values-for-deprecated-op.patch new file mode 100644 index 0000000..45e7874 --- /dev/null +++ b/0034-libmultipath-print-built-in-values-for-deprecated-op.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 11 Sep 2023 11:36:25 +0200 +Subject: [PATCH] libmultipath: print built-in values for deprecated options + +In the error messages we print when a deprecated option is encountered, +print the compile-time value of the option. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/dict.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/libmultipath/dict.c b/libmultipath/dict.c +index f81c84aa..dace343d 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -314,14 +314,16 @@ def_ ## option ## _handler (struct config *conf, vector strvec, \ + static int deprecated_handler(struct config *conf, vector strvec, const char *file, + int line_nr); + +-#define declare_deprecated_handler(option) \ ++#define declare_deprecated_handler(option, default) \ + static int \ + deprecated_ ## option ## _handler (struct config *conf, vector strvec, \ + const char *file, int line_nr) \ + { \ + static bool warned; \ + if (!warned) { \ +- condlog(1, "%s line %d: ignoring deprecated option \"" #option "\"", file, line_nr); \ ++ condlog(1, "%s line %d: ignoring deprecated option \"" \ ++ #option "\", using built-in value: \"%s\"", \ ++ file, line_nr, default); \ + warned = true; \ + } \ + return deprecated_handler(conf, strvec, file, line_nr); \ +@@ -2057,11 +2059,11 @@ snprint_deprecated (struct config *conf, struct strbuf *buff, const void * data) + } + + // Deprecated keywords +-declare_deprecated_handler(config_dir) +-declare_deprecated_handler(disable_changed_wwids) +-declare_deprecated_handler(getuid_callout) +-declare_deprecated_handler(multipath_dir) +-declare_deprecated_handler(pg_timeout) ++declare_deprecated_handler(config_dir, CONFIG_DIR) ++declare_deprecated_handler(disable_changed_wwids, "yes") ++declare_deprecated_handler(getuid_callout, "(not set)") ++declare_deprecated_handler(multipath_dir, MULTIPATH_DIR) ++declare_deprecated_handler(pg_timeout, "(not set)") + + /* + * If you add or remove a keyword also update multipath/multipath.conf.5 diff --git a/0035-multipath-add-a-missing-newline.patch b/0035-multipath-add-a-missing-newline.patch new file mode 100644 index 0000000..706b7d3 --- /dev/null +++ b/0035-multipath-add-a-missing-newline.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 11 Sep 2023 11:37:37 +0200 +Subject: [PATCH] multipath: add a missing newline + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipath/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/multipath/main.c b/multipath/main.c +index 45e9745f..b91289e8 100644 +--- a/multipath/main.c ++++ b/multipath/main.c +@@ -1025,7 +1025,7 @@ main (int argc, char *argv[]) + } + + if (check_alias_settings(conf)) { +- fprintf(stderr, "fatal configuration error, aborting"); ++ fprintf(stderr, "fatal configuration error, aborting\n"); + exit(RTVL_FAIL); + } + diff --git a/0036-multipath-tools-allow-prefixes-with-and-w-o-trailing.patch b/0036-multipath-tools-allow-prefixes-with-and-w-o-trailing.patch new file mode 100644 index 0000000..c48240b --- /dev/null +++ b/0036-multipath-tools-allow-prefixes-with-and-w-o-trailing.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 11 Sep 2023 16:03:34 +0200 +Subject: [PATCH] multipath-tools: allow prefixes with and w/o trailing slash + +Add some logic to Makefile.inc that leads to the same result +for "prefix=" and "prefix=/", or "prefix=/usr" and "prefix=/usr/". +The logic does not work for multiple trailing slashes. It applies +to all XYZ_prefix variables in Makefile.inc. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + Makefile.inc | 35 ++++++++++++++++++++++------------- + 1 file changed, 22 insertions(+), 13 deletions(-) + +diff --git a/Makefile.inc b/Makefile.inc +index 79e521e1..6e384e68 100644 +--- a/Makefile.inc ++++ b/Makefile.inc +@@ -43,22 +43,31 @@ etc_prefix := $(prefix) + # Note: some systemd installations use separate "prefix" and "rootprefix". + # In this case, override only unitdir to use systemd's "rootprefix" instead of $(systemd_prefix) + systemd_prefix := /usr +-unitdir := $(systemd_prefix)/lib/systemd/system +-tmpfilesdir := $(systemd_prefix)/lib/tmpfiles.d +-modulesloaddir := $(systemd_prefix)/lib/modules-load.d +-libudevdir := $(systemd_prefix)/lib/udev ++ ++# Make sure all prefix variables end in "/" ++append-slash = $(1)$(if $(filter %/,$(1)),,/) ++override prefix := $(call append-slash,$(prefix)) ++override exec_prefix := $(call append-slash,$(exec_prefix)) ++override usr_prefix := $(call append-slash,$(usr_prefix)) ++override etc_prefix := $(call append-slash,$(etc_prefix)) ++override systemd_prefix := $(call append-slash,$(systemd_prefix)) ++ ++unitdir := $(systemd_prefix)lib/systemd/system ++tmpfilesdir := $(systemd_prefix)lib/tmpfiles.d ++modulesloaddir := $(systemd_prefix)lib/modules-load.d ++libudevdir := $(systemd_prefix)lib/udev + udevrulesdir := $(libudevdir)/rules.d +-bindir := $(exec_prefix)/sbin +-mandir := $(usr_prefix)/share/man ++bindir := $(exec_prefix)sbin ++mandir := $(usr_prefix)share/man + LIB := $(if $(shell test -d /lib64 && echo 1),lib64,lib) +-syslibdir := $(prefix)/$(LIB) +-usrlibdir := $(usr_prefix)/$(LIB) +-includedir := $(usr_prefix)/include ++syslibdir := $(prefix)$(LIB) ++usrlibdir := $(usr_prefix)$(LIB) ++includedir := $(usr_prefix)include + pkgconfdir := $(usrlibdir)/pkgconfig +-plugindir := $(prefix)/$(LIB)/multipath +-configdir := $(etc_prefix)/etc/multipath/conf.d +-configfile := $(etc_prefix)/etc/multipath.conf +-statedir := $(etc_prefix)/etc/multipath ++plugindir := $(prefix)$(LIB)/multipath ++configdir := $(etc_prefix)etc/multipath/conf.d ++configfile := $(etc_prefix)etc/multipath.conf ++statedir := $(etc_prefix)etc/multipath + runtimedir := $(if $(shell test -L /var/run -o ! -d /var/run && echo 1),/run,/var/run) + devmapper_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir devmapper),/usr/include) + libudev_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir libudev),/usr/include) diff --git a/0037-libmultipath-deprecate-bindings_file-wwids_file-prke.patch b/0037-libmultipath-deprecate-bindings_file-wwids_file-prke.patch new file mode 100644 index 0000000..6e066ee --- /dev/null +++ b/0037-libmultipath-deprecate-bindings_file-wwids_file-prke.patch @@ -0,0 +1,897 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 11 Sep 2023 17:58:13 +0200 +Subject: [PATCH] libmultipath: deprecate bindings_file, wwids_file, + prkeys_file + +The options bindings_file, wwids_file, and prkeys_file have been +deprecated since cb4d6db ("libmultipath: deprecate file and directory config +options") (multipath-tools 0.8.8). Deprecate and ignore them now. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/alias.c | 43 +++++++++---------- + libmultipath/alias.h | 3 +- + libmultipath/config.c | 18 -------- + libmultipath/config.h | 3 -- + libmultipath/dict.c | 39 +++--------------- + libmultipath/libmultipath.version | 8 +--- + libmultipath/prkey.c | 7 ++-- + libmultipath/prkey.h | 7 ++-- + libmultipath/propsel.c | 5 +-- + libmultipath/wwids.c | 18 ++------ + multipath/main.c | 2 +- + multipath/multipath.conf.5.in | 23 +++++------ + multipathd/uxlsnr.c | 17 +++----- + tests/alias.c | 68 +++++++++++++++---------------- + 14 files changed, 90 insertions(+), 171 deletions(-) + +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index 964b8a7b..e5d3f151 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -55,6 +55,8 @@ + /* uatomic access only */ + static int bindings_file_changed = 1; + ++static const char bindings_file_path[] = DEFAULT_BINDINGS_FILE; ++ + static pthread_mutex_t timestamp_mutex = PTHREAD_MUTEX_INITIALIZER; + static struct timespec bindings_last_updated; + +@@ -274,7 +276,6 @@ static int write_bindings_file(const Bindings *bindings, int fd, + + void handle_bindings_file_inotify(const struct inotify_event *event) + { +- struct config *conf; + const char *base; + bool changed = false; + struct stat st; +@@ -284,12 +285,9 @@ void handle_bindings_file_inotify(const struct inotify_event *event) + if (!(event->mask & IN_MOVED_TO)) + return; + +- conf = get_multipath_config(); +- base = strrchr(conf->bindings_file, '/'); +- changed = base && base > conf->bindings_file && +- !strcmp(base + 1, event->name); +- ret = stat(conf->bindings_file, &st); +- put_multipath_config(conf); ++ base = strrchr(bindings_file_path, '/'); ++ changed = base && !strcmp(base + 1, event->name); ++ ret = stat(bindings_file_path, &st); + + if (!changed) + return; +@@ -310,8 +308,7 @@ void handle_bindings_file_inotify(const struct inotify_event *event) + __func__, (long)ts.tv_sec, (long)ts.tv_nsec / 1000); + } + +-static int update_bindings_file(const Bindings *bindings, +- const char *bindings_file) ++static int update_bindings_file(const Bindings *bindings) + { + int rc; + int fd = -1; +@@ -319,7 +316,7 @@ static int update_bindings_file(const Bindings *bindings, + mode_t old_umask; + struct timespec ts; + +- if (safe_sprintf(tempname, "%s.XXXXXX", bindings_file)) ++ if (safe_sprintf(tempname, "%s.XXXXXX", bindings_file_path)) + return -1; + /* coverity: SECURE_TEMP */ + old_umask = umask(0077); +@@ -336,13 +333,13 @@ static int update_bindings_file(const Bindings *bindings, + unlink(tempname); + return rc; + } +- if ((rc = rename(tempname, bindings_file)) == -1) ++ if ((rc = rename(tempname, bindings_file_path)) == -1) + condlog(0, "%s: rename: %m", __func__); + else { + pthread_mutex_lock(×tamp_mutex); + bindings_last_updated = ts; + pthread_mutex_unlock(×tamp_mutex); +- condlog(1, "updated bindings file %s", bindings_file); ++ condlog(1, "updated bindings file %s", bindings_file_path); + } + return rc; + } +@@ -474,7 +471,7 @@ int get_free_id(const Bindings *bindings, const char *prefix, const char *map_ww + + /* Called with binding_mutex held */ + static char * +-allocate_binding(const char *filename, const char *wwid, int id, const char *prefix) ++allocate_binding(const char *wwid, int id, const char *prefix) + { + STRBUF_ON_STACK(buf); + char *alias; +@@ -498,7 +495,7 @@ allocate_binding(const char *filename, const char *wwid, int id, const char *pre + return NULL; + } + +- if (update_bindings_file(&global_bindings, filename) == -1) { ++ if (update_bindings_file(&global_bindings) == -1) { + condlog(1, "%s: deleting binding %s for %s", __func__, alias, wwid); + delete_binding(&global_bindings, wwid); + free(alias); +@@ -565,7 +562,7 @@ static void read_bindings_file(void) + * that the mpvec corrcectly represents kernel state. + */ + +-char *get_user_friendly_alias(const char *wwid, const char *file, const char *alias_old, ++char *get_user_friendly_alias(const char *wwid, const char *alias_old, + const char *prefix, bool bindings_read_only) + { + char *alias = NULL; +@@ -622,7 +619,7 @@ new_alias: + } + + if (!bindings_read_only && id > 0) +- alias = allocate_binding(file, wwid, id, prefix); ++ alias = allocate_binding(wwid, id, prefix); + + if (alias && !new_binding) + condlog(2, "Allocated existing binding [%s] for WWID [%s]", +@@ -715,12 +712,12 @@ static int _check_bindings_file(const struct config *conf, FILE *file, + header[sizeof(BINDINGS_FILE_HEADER) - 1] = '\0'; + if (fread(header, sizeof(BINDINGS_FILE_HEADER) - 1, 1, file) < 1) { + condlog(2, "%s: failed to read header from %s", __func__, +- conf->bindings_file); ++ bindings_file_path); + fseek(file, 0, SEEK_SET); + rc = -1; + } else if (strcmp(header, BINDINGS_FILE_HEADER)) { + condlog(2, "%s: invalid header in %s", __func__, +- conf->bindings_file); ++ bindings_file_path); + fseek(file, 0, SEEK_SET); + rc = -1; + } +@@ -787,13 +784,13 @@ static int _read_bindings_file(const struct config *conf, Bindings *bindings, + } + } + +- fd = open_file(conf->bindings_file, &can_write, BINDINGS_FILE_HEADER); ++ fd = open_file(bindings_file_path, &can_write, BINDINGS_FILE_HEADER); + if (fd == -1) + return BINDINGS_FILE_ERROR; + + file = fdopen(fd, "r"); + if (file != NULL) { +- condlog(3, "%s: reading %s", __func__, conf->bindings_file); ++ condlog(3, "%s: reading %s", __func__, bindings_file_path); + + pthread_cleanup_push(cleanup_fclose, file); + ret = _check_bindings_file(conf, file, bindings); +@@ -812,20 +809,20 @@ static int _read_bindings_file(const struct config *conf, Bindings *bindings, + bindings_last_updated = ts; + pthread_mutex_unlock(×tamp_mutex); + } else if (ret == -1 && can_write && !conf->bindings_read_only) { +- ret = update_bindings_file(bindings, conf->bindings_file); ++ ret = update_bindings_file(bindings); + if (ret == 0) + rc = BINDINGS_FILE_READ; + else + rc = BINDINGS_FILE_BAD; + } else { + condlog(0, "ERROR: bad settings in read-only bindings file %s", +- conf->bindings_file); ++ bindings_file_path); + rc = BINDINGS_FILE_BAD; + } + pthread_cleanup_pop(1); + } else { + condlog(1, "failed to fdopen %s: %m", +- conf->bindings_file); ++ bindings_file_path); + close(fd); + rc = BINDINGS_FILE_ERROR; + } +diff --git a/libmultipath/alias.h b/libmultipath/alias.h +index ca8911f4..629e8d56 100644 +--- a/libmultipath/alias.h ++++ b/libmultipath/alias.h +@@ -3,8 +3,7 @@ + + int valid_alias(const char *alias); + int get_user_friendly_wwid(const char *alias, char *buff); +-char *get_user_friendly_alias(const char *wwid, const char *file, +- const char *alias_old, ++char *get_user_friendly_alias(const char *wwid, const char *alias_old, + const char *prefix, bool bindings_read_only); + + struct config; +diff --git a/libmultipath/config.c b/libmultipath/config.c +index 7b207590..b7dbc6f5 100644 +--- a/libmultipath/config.c ++++ b/libmultipath/config.c +@@ -752,15 +752,6 @@ static void _uninit_config(struct config *conf) + if (conf->hwhandler) + free(conf->hwhandler); + +- if (conf->bindings_file) +- free(conf->bindings_file); +- +- if (conf->wwids_file) +- free(conf->wwids_file); +- +- if (conf->prkeys_file) +- free(conf->prkeys_file); +- + if (conf->prio_name) + free(conf->prio_name); + +@@ -922,9 +913,6 @@ int _init_config (const char *file, struct config *conf) + * internal defaults + */ + get_sys_max_fds(&conf->max_fds); +- conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE); +- conf->wwids_file = set_default(DEFAULT_WWIDS_FILE); +- conf->prkeys_file = set_default(DEFAULT_PRKEYS_FILE); + conf->attribute_flags = 0; + conf->reassign_maps = DEFAULT_REASSIGN_MAPS; + conf->checkint = CHECKINT_UNDEF; +@@ -1078,12 +1066,6 @@ int _init_config (const char *file, struct config *conf) + merge_blacklist(conf->elist_wwid); + merge_blacklist_device(conf->elist_device); + +- if (conf->bindings_file == NULL) +- conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE); +- +- if (!conf->bindings_file || !conf->wwids_file || !conf->prkeys_file) +- goto out; +- + libmp_verbosity = conf->verbosity; + return 0; + out: +diff --git a/libmultipath/config.h b/libmultipath/config.h +index 0a2c297b..8c22ce75 100644 +--- a/libmultipath/config.h ++++ b/libmultipath/config.h +@@ -207,9 +207,6 @@ struct config { + char * uid_attribute; + char * features; + char * hwhandler; +- char * bindings_file; +- char * wwids_file; +- char * prkeys_file; + char * prio_name; + char * prio_args; + char * checker_name; +diff --git a/libmultipath/dict.c b/libmultipath/dict.c +index dace343d..044067af 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -168,27 +168,6 @@ fail: + return 0; + } + +-static int +-set_path(vector strvec, void *ptr, const char *file, int line_nr) +-{ +- char **str_ptr = (char **)ptr; +- char *old_str = *str_ptr; +- +- *str_ptr = set_value(strvec); +- if (!*str_ptr) { +- free(old_str); +- return 1; +- } +- if ((*str_ptr)[0] != '/'){ +- condlog(1, "%s line %d, %s is not an absolute path. Ignoring", +- file, line_nr, *str_ptr); +- free(*str_ptr); +- *str_ptr = old_str; +- } else +- free(old_str); +- return 0; +-} +- + static int + set_str_noslash(vector strvec, void *ptr, const char *file, int line_nr) + { +@@ -831,15 +810,6 @@ declare_hw_snprint(user_friendly_names, print_yes_no_undef) + declare_mp_handler(user_friendly_names, set_yes_no_undef) + declare_mp_snprint(user_friendly_names, print_yes_no_undef) + +-declare_def_warn_handler(bindings_file, set_path) +-declare_def_snprint(bindings_file, print_str) +- +-declare_def_warn_handler(wwids_file, set_path) +-declare_def_snprint(wwids_file, print_str) +- +-declare_def_warn_handler(prkeys_file, set_path) +-declare_def_snprint(prkeys_file, print_str) +- + declare_def_handler(retain_hwhandler, set_yes_no_undef) + declare_def_snprint_defint(retain_hwhandler, print_yes_no_undef, + DEFAULT_RETAIN_HWHANDLER) +@@ -2064,6 +2034,9 @@ declare_deprecated_handler(disable_changed_wwids, "yes") + declare_deprecated_handler(getuid_callout, "(not set)") + declare_deprecated_handler(multipath_dir, MULTIPATH_DIR) + declare_deprecated_handler(pg_timeout, "(not set)") ++declare_deprecated_handler(bindings_file, DEFAULT_BINDINGS_FILE) ++declare_deprecated_handler(wwids_file, DEFAULT_WWIDS_FILE) ++declare_deprecated_handler(prkeys_file, DEFAULT_PRKEYS_FILE) + + /* + * If you add or remove a keyword also update multipath/multipath.conf.5 +@@ -2106,9 +2079,9 @@ init_keywords(vector keywords) + install_keyword("fast_io_fail_tmo", &def_fast_io_fail_handler, &snprint_def_fast_io_fail); + install_keyword("dev_loss_tmo", &def_dev_loss_handler, &snprint_def_dev_loss); + install_keyword("eh_deadline", &def_eh_deadline_handler, &snprint_def_eh_deadline); +- install_keyword("bindings_file", &def_bindings_file_handler, &snprint_def_bindings_file); +- install_keyword("wwids_file", &def_wwids_file_handler, &snprint_def_wwids_file); +- install_keyword("prkeys_file", &def_prkeys_file_handler, &snprint_def_prkeys_file); ++ install_keyword("bindings_file", &deprecated_bindings_file_handler, &snprint_deprecated); ++ install_keyword("wwids_file", &deprecated_wwids_file_handler, &snprint_deprecated); ++ install_keyword("prkeys_file", &deprecated_prkeys_file_handler, &snprint_deprecated); + install_keyword("log_checker_err", &def_log_checker_err_handler, &snprint_def_log_checker_err); + install_keyword("reservation_key", &def_reservation_key_handler, &snprint_def_reservation_key); + install_keyword("all_tg_pt", &def_all_tg_pt_handler, &snprint_def_all_tg_pt); +diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version +index 57e50c12..8368ef7a 100644 +--- a/libmultipath/libmultipath.version ++++ b/libmultipath/libmultipath.version +@@ -43,7 +43,7 @@ LIBMPATHCOMMON_1.0.0 { + put_multipath_config; + }; + +-LIBMULTIPATH_20.0.0 { ++LIBMULTIPATH_21.0.0 { + global: + /* symbols referenced by multipath and multipathd */ + add_foreign; +@@ -121,6 +121,7 @@ global: + get_used_hwes; + get_vpd_sgio; + group_by_prio; ++ handle_bindings_file_inotify; + has_dm_info; + init_checkers; + init_config; +@@ -238,8 +239,3 @@ global: + local: + *; + }; +- +-LIBMULTIPATH_20.1.0 { +-global: +- handle_bindings_file_inotify; +-}; +diff --git a/libmultipath/prkey.c b/libmultipath/prkey.c +index a215499d..c66d293b 100644 +--- a/libmultipath/prkey.c ++++ b/libmultipath/prkey.c +@@ -157,8 +157,7 @@ static int do_prkey(int fd, char *wwid, char *keystr, int cmd) + return 0; + } + +-int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey, +- uint8_t *sa_flags) ++int get_prkey(struct multipath *mpp, uint64_t *prkey, uint8_t *sa_flags) + { + int fd; + int unused; +@@ -168,7 +167,7 @@ int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey, + if (!strlen(mpp->wwid)) + goto out; + +- fd = open_file(conf->prkeys_file, &unused, PRKEYS_FILE_HEADER); ++ fd = open_file(DEFAULT_PRKEYS_FILE, &unused, PRKEYS_FILE_HEADER); + if (fd < 0) + goto out; + ret = do_prkey(fd, mpp->wwid, keystr, PRKEY_READ); +@@ -201,7 +200,7 @@ int set_prkey(struct config *conf, struct multipath *mpp, uint64_t prkey, + sa_flags &= MPATH_F_APTPL_MASK; + } + +- fd = open_file(conf->prkeys_file, &can_write, PRKEYS_FILE_HEADER); ++ fd = open_file(DEFAULT_PRKEYS_FILE, &can_write, PRKEYS_FILE_HEADER); + if (fd < 0) + goto out; + if (!can_write) { +diff --git a/libmultipath/prkey.h b/libmultipath/prkey.h +index a16de106..43afd5e4 100644 +--- a/libmultipath/prkey.h ++++ b/libmultipath/prkey.h +@@ -16,9 +16,8 @@ + int print_reservation_key(struct strbuf *buff, + struct be64 key, uint8_t flags, int source); + int parse_prkey_flags(const char *ptr, uint64_t *prkey, uint8_t *flags); +-int set_prkey(struct config *conf, struct multipath *mpp, uint64_t prkey, +- uint8_t sa_flags); +-int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey, +- uint8_t *sa_flags); ++int set_prkey(struct config *conf, struct multipath *mpp, ++ uint64_t prkey, uint8_t sa_flags); ++int get_prkey(struct multipath *mpp, uint64_t *prkey, uint8_t *sa_flags); + + #endif /* _PRKEY_H */ +diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c +index 354e883f..44241e2a 100644 +--- a/libmultipath/propsel.c ++++ b/libmultipath/propsel.c +@@ -401,8 +401,7 @@ int select_alias(struct config *conf, struct multipath * mp) + + select_alias_prefix(conf, mp); + +- mp->alias = get_user_friendly_alias(mp->wwid, conf->bindings_file, +- mp->alias_old, mp->alias_prefix, ++ mp->alias = get_user_friendly_alias(mp->wwid, mp->alias_old, mp->alias_prefix, + conf->bindings_read_only); + + if (mp->alias && !strncmp(mp->alias, mp->alias_old, WWID_SIZE)) +@@ -992,7 +991,7 @@ int select_reservation_key(struct config *conf, struct multipath *mp) + out: + if (mp->prkey_source == PRKEY_SOURCE_FILE) { + from_file = " (from prkeys file)"; +- if (get_prkey(conf, mp, &prkey, &mp->sa_flags) != 0) ++ if (get_prkey(mp, &prkey, &mp->sa_flags) != 0) + put_be64(mp->reservation_key, 0); + else + put_be64(mp->reservation_key, prkey); +diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c +index 89bb60ca..591cd09b 100644 +--- a/libmultipath/wwids.c ++++ b/libmultipath/wwids.c +@@ -94,12 +94,8 @@ replace_wwids(vector mp) + struct multipath * mpp; + size_t len; + int ret = -1; +- struct config *conf; + +- conf = get_multipath_config(); +- pthread_cleanup_push(put_multipath_config, conf); +- fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER); +- pthread_cleanup_pop(1); ++ fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER); + if (fd < 0) + goto out; + +@@ -200,7 +196,6 @@ remove_wwid(char *wwid) { + int len, can_write; + char *str; + int ret = -1; +- struct config *conf; + + len = strlen(wwid) + 4; /* two slashes the newline and a zero byte */ + str = malloc(len); +@@ -216,10 +211,7 @@ remove_wwid(char *wwid) { + goto out; + } + condlog(3, "removing line '%s' from wwids file", str); +- conf = get_multipath_config(); +- pthread_cleanup_push(put_multipath_config, conf); +- fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER); +- pthread_cleanup_pop(1); ++ fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER); + + if (fd < 0) { + ret = -1; +@@ -244,12 +236,8 @@ check_wwids_file(char *wwid, int write_wwid) + { + int fd, can_write, found, ret; + FILE *f; +- struct config *conf; + +- conf = get_multipath_config(); +- pthread_cleanup_push(put_multipath_config, conf); +- fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER); +- pthread_cleanup_pop(1); ++ fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER); + if (fd < 0) + return -1; + +diff --git a/multipath/main.c b/multipath/main.c +index b91289e8..9e1c5052 100644 +--- a/multipath/main.c ++++ b/multipath/main.c +@@ -856,7 +856,7 @@ main (int argc, char *argv[]) + libmp_verbosity = atoi(optarg); + break; + case 'b': +- conf->bindings_file = strdup(optarg); ++ condlog(1, "option -b ignored"); + break; + case 'B': + conf->bindings_read_only = 1; +diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in +index 20df2232..d320a88f 100644 +--- a/multipath/multipath.conf.5.in ++++ b/multipath/multipath.conf.5.in +@@ -794,35 +794,28 @@ The default is: \fB\fR + . + .TP + .B bindings_file +-(Deprecated) This option is deprecated, and will be removed in a future release. +-The full pathname of the binding file to be used when the user_friendly_names +-option is set. ++(Deprecated) This option is not supported any more, and will be ignored. + .RS + .TP +-The default is: \fB@STATE_DIR@/bindings\fR ++The compiled-in value is: \fB@STATE_DIR@/bindings\fR + .RE + . + . + .TP + .B wwids_file +-(Deprecated) This option is deprecated, and will be removed in a future release. +-The full pathname of the WWIDs file, which is used by multipath to keep track +-of the WWIDs for LUNs it has created multipath devices on in the past. ++(Deprecated) This option is not supported any more, and will be ignored. + .RS + .TP +-The default is: \fB@STATE_DIR@/wwids\fR ++The compiled-in value is: \fB@STATE_DIR@/wwids\fR + .RE + . + . + .TP + .B prkeys_file +-(Deprecated) This option is deprecated, and will be removed in a future release. +-The full pathname of the prkeys file, which is used by multipathd to keep +-track of the persistent reservation key used for a specific WWID, when +-\fIreservation_key\fR is set to \fBfile\fR. ++(Deprecated) This option is not supported any more, and will be ignored. + .RS + .TP +-The default is: \fB@STATE_DIR@/prkeys\fR ++The compiled-in value is: \fB@STATE_DIR@/prkeys\fR + .RE + . + . +@@ -989,6 +982,10 @@ The default is: \fB\fR + .TP + .B config_dir + (Deprecated) This option is not supported any more, and the value is ignored. ++.RS ++.TP ++The compiled-in value is: \fB@CONFIGDIR@\fR ++.RE + . + . + .TP +diff --git a/multipathd/uxlsnr.c b/multipathd/uxlsnr.c +index d1f8f234..4d6f258c 100644 +--- a/multipathd/uxlsnr.c ++++ b/multipathd/uxlsnr.c +@@ -203,7 +203,6 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds, + int dir_reset = 0; + int conf_reset = 0; + int mp_reset = 0; +- char *bindings_file __attribute__((cleanup(cleanup_charp))) = NULL; + + if (notify_fd == -1) + return; +@@ -221,7 +220,6 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds, + if (wds->mp_wd == -1) + mp_reset = 1; + } +- bindings_file = strdup(conf->bindings_file); + put_multipath_config(conf); + + if (dir_reset) { +@@ -242,17 +240,12 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds, + if (wds->conf_wd == -1) + condlog(3, "didn't set up notifications on /etc/multipath.conf: %m"); + } +- if (mp_reset && bindings_file) { +- char *slash = strrchr(bindings_file, '/'); +- +- if (slash && slash > bindings_file) { +- *slash = '\0'; +- wds->mp_wd = inotify_add_watch(notify_fd, bindings_file, +- IN_MOVED_TO|IN_ONLYDIR); +- if (wds->mp_wd == -1) ++ if (mp_reset) { ++ wds->mp_wd = inotify_add_watch(notify_fd, STATE_DIR, ++ IN_MOVED_TO|IN_ONLYDIR); ++ if (wds->mp_wd == -1) + condlog(3, "didn't set up notifications on %s: %m", +- bindings_file); +- } ++ STATE_DIR); + } + } + +diff --git a/tests/alias.c b/tests/alias.c +index 94df36d8..f893d174 100644 +--- a/tests/alias.c ++++ b/tests/alias.c +@@ -1264,10 +1264,10 @@ static void al_a(void **state) + will_return(__wrap_write, ln); + will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); + will_return(__wrap_rename, 0); +- expect_condlog(1, "updated bindings file foo"); ++ expect_condlog(1, "updated bindings file " DEFAULT_BINDINGS_FILE); + expect_condlog(3, NEW_STR("MPATHa", "WWIDa")); + +- alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); ++ alias = allocate_binding("WWIDa", 1, "MPATH"); + assert_ptr_not_equal(alias, NULL); + assert_string_equal(alias, "MPATHa"); + check_bindings_size(1); +@@ -1283,10 +1283,10 @@ static void al_zz(void **state) + will_return(__wrap_write, ln); + will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); + will_return(__wrap_rename, 0); +- expect_condlog(1, "updated bindings file foo"); ++ expect_condlog(1, "updated bindings file " DEFAULT_BINDINGS_FILE); + expect_condlog(3, NEW_STR("MPATHzz", "WWIDzz")); + +- alias = allocate_binding("foo", "WWIDzz", 26*26 + 26, "MPATH"); ++ alias = allocate_binding("WWIDzz", 26*26 + 26, "MPATH"); + assert_ptr_not_equal(alias, NULL); + assert_string_equal(alias, "MPATHzz"); + check_bindings_size(1); +@@ -1298,7 +1298,7 @@ static void al_0(void **state) + char *alias; + + expect_condlog(0, "allocate_binding: cannot allocate new binding for id 0\n"); +- alias = allocate_binding(0, "WWIDa", 0, "MPATH"); ++ alias = allocate_binding("WWIDa", 0, "MPATH"); + assert_ptr_equal(alias, NULL); + check_bindings_size(0); + } +@@ -1308,7 +1308,7 @@ static void al_m2(void **state) + char *alias; + + expect_condlog(0, "allocate_binding: cannot allocate new binding for id -2\n"); +- alias = allocate_binding(0, "WWIDa", -2, "MPATH"); ++ alias = allocate_binding("WWIDa", -2, "MPATH"); + assert_ptr_equal(alias, NULL); + check_bindings_size(0); + } +@@ -1325,10 +1325,10 @@ static void al_write_partial(void **state) + will_return(__wrap_write, ln + sizeof(ln) - 2); + will_return(__wrap_write, 1); + will_return(__wrap_rename, 0); +- expect_condlog(1, "updated bindings file foo"); ++ expect_condlog(1, "updated bindings file " DEFAULT_BINDINGS_FILE); + expect_condlog(3, "Created new binding [MPATHa] for WWID [WWIDa]\n"); + +- alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); ++ alias = allocate_binding("WWIDa", 1, "MPATH"); + assert_ptr_not_equal(alias, NULL); + assert_string_equal(alias, "MPATHa"); + check_bindings_size(1); +@@ -1350,7 +1350,7 @@ static void al_write_short(void **state) + expect_condlog(1, "failed to write new bindings file"); + expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa"); + +- alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); ++ alias = allocate_binding("WWIDa", 1, "MPATH"); + assert_ptr_equal(alias, NULL); + check_bindings_size(0); + } +@@ -1366,7 +1366,7 @@ static void al_write_err(void **state) + expect_condlog(1, "failed to write new bindings file"); + expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa"); + +- alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); ++ alias = allocate_binding("WWIDa", 1, "MPATH"); + assert_ptr_equal(alias, NULL); + check_bindings_size(0); + } +@@ -1383,7 +1383,7 @@ static void al_rename_err(void **state) + + expect_condlog(0, "update_bindings_file: rename: Read-only file system"); + expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa"); +- alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); ++ alias = allocate_binding("WWIDa", 1, "MPATH"); + assert_ptr_equal(alias, NULL); + check_bindings_size(0); + } +@@ -1415,7 +1415,7 @@ static int test_allocate_binding(void) + strlen(BINDINGS_FILE_HEADER) + (len) + strlen(ln)); \ + will_return(__wrap_rename, err); \ + if (err == 0) { \ +- expect_condlog(1, "updated bindings file x\n"); \ ++ expect_condlog(1, "updated bindings file " DEFAULT_BINDINGS_FILE); \ + expect_condlog(3, NEW_STR(alias, wwid)); \ + } else { \ + expect_condlog(0, "update_bindings_file: rename: " msg "\n"); \ +@@ -1441,7 +1441,7 @@ static void gufa_empty_new_rw(void **state) { + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + + mock_allocate_binding("MPATHa", "WWID0"); +- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false); ++ alias = get_user_friendly_alias("WWID0", "", "MPATH", false); + assert_string_equal(alias, "MPATHa"); + free(alias); + } +@@ -1454,7 +1454,7 @@ static void gufa_empty_new_ro_1(void **state) { + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + mock_allocate_binding_err("MPATHa", "WWID0", -EROFS, "Read-only file system"); + +- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false); ++ alias = get_user_friendly_alias("WWID0", "", "MPATH", false); + assert_ptr_equal(alias, NULL); + } + +@@ -1465,7 +1465,7 @@ static void gufa_empty_new_ro_2(void **state) { + expect_condlog(3, NOMATCH_WWID_STR("WWID0")); + mock_unused_alias("MPATHa"); + +- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); ++ alias = get_user_friendly_alias("WWID0", "", "MPATH", true); + assert_ptr_equal(alias, NULL); + } + +@@ -1477,7 +1477,7 @@ static void gufa_match_a_unused(void **state) { + mock_unused_alias("MPATHa"); + expect_condlog(3, EXISTING_STR("MPATHa", "WWID0")); + +- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); ++ alias = get_user_friendly_alias("WWID0", "", "MPATH", true); + assert_string_equal(alias, "MPATHa"); + free(alias); + } +@@ -1490,7 +1490,7 @@ static void gufa_match_a_self(void **state) { + mock_self_alias("MPATHa", "WWID0"); + expect_condlog(3, EXISTING_STR("MPATHa", "WWID0")); + +- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); ++ alias = get_user_friendly_alias("WWID0", "", "MPATH", true); + assert_string_equal(alias, "MPATHa"); + free(alias); + } +@@ -1503,7 +1503,7 @@ static void gufa_match_a_used(void **state) { + expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); + mock_used_alias("MPATHa", "WWID0"); + +- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); ++ alias = get_user_friendly_alias("WWID0", "", "MPATH", true); + assert_ptr_equal(alias, NULL); + } + +@@ -1518,7 +1518,7 @@ static void gufa_nomatch_a_c(void **state) { + + mock_allocate_binding_len("MPATHb", "WWID1", strlen(bindings)); + +- alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false); ++ alias = get_user_friendly_alias("WWID1", "", "MPATH", false); + assert_string_equal(alias, "MPATHb"); + free(alias); + } +@@ -1534,7 +1534,7 @@ static void gufa_nomatch_c_a(void **state) { + + mock_allocate_binding_len("MPATHb", "WWID1", sizeof(bindings) - 1); + +- alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false); ++ alias = get_user_friendly_alias("WWID1", "", "MPATH", false); + assert_string_equal(alias, "MPATHb"); + free(alias); + } +@@ -1550,7 +1550,7 @@ static void gufa_nomatch_c_b(void **state) { + + mock_allocate_binding_len("MPATHa", "WWID0", sizeof(bindings) - 1); + +- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false); ++ alias = get_user_friendly_alias("WWID0", "", "MPATH", false); + assert_string_equal(alias, "MPATHa"); + free(alias); + } +@@ -1567,7 +1567,7 @@ static void gufa_nomatch_c_b_used(void **state) { + + mock_allocate_binding_len("MPATHd", "WWID4", sizeof(bindings) - 1); + +- alias = get_user_friendly_alias("WWID4", "x", "", "MPATH", false); ++ alias = get_user_friendly_alias("WWID4", "", "MPATH", false); + assert_string_equal(alias, "MPATHd"); + free(alias); + } +@@ -1584,7 +1584,7 @@ static void gufa_nomatch_b_f_a(void **state) { + + mock_allocate_binding_len("MPATHc", "WWID7", sizeof(bindings) - 1); + +- alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false); ++ alias = get_user_friendly_alias("WWID7", "", "MPATH", false); + assert_string_equal(alias, "MPATHc"); + free(alias); + } +@@ -1599,7 +1599,7 @@ static void gufa_nomatch_b_aa_a(void **state) { + mock_unused_alias("MPATHab"); + mock_allocate_binding_len("MPATHab", "WWID28", get_strbuf_len(&buf)); + +- alias = get_user_friendly_alias("WWID28", "x", "", "MPATH", false); ++ alias = get_user_friendly_alias("WWID28", "", "MPATH", false); + assert_string_equal(alias, "MPATHab"); + free(alias); + } +@@ -1616,7 +1616,7 @@ static void gufa_nomatch_b_f_a_sorted(void **state) { + + mock_allocate_binding_len("MPATHc", "WWID7", sizeof(bindings) - 1); + +- alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false); ++ alias = get_user_friendly_alias("WWID7", "", "MPATH", false); + assert_string_equal(alias, "MPATHc"); + free(alias); + } +@@ -1632,7 +1632,7 @@ static void gufa_old_empty(void **state) { + mock_allocate_binding("MPATHz", "WWID0"); + expect_condlog(2, ALLOC_STR("MPATHz", "WWID0")); + +- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); ++ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false); + assert_string_equal(alias, "MPATHz"); + free(alias); + } +@@ -1644,7 +1644,7 @@ static void gufa_old_match(void **state) { + "MPATHz WWID0"); + expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID0")); + +- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); ++ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false); + assert_string_equal(alias, "MPATHz"); + free(alias); + } +@@ -1661,7 +1661,7 @@ static void gufa_old_match_other(void **state) { + + mock_allocate_binding_len("MPATHa", "WWID0", sizeof(bindings) - 1); + +- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); ++ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false); + assert_string_equal(alias, "MPATHa"); + free(alias); + } +@@ -1678,7 +1678,7 @@ static void gufa_old_match_other_used(void **state) { + mock_unused_alias("MPATHb"); + + mock_allocate_binding_len("MPATHb", "WWID0", sizeof(bindings) - 1); +- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); ++ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false); + assert_string_equal(alias, "MPATHb"); + free(alias); + } +@@ -1695,7 +1695,7 @@ static void gufa_old_match_other_wwidmatch(void **state) { + mock_unused_alias("MPATHc"); + expect_condlog(3, EXISTING_STR("MPATHc", "WWID2")); + +- alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false); ++ alias = get_user_friendly_alias("WWID2", "MPATHz", "MPATH", false); + assert_string_equal(alias, "MPATHc"); + free(alias); + } +@@ -1711,7 +1711,7 @@ static void gufa_old_match_other_wwidmatch_used(void **state) { + expect_condlog(3, FOUND_STR("MPATHc", "WWID2")); + mock_used_alias("MPATHc", "WWID2"); + +- alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false); ++ alias = get_user_friendly_alias("WWID2", "MPATHz", "MPATH", false); + assert_ptr_equal(alias, NULL); + } + +@@ -1725,7 +1725,7 @@ static void gufa_old_nomatch_wwidmatch(void **state) { + mock_unused_alias("MPATHa"); + expect_condlog(3, EXISTING_STR("MPATHa", "WWID0")); + +- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); ++ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false); + assert_string_equal(alias, "MPATHa"); + free(alias); + } +@@ -1739,7 +1739,7 @@ static void gufa_old_nomatch_wwidmatch_used(void **state) { + expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); + mock_used_alias("MPATHa", "WWID0"); + +- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); ++ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false); + assert_ptr_equal(alias, NULL); + } + +@@ -1754,7 +1754,7 @@ static void gufa_old_nomatch_nowwidmatch(void **state) { + mock_allocate_binding_len("MPATHz", "WWID0", sizeof(bindings) - 1); + expect_condlog(2, ALLOC_STR("MPATHz", "WWID0")); + +- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); ++ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false); + assert_string_equal(alias, "MPATHz"); + free(alias); + } diff --git a/0038-libmultipath-avoid-Warray-bounds-error-in-uatomic-op.patch b/0038-libmultipath-avoid-Warray-bounds-error-in-uatomic-op.patch new file mode 100644 index 0000000..269efcf --- /dev/null +++ b/0038-libmultipath-avoid-Warray-bounds-error-in-uatomic-op.patch @@ -0,0 +1,158 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 12 Sep 2023 11:54:47 +0200 +Subject: [PATCH] libmultipath: avoid -Warray-bounds error in uatomic + operations + +The use of uatomic_xchg() in alias.c causes a -Warray-bounds error +on distributions using gcc 12, such as Fedora 37. This is a similar +error to 2534c4f ("libmultipath: avoid -Warray-bounds error with gcc +12 and musl libc"). This happens only with liburcu 0.13 and earlier, +and only with certain gcc versions. See liburcu commit 835b9ab +("Fix: x86 and s390 uatomic: __hp() macro warning with gcc 11"). + +Enhance the fix for 2534c4f by a adding a workaround for uatomic_xchg(), +and introduce the macro URCU_VERSION (originally only used for multipathd) +globally. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + Makefile.inc | 2 +- + create-config.mk | 5 +++++ + libmultipath/alias.c | 5 +++-- + libmultipath/lock.h | 21 +++++++++++++-------- + multipathd/Makefile | 2 -- + 5 files changed, 22 insertions(+), 13 deletions(-) + +diff --git a/Makefile.inc b/Makefile.inc +index 6e384e68..04bfa56e 100644 +--- a/Makefile.inc ++++ b/Makefile.inc +@@ -95,7 +95,7 @@ OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4 + WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implicit-int \ + -Werror=implicit-function-declaration -Werror=format-security \ + $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) +-CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) \ ++CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \ + -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \ + -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \ + -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DSTATE_DIR=\"$(statedir)\" \ +diff --git a/create-config.mk b/create-config.mk +index d1255971..4d318b96 100644 +--- a/create-config.mk ++++ b/create-config.mk +@@ -73,6 +73,10 @@ TEST_URCU_TYPE_LIMITS = $(shell \ + $(CC) -c -Werror=type-limits -o /dev/null -xc - 2>/dev/null \ + || echo -Wno-type-limits ) + ++URCU_VERSION = $(shell \ ++ $(PKG_CONFIG) --modversion liburcu 2>/dev/null | \ ++ awk -F. '{ printf("-DURCU_VERSION=0x%06x", 256 * ( 256 * $$1 + $$2) + $$3); }') ++ + DEFINES := + + ifneq ($(call check_func,dm_task_no_flush,$(devmapper_incdir)/libdevmapper.h),0) +@@ -168,6 +172,7 @@ $(TOPDIR)/config.mk: $(multipathdir)/autoconfig.h + @echo creating $@ + @echo "FPIN_SUPPORT := $(FPIN_SUPPORT)" >$@ + @echo "FORTIFY_OPT := $(FORTIFY_OPT)" >>$@ ++ @echo "D_URCU_VERSION := $(call URCU_VERSION)" >>$@ + @echo "SYSTEMD := $(SYSTEMD)" >>$@ + @echo "ANA_SUPPORT := $(ANA_SUPPORT)" >>$@ + @echo "STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)" >>$@ +diff --git a/libmultipath/alias.c b/libmultipath/alias.c +index e5d3f151..74431f3f 100644 +--- a/libmultipath/alias.c ++++ b/libmultipath/alias.c +@@ -24,6 +24,7 @@ + #include "devmapper.h" + #include "strbuf.h" + #include "time-util.h" ++#include "lock.h" + + /* + * significant parts of this file were taken from iscsi-bindings.c of the +@@ -300,7 +301,7 @@ void handle_bindings_file_inotify(const struct inotify_event *event) + pthread_mutex_unlock(×tamp_mutex); + + if (changed) { +- uatomic_xchg(&bindings_file_changed, 1); ++ uatomic_xchg_int(&bindings_file_changed, 1); + condlog(3, "%s: bindings file must be re-read, new timestamp: %ld.%06ld", + __func__, (long)ts.tv_sec, (long)ts.tv_nsec / 1000); + } else +@@ -775,7 +776,7 @@ static int _read_bindings_file(const struct config *conf, Bindings *bindings, + int rc = 0, ret, fd; + FILE *file; + struct stat st; +- int has_changed = uatomic_xchg(&bindings_file_changed, 0); ++ int has_changed = uatomic_xchg_int(&bindings_file_changed, 0); + + if (!force) { + if (!has_changed) { +diff --git a/libmultipath/lock.h b/libmultipath/lock.h +index 9814be76..ac80d1d8 100644 +--- a/libmultipath/lock.h ++++ b/libmultipath/lock.h +@@ -13,15 +13,20 @@ struct mutex_lock { + int waiters; /* uatomic access only */ + }; + +-#if !defined(__GLIBC__) && defined(__GNUC__) && __GNUC__ == 12 ++static inline void init_lock(struct mutex_lock *a) ++{ ++ pthread_mutex_init(&a->mutex, NULL); ++ uatomic_set(&a->waiters, 0); ++} ++ ++#if defined(__GNUC__) && __GNUC__ == 12 && URCU_VERSION < 0xe00 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Warray-bounds" + #endif + +-static inline void init_lock(struct mutex_lock *a) ++static inline int uatomic_xchg_int(int *ptr, int val) + { +- pthread_mutex_init(&a->mutex, NULL); +- uatomic_set(&a->waiters, 0); ++ return uatomic_xchg(ptr, val); + } + + static inline void lock(struct mutex_lock *a) +@@ -31,6 +36,10 @@ static inline void lock(struct mutex_lock *a) + uatomic_dec(&a->waiters); + } + ++#if defined(__GNUC__) && __GNUC__ == 12 && URCU_VERSION < 0xe00 ++#pragma GCC diagnostic pop ++#endif ++ + static inline int trylock(struct mutex_lock *a) + { + return pthread_mutex_trylock(&a->mutex); +@@ -51,10 +60,6 @@ static inline bool lock_has_waiters(struct mutex_lock *a) + return (uatomic_read(&a->waiters) > 0); + } + +-#if !defined(__GLIBC__) && defined(__GNUC__) && __GNUC__ == 12 +-#pragma GCC diagnostic pop +-#endif +- + #define lock_cleanup_pop(a) pthread_cleanup_pop(1) + + void cleanup_lock (void * data); +diff --git a/multipathd/Makefile b/multipathd/Makefile +index cdba3db1..0ba6ecb7 100644 +--- a/multipathd/Makefile ++++ b/multipathd/Makefile +@@ -5,8 +5,6 @@ CLI := multipathc + MANPAGES := multipathd.8 + + CPPFLAGS += -I$(multipathdir) -I$(mpathutildir) -I$(mpathpersistdir) -I$(mpathcmddir) -I$(thirdpartydir) \ +- $(shell $(PKG_CONFIG) --modversion liburcu 2>/dev/null | \ +- awk -F. '{ printf("-DURCU_VERSION=0x%06x", 256 * ( 256 * $$1 + $$2) + $$3); }') \ + -DBINDIR='"$(bindir)"' $(SYSTEMD_CPPFLAGS) + + # diff --git a/0039-multipath-tools-fix-spelling.patch b/0039-multipath-tools-fix-spelling.patch new file mode 100644 index 0000000..c0c86f9 --- /dev/null +++ b/0039-multipath-tools-fix-spelling.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Xose Vazquez Perez +Date: Fri, 15 Sep 2023 22:22:06 +0200 +Subject: [PATCH] multipath-tools: fix spelling + +Cc: Martin Wilck +Cc: Benjamin Marzinski +Cc: Christophe Varoqui +Cc: DM-DEVEL ML +Signed-off-by: Xose Vazquez Perez +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + README.md | 4 ++-- + multipath/multipath.conf.5.in | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/README.md b/README.md +index 679e55bf..524c9fb1 100644 +--- a/README.md ++++ b/README.md +@@ -92,7 +92,7 @@ The following variables can be passed to the `make` command line: + The default is `$(prefix)/$(LIB)/multipath`, where `$(LIB)` is `lib64` on + systems that have `/lib64`, and `lib` otherwise. + * `configfile="/some/path`": The path to the main configuration file. +- The defalt is `$(etc_prefix)/etc/multipath.conf`. ++ The default is `$(etc_prefix)/etc/multipath.conf`. + * `configdir="/some/path"` : directory to search for additional configuration files. + This used to be the run-time option `config_dir` in earlier versions. + The default is `$(etc_prefix)/etc/multipath/conf.d`. +@@ -141,7 +141,7 @@ The following variables can be passed to the `make` command line: + found on the build system, and `/lib` otherwise. + + The options `configdir`, `plugindir`, `configfile`, and `statedir` above can +-be used for setting indvidual paths where the `prefix` variables don't provide ++be used for setting individual paths where the `prefix` variables don't provide + sufficient control. See `Makefile.inc` for even more fine-grained control. + + [^systemd]: Some systemd installations use separate `prefix` and `rootprefix`. +diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in +index d320a88f..226d0019 100644 +--- a/multipath/multipath.conf.5.in ++++ b/multipath/multipath.conf.5.in +@@ -36,7 +36,7 @@ Files ending in \fI.conf\fR in this directory are read + in alphabetical order, after reading \fI@CONFIGFILE@\fR. + They use the same syntax as \fI@CONFIGFILE@\fR itself, + and support all sections and keywords. If a keyword occurs in the same section +-in multiple files, the last occurence will take precedence over all others. ++in multiple files, the last occurrence will take precedence over all others. + . + . + .\" ---------------------------------------------------------------------------- diff --git a/0040-multipathd-Added-support-to-handle-FPIN-Li-events-fo.patch b/0040-multipathd-Added-support-to-handle-FPIN-Li-events-fo.patch new file mode 100644 index 0000000..7ed50a3 --- /dev/null +++ b/0040-multipathd-Added-support-to-handle-FPIN-Li-events-fo.patch @@ -0,0 +1,300 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muneendra +Date: Wed, 20 Sep 2023 20:41:15 -0700 +Subject: [PATCH] multipathd: Added support to handle FPIN-Li events for + FC-NVMe + + This patch adds the support to handle FPIN-Li for FC-NVMe. + On receiving the FPIN-Li events this patch moves the devices paths + which are affected due to link integrity to marginal path groups. + The paths which are set to marginal path group will be unset + on receiving the RSCN events + +(mwilck: minor compile fix for 32-bit architectures) + +Signed-off-by: Muneendra +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + multipathd/fpin_handlers.c | 206 +++++++++++++++++++++++++++---------- + 1 file changed, 151 insertions(+), 55 deletions(-) + +diff --git a/multipathd/fpin_handlers.c b/multipathd/fpin_handlers.c +index aa0f63c9..be087ca0 100644 +--- a/multipathd/fpin_handlers.c ++++ b/multipathd/fpin_handlers.c +@@ -60,18 +60,15 @@ static void _udev_device_unref(void *p) + + + /*set/unset the path state to marginal*/ +-static int fpin_set_pathstate(struct path *pp, bool set) ++static void fpin_set_pathstate(struct path *pp, bool set) + { + const char *action = set ? "set" : "unset"; + +- if (!pp || !pp->mpp || !pp->mpp->alias) +- return -1; +- +- condlog(3, "\n%s: %s marginal path %s (fpin)", +- action, pp->mpp->alias, pp->dev_t); ++ condlog(3, "%s: %s marginal path %s (fpin)", ++ pp->mpp ? pp->mpp->alias : "orphan", action, pp->dev_t); + pp->marginal = set; +- pp->mpp->fpin_must_reload = true; +- return 0; ++ if (pp->mpp) ++ pp->mpp->fpin_must_reload = true; + } + + /* This will unset marginal state of a device*/ +@@ -82,14 +79,14 @@ static void fpin_path_unsetmarginal(char *devname, struct vectors *vecs) + pp = find_path_by_dev(vecs->pathvec, devname); + if (!pp) + pp = find_path_by_devt(vecs->pathvec, devname); +- +- fpin_set_pathstate(pp, false); ++ if (pp) ++ fpin_set_pathstate(pp, false); + } + + /*This will set the marginal state of a device*/ +-static int fpin_path_setmarginal(struct path *pp) ++static void fpin_path_setmarginal(struct path *pp) + { +- return fpin_set_pathstate(pp, true); ++ fpin_set_pathstate(pp, true); + } + + /* Unsets all the devices in the list from marginal state */ +@@ -183,8 +180,8 @@ static void fpin_set_rport_marginal(struct udev_device *rport_dev) + udev_device_get_syspath(rport_dev)); + } + +-/*Add the marginal devices info into the list*/ +-static void ++/*Add the marginal devices info into the list and return 0 on success*/ ++static int + fpin_add_marginal_dev_info(uint32_t host_num, char *devname) + { + struct marginal_dev_list *newdev = NULL; +@@ -199,65 +196,160 @@ fpin_add_marginal_dev_info(uint32_t host_num, char *devname) + list_add_tail(&(newdev->node), + &fpin_li_marginal_dev_list_head); + pthread_mutex_unlock(&fpin_li_marginal_dev_mutex); +- } ++ } else ++ return -ENOMEM; ++ return 0; + } + + /* +- * This function goes through the vecs->pathvec, and for +- * each path, check that the host number, +- * the target WWPN associated with the path matches +- * with the els wwpn and sets the path and port state to ++ * This function compares Transport Address Controller Port pn, ++ * Host Transport Address Controller Port pn with the els wwpn ,attached_wwpn ++ * and return 1 (match) or 0 (no match) or a negative error code ++ */ ++static int extract_nvme_addresses_chk_path_pwwn(const char *address, ++ uint64_t els_wwpn, uint64_t els_attached_wwpn) ++ ++{ ++ uint64_t traddr; ++ uint64_t host_traddr; ++ ++ /* ++ * Find the position of "traddr=" and "host_traddr=" ++ * and the address will be in the below format ++ * "traddr=nn-0x200400110dff9400:pn-0x200400110dff9400, ++ * host_traddr=nn-0x200400110dff9400:pn-0x200400110dff9400" ++ */ ++ const char *traddr_start = strstr(address, "traddr="); ++ const char *host_traddr_start = strstr(address, "host_traddr="); ++ ++ if (!traddr_start || !host_traddr_start) ++ return -EINVAL; ++ ++ /* Extract traddr pn */ ++ if (sscanf(traddr_start, "traddr=nn-%*[^:]:pn-%" SCNx64, &traddr) != 1) ++ return -EINVAL; ++ ++ /* Extract host_traddr pn*/ ++ if (sscanf(host_traddr_start, "host_traddr=nn-%*[^:]:pn-%" SCNx64, ++ &host_traddr) != 1) ++ return -EINVAL; ++ condlog(4, "traddr 0x%" PRIx64 " hosttraddr 0x%" PRIx64 " els_wwpn 0x%" ++ PRIx64" els_host_traddr 0x%" PRIx64, ++ traddr, host_traddr, ++ els_wwpn, els_attached_wwpn); ++ if ((host_traddr == els_attached_wwpn) && (traddr == els_wwpn)) ++ return 1; ++ return 0; ++} ++ ++/* ++ * This function check that the Transport Address Controller Port pn, ++ * Host Transport Address Controller Port pn associated with the path matches ++ * with the els wwpn ,attached_wwpn and sets the path state to + * Marginal + */ +-static int fpin_chk_wwn_setpath_marginal(uint16_t host_num, struct vectors *vecs, ++static void fpin_check_set_nvme_path_marginal(uint16_t host_num, struct path *pp, ++ uint64_t els_wwpn, uint64_t attached_wwpn) ++{ ++ struct udev_device *ctl = NULL; ++ const char *address = NULL; ++ int ret = 0; ++ ++ ctl = udev_device_get_parent_with_subsystem_devtype(pp->udev, "nvme", NULL); ++ if (ctl == NULL) { ++ condlog(2, "%s: No parent device for ", pp->dev); ++ return; ++ } ++ address = udev_device_get_sysattr_value(ctl, "address"); ++ if (!address) { ++ condlog(2, "%s: unable to get the address ", pp->dev); ++ return; ++ } ++ condlog(4, "\n address %s: dev :%s\n", address, pp->dev); ++ ret = extract_nvme_addresses_chk_path_pwwn(address, els_wwpn, attached_wwpn); ++ if (ret <= 0) ++ return; ++ ret = fpin_add_marginal_dev_info(host_num, pp->dev); ++ if (ret < 0) ++ return; ++ fpin_path_setmarginal(pp); ++} ++ ++/* ++ * This function check the host number, the target WWPN ++ * associated with the path matches with the els wwpn and ++ * sets the path and port state to Marginal ++ */ ++static void fpin_check_set_scsi_path_marginal(uint16_t host_num, struct path *pp, + uint64_t els_wwpn) + { +- struct path *pp; +- struct multipath *mpp; +- int i, k; + char rport_id[42]; + const char *value = NULL; + struct udev_device *rport_dev = NULL; + uint64_t wwpn; + int ret = 0; ++ sprintf(rport_id, "rport-%d:%d-%d", ++ pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id); ++ rport_dev = udev_device_new_from_subsystem_sysname(udev, ++ "fc_remote_ports", rport_id); ++ if (!rport_dev) { ++ condlog(2, "%s: No fc_remote_port device for '%s'", pp->dev, ++ rport_id); ++ return; ++ } ++ pthread_cleanup_push(_udev_device_unref, rport_dev); ++ value = udev_device_get_sysattr_value(rport_dev, "port_name"); ++ if (!value) ++ goto unref; ++ ++ wwpn = strtol(value, NULL, 16); ++ /* ++ * If the port wwpn matches sets the path and port state ++ * to marginal ++ */ ++ if (wwpn == els_wwpn) { ++ ret = fpin_add_marginal_dev_info(host_num, pp->dev); ++ if (ret < 0) ++ goto unref; ++ fpin_path_setmarginal(pp); ++ fpin_set_rport_marginal(rport_dev); ++ } ++unref: ++ pthread_cleanup_pop(1); ++ return; ++ ++} ++ ++/* ++ * This function goes through the vecs->pathvec, and for ++ * each path, it checks and sets the path state to marginal ++ * if the path's associated port wwpn ,hostnum matches with ++ * els wwnpn ,attached_wwpn ++ */ ++static int fpin_chk_wwn_setpath_marginal(uint16_t host_num, struct vectors *vecs, ++ uint64_t els_wwpn, uint64_t attached_wwpn) ++{ ++ struct path *pp; ++ struct multipath *mpp; ++ int i, k; ++ int ret = 0; + + pthread_cleanup_push(cleanup_lock, &vecs->lock); + lock(&vecs->lock); + pthread_testcancel(); + + vector_foreach_slot(vecs->pathvec, pp, k) { +- /* Checks the host number and also for the SCSI FCP */ +- if (pp->bus != SYSFS_BUS_SCSI || pp->sg_id.proto_id != SCSI_PROTOCOL_FCP || host_num != pp->sg_id.host_no) ++ if (!pp->mpp) + continue; +- sprintf(rport_id, "rport-%d:%d-%d", +- pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id); +- rport_dev = udev_device_new_from_subsystem_sysname(udev, +- "fc_remote_ports", rport_id); +- if (!rport_dev) { +- condlog(2, "%s: No fc_remote_port device for '%s'", pp->dev, +- rport_id); +- continue; +- } +- pthread_cleanup_push(_udev_device_unref, rport_dev); +- value = udev_device_get_sysattr_value(rport_dev, "port_name"); +- if (!value) +- goto unref; +- +- if (value) +- wwpn = strtol(value, NULL, 16); +- /* +- * If the port wwpn matches sets the path and port state +- * to marginal +- */ +- if (wwpn == els_wwpn) { +- ret = fpin_path_setmarginal(pp); +- if (ret < 0) +- goto unref; +- fpin_set_rport_marginal(rport_dev); +- fpin_add_marginal_dev_info(host_num, pp->dev); ++ /*checks if the bus type is nvme and the protocol is FC-NVMe*/ ++ if ((pp->bus == SYSFS_BUS_NVME) && (pp->sg_id.proto_id == NVME_PROTOCOL_FC)) { ++ fpin_check_set_nvme_path_marginal(host_num, pp, els_wwpn, attached_wwpn); ++ } else if ((pp->bus == SYSFS_BUS_SCSI) && ++ (pp->sg_id.proto_id == SCSI_PROTOCOL_FCP) && ++ (host_num == pp->sg_id.host_no)) { ++ /* Checks the host number and also for the SCSI FCP */ ++ fpin_check_set_scsi_path_marginal(host_num, pp, els_wwpn); + } +-unref: +- pthread_cleanup_pop(1); + } + /* walk backwards because reload_and_sync_map() can remove mpp */ + vector_foreach_slot_backwards(vecs->mpvec, mpp, i) { +@@ -286,14 +378,18 @@ fpin_parse_li_els_setpath_marginal(uint16_t host_num, struct fc_tlv_desc *tlv, + struct fc_fn_li_desc *li_desc = (struct fc_fn_li_desc *)tlv; + int count = 0; + int ret = 0; ++ uint64_t attached_wwpn; + + /* Update the wwn to list */ + wwn_count = be32_to_cpu(li_desc->pname_count); +- condlog(4, "Got wwn count as %d\n", wwn_count); ++ attached_wwpn = be64_to_cpu(li_desc->attached_wwpn); ++ condlog(4, "Got wwn count as %d detecting wwn 0x%" PRIx64 ++ " attached_wwpn 0x%" PRIx64 "\n", ++ wwn_count, be64_to_cpu(li_desc->detecting_wwpn), attached_wwpn); + + for (iter = 0; iter < wwn_count; iter++) { + wwpn = be64_to_cpu(li_desc->pname_list[iter]); +- ret = fpin_chk_wwn_setpath_marginal(host_num, vecs, wwpn); ++ ret = fpin_chk_wwn_setpath_marginal(host_num, vecs, wwpn, attached_wwpn); + if (ret < 0) + condlog(2, "failed to set the path marginal associated with wwpn: 0x%" PRIx64 "\n", wwpn); + diff --git a/0001-RH-fixup-udev-rules-for-redhat.patch b/0041-RH-fixup-udev-rules-for-redhat.patch similarity index 89% rename from 0001-RH-fixup-udev-rules-for-redhat.patch rename to 0041-RH-fixup-udev-rules-for-redhat.patch index 618603c..e96c1e7 100644 --- a/0001-RH-fixup-udev-rules-for-redhat.patch +++ b/0041-RH-fixup-udev-rules-for-redhat.patch @@ -15,7 +15,7 @@ Signed-off-by: Benjamin Marzinski 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile.inc b/Makefile.inc -index 2e25d2ea..540e1dfc 100644 +index 04bfa56e..62d3d5cc 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -34,9 +34,9 @@ endif @@ -27,9 +27,9 @@ index 2e25d2ea..540e1dfc 100644 # Prefix for non-essential libraries (libdmmp) -usr_prefix := $(prefix) +usr_prefix := $(prefix)/usr + # Prefix for configfuration files (multipath.conf) + etc_prefix := $(prefix) # Where to install systemd-related files. systemd is usually installed under /usr - # Note: some systemd installations use separate "prefix" and "rootprefix". - # In this case, override only unitdir to use systemd's "rootprefix" instead of $(systemd_prefix) diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules index 1969dee0..d2b28233 100644 --- a/kpartx/kpartx.rules @@ -43,10 +43,10 @@ index 1969dee0..d2b28233 100644 LABEL="kpartx_end" diff --git a/multipath/Makefile b/multipath/Makefile -index 73db991a..b3c2cc81 100644 +index 68cb5ce7..f70e64ec 100644 --- a/multipath/Makefile +++ b/multipath/Makefile -@@ -24,7 +24,7 @@ install: +@@ -26,7 +26,7 @@ install: $(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/ $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) $(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) @@ -55,7 +55,7 @@ index 73db991a..b3c2cc81 100644 $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(modulesloaddir) $(Q)$(INSTALL_PROGRAM) -m 644 modules-load.conf $(DESTDIR)$(modulesloaddir)/multipath.conf $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(tmpfilesdir) -@@ -44,7 +44,7 @@ uninstall: +@@ -46,7 +46,7 @@ uninstall: $(Q)$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules $(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf $(Q)$(RM) $(DESTDIR)$(modulesloaddir)/scsi_dh.conf @@ -63,4 +63,4 @@ index 73db991a..b3c2cc81 100644 + $(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules $(Q)$(RM) $(DESTDIR)$(mandir)/man8/$(EXEC).8 $(Q)$(RM) $(DESTDIR)$(mandir)/man5/$(EXEC).conf.5 - + $(Q)$(RM) $(DESTDIR)$(tmpfilesdir)/multipath.conf diff --git a/0002-RH-Remove-the-property-blacklist-exception-builtin.patch b/0042-RH-Remove-the-property-blacklist-exception-builtin.patch similarity index 79% rename from 0002-RH-Remove-the-property-blacklist-exception-builtin.patch rename to 0042-RH-Remove-the-property-blacklist-exception-builtin.patch index cbd2480..61e8943 100644 --- a/0002-RH-Remove-the-property-blacklist-exception-builtin.patch +++ b/0042-RH-Remove-the-property-blacklist-exception-builtin.patch @@ -13,26 +13,25 @@ it. Signed-off-by: Benjamin Marzinski --- - libmultipath/blacklist.c | 6 ++---- - multipath/multipath.conf.5 | 11 ++++++----- - tests/blacklist.c | 7 ++----- - 3 files changed, 10 insertions(+), 14 deletions(-) + libmultipath/blacklist.c | 5 ++--- + multipath/multipath.conf.5.in | 11 ++++++----- + tests/blacklist.c | 7 ++----- + 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c -index 8d15d2ea..eff690fd 100644 +index 75100b20..0b212078 100644 --- a/libmultipath/blacklist.c +++ b/libmultipath/blacklist.c -@@ -201,9 +201,6 @@ setup_default_blist (struct config * conf) - if (store_ble(conf->blist_devnode, "!^(sd[a-z]|dasd[a-z]|nvme[0-9])", ORIGIN_DEFAULT)) - return 1; - +@@ -230,8 +230,6 @@ setup_default_blist (struct config * conf) + ORIGIN_DEFAULT)) + return 1; + } - if (store_ble(conf->elist_property, "(SCSI_IDENT_|ID_WWN)", ORIGIN_DEFAULT)) - return 1; -- + vector_foreach_slot (conf->hwtable, hwe, i) { if (hwe->bl_product) { - if (find_blacklist_device(conf->blist_device, -@@ -409,7 +406,8 @@ filter_property(const struct config *conf, struct udev_device *udev, +@@ -438,7 +436,8 @@ filter_property(const struct config *conf, struct udev_device *udev, *uid_attribute != '\0'; bool uid_attr_seen = false; @@ -42,11 +41,11 @@ index 8d15d2ea..eff690fd 100644 udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(udev)) { -diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 -index b4dccd1b..284282c6 100644 ---- a/multipath/multipath.conf.5 -+++ b/multipath/multipath.conf.5 -@@ -1367,9 +1367,14 @@ keywords. Both are regular expressions. For a full description of these keywords +diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in +index 226d0019..bae4168f 100644 +--- a/multipath/multipath.conf.5.in ++++ b/multipath/multipath.conf.5.in +@@ -1402,9 +1402,14 @@ keywords. Both are regular expressions. For a full description of these keywords Regular expression for an udev property. All devices that have matching udev properties will be excluded/included. The handling of the \fIproperty\fR keyword is special, @@ -62,7 +61,7 @@ index b4dccd1b..284282c6 100644 . .RS .PP -@@ -1380,10 +1385,6 @@ Blacklisting by missing properties is only applied to devices which do have the +@@ -1415,10 +1420,6 @@ Blacklisting by missing properties is only applied to devices which do have the property specified by \fIuid_attribute\fR (e.g. \fIID_SERIAL\fR) set. Previously, it was applied to every device, possibly causing devices to be blacklisted because of temporary I/O error conditions. @@ -74,10 +73,10 @@ index b4dccd1b..284282c6 100644 .TP .B protocol diff --git a/tests/blacklist.c b/tests/blacklist.c -index 882aa3a1..6a22b660 100644 +index ba8dfd07..693db3fa 100644 --- a/tests/blacklist.c +++ b/tests/blacklist.c -@@ -375,9 +375,8 @@ static void test_property_missing(void **state) +@@ -384,9 +384,8 @@ static void test_property_missing(void **state) { static struct udev_device udev = { "sdb", { "ID_FOO", "ID_BAZ", "ID_BAR", "ID_SERIAL", NULL } }; conf.blist_property = blist_property_wwn; @@ -88,7 +87,7 @@ index 882aa3a1..6a22b660 100644 assert_int_equal(filter_property(&conf, &udev, 3, "ID_BLAH"), MATCH_NOTHING); assert_int_equal(filter_property(&conf, &udev, 3, ""), -@@ -469,9 +468,7 @@ static void test_filter_path_missing1(void **state) +@@ -478,9 +477,7 @@ static void test_filter_path_missing1(void **state) conf.blist_device = blist_device_foo_bar; conf.blist_protocol = blist_protocol_fcp; conf.blist_wwid = blist_wwid_xyzzy; diff --git a/0003-RH-don-t-start-without-a-config-file.patch b/0043-RH-don-t-start-without-a-config-file.patch similarity index 71% rename from 0003-RH-don-t-start-without-a-config-file.patch rename to 0043-RH-don-t-start-without-a-config-file.patch index e6e03b4..ef9415d 100644 --- a/0003-RH-don-t-start-without-a-config-file.patch +++ b/0043-RH-don-t-start-without-a-config-file.patch @@ -14,17 +14,18 @@ Signed-off-by: Benjamin Marzinski --- libmultipath/config.c | 13 +++++++++++++ libmultipath/config.h | 1 + + multipath/main.c | 6 ++++++ multipath/multipath.rules.in | 1 + - multipathd/multipathd.8 | 2 ++ + multipathd/multipathd.8.in | 2 ++ multipathd/multipathd.service | 1 + multipathd/multipathd.socket | 1 + - 6 files changed, 19 insertions(+) + 7 files changed, 25 insertions(+) diff --git a/libmultipath/config.c b/libmultipath/config.c -index 5c5c0726..183b319d 100644 +index b7dbc6f5..3a374b3d 100644 --- a/libmultipath/config.c +++ b/libmultipath/config.c -@@ -966,6 +966,19 @@ int _init_config (const char *file, struct config *conf) +@@ -958,6 +958,19 @@ int _init_config (const char *file, struct config *conf) } factorize_hwtable(conf->hwtable, builtin_hwtable_size, file); validate_pctable(conf->overrides, 0, file); @@ -45,7 +46,7 @@ index 5c5c0726..183b319d 100644 conf->processed_main_config = 1; diff --git a/libmultipath/config.h b/libmultipath/config.h -index 87947469..0dc89c16 100644 +index 8c22ce75..92f3a0df 100644 --- a/libmultipath/config.h +++ b/libmultipath/config.h @@ -10,6 +10,7 @@ @@ -56,6 +57,35 @@ index 87947469..0dc89c16 100644 enum devtypes { DEV_NONE, +diff --git a/multipath/main.c b/multipath/main.c +index 9e1c5052..46944589 100644 +--- a/multipath/main.c ++++ b/multipath/main.c +@@ -829,11 +829,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)) +@@ -1081,6 +1084,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/multipath/multipath.rules.in b/multipath/multipath.rules.in index 6f123760..70b69a06 100644 --- a/multipath/multipath.rules.in @@ -68,11 +98,11 @@ index 6f123760..70b69a06 100644 ENV{DEVTYPE}!="partition", GOTO="test_dev" IMPORT{parent}="DM_MULTIPATH_DEVICE_PATH" -diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8 -index bdf102eb..a16a0bd5 100644 ---- a/multipathd/multipathd.8 -+++ b/multipathd/multipathd.8 -@@ -48,6 +48,8 @@ map regains its maximum performance and redundancy. +diff --git a/multipathd/multipathd.8.in b/multipathd/multipathd.8.in +index e98c27fd..fd2061e5 100644 +--- a/multipathd/multipathd.8.in ++++ b/multipathd/multipathd.8.in +@@ -49,6 +49,8 @@ map regains its maximum performance and redundancy. With the \fB-k\fR option, \fBmultipathd\fR acts as a client utility that sends commands to a running instance of the multipathd daemon (see \fBCOMMANDS\fR below). diff --git a/0004-RH-Fix-nvme-function-missing-argument.patch b/0044-RH-Fix-nvme-function-missing-argument.patch similarity index 100% rename from 0004-RH-Fix-nvme-function-missing-argument.patch rename to 0044-RH-Fix-nvme-function-missing-argument.patch diff --git a/0005-RH-use-rpm-optflags-if-present.patch b/0045-RH-use-rpm-optflags-if-present.patch similarity index 83% rename from 0005-RH-use-rpm-optflags-if-present.patch rename to 0045-RH-use-rpm-optflags-if-present.patch index 6a7fdea..1ad6b40 100644 --- a/0005-RH-use-rpm-optflags-if-present.patch +++ b/0045-RH-use-rpm-optflags-if-present.patch @@ -13,10 +13,10 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/Makefile.inc b/Makefile.inc -index 540e1dfc..748911e2 100644 +index 62d3d5cc..72fd8d57 100644 --- a/Makefile.inc +++ b/Makefile.inc -@@ -78,11 +78,23 @@ ORIG_LDFLAGS := $(LDFLAGS) +@@ -91,11 +91,23 @@ ORIG_LDFLAGS := $(LDFLAGS) SYSTEMD_CPPFLAGS := $(if $(SYSTEMD),-DUSE_SYSTEMD=$(SYSTEMD)) SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo 1),-lsystemd,-lsystemd-daemon)) @@ -38,13 +38,13 @@ index 540e1dfc..748911e2 100644 +WARNFLAGS := -Werror -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implicit-int \ -Werror=implicit-function-declaration -Werror=format-security \ - $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) --CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) \ +-CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \ + $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) -Wstrict-prototypes -+CPPFLAGS := $(CPPFLAGS) \ ++CPPFLAGS := $(CPPFLAGS) $(D_URCU_VERSION) \ -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \ - -DRUNTIME_DIR=\"$(runtimedir)\" \ - -DCONFIG_DIR=\"$(configdir)\" -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP -@@ -90,7 +102,7 @@ CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe + -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \ + -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DSTATE_DIR=\"$(statedir)\" \ +@@ -104,7 +116,7 @@ CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe BIN_CFLAGS := -fPIE -DPIE LIB_CFLAGS := -fPIC SHARED_FLAGS := -shared diff --git a/0006-RH-add-mpathconf.patch b/0046-RH-add-mpathconf.patch similarity index 98% rename from 0006-RH-add-mpathconf.patch rename to 0046-RH-add-mpathconf.patch index e279822..01bc8d2 100644 --- a/0006-RH-add-mpathconf.patch +++ b/0046-RH-add-mpathconf.patch @@ -21,10 +21,10 @@ Signed-off-by: Benjamin Marzinski create mode 100644 multipath/mpathconf.8 diff --git a/libmultipath/config.c b/libmultipath/config.c -index 183b319d..01f36a4f 100644 +index 3a374b3d..4544f484 100644 --- a/libmultipath/config.c +++ b/libmultipath/config.c -@@ -968,6 +968,8 @@ int _init_config (const char *file, struct config *conf) +@@ -960,6 +960,8 @@ int _init_config (const char *file, struct config *conf) validate_pctable(conf->overrides, 0, file); } else { condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices."); @@ -34,10 +34,10 @@ index 183b319d..01f36a4f 100644 conf->blist_devnode = vector_alloc(); if (!conf->blist_devnode) { diff --git a/multipath/Makefile b/multipath/Makefile -index b3c2cc81..413294ef 100644 +index f70e64ec..9942d1a9 100644 --- a/multipath/Makefile +++ b/multipath/Makefile -@@ -22,6 +22,7 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so +@@ -24,6 +24,7 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so install: $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) $(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/ @@ -45,7 +45,7 @@ index b3c2cc81..413294ef 100644 $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) $(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) $(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules -@@ -31,6 +32,7 @@ install: +@@ -33,6 +34,7 @@ install: $(Q)$(INSTALL_PROGRAM) -m 644 tmpfiles.conf $(DESTDIR)$(tmpfilesdir)/multipath.conf $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man8 $(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)/man8 @@ -53,7 +53,7 @@ index b3c2cc81..413294ef 100644 $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man5 $(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5 $(DESTDIR)$(mandir)/man5 ifneq ($(SCSI_DH_MODULES_PRELOAD),) -@@ -41,11 +43,13 @@ endif +@@ -43,11 +45,13 @@ endif uninstall: $(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC) @@ -65,8 +65,8 @@ index b3c2cc81..413294ef 100644 $(Q)$(RM) $(DESTDIR)$(mandir)/man8/$(EXEC).8 + $(Q)$(RM) $(DESTDIR)$(mandir)/man8/mpathconf.8 $(Q)$(RM) $(DESTDIR)$(mandir)/man5/$(EXEC).conf.5 + $(Q)$(RM) $(DESTDIR)$(tmpfilesdir)/multipath.conf - clean: dep_clean diff --git a/multipath/mpathconf b/multipath/mpathconf new file mode 100644 index 00000000..319664b1 diff --git a/0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch b/0047-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch similarity index 87% rename from 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch rename to 0047-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch index 714a1bb..7714825 100644 --- a/0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +++ b/0047-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch @@ -15,12 +15,12 @@ multipathd.service Signed-off-by: Benjamin Marzinski --- multipath/main.c | 54 +++++++++++++++++++++++++++++++++-- - multipath/multipath.8 | 7 ++++- + multipath/multipath.8.in | 7 ++++- multipathd/multipathd.service | 1 + 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/multipath/main.c b/multipath/main.c -index 90f940f1..3549740a 100644 +index 46944589..47f89a0a 100644 --- a/multipath/main.c +++ b/multipath/main.c @@ -120,7 +120,7 @@ usage (char * progname) @@ -41,7 +41,7 @@ index 90f940f1..3549740a 100644 " -c check if a device should be a path in a multipath device\n" " -C check if a multipath device has usable paths\n" " -q allow queue_if_no_path when multipathd is not running\n" -@@ -447,6 +449,50 @@ static void cleanup_vecs(void) +@@ -448,6 +450,50 @@ static void cleanup_vecs(void) free_pathvec(vecs.pathvec, FREE_PATHS); } @@ -92,16 +92,16 @@ index 90f940f1..3549740a 100644 static int configure (struct config *conf, enum mpath_cmds cmd, enum devtypes dev_type, char *devpath) -@@ -842,7 +888,7 @@ main (int argc, char *argv[]) - conf->force_sync = 1; - if (atexit(cleanup_vecs)) +@@ -848,7 +894,7 @@ main (int argc, char *argv[]) condlog(1, "failed to register cleanup handler for vecs: %m"); + if (atexit(cleanup_bindings)) + condlog(1, "failed to register cleanup handler for bindings: %m"); - while ((arg = getopt(argc, argv, ":adDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) { + while ((arg = getopt(argc, argv, ":aAdDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) { switch(arg) { case 'v': if (!isdigit(optarg[0])) { -@@ -913,6 +959,10 @@ main (int argc, char *argv[]) +@@ -919,6 +965,10 @@ main (int argc, char *argv[]) case 'T': cmd = CMD_DUMP_CONFIG; break; @@ -112,11 +112,11 @@ index 90f940f1..3549740a 100644 case 'h': usage(argv[0]); exit(RTVL_OK); -diff --git a/multipath/multipath.8 b/multipath/multipath.8 -index 88149d53..072a03ee 100644 ---- a/multipath/multipath.8 -+++ b/multipath/multipath.8 -@@ -63,7 +63,7 @@ multipath \- Device mapper target autoconfig. +diff --git a/multipath/multipath.8.in b/multipath/multipath.8.in +index 348eb220..82a7e68e 100644 +--- a/multipath/multipath.8.in ++++ b/multipath/multipath.8.in +@@ -64,7 +64,7 @@ multipath \- Device mapper target autoconfig. .B multipath .RB [\| \-v\ \c .IR level \|] @@ -125,7 +125,7 @@ index 88149d53..072a03ee 100644 . .LP .B multipath -@@ -145,6 +145,11 @@ device mapper, path checkers ...). +@@ -146,6 +146,11 @@ device mapper, path checkers ...). Add the WWID for the specified device to the WWIDs file. . .TP diff --git a/0008-RH-reset-default-find_mutipaths-value-to-off.patch b/0048-RH-reset-default-find_mutipaths-value-to-off.patch similarity index 96% rename from 0008-RH-reset-default-find_mutipaths-value-to-off.patch rename to 0048-RH-reset-default-find_mutipaths-value-to-off.patch index ea12464..432b070 100644 --- a/0008-RH-reset-default-find_mutipaths-value-to-off.patch +++ b/0048-RH-reset-default-find_mutipaths-value-to-off.patch @@ -12,7 +12,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h -index a5e9ea0c..514fd880 100644 +index d01f9712..ee2e13a9 100644 --- a/libmultipath/defaults.h +++ b/libmultipath/defaults.h @@ -23,7 +23,7 @@ diff --git a/0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch b/0049-RH-attempt-to-get-ANA-info-via-sysfs-first.patch similarity index 95% rename from 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch rename to 0049-RH-attempt-to-get-ANA-info-via-sysfs-first.patch index 06233ff..1f94eb3 100644 --- a/0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch +++ b/0049-RH-attempt-to-get-ANA-info-via-sysfs-first.patch @@ -13,7 +13,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/libmultipath/prioritizers/ana.c b/libmultipath/prioritizers/ana.c -index b5c7873d..e139360c 100644 +index e9827dca..80a32aa3 100644 --- a/libmultipath/prioritizers/ana.c +++ b/libmultipath/prioritizers/ana.c @@ -24,6 +24,7 @@ @@ -68,7 +68,7 @@ index b5c7873d..e139360c 100644 static int get_ana_info(struct path * pp) { int rc; -@@ -210,8 +234,11 @@ int getprio(struct path *pp, __attribute__((unused)) char *args, +@@ -209,8 +233,11 @@ int getprio(struct path *pp, __attribute__((unused)) char *args) if (pp->fd < 0) rc = -ANA_ERR_NO_INFORMATION; diff --git a/0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch b/0050-RH-make-parse_vpd_pg83-match-scsi_id-output.patch similarity index 98% rename from 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch rename to 0050-RH-make-parse_vpd_pg83-match-scsi_id-output.patch index 4e0b116..1906258 100644 --- a/0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +++ b/0050-RH-make-parse_vpd_pg83-match-scsi_id-output.patch @@ -14,7 +14,7 @@ Signed-off-by: Benjamin Marzinski 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index 6865cd92..72825829 100644 +index 84ce5fe7..104fdd5a 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -1177,13 +1177,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, diff --git a/0011-RH-add-scsi-device-handlers-to-modules-load.d.patch b/0051-RH-add-scsi-device-handlers-to-modules-load.d.patch similarity index 96% rename from 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch rename to 0051-RH-add-scsi-device-handlers-to-modules-load.d.patch index 26b0d06..407b621 100644 --- a/0011-RH-add-scsi-device-handlers-to-modules-load.d.patch +++ b/0051-RH-add-scsi-device-handlers-to-modules-load.d.patch @@ -11,7 +11,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc -index 748911e2..c07bcb0c 100644 +index 72fd8d57..a49e9f5a 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -16,7 +16,7 @@ READLINE := diff --git a/0012-RH-compile-with-libreadline-support.patch b/0052-RH-compile-with-libreadline-support.patch similarity index 96% rename from 0012-RH-compile-with-libreadline-support.patch rename to 0052-RH-compile-with-libreadline-support.patch index df99295..c78d5c0 100644 --- a/0012-RH-compile-with-libreadline-support.patch +++ b/0052-RH-compile-with-libreadline-support.patch @@ -12,7 +12,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc -index c07bcb0c..e59313c6 100644 +index a49e9f5a..51b55196 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -12,7 +12,7 @@ diff --git a/0053-RH-Add-mpathcleanup.patch b/0053-RH-Add-mpathcleanup.patch new file mode 100644 index 0000000..9278829 --- /dev/null +++ b/0053-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 9942d1a9..d281b501 100644 +--- a/multipath/Makefile ++++ b/multipath/Makefile +@@ -25,6 +25,7 @@ install: + $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) + $(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/ + $(Q)$(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/ ++ $(Q)$(INSTALL_PROGRAM) -m 755 mpathcleanup $(DESTDIR)$(bindir)/ + $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) + $(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) + $(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules +@@ -46,6 +47,7 @@ endif + uninstall: + $(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC) + $(Q)$(RM) $(DESTDIR)$(bindir)/mpathconf ++ $(Q)$(RM) $(DESTDIR)$(bindir)/mpathcleanup + $(Q)$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules + $(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf + $(Q)$(RM) $(DESTDIR)$(modulesloaddir)/scsi_dh.conf +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/device-mapper-multipath.spec b/device-mapper-multipath.spec index 268e4b9..30c0bbf 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,27 +1,68 @@ Name: device-mapper-multipath -Version: 0.9.5 -Release: 2%{?dist} +Version: 0.9.6 +Release: 1%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ # The source for this package was pulled from upstream's git repo. Use the # following command to generate the tarball -# curl -L https://github.com/opensvc/multipath-tools/archive/0.9.5.tar.gz -o multipath-tools-0.9.5.tgz -Source0: multipath-tools-0.9.5.tgz +# curl -L https://github.com/opensvc/multipath-tools/archive/0.9.6.tar.gz -o multipath-tools-0.9.6.tgz +Source0: multipath-tools-0.9.6.tgz Source1: multipath.conf -Patch0001: 0001-RH-fixup-udev-rules-for-redhat.patch -Patch0002: 0002-RH-Remove-the-property-blacklist-exception-builtin.patch -Patch0003: 0003-RH-don-t-start-without-a-config-file.patch -Patch0004: 0004-RH-Fix-nvme-function-missing-argument.patch -Patch0005: 0005-RH-use-rpm-optflags-if-present.patch -Patch0006: 0006-RH-add-mpathconf.patch -Patch0007: 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch -Patch0008: 0008-RH-reset-default-find_mutipaths-value-to-off.patch -Patch0009: 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch -Patch0010: 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch -Patch0011: 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch -Patch0012: 0012-RH-compile-with-libreadline-support.patch +Patch0001: 0001-libmultipath-sysfs_set_scsi_tmo-do-nothing-for-ACT_D.patch +Patch0002: 0002-libmultipath-add-alias_already_taken.patch +Patch0003: 0003-libmultipath-unify-use_existing_alias-and-get_user_f.patch +Patch0004: 0004-libmultipath-never-allocate-an-alias-that-s-already-.patch +Patch0005: 0005-libmultipath-lookup_binding-add-comment-about-the-al.patch +Patch0006: 0006-multipath-tools-test-simplify-debugging-for-condlog-.patch +Patch0007: 0007-multipath-tools-tests-add-tests-for-get_user_friendl.patch +Patch0008: 0008-multipath-tools-test-consistent-use-of-macros-in-ali.patch +Patch0009: 0009-multipath-tools-tests-convert-mock_-failed-used-_ali.patch +Patch0010: 0010-multipath-tools-test-use-mock_bindings_file-consiste.patch +Patch0011: 0011-libmultipath-add-global-variable-for-current-binding.patch +Patch0012: 0012-libmultipath-rename-fix_bindings_file-to-update_bind.patch +Patch0013: 0013-libmultipath-alias.c-move-bindings-related-code-up.patch +Patch0014: 0014-libmultipath-update_bindings_file-take-filename-argu.patch +Patch0015: 0015-libmultipath-update_bindings_file-use-a-single-write.patch +Patch0016: 0016-libmultipath-update_bindings_file-don-t-log-temp-fil.patch +Patch0017: 0017-libmultipath-alias.c-factor-out-read_binding.patch +Patch0018: 0018-libmultipath-keep-bindings-in-memory.patch +Patch0019: 0019-multipath-tools-tests-fix-alias-tests.patch +Patch0020: 0020-libmultipath-dm_get_uuid-return-emtpy-UUID-for-non-e.patch +Patch0021: 0021-libmultipath-adapt-to-new-semantics-of-dm_get_uuid.patch +Patch0022: 0022-libmultipath-sort-aliases-by-length-and-strcmp.patch +Patch0023: 0023-multipath-tools-tests-fix-alias-test-after-sort-orde.patch +Patch0024: 0024-libmultipath-simplify-get_free_id-assuming-total-ord.patch +Patch0025: 0025-multipath-tools-tests-adapt-alias-tests-for-total-or.patch +Patch0026: 0026-multipath-tools-tests-add-test-for-ordering-of-bindi.patch +Patch0027: 0027-multipathd-watch-bindings-file-with-inotify-timestam.patch +Patch0028: 0028-multipath-tools-tests-mock-pthread_mutex_-lock-unloc.patch +Patch0029: 0029-multipath-tools-Makefile-sanitize-paths-for-configur.patch +Patch0030: 0030-multipath-tools-add-compile-time-configuration-for-e.patch +Patch0031: 0031-multipath-tools-man-pages-generate-with-correct-path.patch +Patch0032: 0032-libdmmp-Makefile-fix-bug-in-install-section.patch +Patch0033: 0033-multipath-tools-README.md-improve-documentation-for-.patch +Patch0034: 0034-libmultipath-print-built-in-values-for-deprecated-op.patch +Patch0035: 0035-multipath-add-a-missing-newline.patch +Patch0036: 0036-multipath-tools-allow-prefixes-with-and-w-o-trailing.patch +Patch0037: 0037-libmultipath-deprecate-bindings_file-wwids_file-prke.patch +Patch0038: 0038-libmultipath-avoid-Warray-bounds-error-in-uatomic-op.patch +Patch0039: 0039-multipath-tools-fix-spelling.patch +Patch0040: 0040-multipathd-Added-support-to-handle-FPIN-Li-events-fo.patch +Patch0041: 0041-RH-fixup-udev-rules-for-redhat.patch +Patch0042: 0042-RH-Remove-the-property-blacklist-exception-builtin.patch +Patch0043: 0043-RH-don-t-start-without-a-config-file.patch +Patch0044: 0044-RH-Fix-nvme-function-missing-argument.patch +Patch0045: 0045-RH-use-rpm-optflags-if-present.patch +Patch0046: 0046-RH-add-mpathconf.patch +Patch0047: 0047-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +Patch0048: 0048-RH-reset-default-find_mutipaths-value-to-off.patch +Patch0049: 0049-RH-attempt-to-get-ANA-info-via-sysfs-first.patch +Patch0050: 0050-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +Patch0051: 0051-RH-add-scsi-device-handlers-to-modules-load.d.patch +Patch0052: 0052-RH-compile-with-libreadline-support.patch +Patch0053: 0053-RH-Add-mpathcleanup.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -108,7 +149,7 @@ This package contains the files needed to develop applications that use device-mapper-multipath's libdmmp C API library %prep -%autosetup -n multipath-tools-0.9.5 -p1 +%autosetup -n multipath-tools-0.9.6 -p1 cp %{SOURCE1} . %build @@ -158,6 +199,7 @@ fi %{_sbindir}/multipathd %{_sbindir}/multipathc %{_sbindir}/mpathconf +%{_sbindir}/mpathcleanup %{_sbindir}/mpathpersist %{_unitdir}/multipathd.service %{_unitdir}/multipathd.socket @@ -230,6 +272,13 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Fri Sep 22 2023 Benjamin Marzinski - 0.9.6-1 +- Update to the head of the upstream staging branch +- Rename redhat patches + * Previous patches 0001-0012 are now patches 0041-0052 +- Add 0053-RH-Add-mpathcleanup.patch + * add mpathcleanup program + * Wed Jul 19 2023 Fedora Release Engineering - 0.9.5-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild diff --git a/sources b/sources index ece6ffe..5d41f65 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (multipath-tools-0.9.5.tgz) = 39c2e5d45542c6076eb3b17b9994629b4c1f74347aa43e0119001fa2d07d3a606fd5e617962906a11b313afb37a115bd8eec2ef24447e980e61b5900625f9146 +SHA512 (multipath-tools-0.9.6.tgz) = 17d2b46ead9df6826b3266035bc077a2f4d4bea01e2cd59e32d3917cda40c320f11bc8572da7ba66251e312b46d9be317737069193d481d202d49f9aa5fd71b9 SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942 From 748e0a08b6e2efb771d80e644047f0ad856e8b0d Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Tue, 21 Nov 2023 16:11:29 -0500 Subject: [PATCH 04/29] device-mapper-mulitpath-0.9.7-1 Update source to upstream version 0.9.7 * Previous patches 0001-0040 are included in the source tarball Rename redhat patches * Previous patches 0041-0053 are now patches 0001-0013 Remove /usr/lib/modules-load.d/multipath.conf * has been replaced with modprobe@dm_multipath.service unit Wants. --- .gitignore | 1 + ... 0001-RH-fixup-udev-rules-for-redhat.patch | 21 +- ...fs_set_scsi_tmo-do-nothing-for-ACT_D.patch | 51 - ...property-blacklist-exception-builtin.patch | 6 +- ...libmultipath-add-alias_already_taken.patch | 75 - ...RH-don-t-start-without-a-config-file.patch | 28 +- ...fy-use_existing_alias-and-get_user_f.patch | 207 -- ...H-Fix-nvme-function-missing-argument.patch | 0 ...er-allocate-an-alias-that-s-already-.patch | 101 - ... 0005-RH-use-rpm-optflags-if-present.patch | 10 +- ...kup_binding-add-comment-about-the-al.patch | 61 - ...hconf.patch => 0006-RH-add-mpathconf.patch | 8 +- ...test-simplify-debugging-for-condlog-.patch | 35 - ...om-kernel-cmdline-mpath.wwids-with-A.patch | 14 +- ...tests-add-tests-for-get_user_friendl.patch | 493 ----- ...-default-find_mutipaths-value-to-off.patch | 2 +- ...test-consistent-use-of-macros-in-ali.patch | 365 ---- ...empt-to-get-ANA-info-via-sysfs-first.patch | 0 ...tests-convert-mock_-failed-used-_ali.patch | 246 --- ...-parse_vpd_pg83-match-scsi_id-output.patch | 6 +- ...test-use-mock_bindings_file-consiste.patch | 500 ----- ...si-device-handlers-to-modules-load.d.patch | 2 +- ...-global-variable-for-current-binding.patch | 109 -- ...-RH-compile-with-libreadline-support.patch | 2 +- ...ame-fix_bindings_file-to-update_bind.patch | 40 - ...up.patch => 0013-RH-Add-mpathcleanup.patch | 4 +- ...lias.c-move-bindings-related-code-up.patch | 285 --- ...ate_bindings_file-take-filename-argu.patch | 61 - ...ate_bindings_file-use-a-single-write.patch | 59 - ...ate_bindings_file-don-t-log-temp-fil.patch | 29 - ...path-alias.c-factor-out-read_binding.patch | 94 - ...libmultipath-keep-bindings-in-memory.patch | 545 ------ ...ultipath-tools-tests-fix-alias-tests.patch | 1698 ----------------- ...get_uuid-return-emtpy-UUID-for-non-e.patch | 53 - ...dapt-to-new-semantics-of-dm_get_uuid.patch | 158 -- ...th-sort-aliases-by-length-and-strcmp.patch | 98 - ...tests-fix-alias-test-after-sort-orde.patch | 90 - ...plify-get_free_id-assuming-total-ord.patch | 122 -- ...tests-adapt-alias-tests-for-total-or.patch | 203 -- ...tests-add-test-for-ordering-of-bindi.patch | 275 --- ...-bindings-file-with-inotify-timestam.patch | 597 ------ ...tests-mock-pthread_mutex_-lock-unloc.patch | 102 - ...Makefile-sanitize-paths-for-configur.patch | 73 - ...add-compile-time-configuration-for-e.patch | 58 - ...man-pages-generate-with-correct-path.patch | 366 ---- ...-Makefile-fix-bug-in-install-section.patch | 25 - ...README.md-improve-documentation-for-.patch | 75 - ...nt-built-in-values-for-deprecated-op.patch | 55 - 0035-multipath-add-a-missing-newline.patch | 25 - ...allow-prefixes-with-and-w-o-trailing.patch | 66 - ...recate-bindings_file-wwids_file-prke.patch | 897 --------- ...id-Warray-bounds-error-in-uatomic-op.patch | 158 -- 0039-multipath-tools-fix-spelling.patch | 52 - ...-support-to-handle-FPIN-Li-events-fo.patch | 300 --- device-mapper-multipath.spec | 83 +- sources | 2 +- 56 files changed, 77 insertions(+), 9014 deletions(-) rename 0041-RH-fixup-udev-rules-for-redhat.patch => 0001-RH-fixup-udev-rules-for-redhat.patch (81%) delete mode 100644 0001-libmultipath-sysfs_set_scsi_tmo-do-nothing-for-ACT_D.patch rename 0042-RH-Remove-the-property-blacklist-exception-builtin.patch => 0002-RH-Remove-the-property-blacklist-exception-builtin.patch (96%) delete mode 100644 0002-libmultipath-add-alias_already_taken.patch rename 0043-RH-don-t-start-without-a-config-file.patch => 0003-RH-don-t-start-without-a-config-file.patch (87%) delete mode 100644 0003-libmultipath-unify-use_existing_alias-and-get_user_f.patch rename 0044-RH-Fix-nvme-function-missing-argument.patch => 0004-RH-Fix-nvme-function-missing-argument.patch (100%) delete mode 100644 0004-libmultipath-never-allocate-an-alias-that-s-already-.patch rename 0045-RH-use-rpm-optflags-if-present.patch => 0005-RH-use-rpm-optflags-if-present.patch (87%) delete mode 100644 0005-libmultipath-lookup_binding-add-comment-about-the-al.patch rename 0046-RH-add-mpathconf.patch => 0006-RH-add-mpathconf.patch (99%) delete mode 100644 0006-multipath-tools-test-simplify-debugging-for-condlog-.patch rename 0047-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch => 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch (93%) delete mode 100644 0007-multipath-tools-tests-add-tests-for-get_user_friendl.patch rename 0048-RH-reset-default-find_mutipaths-value-to-off.patch => 0008-RH-reset-default-find_mutipaths-value-to-off.patch (96%) delete mode 100644 0008-multipath-tools-test-consistent-use-of-macros-in-ali.patch rename 0049-RH-attempt-to-get-ANA-info-via-sysfs-first.patch => 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch (100%) delete mode 100644 0009-multipath-tools-tests-convert-mock_-failed-used-_ali.patch rename 0050-RH-make-parse_vpd_pg83-match-scsi_id-output.patch => 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch (94%) delete mode 100644 0010-multipath-tools-test-use-mock_bindings_file-consiste.patch rename 0051-RH-add-scsi-device-handlers-to-modules-load.d.patch => 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch (96%) delete mode 100644 0011-libmultipath-add-global-variable-for-current-binding.patch rename 0052-RH-compile-with-libreadline-support.patch => 0012-RH-compile-with-libreadline-support.patch (96%) delete mode 100644 0012-libmultipath-rename-fix_bindings_file-to-update_bind.patch rename 0053-RH-Add-mpathcleanup.patch => 0013-RH-Add-mpathcleanup.patch (98%) delete mode 100644 0013-libmultipath-alias.c-move-bindings-related-code-up.patch delete mode 100644 0014-libmultipath-update_bindings_file-take-filename-argu.patch delete mode 100644 0015-libmultipath-update_bindings_file-use-a-single-write.patch delete mode 100644 0016-libmultipath-update_bindings_file-don-t-log-temp-fil.patch delete mode 100644 0017-libmultipath-alias.c-factor-out-read_binding.patch delete mode 100644 0018-libmultipath-keep-bindings-in-memory.patch delete mode 100644 0019-multipath-tools-tests-fix-alias-tests.patch delete mode 100644 0020-libmultipath-dm_get_uuid-return-emtpy-UUID-for-non-e.patch delete mode 100644 0021-libmultipath-adapt-to-new-semantics-of-dm_get_uuid.patch delete mode 100644 0022-libmultipath-sort-aliases-by-length-and-strcmp.patch delete mode 100644 0023-multipath-tools-tests-fix-alias-test-after-sort-orde.patch delete mode 100644 0024-libmultipath-simplify-get_free_id-assuming-total-ord.patch delete mode 100644 0025-multipath-tools-tests-adapt-alias-tests-for-total-or.patch delete mode 100644 0026-multipath-tools-tests-add-test-for-ordering-of-bindi.patch delete mode 100644 0027-multipathd-watch-bindings-file-with-inotify-timestam.patch delete mode 100644 0028-multipath-tools-tests-mock-pthread_mutex_-lock-unloc.patch delete mode 100644 0029-multipath-tools-Makefile-sanitize-paths-for-configur.patch delete mode 100644 0030-multipath-tools-add-compile-time-configuration-for-e.patch delete mode 100644 0031-multipath-tools-man-pages-generate-with-correct-path.patch delete mode 100644 0032-libdmmp-Makefile-fix-bug-in-install-section.patch delete mode 100644 0033-multipath-tools-README.md-improve-documentation-for-.patch delete mode 100644 0034-libmultipath-print-built-in-values-for-deprecated-op.patch delete mode 100644 0035-multipath-add-a-missing-newline.patch delete mode 100644 0036-multipath-tools-allow-prefixes-with-and-w-o-trailing.patch delete mode 100644 0037-libmultipath-deprecate-bindings_file-wwids_file-prke.patch delete mode 100644 0038-libmultipath-avoid-Warray-bounds-error-in-uatomic-op.patch delete mode 100644 0039-multipath-tools-fix-spelling.patch delete mode 100644 0040-multipathd-Added-support-to-handle-FPIN-Li-events-fo.patch diff --git a/.gitignore b/.gitignore index 75c4abc..f698d08 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,4 @@ multipath-tools-091027.tar.gz /multipath-tools-0.9.4.tgz /multipath-tools-0.9.5.tgz /multipath-tools-0.9.6.tgz +/multipath-tools-0.9.7.tgz diff --git a/0041-RH-fixup-udev-rules-for-redhat.patch b/0001-RH-fixup-udev-rules-for-redhat.patch similarity index 81% rename from 0041-RH-fixup-udev-rules-for-redhat.patch rename to 0001-RH-fixup-udev-rules-for-redhat.patch index e96c1e7..02efadd 100644 --- a/0041-RH-fixup-udev-rules-for-redhat.patch +++ b/0001-RH-fixup-udev-rules-for-redhat.patch @@ -9,27 +9,24 @@ different naming scheme for partitions than SuSE. Signed-off-by: Benjamin Marzinski --- - Makefile.inc | 4 ++-- + Makefile.inc | 2 +- kpartx/kpartx.rules | 2 +- multipath/Makefile | 4 ++-- - 3 files changed, 5 insertions(+), 5 deletions(-) + 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile.inc b/Makefile.inc -index 04bfa56e..62d3d5cc 100644 +index 6b454303..0b0e3ad2 100644 --- a/Makefile.inc +++ b/Makefile.inc -@@ -34,9 +34,9 @@ endif +@@ -34,7 +34,7 @@ endif # Paths. All these can be overridden on the "make" command line. prefix := # Prefix for binaries -exec_prefix := $(prefix) +exec_prefix := $(prefix)/usr # Prefix for non-essential libraries (libdmmp) --usr_prefix := $(prefix) -+usr_prefix := $(prefix)/usr + usr_prefix := $(if $(prefix),$(prefix),/usr) # Prefix for configfuration files (multipath.conf) - etc_prefix := $(prefix) - # Where to install systemd-related files. systemd is usually installed under /usr diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules index 1969dee0..d2b28233 100644 --- a/kpartx/kpartx.rules @@ -43,7 +40,7 @@ index 1969dee0..d2b28233 100644 LABEL="kpartx_end" diff --git a/multipath/Makefile b/multipath/Makefile -index 68cb5ce7..f70e64ec 100644 +index 0efb9b26..504d6892 100644 --- a/multipath/Makefile +++ b/multipath/Makefile @@ -26,7 +26,7 @@ install: @@ -52,10 +49,10 @@ index 68cb5ce7..f70e64ec 100644 $(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) - $(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/56-multipath.rules + $(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules - $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(modulesloaddir) - $(Q)$(INSTALL_PROGRAM) -m 644 modules-load.conf $(DESTDIR)$(modulesloaddir)/multipath.conf $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(tmpfilesdir) -@@ -46,7 +46,7 @@ uninstall: + $(Q)$(INSTALL_PROGRAM) -m 644 tmpfiles.conf $(DESTDIR)$(tmpfilesdir)/multipath.conf + $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man8 +@@ -48,7 +48,7 @@ uninstall: $(Q)$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules $(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf $(Q)$(RM) $(DESTDIR)$(modulesloaddir)/scsi_dh.conf diff --git a/0001-libmultipath-sysfs_set_scsi_tmo-do-nothing-for-ACT_D.patch b/0001-libmultipath-sysfs_set_scsi_tmo-do-nothing-for-ACT_D.patch deleted file mode 100644 index 9b8a486..0000000 --- a/0001-libmultipath-sysfs_set_scsi_tmo-do-nothing-for-ACT_D.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Tue, 22 Aug 2023 16:21:43 +0200 -Subject: [PATCH] libmultipath: sysfs_set_scsi_tmo: do nothing for ACT_DRY_RUN - -"multipath -d" might change sysfs timeouts of SCSI devices. -Make sure it doesn't. - -Signed-off-by: Martin Wilck -Cc: Jehan Singh -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/configure.c | 4 ++-- - libmultipath/discovery.c | 3 +++ - 2 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index 9513baae..029fbbd2 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -1193,13 +1193,13 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid, - - if (cmpp) - mpp->queue_mode = cmpp->queue_mode; -+ if (cmd == CMD_DRY_RUN && mpp->action == ACT_UNDEF) -+ mpp->action = ACT_DRY_RUN; - if (setup_map(mpp, ¶ms, vecs)) { - remove_map(mpp, vecs->pathvec, NULL); - continue; - } - -- if (cmd == CMD_DRY_RUN) -- mpp->action = ACT_DRY_RUN; - if (mpp->action == ACT_UNDEF) - select_action(mpp, curmp, - force_reload == FORCE_RELOAD_YES ? 1 : 0); -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index e4de48e7..84ce5fe7 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -857,6 +857,9 @@ sysfs_set_scsi_tmo (struct config *conf, struct multipath *mpp) - bool warn_dev_loss = false; - bool warn_fast_io_fail = false; - -+ if (mpp->action == ACT_DRY_RUN || mpp->action == ACT_REJECT) -+ return 0; -+ - if (mpp->no_path_retry > 0) { - uint64_t no_path_retry_tmo = - (uint64_t)mpp->no_path_retry * conf->checkint; diff --git a/0042-RH-Remove-the-property-blacklist-exception-builtin.patch b/0002-RH-Remove-the-property-blacklist-exception-builtin.patch similarity index 96% rename from 0042-RH-Remove-the-property-blacklist-exception-builtin.patch rename to 0002-RH-Remove-the-property-blacklist-exception-builtin.patch index 61e8943..bc259d4 100644 --- a/0042-RH-Remove-the-property-blacklist-exception-builtin.patch +++ b/0002-RH-Remove-the-property-blacklist-exception-builtin.patch @@ -42,10 +42,10 @@ index 75100b20..0b212078 100644 udev_device_get_properties_list_entry(udev)) { diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in -index 226d0019..bae4168f 100644 +index 683bdb72..87b3b2a5 100644 --- a/multipath/multipath.conf.5.in +++ b/multipath/multipath.conf.5.in -@@ -1402,9 +1402,14 @@ keywords. Both are regular expressions. For a full description of these keywords +@@ -1431,9 +1431,14 @@ keywords. Both are regular expressions. For a full description of these keywords Regular expression for an udev property. All devices that have matching udev properties will be excluded/included. The handling of the \fIproperty\fR keyword is special, @@ -61,7 +61,7 @@ index 226d0019..bae4168f 100644 . .RS .PP -@@ -1415,10 +1420,6 @@ Blacklisting by missing properties is only applied to devices which do have the +@@ -1444,10 +1449,6 @@ Blacklisting by missing properties is only applied to devices which do have the property specified by \fIuid_attribute\fR (e.g. \fIID_SERIAL\fR) set. Previously, it was applied to every device, possibly causing devices to be blacklisted because of temporary I/O error conditions. diff --git a/0002-libmultipath-add-alias_already_taken.patch b/0002-libmultipath-add-alias_already_taken.patch deleted file mode 100644 index 8ed3c7b..0000000 --- a/0002-libmultipath-add-alias_already_taken.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Tue, 22 Aug 2023 21:36:11 +0200 -Subject: [PATCH] libmultipath: add alias_already_taken() - -Factor out a trivial helper function. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/alias.c | 32 +++++++++++++++++++------------- - 1 file changed, 19 insertions(+), 13 deletions(-) - -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index c0139a2e..83ded886 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - - #include "debug.h" - #include "util.h" -@@ -109,30 +110,35 @@ scan_devname(const char *alias, const char *prefix) - return n; - } - --static int --id_already_taken(int id, const char *prefix, const char *map_wwid) -+static bool alias_already_taken(const char *alias, const char *map_wwid) - { -- STRBUF_ON_STACK(buf); -- const char *alias; -- -- if (append_strbuf_str(&buf, prefix) < 0 || -- format_devname(&buf, id) < 0) -- return 0; - -- alias = get_strbuf_str(&buf); - if (dm_map_present(alias)) { - char wwid[WWID_SIZE]; - - /* If both the name and the wwid match, then it's fine.*/ - if (dm_get_uuid(alias, wwid, sizeof(wwid)) == 0 && - strncmp(map_wwid, wwid, sizeof(wwid)) == 0) -- return 0; -- condlog(3, "%s: alias '%s' already taken, but not in bindings file. reselecting alias", map_wwid, alias); -- return 1; -+ return false; -+ condlog(3, "%s: alias '%s' already taken, but not in bindings file. reselecting alias", -+ map_wwid, alias); -+ return true; - } -- return 0; -+ return false; - } - -+static bool id_already_taken(int id, const char *prefix, const char *map_wwid) -+{ -+ STRBUF_ON_STACK(buf); -+ const char *alias; -+ -+ if (append_strbuf_str(&buf, prefix) < 0 || -+ format_devname(&buf, id) < 0) -+ return false; -+ -+ alias = get_strbuf_str(&buf); -+ return alias_already_taken(alias, map_wwid); -+} - - /* - * Returns: 0 if matching entry in WWIDs file found diff --git a/0043-RH-don-t-start-without-a-config-file.patch b/0003-RH-don-t-start-without-a-config-file.patch similarity index 87% rename from 0043-RH-don-t-start-without-a-config-file.patch rename to 0003-RH-don-t-start-without-a-config-file.patch index ef9415d..fa304dc 100644 --- a/0043-RH-don-t-start-without-a-config-file.patch +++ b/0003-RH-don-t-start-without-a-config-file.patch @@ -12,13 +12,13 @@ simple way to disable multipath. Simply removing or renaming Signed-off-by: Benjamin Marzinski --- - libmultipath/config.c | 13 +++++++++++++ - libmultipath/config.h | 1 + - multipath/main.c | 6 ++++++ - multipath/multipath.rules.in | 1 + - multipathd/multipathd.8.in | 2 ++ - multipathd/multipathd.service | 1 + - multipathd/multipathd.socket | 1 + + libmultipath/config.c | 13 +++++++++++++ + libmultipath/config.h | 1 + + multipath/main.c | 6 ++++++ + multipath/multipath.rules.in | 1 + + multipathd/multipathd.8.in | 2 ++ + multipathd/multipathd.service.in | 1 + + multipathd/multipathd.socket | 1 + 7 files changed, 25 insertions(+) diff --git a/libmultipath/config.c b/libmultipath/config.c @@ -46,7 +46,7 @@ index b7dbc6f5..3a374b3d 100644 conf->processed_main_config = 1; diff --git a/libmultipath/config.h b/libmultipath/config.h -index 8c22ce75..92f3a0df 100644 +index 384193ab..158cebf0 100644 --- a/libmultipath/config.h +++ b/libmultipath/config.h @@ -10,6 +10,7 @@ @@ -111,12 +111,12 @@ index e98c27fd..fd2061e5 100644 . . .\" ---------------------------------------------------------------------------- -diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service -index 5a9cde12..311f49c7 100644 ---- a/multipathd/multipathd.service -+++ b/multipathd/multipathd.service -@@ -6,6 +6,7 @@ Wants=systemd-udevd-kernel.socket - After=systemd-udevd-kernel.socket +diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in +index 6d03ff71..0965d6f9 100644 +--- a/multipathd/multipathd.service.in ++++ b/multipathd/multipathd.service.in +@@ -6,6 +6,7 @@ Wants=systemd-udevd-kernel.socket @MODPROBE_UNIT@ + After=systemd-udevd-kernel.socket @MODPROBE_UNIT@ After=multipathd.socket systemd-remount-fs.service Before=initrd-cleanup.service +ConditionPathExists=/etc/multipath.conf diff --git a/0003-libmultipath-unify-use_existing_alias-and-get_user_f.patch b/0003-libmultipath-unify-use_existing_alias-and-get_user_f.patch deleted file mode 100644 index 5beb1fe..0000000 --- a/0003-libmultipath-unify-use_existing_alias-and-get_user_f.patch +++ /dev/null @@ -1,207 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Tue, 22 Aug 2023 22:00:58 +0200 -Subject: [PATCH] libmultipath: unify use_existing_alias() and - get_user_friendly_alias() - -These functions are only called from select_alias(). The logic -is more obvious when unified in a single function. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/alias.c | 82 ++++++++++++------------------------------ - libmultipath/alias.h | 9 ++--- - libmultipath/propsel.c | 19 +++++----- - 3 files changed, 34 insertions(+), 76 deletions(-) - -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index 83ded886..68f5d848 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -329,13 +329,13 @@ allocate_binding(int fd, const char *wwid, int id, const char *prefix) - return alias; - } - --char * --use_existing_alias (const char *wwid, const char *file, const char *alias_old, -- const char *prefix, int bindings_read_only) -+char *get_user_friendly_alias(const char *wwid, const char *file, const char *alias_old, -+ const char *prefix, bool bindings_read_only) - { - char *alias = NULL; - int id = 0; - int fd, can_write; -+ bool new_binding = false; - char buff[WWID_SIZE]; - FILE *f; - -@@ -349,6 +349,10 @@ use_existing_alias (const char *wwid, const char *file, const char *alias_old, - close(fd); - return NULL; - } -+ -+ if (!strlen(alias_old)) -+ goto new_alias; -+ - /* lookup the binding. if it exists, the wwid will be in buff - * either way, id contains the id for the alias - */ -@@ -358,14 +362,14 @@ use_existing_alias (const char *wwid, const char *file, const char *alias_old, - /* if buff is our wwid, it's already - * allocated correctly - */ -- if (strcmp(buff, wwid) == 0) -+ if (strcmp(buff, wwid) == 0) { - alias = strdup(alias_old); -- else { -- alias = NULL; -+ goto out; -+ } else { - condlog(0, "alias %s already bound to wwid %s, cannot reuse", - alias_old, buff); -+ goto new_alias; - } -- goto out; - } - - id = lookup_binding(f, wwid, &alias, NULL, 0); -@@ -377,8 +381,15 @@ use_existing_alias (const char *wwid, const char *file, const char *alias_old, - - /* allocate the existing alias in the bindings file */ - id = scan_devname(alias_old, prefix); -- if (id <= 0) -- goto out; -+ -+new_alias: -+ if (id <= 0) { -+ id = lookup_binding(f, wwid, &alias, prefix, 1); -+ if (id <= 0) -+ goto out; -+ else -+ new_binding = true; -+ } - - if (fflush(f) != 0) { - condlog(0, "cannot fflush bindings file stream : %s", -@@ -388,8 +399,9 @@ use_existing_alias (const char *wwid, const char *file, const char *alias_old, - - if (can_write && !bindings_read_only) { - alias = allocate_binding(fd, wwid, id, prefix); -- condlog(0, "Allocated existing binding [%s] for WWID [%s]", -- alias, wwid); -+ if (alias && !new_binding) -+ condlog(2, "Allocated existing binding [%s] for WWID [%s]", -+ alias, wwid); - } - - out: -@@ -399,54 +411,6 @@ out: - return alias; - } - --char * --get_user_friendly_alias(const char *wwid, const char *file, const char *prefix, -- int bindings_read_only) --{ -- char *alias; -- int fd, id; -- FILE *f; -- int can_write; -- -- if (!wwid || *wwid == '\0') { -- condlog(3, "Cannot find binding for empty WWID"); -- return NULL; -- } -- -- fd = open_file(file, &can_write, bindings_file_header); -- if (fd < 0) -- return NULL; -- -- f = fdopen(fd, "r"); -- if (!f) { -- condlog(0, "cannot fdopen on bindings file descriptor : %s", -- strerror(errno)); -- close(fd); -- return NULL; -- } -- -- id = lookup_binding(f, wwid, &alias, prefix, 1); -- if (id < 0) { -- fclose(f); -- return NULL; -- } -- -- pthread_cleanup_push(free, alias); -- -- if (fflush(f) != 0) { -- condlog(0, "cannot fflush bindings file stream : %s", -- strerror(errno)); -- free(alias); -- alias = NULL; -- } else if (can_write && !bindings_read_only && !alias) -- alias = allocate_binding(fd, wwid, id, prefix); -- -- fclose(f); -- -- pthread_cleanup_pop(0); -- return alias; --} -- - int - get_user_friendly_wwid(const char *alias, char *buff, const char *file) - { -diff --git a/libmultipath/alias.h b/libmultipath/alias.h -index dbc950c4..fa332233 100644 ---- a/libmultipath/alias.h -+++ b/libmultipath/alias.h -@@ -2,13 +2,10 @@ - #define _ALIAS_H - - int valid_alias(const char *alias); --char *get_user_friendly_alias(const char *wwid, const char *file, -- const char *prefix, -- int bindings_readonly); - int get_user_friendly_wwid(const char *alias, char *buff, const char *file); --char *use_existing_alias (const char *wwid, const char *file, -- const char *alias_old, -- const char *prefix, int bindings_read_only); -+char *get_user_friendly_alias(const char *wwid, const char *file, -+ const char *alias_old, -+ const char *prefix, bool bindings_read_only); - - struct config; - int check_alias_settings(const struct config *); -diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c -index d6bce129..354e883f 100644 ---- a/libmultipath/propsel.c -+++ b/libmultipath/propsel.c -@@ -401,19 +401,16 @@ int select_alias(struct config *conf, struct multipath * mp) - - select_alias_prefix(conf, mp); - -- if (strlen(mp->alias_old) > 0) { -- mp->alias = use_existing_alias(mp->wwid, conf->bindings_file, -- mp->alias_old, mp->alias_prefix, -- conf->bindings_read_only); -- memset (mp->alias_old, 0, WWID_SIZE); -- origin = "(setting: using existing alias)"; -- } -+ mp->alias = get_user_friendly_alias(mp->wwid, conf->bindings_file, -+ mp->alias_old, mp->alias_prefix, -+ conf->bindings_read_only); - -- if (mp->alias == NULL) { -- mp->alias = get_user_friendly_alias(mp->wwid, -- conf->bindings_file, mp->alias_prefix, conf->bindings_read_only); -+ if (mp->alias && !strncmp(mp->alias, mp->alias_old, WWID_SIZE)) -+ origin = "(setting: using existing alias)"; -+ else if (mp->alias) - origin = "(setting: user_friendly_name)"; -- } -+ memset (mp->alias_old, 0, WWID_SIZE); -+ - out: - if (mp->alias == NULL) { - mp->alias = strdup(mp->wwid); diff --git a/0044-RH-Fix-nvme-function-missing-argument.patch b/0004-RH-Fix-nvme-function-missing-argument.patch similarity index 100% rename from 0044-RH-Fix-nvme-function-missing-argument.patch rename to 0004-RH-Fix-nvme-function-missing-argument.patch diff --git a/0004-libmultipath-never-allocate-an-alias-that-s-already-.patch b/0004-libmultipath-never-allocate-an-alias-that-s-already-.patch deleted file mode 100644 index 3d05b85..0000000 --- a/0004-libmultipath-never-allocate-an-alias-that-s-already-.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Tue, 22 Aug 2023 22:23:29 +0200 -Subject: [PATCH] libmultipath: never allocate an alias that's already taken - -If the bindings file is changed in a way that multipathd can't handle -(e.g. by swapping the aliases of two maps), multipathd must not try -to re-use an alias that is already used by another map. Creating -or renaming a map with such an alias will fail. We already avoid -this for some cases, but not for all. Fix it. - -Signed-off-by: Martin Wilck -Cc: David Bond -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/alias.c | 31 +++++++++++++++++++++++-------- - tests/alias.c | 2 +- - 2 files changed, 24 insertions(+), 9 deletions(-) - -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index 68f5d848..3e3dfe98 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -120,7 +120,7 @@ static bool alias_already_taken(const char *alias, const char *map_wwid) - if (dm_get_uuid(alias, wwid, sizeof(wwid)) == 0 && - strncmp(map_wwid, wwid, sizeof(wwid)) == 0) - return false; -- condlog(3, "%s: alias '%s' already taken, but not in bindings file. reselecting alias", -+ condlog(3, "%s: alias '%s' already taken, reselecting alias", - map_wwid, alias); - return true; - } -@@ -359,12 +359,11 @@ char *get_user_friendly_alias(const char *wwid, const char *file, const char *al - rlookup_binding(f, buff, alias_old); - - if (strlen(buff) > 0) { -- /* if buff is our wwid, it's already -- * allocated correctly -- */ -+ /* If buff is our wwid, it's already allocated correctly. */ - if (strcmp(buff, wwid) == 0) { - alias = strdup(alias_old); - goto out; -+ - } else { - condlog(0, "alias %s already bound to wwid %s, cannot reuse", - alias_old, buff); -@@ -372,19 +371,35 @@ char *get_user_friendly_alias(const char *wwid, const char *file, const char *al - } - } - -- id = lookup_binding(f, wwid, &alias, NULL, 0); -+ /* -+ * Look for an existing alias in the bindings file. -+ * Pass prefix = NULL, so lookup_binding() won't try to allocate a new id. -+ */ -+ lookup_binding(f, wwid, &alias, NULL, 0); - if (alias) { -- condlog(3, "Use existing binding [%s] for WWID [%s]", -- alias, wwid); -+ if (alias_already_taken(alias, wwid)) { -+ free(alias); -+ alias = NULL; -+ } else -+ condlog(3, "Use existing binding [%s] for WWID [%s]", -+ alias, wwid); - goto out; - } - -- /* allocate the existing alias in the bindings file */ -+ /* alias_old is already taken by our WWID, update bindings file. */ - id = scan_devname(alias_old, prefix); - - new_alias: - if (id <= 0) { -+ /* -+ * no existing alias was provided, or allocating it -+ * failed. Try a new one. -+ */ - id = lookup_binding(f, wwid, &alias, prefix, 1); -+ if (id == 0 && alias_already_taken(alias, wwid)) { -+ free(alias); -+ alias = NULL; -+ } - if (id <= 0) - goto out; - else -diff --git a/tests/alias.c b/tests/alias.c -index 3ca6c28b..11f209e0 100644 ---- a/tests/alias.c -+++ b/tests/alias.c -@@ -398,7 +398,7 @@ static void mock_self_alias(const char *alias, const char *wwid) - will_return(__wrap_dm_get_uuid, wwid); - } - --#define USED_STR(alias_str, wwid_str) wwid_str ": alias '" alias_str "' already taken, but not in bindings file. reselecting alias\n" -+#define USED_STR(alias_str, wwid_str) wwid_str ": alias '" alias_str "' already taken, reselecting alias\n" - - static void mock_failed_alias(const char *alias, char *msg) - { diff --git a/0045-RH-use-rpm-optflags-if-present.patch b/0005-RH-use-rpm-optflags-if-present.patch similarity index 87% rename from 0045-RH-use-rpm-optflags-if-present.patch rename to 0005-RH-use-rpm-optflags-if-present.patch index 1ad6b40..6352c23 100644 --- a/0045-RH-use-rpm-optflags-if-present.patch +++ b/0005-RH-use-rpm-optflags-if-present.patch @@ -13,12 +13,12 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/Makefile.inc b/Makefile.inc -index 62d3d5cc..72fd8d57 100644 +index 0b0e3ad2..3d80d224 100644 --- a/Makefile.inc +++ b/Makefile.inc -@@ -91,11 +91,23 @@ ORIG_LDFLAGS := $(LDFLAGS) - SYSTEMD_CPPFLAGS := $(if $(SYSTEMD),-DUSE_SYSTEMD=$(SYSTEMD)) - SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo 1),-lsystemd,-lsystemd-daemon)) +@@ -95,11 +95,23 @@ SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo + MODPROBE_UNIT := $(shell test "0$(SYSTEMD)" -lt 245 2>/dev/null || \ + echo "modprobe@dm_multipath.service") -OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4 -WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implicit-int \ @@ -44,7 +44,7 @@ index 62d3d5cc..72fd8d57 100644 -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \ -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \ -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DSTATE_DIR=\"$(statedir)\" \ -@@ -104,7 +116,7 @@ CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe +@@ -108,7 +120,7 @@ CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe BIN_CFLAGS := -fPIE -DPIE LIB_CFLAGS := -fPIC SHARED_FLAGS := -shared diff --git a/0005-libmultipath-lookup_binding-add-comment-about-the-al.patch b/0005-libmultipath-lookup_binding-add-comment-about-the-al.patch deleted file mode 100644 index 71d077a..0000000 --- a/0005-libmultipath-lookup_binding-add-comment-about-the-al.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Tue, 22 Aug 2023 22:30:16 +0200 -Subject: [PATCH] libmultipath: lookup_binding: add comment about the algorithm - -When I read this code, I always get confused. Adding comments to -explain the algorithm. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/alias.c | 35 +++++++++++++++++++++++++++++++++++ - 1 file changed, 35 insertions(+) - -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index 3e3dfe98..9e9ac563 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -172,6 +172,41 @@ lookup_binding(FILE *f, const char *map_wwid, char **map_alias, - alias = strtok_r(buf, " \t", &saveptr); - if (!alias) /* blank line */ - continue; -+ -+ /* -+ * Find an unused index - explanation of the algorithm -+ * -+ * ID: 1 = mpatha, 2 = mpathb, ... -+ * -+ * We assume the bindings are unsorted. The only constraint -+ * is that no ID occurs more than once. IDs that occur in the -+ * bindings are called "used". -+ * -+ * We call the list 1,2,3,..., exactly in this order, the list -+ * of "expected" IDs. The variable "id" always holds the next -+ * "expected" ID, IOW the last "expected" ID encountered plus 1. -+ * Thus all IDs below "id" are known to be used. However, at the -+ * end of the loop, the value of "id" isn't necessarily unused. -+ * -+ * "smallest_bigger_id" is the smallest used ID that was -+ * encountered while it was larger than the next "expected" ID -+ * at that iteration. Let X be some used ID. If all IDs below X -+ * are used and encountered in the right sequence before X, "id" -+ * will be > X when the loop ends. Otherwise, X was encountered -+ * "out of order", the condition (X > id) holds when X is -+ * encountered, and "smallest_bigger_id" will be set to X; i.e. -+ * it will be less or equal than X when the loop ends. -+ * -+ * At the end of the loop, (id < smallest_bigger_id) means that -+ * the value of "id" had been encountered neither in order nor -+ * out of order, and is thus unused. (id >= smallest_bigger_id) -+ * means that "id"'s value is in use. In this case, we play safe -+ * and use "biggest_id + 1" as the next value to try. -+ * -+ * biggest_id is always > smallest_bigger_id, except in the -+ * "perfectly ordered" case. -+ */ -+ - curr_id = scan_devname(alias, prefix); - if (curr_id == id) { - if (id < INT_MAX) diff --git a/0046-RH-add-mpathconf.patch b/0006-RH-add-mpathconf.patch similarity index 99% rename from 0046-RH-add-mpathconf.patch rename to 0006-RH-add-mpathconf.patch index 01bc8d2..7782f65 100644 --- a/0046-RH-add-mpathconf.patch +++ b/0006-RH-add-mpathconf.patch @@ -34,7 +34,7 @@ index 3a374b3d..4544f484 100644 conf->blist_devnode = vector_alloc(); if (!conf->blist_devnode) { diff --git a/multipath/Makefile b/multipath/Makefile -index f70e64ec..9942d1a9 100644 +index 504d6892..9f14036c 100644 --- a/multipath/Makefile +++ b/multipath/Makefile @@ -24,6 +24,7 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so @@ -45,15 +45,15 @@ index f70e64ec..9942d1a9 100644 $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) $(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) $(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules -@@ -33,6 +34,7 @@ install: +@@ -31,6 +32,7 @@ install: $(Q)$(INSTALL_PROGRAM) -m 644 tmpfiles.conf $(DESTDIR)$(tmpfilesdir)/multipath.conf $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man8 $(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)/man8 + $(Q)$(INSTALL_PROGRAM) -m 644 mpathconf.8 $(DESTDIR)$(mandir)/man8 $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man5 $(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5 $(DESTDIR)$(mandir)/man5 - ifneq ($(SCSI_DH_MODULES_PRELOAD),) -@@ -43,11 +45,13 @@ endif + $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(modulesloaddir) +@@ -45,11 +47,13 @@ endif uninstall: $(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC) diff --git a/0006-multipath-tools-test-simplify-debugging-for-condlog-.patch b/0006-multipath-tools-test-simplify-debugging-for-condlog-.patch deleted file mode 100644 index a206358..0000000 --- a/0006-multipath-tools-test-simplify-debugging-for-condlog-.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Wed, 23 Aug 2023 22:56:41 +0200 -Subject: [PATCH] multipath-tools test: simplify debugging for condlog mismatch - -If there's a mismatch between expected and actual log message, -print both messages. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - tests/test-log.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/tests/test-log.c b/tests/test-log.c -index c1745872..63516999 100644 ---- a/tests/test-log.c -+++ b/tests/test-log.c -@@ -16,12 +16,14 @@ void __wrap_dlog (int prio, const char * fmt, ...) - va_list ap; - char *expected; - -- check_expected(prio); - va_start(ap, fmt); - vsnprintf(buff, MAX_MSG_SIZE, fmt, ap); - va_end(ap); - fprintf(stderr, "%s(%d): %s", __func__, prio, buff); - expected = mock_ptr_type(char *); -+ if (memcmp(expected, buff, strlen(expected))) -+ fprintf(stderr, "%s(expected): %s", __func__, expected); -+ check_expected(prio); - assert_memory_equal(buff, expected, strlen(expected)); - } - diff --git a/0047-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch b/0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch similarity index 93% rename from 0047-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch rename to 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch index 7714825..a3c4e9d 100644 --- a/0047-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +++ b/0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch @@ -14,9 +14,9 @@ multipathd.service Signed-off-by: Benjamin Marzinski --- - multipath/main.c | 54 +++++++++++++++++++++++++++++++++-- - multipath/multipath.8.in | 7 ++++- - multipathd/multipathd.service | 1 + + multipath/main.c | 54 ++++++++++++++++++++++++++++++-- + multipath/multipath.8.in | 7 ++++- + multipathd/multipathd.service.in | 1 + 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/multipath/main.c b/multipath/main.c @@ -137,10 +137,10 @@ index 348eb220..82a7e68e 100644 .B \-w Remove the WWID for the specified device from the WWIDs file. . -diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service -index 311f49c7..5324f4bc 100644 ---- a/multipathd/multipathd.service -+++ b/multipathd/multipathd.service +diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in +index 0965d6f9..c964eb1b 100644 +--- a/multipathd/multipathd.service.in ++++ b/multipathd/multipathd.service.in @@ -17,6 +17,7 @@ ConditionVirtualization=!container [Service] Type=notify diff --git a/0007-multipath-tools-tests-add-tests-for-get_user_friendl.patch b/0007-multipath-tools-tests-add-tests-for-get_user_friendl.patch deleted file mode 100644 index f829db4..0000000 --- a/0007-multipath-tools-tests-add-tests-for-get_user_friendl.patch +++ /dev/null @@ -1,493 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Wed, 23 Aug 2023 22:57:29 +0200 -Subject: [PATCH] multipath-tools tests: add tests for - get_user_friendly_alias() - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - tests/alias.c | 441 ++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 441 insertions(+) - -diff --git a/tests/alias.c b/tests/alias.c -index 11f209e0..7e443b06 100644 ---- a/tests/alias.c -+++ b/tests/alias.c -@@ -81,6 +81,35 @@ int __wrap_dm_get_uuid(const char *name, char *uuid, int uuid_len) - return ret; - } - -+#define TEST_FDNO 1234 -+#define TEST_FPTR ((FILE *) 0xaffe) -+ -+int __wrap_open_file(const char *file, int *can_write, const char *header) -+{ -+ int cw = mock_type(int); -+ -+ *can_write = cw; -+ return TEST_FDNO; -+} -+ -+FILE *__wrap_fdopen(int fd, const char *mode) -+{ -+ assert_int_equal(fd, TEST_FDNO); -+ return TEST_FPTR; -+} -+ -+int __wrap_fflush(FILE *f) -+{ -+ assert_ptr_equal(f, TEST_FPTR); -+ return 0; -+} -+ -+int __wrap_fclose(FILE *f) -+{ -+ assert_ptr_equal(f, TEST_FPTR); -+ return 0; -+} -+ - /* strbuf wrapper for the old format_devname() */ - static int __format_devname(char *name, int id, size_t len, const char *prefix) - { -@@ -399,6 +428,22 @@ static void mock_self_alias(const char *alias, const char *wwid) - } - - #define USED_STR(alias_str, wwid_str) wwid_str ": alias '" alias_str "' already taken, reselecting alias\n" -+#define NOMATCH_STR(alias_str) ("No matching alias [" alias_str "] in bindings file.\n") -+#define FOUND_STR(alias_str, wwid_str) \ -+ "Found matching wwid [" wwid_str "] in bindings file." \ -+ " Setting alias to " alias_str "\n" -+#define FOUND_ALIAS_STR(alias_str, wwid_str) \ -+ "Found matching alias [" alias_str "] in bindings file." \ -+ " Setting wwid to " wwid_str "\n" -+#define NOMATCH_WWID_STR(wwid_str) ("No matching wwid [" wwid_str "] in bindings file.\n") -+#define NEW_STR(alias_str, wwid_str) ("Created new binding [" alias_str "] for WWID [" wwid_str "]\n") -+#define EXISTING_STR(alias_str, wwid_str) ("Use existing binding [" alias_str "] for WWID [" wwid_str "]\n") -+#define ALLOC_STR(alias_str, wwid_str) ("Allocated existing binding [" alias_str "] for WWID [" wwid_str "]\n") -+#define BINDING_STR(alias_str, wwid_str) (alias_str " " wwid_str "\n") -+#define BOUND_STR(alias_str, wwid_str) ("alias "alias_str " already bound to wwid " wwid_str ", cannot reuse") -+#define ERR_STR(alias_str, wwid_str) ("ERROR: old alias [" alias_str "] for wwid [" wwid_str "] is used by other map\n") -+#define REUSE_STR(alias_str, wwid_str) ("alias " alias_str " already bound to wwid " wwid_str ", cannot reuse\n") -+#define NOMORE_STR "no more available user_friendly_names\n" - - static void mock_failed_alias(const char *alias, char *msg) - { -@@ -421,6 +466,24 @@ static void mock_used_alias(const char *alias, char *msg) - expect_condlog(3, msg); - } - -+static void mock_bindings_file(const char *content, int match_line) -+{ -+ static char cnt[1024]; -+ char *token; -+ int i; -+ -+ assert_in_range(strlcpy(cnt, content, sizeof(cnt)), 0, sizeof(cnt) - 1); -+ -+ for (token = strtok(cnt, "\n"), i = 0; -+ token && *token; -+ token = strtok(NULL, "\n"), i++) { -+ will_return(__wrap_fgets, token); -+ if (match_line == i) -+ return; -+ } -+ will_return(__wrap_fgets, NULL); -+} -+ - static void lb_empty(void **state) - { - int rc; -@@ -1147,6 +1210,382 @@ static int test_allocate_binding(void) - return cmocka_run_group_tests(tests, NULL, NULL); - } - -+#define mock_allocate_binding(alias, wwid) \ -+ do { \ -+ static const char ln[] = BINDING_STR(alias, wwid); \ -+ \ -+ will_return(__wrap_lseek, 0); \ -+ expect_value(__wrap_write, count, strlen(ln)); \ -+ expect_string(__wrap_write, buf, ln); \ -+ will_return(__wrap_write, strlen(ln)); \ -+ expect_condlog(3, NEW_STR(alias, wwid)); \ -+ } while (0) -+ -+static void gufa_empty_new_rw(void **state) { -+ char *alias; -+ -+ will_return(__wrap_open_file, true); -+ -+ will_return(__wrap_fgets, NULL); -+ mock_unused_alias("MPATHa"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); -+ -+ mock_allocate_binding("MPATHa", "WWID0"); -+ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false); -+ assert_string_equal(alias, "MPATHa"); -+ free(alias); -+} -+ -+static void gufa_empty_new_ro_1(void **state) { -+ char *alias; -+ will_return(__wrap_open_file, false); -+ will_return(__wrap_fgets, NULL); -+ mock_unused_alias("MPATHa"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); -+ -+ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false); -+ assert_ptr_equal(alias, NULL); -+} -+ -+static void gufa_empty_new_ro_2(void **state) { -+ char *alias; -+ -+ will_return(__wrap_open_file, true); -+ -+ will_return(__wrap_fgets, NULL); -+ mock_unused_alias("MPATHa"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); -+ -+ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); -+ assert_ptr_equal(alias, NULL); -+} -+ -+static void gufa_match_a_unused(void **state) { -+ char *alias; -+ -+ will_return(__wrap_open_file, true); -+ -+ will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0")); -+ expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); -+ mock_unused_alias("MPATHa"); -+ -+ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); -+ assert_string_equal(alias, "MPATHa"); -+ free(alias); -+} -+ -+static void gufa_match_a_self(void **state) { -+ char *alias; -+ -+ will_return(__wrap_open_file, true); -+ -+ will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0")); -+ expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); -+ mock_self_alias("MPATHa", "WWID0"); -+ -+ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); -+ assert_string_equal(alias, "MPATHa"); -+ free(alias); -+} -+ -+static void gufa_match_a_used(void **state) { -+ char *alias; -+ -+ will_return(__wrap_open_file, true); -+ -+ will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0")); -+ expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); -+ mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); -+ -+ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); -+ assert_ptr_equal(alias, NULL); -+} -+ -+static void gufa_nomatch_a_c(void **state) { -+ char *alias; -+ will_return(__wrap_open_file, true); -+ -+ mock_bindings_file("MPATHa WWID0\n" -+ "MPATHc WWID2", -+ -1); -+ mock_unused_alias("MPATHb"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID1")); -+ -+ mock_allocate_binding("MPATHb", "WWID1"); -+ -+ alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false); -+ assert_string_equal(alias, "MPATHb"); -+ free(alias); -+} -+ -+static void gufa_nomatch_c_a(void **state) { -+ char *alias; -+ will_return(__wrap_open_file, true); -+ -+ mock_bindings_file("MPATHc WWID2\n" -+ "MPATHa WWID0", -+ -1); -+ mock_unused_alias("MPATHb"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID1")); -+ -+ mock_allocate_binding("MPATHb", "WWID1"); -+ -+ alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false); -+ assert_string_equal(alias, "MPATHb"); -+ free(alias); -+} -+ -+static void gufa_nomatch_c_b(void **state) { -+ char *alias; -+ will_return(__wrap_open_file, true); -+ -+ mock_bindings_file("MPATHc WWID2\n" -+ "MPATHb WWID1\n", -+ -1); -+ mock_unused_alias("MPATHa"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); -+ -+ mock_allocate_binding("MPATHa", "WWID0"); -+ -+ alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false); -+ assert_string_equal(alias, "MPATHa"); -+ free(alias); -+} -+ -+static void gufa_nomatch_c_b_used(void **state) { -+ char *alias; -+ will_return(__wrap_open_file, true); -+ -+ mock_bindings_file("MPATHc WWID2\n" -+ "MPATHb WWID1", -+ -1); -+ mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID4")); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID4")); -+ mock_unused_alias("MPATHd"); -+ -+ mock_allocate_binding("MPATHd", "WWID4"); -+ -+ alias = get_user_friendly_alias("WWID4", "x", "", "MPATH", false); -+ assert_string_equal(alias, "MPATHd"); -+ free(alias); -+} -+ -+static void gufa_nomatch_b_f_a(void **state) { -+ char *alias; -+ will_return(__wrap_open_file, true); -+ -+ mock_bindings_file("MPATHb WWID1\n" -+ "MPATHf WWID6\n" -+ "MPATHa WWID0\n", -+ -1); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID7")); -+ mock_unused_alias("MPATHg"); -+ -+ mock_allocate_binding("MPATHg", "WWID7"); -+ -+ alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false); -+ assert_string_equal(alias, "MPATHg"); -+ free(alias); -+} -+ -+static void gufa_old_empty(void **state) { -+ char *alias; -+ will_return(__wrap_open_file, true); -+ -+ /* rlookup_binding for ALIAS */ -+ will_return(__wrap_fgets, NULL); -+ expect_condlog(3, NOMATCH_STR("MPATHz")); -+ -+ /* lookup_binding */ -+ will_return(__wrap_fgets, NULL); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); -+ -+ mock_allocate_binding("MPATHz", "WWID0"); -+ expect_condlog(2, ALLOC_STR("MPATHz", "WWID0")); -+ -+ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); -+ assert_string_equal(alias, "MPATHz"); -+ free(alias); -+} -+ -+static void gufa_old_match(void **state) { -+ char *alias; -+ will_return(__wrap_open_file, true); -+ -+ mock_bindings_file("MPATHb WWID1\n" -+ "MPATHz WWID0", -+ 1); -+ expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID0")); -+ -+ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); -+ assert_string_equal(alias, "MPATHz"); -+ free(alias); -+} -+ -+static void gufa_old_match_other(void **state) { -+ char *alias; -+ static const char bindings[] = "MPATHz WWID9"; -+ -+ will_return(__wrap_open_file, true); -+ -+ mock_bindings_file(bindings, 0); -+ expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9")); -+ expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); -+ -+ mock_bindings_file(bindings, -1); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); -+ mock_unused_alias("MPATHa"); -+ -+ mock_allocate_binding("MPATHa", "WWID0"); -+ -+ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); -+ assert_string_equal(alias, "MPATHa"); -+ free(alias); -+} -+ -+static void gufa_old_match_other_used(void **state) { -+ char *alias; -+ static const char bindings[] = "MPATHz WWID9"; -+ -+ will_return(__wrap_open_file, true); -+ -+ mock_bindings_file(bindings, 0); -+ expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9")); -+ expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); -+ -+ mock_bindings_file(bindings, -1); -+ mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); -+ mock_unused_alias("MPATHb"); -+ -+ mock_allocate_binding("MPATHb", "WWID0"); -+ -+ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); -+ assert_string_equal(alias, "MPATHb"); -+ free(alias); -+} -+ -+static void gufa_old_match_other_wwidmatch(void **state) { -+ char *alias; -+ static const char bindings[] = ("MPATHz WWID9\n" -+ "MPATHc WWID2"); -+ will_return(__wrap_open_file, true); -+ -+ mock_bindings_file(bindings, 0); -+ expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9")); -+ expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); -+ -+ mock_bindings_file(bindings, 1); -+ expect_condlog(3, FOUND_STR("MPATHc", "WWID2")); -+ mock_unused_alias("MPATHc"); -+ -+ alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false); -+ assert_string_equal(alias, "MPATHc"); -+ free(alias); -+} -+ -+static void gufa_old_match_other_wwidmatch_used(void **state) { -+ char *alias; -+ static const char bindings[] = ("MPATHz WWID9\n" -+ "MPATHc WWID2"); -+ -+ will_return(__wrap_open_file, true); -+ -+ mock_bindings_file(bindings, 0); -+ expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9")); -+ expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); -+ -+ mock_bindings_file(bindings, 1); -+ expect_condlog(3, FOUND_STR("MPATHc", "WWID2")); -+ mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2")); -+ -+ alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false); -+ assert_ptr_equal(alias, NULL); -+} -+ -+static void gufa_old_nomatch_wwidmatch(void **state) { -+ char *alias; -+ static const char bindings[] = "MPATHa WWID0"; -+ -+ will_return(__wrap_open_file, true); -+ -+ mock_bindings_file(bindings, -1); -+ expect_condlog(3, NOMATCH_STR("MPATHz")); -+ -+ mock_bindings_file(bindings, 0); -+ expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); -+ mock_unused_alias("MPATHa"); -+ expect_condlog(3, EXISTING_STR("MPATHa", "WWID0")); -+ -+ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); -+ assert_string_equal(alias, "MPATHa"); -+ free(alias); -+} -+ -+static void gufa_old_nomatch_wwidmatch_used(void **state) { -+ char *alias; -+ static const char bindings[] = "MPATHa WWID0"; -+ will_return(__wrap_open_file, true); -+ -+ mock_bindings_file(bindings, -1); -+ expect_condlog(3, NOMATCH_STR("MPATHz")); -+ -+ mock_bindings_file(bindings, 0); -+ expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); -+ mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); -+ -+ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); -+ assert_ptr_equal(alias, NULL); -+} -+ -+static void gufa_old_nomatch_nowwidmatch(void **state) { -+ char *alias; -+ static const char bindings[] = "MPATHb WWID1"; -+ -+ will_return(__wrap_open_file, true); -+ -+ mock_bindings_file(bindings, -1); -+ expect_condlog(3, NOMATCH_STR("MPATHz")); -+ -+ mock_bindings_file(bindings, -1); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); -+ -+ mock_allocate_binding("MPATHz", "WWID0"); -+ expect_condlog(2, ALLOC_STR("MPATHz", "WWID0")); -+ -+ alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); -+ assert_string_equal(alias, "MPATHz"); -+ free(alias); -+} -+ -+static int test_get_user_friendly_alias() -+{ -+ const struct CMUnitTest tests[] = { -+ cmocka_unit_test(gufa_empty_new_rw), -+ cmocka_unit_test(gufa_empty_new_ro_1), -+ cmocka_unit_test(gufa_empty_new_ro_2), -+ cmocka_unit_test(gufa_match_a_unused), -+ cmocka_unit_test(gufa_match_a_self), -+ cmocka_unit_test(gufa_match_a_used), -+ cmocka_unit_test(gufa_nomatch_a_c), -+ cmocka_unit_test(gufa_nomatch_c_a), -+ cmocka_unit_test(gufa_nomatch_c_b), -+ cmocka_unit_test(gufa_nomatch_c_b_used), -+ cmocka_unit_test(gufa_nomatch_b_f_a), -+ cmocka_unit_test(gufa_old_empty), -+ cmocka_unit_test(gufa_old_match), -+ cmocka_unit_test(gufa_old_match_other), -+ cmocka_unit_test(gufa_old_match_other_used), -+ cmocka_unit_test(gufa_old_match_other_wwidmatch), -+ cmocka_unit_test(gufa_old_match_other_wwidmatch_used), -+ cmocka_unit_test(gufa_old_nomatch_wwidmatch), -+ cmocka_unit_test(gufa_old_nomatch_wwidmatch_used), -+ cmocka_unit_test(gufa_old_nomatch_nowwidmatch), -+ }; -+ -+ return cmocka_run_group_tests(tests, NULL, NULL); -+} -+ - int main(void) - { - int ret = 0; -@@ -1157,6 +1596,8 @@ int main(void) - ret += test_lookup_binding(); - ret += test_rlookup_binding(); - ret += test_allocate_binding(); -+ ret += test_allocate_binding(); -+ ret += test_get_user_friendly_alias(); - - return ret; - } diff --git a/0048-RH-reset-default-find_mutipaths-value-to-off.patch b/0008-RH-reset-default-find_mutipaths-value-to-off.patch similarity index 96% rename from 0048-RH-reset-default-find_mutipaths-value-to-off.patch rename to 0008-RH-reset-default-find_mutipaths-value-to-off.patch index 432b070..4e1253c 100644 --- a/0048-RH-reset-default-find_mutipaths-value-to-off.patch +++ b/0008-RH-reset-default-find_mutipaths-value-to-off.patch @@ -12,7 +12,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h -index d01f9712..ee2e13a9 100644 +index 64b633f2..5bda9f93 100644 --- a/libmultipath/defaults.h +++ b/libmultipath/defaults.h @@ -23,7 +23,7 @@ diff --git a/0008-multipath-tools-test-consistent-use-of-macros-in-ali.patch b/0008-multipath-tools-test-consistent-use-of-macros-in-ali.patch deleted file mode 100644 index 430ceaf..0000000 --- a/0008-multipath-tools-test-consistent-use-of-macros-in-ali.patch +++ /dev/null @@ -1,365 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 24 Aug 2023 10:40:32 +0200 -Subject: [PATCH] multipath-tools test: consistent use of macros in alias test - -Use the macros introduced with the tests for get_user_friendly_alias() -also in the previously existing tests. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - tests/alias.c | 80 ++++++++++++++++++++++++--------------------------- - 1 file changed, 38 insertions(+), 42 deletions(-) - -diff --git a/tests/alias.c b/tests/alias.c -index 7e443b06..427b2814 100644 ---- a/tests/alias.c -+++ b/tests/alias.c -@@ -490,7 +490,7 @@ static void lb_empty(void **state) - char *alias; - - will_return(__wrap_fgets, NULL); -- expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - rc = lookup_binding(NULL, "WWID0", &alias, NULL, 0); - assert_int_equal(rc, 1); - assert_ptr_equal(alias, NULL); -@@ -503,7 +503,7 @@ static void lb_empty_unused(void **state) - - will_return(__wrap_fgets, NULL); - mock_unused_alias("MPATHa"); -- expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); - assert_int_equal(rc, 1); - assert_ptr_equal(alias, NULL); -@@ -518,7 +518,7 @@ static void lb_empty_failed(void **state) - will_return(__wrap_fgets, NULL); - mock_failed_alias("MPATHa", USED_STR("MPATHa", "WWID0")); - mock_unused_alias("MPATHb"); -- expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); - assert_int_equal(rc, 2); - assert_ptr_equal(alias, NULL); -@@ -533,7 +533,7 @@ static void lb_empty_1_used(void **state) - will_return(__wrap_fgets, NULL); - mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); - mock_unused_alias("MPATHb"); -- expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); - assert_int_equal(rc, 2); - assert_ptr_equal(alias, NULL); -@@ -548,7 +548,7 @@ static void lb_empty_1_used_self(void **state) - will_return(__wrap_fgets, NULL); - mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); - mock_self_alias("MPATHb", "WWID0"); -- expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); - assert_int_equal(rc, 2); - assert_ptr_equal(alias, NULL); -@@ -561,8 +561,7 @@ static void lb_match_a(void **state) - char *alias; - - will_return(__wrap_fgets, "MPATHa WWID0\n"); -- expect_condlog(3, "Found matching wwid [WWID0] in bindings file." -- " Setting alias to MPATHa\n"); -+ expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); - rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 0); - assert_int_equal(rc, 0); - assert_ptr_not_equal(alias, NULL); -@@ -577,7 +576,7 @@ static void lb_nomatch_a(void **state) - - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, NULL); -- expect_condlog(3, "No matching wwid [WWID1] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID1")); - rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 0); - assert_int_equal(rc, 2); - assert_ptr_equal(alias, NULL); -@@ -590,7 +589,7 @@ static void lb_nomatch_a_bad_check(void **state) - - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, NULL); -- expect_condlog(0, "no more available user_friendly_names\n"); -+ expect_condlog(0, NOMORE_STR); - rc = lookup_binding(NULL, "WWID1", &alias, NULL, 1); - assert_int_equal(rc, -1); - assert_ptr_equal(alias, NULL); -@@ -604,7 +603,7 @@ static void lb_nomatch_a_unused(void **state) - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, NULL); - mock_unused_alias("MPATHb"); -- expect_condlog(3, "No matching wwid [WWID1] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID1")); - rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); - assert_int_equal(rc, 2); - assert_ptr_equal(alias, NULL); -@@ -622,7 +621,7 @@ static void lb_nomatch_a_3_used_failed_self(void **state) - mock_used_alias("MPATHd", USED_STR("MPATHd", "WWID1")); - mock_failed_alias("MPATHe", USED_STR("MPATHe", "WWID1")); - mock_self_alias("MPATHf", "WWID1"); -- expect_condlog(3, "No matching wwid [WWID1] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID1")); - rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); - assert_int_equal(rc, 6); - assert_ptr_equal(alias, NULL); -@@ -635,8 +634,7 @@ static void do_lb_match_c(void **state, int check_if_taken) - - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, "MPATHc WWID1\n"); -- expect_condlog(3, "Found matching wwid [WWID1] in bindings file." -- " Setting alias to MPATHc\n"); -+ expect_condlog(3, FOUND_STR("MPATHc", "WWID1")); - rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", check_if_taken); - assert_int_equal(rc, 0); - assert_ptr_not_equal(alias, NULL); -@@ -662,7 +660,7 @@ static void lb_nomatch_a_c(void **state) - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, "MPATHc WWID1\n"); - will_return(__wrap_fgets, NULL); -- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); - assert_int_equal(rc, 2); - assert_ptr_equal(alias, NULL); -@@ -677,7 +675,7 @@ static void lb_nomatch_a_d_unused(void **state) - will_return(__wrap_fgets, "MPATHd WWID1\n"); - will_return(__wrap_fgets, NULL); - mock_unused_alias("MPATHb"); -- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, 2); - assert_ptr_equal(alias, NULL); -@@ -693,7 +691,7 @@ static void lb_nomatch_a_d_1_used(void **state) - will_return(__wrap_fgets, NULL); - mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2")); - mock_unused_alias("MPATHc"); -- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, 3); - assert_ptr_equal(alias, NULL); -@@ -710,7 +708,7 @@ static void lb_nomatch_a_d_2_used(void **state) - mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2")); - mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2")); - mock_unused_alias("MPATHe"); -- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, 5); - assert_ptr_equal(alias, NULL); -@@ -728,7 +726,7 @@ static void lb_nomatch_a_d_3_used(void **state) - mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2")); - mock_used_alias("MPATHe", USED_STR("MPATHe", "WWID2")); - mock_unused_alias("MPATHf"); -- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, 6); - assert_ptr_equal(alias, NULL); -@@ -742,7 +740,7 @@ static void lb_nomatch_c_a(void **state) - will_return(__wrap_fgets, "MPATHc WWID1\n"); - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, NULL); -- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); - assert_int_equal(rc, 2); - assert_ptr_equal(alias, NULL); -@@ -758,7 +756,7 @@ static void lb_nomatch_d_a_unused(void **state) - will_return(__wrap_fgets, "MPATHd WWID0\n"); - will_return(__wrap_fgets, NULL); - mock_unused_alias("MPATHb"); -- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, 2); - assert_ptr_equal(alias, NULL); -@@ -775,7 +773,7 @@ static void lb_nomatch_d_a_1_used(void **state) - will_return(__wrap_fgets, NULL); - mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2")); - mock_unused_alias("MPATHe"); -- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, 5); - assert_ptr_equal(alias, NULL); -@@ -790,7 +788,7 @@ static void lb_nomatch_a_b(void **state) - will_return(__wrap_fgets, "MPATHz WWID26\n"); - will_return(__wrap_fgets, "MPATHb WWID1\n"); - will_return(__wrap_fgets, NULL); -- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); - assert_int_equal(rc, 3); - assert_ptr_equal(alias, NULL); -@@ -806,7 +804,7 @@ static void lb_nomatch_a_b_bad(void **state) - will_return(__wrap_fgets, "MPATHb\n"); - will_return(__wrap_fgets, NULL); - expect_condlog(3, "Ignoring malformed line 3 in bindings file\n"); -- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); - assert_int_equal(rc, 3); - assert_ptr_equal(alias, NULL); -@@ -823,7 +821,7 @@ static void lb_nomatch_a_b_bad_self(void **state) - will_return(__wrap_fgets, NULL); - expect_condlog(3, "Ignoring malformed line 3 in bindings file\n"); - mock_self_alias("MPATHc", "WWID2"); -- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, 3); - assert_ptr_equal(alias, NULL); -@@ -838,7 +836,7 @@ static void lb_nomatch_b_a(void **state) - will_return(__wrap_fgets, "MPATHz WWID26\n"); - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, NULL); -- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); - assert_int_equal(rc, 27); - assert_ptr_equal(alias, NULL); -@@ -857,7 +855,7 @@ static void lb_nomatch_b_a_3_used(void **state) - mock_used_alias("MPATHab", USED_STR("MPATHab", "WWID2")); - mock_used_alias("MPATHac", USED_STR("MPATHac", "WWID2")); - mock_unused_alias("MPATHad"); -- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, 30); - assert_ptr_equal(alias, NULL); -@@ -873,7 +871,7 @@ static void do_lb_nomatch_int_max(void **state, int check_if_taken) - will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n"); - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, NULL); -- expect_condlog(0, "no more available user_friendly_names\n"); -+ expect_condlog(0, NOMORE_STR); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", check_if_taken); - assert_int_equal(rc, -1); - assert_ptr_equal(alias, NULL); -@@ -898,7 +896,7 @@ static void lb_nomatch_int_max_used(void **state) - will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n"); - will_return(__wrap_fgets, NULL); - mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2")); -- expect_condlog(0, "no more available user_friendly_names\n"); -+ expect_condlog(0, NOMORE_STR); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, -1); - assert_ptr_equal(alias, NULL); -@@ -913,7 +911,7 @@ static void lb_nomatch_int_max_m1(void **state) - will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, NULL); -- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); - assert_int_equal(rc, INT_MAX); - assert_ptr_equal(alias, NULL); -@@ -929,7 +927,7 @@ static void lb_nomatch_int_max_m1_used(void **state) - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, NULL); - mock_used_alias("MPATH" MPATH_ID_INT_MAX, USED_STR("MPATH" MPATH_ID_INT_MAX, "WWID2")); -- expect_condlog(0, "no more available user_friendly_names\n"); -+ expect_condlog(0, NOMORE_STR); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, -1); - assert_ptr_equal(alias, NULL); -@@ -945,7 +943,7 @@ static void lb_nomatch_int_max_m1_1_used(void **state) - will_return(__wrap_fgets, NULL); - mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2")); - mock_unused_alias("MPATH" MPATH_ID_INT_MAX); -- expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, INT_MAX); - assert_ptr_equal(alias, NULL); -@@ -961,7 +959,7 @@ static void lb_nomatch_int_max_m1_2_used(void **state) - will_return(__wrap_fgets, NULL); - mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2")); - mock_used_alias("MPATH" MPATH_ID_INT_MAX, USED_STR("MPATH" MPATH_ID_INT_MAX, "WWID2")); -- expect_condlog(0, "no more available user_friendly_names\n"); -+ expect_condlog(0, NOMORE_STR); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, -1); - assert_ptr_equal(alias, NULL); -@@ -1017,7 +1015,7 @@ static void rl_empty(void **state) - - buf[0] = '\0'; - will_return(__wrap_fgets, NULL); -- expect_condlog(3, "No matching alias [MPATHa] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_STR("MPATHa")); - rc = rlookup_binding(NULL, buf, "MPATHa"); - assert_int_equal(rc, -1); - assert_string_equal(buf, ""); -@@ -1030,8 +1028,7 @@ static void rl_match_a(void **state) - - buf[0] = '\0'; - will_return(__wrap_fgets, "MPATHa WWID0\n"); -- expect_condlog(3, "Found matching alias [MPATHa] in bindings file. " -- "Setting wwid to WWID0\n"); -+ expect_condlog(3, FOUND_ALIAS_STR("MPATHa", "WWID0")); - rc = rlookup_binding(NULL, buf, "MPATHa"); - assert_int_equal(rc, 0); - assert_string_equal(buf, "WWID0"); -@@ -1045,7 +1042,7 @@ static void rl_nomatch_a(void **state) - buf[0] = '\0'; - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, NULL); -- expect_condlog(3, "No matching alias [MPATHb] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_STR("MPATHb")); - rc = rlookup_binding(NULL, buf, "MPATHb"); - assert_int_equal(rc, -1); - assert_string_equal(buf, ""); -@@ -1060,7 +1057,7 @@ static void rl_malformed_a(void **state) - will_return(__wrap_fgets, "MPATHa \n"); - will_return(__wrap_fgets, NULL); - expect_condlog(3, "Ignoring malformed line 1 in bindings file\n"); -- expect_condlog(3, "No matching alias [MPATHa] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_STR("MPATHa")); - rc = rlookup_binding(NULL, buf, "MPATHa"); - assert_int_equal(rc, -1); - assert_string_equal(buf, ""); -@@ -1080,7 +1077,7 @@ static void rl_overlong_a(void **state) - will_return(__wrap_fgets, line); - will_return(__wrap_fgets, NULL); - expect_condlog(3, "Ignoring too large wwid at 1 in bindings file\n"); -- expect_condlog(3, "No matching alias [MPATHa] in bindings file.\n"); -+ expect_condlog(3, NOMATCH_STR("MPATHa")); - rc = rlookup_binding(NULL, buf, "MPATHa"); - assert_int_equal(rc, -1); - assert_string_equal(buf, ""); -@@ -1095,8 +1092,7 @@ static void rl_match_b(void **state) - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, "MPATHz WWID26\n"); - will_return(__wrap_fgets, "MPATHb WWID2\n"); -- expect_condlog(3, "Found matching alias [MPATHb] in bindings file. " -- "Setting wwid to WWID2\n"); -+ expect_condlog(3, FOUND_ALIAS_STR("MPATHb", "WWID2")); - rc = rlookup_binding(NULL, buf, "MPATHb"); - assert_int_equal(rc, 0); - assert_string_equal(buf, "WWID2"); -@@ -1125,7 +1121,7 @@ static void al_a(void **state) - expect_value(__wrap_write, count, strlen(ln)); - expect_string(__wrap_write, buf, ln); - will_return(__wrap_write, strlen(ln)); -- expect_condlog(3, "Created new binding [MPATHa] for WWID [WWIDa]\n"); -+ expect_condlog(3, NEW_STR("MPATHa", "WWIDa")); - - alias = allocate_binding(0, "WWIDa", 1, "MPATH"); - assert_ptr_not_equal(alias, NULL); -@@ -1142,7 +1138,7 @@ static void al_zz(void **state) - expect_value(__wrap_write, count, strlen(ln)); - expect_string(__wrap_write, buf, ln); - will_return(__wrap_write, strlen(ln)); -- expect_condlog(3, "Created new binding [MPATHzz] for WWID [WWIDzz]\n"); -+ expect_condlog(3, NEW_STR("MPATHzz", "WWIDzz")); - - alias = allocate_binding(0, "WWIDzz", 26*26 + 26, "MPATH"); - assert_ptr_not_equal(alias, NULL); diff --git a/0049-RH-attempt-to-get-ANA-info-via-sysfs-first.patch b/0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch similarity index 100% rename from 0049-RH-attempt-to-get-ANA-info-via-sysfs-first.patch rename to 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch diff --git a/0009-multipath-tools-tests-convert-mock_-failed-used-_ali.patch b/0009-multipath-tools-tests-convert-mock_-failed-used-_ali.patch deleted file mode 100644 index 9d71adf..0000000 --- a/0009-multipath-tools-tests-convert-mock_-failed-used-_ali.patch +++ /dev/null @@ -1,246 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 24 Aug 2023 10:49:32 +0200 -Subject: [PATCH] multipath-tools tests: convert mock_{failed,used}_alias to - macros - -This way we can further improve readability of the individual test -cases. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - tests/alias.c | 92 +++++++++++++++++++++++++-------------------------- - 1 file changed, 46 insertions(+), 46 deletions(-) - -diff --git a/tests/alias.c b/tests/alias.c -index 427b2814..a32b43e8 100644 ---- a/tests/alias.c -+++ b/tests/alias.c -@@ -445,26 +445,26 @@ static void mock_self_alias(const char *alias, const char *wwid) - #define REUSE_STR(alias_str, wwid_str) ("alias " alias_str " already bound to wwid " wwid_str ", cannot reuse\n") - #define NOMORE_STR "no more available user_friendly_names\n" - --static void mock_failed_alias(const char *alias, char *msg) --{ -- expect_string(__wrap_dm_map_present, str, alias); -- will_return(__wrap_dm_map_present, 1); -- expect_string(__wrap_dm_get_uuid, name, alias); -- expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); -- will_return(__wrap_dm_get_uuid, 1); -- expect_condlog(3, msg); --} -+#define mock_failed_alias(alias, wwid) \ -+ do { \ -+ expect_string(__wrap_dm_map_present, str, alias); \ -+ will_return(__wrap_dm_map_present, 1); \ -+ expect_string(__wrap_dm_get_uuid, name, alias); \ -+ expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); \ -+ will_return(__wrap_dm_get_uuid, 1); \ -+ expect_condlog(3, USED_STR(alias, wwid)); \ -+ } while (0) - --static void mock_used_alias(const char *alias, char *msg) --{ -- expect_string(__wrap_dm_map_present, str, alias); -- will_return(__wrap_dm_map_present, 1); -- expect_string(__wrap_dm_get_uuid, name, alias); -- expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); -- will_return(__wrap_dm_get_uuid, 0); -- will_return(__wrap_dm_get_uuid, "WWID_USED"); -- expect_condlog(3, msg); --} -+#define mock_used_alias(alias, wwid) \ -+ do { \ -+ expect_string(__wrap_dm_map_present, str, alias); \ -+ will_return(__wrap_dm_map_present, 1); \ -+ expect_string(__wrap_dm_get_uuid, name, alias); \ -+ expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); \ -+ will_return(__wrap_dm_get_uuid, 0); \ -+ will_return(__wrap_dm_get_uuid, "WWID_USED"); \ -+ expect_condlog(3, USED_STR(alias, wwid)); \ -+ } while(0) - - static void mock_bindings_file(const char *content, int match_line) - { -@@ -516,7 +516,7 @@ static void lb_empty_failed(void **state) - char *alias; - - will_return(__wrap_fgets, NULL); -- mock_failed_alias("MPATHa", USED_STR("MPATHa", "WWID0")); -+ mock_failed_alias("MPATHa", "WWID0"); - mock_unused_alias("MPATHb"); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); -@@ -531,7 +531,7 @@ static void lb_empty_1_used(void **state) - char *alias; - - will_return(__wrap_fgets, NULL); -- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); -+ mock_used_alias("MPATHa", "WWID0"); - mock_unused_alias("MPATHb"); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); -@@ -546,7 +546,7 @@ static void lb_empty_1_used_self(void **state) - char *alias; - - will_return(__wrap_fgets, NULL); -- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); -+ mock_used_alias("MPATHa", "WWID0"); - mock_self_alias("MPATHb", "WWID0"); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); -@@ -616,10 +616,10 @@ static void lb_nomatch_a_3_used_failed_self(void **state) - - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, NULL); -- mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID1")); -- mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID1")); -- mock_used_alias("MPATHd", USED_STR("MPATHd", "WWID1")); -- mock_failed_alias("MPATHe", USED_STR("MPATHe", "WWID1")); -+ mock_used_alias("MPATHb", "WWID1"); -+ mock_used_alias("MPATHc", "WWID1"); -+ mock_used_alias("MPATHd", "WWID1"); -+ mock_failed_alias("MPATHe", "WWID1"); - mock_self_alias("MPATHf", "WWID1"); - expect_condlog(3, NOMATCH_WWID_STR("WWID1")); - rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); -@@ -689,7 +689,7 @@ static void lb_nomatch_a_d_1_used(void **state) - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, "MPATHd WWID1\n"); - will_return(__wrap_fgets, NULL); -- mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2")); -+ mock_used_alias("MPATHb", "WWID2"); - mock_unused_alias("MPATHc"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -@@ -705,8 +705,8 @@ static void lb_nomatch_a_d_2_used(void **state) - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, "MPATHd WWID1\n"); - will_return(__wrap_fgets, NULL); -- mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2")); -- mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2")); -+ mock_used_alias("MPATHb", "WWID2"); -+ mock_used_alias("MPATHc", "WWID2"); - mock_unused_alias("MPATHe"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -@@ -722,9 +722,9 @@ static void lb_nomatch_a_d_3_used(void **state) - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, "MPATHd WWID1\n"); - will_return(__wrap_fgets, NULL); -- mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2")); -- mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2")); -- mock_used_alias("MPATHe", USED_STR("MPATHe", "WWID2")); -+ mock_used_alias("MPATHb", "WWID2"); -+ mock_used_alias("MPATHc", "WWID2"); -+ mock_used_alias("MPATHe", "WWID2"); - mock_unused_alias("MPATHf"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -@@ -771,7 +771,7 @@ static void lb_nomatch_d_a_1_used(void **state) - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, "MPATHd WWID0\n"); - will_return(__wrap_fgets, NULL); -- mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2")); -+ mock_used_alias("MPATHb", "WWID2"); - mock_unused_alias("MPATHe"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -@@ -851,9 +851,9 @@ static void lb_nomatch_b_a_3_used(void **state) - will_return(__wrap_fgets, "MPATHz WWID26\n"); - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, NULL); -- mock_used_alias("MPATHaa", USED_STR("MPATHaa", "WWID2")); -- mock_used_alias("MPATHab", USED_STR("MPATHab", "WWID2")); -- mock_used_alias("MPATHac", USED_STR("MPATHac", "WWID2")); -+ mock_used_alias("MPATHaa", "WWID2"); -+ mock_used_alias("MPATHab", "WWID2"); -+ mock_used_alias("MPATHac", "WWID2"); - mock_unused_alias("MPATHad"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -@@ -895,7 +895,7 @@ static void lb_nomatch_int_max_used(void **state) - will_return(__wrap_fgets, "MPATHb WWID1\n"); - will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n"); - will_return(__wrap_fgets, NULL); -- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2")); -+ mock_used_alias("MPATHa", "WWID2"); - expect_condlog(0, NOMORE_STR); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, -1); -@@ -926,7 +926,7 @@ static void lb_nomatch_int_max_m1_used(void **state) - will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); - will_return(__wrap_fgets, "MPATHa WWID0\n"); - will_return(__wrap_fgets, NULL); -- mock_used_alias("MPATH" MPATH_ID_INT_MAX, USED_STR("MPATH" MPATH_ID_INT_MAX, "WWID2")); -+ mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2"); - expect_condlog(0, NOMORE_STR); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, -1); -@@ -941,7 +941,7 @@ static void lb_nomatch_int_max_m1_1_used(void **state) - will_return(__wrap_fgets, "MPATHb WWID1\n"); - will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); - will_return(__wrap_fgets, NULL); -- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2")); -+ mock_used_alias("MPATHa", "WWID2"); - mock_unused_alias("MPATH" MPATH_ID_INT_MAX); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -@@ -957,8 +957,8 @@ static void lb_nomatch_int_max_m1_2_used(void **state) - will_return(__wrap_fgets, "MPATHb WWID1\n"); - will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); - will_return(__wrap_fgets, NULL); -- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2")); -- mock_used_alias("MPATH" MPATH_ID_INT_MAX, USED_STR("MPATH" MPATH_ID_INT_MAX, "WWID2")); -+ mock_used_alias("MPATHa", "WWID2"); -+ mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2"); - expect_condlog(0, NOMORE_STR); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, -1); -@@ -1291,7 +1291,7 @@ static void gufa_match_a_used(void **state) { - - will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0")); - expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); -- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); -+ mock_used_alias("MPATHa", "WWID0"); - - alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); - assert_ptr_equal(alias, NULL); -@@ -1355,7 +1355,7 @@ static void gufa_nomatch_c_b_used(void **state) { - mock_bindings_file("MPATHc WWID2\n" - "MPATHb WWID1", - -1); -- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID4")); -+ mock_used_alias("MPATHa", "WWID4"); - expect_condlog(3, NOMATCH_WWID_STR("WWID4")); - mock_unused_alias("MPATHd"); - -@@ -1450,7 +1450,7 @@ static void gufa_old_match_other_used(void **state) { - expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); - - mock_bindings_file(bindings, -1); -- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); -+ mock_used_alias("MPATHa", "WWID0"); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - mock_unused_alias("MPATHb"); - -@@ -1493,7 +1493,7 @@ static void gufa_old_match_other_wwidmatch_used(void **state) { - - mock_bindings_file(bindings, 1); - expect_condlog(3, FOUND_STR("MPATHc", "WWID2")); -- mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2")); -+ mock_used_alias("MPATHc", "WWID2"); - - alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false); - assert_ptr_equal(alias, NULL); -@@ -1528,7 +1528,7 @@ static void gufa_old_nomatch_wwidmatch_used(void **state) { - - mock_bindings_file(bindings, 0); - expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); -- mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); -+ mock_used_alias("MPATHa", "WWID0"); - - alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); - assert_ptr_equal(alias, NULL); diff --git a/0050-RH-make-parse_vpd_pg83-match-scsi_id-output.patch b/0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch similarity index 94% rename from 0050-RH-make-parse_vpd_pg83-match-scsi_id-output.patch rename to 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch index 1906258..aa49d69 100644 --- a/0050-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +++ b/0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch @@ -14,10 +14,10 @@ Signed-off-by: Benjamin Marzinski 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index 84ce5fe7..104fdd5a 100644 +index 6fd4dabb..19692b1e 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c -@@ -1177,13 +1177,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, +@@ -1216,13 +1216,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, good_len = 8; break; case 2: @@ -33,7 +33,7 @@ index 84ce5fe7..104fdd5a 100644 good_len = 8; break; default: -@@ -1201,10 +1197,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, +@@ -1240,10 +1236,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, break; case 0x8: /* SCSI Name: Prio 3 */ diff --git a/0010-multipath-tools-test-use-mock_bindings_file-consiste.patch b/0010-multipath-tools-test-use-mock_bindings_file-consiste.patch deleted file mode 100644 index 2105f5a..0000000 --- a/0010-multipath-tools-test-use-mock_bindings_file-consiste.patch +++ /dev/null @@ -1,500 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 24 Aug 2023 11:13:44 +0200 -Subject: [PATCH] multipath-tools test: use mock_bindings_file() consistently - -Further improve test readablity. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - tests/alias.c | 178 +++++++++++++++++++++----------------------------- - 1 file changed, 76 insertions(+), 102 deletions(-) - -diff --git a/tests/alias.c b/tests/alias.c -index a32b43e8..f334f928 100644 ---- a/tests/alias.c -+++ b/tests/alias.c -@@ -489,7 +489,7 @@ static void lb_empty(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("", -1); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - rc = lookup_binding(NULL, "WWID0", &alias, NULL, 0); - assert_int_equal(rc, 1); -@@ -501,7 +501,7 @@ static void lb_empty_unused(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("", -1); - mock_unused_alias("MPATHa"); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); -@@ -515,7 +515,7 @@ static void lb_empty_failed(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("", -1); - mock_failed_alias("MPATHa", "WWID0"); - mock_unused_alias("MPATHb"); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); -@@ -530,7 +530,7 @@ static void lb_empty_1_used(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("", -1); - mock_used_alias("MPATHa", "WWID0"); - mock_unused_alias("MPATHb"); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); -@@ -545,7 +545,7 @@ static void lb_empty_1_used_self(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("", -1); - mock_used_alias("MPATHa", "WWID0"); - mock_self_alias("MPATHb", "WWID0"); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); -@@ -560,7 +560,7 @@ static void lb_match_a(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -+ mock_bindings_file("MPATHa WWID0\n", 0); - expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); - rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 0); - assert_int_equal(rc, 0); -@@ -574,8 +574,7 @@ static void lb_nomatch_a(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHa WWID0\n", -1); - expect_condlog(3, NOMATCH_WWID_STR("WWID1")); - rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 0); - assert_int_equal(rc, 2); -@@ -587,8 +586,7 @@ static void lb_nomatch_a_bad_check(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHa WWID0\n", -1); - expect_condlog(0, NOMORE_STR); - rc = lookup_binding(NULL, "WWID1", &alias, NULL, 1); - assert_int_equal(rc, -1); -@@ -600,8 +598,7 @@ static void lb_nomatch_a_unused(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHa WWID0\n", -1); - mock_unused_alias("MPATHb"); - expect_condlog(3, NOMATCH_WWID_STR("WWID1")); - rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); -@@ -614,8 +611,7 @@ static void lb_nomatch_a_3_used_failed_self(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHa WWID0\n", -1); - mock_used_alias("MPATHb", "WWID1"); - mock_used_alias("MPATHc", "WWID1"); - mock_used_alias("MPATHd", "WWID1"); -@@ -632,8 +628,8 @@ static void do_lb_match_c(void **state, int check_if_taken) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, "MPATHc WWID1\n"); -+ mock_bindings_file("MPATHa WWID0\n" -+ "MPATHc WWID1", 1); - expect_condlog(3, FOUND_STR("MPATHc", "WWID1")); - rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", check_if_taken); - assert_int_equal(rc, 0); -@@ -657,9 +653,8 @@ static void lb_nomatch_a_c(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, "MPATHc WWID1\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHa WWID0\n" -+ "MPATHc WWID1", -1); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); - assert_int_equal(rc, 2); -@@ -671,9 +666,8 @@ static void lb_nomatch_a_d_unused(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, "MPATHd WWID1\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHa WWID0\n" -+ "MPATHd WWID1", -1); - mock_unused_alias("MPATHb"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -@@ -686,9 +680,8 @@ static void lb_nomatch_a_d_1_used(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, "MPATHd WWID1\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHa WWID0\n" -+ "MPATHd WWID1", -1); - mock_used_alias("MPATHb", "WWID2"); - mock_unused_alias("MPATHc"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); -@@ -702,9 +695,8 @@ static void lb_nomatch_a_d_2_used(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, "MPATHd WWID1\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHa WWID0\n" -+ "MPATHd WWID1", -1); - mock_used_alias("MPATHb", "WWID2"); - mock_used_alias("MPATHc", "WWID2"); - mock_unused_alias("MPATHe"); -@@ -719,9 +711,8 @@ static void lb_nomatch_a_d_3_used(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, "MPATHd WWID1\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHa WWID0\n" -+ "MPATHd WWID1", -1); - mock_used_alias("MPATHb", "WWID2"); - mock_used_alias("MPATHc", "WWID2"); - mock_used_alias("MPATHe", "WWID2"); -@@ -737,9 +728,8 @@ static void lb_nomatch_c_a(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHc WWID1\n"); -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHc WWID1\n" -+ "MPATHa WWID0\n", -1); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); - assert_int_equal(rc, 2); -@@ -751,10 +741,9 @@ static void lb_nomatch_d_a_unused(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHc WWID1\n"); -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, "MPATHd WWID0\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHc WWID1\n" -+ "MPATHa WWID0\n" -+ "MPATHd WWID0\n", -1); - mock_unused_alias("MPATHb"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -@@ -767,10 +756,9 @@ static void lb_nomatch_d_a_1_used(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHc WWID1\n"); -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, "MPATHd WWID0\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHc WWID1\n" -+ "MPATHa WWID0\n" -+ "MPATHd WWID0\n", -1); - mock_used_alias("MPATHb", "WWID2"); - mock_unused_alias("MPATHe"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); -@@ -784,10 +772,9 @@ static void lb_nomatch_a_b(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, "MPATHz WWID26\n"); -- will_return(__wrap_fgets, "MPATHb WWID1\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHa WWID0\n" -+ "MPATHz WWID26\n" -+ "MPATHb WWID1\n", -1); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); - assert_int_equal(rc, 3); -@@ -799,10 +786,9 @@ static void lb_nomatch_a_b_bad(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, "MPATHz WWID26\n"); -- will_return(__wrap_fgets, "MPATHb\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHa WWID0\n" -+ "MPATHz WWID26\n" -+ "MPATHb\n", -1); - expect_condlog(3, "Ignoring malformed line 3 in bindings file\n"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); -@@ -815,10 +801,9 @@ static void lb_nomatch_a_b_bad_self(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, "MPATHz WWID26\n"); -- will_return(__wrap_fgets, "MPATHb\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHa WWID0\n" -+ "MPATHz WWID26\n" -+ "MPATHb\n", -1); - expect_condlog(3, "Ignoring malformed line 3 in bindings file\n"); - mock_self_alias("MPATHc", "WWID2"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); -@@ -832,10 +817,9 @@ static void lb_nomatch_b_a(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHb WWID1\n"); -- will_return(__wrap_fgets, "MPATHz WWID26\n"); -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHb WWID1\n" -+ "MPATHz WWID26\n" -+ "MPATHa WWID0\n", -1); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); - assert_int_equal(rc, 27); -@@ -847,10 +831,9 @@ static void lb_nomatch_b_a_3_used(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHb WWID1\n"); -- will_return(__wrap_fgets, "MPATHz WWID26\n"); -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHb WWID1\n" -+ "MPATHz WWID26\n" -+ "MPATHa WWID0\n", -1); - mock_used_alias("MPATHaa", "WWID2"); - mock_used_alias("MPATHab", "WWID2"); - mock_used_alias("MPATHac", "WWID2"); -@@ -867,10 +850,9 @@ static void do_lb_nomatch_int_max(void **state, int check_if_taken) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHb WWID1\n"); -- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n"); -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHb WWID1\n" -+ "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n" -+ "MPATHa WWID0\n", -1); - expect_condlog(0, NOMORE_STR); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", check_if_taken); - assert_int_equal(rc, -1); -@@ -892,9 +874,8 @@ static void lb_nomatch_int_max_used(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHb WWID1\n"); -- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHb WWID1\n" -+ "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n", -1); - mock_used_alias("MPATHa", "WWID2"); - expect_condlog(0, NOMORE_STR); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -@@ -907,10 +888,9 @@ static void lb_nomatch_int_max_m1(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHb WWID1\n"); -- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHb WWID1\n" -+ "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n" -+ "MPATHa WWID0\n", -1); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); - assert_int_equal(rc, INT_MAX); -@@ -922,10 +902,9 @@ static void lb_nomatch_int_max_m1_used(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHb WWID1\n"); -- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHb WWID1\n" -+ "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n" -+ "MPATHa WWID0\n", -1); - mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2"); - expect_condlog(0, NOMORE_STR); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -@@ -938,9 +917,8 @@ static void lb_nomatch_int_max_m1_1_used(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHb WWID1\n"); -- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHb WWID1\n" -+ "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n", -1); - mock_used_alias("MPATHa", "WWID2"); - mock_unused_alias("MPATH" MPATH_ID_INT_MAX); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); -@@ -954,9 +932,8 @@ static void lb_nomatch_int_max_m1_2_used(void **state) - int rc; - char *alias; - -- will_return(__wrap_fgets, "MPATHb WWID1\n"); -- will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHb WWID1\n" -+ "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n", -1); - mock_used_alias("MPATHa", "WWID2"); - mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2"); - expect_condlog(0, NOMORE_STR); -@@ -1014,7 +991,7 @@ static void rl_empty(void **state) - char buf[WWID_SIZE]; - - buf[0] = '\0'; -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("", -1); - expect_condlog(3, NOMATCH_STR("MPATHa")); - rc = rlookup_binding(NULL, buf, "MPATHa"); - assert_int_equal(rc, -1); -@@ -1027,7 +1004,7 @@ static void rl_match_a(void **state) - char buf[WWID_SIZE]; - - buf[0] = '\0'; -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -+ mock_bindings_file("MPATHa WWID0\n", 0); - expect_condlog(3, FOUND_ALIAS_STR("MPATHa", "WWID0")); - rc = rlookup_binding(NULL, buf, "MPATHa"); - assert_int_equal(rc, 0); -@@ -1040,8 +1017,7 @@ static void rl_nomatch_a(void **state) - char buf[WWID_SIZE]; - - buf[0] = '\0'; -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHa WWID0\n", -1); - expect_condlog(3, NOMATCH_STR("MPATHb")); - rc = rlookup_binding(NULL, buf, "MPATHb"); - assert_int_equal(rc, -1); -@@ -1054,8 +1030,7 @@ static void rl_malformed_a(void **state) - char buf[WWID_SIZE]; - - buf[0] = '\0'; -- will_return(__wrap_fgets, "MPATHa \n"); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("MPATHa \n", -1); - expect_condlog(3, "Ignoring malformed line 1 in bindings file\n"); - expect_condlog(3, NOMATCH_STR("MPATHa")); - rc = rlookup_binding(NULL, buf, "MPATHa"); -@@ -1074,8 +1049,7 @@ static void rl_overlong_a(void **state) - snprintf(line + sizeof(line) - 2, 2, "\n"); - - buf[0] = '\0'; -- will_return(__wrap_fgets, line); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file(line, -1); - expect_condlog(3, "Ignoring too large wwid at 1 in bindings file\n"); - expect_condlog(3, NOMATCH_STR("MPATHa")); - rc = rlookup_binding(NULL, buf, "MPATHa"); -@@ -1089,9 +1063,9 @@ static void rl_match_b(void **state) - char buf[WWID_SIZE]; - - buf[0] = '\0'; -- will_return(__wrap_fgets, "MPATHa WWID0\n"); -- will_return(__wrap_fgets, "MPATHz WWID26\n"); -- will_return(__wrap_fgets, "MPATHb WWID2\n"); -+ mock_bindings_file("MPATHa WWID0\n" -+ "MPATHz WWID26\n" -+ "MPATHb WWID2\n", 2); - expect_condlog(3, FOUND_ALIAS_STR("MPATHb", "WWID2")); - rc = rlookup_binding(NULL, buf, "MPATHb"); - assert_int_equal(rc, 0); -@@ -1222,7 +1196,7 @@ static void gufa_empty_new_rw(void **state) { - - will_return(__wrap_open_file, true); - -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("", -1); - mock_unused_alias("MPATHa"); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - -@@ -1235,7 +1209,7 @@ static void gufa_empty_new_rw(void **state) { - static void gufa_empty_new_ro_1(void **state) { - char *alias; - will_return(__wrap_open_file, false); -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("", -1); - mock_unused_alias("MPATHa"); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - -@@ -1248,7 +1222,7 @@ static void gufa_empty_new_ro_2(void **state) { - - will_return(__wrap_open_file, true); - -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("", -1); - mock_unused_alias("MPATHa"); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - -@@ -1261,7 +1235,7 @@ static void gufa_match_a_unused(void **state) { - - will_return(__wrap_open_file, true); - -- will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0")); -+ mock_bindings_file("MPATHa WWID0", 0); - expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); - mock_unused_alias("MPATHa"); - -@@ -1275,7 +1249,7 @@ static void gufa_match_a_self(void **state) { - - will_return(__wrap_open_file, true); - -- will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0")); -+ mock_bindings_file("MPATHa WWID0", 0); - expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); - mock_self_alias("MPATHa", "WWID0"); - -@@ -1289,7 +1263,7 @@ static void gufa_match_a_used(void **state) { - - will_return(__wrap_open_file, true); - -- will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0")); -+ mock_bindings_file("MPATHa WWID0", 0); - expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); - mock_used_alias("MPATHa", "WWID0"); - -@@ -1389,11 +1363,11 @@ static void gufa_old_empty(void **state) { - will_return(__wrap_open_file, true); - - /* rlookup_binding for ALIAS */ -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("", -1); - expect_condlog(3, NOMATCH_STR("MPATHz")); - - /* lookup_binding */ -- will_return(__wrap_fgets, NULL); -+ mock_bindings_file("", -1); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - - mock_allocate_binding("MPATHz", "WWID0"); diff --git a/0051-RH-add-scsi-device-handlers-to-modules-load.d.patch b/0011-RH-add-scsi-device-handlers-to-modules-load.d.patch similarity index 96% rename from 0051-RH-add-scsi-device-handlers-to-modules-load.d.patch rename to 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch index 407b621..0059895 100644 --- a/0051-RH-add-scsi-device-handlers-to-modules-load.d.patch +++ b/0011-RH-add-scsi-device-handlers-to-modules-load.d.patch @@ -11,7 +11,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc -index 72fd8d57..a49e9f5a 100644 +index 3d80d224..15e3bd3a 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -16,7 +16,7 @@ READLINE := diff --git a/0011-libmultipath-add-global-variable-for-current-binding.patch b/0011-libmultipath-add-global-variable-for-current-binding.patch deleted file mode 100644 index c91259d..0000000 --- a/0011-libmultipath-add-global-variable-for-current-binding.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Tue, 22 Aug 2023 15:32:17 +0200 -Subject: [PATCH] libmultipath: add global variable for current bindings - -Add a variable global_bindings that holds the currently active vector of -bindings. This variable is freed at program exit. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/alias.c | 11 +++++++++-- - libmultipath/alias.h | 1 + - libmultipath/libmultipath.version | 1 + - multipath/main.c | 2 ++ - multipathd/main.c | 1 + - 5 files changed, 14 insertions(+), 2 deletions(-) - -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index 9e9ac563..dd363fd8 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -511,6 +511,7 @@ static void _free_binding(struct binding *bdg) - * an abstract type. - */ - typedef struct _vector Bindings; -+static Bindings global_bindings = { .allocated = 0 }; - - static void free_bindings(Bindings *bindings) - { -@@ -522,6 +523,11 @@ static void free_bindings(Bindings *bindings) - vector_reset(bindings); - } - -+void cleanup_bindings(void) -+{ -+ free_bindings(&global_bindings); -+} -+ - enum { - BINDING_EXISTS, - BINDING_CONFLICT, -@@ -751,7 +757,6 @@ int check_alias_settings(const struct config *conf) - pthread_cleanup_pop(1); - pthread_cleanup_pop(1); - -- pthread_cleanup_push_cast(free_bindings, &bindings); - fd = open_file(conf->bindings_file, &can_write, BINDINGS_FILE_HEADER); - if (fd != -1) { - FILE *file = fdopen(fd, "r"); -@@ -771,6 +776,8 @@ int check_alias_settings(const struct config *conf) - close(fd); - } - } -- pthread_cleanup_pop(1); -+ -+ cleanup_bindings(); -+ global_bindings = bindings; - return rc; - } -diff --git a/libmultipath/alias.h b/libmultipath/alias.h -index fa332233..37b49d9c 100644 ---- a/libmultipath/alias.h -+++ b/libmultipath/alias.h -@@ -9,5 +9,6 @@ char *get_user_friendly_alias(const char *wwid, const char *file, - - struct config; - int check_alias_settings(const struct config *); -+void cleanup_bindings(void); - - #endif /* _ALIAS_H */ -diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version -index a7b8c337..ddd302f5 100644 ---- a/libmultipath/libmultipath.version -+++ b/libmultipath/libmultipath.version -@@ -64,6 +64,7 @@ global: - checker_name; - checker_state_name; - check_foreign; -+ cleanup_bindings; - cleanup_lock; - coalesce_paths; - count_active_paths; -diff --git a/multipath/main.c b/multipath/main.c -index b78f3162..45e9745f 100644 ---- a/multipath/main.c -+++ b/multipath/main.c -@@ -843,6 +843,8 @@ main (int argc, char *argv[]) - conf->force_sync = 1; - if (atexit(cleanup_vecs)) - condlog(1, "failed to register cleanup handler for vecs: %m"); -+ if (atexit(cleanup_bindings)) -+ condlog(1, "failed to register cleanup handler for bindings: %m"); - while ((arg = getopt(argc, argv, ":adDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) { - switch(arg) { - case 'v': -diff --git a/multipathd/main.c b/multipathd/main.c -index 2e02a548..214ed4ae 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -3325,6 +3325,7 @@ static void cleanup_child(void) - { - cleanup_threads(); - cleanup_vecs(); -+ cleanup_bindings(); - if (poll_dmevents) - cleanup_dmevent_waiter(); - diff --git a/0052-RH-compile-with-libreadline-support.patch b/0012-RH-compile-with-libreadline-support.patch similarity index 96% rename from 0052-RH-compile-with-libreadline-support.patch rename to 0012-RH-compile-with-libreadline-support.patch index c78d5c0..b0c8749 100644 --- a/0052-RH-compile-with-libreadline-support.patch +++ b/0012-RH-compile-with-libreadline-support.patch @@ -12,7 +12,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc -index a49e9f5a..51b55196 100644 +index 15e3bd3a..64384a72 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -12,7 +12,7 @@ diff --git a/0012-libmultipath-rename-fix_bindings_file-to-update_bind.patch b/0012-libmultipath-rename-fix_bindings_file-to-update_bind.patch deleted file mode 100644 index e0f8673..0000000 --- a/0012-libmultipath-rename-fix_bindings_file-to-update_bind.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Tue, 22 Aug 2023 15:37:15 +0200 -Subject: [PATCH] libmultipath: rename fix_bindings_file() to - update_bindings_file() - -We will use this function in a more generic way, give it a more -generic name. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/alias.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index dd363fd8..0aac2393 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -595,8 +595,8 @@ static int write_bindings_file(const Bindings *bindings, int fd) - return 0; - } - --static int fix_bindings_file(const struct config *conf, -- const Bindings *bindings) -+static int update_bindings_file(const struct config *conf, -+ const Bindings *bindings) - { - int rc; - int fd = -1; -@@ -766,7 +766,7 @@ int check_alias_settings(const struct config *conf) - rc = _check_bindings_file(conf, file, &bindings); - pthread_cleanup_pop(1); - if (rc == -1 && can_write && !conf->bindings_read_only) -- rc = fix_bindings_file(conf, &bindings); -+ rc = update_bindings_file(conf, &bindings); - else if (rc == -1) - condlog(0, "ERROR: bad settings in read-only bindings file %s", - conf->bindings_file); diff --git a/0053-RH-Add-mpathcleanup.patch b/0013-RH-Add-mpathcleanup.patch similarity index 98% rename from 0053-RH-Add-mpathcleanup.patch rename to 0013-RH-Add-mpathcleanup.patch index 9278829..c15fb6d 100644 --- a/0053-RH-Add-mpathcleanup.patch +++ b/0013-RH-Add-mpathcleanup.patch @@ -14,7 +14,7 @@ Signed-off-by: Benjamin Marzinski create mode 100755 multipath/mpathcleanup diff --git a/multipath/Makefile b/multipath/Makefile -index 9942d1a9..d281b501 100644 +index 9f14036c..99ad81b0 100644 --- a/multipath/Makefile +++ b/multipath/Makefile @@ -25,6 +25,7 @@ install: @@ -25,7 +25,7 @@ index 9942d1a9..d281b501 100644 $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) $(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) $(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules -@@ -46,6 +47,7 @@ endif +@@ -48,6 +49,7 @@ endif uninstall: $(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC) $(Q)$(RM) $(DESTDIR)$(bindir)/mpathconf diff --git a/0013-libmultipath-alias.c-move-bindings-related-code-up.patch b/0013-libmultipath-alias.c-move-bindings-related-code-up.patch deleted file mode 100644 index 1ad7b9e..0000000 --- a/0013-libmultipath-alias.c-move-bindings-related-code-up.patch +++ /dev/null @@ -1,285 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Tue, 22 Aug 2023 16:54:54 +0200 -Subject: [PATCH] libmultipath: alias.c: move bindings related code up - -No code changes, just moving code. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/alias.c | 239 ++++++++++++++++++++++--------------------- - 1 file changed, 120 insertions(+), 119 deletions(-) - -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index 0aac2393..7af403da 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - - #include "debug.h" - #include "util.h" -@@ -51,6 +52,125 @@ - - static const char bindings_file_header[] = BINDINGS_FILE_HEADER; - -+struct binding { -+ char *alias; -+ char *wwid; -+}; -+ -+/* -+ * Perhaps one day we'll implement this more efficiently, thus use -+ * an abstract type. -+ */ -+typedef struct _vector Bindings; -+static Bindings global_bindings = { .allocated = 0 }; -+ -+enum { -+ BINDING_EXISTS, -+ BINDING_CONFLICT, -+ BINDING_ADDED, -+ BINDING_DELETED, -+ BINDING_NOTFOUND, -+ BINDING_ERROR, -+}; -+ -+static void _free_binding(struct binding *bdg) -+{ -+ free(bdg->wwid); -+ free(bdg->alias); -+ free(bdg); -+} -+ -+static int add_binding(Bindings *bindings, const char *alias, const char *wwid) -+{ -+ struct binding *bdg; -+ int i, cmp = 0; -+ -+ /* -+ * Keep the bindings array sorted by alias. -+ * Optimization: Search backwards, assuming that the bindings file is -+ * sorted already. -+ */ -+ vector_foreach_slot_backwards(bindings, bdg, i) { -+ if ((cmp = strcmp(bdg->alias, alias)) <= 0) -+ break; -+ } -+ -+ /* Check for exact match */ -+ if (i >= 0 && cmp == 0) -+ return strcmp(bdg->wwid, wwid) ? -+ BINDING_CONFLICT : BINDING_EXISTS; -+ -+ i++; -+ bdg = calloc(1, sizeof(*bdg)); -+ if (bdg) { -+ bdg->wwid = strdup(wwid); -+ bdg->alias = strdup(alias); -+ if (bdg->wwid && bdg->alias && -+ vector_insert_slot(bindings, i, bdg)) -+ return BINDING_ADDED; -+ else -+ _free_binding(bdg); -+ } -+ -+ return BINDING_ERROR; -+} -+ -+static int write_bindings_file(const Bindings *bindings, int fd) -+{ -+ struct binding *bnd; -+ STRBUF_ON_STACK(line); -+ int i; -+ -+ if (write(fd, BINDINGS_FILE_HEADER, sizeof(BINDINGS_FILE_HEADER) - 1) -+ != sizeof(BINDINGS_FILE_HEADER) - 1) -+ return -1; -+ -+ vector_foreach_slot(bindings, bnd, i) { -+ int len; -+ -+ if ((len = print_strbuf(&line, "%s %s\n", -+ bnd->alias, bnd->wwid)) < 0) -+ return -1; -+ if (write(fd, get_strbuf_str(&line), len) != len) -+ return -1; -+ truncate_strbuf(&line, 0); -+ } -+ return 0; -+} -+ -+static int update_bindings_file(const struct config *conf, -+ const Bindings *bindings) -+{ -+ int rc; -+ int fd = -1; -+ char tempname[PATH_MAX]; -+ mode_t old_umask; -+ -+ if (safe_sprintf(tempname, "%s.XXXXXX", conf->bindings_file)) -+ return -1; -+ /* coverity: SECURE_TEMP */ -+ old_umask = umask(0077); -+ if ((fd = mkstemp(tempname)) == -1) { -+ condlog(1, "%s: mkstemp: %m", __func__); -+ return -1; -+ } -+ umask(old_umask); -+ pthread_cleanup_push(cleanup_fd_ptr, &fd); -+ rc = write_bindings_file(bindings, fd); -+ pthread_cleanup_pop(1); -+ if (rc == -1) { -+ condlog(1, "failed to write new bindings file %s", -+ tempname); -+ unlink(tempname); -+ return rc; -+ } -+ if ((rc = rename(tempname, conf->bindings_file)) == -1) -+ condlog(0, "%s: rename: %m", __func__); -+ else -+ condlog(1, "updated bindings file %s", conf->bindings_file); -+ return rc; -+} -+ - int - valid_alias(const char *alias) - { -@@ -494,25 +614,6 @@ get_user_friendly_wwid(const char *alias, char *buff, const char *file) - return 0; - } - --struct binding { -- char *alias; -- char *wwid; --}; -- --static void _free_binding(struct binding *bdg) --{ -- free(bdg->wwid); -- free(bdg->alias); -- free(bdg); --} -- --/* -- * Perhaps one day we'll implement this more efficiently, thus use -- * an abstract type. -- */ --typedef struct _vector Bindings; --static Bindings global_bindings = { .allocated = 0 }; -- - static void free_bindings(Bindings *bindings) - { - struct binding *bdg; -@@ -528,106 +629,6 @@ void cleanup_bindings(void) - free_bindings(&global_bindings); - } - --enum { -- BINDING_EXISTS, -- BINDING_CONFLICT, -- BINDING_ADDED, -- BINDING_DELETED, -- BINDING_NOTFOUND, -- BINDING_ERROR, --}; -- --static int add_binding(Bindings *bindings, const char *alias, const char *wwid) --{ -- struct binding *bdg; -- int i, cmp = 0; -- -- /* -- * Keep the bindings array sorted by alias. -- * Optimization: Search backwards, assuming that the bindings file is -- * sorted already. -- */ -- vector_foreach_slot_backwards(bindings, bdg, i) { -- if ((cmp = strcmp(bdg->alias, alias)) <= 0) -- break; -- } -- -- /* Check for exact match */ -- if (i >= 0 && cmp == 0) -- return strcmp(bdg->wwid, wwid) ? -- BINDING_CONFLICT : BINDING_EXISTS; -- -- i++; -- bdg = calloc(1, sizeof(*bdg)); -- if (bdg) { -- bdg->wwid = strdup(wwid); -- bdg->alias = strdup(alias); -- if (bdg->wwid && bdg->alias && -- vector_insert_slot(bindings, i, bdg)) -- return BINDING_ADDED; -- else -- _free_binding(bdg); -- } -- -- return BINDING_ERROR; --} -- --static int write_bindings_file(const Bindings *bindings, int fd) --{ -- struct binding *bnd; -- STRBUF_ON_STACK(line); -- int i; -- -- if (write(fd, BINDINGS_FILE_HEADER, sizeof(BINDINGS_FILE_HEADER) - 1) -- != sizeof(BINDINGS_FILE_HEADER) - 1) -- return -1; -- -- vector_foreach_slot(bindings, bnd, i) { -- int len; -- -- if ((len = print_strbuf(&line, "%s %s\n", -- bnd->alias, bnd->wwid)) < 0) -- return -1; -- if (write(fd, get_strbuf_str(&line), len) != len) -- return -1; -- truncate_strbuf(&line, 0); -- } -- return 0; --} -- --static int update_bindings_file(const struct config *conf, -- const Bindings *bindings) --{ -- int rc; -- int fd = -1; -- char tempname[PATH_MAX]; -- mode_t old_umask; -- -- if (safe_sprintf(tempname, "%s.XXXXXX", conf->bindings_file)) -- return -1; -- /* coverity: SECURE_TEMP */ -- old_umask = umask(0077); -- if ((fd = mkstemp(tempname)) == -1) { -- condlog(1, "%s: mkstemp: %m", __func__); -- return -1; -- } -- umask(old_umask); -- pthread_cleanup_push(cleanup_fd_ptr, &fd); -- rc = write_bindings_file(bindings, fd); -- pthread_cleanup_pop(1); -- if (rc == -1) { -- condlog(1, "failed to write new bindings file %s", -- tempname); -- unlink(tempname); -- return rc; -- } -- if ((rc = rename(tempname, conf->bindings_file)) == -1) -- condlog(0, "%s: rename: %m", __func__); -- else -- condlog(1, "updated bindings file %s", conf->bindings_file); -- return rc; --} -- - static int _check_bindings_file(const struct config *conf, FILE *file, - Bindings *bindings) - { diff --git a/0014-libmultipath-update_bindings_file-take-filename-argu.patch b/0014-libmultipath-update_bindings_file-take-filename-argu.patch deleted file mode 100644 index 6b9d2e8..0000000 --- a/0014-libmultipath-update_bindings_file-take-filename-argu.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 24 Aug 2023 15:53:49 +0200 -Subject: [PATCH] libmultipath: update_bindings_file: take filename argument - -This function just uses the file name, no other configuration -parameters. Also, pass the Bindings argument first to use the -same convention as the other functions in this file. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/alias.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index 7af403da..9bd3875e 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -138,15 +138,15 @@ static int write_bindings_file(const Bindings *bindings, int fd) - return 0; - } - --static int update_bindings_file(const struct config *conf, -- const Bindings *bindings) -+static int update_bindings_file(const Bindings *bindings, -+ const char *bindings_file) - { - int rc; - int fd = -1; - char tempname[PATH_MAX]; - mode_t old_umask; - -- if (safe_sprintf(tempname, "%s.XXXXXX", conf->bindings_file)) -+ if (safe_sprintf(tempname, "%s.XXXXXX", bindings_file)) - return -1; - /* coverity: SECURE_TEMP */ - old_umask = umask(0077); -@@ -164,10 +164,10 @@ static int update_bindings_file(const struct config *conf, - unlink(tempname); - return rc; - } -- if ((rc = rename(tempname, conf->bindings_file)) == -1) -+ if ((rc = rename(tempname, bindings_file)) == -1) - condlog(0, "%s: rename: %m", __func__); - else -- condlog(1, "updated bindings file %s", conf->bindings_file); -+ condlog(1, "updated bindings file %s", bindings_file); - return rc; - } - -@@ -767,7 +767,7 @@ int check_alias_settings(const struct config *conf) - rc = _check_bindings_file(conf, file, &bindings); - pthread_cleanup_pop(1); - if (rc == -1 && can_write && !conf->bindings_read_only) -- rc = update_bindings_file(conf, &bindings); -+ rc = update_bindings_file(&bindings, conf->bindings_file); - else if (rc == -1) - condlog(0, "ERROR: bad settings in read-only bindings file %s", - conf->bindings_file); diff --git a/0015-libmultipath-update_bindings_file-use-a-single-write.patch b/0015-libmultipath-update_bindings_file-use-a-single-write.patch deleted file mode 100644 index 1e1fd15..0000000 --- a/0015-libmultipath-update_bindings_file-use-a-single-write.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 24 Aug 2023 15:54:45 +0200 -Subject: [PATCH] libmultipath: update_bindings_file: use a single write() - -Save code and syscalls by assembling the content in memory first. -write() may return less bytes written than expected. Deal with it. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/alias.c | 26 +++++++++++++++++--------- - 1 file changed, 17 insertions(+), 9 deletions(-) - -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index 9bd3875e..92f90f05 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -118,22 +118,30 @@ static int add_binding(Bindings *bindings, const char *alias, const char *wwid) - static int write_bindings_file(const Bindings *bindings, int fd) - { - struct binding *bnd; -- STRBUF_ON_STACK(line); -+ STRBUF_ON_STACK(content); - int i; -+ size_t len; - -- if (write(fd, BINDINGS_FILE_HEADER, sizeof(BINDINGS_FILE_HEADER) - 1) -- != sizeof(BINDINGS_FILE_HEADER) - 1) -+ if (__append_strbuf_str(&content, BINDINGS_FILE_HEADER, -+ sizeof(BINDINGS_FILE_HEADER) - 1) == -1) - return -1; - - vector_foreach_slot(bindings, bnd, i) { -- int len; -- -- if ((len = print_strbuf(&line, "%s %s\n", -- bnd->alias, bnd->wwid)) < 0) -+ if (print_strbuf(&content, "%s %s\n", -+ bnd->alias, bnd->wwid) < 0) - return -1; -- if (write(fd, get_strbuf_str(&line), len) != len) -+ } -+ len = get_strbuf_len(&content); -+ while (len > 0) { -+ ssize_t n = write(fd, get_strbuf_str(&content), len); -+ -+ if (n < 0) -+ return n; -+ else if (n == 0) { -+ condlog(2, "%s: short write", __func__); - return -1; -- truncate_strbuf(&line, 0); -+ } -+ len -= n; - } - return 0; - } diff --git a/0016-libmultipath-update_bindings_file-don-t-log-temp-fil.patch b/0016-libmultipath-update_bindings_file-don-t-log-temp-fil.patch deleted file mode 100644 index 1126b95..0000000 --- a/0016-libmultipath-update_bindings_file-don-t-log-temp-fil.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 24 Aug 2023 22:33:39 +0200 -Subject: [PATCH] libmultipath: update_bindings_file: don't log temp file name - -The name of the temp file is unlikely to be helpful for users, -and hard to predict in the unit test. Omit it. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/alias.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index 92f90f05..afa5879e 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -167,8 +167,7 @@ static int update_bindings_file(const Bindings *bindings, - rc = write_bindings_file(bindings, fd); - pthread_cleanup_pop(1); - if (rc == -1) { -- condlog(1, "failed to write new bindings file %s", -- tempname); -+ condlog(1, "failed to write new bindings file"); - unlink(tempname); - return rc; - } diff --git a/0017-libmultipath-alias.c-factor-out-read_binding.patch b/0017-libmultipath-alias.c-factor-out-read_binding.patch deleted file mode 100644 index 8c9cb08..0000000 --- a/0017-libmultipath-alias.c-factor-out-read_binding.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 24 Aug 2023 21:17:25 +0200 -Subject: [PATCH] libmultipath: alias.c: factor out read_binding() - -This way we can test the parsing of input lines from the bindings -file more easily. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/alias.c | 58 ++++++++++++++++++++++++++++++-------------- - 1 file changed, 40 insertions(+), 18 deletions(-) - -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index afa5879e..ecf4a2ac 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -636,6 +636,43 @@ void cleanup_bindings(void) - free_bindings(&global_bindings); - } - -+enum { -+ READ_BINDING_OK, -+ READ_BINDING_SKIP, -+}; -+ -+static int read_binding(char *line, unsigned int linenr, char **alias, -+ char **wwid) { -+ char *c, *saveptr; -+ -+ c = strpbrk(line, "#\n\r"); -+ if (c) -+ *c = '\0'; -+ -+ *alias = strtok_r(line, " \t", &saveptr); -+ if (!*alias) /* blank line */ -+ return READ_BINDING_SKIP; -+ -+ *wwid = strtok_r(NULL, " \t", &saveptr); -+ if (!*wwid) { -+ condlog(1, "invalid line %u in bindings file, missing WWID", -+ linenr); -+ return READ_BINDING_SKIP; -+ } -+ if (strlen(*wwid) > WWID_SIZE - 1) { -+ condlog(3, -+ "Ignoring too large wwid at %u in bindings file", -+ linenr); -+ return READ_BINDING_SKIP; -+ } -+ c = strtok_r(NULL, " \t", &saveptr); -+ if (c) -+ /* This is non-fatal */ -+ condlog(1, "invalid line %d in bindings file, extra args \"%s\"", -+ linenr, c); -+ return READ_BINDING_OK; -+} -+ - static int _check_bindings_file(const struct config *conf, FILE *file, - Bindings *bindings) - { -@@ -647,27 +684,12 @@ static int _check_bindings_file(const struct config *conf, FILE *file, - - pthread_cleanup_push(cleanup_free_ptr, &line); - while ((n = getline(&line, &line_len, file)) >= 0) { -- char *c, *alias, *wwid, *saveptr; -+ char *alias, *wwid; - const char *mpe_wwid; - -- linenr++; -- c = strpbrk(line, "#\n\r"); -- if (c) -- *c = '\0'; -- alias = strtok_r(line, " \t", &saveptr); -- if (!alias) /* blank line */ -- continue; -- wwid = strtok_r(NULL, " \t", &saveptr); -- if (!wwid) { -- condlog(1, "invalid line %d in bindings file, missing WWID", -- linenr); -+ if (read_binding(line, ++linenr, &alias, &wwid) -+ == READ_BINDING_SKIP) - continue; -- } -- c = strtok_r(NULL, " \t", &saveptr); -- if (c) -- /* This is non-fatal */ -- condlog(1, "invalid line %d in bindings file, extra args \"%s\"", -- linenr, c); - - mpe_wwid = get_mpe_wwid(conf->mptable, alias); - if (mpe_wwid && strcmp(mpe_wwid, wwid)) { diff --git a/0018-libmultipath-keep-bindings-in-memory.patch b/0018-libmultipath-keep-bindings-in-memory.patch deleted file mode 100644 index bb26ea2..0000000 --- a/0018-libmultipath-keep-bindings-in-memory.patch +++ /dev/null @@ -1,545 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Tue, 22 Aug 2023 21:14:51 +0200 -Subject: [PATCH] libmultipath: keep bindings in memory - -Rather than opening the bindings file every time we must retrieve -a binding, keep the contents in memory and write the file only -if additions have been made. This simplifies the code, and should speed up -alias lookups significantly. As a side effect, the aliases will be stored -sorted by alias, which changes the way aliases are allocated if there are -unused "holes" in the sequence of aliases. For example, if the bindings file -contains mpathb, mpathy, and mpatha, in this order, the next new alias used to -be mpathz and is now mpathc. - -Another side effect is that multipathd will not automatically pick up changes -to the bindings file at runtime without a reconfigure operation. It is -questionable whether these on-the-fly changes were a good idea in the first -place, as inconsistent configurations may easily come to pass. It desired, -it would be feasible to implement automatic update of the bindings using the -existing inotify approach. - -The new implementation of get_user_friendly_alias() is slightly different -than before. The logic is summarized in a comment in the code. Unit tests -will be provided that illustrate the changes. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/alias.c | 351 ++++++++++++++++----------------------- - libmultipath/alias.h | 2 +- - libmultipath/configure.c | 3 +- - 3 files changed, 144 insertions(+), 212 deletions(-) - -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index ecf4a2ac..d6563749 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -50,8 +50,6 @@ - "# alias wwid\n" \ - "#\n" - --static const char bindings_file_header[] = BINDINGS_FILE_HEADER; -- - struct binding { - char *alias; - char *wwid; -@@ -80,6 +78,45 @@ static void _free_binding(struct binding *bdg) - free(bdg); - } - -+static const struct binding *get_binding_for_alias(const Bindings *bindings, -+ const char *alias) -+{ -+ const struct binding *bdg; -+ int i; -+ -+ if (!alias) -+ return NULL; -+ vector_foreach_slot(bindings, bdg, i) { -+ if (!strncmp(bdg->alias, alias, WWID_SIZE)) { -+ condlog(3, "Found matching alias [%s] in bindings file." -+ " Setting wwid to %s", alias, bdg->wwid); -+ return bdg; -+ } -+ } -+ -+ condlog(3, "No matching alias [%s] in bindings file.", alias); -+ return NULL; -+} -+ -+static const struct binding *get_binding_for_wwid(const Bindings *bindings, -+ const char *wwid) -+{ -+ const struct binding *bdg; -+ int i; -+ -+ if (!wwid) -+ return NULL; -+ vector_foreach_slot(bindings, bdg, i) { -+ if (!strncmp(bdg->wwid, wwid, WWID_SIZE)) { -+ condlog(3, "Found matching wwid [%s] in bindings file." -+ " Setting alias to %s", wwid, bdg->alias); -+ return bdg; -+ } -+ } -+ condlog(3, "No matching wwid [%s] in bindings file.", wwid); -+ return NULL; -+} -+ - static int add_binding(Bindings *bindings, const char *alias, const char *wwid) - { - struct binding *bdg; -@@ -115,6 +152,24 @@ static int add_binding(Bindings *bindings, const char *alias, const char *wwid) - return BINDING_ERROR; - } - -+static int delete_binding(Bindings *bindings, const char *wwid) -+{ -+ struct binding *bdg; -+ int i; -+ -+ vector_foreach_slot(bindings, bdg, i) { -+ if (!strncmp(bdg->wwid, wwid, WWID_SIZE)) { -+ _free_binding(bdg); -+ break; -+ } -+ } -+ if (i >= VECTOR_SIZE(bindings)) -+ return BINDING_NOTFOUND; -+ -+ vector_del_slot(bindings, i); -+ return BINDING_DELETED; -+} -+ - static int write_bindings_file(const Bindings *bindings, int fd) - { - struct binding *bnd; -@@ -267,38 +322,15 @@ static bool id_already_taken(int id, const char *prefix, const char *map_wwid) - return alias_already_taken(alias, map_wwid); - } - --/* -- * Returns: 0 if matching entry in WWIDs file found -- * -1 if an error occurs -- * >0 a free ID that could be used for the WWID at hand -- * *map_alias is set to a freshly allocated string with the matching alias if -- * the function returns 0, or to NULL otherwise. -- */ --static int --lookup_binding(FILE *f, const char *map_wwid, char **map_alias, -- const char *prefix, int check_if_taken) -+int get_free_id(const Bindings *bindings, const char *prefix, const char *map_wwid) - { -- char buf[LINE_MAX]; -- unsigned int line_nr = 0; -- int id = 1; -+ const struct binding *bdg; -+ int i, id = 1; - int biggest_id = 1; - int smallest_bigger_id = INT_MAX; - -- *map_alias = NULL; -- -- rewind(f); -- while (fgets(buf, LINE_MAX, f)) { -- const char *alias, *wwid; -- char *c, *saveptr; -- int curr_id; -- -- line_nr++; -- c = strpbrk(buf, "#\n\r"); -- if (c) -- *c = '\0'; -- alias = strtok_r(buf, " \t", &saveptr); -- if (!alias) /* blank line */ -- continue; -+ vector_foreach_slot(bindings, bdg, i) { -+ int curr_id = scan_devname(bdg->alias, prefix); - - /* - * Find an unused index - explanation of the algorithm -@@ -333,8 +365,6 @@ lookup_binding(FILE *f, const char *map_wwid, char **map_alias, - * biggest_id is always > smallest_bigger_id, except in the - * "perfectly ordered" case. - */ -- -- curr_id = scan_devname(alias, prefix); - if (curr_id == id) { - if (id < INT_MAX) - id++; -@@ -345,36 +375,15 @@ lookup_binding(FILE *f, const char *map_wwid, char **map_alias, - } - if (curr_id > biggest_id) - biggest_id = curr_id; -+ - if (curr_id > id && curr_id < smallest_bigger_id) - smallest_bigger_id = curr_id; -- wwid = strtok_r(NULL, " \t", &saveptr); -- if (!wwid){ -- condlog(3, -- "Ignoring malformed line %u in bindings file", -- line_nr); -- continue; -- } -- if (strcmp(wwid, map_wwid) == 0){ -- condlog(3, "Found matching wwid [%s] in bindings file." -- " Setting alias to %s", wwid, alias); -- *map_alias = strdup(alias); -- if (*map_alias == NULL) { -- condlog(0, "Cannot copy alias from bindings " -- "file: out of memory"); -- return -1; -- } -- return 0; -- } -- } -- if (!prefix && check_if_taken) -- id = -1; -- if (id >= smallest_bigger_id) { -- if (biggest_id < INT_MAX) -- id = biggest_id + 1; -- else -- id = -1; - } -- if (id > 0 && check_if_taken) { -+ -+ if (id >= smallest_bigger_id) -+ id = biggest_id < INT_MAX ? biggest_id + 1 : -1; -+ -+ if (id > 0) { - while(id_already_taken(id, prefix, map_wwid)) { - if (id == INT_MAX) { - id = -1; -@@ -391,64 +400,17 @@ lookup_binding(FILE *f, const char *map_wwid, char **map_alias, - } - } - } -- if (id < 0) { -+ -+ if (id < 0) - condlog(0, "no more available user_friendly_names"); -- return -1; -- } else -- condlog(3, "No matching wwid [%s] in bindings file.", map_wwid); - return id; - } - --static int --rlookup_binding(FILE *f, char *buff, const char *map_alias) --{ -- char line[LINE_MAX]; -- unsigned int line_nr = 0; -- -- buff[0] = '\0'; -- -- while (fgets(line, LINE_MAX, f)) { -- char *c, *saveptr; -- const char *alias, *wwid; -- -- line_nr++; -- c = strpbrk(line, "#\n\r"); -- if (c) -- *c = '\0'; -- alias = strtok_r(line, " \t", &saveptr); -- if (!alias) /* blank line */ -- continue; -- wwid = strtok_r(NULL, " \t", &saveptr); -- if (!wwid){ -- condlog(3, -- "Ignoring malformed line %u in bindings file", -- line_nr); -- continue; -- } -- if (strlen(wwid) > WWID_SIZE - 1) { -- condlog(3, -- "Ignoring too large wwid at %u in bindings file", line_nr); -- continue; -- } -- if (strcmp(alias, map_alias) == 0){ -- condlog(3, "Found matching alias [%s] in bindings file." -- " Setting wwid to %s", alias, wwid); -- strlcpy(buff, wwid, WWID_SIZE); -- return 0; -- } -- } -- condlog(3, "No matching alias [%s] in bindings file.", map_alias); -- -- return -1; --} -- - static char * --allocate_binding(int fd, const char *wwid, int id, const char *prefix) -+allocate_binding(const char *filename, const char *wwid, int id, const char *prefix) - { - STRBUF_ON_STACK(buf); -- off_t offset; -- ssize_t len; -- char *alias, *c; -+ char *alias; - - if (id <= 0) { - condlog(0, "%s: cannot allocate new binding for id %d", -@@ -460,164 +422,135 @@ allocate_binding(int fd, const char *wwid, int id, const char *prefix) - format_devname(&buf, id) == -1) - return NULL; - -- if (print_strbuf(&buf, " %s\n", wwid) < 0) -- return NULL; -+ alias = steal_strbuf_str(&buf); - -- offset = lseek(fd, 0, SEEK_END); -- if (offset < 0){ -- condlog(0, "Cannot seek to end of bindings file : %s", -- strerror(errno)); -+ if (add_binding(&global_bindings, alias, wwid) != BINDING_ADDED) { -+ condlog(0, "%s: cannot allocate new binding %s for %s", -+ __func__, alias, wwid); -+ free(alias); - return NULL; - } - -- len = get_strbuf_len(&buf); -- alias = steal_strbuf_str(&buf); -- -- if (write(fd, alias, len) != len) { -- condlog(0, "Cannot write binding to bindings file : %s", -- strerror(errno)); -- /* clear partial write */ -- if (ftruncate(fd, offset)) -- condlog(0, "Cannot truncate the header : %s", -- strerror(errno)); -+ if (update_bindings_file(&global_bindings, filename) == -1) { -+ condlog(1, "%s: deleting binding %s for %s", __func__, alias, wwid); -+ delete_binding(&global_bindings, wwid); - free(alias); - return NULL; - } -- c = strchr(alias, ' '); -- if (c) -- *c = '\0'; - - condlog(3, "Created new binding [%s] for WWID [%s]", alias, wwid); - return alias; - } - -+/* -+ * get_user_friendly_alias() action table -+ * -+ * The table shows the various cases, the actions taken, and the CI -+ * functions from tests/alias.c that represent them. -+ * -+ * - O: old alias given -+ * - A: old alias in table (y: yes, correct WWID; X: yes, wrong WWID) -+ * - W: wwid in table -+ * -+ * | No | O | A | W | action | function gufa_X | -+ * |----+---+---+---+--------------------------------------------+------------------------------| -+ * | 1 | n | - | n | get new alias | nomatch_Y | -+ * | 2 | n | - | y | use alias from bindings | match_a_Y | -+ * | 3 | y | n | n | add binding for old alias | old_nomatch_nowwidmatch | -+ * | 4 | y | n | y | use alias from bindings (avoid duplicates) | old_nomatch_wwidmatch | -+ * | 5 | y | y | n | [ impossible ] | - | -+ * | 6 | y | y | y | use old alias == alias from bindings | old_match | -+ * | 7 | y | X | n | get new alias | old_match_other | -+ * | 8 | y | X | y | use alias from bindings | old_match_other_wwidmatch | -+ * -+ * Notes: -+ * - "use alias from bindings" means that the alias from the bindings file will -+ * be tried; if it is in use, the alias selection will fail. No other -+ * bindings will be attempted. -+ * - "get new alias" fails if all aliases are used up, or if writing the -+ * bindings file fails. -+ * - if "alias_old" is set, it can't be bound to a different map. alias_old is -+ * initialized in find_existing_alias() by scanning the mpvec. We trust -+ * that the mpvec corrcectly represents kernel state. -+ */ -+ - char *get_user_friendly_alias(const char *wwid, const char *file, const char *alias_old, - const char *prefix, bool bindings_read_only) - { - char *alias = NULL; - int id = 0; -- int fd, can_write; - bool new_binding = false; -- char buff[WWID_SIZE]; -- FILE *f; -- -- fd = open_file(file, &can_write, bindings_file_header); -- if (fd < 0) -- return NULL; -- -- f = fdopen(fd, "r"); -- if (!f) { -- condlog(0, "cannot fdopen on bindings file descriptor"); -- close(fd); -- return NULL; -- } -+ const struct binding *bdg; - -- if (!strlen(alias_old)) -+ if (!*alias_old) - goto new_alias; - -- /* lookup the binding. if it exists, the wwid will be in buff -- * either way, id contains the id for the alias -- */ -- rlookup_binding(f, buff, alias_old); -- -- if (strlen(buff) > 0) { -- /* If buff is our wwid, it's already allocated correctly. */ -- if (strcmp(buff, wwid) == 0) { -+ /* See if there's a binding matching both alias_old and wwid */ -+ bdg = get_binding_for_alias(&global_bindings, alias_old); -+ if (bdg) { -+ if (!strcmp(bdg->wwid, wwid)) { - alias = strdup(alias_old); - goto out; -- - } else { - condlog(0, "alias %s already bound to wwid %s, cannot reuse", -- alias_old, buff); -+ alias_old, bdg->wwid); - goto new_alias; - } - } - -- /* -- * Look for an existing alias in the bindings file. -- * Pass prefix = NULL, so lookup_binding() won't try to allocate a new id. -- */ -- lookup_binding(f, wwid, &alias, NULL, 0); -- if (alias) { -- if (alias_already_taken(alias, wwid)) { -- free(alias); -- alias = NULL; -- } else -+ /* allocate the existing alias in the bindings file */ -+ id = scan_devname(alias_old, prefix); -+ -+new_alias: -+ /* Check for existing binding of WWID */ -+ bdg = get_binding_for_wwid(&global_bindings, wwid); -+ if (bdg) { -+ if (!alias_already_taken(bdg->alias, wwid)) { - condlog(3, "Use existing binding [%s] for WWID [%s]", -- alias, wwid); -+ bdg->alias, wwid); -+ alias = strdup(bdg->alias); -+ } - goto out; - } - -- /* alias_old is already taken by our WWID, update bindings file. */ -- id = scan_devname(alias_old, prefix); -- --new_alias: - if (id <= 0) { - /* - * no existing alias was provided, or allocating it - * failed. Try a new one. - */ -- id = lookup_binding(f, wwid, &alias, prefix, 1); -- if (id == 0 && alias_already_taken(alias, wwid)) { -- free(alias); -- alias = NULL; -- } -+ id = get_free_id(&global_bindings, prefix, wwid); - if (id <= 0) - goto out; - else - new_binding = true; - } - -- if (fflush(f) != 0) { -- condlog(0, "cannot fflush bindings file stream : %s", -- strerror(errno)); -- goto out; -- } -+ if (!bindings_read_only && id > 0) -+ alias = allocate_binding(file, wwid, id, prefix); - -- if (can_write && !bindings_read_only) { -- alias = allocate_binding(fd, wwid, id, prefix); -- if (alias && !new_binding) -- condlog(2, "Allocated existing binding [%s] for WWID [%s]", -- alias, wwid); -- } -+ if (alias && !new_binding) -+ condlog(2, "Allocated existing binding [%s] for WWID [%s]", -+ alias, wwid); - - out: -- pthread_cleanup_push(free, alias); -- fclose(f); -- pthread_cleanup_pop(0); - return alias; - } - --int --get_user_friendly_wwid(const char *alias, char *buff, const char *file) -+int get_user_friendly_wwid(const char *alias, char *buff) - { -- int fd, unused; -- FILE *f; -+ const struct binding *bdg; - - if (!alias || *alias == '\0') { - condlog(3, "Cannot find binding for empty alias"); - return -1; - } - -- fd = open_file(file, &unused, bindings_file_header); -- if (fd < 0) -- return -1; -- -- f = fdopen(fd, "r"); -- if (!f) { -- condlog(0, "cannot fdopen on bindings file descriptor : %s", -- strerror(errno)); -- close(fd); -+ bdg = get_binding_for_alias(&global_bindings, alias); -+ if (!bdg) { -+ *buff = '\0'; - return -1; - } -- -- rlookup_binding(f, buff, alias); -- if (!strlen(buff)) { -- fclose(f); -- return -1; -- } -- -- fclose(f); -+ strlcpy(buff, bdg->wwid, WWID_SIZE); - return 0; - } - -diff --git a/libmultipath/alias.h b/libmultipath/alias.h -index 37b49d9c..5ef6720b 100644 ---- a/libmultipath/alias.h -+++ b/libmultipath/alias.h -@@ -2,7 +2,7 @@ - #define _ALIAS_H - - int valid_alias(const char *alias); --int get_user_friendly_wwid(const char *alias, char *buff, const char *file); -+int get_user_friendly_wwid(const char *alias, char *buff); - char *get_user_friendly_alias(const char *wwid, const char *file, - const char *alias_old, - const char *prefix, bool bindings_read_only); -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index 029fbbd2..d8094903 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -1378,8 +1378,7 @@ static int _get_refwwid(enum mpath_cmds cmd, const char *dev, - refwwid = tmpwwid; - - /* or may be a binding */ -- else if (get_user_friendly_wwid(dev, tmpwwid, -- conf->bindings_file) == 0) -+ else if (get_user_friendly_wwid(dev, tmpwwid) == 0) - refwwid = tmpwwid; - - /* or may be an alias */ diff --git a/0019-multipath-tools-tests-fix-alias-tests.patch b/0019-multipath-tools-tests-fix-alias-tests.patch deleted file mode 100644 index da618f6..0000000 --- a/0019-multipath-tools-tests-fix-alias-tests.patch +++ /dev/null @@ -1,1698 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 25 Aug 2023 17:55:55 +0200 -Subject: [PATCH] multipath-tools tests: fix alias tests - -The different implementation of get_user_friendly_alias() and its helpers -necessitates changes in the unit tests. It would be nice if it didn't, but the -unit tests are too closely bound to the implementation to make this possible. - -- The bindings table is held in memory in alphabetically sorted order, which - may change the result of looking for free alias IDs if the entries in the - bindings file were unordered initially. In particular, if only a small - number of bindings exists, "holes" in the file will be detected more easily. - But because the sort order of the aliases differs from simple alphabetic - sorting ("mpathz" precedes "mpathaa"), a bindings file that contains all - bindings from "a" to "aa" (or more) will appear unsorted. - As an extra check, some of the unit tests deliberately use a different - implementation of add_binding() that does not order the bindings - table. - -- Broken lines in the bindings file never make it to the in-memory - representation. An alias that appeard "used" because it occurred in a broken - line will not appear used any more. Warnings about malformed lines will only - be printed while the bindings file is read, not from get_user_friendly_alias(). - -- The match_line argument of mock_bindings_file() is obsolete. - -- lookup_binding() and rlookup_binding() have been removed from - libmultipath. They are now emulated in the unit test code. - -- lookup_binding() didn't check for used alias in all cases previously, but it does now. - -- prefix != NULL and check_if_taken == false is not supported any more - in lookup_binding(). - -- allocate_binding() uses a very different sequence of systems calls now, as - it's implemented using update_bindings_file(). In particular, it's now more - difficult to predict the content of the write() call that creates the - bindings file. See comments for __wrap_write(). - -- some unit tests for get_user_friendly_alias() had to call - mock_bindings_file() twice, because the old implementation would read the - file twice (first rlookup_binding() and then lookup_binding()). This is not - necessary any more. - -- The unit tests need a teardown function to clear the bindings table in memory. - -- Minor changes are necessary because of changed ordering of the log messages. - Previously, lookup_binding() combined check for an existing entry and the - search for a new ID. The new algorithm does this in two separate steps and - tests for used aliases in between, which causes a change in the order in which - log messages are emitted. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - tests/alias.c | 957 ++++++++++++++++++++++++++++++++------------------ - 1 file changed, 614 insertions(+), 343 deletions(-) - -diff --git a/tests/alias.c b/tests/alias.c -index f334f928..50a21ecf 100644 ---- a/tests/alias.c -+++ b/tests/alias.c -@@ -3,10 +3,12 @@ - #include - #include - #include -+#include "strbuf.h" - #include "util.h" - #include "alias.h" - #include "test-log.h" - #include -+#include - - #include "globals.c" - #include "../libmultipath/alias.c" -@@ -20,18 +22,6 @@ - #define MPATH_ID_INT_MAX_p1 "fxshrxx" - #endif - --void __wrap_rewind(FILE *stream) --{} -- --char *__wrap_fgets(char *buf, int n, FILE *stream) --{ -- char *val = mock_ptr_type(char *); -- if (!val) -- return NULL; -- strlcpy(buf, val, n); -- return buf; --} -- - static int __set_errno(int err) - { - if (err >= 0) { -@@ -43,23 +33,44 @@ static int __set_errno(int err) - } - } - --off_t __wrap_lseek(int fd, off_t offset, int whence) -+/* -+ * allocate_binding -> write_bindings_file() writes the entire file, i.e. the -+ * header, any pre-existing bindings, and the new binding. The complete content -+ * depends on history and is different to predict here. Therefore we check only -+ * the newly added binding. Because add_binding() sorts entries, this new -+ * binding isn't necessarily the last one; receive it from will_return() and -+ * search for it with strstr(). -+ * If the string to be written doesn't start with the bindings file -+ * header, it's a test of a partial write. -+ */ -+ssize_t __wrap_write(int fd, const void *buf, size_t count) - { -- return __set_errno(mock_type(int)); -+ const char *binding, *start; - -+#if DEBUG_WRITE -+ fprintf(stderr, "%s: %zx exp %zx\n===\n%s\n===\n", __func__, strlen(buf), -+ count, (const char *)buf); -+#endif -+ if (!strncmp((const char *)buf, BINDINGS_FILE_HEADER, -+ sizeof(BINDINGS_FILE_HEADER) - 1)) -+ start = (const char *)buf + sizeof(BINDINGS_FILE_HEADER) - 1; -+ else -+ start = buf; -+ binding = mock_ptr_type(char *); -+ start = strstr(start, binding); -+ check_expected(count); -+ assert_ptr_not_equal(start, NULL); -+ return __set_errno(mock_type(int)); - } - --ssize_t __wrap_write(int fd, const void *buf, size_t count) -+int __wrap_rename(const char *old, const char *new) - { -- check_expected(count); -- check_expected(buf); - return __set_errno(mock_type(int)); - } - --int __wrap_ftruncate(int fd, off_t length) -+int __wrap_mkstemp(char *template) - { -- check_expected(length); -- return __set_errno(mock_type(int)); -+ return 10; - } - - int __wrap_dm_map_present(const char * str) -@@ -84,32 +95,6 @@ int __wrap_dm_get_uuid(const char *name, char *uuid, int uuid_len) - #define TEST_FDNO 1234 - #define TEST_FPTR ((FILE *) 0xaffe) - --int __wrap_open_file(const char *file, int *can_write, const char *header) --{ -- int cw = mock_type(int); -- -- *can_write = cw; -- return TEST_FDNO; --} -- --FILE *__wrap_fdopen(int fd, const char *mode) --{ -- assert_int_equal(fd, TEST_FDNO); -- return TEST_FPTR; --} -- --int __wrap_fflush(FILE *f) --{ -- assert_ptr_equal(f, TEST_FPTR); -- return 0; --} -- --int __wrap_fclose(FILE *f) --{ -- assert_ptr_equal(f, TEST_FPTR); -- return 0; --} -- - /* strbuf wrapper for the old format_devname() */ - static int __format_devname(char *name, int id, size_t len, const char *prefix) - { -@@ -466,22 +451,85 @@ static void mock_self_alias(const char *alias, const char *wwid) - expect_condlog(3, USED_STR(alias, wwid)); \ - } while(0) - --static void mock_bindings_file(const char *content, int match_line) -+static int add_binding_unsorted(Bindings *bindings, -+ const char *alias, const char *wwid) -+{ -+ struct binding *bdg = calloc(1, sizeof(*bdg)); -+ -+ if (!bdg) -+ return -1; -+ bdg->wwid = strdup(wwid); -+ bdg->alias = strdup(alias); -+ if (!bdg->wwid || !bdg->alias || !vector_alloc_slot(bindings)) { -+ free(bdg->alias); -+ free(bdg->wwid); -+ free(bdg); -+ return BINDING_ERROR; -+ } -+ vector_set_slot(bindings, bdg); -+ return BINDING_ADDED; -+} -+ -+static void __mock_bindings_file(const char *content, -+ int (*add)(Bindings *, const char *, const char *)) - { -- static char cnt[1024]; -- char *token; -+ char *cnt __attribute__((cleanup(cleanup_charp))) = NULL; -+ char *token, *savep = NULL; - int i; - -- assert_in_range(strlcpy(cnt, content, sizeof(cnt)), 0, sizeof(cnt) - 1); -+ cnt = strdup(content); -+ assert_ptr_not_equal(cnt, NULL); - -- for (token = strtok(cnt, "\n"), i = 0; -+ for (token = strtok_r(cnt, "\n", &savep), i = 0; - token && *token; -- token = strtok(NULL, "\n"), i++) { -- will_return(__wrap_fgets, token); -- if (match_line == i) -- return; -+ token = strtok_r(NULL, "\n", &savep), i++) { -+ char *alias, *wwid; -+ int rc; -+ -+ if (read_binding(token, i + 1, &alias, &wwid) -+ == READ_BINDING_SKIP) -+ continue; -+ -+ rc = add(&global_bindings, alias, wwid); -+ assert_int_equal(rc, BINDING_ADDED); - } -- will_return(__wrap_fgets, NULL); -+} -+ -+static void mock_bindings_file(const char *content) { -+ return __mock_bindings_file(content, add_binding); -+} -+ -+static void mock_bindings_file_unsorted(const char *content) { -+ return __mock_bindings_file(content, add_binding_unsorted); -+} -+ -+static int teardown_bindings(void **state) -+{ -+ cleanup_bindings(); -+ return 0; -+} -+ -+static int lookup_binding(FILE *dummy, const char *wwid, char **alias, -+ const char *prefix, int check_if_taken) -+{ -+ const struct binding *bdg; -+ int id; -+ -+ /* -+ * get_free_id() always checks if aliases are taken. -+ * Therefore if prefix is non-null, check_if_taken must be true. -+ */ -+ assert_true(!prefix || check_if_taken); -+ *alias = NULL; -+ bdg = get_binding_for_wwid(&global_bindings, wwid); -+ if (bdg) { -+ *alias = strdup(bdg->alias); -+ return 0; -+ } else if (!prefix && check_if_taken) -+ return -1; -+ -+ id = get_free_id(&global_bindings, prefix, wwid); -+ return id; - } - - static void lb_empty(void **state) -@@ -489,7 +537,7 @@ static void lb_empty(void **state) - int rc; - char *alias; - -- mock_bindings_file("", -1); -+ mock_bindings_file(""); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - rc = lookup_binding(NULL, "WWID0", &alias, NULL, 0); - assert_int_equal(rc, 1); -@@ -501,7 +549,7 @@ static void lb_empty_unused(void **state) - int rc; - char *alias; - -- mock_bindings_file("", -1); -+ mock_bindings_file(""); - mock_unused_alias("MPATHa"); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); -@@ -515,10 +563,10 @@ static void lb_empty_failed(void **state) - int rc; - char *alias; - -- mock_bindings_file("", -1); -+ mock_bindings_file(""); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - mock_failed_alias("MPATHa", "WWID0"); - mock_unused_alias("MPATHb"); -- expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); - assert_int_equal(rc, 2); - assert_ptr_equal(alias, NULL); -@@ -530,10 +578,10 @@ static void lb_empty_1_used(void **state) - int rc; - char *alias; - -- mock_bindings_file("", -1); -+ mock_bindings_file(""); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - mock_used_alias("MPATHa", "WWID0"); - mock_unused_alias("MPATHb"); -- expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); - assert_int_equal(rc, 2); - assert_ptr_equal(alias, NULL); -@@ -545,10 +593,10 @@ static void lb_empty_1_used_self(void **state) - int rc; - char *alias; - -- mock_bindings_file("", -1); -+ mock_bindings_file(""); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - mock_used_alias("MPATHa", "WWID0"); - mock_self_alias("MPATHb", "WWID0"); -- expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); - assert_int_equal(rc, 2); - assert_ptr_equal(alias, NULL); -@@ -560,9 +608,9 @@ static void lb_match_a(void **state) - int rc; - char *alias; - -- mock_bindings_file("MPATHa WWID0\n", 0); -+ mock_bindings_file("MPATHa WWID0\n"); - expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); -- rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 0); -+ rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); - assert_int_equal(rc, 0); - assert_ptr_not_equal(alias, NULL); - assert_string_equal(alias, "MPATHa"); -@@ -574,9 +622,10 @@ static void lb_nomatch_a(void **state) - int rc; - char *alias; - -- mock_bindings_file("MPATHa WWID0\n", -1); -+ mock_bindings_file("MPATHa WWID0\n"); - expect_condlog(3, NOMATCH_WWID_STR("WWID1")); -- rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 0); -+ mock_unused_alias("MPATHb"); -+ rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); - assert_int_equal(rc, 2); - assert_ptr_equal(alias, NULL); - } -@@ -586,8 +635,8 @@ static void lb_nomatch_a_bad_check(void **state) - int rc; - char *alias; - -- mock_bindings_file("MPATHa WWID0\n", -1); -- expect_condlog(0, NOMORE_STR); -+ mock_bindings_file("MPATHa WWID0\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID1")); - rc = lookup_binding(NULL, "WWID1", &alias, NULL, 1); - assert_int_equal(rc, -1); - assert_ptr_equal(alias, NULL); -@@ -598,7 +647,7 @@ static void lb_nomatch_a_unused(void **state) - int rc; - char *alias; - -- mock_bindings_file("MPATHa WWID0\n", -1); -+ mock_bindings_file("MPATHa WWID0\n"); - mock_unused_alias("MPATHb"); - expect_condlog(3, NOMATCH_WWID_STR("WWID1")); - rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); -@@ -611,27 +660,27 @@ static void lb_nomatch_a_3_used_failed_self(void **state) - int rc; - char *alias; - -- mock_bindings_file("MPATHa WWID0\n", -1); -+ mock_bindings_file("MPATHa WWID0\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID1")); - mock_used_alias("MPATHb", "WWID1"); - mock_used_alias("MPATHc", "WWID1"); - mock_used_alias("MPATHd", "WWID1"); - mock_failed_alias("MPATHe", "WWID1"); - mock_self_alias("MPATHf", "WWID1"); -- expect_condlog(3, NOMATCH_WWID_STR("WWID1")); - rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); - assert_int_equal(rc, 6); - assert_ptr_equal(alias, NULL); - } - --static void do_lb_match_c(void **state, int check_if_taken) -+static void do_lb_match_c(void **state) - { - int rc; - char *alias; - - mock_bindings_file("MPATHa WWID0\n" -- "MPATHc WWID1", 1); -+ "MPATHc WWID1"); - expect_condlog(3, FOUND_STR("MPATHc", "WWID1")); -- rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", check_if_taken); -+ rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); - assert_int_equal(rc, 0); - assert_ptr_not_equal(alias, NULL); - assert_string_equal(alias, "MPATHc"); -@@ -640,12 +689,12 @@ static void do_lb_match_c(void **state, int check_if_taken) - - static void lb_match_c(void **state) - { -- do_lb_match_c(state, 0); -+ do_lb_match_c(state); - } - - static void lb_match_c_check(void **state) - { -- do_lb_match_c(state, 1); -+ do_lb_match_c(state); - } - - static void lb_nomatch_a_c(void **state) -@@ -654,9 +703,10 @@ static void lb_nomatch_a_c(void **state) - char *alias; - - mock_bindings_file("MPATHa WWID0\n" -- "MPATHc WWID1", -1); -+ "MPATHc WWID1"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); -- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); -+ mock_unused_alias("MPATHb"); -+ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, 2); - assert_ptr_equal(alias, NULL); - } -@@ -667,7 +717,7 @@ static void lb_nomatch_a_d_unused(void **state) - char *alias; - - mock_bindings_file("MPATHa WWID0\n" -- "MPATHd WWID1", -1); -+ "MPATHd WWID1"); - mock_unused_alias("MPATHb"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -@@ -681,10 +731,10 @@ static void lb_nomatch_a_d_1_used(void **state) - char *alias; - - mock_bindings_file("MPATHa WWID0\n" -- "MPATHd WWID1", -1); -+ "MPATHd WWID1"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - mock_used_alias("MPATHb", "WWID2"); - mock_unused_alias("MPATHc"); -- expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, 3); - assert_ptr_equal(alias, NULL); -@@ -696,11 +746,11 @@ static void lb_nomatch_a_d_2_used(void **state) - char *alias; - - mock_bindings_file("MPATHa WWID0\n" -- "MPATHd WWID1", -1); -+ "MPATHd WWID1"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - mock_used_alias("MPATHb", "WWID2"); - mock_used_alias("MPATHc", "WWID2"); - mock_unused_alias("MPATHe"); -- expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, 5); - assert_ptr_equal(alias, NULL); -@@ -712,12 +762,12 @@ static void lb_nomatch_a_d_3_used(void **state) - char *alias; - - mock_bindings_file("MPATHa WWID0\n" -- "MPATHd WWID1", -1); -+ "MPATHd WWID1"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - mock_used_alias("MPATHb", "WWID2"); - mock_used_alias("MPATHc", "WWID2"); - mock_used_alias("MPATHe", "WWID2"); - mock_unused_alias("MPATHf"); -- expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, 6); - assert_ptr_equal(alias, NULL); -@@ -729,9 +779,10 @@ static void lb_nomatch_c_a(void **state) - char *alias; - - mock_bindings_file("MPATHc WWID1\n" -- "MPATHa WWID0\n", -1); -+ "MPATHa WWID0\n"); -+ mock_unused_alias("MPATHb"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); -- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); -+ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, 2); - assert_ptr_equal(alias, NULL); - } -@@ -743,7 +794,7 @@ static void lb_nomatch_d_a_unused(void **state) - - mock_bindings_file("MPATHc WWID1\n" - "MPATHa WWID0\n" -- "MPATHd WWID0\n", -1); -+ "MPATHd WWID0\n"); - mock_unused_alias("MPATHb"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -@@ -758,10 +809,10 @@ static void lb_nomatch_d_a_1_used(void **state) - - mock_bindings_file("MPATHc WWID1\n" - "MPATHa WWID0\n" -- "MPATHd WWID0\n", -1); -+ "MPATHd WWID0\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - mock_used_alias("MPATHb", "WWID2"); - mock_unused_alias("MPATHe"); -- expect_condlog(3, NOMATCH_WWID_STR("WWID2")); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, 5); - assert_ptr_equal(alias, NULL); -@@ -774,9 +825,10 @@ static void lb_nomatch_a_b(void **state) - - mock_bindings_file("MPATHa WWID0\n" - "MPATHz WWID26\n" -- "MPATHb WWID1\n", -1); -+ "MPATHb WWID1\n"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); -- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); -+ mock_unused_alias("MPATHc"); -+ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); - assert_int_equal(rc, 3); - assert_ptr_equal(alias, NULL); - } -@@ -786,13 +838,19 @@ static void lb_nomatch_a_b_bad(void **state) - int rc; - char *alias; - -+ expect_condlog(1, "invalid line 3 in bindings file, missing WWID\n"); -+ /* -+ * The broken line will be ignored when constructing the bindings vector. -+ * Thus in lookup_binding() MPATHb is never encountered, -+ * and MPATHb appears usable. -+ */ - mock_bindings_file("MPATHa WWID0\n" - "MPATHz WWID26\n" -- "MPATHb\n", -1); -- expect_condlog(3, "Ignoring malformed line 3 in bindings file\n"); -+ "MPATHb\n"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); -- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); -- assert_int_equal(rc, 3); -+ mock_unused_alias("MPATHb"); -+ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -+ assert_int_equal(rc, 2); - assert_ptr_equal(alias, NULL); - } - -@@ -801,84 +859,200 @@ static void lb_nomatch_a_b_bad_self(void **state) - int rc; - char *alias; - -+ expect_condlog(1, "invalid line 3 in bindings file, missing WWID\n"); - mock_bindings_file("MPATHa WWID0\n" - "MPATHz WWID26\n" -- "MPATHb\n", -1); -- expect_condlog(3, "Ignoring malformed line 3 in bindings file\n"); -- mock_self_alias("MPATHc", "WWID2"); -+ "MPATHb\n"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); -+ mock_self_alias("MPATHb", "WWID2"); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -- assert_int_equal(rc, 3); -+ assert_int_equal(rc, 2); - assert_ptr_equal(alias, NULL); - } - --static void lb_nomatch_b_a(void **state) -+static void lb_nomatch_b_z_a(void **state) - { - int rc; - char *alias; - -+ /* -+ * add_bindings() sorts alphabetically. Therefore get_free_id() -+ * finds MPATHc as a free entry. -+ */ - mock_bindings_file("MPATHb WWID1\n" - "MPATHz WWID26\n" -- "MPATHa WWID0\n", -1); -+ "MPATHa WWID0\n"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); -- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); -- assert_int_equal(rc, 27); -+ mock_unused_alias("MPATHc"); -+ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -+ assert_int_equal(rc, 3); - assert_ptr_equal(alias, NULL); - } - --static void lb_nomatch_b_a_3_used(void **state) -+static void lb_nomatch_b_aa_a(void **state) - { - int rc; - char *alias; - -+ /* -+ * add_bindings() sorts alphabetically. ("a", "aa", b"). -+ * The get_free_id() algorithm finds the "hole" after "b". -+ */ - mock_bindings_file("MPATHb WWID1\n" - "MPATHz WWID26\n" -- "MPATHa WWID0\n", -1); -- mock_used_alias("MPATHaa", "WWID2"); -- mock_used_alias("MPATHab", "WWID2"); -- mock_used_alias("MPATHac", "WWID2"); -- mock_unused_alias("MPATHad"); -+ "MPATHa WWID0\n"); - expect_condlog(3, NOMATCH_WWID_STR("WWID2")); -+ mock_unused_alias("MPATHc"); - rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -- assert_int_equal(rc, 30); -+ assert_int_equal(rc, 3); - assert_ptr_equal(alias, NULL); - } - --#ifdef MPATH_ID_INT_MAX --static void do_lb_nomatch_int_max(void **state, int check_if_taken) -+static void fill_bindings(struct strbuf *buf, int start, int end) -+{ -+ int i; -+ -+ for (i = start; i <= end; i++) { -+ print_strbuf(buf, "MPATH"); -+ format_devname(buf, i + 1); -+ print_strbuf(buf, " WWID%d\n", i); -+ } -+} -+ -+static void lb_nomatch_b_a_aa(void **state) -+{ -+ int rc; -+ char *alias; -+ STRBUF_ON_STACK(buf); -+ -+ /* -+ * add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...) -+ * lookup_binding finds MPATHac as next free entry. -+ */ -+ fill_bindings(&buf, 0, 26); -+ mock_bindings_file(get_strbuf_str(&buf)); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID28")); -+ mock_unused_alias("MPATHab"); -+ rc = lookup_binding(NULL, "WWID28", &alias, "MPATH", 1); -+ assert_int_equal(rc, 28); -+ assert_ptr_equal(alias, NULL); -+} -+ -+static void lb_nomatch_b_a_aa_zz(void **state) -+{ -+ int rc, i; -+ char *alias; -+ STRBUF_ON_STACK(buf); -+ -+ /* -+ * add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...) -+ * lookup_binding finds MPATHaaa as next free entry, because MPATHaa is -+ * found before MPATHb, and MPATHzz was in the bindings, too. -+ */ -+ for (i = 0; i <= 26; i++) { -+ print_strbuf(&buf, "MPATH"); -+ format_devname(&buf, i + 1); -+ print_strbuf(&buf, " WWID%d\n", i); -+ } -+ print_strbuf(&buf, "MPATHzz WWID676\n"); -+ mock_bindings_file(get_strbuf_str(&buf)); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID703")); -+ mock_unused_alias("MPATHaaa"); -+ rc = lookup_binding(NULL, "WWID703", &alias, "MPATH", 1); -+ assert_int_equal(rc, 703); -+ assert_ptr_equal(alias, NULL); -+} -+ -+static void lb_nomatch_b_z_a_unsorted(void **state) -+{ -+ int rc; -+ char *alias; -+ -+ /* -+ * With unsorted bindings (shouldn't happen normally), get_free_id() -+ * plays safe and returns MPATHaa as first free entry. -+ */ -+ mock_bindings_file_unsorted("MPATHb WWID1\n" -+ "MPATHz WWID26\n" -+ "MPATHa WWID0\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); -+ mock_unused_alias("MPATHaa"); -+ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -+ assert_int_equal(rc, 27); -+ assert_ptr_equal(alias, NULL); -+} -+ -+static void lb_nomatch_b_a(void **state) - { - int rc; - char *alias; - - mock_bindings_file("MPATHb WWID1\n" -- "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n" -- "MPATHa WWID0\n", -1); -- expect_condlog(0, NOMORE_STR); -- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", check_if_taken); -- assert_int_equal(rc, -1); -+ "MPATHa WWID0\n"); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID2")); -+ mock_unused_alias("MPATHc"); -+ rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -+ assert_int_equal(rc, 3); - assert_ptr_equal(alias, NULL); - } - --static void lb_nomatch_int_max(void **state) -+static void lb_nomatch_b_a_3_used(void **state) - { -- do_lb_nomatch_int_max(state, 0); -+ int rc; -+ char *alias; -+ STRBUF_ON_STACK(buf); -+ -+ fill_bindings(&buf, 0, 26); -+ mock_bindings_file(get_strbuf_str(&buf)); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID31")); -+ mock_used_alias("MPATHab", "WWID31"); -+ mock_used_alias("MPATHac", "WWID31"); -+ mock_used_alias("MPATHad", "WWID31"); -+ mock_unused_alias("MPATHae"); -+ rc = lookup_binding(NULL, "WWID31", &alias, "MPATH", 1); -+ assert_int_equal(rc, 31); -+ assert_ptr_equal(alias, NULL); - } - --static void lb_nomatch_int_max_check(void **state) -+#ifdef MPATH_ID_INT_MAX -+/* -+ * The bindings will be sorted by alias, alphabetically, which is not -+ * the same as the "numeric" sort order for user-friendly aliases. -+ * get_free_id() selects the highest used ID + 1 if an unsorted entry -+ * is encountered in the bindings table and it's id is equal to the -+ * next "expected" id. This happens if all IDs from "a" to "aa" are -+ * in the table. If the INT_MAX entry is in the table, too, it will -+ * overflow. -+ */ -+static void lb_nomatch_int_max(void **state) - { -- do_lb_nomatch_int_max(state, 1); -+ int rc; -+ char *alias; -+ STRBUF_ON_STACK(buf); -+ -+ fill_bindings(&buf, 0, 26); -+ print_strbuf(&buf, "MPATH%s WWIDMAX\n", MPATH_ID_INT_MAX); -+ mock_bindings_file(get_strbuf_str(&buf)); -+ expect_condlog(3, NOMATCH_WWID_STR("WWIDNOMORE")); -+ expect_condlog(0, NOMORE_STR); -+ rc = lookup_binding(NULL, "WWIDNOMORE", &alias, "MPATH", 1); -+ assert_int_equal(rc, -1); -+ assert_ptr_equal(alias, NULL); - } - - static void lb_nomatch_int_max_used(void **state) - { - int rc; - char *alias; -+ STRBUF_ON_STACK(buf); - -- mock_bindings_file("MPATHb WWID1\n" -- "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n", -1); -- mock_used_alias("MPATHa", "WWID2"); -+ fill_bindings(&buf, 1, 26); -+ print_strbuf(&buf, "MPATH%s WWIDMAX\n", MPATH_ID_INT_MAX); -+ mock_bindings_file(get_strbuf_str(&buf)); -+ expect_condlog(3, NOMATCH_WWID_STR("WWIDNOMORE")); -+ mock_used_alias("MPATHa", "WWIDNOMORE"); - expect_condlog(0, NOMORE_STR); -- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -+ rc = lookup_binding(NULL, "WWIDNOMORE", &alias, "MPATH", 1); - assert_int_equal(rc, -1); - assert_ptr_equal(alias, NULL); - } -@@ -887,12 +1061,14 @@ static void lb_nomatch_int_max_m1(void **state) - { - int rc; - char *alias; -+ STRBUF_ON_STACK(buf); - -- mock_bindings_file("MPATHb WWID1\n" -- "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n" -- "MPATHa WWID0\n", -1); -- expect_condlog(3, NOMATCH_WWID_STR("WWID2")); -- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); -+ fill_bindings(&buf, 0, 26); -+ print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1); -+ mock_bindings_file(get_strbuf_str(&buf)); -+ expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); -+ mock_unused_alias("MPATH" MPATH_ID_INT_MAX); -+ rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); - assert_int_equal(rc, INT_MAX); - assert_ptr_equal(alias, NULL); - } -@@ -901,13 +1077,15 @@ static void lb_nomatch_int_max_m1_used(void **state) - { - int rc; - char *alias; -+ STRBUF_ON_STACK(buf); - -- mock_bindings_file("MPATHb WWID1\n" -- "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n" -- "MPATHa WWID0\n", -1); -- mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2"); -+ fill_bindings(&buf, 0, 26); -+ print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1); -+ mock_bindings_file(get_strbuf_str(&buf)); -+ expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); -+ mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWIDMAX"); - expect_condlog(0, NOMORE_STR); -- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -+ rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); - assert_int_equal(rc, -1); - assert_ptr_equal(alias, NULL); - } -@@ -916,13 +1094,15 @@ static void lb_nomatch_int_max_m1_1_used(void **state) - { - int rc; - char *alias; -+ STRBUF_ON_STACK(buf); - -- mock_bindings_file("MPATHb WWID1\n" -- "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n", -1); -- mock_used_alias("MPATHa", "WWID2"); -+ fill_bindings(&buf, 1, 26); -+ print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1); -+ mock_bindings_file(get_strbuf_str(&buf)); -+ expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); -+ mock_used_alias("MPATHa", "WWIDMAX"); - mock_unused_alias("MPATH" MPATH_ID_INT_MAX); -- expect_condlog(3, NOMATCH_WWID_STR("WWID2")); -- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -+ rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); - assert_int_equal(rc, INT_MAX); - assert_ptr_equal(alias, NULL); - } -@@ -931,13 +1111,17 @@ static void lb_nomatch_int_max_m1_2_used(void **state) - { - int rc; - char *alias; -+ STRBUF_ON_STACK(buf); - -- mock_bindings_file("MPATHb WWID1\n" -- "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n", -1); -- mock_used_alias("MPATHa", "WWID2"); -- mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2"); -+ fill_bindings(&buf, 1, 26); -+ print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1); -+ mock_bindings_file(get_strbuf_str(&buf)); -+ -+ expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); -+ mock_used_alias("MPATHa", "WWIDMAX"); -+ mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWIDMAX"); - expect_condlog(0, NOMORE_STR); -- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -+ rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); - assert_int_equal(rc, -1); - assert_ptr_equal(alias, NULL); - } -@@ -946,52 +1130,68 @@ static void lb_nomatch_int_max_m1_2_used(void **state) - static int test_lookup_binding(void) - { - const struct CMUnitTest tests[] = { -- cmocka_unit_test(lb_empty), -- cmocka_unit_test(lb_empty_unused), -- cmocka_unit_test(lb_empty_failed), -- cmocka_unit_test(lb_empty_1_used), -- cmocka_unit_test(lb_empty_1_used_self), -- cmocka_unit_test(lb_match_a), -- cmocka_unit_test(lb_nomatch_a), -- cmocka_unit_test(lb_nomatch_a_bad_check), -- cmocka_unit_test(lb_nomatch_a_unused), -- cmocka_unit_test(lb_nomatch_a_3_used_failed_self), -- cmocka_unit_test(lb_match_c), -- cmocka_unit_test(lb_match_c_check), -- cmocka_unit_test(lb_nomatch_a_c), -- cmocka_unit_test(lb_nomatch_a_d_unused), -- cmocka_unit_test(lb_nomatch_a_d_1_used), -- cmocka_unit_test(lb_nomatch_a_d_2_used), -- cmocka_unit_test(lb_nomatch_a_d_3_used), -- cmocka_unit_test(lb_nomatch_c_a), -- cmocka_unit_test(lb_nomatch_d_a_unused), -- cmocka_unit_test(lb_nomatch_d_a_1_used), -- cmocka_unit_test(lb_nomatch_a_b), -- cmocka_unit_test(lb_nomatch_a_b_bad), -- cmocka_unit_test(lb_nomatch_a_b_bad_self), -- cmocka_unit_test(lb_nomatch_b_a), -- cmocka_unit_test(lb_nomatch_b_a_3_used), -+ cmocka_unit_test_teardown(lb_empty, teardown_bindings), -+ cmocka_unit_test_teardown(lb_empty_unused, teardown_bindings), -+ cmocka_unit_test_teardown(lb_empty_failed, teardown_bindings), -+ cmocka_unit_test_teardown(lb_empty_1_used, teardown_bindings), -+ cmocka_unit_test_teardown(lb_empty_1_used_self, teardown_bindings), -+ cmocka_unit_test_teardown(lb_match_a, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_a, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_a_bad_check, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_a_unused, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_a_3_used_failed_self, teardown_bindings), -+ cmocka_unit_test_teardown(lb_match_c, teardown_bindings), -+ cmocka_unit_test_teardown(lb_match_c_check, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_a_c, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_a_d_unused, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_a_d_1_used, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_a_d_2_used, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_a_d_3_used, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_c_a, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_d_a_unused, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_d_a_1_used, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_a_b, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_a_b_bad, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_a_b_bad_self, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_b_z_a, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_b_aa_a, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_b_a_aa, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_b_a_aa_zz, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_b_z_a_unsorted, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_b_a, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_b_a_3_used, teardown_bindings), - #ifdef MPATH_ID_INT_MAX -- cmocka_unit_test(lb_nomatch_int_max), -- cmocka_unit_test(lb_nomatch_int_max_check), -- cmocka_unit_test(lb_nomatch_int_max_used), -- cmocka_unit_test(lb_nomatch_int_max_m1), -- cmocka_unit_test(lb_nomatch_int_max_m1_used), -- cmocka_unit_test(lb_nomatch_int_max_m1_1_used), -- cmocka_unit_test(lb_nomatch_int_max_m1_2_used), -+ cmocka_unit_test_teardown(lb_nomatch_int_max, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_int_max_used, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_int_max_m1, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_int_max_m1_used, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_int_max_m1_1_used, teardown_bindings), -+ cmocka_unit_test_teardown(lb_nomatch_int_max_m1_2_used, teardown_bindings), - #endif - }; - - return cmocka_run_group_tests(tests, NULL, NULL); - } - -+static int rlookup_binding(FILE *dummy, char *buf, const char *alias) { -+ -+ const struct binding *bdg; -+ -+ bdg = get_binding_for_alias(&global_bindings, alias); -+ if (!bdg) { -+ return -1; -+ } -+ strlcpy(buf, bdg->wwid, WWID_SIZE); -+ return 0; -+} -+ - static void rl_empty(void **state) - { - int rc; - char buf[WWID_SIZE]; - - buf[0] = '\0'; -- mock_bindings_file("", -1); -+ mock_bindings_file(""); - expect_condlog(3, NOMATCH_STR("MPATHa")); - rc = rlookup_binding(NULL, buf, "MPATHa"); - assert_int_equal(rc, -1); -@@ -1004,7 +1204,7 @@ static void rl_match_a(void **state) - char buf[WWID_SIZE]; - - buf[0] = '\0'; -- mock_bindings_file("MPATHa WWID0\n", 0); -+ mock_bindings_file("MPATHa WWID0\n"); - expect_condlog(3, FOUND_ALIAS_STR("MPATHa", "WWID0")); - rc = rlookup_binding(NULL, buf, "MPATHa"); - assert_int_equal(rc, 0); -@@ -1017,7 +1217,7 @@ static void rl_nomatch_a(void **state) - char buf[WWID_SIZE]; - - buf[0] = '\0'; -- mock_bindings_file("MPATHa WWID0\n", -1); -+ mock_bindings_file("MPATHa WWID0\n"); - expect_condlog(3, NOMATCH_STR("MPATHb")); - rc = rlookup_binding(NULL, buf, "MPATHb"); - assert_int_equal(rc, -1); -@@ -1030,8 +1230,8 @@ static void rl_malformed_a(void **state) - char buf[WWID_SIZE]; - - buf[0] = '\0'; -- mock_bindings_file("MPATHa \n", -1); -- expect_condlog(3, "Ignoring malformed line 1 in bindings file\n"); -+ expect_condlog(1, "invalid line 1 in bindings file, missing WWID\n"); -+ mock_bindings_file("MPATHa \n"); - expect_condlog(3, NOMATCH_STR("MPATHa")); - rc = rlookup_binding(NULL, buf, "MPATHa"); - assert_int_equal(rc, -1); -@@ -1049,8 +1249,8 @@ static void rl_overlong_a(void **state) - snprintf(line + sizeof(line) - 2, 2, "\n"); - - buf[0] = '\0'; -- mock_bindings_file(line, -1); - expect_condlog(3, "Ignoring too large wwid at 1 in bindings file\n"); -+ mock_bindings_file(line); - expect_condlog(3, NOMATCH_STR("MPATHa")); - rc = rlookup_binding(NULL, buf, "MPATHa"); - assert_int_equal(rc, -1); -@@ -1065,7 +1265,7 @@ static void rl_match_b(void **state) - buf[0] = '\0'; - mock_bindings_file("MPATHa WWID0\n" - "MPATHz WWID26\n" -- "MPATHb WWID2\n", 2); -+ "MPATHb WWID2\n"); - expect_condlog(3, FOUND_ALIAS_STR("MPATHb", "WWID2")); - rc = rlookup_binding(NULL, buf, "MPATHb"); - assert_int_equal(rc, 0); -@@ -1075,31 +1275,41 @@ static void rl_match_b(void **state) - static int test_rlookup_binding(void) - { - const struct CMUnitTest tests[] = { -- cmocka_unit_test(rl_empty), -- cmocka_unit_test(rl_match_a), -- cmocka_unit_test(rl_nomatch_a), -- cmocka_unit_test(rl_malformed_a), -- cmocka_unit_test(rl_overlong_a), -- cmocka_unit_test(rl_match_b), -+ cmocka_unit_test_teardown(rl_empty, teardown_bindings), -+ cmocka_unit_test_teardown(rl_match_a, teardown_bindings), -+ cmocka_unit_test_teardown(rl_nomatch_a, teardown_bindings), -+ cmocka_unit_test_teardown(rl_malformed_a, teardown_bindings), -+ cmocka_unit_test_teardown(rl_overlong_a, teardown_bindings), -+ cmocka_unit_test_teardown(rl_match_b, teardown_bindings), - }; - - return cmocka_run_group_tests(tests, NULL, NULL); - } - -+void check_bindings_size(int n) -+{ -+ /* avoid -Waddress problem */ -+ Bindings *bindings = &global_bindings; -+ -+ assert_int_equal(VECTOR_SIZE(bindings), n); -+} -+ - static void al_a(void **state) - { - static const char ln[] = "MPATHa WWIDa\n"; - char *alias; - -- will_return(__wrap_lseek, 0); -- expect_value(__wrap_write, count, strlen(ln)); -- expect_string(__wrap_write, buf, ln); -- will_return(__wrap_write, strlen(ln)); -+ expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); -+ will_return(__wrap_write, ln); -+ will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); -+ will_return(__wrap_rename, 0); -+ expect_condlog(1, "updated bindings file foo"); - expect_condlog(3, NEW_STR("MPATHa", "WWIDa")); - -- alias = allocate_binding(0, "WWIDa", 1, "MPATH"); -+ alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); - assert_ptr_not_equal(alias, NULL); - assert_string_equal(alias, "MPATHa"); -+ check_bindings_size(1); - free(alias); - } - -@@ -1108,15 +1318,17 @@ static void al_zz(void **state) - static const char ln[] = "MPATHzz WWIDzz\n"; - char *alias; - -- will_return(__wrap_lseek, 0); -- expect_value(__wrap_write, count, strlen(ln)); -- expect_string(__wrap_write, buf, ln); -- will_return(__wrap_write, strlen(ln)); -+ expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); -+ will_return(__wrap_write, ln); -+ will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); -+ will_return(__wrap_rename, 0); -+ expect_condlog(1, "updated bindings file foo"); - expect_condlog(3, NEW_STR("MPATHzz", "WWIDzz")); - -- alias = allocate_binding(0, "WWIDzz", 26*26 + 26, "MPATH"); -+ alias = allocate_binding("foo", "WWIDzz", 26*26 + 26, "MPATH"); - assert_ptr_not_equal(alias, NULL); - assert_string_equal(alias, "MPATHzz"); -+ check_bindings_size(1); - free(alias); - } - -@@ -1127,6 +1339,7 @@ static void al_0(void **state) - expect_condlog(0, "allocate_binding: cannot allocate new binding for id 0\n"); - alias = allocate_binding(0, "WWIDa", 0, "MPATH"); - assert_ptr_equal(alias, NULL); -+ check_bindings_size(0); - } - - static void al_m2(void **state) -@@ -1136,67 +1349,133 @@ static void al_m2(void **state) - expect_condlog(0, "allocate_binding: cannot allocate new binding for id -2\n"); - alias = allocate_binding(0, "WWIDa", -2, "MPATH"); - assert_ptr_equal(alias, NULL); -+ check_bindings_size(0); -+} -+ -+static void al_write_partial(void **state) -+{ -+ static const char ln[] = "MPATHa WWIDa\n"; -+ char *alias; -+ -+ expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); -+ will_return(__wrap_write, ln); -+ will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln) - 1); -+ expect_value(__wrap_write, count, 1); -+ will_return(__wrap_write, ln + sizeof(ln) - 2); -+ will_return(__wrap_write, 1); -+ will_return(__wrap_rename, 0); -+ expect_condlog(1, "updated bindings file foo"); -+ expect_condlog(3, "Created new binding [MPATHa] for WWID [WWIDa]\n"); -+ -+ alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); -+ assert_ptr_not_equal(alias, NULL); -+ assert_string_equal(alias, "MPATHa"); -+ check_bindings_size(1); -+ free(alias); - } - --static void al_lseek_err(void **state) -+static void al_write_short(void **state) - { -+ static const char ln[] = "MPATHa WWIDa\n"; - char *alias; - -- will_return(__wrap_lseek, -ENODEV); -- expect_condlog(0, "Cannot seek to end of bindings file : No such device\n"); -- alias = allocate_binding(0, "WWIDa", 1, "MPATH"); -+ expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); -+ will_return(__wrap_write, ln); -+ will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln) - 1); -+ expect_value(__wrap_write, count, 1); -+ will_return(__wrap_write, ln + sizeof(ln) - 2); -+ will_return(__wrap_write, 0); -+ expect_condlog(2, "write_bindings_file: short write"); -+ expect_condlog(1, "failed to write new bindings file"); -+ expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa"); -+ -+ alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); - assert_ptr_equal(alias, NULL); -+ check_bindings_size(0); - } - - static void al_write_err(void **state) - { - static const char ln[] = "MPATHa WWIDa\n"; -- const int offset = 20; - char *alias; - -- will_return(__wrap_lseek, offset); -- expect_value(__wrap_write, count, strlen(ln)); -- expect_string(__wrap_write, buf, ln); -- will_return(__wrap_write, strlen(ln) - 1); -- expect_value(__wrap_ftruncate, length, offset); -- will_return(__wrap_ftruncate, 0); -- expect_condlog(0, "Cannot write binding to bindings file :"); -+ expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); -+ will_return(__wrap_write, ln); -+ will_return(__wrap_write, -EPERM); -+ expect_condlog(1, "failed to write new bindings file"); -+ expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa"); - -- alias = allocate_binding(0, "WWIDa", 1, "MPATH"); -+ alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); - assert_ptr_equal(alias, NULL); -+ check_bindings_size(0); -+} -+ -+static void al_rename_err(void **state) -+{ -+ static const char ln[] = "MPATHa WWIDa\n"; -+ char *alias; -+ -+ expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); -+ will_return(__wrap_write, ln); -+ will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); -+ will_return(__wrap_rename, -EROFS); -+ -+ expect_condlog(0, "update_bindings_file: rename: Read-only file system"); -+ expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa"); -+ alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); -+ assert_ptr_equal(alias, NULL); -+ check_bindings_size(0); - } - - static int test_allocate_binding(void) - { - const struct CMUnitTest tests[] = { -- cmocka_unit_test(al_a), -- cmocka_unit_test(al_zz), -- cmocka_unit_test(al_0), -- cmocka_unit_test(al_m2), -- cmocka_unit_test(al_lseek_err), -- cmocka_unit_test(al_write_err), -+ cmocka_unit_test_teardown(al_a, teardown_bindings), -+ cmocka_unit_test_teardown(al_zz, teardown_bindings), -+ cmocka_unit_test_teardown(al_0, teardown_bindings), -+ cmocka_unit_test_teardown(al_m2, teardown_bindings), -+ cmocka_unit_test_teardown(al_write_partial, teardown_bindings), -+ cmocka_unit_test_teardown(al_write_short, teardown_bindings), -+ cmocka_unit_test_teardown(al_write_err, teardown_bindings), -+ cmocka_unit_test_teardown(al_rename_err, teardown_bindings), - }; - - return cmocka_run_group_tests(tests, NULL, NULL); - } - --#define mock_allocate_binding(alias, wwid) \ -+#define mock_allocate_binding_err_len(alias, wwid, len, err, msg) \ - do { \ - static const char ln[] = BINDING_STR(alias, wwid); \ - \ -- will_return(__wrap_lseek, 0); \ -- expect_value(__wrap_write, count, strlen(ln)); \ -- expect_string(__wrap_write, buf, ln); \ -- will_return(__wrap_write, strlen(ln)); \ -- expect_condlog(3, NEW_STR(alias, wwid)); \ -+ expect_value(__wrap_write, count, \ -+ strlen(BINDINGS_FILE_HEADER) + (len) + strlen(ln)); \ -+ will_return(__wrap_write, ln); \ -+ will_return(__wrap_write, \ -+ strlen(BINDINGS_FILE_HEADER) + (len) + strlen(ln)); \ -+ will_return(__wrap_rename, err); \ -+ if (err == 0) { \ -+ expect_condlog(1, "updated bindings file x\n"); \ -+ expect_condlog(3, NEW_STR(alias, wwid)); \ -+ } else { \ -+ expect_condlog(0, "update_bindings_file: rename: " msg "\n"); \ -+ expect_condlog(1, "allocate_binding: deleting binding " \ -+ alias " for " wwid "\n"); \ -+ } \ - } while (0) - -+#define mock_allocate_binding_err(alias, wwid, err, msg) \ -+ mock_allocate_binding_err_len(alias, wwid, 0, err, msg) -+ -+#define mock_allocate_binding(alias, wwid) \ -+ mock_allocate_binding_err(alias, wwid, 0, "") -+ -+#define mock_allocate_binding_len(alias, wwid, len) \ -+ mock_allocate_binding_err_len(alias, wwid, len, 0, "") -+ - static void gufa_empty_new_rw(void **state) { - char *alias; - -- will_return(__wrap_open_file, true); -- -- mock_bindings_file("", -1); -+ mock_bindings_file(""); - mock_unused_alias("MPATHa"); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - -@@ -1208,10 +1487,11 @@ static void gufa_empty_new_rw(void **state) { - - static void gufa_empty_new_ro_1(void **state) { - char *alias; -- will_return(__wrap_open_file, false); -- mock_bindings_file("", -1); -+ -+ mock_bindings_file(""); - mock_unused_alias("MPATHa"); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); -+ mock_allocate_binding_err("MPATHa", "WWID0", -EROFS, "Read-only file system"); - - alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false); - assert_ptr_equal(alias, NULL); -@@ -1220,11 +1500,9 @@ static void gufa_empty_new_ro_1(void **state) { - static void gufa_empty_new_ro_2(void **state) { - char *alias; - -- will_return(__wrap_open_file, true); -- -- mock_bindings_file("", -1); -- mock_unused_alias("MPATHa"); -+ mock_bindings_file(""); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); -+ mock_unused_alias("MPATHa"); - - alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); - assert_ptr_equal(alias, NULL); -@@ -1233,11 +1511,10 @@ static void gufa_empty_new_ro_2(void **state) { - static void gufa_match_a_unused(void **state) { - char *alias; - -- will_return(__wrap_open_file, true); -- -- mock_bindings_file("MPATHa WWID0", 0); -+ mock_bindings_file("MPATHa WWID0"); - expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); - mock_unused_alias("MPATHa"); -+ expect_condlog(3, EXISTING_STR("MPATHa", "WWID0")); - - alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); - assert_string_equal(alias, "MPATHa"); -@@ -1247,11 +1524,10 @@ static void gufa_match_a_unused(void **state) { - static void gufa_match_a_self(void **state) { - char *alias; - -- will_return(__wrap_open_file, true); -- -- mock_bindings_file("MPATHa WWID0", 0); -+ mock_bindings_file("MPATHa WWID0"); - expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); - mock_self_alias("MPATHa", "WWID0"); -+ expect_condlog(3, EXISTING_STR("MPATHa", "WWID0")); - - alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); - assert_string_equal(alias, "MPATHa"); -@@ -1261,9 +1537,8 @@ static void gufa_match_a_self(void **state) { - static void gufa_match_a_used(void **state) { - char *alias; - -- will_return(__wrap_open_file, true); - -- mock_bindings_file("MPATHa WWID0", 0); -+ mock_bindings_file("MPATHa WWID0"); - expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); - mock_used_alias("MPATHa", "WWID0"); - -@@ -1273,15 +1548,14 @@ static void gufa_match_a_used(void **state) { - - static void gufa_nomatch_a_c(void **state) { - char *alias; -- will_return(__wrap_open_file, true); -+ static const char bindings[] = ("MPATHa WWID0\n" -+ "MPATHc WWID2\n"); - -- mock_bindings_file("MPATHa WWID0\n" -- "MPATHc WWID2", -- -1); -+ mock_bindings_file(bindings); - mock_unused_alias("MPATHb"); - expect_condlog(3, NOMATCH_WWID_STR("WWID1")); - -- mock_allocate_binding("MPATHb", "WWID1"); -+ mock_allocate_binding_len("MPATHb", "WWID1", strlen(bindings)); - - alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false); - assert_string_equal(alias, "MPATHb"); -@@ -1290,15 +1564,14 @@ static void gufa_nomatch_a_c(void **state) { - - static void gufa_nomatch_c_a(void **state) { - char *alias; -- will_return(__wrap_open_file, true); -+ const char bindings[] = ("MPATHc WWID2\n" -+ "MPATHa WWID0\n"); - -- mock_bindings_file("MPATHc WWID2\n" -- "MPATHa WWID0", -- -1); -+ mock_bindings_file(bindings); - mock_unused_alias("MPATHb"); - expect_condlog(3, NOMATCH_WWID_STR("WWID1")); - -- mock_allocate_binding("MPATHb", "WWID1"); -+ mock_allocate_binding_len("MPATHb", "WWID1", sizeof(bindings) - 1); - - alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false); - assert_string_equal(alias, "MPATHb"); -@@ -1307,15 +1580,14 @@ static void gufa_nomatch_c_a(void **state) { - - static void gufa_nomatch_c_b(void **state) { - char *alias; -- will_return(__wrap_open_file, true); -+ const char bindings[] = ("MPATHc WWID2\n" -+ "MPATHb WWID1\n"); - -- mock_bindings_file("MPATHc WWID2\n" -- "MPATHb WWID1\n", -- -1); -- mock_unused_alias("MPATHa"); -+ mock_bindings_file(bindings); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); -+ mock_unused_alias("MPATHa"); - -- mock_allocate_binding("MPATHa", "WWID0"); -+ mock_allocate_binding_len("MPATHa", "WWID0", sizeof(bindings) - 1); - - alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false); - assert_string_equal(alias, "MPATHa"); -@@ -1324,16 +1596,15 @@ static void gufa_nomatch_c_b(void **state) { - - static void gufa_nomatch_c_b_used(void **state) { - char *alias; -- will_return(__wrap_open_file, true); -+ const char bindings[] = ("MPATHc WWID2\n" -+ "MPATHb WWID1\n"); - -- mock_bindings_file("MPATHc WWID2\n" -- "MPATHb WWID1", -- -1); -- mock_used_alias("MPATHa", "WWID4"); -+ mock_bindings_file(bindings); - expect_condlog(3, NOMATCH_WWID_STR("WWID4")); -+ mock_used_alias("MPATHa", "WWID4"); - mock_unused_alias("MPATHd"); - -- mock_allocate_binding("MPATHd", "WWID4"); -+ mock_allocate_binding_len("MPATHd", "WWID4", sizeof(bindings) - 1); - - alias = get_user_friendly_alias("WWID4", "x", "", "MPATH", false); - assert_string_equal(alias, "MPATHd"); -@@ -1342,32 +1613,59 @@ static void gufa_nomatch_c_b_used(void **state) { - - static void gufa_nomatch_b_f_a(void **state) { - char *alias; -- will_return(__wrap_open_file, true); -+ const char bindings[] = ("MPATHb WWID1\n" -+ "MPATHf WWID6\n" -+ "MPATHa WWID0\n"); - -- mock_bindings_file("MPATHb WWID1\n" -- "MPATHf WWID6\n" -- "MPATHa WWID0\n", -- -1); -+ mock_bindings_file_unsorted(bindings); - expect_condlog(3, NOMATCH_WWID_STR("WWID7")); - mock_unused_alias("MPATHg"); - -- mock_allocate_binding("MPATHg", "WWID7"); -+ mock_allocate_binding_len("MPATHg", "WWID7", sizeof(bindings) - 1); - - alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false); - assert_string_equal(alias, "MPATHg"); - free(alias); - } - -+static void gufa_nomatch_b_aa_a(void **state) { -+ char *alias; -+ STRBUF_ON_STACK(buf); -+ -+ fill_bindings(&buf, 0, 26); -+ mock_bindings_file(get_strbuf_str(&buf)); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID28")); -+ mock_unused_alias("MPATHab"); -+ mock_allocate_binding_len("MPATHab", "WWID28", get_strbuf_len(&buf)); -+ -+ alias = get_user_friendly_alias("WWID28", "x", "", "MPATH", false); -+ assert_string_equal(alias, "MPATHab"); -+ free(alias); -+} -+ -+static void gufa_nomatch_b_f_a_sorted(void **state) { -+ char *alias; -+ const char bindings[] = ("MPATHb WWID1\n" -+ "MPATHf WWID6\n" -+ "MPATHa WWID0\n"); -+ -+ mock_bindings_file(bindings); -+ expect_condlog(3, NOMATCH_WWID_STR("WWID7")); -+ mock_unused_alias("MPATHc"); -+ -+ mock_allocate_binding_len("MPATHc", "WWID7", sizeof(bindings) - 1); -+ -+ alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false); -+ assert_string_equal(alias, "MPATHc"); -+ free(alias); -+} -+ - static void gufa_old_empty(void **state) { - char *alias; -- will_return(__wrap_open_file, true); - - /* rlookup_binding for ALIAS */ -- mock_bindings_file("", -1); -+ mock_bindings_file(""); - expect_condlog(3, NOMATCH_STR("MPATHz")); -- -- /* lookup_binding */ -- mock_bindings_file("", -1); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - - mock_allocate_binding("MPATHz", "WWID0"); -@@ -1380,11 +1678,9 @@ static void gufa_old_empty(void **state) { - - static void gufa_old_match(void **state) { - char *alias; -- will_return(__wrap_open_file, true); - - mock_bindings_file("MPATHb WWID1\n" -- "MPATHz WWID0", -- 1); -+ "MPATHz WWID0"); - expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID0")); - - alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); -@@ -1394,19 +1690,15 @@ static void gufa_old_match(void **state) { - - static void gufa_old_match_other(void **state) { - char *alias; -- static const char bindings[] = "MPATHz WWID9"; -- -- will_return(__wrap_open_file, true); -+ static const char bindings[] = "MPATHz WWID9\n"; - -- mock_bindings_file(bindings, 0); -+ mock_bindings_file(bindings); - expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9")); - expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); -- -- mock_bindings_file(bindings, -1); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - mock_unused_alias("MPATHa"); - -- mock_allocate_binding("MPATHa", "WWID0"); -+ mock_allocate_binding_len("MPATHa", "WWID0", sizeof(bindings) - 1); - - alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); - assert_string_equal(alias, "MPATHa"); -@@ -1415,21 +1707,16 @@ static void gufa_old_match_other(void **state) { - - static void gufa_old_match_other_used(void **state) { - char *alias; -- static const char bindings[] = "MPATHz WWID9"; -+ static const char bindings[] = "MPATHz WWID9\n"; - -- will_return(__wrap_open_file, true); -- -- mock_bindings_file(bindings, 0); -+ mock_bindings_file(bindings); - expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9")); - expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); -- -- mock_bindings_file(bindings, -1); -- mock_used_alias("MPATHa", "WWID0"); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); -+ mock_used_alias("MPATHa", "WWID0"); - mock_unused_alias("MPATHb"); - -- mock_allocate_binding("MPATHb", "WWID0"); -- -+ mock_allocate_binding_len("MPATHb", "WWID0", sizeof(bindings) - 1); - alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); - assert_string_equal(alias, "MPATHb"); - free(alias); -@@ -1439,15 +1726,13 @@ static void gufa_old_match_other_wwidmatch(void **state) { - char *alias; - static const char bindings[] = ("MPATHz WWID9\n" - "MPATHc WWID2"); -- will_return(__wrap_open_file, true); - -- mock_bindings_file(bindings, 0); -+ mock_bindings_file(bindings); - expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9")); - expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); -- -- mock_bindings_file(bindings, 1); - expect_condlog(3, FOUND_STR("MPATHc", "WWID2")); - mock_unused_alias("MPATHc"); -+ expect_condlog(3, EXISTING_STR("MPATHc", "WWID2")); - - alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false); - assert_string_equal(alias, "MPATHc"); -@@ -1459,13 +1744,9 @@ static void gufa_old_match_other_wwidmatch_used(void **state) { - static const char bindings[] = ("MPATHz WWID9\n" - "MPATHc WWID2"); - -- will_return(__wrap_open_file, true); -- -- mock_bindings_file(bindings, 0); -+ mock_bindings_file(bindings); - expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9")); - expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); -- -- mock_bindings_file(bindings, 1); - expect_condlog(3, FOUND_STR("MPATHc", "WWID2")); - mock_used_alias("MPATHc", "WWID2"); - -@@ -1477,12 +1758,8 @@ static void gufa_old_nomatch_wwidmatch(void **state) { - char *alias; - static const char bindings[] = "MPATHa WWID0"; - -- will_return(__wrap_open_file, true); -- -- mock_bindings_file(bindings, -1); -+ mock_bindings_file(bindings); - expect_condlog(3, NOMATCH_STR("MPATHz")); -- -- mock_bindings_file(bindings, 0); - expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); - mock_unused_alias("MPATHa"); - expect_condlog(3, EXISTING_STR("MPATHa", "WWID0")); -@@ -1495,12 +1772,9 @@ static void gufa_old_nomatch_wwidmatch(void **state) { - static void gufa_old_nomatch_wwidmatch_used(void **state) { - char *alias; - static const char bindings[] = "MPATHa WWID0"; -- will_return(__wrap_open_file, true); - -- mock_bindings_file(bindings, -1); -+ mock_bindings_file(bindings); - expect_condlog(3, NOMATCH_STR("MPATHz")); -- -- mock_bindings_file(bindings, 0); - expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); - mock_used_alias("MPATHa", "WWID0"); - -@@ -1510,17 +1784,13 @@ static void gufa_old_nomatch_wwidmatch_used(void **state) { - - static void gufa_old_nomatch_nowwidmatch(void **state) { - char *alias; -- static const char bindings[] = "MPATHb WWID1"; -- -- will_return(__wrap_open_file, true); -+ static const char bindings[] = "MPATHb WWID1\n"; - -- mock_bindings_file(bindings, -1); -+ mock_bindings_file(bindings); - expect_condlog(3, NOMATCH_STR("MPATHz")); -- -- mock_bindings_file(bindings, -1); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - -- mock_allocate_binding("MPATHz", "WWID0"); -+ mock_allocate_binding_len("MPATHz", "WWID0", sizeof(bindings) - 1); - expect_condlog(2, ALLOC_STR("MPATHz", "WWID0")); - - alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); -@@ -1531,26 +1801,28 @@ static void gufa_old_nomatch_nowwidmatch(void **state) { - static int test_get_user_friendly_alias() - { - const struct CMUnitTest tests[] = { -- cmocka_unit_test(gufa_empty_new_rw), -- cmocka_unit_test(gufa_empty_new_ro_1), -- cmocka_unit_test(gufa_empty_new_ro_2), -- cmocka_unit_test(gufa_match_a_unused), -- cmocka_unit_test(gufa_match_a_self), -- cmocka_unit_test(gufa_match_a_used), -- cmocka_unit_test(gufa_nomatch_a_c), -- cmocka_unit_test(gufa_nomatch_c_a), -- cmocka_unit_test(gufa_nomatch_c_b), -- cmocka_unit_test(gufa_nomatch_c_b_used), -- cmocka_unit_test(gufa_nomatch_b_f_a), -- cmocka_unit_test(gufa_old_empty), -- cmocka_unit_test(gufa_old_match), -- cmocka_unit_test(gufa_old_match_other), -- cmocka_unit_test(gufa_old_match_other_used), -- cmocka_unit_test(gufa_old_match_other_wwidmatch), -- cmocka_unit_test(gufa_old_match_other_wwidmatch_used), -- cmocka_unit_test(gufa_old_nomatch_wwidmatch), -- cmocka_unit_test(gufa_old_nomatch_wwidmatch_used), -- cmocka_unit_test(gufa_old_nomatch_nowwidmatch), -+ cmocka_unit_test_teardown(gufa_empty_new_rw, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_empty_new_ro_1, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_empty_new_ro_2, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_match_a_unused, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_match_a_self, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_match_a_used, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_nomatch_a_c, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_nomatch_c_a, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_nomatch_c_b, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_nomatch_c_b_used, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_nomatch_b_f_a, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_nomatch_b_aa_a, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_nomatch_b_f_a_sorted, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_old_empty, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_old_match, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_old_match_other, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_old_match_other_used, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_old_match_other_wwidmatch, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_old_match_other_wwidmatch_used, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_old_nomatch_wwidmatch, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_old_nomatch_wwidmatch_used, teardown_bindings), -+ cmocka_unit_test_teardown(gufa_old_nomatch_nowwidmatch, teardown_bindings), - }; - - return cmocka_run_group_tests(tests, NULL, NULL); -@@ -1566,7 +1838,6 @@ int main(void) - ret += test_lookup_binding(); - ret += test_rlookup_binding(); - ret += test_allocate_binding(); -- ret += test_allocate_binding(); - ret += test_get_user_friendly_alias(); - - return ret; diff --git a/0020-libmultipath-dm_get_uuid-return-emtpy-UUID-for-non-e.patch b/0020-libmultipath-dm_get_uuid-return-emtpy-UUID-for-non-e.patch deleted file mode 100644 index c105b01..0000000 --- a/0020-libmultipath-dm_get_uuid-return-emtpy-UUID-for-non-e.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 25 Aug 2023 20:35:19 +0200 -Subject: [PATCH] libmultipath: dm_get_uuid(): return emtpy UUID for - non-existing maps - -libdevmapper will most probably not return a UUID for non-existing -maps anyway. But it's cheap to double-check here. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/devmapper.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c -index 248c3734..9be82f4e 100644 ---- a/libmultipath/devmapper.c -+++ b/libmultipath/devmapper.c -@@ -706,12 +706,16 @@ dm_get_prefixed_uuid(const char *name, char *uuid, int uuid_len) - { - struct dm_task *dmt; - const char *uuidtmp; -+ struct dm_info info; - int r = 1; - - dmt = libmp_dm_task_create(DM_DEVICE_INFO); - if (!dmt) - return 1; - -+ if (uuid_len > 0) -+ uuid[0] = '\0'; -+ - if (!dm_task_set_name (dmt, name)) - goto uuidout; - -@@ -720,11 +724,13 @@ dm_get_prefixed_uuid(const char *name, char *uuid, int uuid_len) - goto uuidout; - } - -+ if (!dm_task_get_info(dmt, &info) || -+ !info.exists) -+ goto uuidout; -+ - uuidtmp = dm_task_get_uuid(dmt); - if (uuidtmp) - strlcpy(uuid, uuidtmp, uuid_len); -- else -- uuid[0] = '\0'; - - r = 0; - uuidout: diff --git a/0021-libmultipath-adapt-to-new-semantics-of-dm_get_uuid.patch b/0021-libmultipath-adapt-to-new-semantics-of-dm_get_uuid.patch deleted file mode 100644 index 4d15554..0000000 --- a/0021-libmultipath-adapt-to-new-semantics-of-dm_get_uuid.patch +++ /dev/null @@ -1,158 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Mon, 28 Aug 2023 12:26:37 +0200 -Subject: [PATCH] libmultipath: adapt to new semantics of dm_get_uuid() - -dm_get_uuid() will return 1 for non-existing maps. Thus we don't need -to call dm_map_present() any more in alias_already_taken(). This changes -our semantics: previously we'd avoid using an alias for which dm_get_uuid() -had failed. Now we treat failure in dm_get_uuid() as indication that the -map doesn't exist. This is not dangerous because dm_task_get_uuid() cannot -fail, and thus the modified dm_get_uuid() will fail if and only if -dm_map_present() would return false. - -This makes the "failed alias" test mostly obsolete, as "failed" is now -treated as "unused". - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/alias.c | 25 +++++++++++++------------ - tests/alias.c | 32 +++++++------------------------- - 2 files changed, 20 insertions(+), 37 deletions(-) - -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index d6563749..58436ec0 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -295,18 +295,19 @@ scan_devname(const char *alias, const char *prefix) - static bool alias_already_taken(const char *alias, const char *map_wwid) - { - -- if (dm_map_present(alias)) { -- char wwid[WWID_SIZE]; -- -- /* If both the name and the wwid match, then it's fine.*/ -- if (dm_get_uuid(alias, wwid, sizeof(wwid)) == 0 && -- strncmp(map_wwid, wwid, sizeof(wwid)) == 0) -- return false; -- condlog(3, "%s: alias '%s' already taken, reselecting alias", -- map_wwid, alias); -- return true; -- } -- return false; -+ char wwid[WWID_SIZE]; -+ -+ /* If the map doesn't exist, it's fine */ -+ if (dm_get_uuid(alias, wwid, sizeof(wwid)) != 0) -+ return false; -+ -+ /* If both the name and the wwid match, it's fine.*/ -+ if (strncmp(map_wwid, wwid, sizeof(wwid)) == 0) -+ return false; -+ -+ condlog(3, "%s: alias '%s' already taken, reselecting alias", -+ map_wwid, alias); -+ return true; - } - - static bool id_already_taken(int id, const char *prefix, const char *map_wwid) -diff --git a/tests/alias.c b/tests/alias.c -index 50a21ecf..d1cc487b 100644 ---- a/tests/alias.c -+++ b/tests/alias.c -@@ -73,12 +73,6 @@ int __wrap_mkstemp(char *template) - return 10; - } - --int __wrap_dm_map_present(const char * str) --{ -- check_expected(str); -- return mock_type(int); --} -- - int __wrap_dm_get_uuid(const char *name, char *uuid, int uuid_len) - { - int ret; -@@ -398,14 +392,13 @@ static int test_scan_devname(void) - - static void mock_unused_alias(const char *alias) - { -- expect_string(__wrap_dm_map_present, str, alias); -- will_return(__wrap_dm_map_present, 0); -+ expect_string(__wrap_dm_get_uuid, name, alias); -+ expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); -+ will_return(__wrap_dm_get_uuid, 1); - } - - static void mock_self_alias(const char *alias, const char *wwid) - { -- expect_string(__wrap_dm_map_present, str, alias); -- will_return(__wrap_dm_map_present, 1); - expect_string(__wrap_dm_get_uuid, name, alias); - expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); - will_return(__wrap_dm_get_uuid, 0); -@@ -432,18 +425,13 @@ static void mock_self_alias(const char *alias, const char *wwid) - - #define mock_failed_alias(alias, wwid) \ - do { \ -- expect_string(__wrap_dm_map_present, str, alias); \ -- will_return(__wrap_dm_map_present, 1); \ - expect_string(__wrap_dm_get_uuid, name, alias); \ - expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); \ - will_return(__wrap_dm_get_uuid, 1); \ -- expect_condlog(3, USED_STR(alias, wwid)); \ - } while (0) - - #define mock_used_alias(alias, wwid) \ - do { \ -- expect_string(__wrap_dm_map_present, str, alias); \ -- will_return(__wrap_dm_map_present, 1); \ - expect_string(__wrap_dm_get_uuid, name, alias); \ - expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); \ - will_return(__wrap_dm_get_uuid, 0); \ -@@ -566,9 +554,8 @@ static void lb_empty_failed(void **state) - mock_bindings_file(""); - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - mock_failed_alias("MPATHa", "WWID0"); -- mock_unused_alias("MPATHb"); - rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); -- assert_int_equal(rc, 2); -+ assert_int_equal(rc, 1); - assert_ptr_equal(alias, NULL); - free(alias); - } -@@ -666,9 +653,8 @@ static void lb_nomatch_a_3_used_failed_self(void **state) - mock_used_alias("MPATHc", "WWID1"); - mock_used_alias("MPATHd", "WWID1"); - mock_failed_alias("MPATHe", "WWID1"); -- mock_self_alias("MPATHf", "WWID1"); - rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); -- assert_int_equal(rc, 6); -+ assert_int_equal(rc, 5); - assert_ptr_equal(alias, NULL); - } - -@@ -940,7 +926,7 @@ static void lb_nomatch_b_a_aa(void **state) - - static void lb_nomatch_b_a_aa_zz(void **state) - { -- int rc, i; -+ int rc; - char *alias; - STRBUF_ON_STACK(buf); - -@@ -949,11 +935,7 @@ static void lb_nomatch_b_a_aa_zz(void **state) - * lookup_binding finds MPATHaaa as next free entry, because MPATHaa is - * found before MPATHb, and MPATHzz was in the bindings, too. - */ -- for (i = 0; i <= 26; i++) { -- print_strbuf(&buf, "MPATH"); -- format_devname(&buf, i + 1); -- print_strbuf(&buf, " WWID%d\n", i); -- } -+ fill_bindings(&buf, 0, 26); - print_strbuf(&buf, "MPATHzz WWID676\n"); - mock_bindings_file(get_strbuf_str(&buf)); - expect_condlog(3, NOMATCH_WWID_STR("WWID703")); diff --git a/0022-libmultipath-sort-aliases-by-length-and-strcmp.patch b/0022-libmultipath-sort-aliases-by-length-and-strcmp.patch deleted file mode 100644 index 1504bec..0000000 --- a/0022-libmultipath-sort-aliases-by-length-and-strcmp.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 8 Sep 2023 15:19:54 +0200 -Subject: [PATCH] libmultipath: sort aliases by length and strcmp - -The current sort order of aliases is alphabetical, which is does not match -the actual order of aliases, where "mpathaa" > "mpathz". Change the ordering as -follows: first sort by string length, then alphabetically. This will make -sure that for aliases with the same prefix, alias order is correct ("mpathaaa" -will be sorted after "mpathzz", etc). Even for mixed prefixes, the alias -order will be correct for every individual prefix, even though aliases with -different prefixes may alternate in the file. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/alias.c | 45 +++++++++++++++++++++++++++++++++----------- - 1 file changed, 34 insertions(+), 11 deletions(-) - -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index 58436ec0..af6565b1 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -117,6 +117,35 @@ static const struct binding *get_binding_for_wwid(const Bindings *bindings, - return NULL; - } - -+/* -+ * Sort order for aliases. -+ * -+ * The "numeric" ordering of aliases for a given prefix P is -+ * Pa, ..., Pz, Paa, ..., Paz, Pba, ... , Pzz, Paaa, ..., Pzzz, Paaaa, ... -+ * We use the fact that for equal prefix, longer strings are always -+ * higher than shorter ones. Strings of equal length are sorted alphabetically. -+ * This is achieved by sorting be length first, then using strcmp(). -+ * If multiple prefixes are in use, the aliases with a given prefix will -+ * not necessarily be in a contiguous range of the vector, but they will -+ * be ordered such that for a given prefix, numercally higher aliases will -+ * always be sorted after lower ones. -+ */ -+static int alias_compar(const void *p1, const void *p2) -+{ -+ const char *alias1 = *((char * const *)p1); -+ const char *alias2 = *((char * const *)p2); -+ -+ if (alias1 && alias2) { -+ ssize_t ldif = strlen(alias1) - strlen(alias2); -+ -+ if (ldif) -+ return ldif; -+ return strcmp(alias1, alias2); -+ } else -+ /* Move NULL alias to the end */ -+ return alias1 ? -1 : alias2 ? 1 : 0; -+} -+ - static int add_binding(Bindings *bindings, const char *alias, const char *wwid) - { - struct binding *bdg; -@@ -128,7 +157,7 @@ static int add_binding(Bindings *bindings, const char *alias, const char *wwid) - * sorted already. - */ - vector_foreach_slot_backwards(bindings, bdg, i) { -- if ((cmp = strcmp(bdg->alias, alias)) <= 0) -+ if ((cmp = alias_compar(&bdg->alias, &alias)) <= 0) - break; - } - -@@ -657,16 +686,10 @@ static int _check_bindings_file(const struct config *conf, FILE *file, - return rc; - } - --static int alias_compar(const void *p1, const void *p2) -+static int mp_alias_compar(const void *p1, const void *p2) - { -- const char *alias1 = (*(struct mpentry * const *)p1)->alias; -- const char *alias2 = (*(struct mpentry * const *)p2)->alias; -- -- if (alias1 && alias2) -- return strcmp(alias1, alias2); -- else -- /* Move NULL alias to the end */ -- return alias1 ? -1 : alias2 ? 1 : 0; -+ return alias_compar(&((*(struct mpentry * const *)p1)->alias), -+ &((*(struct mpentry * const *)p2)->alias)); - } - - /* -@@ -700,7 +723,7 @@ int check_alias_settings(const struct config *conf) - pthread_cleanup_push_cast(free_bindings, &bindings); - pthread_cleanup_push(cleanup_vector_free, mptable); - -- vector_sort(mptable, alias_compar); -+ vector_sort(mptable, mp_alias_compar); - vector_foreach_slot(mptable, mpe, i) { - if (!mpe->alias) - /* diff --git a/0023-multipath-tools-tests-fix-alias-test-after-sort-orde.patch b/0023-multipath-tools-tests-fix-alias-test-after-sort-orde.patch deleted file mode 100644 index dd0f29d..0000000 --- a/0023-multipath-tools-tests-fix-alias-test-after-sort-orde.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 8 Sep 2023 15:46:02 +0200 -Subject: [PATCH] multipath-tools tests: fix alias test after sort order change - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - tests/alias.c | 30 ++++++++++++------------------ - 1 file changed, 12 insertions(+), 18 deletions(-) - -diff --git a/tests/alias.c b/tests/alias.c -index d1cc487b..8ed95d7a 100644 ---- a/tests/alias.c -+++ b/tests/alias.c -@@ -932,16 +932,15 @@ static void lb_nomatch_b_a_aa_zz(void **state) - - /* - * add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...) -- * lookup_binding finds MPATHaaa as next free entry, because MPATHaa is -- * found before MPATHb, and MPATHzz was in the bindings, too. -+ * lookup_binding finds MPATHab as next free entry. - */ - fill_bindings(&buf, 0, 26); - print_strbuf(&buf, "MPATHzz WWID676\n"); - mock_bindings_file(get_strbuf_str(&buf)); - expect_condlog(3, NOMATCH_WWID_STR("WWID703")); -- mock_unused_alias("MPATHaaa"); -+ mock_unused_alias("MPATHab"); - rc = lookup_binding(NULL, "WWID703", &alias, "MPATH", 1); -- assert_int_equal(rc, 703); -+ assert_int_equal(rc, 28); - assert_ptr_equal(alias, NULL); - } - -@@ -998,13 +997,8 @@ static void lb_nomatch_b_a_3_used(void **state) - - #ifdef MPATH_ID_INT_MAX - /* -- * The bindings will be sorted by alias, alphabetically, which is not -- * the same as the "numeric" sort order for user-friendly aliases. -- * get_free_id() selects the highest used ID + 1 if an unsorted entry -- * is encountered in the bindings table and it's id is equal to the -- * next "expected" id. This happens if all IDs from "a" to "aa" are -- * in the table. If the INT_MAX entry is in the table, too, it will -- * overflow. -+ * The bindings will be sorted by alias. Therefore we have no chance to -+ * simulate a "full" table. - */ - static void lb_nomatch_int_max(void **state) - { -@@ -1016,9 +1010,9 @@ static void lb_nomatch_int_max(void **state) - print_strbuf(&buf, "MPATH%s WWIDMAX\n", MPATH_ID_INT_MAX); - mock_bindings_file(get_strbuf_str(&buf)); - expect_condlog(3, NOMATCH_WWID_STR("WWIDNOMORE")); -- expect_condlog(0, NOMORE_STR); -+ mock_unused_alias("MPATHab"); - rc = lookup_binding(NULL, "WWIDNOMORE", &alias, "MPATH", 1); -- assert_int_equal(rc, -1); -+ assert_int_equal(rc, 28); - assert_ptr_equal(alias, NULL); - } - -@@ -1049,9 +1043,9 @@ static void lb_nomatch_int_max_m1(void **state) - print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1); - mock_bindings_file(get_strbuf_str(&buf)); - expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); -- mock_unused_alias("MPATH" MPATH_ID_INT_MAX); -+ mock_unused_alias("MPATHab"); - rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); -- assert_int_equal(rc, INT_MAX); -+ assert_int_equal(rc, 28); - assert_ptr_equal(alias, NULL); - } - -@@ -1065,10 +1059,10 @@ static void lb_nomatch_int_max_m1_used(void **state) - print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1); - mock_bindings_file(get_strbuf_str(&buf)); - expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); -- mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWIDMAX"); -- expect_condlog(0, NOMORE_STR); -+ mock_used_alias("MPATHab", "WWIDMAX"); -+ mock_unused_alias("MPATHac"); - rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); -- assert_int_equal(rc, -1); -+ assert_int_equal(rc, 29); - assert_ptr_equal(alias, NULL); - } - diff --git a/0024-libmultipath-simplify-get_free_id-assuming-total-ord.patch b/0024-libmultipath-simplify-get_free_id-assuming-total-ord.patch deleted file mode 100644 index b16b3da..0000000 --- a/0024-libmultipath-simplify-get_free_id-assuming-total-ord.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 8 Sep 2023 19:50:51 +0200 -Subject: [PATCH] libmultipath: simplify get_free_id() assuming total ordering - -If we can assume that the bindings array is totally ordered for every -prefix, which the previous patch guarantees, the search for a free ID can be -simplified. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/alias.c | 85 ++++++++++---------------------------------- - 1 file changed, 18 insertions(+), 67 deletions(-) - -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index af6565b1..66e34e31 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -356,83 +356,34 @@ int get_free_id(const Bindings *bindings, const char *prefix, const char *map_ww - { - const struct binding *bdg; - int i, id = 1; -- int biggest_id = 1; -- int smallest_bigger_id = INT_MAX; - - vector_foreach_slot(bindings, bdg, i) { - int curr_id = scan_devname(bdg->alias, prefix); - -- /* -- * Find an unused index - explanation of the algorithm -- * -- * ID: 1 = mpatha, 2 = mpathb, ... -- * -- * We assume the bindings are unsorted. The only constraint -- * is that no ID occurs more than once. IDs that occur in the -- * bindings are called "used". -- * -- * We call the list 1,2,3,..., exactly in this order, the list -- * of "expected" IDs. The variable "id" always holds the next -- * "expected" ID, IOW the last "expected" ID encountered plus 1. -- * Thus all IDs below "id" are known to be used. However, at the -- * end of the loop, the value of "id" isn't necessarily unused. -- * -- * "smallest_bigger_id" is the smallest used ID that was -- * encountered while it was larger than the next "expected" ID -- * at that iteration. Let X be some used ID. If all IDs below X -- * are used and encountered in the right sequence before X, "id" -- * will be > X when the loop ends. Otherwise, X was encountered -- * "out of order", the condition (X > id) holds when X is -- * encountered, and "smallest_bigger_id" will be set to X; i.e. -- * it will be less or equal than X when the loop ends. -- * -- * At the end of the loop, (id < smallest_bigger_id) means that -- * the value of "id" had been encountered neither in order nor -- * out of order, and is thus unused. (id >= smallest_bigger_id) -- * means that "id"'s value is in use. In this case, we play safe -- * and use "biggest_id + 1" as the next value to try. -- * -- * biggest_id is always > smallest_bigger_id, except in the -- * "perfectly ordered" case. -- */ -- if (curr_id == id) { -- if (id < INT_MAX) -- id++; -- else { -- id = -1; -- break; -- } -+ if (curr_id == -1) -+ continue; -+ if (id > curr_id) { -+ condlog(0, "%s: ERROR: bindings are not sorted", __func__); -+ return -1; - } -- if (curr_id > biggest_id) -- biggest_id = curr_id; -- -- if (curr_id > id && curr_id < smallest_bigger_id) -- smallest_bigger_id = curr_id; -+ while (id < curr_id && id_already_taken(id, prefix, map_wwid)) -+ id++; -+ if (id < curr_id) -+ return id; -+ id++; -+ if (id <= 0) -+ break; - } - -- if (id >= smallest_bigger_id) -- id = biggest_id < INT_MAX ? biggest_id + 1 : -1; -- -- if (id > 0) { -- while(id_already_taken(id, prefix, map_wwid)) { -- if (id == INT_MAX) { -- id = -1; -- break; -- } -- id++; -- if (id == smallest_bigger_id) { -- if (biggest_id == INT_MAX) { -- id = -1; -- break; -- } -- if (biggest_id >= smallest_bigger_id) -- id = biggest_id + 1; -- } -- } -+ for (; id > 0; id++) { -+ if (!id_already_taken(id, prefix, map_wwid)) -+ break; - } - -- if (id < 0) -+ if (id <= 0) { -+ id = -1; - condlog(0, "no more available user_friendly_names"); -+ } - return id; - } - diff --git a/0025-multipath-tools-tests-adapt-alias-tests-for-total-or.patch b/0025-multipath-tools-tests-adapt-alias-tests-for-total-or.patch deleted file mode 100644 index b1d6b15..0000000 --- a/0025-multipath-tools-tests-adapt-alias-tests-for-total-or.patch +++ /dev/null @@ -1,203 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 8 Sep 2023 19:58:03 +0200 -Subject: [PATCH] multipath-tools tests: adapt alias tests for total ordering - -The "unsorted" test fail now, and are removed. The algorithm is now -better at finding "gaps". - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - tests/alias.c | 88 ++++++++------------------------------------------- - 1 file changed, 14 insertions(+), 74 deletions(-) - -diff --git a/tests/alias.c b/tests/alias.c -index 8ed95d7a..dff5f93b 100644 ---- a/tests/alias.c -+++ b/tests/alias.c -@@ -439,27 +439,7 @@ static void mock_self_alias(const char *alias, const char *wwid) - expect_condlog(3, USED_STR(alias, wwid)); \ - } while(0) - --static int add_binding_unsorted(Bindings *bindings, -- const char *alias, const char *wwid) --{ -- struct binding *bdg = calloc(1, sizeof(*bdg)); -- -- if (!bdg) -- return -1; -- bdg->wwid = strdup(wwid); -- bdg->alias = strdup(alias); -- if (!bdg->wwid || !bdg->alias || !vector_alloc_slot(bindings)) { -- free(bdg->alias); -- free(bdg->wwid); -- free(bdg); -- return BINDING_ERROR; -- } -- vector_set_slot(bindings, bdg); -- return BINDING_ADDED; --} -- --static void __mock_bindings_file(const char *content, -- int (*add)(Bindings *, const char *, const char *)) -+static void __mock_bindings_file(const char *content) - { - char *cnt __attribute__((cleanup(cleanup_charp))) = NULL; - char *token, *savep = NULL; -@@ -478,17 +458,13 @@ static void __mock_bindings_file(const char *content, - == READ_BINDING_SKIP) - continue; - -- rc = add(&global_bindings, alias, wwid); -+ rc = add_binding(&global_bindings, alias, wwid); - assert_int_equal(rc, BINDING_ADDED); - } - } - - static void mock_bindings_file(const char *content) { -- return __mock_bindings_file(content, add_binding); --} -- --static void mock_bindings_file_unsorted(const char *content) { -- return __mock_bindings_file(content, add_binding_unsorted); -+ return __mock_bindings_file(content); - } - - static int teardown_bindings(void **state) -@@ -861,10 +837,6 @@ static void lb_nomatch_b_z_a(void **state) - int rc; - char *alias; - -- /* -- * add_bindings() sorts alphabetically. Therefore get_free_id() -- * finds MPATHc as a free entry. -- */ - mock_bindings_file("MPATHb WWID1\n" - "MPATHz WWID26\n" - "MPATHa WWID0\n"); -@@ -880,10 +852,6 @@ static void lb_nomatch_b_aa_a(void **state) - int rc; - char *alias; - -- /* -- * add_bindings() sorts alphabetically. ("a", "aa", b"). -- * The get_free_id() algorithm finds the "hole" after "b". -- */ - mock_bindings_file("MPATHb WWID1\n" - "MPATHz WWID26\n" - "MPATHa WWID0\n"); -@@ -911,10 +879,6 @@ static void lb_nomatch_b_a_aa(void **state) - char *alias; - STRBUF_ON_STACK(buf); - -- /* -- * add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...) -- * lookup_binding finds MPATHac as next free entry. -- */ - fill_bindings(&buf, 0, 26); - mock_bindings_file(get_strbuf_str(&buf)); - expect_condlog(3, NOMATCH_WWID_STR("WWID28")); -@@ -930,10 +894,6 @@ static void lb_nomatch_b_a_aa_zz(void **state) - char *alias; - STRBUF_ON_STACK(buf); - -- /* -- * add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...) -- * lookup_binding finds MPATHab as next free entry. -- */ - fill_bindings(&buf, 0, 26); - print_strbuf(&buf, "MPATHzz WWID676\n"); - mock_bindings_file(get_strbuf_str(&buf)); -@@ -944,25 +904,6 @@ static void lb_nomatch_b_a_aa_zz(void **state) - assert_ptr_equal(alias, NULL); - } - --static void lb_nomatch_b_z_a_unsorted(void **state) --{ -- int rc; -- char *alias; -- -- /* -- * With unsorted bindings (shouldn't happen normally), get_free_id() -- * plays safe and returns MPATHaa as first free entry. -- */ -- mock_bindings_file_unsorted("MPATHb WWID1\n" -- "MPATHz WWID26\n" -- "MPATHa WWID0\n"); -- expect_condlog(3, NOMATCH_WWID_STR("WWID2")); -- mock_unused_alias("MPATHaa"); -- rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); -- assert_int_equal(rc, 27); -- assert_ptr_equal(alias, NULL); --} -- - static void lb_nomatch_b_a(void **state) - { - int rc; -@@ -1027,9 +968,9 @@ static void lb_nomatch_int_max_used(void **state) - mock_bindings_file(get_strbuf_str(&buf)); - expect_condlog(3, NOMATCH_WWID_STR("WWIDNOMORE")); - mock_used_alias("MPATHa", "WWIDNOMORE"); -- expect_condlog(0, NOMORE_STR); -+ mock_unused_alias("MPATHab"); - rc = lookup_binding(NULL, "WWIDNOMORE", &alias, "MPATH", 1); -- assert_int_equal(rc, -1); -+ assert_int_equal(rc, 28); - assert_ptr_equal(alias, NULL); - } - -@@ -1077,9 +1018,9 @@ static void lb_nomatch_int_max_m1_1_used(void **state) - mock_bindings_file(get_strbuf_str(&buf)); - expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); - mock_used_alias("MPATHa", "WWIDMAX"); -- mock_unused_alias("MPATH" MPATH_ID_INT_MAX); -+ mock_unused_alias("MPATHab"); - rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); -- assert_int_equal(rc, INT_MAX); -+ assert_int_equal(rc, 28); - assert_ptr_equal(alias, NULL); - } - -@@ -1095,10 +1036,10 @@ static void lb_nomatch_int_max_m1_2_used(void **state) - - expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); - mock_used_alias("MPATHa", "WWIDMAX"); -- mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWIDMAX"); -- expect_condlog(0, NOMORE_STR); -+ mock_used_alias("MPATHab", "WWIDMAX"); -+ mock_unused_alias("MPATHac"); - rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); -- assert_int_equal(rc, -1); -+ assert_int_equal(rc, 29); - assert_ptr_equal(alias, NULL); - } - #endif -@@ -1133,7 +1074,6 @@ static int test_lookup_binding(void) - cmocka_unit_test_teardown(lb_nomatch_b_aa_a, teardown_bindings), - cmocka_unit_test_teardown(lb_nomatch_b_a_aa, teardown_bindings), - cmocka_unit_test_teardown(lb_nomatch_b_a_aa_zz, teardown_bindings), -- cmocka_unit_test_teardown(lb_nomatch_b_z_a_unsorted, teardown_bindings), - cmocka_unit_test_teardown(lb_nomatch_b_a, teardown_bindings), - cmocka_unit_test_teardown(lb_nomatch_b_a_3_used, teardown_bindings), - #ifdef MPATH_ID_INT_MAX -@@ -1593,14 +1533,14 @@ static void gufa_nomatch_b_f_a(void **state) { - "MPATHf WWID6\n" - "MPATHa WWID0\n"); - -- mock_bindings_file_unsorted(bindings); -+ mock_bindings_file(bindings); - expect_condlog(3, NOMATCH_WWID_STR("WWID7")); -- mock_unused_alias("MPATHg"); -+ mock_unused_alias("MPATHc"); - -- mock_allocate_binding_len("MPATHg", "WWID7", sizeof(bindings) - 1); -+ mock_allocate_binding_len("MPATHc", "WWID7", sizeof(bindings) - 1); - - alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false); -- assert_string_equal(alias, "MPATHg"); -+ assert_string_equal(alias, "MPATHc"); - free(alias); - } - diff --git a/0026-multipath-tools-tests-add-test-for-ordering-of-bindi.patch b/0026-multipath-tools-tests-add-test-for-ordering-of-bindi.patch deleted file mode 100644 index 5317ef9..0000000 --- a/0026-multipath-tools-tests-add-test-for-ordering-of-bindi.patch +++ /dev/null @@ -1,275 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 8 Sep 2023 21:39:44 +0200 -Subject: [PATCH] multipath-tools tests: add test for ordering of bindings - -As the assignment of free aliases now relies on the bindings being -properly sorted, add some unit tests to make sure the sorting algorithm -works. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - tests/alias.c | 212 +++++++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 209 insertions(+), 3 deletions(-) - -diff --git a/tests/alias.c b/tests/alias.c -index dff5f93b..7f3ff38a 100644 ---- a/tests/alias.c -+++ b/tests/alias.c -@@ -13,6 +13,9 @@ - #include "globals.c" - #include "../libmultipath/alias.c" - -+/* For verbose printing of all aliases in the ordering tests */ -+#define ALIAS_DEBUG 0 -+ - #if INT_MAX == 0x7fffffff - /* user_friendly_name for map #INT_MAX */ - #define MPATH_ID_INT_MAX "fxshrxw" -@@ -439,11 +442,12 @@ static void mock_self_alias(const char *alias, const char *wwid) - expect_condlog(3, USED_STR(alias, wwid)); \ - } while(0) - --static void __mock_bindings_file(const char *content) -+static void __mock_bindings_file(const char *content, bool conflict_ok) - { - char *cnt __attribute__((cleanup(cleanup_charp))) = NULL; - char *token, *savep = NULL; - int i; -+ uintmax_t values[] = { BINDING_ADDED, BINDING_CONFLICT }; - - cnt = strdup(content); - assert_ptr_not_equal(cnt, NULL); -@@ -459,12 +463,12 @@ static void __mock_bindings_file(const char *content) - continue; - - rc = add_binding(&global_bindings, alias, wwid); -- assert_int_equal(rc, BINDING_ADDED); -+ assert_in_set(rc, values, conflict_ok ? 2 : 1); - } - } - - static void mock_bindings_file(const char *content) { -- return __mock_bindings_file(content); -+ return __mock_bindings_file(content, false); - } - - static int teardown_bindings(void **state) -@@ -1744,6 +1748,207 @@ static int test_get_user_friendly_alias() - return cmocka_run_group_tests(tests, NULL, NULL); - } - -+/* Numbers 1-1000, randomly shuffled */ -+static const int random_numbers[1000] = { -+ 694, 977, 224, 178, 841, 818, 914, 549, 831, 942, 263, 834, 919, 800, -+ 111, 517, 719, 297, 988, 98, 332, 516, 754, 772, 495, 488, 331, 529, -+ 142, 747, 848, 618, 375, 624, 74, 753, 782, 944, 623, 468, 862, 997, -+ 417, 258, 298, 774, 673, 904, 883, 766, 867, 400, 11, 950, 14, 784, -+ 655, 155, 396, 9, 743, 93, 651, 245, 968, 306, 785, 581, 880, 486, -+ 168, 631, 203, 4, 663, 294, 702, 762, 619, 684, 48, 181, 21, 443, 643, -+ 863, 1000, 327, 26, 126, 382, 765, 586, 76, 49, 925, 319, 865, 797, -+ 876, 693, 334, 433, 243, 419, 901, 854, 326, 985, 347, 874, 527, 282, -+ 290, 380, 167, 95, 3, 257, 936, 60, 426, 227, 345, 577, 492, 467, 580, -+ 967, 422, 823, 718, 610, 64, 700, 412, 163, 288, 506, 828, 432, 51, -+ 356, 348, 539, 478, 17, 945, 602, 123, 450, 660, 429, 113, 310, 358, -+ 512, 758, 508, 19, 542, 304, 286, 446, 918, 723, 333, 603, 731, 978, -+ 230, 697, 109, 872, 175, 853, 947, 965, 121, 222, 101, 811, 117, 601, -+ 191, 752, 384, 415, 938, 278, 915, 715, 240, 552, 912, 838, 150, 840, -+ 627, 29, 636, 464, 861, 481, 992, 249, 934, 82, 368, 724, 807, 593, -+ 157, 147, 199, 637, 41, 62, 902, 505, 621, 342, 174, 260, 729, 961, -+ 219, 311, 629, 789, 81, 739, 860, 712, 223, 165, 741, 981, 485, 363, -+ 346, 709, 125, 369, 279, 634, 399, 162, 193, 769, 149, 314, 868, 612, -+ 524, 675, 341, 343, 476, 606, 388, 613, 850, 264, 903, 451, 908, 779, -+ 453, 148, 497, 46, 132, 43, 885, 955, 269, 395, 72, 128, 767, 989, -+ 929, 423, 742, 55, 13, 79, 924, 182, 295, 563, 668, 169, 974, 154, -+ 970, 54, 674, 52, 437, 570, 550, 531, 554, 793, 678, 218, 367, 105, -+ 197, 315, 958, 892, 86, 47, 284, 37, 561, 522, 198, 689, 817, 573, -+ 877, 201, 803, 501, 881, 546, 530, 523, 780, 579, 953, 135, 23, 620, -+ 84, 698, 303, 656, 357, 323, 494, 58, 131, 913, 995, 120, 70, 1, 195, -+ 365, 210, 25, 898, 173, 307, 239, 77, 418, 952, 963, 92, 455, 425, 12, -+ 536, 161, 328, 933, 401, 251, 735, 725, 362, 322, 557, 681, 302, 53, -+ 786, 801, 391, 946, 748, 133, 717, 851, 7, 372, 993, 387, 906, 373, -+ 667, 33, 670, 389, 209, 611, 896, 652, 69, 999, 344, 845, 633, 36, -+ 487, 192, 180, 45, 640, 427, 707, 805, 188, 152, 905, 217, 30, 252, -+ 386, 665, 299, 541, 410, 787, 5, 857, 751, 392, 44, 595, 146, 745, -+ 641, 957, 866, 773, 806, 815, 659, 102, 704, 430, 106, 296, 129, 847, -+ 130, 990, 669, 236, 225, 680, 159, 213, 438, 189, 447, 600, 232, 594, -+ 32, 56, 390, 647, 855, 428, 330, 714, 738, 706, 666, 461, 469, 482, -+ 558, 814, 559, 177, 575, 538, 309, 383, 261, 156, 420, 761, 630, 893, -+ 10, 116, 940, 844, 71, 377, 662, 312, 520, 244, 143, 759, 119, 186, -+ 592, 909, 864, 376, 768, 254, 265, 394, 511, 760, 574, 6, 436, 514, -+ 59, 226, 644, 956, 578, 825, 548, 145, 736, 597, 378, 821, 987, 897, -+ 354, 144, 722, 895, 589, 503, 826, 498, 543, 617, 763, 231, 808, 528, -+ 89, 479, 607, 737, 170, 404, 371, 65, 103, 340, 283, 141, 313, 858, -+ 289, 124, 971, 687, 954, 732, 39, 926, 176, 100, 267, 519, 890, 535, -+ 276, 448, 27, 457, 899, 385, 184, 275, 770, 544, 614, 449, 160, 658, -+ 259, 973, 108, 604, 24, 207, 562, 757, 744, 324, 444, 962, 591, 480, -+ 398, 409, 998, 253, 325, 445, 979, 8, 35, 118, 73, 683, 208, 85, 190, -+ 791, 408, 871, 657, 179, 18, 556, 496, 475, 20, 894, 484, 775, 889, -+ 463, 241, 730, 57, 907, 551, 859, 943, 185, 416, 870, 590, 435, 471, -+ 932, 268, 381, 626, 502, 565, 273, 534, 672, 778, 292, 473, 566, 104, -+ 172, 285, 832, 411, 329, 628, 397, 472, 271, 910, 711, 690, 969, 585, -+ 809, 941, 923, 555, 228, 685, 242, 94, 96, 211, 140, 61, 922, 795, -+ 869, 34, 255, 38, 984, 676, 15, 560, 632, 434, 921, 355, 582, 351, -+ 212, 200, 819, 960, 649, 852, 75, 771, 361, 996, 238, 316, 720, 671, -+ 462, 112, 569, 171, 664, 625, 588, 405, 553, 270, 533, 353, 842, 114, -+ 972, 83, 937, 63, 194, 237, 537, 980, 802, 916, 959, 688, 839, 350, -+ 917, 650, 545, 615, 151, 352, 686, 726, 266, 509, 439, 491, 935, 608, -+ 518, 653, 339, 609, 277, 635, 836, 88, 407, 440, 642, 927, 229, 727, -+ 360, 477, 846, 413, 454, 616, 28, 598, 567, 540, 790, 424, 247, 317, -+ 746, 911, 798, 321, 547, 248, 734, 829, 220, 138, 756, 500, 691, 196, -+ 740, 930, 843, 733, 221, 827, 50, 813, 949, 525, 349, 474, 134, 875, -+ 695, 513, 414, 515, 638, 99, 366, 490, 975, 246, 465, 206, 281, 583, -+ 256, 587, 749, 2, 951, 679, 215, 364, 458, 402, 646, 991, 335, 982, -+ 835, 300, 900, 703, 994, 983, 234, 888, 532, 804, 584, 305, 792, 442, -+ 291, 964, 158, 370, 452, 250, 521, 166, 948, 812, 794, 272, 699, 205, -+ 183, 507, 301, 920, 781, 233, 824, 137, 489, 833, 887, 966, 856, 78, -+ 830, 153, 359, 696, 526, 216, 66, 701, 403, 891, 849, 571, 308, 483, -+ 164, 293, 928, 677, 320, 837, 441, 639, 564, 510, 648, 274, 336, 661, -+ 878, 777, 816, 976, 493, 810, 67, 87, 91, 187, 882, 986, 80, 22, 499, -+ 90, 705, 139, 136, 122, 708, 716, 886, 572, 127, 40, 721, 764, 16, -+ 379, 692, 645, 456, 710, 460, 783, 97, 776, 713, 884, 115, 466, 596, -+ 374, 406, 110, 568, 68, 214, 622, 470, 107, 504, 682, 31, 421, 576, -+ 654, 605, 788, 799, 280, 338, 931, 873, 204, 287, 459, 755, 939, 599, -+ 431, 796, 235, 42, 750, 262, 318, 393, 202, 822, 879, 820, 728, 337, -+}; -+ -+static void fill_bindings_random(struct strbuf *buf, int start, int end, -+ const char *prefix) -+{ -+ int i; -+ -+ for (i = start; i < end; i++) { -+ print_strbuf(buf, "%s", prefix); -+ format_devname(buf, random_numbers[i]); -+ print_strbuf(buf, " WWID%d\n", random_numbers[i]); -+ } -+} -+ -+struct random_aliases { -+ int start; -+ int end; -+ const char *prefix; -+}; -+ -+static void order_test(int n, const struct random_aliases ra[], bool conflict_ok) -+{ -+ STRBUF_ON_STACK(buf); -+ int i, j, prev, curr, tmp; -+ struct binding *bdg; -+ Bindings *bindings = &global_bindings; -+ -+ for (j = 0; j < n; j++) -+ fill_bindings_random(&buf, ra[j].start, ra[j].end, ra[j].prefix); -+ __mock_bindings_file(get_strbuf_str(&buf), conflict_ok); -+ -+ for (j = 0; j < n; j++) { -+ bdg = VECTOR_SLOT(bindings, 0); -+ if (ALIAS_DEBUG && j == 0) -+ printf("%d: %s\n", 0, bdg->alias); -+ prev = scan_devname(bdg->alias, ra[j].prefix); -+ i = 1; -+ vector_foreach_slot_after(bindings, bdg, i) { -+ if (ALIAS_DEBUG && j == 0) -+ printf("%d: %s\n", i, bdg->alias); -+ tmp = scan_devname(bdg->alias, ra[j].prefix); -+ if (tmp == -1) -+ continue; -+ curr = tmp; -+ if (prev > 0) { -+ if (curr <= prev) -+ printf("ERROR: %d (%s) %d >= %d\n", -+ i, bdg->alias, prev, curr); -+ assert_true(curr > prev); -+ } -+ prev = curr; -+ } -+ } -+} -+ -+static void order_01(void **state) -+{ -+ const struct random_aliases ra[] = { -+ { 0, 1000, "MPATH" }, -+ }; -+ -+ order_test(ARRAY_SIZE(ra), ra, false); -+} -+ -+static void order_02(void **state) -+{ -+ const struct random_aliases ra[] = { -+ { 0, 500, "MPATH" }, -+ { 200, 700, "mpath" }, -+ }; -+ order_test(ARRAY_SIZE(ra), ra, false); -+} -+ -+static void order_03(void **state) -+{ -+ const struct random_aliases ra[] = { -+ { 500, 1000, "MPTH" }, -+ { 0, 500, "MPATH" }, -+ }; -+ order_test(ARRAY_SIZE(ra), ra, false); -+} -+ -+static void order_04(void **state) -+{ -+ const struct random_aliases ra[] = { -+ { 0, 500, "mpa" }, -+ { 250, 750, "mp" }, -+ }; -+ order_test(ARRAY_SIZE(ra), ra, true); -+} -+ -+static void order_05(void **state) -+{ -+ const struct random_aliases ra[] = { -+ { 0, 100, "A" }, -+ { 0, 100, "B" }, -+ { 0, 100, "C" }, -+ { 0, 100, "D" }, -+ }; -+ order_test(ARRAY_SIZE(ra), ra, false); -+} -+ -+static void order_06(void **state) -+{ -+ const struct random_aliases ra[] = { -+ { 0, 100, "" }, -+ { 0, 100, "a" }, -+ { 0, 100, "aa" }, -+ { 0, 100, "ab" }, -+ { 0, 100, "aaa" }, -+ }; -+ order_test(ARRAY_SIZE(ra), ra, true); -+} -+ -+static int test_bindings_order() -+{ -+ const struct CMUnitTest tests[] = { -+ cmocka_unit_test_teardown(order_01, teardown_bindings), -+ cmocka_unit_test_teardown(order_02, teardown_bindings), -+ cmocka_unit_test_teardown(order_03, teardown_bindings), -+ cmocka_unit_test_teardown(order_04, teardown_bindings), -+ cmocka_unit_test_teardown(order_05, teardown_bindings), -+ cmocka_unit_test_teardown(order_06, teardown_bindings), -+ }; -+ -+ return cmocka_run_group_tests(tests, NULL, NULL); -+} -+ - int main(void) - { - int ret = 0; -@@ -1755,6 +1960,7 @@ int main(void) - ret += test_rlookup_binding(); - ret += test_allocate_binding(); - ret += test_get_user_friendly_alias(); -+ ret += test_bindings_order(); - - return ret; - } diff --git a/0027-multipathd-watch-bindings-file-with-inotify-timestam.patch b/0027-multipathd-watch-bindings-file-with-inotify-timestam.patch deleted file mode 100644 index af21b74..0000000 --- a/0027-multipathd-watch-bindings-file-with-inotify-timestam.patch +++ /dev/null @@ -1,597 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 7 Sep 2023 22:22:43 +0200 -Subject: [PATCH] multipathd: watch bindings file with inotify + timestamp - -Since "libmultipath: keep bindings in memory", we don't re-read the -bindings file after every modification. Add a notification mechanism -that makes multipathd aware of changes to the bindings file. Because -multipathd itself will change the bindings file, it must compare -timestamps in order to avoid reading the file repeatedly. - -Because select_alias() can be called from multiple thread contexts (uxlsnr, -uevent handler), we need to add locking for the bindings file. The -timestamp must also be protected by a lock, because it can't be read -or written atomically. - -Note: The notification mechanism expects the bindings file to be -atomically replaced by rename(2). Changes must be made in a temporary file and -applied using rename(2), as in update_bindings_file(). The inotify -mechanism deliberately does not listen to close-after-write events -that would be generated by editing the bindings file directly. This - -Note also: new bindings will only be read from add_map_with_path(), -i.e. either during reconfigure(), or when a new map is created during -runtime. Existing maps will not be renamed if the binding file changes, -unless the user runs "multipathd reconfigure". This is not a change -wrt the previous code, but it should be mentioned anyway. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/alias.c | 256 +++++++++++++++++++++++++----- - libmultipath/alias.h | 3 +- - libmultipath/libmultipath.version | 5 + - multipathd/uxlsnr.c | 36 ++++- - tests/alias.c | 3 + - 5 files changed, 256 insertions(+), 47 deletions(-) - -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index 66e34e31..964b8a7b 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - #include "debug.h" - #include "util.h" -@@ -22,6 +23,7 @@ - #include "config.h" - #include "devmapper.h" - #include "strbuf.h" -+#include "time-util.h" - - /* - * significant parts of this file were taken from iscsi-bindings.c of the -@@ -50,6 +52,12 @@ - "# alias wwid\n" \ - "#\n" - -+/* uatomic access only */ -+static int bindings_file_changed = 1; -+ -+static pthread_mutex_t timestamp_mutex = PTHREAD_MUTEX_INITIALIZER; -+static struct timespec bindings_last_updated; -+ - struct binding { - char *alias; - char *wwid; -@@ -60,6 +68,9 @@ struct binding { - * an abstract type. - */ - typedef struct _vector Bindings; -+ -+/* Protect global_bindings */ -+static pthread_mutex_t bindings_mutex = PTHREAD_MUTEX_INITIALIZER; - static Bindings global_bindings = { .allocated = 0 }; - - enum { -@@ -78,6 +89,27 @@ static void _free_binding(struct binding *bdg) - free(bdg); - } - -+static void free_bindings(Bindings *bindings) -+{ -+ struct binding *bdg; -+ int i; -+ -+ vector_foreach_slot(bindings, bdg, i) -+ _free_binding(bdg); -+ vector_reset(bindings); -+} -+ -+static void set_global_bindings(Bindings *bindings) -+{ -+ Bindings old_bindings; -+ -+ pthread_mutex_lock(&bindings_mutex); -+ old_bindings = global_bindings; -+ global_bindings = *bindings; -+ pthread_mutex_unlock(&bindings_mutex); -+ free_bindings(&old_bindings); -+} -+ - static const struct binding *get_binding_for_alias(const Bindings *bindings, - const char *alias) - { -@@ -199,7 +231,8 @@ static int delete_binding(Bindings *bindings, const char *wwid) - return BINDING_DELETED; - } - --static int write_bindings_file(const Bindings *bindings, int fd) -+static int write_bindings_file(const Bindings *bindings, int fd, -+ struct timespec *ts) - { - struct binding *bnd; - STRBUF_ON_STACK(content); -@@ -227,9 +260,56 @@ static int write_bindings_file(const Bindings *bindings, int fd) - } - len -= n; - } -+ fsync(fd); -+ if (ts) { -+ struct stat st; -+ -+ if (fstat(fd, &st) == 0) -+ *ts = st.st_mtim; -+ else -+ clock_gettime(CLOCK_REALTIME_COARSE, ts); -+ } - return 0; - } - -+void handle_bindings_file_inotify(const struct inotify_event *event) -+{ -+ struct config *conf; -+ const char *base; -+ bool changed = false; -+ struct stat st; -+ struct timespec ts = { 0, 0 }; -+ int ret; -+ -+ if (!(event->mask & IN_MOVED_TO)) -+ return; -+ -+ conf = get_multipath_config(); -+ base = strrchr(conf->bindings_file, '/'); -+ changed = base && base > conf->bindings_file && -+ !strcmp(base + 1, event->name); -+ ret = stat(conf->bindings_file, &st); -+ put_multipath_config(conf); -+ -+ if (!changed) -+ return; -+ -+ pthread_mutex_lock(×tamp_mutex); -+ if (ret == 0) { -+ ts = st.st_mtim; -+ changed = timespeccmp(&ts, &bindings_last_updated) > 0; -+ } -+ pthread_mutex_unlock(×tamp_mutex); -+ -+ if (changed) { -+ uatomic_xchg(&bindings_file_changed, 1); -+ condlog(3, "%s: bindings file must be re-read, new timestamp: %ld.%06ld", -+ __func__, (long)ts.tv_sec, (long)ts.tv_nsec / 1000); -+ } else -+ condlog(3, "%s: bindings file is up-to-date, timestamp: %ld.%06ld", -+ __func__, (long)ts.tv_sec, (long)ts.tv_nsec / 1000); -+} -+ - static int update_bindings_file(const Bindings *bindings, - const char *bindings_file) - { -@@ -237,6 +317,7 @@ static int update_bindings_file(const Bindings *bindings, - int fd = -1; - char tempname[PATH_MAX]; - mode_t old_umask; -+ struct timespec ts; - - if (safe_sprintf(tempname, "%s.XXXXXX", bindings_file)) - return -1; -@@ -248,7 +329,7 @@ static int update_bindings_file(const Bindings *bindings, - } - umask(old_umask); - pthread_cleanup_push(cleanup_fd_ptr, &fd); -- rc = write_bindings_file(bindings, fd); -+ rc = write_bindings_file(bindings, fd, &ts); - pthread_cleanup_pop(1); - if (rc == -1) { - condlog(1, "failed to write new bindings file"); -@@ -257,8 +338,12 @@ static int update_bindings_file(const Bindings *bindings, - } - if ((rc = rename(tempname, bindings_file)) == -1) - condlog(0, "%s: rename: %m", __func__); -- else -+ else { -+ pthread_mutex_lock(×tamp_mutex); -+ bindings_last_updated = ts; -+ pthread_mutex_unlock(×tamp_mutex); - condlog(1, "updated bindings file %s", bindings_file); -+ } - return rc; - } - -@@ -387,6 +472,7 @@ int get_free_id(const Bindings *bindings, const char *prefix, const char *map_ww - return id; - } - -+/* Called with binding_mutex held */ - static char * - allocate_binding(const char *filename, const char *wwid, int id, const char *prefix) - { -@@ -423,6 +509,30 @@ allocate_binding(const char *filename, const char *wwid, int id, const char *pre - return alias; - } - -+enum { -+ BINDINGS_FILE_UP2DATE, -+ BINDINGS_FILE_READ, -+ BINDINGS_FILE_ERROR, -+ BINDINGS_FILE_BAD, -+}; -+ -+static int _read_bindings_file(const struct config *conf, Bindings *bindings, -+ bool force); -+ -+static void read_bindings_file(void) -+{ -+ struct config *conf; -+ Bindings bindings = {.allocated = 0, }; -+ int rc; -+ -+ conf = get_multipath_config(); -+ pthread_cleanup_push(put_multipath_config, conf); -+ rc = _read_bindings_file(conf, &bindings, false); -+ pthread_cleanup_pop(1); -+ if (rc == BINDINGS_FILE_READ) -+ set_global_bindings(&bindings); -+} -+ - /* - * get_user_friendly_alias() action table - * -@@ -463,6 +573,11 @@ char *get_user_friendly_alias(const char *wwid, const char *file, const char *al - bool new_binding = false; - const struct binding *bdg; - -+ read_bindings_file(); -+ -+ pthread_mutex_lock(&bindings_mutex); -+ pthread_cleanup_push(cleanup_mutex, &bindings_mutex); -+ - if (!*alias_old) - goto new_alias; - -@@ -514,40 +629,40 @@ new_alias: - alias, wwid); - - out: -+ /* unlock bindings_mutex */ -+ pthread_cleanup_pop(1); - return alias; - } - - int get_user_friendly_wwid(const char *alias, char *buff) - { - const struct binding *bdg; -+ int rc = -1; - - if (!alias || *alias == '\0') { - condlog(3, "Cannot find binding for empty alias"); - return -1; - } - -+ read_bindings_file(); -+ -+ pthread_mutex_lock(&bindings_mutex); -+ pthread_cleanup_push(cleanup_mutex, &bindings_mutex); - bdg = get_binding_for_alias(&global_bindings, alias); -- if (!bdg) { -+ if (bdg) { -+ strlcpy(buff, bdg->wwid, WWID_SIZE); -+ rc = 0; -+ } else - *buff = '\0'; -- return -1; -- } -- strlcpy(buff, bdg->wwid, WWID_SIZE); -- return 0; --} -- --static void free_bindings(Bindings *bindings) --{ -- struct binding *bdg; -- int i; -- -- vector_foreach_slot(bindings, bdg, i) -- _free_binding(bdg); -- vector_reset(bindings); -+ pthread_cleanup_pop(1); -+ return rc; - } - - void cleanup_bindings(void) - { -+ pthread_mutex_lock(&bindings_mutex); - free_bindings(&global_bindings); -+ pthread_mutex_unlock(&bindings_mutex); - } - - enum { -@@ -595,7 +710,20 @@ static int _check_bindings_file(const struct config *conf, FILE *file, - char *line = NULL; - size_t line_len = 0; - ssize_t n; -- -+ char header[sizeof(BINDINGS_FILE_HEADER)]; -+ -+ header[sizeof(BINDINGS_FILE_HEADER) - 1] = '\0'; -+ if (fread(header, sizeof(BINDINGS_FILE_HEADER) - 1, 1, file) < 1) { -+ condlog(2, "%s: failed to read header from %s", __func__, -+ conf->bindings_file); -+ fseek(file, 0, SEEK_SET); -+ rc = -1; -+ } else if (strcmp(header, BINDINGS_FILE_HEADER)) { -+ condlog(2, "%s: invalid header in %s", __func__, -+ conf->bindings_file); -+ fseek(file, 0, SEEK_SET); -+ rc = -1; -+ } - pthread_cleanup_push(cleanup_free_ptr, &line); - while ((n = getline(&line, &line_len, file)) >= 0) { - char *alias, *wwid; -@@ -643,6 +771,68 @@ static int mp_alias_compar(const void *p1, const void *p2) - &((*(struct mpentry * const *)p2)->alias)); - } - -+static int _read_bindings_file(const struct config *conf, Bindings *bindings, -+ bool force) -+{ -+ int can_write; -+ int rc = 0, ret, fd; -+ FILE *file; -+ struct stat st; -+ int has_changed = uatomic_xchg(&bindings_file_changed, 0); -+ -+ if (!force) { -+ if (!has_changed) { -+ condlog(4, "%s: bindings are unchanged", __func__); -+ return BINDINGS_FILE_UP2DATE; -+ } -+ } -+ -+ fd = open_file(conf->bindings_file, &can_write, BINDINGS_FILE_HEADER); -+ if (fd == -1) -+ return BINDINGS_FILE_ERROR; -+ -+ file = fdopen(fd, "r"); -+ if (file != NULL) { -+ condlog(3, "%s: reading %s", __func__, conf->bindings_file); -+ -+ pthread_cleanup_push(cleanup_fclose, file); -+ ret = _check_bindings_file(conf, file, bindings); -+ if (ret == 0) { -+ struct timespec ts; -+ -+ rc = BINDINGS_FILE_READ; -+ ret = fstat(fd, &st); -+ if (ret == 0) -+ ts = st.st_mtim; -+ else { -+ condlog(1, "%s: fstat failed (%m), using current time", __func__); -+ clock_gettime(CLOCK_REALTIME_COARSE, &ts); -+ } -+ pthread_mutex_lock(×tamp_mutex); -+ bindings_last_updated = ts; -+ pthread_mutex_unlock(×tamp_mutex); -+ } else if (ret == -1 && can_write && !conf->bindings_read_only) { -+ ret = update_bindings_file(bindings, conf->bindings_file); -+ if (ret == 0) -+ rc = BINDINGS_FILE_READ; -+ else -+ rc = BINDINGS_FILE_BAD; -+ } else { -+ condlog(0, "ERROR: bad settings in read-only bindings file %s", -+ conf->bindings_file); -+ rc = BINDINGS_FILE_BAD; -+ } -+ pthread_cleanup_pop(1); -+ } else { -+ condlog(1, "failed to fdopen %s: %m", -+ conf->bindings_file); -+ close(fd); -+ rc = BINDINGS_FILE_ERROR; -+ } -+ -+ return rc; -+} -+ - /* - * check_alias_settings(): test for inconsistent alias configuration - * -@@ -661,8 +851,7 @@ static int mp_alias_compar(const void *p1, const void *p2) - */ - int check_alias_settings(const struct config *conf) - { -- int can_write; -- int rc = 0, i, fd; -+ int i, rc; - Bindings bindings = {.allocated = 0, }; - vector mptable = NULL; - struct mpentry *mpe; -@@ -695,27 +884,12 @@ int check_alias_settings(const struct config *conf) - pthread_cleanup_pop(1); - pthread_cleanup_pop(1); - -- fd = open_file(conf->bindings_file, &can_write, BINDINGS_FILE_HEADER); -- if (fd != -1) { -- FILE *file = fdopen(fd, "r"); -- -- if (file != NULL) { -- pthread_cleanup_push(cleanup_fclose, file); -- rc = _check_bindings_file(conf, file, &bindings); -- pthread_cleanup_pop(1); -- if (rc == -1 && can_write && !conf->bindings_read_only) -- rc = update_bindings_file(&bindings, conf->bindings_file); -- else if (rc == -1) -- condlog(0, "ERROR: bad settings in read-only bindings file %s", -- conf->bindings_file); -- } else { -- condlog(1, "failed to fdopen %s: %m", -- conf->bindings_file); -- close(fd); -- } -+ rc = _read_bindings_file(conf, &bindings, true); -+ -+ if (rc == BINDINGS_FILE_READ) { -+ set_global_bindings(&bindings); -+ rc = 0; - } - -- cleanup_bindings(); -- global_bindings = bindings; - return rc; - } -diff --git a/libmultipath/alias.h b/libmultipath/alias.h -index 5ef6720b..ca8911f4 100644 ---- a/libmultipath/alias.h -+++ b/libmultipath/alias.h -@@ -10,5 +10,6 @@ char *get_user_friendly_alias(const char *wwid, const char *file, - struct config; - int check_alias_settings(const struct config *); - void cleanup_bindings(void); -- -+struct inotify_event; -+void handle_bindings_file_inotify(const struct inotify_event *event); - #endif /* _ALIAS_H */ -diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version -index ddd302f5..57e50c12 100644 ---- a/libmultipath/libmultipath.version -+++ b/libmultipath/libmultipath.version -@@ -238,3 +238,8 @@ global: - local: - *; - }; -+ -+LIBMULTIPATH_20.1.0 { -+global: -+ handle_bindings_file_inotify; -+}; -diff --git a/multipathd/uxlsnr.c b/multipathd/uxlsnr.c -index 02e89fb4..d1f8f234 100644 ---- a/multipathd/uxlsnr.c -+++ b/multipathd/uxlsnr.c -@@ -41,6 +41,7 @@ - #include "cli.h" - #include "uxlsnr.h" - #include "strbuf.h" -+#include "alias.h" - - /* state of client connection */ - enum { -@@ -190,6 +191,7 @@ void wakeup_cleanup(void *arg) - struct watch_descriptors { - int conf_wd; - int dir_wd; -+ int mp_wd; /* /etc/multipath; for bindings file */ - }; - - /* failing to set the watch descriptor is o.k. we just miss a warning -@@ -200,6 +202,8 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds, - struct config *conf; - int dir_reset = 0; - int conf_reset = 0; -+ int mp_reset = 0; -+ char *bindings_file __attribute__((cleanup(cleanup_charp))) = NULL; - - if (notify_fd == -1) - return; -@@ -214,7 +218,10 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds, - conf_reset = 1; - if (wds->dir_wd == -1) - dir_reset = 1; -+ if (wds->mp_wd == -1) -+ mp_reset = 1; - } -+ bindings_file = strdup(conf->bindings_file); - put_multipath_config(conf); - - if (dir_reset) { -@@ -235,7 +242,18 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds, - if (wds->conf_wd == -1) - condlog(3, "didn't set up notifications on /etc/multipath.conf: %m"); - } -- return; -+ if (mp_reset && bindings_file) { -+ char *slash = strrchr(bindings_file, '/'); -+ -+ if (slash && slash > bindings_file) { -+ *slash = '\0'; -+ wds->mp_wd = inotify_add_watch(notify_fd, bindings_file, -+ IN_MOVED_TO|IN_ONLYDIR); -+ if (wds->mp_wd == -1) -+ condlog(3, "didn't set up notifications on %s: %m", -+ bindings_file); -+ } -+ } - } - - static void handle_inotify(int fd, struct watch_descriptors *wds) -@@ -256,12 +274,13 @@ static void handle_inotify(int fd, struct watch_descriptors *wds) - inotify_rm_watch(fd, wds->conf_wd); - if (wds->dir_wd != -1) - inotify_rm_watch(fd, wds->dir_wd); -- wds->conf_wd = wds->dir_wd = -1; -+ if (wds->mp_wd != -1) -+ inotify_rm_watch(fd, wds->mp_wd); -+ wds->conf_wd = wds->dir_wd = wds->mp_wd = -1; - } - break; - } - -- got_notify = 1; - for (ptr = buff; ptr < buff + len; - ptr += sizeof(struct inotify_event) + event->len) { - event = (const struct inotify_event *) ptr; -@@ -273,7 +292,13 @@ static void handle_inotify(int fd, struct watch_descriptors *wds) - wds->conf_wd = inotify_add_watch(notify_fd, DEFAULT_CONFIGFILE, IN_CLOSE_WRITE); - else if (wds->dir_wd == event->wd) - wds->dir_wd = -1; -+ else if (wds->mp_wd == event->wd) -+ wds->mp_wd = -1; - } -+ if (wds->mp_wd != -1 && wds->mp_wd == event->wd) -+ handle_bindings_file_inotify(event); -+ else -+ got_notify = 1; - } - } - if (got_notify) -@@ -599,7 +624,7 @@ void *uxsock_listen(long ux_sock, void *trigger_data) - int max_pfds = MIN_POLLS + POLLFDS_BASE; - /* conf->sequence_nr will be 1 when uxsock_listen is first called */ - unsigned int sequence_nr = 0; -- struct watch_descriptors wds = { .conf_wd = -1, .dir_wd = -1 }; -+ struct watch_descriptors wds = { .conf_wd = -1, .dir_wd = -1, .mp_wd = -1, }; - struct vectors *vecs = trigger_data; - - condlog(3, "uxsock: startup listener"); -@@ -666,7 +691,8 @@ void *uxsock_listen(long ux_sock, void *trigger_data) - - reset_watch(notify_fd, &wds, &sequence_nr); - polls[POLLFD_NOTIFY].fd = notify_fd; -- if (notify_fd == -1 || (wds.conf_wd == -1 && wds.dir_wd == -1)) -+ if (notify_fd == -1 || (wds.conf_wd == -1 && wds.dir_wd == -1 -+ && wds.mp_wd == -1)) - polls[POLLFD_NOTIFY].events = 0; - else - polls[POLLFD_NOTIFY].events = POLLIN; -diff --git a/tests/alias.c b/tests/alias.c -index 7f3ff38a..9ae27567 100644 ---- a/tests/alias.c -+++ b/tests/alias.c -@@ -1954,6 +1954,9 @@ int main(void) - int ret = 0; - init_test_verbosity(3); - -+ /* avoid open_file() call in _read_bindings_file */ -+ bindings_file_changed = 0; -+ - ret += test_format_devname(); - ret += test_scan_devname(); - ret += test_lookup_binding(); diff --git a/0028-multipath-tools-tests-mock-pthread_mutex_-lock-unloc.patch b/0028-multipath-tools-tests-mock-pthread_mutex_-lock-unloc.patch deleted file mode 100644 index bba92f3..0000000 --- a/0028-multipath-tools-tests-mock-pthread_mutex_-lock-unloc.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 8 Sep 2023 19:54:07 +0200 -Subject: [PATCH] multipath-tools tests: mock pthread_mutex_{lock,unlock} - -If some test fails with a lock held, cmocka doesn't deal well with -pthread_cleanup_pop(). Such tests can cause deadlock with the locking -primitives in the alias code, because locks don't get properly unlocked. Just -mock the lock/unlock functions and generate an error if they weren't paired at -the end of the test. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - tests/Makefile | 1 + - tests/alias.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 47 insertions(+) - -diff --git a/tests/Makefile b/tests/Makefile -index c777d07a..7dac8a8f 100644 ---- a/tests/Makefile -+++ b/tests/Makefile -@@ -52,6 +52,7 @@ blacklist-test_LIBDEPS := -ludev - vpd-test_OBJDEPS := $(multipathdir)/discovery.o - vpd-test_LIBDEPS := -ludev -lpthread -ldl - alias-test_TESTDEPS := test-log.o -+alias-test_OBJDEPS := $(mpathutildir)/util.o - alias-test_LIBDEPS := -lpthread -ldl - valid-test_OBJDEPS := $(multipathdir)/valid.o $(multipathdir)/discovery.o - valid-test_LIBDEPS := -lmount -ludev -lpthread -ldl -diff --git a/tests/alias.c b/tests/alias.c -index 9ae27567..94df36d8 100644 ---- a/tests/alias.c -+++ b/tests/alias.c -@@ -89,6 +89,47 @@ int __wrap_dm_get_uuid(const char *name, char *uuid, int uuid_len) - return ret; - } - -+static int lock_errors; -+static int bindings_locked; -+static int timestamp_locked; -+int __wrap_pthread_mutex_lock(pthread_mutex_t *mutex) -+{ -+ if (mutex == &bindings_mutex) { -+ if (bindings_locked) { -+ fprintf(stderr, "%s: bindings_mutex LOCKED\n", __func__); -+ lock_errors++; -+ } -+ bindings_locked = 1; -+ } else if (mutex == ×tamp_mutex) { -+ if (timestamp_locked) { -+ fprintf(stderr, "%s: timestamp_mutex LOCKED\n", __func__); -+ lock_errors++; -+ } -+ timestamp_locked = 1; -+ } else -+ fprintf(stderr, "%s called for unknown mutex %p\n", __func__, mutex); -+ return 0; -+} -+ -+int __wrap_pthread_mutex_unlock(pthread_mutex_t *mutex) -+{ -+ if (mutex == &bindings_mutex) { -+ if (!bindings_locked) { -+ fprintf(stderr, "%s: bindings_mutex UNLOCKED\n", __func__); -+ lock_errors++; -+ } -+ bindings_locked = 0; -+ } else if (mutex == ×tamp_mutex) { -+ if (!timestamp_locked) { -+ fprintf(stderr, "%s: timestamp_mutex UNLOCKED\n", __func__); -+ lock_errors++; -+ } -+ timestamp_locked = 0; -+ } else -+ fprintf(stderr, "%s called for unknown mutex %p\n", __func__, mutex); -+ return 0; -+} -+ - #define TEST_FDNO 1234 - #define TEST_FPTR ((FILE *) 0xaffe) - -@@ -1718,6 +1759,10 @@ static void gufa_old_nomatch_nowwidmatch(void **state) { - free(alias); - } - -+static void gufa_check_locking(void **state) { -+ assert_int_equal(lock_errors, 0); -+} -+ - static int test_get_user_friendly_alias() - { - const struct CMUnitTest tests[] = { -@@ -1743,6 +1788,7 @@ static int test_get_user_friendly_alias() - cmocka_unit_test_teardown(gufa_old_nomatch_wwidmatch, teardown_bindings), - cmocka_unit_test_teardown(gufa_old_nomatch_wwidmatch_used, teardown_bindings), - cmocka_unit_test_teardown(gufa_old_nomatch_nowwidmatch, teardown_bindings), -+ cmocka_unit_test(gufa_check_locking), - }; - - return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/0029-multipath-tools-Makefile-sanitize-paths-for-configur.patch b/0029-multipath-tools-Makefile-sanitize-paths-for-configur.patch deleted file mode 100644 index 26b79a8..0000000 --- a/0029-multipath-tools-Makefile-sanitize-paths-for-configur.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 8 Sep 2023 22:13:51 +0200 -Subject: [PATCH] multipath-tools Makefile: sanitize paths for configuration - files - -Make the path to multipath.conf configurable, and use the same prefix -by default for multipath.conf and multipath/conf.d. For "usr-merged" -distributions with immutable /usr, we'll want to have the configuration -under a different prefix. This can be achieved by using e.g. - - make prefix=/usr etc_prefix="" - -Note that with prefix=/usr, before this patch the code would use -/usr/etc/multipath/conf.d, but /etc/multipath.conf. If this (rather -inconsistent) behavior is desired, use the following command line: - - make prefix=/usr configfile=/etc/multipath.conf - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - Makefile.inc | 9 ++++++--- - libmultipath/defaults.h | 1 - - 2 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/Makefile.inc b/Makefile.inc -index 502cd0f1..39972d93 100644 ---- a/Makefile.inc -+++ b/Makefile.inc -@@ -37,6 +37,8 @@ prefix := - exec_prefix := $(prefix) - # Prefix for non-essential libraries (libdmmp) - usr_prefix := $(prefix) -+# Prefix for configfuration files (multipath.conf) -+etc_prefix := $(prefix) - # Where to install systemd-related files. systemd is usually installed under /usr - # Note: some systemd installations use separate "prefix" and "rootprefix". - # In this case, override only unitdir to use systemd's "rootprefix" instead of $(systemd_prefix) -@@ -54,7 +56,8 @@ usrlibdir := $(usr_prefix)/$(LIB) - includedir := $(usr_prefix)/include - pkgconfdir := $(usrlibdir)/pkgconfig - plugindir := $(prefix)/$(LIB)/multipath --configdir := $(prefix)/etc/multipath/conf.d -+configdir := $(etc_prefix)/etc/multipath/conf.d -+configfile := $(etc_prefix)/etc/multipath.conf - runtimedir := $(if $(shell test -L /var/run -o ! -d /var/run && echo 1),/run,/var/run) - devmapper_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir devmapper),/usr/include) - libudev_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir libudev),/usr/include) -@@ -84,8 +87,8 @@ WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implici - $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) - CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) \ - -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \ -- -DRUNTIME_DIR=\"$(runtimedir)\" \ -- -DCONFIG_DIR=\"$(configdir)\" -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP -+ -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \ -+ -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP - CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe - BIN_CFLAGS := -fPIE -DPIE - LIB_CFLAGS := -fPIC -diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h -index b3f11d4c..bc2d6388 100644 ---- a/libmultipath/defaults.h -+++ b/libmultipath/defaults.h -@@ -66,7 +66,6 @@ - #define MAX_DEV_LOSS_TMO UINT_MAX - #define DEFAULT_PIDFILE RUNTIME_DIR "/multipathd.pid" - #define DEFAULT_SOCKET "/org/kernel/linux/storage/multipathd" --#define DEFAULT_CONFIGFILE "/etc/multipath.conf" - #define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings" - #define DEFAULT_WWIDS_FILE "/etc/multipath/wwids" - #define DEFAULT_PRKEYS_FILE "/etc/multipath/prkeys" diff --git a/0030-multipath-tools-add-compile-time-configuration-for-e.patch b/0030-multipath-tools-add-compile-time-configuration-for-e.patch deleted file mode 100644 index afdf833..0000000 --- a/0030-multipath-tools-add-compile-time-configuration-for-e.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 8 Sep 2023 22:26:22 +0200 -Subject: [PATCH] multipath-tools: add compile time configuration for - "/etc/multipath" - -Instead of hard-conding "/etc/multipath" as the path for the state -files "bindings", "prkeys", and "wwids", make this path configurable -via the "statedir" compile-time option. The default is currently still -/etc, it might change to /var/lib or similar in the future. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - Makefile.inc | 4 +++- - libmultipath/defaults.h | 6 +++--- - 2 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/Makefile.inc b/Makefile.inc -index 39972d93..96206b2f 100644 ---- a/Makefile.inc -+++ b/Makefile.inc -@@ -58,6 +58,7 @@ pkgconfdir := $(usrlibdir)/pkgconfig - plugindir := $(prefix)/$(LIB)/multipath - configdir := $(etc_prefix)/etc/multipath/conf.d - configfile := $(etc_prefix)/etc/multipath.conf -+statedir := $(etc_prefix)/etc/multipath - runtimedir := $(if $(shell test -L /var/run -o ! -d /var/run && echo 1),/run,/var/run) - devmapper_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir devmapper),/usr/include) - libudev_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir libudev),/usr/include) -@@ -88,7 +89,8 @@ WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implici - CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) \ - -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \ - -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \ -- -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP -+ -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DSTATE_DIR=\"$(statedir)\" \ -+ -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP - CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe - BIN_CFLAGS := -fPIE -DPIE - LIB_CFLAGS := -fPIC -diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h -index bc2d6388..d01f9712 100644 ---- a/libmultipath/defaults.h -+++ b/libmultipath/defaults.h -@@ -66,9 +66,9 @@ - #define MAX_DEV_LOSS_TMO UINT_MAX - #define DEFAULT_PIDFILE RUNTIME_DIR "/multipathd.pid" - #define DEFAULT_SOCKET "/org/kernel/linux/storage/multipathd" --#define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings" --#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids" --#define DEFAULT_PRKEYS_FILE "/etc/multipath/prkeys" -+#define DEFAULT_BINDINGS_FILE STATE_DIR "/bindings" -+#define DEFAULT_WWIDS_FILE STATE_DIR "/wwids" -+#define DEFAULT_PRKEYS_FILE STATE_DIR "/prkeys" - #define MULTIPATH_SHM_BASE RUNTIME_DIR "/multipath/" - - diff --git a/0031-multipath-tools-man-pages-generate-with-correct-path.patch b/0031-multipath-tools-man-pages-generate-with-correct-path.patch deleted file mode 100644 index 65fc077..0000000 --- a/0031-multipath-tools-man-pages-generate-with-correct-path.patch +++ /dev/null @@ -1,366 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 8 Sep 2023 22:48:16 +0200 -Subject: [PATCH] multipath-tools man pages: generate with correct paths - -Generate the man pages using the compile-time settings for paths -to multipath.conf etc. - -Add a paragraph about the CONFIGDIR (/etc/multipath/conf.d) -and the drop-in configuration files in the multipath.conf man page. - -Also, make sure all generated man pages and other files are correctly -removed by "make clean". - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - .gitignore | 4 +++ - Makefile.inc | 3 +++ - mpathpersist/Makefile | 5 ++-- - .../{mpathpersist.8 => mpathpersist.8.in} | 2 +- - multipath/Makefile | 13 +++++---- - multipath/{multipath.8 => multipath.8.in} | 10 +++---- - .../{multipath.conf.5 => multipath.conf.5.in} | 27 ++++++++++++------- - multipathd/Makefile | 9 ++++--- - multipathd/{multipathd.8 => multipathd.8.in} | 8 +++--- - 9 files changed, 49 insertions(+), 32 deletions(-) - rename mpathpersist/{mpathpersist.8 => mpathpersist.8.in} (99%) - rename multipath/{multipath.8 => multipath.8.in} (97%) - rename multipath/{multipath.conf.5 => multipath.conf.5.in} (98%) - rename multipathd/{multipathd.8 => multipathd.8.in} (97%) - -diff --git a/.gitignore b/.gitignore -index 535353e5..2986578f 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -13,11 +13,15 @@ cscope.files - cscope.out - kpartx/kpartx - multipath/multipath -+multipath/multipath.8 -+multipath/multipath.conf.5 - multipath/multipath.rules - multipath/tmpfiles.conf - multipathd/multipathd -+multipathd/multipathd.8 - multipathd/multipathc - mpathpersist/mpathpersist -+mpathpersist/mpathpersist.8 - abi.tar.gz - abi - abi-test -diff --git a/Makefile.inc b/Makefile.inc -index 96206b2f..79e521e1 100644 ---- a/Makefile.inc -+++ b/Makefile.inc -@@ -133,3 +133,6 @@ NV_VERSION_SCRIPT = $(DEVLIB:%.so=%-nv.version) - @grep -P '^[ \t]+[a-zA-Z_][a-zA-Z0-9_]*;' $< >>$@ - @printf 'local:\n\t*;\n};\n' >>$@ - -+%: %.in -+ @echo creating $@ -+ $(Q)sed 's:@CONFIGFILE@:'$(configfile)':g;s:@CONFIGDIR@:'$(configdir)':g;s:@STATE_DIR@:'$(statedir)':g;s:@RUNTIME_DIR@:'$(runtimedir)':g' $< >$@ -diff --git a/mpathpersist/Makefile b/mpathpersist/Makefile -index f57c105c..f3749467 100644 ---- a/mpathpersist/Makefile -+++ b/mpathpersist/Makefile -@@ -8,10 +8,11 @@ LIBDEPS += -L$(mpathpersistdir) -lmpathpersist -L$(multipathdir) -lmultipath \ - -L$(mpathutildir) -lmpathutil -L$(mpathcmddir) -lmpathcmd -lpthread -ldevmapper -ludev - - EXEC = mpathpersist -+MANPAGES := mpathpersist.8 - - OBJS = main.o - --all: $(EXEC) -+all: $(EXEC) $(MANPAGES) - - $(EXEC): $(OBJS) - $(Q)$(CC) $(OBJS) -o $(EXEC) $(LDFLAGS) $(CFLAGS) $(LIBDEPS) -@@ -23,7 +24,7 @@ install: - $(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)/man8 - - clean: dep_clean -- $(Q)$(RM) core *.o $(EXEC) -+ $(Q)$(RM) core *.o $(EXEC) $(MANPAGES) - - include $(wildcard $(OBJS:.o=.d)) - -diff --git a/mpathpersist/mpathpersist.8 b/mpathpersist/mpathpersist.8.in -similarity index 99% -rename from mpathpersist/mpathpersist.8 -rename to mpathpersist/mpathpersist.8.in -index 8d26b37c..fecef0d6 100644 ---- a/mpathpersist/mpathpersist.8 -+++ b/mpathpersist/mpathpersist.8.in -@@ -31,7 +31,7 @@ mpathpersist \- Manages SCSI persistent reservations on dm multipath devices. - . - This utility is used to manage SCSI persistent reservations on Device Mapper - Multipath devices. To be able to use this functionality, the \fIreservation_key\fR --attribute must be defined in the \fI/etc/multipath.conf\fR file. Otherwise the -+attribute must be defined in the \fI@CONFIGFILE@\fR file. Otherwise the - \fBmultipathd\fR daemon will not check for persistent reservation for newly - discovered paths or reinstated paths. - . -diff --git a/multipath/Makefile b/multipath/Makefile -index 73db991a..68cb5ce7 100644 ---- a/multipath/Makefile -+++ b/multipath/Makefile -@@ -3,7 +3,9 @@ - # - include ../Makefile.inc - --EXEC := multipath -+EXEC := multipath -+MANPAGES := multipath.8 multipath.conf.5 -+GENERATED := $(MANPAGES) multipath.rules tmpfiles.conf - - CPPFLAGS += -I$(multipathdir) -I$(mpathutildir) -I$(mpathcmddir) - CFLAGS += $(BIN_CFLAGS) -@@ -13,7 +15,7 @@ LIBDEPS += -L$(multipathdir) -lmultipath -L$(mpathutildir) -lmpathutil \ - - OBJS := main.o - --all: $(EXEC) multipath.rules tmpfiles.conf -+all: $(EXEC) $(GENERATED) - - $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so - @echo building $@ because of $? -@@ -47,15 +49,12 @@ uninstall: - $(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules - $(Q)$(RM) $(DESTDIR)$(mandir)/man8/$(EXEC).8 - $(Q)$(RM) $(DESTDIR)$(mandir)/man5/$(EXEC).conf.5 -+ $(Q)$(RM) $(DESTDIR)$(tmpfilesdir)/multipath.conf - - clean: dep_clean -- $(Q)$(RM) core *.o $(EXEC) multipath.rules tmpfiles.conf -+ $(Q)$(RM) core *.o $(EXEC) $(GENERATED) - - include $(wildcard $(OBJS:.o=.d)) - - dep_clean: - $(Q)$(RM) $(OBJS:.o=.d) -- --%: %.in -- @echo creating $@ -- $(Q)sed 's,@RUNTIME_DIR@,$(runtimedir),' $< >$@ -diff --git a/multipath/multipath.8 b/multipath/multipath.8.in -similarity index 97% -rename from multipath/multipath.8 -rename to multipath/multipath.8.in -index 5fed6df7..348eb220 100644 ---- a/multipath/multipath.8 -+++ b/multipath/multipath.8.in -@@ -185,7 +185,7 @@ Display the currently used multipathd configuration. - .B \-T - Display the currently used multipathd configuration, limiting the output to - those devices actually present in the system. This can be used a template for --creating \fImultipath.conf\fR. -+creating \fI@CONFIGFILE@\fR. - . - .\" ---------------------------------------------------------------------------- - .SH OPTIONS -@@ -233,11 +233,11 @@ option from \fBmultipath.conf(5)\fR. - .B \-i - Ignore WWIDs file when processing devices. If - \fIfind_multipaths strict\fR or \fIfind_multipaths no\fR is set in --\fImultipath.conf\fR, multipath only considers devices that are -+\fI@CONFIGFILE@\fR, multipath only considers devices that are - listed in the WWIDs file. This option overrides that behavior. For other values - of \fIfind_multipaths\fR, this option has no effect. See the description of - \fIfind_multipaths\fR in --.BR multipath.conf (5). -+.BR @CONFIGFILE@ (5). - This option should only be used in rare circumstances. - . - .TP -@@ -246,8 +246,8 @@ Treat the bindings file as read only. - . - .TP - .BI \-b " file" --Set \fIuser_friendly_names\fR bindings file location. The default is --\fI/etc/multipath/bindings\fR. -+(\fBdeprecated, do not use\fR) Set \fIuser_friendly_names\fR bindings file location. The default is -+\fI@STATE_DIR@/bindings\fR. - . - .TP - .B \-q -diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5.in -similarity index 98% -rename from multipath/multipath.conf.5 -rename to multipath/multipath.conf.5.in -index 93af17db..20df2232 100644 ---- a/multipath/multipath.conf.5 -+++ b/multipath/multipath.conf.5.in -@@ -13,14 +13,14 @@ - .SH NAME - .\" ---------------------------------------------------------------------------- - . --multipath.conf \- multipath daemon configuration file. -+@CONFIGFILE@, @CONFIGDIR@/*.conf \- multipath daemon configuration file. - . - . - .\" ---------------------------------------------------------------------------- - .SH DESCRIPTION - .\" ---------------------------------------------------------------------------- - . --.B "/etc/multipath.conf" -+.B "@CONFIGFILE@" - is the configuration file for the multipath daemon. It is used to - overwrite the built-in configuration table of \fBmultipathd\fP. - Any line whose first non-white-space character is a '#' is considered -@@ -29,6 +29,15 @@ a comment line. Empty lines are ignored. - Currently used multipathd configuration can be displayed with the \fBmultipath -t\fR - or \fBmultipathd show config\fR command. - . -+.PP -+Additional configuration can be made in drop-in files under -+.B @CONFIGDIR@. -+Files ending in \fI.conf\fR in this directory are read -+in alphabetical order, after reading \fI@CONFIGFILE@\fR. -+They use the same syntax as \fI@CONFIGFILE@\fR itself, -+and support all sections and keywords. If a keyword occurs in the same section -+in multiple files, the last occurence will take precedence over all others. -+. - . - .\" ---------------------------------------------------------------------------- - .SH SYNTAX -@@ -85,7 +94,7 @@ not mandatory. - . - .LP - .B Note on regular expressions: --The \fImultipath.conf\fR syntax allows many attribute values to be specified as POSIX -+The \fI@CONFIGFILE@\fR syntax allows many attribute values to be specified as POSIX - Extended Regular Expressions (see \fBregex\fR(7)). These regular expressions - are \fBcase sensitive\fR and \fBnot anchored\fR, thus the expression "bar" matches "barbie", - "rhabarber", and "wunderbar", but not "Barbie". To avoid unwanted substring -@@ -711,7 +720,7 @@ The default is: \fBno\fR - .B user_friendly_names - If set to - .I yes --, using the bindings file \fI/etc/multipath/bindings\fR to assign a persistent -+, using the bindings file \fI@STATE_DIR@/bindings\fR to assign a persistent - and unique alias to the multipath, in the form of mpath. If set to - .I no - use the WWID as the alias. In either case this be will -@@ -790,7 +799,7 @@ The full pathname of the binding file to be used when the user_friendly_names - option is set. - .RS - .TP --The default is: \fB/etc/multipath/bindings\fR -+The default is: \fB@STATE_DIR@/bindings\fR - .RE - . - . -@@ -801,7 +810,7 @@ The full pathname of the WWIDs file, which is used by multipath to keep track - of the WWIDs for LUNs it has created multipath devices on in the past. - .RS - .TP --The default is: \fB/etc/multipath/wwids\fR -+The default is: \fB@STATE_DIR@/wwids\fR - .RE - . - . -@@ -813,7 +822,7 @@ track of the persistent reservation key used for a specific WWID, when - \fIreservation_key\fR is set to \fBfile\fR. - .RS - .TP --The default is: \fB/etc/multipath/prkeys\fR -+The default is: \fB@STATE_DIR@/prkeys\fR - .RE - . - . -@@ -872,7 +881,7 @@ The default is: \fBno\fR - .I yes - and the SCSI layer has already attached a hardware_handler to the device, - multipath will not force the device to use the hardware_handler specified by --multipath.conf. If the SCSI layer has not attached a hardware handler, -+@CONFIGFILE@. If the SCSI layer has not attached a hardware handler, - multipath will continue to use its configured hardware handler. - .RS - .PP -@@ -1559,7 +1568,7 @@ given device, the attributes of all matching entries are applied to it. - If an attribute is specified in several matching device subsections, - later entries take precedence. Thus, entries in files under \fIconfig_dir\fR (in - reverse alphabetical order) have the highest precedence, followed by entries --in \fImultipath.conf\fR; the built-in hardware table has the lowest -+in \fI@CONFIGFILE@\fR; the built-in hardware table has the lowest - precedence. Inside a configuration file, later entries have higher precedence - than earlier ones. - .LP -diff --git a/multipathd/Makefile b/multipathd/Makefile -index 0d0146c5..cdba3db1 100644 ---- a/multipathd/Makefile -+++ b/multipathd/Makefile -@@ -1,7 +1,8 @@ - include ../Makefile.inc - --EXEC := multipathd --CLI := multipathc -+EXEC := multipathd -+CLI := multipathc -+MANPAGES := multipathd.8 - - CPPFLAGS += -I$(multipathdir) -I$(mpathutildir) -I$(mpathpersistdir) -I$(mpathcmddir) -I$(thirdpartydir) \ - $(shell $(PKG_CONFIG) --modversion liburcu 2>/dev/null | \ -@@ -42,7 +43,7 @@ ifeq ($(FPIN_SUPPORT),1) - OBJS += fpin_handlers.o - endif - --all : $(EXEC) $(CLI) -+all : $(EXEC) $(CLI) $(MANPAGES) - - $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so - @echo building $@ because of $? -@@ -79,7 +80,7 @@ uninstall: - $(Q)$(RM) $(DESTDIR)$(unitdir)/$(EXEC).socket - - clean: dep_clean -- $(Q)$(RM) core *.o $(EXEC) $(CLI) -+ $(Q)$(RM) core *.o $(EXEC) $(CLI) $(MANPAGES) - - include $(wildcard $(OBJS:.o=.d) $(CLI_OBJS:.o=.d)) - -diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8.in -similarity index 97% -rename from multipathd/multipathd.8 -rename to multipathd/multipathd.8.in -index cc72b775..e98c27fd 100644 ---- a/multipathd/multipathd.8 -+++ b/multipathd/multipathd.8.in -@@ -155,7 +155,7 @@ Show the format wildcards used in interactive commands taking $format. - .TP - .B list|show config - Show the currently used configuration, derived from default values and values --specified within the configuration file \fI/etc/multipath.conf\fR. -+specified within the configuration file \fI@CONFIGFILE@\fR. - . - .TP - .B list|show config local -@@ -165,7 +165,7 @@ the devices section to those devices that are actually present in the system. - .TP - .B list|show blacklist - Show the currently used blacklist rules, derived from default values and values --specified within the configuration file \fI/etc/multipath.conf\fR. -+specified within the configuration file \fI@CONFIGFILE@\fR. - . - .TP - .B list|show devices -@@ -290,13 +290,13 @@ Get the current persistent reservation key associated with $map. - .B map|multipath $map setprkey key $key - Set the persistent reservation key associated with $map to $key in the - \fIprkeys_file\fR. This key will only be used by multipathd if --\fIreservation_key\fR is set to \fBfile\fR in \fI/etc/multipath.conf\fR. -+\fIreservation_key\fR is set to \fBfile\fR in \fI@CONFIGFILE@\fR. - . - .TP - .B map|multipath $map unsetprkey - Remove the persistent reservation key associated with $map from the - \fIprkeys_file\fR. This will only unset the key used by multipathd if --\fIreservation_key\fR is set to \fBfile\fR in \fI/etc/multipath.conf\fR. -+\fIreservation_key\fR is set to \fBfile\fR in \fI@CONFIGFILE@\fR. - . - .TP - .B path $path setmarginal diff --git a/0032-libdmmp-Makefile-fix-bug-in-install-section.patch b/0032-libdmmp-Makefile-fix-bug-in-install-section.patch deleted file mode 100644 index a3f2470..0000000 --- a/0032-libdmmp-Makefile-fix-bug-in-install-section.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Mon, 11 Sep 2023 09:30:13 +0200 -Subject: [PATCH] libdmmp/Makefile: fix bug in install section - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libdmmp/Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/libdmmp/Makefile b/libdmmp/Makefile -index 078eca8f..172ba045 100644 ---- a/libdmmp/Makefile -+++ b/libdmmp/Makefile -@@ -44,7 +44,7 @@ install: - $(DESTDIR)$(pkgconfdir)/$(PKGFILE) - $(Q)sed -i 's|__INCLUDEDIR__|$(includedir)|g' \ - $(DESTDIR)$(pkgconfdir)/$(PKGFILE) -- $(Q)$(INSTALL_PROGRAM) -d 755 $(DESTDIR)$(mandir)/man3 -+ $(Q)$(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(mandir)/man3 - $(Q)$(INSTALL_PROGRAM) -m 644 -t $(DESTDIR)$(mandir)/man3 docs/man/*.3 - - uninstall: diff --git a/0033-multipath-tools-README.md-improve-documentation-for-.patch b/0033-multipath-tools-README.md-improve-documentation-for-.patch deleted file mode 100644 index 3c7edd0..0000000 --- a/0033-multipath-tools-README.md-improve-documentation-for-.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Mon, 11 Sep 2023 10:22:13 +0200 -Subject: [PATCH] multipath-tools: README.md: improve documentation for - compile-time options - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - README.md | 38 ++++++++++++++++++++++++++------------ - 1 file changed, 26 insertions(+), 12 deletions(-) - -diff --git a/README.md b/README.md -index a7f994ae..679e55bf 100644 ---- a/README.md -+++ b/README.md -@@ -89,9 +89,17 @@ The following variables can be passed to the `make` command line: - * `plugindir="/some/path"`: directory where libmultipath plugins (path - checkers, prioritizers, and foreign multipath support) will be looked up. - This used to be the run-time option `multipath_dir` in earlier versions. -- * `configdir="/some/path"` : directory to search for configuration files. -+ The default is `$(prefix)/$(LIB)/multipath`, where `$(LIB)` is `lib64` on -+ systems that have `/lib64`, and `lib` otherwise. -+ * `configfile="/some/path`": The path to the main configuration file. -+ The defalt is `$(etc_prefix)/etc/multipath.conf`. -+ * `configdir="/some/path"` : directory to search for additional configuration files. - This used to be the run-time option `config_dir` in earlier versions. -- The default is `/etc/multipath/conf.d`. -+ The default is `$(etc_prefix)/etc/multipath/conf.d`. -+ * `statedir="/some/path"`: The path of the directory where multipath-tools -+ stores run-time settings that need persist between reboots, such as known -+ WWIDs, user-friendly names, and persistent reservation keys. -+ The default is `$(etc_prefix)/etc/multipath`. - * `READLINE=libedit` or `READLINE=libreadline`: enable command line history - and TAB completion in the interactive mode *(which is entered with `multipathd -k` or `multipathc`)*. - The respective development package will be required for building. -@@ -119,21 +127,27 @@ The following variables can be passed to the `make` command line: - ### Installation Paths - - * `prefix`: The directory prefix for (almost) all files to be installed. -- Distributions may want to set this to `/usr`. -- **Note**: for multipath-tools, unlike many other packages, `prefix` -- defaults to the empty string, which resolves to the root directory (`/`). -+ "Usr-merged" distributions[^systemd] may want to set this to `/usr`. The -+ default is empty (`""`). - * `usr_prefix`: where to install those parts of the code that aren't necessary -- for booting. You may want to set this to `/usr` if `prefix` is empty. -- * `systemd_prefix`: Prefix for systemd-related files. It defaults to `/usr`. -- Some systemd installations use separate `prefix` and `rootprefix`. On such -- a distribution, set `prefix`, and override `unitdir` to use systemd's -- `rootprefix`. -+ for booting. Non-usr-merged distributions[^systemd] may want to set this to -+ `/usr`. The default is `$(prefix)`. -+ * `systemd_prefix`: Prefix for systemd-related files[^systemd]. The default is `/usr`. -+ * `etc_prefix`: The prefix for configuration files. "Usr-merged" -+ distributions with immutable `/usr`[^systemd] may want to set this to -+ `/etc`. The default is `$(prefix)`. - * `LIB`: the subdirectory under `prefix` where shared libraries will be - installed. By default, the makefile uses `/lib64` if this directory is - found on the build system, and `/lib` otherwise. - --See also `configdir` and `plugindir` above. See `Makefile.inc` for more --fine-grained control. -+The options `configdir`, `plugindir`, `configfile`, and `statedir` above can -+be used for setting indvidual paths where the `prefix` variables don't provide -+sufficient control. See `Makefile.inc` for even more fine-grained control. -+ -+[^systemd]: Some systemd installations use separate `prefix` and `rootprefix`. -+ On such a distribution, set `prefix`, and override `unitdir` to use systemd's -+ `rootprefix`. Recent systemd releases generally require everything to be -+ installed under `/usr` (so-called "usr-merged" distribution). On "usr- - - ### Compiler Options - diff --git a/0034-libmultipath-print-built-in-values-for-deprecated-op.patch b/0034-libmultipath-print-built-in-values-for-deprecated-op.patch deleted file mode 100644 index 45e7874..0000000 --- a/0034-libmultipath-print-built-in-values-for-deprecated-op.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Mon, 11 Sep 2023 11:36:25 +0200 -Subject: [PATCH] libmultipath: print built-in values for deprecated options - -In the error messages we print when a deprecated option is encountered, -print the compile-time value of the option. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/dict.c | 16 +++++++++------- - 1 file changed, 9 insertions(+), 7 deletions(-) - -diff --git a/libmultipath/dict.c b/libmultipath/dict.c -index f81c84aa..dace343d 100644 ---- a/libmultipath/dict.c -+++ b/libmultipath/dict.c -@@ -314,14 +314,16 @@ def_ ## option ## _handler (struct config *conf, vector strvec, \ - static int deprecated_handler(struct config *conf, vector strvec, const char *file, - int line_nr); - --#define declare_deprecated_handler(option) \ -+#define declare_deprecated_handler(option, default) \ - static int \ - deprecated_ ## option ## _handler (struct config *conf, vector strvec, \ - const char *file, int line_nr) \ - { \ - static bool warned; \ - if (!warned) { \ -- condlog(1, "%s line %d: ignoring deprecated option \"" #option "\"", file, line_nr); \ -+ condlog(1, "%s line %d: ignoring deprecated option \"" \ -+ #option "\", using built-in value: \"%s\"", \ -+ file, line_nr, default); \ - warned = true; \ - } \ - return deprecated_handler(conf, strvec, file, line_nr); \ -@@ -2057,11 +2059,11 @@ snprint_deprecated (struct config *conf, struct strbuf *buff, const void * data) - } - - // Deprecated keywords --declare_deprecated_handler(config_dir) --declare_deprecated_handler(disable_changed_wwids) --declare_deprecated_handler(getuid_callout) --declare_deprecated_handler(multipath_dir) --declare_deprecated_handler(pg_timeout) -+declare_deprecated_handler(config_dir, CONFIG_DIR) -+declare_deprecated_handler(disable_changed_wwids, "yes") -+declare_deprecated_handler(getuid_callout, "(not set)") -+declare_deprecated_handler(multipath_dir, MULTIPATH_DIR) -+declare_deprecated_handler(pg_timeout, "(not set)") - - /* - * If you add or remove a keyword also update multipath/multipath.conf.5 diff --git a/0035-multipath-add-a-missing-newline.patch b/0035-multipath-add-a-missing-newline.patch deleted file mode 100644 index 706b7d3..0000000 --- a/0035-multipath-add-a-missing-newline.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Mon, 11 Sep 2023 11:37:37 +0200 -Subject: [PATCH] multipath: add a missing newline - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - multipath/main.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/multipath/main.c b/multipath/main.c -index 45e9745f..b91289e8 100644 ---- a/multipath/main.c -+++ b/multipath/main.c -@@ -1025,7 +1025,7 @@ main (int argc, char *argv[]) - } - - if (check_alias_settings(conf)) { -- fprintf(stderr, "fatal configuration error, aborting"); -+ fprintf(stderr, "fatal configuration error, aborting\n"); - exit(RTVL_FAIL); - } - diff --git a/0036-multipath-tools-allow-prefixes-with-and-w-o-trailing.patch b/0036-multipath-tools-allow-prefixes-with-and-w-o-trailing.patch deleted file mode 100644 index c48240b..0000000 --- a/0036-multipath-tools-allow-prefixes-with-and-w-o-trailing.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Mon, 11 Sep 2023 16:03:34 +0200 -Subject: [PATCH] multipath-tools: allow prefixes with and w/o trailing slash - -Add some logic to Makefile.inc that leads to the same result -for "prefix=" and "prefix=/", or "prefix=/usr" and "prefix=/usr/". -The logic does not work for multiple trailing slashes. It applies -to all XYZ_prefix variables in Makefile.inc. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - Makefile.inc | 35 ++++++++++++++++++++++------------- - 1 file changed, 22 insertions(+), 13 deletions(-) - -diff --git a/Makefile.inc b/Makefile.inc -index 79e521e1..6e384e68 100644 ---- a/Makefile.inc -+++ b/Makefile.inc -@@ -43,22 +43,31 @@ etc_prefix := $(prefix) - # Note: some systemd installations use separate "prefix" and "rootprefix". - # In this case, override only unitdir to use systemd's "rootprefix" instead of $(systemd_prefix) - systemd_prefix := /usr --unitdir := $(systemd_prefix)/lib/systemd/system --tmpfilesdir := $(systemd_prefix)/lib/tmpfiles.d --modulesloaddir := $(systemd_prefix)/lib/modules-load.d --libudevdir := $(systemd_prefix)/lib/udev -+ -+# Make sure all prefix variables end in "/" -+append-slash = $(1)$(if $(filter %/,$(1)),,/) -+override prefix := $(call append-slash,$(prefix)) -+override exec_prefix := $(call append-slash,$(exec_prefix)) -+override usr_prefix := $(call append-slash,$(usr_prefix)) -+override etc_prefix := $(call append-slash,$(etc_prefix)) -+override systemd_prefix := $(call append-slash,$(systemd_prefix)) -+ -+unitdir := $(systemd_prefix)lib/systemd/system -+tmpfilesdir := $(systemd_prefix)lib/tmpfiles.d -+modulesloaddir := $(systemd_prefix)lib/modules-load.d -+libudevdir := $(systemd_prefix)lib/udev - udevrulesdir := $(libudevdir)/rules.d --bindir := $(exec_prefix)/sbin --mandir := $(usr_prefix)/share/man -+bindir := $(exec_prefix)sbin -+mandir := $(usr_prefix)share/man - LIB := $(if $(shell test -d /lib64 && echo 1),lib64,lib) --syslibdir := $(prefix)/$(LIB) --usrlibdir := $(usr_prefix)/$(LIB) --includedir := $(usr_prefix)/include -+syslibdir := $(prefix)$(LIB) -+usrlibdir := $(usr_prefix)$(LIB) -+includedir := $(usr_prefix)include - pkgconfdir := $(usrlibdir)/pkgconfig --plugindir := $(prefix)/$(LIB)/multipath --configdir := $(etc_prefix)/etc/multipath/conf.d --configfile := $(etc_prefix)/etc/multipath.conf --statedir := $(etc_prefix)/etc/multipath -+plugindir := $(prefix)$(LIB)/multipath -+configdir := $(etc_prefix)etc/multipath/conf.d -+configfile := $(etc_prefix)etc/multipath.conf -+statedir := $(etc_prefix)etc/multipath - runtimedir := $(if $(shell test -L /var/run -o ! -d /var/run && echo 1),/run,/var/run) - devmapper_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir devmapper),/usr/include) - libudev_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir libudev),/usr/include) diff --git a/0037-libmultipath-deprecate-bindings_file-wwids_file-prke.patch b/0037-libmultipath-deprecate-bindings_file-wwids_file-prke.patch deleted file mode 100644 index 6e066ee..0000000 --- a/0037-libmultipath-deprecate-bindings_file-wwids_file-prke.patch +++ /dev/null @@ -1,897 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Mon, 11 Sep 2023 17:58:13 +0200 -Subject: [PATCH] libmultipath: deprecate bindings_file, wwids_file, - prkeys_file - -The options bindings_file, wwids_file, and prkeys_file have been -deprecated since cb4d6db ("libmultipath: deprecate file and directory config -options") (multipath-tools 0.8.8). Deprecate and ignore them now. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/alias.c | 43 +++++++++---------- - libmultipath/alias.h | 3 +- - libmultipath/config.c | 18 -------- - libmultipath/config.h | 3 -- - libmultipath/dict.c | 39 +++--------------- - libmultipath/libmultipath.version | 8 +--- - libmultipath/prkey.c | 7 ++-- - libmultipath/prkey.h | 7 ++-- - libmultipath/propsel.c | 5 +-- - libmultipath/wwids.c | 18 ++------ - multipath/main.c | 2 +- - multipath/multipath.conf.5.in | 23 +++++------ - multipathd/uxlsnr.c | 17 +++----- - tests/alias.c | 68 +++++++++++++++---------------- - 14 files changed, 90 insertions(+), 171 deletions(-) - -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index 964b8a7b..e5d3f151 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -55,6 +55,8 @@ - /* uatomic access only */ - static int bindings_file_changed = 1; - -+static const char bindings_file_path[] = DEFAULT_BINDINGS_FILE; -+ - static pthread_mutex_t timestamp_mutex = PTHREAD_MUTEX_INITIALIZER; - static struct timespec bindings_last_updated; - -@@ -274,7 +276,6 @@ static int write_bindings_file(const Bindings *bindings, int fd, - - void handle_bindings_file_inotify(const struct inotify_event *event) - { -- struct config *conf; - const char *base; - bool changed = false; - struct stat st; -@@ -284,12 +285,9 @@ void handle_bindings_file_inotify(const struct inotify_event *event) - if (!(event->mask & IN_MOVED_TO)) - return; - -- conf = get_multipath_config(); -- base = strrchr(conf->bindings_file, '/'); -- changed = base && base > conf->bindings_file && -- !strcmp(base + 1, event->name); -- ret = stat(conf->bindings_file, &st); -- put_multipath_config(conf); -+ base = strrchr(bindings_file_path, '/'); -+ changed = base && !strcmp(base + 1, event->name); -+ ret = stat(bindings_file_path, &st); - - if (!changed) - return; -@@ -310,8 +308,7 @@ void handle_bindings_file_inotify(const struct inotify_event *event) - __func__, (long)ts.tv_sec, (long)ts.tv_nsec / 1000); - } - --static int update_bindings_file(const Bindings *bindings, -- const char *bindings_file) -+static int update_bindings_file(const Bindings *bindings) - { - int rc; - int fd = -1; -@@ -319,7 +316,7 @@ static int update_bindings_file(const Bindings *bindings, - mode_t old_umask; - struct timespec ts; - -- if (safe_sprintf(tempname, "%s.XXXXXX", bindings_file)) -+ if (safe_sprintf(tempname, "%s.XXXXXX", bindings_file_path)) - return -1; - /* coverity: SECURE_TEMP */ - old_umask = umask(0077); -@@ -336,13 +333,13 @@ static int update_bindings_file(const Bindings *bindings, - unlink(tempname); - return rc; - } -- if ((rc = rename(tempname, bindings_file)) == -1) -+ if ((rc = rename(tempname, bindings_file_path)) == -1) - condlog(0, "%s: rename: %m", __func__); - else { - pthread_mutex_lock(×tamp_mutex); - bindings_last_updated = ts; - pthread_mutex_unlock(×tamp_mutex); -- condlog(1, "updated bindings file %s", bindings_file); -+ condlog(1, "updated bindings file %s", bindings_file_path); - } - return rc; - } -@@ -474,7 +471,7 @@ int get_free_id(const Bindings *bindings, const char *prefix, const char *map_ww - - /* Called with binding_mutex held */ - static char * --allocate_binding(const char *filename, const char *wwid, int id, const char *prefix) -+allocate_binding(const char *wwid, int id, const char *prefix) - { - STRBUF_ON_STACK(buf); - char *alias; -@@ -498,7 +495,7 @@ allocate_binding(const char *filename, const char *wwid, int id, const char *pre - return NULL; - } - -- if (update_bindings_file(&global_bindings, filename) == -1) { -+ if (update_bindings_file(&global_bindings) == -1) { - condlog(1, "%s: deleting binding %s for %s", __func__, alias, wwid); - delete_binding(&global_bindings, wwid); - free(alias); -@@ -565,7 +562,7 @@ static void read_bindings_file(void) - * that the mpvec corrcectly represents kernel state. - */ - --char *get_user_friendly_alias(const char *wwid, const char *file, const char *alias_old, -+char *get_user_friendly_alias(const char *wwid, const char *alias_old, - const char *prefix, bool bindings_read_only) - { - char *alias = NULL; -@@ -622,7 +619,7 @@ new_alias: - } - - if (!bindings_read_only && id > 0) -- alias = allocate_binding(file, wwid, id, prefix); -+ alias = allocate_binding(wwid, id, prefix); - - if (alias && !new_binding) - condlog(2, "Allocated existing binding [%s] for WWID [%s]", -@@ -715,12 +712,12 @@ static int _check_bindings_file(const struct config *conf, FILE *file, - header[sizeof(BINDINGS_FILE_HEADER) - 1] = '\0'; - if (fread(header, sizeof(BINDINGS_FILE_HEADER) - 1, 1, file) < 1) { - condlog(2, "%s: failed to read header from %s", __func__, -- conf->bindings_file); -+ bindings_file_path); - fseek(file, 0, SEEK_SET); - rc = -1; - } else if (strcmp(header, BINDINGS_FILE_HEADER)) { - condlog(2, "%s: invalid header in %s", __func__, -- conf->bindings_file); -+ bindings_file_path); - fseek(file, 0, SEEK_SET); - rc = -1; - } -@@ -787,13 +784,13 @@ static int _read_bindings_file(const struct config *conf, Bindings *bindings, - } - } - -- fd = open_file(conf->bindings_file, &can_write, BINDINGS_FILE_HEADER); -+ fd = open_file(bindings_file_path, &can_write, BINDINGS_FILE_HEADER); - if (fd == -1) - return BINDINGS_FILE_ERROR; - - file = fdopen(fd, "r"); - if (file != NULL) { -- condlog(3, "%s: reading %s", __func__, conf->bindings_file); -+ condlog(3, "%s: reading %s", __func__, bindings_file_path); - - pthread_cleanup_push(cleanup_fclose, file); - ret = _check_bindings_file(conf, file, bindings); -@@ -812,20 +809,20 @@ static int _read_bindings_file(const struct config *conf, Bindings *bindings, - bindings_last_updated = ts; - pthread_mutex_unlock(×tamp_mutex); - } else if (ret == -1 && can_write && !conf->bindings_read_only) { -- ret = update_bindings_file(bindings, conf->bindings_file); -+ ret = update_bindings_file(bindings); - if (ret == 0) - rc = BINDINGS_FILE_READ; - else - rc = BINDINGS_FILE_BAD; - } else { - condlog(0, "ERROR: bad settings in read-only bindings file %s", -- conf->bindings_file); -+ bindings_file_path); - rc = BINDINGS_FILE_BAD; - } - pthread_cleanup_pop(1); - } else { - condlog(1, "failed to fdopen %s: %m", -- conf->bindings_file); -+ bindings_file_path); - close(fd); - rc = BINDINGS_FILE_ERROR; - } -diff --git a/libmultipath/alias.h b/libmultipath/alias.h -index ca8911f4..629e8d56 100644 ---- a/libmultipath/alias.h -+++ b/libmultipath/alias.h -@@ -3,8 +3,7 @@ - - int valid_alias(const char *alias); - int get_user_friendly_wwid(const char *alias, char *buff); --char *get_user_friendly_alias(const char *wwid, const char *file, -- const char *alias_old, -+char *get_user_friendly_alias(const char *wwid, const char *alias_old, - const char *prefix, bool bindings_read_only); - - struct config; -diff --git a/libmultipath/config.c b/libmultipath/config.c -index 7b207590..b7dbc6f5 100644 ---- a/libmultipath/config.c -+++ b/libmultipath/config.c -@@ -752,15 +752,6 @@ static void _uninit_config(struct config *conf) - if (conf->hwhandler) - free(conf->hwhandler); - -- if (conf->bindings_file) -- free(conf->bindings_file); -- -- if (conf->wwids_file) -- free(conf->wwids_file); -- -- if (conf->prkeys_file) -- free(conf->prkeys_file); -- - if (conf->prio_name) - free(conf->prio_name); - -@@ -922,9 +913,6 @@ int _init_config (const char *file, struct config *conf) - * internal defaults - */ - get_sys_max_fds(&conf->max_fds); -- conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE); -- conf->wwids_file = set_default(DEFAULT_WWIDS_FILE); -- conf->prkeys_file = set_default(DEFAULT_PRKEYS_FILE); - conf->attribute_flags = 0; - conf->reassign_maps = DEFAULT_REASSIGN_MAPS; - conf->checkint = CHECKINT_UNDEF; -@@ -1078,12 +1066,6 @@ int _init_config (const char *file, struct config *conf) - merge_blacklist(conf->elist_wwid); - merge_blacklist_device(conf->elist_device); - -- if (conf->bindings_file == NULL) -- conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE); -- -- if (!conf->bindings_file || !conf->wwids_file || !conf->prkeys_file) -- goto out; -- - libmp_verbosity = conf->verbosity; - return 0; - out: -diff --git a/libmultipath/config.h b/libmultipath/config.h -index 0a2c297b..8c22ce75 100644 ---- a/libmultipath/config.h -+++ b/libmultipath/config.h -@@ -207,9 +207,6 @@ struct config { - char * uid_attribute; - char * features; - char * hwhandler; -- char * bindings_file; -- char * wwids_file; -- char * prkeys_file; - char * prio_name; - char * prio_args; - char * checker_name; -diff --git a/libmultipath/dict.c b/libmultipath/dict.c -index dace343d..044067af 100644 ---- a/libmultipath/dict.c -+++ b/libmultipath/dict.c -@@ -168,27 +168,6 @@ fail: - return 0; - } - --static int --set_path(vector strvec, void *ptr, const char *file, int line_nr) --{ -- char **str_ptr = (char **)ptr; -- char *old_str = *str_ptr; -- -- *str_ptr = set_value(strvec); -- if (!*str_ptr) { -- free(old_str); -- return 1; -- } -- if ((*str_ptr)[0] != '/'){ -- condlog(1, "%s line %d, %s is not an absolute path. Ignoring", -- file, line_nr, *str_ptr); -- free(*str_ptr); -- *str_ptr = old_str; -- } else -- free(old_str); -- return 0; --} -- - static int - set_str_noslash(vector strvec, void *ptr, const char *file, int line_nr) - { -@@ -831,15 +810,6 @@ declare_hw_snprint(user_friendly_names, print_yes_no_undef) - declare_mp_handler(user_friendly_names, set_yes_no_undef) - declare_mp_snprint(user_friendly_names, print_yes_no_undef) - --declare_def_warn_handler(bindings_file, set_path) --declare_def_snprint(bindings_file, print_str) -- --declare_def_warn_handler(wwids_file, set_path) --declare_def_snprint(wwids_file, print_str) -- --declare_def_warn_handler(prkeys_file, set_path) --declare_def_snprint(prkeys_file, print_str) -- - declare_def_handler(retain_hwhandler, set_yes_no_undef) - declare_def_snprint_defint(retain_hwhandler, print_yes_no_undef, - DEFAULT_RETAIN_HWHANDLER) -@@ -2064,6 +2034,9 @@ declare_deprecated_handler(disable_changed_wwids, "yes") - declare_deprecated_handler(getuid_callout, "(not set)") - declare_deprecated_handler(multipath_dir, MULTIPATH_DIR) - declare_deprecated_handler(pg_timeout, "(not set)") -+declare_deprecated_handler(bindings_file, DEFAULT_BINDINGS_FILE) -+declare_deprecated_handler(wwids_file, DEFAULT_WWIDS_FILE) -+declare_deprecated_handler(prkeys_file, DEFAULT_PRKEYS_FILE) - - /* - * If you add or remove a keyword also update multipath/multipath.conf.5 -@@ -2106,9 +2079,9 @@ init_keywords(vector keywords) - install_keyword("fast_io_fail_tmo", &def_fast_io_fail_handler, &snprint_def_fast_io_fail); - install_keyword("dev_loss_tmo", &def_dev_loss_handler, &snprint_def_dev_loss); - install_keyword("eh_deadline", &def_eh_deadline_handler, &snprint_def_eh_deadline); -- install_keyword("bindings_file", &def_bindings_file_handler, &snprint_def_bindings_file); -- install_keyword("wwids_file", &def_wwids_file_handler, &snprint_def_wwids_file); -- install_keyword("prkeys_file", &def_prkeys_file_handler, &snprint_def_prkeys_file); -+ install_keyword("bindings_file", &deprecated_bindings_file_handler, &snprint_deprecated); -+ install_keyword("wwids_file", &deprecated_wwids_file_handler, &snprint_deprecated); -+ install_keyword("prkeys_file", &deprecated_prkeys_file_handler, &snprint_deprecated); - install_keyword("log_checker_err", &def_log_checker_err_handler, &snprint_def_log_checker_err); - install_keyword("reservation_key", &def_reservation_key_handler, &snprint_def_reservation_key); - install_keyword("all_tg_pt", &def_all_tg_pt_handler, &snprint_def_all_tg_pt); -diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version -index 57e50c12..8368ef7a 100644 ---- a/libmultipath/libmultipath.version -+++ b/libmultipath/libmultipath.version -@@ -43,7 +43,7 @@ LIBMPATHCOMMON_1.0.0 { - put_multipath_config; - }; - --LIBMULTIPATH_20.0.0 { -+LIBMULTIPATH_21.0.0 { - global: - /* symbols referenced by multipath and multipathd */ - add_foreign; -@@ -121,6 +121,7 @@ global: - get_used_hwes; - get_vpd_sgio; - group_by_prio; -+ handle_bindings_file_inotify; - has_dm_info; - init_checkers; - init_config; -@@ -238,8 +239,3 @@ global: - local: - *; - }; -- --LIBMULTIPATH_20.1.0 { --global: -- handle_bindings_file_inotify; --}; -diff --git a/libmultipath/prkey.c b/libmultipath/prkey.c -index a215499d..c66d293b 100644 ---- a/libmultipath/prkey.c -+++ b/libmultipath/prkey.c -@@ -157,8 +157,7 @@ static int do_prkey(int fd, char *wwid, char *keystr, int cmd) - return 0; - } - --int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey, -- uint8_t *sa_flags) -+int get_prkey(struct multipath *mpp, uint64_t *prkey, uint8_t *sa_flags) - { - int fd; - int unused; -@@ -168,7 +167,7 @@ int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey, - if (!strlen(mpp->wwid)) - goto out; - -- fd = open_file(conf->prkeys_file, &unused, PRKEYS_FILE_HEADER); -+ fd = open_file(DEFAULT_PRKEYS_FILE, &unused, PRKEYS_FILE_HEADER); - if (fd < 0) - goto out; - ret = do_prkey(fd, mpp->wwid, keystr, PRKEY_READ); -@@ -201,7 +200,7 @@ int set_prkey(struct config *conf, struct multipath *mpp, uint64_t prkey, - sa_flags &= MPATH_F_APTPL_MASK; - } - -- fd = open_file(conf->prkeys_file, &can_write, PRKEYS_FILE_HEADER); -+ fd = open_file(DEFAULT_PRKEYS_FILE, &can_write, PRKEYS_FILE_HEADER); - if (fd < 0) - goto out; - if (!can_write) { -diff --git a/libmultipath/prkey.h b/libmultipath/prkey.h -index a16de106..43afd5e4 100644 ---- a/libmultipath/prkey.h -+++ b/libmultipath/prkey.h -@@ -16,9 +16,8 @@ - int print_reservation_key(struct strbuf *buff, - struct be64 key, uint8_t flags, int source); - int parse_prkey_flags(const char *ptr, uint64_t *prkey, uint8_t *flags); --int set_prkey(struct config *conf, struct multipath *mpp, uint64_t prkey, -- uint8_t sa_flags); --int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey, -- uint8_t *sa_flags); -+int set_prkey(struct config *conf, struct multipath *mpp, -+ uint64_t prkey, uint8_t sa_flags); -+int get_prkey(struct multipath *mpp, uint64_t *prkey, uint8_t *sa_flags); - - #endif /* _PRKEY_H */ -diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c -index 354e883f..44241e2a 100644 ---- a/libmultipath/propsel.c -+++ b/libmultipath/propsel.c -@@ -401,8 +401,7 @@ int select_alias(struct config *conf, struct multipath * mp) - - select_alias_prefix(conf, mp); - -- mp->alias = get_user_friendly_alias(mp->wwid, conf->bindings_file, -- mp->alias_old, mp->alias_prefix, -+ mp->alias = get_user_friendly_alias(mp->wwid, mp->alias_old, mp->alias_prefix, - conf->bindings_read_only); - - if (mp->alias && !strncmp(mp->alias, mp->alias_old, WWID_SIZE)) -@@ -992,7 +991,7 @@ int select_reservation_key(struct config *conf, struct multipath *mp) - out: - if (mp->prkey_source == PRKEY_SOURCE_FILE) { - from_file = " (from prkeys file)"; -- if (get_prkey(conf, mp, &prkey, &mp->sa_flags) != 0) -+ if (get_prkey(mp, &prkey, &mp->sa_flags) != 0) - put_be64(mp->reservation_key, 0); - else - put_be64(mp->reservation_key, prkey); -diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c -index 89bb60ca..591cd09b 100644 ---- a/libmultipath/wwids.c -+++ b/libmultipath/wwids.c -@@ -94,12 +94,8 @@ replace_wwids(vector mp) - struct multipath * mpp; - size_t len; - int ret = -1; -- struct config *conf; - -- conf = get_multipath_config(); -- pthread_cleanup_push(put_multipath_config, conf); -- fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER); -- pthread_cleanup_pop(1); -+ fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER); - if (fd < 0) - goto out; - -@@ -200,7 +196,6 @@ remove_wwid(char *wwid) { - int len, can_write; - char *str; - int ret = -1; -- struct config *conf; - - len = strlen(wwid) + 4; /* two slashes the newline and a zero byte */ - str = malloc(len); -@@ -216,10 +211,7 @@ remove_wwid(char *wwid) { - goto out; - } - condlog(3, "removing line '%s' from wwids file", str); -- conf = get_multipath_config(); -- pthread_cleanup_push(put_multipath_config, conf); -- fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER); -- pthread_cleanup_pop(1); -+ fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER); - - if (fd < 0) { - ret = -1; -@@ -244,12 +236,8 @@ check_wwids_file(char *wwid, int write_wwid) - { - int fd, can_write, found, ret; - FILE *f; -- struct config *conf; - -- conf = get_multipath_config(); -- pthread_cleanup_push(put_multipath_config, conf); -- fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER); -- pthread_cleanup_pop(1); -+ fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER); - if (fd < 0) - return -1; - -diff --git a/multipath/main.c b/multipath/main.c -index b91289e8..9e1c5052 100644 ---- a/multipath/main.c -+++ b/multipath/main.c -@@ -856,7 +856,7 @@ main (int argc, char *argv[]) - libmp_verbosity = atoi(optarg); - break; - case 'b': -- conf->bindings_file = strdup(optarg); -+ condlog(1, "option -b ignored"); - break; - case 'B': - conf->bindings_read_only = 1; -diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in -index 20df2232..d320a88f 100644 ---- a/multipath/multipath.conf.5.in -+++ b/multipath/multipath.conf.5.in -@@ -794,35 +794,28 @@ The default is: \fB\fR - . - .TP - .B bindings_file --(Deprecated) This option is deprecated, and will be removed in a future release. --The full pathname of the binding file to be used when the user_friendly_names --option is set. -+(Deprecated) This option is not supported any more, and will be ignored. - .RS - .TP --The default is: \fB@STATE_DIR@/bindings\fR -+The compiled-in value is: \fB@STATE_DIR@/bindings\fR - .RE - . - . - .TP - .B wwids_file --(Deprecated) This option is deprecated, and will be removed in a future release. --The full pathname of the WWIDs file, which is used by multipath to keep track --of the WWIDs for LUNs it has created multipath devices on in the past. -+(Deprecated) This option is not supported any more, and will be ignored. - .RS - .TP --The default is: \fB@STATE_DIR@/wwids\fR -+The compiled-in value is: \fB@STATE_DIR@/wwids\fR - .RE - . - . - .TP - .B prkeys_file --(Deprecated) This option is deprecated, and will be removed in a future release. --The full pathname of the prkeys file, which is used by multipathd to keep --track of the persistent reservation key used for a specific WWID, when --\fIreservation_key\fR is set to \fBfile\fR. -+(Deprecated) This option is not supported any more, and will be ignored. - .RS - .TP --The default is: \fB@STATE_DIR@/prkeys\fR -+The compiled-in value is: \fB@STATE_DIR@/prkeys\fR - .RE - . - . -@@ -989,6 +982,10 @@ The default is: \fB\fR - .TP - .B config_dir - (Deprecated) This option is not supported any more, and the value is ignored. -+.RS -+.TP -+The compiled-in value is: \fB@CONFIGDIR@\fR -+.RE - . - . - .TP -diff --git a/multipathd/uxlsnr.c b/multipathd/uxlsnr.c -index d1f8f234..4d6f258c 100644 ---- a/multipathd/uxlsnr.c -+++ b/multipathd/uxlsnr.c -@@ -203,7 +203,6 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds, - int dir_reset = 0; - int conf_reset = 0; - int mp_reset = 0; -- char *bindings_file __attribute__((cleanup(cleanup_charp))) = NULL; - - if (notify_fd == -1) - return; -@@ -221,7 +220,6 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds, - if (wds->mp_wd == -1) - mp_reset = 1; - } -- bindings_file = strdup(conf->bindings_file); - put_multipath_config(conf); - - if (dir_reset) { -@@ -242,17 +240,12 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds, - if (wds->conf_wd == -1) - condlog(3, "didn't set up notifications on /etc/multipath.conf: %m"); - } -- if (mp_reset && bindings_file) { -- char *slash = strrchr(bindings_file, '/'); -- -- if (slash && slash > bindings_file) { -- *slash = '\0'; -- wds->mp_wd = inotify_add_watch(notify_fd, bindings_file, -- IN_MOVED_TO|IN_ONLYDIR); -- if (wds->mp_wd == -1) -+ if (mp_reset) { -+ wds->mp_wd = inotify_add_watch(notify_fd, STATE_DIR, -+ IN_MOVED_TO|IN_ONLYDIR); -+ if (wds->mp_wd == -1) - condlog(3, "didn't set up notifications on %s: %m", -- bindings_file); -- } -+ STATE_DIR); - } - } - -diff --git a/tests/alias.c b/tests/alias.c -index 94df36d8..f893d174 100644 ---- a/tests/alias.c -+++ b/tests/alias.c -@@ -1264,10 +1264,10 @@ static void al_a(void **state) - will_return(__wrap_write, ln); - will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); - will_return(__wrap_rename, 0); -- expect_condlog(1, "updated bindings file foo"); -+ expect_condlog(1, "updated bindings file " DEFAULT_BINDINGS_FILE); - expect_condlog(3, NEW_STR("MPATHa", "WWIDa")); - -- alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); -+ alias = allocate_binding("WWIDa", 1, "MPATH"); - assert_ptr_not_equal(alias, NULL); - assert_string_equal(alias, "MPATHa"); - check_bindings_size(1); -@@ -1283,10 +1283,10 @@ static void al_zz(void **state) - will_return(__wrap_write, ln); - will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); - will_return(__wrap_rename, 0); -- expect_condlog(1, "updated bindings file foo"); -+ expect_condlog(1, "updated bindings file " DEFAULT_BINDINGS_FILE); - expect_condlog(3, NEW_STR("MPATHzz", "WWIDzz")); - -- alias = allocate_binding("foo", "WWIDzz", 26*26 + 26, "MPATH"); -+ alias = allocate_binding("WWIDzz", 26*26 + 26, "MPATH"); - assert_ptr_not_equal(alias, NULL); - assert_string_equal(alias, "MPATHzz"); - check_bindings_size(1); -@@ -1298,7 +1298,7 @@ static void al_0(void **state) - char *alias; - - expect_condlog(0, "allocate_binding: cannot allocate new binding for id 0\n"); -- alias = allocate_binding(0, "WWIDa", 0, "MPATH"); -+ alias = allocate_binding("WWIDa", 0, "MPATH"); - assert_ptr_equal(alias, NULL); - check_bindings_size(0); - } -@@ -1308,7 +1308,7 @@ static void al_m2(void **state) - char *alias; - - expect_condlog(0, "allocate_binding: cannot allocate new binding for id -2\n"); -- alias = allocate_binding(0, "WWIDa", -2, "MPATH"); -+ alias = allocate_binding("WWIDa", -2, "MPATH"); - assert_ptr_equal(alias, NULL); - check_bindings_size(0); - } -@@ -1325,10 +1325,10 @@ static void al_write_partial(void **state) - will_return(__wrap_write, ln + sizeof(ln) - 2); - will_return(__wrap_write, 1); - will_return(__wrap_rename, 0); -- expect_condlog(1, "updated bindings file foo"); -+ expect_condlog(1, "updated bindings file " DEFAULT_BINDINGS_FILE); - expect_condlog(3, "Created new binding [MPATHa] for WWID [WWIDa]\n"); - -- alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); -+ alias = allocate_binding("WWIDa", 1, "MPATH"); - assert_ptr_not_equal(alias, NULL); - assert_string_equal(alias, "MPATHa"); - check_bindings_size(1); -@@ -1350,7 +1350,7 @@ static void al_write_short(void **state) - expect_condlog(1, "failed to write new bindings file"); - expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa"); - -- alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); -+ alias = allocate_binding("WWIDa", 1, "MPATH"); - assert_ptr_equal(alias, NULL); - check_bindings_size(0); - } -@@ -1366,7 +1366,7 @@ static void al_write_err(void **state) - expect_condlog(1, "failed to write new bindings file"); - expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa"); - -- alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); -+ alias = allocate_binding("WWIDa", 1, "MPATH"); - assert_ptr_equal(alias, NULL); - check_bindings_size(0); - } -@@ -1383,7 +1383,7 @@ static void al_rename_err(void **state) - - expect_condlog(0, "update_bindings_file: rename: Read-only file system"); - expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa"); -- alias = allocate_binding("foo", "WWIDa", 1, "MPATH"); -+ alias = allocate_binding("WWIDa", 1, "MPATH"); - assert_ptr_equal(alias, NULL); - check_bindings_size(0); - } -@@ -1415,7 +1415,7 @@ static int test_allocate_binding(void) - strlen(BINDINGS_FILE_HEADER) + (len) + strlen(ln)); \ - will_return(__wrap_rename, err); \ - if (err == 0) { \ -- expect_condlog(1, "updated bindings file x\n"); \ -+ expect_condlog(1, "updated bindings file " DEFAULT_BINDINGS_FILE); \ - expect_condlog(3, NEW_STR(alias, wwid)); \ - } else { \ - expect_condlog(0, "update_bindings_file: rename: " msg "\n"); \ -@@ -1441,7 +1441,7 @@ static void gufa_empty_new_rw(void **state) { - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - - mock_allocate_binding("MPATHa", "WWID0"); -- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false); -+ alias = get_user_friendly_alias("WWID0", "", "MPATH", false); - assert_string_equal(alias, "MPATHa"); - free(alias); - } -@@ -1454,7 +1454,7 @@ static void gufa_empty_new_ro_1(void **state) { - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - mock_allocate_binding_err("MPATHa", "WWID0", -EROFS, "Read-only file system"); - -- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false); -+ alias = get_user_friendly_alias("WWID0", "", "MPATH", false); - assert_ptr_equal(alias, NULL); - } - -@@ -1465,7 +1465,7 @@ static void gufa_empty_new_ro_2(void **state) { - expect_condlog(3, NOMATCH_WWID_STR("WWID0")); - mock_unused_alias("MPATHa"); - -- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); -+ alias = get_user_friendly_alias("WWID0", "", "MPATH", true); - assert_ptr_equal(alias, NULL); - } - -@@ -1477,7 +1477,7 @@ static void gufa_match_a_unused(void **state) { - mock_unused_alias("MPATHa"); - expect_condlog(3, EXISTING_STR("MPATHa", "WWID0")); - -- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); -+ alias = get_user_friendly_alias("WWID0", "", "MPATH", true); - assert_string_equal(alias, "MPATHa"); - free(alias); - } -@@ -1490,7 +1490,7 @@ static void gufa_match_a_self(void **state) { - mock_self_alias("MPATHa", "WWID0"); - expect_condlog(3, EXISTING_STR("MPATHa", "WWID0")); - -- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); -+ alias = get_user_friendly_alias("WWID0", "", "MPATH", true); - assert_string_equal(alias, "MPATHa"); - free(alias); - } -@@ -1503,7 +1503,7 @@ static void gufa_match_a_used(void **state) { - expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); - mock_used_alias("MPATHa", "WWID0"); - -- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); -+ alias = get_user_friendly_alias("WWID0", "", "MPATH", true); - assert_ptr_equal(alias, NULL); - } - -@@ -1518,7 +1518,7 @@ static void gufa_nomatch_a_c(void **state) { - - mock_allocate_binding_len("MPATHb", "WWID1", strlen(bindings)); - -- alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false); -+ alias = get_user_friendly_alias("WWID1", "", "MPATH", false); - assert_string_equal(alias, "MPATHb"); - free(alias); - } -@@ -1534,7 +1534,7 @@ static void gufa_nomatch_c_a(void **state) { - - mock_allocate_binding_len("MPATHb", "WWID1", sizeof(bindings) - 1); - -- alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false); -+ alias = get_user_friendly_alias("WWID1", "", "MPATH", false); - assert_string_equal(alias, "MPATHb"); - free(alias); - } -@@ -1550,7 +1550,7 @@ static void gufa_nomatch_c_b(void **state) { - - mock_allocate_binding_len("MPATHa", "WWID0", sizeof(bindings) - 1); - -- alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false); -+ alias = get_user_friendly_alias("WWID0", "", "MPATH", false); - assert_string_equal(alias, "MPATHa"); - free(alias); - } -@@ -1567,7 +1567,7 @@ static void gufa_nomatch_c_b_used(void **state) { - - mock_allocate_binding_len("MPATHd", "WWID4", sizeof(bindings) - 1); - -- alias = get_user_friendly_alias("WWID4", "x", "", "MPATH", false); -+ alias = get_user_friendly_alias("WWID4", "", "MPATH", false); - assert_string_equal(alias, "MPATHd"); - free(alias); - } -@@ -1584,7 +1584,7 @@ static void gufa_nomatch_b_f_a(void **state) { - - mock_allocate_binding_len("MPATHc", "WWID7", sizeof(bindings) - 1); - -- alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false); -+ alias = get_user_friendly_alias("WWID7", "", "MPATH", false); - assert_string_equal(alias, "MPATHc"); - free(alias); - } -@@ -1599,7 +1599,7 @@ static void gufa_nomatch_b_aa_a(void **state) { - mock_unused_alias("MPATHab"); - mock_allocate_binding_len("MPATHab", "WWID28", get_strbuf_len(&buf)); - -- alias = get_user_friendly_alias("WWID28", "x", "", "MPATH", false); -+ alias = get_user_friendly_alias("WWID28", "", "MPATH", false); - assert_string_equal(alias, "MPATHab"); - free(alias); - } -@@ -1616,7 +1616,7 @@ static void gufa_nomatch_b_f_a_sorted(void **state) { - - mock_allocate_binding_len("MPATHc", "WWID7", sizeof(bindings) - 1); - -- alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false); -+ alias = get_user_friendly_alias("WWID7", "", "MPATH", false); - assert_string_equal(alias, "MPATHc"); - free(alias); - } -@@ -1632,7 +1632,7 @@ static void gufa_old_empty(void **state) { - mock_allocate_binding("MPATHz", "WWID0"); - expect_condlog(2, ALLOC_STR("MPATHz", "WWID0")); - -- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); -+ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false); - assert_string_equal(alias, "MPATHz"); - free(alias); - } -@@ -1644,7 +1644,7 @@ static void gufa_old_match(void **state) { - "MPATHz WWID0"); - expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID0")); - -- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); -+ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false); - assert_string_equal(alias, "MPATHz"); - free(alias); - } -@@ -1661,7 +1661,7 @@ static void gufa_old_match_other(void **state) { - - mock_allocate_binding_len("MPATHa", "WWID0", sizeof(bindings) - 1); - -- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); -+ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false); - assert_string_equal(alias, "MPATHa"); - free(alias); - } -@@ -1678,7 +1678,7 @@ static void gufa_old_match_other_used(void **state) { - mock_unused_alias("MPATHb"); - - mock_allocate_binding_len("MPATHb", "WWID0", sizeof(bindings) - 1); -- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); -+ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false); - assert_string_equal(alias, "MPATHb"); - free(alias); - } -@@ -1695,7 +1695,7 @@ static void gufa_old_match_other_wwidmatch(void **state) { - mock_unused_alias("MPATHc"); - expect_condlog(3, EXISTING_STR("MPATHc", "WWID2")); - -- alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false); -+ alias = get_user_friendly_alias("WWID2", "MPATHz", "MPATH", false); - assert_string_equal(alias, "MPATHc"); - free(alias); - } -@@ -1711,7 +1711,7 @@ static void gufa_old_match_other_wwidmatch_used(void **state) { - expect_condlog(3, FOUND_STR("MPATHc", "WWID2")); - mock_used_alias("MPATHc", "WWID2"); - -- alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false); -+ alias = get_user_friendly_alias("WWID2", "MPATHz", "MPATH", false); - assert_ptr_equal(alias, NULL); - } - -@@ -1725,7 +1725,7 @@ static void gufa_old_nomatch_wwidmatch(void **state) { - mock_unused_alias("MPATHa"); - expect_condlog(3, EXISTING_STR("MPATHa", "WWID0")); - -- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); -+ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false); - assert_string_equal(alias, "MPATHa"); - free(alias); - } -@@ -1739,7 +1739,7 @@ static void gufa_old_nomatch_wwidmatch_used(void **state) { - expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); - mock_used_alias("MPATHa", "WWID0"); - -- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); -+ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false); - assert_ptr_equal(alias, NULL); - } - -@@ -1754,7 +1754,7 @@ static void gufa_old_nomatch_nowwidmatch(void **state) { - mock_allocate_binding_len("MPATHz", "WWID0", sizeof(bindings) - 1); - expect_condlog(2, ALLOC_STR("MPATHz", "WWID0")); - -- alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); -+ alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false); - assert_string_equal(alias, "MPATHz"); - free(alias); - } diff --git a/0038-libmultipath-avoid-Warray-bounds-error-in-uatomic-op.patch b/0038-libmultipath-avoid-Warray-bounds-error-in-uatomic-op.patch deleted file mode 100644 index 269efcf..0000000 --- a/0038-libmultipath-avoid-Warray-bounds-error-in-uatomic-op.patch +++ /dev/null @@ -1,158 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Tue, 12 Sep 2023 11:54:47 +0200 -Subject: [PATCH] libmultipath: avoid -Warray-bounds error in uatomic - operations - -The use of uatomic_xchg() in alias.c causes a -Warray-bounds error -on distributions using gcc 12, such as Fedora 37. This is a similar -error to 2534c4f ("libmultipath: avoid -Warray-bounds error with gcc -12 and musl libc"). This happens only with liburcu 0.13 and earlier, -and only with certain gcc versions. See liburcu commit 835b9ab -("Fix: x86 and s390 uatomic: __hp() macro warning with gcc 11"). - -Enhance the fix for 2534c4f by a adding a workaround for uatomic_xchg(), -and introduce the macro URCU_VERSION (originally only used for multipathd) -globally. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - Makefile.inc | 2 +- - create-config.mk | 5 +++++ - libmultipath/alias.c | 5 +++-- - libmultipath/lock.h | 21 +++++++++++++-------- - multipathd/Makefile | 2 -- - 5 files changed, 22 insertions(+), 13 deletions(-) - -diff --git a/Makefile.inc b/Makefile.inc -index 6e384e68..04bfa56e 100644 ---- a/Makefile.inc -+++ b/Makefile.inc -@@ -95,7 +95,7 @@ OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4 - WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implicit-int \ - -Werror=implicit-function-declaration -Werror=format-security \ - $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) --CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) \ -+CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \ - -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \ - -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \ - -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DSTATE_DIR=\"$(statedir)\" \ -diff --git a/create-config.mk b/create-config.mk -index d1255971..4d318b96 100644 ---- a/create-config.mk -+++ b/create-config.mk -@@ -73,6 +73,10 @@ TEST_URCU_TYPE_LIMITS = $(shell \ - $(CC) -c -Werror=type-limits -o /dev/null -xc - 2>/dev/null \ - || echo -Wno-type-limits ) - -+URCU_VERSION = $(shell \ -+ $(PKG_CONFIG) --modversion liburcu 2>/dev/null | \ -+ awk -F. '{ printf("-DURCU_VERSION=0x%06x", 256 * ( 256 * $$1 + $$2) + $$3); }') -+ - DEFINES := - - ifneq ($(call check_func,dm_task_no_flush,$(devmapper_incdir)/libdevmapper.h),0) -@@ -168,6 +172,7 @@ $(TOPDIR)/config.mk: $(multipathdir)/autoconfig.h - @echo creating $@ - @echo "FPIN_SUPPORT := $(FPIN_SUPPORT)" >$@ - @echo "FORTIFY_OPT := $(FORTIFY_OPT)" >>$@ -+ @echo "D_URCU_VERSION := $(call URCU_VERSION)" >>$@ - @echo "SYSTEMD := $(SYSTEMD)" >>$@ - @echo "ANA_SUPPORT := $(ANA_SUPPORT)" >>$@ - @echo "STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)" >>$@ -diff --git a/libmultipath/alias.c b/libmultipath/alias.c -index e5d3f151..74431f3f 100644 ---- a/libmultipath/alias.c -+++ b/libmultipath/alias.c -@@ -24,6 +24,7 @@ - #include "devmapper.h" - #include "strbuf.h" - #include "time-util.h" -+#include "lock.h" - - /* - * significant parts of this file were taken from iscsi-bindings.c of the -@@ -300,7 +301,7 @@ void handle_bindings_file_inotify(const struct inotify_event *event) - pthread_mutex_unlock(×tamp_mutex); - - if (changed) { -- uatomic_xchg(&bindings_file_changed, 1); -+ uatomic_xchg_int(&bindings_file_changed, 1); - condlog(3, "%s: bindings file must be re-read, new timestamp: %ld.%06ld", - __func__, (long)ts.tv_sec, (long)ts.tv_nsec / 1000); - } else -@@ -775,7 +776,7 @@ static int _read_bindings_file(const struct config *conf, Bindings *bindings, - int rc = 0, ret, fd; - FILE *file; - struct stat st; -- int has_changed = uatomic_xchg(&bindings_file_changed, 0); -+ int has_changed = uatomic_xchg_int(&bindings_file_changed, 0); - - if (!force) { - if (!has_changed) { -diff --git a/libmultipath/lock.h b/libmultipath/lock.h -index 9814be76..ac80d1d8 100644 ---- a/libmultipath/lock.h -+++ b/libmultipath/lock.h -@@ -13,15 +13,20 @@ struct mutex_lock { - int waiters; /* uatomic access only */ - }; - --#if !defined(__GLIBC__) && defined(__GNUC__) && __GNUC__ == 12 -+static inline void init_lock(struct mutex_lock *a) -+{ -+ pthread_mutex_init(&a->mutex, NULL); -+ uatomic_set(&a->waiters, 0); -+} -+ -+#if defined(__GNUC__) && __GNUC__ == 12 && URCU_VERSION < 0xe00 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Warray-bounds" - #endif - --static inline void init_lock(struct mutex_lock *a) -+static inline int uatomic_xchg_int(int *ptr, int val) - { -- pthread_mutex_init(&a->mutex, NULL); -- uatomic_set(&a->waiters, 0); -+ return uatomic_xchg(ptr, val); - } - - static inline void lock(struct mutex_lock *a) -@@ -31,6 +36,10 @@ static inline void lock(struct mutex_lock *a) - uatomic_dec(&a->waiters); - } - -+#if defined(__GNUC__) && __GNUC__ == 12 && URCU_VERSION < 0xe00 -+#pragma GCC diagnostic pop -+#endif -+ - static inline int trylock(struct mutex_lock *a) - { - return pthread_mutex_trylock(&a->mutex); -@@ -51,10 +60,6 @@ static inline bool lock_has_waiters(struct mutex_lock *a) - return (uatomic_read(&a->waiters) > 0); - } - --#if !defined(__GLIBC__) && defined(__GNUC__) && __GNUC__ == 12 --#pragma GCC diagnostic pop --#endif -- - #define lock_cleanup_pop(a) pthread_cleanup_pop(1) - - void cleanup_lock (void * data); -diff --git a/multipathd/Makefile b/multipathd/Makefile -index cdba3db1..0ba6ecb7 100644 ---- a/multipathd/Makefile -+++ b/multipathd/Makefile -@@ -5,8 +5,6 @@ CLI := multipathc - MANPAGES := multipathd.8 - - CPPFLAGS += -I$(multipathdir) -I$(mpathutildir) -I$(mpathpersistdir) -I$(mpathcmddir) -I$(thirdpartydir) \ -- $(shell $(PKG_CONFIG) --modversion liburcu 2>/dev/null | \ -- awk -F. '{ printf("-DURCU_VERSION=0x%06x", 256 * ( 256 * $$1 + $$2) + $$3); }') \ - -DBINDIR='"$(bindir)"' $(SYSTEMD_CPPFLAGS) - - # diff --git a/0039-multipath-tools-fix-spelling.patch b/0039-multipath-tools-fix-spelling.patch deleted file mode 100644 index c0c86f9..0000000 --- a/0039-multipath-tools-fix-spelling.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Xose Vazquez Perez -Date: Fri, 15 Sep 2023 22:22:06 +0200 -Subject: [PATCH] multipath-tools: fix spelling - -Cc: Martin Wilck -Cc: Benjamin Marzinski -Cc: Christophe Varoqui -Cc: DM-DEVEL ML -Signed-off-by: Xose Vazquez Perez -Reviewed-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - README.md | 4 ++-- - multipath/multipath.conf.5.in | 2 +- - 2 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/README.md b/README.md -index 679e55bf..524c9fb1 100644 ---- a/README.md -+++ b/README.md -@@ -92,7 +92,7 @@ The following variables can be passed to the `make` command line: - The default is `$(prefix)/$(LIB)/multipath`, where `$(LIB)` is `lib64` on - systems that have `/lib64`, and `lib` otherwise. - * `configfile="/some/path`": The path to the main configuration file. -- The defalt is `$(etc_prefix)/etc/multipath.conf`. -+ The default is `$(etc_prefix)/etc/multipath.conf`. - * `configdir="/some/path"` : directory to search for additional configuration files. - This used to be the run-time option `config_dir` in earlier versions. - The default is `$(etc_prefix)/etc/multipath/conf.d`. -@@ -141,7 +141,7 @@ The following variables can be passed to the `make` command line: - found on the build system, and `/lib` otherwise. - - The options `configdir`, `plugindir`, `configfile`, and `statedir` above can --be used for setting indvidual paths where the `prefix` variables don't provide -+be used for setting individual paths where the `prefix` variables don't provide - sufficient control. See `Makefile.inc` for even more fine-grained control. - - [^systemd]: Some systemd installations use separate `prefix` and `rootprefix`. -diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in -index d320a88f..226d0019 100644 ---- a/multipath/multipath.conf.5.in -+++ b/multipath/multipath.conf.5.in -@@ -36,7 +36,7 @@ Files ending in \fI.conf\fR in this directory are read - in alphabetical order, after reading \fI@CONFIGFILE@\fR. - They use the same syntax as \fI@CONFIGFILE@\fR itself, - and support all sections and keywords. If a keyword occurs in the same section --in multiple files, the last occurence will take precedence over all others. -+in multiple files, the last occurrence will take precedence over all others. - . - . - .\" ---------------------------------------------------------------------------- diff --git a/0040-multipathd-Added-support-to-handle-FPIN-Li-events-fo.patch b/0040-multipathd-Added-support-to-handle-FPIN-Li-events-fo.patch deleted file mode 100644 index 7ed50a3..0000000 --- a/0040-multipathd-Added-support-to-handle-FPIN-Li-events-fo.patch +++ /dev/null @@ -1,300 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Muneendra -Date: Wed, 20 Sep 2023 20:41:15 -0700 -Subject: [PATCH] multipathd: Added support to handle FPIN-Li events for - FC-NVMe - - This patch adds the support to handle FPIN-Li for FC-NVMe. - On receiving the FPIN-Li events this patch moves the devices paths - which are affected due to link integrity to marginal path groups. - The paths which are set to marginal path group will be unset - on receiving the RSCN events - -(mwilck: minor compile fix for 32-bit architectures) - -Signed-off-by: Muneendra -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck ---- - multipathd/fpin_handlers.c | 206 +++++++++++++++++++++++++++---------- - 1 file changed, 151 insertions(+), 55 deletions(-) - -diff --git a/multipathd/fpin_handlers.c b/multipathd/fpin_handlers.c -index aa0f63c9..be087ca0 100644 ---- a/multipathd/fpin_handlers.c -+++ b/multipathd/fpin_handlers.c -@@ -60,18 +60,15 @@ static void _udev_device_unref(void *p) - - - /*set/unset the path state to marginal*/ --static int fpin_set_pathstate(struct path *pp, bool set) -+static void fpin_set_pathstate(struct path *pp, bool set) - { - const char *action = set ? "set" : "unset"; - -- if (!pp || !pp->mpp || !pp->mpp->alias) -- return -1; -- -- condlog(3, "\n%s: %s marginal path %s (fpin)", -- action, pp->mpp->alias, pp->dev_t); -+ condlog(3, "%s: %s marginal path %s (fpin)", -+ pp->mpp ? pp->mpp->alias : "orphan", action, pp->dev_t); - pp->marginal = set; -- pp->mpp->fpin_must_reload = true; -- return 0; -+ if (pp->mpp) -+ pp->mpp->fpin_must_reload = true; - } - - /* This will unset marginal state of a device*/ -@@ -82,14 +79,14 @@ static void fpin_path_unsetmarginal(char *devname, struct vectors *vecs) - pp = find_path_by_dev(vecs->pathvec, devname); - if (!pp) - pp = find_path_by_devt(vecs->pathvec, devname); -- -- fpin_set_pathstate(pp, false); -+ if (pp) -+ fpin_set_pathstate(pp, false); - } - - /*This will set the marginal state of a device*/ --static int fpin_path_setmarginal(struct path *pp) -+static void fpin_path_setmarginal(struct path *pp) - { -- return fpin_set_pathstate(pp, true); -+ fpin_set_pathstate(pp, true); - } - - /* Unsets all the devices in the list from marginal state */ -@@ -183,8 +180,8 @@ static void fpin_set_rport_marginal(struct udev_device *rport_dev) - udev_device_get_syspath(rport_dev)); - } - --/*Add the marginal devices info into the list*/ --static void -+/*Add the marginal devices info into the list and return 0 on success*/ -+static int - fpin_add_marginal_dev_info(uint32_t host_num, char *devname) - { - struct marginal_dev_list *newdev = NULL; -@@ -199,65 +196,160 @@ fpin_add_marginal_dev_info(uint32_t host_num, char *devname) - list_add_tail(&(newdev->node), - &fpin_li_marginal_dev_list_head); - pthread_mutex_unlock(&fpin_li_marginal_dev_mutex); -- } -+ } else -+ return -ENOMEM; -+ return 0; - } - - /* -- * This function goes through the vecs->pathvec, and for -- * each path, check that the host number, -- * the target WWPN associated with the path matches -- * with the els wwpn and sets the path and port state to -+ * This function compares Transport Address Controller Port pn, -+ * Host Transport Address Controller Port pn with the els wwpn ,attached_wwpn -+ * and return 1 (match) or 0 (no match) or a negative error code -+ */ -+static int extract_nvme_addresses_chk_path_pwwn(const char *address, -+ uint64_t els_wwpn, uint64_t els_attached_wwpn) -+ -+{ -+ uint64_t traddr; -+ uint64_t host_traddr; -+ -+ /* -+ * Find the position of "traddr=" and "host_traddr=" -+ * and the address will be in the below format -+ * "traddr=nn-0x200400110dff9400:pn-0x200400110dff9400, -+ * host_traddr=nn-0x200400110dff9400:pn-0x200400110dff9400" -+ */ -+ const char *traddr_start = strstr(address, "traddr="); -+ const char *host_traddr_start = strstr(address, "host_traddr="); -+ -+ if (!traddr_start || !host_traddr_start) -+ return -EINVAL; -+ -+ /* Extract traddr pn */ -+ if (sscanf(traddr_start, "traddr=nn-%*[^:]:pn-%" SCNx64, &traddr) != 1) -+ return -EINVAL; -+ -+ /* Extract host_traddr pn*/ -+ if (sscanf(host_traddr_start, "host_traddr=nn-%*[^:]:pn-%" SCNx64, -+ &host_traddr) != 1) -+ return -EINVAL; -+ condlog(4, "traddr 0x%" PRIx64 " hosttraddr 0x%" PRIx64 " els_wwpn 0x%" -+ PRIx64" els_host_traddr 0x%" PRIx64, -+ traddr, host_traddr, -+ els_wwpn, els_attached_wwpn); -+ if ((host_traddr == els_attached_wwpn) && (traddr == els_wwpn)) -+ return 1; -+ return 0; -+} -+ -+/* -+ * This function check that the Transport Address Controller Port pn, -+ * Host Transport Address Controller Port pn associated with the path matches -+ * with the els wwpn ,attached_wwpn and sets the path state to - * Marginal - */ --static int fpin_chk_wwn_setpath_marginal(uint16_t host_num, struct vectors *vecs, -+static void fpin_check_set_nvme_path_marginal(uint16_t host_num, struct path *pp, -+ uint64_t els_wwpn, uint64_t attached_wwpn) -+{ -+ struct udev_device *ctl = NULL; -+ const char *address = NULL; -+ int ret = 0; -+ -+ ctl = udev_device_get_parent_with_subsystem_devtype(pp->udev, "nvme", NULL); -+ if (ctl == NULL) { -+ condlog(2, "%s: No parent device for ", pp->dev); -+ return; -+ } -+ address = udev_device_get_sysattr_value(ctl, "address"); -+ if (!address) { -+ condlog(2, "%s: unable to get the address ", pp->dev); -+ return; -+ } -+ condlog(4, "\n address %s: dev :%s\n", address, pp->dev); -+ ret = extract_nvme_addresses_chk_path_pwwn(address, els_wwpn, attached_wwpn); -+ if (ret <= 0) -+ return; -+ ret = fpin_add_marginal_dev_info(host_num, pp->dev); -+ if (ret < 0) -+ return; -+ fpin_path_setmarginal(pp); -+} -+ -+/* -+ * This function check the host number, the target WWPN -+ * associated with the path matches with the els wwpn and -+ * sets the path and port state to Marginal -+ */ -+static void fpin_check_set_scsi_path_marginal(uint16_t host_num, struct path *pp, - uint64_t els_wwpn) - { -- struct path *pp; -- struct multipath *mpp; -- int i, k; - char rport_id[42]; - const char *value = NULL; - struct udev_device *rport_dev = NULL; - uint64_t wwpn; - int ret = 0; -+ sprintf(rport_id, "rport-%d:%d-%d", -+ pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id); -+ rport_dev = udev_device_new_from_subsystem_sysname(udev, -+ "fc_remote_ports", rport_id); -+ if (!rport_dev) { -+ condlog(2, "%s: No fc_remote_port device for '%s'", pp->dev, -+ rport_id); -+ return; -+ } -+ pthread_cleanup_push(_udev_device_unref, rport_dev); -+ value = udev_device_get_sysattr_value(rport_dev, "port_name"); -+ if (!value) -+ goto unref; -+ -+ wwpn = strtol(value, NULL, 16); -+ /* -+ * If the port wwpn matches sets the path and port state -+ * to marginal -+ */ -+ if (wwpn == els_wwpn) { -+ ret = fpin_add_marginal_dev_info(host_num, pp->dev); -+ if (ret < 0) -+ goto unref; -+ fpin_path_setmarginal(pp); -+ fpin_set_rport_marginal(rport_dev); -+ } -+unref: -+ pthread_cleanup_pop(1); -+ return; -+ -+} -+ -+/* -+ * This function goes through the vecs->pathvec, and for -+ * each path, it checks and sets the path state to marginal -+ * if the path's associated port wwpn ,hostnum matches with -+ * els wwnpn ,attached_wwpn -+ */ -+static int fpin_chk_wwn_setpath_marginal(uint16_t host_num, struct vectors *vecs, -+ uint64_t els_wwpn, uint64_t attached_wwpn) -+{ -+ struct path *pp; -+ struct multipath *mpp; -+ int i, k; -+ int ret = 0; - - pthread_cleanup_push(cleanup_lock, &vecs->lock); - lock(&vecs->lock); - pthread_testcancel(); - - vector_foreach_slot(vecs->pathvec, pp, k) { -- /* Checks the host number and also for the SCSI FCP */ -- if (pp->bus != SYSFS_BUS_SCSI || pp->sg_id.proto_id != SCSI_PROTOCOL_FCP || host_num != pp->sg_id.host_no) -+ if (!pp->mpp) - continue; -- sprintf(rport_id, "rport-%d:%d-%d", -- pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id); -- rport_dev = udev_device_new_from_subsystem_sysname(udev, -- "fc_remote_ports", rport_id); -- if (!rport_dev) { -- condlog(2, "%s: No fc_remote_port device for '%s'", pp->dev, -- rport_id); -- continue; -- } -- pthread_cleanup_push(_udev_device_unref, rport_dev); -- value = udev_device_get_sysattr_value(rport_dev, "port_name"); -- if (!value) -- goto unref; -- -- if (value) -- wwpn = strtol(value, NULL, 16); -- /* -- * If the port wwpn matches sets the path and port state -- * to marginal -- */ -- if (wwpn == els_wwpn) { -- ret = fpin_path_setmarginal(pp); -- if (ret < 0) -- goto unref; -- fpin_set_rport_marginal(rport_dev); -- fpin_add_marginal_dev_info(host_num, pp->dev); -+ /*checks if the bus type is nvme and the protocol is FC-NVMe*/ -+ if ((pp->bus == SYSFS_BUS_NVME) && (pp->sg_id.proto_id == NVME_PROTOCOL_FC)) { -+ fpin_check_set_nvme_path_marginal(host_num, pp, els_wwpn, attached_wwpn); -+ } else if ((pp->bus == SYSFS_BUS_SCSI) && -+ (pp->sg_id.proto_id == SCSI_PROTOCOL_FCP) && -+ (host_num == pp->sg_id.host_no)) { -+ /* Checks the host number and also for the SCSI FCP */ -+ fpin_check_set_scsi_path_marginal(host_num, pp, els_wwpn); - } --unref: -- pthread_cleanup_pop(1); - } - /* walk backwards because reload_and_sync_map() can remove mpp */ - vector_foreach_slot_backwards(vecs->mpvec, mpp, i) { -@@ -286,14 +378,18 @@ fpin_parse_li_els_setpath_marginal(uint16_t host_num, struct fc_tlv_desc *tlv, - struct fc_fn_li_desc *li_desc = (struct fc_fn_li_desc *)tlv; - int count = 0; - int ret = 0; -+ uint64_t attached_wwpn; - - /* Update the wwn to list */ - wwn_count = be32_to_cpu(li_desc->pname_count); -- condlog(4, "Got wwn count as %d\n", wwn_count); -+ attached_wwpn = be64_to_cpu(li_desc->attached_wwpn); -+ condlog(4, "Got wwn count as %d detecting wwn 0x%" PRIx64 -+ " attached_wwpn 0x%" PRIx64 "\n", -+ wwn_count, be64_to_cpu(li_desc->detecting_wwpn), attached_wwpn); - - for (iter = 0; iter < wwn_count; iter++) { - wwpn = be64_to_cpu(li_desc->pname_list[iter]); -- ret = fpin_chk_wwn_setpath_marginal(host_num, vecs, wwpn); -+ ret = fpin_chk_wwn_setpath_marginal(host_num, vecs, wwpn, attached_wwpn); - if (ret < 0) - condlog(2, "failed to set the path marginal associated with wwpn: 0x%" PRIx64 "\n", wwpn); - diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 30c0bbf..5a9b492 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,5 +1,5 @@ Name: device-mapper-multipath -Version: 0.9.6 +Version: 0.9.7 Release: 1%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 @@ -7,62 +7,22 @@ URL: http://christophe.varoqui.free.fr/ # The source for this package was pulled from upstream's git repo. Use the # following command to generate the tarball -# curl -L https://github.com/opensvc/multipath-tools/archive/0.9.6.tar.gz -o multipath-tools-0.9.6.tgz -Source0: multipath-tools-0.9.6.tgz +# curl -L https://github.com/opensvc/multipath-tools/archive/0.9.7.tar.gz -o multipath-tools-0.9.7.tgz +Source0: multipath-tools-0.9.7.tgz Source1: multipath.conf -Patch0001: 0001-libmultipath-sysfs_set_scsi_tmo-do-nothing-for-ACT_D.patch -Patch0002: 0002-libmultipath-add-alias_already_taken.patch -Patch0003: 0003-libmultipath-unify-use_existing_alias-and-get_user_f.patch -Patch0004: 0004-libmultipath-never-allocate-an-alias-that-s-already-.patch -Patch0005: 0005-libmultipath-lookup_binding-add-comment-about-the-al.patch -Patch0006: 0006-multipath-tools-test-simplify-debugging-for-condlog-.patch -Patch0007: 0007-multipath-tools-tests-add-tests-for-get_user_friendl.patch -Patch0008: 0008-multipath-tools-test-consistent-use-of-macros-in-ali.patch -Patch0009: 0009-multipath-tools-tests-convert-mock_-failed-used-_ali.patch -Patch0010: 0010-multipath-tools-test-use-mock_bindings_file-consiste.patch -Patch0011: 0011-libmultipath-add-global-variable-for-current-binding.patch -Patch0012: 0012-libmultipath-rename-fix_bindings_file-to-update_bind.patch -Patch0013: 0013-libmultipath-alias.c-move-bindings-related-code-up.patch -Patch0014: 0014-libmultipath-update_bindings_file-take-filename-argu.patch -Patch0015: 0015-libmultipath-update_bindings_file-use-a-single-write.patch -Patch0016: 0016-libmultipath-update_bindings_file-don-t-log-temp-fil.patch -Patch0017: 0017-libmultipath-alias.c-factor-out-read_binding.patch -Patch0018: 0018-libmultipath-keep-bindings-in-memory.patch -Patch0019: 0019-multipath-tools-tests-fix-alias-tests.patch -Patch0020: 0020-libmultipath-dm_get_uuid-return-emtpy-UUID-for-non-e.patch -Patch0021: 0021-libmultipath-adapt-to-new-semantics-of-dm_get_uuid.patch -Patch0022: 0022-libmultipath-sort-aliases-by-length-and-strcmp.patch -Patch0023: 0023-multipath-tools-tests-fix-alias-test-after-sort-orde.patch -Patch0024: 0024-libmultipath-simplify-get_free_id-assuming-total-ord.patch -Patch0025: 0025-multipath-tools-tests-adapt-alias-tests-for-total-or.patch -Patch0026: 0026-multipath-tools-tests-add-test-for-ordering-of-bindi.patch -Patch0027: 0027-multipathd-watch-bindings-file-with-inotify-timestam.patch -Patch0028: 0028-multipath-tools-tests-mock-pthread_mutex_-lock-unloc.patch -Patch0029: 0029-multipath-tools-Makefile-sanitize-paths-for-configur.patch -Patch0030: 0030-multipath-tools-add-compile-time-configuration-for-e.patch -Patch0031: 0031-multipath-tools-man-pages-generate-with-correct-path.patch -Patch0032: 0032-libdmmp-Makefile-fix-bug-in-install-section.patch -Patch0033: 0033-multipath-tools-README.md-improve-documentation-for-.patch -Patch0034: 0034-libmultipath-print-built-in-values-for-deprecated-op.patch -Patch0035: 0035-multipath-add-a-missing-newline.patch -Patch0036: 0036-multipath-tools-allow-prefixes-with-and-w-o-trailing.patch -Patch0037: 0037-libmultipath-deprecate-bindings_file-wwids_file-prke.patch -Patch0038: 0038-libmultipath-avoid-Warray-bounds-error-in-uatomic-op.patch -Patch0039: 0039-multipath-tools-fix-spelling.patch -Patch0040: 0040-multipathd-Added-support-to-handle-FPIN-Li-events-fo.patch -Patch0041: 0041-RH-fixup-udev-rules-for-redhat.patch -Patch0042: 0042-RH-Remove-the-property-blacklist-exception-builtin.patch -Patch0043: 0043-RH-don-t-start-without-a-config-file.patch -Patch0044: 0044-RH-Fix-nvme-function-missing-argument.patch -Patch0045: 0045-RH-use-rpm-optflags-if-present.patch -Patch0046: 0046-RH-add-mpathconf.patch -Patch0047: 0047-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch -Patch0048: 0048-RH-reset-default-find_mutipaths-value-to-off.patch -Patch0049: 0049-RH-attempt-to-get-ANA-info-via-sysfs-first.patch -Patch0050: 0050-RH-make-parse_vpd_pg83-match-scsi_id-output.patch -Patch0051: 0051-RH-add-scsi-device-handlers-to-modules-load.d.patch -Patch0052: 0052-RH-compile-with-libreadline-support.patch -Patch0053: 0053-RH-Add-mpathcleanup.patch +Patch0001: 0001-RH-fixup-udev-rules-for-redhat.patch +Patch0002: 0002-RH-Remove-the-property-blacklist-exception-builtin.patch +Patch0003: 0003-RH-don-t-start-without-a-config-file.patch +Patch0004: 0004-RH-Fix-nvme-function-missing-argument.patch +Patch0005: 0005-RH-use-rpm-optflags-if-present.patch +Patch0006: 0006-RH-add-mpathconf.patch +Patch0007: 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +Patch0008: 0008-RH-reset-default-find_mutipaths-value-to-off.patch +Patch0009: 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch +Patch0010: 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +Patch0011: 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch +Patch0012: 0012-RH-compile-with-libreadline-support.patch +Patch0013: 0013-RH-Add-mpathcleanup.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -149,7 +109,7 @@ This package contains the files needed to develop applications that use device-mapper-multipath's libdmmp C API library %prep -%autosetup -n multipath-tools-0.9.6 -p1 +%autosetup -n multipath-tools-0.9.7 -p1 cp %{SOURCE1} . %build @@ -212,7 +172,6 @@ fi %config /usr/lib/udev/rules.d/62-multipath.rules %config /usr/lib/udev/rules.d/11-dm-mpath.rules %dir /usr/lib/modules-load.d -/usr/lib/modules-load.d/multipath.conf /usr/lib/modules-load.d/scsi_dh.conf %{_tmpfilesdir}/multipath.conf %doc README.md @@ -272,6 +231,14 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Tue Nov 21 2023 Benjamin Marzinski - 0.9.7-1 +- Update source to upstream version 0.9.7 + * Previous patches 0001-0040 are included in the source tarball +- Rename redhat patches + * Previous patches 0041-0053 are now patches 0001-0013 +- Remove /usr/lib/modules-load.d/multipath.conf + * has been replaced with modprobe@dm_multipath.service unit Wants. + * Fri Sep 22 2023 Benjamin Marzinski - 0.9.6-1 - Update to the head of the upstream staging branch - Rename redhat patches diff --git a/sources b/sources index 5d41f65..89f8f37 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (multipath-tools-0.9.6.tgz) = 17d2b46ead9df6826b3266035bc077a2f4d4bea01e2cd59e32d3917cda40c320f11bc8572da7ba66251e312b46d9be317737069193d481d202d49f9aa5fd71b9 +SHA512 (multipath-tools-0.9.7.tgz) = 0f4c97179a3de5a0c77893fec229eb183293fed8e5e01a9945b261845ccf5d13f8ef2c2ff0c17c9345217d236275caed4765422ec95aed80821f11658bf96e26 SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942 From f52f69af955c7d182060b0ed07f3bda9b0dabd86 Mon Sep 17 00:00:00 2001 From: Paul Donohue Date: Tue, 28 Nov 2023 17:34:41 -0500 Subject: [PATCH 05/29] device-mapper-multipath-0.9.7-2 Modify 0006-RH-add-mpathconf.patch Modify 0008-RH-reset-default-find_mutipaths-value-to-off.patch * Fix find_multipaths values in docs and mpathconf Signed-off-by: Benjamin Marzinski --- 0006-RH-add-mpathconf.patch | 25 ++++++++++--------- ...-default-find_mutipaths-value-to-off.patch | 19 ++++++++++++-- device-mapper-multipath.spec | 7 +++++- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/0006-RH-add-mpathconf.patch b/0006-RH-add-mpathconf.patch index 7782f65..fd47a6c 100644 --- a/0006-RH-add-mpathconf.patch +++ b/0006-RH-add-mpathconf.patch @@ -10,6 +10,7 @@ command line. But, mostly it is used to get a multipath.conf file with the OS defaults, and to enable and disable multipathing via a single command. +Co-authored-by: Paul Donohue Signed-off-by: Benjamin Marzinski --- libmultipath/config.c | 2 + @@ -69,7 +70,7 @@ index 504d6892..9f14036c 100644 diff --git a/multipath/mpathconf b/multipath/mpathconf new file mode 100644 -index 00000000..319664b1 +index 00000000..ce430075 --- /dev/null +++ b/multipath/mpathconf @@ -0,0 +1,658 @@ @@ -106,7 +107,7 @@ index 00000000..319664b1 + +defaults { + user_friendly_names yes -+ find_multipaths yes ++ find_multipaths on +}" + +CONFIGFILE="/etc/multipath.conf" @@ -124,7 +125,7 @@ index 00000000..319664b1 + echo "Disable: --disable" + echo "Only allow certain wwids (instead of enable): --allow " + echo "Set user_friendly_names (Default y): --user_friendly_names " -+ echo "Set find_multipaths (Default y): --find_multipaths " ++ echo "Set find_multipaths (Default on): --find_multipaths " + echo "Set default property blacklist (Default n): --property_blacklist " + echo "Set enable_foreign to show foreign devices (Default n): --enable_foreign " + echo "Set recheck_wwid (Defaut n): --recheck_wwid " @@ -328,11 +329,11 @@ index 00000000..319664b1 + exit 1 + fi + if [ "$FIND" = "y" ]; then -+ FIND="yes" ++ FIND="on" + elif [ "$FIND" = "n" ]; then -+ FIND="no" -+ elif [ -n "$FIND" ] && [ "$FIND" != "yes" -a "$FIND" != "no" -a "$FIND" != "strict" -a "$FIND" != "greedy" -a "$FIND" != "smart" ]; then -+ echo "--find_multipaths must be one of 'yes' 'no' 'strict' 'greedy' or 'smart'" ++ FIND="off" ++ elif [ -n "$FIND" ] && [ "$FIND" != "on" -a "$FIND" != "yes" -a "$FIND" != "off" -a "$FIND" != "no" -a "$FIND" != "strict" -a "$FIND" != "greedy" -a "$FIND" != "smart" ]; then ++ echo "--find_multipaths must be one of 'on' 'yes' 'y' 'off' 'no' 'n' 'strict' 'greedy' or 'smart'" + exit 1 + fi + if [ -n "$PROPERTY" ] && [ "$PROPERTY" != "y" -a "$PROPERTY" != "n" ]; then @@ -497,7 +498,7 @@ index 00000000..319664b1 + echo "multipath is disabled" + fi + if [ -z "$HAVE_FIND" ]; then -+ echo "find_multipaths is no" ++ echo "find_multipaths is off" + else + echo "find_multipaths is $HAVE_FIND" + fi @@ -733,7 +734,7 @@ index 00000000..319664b1 +fi diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8 new file mode 100644 -index 00000000..9c2fb835 +index 00000000..ea025f31 --- /dev/null +++ b/multipath/mpathconf.8 @@ -0,0 +1,151 @@ @@ -779,10 +780,10 @@ index 00000000..9c2fb835 +.B user_friendly_names +set and +.B find_multipaths -+set to \fByes\fP. To disable these, use the ++set to \fBon\fP. To disable these, use the +.B --user_friendly_names n +and -+.B --find_multipaths n ++.B --find_multipaths off +options +.SH COMMANDS +.TP @@ -825,7 +826,7 @@ index 00000000..9c2fb835 +sets an existing \fBrecheck_wwid\fP line to \fBno\fP. This command can be used +along with any other command. +.TP -+.B --find_multipaths\fP { \fByes\fP | \fBno\fP | \fBstrict\fP | \fBgreedy\fP | \fBsmart\fP } ++.B --find_multipaths\fP { \fBon\fP | \fByes\fP | \fBy\fP | \fBoff\fP | \fBno\fP | \fBn\fP | \fBstrict\fP | \fBgreedy\fP | \fBsmart\fP } +If set to \fB\fP, this adds the line +.B find_multipaths +to the diff --git a/0008-RH-reset-default-find_mutipaths-value-to-off.patch b/0008-RH-reset-default-find_mutipaths-value-to-off.patch index 4e1253c..cf7317e 100644 --- a/0008-RH-reset-default-find_mutipaths-value-to-off.patch +++ b/0008-RH-reset-default-find_mutipaths-value-to-off.patch @@ -6,10 +6,12 @@ Subject: [PATCH] RH: reset default find_mutipaths value to off Upstream has changed to default find_multipaths to "strict". For now Redhat will retain the previous default of "off". +Co-authored-by: Paul Donohue Signed-off-by: Benjamin Marzinski --- - libmultipath/defaults.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) + libmultipath/defaults.h | 2 +- + multipath/multipath.conf.5.in | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h index 64b633f2..5bda9f93 100644 @@ -24,3 +26,16 @@ index 64b633f2..5bda9f93 100644 #define DEFAULT_FAST_IO_FAIL 5 #define DEFAULT_DEV_LOSS_TMO 600 #define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_ON +diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in +index 87b3b2a5..8e246571 100644 +--- a/multipath/multipath.conf.5.in ++++ b/multipath/multipath.conf.5.in +@@ -1213,7 +1213,7 @@ as non-multipath and passed on to upper layers. + \fBNote:\fR this may cause delays during device detection if + there are single-path devices which aren\'t blacklisted. + .TP +-The default is: \fBstrict\fR ++The default is: \fBoff\fR + .RE + . + . diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 5a9b492..aea93d7 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.9.7 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ @@ -231,6 +231,11 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Tue Nov 28 2023 Paul Donohue - 0.9.7-2 +- Modify 0006-RH-add-mpathconf.patch +- Modify 0008-RH-reset-default-find_mutipaths-value-to-off.patch + * Fix find_multipaths values in docs and mpathconf + * Tue Nov 21 2023 Benjamin Marzinski - 0.9.7-1 - Update source to upstream version 0.9.7 * Previous patches 0001-0040 are included in the source tarball From 0f3122f75fe934276c0e8672f11b8d0a8abada11 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Wed, 29 Nov 2023 22:24:39 -0500 Subject: [PATCH 06/29] device-mapper-multipath-0.9.7-3 Fix multipath_conf_syntax test Fix restate_module test Fix find_multipaths test --- device-mapper-multipath.spec | 6 +++++- tests/find_multipaths/main.sh | 1 + tests/multipath_conf_syntax/main.sh | 2 +- tests/restate_module/main.sh | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index aea93d7..1fdaa06 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.9.7 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ @@ -231,6 +231,10 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Wed Nov 29 2023 Benjamin Marzinski - 0.9.7-3 +- Fix multipath_conf_syntax test +- Fix restate_module test + * Tue Nov 28 2023 Paul Donohue - 0.9.7-2 - Modify 0006-RH-add-mpathconf.patch - Modify 0008-RH-reset-default-find_mutipaths-value-to-off.patch diff --git a/tests/find_multipaths/main.sh b/tests/find_multipaths/main.sh index a39af79..4d94c87 100755 --- a/tests/find_multipaths/main.sh +++ b/tests/find_multipaths/main.sh @@ -40,6 +40,7 @@ rpm -q device-mapper-multipath || yum install -y device-mapper-multipath # test with find_multipath=y, will not multipath for the single device; reload/start the service to enable the config cleanup trun "rm -f /etc/multipath.conf" +trun "rm -f /etc/multipath/wwids" trun "mpathconf --enable --user_friendly_names y --find_multipaths y --with_multipathd n" sed -i '/^blacklist[[:space:]]*{/ a\ device {\n vendor ".*"\n product ".*"\n } diff --git a/tests/multipath_conf_syntax/main.sh b/tests/multipath_conf_syntax/main.sh index 331d65e..fb303c3 100755 --- a/tests/multipath_conf_syntax/main.sh +++ b/tests/multipath_conf_syntax/main.sh @@ -119,7 +119,7 @@ tok "multipath -ll | grep mypath" # test wrong alias keyword trun "sed -i 's/alias.*$/alia mypath/g' /etc/multipath.conf" -tok "multipath 2>&1 | grep 'invalid keyword: alia'" +tok "multipath 2>&1 | grep 'invalid keyword in the multipath section: alia'" trun "multipath -r" tok "multipath -ll | grep mpath" trun "sed -i 's/alia.*$/alias mypath/g' /etc/multipath.conf" diff --git a/tests/restate_module/main.sh b/tests/restate_module/main.sh index 7f3279d..565e59c 100755 --- a/tests/restate_module/main.sh +++ b/tests/restate_module/main.sh @@ -69,7 +69,7 @@ tlog "Checking if active path count equals 2" assert "[[ $pathcount -eq 2 ]]" tlog "offline one path device" -pathname=`multipathd show paths raw format "%d %m" | grep ${mpathdev} | head -1 | awk '{print $1}'` +pathname=`multipathd show paths raw format "%d %m %p" | grep ${mpathdev} | sort -k 3n | head -1 | awk '{print $1}'` tlog "path to offline: ${pathname}" trun "echo 'offline' > /sys/block/${pathname}/device/state" tlog "waiting for multipathd to fail path" From b0b20d4f7b4de67597a1db368eb183c938714547 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Thu, 30 Nov 2023 16:30:05 -0500 Subject: [PATCH 07/29] device-mapper-multipath-0.9.7-4 Use modulesloaddir macro for installing scsi_dh.conf --- device-mapper-multipath.spec | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 1fdaa06..2a92a06 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.9.7 -Release: 3%{?dist} +Release: 4%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ @@ -171,8 +171,8 @@ fi %{_mandir}/man8/mpathpersist.8* %config /usr/lib/udev/rules.d/62-multipath.rules %config /usr/lib/udev/rules.d/11-dm-mpath.rules -%dir /usr/lib/modules-load.d -/usr/lib/modules-load.d/scsi_dh.conf +%dir %{_modulesloaddir} +%{_modulesloaddir}/scsi_dh.conf %{_tmpfilesdir}/multipath.conf %doc README.md %doc multipath.conf @@ -231,6 +231,9 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Thu Nov 30 2023 Benjamin Marzinski - 0.9.7-4 +- Use modulesloaddir macro for installing scsi_dh.conf + * Wed Nov 29 2023 Benjamin Marzinski - 0.9.7-3 - Fix multipath_conf_syntax test - Fix restate_module test From 835a8a43de1620fcb450510713cbdeb859b318d5 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Tue, 16 Jan 2024 22:54:08 -0500 Subject: [PATCH 08/29] device-mapper-multipath-0.9.7-5 Add 0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch * Fix auto_resize code to avoid a segfault Add 0015-multipathd-fix-auto-resize-configuration.patch * Fix auto_resize default value --- ...ull-pointer-dereference-in-uev_updat.patch | 27 ++++++++++++ ...ipathd-fix-auto-resize-configuration.patch | 42 +++++++++++++++++++ device-mapper-multipath.spec | 10 ++++- 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch create mode 100644 0015-multipathd-fix-auto-resize-configuration.patch diff --git a/0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch b/0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch new file mode 100644 index 0000000..7655591 --- /dev/null +++ b/0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 16 Jan 2024 00:54:37 -0500 +Subject: [PATCH] multipathd: fix null pointer dereference in uev_update_path + +The Auto-resize code added a check that deferences pp->mpp without +checking that it's non-NULL. Fix it. + +Fixes: 981b83ad1 ("multipathd: Add auto_resize config option") +Signed-off-by: Benjamin Marzinski +--- + multipathd/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index 230c9d10..57c04364 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -1653,7 +1653,7 @@ uev_update_path (struct uevent *uev, struct vectors * vecs) + } + } + } +- if (auto_resize != AUTO_RESIZE_NEVER && ++ if (auto_resize != AUTO_RESIZE_NEVER && mpp && + !mpp->wait_for_udev) { + struct pathgroup *pgp; + struct path *pp2; diff --git a/0015-multipathd-fix-auto-resize-configuration.patch b/0015-multipathd-fix-auto-resize-configuration.patch new file mode 100644 index 0000000..35e4d48 --- /dev/null +++ b/0015-multipathd-fix-auto-resize-configuration.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 16 Jan 2024 01:11:02 -0500 +Subject: [PATCH] multipathd: fix auto-resize configuration + +The code acted like AUTO_RESIZE_UNDEFINED didn't exist, but since +conf->auto_resize was never set to AUTO_RESIZE_NEVER, the default was in +fact AUTO_RESIZE_UNDEFINED, which ended up getting treated like +AUTO_RESIZE_GROW_SHRINK. Remove AUTO_RESIZE_UNDEFINED and explicitly +default auto_resize tp AUTO_RESIZE_NEVER. + +Fixes: 981b83ad1 ("multipathd: Add auto_resize config option") +Signed-off-by: Benjamin Marzinski +--- + libmultipath/config.c | 1 + + libmultipath/structs.h | 1 - + 2 files changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/config.c b/libmultipath/config.c +index 4544f484..3d5943d3 100644 +--- a/libmultipath/config.c ++++ b/libmultipath/config.c +@@ -927,6 +927,7 @@ int _init_config (const char *file, struct config *conf) + conf->retrigger_tries = DEFAULT_RETRIGGER_TRIES; + conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY; + conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT; ++ conf->auto_resize = DEFAULT_AUTO_RESIZE; + conf->remove_retries = 0; + conf->ghost_delay = DEFAULT_GHOST_DELAY; + conf->all_tg_pt = DEFAULT_ALL_TG_PT; +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index a1aac1b4..734905e2 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -180,7 +180,6 @@ enum queue_mode_states { + }; + + enum auto_resize_state { +- AUTO_RESIZE_UNDEF = 0, + AUTO_RESIZE_NEVER, + AUTO_RESIZE_GROW_ONLY, + AUTO_RESIZE_GROW_SHRINK, diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 2a92a06..b448595 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.9.7 -Release: 4%{?dist} +Release: 5%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ @@ -23,6 +23,8 @@ Patch0010: 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch Patch0011: 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch Patch0012: 0012-RH-compile-with-libreadline-support.patch Patch0013: 0013-RH-Add-mpathcleanup.patch +Patch0014: 0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch +Patch0015: 0015-multipathd-fix-auto-resize-configuration.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -231,6 +233,12 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Tue Jan 16 2024 Benjamin Marzinski - 0.9.7-5 +- Add 0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch + * Fix auto_resize code to avoid a segfault +- Add 0015-multipathd-fix-auto-resize-configuration.patch + * Fix auto_resize default value + * Thu Nov 30 2023 Benjamin Marzinski - 0.9.7-4 - Use modulesloaddir macro for installing scsi_dh.conf From c9568c86e6bd6a57461f3ca10225a45b57a664ca Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Fri, 19 Jan 2024 17:03:18 +0000 Subject: [PATCH 09/29] Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild --- device-mapper-multipath.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index b448595..2b4e20d 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.9.7 -Release: 5%{?dist} +Release: 6%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ @@ -233,6 +233,9 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Fri Jan 19 2024 Fedora Release Engineering - 0.9.7-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + * Tue Jan 16 2024 Benjamin Marzinski - 0.9.7-5 - Add 0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch * Fix auto_resize code to avoid a segfault From 6956fa4aa7f800ccf59fd8d4569975fd36fd9f11 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Wed, 24 Jan 2024 09:20:08 +0000 Subject: [PATCH 10/29] Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild --- device-mapper-multipath.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 2b4e20d..3cf8fb0 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.9.7 -Release: 6%{?dist} +Release: 7%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ @@ -233,6 +233,9 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Wed Jan 24 2024 Fedora Release Engineering - 0.9.7-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + * Fri Jan 19 2024 Fedora Release Engineering - 0.9.7-6 - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild From 6496193f3f25e1033cd68e6248baaa16bd4bf4ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 17 Apr 2024 22:49:31 +0200 Subject: [PATCH 11/29] Stop harcoding paths Preparation for https://fedoraproject.org/wiki/Changes/Unify_bin_and_sbin. Packages must honour macros for directories, in particular %_sbindir may be set to /usr/bin. --- device-mapper-multipath.spec | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 3cf8fb0..78bef5a 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -115,7 +115,6 @@ device-mapper-multipath's libdmmp C API library cp %{SOURCE1} . %build -%define _sbindir /usr/sbin %define _libdir /usr/%{_lib} %define _libmpathdir %{_libdir}/multipath %define _pkgconfdir %{_libdir}/pkgconfig @@ -146,7 +145,7 @@ rm -rf %{buildroot}/%{_initrddir} %postun if [ $1 -ge 1 ] ; then - /sbin/multipathd forcequeueing daemon > /dev/null 2>&1 || : + multipathd forcequeueing daemon > /dev/null 2>&1 || : fi %systemd_postun_with_restart multipathd.service From 588b3f63e9e24d8b4e5e810601fd417301f95e5a Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Mon, 20 May 2024 22:01:48 -0400 Subject: [PATCH 12/29] device-mapper-multipath-0.9.8-1 Update source to upstream version 0.9.8 plus latest staging branch * Previous patches 0014 & 0015 are included in the source tarball * patches 0001-0044 are from the upstream staging branch. Rename redhat patches * Previous patches 0001-0013 are now patches 0045-0057 --- .gitignore | 1 + ...s-fix-misspelled-DM_UDEV_DISABLE_OTH.patch | 27 ++ ...ondlog-level-for-setscheduler-error-.patch | 27 ++ ...e-multipathd-scheduling-configurable.patch | 87 +++++ ...til-really-always-use-glibc-basename.patch | 144 ++++++++ ...multipathd-set-priority-to-RLIMIT_RT.patch | 134 +++++++ ...PUWeight-to-1000-and-LimitRTPRIO-to-.patch | 33 ++ ...s-explain-logic-for-device-becoming-.patch | 30 ++ ...s-don-t-import-DM_NOSCAN-from-udev-d.patch | 37 ++ ...s-don-t-import-ID_FS_VERSION-from-ud.patch | 27 ++ ...s-adapt-MPATH_DEVICE_READY-0-logic-t.patch | 67 ++++ ...s-adapt-coldplug-event-handling-ro-1.patch | 43 +++ ...s-don-t-import-properties-with-new-1.patch | 36 ++ ...s-replace-DM_SUSPENDED-by-.DM_SUSPEN.patch | 75 ++++ ...ules-replace-DM_NOSCAN-by-.DM_NOSCAN.patch | 55 +++ ...ull-pointer-dereference-in-uev_updat.patch | 27 -- ...path.rules-simplify-PATH_FAILED-case.patch | 38 ++ ...ipathd-fix-auto-resize-configuration.patch | 42 --- ...ules-make-label-names-more-intuitive.patch | 109 ++++++ 0017-kpartx.rules-ignore-DM_SUSPENDED.patch | 29 ++ ...tests-fix-CI-failures-on-arm-v7-with.patch | 270 ++++++++++++++ ...tests-fix-CI-failures-with-clang-on-.patch | 246 +++++++++++++ ...GitHub-actions-fixes-for-spelling-CI.patch | 31 ++ ...-run-workflows-if-workflow-file-has-.patch | 146 ++++++++ 0022-multipath-tools-add-TGTDIR-option.patch | 106 ++++++ ...ath-move-get_udev_for_mpp-to-sysfs.c.patch | 87 +++++ ...ibmultipath-add-mp_find_path_by_devt.patch | 60 +++ ...ath-fix-max_sectors_kb-on-adding-pat.patch | 33 ++ ...y-set-max_sectors_kb-on-map-creation.patch | 122 ++++++ ...th-set-max_sectors_kb-in-adopt_paths.patch | 233 ++++++++++++ ...-wildcard-k-for-printing-max_sectors.patch | 89 +++++ ...-update-documentation-for-max_sector.patch | 57 +++ ...th-tools-simplify-comment-in-hwtable.patch | 34 ++ ...tools-unify-text-in-multipath.conf.5.patch | 75 ++++ ...ltipath-tools-update-man-pages-dates.patch | 86 +++++ 0033-libmultipath-export-partmap_in_use.patch | 53 +++ ...nge-flush_on_last_del-to-fix-a-multi.patch | 346 ++++++++++++++++++ ...ove-redundant-config-option-from-Inf.patch | 31 ++ ...-dev_loss_tmo-to-avoid-race-with-no_.patch | 40 ++ ...x-deferred_remove-function-arguments.patch | 107 ++++++ ...e-bitwise-flags-for-map-flushing-API.patch | 212 +++++++++++ ...e-bitwise-flags-for-dm_simplecmd-API.patch | 117 ++++++ ...dd-argument-names-to-some-prototypes.patch | 34 ++ 0041-libmultipath-bump-version-to-0.9.9.patch | 27 ++ ...kflows-native.yaml-run-for-Fedora-40.patch | 24 ++ 0043-update-NEWS.md.patch | 134 +++++++ ...ultipath.conf.5.in-fix-man-page-date.patch | 24 ++ ... 0045-RH-fixup-udev-rules-for-redhat.patch | 16 +- ...property-blacklist-exception-builtin.patch | 6 +- ...RH-don-t-start-without-a-config-file.patch | 20 +- ...H-Fix-nvme-function-missing-argument.patch | 0 ... 0049-RH-use-rpm-optflags-if-present.patch | 10 +- ...hconf.patch => 0050-RH-add-mpathconf.patch | 13 +- ...om-kernel-cmdline-mpath.wwids-with-A.patch | 10 +- ...-default-find_mutipaths-value-to-off.patch | 6 +- ...empt-to-get-ANA-info-via-sysfs-first.patch | 0 ...-parse_vpd_pg83-match-scsi_id-output.patch | 18 +- ...si-device-handlers-to-modules-load.d.patch | 2 +- ...-RH-compile-with-libreadline-support.patch | 2 +- ...up.patch => 0057-RH-Add-mpathcleanup.patch | 8 +- device-mapper-multipath.spec | 91 ++++- sources | 2 +- 62 files changed, 3951 insertions(+), 145 deletions(-) create mode 100644 0001-11-dm-mpath.rules-fix-misspelled-DM_UDEV_DISABLE_OTH.patch create mode 100644 0002-multipathd-use-condlog-level-for-setscheduler-error-.patch create mode 100644 0003-multipathd-make-multipathd-scheduling-configurable.patch create mode 100644 0004-libmpathutil-really-always-use-glibc-basename.patch create mode 100644 0005-multipathd-make-multipathd-set-priority-to-RLIMIT_RT.patch create mode 100644 0006-multipathd-Set-CPUWeight-to-1000-and-LimitRTPRIO-to-.patch create mode 100644 0007-11-dm-mpath.rules-explain-logic-for-device-becoming-.patch create mode 100644 0008-11-dm-mpath.rules-don-t-import-DM_NOSCAN-from-udev-d.patch create mode 100644 0009-11-dm-mpath.rules-don-t-import-ID_FS_VERSION-from-ud.patch create mode 100644 0010-11-dm-mpath.rules-adapt-MPATH_DEVICE_READY-0-logic-t.patch create mode 100644 0011-11-dm-mpath.rules-adapt-coldplug-event-handling-ro-1.patch create mode 100644 0012-11-dm-mpath.rules-don-t-import-properties-with-new-1.patch create mode 100644 0013-11-dm-mpath.rules-replace-DM_SUSPENDED-by-.DM_SUSPEN.patch create mode 100644 0014-11-dm-mpath.rules-replace-DM_NOSCAN-by-.DM_NOSCAN.patch delete mode 100644 0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch create mode 100644 0015-11-dm-mpath.rules-simplify-PATH_FAILED-case.patch delete mode 100644 0015-multipathd-fix-auto-resize-configuration.patch create mode 100644 0016-11-dm-mpath.rules-make-label-names-more-intuitive.patch create mode 100644 0017-kpartx.rules-ignore-DM_SUSPENDED.patch create mode 100644 0018-multipath-tools-tests-fix-CI-failures-on-arm-v7-with.patch create mode 100644 0019-multipath-tools-tests-fix-CI-failures-with-clang-on-.patch create mode 100644 0020-GitHub-actions-fixes-for-spelling-CI.patch create mode 100644 0021-GitHub-workflows-run-workflows-if-workflow-file-has-.patch create mode 100644 0022-multipath-tools-add-TGTDIR-option.patch create mode 100644 0023-libmultipath-move-get_udev_for_mpp-to-sysfs.c.patch create mode 100644 0024-libmultipath-add-mp_find_path_by_devt.patch create mode 100644 0025-Revert-libmultipath-fix-max_sectors_kb-on-adding-pat.patch create mode 100644 0026-libmultipath-Only-set-max_sectors_kb-on-map-creation.patch create mode 100644 0027-libmultipath-set-max_sectors_kb-in-adopt_paths.patch create mode 100644 0028-libmultipath-add-wildcard-k-for-printing-max_sectors.patch create mode 100644 0029-multipath.conf-5-update-documentation-for-max_sector.patch create mode 100644 0030-multipath-tools-simplify-comment-in-hwtable.patch create mode 100644 0031-multipath-tools-unify-text-in-multipath.conf.5.patch create mode 100644 0032-multipath-tools-update-man-pages-dates.patch create mode 100644 0033-libmultipath-export-partmap_in_use.patch create mode 100644 0034-libmultipath-change-flush_on_last_del-to-fix-a-multi.patch create mode 100644 0035-libmultipath-remove-redundant-config-option-from-Inf.patch create mode 100644 0036-libmultipath-pad-dev_loss_tmo-to-avoid-race-with-no_.patch create mode 100644 0037-libmultipath-fix-deferred_remove-function-arguments.patch create mode 100644 0038-libmultipath-use-bitwise-flags-for-map-flushing-API.patch create mode 100644 0039-libmultipath-use-bitwise-flags-for-dm_simplecmd-API.patch create mode 100644 0040-libmultipath-add-argument-names-to-some-prototypes.patch create mode 100644 0041-libmultipath-bump-version-to-0.9.9.patch create mode 100644 0042-GitHub-Workflows-native.yaml-run-for-Fedora-40.patch create mode 100644 0043-update-NEWS.md.patch create mode 100644 0044-multipath.conf.5.in-fix-man-page-date.patch rename 0001-RH-fixup-udev-rules-for-redhat.patch => 0045-RH-fixup-udev-rules-for-redhat.patch (86%) rename 0002-RH-Remove-the-property-blacklist-exception-builtin.patch => 0046-RH-Remove-the-property-blacklist-exception-builtin.patch (96%) rename 0003-RH-don-t-start-without-a-config-file.patch => 0047-RH-don-t-start-without-a-config-file.patch (92%) rename 0004-RH-Fix-nvme-function-missing-argument.patch => 0048-RH-Fix-nvme-function-missing-argument.patch (100%) rename 0005-RH-use-rpm-optflags-if-present.patch => 0049-RH-use-rpm-optflags-if-present.patch (87%) rename 0006-RH-add-mpathconf.patch => 0050-RH-add-mpathconf.patch (98%) rename 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch => 0051-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch (96%) rename 0008-RH-reset-default-find_mutipaths-value-to-off.patch => 0052-RH-reset-default-find_mutipaths-value-to-off.patch (91%) rename 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch => 0053-RH-attempt-to-get-ANA-info-via-sysfs-first.patch (100%) rename 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch => 0054-RH-make-parse_vpd_pg83-match-scsi_id-output.patch (84%) rename 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch => 0055-RH-add-scsi-device-handlers-to-modules-load.d.patch (96%) rename 0012-RH-compile-with-libreadline-support.patch => 0056-RH-compile-with-libreadline-support.patch (96%) rename 0013-RH-Add-mpathcleanup.patch => 0057-RH-Add-mpathcleanup.patch (96%) diff --git a/.gitignore b/.gitignore index f698d08..80e9936 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ multipath-tools-091027.tar.gz /multipath-tools-0.9.5.tgz /multipath-tools-0.9.6.tgz /multipath-tools-0.9.7.tgz +/multipath-tools-0.9.8.tgz diff --git a/0001-11-dm-mpath.rules-fix-misspelled-DM_UDEV_DISABLE_OTH.patch b/0001-11-dm-mpath.rules-fix-misspelled-DM_UDEV_DISABLE_OTH.patch new file mode 100644 index 0000000..4b9d7fc --- /dev/null +++ b/0001-11-dm-mpath.rules-fix-misspelled-DM_UDEV_DISABLE_OTH.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 1 Mar 2024 18:16:32 +0100 +Subject: [PATCH] 11-dm-mpath.rules: fix misspelled + DM_UDEV_DISABLE_OTHER_RULES_FLAG + +Fixes: b3582da ("11-dm-mpath.rules: use import logic like 13-dm-disk.rules") +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipath/11-dm-mpath.rules.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in +index d364f9bc..d9585abf 100644 +--- a/multipath/11-dm-mpath.rules.in ++++ b/multipath/11-dm-mpath.rules.in +@@ -116,7 +116,7 @@ LABEL="scan_import" + ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}!="1", GOTO="import_end" + + # Don't import the properties from db if we will run blkid later. +-ENV{DM_NOSCAN}!="1", ENV{DM_DISABLE_OTHER_RULES_FLAG}!="1", GOTO="import_end" ++ENV{DM_NOSCAN}!="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}!="1", GOTO="import_end" + + IMPORT{db}="ID_FS_TYPE" + IMPORT{db}="ID_FS_USAGE" diff --git a/0002-multipathd-use-condlog-level-for-setscheduler-error-.patch b/0002-multipathd-use-condlog-level-for-setscheduler-error-.patch new file mode 100644 index 0000000..8a6ff99 --- /dev/null +++ b/0002-multipathd-use-condlog-level-for-setscheduler-error-.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 1 Mar 2024 19:37:29 -0500 +Subject: [PATCH] multipathd: use condlog level for setscheduler error message + +condlog uses its own log levels, so LOG_WARNING makes no sense. It +actually translates to a message sent at the LOG_DEBUG level. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + multipathd/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index 6193e691..85ac540f 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -3178,7 +3178,7 @@ setscheduler (void) + res = sched_setscheduler (0, SCHED_RR, &sched_param); + + if (res == -1) +- condlog(LOG_WARNING, "Could not set SCHED_RR at priority 99"); ++ condlog(2, "Could not set SCHED_RR at priority 99"); + return; + } + diff --git a/0003-multipathd-make-multipathd-scheduling-configurable.patch b/0003-multipathd-make-multipathd-scheduling-configurable.patch new file mode 100644 index 0000000..8529152 --- /dev/null +++ b/0003-multipathd-make-multipathd-scheduling-configurable.patch @@ -0,0 +1,87 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 1 Mar 2024 19:37:30 -0500 +Subject: [PATCH] multipathd: make multipathd scheduling configurable + +Currently multipathd always tries to run as a realtime process with a +priority of 99. This is excessive. As a first step towards fixing this, +make it possible at compile time to lower the priority or keep +multipathd from making itself a realtime process. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + Makefile.inc | 6 ++++++ + README.md | 3 +++ + multipathd/Makefile | 3 +++ + multipathd/main.c | 5 +++-- + 4 files changed, 15 insertions(+), 2 deletions(-) + +diff --git a/Makefile.inc b/Makefile.inc +index 5668e638..6d206281 100644 +--- a/Makefile.inc ++++ b/Makefile.inc +@@ -18,6 +18,12 @@ READLINE := + # SCSI_DH_MODULES_PRELOAD := scsi_dh_alua scsi_dh_rdac + SCSI_DH_MODULES_PRELOAD := + ++# Multipathd scheduling priority. Set value from 1 to 99 to make multipathd ++# change its scheduling policy to SCHED_RR and its priority to the specified ++# value. set to 0 to stop multipathd from changing the scheduling policy and ++# priority it was started with. ++SCHED_RT_PRIO := 99 ++ + EXTRAVERSION := $(shell rev=$$(git rev-parse --short=7 HEAD 2>/dev/null); echo $${rev:+-g$$rev}) + + # PKG_CONFIG must be read from the environment to enable compilation +diff --git a/README.md b/README.md +index d4f35f57..bb41bf0e 100644 +--- a/README.md ++++ b/README.md +@@ -98,6 +98,9 @@ The following variables can be passed to the `make` command line: + By default, command line editing is disabled. + Note that using libreadline may + [make binary indistributable due to license incompatibility](https://github.com/opensvc/multipath-tools/issues/36). ++ * `SCHED_RT_PRIO={0-99}`: for values {1-99} set the realtime priority ++ multipathd will attempt to run with. for value 0, disable multipathd ++ changing itself to a realtime process. + * `ENABLE_LIBDMMP=0`: disable building libdmmp + * `ENABLE_DMEVENTS_POLL=0`: disable support for the device-mapper event + polling API. For use with pre-5.0 kernels that don't support dmevent polling +diff --git a/multipathd/Makefile b/multipathd/Makefile +index 997b40cf..7300f07a 100644 +--- a/multipathd/Makefile ++++ b/multipathd/Makefile +@@ -57,6 +57,9 @@ $(CLI): $(CLI_OBJS) + cli_handlers.o: cli_handlers.c + $(Q)$(CC) $(CPPFLAGS) $(CFLAGS) -Wno-unused-parameter -c -o $@ $< + ++main.o: main.c ++ $(Q)$(CC) $(CPPFLAGS) -DSCHED_RT_PRIO=$(SCHED_RT_PRIO) $(CFLAGS) -c -o $@ $< ++ + install: + $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) + $(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir) +diff --git a/multipathd/main.c b/multipathd/main.c +index 85ac540f..9486a8a3 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -3172,7 +3172,7 @@ setscheduler (void) + { + int res; + static struct sched_param sched_param = { +- .sched_priority = 99 ++ .sched_priority = SCHED_RT_PRIO + }; + + res = sched_setscheduler (0, SCHED_RR, &sched_param); +@@ -3471,7 +3471,8 @@ child (__attribute__((unused)) void *param) + if (!vecs) + goto failed; + +- setscheduler(); ++ if (SCHED_RT_PRIO) ++ setscheduler(); + set_oom_adj(); + #ifdef FPIN_EVENT_HANDLER + if (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN) diff --git a/0004-libmpathutil-really-always-use-glibc-basename.patch b/0004-libmpathutil-really-always-use-glibc-basename.patch new file mode 100644 index 0000000..78f8859 --- /dev/null +++ b/0004-libmpathutil-really-always-use-glibc-basename.patch @@ -0,0 +1,144 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 3 Apr 2024 18:55:54 +0200 +Subject: [PATCH] libmpathutil: really always use glibc basename() + +Despite 03a5456 ("libmultipath: always use glibc basename()"), we +still call the system library's basename() from libmultipath. +musl libc until 1.24 provided a prototype for basename() in string.h, +which was not correct and was resolved to the destructive POSIX +basename(). musl libc 1.25 removed this prototype. + +While the remaining code path doesn't strictly depend on the non-destructive +behavior of glibc's basename(), it's cleaner and safer to use the same +implementation everywhere. + +Fixes: 03a5456 ("libmultipath: always use glibc basename()") +Fixes: https://github.com/opensvc/multipath-tools/pull/84 + +Signed-off-by: Martin Wilck +Reviewed-by: Khem Raj +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmpathutil/libmpathutil.version | 4 ++++ + libmpathutil/util.c | 5 +---- + libmpathutil/util.h | 5 +++++ + tests/util.c | 31 +++++++++++++++++++++++++++++++ + 4 files changed, 41 insertions(+), 4 deletions(-) + +diff --git a/libmpathutil/libmpathutil.version b/libmpathutil/libmpathutil.version +index 80d64a3e..fee74a32 100644 +--- a/libmpathutil/libmpathutil.version ++++ b/libmpathutil/libmpathutil.version +@@ -129,3 +129,7 @@ LIBMPATHUTIL_2.0 { + vector_move_up; + vector_sort; + }; ++ ++LIBMPATHUTIL_2.1 { ++ libmp_basename; ++}; +diff --git a/libmpathutil/util.c b/libmpathutil/util.c +index 9d147fca..23d303f9 100644 +--- a/libmpathutil/util.c ++++ b/libmpathutil/util.c +@@ -32,18 +32,15 @@ strchop(char *str) + return i; + } + +-#ifndef __GLIBC__ + /* + * glibc's non-destructive version of basename() + * License: LGPL-2.1-or-later + */ +-static const char *__basename(const char *filename) ++const char *libmp_basename(const char *filename) + { + char *p = strrchr(filename, '/'); + return p ? p + 1 : filename; + } +-#define basename(x) __basename(x) +-#endif + + int + basenamecpy (const char *src, char *dst, size_t size) +diff --git a/libmpathutil/util.h b/libmpathutil/util.h +index de9fcfdd..4997fed6 100644 +--- a/libmpathutil/util.h ++++ b/libmpathutil/util.h +@@ -12,6 +12,11 @@ + #include + + size_t strchop(char *); ++ ++const char *libmp_basename(const char *filename); ++#ifndef __GLIBC__ ++#define basename(x) libmp_basename(x) ++#endif + int basenamecpy (const char *src, char *dst, size_t size); + int filepresent (const char *run); + char *get_next_string(char **temp, const char *split_char); +diff --git a/tests/util.c b/tests/util.c +index d6083dce..4850ddcb 100644 +--- a/tests/util.c ++++ b/tests/util.c +@@ -16,6 +16,7 @@ + * + */ + ++#define _GNU_SOURCE + #include + #include + #include +@@ -23,6 +24,7 @@ + #include + #include + #include ++#include + #include "util.h" + + #include "globals.c" +@@ -163,6 +165,34 @@ static int test_basenamecpy(void) + return cmocka_run_group_tests(tests, NULL, NULL); + } + ++static void test_basename_01(void **state) ++{ ++ const char *path = "/foo/bar"; ++ const char *base; ++ ++ base = basename(path); ++ assert_string_equal(base, "bar"); ++ assert_string_equal(path, "/foo/bar"); ++} ++ ++static void test_basename_02(void **state) ++{ ++ const char *path = "/foo/bar/"; ++ const char *base; ++ ++ base = basename(path); ++ assert_string_equal(base, ""); ++ assert_string_equal(path, "/foo/bar/"); ++} ++ ++static int test_basename(void) { ++ const struct CMUnitTest tests[] = { ++ cmocka_unit_test(test_basename_01), ++ cmocka_unit_test(test_basename_02), ++ }; ++ return cmocka_run_group_tests(tests, NULL, NULL); ++} ++ + /* + * On big endian systems, if bitfield_t is 32bit, we need + * to swap the two 32 bit parts of a 64bit value to make +@@ -946,6 +976,7 @@ int main(void) + + init_test_verbosity(-1); + ret += test_basenamecpy(); ++ ret += test_basename(); + ret += test_bitmasks(); + ret += test_strlcpy(); + ret += test_strlcat(); diff --git a/0005-multipathd-make-multipathd-set-priority-to-RLIMIT_RT.patch b/0005-multipathd-make-multipathd-set-priority-to-RLIMIT_RT.patch new file mode 100644 index 0000000..fd12767 --- /dev/null +++ b/0005-multipathd-make-multipathd-set-priority-to-RLIMIT_RT.patch @@ -0,0 +1,134 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 9 Apr 2024 18:56:12 -0400 +Subject: [PATCH] multipathd: make multipathd set priority to RLIMIT_RTPRIO + +With this change, if the SCHED_RT_PRIO compiler flag has been removed. +Instead multipathd will call getrlimit(RLIMIT_RTPRIO, ...) and look at +the hard limit. It it's 0, multipath will do nothing. Otherwise it will +change its scheduling policy to SCHED_RR and its priority to the hard +limit. + +This allows users to change the priority of that multipathd runs with by +adding + +LimitRTPRIO= + +to the [Service] section of the multipathd.service unit file. Setting +LimitRTPRIO=0 will make multipathd run as a normal process, while +setting LimitRTPRIO=infinity will make it use the maximum SCHED_RR prio, +which is 99. + +To keep the existing behavior, multipathd.service now sets +LimitRTPRIO=infinity + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + Makefile.inc | 6 ------ + README.md | 3 --- + multipathd/Makefile | 3 --- + multipathd/main.c | 22 +++++++++++++++------- + multipathd/multipathd.service.in | 1 + + 5 files changed, 16 insertions(+), 19 deletions(-) + +diff --git a/Makefile.inc b/Makefile.inc +index 6d206281..5668e638 100644 +--- a/Makefile.inc ++++ b/Makefile.inc +@@ -18,12 +18,6 @@ READLINE := + # SCSI_DH_MODULES_PRELOAD := scsi_dh_alua scsi_dh_rdac + SCSI_DH_MODULES_PRELOAD := + +-# Multipathd scheduling priority. Set value from 1 to 99 to make multipathd +-# change its scheduling policy to SCHED_RR and its priority to the specified +-# value. set to 0 to stop multipathd from changing the scheduling policy and +-# priority it was started with. +-SCHED_RT_PRIO := 99 +- + EXTRAVERSION := $(shell rev=$$(git rev-parse --short=7 HEAD 2>/dev/null); echo $${rev:+-g$$rev}) + + # PKG_CONFIG must be read from the environment to enable compilation +diff --git a/README.md b/README.md +index bb41bf0e..d4f35f57 100644 +--- a/README.md ++++ b/README.md +@@ -98,9 +98,6 @@ The following variables can be passed to the `make` command line: + By default, command line editing is disabled. + Note that using libreadline may + [make binary indistributable due to license incompatibility](https://github.com/opensvc/multipath-tools/issues/36). +- * `SCHED_RT_PRIO={0-99}`: for values {1-99} set the realtime priority +- multipathd will attempt to run with. for value 0, disable multipathd +- changing itself to a realtime process. + * `ENABLE_LIBDMMP=0`: disable building libdmmp + * `ENABLE_DMEVENTS_POLL=0`: disable support for the device-mapper event + polling API. For use with pre-5.0 kernels that don't support dmevent polling +diff --git a/multipathd/Makefile b/multipathd/Makefile +index 7300f07a..997b40cf 100644 +--- a/multipathd/Makefile ++++ b/multipathd/Makefile +@@ -57,9 +57,6 @@ $(CLI): $(CLI_OBJS) + cli_handlers.o: cli_handlers.c + $(Q)$(CC) $(CPPFLAGS) $(CFLAGS) -Wno-unused-parameter -c -o $@ $< + +-main.o: main.c +- $(Q)$(CC) $(CPPFLAGS) -DSCHED_RT_PRIO=$(SCHED_RT_PRIO) $(CFLAGS) -c -o $@ $< +- + install: + $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) + $(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir) +diff --git a/multipathd/main.c b/multipathd/main.c +index 9486a8a3..dd17d5c3 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -3171,14 +3171,23 @@ static void + setscheduler (void) + { + int res; +- static struct sched_param sched_param = { +- .sched_priority = SCHED_RT_PRIO +- }; ++ static struct sched_param sched_param; ++ struct rlimit rlim; ++ ++ if (getrlimit(RLIMIT_RTPRIO, &rlim) < 0 || rlim.rlim_max == 0) ++ return; ++ ++ sched_param.sched_priority = rlim.rlim_max > INT_MAX ? INT_MAX : ++ rlim.rlim_max; ++ res = sched_get_priority_max(SCHED_RR); ++ if (res > 0 && res < sched_param.sched_priority) ++ sched_param.sched_priority = res; + +- res = sched_setscheduler (0, SCHED_RR, &sched_param); ++ res = sched_setscheduler(0, SCHED_RR, &sched_param); + + if (res == -1) +- condlog(2, "Could not set SCHED_RR at priority 99"); ++ condlog(2, "Could not set SCHED_RR at priority %d", ++ sched_param.sched_priority); + return; + } + +@@ -3471,8 +3480,7 @@ child (__attribute__((unused)) void *param) + if (!vecs) + goto failed; + +- if (SCHED_RT_PRIO) +- setscheduler(); ++ setscheduler(); + set_oom_adj(); + #ifdef FPIN_EVENT_HANDLER + if (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN) +diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in +index 6d03ff71..18bb367e 100644 +--- a/multipathd/multipathd.service.in ++++ b/multipathd/multipathd.service.in +@@ -19,6 +19,7 @@ NotifyAccess=main + ExecStart=/sbin/multipathd -d -s + ExecReload=/sbin/multipathd reconfigure + TasksMax=infinity ++LimitRTPRIO=infinity + + [Install] + WantedBy=sysinit.target diff --git a/0006-multipathd-Set-CPUWeight-to-1000-and-LimitRTPRIO-to-.patch b/0006-multipathd-Set-CPUWeight-to-1000-and-LimitRTPRIO-to-.patch new file mode 100644 index 0000000..0cbe997 --- /dev/null +++ b/0006-multipathd-Set-CPUWeight-to-1000-and-LimitRTPRIO-to-.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Mon, 15 Apr 2024 19:43:06 -0400 +Subject: [PATCH] multipathd: Set CPUWeight to 1000 and LimitRTPRIO to 10 + +If multipathd doesn't become a real time process, it was scheduled as a +normal process, without any priority increase. Bump up the CPUWeight so +that even as a normal process, it will still run with increased +priority. + +If multipathd did become a real time process, it set itself to the +highest priority, which is excessive. A priority of 10 is plenty. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + multipathd/multipathd.service.in | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in +index 18bb367e..a63ddd9a 100644 +--- a/multipathd/multipathd.service.in ++++ b/multipathd/multipathd.service.in +@@ -19,7 +19,8 @@ NotifyAccess=main + ExecStart=/sbin/multipathd -d -s + ExecReload=/sbin/multipathd reconfigure + TasksMax=infinity +-LimitRTPRIO=infinity ++LimitRTPRIO=10 ++CPUWeight=1000 + + [Install] + WantedBy=sysinit.target diff --git a/0007-11-dm-mpath.rules-explain-logic-for-device-becoming-.patch b/0007-11-dm-mpath.rules-explain-logic-for-device-becoming-.patch new file mode 100644 index 0000000..6241459 --- /dev/null +++ b/0007-11-dm-mpath.rules-explain-logic-for-device-becoming-.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 1 Mar 2024 19:53:14 +0100 +Subject: [PATCH] 11-dm-mpath.rules: explain logic for device becoming ready + while suspended + +Add a comment to explain why we must set MPATH_DEVICE_READY=0 when +we see a device becoming ready (number of active paths 0 -> 1) while +the device is suspended. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipath/11-dm-mpath.rules.in | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in +index d9585abf..b8d19d01 100644 +--- a/multipath/11-dm-mpath.rules.in ++++ b/multipath/11-dm-mpath.rules.in +@@ -98,6 +98,8 @@ ENV{MPATH_DEVICE_READY}=="0", \ + # If the device comes back online, set DM_ACTIVATION so that + # upper layers do a rescan. If the device is currently suspended, + # we have to postpone the activation until the next event. ++# In this case, we have to set MPATH_DEVICE_READY=0; otherwise, the ++# MPATH_UNCHANGED logic will cause later rules to skipped in the next event. + ENV{MPATH_DEVICE_READY}=="0", GOTO="dont_activate" + ENV{.MPATH_DEVICE_READY_OLD}!="0", GOTO="dont_activate" + ENV{DM_SUSPENDED}=="1", ENV{MPATH_DEVICE_READY}="0", GOTO="dont_activate" diff --git a/0008-11-dm-mpath.rules-don-t-import-DM_NOSCAN-from-udev-d.patch b/0008-11-dm-mpath.rules-don-t-import-DM_NOSCAN-from-udev-d.patch new file mode 100644 index 0000000..3900b39 --- /dev/null +++ b/0008-11-dm-mpath.rules-don-t-import-DM_NOSCAN-from-udev-d.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 1 Mar 2024 19:57:59 +0100 +Subject: [PATCH] 11-dm-mpath.rules: don't import DM_NOSCAN from udev db + +DM_NOSCAN is our "output" flag for 13-dm-disk.rules, and it should +be treated the same way as DM_UDEV_DISABLE_OTHER_RULES_FLAG, which +isn't imported from the udev database. The state that we need to +remember is MPATH_DEVICE_READY, which we've already imported above, +and we will set the "output" flags accordingly in the "force_activation" +code path further down. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipath/11-dm-mpath.rules.in | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in +index b8d19d01..eb12b0c6 100644 +--- a/multipath/11-dm-mpath.rules.in ++++ b/multipath/11-dm-mpath.rules.in +@@ -18,9 +18,11 @@ ACTION=="add", ENV{DM_ACTIVATION}=="1", ENV{DM_SUSPENDED}!="1", ENV{DISK_RO}!="1 + + # If this uevent didn't come from dm, don't try to update the + # device state ++# Note that .MPATH_DEVICE_READY_OLD=="" here. Thus we won't activate the ++# device below at force_activation, which is correct. + ENV{DM_COOKIE}!="?*", ENV{DM_ACTION}!="PATH_*", \ +- IMPORT{db}="DM_NOSCAN", IMPORT{db}="DM_COLDPLUG_SUSPENDED", \ +- GOTO="scan_import" ++ IMPORT{db}="DM_COLDPLUG_SUSPENDED", \ ++ GOTO="force_activation" + + ENV{.MPATH_DEVICE_READY_OLD}="$env{MPATH_DEVICE_READY}" + diff --git a/0009-11-dm-mpath.rules-don-t-import-ID_FS_VERSION-from-ud.patch b/0009-11-dm-mpath.rules-don-t-import-ID_FS_VERSION-from-ud.patch new file mode 100644 index 0000000..933a43a --- /dev/null +++ b/0009-11-dm-mpath.rules-don-t-import-ID_FS_VERSION-from-ud.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 1 Mar 2024 21:02:49 +0100 +Subject: [PATCH] 11-dm-mpath.rules: don't import ID_FS_VERSION from udev db + +Use the same set of properties to import as 13-dm-disk.rules. +ID_FS_VERSION isn't used in any udev rule I am aware of. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipath/11-dm-mpath.rules.in | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in +index eb12b0c6..4386b6ca 100644 +--- a/multipath/11-dm-mpath.rules.in ++++ b/multipath/11-dm-mpath.rules.in +@@ -126,7 +126,6 @@ IMPORT{db}="ID_FS_TYPE" + IMPORT{db}="ID_FS_USAGE" + IMPORT{db}="ID_FS_UUID_ENC" + IMPORT{db}="ID_FS_LABEL_ENC" +-IMPORT{db}="ID_FS_VERSION" + IMPORT{db}="ID_PART_ENTRY_NAME" + IMPORT{db}="ID_PART_ENTRY_UUID" + IMPORT{db}="ID_PART_ENTRY_SCHEME" diff --git a/0010-11-dm-mpath.rules-adapt-MPATH_DEVICE_READY-0-logic-t.patch b/0010-11-dm-mpath.rules-adapt-MPATH_DEVICE_READY-0-logic-t.patch new file mode 100644 index 0000000..97b3901 --- /dev/null +++ b/0010-11-dm-mpath.rules-adapt-MPATH_DEVICE_READY-0-logic-t.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 1 Mar 2024 20:53:50 +0100 +Subject: [PATCH] 11-dm-mpath.rules: adapt MPATH_DEVICE_READY=0 logic to + 10-dm.rules update + +With the late patches for 10-dm.rules, DM_UDEV_DISABLE_OTHER_RULES_FLAG isn't +restored from the udev database any more, so we don't need to restore +the flag to its original state before it is saved to the db. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipath/11-dm-mpath.rules.in | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in +index 4386b6ca..2f909c3a 100644 +--- a/multipath/11-dm-mpath.rules.in ++++ b/multipath/11-dm-mpath.rules.in +@@ -19,7 +19,7 @@ ACTION=="add", ENV{DM_ACTIVATION}=="1", ENV{DM_SUSPENDED}!="1", ENV{DISK_RO}!="1 + # If this uevent didn't come from dm, don't try to update the + # device state + # Note that .MPATH_DEVICE_READY_OLD=="" here. Thus we won't activate the +-# device below at force_activation, which is correct. ++# device below at mpath_is_ready, which is correct. + ENV{DM_COOKIE}!="?*", ENV{DM_ACTION}!="PATH_*", \ + IMPORT{db}="DM_COLDPLUG_SUSPENDED", \ + GOTO="force_activation" +@@ -84,25 +84,27 @@ ENV{DM_ACTION}=="PATH_FAILED|PATH_REINSTATED", \ + + LABEL="force_activation" + ++ENV{MPATH_DEVICE_READY}!="0", GOTO="mpath_is_ready" + # Do not initiate scanning if no path is available, + # otherwise there would be a hang or IO error on access. + # We'd like to avoid this, especially within udev processing. +-ENV{MPATH_DEVICE_READY}=="0", ENV{DM_NOSCAN}="1" +- +-# Skip all foreign rules if no path is available. ++# This is communicated to later rules in DM_NOSCAN. ++# Likewise, skip all foreign rules if no path is available. + # Use DM_UDEV_DISABLE_OTHER_RULES_FLAG to communicate this +-# to upper layers. The original value will be restored in a late +-# udev rule. +-ENV{MPATH_DEVICE_READY}=="0", \ +- ENV{.MPATH_SAVE_DISABLE_OTHER_RULES_FLAG}="$env{DM_UDEV_DISABLE_OTHER_RULES_FLAG}", \ +- ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1" ++# to upper layers. With dm rules < v3, save the original value here; ++# it will be restored in a late udev rule. ++ENV{DM_UDEV_RULES_VSN}=="1|2", \ ++ ENV{.MPATH_SAVE_DISABLE_OTHER_RULES_FLAG}="$env{DM_UDEV_DISABLE_OTHER_RULES_FLAG}" ++ENV{DM_NOSCAN}="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1" ++GOTO="dont_activate" ++ ++LABEL="mpath_is_ready" + + # If the device comes back online, set DM_ACTIVATION so that + # upper layers do a rescan. If the device is currently suspended, + # we have to postpone the activation until the next event. + # In this case, we have to set MPATH_DEVICE_READY=0; otherwise, the + # MPATH_UNCHANGED logic will cause later rules to skipped in the next event. +-ENV{MPATH_DEVICE_READY}=="0", GOTO="dont_activate" + ENV{.MPATH_DEVICE_READY_OLD}!="0", GOTO="dont_activate" + ENV{DM_SUSPENDED}=="1", ENV{MPATH_DEVICE_READY}="0", GOTO="dont_activate" + diff --git a/0011-11-dm-mpath.rules-adapt-coldplug-event-handling-ro-1.patch b/0011-11-dm-mpath.rules-adapt-coldplug-event-handling-ro-1.patch new file mode 100644 index 0000000..938a07f --- /dev/null +++ b/0011-11-dm-mpath.rules-adapt-coldplug-event-handling-ro-1.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 1 Mar 2024 20:55:40 +0100 +Subject: [PATCH] 11-dm-mpath.rules: adapt coldplug event handling ro + 10-dm.rules update + +With late late patches for 10-dm.rules, DM_UDEV_DISABLE_OTHER_RULES_FLAG is +never restored from the udev db. Thus we don't need to clear it here +any more for coldplug events. Also, we must use .DM_SUSPENDED instead of +DM_SUSPENDED as input flag with the v3 rule set (other occurences of +DM_SUSPENDED will be replaced in a follow-up patch). + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipath/11-dm-mpath.rules.in | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in +index 2f909c3a..5f547cab 100644 +--- a/multipath/11-dm-mpath.rules.in ++++ b/multipath/11-dm-mpath.rules.in +@@ -9,12 +9,17 @@ ACTION=="add", ENV{DM_ACTIVATION}=="1", ENV{DM_SUSPENDED}=="1", \ + PROGRAM="/bin/logger -t 11-dm-mpath.rules -p daemon.warning \"Coldplug event for suspended device\"", \ + ENV{DM_COLDPLUG_SUSPENDED}="1", GOTO="scan_import" + +-# Coldplug event. DM_UDEV_DISABLE_OTHER_RULES_FLAG has been restored ++# Coldplug event. Import previously set properties. ++ACTION!="add", GOTO="mpath_coldplug_end" ++ENV{DM_ACTIVATION}!="1", GOTO="mpath_coldplug_end" ++ENV{DM_UDEV_RULES_VSN}!="1|2", ENV{.DM_SUSPENDED}!="1", GOTO="scan_import" ++# With DM rules < v3, DM_UDEV_DISABLE_OTHER_RULES_FLAG has been restored + # from DB in 10-dm.rules. If the device is not suspended, clear the flag. + # This is safe for multipath where DM_UDEV_DISABLE_OTHER_RULES_FLAG is basically + # equivalent to DM_SUSPENDED==1 || DISK_RO==1 +-ACTION=="add", ENV{DM_ACTIVATION}=="1", ENV{DM_SUSPENDED}!="1", ENV{DISK_RO}!="1", \ ++ENV{DM_UDEV_RULES_VSN}=="1|2", ENV{DM_SUSPENDED}!="1", ENV{DISK_RO}!="1", \ + ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="", GOTO="scan_import" ++LABEL="mpath_coldplug_end" + + # If this uevent didn't come from dm, don't try to update the + # device state diff --git a/0012-11-dm-mpath.rules-don-t-import-properties-with-new-1.patch b/0012-11-dm-mpath.rules-don-t-import-properties-with-new-1.patch new file mode 100644 index 0000000..f4e69cf --- /dev/null +++ b/0012-11-dm-mpath.rules-don-t-import-properties-with-new-1.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 1 Mar 2024 20:58:47 +0100 +Subject: [PATCH] 11-dm-mpath.rules: don't import properties with new + 13-dm-disk.rules + +With the late changes to 13-dm-disk.rules, we don't need to import any +blkid-generated properties from the udev database, because they will +be imported later. + +Except for ID_FS_TYPE, this actually holds since lvm2 commit 94f77a4 ("udev: +import previous results of blkid when in suspended state"), included in lvm2 +2.03.19, but we have no simple way to detect the version of the lvm2 rules. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipath/11-dm-mpath.rules.in | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in +index 5f547cab..95126bf2 100644 +--- a/multipath/11-dm-mpath.rules.in ++++ b/multipath/11-dm-mpath.rules.in +@@ -126,6 +126,10 @@ LABEL="scan_import" + # have never been properly set. Don't import them. + ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}!="1", GOTO="import_end" + ++# DM rules v3 will import missing properties on 13-dm-disk.rules. ++# No need to do it here. ++ENV{DM_UDEV_RULES_VSN}!="1|2", GOTO="import_end" ++ + # Don't import the properties from db if we will run blkid later. + ENV{DM_NOSCAN}!="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}!="1", GOTO="import_end" + diff --git a/0013-11-dm-mpath.rules-replace-DM_SUSPENDED-by-.DM_SUSPEN.patch b/0013-11-dm-mpath.rules-replace-DM_SUSPENDED-by-.DM_SUSPEN.patch new file mode 100644 index 0000000..e922427 --- /dev/null +++ b/0013-11-dm-mpath.rules-replace-DM_SUSPENDED-by-.DM_SUSPEN.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 1 Mar 2024 22:33:59 +0100 +Subject: [PATCH] 11-dm-mpath.rules: replace DM_SUSPENDED by .DM_SUSPENDED + +With the late changes to the device mapper rules, DM_SUSPENDED +is not exported any more. Use .DM_SUSPENDED instead. + +Note that although 11-dm-mpath.rules is not a part of lvm2, it +can be considered as part of the device-mapper layer (everything +before 13-dm-disk.rules can), and is thus allowed to use +.DM_SUSPENDED. In practice .DM_SUSPENDED is equivalent to +DM_UDEV_DISABLE_OTHER_RULES_FLAG for multipath devices, but +using .DM_SUSPENDED here makes the intention more obvious. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipath/11-dm-mpath.rules.in | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in +index 95126bf2..efc6416f 100644 +--- a/multipath/11-dm-mpath.rules.in ++++ b/multipath/11-dm-mpath.rules.in +@@ -4,8 +4,11 @@ ENV{DM_UUID}!="mpath-?*", GOTO="mpath_end" + + IMPORT{db}="MPATH_DEVICE_READY" + ++# device-mapper rules v2 compatibility ++ENV{.DM_SUSPENDED}!="?*", ENV{.DM_SUSPENDED}="$env{DM_SUSPENDED}" ++ + # Coldplug event while device is suspended (e.g. during a reload) +-ACTION=="add", ENV{DM_ACTIVATION}=="1", ENV{DM_SUSPENDED}=="1", \ ++ACTION=="add", ENV{DM_ACTIVATION}=="1", ENV{.DM_SUSPENDED}=="1", \ + PROGRAM="/bin/logger -t 11-dm-mpath.rules -p daemon.warning \"Coldplug event for suspended device\"", \ + ENV{DM_COLDPLUG_SUSPENDED}="1", GOTO="scan_import" + +@@ -17,7 +20,7 @@ ENV{DM_UDEV_RULES_VSN}!="1|2", ENV{.DM_SUSPENDED}!="1", GOTO="scan_import" + # from DB in 10-dm.rules. If the device is not suspended, clear the flag. + # This is safe for multipath where DM_UDEV_DISABLE_OTHER_RULES_FLAG is basically + # equivalent to DM_SUSPENDED==1 || DISK_RO==1 +-ENV{DM_UDEV_RULES_VSN}=="1|2", ENV{DM_SUSPENDED}!="1", ENV{DISK_RO}!="1", \ ++ENV{DM_UDEV_RULES_VSN}=="1|2", ENV{.DM_SUSPENDED}!="1", ENV{DISK_RO}!="1", \ + ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="", GOTO="scan_import" + LABEL="mpath_coldplug_end" + +@@ -68,7 +71,7 @@ LABEL="mpath_action" + # Activation might have been partially skipped. Activate the device now, + # i.e. disable the MPATH_UNCHANGED logic and set DM_ACTIVATION=1. + IMPORT{db}="DM_COLDPLUG_SUSPENDED" +-ENV{DM_COLDPLUG_SUSPENDED}=="1", ENV{DM_SUSPENDED}!="1", \ ++ENV{DM_COLDPLUG_SUSPENDED}=="1", ENV{.DM_SUSPENDED}!="1", \ + ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0", \ + PROGRAM="/bin/logger -t 11-dm-mpath.rules -p daemon.notice \"Forcing activation of previously suspended device\"", \ + GOTO="force_activation" +@@ -111,7 +114,7 @@ LABEL="mpath_is_ready" + # In this case, we have to set MPATH_DEVICE_READY=0; otherwise, the + # MPATH_UNCHANGED logic will cause later rules to skipped in the next event. + ENV{.MPATH_DEVICE_READY_OLD}!="0", GOTO="dont_activate" +-ENV{DM_SUSPENDED}=="1", ENV{MPATH_DEVICE_READY}="0", GOTO="dont_activate" ++ENV{.DM_SUSPENDED}=="1", ENV{MPATH_DEVICE_READY}="0", GOTO="dont_activate" + + ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0" + LABEL="dont_activate" +@@ -145,7 +148,7 @@ IMPORT{db}="ID_PART_GPT_AUTO_ROOT" + LABEL="import_end" + + # Reset previous DM_COLDPLUG_SUSPENDED if activation happens now +-ENV{DM_SUSPENDED}!="1", ENV{DM_ACTIVATION}=="1", ENV{DM_COLDPLUG_SUSPENDED}="" ++ENV{.DM_SUSPENDED}!="1", ENV{DM_ACTIVATION}=="1", ENV{DM_COLDPLUG_SUSPENDED}="" + + # Multipath maps should take precedence over their members. + ENV{DM_UDEV_LOW_PRIORITY_FLAG}!="1", OPTIONS+="link_priority=50" diff --git a/0014-11-dm-mpath.rules-replace-DM_NOSCAN-by-.DM_NOSCAN.patch b/0014-11-dm-mpath.rules-replace-DM_NOSCAN-by-.DM_NOSCAN.patch new file mode 100644 index 0000000..a5eecaf --- /dev/null +++ b/0014-11-dm-mpath.rules-replace-DM_NOSCAN-by-.DM_NOSCAN.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 1 Mar 2024 23:23:53 +0100 +Subject: [PATCH] 11-dm-mpath.rules: replace DM_NOSCAN by .DM_NOSCAN + +We don't need to restore DM_NOSCAN from the db anymore, so we can rename +it to .DM_NOSCAN, making it a temporary property. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipath/11-dm-mpath.rules.in | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in +index efc6416f..3ae3c054 100644 +--- a/multipath/11-dm-mpath.rules.in ++++ b/multipath/11-dm-mpath.rules.in +@@ -96,14 +96,14 @@ ENV{MPATH_DEVICE_READY}!="0", GOTO="mpath_is_ready" + # Do not initiate scanning if no path is available, + # otherwise there would be a hang or IO error on access. + # We'd like to avoid this, especially within udev processing. +-# This is communicated to later rules in DM_NOSCAN. ++# This is communicated to later rules in .DM_NOSCAN. + # Likewise, skip all foreign rules if no path is available. + # Use DM_UDEV_DISABLE_OTHER_RULES_FLAG to communicate this + # to upper layers. With dm rules < v3, save the original value here; + # it will be restored in a late udev rule. + ENV{DM_UDEV_RULES_VSN}=="1|2", \ + ENV{.MPATH_SAVE_DISABLE_OTHER_RULES_FLAG}="$env{DM_UDEV_DISABLE_OTHER_RULES_FLAG}" +-ENV{DM_NOSCAN}="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1" ++ENV{.DM_NOSCAN}="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1" + GOTO="dont_activate" + + LABEL="mpath_is_ready" +@@ -134,7 +134,7 @@ ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}!="1", GOTO="import_end" + ENV{DM_UDEV_RULES_VSN}!="1|2", GOTO="import_end" + + # Don't import the properties from db if we will run blkid later. +-ENV{DM_NOSCAN}!="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}!="1", GOTO="import_end" ++ENV{.DM_NOSCAN}!="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}!="1", GOTO="import_end" + + IMPORT{db}="ID_FS_TYPE" + IMPORT{db}="ID_FS_USAGE" +@@ -150,6 +150,9 @@ LABEL="import_end" + # Reset previous DM_COLDPLUG_SUSPENDED if activation happens now + ENV{.DM_SUSPENDED}!="1", ENV{DM_ACTIVATION}=="1", ENV{DM_COLDPLUG_SUSPENDED}="" + ++# device-mapper rules v2 compatibility for 13-dm-disk.rules ++ENV{DM_UDEV_RULES_VSN}=="1|2", ENV{DM_NOSCAN}="$env{.DM_NOSCAN}" ++ + # Multipath maps should take precedence over their members. + ENV{DM_UDEV_LOW_PRIORITY_FLAG}!="1", OPTIONS+="link_priority=50" + diff --git a/0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch b/0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch deleted file mode 100644 index 7655591..0000000 --- a/0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Tue, 16 Jan 2024 00:54:37 -0500 -Subject: [PATCH] multipathd: fix null pointer dereference in uev_update_path - -The Auto-resize code added a check that deferences pp->mpp without -checking that it's non-NULL. Fix it. - -Fixes: 981b83ad1 ("multipathd: Add auto_resize config option") -Signed-off-by: Benjamin Marzinski ---- - multipathd/main.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/multipathd/main.c b/multipathd/main.c -index 230c9d10..57c04364 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -1653,7 +1653,7 @@ uev_update_path (struct uevent *uev, struct vectors * vecs) - } - } - } -- if (auto_resize != AUTO_RESIZE_NEVER && -+ if (auto_resize != AUTO_RESIZE_NEVER && mpp && - !mpp->wait_for_udev) { - struct pathgroup *pgp; - struct path *pp2; diff --git a/0015-11-dm-mpath.rules-simplify-PATH_FAILED-case.patch b/0015-11-dm-mpath.rules-simplify-PATH_FAILED-case.patch new file mode 100644 index 0000000..ce393ae --- /dev/null +++ b/0015-11-dm-mpath.rules-simplify-PATH_FAILED-case.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 6 Mar 2024 21:17:51 +0100 +Subject: [PATCH] 11-dm-mpath.rules: simplify PATH_FAILED case + +This combination of a GOTO and a simple rule can be combined +into a single rule. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipath/11-dm-mpath.rules.in | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in +index 3ae3c054..4777fbec 100644 +--- a/multipath/11-dm-mpath.rules.in ++++ b/multipath/11-dm-mpath.rules.in +@@ -56,14 +56,10 @@ PROGRAM=="@BINDIR@/multipath -U -v1 %k", GOTO="paths_ok" + ENV{MPATH_DEVICE_READY}="0", GOTO="mpath_action" + LABEL="paths_ok" + +-# Don't mark a device ready on a PATH_FAILED event. even if +-# DM_NR_VALID_PATHS is greater than 0. Just keep the existing +-# value +-ENV{DM_ACTION}=="PATH_FAILED", GOTO="mpath_action" +- +-# This event is either a PATH_REINSTATED or a table reload where +-# there are active paths. Mark the device ready +-ENV{MPATH_DEVICE_READY}="1" ++# For PATH_FAILED events, keep the existing value of MPATH_DEVICE_READY. ++# If it's not PATH_FAILED, this event is either a PATH_REINSTATED or a ++# table reload where there are active paths. Mark the device ready. ++ENV{DM_ACTION}!="PATH_FAILED", ENV{MPATH_DEVICE_READY}="1" + + LABEL="mpath_action" + diff --git a/0015-multipathd-fix-auto-resize-configuration.patch b/0015-multipathd-fix-auto-resize-configuration.patch deleted file mode 100644 index 35e4d48..0000000 --- a/0015-multipathd-fix-auto-resize-configuration.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Tue, 16 Jan 2024 01:11:02 -0500 -Subject: [PATCH] multipathd: fix auto-resize configuration - -The code acted like AUTO_RESIZE_UNDEFINED didn't exist, but since -conf->auto_resize was never set to AUTO_RESIZE_NEVER, the default was in -fact AUTO_RESIZE_UNDEFINED, which ended up getting treated like -AUTO_RESIZE_GROW_SHRINK. Remove AUTO_RESIZE_UNDEFINED and explicitly -default auto_resize tp AUTO_RESIZE_NEVER. - -Fixes: 981b83ad1 ("multipathd: Add auto_resize config option") -Signed-off-by: Benjamin Marzinski ---- - libmultipath/config.c | 1 + - libmultipath/structs.h | 1 - - 2 files changed, 1 insertion(+), 1 deletion(-) - -diff --git a/libmultipath/config.c b/libmultipath/config.c -index 4544f484..3d5943d3 100644 ---- a/libmultipath/config.c -+++ b/libmultipath/config.c -@@ -927,6 +927,7 @@ int _init_config (const char *file, struct config *conf) - conf->retrigger_tries = DEFAULT_RETRIGGER_TRIES; - conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY; - conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT; -+ conf->auto_resize = DEFAULT_AUTO_RESIZE; - conf->remove_retries = 0; - conf->ghost_delay = DEFAULT_GHOST_DELAY; - conf->all_tg_pt = DEFAULT_ALL_TG_PT; -diff --git a/libmultipath/structs.h b/libmultipath/structs.h -index a1aac1b4..734905e2 100644 ---- a/libmultipath/structs.h -+++ b/libmultipath/structs.h -@@ -180,7 +180,6 @@ enum queue_mode_states { - }; - - enum auto_resize_state { -- AUTO_RESIZE_UNDEF = 0, - AUTO_RESIZE_NEVER, - AUTO_RESIZE_GROW_ONLY, - AUTO_RESIZE_GROW_SHRINK, diff --git a/0016-11-dm-mpath.rules-make-label-names-more-intuitive.patch b/0016-11-dm-mpath.rules-make-label-names-more-intuitive.patch new file mode 100644 index 0000000..e81f04f --- /dev/null +++ b/0016-11-dm-mpath.rules-make-label-names-more-intuitive.patch @@ -0,0 +1,109 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 1 Mar 2024 21:54:26 +0100 +Subject: [PATCH] 11-dm-mpath.rules: make label names more intuitive + +The labels "dont_activate" and "scan_import" denote the same code line. +Remove "dont_activate". Improve two misleading label names. + +Substitutions: + dont_activate -> scan_import + force_activation -> check_mpath_ready + mpath_action -> check_mpath_unchanged + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipath/11-dm-mpath.rules.in | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in +index 4777fbec..0562eddf 100644 +--- a/multipath/11-dm-mpath.rules.in ++++ b/multipath/11-dm-mpath.rules.in +@@ -30,7 +30,7 @@ LABEL="mpath_coldplug_end" + # device below at mpath_is_ready, which is correct. + ENV{DM_COOKIE}!="?*", ENV{DM_ACTION}!="PATH_*", \ + IMPORT{db}="DM_COLDPLUG_SUSPENDED", \ +- GOTO="force_activation" ++ GOTO="check_mpath_ready" + + ENV{.MPATH_DEVICE_READY_OLD}="$env{MPATH_DEVICE_READY}" + +@@ -38,13 +38,13 @@ ENV{.MPATH_DEVICE_READY_OLD}="$env{MPATH_DEVICE_READY}" + # table with no active devices. If this happens, mark the + # device not ready + ENV{DM_SUBSYSTEM_UDEV_FLAG2}=="1", ENV{MPATH_DEVICE_READY}="0", \ +- GOTO="mpath_action" ++ GOTO="check_mpath_unchanged" + + # If the last path has failed mark the device not ready + # Note that DM_NR_VALID_PATHS is only set for PATH_FAILED|PATH_REINSTATED + # events. + # This may not be reliable, as events aren't necessarily received in order. +-ENV{DM_NR_VALID_PATHS}=="0", ENV{MPATH_DEVICE_READY}="0", GOTO="mpath_action" ++ENV{DM_NR_VALID_PATHS}=="0", ENV{MPATH_DEVICE_READY}="0", GOTO="check_mpath_unchanged" + + # Don't run multipath -U during "coldplug" after switching root, + # because paths are just being added to the udev db. +@@ -53,7 +53,8 @@ ACTION=="add", ENV{.MPATH_DEVICE_READY_OLD}=="1", GOTO="paths_ok" + # Check the map state directly with multipath -U. + # This doesn't attempt I/O on the device. + PROGRAM=="@BINDIR@/multipath -U -v1 %k", GOTO="paths_ok" +-ENV{MPATH_DEVICE_READY}="0", GOTO="mpath_action" ++ENV{MPATH_DEVICE_READY}="0", GOTO="check_mpath_unchanged" ++ + LABEL="paths_ok" + + # For PATH_FAILED events, keep the existing value of MPATH_DEVICE_READY. +@@ -61,7 +62,7 @@ LABEL="paths_ok" + # table reload where there are active paths. Mark the device ready. + ENV{DM_ACTION}!="PATH_FAILED", ENV{MPATH_DEVICE_READY}="1" + +-LABEL="mpath_action" ++LABEL="check_mpath_unchanged" + + # A previous coldplug event occurred while the device was suspended. + # Activation might have been partially skipped. Activate the device now, +@@ -70,7 +71,7 @@ IMPORT{db}="DM_COLDPLUG_SUSPENDED" + ENV{DM_COLDPLUG_SUSPENDED}=="1", ENV{.DM_SUSPENDED}!="1", \ + ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0", \ + PROGRAM="/bin/logger -t 11-dm-mpath.rules -p daemon.notice \"Forcing activation of previously suspended device\"", \ +- GOTO="force_activation" ++ GOTO="check_mpath_ready" + + # DM_SUBSYSTEM_UDEV_FLAG0 is the "RELOAD" flag for multipath subsystem. + # Drop the DM_ACTIVATION flag here as mpath reloads tables if any of its +@@ -86,7 +87,7 @@ ENV{DM_SUBSYSTEM_UDEV_FLAG0}=="1", \ + ENV{DM_ACTION}=="PATH_FAILED|PATH_REINSTATED", \ + ENV{DM_ACTIVATION}="0", ENV{MPATH_UNCHANGED}="1" + +-LABEL="force_activation" ++LABEL="check_mpath_ready" + + ENV{MPATH_DEVICE_READY}!="0", GOTO="mpath_is_ready" + # Do not initiate scanning if no path is available, +@@ -100,7 +101,7 @@ ENV{MPATH_DEVICE_READY}!="0", GOTO="mpath_is_ready" + ENV{DM_UDEV_RULES_VSN}=="1|2", \ + ENV{.MPATH_SAVE_DISABLE_OTHER_RULES_FLAG}="$env{DM_UDEV_DISABLE_OTHER_RULES_FLAG}" + ENV{.DM_NOSCAN}="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1" +-GOTO="dont_activate" ++GOTO="scan_import" + + LABEL="mpath_is_ready" + +@@ -109,11 +110,10 @@ LABEL="mpath_is_ready" + # we have to postpone the activation until the next event. + # In this case, we have to set MPATH_DEVICE_READY=0; otherwise, the + # MPATH_UNCHANGED logic will cause later rules to skipped in the next event. +-ENV{.MPATH_DEVICE_READY_OLD}!="0", GOTO="dont_activate" +-ENV{.DM_SUSPENDED}=="1", ENV{MPATH_DEVICE_READY}="0", GOTO="dont_activate" ++ENV{.MPATH_DEVICE_READY_OLD}!="0", GOTO="scan_import" ++ENV{.DM_SUSPENDED}=="1", ENV{MPATH_DEVICE_READY}="0", GOTO="scan_import" + + ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0" +-LABEL="dont_activate" + + # The code to check multipath state ends here. We need to set + # properties and symlinks regardless whether the map is usable or diff --git a/0017-kpartx.rules-ignore-DM_SUSPENDED.patch b/0017-kpartx.rules-ignore-DM_SUSPENDED.patch new file mode 100644 index 0000000..3b0ac76 --- /dev/null +++ b/0017-kpartx.rules-ignore-DM_SUSPENDED.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 1 Mar 2024 21:17:26 +0100 +Subject: [PATCH] kpartx.rules: ignore DM_SUSPENDED + +DM_SUSPENDED=1 implies DM_UDEV_DISABLE_OTHER_RULES_FLAG=1, no +need to check it again. The DM_NOSCAN check needs to remain in +order to keep compatibility with dm rules v2. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + kpartx/kpartx.rules | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules +index 1969dee0..8dd3369c 100644 +--- a/kpartx/kpartx.rules ++++ b/kpartx/kpartx.rules +@@ -27,7 +27,7 @@ ENV{DM_SUBSYSTEM_UDEV_FLAG1}=="1", GOTO="mpath_kpartx_end" + ENV{MPATH_UNCHANGED}=="1", GOTO="mpath_kpartx_end" + + # Don't run kpartx now if we know it will fail or hang. +-ENV{DM_SUSPENDED}=="1", GOTO="mpath_kpartx_end" ++# This is required for device mapper rules v2 compatibility. + ENV{DM_NOSCAN}=="1", GOTO="mpath_kpartx_end" + + # Run kpartx diff --git a/0018-multipath-tools-tests-fix-CI-failures-on-arm-v7-with.patch b/0018-multipath-tools-tests-fix-CI-failures-on-arm-v7-with.patch new file mode 100644 index 0000000..2840cec --- /dev/null +++ b/0018-multipath-tools-tests-fix-CI-failures-on-arm-v7-with.patch @@ -0,0 +1,270 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 4 Apr 2024 23:23:28 +0200 +Subject: [PATCH] multipath-tools tests: fix CI failures on arm/v7 with glibc + 2.37 + +glibc 2.37 has added several new wrappers around the ioctl and +io_getevents system calls on 32 bit systems, to deal with 64bit +time_t. These aren't resolved with cmocka's wrapping technique. + +Fix this with C preprocessor trickery, similar to +7b217f8 ("multipath-tools: Makefile.inc: set _FILE_OFFSET_BITS=64"). + +Note: the directio test with DIO_TEST_DEV for fails under qemu-linux-user +with foreign-arch binfmt, because aio-related system calls are unsupported +by qemu-linux-user. See https://gitlab.com/qemu-project/qemu/-/issues/210. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + tests/directio.c | 28 ++++++++++++++-------------- + tests/vpd.c | 35 ++++++++++++++++++----------------- + tests/wrap64.h | 25 ++++++++++++++++++++++++- + 3 files changed, 56 insertions(+), 32 deletions(-) + +diff --git a/tests/directio.c b/tests/directio.c +index cbedcc9c..d5f84f10 100644 +--- a/tests/directio.c ++++ b/tests/directio.c +@@ -41,13 +41,13 @@ struct timespec full_timeout = { .tv_sec = -1 }; + #define ioctl_request_t int + #endif + +-int __real_ioctl(int fd, ioctl_request_t request, void *argp); ++int REAL_IOCTL(int fd, ioctl_request_t request, void *argp); + +-int __wrap_ioctl(int fd, ioctl_request_t request, void *argp) ++int WRAP_IOCTL(int fd, ioctl_request_t request, void *argp) + { + #ifdef DIO_TEST_DEV + mock_type(int); +- return __real_ioctl(fd, request, argp); ++ return REAL_IOCTL(fd, request, argp); + #else + int *blocksize = (int *)argp; + +@@ -148,10 +148,10 @@ int __wrap_io_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt) + #endif + } + +-int __real_io_getevents(io_context_t ctx, long min_nr, long nr, ++int REAL_IO_GETEVENTS(io_context_t ctx, long min_nr, long nr, + struct io_event *events, struct timespec *timeout); + +-int __wrap_io_getevents(io_context_t ctx, long min_nr, long nr, ++int WRAP_IO_GETEVENTS(io_context_t ctx, long min_nr, long nr, + struct io_event *events, struct timespec *timeout) + { + int nr_evs; +@@ -169,8 +169,8 @@ int __wrap_io_getevents(io_context_t ctx, long min_nr, long nr, + #ifdef DIO_TEST_DEV + mock_ptr_type(struct timespec *); + mock_ptr_type(struct io_event *); +- assert_int_equal(nr_evs, __real_io_getevents(ctx, min_nr, nr_evs, +- events, timeout)); ++ assert_int_equal(nr_evs, REAL_IO_GETEVENTS(ctx, min_nr, nr_evs, ++ events, timeout)); + #else + sleep_tmo = mock_ptr_type(struct timespec *); + if (sleep_tmo) { +@@ -193,7 +193,7 @@ int __wrap_io_getevents(io_context_t ctx, long min_nr, long nr, + + static void return_io_getevents_none(void) + { +- will_return(__wrap_io_getevents, 0); ++ wrap_will_return(WRAP_IO_GETEVENTS, 0); + } + + static void return_io_getevents_nr(struct timespec *ts, int nr, +@@ -207,15 +207,15 @@ static void return_io_getevents_nr(struct timespec *ts, int nr, + mock_events[i + ev_off].res = reqs[i]->blksize; + } + while (nr > 0) { +- will_return(__wrap_io_getevents, (nr > 128)? 128 : nr); +- will_return(__wrap_io_getevents, ts); +- will_return(__wrap_io_getevents, &mock_events[off + ev_off]); ++ wrap_will_return(WRAP_IO_GETEVENTS, (nr > 128)? 128 : nr); ++ wrap_will_return(WRAP_IO_GETEVENTS, ts); ++ wrap_will_return(WRAP_IO_GETEVENTS, &mock_events[off + ev_off]); + ts = NULL; + off += 128; + nr -= 128; + } + if (nr == 0) +- will_return(__wrap_io_getevents, 0); ++ wrap_will_return(WRAP_IO_GETEVENTS, 0); + ev_off += i; + } + +@@ -251,7 +251,7 @@ static void do_libcheck_init(struct checker *c, int blocksize, + struct directio_context * ct; + + c->fd = test_fd; +- will_return(__wrap_ioctl, blocksize); ++ wrap_will_return(WRAP_IOCTL, blocksize); + assert_int_equal(libcheck_init(c), 0); + ct = (struct directio_context *)c->context; + assert_non_null(ct); +@@ -762,7 +762,7 @@ int main(void) + { + int ret = 0; + +- init_test_verbosity(2); ++ init_test_verbosity(5); + ret += test_directio(); + return ret; + } +diff --git a/tests/vpd.c b/tests/vpd.c +index 1b2d62d6..e3212e61 100644 +--- a/tests/vpd.c ++++ b/tests/vpd.c +@@ -20,6 +20,7 @@ + #include "vector.h" + #include "structs.h" + #include "discovery.h" ++#include "wrap64.h" + #include "globals.c" + + #define VPD_BUFSIZ 4096 +@@ -58,7 +59,7 @@ static const char vendor_id[] = "Linux"; + static const char test_id[] = + "A123456789AbcDefB123456789AbcDefC123456789AbcDefD123456789AbcDef"; + +-int __wrap_ioctl(int fd, unsigned long request, void *param) ++int WRAP_IOCTL(int fd, unsigned long request, void *param) + { + int len; + struct sg_io_hdr *io_hdr; +@@ -428,8 +429,8 @@ static void test_vpd_vnd_ ## len ## _ ## wlen(void **state) \ + /* Replace spaces, like code under test */ \ + exp_subst = subst_spaces(exp_wwid); \ + free(exp_wwid); \ +- will_return(__wrap_ioctl, n); \ +- will_return(__wrap_ioctl, vt->vpdbuf); \ ++ wrap_will_return(WRAP_IOCTL, n); \ ++ wrap_will_return(WRAP_IOCTL, vt->vpdbuf); \ + ret = get_vpd_sgio(10, 0x83, 0, vt->wwid, wlen); \ + assert_correct_wwid("test_vpd_vnd_" #len "_" #wlen, \ + exp_len, ret, '1', 0, false, \ +@@ -458,8 +459,8 @@ static void test_vpd_str_ ## typ ## _ ## len ## _ ## wlen(void **state) \ + exp_len--; \ + if (exp_len >= wlen) \ + exp_len = wlen - 1; \ +- will_return(__wrap_ioctl, n); \ +- will_return(__wrap_ioctl, vt->vpdbuf); \ ++ wrap_will_return(WRAP_IOCTL, n); \ ++ wrap_will_return(WRAP_IOCTL, vt->vpdbuf); \ + ret = get_vpd_sgio(10, 0x83, 0, vt->wwid, wlen); \ + assert_correct_wwid("test_vpd_str_" #typ "_" #len "_" #wlen, \ + exp_len, ret, byte0[type], 0, \ +@@ -495,8 +496,8 @@ static void test_vpd_naa_ ## naa ## _ ## wlen(void **state) \ + \ + n = create_vpd83(vt->vpdbuf, sizeof(vt->vpdbuf), test_id, \ + 3, naa, 0); \ +- will_return(__wrap_ioctl, n); \ +- will_return(__wrap_ioctl, vt->vpdbuf); \ ++ wrap_will_return(WRAP_IOCTL, n); \ ++ wrap_will_return(WRAP_IOCTL, vt->vpdbuf); \ + ret = get_vpd_sgio(10, 0x83, 0, vt->wwid, wlen); \ + assert_correct_wwid("test_vpd_naa_" #naa "_" #wlen, \ + exp_len, ret, '3', '0' + naa, true, \ +@@ -518,8 +519,8 @@ static void test_vpd_naa_##NAA##_badlen_##BAD(void **state) \ + n = create_vpd83(vt->vpdbuf, sizeof(vt->vpdbuf), test_id, 3, NAA, 0); \ + \ + vt->vpdbuf[7] = BAD; \ +- will_return(__wrap_ioctl, n); \ +- will_return(__wrap_ioctl, vt->vpdbuf); \ ++ wrap_will_return(WRAP_IOCTL, n); \ ++ wrap_will_return(WRAP_IOCTL, vt->vpdbuf); \ + ret = get_vpd_sgio(10, 0x83, 0, vt->wwid, 40); \ + assert_int_equal(-ret, -ERR); \ + } +@@ -545,11 +546,11 @@ static void test_vpd_eui_ ## len ## _ ## wlen ## _ ## sml(void **state) \ + /* overwrite the page size to DEFAULT_SGIO_LEN + 1 */ \ + put_unaligned_be16(255, vt->vpdbuf + 2); \ + /* this causes get_vpd_sgio to do a second ioctl */ \ +- will_return(__wrap_ioctl, n); \ +- will_return(__wrap_ioctl, vt->vpdbuf); \ ++ wrap_will_return(WRAP_IOCTL, n); \ ++ wrap_will_return(WRAP_IOCTL, vt->vpdbuf); \ + } \ +- will_return(__wrap_ioctl, n); \ +- will_return(__wrap_ioctl, vt->vpdbuf); \ ++ wrap_will_return(WRAP_IOCTL, n); \ ++ wrap_will_return(WRAP_IOCTL, vt->vpdbuf); \ + ret = get_vpd_sgio(10, 0x83, 0, vt->wwid, wlen); \ + assert_correct_wwid("test_vpd_eui_" #len "_" #wlen "_" #sml, \ + exp_len, ret, '2', 0, true, \ +@@ -571,8 +572,8 @@ static void test_vpd_eui_badlen_##LEN##_##BAD(void **state) \ + n = create_vpd83(vt->vpdbuf, sizeof(vt->vpdbuf), test_id, 2, 0, LEN); \ + \ + vt->vpdbuf[7] = BAD; \ +- will_return(__wrap_ioctl, n); \ +- will_return(__wrap_ioctl, vt->vpdbuf); \ ++ wrap_will_return(WRAP_IOCTL, n); \ ++ wrap_will_return(WRAP_IOCTL, vt->vpdbuf); \ + ret = get_vpd_sgio(10, 0x83, 0, vt->wwid, 40); \ + assert_int_equal(ret, ERR); \ + if (ERR >= 0) \ +@@ -600,8 +601,8 @@ static void test_vpd80_ ## size ## _ ## len ## _ ## wlen(void **state) \ + exp_len = wlen - 1; \ + n = create_vpd80(vt->vpdbuf, sizeof(vt->vpdbuf), input, \ + size, len); \ +- will_return(__wrap_ioctl, n); \ +- will_return(__wrap_ioctl, vt->vpdbuf); \ ++ wrap_will_return(WRAP_IOCTL, n); \ ++ wrap_will_return(WRAP_IOCTL, vt->vpdbuf); \ + ret = get_vpd_sgio(10, 0x80, 0, vt->wwid, wlen); \ + assert_correct_wwid("test_vpd80_" #size "_" #len "_" #wlen, \ + exp_len, ret, 0, 0, false, \ +diff --git a/tests/wrap64.h b/tests/wrap64.h +index 8c91d279..b0a4d831 100644 +--- a/tests/wrap64.h ++++ b/tests/wrap64.h +@@ -1,5 +1,7 @@ + #ifndef _WRAP64_H + #define _WRAP64_H 1 ++#include ++#include + #include "util.h" + + /* +@@ -31,7 +33,9 @@ + * fcntl() needs special treatment; fcntl64() has been introduced in 2.28. + * https://savannah.gnu.org/forum/forum.php?forum_id=9205 + */ +-#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 28) ++#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 37) && defined(__arm__) && __ARM_ARCH == 7 ++#define WRAP_FCNTL_NAME __fcntl_time64 ++#elif defined(__GLIBC__) && __GLIBC_PREREQ(2, 28) + #define WRAP_FCNTL_NAME WRAP_NAME(fcntl) + #else + #define WRAP_FCNTL_NAME fcntl +@@ -39,6 +43,25 @@ + #define WRAP_FCNTL CONCAT2(__wrap_, WRAP_FCNTL_NAME) + #define REAL_FCNTL CONCAT2(__real_, WRAP_FCNTL_NAME) + ++/* ++ * glibc 2.37 uses __ioctl_time64 for ioctl ++ */ ++#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 37) && defined(__arm__) && __ARM_ARCH == 7 ++#define WRAP_IOCTL_NAME __ioctl_time64 ++#else ++#define WRAP_IOCTL_NAME ioctl ++#endif ++#define WRAP_IOCTL CONCAT2(__wrap_, WRAP_IOCTL_NAME) ++#define REAL_IOCTL CONCAT2(__real_, WRAP_IOCTL_NAME) ++ ++#if defined(__NR_io_pgetevents) && __BITS_PER_LONG == 32 && defined(_TIME_BITS) && _TIME_BITS == 64 ++#define WRAP_IO_GETEVENTS_NAME io_getevents_time64 ++#else ++#define WRAP_IO_GETEVENTS_NAME io_getevents ++#endif ++#define WRAP_IO_GETEVENTS CONCAT2(__wrap_, WRAP_IO_GETEVENTS_NAME) ++#define REAL_IO_GETEVENTS CONCAT2(__real_, WRAP_IO_GETEVENTS_NAME) ++ + /* + * will_return() is itself a macro that uses CPP "stringizing". We need a + * macro indirection to make sure the *value* of WRAP_FUNC() is stringized diff --git a/0019-multipath-tools-tests-fix-CI-failures-with-clang-on-.patch b/0019-multipath-tools-tests-fix-CI-failures-with-clang-on-.patch new file mode 100644 index 0000000..d1dedac --- /dev/null +++ b/0019-multipath-tools-tests-fix-CI-failures-with-clang-on-.patch @@ -0,0 +1,246 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 5 Apr 2024 22:21:43 +0200 +Subject: [PATCH] multipath-tools tests: fix CI failures with clang on Fedora + Rawhide + +Fedora's glibc 2.39 includes the following patch: + +https://patches.linaro.org/project/libc-alpha/patch/20240208184622.332678-10-adhemerval.zanella@linaro.org/ + +It causes open("file", O_RDONLY) to resolve to __open64_2(), +whereas it resolves to open64() with gcc, causing CI failures because of +wrong wrapper substitutions. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + tests/dmevents.c | 6 ++--- + tests/sysfs.c | 58 ++++++++++++++++++++++++------------------------ + tests/test-lib.c | 6 ++--- + tests/wrap64.h | 14 ++++++++++++ + 4 files changed, 49 insertions(+), 35 deletions(-) + +diff --git a/tests/dmevents.c b/tests/dmevents.c +index 540bf0d3..395b16d7 100644 +--- a/tests/dmevents.c ++++ b/tests/dmevents.c +@@ -207,7 +207,7 @@ static int teardown(void **state) + return 0; + } + +-int WRAP_FUNC(open)(const char *pathname, int flags) ++int WRAP_OPEN(const char *pathname, int flags) + { + assert_ptr_equal(pathname, "/dev/mapper/control"); + assert_int_equal(flags, O_RDWR); +@@ -389,7 +389,7 @@ static void test_init_waiter_bad1(void **state) + struct test_data *datap = (struct test_data *)(*state); + if (datap == NULL) + skip(); +- wrap_will_return(WRAP_FUNC(open), -1); ++ wrap_will_return(WRAP_OPEN, -1); + assert_int_equal(init_dmevent_waiter(&datap->vecs), -1); + assert_ptr_equal(waiter, NULL); + } +@@ -400,7 +400,7 @@ static void test_init_waiter_good0(void **state) + struct test_data *datap = (struct test_data *)(*state); + if (datap == NULL) + skip(); +- wrap_will_return(WRAP_FUNC(open), 2); ++ wrap_will_return(WRAP_OPEN, 2); + assert_int_equal(init_dmevent_waiter(&datap->vecs), 0); + assert_ptr_not_equal(waiter, NULL); + } +diff --git a/tests/sysfs.c b/tests/sysfs.c +index fc256d87..c623d1bb 100644 +--- a/tests/sysfs.c ++++ b/tests/sysfs.c +@@ -29,7 +29,7 @@ char *__wrap_udev_device_get_syspath(struct udev_device *ud) + return val; + } + +-int WRAP_FUNC(open)(const char *pathname, int flags) ++int WRAP_OPEN(const char *pathname, int flags) + { + int ret; + +@@ -167,10 +167,10 @@ static void test_sagv_open_fail(void **state) + + will_return(__wrap_udev_device_get_syspath, "/foo"); + expect_condlog(4, "open '/foo/bar'"); +- expect_string(WRAP_FUNC(open), pathname, "/foo/bar"); +- expect_value(WRAP_FUNC(open), flags, O_RDONLY); ++ expect_string(WRAP_OPEN, pathname, "/foo/bar"); ++ expect_value(WRAP_OPEN, flags, O_RDONLY); + errno = ENOENT; +- wrap_will_return(WRAP_FUNC(open), -1); ++ wrap_will_return(WRAP_OPEN, -1); + expect_condlog(3, "__sysfs_attr_get_value: attribute '/foo/bar' cannot be opened"); + assert_int_equal(sysfs_attr_get_value((void *)state, "bar", + buf, sizeof(buf)), -ENOENT); +@@ -182,9 +182,9 @@ static void test_sagv_read_fail(void **state) + + will_return(__wrap_udev_device_get_syspath, "/foo"); + expect_condlog(4, "open '/foo/bar'"); +- expect_string(WRAP_FUNC(open), pathname, "/foo/bar"); +- expect_value(WRAP_FUNC(open), flags, O_RDONLY); +- wrap_will_return(WRAP_FUNC(open), TEST_FD); ++ expect_string(WRAP_OPEN, pathname, "/foo/bar"); ++ expect_value(WRAP_OPEN, flags, O_RDONLY); ++ wrap_will_return(WRAP_OPEN, TEST_FD); + expect_value(__wrap_read, fd, TEST_FD); + expect_value(__wrap_read, count, sizeof(buf)); + errno = EISDIR; +@@ -197,9 +197,9 @@ static void test_sagv_read_fail(void **state) + + will_return(__wrap_udev_device_get_syspath, "/foo"); + expect_condlog(4, "open '/foo/baz'"); +- expect_string(WRAP_FUNC(open), pathname, "/foo/baz"); +- expect_value(WRAP_FUNC(open), flags, O_RDONLY); +- wrap_will_return(WRAP_FUNC(open), TEST_FD); ++ expect_string(WRAP_OPEN, pathname, "/foo/baz"); ++ expect_value(WRAP_OPEN, flags, O_RDONLY); ++ wrap_will_return(WRAP_OPEN, TEST_FD); + expect_value(__wrap_read, fd, TEST_FD); + expect_value(__wrap_read, count, sizeof(buf)); + errno = EPERM; +@@ -223,9 +223,9 @@ static void _test_sagv_read(void **state, unsigned int bufsz) + memset(buf, '.', sizeof(buf)); + will_return(__wrap_udev_device_get_syspath, "/foo"); + expect_condlog(4, "open '/foo/bar'"); +- expect_string(WRAP_FUNC(open), pathname, "/foo/bar"); +- expect_value(WRAP_FUNC(open), flags, O_RDONLY); +- wrap_will_return(WRAP_FUNC(open), TEST_FD); ++ expect_string(WRAP_OPEN, pathname, "/foo/bar"); ++ expect_value(WRAP_OPEN, flags, O_RDONLY); ++ wrap_will_return(WRAP_OPEN, TEST_FD); + expect_value(__wrap_read, fd, TEST_FD); + expect_value(__wrap_read, count, bufsz); + will_return(__wrap_read, sizeof(input) - 1); +@@ -250,9 +250,9 @@ static void _test_sagv_read(void **state, unsigned int bufsz) + memset(buf, '.', sizeof(buf)); + will_return(__wrap_udev_device_get_syspath, "/foo"); + expect_condlog(4, "open '/foo/baz'"); +- expect_string(WRAP_FUNC(open), pathname, "/foo/baz"); +- expect_value(WRAP_FUNC(open), flags, O_RDONLY); +- wrap_will_return(WRAP_FUNC(open), TEST_FD); ++ expect_string(WRAP_OPEN, pathname, "/foo/baz"); ++ expect_value(WRAP_OPEN, flags, O_RDONLY); ++ wrap_will_return(WRAP_OPEN, TEST_FD); + expect_value(__wrap_read, fd, TEST_FD); + expect_value(__wrap_read, count, bufsz); + will_return(__wrap_read, sizeof(input) - 1); +@@ -301,9 +301,9 @@ static void _test_sagv_read_zeroes(void **state, unsigned int bufsz) + memset(buf, '.', sizeof(buf)); + will_return(__wrap_udev_device_get_syspath, "/foo"); + expect_condlog(4, "open '/foo/bar'"); +- expect_string(WRAP_FUNC(open), pathname, "/foo/bar"); +- expect_value(WRAP_FUNC(open), flags, O_RDONLY); +- wrap_will_return(WRAP_FUNC(open), TEST_FD); ++ expect_string(WRAP_OPEN, pathname, "/foo/bar"); ++ expect_value(WRAP_OPEN, flags, O_RDONLY); ++ wrap_will_return(WRAP_OPEN, TEST_FD); + expect_value(__wrap_read, fd, TEST_FD); + expect_value(__wrap_read, count, bufsz); + will_return(__wrap_read, sizeof(input) - 1); +@@ -386,10 +386,10 @@ static void test_sasv_open_fail(void **state) + + will_return(__wrap_udev_device_get_syspath, "/foo"); + expect_condlog(4, "open '/foo/bar'"); +- expect_string(WRAP_FUNC(open), pathname, "/foo/bar"); +- expect_value(WRAP_FUNC(open), flags, O_WRONLY); ++ expect_string(WRAP_OPEN, pathname, "/foo/bar"); ++ expect_value(WRAP_OPEN, flags, O_WRONLY); + errno = EPERM; +- wrap_will_return(WRAP_FUNC(open), -1); ++ wrap_will_return(WRAP_OPEN, -1); + expect_condlog(3, "sysfs_attr_set_value: attribute '/foo/bar' cannot be opened"); + assert_int_equal(sysfs_attr_set_value((void *)state, "bar", + buf, sizeof(buf)), -EPERM); +@@ -401,9 +401,9 @@ static void test_sasv_write_fail(void **state) + + will_return(__wrap_udev_device_get_syspath, "/foo"); + expect_condlog(4, "open '/foo/bar'"); +- expect_string(WRAP_FUNC(open), pathname, "/foo/bar"); +- expect_value(WRAP_FUNC(open), flags, O_WRONLY); +- wrap_will_return(WRAP_FUNC(open), TEST_FD); ++ expect_string(WRAP_OPEN, pathname, "/foo/bar"); ++ expect_value(WRAP_OPEN, flags, O_WRONLY); ++ wrap_will_return(WRAP_OPEN, TEST_FD); + expect_value(__wrap_write, fd, TEST_FD); + expect_value(__wrap_write, count, sizeof(buf)); + errno = EISDIR; +@@ -422,9 +422,9 @@ static void _test_sasv_write(void **state, unsigned int n_written) + assert_in_range(n_written, 0, sizeof(buf)); + will_return(__wrap_udev_device_get_syspath, "/foo"); + expect_condlog(4, "open '/foo/bar'"); +- expect_string(WRAP_FUNC(open), pathname, "/foo/bar"); +- expect_value(WRAP_FUNC(open), flags, O_WRONLY); +- wrap_will_return(WRAP_FUNC(open), TEST_FD); ++ expect_string(WRAP_OPEN, pathname, "/foo/bar"); ++ expect_value(WRAP_OPEN, flags, O_WRONLY); ++ wrap_will_return(WRAP_OPEN, TEST_FD); + expect_value(__wrap_write, fd, TEST_FD); + expect_value(__wrap_write, count, sizeof(buf)); + will_return(__wrap_write, n_written); +@@ -489,7 +489,7 @@ int main(void) + { + int ret = 0; + +- init_test_verbosity(4); ++ init_test_verbosity(5); + ret += test_sysfs(); + return ret; + } +diff --git a/tests/test-lib.c b/tests/test-lib.c +index 665d438e..cdb2780d 100644 +--- a/tests/test-lib.c ++++ b/tests/test-lib.c +@@ -40,17 +40,17 @@ const char default_wwid_1[] = "TEST-WWID-1"; + */ + + +-int REAL_FUNC(open)(const char *path, int flags, int mode); ++int REAL_OPEN(const char *path, int flags, int mode); + + static const char _mocked_filename[] = "mocked_path"; + +-int WRAP_FUNC(open)(const char *path, int flags, int mode) ++int WRAP_OPEN(const char *path, int flags, int mode) + { + condlog(4, "%s: %s", __func__, path); + + if (!strcmp(path, _mocked_filename)) + return 111; +- return REAL_FUNC(open)(path, flags, mode); ++ return REAL_OPEN(path, flags, mode); + } + + int __wrap_libmp_get_version(int which, unsigned int version[3]) +diff --git a/tests/wrap64.h b/tests/wrap64.h +index b0a4d831..7e434206 100644 +--- a/tests/wrap64.h ++++ b/tests/wrap64.h +@@ -29,6 +29,20 @@ + #define WRAP_FUNC(x) CONCAT2(__wrap_, WRAP_NAME(x)) + #define REAL_FUNC(x) CONCAT2(__real_, WRAP_NAME(x)) + ++/* ++ * With clang, glibc 2.39, and _FILE_OFFSET_BITS==64, ++ * open() resolves to __open64_2(). ++ */ ++#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 39) && \ ++ defined(__clang__) && __clang__ == 1 && \ ++ defined(__fortify_use_clang) && __fortify_use_clang == 1 ++#define WRAP_OPEN_NAME __open64_2 ++#else ++#define WRAP_OPEN_NAME WRAP_NAME(open) ++#endif ++#define WRAP_OPEN CONCAT2(__wrap_, WRAP_OPEN_NAME) ++#define REAL_OPEN CONCAT2(__real_, WRAP_OPEN_NAME) ++ + /* + * fcntl() needs special treatment; fcntl64() has been introduced in 2.28. + * https://savannah.gnu.org/forum/forum.php?forum_id=9205 diff --git a/0020-GitHub-actions-fixes-for-spelling-CI.patch b/0020-GitHub-actions-fixes-for-spelling-CI.patch new file mode 100644 index 0000000..21b74ff --- /dev/null +++ b/0020-GitHub-actions-fixes-for-spelling-CI.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 8 Mar 2024 10:04:39 +0100 +Subject: [PATCH] GitHub actions: fixes for spelling CI + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + .github/actions/spelling/patterns.txt | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/.github/actions/spelling/patterns.txt b/.github/actions/spelling/patterns.txt +index 57767ea1..858faee6 100644 +--- a/.github/actions/spelling/patterns.txt ++++ b/.github/actions/spelling/patterns.txt +@@ -22,6 +22,7 @@ + \bdmmp_pgs\b + \bdmmp_mpath_kdev_name_get\b + \bfast_io_fail_tmo\b ++\bLimitRTPRIO\b + \bmax_fds\b + \bmissing_uev_wait_timeout\b + \bMPATH_MAX_PARAM_LEN\b +@@ -86,6 +87,7 @@ + \bprin_resvdescr\b + \bprout_param_descriptor\b + \brq_servact\b ++\bSCHED_RT_PRIO\b + \bssize_t\b + \btrnptid_list\b + \buxsock_timeout\b diff --git a/0021-GitHub-workflows-run-workflows-if-workflow-file-has-.patch b/0021-GitHub-workflows-run-workflows-if-workflow-file-has-.patch new file mode 100644 index 0000000..59cdd0e --- /dev/null +++ b/0021-GitHub-workflows-run-workflows-if-workflow-file-has-.patch @@ -0,0 +1,146 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 27 Feb 2024 09:57:47 +0100 +Subject: [PATCH] GitHub workflows: run workflows if workflow file has changed + +We want to run workflows if the workflow file itself has changed. + +Fixes: 2cbe81a ("GitHub Workflows: run expensive workflows only on relevant changes") +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + .github/workflows/abi.yaml | 1 + + .github/workflows/foreign.yaml | 2 ++ + .github/workflows/multiarch-stable.yaml | 2 ++ + .github/workflows/multiarch.yaml | 2 ++ + .github/workflows/native.yaml | 2 ++ + .github/workflows/rolling.yaml | 2 ++ + .github/workflows/spelling.yml | 2 ++ + 7 files changed, 13 insertions(+) + +diff --git a/.github/workflows/abi.yaml b/.github/workflows/abi.yaml +index 53382420..393322e5 100644 +--- a/.github/workflows/abi.yaml ++++ b/.github/workflows/abi.yaml +@@ -5,6 +5,7 @@ on: + - queue + - abi + paths: ++ - '.github/workflows/abi.yaml' + - '**.h' + - '**.c' + pull_request: +diff --git a/.github/workflows/foreign.yaml b/.github/workflows/foreign.yaml +index 92f6d17a..a62ae009 100644 +--- a/.github/workflows/foreign.yaml ++++ b/.github/workflows/foreign.yaml +@@ -6,6 +6,7 @@ on: + - queue + - tip + paths: ++ - '.github/workflows/foreign.yaml' + - '**.h' + - '**.c' + - '**Makefile*' +@@ -15,6 +16,7 @@ on: + - master + - queue + paths: ++ - '.github/workflows/foreign.yaml' + - '**.h' + - '**.c' + - '**Makefile*' +diff --git a/.github/workflows/multiarch-stable.yaml b/.github/workflows/multiarch-stable.yaml +index 45b74c51..e51d383c 100644 +--- a/.github/workflows/multiarch-stable.yaml ++++ b/.github/workflows/multiarch-stable.yaml +@@ -6,6 +6,7 @@ on: + - queue + - tip + paths: ++ - '.github/workflows/multiarch-stable.yaml' + - '**.h' + - '**.c' + - '**Makefile*' +@@ -15,6 +16,7 @@ on: + - master + - queue + paths: ++ - '.github/workflows/multiarch-stable.yaml' + - '**.h' + - '**.c' + - '**Makefile*' +diff --git a/.github/workflows/multiarch.yaml b/.github/workflows/multiarch.yaml +index b4dec9c7..7b762e5c 100644 +--- a/.github/workflows/multiarch.yaml ++++ b/.github/workflows/multiarch.yaml +@@ -6,6 +6,7 @@ on: + - queue + - tip + paths: ++ - '.github/workflows/multiarch.yaml' + - '**.h' + - '**.c' + - '**Makefile*' +@@ -15,6 +16,7 @@ on: + - master + - queue + paths: ++ - '.github/workflows/multiarch.yaml' + - '**.h' + - '**.c' + - '**Makefile*' +diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml +index 09133c1e..0ef9df94 100644 +--- a/.github/workflows/native.yaml ++++ b/.github/workflows/native.yaml +@@ -6,6 +6,7 @@ on: + - queue + - tip + paths: ++ - '.github/workflows/native.yaml' + - '**.h' + - '**.c' + - '**Makefile*' +@@ -15,6 +16,7 @@ on: + - master + - queue + paths: ++ - '.github/workflows/native.yaml' + - '**.h' + - '**.c' + - '**Makefile*' +diff --git a/.github/workflows/rolling.yaml b/.github/workflows/rolling.yaml +index 1f1507ee..3536b944 100644 +--- a/.github/workflows/rolling.yaml ++++ b/.github/workflows/rolling.yaml +@@ -6,6 +6,7 @@ on: + - queue + - tip + paths: ++ - '.github/workflows/rolling.yaml' + - '**.h' + - '**.c' + - '**Makefile*' +@@ -15,6 +16,7 @@ on: + - master + - queue + paths: ++ - '.github/workflows/rolling.yaml' + - '**.h' + - '**.c' + - '**Makefile*' +diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml +index 0416fa9e..7943ebb8 100644 +--- a/.github/workflows/spelling.yml ++++ b/.github/workflows/spelling.yml +@@ -63,7 +63,9 @@ on: + tags-ignore: + - "**" + paths: ++ - '.github/workflows/spelling.yml' + - 'README*' ++ - 'NEWS.md' + - '**.3' + - '**.5' + - '**.8' diff --git a/0022-multipath-tools-add-TGTDIR-option.patch b/0022-multipath-tools-add-TGTDIR-option.patch new file mode 100644 index 0000000..d26fb18 --- /dev/null +++ b/0022-multipath-tools-add-TGTDIR-option.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 17 Apr 2024 14:44:45 +0200 +Subject: [PATCH] multipath-tools: add TGTDIR option + +TGTDIR is a convenience option for developers for building multipath-tools such +that compiled-in paths of the plugins, config files, etc. match an +installation under some optional path. See README.md for instructions and +examples. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + .github/actions/spelling/expect.txt | 2 ++ + Makefile.inc | 8 +++---- + README.md | 33 +++++++++++++++++++++++++++++ + 3 files changed, 39 insertions(+), 4 deletions(-) + +diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt +index 5906403d..fc9f22f8 100644 +--- a/.github/actions/spelling/expect.txt ++++ b/.github/actions/spelling/expect.txt +@@ -167,6 +167,7 @@ retrigger + rhabarber + rootprefix + rootprefixdir ++rpmbuild + rport + rtpi + sas +@@ -200,6 +201,7 @@ tcp + TESTDEPS + testname + tgill ++TGTDIR + TIDS + tmo + tpg +diff --git a/Makefile.inc b/Makefile.inc +index 5668e638..81b86cd8 100644 +--- a/Makefile.inc ++++ b/Makefile.inc +@@ -101,9 +101,9 @@ WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implici + $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) + CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \ + -D_FILE_OFFSET_BITS=64 \ +- -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \ +- -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \ +- -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DSTATE_DIR=\"$(statedir)\" \ ++ -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(TGTDIR)$(plugindir)\" \ ++ -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(TGTDIR)$(configdir)\" \ ++ -DDEFAULT_CONFIGFILE=\"$(TGTDIR)$(configfile)\" -DSTATE_DIR=\"$(TGTDIR)$(statedir)\" \ + -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP + CFLAGS := -std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe + BIN_CFLAGS := -fPIE -DPIE +@@ -149,4 +149,4 @@ NV_VERSION_SCRIPT = $(DEVLIB:%.so=%-nv.version) + + %: %.in + @echo creating $@ +- $(Q)sed 's:@CONFIGFILE@:'$(configfile)':g;s:@CONFIGDIR@:'$(configdir)':g;s:@STATE_DIR@:'$(statedir)':g;s:@RUNTIME_DIR@:'$(runtimedir)':g;s/@MODPROBE_UNIT@/'$(MODPROBE_UNIT)'/g;s:@BINDIR@:'$(bindir)':g' $< >$@ ++ $(Q)sed 's:@CONFIGFILE@:'$(TGTDIR)$(configfile)':g;s:@CONFIGDIR@:'$(TGTDIR)$(configdir)':g;s:@STATE_DIR@:'$(TGTDIR)$(statedir)':g;s:@RUNTIME_DIR@:'$(runtimedir)':g;s/@MODPROBE_UNIT@/'$(MODPROBE_UNIT)'/g;s:@BINDIR@:'$(bindir)':g' $< >$@ +diff --git a/README.md b/README.md +index d4f35f57..7207b14c 100644 +--- a/README.md ++++ b/README.md +@@ -151,6 +151,39 @@ sufficient control. See `Makefile.inc` for even more fine-grained control. + On such distributions, override `unitdir` and `libudevdir` to use systemd's + `rootprefix`: `make libudevdir=/lib/udev unitdir=/lib/systemd/system` + ++### prefix, DESTDIR and TGTDIR ++ ++`prefix` and related variables are included in compiled-in paths like ++`plugindir` and are used by `make install`. Using `prefix` is useful if ++multipath-tools is built locally on the same host where it's supposed to be ++installed. ++ ++By convention, the `DESTDIR` variable is prepended to all paths by `make ++install`, but not to any compiled-in paths. ++It is useful if the software is built on one system (build host) but intended ++to be run on another system (installation host). This is typically used in build ++systems like *rpmbuild* to set a root directory for all the installed ++files. ++ ++On the contrary, the `TGTDIR` variable is used for compiled-in paths only, and ++ignored by `make install`. It is useful for running multipath-tools in a separate ++subdirectory in the installation host, mostly for testing / development ++purposes. ++ ++For example, ++ ++ make prefix=/opt DESTDIR=/build TGTDIR=/test install ++ ++will install plugins into `/build/opt/lib64/multipath` on the build ++host. On the installation host, the plugins will be expected to be found under ++`/test/opt/lib64/multipath`. If the developer runs ++ ++ rsync -a $BUILD_HOST:$DESTDIR/ $INSTALL_HOST:$TGTDIR/ ++ ++and adds `$TGTDIR/lib64` to `LD_LIBRARY_PATH` on the installation host, the ++multipath binaries installed under `$TGTDIR` will find their plugins and ++configuration files in the expected compiled-in paths. ++ + ### Compiler Options + + Use `OPTFLAGS` to change optimization-related compiler options; diff --git a/0023-libmultipath-move-get_udev_for_mpp-to-sysfs.c.patch b/0023-libmultipath-move-get_udev_for_mpp-to-sysfs.c.patch new file mode 100644 index 0000000..b59f879 --- /dev/null +++ b/0023-libmultipath-move-get_udev_for_mpp-to-sysfs.c.patch @@ -0,0 +1,87 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 17 Apr 2024 17:18:18 +0200 +Subject: [PATCH] libmultipath: move get_udev_for_mpp to sysfs.c + +No functional changes, just code movement. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/configure.c | 20 -------------------- + libmultipath/sysfs.c | 19 +++++++++++++++++++ + libmultipath/sysfs.h | 4 ++++ + 3 files changed, 23 insertions(+), 20 deletions(-) + +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index 4ecf6ba4..89ac03d5 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -453,26 +453,6 @@ pgcmp (struct multipath * mpp, struct multipath * cmpp) + return r; + } + +-static struct udev_device * +-get_udev_for_mpp(const struct multipath *mpp) +-{ +- dev_t devnum; +- struct udev_device *udd; +- +- if (!mpp || !has_dm_info(mpp)) { +- condlog(1, "%s called with empty mpp", __func__); +- return NULL; +- } +- +- devnum = makedev(mpp->dmi.major, mpp->dmi.minor); +- udd = udev_device_new_from_devnum(udev, 'b', devnum); +- if (!udd) { +- condlog(1, "failed to get udev device for %s", mpp->alias); +- return NULL; +- } +- return udd; +-} +- + void trigger_partitions_udev_change(struct udev_device *dev, + const char *action, int len) + { +diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c +index 328951ed..afe9de91 100644 +--- a/libmultipath/sysfs.c ++++ b/libmultipath/sysfs.c +@@ -339,3 +339,22 @@ bool sysfs_is_multipathed(struct path *pp, bool set_wwid) + + return found; + } ++ ++struct udev_device *get_udev_for_mpp(const struct multipath *mpp) ++{ ++ dev_t devnum; ++ struct udev_device *udd; ++ ++ if (!mpp || !has_dm_info(mpp)) { ++ condlog(1, "%s called with empty mpp", __func__); ++ return NULL; ++ } ++ ++ devnum = makedev(mpp->dmi.major, mpp->dmi.minor); ++ udd = udev_device_new_from_devnum(udev, 'b', devnum); ++ if (!udd) { ++ condlog(1, "failed to get udev device for %s", mpp->alias); ++ return NULL; ++ } ++ return udd; ++} +diff --git a/libmultipath/sysfs.h b/libmultipath/sysfs.h +index 2db86bd6..3be3f665 100644 +--- a/libmultipath/sysfs.h ++++ b/libmultipath/sysfs.h +@@ -39,4 +39,8 @@ do { \ + int sysfs_get_size (struct path *pp, unsigned long long * size); + int sysfs_check_holders(char * check_devt, char * new_devt); + bool sysfs_is_multipathed(struct path *pp, bool set_wwid); ++ ++struct multipath; ++struct udev_device *get_udev_for_mpp(const struct multipath *mpp); ++ + #endif diff --git a/0024-libmultipath-add-mp_find_path_by_devt.patch b/0024-libmultipath-add-mp_find_path_by_devt.patch new file mode 100644 index 0000000..8a85be2 --- /dev/null +++ b/0024-libmultipath-add-mp_find_path_by_devt.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 17 Apr 2024 14:57:33 +0200 +Subject: [PATCH] libmultipath: add mp_find_path_by_devt() + +A helper function that searches a struct multipath by dev_t, and +works whether or not mpp->paths is currently available. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/structs.c | 19 +++++++++++++++++++ + libmultipath/structs.h | 3 +++ + 2 files changed, 22 insertions(+) + +diff --git a/libmultipath/structs.c b/libmultipath/structs.c +index 74e31a13..e248fb51 100644 +--- a/libmultipath/structs.c ++++ b/libmultipath/structs.c +@@ -526,6 +526,25 @@ find_path_by_devt (const struct _vector *pathvec, const char * dev_t) + return NULL; + } + ++struct path *mp_find_path_by_devt(const struct multipath *mpp, const char *devt) ++{ ++ struct path *pp; ++ struct pathgroup *pgp; ++ unsigned int i, j; ++ ++ pp = find_path_by_devt(mpp->paths, devt); ++ if (pp) ++ return pp; ++ ++ vector_foreach_slot (mpp->pg, pgp, i){ ++ vector_foreach_slot (pgp->paths, pp, j){ ++ if (!strcmp(pp->dev_t, devt)) ++ return pp; ++ } ++ } ++ return NULL; ++} ++ + static int do_pathcount(const struct multipath *mpp, const int *states, + unsigned int nr_states) + { +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index 734905e2..a25eb9d5 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -568,6 +568,9 @@ struct path * find_path_by_devt (const struct _vector *pathvec, const char *devt + struct path * find_path_by_dev (const struct _vector *pathvec, const char *dev); + struct path * first_path (const struct multipath *mpp); + ++struct path *mp_find_path_by_devt(const struct multipath *mpp, const char *devt); ++ ++ + int pathcount (const struct multipath *, int); + int count_active_paths(const struct multipath *); + int count_active_pending_paths(const struct multipath *); diff --git a/0025-Revert-libmultipath-fix-max_sectors_kb-on-adding-pat.patch b/0025-Revert-libmultipath-fix-max_sectors_kb-on-adding-pat.patch new file mode 100644 index 0000000..aaa0e9f --- /dev/null +++ b/0025-Revert-libmultipath-fix-max_sectors_kb-on-adding-pat.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 11 Apr 2024 17:20:14 +0200 +Subject: [PATCH] Revert "libmultipath: fix max_sectors_kb on adding path" + +This reverts commit bbb77f318ee483292f50a7782aecaecc7e60f727. +Reviewed-by: Benjamin Marzinski + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/configure.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index 89ac03d5..13602f3f 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -575,12 +575,11 @@ sysfs_set_max_sectors_kb(struct multipath *mpp, int is_reload) + ssize_t len; + int i, j, ret, err = 0; + struct udev_device *udd; +- int max_sectors_kb = mpp->max_sectors_kb; ++ int max_sectors_kb; + +- /* by default, do not initialize max_sectors_kb on the device */ +- if (max_sectors_kb == MAX_SECTORS_KB_UNDEF && !is_reload) ++ if (mpp->max_sectors_kb == MAX_SECTORS_KB_UNDEF) + return 0; +- /* on reload, re-apply the user tuning on all the path devices */ ++ max_sectors_kb = mpp->max_sectors_kb; + if (is_reload) { + if (!has_dm_info(mpp) && + dm_get_info(mpp->alias, &mpp->dmi) != 0) { diff --git a/0026-libmultipath-Only-set-max_sectors_kb-on-map-creation.patch b/0026-libmultipath-Only-set-max_sectors_kb-on-map-creation.patch new file mode 100644 index 0000000..c82cfe7 --- /dev/null +++ b/0026-libmultipath-Only-set-max_sectors_kb-on-map-creation.patch @@ -0,0 +1,122 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 16 Apr 2024 22:20:46 +0200 +Subject: [PATCH] libmultipath: Only set max_sectors_kb on map creation + +Changing max_sectors_kb on a live map is dangerous. When I/O occurs while the +max_sectors_kb value of a map is larger than that of any of its paths, I/O +errors like this may result: + + blk_insert_cloned_request: over max size limit. (127 > 126) + +This situation must be strictly avoided. The kernel makes sure that the +map's limits match those of the paths when the map is created. But setting +max_sectors_kb on path devices before reloading is dangerous, even if we +read the value from the map's max_sectors_kb beforehand. The reason for +this is that the sysfs value max_sectors_kb is the kernel's max_sectors +divided by 2, and user space has no way to figure out if the kernel-internal +value is odd or even. Thus by writing back the value just read to +max_sectors_kb, one might actually decrease the kernel value by one. + +The only safe way to set max_sectors_kb on a live map would be to suspend +it, flushing all outstanding IO, then the path max_sectors_kb, reload, +and resume. + +Since commit 8fd4868 ("libmultipath: don't set max_sectors_kb on reloads"), +we don't set the configured max_sectors_kb any more. But as shown above, +this is not safe. So really only set max_sectors_kb when creating a map. + +Users who have stacked block devices on top of multipath, as described in the +commit message of 8fd4868 must make sure that the max_sectors_kb setting is +correct when the multipath map is first created. Decreasing the map's +max_sectors_kb value (without touching the paths) should actually be possible +in this situation, because stacked block devices are usually bio-based, and +bio-based IO (in contrast to request-based) can be split if the lower-level +device has can't handle the size of the I/O. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/configure.c | 38 ++++---------------------------------- + 1 file changed, 4 insertions(+), 34 deletions(-) + +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index 13602f3f..8cbb2a88 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -566,46 +566,18 @@ trigger_paths_udev_change(struct multipath *mpp, bool is_mpath) + mpp->needs_paths_uevent = 0; + } + +-static int +-sysfs_set_max_sectors_kb(struct multipath *mpp, int is_reload) ++static int sysfs_set_max_sectors_kb(struct multipath *mpp) + { + struct pathgroup * pgp; + struct path *pp; + char buff[11]; + ssize_t len; + int i, j, ret, err = 0; +- struct udev_device *udd; +- int max_sectors_kb; + + if (mpp->max_sectors_kb == MAX_SECTORS_KB_UNDEF) + return 0; +- max_sectors_kb = mpp->max_sectors_kb; +- if (is_reload) { +- if (!has_dm_info(mpp) && +- dm_get_info(mpp->alias, &mpp->dmi) != 0) { +- condlog(1, "failed to get dm info for %s", mpp->alias); +- return 1; +- } +- udd = get_udev_for_mpp(mpp); +- if (!udd) { +- condlog(1, "failed to get udev device to set max_sectors_kb for %s", mpp->alias); +- return 1; +- } +- ret = sysfs_attr_get_value(udd, "queue/max_sectors_kb", buff, +- sizeof(buff)); +- udev_device_unref(udd); +- if (!sysfs_attr_value_ok(ret, sizeof(buff))) { +- condlog(1, "failed to get current max_sectors_kb from %s", mpp->alias); +- return 1; +- } +- if (sscanf(buff, "%u\n", &max_sectors_kb) != 1) { +- condlog(1, "can't parse current max_sectors_kb from %s", +- mpp->alias); +- return 1; +- } +- } +- snprintf(buff, 11, "%d", max_sectors_kb); +- len = strlen(buff); ++ ++ len = snprintf(buff, sizeof(buff), "%d", mpp->max_sectors_kb); + + vector_foreach_slot (mpp->pg, pgp, i) { + vector_foreach_slot(pgp->paths, pp, j) { +@@ -923,7 +895,7 @@ int domap(struct multipath *mpp, char *params, int is_daemon) + return DOMAP_RETRY; + } + +- sysfs_set_max_sectors_kb(mpp, 0); ++ sysfs_set_max_sectors_kb(mpp); + if (is_daemon && mpp->ghost_delay > 0 && count_active_paths(mpp) && + pathcount(mpp, PATH_UP) == 0) + mpp->ghost_delay_tick = mpp->ghost_delay; +@@ -934,7 +906,6 @@ int domap(struct multipath *mpp, char *params, int is_daemon) + + case ACT_RELOAD: + case ACT_RELOAD_RENAME: +- sysfs_set_max_sectors_kb(mpp, 1); + if (mpp->ghost_delay_tick > 0 && pathcount(mpp, PATH_UP)) + mpp->ghost_delay_tick = 0; + r = dm_addmap_reload(mpp, params, 0); +@@ -942,7 +913,6 @@ int domap(struct multipath *mpp, char *params, int is_daemon) + + case ACT_RESIZE: + case ACT_RESIZE_RENAME: +- sysfs_set_max_sectors_kb(mpp, 1); + if (mpp->ghost_delay_tick > 0 && pathcount(mpp, PATH_UP)) + mpp->ghost_delay_tick = 0; + r = dm_addmap_reload(mpp, params, 1); diff --git a/0027-libmultipath-set-max_sectors_kb-in-adopt_paths.patch b/0027-libmultipath-set-max_sectors_kb-in-adopt_paths.patch new file mode 100644 index 0000000..a4389df --- /dev/null +++ b/0027-libmultipath-set-max_sectors_kb-in-adopt_paths.patch @@ -0,0 +1,233 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 16 Apr 2024 23:59:03 +0200 +Subject: [PATCH] libmultipath: set max_sectors_kb in adopt_paths() + +As explained in the previous commit, setting max_sectors_kb for +paths that are members of a live map is dangerous. But as long as +a path is not a member of a map, setting max_sectors_kb poses no risk. +Set the parameter in adopt_paths(), for paths that aren't members +of the map yet. In order to determine whether or not a path is currently +member of the map, adopt_paths() needs to passed the current member list. If +(and only if) it's called from coalesce_paths(), the passed struct multipath +doesn not represent the current state of the map; adopt_paths() must therefore +get a new argument current_mpp that represents the kernel state. + +We must still call sysfs_set_max_sectors_kb() from domap() in the ACT_CREATE +case, because when adopt_paths is called from coalesce_paths() for a map that +doesn't exist yet, mpp->max_sectors_kb is not set. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/configure.c | 2 +- + libmultipath/structs_vec.c | 62 ++++++++++++++++++++++++++++++++++---- + libmultipath/structs_vec.h | 6 ++-- + multipathd/main.c | 6 ++-- + tests/Makefile | 2 +- + tests/test-lib.c | 9 +++++- + 6 files changed, 73 insertions(+), 14 deletions(-) + +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index 8cbb2a88..b5c701fa 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -1105,7 +1105,7 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid, + /* + * at this point, we know we really got a new mp + */ +- mpp = add_map_with_path(vecs, pp1, 0); ++ mpp = add_map_with_path(vecs, pp1, 0, cmpp); + if (!mpp) { + orphan_path(pp1, "failed to create multipath device"); + continue; +diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c +index 0fc608c2..c0c5cc90 100644 +--- a/libmultipath/structs_vec.c ++++ b/libmultipath/structs_vec.c +@@ -242,7 +242,38 @@ static bool update_pathvec_from_dm(vector pathvec, struct multipath *mpp, + return must_reload; + } + +-int adopt_paths(vector pathvec, struct multipath *mpp) ++static bool set_path_max_sectors_kb(const struct path *pp, int max_sectors_kb) ++{ ++ char buf[11]; ++ ssize_t len; ++ int ret, current; ++ bool rc = false; ++ ++ if (max_sectors_kb == MAX_SECTORS_KB_UNDEF) ++ return rc; ++ ++ if (sysfs_attr_get_value(pp->udev, "queue/max_sectors_kb", buf, sizeof(buf)) <= 0 ++ || sscanf(buf, "%d\n", ¤t) != 1) ++ current = MAX_SECTORS_KB_UNDEF; ++ if (current == max_sectors_kb) ++ return rc; ++ ++ len = snprintf(buf, sizeof(buf), "%d", max_sectors_kb); ++ ret = sysfs_attr_set_value(pp->udev, "queue/max_sectors_kb", buf, len); ++ if (ret != len) ++ log_sysfs_attr_set_value(3, ret, ++ "failed setting max_sectors_kb on %s", ++ pp->dev); ++ else { ++ condlog(3, "%s: set max_sectors_kb to %d for %s", __func__, ++ max_sectors_kb, pp->dev); ++ rc = true; ++ } ++ return rc; ++} ++ ++int adopt_paths(vector pathvec, struct multipath *mpp, ++ const struct multipath *current_mpp) + { + int i, ret; + struct path * pp; +@@ -285,9 +316,28 @@ int adopt_paths(vector pathvec, struct multipath *mpp) + continue; + } + +- if (!find_path_by_devt(mpp->paths, pp->dev_t) && +- store_path(mpp->paths, pp)) +- goto err; ++ if (!find_path_by_devt(mpp->paths, pp->dev_t)) { ++ ++ if (store_path(mpp->paths, pp)) ++ goto err; ++ /* ++ * Setting max_sectors_kb on live paths is dangerous. ++ * But we can do it here on a path that isn't yet part ++ * of the map. If this value is lower than the current ++ * max_sectors_kb and the map is reloaded, the map's ++ * max_sectors_kb will be safely adjusted by the kernel. ++ * ++ * We must make sure that the path is not part of the ++ * map yet. Normally we can check this in mpp->paths. ++ * But if adopt_paths is called from coalesce_paths, ++ * we need to check the separate struct multipath that ++ * has been obtained from map_discovery(). ++ */ ++ if (!current_mpp || ++ !mp_find_path_by_devt(current_mpp, pp->dev_t)) ++ mpp->need_reload = mpp->need_reload || ++ set_path_max_sectors_kb(pp, mpp->max_sectors_kb); ++ } + + pp->mpp = mpp; + condlog(3, "%s: ownership set to %s", +@@ -693,7 +743,7 @@ find_existing_alias (struct multipath * mpp, + } + + struct multipath *add_map_with_path(struct vectors *vecs, struct path *pp, +- int add_vec) ++ int add_vec, const struct multipath *current_mpp) + { + struct multipath * mpp; + struct config *conf = NULL; +@@ -721,7 +771,7 @@ struct multipath *add_map_with_path(struct vectors *vecs, struct path *pp, + goto out; + mpp->size = pp->size; + +- if (adopt_paths(vecs->pathvec, mpp) || pp->mpp != mpp || ++ if (adopt_paths(vecs->pathvec, mpp, current_mpp) || pp->mpp != mpp || + find_slot(mpp->paths, pp) == -1) + goto out; + +diff --git a/libmultipath/structs_vec.h b/libmultipath/structs_vec.h +index 3253f1bb..dbc43058 100644 +--- a/libmultipath/structs_vec.h ++++ b/libmultipath/structs_vec.h +@@ -13,7 +13,8 @@ struct vectors { + + void set_no_path_retry(struct multipath *mpp); + +-int adopt_paths (vector pathvec, struct multipath * mpp); ++int adopt_paths (vector pathvec, struct multipath *mpp, ++ const struct multipath *current_mpp); + void orphan_path (struct path * pp, const char *reason); + void set_path_removed(struct path *pp); + +@@ -28,7 +29,8 @@ void remove_maps (struct vectors * vecs); + + void sync_map_state (struct multipath *); + struct multipath * add_map_with_path (struct vectors * vecs, +- struct path * pp, int add_vec); ++ struct path * pp, int add_vec, ++ const struct multipath *current_mpp); + void update_queue_mode_del_path(struct multipath *mpp); + void update_queue_mode_add_path(struct multipath *mpp); + int update_multipath_table (struct multipath *mpp, vector pathvec, int flags); +diff --git a/multipathd/main.c b/multipathd/main.c +index dd17d5c3..d8518a92 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -636,7 +636,7 @@ update_map (struct multipath *mpp, struct vectors *vecs, int new_map) + + retry: + condlog(4, "%s: updating new map", mpp->alias); +- if (adopt_paths(vecs->pathvec, mpp)) { ++ if (adopt_paths(vecs->pathvec, mpp, NULL)) { + condlog(0, "%s: failed to adopt paths for new map update", + mpp->alias); + retries = -1; +@@ -1231,7 +1231,7 @@ rescan: + if (mpp) { + condlog(4,"%s: adopting all paths for path %s", + mpp->alias, pp->dev); +- if (adopt_paths(vecs->pathvec, mpp) || pp->mpp != mpp || ++ if (adopt_paths(vecs->pathvec, mpp, NULL) || pp->mpp != mpp || + find_slot(mpp->paths, pp) == -1) + goto fail; /* leave path added to pathvec */ + +@@ -1245,7 +1245,7 @@ rescan: + return 0; + } + condlog(4,"%s: creating new map", pp->dev); +- if ((mpp = add_map_with_path(vecs, pp, 1))) { ++ if ((mpp = add_map_with_path(vecs, pp, 1, NULL))) { + mpp->action = ACT_CREATE; + /* + * We don't depend on ACT_CREATE, as domap will +diff --git a/tests/Makefile b/tests/Makefile +index d1d52dde..4005204a 100644 +--- a/tests/Makefile ++++ b/tests/Makefile +@@ -45,7 +45,7 @@ dmevents-test_OBJDEPS = $(multipathdir)/devmapper.o + dmevents-test_LIBDEPS = -lpthread -ldevmapper -lurcu + hwtable-test_TESTDEPS := test-lib.o + hwtable-test_OBJDEPS := $(multipathdir)/discovery.o $(multipathdir)/blacklist.o \ +- $(multipathdir)/structs.o $(multipathdir)/propsel.o ++ $(multipathdir)/structs_vec.o $(multipathdir)/structs.o $(multipathdir)/propsel.o + hwtable-test_LIBDEPS := -ludev -lpthread -ldl + blacklist-test_TESTDEPS := test-log.o + blacklist-test_LIBDEPS := -ludev +diff --git a/tests/test-lib.c b/tests/test-lib.c +index cdb2780d..88f35e94 100644 +--- a/tests/test-lib.c ++++ b/tests/test-lib.c +@@ -152,6 +152,13 @@ int __wrap_sysfs_get_size(struct path *pp, unsigned long long *sz) + return 0; + } + ++int __wrap_sysfs_attr_set_value(struct udev_device *dev, const char *attr_name, ++ const char * value, size_t value_len) ++{ ++ condlog(5, "%s: %s", __func__, value); ++ return value_len; ++} ++ + void *__wrap_udev_device_get_parent_with_subsystem_devtype( + struct udev_device *ud, const char *subsys, char *type) + { +@@ -400,7 +407,7 @@ struct multipath *__mock_multipath(struct vectors *vecs, struct path *pp) + /* pathinfo() call in adopt_paths */ + mock_pathinfo(DI_CHECKER|DI_PRIO, &mop); + +- mp = add_map_with_path(vecs, pp, 1); ++ mp = add_map_with_path(vecs, pp, 1, NULL); + assert_ptr_not_equal(mp, NULL); + + /* TBD: mock setup_map() ... */ diff --git a/0028-libmultipath-add-wildcard-k-for-printing-max_sectors.patch b/0028-libmultipath-add-wildcard-k-for-printing-max_sectors.patch new file mode 100644 index 0000000..9b66bbb --- /dev/null +++ b/0028-libmultipath-add-wildcard-k-for-printing-max_sectors.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 17 Apr 2024 17:19:43 +0200 +Subject: [PATCH] libmultipath: add wildcard %k for printing max_sectors_kb + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/print.c | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/libmultipath/print.c b/libmultipath/print.c +index 360308d2..efd5a16a 100644 +--- a/libmultipath/print.c ++++ b/libmultipath/print.c +@@ -32,6 +32,7 @@ + #include "util.h" + #include "foreign.h" + #include "strbuf.h" ++#include "sysfs.h" + + #define PRINT_PATH_LONG "%w %i %d %D %p %t %T %s %o" + #define PRINT_PATH_INDENT "%i %d %D %t %T %o" +@@ -431,6 +432,27 @@ snprint_multipath_vpd_data(struct strbuf *buff, + return append_strbuf_str(buff, "[undef]"); + } + ++static void cleanup_udev_device(struct udev_device **udd) ++{ ++ if (*udd) ++ udev_device_unref(*udd); ++} ++ ++static int ++snprint_multipath_max_sectors_kb(struct strbuf *buff, const struct multipath *mpp) ++{ ++ char buf[11]; ++ int max_sectors_kb; ++ struct udev_device *udd __attribute__((cleanup(cleanup_udev_device))) ++ = get_udev_for_mpp(mpp); ++ ++ if (!udd || ++ sysfs_attr_get_value(udd, "queue/max_sectors_kb", buf, sizeof(buf)) <= 0 || ++ sscanf(buf, "%d\n", &max_sectors_kb) != 1) ++ return print_strbuf(buff, "n/a"); ++ return print_strbuf(buff, "%d", max_sectors_kb); ++} ++ + /* + * path info printing functions + */ +@@ -790,6 +812,20 @@ snprint_alua_tpg(struct strbuf *buff, const struct path * pp) + return print_strbuf(buff, "0x%04x", pp->tpg_id); + } + ++static int ++snprint_path_max_sectors_kb(struct strbuf *buff, const struct path *pp) ++{ ++ char buf[11]; ++ int max_sectors_kb; ++ ++ if (!pp->udev || ++ sysfs_attr_get_value(pp->udev, "queue/max_sectors_kb", ++ buf, sizeof(buf)) <= 0 || ++ sscanf(buf, "%d\n", &max_sectors_kb) != 1) ++ return print_strbuf(buff, "n/a"); ++ return print_strbuf(buff, "%d", max_sectors_kb); ++} ++ + static const struct multipath_data mpd[] = { + {'n', "name", snprint_name}, + {'w', "uuid", snprint_multipath_uuid}, +@@ -815,6 +851,7 @@ static const struct multipath_data mpd[] = { + {'e', "rev", snprint_multipath_rev}, + {'G', "foreign", snprint_multipath_foreign}, + {'g', "vpd page data", snprint_multipath_vpd_data}, ++ {'k', "max_sectors_kb",snprint_multipath_max_sectors_kb}, + }; + + static const struct path_data pd[] = { +@@ -845,6 +882,7 @@ static const struct path_data pd[] = { + {'I', "init_st", snprint_initialized}, + {'L', "LUN hex", snprint_path_lunhex}, + {'A', "TPG", snprint_alua_tpg}, ++ {'k', "max_sectors_kb",snprint_path_max_sectors_kb}, + }; + + static const struct pathgroup_data pgd[] = { diff --git a/0029-multipath.conf-5-update-documentation-for-max_sector.patch b/0029-multipath.conf-5-update-documentation-for-max_sector.patch new file mode 100644 index 0000000..dcdf164 --- /dev/null +++ b/0029-multipath.conf-5-update-documentation-for-max_sector.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 17 Apr 2024 18:59:04 +0200 +Subject: [PATCH] multipath.conf(5): update documentation for max_sectors_kb + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipath/multipath.conf.5.in | 33 +++++++++++++++++++++++++++++---- + 1 file changed, 29 insertions(+), 4 deletions(-) + +diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in +index c788c180..b29a75fe 100644 +--- a/multipath/multipath.conf.5.in ++++ b/multipath/multipath.conf.5.in +@@ -1311,11 +1311,36 @@ The default is: \fB0\fR + . + .TP + .B max_sectors_kb +-Sets the max_sectors_kb device parameter on all path devices and the multipath +-device to the specified value. ++Sets the \fImax_sectors_kb\fR device parameter on some path devices and the multipath ++device to the specified value. \fImax_sectors_kb\fR is the largest I/O size, in units ++of 1024 bytes, that the kernel allows for a single I/O request. For hardware devices ++like SCSI disks, this value is limited by the capabilities of the hardware. ++It is crucial that the value of a multipath map is never higher than the minimum value of ++of all its path devices. This is ensured by the kernel when a multipath map ++is loaded, but manipulating the values of a map or either of its paths while the ++map is live can cause race conditions and I/O errors. Therefore this value is only ++enforced by multipathd when a multipath map is first created, or when a path device ++is added to a map. In both cases, race conditions are avoided by the kernel. + .RS +-.TP +-The default is: in \fB/sys/block//queue/max_sectors_kb\fR ++.PP ++Setting \fImax_sectors_kb\fR does not guarantee that all path devices will have this ++value set. It is not an error if the value of a path device is higher than that of ++the containing multipath map. It is also not an error if the actual limit of a map is ++lower than the value in \fI@CONFIGFILE@\fR. This can happen if the hardware limits of one ++or more path devices are lower than the configured value. ++.PP ++Normally the kernel and its device drivers take care of the maximum ++I/O size, and administrators do not need to bother about \fImax_sectors_kb\fR. ++But some hardware devices may report incorrect I/O size limits, or other components ++in the environment (e.g. the fabric) may impose constraints that the kernel cannot ++detect. In such cases setting \fImax_sectors_kb\fR makes sense. It should be set when ++maps are first created, and not be changed thereafter. ++If the setting \fBmust\fR be changed for a live map, set the ++value in \fI@CONFIGFILE@\fR, run \fBmultipathd reconfigure\fR, and use ++\fBmultipathd del path \fR and \fBmultipathd add path \fR to ++delete and re-add the same path device. ++.LP ++The default is: \fBundefined\fR. + .RE + . + . diff --git a/0030-multipath-tools-simplify-comment-in-hwtable.patch b/0030-multipath-tools-simplify-comment-in-hwtable.patch new file mode 100644 index 0000000..59090a7 --- /dev/null +++ b/0030-multipath-tools-simplify-comment-in-hwtable.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Xose Vazquez Perez +Date: Sun, 28 Apr 2024 01:45:35 +0200 +Subject: [PATCH] multipath-tools: simplify comment in hwtable + +Instead of adding the new 5300 model, replace them with wildcards. + +Cc: Martin Wilck +Cc: Benjamin Marzinski +Cc: Christophe Varoqui +Cc: DM-DEVEL ML +Signed-off-by: Xose Vazquez Perez +Reviewed-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/hwtable.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c +index 640bf347..7aac3f37 100644 +--- a/libmultipath/hwtable.c ++++ b/libmultipath/hwtable.c +@@ -683,8 +683,8 @@ static struct hwentry default_hw[] = { + .pgfailback = -FAILBACK_IMMEDIATE, + }, + { +- // Storwize V5000/V7000 lines / SAN Volume Controller (SVC) / Flex System V7000 +- // FlashSystem V840/V9000/5000/5100/5200/7200/7300/9100/9200/9200R/9500 ++ // Storwize V5000/V7000 lines / SAN Volume Controller (SVC) ++ // Flex System V7000 / FlashSystem V840/V9000 and 5x00/7x00/9x00 + .vendor = "IBM", + .product = "^2145", + .no_path_retry = NO_PATH_RETRY_QUEUE, diff --git a/0031-multipath-tools-unify-text-in-multipath.conf.5.patch b/0031-multipath-tools-unify-text-in-multipath.conf.5.patch new file mode 100644 index 0000000..b6d9af3 --- /dev/null +++ b/0031-multipath-tools-unify-text-in-multipath.conf.5.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Xose Vazquez Perez +Date: Sun, 28 Apr 2024 01:45:36 +0200 +Subject: [PATCH] multipath-tools: unify text in multipath.conf.5 + +Cc: Martin Wilck +Cc: Benjamin Marzinski +Cc: Christophe Varoqui +Cc: DM-DEVEL ML +Signed-off-by: Xose Vazquez Perez +Reviewed-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + multipath/multipath.conf.5.in | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in +index b29a75fe..c1a19ebb 100644 +--- a/multipath/multipath.conf.5.in ++++ b/multipath/multipath.conf.5.in +@@ -187,7 +187,7 @@ The default is: \fBno\fR + . + .TP + .B multipath_dir +-(Deprecated) This option is not supported anymore, and the value is ignored. ++(Deprecated) This option is not supported anymore, and will be ignored. + . + . + .TP +@@ -277,7 +277,7 @@ The default is: \fBno\fR + . + .TP + .B pg_timeout +-(Deprecated) This option is not supported anymore, and the value is ignored. ++(Deprecated) This option is not supported anymore, and will be ignored. + . + . + .TP +@@ -322,7 +322,7 @@ The default is: \fBID_WWN\fR, for NVMe devices + . + .TP + .B getuid_callout +-(Deprecated) This option is not supported anymore, and the value is ignored. ++(Deprecated) This option is not supported anymore, and will be ignored. + . + . + .TP +@@ -995,7 +995,7 @@ The default is: \fB\fR + . + .TP + .B config_dir +-(Deprecated) This option is not supported anymore, and the value is ignored. ++(Deprecated) This option is not supported anymore, and will be ignored. + .RS + .TP + The compiled-in value is: \fB@CONFIGDIR@\fR +@@ -1295,7 +1295,7 @@ The default is: \fBno\fR + . + .TP + .B disable_changed_wwids +-(Deprecated) This option is not supported anymore, and the value is ignored. ++(Deprecated) This option is not supported anymore, and will be ignored. + .RE + . + . +@@ -1340,7 +1340,7 @@ value in \fI@CONFIGFILE@\fR, run \fBmultipathd reconfigure\fR, and use + \fBmultipathd del path \fR and \fBmultipathd add path \fR to + delete and re-add the same path device. + .LP +-The default is: \fBundefined\fR. ++The default is: \fB\fR + .RE + . + . diff --git a/0032-multipath-tools-update-man-pages-dates.patch b/0032-multipath-tools-update-man-pages-dates.patch new file mode 100644 index 0000000..c011eac --- /dev/null +++ b/0032-multipath-tools-update-man-pages-dates.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Xose Vazquez Perez +Date: Sun, 28 Apr 2024 01:45:37 +0200 +Subject: [PATCH] multipath-tools: update man pages dates + +Cc: Martin Wilck +Cc: Benjamin Marzinski +Cc: Christophe Varoqui +Cc: DM-DEVEL ML +Signed-off-by: Xose Vazquez Perez +Reviewed-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmpathpersist/mpath_persistent_reserve_in.3 | 2 +- + libmpathpersist/mpath_persistent_reserve_out.3 | 2 +- + multipath/multipath.8.in | 2 +- + multipath/multipath.conf.5.in | 2 +- + multipathd/multipathd.8.in | 2 +- + 5 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/libmpathpersist/mpath_persistent_reserve_in.3 b/libmpathpersist/mpath_persistent_reserve_in.3 +index 6cc35349..4ac43fa3 100644 +--- a/libmpathpersist/mpath_persistent_reserve_in.3 ++++ b/libmpathpersist/mpath_persistent_reserve_in.3 +@@ -6,7 +6,7 @@ + .\" Update the date below if you make any significant change. + .\" ---------------------------------------------------------------------------- + . +-.TH MPATH_PERSISTENT_RESERVE_IN 3 2018-06-15 Linux ++.TH MPATH_PERSISTENT_RESERVE_IN 3 2024-02-09 Linux + . + . + .\" ---------------------------------------------------------------------------- +diff --git a/libmpathpersist/mpath_persistent_reserve_out.3 b/libmpathpersist/mpath_persistent_reserve_out.3 +index 70e26028..3dbeae1f 100644 +--- a/libmpathpersist/mpath_persistent_reserve_out.3 ++++ b/libmpathpersist/mpath_persistent_reserve_out.3 +@@ -6,7 +6,7 @@ + .\" Update the date below if you make any significant change. + .\" ---------------------------------------------------------------------------- + . +-.TH MPATH_PERSISTENT_RESERVE_OUT 3 2018-06-15 Linux ++.TH MPATH_PERSISTENT_RESERVE_OUT 3 2024-02-09 Linux + . + . + .\" ---------------------------------------------------------------------------- +diff --git a/multipath/multipath.8.in b/multipath/multipath.8.in +index 348eb220..b88e9a4c 100644 +--- a/multipath/multipath.8.in ++++ b/multipath/multipath.8.in +@@ -6,7 +6,7 @@ + .\" Update the date below if you make any significant change. + .\" ---------------------------------------------------------------------------- + . +-.TH MULTIPATH 8 2021-11-12 Linux ++.TH MULTIPATH 8 2023-09-08 Linux + . + . + .\" ---------------------------------------------------------------------------- +diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in +index c1a19ebb..46d3685a 100644 +--- a/multipath/multipath.conf.5.in ++++ b/multipath/multipath.conf.5.in +@@ -6,7 +6,7 @@ + .\" Update the date below if you make any significant change. + .\" ---------------------------------------------------------------------------- + . +-.TH MULTIPATH.CONF 5 2023-06-15 Linux ++.TH MULTIPATH.CONF 5 2024-04-17 Linux + . + . + .\" ---------------------------------------------------------------------------- +diff --git a/multipathd/multipathd.8.in b/multipathd/multipathd.8.in +index f1cab3ff..12b77156 100644 +--- a/multipathd/multipathd.8.in ++++ b/multipathd/multipathd.8.in +@@ -6,7 +6,7 @@ + .\" Update the date below if you make any significant change. + .\" ---------------------------------------------------------------------------- + . +-.TH MULTIPATHD 8 2022-09-03 Linux ++.TH MULTIPATHD 8 2023-12-19 Linux + . + . + .\" ---------------------------------------------------------------------------- diff --git a/0033-libmultipath-export-partmap_in_use.patch b/0033-libmultipath-export-partmap_in_use.patch new file mode 100644 index 0000000..47a6772 --- /dev/null +++ b/0033-libmultipath-export-partmap_in_use.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 25 Apr 2024 19:35:13 -0400 +Subject: [PATCH] libmultipath: export partmap_in_use + +A future commit will make use of this function + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +--- + libmultipath/devmapper.c | 2 +- + libmultipath/devmapper.h | 1 + + libmultipath/libmultipath.version | 1 + + 3 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c +index 4ce7e82f..a87abf7e 100644 +--- a/libmultipath/devmapper.c ++++ b/libmultipath/devmapper.c +@@ -1043,7 +1043,7 @@ has_partmap(const char *name __attribute__((unused)), + return 1; + } + +-static int ++int + partmap_in_use(const char *name, void *data) + { + int part_count, *ret_count = (int *)data; +diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h +index a7d66604..93caa2aa 100644 +--- a/libmultipath/devmapper.h ++++ b/libmultipath/devmapper.h +@@ -57,6 +57,7 @@ enum { + DM_FLUSH_BUSY, + }; + ++int partmap_in_use(const char *name, void *data); + int _dm_flush_map (const char *, int, int, int, int); + int dm_flush_map_nopaths(const char * mapname, int deferred_remove); + #define dm_flush_map(mapname) _dm_flush_map(mapname, 1, 0, 0, 0) +diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version +index 724786d5..e070f296 100644 +--- a/libmultipath/libmultipath.version ++++ b/libmultipath/libmultipath.version +@@ -141,6 +141,7 @@ global: + need_io_err_check; + orphan_path; + parse_prkey_flags; ++ partmap_in_use; + pathcount; + path_discovery; + path_get_tpgs; diff --git a/0034-libmultipath-change-flush_on_last_del-to-fix-a-multi.patch b/0034-libmultipath-change-flush_on_last_del-to-fix-a-multi.patch new file mode 100644 index 0000000..7c36521 --- /dev/null +++ b/0034-libmultipath-change-flush_on_last_del-to-fix-a-multi.patch @@ -0,0 +1,346 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 25 Apr 2024 19:35:14 -0400 +Subject: [PATCH] libmultipath: change flush_on_last_del to fix a multipathd + hang + +Commit 9bd3482e ("multipathd: make flush_map() delete maps like the +multipath command") fixed an issue where deleting a queueing multipath +device through multipathd could hang because the multipath device had +outstanding IO, even though the only openers of it at the time of +deletion were the kpartx partition devices. However it is still possible +to hang multipathd, because autoremoving the device when all paths have +been deleted doesn't disable queueing. To reproduce this hang: + +1. create a multipath device with a kpartx partition on top of it and +no_path_retry set to either "queue" or something long enough to run all +the commands in the reproducer before it disables queueing. +2. disable all the paths to the device with something like: + # echo offline > /sys/block//device/state +3. Write directly to the multipath device with something like: + # dd if=/dev/zero of=/dev/mapper/ bs=4K count=1 +4. delete all the paths to the device with something like: + # echo 1 > /sys/block//device/delete + +Multipathd will hang trying to delete the kpartx device because, as the +last opener, it must flush the multipath device before closing it. +Because it hangs holding the vecs_lock, multipathd will never disable +queueing on the device, so it will hang forever, even if no_path_retry +is set to a number. + +This hang can occur, even if deferred_remove is set. Since nothing has +the kpartx device opened, device-mapper does an immediate remove, which +will still hang. This means that even if deferred_remove is set, +multipathd still cannot delete a map while queueing is enabled. It must +either disable queueing or skip the autoremove. + +Mulitpath can currently be configured to avoid this hang by setting + +flush_on_last_del yes + +However there are good reasons why users wouldn't want to set that. They +may need to be able to survive having all paths getting temporarily +deleted. I should note that this is a pretty rare corner case, since +multipath automatically sets dev_loss_tmo so that it should not trigger +before queueing is disabled. + +This commit avoids the hang by changing the possible values for +flush_on_last_del to "never", "unused", and "always", and sets the +default to "unused". "always" works like "yes" did, "never" will not +disable queueing, and "unused" will only disable queueing if nothing has +the kpartx devices or the multipath device open. In order to be safe, if +the device has queue_if_no_paths set (and in case of "unused", the +device is in-use) the autoremove will be skipped. Also, instead of just +trusting the lack of "queue_if_no_paths" in the current mpp->features, +multipathd will tell the kernel to disable queueing, just to be sure it +actually is. + +I chose "unused" as the default because this should generally only cause +multipathd to work differently from the users perspective when nothing +has the multipath device open but it is queueing and there is +outstanding IO. Without this change, it would have hung instead of +failing the outstanding IO. However, I do understand that an argument +could be made that "never" makes more sense as default, even though it +will cause multipathd to skip autoremoves in cases where it wouldn't +before. The change to the behavior of deffered_remove will be +noticeable, but skipping an autoremove is much better than hanging. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +--- + libmultipath/defaults.h | 2 +- + libmultipath/dict.c | 72 +++++++++++++++++++++++++++++++---- + libmultipath/dict.h | 1 + + libmultipath/hwtable.c | 6 +-- + libmultipath/propsel.c | 4 +- + libmultipath/structs.h | 7 ++-- + multipath/multipath.conf.5.in | 20 +++++++--- + multipathd/main.c | 39 +++++++++++++++---- + 8 files changed, 122 insertions(+), 29 deletions(-) + +diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h +index 64b633f2..ed08c251 100644 +--- a/libmultipath/defaults.h ++++ b/libmultipath/defaults.h +@@ -43,7 +43,7 @@ + #define DEFAULT_PRIO PRIO_CONST + #define DEFAULT_PRIO_ARGS "" + #define DEFAULT_CHECKER TUR +-#define DEFAULT_FLUSH FLUSH_DISABLED ++#define DEFAULT_FLUSH FLUSH_UNUSED + #define DEFAULT_USER_FRIENDLY_NAMES USER_FRIENDLY_NAMES_OFF + #define DEFAULT_FORCE_SYNC 0 + #define UNSET_PARTITION_DELIM "/UNSET/" +diff --git a/libmultipath/dict.c b/libmultipath/dict.c +index 5af036b7..546103f2 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -791,14 +791,70 @@ declare_def_snprint(checker_timeout, print_nonzero) + declare_def_handler(allow_usb_devices, set_yes_no) + declare_def_snprint(allow_usb_devices, print_yes_no) + +-declare_def_handler(flush_on_last_del, set_yes_no_undef) +-declare_def_snprint_defint(flush_on_last_del, print_yes_no_undef, DEFAULT_FLUSH) +-declare_ovr_handler(flush_on_last_del, set_yes_no_undef) +-declare_ovr_snprint(flush_on_last_del, print_yes_no_undef) +-declare_hw_handler(flush_on_last_del, set_yes_no_undef) +-declare_hw_snprint(flush_on_last_del, print_yes_no_undef) +-declare_mp_handler(flush_on_last_del, set_yes_no_undef) +-declare_mp_snprint(flush_on_last_del, print_yes_no_undef) ++ ++static const char * const flush_on_last_del_optvals[] = { ++ [FLUSH_NEVER] = "never", ++ [FLUSH_ALWAYS] = "always", ++ [FLUSH_UNUSED] = "unused", ++}; ++ ++static int ++set_flush_on_last_del(vector strvec, void *ptr, const char *file, int line_nr) ++{ ++ int i; ++ int *flush_val_ptr = (int *)ptr; ++ char *buff; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ for (i = FLUSH_NEVER; i <= FLUSH_UNUSED; i++) { ++ if (flush_on_last_del_optvals[i] != NULL && ++ !strcmp(buff, flush_on_last_del_optvals[i])) { ++ *flush_val_ptr = i; ++ break; ++ } ++ } ++ ++ if (i > FLUSH_UNUSED) { ++ bool deprecated = true; ++ if (strcmp(buff, "no") == 0 || strcmp(buff, "0") == 0) ++ *flush_val_ptr = FLUSH_UNUSED; ++ else if (strcmp(buff, "yes") == 0 || strcmp(buff, "1") == 0) ++ *flush_val_ptr = FLUSH_ALWAYS; ++ else { ++ deprecated = false; ++ condlog(1, "%s line %d, invalid value for flush_on_last_del: \"%s\"", ++ file, line_nr, buff); ++ } ++ if (deprecated) ++ condlog(2, "%s line %d, \"%s\" is a deprecated value for flush_on_last_del and is treated as \"%s\"", ++ file, line_nr, buff, ++ flush_on_last_del_optvals[*flush_val_ptr]); ++ } ++ ++ free(buff); ++ return 0; ++} ++ ++int ++print_flush_on_last_del(struct strbuf *buff, long v) ++{ ++ if (v == FLUSH_UNDEF) ++ return 0; ++ return append_strbuf_quoted(buff, flush_on_last_del_optvals[(int)v]); ++} ++ ++declare_def_handler(flush_on_last_del, set_flush_on_last_del) ++declare_def_snprint_defint(flush_on_last_del, print_flush_on_last_del, ++ DEFAULT_FLUSH) ++declare_ovr_handler(flush_on_last_del, set_flush_on_last_del) ++declare_ovr_snprint(flush_on_last_del, print_flush_on_last_del) ++declare_hw_handler(flush_on_last_del, set_flush_on_last_del) ++declare_hw_snprint(flush_on_last_del, print_flush_on_last_del) ++declare_mp_handler(flush_on_last_del, set_flush_on_last_del) ++declare_mp_snprint(flush_on_last_del, print_flush_on_last_del) + + declare_def_handler(user_friendly_names, set_yes_no_undef) + declare_def_snprint_defint(user_friendly_names, print_yes_no_undef, +diff --git a/libmultipath/dict.h b/libmultipath/dict.h +index 7e2dfbe0..e1794537 100644 +--- a/libmultipath/dict.h ++++ b/libmultipath/dict.h +@@ -18,4 +18,5 @@ int print_undef_off_zero(struct strbuf *buff, long v); + int print_dev_loss(struct strbuf *buff, unsigned long v); + int print_off_int_undef(struct strbuf *buff, long v); + int print_auto_resize(struct strbuf *buff, long v); ++int print_flush_on_last_del(struct strbuf *buff, long v); + #endif /* _DICT_H */ +diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c +index 7aac3f37..d1148de7 100644 +--- a/libmultipath/hwtable.c ++++ b/libmultipath/hwtable.c +@@ -60,7 +60,7 @@ + .no_path_retry = NO_PATH_RETRY_UNDEF, + .minio = 1000, + .minio_rq = 1, +- .flush_on_last_del = FLUSH_DISABLED, ++ .flush_on_last_del = FLUSH_UNUSED, + .user_friendly_names = USER_FRIENDLY_NAMES_OFF, + .fast_io_fail = 5, + .dev_loss = 600, +@@ -829,7 +829,7 @@ static struct hwentry default_hw[] = { + .no_path_retry = NO_PATH_RETRY_QUEUE, + .pgpolicy = GROUP_BY_PRIO, + .pgfailback = -FAILBACK_IMMEDIATE, +- .flush_on_last_del = FLUSH_ENABLED, ++ .flush_on_last_del = FLUSH_ALWAYS, + .dev_loss = MAX_DEV_LOSS_TMO, + .prio_name = PRIO_ONTAP, + .user_friendly_names = USER_FRIENDLY_NAMES_OFF, +@@ -1160,7 +1160,7 @@ static struct hwentry default_hw[] = { + .no_path_retry = NO_PATH_RETRY_FAIL, + .minio = 1, + .minio_rq = 1, +- .flush_on_last_del = FLUSH_ENABLED, ++ .flush_on_last_del = FLUSH_ALWAYS, + .fast_io_fail = 15, + }, + /* +diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c +index 44241e2a..e2dcb316 100644 +--- a/libmultipath/propsel.c ++++ b/libmultipath/propsel.c +@@ -963,6 +963,7 @@ out: + int select_flush_on_last_del(struct config *conf, struct multipath *mp) + { + const char *origin; ++ STRBUF_ON_STACK(buff); + + mp_set_mpe(flush_on_last_del); + mp_set_ovr(flush_on_last_del); +@@ -970,8 +971,9 @@ int select_flush_on_last_del(struct config *conf, struct multipath *mp) + mp_set_conf(flush_on_last_del); + mp_set_default(flush_on_last_del, DEFAULT_FLUSH); + out: ++ print_flush_on_last_del(&buff, mp->flush_on_last_del); + condlog(3, "%s: flush_on_last_del = %s %s", mp->alias, +- (mp->flush_on_last_del == FLUSH_ENABLED)? "yes" : "no", origin); ++ get_strbuf_str(&buff), origin); + return 0; + } + +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index a25eb9d5..dbaf4d43 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -109,9 +109,10 @@ enum marginal_pathgroups_mode { + }; + + enum flush_states { +- FLUSH_UNDEF = YNU_UNDEF, +- FLUSH_DISABLED = YNU_NO, +- FLUSH_ENABLED = YNU_YES, ++ FLUSH_UNDEF, ++ FLUSH_NEVER, ++ FLUSH_ALWAYS, ++ FLUSH_UNUSED, + }; + + enum log_checker_err_states { +diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in +index 46d3685a..1d3d53bb 100644 +--- a/multipath/multipath.conf.5.in ++++ b/multipath/multipath.conf.5.in +@@ -707,12 +707,22 @@ The default is: \fBno\fR + .TP + .B flush_on_last_del + If set to +-.I yes ++.I always + , multipathd will disable queueing when the last path to a device has been +-deleted. +-.RS +-.TP +-The default is: \fBno\fR ++deleted. If set to ++.I never ++, multipathd will not disable queueing when the last path to a device has ++been deleted. Since multipath cannot safely remove a device while queueing ++is enabled, setting this to \fInever\fR means that multipathd will not ++automatically remove an unused multipath device whose paths are all deleted if ++it is currently set to queue_if_no_path. If set to ++.I unused ++, multipathd will only disable queueing when the last path is removed if ++nothing currently has the multipath device or any of the kpartx partition ++devices on top of it open. ++.RS ++.TP ++The default is: \fBunused\fR + .RE + . + . +diff --git a/multipathd/main.c b/multipathd/main.c +index d8518a92..09286dd0 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -584,19 +584,42 @@ int update_multipath (struct vectors *vecs, char *mapname) + static bool + flush_map_nopaths(struct multipath *mpp, struct vectors *vecs) { + int r; ++ bool is_queueing = true; + ++ if (mpp->features) ++ is_queueing = strstr(mpp->features, "queue_if_no_path"); ++ ++ /* It's not safe to do a remove of a map that has "queue_if_no_path" ++ * set, since there could be outstanding IO which will cause ++ * multipathd to hang while attempting the remove */ ++ if (mpp->flush_on_last_del == FLUSH_NEVER && is_queueing) { ++ condlog(2, "%s: map is queueing, can't remove", mpp->alias); ++ return false; ++ } ++ if (mpp->flush_on_last_del == FLUSH_UNUSED && ++ partmap_in_use(mpp->alias, NULL) && is_queueing) { ++ condlog(2, "%s: map in use and queueing, can't remove", ++ mpp->alias); ++ return false; ++ } + /* +- * flush_map will fail if the device is open ++ * This will flush FLUSH_NEVER devices and FLUSH_UNUSED devices ++ * that are in use, but only if they are already marked as not ++ * queueing. That is just to make absolutely certain that they ++ * really are not queueing, like they claim. + */ +- if (mpp->flush_on_last_del == FLUSH_ENABLED) { +- condlog(2, "%s Last path deleted, disabling queueing", ++ condlog(is_queueing ? 2 : 3, "%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++; ++ if (dm_queue_if_no_path(mpp, 0) != 0) { ++ condlog(0, "%s: failed to disable queueing. Not removing", + 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, 0); ++ return false; + } ++ + r = dm_flush_map_nopaths(mpp->alias, mpp->deferred_remove); + if (r != DM_FLUSH_OK) { + if (r == DM_FLUSH_DEFERRED) { diff --git a/0035-libmultipath-remove-redundant-config-option-from-Inf.patch b/0035-libmultipath-remove-redundant-config-option-from-Inf.patch new file mode 100644 index 0000000..8de5639 --- /dev/null +++ b/0035-libmultipath-remove-redundant-config-option-from-Inf.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 25 Apr 2024 19:35:15 -0400 +Subject: [PATCH] libmultipath: remove redundant config option from InfiniBox + config + +The InfiniBox config already sets no_path_retry to "fail", so it won't +ever queue IO. That means setting flush_on_last_del to "always" is +redundant, since queueing is always disabled. Remove the +flush_on_last_del parameter, to make it easier for users to override the +default behavior if desired. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +--- + libmultipath/hwtable.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c +index d1148de7..9e008df6 100644 +--- a/libmultipath/hwtable.c ++++ b/libmultipath/hwtable.c +@@ -1160,7 +1160,6 @@ static struct hwentry default_hw[] = { + .no_path_retry = NO_PATH_RETRY_FAIL, + .minio = 1, + .minio_rq = 1, +- .flush_on_last_del = FLUSH_ALWAYS, + .fast_io_fail = 15, + }, + /* diff --git a/0036-libmultipath-pad-dev_loss_tmo-to-avoid-race-with-no_.patch b/0036-libmultipath-pad-dev_loss_tmo-to-avoid-race-with-no_.patch new file mode 100644 index 0000000..f61f658 --- /dev/null +++ b/0036-libmultipath-pad-dev_loss_tmo-to-avoid-race-with-no_.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 25 Apr 2024 19:35:16 -0400 +Subject: [PATCH] libmultipath: pad dev_loss_tmo to avoid race with + no_path_retry + +Currently multipath makes sure that dev_loss_tmo is at least as long as +the configured no path queueing time. The goal is to make sure that path +devices aren't removed while the multipath device is still queueing in +hopes that they will become usable again. + +This is racy. Multipathd may take longer to check the paths than +configured. If strict_timing isn't set, it will definitely take longer. +To account for this, pad the minimum dev_loss_tmo value by five seconds +(one default checker interval) plus one second per minute of no path +queueing time. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +--- + libmultipath/discovery.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 6fd4dabb..e2052422 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -901,6 +901,11 @@ sysfs_set_scsi_tmo (struct config *conf, struct multipath *mpp) + uint64_t no_path_retry_tmo = + (uint64_t)mpp->no_path_retry * conf->checkint; + ++ /* pad no_path_retry_tmo by one standard check interval ++ * plus one second per minute to account for timing ++ * issues with the rechecks */ ++ no_path_retry_tmo += no_path_retry_tmo / 60 + DEFAULT_CHECKINT; ++ + if (no_path_retry_tmo > MAX_DEV_LOSS_TMO) + min_dev_loss = MAX_DEV_LOSS_TMO; + else diff --git a/0037-libmultipath-fix-deferred_remove-function-arguments.patch b/0037-libmultipath-fix-deferred_remove-function-arguments.patch new file mode 100644 index 0000000..507a056 --- /dev/null +++ b/0037-libmultipath-fix-deferred_remove-function-arguments.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 25 Apr 2024 19:35:17 -0400 +Subject: [PATCH] libmultipath: fix deferred_remove function arguments + +Aside from one version of dm_flush_map_nopaths(), all the callers of +_dm_flush_map() and dm_simplecmd() set deferred_remove to 0. But these +functions, as well as some helper functions they called, all treated the +deferred_remove argument as an enum deferred_remove_states, and called +do_deferred() to see if the remove should be deferred. To simplify the +code, make these functions treat deferred_remove as a boolean value +signifying whether a remove is deferred, and make dm_flush_map_nopaths() +do the work of checking if the remove should be deferred. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +--- + libmultipath/devmapper.c | 19 +++++++++---------- + libmultipath/libmultipath.version | 2 +- + 2 files changed, 10 insertions(+), 11 deletions(-) + +diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c +index a87abf7e..2e7b2c64 100644 +--- a/libmultipath/devmapper.c ++++ b/libmultipath/devmapper.c +@@ -386,8 +386,6 @@ libmp_dm_task_create(int task) + return dm_task_create(task); + } + +-#define do_deferred(x) ((x) == DEFERRED_REMOVE_ON || (x) == DEFERRED_REMOVE_IN_PROGRESS) +- + static int + dm_simplecmd (int task, const char *name, int no_flush, int need_sync, + uint16_t udev_flags, int deferred_remove __DR_UNUSED__) { +@@ -411,7 +409,7 @@ dm_simplecmd (int task, const char *name, int no_flush, int need_sync, + dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ + #endif + #ifdef LIBDM_API_DEFERRED +- if (do_deferred(deferred_remove)) ++ if (deferred_remove) + dm_task_deferred_remove(dmt); + #endif + if (udev_wait_flag && +@@ -1082,7 +1080,7 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, + + /* If you aren't doing a deferred remove, make sure that no + * devices are in use */ +- if (!do_deferred(deferred_remove) && partmap_in_use(mapname, NULL)) ++ if (!deferred_remove && partmap_in_use(mapname, NULL)) + return DM_FLUSH_BUSY; + + if (need_suspend && +@@ -1100,7 +1098,7 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, + if ((r = dm_remove_partmaps(mapname, need_sync, deferred_remove))) + return r; + +- if (!do_deferred(deferred_remove) && dm_get_opencount(mapname)) { ++ if (!deferred_remove && dm_get_opencount(mapname)) { + condlog(2, "%s: map in use", mapname); + return DM_FLUSH_BUSY; + } +@@ -1112,8 +1110,7 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, + r = dm_device_remove(mapname, need_sync, deferred_remove); + + if (r) { +- if (do_deferred(deferred_remove) +- && dm_map_present(mapname)) { ++ if (deferred_remove && dm_map_present(mapname)) { + condlog(4, "multipath map %s remove deferred", + mapname); + return DM_FLUSH_DEFERRED; +@@ -1147,7 +1144,10 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, + int + dm_flush_map_nopaths(const char * mapname, int deferred_remove) + { +- return _dm_flush_map(mapname, 1, deferred_remove, 0, 0); ++ return _dm_flush_map(mapname, 1, ++ (deferred_remove == DEFERRED_REMOVE_ON || ++ deferred_remove == DEFERRED_REMOVE_IN_PROGRESS), ++ 0, 0); + } + + #else +@@ -1539,8 +1539,7 @@ remove_partmap(const char *name, void *data) + + if (dm_get_opencount(name)) { + dm_remove_partmaps(name, rd->need_sync, rd->deferred_remove); +- if (!do_deferred(rd->deferred_remove) && +- dm_get_opencount(name)) { ++ if (rd->deferred_remove && dm_get_opencount(name)) { + condlog(2, "%s: map in use", name); + return DM_FLUSH_BUSY; + } +diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version +index e070f296..eb511749 100644 +--- a/libmultipath/libmultipath.version ++++ b/libmultipath/libmultipath.version +@@ -43,7 +43,7 @@ LIBMPATHCOMMON_1.0.0 { + put_multipath_config; + }; + +-LIBMULTIPATH_23.0.0 { ++LIBMULTIPATH_24.0.0 { + global: + /* symbols referenced by multipath and multipathd */ + add_foreign; diff --git a/0038-libmultipath-use-bitwise-flags-for-map-flushing-API.patch b/0038-libmultipath-use-bitwise-flags-for-map-flushing-API.patch new file mode 100644 index 0000000..ef922ec --- /dev/null +++ b/0038-libmultipath-use-bitwise-flags-for-map-flushing-API.patch @@ -0,0 +1,212 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 2 May 2024 18:38:24 +0200 +Subject: [PATCH] libmultipath: use bitwise flags for map flushing API + +Rather than passing 3 separate bool variables to _dm_flush_map(), +define bitwise flags to modify the function's behavior, and pass +these flags to called functions accordingly. + +This improves the readability of the code, function calls are +more expressive. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/devmapper.c | 68 +++++++++++++++++----------------------- + libmultipath/devmapper.h | 18 ++++++++--- + 2 files changed, 41 insertions(+), 45 deletions(-) + +diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c +index 2e7b2c64..a6a9c2b7 100644 +--- a/libmultipath/devmapper.c ++++ b/libmultipath/devmapper.c +@@ -53,9 +53,8 @@ static int dm_cancel_remove_partmaps(const char * mapname); + #define __DR_UNUSED__ __attribute__((unused)) + #endif + +-static int dm_remove_partmaps (const char * mapname, int need_sync, +- int deferred_remove); +-static int do_foreach_partmaps(const char * mapname, ++static int dm_remove_partmaps (const char *mapname, int flags); ++static int do_foreach_partmaps(const char *mapname, + int (*partmap_func)(const char *, void *), + void *data); + static int _dm_queue_if_no_path(const char *mapname, int enable); +@@ -439,9 +438,9 @@ int dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags) + } + + static int +-dm_device_remove (const char *name, int needsync, int deferred_remove) { +- return dm_simplecmd(DM_DEVICE_REMOVE, name, 0, needsync, 0, +- deferred_remove); ++dm_device_remove (const char *name, int flags) { ++ return dm_simplecmd(DM_DEVICE_REMOVE, name, 0, flags & DMFL_NEED_SYNC, 0, ++ flags & DMFL_DEFERRED); + } + + static int +@@ -1061,8 +1060,7 @@ partmap_in_use(const char *name, void *data) + return 0; + } + +-int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, +- int need_suspend, int retries) ++int _dm_flush_map (const char *mapname, int flags, int retries) + { + int r; + int queue_if_no_path = 0; +@@ -1080,10 +1078,10 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, + + /* If you aren't doing a deferred remove, make sure that no + * devices are in use */ +- if (!deferred_remove && partmap_in_use(mapname, NULL)) ++ if (!(flags & DMFL_DEFERRED) && partmap_in_use(mapname, NULL)) + return DM_FLUSH_BUSY; + +- if (need_suspend && ++ if ((flags & DMFL_SUSPEND) && + dm_get_map(mapname, &mapsize, ¶ms) == DMP_OK && + strstr(params, "queue_if_no_path")) { + if (!_dm_queue_if_no_path(mapname, 0)) +@@ -1095,22 +1093,22 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, + free(params); + params = NULL; + +- if ((r = dm_remove_partmaps(mapname, need_sync, deferred_remove))) ++ if ((r = dm_remove_partmaps(mapname, flags))) + return r; + +- if (!deferred_remove && dm_get_opencount(mapname)) { ++ if (!(flags & DMFL_DEFERRED) && dm_get_opencount(mapname)) { + condlog(2, "%s: map in use", mapname); + return DM_FLUSH_BUSY; + } + + do { +- if (need_suspend && queue_if_no_path != -1) ++ if ((flags & DMFL_SUSPEND) && queue_if_no_path != -1) + dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 0); + +- r = dm_device_remove(mapname, need_sync, deferred_remove); ++ r = dm_device_remove(mapname, flags); + + if (r) { +- if (deferred_remove && dm_map_present(mapname)) { ++ if ((flags & DMFL_DEFERRED) && dm_map_present(mapname)) { + condlog(4, "multipath map %s remove deferred", + mapname); + return DM_FLUSH_DEFERRED; +@@ -1124,7 +1122,7 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, + } else { + condlog(2, "failed to remove multipath map %s", + mapname); +- if (need_suspend && queue_if_no_path != -1) { ++ if ((flags & DMFL_SUSPEND) && queue_if_no_path != -1) { + dm_simplecmd_noflush(DM_DEVICE_RESUME, + mapname, udev_flags); + } +@@ -1139,27 +1137,18 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, + return DM_FLUSH_FAIL; + } + +-#ifdef LIBDM_API_DEFERRED +- + int +-dm_flush_map_nopaths(const char * mapname, int deferred_remove) ++dm_flush_map_nopaths(const char *mapname, int deferred_remove __DR_UNUSED__) + { +- return _dm_flush_map(mapname, 1, +- (deferred_remove == DEFERRED_REMOVE_ON || +- deferred_remove == DEFERRED_REMOVE_IN_PROGRESS), +- 0, 0); +-} +- +-#else +- +-int +-dm_flush_map_nopaths(const char * mapname, +- int deferred_remove __attribute__((unused))) +-{ +- return _dm_flush_map(mapname, 1, 0, 0, 0); +-} ++ int flags = DMFL_NEED_SYNC; + ++#ifdef LIBDM_API_DEFERRED ++ flags |= ((deferred_remove == DEFERRED_REMOVE_ON || ++ deferred_remove == DEFERRED_REMOVE_IN_PROGRESS) ? ++ DMFL_DEFERRED : 0); + #endif ++ return _dm_flush_map(mapname, flags, 0); ++} + + int dm_flush_maps (int retries) + { +@@ -1528,8 +1517,7 @@ out: + } + + struct remove_data { +- int need_sync; +- int deferred_remove; ++ int flags; + }; + + static int +@@ -1538,21 +1526,21 @@ remove_partmap(const char *name, void *data) + struct remove_data *rd = (struct remove_data *)data; + + if (dm_get_opencount(name)) { +- dm_remove_partmaps(name, rd->need_sync, rd->deferred_remove); +- if (rd->deferred_remove && dm_get_opencount(name)) { ++ dm_remove_partmaps(name, rd->flags); ++ if ((rd->flags & DMFL_DEFERRED) && dm_get_opencount(name)) { + condlog(2, "%s: map in use", name); + return DM_FLUSH_BUSY; + } + } + condlog(4, "partition map %s removed", name); +- dm_device_remove(name, rd->need_sync, rd->deferred_remove); ++ dm_device_remove(name, rd->flags); + return DM_FLUSH_OK; + } + + static int +-dm_remove_partmaps (const char * mapname, int need_sync, int deferred_remove) ++dm_remove_partmaps (const char * mapname, int flags) + { +- struct remove_data rd = { need_sync, deferred_remove }; ++ struct remove_data rd = { flags }; + return do_foreach_partmaps(mapname, remove_partmap, &rd); + } + +diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h +index 93caa2aa..bb4a55a6 100644 +--- a/libmultipath/devmapper.h ++++ b/libmultipath/devmapper.h +@@ -58,12 +58,20 @@ enum { + }; + + int partmap_in_use(const char *name, void *data); +-int _dm_flush_map (const char *, int, int, int, int); +-int dm_flush_map_nopaths(const char * mapname, int deferred_remove); +-#define dm_flush_map(mapname) _dm_flush_map(mapname, 1, 0, 0, 0) +-#define dm_flush_map_nosync(mapname) _dm_flush_map(mapname, 0, 0, 0, 0) ++ ++enum { ++ DMFL_NONE = 0, ++ DMFL_NEED_SYNC = 1 << 0, ++ DMFL_DEFERRED = 1 << 1, ++ DMFL_SUSPEND = 1 << 2, ++}; ++ ++int _dm_flush_map (const char *mapname, int flags, int retries); ++#define dm_flush_map(mapname) _dm_flush_map(mapname, DMFL_NEED_SYNC, 0) ++#define dm_flush_map_nosync(mapname) _dm_flush_map(mapname, DMFL_NONE, 0) + #define dm_suspend_and_flush_map(mapname, retries) \ +- _dm_flush_map(mapname, 1, 0, 1, retries) ++ _dm_flush_map(mapname, DMFL_NEED_SYNC|DMFL_SUSPEND, retries) ++int dm_flush_map_nopaths(const char * mapname, int deferred_remove); + int dm_cancel_deferred_remove(struct multipath *mpp); + int dm_flush_maps (int retries); + int dm_fail_path(const char * mapname, char * path); diff --git a/0039-libmultipath-use-bitwise-flags-for-dm_simplecmd-API.patch b/0039-libmultipath-use-bitwise-flags-for-dm_simplecmd-API.patch new file mode 100644 index 0000000..1aee878 --- /dev/null +++ b/0039-libmultipath-use-bitwise-flags-for-dm_simplecmd-API.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 2 May 2024 18:45:17 +0200 +Subject: [PATCH] libmultipath: use bitwise flags for dm_simplecmd API + +Also use bitwise flags for dm_simplecmd() and its relatives. Again, +this makes the code more expressive and more readable, while +simplifying the function calls. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/devmapper.c | 26 +++++++++++++------------- + libmultipath/devmapper.h | 5 +++-- + 2 files changed, 16 insertions(+), 15 deletions(-) + +diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c +index a6a9c2b7..08bb3c51 100644 +--- a/libmultipath/devmapper.c ++++ b/libmultipath/devmapper.c +@@ -386,10 +386,9 @@ libmp_dm_task_create(int task) + } + + static int +-dm_simplecmd (int task, const char *name, int no_flush, int need_sync, +- uint16_t udev_flags, int deferred_remove __DR_UNUSED__) { ++dm_simplecmd (int task, const char *name, int flags, uint16_t udev_flags) { + int r = 0; +- int udev_wait_flag = ((need_sync || udev_flags) && ++ int udev_wait_flag = (((flags & DMFL_NEED_SYNC) || udev_flags) && + (task == DM_DEVICE_RESUME || + task == DM_DEVICE_REMOVE)); + uint32_t cookie = 0; +@@ -404,11 +403,11 @@ dm_simplecmd (int task, const char *name, int no_flush, int need_sync, + dm_task_no_open_count(dmt); + dm_task_skip_lockfs(dmt); /* for DM_DEVICE_RESUME */ + #ifdef LIBDM_API_FLUSH +- if (no_flush) ++ if (flags & DMFL_NO_FLUSH) + dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ + #endif + #ifdef LIBDM_API_DEFERRED +- if (deferred_remove) ++ if (flags & DMFL_DEFERRED) + dm_task_deferred_remove(dmt); + #endif + if (udev_wait_flag && +@@ -429,18 +428,17 @@ out: + + int dm_simplecmd_flush (int task, const char *name, uint16_t udev_flags) + { +- return dm_simplecmd(task, name, 0, 1, udev_flags, 0); ++ return dm_simplecmd(task, name, DMFL_NEED_SYNC, udev_flags); + } + + int dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags) + { +- return dm_simplecmd(task, name, 1, 1, udev_flags, 0); ++ return dm_simplecmd(task, name, DMFL_NO_FLUSH|DMFL_NEED_SYNC, udev_flags); + } + + static int + dm_device_remove (const char *name, int flags) { +- return dm_simplecmd(DM_DEVICE_REMOVE, name, 0, flags & DMFL_NEED_SYNC, 0, +- flags & DMFL_DEFERRED); ++ return dm_simplecmd(DM_DEVICE_REMOVE, name, flags, 0); + } + + static int +@@ -594,8 +592,9 @@ int dm_addmap_reload(struct multipath *mpp, char *params, int flush) + params, ADDMAP_RO, 0); + } + if (r) +- r = dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, !flush, +- 1, udev_flags, 0); ++ r = dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, ++ DMFL_NEED_SYNC | (flush ? 0 : DMFL_NO_FLUSH), ++ udev_flags); + if (r) + return r; + +@@ -603,8 +602,9 @@ int dm_addmap_reload(struct multipath *mpp, char *params, int flush) + * drop the new table, so doing a second resume will try using + * the original table */ + if (dm_is_suspended(mpp->alias)) +- dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, !flush, 1, +- udev_flags, 0); ++ dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, ++ DMFL_NEED_SYNC | (flush ? 0 : DMFL_NO_FLUSH), ++ udev_flags); + return 0; + } + +diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h +index bb4a55a6..a242381e 100644 +--- a/libmultipath/devmapper.h ++++ b/libmultipath/devmapper.h +@@ -38,8 +38,8 @@ void skip_libmp_dm_init(void); + void libmp_dm_exit(void); + void libmp_udev_set_sync_support(int on); + struct dm_task *libmp_dm_task_create(int task); +-int dm_simplecmd_flush (int, const char *, uint16_t); +-int dm_simplecmd_noflush (int, const char *, uint16_t); ++int dm_simplecmd_flush (int task, const char *name, uint16_t udev_flags); ++int dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags); + int dm_addmap_create (struct multipath *mpp, char *params); + int dm_addmap_reload (struct multipath *mpp, char *params, int flush); + int dm_map_present (const char *); +@@ -64,6 +64,7 @@ enum { + DMFL_NEED_SYNC = 1 << 0, + DMFL_DEFERRED = 1 << 1, + DMFL_SUSPEND = 1 << 2, ++ DMFL_NO_FLUSH = 1 << 3, + }; + + int _dm_flush_map (const char *mapname, int flags, int retries); diff --git a/0040-libmultipath-add-argument-names-to-some-prototypes.patch b/0040-libmultipath-add-argument-names-to-some-prototypes.patch new file mode 100644 index 0000000..3244d55 --- /dev/null +++ b/0040-libmultipath-add-argument-names-to-some-prototypes.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 2 May 2024 18:46:42 +0200 +Subject: [PATCH] libmultipath: add argument names to some prototypes + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/devmapper.h | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h +index a242381e..19b79c5b 100644 +--- a/libmultipath/devmapper.h ++++ b/libmultipath/devmapper.h +@@ -42,12 +42,12 @@ int dm_simplecmd_flush (int task, const char *name, uint16_t udev_flags); + int dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags); + int dm_addmap_create (struct multipath *mpp, char *params); + int dm_addmap_reload (struct multipath *mpp, char *params, int flush); +-int dm_map_present (const char *); ++int dm_map_present (const char *name); + int dm_map_present_by_uuid(const char *uuid); +-int dm_get_map(const char *, unsigned long long *, char **); +-int dm_get_status(const char *, char **); +-int dm_type(const char *, char *); +-int dm_is_mpath(const char *); ++int dm_get_map(const char *name, unsigned long long *size, char **outparams); ++int dm_get_status(const char *name, char **outstatus); ++int dm_type(const char *name, char *type); ++int dm_is_mpath(const char *name); + + enum { + DM_FLUSH_OK = 0, diff --git a/0041-libmultipath-bump-version-to-0.9.9.patch b/0041-libmultipath-bump-version-to-0.9.9.patch new file mode 100644 index 0000000..890b047 --- /dev/null +++ b/0041-libmultipath-bump-version-to-0.9.9.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 3 May 2024 22:09:10 +0200 +Subject: [PATCH] libmultipath: bump version to 0.9.9 + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/version.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libmultipath/version.h b/libmultipath/version.h +index e102975f..271d8e74 100644 +--- a/libmultipath/version.h ++++ b/libmultipath/version.h +@@ -20,9 +20,9 @@ + #ifndef _VERSION_H + #define _VERSION_H + +-#define VERSION_CODE 0x000908 ++#define VERSION_CODE 0x000909 + /* MMDDYY, in hex */ +-#define DATE_CODE 0x020F18 ++#define DATE_CODE 0x050318 + + #define PROG "multipath-tools" + diff --git a/0042-GitHub-Workflows-native.yaml-run-for-Fedora-40.patch b/0042-GitHub-Workflows-native.yaml-run-for-Fedora-40.patch new file mode 100644 index 0000000..47c3949 --- /dev/null +++ b/0042-GitHub-Workflows-native.yaml-run-for-Fedora-40.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 3 May 2024 22:28:34 +0200 +Subject: [PATCH] GitHub Workflows: native.yaml: run for Fedora 40 + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + .github/workflows/native.yaml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml +index 0ef9df94..a062845e 100644 +--- a/.github/workflows/native.yaml ++++ b/.github/workflows/native.yaml +@@ -33,7 +33,7 @@ jobs: + - debian-buster + - debian-bullseye + - debian-bookworm +- - fedora-39 ++ - fedora-40 + - opensuse-leap + container: ghcr.io/mwilck/multipath-build-${{ matrix.os }} + steps: diff --git a/0043-update-NEWS.md.patch b/0043-update-NEWS.md.patch new file mode 100644 index 0000000..4edc69d --- /dev/null +++ b/0043-update-NEWS.md.patch @@ -0,0 +1,134 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 3 May 2024 23:11:48 +0200 +Subject: [PATCH] update NEWS.md + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + .github/actions/spelling/expect.txt | 3 ++ + .github/actions/spelling/patterns.txt | 3 +- + NEWS.md | 62 +++++++++++++++++++++++++++ + 3 files changed, 67 insertions(+), 1 deletion(-) + +diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt +index fc9f22f8..bdfce83a 100644 +--- a/.github/actions/spelling/expect.txt ++++ b/.github/actions/spelling/expect.txt +@@ -17,6 +17,7 @@ blkid + bmarzins + cciss + CFLAGS ++cgroups + christophe + clangd + clariion +@@ -67,6 +68,7 @@ fulldescr + gcc + getprkey + getprstatus ++getrlimit + getuid + github + GPT +@@ -170,6 +172,7 @@ rootprefixdir + rpmbuild + rport + rtpi ++rtprio + sas + sbp + scsi +diff --git a/.github/actions/spelling/patterns.txt b/.github/actions/spelling/patterns.txt +index 858faee6..aa361654 100644 +--- a/.github/actions/spelling/patterns.txt ++++ b/.github/actions/spelling/patterns.txt +@@ -22,7 +22,7 @@ + \bdmmp_pgs\b + \bdmmp_mpath_kdev_name_get\b + \bfast_io_fail_tmo\b +-\bLimitRTPRIO\b ++\bLimitRTPRIO=?\b + \bmax_fds\b + \bmissing_uev_wait_timeout\b + \bMPATH_MAX_PARAM_LEN\b +@@ -87,6 +87,7 @@ + \bprin_resvdescr\b + \bprout_param_descriptor\b + \brq_servact\b ++\bRLIMIT_RTPRIO\b + \bSCHED_RT_PRIO\b + \bssize_t\b + \btrnptid_list\b +diff --git a/NEWS.md b/NEWS.md +index 0b094b98..4c54afa0 100644 +--- a/NEWS.md ++++ b/NEWS.md +@@ -1,5 +1,67 @@ + # multipath-tools Release Notes + ++## multipath-tools 0.9.9, 2024/05 ++ ++### User-Visible Changes ++ ++* *Changed realtime scheduling:* multipathd used to run at the highest possible ++ realtime priority, 99. This has always been excessive, and on some ++ distributions (e.g. RHEL 8), it hasn't worked at all. It is now possible to ++ set multipathd's real time scheduling by setting the hard limit for ++ `RLIMIT_RTPRIO` (see getrlimit(2)), which corresponds to the `rtprio` ++ setting in limits.conf and to `LimitRTPRIO=` in the systemd unit file. The ++ default in the systemd unit file has been set to 10. If the limit is set to ++ 0, multipathd doesn't attempt to enable real-time scheduling. ++ Otherwise, it will try to set the scheduling priority to the given value. ++ Fixes [#82](https://github.com/opensvc/multipath-tools/issues/82). ++* *Changed normal scheduling:* In order to make sure that multipathd has ++ sufficient priority even if real time scheduling is switched off, the ++ `CPUWeight=` setting in the unit file is set to 1000. This is necessary ++ because regular nice(2) values have no effect in systems with cgroups enabled. ++* *Changed handling of `max_sectors_kb` configuration:* multipathd applies ++ the `max_sectors_kb` setting only during map creation, or when a new path is ++ added to an existing map. The kernel makes sure that the multipath device ++ never has a larger `max_sectors_kb` value than any of its configured path ++ devices. The reason for this change is that applying `max_sectors_kb` on ++ live maps can cause IO errors and data loss in rare situations. ++ It can now happen that some path devices have a higher `max_sectors_kb` ++ value than the map; this is not an error. It is not possible any more to ++ decrease `max_sectors_kb` in `multipath.conf` and run `multipathd ++ reconfigure` to "apply" this setting to the map and its paths. If decreasing ++ the IO size is necessary, either destroy and recreate the map, or remove one ++ path with `multipathd del path $PATH`, run `multipathd reconfigure`, and ++ re-add the path with `multipathd add path $PATH`. ++* *New wildcard %k:* The wildcard `%k` for `max_sectors_kb` has been added to ++ the `multipathd show paths format` and `multipathd show maps format` ++ commands. ++* *Changed semantics of flush_on_last_del:* The `flush_on_last_del` option ++ now takes the values `always` , `unused`, or `never`. `yes` and `no` ++ are still accepted as aliases for `always` and `unused`, respectively. ++ `always` means that when all paths for a multipath map have been removed, ++ *outstanding IO will be failed* and the map will be deleted. `unused` means ++ that this will only happen when the map is not mounted or otherwise opened. ++ `never` means the map will only be removed if the `queue_if_no_path` ++ feature is off. ++ This fixes a problem where multipathd could hang when the last path of ++ a queueing map was deleted. ++ ++### Other major changes ++ ++* Adapted the dm-mpath udev rules such that they will work with the modified ++ device mapper udev rules (`DM_UDEV_RULES_VSN==3`, lvm2 > 2.03.22). They are ++ still compatible with older versions of the device-mapper udev rules. ++ ++### Bug fixes ++ ++* Fixed misspelled DM_UDEV_DISABLE_OTHER_RULES_FLAG in 11-dm-mpath.rules ++* Always use `glibc_basename()` to avoid some issues with MUSL libc. ++ Fixes [#84](https://github.com/opensvc/multipath-tools/pull/84). ++ ++### Other ++ ++* Build: added `TGTDIR` option to simplify building for a different target ++ host (see README.md). ++ + ## multipath-tools 0.9.8, 2024/02 + + ### User-Visible Changes diff --git a/0044-multipath.conf.5.in-fix-man-page-date.patch b/0044-multipath.conf.5.in-fix-man-page-date.patch new file mode 100644 index 0000000..c9f2d5d --- /dev/null +++ b/0044-multipath.conf.5.in-fix-man-page-date.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 3 May 2024 23:22:50 +0200 +Subject: [PATCH] multipath.conf.5.in: fix man page date + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + multipath/multipath.conf.5.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in +index 1d3d53bb..dacb9b0e 100644 +--- a/multipath/multipath.conf.5.in ++++ b/multipath/multipath.conf.5.in +@@ -6,7 +6,7 @@ + .\" Update the date below if you make any significant change. + .\" ---------------------------------------------------------------------------- + . +-.TH MULTIPATH.CONF 5 2024-04-17 Linux ++.TH MULTIPATH.CONF 5 2024-04-25 Linux + . + . + .\" ---------------------------------------------------------------------------- diff --git a/0001-RH-fixup-udev-rules-for-redhat.patch b/0045-RH-fixup-udev-rules-for-redhat.patch similarity index 86% rename from 0001-RH-fixup-udev-rules-for-redhat.patch rename to 0045-RH-fixup-udev-rules-for-redhat.patch index 02efadd..d78919e 100644 --- a/0001-RH-fixup-udev-rules-for-redhat.patch +++ b/0045-RH-fixup-udev-rules-for-redhat.patch @@ -15,7 +15,7 @@ Signed-off-by: Benjamin Marzinski 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile.inc b/Makefile.inc -index 6b454303..0b0e3ad2 100644 +index 81b86cd8..33dbb99c 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -34,7 +34,7 @@ endif @@ -26,9 +26,9 @@ index 6b454303..0b0e3ad2 100644 +exec_prefix := $(prefix)/usr # Prefix for non-essential libraries (libdmmp) usr_prefix := $(if $(prefix),$(prefix),/usr) - # Prefix for configfuration files (multipath.conf) + # Prefix for configuration files (multipath.conf) diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules -index 1969dee0..d2b28233 100644 +index 8dd3369c..7c3c7524 100644 --- a/kpartx/kpartx.rules +++ b/kpartx/kpartx.rules @@ -39,6 +39,6 @@ LABEL="mpath_kpartx_end" @@ -40,20 +40,20 @@ index 1969dee0..d2b28233 100644 LABEL="kpartx_end" diff --git a/multipath/Makefile b/multipath/Makefile -index 0efb9b26..504d6892 100644 +index 67fb5e62..2ea9e528 100644 --- a/multipath/Makefile +++ b/multipath/Makefile -@@ -26,7 +26,7 @@ install: - $(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/ +@@ -27,7 +27,7 @@ install: $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) $(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) + $(Q)$(INSTALL_PROGRAM) -m 644 99-z-dm-mpath-late.rules $(DESTDIR)$(udevrulesdir) - $(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/56-multipath.rules + $(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(tmpfilesdir) $(Q)$(INSTALL_PROGRAM) -m 644 tmpfiles.conf $(DESTDIR)$(tmpfilesdir)/multipath.conf $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man8 -@@ -48,7 +48,7 @@ uninstall: - $(Q)$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules +@@ -50,7 +50,7 @@ uninstall: + $(Q)$(RM) $(DESTDIR)$(udevrulesdir)/99-z-dm-mpath-late.rules $(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf $(Q)$(RM) $(DESTDIR)$(modulesloaddir)/scsi_dh.conf - $(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules diff --git a/0002-RH-Remove-the-property-blacklist-exception-builtin.patch b/0046-RH-Remove-the-property-blacklist-exception-builtin.patch similarity index 96% rename from 0002-RH-Remove-the-property-blacklist-exception-builtin.patch rename to 0046-RH-Remove-the-property-blacklist-exception-builtin.patch index bc259d4..b039539 100644 --- a/0002-RH-Remove-the-property-blacklist-exception-builtin.patch +++ b/0046-RH-Remove-the-property-blacklist-exception-builtin.patch @@ -42,10 +42,10 @@ index 75100b20..0b212078 100644 udev_device_get_properties_list_entry(udev)) { diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in -index 683bdb72..87b3b2a5 100644 +index dacb9b0e..645e8f88 100644 --- a/multipath/multipath.conf.5.in +++ b/multipath/multipath.conf.5.in -@@ -1431,9 +1431,14 @@ keywords. Both are regular expressions. For a full description of these keywords +@@ -1468,9 +1468,14 @@ keywords. Both are regular expressions. For a full description of these keywords Regular expression for an udev property. All devices that have matching udev properties will be excluded/included. The handling of the \fIproperty\fR keyword is special, @@ -61,7 +61,7 @@ index 683bdb72..87b3b2a5 100644 . .RS .PP -@@ -1444,10 +1449,6 @@ Blacklisting by missing properties is only applied to devices which do have the +@@ -1481,10 +1486,6 @@ Blacklisting by missing properties is only applied to devices which do have the property specified by \fIuid_attribute\fR (e.g. \fIID_SERIAL\fR) set. Previously, it was applied to every device, possibly causing devices to be blacklisted because of temporary I/O error conditions. diff --git a/0003-RH-don-t-start-without-a-config-file.patch b/0047-RH-don-t-start-without-a-config-file.patch similarity index 92% rename from 0003-RH-don-t-start-without-a-config-file.patch rename to 0047-RH-don-t-start-without-a-config-file.patch index fa304dc..ad7962a 100644 --- a/0003-RH-don-t-start-without-a-config-file.patch +++ b/0047-RH-don-t-start-without-a-config-file.patch @@ -22,10 +22,10 @@ Signed-off-by: Benjamin Marzinski 7 files changed, 25 insertions(+) diff --git a/libmultipath/config.c b/libmultipath/config.c -index b7dbc6f5..3a374b3d 100644 +index 83fa7369..002027a7 100644 --- a/libmultipath/config.c +++ b/libmultipath/config.c -@@ -958,6 +958,19 @@ int _init_config (const char *file, struct config *conf) +@@ -959,6 +959,19 @@ int _init_config (const char *file, struct config *conf) } factorize_hwtable(conf->hwtable, builtin_hwtable_size, file); validate_pctable(conf->overrides, 0, file); @@ -58,12 +58,12 @@ index 384193ab..158cebf0 100644 enum devtypes { DEV_NONE, diff --git a/multipath/main.c b/multipath/main.c -index 9e1c5052..46944589 100644 +index ce702e7f..c21e3e0b 100644 --- a/multipath/main.c +++ b/multipath/main.c -@@ -829,11 +829,14 @@ main (int argc, char *argv[]) +@@ -842,11 +842,14 @@ main (int argc, char *argv[]) + char *dev = NULL; struct config *conf; - int retries = -1; bool enable_foreign = false; + bool have_config; + struct stat buf; @@ -76,7 +76,7 @@ index 9e1c5052..46944589 100644 if (init_config(DEFAULT_CONFIGFILE)) exit(RTVL_FAIL); if (atexit(uninit_config)) -@@ -1081,6 +1084,9 @@ main (int argc, char *argv[]) +@@ -1097,6 +1100,9 @@ main (int argc, char *argv[]) while ((r = configure(conf, cmd, dev_type, dev)) == RTVL_RETRY) condlog(3, "restart multipath configuration process"); @@ -87,7 +87,7 @@ index 9e1c5052..46944589 100644 put_multipath_config(conf); if (dev) diff --git a/multipath/multipath.rules.in b/multipath/multipath.rules.in -index 6f123760..70b69a06 100644 +index 780bf852..2c518378 100644 --- a/multipath/multipath.rules.in +++ b/multipath/multipath.rules.in @@ -9,6 +9,7 @@ IMPORT{cmdline}="nompath" @@ -99,7 +99,7 @@ index 6f123760..70b69a06 100644 ENV{DEVTYPE}!="partition", GOTO="test_dev" IMPORT{parent}="DM_MULTIPATH_DEVICE_PATH" diff --git a/multipathd/multipathd.8.in b/multipathd/multipathd.8.in -index e98c27fd..fd2061e5 100644 +index 12b77156..499557a0 100644 --- a/multipathd/multipathd.8.in +++ b/multipathd/multipathd.8.in @@ -49,6 +49,8 @@ map regains its maximum performance and redundancy. @@ -112,7 +112,7 @@ index e98c27fd..fd2061e5 100644 . .\" ---------------------------------------------------------------------------- diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in -index 6d03ff71..0965d6f9 100644 +index a63ddd9a..01ceff7d 100644 --- a/multipathd/multipathd.service.in +++ b/multipathd/multipathd.service.in @@ -6,6 +6,7 @@ Wants=systemd-udevd-kernel.socket @MODPROBE_UNIT@ @@ -124,7 +124,7 @@ index 6d03ff71..0965d6f9 100644 Conflicts=shutdown.target Conflicts=initrd-cleanup.service diff --git a/multipathd/multipathd.socket b/multipathd/multipathd.socket -index c777e5e3..3c20a2ff 100644 +index 6a62f5fd..263b6b0c 100644 --- a/multipathd/multipathd.socket +++ b/multipathd/multipathd.socket @@ -1,6 +1,7 @@ diff --git a/0004-RH-Fix-nvme-function-missing-argument.patch b/0048-RH-Fix-nvme-function-missing-argument.patch similarity index 100% rename from 0004-RH-Fix-nvme-function-missing-argument.patch rename to 0048-RH-Fix-nvme-function-missing-argument.patch diff --git a/0005-RH-use-rpm-optflags-if-present.patch b/0049-RH-use-rpm-optflags-if-present.patch similarity index 87% rename from 0005-RH-use-rpm-optflags-if-present.patch rename to 0049-RH-use-rpm-optflags-if-present.patch index 6352c23..0f354e7 100644 --- a/0005-RH-use-rpm-optflags-if-present.patch +++ b/0049-RH-use-rpm-optflags-if-present.patch @@ -13,7 +13,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/Makefile.inc b/Makefile.inc -index 0b0e3ad2..3d80d224 100644 +index 33dbb99c..94e0ec85 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -95,11 +95,23 @@ SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo @@ -41,10 +41,10 @@ index 0b0e3ad2..3d80d224 100644 -CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \ + $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) -Wstrict-prototypes +CPPFLAGS := $(CPPFLAGS) $(D_URCU_VERSION) \ - -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \ - -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \ - -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DSTATE_DIR=\"$(statedir)\" \ -@@ -108,7 +120,7 @@ CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe + -D_FILE_OFFSET_BITS=64 \ + -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(TGTDIR)$(plugindir)\" \ + -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(TGTDIR)$(configdir)\" \ +@@ -109,7 +121,7 @@ CFLAGS := -std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe BIN_CFLAGS := -fPIE -DPIE LIB_CFLAGS := -fPIC SHARED_FLAGS := -shared diff --git a/0006-RH-add-mpathconf.patch b/0050-RH-add-mpathconf.patch similarity index 98% rename from 0006-RH-add-mpathconf.patch rename to 0050-RH-add-mpathconf.patch index fd47a6c..fd65e34 100644 --- a/0006-RH-add-mpathconf.patch +++ b/0050-RH-add-mpathconf.patch @@ -22,10 +22,10 @@ Signed-off-by: Benjamin Marzinski create mode 100644 multipath/mpathconf.8 diff --git a/libmultipath/config.c b/libmultipath/config.c -index 3a374b3d..4544f484 100644 +index 002027a7..3d5943d3 100644 --- a/libmultipath/config.c +++ b/libmultipath/config.c -@@ -960,6 +960,8 @@ int _init_config (const char *file, struct config *conf) +@@ -961,6 +961,8 @@ int _init_config (const char *file, struct config *conf) validate_pctable(conf->overrides, 0, file); } else { condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices."); @@ -35,7 +35,7 @@ index 3a374b3d..4544f484 100644 conf->blist_devnode = vector_alloc(); if (!conf->blist_devnode) { diff --git a/multipath/Makefile b/multipath/Makefile -index 504d6892..9f14036c 100644 +index 2ea9e528..3dc241cc 100644 --- a/multipath/Makefile +++ b/multipath/Makefile @@ -24,6 +24,7 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so @@ -45,8 +45,8 @@ index 504d6892..9f14036c 100644 + $(Q)$(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/ $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) $(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) - $(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules -@@ -31,6 +32,7 @@ install: + $(Q)$(INSTALL_PROGRAM) -m 644 99-z-dm-mpath-late.rules $(DESTDIR)$(udevrulesdir) +@@ -32,6 +33,7 @@ install: $(Q)$(INSTALL_PROGRAM) -m 644 tmpfiles.conf $(DESTDIR)$(tmpfilesdir)/multipath.conf $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man8 $(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)/man8 @@ -54,12 +54,13 @@ index 504d6892..9f14036c 100644 $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man5 $(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5 $(DESTDIR)$(mandir)/man5 $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(modulesloaddir) -@@ -45,11 +47,13 @@ endif +@@ -46,12 +48,14 @@ endif uninstall: $(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC) + $(Q)$(RM) $(DESTDIR)$(bindir)/mpathconf $(Q)$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules + $(Q)$(RM) $(DESTDIR)$(udevrulesdir)/99-z-dm-mpath-late.rules $(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf $(Q)$(RM) $(DESTDIR)$(modulesloaddir)/scsi_dh.conf $(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules diff --git a/0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch b/0051-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch similarity index 96% rename from 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch rename to 0051-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch index a3c4e9d..9884258 100644 --- a/0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +++ b/0051-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch @@ -20,7 +20,7 @@ Signed-off-by: Benjamin Marzinski 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/multipath/main.c b/multipath/main.c -index 46944589..47f89a0a 100644 +index c21e3e0b..3f3ac9fb 100644 --- a/multipath/main.c +++ b/multipath/main.c @@ -120,7 +120,7 @@ usage (char * progname) @@ -92,7 +92,7 @@ index 46944589..47f89a0a 100644 static int configure (struct config *conf, enum mpath_cmds cmd, enum devtypes dev_type, char *devpath) -@@ -848,7 +894,7 @@ main (int argc, char *argv[]) +@@ -861,7 +907,7 @@ main (int argc, char *argv[]) condlog(1, "failed to register cleanup handler for vecs: %m"); if (atexit(cleanup_bindings)) condlog(1, "failed to register cleanup handler for bindings: %m"); @@ -101,7 +101,7 @@ index 46944589..47f89a0a 100644 switch(arg) { case 'v': if (!isdigit(optarg[0])) { -@@ -919,6 +965,10 @@ main (int argc, char *argv[]) +@@ -932,6 +978,10 @@ main (int argc, char *argv[]) case 'T': cmd = CMD_DUMP_CONFIG; break; @@ -113,7 +113,7 @@ index 46944589..47f89a0a 100644 usage(argv[0]); exit(RTVL_OK); diff --git a/multipath/multipath.8.in b/multipath/multipath.8.in -index 348eb220..82a7e68e 100644 +index b88e9a4c..edd742aa 100644 --- a/multipath/multipath.8.in +++ b/multipath/multipath.8.in @@ -64,7 +64,7 @@ multipath \- Device mapper target autoconfig. @@ -138,7 +138,7 @@ index 348eb220..82a7e68e 100644 Remove the WWID for the specified device from the WWIDs file. . diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in -index 0965d6f9..c964eb1b 100644 +index 01ceff7d..e0c2011b 100644 --- a/multipathd/multipathd.service.in +++ b/multipathd/multipathd.service.in @@ -17,6 +17,7 @@ ConditionVirtualization=!container diff --git a/0008-RH-reset-default-find_mutipaths-value-to-off.patch b/0052-RH-reset-default-find_mutipaths-value-to-off.patch similarity index 91% rename from 0008-RH-reset-default-find_mutipaths-value-to-off.patch rename to 0052-RH-reset-default-find_mutipaths-value-to-off.patch index cf7317e..04ad52c 100644 --- a/0008-RH-reset-default-find_mutipaths-value-to-off.patch +++ b/0052-RH-reset-default-find_mutipaths-value-to-off.patch @@ -14,7 +14,7 @@ Signed-off-by: Benjamin Marzinski 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h -index 64b633f2..5bda9f93 100644 +index ed08c251..4b033ff9 100644 --- a/libmultipath/defaults.h +++ b/libmultipath/defaults.h @@ -23,7 +23,7 @@ @@ -27,10 +27,10 @@ index 64b633f2..5bda9f93 100644 #define DEFAULT_DEV_LOSS_TMO 600 #define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_ON diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in -index 87b3b2a5..8e246571 100644 +index 645e8f88..a7543939 100644 --- a/multipath/multipath.conf.5.in +++ b/multipath/multipath.conf.5.in -@@ -1213,7 +1213,7 @@ as non-multipath and passed on to upper layers. +@@ -1225,7 +1225,7 @@ as non-multipath and passed on to upper layers. \fBNote:\fR this may cause delays during device detection if there are single-path devices which aren\'t blacklisted. .TP diff --git a/0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch b/0053-RH-attempt-to-get-ANA-info-via-sysfs-first.patch similarity index 100% rename from 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch rename to 0053-RH-attempt-to-get-ANA-info-via-sysfs-first.patch diff --git a/0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch b/0054-RH-make-parse_vpd_pg83-match-scsi_id-output.patch similarity index 84% rename from 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch rename to 0054-RH-make-parse_vpd_pg83-match-scsi_id-output.patch index aa49d69..c090da0 100644 --- a/0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +++ b/0054-RH-make-parse_vpd_pg83-match-scsi_id-output.patch @@ -14,10 +14,10 @@ Signed-off-by: Benjamin Marzinski 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index 6fd4dabb..19692b1e 100644 +index e2052422..3bcd94ce 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c -@@ -1216,13 +1216,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, +@@ -1221,13 +1221,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, good_len = 8; break; case 2: @@ -33,7 +33,7 @@ index 6fd4dabb..19692b1e 100644 good_len = 8; break; default: -@@ -1240,10 +1236,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, +@@ -1245,10 +1241,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, break; case 0x8: /* SCSI Name: Prio 3 */ @@ -45,10 +45,10 @@ index 6fd4dabb..19692b1e 100644 case 0x1: /* T-10 Vendor ID: Prio 2 */ diff --git a/tests/vpd.c b/tests/vpd.c -index 1b2d62d6..7309b5c5 100644 +index e3212e61..cdb111bb 100644 --- a/tests/vpd.c +++ b/tests/vpd.c -@@ -231,11 +231,13 @@ static const char * const str_prefix[] = { +@@ -232,11 +232,13 @@ static const char * const str_prefix[] = { [STR_IQN] = "iqn.", }; @@ -62,7 +62,7 @@ index 1b2d62d6..7309b5c5 100644 /** * create_scsi_string_desc() - create a SCSI name string descriptor. -@@ -766,6 +768,7 @@ make_test_vpd_naa(2, 18); +@@ -767,6 +769,7 @@ make_test_vpd_naa(2, 18); make_test_vpd_naa(2, 17); make_test_vpd_naa(2, 16); @@ -70,7 +70,7 @@ index 1b2d62d6..7309b5c5 100644 /* SCSI Name string: EUI64, WWID size: 17 */ make_test_vpd_str(0, 20, 18) make_test_vpd_str(0, 20, 17) -@@ -801,6 +804,7 @@ make_test_vpd_str(18, 20, 18) +@@ -802,6 +805,7 @@ make_test_vpd_str(18, 20, 18) make_test_vpd_str(18, 20, 17) make_test_vpd_str(18, 20, 16) make_test_vpd_str(18, 20, 15) @@ -78,7 +78,7 @@ index 1b2d62d6..7309b5c5 100644 static int test_vpd(void) { -@@ -909,6 +913,7 @@ static int test_vpd(void) +@@ -910,6 +914,7 @@ static int test_vpd(void) cmocka_unit_test(test_vpd_naa_2_18), cmocka_unit_test(test_vpd_naa_2_17), cmocka_unit_test(test_vpd_naa_2_16), @@ -86,7 +86,7 @@ index 1b2d62d6..7309b5c5 100644 cmocka_unit_test(test_vpd_str_0_20_18), cmocka_unit_test(test_vpd_str_0_20_17), cmocka_unit_test(test_vpd_str_0_20_16), -@@ -933,6 +938,7 @@ static int test_vpd(void) +@@ -934,6 +939,7 @@ static int test_vpd(void) cmocka_unit_test(test_vpd_str_18_20_17), cmocka_unit_test(test_vpd_str_18_20_16), cmocka_unit_test(test_vpd_str_18_20_15), diff --git a/0011-RH-add-scsi-device-handlers-to-modules-load.d.patch b/0055-RH-add-scsi-device-handlers-to-modules-load.d.patch similarity index 96% rename from 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch rename to 0055-RH-add-scsi-device-handlers-to-modules-load.d.patch index 0059895..7624c5b 100644 --- a/0011-RH-add-scsi-device-handlers-to-modules-load.d.patch +++ b/0055-RH-add-scsi-device-handlers-to-modules-load.d.patch @@ -11,7 +11,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc -index 3d80d224..15e3bd3a 100644 +index 94e0ec85..49514b06 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -16,7 +16,7 @@ READLINE := diff --git a/0012-RH-compile-with-libreadline-support.patch b/0056-RH-compile-with-libreadline-support.patch similarity index 96% rename from 0012-RH-compile-with-libreadline-support.patch rename to 0056-RH-compile-with-libreadline-support.patch index b0c8749..eb0ab13 100644 --- a/0012-RH-compile-with-libreadline-support.patch +++ b/0056-RH-compile-with-libreadline-support.patch @@ -12,7 +12,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc -index 15e3bd3a..64384a72 100644 +index 49514b06..a3ed9f28 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -12,7 +12,7 @@ diff --git a/0013-RH-Add-mpathcleanup.patch b/0057-RH-Add-mpathcleanup.patch similarity index 96% rename from 0013-RH-Add-mpathcleanup.patch rename to 0057-RH-Add-mpathcleanup.patch index c15fb6d..bd2dcd6 100644 --- a/0013-RH-Add-mpathcleanup.patch +++ b/0057-RH-Add-mpathcleanup.patch @@ -14,7 +14,7 @@ Signed-off-by: Benjamin Marzinski create mode 100755 multipath/mpathcleanup diff --git a/multipath/Makefile b/multipath/Makefile -index 9f14036c..99ad81b0 100644 +index 3dc241cc..47e82234 100644 --- a/multipath/Makefile +++ b/multipath/Makefile @@ -25,6 +25,7 @@ install: @@ -24,15 +24,15 @@ index 9f14036c..99ad81b0 100644 + $(Q)$(INSTALL_PROGRAM) -m 755 mpathcleanup $(DESTDIR)$(bindir)/ $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) $(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) - $(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules -@@ -48,6 +49,7 @@ endif + $(Q)$(INSTALL_PROGRAM) -m 644 99-z-dm-mpath-late.rules $(DESTDIR)$(udevrulesdir) +@@ -49,6 +50,7 @@ endif uninstall: $(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC) $(Q)$(RM) $(DESTDIR)$(bindir)/mpathconf + $(Q)$(RM) $(DESTDIR)$(bindir)/mpathcleanup $(Q)$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules + $(Q)$(RM) $(DESTDIR)$(udevrulesdir)/99-z-dm-mpath-late.rules $(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf - $(Q)$(RM) $(DESTDIR)$(modulesloaddir)/scsi_dh.conf diff --git a/multipath/mpathcleanup b/multipath/mpathcleanup new file mode 100755 index 00000000..6fd921e4 diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 78bef5a..22e6ad7 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,30 +1,72 @@ Name: device-mapper-multipath -Version: 0.9.7 -Release: 7%{?dist} +Version: 0.9.8 +Release: 1%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ # The source for this package was pulled from upstream's git repo. Use the # following command to generate the tarball -# curl -L https://github.com/opensvc/multipath-tools/archive/0.9.7.tar.gz -o multipath-tools-0.9.7.tgz -Source0: multipath-tools-0.9.7.tgz +# curl -L https://github.com/opensvc/multipath-tools/archive/0.9.8.tar.gz -o multipath-tools-0.9.8.tgz +Source0: multipath-tools-0.9.8.tgz Source1: multipath.conf -Patch0001: 0001-RH-fixup-udev-rules-for-redhat.patch -Patch0002: 0002-RH-Remove-the-property-blacklist-exception-builtin.patch -Patch0003: 0003-RH-don-t-start-without-a-config-file.patch -Patch0004: 0004-RH-Fix-nvme-function-missing-argument.patch -Patch0005: 0005-RH-use-rpm-optflags-if-present.patch -Patch0006: 0006-RH-add-mpathconf.patch -Patch0007: 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch -Patch0008: 0008-RH-reset-default-find_mutipaths-value-to-off.patch -Patch0009: 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch -Patch0010: 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch -Patch0011: 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch -Patch0012: 0012-RH-compile-with-libreadline-support.patch -Patch0013: 0013-RH-Add-mpathcleanup.patch -Patch0014: 0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch -Patch0015: 0015-multipathd-fix-auto-resize-configuration.patch +Patch0001: 0001-11-dm-mpath.rules-fix-misspelled-DM_UDEV_DISABLE_OTH.patch +Patch0002: 0002-multipathd-use-condlog-level-for-setscheduler-error-.patch +Patch0003: 0003-multipathd-make-multipathd-scheduling-configurable.patch +Patch0004: 0004-libmpathutil-really-always-use-glibc-basename.patch +Patch0005: 0005-multipathd-make-multipathd-set-priority-to-RLIMIT_RT.patch +Patch0006: 0006-multipathd-Set-CPUWeight-to-1000-and-LimitRTPRIO-to-.patch +Patch0007: 0007-11-dm-mpath.rules-explain-logic-for-device-becoming-.patch +Patch0008: 0008-11-dm-mpath.rules-don-t-import-DM_NOSCAN-from-udev-d.patch +Patch0009: 0009-11-dm-mpath.rules-don-t-import-ID_FS_VERSION-from-ud.patch +Patch0010: 0010-11-dm-mpath.rules-adapt-MPATH_DEVICE_READY-0-logic-t.patch +Patch0011: 0011-11-dm-mpath.rules-adapt-coldplug-event-handling-ro-1.patch +Patch0012: 0012-11-dm-mpath.rules-don-t-import-properties-with-new-1.patch +Patch0013: 0013-11-dm-mpath.rules-replace-DM_SUSPENDED-by-.DM_SUSPEN.patch +Patch0014: 0014-11-dm-mpath.rules-replace-DM_NOSCAN-by-.DM_NOSCAN.patch +Patch0015: 0015-11-dm-mpath.rules-simplify-PATH_FAILED-case.patch +Patch0016: 0016-11-dm-mpath.rules-make-label-names-more-intuitive.patch +Patch0017: 0017-kpartx.rules-ignore-DM_SUSPENDED.patch +Patch0018: 0018-multipath-tools-tests-fix-CI-failures-on-arm-v7-with.patch +Patch0019: 0019-multipath-tools-tests-fix-CI-failures-with-clang-on-.patch +Patch0020: 0020-GitHub-actions-fixes-for-spelling-CI.patch +Patch0021: 0021-GitHub-workflows-run-workflows-if-workflow-file-has-.patch +Patch0022: 0022-multipath-tools-add-TGTDIR-option.patch +Patch0023: 0023-libmultipath-move-get_udev_for_mpp-to-sysfs.c.patch +Patch0024: 0024-libmultipath-add-mp_find_path_by_devt.patch +Patch0025: 0025-Revert-libmultipath-fix-max_sectors_kb-on-adding-pat.patch +Patch0026: 0026-libmultipath-Only-set-max_sectors_kb-on-map-creation.patch +Patch0027: 0027-libmultipath-set-max_sectors_kb-in-adopt_paths.patch +Patch0028: 0028-libmultipath-add-wildcard-k-for-printing-max_sectors.patch +Patch0029: 0029-multipath.conf-5-update-documentation-for-max_sector.patch +Patch0030: 0030-multipath-tools-simplify-comment-in-hwtable.patch +Patch0031: 0031-multipath-tools-unify-text-in-multipath.conf.5.patch +Patch0032: 0032-multipath-tools-update-man-pages-dates.patch +Patch0033: 0033-libmultipath-export-partmap_in_use.patch +Patch0034: 0034-libmultipath-change-flush_on_last_del-to-fix-a-multi.patch +Patch0035: 0035-libmultipath-remove-redundant-config-option-from-Inf.patch +Patch0036: 0036-libmultipath-pad-dev_loss_tmo-to-avoid-race-with-no_.patch +Patch0037: 0037-libmultipath-fix-deferred_remove-function-arguments.patch +Patch0038: 0038-libmultipath-use-bitwise-flags-for-map-flushing-API.patch +Patch0039: 0039-libmultipath-use-bitwise-flags-for-dm_simplecmd-API.patch +Patch0040: 0040-libmultipath-add-argument-names-to-some-prototypes.patch +Patch0041: 0041-libmultipath-bump-version-to-0.9.9.patch +Patch0042: 0042-GitHub-Workflows-native.yaml-run-for-Fedora-40.patch +Patch0043: 0043-update-NEWS.md.patch +Patch0044: 0044-multipath.conf.5.in-fix-man-page-date.patch +Patch0045: 0045-RH-fixup-udev-rules-for-redhat.patch +Patch0046: 0046-RH-Remove-the-property-blacklist-exception-builtin.patch +Patch0047: 0047-RH-don-t-start-without-a-config-file.patch +Patch0048: 0048-RH-Fix-nvme-function-missing-argument.patch +Patch0049: 0049-RH-use-rpm-optflags-if-present.patch +Patch0050: 0050-RH-add-mpathconf.patch +Patch0051: 0051-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +Patch0052: 0052-RH-reset-default-find_mutipaths-value-to-off.patch +Patch0053: 0053-RH-attempt-to-get-ANA-info-via-sysfs-first.patch +Patch0054: 0054-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +Patch0055: 0055-RH-add-scsi-device-handlers-to-modules-load.d.patch +Patch0056: 0056-RH-compile-with-libreadline-support.patch +Patch0057: 0057-RH-Add-mpathcleanup.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -111,7 +153,7 @@ This package contains the files needed to develop applications that use device-mapper-multipath's libdmmp C API library %prep -%autosetup -n multipath-tools-0.9.7 -p1 +%autosetup -n multipath-tools-0.9.8 -p1 cp %{SOURCE1} . %build @@ -172,6 +214,7 @@ fi %{_mandir}/man8/mpathpersist.8* %config /usr/lib/udev/rules.d/62-multipath.rules %config /usr/lib/udev/rules.d/11-dm-mpath.rules +%config /usr/lib/udev/rules.d/99-z-dm-mpath-late.rules %dir %{_modulesloaddir} %{_modulesloaddir}/scsi_dh.conf %{_tmpfilesdir}/multipath.conf @@ -232,6 +275,14 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Mon May 20 2024 Benjamin Marzinski - 0.9.8-1 +- Update source to upstream version 0.9.8 plus latest staging branch + * Previous patches 0014 & 0015 are included in the source tarball + * patches 0001-0044 are from the upstream staging branch +- Rename redhat patches + * Previous patches 0001-0013 are now patches 0045-0057 +- Install /lib/udev/rules.d/99-z-dm-mpath-late.rules + * Wed Jan 24 2024 Fedora Release Engineering - 0.9.7-7 - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild diff --git a/sources b/sources index 89f8f37..b0337e2 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (multipath-tools-0.9.7.tgz) = 0f4c97179a3de5a0c77893fec229eb183293fed8e5e01a9945b261845ccf5d13f8ef2c2ff0c17c9345217d236275caed4765422ec95aed80821f11658bf96e26 +SHA512 (multipath-tools-0.9.8.tgz) = 4d73bcf6bce769a829c306c609b206ddba65a708620f458106e406dd18d12f9a9d97f400662daa8e6a75c9fdf7decb6dcbda92cb807b6c53522c7b4b2795b627 SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942 From 59945a7f7ef24b659a0e3895f78f84a15384454a Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Thu, 13 Jun 2024 14:29:22 -0400 Subject: [PATCH 13/29] device-mapper-multipath-0.9.9-1 Update source to upstream version 0.9.9 * Previous patches 0001-0044 are included in the source tarball Rename redhat patches * Previous patches 0045-0057 are now patches 0001-0013 --- .gitignore | 1 + ...s-fix-misspelled-DM_UDEV_DISABLE_OTH.patch | 27 -- ... 0001-RH-fixup-udev-rules-for-redhat.patch | 0 ...property-blacklist-exception-builtin.patch | 0 ...ondlog-level-for-setscheduler-error-.patch | 27 -- ...RH-don-t-start-without-a-config-file.patch | 2 +- ...e-multipathd-scheduling-configurable.patch | 87 ----- ...H-Fix-nvme-function-missing-argument.patch | 0 ...til-really-always-use-glibc-basename.patch | 144 -------- ... 0005-RH-use-rpm-optflags-if-present.patch | 0 ...multipathd-set-priority-to-RLIMIT_RT.patch | 134 ------- ...hconf.patch => 0006-RH-add-mpathconf.patch | 0 ...PUWeight-to-1000-and-LimitRTPRIO-to-.patch | 33 -- ...s-explain-logic-for-device-becoming-.patch | 30 -- ...om-kernel-cmdline-mpath.wwids-with-A.patch | 0 ...s-don-t-import-DM_NOSCAN-from-udev-d.patch | 37 -- ...-default-find_mutipaths-value-to-off.patch | 0 ...s-don-t-import-ID_FS_VERSION-from-ud.patch | 27 -- ...empt-to-get-ANA-info-via-sysfs-first.patch | 0 ...s-adapt-MPATH_DEVICE_READY-0-logic-t.patch | 67 ---- ...-parse_vpd_pg83-match-scsi_id-output.patch | 0 ...s-adapt-coldplug-event-handling-ro-1.patch | 43 --- ...si-device-handlers-to-modules-load.d.patch | 0 ...s-don-t-import-properties-with-new-1.patch | 36 -- ...-RH-compile-with-libreadline-support.patch | 0 ...s-replace-DM_SUSPENDED-by-.DM_SUSPEN.patch | 75 ---- ...up.patch => 0013-RH-Add-mpathcleanup.patch | 0 ...ules-replace-DM_NOSCAN-by-.DM_NOSCAN.patch | 55 --- ...path.rules-simplify-PATH_FAILED-case.patch | 38 -- ...ules-make-label-names-more-intuitive.patch | 109 ------ 0017-kpartx.rules-ignore-DM_SUSPENDED.patch | 29 -- ...tests-fix-CI-failures-on-arm-v7-with.patch | 270 -------------- ...tests-fix-CI-failures-with-clang-on-.patch | 246 ------------- ...GitHub-actions-fixes-for-spelling-CI.patch | 31 -- ...-run-workflows-if-workflow-file-has-.patch | 146 -------- 0022-multipath-tools-add-TGTDIR-option.patch | 106 ------ ...ath-move-get_udev_for_mpp-to-sysfs.c.patch | 87 ----- ...ibmultipath-add-mp_find_path_by_devt.patch | 60 --- ...ath-fix-max_sectors_kb-on-adding-pat.patch | 33 -- ...y-set-max_sectors_kb-on-map-creation.patch | 122 ------ ...th-set-max_sectors_kb-in-adopt_paths.patch | 233 ------------ ...-wildcard-k-for-printing-max_sectors.patch | 89 ----- ...-update-documentation-for-max_sector.patch | 57 --- ...th-tools-simplify-comment-in-hwtable.patch | 34 -- ...tools-unify-text-in-multipath.conf.5.patch | 75 ---- ...ltipath-tools-update-man-pages-dates.patch | 86 ----- 0033-libmultipath-export-partmap_in_use.patch | 53 --- ...nge-flush_on_last_del-to-fix-a-multi.patch | 346 ------------------ ...ove-redundant-config-option-from-Inf.patch | 31 -- ...-dev_loss_tmo-to-avoid-race-with-no_.patch | 40 -- ...x-deferred_remove-function-arguments.patch | 107 ------ ...e-bitwise-flags-for-map-flushing-API.patch | 212 ----------- ...e-bitwise-flags-for-dm_simplecmd-API.patch | 117 ------ ...dd-argument-names-to-some-prototypes.patch | 34 -- 0041-libmultipath-bump-version-to-0.9.9.patch | 27 -- ...kflows-native.yaml-run-for-Fedora-40.patch | 24 -- 0043-update-NEWS.md.patch | 134 ------- ...ultipath.conf.5.in-fix-man-page-date.patch | 24 -- device-mapper-multipath.spec | 84 ++--- sources | 2 +- 60 files changed, 26 insertions(+), 3885 deletions(-) delete mode 100644 0001-11-dm-mpath.rules-fix-misspelled-DM_UDEV_DISABLE_OTH.patch rename 0045-RH-fixup-udev-rules-for-redhat.patch => 0001-RH-fixup-udev-rules-for-redhat.patch (100%) rename 0046-RH-Remove-the-property-blacklist-exception-builtin.patch => 0002-RH-Remove-the-property-blacklist-exception-builtin.patch (100%) delete mode 100644 0002-multipathd-use-condlog-level-for-setscheduler-error-.patch rename 0047-RH-don-t-start-without-a-config-file.patch => 0003-RH-don-t-start-without-a-config-file.patch (99%) delete mode 100644 0003-multipathd-make-multipathd-scheduling-configurable.patch rename 0048-RH-Fix-nvme-function-missing-argument.patch => 0004-RH-Fix-nvme-function-missing-argument.patch (100%) delete mode 100644 0004-libmpathutil-really-always-use-glibc-basename.patch rename 0049-RH-use-rpm-optflags-if-present.patch => 0005-RH-use-rpm-optflags-if-present.patch (100%) delete mode 100644 0005-multipathd-make-multipathd-set-priority-to-RLIMIT_RT.patch rename 0050-RH-add-mpathconf.patch => 0006-RH-add-mpathconf.patch (100%) delete mode 100644 0006-multipathd-Set-CPUWeight-to-1000-and-LimitRTPRIO-to-.patch delete mode 100644 0007-11-dm-mpath.rules-explain-logic-for-device-becoming-.patch rename 0051-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch => 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch (100%) delete mode 100644 0008-11-dm-mpath.rules-don-t-import-DM_NOSCAN-from-udev-d.patch rename 0052-RH-reset-default-find_mutipaths-value-to-off.patch => 0008-RH-reset-default-find_mutipaths-value-to-off.patch (100%) delete mode 100644 0009-11-dm-mpath.rules-don-t-import-ID_FS_VERSION-from-ud.patch rename 0053-RH-attempt-to-get-ANA-info-via-sysfs-first.patch => 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch (100%) delete mode 100644 0010-11-dm-mpath.rules-adapt-MPATH_DEVICE_READY-0-logic-t.patch rename 0054-RH-make-parse_vpd_pg83-match-scsi_id-output.patch => 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch (100%) delete mode 100644 0011-11-dm-mpath.rules-adapt-coldplug-event-handling-ro-1.patch rename 0055-RH-add-scsi-device-handlers-to-modules-load.d.patch => 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch (100%) delete mode 100644 0012-11-dm-mpath.rules-don-t-import-properties-with-new-1.patch rename 0056-RH-compile-with-libreadline-support.patch => 0012-RH-compile-with-libreadline-support.patch (100%) delete mode 100644 0013-11-dm-mpath.rules-replace-DM_SUSPENDED-by-.DM_SUSPEN.patch rename 0057-RH-Add-mpathcleanup.patch => 0013-RH-Add-mpathcleanup.patch (100%) delete mode 100644 0014-11-dm-mpath.rules-replace-DM_NOSCAN-by-.DM_NOSCAN.patch delete mode 100644 0015-11-dm-mpath.rules-simplify-PATH_FAILED-case.patch delete mode 100644 0016-11-dm-mpath.rules-make-label-names-more-intuitive.patch delete mode 100644 0017-kpartx.rules-ignore-DM_SUSPENDED.patch delete mode 100644 0018-multipath-tools-tests-fix-CI-failures-on-arm-v7-with.patch delete mode 100644 0019-multipath-tools-tests-fix-CI-failures-with-clang-on-.patch delete mode 100644 0020-GitHub-actions-fixes-for-spelling-CI.patch delete mode 100644 0021-GitHub-workflows-run-workflows-if-workflow-file-has-.patch delete mode 100644 0022-multipath-tools-add-TGTDIR-option.patch delete mode 100644 0023-libmultipath-move-get_udev_for_mpp-to-sysfs.c.patch delete mode 100644 0024-libmultipath-add-mp_find_path_by_devt.patch delete mode 100644 0025-Revert-libmultipath-fix-max_sectors_kb-on-adding-pat.patch delete mode 100644 0026-libmultipath-Only-set-max_sectors_kb-on-map-creation.patch delete mode 100644 0027-libmultipath-set-max_sectors_kb-in-adopt_paths.patch delete mode 100644 0028-libmultipath-add-wildcard-k-for-printing-max_sectors.patch delete mode 100644 0029-multipath.conf-5-update-documentation-for-max_sector.patch delete mode 100644 0030-multipath-tools-simplify-comment-in-hwtable.patch delete mode 100644 0031-multipath-tools-unify-text-in-multipath.conf.5.patch delete mode 100644 0032-multipath-tools-update-man-pages-dates.patch delete mode 100644 0033-libmultipath-export-partmap_in_use.patch delete mode 100644 0034-libmultipath-change-flush_on_last_del-to-fix-a-multi.patch delete mode 100644 0035-libmultipath-remove-redundant-config-option-from-Inf.patch delete mode 100644 0036-libmultipath-pad-dev_loss_tmo-to-avoid-race-with-no_.patch delete mode 100644 0037-libmultipath-fix-deferred_remove-function-arguments.patch delete mode 100644 0038-libmultipath-use-bitwise-flags-for-map-flushing-API.patch delete mode 100644 0039-libmultipath-use-bitwise-flags-for-dm_simplecmd-API.patch delete mode 100644 0040-libmultipath-add-argument-names-to-some-prototypes.patch delete mode 100644 0041-libmultipath-bump-version-to-0.9.9.patch delete mode 100644 0042-GitHub-Workflows-native.yaml-run-for-Fedora-40.patch delete mode 100644 0043-update-NEWS.md.patch delete mode 100644 0044-multipath.conf.5.in-fix-man-page-date.patch diff --git a/.gitignore b/.gitignore index 80e9936..3bea72e 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ multipath-tools-091027.tar.gz /multipath-tools-0.9.6.tgz /multipath-tools-0.9.7.tgz /multipath-tools-0.9.8.tgz +/multipath-tools-0.9.9.tgz diff --git a/0001-11-dm-mpath.rules-fix-misspelled-DM_UDEV_DISABLE_OTH.patch b/0001-11-dm-mpath.rules-fix-misspelled-DM_UDEV_DISABLE_OTH.patch deleted file mode 100644 index 4b9d7fc..0000000 --- a/0001-11-dm-mpath.rules-fix-misspelled-DM_UDEV_DISABLE_OTH.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 1 Mar 2024 18:16:32 +0100 -Subject: [PATCH] 11-dm-mpath.rules: fix misspelled - DM_UDEV_DISABLE_OTHER_RULES_FLAG - -Fixes: b3582da ("11-dm-mpath.rules: use import logic like 13-dm-disk.rules") -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - multipath/11-dm-mpath.rules.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in -index d364f9bc..d9585abf 100644 ---- a/multipath/11-dm-mpath.rules.in -+++ b/multipath/11-dm-mpath.rules.in -@@ -116,7 +116,7 @@ LABEL="scan_import" - ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}!="1", GOTO="import_end" - - # Don't import the properties from db if we will run blkid later. --ENV{DM_NOSCAN}!="1", ENV{DM_DISABLE_OTHER_RULES_FLAG}!="1", GOTO="import_end" -+ENV{DM_NOSCAN}!="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}!="1", GOTO="import_end" - - IMPORT{db}="ID_FS_TYPE" - IMPORT{db}="ID_FS_USAGE" diff --git a/0045-RH-fixup-udev-rules-for-redhat.patch b/0001-RH-fixup-udev-rules-for-redhat.patch similarity index 100% rename from 0045-RH-fixup-udev-rules-for-redhat.patch rename to 0001-RH-fixup-udev-rules-for-redhat.patch diff --git a/0046-RH-Remove-the-property-blacklist-exception-builtin.patch b/0002-RH-Remove-the-property-blacklist-exception-builtin.patch similarity index 100% rename from 0046-RH-Remove-the-property-blacklist-exception-builtin.patch rename to 0002-RH-Remove-the-property-blacklist-exception-builtin.patch diff --git a/0002-multipathd-use-condlog-level-for-setscheduler-error-.patch b/0002-multipathd-use-condlog-level-for-setscheduler-error-.patch deleted file mode 100644 index 8a6ff99..0000000 --- a/0002-multipathd-use-condlog-level-for-setscheduler-error-.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Fri, 1 Mar 2024 19:37:29 -0500 -Subject: [PATCH] multipathd: use condlog level for setscheduler error message - -condlog uses its own log levels, so LOG_WARNING makes no sense. It -actually translates to a message sent at the LOG_DEBUG level. - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck ---- - multipathd/main.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/multipathd/main.c b/multipathd/main.c -index 6193e691..85ac540f 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -3178,7 +3178,7 @@ setscheduler (void) - res = sched_setscheduler (0, SCHED_RR, &sched_param); - - if (res == -1) -- condlog(LOG_WARNING, "Could not set SCHED_RR at priority 99"); -+ condlog(2, "Could not set SCHED_RR at priority 99"); - return; - } - diff --git a/0047-RH-don-t-start-without-a-config-file.patch b/0003-RH-don-t-start-without-a-config-file.patch similarity index 99% rename from 0047-RH-don-t-start-without-a-config-file.patch rename to 0003-RH-don-t-start-without-a-config-file.patch index ad7962a..267ffa7 100644 --- a/0047-RH-don-t-start-without-a-config-file.patch +++ b/0003-RH-don-t-start-without-a-config-file.patch @@ -99,7 +99,7 @@ index 780bf852..2c518378 100644 ENV{DEVTYPE}!="partition", GOTO="test_dev" IMPORT{parent}="DM_MULTIPATH_DEVICE_PATH" diff --git a/multipathd/multipathd.8.in b/multipathd/multipathd.8.in -index 12b77156..499557a0 100644 +index 7bc8806e..315884eb 100644 --- a/multipathd/multipathd.8.in +++ b/multipathd/multipathd.8.in @@ -49,6 +49,8 @@ map regains its maximum performance and redundancy. diff --git a/0003-multipathd-make-multipathd-scheduling-configurable.patch b/0003-multipathd-make-multipathd-scheduling-configurable.patch deleted file mode 100644 index 8529152..0000000 --- a/0003-multipathd-make-multipathd-scheduling-configurable.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Fri, 1 Mar 2024 19:37:30 -0500 -Subject: [PATCH] multipathd: make multipathd scheduling configurable - -Currently multipathd always tries to run as a realtime process with a -priority of 99. This is excessive. As a first step towards fixing this, -make it possible at compile time to lower the priority or keep -multipathd from making itself a realtime process. - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck ---- - Makefile.inc | 6 ++++++ - README.md | 3 +++ - multipathd/Makefile | 3 +++ - multipathd/main.c | 5 +++-- - 4 files changed, 15 insertions(+), 2 deletions(-) - -diff --git a/Makefile.inc b/Makefile.inc -index 5668e638..6d206281 100644 ---- a/Makefile.inc -+++ b/Makefile.inc -@@ -18,6 +18,12 @@ READLINE := - # SCSI_DH_MODULES_PRELOAD := scsi_dh_alua scsi_dh_rdac - SCSI_DH_MODULES_PRELOAD := - -+# Multipathd scheduling priority. Set value from 1 to 99 to make multipathd -+# change its scheduling policy to SCHED_RR and its priority to the specified -+# value. set to 0 to stop multipathd from changing the scheduling policy and -+# priority it was started with. -+SCHED_RT_PRIO := 99 -+ - EXTRAVERSION := $(shell rev=$$(git rev-parse --short=7 HEAD 2>/dev/null); echo $${rev:+-g$$rev}) - - # PKG_CONFIG must be read from the environment to enable compilation -diff --git a/README.md b/README.md -index d4f35f57..bb41bf0e 100644 ---- a/README.md -+++ b/README.md -@@ -98,6 +98,9 @@ The following variables can be passed to the `make` command line: - By default, command line editing is disabled. - Note that using libreadline may - [make binary indistributable due to license incompatibility](https://github.com/opensvc/multipath-tools/issues/36). -+ * `SCHED_RT_PRIO={0-99}`: for values {1-99} set the realtime priority -+ multipathd will attempt to run with. for value 0, disable multipathd -+ changing itself to a realtime process. - * `ENABLE_LIBDMMP=0`: disable building libdmmp - * `ENABLE_DMEVENTS_POLL=0`: disable support for the device-mapper event - polling API. For use with pre-5.0 kernels that don't support dmevent polling -diff --git a/multipathd/Makefile b/multipathd/Makefile -index 997b40cf..7300f07a 100644 ---- a/multipathd/Makefile -+++ b/multipathd/Makefile -@@ -57,6 +57,9 @@ $(CLI): $(CLI_OBJS) - cli_handlers.o: cli_handlers.c - $(Q)$(CC) $(CPPFLAGS) $(CFLAGS) -Wno-unused-parameter -c -o $@ $< - -+main.o: main.c -+ $(Q)$(CC) $(CPPFLAGS) -DSCHED_RT_PRIO=$(SCHED_RT_PRIO) $(CFLAGS) -c -o $@ $< -+ - install: - $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) - $(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir) -diff --git a/multipathd/main.c b/multipathd/main.c -index 85ac540f..9486a8a3 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -3172,7 +3172,7 @@ setscheduler (void) - { - int res; - static struct sched_param sched_param = { -- .sched_priority = 99 -+ .sched_priority = SCHED_RT_PRIO - }; - - res = sched_setscheduler (0, SCHED_RR, &sched_param); -@@ -3471,7 +3471,8 @@ child (__attribute__((unused)) void *param) - if (!vecs) - goto failed; - -- setscheduler(); -+ if (SCHED_RT_PRIO) -+ setscheduler(); - set_oom_adj(); - #ifdef FPIN_EVENT_HANDLER - if (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN) diff --git a/0048-RH-Fix-nvme-function-missing-argument.patch b/0004-RH-Fix-nvme-function-missing-argument.patch similarity index 100% rename from 0048-RH-Fix-nvme-function-missing-argument.patch rename to 0004-RH-Fix-nvme-function-missing-argument.patch diff --git a/0004-libmpathutil-really-always-use-glibc-basename.patch b/0004-libmpathutil-really-always-use-glibc-basename.patch deleted file mode 100644 index 78f8859..0000000 --- a/0004-libmpathutil-really-always-use-glibc-basename.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Wed, 3 Apr 2024 18:55:54 +0200 -Subject: [PATCH] libmpathutil: really always use glibc basename() - -Despite 03a5456 ("libmultipath: always use glibc basename()"), we -still call the system library's basename() from libmultipath. -musl libc until 1.24 provided a prototype for basename() in string.h, -which was not correct and was resolved to the destructive POSIX -basename(). musl libc 1.25 removed this prototype. - -While the remaining code path doesn't strictly depend on the non-destructive -behavior of glibc's basename(), it's cleaner and safer to use the same -implementation everywhere. - -Fixes: 03a5456 ("libmultipath: always use glibc basename()") -Fixes: https://github.com/opensvc/multipath-tools/pull/84 - -Signed-off-by: Martin Wilck -Reviewed-by: Khem Raj -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmpathutil/libmpathutil.version | 4 ++++ - libmpathutil/util.c | 5 +---- - libmpathutil/util.h | 5 +++++ - tests/util.c | 31 +++++++++++++++++++++++++++++++ - 4 files changed, 41 insertions(+), 4 deletions(-) - -diff --git a/libmpathutil/libmpathutil.version b/libmpathutil/libmpathutil.version -index 80d64a3e..fee74a32 100644 ---- a/libmpathutil/libmpathutil.version -+++ b/libmpathutil/libmpathutil.version -@@ -129,3 +129,7 @@ LIBMPATHUTIL_2.0 { - vector_move_up; - vector_sort; - }; -+ -+LIBMPATHUTIL_2.1 { -+ libmp_basename; -+}; -diff --git a/libmpathutil/util.c b/libmpathutil/util.c -index 9d147fca..23d303f9 100644 ---- a/libmpathutil/util.c -+++ b/libmpathutil/util.c -@@ -32,18 +32,15 @@ strchop(char *str) - return i; - } - --#ifndef __GLIBC__ - /* - * glibc's non-destructive version of basename() - * License: LGPL-2.1-or-later - */ --static const char *__basename(const char *filename) -+const char *libmp_basename(const char *filename) - { - char *p = strrchr(filename, '/'); - return p ? p + 1 : filename; - } --#define basename(x) __basename(x) --#endif - - int - basenamecpy (const char *src, char *dst, size_t size) -diff --git a/libmpathutil/util.h b/libmpathutil/util.h -index de9fcfdd..4997fed6 100644 ---- a/libmpathutil/util.h -+++ b/libmpathutil/util.h -@@ -12,6 +12,11 @@ - #include - - size_t strchop(char *); -+ -+const char *libmp_basename(const char *filename); -+#ifndef __GLIBC__ -+#define basename(x) libmp_basename(x) -+#endif - int basenamecpy (const char *src, char *dst, size_t size); - int filepresent (const char *run); - char *get_next_string(char **temp, const char *split_char); -diff --git a/tests/util.c b/tests/util.c -index d6083dce..4850ddcb 100644 ---- a/tests/util.c -+++ b/tests/util.c -@@ -16,6 +16,7 @@ - * - */ - -+#define _GNU_SOURCE - #include - #include - #include -@@ -23,6 +24,7 @@ - #include - #include - #include -+#include - #include "util.h" - - #include "globals.c" -@@ -163,6 +165,34 @@ static int test_basenamecpy(void) - return cmocka_run_group_tests(tests, NULL, NULL); - } - -+static void test_basename_01(void **state) -+{ -+ const char *path = "/foo/bar"; -+ const char *base; -+ -+ base = basename(path); -+ assert_string_equal(base, "bar"); -+ assert_string_equal(path, "/foo/bar"); -+} -+ -+static void test_basename_02(void **state) -+{ -+ const char *path = "/foo/bar/"; -+ const char *base; -+ -+ base = basename(path); -+ assert_string_equal(base, ""); -+ assert_string_equal(path, "/foo/bar/"); -+} -+ -+static int test_basename(void) { -+ const struct CMUnitTest tests[] = { -+ cmocka_unit_test(test_basename_01), -+ cmocka_unit_test(test_basename_02), -+ }; -+ return cmocka_run_group_tests(tests, NULL, NULL); -+} -+ - /* - * On big endian systems, if bitfield_t is 32bit, we need - * to swap the two 32 bit parts of a 64bit value to make -@@ -946,6 +976,7 @@ int main(void) - - init_test_verbosity(-1); - ret += test_basenamecpy(); -+ ret += test_basename(); - ret += test_bitmasks(); - ret += test_strlcpy(); - ret += test_strlcat(); diff --git a/0049-RH-use-rpm-optflags-if-present.patch b/0005-RH-use-rpm-optflags-if-present.patch similarity index 100% rename from 0049-RH-use-rpm-optflags-if-present.patch rename to 0005-RH-use-rpm-optflags-if-present.patch diff --git a/0005-multipathd-make-multipathd-set-priority-to-RLIMIT_RT.patch b/0005-multipathd-make-multipathd-set-priority-to-RLIMIT_RT.patch deleted file mode 100644 index fd12767..0000000 --- a/0005-multipathd-make-multipathd-set-priority-to-RLIMIT_RT.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Tue, 9 Apr 2024 18:56:12 -0400 -Subject: [PATCH] multipathd: make multipathd set priority to RLIMIT_RTPRIO - -With this change, if the SCHED_RT_PRIO compiler flag has been removed. -Instead multipathd will call getrlimit(RLIMIT_RTPRIO, ...) and look at -the hard limit. It it's 0, multipath will do nothing. Otherwise it will -change its scheduling policy to SCHED_RR and its priority to the hard -limit. - -This allows users to change the priority of that multipathd runs with by -adding - -LimitRTPRIO= - -to the [Service] section of the multipathd.service unit file. Setting -LimitRTPRIO=0 will make multipathd run as a normal process, while -setting LimitRTPRIO=infinity will make it use the maximum SCHED_RR prio, -which is 99. - -To keep the existing behavior, multipathd.service now sets -LimitRTPRIO=infinity - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck ---- - Makefile.inc | 6 ------ - README.md | 3 --- - multipathd/Makefile | 3 --- - multipathd/main.c | 22 +++++++++++++++------- - multipathd/multipathd.service.in | 1 + - 5 files changed, 16 insertions(+), 19 deletions(-) - -diff --git a/Makefile.inc b/Makefile.inc -index 6d206281..5668e638 100644 ---- a/Makefile.inc -+++ b/Makefile.inc -@@ -18,12 +18,6 @@ READLINE := - # SCSI_DH_MODULES_PRELOAD := scsi_dh_alua scsi_dh_rdac - SCSI_DH_MODULES_PRELOAD := - --# Multipathd scheduling priority. Set value from 1 to 99 to make multipathd --# change its scheduling policy to SCHED_RR and its priority to the specified --# value. set to 0 to stop multipathd from changing the scheduling policy and --# priority it was started with. --SCHED_RT_PRIO := 99 -- - EXTRAVERSION := $(shell rev=$$(git rev-parse --short=7 HEAD 2>/dev/null); echo $${rev:+-g$$rev}) - - # PKG_CONFIG must be read from the environment to enable compilation -diff --git a/README.md b/README.md -index bb41bf0e..d4f35f57 100644 ---- a/README.md -+++ b/README.md -@@ -98,9 +98,6 @@ The following variables can be passed to the `make` command line: - By default, command line editing is disabled. - Note that using libreadline may - [make binary indistributable due to license incompatibility](https://github.com/opensvc/multipath-tools/issues/36). -- * `SCHED_RT_PRIO={0-99}`: for values {1-99} set the realtime priority -- multipathd will attempt to run with. for value 0, disable multipathd -- changing itself to a realtime process. - * `ENABLE_LIBDMMP=0`: disable building libdmmp - * `ENABLE_DMEVENTS_POLL=0`: disable support for the device-mapper event - polling API. For use with pre-5.0 kernels that don't support dmevent polling -diff --git a/multipathd/Makefile b/multipathd/Makefile -index 7300f07a..997b40cf 100644 ---- a/multipathd/Makefile -+++ b/multipathd/Makefile -@@ -57,9 +57,6 @@ $(CLI): $(CLI_OBJS) - cli_handlers.o: cli_handlers.c - $(Q)$(CC) $(CPPFLAGS) $(CFLAGS) -Wno-unused-parameter -c -o $@ $< - --main.o: main.c -- $(Q)$(CC) $(CPPFLAGS) -DSCHED_RT_PRIO=$(SCHED_RT_PRIO) $(CFLAGS) -c -o $@ $< -- - install: - $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) - $(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir) -diff --git a/multipathd/main.c b/multipathd/main.c -index 9486a8a3..dd17d5c3 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -3171,14 +3171,23 @@ static void - setscheduler (void) - { - int res; -- static struct sched_param sched_param = { -- .sched_priority = SCHED_RT_PRIO -- }; -+ static struct sched_param sched_param; -+ struct rlimit rlim; -+ -+ if (getrlimit(RLIMIT_RTPRIO, &rlim) < 0 || rlim.rlim_max == 0) -+ return; -+ -+ sched_param.sched_priority = rlim.rlim_max > INT_MAX ? INT_MAX : -+ rlim.rlim_max; -+ res = sched_get_priority_max(SCHED_RR); -+ if (res > 0 && res < sched_param.sched_priority) -+ sched_param.sched_priority = res; - -- res = sched_setscheduler (0, SCHED_RR, &sched_param); -+ res = sched_setscheduler(0, SCHED_RR, &sched_param); - - if (res == -1) -- condlog(2, "Could not set SCHED_RR at priority 99"); -+ condlog(2, "Could not set SCHED_RR at priority %d", -+ sched_param.sched_priority); - return; - } - -@@ -3471,8 +3480,7 @@ child (__attribute__((unused)) void *param) - if (!vecs) - goto failed; - -- if (SCHED_RT_PRIO) -- setscheduler(); -+ setscheduler(); - set_oom_adj(); - #ifdef FPIN_EVENT_HANDLER - if (conf->marginal_pathgroups == MARGINAL_PATHGROUP_FPIN) -diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in -index 6d03ff71..18bb367e 100644 ---- a/multipathd/multipathd.service.in -+++ b/multipathd/multipathd.service.in -@@ -19,6 +19,7 @@ NotifyAccess=main - ExecStart=/sbin/multipathd -d -s - ExecReload=/sbin/multipathd reconfigure - TasksMax=infinity -+LimitRTPRIO=infinity - - [Install] - WantedBy=sysinit.target diff --git a/0050-RH-add-mpathconf.patch b/0006-RH-add-mpathconf.patch similarity index 100% rename from 0050-RH-add-mpathconf.patch rename to 0006-RH-add-mpathconf.patch diff --git a/0006-multipathd-Set-CPUWeight-to-1000-and-LimitRTPRIO-to-.patch b/0006-multipathd-Set-CPUWeight-to-1000-and-LimitRTPRIO-to-.patch deleted file mode 100644 index 0cbe997..0000000 --- a/0006-multipathd-Set-CPUWeight-to-1000-and-LimitRTPRIO-to-.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Mon, 15 Apr 2024 19:43:06 -0400 -Subject: [PATCH] multipathd: Set CPUWeight to 1000 and LimitRTPRIO to 10 - -If multipathd doesn't become a real time process, it was scheduled as a -normal process, without any priority increase. Bump up the CPUWeight so -that even as a normal process, it will still run with increased -priority. - -If multipathd did become a real time process, it set itself to the -highest priority, which is excessive. A priority of 10 is plenty. - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck ---- - multipathd/multipathd.service.in | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in -index 18bb367e..a63ddd9a 100644 ---- a/multipathd/multipathd.service.in -+++ b/multipathd/multipathd.service.in -@@ -19,7 +19,8 @@ NotifyAccess=main - ExecStart=/sbin/multipathd -d -s - ExecReload=/sbin/multipathd reconfigure - TasksMax=infinity --LimitRTPRIO=infinity -+LimitRTPRIO=10 -+CPUWeight=1000 - - [Install] - WantedBy=sysinit.target diff --git a/0007-11-dm-mpath.rules-explain-logic-for-device-becoming-.patch b/0007-11-dm-mpath.rules-explain-logic-for-device-becoming-.patch deleted file mode 100644 index 6241459..0000000 --- a/0007-11-dm-mpath.rules-explain-logic-for-device-becoming-.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 1 Mar 2024 19:53:14 +0100 -Subject: [PATCH] 11-dm-mpath.rules: explain logic for device becoming ready - while suspended - -Add a comment to explain why we must set MPATH_DEVICE_READY=0 when -we see a device becoming ready (number of active paths 0 -> 1) while -the device is suspended. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - multipath/11-dm-mpath.rules.in | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in -index d9585abf..b8d19d01 100644 ---- a/multipath/11-dm-mpath.rules.in -+++ b/multipath/11-dm-mpath.rules.in -@@ -98,6 +98,8 @@ ENV{MPATH_DEVICE_READY}=="0", \ - # If the device comes back online, set DM_ACTIVATION so that - # upper layers do a rescan. If the device is currently suspended, - # we have to postpone the activation until the next event. -+# In this case, we have to set MPATH_DEVICE_READY=0; otherwise, the -+# MPATH_UNCHANGED logic will cause later rules to skipped in the next event. - ENV{MPATH_DEVICE_READY}=="0", GOTO="dont_activate" - ENV{.MPATH_DEVICE_READY_OLD}!="0", GOTO="dont_activate" - ENV{DM_SUSPENDED}=="1", ENV{MPATH_DEVICE_READY}="0", GOTO="dont_activate" diff --git a/0051-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch b/0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch similarity index 100% rename from 0051-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch rename to 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch diff --git a/0008-11-dm-mpath.rules-don-t-import-DM_NOSCAN-from-udev-d.patch b/0008-11-dm-mpath.rules-don-t-import-DM_NOSCAN-from-udev-d.patch deleted file mode 100644 index 3900b39..0000000 --- a/0008-11-dm-mpath.rules-don-t-import-DM_NOSCAN-from-udev-d.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 1 Mar 2024 19:57:59 +0100 -Subject: [PATCH] 11-dm-mpath.rules: don't import DM_NOSCAN from udev db - -DM_NOSCAN is our "output" flag for 13-dm-disk.rules, and it should -be treated the same way as DM_UDEV_DISABLE_OTHER_RULES_FLAG, which -isn't imported from the udev database. The state that we need to -remember is MPATH_DEVICE_READY, which we've already imported above, -and we will set the "output" flags accordingly in the "force_activation" -code path further down. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - multipath/11-dm-mpath.rules.in | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in -index b8d19d01..eb12b0c6 100644 ---- a/multipath/11-dm-mpath.rules.in -+++ b/multipath/11-dm-mpath.rules.in -@@ -18,9 +18,11 @@ ACTION=="add", ENV{DM_ACTIVATION}=="1", ENV{DM_SUSPENDED}!="1", ENV{DISK_RO}!="1 - - # If this uevent didn't come from dm, don't try to update the - # device state -+# Note that .MPATH_DEVICE_READY_OLD=="" here. Thus we won't activate the -+# device below at force_activation, which is correct. - ENV{DM_COOKIE}!="?*", ENV{DM_ACTION}!="PATH_*", \ -- IMPORT{db}="DM_NOSCAN", IMPORT{db}="DM_COLDPLUG_SUSPENDED", \ -- GOTO="scan_import" -+ IMPORT{db}="DM_COLDPLUG_SUSPENDED", \ -+ GOTO="force_activation" - - ENV{.MPATH_DEVICE_READY_OLD}="$env{MPATH_DEVICE_READY}" - diff --git a/0052-RH-reset-default-find_mutipaths-value-to-off.patch b/0008-RH-reset-default-find_mutipaths-value-to-off.patch similarity index 100% rename from 0052-RH-reset-default-find_mutipaths-value-to-off.patch rename to 0008-RH-reset-default-find_mutipaths-value-to-off.patch diff --git a/0009-11-dm-mpath.rules-don-t-import-ID_FS_VERSION-from-ud.patch b/0009-11-dm-mpath.rules-don-t-import-ID_FS_VERSION-from-ud.patch deleted file mode 100644 index 933a43a..0000000 --- a/0009-11-dm-mpath.rules-don-t-import-ID_FS_VERSION-from-ud.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 1 Mar 2024 21:02:49 +0100 -Subject: [PATCH] 11-dm-mpath.rules: don't import ID_FS_VERSION from udev db - -Use the same set of properties to import as 13-dm-disk.rules. -ID_FS_VERSION isn't used in any udev rule I am aware of. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - multipath/11-dm-mpath.rules.in | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in -index eb12b0c6..4386b6ca 100644 ---- a/multipath/11-dm-mpath.rules.in -+++ b/multipath/11-dm-mpath.rules.in -@@ -126,7 +126,6 @@ IMPORT{db}="ID_FS_TYPE" - IMPORT{db}="ID_FS_USAGE" - IMPORT{db}="ID_FS_UUID_ENC" - IMPORT{db}="ID_FS_LABEL_ENC" --IMPORT{db}="ID_FS_VERSION" - IMPORT{db}="ID_PART_ENTRY_NAME" - IMPORT{db}="ID_PART_ENTRY_UUID" - IMPORT{db}="ID_PART_ENTRY_SCHEME" diff --git a/0053-RH-attempt-to-get-ANA-info-via-sysfs-first.patch b/0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch similarity index 100% rename from 0053-RH-attempt-to-get-ANA-info-via-sysfs-first.patch rename to 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch diff --git a/0010-11-dm-mpath.rules-adapt-MPATH_DEVICE_READY-0-logic-t.patch b/0010-11-dm-mpath.rules-adapt-MPATH_DEVICE_READY-0-logic-t.patch deleted file mode 100644 index 97b3901..0000000 --- a/0010-11-dm-mpath.rules-adapt-MPATH_DEVICE_READY-0-logic-t.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 1 Mar 2024 20:53:50 +0100 -Subject: [PATCH] 11-dm-mpath.rules: adapt MPATH_DEVICE_READY=0 logic to - 10-dm.rules update - -With the late patches for 10-dm.rules, DM_UDEV_DISABLE_OTHER_RULES_FLAG isn't -restored from the udev database any more, so we don't need to restore -the flag to its original state before it is saved to the db. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - multipath/11-dm-mpath.rules.in | 22 ++++++++++++---------- - 1 file changed, 12 insertions(+), 10 deletions(-) - -diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in -index 4386b6ca..2f909c3a 100644 ---- a/multipath/11-dm-mpath.rules.in -+++ b/multipath/11-dm-mpath.rules.in -@@ -19,7 +19,7 @@ ACTION=="add", ENV{DM_ACTIVATION}=="1", ENV{DM_SUSPENDED}!="1", ENV{DISK_RO}!="1 - # If this uevent didn't come from dm, don't try to update the - # device state - # Note that .MPATH_DEVICE_READY_OLD=="" here. Thus we won't activate the --# device below at force_activation, which is correct. -+# device below at mpath_is_ready, which is correct. - ENV{DM_COOKIE}!="?*", ENV{DM_ACTION}!="PATH_*", \ - IMPORT{db}="DM_COLDPLUG_SUSPENDED", \ - GOTO="force_activation" -@@ -84,25 +84,27 @@ ENV{DM_ACTION}=="PATH_FAILED|PATH_REINSTATED", \ - - LABEL="force_activation" - -+ENV{MPATH_DEVICE_READY}!="0", GOTO="mpath_is_ready" - # Do not initiate scanning if no path is available, - # otherwise there would be a hang or IO error on access. - # We'd like to avoid this, especially within udev processing. --ENV{MPATH_DEVICE_READY}=="0", ENV{DM_NOSCAN}="1" -- --# Skip all foreign rules if no path is available. -+# This is communicated to later rules in DM_NOSCAN. -+# Likewise, skip all foreign rules if no path is available. - # Use DM_UDEV_DISABLE_OTHER_RULES_FLAG to communicate this --# to upper layers. The original value will be restored in a late --# udev rule. --ENV{MPATH_DEVICE_READY}=="0", \ -- ENV{.MPATH_SAVE_DISABLE_OTHER_RULES_FLAG}="$env{DM_UDEV_DISABLE_OTHER_RULES_FLAG}", \ -- ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1" -+# to upper layers. With dm rules < v3, save the original value here; -+# it will be restored in a late udev rule. -+ENV{DM_UDEV_RULES_VSN}=="1|2", \ -+ ENV{.MPATH_SAVE_DISABLE_OTHER_RULES_FLAG}="$env{DM_UDEV_DISABLE_OTHER_RULES_FLAG}" -+ENV{DM_NOSCAN}="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1" -+GOTO="dont_activate" -+ -+LABEL="mpath_is_ready" - - # If the device comes back online, set DM_ACTIVATION so that - # upper layers do a rescan. If the device is currently suspended, - # we have to postpone the activation until the next event. - # In this case, we have to set MPATH_DEVICE_READY=0; otherwise, the - # MPATH_UNCHANGED logic will cause later rules to skipped in the next event. --ENV{MPATH_DEVICE_READY}=="0", GOTO="dont_activate" - ENV{.MPATH_DEVICE_READY_OLD}!="0", GOTO="dont_activate" - ENV{DM_SUSPENDED}=="1", ENV{MPATH_DEVICE_READY}="0", GOTO="dont_activate" - diff --git a/0054-RH-make-parse_vpd_pg83-match-scsi_id-output.patch b/0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch similarity index 100% rename from 0054-RH-make-parse_vpd_pg83-match-scsi_id-output.patch rename to 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch diff --git a/0011-11-dm-mpath.rules-adapt-coldplug-event-handling-ro-1.patch b/0011-11-dm-mpath.rules-adapt-coldplug-event-handling-ro-1.patch deleted file mode 100644 index 938a07f..0000000 --- a/0011-11-dm-mpath.rules-adapt-coldplug-event-handling-ro-1.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 1 Mar 2024 20:55:40 +0100 -Subject: [PATCH] 11-dm-mpath.rules: adapt coldplug event handling ro - 10-dm.rules update - -With late late patches for 10-dm.rules, DM_UDEV_DISABLE_OTHER_RULES_FLAG is -never restored from the udev db. Thus we don't need to clear it here -any more for coldplug events. Also, we must use .DM_SUSPENDED instead of -DM_SUSPENDED as input flag with the v3 rule set (other occurences of -DM_SUSPENDED will be replaced in a follow-up patch). - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - multipath/11-dm-mpath.rules.in | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in -index 2f909c3a..5f547cab 100644 ---- a/multipath/11-dm-mpath.rules.in -+++ b/multipath/11-dm-mpath.rules.in -@@ -9,12 +9,17 @@ ACTION=="add", ENV{DM_ACTIVATION}=="1", ENV{DM_SUSPENDED}=="1", \ - PROGRAM="/bin/logger -t 11-dm-mpath.rules -p daemon.warning \"Coldplug event for suspended device\"", \ - ENV{DM_COLDPLUG_SUSPENDED}="1", GOTO="scan_import" - --# Coldplug event. DM_UDEV_DISABLE_OTHER_RULES_FLAG has been restored -+# Coldplug event. Import previously set properties. -+ACTION!="add", GOTO="mpath_coldplug_end" -+ENV{DM_ACTIVATION}!="1", GOTO="mpath_coldplug_end" -+ENV{DM_UDEV_RULES_VSN}!="1|2", ENV{.DM_SUSPENDED}!="1", GOTO="scan_import" -+# With DM rules < v3, DM_UDEV_DISABLE_OTHER_RULES_FLAG has been restored - # from DB in 10-dm.rules. If the device is not suspended, clear the flag. - # This is safe for multipath where DM_UDEV_DISABLE_OTHER_RULES_FLAG is basically - # equivalent to DM_SUSPENDED==1 || DISK_RO==1 --ACTION=="add", ENV{DM_ACTIVATION}=="1", ENV{DM_SUSPENDED}!="1", ENV{DISK_RO}!="1", \ -+ENV{DM_UDEV_RULES_VSN}=="1|2", ENV{DM_SUSPENDED}!="1", ENV{DISK_RO}!="1", \ - ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="", GOTO="scan_import" -+LABEL="mpath_coldplug_end" - - # If this uevent didn't come from dm, don't try to update the - # device state diff --git a/0055-RH-add-scsi-device-handlers-to-modules-load.d.patch b/0011-RH-add-scsi-device-handlers-to-modules-load.d.patch similarity index 100% rename from 0055-RH-add-scsi-device-handlers-to-modules-load.d.patch rename to 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch diff --git a/0012-11-dm-mpath.rules-don-t-import-properties-with-new-1.patch b/0012-11-dm-mpath.rules-don-t-import-properties-with-new-1.patch deleted file mode 100644 index f4e69cf..0000000 --- a/0012-11-dm-mpath.rules-don-t-import-properties-with-new-1.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 1 Mar 2024 20:58:47 +0100 -Subject: [PATCH] 11-dm-mpath.rules: don't import properties with new - 13-dm-disk.rules - -With the late changes to 13-dm-disk.rules, we don't need to import any -blkid-generated properties from the udev database, because they will -be imported later. - -Except for ID_FS_TYPE, this actually holds since lvm2 commit 94f77a4 ("udev: -import previous results of blkid when in suspended state"), included in lvm2 -2.03.19, but we have no simple way to detect the version of the lvm2 rules. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - multipath/11-dm-mpath.rules.in | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in -index 5f547cab..95126bf2 100644 ---- a/multipath/11-dm-mpath.rules.in -+++ b/multipath/11-dm-mpath.rules.in -@@ -126,6 +126,10 @@ LABEL="scan_import" - # have never been properly set. Don't import them. - ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}!="1", GOTO="import_end" - -+# DM rules v3 will import missing properties on 13-dm-disk.rules. -+# No need to do it here. -+ENV{DM_UDEV_RULES_VSN}!="1|2", GOTO="import_end" -+ - # Don't import the properties from db if we will run blkid later. - ENV{DM_NOSCAN}!="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}!="1", GOTO="import_end" - diff --git a/0056-RH-compile-with-libreadline-support.patch b/0012-RH-compile-with-libreadline-support.patch similarity index 100% rename from 0056-RH-compile-with-libreadline-support.patch rename to 0012-RH-compile-with-libreadline-support.patch diff --git a/0013-11-dm-mpath.rules-replace-DM_SUSPENDED-by-.DM_SUSPEN.patch b/0013-11-dm-mpath.rules-replace-DM_SUSPENDED-by-.DM_SUSPEN.patch deleted file mode 100644 index e922427..0000000 --- a/0013-11-dm-mpath.rules-replace-DM_SUSPENDED-by-.DM_SUSPEN.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 1 Mar 2024 22:33:59 +0100 -Subject: [PATCH] 11-dm-mpath.rules: replace DM_SUSPENDED by .DM_SUSPENDED - -With the late changes to the device mapper rules, DM_SUSPENDED -is not exported any more. Use .DM_SUSPENDED instead. - -Note that although 11-dm-mpath.rules is not a part of lvm2, it -can be considered as part of the device-mapper layer (everything -before 13-dm-disk.rules can), and is thus allowed to use -.DM_SUSPENDED. In practice .DM_SUSPENDED is equivalent to -DM_UDEV_DISABLE_OTHER_RULES_FLAG for multipath devices, but -using .DM_SUSPENDED here makes the intention more obvious. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - multipath/11-dm-mpath.rules.in | 13 ++++++++----- - 1 file changed, 8 insertions(+), 5 deletions(-) - -diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in -index 95126bf2..efc6416f 100644 ---- a/multipath/11-dm-mpath.rules.in -+++ b/multipath/11-dm-mpath.rules.in -@@ -4,8 +4,11 @@ ENV{DM_UUID}!="mpath-?*", GOTO="mpath_end" - - IMPORT{db}="MPATH_DEVICE_READY" - -+# device-mapper rules v2 compatibility -+ENV{.DM_SUSPENDED}!="?*", ENV{.DM_SUSPENDED}="$env{DM_SUSPENDED}" -+ - # Coldplug event while device is suspended (e.g. during a reload) --ACTION=="add", ENV{DM_ACTIVATION}=="1", ENV{DM_SUSPENDED}=="1", \ -+ACTION=="add", ENV{DM_ACTIVATION}=="1", ENV{.DM_SUSPENDED}=="1", \ - PROGRAM="/bin/logger -t 11-dm-mpath.rules -p daemon.warning \"Coldplug event for suspended device\"", \ - ENV{DM_COLDPLUG_SUSPENDED}="1", GOTO="scan_import" - -@@ -17,7 +20,7 @@ ENV{DM_UDEV_RULES_VSN}!="1|2", ENV{.DM_SUSPENDED}!="1", GOTO="scan_import" - # from DB in 10-dm.rules. If the device is not suspended, clear the flag. - # This is safe for multipath where DM_UDEV_DISABLE_OTHER_RULES_FLAG is basically - # equivalent to DM_SUSPENDED==1 || DISK_RO==1 --ENV{DM_UDEV_RULES_VSN}=="1|2", ENV{DM_SUSPENDED}!="1", ENV{DISK_RO}!="1", \ -+ENV{DM_UDEV_RULES_VSN}=="1|2", ENV{.DM_SUSPENDED}!="1", ENV{DISK_RO}!="1", \ - ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="", GOTO="scan_import" - LABEL="mpath_coldplug_end" - -@@ -68,7 +71,7 @@ LABEL="mpath_action" - # Activation might have been partially skipped. Activate the device now, - # i.e. disable the MPATH_UNCHANGED logic and set DM_ACTIVATION=1. - IMPORT{db}="DM_COLDPLUG_SUSPENDED" --ENV{DM_COLDPLUG_SUSPENDED}=="1", ENV{DM_SUSPENDED}!="1", \ -+ENV{DM_COLDPLUG_SUSPENDED}=="1", ENV{.DM_SUSPENDED}!="1", \ - ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0", \ - PROGRAM="/bin/logger -t 11-dm-mpath.rules -p daemon.notice \"Forcing activation of previously suspended device\"", \ - GOTO="force_activation" -@@ -111,7 +114,7 @@ LABEL="mpath_is_ready" - # In this case, we have to set MPATH_DEVICE_READY=0; otherwise, the - # MPATH_UNCHANGED logic will cause later rules to skipped in the next event. - ENV{.MPATH_DEVICE_READY_OLD}!="0", GOTO="dont_activate" --ENV{DM_SUSPENDED}=="1", ENV{MPATH_DEVICE_READY}="0", GOTO="dont_activate" -+ENV{.DM_SUSPENDED}=="1", ENV{MPATH_DEVICE_READY}="0", GOTO="dont_activate" - - ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0" - LABEL="dont_activate" -@@ -145,7 +148,7 @@ IMPORT{db}="ID_PART_GPT_AUTO_ROOT" - LABEL="import_end" - - # Reset previous DM_COLDPLUG_SUSPENDED if activation happens now --ENV{DM_SUSPENDED}!="1", ENV{DM_ACTIVATION}=="1", ENV{DM_COLDPLUG_SUSPENDED}="" -+ENV{.DM_SUSPENDED}!="1", ENV{DM_ACTIVATION}=="1", ENV{DM_COLDPLUG_SUSPENDED}="" - - # Multipath maps should take precedence over their members. - ENV{DM_UDEV_LOW_PRIORITY_FLAG}!="1", OPTIONS+="link_priority=50" diff --git a/0057-RH-Add-mpathcleanup.patch b/0013-RH-Add-mpathcleanup.patch similarity index 100% rename from 0057-RH-Add-mpathcleanup.patch rename to 0013-RH-Add-mpathcleanup.patch diff --git a/0014-11-dm-mpath.rules-replace-DM_NOSCAN-by-.DM_NOSCAN.patch b/0014-11-dm-mpath.rules-replace-DM_NOSCAN-by-.DM_NOSCAN.patch deleted file mode 100644 index a5eecaf..0000000 --- a/0014-11-dm-mpath.rules-replace-DM_NOSCAN-by-.DM_NOSCAN.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 1 Mar 2024 23:23:53 +0100 -Subject: [PATCH] 11-dm-mpath.rules: replace DM_NOSCAN by .DM_NOSCAN - -We don't need to restore DM_NOSCAN from the db anymore, so we can rename -it to .DM_NOSCAN, making it a temporary property. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - multipath/11-dm-mpath.rules.in | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in -index efc6416f..3ae3c054 100644 ---- a/multipath/11-dm-mpath.rules.in -+++ b/multipath/11-dm-mpath.rules.in -@@ -96,14 +96,14 @@ ENV{MPATH_DEVICE_READY}!="0", GOTO="mpath_is_ready" - # Do not initiate scanning if no path is available, - # otherwise there would be a hang or IO error on access. - # We'd like to avoid this, especially within udev processing. --# This is communicated to later rules in DM_NOSCAN. -+# This is communicated to later rules in .DM_NOSCAN. - # Likewise, skip all foreign rules if no path is available. - # Use DM_UDEV_DISABLE_OTHER_RULES_FLAG to communicate this - # to upper layers. With dm rules < v3, save the original value here; - # it will be restored in a late udev rule. - ENV{DM_UDEV_RULES_VSN}=="1|2", \ - ENV{.MPATH_SAVE_DISABLE_OTHER_RULES_FLAG}="$env{DM_UDEV_DISABLE_OTHER_RULES_FLAG}" --ENV{DM_NOSCAN}="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1" -+ENV{.DM_NOSCAN}="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1" - GOTO="dont_activate" - - LABEL="mpath_is_ready" -@@ -134,7 +134,7 @@ ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}!="1", GOTO="import_end" - ENV{DM_UDEV_RULES_VSN}!="1|2", GOTO="import_end" - - # Don't import the properties from db if we will run blkid later. --ENV{DM_NOSCAN}!="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}!="1", GOTO="import_end" -+ENV{.DM_NOSCAN}!="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}!="1", GOTO="import_end" - - IMPORT{db}="ID_FS_TYPE" - IMPORT{db}="ID_FS_USAGE" -@@ -150,6 +150,9 @@ LABEL="import_end" - # Reset previous DM_COLDPLUG_SUSPENDED if activation happens now - ENV{.DM_SUSPENDED}!="1", ENV{DM_ACTIVATION}=="1", ENV{DM_COLDPLUG_SUSPENDED}="" - -+# device-mapper rules v2 compatibility for 13-dm-disk.rules -+ENV{DM_UDEV_RULES_VSN}=="1|2", ENV{DM_NOSCAN}="$env{.DM_NOSCAN}" -+ - # Multipath maps should take precedence over their members. - ENV{DM_UDEV_LOW_PRIORITY_FLAG}!="1", OPTIONS+="link_priority=50" - diff --git a/0015-11-dm-mpath.rules-simplify-PATH_FAILED-case.patch b/0015-11-dm-mpath.rules-simplify-PATH_FAILED-case.patch deleted file mode 100644 index ce393ae..0000000 --- a/0015-11-dm-mpath.rules-simplify-PATH_FAILED-case.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Wed, 6 Mar 2024 21:17:51 +0100 -Subject: [PATCH] 11-dm-mpath.rules: simplify PATH_FAILED case - -This combination of a GOTO and a simple rule can be combined -into a single rule. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - multipath/11-dm-mpath.rules.in | 12 ++++-------- - 1 file changed, 4 insertions(+), 8 deletions(-) - -diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in -index 3ae3c054..4777fbec 100644 ---- a/multipath/11-dm-mpath.rules.in -+++ b/multipath/11-dm-mpath.rules.in -@@ -56,14 +56,10 @@ PROGRAM=="@BINDIR@/multipath -U -v1 %k", GOTO="paths_ok" - ENV{MPATH_DEVICE_READY}="0", GOTO="mpath_action" - LABEL="paths_ok" - --# Don't mark a device ready on a PATH_FAILED event. even if --# DM_NR_VALID_PATHS is greater than 0. Just keep the existing --# value --ENV{DM_ACTION}=="PATH_FAILED", GOTO="mpath_action" -- --# This event is either a PATH_REINSTATED or a table reload where --# there are active paths. Mark the device ready --ENV{MPATH_DEVICE_READY}="1" -+# For PATH_FAILED events, keep the existing value of MPATH_DEVICE_READY. -+# If it's not PATH_FAILED, this event is either a PATH_REINSTATED or a -+# table reload where there are active paths. Mark the device ready. -+ENV{DM_ACTION}!="PATH_FAILED", ENV{MPATH_DEVICE_READY}="1" - - LABEL="mpath_action" - diff --git a/0016-11-dm-mpath.rules-make-label-names-more-intuitive.patch b/0016-11-dm-mpath.rules-make-label-names-more-intuitive.patch deleted file mode 100644 index e81f04f..0000000 --- a/0016-11-dm-mpath.rules-make-label-names-more-intuitive.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 1 Mar 2024 21:54:26 +0100 -Subject: [PATCH] 11-dm-mpath.rules: make label names more intuitive - -The labels "dont_activate" and "scan_import" denote the same code line. -Remove "dont_activate". Improve two misleading label names. - -Substitutions: - dont_activate -> scan_import - force_activation -> check_mpath_ready - mpath_action -> check_mpath_unchanged - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - multipath/11-dm-mpath.rules.in | 22 +++++++++++----------- - 1 file changed, 11 insertions(+), 11 deletions(-) - -diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in -index 4777fbec..0562eddf 100644 ---- a/multipath/11-dm-mpath.rules.in -+++ b/multipath/11-dm-mpath.rules.in -@@ -30,7 +30,7 @@ LABEL="mpath_coldplug_end" - # device below at mpath_is_ready, which is correct. - ENV{DM_COOKIE}!="?*", ENV{DM_ACTION}!="PATH_*", \ - IMPORT{db}="DM_COLDPLUG_SUSPENDED", \ -- GOTO="force_activation" -+ GOTO="check_mpath_ready" - - ENV{.MPATH_DEVICE_READY_OLD}="$env{MPATH_DEVICE_READY}" - -@@ -38,13 +38,13 @@ ENV{.MPATH_DEVICE_READY_OLD}="$env{MPATH_DEVICE_READY}" - # table with no active devices. If this happens, mark the - # device not ready - ENV{DM_SUBSYSTEM_UDEV_FLAG2}=="1", ENV{MPATH_DEVICE_READY}="0", \ -- GOTO="mpath_action" -+ GOTO="check_mpath_unchanged" - - # If the last path has failed mark the device not ready - # Note that DM_NR_VALID_PATHS is only set for PATH_FAILED|PATH_REINSTATED - # events. - # This may not be reliable, as events aren't necessarily received in order. --ENV{DM_NR_VALID_PATHS}=="0", ENV{MPATH_DEVICE_READY}="0", GOTO="mpath_action" -+ENV{DM_NR_VALID_PATHS}=="0", ENV{MPATH_DEVICE_READY}="0", GOTO="check_mpath_unchanged" - - # Don't run multipath -U during "coldplug" after switching root, - # because paths are just being added to the udev db. -@@ -53,7 +53,8 @@ ACTION=="add", ENV{.MPATH_DEVICE_READY_OLD}=="1", GOTO="paths_ok" - # Check the map state directly with multipath -U. - # This doesn't attempt I/O on the device. - PROGRAM=="@BINDIR@/multipath -U -v1 %k", GOTO="paths_ok" --ENV{MPATH_DEVICE_READY}="0", GOTO="mpath_action" -+ENV{MPATH_DEVICE_READY}="0", GOTO="check_mpath_unchanged" -+ - LABEL="paths_ok" - - # For PATH_FAILED events, keep the existing value of MPATH_DEVICE_READY. -@@ -61,7 +62,7 @@ LABEL="paths_ok" - # table reload where there are active paths. Mark the device ready. - ENV{DM_ACTION}!="PATH_FAILED", ENV{MPATH_DEVICE_READY}="1" - --LABEL="mpath_action" -+LABEL="check_mpath_unchanged" - - # A previous coldplug event occurred while the device was suspended. - # Activation might have been partially skipped. Activate the device now, -@@ -70,7 +71,7 @@ IMPORT{db}="DM_COLDPLUG_SUSPENDED" - ENV{DM_COLDPLUG_SUSPENDED}=="1", ENV{.DM_SUSPENDED}!="1", \ - ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0", \ - PROGRAM="/bin/logger -t 11-dm-mpath.rules -p daemon.notice \"Forcing activation of previously suspended device\"", \ -- GOTO="force_activation" -+ GOTO="check_mpath_ready" - - # DM_SUBSYSTEM_UDEV_FLAG0 is the "RELOAD" flag for multipath subsystem. - # Drop the DM_ACTIVATION flag here as mpath reloads tables if any of its -@@ -86,7 +87,7 @@ ENV{DM_SUBSYSTEM_UDEV_FLAG0}=="1", \ - ENV{DM_ACTION}=="PATH_FAILED|PATH_REINSTATED", \ - ENV{DM_ACTIVATION}="0", ENV{MPATH_UNCHANGED}="1" - --LABEL="force_activation" -+LABEL="check_mpath_ready" - - ENV{MPATH_DEVICE_READY}!="0", GOTO="mpath_is_ready" - # Do not initiate scanning if no path is available, -@@ -100,7 +101,7 @@ ENV{MPATH_DEVICE_READY}!="0", GOTO="mpath_is_ready" - ENV{DM_UDEV_RULES_VSN}=="1|2", \ - ENV{.MPATH_SAVE_DISABLE_OTHER_RULES_FLAG}="$env{DM_UDEV_DISABLE_OTHER_RULES_FLAG}" - ENV{.DM_NOSCAN}="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1" --GOTO="dont_activate" -+GOTO="scan_import" - - LABEL="mpath_is_ready" - -@@ -109,11 +110,10 @@ LABEL="mpath_is_ready" - # we have to postpone the activation until the next event. - # In this case, we have to set MPATH_DEVICE_READY=0; otherwise, the - # MPATH_UNCHANGED logic will cause later rules to skipped in the next event. --ENV{.MPATH_DEVICE_READY_OLD}!="0", GOTO="dont_activate" --ENV{.DM_SUSPENDED}=="1", ENV{MPATH_DEVICE_READY}="0", GOTO="dont_activate" -+ENV{.MPATH_DEVICE_READY_OLD}!="0", GOTO="scan_import" -+ENV{.DM_SUSPENDED}=="1", ENV{MPATH_DEVICE_READY}="0", GOTO="scan_import" - - ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0" --LABEL="dont_activate" - - # The code to check multipath state ends here. We need to set - # properties and symlinks regardless whether the map is usable or diff --git a/0017-kpartx.rules-ignore-DM_SUSPENDED.patch b/0017-kpartx.rules-ignore-DM_SUSPENDED.patch deleted file mode 100644 index 3b0ac76..0000000 --- a/0017-kpartx.rules-ignore-DM_SUSPENDED.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 1 Mar 2024 21:17:26 +0100 -Subject: [PATCH] kpartx.rules: ignore DM_SUSPENDED - -DM_SUSPENDED=1 implies DM_UDEV_DISABLE_OTHER_RULES_FLAG=1, no -need to check it again. The DM_NOSCAN check needs to remain in -order to keep compatibility with dm rules v2. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - kpartx/kpartx.rules | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules -index 1969dee0..8dd3369c 100644 ---- a/kpartx/kpartx.rules -+++ b/kpartx/kpartx.rules -@@ -27,7 +27,7 @@ ENV{DM_SUBSYSTEM_UDEV_FLAG1}=="1", GOTO="mpath_kpartx_end" - ENV{MPATH_UNCHANGED}=="1", GOTO="mpath_kpartx_end" - - # Don't run kpartx now if we know it will fail or hang. --ENV{DM_SUSPENDED}=="1", GOTO="mpath_kpartx_end" -+# This is required for device mapper rules v2 compatibility. - ENV{DM_NOSCAN}=="1", GOTO="mpath_kpartx_end" - - # Run kpartx diff --git a/0018-multipath-tools-tests-fix-CI-failures-on-arm-v7-with.patch b/0018-multipath-tools-tests-fix-CI-failures-on-arm-v7-with.patch deleted file mode 100644 index 2840cec..0000000 --- a/0018-multipath-tools-tests-fix-CI-failures-on-arm-v7-with.patch +++ /dev/null @@ -1,270 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 4 Apr 2024 23:23:28 +0200 -Subject: [PATCH] multipath-tools tests: fix CI failures on arm/v7 with glibc - 2.37 - -glibc 2.37 has added several new wrappers around the ioctl and -io_getevents system calls on 32 bit systems, to deal with 64bit -time_t. These aren't resolved with cmocka's wrapping technique. - -Fix this with C preprocessor trickery, similar to -7b217f8 ("multipath-tools: Makefile.inc: set _FILE_OFFSET_BITS=64"). - -Note: the directio test with DIO_TEST_DEV for fails under qemu-linux-user -with foreign-arch binfmt, because aio-related system calls are unsupported -by qemu-linux-user. See https://gitlab.com/qemu-project/qemu/-/issues/210. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - tests/directio.c | 28 ++++++++++++++-------------- - tests/vpd.c | 35 ++++++++++++++++++----------------- - tests/wrap64.h | 25 ++++++++++++++++++++++++- - 3 files changed, 56 insertions(+), 32 deletions(-) - -diff --git a/tests/directio.c b/tests/directio.c -index cbedcc9c..d5f84f10 100644 ---- a/tests/directio.c -+++ b/tests/directio.c -@@ -41,13 +41,13 @@ struct timespec full_timeout = { .tv_sec = -1 }; - #define ioctl_request_t int - #endif - --int __real_ioctl(int fd, ioctl_request_t request, void *argp); -+int REAL_IOCTL(int fd, ioctl_request_t request, void *argp); - --int __wrap_ioctl(int fd, ioctl_request_t request, void *argp) -+int WRAP_IOCTL(int fd, ioctl_request_t request, void *argp) - { - #ifdef DIO_TEST_DEV - mock_type(int); -- return __real_ioctl(fd, request, argp); -+ return REAL_IOCTL(fd, request, argp); - #else - int *blocksize = (int *)argp; - -@@ -148,10 +148,10 @@ int __wrap_io_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt) - #endif - } - --int __real_io_getevents(io_context_t ctx, long min_nr, long nr, -+int REAL_IO_GETEVENTS(io_context_t ctx, long min_nr, long nr, - struct io_event *events, struct timespec *timeout); - --int __wrap_io_getevents(io_context_t ctx, long min_nr, long nr, -+int WRAP_IO_GETEVENTS(io_context_t ctx, long min_nr, long nr, - struct io_event *events, struct timespec *timeout) - { - int nr_evs; -@@ -169,8 +169,8 @@ int __wrap_io_getevents(io_context_t ctx, long min_nr, long nr, - #ifdef DIO_TEST_DEV - mock_ptr_type(struct timespec *); - mock_ptr_type(struct io_event *); -- assert_int_equal(nr_evs, __real_io_getevents(ctx, min_nr, nr_evs, -- events, timeout)); -+ assert_int_equal(nr_evs, REAL_IO_GETEVENTS(ctx, min_nr, nr_evs, -+ events, timeout)); - #else - sleep_tmo = mock_ptr_type(struct timespec *); - if (sleep_tmo) { -@@ -193,7 +193,7 @@ int __wrap_io_getevents(io_context_t ctx, long min_nr, long nr, - - static void return_io_getevents_none(void) - { -- will_return(__wrap_io_getevents, 0); -+ wrap_will_return(WRAP_IO_GETEVENTS, 0); - } - - static void return_io_getevents_nr(struct timespec *ts, int nr, -@@ -207,15 +207,15 @@ static void return_io_getevents_nr(struct timespec *ts, int nr, - mock_events[i + ev_off].res = reqs[i]->blksize; - } - while (nr > 0) { -- will_return(__wrap_io_getevents, (nr > 128)? 128 : nr); -- will_return(__wrap_io_getevents, ts); -- will_return(__wrap_io_getevents, &mock_events[off + ev_off]); -+ wrap_will_return(WRAP_IO_GETEVENTS, (nr > 128)? 128 : nr); -+ wrap_will_return(WRAP_IO_GETEVENTS, ts); -+ wrap_will_return(WRAP_IO_GETEVENTS, &mock_events[off + ev_off]); - ts = NULL; - off += 128; - nr -= 128; - } - if (nr == 0) -- will_return(__wrap_io_getevents, 0); -+ wrap_will_return(WRAP_IO_GETEVENTS, 0); - ev_off += i; - } - -@@ -251,7 +251,7 @@ static void do_libcheck_init(struct checker *c, int blocksize, - struct directio_context * ct; - - c->fd = test_fd; -- will_return(__wrap_ioctl, blocksize); -+ wrap_will_return(WRAP_IOCTL, blocksize); - assert_int_equal(libcheck_init(c), 0); - ct = (struct directio_context *)c->context; - assert_non_null(ct); -@@ -762,7 +762,7 @@ int main(void) - { - int ret = 0; - -- init_test_verbosity(2); -+ init_test_verbosity(5); - ret += test_directio(); - return ret; - } -diff --git a/tests/vpd.c b/tests/vpd.c -index 1b2d62d6..e3212e61 100644 ---- a/tests/vpd.c -+++ b/tests/vpd.c -@@ -20,6 +20,7 @@ - #include "vector.h" - #include "structs.h" - #include "discovery.h" -+#include "wrap64.h" - #include "globals.c" - - #define VPD_BUFSIZ 4096 -@@ -58,7 +59,7 @@ static const char vendor_id[] = "Linux"; - static const char test_id[] = - "A123456789AbcDefB123456789AbcDefC123456789AbcDefD123456789AbcDef"; - --int __wrap_ioctl(int fd, unsigned long request, void *param) -+int WRAP_IOCTL(int fd, unsigned long request, void *param) - { - int len; - struct sg_io_hdr *io_hdr; -@@ -428,8 +429,8 @@ static void test_vpd_vnd_ ## len ## _ ## wlen(void **state) \ - /* Replace spaces, like code under test */ \ - exp_subst = subst_spaces(exp_wwid); \ - free(exp_wwid); \ -- will_return(__wrap_ioctl, n); \ -- will_return(__wrap_ioctl, vt->vpdbuf); \ -+ wrap_will_return(WRAP_IOCTL, n); \ -+ wrap_will_return(WRAP_IOCTL, vt->vpdbuf); \ - ret = get_vpd_sgio(10, 0x83, 0, vt->wwid, wlen); \ - assert_correct_wwid("test_vpd_vnd_" #len "_" #wlen, \ - exp_len, ret, '1', 0, false, \ -@@ -458,8 +459,8 @@ static void test_vpd_str_ ## typ ## _ ## len ## _ ## wlen(void **state) \ - exp_len--; \ - if (exp_len >= wlen) \ - exp_len = wlen - 1; \ -- will_return(__wrap_ioctl, n); \ -- will_return(__wrap_ioctl, vt->vpdbuf); \ -+ wrap_will_return(WRAP_IOCTL, n); \ -+ wrap_will_return(WRAP_IOCTL, vt->vpdbuf); \ - ret = get_vpd_sgio(10, 0x83, 0, vt->wwid, wlen); \ - assert_correct_wwid("test_vpd_str_" #typ "_" #len "_" #wlen, \ - exp_len, ret, byte0[type], 0, \ -@@ -495,8 +496,8 @@ static void test_vpd_naa_ ## naa ## _ ## wlen(void **state) \ - \ - n = create_vpd83(vt->vpdbuf, sizeof(vt->vpdbuf), test_id, \ - 3, naa, 0); \ -- will_return(__wrap_ioctl, n); \ -- will_return(__wrap_ioctl, vt->vpdbuf); \ -+ wrap_will_return(WRAP_IOCTL, n); \ -+ wrap_will_return(WRAP_IOCTL, vt->vpdbuf); \ - ret = get_vpd_sgio(10, 0x83, 0, vt->wwid, wlen); \ - assert_correct_wwid("test_vpd_naa_" #naa "_" #wlen, \ - exp_len, ret, '3', '0' + naa, true, \ -@@ -518,8 +519,8 @@ static void test_vpd_naa_##NAA##_badlen_##BAD(void **state) \ - n = create_vpd83(vt->vpdbuf, sizeof(vt->vpdbuf), test_id, 3, NAA, 0); \ - \ - vt->vpdbuf[7] = BAD; \ -- will_return(__wrap_ioctl, n); \ -- will_return(__wrap_ioctl, vt->vpdbuf); \ -+ wrap_will_return(WRAP_IOCTL, n); \ -+ wrap_will_return(WRAP_IOCTL, vt->vpdbuf); \ - ret = get_vpd_sgio(10, 0x83, 0, vt->wwid, 40); \ - assert_int_equal(-ret, -ERR); \ - } -@@ -545,11 +546,11 @@ static void test_vpd_eui_ ## len ## _ ## wlen ## _ ## sml(void **state) \ - /* overwrite the page size to DEFAULT_SGIO_LEN + 1 */ \ - put_unaligned_be16(255, vt->vpdbuf + 2); \ - /* this causes get_vpd_sgio to do a second ioctl */ \ -- will_return(__wrap_ioctl, n); \ -- will_return(__wrap_ioctl, vt->vpdbuf); \ -+ wrap_will_return(WRAP_IOCTL, n); \ -+ wrap_will_return(WRAP_IOCTL, vt->vpdbuf); \ - } \ -- will_return(__wrap_ioctl, n); \ -- will_return(__wrap_ioctl, vt->vpdbuf); \ -+ wrap_will_return(WRAP_IOCTL, n); \ -+ wrap_will_return(WRAP_IOCTL, vt->vpdbuf); \ - ret = get_vpd_sgio(10, 0x83, 0, vt->wwid, wlen); \ - assert_correct_wwid("test_vpd_eui_" #len "_" #wlen "_" #sml, \ - exp_len, ret, '2', 0, true, \ -@@ -571,8 +572,8 @@ static void test_vpd_eui_badlen_##LEN##_##BAD(void **state) \ - n = create_vpd83(vt->vpdbuf, sizeof(vt->vpdbuf), test_id, 2, 0, LEN); \ - \ - vt->vpdbuf[7] = BAD; \ -- will_return(__wrap_ioctl, n); \ -- will_return(__wrap_ioctl, vt->vpdbuf); \ -+ wrap_will_return(WRAP_IOCTL, n); \ -+ wrap_will_return(WRAP_IOCTL, vt->vpdbuf); \ - ret = get_vpd_sgio(10, 0x83, 0, vt->wwid, 40); \ - assert_int_equal(ret, ERR); \ - if (ERR >= 0) \ -@@ -600,8 +601,8 @@ static void test_vpd80_ ## size ## _ ## len ## _ ## wlen(void **state) \ - exp_len = wlen - 1; \ - n = create_vpd80(vt->vpdbuf, sizeof(vt->vpdbuf), input, \ - size, len); \ -- will_return(__wrap_ioctl, n); \ -- will_return(__wrap_ioctl, vt->vpdbuf); \ -+ wrap_will_return(WRAP_IOCTL, n); \ -+ wrap_will_return(WRAP_IOCTL, vt->vpdbuf); \ - ret = get_vpd_sgio(10, 0x80, 0, vt->wwid, wlen); \ - assert_correct_wwid("test_vpd80_" #size "_" #len "_" #wlen, \ - exp_len, ret, 0, 0, false, \ -diff --git a/tests/wrap64.h b/tests/wrap64.h -index 8c91d279..b0a4d831 100644 ---- a/tests/wrap64.h -+++ b/tests/wrap64.h -@@ -1,5 +1,7 @@ - #ifndef _WRAP64_H - #define _WRAP64_H 1 -+#include -+#include - #include "util.h" - - /* -@@ -31,7 +33,9 @@ - * fcntl() needs special treatment; fcntl64() has been introduced in 2.28. - * https://savannah.gnu.org/forum/forum.php?forum_id=9205 - */ --#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 28) -+#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 37) && defined(__arm__) && __ARM_ARCH == 7 -+#define WRAP_FCNTL_NAME __fcntl_time64 -+#elif defined(__GLIBC__) && __GLIBC_PREREQ(2, 28) - #define WRAP_FCNTL_NAME WRAP_NAME(fcntl) - #else - #define WRAP_FCNTL_NAME fcntl -@@ -39,6 +43,25 @@ - #define WRAP_FCNTL CONCAT2(__wrap_, WRAP_FCNTL_NAME) - #define REAL_FCNTL CONCAT2(__real_, WRAP_FCNTL_NAME) - -+/* -+ * glibc 2.37 uses __ioctl_time64 for ioctl -+ */ -+#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 37) && defined(__arm__) && __ARM_ARCH == 7 -+#define WRAP_IOCTL_NAME __ioctl_time64 -+#else -+#define WRAP_IOCTL_NAME ioctl -+#endif -+#define WRAP_IOCTL CONCAT2(__wrap_, WRAP_IOCTL_NAME) -+#define REAL_IOCTL CONCAT2(__real_, WRAP_IOCTL_NAME) -+ -+#if defined(__NR_io_pgetevents) && __BITS_PER_LONG == 32 && defined(_TIME_BITS) && _TIME_BITS == 64 -+#define WRAP_IO_GETEVENTS_NAME io_getevents_time64 -+#else -+#define WRAP_IO_GETEVENTS_NAME io_getevents -+#endif -+#define WRAP_IO_GETEVENTS CONCAT2(__wrap_, WRAP_IO_GETEVENTS_NAME) -+#define REAL_IO_GETEVENTS CONCAT2(__real_, WRAP_IO_GETEVENTS_NAME) -+ - /* - * will_return() is itself a macro that uses CPP "stringizing". We need a - * macro indirection to make sure the *value* of WRAP_FUNC() is stringized diff --git a/0019-multipath-tools-tests-fix-CI-failures-with-clang-on-.patch b/0019-multipath-tools-tests-fix-CI-failures-with-clang-on-.patch deleted file mode 100644 index d1dedac..0000000 --- a/0019-multipath-tools-tests-fix-CI-failures-with-clang-on-.patch +++ /dev/null @@ -1,246 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 5 Apr 2024 22:21:43 +0200 -Subject: [PATCH] multipath-tools tests: fix CI failures with clang on Fedora - Rawhide - -Fedora's glibc 2.39 includes the following patch: - -https://patches.linaro.org/project/libc-alpha/patch/20240208184622.332678-10-adhemerval.zanella@linaro.org/ - -It causes open("file", O_RDONLY) to resolve to __open64_2(), -whereas it resolves to open64() with gcc, causing CI failures because of -wrong wrapper substitutions. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - tests/dmevents.c | 6 ++--- - tests/sysfs.c | 58 ++++++++++++++++++++++++------------------------ - tests/test-lib.c | 6 ++--- - tests/wrap64.h | 14 ++++++++++++ - 4 files changed, 49 insertions(+), 35 deletions(-) - -diff --git a/tests/dmevents.c b/tests/dmevents.c -index 540bf0d3..395b16d7 100644 ---- a/tests/dmevents.c -+++ b/tests/dmevents.c -@@ -207,7 +207,7 @@ static int teardown(void **state) - return 0; - } - --int WRAP_FUNC(open)(const char *pathname, int flags) -+int WRAP_OPEN(const char *pathname, int flags) - { - assert_ptr_equal(pathname, "/dev/mapper/control"); - assert_int_equal(flags, O_RDWR); -@@ -389,7 +389,7 @@ static void test_init_waiter_bad1(void **state) - struct test_data *datap = (struct test_data *)(*state); - if (datap == NULL) - skip(); -- wrap_will_return(WRAP_FUNC(open), -1); -+ wrap_will_return(WRAP_OPEN, -1); - assert_int_equal(init_dmevent_waiter(&datap->vecs), -1); - assert_ptr_equal(waiter, NULL); - } -@@ -400,7 +400,7 @@ static void test_init_waiter_good0(void **state) - struct test_data *datap = (struct test_data *)(*state); - if (datap == NULL) - skip(); -- wrap_will_return(WRAP_FUNC(open), 2); -+ wrap_will_return(WRAP_OPEN, 2); - assert_int_equal(init_dmevent_waiter(&datap->vecs), 0); - assert_ptr_not_equal(waiter, NULL); - } -diff --git a/tests/sysfs.c b/tests/sysfs.c -index fc256d87..c623d1bb 100644 ---- a/tests/sysfs.c -+++ b/tests/sysfs.c -@@ -29,7 +29,7 @@ char *__wrap_udev_device_get_syspath(struct udev_device *ud) - return val; - } - --int WRAP_FUNC(open)(const char *pathname, int flags) -+int WRAP_OPEN(const char *pathname, int flags) - { - int ret; - -@@ -167,10 +167,10 @@ static void test_sagv_open_fail(void **state) - - will_return(__wrap_udev_device_get_syspath, "/foo"); - expect_condlog(4, "open '/foo/bar'"); -- expect_string(WRAP_FUNC(open), pathname, "/foo/bar"); -- expect_value(WRAP_FUNC(open), flags, O_RDONLY); -+ expect_string(WRAP_OPEN, pathname, "/foo/bar"); -+ expect_value(WRAP_OPEN, flags, O_RDONLY); - errno = ENOENT; -- wrap_will_return(WRAP_FUNC(open), -1); -+ wrap_will_return(WRAP_OPEN, -1); - expect_condlog(3, "__sysfs_attr_get_value: attribute '/foo/bar' cannot be opened"); - assert_int_equal(sysfs_attr_get_value((void *)state, "bar", - buf, sizeof(buf)), -ENOENT); -@@ -182,9 +182,9 @@ static void test_sagv_read_fail(void **state) - - will_return(__wrap_udev_device_get_syspath, "/foo"); - expect_condlog(4, "open '/foo/bar'"); -- expect_string(WRAP_FUNC(open), pathname, "/foo/bar"); -- expect_value(WRAP_FUNC(open), flags, O_RDONLY); -- wrap_will_return(WRAP_FUNC(open), TEST_FD); -+ expect_string(WRAP_OPEN, pathname, "/foo/bar"); -+ expect_value(WRAP_OPEN, flags, O_RDONLY); -+ wrap_will_return(WRAP_OPEN, TEST_FD); - expect_value(__wrap_read, fd, TEST_FD); - expect_value(__wrap_read, count, sizeof(buf)); - errno = EISDIR; -@@ -197,9 +197,9 @@ static void test_sagv_read_fail(void **state) - - will_return(__wrap_udev_device_get_syspath, "/foo"); - expect_condlog(4, "open '/foo/baz'"); -- expect_string(WRAP_FUNC(open), pathname, "/foo/baz"); -- expect_value(WRAP_FUNC(open), flags, O_RDONLY); -- wrap_will_return(WRAP_FUNC(open), TEST_FD); -+ expect_string(WRAP_OPEN, pathname, "/foo/baz"); -+ expect_value(WRAP_OPEN, flags, O_RDONLY); -+ wrap_will_return(WRAP_OPEN, TEST_FD); - expect_value(__wrap_read, fd, TEST_FD); - expect_value(__wrap_read, count, sizeof(buf)); - errno = EPERM; -@@ -223,9 +223,9 @@ static void _test_sagv_read(void **state, unsigned int bufsz) - memset(buf, '.', sizeof(buf)); - will_return(__wrap_udev_device_get_syspath, "/foo"); - expect_condlog(4, "open '/foo/bar'"); -- expect_string(WRAP_FUNC(open), pathname, "/foo/bar"); -- expect_value(WRAP_FUNC(open), flags, O_RDONLY); -- wrap_will_return(WRAP_FUNC(open), TEST_FD); -+ expect_string(WRAP_OPEN, pathname, "/foo/bar"); -+ expect_value(WRAP_OPEN, flags, O_RDONLY); -+ wrap_will_return(WRAP_OPEN, TEST_FD); - expect_value(__wrap_read, fd, TEST_FD); - expect_value(__wrap_read, count, bufsz); - will_return(__wrap_read, sizeof(input) - 1); -@@ -250,9 +250,9 @@ static void _test_sagv_read(void **state, unsigned int bufsz) - memset(buf, '.', sizeof(buf)); - will_return(__wrap_udev_device_get_syspath, "/foo"); - expect_condlog(4, "open '/foo/baz'"); -- expect_string(WRAP_FUNC(open), pathname, "/foo/baz"); -- expect_value(WRAP_FUNC(open), flags, O_RDONLY); -- wrap_will_return(WRAP_FUNC(open), TEST_FD); -+ expect_string(WRAP_OPEN, pathname, "/foo/baz"); -+ expect_value(WRAP_OPEN, flags, O_RDONLY); -+ wrap_will_return(WRAP_OPEN, TEST_FD); - expect_value(__wrap_read, fd, TEST_FD); - expect_value(__wrap_read, count, bufsz); - will_return(__wrap_read, sizeof(input) - 1); -@@ -301,9 +301,9 @@ static void _test_sagv_read_zeroes(void **state, unsigned int bufsz) - memset(buf, '.', sizeof(buf)); - will_return(__wrap_udev_device_get_syspath, "/foo"); - expect_condlog(4, "open '/foo/bar'"); -- expect_string(WRAP_FUNC(open), pathname, "/foo/bar"); -- expect_value(WRAP_FUNC(open), flags, O_RDONLY); -- wrap_will_return(WRAP_FUNC(open), TEST_FD); -+ expect_string(WRAP_OPEN, pathname, "/foo/bar"); -+ expect_value(WRAP_OPEN, flags, O_RDONLY); -+ wrap_will_return(WRAP_OPEN, TEST_FD); - expect_value(__wrap_read, fd, TEST_FD); - expect_value(__wrap_read, count, bufsz); - will_return(__wrap_read, sizeof(input) - 1); -@@ -386,10 +386,10 @@ static void test_sasv_open_fail(void **state) - - will_return(__wrap_udev_device_get_syspath, "/foo"); - expect_condlog(4, "open '/foo/bar'"); -- expect_string(WRAP_FUNC(open), pathname, "/foo/bar"); -- expect_value(WRAP_FUNC(open), flags, O_WRONLY); -+ expect_string(WRAP_OPEN, pathname, "/foo/bar"); -+ expect_value(WRAP_OPEN, flags, O_WRONLY); - errno = EPERM; -- wrap_will_return(WRAP_FUNC(open), -1); -+ wrap_will_return(WRAP_OPEN, -1); - expect_condlog(3, "sysfs_attr_set_value: attribute '/foo/bar' cannot be opened"); - assert_int_equal(sysfs_attr_set_value((void *)state, "bar", - buf, sizeof(buf)), -EPERM); -@@ -401,9 +401,9 @@ static void test_sasv_write_fail(void **state) - - will_return(__wrap_udev_device_get_syspath, "/foo"); - expect_condlog(4, "open '/foo/bar'"); -- expect_string(WRAP_FUNC(open), pathname, "/foo/bar"); -- expect_value(WRAP_FUNC(open), flags, O_WRONLY); -- wrap_will_return(WRAP_FUNC(open), TEST_FD); -+ expect_string(WRAP_OPEN, pathname, "/foo/bar"); -+ expect_value(WRAP_OPEN, flags, O_WRONLY); -+ wrap_will_return(WRAP_OPEN, TEST_FD); - expect_value(__wrap_write, fd, TEST_FD); - expect_value(__wrap_write, count, sizeof(buf)); - errno = EISDIR; -@@ -422,9 +422,9 @@ static void _test_sasv_write(void **state, unsigned int n_written) - assert_in_range(n_written, 0, sizeof(buf)); - will_return(__wrap_udev_device_get_syspath, "/foo"); - expect_condlog(4, "open '/foo/bar'"); -- expect_string(WRAP_FUNC(open), pathname, "/foo/bar"); -- expect_value(WRAP_FUNC(open), flags, O_WRONLY); -- wrap_will_return(WRAP_FUNC(open), TEST_FD); -+ expect_string(WRAP_OPEN, pathname, "/foo/bar"); -+ expect_value(WRAP_OPEN, flags, O_WRONLY); -+ wrap_will_return(WRAP_OPEN, TEST_FD); - expect_value(__wrap_write, fd, TEST_FD); - expect_value(__wrap_write, count, sizeof(buf)); - will_return(__wrap_write, n_written); -@@ -489,7 +489,7 @@ int main(void) - { - int ret = 0; - -- init_test_verbosity(4); -+ init_test_verbosity(5); - ret += test_sysfs(); - return ret; - } -diff --git a/tests/test-lib.c b/tests/test-lib.c -index 665d438e..cdb2780d 100644 ---- a/tests/test-lib.c -+++ b/tests/test-lib.c -@@ -40,17 +40,17 @@ const char default_wwid_1[] = "TEST-WWID-1"; - */ - - --int REAL_FUNC(open)(const char *path, int flags, int mode); -+int REAL_OPEN(const char *path, int flags, int mode); - - static const char _mocked_filename[] = "mocked_path"; - --int WRAP_FUNC(open)(const char *path, int flags, int mode) -+int WRAP_OPEN(const char *path, int flags, int mode) - { - condlog(4, "%s: %s", __func__, path); - - if (!strcmp(path, _mocked_filename)) - return 111; -- return REAL_FUNC(open)(path, flags, mode); -+ return REAL_OPEN(path, flags, mode); - } - - int __wrap_libmp_get_version(int which, unsigned int version[3]) -diff --git a/tests/wrap64.h b/tests/wrap64.h -index b0a4d831..7e434206 100644 ---- a/tests/wrap64.h -+++ b/tests/wrap64.h -@@ -29,6 +29,20 @@ - #define WRAP_FUNC(x) CONCAT2(__wrap_, WRAP_NAME(x)) - #define REAL_FUNC(x) CONCAT2(__real_, WRAP_NAME(x)) - -+/* -+ * With clang, glibc 2.39, and _FILE_OFFSET_BITS==64, -+ * open() resolves to __open64_2(). -+ */ -+#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 39) && \ -+ defined(__clang__) && __clang__ == 1 && \ -+ defined(__fortify_use_clang) && __fortify_use_clang == 1 -+#define WRAP_OPEN_NAME __open64_2 -+#else -+#define WRAP_OPEN_NAME WRAP_NAME(open) -+#endif -+#define WRAP_OPEN CONCAT2(__wrap_, WRAP_OPEN_NAME) -+#define REAL_OPEN CONCAT2(__real_, WRAP_OPEN_NAME) -+ - /* - * fcntl() needs special treatment; fcntl64() has been introduced in 2.28. - * https://savannah.gnu.org/forum/forum.php?forum_id=9205 diff --git a/0020-GitHub-actions-fixes-for-spelling-CI.patch b/0020-GitHub-actions-fixes-for-spelling-CI.patch deleted file mode 100644 index 21b74ff..0000000 --- a/0020-GitHub-actions-fixes-for-spelling-CI.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 8 Mar 2024 10:04:39 +0100 -Subject: [PATCH] GitHub actions: fixes for spelling CI - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - .github/actions/spelling/patterns.txt | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/.github/actions/spelling/patterns.txt b/.github/actions/spelling/patterns.txt -index 57767ea1..858faee6 100644 ---- a/.github/actions/spelling/patterns.txt -+++ b/.github/actions/spelling/patterns.txt -@@ -22,6 +22,7 @@ - \bdmmp_pgs\b - \bdmmp_mpath_kdev_name_get\b - \bfast_io_fail_tmo\b -+\bLimitRTPRIO\b - \bmax_fds\b - \bmissing_uev_wait_timeout\b - \bMPATH_MAX_PARAM_LEN\b -@@ -86,6 +87,7 @@ - \bprin_resvdescr\b - \bprout_param_descriptor\b - \brq_servact\b -+\bSCHED_RT_PRIO\b - \bssize_t\b - \btrnptid_list\b - \buxsock_timeout\b diff --git a/0021-GitHub-workflows-run-workflows-if-workflow-file-has-.patch b/0021-GitHub-workflows-run-workflows-if-workflow-file-has-.patch deleted file mode 100644 index 59cdd0e..0000000 --- a/0021-GitHub-workflows-run-workflows-if-workflow-file-has-.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Tue, 27 Feb 2024 09:57:47 +0100 -Subject: [PATCH] GitHub workflows: run workflows if workflow file has changed - -We want to run workflows if the workflow file itself has changed. - -Fixes: 2cbe81a ("GitHub Workflows: run expensive workflows only on relevant changes") -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - .github/workflows/abi.yaml | 1 + - .github/workflows/foreign.yaml | 2 ++ - .github/workflows/multiarch-stable.yaml | 2 ++ - .github/workflows/multiarch.yaml | 2 ++ - .github/workflows/native.yaml | 2 ++ - .github/workflows/rolling.yaml | 2 ++ - .github/workflows/spelling.yml | 2 ++ - 7 files changed, 13 insertions(+) - -diff --git a/.github/workflows/abi.yaml b/.github/workflows/abi.yaml -index 53382420..393322e5 100644 ---- a/.github/workflows/abi.yaml -+++ b/.github/workflows/abi.yaml -@@ -5,6 +5,7 @@ on: - - queue - - abi - paths: -+ - '.github/workflows/abi.yaml' - - '**.h' - - '**.c' - pull_request: -diff --git a/.github/workflows/foreign.yaml b/.github/workflows/foreign.yaml -index 92f6d17a..a62ae009 100644 ---- a/.github/workflows/foreign.yaml -+++ b/.github/workflows/foreign.yaml -@@ -6,6 +6,7 @@ on: - - queue - - tip - paths: -+ - '.github/workflows/foreign.yaml' - - '**.h' - - '**.c' - - '**Makefile*' -@@ -15,6 +16,7 @@ on: - - master - - queue - paths: -+ - '.github/workflows/foreign.yaml' - - '**.h' - - '**.c' - - '**Makefile*' -diff --git a/.github/workflows/multiarch-stable.yaml b/.github/workflows/multiarch-stable.yaml -index 45b74c51..e51d383c 100644 ---- a/.github/workflows/multiarch-stable.yaml -+++ b/.github/workflows/multiarch-stable.yaml -@@ -6,6 +6,7 @@ on: - - queue - - tip - paths: -+ - '.github/workflows/multiarch-stable.yaml' - - '**.h' - - '**.c' - - '**Makefile*' -@@ -15,6 +16,7 @@ on: - - master - - queue - paths: -+ - '.github/workflows/multiarch-stable.yaml' - - '**.h' - - '**.c' - - '**Makefile*' -diff --git a/.github/workflows/multiarch.yaml b/.github/workflows/multiarch.yaml -index b4dec9c7..7b762e5c 100644 ---- a/.github/workflows/multiarch.yaml -+++ b/.github/workflows/multiarch.yaml -@@ -6,6 +6,7 @@ on: - - queue - - tip - paths: -+ - '.github/workflows/multiarch.yaml' - - '**.h' - - '**.c' - - '**Makefile*' -@@ -15,6 +16,7 @@ on: - - master - - queue - paths: -+ - '.github/workflows/multiarch.yaml' - - '**.h' - - '**.c' - - '**Makefile*' -diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml -index 09133c1e..0ef9df94 100644 ---- a/.github/workflows/native.yaml -+++ b/.github/workflows/native.yaml -@@ -6,6 +6,7 @@ on: - - queue - - tip - paths: -+ - '.github/workflows/native.yaml' - - '**.h' - - '**.c' - - '**Makefile*' -@@ -15,6 +16,7 @@ on: - - master - - queue - paths: -+ - '.github/workflows/native.yaml' - - '**.h' - - '**.c' - - '**Makefile*' -diff --git a/.github/workflows/rolling.yaml b/.github/workflows/rolling.yaml -index 1f1507ee..3536b944 100644 ---- a/.github/workflows/rolling.yaml -+++ b/.github/workflows/rolling.yaml -@@ -6,6 +6,7 @@ on: - - queue - - tip - paths: -+ - '.github/workflows/rolling.yaml' - - '**.h' - - '**.c' - - '**Makefile*' -@@ -15,6 +16,7 @@ on: - - master - - queue - paths: -+ - '.github/workflows/rolling.yaml' - - '**.h' - - '**.c' - - '**Makefile*' -diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml -index 0416fa9e..7943ebb8 100644 ---- a/.github/workflows/spelling.yml -+++ b/.github/workflows/spelling.yml -@@ -63,7 +63,9 @@ on: - tags-ignore: - - "**" - paths: -+ - '.github/workflows/spelling.yml' - - 'README*' -+ - 'NEWS.md' - - '**.3' - - '**.5' - - '**.8' diff --git a/0022-multipath-tools-add-TGTDIR-option.patch b/0022-multipath-tools-add-TGTDIR-option.patch deleted file mode 100644 index d26fb18..0000000 --- a/0022-multipath-tools-add-TGTDIR-option.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Wed, 17 Apr 2024 14:44:45 +0200 -Subject: [PATCH] multipath-tools: add TGTDIR option - -TGTDIR is a convenience option for developers for building multipath-tools such -that compiled-in paths of the plugins, config files, etc. match an -installation under some optional path. See README.md for instructions and -examples. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - .github/actions/spelling/expect.txt | 2 ++ - Makefile.inc | 8 +++---- - README.md | 33 +++++++++++++++++++++++++++++ - 3 files changed, 39 insertions(+), 4 deletions(-) - -diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt -index 5906403d..fc9f22f8 100644 ---- a/.github/actions/spelling/expect.txt -+++ b/.github/actions/spelling/expect.txt -@@ -167,6 +167,7 @@ retrigger - rhabarber - rootprefix - rootprefixdir -+rpmbuild - rport - rtpi - sas -@@ -200,6 +201,7 @@ tcp - TESTDEPS - testname - tgill -+TGTDIR - TIDS - tmo - tpg -diff --git a/Makefile.inc b/Makefile.inc -index 5668e638..81b86cd8 100644 ---- a/Makefile.inc -+++ b/Makefile.inc -@@ -101,9 +101,9 @@ WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implici - $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) - CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \ - -D_FILE_OFFSET_BITS=64 \ -- -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \ -- -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \ -- -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DSTATE_DIR=\"$(statedir)\" \ -+ -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(TGTDIR)$(plugindir)\" \ -+ -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(TGTDIR)$(configdir)\" \ -+ -DDEFAULT_CONFIGFILE=\"$(TGTDIR)$(configfile)\" -DSTATE_DIR=\"$(TGTDIR)$(statedir)\" \ - -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP - CFLAGS := -std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe - BIN_CFLAGS := -fPIE -DPIE -@@ -149,4 +149,4 @@ NV_VERSION_SCRIPT = $(DEVLIB:%.so=%-nv.version) - - %: %.in - @echo creating $@ -- $(Q)sed 's:@CONFIGFILE@:'$(configfile)':g;s:@CONFIGDIR@:'$(configdir)':g;s:@STATE_DIR@:'$(statedir)':g;s:@RUNTIME_DIR@:'$(runtimedir)':g;s/@MODPROBE_UNIT@/'$(MODPROBE_UNIT)'/g;s:@BINDIR@:'$(bindir)':g' $< >$@ -+ $(Q)sed 's:@CONFIGFILE@:'$(TGTDIR)$(configfile)':g;s:@CONFIGDIR@:'$(TGTDIR)$(configdir)':g;s:@STATE_DIR@:'$(TGTDIR)$(statedir)':g;s:@RUNTIME_DIR@:'$(runtimedir)':g;s/@MODPROBE_UNIT@/'$(MODPROBE_UNIT)'/g;s:@BINDIR@:'$(bindir)':g' $< >$@ -diff --git a/README.md b/README.md -index d4f35f57..7207b14c 100644 ---- a/README.md -+++ b/README.md -@@ -151,6 +151,39 @@ sufficient control. See `Makefile.inc` for even more fine-grained control. - On such distributions, override `unitdir` and `libudevdir` to use systemd's - `rootprefix`: `make libudevdir=/lib/udev unitdir=/lib/systemd/system` - -+### prefix, DESTDIR and TGTDIR -+ -+`prefix` and related variables are included in compiled-in paths like -+`plugindir` and are used by `make install`. Using `prefix` is useful if -+multipath-tools is built locally on the same host where it's supposed to be -+installed. -+ -+By convention, the `DESTDIR` variable is prepended to all paths by `make -+install`, but not to any compiled-in paths. -+It is useful if the software is built on one system (build host) but intended -+to be run on another system (installation host). This is typically used in build -+systems like *rpmbuild* to set a root directory for all the installed -+files. -+ -+On the contrary, the `TGTDIR` variable is used for compiled-in paths only, and -+ignored by `make install`. It is useful for running multipath-tools in a separate -+subdirectory in the installation host, mostly for testing / development -+purposes. -+ -+For example, -+ -+ make prefix=/opt DESTDIR=/build TGTDIR=/test install -+ -+will install plugins into `/build/opt/lib64/multipath` on the build -+host. On the installation host, the plugins will be expected to be found under -+`/test/opt/lib64/multipath`. If the developer runs -+ -+ rsync -a $BUILD_HOST:$DESTDIR/ $INSTALL_HOST:$TGTDIR/ -+ -+and adds `$TGTDIR/lib64` to `LD_LIBRARY_PATH` on the installation host, the -+multipath binaries installed under `$TGTDIR` will find their plugins and -+configuration files in the expected compiled-in paths. -+ - ### Compiler Options - - Use `OPTFLAGS` to change optimization-related compiler options; diff --git a/0023-libmultipath-move-get_udev_for_mpp-to-sysfs.c.patch b/0023-libmultipath-move-get_udev_for_mpp-to-sysfs.c.patch deleted file mode 100644 index b59f879..0000000 --- a/0023-libmultipath-move-get_udev_for_mpp-to-sysfs.c.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Wed, 17 Apr 2024 17:18:18 +0200 -Subject: [PATCH] libmultipath: move get_udev_for_mpp to sysfs.c - -No functional changes, just code movement. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/configure.c | 20 -------------------- - libmultipath/sysfs.c | 19 +++++++++++++++++++ - libmultipath/sysfs.h | 4 ++++ - 3 files changed, 23 insertions(+), 20 deletions(-) - -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index 4ecf6ba4..89ac03d5 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -453,26 +453,6 @@ pgcmp (struct multipath * mpp, struct multipath * cmpp) - return r; - } - --static struct udev_device * --get_udev_for_mpp(const struct multipath *mpp) --{ -- dev_t devnum; -- struct udev_device *udd; -- -- if (!mpp || !has_dm_info(mpp)) { -- condlog(1, "%s called with empty mpp", __func__); -- return NULL; -- } -- -- devnum = makedev(mpp->dmi.major, mpp->dmi.minor); -- udd = udev_device_new_from_devnum(udev, 'b', devnum); -- if (!udd) { -- condlog(1, "failed to get udev device for %s", mpp->alias); -- return NULL; -- } -- return udd; --} -- - void trigger_partitions_udev_change(struct udev_device *dev, - const char *action, int len) - { -diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c -index 328951ed..afe9de91 100644 ---- a/libmultipath/sysfs.c -+++ b/libmultipath/sysfs.c -@@ -339,3 +339,22 @@ bool sysfs_is_multipathed(struct path *pp, bool set_wwid) - - return found; - } -+ -+struct udev_device *get_udev_for_mpp(const struct multipath *mpp) -+{ -+ dev_t devnum; -+ struct udev_device *udd; -+ -+ if (!mpp || !has_dm_info(mpp)) { -+ condlog(1, "%s called with empty mpp", __func__); -+ return NULL; -+ } -+ -+ devnum = makedev(mpp->dmi.major, mpp->dmi.minor); -+ udd = udev_device_new_from_devnum(udev, 'b', devnum); -+ if (!udd) { -+ condlog(1, "failed to get udev device for %s", mpp->alias); -+ return NULL; -+ } -+ return udd; -+} -diff --git a/libmultipath/sysfs.h b/libmultipath/sysfs.h -index 2db86bd6..3be3f665 100644 ---- a/libmultipath/sysfs.h -+++ b/libmultipath/sysfs.h -@@ -39,4 +39,8 @@ do { \ - int sysfs_get_size (struct path *pp, unsigned long long * size); - int sysfs_check_holders(char * check_devt, char * new_devt); - bool sysfs_is_multipathed(struct path *pp, bool set_wwid); -+ -+struct multipath; -+struct udev_device *get_udev_for_mpp(const struct multipath *mpp); -+ - #endif diff --git a/0024-libmultipath-add-mp_find_path_by_devt.patch b/0024-libmultipath-add-mp_find_path_by_devt.patch deleted file mode 100644 index 8a85be2..0000000 --- a/0024-libmultipath-add-mp_find_path_by_devt.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Wed, 17 Apr 2024 14:57:33 +0200 -Subject: [PATCH] libmultipath: add mp_find_path_by_devt() - -A helper function that searches a struct multipath by dev_t, and -works whether or not mpp->paths is currently available. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/structs.c | 19 +++++++++++++++++++ - libmultipath/structs.h | 3 +++ - 2 files changed, 22 insertions(+) - -diff --git a/libmultipath/structs.c b/libmultipath/structs.c -index 74e31a13..e248fb51 100644 ---- a/libmultipath/structs.c -+++ b/libmultipath/structs.c -@@ -526,6 +526,25 @@ find_path_by_devt (const struct _vector *pathvec, const char * dev_t) - return NULL; - } - -+struct path *mp_find_path_by_devt(const struct multipath *mpp, const char *devt) -+{ -+ struct path *pp; -+ struct pathgroup *pgp; -+ unsigned int i, j; -+ -+ pp = find_path_by_devt(mpp->paths, devt); -+ if (pp) -+ return pp; -+ -+ vector_foreach_slot (mpp->pg, pgp, i){ -+ vector_foreach_slot (pgp->paths, pp, j){ -+ if (!strcmp(pp->dev_t, devt)) -+ return pp; -+ } -+ } -+ return NULL; -+} -+ - static int do_pathcount(const struct multipath *mpp, const int *states, - unsigned int nr_states) - { -diff --git a/libmultipath/structs.h b/libmultipath/structs.h -index 734905e2..a25eb9d5 100644 ---- a/libmultipath/structs.h -+++ b/libmultipath/structs.h -@@ -568,6 +568,9 @@ struct path * find_path_by_devt (const struct _vector *pathvec, const char *devt - struct path * find_path_by_dev (const struct _vector *pathvec, const char *dev); - struct path * first_path (const struct multipath *mpp); - -+struct path *mp_find_path_by_devt(const struct multipath *mpp, const char *devt); -+ -+ - int pathcount (const struct multipath *, int); - int count_active_paths(const struct multipath *); - int count_active_pending_paths(const struct multipath *); diff --git a/0025-Revert-libmultipath-fix-max_sectors_kb-on-adding-pat.patch b/0025-Revert-libmultipath-fix-max_sectors_kb-on-adding-pat.patch deleted file mode 100644 index aaa0e9f..0000000 --- a/0025-Revert-libmultipath-fix-max_sectors_kb-on-adding-pat.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 11 Apr 2024 17:20:14 +0200 -Subject: [PATCH] Revert "libmultipath: fix max_sectors_kb on adding path" - -This reverts commit bbb77f318ee483292f50a7782aecaecc7e60f727. -Reviewed-by: Benjamin Marzinski - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/configure.c | 7 +++---- - 1 file changed, 3 insertions(+), 4 deletions(-) - -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index 89ac03d5..13602f3f 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -575,12 +575,11 @@ sysfs_set_max_sectors_kb(struct multipath *mpp, int is_reload) - ssize_t len; - int i, j, ret, err = 0; - struct udev_device *udd; -- int max_sectors_kb = mpp->max_sectors_kb; -+ int max_sectors_kb; - -- /* by default, do not initialize max_sectors_kb on the device */ -- if (max_sectors_kb == MAX_SECTORS_KB_UNDEF && !is_reload) -+ if (mpp->max_sectors_kb == MAX_SECTORS_KB_UNDEF) - return 0; -- /* on reload, re-apply the user tuning on all the path devices */ -+ max_sectors_kb = mpp->max_sectors_kb; - if (is_reload) { - if (!has_dm_info(mpp) && - dm_get_info(mpp->alias, &mpp->dmi) != 0) { diff --git a/0026-libmultipath-Only-set-max_sectors_kb-on-map-creation.patch b/0026-libmultipath-Only-set-max_sectors_kb-on-map-creation.patch deleted file mode 100644 index c82cfe7..0000000 --- a/0026-libmultipath-Only-set-max_sectors_kb-on-map-creation.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Tue, 16 Apr 2024 22:20:46 +0200 -Subject: [PATCH] libmultipath: Only set max_sectors_kb on map creation - -Changing max_sectors_kb on a live map is dangerous. When I/O occurs while the -max_sectors_kb value of a map is larger than that of any of its paths, I/O -errors like this may result: - - blk_insert_cloned_request: over max size limit. (127 > 126) - -This situation must be strictly avoided. The kernel makes sure that the -map's limits match those of the paths when the map is created. But setting -max_sectors_kb on path devices before reloading is dangerous, even if we -read the value from the map's max_sectors_kb beforehand. The reason for -this is that the sysfs value max_sectors_kb is the kernel's max_sectors -divided by 2, and user space has no way to figure out if the kernel-internal -value is odd or even. Thus by writing back the value just read to -max_sectors_kb, one might actually decrease the kernel value by one. - -The only safe way to set max_sectors_kb on a live map would be to suspend -it, flushing all outstanding IO, then the path max_sectors_kb, reload, -and resume. - -Since commit 8fd4868 ("libmultipath: don't set max_sectors_kb on reloads"), -we don't set the configured max_sectors_kb any more. But as shown above, -this is not safe. So really only set max_sectors_kb when creating a map. - -Users who have stacked block devices on top of multipath, as described in the -commit message of 8fd4868 must make sure that the max_sectors_kb setting is -correct when the multipath map is first created. Decreasing the map's -max_sectors_kb value (without touching the paths) should actually be possible -in this situation, because stacked block devices are usually bio-based, and -bio-based IO (in contrast to request-based) can be split if the lower-level -device has can't handle the size of the I/O. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/configure.c | 38 ++++---------------------------------- - 1 file changed, 4 insertions(+), 34 deletions(-) - -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index 13602f3f..8cbb2a88 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -566,46 +566,18 @@ trigger_paths_udev_change(struct multipath *mpp, bool is_mpath) - mpp->needs_paths_uevent = 0; - } - --static int --sysfs_set_max_sectors_kb(struct multipath *mpp, int is_reload) -+static int sysfs_set_max_sectors_kb(struct multipath *mpp) - { - struct pathgroup * pgp; - struct path *pp; - char buff[11]; - ssize_t len; - int i, j, ret, err = 0; -- struct udev_device *udd; -- int max_sectors_kb; - - if (mpp->max_sectors_kb == MAX_SECTORS_KB_UNDEF) - return 0; -- max_sectors_kb = mpp->max_sectors_kb; -- if (is_reload) { -- if (!has_dm_info(mpp) && -- dm_get_info(mpp->alias, &mpp->dmi) != 0) { -- condlog(1, "failed to get dm info for %s", mpp->alias); -- return 1; -- } -- udd = get_udev_for_mpp(mpp); -- if (!udd) { -- condlog(1, "failed to get udev device to set max_sectors_kb for %s", mpp->alias); -- return 1; -- } -- ret = sysfs_attr_get_value(udd, "queue/max_sectors_kb", buff, -- sizeof(buff)); -- udev_device_unref(udd); -- if (!sysfs_attr_value_ok(ret, sizeof(buff))) { -- condlog(1, "failed to get current max_sectors_kb from %s", mpp->alias); -- return 1; -- } -- if (sscanf(buff, "%u\n", &max_sectors_kb) != 1) { -- condlog(1, "can't parse current max_sectors_kb from %s", -- mpp->alias); -- return 1; -- } -- } -- snprintf(buff, 11, "%d", max_sectors_kb); -- len = strlen(buff); -+ -+ len = snprintf(buff, sizeof(buff), "%d", mpp->max_sectors_kb); - - vector_foreach_slot (mpp->pg, pgp, i) { - vector_foreach_slot(pgp->paths, pp, j) { -@@ -923,7 +895,7 @@ int domap(struct multipath *mpp, char *params, int is_daemon) - return DOMAP_RETRY; - } - -- sysfs_set_max_sectors_kb(mpp, 0); -+ sysfs_set_max_sectors_kb(mpp); - if (is_daemon && mpp->ghost_delay > 0 && count_active_paths(mpp) && - pathcount(mpp, PATH_UP) == 0) - mpp->ghost_delay_tick = mpp->ghost_delay; -@@ -934,7 +906,6 @@ int domap(struct multipath *mpp, char *params, int is_daemon) - - case ACT_RELOAD: - case ACT_RELOAD_RENAME: -- sysfs_set_max_sectors_kb(mpp, 1); - if (mpp->ghost_delay_tick > 0 && pathcount(mpp, PATH_UP)) - mpp->ghost_delay_tick = 0; - r = dm_addmap_reload(mpp, params, 0); -@@ -942,7 +913,6 @@ int domap(struct multipath *mpp, char *params, int is_daemon) - - case ACT_RESIZE: - case ACT_RESIZE_RENAME: -- sysfs_set_max_sectors_kb(mpp, 1); - if (mpp->ghost_delay_tick > 0 && pathcount(mpp, PATH_UP)) - mpp->ghost_delay_tick = 0; - r = dm_addmap_reload(mpp, params, 1); diff --git a/0027-libmultipath-set-max_sectors_kb-in-adopt_paths.patch b/0027-libmultipath-set-max_sectors_kb-in-adopt_paths.patch deleted file mode 100644 index a4389df..0000000 --- a/0027-libmultipath-set-max_sectors_kb-in-adopt_paths.patch +++ /dev/null @@ -1,233 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Tue, 16 Apr 2024 23:59:03 +0200 -Subject: [PATCH] libmultipath: set max_sectors_kb in adopt_paths() - -As explained in the previous commit, setting max_sectors_kb for -paths that are members of a live map is dangerous. But as long as -a path is not a member of a map, setting max_sectors_kb poses no risk. -Set the parameter in adopt_paths(), for paths that aren't members -of the map yet. In order to determine whether or not a path is currently -member of the map, adopt_paths() needs to passed the current member list. If -(and only if) it's called from coalesce_paths(), the passed struct multipath -doesn not represent the current state of the map; adopt_paths() must therefore -get a new argument current_mpp that represents the kernel state. - -We must still call sysfs_set_max_sectors_kb() from domap() in the ACT_CREATE -case, because when adopt_paths is called from coalesce_paths() for a map that -doesn't exist yet, mpp->max_sectors_kb is not set. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/configure.c | 2 +- - libmultipath/structs_vec.c | 62 ++++++++++++++++++++++++++++++++++---- - libmultipath/structs_vec.h | 6 ++-- - multipathd/main.c | 6 ++-- - tests/Makefile | 2 +- - tests/test-lib.c | 9 +++++- - 6 files changed, 73 insertions(+), 14 deletions(-) - -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index 8cbb2a88..b5c701fa 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -1105,7 +1105,7 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid, - /* - * at this point, we know we really got a new mp - */ -- mpp = add_map_with_path(vecs, pp1, 0); -+ mpp = add_map_with_path(vecs, pp1, 0, cmpp); - if (!mpp) { - orphan_path(pp1, "failed to create multipath device"); - continue; -diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c -index 0fc608c2..c0c5cc90 100644 ---- a/libmultipath/structs_vec.c -+++ b/libmultipath/structs_vec.c -@@ -242,7 +242,38 @@ static bool update_pathvec_from_dm(vector pathvec, struct multipath *mpp, - return must_reload; - } - --int adopt_paths(vector pathvec, struct multipath *mpp) -+static bool set_path_max_sectors_kb(const struct path *pp, int max_sectors_kb) -+{ -+ char buf[11]; -+ ssize_t len; -+ int ret, current; -+ bool rc = false; -+ -+ if (max_sectors_kb == MAX_SECTORS_KB_UNDEF) -+ return rc; -+ -+ if (sysfs_attr_get_value(pp->udev, "queue/max_sectors_kb", buf, sizeof(buf)) <= 0 -+ || sscanf(buf, "%d\n", ¤t) != 1) -+ current = MAX_SECTORS_KB_UNDEF; -+ if (current == max_sectors_kb) -+ return rc; -+ -+ len = snprintf(buf, sizeof(buf), "%d", max_sectors_kb); -+ ret = sysfs_attr_set_value(pp->udev, "queue/max_sectors_kb", buf, len); -+ if (ret != len) -+ log_sysfs_attr_set_value(3, ret, -+ "failed setting max_sectors_kb on %s", -+ pp->dev); -+ else { -+ condlog(3, "%s: set max_sectors_kb to %d for %s", __func__, -+ max_sectors_kb, pp->dev); -+ rc = true; -+ } -+ return rc; -+} -+ -+int adopt_paths(vector pathvec, struct multipath *mpp, -+ const struct multipath *current_mpp) - { - int i, ret; - struct path * pp; -@@ -285,9 +316,28 @@ int adopt_paths(vector pathvec, struct multipath *mpp) - continue; - } - -- if (!find_path_by_devt(mpp->paths, pp->dev_t) && -- store_path(mpp->paths, pp)) -- goto err; -+ if (!find_path_by_devt(mpp->paths, pp->dev_t)) { -+ -+ if (store_path(mpp->paths, pp)) -+ goto err; -+ /* -+ * Setting max_sectors_kb on live paths is dangerous. -+ * But we can do it here on a path that isn't yet part -+ * of the map. If this value is lower than the current -+ * max_sectors_kb and the map is reloaded, the map's -+ * max_sectors_kb will be safely adjusted by the kernel. -+ * -+ * We must make sure that the path is not part of the -+ * map yet. Normally we can check this in mpp->paths. -+ * But if adopt_paths is called from coalesce_paths, -+ * we need to check the separate struct multipath that -+ * has been obtained from map_discovery(). -+ */ -+ if (!current_mpp || -+ !mp_find_path_by_devt(current_mpp, pp->dev_t)) -+ mpp->need_reload = mpp->need_reload || -+ set_path_max_sectors_kb(pp, mpp->max_sectors_kb); -+ } - - pp->mpp = mpp; - condlog(3, "%s: ownership set to %s", -@@ -693,7 +743,7 @@ find_existing_alias (struct multipath * mpp, - } - - struct multipath *add_map_with_path(struct vectors *vecs, struct path *pp, -- int add_vec) -+ int add_vec, const struct multipath *current_mpp) - { - struct multipath * mpp; - struct config *conf = NULL; -@@ -721,7 +771,7 @@ struct multipath *add_map_with_path(struct vectors *vecs, struct path *pp, - goto out; - mpp->size = pp->size; - -- if (adopt_paths(vecs->pathvec, mpp) || pp->mpp != mpp || -+ if (adopt_paths(vecs->pathvec, mpp, current_mpp) || pp->mpp != mpp || - find_slot(mpp->paths, pp) == -1) - goto out; - -diff --git a/libmultipath/structs_vec.h b/libmultipath/structs_vec.h -index 3253f1bb..dbc43058 100644 ---- a/libmultipath/structs_vec.h -+++ b/libmultipath/structs_vec.h -@@ -13,7 +13,8 @@ struct vectors { - - void set_no_path_retry(struct multipath *mpp); - --int adopt_paths (vector pathvec, struct multipath * mpp); -+int adopt_paths (vector pathvec, struct multipath *mpp, -+ const struct multipath *current_mpp); - void orphan_path (struct path * pp, const char *reason); - void set_path_removed(struct path *pp); - -@@ -28,7 +29,8 @@ void remove_maps (struct vectors * vecs); - - void sync_map_state (struct multipath *); - struct multipath * add_map_with_path (struct vectors * vecs, -- struct path * pp, int add_vec); -+ struct path * pp, int add_vec, -+ const struct multipath *current_mpp); - void update_queue_mode_del_path(struct multipath *mpp); - void update_queue_mode_add_path(struct multipath *mpp); - int update_multipath_table (struct multipath *mpp, vector pathvec, int flags); -diff --git a/multipathd/main.c b/multipathd/main.c -index dd17d5c3..d8518a92 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -636,7 +636,7 @@ update_map (struct multipath *mpp, struct vectors *vecs, int new_map) - - retry: - condlog(4, "%s: updating new map", mpp->alias); -- if (adopt_paths(vecs->pathvec, mpp)) { -+ if (adopt_paths(vecs->pathvec, mpp, NULL)) { - condlog(0, "%s: failed to adopt paths for new map update", - mpp->alias); - retries = -1; -@@ -1231,7 +1231,7 @@ rescan: - if (mpp) { - condlog(4,"%s: adopting all paths for path %s", - mpp->alias, pp->dev); -- if (adopt_paths(vecs->pathvec, mpp) || pp->mpp != mpp || -+ if (adopt_paths(vecs->pathvec, mpp, NULL) || pp->mpp != mpp || - find_slot(mpp->paths, pp) == -1) - goto fail; /* leave path added to pathvec */ - -@@ -1245,7 +1245,7 @@ rescan: - return 0; - } - condlog(4,"%s: creating new map", pp->dev); -- if ((mpp = add_map_with_path(vecs, pp, 1))) { -+ if ((mpp = add_map_with_path(vecs, pp, 1, NULL))) { - mpp->action = ACT_CREATE; - /* - * We don't depend on ACT_CREATE, as domap will -diff --git a/tests/Makefile b/tests/Makefile -index d1d52dde..4005204a 100644 ---- a/tests/Makefile -+++ b/tests/Makefile -@@ -45,7 +45,7 @@ dmevents-test_OBJDEPS = $(multipathdir)/devmapper.o - dmevents-test_LIBDEPS = -lpthread -ldevmapper -lurcu - hwtable-test_TESTDEPS := test-lib.o - hwtable-test_OBJDEPS := $(multipathdir)/discovery.o $(multipathdir)/blacklist.o \ -- $(multipathdir)/structs.o $(multipathdir)/propsel.o -+ $(multipathdir)/structs_vec.o $(multipathdir)/structs.o $(multipathdir)/propsel.o - hwtable-test_LIBDEPS := -ludev -lpthread -ldl - blacklist-test_TESTDEPS := test-log.o - blacklist-test_LIBDEPS := -ludev -diff --git a/tests/test-lib.c b/tests/test-lib.c -index cdb2780d..88f35e94 100644 ---- a/tests/test-lib.c -+++ b/tests/test-lib.c -@@ -152,6 +152,13 @@ int __wrap_sysfs_get_size(struct path *pp, unsigned long long *sz) - return 0; - } - -+int __wrap_sysfs_attr_set_value(struct udev_device *dev, const char *attr_name, -+ const char * value, size_t value_len) -+{ -+ condlog(5, "%s: %s", __func__, value); -+ return value_len; -+} -+ - void *__wrap_udev_device_get_parent_with_subsystem_devtype( - struct udev_device *ud, const char *subsys, char *type) - { -@@ -400,7 +407,7 @@ struct multipath *__mock_multipath(struct vectors *vecs, struct path *pp) - /* pathinfo() call in adopt_paths */ - mock_pathinfo(DI_CHECKER|DI_PRIO, &mop); - -- mp = add_map_with_path(vecs, pp, 1); -+ mp = add_map_with_path(vecs, pp, 1, NULL); - assert_ptr_not_equal(mp, NULL); - - /* TBD: mock setup_map() ... */ diff --git a/0028-libmultipath-add-wildcard-k-for-printing-max_sectors.patch b/0028-libmultipath-add-wildcard-k-for-printing-max_sectors.patch deleted file mode 100644 index 9b66bbb..0000000 --- a/0028-libmultipath-add-wildcard-k-for-printing-max_sectors.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Wed, 17 Apr 2024 17:19:43 +0200 -Subject: [PATCH] libmultipath: add wildcard %k for printing max_sectors_kb - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/print.c | 38 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 38 insertions(+) - -diff --git a/libmultipath/print.c b/libmultipath/print.c -index 360308d2..efd5a16a 100644 ---- a/libmultipath/print.c -+++ b/libmultipath/print.c -@@ -32,6 +32,7 @@ - #include "util.h" - #include "foreign.h" - #include "strbuf.h" -+#include "sysfs.h" - - #define PRINT_PATH_LONG "%w %i %d %D %p %t %T %s %o" - #define PRINT_PATH_INDENT "%i %d %D %t %T %o" -@@ -431,6 +432,27 @@ snprint_multipath_vpd_data(struct strbuf *buff, - return append_strbuf_str(buff, "[undef]"); - } - -+static void cleanup_udev_device(struct udev_device **udd) -+{ -+ if (*udd) -+ udev_device_unref(*udd); -+} -+ -+static int -+snprint_multipath_max_sectors_kb(struct strbuf *buff, const struct multipath *mpp) -+{ -+ char buf[11]; -+ int max_sectors_kb; -+ struct udev_device *udd __attribute__((cleanup(cleanup_udev_device))) -+ = get_udev_for_mpp(mpp); -+ -+ if (!udd || -+ sysfs_attr_get_value(udd, "queue/max_sectors_kb", buf, sizeof(buf)) <= 0 || -+ sscanf(buf, "%d\n", &max_sectors_kb) != 1) -+ return print_strbuf(buff, "n/a"); -+ return print_strbuf(buff, "%d", max_sectors_kb); -+} -+ - /* - * path info printing functions - */ -@@ -790,6 +812,20 @@ snprint_alua_tpg(struct strbuf *buff, const struct path * pp) - return print_strbuf(buff, "0x%04x", pp->tpg_id); - } - -+static int -+snprint_path_max_sectors_kb(struct strbuf *buff, const struct path *pp) -+{ -+ char buf[11]; -+ int max_sectors_kb; -+ -+ if (!pp->udev || -+ sysfs_attr_get_value(pp->udev, "queue/max_sectors_kb", -+ buf, sizeof(buf)) <= 0 || -+ sscanf(buf, "%d\n", &max_sectors_kb) != 1) -+ return print_strbuf(buff, "n/a"); -+ return print_strbuf(buff, "%d", max_sectors_kb); -+} -+ - static const struct multipath_data mpd[] = { - {'n', "name", snprint_name}, - {'w', "uuid", snprint_multipath_uuid}, -@@ -815,6 +851,7 @@ static const struct multipath_data mpd[] = { - {'e', "rev", snprint_multipath_rev}, - {'G', "foreign", snprint_multipath_foreign}, - {'g', "vpd page data", snprint_multipath_vpd_data}, -+ {'k', "max_sectors_kb",snprint_multipath_max_sectors_kb}, - }; - - static const struct path_data pd[] = { -@@ -845,6 +882,7 @@ static const struct path_data pd[] = { - {'I', "init_st", snprint_initialized}, - {'L', "LUN hex", snprint_path_lunhex}, - {'A', "TPG", snprint_alua_tpg}, -+ {'k', "max_sectors_kb",snprint_path_max_sectors_kb}, - }; - - static const struct pathgroup_data pgd[] = { diff --git a/0029-multipath.conf-5-update-documentation-for-max_sector.patch b/0029-multipath.conf-5-update-documentation-for-max_sector.patch deleted file mode 100644 index dcdf164..0000000 --- a/0029-multipath.conf-5-update-documentation-for-max_sector.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Wed, 17 Apr 2024 18:59:04 +0200 -Subject: [PATCH] multipath.conf(5): update documentation for max_sectors_kb - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - multipath/multipath.conf.5.in | 33 +++++++++++++++++++++++++++++---- - 1 file changed, 29 insertions(+), 4 deletions(-) - -diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in -index c788c180..b29a75fe 100644 ---- a/multipath/multipath.conf.5.in -+++ b/multipath/multipath.conf.5.in -@@ -1311,11 +1311,36 @@ The default is: \fB0\fR - . - .TP - .B max_sectors_kb --Sets the max_sectors_kb device parameter on all path devices and the multipath --device to the specified value. -+Sets the \fImax_sectors_kb\fR device parameter on some path devices and the multipath -+device to the specified value. \fImax_sectors_kb\fR is the largest I/O size, in units -+of 1024 bytes, that the kernel allows for a single I/O request. For hardware devices -+like SCSI disks, this value is limited by the capabilities of the hardware. -+It is crucial that the value of a multipath map is never higher than the minimum value of -+of all its path devices. This is ensured by the kernel when a multipath map -+is loaded, but manipulating the values of a map or either of its paths while the -+map is live can cause race conditions and I/O errors. Therefore this value is only -+enforced by multipathd when a multipath map is first created, or when a path device -+is added to a map. In both cases, race conditions are avoided by the kernel. - .RS --.TP --The default is: in \fB/sys/block//queue/max_sectors_kb\fR -+.PP -+Setting \fImax_sectors_kb\fR does not guarantee that all path devices will have this -+value set. It is not an error if the value of a path device is higher than that of -+the containing multipath map. It is also not an error if the actual limit of a map is -+lower than the value in \fI@CONFIGFILE@\fR. This can happen if the hardware limits of one -+or more path devices are lower than the configured value. -+.PP -+Normally the kernel and its device drivers take care of the maximum -+I/O size, and administrators do not need to bother about \fImax_sectors_kb\fR. -+But some hardware devices may report incorrect I/O size limits, or other components -+in the environment (e.g. the fabric) may impose constraints that the kernel cannot -+detect. In such cases setting \fImax_sectors_kb\fR makes sense. It should be set when -+maps are first created, and not be changed thereafter. -+If the setting \fBmust\fR be changed for a live map, set the -+value in \fI@CONFIGFILE@\fR, run \fBmultipathd reconfigure\fR, and use -+\fBmultipathd del path \fR and \fBmultipathd add path \fR to -+delete and re-add the same path device. -+.LP -+The default is: \fBundefined\fR. - .RE - . - . diff --git a/0030-multipath-tools-simplify-comment-in-hwtable.patch b/0030-multipath-tools-simplify-comment-in-hwtable.patch deleted file mode 100644 index 59090a7..0000000 --- a/0030-multipath-tools-simplify-comment-in-hwtable.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Xose Vazquez Perez -Date: Sun, 28 Apr 2024 01:45:35 +0200 -Subject: [PATCH] multipath-tools: simplify comment in hwtable - -Instead of adding the new 5300 model, replace them with wildcards. - -Cc: Martin Wilck -Cc: Benjamin Marzinski -Cc: Christophe Varoqui -Cc: DM-DEVEL ML -Signed-off-by: Xose Vazquez Perez -Reviewed-by: Benjamin Marzinski -Reviewed-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - libmultipath/hwtable.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c -index 640bf347..7aac3f37 100644 ---- a/libmultipath/hwtable.c -+++ b/libmultipath/hwtable.c -@@ -683,8 +683,8 @@ static struct hwentry default_hw[] = { - .pgfailback = -FAILBACK_IMMEDIATE, - }, - { -- // Storwize V5000/V7000 lines / SAN Volume Controller (SVC) / Flex System V7000 -- // FlashSystem V840/V9000/5000/5100/5200/7200/7300/9100/9200/9200R/9500 -+ // Storwize V5000/V7000 lines / SAN Volume Controller (SVC) -+ // Flex System V7000 / FlashSystem V840/V9000 and 5x00/7x00/9x00 - .vendor = "IBM", - .product = "^2145", - .no_path_retry = NO_PATH_RETRY_QUEUE, diff --git a/0031-multipath-tools-unify-text-in-multipath.conf.5.patch b/0031-multipath-tools-unify-text-in-multipath.conf.5.patch deleted file mode 100644 index b6d9af3..0000000 --- a/0031-multipath-tools-unify-text-in-multipath.conf.5.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Xose Vazquez Perez -Date: Sun, 28 Apr 2024 01:45:36 +0200 -Subject: [PATCH] multipath-tools: unify text in multipath.conf.5 - -Cc: Martin Wilck -Cc: Benjamin Marzinski -Cc: Christophe Varoqui -Cc: DM-DEVEL ML -Signed-off-by: Xose Vazquez Perez -Reviewed-by: Benjamin Marzinski -Reviewed-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - multipath/multipath.conf.5.in | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in -index b29a75fe..c1a19ebb 100644 ---- a/multipath/multipath.conf.5.in -+++ b/multipath/multipath.conf.5.in -@@ -187,7 +187,7 @@ The default is: \fBno\fR - . - .TP - .B multipath_dir --(Deprecated) This option is not supported anymore, and the value is ignored. -+(Deprecated) This option is not supported anymore, and will be ignored. - . - . - .TP -@@ -277,7 +277,7 @@ The default is: \fBno\fR - . - .TP - .B pg_timeout --(Deprecated) This option is not supported anymore, and the value is ignored. -+(Deprecated) This option is not supported anymore, and will be ignored. - . - . - .TP -@@ -322,7 +322,7 @@ The default is: \fBID_WWN\fR, for NVMe devices - . - .TP - .B getuid_callout --(Deprecated) This option is not supported anymore, and the value is ignored. -+(Deprecated) This option is not supported anymore, and will be ignored. - . - . - .TP -@@ -995,7 +995,7 @@ The default is: \fB\fR - . - .TP - .B config_dir --(Deprecated) This option is not supported anymore, and the value is ignored. -+(Deprecated) This option is not supported anymore, and will be ignored. - .RS - .TP - The compiled-in value is: \fB@CONFIGDIR@\fR -@@ -1295,7 +1295,7 @@ The default is: \fBno\fR - . - .TP - .B disable_changed_wwids --(Deprecated) This option is not supported anymore, and the value is ignored. -+(Deprecated) This option is not supported anymore, and will be ignored. - .RE - . - . -@@ -1340,7 +1340,7 @@ value in \fI@CONFIGFILE@\fR, run \fBmultipathd reconfigure\fR, and use - \fBmultipathd del path \fR and \fBmultipathd add path \fR to - delete and re-add the same path device. - .LP --The default is: \fBundefined\fR. -+The default is: \fB\fR - .RE - . - . diff --git a/0032-multipath-tools-update-man-pages-dates.patch b/0032-multipath-tools-update-man-pages-dates.patch deleted file mode 100644 index c011eac..0000000 --- a/0032-multipath-tools-update-man-pages-dates.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Xose Vazquez Perez -Date: Sun, 28 Apr 2024 01:45:37 +0200 -Subject: [PATCH] multipath-tools: update man pages dates - -Cc: Martin Wilck -Cc: Benjamin Marzinski -Cc: Christophe Varoqui -Cc: DM-DEVEL ML -Signed-off-by: Xose Vazquez Perez -Reviewed-by: Benjamin Marzinski -Reviewed-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - libmpathpersist/mpath_persistent_reserve_in.3 | 2 +- - libmpathpersist/mpath_persistent_reserve_out.3 | 2 +- - multipath/multipath.8.in | 2 +- - multipath/multipath.conf.5.in | 2 +- - multipathd/multipathd.8.in | 2 +- - 5 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/libmpathpersist/mpath_persistent_reserve_in.3 b/libmpathpersist/mpath_persistent_reserve_in.3 -index 6cc35349..4ac43fa3 100644 ---- a/libmpathpersist/mpath_persistent_reserve_in.3 -+++ b/libmpathpersist/mpath_persistent_reserve_in.3 -@@ -6,7 +6,7 @@ - .\" Update the date below if you make any significant change. - .\" ---------------------------------------------------------------------------- - . --.TH MPATH_PERSISTENT_RESERVE_IN 3 2018-06-15 Linux -+.TH MPATH_PERSISTENT_RESERVE_IN 3 2024-02-09 Linux - . - . - .\" ---------------------------------------------------------------------------- -diff --git a/libmpathpersist/mpath_persistent_reserve_out.3 b/libmpathpersist/mpath_persistent_reserve_out.3 -index 70e26028..3dbeae1f 100644 ---- a/libmpathpersist/mpath_persistent_reserve_out.3 -+++ b/libmpathpersist/mpath_persistent_reserve_out.3 -@@ -6,7 +6,7 @@ - .\" Update the date below if you make any significant change. - .\" ---------------------------------------------------------------------------- - . --.TH MPATH_PERSISTENT_RESERVE_OUT 3 2018-06-15 Linux -+.TH MPATH_PERSISTENT_RESERVE_OUT 3 2024-02-09 Linux - . - . - .\" ---------------------------------------------------------------------------- -diff --git a/multipath/multipath.8.in b/multipath/multipath.8.in -index 348eb220..b88e9a4c 100644 ---- a/multipath/multipath.8.in -+++ b/multipath/multipath.8.in -@@ -6,7 +6,7 @@ - .\" Update the date below if you make any significant change. - .\" ---------------------------------------------------------------------------- - . --.TH MULTIPATH 8 2021-11-12 Linux -+.TH MULTIPATH 8 2023-09-08 Linux - . - . - .\" ---------------------------------------------------------------------------- -diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in -index c1a19ebb..46d3685a 100644 ---- a/multipath/multipath.conf.5.in -+++ b/multipath/multipath.conf.5.in -@@ -6,7 +6,7 @@ - .\" Update the date below if you make any significant change. - .\" ---------------------------------------------------------------------------- - . --.TH MULTIPATH.CONF 5 2023-06-15 Linux -+.TH MULTIPATH.CONF 5 2024-04-17 Linux - . - . - .\" ---------------------------------------------------------------------------- -diff --git a/multipathd/multipathd.8.in b/multipathd/multipathd.8.in -index f1cab3ff..12b77156 100644 ---- a/multipathd/multipathd.8.in -+++ b/multipathd/multipathd.8.in -@@ -6,7 +6,7 @@ - .\" Update the date below if you make any significant change. - .\" ---------------------------------------------------------------------------- - . --.TH MULTIPATHD 8 2022-09-03 Linux -+.TH MULTIPATHD 8 2023-12-19 Linux - . - . - .\" ---------------------------------------------------------------------------- diff --git a/0033-libmultipath-export-partmap_in_use.patch b/0033-libmultipath-export-partmap_in_use.patch deleted file mode 100644 index 47a6772..0000000 --- a/0033-libmultipath-export-partmap_in_use.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Thu, 25 Apr 2024 19:35:13 -0400 -Subject: [PATCH] libmultipath: export partmap_in_use - -A future commit will make use of this function - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck -Reviewed-by: Benjamin Marzinski ---- - libmultipath/devmapper.c | 2 +- - libmultipath/devmapper.h | 1 + - libmultipath/libmultipath.version | 1 + - 3 files changed, 3 insertions(+), 1 deletion(-) - -diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c -index 4ce7e82f..a87abf7e 100644 ---- a/libmultipath/devmapper.c -+++ b/libmultipath/devmapper.c -@@ -1043,7 +1043,7 @@ has_partmap(const char *name __attribute__((unused)), - return 1; - } - --static int -+int - partmap_in_use(const char *name, void *data) - { - int part_count, *ret_count = (int *)data; -diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h -index a7d66604..93caa2aa 100644 ---- a/libmultipath/devmapper.h -+++ b/libmultipath/devmapper.h -@@ -57,6 +57,7 @@ enum { - DM_FLUSH_BUSY, - }; - -+int partmap_in_use(const char *name, void *data); - int _dm_flush_map (const char *, int, int, int, int); - int dm_flush_map_nopaths(const char * mapname, int deferred_remove); - #define dm_flush_map(mapname) _dm_flush_map(mapname, 1, 0, 0, 0) -diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version -index 724786d5..e070f296 100644 ---- a/libmultipath/libmultipath.version -+++ b/libmultipath/libmultipath.version -@@ -141,6 +141,7 @@ global: - need_io_err_check; - orphan_path; - parse_prkey_flags; -+ partmap_in_use; - pathcount; - path_discovery; - path_get_tpgs; diff --git a/0034-libmultipath-change-flush_on_last_del-to-fix-a-multi.patch b/0034-libmultipath-change-flush_on_last_del-to-fix-a-multi.patch deleted file mode 100644 index 7c36521..0000000 --- a/0034-libmultipath-change-flush_on_last_del-to-fix-a-multi.patch +++ /dev/null @@ -1,346 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Thu, 25 Apr 2024 19:35:14 -0400 -Subject: [PATCH] libmultipath: change flush_on_last_del to fix a multipathd - hang - -Commit 9bd3482e ("multipathd: make flush_map() delete maps like the -multipath command") fixed an issue where deleting a queueing multipath -device through multipathd could hang because the multipath device had -outstanding IO, even though the only openers of it at the time of -deletion were the kpartx partition devices. However it is still possible -to hang multipathd, because autoremoving the device when all paths have -been deleted doesn't disable queueing. To reproduce this hang: - -1. create a multipath device with a kpartx partition on top of it and -no_path_retry set to either "queue" or something long enough to run all -the commands in the reproducer before it disables queueing. -2. disable all the paths to the device with something like: - # echo offline > /sys/block//device/state -3. Write directly to the multipath device with something like: - # dd if=/dev/zero of=/dev/mapper/ bs=4K count=1 -4. delete all the paths to the device with something like: - # echo 1 > /sys/block//device/delete - -Multipathd will hang trying to delete the kpartx device because, as the -last opener, it must flush the multipath device before closing it. -Because it hangs holding the vecs_lock, multipathd will never disable -queueing on the device, so it will hang forever, even if no_path_retry -is set to a number. - -This hang can occur, even if deferred_remove is set. Since nothing has -the kpartx device opened, device-mapper does an immediate remove, which -will still hang. This means that even if deferred_remove is set, -multipathd still cannot delete a map while queueing is enabled. It must -either disable queueing or skip the autoremove. - -Mulitpath can currently be configured to avoid this hang by setting - -flush_on_last_del yes - -However there are good reasons why users wouldn't want to set that. They -may need to be able to survive having all paths getting temporarily -deleted. I should note that this is a pretty rare corner case, since -multipath automatically sets dev_loss_tmo so that it should not trigger -before queueing is disabled. - -This commit avoids the hang by changing the possible values for -flush_on_last_del to "never", "unused", and "always", and sets the -default to "unused". "always" works like "yes" did, "never" will not -disable queueing, and "unused" will only disable queueing if nothing has -the kpartx devices or the multipath device open. In order to be safe, if -the device has queue_if_no_paths set (and in case of "unused", the -device is in-use) the autoremove will be skipped. Also, instead of just -trusting the lack of "queue_if_no_paths" in the current mpp->features, -multipathd will tell the kernel to disable queueing, just to be sure it -actually is. - -I chose "unused" as the default because this should generally only cause -multipathd to work differently from the users perspective when nothing -has the multipath device open but it is queueing and there is -outstanding IO. Without this change, it would have hung instead of -failing the outstanding IO. However, I do understand that an argument -could be made that "never" makes more sense as default, even though it -will cause multipathd to skip autoremoves in cases where it wouldn't -before. The change to the behavior of deffered_remove will be -noticeable, but skipping an autoremove is much better than hanging. - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck -Reviewed-by: Benjamin Marzinski ---- - libmultipath/defaults.h | 2 +- - libmultipath/dict.c | 72 +++++++++++++++++++++++++++++++---- - libmultipath/dict.h | 1 + - libmultipath/hwtable.c | 6 +-- - libmultipath/propsel.c | 4 +- - libmultipath/structs.h | 7 ++-- - multipath/multipath.conf.5.in | 20 +++++++--- - multipathd/main.c | 39 +++++++++++++++---- - 8 files changed, 122 insertions(+), 29 deletions(-) - -diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h -index 64b633f2..ed08c251 100644 ---- a/libmultipath/defaults.h -+++ b/libmultipath/defaults.h -@@ -43,7 +43,7 @@ - #define DEFAULT_PRIO PRIO_CONST - #define DEFAULT_PRIO_ARGS "" - #define DEFAULT_CHECKER TUR --#define DEFAULT_FLUSH FLUSH_DISABLED -+#define DEFAULT_FLUSH FLUSH_UNUSED - #define DEFAULT_USER_FRIENDLY_NAMES USER_FRIENDLY_NAMES_OFF - #define DEFAULT_FORCE_SYNC 0 - #define UNSET_PARTITION_DELIM "/UNSET/" -diff --git a/libmultipath/dict.c b/libmultipath/dict.c -index 5af036b7..546103f2 100644 ---- a/libmultipath/dict.c -+++ b/libmultipath/dict.c -@@ -791,14 +791,70 @@ declare_def_snprint(checker_timeout, print_nonzero) - declare_def_handler(allow_usb_devices, set_yes_no) - declare_def_snprint(allow_usb_devices, print_yes_no) - --declare_def_handler(flush_on_last_del, set_yes_no_undef) --declare_def_snprint_defint(flush_on_last_del, print_yes_no_undef, DEFAULT_FLUSH) --declare_ovr_handler(flush_on_last_del, set_yes_no_undef) --declare_ovr_snprint(flush_on_last_del, print_yes_no_undef) --declare_hw_handler(flush_on_last_del, set_yes_no_undef) --declare_hw_snprint(flush_on_last_del, print_yes_no_undef) --declare_mp_handler(flush_on_last_del, set_yes_no_undef) --declare_mp_snprint(flush_on_last_del, print_yes_no_undef) -+ -+static const char * const flush_on_last_del_optvals[] = { -+ [FLUSH_NEVER] = "never", -+ [FLUSH_ALWAYS] = "always", -+ [FLUSH_UNUSED] = "unused", -+}; -+ -+static int -+set_flush_on_last_del(vector strvec, void *ptr, const char *file, int line_nr) -+{ -+ int i; -+ int *flush_val_ptr = (int *)ptr; -+ char *buff; -+ -+ buff = set_value(strvec); -+ if (!buff) -+ return 1; -+ -+ for (i = FLUSH_NEVER; i <= FLUSH_UNUSED; i++) { -+ if (flush_on_last_del_optvals[i] != NULL && -+ !strcmp(buff, flush_on_last_del_optvals[i])) { -+ *flush_val_ptr = i; -+ break; -+ } -+ } -+ -+ if (i > FLUSH_UNUSED) { -+ bool deprecated = true; -+ if (strcmp(buff, "no") == 0 || strcmp(buff, "0") == 0) -+ *flush_val_ptr = FLUSH_UNUSED; -+ else if (strcmp(buff, "yes") == 0 || strcmp(buff, "1") == 0) -+ *flush_val_ptr = FLUSH_ALWAYS; -+ else { -+ deprecated = false; -+ condlog(1, "%s line %d, invalid value for flush_on_last_del: \"%s\"", -+ file, line_nr, buff); -+ } -+ if (deprecated) -+ condlog(2, "%s line %d, \"%s\" is a deprecated value for flush_on_last_del and is treated as \"%s\"", -+ file, line_nr, buff, -+ flush_on_last_del_optvals[*flush_val_ptr]); -+ } -+ -+ free(buff); -+ return 0; -+} -+ -+int -+print_flush_on_last_del(struct strbuf *buff, long v) -+{ -+ if (v == FLUSH_UNDEF) -+ return 0; -+ return append_strbuf_quoted(buff, flush_on_last_del_optvals[(int)v]); -+} -+ -+declare_def_handler(flush_on_last_del, set_flush_on_last_del) -+declare_def_snprint_defint(flush_on_last_del, print_flush_on_last_del, -+ DEFAULT_FLUSH) -+declare_ovr_handler(flush_on_last_del, set_flush_on_last_del) -+declare_ovr_snprint(flush_on_last_del, print_flush_on_last_del) -+declare_hw_handler(flush_on_last_del, set_flush_on_last_del) -+declare_hw_snprint(flush_on_last_del, print_flush_on_last_del) -+declare_mp_handler(flush_on_last_del, set_flush_on_last_del) -+declare_mp_snprint(flush_on_last_del, print_flush_on_last_del) - - declare_def_handler(user_friendly_names, set_yes_no_undef) - declare_def_snprint_defint(user_friendly_names, print_yes_no_undef, -diff --git a/libmultipath/dict.h b/libmultipath/dict.h -index 7e2dfbe0..e1794537 100644 ---- a/libmultipath/dict.h -+++ b/libmultipath/dict.h -@@ -18,4 +18,5 @@ int print_undef_off_zero(struct strbuf *buff, long v); - int print_dev_loss(struct strbuf *buff, unsigned long v); - int print_off_int_undef(struct strbuf *buff, long v); - int print_auto_resize(struct strbuf *buff, long v); -+int print_flush_on_last_del(struct strbuf *buff, long v); - #endif /* _DICT_H */ -diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c -index 7aac3f37..d1148de7 100644 ---- a/libmultipath/hwtable.c -+++ b/libmultipath/hwtable.c -@@ -60,7 +60,7 @@ - .no_path_retry = NO_PATH_RETRY_UNDEF, - .minio = 1000, - .minio_rq = 1, -- .flush_on_last_del = FLUSH_DISABLED, -+ .flush_on_last_del = FLUSH_UNUSED, - .user_friendly_names = USER_FRIENDLY_NAMES_OFF, - .fast_io_fail = 5, - .dev_loss = 600, -@@ -829,7 +829,7 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_QUEUE, - .pgpolicy = GROUP_BY_PRIO, - .pgfailback = -FAILBACK_IMMEDIATE, -- .flush_on_last_del = FLUSH_ENABLED, -+ .flush_on_last_del = FLUSH_ALWAYS, - .dev_loss = MAX_DEV_LOSS_TMO, - .prio_name = PRIO_ONTAP, - .user_friendly_names = USER_FRIENDLY_NAMES_OFF, -@@ -1160,7 +1160,7 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_FAIL, - .minio = 1, - .minio_rq = 1, -- .flush_on_last_del = FLUSH_ENABLED, -+ .flush_on_last_del = FLUSH_ALWAYS, - .fast_io_fail = 15, - }, - /* -diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c -index 44241e2a..e2dcb316 100644 ---- a/libmultipath/propsel.c -+++ b/libmultipath/propsel.c -@@ -963,6 +963,7 @@ out: - int select_flush_on_last_del(struct config *conf, struct multipath *mp) - { - const char *origin; -+ STRBUF_ON_STACK(buff); - - mp_set_mpe(flush_on_last_del); - mp_set_ovr(flush_on_last_del); -@@ -970,8 +971,9 @@ int select_flush_on_last_del(struct config *conf, struct multipath *mp) - mp_set_conf(flush_on_last_del); - mp_set_default(flush_on_last_del, DEFAULT_FLUSH); - out: -+ print_flush_on_last_del(&buff, mp->flush_on_last_del); - condlog(3, "%s: flush_on_last_del = %s %s", mp->alias, -- (mp->flush_on_last_del == FLUSH_ENABLED)? "yes" : "no", origin); -+ get_strbuf_str(&buff), origin); - return 0; - } - -diff --git a/libmultipath/structs.h b/libmultipath/structs.h -index a25eb9d5..dbaf4d43 100644 ---- a/libmultipath/structs.h -+++ b/libmultipath/structs.h -@@ -109,9 +109,10 @@ enum marginal_pathgroups_mode { - }; - - enum flush_states { -- FLUSH_UNDEF = YNU_UNDEF, -- FLUSH_DISABLED = YNU_NO, -- FLUSH_ENABLED = YNU_YES, -+ FLUSH_UNDEF, -+ FLUSH_NEVER, -+ FLUSH_ALWAYS, -+ FLUSH_UNUSED, - }; - - enum log_checker_err_states { -diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in -index 46d3685a..1d3d53bb 100644 ---- a/multipath/multipath.conf.5.in -+++ b/multipath/multipath.conf.5.in -@@ -707,12 +707,22 @@ The default is: \fBno\fR - .TP - .B flush_on_last_del - If set to --.I yes -+.I always - , multipathd will disable queueing when the last path to a device has been --deleted. --.RS --.TP --The default is: \fBno\fR -+deleted. If set to -+.I never -+, multipathd will not disable queueing when the last path to a device has -+been deleted. Since multipath cannot safely remove a device while queueing -+is enabled, setting this to \fInever\fR means that multipathd will not -+automatically remove an unused multipath device whose paths are all deleted if -+it is currently set to queue_if_no_path. If set to -+.I unused -+, multipathd will only disable queueing when the last path is removed if -+nothing currently has the multipath device or any of the kpartx partition -+devices on top of it open. -+.RS -+.TP -+The default is: \fBunused\fR - .RE - . - . -diff --git a/multipathd/main.c b/multipathd/main.c -index d8518a92..09286dd0 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -584,19 +584,42 @@ int update_multipath (struct vectors *vecs, char *mapname) - static bool - flush_map_nopaths(struct multipath *mpp, struct vectors *vecs) { - int r; -+ bool is_queueing = true; - -+ if (mpp->features) -+ is_queueing = strstr(mpp->features, "queue_if_no_path"); -+ -+ /* It's not safe to do a remove of a map that has "queue_if_no_path" -+ * set, since there could be outstanding IO which will cause -+ * multipathd to hang while attempting the remove */ -+ if (mpp->flush_on_last_del == FLUSH_NEVER && is_queueing) { -+ condlog(2, "%s: map is queueing, can't remove", mpp->alias); -+ return false; -+ } -+ if (mpp->flush_on_last_del == FLUSH_UNUSED && -+ partmap_in_use(mpp->alias, NULL) && is_queueing) { -+ condlog(2, "%s: map in use and queueing, can't remove", -+ mpp->alias); -+ return false; -+ } - /* -- * flush_map will fail if the device is open -+ * This will flush FLUSH_NEVER devices and FLUSH_UNUSED devices -+ * that are in use, but only if they are already marked as not -+ * queueing. That is just to make absolutely certain that they -+ * really are not queueing, like they claim. - */ -- if (mpp->flush_on_last_del == FLUSH_ENABLED) { -- condlog(2, "%s Last path deleted, disabling queueing", -+ condlog(is_queueing ? 2 : 3, "%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++; -+ if (dm_queue_if_no_path(mpp, 0) != 0) { -+ condlog(0, "%s: failed to disable queueing. Not removing", - 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, 0); -+ return false; - } -+ - r = dm_flush_map_nopaths(mpp->alias, mpp->deferred_remove); - if (r != DM_FLUSH_OK) { - if (r == DM_FLUSH_DEFERRED) { diff --git a/0035-libmultipath-remove-redundant-config-option-from-Inf.patch b/0035-libmultipath-remove-redundant-config-option-from-Inf.patch deleted file mode 100644 index 8de5639..0000000 --- a/0035-libmultipath-remove-redundant-config-option-from-Inf.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Thu, 25 Apr 2024 19:35:15 -0400 -Subject: [PATCH] libmultipath: remove redundant config option from InfiniBox - config - -The InfiniBox config already sets no_path_retry to "fail", so it won't -ever queue IO. That means setting flush_on_last_del to "always" is -redundant, since queueing is always disabled. Remove the -flush_on_last_del parameter, to make it easier for users to override the -default behavior if desired. - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck -Reviewed-by: Benjamin Marzinski ---- - libmultipath/hwtable.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c -index d1148de7..9e008df6 100644 ---- a/libmultipath/hwtable.c -+++ b/libmultipath/hwtable.c -@@ -1160,7 +1160,6 @@ static struct hwentry default_hw[] = { - .no_path_retry = NO_PATH_RETRY_FAIL, - .minio = 1, - .minio_rq = 1, -- .flush_on_last_del = FLUSH_ALWAYS, - .fast_io_fail = 15, - }, - /* diff --git a/0036-libmultipath-pad-dev_loss_tmo-to-avoid-race-with-no_.patch b/0036-libmultipath-pad-dev_loss_tmo-to-avoid-race-with-no_.patch deleted file mode 100644 index f61f658..0000000 --- a/0036-libmultipath-pad-dev_loss_tmo-to-avoid-race-with-no_.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Thu, 25 Apr 2024 19:35:16 -0400 -Subject: [PATCH] libmultipath: pad dev_loss_tmo to avoid race with - no_path_retry - -Currently multipath makes sure that dev_loss_tmo is at least as long as -the configured no path queueing time. The goal is to make sure that path -devices aren't removed while the multipath device is still queueing in -hopes that they will become usable again. - -This is racy. Multipathd may take longer to check the paths than -configured. If strict_timing isn't set, it will definitely take longer. -To account for this, pad the minimum dev_loss_tmo value by five seconds -(one default checker interval) plus one second per minute of no path -queueing time. - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck -Reviewed-by: Benjamin Marzinski ---- - libmultipath/discovery.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index 6fd4dabb..e2052422 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -901,6 +901,11 @@ sysfs_set_scsi_tmo (struct config *conf, struct multipath *mpp) - uint64_t no_path_retry_tmo = - (uint64_t)mpp->no_path_retry * conf->checkint; - -+ /* pad no_path_retry_tmo by one standard check interval -+ * plus one second per minute to account for timing -+ * issues with the rechecks */ -+ no_path_retry_tmo += no_path_retry_tmo / 60 + DEFAULT_CHECKINT; -+ - if (no_path_retry_tmo > MAX_DEV_LOSS_TMO) - min_dev_loss = MAX_DEV_LOSS_TMO; - else diff --git a/0037-libmultipath-fix-deferred_remove-function-arguments.patch b/0037-libmultipath-fix-deferred_remove-function-arguments.patch deleted file mode 100644 index 507a056..0000000 --- a/0037-libmultipath-fix-deferred_remove-function-arguments.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Thu, 25 Apr 2024 19:35:17 -0400 -Subject: [PATCH] libmultipath: fix deferred_remove function arguments - -Aside from one version of dm_flush_map_nopaths(), all the callers of -_dm_flush_map() and dm_simplecmd() set deferred_remove to 0. But these -functions, as well as some helper functions they called, all treated the -deferred_remove argument as an enum deferred_remove_states, and called -do_deferred() to see if the remove should be deferred. To simplify the -code, make these functions treat deferred_remove as a boolean value -signifying whether a remove is deferred, and make dm_flush_map_nopaths() -do the work of checking if the remove should be deferred. - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck -Reviewed-by: Benjamin Marzinski ---- - libmultipath/devmapper.c | 19 +++++++++---------- - libmultipath/libmultipath.version | 2 +- - 2 files changed, 10 insertions(+), 11 deletions(-) - -diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c -index a87abf7e..2e7b2c64 100644 ---- a/libmultipath/devmapper.c -+++ b/libmultipath/devmapper.c -@@ -386,8 +386,6 @@ libmp_dm_task_create(int task) - return dm_task_create(task); - } - --#define do_deferred(x) ((x) == DEFERRED_REMOVE_ON || (x) == DEFERRED_REMOVE_IN_PROGRESS) -- - static int - dm_simplecmd (int task, const char *name, int no_flush, int need_sync, - uint16_t udev_flags, int deferred_remove __DR_UNUSED__) { -@@ -411,7 +409,7 @@ dm_simplecmd (int task, const char *name, int no_flush, int need_sync, - dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ - #endif - #ifdef LIBDM_API_DEFERRED -- if (do_deferred(deferred_remove)) -+ if (deferred_remove) - dm_task_deferred_remove(dmt); - #endif - if (udev_wait_flag && -@@ -1082,7 +1080,7 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, - - /* If you aren't doing a deferred remove, make sure that no - * devices are in use */ -- if (!do_deferred(deferred_remove) && partmap_in_use(mapname, NULL)) -+ if (!deferred_remove && partmap_in_use(mapname, NULL)) - return DM_FLUSH_BUSY; - - if (need_suspend && -@@ -1100,7 +1098,7 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, - if ((r = dm_remove_partmaps(mapname, need_sync, deferred_remove))) - return r; - -- if (!do_deferred(deferred_remove) && dm_get_opencount(mapname)) { -+ if (!deferred_remove && dm_get_opencount(mapname)) { - condlog(2, "%s: map in use", mapname); - return DM_FLUSH_BUSY; - } -@@ -1112,8 +1110,7 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, - r = dm_device_remove(mapname, need_sync, deferred_remove); - - if (r) { -- if (do_deferred(deferred_remove) -- && dm_map_present(mapname)) { -+ if (deferred_remove && dm_map_present(mapname)) { - condlog(4, "multipath map %s remove deferred", - mapname); - return DM_FLUSH_DEFERRED; -@@ -1147,7 +1144,10 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, - int - dm_flush_map_nopaths(const char * mapname, int deferred_remove) - { -- return _dm_flush_map(mapname, 1, deferred_remove, 0, 0); -+ return _dm_flush_map(mapname, 1, -+ (deferred_remove == DEFERRED_REMOVE_ON || -+ deferred_remove == DEFERRED_REMOVE_IN_PROGRESS), -+ 0, 0); - } - - #else -@@ -1539,8 +1539,7 @@ remove_partmap(const char *name, void *data) - - if (dm_get_opencount(name)) { - dm_remove_partmaps(name, rd->need_sync, rd->deferred_remove); -- if (!do_deferred(rd->deferred_remove) && -- dm_get_opencount(name)) { -+ if (rd->deferred_remove && dm_get_opencount(name)) { - condlog(2, "%s: map in use", name); - return DM_FLUSH_BUSY; - } -diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version -index e070f296..eb511749 100644 ---- a/libmultipath/libmultipath.version -+++ b/libmultipath/libmultipath.version -@@ -43,7 +43,7 @@ LIBMPATHCOMMON_1.0.0 { - put_multipath_config; - }; - --LIBMULTIPATH_23.0.0 { -+LIBMULTIPATH_24.0.0 { - global: - /* symbols referenced by multipath and multipathd */ - add_foreign; diff --git a/0038-libmultipath-use-bitwise-flags-for-map-flushing-API.patch b/0038-libmultipath-use-bitwise-flags-for-map-flushing-API.patch deleted file mode 100644 index ef922ec..0000000 --- a/0038-libmultipath-use-bitwise-flags-for-map-flushing-API.patch +++ /dev/null @@ -1,212 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 2 May 2024 18:38:24 +0200 -Subject: [PATCH] libmultipath: use bitwise flags for map flushing API - -Rather than passing 3 separate bool variables to _dm_flush_map(), -define bitwise flags to modify the function's behavior, and pass -these flags to called functions accordingly. - -This improves the readability of the code, function calls are -more expressive. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/devmapper.c | 68 +++++++++++++++++----------------------- - libmultipath/devmapper.h | 18 ++++++++--- - 2 files changed, 41 insertions(+), 45 deletions(-) - -diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c -index 2e7b2c64..a6a9c2b7 100644 ---- a/libmultipath/devmapper.c -+++ b/libmultipath/devmapper.c -@@ -53,9 +53,8 @@ static int dm_cancel_remove_partmaps(const char * mapname); - #define __DR_UNUSED__ __attribute__((unused)) - #endif - --static int dm_remove_partmaps (const char * mapname, int need_sync, -- int deferred_remove); --static int do_foreach_partmaps(const char * mapname, -+static int dm_remove_partmaps (const char *mapname, int flags); -+static int do_foreach_partmaps(const char *mapname, - int (*partmap_func)(const char *, void *), - void *data); - static int _dm_queue_if_no_path(const char *mapname, int enable); -@@ -439,9 +438,9 @@ int dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags) - } - - static int --dm_device_remove (const char *name, int needsync, int deferred_remove) { -- return dm_simplecmd(DM_DEVICE_REMOVE, name, 0, needsync, 0, -- deferred_remove); -+dm_device_remove (const char *name, int flags) { -+ return dm_simplecmd(DM_DEVICE_REMOVE, name, 0, flags & DMFL_NEED_SYNC, 0, -+ flags & DMFL_DEFERRED); - } - - static int -@@ -1061,8 +1060,7 @@ partmap_in_use(const char *name, void *data) - return 0; - } - --int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, -- int need_suspend, int retries) -+int _dm_flush_map (const char *mapname, int flags, int retries) - { - int r; - int queue_if_no_path = 0; -@@ -1080,10 +1078,10 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, - - /* If you aren't doing a deferred remove, make sure that no - * devices are in use */ -- if (!deferred_remove && partmap_in_use(mapname, NULL)) -+ if (!(flags & DMFL_DEFERRED) && partmap_in_use(mapname, NULL)) - return DM_FLUSH_BUSY; - -- if (need_suspend && -+ if ((flags & DMFL_SUSPEND) && - dm_get_map(mapname, &mapsize, ¶ms) == DMP_OK && - strstr(params, "queue_if_no_path")) { - if (!_dm_queue_if_no_path(mapname, 0)) -@@ -1095,22 +1093,22 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, - free(params); - params = NULL; - -- if ((r = dm_remove_partmaps(mapname, need_sync, deferred_remove))) -+ if ((r = dm_remove_partmaps(mapname, flags))) - return r; - -- if (!deferred_remove && dm_get_opencount(mapname)) { -+ if (!(flags & DMFL_DEFERRED) && dm_get_opencount(mapname)) { - condlog(2, "%s: map in use", mapname); - return DM_FLUSH_BUSY; - } - - do { -- if (need_suspend && queue_if_no_path != -1) -+ if ((flags & DMFL_SUSPEND) && queue_if_no_path != -1) - dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 0); - -- r = dm_device_remove(mapname, need_sync, deferred_remove); -+ r = dm_device_remove(mapname, flags); - - if (r) { -- if (deferred_remove && dm_map_present(mapname)) { -+ if ((flags & DMFL_DEFERRED) && dm_map_present(mapname)) { - condlog(4, "multipath map %s remove deferred", - mapname); - return DM_FLUSH_DEFERRED; -@@ -1124,7 +1122,7 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, - } else { - condlog(2, "failed to remove multipath map %s", - mapname); -- if (need_suspend && queue_if_no_path != -1) { -+ if ((flags & DMFL_SUSPEND) && queue_if_no_path != -1) { - dm_simplecmd_noflush(DM_DEVICE_RESUME, - mapname, udev_flags); - } -@@ -1139,27 +1137,18 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, - return DM_FLUSH_FAIL; - } - --#ifdef LIBDM_API_DEFERRED -- - int --dm_flush_map_nopaths(const char * mapname, int deferred_remove) -+dm_flush_map_nopaths(const char *mapname, int deferred_remove __DR_UNUSED__) - { -- return _dm_flush_map(mapname, 1, -- (deferred_remove == DEFERRED_REMOVE_ON || -- deferred_remove == DEFERRED_REMOVE_IN_PROGRESS), -- 0, 0); --} -- --#else -- --int --dm_flush_map_nopaths(const char * mapname, -- int deferred_remove __attribute__((unused))) --{ -- return _dm_flush_map(mapname, 1, 0, 0, 0); --} -+ int flags = DMFL_NEED_SYNC; - -+#ifdef LIBDM_API_DEFERRED -+ flags |= ((deferred_remove == DEFERRED_REMOVE_ON || -+ deferred_remove == DEFERRED_REMOVE_IN_PROGRESS) ? -+ DMFL_DEFERRED : 0); - #endif -+ return _dm_flush_map(mapname, flags, 0); -+} - - int dm_flush_maps (int retries) - { -@@ -1528,8 +1517,7 @@ out: - } - - struct remove_data { -- int need_sync; -- int deferred_remove; -+ int flags; - }; - - static int -@@ -1538,21 +1526,21 @@ remove_partmap(const char *name, void *data) - struct remove_data *rd = (struct remove_data *)data; - - if (dm_get_opencount(name)) { -- dm_remove_partmaps(name, rd->need_sync, rd->deferred_remove); -- if (rd->deferred_remove && dm_get_opencount(name)) { -+ dm_remove_partmaps(name, rd->flags); -+ if ((rd->flags & DMFL_DEFERRED) && dm_get_opencount(name)) { - condlog(2, "%s: map in use", name); - return DM_FLUSH_BUSY; - } - } - condlog(4, "partition map %s removed", name); -- dm_device_remove(name, rd->need_sync, rd->deferred_remove); -+ dm_device_remove(name, rd->flags); - return DM_FLUSH_OK; - } - - static int --dm_remove_partmaps (const char * mapname, int need_sync, int deferred_remove) -+dm_remove_partmaps (const char * mapname, int flags) - { -- struct remove_data rd = { need_sync, deferred_remove }; -+ struct remove_data rd = { flags }; - return do_foreach_partmaps(mapname, remove_partmap, &rd); - } - -diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h -index 93caa2aa..bb4a55a6 100644 ---- a/libmultipath/devmapper.h -+++ b/libmultipath/devmapper.h -@@ -58,12 +58,20 @@ enum { - }; - - int partmap_in_use(const char *name, void *data); --int _dm_flush_map (const char *, int, int, int, int); --int dm_flush_map_nopaths(const char * mapname, int deferred_remove); --#define dm_flush_map(mapname) _dm_flush_map(mapname, 1, 0, 0, 0) --#define dm_flush_map_nosync(mapname) _dm_flush_map(mapname, 0, 0, 0, 0) -+ -+enum { -+ DMFL_NONE = 0, -+ DMFL_NEED_SYNC = 1 << 0, -+ DMFL_DEFERRED = 1 << 1, -+ DMFL_SUSPEND = 1 << 2, -+}; -+ -+int _dm_flush_map (const char *mapname, int flags, int retries); -+#define dm_flush_map(mapname) _dm_flush_map(mapname, DMFL_NEED_SYNC, 0) -+#define dm_flush_map_nosync(mapname) _dm_flush_map(mapname, DMFL_NONE, 0) - #define dm_suspend_and_flush_map(mapname, retries) \ -- _dm_flush_map(mapname, 1, 0, 1, retries) -+ _dm_flush_map(mapname, DMFL_NEED_SYNC|DMFL_SUSPEND, retries) -+int dm_flush_map_nopaths(const char * mapname, int deferred_remove); - int dm_cancel_deferred_remove(struct multipath *mpp); - int dm_flush_maps (int retries); - int dm_fail_path(const char * mapname, char * path); diff --git a/0039-libmultipath-use-bitwise-flags-for-dm_simplecmd-API.patch b/0039-libmultipath-use-bitwise-flags-for-dm_simplecmd-API.patch deleted file mode 100644 index 1aee878..0000000 --- a/0039-libmultipath-use-bitwise-flags-for-dm_simplecmd-API.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 2 May 2024 18:45:17 +0200 -Subject: [PATCH] libmultipath: use bitwise flags for dm_simplecmd API - -Also use bitwise flags for dm_simplecmd() and its relatives. Again, -this makes the code more expressive and more readable, while -simplifying the function calls. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/devmapper.c | 26 +++++++++++++------------- - libmultipath/devmapper.h | 5 +++-- - 2 files changed, 16 insertions(+), 15 deletions(-) - -diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c -index a6a9c2b7..08bb3c51 100644 ---- a/libmultipath/devmapper.c -+++ b/libmultipath/devmapper.c -@@ -386,10 +386,9 @@ libmp_dm_task_create(int task) - } - - static int --dm_simplecmd (int task, const char *name, int no_flush, int need_sync, -- uint16_t udev_flags, int deferred_remove __DR_UNUSED__) { -+dm_simplecmd (int task, const char *name, int flags, uint16_t udev_flags) { - int r = 0; -- int udev_wait_flag = ((need_sync || udev_flags) && -+ int udev_wait_flag = (((flags & DMFL_NEED_SYNC) || udev_flags) && - (task == DM_DEVICE_RESUME || - task == DM_DEVICE_REMOVE)); - uint32_t cookie = 0; -@@ -404,11 +403,11 @@ dm_simplecmd (int task, const char *name, int no_flush, int need_sync, - dm_task_no_open_count(dmt); - dm_task_skip_lockfs(dmt); /* for DM_DEVICE_RESUME */ - #ifdef LIBDM_API_FLUSH -- if (no_flush) -+ if (flags & DMFL_NO_FLUSH) - dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ - #endif - #ifdef LIBDM_API_DEFERRED -- if (deferred_remove) -+ if (flags & DMFL_DEFERRED) - dm_task_deferred_remove(dmt); - #endif - if (udev_wait_flag && -@@ -429,18 +428,17 @@ out: - - int dm_simplecmd_flush (int task, const char *name, uint16_t udev_flags) - { -- return dm_simplecmd(task, name, 0, 1, udev_flags, 0); -+ return dm_simplecmd(task, name, DMFL_NEED_SYNC, udev_flags); - } - - int dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags) - { -- return dm_simplecmd(task, name, 1, 1, udev_flags, 0); -+ return dm_simplecmd(task, name, DMFL_NO_FLUSH|DMFL_NEED_SYNC, udev_flags); - } - - static int - dm_device_remove (const char *name, int flags) { -- return dm_simplecmd(DM_DEVICE_REMOVE, name, 0, flags & DMFL_NEED_SYNC, 0, -- flags & DMFL_DEFERRED); -+ return dm_simplecmd(DM_DEVICE_REMOVE, name, flags, 0); - } - - static int -@@ -594,8 +592,9 @@ int dm_addmap_reload(struct multipath *mpp, char *params, int flush) - params, ADDMAP_RO, 0); - } - if (r) -- r = dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, !flush, -- 1, udev_flags, 0); -+ r = dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, -+ DMFL_NEED_SYNC | (flush ? 0 : DMFL_NO_FLUSH), -+ udev_flags); - if (r) - return r; - -@@ -603,8 +602,9 @@ int dm_addmap_reload(struct multipath *mpp, char *params, int flush) - * drop the new table, so doing a second resume will try using - * the original table */ - if (dm_is_suspended(mpp->alias)) -- dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, !flush, 1, -- udev_flags, 0); -+ dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, -+ DMFL_NEED_SYNC | (flush ? 0 : DMFL_NO_FLUSH), -+ udev_flags); - return 0; - } - -diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h -index bb4a55a6..a242381e 100644 ---- a/libmultipath/devmapper.h -+++ b/libmultipath/devmapper.h -@@ -38,8 +38,8 @@ void skip_libmp_dm_init(void); - void libmp_dm_exit(void); - void libmp_udev_set_sync_support(int on); - struct dm_task *libmp_dm_task_create(int task); --int dm_simplecmd_flush (int, const char *, uint16_t); --int dm_simplecmd_noflush (int, const char *, uint16_t); -+int dm_simplecmd_flush (int task, const char *name, uint16_t udev_flags); -+int dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags); - int dm_addmap_create (struct multipath *mpp, char *params); - int dm_addmap_reload (struct multipath *mpp, char *params, int flush); - int dm_map_present (const char *); -@@ -64,6 +64,7 @@ enum { - DMFL_NEED_SYNC = 1 << 0, - DMFL_DEFERRED = 1 << 1, - DMFL_SUSPEND = 1 << 2, -+ DMFL_NO_FLUSH = 1 << 3, - }; - - int _dm_flush_map (const char *mapname, int flags, int retries); diff --git a/0040-libmultipath-add-argument-names-to-some-prototypes.patch b/0040-libmultipath-add-argument-names-to-some-prototypes.patch deleted file mode 100644 index 3244d55..0000000 --- a/0040-libmultipath-add-argument-names-to-some-prototypes.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 2 May 2024 18:46:42 +0200 -Subject: [PATCH] libmultipath: add argument names to some prototypes - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/devmapper.h | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h -index a242381e..19b79c5b 100644 ---- a/libmultipath/devmapper.h -+++ b/libmultipath/devmapper.h -@@ -42,12 +42,12 @@ int dm_simplecmd_flush (int task, const char *name, uint16_t udev_flags); - int dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags); - int dm_addmap_create (struct multipath *mpp, char *params); - int dm_addmap_reload (struct multipath *mpp, char *params, int flush); --int dm_map_present (const char *); -+int dm_map_present (const char *name); - int dm_map_present_by_uuid(const char *uuid); --int dm_get_map(const char *, unsigned long long *, char **); --int dm_get_status(const char *, char **); --int dm_type(const char *, char *); --int dm_is_mpath(const char *); -+int dm_get_map(const char *name, unsigned long long *size, char **outparams); -+int dm_get_status(const char *name, char **outstatus); -+int dm_type(const char *name, char *type); -+int dm_is_mpath(const char *name); - - enum { - DM_FLUSH_OK = 0, diff --git a/0041-libmultipath-bump-version-to-0.9.9.patch b/0041-libmultipath-bump-version-to-0.9.9.patch deleted file mode 100644 index 890b047..0000000 --- a/0041-libmultipath-bump-version-to-0.9.9.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 3 May 2024 22:09:10 +0200 -Subject: [PATCH] libmultipath: bump version to 0.9.9 - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - libmultipath/version.h | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/libmultipath/version.h b/libmultipath/version.h -index e102975f..271d8e74 100644 ---- a/libmultipath/version.h -+++ b/libmultipath/version.h -@@ -20,9 +20,9 @@ - #ifndef _VERSION_H - #define _VERSION_H - --#define VERSION_CODE 0x000908 -+#define VERSION_CODE 0x000909 - /* MMDDYY, in hex */ --#define DATE_CODE 0x020F18 -+#define DATE_CODE 0x050318 - - #define PROG "multipath-tools" - diff --git a/0042-GitHub-Workflows-native.yaml-run-for-Fedora-40.patch b/0042-GitHub-Workflows-native.yaml-run-for-Fedora-40.patch deleted file mode 100644 index 47c3949..0000000 --- a/0042-GitHub-Workflows-native.yaml-run-for-Fedora-40.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 3 May 2024 22:28:34 +0200 -Subject: [PATCH] GitHub Workflows: native.yaml: run for Fedora 40 - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - .github/workflows/native.yaml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml -index 0ef9df94..a062845e 100644 ---- a/.github/workflows/native.yaml -+++ b/.github/workflows/native.yaml -@@ -33,7 +33,7 @@ jobs: - - debian-buster - - debian-bullseye - - debian-bookworm -- - fedora-39 -+ - fedora-40 - - opensuse-leap - container: ghcr.io/mwilck/multipath-build-${{ matrix.os }} - steps: diff --git a/0043-update-NEWS.md.patch b/0043-update-NEWS.md.patch deleted file mode 100644 index 4edc69d..0000000 --- a/0043-update-NEWS.md.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 3 May 2024 23:11:48 +0200 -Subject: [PATCH] update NEWS.md - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - .github/actions/spelling/expect.txt | 3 ++ - .github/actions/spelling/patterns.txt | 3 +- - NEWS.md | 62 +++++++++++++++++++++++++++ - 3 files changed, 67 insertions(+), 1 deletion(-) - -diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt -index fc9f22f8..bdfce83a 100644 ---- a/.github/actions/spelling/expect.txt -+++ b/.github/actions/spelling/expect.txt -@@ -17,6 +17,7 @@ blkid - bmarzins - cciss - CFLAGS -+cgroups - christophe - clangd - clariion -@@ -67,6 +68,7 @@ fulldescr - gcc - getprkey - getprstatus -+getrlimit - getuid - github - GPT -@@ -170,6 +172,7 @@ rootprefixdir - rpmbuild - rport - rtpi -+rtprio - sas - sbp - scsi -diff --git a/.github/actions/spelling/patterns.txt b/.github/actions/spelling/patterns.txt -index 858faee6..aa361654 100644 ---- a/.github/actions/spelling/patterns.txt -+++ b/.github/actions/spelling/patterns.txt -@@ -22,7 +22,7 @@ - \bdmmp_pgs\b - \bdmmp_mpath_kdev_name_get\b - \bfast_io_fail_tmo\b --\bLimitRTPRIO\b -+\bLimitRTPRIO=?\b - \bmax_fds\b - \bmissing_uev_wait_timeout\b - \bMPATH_MAX_PARAM_LEN\b -@@ -87,6 +87,7 @@ - \bprin_resvdescr\b - \bprout_param_descriptor\b - \brq_servact\b -+\bRLIMIT_RTPRIO\b - \bSCHED_RT_PRIO\b - \bssize_t\b - \btrnptid_list\b -diff --git a/NEWS.md b/NEWS.md -index 0b094b98..4c54afa0 100644 ---- a/NEWS.md -+++ b/NEWS.md -@@ -1,5 +1,67 @@ - # multipath-tools Release Notes - -+## multipath-tools 0.9.9, 2024/05 -+ -+### User-Visible Changes -+ -+* *Changed realtime scheduling:* multipathd used to run at the highest possible -+ realtime priority, 99. This has always been excessive, and on some -+ distributions (e.g. RHEL 8), it hasn't worked at all. It is now possible to -+ set multipathd's real time scheduling by setting the hard limit for -+ `RLIMIT_RTPRIO` (see getrlimit(2)), which corresponds to the `rtprio` -+ setting in limits.conf and to `LimitRTPRIO=` in the systemd unit file. The -+ default in the systemd unit file has been set to 10. If the limit is set to -+ 0, multipathd doesn't attempt to enable real-time scheduling. -+ Otherwise, it will try to set the scheduling priority to the given value. -+ Fixes [#82](https://github.com/opensvc/multipath-tools/issues/82). -+* *Changed normal scheduling:* In order to make sure that multipathd has -+ sufficient priority even if real time scheduling is switched off, the -+ `CPUWeight=` setting in the unit file is set to 1000. This is necessary -+ because regular nice(2) values have no effect in systems with cgroups enabled. -+* *Changed handling of `max_sectors_kb` configuration:* multipathd applies -+ the `max_sectors_kb` setting only during map creation, or when a new path is -+ added to an existing map. The kernel makes sure that the multipath device -+ never has a larger `max_sectors_kb` value than any of its configured path -+ devices. The reason for this change is that applying `max_sectors_kb` on -+ live maps can cause IO errors and data loss in rare situations. -+ It can now happen that some path devices have a higher `max_sectors_kb` -+ value than the map; this is not an error. It is not possible any more to -+ decrease `max_sectors_kb` in `multipath.conf` and run `multipathd -+ reconfigure` to "apply" this setting to the map and its paths. If decreasing -+ the IO size is necessary, either destroy and recreate the map, or remove one -+ path with `multipathd del path $PATH`, run `multipathd reconfigure`, and -+ re-add the path with `multipathd add path $PATH`. -+* *New wildcard %k:* The wildcard `%k` for `max_sectors_kb` has been added to -+ the `multipathd show paths format` and `multipathd show maps format` -+ commands. -+* *Changed semantics of flush_on_last_del:* The `flush_on_last_del` option -+ now takes the values `always` , `unused`, or `never`. `yes` and `no` -+ are still accepted as aliases for `always` and `unused`, respectively. -+ `always` means that when all paths for a multipath map have been removed, -+ *outstanding IO will be failed* and the map will be deleted. `unused` means -+ that this will only happen when the map is not mounted or otherwise opened. -+ `never` means the map will only be removed if the `queue_if_no_path` -+ feature is off. -+ This fixes a problem where multipathd could hang when the last path of -+ a queueing map was deleted. -+ -+### Other major changes -+ -+* Adapted the dm-mpath udev rules such that they will work with the modified -+ device mapper udev rules (`DM_UDEV_RULES_VSN==3`, lvm2 > 2.03.22). They are -+ still compatible with older versions of the device-mapper udev rules. -+ -+### Bug fixes -+ -+* Fixed misspelled DM_UDEV_DISABLE_OTHER_RULES_FLAG in 11-dm-mpath.rules -+* Always use `glibc_basename()` to avoid some issues with MUSL libc. -+ Fixes [#84](https://github.com/opensvc/multipath-tools/pull/84). -+ -+### Other -+ -+* Build: added `TGTDIR` option to simplify building for a different target -+ host (see README.md). -+ - ## multipath-tools 0.9.8, 2024/02 - - ### User-Visible Changes diff --git a/0044-multipath.conf.5.in-fix-man-page-date.patch b/0044-multipath.conf.5.in-fix-man-page-date.patch deleted file mode 100644 index c9f2d5d..0000000 --- a/0044-multipath.conf.5.in-fix-man-page-date.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 3 May 2024 23:22:50 +0200 -Subject: [PATCH] multipath.conf.5.in: fix man page date - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - multipath/multipath.conf.5.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in -index 1d3d53bb..dacb9b0e 100644 ---- a/multipath/multipath.conf.5.in -+++ b/multipath/multipath.conf.5.in -@@ -6,7 +6,7 @@ - .\" Update the date below if you make any significant change. - .\" ---------------------------------------------------------------------------- - . --.TH MULTIPATH.CONF 5 2024-04-17 Linux -+.TH MULTIPATH.CONF 5 2024-04-25 Linux - . - . - .\" ---------------------------------------------------------------------------- diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 22e6ad7..b898339 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,5 +1,5 @@ Name: device-mapper-multipath -Version: 0.9.8 +Version: 0.9.9 Release: 1%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 @@ -7,66 +7,22 @@ URL: http://christophe.varoqui.free.fr/ # The source for this package was pulled from upstream's git repo. Use the # following command to generate the tarball -# curl -L https://github.com/opensvc/multipath-tools/archive/0.9.8.tar.gz -o multipath-tools-0.9.8.tgz -Source0: multipath-tools-0.9.8.tgz +# curl -L https://github.com/opensvc/multipath-tools/archive/0.9.9.tar.gz -o multipath-tools-0.9.9.tgz +Source0: multipath-tools-0.9.9.tgz Source1: multipath.conf -Patch0001: 0001-11-dm-mpath.rules-fix-misspelled-DM_UDEV_DISABLE_OTH.patch -Patch0002: 0002-multipathd-use-condlog-level-for-setscheduler-error-.patch -Patch0003: 0003-multipathd-make-multipathd-scheduling-configurable.patch -Patch0004: 0004-libmpathutil-really-always-use-glibc-basename.patch -Patch0005: 0005-multipathd-make-multipathd-set-priority-to-RLIMIT_RT.patch -Patch0006: 0006-multipathd-Set-CPUWeight-to-1000-and-LimitRTPRIO-to-.patch -Patch0007: 0007-11-dm-mpath.rules-explain-logic-for-device-becoming-.patch -Patch0008: 0008-11-dm-mpath.rules-don-t-import-DM_NOSCAN-from-udev-d.patch -Patch0009: 0009-11-dm-mpath.rules-don-t-import-ID_FS_VERSION-from-ud.patch -Patch0010: 0010-11-dm-mpath.rules-adapt-MPATH_DEVICE_READY-0-logic-t.patch -Patch0011: 0011-11-dm-mpath.rules-adapt-coldplug-event-handling-ro-1.patch -Patch0012: 0012-11-dm-mpath.rules-don-t-import-properties-with-new-1.patch -Patch0013: 0013-11-dm-mpath.rules-replace-DM_SUSPENDED-by-.DM_SUSPEN.patch -Patch0014: 0014-11-dm-mpath.rules-replace-DM_NOSCAN-by-.DM_NOSCAN.patch -Patch0015: 0015-11-dm-mpath.rules-simplify-PATH_FAILED-case.patch -Patch0016: 0016-11-dm-mpath.rules-make-label-names-more-intuitive.patch -Patch0017: 0017-kpartx.rules-ignore-DM_SUSPENDED.patch -Patch0018: 0018-multipath-tools-tests-fix-CI-failures-on-arm-v7-with.patch -Patch0019: 0019-multipath-tools-tests-fix-CI-failures-with-clang-on-.patch -Patch0020: 0020-GitHub-actions-fixes-for-spelling-CI.patch -Patch0021: 0021-GitHub-workflows-run-workflows-if-workflow-file-has-.patch -Patch0022: 0022-multipath-tools-add-TGTDIR-option.patch -Patch0023: 0023-libmultipath-move-get_udev_for_mpp-to-sysfs.c.patch -Patch0024: 0024-libmultipath-add-mp_find_path_by_devt.patch -Patch0025: 0025-Revert-libmultipath-fix-max_sectors_kb-on-adding-pat.patch -Patch0026: 0026-libmultipath-Only-set-max_sectors_kb-on-map-creation.patch -Patch0027: 0027-libmultipath-set-max_sectors_kb-in-adopt_paths.patch -Patch0028: 0028-libmultipath-add-wildcard-k-for-printing-max_sectors.patch -Patch0029: 0029-multipath.conf-5-update-documentation-for-max_sector.patch -Patch0030: 0030-multipath-tools-simplify-comment-in-hwtable.patch -Patch0031: 0031-multipath-tools-unify-text-in-multipath.conf.5.patch -Patch0032: 0032-multipath-tools-update-man-pages-dates.patch -Patch0033: 0033-libmultipath-export-partmap_in_use.patch -Patch0034: 0034-libmultipath-change-flush_on_last_del-to-fix-a-multi.patch -Patch0035: 0035-libmultipath-remove-redundant-config-option-from-Inf.patch -Patch0036: 0036-libmultipath-pad-dev_loss_tmo-to-avoid-race-with-no_.patch -Patch0037: 0037-libmultipath-fix-deferred_remove-function-arguments.patch -Patch0038: 0038-libmultipath-use-bitwise-flags-for-map-flushing-API.patch -Patch0039: 0039-libmultipath-use-bitwise-flags-for-dm_simplecmd-API.patch -Patch0040: 0040-libmultipath-add-argument-names-to-some-prototypes.patch -Patch0041: 0041-libmultipath-bump-version-to-0.9.9.patch -Patch0042: 0042-GitHub-Workflows-native.yaml-run-for-Fedora-40.patch -Patch0043: 0043-update-NEWS.md.patch -Patch0044: 0044-multipath.conf.5.in-fix-man-page-date.patch -Patch0045: 0045-RH-fixup-udev-rules-for-redhat.patch -Patch0046: 0046-RH-Remove-the-property-blacklist-exception-builtin.patch -Patch0047: 0047-RH-don-t-start-without-a-config-file.patch -Patch0048: 0048-RH-Fix-nvme-function-missing-argument.patch -Patch0049: 0049-RH-use-rpm-optflags-if-present.patch -Patch0050: 0050-RH-add-mpathconf.patch -Patch0051: 0051-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch -Patch0052: 0052-RH-reset-default-find_mutipaths-value-to-off.patch -Patch0053: 0053-RH-attempt-to-get-ANA-info-via-sysfs-first.patch -Patch0054: 0054-RH-make-parse_vpd_pg83-match-scsi_id-output.patch -Patch0055: 0055-RH-add-scsi-device-handlers-to-modules-load.d.patch -Patch0056: 0056-RH-compile-with-libreadline-support.patch -Patch0057: 0057-RH-Add-mpathcleanup.patch +Patch0001: 0001-RH-fixup-udev-rules-for-redhat.patch +Patch0002: 0002-RH-Remove-the-property-blacklist-exception-builtin.patch +Patch0003: 0003-RH-don-t-start-without-a-config-file.patch +Patch0004: 0004-RH-Fix-nvme-function-missing-argument.patch +Patch0005: 0005-RH-use-rpm-optflags-if-present.patch +Patch0006: 0006-RH-add-mpathconf.patch +Patch0007: 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +Patch0008: 0008-RH-reset-default-find_mutipaths-value-to-off.patch +Patch0009: 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch +Patch0010: 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +Patch0011: 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch +Patch0012: 0012-RH-compile-with-libreadline-support.patch +Patch0013: 0013-RH-Add-mpathcleanup.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -153,7 +109,7 @@ This package contains the files needed to develop applications that use device-mapper-multipath's libdmmp C API library %prep -%autosetup -n multipath-tools-0.9.8 -p1 +%autosetup -n multipath-tools-0.9.9 -p1 cp %{SOURCE1} . %build @@ -275,6 +231,12 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Thu Jun 13 2024 Benjamin Marzinski - 0.9.9-1 +- Update source to upstream version 0.9.9 + * Previous patches 0001-0044 are included in the source tarball +- Rename redhat patches + * Previous patches 0045-0057 are now patches 0001-0013 + * Mon May 20 2024 Benjamin Marzinski - 0.9.8-1 - Update source to upstream version 0.9.8 plus latest staging branch * Previous patches 0014 & 0015 are included in the source tarball diff --git a/sources b/sources index b0337e2..f098bc9 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (multipath-tools-0.9.8.tgz) = 4d73bcf6bce769a829c306c609b206ddba65a708620f458106e406dd18d12f9a9d97f400662daa8e6a75c9fdf7decb6dcbda92cb807b6c53522c7b4b2795b627 +SHA512 (multipath-tools-0.9.9.tgz) = 65b5d5c48792f6041d700968c87675bc349ede475fe178a203814dbb0325f69895782a22c5c35f6c0157f694951714de9e83cc1464a6c062d911a58faed8960a SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942 From 4e4233829d041b14b0773e59b57ed1aca0de9b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 9 Jul 2024 12:58:25 +0200 Subject: [PATCH 14/29] Rebuilt for the bin-sbin merge https://fedoraproject.org/wiki/Changes/Unify_bin_and_sbin --- device-mapper-multipath.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index b898339..2897380 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.9.9 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ @@ -231,6 +231,9 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Tue Jul 09 2024 Zbigniew Jฤ™drzejewski-Szmek - 0.9.9-2 +- Rebuilt for the bin-sbin merge + * Thu Jun 13 2024 Benjamin Marzinski - 0.9.9-1 - Update source to upstream version 0.9.9 * Previous patches 0001-0044 are included in the source tarball From 3cde646adee765e1e8dca298f73db057039f317d Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Wed, 17 Jul 2024 20:51:42 +0000 Subject: [PATCH 15/29] Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild --- device-mapper-multipath.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 2897380..247501d 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.9.9 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ @@ -231,6 +231,9 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Wed Jul 17 2024 Fedora Release Engineering - 0.9.9-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild + * Tue Jul 09 2024 Zbigniew Jฤ™drzejewski-Szmek - 0.9.9-2 - Rebuilt for the bin-sbin merge From 519bd15b4dd30fadd1310fae97d8189ea061cae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Such=C3=BD?= Date: Thu, 25 Jul 2024 11:35:35 +0200 Subject: [PATCH 16/29] convert GPLv3+ license to SPDX This is part of https://fedoraproject.org/wiki/Changes/SPDX_Licenses_Phase_4 --- device-mapper-multipath.spec | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 247501d..fb448ed 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.9.9 -Release: 3%{?dist} +Release: 4%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ @@ -90,7 +90,8 @@ kpartx manages partition creation and removal for device-mapper devices. %package -n libdmmp Summary: device-mapper-multipath C API library -License: GPLv3+ +# Automatically converted from old format: GPLv3+ - review is highly recommended. +License: GPL-3.0-or-later Requires: json-c Requires: %{name} = %{version}-%{release} Requires: %{name}-libs = %{version}-%{release} @@ -231,6 +232,9 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Thu Jul 25 2024 Miroslav Suchรฝ - 0.9.9-4 +- convert license to SPDX + * Wed Jul 17 2024 Fedora Release Engineering - 0.9.9-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild From 354f1e7cfbad435492ff429f5a3e98e713a2530b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Such=C3=BD?= Date: Mon, 29 Jul 2024 10:25:45 +0200 Subject: [PATCH 17/29] convert GPLv2 license to SPDX This is part of https://fedoraproject.org/wiki/Changes/SPDX_Licenses_Phase_4 --- device-mapper-multipath.spec | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index fb448ed..6cd8a6d 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,8 +1,9 @@ Name: device-mapper-multipath Version: 0.9.9 -Release: 4%{?dist} +Release: 5%{?dist} Summary: Tools to manage multipath devices using device-mapper -License: GPLv2 +# Automatically converted from old format: GPLv2 - review is highly recommended. +License: GPL-2.0-only URL: http://christophe.varoqui.free.fr/ # The source for this package was pulled from upstream's git repo. Use the @@ -232,6 +233,9 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Mon Jul 29 2024 Miroslav Suchรฝ - 0.9.9-5 +- convert license to SPDX + * Thu Jul 25 2024 Miroslav Suchรฝ - 0.9.9-4 - convert license to SPDX From 0c6649fa32544f07677c7495c8269bd0d95cc62b Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Fri, 9 Aug 2024 16:00:03 -0400 Subject: [PATCH 18/29] device-mapper-multipath-0.9.9-6 Add 0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch * multipath features tracking on failed removes --- ...tipathd-fix-flush-check-in-flush_map.patch | 28 +++++++++++++++++++ device-mapper-multipath.spec | 7 ++++- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 0014-multipathd-fix-flush-check-in-flush_map.patch diff --git a/0014-multipathd-fix-flush-check-in-flush_map.patch b/0014-multipathd-fix-flush-check-in-flush_map.patch new file mode 100644 index 0000000..3ff957d --- /dev/null +++ b/0014-multipathd-fix-flush-check-in-flush_map.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 5 Jun 2024 19:22:48 -0400 +Subject: [PATCH] multipathd: fix flush check in flush_map() + +Forgot the comparison in the "if" statement. + +Fixes 8a3898339 ("multipathd: sync features on flush_map failure corner case") + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + multipathd/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index 09286dd0..58afe14a 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -813,7 +813,7 @@ flush_map(struct multipath * mpp, struct vectors * vecs) + { + int r = dm_suspend_and_flush_map(mpp->alias, 0); + if (r != DM_FLUSH_OK) { +- if (DM_FLUSH_FAIL_CANT_RESTORE) ++ if (r == DM_FLUSH_FAIL_CANT_RESTORE) + remove_feature(&mpp->features, "queue_if_no_path"); + condlog(0, "%s: can't flush", mpp->alias); + return r; diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 6cd8a6d..9e74d46 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.9.9 -Release: 5%{?dist} +Release: 6%{?dist} Summary: Tools to manage multipath devices using device-mapper # Automatically converted from old format: GPLv2 - review is highly recommended. License: GPL-2.0-only @@ -24,6 +24,7 @@ Patch0010: 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch Patch0011: 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch Patch0012: 0012-RH-compile-with-libreadline-support.patch Patch0013: 0013-RH-Add-mpathcleanup.patch +Patch0014: 0014-multipathd-fix-flush-check-in-flush_map.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -233,6 +234,10 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Fri Aug 9 2024 Benjamin Marzinski - 0.9.9-6 +- Add 0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch + * multipath features tracking on failed removes + * Mon Jul 29 2024 Miroslav Suchรฝ - 0.9.9-5 - convert license to SPDX From 94144d9276e41dd879043596114d248db042dbc5 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Thu, 29 Aug 2024 15:20:13 -0400 Subject: [PATCH 19/29] device-mapper-multipath-0.10.0-1 Update source to upstream version 0.9.9 * Previous patch 0014-multipathd-fix-flush-check-in-flush_map.patch is included in the source tarball Rebase redhat patches --- .gitignore | 1 + 0001-RH-fixup-udev-rules-for-redhat.patch | 20 ++++----- ...property-blacklist-exception-builtin.patch | 8 ++-- ...RH-don-t-start-without-a-config-file.patch | 16 +++---- ...H-Fix-nvme-function-missing-argument.patch | 2 +- 0005-RH-use-rpm-optflags-if-present.patch | 30 ++++++++----- 0006-RH-add-mpathconf.patch | 43 +++++++++++++++---- ...om-kernel-cmdline-mpath.wwids-with-A.patch | 16 +++---- ...-default-find_mutipaths-value-to-off.patch | 8 ++-- ...-parse_vpd_pg83-match-scsi_id-output.patch | 2 +- ...si-device-handlers-to-modules-load.d.patch | 2 +- ...-RH-compile-with-libreadline-support.patch | 2 +- ...tipathd-fix-flush-check-in-flush_map.patch | 28 ------------ device-mapper-multipath.spec | 17 +++++--- sources | 2 +- 15 files changed, 105 insertions(+), 92 deletions(-) delete mode 100644 0014-multipathd-fix-flush-check-in-flush_map.patch diff --git a/.gitignore b/.gitignore index 3bea72e..908094d 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ multipath-tools-091027.tar.gz /multipath-tools-0.9.7.tgz /multipath-tools-0.9.8.tgz /multipath-tools-0.9.9.tgz +/multipath-tools-0.10.0.tgz diff --git a/0001-RH-fixup-udev-rules-for-redhat.patch b/0001-RH-fixup-udev-rules-for-redhat.patch index d78919e..0645240 100644 --- a/0001-RH-fixup-udev-rules-for-redhat.patch +++ b/0001-RH-fixup-udev-rules-for-redhat.patch @@ -9,13 +9,13 @@ different naming scheme for partitions than SuSE. Signed-off-by: Benjamin Marzinski --- - Makefile.inc | 2 +- - kpartx/kpartx.rules | 2 +- - multipath/Makefile | 4 ++-- + Makefile.inc | 2 +- + kpartx/kpartx.rules.in | 2 +- + multipath/Makefile | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile.inc b/Makefile.inc -index 81b86cd8..33dbb99c 100644 +index 729618bd..81cb61d2 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -34,7 +34,7 @@ endif @@ -27,16 +27,16 @@ index 81b86cd8..33dbb99c 100644 # Prefix for non-essential libraries (libdmmp) usr_prefix := $(if $(prefix),$(prefix),/usr) # Prefix for configuration files (multipath.conf) -diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules -index 8dd3369c..7c3c7524 100644 ---- a/kpartx/kpartx.rules -+++ b/kpartx/kpartx.rules +diff --git a/kpartx/kpartx.rules.in b/kpartx/kpartx.rules.in +index 9d879609..2049eb8f 100644 +--- a/kpartx/kpartx.rules.in ++++ b/kpartx/kpartx.rules.in @@ -39,6 +39,6 @@ LABEL="mpath_kpartx_end" GOTO="kpartx_end" LABEL="run_kpartx" --RUN+="/sbin/kpartx -un -p -part /dev/$name" -+RUN+="/sbin/kpartx -un /dev/$name" +-RUN+="@BINDIR@/kpartx -un -p -part /dev/$name" ++RUN+="@BINDIR@/kpartx -un /dev/$name" LABEL="kpartx_end" diff --git a/multipath/Makefile b/multipath/Makefile diff --git a/0002-RH-Remove-the-property-blacklist-exception-builtin.patch b/0002-RH-Remove-the-property-blacklist-exception-builtin.patch index b039539..a74e6c2 100644 --- a/0002-RH-Remove-the-property-blacklist-exception-builtin.patch +++ b/0002-RH-Remove-the-property-blacklist-exception-builtin.patch @@ -19,7 +19,7 @@ Signed-off-by: Benjamin Marzinski 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c -index 75100b20..0b212078 100644 +index 17e1b54a..10d13e98 100644 --- a/libmultipath/blacklist.c +++ b/libmultipath/blacklist.c @@ -230,8 +230,6 @@ setup_default_blist (struct config * conf) @@ -42,10 +42,10 @@ index 75100b20..0b212078 100644 udev_device_get_properties_list_entry(udev)) { diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in -index dacb9b0e..645e8f88 100644 +index 4388baad..af9fbb96 100644 --- a/multipath/multipath.conf.5.in +++ b/multipath/multipath.conf.5.in -@@ -1468,9 +1468,14 @@ keywords. Both are regular expressions. For a full description of these keywords +@@ -1469,9 +1469,14 @@ keywords. Both are regular expressions. For a full description of these keywords Regular expression for an udev property. All devices that have matching udev properties will be excluded/included. The handling of the \fIproperty\fR keyword is special, @@ -61,7 +61,7 @@ index dacb9b0e..645e8f88 100644 . .RS .PP -@@ -1481,10 +1486,6 @@ Blacklisting by missing properties is only applied to devices which do have the +@@ -1482,10 +1487,6 @@ Blacklisting by missing properties is only applied to devices which do have the property specified by \fIuid_attribute\fR (e.g. \fIID_SERIAL\fR) set. Previously, it was applied to every device, possibly causing devices to be blacklisted because of temporary I/O error conditions. diff --git a/0003-RH-don-t-start-without-a-config-file.patch b/0003-RH-don-t-start-without-a-config-file.patch index 267ffa7..02827df 100644 --- a/0003-RH-don-t-start-without-a-config-file.patch +++ b/0003-RH-don-t-start-without-a-config-file.patch @@ -22,10 +22,10 @@ Signed-off-by: Benjamin Marzinski 7 files changed, 25 insertions(+) diff --git a/libmultipath/config.c b/libmultipath/config.c -index 83fa7369..002027a7 100644 +index 0e3a5cc1..80f61914 100644 --- a/libmultipath/config.c +++ b/libmultipath/config.c -@@ -959,6 +959,19 @@ int _init_config (const char *file, struct config *conf) +@@ -959,6 +959,19 @@ int init_config__ (const char *file, struct config *conf) } factorize_hwtable(conf->hwtable, builtin_hwtable_size, file); validate_pctable(conf->overrides, 0, file); @@ -46,7 +46,7 @@ index 83fa7369..002027a7 100644 conf->processed_main_config = 1; diff --git a/libmultipath/config.h b/libmultipath/config.h -index 384193ab..158cebf0 100644 +index 94cdf252..534b6142 100644 --- a/libmultipath/config.h +++ b/libmultipath/config.h @@ -10,6 +10,7 @@ @@ -58,10 +58,10 @@ index 384193ab..158cebf0 100644 enum devtypes { DEV_NONE, diff --git a/multipath/main.c b/multipath/main.c -index ce702e7f..c21e3e0b 100644 +index 28e3a055..346acb61 100644 --- a/multipath/main.c +++ b/multipath/main.c -@@ -842,11 +842,14 @@ main (int argc, char *argv[]) +@@ -843,11 +843,14 @@ main (int argc, char *argv[]) char *dev = NULL; struct config *conf; bool enable_foreign = false; @@ -76,7 +76,7 @@ index ce702e7f..c21e3e0b 100644 if (init_config(DEFAULT_CONFIGFILE)) exit(RTVL_FAIL); if (atexit(uninit_config)) -@@ -1097,6 +1100,9 @@ main (int argc, char *argv[]) +@@ -1101,6 +1104,9 @@ main (int argc, char *argv[]) while ((r = configure(conf, cmd, dev_type, dev)) == RTVL_RETRY) condlog(3, "restart multipath configuration process"); @@ -87,7 +87,7 @@ index ce702e7f..c21e3e0b 100644 put_multipath_config(conf); if (dev) diff --git a/multipath/multipath.rules.in b/multipath/multipath.rules.in -index 780bf852..2c518378 100644 +index 2ac1972f..cc248231 100644 --- a/multipath/multipath.rules.in +++ b/multipath/multipath.rules.in @@ -9,6 +9,7 @@ IMPORT{cmdline}="nompath" @@ -112,7 +112,7 @@ index 7bc8806e..315884eb 100644 . .\" ---------------------------------------------------------------------------- diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in -index a63ddd9a..01ceff7d 100644 +index 646001e6..72e44849 100644 --- a/multipathd/multipathd.service.in +++ b/multipathd/multipathd.service.in @@ -6,6 +6,7 @@ Wants=systemd-udevd-kernel.socket @MODPROBE_UNIT@ diff --git a/0004-RH-Fix-nvme-function-missing-argument.patch b/0004-RH-Fix-nvme-function-missing-argument.patch index ced7159..74b7b53 100644 --- a/0004-RH-Fix-nvme-function-missing-argument.patch +++ b/0004-RH-Fix-nvme-function-missing-argument.patch @@ -12,7 +12,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmultipath/nvme/argconfig.h b/libmultipath/nvme/argconfig.h -index adb192b6..bfd10ef8 100644 +index e6c54453..0c6c9439 100644 --- a/libmultipath/nvme/argconfig.h +++ b/libmultipath/nvme/argconfig.h @@ -76,7 +76,7 @@ struct argconfig_commandline_options { diff --git a/0005-RH-use-rpm-optflags-if-present.patch b/0005-RH-use-rpm-optflags-if-present.patch index 0f354e7..3f115c1 100644 --- a/0005-RH-use-rpm-optflags-if-present.patch +++ b/0005-RH-use-rpm-optflags-if-present.patch @@ -9,19 +9,18 @@ still being generic. Signed-off-by: Benjamin Marzinski --- - Makefile.inc | 22 +++++++++++++++++----- - 1 file changed, 17 insertions(+), 5 deletions(-) + Makefile.inc | 25 ++++++++++++++++++------- + 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/Makefile.inc b/Makefile.inc -index 33dbb99c..94e0ec85 100644 +index 81cb61d2..35334a0c 100644 --- a/Makefile.inc +++ b/Makefile.inc -@@ -95,11 +95,23 @@ SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo +@@ -99,28 +99,39 @@ SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo MODPROBE_UNIT := $(shell test "0$(SYSTEMD)" -lt 245 2>/dev/null || \ echo "modprobe@dm_multipath.service") -OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4 --WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implicit-int \ +ifndef RPM_OPT_FLAGS + OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4 \ + -Wall $(FORTIFY_OPT) -fexceptions -grecord-gcc-switches \ @@ -35,16 +34,27 @@ index 33dbb99c..94e0ec85 100644 +else + OPTFLAGS := $(RPM_OPT_FLAGS) --param=ssp-buffer-size=4 +endif -+WARNFLAGS := -Werror -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implicit-int \ - -Werror=implicit-function-declaration -Werror=format-security \ -- $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) + + # Set WARN_ONLY=1 to avoid compilation erroring out due to warnings. Useful during development. + WARN_ONLY := + ERROR := $(if $(WARN_ONLY),,error=) + WERROR := $(if $(WARN_ONLY),,-Werror) +-WARNFLAGS := $(WERROR) -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -W$(ERROR)implicit-int \ ++WARNFLAGS := $(WERROR) -Wextra -Wformat=2 $(WFORMATOVERFLOW) -W$(ERROR)implicit-int \ + -W$(ERROR)implicit-function-declaration -W$(ERROR)format-security \ +- $(WNOCLOBBERED) -W$(ERROR)cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) ++ $(WNOCLOBBERED) -W$(ERROR)cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) -Wstrict-prototypes + -CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \ -+ $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) -Wstrict-prototypes +CPPFLAGS := $(CPPFLAGS) $(D_URCU_VERSION) \ -D_FILE_OFFSET_BITS=64 \ -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(TGTDIR)$(plugindir)\" \ -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(TGTDIR)$(configdir)\" \ -@@ -109,7 +121,7 @@ CFLAGS := -std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe + -DDEFAULT_CONFIGFILE=\"$(TGTDIR)$(configfile)\" -DSTATE_DIR=\"$(TGTDIR)$(statedir)\" \ + -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP +-CFLAGS := -std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \ +- -fexceptions ++CFLAGS := -std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe BIN_CFLAGS := -fPIE -DPIE LIB_CFLAGS := -fPIC SHARED_FLAGS := -shared diff --git a/0006-RH-add-mpathconf.patch b/0006-RH-add-mpathconf.patch index fd65e34..2ae48f3 100644 --- a/0006-RH-add-mpathconf.patch +++ b/0006-RH-add-mpathconf.patch @@ -13,19 +13,44 @@ a single command. Co-authored-by: Paul Donohue Signed-off-by: Benjamin Marzinski --- - libmultipath/config.c | 2 + - multipath/Makefile | 4 + - multipath/mpathconf | 658 ++++++++++++++++++++++++++++++++++++++++++ - multipath/mpathconf.8 | 151 ++++++++++ - 4 files changed, 815 insertions(+) + .github/actions/spelling/expect.txt | 3 + + libmultipath/config.c | 2 + + multipath/Makefile | 4 + + multipath/mpathconf | 658 ++++++++++++++++++++++++++++ + multipath/mpathconf.8 | 151 +++++++ + 5 files changed, 818 insertions(+) create mode 100644 multipath/mpathconf create mode 100644 multipath/mpathconf.8 +diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt +index 934f582e..61351583 100644 +--- a/.github/actions/spelling/expect.txt ++++ b/.github/actions/spelling/expect.txt +@@ -124,9 +124,11 @@ lvmteam + Marzinski + mpath + mpathb ++mpathconf + mpathpersist + mpathvalid + msecs ++multipathable + multipathc + multipathd + multipathed +@@ -144,6 +146,7 @@ ontap + OOM + opensvc + OPTFLAGS ++outfile + paramp + partx + pathgroup diff --git a/libmultipath/config.c b/libmultipath/config.c -index 002027a7..3d5943d3 100644 +index 80f61914..1373f15b 100644 --- a/libmultipath/config.c +++ b/libmultipath/config.c -@@ -961,6 +961,8 @@ int _init_config (const char *file, struct config *conf) +@@ -961,6 +961,8 @@ int init_config__ (const char *file, struct config *conf) validate_pctable(conf->overrides, 0, file); } else { condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices."); @@ -735,7 +760,7 @@ index 00000000..ce430075 +fi diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8 new file mode 100644 -index 00000000..ea025f31 +index 00000000..ec4e5c56 --- /dev/null +++ b/multipath/mpathconf.8 @@ -0,0 +1,151 @@ @@ -877,7 +902,7 @@ index 00000000..ea025f31 +.B service multipathd stop +to stop the multipathd daemon on \fB--disable\fP, and +.B service multipathd reload -+to reconfigure multipathd on \fB--user_frindly_names\fP and ++to reconfigure multipathd on \fB--user_friendly_names\fP and +\fB--find_multipaths\fP. +This option is set to \fBn\fP by default. +.SH FILES diff --git a/0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch b/0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch index 9884258..4e781fa 100644 --- a/0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +++ b/0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch @@ -20,7 +20,7 @@ Signed-off-by: Benjamin Marzinski 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/multipath/main.c b/multipath/main.c -index c21e3e0b..3f3ac9fb 100644 +index 346acb61..adc50d69 100644 --- a/multipath/main.c +++ b/multipath/main.c @@ -120,7 +120,7 @@ usage (char * progname) @@ -41,7 +41,7 @@ index c21e3e0b..3f3ac9fb 100644 " -c check if a device should be a path in a multipath device\n" " -C check if a multipath device has usable paths\n" " -q allow queue_if_no_path when multipathd is not running\n" -@@ -448,6 +450,50 @@ static void cleanup_vecs(void) +@@ -449,6 +451,50 @@ static void cleanup_vecs(void) free_pathvec(vecs.pathvec, FREE_PATHS); } @@ -92,7 +92,7 @@ index c21e3e0b..3f3ac9fb 100644 static int configure (struct config *conf, enum mpath_cmds cmd, enum devtypes dev_type, char *devpath) -@@ -861,7 +907,7 @@ main (int argc, char *argv[]) +@@ -860,7 +906,7 @@ main (int argc, char *argv[]) condlog(1, "failed to register cleanup handler for vecs: %m"); if (atexit(cleanup_bindings)) condlog(1, "failed to register cleanup handler for bindings: %m"); @@ -101,7 +101,7 @@ index c21e3e0b..3f3ac9fb 100644 switch(arg) { case 'v': if (!isdigit(optarg[0])) { -@@ -932,6 +978,10 @@ main (int argc, char *argv[]) +@@ -931,6 +977,10 @@ main (int argc, char *argv[]) case 'T': cmd = CMD_DUMP_CONFIG; break; @@ -138,14 +138,14 @@ index b88e9a4c..edd742aa 100644 Remove the WWID for the specified device from the WWIDs file. . diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in -index 01ceff7d..e0c2011b 100644 +index 72e44849..69a6c39d 100644 --- a/multipathd/multipathd.service.in +++ b/multipathd/multipathd.service.in @@ -17,6 +17,7 @@ ConditionVirtualization=!container [Service] Type=notify NotifyAccess=main -+ExecStartPre=-/sbin/multipath -A - ExecStart=/sbin/multipathd -d -s - ExecReload=/sbin/multipathd reconfigure ++ExecStartPre=-@BINDIR@/multipath -A + ExecStart=@BINDIR@/multipathd -d -s + ExecReload=@BINDIR@/multipathd reconfigure TasksMax=infinity diff --git a/0008-RH-reset-default-find_mutipaths-value-to-off.patch b/0008-RH-reset-default-find_mutipaths-value-to-off.patch index 04ad52c..5789916 100644 --- a/0008-RH-reset-default-find_mutipaths-value-to-off.patch +++ b/0008-RH-reset-default-find_mutipaths-value-to-off.patch @@ -14,10 +14,10 @@ Signed-off-by: Benjamin Marzinski 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h -index ed08c251..4b033ff9 100644 +index 02f7e57c..cd03fd1a 100644 --- a/libmultipath/defaults.h +++ b/libmultipath/defaults.h -@@ -23,7 +23,7 @@ +@@ -24,7 +24,7 @@ #define DEFAULT_NO_PATH_RETRY NO_PATH_RETRY_UNDEF #define DEFAULT_VERBOSITY 2 #define DEFAULT_REASSIGN_MAPS 0 @@ -27,10 +27,10 @@ index ed08c251..4b033ff9 100644 #define DEFAULT_DEV_LOSS_TMO 600 #define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_ON diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in -index 645e8f88..a7543939 100644 +index af9fbb96..0c1eff40 100644 --- a/multipath/multipath.conf.5.in +++ b/multipath/multipath.conf.5.in -@@ -1225,7 +1225,7 @@ as non-multipath and passed on to upper layers. +@@ -1226,7 +1226,7 @@ as non-multipath and passed on to upper layers. \fBNote:\fR this may cause delays during device detection if there are single-path devices which aren\'t blacklisted. .TP diff --git a/0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch b/0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch index c090da0..06194f6 100644 --- a/0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +++ b/0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch @@ -14,7 +14,7 @@ Signed-off-by: Benjamin Marzinski 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index e2052422..3bcd94ce 100644 +index e94705bf..61ac27ef 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -1221,13 +1221,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, diff --git a/0011-RH-add-scsi-device-handlers-to-modules-load.d.patch b/0011-RH-add-scsi-device-handlers-to-modules-load.d.patch index 7624c5b..3debe8a 100644 --- a/0011-RH-add-scsi-device-handlers-to-modules-load.d.patch +++ b/0011-RH-add-scsi-device-handlers-to-modules-load.d.patch @@ -11,7 +11,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc -index 94e0ec85..49514b06 100644 +index 35334a0c..377125b6 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -16,7 +16,7 @@ READLINE := diff --git a/0012-RH-compile-with-libreadline-support.patch b/0012-RH-compile-with-libreadline-support.patch index eb0ab13..db04640 100644 --- a/0012-RH-compile-with-libreadline-support.patch +++ b/0012-RH-compile-with-libreadline-support.patch @@ -12,7 +12,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc -index 49514b06..a3ed9f28 100644 +index 377125b6..4a6528a9 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -12,7 +12,7 @@ diff --git a/0014-multipathd-fix-flush-check-in-flush_map.patch b/0014-multipathd-fix-flush-check-in-flush_map.patch deleted file mode 100644 index 3ff957d..0000000 --- a/0014-multipathd-fix-flush-check-in-flush_map.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Wed, 5 Jun 2024 19:22:48 -0400 -Subject: [PATCH] multipathd: fix flush check in flush_map() - -Forgot the comparison in the "if" statement. - -Fixes 8a3898339 ("multipathd: sync features on flush_map failure corner case") - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck ---- - multipathd/main.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/multipathd/main.c b/multipathd/main.c -index 09286dd0..58afe14a 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -813,7 +813,7 @@ flush_map(struct multipath * mpp, struct vectors * vecs) - { - int r = dm_suspend_and_flush_map(mpp->alias, 0); - if (r != DM_FLUSH_OK) { -- if (DM_FLUSH_FAIL_CANT_RESTORE) -+ if (r == DM_FLUSH_FAIL_CANT_RESTORE) - remove_feature(&mpp->features, "queue_if_no_path"); - condlog(0, "%s: can't flush", mpp->alias); - return r; diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 9e74d46..da97503 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath -Version: 0.9.9 -Release: 6%{?dist} +Version: 0.10.0 +Release: 1%{?dist} Summary: Tools to manage multipath devices using device-mapper # Automatically converted from old format: GPLv2 - review is highly recommended. License: GPL-2.0-only @@ -8,8 +8,8 @@ URL: http://christophe.varoqui.free.fr/ # The source for this package was pulled from upstream's git repo. Use the # following command to generate the tarball -# curl -L https://github.com/opensvc/multipath-tools/archive/0.9.9.tar.gz -o multipath-tools-0.9.9.tgz -Source0: multipath-tools-0.9.9.tgz +# curl -L https://github.com/opensvc/multipath-tools/archive/0.10.0.tar.gz -o multipath-tools-0.10.0.tgz +Source0: multipath-tools-0.10.0.tgz Source1: multipath.conf Patch0001: 0001-RH-fixup-udev-rules-for-redhat.patch Patch0002: 0002-RH-Remove-the-property-blacklist-exception-builtin.patch @@ -24,7 +24,6 @@ Patch0010: 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch Patch0011: 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch Patch0012: 0012-RH-compile-with-libreadline-support.patch Patch0013: 0013-RH-Add-mpathcleanup.patch -Patch0014: 0014-multipathd-fix-flush-check-in-flush_map.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -112,7 +111,7 @@ This package contains the files needed to develop applications that use device-mapper-multipath's libdmmp C API library %prep -%autosetup -n multipath-tools-0.9.9 -p1 +%autosetup -n multipath-tools-0.10.0 -p1 cp %{SOURCE1} . %build @@ -234,6 +233,12 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Thu Aug 29 2024 Benjamin Marzinski - 0.10.0-1 +- Update source to upstream version 0.9.9 + * Previous patch 0014-multipathd-fix-flush-check-in-flush_map.patch is + included in the source tarball +- Rebase redhat patches + * Fri Aug 9 2024 Benjamin Marzinski - 0.9.9-6 - Add 0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch * multipath features tracking on failed removes diff --git a/sources b/sources index f098bc9..da06e16 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (multipath-tools-0.9.9.tgz) = 65b5d5c48792f6041d700968c87675bc349ede475fe178a203814dbb0325f69895782a22c5c35f6c0157f694951714de9e83cc1464a6c062d911a58faed8960a +SHA512 (multipath-tools-0.10.0.tgz) = 8f545609fa20df7547428f2929571dc0df87c17d9f61f11aad3559446c2e94755e18b1c4b3780b3de92ec2cbc450939ca15a9d6c95551eee4084064d83874b2d SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942 From 75d5c0c70a04b7033f662e60c47f6634298a067e Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Thu, 29 Aug 2024 18:11:38 -0400 Subject: [PATCH 20/29] device-mapper-multipath-0.10.0-2 Update CI tests. --- device-mapper-multipath.spec | 5 +- tests/bindings/main.sh | 126 ++++++++--- tests/find_multipaths/Makefile | 49 ----- tests/find_multipaths/main.sh | 208 ++++++++++++------- tests/include/ec.sh | 14 +- tests/medium_error_scsi_debug/main.sh | 66 +++--- tests/restate_module/main.sh | 6 +- tests/user_friendly_names/main.sh | 151 ++++++++++---- tests/user_friendly_names/multipath.conf.no | 3 - tests/user_friendly_names/multipath.conf.yes | 11 - 10 files changed, 395 insertions(+), 244 deletions(-) delete mode 100644 tests/find_multipaths/Makefile delete mode 100644 tests/user_friendly_names/multipath.conf.no delete mode 100644 tests/user_friendly_names/multipath.conf.yes diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index da97503..4363b49 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.10.0 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Tools to manage multipath devices using device-mapper # Automatically converted from old format: GPLv2 - review is highly recommended. License: GPL-2.0-only @@ -233,6 +233,9 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Thu Aug 29 2024 Benjamin Marzinski - 0.10.0-2 +- update CI tests. + * Thu Aug 29 2024 Benjamin Marzinski - 0.10.0-1 - Update source to upstream version 0.9.9 * Previous patch 0014-multipathd-fix-flush-check-in-flush_map.patch is diff --git a/tests/bindings/main.sh b/tests/bindings/main.sh index 2d6f284..76292e4 100755 --- a/tests/bindings/main.sh +++ b/tests/bindings/main.sh @@ -18,40 +18,110 @@ # Author: Lin Li #set -x -source ../include/ec.sh || exit 200 - +source ../include/tc.sh || exit 200 tlog "running $0" -trun "service multipathd stop" -rpm -q device-mapper-multipath || yum install -y device-mapper-multipath -trun "mpathconf --enable --with_multipathd y --user_friendly_names y" -trun "service multipathd status" -sleep 5 +cleanup () +{ + local retries + if pidof multipathd; then + tlog "stopping multipathd" + trun "systemctl stop multipathd.service || pkill multipathd" + sleep 1 + fi + retries=10 + while pidof multipathd; do + ((retries--)) + if [[ $retries -le 0 ]]; then + tfail_ "failed to stop multipath" + tend + fi + tlog "waiting for multipathd to stop" + sleep 2 + pidof multipathd && pkill multipathd + done + trun "multipath -l -v1" + retries=10 + while [[ -n `multipath -l -v1` ]]; do + ((retries--)) + if [[ $retries -le 0 ]]; then + tfail_ "failed to remove deviece" + tend + fi + tlog "removing multipath device" + trun "udevadm settle" + trun "multipath -DF" + sleep 2 + done + if lsmod | grep -q "^scsi_debug"; then + tlog "removing scsi_debug module" + tok "rmmod scsi_debug" + fi + trun "rm -f /etc/multipath.conf" +} -trun "multipath -F" -sleep 5 -terr "modprobe -r scsi_debug" -terr "modprobe scsi_debug num_tgts=1 vpd_use_hostno=0 add_host=2 delay=20 \ -max_luns=2 no_lun_0=1" -sleep 60 +assert () +{ + local cmd="$*" + _trun_ "$cmd" 0 + if test $? -eq 0; then + tpass_ "$cmd" ; + else + tfail_ "$cmd" ; + cleanup ; + tend ; + fi +} -disk_path=$(get_scsi_debug_devices) -disk=$(basename $disk_path) -mpath_name=$(get_mpath_disk_by_scsi_device $disk) +setup_config () +{ + trun "mpathconf --enable --user_friendly_names y" + sed -i '/^blacklist[[:space:]]*{/ a\ + device {\ + vendor ".*"\ + product ".*"\ + } +' /etc/multipath.conf + cat << _EOF_ >> /etc/multipath.conf + +blacklist_exceptions { + device { + vendor Linux + product scsi_debug + } +} +_EOF_ + trun "cat /etc/multipath.conf" +} + +do_reconfigure () +{ + tok "multipathd reconfigure" + sleep 5 +} + +rpm -q device-mapper-multipath || dnf install -y device-mapper-multipath +cleanup +setup_config +trun "rm -r /etc/multipath/bindings" +trun "modprobe scsi_debug vpd_use_hostno=0 add_host=2" +sleep 5 +trun "systemctl start multipathd.service" +while multipathd show daemon | grep -qv idle; do + tlog "waiting for multipathd to start" + sleep 1 +done + +trun 'multipathd show maps raw format "%n"' +mpath_name=`multipathd show maps raw format "%n" | head -1` +assert "[[ -n $mpath_name ]] && [[ $mpath_name != ok ]]" new_alias="mpath_test_$$" trun "sed -i 's/$mpath_name/$new_alias/' /etc/multipath/bindings" -trun "multipath -r" -sleep 5 -tok "[[ -b /dev/mapper/$new_alias ]]" -tok is_mpath $new_alias -sleep 5 +do_reconfigure +trun 'multipathd show maps raw format "%n"' +mpath_name=`multipathd show maps raw format "%n" | head -1` +assert "[[ $mpath_name = $new_alias ]]" -trun "multipath -F" -sleep 5 -trun "modprobe -r scsi_debug" -trun "service multipathd stop" -sleep 3 -trun "multipath -W" -trun "rm /etc/multipath/bindings" +cleanup tend diff --git a/tests/find_multipaths/Makefile b/tests/find_multipaths/Makefile deleted file mode 100644 index b78dc57..0000000 --- a/tests/find_multipaths/Makefile +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2016 Red Hat, Inc. -# # -# # This program is free software: you can redistribute it and/or modify -# # it under the terms of the GNU General Public License as published by -# # the Free Software Foundation, either version 3 of the License, or -# # (at your option) any later version. -# # -# # This program is distributed in the hope that it will be useful, -# # but WITHOUT ANY WARRANTY; without even the implied warranty of -# # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# # GNU General Public License for more details. -# # -# # You should have received a copy of the GNU General Public License -# # along with this program. If not, see . -# -# # Author: Lin Li - -.PHONY: all install download clean - -BUILT_FILES= - -FILES=$(METADATA) Makefile PURPOSE main.sh - -run: $(FILES) build - ./main.sh - -build: $(BUILT_FILES) - chmod a+x ./main.sh - -clean: - rm -f *~ *.rpm $(BUILT_FILES) - -include /usr/share/rhts/lib/rhts-make.include - -$(METADATA): Makefile - @touch $(METADATA) - @echo "Owner: LiLin " > $(METADATA) - @echo "Name: $(TEST)" >> $(METADATA) - @echo "Path: $(TEST_DIR)" >> $(METADATA) - @echo "License: GPLv3" >> $(METADATA) - @echo "TestVersion: $(TESTVERSION)" >> $(METADATA) - @echo "Description: find_multipaths" >> $(METADATA) - @echo "TestTime: 15m" >> $(METADATA) - @echo "RunFor: device-mapper-multipath" >> $(METADATA) - @echo "Requires: device-mapper-multipath" >> $(METADATA) - - rhts-lint $(METADATA) diff --git a/tests/find_multipaths/main.sh b/tests/find_multipaths/main.sh index 4d94c87..28c325c 100755 --- a/tests/find_multipaths/main.sh +++ b/tests/find_multipaths/main.sh @@ -18,39 +18,92 @@ # Author: Lin Li #set -x -source ../include/ec.sh || exit 200 +source ../include/tc.sh || exit 200 +tlog "running $0" + +remove_devices () +{ + local retries + retries=10 + while [[ -n `multipath -l -v1` ]]; do + ((retries--)) + if [[ $retries -le 0 ]]; then + tfail_ "failed to remove devices" + cleanup + tend + fi + tlog "removing multipath devices" + trun "udevadm settle" + trun "multipath -F" + sleep 2 + done +} cleanup () { - trun "multipathd disablequeueing maps" - trun "service multipathd stop" - sleep 5 - trun "udevadm settle" - trun "multipath -F" - sleep 5 - trun "modprobe -r scsi_debug" + local retries + if pidof multipathd; then + tlog "stopping multipathd" + trun "systemctl stop multipathd.service || pkill multipathd" + sleep 1 + fi + retries=10 + while pidof multipathd; do + ((retries--)) + if [[ $retries -le 0 ]]; then + tfail_ "failed to stop multipath" + tend + fi + tlog "waiting for multipathd to stop" + sleep 2 + pidof multipathd && pkill multipathd + done + trun "multipath -l -v1" + retries=10 + while [[ -n `multipath -l -v1` ]]; do + ((retries--)) + if [[ $retries -le 0 ]]; then + tfail_ "failed to remove devices" + tend + fi + tlog "removing multipath devices" + trun "udevadm settle" + trun "multipath -DF" + sleep 2 + done + if lsmod | grep -q "^scsi_debug"; then + tlog "removing scsi_debug module" + tok "rmmod scsi_debug" + fi + trun "rm -f /etc/multipath.conf" + trun "rm -f /etc/multipath/wwids" + trun "rm -r /etc/multipath/bindings" } -tlog "running $0" +assert () +{ + local cmd="$*" + _trun_ "$cmd" 0 + if test $? -eq 0; then + tpass_ "$cmd" ; + else + tfail_ "$cmd" ; + cleanup ; + tend ; + fi +} -# which not set find_multipaths yes, so multipath always create a multipath device for single device -# so stop service and reconfig with --find_multipaths y, and reload/start the service again. -rpm -q device-mapper-multipath || yum install -y device-mapper-multipath +setup_config () +{ + trun "mpathconf --enable --user_friendly_names y --find_multipaths y" + sed -i '/^blacklist[[:space:]]*{/ a\ + device {\ + vendor ".*"\ + product ".*"\ + } +' /etc/multipath.conf + cat << _EOF_ >> /etc/multipath.conf -# test with find_multipath=y, will not multipath for the single device; reload/start the service to enable the config -cleanup -trun "rm -f /etc/multipath.conf" -trun "rm -f /etc/multipath/wwids" -trun "mpathconf --enable --user_friendly_names y --find_multipaths y --with_multipathd n" -sed -i '/^blacklist[[:space:]]*{/ a\ - device {\n vendor ".*"\n product ".*"\n } -' /etc/multipath.conf -if grep -qw blacklist_exceptions /etc/multipath.conf ; then - sed -i '/^blacklist_exceptions[[:space:]]*{/ a\ - device {\n vendor Linux\n product scsi_debug\n } -' /etc/multipath.conf -else - cat << _EOF_ >> /etc/multipath.conf blacklist_exceptions { device { vendor Linux @@ -58,56 +111,69 @@ blacklist_exceptions { } } _EOF_ -fi -trun "service multipathd start" + trun "cat /etc/multipath.conf" +} + +do_reconfigure () +{ + trun "cat /etc/multipath.conf" + tok "multipathd reconfigure" + sleep 5 +} + +trun "rpm -q device-mapper-multipath || dnf install -y device-mapper-multipath" +cleanup +setup_config + +# test with find_multipath=y, will not multipath the single device trun "modprobe scsi_debug" sleep 5 +trun "systemctl start multipathd.service" +while multipathd show daemon | grep -qv idle; do + tlog "waiting for multipathd to start" + sleep 1 +done +trun 'multipathd show paths raw format "%d %m"' +trun 'cat /etc/multipath/wwids' +mpath_name=`multipathd show paths raw format "%m" | head -1` +tok "[[ $mpath_name = '[orphan]' ]]" +remove_devices + +# test with find_multipath=n, will multipath the single device +trun 'mpathconf --find_multipaths n' +do_reconfigure +trun 'multipathd show paths raw format "%d %m"' +trun 'cat /etc/multipath/wwids' +mpath_name=`multipathd show paths raw format "%m" | head -1` +tok "[[ -n $mpath_name ]] && [[ $mpath_name != '[orphan]' ]]" +remove_devices + +# test with find_multipath=y, with multipath single device with known WWID +trun 'mpathconf --find_multipaths y' +do_reconfigure +trun 'multipathd show paths raw format "%d %m"' +trun 'cat /etc/multipath/wwids' +mpath_name=`multipathd show paths raw format "%m" | head -1` +tok "[[ -n $mpath_name ]] && [[ $mpath_name != '[orphan]' ]]" +remove_devices + +# Clear WWID, test with find_multipath=y, will not multipath single device trun "multipath -W" -cat /etc/multipath/wwids -trun "multipath" -disk_path=$(get_scsi_debug_devices) -disk_node=$(basename $disk_path) -mpath_name=$(get_mpath_disk_by_scsi_device $disk_node) -tok '[[ $mpath_name = "[orphan]" ]]' - -# test with find_multipath=n, will multipath for the single device -trun "mpathconf --user_friendly_names y --find_multipaths n --with_multipathd y" -sleep 5 -mpath_name=$(get_mpath_disk_by_scsi_device $disk_node) -tok "is_mpath $mpath_name" - -# flush new created path -trun "multipath -F" -sleep 1 - -# test with find_multipath=y, A path has the same WWID as a multipath device that was previously created -trun "mpathconf --user_friendly_names y --find_multipaths y --with_multipathd y" -sleep 5 -mpath_name=$(get_mpath_disk_by_scsi_device $disk_node) -tok "is_mpath $mpath_name" -trun "multipath -F" -sleep 1 - -# Clear wwid, test with find_multipath=y, will not multipath for the single device -trun "multipath -W" -trun "service multipathd reload" -sleep 5 -mpath_name=$(get_mpath_disk_by_scsi_device $disk_node) -tok '[[ $mpath_name = "[orphan]" ]]' - -trun "multipath -F" -sleep 5 -trun "modprobe -r scsi_debug" +do_reconfigure +trun 'multipathd show paths raw format "%d %m"' +trun 'cat /etc/multipath/wwids' +mpath_name=`multipathd show paths raw format "%m" | head -1` +tok "[[ $mpath_name = '[orphan]' ]]" +remove_devices +assert 'rmmod scsi_debug' # test find_multipaths=y create device for paths have same wwid -tok "modprobe scsi_debug num_tgts=1 vpd_use_hostno=0 add_host=2 delay=20 max_luns=2 no_lun_0=1" -sleep 10 -disk_paths=$(get_scsi_debug_devices) -disk_node=$(basename $disk_paths) -mpath_name=$(get_mpath_disk_by_scsi_device $disk_node) -tok "is_mpath $mpath_name" +trun "modprobe scsi_debug vpd_use_hostno=0 add_host=2" +sleep 5 +trun 'multipathd show paths raw format "%d %m"' +trun 'cat /etc/multipath/wwids' +mpath_name=`multipathd show paths raw format "%m" | head -1` +tok "[[ -n $mpath_name ]] && [[ $mpath_name != '[orphan]' ]]" cleanup -trun "multipath -W" -cat /etc/multipath/wwids tend diff --git a/tests/include/ec.sh b/tests/include/ec.sh index 22dfc40..4b0aba9 100755 --- a/tests/include/ec.sh +++ b/tests/include/ec.sh @@ -44,9 +44,12 @@ function _init (){ } function _destroy (){ - sleep 10 - Cmd "multipath -F" + Cmd "multipathd disablequeueing maps" sleep 5 + Cmd "multipath -DF -R2" + Cmd "service multipathd stop" + sleep 5 + Cmd "udevadm settle" Cmd "modprobe -r scsi_debug" } @@ -174,10 +177,7 @@ AA fi #setup scsi_debug echo "INFO: Loading scsi_debug module for simulation of mpath" - modprobe scsi_debug \ - num_tgts=1 vpd_use_hostno=0 \ - add_host=4 delay=20 \ - max_luns=2 no_lun_0=1 2>&1 1>/dev/null + modprobe scsi_debug vpd_use_hostno=0 add_host=2 echo "INFO: Waiting for udev to create /dev/sdX" sleep 15s #wait for udev to create /dev/sdX @@ -189,8 +189,6 @@ AA #enable multipath for scsi_debug. cat << AA > /etc/multipath.conf defaults { -#Enable multibus is for mutlbus testing - path_grouping_policy multibus user_friendly_names yes } blacklist { diff --git a/tests/medium_error_scsi_debug/main.sh b/tests/medium_error_scsi_debug/main.sh index db2f008..35c6e6f 100755 --- a/tests/medium_error_scsi_debug/main.sh +++ b/tests/medium_error_scsi_debug/main.sh @@ -16,47 +16,51 @@ # along with this program. If not, see . # Author: LiLin +source ../include/tc.sh || exit 200 -function cleanup() +cleanup() { sleep 5 udevadm settle - multipath -F + trun "multipath -DF" sleep 5 - modprobe -r scsi_debug - - return 0 + trun "modprobe -r scsi_debug" } -yum -y install device-mapper device-mapper-multipath -mpathconf --enable -service multipathd stop -modprobe scsi_debug num_tgts=1 vpd_use_hostno=0 add_host=2 delay=20 max_luns=2 no_lun_0=1 opts=2 +assert () +{ + local cmd="$*" + _trun_ "$cmd" 0 + if test $? -eq 0; then + tpass_ "$cmd" ; + else + tfail_ "$cmd" ; + cleanup ; + tend ; + fi +} + +tlog "running $0" +rpm -q device-mapper-multipath || dnf install -y device-mapper-multipath +trun "multipathd disablequeueing maps" +cleanup +trun "service multipathd stop" +trun "rm -f /etc/multipath.conf" +trun "mpathconf --enable" +trun "modprobe scsi_debug vpd_use_hostno=0 add_host=2 opts=2" sleep 5 -multipath > /dev/null +trun "multipath" sleep 5 +trun "multipath -l" mpathdev=`multipath -l | grep scsi_debug | awk '{print $1}' | head -1` -if [ -z "$mpathdev" ]; then - echo "------- FAIL, no multipath device created -----" - cleanup - exit 1 -fi +assert "[[ -n \"$mpathdev\" ]]" before_active=`multipath -l $mpathdev | grep "active undef" | wc -l` +tlog "before active = ${before_active}" IO_error=`dd if=/dev/zero of=/dev/mapper/$mpathdev bs=1024 seek=2330 count=10 2>&1 | grep -o "Input/output error" ` -if [ -n "$IO_error" ];then - after_active=`multipath -l $mpathdev | grep "active undef" | wc -l` - if [ "$before_active" -eq "$after_active" ]; then - echo "------- PASS, a medium error, correctly generated an I/O error and did not fail paths -----" - cleanup - exit 0 - else - echo "------- FAIL, paths failed -----" - cleanup - exit 1 - fi -else - echo "------- FAIL, did not generate an I/O error -----" - cleanup - exit 1 -fi +assert "[[ -n \"$IO_error\" ]]" +after_active=`multipath -l $mpathdev | grep "active undef" | wc -l` +tlog "after active = ${after_active}" +assert "[[ \"$before_active\" -eq \"$after_active\" ]]" +cleanup +tend diff --git a/tests/restate_module/main.sh b/tests/restate_module/main.sh index 565e59c..be60eba 100755 --- a/tests/restate_module/main.sh +++ b/tests/restate_module/main.sh @@ -48,10 +48,8 @@ rpm -q device-mapper-multipath || yum install -y device-mapper-multipath tlog "device-mapper-multipath is installed" # cleanup existing devices trun "rm /etc/multipath.conf" -trun "mpathconf --enable --with_module y" -sed -i '/^defaults[[:space:]]*{/ a\ - max_polling_interval 10 -' /etc/multipath.conf +trun "mpathconf --enable --with_module y --option max_polling_interval:10" +trun "mpathconf --option detect_pgpolicy_use_tpg:yes" trun "service multipathd stop" trun "multipath -F" sleep 5 diff --git a/tests/user_friendly_names/main.sh b/tests/user_friendly_names/main.sh index 56082fd..1d48801 100755 --- a/tests/user_friendly_names/main.sh +++ b/tests/user_friendly_names/main.sh @@ -17,50 +17,125 @@ # Author: Lin Li -source ../include/ec.sh || exit 200 - +source ../include/tc.sh || exit 200 tlog "running $0" -trun "rpm -q device-mapper-multipath || yum install -y device-mapper-multipath" -trun "mpathconf --enable --with_multipathd y --user_friendly_names y" +cleanup () +{ + local retries + if pidof multipathd; then + tlog "stopping multipathd" + trun "systemctl stop multipathd.service || pkill multipathd" + sleep 1 + fi + retries=10 + while pidof multipathd; do + ((retries--)) + if [[ $retries -le 0 ]]; then + tfail_ "failed to stop multipath" + tend + fi + tlog "waiting for multipathd to stop" + sleep 2 + pidof multipathd && pkill multipathd + done + trun "multipath -l -v1" + retries=10 + while [[ -n `multipath -l -v1` ]]; do + ((retries--)) + if [[ $retries -le 0 ]]; then + tfail_ "failed to remove deviece" + tend + fi + tlog "removing multipath device" + trun "udevadm settle" + trun "multipath -DF" + sleep 2 + done + if lsmod | grep -q "^scsi_debug"; then + tlog "removing scsi_debug module" + tok "rmmod scsi_debug" + fi + trun "rm -f /etc/multipath.conf" +} -# backup the /etc/multipath.conf -trun "cp /etc/multipath.conf /etc/multipath.conf.$$" -trun "multipath -F" +assert () +{ + local cmd="$*" + _trun_ "$cmd" 0 + if test $? -eq 0; then + tpass_ "$cmd" ; + else + tfail_ "$cmd" ; + cleanup ; + tend ; + fi +} -trun "modprobe scsi_debug num_tgts=1 vpd_use_hostno=0 add_host=2 delay=20 \ -max_luns=2 no_lun_0=1" -trun "multipath" -# wwid shown slowly on s390x by the script framework, but normally when run by multipath command directly -# so extend sleep time -sleep 20 +setup_config () +{ + trun "mpathconf --enable --user_friendly_names y" + sed -i '/^blacklist[[:space:]]*{/ a\ + device {\ + vendor ".*"\ + product ".*"\ + } +' /etc/multipath.conf + cat << _EOF_ >> /etc/multipath.conf -disk=$(get_scsi_debug_devices) -disk=$(basename $disk) -wwid=$(get_wwid_of_disk $disk) -mpath=$(get_mpath_disk_by_scsi_device $disk) +blacklist_exceptions { + device { + vendor Linux + product scsi_debug + } +} -# user_friendly_names = yes and mpath=test -#cur_dir=/mnt/tests/kernel/storage/multipath/user_friendly_names/ -#cur_dir=/home/test/scratch/device-mapper-multipath/user_friendly_names -trun "cat multipath.conf.yes | sed "s/your_wwid/$wwid/g" > /etc/multipath.conf" -trun "cat -n /etc/multipath.conf" -trun "multipath -r" -echo ">>> Verify 'test ($wwid)' is present ..." -trun "multipath -ll" -tok "multipath -ll | egrep \"^test\"" +multipaths { + multipath { + wwid TEST_WWID + alias test + } +} +_EOF_ + trun "cat /etc/multipath.conf" +} -# user_friendly_names = no -trun "cat multipath.conf.no > /etc/multipath.conf" -trun "multipath -r" -echo ">>> Verify 'test' is gone but '$wwid' present ..." -trun "multipath -ll" -tok "multipath -ll | egrep \"^$wwid\"" -sleep 10 -tok "multipath -F $wwid" -sleep 10 -trun "modprobe -r scsi_debug" +do_reconfigure () +{ + trun "cat /etc/multipath.conf" + tok "multipathd reconfigure" + sleep 5 +} -trun "cp /etc/multipath.conf.$$ /etc/multipath.conf" -trun "multipath -F; multipath" +trun "rpm -q device-mapper-multipath || dnf install -y device-mapper-multipath" +cleanup +setup_config +trun "rm -r /etc/multipath/bindings" +trun "modprobe scsi_debug vpd_use_hostno=0 add_host=2" +sleep 5 +trun "systemctl start multipathd.service" +while multipathd show daemon | grep -qv idle; do + tlog "waiting for multipathd to start" + sleep 1 +done +trun 'multipathd show maps raw format "%n %w"' +# verify user_friendly_name +tok 'multipathd show maps raw format "%n" | head -1 | grep -q mpath' +wwid=`multipathd show maps raw format "%w" | head -1` +assert "[[ -n $wwid ]] && [[ $wwid != ok ]]" +sed -i 's/TEST_WWID/'"$wwid"'/' /etc/multipath.conf +do_reconfigure +trun 'multipathd show maps raw format "%n %w"' +# verify configured alias takes precedence over user_friendly_name +tok 'multipathd show maps raw format "%n" | head -1 | grep -q test' +trun "mpathconf --user_friendly_names n" +do_reconfigure +trun 'multipathd show maps raw format "%n %w"' +# verify configured alias takes precedence over wwid name +tok 'multipathd show maps raw format "%n" | head -1 | grep -q test' +sed -i 's/'"$wwid"'/TEST_WWID/' /etc/multipath.conf +do_reconfigure +trun 'multipathd show maps raw format "%n %w"' +tok 'multipathd show maps raw format "%n" | head -1 | grep -q '"$wwid" +cleanup tend diff --git a/tests/user_friendly_names/multipath.conf.no b/tests/user_friendly_names/multipath.conf.no deleted file mode 100644 index b916bfb..0000000 --- a/tests/user_friendly_names/multipath.conf.no +++ /dev/null @@ -1,3 +0,0 @@ -defaults { - user_friendly_names no -} diff --git a/tests/user_friendly_names/multipath.conf.yes b/tests/user_friendly_names/multipath.conf.yes deleted file mode 100644 index ffc21bb..0000000 --- a/tests/user_friendly_names/multipath.conf.yes +++ /dev/null @@ -1,11 +0,0 @@ -defaults { - user_friendly_names yes -} - -multipaths { - multipath { - wwid your_wwid - alias test - } -} - From 4ec4661deede93f7134c87624f89a07ac166e3f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 12 Jan 2025 14:25:51 +0100 Subject: [PATCH 21/29] Rebuilt for the bin-sbin merge (2nd attempt) https://fedoraproject.org/wiki/Changes/Unify_bin_and_sbin --- device-mapper-multipath.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 4363b49..2eebd2f 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.10.0 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Tools to manage multipath devices using device-mapper # Automatically converted from old format: GPLv2 - review is highly recommended. License: GPL-2.0-only @@ -233,6 +233,9 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Sun Jan 12 2025 Zbigniew Jฤ™drzejewski-Szmek - 0.10.0-3 +- Rebuilt for the bin-sbin merge (2nd attempt) + * Thu Aug 29 2024 Benjamin Marzinski - 0.10.0-2 - update CI tests. From 61847c90be2f7afa60de098651ff5c92cd0f1374 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 16 Jan 2025 15:37:12 +0000 Subject: [PATCH 22/29] Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild --- device-mapper-multipath.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 2eebd2f..8ff030a 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.10.0 -Release: 3%{?dist} +Release: 4%{?dist} Summary: Tools to manage multipath devices using device-mapper # Automatically converted from old format: GPLv2 - review is highly recommended. License: GPL-2.0-only @@ -233,6 +233,9 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Thu Jan 16 2025 Fedora Release Engineering - 0.10.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild + * Sun Jan 12 2025 Zbigniew Jฤ™drzejewski-Szmek - 0.10.0-3 - Rebuilt for the bin-sbin merge (2nd attempt) From 05ecb26e7c73e0563c5b4096bf6288324b753cea Mon Sep 17 00:00:00 2001 From: Yaakov Selkowitz Date: Tue, 28 Jan 2025 23:12:39 -0500 Subject: [PATCH 23/29] Fix build with userspace-rcu 0.15.0 C11 (or C++11) are now required for atomics in userspace-rcu: https://github.com/urcu/userspace-rcu/commit/89280d020bf064d1055c360fb9974f128051043f --- 0005-RH-use-rpm-optflags-if-present.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/0005-RH-use-rpm-optflags-if-present.patch b/0005-RH-use-rpm-optflags-if-present.patch index 3f115c1..266e224 100644 --- a/0005-RH-use-rpm-optflags-if-present.patch +++ b/0005-RH-use-rpm-optflags-if-present.patch @@ -54,7 +54,7 @@ index 81cb61d2..35334a0c 100644 -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP -CFLAGS := -std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \ - -fexceptions -+CFLAGS := -std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe ++CFLAGS := -std=gnu11 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe BIN_CFLAGS := -fPIE -DPIE LIB_CFLAGS := -fPIC SHARED_FLAGS := -shared From 3c2eb3f84ecbc2fd6790437dc83955ab4fd6cc33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Such=C3=BD?= Date: Mon, 20 Jan 2025 08:06:30 +0000 Subject: [PATCH 24/29] Migrate to SPDX license This is part of https://fedoraproject.org/wiki/Changes/SPDX_Licenses_Phase_4 --- device-mapper-multipath.spec | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 8ff030a..d2c3cc6 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -2,8 +2,8 @@ Name: device-mapper-multipath Version: 0.10.0 Release: 4%{?dist} Summary: Tools to manage multipath devices using device-mapper -# Automatically converted from old format: GPLv2 - review is highly recommended. -License: GPL-2.0-only +# readline uses GPL-3.0-only +License: GPL-2.0-only AND GPL-3.0-only URL: http://christophe.varoqui.free.fr/ # The source for this package was pulled from upstream's git repo. Use the @@ -65,8 +65,8 @@ The tools are : %package libs Summary: The %{name} modules and shared library -# only libmpathcmd is LGPLv2+ -License: GPLv2 and LGPLv2+ +# only libmpathcmd is LGPL-2.1-or-later AND LGPL-2.0-or-later +License: GPL-2.0-or-later AND LGPL-2.1-or-later AND LGPL-2.0-or-later %description libs The %{name}-libs provides the path checker From f2377371e3fef1c096acab223bd842dbd755f5d0 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Sun, 2 Feb 2025 01:54:16 -0500 Subject: [PATCH 25/29] device-mapper-multipath-0.10.0-5 - Update source to upstream staging branch for 0.10.y (will be 0.10.2 when merged). - Rebase redhat patches --- ...lows-use-upload-download-artifact-v4.patch | 122 ++++++++++++++++ ...-update-dawidd6-action-download-arti.patch | 24 +++ ...-native.yml-use-mosteo-actions-docke.patch | 98 +++++++++++++ ...s-native.yml-use-extra-job-for-clang.patch | 43 ++++++ ...-native.yaml-make-test-and-archive-s.patch | 51 +++++++ ...-enable-unit-tests-for-stable-branch.patch | 133 +++++++++++++++++ ...ws-add-abi-check-for-stable-branches.patch | 110 ++++++++++++++ ...get_maps-don-t-bail-out-for-single-m.patch | 32 ++++ ...s.in-import-DM_COLDPLUG_SUSPENDED-on.patch | 42 ++++++ ...s.in-handle-inactive-suspended-devic.patch | 66 +++++++++ ...rules.in-clarify-DM_ACTIVATION-logic.patch | 78 ++++++++++ ...h-rules.in-skip-one-.DM_NOSCAN-check.patch | 28 ++++ ...s.in-set-.DM_NOSCAN-if-MPATH_UNCHANG.patch | 44 ++++++ ...-t-set-dev_loss_tmo-to-0-for-NO_PATH.patch | 31 ++++ ...eferred_failback_tick-for-reload-rem.patch | 35 +++++ ...ipathd-fix-an-unsigned-int-ovwerflow.patch | 28 ++++ ...id-Wcast-function-type-mismatch-erro.patch | 36 +++++ 0018-Update-NEWS.md-for-0.10.1.patch | 44 ++++++ ...-t-print-error-message-if-WATCHDOG_U.patch | 30 ++++ ...uce-log-level-of-map-X-has-multiple-.patch | 38 +++++ ...eign-fix-memory-leak-in-nvme-foreign.patch | 54 +++++++ ...-condition-for-enqueueing-path-to-io.patch | 41 ++++++ ...dditional-NEWS.md-updates-for-0.10.1.patch | 63 ++++++++ ...multipath-fix-handling-of-pp-pgindex.patch | 138 ++++++++++++++++++ ...e-pgcmp-detect-if-map-is-missing-a-p.patch | 70 +++++++++ ...gger-uevents-upon-map-creation-in-do.patch | 94 ++++++++++++ ...er-uevents-upon-map-removal-in-coale.patch | 41 ++++++ ...h-Don-t-skip-set_path_max_sectors_kb.patch | 31 ++++ ...p-static-analyzer-complaint-in-init_.patch | 27 ++++ ...lenient-in-allowing-the-alua-based-p.patch | 44 ++++++ 0031-Update-NEWS.md-for-0.10.2.patch | 64 ++++++++ ...-fix-abi-stable.yaml-for-pull-reques.patch | 61 ++++++++ ... 0033-RH-fixup-udev-rules-for-redhat.patch | 0 ...property-blacklist-exception-builtin.patch | 0 ...RH-don-t-start-without-a-config-file.patch | 4 +- ...H-Fix-nvme-function-missing-argument.patch | 0 ... 0037-RH-use-rpm-optflags-if-present.patch | 3 +- ...hconf.patch => 0038-RH-add-mpathconf.patch | 12 +- ...om-kernel-cmdline-mpath.wwids-with-A.patch | 0 ...-default-find_mutipaths-value-to-off.patch | 0 ...empt-to-get-ANA-info-via-sysfs-first.patch | 0 ...-parse_vpd_pg83-match-scsi_id-output.patch | 2 +- ...si-device-handlers-to-modules-load.d.patch | 2 +- ...-RH-compile-with-libreadline-support.patch | 2 +- ...up.patch => 0045-RH-Add-mpathcleanup.patch | 0 device-mapper-multipath.spec | 65 +++++++-- 46 files changed, 1905 insertions(+), 26 deletions(-) create mode 100644 0001-GitHub-workflows-use-upload-download-artifact-v4.patch create mode 100644 0002-GitHub-workflows-update-dawidd6-action-download-arti.patch create mode 100644 0003-Github-workflows-native.yml-use-mosteo-actions-docke.patch create mode 100644 0004-GitHub-workflows-native.yml-use-extra-job-for-clang.patch create mode 100644 0005-GitHub-workflows-native.yaml-make-test-and-archive-s.patch create mode 100644 0006-GitHub-workflows-enable-unit-tests-for-stable-branch.patch create mode 100644 0007-GitHub-Workflows-add-abi-check-for-stable-branches.patch create mode 100644 0008-libmultipath-dm_get_maps-don-t-bail-out-for-single-m.patch create mode 100644 0009-11-dm-mpath.rules.in-import-DM_COLDPLUG_SUSPENDED-on.patch create mode 100644 0010-11-dm-mpath.rules.in-handle-inactive-suspended-devic.patch create mode 100644 0011-11-dm-mpath.rules.in-clarify-DM_ACTIVATION-logic.patch create mode 100644 0012-11-dm-mpath-rules.in-skip-one-.DM_NOSCAN-check.patch create mode 100644 0013-11-dm-mpath.rules.in-set-.DM_NOSCAN-if-MPATH_UNCHANG.patch create mode 100644 0014-libmultipath-don-t-set-dev_loss_tmo-to-0-for-NO_PATH.patch create mode 100644 0015-multipathd-fix-deferred_failback_tick-for-reload-rem.patch create mode 100644 0016-multipathd-fix-an-unsigned-int-ovwerflow.patch create mode 100644 0017-libmpathutil-avoid-Wcast-function-type-mismatch-erro.patch create mode 100644 0018-Update-NEWS.md-for-0.10.1.patch create mode 100644 0019-libmultipath-don-t-print-error-message-if-WATCHDOG_U.patch create mode 100644 0020-libmultipath-reduce-log-level-of-map-X-has-multiple-.patch create mode 100644 0021-libmultipath-foreign-fix-memory-leak-in-nvme-foreign.patch create mode 100644 0022-libmultipath-add-condition-for-enqueueing-path-to-io.patch create mode 100644 0023-Additional-NEWS.md-updates-for-0.10.1.patch create mode 100644 0024-libmultipath-fix-handling-of-pp-pgindex.patch create mode 100644 0025-libmultipath-make-pgcmp-detect-if-map-is-missing-a-p.patch create mode 100644 0026-libmultipath-trigger-uevents-upon-map-creation-in-do.patch create mode 100644 0027-multipathd-trigger-uevents-upon-map-removal-in-coale.patch create mode 100644 0028-libmultipath-Don-t-skip-set_path_max_sectors_kb.patch create mode 100644 0029-libmultipath-stop-static-analyzer-complaint-in-init_.patch create mode 100644 0030-libmultipath-be-lenient-in-allowing-the-alua-based-p.patch create mode 100644 0031-Update-NEWS.md-for-0.10.2.patch create mode 100644 0032-GitHub-Workflows-fix-abi-stable.yaml-for-pull-reques.patch rename 0001-RH-fixup-udev-rules-for-redhat.patch => 0033-RH-fixup-udev-rules-for-redhat.patch (100%) rename 0002-RH-Remove-the-property-blacklist-exception-builtin.patch => 0034-RH-Remove-the-property-blacklist-exception-builtin.patch (100%) rename 0003-RH-don-t-start-without-a-config-file.patch => 0035-RH-don-t-start-without-a-config-file.patch (98%) rename 0004-RH-Fix-nvme-function-missing-argument.patch => 0036-RH-Fix-nvme-function-missing-argument.patch (100%) rename 0005-RH-use-rpm-optflags-if-present.patch => 0037-RH-use-rpm-optflags-if-present.patch (97%) rename 0006-RH-add-mpathconf.patch => 0038-RH-add-mpathconf.patch (99%) rename 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch => 0039-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch (100%) rename 0008-RH-reset-default-find_mutipaths-value-to-off.patch => 0040-RH-reset-default-find_mutipaths-value-to-off.patch (100%) rename 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch => 0041-RH-attempt-to-get-ANA-info-via-sysfs-first.patch (100%) rename 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch => 0042-RH-make-parse_vpd_pg83-match-scsi_id-output.patch (98%) rename 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch => 0043-RH-add-scsi-device-handlers-to-modules-load.d.patch (96%) rename 0012-RH-compile-with-libreadline-support.patch => 0044-RH-compile-with-libreadline-support.patch (96%) rename 0013-RH-Add-mpathcleanup.patch => 0045-RH-Add-mpathcleanup.patch (100%) diff --git a/0001-GitHub-workflows-use-upload-download-artifact-v4.patch b/0001-GitHub-workflows-use-upload-download-artifact-v4.patch new file mode 100644 index 0000000..c8247ca --- /dev/null +++ b/0001-GitHub-workflows-use-upload-download-artifact-v4.patch @@ -0,0 +1,122 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 13 Sep 2024 09:09:19 +0200 +Subject: [PATCH] GitHub workflows: use {upload,download}-artifact@v4 + +The @v1 releases are deprecated. +https://github.blog/changelog/2024-02-13-deprecation-notice-v1-and-v2-of-the-artifact-actions/ + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + .github/workflows/abi.yaml | 6 ++++-- + .github/workflows/foreign.yaml | 15 +++++++-------- + .github/workflows/native.yaml | 5 +++-- + 3 files changed, 14 insertions(+), 12 deletions(-) + +diff --git a/.github/workflows/abi.yaml b/.github/workflows/abi.yaml +index 393322e5..dce09f5c 100644 +--- a/.github/workflows/abi.yaml ++++ b/.github/workflows/abi.yaml +@@ -45,10 +45,11 @@ jobs: + - name: create ABI + run: make -Orecurse -j$(grep -c ^processor /proc/cpuinfo) abi.tar.gz + - name: save ABI +- uses: actions/upload-artifact@v1 ++ uses: actions/upload-artifact@v4 + with: + name: abi + path: abi ++ overwrite: true + - name: compare ABI against reference + id: compare + continue-on-error: true +@@ -56,10 +57,11 @@ jobs: + run: make abi-test + - name: save differences + if: ${{ steps.compare.outcome == 'failure' }} +- uses: actions/upload-artifact@v1 ++ uses: actions/upload-artifact@v4 + with: + name: abi-test + path: abi-test ++ overwrite: true + + - name: fail + # MUST use >- here, otherwise the condition always evaluates to true +diff --git a/.github/workflows/foreign.yaml b/.github/workflows/foreign.yaml +index 9e4d35e0..d68650df 100644 +--- a/.github/workflows/foreign.yaml ++++ b/.github/workflows/foreign.yaml +@@ -36,14 +36,13 @@ jobs: + - name: checkout + uses: actions/checkout@v1 + - name: build +- run: make -j8 -Orecurse test-progs +- - name: create binary archive +- run: make test-progs.tar ++ run: make -j -Orecurse test-progs.tar + - name: upload binary archive +- uses: actions/upload-artifact@v1 ++ uses: actions/upload-artifact@v4 + with: + name: cross-${{ matrix.os }}-${{ matrix.arch }} + path: test-progs.tar ++ overwrite: true + + test: + runs-on: ubuntu-22.04 +@@ -61,11 +60,11 @@ jobs: + run: echo CONTAINER_ARCH="arm/v7" >> $GITHUB_ENV + if: ${{ matrix.arch == 'armhf' }} + - name: download binary archive +- uses: actions/download-artifact@v1 ++ uses: actions/download-artifact@v4 + with: + name: cross-${{ matrix.os }}-${{ matrix.arch }} + - name: unpack binary archive +- run: tar xfv cross-${{ matrix.os }}-${{ matrix.arch }}/test-progs.tar ++ run: tar xfv test-progs.tar + - name: enable foreign arch + uses: dbhi/qus/action@main + - name: run tests +@@ -100,11 +99,11 @@ jobs: + run: echo CONTAINER_ARCH="arm/v7" >> $GITHUB_ENV + if: ${{ matrix.arch == 'armhf' }} + - name: download binary archive +- uses: actions/download-artifact@v1 ++ uses: actions/download-artifact@v4 + with: + name: cross-${{ matrix.os }}-${{ matrix.arch }} + - name: unpack binary archive +- run: tar xfv cross-${{ matrix.os }}-${{ matrix.arch }}/test-progs.tar ++ run: tar xfv test-progs.tar + - name: enable foreign arch + uses: dbhi/qus/action@main + - name: run tests +diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml +index 80ff6df5..500becaa 100644 +--- a/.github/workflows/native.yaml ++++ b/.github/workflows/native.yaml +@@ -57,10 +57,11 @@ jobs: + - name: create binary archive + run: make ${{ env.ARCHIVE_TGT }} + - name: upload binary archive +- uses: actions/upload-artifact@v1 ++ uses: actions/upload-artifact@v4 + with: + name: native-${{ matrix.os }} + path: ${{ env.ARCHIVE_TGT }} ++ overwrite: true + + - name: clean + run: make clean +@@ -98,7 +99,7 @@ jobs: + uses: actions/checkout@v1 + + - name: download binary archive +- uses: actions/download-artifact@v1 ++ uses: actions/download-artifact@v4 + with: + name: native-${{ matrix.os }} + - name: unpack binary archive diff --git a/0002-GitHub-workflows-update-dawidd6-action-download-arti.patch b/0002-GitHub-workflows-update-dawidd6-action-download-arti.patch new file mode 100644 index 0000000..423bf56 --- /dev/null +++ b/0002-GitHub-workflows-update-dawidd6-action-download-arti.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 13 Sep 2024 09:10:38 +0200 +Subject: [PATCH] GitHub workflows: update dawidd6/action-download-artifact + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + .github/workflows/abi.yaml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/.github/workflows/abi.yaml b/.github/workflows/abi.yaml +index dce09f5c..d5f8b477 100644 +--- a/.github/workflows/abi.yaml ++++ b/.github/workflows/abi.yaml +@@ -28,7 +28,7 @@ jobs: + - name: get reference ABI + id: reference + continue-on-error: true +- uses: dawidd6/action-download-artifact@v2 ++ uses: dawidd6/action-download-artifact@v6 + with: + workflow: abi.yaml + branch: ${{ env.ABI_BRANCH }} diff --git a/0003-Github-workflows-native.yml-use-mosteo-actions-docke.patch b/0003-Github-workflows-native.yml-use-mosteo-actions-docke.patch new file mode 100644 index 0000000..63aa273 --- /dev/null +++ b/0003-Github-workflows-native.yml-use-mosteo-actions-docke.patch @@ -0,0 +1,98 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 13 Sep 2024 09:45:25 +0200 +Subject: [PATCH] Github workflows: native.yml: use mosteo-actions/docker-run + +We can't use "container:" any more because upload-artifact@v4 doesn't +work on Debian Jessie. + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + .github/workflows/native.yaml | 45 +++++++++++++++++++++-------------- + 1 file changed, 27 insertions(+), 18 deletions(-) + +diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml +index 500becaa..70d01c55 100644 +--- a/.github/workflows/native.yaml ++++ b/.github/workflows/native.yaml +@@ -35,17 +35,9 @@ jobs: + - debian-bookworm + - fedora-40 + - opensuse-leap +- container: ghcr.io/mwilck/multipath-build-${{ matrix.os }} + steps: + - name: checkout + uses: actions/checkout@v1 +- - name: build and test +- if: ${{ matrix.os != 'debian-jessie' }} +- run: make -j -Orecurse test +- - name: build and test (jessie) +- # On jessie, we use libreadline 5 (no licensing issue) +- if: ${{ matrix.os == 'debian-jessie' }} +- run: make -j -Orecurse READLINE=libreadline test + + - name: set archive name + # Leap containers have cpio but not tar +@@ -54,8 +46,21 @@ jobs: + - name: set archive name + run: echo ARCHIVE_TGT=test-progs.tar >> $GITHUB_ENV + if: ${{ matrix.os != 'opensuse-leap' }} +- - name: create binary archive +- run: make ${{ env.ARCHIVE_TGT }} ++ ++ - name: build and test ++ if: ${{ matrix.os != 'debian-jessie' }} ++ uses: mosteo-actions/docker-run@v1 ++ with: ++ image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} ++ command: -j -Orecurse ${{ env.ARCHIVE_TGT }} test ++ - name: build and test (jessie) ++ # On jessie, we use libreadline 5 (no licensing issue) ++ if: ${{ matrix.os == 'debian-jessie' }} ++ uses: mosteo-actions/docker-run@v1 ++ with: ++ image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} ++ command: -j -Orecurse READLINE=libreadline ${{ env.ARCHIVE_TGT }} test ++ + - name: upload binary archive + uses: actions/upload-artifact@v4 + with: +@@ -67,14 +72,18 @@ jobs: + run: make clean + - name: clang + if: ${{ matrix.os != 'debian-jessie' }} +- env: +- CC: clang +- run: make -j -Orecurse test ++ uses: mosteo-actions/docker-run@v1 ++ with: ++ image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} ++ params: -e CC=clang ++ command: -j -Orecurse test + - name: clang (jessie) + if: ${{ matrix.os == 'debian-jessie' }} +- env: +- CC: clang +- run: make READLINE=libreadline test ++ uses: mosteo-actions/docker-run@v1 ++ with: ++ image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} ++ params: -e CC=clang ++ command: -j -Orecurse READLINE=libreadline test + + root-test: + runs-on: ubuntu-22.04 +@@ -103,10 +112,10 @@ jobs: + with: + name: native-${{ matrix.os }} + - name: unpack binary archive +- run: cpio -idv < native-${{ matrix.os }}/test-progs.cpio ++ run: cpio -idv < test-progs.cpio + if: ${{ matrix.os == 'opensuse-leap' }} + - name: unpack binary archive +- run: tar xfmv native-${{ matrix.os }}/test-progs.tar ++ run: tar xfmv test-progs.tar + if: ${{ matrix.os != 'opensuse-leap' }} + + - name: run root tests diff --git a/0004-GitHub-workflows-native.yml-use-extra-job-for-clang.patch b/0004-GitHub-workflows-native.yml-use-extra-job-for-clang.patch new file mode 100644 index 0000000..e6d618c --- /dev/null +++ b/0004-GitHub-workflows-native.yml-use-extra-job-for-clang.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 13 Sep 2024 10:17:17 +0200 +Subject: [PATCH] GitHub workflows: native.yml: use extra job for clang + +Running "make" in a container and "make clean" outside doesn't +work (access right issues). So just use separate jobs. + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + .github/workflows/native.yaml | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml +index 70d01c55..95b53b87 100644 +--- a/.github/workflows/native.yaml ++++ b/.github/workflows/native.yaml +@@ -68,8 +68,22 @@ jobs: + path: ${{ env.ARCHIVE_TGT }} + overwrite: true + +- - name: clean +- run: make clean ++ clang: ++ runs-on: ubuntu-22.04 ++ strategy: ++ fail-fast: false ++ matrix: ++ os: ++ - debian-jessie ++ - debian-buster ++ - debian-bullseye ++ - debian-bookworm ++ - fedora-40 ++ - opensuse-leap ++ steps: ++ - name: checkout ++ uses: actions/checkout@v1 ++ + - name: clang + if: ${{ matrix.os != 'debian-jessie' }} + uses: mosteo-actions/docker-run@v1 diff --git a/0005-GitHub-workflows-native.yaml-make-test-and-archive-s.patch b/0005-GitHub-workflows-native.yaml-make-test-and-archive-s.patch new file mode 100644 index 0000000..cabfbcf --- /dev/null +++ b/0005-GitHub-workflows-native.yaml-make-test-and-archive-s.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 13 Sep 2024 10:30:47 +0200 +Subject: [PATCH] GitHub workflows: native.yaml: make test and archive + separately + +Avoid "text file busy" error on GitHub. + +dmevents-test: Text file busy +Makefile:74: recipe for target 'dmevents.out' failed + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + .github/workflows/native.yaml | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml +index 95b53b87..f06b09df 100644 +--- a/.github/workflows/native.yaml ++++ b/.github/workflows/native.yaml +@@ -52,14 +52,27 @@ jobs: + uses: mosteo-actions/docker-run@v1 + with: + image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} +- command: -j -Orecurse ${{ env.ARCHIVE_TGT }} test ++ command: -j -Orecurse test + - name: build and test (jessie) + # On jessie, we use libreadline 5 (no licensing issue) + if: ${{ matrix.os == 'debian-jessie' }} + uses: mosteo-actions/docker-run@v1 + with: + image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} +- command: -j -Orecurse READLINE=libreadline ${{ env.ARCHIVE_TGT }} test ++ command: -j -Orecurse READLINE=libreadline test ++ ++ - name: create ${{ env.ARCHIVE_TGT }} ++ if: ${{ matrix.os != 'debian-jessie' }} ++ uses: mosteo-actions/docker-run@v1 ++ with: ++ image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} ++ command: ${{ env.ARCHIVE_TGT }} ++ - name: create ${{ env.ARCHIVE_TGT }} (jessie) ++ if: ${{ matrix.os == 'debian-jessie' }} ++ uses: mosteo-actions/docker-run@v1 ++ with: ++ image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} ++ command: READLINE=libreadline ${{ env.ARCHIVE_TGT }} + + - name: upload binary archive + uses: actions/upload-artifact@v4 diff --git a/0006-GitHub-workflows-enable-unit-tests-for-stable-branch.patch b/0006-GitHub-workflows-enable-unit-tests-for-stable-branch.patch new file mode 100644 index 0000000..4a9b254 --- /dev/null +++ b/0006-GitHub-workflows-enable-unit-tests-for-stable-branch.patch @@ -0,0 +1,133 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 14 Nov 2024 16:02:38 +0100 +Subject: [PATCH] GitHub workflows: enable unit tests for stable branches + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + .github/workflows/build-and-unittest.yaml | 2 ++ + .github/workflows/foreign.yaml | 2 ++ + .github/workflows/multiarch-stable.yaml | 2 ++ + .github/workflows/multiarch.yaml | 2 ++ + .github/workflows/native.yaml | 2 ++ + .github/workflows/rolling.yaml | 2 ++ + 6 files changed, 12 insertions(+) + +diff --git a/.github/workflows/build-and-unittest.yaml b/.github/workflows/build-and-unittest.yaml +index a838f9a2..1a727e14 100644 +--- a/.github/workflows/build-and-unittest.yaml ++++ b/.github/workflows/build-and-unittest.yaml +@@ -5,10 +5,12 @@ on: + - master + - queue + - tip ++ - 'stable-*' + pull_request: + branches: + - master + - queue ++ - 'stable-*' + jobs: + jammy: + runs-on: ubuntu-22.04 +diff --git a/.github/workflows/foreign.yaml b/.github/workflows/foreign.yaml +index d68650df..0f80957b 100644 +--- a/.github/workflows/foreign.yaml ++++ b/.github/workflows/foreign.yaml +@@ -5,6 +5,7 @@ on: + - master + - queue + - tip ++ - 'stable-*' + paths: + - '.github/workflows/foreign.yaml' + - '**.h' +@@ -15,6 +16,7 @@ on: + branches: + - master + - queue ++ - 'stable-*' + paths: + - '.github/workflows/foreign.yaml' + - '**.h' +diff --git a/.github/workflows/multiarch-stable.yaml b/.github/workflows/multiarch-stable.yaml +index e51d383c..ffede53d 100644 +--- a/.github/workflows/multiarch-stable.yaml ++++ b/.github/workflows/multiarch-stable.yaml +@@ -5,6 +5,7 @@ on: + - master + - queue + - tip ++ - 'stable-*' + paths: + - '.github/workflows/multiarch-stable.yaml' + - '**.h' +@@ -15,6 +16,7 @@ on: + branches: + - master + - queue ++ - 'stable-*' + paths: + - '.github/workflows/multiarch-stable.yaml' + - '**.h' +diff --git a/.github/workflows/multiarch.yaml b/.github/workflows/multiarch.yaml +index df95a02f..d2b833a4 100644 +--- a/.github/workflows/multiarch.yaml ++++ b/.github/workflows/multiarch.yaml +@@ -5,6 +5,7 @@ on: + - master + - queue + - tip ++ - 'stable-*' + paths: + - '.github/workflows/multiarch.yaml' + - '**.h' +@@ -15,6 +16,7 @@ on: + branches: + - master + - queue ++ - 'stable-*' + paths: + - '.github/workflows/multiarch.yaml' + - '**.h' +diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml +index f06b09df..c9d9df9e 100644 +--- a/.github/workflows/native.yaml ++++ b/.github/workflows/native.yaml +@@ -5,6 +5,7 @@ on: + - master + - queue + - tip ++ - 'stable-*' + paths: + - '.github/workflows/native.yaml' + - '**.h' +@@ -15,6 +16,7 @@ on: + branches: + - master + - queue ++ - 'stable-*' + paths: + - '.github/workflows/native.yaml' + - '**.h' +diff --git a/.github/workflows/rolling.yaml b/.github/workflows/rolling.yaml +index 3536b944..66af7a44 100644 +--- a/.github/workflows/rolling.yaml ++++ b/.github/workflows/rolling.yaml +@@ -5,6 +5,7 @@ on: + - master + - queue + - tip ++ - 'stable-*' + paths: + - '.github/workflows/rolling.yaml' + - '**.h' +@@ -15,6 +16,7 @@ on: + branches: + - master + - queue ++ - 'stable-*' + paths: + - '.github/workflows/rolling.yaml' + - '**.h' diff --git a/0007-GitHub-Workflows-add-abi-check-for-stable-branches.patch b/0007-GitHub-Workflows-add-abi-check-for-stable-branches.patch new file mode 100644 index 0000000..c19980f --- /dev/null +++ b/0007-GitHub-Workflows-add-abi-check-for-stable-branches.patch @@ -0,0 +1,110 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 14 Nov 2024 16:51:05 +0100 +Subject: [PATCH] GitHub Workflows: add abi check for stable branches + +The ABI should never change on a stable branch. This workflow +asserts that. + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + .github/workflows/abi-stable.yaml | 89 +++++++++++++++++++++++++++++++ + 1 file changed, 89 insertions(+) + create mode 100644 .github/workflows/abi-stable.yaml + +diff --git a/.github/workflows/abi-stable.yaml b/.github/workflows/abi-stable.yaml +new file mode 100644 +index 00000000..a6746f23 +--- /dev/null ++++ b/.github/workflows/abi-stable.yaml +@@ -0,0 +1,89 @@ ++name: check-abi for stable branch ++on: ++ push: ++ branches: ++ - 'stable-*' ++ paths: ++ - '.github/workflows/abi-stable.yaml' ++ - '**.h' ++ - '**.c' ++ - '**.version' ++ pull_request: ++ branches: ++ - 'stable-*' ++ workflow_dispatch: ++ ++jobs: ++ reference-abi: ++ runs-on: ubuntu-20.04 ++ steps: ++ - name: get parent tag ++ run: > ++ echo ${{ github.ref }} | ++ sed -E 's,refs/heads/stable-([0-9]\.[0-9]*)\.y,PARENT_TAG=\1.0,' >> $GITHUB_ENV ++ - name: assert parent tag ++ run: /bin/false ++ if: ${{ env.PARENT_TAG == '' }} ++ - name: update ++ run: sudo apt-get update ++ - name: dependencies ++ run: > ++ sudo apt-get install --yes gcc ++ gcc make pkg-config abigail-tools ++ libdevmapper-dev libreadline-dev libaio-dev libsystemd-dev ++ libudev-dev libjson-c-dev liburcu-dev libcmocka-dev libedit-dev ++ - name: checkout ${{ env.PARENT_TAG }} ++ uses: actions/checkout@v4 ++ with: ++ ref: ${{ env.PARENT_TAG }} ++ - name: build ABI for ${{ env.PARENT_TAG }} ++ run: make -j$(grep -c ^processor /proc/cpuinfo) -Orecurse abi ++ - name: save ABI ++ uses: actions/upload-artifact@v4 ++ with: ++ name: multipath-abi-${{ env.PARENT_TAG }} ++ path: abi ++ ++ check-abi: ++ runs-on: ubuntu-20.04 ++ needs: reference-abi ++ steps: ++ - name: get parent tag ++ run: > ++ echo ${{ github.ref }} | ++ sed -E 's,refs/heads/stable-([0-9]\.[0-9]*)\.y,PARENT_TAG=\1.0,' >> $GITHUB_ENV ++ - name: assert parent tag ++ run: /bin/false ++ if: ${{ env.PARENT_TAG == '' }} ++ - name: checkout ${{ env.PARENT_TAG }} ++ uses: actions/checkout@v4 ++ with: ++ ref: ${{ env.PARENT_TAG }} ++ - name: download ABI for ${{ env.PARENT_TAG }} ++ id: download_abi ++ uses: actions/download-artifact@v4 ++ with: ++ name: multipath-abi-${{ env.PARENT_TAG }} ++ path: reference-abi ++ - name: update ++ run: sudo apt-get update ++ if: steps.download_abi.outcome != 'success' ++ - name: dependencies ++ run: > ++ sudo apt-get install --yes gcc ++ gcc make pkg-config abigail-tools ++ libdevmapper-dev libreadline-dev libaio-dev libsystemd-dev ++ libudev-dev libjson-c-dev liburcu-dev libcmocka-dev libedit-dev ++ - name: check ABI of ${{ github.ref }} against ${{ env.PARENT_TAG }} ++ id: check_abi ++ run: make -j$(grep -c ^processor /proc/cpuinfo) -Orecurse abi-test ++ continue-on-error: true ++ - name: save differences ++ if: ${{ steps.check_abi.outcome != 'success' }} ++ uses: actions/upload-artifact@v4 ++ with: ++ name: abi-test ++ path: abi-test ++ - name: fail ++ run: /bin/false ++ if: steps.check_abi.outcome != 'success' diff --git a/0008-libmultipath-dm_get_maps-don-t-bail-out-for-single-m.patch b/0008-libmultipath-dm_get_maps-don-t-bail-out-for-single-m.patch new file mode 100644 index 0000000..88122b0 --- /dev/null +++ b/0008-libmultipath-dm_get_maps-don-t-bail-out-for-single-m.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 12 Nov 2024 13:06:10 +0100 +Subject: [PATCH] libmultipath: dm_get_maps(): don't bail out for single-map + failures + +dm_get_maps() traverses the entire list of dm maps. We shouldn't +give up just because probing a single map failed. + +Fixes: bf3a4ad ("libmultipath: simplify dm_get_maps()") +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/devmapper.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c +index c497c225..52bfe9ce 100644 +--- a/libmultipath/devmapper.c ++++ b/libmultipath/devmapper.c +@@ -1262,10 +1262,8 @@ int dm_get_maps(vector mp) + } + vector_set_slot(mp, mpp); + break; +- case DMP_NO_MATCH: +- break; + default: +- return 1; ++ break; + } + next = names->next; + names = (void *) names + next; diff --git a/0009-11-dm-mpath.rules.in-import-DM_COLDPLUG_SUSPENDED-on.patch b/0009-11-dm-mpath.rules.in-import-DM_COLDPLUG_SUSPENDED-on.patch new file mode 100644 index 0000000..b380f75 --- /dev/null +++ b/0009-11-dm-mpath.rules.in-import-DM_COLDPLUG_SUSPENDED-on.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 31 Oct 2024 12:08:08 +0100 +Subject: [PATCH] 11-dm-mpath.rules.in: import DM_COLDPLUG_SUSPENDED only once + +We import DM_COLDPLUG_SUSPENDED in all code flows below mpath_coldplug_end. +Clarify this in the code. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipath/11-dm-mpath.rules.in | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in +index 30647b99..67838261 100644 +--- a/multipath/11-dm-mpath.rules.in ++++ b/multipath/11-dm-mpath.rules.in +@@ -24,12 +24,13 @@ ENV{DM_UDEV_RULES_VSN}=="1|2", ENV{.DM_SUSPENDED}!="1", ENV{DISK_RO}!="1", \ + ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="", GOTO="scan_import" + LABEL="mpath_coldplug_end" + ++IMPORT{db}="DM_COLDPLUG_SUSPENDED" ++ + # If this uevent didn't come from dm, don't try to update the + # device state + # Note that .MPATH_DEVICE_READY_OLD=="" here. Thus we won't activate the + # device below at mpath_is_ready, which is correct. + ENV{DM_COOKIE}!="?*", ENV{DM_ACTION}!="PATH_*", \ +- IMPORT{db}="DM_COLDPLUG_SUSPENDED", \ + GOTO="check_mpath_ready" + + ENV{.MPATH_DEVICE_READY_OLD}="$env{MPATH_DEVICE_READY}" +@@ -67,7 +68,6 @@ LABEL="check_mpath_unchanged" + # A previous coldplug event occurred while the device was suspended. + # Activation might have been partially skipped. Activate the device now, + # i.e. disable the MPATH_UNCHANGED logic and set DM_ACTIVATION=1. +-IMPORT{db}="DM_COLDPLUG_SUSPENDED" + ENV{DM_COLDPLUG_SUSPENDED}=="1", ENV{.DM_SUSPENDED}!="1", \ + ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0", \ + PROGRAM="@SYSDIR_BIN@/logger -t 11-dm-mpath.rules -p daemon.notice \"Forcing activation of previously suspended device\"", \ diff --git a/0010-11-dm-mpath.rules.in-handle-inactive-suspended-devic.patch b/0010-11-dm-mpath.rules.in-handle-inactive-suspended-devic.patch new file mode 100644 index 0000000..f34e699 --- /dev/null +++ b/0010-11-dm-mpath.rules.in-handle-inactive-suspended-devic.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 31 Oct 2024 12:59:03 +0100 +Subject: [PATCH] 11-dm-mpath.rules.in: handle inactive suspended devices + correctly + +Since b22c273 ("11-dm-mpath.rules: Don't force activation while device is +suspended"), we've handled the case where a device is suspended while +an uevent is processed (e.g. because multipathd is reloading the +map again at the same time). But we were missing the case where +The device had never been initialized before. If .MPATH_DEVICE_READY_OLD +was empty, we'd jump to scan_import without setting MPATH_DEVICE_READY +to 0. This can cause a device not to be fully activated at boot time, +because in follow-up uevents we'd assume that the device had already +been set up. + +Treat the case in which an uevent is processed for a previously not +fully set-up, suspended device like other situations where we set +MPATH_DEVICE_READY to 0. + +Fixes: b22c273 ("11-dm-mpath.rules: Don't force activation while device is +suspended") +Reviewed-by: Benjamin Marzinski + +Signed-off-by: Benjamin Marzinski +--- + multipath/11-dm-mpath.rules.in | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in +index 67838261..20f8c6ac 100644 +--- a/multipath/11-dm-mpath.rules.in ++++ b/multipath/11-dm-mpath.rules.in +@@ -35,6 +35,13 @@ ENV{DM_COOKIE}!="?*", ENV{DM_ACTION}!="PATH_*", \ + + ENV{.MPATH_DEVICE_READY_OLD}="$env{MPATH_DEVICE_READY}" + ++# If the device wasn't ready previously and is currently suspended, ++# we have to postpone the activation until the next event. ++# In this case, we have to set MPATH_DEVICE_READY=0; otherwise, the ++# MPATH_UNCHANGED logic will cause later rules to skipped in the next event. ++ENV{.MPATH_DEVICE_READY_OLD}!="1", ENV{.DM_SUSPENDED}=="1", \ ++ ENV{MPATH_DEVICE_READY}="0", GOTO="check_mpath_unchanged" ++ + # multipath sets DM_SUBSYSTEM_UDEV_FLAG2 when it reloads a + # table with no active devices. If this happens, mark the + # device not ready +@@ -106,14 +113,10 @@ GOTO="scan_import" + LABEL="mpath_is_ready" + + # If the device comes back online, set DM_ACTIVATION so that +-# upper layers do a rescan. If the device is currently suspended, +-# we have to postpone the activation until the next event. +-# In this case, we have to set MPATH_DEVICE_READY=0; otherwise, the +-# MPATH_UNCHANGED logic will cause later rules to skipped in the next event. +-ENV{.MPATH_DEVICE_READY_OLD}!="0", GOTO="scan_import" +-ENV{.DM_SUSPENDED}=="1", ENV{MPATH_DEVICE_READY}="0", GOTO="scan_import" +- +-ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0" ++# upper layers will do a rescan. Don't do this if .MPATH_DEVICE_READY_OLD ++# is just empty (see comment above the DM_COOKIE test above). ++ENV{.MPATH_DEVICE_READY_OLD}=="0", \ ++ ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0" + + # The code to check multipath state ends here. We need to set + # properties and symlinks regardless whether the map is usable or diff --git a/0011-11-dm-mpath.rules.in-clarify-DM_ACTIVATION-logic.patch b/0011-11-dm-mpath.rules.in-clarify-DM_ACTIVATION-logic.patch new file mode 100644 index 0000000..cb129bf --- /dev/null +++ b/0011-11-dm-mpath.rules.in-clarify-DM_ACTIVATION-logic.patch @@ -0,0 +1,78 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 31 Oct 2024 13:11:21 +0100 +Subject: [PATCH] 11-dm-mpath.rules.in: clarify DM_ACTIVATION logic + +Our code is always setting MPATH_UNCHANGED and DM_ACTIVATION in +pairs. While DM_ACTIVATION is a global DM property, MPATH_UNCHANGED +is owned by us. Just set MPATH_UNCHANGED, and adapt DM_ACTIVATION +when necessary just in one place. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipath/11-dm-mpath.rules.in | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in +index 20f8c6ac..a2655cb2 100644 +--- a/multipath/11-dm-mpath.rules.in ++++ b/multipath/11-dm-mpath.rules.in +@@ -74,25 +74,25 @@ LABEL="check_mpath_unchanged" + + # A previous coldplug event occurred while the device was suspended. + # Activation might have been partially skipped. Activate the device now, +-# i.e. disable the MPATH_UNCHANGED logic and set DM_ACTIVATION=1. ++# i.e. disable the MPATH_UNCHANGED logic. + ENV{DM_COLDPLUG_SUSPENDED}=="1", ENV{.DM_SUSPENDED}!="1", \ +- ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0", \ ++ ENV{MPATH_UNCHANGED}="0", \ + PROGRAM="@SYSDIR_BIN@/logger -t 11-dm-mpath.rules -p daemon.notice \"Forcing activation of previously suspended device\"", \ + GOTO="check_mpath_ready" + + # DM_SUBSYSTEM_UDEV_FLAG0 is the "RELOAD" flag for multipath subsystem. +-# Drop the DM_ACTIVATION flag here as mpath reloads tables if any of its ++# Set the MPATH_UNCHANGED flag here as mpath reloads tables if any of its + # paths are lost/recovered. For any stack above the mpath device, this is not + # something that should be reacted upon since it would be useless extra work. + # It's exactly mpath's job to provide *seamless* device access to any of the + # paths that are available underneath. + ENV{DM_SUBSYSTEM_UDEV_FLAG0}=="1", \ +- ENV{DM_ACTIVATION}="0", ENV{MPATH_UNCHANGED}="1" ++ ENV{MPATH_UNCHANGED}="1" + +-# For path failed or reinstated events, unset DM_ACTIVATION. ++# For path failed or reinstated events, set MPATH_UNCHANGED. + # This is similar to the DM_SUBSYSTEM_UDEV_FLAG0 case above. + ENV{DM_ACTION}=="PATH_FAILED|PATH_REINSTATED", \ +- ENV{DM_ACTIVATION}="0", ENV{MPATH_UNCHANGED}="1" ++ ENV{MPATH_UNCHANGED}="1" + + LABEL="check_mpath_ready" + +@@ -112,11 +112,10 @@ GOTO="scan_import" + + LABEL="mpath_is_ready" + +-# If the device comes back online, set DM_ACTIVATION so that ++# If the device comes back online, clear MPATH_UNCHANGED so that + # upper layers will do a rescan. Don't do this if .MPATH_DEVICE_READY_OLD + # is just empty (see comment above the DM_COOKIE test above). +-ENV{.MPATH_DEVICE_READY_OLD}=="0", \ +- ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0" ++ENV{.MPATH_DEVICE_READY_OLD}=="0", ENV{MPATH_UNCHANGED}="0" + + # The code to check multipath state ends here. We need to set + # properties and symlinks regardless whether the map is usable or +@@ -146,6 +145,10 @@ IMPORT{db}="ID_PART_GPT_AUTO_ROOT" + + LABEL="import_end" + ++# If MPATH_UNCHANGED is set, adapt DM_ACTIVATION. ++ENV{MPATH_UNCHANGED}=="0", ENV{DM_ACTIVATION}="1" ++ENV{MPATH_UNCHANGED}=="1", ENV{DM_ACTIVATION}="0" ++ + # Reset previous DM_COLDPLUG_SUSPENDED if activation happens now + ENV{.DM_SUSPENDED}!="1", ENV{DM_ACTIVATION}=="1", ENV{DM_COLDPLUG_SUSPENDED}="" + diff --git a/0012-11-dm-mpath-rules.in-skip-one-.DM_NOSCAN-check.patch b/0012-11-dm-mpath-rules.in-skip-one-.DM_NOSCAN-check.patch new file mode 100644 index 0000000..cb1620a --- /dev/null +++ b/0012-11-dm-mpath-rules.in-skip-one-.DM_NOSCAN-check.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Sun, 3 Nov 2024 23:04:08 +0100 +Subject: [PATCH] 11-dm-mpath-rules.in: skip one .DM_NOSCAN check + +We set .DM_NOSCAN above where we set DM_UDEV_DISABLE_OTHER_RULES_FLAG, too. If +the latter isn't set, .DM_NOSCAN can't be set. Skip the redundant test. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipath/11-dm-mpath.rules.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in +index a2655cb2..79227bec 100644 +--- a/multipath/11-dm-mpath.rules.in ++++ b/multipath/11-dm-mpath.rules.in +@@ -132,7 +132,7 @@ ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}!="1", GOTO="import_end" + ENV{DM_UDEV_RULES_VSN}!="1|2", GOTO="import_end" + + # Don't import the properties from db if we will run blkid later. +-ENV{.DM_NOSCAN}!="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}!="1", GOTO="import_end" ++ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}!="1", GOTO="import_end" + + IMPORT{db}="ID_FS_TYPE" + IMPORT{db}="ID_FS_USAGE" diff --git a/0013-11-dm-mpath.rules.in-set-.DM_NOSCAN-if-MPATH_UNCHANG.patch b/0013-11-dm-mpath.rules.in-set-.DM_NOSCAN-if-MPATH_UNCHANG.patch new file mode 100644 index 0000000..36cd91d --- /dev/null +++ b/0013-11-dm-mpath.rules.in-set-.DM_NOSCAN-if-MPATH_UNCHANG.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Sun, 3 Nov 2024 23:07:23 +0100 +Subject: [PATCH] 11-dm-mpath.rules.in: set .DM_NOSCAN if MPATH_UNCHANGED is + set + +When multipath reloads a device or fails or restores a path, the udev +rules disable LVM scanning, but since .DM_NOSCAN isn't set, blkid is +still run on the device. When multipath devices that are set to +queue_if_no_path lose all their paths at close to the same time, udev +workers can hang trying to run blkid. The blkid results shouldn't +change when multipathd is adding, removing, failing or reinstating +paths, aside from avoiding hanging udev processes, we're skipping +unnecessary work. + +Hence, set .DM_NOSCAN if MPATH_UNCHANGED is set, to avoid blkid from +being called in 13-dm.rules. + +Suggested-by: Benjamin Marzinski +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipath/11-dm-mpath.rules.in | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in +index 79227bec..a816edbf 100644 +--- a/multipath/11-dm-mpath.rules.in ++++ b/multipath/11-dm-mpath.rules.in +@@ -145,9 +145,11 @@ IMPORT{db}="ID_PART_GPT_AUTO_ROOT" + + LABEL="import_end" + +-# If MPATH_UNCHANGED is set, adapt DM_ACTIVATION. ++# If MPATH_UNCHANGED is set, adapt DM_ACTIVATION and DM_NOSCAN. ++# .DM_NOSCAN controls whether blkid will be run in 13-dm-disk.rules; ++# we don't want to do that if MPATH_UNCHANGED is 1. + ENV{MPATH_UNCHANGED}=="0", ENV{DM_ACTIVATION}="1" +-ENV{MPATH_UNCHANGED}=="1", ENV{DM_ACTIVATION}="0" ++ENV{MPATH_UNCHANGED}=="1", ENV{DM_ACTIVATION}="0", ENV{.DM_NOSCAN}="1" + + # Reset previous DM_COLDPLUG_SUSPENDED if activation happens now + ENV{.DM_SUSPENDED}!="1", ENV{DM_ACTIVATION}=="1", ENV{DM_COLDPLUG_SUSPENDED}="" diff --git a/0014-libmultipath-don-t-set-dev_loss_tmo-to-0-for-NO_PATH.patch b/0014-libmultipath-don-t-set-dev_loss_tmo-to-0-for-NO_PATH.patch new file mode 100644 index 0000000..b7ae3c4 --- /dev/null +++ b/0014-libmultipath-don-t-set-dev_loss_tmo-to-0-for-NO_PATH.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 7 Nov 2024 22:07:03 +0100 +Subject: [PATCH] libmultipath: don't set dev_loss_tmo to 0 for + NO_PATH_RETRY_FAIL + +If pp->dev_loss is DEV_LOSS_TMO_UNSET and min_dev_loss is 0 (which is +the case if no_path_retry is NO_PATH_RETRY_FAIL or NO_PATH_RETRY_UNDEF), +we will set pp->dev_loss to 0, which is wrong. Fix it. + +Fixes: 058b5f5 ("libmultipath: fix dev_loss_tmo even if not set in configuration") +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/discovery.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index e94705bf..5043330c 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -942,7 +942,7 @@ sysfs_set_scsi_tmo (struct config *conf, struct multipath *mpp) + continue; + } + +- if (pp->dev_loss == DEV_LOSS_TMO_UNSET) ++ if (pp->dev_loss == DEV_LOSS_TMO_UNSET && min_dev_loss != 0) + pp->dev_loss = min_dev_loss; + else if (pp->dev_loss < min_dev_loss) { + pp->dev_loss = min_dev_loss; diff --git a/0015-multipathd-fix-deferred_failback_tick-for-reload-rem.patch b/0015-multipathd-fix-deferred_failback_tick-for-reload-rem.patch new file mode 100644 index 0000000..f775e85 --- /dev/null +++ b/0015-multipathd-fix-deferred_failback_tick-for-reload-rem.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Mon, 14 Oct 2024 23:28:30 -0400 +Subject: [PATCH] multipathd: fix deferred_failback_tick for reload removes + +If reload_and_sync_map() removes the multipath device, +deferred_failback_tick() needs to decrement the counter so that it +doesn't skip the following device. + +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + multipathd/main.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index 1b7fd04f..e4ef9a1d 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -2080,9 +2080,12 @@ deferred_failback_tick (struct vectors *vecs) + + if (!mpp->failback_tick && + need_switch_pathgroup(mpp, &need_reload)) { +- if (need_reload) +- reload_and_sync_map(mpp, vecs); +- else ++ if (need_reload) { ++ if (reload_and_sync_map(mpp, vecs) == 2) { ++ /* multipath device removed */ ++ i--; ++ } ++ } else + switch_pathgroup(mpp); + } + } diff --git a/0016-multipathd-fix-an-unsigned-int-ovwerflow.patch b/0016-multipathd-fix-an-unsigned-int-ovwerflow.patch new file mode 100644 index 0000000..12c9a51 --- /dev/null +++ b/0016-multipathd-fix-an-unsigned-int-ovwerflow.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 13 Nov 2024 16:19:49 +0100 +Subject: [PATCH] multipathd: fix an unsigned int ovwerflow + +Reported by coverity: "i--" may cause an underflow, which will again +cause an overflow when the loop continues. Use a signed int for +loops like this to make coverity happy. + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + multipathd/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index e4ef9a1d..3fb623fd 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -2068,7 +2068,7 @@ static void + deferred_failback_tick (struct vectors *vecs) + { + struct multipath * mpp; +- unsigned int i; ++ int i; + bool need_reload; + + vector_foreach_slot (vecs->mpvec, mpp, i) { diff --git a/0017-libmpathutil-avoid-Wcast-function-type-mismatch-erro.patch b/0017-libmpathutil-avoid-Wcast-function-type-mismatch-erro.patch new file mode 100644 index 0000000..64b90d7 --- /dev/null +++ b/0017-libmpathutil-avoid-Wcast-function-type-mismatch-erro.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 6 Nov 2024 22:17:16 +0100 +Subject: [PATCH] libmpathutil: avoid -Wcast-function-type-mismatch error with + clang 19 + +Avoid the following error with clang 19: + +msort.c:268:27: error: cast from '__compar_fn_t' (aka 'int (*)(const void *, const void *)') to '__compar_d_fn_t' (aka 'int (*)(const void *, const void *, void *)') converts to incompatible function type [-Werror,-Wcast-function-type-mismatch] + 268 | return msort_r (b, n, s, (__compar_d_fn_t)cmp, NULL); + | ^~~~~~~~~~~~~~~~~~~~ + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmpathutil/msort.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/libmpathutil/msort.c b/libmpathutil/msort.c +index 50f799d9..9df7b267 100644 +--- a/libmpathutil/msort.c ++++ b/libmpathutil/msort.c +@@ -259,9 +259,12 @@ msort_r (void *b, size_t n, size_t s, __compar_d_fn_t cmp, void *arg) + * If this is safe for them, it should be for us, too. + */ + #pragma GCC diagnostic push +-#if __GNUC__ >= 8 ++#if __GNUC__ >= 8 || __clang_major__ >= 19 + #pragma GCC diagnostic ignored "-Wcast-function-type" + #endif ++#if __clang_major__ >= 19 ++#pragma GCC diagnostic ignored "-Wcast-function-type-mismatch" ++#endif + void + msort (void *b, size_t n, size_t s, __compar_fn_t cmp) + { diff --git a/0018-Update-NEWS.md-for-0.10.1.patch b/0018-Update-NEWS.md-for-0.10.1.patch new file mode 100644 index 0000000..601b6e5 --- /dev/null +++ b/0018-Update-NEWS.md-for-0.10.1.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 14 Nov 2024 17:59:14 +0100 +Subject: [PATCH] Update NEWS.md for 0.10.1 + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + NEWS.md | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/NEWS.md b/NEWS.md +index 69acda47..b740efb1 100644 +--- a/NEWS.md ++++ b/NEWS.md +@@ -1,5 +1,28 @@ + # multipath-tools Release Notes + ++## multipath-tools 0.10.1, 2024/11 ++ ++This is the first bug fix release on the `stable-0.10.y` branch. It contains ++bug fixes from 0.11.0, and some CI-related fixes. ++ ++### Bug fixes ++ ++* Fixed the problem that multipathd wouldn't start on systems with certain types ++ of device mapper devices, in particular devices with multiple DM targets. ++ The problem was introduced in 0.10.0. ++ Fixes [#102](https://github.com/opensvc/multipath-tools/issues/102). ++* Fixed a corner case in the udev rules which could cause a device not to be ++ activated during boot if a cold plug uevent is processed for a previously ++ not configured multipath map while this map was suspended. This problem existed ++ since 0.9.8. ++* Fixed the problem that devices with `no_path_retry fail` and no setting ++ for `dev_loss_tmo` might get the `dev_loss_tmo` set to 0, causing the ++ device to be deleted immediately in the event of a transport disruption. ++ This bug was introduced in 0.9.6. ++* Fixed the problem that, if there were multiple maps with deferred failback ++ (`failback` value > 0 in `multipath.conf`), some maps might fail back later ++ than configured. The problem existed since 0.9.6. ++ + ## multipath-tools 0.10.0, 2024/08 + + ### User-Visible Changes diff --git a/0019-libmultipath-don-t-print-error-message-if-WATCHDOG_U.patch b/0019-libmultipath-don-t-print-error-message-if-WATCHDOG_U.patch new file mode 100644 index 0000000..18fb614 --- /dev/null +++ b/0019-libmultipath-don-t-print-error-message-if-WATCHDOG_U.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 14 Nov 2024 15:20:24 +0100 +Subject: [PATCH] libmultipath: don't print error message if WATCHDOG_USEC is 0 + +WATCHDOG_USEC may be set to 0, which means that the watchdog +is disabled in systemd. + +Fixes: 9366cfb ("multipathd: Implement systemd watchdog integration") +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/config.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/libmultipath/config.c b/libmultipath/config.c +index 0e3a5cc1..226ddecb 100644 +--- a/libmultipath/config.c ++++ b/libmultipath/config.c +@@ -865,6 +865,9 @@ static void set_max_checkint_from_watchdog(struct config *conf) + unsigned long checkint; + + if (envp && sscanf(envp, "%lu", &checkint) == 1) { ++ if (checkint == 0) ++ /* watchdog disabled */ ++ return; + /* Value is in microseconds */ + checkint /= 1000000; + if (checkint < 1 || checkint > UINT_MAX) { diff --git a/0020-libmultipath-reduce-log-level-of-map-X-has-multiple-.patch b/0020-libmultipath-reduce-log-level-of-map-X-has-multiple-.patch new file mode 100644 index 0000000..7467627 --- /dev/null +++ b/0020-libmultipath-reduce-log-level-of-map-X-has-multiple-.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 25 Nov 2024 18:01:32 +0100 +Subject: [PATCH] libmultipath: reduce log level of "map X has multiple + targets" + +On systems with LVM volumes, "multipath -ll" will spit out lots of messages +like + + libmp_mapinfo: map vg-lv0 has multiple targets + +which is irritating. Reduce the log level of these messages to 3, as they +are harmless most of the time. + +This is a backport of e8949c2 ("libmultipath: reduce log level of +libmp_mapinfo() messages") from the master branch. We can't apply exactly +the same fix because the stable branch is missing 8c772d3 ("libmultipath: +check DM UUID earlier in libmp_mapinfo__"). + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/devmapper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c +index 52bfe9ce..fe5637b3 100644 +--- a/libmultipath/devmapper.c ++++ b/libmultipath/devmapper.c +@@ -718,7 +718,7 @@ static int libmp_mapinfo__(int flags, mapid_t id, mapinfo_t info, const char *ma + if (info.target || info.status || info.size || flags & MAPINFO_TGT_TYPE__) { + if (dm_get_next_target(dmt, NULL, &start, &length, + &target_type, ¶ms) != NULL) { +- condlog(2, "%s: map %s has multiple targets", fname__, map_id); ++ condlog(3, "%s: map %s has multiple targets", fname__, map_id); + return DMP_NOT_FOUND; + } + if (!params) { diff --git a/0021-libmultipath-foreign-fix-memory-leak-in-nvme-foreign.patch b/0021-libmultipath-foreign-fix-memory-leak-in-nvme-foreign.patch new file mode 100644 index 0000000..2610c6d --- /dev/null +++ b/0021-libmultipath-foreign-fix-memory-leak-in-nvme-foreign.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 8 Jan 2025 19:06:53 -0500 +Subject: [PATCH] libmultipath/foreign: fix memory leak in nvme foreign handler + +_find_controllers() needs to free the udev device if it doesn't get +added to a path. Otherwise it can leak memory whenever check_foreign() +is called, causing multipathd's memory usage to continually grow. + +Fixes: 7b47762 ("libmultipath: nvme: fix path detection for kernel 4.16") +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +(cherry picked from commit 5a3d334e416a4a35ee88d7b8f1433ff7f57923ad) +--- + libmultipath/foreign/nvme.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/libmultipath/foreign/nvme.c b/libmultipath/foreign/nvme.c +index 0b7f4eab..cde660ce 100644 +--- a/libmultipath/foreign/nvme.c ++++ b/libmultipath/foreign/nvme.c +@@ -675,7 +675,8 @@ static void _find_controllers(struct context *ctx, struct nvme_map *map) + pthread_cleanup_push_cast(free_scandir_result, &sr); + for (i = 0; i < r; i++) { + char *fn = di[i]->d_name; +- struct udev_device *ctrl, *udev; ++ struct udev_device *ctrl; ++ struct udev_device *udev __attribute__((cleanup(cleanup_udev_device))) = NULL; + + if (safe_snprintf(pathbuf + n, sizeof(pathbuf) - n, "/%s", fn)) + continue; +@@ -719,11 +720,11 @@ static void _find_controllers(struct context *ctx, struct nvme_map *map) + continue; + + path->gen.ops = &nvme_path_ops; +- path->udev = udev; ++ path->udev = steal_ptr(udev); + path->seen = true; + path->map = map; + path->ctl = udev_device_get_parent_with_subsystem_devtype +- (udev, "nvme", NULL); ++ (path->udev, "nvme", NULL); + if (path->ctl == NULL) { + condlog(1, "%s: %s: failed to get controller for %s", + __func__, THIS, fn); +@@ -744,7 +745,7 @@ static void _find_controllers(struct context *ctx, struct nvme_map *map) + } + vector_set_slot(&map->pgvec, &path->pg); + condlog(3, "%s: %s: new path %s added to %s", +- __func__, THIS, udev_device_get_sysname(udev), ++ __func__, THIS, udev_device_get_sysname(path->udev), + udev_device_get_sysname(map->udev)); + } + pthread_cleanup_pop(1); diff --git a/0022-libmultipath-add-condition-for-enqueueing-path-to-io.patch b/0022-libmultipath-add-condition-for-enqueueing-path-to-io.patch new file mode 100644 index 0000000..cf8d80a --- /dev/null +++ b/0022-libmultipath-add-condition-for-enqueueing-path-to-io.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chenrenhui +Date: Fri, 10 Jan 2025 14:38:16 +0800 +Subject: [PATCH] libmultipath: add condition for enqueueing path to io error + check + +In function io_err_stat_handle_pathfail(), path->io_err_dis_reinstate_time +is set to 0 to enqueue path to io error check as soon as possible. But +multipathd can not do it within marginal_path_err_recheck_gap_time seconds +after power-on, because curr_time is less than +marginal_path_err_recheck_gap_time. + +To handle the early marginal path, we can enqueue path when +io_err_dis_reinstate_time is 0. + +Signed-off-by: chenrenhui +Reviewed-by: Benjamin Marzinski +Reviewed-by: Martin Wilck + +> + +(cherry picked from commit a1e3cf2d42cc4bab10753e466c8adb7efa83c99e) +Signed-off-by: Benjamin Marzinski +--- + libmultipath/io_err_stat.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c +index 4996c0b0..879c310a 100644 +--- a/libmultipath/io_err_stat.c ++++ b/libmultipath/io_err_stat.c +@@ -367,7 +367,8 @@ int need_io_err_check(struct path *pp) + return 1; + get_monotonic_time(&curr_time); + if ((curr_time.tv_sec - pp->io_err_dis_reinstate_time) > +- pp->mpp->marginal_path_err_recheck_gap_time) { ++ pp->mpp->marginal_path_err_recheck_gap_time || ++ pp->io_err_dis_reinstate_time == 0) { + io_err_stat_log(4, "%s: reschedule checking after %d seconds", + pp->dev, + pp->mpp->marginal_path_err_recheck_gap_time); diff --git a/0023-Additional-NEWS.md-updates-for-0.10.1.patch b/0023-Additional-NEWS.md-updates-for-0.10.1.patch new file mode 100644 index 0000000..1093bd0 --- /dev/null +++ b/0023-Additional-NEWS.md-updates-for-0.10.1.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 17 Jan 2025 22:38:26 +0100 +Subject: [PATCH] Additional NEWS.md updates for 0.10.1 + +Signed-off-by: Benjamin Marzinski +--- + .github/actions/spelling/expect.txt | 4 ++-- + NEWS.md | 8 ++++++++ + 2 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt +index 934f582e..000d5ebb 100644 +--- a/.github/actions/spelling/expect.txt ++++ b/.github/actions/spelling/expect.txt +@@ -184,7 +184,6 @@ sas + sbp + scsi + sda +-sdc + setmarginal + setprkey + setprstatus +@@ -205,11 +204,11 @@ suse + svg + switchgroup + sys ++SYSDIR + sysfs + sysinit + tcp + terabytes +-SYSDIR + TESTDEPS + testname + tgill +@@ -231,6 +230,7 @@ unsetprkey + unsetprstatus + unspec + usb ++USEC + userdata + userspace + usr +diff --git a/NEWS.md b/NEWS.md +index b740efb1..3c51553e 100644 +--- a/NEWS.md ++++ b/NEWS.md +@@ -22,6 +22,14 @@ bug fixes from 0.11.0, and some CI-related fixes. + * Fixed the problem that, if there were multiple maps with deferred failback + (`failback` value > 0 in `multipath.conf`), some maps might fail back later + than configured. The problem existed since 0.9.6. ++* Removed a warning message that multipathd would print if systemd's ++ `WATCHDOG_USEC` environment variable had the value "0", which means that the ++ watchdog is simply disabled. This (minor) problem existed since 0.4.9. ++* Fixed a memory leak in the nvme foreign library. The bug existed since ++ 0.7.8. ++* Fixed a problem in the marginal path detection algorithm that could cause ++ the io error check for a recently failed path to be delayed. This bug ++ existed since 0.7.4. + + ## multipath-tools 0.10.0, 2024/08 + diff --git a/0024-libmultipath-fix-handling-of-pp-pgindex.patch b/0024-libmultipath-fix-handling-of-pp-pgindex.patch new file mode 100644 index 0000000..a9da346 --- /dev/null +++ b/0024-libmultipath-fix-handling-of-pp-pgindex.patch @@ -0,0 +1,138 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 25 Nov 2024 13:11:07 +0100 +Subject: [PATCH] libmultipath: fix handling of pp->pgindex + +pp->pgindex is set in disassemble_map() when a map is parsed. +There are various possiblities for this index to become invalid. +pp->pgindex is only used in enable_group() and followover_should_fallback(), +and both callers take no action if it is 0, which is the right +thing to do if we don't know the path's pathgroup. + +Make sure pp->pgindex is reset to 0 in various places: +- when it's orphaned, +- before (re)grouping paths, +- when we detect a bad mpp assignment in update_pathvec_from_dm(). +- when a pathgroup is deleted in update_pathvec_from_dm(). In this + case, pgindex needs to be invalidated for all paths in all pathgroups + after the one that was deleted. + +The hunk in group_paths is mostly redundant with the hunk in free_pgvec(), but +because we're looping over pg->paths in the former and over pg->pgp in +the latter, I think it's better too play safe. + +Fixes: 99db1bd ("[multipathd] re-enable disabled PG when at least one path is up") +Fixes: https://github.com/opensvc/multipath-tools/issues/105 +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +(cherry picked from commit cd912cffa2797a18c47426c816afa8eb2eae5b22) +(cherry picked from commit 714c20bebba6911255a527d937e7a62764ffe338) +Signed-off-by: Benjamin Marzinski +--- + libmultipath/pgpolicies.c | 6 ++++++ + libmultipath/structs.c | 12 +++++++++++- + libmultipath/structs_vec.c | 15 +++++++++++++++ + 3 files changed, 32 insertions(+), 1 deletion(-) + +diff --git a/libmultipath/pgpolicies.c b/libmultipath/pgpolicies.c +index edc3c611..23ef2bdc 100644 +--- a/libmultipath/pgpolicies.c ++++ b/libmultipath/pgpolicies.c +@@ -127,6 +127,8 @@ fail: + int group_paths(struct multipath *mp, int marginal_pathgroups) + { + vector normal, marginal; ++ struct path *pp; ++ int i; + + if (!mp->pg) + mp->pg = vector_alloc(); +@@ -138,6 +140,10 @@ int group_paths(struct multipath *mp, int marginal_pathgroups) + if (!mp->pgpolicyfn) + goto fail; + ++ /* Reset pgindex, we're going to invalidate it */ ++ vector_foreach_slot(mp->paths, pp, i) ++ pp->pgindex = 0; ++ + if (!marginal_pathgroups || + split_marginal_paths(mp->paths, &normal, &marginal) != 0) { + if (mp->pgpolicyfn(mp, mp->paths) != 0) +diff --git a/libmultipath/structs.c b/libmultipath/structs.c +index 61c8f32c..48517252 100644 +--- a/libmultipath/structs.c ++++ b/libmultipath/structs.c +@@ -239,8 +239,18 @@ free_pgvec (vector pgvec, enum free_path_mode free_paths) + if (!pgvec) + return; + +- vector_foreach_slot(pgvec, pgp, i) ++ vector_foreach_slot(pgvec, pgp, i) { ++ ++ /* paths are going to be re-grouped, reset pgindex */ ++ if (free_paths != FREE_PATHS) { ++ struct path *pp; ++ int j; ++ ++ vector_foreach_slot(pgp->paths, pp, j) ++ pp->pgindex = 0; ++ } + free_pathgroup(pgp, free_paths); ++ } + + vector_free(pgvec); + } +diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c +index 5df495b3..9dc5a5ca 100644 +--- a/libmultipath/structs_vec.c ++++ b/libmultipath/structs_vec.c +@@ -108,6 +108,7 @@ static bool update_pathvec_from_dm(vector pathvec, struct multipath *mpp, + struct config *conf; + bool mpp_has_wwid; + bool must_reload = false; ++ bool pg_deleted = false; + + if (!mpp->pg) + return false; +@@ -125,6 +126,10 @@ static bool update_pathvec_from_dm(vector pathvec, struct multipath *mpp, + + vector_foreach_slot(pgp->paths, pp, j) { + ++ /* A pathgroup has been deleted before. Invalidate pgindex */ ++ if (pg_deleted) ++ pp->pgindex = 0; ++ + if (pp->mpp && pp->mpp != mpp) { + condlog(0, "BUG: %s: found path %s which is already in %s", + mpp->alias, pp->dev, pp->mpp->alias); +@@ -139,6 +144,13 @@ static bool update_pathvec_from_dm(vector pathvec, struct multipath *mpp, + must_reload = true; + dm_fail_path(mpp->alias, pp->dev_t); + vector_del_slot(pgp->paths, j--); ++ /* ++ * pp->pgindex has been set in disassemble_map(), ++ * which has probably been called just before for ++ * mpp. So he pgindex relates to mpp and may be ++ * wrong for pp->mpp. Invalidate it. ++ */ ++ pp->pgindex = 0; + continue; + } + pp->mpp = mpp; +@@ -237,6 +249,8 @@ static bool update_pathvec_from_dm(vector pathvec, struct multipath *mpp, + vector_del_slot(mpp->pg, i--); + free_pathgroup(pgp, KEEP_PATHS); + must_reload = true; ++ /* Invalidate pgindex for all other pathgroups */ ++ pg_deleted = true; + } + mpp->need_reload = mpp->need_reload || must_reload; + return must_reload; +@@ -354,6 +368,7 @@ void orphan_path(struct path *pp, const char *reason) + { + condlog(3, "%s: orphan path, %s", pp->dev, reason); + pp->mpp = NULL; ++ pp->pgindex = 0; + uninitialize_path(pp); + } + diff --git a/0025-libmultipath-make-pgcmp-detect-if-map-is-missing-a-p.patch b/0025-libmultipath-make-pgcmp-detect-if-map-is-missing-a-p.patch new file mode 100644 index 0000000..b2b9e48 --- /dev/null +++ b/0025-libmultipath-make-pgcmp-detect-if-map-is-missing-a-p.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 25 Nov 2024 15:18:15 +0100 +Subject: [PATCH] libmultipath: make pgcmp detect if map is missing a path + group + +The previous algorithm didn't detect the case case where cpgp +contained a path that was not contained in pgp. Fix this. + +Cherry-picked from d4b35f61cb75c6e9b289e56c98457fc04ce4835e +Fixes: 90773ba ("libmultipath: resolve hash collisions in pgcmp()") +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/configure.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index a7257981..e86c1fd5 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -426,6 +426,11 @@ compute_pgid(struct pathgroup * pgp) + pgp->id ^= (long)pp; + } + ++static void cleanup_bitfield(struct bitfield **p) ++{ ++ free(*p); ++} ++ + static int + pgcmp (struct multipath * mpp, struct multipath * cmpp) + { +@@ -433,16 +438,25 @@ pgcmp (struct multipath * mpp, struct multipath * cmpp) + struct pathgroup * pgp; + struct pathgroup * cpgp; + int r = 0; ++ struct bitfield *bf __attribute__((cleanup(cleanup_bitfield))) = NULL; + + if (!mpp) + return 0; + ++ if (VECTOR_SIZE(mpp->pg) != VECTOR_SIZE(cmpp->pg)) ++ return 1; ++ ++ bf = alloc_bitfield(VECTOR_SIZE(cmpp->pg)); ++ if (!bf) ++ return 1; ++ + vector_foreach_slot (mpp->pg, pgp, i) { + compute_pgid(pgp); + + vector_foreach_slot (cmpp->pg, cpgp, j) { + if (pgp->id == cpgp->id && + !pathcmp(pgp, cpgp)) { ++ set_bit_in_bitfield(j, bf); + r = 0; + break; + } +@@ -451,6 +465,10 @@ pgcmp (struct multipath * mpp, struct multipath * cmpp) + if (r) + return r; + } ++ vector_foreach_slot (cmpp->pg, cpgp, j) { ++ if (!is_bit_set_in_bitfield(j, bf)) ++ return 1; ++ } + return r; + } + diff --git a/0026-libmultipath-trigger-uevents-upon-map-creation-in-do.patch b/0026-libmultipath-trigger-uevents-upon-map-creation-in-do.patch new file mode 100644 index 0000000..bd3a7a4 --- /dev/null +++ b/0026-libmultipath-trigger-uevents-upon-map-creation-in-do.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 26 Nov 2024 22:37:20 +0100 +Subject: [PATCH] libmultipath: trigger uevents upon map creation in domap() + +If map creation succeeds, previously not multipathed devices are +now multipathed. udev may not have noticed this yet, thus trigger +path uevents to make it aware of the situation. Likewise, if +creating a map fails, the paths in question were likely considered +multipath members by udev, too. They will now be marked as failed, +so trigger an event in this situation as well. + +Fixes: https://github.com/opensvc/multipath-tools/issues/103 +Suggested-by: Benjamin Marzinski +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +(cherry picked from commit 98b3a7bd9ed2a89f068fe40c253843cf78261905) +Signed-off-by: Benjamin Marzinski +--- + libmultipath/configure.c | 11 ++++------- + libmultipath/devmapper.c | 9 +++------ + 2 files changed, 7 insertions(+), 13 deletions(-) + +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index e86c1fd5..d9fac384 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -581,8 +581,6 @@ trigger_paths_udev_change(struct multipath *mpp, bool is_mpath) + vector_foreach_slot(pgp->paths, pp, j) + trigger_path_udev_change(pp, is_mpath); + } +- +- mpp->needs_paths_uevent = 0; + } + + static int sysfs_set_max_sectors_kb(struct multipath *mpp) +@@ -954,10 +952,10 @@ int domap(struct multipath *mpp, char *params, int is_daemon) + * succeeded + */ + mpp->force_udev_reload = 0; +- if (mpp->action == ACT_CREATE && +- (remember_wwid(mpp->wwid) == 1 || +- mpp->needs_paths_uevent)) ++ if (mpp->action == ACT_CREATE) { ++ remember_wwid(mpp->wwid); + trigger_paths_udev_change(mpp, true); ++ } + if (!is_daemon) { + /* multipath client mode */ + dm_switchgroup(mpp->alias, mpp->bestpg); +@@ -982,8 +980,7 @@ int domap(struct multipath *mpp, char *params, int is_daemon) + } + dm_setgeometry(mpp); + return DOMAP_OK; +- } else if (r == DOMAP_FAIL && mpp->action == ACT_CREATE && +- mpp->needs_paths_uevent) ++ } else if (r == DOMAP_FAIL && mpp->action == ACT_CREATE) + trigger_paths_udev_change(mpp, false); + + return DOMAP_FAIL; +diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c +index fe5637b3..a0070c56 100644 +--- a/libmultipath/devmapper.c ++++ b/libmultipath/devmapper.c +@@ -536,7 +536,7 @@ static uint16_t build_udev_flags(const struct multipath *mpp, int reload) + MPATH_UDEV_RELOAD_FLAG : 0); + } + +-int dm_addmap_create (struct multipath *mpp, char * params) ++int dm_addmap_create (struct multipath *mpp, char *params) + { + int ro; + uint16_t udev_flags = build_udev_flags(mpp, 0); +@@ -546,9 +546,7 @@ int dm_addmap_create (struct multipath *mpp, char * params) + + if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, mpp, params, ro, + udev_flags)) { +- if (unmark_failed_wwid(mpp->wwid) == +- WWID_FAILED_CHANGED) +- mpp->needs_paths_uevent = 1; ++ unmark_failed_wwid(mpp->wwid); + return 1; + } + /* +@@ -566,8 +564,7 @@ int dm_addmap_create (struct multipath *mpp, char * params) + break; + } + } +- if (mark_failed_wwid(mpp->wwid) == WWID_FAILED_CHANGED) +- mpp->needs_paths_uevent = 1; ++ mark_failed_wwid(mpp->wwid); + return 0; + } + diff --git a/0027-multipathd-trigger-uevents-upon-map-removal-in-coale.patch b/0027-multipathd-trigger-uevents-upon-map-removal-in-coale.patch new file mode 100644 index 0000000..f43ca0c --- /dev/null +++ b/0027-multipathd-trigger-uevents-upon-map-removal-in-coale.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 27 Nov 2024 20:39:50 +0100 +Subject: [PATCH] multipathd: trigger uevents upon map removal in + coalesce_maps() + +... if a map has been flushed. In this case, we know that the +the paths haven't been multipathed by coalesce_paths() because of the current +configuration (failure to create the map can't be the reason if the map +exists in coalesce_maps()). Make sure udev sees the paths which have +been released from the map as non-multipath. + +Note that this is the only case where maps are flushed where it is correct +to trigger paths uevents. In other cases, e.g. after a "remove map" CLI +command, the configuration is unchanged and if we triggered an uevent, +the map would be re-created by multipathd when the uevent arrived. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +(cherry picked from commit ad3ea472b587c0c20d2100331b5c66f8602f8414) +Signed-off-by: Benjamin Marzinski +--- + multipathd/main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index 3fb623fd..4b089c0e 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -794,8 +794,10 @@ coalesce_maps(struct vectors *vecs, vector nmpv) + vector_del_slot(ompv, i); + i--; + } +- else ++ else { + condlog(2, "%s devmap removed", ompp->alias); ++ trigger_paths_udev_change(ompp, false); ++ } + } else if (reassign_maps) { + condlog(3, "%s: Reassign existing device-mapper" + " devices", ompp->alias); diff --git a/0028-libmultipath-Don-t-skip-set_path_max_sectors_kb.patch b/0028-libmultipath-Don-t-skip-set_path_max_sectors_kb.patch new file mode 100644 index 0000000..6c001f5 --- /dev/null +++ b/0028-libmultipath-Don-t-skip-set_path_max_sectors_kb.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 4 Dec 2024 22:56:36 -0500 +Subject: [PATCH] libmultipath: Don't skip set_path_max_sectors_kb() + +If a multipath device already has need_reload set when a path is +adopted, it won't call set_path_max_sectors_kb() because of +short-circuit evaluation. This isn't what's intended. + +Fixes: e5e20c7b ("libmultipath: set max_sectors_kb in adopt_paths()") +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +(cherry picked from commit f5c0c4b25c5eaac87b78e6e0c8d52b0828c29893) +--- + libmultipath/structs_vec.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c +index 9dc5a5ca..683ab473 100644 +--- a/libmultipath/structs_vec.c ++++ b/libmultipath/structs_vec.c +@@ -349,8 +349,7 @@ int adopt_paths(vector pathvec, struct multipath *mpp, + */ + if (!current_mpp || + !mp_find_path_by_devt(current_mpp, pp->dev_t)) +- mpp->need_reload = mpp->need_reload || +- set_path_max_sectors_kb(pp, mpp->max_sectors_kb); ++ mpp->need_reload = set_path_max_sectors_kb(pp, mpp->max_sectors_kb) || mpp->need_reload; + } + + pp->mpp = mpp; diff --git a/0029-libmultipath-stop-static-analyzer-complaint-in-init_.patch b/0029-libmultipath-stop-static-analyzer-complaint-in-init_.patch new file mode 100644 index 0000000..e293a0e --- /dev/null +++ b/0029-libmultipath-stop-static-analyzer-complaint-in-init_.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 22 Jan 2025 22:16:42 -0500 +Subject: [PATCH] libmultipath: stop static analyzer complaint in init_foreign + +This change doesn't actually fix anything. The code was already safe. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +(cherry picked from commit 85ec51e7930b4cadfbc12718afa91ce3a4adf4b5) +--- + libmultipath/foreign.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/foreign.c b/libmultipath/foreign.c +index 28d1b115..af5b0ed3 100644 +--- a/libmultipath/foreign.c ++++ b/libmultipath/foreign.c +@@ -129,7 +129,7 @@ static void free_pre(void *arg) + static int _init_foreign(const char *enable) + { + char pathbuf[PATH_MAX]; +- struct dirent **di; ++ struct dirent **di = NULL; + struct scandir_result sr; + int r, i; + regex_t *enable_re = NULL; diff --git a/0030-libmultipath-be-lenient-in-allowing-the-alua-based-p.patch b/0030-libmultipath-be-lenient-in-allowing-the-alua-based-p.patch new file mode 100644 index 0000000..06a1b0f --- /dev/null +++ b/0030-libmultipath-be-lenient-in-allowing-the-alua-based-p.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 22 Jan 2025 22:16:43 -0500 +Subject: [PATCH] libmultipath: be lenient in allowing the alua-based + pgpolicies + +multipath wouldn't autodetect the GROUP_BY_PRIO path grouping policy or +allow the GROUP_BY_TPG policy if there was a path that didn't have its +prioritizer selected (for instance because multipathd was reconfigured +while it was offline). To avoid this, make verify_alua_prio() assume an +alua multipath device if all the paths with a prioritizer selected +(there must be at least one) use an alua-based prioritizer. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +(cherry picked from commit b47a577998eaff203018a00b57ba5e3674645848) +--- + libmultipath/propsel.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c +index a3fce203..c09a0619 100644 +--- a/libmultipath/propsel.c ++++ b/libmultipath/propsel.c +@@ -255,14 +255,18 @@ verify_alua_prio(struct multipath *mp) + { + int i; + struct path *pp; ++ bool assume_alua = false; + + vector_foreach_slot(mp->paths, pp, i) { + const char *name = prio_name(&pp->prio); ++ if (!prio_selected(&pp->prio)) ++ continue; + if (strncmp(name, PRIO_ALUA, PRIO_NAME_LEN) && + strncmp(name, PRIO_SYSFS, PRIO_NAME_LEN)) + return false; ++ assume_alua = true; + } +- return true; ++ return assume_alua; + } + + int select_detect_pgpolicy(struct config *conf, struct multipath *mp) diff --git a/0031-Update-NEWS.md-for-0.10.2.patch b/0031-Update-NEWS.md-for-0.10.2.patch new file mode 100644 index 0000000..fd31420 --- /dev/null +++ b/0031-Update-NEWS.md-for-0.10.2.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 24 Jan 2025 20:03:15 +0100 +Subject: [PATCH] Update NEWS.md for 0.10.2 + +Signed-off-by: Benjamin Marzinski +--- + .github/actions/spelling/expect.txt | 2 ++ + NEWS.md | 23 ++++++++++++++++++++++- + 2 files changed, 24 insertions(+), 1 deletion(-) + +diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt +index 000d5ebb..4ac57510 100644 +--- a/.github/actions/spelling/expect.txt ++++ b/.github/actions/spelling/expect.txt +@@ -11,6 +11,7 @@ ata + autoconfig + autodetected + autoresize ++backported + barbie + BINDIR + blkid +@@ -122,6 +123,7 @@ Lun + lvm + lvmteam + Marzinski ++misdetection + mpath + mpathb + mpathpersist +diff --git a/NEWS.md b/NEWS.md +index 3c51553e..1b239ffa 100644 +--- a/NEWS.md ++++ b/NEWS.md +@@ -1,6 +1,27 @@ + # multipath-tools Release Notes + +-## multipath-tools 0.10.1, 2024/11 ++## multipath-tools 0.10.2, 2025/02 ++ ++This release contains backported bug fixes from the stable-0.11.y branch. ++ ++### Bug fixes ++ ++* Fix multipathd crash because of invalid path group index value, for example ++ if an invalid path device was removed from a map. ++ Fixes [#105](https://github.com/opensvc/multipath-tools/issues/105). ++* Make sure maps are reloaded in the path checker loop after detecting an ++ inconsistent or wrong kernel state (e.g. missing or falsely mapped path ++ device). Wrongly mapped paths will be unmapped and released to the system. ++ Fixes another issue reported in ++ [#105](https://github.com/opensvc/multipath-tools/issues/105). ++* Fix the problem that `group_by_tpg` might be disabled if one or more ++ paths were offline during initial configuration. ++* Fix possible misdetection of changed pathgroups in a map. ++* Fix the problem that if a map was scheduled to be reloaded already, ++ `max_sectors_kb` might not be set on a path device that ++ was being added to a multipath map. This problem was introduced in 0.9.9. ++ ++## multipath-tools 0.10.1, 2025/01 + + This is the first bug fix release on the `stable-0.10.y` branch. It contains + bug fixes from 0.11.0, and some CI-related fixes. diff --git a/0032-GitHub-Workflows-fix-abi-stable.yaml-for-pull-reques.patch b/0032-GitHub-Workflows-fix-abi-stable.yaml-for-pull-reques.patch new file mode 100644 index 0000000..3ddab39 --- /dev/null +++ b/0032-GitHub-Workflows-fix-abi-stable.yaml-for-pull-reques.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Sat, 25 Jan 2025 00:49:19 +0100 +Subject: [PATCH] GitHub Workflows: fix abi-stable.yaml for pull request + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + .github/workflows/abi-stable.yaml | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/.github/workflows/abi-stable.yaml b/.github/workflows/abi-stable.yaml +index a6746f23..472914ce 100644 +--- a/.github/workflows/abi-stable.yaml ++++ b/.github/workflows/abi-stable.yaml +@@ -15,12 +15,16 @@ on: + + jobs: + reference-abi: +- runs-on: ubuntu-20.04 ++ runs-on: ubuntu-22.04 + steps: + - name: get parent tag + run: > + echo ${{ github.ref }} | + sed -E 's,refs/heads/stable-([0-9]\.[0-9]*)\.y,PARENT_TAG=\1.0,' >> $GITHUB_ENV ++ if: ${{ github.event_name == 'push' }} ++ - name: get parent tag ++ run: echo PARENT_TAG=${{ github.base_ref }} >> $GITHUB_ENV ++ if: ${{ github.event_name == 'pull_request' }} + - name: assert parent tag + run: /bin/false + if: ${{ env.PARENT_TAG == '' }} +@@ -45,20 +49,24 @@ jobs: + path: abi + + check-abi: +- runs-on: ubuntu-20.04 ++ runs-on: ubuntu-22.04 + needs: reference-abi + steps: + - name: get parent tag + run: > + echo ${{ github.ref }} | + sed -E 's,refs/heads/stable-([0-9]\.[0-9]*)\.y,PARENT_TAG=\1.0,' >> $GITHUB_ENV ++ if: ${{ github.event_name == 'push' }} ++ - name: get parent tag ++ run: echo PARENT_TAG=${{ github.base_ref }} >> $GITHUB_ENV ++ if: ${{ github.event_name == 'pull_request' }} + - name: assert parent tag + run: /bin/false + if: ${{ env.PARENT_TAG == '' }} +- - name: checkout ${{ env.PARENT_TAG }} ++ - name: checkout ${{ github.base_ref }} + uses: actions/checkout@v4 + with: +- ref: ${{ env.PARENT_TAG }} ++ ref: ${{ github.base_ref }} + - name: download ABI for ${{ env.PARENT_TAG }} + id: download_abi + uses: actions/download-artifact@v4 diff --git a/0001-RH-fixup-udev-rules-for-redhat.patch b/0033-RH-fixup-udev-rules-for-redhat.patch similarity index 100% rename from 0001-RH-fixup-udev-rules-for-redhat.patch rename to 0033-RH-fixup-udev-rules-for-redhat.patch diff --git a/0002-RH-Remove-the-property-blacklist-exception-builtin.patch b/0034-RH-Remove-the-property-blacklist-exception-builtin.patch similarity index 100% rename from 0002-RH-Remove-the-property-blacklist-exception-builtin.patch rename to 0034-RH-Remove-the-property-blacklist-exception-builtin.patch diff --git a/0003-RH-don-t-start-without-a-config-file.patch b/0035-RH-don-t-start-without-a-config-file.patch similarity index 98% rename from 0003-RH-don-t-start-without-a-config-file.patch rename to 0035-RH-don-t-start-without-a-config-file.patch index 02827df..8a3c5b6 100644 --- a/0003-RH-don-t-start-without-a-config-file.patch +++ b/0035-RH-don-t-start-without-a-config-file.patch @@ -22,10 +22,10 @@ Signed-off-by: Benjamin Marzinski 7 files changed, 25 insertions(+) diff --git a/libmultipath/config.c b/libmultipath/config.c -index 0e3a5cc1..80f61914 100644 +index 226ddecb..588ae9ee 100644 --- a/libmultipath/config.c +++ b/libmultipath/config.c -@@ -959,6 +959,19 @@ int init_config__ (const char *file, struct config *conf) +@@ -962,6 +962,19 @@ int init_config__ (const char *file, struct config *conf) } factorize_hwtable(conf->hwtable, builtin_hwtable_size, file); validate_pctable(conf->overrides, 0, file); diff --git a/0004-RH-Fix-nvme-function-missing-argument.patch b/0036-RH-Fix-nvme-function-missing-argument.patch similarity index 100% rename from 0004-RH-Fix-nvme-function-missing-argument.patch rename to 0036-RH-Fix-nvme-function-missing-argument.patch diff --git a/0005-RH-use-rpm-optflags-if-present.patch b/0037-RH-use-rpm-optflags-if-present.patch similarity index 97% rename from 0005-RH-use-rpm-optflags-if-present.patch rename to 0037-RH-use-rpm-optflags-if-present.patch index 266e224..66d14bc 100644 --- a/0005-RH-use-rpm-optflags-if-present.patch +++ b/0037-RH-use-rpm-optflags-if-present.patch @@ -7,13 +7,14 @@ Use the passed in optflags when compiling as an RPM, and keep the default flags as close as possible to the current fedora flags, while still being generic. +Co-authored-by: Yaakov Selkowitz Signed-off-by: Benjamin Marzinski --- Makefile.inc | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/Makefile.inc b/Makefile.inc -index 81cb61d2..35334a0c 100644 +index 81cb61d2..a5024bb7 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -99,28 +99,39 @@ SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo diff --git a/0006-RH-add-mpathconf.patch b/0038-RH-add-mpathconf.patch similarity index 99% rename from 0006-RH-add-mpathconf.patch rename to 0038-RH-add-mpathconf.patch index 2ae48f3..103ca55 100644 --- a/0006-RH-add-mpathconf.patch +++ b/0038-RH-add-mpathconf.patch @@ -23,11 +23,11 @@ Signed-off-by: Benjamin Marzinski create mode 100644 multipath/mpathconf.8 diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt -index 934f582e..61351583 100644 +index 4ac57510..3602a071 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt -@@ -124,9 +124,11 @@ lvmteam - Marzinski +@@ -126,9 +126,11 @@ Marzinski + misdetection mpath mpathb +mpathconf @@ -38,7 +38,7 @@ index 934f582e..61351583 100644 multipathc multipathd multipathed -@@ -144,6 +146,7 @@ ontap +@@ -146,6 +148,7 @@ ontap OOM opensvc OPTFLAGS @@ -47,10 +47,10 @@ index 934f582e..61351583 100644 partx pathgroup diff --git a/libmultipath/config.c b/libmultipath/config.c -index 80f61914..1373f15b 100644 +index 588ae9ee..3cb8449c 100644 --- a/libmultipath/config.c +++ b/libmultipath/config.c -@@ -961,6 +961,8 @@ int init_config__ (const char *file, struct config *conf) +@@ -964,6 +964,8 @@ int init_config__ (const char *file, struct config *conf) validate_pctable(conf->overrides, 0, file); } else { condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices."); diff --git a/0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch b/0039-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch similarity index 100% rename from 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch rename to 0039-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch diff --git a/0008-RH-reset-default-find_mutipaths-value-to-off.patch b/0040-RH-reset-default-find_mutipaths-value-to-off.patch similarity index 100% rename from 0008-RH-reset-default-find_mutipaths-value-to-off.patch rename to 0040-RH-reset-default-find_mutipaths-value-to-off.patch diff --git a/0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch b/0041-RH-attempt-to-get-ANA-info-via-sysfs-first.patch similarity index 100% rename from 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch rename to 0041-RH-attempt-to-get-ANA-info-via-sysfs-first.patch diff --git a/0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch b/0042-RH-make-parse_vpd_pg83-match-scsi_id-output.patch similarity index 98% rename from 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch rename to 0042-RH-make-parse_vpd_pg83-match-scsi_id-output.patch index 06194f6..0d5baa3 100644 --- a/0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +++ b/0042-RH-make-parse_vpd_pg83-match-scsi_id-output.patch @@ -14,7 +14,7 @@ Signed-off-by: Benjamin Marzinski 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index e94705bf..61ac27ef 100644 +index 5043330c..e14507e8 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -1221,13 +1221,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, diff --git a/0011-RH-add-scsi-device-handlers-to-modules-load.d.patch b/0043-RH-add-scsi-device-handlers-to-modules-load.d.patch similarity index 96% rename from 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch rename to 0043-RH-add-scsi-device-handlers-to-modules-load.d.patch index 3debe8a..ef0ee42 100644 --- a/0011-RH-add-scsi-device-handlers-to-modules-load.d.patch +++ b/0043-RH-add-scsi-device-handlers-to-modules-load.d.patch @@ -11,7 +11,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc -index 35334a0c..377125b6 100644 +index a5024bb7..834b63b9 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -16,7 +16,7 @@ READLINE := diff --git a/0012-RH-compile-with-libreadline-support.patch b/0044-RH-compile-with-libreadline-support.patch similarity index 96% rename from 0012-RH-compile-with-libreadline-support.patch rename to 0044-RH-compile-with-libreadline-support.patch index db04640..50781c3 100644 --- a/0012-RH-compile-with-libreadline-support.patch +++ b/0044-RH-compile-with-libreadline-support.patch @@ -12,7 +12,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc -index 377125b6..4a6528a9 100644 +index 834b63b9..c482a181 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -12,7 +12,7 @@ diff --git a/0013-RH-Add-mpathcleanup.patch b/0045-RH-Add-mpathcleanup.patch similarity index 100% rename from 0013-RH-Add-mpathcleanup.patch rename to 0045-RH-Add-mpathcleanup.patch diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index d2c3cc6..8e469ab 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.10.0 -Release: 4%{?dist} +Release: 5%{?dist} Summary: Tools to manage multipath devices using device-mapper # readline uses GPL-3.0-only License: GPL-2.0-only AND GPL-3.0-only @@ -11,19 +11,51 @@ URL: http://christophe.varoqui.free.fr/ # curl -L https://github.com/opensvc/multipath-tools/archive/0.10.0.tar.gz -o multipath-tools-0.10.0.tgz Source0: multipath-tools-0.10.0.tgz Source1: multipath.conf -Patch0001: 0001-RH-fixup-udev-rules-for-redhat.patch -Patch0002: 0002-RH-Remove-the-property-blacklist-exception-builtin.patch -Patch0003: 0003-RH-don-t-start-without-a-config-file.patch -Patch0004: 0004-RH-Fix-nvme-function-missing-argument.patch -Patch0005: 0005-RH-use-rpm-optflags-if-present.patch -Patch0006: 0006-RH-add-mpathconf.patch -Patch0007: 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch -Patch0008: 0008-RH-reset-default-find_mutipaths-value-to-off.patch -Patch0009: 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch -Patch0010: 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch -Patch0011: 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch -Patch0012: 0012-RH-compile-with-libreadline-support.patch -Patch0013: 0013-RH-Add-mpathcleanup.patch +Patch0001: 0001-GitHub-workflows-use-upload-download-artifact-v4.patch +Patch0002: 0002-GitHub-workflows-update-dawidd6-action-download-arti.patch +Patch0003: 0003-Github-workflows-native.yml-use-mosteo-actions-docke.patch +Patch0004: 0004-GitHub-workflows-native.yml-use-extra-job-for-clang.patch +Patch0005: 0005-GitHub-workflows-native.yaml-make-test-and-archive-s.patch +Patch0006: 0006-GitHub-workflows-enable-unit-tests-for-stable-branch.patch +Patch0007: 0007-GitHub-Workflows-add-abi-check-for-stable-branches.patch +Patch0008: 0008-libmultipath-dm_get_maps-don-t-bail-out-for-single-m.patch +Patch0009: 0009-11-dm-mpath.rules.in-import-DM_COLDPLUG_SUSPENDED-on.patch +Patch0010: 0010-11-dm-mpath.rules.in-handle-inactive-suspended-devic.patch +Patch0011: 0011-11-dm-mpath.rules.in-clarify-DM_ACTIVATION-logic.patch +Patch0012: 0012-11-dm-mpath-rules.in-skip-one-.DM_NOSCAN-check.patch +Patch0013: 0013-11-dm-mpath.rules.in-set-.DM_NOSCAN-if-MPATH_UNCHANG.patch +Patch0014: 0014-libmultipath-don-t-set-dev_loss_tmo-to-0-for-NO_PATH.patch +Patch0015: 0015-multipathd-fix-deferred_failback_tick-for-reload-rem.patch +Patch0016: 0016-multipathd-fix-an-unsigned-int-ovwerflow.patch +Patch0017: 0017-libmpathutil-avoid-Wcast-function-type-mismatch-erro.patch +Patch0018: 0018-Update-NEWS.md-for-0.10.1.patch +Patch0019: 0019-libmultipath-don-t-print-error-message-if-WATCHDOG_U.patch +Patch0020: 0020-libmultipath-reduce-log-level-of-map-X-has-multiple-.patch +Patch0021: 0021-libmultipath-foreign-fix-memory-leak-in-nvme-foreign.patch +Patch0022: 0022-libmultipath-add-condition-for-enqueueing-path-to-io.patch +Patch0023: 0023-Additional-NEWS.md-updates-for-0.10.1.patch +Patch0024: 0024-libmultipath-fix-handling-of-pp-pgindex.patch +Patch0025: 0025-libmultipath-make-pgcmp-detect-if-map-is-missing-a-p.patch +Patch0026: 0026-libmultipath-trigger-uevents-upon-map-creation-in-do.patch +Patch0027: 0027-multipathd-trigger-uevents-upon-map-removal-in-coale.patch +Patch0028: 0028-libmultipath-Don-t-skip-set_path_max_sectors_kb.patch +Patch0029: 0029-libmultipath-stop-static-analyzer-complaint-in-init_.patch +Patch0030: 0030-libmultipath-be-lenient-in-allowing-the-alua-based-p.patch +Patch0031: 0031-Update-NEWS.md-for-0.10.2.patch +Patch0032: 0032-GitHub-Workflows-fix-abi-stable.yaml-for-pull-reques.patch +Patch0033: 0033-RH-fixup-udev-rules-for-redhat.patch +Patch0034: 0034-RH-Remove-the-property-blacklist-exception-builtin.patch +Patch0035: 0035-RH-don-t-start-without-a-config-file.patch +Patch0036: 0036-RH-Fix-nvme-function-missing-argument.patch +Patch0037: 0037-RH-use-rpm-optflags-if-present.patch +Patch0038: 0038-RH-add-mpathconf.patch +Patch0039: 0039-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +Patch0040: 0040-RH-reset-default-find_mutipaths-value-to-off.patch +Patch0041: 0041-RH-attempt-to-get-ANA-info-via-sysfs-first.patch +Patch0042: 0042-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +Patch0043: 0043-RH-add-scsi-device-handlers-to-modules-load.d.patch +Patch0044: 0044-RH-compile-with-libreadline-support.patch +Patch0045: 0045-RH-Add-mpathcleanup.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -233,6 +265,11 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Sat Feb 1 2025 Benjamin Marzinski - 0.10.0-5 +- Update source to upstream staging branch for 0.10.y (will be 0.10.2 when + merged). +- Rebase redhat patches + * Thu Jan 16 2025 Fedora Release Engineering - 0.10.0-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild From 30306052cc8ded97742c95e1b7e1c4a5ceeab621 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Mon, 3 Mar 2025 12:33:06 -0500 Subject: [PATCH 26/29] device-mapper-multipath-0.11.1-1 Update source to upstream staging branch for 0.11.1 plus additional stable branch patches. * Previous patches 0001-0032 are included in the tarball Rename redhat patches * Previous patches 0033-0045 are now patches 0005-0017 --- .gitignore | 1 + ...lows-use-upload-download-artifact-v4.patch | 122 ---------------- ...er-uevents-for-blacklisted-paths-in-.patch | 101 +++++++++++++ ...-update-dawidd6-action-download-arti.patch | 24 --- ...fix-compilation-with-latest-userspac.patch | 63 ++++++++ ...-native.yml-use-mosteo-actions-docke.patch | 98 ------------- ...-include-urcu.h-before-urcu-atomic.h.patch | 40 +++++ ...s-native.yml-use-extra-job-for-clang.patch | 43 ------ ...uxsock.c-Include-string.h-for-memcpy.patch | 29 ++++ ...-native.yaml-make-test-and-archive-s.patch | 51 ------- ... 0005-RH-fixup-udev-rules-for-redhat.patch | 2 +- ...-enable-unit-tests-for-stable-branch.patch | 133 ----------------- ...property-blacklist-exception-builtin.patch | 0 ...ws-add-abi-check-for-stable-branches.patch | 110 -------------- ...RH-don-t-start-without-a-config-file.patch | 8 +- ...H-Fix-nvme-function-missing-argument.patch | 0 ...get_maps-don-t-bail-out-for-single-m.patch | 32 ---- ...s.in-import-DM_COLDPLUG_SUSPENDED-on.patch | 42 ------ ... 0009-RH-use-rpm-optflags-if-present.patch | 7 +- ...s.in-handle-inactive-suspended-devic.patch | 66 --------- ...hconf.patch => 0010-RH-add-mpathconf.patch | 10 +- ...rules.in-clarify-DM_ACTIVATION-logic.patch | 78 ---------- ...om-kernel-cmdline-mpath.wwids-with-A.patch | 6 +- ...h-rules.in-skip-one-.DM_NOSCAN-check.patch | 28 ---- ...-default-find_mutipaths-value-to-off.patch | 0 ...s.in-set-.DM_NOSCAN-if-MPATH_UNCHANG.patch | 44 ------ ...empt-to-get-ANA-info-via-sysfs-first.patch | 0 ...-parse_vpd_pg83-match-scsi_id-output.patch | 6 +- ...-t-set-dev_loss_tmo-to-0-for-NO_PATH.patch | 31 ---- ...si-device-handlers-to-modules-load.d.patch | 2 +- ...eferred_failback_tick-for-reload-rem.patch | 35 ----- ...-RH-compile-with-libreadline-support.patch | 2 +- ...ipathd-fix-an-unsigned-int-ovwerflow.patch | 28 ---- ...up.patch => 0017-RH-Add-mpathcleanup.patch | 0 ...id-Wcast-function-type-mismatch-erro.patch | 36 ----- 0018-Update-NEWS.md-for-0.10.1.patch | 44 ------ ...-t-print-error-message-if-WATCHDOG_U.patch | 30 ---- ...uce-log-level-of-map-X-has-multiple-.patch | 38 ----- ...eign-fix-memory-leak-in-nvme-foreign.patch | 54 ------- ...-condition-for-enqueueing-path-to-io.patch | 41 ------ ...dditional-NEWS.md-updates-for-0.10.1.patch | 63 -------- ...multipath-fix-handling-of-pp-pgindex.patch | 138 ------------------ ...e-pgcmp-detect-if-map-is-missing-a-p.patch | 70 --------- ...gger-uevents-upon-map-creation-in-do.patch | 94 ------------ ...er-uevents-upon-map-removal-in-coale.patch | 41 ------ ...h-Don-t-skip-set_path_max_sectors_kb.patch | 31 ---- ...p-static-analyzer-complaint-in-init_.patch | 27 ---- ...lenient-in-allowing-the-alua-based-p.patch | 44 ------ 0031-Update-NEWS.md-for-0.10.2.patch | 64 -------- ...-fix-abi-stable.yaml-for-pull-reques.patch | 61 -------- device-mapper-multipath.spec | 79 ++++------ sources | 2 +- 52 files changed, 285 insertions(+), 1914 deletions(-) delete mode 100644 0001-GitHub-workflows-use-upload-download-artifact-v4.patch create mode 100644 0001-multipathd-trigger-uevents-for-blacklisted-paths-in-.patch delete mode 100644 0002-GitHub-workflows-update-dawidd6-action-download-arti.patch create mode 100644 0002-multipath-tools-fix-compilation-with-latest-userspac.patch delete mode 100644 0003-Github-workflows-native.yml-use-mosteo-actions-docke.patch create mode 100644 0003-libmultipath-include-urcu.h-before-urcu-atomic.h.patch delete mode 100644 0004-GitHub-workflows-native.yml-use-extra-job-for-clang.patch create mode 100644 0004-libmpathutils-uxsock.c-Include-string.h-for-memcpy.patch delete mode 100644 0005-GitHub-workflows-native.yaml-make-test-and-archive-s.patch rename 0033-RH-fixup-udev-rules-for-redhat.patch => 0005-RH-fixup-udev-rules-for-redhat.patch (98%) delete mode 100644 0006-GitHub-workflows-enable-unit-tests-for-stable-branch.patch rename 0034-RH-Remove-the-property-blacklist-exception-builtin.patch => 0006-RH-Remove-the-property-blacklist-exception-builtin.patch (100%) delete mode 100644 0007-GitHub-Workflows-add-abi-check-for-stable-branches.patch rename 0035-RH-don-t-start-without-a-config-file.patch => 0007-RH-don-t-start-without-a-config-file.patch (96%) rename 0036-RH-Fix-nvme-function-missing-argument.patch => 0008-RH-Fix-nvme-function-missing-argument.patch (100%) delete mode 100644 0008-libmultipath-dm_get_maps-don-t-bail-out-for-single-m.patch delete mode 100644 0009-11-dm-mpath.rules.in-import-DM_COLDPLUG_SUSPENDED-on.patch rename 0037-RH-use-rpm-optflags-if-present.patch => 0009-RH-use-rpm-optflags-if-present.patch (92%) delete mode 100644 0010-11-dm-mpath.rules.in-handle-inactive-suspended-devic.patch rename 0038-RH-add-mpathconf.patch => 0010-RH-add-mpathconf.patch (99%) delete mode 100644 0011-11-dm-mpath.rules.in-clarify-DM_ACTIVATION-logic.patch rename 0039-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch => 0011-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch (97%) delete mode 100644 0012-11-dm-mpath-rules.in-skip-one-.DM_NOSCAN-check.patch rename 0040-RH-reset-default-find_mutipaths-value-to-off.patch => 0012-RH-reset-default-find_mutipaths-value-to-off.patch (100%) delete mode 100644 0013-11-dm-mpath.rules.in-set-.DM_NOSCAN-if-MPATH_UNCHANG.patch rename 0041-RH-attempt-to-get-ANA-info-via-sysfs-first.patch => 0013-RH-attempt-to-get-ANA-info-via-sysfs-first.patch (100%) rename 0042-RH-make-parse_vpd_pg83-match-scsi_id-output.patch => 0014-RH-make-parse_vpd_pg83-match-scsi_id-output.patch (94%) delete mode 100644 0014-libmultipath-don-t-set-dev_loss_tmo-to-0-for-NO_PATH.patch rename 0043-RH-add-scsi-device-handlers-to-modules-load.d.patch => 0015-RH-add-scsi-device-handlers-to-modules-load.d.patch (96%) delete mode 100644 0015-multipathd-fix-deferred_failback_tick-for-reload-rem.patch rename 0044-RH-compile-with-libreadline-support.patch => 0016-RH-compile-with-libreadline-support.patch (96%) delete mode 100644 0016-multipathd-fix-an-unsigned-int-ovwerflow.patch rename 0045-RH-Add-mpathcleanup.patch => 0017-RH-Add-mpathcleanup.patch (100%) delete mode 100644 0017-libmpathutil-avoid-Wcast-function-type-mismatch-erro.patch delete mode 100644 0018-Update-NEWS.md-for-0.10.1.patch delete mode 100644 0019-libmultipath-don-t-print-error-message-if-WATCHDOG_U.patch delete mode 100644 0020-libmultipath-reduce-log-level-of-map-X-has-multiple-.patch delete mode 100644 0021-libmultipath-foreign-fix-memory-leak-in-nvme-foreign.patch delete mode 100644 0022-libmultipath-add-condition-for-enqueueing-path-to-io.patch delete mode 100644 0023-Additional-NEWS.md-updates-for-0.10.1.patch delete mode 100644 0024-libmultipath-fix-handling-of-pp-pgindex.patch delete mode 100644 0025-libmultipath-make-pgcmp-detect-if-map-is-missing-a-p.patch delete mode 100644 0026-libmultipath-trigger-uevents-upon-map-creation-in-do.patch delete mode 100644 0027-multipathd-trigger-uevents-upon-map-removal-in-coale.patch delete mode 100644 0028-libmultipath-Don-t-skip-set_path_max_sectors_kb.patch delete mode 100644 0029-libmultipath-stop-static-analyzer-complaint-in-init_.patch delete mode 100644 0030-libmultipath-be-lenient-in-allowing-the-alua-based-p.patch delete mode 100644 0031-Update-NEWS.md-for-0.10.2.patch delete mode 100644 0032-GitHub-Workflows-fix-abi-stable.yaml-for-pull-reques.patch diff --git a/.gitignore b/.gitignore index 908094d..8cd21df 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ multipath-tools-091027.tar.gz /multipath-tools-0.9.8.tgz /multipath-tools-0.9.9.tgz /multipath-tools-0.10.0.tgz +/multipath-tools-0.11.1.tgz diff --git a/0001-GitHub-workflows-use-upload-download-artifact-v4.patch b/0001-GitHub-workflows-use-upload-download-artifact-v4.patch deleted file mode 100644 index c8247ca..0000000 --- a/0001-GitHub-workflows-use-upload-download-artifact-v4.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 13 Sep 2024 09:09:19 +0200 -Subject: [PATCH] GitHub workflows: use {upload,download}-artifact@v4 - -The @v1 releases are deprecated. -https://github.blog/changelog/2024-02-13-deprecation-notice-v1-and-v2-of-the-artifact-actions/ - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - .github/workflows/abi.yaml | 6 ++++-- - .github/workflows/foreign.yaml | 15 +++++++-------- - .github/workflows/native.yaml | 5 +++-- - 3 files changed, 14 insertions(+), 12 deletions(-) - -diff --git a/.github/workflows/abi.yaml b/.github/workflows/abi.yaml -index 393322e5..dce09f5c 100644 ---- a/.github/workflows/abi.yaml -+++ b/.github/workflows/abi.yaml -@@ -45,10 +45,11 @@ jobs: - - name: create ABI - run: make -Orecurse -j$(grep -c ^processor /proc/cpuinfo) abi.tar.gz - - name: save ABI -- uses: actions/upload-artifact@v1 -+ uses: actions/upload-artifact@v4 - with: - name: abi - path: abi -+ overwrite: true - - name: compare ABI against reference - id: compare - continue-on-error: true -@@ -56,10 +57,11 @@ jobs: - run: make abi-test - - name: save differences - if: ${{ steps.compare.outcome == 'failure' }} -- uses: actions/upload-artifact@v1 -+ uses: actions/upload-artifact@v4 - with: - name: abi-test - path: abi-test -+ overwrite: true - - - name: fail - # MUST use >- here, otherwise the condition always evaluates to true -diff --git a/.github/workflows/foreign.yaml b/.github/workflows/foreign.yaml -index 9e4d35e0..d68650df 100644 ---- a/.github/workflows/foreign.yaml -+++ b/.github/workflows/foreign.yaml -@@ -36,14 +36,13 @@ jobs: - - name: checkout - uses: actions/checkout@v1 - - name: build -- run: make -j8 -Orecurse test-progs -- - name: create binary archive -- run: make test-progs.tar -+ run: make -j -Orecurse test-progs.tar - - name: upload binary archive -- uses: actions/upload-artifact@v1 -+ uses: actions/upload-artifact@v4 - with: - name: cross-${{ matrix.os }}-${{ matrix.arch }} - path: test-progs.tar -+ overwrite: true - - test: - runs-on: ubuntu-22.04 -@@ -61,11 +60,11 @@ jobs: - run: echo CONTAINER_ARCH="arm/v7" >> $GITHUB_ENV - if: ${{ matrix.arch == 'armhf' }} - - name: download binary archive -- uses: actions/download-artifact@v1 -+ uses: actions/download-artifact@v4 - with: - name: cross-${{ matrix.os }}-${{ matrix.arch }} - - name: unpack binary archive -- run: tar xfv cross-${{ matrix.os }}-${{ matrix.arch }}/test-progs.tar -+ run: tar xfv test-progs.tar - - name: enable foreign arch - uses: dbhi/qus/action@main - - name: run tests -@@ -100,11 +99,11 @@ jobs: - run: echo CONTAINER_ARCH="arm/v7" >> $GITHUB_ENV - if: ${{ matrix.arch == 'armhf' }} - - name: download binary archive -- uses: actions/download-artifact@v1 -+ uses: actions/download-artifact@v4 - with: - name: cross-${{ matrix.os }}-${{ matrix.arch }} - - name: unpack binary archive -- run: tar xfv cross-${{ matrix.os }}-${{ matrix.arch }}/test-progs.tar -+ run: tar xfv test-progs.tar - - name: enable foreign arch - uses: dbhi/qus/action@main - - name: run tests -diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml -index 80ff6df5..500becaa 100644 ---- a/.github/workflows/native.yaml -+++ b/.github/workflows/native.yaml -@@ -57,10 +57,11 @@ jobs: - - name: create binary archive - run: make ${{ env.ARCHIVE_TGT }} - - name: upload binary archive -- uses: actions/upload-artifact@v1 -+ uses: actions/upload-artifact@v4 - with: - name: native-${{ matrix.os }} - path: ${{ env.ARCHIVE_TGT }} -+ overwrite: true - - - name: clean - run: make clean -@@ -98,7 +99,7 @@ jobs: - uses: actions/checkout@v1 - - - name: download binary archive -- uses: actions/download-artifact@v1 -+ uses: actions/download-artifact@v4 - with: - name: native-${{ matrix.os }} - - name: unpack binary archive diff --git a/0001-multipathd-trigger-uevents-for-blacklisted-paths-in-.patch b/0001-multipathd-trigger-uevents-for-blacklisted-paths-in-.patch new file mode 100644 index 0000000..72bcf69 --- /dev/null +++ b/0001-multipathd-trigger-uevents-for-blacklisted-paths-in-.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 23 Jan 2025 22:19:39 +0100 +Subject: [PATCH] multipathd: trigger uevents for blacklisted paths in + reconfigure + +If multipathd has already configured maps, and the user changes the +blacklist or other parameters that cause currently multipathed +devices to be skipped, and then runs "multipathd reconfigure" +or restarts multipathd, multipathd flushes the maps in question, +but doesn't trigger uevents for the now-blacklisted paths. + +This is because the blacklisted paths are removed from the discovered +maps internally when update_pathvec_from_dm() is called through +map_discovery() and update_multipath_table(); when later +trigger_paths_udev_change() is called from coalesce_maps(), the +map contains no paths for which an uevent could be triggered. + +The map_discovery() code flow is special, because we will call +coalesce_paths() afterwards anyway and reconstruct the mpvec. Unlike the +regular code flow, we don't want the maps to be "corrected" in this +case, because the maps discovered here aren't going to be reloaded. +We just want update_pathvec_from_dm() to populate the pathvec. + +Therefore add a new flag DI_DISCOVERY, which is only set when +update_multipath_table() is called from map_discovery(), and if +this flag is set, keep PATHINFO_SKIPPED paths in the map's table in +update_pathvec_from_dm(). Later on, the paths will still be visible +in the old mpp (ompp) in coalesce_maps(), and uevents will be +triggered for them to release them to systemd. + +We can't always do this for PATHINFO_SKIPPED, because in some cases +paths may be accepted in a map first and SKIPPED later (for example if +the WWID wasn't yet available at startup). Therefore the special +case for DI_DISCOVERY is necessary. + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/discovery.h | 2 ++ + libmultipath/structs_vec.c | 6 +++++- + multipathd/main.c | 2 +- + 3 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h +index 7d42eae5..9824a8d3 100644 +--- a/libmultipath/discovery.h ++++ b/libmultipath/discovery.h +@@ -72,6 +72,7 @@ enum discovery_mode { + DI_BLACKLIST__, + DI_NOIO__, + DI_NOFALLBACK__, ++ DI_DISCOVERY__, + }; + + #define DI_SYSFS (1 << DI_SYSFS__) +@@ -82,6 +83,7 @@ enum discovery_mode { + #define DI_BLACKLIST (1 << DI_BLACKLIST__) + #define DI_NOIO (1 << DI_NOIO__) /* Avoid IO on the device */ + #define DI_NOFALLBACK (1 << DI_NOFALLBACK__) /* do not allow wwid fallback */ ++#define DI_DISCOVERY (1 << DI_DISCOVERY__) /* set only during map discovery */ + + #define DI_ALL (DI_SYSFS | DI_SERIAL | DI_CHECKER | DI_PRIO | \ + DI_WWID) +diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c +index 7a4e3eb0..5ccdaea0 100644 +--- a/libmultipath/structs_vec.c ++++ b/libmultipath/structs_vec.c +@@ -109,6 +109,9 @@ static bool update_pathvec_from_dm(vector pathvec, struct multipath *mpp, + bool mpp_has_wwid; + bool must_reload = false; + bool pg_deleted = false; ++ bool map_discovery = !!(pathinfo_flags & DI_DISCOVERY); ++ ++ pathinfo_flags &= ~DI_DISCOVERY; + + if (!mpp->pg) + return false; +@@ -195,7 +198,8 @@ static bool update_pathvec_from_dm(vector pathvec, struct multipath *mpp, + rc = pathinfo(pp, conf, + DI_SYSFS|DI_WWID|DI_BLACKLIST|DI_NOFALLBACK|pathinfo_flags); + pthread_cleanup_pop(1); +- if (rc != PATHINFO_OK) { ++ if (rc == PATHINFO_FAILED || ++ (rc == PATHINFO_SKIPPED && !map_discovery)) { + condlog(1, "%s: error %d in pathinfo, discarding path", + pp->dev, rc); + vector_del_slot(pgp->paths, j--); +diff --git a/multipathd/main.c b/multipathd/main.c +index 9ed27da0..fb3e44a8 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -1763,7 +1763,7 @@ map_discovery (struct vectors * vecs) + return 1; + + vector_foreach_slot (vecs->mpvec, mpp, i) +- if (update_multipath_table(mpp, vecs->pathvec, 0) != DMP_OK) { ++ if (update_multipath_table(mpp, vecs->pathvec, DI_DISCOVERY) != DMP_OK) { + remove_map(mpp, vecs->pathvec, vecs->mpvec); + i--; + } diff --git a/0002-GitHub-workflows-update-dawidd6-action-download-arti.patch b/0002-GitHub-workflows-update-dawidd6-action-download-arti.patch deleted file mode 100644 index 423bf56..0000000 --- a/0002-GitHub-workflows-update-dawidd6-action-download-arti.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 13 Sep 2024 09:10:38 +0200 -Subject: [PATCH] GitHub workflows: update dawidd6/action-download-artifact - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - .github/workflows/abi.yaml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/.github/workflows/abi.yaml b/.github/workflows/abi.yaml -index dce09f5c..d5f8b477 100644 ---- a/.github/workflows/abi.yaml -+++ b/.github/workflows/abi.yaml -@@ -28,7 +28,7 @@ jobs: - - name: get reference ABI - id: reference - continue-on-error: true -- uses: dawidd6/action-download-artifact@v2 -+ uses: dawidd6/action-download-artifact@v6 - with: - workflow: abi.yaml - branch: ${{ env.ABI_BRANCH }} diff --git a/0002-multipath-tools-fix-compilation-with-latest-userspac.patch b/0002-multipath-tools-fix-compilation-with-latest-userspac.patch new file mode 100644 index 0000000..03d7d9d --- /dev/null +++ b/0002-multipath-tools-fix-compilation-with-latest-userspac.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Mon, 3 Feb 2025 16:43:42 -0500 +Subject: [PATCH] multipath-tools: fix compilation with latest userspace-rcu + code + +starting with version 0.15, userspace-rcu can be compiled with +CONFIG_RCU_USE_ATOMIC_BUILTINS. If it is, then any programs using it +must be compiled with at least the C11 standard. See: +https://github.com/urcu/userspace-rcu/commit/89280d020bf064d1055c360fb9974f128051043f + +To deal with this, check if compiling with gnu99 fails, and if so, +switch to using gnu11. + +Based-on-patch-by: Yaakov Selkowitz +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + Makefile.inc | 2 +- + create-config.mk | 13 +++++++++++++ + 2 files changed, 14 insertions(+), 1 deletion(-) + +diff --git a/Makefile.inc b/Makefile.inc +index 729618bd..65f6efc8 100644 +--- a/Makefile.inc ++++ b/Makefile.inc +@@ -115,7 +115,7 @@ CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \ + -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(TGTDIR)$(configdir)\" \ + -DDEFAULT_CONFIGFILE=\"$(TGTDIR)$(configfile)\" -DSTATE_DIR=\"$(TGTDIR)$(statedir)\" \ + -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP +-CFLAGS := -std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \ ++CFLAGS := -std=$(C_STD) $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \ + -fexceptions + BIN_CFLAGS := -fPIE -DPIE + LIB_CFLAGS := -fPIC +diff --git a/create-config.mk b/create-config.mk +index 8bd2c20c..ab163ed1 100644 +--- a/create-config.mk ++++ b/create-config.mk +@@ -157,6 +157,18 @@ FORTIFY_OPT := $(shell \ + echo "-D_FORTIFY_SOURCE=2"; \ + fi) + ++# Check is you can compile with the urcu.h header, using the C99 standard. ++# If urcu/config-.h defines CONFIG_RCU_USE_ATOMIC_BUILTINS, then anything ++# including urcu.h must be compiled with at least the C11 standard. See: ++# https://github.com/urcu/userspace-rcu/commit/89280d020bf064d1055c360fb9974f128051043f ++C_STD := $(shell \ ++ if printf '$(__HASH__)include \nint main(void) { return 0; }\n' | $(CC) -o /dev/null -c -xc --std=gnu99 - 2>/dev/null; \ ++ then \ ++ echo "gnu99"; \ ++ else \ ++ echo "gnu11"; \ ++ fi) ++ + STACKPROT := + + all: $(TOPDIR)/config.mk +@@ -182,3 +194,4 @@ $(TOPDIR)/config.mk: $(multipathdir)/autoconfig.h + @echo "W_MISSING_INITIALIZERS := $(call TEST_MISSING_INITIALIZERS)" >>$@ + @echo "W_URCU_TYPE_LIMITS := $(call TEST_URCU_TYPE_LIMITS)" >>$@ + @echo "ENABLE_LIBDMMP := $(ENABLE_LIBDMMP)" >>$@ ++ @echo "C_STD := $(C_STD)" >>$@ diff --git a/0003-Github-workflows-native.yml-use-mosteo-actions-docke.patch b/0003-Github-workflows-native.yml-use-mosteo-actions-docke.patch deleted file mode 100644 index 63aa273..0000000 --- a/0003-Github-workflows-native.yml-use-mosteo-actions-docke.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 13 Sep 2024 09:45:25 +0200 -Subject: [PATCH] Github workflows: native.yml: use mosteo-actions/docker-run - -We can't use "container:" any more because upload-artifact@v4 doesn't -work on Debian Jessie. - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - .github/workflows/native.yaml | 45 +++++++++++++++++++++-------------- - 1 file changed, 27 insertions(+), 18 deletions(-) - -diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml -index 500becaa..70d01c55 100644 ---- a/.github/workflows/native.yaml -+++ b/.github/workflows/native.yaml -@@ -35,17 +35,9 @@ jobs: - - debian-bookworm - - fedora-40 - - opensuse-leap -- container: ghcr.io/mwilck/multipath-build-${{ matrix.os }} - steps: - - name: checkout - uses: actions/checkout@v1 -- - name: build and test -- if: ${{ matrix.os != 'debian-jessie' }} -- run: make -j -Orecurse test -- - name: build and test (jessie) -- # On jessie, we use libreadline 5 (no licensing issue) -- if: ${{ matrix.os == 'debian-jessie' }} -- run: make -j -Orecurse READLINE=libreadline test - - - name: set archive name - # Leap containers have cpio but not tar -@@ -54,8 +46,21 @@ jobs: - - name: set archive name - run: echo ARCHIVE_TGT=test-progs.tar >> $GITHUB_ENV - if: ${{ matrix.os != 'opensuse-leap' }} -- - name: create binary archive -- run: make ${{ env.ARCHIVE_TGT }} -+ -+ - name: build and test -+ if: ${{ matrix.os != 'debian-jessie' }} -+ uses: mosteo-actions/docker-run@v1 -+ with: -+ image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} -+ command: -j -Orecurse ${{ env.ARCHIVE_TGT }} test -+ - name: build and test (jessie) -+ # On jessie, we use libreadline 5 (no licensing issue) -+ if: ${{ matrix.os == 'debian-jessie' }} -+ uses: mosteo-actions/docker-run@v1 -+ with: -+ image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} -+ command: -j -Orecurse READLINE=libreadline ${{ env.ARCHIVE_TGT }} test -+ - - name: upload binary archive - uses: actions/upload-artifact@v4 - with: -@@ -67,14 +72,18 @@ jobs: - run: make clean - - name: clang - if: ${{ matrix.os != 'debian-jessie' }} -- env: -- CC: clang -- run: make -j -Orecurse test -+ uses: mosteo-actions/docker-run@v1 -+ with: -+ image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} -+ params: -e CC=clang -+ command: -j -Orecurse test - - name: clang (jessie) - if: ${{ matrix.os == 'debian-jessie' }} -- env: -- CC: clang -- run: make READLINE=libreadline test -+ uses: mosteo-actions/docker-run@v1 -+ with: -+ image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} -+ params: -e CC=clang -+ command: -j -Orecurse READLINE=libreadline test - - root-test: - runs-on: ubuntu-22.04 -@@ -103,10 +112,10 @@ jobs: - with: - name: native-${{ matrix.os }} - - name: unpack binary archive -- run: cpio -idv < native-${{ matrix.os }}/test-progs.cpio -+ run: cpio -idv < test-progs.cpio - if: ${{ matrix.os == 'opensuse-leap' }} - - name: unpack binary archive -- run: tar xfmv native-${{ matrix.os }}/test-progs.tar -+ run: tar xfmv test-progs.tar - if: ${{ matrix.os != 'opensuse-leap' }} - - - name: run root tests diff --git a/0003-libmultipath-include-urcu.h-before-urcu-atomic.h.patch b/0003-libmultipath-include-urcu.h-before-urcu-atomic.h.patch new file mode 100644 index 0000000..8da3ce7 --- /dev/null +++ b/0003-libmultipath-include-urcu.h-before-urcu-atomic.h.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 11 Feb 2025 13:11:03 -0500 +Subject: [PATCH] libmultipath: include urcu.h before urcu/atomic.h + +urcu/atomic.h requires some header files included by urcu.h. Make sure +to include it first. + +Fixes: https://github.com/opensvc/multipath-tools/issues/112 +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + libmultipath/checkers/tur.c | 1 + + libmultipath/lock.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c +index e70a2e11..0010acf8 100644 +--- a/libmultipath/checkers/tur.c ++++ b/libmultipath/checkers/tur.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + + #include "checkers.h" +diff --git a/libmultipath/lock.h b/libmultipath/lock.h +index 38473a8c..5f323055 100644 +--- a/libmultipath/lock.h ++++ b/libmultipath/lock.h +@@ -2,6 +2,7 @@ + #define LOCK_H_INCLUDED + + #include ++#include + #include + #include + diff --git a/0004-GitHub-workflows-native.yml-use-extra-job-for-clang.patch b/0004-GitHub-workflows-native.yml-use-extra-job-for-clang.patch deleted file mode 100644 index e6d618c..0000000 --- a/0004-GitHub-workflows-native.yml-use-extra-job-for-clang.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 13 Sep 2024 10:17:17 +0200 -Subject: [PATCH] GitHub workflows: native.yml: use extra job for clang - -Running "make" in a container and "make clean" outside doesn't -work (access right issues). So just use separate jobs. - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - .github/workflows/native.yaml | 18 ++++++++++++++++-- - 1 file changed, 16 insertions(+), 2 deletions(-) - -diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml -index 70d01c55..95b53b87 100644 ---- a/.github/workflows/native.yaml -+++ b/.github/workflows/native.yaml -@@ -68,8 +68,22 @@ jobs: - path: ${{ env.ARCHIVE_TGT }} - overwrite: true - -- - name: clean -- run: make clean -+ clang: -+ runs-on: ubuntu-22.04 -+ strategy: -+ fail-fast: false -+ matrix: -+ os: -+ - debian-jessie -+ - debian-buster -+ - debian-bullseye -+ - debian-bookworm -+ - fedora-40 -+ - opensuse-leap -+ steps: -+ - name: checkout -+ uses: actions/checkout@v1 -+ - - name: clang - if: ${{ matrix.os != 'debian-jessie' }} - uses: mosteo-actions/docker-run@v1 diff --git a/0004-libmpathutils-uxsock.c-Include-string.h-for-memcpy.patch b/0004-libmpathutils-uxsock.c-Include-string.h-for-memcpy.patch new file mode 100644 index 0000000..8fc3211 --- /dev/null +++ b/0004-libmpathutils-uxsock.c-Include-string.h-for-memcpy.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Mon, 17 Feb 2025 12:05:03 -0800 +Subject: [PATCH] libmpathutils/uxsock.c: Include string.h for memcpy + +Fixes +uxsock.c:72:2: error: call to undeclared library function 'memcpy' with type 'void *(void *, const void *, unsigned long)'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] + +Signed-off-by: Khem Raj +Cc: Benjamin Marzinski +Cc: Martin Wilck +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmpathutil/uxsock.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/libmpathutil/uxsock.c b/libmpathutil/uxsock.c +index 2135476d..a474874e 100644 +--- a/libmpathutil/uxsock.c ++++ b/libmpathutil/uxsock.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include diff --git a/0005-GitHub-workflows-native.yaml-make-test-and-archive-s.patch b/0005-GitHub-workflows-native.yaml-make-test-and-archive-s.patch deleted file mode 100644 index cabfbcf..0000000 --- a/0005-GitHub-workflows-native.yaml-make-test-and-archive-s.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 13 Sep 2024 10:30:47 +0200 -Subject: [PATCH] GitHub workflows: native.yaml: make test and archive - separately - -Avoid "text file busy" error on GitHub. - -dmevents-test: Text file busy -Makefile:74: recipe for target 'dmevents.out' failed - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - .github/workflows/native.yaml | 17 +++++++++++++++-- - 1 file changed, 15 insertions(+), 2 deletions(-) - -diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml -index 95b53b87..f06b09df 100644 ---- a/.github/workflows/native.yaml -+++ b/.github/workflows/native.yaml -@@ -52,14 +52,27 @@ jobs: - uses: mosteo-actions/docker-run@v1 - with: - image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} -- command: -j -Orecurse ${{ env.ARCHIVE_TGT }} test -+ command: -j -Orecurse test - - name: build and test (jessie) - # On jessie, we use libreadline 5 (no licensing issue) - if: ${{ matrix.os == 'debian-jessie' }} - uses: mosteo-actions/docker-run@v1 - with: - image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} -- command: -j -Orecurse READLINE=libreadline ${{ env.ARCHIVE_TGT }} test -+ command: -j -Orecurse READLINE=libreadline test -+ -+ - name: create ${{ env.ARCHIVE_TGT }} -+ if: ${{ matrix.os != 'debian-jessie' }} -+ uses: mosteo-actions/docker-run@v1 -+ with: -+ image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} -+ command: ${{ env.ARCHIVE_TGT }} -+ - name: create ${{ env.ARCHIVE_TGT }} (jessie) -+ if: ${{ matrix.os == 'debian-jessie' }} -+ uses: mosteo-actions/docker-run@v1 -+ with: -+ image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} -+ command: READLINE=libreadline ${{ env.ARCHIVE_TGT }} - - - name: upload binary archive - uses: actions/upload-artifact@v4 diff --git a/0033-RH-fixup-udev-rules-for-redhat.patch b/0005-RH-fixup-udev-rules-for-redhat.patch similarity index 98% rename from 0033-RH-fixup-udev-rules-for-redhat.patch rename to 0005-RH-fixup-udev-rules-for-redhat.patch index 0645240..0135f49 100644 --- a/0033-RH-fixup-udev-rules-for-redhat.patch +++ b/0005-RH-fixup-udev-rules-for-redhat.patch @@ -15,7 +15,7 @@ Signed-off-by: Benjamin Marzinski 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile.inc b/Makefile.inc -index 729618bd..81cb61d2 100644 +index 65f6efc8..c225a1ed 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -34,7 +34,7 @@ endif diff --git a/0006-GitHub-workflows-enable-unit-tests-for-stable-branch.patch b/0006-GitHub-workflows-enable-unit-tests-for-stable-branch.patch deleted file mode 100644 index 4a9b254..0000000 --- a/0006-GitHub-workflows-enable-unit-tests-for-stable-branch.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 14 Nov 2024 16:02:38 +0100 -Subject: [PATCH] GitHub workflows: enable unit tests for stable branches - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - .github/workflows/build-and-unittest.yaml | 2 ++ - .github/workflows/foreign.yaml | 2 ++ - .github/workflows/multiarch-stable.yaml | 2 ++ - .github/workflows/multiarch.yaml | 2 ++ - .github/workflows/native.yaml | 2 ++ - .github/workflows/rolling.yaml | 2 ++ - 6 files changed, 12 insertions(+) - -diff --git a/.github/workflows/build-and-unittest.yaml b/.github/workflows/build-and-unittest.yaml -index a838f9a2..1a727e14 100644 ---- a/.github/workflows/build-and-unittest.yaml -+++ b/.github/workflows/build-and-unittest.yaml -@@ -5,10 +5,12 @@ on: - - master - - queue - - tip -+ - 'stable-*' - pull_request: - branches: - - master - - queue -+ - 'stable-*' - jobs: - jammy: - runs-on: ubuntu-22.04 -diff --git a/.github/workflows/foreign.yaml b/.github/workflows/foreign.yaml -index d68650df..0f80957b 100644 ---- a/.github/workflows/foreign.yaml -+++ b/.github/workflows/foreign.yaml -@@ -5,6 +5,7 @@ on: - - master - - queue - - tip -+ - 'stable-*' - paths: - - '.github/workflows/foreign.yaml' - - '**.h' -@@ -15,6 +16,7 @@ on: - branches: - - master - - queue -+ - 'stable-*' - paths: - - '.github/workflows/foreign.yaml' - - '**.h' -diff --git a/.github/workflows/multiarch-stable.yaml b/.github/workflows/multiarch-stable.yaml -index e51d383c..ffede53d 100644 ---- a/.github/workflows/multiarch-stable.yaml -+++ b/.github/workflows/multiarch-stable.yaml -@@ -5,6 +5,7 @@ on: - - master - - queue - - tip -+ - 'stable-*' - paths: - - '.github/workflows/multiarch-stable.yaml' - - '**.h' -@@ -15,6 +16,7 @@ on: - branches: - - master - - queue -+ - 'stable-*' - paths: - - '.github/workflows/multiarch-stable.yaml' - - '**.h' -diff --git a/.github/workflows/multiarch.yaml b/.github/workflows/multiarch.yaml -index df95a02f..d2b833a4 100644 ---- a/.github/workflows/multiarch.yaml -+++ b/.github/workflows/multiarch.yaml -@@ -5,6 +5,7 @@ on: - - master - - queue - - tip -+ - 'stable-*' - paths: - - '.github/workflows/multiarch.yaml' - - '**.h' -@@ -15,6 +16,7 @@ on: - branches: - - master - - queue -+ - 'stable-*' - paths: - - '.github/workflows/multiarch.yaml' - - '**.h' -diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml -index f06b09df..c9d9df9e 100644 ---- a/.github/workflows/native.yaml -+++ b/.github/workflows/native.yaml -@@ -5,6 +5,7 @@ on: - - master - - queue - - tip -+ - 'stable-*' - paths: - - '.github/workflows/native.yaml' - - '**.h' -@@ -15,6 +16,7 @@ on: - branches: - - master - - queue -+ - 'stable-*' - paths: - - '.github/workflows/native.yaml' - - '**.h' -diff --git a/.github/workflows/rolling.yaml b/.github/workflows/rolling.yaml -index 3536b944..66af7a44 100644 ---- a/.github/workflows/rolling.yaml -+++ b/.github/workflows/rolling.yaml -@@ -5,6 +5,7 @@ on: - - master - - queue - - tip -+ - 'stable-*' - paths: - - '.github/workflows/rolling.yaml' - - '**.h' -@@ -15,6 +16,7 @@ on: - branches: - - master - - queue -+ - 'stable-*' - paths: - - '.github/workflows/rolling.yaml' - - '**.h' diff --git a/0034-RH-Remove-the-property-blacklist-exception-builtin.patch b/0006-RH-Remove-the-property-blacklist-exception-builtin.patch similarity index 100% rename from 0034-RH-Remove-the-property-blacklist-exception-builtin.patch rename to 0006-RH-Remove-the-property-blacklist-exception-builtin.patch diff --git a/0007-GitHub-Workflows-add-abi-check-for-stable-branches.patch b/0007-GitHub-Workflows-add-abi-check-for-stable-branches.patch deleted file mode 100644 index c19980f..0000000 --- a/0007-GitHub-Workflows-add-abi-check-for-stable-branches.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 14 Nov 2024 16:51:05 +0100 -Subject: [PATCH] GitHub Workflows: add abi check for stable branches - -The ABI should never change on a stable branch. This workflow -asserts that. - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - .github/workflows/abi-stable.yaml | 89 +++++++++++++++++++++++++++++++ - 1 file changed, 89 insertions(+) - create mode 100644 .github/workflows/abi-stable.yaml - -diff --git a/.github/workflows/abi-stable.yaml b/.github/workflows/abi-stable.yaml -new file mode 100644 -index 00000000..a6746f23 ---- /dev/null -+++ b/.github/workflows/abi-stable.yaml -@@ -0,0 +1,89 @@ -+name: check-abi for stable branch -+on: -+ push: -+ branches: -+ - 'stable-*' -+ paths: -+ - '.github/workflows/abi-stable.yaml' -+ - '**.h' -+ - '**.c' -+ - '**.version' -+ pull_request: -+ branches: -+ - 'stable-*' -+ workflow_dispatch: -+ -+jobs: -+ reference-abi: -+ runs-on: ubuntu-20.04 -+ steps: -+ - name: get parent tag -+ run: > -+ echo ${{ github.ref }} | -+ sed -E 's,refs/heads/stable-([0-9]\.[0-9]*)\.y,PARENT_TAG=\1.0,' >> $GITHUB_ENV -+ - name: assert parent tag -+ run: /bin/false -+ if: ${{ env.PARENT_TAG == '' }} -+ - name: update -+ run: sudo apt-get update -+ - name: dependencies -+ run: > -+ sudo apt-get install --yes gcc -+ gcc make pkg-config abigail-tools -+ libdevmapper-dev libreadline-dev libaio-dev libsystemd-dev -+ libudev-dev libjson-c-dev liburcu-dev libcmocka-dev libedit-dev -+ - name: checkout ${{ env.PARENT_TAG }} -+ uses: actions/checkout@v4 -+ with: -+ ref: ${{ env.PARENT_TAG }} -+ - name: build ABI for ${{ env.PARENT_TAG }} -+ run: make -j$(grep -c ^processor /proc/cpuinfo) -Orecurse abi -+ - name: save ABI -+ uses: actions/upload-artifact@v4 -+ with: -+ name: multipath-abi-${{ env.PARENT_TAG }} -+ path: abi -+ -+ check-abi: -+ runs-on: ubuntu-20.04 -+ needs: reference-abi -+ steps: -+ - name: get parent tag -+ run: > -+ echo ${{ github.ref }} | -+ sed -E 's,refs/heads/stable-([0-9]\.[0-9]*)\.y,PARENT_TAG=\1.0,' >> $GITHUB_ENV -+ - name: assert parent tag -+ run: /bin/false -+ if: ${{ env.PARENT_TAG == '' }} -+ - name: checkout ${{ env.PARENT_TAG }} -+ uses: actions/checkout@v4 -+ with: -+ ref: ${{ env.PARENT_TAG }} -+ - name: download ABI for ${{ env.PARENT_TAG }} -+ id: download_abi -+ uses: actions/download-artifact@v4 -+ with: -+ name: multipath-abi-${{ env.PARENT_TAG }} -+ path: reference-abi -+ - name: update -+ run: sudo apt-get update -+ if: steps.download_abi.outcome != 'success' -+ - name: dependencies -+ run: > -+ sudo apt-get install --yes gcc -+ gcc make pkg-config abigail-tools -+ libdevmapper-dev libreadline-dev libaio-dev libsystemd-dev -+ libudev-dev libjson-c-dev liburcu-dev libcmocka-dev libedit-dev -+ - name: check ABI of ${{ github.ref }} against ${{ env.PARENT_TAG }} -+ id: check_abi -+ run: make -j$(grep -c ^processor /proc/cpuinfo) -Orecurse abi-test -+ continue-on-error: true -+ - name: save differences -+ if: ${{ steps.check_abi.outcome != 'success' }} -+ uses: actions/upload-artifact@v4 -+ with: -+ name: abi-test -+ path: abi-test -+ - name: fail -+ run: /bin/false -+ if: steps.check_abi.outcome != 'success' diff --git a/0035-RH-don-t-start-without-a-config-file.patch b/0007-RH-don-t-start-without-a-config-file.patch similarity index 96% rename from 0035-RH-don-t-start-without-a-config-file.patch rename to 0007-RH-don-t-start-without-a-config-file.patch index 8a3c5b6..edbc647 100644 --- a/0035-RH-don-t-start-without-a-config-file.patch +++ b/0007-RH-don-t-start-without-a-config-file.patch @@ -22,10 +22,10 @@ Signed-off-by: Benjamin Marzinski 7 files changed, 25 insertions(+) diff --git a/libmultipath/config.c b/libmultipath/config.c -index 226ddecb..588ae9ee 100644 +index 8b424d18..b8317f4d 100644 --- a/libmultipath/config.c +++ b/libmultipath/config.c -@@ -962,6 +962,19 @@ int init_config__ (const char *file, struct config *conf) +@@ -937,6 +937,19 @@ int init_config__ (const char *file, struct config *conf) } factorize_hwtable(conf->hwtable, builtin_hwtable_size, file); validate_pctable(conf->overrides, 0, file); @@ -46,7 +46,7 @@ index 226ddecb..588ae9ee 100644 conf->processed_main_config = 1; diff --git a/libmultipath/config.h b/libmultipath/config.h -index 94cdf252..534b6142 100644 +index 5b4ebf8c..2302eacc 100644 --- a/libmultipath/config.h +++ b/libmultipath/config.h @@ -10,6 +10,7 @@ @@ -112,7 +112,7 @@ index 7bc8806e..315884eb 100644 . .\" ---------------------------------------------------------------------------- diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in -index 646001e6..72e44849 100644 +index b6a25b31..3d957733 100644 --- a/multipathd/multipathd.service.in +++ b/multipathd/multipathd.service.in @@ -6,6 +6,7 @@ Wants=systemd-udevd-kernel.socket @MODPROBE_UNIT@ diff --git a/0036-RH-Fix-nvme-function-missing-argument.patch b/0008-RH-Fix-nvme-function-missing-argument.patch similarity index 100% rename from 0036-RH-Fix-nvme-function-missing-argument.patch rename to 0008-RH-Fix-nvme-function-missing-argument.patch diff --git a/0008-libmultipath-dm_get_maps-don-t-bail-out-for-single-m.patch b/0008-libmultipath-dm_get_maps-don-t-bail-out-for-single-m.patch deleted file mode 100644 index 88122b0..0000000 --- a/0008-libmultipath-dm_get_maps-don-t-bail-out-for-single-m.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Tue, 12 Nov 2024 13:06:10 +0100 -Subject: [PATCH] libmultipath: dm_get_maps(): don't bail out for single-map - failures - -dm_get_maps() traverses the entire list of dm maps. We shouldn't -give up just because probing a single map failed. - -Fixes: bf3a4ad ("libmultipath: simplify dm_get_maps()") -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - libmultipath/devmapper.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c -index c497c225..52bfe9ce 100644 ---- a/libmultipath/devmapper.c -+++ b/libmultipath/devmapper.c -@@ -1262,10 +1262,8 @@ int dm_get_maps(vector mp) - } - vector_set_slot(mp, mpp); - break; -- case DMP_NO_MATCH: -- break; - default: -- return 1; -+ break; - } - next = names->next; - names = (void *) names + next; diff --git a/0009-11-dm-mpath.rules.in-import-DM_COLDPLUG_SUSPENDED-on.patch b/0009-11-dm-mpath.rules.in-import-DM_COLDPLUG_SUSPENDED-on.patch deleted file mode 100644 index b380f75..0000000 --- a/0009-11-dm-mpath.rules.in-import-DM_COLDPLUG_SUSPENDED-on.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 31 Oct 2024 12:08:08 +0100 -Subject: [PATCH] 11-dm-mpath.rules.in: import DM_COLDPLUG_SUSPENDED only once - -We import DM_COLDPLUG_SUSPENDED in all code flows below mpath_coldplug_end. -Clarify this in the code. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - multipath/11-dm-mpath.rules.in | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in -index 30647b99..67838261 100644 ---- a/multipath/11-dm-mpath.rules.in -+++ b/multipath/11-dm-mpath.rules.in -@@ -24,12 +24,13 @@ ENV{DM_UDEV_RULES_VSN}=="1|2", ENV{.DM_SUSPENDED}!="1", ENV{DISK_RO}!="1", \ - ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="", GOTO="scan_import" - LABEL="mpath_coldplug_end" - -+IMPORT{db}="DM_COLDPLUG_SUSPENDED" -+ - # If this uevent didn't come from dm, don't try to update the - # device state - # Note that .MPATH_DEVICE_READY_OLD=="" here. Thus we won't activate the - # device below at mpath_is_ready, which is correct. - ENV{DM_COOKIE}!="?*", ENV{DM_ACTION}!="PATH_*", \ -- IMPORT{db}="DM_COLDPLUG_SUSPENDED", \ - GOTO="check_mpath_ready" - - ENV{.MPATH_DEVICE_READY_OLD}="$env{MPATH_DEVICE_READY}" -@@ -67,7 +68,6 @@ LABEL="check_mpath_unchanged" - # A previous coldplug event occurred while the device was suspended. - # Activation might have been partially skipped. Activate the device now, - # i.e. disable the MPATH_UNCHANGED logic and set DM_ACTIVATION=1. --IMPORT{db}="DM_COLDPLUG_SUSPENDED" - ENV{DM_COLDPLUG_SUSPENDED}=="1", ENV{.DM_SUSPENDED}!="1", \ - ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0", \ - PROGRAM="@SYSDIR_BIN@/logger -t 11-dm-mpath.rules -p daemon.notice \"Forcing activation of previously suspended device\"", \ diff --git a/0037-RH-use-rpm-optflags-if-present.patch b/0009-RH-use-rpm-optflags-if-present.patch similarity index 92% rename from 0037-RH-use-rpm-optflags-if-present.patch rename to 0009-RH-use-rpm-optflags-if-present.patch index 66d14bc..1b96a3a 100644 --- a/0037-RH-use-rpm-optflags-if-present.patch +++ b/0009-RH-use-rpm-optflags-if-present.patch @@ -7,14 +7,13 @@ Use the passed in optflags when compiling as an RPM, and keep the default flags as close as possible to the current fedora flags, while still being generic. -Co-authored-by: Yaakov Selkowitz Signed-off-by: Benjamin Marzinski --- Makefile.inc | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/Makefile.inc b/Makefile.inc -index 81cb61d2..a5024bb7 100644 +index c225a1ed..7774f1f4 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -99,28 +99,39 @@ SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo @@ -53,9 +52,9 @@ index 81cb61d2..a5024bb7 100644 -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(TGTDIR)$(configdir)\" \ -DDEFAULT_CONFIGFILE=\"$(TGTDIR)$(configfile)\" -DSTATE_DIR=\"$(TGTDIR)$(statedir)\" \ -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP --CFLAGS := -std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \ +-CFLAGS := -std=$(C_STD) $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \ - -fexceptions -+CFLAGS := -std=gnu11 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe ++CFLAGS := -std=$(C_STD) $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe BIN_CFLAGS := -fPIE -DPIE LIB_CFLAGS := -fPIC SHARED_FLAGS := -shared diff --git a/0010-11-dm-mpath.rules.in-handle-inactive-suspended-devic.patch b/0010-11-dm-mpath.rules.in-handle-inactive-suspended-devic.patch deleted file mode 100644 index f34e699..0000000 --- a/0010-11-dm-mpath.rules.in-handle-inactive-suspended-devic.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 31 Oct 2024 12:59:03 +0100 -Subject: [PATCH] 11-dm-mpath.rules.in: handle inactive suspended devices - correctly - -Since b22c273 ("11-dm-mpath.rules: Don't force activation while device is -suspended"), we've handled the case where a device is suspended while -an uevent is processed (e.g. because multipathd is reloading the -map again at the same time). But we were missing the case where -The device had never been initialized before. If .MPATH_DEVICE_READY_OLD -was empty, we'd jump to scan_import without setting MPATH_DEVICE_READY -to 0. This can cause a device not to be fully activated at boot time, -because in follow-up uevents we'd assume that the device had already -been set up. - -Treat the case in which an uevent is processed for a previously not -fully set-up, suspended device like other situations where we set -MPATH_DEVICE_READY to 0. - -Fixes: b22c273 ("11-dm-mpath.rules: Don't force activation while device is -suspended") -Reviewed-by: Benjamin Marzinski - -Signed-off-by: Benjamin Marzinski ---- - multipath/11-dm-mpath.rules.in | 19 +++++++++++-------- - 1 file changed, 11 insertions(+), 8 deletions(-) - -diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in -index 67838261..20f8c6ac 100644 ---- a/multipath/11-dm-mpath.rules.in -+++ b/multipath/11-dm-mpath.rules.in -@@ -35,6 +35,13 @@ ENV{DM_COOKIE}!="?*", ENV{DM_ACTION}!="PATH_*", \ - - ENV{.MPATH_DEVICE_READY_OLD}="$env{MPATH_DEVICE_READY}" - -+# If the device wasn't ready previously and is currently suspended, -+# we have to postpone the activation until the next event. -+# In this case, we have to set MPATH_DEVICE_READY=0; otherwise, the -+# MPATH_UNCHANGED logic will cause later rules to skipped in the next event. -+ENV{.MPATH_DEVICE_READY_OLD}!="1", ENV{.DM_SUSPENDED}=="1", \ -+ ENV{MPATH_DEVICE_READY}="0", GOTO="check_mpath_unchanged" -+ - # multipath sets DM_SUBSYSTEM_UDEV_FLAG2 when it reloads a - # table with no active devices. If this happens, mark the - # device not ready -@@ -106,14 +113,10 @@ GOTO="scan_import" - LABEL="mpath_is_ready" - - # If the device comes back online, set DM_ACTIVATION so that --# upper layers do a rescan. If the device is currently suspended, --# we have to postpone the activation until the next event. --# In this case, we have to set MPATH_DEVICE_READY=0; otherwise, the --# MPATH_UNCHANGED logic will cause later rules to skipped in the next event. --ENV{.MPATH_DEVICE_READY_OLD}!="0", GOTO="scan_import" --ENV{.DM_SUSPENDED}=="1", ENV{MPATH_DEVICE_READY}="0", GOTO="scan_import" -- --ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0" -+# upper layers will do a rescan. Don't do this if .MPATH_DEVICE_READY_OLD -+# is just empty (see comment above the DM_COOKIE test above). -+ENV{.MPATH_DEVICE_READY_OLD}=="0", \ -+ ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0" - - # The code to check multipath state ends here. We need to set - # properties and symlinks regardless whether the map is usable or diff --git a/0038-RH-add-mpathconf.patch b/0010-RH-add-mpathconf.patch similarity index 99% rename from 0038-RH-add-mpathconf.patch rename to 0010-RH-add-mpathconf.patch index 103ca55..c587841 100644 --- a/0038-RH-add-mpathconf.patch +++ b/0010-RH-add-mpathconf.patch @@ -23,10 +23,10 @@ Signed-off-by: Benjamin Marzinski create mode 100644 multipath/mpathconf.8 diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt -index 4ac57510..3602a071 100644 +index 7843c380..ab5259cf 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt -@@ -126,9 +126,11 @@ Marzinski +@@ -127,9 +127,11 @@ Marzinski misdetection mpath mpathb @@ -38,7 +38,7 @@ index 4ac57510..3602a071 100644 multipathc multipathd multipathed -@@ -146,6 +148,7 @@ ontap +@@ -147,6 +149,7 @@ ontap OOM opensvc OPTFLAGS @@ -47,10 +47,10 @@ index 4ac57510..3602a071 100644 partx pathgroup diff --git a/libmultipath/config.c b/libmultipath/config.c -index 588ae9ee..3cb8449c 100644 +index b8317f4d..0bbaa981 100644 --- a/libmultipath/config.c +++ b/libmultipath/config.c -@@ -964,6 +964,8 @@ int init_config__ (const char *file, struct config *conf) +@@ -939,6 +939,8 @@ int init_config__ (const char *file, struct config *conf) validate_pctable(conf->overrides, 0, file); } else { condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices."); diff --git a/0011-11-dm-mpath.rules.in-clarify-DM_ACTIVATION-logic.patch b/0011-11-dm-mpath.rules.in-clarify-DM_ACTIVATION-logic.patch deleted file mode 100644 index cb129bf..0000000 --- a/0011-11-dm-mpath.rules.in-clarify-DM_ACTIVATION-logic.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 31 Oct 2024 13:11:21 +0100 -Subject: [PATCH] 11-dm-mpath.rules.in: clarify DM_ACTIVATION logic - -Our code is always setting MPATH_UNCHANGED and DM_ACTIVATION in -pairs. While DM_ACTIVATION is a global DM property, MPATH_UNCHANGED -is owned by us. Just set MPATH_UNCHANGED, and adapt DM_ACTIVATION -when necessary just in one place. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - multipath/11-dm-mpath.rules.in | 21 ++++++++++++--------- - 1 file changed, 12 insertions(+), 9 deletions(-) - -diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in -index 20f8c6ac..a2655cb2 100644 ---- a/multipath/11-dm-mpath.rules.in -+++ b/multipath/11-dm-mpath.rules.in -@@ -74,25 +74,25 @@ LABEL="check_mpath_unchanged" - - # A previous coldplug event occurred while the device was suspended. - # Activation might have been partially skipped. Activate the device now, --# i.e. disable the MPATH_UNCHANGED logic and set DM_ACTIVATION=1. -+# i.e. disable the MPATH_UNCHANGED logic. - ENV{DM_COLDPLUG_SUSPENDED}=="1", ENV{.DM_SUSPENDED}!="1", \ -- ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0", \ -+ ENV{MPATH_UNCHANGED}="0", \ - PROGRAM="@SYSDIR_BIN@/logger -t 11-dm-mpath.rules -p daemon.notice \"Forcing activation of previously suspended device\"", \ - GOTO="check_mpath_ready" - - # DM_SUBSYSTEM_UDEV_FLAG0 is the "RELOAD" flag for multipath subsystem. --# Drop the DM_ACTIVATION flag here as mpath reloads tables if any of its -+# Set the MPATH_UNCHANGED flag here as mpath reloads tables if any of its - # paths are lost/recovered. For any stack above the mpath device, this is not - # something that should be reacted upon since it would be useless extra work. - # It's exactly mpath's job to provide *seamless* device access to any of the - # paths that are available underneath. - ENV{DM_SUBSYSTEM_UDEV_FLAG0}=="1", \ -- ENV{DM_ACTIVATION}="0", ENV{MPATH_UNCHANGED}="1" -+ ENV{MPATH_UNCHANGED}="1" - --# For path failed or reinstated events, unset DM_ACTIVATION. -+# For path failed or reinstated events, set MPATH_UNCHANGED. - # This is similar to the DM_SUBSYSTEM_UDEV_FLAG0 case above. - ENV{DM_ACTION}=="PATH_FAILED|PATH_REINSTATED", \ -- ENV{DM_ACTIVATION}="0", ENV{MPATH_UNCHANGED}="1" -+ ENV{MPATH_UNCHANGED}="1" - - LABEL="check_mpath_ready" - -@@ -112,11 +112,10 @@ GOTO="scan_import" - - LABEL="mpath_is_ready" - --# If the device comes back online, set DM_ACTIVATION so that -+# If the device comes back online, clear MPATH_UNCHANGED so that - # upper layers will do a rescan. Don't do this if .MPATH_DEVICE_READY_OLD - # is just empty (see comment above the DM_COOKIE test above). --ENV{.MPATH_DEVICE_READY_OLD}=="0", \ -- ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0" -+ENV{.MPATH_DEVICE_READY_OLD}=="0", ENV{MPATH_UNCHANGED}="0" - - # The code to check multipath state ends here. We need to set - # properties and symlinks regardless whether the map is usable or -@@ -146,6 +145,10 @@ IMPORT{db}="ID_PART_GPT_AUTO_ROOT" - - LABEL="import_end" - -+# If MPATH_UNCHANGED is set, adapt DM_ACTIVATION. -+ENV{MPATH_UNCHANGED}=="0", ENV{DM_ACTIVATION}="1" -+ENV{MPATH_UNCHANGED}=="1", ENV{DM_ACTIVATION}="0" -+ - # Reset previous DM_COLDPLUG_SUSPENDED if activation happens now - ENV{.DM_SUSPENDED}!="1", ENV{DM_ACTIVATION}=="1", ENV{DM_COLDPLUG_SUSPENDED}="" - diff --git a/0039-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch b/0011-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch similarity index 97% rename from 0039-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch rename to 0011-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch index 4e781fa..612d876 100644 --- a/0039-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +++ b/0011-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch @@ -138,14 +138,14 @@ index b88e9a4c..edd742aa 100644 Remove the WWID for the specified device from the WWIDs file. . diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in -index 72e44849..69a6c39d 100644 +index 3d957733..7ef6e99e 100644 --- a/multipathd/multipathd.service.in +++ b/multipathd/multipathd.service.in -@@ -17,6 +17,7 @@ ConditionVirtualization=!container +@@ -19,6 +19,7 @@ StartLimitBurst=3 [Service] Type=notify NotifyAccess=main +ExecStartPre=-@BINDIR@/multipath -A ExecStart=@BINDIR@/multipathd -d -s ExecReload=@BINDIR@/multipathd reconfigure - TasksMax=infinity + Restart=on-failure diff --git a/0012-11-dm-mpath-rules.in-skip-one-.DM_NOSCAN-check.patch b/0012-11-dm-mpath-rules.in-skip-one-.DM_NOSCAN-check.patch deleted file mode 100644 index cb1620a..0000000 --- a/0012-11-dm-mpath-rules.in-skip-one-.DM_NOSCAN-check.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Sun, 3 Nov 2024 23:04:08 +0100 -Subject: [PATCH] 11-dm-mpath-rules.in: skip one .DM_NOSCAN check - -We set .DM_NOSCAN above where we set DM_UDEV_DISABLE_OTHER_RULES_FLAG, too. If -the latter isn't set, .DM_NOSCAN can't be set. Skip the redundant test. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - multipath/11-dm-mpath.rules.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in -index a2655cb2..79227bec 100644 ---- a/multipath/11-dm-mpath.rules.in -+++ b/multipath/11-dm-mpath.rules.in -@@ -132,7 +132,7 @@ ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}!="1", GOTO="import_end" - ENV{DM_UDEV_RULES_VSN}!="1|2", GOTO="import_end" - - # Don't import the properties from db if we will run blkid later. --ENV{.DM_NOSCAN}!="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}!="1", GOTO="import_end" -+ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}!="1", GOTO="import_end" - - IMPORT{db}="ID_FS_TYPE" - IMPORT{db}="ID_FS_USAGE" diff --git a/0040-RH-reset-default-find_mutipaths-value-to-off.patch b/0012-RH-reset-default-find_mutipaths-value-to-off.patch similarity index 100% rename from 0040-RH-reset-default-find_mutipaths-value-to-off.patch rename to 0012-RH-reset-default-find_mutipaths-value-to-off.patch diff --git a/0013-11-dm-mpath.rules.in-set-.DM_NOSCAN-if-MPATH_UNCHANG.patch b/0013-11-dm-mpath.rules.in-set-.DM_NOSCAN-if-MPATH_UNCHANG.patch deleted file mode 100644 index 36cd91d..0000000 --- a/0013-11-dm-mpath.rules.in-set-.DM_NOSCAN-if-MPATH_UNCHANG.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Sun, 3 Nov 2024 23:07:23 +0100 -Subject: [PATCH] 11-dm-mpath.rules.in: set .DM_NOSCAN if MPATH_UNCHANGED is - set - -When multipath reloads a device or fails or restores a path, the udev -rules disable LVM scanning, but since .DM_NOSCAN isn't set, blkid is -still run on the device. When multipath devices that are set to -queue_if_no_path lose all their paths at close to the same time, udev -workers can hang trying to run blkid. The blkid results shouldn't -change when multipathd is adding, removing, failing or reinstating -paths, aside from avoiding hanging udev processes, we're skipping -unnecessary work. - -Hence, set .DM_NOSCAN if MPATH_UNCHANGED is set, to avoid blkid from -being called in 13-dm.rules. - -Suggested-by: Benjamin Marzinski -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - multipath/11-dm-mpath.rules.in | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in -index 79227bec..a816edbf 100644 ---- a/multipath/11-dm-mpath.rules.in -+++ b/multipath/11-dm-mpath.rules.in -@@ -145,9 +145,11 @@ IMPORT{db}="ID_PART_GPT_AUTO_ROOT" - - LABEL="import_end" - --# If MPATH_UNCHANGED is set, adapt DM_ACTIVATION. -+# If MPATH_UNCHANGED is set, adapt DM_ACTIVATION and DM_NOSCAN. -+# .DM_NOSCAN controls whether blkid will be run in 13-dm-disk.rules; -+# we don't want to do that if MPATH_UNCHANGED is 1. - ENV{MPATH_UNCHANGED}=="0", ENV{DM_ACTIVATION}="1" --ENV{MPATH_UNCHANGED}=="1", ENV{DM_ACTIVATION}="0" -+ENV{MPATH_UNCHANGED}=="1", ENV{DM_ACTIVATION}="0", ENV{.DM_NOSCAN}="1" - - # Reset previous DM_COLDPLUG_SUSPENDED if activation happens now - ENV{.DM_SUSPENDED}!="1", ENV{DM_ACTIVATION}=="1", ENV{DM_COLDPLUG_SUSPENDED}="" diff --git a/0041-RH-attempt-to-get-ANA-info-via-sysfs-first.patch b/0013-RH-attempt-to-get-ANA-info-via-sysfs-first.patch similarity index 100% rename from 0041-RH-attempt-to-get-ANA-info-via-sysfs-first.patch rename to 0013-RH-attempt-to-get-ANA-info-via-sysfs-first.patch diff --git a/0042-RH-make-parse_vpd_pg83-match-scsi_id-output.patch b/0014-RH-make-parse_vpd_pg83-match-scsi_id-output.patch similarity index 94% rename from 0042-RH-make-parse_vpd_pg83-match-scsi_id-output.patch rename to 0014-RH-make-parse_vpd_pg83-match-scsi_id-output.patch index 0d5baa3..3243375 100644 --- a/0042-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +++ b/0014-RH-make-parse_vpd_pg83-match-scsi_id-output.patch @@ -14,10 +14,10 @@ Signed-off-by: Benjamin Marzinski 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index 5043330c..e14507e8 100644 +index b5851561..a3cc6e83 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c -@@ -1221,13 +1221,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, +@@ -1219,13 +1219,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, good_len = 8; break; case 2: @@ -33,7 +33,7 @@ index 5043330c..e14507e8 100644 good_len = 8; break; default: -@@ -1245,10 +1241,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, +@@ -1243,10 +1239,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, break; case 0x8: /* SCSI Name: Prio 3 */ diff --git a/0014-libmultipath-don-t-set-dev_loss_tmo-to-0-for-NO_PATH.patch b/0014-libmultipath-don-t-set-dev_loss_tmo-to-0-for-NO_PATH.patch deleted file mode 100644 index b7ae3c4..0000000 --- a/0014-libmultipath-don-t-set-dev_loss_tmo-to-0-for-NO_PATH.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 7 Nov 2024 22:07:03 +0100 -Subject: [PATCH] libmultipath: don't set dev_loss_tmo to 0 for - NO_PATH_RETRY_FAIL - -If pp->dev_loss is DEV_LOSS_TMO_UNSET and min_dev_loss is 0 (which is -the case if no_path_retry is NO_PATH_RETRY_FAIL or NO_PATH_RETRY_UNDEF), -we will set pp->dev_loss to 0, which is wrong. Fix it. - -Fixes: 058b5f5 ("libmultipath: fix dev_loss_tmo even if not set in configuration") -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/discovery.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index e94705bf..5043330c 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -942,7 +942,7 @@ sysfs_set_scsi_tmo (struct config *conf, struct multipath *mpp) - continue; - } - -- if (pp->dev_loss == DEV_LOSS_TMO_UNSET) -+ if (pp->dev_loss == DEV_LOSS_TMO_UNSET && min_dev_loss != 0) - pp->dev_loss = min_dev_loss; - else if (pp->dev_loss < min_dev_loss) { - pp->dev_loss = min_dev_loss; diff --git a/0043-RH-add-scsi-device-handlers-to-modules-load.d.patch b/0015-RH-add-scsi-device-handlers-to-modules-load.d.patch similarity index 96% rename from 0043-RH-add-scsi-device-handlers-to-modules-load.d.patch rename to 0015-RH-add-scsi-device-handlers-to-modules-load.d.patch index ef0ee42..97fb4df 100644 --- a/0043-RH-add-scsi-device-handlers-to-modules-load.d.patch +++ b/0015-RH-add-scsi-device-handlers-to-modules-load.d.patch @@ -11,7 +11,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc -index a5024bb7..834b63b9 100644 +index 7774f1f4..0e836f0a 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -16,7 +16,7 @@ READLINE := diff --git a/0015-multipathd-fix-deferred_failback_tick-for-reload-rem.patch b/0015-multipathd-fix-deferred_failback_tick-for-reload-rem.patch deleted file mode 100644 index f775e85..0000000 --- a/0015-multipathd-fix-deferred_failback_tick-for-reload-rem.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Mon, 14 Oct 2024 23:28:30 -0400 -Subject: [PATCH] multipathd: fix deferred_failback_tick for reload removes - -If reload_and_sync_map() removes the multipath device, -deferred_failback_tick() needs to decrement the counter so that it -doesn't skip the following device. - -Reviewed-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - multipathd/main.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/multipathd/main.c b/multipathd/main.c -index 1b7fd04f..e4ef9a1d 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -2080,9 +2080,12 @@ deferred_failback_tick (struct vectors *vecs) - - if (!mpp->failback_tick && - need_switch_pathgroup(mpp, &need_reload)) { -- if (need_reload) -- reload_and_sync_map(mpp, vecs); -- else -+ if (need_reload) { -+ if (reload_and_sync_map(mpp, vecs) == 2) { -+ /* multipath device removed */ -+ i--; -+ } -+ } else - switch_pathgroup(mpp); - } - } diff --git a/0044-RH-compile-with-libreadline-support.patch b/0016-RH-compile-with-libreadline-support.patch similarity index 96% rename from 0044-RH-compile-with-libreadline-support.patch rename to 0016-RH-compile-with-libreadline-support.patch index 50781c3..e7579b0 100644 --- a/0044-RH-compile-with-libreadline-support.patch +++ b/0016-RH-compile-with-libreadline-support.patch @@ -12,7 +12,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc -index 834b63b9..c482a181 100644 +index 0e836f0a..e1d3fcd1 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -12,7 +12,7 @@ diff --git a/0016-multipathd-fix-an-unsigned-int-ovwerflow.patch b/0016-multipathd-fix-an-unsigned-int-ovwerflow.patch deleted file mode 100644 index 12c9a51..0000000 --- a/0016-multipathd-fix-an-unsigned-int-ovwerflow.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Wed, 13 Nov 2024 16:19:49 +0100 -Subject: [PATCH] multipathd: fix an unsigned int ovwerflow - -Reported by coverity: "i--" may cause an underflow, which will again -cause an overflow when the loop continues. Use a signed int for -loops like this to make coverity happy. - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - multipathd/main.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/multipathd/main.c b/multipathd/main.c -index e4ef9a1d..3fb623fd 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -2068,7 +2068,7 @@ static void - deferred_failback_tick (struct vectors *vecs) - { - struct multipath * mpp; -- unsigned int i; -+ int i; - bool need_reload; - - vector_foreach_slot (vecs->mpvec, mpp, i) { diff --git a/0045-RH-Add-mpathcleanup.patch b/0017-RH-Add-mpathcleanup.patch similarity index 100% rename from 0045-RH-Add-mpathcleanup.patch rename to 0017-RH-Add-mpathcleanup.patch diff --git a/0017-libmpathutil-avoid-Wcast-function-type-mismatch-erro.patch b/0017-libmpathutil-avoid-Wcast-function-type-mismatch-erro.patch deleted file mode 100644 index 64b90d7..0000000 --- a/0017-libmpathutil-avoid-Wcast-function-type-mismatch-erro.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Wed, 6 Nov 2024 22:17:16 +0100 -Subject: [PATCH] libmpathutil: avoid -Wcast-function-type-mismatch error with - clang 19 - -Avoid the following error with clang 19: - -msort.c:268:27: error: cast from '__compar_fn_t' (aka 'int (*)(const void *, const void *)') to '__compar_d_fn_t' (aka 'int (*)(const void *, const void *, void *)') converts to incompatible function type [-Werror,-Wcast-function-type-mismatch] - 268 | return msort_r (b, n, s, (__compar_d_fn_t)cmp, NULL); - | ^~~~~~~~~~~~~~~~~~~~ - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - libmpathutil/msort.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/libmpathutil/msort.c b/libmpathutil/msort.c -index 50f799d9..9df7b267 100644 ---- a/libmpathutil/msort.c -+++ b/libmpathutil/msort.c -@@ -259,9 +259,12 @@ msort_r (void *b, size_t n, size_t s, __compar_d_fn_t cmp, void *arg) - * If this is safe for them, it should be for us, too. - */ - #pragma GCC diagnostic push --#if __GNUC__ >= 8 -+#if __GNUC__ >= 8 || __clang_major__ >= 19 - #pragma GCC diagnostic ignored "-Wcast-function-type" - #endif -+#if __clang_major__ >= 19 -+#pragma GCC diagnostic ignored "-Wcast-function-type-mismatch" -+#endif - void - msort (void *b, size_t n, size_t s, __compar_fn_t cmp) - { diff --git a/0018-Update-NEWS.md-for-0.10.1.patch b/0018-Update-NEWS.md-for-0.10.1.patch deleted file mode 100644 index 601b6e5..0000000 --- a/0018-Update-NEWS.md-for-0.10.1.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 14 Nov 2024 17:59:14 +0100 -Subject: [PATCH] Update NEWS.md for 0.10.1 - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - NEWS.md | 23 +++++++++++++++++++++++ - 1 file changed, 23 insertions(+) - -diff --git a/NEWS.md b/NEWS.md -index 69acda47..b740efb1 100644 ---- a/NEWS.md -+++ b/NEWS.md -@@ -1,5 +1,28 @@ - # multipath-tools Release Notes - -+## multipath-tools 0.10.1, 2024/11 -+ -+This is the first bug fix release on the `stable-0.10.y` branch. It contains -+bug fixes from 0.11.0, and some CI-related fixes. -+ -+### Bug fixes -+ -+* Fixed the problem that multipathd wouldn't start on systems with certain types -+ of device mapper devices, in particular devices with multiple DM targets. -+ The problem was introduced in 0.10.0. -+ Fixes [#102](https://github.com/opensvc/multipath-tools/issues/102). -+* Fixed a corner case in the udev rules which could cause a device not to be -+ activated during boot if a cold plug uevent is processed for a previously -+ not configured multipath map while this map was suspended. This problem existed -+ since 0.9.8. -+* Fixed the problem that devices with `no_path_retry fail` and no setting -+ for `dev_loss_tmo` might get the `dev_loss_tmo` set to 0, causing the -+ device to be deleted immediately in the event of a transport disruption. -+ This bug was introduced in 0.9.6. -+* Fixed the problem that, if there were multiple maps with deferred failback -+ (`failback` value > 0 in `multipath.conf`), some maps might fail back later -+ than configured. The problem existed since 0.9.6. -+ - ## multipath-tools 0.10.0, 2024/08 - - ### User-Visible Changes diff --git a/0019-libmultipath-don-t-print-error-message-if-WATCHDOG_U.patch b/0019-libmultipath-don-t-print-error-message-if-WATCHDOG_U.patch deleted file mode 100644 index 18fb614..0000000 --- a/0019-libmultipath-don-t-print-error-message-if-WATCHDOG_U.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 14 Nov 2024 15:20:24 +0100 -Subject: [PATCH] libmultipath: don't print error message if WATCHDOG_USEC is 0 - -WATCHDOG_USEC may be set to 0, which means that the watchdog -is disabled in systemd. - -Fixes: 9366cfb ("multipathd: Implement systemd watchdog integration") -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmultipath/config.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/libmultipath/config.c b/libmultipath/config.c -index 0e3a5cc1..226ddecb 100644 ---- a/libmultipath/config.c -+++ b/libmultipath/config.c -@@ -865,6 +865,9 @@ static void set_max_checkint_from_watchdog(struct config *conf) - unsigned long checkint; - - if (envp && sscanf(envp, "%lu", &checkint) == 1) { -+ if (checkint == 0) -+ /* watchdog disabled */ -+ return; - /* Value is in microseconds */ - checkint /= 1000000; - if (checkint < 1 || checkint > UINT_MAX) { diff --git a/0020-libmultipath-reduce-log-level-of-map-X-has-multiple-.patch b/0020-libmultipath-reduce-log-level-of-map-X-has-multiple-.patch deleted file mode 100644 index 7467627..0000000 --- a/0020-libmultipath-reduce-log-level-of-map-X-has-multiple-.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Mon, 25 Nov 2024 18:01:32 +0100 -Subject: [PATCH] libmultipath: reduce log level of "map X has multiple - targets" - -On systems with LVM volumes, "multipath -ll" will spit out lots of messages -like - - libmp_mapinfo: map vg-lv0 has multiple targets - -which is irritating. Reduce the log level of these messages to 3, as they -are harmless most of the time. - -This is a backport of e8949c2 ("libmultipath: reduce log level of -libmp_mapinfo() messages") from the master branch. We can't apply exactly -the same fix because the stable branch is missing 8c772d3 ("libmultipath: -check DM UUID earlier in libmp_mapinfo__"). - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - libmultipath/devmapper.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c -index 52bfe9ce..fe5637b3 100644 ---- a/libmultipath/devmapper.c -+++ b/libmultipath/devmapper.c -@@ -718,7 +718,7 @@ static int libmp_mapinfo__(int flags, mapid_t id, mapinfo_t info, const char *ma - if (info.target || info.status || info.size || flags & MAPINFO_TGT_TYPE__) { - if (dm_get_next_target(dmt, NULL, &start, &length, - &target_type, ¶ms) != NULL) { -- condlog(2, "%s: map %s has multiple targets", fname__, map_id); -+ condlog(3, "%s: map %s has multiple targets", fname__, map_id); - return DMP_NOT_FOUND; - } - if (!params) { diff --git a/0021-libmultipath-foreign-fix-memory-leak-in-nvme-foreign.patch b/0021-libmultipath-foreign-fix-memory-leak-in-nvme-foreign.patch deleted file mode 100644 index 2610c6d..0000000 --- a/0021-libmultipath-foreign-fix-memory-leak-in-nvme-foreign.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Wed, 8 Jan 2025 19:06:53 -0500 -Subject: [PATCH] libmultipath/foreign: fix memory leak in nvme foreign handler - -_find_controllers() needs to free the udev device if it doesn't get -added to a path. Otherwise it can leak memory whenever check_foreign() -is called, causing multipathd's memory usage to continually grow. - -Fixes: 7b47762 ("libmultipath: nvme: fix path detection for kernel 4.16") -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck -(cherry picked from commit 5a3d334e416a4a35ee88d7b8f1433ff7f57923ad) ---- - libmultipath/foreign/nvme.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/libmultipath/foreign/nvme.c b/libmultipath/foreign/nvme.c -index 0b7f4eab..cde660ce 100644 ---- a/libmultipath/foreign/nvme.c -+++ b/libmultipath/foreign/nvme.c -@@ -675,7 +675,8 @@ static void _find_controllers(struct context *ctx, struct nvme_map *map) - pthread_cleanup_push_cast(free_scandir_result, &sr); - for (i = 0; i < r; i++) { - char *fn = di[i]->d_name; -- struct udev_device *ctrl, *udev; -+ struct udev_device *ctrl; -+ struct udev_device *udev __attribute__((cleanup(cleanup_udev_device))) = NULL; - - if (safe_snprintf(pathbuf + n, sizeof(pathbuf) - n, "/%s", fn)) - continue; -@@ -719,11 +720,11 @@ static void _find_controllers(struct context *ctx, struct nvme_map *map) - continue; - - path->gen.ops = &nvme_path_ops; -- path->udev = udev; -+ path->udev = steal_ptr(udev); - path->seen = true; - path->map = map; - path->ctl = udev_device_get_parent_with_subsystem_devtype -- (udev, "nvme", NULL); -+ (path->udev, "nvme", NULL); - if (path->ctl == NULL) { - condlog(1, "%s: %s: failed to get controller for %s", - __func__, THIS, fn); -@@ -744,7 +745,7 @@ static void _find_controllers(struct context *ctx, struct nvme_map *map) - } - vector_set_slot(&map->pgvec, &path->pg); - condlog(3, "%s: %s: new path %s added to %s", -- __func__, THIS, udev_device_get_sysname(udev), -+ __func__, THIS, udev_device_get_sysname(path->udev), - udev_device_get_sysname(map->udev)); - } - pthread_cleanup_pop(1); diff --git a/0022-libmultipath-add-condition-for-enqueueing-path-to-io.patch b/0022-libmultipath-add-condition-for-enqueueing-path-to-io.patch deleted file mode 100644 index cf8d80a..0000000 --- a/0022-libmultipath-add-condition-for-enqueueing-path-to-io.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chenrenhui -Date: Fri, 10 Jan 2025 14:38:16 +0800 -Subject: [PATCH] libmultipath: add condition for enqueueing path to io error - check - -In function io_err_stat_handle_pathfail(), path->io_err_dis_reinstate_time -is set to 0 to enqueue path to io error check as soon as possible. But -multipathd can not do it within marginal_path_err_recheck_gap_time seconds -after power-on, because curr_time is less than -marginal_path_err_recheck_gap_time. - -To handle the early marginal path, we can enqueue path when -io_err_dis_reinstate_time is 0. - -Signed-off-by: chenrenhui -Reviewed-by: Benjamin Marzinski -Reviewed-by: Martin Wilck - -> - -(cherry picked from commit a1e3cf2d42cc4bab10753e466c8adb7efa83c99e) -Signed-off-by: Benjamin Marzinski ---- - libmultipath/io_err_stat.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c -index 4996c0b0..879c310a 100644 ---- a/libmultipath/io_err_stat.c -+++ b/libmultipath/io_err_stat.c -@@ -367,7 +367,8 @@ int need_io_err_check(struct path *pp) - return 1; - get_monotonic_time(&curr_time); - if ((curr_time.tv_sec - pp->io_err_dis_reinstate_time) > -- pp->mpp->marginal_path_err_recheck_gap_time) { -+ pp->mpp->marginal_path_err_recheck_gap_time || -+ pp->io_err_dis_reinstate_time == 0) { - io_err_stat_log(4, "%s: reschedule checking after %d seconds", - pp->dev, - pp->mpp->marginal_path_err_recheck_gap_time); diff --git a/0023-Additional-NEWS.md-updates-for-0.10.1.patch b/0023-Additional-NEWS.md-updates-for-0.10.1.patch deleted file mode 100644 index 1093bd0..0000000 --- a/0023-Additional-NEWS.md-updates-for-0.10.1.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 17 Jan 2025 22:38:26 +0100 -Subject: [PATCH] Additional NEWS.md updates for 0.10.1 - -Signed-off-by: Benjamin Marzinski ---- - .github/actions/spelling/expect.txt | 4 ++-- - NEWS.md | 8 ++++++++ - 2 files changed, 10 insertions(+), 2 deletions(-) - -diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt -index 934f582e..000d5ebb 100644 ---- a/.github/actions/spelling/expect.txt -+++ b/.github/actions/spelling/expect.txt -@@ -184,7 +184,6 @@ sas - sbp - scsi - sda --sdc - setmarginal - setprkey - setprstatus -@@ -205,11 +204,11 @@ suse - svg - switchgroup - sys -+SYSDIR - sysfs - sysinit - tcp - terabytes --SYSDIR - TESTDEPS - testname - tgill -@@ -231,6 +230,7 @@ unsetprkey - unsetprstatus - unspec - usb -+USEC - userdata - userspace - usr -diff --git a/NEWS.md b/NEWS.md -index b740efb1..3c51553e 100644 ---- a/NEWS.md -+++ b/NEWS.md -@@ -22,6 +22,14 @@ bug fixes from 0.11.0, and some CI-related fixes. - * Fixed the problem that, if there were multiple maps with deferred failback - (`failback` value > 0 in `multipath.conf`), some maps might fail back later - than configured. The problem existed since 0.9.6. -+* Removed a warning message that multipathd would print if systemd's -+ `WATCHDOG_USEC` environment variable had the value "0", which means that the -+ watchdog is simply disabled. This (minor) problem existed since 0.4.9. -+* Fixed a memory leak in the nvme foreign library. The bug existed since -+ 0.7.8. -+* Fixed a problem in the marginal path detection algorithm that could cause -+ the io error check for a recently failed path to be delayed. This bug -+ existed since 0.7.4. - - ## multipath-tools 0.10.0, 2024/08 - diff --git a/0024-libmultipath-fix-handling-of-pp-pgindex.patch b/0024-libmultipath-fix-handling-of-pp-pgindex.patch deleted file mode 100644 index a9da346..0000000 --- a/0024-libmultipath-fix-handling-of-pp-pgindex.patch +++ /dev/null @@ -1,138 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Mon, 25 Nov 2024 13:11:07 +0100 -Subject: [PATCH] libmultipath: fix handling of pp->pgindex - -pp->pgindex is set in disassemble_map() when a map is parsed. -There are various possiblities for this index to become invalid. -pp->pgindex is only used in enable_group() and followover_should_fallback(), -and both callers take no action if it is 0, which is the right -thing to do if we don't know the path's pathgroup. - -Make sure pp->pgindex is reset to 0 in various places: -- when it's orphaned, -- before (re)grouping paths, -- when we detect a bad mpp assignment in update_pathvec_from_dm(). -- when a pathgroup is deleted in update_pathvec_from_dm(). In this - case, pgindex needs to be invalidated for all paths in all pathgroups - after the one that was deleted. - -The hunk in group_paths is mostly redundant with the hunk in free_pgvec(), but -because we're looping over pg->paths in the former and over pg->pgp in -the latter, I think it's better too play safe. - -Fixes: 99db1bd ("[multipathd] re-enable disabled PG when at least one path is up") -Fixes: https://github.com/opensvc/multipath-tools/issues/105 -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -(cherry picked from commit cd912cffa2797a18c47426c816afa8eb2eae5b22) -(cherry picked from commit 714c20bebba6911255a527d937e7a62764ffe338) -Signed-off-by: Benjamin Marzinski ---- - libmultipath/pgpolicies.c | 6 ++++++ - libmultipath/structs.c | 12 +++++++++++- - libmultipath/structs_vec.c | 15 +++++++++++++++ - 3 files changed, 32 insertions(+), 1 deletion(-) - -diff --git a/libmultipath/pgpolicies.c b/libmultipath/pgpolicies.c -index edc3c611..23ef2bdc 100644 ---- a/libmultipath/pgpolicies.c -+++ b/libmultipath/pgpolicies.c -@@ -127,6 +127,8 @@ fail: - int group_paths(struct multipath *mp, int marginal_pathgroups) - { - vector normal, marginal; -+ struct path *pp; -+ int i; - - if (!mp->pg) - mp->pg = vector_alloc(); -@@ -138,6 +140,10 @@ int group_paths(struct multipath *mp, int marginal_pathgroups) - if (!mp->pgpolicyfn) - goto fail; - -+ /* Reset pgindex, we're going to invalidate it */ -+ vector_foreach_slot(mp->paths, pp, i) -+ pp->pgindex = 0; -+ - if (!marginal_pathgroups || - split_marginal_paths(mp->paths, &normal, &marginal) != 0) { - if (mp->pgpolicyfn(mp, mp->paths) != 0) -diff --git a/libmultipath/structs.c b/libmultipath/structs.c -index 61c8f32c..48517252 100644 ---- a/libmultipath/structs.c -+++ b/libmultipath/structs.c -@@ -239,8 +239,18 @@ free_pgvec (vector pgvec, enum free_path_mode free_paths) - if (!pgvec) - return; - -- vector_foreach_slot(pgvec, pgp, i) -+ vector_foreach_slot(pgvec, pgp, i) { -+ -+ /* paths are going to be re-grouped, reset pgindex */ -+ if (free_paths != FREE_PATHS) { -+ struct path *pp; -+ int j; -+ -+ vector_foreach_slot(pgp->paths, pp, j) -+ pp->pgindex = 0; -+ } - free_pathgroup(pgp, free_paths); -+ } - - vector_free(pgvec); - } -diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c -index 5df495b3..9dc5a5ca 100644 ---- a/libmultipath/structs_vec.c -+++ b/libmultipath/structs_vec.c -@@ -108,6 +108,7 @@ static bool update_pathvec_from_dm(vector pathvec, struct multipath *mpp, - struct config *conf; - bool mpp_has_wwid; - bool must_reload = false; -+ bool pg_deleted = false; - - if (!mpp->pg) - return false; -@@ -125,6 +126,10 @@ static bool update_pathvec_from_dm(vector pathvec, struct multipath *mpp, - - vector_foreach_slot(pgp->paths, pp, j) { - -+ /* A pathgroup has been deleted before. Invalidate pgindex */ -+ if (pg_deleted) -+ pp->pgindex = 0; -+ - if (pp->mpp && pp->mpp != mpp) { - condlog(0, "BUG: %s: found path %s which is already in %s", - mpp->alias, pp->dev, pp->mpp->alias); -@@ -139,6 +144,13 @@ static bool update_pathvec_from_dm(vector pathvec, struct multipath *mpp, - must_reload = true; - dm_fail_path(mpp->alias, pp->dev_t); - vector_del_slot(pgp->paths, j--); -+ /* -+ * pp->pgindex has been set in disassemble_map(), -+ * which has probably been called just before for -+ * mpp. So he pgindex relates to mpp and may be -+ * wrong for pp->mpp. Invalidate it. -+ */ -+ pp->pgindex = 0; - continue; - } - pp->mpp = mpp; -@@ -237,6 +249,8 @@ static bool update_pathvec_from_dm(vector pathvec, struct multipath *mpp, - vector_del_slot(mpp->pg, i--); - free_pathgroup(pgp, KEEP_PATHS); - must_reload = true; -+ /* Invalidate pgindex for all other pathgroups */ -+ pg_deleted = true; - } - mpp->need_reload = mpp->need_reload || must_reload; - return must_reload; -@@ -354,6 +368,7 @@ void orphan_path(struct path *pp, const char *reason) - { - condlog(3, "%s: orphan path, %s", pp->dev, reason); - pp->mpp = NULL; -+ pp->pgindex = 0; - uninitialize_path(pp); - } - diff --git a/0025-libmultipath-make-pgcmp-detect-if-map-is-missing-a-p.patch b/0025-libmultipath-make-pgcmp-detect-if-map-is-missing-a-p.patch deleted file mode 100644 index b2b9e48..0000000 --- a/0025-libmultipath-make-pgcmp-detect-if-map-is-missing-a-p.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Mon, 25 Nov 2024 15:18:15 +0100 -Subject: [PATCH] libmultipath: make pgcmp detect if map is missing a path - group - -The previous algorithm didn't detect the case case where cpgp -contained a path that was not contained in pgp. Fix this. - -Cherry-picked from d4b35f61cb75c6e9b289e56c98457fc04ce4835e -Fixes: 90773ba ("libmultipath: resolve hash collisions in pgcmp()") -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - libmultipath/configure.c | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index a7257981..e86c1fd5 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -426,6 +426,11 @@ compute_pgid(struct pathgroup * pgp) - pgp->id ^= (long)pp; - } - -+static void cleanup_bitfield(struct bitfield **p) -+{ -+ free(*p); -+} -+ - static int - pgcmp (struct multipath * mpp, struct multipath * cmpp) - { -@@ -433,16 +438,25 @@ pgcmp (struct multipath * mpp, struct multipath * cmpp) - struct pathgroup * pgp; - struct pathgroup * cpgp; - int r = 0; -+ struct bitfield *bf __attribute__((cleanup(cleanup_bitfield))) = NULL; - - if (!mpp) - return 0; - -+ if (VECTOR_SIZE(mpp->pg) != VECTOR_SIZE(cmpp->pg)) -+ return 1; -+ -+ bf = alloc_bitfield(VECTOR_SIZE(cmpp->pg)); -+ if (!bf) -+ return 1; -+ - vector_foreach_slot (mpp->pg, pgp, i) { - compute_pgid(pgp); - - vector_foreach_slot (cmpp->pg, cpgp, j) { - if (pgp->id == cpgp->id && - !pathcmp(pgp, cpgp)) { -+ set_bit_in_bitfield(j, bf); - r = 0; - break; - } -@@ -451,6 +465,10 @@ pgcmp (struct multipath * mpp, struct multipath * cmpp) - if (r) - return r; - } -+ vector_foreach_slot (cmpp->pg, cpgp, j) { -+ if (!is_bit_set_in_bitfield(j, bf)) -+ return 1; -+ } - return r; - } - diff --git a/0026-libmultipath-trigger-uevents-upon-map-creation-in-do.patch b/0026-libmultipath-trigger-uevents-upon-map-creation-in-do.patch deleted file mode 100644 index bd3a7a4..0000000 --- a/0026-libmultipath-trigger-uevents-upon-map-creation-in-do.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Tue, 26 Nov 2024 22:37:20 +0100 -Subject: [PATCH] libmultipath: trigger uevents upon map creation in domap() - -If map creation succeeds, previously not multipathed devices are -now multipathed. udev may not have noticed this yet, thus trigger -path uevents to make it aware of the situation. Likewise, if -creating a map fails, the paths in question were likely considered -multipath members by udev, too. They will now be marked as failed, -so trigger an event in this situation as well. - -Fixes: https://github.com/opensvc/multipath-tools/issues/103 -Suggested-by: Benjamin Marzinski -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -(cherry picked from commit 98b3a7bd9ed2a89f068fe40c253843cf78261905) -Signed-off-by: Benjamin Marzinski ---- - libmultipath/configure.c | 11 ++++------- - libmultipath/devmapper.c | 9 +++------ - 2 files changed, 7 insertions(+), 13 deletions(-) - -diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index e86c1fd5..d9fac384 100644 ---- a/libmultipath/configure.c -+++ b/libmultipath/configure.c -@@ -581,8 +581,6 @@ trigger_paths_udev_change(struct multipath *mpp, bool is_mpath) - vector_foreach_slot(pgp->paths, pp, j) - trigger_path_udev_change(pp, is_mpath); - } -- -- mpp->needs_paths_uevent = 0; - } - - static int sysfs_set_max_sectors_kb(struct multipath *mpp) -@@ -954,10 +952,10 @@ int domap(struct multipath *mpp, char *params, int is_daemon) - * succeeded - */ - mpp->force_udev_reload = 0; -- if (mpp->action == ACT_CREATE && -- (remember_wwid(mpp->wwid) == 1 || -- mpp->needs_paths_uevent)) -+ if (mpp->action == ACT_CREATE) { -+ remember_wwid(mpp->wwid); - trigger_paths_udev_change(mpp, true); -+ } - if (!is_daemon) { - /* multipath client mode */ - dm_switchgroup(mpp->alias, mpp->bestpg); -@@ -982,8 +980,7 @@ int domap(struct multipath *mpp, char *params, int is_daemon) - } - dm_setgeometry(mpp); - return DOMAP_OK; -- } else if (r == DOMAP_FAIL && mpp->action == ACT_CREATE && -- mpp->needs_paths_uevent) -+ } else if (r == DOMAP_FAIL && mpp->action == ACT_CREATE) - trigger_paths_udev_change(mpp, false); - - return DOMAP_FAIL; -diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c -index fe5637b3..a0070c56 100644 ---- a/libmultipath/devmapper.c -+++ b/libmultipath/devmapper.c -@@ -536,7 +536,7 @@ static uint16_t build_udev_flags(const struct multipath *mpp, int reload) - MPATH_UDEV_RELOAD_FLAG : 0); - } - --int dm_addmap_create (struct multipath *mpp, char * params) -+int dm_addmap_create (struct multipath *mpp, char *params) - { - int ro; - uint16_t udev_flags = build_udev_flags(mpp, 0); -@@ -546,9 +546,7 @@ int dm_addmap_create (struct multipath *mpp, char * params) - - if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, mpp, params, ro, - udev_flags)) { -- if (unmark_failed_wwid(mpp->wwid) == -- WWID_FAILED_CHANGED) -- mpp->needs_paths_uevent = 1; -+ unmark_failed_wwid(mpp->wwid); - return 1; - } - /* -@@ -566,8 +564,7 @@ int dm_addmap_create (struct multipath *mpp, char * params) - break; - } - } -- if (mark_failed_wwid(mpp->wwid) == WWID_FAILED_CHANGED) -- mpp->needs_paths_uevent = 1; -+ mark_failed_wwid(mpp->wwid); - return 0; - } - diff --git a/0027-multipathd-trigger-uevents-upon-map-removal-in-coale.patch b/0027-multipathd-trigger-uevents-upon-map-removal-in-coale.patch deleted file mode 100644 index f43ca0c..0000000 --- a/0027-multipathd-trigger-uevents-upon-map-removal-in-coale.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Wed, 27 Nov 2024 20:39:50 +0100 -Subject: [PATCH] multipathd: trigger uevents upon map removal in - coalesce_maps() - -... if a map has been flushed. In this case, we know that the -the paths haven't been multipathed by coalesce_paths() because of the current -configuration (failure to create the map can't be the reason if the map -exists in coalesce_maps()). Make sure udev sees the paths which have -been released from the map as non-multipath. - -Note that this is the only case where maps are flushed where it is correct -to trigger paths uevents. In other cases, e.g. after a "remove map" CLI -command, the configuration is unchanged and if we triggered an uevent, -the map would be re-created by multipathd when the uevent arrived. - -Signed-off-by: Martin Wilck -Reviewed-by: Benjamin Marzinski -(cherry picked from commit ad3ea472b587c0c20d2100331b5c66f8602f8414) -Signed-off-by: Benjamin Marzinski ---- - multipathd/main.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/multipathd/main.c b/multipathd/main.c -index 3fb623fd..4b089c0e 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -794,8 +794,10 @@ coalesce_maps(struct vectors *vecs, vector nmpv) - vector_del_slot(ompv, i); - i--; - } -- else -+ else { - condlog(2, "%s devmap removed", ompp->alias); -+ trigger_paths_udev_change(ompp, false); -+ } - } else if (reassign_maps) { - condlog(3, "%s: Reassign existing device-mapper" - " devices", ompp->alias); diff --git a/0028-libmultipath-Don-t-skip-set_path_max_sectors_kb.patch b/0028-libmultipath-Don-t-skip-set_path_max_sectors_kb.patch deleted file mode 100644 index 6c001f5..0000000 --- a/0028-libmultipath-Don-t-skip-set_path_max_sectors_kb.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Wed, 4 Dec 2024 22:56:36 -0500 -Subject: [PATCH] libmultipath: Don't skip set_path_max_sectors_kb() - -If a multipath device already has need_reload set when a path is -adopted, it won't call set_path_max_sectors_kb() because of -short-circuit evaluation. This isn't what's intended. - -Fixes: e5e20c7b ("libmultipath: set max_sectors_kb in adopt_paths()") -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck -(cherry picked from commit f5c0c4b25c5eaac87b78e6e0c8d52b0828c29893) ---- - libmultipath/structs_vec.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c -index 9dc5a5ca..683ab473 100644 ---- a/libmultipath/structs_vec.c -+++ b/libmultipath/structs_vec.c -@@ -349,8 +349,7 @@ int adopt_paths(vector pathvec, struct multipath *mpp, - */ - if (!current_mpp || - !mp_find_path_by_devt(current_mpp, pp->dev_t)) -- mpp->need_reload = mpp->need_reload || -- set_path_max_sectors_kb(pp, mpp->max_sectors_kb); -+ mpp->need_reload = set_path_max_sectors_kb(pp, mpp->max_sectors_kb) || mpp->need_reload; - } - - pp->mpp = mpp; diff --git a/0029-libmultipath-stop-static-analyzer-complaint-in-init_.patch b/0029-libmultipath-stop-static-analyzer-complaint-in-init_.patch deleted file mode 100644 index e293a0e..0000000 --- a/0029-libmultipath-stop-static-analyzer-complaint-in-init_.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Wed, 22 Jan 2025 22:16:42 -0500 -Subject: [PATCH] libmultipath: stop static analyzer complaint in init_foreign - -This change doesn't actually fix anything. The code was already safe. - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck -(cherry picked from commit 85ec51e7930b4cadfbc12718afa91ce3a4adf4b5) ---- - libmultipath/foreign.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/libmultipath/foreign.c b/libmultipath/foreign.c -index 28d1b115..af5b0ed3 100644 ---- a/libmultipath/foreign.c -+++ b/libmultipath/foreign.c -@@ -129,7 +129,7 @@ static void free_pre(void *arg) - static int _init_foreign(const char *enable) - { - char pathbuf[PATH_MAX]; -- struct dirent **di; -+ struct dirent **di = NULL; - struct scandir_result sr; - int r, i; - regex_t *enable_re = NULL; diff --git a/0030-libmultipath-be-lenient-in-allowing-the-alua-based-p.patch b/0030-libmultipath-be-lenient-in-allowing-the-alua-based-p.patch deleted file mode 100644 index 06a1b0f..0000000 --- a/0030-libmultipath-be-lenient-in-allowing-the-alua-based-p.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Wed, 22 Jan 2025 22:16:43 -0500 -Subject: [PATCH] libmultipath: be lenient in allowing the alua-based - pgpolicies - -multipath wouldn't autodetect the GROUP_BY_PRIO path grouping policy or -allow the GROUP_BY_TPG policy if there was a path that didn't have its -prioritizer selected (for instance because multipathd was reconfigured -while it was offline). To avoid this, make verify_alua_prio() assume an -alua multipath device if all the paths with a prioritizer selected -(there must be at least one) use an alua-based prioritizer. - -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck -(cherry picked from commit b47a577998eaff203018a00b57ba5e3674645848) ---- - libmultipath/propsel.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c -index a3fce203..c09a0619 100644 ---- a/libmultipath/propsel.c -+++ b/libmultipath/propsel.c -@@ -255,14 +255,18 @@ verify_alua_prio(struct multipath *mp) - { - int i; - struct path *pp; -+ bool assume_alua = false; - - vector_foreach_slot(mp->paths, pp, i) { - const char *name = prio_name(&pp->prio); -+ if (!prio_selected(&pp->prio)) -+ continue; - if (strncmp(name, PRIO_ALUA, PRIO_NAME_LEN) && - strncmp(name, PRIO_SYSFS, PRIO_NAME_LEN)) - return false; -+ assume_alua = true; - } -- return true; -+ return assume_alua; - } - - int select_detect_pgpolicy(struct config *conf, struct multipath *mp) diff --git a/0031-Update-NEWS.md-for-0.10.2.patch b/0031-Update-NEWS.md-for-0.10.2.patch deleted file mode 100644 index fd31420..0000000 --- a/0031-Update-NEWS.md-for-0.10.2.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Fri, 24 Jan 2025 20:03:15 +0100 -Subject: [PATCH] Update NEWS.md for 0.10.2 - -Signed-off-by: Benjamin Marzinski ---- - .github/actions/spelling/expect.txt | 2 ++ - NEWS.md | 23 ++++++++++++++++++++++- - 2 files changed, 24 insertions(+), 1 deletion(-) - -diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt -index 000d5ebb..4ac57510 100644 ---- a/.github/actions/spelling/expect.txt -+++ b/.github/actions/spelling/expect.txt -@@ -11,6 +11,7 @@ ata - autoconfig - autodetected - autoresize -+backported - barbie - BINDIR - blkid -@@ -122,6 +123,7 @@ Lun - lvm - lvmteam - Marzinski -+misdetection - mpath - mpathb - mpathpersist -diff --git a/NEWS.md b/NEWS.md -index 3c51553e..1b239ffa 100644 ---- a/NEWS.md -+++ b/NEWS.md -@@ -1,6 +1,27 @@ - # multipath-tools Release Notes - --## multipath-tools 0.10.1, 2024/11 -+## multipath-tools 0.10.2, 2025/02 -+ -+This release contains backported bug fixes from the stable-0.11.y branch. -+ -+### Bug fixes -+ -+* Fix multipathd crash because of invalid path group index value, for example -+ if an invalid path device was removed from a map. -+ Fixes [#105](https://github.com/opensvc/multipath-tools/issues/105). -+* Make sure maps are reloaded in the path checker loop after detecting an -+ inconsistent or wrong kernel state (e.g. missing or falsely mapped path -+ device). Wrongly mapped paths will be unmapped and released to the system. -+ Fixes another issue reported in -+ [#105](https://github.com/opensvc/multipath-tools/issues/105). -+* Fix the problem that `group_by_tpg` might be disabled if one or more -+ paths were offline during initial configuration. -+* Fix possible misdetection of changed pathgroups in a map. -+* Fix the problem that if a map was scheduled to be reloaded already, -+ `max_sectors_kb` might not be set on a path device that -+ was being added to a multipath map. This problem was introduced in 0.9.9. -+ -+## multipath-tools 0.10.1, 2025/01 - - This is the first bug fix release on the `stable-0.10.y` branch. It contains - bug fixes from 0.11.0, and some CI-related fixes. diff --git a/0032-GitHub-Workflows-fix-abi-stable.yaml-for-pull-reques.patch b/0032-GitHub-Workflows-fix-abi-stable.yaml-for-pull-reques.patch deleted file mode 100644 index 3ddab39..0000000 --- a/0032-GitHub-Workflows-fix-abi-stable.yaml-for-pull-reques.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Sat, 25 Jan 2025 00:49:19 +0100 -Subject: [PATCH] GitHub Workflows: fix abi-stable.yaml for pull request - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - .github/workflows/abi-stable.yaml | 16 ++++++++++++---- - 1 file changed, 12 insertions(+), 4 deletions(-) - -diff --git a/.github/workflows/abi-stable.yaml b/.github/workflows/abi-stable.yaml -index a6746f23..472914ce 100644 ---- a/.github/workflows/abi-stable.yaml -+++ b/.github/workflows/abi-stable.yaml -@@ -15,12 +15,16 @@ on: - - jobs: - reference-abi: -- runs-on: ubuntu-20.04 -+ runs-on: ubuntu-22.04 - steps: - - name: get parent tag - run: > - echo ${{ github.ref }} | - sed -E 's,refs/heads/stable-([0-9]\.[0-9]*)\.y,PARENT_TAG=\1.0,' >> $GITHUB_ENV -+ if: ${{ github.event_name == 'push' }} -+ - name: get parent tag -+ run: echo PARENT_TAG=${{ github.base_ref }} >> $GITHUB_ENV -+ if: ${{ github.event_name == 'pull_request' }} - - name: assert parent tag - run: /bin/false - if: ${{ env.PARENT_TAG == '' }} -@@ -45,20 +49,24 @@ jobs: - path: abi - - check-abi: -- runs-on: ubuntu-20.04 -+ runs-on: ubuntu-22.04 - needs: reference-abi - steps: - - name: get parent tag - run: > - echo ${{ github.ref }} | - sed -E 's,refs/heads/stable-([0-9]\.[0-9]*)\.y,PARENT_TAG=\1.0,' >> $GITHUB_ENV -+ if: ${{ github.event_name == 'push' }} -+ - name: get parent tag -+ run: echo PARENT_TAG=${{ github.base_ref }} >> $GITHUB_ENV -+ if: ${{ github.event_name == 'pull_request' }} - - name: assert parent tag - run: /bin/false - if: ${{ env.PARENT_TAG == '' }} -- - name: checkout ${{ env.PARENT_TAG }} -+ - name: checkout ${{ github.base_ref }} - uses: actions/checkout@v4 - with: -- ref: ${{ env.PARENT_TAG }} -+ ref: ${{ github.base_ref }} - - name: download ABI for ${{ env.PARENT_TAG }} - id: download_abi - uses: actions/download-artifact@v4 diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 8e469ab..2de9457 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath -Version: 0.10.0 -Release: 5%{?dist} +Version: 0.11.1 +Release: 1%{?dist} Summary: Tools to manage multipath devices using device-mapper # readline uses GPL-3.0-only License: GPL-2.0-only AND GPL-3.0-only @@ -8,54 +8,26 @@ URL: http://christophe.varoqui.free.fr/ # The source for this package was pulled from upstream's git repo. Use the # following command to generate the tarball -# curl -L https://github.com/opensvc/multipath-tools/archive/0.10.0.tar.gz -o multipath-tools-0.10.0.tgz -Source0: multipath-tools-0.10.0.tgz +# curl -L https://github.com/opensvc/multipath-tools/archive/0.11.1.tar.gz -o multipath-tools-0.11.1.tgz +Source0: multipath-tools-0.11.1.tgz Source1: multipath.conf -Patch0001: 0001-GitHub-workflows-use-upload-download-artifact-v4.patch -Patch0002: 0002-GitHub-workflows-update-dawidd6-action-download-arti.patch -Patch0003: 0003-Github-workflows-native.yml-use-mosteo-actions-docke.patch -Patch0004: 0004-GitHub-workflows-native.yml-use-extra-job-for-clang.patch -Patch0005: 0005-GitHub-workflows-native.yaml-make-test-and-archive-s.patch -Patch0006: 0006-GitHub-workflows-enable-unit-tests-for-stable-branch.patch -Patch0007: 0007-GitHub-Workflows-add-abi-check-for-stable-branches.patch -Patch0008: 0008-libmultipath-dm_get_maps-don-t-bail-out-for-single-m.patch -Patch0009: 0009-11-dm-mpath.rules.in-import-DM_COLDPLUG_SUSPENDED-on.patch -Patch0010: 0010-11-dm-mpath.rules.in-handle-inactive-suspended-devic.patch -Patch0011: 0011-11-dm-mpath.rules.in-clarify-DM_ACTIVATION-logic.patch -Patch0012: 0012-11-dm-mpath-rules.in-skip-one-.DM_NOSCAN-check.patch -Patch0013: 0013-11-dm-mpath.rules.in-set-.DM_NOSCAN-if-MPATH_UNCHANG.patch -Patch0014: 0014-libmultipath-don-t-set-dev_loss_tmo-to-0-for-NO_PATH.patch -Patch0015: 0015-multipathd-fix-deferred_failback_tick-for-reload-rem.patch -Patch0016: 0016-multipathd-fix-an-unsigned-int-ovwerflow.patch -Patch0017: 0017-libmpathutil-avoid-Wcast-function-type-mismatch-erro.patch -Patch0018: 0018-Update-NEWS.md-for-0.10.1.patch -Patch0019: 0019-libmultipath-don-t-print-error-message-if-WATCHDOG_U.patch -Patch0020: 0020-libmultipath-reduce-log-level-of-map-X-has-multiple-.patch -Patch0021: 0021-libmultipath-foreign-fix-memory-leak-in-nvme-foreign.patch -Patch0022: 0022-libmultipath-add-condition-for-enqueueing-path-to-io.patch -Patch0023: 0023-Additional-NEWS.md-updates-for-0.10.1.patch -Patch0024: 0024-libmultipath-fix-handling-of-pp-pgindex.patch -Patch0025: 0025-libmultipath-make-pgcmp-detect-if-map-is-missing-a-p.patch -Patch0026: 0026-libmultipath-trigger-uevents-upon-map-creation-in-do.patch -Patch0027: 0027-multipathd-trigger-uevents-upon-map-removal-in-coale.patch -Patch0028: 0028-libmultipath-Don-t-skip-set_path_max_sectors_kb.patch -Patch0029: 0029-libmultipath-stop-static-analyzer-complaint-in-init_.patch -Patch0030: 0030-libmultipath-be-lenient-in-allowing-the-alua-based-p.patch -Patch0031: 0031-Update-NEWS.md-for-0.10.2.patch -Patch0032: 0032-GitHub-Workflows-fix-abi-stable.yaml-for-pull-reques.patch -Patch0033: 0033-RH-fixup-udev-rules-for-redhat.patch -Patch0034: 0034-RH-Remove-the-property-blacklist-exception-builtin.patch -Patch0035: 0035-RH-don-t-start-without-a-config-file.patch -Patch0036: 0036-RH-Fix-nvme-function-missing-argument.patch -Patch0037: 0037-RH-use-rpm-optflags-if-present.patch -Patch0038: 0038-RH-add-mpathconf.patch -Patch0039: 0039-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch -Patch0040: 0040-RH-reset-default-find_mutipaths-value-to-off.patch -Patch0041: 0041-RH-attempt-to-get-ANA-info-via-sysfs-first.patch -Patch0042: 0042-RH-make-parse_vpd_pg83-match-scsi_id-output.patch -Patch0043: 0043-RH-add-scsi-device-handlers-to-modules-load.d.patch -Patch0044: 0044-RH-compile-with-libreadline-support.patch -Patch0045: 0045-RH-Add-mpathcleanup.patch +Patch0001: 0001-multipathd-trigger-uevents-for-blacklisted-paths-in-.patch +Patch0002: 0002-multipath-tools-fix-compilation-with-latest-userspac.patch +Patch0003: 0003-libmultipath-include-urcu.h-before-urcu-atomic.h.patch +Patch0004: 0004-libmpathutils-uxsock.c-Include-string.h-for-memcpy.patch +Patch0005: 0005-RH-fixup-udev-rules-for-redhat.patch +Patch0006: 0006-RH-Remove-the-property-blacklist-exception-builtin.patch +Patch0007: 0007-RH-don-t-start-without-a-config-file.patch +Patch0008: 0008-RH-Fix-nvme-function-missing-argument.patch +Patch0009: 0009-RH-use-rpm-optflags-if-present.patch +Patch0010: 0010-RH-add-mpathconf.patch +Patch0011: 0011-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +Patch0012: 0012-RH-reset-default-find_mutipaths-value-to-off.patch +Patch0013: 0013-RH-attempt-to-get-ANA-info-via-sysfs-first.patch +Patch0014: 0014-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +Patch0015: 0015-RH-add-scsi-device-handlers-to-modules-load.d.patch +Patch0016: 0016-RH-compile-with-libreadline-support.patch +Patch0017: 0017-RH-Add-mpathcleanup.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -143,7 +115,7 @@ This package contains the files needed to develop applications that use device-mapper-multipath's libdmmp C API library %prep -%autosetup -n multipath-tools-0.10.0 -p1 +%autosetup -n multipath-tools-0.11.1 -p1 cp %{SOURCE1} . %build @@ -265,6 +237,13 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Thu Feb 27 2025 Benjamin Marzinski - 0.11.1-1 +- Update source to upstream staging branch for 0.11.1 plus additional + stable branch patches. + * Previous patches 0001-0032 are included in the tarball +- Rename redhat patches + * Previous patches 0033-0045 are now patches 0005-0017 + * Sat Feb 1 2025 Benjamin Marzinski - 0.10.0-5 - Update source to upstream staging branch for 0.10.y (will be 0.10.2 when merged). diff --git a/sources b/sources index da06e16..5eea94e 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (multipath-tools-0.10.0.tgz) = 8f545609fa20df7547428f2929571dc0df87c17d9f61f11aad3559446c2e94755e18b1c4b3780b3de92ec2cbc450939ca15a9d6c95551eee4084064d83874b2d +SHA512 (multipath-tools-0.11.1.tgz) = ac6bacd725bc831a140b75a72c81296eb1ed4080fb6350caf6178914d1bdce743705f3bd4e31f318068f6272dc98e12d63ee38228a3521a3d1c7bc8eb30812f9 SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942 From 9f48ebd2e22ad64a101f59f06a9e8306f6e3b317 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Wed, 23 Jul 2025 19:12:54 +0000 Subject: [PATCH 27/29] Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild --- device-mapper-multipath.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 2de9457..232daba 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.11.1 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Tools to manage multipath devices using device-mapper # readline uses GPL-3.0-only License: GPL-2.0-only AND GPL-3.0-only @@ -237,6 +237,9 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Wed Jul 23 2025 Fedora Release Engineering - 0.11.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild + * Thu Feb 27 2025 Benjamin Marzinski - 0.11.1-1 - Update source to upstream staging branch for 0.11.1 plus additional stable branch patches. From 3c9f48504bb89ec2a2c84cfffbeaf2f2811fcefd Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Tue, 4 Nov 2025 18:02:43 -0500 Subject: [PATCH 28/29] device-mapper-multipath-0.13.0-1 Update source to upstream release 0.13.0 * Previous patches 0001-0004 are included in the tarball Install /lib/systemd/system/multipathd-queueing.service Rename redhat patches * Previous patches 0005-0017 are now patches 0001-0013 --- .gitignore | 1 + ... 0001-RH-fixup-udev-rules-for-redhat.patch | 4 +- ...er-uevents-for-blacklisted-paths-in-.patch | 101 ------------------ ...property-blacklist-exception-builtin.patch | 14 +-- ...fix-compilation-with-latest-userspac.patch | 63 ----------- ...RH-don-t-start-without-a-config-file.patch | 24 ++--- ...-include-urcu.h-before-urcu-atomic.h.patch | 40 ------- ...H-Fix-nvme-function-missing-argument.patch | 6 +- ...uxsock.c-Include-string.h-for-memcpy.patch | 29 ----- ... 0005-RH-use-rpm-optflags-if-present.patch | 12 ++- ...hconf.patch => 0006-RH-add-mpathconf.patch | 8 +- ...om-kernel-cmdline-mpath.wwids-with-A.patch | 16 +-- ...-default-find_mutipaths-value-to-off.patch | 8 +- ...empt-to-get-ANA-info-via-sysfs-first.patch | 14 +-- ...-parse_vpd_pg83-match-scsi_id-output.patch | 8 +- ...si-device-handlers-to-modules-load.d.patch | 4 +- ...-RH-compile-with-libreadline-support.patch | 4 +- ...up.patch => 0013-RH-Add-mpathcleanup.patch | 2 +- device-mapper-multipath.spec | 48 +++++---- sources | 2 +- 20 files changed, 91 insertions(+), 317 deletions(-) rename 0005-RH-fixup-udev-rules-for-redhat.patch => 0001-RH-fixup-udev-rules-for-redhat.patch (96%) delete mode 100644 0001-multipathd-trigger-uevents-for-blacklisted-paths-in-.patch rename 0006-RH-Remove-the-property-blacklist-exception-builtin.patch => 0002-RH-Remove-the-property-blacklist-exception-builtin.patch (91%) delete mode 100644 0002-multipath-tools-fix-compilation-with-latest-userspac.patch rename 0007-RH-don-t-start-without-a-config-file.patch => 0003-RH-don-t-start-without-a-config-file.patch (88%) delete mode 100644 0003-libmultipath-include-urcu.h-before-urcu-atomic.h.patch rename 0008-RH-Fix-nvme-function-missing-argument.patch => 0004-RH-Fix-nvme-function-missing-argument.patch (84%) delete mode 100644 0004-libmpathutils-uxsock.c-Include-string.h-for-memcpy.patch rename 0009-RH-use-rpm-optflags-if-present.patch => 0005-RH-use-rpm-optflags-if-present.patch (85%) rename 0010-RH-add-mpathconf.patch => 0006-RH-add-mpathconf.patch (99%) rename 0011-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch => 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch (92%) rename 0012-RH-reset-default-find_mutipaths-value-to-off.patch => 0008-RH-reset-default-find_mutipaths-value-to-off.patch (87%) rename 0013-RH-attempt-to-get-ANA-info-via-sysfs-first.patch => 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch (86%) rename 0014-RH-make-parse_vpd_pg83-match-scsi_id-output.patch => 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch (91%) rename 0015-RH-add-scsi-device-handlers-to-modules-load.d.patch => 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch (89%) rename 0016-RH-compile-with-libreadline-support.patch => 0012-RH-compile-with-libreadline-support.patch (89%) rename 0017-RH-Add-mpathcleanup.patch => 0013-RH-Add-mpathcleanup.patch (98%) diff --git a/.gitignore b/.gitignore index 8cd21df..c297b30 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,4 @@ multipath-tools-091027.tar.gz /multipath-tools-0.9.9.tgz /multipath-tools-0.10.0.tgz /multipath-tools-0.11.1.tgz +/multipath-tools-0.13.0.tgz diff --git a/0005-RH-fixup-udev-rules-for-redhat.patch b/0001-RH-fixup-udev-rules-for-redhat.patch similarity index 96% rename from 0005-RH-fixup-udev-rules-for-redhat.patch rename to 0001-RH-fixup-udev-rules-for-redhat.patch index 0135f49..ed5b7e9 100644 --- a/0005-RH-fixup-udev-rules-for-redhat.patch +++ b/0001-RH-fixup-udev-rules-for-redhat.patch @@ -1,4 +1,4 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From 64a07df23affd21842fdc604887276e62e5b41de Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Thu, 13 Apr 2017 07:22:23 -0500 Subject: [PATCH] RH: fixup udev rules for redhat @@ -15,7 +15,7 @@ Signed-off-by: Benjamin Marzinski 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile.inc b/Makefile.inc -index 65f6efc8..c225a1ed 100644 +index 9e3dc466..ead89030 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -34,7 +34,7 @@ endif diff --git a/0001-multipathd-trigger-uevents-for-blacklisted-paths-in-.patch b/0001-multipathd-trigger-uevents-for-blacklisted-paths-in-.patch deleted file mode 100644 index 72bcf69..0000000 --- a/0001-multipathd-trigger-uevents-for-blacklisted-paths-in-.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Thu, 23 Jan 2025 22:19:39 +0100 -Subject: [PATCH] multipathd: trigger uevents for blacklisted paths in - reconfigure - -If multipathd has already configured maps, and the user changes the -blacklist or other parameters that cause currently multipathed -devices to be skipped, and then runs "multipathd reconfigure" -or restarts multipathd, multipathd flushes the maps in question, -but doesn't trigger uevents for the now-blacklisted paths. - -This is because the blacklisted paths are removed from the discovered -maps internally when update_pathvec_from_dm() is called through -map_discovery() and update_multipath_table(); when later -trigger_paths_udev_change() is called from coalesce_maps(), the -map contains no paths for which an uevent could be triggered. - -The map_discovery() code flow is special, because we will call -coalesce_paths() afterwards anyway and reconstruct the mpvec. Unlike the -regular code flow, we don't want the maps to be "corrected" in this -case, because the maps discovered here aren't going to be reloaded. -We just want update_pathvec_from_dm() to populate the pathvec. - -Therefore add a new flag DI_DISCOVERY, which is only set when -update_multipath_table() is called from map_discovery(), and if -this flag is set, keep PATHINFO_SKIPPED paths in the map's table in -update_pathvec_from_dm(). Later on, the paths will still be visible -in the old mpp (ompp) in coalesce_maps(), and uevents will be -triggered for them to release them to systemd. - -We can't always do this for PATHINFO_SKIPPED, because in some cases -paths may be accepted in a map first and SKIPPED later (for example if -the WWID wasn't yet available at startup). Therefore the special -case for DI_DISCOVERY is necessary. - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - libmultipath/discovery.h | 2 ++ - libmultipath/structs_vec.c | 6 +++++- - multipathd/main.c | 2 +- - 3 files changed, 8 insertions(+), 2 deletions(-) - -diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h -index 7d42eae5..9824a8d3 100644 ---- a/libmultipath/discovery.h -+++ b/libmultipath/discovery.h -@@ -72,6 +72,7 @@ enum discovery_mode { - DI_BLACKLIST__, - DI_NOIO__, - DI_NOFALLBACK__, -+ DI_DISCOVERY__, - }; - - #define DI_SYSFS (1 << DI_SYSFS__) -@@ -82,6 +83,7 @@ enum discovery_mode { - #define DI_BLACKLIST (1 << DI_BLACKLIST__) - #define DI_NOIO (1 << DI_NOIO__) /* Avoid IO on the device */ - #define DI_NOFALLBACK (1 << DI_NOFALLBACK__) /* do not allow wwid fallback */ -+#define DI_DISCOVERY (1 << DI_DISCOVERY__) /* set only during map discovery */ - - #define DI_ALL (DI_SYSFS | DI_SERIAL | DI_CHECKER | DI_PRIO | \ - DI_WWID) -diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c -index 7a4e3eb0..5ccdaea0 100644 ---- a/libmultipath/structs_vec.c -+++ b/libmultipath/structs_vec.c -@@ -109,6 +109,9 @@ static bool update_pathvec_from_dm(vector pathvec, struct multipath *mpp, - bool mpp_has_wwid; - bool must_reload = false; - bool pg_deleted = false; -+ bool map_discovery = !!(pathinfo_flags & DI_DISCOVERY); -+ -+ pathinfo_flags &= ~DI_DISCOVERY; - - if (!mpp->pg) - return false; -@@ -195,7 +198,8 @@ static bool update_pathvec_from_dm(vector pathvec, struct multipath *mpp, - rc = pathinfo(pp, conf, - DI_SYSFS|DI_WWID|DI_BLACKLIST|DI_NOFALLBACK|pathinfo_flags); - pthread_cleanup_pop(1); -- if (rc != PATHINFO_OK) { -+ if (rc == PATHINFO_FAILED || -+ (rc == PATHINFO_SKIPPED && !map_discovery)) { - condlog(1, "%s: error %d in pathinfo, discarding path", - pp->dev, rc); - vector_del_slot(pgp->paths, j--); -diff --git a/multipathd/main.c b/multipathd/main.c -index 9ed27da0..fb3e44a8 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -1763,7 +1763,7 @@ map_discovery (struct vectors * vecs) - return 1; - - vector_foreach_slot (vecs->mpvec, mpp, i) -- if (update_multipath_table(mpp, vecs->pathvec, 0) != DMP_OK) { -+ if (update_multipath_table(mpp, vecs->pathvec, DI_DISCOVERY) != DMP_OK) { - remove_map(mpp, vecs->pathvec, vecs->mpvec); - i--; - } diff --git a/0006-RH-Remove-the-property-blacklist-exception-builtin.patch b/0002-RH-Remove-the-property-blacklist-exception-builtin.patch similarity index 91% rename from 0006-RH-Remove-the-property-blacklist-exception-builtin.patch rename to 0002-RH-Remove-the-property-blacklist-exception-builtin.patch index a74e6c2..b8e580a 100644 --- a/0006-RH-Remove-the-property-blacklist-exception-builtin.patch +++ b/0002-RH-Remove-the-property-blacklist-exception-builtin.patch @@ -1,4 +1,4 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From f7be16ac9fce97585a4552d49f3d3c54a93c9c17 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Wed, 2 Jul 2014 12:49:53 -0500 Subject: [PATCH] RH: Remove the property blacklist exception builtin @@ -42,10 +42,10 @@ index 17e1b54a..10d13e98 100644 udev_device_get_properties_list_entry(udev)) { diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in -index 4388baad..af9fbb96 100644 +index 3c9ae097..ba291e11 100644 --- a/multipath/multipath.conf.5.in +++ b/multipath/multipath.conf.5.in -@@ -1469,9 +1469,14 @@ keywords. Both are regular expressions. For a full description of these keywords +@@ -1470,9 +1470,14 @@ keywords. Both are regular expressions. For a full description of these keywords Regular expression for an udev property. All devices that have matching udev properties will be excluded/included. The handling of the \fIproperty\fR keyword is special, @@ -61,7 +61,7 @@ index 4388baad..af9fbb96 100644 . .RS .PP -@@ -1482,10 +1487,6 @@ Blacklisting by missing properties is only applied to devices which do have the +@@ -1483,10 +1488,6 @@ Blacklisting by missing properties is only applied to devices which do have the property specified by \fIuid_attribute\fR (e.g. \fIID_SERIAL\fR) set. Previously, it was applied to every device, possibly causing devices to be blacklisted because of temporary I/O error conditions. @@ -73,10 +73,10 @@ index 4388baad..af9fbb96 100644 .TP .B protocol diff --git a/tests/blacklist.c b/tests/blacklist.c -index ba8dfd07..693db3fa 100644 +index ab3da619..52ae03e0 100644 --- a/tests/blacklist.c +++ b/tests/blacklist.c -@@ -384,9 +384,8 @@ static void test_property_missing(void **state) +@@ -371,9 +371,8 @@ static void test_property_missing(void **state) { static struct udev_device udev = { "sdb", { "ID_FOO", "ID_BAZ", "ID_BAR", "ID_SERIAL", NULL } }; conf.blist_property = blist_property_wwn; @@ -87,7 +87,7 @@ index ba8dfd07..693db3fa 100644 assert_int_equal(filter_property(&conf, &udev, 3, "ID_BLAH"), MATCH_NOTHING); assert_int_equal(filter_property(&conf, &udev, 3, ""), -@@ -478,9 +477,7 @@ static void test_filter_path_missing1(void **state) +@@ -465,9 +464,7 @@ static void test_filter_path_missing1(void **state) conf.blist_device = blist_device_foo_bar; conf.blist_protocol = blist_protocol_fcp; conf.blist_wwid = blist_wwid_xyzzy; diff --git a/0002-multipath-tools-fix-compilation-with-latest-userspac.patch b/0002-multipath-tools-fix-compilation-with-latest-userspac.patch deleted file mode 100644 index 03d7d9d..0000000 --- a/0002-multipath-tools-fix-compilation-with-latest-userspac.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Mon, 3 Feb 2025 16:43:42 -0500 -Subject: [PATCH] multipath-tools: fix compilation with latest userspace-rcu - code - -starting with version 0.15, userspace-rcu can be compiled with -CONFIG_RCU_USE_ATOMIC_BUILTINS. If it is, then any programs using it -must be compiled with at least the C11 standard. See: -https://github.com/urcu/userspace-rcu/commit/89280d020bf064d1055c360fb9974f128051043f - -To deal with this, check if compiling with gnu99 fails, and if so, -switch to using gnu11. - -Based-on-patch-by: Yaakov Selkowitz -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck ---- - Makefile.inc | 2 +- - create-config.mk | 13 +++++++++++++ - 2 files changed, 14 insertions(+), 1 deletion(-) - -diff --git a/Makefile.inc b/Makefile.inc -index 729618bd..65f6efc8 100644 ---- a/Makefile.inc -+++ b/Makefile.inc -@@ -115,7 +115,7 @@ CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \ - -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(TGTDIR)$(configdir)\" \ - -DDEFAULT_CONFIGFILE=\"$(TGTDIR)$(configfile)\" -DSTATE_DIR=\"$(TGTDIR)$(statedir)\" \ - -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP --CFLAGS := -std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \ -+CFLAGS := -std=$(C_STD) $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \ - -fexceptions - BIN_CFLAGS := -fPIE -DPIE - LIB_CFLAGS := -fPIC -diff --git a/create-config.mk b/create-config.mk -index 8bd2c20c..ab163ed1 100644 ---- a/create-config.mk -+++ b/create-config.mk -@@ -157,6 +157,18 @@ FORTIFY_OPT := $(shell \ - echo "-D_FORTIFY_SOURCE=2"; \ - fi) - -+# Check is you can compile with the urcu.h header, using the C99 standard. -+# If urcu/config-.h defines CONFIG_RCU_USE_ATOMIC_BUILTINS, then anything -+# including urcu.h must be compiled with at least the C11 standard. See: -+# https://github.com/urcu/userspace-rcu/commit/89280d020bf064d1055c360fb9974f128051043f -+C_STD := $(shell \ -+ if printf '$(__HASH__)include \nint main(void) { return 0; }\n' | $(CC) -o /dev/null -c -xc --std=gnu99 - 2>/dev/null; \ -+ then \ -+ echo "gnu99"; \ -+ else \ -+ echo "gnu11"; \ -+ fi) -+ - STACKPROT := - - all: $(TOPDIR)/config.mk -@@ -182,3 +194,4 @@ $(TOPDIR)/config.mk: $(multipathdir)/autoconfig.h - @echo "W_MISSING_INITIALIZERS := $(call TEST_MISSING_INITIALIZERS)" >>$@ - @echo "W_URCU_TYPE_LIMITS := $(call TEST_URCU_TYPE_LIMITS)" >>$@ - @echo "ENABLE_LIBDMMP := $(ENABLE_LIBDMMP)" >>$@ -+ @echo "C_STD := $(C_STD)" >>$@ diff --git a/0007-RH-don-t-start-without-a-config-file.patch b/0003-RH-don-t-start-without-a-config-file.patch similarity index 88% rename from 0007-RH-don-t-start-without-a-config-file.patch rename to 0003-RH-don-t-start-without-a-config-file.patch index edbc647..05d4e7a 100644 --- a/0007-RH-don-t-start-without-a-config-file.patch +++ b/0003-RH-don-t-start-without-a-config-file.patch @@ -1,4 +1,4 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From 5613e07ce9cabf2fdc402f6f102cc54bd1059800 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Wed, 15 Oct 2014 10:39:30 -0500 Subject: [PATCH] RH: don't start without a config file @@ -18,7 +18,7 @@ Signed-off-by: Benjamin Marzinski multipath/multipath.rules.in | 1 + multipathd/multipathd.8.in | 2 ++ multipathd/multipathd.service.in | 1 + - multipathd/multipathd.socket | 1 + + multipathd/multipathd.socket.in | 1 + 7 files changed, 25 insertions(+) diff --git a/libmultipath/config.c b/libmultipath/config.c @@ -58,10 +58,10 @@ index 5b4ebf8c..2302eacc 100644 enum devtypes { DEV_NONE, diff --git a/multipath/main.c b/multipath/main.c -index 28e3a055..346acb61 100644 +index f2adcdeb..31012874 100644 --- a/multipath/main.c +++ b/multipath/main.c -@@ -843,11 +843,14 @@ main (int argc, char *argv[]) +@@ -834,11 +834,14 @@ main (int argc, char *argv[]) char *dev = NULL; struct config *conf; bool enable_foreign = false; @@ -76,7 +76,7 @@ index 28e3a055..346acb61 100644 if (init_config(DEFAULT_CONFIGFILE)) exit(RTVL_FAIL); if (atexit(uninit_config)) -@@ -1101,6 +1104,9 @@ main (int argc, char *argv[]) +@@ -1092,6 +1095,9 @@ main (int argc, char *argv[]) while ((r = configure(conf, cmd, dev_type, dev)) == RTVL_RETRY) condlog(3, "restart multipath configuration process"); @@ -99,7 +99,7 @@ index 2ac1972f..cc248231 100644 ENV{DEVTYPE}!="partition", GOTO="test_dev" IMPORT{parent}="DM_MULTIPATH_DEVICE_PATH" diff --git a/multipathd/multipathd.8.in b/multipathd/multipathd.8.in -index 7bc8806e..315884eb 100644 +index 8815e099..342e363e 100644 --- a/multipathd/multipathd.8.in +++ b/multipathd/multipathd.8.in @@ -49,6 +49,8 @@ map regains its maximum performance and redundancy. @@ -112,10 +112,10 @@ index 7bc8806e..315884eb 100644 . .\" ---------------------------------------------------------------------------- diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in -index b6a25b31..3d957733 100644 +index eb58943c..ab166435 100644 --- a/multipathd/multipathd.service.in +++ b/multipathd/multipathd.service.in -@@ -6,6 +6,7 @@ Wants=systemd-udevd-kernel.socket @MODPROBE_UNIT@ +@@ -6,6 +6,7 @@ Wants=systemd-udevd-kernel.socket multipathd-queueing.service @MODPROBE_UNIT@ After=systemd-udevd-kernel.socket @MODPROBE_UNIT@ After=multipathd.socket systemd-remount-fs.service Before=initrd-cleanup.service @@ -123,10 +123,10 @@ index b6a25b31..3d957733 100644 DefaultDependencies=no Conflicts=shutdown.target Conflicts=initrd-cleanup.service -diff --git a/multipathd/multipathd.socket b/multipathd/multipathd.socket -index 6a62f5fd..263b6b0c 100644 ---- a/multipathd/multipathd.socket -+++ b/multipathd/multipathd.socket +diff --git a/multipathd/multipathd.socket.in b/multipathd/multipathd.socket.in +index 11002fce..5ed24757 100644 +--- a/multipathd/multipathd.socket.in ++++ b/multipathd/multipathd.socket.in @@ -1,6 +1,7 @@ [Unit] Description=multipathd control socket diff --git a/0003-libmultipath-include-urcu.h-before-urcu-atomic.h.patch b/0003-libmultipath-include-urcu.h-before-urcu-atomic.h.patch deleted file mode 100644 index 8da3ce7..0000000 --- a/0003-libmultipath-include-urcu.h-before-urcu-atomic.h.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Tue, 11 Feb 2025 13:11:03 -0500 -Subject: [PATCH] libmultipath: include urcu.h before urcu/atomic.h - -urcu/atomic.h requires some header files included by urcu.h. Make sure -to include it first. - -Fixes: https://github.com/opensvc/multipath-tools/issues/112 -Signed-off-by: Benjamin Marzinski -Reviewed-by: Martin Wilck ---- - libmultipath/checkers/tur.c | 1 + - libmultipath/lock.h | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c -index e70a2e11..0010acf8 100644 ---- a/libmultipath/checkers/tur.c -+++ b/libmultipath/checkers/tur.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - - #include "checkers.h" -diff --git a/libmultipath/lock.h b/libmultipath/lock.h -index 38473a8c..5f323055 100644 ---- a/libmultipath/lock.h -+++ b/libmultipath/lock.h -@@ -2,6 +2,7 @@ - #define LOCK_H_INCLUDED - - #include -+#include - #include - #include - diff --git a/0008-RH-Fix-nvme-function-missing-argument.patch b/0004-RH-Fix-nvme-function-missing-argument.patch similarity index 84% rename from 0008-RH-Fix-nvme-function-missing-argument.patch rename to 0004-RH-Fix-nvme-function-missing-argument.patch index 74b7b53..33a8d5f 100644 --- a/0008-RH-Fix-nvme-function-missing-argument.patch +++ b/0004-RH-Fix-nvme-function-missing-argument.patch @@ -1,4 +1,4 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From 283b5dd645663a2cf16f2813581772d7a84db6ad Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Fri, 25 Jan 2019 14:54:56 -0600 Subject: [PATCH] RH: Fix nvme function missing argument @@ -12,10 +12,10 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmultipath/nvme/argconfig.h b/libmultipath/nvme/argconfig.h -index e6c54453..0c6c9439 100644 +index b3caa7be..f91504c9 100644 --- a/libmultipath/nvme/argconfig.h +++ b/libmultipath/nvme/argconfig.h -@@ -76,7 +76,7 @@ struct argconfig_commandline_options { +@@ -63,7 +63,7 @@ struct argconfig_commandline_options { extern "C" { #endif diff --git a/0004-libmpathutils-uxsock.c-Include-string.h-for-memcpy.patch b/0004-libmpathutils-uxsock.c-Include-string.h-for-memcpy.patch deleted file mode 100644 index 8fc3211..0000000 --- a/0004-libmpathutils-uxsock.c-Include-string.h-for-memcpy.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Khem Raj -Date: Mon, 17 Feb 2025 12:05:03 -0800 -Subject: [PATCH] libmpathutils/uxsock.c: Include string.h for memcpy - -Fixes -uxsock.c:72:2: error: call to undeclared library function 'memcpy' with type 'void *(void *, const void *, unsigned long)'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] - -Signed-off-by: Khem Raj -Cc: Benjamin Marzinski -Cc: Martin Wilck -Reviewed-by: Benjamin Marzinski -Signed-off-by: Benjamin Marzinski ---- - libmpathutil/uxsock.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/libmpathutil/uxsock.c b/libmpathutil/uxsock.c -index 2135476d..a474874e 100644 ---- a/libmpathutil/uxsock.c -+++ b/libmpathutil/uxsock.c -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - #include - #include - #include diff --git a/0009-RH-use-rpm-optflags-if-present.patch b/0005-RH-use-rpm-optflags-if-present.patch similarity index 85% rename from 0009-RH-use-rpm-optflags-if-present.patch rename to 0005-RH-use-rpm-optflags-if-present.patch index 1b96a3a..7a6f57f 100644 --- a/0009-RH-use-rpm-optflags-if-present.patch +++ b/0005-RH-use-rpm-optflags-if-present.patch @@ -1,4 +1,4 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From bf46f8029998498045bb055415ba3ff515c79eaa Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Wed, 19 Apr 2017 06:10:01 -0500 Subject: [PATCH] RH: use rpm optflags if present @@ -13,10 +13,10 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/Makefile.inc b/Makefile.inc -index c225a1ed..7774f1f4 100644 +index ead89030..03aee175 100644 --- a/Makefile.inc +++ b/Makefile.inc -@@ -99,28 +99,39 @@ SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo +@@ -102,17 +102,29 @@ SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo MODPROBE_UNIT := $(shell test "0$(SYSTEMD)" -lt 245 2>/dev/null || \ echo "modprobe@dm_multipath.service") @@ -50,8 +50,10 @@ index c225a1ed..7774f1f4 100644 -D_FILE_OFFSET_BITS=64 \ -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(TGTDIR)$(plugindir)\" \ -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(TGTDIR)$(configdir)\" \ - -DDEFAULT_CONFIGFILE=\"$(TGTDIR)$(configfile)\" -DSTATE_DIR=\"$(TGTDIR)$(statedir)\" \ - -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP +@@ -121,12 +133,11 @@ CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \ + -DABSTRACT_SOCKET=\"$(abstract_socket)\" -DPATHNAME_SOCKET=\"$(pathname_socket)\" \ + -DWSTRINGOP_TRUNCATION=$(if $(WSTRINGOP_TRUNCATION),1,0) \ + -MMD -MP -CFLAGS := -std=$(C_STD) $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \ - -fexceptions +CFLAGS := -std=$(C_STD) $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe diff --git a/0010-RH-add-mpathconf.patch b/0006-RH-add-mpathconf.patch similarity index 99% rename from 0010-RH-add-mpathconf.patch rename to 0006-RH-add-mpathconf.patch index c587841..46f1126 100644 --- a/0010-RH-add-mpathconf.patch +++ b/0006-RH-add-mpathconf.patch @@ -1,4 +1,4 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From 29e5c6d6e2177e73d1be2ed2af66c1007487bf60 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Thu, 16 Oct 2014 15:49:01 -0500 Subject: [PATCH] RH: add mpathconf @@ -23,10 +23,10 @@ Signed-off-by: Benjamin Marzinski create mode 100644 multipath/mpathconf.8 diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt -index 7843c380..ab5259cf 100644 +index a5856bcc..5c9113ba 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt -@@ -127,9 +127,11 @@ Marzinski +@@ -131,9 +131,11 @@ Marzinski misdetection mpath mpathb @@ -38,7 +38,7 @@ index 7843c380..ab5259cf 100644 multipathc multipathd multipathed -@@ -147,6 +149,7 @@ ontap +@@ -154,6 +156,7 @@ ontap OOM opensvc OPTFLAGS diff --git a/0011-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch b/0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch similarity index 92% rename from 0011-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch rename to 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch index 612d876..cef8b56 100644 --- a/0011-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +++ b/0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch @@ -1,4 +1,4 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From d6ad888bad3850bb0a342ebcdc9fd78773eb3b2a Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Fri, 17 Oct 2014 11:20:34 -0500 Subject: [PATCH] RH: add wwids from kernel cmdline mpath.wwids with -A @@ -20,10 +20,10 @@ Signed-off-by: Benjamin Marzinski 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/multipath/main.c b/multipath/main.c -index 346acb61..adc50d69 100644 +index 31012874..a667c2ee 100644 --- a/multipath/main.c +++ b/multipath/main.c -@@ -120,7 +120,7 @@ usage (char * progname) +@@ -111,7 +111,7 @@ usage (char * progname) fprintf (stderr, " %s [-v level] [-R retries] -F\n", progname); fprintf (stderr, " %s [-v level] [-l|-ll] [device]\n", progname); fprintf (stderr, " %s [-v level] [-a|-w] device\n", progname); @@ -32,7 +32,7 @@ index 346acb61..adc50d69 100644 fprintf (stderr, " %s [-v level] [-i] [-c|-C] device\n", progname); fprintf (stderr, " %s [-v level] [-i] [-u|-U]\n", progname); fprintf (stderr, " %s [-h|-t|-T]\n", progname); -@@ -134,6 +134,8 @@ usage (char * progname) +@@ -125,6 +125,8 @@ usage (char * progname) " -f flush a multipath device map\n" " -F flush all multipath device maps\n" " -a add a device wwid to the wwids file\n" @@ -41,7 +41,7 @@ index 346acb61..adc50d69 100644 " -c check if a device should be a path in a multipath device\n" " -C check if a multipath device has usable paths\n" " -q allow queue_if_no_path when multipathd is not running\n" -@@ -449,6 +451,50 @@ static void cleanup_vecs(void) +@@ -440,6 +442,50 @@ static void cleanup_vecs(void) free_pathvec(vecs.pathvec, FREE_PATHS); } @@ -92,7 +92,7 @@ index 346acb61..adc50d69 100644 static int configure (struct config *conf, enum mpath_cmds cmd, enum devtypes dev_type, char *devpath) -@@ -860,7 +906,7 @@ main (int argc, char *argv[]) +@@ -851,7 +897,7 @@ main (int argc, char *argv[]) condlog(1, "failed to register cleanup handler for vecs: %m"); if (atexit(cleanup_bindings)) condlog(1, "failed to register cleanup handler for bindings: %m"); @@ -101,7 +101,7 @@ index 346acb61..adc50d69 100644 switch(arg) { case 'v': if (!isdigit(optarg[0])) { -@@ -931,6 +977,10 @@ main (int argc, char *argv[]) +@@ -922,6 +968,10 @@ main (int argc, char *argv[]) case 'T': cmd = CMD_DUMP_CONFIG; break; @@ -138,7 +138,7 @@ index b88e9a4c..edd742aa 100644 Remove the WWID for the specified device from the WWIDs file. . diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in -index 3d957733..7ef6e99e 100644 +index ab166435..1ec08c6e 100644 --- a/multipathd/multipathd.service.in +++ b/multipathd/multipathd.service.in @@ -19,6 +19,7 @@ StartLimitBurst=3 diff --git a/0012-RH-reset-default-find_mutipaths-value-to-off.patch b/0008-RH-reset-default-find_mutipaths-value-to-off.patch similarity index 87% rename from 0012-RH-reset-default-find_mutipaths-value-to-off.patch rename to 0008-RH-reset-default-find_mutipaths-value-to-off.patch index 5789916..fdc90d4 100644 --- a/0012-RH-reset-default-find_mutipaths-value-to-off.patch +++ b/0008-RH-reset-default-find_mutipaths-value-to-off.patch @@ -1,4 +1,4 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From 064d761121e7e2c7b63ab280e341d8010a413119 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Thu, 7 Jun 2018 17:43:52 -0500 Subject: [PATCH] RH: reset default find_mutipaths value to off @@ -14,7 +14,7 @@ Signed-off-by: Benjamin Marzinski 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h -index 02f7e57c..cd03fd1a 100644 +index 134b690a..e2fe7ac4 100644 --- a/libmultipath/defaults.h +++ b/libmultipath/defaults.h @@ -24,7 +24,7 @@ @@ -27,10 +27,10 @@ index 02f7e57c..cd03fd1a 100644 #define DEFAULT_DEV_LOSS_TMO 600 #define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_ON diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in -index af9fbb96..0c1eff40 100644 +index ba291e11..b8389db3 100644 --- a/multipath/multipath.conf.5.in +++ b/multipath/multipath.conf.5.in -@@ -1226,7 +1226,7 @@ as non-multipath and passed on to upper layers. +@@ -1227,7 +1227,7 @@ as non-multipath and passed on to upper layers. \fBNote:\fR this may cause delays during device detection if there are single-path devices which aren\'t blacklisted. .TP diff --git a/0013-RH-attempt-to-get-ANA-info-via-sysfs-first.patch b/0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch similarity index 86% rename from 0013-RH-attempt-to-get-ANA-info-via-sysfs-first.patch rename to 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch index 1f94eb3..8065e9f 100644 --- a/0013-RH-attempt-to-get-ANA-info-via-sysfs-first.patch +++ b/0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch @@ -1,4 +1,4 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From 335b8eb2773b07a602e84e14c1f3e289a9b25b5a Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Thu, 11 Apr 2019 13:25:42 -0500 Subject: [PATCH] RH: attempt to get ANA info via sysfs first @@ -13,10 +13,10 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/libmultipath/prioritizers/ana.c b/libmultipath/prioritizers/ana.c -index e9827dca..80a32aa3 100644 +index 34527b22..4eaa3cc3 100644 --- a/libmultipath/prioritizers/ana.c +++ b/libmultipath/prioritizers/ana.c -@@ -24,6 +24,7 @@ +@@ -23,6 +23,7 @@ #include "prio.h" #include "util.h" #include "structs.h" @@ -24,7 +24,7 @@ index e9827dca..80a32aa3 100644 enum { ANA_ERR_GETCTRL_FAILED = 1, -@@ -36,6 +37,7 @@ enum { +@@ -35,6 +36,7 @@ enum { ANA_ERR_GETNS_FAILED, ANA_ERR_NO_MEMORY, ANA_ERR_NO_INFORMATION, @@ -32,7 +32,7 @@ index e9827dca..80a32aa3 100644 }; static const char *ana_errmsg[] = { -@@ -49,6 +51,7 @@ static const char *ana_errmsg[] = { +@@ -48,6 +50,7 @@ static const char *ana_errmsg[] = { [ANA_ERR_GETNS_FAILED] = "couldn't get namespace info", [ANA_ERR_NO_MEMORY] = "out of memory", [ANA_ERR_NO_INFORMATION] = "invalid fd", @@ -40,7 +40,7 @@ index e9827dca..80a32aa3 100644 }; static const char *anas_string[] = { -@@ -107,6 +110,27 @@ static int get_ana_state(__u32 nsid, __u32 anagrpid, void *ana_log, +@@ -106,6 +109,27 @@ static int get_ana_state(__u32 nsid, __u32 anagrpid, void *ana_log, return -ANA_ERR_GETANAS_NOTFOUND; } @@ -68,7 +68,7 @@ index e9827dca..80a32aa3 100644 static int get_ana_info(struct path * pp) { int rc; -@@ -209,8 +233,11 @@ int getprio(struct path *pp, __attribute__((unused)) char *args) +@@ -208,8 +232,11 @@ int getprio(struct path *pp, __attribute__((unused)) char *args) if (pp->fd < 0) rc = -ANA_ERR_NO_INFORMATION; diff --git a/0014-RH-make-parse_vpd_pg83-match-scsi_id-output.patch b/0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch similarity index 91% rename from 0014-RH-make-parse_vpd_pg83-match-scsi_id-output.patch rename to 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch index 3243375..f7bca92 100644 --- a/0014-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +++ b/0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch @@ -1,4 +1,4 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From 137c96d16b6bb03d8a52854e152db4ee36b7d9e4 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Thu, 25 Mar 2021 13:05:10 -0500 Subject: [PATCH] RH: make parse_vpd_pg83 match scsi_id output @@ -14,10 +14,10 @@ Signed-off-by: Benjamin Marzinski 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index b5851561..a3cc6e83 100644 +index 31db8758..21cfcc73 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c -@@ -1219,13 +1219,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, +@@ -1225,13 +1225,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, good_len = 8; break; case 2: @@ -33,7 +33,7 @@ index b5851561..a3cc6e83 100644 good_len = 8; break; default: -@@ -1243,10 +1239,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, +@@ -1249,10 +1245,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, break; case 0x8: /* SCSI Name: Prio 3 */ diff --git a/0015-RH-add-scsi-device-handlers-to-modules-load.d.patch b/0011-RH-add-scsi-device-handlers-to-modules-load.d.patch similarity index 89% rename from 0015-RH-add-scsi-device-handlers-to-modules-load.d.patch rename to 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch index 97fb4df..3fe7c25 100644 --- a/0015-RH-add-scsi-device-handlers-to-modules-load.d.patch +++ b/0011-RH-add-scsi-device-handlers-to-modules-load.d.patch @@ -1,4 +1,4 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From 374755791536be4870ab2e93ae36549cbaaeb800 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Fri, 25 Mar 2022 18:12:06 -0500 Subject: [PATCH] RH: add scsi device handlers to modules-load.d @@ -11,7 +11,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc -index 7774f1f4..0e836f0a 100644 +index 03aee175..936a622f 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -16,7 +16,7 @@ READLINE := diff --git a/0016-RH-compile-with-libreadline-support.patch b/0012-RH-compile-with-libreadline-support.patch similarity index 89% rename from 0016-RH-compile-with-libreadline-support.patch rename to 0012-RH-compile-with-libreadline-support.patch index e7579b0..0964c42 100644 --- a/0016-RH-compile-with-libreadline-support.patch +++ b/0012-RH-compile-with-libreadline-support.patch @@ -1,4 +1,4 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From cc15379130e8aa068e97c64afd46be212b456d4f Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Tue, 15 Nov 2022 18:03:33 -0600 Subject: [PATCH] RH: compile with libreadline support @@ -12,7 +12,7 @@ Signed-off-by: Benjamin Marzinski 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc -index 0e836f0a..e1d3fcd1 100644 +index 936a622f..f475f70f 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -12,7 +12,7 @@ diff --git a/0017-RH-Add-mpathcleanup.patch b/0013-RH-Add-mpathcleanup.patch similarity index 98% rename from 0017-RH-Add-mpathcleanup.patch rename to 0013-RH-Add-mpathcleanup.patch index bd2dcd6..d1a8e84 100644 --- a/0017-RH-Add-mpathcleanup.patch +++ b/0013-RH-Add-mpathcleanup.patch @@ -1,4 +1,4 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From 2ef5bd86052ba0b22f4d3a16e69cdf268d90a53a Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Fri, 7 Jul 2023 15:25:59 -0500 Subject: [PATCH] RH: Add mpathcleanup diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 232daba..24b00bd 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath -Version: 0.11.1 -Release: 2%{?dist} +Version: 0.13.0 +Release: 1%{?dist} Summary: Tools to manage multipath devices using device-mapper # readline uses GPL-3.0-only License: GPL-2.0-only AND GPL-3.0-only @@ -8,26 +8,22 @@ URL: http://christophe.varoqui.free.fr/ # The source for this package was pulled from upstream's git repo. Use the # following command to generate the tarball -# curl -L https://github.com/opensvc/multipath-tools/archive/0.11.1.tar.gz -o multipath-tools-0.11.1.tgz -Source0: multipath-tools-0.11.1.tgz +# curl -L https://github.com/opensvc/multipath-tools/archive/0.13.0.tar.gz -o multipath-tools-0.13.0.tgz +Source0: multipath-tools-0.13.0.tgz Source1: multipath.conf -Patch0001: 0001-multipathd-trigger-uevents-for-blacklisted-paths-in-.patch -Patch0002: 0002-multipath-tools-fix-compilation-with-latest-userspac.patch -Patch0003: 0003-libmultipath-include-urcu.h-before-urcu-atomic.h.patch -Patch0004: 0004-libmpathutils-uxsock.c-Include-string.h-for-memcpy.patch -Patch0005: 0005-RH-fixup-udev-rules-for-redhat.patch -Patch0006: 0006-RH-Remove-the-property-blacklist-exception-builtin.patch -Patch0007: 0007-RH-don-t-start-without-a-config-file.patch -Patch0008: 0008-RH-Fix-nvme-function-missing-argument.patch -Patch0009: 0009-RH-use-rpm-optflags-if-present.patch -Patch0010: 0010-RH-add-mpathconf.patch -Patch0011: 0011-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch -Patch0012: 0012-RH-reset-default-find_mutipaths-value-to-off.patch -Patch0013: 0013-RH-attempt-to-get-ANA-info-via-sysfs-first.patch -Patch0014: 0014-RH-make-parse_vpd_pg83-match-scsi_id-output.patch -Patch0015: 0015-RH-add-scsi-device-handlers-to-modules-load.d.patch -Patch0016: 0016-RH-compile-with-libreadline-support.patch -Patch0017: 0017-RH-Add-mpathcleanup.patch +Patch0001: 0001-RH-fixup-udev-rules-for-redhat.patch +Patch0002: 0002-RH-Remove-the-property-blacklist-exception-builtin.patch +Patch0003: 0003-RH-don-t-start-without-a-config-file.patch +Patch0004: 0004-RH-Fix-nvme-function-missing-argument.patch +Patch0005: 0005-RH-use-rpm-optflags-if-present.patch +Patch0006: 0006-RH-add-mpathconf.patch +Patch0007: 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +Patch0008: 0008-RH-reset-default-find_mutipaths-value-to-off.patch +Patch0009: 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch +Patch0010: 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch +Patch0011: 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch +Patch0012: 0012-RH-compile-with-libreadline-support.patch +Patch0013: 0013-RH-Add-mpathcleanup.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -115,7 +111,7 @@ This package contains the files needed to develop applications that use device-mapper-multipath's libdmmp C API library %prep -%autosetup -n multipath-tools-0.11.1 -p1 +%autosetup -n multipath-tools-0.13.0 -p1 cp %{SOURCE1} . %build @@ -167,6 +163,7 @@ fi %{_sbindir}/mpathcleanup %{_sbindir}/mpathpersist %{_unitdir}/multipathd.service +%{_unitdir}/multipathd-queueing.service %{_unitdir}/multipathd.socket %{_mandir}/man5/multipath.conf.5* %{_mandir}/man8/multipath.8* @@ -237,6 +234,13 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Tue Nov 4 2025 Benjamin Marzinski - 0.13.0-1 +- Update source to upstream release 0.13.0 + * Previous patches 0001-0004 are included in the tarball +- Install /lib/systemd/system/multipathd-queueing.service +- Rename redhat patches + * Previous patches 0005-0017 are now patches 0001-0013 + * Wed Jul 23 2025 Fedora Release Engineering - 0.11.1-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild diff --git a/sources b/sources index 5eea94e..233c4ea 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (multipath-tools-0.11.1.tgz) = ac6bacd725bc831a140b75a72c81296eb1ed4080fb6350caf6178914d1bdce743705f3bd4e31f318068f6272dc98e12d63ee38228a3521a3d1c7bc8eb30812f9 +SHA512 (multipath-tools-0.13.0.tgz) = 75c84524ee27590b8b751ea500898a44e5ac3d58d55be6bcab919d0d423049db3a4466fcb9135705cf63ba074416973bb651255063269e9f682f11d21ba57e59 SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942 From d6f2be9e59baa23b2d610a68d3635da3d5b6b991 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Thu, 13 Nov 2025 19:23:18 -0500 Subject: [PATCH 29/29] device-mapper-multipath-0.13.0-2 Move STI tests to TMT --- {tests/.fmf => .fmf}/version | 0 device-mapper-multipath.spec | 5 +++- plans/multipath.fmf | 58 ++++++++++++++++++++++++++++++++++++ tests/provision.fmf | 5 ---- tests/tests.yml | 44 --------------------------- 5 files changed, 62 insertions(+), 50 deletions(-) rename {tests/.fmf => .fmf}/version (100%) create mode 100644 plans/multipath.fmf delete mode 100644 tests/provision.fmf delete mode 100644 tests/tests.yml diff --git a/tests/.fmf/version b/.fmf/version similarity index 100% rename from tests/.fmf/version rename to .fmf/version diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 24b00bd..5d80d4e 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.13.0 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Tools to manage multipath devices using device-mapper # readline uses GPL-3.0-only License: GPL-2.0-only AND GPL-3.0-only @@ -234,6 +234,9 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Thu Nov 13 2025 Benjamin Marzinski - 0.13.0-2 +- Move STI tests to TMT + * Tue Nov 4 2025 Benjamin Marzinski - 0.13.0-1 - Update source to upstream release 0.13.0 * Previous patches 0001-0004 are included in the tarball diff --git a/plans/multipath.fmf b/plans/multipath.fmf new file mode 100644 index 0000000..876c77a --- /dev/null +++ b/plans/multipath.fmf @@ -0,0 +1,58 @@ +summary: basic functionality tests + +provision: + hardware: + memory: ">= 2 GB" + +prepare: + how: install + package: + - device-mapper-multipath + - perl + +discover: + how: shell + tests: + - name: medium_error_scsi_debug + path: /tests/medium_error_scsi_debug + test: ./main.sh + duration: 15m + - name: squelch_scsi_id + path: /tests/squelch_scsi_id + test: ./main.sh + duration: 15m + - name: multipathd_oom + path: /tests/multipathd_oom + test: ./main.sh + duration: 15m + - name: user_friendly_names + path: /tests/user_friendly_names + test: ./main.sh + duration: 15m + - name: kpartx_4k_aligned + path: /tests/kpartx_4k_aligned + test: ./main.sh + duration: 15m + - name: bindings + path: /tests/bindings + test: ./main.sh + duration: 15m + - name: restate_module + path: /tests/restate_module + test: ./main.sh + duration: 15m + - name: find_multipaths + path: /tests/find_multipaths + test: ./main.sh + duration: 15m + - name: multipath_conf_syntax + path: /tests/multipath_conf_syntax + test: ./main.sh + duration: 15m + - name: alias_clash + path: /tests/alias_clash + test: ./main.sh + duration: 15m + +execute: + how: tmt diff --git a/tests/provision.fmf b/tests/provision.fmf deleted file mode 100644 index 62a6eba..0000000 --- a/tests/provision.fmf +++ /dev/null @@ -1,5 +0,0 @@ ---- - -standard-inventory-qcow2: - qemu: - m: 2G diff --git a/tests/tests.yml b/tests/tests.yml deleted file mode 100644 index 15f26d2..0000000 --- a/tests/tests.yml +++ /dev/null @@ -1,44 +0,0 @@ ---- -# No tests suitable for atomic environment -# No tests suitable for container environment - -# Tests suitable for classic environment -- hosts: localhost - roles: - - role: standard-test-basic - tags: - - classic - tests: - - medium_error_scsi_debug: - run: ./main.sh - timeout: 15m - - squelch_scsi_id: - run: ./main.sh - timeout: 15m - - multipathd_oom: - run: ./main.sh - timeout: 15m - - user_friendly_names: - run: ./main.sh - timeout: 15m - - kpartx_4k_aligned: - run: ./main.sh - timeout: 15m - - bindings: - run: ./main.sh - timeout: 15m - - restate_module: - run: ./main.sh - timeout: 15m - - find_multipaths: - run: ./main.sh - timeout: 15m - - multipath_conf_syntax: - run: ./main.sh - timeout: 15m - - alias_clash: - run: ./main.sh - timeout: 15m - required_packages: - - device-mapper-multipath - - perl