From e5cbd1f1073b3c15a7b1afbe2049bca46cba88a8 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Mon, 2 Apr 2018 17:29:20 -0500 Subject: [PATCH] device-mapper-multipath-0.7.6-1.git1cb704b Update Source to the latest upstream commit * Previous patches 0001-0014 are included in this commit * Previous patches 0015-0022 are now patches 0007-0014 0001-multipathd-remove-incorrect-pthread_testcancel.patch * Fixed pthread cancellation issue. posted upstream 0002-multipath-add-comments.patch * Posted upstream 0003-multipathd-minor-dmevents-polling-code-cleanups.patch * Fixed minor polling issues. posted upstream 0004-multipathd-remove-unneeded-function-parameter.patch * Posted upstream 0005-mpathcmd-fix-libmpathcmd-license.patch * License clarification. posted upstream 0006-libmultipath-don-t-print-undefined-values.patch * Fixed bug in 'multipath show config'. posted upstream --- .gitignore | 1 + ...libmultipath-fix-tur-checker-locking.patch | 269 ------ ...-remove-incorrect-pthread_testcancel.patch | 30 + 0002-multipath-add-comments.patch | 389 +++++++++ 0002-multipath-fix-DEF_TIMEOUT-use.patch | 32 - ...minor-dmevents-polling-code-cleanups.patch | 48 ++ ...emove-coalesce_paths-from-ev_add_map.patch | 98 --- ...d-remove-unneeded-function-parameter.patch | 83 ++ ...hd-remove-unused-configure-parameter.patch | 53 -- 0005-Fix-set_no_path_retry-regression.patch | 81 -- 0005-mpathcmd-fix-libmpathcmd-license.patch | 58 ++ ...ltipath-don-t-print-undefined-values.patch | 60 ++ ...-change-spurious-uevent-msg-priority.patch | 29 - ... 0007-RH-fixup-udev-rules-for-redhat.patch | 6 +- ...-print-sysfs-state-in-fast-list-mode.patch | 68 -- ...property-blacklist-exception-builtin.patch | 4 +- ...e-remove_map-waiter-code-to-multipat.patch | 148 ---- ...RH-don-t-start-without-a-config-file.patch | 10 +- ...code-from-libmultipath-to-multipathd.patch | 793 ------------------ ... 0010-RH-use-rpm-optflags-if-present.patch | 16 +- ...waiter_thread-before-setup_multipath.patch | 129 --- ...hconf.patch => 0011-RH-add-mpathconf.patch | 8 +- 0011-libmultipath-add-helper-functions.patch | 155 ---- ...om-kernel-cmdline-mpath.wwids-with-A.patch | 18 +- ...dd-new-polling-dmevents-waiter-threa.patch | 643 -------------- ...change-uevent-on-new-device-creation.patch | 28 +- 0013-libmultipath-condlog-log-to-stderr.patch | 35 - ...-on-invalid-regex-instead-of-failing.patch | 18 +- ...ompiler-warning-for-uev_pathfail_che.patch | 31 - device-mapper-multipath.spec | 71 +- sources | 2 +- 31 files changed, 761 insertions(+), 2653 deletions(-) delete mode 100644 0001-libmultipath-fix-tur-checker-locking.patch create mode 100644 0001-multipathd-remove-incorrect-pthread_testcancel.patch create mode 100644 0002-multipath-add-comments.patch delete mode 100644 0002-multipath-fix-DEF_TIMEOUT-use.patch create mode 100644 0003-multipathd-minor-dmevents-polling-code-cleanups.patch delete mode 100644 0003-multipathd-remove-coalesce_paths-from-ev_add_map.patch create mode 100644 0004-multipathd-remove-unneeded-function-parameter.patch delete mode 100644 0004-multipathd-remove-unused-configure-parameter.patch delete mode 100644 0005-Fix-set_no_path_retry-regression.patch create mode 100644 0005-mpathcmd-fix-libmpathcmd-license.patch create mode 100644 0006-libmultipath-don-t-print-undefined-values.patch delete mode 100644 0006-multipathd-change-spurious-uevent-msg-priority.patch rename 0015-RH-fixup-udev-rules-for-redhat.patch => 0007-RH-fixup-udev-rules-for-redhat.patch (96%) delete mode 100644 0007-multipath-print-sysfs-state-in-fast-list-mode.patch rename 0016-RH-Remove-the-property-blacklist-exception-builtin.patch => 0008-RH-Remove-the-property-blacklist-exception-builtin.patch (96%) delete mode 100644 0008-libmultipath-move-remove_map-waiter-code-to-multipat.patch rename 0017-RH-don-t-start-without-a-config-file.patch => 0009-RH-don-t-start-without-a-config-file.patch (94%) delete mode 100644 0009-move-waiter-code-from-libmultipath-to-multipathd.patch rename 0018-RH-use-rpm-optflags-if-present.patch => 0010-RH-use-rpm-optflags-if-present.patch (77%) delete mode 100644 0010-call-start_waiter_thread-before-setup_multipath.patch rename 0019-RH-add-mpathconf.patch => 0011-RH-add-mpathconf.patch (99%) delete mode 100644 0011-libmultipath-add-helper-functions.patch rename 0020-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch => 0012-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch (93%) delete mode 100644 0012-multipathd-RFC-add-new-polling-dmevents-waiter-threa.patch rename 0021-RH-trigger-change-uevent-on-new-device-creation.patch => 0013-RH-trigger-change-uevent-on-new-device-creation.patch (86%) delete mode 100644 0013-libmultipath-condlog-log-to-stderr.patch rename 0022-RH-warn-on-invalid-regex-instead-of-failing.patch => 0014-RH-warn-on-invalid-regex-instead-of-failing.patch (87%) delete mode 100644 0014-multipathd-fix-compiler-warning-for-uev_pathfail_che.patch diff --git a/.gitignore b/.gitignore index 4f88485..ef47b0b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ multipath-tools-091027.tar.gz /multipath-tools-git847cc43.tgz /multipath-tools-0.7.3.tgz /multipath-tools-07e7bd5.tgz +/multipath-tools-1cb704b.tgz diff --git a/0001-libmultipath-fix-tur-checker-locking.patch b/0001-libmultipath-fix-tur-checker-locking.patch deleted file mode 100644 index f6a255f..0000000 --- a/0001-libmultipath-fix-tur-checker-locking.patch +++ /dev/null @@ -1,269 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Thu, 8 Feb 2018 16:56:45 -0600 -Subject: [PATCH] libmultipath: fix tur checker locking - -Commit 6e2423fd fixed a bug where the tur checker could cancel a -detached thread after it had exitted. However in fixing this, the new -code grabbed a mutex (to call condlog) while holding a spin_lock. To -deal with this, I've done away with the holder spin_lock completely, and -replaced it with two atomic variables, based on a suggestion by Martin -Wilck. - -The holder variable works exactly like before. When the checker is -initialized, it is set to 1. When a thread is created it is incremented. -When either the thread or the checker are done with the context, they -atomically decrement the holder variable and check its value. If it -is 0, they free the context. If it is 1, they never touch the context -again. - -The other variable has changed. First, ct->running and ct->thread have -switched uses. ct->thread is now only ever accessed by the checker, -never the thread. If it is non-NULL, a thread has started up, but -hasn't been dealt with by the checker yet. It is also obviously used -by the checker to cancel the thread. - -ct->running is now an atomic variable. When the thread is started -it is set to 1. When the checker wants to kill a thread, it atomically -sets the value to 0 and reads the previous value. If it was 1, -the checker cancels the thread. If it was 0, the nothing needs to be -done. After the checker has dealt with the thread, it sets ct->thread -to NULL. - -Right before the thread finishes and pops the cleanup handler, it -atomically sets the value of ct->running to 0 and reads the previous -value. If it was 1, the thread just pops the cleanup handler and exits. -If it was 0, then the checker is trying to cancel the thread, and so the -thread calls pause(), which is a cancellation point. - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/checkers/tur.c | 107 ++++++++++++++++++-------------------------- - 1 file changed, 43 insertions(+), 64 deletions(-) - -diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c -index b4a5cb2..9155960 100644 ---- a/libmultipath/checkers/tur.c -+++ b/libmultipath/checkers/tur.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - - #include "checkers.h" - -@@ -44,7 +45,6 @@ struct tur_checker_context { - pthread_t thread; - pthread_mutex_t lock; - pthread_cond_t active; -- pthread_spinlock_t hldr_lock; - int holders; - char message[CHECKER_MSG_LEN]; - }; -@@ -74,13 +74,12 @@ int libcheck_init (struct checker * c) - - ct->state = PATH_UNCHECKED; - ct->fd = -1; -- ct->holders = 1; -+ uatomic_set(&ct->holders, 1); - pthread_cond_init_mono(&ct->active); - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&ct->lock, &attr); - pthread_mutexattr_destroy(&attr); -- pthread_spin_init(&ct->hldr_lock, PTHREAD_PROCESS_PRIVATE); - c->context = ct; - - return 0; -@@ -90,7 +89,6 @@ static void cleanup_context(struct tur_checker_context *ct) - { - pthread_mutex_destroy(&ct->lock); - pthread_cond_destroy(&ct->active); -- pthread_spin_destroy(&ct->hldr_lock); - free(ct); - } - -@@ -99,16 +97,14 @@ void libcheck_free (struct checker * c) - if (c->context) { - struct tur_checker_context *ct = c->context; - int holders; -- pthread_t thread; -- -- pthread_spin_lock(&ct->hldr_lock); -- ct->holders--; -- holders = ct->holders; -- thread = ct->thread; -- pthread_spin_unlock(&ct->hldr_lock); -- if (holders) -- pthread_cancel(thread); -- else -+ int running; -+ -+ running = uatomic_xchg(&ct->running, 0); -+ if (running) -+ pthread_cancel(ct->thread); -+ ct->thread = 0; -+ holders = uatomic_sub_return(&ct->holders, 1); -+ if (!holders) - cleanup_context(ct); - c->context = NULL; - } -@@ -220,26 +216,12 @@ static void cleanup_func(void *data) - { - int holders; - struct tur_checker_context *ct = data; -- pthread_spin_lock(&ct->hldr_lock); -- ct->holders--; -- holders = ct->holders; -- ct->thread = 0; -- pthread_spin_unlock(&ct->hldr_lock); -+ -+ holders = uatomic_sub_return(&ct->holders, 1); - if (!holders) - cleanup_context(ct); - } - --static int tur_running(struct tur_checker_context *ct) --{ -- pthread_t thread; -- -- pthread_spin_lock(&ct->hldr_lock); -- thread = ct->thread; -- pthread_spin_unlock(&ct->hldr_lock); -- -- return thread != 0; --} -- - static void copy_msg_to_tcc(void *ct_p, const char *msg) - { - struct tur_checker_context *ct = ct_p; -@@ -252,7 +234,7 @@ static void copy_msg_to_tcc(void *ct_p, const char *msg) - static void *tur_thread(void *ctx) - { - struct tur_checker_context *ct = ctx; -- int state; -+ int state, running; - char devt[32]; - - condlog(3, "%s: tur checker starting up", -@@ -278,6 +260,11 @@ static void *tur_thread(void *ctx) - - condlog(3, "%s: tur checker finished, state %s", - tur_devt(devt, sizeof(devt), ct), checker_state_name(state)); -+ -+ running = uatomic_xchg(&ct->running, 0); -+ if (!running) -+ pause(); -+ - tur_thread_cleanup_pop(ct); - - return ((void *)0); -@@ -325,7 +312,6 @@ int libcheck_check(struct checker * c) - int tur_status, r; - char devt[32]; - -- - if (!ct) - return PATH_UNCHECKED; - -@@ -349,38 +335,29 @@ int libcheck_check(struct checker * c) - return PATH_WILD; - } - -- if (ct->running) { -- /* -- * Check if TUR checker is still running. Hold hldr_lock -- * around the pthread_cancel() call to avoid that -- * pthread_cancel() gets called after the (detached) TUR -- * thread has exited. -- */ -- pthread_spin_lock(&ct->hldr_lock); -- if (ct->thread) { -- if (tur_check_async_timeout(c)) { -- condlog(3, "%s: tur checker timeout", -- tur_devt(devt, sizeof(devt), ct)); -+ if (ct->thread) { -+ if (tur_check_async_timeout(c)) { -+ int running = uatomic_xchg(&ct->running, 0); -+ if (running) - pthread_cancel(ct->thread); -- ct->running = 0; -- MSG(c, MSG_TUR_TIMEOUT); -- tur_status = PATH_TIMEOUT; -- } else { -- condlog(3, "%s: tur checker not finished", -+ condlog(3, "%s: tur checker timeout", -+ tur_devt(devt, sizeof(devt), ct)); -+ ct->thread = 0; -+ MSG(c, MSG_TUR_TIMEOUT); -+ tur_status = PATH_TIMEOUT; -+ } else if (uatomic_read(&ct->running) != 0) { -+ condlog(3, "%s: tur checker not finished", - tur_devt(devt, sizeof(devt), ct)); -- ct->running++; -- tur_status = PATH_PENDING; -- } -+ tur_status = PATH_PENDING; - } else { - /* TUR checker done */ -- ct->running = 0; -+ ct->thread = 0; - tur_status = ct->state; - strlcpy(c->message, ct->message, sizeof(c->message)); - } -- pthread_spin_unlock(&ct->hldr_lock); - pthread_mutex_unlock(&ct->lock); - } else { -- if (tur_running(ct)) { -+ if (uatomic_read(&ct->running) != 0) { - /* pthread cancel failed. continue in sync mode */ - pthread_mutex_unlock(&ct->lock); - condlog(3, "%s: tur thread not responding", -@@ -391,19 +368,17 @@ int libcheck_check(struct checker * c) - ct->state = PATH_UNCHECKED; - ct->fd = c->fd; - ct->timeout = c->timeout; -- pthread_spin_lock(&ct->hldr_lock); -- ct->holders++; -- pthread_spin_unlock(&ct->hldr_lock); -+ uatomic_add(&ct->holders, 1); -+ uatomic_set(&ct->running, 1); - tur_set_async_timeout(c); - setup_thread_attr(&attr, 32 * 1024, 1); - r = pthread_create(&ct->thread, &attr, tur_thread, ct); - pthread_attr_destroy(&attr); - if (r) { -- pthread_spin_lock(&ct->hldr_lock); -- ct->holders--; -- pthread_spin_unlock(&ct->hldr_lock); -- pthread_mutex_unlock(&ct->lock); -+ uatomic_sub(&ct->holders, 1); -+ uatomic_set(&ct->running, 0); - ct->thread = 0; -+ pthread_mutex_unlock(&ct->lock); - condlog(3, "%s: failed to start tur thread, using" - " sync mode", tur_devt(devt, sizeof(devt), ct)); - return tur_check(c->fd, c->timeout, -@@ -414,12 +389,16 @@ int libcheck_check(struct checker * c) - tur_status = ct->state; - strlcpy(c->message, ct->message, sizeof(c->message)); - pthread_mutex_unlock(&ct->lock); -- if (tur_running(ct) && -+ if (uatomic_read(&ct->running) != 0 && - (tur_status == PATH_PENDING || tur_status == PATH_UNCHECKED)) { - condlog(3, "%s: tur checker still running", - tur_devt(devt, sizeof(devt), ct)); -- ct->running = 1; - tur_status = PATH_PENDING; -+ } else { -+ int running = uatomic_xchg(&ct->running, 0); -+ if (running) -+ pthread_cancel(ct->thread); -+ ct->thread = 0; - } - } - --- -2.7.4 - diff --git a/0001-multipathd-remove-incorrect-pthread_testcancel.patch b/0001-multipathd-remove-incorrect-pthread_testcancel.patch new file mode 100644 index 0000000..0c9e3fb --- /dev/null +++ b/0001-multipathd-remove-incorrect-pthread_testcancel.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 28 Mar 2018 16:47:05 -0500 +Subject: [PATCH] multipathd: remove incorrect pthread_testcancel + +As Martin Wilck pointed out, a thread that's trying to stop the waiter +thread should not cancel itself before it gets a chance to do so + +Cc: Martin Wilck +Fixes: c7625f92 "multipathd: fix waiter thread cancelling" +Signed-off-by: Benjamin Marzinski +--- + multipathd/waiter.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/multipathd/waiter.c b/multipathd/waiter.c +index 595c69a..0ef8b25 100644 +--- a/multipathd/waiter.c ++++ b/multipathd/waiter.c +@@ -68,7 +68,6 @@ void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs) + mpp->waiter = (pthread_t)0; + pthread_cleanup_push(cleanup_lock, &waiter_lock); + lock(&waiter_lock); +- pthread_testcancel(); + pthread_kill(thread, SIGUSR2); + pthread_cancel(thread); + lock_cleanup_pop(&waiter_lock); +-- +2.7.4 + diff --git a/0002-multipath-add-comments.patch b/0002-multipath-add-comments.patch new file mode 100644 index 0000000..f82c828 --- /dev/null +++ b/0002-multipath-add-comments.patch @@ -0,0 +1,389 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 29 Mar 2018 12:07:11 -0500 +Subject: [PATCH] multipath: add comments + +This commit simply adds a number of comments based on suggestions by +Martin Wilck. + +Cc: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + multipathd/dmevents.c | 4 ++- + tests/dmevents.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++- + tests/util.c | 2 ++ + 3 files changed, 76 insertions(+), 2 deletions(-) + +diff --git a/multipathd/dmevents.c b/multipathd/dmevents.c +index 2281a10..0b0d0ce 100644 +--- a/multipathd/dmevents.c ++++ b/multipathd/dmevents.c +@@ -122,6 +122,8 @@ static int arm_dm_event_poll(int fd) + dmi.version[0] = DM_VERSION_MAJOR; + dmi.version[1] = DM_VERSION_MINOR; + dmi.version[2] = DM_VERSION_PATCHLEVEL; ++ /* This flag currently does nothing. It simply exists to ++ * duplicate the behavior of libdevmapper */ + dmi.flags = 0x4; + dmi.data_start = offsetof(struct dm_ioctl, data); + dmi.data_size = sizeof(dmi); +@@ -189,7 +191,7 @@ fail: + return -1; + } + +-/* You must call update_multipath() after calling this function, to ++/* You must call __setup_multipath() after calling this function, to + * deal with any events that came in before the device was added */ + int watch_dmevents(char *name) + { +diff --git a/tests/dmevents.c b/tests/dmevents.c +index 4442fc2..bba51dc 100644 +--- a/tests/dmevents.c ++++ b/tests/dmevents.c +@@ -33,10 +33,13 @@ + /* I have to do this to get at the static variables */ + #include "../multipathd/dmevents.c" + ++/* pretend dm device */ + struct dm_device { + char name[WWID_SIZE]; ++ /* is this a mpath device, or other dm device */ + int is_mpath; + uint32_t evt_nr; ++ /* tracks the event number when the multipath device was updated */ + uint32_t update_nr; + }; + +@@ -48,6 +51,9 @@ struct test_data { + + struct test_data data; + ++/* Add a pretend dm device, or update its event number. This is used to build ++ * up the dm devices that the dmevents code queries with dm_task_get_names, ++ * dm_geteventnr, and dm_is_mpath */ + int add_dm_device_event(char *name, int is_mpath, uint32_t evt_nr) + { + struct dm_device *dev; +@@ -77,6 +83,7 @@ int add_dm_device_event(char *name, int is_mpath, uint32_t evt_nr) + return 0; + } + ++/* helper function for pretend dm devices */ + struct dm_device *find_dm_device(const char *name) + { + struct dm_device *dev; +@@ -88,6 +95,7 @@ struct dm_device *find_dm_device(const char *name) + return NULL; + } + ++/* helper function for pretend dm devices */ + int remove_dm_device_event(const char *name) + { + struct dm_device *dev; +@@ -103,6 +111,7 @@ int remove_dm_device_event(const char *name) + return -1; + } + ++/* helper function for pretend dm devices */ + void remove_all_dm_device_events(void) + { + struct dm_device *dev; +@@ -122,7 +131,9 @@ static inline void *align_ptr(void *ptr) + return (void *)align_val((size_t)ptr); + } + +-/* copied off of list_devices in dm-ioctl.c */ ++/* copied off of list_devices in dm-ioctl.c except that it uses ++ * the pretend dm devices, and saves the output to the test_data ++ * structure */ + struct dm_names *build_dm_names(void) + { + struct dm_names *names, *np, *old_np = NULL; +@@ -199,12 +210,16 @@ int __wrap_open(const char *pathname, int flags) + return mock_type(int); + } + ++/* We never check the result of the close(), so there's no need to ++ * to mock a return value */ + int __wrap_close(int fd) + { + assert_int_equal(fd, waiter->fd); + return 0; + } + ++/* the pretend dm device code checks the input and supplies the ++ * return value, so there's no need to do that here */ + int __wrap_dm_is_mpath(const char *name) + { + struct dm_device *dev; +@@ -216,6 +231,8 @@ int __wrap_dm_is_mpath(const char *name) + return 0; + } + ++/* either get return info from the pretend dm device, or ++ * override it to test -1 return */ + int __wrap_dm_geteventnr(const char *name) + { + struct dm_device *dev; +@@ -257,6 +274,8 @@ int __wrap_dm_task_run(struct dm_task *dmt) + return mock_type(int); + } + ++/* either get return info from the pretend dm device, or ++ * override it to test NULL return */ + struct dm_names * __wrap_dm_task_get_names(struct dm_task *dmt) + { + int good = mock_type(int); +@@ -299,6 +318,9 @@ void __wrap_remove_map_by_alias(const char *alias, struct vectors * vecs, + assert_int_equal(purge_vec, 1); + } + ++/* pretend update the pretend dm devices. If fail is set, it ++ * simulates having the dm device removed. Otherwise it just sets ++ * update_nr to record when the update happened */ + int __wrap_update_multipath(struct vectors *vecs, char *mapname, int reset) + { + int fail; +@@ -325,6 +347,9 @@ int __wrap_update_multipath(struct vectors *vecs, char *mapname, int reset) + return fail; + } + ++/* helper function used to check if the dmevents list of devices ++ * includes a specific device. To make sure that dmevents is ++ * in the correct state after running a function */ + struct dev_event *find_dmevents(const char *name) + { + struct dev_event *dev_evt; +@@ -336,14 +361,19 @@ struct dev_event *find_dmevents(const char *name) + return NULL; + } + ++/* null vecs pointer when initialized dmevents */ + static void test_init_waiter_bad0(void **state) + { ++ /* this boilerplate code just skips the test if ++ * dmevents polling is not supported */ + struct test_data *datap = (struct test_data *)(*state); + if (datap == NULL) + skip(); ++ + assert_int_equal(init_dmevent_waiter(NULL), -1); + } + ++/* fail to open /dev/mapper/control */ + static void test_init_waiter_bad1(void **state) + { + struct test_data *datap = (struct test_data *)(*state); +@@ -354,6 +384,7 @@ static void test_init_waiter_bad1(void **state) + assert_ptr_equal(waiter, NULL); + } + ++/* waiter remains initialized after this test */ + static void test_init_waiter_good0(void **state) + { + struct test_data *datap = (struct test_data *)(*state); +@@ -364,6 +395,7 @@ static void test_init_waiter_good0(void **state) + assert_ptr_not_equal(waiter, NULL); + } + ++/* No dm device named foo */ + static void test_watch_dmevents_bad0(void **state) + { + struct test_data *datap = (struct test_data *)(*state); +@@ -373,6 +405,7 @@ static void test_watch_dmevents_bad0(void **state) + assert_ptr_equal(find_dmevents("foo"), NULL); + } + ++/* foo is not a multipath device */ + static void test_watch_dmevents_bad1(void **state) + { + struct test_data *datap = (struct test_data *)(*state); +@@ -384,6 +417,7 @@ static void test_watch_dmevents_bad1(void **state) + assert_ptr_equal(find_dmevents("foo"), NULL); + } + ++/* failed getting the dmevent number */ + static void test_watch_dmevents_bad2(void **state) + { + struct test_data *datap = (struct test_data *)(*state); +@@ -396,6 +430,8 @@ static void test_watch_dmevents_bad2(void **state) + assert_int_equal(watch_dmevents("foo"), -1); + assert_ptr_equal(find_dmevents("foo"), NULL); + } ++ ++/* verify that you can watch and unwatch dm multipath device "foo" */ + static void test_watch_dmevents_good0(void **state) + { + struct dev_event *dev_evt; +@@ -407,16 +443,20 @@ static void test_watch_dmevents_good0(void **state) + assert_int_equal(add_dm_device_event("foo", 1, 5), 0); + will_return(__wrap_dm_geteventnr, 0); + assert_int_equal(watch_dmevents("foo"), 0); ++ /* verify foo is being watched */ + dev_evt = find_dmevents("foo"); + assert_ptr_not_equal(dev_evt, NULL); + assert_int_equal(dev_evt->evt_nr, 5); + assert_int_equal(dev_evt->action, EVENT_NOTHING); + assert_int_equal(VECTOR_SIZE(waiter->events), 1); + unwatch_dmevents("foo"); ++ /* verify foo is no longer being watched */ + assert_int_equal(VECTOR_SIZE(waiter->events), 0); + assert_ptr_equal(find_dmevents("foo"), NULL); + } + ++/* verify that if you try to watch foo multiple times, it only ++ * is placed on the waiter list once */ + static void test_watch_dmevents_good1(void **state) + { + struct dev_event *dev_evt; +@@ -445,6 +485,7 @@ static void test_watch_dmevents_good1(void **state) + assert_ptr_equal(find_dmevents("foo"), NULL); + } + ++/* watch and then unwatch multiple devices */ + static void test_watch_dmevents_good2(void **state) + { + struct dev_event *dev_evt; +@@ -480,6 +521,7 @@ static void test_watch_dmevents_good2(void **state) + assert_ptr_equal(find_dmevents("bar"), NULL); + } + ++/* dm_task_create fails */ + static void test_get_events_bad0(void **state) + { + struct test_data *datap = (struct test_data *)(*state); +@@ -493,6 +535,7 @@ static void test_get_events_bad0(void **state) + assert_int_equal(dm_get_events(), -1); + } + ++/* dm_task_run fails */ + static void test_get_events_bad1(void **state) + { + struct test_data *datap = (struct test_data *)(*state); +@@ -505,6 +548,7 @@ static void test_get_events_bad1(void **state) + assert_int_equal(dm_get_events(), -1); + } + ++/* dm_task_get_names fails */ + static void test_get_events_bad2(void **state) + { + struct test_data *datap = (struct test_data *)(*state); +@@ -518,6 +562,7 @@ static void test_get_events_bad2(void **state) + assert_int_equal(dm_get_events(), -1); + } + ++/* If the device isn't being watched, dm_get_events returns NULL */ + static void test_get_events_good0(void **state) + { + struct test_data *datap = (struct test_data *)(*state); +@@ -534,6 +579,11 @@ static void test_get_events_good0(void **state) + assert_int_equal(VECTOR_SIZE(waiter->events), 0); + } + ++/* There are 5 dm devices. 4 of them are multipath devices. ++ * Only 3 of them are being watched. "foo" has a new event ++ * "xyzzy" gets removed. Nothing happens to bar. Verify ++ * that all the events are properly set, and that nothing ++ * happens with the two devices that aren't being watched */ + static void test_get_events_good1(void **state) + { + struct dev_event *dev_evt; +@@ -577,6 +627,8 @@ static void test_get_events_good1(void **state) + assert_int_equal(VECTOR_SIZE(waiter->events), 3); + } + ++/* poll does not return an event. nothing happens. The ++ * devices remain after this test */ + static void test_dmevent_loop_bad0(void **state) + { + struct dm_device *dev; +@@ -603,6 +655,7 @@ static void test_dmevent_loop_bad0(void **state) + assert_int_equal(dev->update_nr, 5); + } + ++/* arm_dm_event_poll's ioctl fails. Nothing happens */ + static void test_dmevent_loop_bad1(void **state) + { + struct dm_device *dev; +@@ -624,6 +677,7 @@ static void test_dmevent_loop_bad1(void **state) + assert_int_equal(dev->update_nr, 5); + } + ++/* dm_get_events fails. Nothing happens */ + static void test_dmevent_loop_bad2(void **state) + { + struct dm_device *dev; +@@ -646,6 +700,8 @@ static void test_dmevent_loop_bad2(void **state) + assert_int_equal(dev->update_nr, 5); + } + ++/* verify dmevent_loop runs successfully when no devices are being ++ * watched */ + static void test_dmevent_loop_good0(void **state) + { + struct test_data *datap = (struct test_data *)(*state); +@@ -663,6 +719,11 @@ static void test_dmevent_loop_good0(void **state) + assert_int_equal(dmevent_loop(), 1); + } + ++/* Watch 3 devices, where one device has an event (foo), one device is ++ * removed (xyzzy), and one device does nothing (bar). Verify that ++ * the device with the event gets updated, the device that is removed ++ * gets unwatched, and the device with no events stays the same. ++ * The devices remain after this test */ + static void test_dmevent_loop_good1(void **state) + { + struct dm_device *dev; +@@ -717,6 +778,10 @@ static void test_dmevent_loop_good1(void **state) + assert_ptr_equal(find_dm_device("xyzzy"), NULL); + } + ++/* watch another dm device and add events to two of them, so bar and ++ * baz have new events, and foo doesn't. Set update_multipath to ++ * fail for baz. Verify that baz is unwatched, bar is updated, and ++ * foo stays the same. */ + static void test_dmevent_loop_good2(void **state) + { + struct dm_device *dev; +@@ -762,6 +827,8 @@ static void test_dmevent_loop_good2(void **state) + assert_ptr_equal(find_dm_device("baz"), NULL); + } + ++/* remove dm device foo, and unwatch events on bar. Verify that ++ * foo is cleaned up and unwatched, and bar is no longer updated */ + static void test_dmevent_loop_good3(void **state) + { + struct dm_device *dev; +@@ -790,6 +857,8 @@ static void test_dmevent_loop_good3(void **state) + assert_ptr_equal(find_dm_device("foo"), NULL); + } + ++ ++/* verify that rearming the dmevents polling works */ + static void test_arm_poll(void **state) + { + struct test_data *datap = (struct test_data *)(*state); +@@ -799,6 +868,7 @@ static void test_arm_poll(void **state) + assert_int_equal(arm_dm_event_poll(waiter->fd), 0); + } + ++/* verify that the waiter is cleaned up */ + static void test_cleanup_waiter(void **state) + { + struct test_data *datap = (struct test_data *)(*state); +diff --git a/tests/util.c b/tests/util.c +index e9a004f..113b134 100644 +--- a/tests/util.c ++++ b/tests/util.c +@@ -74,6 +74,8 @@ static void test_basenamecpy_good5(void **state) + assert_string_equal(dst, "bar"); + } + ++/* multipath expects any trailing whitespace to be stripped off the basename, ++ * so that it will match pp->dev */ + static void test_basenamecpy_good6(void **state) + { + char dst[6]; +-- +2.7.4 + diff --git a/0002-multipath-fix-DEF_TIMEOUT-use.patch b/0002-multipath-fix-DEF_TIMEOUT-use.patch deleted file mode 100644 index 9df8ceb..0000000 --- a/0002-multipath-fix-DEF_TIMEOUT-use.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Thu, 18 Jan 2018 13:13:54 -0600 -Subject: [PATCH] multipath: fix DEF_TIMEOUT use - -DEF_TIMEOUT is specified in seconds. The io_hdr timeout is specified in -milliseconds, so we need to convert it. Multipath should be waiting -longer than 30 milliseconds here. If there are concerns that 30 seconds -may be too long, we could always make this configurable, using -conf->checker_timeout if set. - -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 4b31dde..f118800 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -766,7 +766,7 @@ do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op, - io_hdr.dxferp = resp; - io_hdr.cmdp = inqCmdBlk; - io_hdr.sbp = sense_b; -- io_hdr.timeout = DEF_TIMEOUT; -+ io_hdr.timeout = DEF_TIMEOUT * 1000; - - if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) - return -1; --- -2.7.4 - diff --git a/0003-multipathd-minor-dmevents-polling-code-cleanups.patch b/0003-multipathd-minor-dmevents-polling-code-cleanups.patch new file mode 100644 index 0000000..9503b55 --- /dev/null +++ b/0003-multipathd-minor-dmevents-polling-code-cleanups.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 29 Mar 2018 12:48:08 -0500 +Subject: [PATCH] multipathd: minor dmevents polling code cleanups + +Change strncpy to strlcpy and lock_cleanup_pop to pthread_cleanup_pop, +based on suggestions by Martin Wilck + +Cc: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + multipathd/dmevents.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/multipathd/dmevents.c b/multipathd/dmevents.c +index 0b0d0ce..e98a974 100644 +--- a/multipathd/dmevents.c ++++ b/multipathd/dmevents.c +@@ -24,6 +24,7 @@ + #include "debug.h" + #include "main.h" + #include "dmevents.h" ++#include "util.h" + + #ifndef DM_DEV_ARM_POLL + #define DM_DEV_ARM_POLL _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD + 1, struct dm_ioctl) +@@ -214,8 +215,7 @@ int watch_dmevents(char *name) + return -1; + } + +- strncpy(dev_evt->name, name, WWID_SIZE); +- dev_evt->name[WWID_SIZE - 1] = 0; ++ strlcpy(dev_evt->name, name, WWID_SIZE); + dev_evt->evt_nr = event_nr; + dev_evt->action = EVENT_NOTHING; + +@@ -350,7 +350,7 @@ static int dmevent_loop (void) + remove_map_by_alias(curr_dev.name, waiter->vecs, 1); + else + r = update_multipath(waiter->vecs, curr_dev.name, 1); +- lock_cleanup_pop(&waiter->vecs->lock); ++ pthread_cleanup_pop(1); + + if (r) { + condlog(2, "%s: stopped watching dmevents", +-- +2.7.4 + diff --git a/0003-multipathd-remove-coalesce_paths-from-ev_add_map.patch b/0003-multipathd-remove-coalesce_paths-from-ev_add_map.patch deleted file mode 100644 index b03576a..0000000 --- a/0003-multipathd-remove-coalesce_paths-from-ev_add_map.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Fri, 19 Jan 2018 22:35:26 -0600 -Subject: [PATCH] multipathd: remove coalesce_paths from ev_add_map - -If ev_add_map is called for a multipath device that doesn't exist in -device-mapper, it will call coalesce_paths to add it. This doesn't work -and hasn't for years. It doesn't add the map to the mpvec, or start up -waiters, or do any of the necessary things that do get done when you -call ev_add_map for a map that does exist in device mapper. - -Fortunately, there are only two things that call ev_add_map. uev_add_map -makes sure that the device does exist in device-mapper before calling -ev_add_map, and cli_add_map creates the device first and then calls -ev_add_map, if the device doesn't exist. - -So, there is no reason for coalesce_paths to be in ev_add_map. This -removes it. - -Signed-off-by: Benjamin Marzinski ---- - multipathd/main.c | 46 ++++++++++++++-------------------------------- - 1 file changed, 14 insertions(+), 32 deletions(-) - -diff --git a/multipathd/main.c b/multipathd/main.c -index 27cf234..dbf9890 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -412,18 +412,19 @@ uev_add_map (struct uevent * uev, struct vectors * vecs) - return rc; - } - -+/* -+ * ev_add_map expects that the multipath device already exists in kernel -+ * before it is called. It just adds a device to multipathd or updates an -+ * existing device. -+ */ - int - ev_add_map (char * dev, char * alias, struct vectors * vecs) - { -- char * refwwid; - struct multipath * mpp; -- int map_present; -- int r = 1, delayed_reconfig, reassign_maps; -+ int delayed_reconfig, reassign_maps; - struct config *conf; - -- map_present = dm_map_present(alias); -- -- if (map_present && !dm_is_mpath(alias)) { -+ if (!dm_is_mpath(alias)) { - condlog(4, "%s: not a multipath map", alias); - return 0; - } -@@ -468,33 +469,14 @@ ev_add_map (char * dev, char * alias, struct vectors * vecs) - /* - * now we can register the map - */ -- if (map_present) { -- if ((mpp = add_map_without_path(vecs, alias))) { -- sync_map_state(mpp); -- condlog(2, "%s: devmap %s registered", alias, dev); -- return 0; -- } else { -- condlog(2, "%s: uev_add_map failed", dev); -- return 1; -- } -- } -- r = get_refwwid(CMD_NONE, dev, DEV_DEVMAP, vecs->pathvec, &refwwid); -- -- if (refwwid) { -- r = coalesce_paths(vecs, NULL, refwwid, FORCE_RELOAD_NONE, -- CMD_NONE); -- dm_lib_release(); -+ if ((mpp = add_map_without_path(vecs, alias))) { -+ sync_map_state(mpp); -+ condlog(2, "%s: devmap %s registered", alias, dev); -+ return 0; -+ } else { -+ condlog(2, "%s: ev_add_map failed", dev); -+ return 1; - } -- -- if (!r) -- condlog(2, "%s: devmap %s added", alias, dev); -- else if (r == 2) -- condlog(2, "%s: uev_add_map %s blacklisted", alias, dev); -- else -- condlog(0, "%s: uev_add_map %s failed", alias, dev); -- -- FREE(refwwid); -- return r; - } - - static int --- -2.7.4 - diff --git a/0004-multipathd-remove-unneeded-function-parameter.patch b/0004-multipathd-remove-unneeded-function-parameter.patch new file mode 100644 index 0000000..708d2fc --- /dev/null +++ b/0004-multipathd-remove-unneeded-function-parameter.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 29 Mar 2018 14:01:30 -0500 +Subject: [PATCH] multipathd: remove unneeded function parameter + +remove_map_and_stop_waiter was always called with purge_vecs = 1, so +it can simply be removed, as suggested by Martin Wilck + +Cc: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + multipathd/main.c | 15 +++++++-------- + 1 file changed, 7 insertions(+), 8 deletions(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index 9a4f671..841d3e9 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -311,14 +311,13 @@ wait_for_events(struct multipath *mpp, struct vectors *vecs) + } + + static void +-remove_map_and_stop_waiter(struct multipath *mpp, struct vectors *vecs, +- int purge_vec) ++remove_map_and_stop_waiter(struct multipath *mpp, struct vectors *vecs) + { + /* devices are automatically removed by the dmevent polling code, + * so they don't need to be manually removed here */ + if (!poll_dmevents) + stop_waiter_thread(mpp, vecs); +- remove_map(mpp, vecs, purge_vec); ++ remove_map(mpp, vecs, PURGE_VEC); + } + + static void +@@ -400,7 +399,7 @@ int __setup_multipath(struct vectors *vecs, struct multipath *mpp, + + return 0; + out: +- remove_map_and_stop_waiter(mpp, vecs, PURGE_VEC); ++ remove_map_and_stop_waiter(mpp, vecs); + return 1; + } + +@@ -637,7 +636,7 @@ flush_map(struct multipath * mpp, struct vectors * vecs, int nopaths) + } + + orphan_paths(vecs->pathvec, mpp); +- remove_map_and_stop_waiter(mpp, vecs, 1); ++ remove_map_and_stop_waiter(mpp, vecs); + + return 0; + } +@@ -769,7 +768,7 @@ uev_remove_map (struct uevent * uev, struct vectors * vecs) + } + + orphan_paths(vecs->pathvec, mpp); +- remove_map_and_stop_waiter(mpp, vecs, 1); ++ remove_map_and_stop_waiter(mpp, vecs); + out: + lock_cleanup_pop(vecs->lock); + FREE(alias); +@@ -1154,7 +1153,7 @@ out: + return retval; + + fail: +- remove_map_and_stop_waiter(mpp, vecs, 1); ++ remove_map_and_stop_waiter(mpp, vecs); + return 1; + } + +@@ -1612,7 +1611,7 @@ mpvec_garbage_collector (struct vectors * vecs) + vector_foreach_slot (vecs->mpvec, mpp, i) { + if (mpp && mpp->alias && !dm_map_present(mpp->alias)) { + condlog(2, "%s: remove dead map", mpp->alias); +- remove_map_and_stop_waiter(mpp, vecs, 1); ++ remove_map_and_stop_waiter(mpp, vecs); + i--; + } + } +-- +2.7.4 + diff --git a/0004-multipathd-remove-unused-configure-parameter.patch b/0004-multipathd-remove-unused-configure-parameter.patch deleted file mode 100644 index d2a8b58..0000000 --- a/0004-multipathd-remove-unused-configure-parameter.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Fri, 2 Feb 2018 15:04:01 -0600 -Subject: [PATCH] multipathd: remove unused configure parameter - -configure() is always called with start_waiters=1, so there is no point -in having the parameter. Remove it. - -Signed-off-by: Benjamin Marzinski ---- - multipathd/main.c | 12 +++++------- - 1 file changed, 5 insertions(+), 7 deletions(-) - -diff --git a/multipathd/main.c b/multipathd/main.c -index dbf9890..51e0f5e 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -1955,7 +1955,7 @@ checkerloop (void *ap) - } - - int --configure (struct vectors * vecs, int start_waiters) -+configure (struct vectors * vecs) - { - struct multipath * mpp; - struct path * pp; -@@ -2054,11 +2054,9 @@ configure (struct vectors * vecs, int start_waiters) - i--; - continue; - } -- if (start_waiters) { -- if (start_waiter_thread(mpp, vecs)) { -- remove_map(mpp, vecs, 1); -- i--; -- } -+ if (start_waiter_thread(mpp, vecs)) { -+ remove_map(mpp, vecs, 1); -+ i--; - } - } - return 0; -@@ -2125,7 +2123,7 @@ reconfigure (struct vectors * vecs) - rcu_assign_pointer(multipath_conf, conf); - call_rcu(&old->rcu, rcu_free_config); - -- configure(vecs, 1); -+ configure(vecs); - - - return 0; --- -2.7.4 - diff --git a/0005-Fix-set_no_path_retry-regression.patch b/0005-Fix-set_no_path_retry-regression.patch deleted file mode 100644 index 1cf6f09..0000000 --- a/0005-Fix-set_no_path_retry-regression.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Tue, 6 Feb 2018 20:53:17 -0600 -Subject: [PATCH] Fix set_no_path_retry() regression - -commit 0f850db7fceb6b2bf4968f3831efd250c17c6138 "multipathd: clean up -set_no_path_retry" has a bug in it. It made set_no_path_retry -never reset mpp->retry_ticks, even if the device was in recovery mode, -and there were valid paths. This meant that adding new paths didn't -remove a device from recovery mode, and queueing could get disabled, -even while there were valid paths. This patch fixes that. - -This patch also fixes a bug in cli_restore_queueing() and -cli_restore_all_queueing(), where a device that had no_path_retry -set to "queue" would enter recovery mode (although queueing would -never actually get disabled). - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/structs_vec.c | 5 +++-- - multipathd/cli_handlers.c | 20 ++++++++++++-------- - 2 files changed, 15 insertions(+), 10 deletions(-) - -diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c -index fbab61f..0de2221 100644 ---- a/libmultipath/structs_vec.c -+++ b/libmultipath/structs_vec.c -@@ -343,9 +343,10 @@ static void set_no_path_retry(struct multipath *mpp) - dm_queue_if_no_path(mpp->alias, 1); - break; - default: -- if (mpp->nr_active > 0) -+ if (mpp->nr_active > 0) { -+ mpp->retry_tick = 0; - dm_queue_if_no_path(mpp->alias, 1); -- else if (is_queueing && mpp->retry_tick == 0) -+ } else if (is_queueing && mpp->retry_tick == 0) - enter_recovery_mode(mpp); - break; - } -diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c -index 7f13bc9..80519b1 100644 ---- a/multipathd/cli_handlers.c -+++ b/multipathd/cli_handlers.c -@@ -995,10 +995,12 @@ cli_restore_queueing(void *v, char **reply, int *len, void *data) - if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF && - mpp->no_path_retry != NO_PATH_RETRY_FAIL) { - dm_queue_if_no_path(mpp->alias, 1); -- if (mpp->nr_active > 0) -- mpp->retry_tick = 0; -- else -- enter_recovery_mode(mpp); -+ if (mpp->no_path_retry > 0) { -+ if (mpp->nr_active > 0) -+ mpp->retry_tick = 0; -+ else -+ enter_recovery_mode(mpp); -+ } - } - return 0; - } -@@ -1019,10 +1021,12 @@ cli_restore_all_queueing(void *v, char **reply, int *len, void *data) - if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF && - mpp->no_path_retry != NO_PATH_RETRY_FAIL) { - dm_queue_if_no_path(mpp->alias, 1); -- if (mpp->nr_active > 0) -- mpp->retry_tick = 0; -- else -- enter_recovery_mode(mpp); -+ if (mpp->no_path_retry > 0) { -+ if (mpp->nr_active > 0) -+ mpp->retry_tick = 0; -+ else -+ enter_recovery_mode(mpp); -+ } - } - } - return 0; --- -2.7.4 - diff --git a/0005-mpathcmd-fix-libmpathcmd-license.patch b/0005-mpathcmd-fix-libmpathcmd-license.patch new file mode 100644 index 0000000..652c8c2 --- /dev/null +++ b/0005-mpathcmd-fix-libmpathcmd-license.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 29 Mar 2018 15:00:12 -0500 +Subject: [PATCH] mpathcmd: fix libmpathcmd license + +There is no version 2 of the GNU Lesser General Public License, so +change the license header to version 2.1, which does exist. Also copy +the license header to mpath_cmd.c. + +Signed-off-by: Benjamin Marzinski +--- + libmpathcmd/mpath_cmd.c | 19 +++++++++++++++++++ + libmpathcmd/mpath_cmd.h | 2 +- + 2 files changed, 20 insertions(+), 1 deletion(-) + +diff --git a/libmpathcmd/mpath_cmd.c b/libmpathcmd/mpath_cmd.c +index 29d148c..61e6a98 100644 +--- a/libmpathcmd/mpath_cmd.c ++++ b/libmpathcmd/mpath_cmd.c +@@ -1,3 +1,22 @@ ++/* ++ * Copyright (C) 2015 Red Hat, Inc. ++ * ++ * This file is part of the device-mapper multipath userspace tools. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public License ++ * as published by the Free Software Foundation; either version 2.1 ++ * 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 Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this program. If not, see . ++ */ ++ + #include + #include + #include +diff --git a/libmpathcmd/mpath_cmd.h b/libmpathcmd/mpath_cmd.h +index b57b708..aaa8da9 100644 +--- a/libmpathcmd/mpath_cmd.h ++++ b/libmpathcmd/mpath_cmd.h +@@ -5,7 +5,7 @@ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License +- * as published by the Free Software Foundation; either version 2 ++ * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, +-- +2.7.4 + diff --git a/0006-libmultipath-don-t-print-undefined-values.patch b/0006-libmultipath-don-t-print-undefined-values.patch new file mode 100644 index 0000000..bd40be0 --- /dev/null +++ b/0006-libmultipath-don-t-print-undefined-values.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 29 Mar 2018 18:26:12 -0500 +Subject: [PATCH] libmultipath: don't print undefined values + +commit 48e9fd9f ("libmultipath: parser: use call-by-value for "snprint" +methods") removed some of the code that checked for undefined values to +avoid printing them. This lead to device configurations that printed +out values for parameters that they hadn't configured. This patch adds +that code back in. + +Fixes: 48e9fd9f ("libmultipath: parser: use call-by-value for "snprint" methods") +Cc: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/dict.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/libmultipath/dict.c b/libmultipath/dict.c +index ac9216c..1a18337 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -101,12 +101,16 @@ print_int (char *buff, int len, long v) + static int + print_nonzero (char *buff, int len, long v) + { ++ if (!v) ++ return 0; + return snprintf(buff, len, "%li", v); + } + + static int + print_str (char *buff, int len, const char *ptr) + { ++ if (!ptr) ++ return 0; + return snprintf(buff, len, "\"%s\"", ptr); + } + +@@ -120,6 +124,8 @@ print_yes_no (char *buff, int len, long v) + static int + print_yes_no_undef (char *buff, int len, long v) + { ++ if (!v) ++ return 0; + return snprintf(buff, len, "\"%s\"", + (v == YNU_NO)? "no" : "yes"); + } +@@ -665,6 +671,8 @@ set_dev_loss(vector strvec, void *ptr) + int + print_dev_loss(char * buff, int len, unsigned long v) + { ++ if (!v) ++ return 0; + if (v >= MAX_DEV_LOSS_TMO) + return snprintf(buff, len, "\"infinity\""); + return snprintf(buff, len, "%lu", v); +-- +2.7.4 + diff --git a/0006-multipathd-change-spurious-uevent-msg-priority.patch b/0006-multipathd-change-spurious-uevent-msg-priority.patch deleted file mode 100644 index 1e53803..0000000 --- a/0006-multipathd-change-spurious-uevent-msg-priority.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Wed, 7 Feb 2018 14:20:11 -0600 -Subject: [PATCH] multipathd: change spurious uevent msg priority - -The "spurious uevent, path already in pathvec" is not anything to worry -about, so it should not have the error priority. - -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 51e0f5e..7ac59d9 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -562,7 +562,7 @@ uev_add_path (struct uevent *uev, struct vectors * vecs, int need_do_map) - if (pp) { - int r; - -- condlog(0, "%s: spurious uevent, path already in pathvec", -+ condlog(2, "%s: spurious uevent, path already in pathvec", - uev->kernel); - if (!pp->mpp && !strlen(pp->wwid)) { - condlog(3, "%s: reinitialize path", uev->kernel); --- -2.7.4 - diff --git a/0015-RH-fixup-udev-rules-for-redhat.patch b/0007-RH-fixup-udev-rules-for-redhat.patch similarity index 96% rename from 0015-RH-fixup-udev-rules-for-redhat.patch rename to 0007-RH-fixup-udev-rules-for-redhat.patch index d9e33c7..24a70f5 100644 --- a/0015-RH-fixup-udev-rules-for-redhat.patch +++ b/0007-RH-fixup-udev-rules-for-redhat.patch @@ -15,10 +15,10 @@ Signed-off-by: Benjamin Marzinski 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile.inc b/Makefile.inc -index d953f5e..5145909 100644 +index 57a1835..f589ab0 100644 --- a/Makefile.inc +++ b/Makefile.inc -@@ -48,7 +48,7 @@ endif +@@ -51,7 +51,7 @@ endif prefix = exec_prefix = $(prefix) usr_prefix = $(prefix) @@ -40,7 +40,7 @@ index 8f99049..8a3a171 100644 LABEL="kpartx_end" diff --git a/multipath/Makefile b/multipath/Makefile -index 468c056..dda5565 100644 +index 0828a8f..b9bbb3c 100644 --- a/multipath/Makefile +++ b/multipath/Makefile @@ -24,7 +24,7 @@ install: diff --git a/0007-multipath-print-sysfs-state-in-fast-list-mode.patch b/0007-multipath-print-sysfs-state-in-fast-list-mode.patch deleted file mode 100644 index 890793c..0000000 --- a/0007-multipath-print-sysfs-state-in-fast-list-mode.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Wed, 7 Feb 2018 16:06:06 -0600 -Subject: [PATCH] multipath: print sysfs state in fast list mode - -commit b123e711ea2a4b471a98ff5e26815df3773636b5 "libmultipath: cleanup -orphan device states" stopped multipathd from showing old state for -orphan paths by checking if pp->mpp was set, and only printing the state -if it was. Unfortunately, when "multipath -l" is run, pp->mpp isn't -set. While the checker state isn't checked and shouldn't be printed with -"-l", the sysfs state can be, and was before b123e711. This patch sets -pp->mpp in fast list mode, so that the sysfs state gets printed. It -also verifies that the path exists in sysfs, and if not, marks it as -faulty. - -Signed-off-by: Benjamin Marzinski ---- - multipath/main.c | 10 +++++++--- - 1 file changed, 7 insertions(+), 3 deletions(-) - -diff --git a/multipath/main.c b/multipath/main.c -index bffe065..d2415a9 100644 ---- a/multipath/main.c -+++ b/multipath/main.c -@@ -149,7 +149,7 @@ usage (char * progname) - } - - static int --update_paths (struct multipath * mpp) -+update_paths (struct multipath * mpp, int quick) - { - int i, j; - struct pathgroup * pgp; -@@ -171,9 +171,12 @@ update_paths (struct multipath * mpp) - * path is not in sysfs anymore - */ - pp->chkrstate = pp->state = PATH_DOWN; -+ pp->offline = 1; - continue; - } - pp->mpp = mpp; -+ if (quick) -+ continue; - conf = get_multipath_config(); - if (pathinfo(pp, conf, DI_ALL)) - pp->state = PATH_UNCHECKED; -@@ -181,6 +184,8 @@ update_paths (struct multipath * mpp) - continue; - } - pp->mpp = mpp; -+ if (quick) -+ continue; - if (pp->state == PATH_UNCHECKED || - pp->state == PATH_WILD) { - conf = get_multipath_config(); -@@ -238,8 +243,7 @@ get_dm_mpvec (enum mpath_cmds cmd, vector curmp, vector pathvec, char * refwwid) - * If not in "fast list mode", we need to fetch information - * about them - */ -- if (cmd != CMD_LIST_SHORT) -- update_paths(mpp); -+ update_paths(mpp, (cmd == CMD_LIST_SHORT)); - - if (cmd == CMD_LIST_LONG) - mpp->bestpg = select_path_group(mpp); --- -2.7.4 - diff --git a/0016-RH-Remove-the-property-blacklist-exception-builtin.patch b/0008-RH-Remove-the-property-blacklist-exception-builtin.patch similarity index 96% rename from 0016-RH-Remove-the-property-blacklist-exception-builtin.patch rename to 0008-RH-Remove-the-property-blacklist-exception-builtin.patch index d52d3fa..fb48502 100644 --- a/0016-RH-Remove-the-property-blacklist-exception-builtin.patch +++ b/0008-RH-Remove-the-property-blacklist-exception-builtin.patch @@ -51,10 +51,10 @@ index ee396e2..19d4697 100644 void diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 -index ab151e7..2201d7f 100644 +index c4d0789..f046a54 100644 --- a/multipath/multipath.conf.5 +++ b/multipath/multipath.conf.5 -@@ -1114,10 +1114,6 @@ The \fIWorld Wide Identification\fR of a device. +@@ -1131,10 +1131,6 @@ The \fIWorld Wide Identification\fR of a device. .TP .B property Regular expression of the udev property to be whitelisted. diff --git a/0008-libmultipath-move-remove_map-waiter-code-to-multipat.patch b/0008-libmultipath-move-remove_map-waiter-code-to-multipat.patch deleted file mode 100644 index 314b7c0..0000000 --- a/0008-libmultipath-move-remove_map-waiter-code-to-multipat.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Mon, 5 Feb 2018 16:07:36 -0600 -Subject: [PATCH] libmultipath: move remove_map waiter code to multipathd - -Only multipathd needs to worry about the multipath waiter code. There is -no point in having remove_map_and_stop_waiter() or -remove_maps_and_stop_waiters() in libmultipath, since they should never -be use outside of multipathd. - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/structs_vec.c | 40 +++++----------------------------------- - libmultipath/structs_vec.h | 2 -- - multipathd/main.c | 23 +++++++++++++++++++++++ - 3 files changed, 28 insertions(+), 37 deletions(-) - -diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c -index 0de2221..abf5327 100644 ---- a/libmultipath/structs_vec.c -+++ b/libmultipath/structs_vec.c -@@ -116,25 +116,16 @@ set_multipath_wwid (struct multipath * mpp) - dm_get_uuid(mpp->alias, mpp->wwid); - } - --#define KEEP_WAITER 0 --#define STOP_WAITER 1 - #define PURGE_VEC 1 - --static void --_remove_map (struct multipath * mpp, struct vectors * vecs, -- int stop_waiter, int purge_vec) -+void -+remove_map(struct multipath * mpp, struct vectors * vecs, int purge_vec) - { - int i; - - condlog(4, "%s: remove multipath map", mpp->alias); - - /* -- * stop the DM event waiter thread -- */ -- if (stop_waiter) -- stop_waiter_thread(mpp, vecs); -- -- /* - * clear references to this map - */ - orphan_paths(vecs->pathvec, mpp); -@@ -149,19 +140,8 @@ _remove_map (struct multipath * mpp, struct vectors * vecs, - free_multipath(mpp, KEEP_PATHS); - } - --void remove_map(struct multipath *mpp, struct vectors *vecs, int purge_vec) --{ -- _remove_map(mpp, vecs, KEEP_WAITER, purge_vec); --} -- --void remove_map_and_stop_waiter(struct multipath *mpp, struct vectors *vecs, -- int purge_vec) --{ -- _remove_map(mpp, vecs, STOP_WAITER, purge_vec); --} -- --static void --_remove_maps (struct vectors * vecs, int stop_waiter) -+void -+remove_maps(struct vectors * vecs) - { - int i; - struct multipath * mpp; -@@ -170,7 +150,7 @@ _remove_maps (struct vectors * vecs, int stop_waiter) - return; - - vector_foreach_slot (vecs->mpvec, mpp, i) { -- _remove_map(mpp, vecs, stop_waiter, 1); -+ remove_map(mpp, vecs, 1); - i--; - } - -@@ -178,16 +158,6 @@ _remove_maps (struct vectors * vecs, int stop_waiter) - vecs->mpvec = NULL; - } - --void remove_maps(struct vectors *vecs) --{ -- _remove_maps(vecs, KEEP_WAITER); --} -- --void remove_maps_and_stop_waiters(struct vectors *vecs) --{ -- _remove_maps(vecs, STOP_WAITER); --} -- - void - extract_hwe_from_path(struct multipath * mpp) - { -diff --git a/libmultipath/structs_vec.h b/libmultipath/structs_vec.h -index b81413b..d6e17bb 100644 ---- a/libmultipath/structs_vec.h -+++ b/libmultipath/structs_vec.h -@@ -27,9 +27,7 @@ int update_multipath_strings (struct multipath *mpp, vector pathvec, - void extract_hwe_from_path(struct multipath * mpp); - - void remove_map (struct multipath * mpp, struct vectors * vecs, int purge_vec); --void remove_map_and_stop_waiter (struct multipath * mpp, struct vectors * vecs, int purge_vec); - void remove_maps (struct vectors * vecs); --void remove_maps_and_stop_waiters (struct vectors * vecs); - - void sync_map_state (struct multipath *); - int update_map (struct multipath *mpp, struct vectors *vecs); -diff --git a/multipathd/main.c b/multipathd/main.c -index 7ac59d9..72c3c2f 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -288,6 +288,29 @@ switch_pathgroup (struct multipath * mpp) - mpp->alias, mpp->bestpg); - } - -+static void -+remove_map_and_stop_waiter(struct multipath *mpp, struct vectors *vecs, -+ int purge_vec) -+{ -+ stop_waiter_thread(mpp, vecs); -+ remove_map(mpp, vecs, purge_vec); -+} -+ -+static void -+remove_maps_and_stop_waiters(struct vectors *vecs) -+{ -+ int i; -+ struct multipath * mpp; -+ -+ if (!vecs) -+ return; -+ -+ vector_foreach_slot(vecs->mpvec, mpp, i) -+ stop_waiter_thread(mpp, vecs); -+ -+ remove_maps(vecs); -+} -+ - static int - coalesce_maps(struct vectors *vecs, vector nmpv) - { --- -2.7.4 - diff --git a/0017-RH-don-t-start-without-a-config-file.patch b/0009-RH-don-t-start-without-a-config-file.patch similarity index 94% rename from 0017-RH-don-t-start-without-a-config-file.patch rename to 0009-RH-don-t-start-without-a-config-file.patch index 55f1f57..4f10ad6 100644 --- a/0017-RH-don-t-start-without-a-config-file.patch +++ b/0009-RH-don-t-start-without-a-config-file.patch @@ -20,7 +20,7 @@ Signed-off-by: Benjamin Marzinski 5 files changed, 20 insertions(+) diff --git a/libmultipath/config.c b/libmultipath/config.c -index 3d6a24c..27826fa 100644 +index 085a3e1..83d26be 100644 --- a/libmultipath/config.c +++ b/libmultipath/config.c @@ -26,6 +26,7 @@ @@ -53,7 +53,7 @@ index 3d6a24c..27826fa 100644 conf->processed_main_config = 1; diff --git a/libmultipath/config.h b/libmultipath/config.h -index a20ac2a..21a3bbd 100644 +index 329f3ed..bc34eb7 100644 --- a/libmultipath/config.h +++ b/libmultipath/config.h @@ -9,6 +9,7 @@ @@ -65,7 +65,7 @@ index a20ac2a..21a3bbd 100644 /* * In kernel, fast_io_fail == 0 means immediate failure on rport delete. diff --git a/multipath/multipath.rules b/multipath/multipath.rules -index bc1a852..2bc0348 100644 +index 6f8ee2b..d1a484e 100644 --- a/multipath/multipath.rules +++ b/multipath/multipath.rules @@ -7,6 +7,7 @@ IMPORT{cmdline}="nompath" @@ -90,11 +90,11 @@ index 5c96680..0515211 100644 . .\" ---------------------------------------------------------------------------- diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service -index fd66cf6..fafd088 100644 +index ba24983..17434ce 100644 --- a/multipathd/multipathd.service +++ b/multipathd/multipathd.service @@ -4,6 +4,7 @@ Wants=systemd-udev-trigger.service systemd-udev-settle.service - Before=iscsi.service iscsid.service lvm2-lvmetad.service lvm2-activation-early.service + Before=iscsi.service iscsid.service lvm2-activation-early.service Before=local-fs-pre.target blk-availability.service After=multipathd.socket systemd-udev-trigger.service systemd-udev-settle.service +ConditionPathExists=/etc/multipath.conf diff --git a/0009-move-waiter-code-from-libmultipath-to-multipathd.patch b/0009-move-waiter-code-from-libmultipath-to-multipathd.patch deleted file mode 100644 index 4012267..0000000 --- a/0009-move-waiter-code-from-libmultipath-to-multipathd.patch +++ /dev/null @@ -1,793 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Mon, 5 Feb 2018 18:50:45 -0600 -Subject: [PATCH] move waiter code from libmultipath to multipathd - -Only multipathd uses the code in waiter.[ch] and the functions that call -it directly, so they should all live in the multipathd directory. This -patch is simply moving the waiter.[ch] files and the functions in -structs_vec that use them. None of the moved code has been changed. - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/Makefile | 2 +- - libmultipath/structs_vec.c | 98 --------------------- - libmultipath/structs_vec.h | 4 +- - libmultipath/waiter.c | 215 --------------------------------------------- - libmultipath/waiter.h | 17 ---- - multipathd/Makefile | 2 +- - multipathd/main.c | 96 ++++++++++++++++++++ - multipathd/waiter.c | 215 +++++++++++++++++++++++++++++++++++++++++++++ - multipathd/waiter.h | 17 ++++ - 9 files changed, 332 insertions(+), 334 deletions(-) - delete mode 100644 libmultipath/waiter.c - delete mode 100644 libmultipath/waiter.h - create mode 100644 multipathd/waiter.c - create mode 100644 multipathd/waiter.h - -diff --git a/libmultipath/Makefile b/libmultipath/Makefile -index 6447d8d..a1005b2 100644 ---- a/libmultipath/Makefile -+++ b/libmultipath/Makefile -@@ -42,7 +42,7 @@ OBJS = memory.o parser.o vector.o devmapper.o callout.o \ - pgpolicies.o debug.o defaults.o uevent.o time-util.o \ - switchgroup.o uxsock.o print.o alias.o log_pthread.o \ - log.o configure.o structs_vec.o sysfs.o prio.o checkers.o \ -- lock.o waiter.o file.o wwids.o prioritizers/alua_rtpg.o prkey.o \ -+ lock.o file.o wwids.o prioritizers/alua_rtpg.o prkey.o \ - io_err_stat.o - - all: $(LIBS) -diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c -index abf5327..77b045b 100644 ---- a/libmultipath/structs_vec.c -+++ b/libmultipath/structs_vec.c -@@ -10,7 +10,6 @@ - #include "structs.h" - #include "structs_vec.h" - #include "sysfs.h" --#include "waiter.h" - #include "devmapper.h" - #include "dmparser.h" - #include "propsel.h" -@@ -107,17 +106,6 @@ void orphan_paths(vector pathvec, struct multipath *mpp) - } - } - --static void --set_multipath_wwid (struct multipath * mpp) --{ -- if (strlen(mpp->wwid)) -- return; -- -- dm_get_uuid(mpp->alias, mpp->wwid); --} -- --#define PURGE_VEC 1 -- - void - remove_map(struct multipath * mpp, struct vectors * vecs, int purge_vec) - { -@@ -379,92 +367,6 @@ sync_map_state(struct multipath *mpp) - } - } - --int --update_map (struct multipath *mpp, struct vectors *vecs) --{ -- int retries = 3; -- char params[PARAMS_SIZE] = {0}; -- --retry: -- condlog(4, "%s: updating new map", mpp->alias); -- if (adopt_paths(vecs->pathvec, mpp)) { -- condlog(0, "%s: failed to adopt paths for new map update", -- mpp->alias); -- retries = -1; -- goto fail; -- } -- verify_paths(mpp, vecs); -- mpp->action = ACT_RELOAD; -- -- extract_hwe_from_path(mpp); -- if (setup_map(mpp, params, PARAMS_SIZE)) { -- condlog(0, "%s: failed to setup new map in update", mpp->alias); -- retries = -1; -- goto fail; -- } -- if (domap(mpp, params, 1) <= 0 && retries-- > 0) { -- condlog(0, "%s: map_udate sleep", mpp->alias); -- sleep(1); -- goto retry; -- } -- dm_lib_release(); -- --fail: -- if (setup_multipath(vecs, mpp)) -- return 1; -- -- sync_map_state(mpp); -- -- if (retries < 0) -- condlog(0, "%s: failed reload in new map update", mpp->alias); -- return 0; --} -- --struct multipath *add_map_without_path (struct vectors *vecs, char *alias) --{ -- struct multipath * mpp = alloc_multipath(); -- struct config *conf; -- -- if (!mpp) -- return NULL; -- if (!alias) { -- FREE(mpp); -- return NULL; -- } -- -- mpp->alias = STRDUP(alias); -- -- if (dm_get_info(mpp->alias, &mpp->dmi)) { -- condlog(3, "%s: cannot access table", mpp->alias); -- goto out; -- } -- set_multipath_wwid(mpp); -- conf = get_multipath_config(); -- mpp->mpe = find_mpe(conf->mptable, mpp->wwid); -- put_multipath_config(conf); -- -- if (update_multipath_table(mpp, vecs->pathvec, 1)) -- goto out; -- if (update_multipath_status(mpp)) -- goto out; -- -- if (!vector_alloc_slot(vecs->mpvec)) -- goto out; -- -- vector_set_slot(vecs->mpvec, mpp); -- -- if (update_map(mpp, vecs) != 0) /* map removed */ -- return NULL; -- -- if (start_waiter_thread(mpp, vecs)) -- goto out; -- -- return mpp; --out: -- remove_map(mpp, vecs, PURGE_VEC); -- return NULL; --} -- - static void - find_existing_alias (struct multipath * mpp, - struct vectors *vecs) -diff --git a/libmultipath/structs_vec.h b/libmultipath/structs_vec.h -index d6e17bb..ceab6d9 100644 ---- a/libmultipath/structs_vec.h -+++ b/libmultipath/structs_vec.h -@@ -26,12 +26,12 @@ int update_multipath_strings (struct multipath *mpp, vector pathvec, - int is_daemon); - void extract_hwe_from_path(struct multipath * mpp); - -+#define PURGE_VEC 1 -+ - void remove_map (struct multipath * mpp, struct vectors * vecs, int purge_vec); - void remove_maps (struct vectors * vecs); - - void sync_map_state (struct multipath *); --int update_map (struct multipath *mpp, struct vectors *vecs); --struct multipath * add_map_without_path (struct vectors * vecs, char * alias); - struct multipath * add_map_with_path (struct vectors * vecs, - struct path * pp, int add_vec); - int update_multipath (struct vectors *vecs, char *mapname, int reset); -diff --git a/libmultipath/waiter.c b/libmultipath/waiter.c -deleted file mode 100644 -index cb9708b..0000000 ---- a/libmultipath/waiter.c -+++ /dev/null -@@ -1,215 +0,0 @@ --/* -- * Copyright (c) 2004, 2005 Christophe Varoqui -- * Copyright (c) 2005 Kiyoshi Ueda, NEC -- * Copyright (c) 2005 Benjamin Marzinski, Redhat -- * Copyright (c) 2005 Edward Goggin, EMC -- */ --#include --#include --#include --#include --#include --#include -- --#include "vector.h" --#include "memory.h" --#include "checkers.h" --#include "config.h" --#include "structs.h" --#include "structs_vec.h" --#include "devmapper.h" --#include "debug.h" --#include "lock.h" --#include "waiter.h" -- --pthread_attr_t waiter_attr; -- --static struct event_thread *alloc_waiter (void) --{ -- -- struct event_thread *wp; -- -- wp = (struct event_thread *)MALLOC(sizeof(struct event_thread)); -- memset(wp, 0, sizeof(struct event_thread)); -- -- return wp; --} -- --static void free_waiter (void *data) --{ -- struct event_thread *wp = (struct event_thread *)data; -- -- if (wp->dmt) -- dm_task_destroy(wp->dmt); -- -- rcu_unregister_thread(); -- FREE(wp); --} -- --void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs) --{ -- pthread_t thread; -- -- if (mpp->waiter == (pthread_t)0) { -- condlog(3, "%s: event checker thread already stopped", -- mpp->alias); -- return; -- } -- condlog(2, "%s: stop event checker thread (%lu)", mpp->alias, -- mpp->waiter); -- thread = mpp->waiter; -- mpp->waiter = (pthread_t)0; -- pthread_cancel(thread); -- pthread_kill(thread, SIGUSR2); --} -- --/* -- * returns the reschedule delay -- * negative means *stop* -- */ --static int waiteventloop (struct event_thread *waiter) --{ -- sigset_t set, oldset; -- int event_nr; -- int r; -- -- if (!waiter->event_nr) -- waiter->event_nr = dm_geteventnr(waiter->mapname); -- -- if (!(waiter->dmt = libmp_dm_task_create(DM_DEVICE_WAITEVENT))) { -- condlog(0, "%s: devmap event #%i dm_task_create error", -- waiter->mapname, waiter->event_nr); -- return 1; -- } -- -- if (!dm_task_set_name(waiter->dmt, waiter->mapname)) { -- condlog(0, "%s: devmap event #%i dm_task_set_name error", -- waiter->mapname, waiter->event_nr); -- dm_task_destroy(waiter->dmt); -- waiter->dmt = NULL; -- return 1; -- } -- -- if (waiter->event_nr && !dm_task_set_event_nr(waiter->dmt, -- waiter->event_nr)) { -- condlog(0, "%s: devmap event #%i dm_task_set_event_nr error", -- waiter->mapname, waiter->event_nr); -- dm_task_destroy(waiter->dmt); -- waiter->dmt = NULL; -- return 1; -- } -- -- dm_task_no_open_count(waiter->dmt); -- -- /* wait */ -- sigemptyset(&set); -- sigaddset(&set, SIGUSR2); -- pthread_sigmask(SIG_UNBLOCK, &set, &oldset); -- -- pthread_testcancel(); -- r = dm_task_run(waiter->dmt); -- pthread_testcancel(); -- -- pthread_sigmask(SIG_SETMASK, &oldset, NULL); -- dm_task_destroy(waiter->dmt); -- waiter->dmt = NULL; -- -- if (!r) /* wait interrupted by signal */ -- return -1; -- -- waiter->event_nr++; -- -- /* -- * upon event ... -- */ -- while (1) { -- condlog(3, "%s: devmap event #%i", -- waiter->mapname, waiter->event_nr); -- -- /* -- * event might be : -- * -- * 1) a table reload, which means our mpp structure is -- * obsolete : refresh it through update_multipath() -- * 2) a path failed by DM : mark as such through -- * update_multipath() -- * 3) map has gone away : stop the thread. -- * 4) a path reinstate : nothing to do -- * 5) a switch group : nothing to do -- */ -- pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock); -- lock(&waiter->vecs->lock); -- pthread_testcancel(); -- r = update_multipath(waiter->vecs, waiter->mapname, 1); -- lock_cleanup_pop(waiter->vecs->lock); -- -- if (r) { -- condlog(2, "%s: event checker exit", -- waiter->mapname); -- return -1; /* stop the thread */ -- } -- -- event_nr = dm_geteventnr(waiter->mapname); -- -- if (waiter->event_nr == event_nr) -- return 1; /* upon problem reschedule 1s later */ -- -- waiter->event_nr = event_nr; -- } -- return -1; /* never reach there */ --} -- --static void *waitevent (void *et) --{ -- int r; -- struct event_thread *waiter; -- -- mlockall(MCL_CURRENT | MCL_FUTURE); -- -- waiter = (struct event_thread *)et; -- pthread_cleanup_push(free_waiter, et); -- -- rcu_register_thread(); -- while (1) { -- r = waiteventloop(waiter); -- -- if (r < 0) -- break; -- -- sleep(r); -- } -- -- pthread_cleanup_pop(1); -- return NULL; --} -- --int start_waiter_thread (struct multipath *mpp, struct vectors *vecs) --{ -- struct event_thread *wp; -- -- if (!mpp) -- return 0; -- -- wp = alloc_waiter(); -- -- if (!wp) -- goto out; -- -- strncpy(wp->mapname, mpp->alias, WWID_SIZE - 1); -- wp->vecs = vecs; -- -- if (pthread_create(&wp->thread, &waiter_attr, waitevent, wp)) { -- condlog(0, "%s: cannot create event checker", wp->mapname); -- goto out1; -- } -- mpp->waiter = wp->thread; -- condlog(2, "%s: event checker started", wp->mapname); -- -- return 0; --out1: -- free_waiter(wp); -- mpp->waiter = (pthread_t)0; --out: -- condlog(0, "failed to start waiter thread"); -- return 1; --} -diff --git a/libmultipath/waiter.h b/libmultipath/waiter.h -deleted file mode 100644 -index 0cfae46..0000000 ---- a/libmultipath/waiter.h -+++ /dev/null -@@ -1,17 +0,0 @@ --#ifndef _WAITER_H --#define _WAITER_H -- --extern pthread_attr_t waiter_attr; -- --struct event_thread { -- struct dm_task *dmt; -- pthread_t thread; -- int event_nr; -- char mapname[WWID_SIZE]; -- struct vectors *vecs; --}; -- --void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs); --int start_waiter_thread (struct multipath *mpp, struct vectors *vecs); -- --#endif /* _WAITER_H */ -diff --git a/multipathd/Makefile b/multipathd/Makefile -index e6f140b..85f29a7 100644 ---- a/multipathd/Makefile -+++ b/multipathd/Makefile -@@ -22,7 +22,7 @@ ifdef SYSTEMD - endif - endif - --OBJS = main.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o -+OBJS = main.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o waiter.o - - EXEC = multipathd - -diff --git a/multipathd/main.c b/multipathd/main.c -index 72c3c2f..94b2406 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -311,6 +311,102 @@ remove_maps_and_stop_waiters(struct vectors *vecs) - remove_maps(vecs); - } - -+static void -+set_multipath_wwid (struct multipath * mpp) -+{ -+ if (strlen(mpp->wwid)) -+ return; -+ -+ dm_get_uuid(mpp->alias, mpp->wwid); -+} -+ -+static int -+update_map (struct multipath *mpp, struct vectors *vecs) -+{ -+ int retries = 3; -+ char params[PARAMS_SIZE] = {0}; -+ -+retry: -+ condlog(4, "%s: updating new map", mpp->alias); -+ if (adopt_paths(vecs->pathvec, mpp)) { -+ condlog(0, "%s: failed to adopt paths for new map update", -+ mpp->alias); -+ retries = -1; -+ goto fail; -+ } -+ verify_paths(mpp, vecs); -+ mpp->action = ACT_RELOAD; -+ -+ extract_hwe_from_path(mpp); -+ if (setup_map(mpp, params, PARAMS_SIZE)) { -+ condlog(0, "%s: failed to setup new map in update", mpp->alias); -+ retries = -1; -+ goto fail; -+ } -+ if (domap(mpp, params, 1) <= 0 && retries-- > 0) { -+ condlog(0, "%s: map_udate sleep", mpp->alias); -+ sleep(1); -+ goto retry; -+ } -+ dm_lib_release(); -+ -+fail: -+ if (setup_multipath(vecs, mpp)) -+ return 1; -+ -+ sync_map_state(mpp); -+ -+ if (retries < 0) -+ condlog(0, "%s: failed reload in new map update", mpp->alias); -+ return 0; -+} -+ -+static struct multipath * -+add_map_without_path (struct vectors *vecs, char *alias) -+{ -+ struct multipath * mpp = alloc_multipath(); -+ struct config *conf; -+ -+ if (!mpp) -+ return NULL; -+ if (!alias) { -+ FREE(mpp); -+ return NULL; -+ } -+ -+ mpp->alias = STRDUP(alias); -+ -+ if (dm_get_info(mpp->alias, &mpp->dmi)) { -+ condlog(3, "%s: cannot access table", mpp->alias); -+ goto out; -+ } -+ set_multipath_wwid(mpp); -+ conf = get_multipath_config(); -+ mpp->mpe = find_mpe(conf->mptable, mpp->wwid); -+ put_multipath_config(conf); -+ -+ if (update_multipath_table(mpp, vecs->pathvec, 1)) -+ goto out; -+ if (update_multipath_status(mpp)) -+ goto out; -+ -+ if (!vector_alloc_slot(vecs->mpvec)) -+ goto out; -+ -+ vector_set_slot(vecs->mpvec, mpp); -+ -+ if (update_map(mpp, vecs) != 0) /* map removed */ -+ return NULL; -+ -+ if (start_waiter_thread(mpp, vecs)) -+ goto out; -+ -+ return mpp; -+out: -+ remove_map(mpp, vecs, PURGE_VEC); -+ return NULL; -+} -+ - static int - coalesce_maps(struct vectors *vecs, vector nmpv) - { -diff --git a/multipathd/waiter.c b/multipathd/waiter.c -new file mode 100644 -index 0000000..cb9708b ---- /dev/null -+++ b/multipathd/waiter.c -@@ -0,0 +1,215 @@ -+/* -+ * Copyright (c) 2004, 2005 Christophe Varoqui -+ * Copyright (c) 2005 Kiyoshi Ueda, NEC -+ * Copyright (c) 2005 Benjamin Marzinski, Redhat -+ * Copyright (c) 2005 Edward Goggin, EMC -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "vector.h" -+#include "memory.h" -+#include "checkers.h" -+#include "config.h" -+#include "structs.h" -+#include "structs_vec.h" -+#include "devmapper.h" -+#include "debug.h" -+#include "lock.h" -+#include "waiter.h" -+ -+pthread_attr_t waiter_attr; -+ -+static struct event_thread *alloc_waiter (void) -+{ -+ -+ struct event_thread *wp; -+ -+ wp = (struct event_thread *)MALLOC(sizeof(struct event_thread)); -+ memset(wp, 0, sizeof(struct event_thread)); -+ -+ return wp; -+} -+ -+static void free_waiter (void *data) -+{ -+ struct event_thread *wp = (struct event_thread *)data; -+ -+ if (wp->dmt) -+ dm_task_destroy(wp->dmt); -+ -+ rcu_unregister_thread(); -+ FREE(wp); -+} -+ -+void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs) -+{ -+ pthread_t thread; -+ -+ if (mpp->waiter == (pthread_t)0) { -+ condlog(3, "%s: event checker thread already stopped", -+ mpp->alias); -+ return; -+ } -+ condlog(2, "%s: stop event checker thread (%lu)", mpp->alias, -+ mpp->waiter); -+ thread = mpp->waiter; -+ mpp->waiter = (pthread_t)0; -+ pthread_cancel(thread); -+ pthread_kill(thread, SIGUSR2); -+} -+ -+/* -+ * returns the reschedule delay -+ * negative means *stop* -+ */ -+static int waiteventloop (struct event_thread *waiter) -+{ -+ sigset_t set, oldset; -+ int event_nr; -+ int r; -+ -+ if (!waiter->event_nr) -+ waiter->event_nr = dm_geteventnr(waiter->mapname); -+ -+ if (!(waiter->dmt = libmp_dm_task_create(DM_DEVICE_WAITEVENT))) { -+ condlog(0, "%s: devmap event #%i dm_task_create error", -+ waiter->mapname, waiter->event_nr); -+ return 1; -+ } -+ -+ if (!dm_task_set_name(waiter->dmt, waiter->mapname)) { -+ condlog(0, "%s: devmap event #%i dm_task_set_name error", -+ waiter->mapname, waiter->event_nr); -+ dm_task_destroy(waiter->dmt); -+ waiter->dmt = NULL; -+ return 1; -+ } -+ -+ if (waiter->event_nr && !dm_task_set_event_nr(waiter->dmt, -+ waiter->event_nr)) { -+ condlog(0, "%s: devmap event #%i dm_task_set_event_nr error", -+ waiter->mapname, waiter->event_nr); -+ dm_task_destroy(waiter->dmt); -+ waiter->dmt = NULL; -+ return 1; -+ } -+ -+ dm_task_no_open_count(waiter->dmt); -+ -+ /* wait */ -+ sigemptyset(&set); -+ sigaddset(&set, SIGUSR2); -+ pthread_sigmask(SIG_UNBLOCK, &set, &oldset); -+ -+ pthread_testcancel(); -+ r = dm_task_run(waiter->dmt); -+ pthread_testcancel(); -+ -+ pthread_sigmask(SIG_SETMASK, &oldset, NULL); -+ dm_task_destroy(waiter->dmt); -+ waiter->dmt = NULL; -+ -+ if (!r) /* wait interrupted by signal */ -+ return -1; -+ -+ waiter->event_nr++; -+ -+ /* -+ * upon event ... -+ */ -+ while (1) { -+ condlog(3, "%s: devmap event #%i", -+ waiter->mapname, waiter->event_nr); -+ -+ /* -+ * event might be : -+ * -+ * 1) a table reload, which means our mpp structure is -+ * obsolete : refresh it through update_multipath() -+ * 2) a path failed by DM : mark as such through -+ * update_multipath() -+ * 3) map has gone away : stop the thread. -+ * 4) a path reinstate : nothing to do -+ * 5) a switch group : nothing to do -+ */ -+ pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock); -+ lock(&waiter->vecs->lock); -+ pthread_testcancel(); -+ r = update_multipath(waiter->vecs, waiter->mapname, 1); -+ lock_cleanup_pop(waiter->vecs->lock); -+ -+ if (r) { -+ condlog(2, "%s: event checker exit", -+ waiter->mapname); -+ return -1; /* stop the thread */ -+ } -+ -+ event_nr = dm_geteventnr(waiter->mapname); -+ -+ if (waiter->event_nr == event_nr) -+ return 1; /* upon problem reschedule 1s later */ -+ -+ waiter->event_nr = event_nr; -+ } -+ return -1; /* never reach there */ -+} -+ -+static void *waitevent (void *et) -+{ -+ int r; -+ struct event_thread *waiter; -+ -+ mlockall(MCL_CURRENT | MCL_FUTURE); -+ -+ waiter = (struct event_thread *)et; -+ pthread_cleanup_push(free_waiter, et); -+ -+ rcu_register_thread(); -+ while (1) { -+ r = waiteventloop(waiter); -+ -+ if (r < 0) -+ break; -+ -+ sleep(r); -+ } -+ -+ pthread_cleanup_pop(1); -+ return NULL; -+} -+ -+int start_waiter_thread (struct multipath *mpp, struct vectors *vecs) -+{ -+ struct event_thread *wp; -+ -+ if (!mpp) -+ return 0; -+ -+ wp = alloc_waiter(); -+ -+ if (!wp) -+ goto out; -+ -+ strncpy(wp->mapname, mpp->alias, WWID_SIZE - 1); -+ wp->vecs = vecs; -+ -+ if (pthread_create(&wp->thread, &waiter_attr, waitevent, wp)) { -+ condlog(0, "%s: cannot create event checker", wp->mapname); -+ goto out1; -+ } -+ mpp->waiter = wp->thread; -+ condlog(2, "%s: event checker started", wp->mapname); -+ -+ return 0; -+out1: -+ free_waiter(wp); -+ mpp->waiter = (pthread_t)0; -+out: -+ condlog(0, "failed to start waiter thread"); -+ return 1; -+} -diff --git a/multipathd/waiter.h b/multipathd/waiter.h -new file mode 100644 -index 0000000..0cfae46 ---- /dev/null -+++ b/multipathd/waiter.h -@@ -0,0 +1,17 @@ -+#ifndef _WAITER_H -+#define _WAITER_H -+ -+extern pthread_attr_t waiter_attr; -+ -+struct event_thread { -+ struct dm_task *dmt; -+ pthread_t thread; -+ int event_nr; -+ char mapname[WWID_SIZE]; -+ struct vectors *vecs; -+}; -+ -+void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs); -+int start_waiter_thread (struct multipath *mpp, struct vectors *vecs); -+ -+#endif /* _WAITER_H */ --- -2.7.4 - diff --git a/0018-RH-use-rpm-optflags-if-present.patch b/0010-RH-use-rpm-optflags-if-present.patch similarity index 77% rename from 0018-RH-use-rpm-optflags-if-present.patch rename to 0010-RH-use-rpm-optflags-if-present.patch index 99e0a7e..18c975c 100644 --- a/0018-RH-use-rpm-optflags-if-present.patch +++ b/0010-RH-use-rpm-optflags-if-present.patch @@ -9,14 +9,14 @@ still being generic. Signed-off-by: Benjamin Marzinski --- - Makefile.inc | 22 +++++++++++++++------- - 1 file changed, 15 insertions(+), 7 deletions(-) + Makefile.inc | 24 ++++++++++++++++-------- + 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Makefile.inc b/Makefile.inc -index 5145909..0b4ee17 100644 +index f589ab0..c07023a 100644 --- a/Makefile.inc +++ b/Makefile.inc -@@ -82,13 +82,21 @@ TEST_CC_OPTION = $(shell \ +@@ -85,14 +85,22 @@ TEST_CC_OPTION = $(shell \ echo "$(2)"; \ fi) @@ -25,6 +25,7 @@ index 5145909..0b4ee17 100644 -OPTFLAGS = -O2 -g -pipe -Wall -Wextra -Wformat=2 -Werror=implicit-int \ - -Werror=implicit-function-declaration -Werror=format-security \ - -Wno-sign-compare -Wno-unused-parameter -Wno-clobbered \ +- -Werror=cast-qual -Werror=discarded-qualifiers \ - -Wp,-D_FORTIFY_SOURCE=2 $(STACKPROT) \ - --param=ssp-buffer-size=4 +ifndef RPM_OPT_FLAGS @@ -41,10 +42,11 @@ index 5145909..0b4ee17 100644 +endif +OPTFLAGS += -Wextra -Wstrict-prototypes -Wformat=2 -Werror=implicit-int \ + -Werror=implicit-function-declaration -Wno-sign-compare \ -+ -Wno-unused-parameter ++ -Wno-unused-parameter -Werror=cast-qual \ ++ -Werror=discarded-qualifiers - CFLAGS := $(OPTFLAGS) -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \ - $(CFLAGS) + CFLAGS := $(OPTFLAGS) -DBIN_DIR=\"$(bindir)\" -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \ + -MMD -MP $(CFLAGS) -- 2.7.4 diff --git a/0010-call-start_waiter_thread-before-setup_multipath.patch b/0010-call-start_waiter_thread-before-setup_multipath.patch deleted file mode 100644 index bb5a479..0000000 --- a/0010-call-start_waiter_thread-before-setup_multipath.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Mon, 5 Feb 2018 21:59:16 -0600 -Subject: [PATCH] call start_waiter_thread() before setup_multipath() - -If setup_multipath() is called before the waiter thread has started, -there is a window where a dm event can occur between when -setup_multipath() updates the device state and when the waiter thread -starts waiting for new events, causing the new event to be missed and -the multipath device to not get updated. - -Signed-off-by: Benjamin Marzinski ---- - multipathd/main.c | 37 ++++++++++++++++++++----------------- - 1 file changed, 20 insertions(+), 17 deletions(-) - -diff --git a/multipathd/main.c b/multipathd/main.c -index 94b2406..efc39d7 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -321,7 +321,7 @@ set_multipath_wwid (struct multipath * mpp) - } - - static int --update_map (struct multipath *mpp, struct vectors *vecs) -+update_map (struct multipath *mpp, struct vectors *vecs, int new_map) - { - int retries = 3; - char params[PARAMS_SIZE] = {0}; -@@ -351,6 +351,12 @@ retry: - dm_lib_release(); - - fail: -+ if (new_map && (retries < 0 || start_waiter_thread(mpp, vecs))) { -+ condlog(0, "%s: failed to create new map", mpp->alias); -+ remove_map(mpp, vecs, 1); -+ return 1; -+ } -+ - if (setup_multipath(vecs, mpp)) - return 1; - -@@ -395,12 +401,9 @@ add_map_without_path (struct vectors *vecs, char *alias) - - vector_set_slot(vecs->mpvec, mpp); - -- if (update_map(mpp, vecs) != 0) /* map removed */ -+ if (update_map(mpp, vecs, 1) != 0) /* map removed */ - return NULL; - -- if (start_waiter_thread(mpp, vecs)) -- goto out; -- - return mpp; - out: - remove_map(mpp, vecs, PURGE_VEC); -@@ -554,7 +557,7 @@ ev_add_map (char * dev, char * alias, struct vectors * vecs) - if (mpp->wait_for_udev > 1) { - condlog(2, "%s: performing delayed actions", - mpp->alias); -- if (update_map(mpp, vecs)) -+ if (update_map(mpp, vecs, 0)) - /* setup multipathd removed the map */ - return 1; - } -@@ -865,6 +868,11 @@ retry: - } - dm_lib_release(); - -+ if ((mpp->action == ACT_CREATE || -+ (mpp->action == ACT_NOTHING && start_waiter && !mpp->waiter)) && -+ start_waiter_thread(mpp, vecs)) -+ goto fail_map; -+ - /* - * update our state from kernel regardless of create or reload - */ -@@ -873,11 +881,6 @@ retry: - - sync_map_state(mpp); - -- if ((mpp->action == ACT_CREATE || -- (mpp->action == ACT_NOTHING && start_waiter && !mpp->waiter)) && -- start_waiter_thread(mpp, vecs)) -- goto fail_map; -- - if (retries >= 0) { - condlog(2, "%s [%s]: path added to devmap %s", - pp->dev, pp->dev_t, mpp->alias); -@@ -1479,7 +1482,8 @@ missing_uev_wait_tick(struct vectors *vecs) - if (mpp->wait_for_udev && --mpp->uev_wait_tick <= 0) { - timed_out = 1; - condlog(0, "%s: timeout waiting on creation uevent. enabling reloads", mpp->alias); -- if (mpp->wait_for_udev > 1 && update_map(mpp, vecs)) { -+ if (mpp->wait_for_udev > 1 && -+ update_map(mpp, vecs, 0)) { - /* update_map removed map */ - i--; - continue; -@@ -1511,7 +1515,7 @@ ghost_delay_tick(struct vectors *vecs) - condlog(0, "%s: timed out waiting for active path", - mpp->alias); - mpp->force_udev_reload = 1; -- if (update_map(mpp, vecs) != 0) { -+ if (update_map(mpp, vecs, 0) != 0) { - /* update_map removed map */ - i--; - continue; -@@ -2169,14 +2173,13 @@ configure (struct vectors * vecs) - * start dm event waiter threads for these new maps - */ - vector_foreach_slot(vecs->mpvec, mpp, i) { -- if (setup_multipath(vecs, mpp)) { -- i--; -- continue; -- } - if (start_waiter_thread(mpp, vecs)) { - remove_map(mpp, vecs, 1); - i--; -+ continue; - } -+ if (setup_multipath(vecs, mpp)) -+ i--; - } - return 0; - } --- -2.7.4 - diff --git a/0019-RH-add-mpathconf.patch b/0011-RH-add-mpathconf.patch similarity index 99% rename from 0019-RH-add-mpathconf.patch rename to 0011-RH-add-mpathconf.patch index fc199fa..22480c4 100644 --- a/0019-RH-add-mpathconf.patch +++ b/0011-RH-add-mpathconf.patch @@ -21,7 +21,7 @@ Signed-off-by: Benjamin Marzinski create mode 100644 multipath/mpathconf.8 diff --git a/libmultipath/config.c b/libmultipath/config.c -index 27826fa..9bf4fb7 100644 +index 83d26be..a50f41a 100644 --- a/libmultipath/config.c +++ b/libmultipath/config.c @@ -659,6 +659,7 @@ load_config (char * file) @@ -33,10 +33,10 @@ index 27826fa..9bf4fb7 100644 conf->blist_devnode = vector_alloc(); if (!conf->blist_devnode) { diff --git a/multipath/Makefile b/multipath/Makefile -index dda5565..d35127a 100644 +index b9bbb3c..e720c7f 100644 --- a/multipath/Makefile +++ b/multipath/Makefile -@@ -18,10 +18,12 @@ $(EXEC): $(OBJS) +@@ -18,10 +18,12 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so $(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS) $(LIBDEPS) $(GZIP) $(EXEC).8 > $(EXEC).8.gz $(GZIP) $(EXEC).conf.5 > $(EXEC).conf.5.gz @@ -64,7 +64,7 @@ index dda5565..d35127a 100644 $(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz + $(RM) $(DESTDIR)$(man8dir)/mpathconf.8.gz - clean: + clean: dep_clean $(RM) core *.o $(EXEC) *.gz diff --git a/multipath/mpathconf b/multipath/mpathconf new file mode 100644 diff --git a/0011-libmultipath-add-helper-functions.patch b/0011-libmultipath-add-helper-functions.patch deleted file mode 100644 index aa62edf..0000000 --- a/0011-libmultipath-add-helper-functions.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Mon, 5 Feb 2018 10:40:24 -0600 -Subject: [PATCH] libmultipath: add helper functions - -Add the ability to reset a vector without completely freeing it, and to -check the version of the device-mapper module. The existing version -checking code checks the version of a specific device mapper target, and -has been renamed for clarity's sake. These functions will be used in a -later patch. - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/devmapper.c | 28 ++++++++++++++++++++++++---- - libmultipath/devmapper.h | 3 ++- - libmultipath/vector.c | 16 ++++++++++++---- - libmultipath/vector.h | 1 + - multipathd/main.c | 2 +- - 5 files changed, 40 insertions(+), 10 deletions(-) - -diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c -index 573fc75..2960bf5 100644 ---- a/libmultipath/devmapper.c -+++ b/libmultipath/devmapper.c -@@ -132,7 +132,27 @@ dm_lib_prereq (void) - } - - int --dm_drv_version (unsigned int * version, char * str) -+dm_drv_version(unsigned int *v) -+{ -+ char buff[64]; -+ -+ v[0] = 0; -+ v[1] = 0; -+ v[2] = 0; -+ -+ if (!dm_driver_version(buff, sizeof(buff))) { -+ condlog(0, "cannot get kernel dm version"); -+ return 1; -+ } -+ if (sscanf(buff, "%u.%u.%u ", &v[0], &v[1], &v[2]) != 3) { -+ condlog(0, "invalid kernel dm version '%s'", buff); -+ return 1; -+ } -+ return 0; -+} -+ -+int -+dm_tgt_version (unsigned int * version, char * str) - { - int r = 2; - struct dm_task *dmt; -@@ -179,13 +199,13 @@ out: - } - - static int --dm_drv_prereq (unsigned int *ver) -+dm_tgt_prereq (unsigned int *ver) - { - unsigned int minv[3] = {1, 0, 3}; - unsigned int version[3] = {0, 0, 0}; - unsigned int * v = version; - -- if (dm_drv_version(v, TGT_MPATH)) { -+ if (dm_tgt_version(v, TGT_MPATH)) { - /* in doubt return not capable */ - return 1; - } -@@ -210,7 +230,7 @@ static int dm_prereq(unsigned int *v) - { - if (dm_lib_prereq()) - return 1; -- return dm_drv_prereq(v); -+ return dm_tgt_prereq(v); - } - - static int libmp_dm_udev_sync = 0; -diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h -index 62e14d1..52d4af8 100644 ---- a/libmultipath/devmapper.h -+++ b/libmultipath/devmapper.h -@@ -28,7 +28,8 @@ void dm_init(int verbosity); - void libmp_dm_init(void); - void libmp_udev_set_sync_support(int on); - struct dm_task *libmp_dm_task_create(int task); --int dm_drv_version (unsigned int * version, char * str); -+int dm_drv_version (unsigned int * version); -+int dm_tgt_version (unsigned int * version, char * str); - int dm_simplecmd_flush (int, const char *, uint16_t); - int dm_simplecmd_noflush (int, const char *, uint16_t); - int dm_addmap_create (struct multipath *mpp, char *params); -diff --git a/libmultipath/vector.c b/libmultipath/vector.c -index 6266e0a..f741ae0 100644 ---- a/libmultipath/vector.c -+++ b/libmultipath/vector.c -@@ -145,18 +145,26 @@ vector_repack(vector v) - vector_del_slot(v, i--); - } - --/* Free memory vector allocation */ --void --vector_free(vector v) -+vector -+vector_reset(vector v) - { - if (!v) -- return; -+ return NULL; - - if (v->slot) - FREE(v->slot); - - v->allocated = 0; - v->slot = NULL; -+ return v; -+} -+ -+/* Free memory vector allocation */ -+void -+vector_free(vector v) -+{ -+ if (!vector_reset(v)) -+ return; - FREE(v); - } - -diff --git a/libmultipath/vector.h b/libmultipath/vector.h -index 5cfd4d0..d69cd0b 100644 ---- a/libmultipath/vector.h -+++ b/libmultipath/vector.h -@@ -45,6 +45,7 @@ typedef struct _vector *vector; - /* Prototypes */ - extern vector vector_alloc(void); - extern void *vector_alloc_slot(vector v); -+vector vector_reset(vector v); - extern void vector_free(vector v); - extern void free_strvec(vector strvec); - extern void vector_set_slot(vector v, void *value); -diff --git a/multipathd/main.c b/multipathd/main.c -index efc39d7..2963bde 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -2228,7 +2228,7 @@ reconfigure (struct vectors * vecs) - /* Re-read any timezone changes */ - tzset(); - -- dm_drv_version(conf->version, TGT_MPATH); -+ dm_tgt_version(conf->version, TGT_MPATH); - if (verbosity) - conf->verbosity = verbosity; - if (bindings_read_only) --- -2.7.4 - diff --git a/0020-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch b/0012-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch similarity index 93% rename from 0020-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch rename to 0012-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch index d9dc69a..23af6db 100644 --- a/0020-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +++ b/0012-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch @@ -22,10 +22,10 @@ Signed-off-by: Benjamin Marzinski 5 files changed, 58 insertions(+), 3 deletions(-) diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c -index bc70a27..88bb72b 100644 +index 0ec9f25..9722714 100644 --- a/libmultipath/wwids.c +++ b/libmultipath/wwids.c -@@ -321,3 +321,47 @@ remember_wwid(char *wwid) +@@ -323,3 +323,47 @@ remember_wwid(char *wwid) condlog(4, "wwid %s already in wwids file", wwid); return 0; } @@ -85,10 +85,10 @@ index 9527012..b665232 100644 #endif /* _WWIDS_H */ diff --git a/multipath/main.c b/multipath/main.c -index d2415a9..ff570ac 100644 +index d08c688..baf6759 100644 --- a/multipath/main.c +++ b/multipath/main.c -@@ -102,7 +102,7 @@ usage (char * progname) +@@ -104,7 +104,7 @@ usage (char * progname) { fprintf (stderr, VERSION_STRING); fprintf (stderr, "Usage:\n"); @@ -97,7 +97,7 @@ index d2415a9..ff570ac 100644 fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [-R num] [dev]\n", progname); fprintf (stderr, " %s -F [-v lvl] [-R num]\n", progname); fprintf (stderr, " %s -t\n", progname); -@@ -116,6 +116,8 @@ usage (char * progname) +@@ -118,6 +118,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" @@ -106,7 +106,7 @@ index d2415a9..ff570ac 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" -@@ -602,7 +604,7 @@ main (int argc, char *argv[]) +@@ -672,7 +674,7 @@ main (int argc, char *argv[]) exit(1); multipath_conf = conf; conf->retrigger_tries = 0; @@ -115,7 +115,7 @@ index d2415a9..ff570ac 100644 switch(arg) { case 1: printf("optarg : %s\n",optarg); break; -@@ -669,6 +671,10 @@ main (int argc, char *argv[]) +@@ -739,6 +741,10 @@ main (int argc, char *argv[]) case 't': r = dump_config(conf); goto out_free_config; @@ -150,7 +150,7 @@ index 56f8703..9fc2317 100644 .B \-U Check if the device specified in the program environment is a multipath device diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service -index fafd088..a623a3f 100644 +index 17434ce..0fbcc46 100644 --- a/multipathd/multipathd.service +++ b/multipathd/multipathd.service @@ -15,6 +15,7 @@ Type=notify @@ -160,7 +160,7 @@ index fafd088..a623a3f 100644 +ExecStartPre=-/sbin/multipath -A ExecStart=/sbin/multipathd -d -s ExecReload=/sbin/multipathd reconfigure - + TasksMax=infinity -- 2.7.4 diff --git a/0012-multipathd-RFC-add-new-polling-dmevents-waiter-threa.patch b/0012-multipathd-RFC-add-new-polling-dmevents-waiter-threa.patch deleted file mode 100644 index 64db4ad..0000000 --- a/0012-multipathd-RFC-add-new-polling-dmevents-waiter-threa.patch +++ /dev/null @@ -1,643 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Tue, 6 Feb 2018 15:36:39 -0600 -Subject: [PATCH] multipathd: RFC add new polling dmevents waiter thread - -The current method of waiting for dmevents on multipath devices involves -creating a seperate thread for each device. This can become very -wasteful when there are large numbers of multipath devices. Also, since -multipathd needs to grab the vecs lock to update the devices, the -additional threads don't actually provide much parallelism. - -The patch adds a new method of updating multipath devices on dmevents, -which uses the new device-mapper event polling interface. This means -that there is only one dmevent waiting thread which will wait for events -on all of the multipath devices. Currently the code to get the event -number from the list of device names and to re-arm the polling interface -is not in libdevmapper, so the patch does that work. Obviously, these -bits need to go into libdevmapper, so that multipathd can use a standard -interface. - -I haven't touched any of the existing event waiting code, since event -polling was only added to device-mapper in version 4.37.0. multipathd -checks this version, and defaults to using the polling code if -device-mapper supports it. This can be overridden by running multipathd -with "-w", to force it to use the old event waiting code. - -Signed-off-by: Benjamin Marzinski ---- - multipathd/Makefile | 3 +- - multipathd/dmevents.c | 396 ++++++++++++++++++++++++++++++++++++++++++++++++++ - multipathd/dmevents.h | 13 ++ - multipathd/main.c | 58 +++++++- - 4 files changed, 461 insertions(+), 9 deletions(-) - create mode 100644 multipathd/dmevents.c - create mode 100644 multipathd/dmevents.h - -diff --git a/multipathd/Makefile b/multipathd/Makefile -index 85f29a7..4c438f0 100644 ---- a/multipathd/Makefile -+++ b/multipathd/Makefile -@@ -22,7 +22,8 @@ ifdef SYSTEMD - endif - endif - --OBJS = main.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o waiter.o -+OBJS = main.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o waiter.o \ -+ dmevents.o - - EXEC = multipathd - -diff --git a/multipathd/dmevents.c b/multipathd/dmevents.c -new file mode 100644 -index 0000000..a56c055 ---- /dev/null -+++ b/multipathd/dmevents.c -@@ -0,0 +1,396 @@ -+/* -+ * Copyright (c) 2004, 2005 Christophe Varoqui -+ * Copyright (c) 2005 Kiyoshi Ueda, NEC -+ * Copyright (c) 2005 Edward Goggin, EMC -+ * Copyright (c) 2005, 2018 Benjamin Marzinski, Redhat -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "vector.h" -+#include "structs.h" -+#include "structs_vec.h" -+#include "devmapper.h" -+#include "debug.h" -+#include "dmevents.h" -+ -+#ifndef DM_DEV_ARM_POLL -+#define DM_DEV_ARM_POLL _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD + 1, struct dm_ioctl) -+#endif -+ -+enum event_actions { -+ EVENT_NOTHING, -+ EVENT_REMOVE, -+ EVENT_UPDATE, -+}; -+ -+struct dev_event { -+ char name[WWID_SIZE]; -+ uint32_t evt_nr; -+ enum event_actions action; -+}; -+ -+struct dmevent_waiter { -+ int fd; -+ struct vectors *vecs; -+ vector events; -+ pthread_mutex_t events_lock; -+}; -+ -+static struct dmevent_waiter *waiter; -+ -+int dmevent_poll_supported(void) -+{ -+ unsigned int minv[3] = {4, 37, 0}; -+ unsigned int v[3]; -+ -+ if (dm_drv_version(v)) -+ return 0; -+ -+ if (VERSION_GE(v, minv)) -+ return 1; -+ return 0; -+} -+ -+ -+int alloc_dmevent_waiter(struct vectors *vecs) -+{ -+ if (!vecs) { -+ condlog(0, "can't create waiter structure. invalid vectors"); -+ goto fail; -+ } -+ waiter = (struct dmevent_waiter *)malloc(sizeof(struct dmevent_waiter)); -+ if (!waiter) { -+ condlog(0, "failed to allocate waiter structure"); -+ goto fail; -+ } -+ memset(waiter, 0, sizeof(struct dmevent_waiter)); -+ waiter->events = vector_alloc(); -+ if (!waiter->events) { -+ condlog(0, "failed to allocate waiter events vector"); -+ goto fail_waiter; -+ } -+ waiter->fd = open("/dev/mapper/control", O_RDWR); -+ if (waiter->fd < 0) { -+ condlog(0, "failed to open /dev/mapper/control for waiter"); -+ goto fail_events; -+ } -+ pthread_mutex_init(&waiter->events_lock, NULL); -+ waiter->vecs = vecs; -+ -+ return 0; -+fail_events: -+ vector_free(waiter->events); -+fail_waiter: -+ free(waiter); -+fail: -+ waiter = NULL; -+ return -1; -+} -+ -+void free_dmevent_waiter(void) -+{ -+ struct dev_event *dev_evt; -+ int i; -+ -+ if (!waiter) -+ return; -+ pthread_mutex_destroy(&waiter->events_lock); -+ close(waiter->fd); -+ vector_foreach_slot(waiter->events, dev_evt, i) -+ free(dev_evt); -+ vector_free(waiter->events); -+ free(waiter); -+ waiter = NULL; -+} -+ -+static int arm_dm_event_poll(int fd) -+{ -+ struct dm_ioctl dmi; -+ memset(&dmi, 0, sizeof(dmi)); -+ dmi.version[0] = DM_VERSION_MAJOR; -+ dmi.version[1] = DM_VERSION_MINOR; -+ dmi.version[2] = DM_VERSION_PATCHLEVEL; -+ dmi.flags = 0x4; -+ dmi.data_start = offsetof(struct dm_ioctl, data); -+ dmi.data_size = sizeof(dmi); -+ return ioctl(fd, DM_DEV_ARM_POLL, &dmi); -+} -+ -+/* -+ * As of version 4.37.0 device-mapper stores the event number in the -+ * dm_names structure after the name, when DM_DEVICE_LIST is called -+ */ -+static uint32_t dm_event_nr(struct dm_names *n) -+{ -+ return *(uint32_t *)(((uintptr_t)(strchr(n->name, 0) + 1) + 7) & ~7); -+} -+ -+static int dm_get_events(void) -+{ -+ struct dm_task *dmt; -+ struct dm_names *names; -+ struct dev_event *dev_evt; -+ int i; -+ -+ if (!(dmt = libmp_dm_task_create(DM_DEVICE_LIST))) -+ return -1; -+ -+ dm_task_no_open_count(dmt); -+ -+ if (!dm_task_run(dmt)) -+ goto fail; -+ -+ if (!(names = dm_task_get_names(dmt))) -+ goto fail; -+ -+ pthread_mutex_lock(&waiter->events_lock); -+ vector_foreach_slot(waiter->events, dev_evt, i) -+ dev_evt->action = EVENT_REMOVE; -+ while (names->dev) { -+ uint32_t event_nr; -+ -+ if (!dm_is_mpath(names->name)) -+ goto next; -+ -+ event_nr = dm_event_nr(names); -+ vector_foreach_slot(waiter->events, dev_evt, i) { -+ if (!strcmp(dev_evt->name, names->name)) { -+ if (event_nr != dev_evt->evt_nr) { -+ dev_evt->evt_nr = event_nr; -+ dev_evt->action = EVENT_UPDATE; -+ } else -+ dev_evt->action = EVENT_NOTHING; -+ break; -+ } -+ } -+next: -+ if (!names->next) -+ break; -+ names = (void *)names + names->next; -+ } -+ pthread_mutex_unlock(&waiter->events_lock); -+ dm_task_destroy(dmt); -+ return 0; -+ -+fail: -+ dm_task_destroy(dmt); -+ return -1; -+} -+ -+/* You must call update_multipath() after calling this function, to -+ * deal with any events that came in before the device was added */ -+int watch_dmevents(char *name) -+{ -+ int event_nr; -+ struct dev_event *dev_evt, *old_dev_evt; -+ int i; -+ -+ if (!dm_is_mpath(name)) { -+ condlog(0, "%s: not a multipath device. can't watch events", -+ name); -+ return -1; -+ } -+ -+ if ((event_nr = dm_geteventnr(name)) < 0) -+ return -1; -+ -+ dev_evt = (struct dev_event *)malloc(sizeof(struct dev_event)); -+ if (!dev_evt) { -+ condlog(0, "%s: can't allocate event waiter structure", name); -+ return -1; -+ } -+ -+ strncpy(dev_evt->name, name, WWID_SIZE); -+ dev_evt->name[WWID_SIZE - 1] = 0; -+ dev_evt->evt_nr = event_nr; -+ dev_evt->action = EVENT_NOTHING; -+ -+ pthread_mutex_lock(&waiter->events_lock); -+ vector_foreach_slot(waiter->events, old_dev_evt, i){ -+ if (!strcmp(dev_evt->name, old_dev_evt->name)) { -+ /* caller will be updating this device */ -+ old_dev_evt->evt_nr = event_nr; -+ old_dev_evt->action = EVENT_NOTHING; -+ pthread_mutex_unlock(&waiter->events_lock); -+ condlog(2, "%s: already waiting for events on device", -+ name); -+ free(dev_evt); -+ return 0; -+ } -+ } -+ if (!vector_alloc_slot(waiter->events)) { -+ pthread_mutex_unlock(&waiter->events_lock); -+ free(dev_evt); -+ return -1; -+ } -+ vector_set_slot(waiter->events, dev_evt); -+ pthread_mutex_unlock(&waiter->events_lock); -+ return 0; -+} -+ -+void unwatch_all_dmevents(void) -+{ -+ struct dev_event *dev_evt; -+ int i; -+ -+ pthread_mutex_lock(&waiter->events_lock); -+ vector_foreach_slot(waiter->events, dev_evt, i) -+ free(dev_evt); -+ vector_reset(waiter->events); -+ pthread_mutex_unlock(&waiter->events_lock); -+} -+ -+static void unwatch_dmevents(char *name) -+{ -+ struct dev_event *dev_evt; -+ int i; -+ -+ pthread_mutex_lock(&waiter->events_lock); -+ vector_foreach_slot(waiter->events, dev_evt, i) { -+ if (!strcmp(dev_evt->name, name)) { -+ vector_del_slot(waiter->events, i); -+ free(dev_evt); -+ break; -+ } -+ } -+ pthread_mutex_unlock(&waiter->events_lock); -+} -+ -+/* -+ * returns the reschedule delay -+ * negative means *stop* -+ */ -+ -+/* poll, arm, update, return */ -+static int dmevent_loop (void) -+{ -+ int r, i = 0; -+ struct pollfd pfd; -+ struct dev_event *dev_evt; -+ -+ pfd.fd = waiter->fd; -+ pfd.events = POLLIN; -+ r = poll(&pfd, 1, -1); -+ if (r <= 0) { -+ condlog(0, "failed polling for dm events: %s", strerror(errno)); -+ /* sleep 1s and hope things get better */ -+ return 1; -+ } -+ -+ if (arm_dm_event_poll(waiter->fd) != 0) { -+ condlog(0, "Cannot re-arm event polling: %s", strerror(errno)); -+ /* sleep 1s and hope things get better */ -+ return 1; -+ } -+ -+ if (dm_get_events() != 0) { -+ condlog(0, "failed getting dm events: %s", strerror(errno)); -+ /* sleep 1s and hope things get better */ -+ return 1; -+ } -+ -+ /* -+ * upon event ... -+ */ -+ -+ while (1) { -+ int done = 1; -+ struct dev_event curr_dev; -+ struct multipath *mpp; -+ -+ pthread_mutex_lock(&waiter->events_lock); -+ vector_foreach_slot(waiter->events, dev_evt, i) { -+ if (dev_evt->action != EVENT_NOTHING) { -+ curr_dev = *dev_evt; -+ if (dev_evt->action == EVENT_REMOVE) { -+ vector_del_slot(waiter->events, i); -+ free(dev_evt); -+ } else -+ dev_evt->action = EVENT_NOTHING; -+ done = 0; -+ break; -+ } -+ } -+ pthread_mutex_unlock(&waiter->events_lock); -+ if (done) -+ return 1; -+ -+ condlog(3, "%s: devmap event #%i", curr_dev.name, -+ curr_dev.evt_nr); -+ -+ /* -+ * event might be : -+ * -+ * 1) a table reload, which means our mpp structure is -+ * obsolete : refresh it through update_multipath() -+ * 2) a path failed by DM : mark as such through -+ * update_multipath() -+ * 3) map has gone away : stop the thread. -+ * 4) a path reinstate : nothing to do -+ * 5) a switch group : nothing to do -+ */ -+ pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock); -+ lock(&waiter->vecs->lock); -+ pthread_testcancel(); -+ r = 0; -+ if (curr_dev.action == EVENT_REMOVE) { -+ mpp = find_mp_by_alias(waiter->vecs->mpvec, -+ curr_dev.name); -+ if (mpp) -+ remove_map(mpp, waiter->vecs, 1); -+ } else -+ r = update_multipath(waiter->vecs, curr_dev.name, 1); -+ lock_cleanup_pop(&waiter->vecs->lock); -+ -+ if (r) { -+ condlog(2, "%s: stopped watching dmevents", -+ curr_dev.name); -+ unwatch_dmevents(curr_dev.name); -+ } -+ } -+ condlog(0, "dmevent waiter thread unexpectedly quit"); -+ return -1; /* never reach there */ -+} -+ -+static void rcu_unregister(void *param) -+{ -+ rcu_unregister_thread(); -+} -+ -+void *wait_dmevents (void *unused) -+{ -+ int r; -+ -+ -+ if (!waiter) { -+ condlog(0, "dmevents waiter not intialized"); -+ return NULL; -+ } -+ -+ pthread_cleanup_push(rcu_unregister, NULL); -+ rcu_register_thread(); -+ mlockall(MCL_CURRENT | MCL_FUTURE); -+ -+ while (1) { -+ r = dmevent_loop(); -+ -+ if (r < 0) -+ break; -+ -+ sleep(r); -+ } -+ -+ pthread_cleanup_pop(1); -+ return NULL; -+} -diff --git a/multipathd/dmevents.h b/multipathd/dmevents.h -new file mode 100644 -index 0000000..569e855 ---- /dev/null -+++ b/multipathd/dmevents.h -@@ -0,0 +1,13 @@ -+#ifndef _DMEVENTS_H -+#define _DMEVENTS_H -+ -+#include "structs_vec.h" -+ -+int dmevent_poll_supported(void); -+int alloc_dmevent_waiter(struct vectors *vecs); -+void free_dmevent_waiter(void); -+int watch_dmevents(char *name); -+void unwatch_all_dmevents(void); -+void *wait_dmevents (void *unused); -+ -+#endif /* _DMEVENTS_H */ -diff --git a/multipathd/main.c b/multipathd/main.c -index 2963bde..6dabf2c 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -82,6 +82,7 @@ static int use_watchdog; - #include "cli_handlers.h" - #include "lock.h" - #include "waiter.h" -+#include "dmevents.h" - #include "io_err_stat.h" - #include "wwids.h" - #include "../third-party/valgrind/drd.h" -@@ -108,6 +109,7 @@ int uxsock_timeout; - int verbosity; - int bindings_read_only; - int ignore_new_devs; -+int poll_dmevents = 1; - enum daemon_status running_state = DAEMON_INIT; - pid_t daemon_pid; - pthread_mutex_t config_lock = PTHREAD_MUTEX_INITIALIZER; -@@ -288,11 +290,23 @@ switch_pathgroup (struct multipath * mpp) - mpp->alias, mpp->bestpg); - } - -+static int -+wait_for_events(struct multipath *mpp, struct vectors *vecs) -+{ -+ if (poll_dmevents) -+ return watch_dmevents(mpp->alias); -+ else -+ return start_waiter_thread(mpp, vecs); -+} -+ - static void - remove_map_and_stop_waiter(struct multipath *mpp, struct vectors *vecs, - int purge_vec) - { -- stop_waiter_thread(mpp, vecs); -+ /* devices are automatically removed by the dmevent polling code, -+ * so they don't need to be manually removed here */ -+ if (!poll_dmevents) -+ stop_waiter_thread(mpp, vecs); - remove_map(mpp, vecs, purge_vec); - } - -@@ -305,8 +319,12 @@ remove_maps_and_stop_waiters(struct vectors *vecs) - if (!vecs) - return; - -- vector_foreach_slot(vecs->mpvec, mpp, i) -- stop_waiter_thread(mpp, vecs); -+ if (!poll_dmevents) { -+ vector_foreach_slot(vecs->mpvec, mpp, i) -+ stop_waiter_thread(mpp, vecs); -+ } -+ else -+ unwatch_all_dmevents(); - - remove_maps(vecs); - } -@@ -351,7 +369,7 @@ retry: - dm_lib_release(); - - fail: -- if (new_map && (retries < 0 || start_waiter_thread(mpp, vecs))) { -+ if (new_map && (retries < 0 || wait_for_events(mpp, vecs))) { - condlog(0, "%s: failed to create new map", mpp->alias); - remove_map(mpp, vecs, 1); - return 1; -@@ -870,7 +888,7 @@ retry: - - if ((mpp->action == ACT_CREATE || - (mpp->action == ACT_NOTHING && start_waiter && !mpp->waiter)) && -- start_waiter_thread(mpp, vecs)) -+ wait_for_events(mpp, vecs)) - goto fail_map; - - /* -@@ -2173,7 +2191,7 @@ configure (struct vectors * vecs) - * start dm event waiter threads for these new maps - */ - vector_foreach_slot(vecs->mpvec, mpp, i) { -- if (start_waiter_thread(mpp, vecs)) { -+ if (wait_for_events(mpp, vecs)) { - remove_map(mpp, vecs, 1); - i--; - continue; -@@ -2414,7 +2432,7 @@ set_oom_adj (void) - static int - child (void * param) - { -- pthread_t check_thr, uevent_thr, uxlsnr_thr, uevq_thr; -+ pthread_t check_thr, uevent_thr, uxlsnr_thr, uevq_thr, dmevent_thr; - pthread_attr_t log_attr, misc_attr, uevent_attr; - struct vectors * vecs; - struct multipath * mpp; -@@ -2476,6 +2494,8 @@ child (void * param) - goto failed; - } - -+ if (poll_dmevents) -+ poll_dmevents = dmevent_poll_supported(); - setlogmask(LOG_UPTO(conf->verbosity + 3)); - - envp = getenv("LimitNOFILE"); -@@ -2542,6 +2562,19 @@ child (void * param) - - init_path_check_interval(vecs); - -+ if (poll_dmevents) { -+ if (alloc_dmevent_waiter(vecs)) { -+ condlog(0, "failed to allocate dmevents waiter info"); -+ goto failed; -+ } -+ if ((rc = pthread_create(&dmevent_thr, &misc_attr, -+ wait_dmevents, NULL))) { -+ condlog(0, "failed to create dmevent waiter thread: %d", -+ rc); -+ goto failed; -+ } -+ } -+ - /* - * Start uevent listener early to catch events - */ -@@ -2615,11 +2648,15 @@ child (void * param) - pthread_cancel(uevent_thr); - pthread_cancel(uxlsnr_thr); - pthread_cancel(uevq_thr); -+ if (poll_dmevents) -+ pthread_cancel(dmevent_thr); - - pthread_join(check_thr, NULL); - pthread_join(uevent_thr, NULL); - pthread_join(uxlsnr_thr, NULL); - pthread_join(uevq_thr, NULL); -+ if (poll_dmevents) -+ pthread_join(dmevent_thr, NULL); - - stop_io_err_stat_thread(); - -@@ -2634,6 +2671,8 @@ child (void * param) - - cleanup_checkers(); - cleanup_prio(); -+ if (poll_dmevents) -+ free_dmevent_waiter(); - - dm_lib_release(); - dm_lib_exit(); -@@ -2765,7 +2804,7 @@ main (int argc, char *argv[]) - udev = udev_new(); - libmp_udev_set_sync_support(0); - -- while ((arg = getopt(argc, argv, ":dsv:k::Bn")) != EOF ) { -+ while ((arg = getopt(argc, argv, ":dsv:k::Bniw")) != EOF ) { - switch(arg) { - case 'd': - foreground = 1; -@@ -2799,6 +2838,9 @@ main (int argc, char *argv[]) - case 'n': - ignore_new_devs = 1; - break; -+ case 'w': -+ poll_dmevents = 0; -+ break; - default: - fprintf(stderr, "Invalid argument '-%c'\n", - optopt); --- -2.7.4 - diff --git a/0021-RH-trigger-change-uevent-on-new-device-creation.patch b/0013-RH-trigger-change-uevent-on-new-device-creation.patch similarity index 86% rename from 0021-RH-trigger-change-uevent-on-new-device-creation.patch rename to 0013-RH-trigger-change-uevent-on-new-device-creation.patch index 54c6d57..726a54d 100644 --- a/0021-RH-trigger-change-uevent-on-new-device-creation.patch +++ b/0013-RH-trigger-change-uevent-on-new-device-creation.patch @@ -22,10 +22,10 @@ Signed-off-by: Benjamin Marzinski 5 files changed, 30 insertions(+), 20 deletions(-) diff --git a/libmultipath/configure.c b/libmultipath/configure.c -index 22c11a2..7011ef7 100644 +index 61f68f8..81b0bc4 100644 --- a/libmultipath/configure.c +++ b/libmultipath/configure.c -@@ -427,6 +427,28 @@ trigger_udev_change(const struct multipath *mpp) +@@ -444,6 +444,28 @@ trigger_udev_change(const struct multipath *mpp) udev_device_unref(udd); } @@ -54,7 +54,7 @@ index 22c11a2..7011ef7 100644 static int is_mpp_known_to_udev(const struct multipath *mpp) { -@@ -821,8 +843,8 @@ int domap(struct multipath *mpp, char *params, int is_daemon) +@@ -842,8 +864,8 @@ int domap(struct multipath *mpp, char *params, int is_daemon) * succeeded */ mpp->force_udev_reload = 0; @@ -66,19 +66,19 @@ index 22c11a2..7011ef7 100644 /* multipath client mode */ dm_switchgroup(mpp->alias, mpp->bestpg); diff --git a/libmultipath/configure.h b/libmultipath/configure.h -index 0ffc28e..09603ba 100644 +index 27a7e6f..545cbc2 100644 --- a/libmultipath/configure.h +++ b/libmultipath/configure.h @@ -37,3 +37,4 @@ int get_refwwid (enum mpath_cmds cmd, char * dev, enum devtypes dev_type, + vector pathvec, char **wwid); int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh, int is_daemon); - int sysfs_get_host_adapter_name(struct path *pp, char *adapter_name); struct udev_device *get_udev_device(const char *dev, enum devtypes dev_type); +void trigger_paths_udev_change(const struct multipath *mpp); diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c -index 88bb72b..249c6c1 100644 +index 9722714..9e9baed 100644 --- a/libmultipath/wwids.c +++ b/libmultipath/wwids.c -@@ -319,7 +319,7 @@ remember_wwid(char *wwid) +@@ -321,7 +321,7 @@ remember_wwid(char *wwid) condlog(3, "wrote wwid %s to wwids file", wwid); else condlog(4, "wwid %s already in wwids file", wwid); @@ -87,7 +87,7 @@ index 88bb72b..249c6c1 100644 } int remember_cmdline_wwid(void) -@@ -353,7 +353,7 @@ int remember_cmdline_wwid(void) +@@ -355,7 +355,7 @@ int remember_cmdline_wwid(void) next++; } if (strlen(ptr)) { @@ -97,10 +97,10 @@ index 88bb72b..249c6c1 100644 } else { diff --git a/multipath/main.c b/multipath/main.c -index ff570ac..ae6b06e 100644 +index baf6759..12d6f15 100644 --- a/multipath/main.c +++ b/multipath/main.c -@@ -416,7 +416,7 @@ configure (struct config *conf, enum mpath_cmds cmd, +@@ -427,7 +427,7 @@ configure (struct config *conf, enum mpath_cmds cmd, } if (cmd == CMD_ADD_WWID) { r = remember_wwid(refwwid); @@ -109,7 +109,7 @@ index ff570ac..ae6b06e 100644 printf("wwid '%s' added\n", refwwid); else printf("failed adding '%s' to wwids file\n", -@@ -712,16 +712,6 @@ main (int argc, char *argv[]) +@@ -782,16 +782,6 @@ main (int argc, char *argv[]) } } @@ -127,10 +127,10 @@ index ff570ac..ae6b06e 100644 fprintf(stderr, "need to be root\n"); exit(1); diff --git a/multipathd/main.c b/multipathd/main.c -index 596654c..c860e88 100644 +index 841d3e9..417fc7e 100644 --- a/multipathd/main.c +++ b/multipathd/main.c -@@ -2172,7 +2172,8 @@ configure (struct vectors * vecs) +@@ -2323,7 +2323,8 @@ configure (struct vectors * vecs) sync_maps_state(mpvec); vector_foreach_slot(mpvec, mpp, i){ @@ -140,7 +140,7 @@ index 596654c..c860e88 100644 update_map_pr(mpp); } -@@ -2251,10 +2252,6 @@ reconfigure (struct vectors * vecs) +@@ -2403,10 +2404,6 @@ reconfigure (struct vectors * vecs) conf->verbosity = verbosity; if (bindings_read_only) conf->bindings_read_only = bindings_read_only; diff --git a/0013-libmultipath-condlog-log-to-stderr.patch b/0013-libmultipath-condlog-log-to-stderr.patch deleted file mode 100644 index 8819730..0000000 --- a/0013-libmultipath-condlog-log-to-stderr.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Sat, 13 Jan 2018 22:19:21 +0100 -Subject: [PATCH] libmultipath: condlog: log to stderr - -Calling 'multipath' might result in various error messages, all -of which should be directed to stderr. -Having them intermixed with the actual output on stdout makes -parsing really hard. - -Signed-off-by: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - libmultipath/debug.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/libmultipath/debug.c b/libmultipath/debug.c -index f89b264..f95a3e5 100644 ---- a/libmultipath/debug.c -+++ b/libmultipath/debug.c -@@ -37,9 +37,9 @@ void dlog (int sink, int prio, const char * fmt, ...) - "%b %d %H:%M:%S", tb); - buff[sizeof(buff)-1] = '\0'; - -- fprintf(stdout, "%s | ", buff); -+ fprintf(stderr, "%s | ", buff); - } -- vfprintf(stdout, fmt, ap); -+ vfprintf(stderr, fmt, ap); - } - else - log_safe(prio + 3, fmt, ap); --- -2.7.4 - diff --git a/0022-RH-warn-on-invalid-regex-instead-of-failing.patch b/0014-RH-warn-on-invalid-regex-instead-of-failing.patch similarity index 87% rename from 0022-RH-warn-on-invalid-regex-instead-of-failing.patch rename to 0014-RH-warn-on-invalid-regex-instead-of-failing.patch index 5c680c1..a8b9411 100644 --- a/0022-RH-warn-on-invalid-regex-instead-of-failing.patch +++ b/0014-RH-warn-on-invalid-regex-instead-of-failing.patch @@ -16,10 +16,10 @@ Signed-off-by: Benjamin Marzinski 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/libmultipath/dict.c b/libmultipath/dict.c -index e52f1f7..31897cd 100644 +index 1a18337..167696a 100644 --- a/libmultipath/dict.c +++ b/libmultipath/dict.c -@@ -52,6 +52,21 @@ set_str(vector strvec, void *ptr) +@@ -53,6 +53,21 @@ set_str(vector strvec, void *ptr) } static int @@ -41,7 +41,7 @@ index e52f1f7..31897cd 100644 set_yes_no(vector strvec, void *ptr) { char * buff; -@@ -1200,7 +1215,7 @@ ble_ ## option ## _handler (struct config *conf, vector strvec) \ +@@ -1199,7 +1214,7 @@ ble_ ## option ## _handler (struct config *conf, vector strvec) \ if (!conf->option) \ return 1; \ \ @@ -50,7 +50,7 @@ index e52f1f7..31897cd 100644 if (!buff) \ return 1; \ \ -@@ -1216,7 +1231,7 @@ ble_ ## option ## _ ## name ## _handler (struct config *conf, vector strvec) \ +@@ -1215,7 +1230,7 @@ ble_ ## option ## _ ## name ## _handler (struct config *conf, vector strvec) \ if (!conf->option) \ return 1; \ \ @@ -59,7 +59,7 @@ index e52f1f7..31897cd 100644 if (!buff) \ return 1; \ \ -@@ -1311,16 +1326,16 @@ device_handler(struct config *conf, vector strvec) +@@ -1316,16 +1331,16 @@ device_handler(struct config *conf, vector strvec) return 0; } @@ -81,10 +81,10 @@ index e52f1f7..31897cd 100644 declare_hw_handler(hwhandler, set_str) diff --git a/libmultipath/parser.c b/libmultipath/parser.c -index c47d891..74b4efe 100644 +index b8b7e0d..34b4ad2 100644 --- a/libmultipath/parser.c +++ b/libmultipath/parser.c -@@ -346,6 +346,19 @@ set_value(vector strvec) +@@ -380,6 +380,19 @@ set_value(vector strvec) return alloc; } @@ -105,10 +105,10 @@ index c47d891..74b4efe 100644 static int kw_level = 0; diff --git a/libmultipath/parser.h b/libmultipath/parser.h -index 519b805..96f40bd 100644 +index 62906e9..b791705 100644 --- a/libmultipath/parser.h +++ b/libmultipath/parser.h -@@ -73,6 +73,7 @@ extern void dump_keywords(vector keydump, int level); +@@ -77,6 +77,7 @@ extern void dump_keywords(vector keydump, int level); extern void free_keywords(vector keywords); extern vector alloc_strvec(char *string); extern void *set_value(vector strvec); diff --git a/0014-multipathd-fix-compiler-warning-for-uev_pathfail_che.patch b/0014-multipathd-fix-compiler-warning-for-uev_pathfail_che.patch deleted file mode 100644 index 1f16290..0000000 --- a/0014-multipathd-fix-compiler-warning-for-uev_pathfail_che.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Sat, 13 Jan 2018 22:19:32 +0100 -Subject: [PATCH] multipathd: fix compiler warning for uev_pathfail_check - -gcc7 spits out an indentation warning for this function. - -Fixes: 8392431 "multipath-tools: check null path before handle path-failed event" -Signed-off-by: Benjamin Marzinski ---- - multipathd/main.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/multipathd/main.c b/multipathd/main.c -index 6dabf2c..596654c 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -1142,8 +1142,8 @@ uev_pathfail_check(struct uevent *uev, struct vectors *vecs) - lock(&vecs->lock); - pthread_testcancel(); - pp = find_path_by_devt(vecs->pathvec, devt); -- if (!pp) -- goto out_lock; -+ if (!pp) -+ goto out_lock; - r = io_err_stat_handle_pathfail(pp); - if (r) - condlog(3, "io_err_stat: %s: cannot handle pathfail uevent", --- -2.7.4 - diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index aa71c69..2ac68a4 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,38 +1,30 @@ Summary: Tools to manage multipath devices using device-mapper Name: device-mapper-multipath -Version: 0.7.4 -Release: 2.git07e7bd5%{?dist} +Version: 0.7.6 +Release: 1.git1cb704b%{?dist} License: GPL+ Group: System Environment/Base 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 "https://git.opensvc.com/?p=multipath-tools/.git;a=snapshot;h=07e7bd5;sf=tgz" -o multipath-tools-07e7bd5.tgz -Source0: multipath-tools-07e7bd5.tgz +# curl "https://git.opensvc.com/?p=multipath-tools/.git;a=snapshot;h=1cb704b;sf=tgz" -o multipath-tools-1cb704b.tgz +Source0: multipath-tools-1cb704b.tgz Source1: multipath.conf -Patch0001: 0001-libmultipath-fix-tur-checker-locking.patch -Patch0002: 0002-multipath-fix-DEF_TIMEOUT-use.patch -Patch0003: 0003-multipathd-remove-coalesce_paths-from-ev_add_map.patch -Patch0004: 0004-multipathd-remove-unused-configure-parameter.patch -Patch0005: 0005-Fix-set_no_path_retry-regression.patch -Patch0006: 0006-multipathd-change-spurious-uevent-msg-priority.patch -Patch0007: 0007-multipath-print-sysfs-state-in-fast-list-mode.patch -Patch0008: 0008-libmultipath-move-remove_map-waiter-code-to-multipat.patch -Patch0009: 0009-move-waiter-code-from-libmultipath-to-multipathd.patch -Patch0010: 0010-call-start_waiter_thread-before-setup_multipath.patch -Patch0011: 0011-libmultipath-add-helper-functions.patch -Patch0012: 0012-multipathd-RFC-add-new-polling-dmevents-waiter-threa.patch -Patch0013: 0013-libmultipath-condlog-log-to-stderr.patch -Patch0014: 0014-multipathd-fix-compiler-warning-for-uev_pathfail_che.patch -Patch0015: 0015-RH-fixup-udev-rules-for-redhat.patch -Patch0016: 0016-RH-Remove-the-property-blacklist-exception-builtin.patch -Patch0017: 0017-RH-don-t-start-without-a-config-file.patch -Patch0018: 0018-RH-use-rpm-optflags-if-present.patch -Patch0019: 0019-RH-add-mpathconf.patch -Patch0020: 0020-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch -Patch0021: 0021-RH-trigger-change-uevent-on-new-device-creation.patch -Patch0022: 0022-RH-warn-on-invalid-regex-instead-of-failing.patch +Patch0001: 0001-multipathd-remove-incorrect-pthread_testcancel.patch +Patch0002: 0002-multipath-add-comments.patch +Patch0003: 0003-multipathd-minor-dmevents-polling-code-cleanups.patch +Patch0004: 0004-multipathd-remove-unneeded-function-parameter.patch +Patch0005: 0005-mpathcmd-fix-libmpathcmd-license.patch +Patch0006: 0006-libmultipath-don-t-print-undefined-values.patch +Patch0007: 0007-RH-fixup-udev-rules-for-redhat.patch +Patch0008: 0008-RH-Remove-the-property-blacklist-exception-builtin.patch +Patch0009: 0009-RH-don-t-start-without-a-config-file.patch +Patch0010: 0010-RH-use-rpm-optflags-if-present.patch +Patch0011: 0011-RH-add-mpathconf.patch +Patch0012: 0012-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +Patch0013: 0013-RH-trigger-change-uevent-on-new-device-creation.patch +Patch0014: 0014-RH-warn-on-invalid-regex-instead-of-failing.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -110,7 +102,7 @@ This package contains the files needed to develop applications that use device-mapper-multipath's libdmmp C API library %prep -%setup -q -n multipath-tools-07e7bd5 +%setup -q -n multipath-tools-1cb704b %patch0001 -p1 %patch0002 -p1 %patch0003 -p1 @@ -125,14 +117,6 @@ device-mapper-multipath's libdmmp C API library %patch0012 -p1 %patch0013 -p1 %patch0014 -p1 -%patch0015 -p1 -%patch0016 -p1 -%patch0017 -p1 -%patch0018 -p1 -%patch0019 -p1 -%patch0020 -p1 -%patch0021 -p1 -%patch0022 -p1 cp %{SOURCE1} . %build @@ -256,6 +240,23 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Tue Apr 02 2018 Björn Esser - 0.7.6-1.git1cb704b +- Update Source to the latest upstream commit + * Previous patches 0001-0014 are included in this commit + * Previous patches 0015-0022 are now patches 0007-0014 +- 0001-multipathd-remove-incorrect-pthread_testcancel.patch + * Fixed pthread cancellation issue. posted upstream +- 0002-multipath-add-comments.patch + * Posted upstream +- 0003-multipathd-minor-dmevents-polling-code-cleanups.patch + * Fixed minor polling issues. posted upstream +- 0004-multipathd-remove-unneeded-function-parameter.patch + * Posted upstream +- 0005-mpathcmd-fix-libmpathcmd-license.patch + * License clarification. posted upstream +- 0006-libmultipath-don-t-print-undefined-values.patch + * Fixed bug in 'multipath show config'. posted upstream + * Tue Mar 06 2018 Björn Esser - 0.7.4-2.git07e7bd5 - Rebuilt for libjson-c.so.4 (json-c v0.13.1) diff --git a/sources b/sources index a7ce09f..c6db37e 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (multipath-tools-07e7bd5.tgz) = e84d451c8927119bac6612585d15497325da08d762ea6cde20d400a651fac599cb6edf4f9144204d91f92e04fec4ea3b955b9a9216ae82b513437b8ce516136a +SHA512 (multipath-tools-1cb704b.tgz) = dd4779a35681b4f9c0ba1f7fd3c0e6eac3407cb6b24e684659df27d8d3ae2bb024552611f44fefa90b38e02d2dfaf90e7f608b9868cce24c70b6be405b5ac989 SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942