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
This commit is contained in:
parent
5dbff48724
commit
e5cbd1f107
1
.gitignore
vendored
1
.gitignore
vendored
@ -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
|
||||
|
@ -1,269 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <bmarzins@redhat.com>
|
||||
---
|
||||
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 <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
+#include <urcu/uatomic.h>
|
||||
|
||||
#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
|
||||
|
30
0001-multipathd-remove-incorrect-pthread_testcancel.patch
Normal file
30
0001-multipathd-remove-incorrect-pthread_testcancel.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <mwilck@suse.com>
|
||||
Fixes: c7625f92 "multipathd: fix waiter thread cancelling"
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
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
|
||||
|
389
0002-multipath-add-comments.patch
Normal file
389
0002-multipath-add-comments.patch
Normal file
@ -0,0 +1,389 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <mwilck@suse.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -1,32 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <bmarzins@redhat.com>
|
||||
---
|
||||
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
|
||||
|
48
0003-multipathd-minor-dmevents-polling-code-cleanups.patch
Normal file
48
0003-multipathd-minor-dmevents-polling-code-cleanups.patch
Normal file
@ -0,0 +1,48 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <mwilck@suse.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -1,98 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <bmarzins@redhat.com>
|
||||
---
|
||||
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
|
||||
|
83
0004-multipathd-remove-unneeded-function-parameter.patch
Normal file
83
0004-multipathd-remove-unneeded-function-parameter.patch
Normal file
@ -0,0 +1,83 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <mwilck@suse.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -1,53 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <bmarzins@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -1,81 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <bmarzins@redhat.com>
|
||||
---
|
||||
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
|
||||
|
58
0005-mpathcmd-fix-libmpathcmd-license.patch
Normal file
58
0005-mpathcmd-fix-libmpathcmd-license.patch
Normal file
@ -0,0 +1,58 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <bmarzins@redhat.com>
|
||||
---
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
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
|
||||
|
60
0006-libmultipath-don-t-print-undefined-values.patch
Normal file
60
0006-libmultipath-don-t-print-undefined-values.patch
Normal file
@ -0,0 +1,60 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <mwilck@suse.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -1,29 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <bmarzins@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -15,10 +15,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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:
|
@ -1,68 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <bmarzins@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -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.
|
@ -1,148 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <bmarzins@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -20,7 +20,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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
|
@ -1,793 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <bmarzins@redhat.com>
|
||||
---
|
||||
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 <unistd.h>
|
||||
-#include <libdevmapper.h>
|
||||
-#include <sys/mman.h>
|
||||
-#include <pthread.h>
|
||||
-#include <signal.h>
|
||||
-#include <urcu.h>
|
||||
-
|
||||
-#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 <unistd.h>
|
||||
+#include <libdevmapper.h>
|
||||
+#include <sys/mman.h>
|
||||
+#include <pthread.h>
|
||||
+#include <signal.h>
|
||||
+#include <urcu.h>
|
||||
+
|
||||
+#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
|
||||
|
@ -9,14 +9,14 @@ still being generic.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -1,129 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <bmarzins@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -21,7 +21,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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
|
@ -1,155 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <bmarzins@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -22,10 +22,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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
|
||||
|
@ -1,643 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 <bmarzins@redhat.com>
|
||||
---
|
||||
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 <unistd.h>
|
||||
+#include <libdevmapper.h>
|
||||
+#include <sys/mman.h>
|
||||
+#include <pthread.h>
|
||||
+#include <urcu.h>
|
||||
+#include <poll.h>
|
||||
+#include <sys/ioctl.h>
|
||||
+#include <sys/types.h>
|
||||
+#include <sys/stat.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <linux/dm-ioctl.h>
|
||||
+#include <errno.h>
|
||||
+
|
||||
+#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
|
||||
|
@ -22,10 +22,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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;
|
@ -1,35 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
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 <mwilck@suse.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -16,10 +16,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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);
|
@ -1,31 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
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 <bmarzins@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -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 <besser82@fedoraproject.org> - 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 <besser82@fedoraproject.org> - 0.7.4-2.git07e7bd5
|
||||
- Rebuilt for libjson-c.so.4 (json-c v0.13.1)
|
||||
|
||||
|
2
sources
2
sources
@ -1,2 +1,2 @@
|
||||
SHA512 (multipath-tools-07e7bd5.tgz) = e84d451c8927119bac6612585d15497325da08d762ea6cde20d400a651fac599cb6edf4f9144204d91f92e04fec4ea3b955b9a9216ae82b513437b8ce516136a
|
||||
SHA512 (multipath-tools-1cb704b.tgz) = dd4779a35681b4f9c0ba1f7fd3c0e6eac3407cb6b24e684659df27d8d3ae2bb024552611f44fefa90b38e02d2dfaf90e7f608b9868cce24c70b6be405b5ac989
|
||||
SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942
|
||||
|
Loading…
Reference in New Issue
Block a user