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:
Benjamin Marzinski 2018-02-15 13:17:53 -06:00
parent 7e8f34e181
commit 5bea53fe7e
31 changed files with 2687 additions and 652 deletions

1
.gitignore vendored
View File

@ -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

View 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

View File

@ -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

View File

@ -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

View 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

View File

@ -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

View 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

View 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

View File

@ -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

View 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

View File

@ -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

View File

@ -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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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 @@

View File

@ -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

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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;
} }

View File

@ -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

View File

@ -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