device-mapper-multipath-0.7.4-1.git07e7bd5
Update Source to the latest upstream commit * Previous patches 0001-0006 are included in this commit * Previous patches 0007-0014 are now patches 0015-0022 Add 0001-libmultipath-fix-tur-checker-locking.patch * Fixed spinlock bug. posted upstream Add 0002-multipath-fix-DEF_TIMEOUT-use.patch * Add missing sec to ms conversion. posted upstream Add 0003-multipathd-remove-coalesce_paths-from-ev_add_map.patch * Remove unused code. posted upstream Add 0004-multipathd-remove-unused-configure-parameter.patch * Remove unused code. posted upstream Add 0005-Fix-set_no_path_retry-regression.patch * Fix issue with queueing and path addition. posted upstream Add 0006-multipathd-change-spurious-uevent-msg-priority.patch * Change message priority to Notice. posted upstream Add 0007-multipath-print-sysfs-state-in-fast-list-mode.patch * Show sysfs state correctly in fast list mode (-l). posted upstream Add 0008-libmultipath-move-remove_map-waiter-code-to-multipat.patch * Move code around. posted upstream Add 0009-move-waiter-code-from-libmultipath-to-multipathd.patch * Move code around. posted upstream Add 0010-call-start_waiter_thread-before-setup_multipath.patch * Fix race on multipath device creations. posted upstream Add 0011-libmultipath-add-helper-functions.patch * posted upstream Add 0012-multipathd-RFC-add-new-polling-dmevents-waiter-threa.patch * Add alternate method of getting dmevents, that doesn't require a thread per device. posted upstream Add 0013-libmultipath-condlog-log-to-stderr.patch * change condlog to log to stderr instead of stdout. posted upstream Add 0014-multipathd-fix-compiler-warning-for-uev_pathfail_che.patch * fix indentation issue. posted upstream
This commit is contained in:
parent
7e8f34e181
commit
5bea53fe7e
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,3 +7,4 @@ multipath-tools-091027.tar.gz
|
|||||||
/multipath.conf
|
/multipath.conf
|
||||||
/multipath-tools-git847cc43.tgz
|
/multipath-tools-git847cc43.tgz
|
||||||
/multipath-tools-0.7.3.tgz
|
/multipath-tools-0.7.3.tgz
|
||||||
|
/multipath-tools-07e7bd5.tgz
|
||||||
|
269
0001-libmultipath-fix-tur-checker-locking.patch
Normal file
269
0001-libmultipath-fix-tur-checker-locking.patch
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
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
|
||||||
|
|
@ -1,35 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
|
||||||
Date: Wed, 6 Sep 2017 16:27:36 -0500
|
|
||||||
Subject: [PATCH] mpathpersist: Fix invalid condition check
|
|
||||||
|
|
||||||
In commit 1990257c (mpathpersist: add support for prkeys file), the
|
|
||||||
check to see if mpathpersist needed to tell multipathd to update a
|
|
||||||
device's prkey was wrong. It had a typo that made it evaluate to true
|
|
||||||
for any service action, instead of just for registrations. This is the
|
|
||||||
correct check.
|
|
||||||
|
|
||||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
|
||||||
---
|
|
||||||
libmpathpersist/mpath_persist.c | 5 +++--
|
|
||||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
|
||||||
index b5ed556..84ab293 100644
|
|
||||||
--- a/libmpathpersist/mpath_persist.c
|
|
||||||
+++ b/libmpathpersist/mpath_persist.c
|
|
||||||
@@ -339,8 +339,9 @@ int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
|
||||||
|
|
||||||
memcpy(&prkey, paramp->sa_key, 8);
|
|
||||||
if (mpp->prkey_source == PRKEY_SOURCE_FILE && prkey &&
|
|
||||||
- ((!get_be64(mpp->reservation_key) && MPATH_PROUT_REG_SA) ||
|
|
||||||
- MPATH_PROUT_REG_IGN_SA)) {
|
|
||||||
+ ((!get_be64(mpp->reservation_key) &&
|
|
||||||
+ rq_servact == MPATH_PROUT_REG_SA) ||
|
|
||||||
+ rq_servact == MPATH_PROUT_REG_IGN_SA)) {
|
|
||||||
memcpy(&mpp->reservation_key, paramp->sa_key, 8);
|
|
||||||
if (update_prkey(alias, get_be64(mpp->reservation_key))) {
|
|
||||||
condlog(0, "%s: failed to set prkey for multipathd.",
|
|
||||||
--
|
|
||||||
2.7.4
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
|
||||||
Date: Tue, 19 Sep 2017 16:29:18 -0500
|
|
||||||
Subject: [PATCH] multipath: add man page info for my prkey changes
|
|
||||||
|
|
||||||
Update the man pages to list the new configuration options and
|
|
||||||
multipathd commands.
|
|
||||||
|
|
||||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
|
||||||
---
|
|
||||||
multipath/multipath.conf.5 | 17 +++++++++++++++++
|
|
||||||
multipathd/multipathd.8 | 16 ++++++++++++++++
|
|
||||||
2 files changed, 33 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
|
||||||
index 5b6dde7..92ad8b1 100644
|
|
||||||
--- a/multipath/multipath.conf.5
|
|
||||||
+++ b/multipath/multipath.conf.5
|
|
||||||
@@ -682,6 +682,17 @@ The default is: \fB/etc/multipath/wwids\fR
|
|
||||||
.
|
|
||||||
.
|
|
||||||
.TP
|
|
||||||
+.B prkeys_file
|
|
||||||
+The full pathname of the prkeys file, which is used by multipathd to keep
|
|
||||||
+track of the persistent reservation key used for a specific WWID, when
|
|
||||||
+\fIreservation_key\fR is set to \fBfile\fR.
|
|
||||||
+.RS
|
|
||||||
+.TP
|
|
||||||
+The default is \fB/etc/multipath/prkeys\fR
|
|
||||||
+.RE
|
|
||||||
+.
|
|
||||||
+.
|
|
||||||
+.TP
|
|
||||||
.B log_checker_err
|
|
||||||
If set to
|
|
||||||
.I once
|
|
||||||
@@ -703,6 +714,12 @@ the same as the RESERVATION KEY field of the PERSISTENT RESERVE OUT parameter
|
|
||||||
list which contains an 8-byte value provided by the application client to the
|
|
||||||
device server to identify the I_T nexus.
|
|
||||||
.RS
|
|
||||||
+.PP
|
|
||||||
+Alternatively, this can be set to \fBfile\fR, which will store the RESERVATION
|
|
||||||
+KEY registered by mpathpersist in the \fIprkeys_file\fR. multipathd will then
|
|
||||||
+use this key to register additional paths as they appear. When the
|
|
||||||
+registration is removed, the RESERVATION KEY is removed from the
|
|
||||||
+\fIprkeys_file\fR.
|
|
||||||
.TP
|
|
||||||
The default is: \fB<unset>\fR
|
|
||||||
.RE
|
|
||||||
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8
|
|
||||||
index 2615728..5c96680 100644
|
|
||||||
--- a/multipathd/multipathd.8
|
|
||||||
+++ b/multipathd/multipathd.8
|
|
||||||
@@ -247,6 +247,22 @@ Disable persistent reservation management on $map.
|
|
||||||
Get the current persistent reservation management status of $map.
|
|
||||||
.
|
|
||||||
.TP
|
|
||||||
+.B map|multipath $map getprkey
|
|
||||||
+Get the current persistent reservation key associated with $map.
|
|
||||||
+.
|
|
||||||
+.TP
|
|
||||||
+.B map|multipath $map setprkey key $key
|
|
||||||
+Set the persistent reservation key associated with $map to $key in the
|
|
||||||
+\fIprkeys_file\fR. This key will only be used by multipathd if
|
|
||||||
+\fIreservation_key\fR is set to \fBfile\fR in \fI/etc/multipath.conf\fR.
|
|
||||||
+.
|
|
||||||
+.TP
|
|
||||||
+.B map|multipath $map unsetprkey
|
|
||||||
+Remove the persistent reservation key associated with $map from the
|
|
||||||
+\fIprkeys_file\fR. This will only unset the key used by multipathd if
|
|
||||||
+\fIreservation_key\fR is set to \fBfile\fR in \fI/etc/multipath.conf\fR.
|
|
||||||
+.
|
|
||||||
+.TP
|
|
||||||
.B quit|exit
|
|
||||||
End interactive session.
|
|
||||||
.
|
|
||||||
--
|
|
||||||
2.7.4
|
|
||||||
|
|
32
0002-multipath-fix-DEF_TIMEOUT-use.patch
Normal file
32
0002-multipath-fix-DEF_TIMEOUT-use.patch
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
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
|
||||||
|
|
@ -1,27 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
|
||||||
Date: Thu, 26 Oct 2017 17:00:20 -0500
|
|
||||||
Subject: [PATCH] multipath: there is no "none" path state
|
|
||||||
|
|
||||||
There is a "none" path checker, but not a "none" path state.
|
|
||||||
|
|
||||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
|
||||||
---
|
|
||||||
libmultipath/checkers.c | 1 -
|
|
||||||
1 file changed, 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c
|
|
||||||
index cd6d6a3..94d8486 100644
|
|
||||||
--- a/libmultipath/checkers.c
|
|
||||||
+++ b/libmultipath/checkers.c
|
|
||||||
@@ -19,7 +19,6 @@ char *checker_state_names[] = {
|
|
||||||
"timeout",
|
|
||||||
"removed",
|
|
||||||
"delayed",
|
|
||||||
- "none",
|
|
||||||
};
|
|
||||||
|
|
||||||
static LIST_HEAD(checkers);
|
|
||||||
--
|
|
||||||
2.7.4
|
|
||||||
|
|
98
0003-multipathd-remove-coalesce_paths-from-ev_add_map.patch
Normal file
98
0003-multipathd-remove-coalesce_paths-from-ev_add_map.patch
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
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
|
||||||
|
|
53
0004-multipathd-remove-unused-configure-parameter.patch
Normal file
53
0004-multipathd-remove-unused-configure-parameter.patch
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
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,30 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
|
||||||
Date: Wed, 1 Nov 2017 19:53:11 -0500
|
|
||||||
Subject: [PATCH] mutipath: updated Huawei storage config
|
|
||||||
|
|
||||||
I was given this updated built-in config by Zhou Weigang from
|
|
||||||
Huawei.
|
|
||||||
|
|
||||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
|
||||||
---
|
|
||||||
libmultipath/hwtable.c | 3 ++-
|
|
||||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
|
|
||||||
index b018ddf..78de1fa 100644
|
|
||||||
--- a/libmultipath/hwtable.c
|
|
||||||
+++ b/libmultipath/hwtable.c
|
|
||||||
@@ -940,7 +940,8 @@ static struct hwentry default_hw[] = {
|
|
||||||
/* OceanStor V3 */
|
|
||||||
.vendor = "HUAWEI",
|
|
||||||
.product = "XSG1",
|
|
||||||
- .pgpolicy = MULTIBUS,
|
|
||||||
+ .pgpolicy = GROUP_BY_PRIO,
|
|
||||||
+ .prio_name = PRIO_ALUA,
|
|
||||||
},
|
|
||||||
/*
|
|
||||||
* Red Hat
|
|
||||||
--
|
|
||||||
2.7.4
|
|
||||||
|
|
81
0005-Fix-set_no_path_retry-regression.patch
Normal file
81
0005-Fix-set_no_path_retry-regression.patch
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
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
|
||||||
|
|
@ -1,29 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
|
||||||
Date: Wed, 1 Nov 2017 19:58:10 -0500
|
|
||||||
Subject: [PATCH] multipath: fix doc typo
|
|
||||||
|
|
||||||
The dev_loss_tmo cap if fast_io_fail_tmo isn't set is 600 seconds,
|
|
||||||
not 300 seconds.
|
|
||||||
|
|
||||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
|
||||||
---
|
|
||||||
multipath/multipath.conf.5 | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
|
||||||
index 92ad8b1..4bd1a8d 100644
|
|
||||||
--- a/multipath/multipath.conf.5
|
|
||||||
+++ b/multipath/multipath.conf.5
|
|
||||||
@@ -653,7 +653,7 @@ seconds, or 68 years. It will be automatically adjusted to the overall
|
|
||||||
retry interval \fIno_path_retry\fR * \fIpolling_interval\fR
|
|
||||||
if a number of retries is given with \fIno_path_retry\fR and the
|
|
||||||
overall retry interval is longer than the specified \fIdev_loss_tmo\fR value.
|
|
||||||
-The Linux kernel will cap this value to \fI300\fR if \fIfast_io_fail_tmo\fR
|
|
||||||
+The Linux kernel will cap this value to \fI600\fR if \fIfast_io_fail_tmo\fR
|
|
||||||
is not set. See KNOWN ISSUES.
|
|
||||||
.RS
|
|
||||||
.TP
|
|
||||||
--
|
|
||||||
2.7.4
|
|
||||||
|
|
@ -1,397 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
|
||||||
Date: Thu, 2 Nov 2017 18:02:56 -0500
|
|
||||||
Subject: [PATCH] multipath: add "ghost_delay" parameter
|
|
||||||
|
|
||||||
If the lower-priority passive paths for a multipath device appear first,
|
|
||||||
IO can go to them and cause the hardware handler to activate them,
|
|
||||||
before the higher priority paths appear, causing the devices to
|
|
||||||
failback. Setting the "ghost_delay" parameter to a value greater than
|
|
||||||
0 can avoid this ping-ponging by causing udev to not mark the device as
|
|
||||||
Ready after its initial creation until either an active path appears,
|
|
||||||
or ghost_delay seconds have passed. Multipathd does this by setting
|
|
||||||
the MPATH_UDEV_NO_PATHS_FLAG.
|
|
||||||
|
|
||||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
|
||||||
---
|
|
||||||
libmultipath/config.c | 3 +++
|
|
||||||
libmultipath/config.h | 3 +++
|
|
||||||
libmultipath/configure.c | 11 +++++++++++
|
|
||||||
libmultipath/defaults.h | 1 +
|
|
||||||
libmultipath/devmapper.c | 2 +-
|
|
||||||
libmultipath/dict.c | 14 ++++++++++++++
|
|
||||||
libmultipath/hwtable.c | 1 +
|
|
||||||
libmultipath/propsel.c | 15 +++++++++++++++
|
|
||||||
libmultipath/propsel.h | 1 +
|
|
||||||
libmultipath/structs.h | 7 +++++++
|
|
||||||
multipath/multipath.conf.5 | 19 +++++++++++++++++++
|
|
||||||
multipathd/main.c | 28 +++++++++++++++++++++++++++-
|
|
||||||
12 files changed, 103 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
|
||||||
index ea2359a..9486116 100644
|
|
||||||
--- a/libmultipath/config.c
|
|
||||||
+++ b/libmultipath/config.c
|
|
||||||
@@ -351,6 +351,7 @@ merge_hwe (struct hwentry * dst, struct hwentry * src)
|
|
||||||
merge_num(delay_wait_checks);
|
|
||||||
merge_num(skip_kpartx);
|
|
||||||
merge_num(max_sectors_kb);
|
|
||||||
+ merge_num(ghost_delay);
|
|
||||||
merge_num(san_path_err_threshold);
|
|
||||||
merge_num(san_path_err_forget_rate);
|
|
||||||
merge_num(san_path_err_recovery_time);
|
|
||||||
@@ -422,6 +423,7 @@ store_hwe (vector hwtable, struct hwentry * dhwe)
|
|
||||||
hwe->retain_hwhandler = dhwe->retain_hwhandler;
|
|
||||||
hwe->detect_prio = dhwe->detect_prio;
|
|
||||||
hwe->detect_checker = dhwe->detect_checker;
|
|
||||||
+ hwe->ghost_delay = dhwe->ghost_delay;
|
|
||||||
|
|
||||||
if (dhwe->bl_product && !(hwe->bl_product = set_param_str(dhwe->bl_product)))
|
|
||||||
goto out;
|
|
||||||
@@ -622,6 +624,7 @@ load_config (char * file)
|
|
||||||
conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT;
|
|
||||||
conf->disable_changed_wwids = DEFAULT_DISABLE_CHANGED_WWIDS;
|
|
||||||
conf->remove_retries = 0;
|
|
||||||
+ conf->ghost_delay = DEFAULT_GHOST_DELAY;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* preload default hwtable
|
|
||||||
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
|
||||||
index 240730b..67ff983 100644
|
|
||||||
--- a/libmultipath/config.h
|
|
||||||
+++ b/libmultipath/config.h
|
|
||||||
@@ -80,6 +80,7 @@ struct hwentry {
|
|
||||||
int san_path_err_recovery_time;
|
|
||||||
int skip_kpartx;
|
|
||||||
int max_sectors_kb;
|
|
||||||
+ int ghost_delay;
|
|
||||||
char * bl_product;
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -112,6 +113,7 @@ struct mpentry {
|
|
||||||
int san_path_err_recovery_time;
|
|
||||||
int skip_kpartx;
|
|
||||||
int max_sectors_kb;
|
|
||||||
+ int ghost_delay;
|
|
||||||
uid_t uid;
|
|
||||||
gid_t gid;
|
|
||||||
mode_t mode;
|
|
||||||
@@ -170,6 +172,7 @@ struct config {
|
|
||||||
int disable_changed_wwids;
|
|
||||||
int remove_retries;
|
|
||||||
int max_sectors_kb;
|
|
||||||
+ int ghost_delay;
|
|
||||||
unsigned int version[3];
|
|
||||||
|
|
||||||
char * multipath_dir;
|
|
||||||
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
|
||||||
index 7a3db31..e2f393f 100644
|
|
||||||
--- a/libmultipath/configure.c
|
|
||||||
+++ b/libmultipath/configure.c
|
|
||||||
@@ -300,6 +300,7 @@ int setup_map(struct multipath *mpp, char *params, int params_size)
|
|
||||||
select_san_path_err_recovery_time(conf, mpp);
|
|
||||||
select_skip_kpartx(conf, mpp);
|
|
||||||
select_max_sectors_kb(conf, mpp);
|
|
||||||
+ select_ghost_delay(conf, mpp);
|
|
||||||
|
|
||||||
sysfs_set_scsi_tmo(mpp, conf->checkint);
|
|
||||||
put_multipath_config(conf);
|
|
||||||
@@ -760,6 +761,9 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
|
|
||||||
}
|
|
||||||
|
|
||||||
sysfs_set_max_sectors_kb(mpp, 0);
|
|
||||||
+ if (is_daemon && mpp->ghost_delay > 0 && mpp->nr_active &&
|
|
||||||
+ pathcount(mpp, PATH_GHOST) == mpp->nr_active)
|
|
||||||
+ mpp->ghost_delay_tick = mpp->ghost_delay;
|
|
||||||
r = dm_addmap_create(mpp, params);
|
|
||||||
|
|
||||||
lock_multipath(mpp, 0);
|
|
||||||
@@ -767,11 +771,15 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
|
|
||||||
|
|
||||||
case ACT_RELOAD:
|
|
||||||
sysfs_set_max_sectors_kb(mpp, 1);
|
|
||||||
+ if (mpp->ghost_delay_tick > 0 && pathcount(mpp, PATH_UP))
|
|
||||||
+ mpp->ghost_delay_tick = 0;
|
|
||||||
r = dm_addmap_reload(mpp, params, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ACT_RESIZE:
|
|
||||||
sysfs_set_max_sectors_kb(mpp, 1);
|
|
||||||
+ if (mpp->ghost_delay_tick > 0 && pathcount(mpp, PATH_UP))
|
|
||||||
+ mpp->ghost_delay_tick = 0;
|
|
||||||
r = dm_addmap_reload(mpp, params, 1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
@@ -789,6 +797,9 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
|
|
||||||
put_multipath_config(conf);
|
|
||||||
if (r) {
|
|
||||||
sysfs_set_max_sectors_kb(mpp, 1);
|
|
||||||
+ if (mpp->ghost_delay_tick > 0 &&
|
|
||||||
+ pathcount(mpp, PATH_UP))
|
|
||||||
+ mpp->ghost_delay_tick = 0;
|
|
||||||
r = dm_addmap_reload(mpp, params, 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
|
|
||||||
index 740ccf4..c9e3411 100644
|
|
||||||
--- a/libmultipath/defaults.h
|
|
||||||
+++ b/libmultipath/defaults.h
|
|
||||||
@@ -40,6 +40,7 @@
|
|
||||||
#define DEFAULT_SKIP_KPARTX SKIP_KPARTX_OFF
|
|
||||||
#define DEFAULT_DISABLE_CHANGED_WWIDS 0
|
|
||||||
#define DEFAULT_MAX_SECTORS_KB MAX_SECTORS_KB_UNDEF
|
|
||||||
+#define DEFAULT_GHOST_DELAY GHOST_DELAY_OFF
|
|
||||||
|
|
||||||
#define DEFAULT_CHECKINT 5
|
|
||||||
#define MAX_CHECKINT(a) (a << 2)
|
|
||||||
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
|
||||||
index fcac6bc..573fc75 100644
|
|
||||||
--- a/libmultipath/devmapper.c
|
|
||||||
+++ b/libmultipath/devmapper.c
|
|
||||||
@@ -378,7 +378,7 @@ static uint16_t build_udev_flags(const struct multipath *mpp, int reload)
|
|
||||||
/* DM_UDEV_DISABLE_LIBRARY_FALLBACK is added in dm_addmap */
|
|
||||||
return (mpp->skip_kpartx == SKIP_KPARTX_ON ?
|
|
||||||
MPATH_UDEV_NO_KPARTX_FLAG : 0) |
|
|
||||||
- (mpp->nr_active == 0 ?
|
|
||||||
+ ((mpp->nr_active == 0 || mpp->ghost_delay_tick > 0)?
|
|
||||||
MPATH_UDEV_NO_PATHS_FLAG : 0) |
|
|
||||||
(reload && !mpp->force_udev_reload ?
|
|
||||||
MPATH_UDEV_RELOAD_FLAG : 0);
|
|
||||||
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
|
||||||
index 36cccc9..54652d4 100644
|
|
||||||
--- a/libmultipath/dict.c
|
|
||||||
+++ b/libmultipath/dict.c
|
|
||||||
@@ -1110,6 +1110,16 @@ declare_hw_handler(san_path_err_recovery_time, set_off_int_undef)
|
|
||||||
declare_hw_snprint(san_path_err_recovery_time, print_off_int_undef)
|
|
||||||
declare_mp_handler(san_path_err_recovery_time, set_off_int_undef)
|
|
||||||
declare_mp_snprint(san_path_err_recovery_time, print_off_int_undef)
|
|
||||||
+
|
|
||||||
+declare_def_handler(ghost_delay, set_off_int_undef)
|
|
||||||
+declare_def_snprint(ghost_delay, print_off_int_undef)
|
|
||||||
+declare_ovr_handler(ghost_delay, set_off_int_undef)
|
|
||||||
+declare_ovr_snprint(ghost_delay, print_off_int_undef)
|
|
||||||
+declare_hw_handler(ghost_delay, set_off_int_undef)
|
|
||||||
+declare_hw_snprint(ghost_delay, print_off_int_undef)
|
|
||||||
+declare_mp_handler(ghost_delay, set_off_int_undef)
|
|
||||||
+declare_mp_snprint(ghost_delay, print_off_int_undef)
|
|
||||||
+
|
|
||||||
static int
|
|
||||||
def_uxsock_timeout_handler(struct config *conf, vector strvec)
|
|
||||||
{
|
|
||||||
@@ -1456,6 +1466,7 @@ init_keywords(vector keywords)
|
|
||||||
install_keyword("disable_changed_wwids", &def_disable_changed_wwids_handler, &snprint_def_disable_changed_wwids);
|
|
||||||
install_keyword("remove_retries", &def_remove_retries_handler, &snprint_def_remove_retries);
|
|
||||||
install_keyword("max_sectors_kb", &def_max_sectors_kb_handler, &snprint_def_max_sectors_kb);
|
|
||||||
+ install_keyword("ghost_delay", &def_ghost_delay_handler, &snprint_def_ghost_delay);
|
|
||||||
__deprecated install_keyword("default_selector", &def_selector_handler, NULL);
|
|
||||||
__deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
|
|
||||||
__deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL);
|
|
||||||
@@ -1535,6 +1546,7 @@ init_keywords(vector keywords)
|
|
||||||
install_keyword("san_path_err_recovery_time", &hw_san_path_err_recovery_time_handler, &snprint_hw_san_path_err_recovery_time);
|
|
||||||
install_keyword("skip_kpartx", &hw_skip_kpartx_handler, &snprint_hw_skip_kpartx);
|
|
||||||
install_keyword("max_sectors_kb", &hw_max_sectors_kb_handler, &snprint_hw_max_sectors_kb);
|
|
||||||
+ install_keyword("ghost_delay", &hw_ghost_delay_handler, &snprint_hw_ghost_delay);
|
|
||||||
install_sublevel_end();
|
|
||||||
|
|
||||||
install_keyword_root("overrides", &overrides_handler);
|
|
||||||
@@ -1569,6 +1581,7 @@ init_keywords(vector keywords)
|
|
||||||
|
|
||||||
install_keyword("skip_kpartx", &ovr_skip_kpartx_handler, &snprint_ovr_skip_kpartx);
|
|
||||||
install_keyword("max_sectors_kb", &ovr_max_sectors_kb_handler, &snprint_ovr_max_sectors_kb);
|
|
||||||
+ install_keyword("ghost_delay", &ovr_ghost_delay_handler, &snprint_ovr_ghost_delay);
|
|
||||||
|
|
||||||
install_keyword_root("multipaths", &multipaths_handler);
|
|
||||||
install_keyword_multi("multipath", &multipath_handler, NULL);
|
|
||||||
@@ -1600,5 +1613,6 @@ init_keywords(vector keywords)
|
|
||||||
install_keyword("san_path_err_recovery_time", &mp_san_path_err_recovery_time_handler, &snprint_mp_san_path_err_recovery_time);
|
|
||||||
install_keyword("skip_kpartx", &mp_skip_kpartx_handler, &snprint_mp_skip_kpartx);
|
|
||||||
install_keyword("max_sectors_kb", &mp_max_sectors_kb_handler, &snprint_mp_max_sectors_kb);
|
|
||||||
+ install_keyword("ghost_delay", &mp_ghost_delay_handler, &snprint_mp_ghost_delay);
|
|
||||||
install_sublevel_end();
|
|
||||||
}
|
|
||||||
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
|
|
||||||
index 78de1fa..7226fb1 100644
|
|
||||||
--- a/libmultipath/hwtable.c
|
|
||||||
+++ b/libmultipath/hwtable.c
|
|
||||||
@@ -72,6 +72,7 @@
|
|
||||||
.delay_wait_checks = DELAY_CHECKS_OFF,
|
|
||||||
.skip_kpartx = SKIP_KPARTX_OFF,
|
|
||||||
.max_sectors_kb = MAX_SECTORS_KB_UNDEF,
|
|
||||||
+ .ghost_delay = GHOST_DELAY_OFF
|
|
||||||
},
|
|
||||||
#endif
|
|
||||||
|
|
||||||
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
|
||||||
index 00adc0d..6721cc6 100644
|
|
||||||
--- a/libmultipath/propsel.c
|
|
||||||
+++ b/libmultipath/propsel.c
|
|
||||||
@@ -835,3 +835,18 @@ out:
|
|
||||||
origin);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+int select_ghost_delay (struct config *conf, struct multipath * mp)
|
|
||||||
+{
|
|
||||||
+ char *origin, buff[12];
|
|
||||||
+
|
|
||||||
+ mp_set_mpe(ghost_delay);
|
|
||||||
+ mp_set_ovr(ghost_delay);
|
|
||||||
+ mp_set_hwe(ghost_delay);
|
|
||||||
+ mp_set_conf(ghost_delay);
|
|
||||||
+ mp_set_default(ghost_delay, DEFAULT_GHOST_DELAY);
|
|
||||||
+out:
|
|
||||||
+ print_off_int_undef(buff, 12, &mp->ghost_delay);
|
|
||||||
+ condlog(3, "%s: ghost_delay = %s %s", mp->alias, buff, origin);
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
diff --git a/libmultipath/propsel.h b/libmultipath/propsel.h
|
|
||||||
index f8e96d8..494fb10 100644
|
|
||||||
--- a/libmultipath/propsel.h
|
|
||||||
+++ b/libmultipath/propsel.h
|
|
||||||
@@ -25,6 +25,7 @@ int select_delay_watch_checks (struct config *conf, struct multipath * mp);
|
|
||||||
int select_delay_wait_checks (struct config *conf, struct multipath * mp);
|
|
||||||
int select_skip_kpartx (struct config *conf, struct multipath * mp);
|
|
||||||
int select_max_sectors_kb (struct config *conf, struct multipath * mp);
|
|
||||||
+int select_ghost_delay(struct config *conf, struct multipath * mp);
|
|
||||||
int select_san_path_err_forget_rate(struct config *conf, struct multipath *mp);
|
|
||||||
int select_san_path_err_threshold(struct config *conf, struct multipath *mp);
|
|
||||||
int select_san_path_err_recovery_time(struct config *conf, struct multipath *mp);
|
|
||||||
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
|
||||||
index f06824a..d2d7701 100644
|
|
||||||
--- a/libmultipath/structs.h
|
|
||||||
+++ b/libmultipath/structs.h
|
|
||||||
@@ -167,6 +167,11 @@ enum no_undef_states {
|
|
||||||
NU_UNDEF = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
+enum ghost_delay_states {
|
|
||||||
+ GHOST_DELAY_OFF = NU_NO,
|
|
||||||
+ GHOST_DELAY_UNDEF = NU_UNDEF,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
enum initialized_states {
|
|
||||||
INIT_FAILED,
|
|
||||||
INIT_MISSING_UDEV,
|
|
||||||
@@ -282,6 +287,8 @@ struct multipath {
|
|
||||||
int max_sectors_kb;
|
|
||||||
int force_readonly;
|
|
||||||
int force_udev_reload;
|
|
||||||
+ int ghost_delay;
|
|
||||||
+ int ghost_delay_tick;
|
|
||||||
unsigned int dev_loss;
|
|
||||||
uid_t uid;
|
|
||||||
gid_t gid;
|
|
||||||
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
|
||||||
index 4bd1a8d..8783124 100644
|
|
||||||
--- a/multipath/multipath.conf.5
|
|
||||||
+++ b/multipath/multipath.conf.5
|
|
||||||
@@ -1017,6 +1017,19 @@ The default is: \fB<device dependent>\fR
|
|
||||||
.RE
|
|
||||||
.
|
|
||||||
.
|
|
||||||
+.TP
|
|
||||||
+.B ghost_delay
|
|
||||||
+Sets the number of seconds that multipath will wait after creating a device
|
|
||||||
+with only ghost paths before marking it ready for use in systemd. This gives
|
|
||||||
+the active paths time to appear before the multipath runs the hardware handler
|
|
||||||
+to switch the ghost paths to active ones. Setting this to \fI0\fR or \fIon\fR
|
|
||||||
+makes multipath immediately mark a device with only ghost paths as ready.
|
|
||||||
+.RS
|
|
||||||
+.TP
|
|
||||||
+The default is \fBno\fR
|
|
||||||
+.RE
|
|
||||||
+.
|
|
||||||
+.
|
|
||||||
.\" ----------------------------------------------------------------------------
|
|
||||||
.SH "blacklist section"
|
|
||||||
.\" ----------------------------------------------------------------------------
|
|
||||||
@@ -1157,6 +1170,8 @@ are taken from the \fIdefaults\fR or \fIdevices\fR section:
|
|
||||||
.B skip_kpartx
|
|
||||||
.TP
|
|
||||||
.B max_sectors_kb
|
|
||||||
+.TP
|
|
||||||
+.B ghost_delay
|
|
||||||
.RE
|
|
||||||
.PD
|
|
||||||
.LP
|
|
||||||
@@ -1284,6 +1299,8 @@ section:
|
|
||||||
.B skip_kpartx
|
|
||||||
.TP
|
|
||||||
.B max_sectors_kb
|
|
||||||
+.TP
|
|
||||||
+.B ghost_delay
|
|
||||||
.RE
|
|
||||||
.PD
|
|
||||||
.LP
|
|
||||||
@@ -1354,6 +1371,8 @@ the values are taken from the \fIdevices\fR or \fIdefaults\fR sections:
|
|
||||||
.B delay_wait_checks
|
|
||||||
.TP
|
|
||||||
.B skip_kpartx
|
|
||||||
+.TP
|
|
||||||
+.B ghost_delay
|
|
||||||
.RE
|
|
||||||
.PD
|
|
||||||
.LP
|
|
||||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
|
||||||
index 8049da2..c475fcd 100644
|
|
||||||
--- a/multipathd/main.c
|
|
||||||
+++ b/multipathd/main.c
|
|
||||||
@@ -351,6 +351,8 @@ sync_map_state(struct multipath *mpp)
|
|
||||||
pp->state == PATH_WILD ||
|
|
||||||
pp->state == PATH_DELAYED)
|
|
||||||
continue;
|
|
||||||
+ if (mpp->ghost_delay_tick > 0)
|
|
||||||
+ continue;
|
|
||||||
if ((pp->dmstate == PSTATE_FAILED ||
|
|
||||||
pp->dmstate == PSTATE_UNDEF) &&
|
|
||||||
(pp->state == PATH_UP || pp->state == PATH_GHOST))
|
|
||||||
@@ -735,7 +737,8 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map)
|
|
||||||
mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid);
|
|
||||||
if (mpp && mpp->wait_for_udev &&
|
|
||||||
(pathcount(mpp, PATH_UP) > 0 ||
|
|
||||||
- (pathcount(mpp, PATH_GHOST) > 0 && pp->tpgs != TPGS_IMPLICIT))) {
|
|
||||||
+ (pathcount(mpp, PATH_GHOST) > 0 && pp->tpgs != TPGS_IMPLICIT &&
|
|
||||||
+ mpp->ghost_delay_tick <= 0))) {
|
|
||||||
/* if wait_for_udev is set and valid paths exist */
|
|
||||||
condlog(2, "%s: delaying path addition until %s is fully initialized", pp->dev, mpp->alias);
|
|
||||||
mpp->wait_for_udev = 2;
|
|
||||||
@@ -1416,6 +1419,28 @@ missing_uev_wait_tick(struct vectors *vecs)
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
+ghost_delay_tick(struct vectors *vecs)
|
|
||||||
+{
|
|
||||||
+ struct multipath * mpp;
|
|
||||||
+ unsigned int i;
|
|
||||||
+
|
|
||||||
+ vector_foreach_slot (vecs->mpvec, mpp, i) {
|
|
||||||
+ if (mpp->ghost_delay_tick <= 0)
|
|
||||||
+ continue;
|
|
||||||
+ if (--mpp->ghost_delay_tick <= 0) {
|
|
||||||
+ condlog(0, "%s: timed out waiting for active path",
|
|
||||||
+ mpp->alias);
|
|
||||||
+ mpp->force_udev_reload = 1;
|
|
||||||
+ if (update_map(mpp, vecs) != 0) {
|
|
||||||
+ /* update_map removed map */
|
|
||||||
+ i--;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
defered_failback_tick (vector mpvec)
|
|
||||||
{
|
|
||||||
struct multipath * mpp;
|
|
||||||
@@ -1961,6 +1986,7 @@ checkerloop (void *ap)
|
|
||||||
defered_failback_tick(vecs->mpvec);
|
|
||||||
retry_count_tick(vecs->mpvec);
|
|
||||||
missing_uev_wait_tick(vecs);
|
|
||||||
+ ghost_delay_tick(vecs);
|
|
||||||
lock_cleanup_pop(vecs->lock);
|
|
||||||
|
|
||||||
if (count)
|
|
||||||
--
|
|
||||||
2.7.4
|
|
||||||
|
|
29
0006-multipathd-change-spurious-uevent-msg-priority.patch
Normal file
29
0006-multipathd-change-spurious-uevent-msg-priority.patch
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
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
|
||||||
|
|
68
0007-multipath-print-sysfs-state-in-fast-list-mode.patch
Normal file
68
0007-multipath-print-sysfs-state-in-fast-list-mode.patch
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
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
|
||||||
|
|
148
0008-libmultipath-move-remove_map-waiter-code-to-multipat.patch
Normal file
148
0008-libmultipath-move-remove_map-waiter-code-to-multipat.patch
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
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
|
||||||
|
|
793
0009-move-waiter-code-from-libmultipath-to-multipathd.patch
Normal file
793
0009-move-waiter-code-from-libmultipath-to-multipathd.patch
Normal file
@ -0,0 +1,793 @@
|
|||||||
|
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
|
||||||
|
|
129
0010-call-start_waiter_thread-before-setup_multipath.patch
Normal file
129
0010-call-start_waiter_thread-before-setup_multipath.patch
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
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
|
||||||
|
|
155
0011-libmultipath-add-helper-functions.patch
Normal file
155
0011-libmultipath-add-helper-functions.patch
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
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
|
||||||
|
|
643
0012-multipathd-RFC-add-new-polling-dmevents-waiter-threa.patch
Normal file
643
0012-multipathd-RFC-add-new-polling-dmevents-waiter-threa.patch
Normal file
@ -0,0 +1,643 @@
|
|||||||
|
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
|
||||||
|
|
35
0013-libmultipath-condlog-log-to-stderr.patch
Normal file
35
0013-libmultipath-condlog-log-to-stderr.patch
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
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
|
||||||
|
|
@ -0,0 +1,31 @@
|
|||||||
|
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
|
||||||
|
|
@ -15,7 +15,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
|||||||
3 files changed, 4 insertions(+), 4 deletions(-)
|
3 files changed, 4 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
diff --git a/Makefile.inc b/Makefile.inc
|
diff --git a/Makefile.inc b/Makefile.inc
|
||||||
index 29c290a..cea015b 100644
|
index d953f5e..5145909 100644
|
||||||
--- a/Makefile.inc
|
--- a/Makefile.inc
|
||||||
+++ b/Makefile.inc
|
+++ b/Makefile.inc
|
||||||
@@ -48,7 +48,7 @@ endif
|
@@ -48,7 +48,7 @@ endif
|
@ -51,10 +51,10 @@ index ee396e2..19d4697 100644
|
|||||||
|
|
||||||
void
|
void
|
||||||
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
||||||
index 8783124..fa4333d 100644
|
index ab151e7..2201d7f 100644
|
||||||
--- a/multipath/multipath.conf.5
|
--- a/multipath/multipath.conf.5
|
||||||
+++ b/multipath/multipath.conf.5
|
+++ b/multipath/multipath.conf.5
|
||||||
@@ -1085,10 +1085,6 @@ The \fIWorld Wide Identification\fR of a device.
|
@@ -1114,10 +1114,6 @@ The \fIWorld Wide Identification\fR of a device.
|
||||||
.TP
|
.TP
|
||||||
.B property
|
.B property
|
||||||
Regular expression of the udev property to be whitelisted.
|
Regular expression of the udev property to be whitelisted.
|
@ -12,15 +12,15 @@ simple way to disable multipath. Simply removing or renaming
|
|||||||
|
|
||||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
---
|
---
|
||||||
libmultipath/config.c | 17 +++++++++++++++++
|
libmultipath/config.c | 15 +++++++++++++++
|
||||||
libmultipath/config.h | 1 +
|
libmultipath/config.h | 1 +
|
||||||
multipath/multipath.rules | 1 +
|
multipath/multipath.rules | 1 +
|
||||||
multipathd/multipathd.8 | 2 ++
|
multipathd/multipathd.8 | 2 ++
|
||||||
multipathd/multipathd.service | 1 +
|
multipathd/multipathd.service | 1 +
|
||||||
5 files changed, 22 insertions(+)
|
5 files changed, 20 insertions(+)
|
||||||
|
|
||||||
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||||
index 9486116..85e32ee 100644
|
index 3d6a24c..27826fa 100644
|
||||||
--- a/libmultipath/config.c
|
--- a/libmultipath/config.c
|
||||||
+++ b/libmultipath/config.c
|
+++ b/libmultipath/config.c
|
||||||
@@ -26,6 +26,7 @@
|
@@ -26,6 +26,7 @@
|
||||||
@ -31,14 +31,12 @@ index 9486116..85e32ee 100644
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
hwe_strmatch (struct hwentry *hwe1, struct hwentry *hwe2)
|
hwe_strmatch (struct hwentry *hwe1, struct hwentry *hwe2)
|
||||||
@@ -659,6 +660,22 @@ load_config (char * file)
|
@@ -656,6 +657,20 @@ load_config (char * file)
|
||||||
factorize_hwtable(conf->hwtable, builtin_hwtable_size);
|
factorize_hwtable(conf->hwtable, builtin_hwtable_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
+ } else {
|
+ } else {
|
||||||
+ condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
|
+ condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
|
||||||
+ condlog(0, "A default multipath.conf file is located at");
|
|
||||||
+ condlog(0, "/usr/share/doc/device-mapper-multipath-%d.%d.%d/multipath.conf", MULTIPATH_VERSION(VERSION_CODE));
|
|
||||||
+ if (conf->blist_devnode == NULL) {
|
+ if (conf->blist_devnode == NULL) {
|
||||||
+ conf->blist_devnode = vector_alloc();
|
+ conf->blist_devnode = vector_alloc();
|
||||||
+ if (!conf->blist_devnode) {
|
+ if (!conf->blist_devnode) {
|
||||||
@ -55,7 +53,7 @@ index 9486116..85e32ee 100644
|
|||||||
|
|
||||||
conf->processed_main_config = 1;
|
conf->processed_main_config = 1;
|
||||||
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||||
index 67ff983..1dbb9a7 100644
|
index a20ac2a..21a3bbd 100644
|
||||||
--- a/libmultipath/config.h
|
--- a/libmultipath/config.h
|
||||||
+++ b/libmultipath/config.h
|
+++ b/libmultipath/config.h
|
||||||
@@ -9,6 +9,7 @@
|
@@ -9,6 +9,7 @@
|
@ -13,7 +13,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
|||||||
1 file changed, 15 insertions(+), 7 deletions(-)
|
1 file changed, 15 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
diff --git a/Makefile.inc b/Makefile.inc
|
diff --git a/Makefile.inc b/Makefile.inc
|
||||||
index cea015b..d6b4ef7 100644
|
index 5145909..0b4ee17 100644
|
||||||
--- a/Makefile.inc
|
--- a/Makefile.inc
|
||||||
+++ b/Makefile.inc
|
+++ b/Makefile.inc
|
||||||
@@ -82,13 +82,21 @@ TEST_CC_OPTION = $(shell \
|
@@ -82,13 +82,21 @@ TEST_CC_OPTION = $(shell \
|
||||||
@ -43,8 +43,8 @@ index cea015b..d6b4ef7 100644
|
|||||||
+ -Werror=implicit-function-declaration -Wno-sign-compare \
|
+ -Werror=implicit-function-declaration -Wno-sign-compare \
|
||||||
+ -Wno-unused-parameter
|
+ -Wno-unused-parameter
|
||||||
|
|
||||||
CFLAGS = $(OPTFLAGS) -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\"
|
CFLAGS := $(OPTFLAGS) -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \
|
||||||
BIN_CFLAGS = -fPIE -DPIE
|
$(CFLAGS)
|
||||||
--
|
--
|
||||||
2.7.4
|
2.7.4
|
||||||
|
|
@ -21,13 +21,13 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
|||||||
create mode 100644 multipath/mpathconf.8
|
create mode 100644 multipath/mpathconf.8
|
||||||
|
|
||||||
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||||
index 85e32ee..f1a6ca8 100644
|
index 27826fa..9bf4fb7 100644
|
||||||
--- a/libmultipath/config.c
|
--- a/libmultipath/config.c
|
||||||
+++ b/libmultipath/config.c
|
+++ b/libmultipath/config.c
|
||||||
@@ -664,6 +664,7 @@ load_config (char * file)
|
@@ -659,6 +659,7 @@ load_config (char * file)
|
||||||
|
|
||||||
|
} else {
|
||||||
condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
|
condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
|
||||||
condlog(0, "A default multipath.conf file is located at");
|
|
||||||
condlog(0, "/usr/share/doc/device-mapper-multipath-%d.%d.%d/multipath.conf", MULTIPATH_VERSION(VERSION_CODE));
|
|
||||||
+ condlog(0, "You can run /sbin/mpathconf to create or modify /etc/multipath.conf");
|
+ condlog(0, "You can run /sbin/mpathconf to create or modify /etc/multipath.conf");
|
||||||
if (conf->blist_devnode == NULL) {
|
if (conf->blist_devnode == NULL) {
|
||||||
conf->blist_devnode = vector_alloc();
|
conf->blist_devnode = vector_alloc();
|
@ -85,7 +85,7 @@ index 9527012..b665232 100644
|
|||||||
|
|
||||||
#endif /* _WWIDS_H */
|
#endif /* _WWIDS_H */
|
||||||
diff --git a/multipath/main.c b/multipath/main.c
|
diff --git a/multipath/main.c b/multipath/main.c
|
||||||
index bffe065..2e69300 100644
|
index d2415a9..ff570ac 100644
|
||||||
--- a/multipath/main.c
|
--- a/multipath/main.c
|
||||||
+++ b/multipath/main.c
|
+++ b/multipath/main.c
|
||||||
@@ -102,7 +102,7 @@ usage (char * progname)
|
@@ -102,7 +102,7 @@ usage (char * progname)
|
||||||
@ -106,7 +106,7 @@ index bffe065..2e69300 100644
|
|||||||
" -c check if a device should be a path in a multipath device\n"
|
" -c check if a device should be a path in a multipath device\n"
|
||||||
" -C check if a multipath device has usable paths\n"
|
" -C check if a multipath device has usable paths\n"
|
||||||
" -q allow queue_if_no_path when multipathd is not running\n"
|
" -q allow queue_if_no_path when multipathd is not running\n"
|
||||||
@@ -598,7 +600,7 @@ main (int argc, char *argv[])
|
@@ -602,7 +604,7 @@ main (int argc, char *argv[])
|
||||||
exit(1);
|
exit(1);
|
||||||
multipath_conf = conf;
|
multipath_conf = conf;
|
||||||
conf->retrigger_tries = 0;
|
conf->retrigger_tries = 0;
|
||||||
@ -115,7 +115,7 @@ index bffe065..2e69300 100644
|
|||||||
switch(arg) {
|
switch(arg) {
|
||||||
case 1: printf("optarg : %s\n",optarg);
|
case 1: printf("optarg : %s\n",optarg);
|
||||||
break;
|
break;
|
||||||
@@ -665,6 +667,10 @@ main (int argc, char *argv[])
|
@@ -669,6 +671,10 @@ main (int argc, char *argv[])
|
||||||
case 't':
|
case 't':
|
||||||
r = dump_config(conf);
|
r = dump_config(conf);
|
||||||
goto out_free_config;
|
goto out_free_config;
|
@ -9,22 +9,23 @@ that it will not claim the device in udev. If the device is eventually
|
|||||||
multipathed, multipath should trigger a change uevent to update the udev
|
multipathed, multipath should trigger a change uevent to update the udev
|
||||||
database to claim the device.
|
database to claim the device.
|
||||||
|
|
||||||
This also reverts commit 64e27ec066a001012f44550f095c93443e91d845.
|
This also reverts commit 64e27ec066a001012f44550f095c93443e91d845 and
|
||||||
|
commit ffbb886a8a16cb063d669cd76a1e656fd3ec8c4b.
|
||||||
|
|
||||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
---
|
---
|
||||||
libmultipath/configure.c | 26 ++++++++++++++++++++++++--
|
libmultipath/configure.c | 26 ++++++++++++++++++++++++--
|
||||||
libmultipath/configure.h | 1 +
|
libmultipath/configure.h | 1 +
|
||||||
libmultipath/wwids.c | 4 ++--
|
libmultipath/wwids.c | 4 ++--
|
||||||
multipath/main.c | 2 +-
|
multipath/main.c | 12 +-----------
|
||||||
multipathd/main.c | 7 ++-----
|
multipathd/main.c | 7 ++-----
|
||||||
5 files changed, 30 insertions(+), 10 deletions(-)
|
5 files changed, 30 insertions(+), 20 deletions(-)
|
||||||
|
|
||||||
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
||||||
index e2f393f..64d7751 100644
|
index 22c11a2..7011ef7 100644
|
||||||
--- a/libmultipath/configure.c
|
--- a/libmultipath/configure.c
|
||||||
+++ b/libmultipath/configure.c
|
+++ b/libmultipath/configure.c
|
||||||
@@ -423,6 +423,28 @@ trigger_udev_change(const struct multipath *mpp)
|
@@ -427,6 +427,28 @@ trigger_udev_change(const struct multipath *mpp)
|
||||||
udev_device_unref(udd);
|
udev_device_unref(udd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +54,7 @@ index e2f393f..64d7751 100644
|
|||||||
static int
|
static int
|
||||||
is_mpp_known_to_udev(const struct multipath *mpp)
|
is_mpp_known_to_udev(const struct multipath *mpp)
|
||||||
{
|
{
|
||||||
@@ -814,8 +836,8 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
|
@@ -821,8 +843,8 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
|
||||||
* succeeded
|
* succeeded
|
||||||
*/
|
*/
|
||||||
mpp->force_udev_reload = 0;
|
mpp->force_udev_reload = 0;
|
||||||
@ -96,10 +97,10 @@ index 88bb72b..249c6c1 100644
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
diff --git a/multipath/main.c b/multipath/main.c
|
diff --git a/multipath/main.c b/multipath/main.c
|
||||||
index 2e69300..4dde5af 100644
|
index ff570ac..ae6b06e 100644
|
||||||
--- a/multipath/main.c
|
--- a/multipath/main.c
|
||||||
+++ b/multipath/main.c
|
+++ b/multipath/main.c
|
||||||
@@ -412,7 +412,7 @@ configure (struct config *conf, enum mpath_cmds cmd,
|
@@ -416,7 +416,7 @@ configure (struct config *conf, enum mpath_cmds cmd,
|
||||||
}
|
}
|
||||||
if (cmd == CMD_ADD_WWID) {
|
if (cmd == CMD_ADD_WWID) {
|
||||||
r = remember_wwid(refwwid);
|
r = remember_wwid(refwwid);
|
||||||
@ -108,11 +109,28 @@ index 2e69300..4dde5af 100644
|
|||||||
printf("wwid '%s' added\n", refwwid);
|
printf("wwid '%s' added\n", refwwid);
|
||||||
else
|
else
|
||||||
printf("failed adding '%s' to wwids file\n",
|
printf("failed adding '%s' to wwids file\n",
|
||||||
|
@@ -712,16 +712,6 @@ main (int argc, char *argv[])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * FIXME: new device detection with find_multipaths currently
|
||||||
|
- * doesn't work reliably.
|
||||||
|
- */
|
||||||
|
- if (cmd == CMD_VALID_PATH &&
|
||||||
|
- conf->find_multipaths && conf->ignore_wwids) {
|
||||||
|
- condlog(2, "ignoring -i flag because find_multipath is set in multipath.conf");
|
||||||
|
- conf->ignore_wwids = 0;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
if (getuid() != 0) {
|
||||||
|
fprintf(stderr, "need to be root\n");
|
||||||
|
exit(1);
|
||||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
index c475fcd..50749a8 100644
|
index 596654c..c860e88 100644
|
||||||
--- a/multipathd/main.c
|
--- a/multipathd/main.c
|
||||||
+++ b/multipathd/main.c
|
+++ b/multipathd/main.c
|
||||||
@@ -2138,7 +2138,8 @@ configure (struct vectors * vecs, int start_waiters)
|
@@ -2172,7 +2172,8 @@ configure (struct vectors * vecs)
|
||||||
|
|
||||||
sync_maps_state(mpvec);
|
sync_maps_state(mpvec);
|
||||||
vector_foreach_slot(mpvec, mpp, i){
|
vector_foreach_slot(mpvec, mpp, i){
|
||||||
@ -122,7 +140,7 @@ index c475fcd..50749a8 100644
|
|||||||
update_map_pr(mpp);
|
update_map_pr(mpp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2220,10 +2221,6 @@ reconfigure (struct vectors * vecs)
|
@@ -2251,10 +2252,6 @@ reconfigure (struct vectors * vecs)
|
||||||
conf->verbosity = verbosity;
|
conf->verbosity = verbosity;
|
||||||
if (bindings_read_only)
|
if (bindings_read_only)
|
||||||
conf->bindings_read_only = bindings_read_only;
|
conf->bindings_read_only = bindings_read_only;
|
@ -16,7 +16,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
|||||||
3 files changed, 35 insertions(+), 6 deletions(-)
|
3 files changed, 35 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||||
index 54652d4..8d97602 100644
|
index e52f1f7..31897cd 100644
|
||||||
--- a/libmultipath/dict.c
|
--- a/libmultipath/dict.c
|
||||||
+++ b/libmultipath/dict.c
|
+++ b/libmultipath/dict.c
|
||||||
@@ -52,6 +52,21 @@ set_str(vector strvec, void *ptr)
|
@@ -52,6 +52,21 @@ set_str(vector strvec, void *ptr)
|
||||||
@ -41,7 +41,7 @@ index 54652d4..8d97602 100644
|
|||||||
set_yes_no(vector strvec, void *ptr)
|
set_yes_no(vector strvec, void *ptr)
|
||||||
{
|
{
|
||||||
char * buff;
|
char * buff;
|
||||||
@@ -1190,7 +1205,7 @@ ble_ ## option ## _handler (struct config *conf, vector strvec) \
|
@@ -1200,7 +1215,7 @@ ble_ ## option ## _handler (struct config *conf, vector strvec) \
|
||||||
if (!conf->option) \
|
if (!conf->option) \
|
||||||
return 1; \
|
return 1; \
|
||||||
\
|
\
|
||||||
@ -50,7 +50,7 @@ index 54652d4..8d97602 100644
|
|||||||
if (!buff) \
|
if (!buff) \
|
||||||
return 1; \
|
return 1; \
|
||||||
\
|
\
|
||||||
@@ -1206,7 +1221,7 @@ ble_ ## option ## _ ## name ## _handler (struct config *conf, vector strvec) \
|
@@ -1216,7 +1231,7 @@ ble_ ## option ## _ ## name ## _handler (struct config *conf, vector strvec) \
|
||||||
if (!conf->option) \
|
if (!conf->option) \
|
||||||
return 1; \
|
return 1; \
|
||||||
\
|
\
|
||||||
@ -59,7 +59,7 @@ index 54652d4..8d97602 100644
|
|||||||
if (!buff) \
|
if (!buff) \
|
||||||
return 1; \
|
return 1; \
|
||||||
\
|
\
|
||||||
@@ -1301,16 +1316,16 @@ device_handler(struct config *conf, vector strvec)
|
@@ -1311,16 +1326,16 @@ device_handler(struct config *conf, vector strvec)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1,30 +1,38 @@
|
|||||||
Summary: Tools to manage multipath devices using device-mapper
|
Summary: Tools to manage multipath devices using device-mapper
|
||||||
Name: device-mapper-multipath
|
Name: device-mapper-multipath
|
||||||
Version: 0.7.3
|
Version: 0.7.4
|
||||||
Release: 3%{?dist}
|
Release: 1.git07e7bd5%{?dist}
|
||||||
License: GPL+
|
License: GPL+
|
||||||
Group: System Environment/Base
|
Group: System Environment/Base
|
||||||
URL: http://christophe.varoqui.free.fr/
|
URL: http://christophe.varoqui.free.fr/
|
||||||
|
|
||||||
# The source for this package was pulled from upstream's git repo. Use the
|
# The source for this package was pulled from upstream's git repo. Use the
|
||||||
# following command to generate the tarball
|
# following command to generate the tarball
|
||||||
# curl "https://git.opensvc.com/?p=multipath-tools/.git;a=snapshot;h=refs/tags/0.7.3;sf=tgz" -o multipath-tools-0.7.3.tgz
|
# curl "https://git.opensvc.com/?p=multipath-tools/.git;a=snapshot;h=07e7bd5;sf=tgz" -o multipath-tools-07e7bd5.tgz
|
||||||
Source0: multipath-tools-0.7.3.tgz
|
Source0: multipath-tools-07e7bd5.tgz
|
||||||
Source1: multipath.conf
|
Source1: multipath.conf
|
||||||
Patch0001: 0001-mpathpersist-Fix-invalid-condition-check.patch
|
Patch0001: 0001-libmultipath-fix-tur-checker-locking.patch
|
||||||
Patch0002: 0002-multipath-add-man-page-info-for-my-prkey-changes.patch
|
Patch0002: 0002-multipath-fix-DEF_TIMEOUT-use.patch
|
||||||
Patch0003: 0003-multipath-there-is-no-none-path-state.patch
|
Patch0003: 0003-multipathd-remove-coalesce_paths-from-ev_add_map.patch
|
||||||
Patch0004: 0004-mutipath-updated-Huawei-storage-config.patch
|
Patch0004: 0004-multipathd-remove-unused-configure-parameter.patch
|
||||||
Patch0005: 0005-multipath-fix-doc-typo.patch
|
Patch0005: 0005-Fix-set_no_path_retry-regression.patch
|
||||||
Patch0006: 0006-multipath-add-ghost_delay-parameter.patch
|
Patch0006: 0006-multipathd-change-spurious-uevent-msg-priority.patch
|
||||||
Patch0007: 0007-RH-fixup-udev-rules-for-redhat.patch
|
Patch0007: 0007-multipath-print-sysfs-state-in-fast-list-mode.patch
|
||||||
Patch0008: 0008-RH-Remove-the-property-blacklist-exception-builtin.patch
|
Patch0008: 0008-libmultipath-move-remove_map-waiter-code-to-multipat.patch
|
||||||
Patch0009: 0009-RH-don-t-start-without-a-config-file.patch
|
Patch0009: 0009-move-waiter-code-from-libmultipath-to-multipathd.patch
|
||||||
Patch0010: 0010-RH-use-rpm-optflags-if-present.patch
|
Patch0010: 0010-call-start_waiter_thread-before-setup_multipath.patch
|
||||||
Patch0011: 0011-RH-add-mpathconf.patch
|
Patch0011: 0011-libmultipath-add-helper-functions.patch
|
||||||
Patch0012: 0012-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch
|
Patch0012: 0012-multipathd-RFC-add-new-polling-dmevents-waiter-threa.patch
|
||||||
Patch0013: 0013-RH-trigger-change-uevent-on-new-device-creation.patch
|
Patch0013: 0013-libmultipath-condlog-log-to-stderr.patch
|
||||||
Patch0014: 0014-RH-warn-on-invalid-regex-instead-of-failing.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
|
||||||
|
|
||||||
# runtime
|
# runtime
|
||||||
Requires: %{name}-libs = %{version}-%{release}
|
Requires: %{name}-libs = %{version}-%{release}
|
||||||
@ -102,7 +110,7 @@ This package contains the files needed to develop applications that use
|
|||||||
device-mapper-multipath's libdmmp C API library
|
device-mapper-multipath's libdmmp C API library
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q -n multipath-tools-0.7.3
|
%setup -q -n multipath-tools-07e7bd5
|
||||||
%patch0001 -p1
|
%patch0001 -p1
|
||||||
%patch0002 -p1
|
%patch0002 -p1
|
||||||
%patch0003 -p1
|
%patch0003 -p1
|
||||||
@ -117,6 +125,14 @@ device-mapper-multipath's libdmmp C API library
|
|||||||
%patch0012 -p1
|
%patch0012 -p1
|
||||||
%patch0013 -p1
|
%patch0013 -p1
|
||||||
%patch0014 -p1
|
%patch0014 -p1
|
||||||
|
%patch0015 -p1
|
||||||
|
%patch0016 -p1
|
||||||
|
%patch0017 -p1
|
||||||
|
%patch0018 -p1
|
||||||
|
%patch0019 -p1
|
||||||
|
%patch0020 -p1
|
||||||
|
%patch0021 -p1
|
||||||
|
%patch0022 -p1
|
||||||
cp %{SOURCE1} .
|
cp %{SOURCE1} .
|
||||||
|
|
||||||
%build
|
%build
|
||||||
@ -178,6 +194,7 @@ fi
|
|||||||
%{!?_licensedir:%global license %%doc}
|
%{!?_licensedir:%global license %%doc}
|
||||||
%license COPYING
|
%license COPYING
|
||||||
%doc README
|
%doc README
|
||||||
|
%doc README.alua
|
||||||
%doc multipath.conf
|
%doc multipath.conf
|
||||||
%dir /etc/multipath
|
%dir /etc/multipath
|
||||||
|
|
||||||
@ -239,6 +256,40 @@ fi
|
|||||||
%{_pkgconfdir}/libdmmp.pc
|
%{_pkgconfdir}/libdmmp.pc
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Feb 15 2018 Benjamin Marzinski <bmarzins@redhat.com> 0.7.4-1.git07e7bd5
|
||||||
|
- Update Source to the latest upstream commit
|
||||||
|
* Previous patches 0001-0006 are included in this commit
|
||||||
|
* Previous patches 0007-0014 are now patches 0015-0022
|
||||||
|
- Add 0001-libmultipath-fix-tur-checker-locking.patch
|
||||||
|
* Fixed spinlock bug. posted upstream
|
||||||
|
- Add 0002-multipath-fix-DEF_TIMEOUT-use.patch
|
||||||
|
* Add missing sec to ms conversion. posted upstream
|
||||||
|
- Add 0003-multipathd-remove-coalesce_paths-from-ev_add_map.patch
|
||||||
|
* Remove unused code. posted upstream
|
||||||
|
- Add 0004-multipathd-remove-unused-configure-parameter.patch
|
||||||
|
* Remove unused code. posted upstream
|
||||||
|
- Add 0005-Fix-set_no_path_retry-regression.patch
|
||||||
|
* Fix issue with queueing and path addition. posted upstream
|
||||||
|
- Add 0006-multipathd-change-spurious-uevent-msg-priority.patch
|
||||||
|
* Change message priority to Notice. posted upstream
|
||||||
|
- Add 0007-multipath-print-sysfs-state-in-fast-list-mode.patch
|
||||||
|
* Show sysfs state correctly in fast list mode (-l). posted upstream
|
||||||
|
- Add 0008-libmultipath-move-remove_map-waiter-code-to-multipat.patch
|
||||||
|
* Move code around. posted upstream
|
||||||
|
- Add 0009-move-waiter-code-from-libmultipath-to-multipathd.patch
|
||||||
|
* Move code around. posted upstream
|
||||||
|
- Add 0010-call-start_waiter_thread-before-setup_multipath.patch
|
||||||
|
* Fix race on multipath device creations. posted upstream
|
||||||
|
- Add 0011-libmultipath-add-helper-functions.patch
|
||||||
|
* posted upstream
|
||||||
|
- Add 0012-multipathd-RFC-add-new-polling-dmevents-waiter-threa.patch
|
||||||
|
* Add alternate method of getting dmevents, that doesn't
|
||||||
|
require a thread per device. posted upstream
|
||||||
|
- Add 0013-libmultipath-condlog-log-to-stderr.patch
|
||||||
|
* change condlog to log to stderr instead of stdout. posted upstream
|
||||||
|
- Add 0014-multipathd-fix-compiler-warning-for-uev_pathfail_che.patch
|
||||||
|
* fix indentation issue. posted upstream
|
||||||
|
|
||||||
* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.7.3-3
|
* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.7.3-3
|
||||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
|
||||||
|
|
||||||
|
2
sources
2
sources
@ -1,2 +1,2 @@
|
|||||||
|
SHA512 (multipath-tools-07e7bd5.tgz) = e84d451c8927119bac6612585d15497325da08d762ea6cde20d400a651fac599cb6edf4f9144204d91f92e04fec4ea3b955b9a9216ae82b513437b8ce516136a
|
||||||
SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942
|
SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942
|
||||||
SHA512 (multipath-tools-0.7.3.tgz) = d1e1f4e57ead7a79accf55173263138a78b86c3b846bac8ad2526f36f01fe32a8b7e6bb5bb785b083f3bdbf39c34c06032b7a0d6db6c4cc99e5bc98f67a7e7f3
|
|
||||||
|
Loading…
Reference in New Issue
Block a user