import device-mapper-multipath-0.8.0-5.el8

This commit is contained in:
CentOS Sources 2019-08-01 23:04:25 -04:00 committed by Stepan Oksanichenko
commit 70e223f212
40 changed files with 5128 additions and 0 deletions

View File

@ -0,0 +1 @@
30bf38b713001c2b80b86d67473fbe20dc0f28cc SOURCES/multipath-tools-0.8.0.tgz

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
SOURCES/multipath-tools-0.8.0.tgz

View File

@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 24 Jan 2019 14:09:23 -0600
Subject: [PATCH] BZ 1668693: disable user_friendly_names for NetApp
NetApp has tools that rely on devices using WWID names. To avoid
breaking these, NetApp devices should continue to use WWID names, even
if the default config is set to enable user_friendly_names. If users
want to use user_friendly_names on NetApp devices, the must specifically
override the device config.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/hwtable.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index d3a8d9b..8776411 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -719,6 +719,7 @@ static struct hwentry default_hw[] = {
.flush_on_last_del = FLUSH_ENABLED,
.dev_loss = MAX_DEV_LOSS_TMO,
.prio_name = PRIO_ONTAP,
+ .user_friendly_names = USER_FRIENDLY_NAMES_OFF,
},
{
/*
--
2.17.2

View File

@ -0,0 +1,49 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 25 Jan 2019 16:45:26 -0600
Subject: [PATCH] libmultipath: handle existing paths in marginal_path enqueue
If the path that enqueue_io_err_stat_by_path() is trying to add
is already on the list, just return success. There's no reason
to fail in this case.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/io_err_stat.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
index 02b1453..1cb3ffe 100644
--- a/libmultipath/io_err_stat.c
+++ b/libmultipath/io_err_stat.c
@@ -254,7 +254,6 @@ static void free_io_err_pathvec(struct io_err_stat_pathvec *p)
* return value
* 0: enqueue OK
* 1: fails because of internal error
- * 2: fails because of existing already
*/
static int enqueue_io_err_stat_by_path(struct path *path)
{
@@ -264,7 +263,7 @@ static int enqueue_io_err_stat_by_path(struct path *path)
p = find_err_path_by_dev(paths->pathvec, path->dev);
if (p) {
pthread_mutex_unlock(&paths->mutex);
- return 2;
+ return 0;
}
pthread_mutex_unlock(&paths->mutex);
@@ -418,9 +417,8 @@ int hit_io_err_recheck_time(struct path *pp)
io_err_stat_log(3, "%s: enqueue fails, to recover",
pp->dev);
goto recover;
- } else if (!r) {
+ } else
pp->io_err_pathfail_cnt = PATH_IO_ERR_IN_CHECKING;
- }
}
return 1;
--
2.17.2

View File

@ -0,0 +1,70 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 25 Jan 2019 17:09:42 -0600
Subject: [PATCH] multipathd: cleanup marginal paths checking timers
When a path gets recovered in hit_io_err_recheck_time(), it will
continue running in check_path(), so there is no reason to schedule
another path check as soon as possible (since one is currently
happening).
Also, there isn't much point in restarting the io err stat checking when
the path is down, so hit_io_err_recheck_time() should only be run when
the path is up. Downed marginal paths can be treated just like any other
downed path.
Finally, there is no reason to set reset pp->io_err_dis_reinstate_time
when we decide to enqueue a path. Either th enqueue will fail and the
path will get recovered, or it will succeed, and we won't check the
reinstate time again until poll_io_err_stat() marks the path as needing
a requeue.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/io_err_stat.c | 8 --------
multipathd/main.c | 3 ++-
2 files changed, 2 insertions(+), 9 deletions(-)
diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
index 1cb3ffe..416e13a 100644
--- a/libmultipath/io_err_stat.c
+++ b/libmultipath/io_err_stat.c
@@ -400,13 +400,6 @@ int hit_io_err_recheck_time(struct path *pp)
io_err_stat_log(4, "%s: reschedule checking after %d seconds",
pp->dev,
pp->mpp->marginal_path_err_recheck_gap_time);
- /*
- * to reschedule io error checking again
- * if the path is good enough, we claim it is good
- * and can be reinsated as soon as possible in the
- * check_path routine.
- */
- pp->io_err_dis_reinstate_time = curr_time.tv_sec;
r = enqueue_io_err_stat_by_path(pp);
/*
* Enqueue fails because of internal error.
@@ -426,7 +419,6 @@ int hit_io_err_recheck_time(struct path *pp)
recover:
pp->io_err_pathfail_cnt = 0;
pp->io_err_disable_reinstate = 0;
- pp->tick = 1;
return 0;
}
diff --git a/multipathd/main.c b/multipathd/main.c
index fb520b6..fe6d8ef 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -2079,7 +2079,8 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
return 1;
}
- if (pp->io_err_disable_reinstate && hit_io_err_recheck_time(pp)) {
+ if ((newstate == PATH_UP || newstate == PATH_GHOST) &&
+ pp->io_err_disable_reinstate && hit_io_err_recheck_time(pp)) {
pp->state = PATH_SHAKY;
/*
* to reschedule as soon as possible,so that this path can
--
2.17.2

View File

@ -0,0 +1,176 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 28 Jan 2019 00:20:53 -0600
Subject: [PATCH] libmultipath: fix marginal paths queueing errors
The current marginal paths code tries to enqueue paths for io error
checking when multipathd receives a uevent on path failure. This can run
into a couple of problems. First, this uevent could happen before or
after multipathd actually fails the path, so simply checking nr_active
doesn't tell us if this is the last active path. Also, The code to fail
the path in enqueue_io_err_stat_by_path() doesn't ever update the path
state. This can cause the path to get failed twice, temporarily leading
to incorrect nr_active counts. Further, The point when multipathd should
care if this is the last active path is when the path has come up again,
not when it goes down. Lastly, if the path is down, it is often
impossible to open the path device, causing setup_directio_ctx() to
fail, which causes multipathd to skip io error checking and mark the
path as not marginal.
Instead, multipathd should just make sure that if the path is marginal,
it gets failed in the uevent, so as not to race with the checkerloop
thread. Then, when the path comes back up, check_path() can enqueue it,
just like it does for paths that need to get rechecked. To make it
obvious that the state PATH_IO_ERR_IN_POLLING_RECHECK and the function
hit_io_err_recheck_time() now apply to paths waiting to be enqueued for
the first time as well, I've also changed their names to
PATH_IO_ERR_WAITING_TO_CHECK and need_io_err_check(), respectively.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/io_err_stat.c | 55 +++++++++++++++++---------------------
libmultipath/io_err_stat.h | 2 +-
multipathd/main.c | 2 +-
3 files changed, 27 insertions(+), 32 deletions(-)
diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
index 416e13a..72aacf3 100644
--- a/libmultipath/io_err_stat.c
+++ b/libmultipath/io_err_stat.c
@@ -41,7 +41,7 @@
#define CONCUR_NR_EVENT 32
#define PATH_IO_ERR_IN_CHECKING -1
-#define PATH_IO_ERR_IN_POLLING_RECHECK -2
+#define PATH_IO_ERR_WAITING_TO_CHECK -2
#define io_err_stat_log(prio, fmt, args...) \
condlog(prio, "io error statistic: " fmt, ##args)
@@ -283,24 +283,6 @@ static int enqueue_io_err_stat_by_path(struct path *path)
vector_set_slot(paths->pathvec, p);
pthread_mutex_unlock(&paths->mutex);
- if (!path->io_err_disable_reinstate) {
- /*
- *fail the path in the kernel for the time of the to make
- *the test more reliable
- */
- io_err_stat_log(3, "%s: fail dm path %s before checking",
- path->mpp->alias, path->dev);
- path->io_err_disable_reinstate = 1;
- dm_fail_path(path->mpp->alias, path->dev_t);
- update_queue_mode_del_path(path->mpp);
-
- /*
- * schedule path check as soon as possible to
- * update path state to delayed state
- */
- path->tick = 1;
-
- }
io_err_stat_log(2, "%s: enqueue path %s to check",
path->mpp->alias, path->dev);
return 0;
@@ -317,7 +299,6 @@ free_ioerr_path:
int io_err_stat_handle_pathfail(struct path *path)
{
struct timespec curr_time;
- int res;
if (uatomic_read(&io_err_thread_running) == 0)
return 1;
@@ -332,8 +313,6 @@ int io_err_stat_handle_pathfail(struct path *path)
if (!path->mpp)
return 1;
- if (path->mpp->nr_active <= 1)
- return 1;
if (path->mpp->marginal_path_double_failed_time <= 0 ||
path->mpp->marginal_path_err_sample_time <= 0 ||
path->mpp->marginal_path_err_recheck_gap_time <= 0 ||
@@ -371,17 +350,33 @@ int io_err_stat_handle_pathfail(struct path *path)
}
path->io_err_pathfail_cnt++;
if (path->io_err_pathfail_cnt >= FLAKY_PATHFAIL_THRESHOLD) {
- res = enqueue_io_err_stat_by_path(path);
- if (!res)
- path->io_err_pathfail_cnt = PATH_IO_ERR_IN_CHECKING;
- else
- path->io_err_pathfail_cnt = 0;
+ path->io_err_disable_reinstate = 1;
+ path->io_err_pathfail_cnt = PATH_IO_ERR_WAITING_TO_CHECK;
+ /* enqueue path as soon as it comes up */
+ path->io_err_dis_reinstate_time = 0;
+ if (path->state != PATH_DOWN) {
+ struct config *conf;
+ int oldstate = path->state;
+ int checkint;
+
+ conf = get_multipath_config();
+ checkint = conf->checkint;
+ put_multipath_config(conf);
+ io_err_stat_log(2, "%s: mark as failed", path->dev);
+ path->mpp->stat_path_failures++;
+ path->state = PATH_DOWN;
+ path->dmstate = PSTATE_FAILED;
+ if (oldstate == PATH_UP || oldstate == PATH_GHOST)
+ update_queue_mode_del_path(path->mpp);
+ if (path->tick > checkint)
+ path->tick = checkint;
+ }
}
return 0;
}
-int hit_io_err_recheck_time(struct path *pp)
+int need_io_err_check(struct path *pp)
{
struct timespec curr_time;
int r;
@@ -392,7 +387,7 @@ int hit_io_err_recheck_time(struct path *pp)
io_err_stat_log(2, "%s: recover path early", pp->dev);
goto recover;
}
- if (pp->io_err_pathfail_cnt != PATH_IO_ERR_IN_POLLING_RECHECK)
+ if (pp->io_err_pathfail_cnt != PATH_IO_ERR_WAITING_TO_CHECK)
return 1;
if (clock_gettime(CLOCK_MONOTONIC, &curr_time) != 0 ||
(curr_time.tv_sec - pp->io_err_dis_reinstate_time) >
@@ -489,7 +484,7 @@ static int poll_io_err_stat(struct vectors *vecs, struct io_err_stat_path *pp)
} else if (path->mpp && path->mpp->nr_active > 1) {
io_err_stat_log(3, "%s: keep failing the dm path %s",
path->mpp->alias, path->dev);
- path->io_err_pathfail_cnt = PATH_IO_ERR_IN_POLLING_RECHECK;
+ path->io_err_pathfail_cnt = PATH_IO_ERR_WAITING_TO_CHECK;
path->io_err_disable_reinstate = 1;
path->io_err_dis_reinstate_time = currtime.tv_sec;
io_err_stat_log(3, "%s: disable reinstating of %s",
diff --git a/libmultipath/io_err_stat.h b/libmultipath/io_err_stat.h
index bbf31b4..53d6d7d 100644
--- a/libmultipath/io_err_stat.h
+++ b/libmultipath/io_err_stat.h
@@ -10,6 +10,6 @@ extern pthread_attr_t io_err_stat_attr;
int start_io_err_stat_thread(void *data);
void stop_io_err_stat_thread(void);
int io_err_stat_handle_pathfail(struct path *path);
-int hit_io_err_recheck_time(struct path *pp);
+int need_io_err_check(struct path *pp);
#endif /* _IO_ERR_STAT_H */
diff --git a/multipathd/main.c b/multipathd/main.c
index fe6d8ef..43830e8 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -2080,7 +2080,7 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
}
if ((newstate == PATH_UP || newstate == PATH_GHOST) &&
- pp->io_err_disable_reinstate && hit_io_err_recheck_time(pp)) {
+ pp->io_err_disable_reinstate && need_io_err_check(pp)) {
pp->state = PATH_SHAKY;
/*
* to reschedule as soon as possible,so that this path can
--
2.17.2

View File

@ -0,0 +1,30 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 29 Jan 2019 18:26:04 -0600
Subject: [PATCH] libmultipath: fix marginal_paths nr_active check
Marginal paths are SHAKY, so they don't count towards the number of
active paths. poll_io_err_stat() shouldn't automatically reinstate a
marginal path if there already is an active path.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/io_err_stat.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
index 72aacf3..554b777 100644
--- a/libmultipath/io_err_stat.c
+++ b/libmultipath/io_err_stat.c
@@ -481,7 +481,7 @@ static int poll_io_err_stat(struct vectors *vecs, struct io_err_stat_path *pp)
*/
path->tick = 1;
- } else if (path->mpp && path->mpp->nr_active > 1) {
+ } else if (path->mpp && path->mpp->nr_active > 0) {
io_err_stat_log(3, "%s: keep failing the dm path %s",
path->mpp->alias, path->dev);
path->io_err_pathfail_cnt = PATH_IO_ERR_WAITING_TO_CHECK;
--
2.17.2

View File

@ -0,0 +1,92 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 15 Feb 2019 17:19:46 -0600
Subject: [PATCH] multipathd: Fix miscounting active paths
When multipathd gets a change uevent, it calls pathinfo with DI_NOIO.
This sets the path state to the return value of path_offline(). If a
path is in the PATH_DOWN state but path_offline() returns PATH_UP, when
that path gets a change event, its state will get moved to PATH_UP
without either reinstating the path, or reloading the map. The next
call to check_path() will move the path back to PATH_DOWN. Since
check_path() simply increments and decrements nr_active instead of
calculating it based on the actual number of active paths, nr_active
will get decremented a second time for this failed path, potentially
putting the multipath device into recovery mode.
This commit does two things to avoid this situation. It makes the
DI_NOIO flag only set pp->state in pathinfo() if DI_CHECKER is also set.
This isn't set in uev_update_path() to avoid changing the path state in
this case. Also, to guard against pp->state getting changed in some
other code path without properly updating the map state, check_path()
now calls set_no_path_retry, which recalculates nr_active based on the
actual number of active paths, and makes sure that the queue_if_no_path
value in the features line is correct.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/discovery.c | 11 ++++++-----
multipath/main.c | 2 +-
multipathd/main.c | 4 +++-
3 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index 10bd8cd..729bcb9 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1914,11 +1914,12 @@ int pathinfo(struct path *pp, struct config *conf, int mask)
if (path_state == PATH_REMOVED)
goto blank;
else if (mask & DI_NOIO) {
- /*
- * Avoid any IO on the device itself.
- * Behave like DI_CHECKER in the "path unavailable" case.
- */
- pp->chkrstate = pp->state = path_state;
+ if (mask & DI_CHECKER)
+ /*
+ * Avoid any IO on the device itself.
+ * simply use the path_offline() return as its state
+ */
+ pp->chkrstate = pp->state = path_state;
return PATHINFO_OK;
}
diff --git a/multipath/main.c b/multipath/main.c
index 5abb118..69141db 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -356,7 +356,7 @@ static int check_usable_paths(struct config *conf,
pp->udev = get_udev_device(pp->dev_t, DEV_DEVT);
if (pp->udev == NULL)
continue;
- if (pathinfo(pp, conf, DI_SYSFS|DI_NOIO) != PATHINFO_OK)
+ if (pathinfo(pp, conf, DI_SYSFS|DI_NOIO|DI_CHECKER) != PATHINFO_OK)
continue;
if (pp->state == PATH_UP &&
diff --git a/multipathd/main.c b/multipathd/main.c
index 43830e8..678ecf8 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -392,7 +392,8 @@ static void set_no_path_retry(struct multipath *mpp)
default:
if (mpp->nr_active > 0) {
mpp->retry_tick = 0;
- dm_queue_if_no_path(mpp->alias, 1);
+ if (!is_queueing)
+ dm_queue_if_no_path(mpp->alias, 1);
} else if (is_queueing && mpp->retry_tick == 0)
enter_recovery_mode(mpp);
break;
@@ -2072,6 +2073,7 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
/* if update_multipath_strings orphaned the path, quit early */
if (!pp->mpp)
return 0;
+ set_no_path_retry(pp->mpp);
if ((newstate == PATH_UP || newstate == PATH_GHOST) &&
check_path_reinstate_state(pp)) {
--
2.17.2

View File

@ -0,0 +1,71 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 20 Feb 2019 17:05:08 -0600
Subject: [PATCH] multipathd: ignore failed wwid recheck
If disable_changed_wwids is set, when multipathd gets a change event on
a path, it verifies that the wwid hasn't changed in uev_update_path().
If get_uid() failed, uev_update_path treated this as a wwid change to 0.
This could cause paths to suddenly be dropped due to an issue with
getting the wwid. Even if get_uid() failed because the path was down,
it no change uevent happend when it later became active, multipathd
would continue to ignore the path. Also, scsi_uid_fallback() clears the
failure return if it doesn't attempt to fallback, causing get_uid()
to return success, when it actually failed.
Multipathd should neither set nor clear wwid_changed if get_uid()
returned failure. Also, scsi_uid_fallback() should retain the old return
value if it doesn't attempt to fallback.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/discovery.c | 6 +++---
multipathd/main.c | 6 ++++--
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index 729bcb9..b08cb2d 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1755,9 +1755,9 @@ get_vpd_uid(struct path * pp)
}
static ssize_t scsi_uid_fallback(struct path *pp, int path_state,
- const char **origin)
+ const char **origin, ssize_t old_len)
{
- ssize_t len = 0;
+ ssize_t len = old_len;
int retrigger;
struct config *conf;
@@ -1828,7 +1828,7 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev)
origin = "sysfs";
}
if (len <= 0 && pp->bus == SYSFS_BUS_SCSI)
- len = scsi_uid_fallback(pp, path_state, &origin);
+ len = scsi_uid_fallback(pp, path_state, &origin, len);
}
if ( len < 0 ) {
condlog(1, "%s: failed to get %s uid: %s",
diff --git a/multipathd/main.c b/multipathd/main.c
index 678ecf8..fd83a6a 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1234,9 +1234,11 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
goto out;
strcpy(wwid, pp->wwid);
- get_uid(pp, pp->state, uev->udev);
+ rc = get_uid(pp, pp->state, uev->udev);
- if (strncmp(wwid, pp->wwid, WWID_SIZE) != 0) {
+ if (rc != 0)
+ strcpy(pp->wwid, wwid);
+ else if (strncmp(wwid, pp->wwid, WWID_SIZE) != 0) {
condlog(0, "%s: path wwid changed from '%s' to '%s'. %s",
uev->kernel, wwid, pp->wwid,
(disable_changed_wwids ? "disallowing" :
--
2.17.2

View File

@ -0,0 +1,47 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 21 Feb 2019 13:05:43 -0600
Subject: [PATCH] libmutipath: continue to use old state on PATH_PENDING
When pathinfo() sets pp->state to PATH_PENDING, it can cause problems
with path checking. It should act more like check_path(). When
check_path() sees a new state of PATH_PENDING, it doesn't update the
path state at all, so a path's old state is normally never PATH_PENDING.
As and example of the problems of setting a path to PATH_PENDING, If
check_path() sets a path's state to PATH_UP, then a call to pathinfo()
sets the state to PATH_PENDING, and then another call the check_path()
sets the state to PATH_DOWN, multipathd won't fail the path in the
kernel. Also, if a path's state is PATH_PENDING, and nr_active is
recalculated, that path will count as down, even if the state was
previously PATH_UP. If a path already has a state of PATH_WILD or
PATH_UNCHECKED, changing it to PATH_PENDING won't hurt anything, and it
will help anyone who sees it know what's actually happening. But
otherwise, pathinfo() should leave the previous state alone.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/discovery.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index b08cb2d..28c00e5 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1946,8 +1946,11 @@ int pathinfo(struct path *pp, struct config *conf, int mask)
if (mask & DI_CHECKER) {
if (path_state == PATH_UP) {
- pp->chkrstate = pp->state = get_state(pp, conf, 0,
- path_state);
+ int newstate = get_state(pp, conf, 0, path_state);
+ if (newstate != PATH_PENDING ||
+ pp->state == PATH_UNCHECKED ||
+ pp->state == PATH_WILD)
+ pp->chkrstate = pp->state = newstate;
if (pp->state == PATH_TIMEOUT)
pp->state = PATH_DOWN;
if (pp->state == PATH_UP && !pp->size) {
--
2.17.2

View File

@ -0,0 +1,76 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 21 Feb 2019 17:00:17 -0600
Subject: [PATCH] multipathd: use update_path_groups instead of reload_map
reload_map() doesn't do the work to sync the state after reloading the
map. Instead of calling it directly, cli_reload() and uev_update_path()
should call update_path_groups(), which calls reload_map() with all the
necessary syncing.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/cli_handlers.c | 2 +-
multipathd/main.c | 13 ++++++++-----
multipathd/main.h | 2 ++
3 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index f95813e..60e17d6 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -877,7 +877,7 @@ cli_reload(void *v, char **reply, int *len, void *data)
return 1;
}
- return reload_map(vecs, mpp, 0, 1);
+ return update_path_groups(mpp, vecs, 0);
}
int resize_map(struct multipath *mpp, unsigned long long size,
diff --git a/multipathd/main.c b/multipathd/main.c
index fd83a6a..7a317d9 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1273,10 +1273,13 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
else {
if (ro == 1)
pp->mpp->force_readonly = 1;
- retval = reload_map(vecs, mpp, 0, 1);
- pp->mpp->force_readonly = 0;
- condlog(2, "%s: map %s reloaded (retval %d)",
- uev->kernel, mpp->alias, retval);
+ retval = update_path_groups(mpp, vecs, 0);
+ if (retval == 2)
+ condlog(2, "%s: map removed during reload", pp->dev);
+ else {
+ pp->mpp->force_readonly = 0;
+ condlog(2, "%s: map %s reloaded (retval %d)", uev->kernel, mpp->alias, retval);
+ }
}
}
}
@@ -1832,7 +1835,7 @@ int update_path_groups(struct multipath *mpp, struct vectors *vecs, int refresh)
dm_lib_release();
if (setup_multipath(vecs, mpp) != 0)
- return 1;
+ return 2;
sync_map_state(mpp);
return 0;
diff --git a/multipathd/main.h b/multipathd/main.h
index 8fd426b..e5c1398 100644
--- a/multipathd/main.h
+++ b/multipathd/main.h
@@ -43,5 +43,7 @@ int __setup_multipath (struct vectors * vecs, struct multipath * mpp,
int reset);
#define setup_multipath(vecs, mpp) __setup_multipath(vecs, mpp, 1)
int update_multipath (struct vectors *vecs, char *mapname, int reset);
+int update_path_groups(struct multipath *mpp, struct vectors *vecs,
+ int refresh);
#endif /* MAIN_H */
--
2.17.2

View File

@ -0,0 +1,56 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 26 Feb 2019 12:22:59 -0600
Subject: [PATCH] multipath.conf: add missing options to man page
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/multipath.conf.5 | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 0fe8461..864d7eb 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1468,6 +1468,8 @@ section:
.TP
.B uid_attribute
.TP
+.B getuid_callout
+.TP
.B path_selector
.TP
.B path_checker
@@ -1494,6 +1496,8 @@ section:
.TP
.B flush_on_last_del
.TP
+.B user_friendly_names
+.TP
.B retain_attached_hw_handler
.TP
.B detect_prio
@@ -1525,6 +1529,8 @@ section:
.B max_sectors_kb
.TP
.B ghost_delay
+.TP
+.B all_tg_pt
.RE
.PD
.LP
@@ -1604,7 +1610,11 @@ the values are taken from the \fIdevices\fR or \fIdefaults\fR sections:
.TP
.B skip_kpartx
.TP
+.B max_sectors_kb
+.TP
.B ghost_delay
+.TP
+.B all_tg_pt
.RE
.PD
.LP
--
2.17.2

View File

@ -0,0 +1,90 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 7 Mar 2019 16:14:35 -0600
Subject: [PATCH] libmultipath: add get_uid fallback code for NVMe devices
If multipath can't get the uid for NVMe devices from udev, it can get it
directly from sysfs.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/discovery.c | 49 ++++++++++++++++++++++++++++------------
1 file changed, 34 insertions(+), 15 deletions(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index 28c00e5..bece67c 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1754,8 +1754,8 @@ get_vpd_uid(struct path * pp)
return get_vpd_sysfs(parent, 0x83, pp->wwid, WWID_SIZE);
}
-static ssize_t scsi_uid_fallback(struct path *pp, int path_state,
- const char **origin, ssize_t old_len)
+static ssize_t uid_fallback(struct path *pp, int path_state,
+ const char **origin, ssize_t old_len)
{
ssize_t len = old_len;
int retrigger;
@@ -1764,17 +1764,36 @@ static ssize_t scsi_uid_fallback(struct path *pp, int path_state,
conf = get_multipath_config();
retrigger = conf->retrigger_tries;
put_multipath_config(conf);
- if (pp->retriggers >= retrigger &&
- !strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) {
- len = get_vpd_uid(pp);
- *origin = "sysfs";
- pp->uid_attribute = NULL;
- if (len < 0 && path_state == PATH_UP) {
- condlog(1, "%s: failed to get sysfs uid: %s",
- pp->dev, strerror(-len));
- len = get_vpd_sgio(pp->fd, 0x83, pp->wwid,
- WWID_SIZE);
- *origin = "sgio";
+ if (pp->retriggers >= retrigger) {
+ if (pp->bus == SYSFS_BUS_SCSI &&
+ !strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) {
+ len = get_vpd_uid(pp);
+ *origin = "sysfs";
+ pp->uid_attribute = NULL;
+ if (len < 0 && path_state == PATH_UP) {
+ condlog(1, "%s: failed to get sysfs uid: %s",
+ pp->dev, strerror(-len));
+ len = get_vpd_sgio(pp->fd, 0x83, pp->wwid,
+ WWID_SIZE);
+ *origin = "sgio";
+ }
+ } else if (pp->bus == SYSFS_BUS_NVME) {
+ char value[256];
+ len = sysfs_attr_get_value(pp->udev, "wwid", value,
+ sizeof(value));
+ if (len <= 0)
+ return -1;
+ len = strlcpy(pp->wwid, value, WWID_SIZE);
+ if (len >= WWID_SIZE) {
+ len = fix_broken_nvme_wwid(pp, value,
+ WWID_SIZE);
+ if (len > 0)
+ return len;
+ condlog(0, "%s: wwid overflow", pp->dev);
+ len = WWID_SIZE;
+ }
+ *origin = "sysfs";
+ pp->uid_attribute = NULL;
}
}
return len;
@@ -1827,8 +1846,8 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev)
len = get_vpd_uid(pp);
origin = "sysfs";
}
- if (len <= 0 && pp->bus == SYSFS_BUS_SCSI)
- len = scsi_uid_fallback(pp, path_state, &origin, len);
+ if (len <= 0)
+ len = uid_fallback(pp, path_state, &origin, len);
}
if ( len < 0 ) {
condlog(1, "%s: failed to get %s uid: %s",
--
2.17.2

View File

@ -0,0 +1,129 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 27 Mar 2019 12:21:57 -0500
Subject: [PATCH] libmulitpath: cleanup uid_fallback code
Instead of always calling uid_fallback() if the configured method to get
the uid failed, get_uid now checks if the path supports fallbacks and if
all the retriggers have occurred. If so, it calls uid_fallback(), which
just attempts to get the uid using the appropriate fallback method. None
of these changes should make the code function any differently.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/discovery.c | 85 ++++++++++++++++++++++------------------
1 file changed, 46 insertions(+), 39 deletions(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index bece67c..3ec60d6 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1755,50 +1755,50 @@ get_vpd_uid(struct path * pp)
}
static ssize_t uid_fallback(struct path *pp, int path_state,
- const char **origin, ssize_t old_len)
+ const char **origin)
{
- ssize_t len = old_len;
- int retrigger;
- struct config *conf;
-
- conf = get_multipath_config();
- retrigger = conf->retrigger_tries;
- put_multipath_config(conf);
- if (pp->retriggers >= retrigger) {
- if (pp->bus == SYSFS_BUS_SCSI &&
- !strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) {
- len = get_vpd_uid(pp);
- *origin = "sysfs";
- pp->uid_attribute = NULL;
- if (len < 0 && path_state == PATH_UP) {
- condlog(1, "%s: failed to get sysfs uid: %s",
- pp->dev, strerror(-len));
- len = get_vpd_sgio(pp->fd, 0x83, pp->wwid,
+ ssize_t len = -1;
+
+ if (pp->bus == SYSFS_BUS_SCSI &&
+ !strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) {
+ len = get_vpd_uid(pp);
+ *origin = "sysfs";
+ pp->uid_attribute = NULL;
+ if (len < 0 && path_state == PATH_UP) {
+ condlog(1, "%s: failed to get sysfs uid: %s",
+ pp->dev, strerror(-len));
+ len = get_vpd_sgio(pp->fd, 0x83, pp->wwid,
+ WWID_SIZE);
+ *origin = "sgio";
+ }
+ } else if (pp->bus == SYSFS_BUS_NVME) {
+ char value[256];
+ len = sysfs_attr_get_value(pp->udev, "wwid", value,
+ sizeof(value));
+ if (len <= 0)
+ return -1;
+ len = strlcpy(pp->wwid, value, WWID_SIZE);
+ if (len >= WWID_SIZE) {
+ len = fix_broken_nvme_wwid(pp, value,
WWID_SIZE);
- *origin = "sgio";
- }
- } else if (pp->bus == SYSFS_BUS_NVME) {
- char value[256];
- len = sysfs_attr_get_value(pp->udev, "wwid", value,
- sizeof(value));
- if (len <= 0)
- return -1;
- len = strlcpy(pp->wwid, value, WWID_SIZE);
- if (len >= WWID_SIZE) {
- len = fix_broken_nvme_wwid(pp, value,
- WWID_SIZE);
- if (len > 0)
- return len;
- condlog(0, "%s: wwid overflow", pp->dev);
- len = WWID_SIZE;
- }
- *origin = "sysfs";
- pp->uid_attribute = NULL;
+ if (len > 0)
+ return len;
+ condlog(0, "%s: wwid overflow", pp->dev);
+ len = WWID_SIZE;
}
+ *origin = "sysfs";
+ pp->uid_attribute = NULL;
}
return len;
}
+static int has_uid_fallback(struct path *pp)
+{
+ return ((pp->bus == SYSFS_BUS_SCSI &&
+ !strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) ||
+ pp->bus == SYSFS_BUS_NVME);
+}
+
int
get_uid (struct path * pp, int path_state, struct udev_device *udev)
{
@@ -1846,8 +1846,15 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev)
len = get_vpd_uid(pp);
origin = "sysfs";
}
- if (len <= 0)
- len = uid_fallback(pp, path_state, &origin, len);
+ if (len <= 0 && has_uid_fallback(pp)) {
+ int retrigger_tries;
+
+ conf = get_multipath_config();
+ retrigger_tries = conf->retrigger_tries;
+ put_multipath_config(conf);
+ if (pp->retriggers >= retrigger_tries)
+ len = uid_fallback(pp, path_state, &origin);
+ }
}
if ( len < 0 ) {
condlog(1, "%s: failed to get %s uid: %s",
--
2.17.2

View File

@ -0,0 +1,83 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 27 Mar 2019 23:27:47 -0500
Subject: [PATCH] multipathd: handle changed wwids by removal and addition
If a path's WWID changes, it's not necessarily failed. But it certainly
has to be removed from an existing map, otherwise data corruption is
imminent. Instead of keeping the path in the map, failing it, and
remembering the "changed WWID" state, this patch simply removes and
re-adds the path.
This is patch is heavily based on the previous patch of the same name
by Martin Wilck.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/main.c | 28 ++++++----------------------
1 file changed, 6 insertions(+), 22 deletions(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index 7a317d9..b3571d9 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1191,7 +1191,6 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
int ro, retval = 0, rc;
struct path * pp;
struct config *conf;
- int disable_changed_wwids;
int needs_reinit = 0;
switch ((rc = change_foreign(uev->udev))) {
@@ -1209,12 +1208,6 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
break;
}
- conf = get_multipath_config();
- disable_changed_wwids = conf->disable_changed_wwids;
- put_multipath_config(conf);
-
- ro = uevent_get_disk_ro(uev);
-
pthread_cleanup_push(cleanup_lock, &vecs->lock);
lock(&vecs->lock);
pthread_testcancel();
@@ -1239,22 +1232,12 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
if (rc != 0)
strcpy(pp->wwid, wwid);
else if (strncmp(wwid, pp->wwid, WWID_SIZE) != 0) {
- condlog(0, "%s: path wwid changed from '%s' to '%s'. %s",
- uev->kernel, wwid, pp->wwid,
- (disable_changed_wwids ? "disallowing" :
- "continuing"));
- strcpy(pp->wwid, wwid);
- if (disable_changed_wwids) {
- if (!pp->wwid_changed) {
- pp->wwid_changed = 1;
- pp->tick = 1;
- if (pp->mpp)
- dm_fail_path(pp->mpp->alias, pp->dev_t);
- }
- goto out;
- }
+ condlog(0, "%s: path wwid changed from '%s' to '%s'",
+ uev->kernel, wwid, pp->wwid);
+ ev_remove_path(pp, vecs, 1);
+ needs_reinit = 1;
+ goto out;
} else {
- pp->wwid_changed = 0;
udev_device_unref(pp->udev);
pp->udev = udev_device_ref(uev->udev);
conf = get_multipath_config();
@@ -1265,6 +1248,7 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
pthread_cleanup_pop(1);
}
+ ro = uevent_get_disk_ro(uev);
if (mpp && ro >= 0) {
condlog(2, "%s: update path write_protect to '%d' (uevent)", uev->kernel, ro);
--
2.17.2

View File

@ -0,0 +1,46 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Mon, 18 Mar 2019 13:12:34 +0100
Subject: [PATCH] multipathd: remove "wwid_changed" path attribute
This is now not needed any more.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/structs.h | 1 -
multipathd/main.c | 6 ------
2 files changed, 7 deletions(-)
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index b794b0d..7879d76 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -280,7 +280,6 @@ struct path {
int fd;
int initialized;
int retriggers;
- int wwid_changed;
unsigned int path_failures;
time_t dis_reinstate_time;
int disable_reinstate;
diff --git a/multipathd/main.c b/multipathd/main.c
index b3571d9..e4f95a0 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -2001,12 +2001,6 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
if (newstate == PATH_REMOVED)
newstate = PATH_DOWN;
- if (pp->wwid_changed) {
- condlog(2, "%s: path wwid has changed. Refusing to use",
- pp->dev);
- newstate = PATH_DOWN;
- }
-
if (newstate == PATH_WILD || newstate == PATH_UNCHECKED) {
condlog(2, "%s: unusable path (%s) - checker failed",
pp->dev, checker_state_name(newstate));
--
2.17.2

View File

@ -0,0 +1,98 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Mon, 18 Mar 2019 13:12:35 +0100
Subject: [PATCH] multipathd: ignore "disable_changed_wwids"
This option has no effect any more.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/config.c | 1 -
libmultipath/config.h | 1 -
libmultipath/dict.c | 18 +++++++++++++++---
multipath/multipath.conf.5 | 8 ++------
4 files changed, 17 insertions(+), 11 deletions(-)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 24d71ae..141f092 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -715,7 +715,6 @@ load_config (char * file)
conf->retrigger_tries = DEFAULT_RETRIGGER_TRIES;
conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY;
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;
conf->all_tg_pt = DEFAULT_ALL_TG_PT;
diff --git a/libmultipath/config.h b/libmultipath/config.h
index b938c26..f5bf5b1 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -182,7 +182,6 @@ struct config {
int delayed_reconfig;
int uev_wait_timeout;
int skip_kpartx;
- int disable_changed_wwids;
int remove_retries;
int max_sectors_kb;
int ghost_delay;
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index eaad4f1..96815f8 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -156,6 +156,12 @@ out:
return len;
}
+static int
+print_ignored (char *buff, int len)
+{
+ return snprintf(buff, len, "ignored");
+}
+
static int
print_yes_no (char *buff, int len, long v)
{
@@ -548,9 +554,15 @@ declare_hw_handler(skip_kpartx, set_yes_no_undef)
declare_hw_snprint(skip_kpartx, print_yes_no_undef)
declare_mp_handler(skip_kpartx, set_yes_no_undef)
declare_mp_snprint(skip_kpartx, print_yes_no_undef)
-
-declare_def_handler(disable_changed_wwids, set_yes_no)
-declare_def_snprint(disable_changed_wwids, print_yes_no)
+static int def_disable_changed_wwids_handler(struct config *conf, vector strvec)
+{
+ return 0;
+}
+static int snprint_def_disable_changed_wwids(struct config *conf, char *buff,
+ int len, const void *data)
+{
+ return print_ignored(buff, len);
+}
declare_def_handler(remove_retries, set_int)
declare_def_snprint(remove_retries, print_int)
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 864d7eb..646c156 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1148,12 +1148,8 @@ The default is: \fBno\fR
.
.TP
.B disable_changed_wwids
-If set to \fIyes\fR, multipathd will check the path wwid on change events, and
-if it has changed from the wwid of the multipath device, multipathd will
-disable access to the path until the wwid changes back.
-.RS
-.TP
-The default is: \fBno\fR
+This option is deprecated and ignored. If the WWID of a path suddenly changes,
+multipathd handles it as if it was removed and then added again.
.RE
.
.
--
2.17.2

View File

@ -0,0 +1,135 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 28 Mar 2019 15:17:48 -0500
Subject: [PATCH] multipathd: Don't use fallback code after getting wwid
The fallback code is necessary to set up mutipath devices, if multipath
temporarily can't get the information from udev. However, once the
devices are set up, udev is the definitive source of this information.
The wwid gotten from the fallback code and the udev code should always
be the same, in which case it doesn't matter where we get the wwid
from. But if they are different, it's important to try to do the
right thing.
Working under the assumption that udev will either never give us this
information, or that it usually will. multipath should assume that if
there are multiple paths to a device, either they will all never get
a wwid from udev, or some of them will likely already have gotten the
correct wwid from udev. In this case, we should fix this as soon as
possible.
This does mean that devices where udev will never give out the uuid
will not notice if the wwid changes, but that's a small price to pay
for doing the right thing most of the time.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/discovery.c | 22 +++++++++-------------
libmultipath/discovery.h | 3 ++-
multipathd/main.c | 2 +-
3 files changed, 12 insertions(+), 15 deletions(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index 3ec60d6..744cf2c 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1763,7 +1763,6 @@ static ssize_t uid_fallback(struct path *pp, int path_state,
!strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) {
len = get_vpd_uid(pp);
*origin = "sysfs";
- pp->uid_attribute = NULL;
if (len < 0 && path_state == PATH_UP) {
condlog(1, "%s: failed to get sysfs uid: %s",
pp->dev, strerror(-len));
@@ -1787,7 +1786,6 @@ static ssize_t uid_fallback(struct path *pp, int path_state,
len = WWID_SIZE;
}
*origin = "sysfs";
- pp->uid_attribute = NULL;
}
return len;
}
@@ -1800,12 +1798,14 @@ static int has_uid_fallback(struct path *pp)
}
int
-get_uid (struct path * pp, int path_state, struct udev_device *udev)
+get_uid (struct path * pp, int path_state, struct udev_device *udev,
+ int allow_fallback)
{
char *c;
const char *origin = "unknown";
ssize_t len = 0;
struct config *conf;
+ int used_fallback = 0;
if (!pp->uid_attribute && !pp->getuid) {
conf = get_multipath_config();
@@ -1846,14 +1846,9 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev)
len = get_vpd_uid(pp);
origin = "sysfs";
}
- if (len <= 0 && has_uid_fallback(pp)) {
- int retrigger_tries;
-
- conf = get_multipath_config();
- retrigger_tries = conf->retrigger_tries;
- put_multipath_config(conf);
- if (pp->retriggers >= retrigger_tries)
- len = uid_fallback(pp, path_state, &origin);
+ if (len <= 0 && allow_fallback && has_uid_fallback(pp)) {
+ used_fallback = 1;
+ len = uid_fallback(pp, path_state, &origin);
}
}
if ( len < 0 ) {
@@ -1870,7 +1865,7 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev)
c--;
}
}
- condlog(3, "%s: uid = %s (%s)", pp->dev,
+ condlog((used_fallback)? 1 : 3, "%s: uid = %s (%s)", pp->dev,
*pp->wwid == '\0' ? "<empty>" : pp->wwid, origin);
return 0;
}
@@ -1994,7 +1989,8 @@ int pathinfo(struct path *pp, struct config *conf, int mask)
}
if ((mask & DI_WWID) && !strlen(pp->wwid)) {
- get_uid(pp, path_state, pp->udev);
+ get_uid(pp, path_state, pp->udev,
+ (pp->retriggers >= conf->retrigger_tries));
if (!strlen(pp->wwid)) {
if (pp->bus == SYSFS_BUS_UNDEF)
return PATHINFO_SKIPPED;
diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h
index 9aacf75..8fd126b 100644
--- a/libmultipath/discovery.h
+++ b/libmultipath/discovery.h
@@ -52,7 +52,8 @@ ssize_t sysfs_get_vpd (struct udev_device * udev, int pg, unsigned char * buff,
size_t len);
int sysfs_get_asymmetric_access_state(struct path *pp,
char *buff, int buflen);
-int get_uid(struct path * pp, int path_state, struct udev_device *udev);
+int get_uid(struct path * pp, int path_state, struct udev_device *udev,
+ int allow_fallback);
/*
* discovery bitmask
diff --git a/multipathd/main.c b/multipathd/main.c
index e4f95a0..1413c6d 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1227,7 +1227,7 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
goto out;
strcpy(wwid, pp->wwid);
- rc = get_uid(pp, pp->state, uev->udev);
+ rc = get_uid(pp, pp->state, uev->udev, 0);
if (rc != 0)
strcpy(pp->wwid, wwid);
--
2.17.2

View File

@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 28 Mar 2019 17:49:38 -0500
Subject: [PATCH] libmultipath: silence dm_is_mpath error messages
When "multipath -F" is run, dm_is_mpath was printing error messages
about partition devices, because they had already been removed, when
it checked. Lower the error logging level so this doesn't happen on
the default verbosity.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 3294bd4..2e79667 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -746,7 +746,7 @@ out_task:
dm_task_destroy(dmt);
out:
if (r < 0)
- condlog(2, "%s: dm command failed in %s", name, __FUNCTION__);
+ condlog(3, "%s: dm command failed in %s: %s", name, __FUNCTION__, strerror(errno));
return r;
}
--
2.17.2

View File

@ -0,0 +1,66 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 13 Apr 2017 07:22:23 -0500
Subject: [PATCH] RH: fixup udev rules for redhat
The multipath rules need to run after scsi_id is run. This means moving
them after 60-persistent-storage.rules for redhat. Redhat also uses a
different naming scheme for partitions than SuSE.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile.inc | 2 +-
kpartx/kpartx.rules | 2 +-
multipath/Makefile | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index fc728ca..2f0bcea 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -48,7 +48,7 @@ endif
prefix =
exec_prefix = $(prefix)
usr_prefix = $(prefix)
-bindir = $(exec_prefix)/sbin
+bindir = $(exec_prefix)/usr/sbin
libudevdir = $(prefix)/$(SYSTEMDPATH)/udev
udevrulesdir = $(libudevdir)/rules.d
multipathdir = $(TOPDIR)/libmultipath
diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
index 8f99049..8a3a171 100644
--- a/kpartx/kpartx.rules
+++ b/kpartx/kpartx.rules
@@ -32,6 +32,6 @@ LABEL="mpath_kpartx_end"
GOTO="kpartx_end"
LABEL="run_kpartx"
-RUN+="/sbin/kpartx -un -p -part /dev/$name"
+RUN+="/sbin/kpartx -un /dev/$name"
LABEL="kpartx_end"
diff --git a/multipath/Makefile b/multipath/Makefile
index 0828a8f..b9bbb3c 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -24,7 +24,7 @@ install:
$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
- $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
+ $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man8dir)
$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(man8dir)
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir)
@@ -33,7 +33,7 @@ install:
uninstall:
$(RM) $(DESTDIR)$(bindir)/$(EXEC)
$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
- $(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
+ $(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
$(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz
$(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
--
2.17.2

View File

@ -0,0 +1,80 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 2 Jul 2014 12:49:53 -0500
Subject: [PATCH] RH: Remove the property blacklist exception builtin
Multipath set the default property blacklist exceptions to
(ID_SCSI_VPD|ID_WWN). This has the effect of blacklisting some internal
devices. These devices may never have multiple paths, but it is nice
to be able to set multipath up on them all the same. This patch simply
removes the default, and makes it so that if no property
blacklist_exception is given, then devices aren't failed for not matching
it.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/blacklist.c | 12 ++++--------
multipath/multipath.conf.5 | 14 ++++++--------
2 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
index e0d0279..556c0b9 100644
--- a/libmultipath/blacklist.c
+++ b/libmultipath/blacklist.c
@@ -204,12 +204,6 @@ setup_default_blist (struct config * conf)
if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
return 1;
- str = STRDUP("(SCSI_IDENT_|ID_WWN)");
- if (!str)
- return 1;
- if (store_ble(conf->elist_property, str, ORIGIN_DEFAULT))
- return 1;
-
vector_foreach_slot (conf->hwtable, hwe, i) {
if (hwe->bl_product) {
if (find_blacklist_device(conf->blist_device,
@@ -394,9 +388,11 @@ filter_property(struct config *conf, struct udev_device *udev, int lvl)
if (udev) {
/*
* This is the inverse of the 'normal' matching;
- * the environment variable _has_ to match.
+ * the environment variable _has_ to match
+ * if a whitelist is present.
*/
- r = MATCH_PROPERTY_BLIST_MISSING;
+ if (VECTOR_SIZE(conf->elist_property))
+ r = MATCH_PROPERTY_BLIST_MISSING;
udev_list_entry_foreach(list_entry,
udev_device_get_properties_list_entry(udev)) {
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 646c156..768ab83 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1235,16 +1235,14 @@ keywords. Both are regular expressions. For a full description of these keywords
Regular expression for an udev property. All
devices that have matching udev properties will be excluded/included.
The handling of the \fIproperty\fR keyword is special,
-because devices \fBmust\fR have at least one whitelisted udev property;
+because if a property blacklist_exception is set, devices \fBmust\fR have at
+least one whitelisted udev property;
otherwise they're treated as blacklisted, and the message
"\fIblacklisted, udev property missing\fR" is displayed in the logs.
-.
-.RS
-.PP
-The default \fIblacklist exception\fR is: \fB(SCSI_IDENT_|ID_WWN)\fR, causing
-well-behaved SCSI devices and devices that provide a WWN (World Wide Number)
-to be included, and all others to be excluded.
-.RE
+For example, setting the property blacklist_exception to
+\fB(SCSI_IDENT_|ID_WWN)\fR, will cause well-behaved SCSI devices and devices
+that provide a WWN (World Wide Number) to be included, and all others to be
+excluded. This works to exclude most non-multipathable devices.
.TP
.B protocol
Regular expression for the protocol of a device to be excluded/included.
--
2.17.2

View File

@ -0,0 +1,106 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 15 Oct 2014 10:39:30 -0500
Subject: [PATCH] RH: don't start without a config file
If /etc/multipath.conf doesn't exist, don't start multipathd and blacklist
all devices when running multipath. A completely blank configuration file
is almost never what users want. Also, people may have the multipath
packages installed but don't want to use them. This patch provides a
simple way to disable multipath. Simply removing or renaming
/etc/multipath.conf will keep multipath from doing anything.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/config.c | 15 +++++++++++++++
libmultipath/config.h | 1 +
multipath/multipath.rules | 1 +
multipathd/multipathd.8 | 2 ++
multipathd/multipathd.service | 1 +
5 files changed, 20 insertions(+)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 141f092..544d2fb 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -26,6 +26,7 @@
#include "devmapper.h"
#include "mpath_cmd.h"
#include "propsel.h"
+#include "version.h"
static int
hwe_strmatch (const struct hwentry *hwe1, const struct hwentry *hwe2)
@@ -745,6 +746,20 @@ load_config (char * file)
goto out;
}
factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
+ } else {
+ condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
+ if (conf->blist_devnode == NULL) {
+ conf->blist_devnode = vector_alloc();
+ if (!conf->blist_devnode) {
+ condlog(0, "cannot allocate blacklist\n");
+ goto out;
+ }
+ }
+ if (store_ble(conf->blist_devnode, strdup(".*"),
+ ORIGIN_NO_CONFIG)) {
+ condlog(0, "cannot store default no-config blacklist\n");
+ goto out;
+ }
}
conf->processed_main_config = 1;
diff --git a/libmultipath/config.h b/libmultipath/config.h
index f5bf5b1..8803967 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -9,6 +9,7 @@
#define ORIGIN_DEFAULT 0
#define ORIGIN_CONFIG 1
+#define ORIGIN_NO_CONFIG 2
/*
* In kernel, fast_io_fail == 0 means immediate failure on rport delete.
diff --git a/multipath/multipath.rules b/multipath/multipath.rules
index 9df11a9..0486bf7 100644
--- a/multipath/multipath.rules
+++ b/multipath/multipath.rules
@@ -9,6 +9,7 @@ IMPORT{cmdline}="nompath"
ENV{nompath}=="?*", GOTO="end_mpath"
IMPORT{cmdline}="multipath"
ENV{multipath}=="off", GOTO="end_mpath"
+TEST!="/etc/multipath.conf", GOTO="end_mpath"
ENV{DEVTYPE}!="partition", GOTO="test_dev"
IMPORT{parent}="DM_MULTIPATH_DEVICE_PATH"
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8
index 94c3f97..ed13efd 100644
--- a/multipathd/multipathd.8
+++ b/multipathd/multipathd.8
@@ -38,6 +38,8 @@ map regains its maximum performance and redundancy.
This daemon executes the external \fBmultipath\fR tool when events occur.
In turn, the multipath tool signals the multipathd daemon when it is done with
devmap reconfiguration, so that it can refresh its failed path list.
+
+In this Linux distribution, multipathd does not run unless a /etc/multipath.conf file exists.
.
.
.\" ----------------------------------------------------------------------------
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
index ba24983..17434ce 100644
--- a/multipathd/multipathd.service
+++ b/multipathd/multipathd.service
@@ -4,6 +4,7 @@ Wants=systemd-udev-trigger.service systemd-udev-settle.service
Before=iscsi.service iscsid.service lvm2-activation-early.service
Before=local-fs-pre.target blk-availability.service
After=multipathd.socket systemd-udev-trigger.service systemd-udev-settle.service
+ConditionPathExists=/etc/multipath.conf
DefaultDependencies=no
Conflicts=shutdown.target
ConditionKernelCommandLine=!nompath
--
2.17.2

View File

@ -0,0 +1,53 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 19 Apr 2017 06:10:01 -0500
Subject: [PATCH] RH: use rpm optflags if present
Use the passed in optflags when compiling as an RPM, and keep the
default flags as close as possible to the current fedora flags, while
still being generic.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile.inc | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 2f0bcea..b98800a 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -83,15 +83,23 @@ TEST_CC_OPTION = $(shell \
echo "$(2)"; \
fi)
-STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)
ERROR_DISCARDED_QUALIFIERS := $(call TEST_CC_OPTION,-Werror=discarded-qualifiers,)
-
-OPTFLAGS = -O2 -g -pipe -Wall -Wextra -Wformat=2 -Werror=implicit-int \
- -Werror=implicit-function-declaration -Werror=format-security \
- -Wno-sign-compare -Wno-unused-parameter -Wno-clobbered \
- -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) \
- -Wp,-D_FORTIFY_SOURCE=2 $(STACKPROT) \
- --param=ssp-buffer-size=4
+ifndef RPM_OPT_FLAGS
+ STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)
+ OPTFLAGS = -O2 -g -pipe -Wall -Werror=format-security \
+ -Wp,-D_FORTIFY_SOURCE=2 -fexceptions \
+ $(STACKPROT) --param=ssp-buffer-size=4 \
+ -grecord-gcc-switches
+ ifeq ($(shell test -f /usr/lib/rpm/redhat/redhat-hardened-cc1 && echo 1),1)
+ OPTFLAGS += -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1
+ endif
+else
+ OPTFLAGS = $(RPM_OPT_FLAGS)
+endif
+OPTFLAGS += -Wextra -Wstrict-prototypes -Wformat=2 -Werror=implicit-int \
+ -Werror=implicit-function-declaration -Wno-sign-compare \
+ -Wno-unused-parameter $(ERROR_DISCARDED_QUALIFIERS) \
+ -Werror=cast-qual
CFLAGS := $(OPTFLAGS) -DBIN_DIR=\"$(bindir)\" -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \
-MMD -MP $(CFLAGS)
--
2.17.2

View File

@ -0,0 +1,667 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 16 Oct 2014 15:49:01 -0500
Subject: [PATCH] RH: add mpathconf
mpathconf is a program (largely based on lvmcomf) to help users
configure /etc/multipath.conf and enable or disable multipathing. It
has a couple of built-in options that can be set directly from the
command line. But, mostly it is used to get a multipath.conf file
with the OS defaults, and to enable and disable multipathing via
a single command.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/config.c | 2 +
multipath/Makefile | 5 +
multipath/mpathconf | 464 ++++++++++++++++++++++++++++++++++++++++++
multipath/mpathconf.8 | 119 +++++++++++
4 files changed, 590 insertions(+)
create mode 100644 multipath/mpathconf
create mode 100644 multipath/mpathconf.8
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 544d2fb..deb80c2 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -748,6 +748,8 @@ load_config (char * file)
factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
} else {
condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
+ condlog(0, "You can run \"/sbin/mpathconf --enable\" to create");
+ condlog(0, "/etc/multipath.conf. See man mpathconf(8) for more details");
if (conf->blist_devnode == NULL) {
conf->blist_devnode = vector_alloc();
if (!conf->blist_devnode) {
diff --git a/multipath/Makefile b/multipath/Makefile
index b9bbb3c..e720c7f 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -18,10 +18,12 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
$(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS) $(LIBDEPS)
$(GZIP) $(EXEC).8 > $(EXEC).8.gz
$(GZIP) $(EXEC).conf.5 > $(EXEC).conf.5.gz
+ $(GZIP) mpathconf.8 > mpathconf.8.gz
install:
$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
+ $(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/
$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
$(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
@@ -29,13 +31,16 @@ install:
$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(man8dir)
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir)
$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir)
+ $(INSTALL_PROGRAM) -m 644 mpathconf.8.gz $(DESTDIR)$(man8dir)
uninstall:
$(RM) $(DESTDIR)$(bindir)/$(EXEC)
$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
$(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
+ $(RM) $(DESTDIR)$(bindir)/mpathconf
$(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz
$(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
+ $(RM) $(DESTDIR)$(man8dir)/mpathconf.8.gz
clean: dep_clean
$(RM) core *.o $(EXEC) *.gz
diff --git a/multipath/mpathconf b/multipath/mpathconf
new file mode 100644
index 0000000..e839134
--- /dev/null
+++ b/multipath/mpathconf
@@ -0,0 +1,464 @@
+#!/bin/bash
+#
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This file is part of the device-mapper-multipath package.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#
+# Simple editting of /etc/multipath.conf
+# This program was largely ripped off from lvmconf
+#
+
+unset ENABLE FIND FRIENDLY MODULE MULTIPATHD HAVE_DISABLE HAVE_WWID_DISABLE HAVE_FIND HAVE_BLACKLIST HAVE_EXCEPTIONS HAVE_DEFAULTS HAVE_FRIENDLY HAVE_MULTIPATHD HAVE_MODULE HAVE_OUTFILE SHOW_STATUS CHANGED_CONFIG WWID_LIST
+
+DEFAULT_CONFIG="# device-mapper-multipath configuration file
+
+# For a complete list of the default configuration values, run either:
+# # multipath -t
+# or
+# # multipathd show config
+
+# For a list of configuration options with descriptions, see the
+# multipath.conf man page.
+
+defaults {
+ user_friendly_names yes
+ find_multipaths yes
+}
+
+blacklist_exceptions {
+ property \"(SCSI_IDENT_|ID_WWN)\"
+}"
+
+CONFIGFILE="/etc/multipath.conf"
+OUTPUTFILE="/etc/multipath.conf"
+MULTIPATHDIR="/etc/multipath"
+TMPFILE="/etc/multipath/.multipath.conf.tmp"
+WWIDS=0
+
+function usage
+{
+ echo "usage: $0 <command>"
+ echo ""
+ echo "Commands:"
+ echo "Enable: --enable "
+ echo "Disable: --disable"
+ echo "Only allow certain wwids (instead of enable): --allow <WWID>"
+ echo "Set user_friendly_names (Default y): --user_friendly_names <y|n>"
+ echo "Set find_multipaths (Default y): --find_multipaths <y|n>"
+ echo "Load the dm-multipath modules on enable (Default y): --with_module <y|n>"
+ echo "start/stop/reload multipathd (Default n): --with_multipathd <y|n>"
+ echo "select output file (Default /etc/multipath.conf): --outfile <FILE>"
+ echo ""
+}
+
+function add_wwid
+{
+ INDEX=0
+ while [ "$INDEX" -lt "$WWIDS" ] ; do
+ if [ "$1" = "${WWID_LIST[$INDEX]}" ] ; then
+ return
+ fi
+ ((INDEX++))
+ done
+ WWID_LIST[$WWIDS]="$1"
+ ((WWIDS++))
+}
+
+function get_dm_deps
+{
+ shift 3
+ while [ -n "$1" -a -n "$2" ]; do
+ MAJOR=$(echo $1 | tr -d '(,')
+ MINOR=$(echo $2 | tr -d ')')
+ UUID=`dmsetup info -c --noheadings -o uuid -j $MAJOR -m $MINOR 2> /dev/null`
+ if [ -n "$UUID" ] ; then
+ set_dm_wwid $UUID
+ fi
+ shift 2
+ done
+}
+
+function set_dm_wwid
+{
+ if [[ "$1" =~ ^part[[:digit:]]+-mpath- ]] ; then
+ add_wwid "${1##part*-mpath-}"
+ elif [[ "$1" =~ ^mpath- ]] ; then
+ add_wwid "${1##mpath-}"
+ else
+ get_dm_deps `dmsetup deps -u $1`
+ fi
+}
+
+function set_wwid
+{
+ UUID=""
+ if [[ "$1" =~ ^[[:digit:]]+:[[:digit:]]+$ ]] ; then
+ MAJOR=${1%%:*}
+ MINOR=${1##*:}
+ UUID=`dmsetup info -c --noheadings -o uuid -j $MAJOR -m $MINOR 2> /dev/null`
+ else
+ UUID=`dmsetup info -c --noheadings -o uuid $1 2> /dev/null`
+ fi
+ if [ -n "$UUID" ] ; then
+ set_dm_wwid $UUID
+ else
+ add_wwid "$1"
+ fi
+}
+
+function parse_args
+{
+ while [ -n "$1" ]; do
+ case $1 in
+ --enable)
+ ENABLE=1
+ shift
+ ;;
+ --disable)
+ ENABLE=0
+ shift
+ ;;
+ --allow)
+ ENABLE=2
+ if [ -n "$2" ]; then
+ set_wwid $2
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ --user_friendly_names)
+ if [ -n "$2" ]; then
+ FRIENDLY=$2
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ --find_multipaths)
+ if [ -n "$2" ]; then
+ FIND=$2
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ --with_module)
+ if [ -n "$2" ]; then
+ MODULE=$2
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ --with_multipathd)
+ if [ -n "$2" ]; then
+ MULTIPATHD=$2
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ --outfile)
+ if [ -n "$2" ]; then
+ OUTPUTFILE=$2
+ HAVE_OUTFILE=1
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ *)
+ usage
+ exit
+ esac
+ done
+}
+
+function validate_args
+{
+ if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$MODULE" ]; then
+ echo "ignoring extra parameters on disable"
+ FRIENDLY=""
+ FIND=""
+ MODULE=""
+ fi
+ if [ -n "$FRIENDLY" ] && [ "$FRIENDLY" != "y" -a "$FRIENDLY" != "n" ]; then
+ echo "--user_friendly_names must be either 'y' or 'n'"
+ exit 1
+ fi
+ if [ -n "$FIND" ] && [ "$FIND" != "y" -a "$FIND" != "n" ]; then
+ echo "--find_multipaths must be either 'y' or 'n'"
+ exit 1
+ fi
+ if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" ]; then
+ SHOW_STATUS=1
+ fi
+ if [ -n "$MODULE" ] && [ "$MODULE" != "y" -a "$MODULE" != "n" ]; then
+ echo "--with_module must be either 'y' or 'n'"
+ exit 1
+ fi
+ if [ -n "$MULTIPATHD" ] && [ "$MULTIPATHD" != "y" -a "$MULTIPATHD" != "n" ]; then
+ echo "--with_multipathd must be either 'y' or 'n'"
+ exit 1
+ fi
+ if [ "$ENABLE" = 2 -a -z "$HAVE_OUTFILE" ]; then
+ echo "Because --allow makes changes that cannot be automatically reversed,"
+ echo "you must set --outfile when you set --allow"
+ exit 1
+ fi
+}
+
+function add_blacklist_exceptions
+{
+ INDEX=0
+ while [ "$INDEX" -lt "$WWIDS" ] ; do
+ sed -i '/^blacklist_exceptions[[:space:]]*{/ a\
+ wwid '"\"${WWID_LIST[$INDEX]}\""'
+' $TMPFILE
+ ((INDEX++))
+ done
+}
+
+umask 0077
+
+parse_args "$@"
+
+validate_args
+
+if [ ! -d "$MULTIPATHDIR" ]; then
+ echo "/etc/multipath/ does not exist. failing"
+ exit 1
+fi
+
+rm $TMPFILE 2> /dev/null
+echo "$DEFAULT_CONFIG" > $TMPFILE
+if [ -f "$CONFIGFILE" ]; then
+ cp $CONFIGFILE $TMPFILE
+fi
+
+if grep -q "^blacklist[[:space:]]*{" $TMPFILE ; then
+ HAVE_BLACKLIST=1
+fi
+
+if grep -q "^blacklist_exceptions[[:space:]]*{" $TMPFILE ; then
+ HAVE_EXCEPTIONS=1
+fi
+
+if grep -q "^defaults[[:space:]]*{" $TMPFILE ; then
+ HAVE_DEFAULTS=1
+fi
+
+if [ -z "$MODULE" -o "$MODULE" = "y" ]; then
+ if lsmod | grep -q "dm_multipath" ; then
+ HAVE_MODULE=1
+ else
+ HAVE_MODULE=0
+ fi
+fi
+
+if [ "$MULTIPATHD" = "y" ]; then
+ if /bin/systemctl status multipathd.service > /dev/null 2>&1 ; then
+ HAVE_MULTIPATHD=1
+ else
+ HAVE_MULTIPATHD=0
+ fi
+fi
+
+if [ "$HAVE_BLACKLIST" = "1" ]; then
+ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*devnode \"\.\?\*\"" ; then
+ HAVE_DISABLE=1
+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"" ; then
+ HAVE_DISABLE=0
+ fi
+fi
+
+if [ "$HAVE_BLACKLIST" = "1" ]; then
+ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*wwid \"\.\?\*\"" ; then
+ HAVE_WWID_DISABLE=1
+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"" ; then
+ HAVE_WWID_DISABLE=0
+ fi
+fi
+
+if [ "$HAVE_DEFAULTS" = "1" ]; then
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)" ; then
+ HAVE_FIND=1
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)" ; then
+ HAVE_FIND=0
+ fi
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)" ; then
+ HAVE_FRIENDLY=1
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)" ; then
+ HAVE_FRIENDLY=0
+ fi
+fi
+
+if [ -n "$SHOW_STATUS" ]; then
+ if [ -z "$HAVE_DISABLE" -o "$HAVE_DISABLE" = 0 ]; then
+ echo "multipath is enabled"
+ else
+ echo "multipath is disabled"
+ fi
+ if [ -z "$HAVE_FIND" -o "$HAVE_FIND" = 0 ]; then
+ echo "find_multipaths is disabled"
+ else
+ echo "find_multipaths is enabled"
+ fi
+ if [ -z "$HAVE_FRIENDLY" -o "$HAVE_FRIENDLY" = 0 ]; then
+ echo "user_friendly_names is disabled"
+ else
+ echo "user_friendly_names is enabled"
+ fi
+ if [ -n "$HAVE_MODULE" ]; then
+ if [ "$HAVE_MODULE" = 1 ]; then
+ echo "dm_multipath module is loaded"
+ else
+ echo "dm_multipath module is not loaded"
+ fi
+ fi
+ if [ -z "$HAVE_MULTIPATHD" ]; then
+ if /bin/systemctl status multipathd.service > /dev/null 2>&1 ; then
+ HAVE_MULTIPATHD=1
+ else
+ HAVE_MULTIPATHD=0
+ fi
+ fi
+ if [ "$HAVE_MULTIPATHD" = 1 ]; then
+ echo "multipathd is running"
+ else
+ echo "multipathd is not running"
+ fi
+ exit 0
+fi
+
+if [ -z "$HAVE_BLACKLIST" ]; then
+ cat >> $TMPFILE <<- _EOF_
+
+blacklist {
+}
+_EOF_
+fi
+
+if [ -z "$HAVE_DEFAULTS" ]; then
+ cat >> $TMPFILE <<- _EOF_
+
+defaults {
+}
+_EOF_
+fi
+
+if [ "$ENABLE" = 2 ]; then
+ if [ "$HAVE_DISABLE" = 1 ]; then
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE
+ fi
+ if [ -z "$HAVE_WWID_DISABLE" ]; then
+ sed -i '/^blacklist[[:space:]]*{/ a\
+ wwid ".*"
+' $TMPFILE
+ elif [ "$HAVE_WWID_DISABLE" = 0 ]; then
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"/ wwid ".*"/' $TMPFILE
+ fi
+ if [ "$HAVE_EXCEPTIONS" = 1 ]; then
+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ {/^[[:space:]]*wwid/ d}' $TMPFILE
+ else
+ cat >> $TMPFILE <<- _EOF_
+
+blacklist_exceptions {
+}
+_EOF_
+ fi
+ add_blacklist_exceptions
+elif [ "$ENABLE" = 1 ]; then
+ if [ "$HAVE_DISABLE" = 1 ]; then
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE
+ fi
+elif [ "$ENABLE" = 0 ]; then
+ if [ -z "$HAVE_DISABLE" ]; then
+ sed -i '/^blacklist[[:space:]]*{/ a\
+ devnode ".*"
+' $TMPFILE
+ elif [ "$HAVE_DISABLE" = 0 ]; then
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"/ devnode ".*"/' $TMPFILE
+ fi
+fi
+
+if [ "$FIND" = "n" ]; then
+ if [ "$HAVE_FIND" = 1 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)/ find_multipaths no/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+elif [ "$FIND" = "y" ]; then
+ if [ -z "$HAVE_FIND" ]; then
+ sed -i '/^defaults[[:space:]]*{/ a\
+ find_multipaths yes
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$HAVE_FIND" = 0 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)/ find_multipaths yes/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+fi
+
+if [ "$FRIENDLY" = "n" ]; then
+ if [ "$HAVE_FRIENDLY" = 1 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)/ user_friendly_names no/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+elif [ "$FRIENDLY" = "y" ]; then
+ if [ -z "$HAVE_FRIENDLY" ]; then
+ sed -i '/^defaults[[:space:]]*{/ a\
+ user_friendly_names yes
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$HAVE_FRIENDLY" = 0 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)/ user_friendly_names yes/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+fi
+
+if [ -f "$OUTPUTFILE" ]; then
+ cp $OUTPUTFILE $OUTPUTFILE.old
+ if [ $? != 0 ]; then
+ echo "failed to backup old config file, $OUTPUTFILE not updated"
+ exit 1
+ fi
+fi
+
+cp $TMPFILE $OUTPUTFILE
+if [ $? != 0 ]; then
+ echo "failed to copy new config file into place, check $OUTPUTFILE is still OK"
+ exit 1
+fi
+
+rm -f $TMPFILE
+
+if [ "$ENABLE" = 1 ]; then
+ if [ "$HAVE_MODULE" = 0 ]; then
+ modprobe dm_multipath
+ fi
+ if [ "$HAVE_MULTIPATHD" = 0 ]; then
+ systemctl start multipathd.service
+ fi
+elif [ "$ENABLE" = 0 ]; then
+ if [ "$HAVE_MULTIPATHD" = 1 ]; then
+ systemctl stop multipathd.service
+ fi
+elif [ -n "$CHANGED_CONFIG" -a "$HAVE_MULTIPATHD" = 1 ]; then
+ systemctl reload multipathd.service
+fi
diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8
new file mode 100644
index 0000000..5b7ae0c
--- /dev/null
+++ b/multipath/mpathconf.8
@@ -0,0 +1,119 @@
+.TH MPATHCONF 8 "June 2010" "" "Linux Administrator's Manual"
+.SH NAME
+mpathconf - A tool for configuring device-mapper-multipath
+.SH SYNOPSIS
+.B mpathconf
+.RB [\| commands \|]
+.RB [\| options \|]
+.SH DESCRIPTION
+.B mpathconf
+is a utility that creates or modifies
+.B /etc/multipath.conf.
+It can enable or disable multipathing and configure some common options.
+.B mpathconf
+can also load the
+.B dm_multipath
+module, start and stop the
+.B multipathd
+daemon, and configure the
+.B multipathd
+service to start automatically or not. If
+.B mpathconf
+is called with no commands, it will display the current configuration, but
+will not create of modify
+.B /etc/multipath.conf
+
+The default options for mpathconf are
+.B --with_module
+The
+.B --with_multipathd
+option is not set by default. Enabling multipathing will load the
+.B dm_multipath
+module but it will not immediately start it. This is so
+that users can manually edit their config file if necessary, before starting
+.B multipathd.
+
+If
+.B /etc/multipath.conf
+already exists, mpathconf will edit it. If it does not exist, mpathconf will
+create a default file with
+.B user_friendly_names
+and
+.B find_multipaths
+set. To disable these, use the
+.B --user_friendly_names n
+and
+.B --find_multipaths n
+options
+.SH COMMANDS
+.TP
+.B --enable
+Removes any line that blacklists all device nodes from the
+.B /etc/multipath.conf
+blacklist section. Also, creates
+.B /etc/multipath.conf
+if it doesn't exist.
+.TP
+.B --disable
+Adds a line that blacklists all device nodes to the
+.B /etc/multipath.conf
+blacklist section. If no blacklist section exists, it will create one.
+.TP
+.B --allow \fB<device>\fP
+Modifies the \fB/etc/multipath/conf\fP blacklist to blacklist all
+wwids and the blacklist_exceptions to whitelist \fB<device>\fP. \fB<device>\fP
+can be in the form of MAJOR:MINOR, a wwid, or the name of a device-mapper
+device, either a multipath device, or any device on stacked on top of one or
+more multipath devices. This command can be used multiple times to allow
+multiple devices. \fBNOTE:\fP This action will create a configuration file that
+mpathconf will not be able to revert back to its previous state. Because
+of this, \fB--outfile\fP is required when using \fB--allow\fP.
+.TP
+.B --user_friendly_name \fP { \fBy\fP | \fBn\fP }
+If set to \fBy\fP, this adds the line
+.B user_friendly_names yes
+to the
+.B /etc/multipath.conf
+defaults section. If set to \fBn\fP, this removes the line, if present. This
+command can be used along with any other command.
+.TP
+.B --find_multipaths\fP { \fBy\fP | \fBn\fP }
+If set to \fBy\fP, this adds the line
+.B find_multipaths yes
+to the
+.B /etc/multipath.conf
+defaults section. If set to \fBn\fP, this removes the line, if present. This
+command can be used aldong with any other command.
+.TP
+.B --outfile \fB<filename>\fP
+Write the resulting multipath configuration to \fB<filename>\fP instead of
+\fB/etc/multipath.conf\fP.
+.SH OPTIONS
+.TP
+.B --with_module\fP { \fBy\fP | \fBn\fP }
+If set to \fBy\fP, this runs
+.B modprobe dm_multipath
+to install the multipath modules. This option only works with the
+.B --enable
+command. This option is set to \fBy\fP by default.
+.TP
+.B --with_multipathd { \fBy\fP | \fBn\fP }
+If set to \fBy\fP, this runs
+.B service multipathd start
+to start the multipathd daemon on \fB--enable\fP,
+.B service multipathd stop
+to stop the multipathd daemon on \fB--disable\fP, and
+.B service multipathd reload
+to reconfigure multipathd on \fB--user_frindly_names\fP and
+\fB--find_multipaths\fP.
+This option is set to \fBn\fP by default.
+.SH FILES
+.BR /etc/multipath.conf
+.SH "SEE ALSO"
+.BR multipath.conf (5),
+.BR modprobe (8),
+.BR multipath (8),
+.BR multipathd (8),
+.BR service (8),
+.SH AUTHOR
+Benjamin Marzinski <bmarzins@redhat.com>
--
2.17.2

View File

@ -0,0 +1,169 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 17 Oct 2014 11:20:34 -0500
Subject: [PATCH] RH: add wwids from kernel cmdline mpath.wwids with -A
This patch adds another option to multipath, "-A", which reads
/proc/cmdline for mpath.wwid=<WWID> options, and adds any wwids it finds
to /etc/multipath/wwids. While this isn't usually important during
normal operation, since these wwids should already be added, it can be
helpful during installation, to make sure that multipath can claim
devices as its own, before LVM or something else makes use of them. The
patch also execs "/sbin/multipath -A" before running multipathd in
multipathd.service
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/wwids.c | 44 +++++++++++++++++++++++++++++++++++
libmultipath/wwids.h | 1 +
multipath/main.c | 10 ++++++--
multipath/multipath.8 | 7 +++++-
multipathd/multipathd.service | 1 +
5 files changed, 60 insertions(+), 3 deletions(-)
diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
index 53e7951..39e08cd 100644
--- a/libmultipath/wwids.c
+++ b/libmultipath/wwids.c
@@ -443,3 +443,47 @@ int op ## _wwid(const char *wwid) \
declare_failed_wwid_op(is_failed, false)
declare_failed_wwid_op(mark_failed, true)
declare_failed_wwid_op(unmark_failed, true)
+
+int remember_cmdline_wwid(void)
+{
+ FILE *f = NULL;
+ char buf[LINE_MAX], *next, *ptr;
+ int ret = 0;
+
+ f = fopen("/proc/cmdline", "re");
+ if (!f) {
+ condlog(0, "can't open /proc/cmdline : %s", strerror(errno));
+ return -1;
+ }
+
+ if (!fgets(buf, sizeof(buf), f)) {
+ if (ferror(f))
+ condlog(0, "read of /proc/cmdline failed : %s",
+ strerror(errno));
+ else
+ condlog(0, "couldn't read /proc/cmdline");
+ fclose(f);
+ return -1;
+ }
+ fclose(f);
+ next = buf;
+ while((ptr = strstr(next, "mpath.wwid="))) {
+ ptr += 11;
+ next = strpbrk(ptr, " \t\n");
+ if (next) {
+ *next = '\0';
+ next++;
+ }
+ if (strlen(ptr)) {
+ if (remember_wwid(ptr) != 0)
+ ret = -1;
+ }
+ else {
+ condlog(0, "empty mpath.wwid kernel command line option");
+ ret = -1;
+ }
+ if (!next)
+ break;
+ }
+ return ret;
+}
diff --git a/libmultipath/wwids.h b/libmultipath/wwids.h
index 0c6ee54..e32a0b0 100644
--- a/libmultipath/wwids.h
+++ b/libmultipath/wwids.h
@@ -17,6 +17,7 @@ int remember_wwid(char *wwid);
int check_wwids_file(char *wwid, int write_wwid);
int remove_wwid(char *wwid);
int replace_wwids(vector mp);
+int remember_cmdline_wwid(void);
enum {
WWID_IS_NOT_FAILED = 0,
diff --git a/multipath/main.c b/multipath/main.c
index 69141db..e7771c0 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -133,7 +133,7 @@ usage (char * progname)
{
fprintf (stderr, VERSION_STRING);
fprintf (stderr, "Usage:\n");
- fprintf (stderr, " %s [-a|-c|-w|-W] [-d] [-r] [-i] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname);
+ fprintf (stderr, " %s [-a|-A|-c|-w|-W] [-d] [-r] [-i] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname);
fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [-R num] [dev]\n", progname);
fprintf (stderr, " %s -F [-v lvl] [-R num]\n", progname);
fprintf (stderr, " %s [-t|-T]\n", progname);
@@ -147,6 +147,8 @@ usage (char * progname)
" -f flush a multipath device map\n"
" -F flush all multipath device maps\n"
" -a add a device wwid to the wwids file\n"
+ " -A add devices from kernel command line mpath.wwids\n"
+ " parameters to wwids file\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"
" -q allow queue_if_no_path when multipathd is not running\n"
@@ -870,7 +872,7 @@ main (int argc, char *argv[])
exit(RTVL_FAIL);
multipath_conf = conf;
conf->retrigger_tries = 0;
- while ((arg = getopt(argc, argv, ":adcChl::FfM:v:p:b:BrR:itTquUwW")) != EOF ) {
+ while ((arg = getopt(argc, argv, ":aAdcChl::FfM:v:p:b:BrR:itTquUwW")) != EOF ) {
switch(arg) {
case 1: printf("optarg : %s\n",optarg);
break;
@@ -940,6 +942,10 @@ main (int argc, char *argv[])
case 'T':
cmd = CMD_DUMP_CONFIG;
break;
+ case 'A':
+ if (remember_cmdline_wwid() != 0)
+ exit(RTVL_FAIL);
+ exit(RTVL_OK);
case 'h':
usage(argv[0]);
exit(RTVL_OK);
diff --git a/multipath/multipath.8 b/multipath/multipath.8
index 9cdd05a..8befc45 100644
--- a/multipath/multipath.8
+++ b/multipath/multipath.8
@@ -63,7 +63,7 @@ multipath \- Device mapper target autoconfig.
.B multipath
.RB [\| \-v\ \c
.IR level \|]
-.B -W
+.RB [\| \-A | \-W \|]
.
.LP
.B multipath
@@ -145,6 +145,11 @@ device mapper, path checkers ...).
Add the WWID for the specified device to the WWIDs file.
.
.TP
+.B \-A
+Add the WWIDs from any kernel command line \fImpath.wwid\fR parameters to the
+WWIDs file.
+.
+.TP
.B \-w
Remove the WWID for the specified device from the WWIDs file.
.
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
index 17434ce..0fbcc46 100644
--- a/multipathd/multipathd.service
+++ b/multipathd/multipathd.service
@@ -15,6 +15,7 @@ Type=notify
NotifyAccess=main
LimitCORE=infinity
ExecStartPre=-/sbin/modprobe -a scsi_dh_alua scsi_dh_emc scsi_dh_rdac dm-multipath
+ExecStartPre=-/sbin/multipath -A
ExecStart=/sbin/multipathd -d -s
ExecReload=/sbin/multipathd reconfigure
TasksMax=infinity
--
2.17.2

View File

@ -0,0 +1,121 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 6 Nov 2017 21:39:28 -0600
Subject: [PATCH] RH: warn on invalid regex instead of failing
multipath.conf used to allow "*" as a match everything regular expression,
instead of requiring ".*". Instead of erroring when the old style
regular expressions are used, it should print a warning and convert
them.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/dict.c | 27 +++++++++++++++++++++------
libmultipath/parser.c | 13 +++++++++++++
libmultipath/parser.h | 1 +
3 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index 96815f8..3b1b652 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -58,6 +58,21 @@ set_str(vector strvec, void *ptr)
return 0;
}
+static int
+set_regex(vector strvec, void *ptr)
+{
+ char **str_ptr = (char **)ptr;
+
+ if (*str_ptr)
+ FREE(*str_ptr);
+ *str_ptr = set_regex_value(strvec);
+
+ if (!*str_ptr)
+ return 1;
+
+ return 0;
+}
+
static int
set_yes_no(vector strvec, void *ptr)
{
@@ -1386,7 +1401,7 @@ ble_ ## option ## _handler (struct config *conf, vector strvec) \
if (!conf->option) \
return 1; \
\
- buff = set_value(strvec); \
+ buff = set_regex_value(strvec); \
if (!buff) \
return 1; \
\
@@ -1402,7 +1417,7 @@ ble_ ## option ## _ ## name ## _handler (struct config *conf, vector strvec) \
if (!conf->option) \
return 1; \
\
- buff = set_value(strvec); \
+ buff = set_regex_value(strvec); \
if (!buff) \
return 1; \
\
@@ -1505,16 +1520,16 @@ device_handler(struct config *conf, vector strvec)
return 0;
}
-declare_hw_handler(vendor, set_str)
+declare_hw_handler(vendor, set_regex)
declare_hw_snprint(vendor, print_str)
-declare_hw_handler(product, set_str)
+declare_hw_handler(product, set_regex)
declare_hw_snprint(product, print_str)
-declare_hw_handler(revision, set_str)
+declare_hw_handler(revision, set_regex)
declare_hw_snprint(revision, print_str)
-declare_hw_handler(bl_product, set_str)
+declare_hw_handler(bl_product, set_regex)
declare_hw_snprint(bl_product, print_str)
declare_hw_handler(hwhandler, set_str)
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
index 92ef7cf..4289336 100644
--- a/libmultipath/parser.c
+++ b/libmultipath/parser.c
@@ -384,6 +384,19 @@ set_value(vector strvec)
return alloc;
}
+void *
+set_regex_value(vector strvec)
+{
+ char *buff = set_value(strvec);
+
+ if (buff && strcmp("*", buff) == 0) {
+ condlog(0, "Invalid regular expression \"*\" in multipath.conf. Using \".*\"");
+ FREE(buff);
+ return strdup(".*");
+ }
+ return buff;
+}
+
/* non-recursive configuration stream handler */
static int kw_level = 0;
diff --git a/libmultipath/parser.h b/libmultipath/parser.h
index 62906e9..b791705 100644
--- a/libmultipath/parser.h
+++ b/libmultipath/parser.h
@@ -77,6 +77,7 @@ extern void dump_keywords(vector keydump, int level);
extern void free_keywords(vector keywords);
extern vector alloc_strvec(char *string);
extern void *set_value(vector strvec);
+extern void *set_regex_value(vector strvec);
extern int process_file(struct config *conf, char *conf_file);
extern struct keyword * find_keyword(vector keywords, vector v, char * name);
int snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw,
--
2.17.2

View File

@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 7 Jun 2018 17:43:52 -0500
Subject: [PATCH] RH: reset default find_mutipaths value to off
Upstream has changed to default find_multipaths to "strict". For now
Redhat will retain the previous default of "off".
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/defaults.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index 6576939..2ad6308 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -17,7 +17,7 @@
#define DEFAULT_NO_PATH_RETRY NO_PATH_RETRY_UNDEF
#define DEFAULT_VERBOSITY 2
#define DEFAULT_REASSIGN_MAPS 0
-#define DEFAULT_FIND_MULTIPATHS FIND_MULTIPATHS_STRICT
+#define DEFAULT_FIND_MULTIPATHS FIND_MULTIPATHS_OFF
#define DEFAULT_FAST_IO_FAIL 5
#define DEFAULT_DEV_LOSS_TMO 600
#define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_ON
--
2.17.2

View File

@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 25 Jan 2019 14:54:56 -0600
Subject: [PATCH] RH: Fix nvme compilation warning
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/nvme/argconfig.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/nvme/argconfig.h b/libmultipath/nvme/argconfig.h
index adb192b..bfd10ef 100644
--- a/libmultipath/nvme/argconfig.h
+++ b/libmultipath/nvme/argconfig.h
@@ -76,7 +76,7 @@ struct argconfig_commandline_options {
extern "C" {
#endif
-typedef void argconfig_help_func();
+typedef void argconfig_help_func(void);
void argconfig_append_usage(const char *str);
void argconfig_print_help(const char *program_desc,
const struct argconfig_commandline_options *options);
--
2.17.2

View File

@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Igor Gnatenko <ignatenkobrain@fedoraproject.org>
Date: Tue, 26 Mar 2019 16:34:32 -0500
Subject: [PATCH] Fix systemd version detection
Signed-off-by: Igor Gnatenko <ignatenkobrain@fedoraproject.org>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile.inc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile.inc b/Makefile.inc
index b98800a..da49852 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -37,7 +37,7 @@ endif
ifndef SYSTEMD
ifeq ($(shell systemctl --version > /dev/null 2>&1 && echo 1), 1)
- SYSTEMD = $(shell systemctl --version 2> /dev/null | sed -n 's/systemd \([0-9]*\)/\1/p')
+ SYSTEMD = $(shell systemctl --version 2> /dev/null | sed -n 's/systemd \([0-9]*\).*/\1/p')
endif
endif
--
2.17.2

View File

@ -0,0 +1,87 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 11 Apr 2019 13:25:42 -0500
Subject: [PATCH] RH: attempt to get ANA info via sysfs first
When the ANA prioritizer is run, first see if the "ana_state" sysfs file
exists, and if it does, try to read the state from there. If that fails,
fallback to using an ioctl.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/prioritizers/ana.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/libmultipath/prioritizers/ana.c b/libmultipath/prioritizers/ana.c
index 990d935..d84571b 100644
--- a/libmultipath/prioritizers/ana.c
+++ b/libmultipath/prioritizers/ana.c
@@ -24,6 +24,7 @@
#include "prio.h"
#include "util.h"
#include "structs.h"
+#include "sysfs.h"
enum {
ANA_ERR_GETCTRL_FAILED = 1,
@@ -36,6 +37,7 @@ enum {
ANA_ERR_GETNS_FAILED,
ANA_ERR_NO_MEMORY,
ANA_ERR_NO_INFORMATION,
+ ANA_ERR_INVALID_STATE,
};
static const char *ana_errmsg[] = {
@@ -49,6 +51,7 @@ static const char *ana_errmsg[] = {
[ANA_ERR_GETNS_FAILED] = "couldn't get namespace info",
[ANA_ERR_NO_MEMORY] = "out of memory",
[ANA_ERR_NO_INFORMATION] = "invalid fd",
+ [ANA_ERR_INVALID_STATE] = "invalid state",
};
static const char *anas_string[] = {
@@ -106,6 +109,27 @@ static int get_ana_state(__u32 nsid, __u32 anagrpid, void *ana_log,
return -ANA_ERR_GETANAS_NOTFOUND;
}
+int get_ana_info_sysfs(struct path *pp)
+{
+ char state[32];
+
+ if (!pp->udev || sysfs_attr_get_value(pp->udev, "ana_state", state,
+ sizeof(state)) <= 0)
+ return -ANA_ERR_NO_INFORMATION;
+
+ if (strcmp(state, "optimized") == 0)
+ return NVME_ANA_OPTIMIZED;
+ if (strcmp(state, "non-optimized") == 0)
+ return NVME_ANA_NONOPTIMIZED;
+ if (strcmp(state, "inaccessible") == 0)
+ return NVME_ANA_INACCESSIBLE;
+ if (strcmp(state, "persistent-loss") == 0)
+ return NVME_ANA_PERSISTENT_LOSS;
+ if (strcmp(state, "change") == 0)
+ return NVME_ANA_CHANGE;
+ return -ANA_ERR_INVALID_STATE;
+}
+
int get_ana_info(struct path * pp, unsigned int timeout)
{
int rc;
@@ -208,8 +232,11 @@ int getprio(struct path *pp, char *args, unsigned int timeout)
if (pp->fd < 0)
rc = -ANA_ERR_NO_INFORMATION;
- else
- rc = get_ana_info(pp, timeout);
+ else {
+ rc = get_ana_info_sysfs(pp);
+ if (rc < 0)
+ rc = get_ana_info(pp, timeout);
+ }
switch (rc) {
case NVME_ANA_OPTIMIZED:
--
2.17.2

View File

@ -0,0 +1,118 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 18 Apr 2019 12:49:46 -0500
Subject: [PATCH] BZ 1700451: check on multipathd without starting it
When "multipath -u" is run, it checks if multipathd is running.
Currently it does this by trying to connect to the mutipathd socket.
This can cause problems during boot. The multipathd.socket systemd unit
file will cause "multipath -u" to wait until multipathd has been started
before continuing. If there is a lot of activity on the system,
multipathd may not start up immediately, causing block device
initialization to be delayed, potentially until after systemd times
waiting for the device. To avoid this, multipath now checks if
multipathd is running by reading /run/multipathd.pid and checking the
/proc/<pid>/comm to verify that multipathd is really running with this
pid. This avoids forcing "multipath -u" to wait on multipathd starting
up.
As an alternative to this patch, multipath could simply switch the order
of the calls to systemd_service_enabled() and mpath_connect(). This would
make multipath only try to connect with multipathd if it wasn't enabled in
systemd, so that it wouldn't autostart.
Another alternative is to do away with multipathd.socket. Since multipathd
needs to always be running in order to get uevents, there isn't much value
in having it autoactivate when it gets an interactive command.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/main.c | 60 +++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 54 insertions(+), 6 deletions(-)
diff --git a/multipath/main.c b/multipath/main.c
index e7771c0..632ce4d 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -852,6 +852,58 @@ out:
return r;
}
+int is_multipathd_running(void)
+{
+ FILE *f = NULL;
+ char buf[16];
+ char path[PATH_MAX];
+ int pid;
+ char *end;
+
+ f = fopen(DEFAULT_PIDFILE, "r");
+ if (!f) {
+ if (errno != ENOENT)
+ condlog(4, "can't open " DEFAULT_PIDFILE ": %s",
+ strerror(errno));
+ return 0;
+ }
+ if (!fgets(buf, sizeof(buf), f)) {
+ if (ferror(f))
+ condlog(4, "read of " DEFAULT_PIDFILE " failed: %s",
+ strerror(errno));
+ fclose(f);
+ return 0;
+ }
+ fclose(f);
+ errno = 0;
+ strchop(buf);
+ pid = strtol(buf, &end, 10);
+ if (errno != 0 || pid <= 0 || *end != '\0') {
+ condlog(4, "invalid contents in " DEFAULT_PIDFILE ": '%s'",
+ buf);
+ return 0;
+ }
+ snprintf(path, sizeof(path), "/proc/%d/comm", pid);
+ f = fopen(path, "r");
+ if (!f) {
+ if (errno != ENOENT)
+ condlog(4, "can't open %s: %s", path, strerror(errno));
+ return 0;
+ }
+ if (!fgets(buf, sizeof(buf), f)) {
+ if (ferror(f))
+ condlog(4, "read of %s failed: %s", path,
+ strerror(errno));
+ fclose(f);
+ return 0;
+ }
+ fclose(f);
+ strchop(buf);
+ if (strcmp(buf, "multipathd") != 0)
+ return 0;
+ return 1;
+}
+
int
main (int argc, char *argv[])
{
@@ -1034,17 +1086,13 @@ main (int argc, char *argv[])
}
if (cmd == CMD_VALID_PATH &&
dev_type == DEV_UEVENT) {
- int fd;
-
- fd = mpath_connect();
- if (fd == -1) {
+ if (!is_multipathd_running()) {
condlog(3, "%s: daemon is not running", dev);
if (!systemd_service_enabled(dev)) {
r = print_cmd_valid(RTVL_NO, NULL, conf);
goto out;
}
- } else
- mpath_disconnect(fd);
+ }
}
if (cmd == CMD_REMOVE_WWID && !dev) {
--
2.17.2

View File

@ -0,0 +1,223 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Wed, 24 Apr 2019 11:07:59 +0200
Subject: [PATCH] BZ 1700451: test socket connection in non-blocking mode
Since commit d7188fcd "multipathd: start daemon after udev trigger",
multipathd startup is delayed during boot until after "udev settle"
terminates. But "multipath -u" is run by udev workers for storage devices,
and attempts to connect to the multipathd socket. This causes a start job
for multipathd to be scheduled by systemd, but that job won't be started
until "udev settle" finishes. This is not a problem on systems with 129 or
less storage units, because the connect() call of "multipath -u" will
succeed anyway. But on larger systems, the listen backlog of the systemd
socket can be exceeded, which causes connect() calls for the socket to
block until multipathd starts up and begins calling accept(). This creates
a deadlock situation, because "multipath -u" (called by udev workers)
blocks, and thus "udev settle" doesn't finish, delaying multipathd
startup. This situation then persists until either the workers or "udev
settle" time out. In the former case, path devices might be misclassified
as non-multipath devices by "multipath -u".
Fix this by using a non-blocking socket fd for connect() and interpret the
errno appropriately.
This patch reverts most of the changes from commit 8cdf6661 "multipath:
check on multipathd without starting it". Instead, "multipath -u" does
access the socket and start multipath again (which is what we want IMO),
but it is now able to detect and handle the "full backlog" situation.
Signed-off-by: Martin Wilck <mwilck@suse.com>
V2:
Use same error reporting convention in __mpath_connect() as in
mpath_connect() (Hannes Reinecke). We can't easily change the latter,
because it's part of the "public" libmpathcmd API.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmpathcmd/mpath_cmd.c | 24 +++++++++++++-
libmpathcmd/mpath_cmd.h | 15 +++++++++
multipath/main.c | 70 +++++++++++++----------------------------
3 files changed, 60 insertions(+), 49 deletions(-)
diff --git a/libmpathcmd/mpath_cmd.c b/libmpathcmd/mpath_cmd.c
index df4ca54..b681311 100644
--- a/libmpathcmd/mpath_cmd.c
+++ b/libmpathcmd/mpath_cmd.c
@@ -26,6 +26,7 @@
#include <poll.h>
#include <string.h>
#include <errno.h>
+#include <fcntl.h>
#include "mpath_cmd.h"
@@ -93,10 +94,11 @@ static size_t write_all(int fd, const void *buf, size_t len)
/*
* connect to a unix domain socket
*/
-int mpath_connect(void)
+int __mpath_connect(int nonblocking)
{
int fd, len;
struct sockaddr_un addr;
+ int flags = 0;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_LOCAL;
@@ -108,14 +110,34 @@ int mpath_connect(void)
if (fd == -1)
return -1;
+ if (nonblocking) {
+ flags = fcntl(fd, F_GETFL, 0);
+ if (flags != -1)
+ (void)fcntl(fd, F_SETFL, flags|O_NONBLOCK);
+ }
+
if (connect(fd, (struct sockaddr *)&addr, len) == -1) {
+ int err = errno;
+
close(fd);
+ errno = err;
return -1;
}
+ if (nonblocking && flags != -1)
+ (void)fcntl(fd, F_SETFL, flags);
+
return fd;
}
+/*
+ * connect to a unix domain socket
+ */
+int mpath_connect(void)
+{
+ return __mpath_connect(0);
+}
+
int mpath_disconnect(int fd)
{
return close(fd);
diff --git a/libmpathcmd/mpath_cmd.h b/libmpathcmd/mpath_cmd.h
index 15aeb06..ccfd35f 100644
--- a/libmpathcmd/mpath_cmd.h
+++ b/libmpathcmd/mpath_cmd.h
@@ -34,6 +34,21 @@ extern "C" {
#define DEFAULT_REPLY_TIMEOUT 4000
+/*
+ * DESCRIPTION:
+ * Same as mpath_connect() (see below) except for the "nonblocking"
+ * parameter.
+ * If "nonblocking" is set, connects in non-blocking mode. This is
+ * useful to avoid blocking if the listening socket's backlog is
+ * exceeded. In this case, errno will be set to EAGAIN.
+ * In case of success, the returned file descriptor is in in blocking
+ * mode, even if "nonblocking" was true.
+ *
+ * RETURNS:
+ * A file descriptor on success. -1 on failure (with errno set).
+ */
+int __mpath_connect(int nonblocking);
+
/*
* DESCRIPTION:
* Connect to the running multipathd daemon. On systems with the
diff --git a/multipath/main.c b/multipath/main.c
index 632ce4d..3fb6699 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -852,55 +852,29 @@ out:
return r;
}
-int is_multipathd_running(void)
+static int test_multipathd_socket(void)
{
- FILE *f = NULL;
- char buf[16];
- char path[PATH_MAX];
- int pid;
- char *end;
+ int fd;
+ /*
+ * "multipath -u" may be run before the daemon is started. In this
+ * case, systemd might own the socket but might delay multipathd
+ * startup until some other unit (udev settle!) has finished
+ * starting. With many LUNs, the listen backlog may be exceeded, which
+ * would cause connect() to block. This causes udev workers calling
+ * "multipath -u" to hang, and thus creates a deadlock, until "udev
+ * settle" times out. To avoid this, call connect() in non-blocking
+ * mode here, and take EAGAIN as indication for a filled-up systemd
+ * backlog.
+ */
- f = fopen(DEFAULT_PIDFILE, "r");
- if (!f) {
- if (errno != ENOENT)
- condlog(4, "can't open " DEFAULT_PIDFILE ": %s",
- strerror(errno));
- return 0;
- }
- if (!fgets(buf, sizeof(buf), f)) {
- if (ferror(f))
- condlog(4, "read of " DEFAULT_PIDFILE " failed: %s",
- strerror(errno));
- fclose(f);
- return 0;
- }
- fclose(f);
- errno = 0;
- strchop(buf);
- pid = strtol(buf, &end, 10);
- if (errno != 0 || pid <= 0 || *end != '\0') {
- condlog(4, "invalid contents in " DEFAULT_PIDFILE ": '%s'",
- buf);
- return 0;
- }
- snprintf(path, sizeof(path), "/proc/%d/comm", pid);
- f = fopen(path, "r");
- if (!f) {
- if (errno != ENOENT)
- condlog(4, "can't open %s: %s", path, strerror(errno));
- return 0;
- }
- if (!fgets(buf, sizeof(buf), f)) {
- if (ferror(f))
- condlog(4, "read of %s failed: %s", path,
- strerror(errno));
- fclose(f);
- return 0;
- }
- fclose(f);
- strchop(buf);
- if (strcmp(buf, "multipathd") != 0)
- return 0;
+ fd = __mpath_connect(1);
+ if (fd == -1) {
+ if (errno == EAGAIN)
+ condlog(3, "daemon backlog exceeded");
+ else
+ return 0;
+ } else
+ close(fd);
return 1;
}
@@ -1086,7 +1060,7 @@ main (int argc, char *argv[])
}
if (cmd == CMD_VALID_PATH &&
dev_type == DEV_UEVENT) {
- if (!is_multipathd_running()) {
+ if (!test_multipathd_socket()) {
condlog(3, "%s: daemon is not running", dev);
if (!systemd_service_enabled(dev)) {
r = print_cmd_valid(RTVL_NO, NULL, conf);
--
2.17.2

View File

@ -0,0 +1,61 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 16 May 2019 12:41:33 -0500
Subject: [PATCH] libmultipath: handle clock_gettime failures in tur checker
If clock_gettime() fails, and multipathd can't figure out when it should
time out, it should just default to assuming that it has already timed
out. Found by coverity.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/checkers/tur.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c
index 6b08dbb..717353e 100644
--- a/libmultipath/checkers/tur.c
+++ b/libmultipath/checkers/tur.c
@@ -290,7 +290,12 @@ static void *tur_thread(void *ctx)
static void tur_timeout(struct timespec *tsp)
{
- clock_gettime(CLOCK_MONOTONIC, tsp);
+ if (clock_gettime(CLOCK_MONOTONIC, tsp) != 0) {
+ /* can't get time. clear tsp to not wait */
+ tsp->tv_sec = 0;
+ tsp->tv_nsec = 0;
+ return;
+ }
tsp->tv_nsec += 1000 * 1000; /* 1 millisecond */
normalize_timespec(tsp);
}
@@ -300,8 +305,12 @@ static void tur_set_async_timeout(struct checker *c)
struct tur_checker_context *ct = c->context;
struct timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
- ct->time = now.tv_sec + c->timeout;
+ if (clock_gettime(CLOCK_MONOTONIC, &now) != 0)
+ /* can't get time. clear time to always timeout on
+ * next path check */
+ ct->time = 0;
+ else
+ ct->time = now.tv_sec + c->timeout;
}
static int tur_check_async_timeout(struct checker *c)
@@ -309,7 +318,9 @@ static int tur_check_async_timeout(struct checker *c)
struct tur_checker_context *ct = c->context;
struct timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
+ if (clock_gettime(CLOCK_MONOTONIC, &now) != 0)
+ /* can't get time. assume we've timed out */
+ return 1;
return (now.tv_sec > ct->time);
}
--
2.17.2

View File

@ -0,0 +1,30 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 16 May 2019 12:55:16 -0500
Subject: [PATCH] kpartx: fail if dup() of dasd file descriptor fails
If kpartx fails to create a copy of the dasd file descriptor, it should
fail, instead of treating the error value as a valid fd. Found by
coverity.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
kpartx/dasd.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/kpartx/dasd.c b/kpartx/dasd.c
index 61b609a..d95d8ca 100644
--- a/kpartx/dasd.c
+++ b/kpartx/dasd.c
@@ -138,6 +138,8 @@ read_dasd_pt(int fd, struct slice all, struct slice *sp, int ns)
return -1;
} else {
fd_dasd = dup(fd);
+ if (fd_dasd < 0)
+ return -1;
}
if (ioctl(fd_dasd, BIODASDINFO, (unsigned long)&info) != 0) {
--
2.17.2

View File

@ -0,0 +1,49 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 16 May 2019 13:31:35 -0500
Subject: [PATCH] multipathd: fix REALLOC_REPLY with max length reply
Commit cd5a9797e added code to REALLOC_REPLY() that intended to stop
growing the reply buffer after it reached a maximum size. However this
coded didn't stop the realloc() from happening. Worse, if the realloci()
failed, multipathd would double free the reply buffer. Found by
Coverity.
Fixes: cd5a9797e "libmpathcmd(coverity): limit reply length"
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/cli.h | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/multipathd/cli.h b/multipathd/cli.h
index f3fa077..32dcffa 100644
--- a/multipathd/cli.h
+++ b/multipathd/cli.h
@@ -100,15 +100,16 @@ enum {
if (m >= MAX_REPLY_LEN) { \
condlog(1, "Warning: max reply length exceeded"); \
free(tmp); \
- r = NULL; \
+ (r) = NULL; \
+ } else { \
+ (r) = REALLOC((r), (m) * 2); \
+ if ((r)) { \
+ memset((r) + (m), 0, (m)); \
+ (m) *= 2; \
+ } \
+ else \
+ free(tmp); \
} \
- (r) = REALLOC((r), (m) * 2); \
- if ((r)) { \
- memset((r) + (m), 0, (m)); \
- (m) *= 2; \
- } \
- else \
- free(tmp); \
} \
} while (0)
--
2.17.2

View File

@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 16 May 2019 15:44:20 -0500
Subject: [PATCH] multipathd: handle NULL return from genhelp_handler
If parse_cmd() wasn't checking if genhelp_handler() returned NULL. It
was simply assuming that it got a string. Instead, it should just return
and error. Found by Coverity.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/cli.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/multipathd/cli.c b/multipathd/cli.c
index ca176a9..17795b6 100644
--- a/multipathd/cli.c
+++ b/multipathd/cli.c
@@ -467,6 +467,8 @@ parse_cmd (char * cmd, char ** reply, int * len, void * data, int timeout )
if (r) {
*reply = genhelp_handler(cmd, r);
+ if (*reply == NULL)
+ return EINVAL;
*len = strlen(*reply) + 1;
return 0;
}
@@ -474,9 +476,11 @@ parse_cmd (char * cmd, char ** reply, int * len, void * data, int timeout )
h = find_handler(fingerprint(cmdvec));
if (!h || !h->fn) {
+ free_keys(cmdvec);
*reply = genhelp_handler(cmd, EINVAL);
+ if (*reply == NULL)
+ return EINVAL;
*len = strlen(*reply) + 1;
- free_keys(cmdvec);
return 0;
}
--
2.17.2

View File

@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Mon, 18 Mar 2019 12:24:45 +0100
Subject: [PATCH] BZ 1700911: hwtable: add Lenovo DE series
I got this from Steven.
Cc: Steve.Schremmer@netapp.com
Cc: NetApp RDAC team <ng-eseries-upstream-maintainers@netapp.com>
Cc: xose.vazquez@gmail.com
Signed-off-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/hwtable.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index 8776411..f13591d 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -701,6 +701,26 @@ static struct hwentry default_hw[] = {
.no_path_retry = (300 / DEFAULT_CHECKINT),
.prio_name = PRIO_ALUA,
},
+ /*
+ * Lenovo
+ */
+ {
+ /*
+ * DE Series
+ *
+ * Maintainer: ng-eseries-upstream-maintainers@netapp.com
+ */
+ .vendor = "LENOVO",
+ .product = "DE_Series",
+ .bl_product = "Universal Xport",
+ .pgpolicy = GROUP_BY_PRIO,
+ .checker_name = RDAC,
+ .features = "2 pg_init_retries 50",
+ .hwhandler = "1 rdac",
+ .prio_name = PRIO_RDAC,
+ .pgfailback = -FAILBACK_IMMEDIATE,
+ .no_path_retry = 30,
+ },
/*
* NetApp
*/
--
2.17.2

View File

@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 24 May 2019 17:30:07 -0500
Subject: [PATCH] libmultipath: make vector_foreach_slot_backwards work as
expected
All of the code that uses vector_foreach_slot_backwards() treats "i" as
the index of the entry "p", but the way it was coded, that wasn't the
case. "i" was the number of the entry counting from 1, not 0.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/vector.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/vector.h b/libmultipath/vector.h
index 41d2b89..344dffd 100644
--- a/libmultipath/vector.h
+++ b/libmultipath/vector.h
@@ -40,7 +40,7 @@ typedef struct _vector *vector;
#define vector_foreach_slot_after(v,p,i) \
for (; (v) && i < VECTOR_SIZE(v) && ((p) = (v)->slot[i]); i++)
#define vector_foreach_slot_backwards(v,p,i) \
- for (i = VECTOR_SIZE(v); i > 0 && ((p) = (v)->slot[i-1]); i--)
+ for (i = VECTOR_SIZE(v) - 1; (int)i >= 0 && ((p) = (v)->slot[i]); i--)
#define identity(x) (x)
/*
--
2.17.2

93
SOURCES/multipath.conf Normal file
View File

@ -0,0 +1,93 @@
# This is a basic configuration file with some examples, for device mapper
# multipath.
#
# For a complete list of the default configuration values, run either
# multipath -t
# or
# multipathd show config
#
# For a list of configuration options with descriptions, see the multipath.conf
# man page
## By default, devices with vendor = "IBM" and product = "S/390.*" are
## blacklisted. To enable mulitpathing on these devies, uncomment the
## following lines.
#blacklist_exceptions {
# device {
# vendor "IBM"
# product "S/390.*"
# }
#}
## Use user friendly names, instead of using WWIDs as names.
defaults {
user_friendly_names yes
find_multipaths yes
}
##
## Here is an example of how to configure some standard options.
##
#
#defaults {
# udev_dir /dev
# polling_interval 10
# selector "round-robin 0"
# path_grouping_policy multibus
# prio alua
# path_checker readsector0
# rr_min_io 100
# max_fds 8192
# rr_weight priorities
# failback immediate
# no_path_retry fail
# user_friendly_names yes
#}
##
## The wwid line in the following blacklist section is shown as an example
## of how to blacklist devices by wwid. The 2 devnode lines are the
## compiled in default blacklist. If you want to blacklist entire types
## of devices, such as all scsi devices, you should use a devnode line.
## However, if you want to blacklist specific devices, you should use
## a wwid line. Since there is no guarantee that a specific device will
## not change names on reboot (from /dev/sda to /dev/sdb for example)
## devnode lines are not recommended for blacklisting specific devices.
##
#blacklist {
# wwid 26353900f02796769
# devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
# devnode "^hd[a-z]"
#}
#multipaths {
# multipath {
# wwid 3600508b4000156d700012000000b0000
# alias yellow
# path_grouping_policy multibus
# path_checker readsector0
# path_selector "round-robin 0"
# failback manual
# rr_weight priorities
# no_path_retry 5
# }
# multipath {
# wwid 1DEC_____321816758474
# alias red
# }
#}
#devices {
# device {
# vendor "COMPAQ "
# product "HSV110 (C)COMPAQ"
# path_grouping_policy multibus
# path_checker readsector0
# path_selector "round-robin 0"
# hardware_handler "0"
# failback 15
# rr_weight priorities
# no_path_retry queue
# }
# device {
# vendor "COMPAQ "
# product "MSA1000 "
# path_grouping_policy multibus
# }
#}

File diff suppressed because it is too large Load Diff