Compare commits

..

1 commit

Author SHA1 Message Date
Benjamin Marzinski
25cca89fbe device-mapper-multipath-0.7.4-3.git07e7bd5
- Add 0023-libmutipath-remove-unused-IDE-bus-type.patch
- Add 0024-multipathd-add-new-protocol-path-wildcard.patch
  * multipathd show paths format now accepts %P for the path
    protocol/transport
- Add 0025-libmultipath-add-protocol-blacklist-option.patch
  * You can now use the "protocol" blacklist section parameter to
    blacklist by protocol/transport
2018-07-18 14:24:43 -05:00
67 changed files with 5403 additions and 4161 deletions

View file

@ -1 +0,0 @@
1

27
.gitignore vendored
View file

@ -8,30 +8,3 @@ multipath-tools-091027.tar.gz
/multipath-tools-git847cc43.tgz
/multipath-tools-0.7.3.tgz
/multipath-tools-07e7bd5.tgz
/multipath-tools-1cb704b.tgz
/multipath-tools-0.7.7.tgz
/multipath-tools-ef6d98b.tgz
/multipath-tools-1a8625a.tgz
/multipath-tools-b80318b.tgz
/multipath-tools-0.7.8.tgz
/multipath-tools-0.7.9.tgz
/multipath-tools-17a6101.tgz
/multipath-tools-2df6110.tgz
/multipath-tools-0.8.0.tgz
/multipath-tools-0.8.2.tgz
/multipath-tools-0.8.4.tgz
/multipath-tools-0.8.5.tgz
/multipath-tools-0.8.6.tgz
/multipath-tools-0.8.7.tgz
/multipath-tools-0.8.9.tgz
/multipath-tools-0.9.0.tgz
/multipath-tools-0.9.3.tgz
/multipath-tools-0.9.4.tgz
/multipath-tools-0.9.5.tgz
/multipath-tools-0.9.6.tgz
/multipath-tools-0.9.7.tgz
/multipath-tools-0.9.8.tgz
/multipath-tools-0.9.9.tgz
/multipath-tools-0.10.0.tgz
/multipath-tools-0.11.1.tgz
/multipath-tools-0.13.0.tgz

View file

@ -1,63 +0,0 @@
From 64a07df23affd21842fdc604887276e62e5b41de 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.in | 2 +-
multipath/Makefile | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 9e3dc466..ead89030 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -34,7 +34,7 @@ endif
# Paths. All these can be overridden on the "make" command line.
prefix :=
# Prefix for binaries
-exec_prefix := $(prefix)
+exec_prefix := $(prefix)/usr
# Prefix for non-essential libraries (libdmmp)
usr_prefix := $(if $(prefix),$(prefix),/usr)
# Prefix for configuration files (multipath.conf)
diff --git a/kpartx/kpartx.rules.in b/kpartx/kpartx.rules.in
index 9d879609..2049eb8f 100644
--- a/kpartx/kpartx.rules.in
+++ b/kpartx/kpartx.rules.in
@@ -39,6 +39,6 @@ LABEL="mpath_kpartx_end"
GOTO="kpartx_end"
LABEL="run_kpartx"
-RUN+="@BINDIR@/kpartx -un -p -part /dev/$name"
+RUN+="@BINDIR@/kpartx -un /dev/$name"
LABEL="kpartx_end"
diff --git a/multipath/Makefile b/multipath/Makefile
index 67fb5e62..2ea9e528 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -27,7 +27,7 @@ install:
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 99-z-dm-mpath-late.rules $(DESTDIR)$(udevrulesdir)
- $(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/56-multipath.rules
+ $(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(tmpfilesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 tmpfiles.conf $(DESTDIR)$(tmpfilesdir)/multipath.conf
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man8
@@ -50,7 +50,7 @@ uninstall:
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/99-z-dm-mpath-late.rules
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/scsi_dh.conf
- $(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
+ $(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
$(Q)$(RM) $(DESTDIR)$(mandir)/man8/$(EXEC).8
$(Q)$(RM) $(DESTDIR)$(mandir)/man5/$(EXEC).conf.5
$(Q)$(RM) $(DESTDIR)$(tmpfilesdir)/multipath.conf

View file

@ -0,0 +1,269 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 8 Feb 2018 16:56:45 -0600
Subject: [PATCH] libmultipath: fix tur checker locking
Commit 6e2423fd fixed a bug where the tur checker could cancel a
detached thread after it had exitted. However in fixing this, the new
code grabbed a mutex (to call condlog) while holding a spin_lock. To
deal with this, I've done away with the holder spin_lock completely, and
replaced it with two atomic variables, based on a suggestion by Martin
Wilck.
The holder variable works exactly like before. When the checker is
initialized, it is set to 1. When a thread is created it is incremented.
When either the thread or the checker are done with the context, they
atomically decrement the holder variable and check its value. If it
is 0, they free the context. If it is 1, they never touch the context
again.
The other variable has changed. First, ct->running and ct->thread have
switched uses. ct->thread is now only ever accessed by the checker,
never the thread. If it is non-NULL, a thread has started up, but
hasn't been dealt with by the checker yet. It is also obviously used
by the checker to cancel the thread.
ct->running is now an atomic variable. When the thread is started
it is set to 1. When the checker wants to kill a thread, it atomically
sets the value to 0 and reads the previous value. If it was 1,
the checker cancels the thread. If it was 0, the nothing needs to be
done. After the checker has dealt with the thread, it sets ct->thread
to NULL.
Right before the thread finishes and pops the cleanup handler, it
atomically sets the value of ct->running to 0 and reads the previous
value. If it was 1, the thread just pops the cleanup handler and exits.
If it was 0, then the checker is trying to cancel the thread, and so the
thread calls pause(), which is a cancellation point.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/checkers/tur.c | 107 ++++++++++++++++++--------------------------
1 file changed, 43 insertions(+), 64 deletions(-)
diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c
index b4a5cb2..9155960 100644
--- a/libmultipath/checkers/tur.c
+++ b/libmultipath/checkers/tur.c
@@ -15,6 +15,7 @@
#include <errno.h>
#include <sys/time.h>
#include <pthread.h>
+#include <urcu/uatomic.h>
#include "checkers.h"
@@ -44,7 +45,6 @@ struct tur_checker_context {
pthread_t thread;
pthread_mutex_t lock;
pthread_cond_t active;
- pthread_spinlock_t hldr_lock;
int holders;
char message[CHECKER_MSG_LEN];
};
@@ -74,13 +74,12 @@ int libcheck_init (struct checker * c)
ct->state = PATH_UNCHECKED;
ct->fd = -1;
- ct->holders = 1;
+ uatomic_set(&ct->holders, 1);
pthread_cond_init_mono(&ct->active);
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&ct->lock, &attr);
pthread_mutexattr_destroy(&attr);
- pthread_spin_init(&ct->hldr_lock, PTHREAD_PROCESS_PRIVATE);
c->context = ct;
return 0;
@@ -90,7 +89,6 @@ static void cleanup_context(struct tur_checker_context *ct)
{
pthread_mutex_destroy(&ct->lock);
pthread_cond_destroy(&ct->active);
- pthread_spin_destroy(&ct->hldr_lock);
free(ct);
}
@@ -99,16 +97,14 @@ void libcheck_free (struct checker * c)
if (c->context) {
struct tur_checker_context *ct = c->context;
int holders;
- pthread_t thread;
-
- pthread_spin_lock(&ct->hldr_lock);
- ct->holders--;
- holders = ct->holders;
- thread = ct->thread;
- pthread_spin_unlock(&ct->hldr_lock);
- if (holders)
- pthread_cancel(thread);
- else
+ int running;
+
+ running = uatomic_xchg(&ct->running, 0);
+ if (running)
+ pthread_cancel(ct->thread);
+ ct->thread = 0;
+ holders = uatomic_sub_return(&ct->holders, 1);
+ if (!holders)
cleanup_context(ct);
c->context = NULL;
}
@@ -220,26 +216,12 @@ static void cleanup_func(void *data)
{
int holders;
struct tur_checker_context *ct = data;
- pthread_spin_lock(&ct->hldr_lock);
- ct->holders--;
- holders = ct->holders;
- ct->thread = 0;
- pthread_spin_unlock(&ct->hldr_lock);
+
+ holders = uatomic_sub_return(&ct->holders, 1);
if (!holders)
cleanup_context(ct);
}
-static int tur_running(struct tur_checker_context *ct)
-{
- pthread_t thread;
-
- pthread_spin_lock(&ct->hldr_lock);
- thread = ct->thread;
- pthread_spin_unlock(&ct->hldr_lock);
-
- return thread != 0;
-}
-
static void copy_msg_to_tcc(void *ct_p, const char *msg)
{
struct tur_checker_context *ct = ct_p;
@@ -252,7 +234,7 @@ static void copy_msg_to_tcc(void *ct_p, const char *msg)
static void *tur_thread(void *ctx)
{
struct tur_checker_context *ct = ctx;
- int state;
+ int state, running;
char devt[32];
condlog(3, "%s: tur checker starting up",
@@ -278,6 +260,11 @@ static void *tur_thread(void *ctx)
condlog(3, "%s: tur checker finished, state %s",
tur_devt(devt, sizeof(devt), ct), checker_state_name(state));
+
+ running = uatomic_xchg(&ct->running, 0);
+ if (!running)
+ pause();
+
tur_thread_cleanup_pop(ct);
return ((void *)0);
@@ -325,7 +312,6 @@ int libcheck_check(struct checker * c)
int tur_status, r;
char devt[32];
-
if (!ct)
return PATH_UNCHECKED;
@@ -349,38 +335,29 @@ int libcheck_check(struct checker * c)
return PATH_WILD;
}
- if (ct->running) {
- /*
- * Check if TUR checker is still running. Hold hldr_lock
- * around the pthread_cancel() call to avoid that
- * pthread_cancel() gets called after the (detached) TUR
- * thread has exited.
- */
- pthread_spin_lock(&ct->hldr_lock);
- if (ct->thread) {
- if (tur_check_async_timeout(c)) {
- condlog(3, "%s: tur checker timeout",
- tur_devt(devt, sizeof(devt), ct));
+ if (ct->thread) {
+ if (tur_check_async_timeout(c)) {
+ int running = uatomic_xchg(&ct->running, 0);
+ if (running)
pthread_cancel(ct->thread);
- ct->running = 0;
- MSG(c, MSG_TUR_TIMEOUT);
- tur_status = PATH_TIMEOUT;
- } else {
- condlog(3, "%s: tur checker not finished",
+ condlog(3, "%s: tur checker timeout",
+ tur_devt(devt, sizeof(devt), ct));
+ ct->thread = 0;
+ MSG(c, MSG_TUR_TIMEOUT);
+ tur_status = PATH_TIMEOUT;
+ } else if (uatomic_read(&ct->running) != 0) {
+ condlog(3, "%s: tur checker not finished",
tur_devt(devt, sizeof(devt), ct));
- ct->running++;
- tur_status = PATH_PENDING;
- }
+ tur_status = PATH_PENDING;
} else {
/* TUR checker done */
- ct->running = 0;
+ ct->thread = 0;
tur_status = ct->state;
strlcpy(c->message, ct->message, sizeof(c->message));
}
- pthread_spin_unlock(&ct->hldr_lock);
pthread_mutex_unlock(&ct->lock);
} else {
- if (tur_running(ct)) {
+ if (uatomic_read(&ct->running) != 0) {
/* pthread cancel failed. continue in sync mode */
pthread_mutex_unlock(&ct->lock);
condlog(3, "%s: tur thread not responding",
@@ -391,19 +368,17 @@ int libcheck_check(struct checker * c)
ct->state = PATH_UNCHECKED;
ct->fd = c->fd;
ct->timeout = c->timeout;
- pthread_spin_lock(&ct->hldr_lock);
- ct->holders++;
- pthread_spin_unlock(&ct->hldr_lock);
+ uatomic_add(&ct->holders, 1);
+ uatomic_set(&ct->running, 1);
tur_set_async_timeout(c);
setup_thread_attr(&attr, 32 * 1024, 1);
r = pthread_create(&ct->thread, &attr, tur_thread, ct);
pthread_attr_destroy(&attr);
if (r) {
- pthread_spin_lock(&ct->hldr_lock);
- ct->holders--;
- pthread_spin_unlock(&ct->hldr_lock);
- pthread_mutex_unlock(&ct->lock);
+ uatomic_sub(&ct->holders, 1);
+ uatomic_set(&ct->running, 0);
ct->thread = 0;
+ pthread_mutex_unlock(&ct->lock);
condlog(3, "%s: failed to start tur thread, using"
" sync mode", tur_devt(devt, sizeof(devt), ct));
return tur_check(c->fd, c->timeout,
@@ -414,12 +389,16 @@ int libcheck_check(struct checker * c)
tur_status = ct->state;
strlcpy(c->message, ct->message, sizeof(c->message));
pthread_mutex_unlock(&ct->lock);
- if (tur_running(ct) &&
+ if (uatomic_read(&ct->running) != 0 &&
(tur_status == PATH_PENDING || tur_status == PATH_UNCHECKED)) {
condlog(3, "%s: tur checker still running",
tur_devt(devt, sizeof(devt), ct));
- ct->running = 1;
tur_status = PATH_PENDING;
+ } else {
+ int running = uatomic_xchg(&ct->running, 0);
+ if (running)
+ pthread_cancel(ct->thread);
+ ct->thread = 0;
}
}
--
2.7.4

View file

@ -1,100 +0,0 @@
From f7be16ac9fce97585a4552d49f3d3c54a93c9c17 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 | 5 ++---
multipath/multipath.conf.5.in | 11 ++++++-----
tests/blacklist.c | 7 ++-----
3 files changed, 10 insertions(+), 13 deletions(-)
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
index 17e1b54a..10d13e98 100644
--- a/libmultipath/blacklist.c
+++ b/libmultipath/blacklist.c
@@ -230,8 +230,6 @@ setup_default_blist (struct config * conf)
ORIGIN_DEFAULT))
return 1;
}
- if (store_ble(conf->elist_property, "(SCSI_IDENT_|ID_WWN)", ORIGIN_DEFAULT))
- return 1;
vector_foreach_slot (conf->hwtable, hwe, i) {
if (hwe->bl_product) {
@@ -438,7 +436,8 @@ filter_property(const struct config *conf, struct udev_device *udev,
*uid_attribute != '\0';
bool uid_attr_seen = false;
- 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.in b/multipath/multipath.conf.5.in
index 3c9ae097..ba291e11 100644
--- a/multipath/multipath.conf.5.in
+++ b/multipath/multipath.conf.5.in
@@ -1470,9 +1470,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.
+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.
.
.RS
.PP
@@ -1483,10 +1488,6 @@ Blacklisting by missing properties is only applied to devices which do have the
property specified by \fIuid_attribute\fR (e.g. \fIID_SERIAL\fR)
set. Previously, it was applied to every device, possibly causing devices to be
blacklisted because of temporary I/O error conditions.
-.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
.TP
.B protocol
diff --git a/tests/blacklist.c b/tests/blacklist.c
index ab3da619..52ae03e0 100644
--- a/tests/blacklist.c
+++ b/tests/blacklist.c
@@ -371,9 +371,8 @@ static void test_property_missing(void **state)
{
static struct udev_device udev = { "sdb", { "ID_FOO", "ID_BAZ", "ID_BAR", "ID_SERIAL", NULL } };
conf.blist_property = blist_property_wwn;
- expect_condlog(3, "sdb: blacklisted, udev property missing\n");
assert_int_equal(filter_property(&conf, &udev, 3, "ID_SERIAL"),
- MATCH_PROPERTY_BLIST_MISSING);
+ MATCH_NOTHING);
assert_int_equal(filter_property(&conf, &udev, 3, "ID_BLAH"),
MATCH_NOTHING);
assert_int_equal(filter_property(&conf, &udev, 3, ""),
@@ -465,9 +464,7 @@ static void test_filter_path_missing1(void **state)
conf.blist_device = blist_device_foo_bar;
conf.blist_protocol = blist_protocol_fcp;
conf.blist_wwid = blist_wwid_xyzzy;
- expect_condlog(3, "sdb: blacklisted, udev property missing\n");
- assert_int_equal(filter_path(&conf, &miss1_pp),
- MATCH_PROPERTY_BLIST_MISSING);
+ assert_int_equal(filter_path(&conf, &miss1_pp), MATCH_NOTHING);
}
/* This one matches the property whitelist, to test the other missing

View file

@ -0,0 +1,32 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 18 Jan 2018 13:13:54 -0600
Subject: [PATCH] multipath: fix DEF_TIMEOUT use
DEF_TIMEOUT is specified in seconds. The io_hdr timeout is specified in
milliseconds, so we need to convert it. Multipath should be waiting
longer than 30 milliseconds here. If there are concerns that 30 seconds
may be too long, we could always make this configurable, using
conf->checker_timeout if set.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/discovery.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index 4b31dde..f118800 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -766,7 +766,7 @@ do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op,
io_hdr.dxferp = resp;
io_hdr.cmdp = inqCmdBlk;
io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_TIMEOUT;
+ io_hdr.timeout = DEF_TIMEOUT * 1000;
if (ioctl(sg_fd, SG_IO, &io_hdr) < 0)
return -1;
--
2.7.4

View file

@ -1,137 +0,0 @@
From 5613e07ce9cabf2fdc402f6f102cc54bd1059800 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 | 13 +++++++++++++
libmultipath/config.h | 1 +
multipath/main.c | 6 ++++++
multipath/multipath.rules.in | 1 +
multipathd/multipathd.8.in | 2 ++
multipathd/multipathd.service.in | 1 +
multipathd/multipathd.socket.in | 1 +
7 files changed, 25 insertions(+)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 8b424d18..b8317f4d 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -937,6 +937,19 @@ int init_config__ (const char *file, struct config *conf)
}
factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
validate_pctable(conf->overrides, 0, 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, ".*", 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 5b4ebf8c..2302eacc 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -10,6 +10,7 @@
#define ORIGIN_DEFAULT 0
#define ORIGIN_CONFIG 1
+#define ORIGIN_NO_CONFIG 2
enum devtypes {
DEV_NONE,
diff --git a/multipath/main.c b/multipath/main.c
index f2adcdeb..31012874 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -834,11 +834,14 @@ main (int argc, char *argv[])
char *dev = NULL;
struct config *conf;
bool enable_foreign = false;
+ bool have_config;
+ struct stat buf;
libmultipath_init();
if (atexit(dm_lib_exit) || atexit(libmultipath_exit))
condlog(1, "failed to register cleanup handler for libmultipath: %m");
logsink = LOGSINK_STDERR_WITH_TIME;
+ have_config = (stat(DEFAULT_CONFIGFILE, &buf) == 0);
if (init_config(DEFAULT_CONFIGFILE))
exit(RTVL_FAIL);
if (atexit(uninit_config))
@@ -1092,6 +1095,9 @@ main (int argc, char *argv[])
while ((r = configure(conf, cmd, dev_type, dev)) == RTVL_RETRY)
condlog(3, "restart multipath configuration process");
+ if (!have_config && r == RTVL_OK &&
+ (cmd == CMD_LIST_SHORT || cmd == CMD_LIST_LONG))
+ r = RTVL_FAIL;
out:
put_multipath_config(conf);
if (dev)
diff --git a/multipath/multipath.rules.in b/multipath/multipath.rules.in
index 2ac1972f..cc248231 100644
--- a/multipath/multipath.rules.in
+++ b/multipath/multipath.rules.in
@@ -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.in b/multipathd/multipathd.8.in
index 8815e099..342e363e 100644
--- a/multipathd/multipathd.8.in
+++ b/multipathd/multipathd.8.in
@@ -49,6 +49,8 @@ map regains its maximum performance and redundancy.
With the \fB-k\fR option, \fBmultipathd\fR acts as a client utility that
sends commands to a running instance of the multipathd daemon (see
\fBCOMMANDS\fR below).
+
+In this Linux distribution, multipathd does not run unless a /etc/multipath.conf file exists.
.
.
.\" ----------------------------------------------------------------------------
diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in
index eb58943c..ab166435 100644
--- a/multipathd/multipathd.service.in
+++ b/multipathd/multipathd.service.in
@@ -6,6 +6,7 @@ Wants=systemd-udevd-kernel.socket multipathd-queueing.service @MODPROBE_UNIT@
After=systemd-udevd-kernel.socket @MODPROBE_UNIT@
After=multipathd.socket systemd-remount-fs.service
Before=initrd-cleanup.service
+ConditionPathExists=/etc/multipath.conf
DefaultDependencies=no
Conflicts=shutdown.target
Conflicts=initrd-cleanup.service
diff --git a/multipathd/multipathd.socket.in b/multipathd/multipathd.socket.in
index 11002fce..5ed24757 100644
--- a/multipathd/multipathd.socket.in
+++ b/multipathd/multipathd.socket.in
@@ -1,6 +1,7 @@
[Unit]
Description=multipathd control socket
DefaultDependencies=no
+ConditionPathExists=/etc/multipath.conf
ConditionKernelCommandLine=!nompath
ConditionKernelCommandLine=!multipath=off
ConditionVirtualization=!container

View file

@ -0,0 +1,98 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 19 Jan 2018 22:35:26 -0600
Subject: [PATCH] multipathd: remove coalesce_paths from ev_add_map
If ev_add_map is called for a multipath device that doesn't exist in
device-mapper, it will call coalesce_paths to add it. This doesn't work
and hasn't for years. It doesn't add the map to the mpvec, or start up
waiters, or do any of the necessary things that do get done when you
call ev_add_map for a map that does exist in device mapper.
Fortunately, there are only two things that call ev_add_map. uev_add_map
makes sure that the device does exist in device-mapper before calling
ev_add_map, and cli_add_map creates the device first and then calls
ev_add_map, if the device doesn't exist.
So, there is no reason for coalesce_paths to be in ev_add_map. This
removes it.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/main.c | 46 ++++++++++++++--------------------------------
1 file changed, 14 insertions(+), 32 deletions(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index 27cf234..dbf9890 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -412,18 +412,19 @@ uev_add_map (struct uevent * uev, struct vectors * vecs)
return rc;
}
+/*
+ * ev_add_map expects that the multipath device already exists in kernel
+ * before it is called. It just adds a device to multipathd or updates an
+ * existing device.
+ */
int
ev_add_map (char * dev, char * alias, struct vectors * vecs)
{
- char * refwwid;
struct multipath * mpp;
- int map_present;
- int r = 1, delayed_reconfig, reassign_maps;
+ int delayed_reconfig, reassign_maps;
struct config *conf;
- map_present = dm_map_present(alias);
-
- if (map_present && !dm_is_mpath(alias)) {
+ if (!dm_is_mpath(alias)) {
condlog(4, "%s: not a multipath map", alias);
return 0;
}
@@ -468,33 +469,14 @@ ev_add_map (char * dev, char * alias, struct vectors * vecs)
/*
* now we can register the map
*/
- if (map_present) {
- if ((mpp = add_map_without_path(vecs, alias))) {
- sync_map_state(mpp);
- condlog(2, "%s: devmap %s registered", alias, dev);
- return 0;
- } else {
- condlog(2, "%s: uev_add_map failed", dev);
- return 1;
- }
- }
- r = get_refwwid(CMD_NONE, dev, DEV_DEVMAP, vecs->pathvec, &refwwid);
-
- if (refwwid) {
- r = coalesce_paths(vecs, NULL, refwwid, FORCE_RELOAD_NONE,
- CMD_NONE);
- dm_lib_release();
+ if ((mpp = add_map_without_path(vecs, alias))) {
+ sync_map_state(mpp);
+ condlog(2, "%s: devmap %s registered", alias, dev);
+ return 0;
+ } else {
+ condlog(2, "%s: ev_add_map failed", dev);
+ return 1;
}
-
- if (!r)
- condlog(2, "%s: devmap %s added", alias, dev);
- else if (r == 2)
- condlog(2, "%s: uev_add_map %s blacklisted", alias, dev);
- else
- condlog(0, "%s: uev_add_map %s failed", alias, dev);
-
- FREE(refwwid);
- return r;
}
static int
--
2.7.4

View file

@ -1,26 +0,0 @@
From 283b5dd645663a2cf16f2813581772d7a84db6ad 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 function missing argument
A future patch will change the compilation options to error when
function declarations have unspecified arguments.
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 b3caa7be..f91504c9 100644
--- a/libmultipath/nvme/argconfig.h
+++ b/libmultipath/nvme/argconfig.h
@@ -63,7 +63,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);

View file

@ -0,0 +1,53 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 2 Feb 2018 15:04:01 -0600
Subject: [PATCH] multipathd: remove unused configure parameter
configure() is always called with start_waiters=1, so there is no point
in having the parameter. Remove it.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/main.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index dbf9890..51e0f5e 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1955,7 +1955,7 @@ checkerloop (void *ap)
}
int
-configure (struct vectors * vecs, int start_waiters)
+configure (struct vectors * vecs)
{
struct multipath * mpp;
struct path * pp;
@@ -2054,11 +2054,9 @@ configure (struct vectors * vecs, int start_waiters)
i--;
continue;
}
- if (start_waiters) {
- if (start_waiter_thread(mpp, vecs)) {
- remove_map(mpp, vecs, 1);
- i--;
- }
+ if (start_waiter_thread(mpp, vecs)) {
+ remove_map(mpp, vecs, 1);
+ i--;
}
}
return 0;
@@ -2125,7 +2123,7 @@ reconfigure (struct vectors * vecs)
rcu_assign_pointer(multipath_conf, conf);
call_rcu(&old->rcu, rcu_free_config);
- configure(vecs, 1);
+ configure(vecs);
return 0;
--
2.7.4

View file

@ -0,0 +1,81 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 6 Feb 2018 20:53:17 -0600
Subject: [PATCH] Fix set_no_path_retry() regression
commit 0f850db7fceb6b2bf4968f3831efd250c17c6138 "multipathd: clean up
set_no_path_retry" has a bug in it. It made set_no_path_retry
never reset mpp->retry_ticks, even if the device was in recovery mode,
and there were valid paths. This meant that adding new paths didn't
remove a device from recovery mode, and queueing could get disabled,
even while there were valid paths. This patch fixes that.
This patch also fixes a bug in cli_restore_queueing() and
cli_restore_all_queueing(), where a device that had no_path_retry
set to "queue" would enter recovery mode (although queueing would
never actually get disabled).
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/structs_vec.c | 5 +++--
multipathd/cli_handlers.c | 20 ++++++++++++--------
2 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index fbab61f..0de2221 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -343,9 +343,10 @@ static void set_no_path_retry(struct multipath *mpp)
dm_queue_if_no_path(mpp->alias, 1);
break;
default:
- if (mpp->nr_active > 0)
+ if (mpp->nr_active > 0) {
+ mpp->retry_tick = 0;
dm_queue_if_no_path(mpp->alias, 1);
- else if (is_queueing && mpp->retry_tick == 0)
+ } else if (is_queueing && mpp->retry_tick == 0)
enter_recovery_mode(mpp);
break;
}
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index 7f13bc9..80519b1 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -995,10 +995,12 @@ cli_restore_queueing(void *v, char **reply, int *len, void *data)
if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
mpp->no_path_retry != NO_PATH_RETRY_FAIL) {
dm_queue_if_no_path(mpp->alias, 1);
- if (mpp->nr_active > 0)
- mpp->retry_tick = 0;
- else
- enter_recovery_mode(mpp);
+ if (mpp->no_path_retry > 0) {
+ if (mpp->nr_active > 0)
+ mpp->retry_tick = 0;
+ else
+ enter_recovery_mode(mpp);
+ }
}
return 0;
}
@@ -1019,10 +1021,12 @@ cli_restore_all_queueing(void *v, char **reply, int *len, void *data)
if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
mpp->no_path_retry != NO_PATH_RETRY_FAIL) {
dm_queue_if_no_path(mpp->alias, 1);
- if (mpp->nr_active > 0)
- mpp->retry_tick = 0;
- else
- enter_recovery_mode(mpp);
+ if (mpp->no_path_retry > 0) {
+ if (mpp->nr_active > 0)
+ mpp->retry_tick = 0;
+ else
+ enter_recovery_mode(mpp);
+ }
}
}
return 0;
--
2.7.4

View file

@ -1,67 +0,0 @@
From bf46f8029998498045bb055415ba3ff515c79eaa 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 | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index ead89030..03aee175 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -102,17 +102,29 @@ SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo
MODPROBE_UNIT := $(shell test "0$(SYSTEMD)" -lt 245 2>/dev/null || \
echo "modprobe@dm_multipath.service")
-OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4
+ifndef RPM_OPT_FLAGS
+ OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4 \
+ -Wall $(FORTIFY_OPT) -fexceptions -grecord-gcc-switches \
+ -fasynchronous-unwind-tables
+ ifeq ($(shell test -f /usr/lib/rpm/redhat/redhat-hardened-cc1 && echo 1),1)
+ OPTFLAGS += -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1
+ endif
+ ifeq ($(shell test -f /usr/lib/rpm/redhat/redhat-annobin-cc1 && echo 1),1)
+ OPTFLAGS += -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1
+ endif
+else
+ OPTFLAGS := $(RPM_OPT_FLAGS) --param=ssp-buffer-size=4
+endif
# Set WARN_ONLY=1 to avoid compilation erroring out due to warnings. Useful during development.
WARN_ONLY :=
ERROR := $(if $(WARN_ONLY),,error=)
WERROR := $(if $(WARN_ONLY),,-Werror)
-WARNFLAGS := $(WERROR) -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -W$(ERROR)implicit-int \
+WARNFLAGS := $(WERROR) -Wextra -Wformat=2 $(WFORMATOVERFLOW) -W$(ERROR)implicit-int \
-W$(ERROR)implicit-function-declaration -W$(ERROR)format-security \
- $(WNOCLOBBERED) -W$(ERROR)cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS)
+ $(WNOCLOBBERED) -W$(ERROR)cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) -Wstrict-prototypes
-CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \
+CPPFLAGS := $(CPPFLAGS) $(D_URCU_VERSION) \
-D_FILE_OFFSET_BITS=64 \
-DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(TGTDIR)$(plugindir)\" \
-DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(TGTDIR)$(configdir)\" \
@@ -121,12 +133,11 @@ CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \
-DABSTRACT_SOCKET=\"$(abstract_socket)\" -DPATHNAME_SOCKET=\"$(pathname_socket)\" \
-DWSTRINGOP_TRUNCATION=$(if $(WSTRINGOP_TRUNCATION),1,0) \
-MMD -MP
-CFLAGS := -std=$(C_STD) $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \
- -fexceptions
+CFLAGS := -std=$(C_STD) $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe
BIN_CFLAGS := -fPIE -DPIE
LIB_CFLAGS := -fPIC
SHARED_FLAGS := -shared
-LDFLAGS := $(LDFLAGS) -Wl,-z,relro -Wl,-z,now -Wl,-z,defs
+LDFLAGS := $(LDFLAGS) $(RPM_LD_FLAGS) -Wl,-z,relro -Wl,-z,now -Wl,-z,defs
BIN_LDFLAGS := -pie
# Source code directories. Don't modify.

View file

@ -1,917 +0,0 @@
From 29e5c6d6e2177e73d1be2ed2af66c1007487bf60 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.
Co-authored-by: Paul Donohue <git@PaulSD.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
.github/actions/spelling/expect.txt | 3 +
libmultipath/config.c | 2 +
multipath/Makefile | 4 +
multipath/mpathconf | 658 ++++++++++++++++++++++++++++
multipath/mpathconf.8 | 151 +++++++
5 files changed, 818 insertions(+)
create mode 100644 multipath/mpathconf
create mode 100644 multipath/mpathconf.8
diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt
index a5856bcc..5c9113ba 100644
--- a/.github/actions/spelling/expect.txt
+++ b/.github/actions/spelling/expect.txt
@@ -131,9 +131,11 @@ Marzinski
misdetection
mpath
mpathb
+mpathconf
mpathpersist
mpathvalid
msecs
+multipathable
multipathc
multipathd
multipathed
@@ -154,6 +156,7 @@ ontap
OOM
opensvc
OPTFLAGS
+outfile
paramp
partx
pathgroup
diff --git a/libmultipath/config.c b/libmultipath/config.c
index b8317f4d..0bbaa981 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -939,6 +939,8 @@ int init_config__ (const char *file, struct config *conf)
validate_pctable(conf->overrides, 0, 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 2ea9e528..3dc241cc 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -24,6 +24,7 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
install:
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
$(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
+ $(Q)$(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 99-z-dm-mpath-late.rules $(DESTDIR)$(udevrulesdir)
@@ -32,6 +33,7 @@ install:
$(Q)$(INSTALL_PROGRAM) -m 644 tmpfiles.conf $(DESTDIR)$(tmpfilesdir)/multipath.conf
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man8
$(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)/man8
+ $(Q)$(INSTALL_PROGRAM) -m 644 mpathconf.8 $(DESTDIR)$(mandir)/man8
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man5
$(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5 $(DESTDIR)$(mandir)/man5
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(modulesloaddir)
@@ -46,12 +48,14 @@ endif
uninstall:
$(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC)
+ $(Q)$(RM) $(DESTDIR)$(bindir)/mpathconf
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/99-z-dm-mpath-late.rules
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/scsi_dh.conf
$(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
$(Q)$(RM) $(DESTDIR)$(mandir)/man8/$(EXEC).8
+ $(Q)$(RM) $(DESTDIR)$(mandir)/man8/mpathconf.8
$(Q)$(RM) $(DESTDIR)$(mandir)/man5/$(EXEC).conf.5
$(Q)$(RM) $(DESTDIR)$(tmpfilesdir)/multipath.conf
diff --git a/multipath/mpathconf b/multipath/mpathconf
new file mode 100644
index 00000000..ce430075
--- /dev/null
+++ b/multipath/mpathconf
@@ -0,0 +1,658 @@
+#!/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 PROPERTY FOREIGN MODULE MULTIPATHD HAVE_DISABLE HAVE_WWID_DISABLE HAVE_FIND HAVE_BLACKLIST HAVE_EXCEPTIONS HAVE_DEFAULTS HAVE_FRIENDLY HAVE_PROPERTY HAVE_FOREIGN HAVE_MULTIPATHD HAVE_MODULE HAVE_OUTFILE SHOW_STATUS CHANGED_CONFIG WWID_LIST HAVE_OPTION OPTION_NAME OPTION_VALUE HAVE_RECHECK_WWID RECHECK_WWID
+
+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 on
+}"
+
+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 on): --find_multipaths <on|yes|y|off|no|n|strict|greedy|smart>"
+ echo "Set default property blacklist (Default n): --property_blacklist <y|n>"
+ echo "Set enable_foreign to show foreign devices (Default n): --enable_foreign <y|n>"
+ echo "Set recheck_wwid (Defaut n): --recheck_wwid <y|n>"
+ echo "Add/Change/Remove option in defaults section: --option <option_name>:<value>"
+ 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
+ ;;
+ --recheck_wwid)
+ if [ -n "$2" ]; then
+ RECHECK_WWID=$2
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ --find_multipaths)
+ if [ -n "$2" ]; then
+ FIND=$2
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ --property_blacklist)
+ if [ -n "$2" ]; then
+ PROPERTY=$2
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ --option)
+ if [ -n "$2" ]; then
+ OPTION_NAME=$(echo $2 | cut -s -f1 -d:)
+ OPTION_VALUE=$(echo $2 | cut -s -f2 -d:)
+ if [ -z "$OPTION_NAME" ]; then
+ usage
+ exit 1
+ fi
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ --enable_foreign)
+ if [ -n "$2" ]; then
+ FOREIGN=$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 "$PROPERTY" -o -n "$MODULE" -o -n "$FOREIGN" -o -n "$OPTION_NAME" -o -n "$RECHECK_WWID" ]; then
+ echo "ignoring extra parameters on disable"
+ FRIENDLY=""
+ FIND=""
+ PROPERTY=""
+ MODULE=""
+ FOREIGN=""
+ OPTION_NAME=""
+ OPTION_VALUE=""
+ RECHECK_WWID=""
+ 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 "$RECHECK_WWID" ] && [ "$RECHECK_WWID" != "y" -a "$RECHECK_WWID" != "n" ]; then
+ echo "--recheck_wwid must be either 'y' or 'n'"
+ exit 1
+ fi
+ if [ "$FIND" = "y" ]; then
+ FIND="on"
+ elif [ "$FIND" = "n" ]; then
+ FIND="off"
+ elif [ -n "$FIND" ] && [ "$FIND" != "on" -a "$FIND" != "yes" -a "$FIND" != "off" -a "$FIND" != "no" -a "$FIND" != "strict" -a "$FIND" != "greedy" -a "$FIND" != "smart" ]; then
+ echo "--find_multipaths must be one of 'on' 'yes' 'y' 'off' 'no' 'n' 'strict' 'greedy' or 'smart'"
+ exit 1
+ fi
+ if [ -n "$PROPERTY" ] && [ "$PROPERTY" != "y" -a "$PROPERTY" != "n" ]; then
+ echo "--property_blacklist must be either 'y' or 'n'"
+ exit 1
+ fi
+ if [ -n "$FOREIGN" ] && [ "$FOREIGN" != "y" -a "$FOREIGN" != "n" ]; then
+ echo "--enable_foreign must be either 'y' or 'n'"
+ exit 1
+ fi
+ if [ -n "$OPTION_NAME" ]; then
+ if [[ $OPTION_NAME =~ [[:space:]]|#|\"|!|\{|\} ]]; then
+ echo "--option name \"$OPTION_NAME\" is invalid"
+ exit 1
+ elif [[ $OPTION_VALUE =~ \"|#|!|\{|\} ]]; then
+ echo "--option value \"$OPTION_VALUE\" is invalid"
+ exit 1
+ fi
+ if [[ $OPTION_VALUE =~ [[:space:]] ]]; then
+ OPTION_VALUE=\"$OPTION_VALUE\"
+ fi
+ fi
+ if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" -a -z "$PROPERTY" -a -z "$FOREIGN" -a -z "$OPTION_NAME" -a -z "$RECHECK_WWID" ]; 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[[:space:]][[:space:]]*\"\.\?\*\"" ; then
+ HAVE_DISABLE=1
+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"" ; then
+ HAVE_DISABLE=0
+ fi
+fi
+
+if [ "$HAVE_BLACKLIST" = "1" ]; then
+ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*wwid[[:space:]][[:space:]]*\"\.\?\*\"" ; then
+ HAVE_WWID_DISABLE=1
+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*wwid[[:space:]][[:space:]]*\"\.\?\*\"" ; then
+ HAVE_WWID_DISABLE=0
+ fi
+fi
+
+if [ "$HAVE_DEFAULTS" = "1" ]; then
+ HAVE_FIND=`sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | sed -n 's/^[[:blank:]]*find_multipaths[[:blank:]][[:blank:]]*\([^[:blank:]]*\).*$/\1/p' | sed -n 1p`
+ if [ "$HAVE_FIND" = "1" ]; then
+ HAVE_FIND="yes"
+ elif [ "$HAVE_FIND" = "0" ]; then
+ HAVE_FIND="no"
+ fi
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]][[:space:]]*\(yes\|1\)" ; then
+ HAVE_FRIENDLY=1
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]][[:space:]]*\(no\|0\)" ; then
+ HAVE_FRIENDLY=0
+ fi
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*recheck_wwid[[:space:]][[:space:]]*\(yes\|1\)" ; then
+ HAVE_RECHECK_WWID=1
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*recheck_wwid[[:space:]][[:space:]]*\(no\|0\)" ; then
+ HAVE_RECHECK_WWID=0
+ fi
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*enable_foreign" ; then
+ HAVE_FOREIGN=0
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign[[:space:]][[:space:]]*\"\.\*\"" ; then
+ HAVE_FOREIGN=1
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign[[:space:]][[:space:]]*\"\^\$\"" ; then
+ HAVE_FOREIGN=2
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign[[:space:]][[:space:]]*\"NONE\"" ; then
+ HAVE_FOREIGN=2
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign" ; then
+ HAVE_FOREIGN=3
+ fi
+ if [ -n "$OPTION_NAME" ]; then
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q '^[[:space:]]*'"$OPTION_NAME"'[[:space:]][[:space:]]*'"$OPTION_VALUE" ; then
+ HAVE_OPTION=1
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q '^[[:space:]]*'"$OPTION_NAME"'\([[:space:]].*\)\?$' ; then
+ HAVE_OPTION=0
+ fi
+ fi
+fi
+
+if [ "$HAVE_EXCEPTIONS" = "1" ]; then
+ if sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
+ HAVE_PROPERTY=1
+ elif sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
+ HAVE_PROPERTY=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" ]; then
+ echo "find_multipaths is off"
+ else
+ echo "find_multipaths is $HAVE_FIND"
+ 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 [ -z "$HAVE_RECHECK_WWID" -o "$HAVE_RECHECK_WWID" = 0 ]; then
+ echo "recheck_wwid is disabled"
+ else
+ echo "recheck_wwid is enabled"
+ fi
+ if [ -z "$HAVE_PROPERTY" -o "$HAVE_PROPERTY" = 0 ]; then
+ echo "default property blacklist is disabled"
+ else
+ echo "default property blacklist is enabled"
+ fi
+ if [ -z "$HAVE_FOREIGN" -o "$HAVE_FOREIGN" = 0 ]; then
+ echo "enable_foreign is not set (no foreign multipath devices will be shown)"
+ elif [ "$HAVE_FOREIGN" = 1 ]; then
+ echo "enable_foreign is set (all foreign multipath devices will be shown)"
+ elif [ "$HAVE_FOREIGN" = 2 ]; then
+ echo "enable_foreign is set (no foreign multipath devices will be shown)"
+ else
+ echo "enable_foreign is set (foreign multipath devices may not be shown)"
+ 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[[:space:]][[:space:]]*\"\.\?\*\"/# 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[[:space:]][[:space:]]*\"\.\?\*\"/ 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[[:space:]][[:space:]]*\"\.\?\*\"/# 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[[:space:]][[:space:]]*\"\.\?\*\"/ devnode ".*"/' $TMPFILE
+ fi
+fi
+
+if [ -n "$FIND" ]; then
+ if [ -z "$HAVE_FIND" ]; then
+ sed -i '/^defaults[[:space:]]*{/ a\
+ find_multipaths '"$FIND"'
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$FIND" != "$HAVE_FIND" ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:blank:]]*find_multipaths[[:blank:]][[:blank:]]*[^[:blank:]]*/ find_multipaths '"$FIND"'/' $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:]][[: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:]][[:space:]]*\(no\|0\)/ user_friendly_names yes/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+fi
+
+if [ "$RECHECK_WWID" = "n" ]; then
+ if [ "$HAVE_RECHECK_WWID" = 1 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*recheck_wwid[[:space:]][[:space:]]*\(yes\|1\)/ recheck_wwid no/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+elif [ "$RECHECK_WWID" = "y" ]; then
+ if [ -z "$HAVE_RECHECK_WWID" ]; then
+ sed -i '/^defaults[[:space:]]*{/ a\
+ recheck_wwid yes
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$HAVE_RECHECK_WWID" = 0 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*recheck_wwid[[:space:]][[:space:]]*\(no\|0\)/ recheck_wwid yes/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+fi
+
+if [ "$PROPERTY" = "n" ]; then
+ if [ "$HAVE_PROPERTY" = 1 ]; then
+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/# property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+elif [ "$PROPERTY" = "y" ]; then
+ if [ -z "$HAVE_PROPERTY" -a -z "$HAVE_EXCEPTIONS" ]; then
+ cat >> $TMPFILE << _EOF_
+
+blacklist_exceptions {
+ property "(SCSI_IDENT_|ID_WWN)"
+}
+_EOF_
+ CHANGED_CONFIG=1
+ elif [ -z "$HAVE_PROPERTY" ]; then
+ sed -i '/^blacklist_exceptions[[:space:]]*{/ a\
+ property "(SCSI_IDENT_|ID_WWN)"
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$HAVE_PROPERTY" = 0 ]; then
+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/ property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+fi
+
+if [ "$FOREIGN" = "n" ]; then
+ if [ "$HAVE_FOREIGN" = 1 -o "$HAVE_FOREIGN" = 3 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*enable_foreign/# enable_foreign/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+elif [ "$FOREIGN" = "y" ]; then
+ if [ -z "$HAVE_FOREIGN" ]; then
+ sed -i '/^defaults[[:space:]]*{/ a\
+ enable_foreign ".*"
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$HAVE_FOREIGN" = 0 -o "$HAVE_FOREIGN" = 2 -o "$HAVE_FOREIGN" = 3 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*#\?[[:space:]]*enable_foreign.*$/ enable_foreign ".*"/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+fi
+
+if [ -n "$OPTION_NAME" -a -n "$OPTION_VALUE" ]; then
+ if [ -z "$HAVE_OPTION" ]; then
+ sed -i '/^defaults[[:space:]]*{/ a\
+ '"$OPTION_NAME"' '"$OPTION_VALUE"'
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$HAVE_OPTION" = 0 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*'"$OPTION_NAME"'\([[:space:]].*\)\?$/ '"$OPTION_NAME"' '"$OPTION_VALUE"'/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+elif [ -n "$OPTION_NAME" -a -n "$HAVE_OPTION" ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/{/^[[:space:]]*'"$OPTION_NAME"'\([[:space:]].*\)\?$/d}' $TMPFILE
+ CHANGED_CONFIG=1
+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 00000000..ec4e5c56
--- /dev/null
+++ b/multipath/mpathconf.8
@@ -0,0 +1,151 @@
+.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
+set and
+.B find_multipaths
+set to \fBon\fP. To disable these, use the
+.B --user_friendly_names n
+and
+.B --find_multipaths off
+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_names \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 --recheck_wwid \fP { \fBy\fP | \fBn\fP }
+If set to \fBy\fP, this adds the line
+.B recheck_wwid yes
+to the
+.B /etc/multipath.conf
+defaults section, or sets an existing line to \fByes\fP. If set to \fBn\fP, this
+sets an existing \fBrecheck_wwid\fP line to \fBno\fP. This command can be used
+along with any other command.
+.TP
+.B --find_multipaths\fP { \fBon\fP | \fByes\fP | \fBy\fP | \fBoff\fP | \fBno\fP | \fBn\fP | \fBstrict\fP | \fBgreedy\fP | \fBsmart\fP }
+If set to \fB<value>\fP, this adds the line
+.B find_multipaths <value>
+to the
+.B /etc/multipath.conf
+defaults section. This command can be used along with any other command.
+\fBy\fP and \fBn\fP can be used instead of \fByes\fP and \fBno\fP.
+.TP
+.B --property_blacklist \fP { \fBy\fP | \fBn\fP }
+If set to \fBy\fP, this adds the line
+.B property "(SCSI_IDENT_|ID_WWN)"
+to the
+.B /etc/multipath.conf
+blacklist_exceptions section. If set to \fBn\fP, this removes the line, if
+present. This command can be used along with any other command.
+.TP
+.B --enable_foreign\fP { \fBy\fP | \fBn\fP }
+If set to \fBy\fP, this adds the line
+.B enable_foreign ".*"
+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 --option \fB<option_name>:[<value>]\fP
+Sets the defaults section option \fB<option_name>\fP to \fB<value>\fP. If the
+option was not previously set in the defaults section, it is added. If it was
+set, its value is changed to \fB<value>\fP. If \fB<value>\fP is left blank,
+then the option is removed from the defaults section, if was set there. This
+command can be used along 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_friendly_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>

View file

@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 7 Feb 2018 14:20:11 -0600
Subject: [PATCH] multipathd: change spurious uevent msg priority
The "spurious uevent, path already in pathvec" is not anything to worry
about, so it should not have the error priority.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index 51e0f5e..7ac59d9 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -562,7 +562,7 @@ uev_add_path (struct uevent *uev, struct vectors * vecs, int need_do_map)
if (pp) {
int r;
- condlog(0, "%s: spurious uevent, path already in pathvec",
+ condlog(2, "%s: spurious uevent, path already in pathvec",
uev->kernel);
if (!pp->mpp && !strlen(pp->wwid)) {
condlog(3, "%s: reinitialize path", uev->kernel);
--
2.7.4

View file

@ -1,151 +0,0 @@
From d6ad888bad3850bb0a342ebcdc9fd78773eb3b2a 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>
---
multipath/main.c | 54 ++++++++++++++++++++++++++++++--
multipath/multipath.8.in | 7 ++++-
multipathd/multipathd.service.in | 1 +
3 files changed, 59 insertions(+), 3 deletions(-)
diff --git a/multipath/main.c b/multipath/main.c
index 31012874..a667c2ee 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -111,7 +111,7 @@ usage (char * progname)
fprintf (stderr, " %s [-v level] [-R retries] -F\n", progname);
fprintf (stderr, " %s [-v level] [-l|-ll] [device]\n", progname);
fprintf (stderr, " %s [-v level] [-a|-w] device\n", progname);
- fprintf (stderr, " %s [-v level] -W\n", progname);
+ fprintf (stderr, " %s [-v level] [-A|-W]\n", progname);
fprintf (stderr, " %s [-v level] [-i] [-c|-C] device\n", progname);
fprintf (stderr, " %s [-v level] [-i] [-u|-U]\n", progname);
fprintf (stderr, " %s [-h|-t|-T]\n", progname);
@@ -125,6 +125,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"
@@ -440,6 +442,50 @@ static void cleanup_vecs(void)
free_pathvec(vecs.pathvec, FREE_PATHS);
}
+static 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;
+}
+
static int
configure (struct config *conf, enum mpath_cmds cmd,
enum devtypes dev_type, char *devpath)
@@ -851,7 +897,7 @@ main (int argc, char *argv[])
condlog(1, "failed to register cleanup handler for vecs: %m");
if (atexit(cleanup_bindings))
condlog(1, "failed to register cleanup handler for bindings: %m");
- while ((arg = getopt(argc, argv, ":adDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
+ while ((arg = getopt(argc, argv, ":aAdDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
switch(arg) {
case 'v':
if (!isdigit(optarg[0])) {
@@ -922,6 +968,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.in b/multipath/multipath.8.in
index b88e9a4c..edd742aa 100644
--- a/multipath/multipath.8.in
+++ b/multipath/multipath.8.in
@@ -64,7 +64,7 @@ multipath \- Device mapper target autoconfig.
.B multipath
.RB [\| \-v\ \c
.IR level \|]
-.B -W
+.RB [\| \-A | \-W \|]
.
.LP
.B multipath
@@ -146,6 +146,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.in b/multipathd/multipathd.service.in
index ab166435..1ec08c6e 100644
--- a/multipathd/multipathd.service.in
+++ b/multipathd/multipathd.service.in
@@ -19,6 +19,7 @@ StartLimitBurst=3
[Service]
Type=notify
NotifyAccess=main
+ExecStartPre=-@BINDIR@/multipath -A
ExecStart=@BINDIR@/multipathd -d -s
ExecReload=@BINDIR@/multipathd reconfigure
Restart=on-failure

View file

@ -0,0 +1,68 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 7 Feb 2018 16:06:06 -0600
Subject: [PATCH] multipath: print sysfs state in fast list mode
commit b123e711ea2a4b471a98ff5e26815df3773636b5 "libmultipath: cleanup
orphan device states" stopped multipathd from showing old state for
orphan paths by checking if pp->mpp was set, and only printing the state
if it was. Unfortunately, when "multipath -l" is run, pp->mpp isn't
set. While the checker state isn't checked and shouldn't be printed with
"-l", the sysfs state can be, and was before b123e711. This patch sets
pp->mpp in fast list mode, so that the sysfs state gets printed. It
also verifies that the path exists in sysfs, and if not, marks it as
faulty.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/main.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/multipath/main.c b/multipath/main.c
index bffe065..d2415a9 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -149,7 +149,7 @@ usage (char * progname)
}
static int
-update_paths (struct multipath * mpp)
+update_paths (struct multipath * mpp, int quick)
{
int i, j;
struct pathgroup * pgp;
@@ -171,9 +171,12 @@ update_paths (struct multipath * mpp)
* path is not in sysfs anymore
*/
pp->chkrstate = pp->state = PATH_DOWN;
+ pp->offline = 1;
continue;
}
pp->mpp = mpp;
+ if (quick)
+ continue;
conf = get_multipath_config();
if (pathinfo(pp, conf, DI_ALL))
pp->state = PATH_UNCHECKED;
@@ -181,6 +184,8 @@ update_paths (struct multipath * mpp)
continue;
}
pp->mpp = mpp;
+ if (quick)
+ continue;
if (pp->state == PATH_UNCHECKED ||
pp->state == PATH_WILD) {
conf = get_multipath_config();
@@ -238,8 +243,7 @@ get_dm_mpvec (enum mpath_cmds cmd, vector curmp, vector pathvec, char * refwwid)
* If not in "fast list mode", we need to fetch information
* about them
*/
- if (cmd != CMD_LIST_SHORT)
- update_paths(mpp);
+ update_paths(mpp, (cmd == CMD_LIST_SHORT));
if (cmd == CMD_LIST_LONG)
mpp->bestpg = select_path_group(mpp);
--
2.7.4

View file

@ -1,41 +0,0 @@
From 064d761121e7e2c7b63ab280e341d8010a413119 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".
Co-authored-by: Paul Donohue <git@PaulSD.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/defaults.h | 2 +-
multipath/multipath.conf.5.in | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index 134b690a..e2fe7ac4 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -24,7 +24,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
diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in
index ba291e11..b8389db3 100644
--- a/multipath/multipath.conf.5.in
+++ b/multipath/multipath.conf.5.in
@@ -1227,7 +1227,7 @@ as non-multipath and passed on to upper layers.
\fBNote:\fR this may cause delays during device detection if
there are single-path devices which aren\'t blacklisted.
.TP
-The default is: \fBstrict\fR
+The default is: \fBoff\fR
.RE
.
.

View file

@ -0,0 +1,148 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 5 Feb 2018 16:07:36 -0600
Subject: [PATCH] libmultipath: move remove_map waiter code to multipathd
Only multipathd needs to worry about the multipath waiter code. There is
no point in having remove_map_and_stop_waiter() or
remove_maps_and_stop_waiters() in libmultipath, since they should never
be use outside of multipathd.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/structs_vec.c | 40 +++++-----------------------------------
libmultipath/structs_vec.h | 2 --
multipathd/main.c | 23 +++++++++++++++++++++++
3 files changed, 28 insertions(+), 37 deletions(-)
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index 0de2221..abf5327 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -116,25 +116,16 @@ set_multipath_wwid (struct multipath * mpp)
dm_get_uuid(mpp->alias, mpp->wwid);
}
-#define KEEP_WAITER 0
-#define STOP_WAITER 1
#define PURGE_VEC 1
-static void
-_remove_map (struct multipath * mpp, struct vectors * vecs,
- int stop_waiter, int purge_vec)
+void
+remove_map(struct multipath * mpp, struct vectors * vecs, int purge_vec)
{
int i;
condlog(4, "%s: remove multipath map", mpp->alias);
/*
- * stop the DM event waiter thread
- */
- if (stop_waiter)
- stop_waiter_thread(mpp, vecs);
-
- /*
* clear references to this map
*/
orphan_paths(vecs->pathvec, mpp);
@@ -149,19 +140,8 @@ _remove_map (struct multipath * mpp, struct vectors * vecs,
free_multipath(mpp, KEEP_PATHS);
}
-void remove_map(struct multipath *mpp, struct vectors *vecs, int purge_vec)
-{
- _remove_map(mpp, vecs, KEEP_WAITER, purge_vec);
-}
-
-void remove_map_and_stop_waiter(struct multipath *mpp, struct vectors *vecs,
- int purge_vec)
-{
- _remove_map(mpp, vecs, STOP_WAITER, purge_vec);
-}
-
-static void
-_remove_maps (struct vectors * vecs, int stop_waiter)
+void
+remove_maps(struct vectors * vecs)
{
int i;
struct multipath * mpp;
@@ -170,7 +150,7 @@ _remove_maps (struct vectors * vecs, int stop_waiter)
return;
vector_foreach_slot (vecs->mpvec, mpp, i) {
- _remove_map(mpp, vecs, stop_waiter, 1);
+ remove_map(mpp, vecs, 1);
i--;
}
@@ -178,16 +158,6 @@ _remove_maps (struct vectors * vecs, int stop_waiter)
vecs->mpvec = NULL;
}
-void remove_maps(struct vectors *vecs)
-{
- _remove_maps(vecs, KEEP_WAITER);
-}
-
-void remove_maps_and_stop_waiters(struct vectors *vecs)
-{
- _remove_maps(vecs, STOP_WAITER);
-}
-
void
extract_hwe_from_path(struct multipath * mpp)
{
diff --git a/libmultipath/structs_vec.h b/libmultipath/structs_vec.h
index b81413b..d6e17bb 100644
--- a/libmultipath/structs_vec.h
+++ b/libmultipath/structs_vec.h
@@ -27,9 +27,7 @@ int update_multipath_strings (struct multipath *mpp, vector pathvec,
void extract_hwe_from_path(struct multipath * mpp);
void remove_map (struct multipath * mpp, struct vectors * vecs, int purge_vec);
-void remove_map_and_stop_waiter (struct multipath * mpp, struct vectors * vecs, int purge_vec);
void remove_maps (struct vectors * vecs);
-void remove_maps_and_stop_waiters (struct vectors * vecs);
void sync_map_state (struct multipath *);
int update_map (struct multipath *mpp, struct vectors *vecs);
diff --git a/multipathd/main.c b/multipathd/main.c
index 7ac59d9..72c3c2f 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -288,6 +288,29 @@ switch_pathgroup (struct multipath * mpp)
mpp->alias, mpp->bestpg);
}
+static void
+remove_map_and_stop_waiter(struct multipath *mpp, struct vectors *vecs,
+ int purge_vec)
+{
+ stop_waiter_thread(mpp, vecs);
+ remove_map(mpp, vecs, purge_vec);
+}
+
+static void
+remove_maps_and_stop_waiters(struct vectors *vecs)
+{
+ int i;
+ struct multipath * mpp;
+
+ if (!vecs)
+ return;
+
+ vector_foreach_slot(vecs->mpvec, mpp, i)
+ stop_waiter_thread(mpp, vecs);
+
+ remove_maps(vecs);
+}
+
static int
coalesce_maps(struct vectors *vecs, vector nmpv)
{
--
2.7.4

View file

@ -1,84 +0,0 @@
From 335b8eb2773b07a602e84e14c1f3e289a9b25b5a 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 34527b22..4eaa3cc3 100644
--- a/libmultipath/prioritizers/ana.c
+++ b/libmultipath/prioritizers/ana.c
@@ -23,6 +23,7 @@
#include "prio.h"
#include "util.h"
#include "structs.h"
+#include "sysfs.h"
enum {
ANA_ERR_GETCTRL_FAILED = 1,
@@ -35,6 +36,7 @@ enum {
ANA_ERR_GETNS_FAILED,
ANA_ERR_NO_MEMORY,
ANA_ERR_NO_INFORMATION,
+ ANA_ERR_INVALID_STATE,
};
static const char *ana_errmsg[] = {
@@ -48,6 +50,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;
}
+static 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;
+}
+
static int get_ana_info(struct path * pp)
{
int rc;
@@ -208,8 +232,11 @@ int getprio(struct path *pp, __attribute__((unused)) char *args)
if (pp->fd < 0)
rc = -ANA_ERR_NO_INFORMATION;
- else
- rc = get_ana_info(pp);
+ else {
+ rc = get_ana_info_sysfs(pp);
+ if (rc < 0)
+ rc = get_ana_info(pp);
+ }
switch (rc) {
case NVME_ANA_OPTIMIZED:

View file

@ -0,0 +1,793 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 5 Feb 2018 18:50:45 -0600
Subject: [PATCH] move waiter code from libmultipath to multipathd
Only multipathd uses the code in waiter.[ch] and the functions that call
it directly, so they should all live in the multipathd directory. This
patch is simply moving the waiter.[ch] files and the functions in
structs_vec that use them. None of the moved code has been changed.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/Makefile | 2 +-
libmultipath/structs_vec.c | 98 ---------------------
libmultipath/structs_vec.h | 4 +-
libmultipath/waiter.c | 215 ---------------------------------------------
libmultipath/waiter.h | 17 ----
multipathd/Makefile | 2 +-
multipathd/main.c | 96 ++++++++++++++++++++
multipathd/waiter.c | 215 +++++++++++++++++++++++++++++++++++++++++++++
multipathd/waiter.h | 17 ++++
9 files changed, 332 insertions(+), 334 deletions(-)
delete mode 100644 libmultipath/waiter.c
delete mode 100644 libmultipath/waiter.h
create mode 100644 multipathd/waiter.c
create mode 100644 multipathd/waiter.h
diff --git a/libmultipath/Makefile b/libmultipath/Makefile
index 6447d8d..a1005b2 100644
--- a/libmultipath/Makefile
+++ b/libmultipath/Makefile
@@ -42,7 +42,7 @@ OBJS = memory.o parser.o vector.o devmapper.o callout.o \
pgpolicies.o debug.o defaults.o uevent.o time-util.o \
switchgroup.o uxsock.o print.o alias.o log_pthread.o \
log.o configure.o structs_vec.o sysfs.o prio.o checkers.o \
- lock.o waiter.o file.o wwids.o prioritizers/alua_rtpg.o prkey.o \
+ lock.o file.o wwids.o prioritizers/alua_rtpg.o prkey.o \
io_err_stat.o
all: $(LIBS)
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index abf5327..77b045b 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -10,7 +10,6 @@
#include "structs.h"
#include "structs_vec.h"
#include "sysfs.h"
-#include "waiter.h"
#include "devmapper.h"
#include "dmparser.h"
#include "propsel.h"
@@ -107,17 +106,6 @@ void orphan_paths(vector pathvec, struct multipath *mpp)
}
}
-static void
-set_multipath_wwid (struct multipath * mpp)
-{
- if (strlen(mpp->wwid))
- return;
-
- dm_get_uuid(mpp->alias, mpp->wwid);
-}
-
-#define PURGE_VEC 1
-
void
remove_map(struct multipath * mpp, struct vectors * vecs, int purge_vec)
{
@@ -379,92 +367,6 @@ sync_map_state(struct multipath *mpp)
}
}
-int
-update_map (struct multipath *mpp, struct vectors *vecs)
-{
- int retries = 3;
- char params[PARAMS_SIZE] = {0};
-
-retry:
- condlog(4, "%s: updating new map", mpp->alias);
- if (adopt_paths(vecs->pathvec, mpp)) {
- condlog(0, "%s: failed to adopt paths for new map update",
- mpp->alias);
- retries = -1;
- goto fail;
- }
- verify_paths(mpp, vecs);
- mpp->action = ACT_RELOAD;
-
- extract_hwe_from_path(mpp);
- if (setup_map(mpp, params, PARAMS_SIZE)) {
- condlog(0, "%s: failed to setup new map in update", mpp->alias);
- retries = -1;
- goto fail;
- }
- if (domap(mpp, params, 1) <= 0 && retries-- > 0) {
- condlog(0, "%s: map_udate sleep", mpp->alias);
- sleep(1);
- goto retry;
- }
- dm_lib_release();
-
-fail:
- if (setup_multipath(vecs, mpp))
- return 1;
-
- sync_map_state(mpp);
-
- if (retries < 0)
- condlog(0, "%s: failed reload in new map update", mpp->alias);
- return 0;
-}
-
-struct multipath *add_map_without_path (struct vectors *vecs, char *alias)
-{
- struct multipath * mpp = alloc_multipath();
- struct config *conf;
-
- if (!mpp)
- return NULL;
- if (!alias) {
- FREE(mpp);
- return NULL;
- }
-
- mpp->alias = STRDUP(alias);
-
- if (dm_get_info(mpp->alias, &mpp->dmi)) {
- condlog(3, "%s: cannot access table", mpp->alias);
- goto out;
- }
- set_multipath_wwid(mpp);
- conf = get_multipath_config();
- mpp->mpe = find_mpe(conf->mptable, mpp->wwid);
- put_multipath_config(conf);
-
- if (update_multipath_table(mpp, vecs->pathvec, 1))
- goto out;
- if (update_multipath_status(mpp))
- goto out;
-
- if (!vector_alloc_slot(vecs->mpvec))
- goto out;
-
- vector_set_slot(vecs->mpvec, mpp);
-
- if (update_map(mpp, vecs) != 0) /* map removed */
- return NULL;
-
- if (start_waiter_thread(mpp, vecs))
- goto out;
-
- return mpp;
-out:
- remove_map(mpp, vecs, PURGE_VEC);
- return NULL;
-}
-
static void
find_existing_alias (struct multipath * mpp,
struct vectors *vecs)
diff --git a/libmultipath/structs_vec.h b/libmultipath/structs_vec.h
index d6e17bb..ceab6d9 100644
--- a/libmultipath/structs_vec.h
+++ b/libmultipath/structs_vec.h
@@ -26,12 +26,12 @@ int update_multipath_strings (struct multipath *mpp, vector pathvec,
int is_daemon);
void extract_hwe_from_path(struct multipath * mpp);
+#define PURGE_VEC 1
+
void remove_map (struct multipath * mpp, struct vectors * vecs, int purge_vec);
void remove_maps (struct vectors * vecs);
void sync_map_state (struct multipath *);
-int update_map (struct multipath *mpp, struct vectors *vecs);
-struct multipath * add_map_without_path (struct vectors * vecs, char * alias);
struct multipath * add_map_with_path (struct vectors * vecs,
struct path * pp, int add_vec);
int update_multipath (struct vectors *vecs, char *mapname, int reset);
diff --git a/libmultipath/waiter.c b/libmultipath/waiter.c
deleted file mode 100644
index cb9708b..0000000
--- a/libmultipath/waiter.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (c) 2004, 2005 Christophe Varoqui
- * Copyright (c) 2005 Kiyoshi Ueda, NEC
- * Copyright (c) 2005 Benjamin Marzinski, Redhat
- * Copyright (c) 2005 Edward Goggin, EMC
- */
-#include <unistd.h>
-#include <libdevmapper.h>
-#include <sys/mman.h>
-#include <pthread.h>
-#include <signal.h>
-#include <urcu.h>
-
-#include "vector.h"
-#include "memory.h"
-#include "checkers.h"
-#include "config.h"
-#include "structs.h"
-#include "structs_vec.h"
-#include "devmapper.h"
-#include "debug.h"
-#include "lock.h"
-#include "waiter.h"
-
-pthread_attr_t waiter_attr;
-
-static struct event_thread *alloc_waiter (void)
-{
-
- struct event_thread *wp;
-
- wp = (struct event_thread *)MALLOC(sizeof(struct event_thread));
- memset(wp, 0, sizeof(struct event_thread));
-
- return wp;
-}
-
-static void free_waiter (void *data)
-{
- struct event_thread *wp = (struct event_thread *)data;
-
- if (wp->dmt)
- dm_task_destroy(wp->dmt);
-
- rcu_unregister_thread();
- FREE(wp);
-}
-
-void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs)
-{
- pthread_t thread;
-
- if (mpp->waiter == (pthread_t)0) {
- condlog(3, "%s: event checker thread already stopped",
- mpp->alias);
- return;
- }
- condlog(2, "%s: stop event checker thread (%lu)", mpp->alias,
- mpp->waiter);
- thread = mpp->waiter;
- mpp->waiter = (pthread_t)0;
- pthread_cancel(thread);
- pthread_kill(thread, SIGUSR2);
-}
-
-/*
- * returns the reschedule delay
- * negative means *stop*
- */
-static int waiteventloop (struct event_thread *waiter)
-{
- sigset_t set, oldset;
- int event_nr;
- int r;
-
- if (!waiter->event_nr)
- waiter->event_nr = dm_geteventnr(waiter->mapname);
-
- if (!(waiter->dmt = libmp_dm_task_create(DM_DEVICE_WAITEVENT))) {
- condlog(0, "%s: devmap event #%i dm_task_create error",
- waiter->mapname, waiter->event_nr);
- return 1;
- }
-
- if (!dm_task_set_name(waiter->dmt, waiter->mapname)) {
- condlog(0, "%s: devmap event #%i dm_task_set_name error",
- waiter->mapname, waiter->event_nr);
- dm_task_destroy(waiter->dmt);
- waiter->dmt = NULL;
- return 1;
- }
-
- if (waiter->event_nr && !dm_task_set_event_nr(waiter->dmt,
- waiter->event_nr)) {
- condlog(0, "%s: devmap event #%i dm_task_set_event_nr error",
- waiter->mapname, waiter->event_nr);
- dm_task_destroy(waiter->dmt);
- waiter->dmt = NULL;
- return 1;
- }
-
- dm_task_no_open_count(waiter->dmt);
-
- /* wait */
- sigemptyset(&set);
- sigaddset(&set, SIGUSR2);
- pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
-
- pthread_testcancel();
- r = dm_task_run(waiter->dmt);
- pthread_testcancel();
-
- pthread_sigmask(SIG_SETMASK, &oldset, NULL);
- dm_task_destroy(waiter->dmt);
- waiter->dmt = NULL;
-
- if (!r) /* wait interrupted by signal */
- return -1;
-
- waiter->event_nr++;
-
- /*
- * upon event ...
- */
- while (1) {
- condlog(3, "%s: devmap event #%i",
- waiter->mapname, waiter->event_nr);
-
- /*
- * event might be :
- *
- * 1) a table reload, which means our mpp structure is
- * obsolete : refresh it through update_multipath()
- * 2) a path failed by DM : mark as such through
- * update_multipath()
- * 3) map has gone away : stop the thread.
- * 4) a path reinstate : nothing to do
- * 5) a switch group : nothing to do
- */
- pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock);
- lock(&waiter->vecs->lock);
- pthread_testcancel();
- r = update_multipath(waiter->vecs, waiter->mapname, 1);
- lock_cleanup_pop(waiter->vecs->lock);
-
- if (r) {
- condlog(2, "%s: event checker exit",
- waiter->mapname);
- return -1; /* stop the thread */
- }
-
- event_nr = dm_geteventnr(waiter->mapname);
-
- if (waiter->event_nr == event_nr)
- return 1; /* upon problem reschedule 1s later */
-
- waiter->event_nr = event_nr;
- }
- return -1; /* never reach there */
-}
-
-static void *waitevent (void *et)
-{
- int r;
- struct event_thread *waiter;
-
- mlockall(MCL_CURRENT | MCL_FUTURE);
-
- waiter = (struct event_thread *)et;
- pthread_cleanup_push(free_waiter, et);
-
- rcu_register_thread();
- while (1) {
- r = waiteventloop(waiter);
-
- if (r < 0)
- break;
-
- sleep(r);
- }
-
- pthread_cleanup_pop(1);
- return NULL;
-}
-
-int start_waiter_thread (struct multipath *mpp, struct vectors *vecs)
-{
- struct event_thread *wp;
-
- if (!mpp)
- return 0;
-
- wp = alloc_waiter();
-
- if (!wp)
- goto out;
-
- strncpy(wp->mapname, mpp->alias, WWID_SIZE - 1);
- wp->vecs = vecs;
-
- if (pthread_create(&wp->thread, &waiter_attr, waitevent, wp)) {
- condlog(0, "%s: cannot create event checker", wp->mapname);
- goto out1;
- }
- mpp->waiter = wp->thread;
- condlog(2, "%s: event checker started", wp->mapname);
-
- return 0;
-out1:
- free_waiter(wp);
- mpp->waiter = (pthread_t)0;
-out:
- condlog(0, "failed to start waiter thread");
- return 1;
-}
diff --git a/libmultipath/waiter.h b/libmultipath/waiter.h
deleted file mode 100644
index 0cfae46..0000000
--- a/libmultipath/waiter.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _WAITER_H
-#define _WAITER_H
-
-extern pthread_attr_t waiter_attr;
-
-struct event_thread {
- struct dm_task *dmt;
- pthread_t thread;
- int event_nr;
- char mapname[WWID_SIZE];
- struct vectors *vecs;
-};
-
-void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs);
-int start_waiter_thread (struct multipath *mpp, struct vectors *vecs);
-
-#endif /* _WAITER_H */
diff --git a/multipathd/Makefile b/multipathd/Makefile
index e6f140b..85f29a7 100644
--- a/multipathd/Makefile
+++ b/multipathd/Makefile
@@ -22,7 +22,7 @@ ifdef SYSTEMD
endif
endif
-OBJS = main.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o
+OBJS = main.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o waiter.o
EXEC = multipathd
diff --git a/multipathd/main.c b/multipathd/main.c
index 72c3c2f..94b2406 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -311,6 +311,102 @@ remove_maps_and_stop_waiters(struct vectors *vecs)
remove_maps(vecs);
}
+static void
+set_multipath_wwid (struct multipath * mpp)
+{
+ if (strlen(mpp->wwid))
+ return;
+
+ dm_get_uuid(mpp->alias, mpp->wwid);
+}
+
+static int
+update_map (struct multipath *mpp, struct vectors *vecs)
+{
+ int retries = 3;
+ char params[PARAMS_SIZE] = {0};
+
+retry:
+ condlog(4, "%s: updating new map", mpp->alias);
+ if (adopt_paths(vecs->pathvec, mpp)) {
+ condlog(0, "%s: failed to adopt paths for new map update",
+ mpp->alias);
+ retries = -1;
+ goto fail;
+ }
+ verify_paths(mpp, vecs);
+ mpp->action = ACT_RELOAD;
+
+ extract_hwe_from_path(mpp);
+ if (setup_map(mpp, params, PARAMS_SIZE)) {
+ condlog(0, "%s: failed to setup new map in update", mpp->alias);
+ retries = -1;
+ goto fail;
+ }
+ if (domap(mpp, params, 1) <= 0 && retries-- > 0) {
+ condlog(0, "%s: map_udate sleep", mpp->alias);
+ sleep(1);
+ goto retry;
+ }
+ dm_lib_release();
+
+fail:
+ if (setup_multipath(vecs, mpp))
+ return 1;
+
+ sync_map_state(mpp);
+
+ if (retries < 0)
+ condlog(0, "%s: failed reload in new map update", mpp->alias);
+ return 0;
+}
+
+static struct multipath *
+add_map_without_path (struct vectors *vecs, char *alias)
+{
+ struct multipath * mpp = alloc_multipath();
+ struct config *conf;
+
+ if (!mpp)
+ return NULL;
+ if (!alias) {
+ FREE(mpp);
+ return NULL;
+ }
+
+ mpp->alias = STRDUP(alias);
+
+ if (dm_get_info(mpp->alias, &mpp->dmi)) {
+ condlog(3, "%s: cannot access table", mpp->alias);
+ goto out;
+ }
+ set_multipath_wwid(mpp);
+ conf = get_multipath_config();
+ mpp->mpe = find_mpe(conf->mptable, mpp->wwid);
+ put_multipath_config(conf);
+
+ if (update_multipath_table(mpp, vecs->pathvec, 1))
+ goto out;
+ if (update_multipath_status(mpp))
+ goto out;
+
+ if (!vector_alloc_slot(vecs->mpvec))
+ goto out;
+
+ vector_set_slot(vecs->mpvec, mpp);
+
+ if (update_map(mpp, vecs) != 0) /* map removed */
+ return NULL;
+
+ if (start_waiter_thread(mpp, vecs))
+ goto out;
+
+ return mpp;
+out:
+ remove_map(mpp, vecs, PURGE_VEC);
+ return NULL;
+}
+
static int
coalesce_maps(struct vectors *vecs, vector nmpv)
{
diff --git a/multipathd/waiter.c b/multipathd/waiter.c
new file mode 100644
index 0000000..cb9708b
--- /dev/null
+++ b/multipathd/waiter.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2004, 2005 Christophe Varoqui
+ * Copyright (c) 2005 Kiyoshi Ueda, NEC
+ * Copyright (c) 2005 Benjamin Marzinski, Redhat
+ * Copyright (c) 2005 Edward Goggin, EMC
+ */
+#include <unistd.h>
+#include <libdevmapper.h>
+#include <sys/mman.h>
+#include <pthread.h>
+#include <signal.h>
+#include <urcu.h>
+
+#include "vector.h"
+#include "memory.h"
+#include "checkers.h"
+#include "config.h"
+#include "structs.h"
+#include "structs_vec.h"
+#include "devmapper.h"
+#include "debug.h"
+#include "lock.h"
+#include "waiter.h"
+
+pthread_attr_t waiter_attr;
+
+static struct event_thread *alloc_waiter (void)
+{
+
+ struct event_thread *wp;
+
+ wp = (struct event_thread *)MALLOC(sizeof(struct event_thread));
+ memset(wp, 0, sizeof(struct event_thread));
+
+ return wp;
+}
+
+static void free_waiter (void *data)
+{
+ struct event_thread *wp = (struct event_thread *)data;
+
+ if (wp->dmt)
+ dm_task_destroy(wp->dmt);
+
+ rcu_unregister_thread();
+ FREE(wp);
+}
+
+void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs)
+{
+ pthread_t thread;
+
+ if (mpp->waiter == (pthread_t)0) {
+ condlog(3, "%s: event checker thread already stopped",
+ mpp->alias);
+ return;
+ }
+ condlog(2, "%s: stop event checker thread (%lu)", mpp->alias,
+ mpp->waiter);
+ thread = mpp->waiter;
+ mpp->waiter = (pthread_t)0;
+ pthread_cancel(thread);
+ pthread_kill(thread, SIGUSR2);
+}
+
+/*
+ * returns the reschedule delay
+ * negative means *stop*
+ */
+static int waiteventloop (struct event_thread *waiter)
+{
+ sigset_t set, oldset;
+ int event_nr;
+ int r;
+
+ if (!waiter->event_nr)
+ waiter->event_nr = dm_geteventnr(waiter->mapname);
+
+ if (!(waiter->dmt = libmp_dm_task_create(DM_DEVICE_WAITEVENT))) {
+ condlog(0, "%s: devmap event #%i dm_task_create error",
+ waiter->mapname, waiter->event_nr);
+ return 1;
+ }
+
+ if (!dm_task_set_name(waiter->dmt, waiter->mapname)) {
+ condlog(0, "%s: devmap event #%i dm_task_set_name error",
+ waiter->mapname, waiter->event_nr);
+ dm_task_destroy(waiter->dmt);
+ waiter->dmt = NULL;
+ return 1;
+ }
+
+ if (waiter->event_nr && !dm_task_set_event_nr(waiter->dmt,
+ waiter->event_nr)) {
+ condlog(0, "%s: devmap event #%i dm_task_set_event_nr error",
+ waiter->mapname, waiter->event_nr);
+ dm_task_destroy(waiter->dmt);
+ waiter->dmt = NULL;
+ return 1;
+ }
+
+ dm_task_no_open_count(waiter->dmt);
+
+ /* wait */
+ sigemptyset(&set);
+ sigaddset(&set, SIGUSR2);
+ pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
+
+ pthread_testcancel();
+ r = dm_task_run(waiter->dmt);
+ pthread_testcancel();
+
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+ dm_task_destroy(waiter->dmt);
+ waiter->dmt = NULL;
+
+ if (!r) /* wait interrupted by signal */
+ return -1;
+
+ waiter->event_nr++;
+
+ /*
+ * upon event ...
+ */
+ while (1) {
+ condlog(3, "%s: devmap event #%i",
+ waiter->mapname, waiter->event_nr);
+
+ /*
+ * event might be :
+ *
+ * 1) a table reload, which means our mpp structure is
+ * obsolete : refresh it through update_multipath()
+ * 2) a path failed by DM : mark as such through
+ * update_multipath()
+ * 3) map has gone away : stop the thread.
+ * 4) a path reinstate : nothing to do
+ * 5) a switch group : nothing to do
+ */
+ pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock);
+ lock(&waiter->vecs->lock);
+ pthread_testcancel();
+ r = update_multipath(waiter->vecs, waiter->mapname, 1);
+ lock_cleanup_pop(waiter->vecs->lock);
+
+ if (r) {
+ condlog(2, "%s: event checker exit",
+ waiter->mapname);
+ return -1; /* stop the thread */
+ }
+
+ event_nr = dm_geteventnr(waiter->mapname);
+
+ if (waiter->event_nr == event_nr)
+ return 1; /* upon problem reschedule 1s later */
+
+ waiter->event_nr = event_nr;
+ }
+ return -1; /* never reach there */
+}
+
+static void *waitevent (void *et)
+{
+ int r;
+ struct event_thread *waiter;
+
+ mlockall(MCL_CURRENT | MCL_FUTURE);
+
+ waiter = (struct event_thread *)et;
+ pthread_cleanup_push(free_waiter, et);
+
+ rcu_register_thread();
+ while (1) {
+ r = waiteventloop(waiter);
+
+ if (r < 0)
+ break;
+
+ sleep(r);
+ }
+
+ pthread_cleanup_pop(1);
+ return NULL;
+}
+
+int start_waiter_thread (struct multipath *mpp, struct vectors *vecs)
+{
+ struct event_thread *wp;
+
+ if (!mpp)
+ return 0;
+
+ wp = alloc_waiter();
+
+ if (!wp)
+ goto out;
+
+ strncpy(wp->mapname, mpp->alias, WWID_SIZE - 1);
+ wp->vecs = vecs;
+
+ if (pthread_create(&wp->thread, &waiter_attr, waitevent, wp)) {
+ condlog(0, "%s: cannot create event checker", wp->mapname);
+ goto out1;
+ }
+ mpp->waiter = wp->thread;
+ condlog(2, "%s: event checker started", wp->mapname);
+
+ return 0;
+out1:
+ free_waiter(wp);
+ mpp->waiter = (pthread_t)0;
+out:
+ condlog(0, "failed to start waiter thread");
+ return 1;
+}
diff --git a/multipathd/waiter.h b/multipathd/waiter.h
new file mode 100644
index 0000000..0cfae46
--- /dev/null
+++ b/multipathd/waiter.h
@@ -0,0 +1,17 @@
+#ifndef _WAITER_H
+#define _WAITER_H
+
+extern pthread_attr_t waiter_attr;
+
+struct event_thread {
+ struct dm_task *dmt;
+ pthread_t thread;
+ int event_nr;
+ char mapname[WWID_SIZE];
+ struct vectors *vecs;
+};
+
+void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs);
+int start_waiter_thread (struct multipath *mpp, struct vectors *vecs);
+
+#endif /* _WAITER_H */
--
2.7.4

View file

@ -1,96 +0,0 @@
From 137c96d16b6bb03d8a52854e152db4ee36b7d9e4 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 25 Mar 2021 13:05:10 -0500
Subject: [PATCH] RH: make parse_vpd_pg83 match scsi_id output
Red Hat sets ID_SERIAL based on the result of scsi_id, instead of using
the result of sg_inq and 55-scsi-sg3_id.rules. Make parse_vpd_pg83 match
that.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/discovery.c | 12 ++----------
tests/vpd.c | 6 ++++++
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index 31db8758..21cfcc73 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1225,13 +1225,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
good_len = 8;
break;
case 2:
- /* IEEE Extended: Prio 6 */
- new_prio = 6;
- good_len = 8;
- break;
case 3:
- /* IEEE Locally assigned: Prio 1 */
- new_prio = 1;
+ /* IEEE Extended or Locally assigned: Prio 6 */
+ new_prio = 6;
good_len = 8;
break;
default:
@@ -1249,10 +1245,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
break;
case 0x8:
/* SCSI Name: Prio 3 */
- invalid = (d[3] < 4 || (memcmp(d + 4, "eui.", 4) &&
- memcmp(d + 4, "naa.", 4) &&
- memcmp(d + 4, "iqn.", 4)));
- new_prio = 3;
break;
case 0x1:
/* T-10 Vendor ID: Prio 2 */
diff --git a/tests/vpd.c b/tests/vpd.c
index e3212e61..cdb111bb 100644
--- a/tests/vpd.c
+++ b/tests/vpd.c
@@ -232,11 +232,13 @@ static const char * const str_prefix[] = {
[STR_IQN] = "iqn.",
};
+#if 0
static const char byte0[] = {
[STR_EUI] = '2',
[STR_NAA] = '3',
[STR_IQN] = '8',
};
+#endif
/**
* create_scsi_string_desc() - create a SCSI name string descriptor.
@@ -767,6 +769,7 @@ make_test_vpd_naa(2, 18);
make_test_vpd_naa(2, 17);
make_test_vpd_naa(2, 16);
+#if 0
/* SCSI Name string: EUI64, WWID size: 17 */
make_test_vpd_str(0, 20, 18)
make_test_vpd_str(0, 20, 17)
@@ -802,6 +805,7 @@ make_test_vpd_str(18, 20, 18)
make_test_vpd_str(18, 20, 17)
make_test_vpd_str(18, 20, 16)
make_test_vpd_str(18, 20, 15)
+#endif
static int test_vpd(void)
{
@@ -910,6 +914,7 @@ static int test_vpd(void)
cmocka_unit_test(test_vpd_naa_2_18),
cmocka_unit_test(test_vpd_naa_2_17),
cmocka_unit_test(test_vpd_naa_2_16),
+/*
cmocka_unit_test(test_vpd_str_0_20_18),
cmocka_unit_test(test_vpd_str_0_20_17),
cmocka_unit_test(test_vpd_str_0_20_16),
@@ -934,6 +939,7 @@ static int test_vpd(void)
cmocka_unit_test(test_vpd_str_18_20_17),
cmocka_unit_test(test_vpd_str_18_20_16),
cmocka_unit_test(test_vpd_str_18_20_15),
+*/
};
return cmocka_run_group_tests(tests, setup, teardown);
}

View file

@ -0,0 +1,129 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 5 Feb 2018 21:59:16 -0600
Subject: [PATCH] call start_waiter_thread() before setup_multipath()
If setup_multipath() is called before the waiter thread has started,
there is a window where a dm event can occur between when
setup_multipath() updates the device state and when the waiter thread
starts waiting for new events, causing the new event to be missed and
the multipath device to not get updated.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/main.c | 37 ++++++++++++++++++++-----------------
1 file changed, 20 insertions(+), 17 deletions(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index 94b2406..efc39d7 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -321,7 +321,7 @@ set_multipath_wwid (struct multipath * mpp)
}
static int
-update_map (struct multipath *mpp, struct vectors *vecs)
+update_map (struct multipath *mpp, struct vectors *vecs, int new_map)
{
int retries = 3;
char params[PARAMS_SIZE] = {0};
@@ -351,6 +351,12 @@ retry:
dm_lib_release();
fail:
+ if (new_map && (retries < 0 || start_waiter_thread(mpp, vecs))) {
+ condlog(0, "%s: failed to create new map", mpp->alias);
+ remove_map(mpp, vecs, 1);
+ return 1;
+ }
+
if (setup_multipath(vecs, mpp))
return 1;
@@ -395,12 +401,9 @@ add_map_without_path (struct vectors *vecs, char *alias)
vector_set_slot(vecs->mpvec, mpp);
- if (update_map(mpp, vecs) != 0) /* map removed */
+ if (update_map(mpp, vecs, 1) != 0) /* map removed */
return NULL;
- if (start_waiter_thread(mpp, vecs))
- goto out;
-
return mpp;
out:
remove_map(mpp, vecs, PURGE_VEC);
@@ -554,7 +557,7 @@ ev_add_map (char * dev, char * alias, struct vectors * vecs)
if (mpp->wait_for_udev > 1) {
condlog(2, "%s: performing delayed actions",
mpp->alias);
- if (update_map(mpp, vecs))
+ if (update_map(mpp, vecs, 0))
/* setup multipathd removed the map */
return 1;
}
@@ -865,6 +868,11 @@ retry:
}
dm_lib_release();
+ if ((mpp->action == ACT_CREATE ||
+ (mpp->action == ACT_NOTHING && start_waiter && !mpp->waiter)) &&
+ start_waiter_thread(mpp, vecs))
+ goto fail_map;
+
/*
* update our state from kernel regardless of create or reload
*/
@@ -873,11 +881,6 @@ retry:
sync_map_state(mpp);
- if ((mpp->action == ACT_CREATE ||
- (mpp->action == ACT_NOTHING && start_waiter && !mpp->waiter)) &&
- start_waiter_thread(mpp, vecs))
- goto fail_map;
-
if (retries >= 0) {
condlog(2, "%s [%s]: path added to devmap %s",
pp->dev, pp->dev_t, mpp->alias);
@@ -1479,7 +1482,8 @@ missing_uev_wait_tick(struct vectors *vecs)
if (mpp->wait_for_udev && --mpp->uev_wait_tick <= 0) {
timed_out = 1;
condlog(0, "%s: timeout waiting on creation uevent. enabling reloads", mpp->alias);
- if (mpp->wait_for_udev > 1 && update_map(mpp, vecs)) {
+ if (mpp->wait_for_udev > 1 &&
+ update_map(mpp, vecs, 0)) {
/* update_map removed map */
i--;
continue;
@@ -1511,7 +1515,7 @@ ghost_delay_tick(struct vectors *vecs)
condlog(0, "%s: timed out waiting for active path",
mpp->alias);
mpp->force_udev_reload = 1;
- if (update_map(mpp, vecs) != 0) {
+ if (update_map(mpp, vecs, 0) != 0) {
/* update_map removed map */
i--;
continue;
@@ -2169,14 +2173,13 @@ configure (struct vectors * vecs)
* start dm event waiter threads for these new maps
*/
vector_foreach_slot(vecs->mpvec, mpp, i) {
- if (setup_multipath(vecs, mpp)) {
- i--;
- continue;
- }
if (start_waiter_thread(mpp, vecs)) {
remove_map(mpp, vecs, 1);
i--;
+ continue;
}
+ if (setup_multipath(vecs, mpp))
+ i--;
}
return 0;
}
--
2.7.4

View file

@ -1,25 +0,0 @@
From 374755791536be4870ab2e93ae36549cbaaeb800 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 25 Mar 2022 18:12:06 -0500
Subject: [PATCH] RH: add scsi device handlers to modules-load.d
Make scsi_dh_alua scsi_dh_emc and scsi_dh_rdac get loaded in early boot.
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 03aee175..936a622f 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -16,7 +16,7 @@ READLINE :=
# List of scsi device handler modules to load on boot, e.g.
# SCSI_DH_MODULES_PRELOAD := scsi_dh_alua scsi_dh_rdac
-SCSI_DH_MODULES_PRELOAD :=
+SCSI_DH_MODULES_PRELOAD := scsi_dh_alua scsi_dh_emc scsi_dh_rdac
EXTRAVERSION := $(shell rev=$$(git rev-parse --short=7 HEAD 2>/dev/null); echo $${rev:+-g$$rev})

View file

@ -0,0 +1,155 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 5 Feb 2018 10:40:24 -0600
Subject: [PATCH] libmultipath: add helper functions
Add the ability to reset a vector without completely freeing it, and to
check the version of the device-mapper module. The existing version
checking code checks the version of a specific device mapper target, and
has been renamed for clarity's sake. These functions will be used in a
later patch.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 28 ++++++++++++++++++++++++----
libmultipath/devmapper.h | 3 ++-
libmultipath/vector.c | 16 ++++++++++++----
libmultipath/vector.h | 1 +
multipathd/main.c | 2 +-
5 files changed, 40 insertions(+), 10 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 573fc75..2960bf5 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -132,7 +132,27 @@ dm_lib_prereq (void)
}
int
-dm_drv_version (unsigned int * version, char * str)
+dm_drv_version(unsigned int *v)
+{
+ char buff[64];
+
+ v[0] = 0;
+ v[1] = 0;
+ v[2] = 0;
+
+ if (!dm_driver_version(buff, sizeof(buff))) {
+ condlog(0, "cannot get kernel dm version");
+ return 1;
+ }
+ if (sscanf(buff, "%u.%u.%u ", &v[0], &v[1], &v[2]) != 3) {
+ condlog(0, "invalid kernel dm version '%s'", buff);
+ return 1;
+ }
+ return 0;
+}
+
+int
+dm_tgt_version (unsigned int * version, char * str)
{
int r = 2;
struct dm_task *dmt;
@@ -179,13 +199,13 @@ out:
}
static int
-dm_drv_prereq (unsigned int *ver)
+dm_tgt_prereq (unsigned int *ver)
{
unsigned int minv[3] = {1, 0, 3};
unsigned int version[3] = {0, 0, 0};
unsigned int * v = version;
- if (dm_drv_version(v, TGT_MPATH)) {
+ if (dm_tgt_version(v, TGT_MPATH)) {
/* in doubt return not capable */
return 1;
}
@@ -210,7 +230,7 @@ static int dm_prereq(unsigned int *v)
{
if (dm_lib_prereq())
return 1;
- return dm_drv_prereq(v);
+ return dm_tgt_prereq(v);
}
static int libmp_dm_udev_sync = 0;
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 62e14d1..52d4af8 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -28,7 +28,8 @@ void dm_init(int verbosity);
void libmp_dm_init(void);
void libmp_udev_set_sync_support(int on);
struct dm_task *libmp_dm_task_create(int task);
-int dm_drv_version (unsigned int * version, char * str);
+int dm_drv_version (unsigned int * version);
+int dm_tgt_version (unsigned int * version, char * str);
int dm_simplecmd_flush (int, const char *, uint16_t);
int dm_simplecmd_noflush (int, const char *, uint16_t);
int dm_addmap_create (struct multipath *mpp, char *params);
diff --git a/libmultipath/vector.c b/libmultipath/vector.c
index 6266e0a..f741ae0 100644
--- a/libmultipath/vector.c
+++ b/libmultipath/vector.c
@@ -145,18 +145,26 @@ vector_repack(vector v)
vector_del_slot(v, i--);
}
-/* Free memory vector allocation */
-void
-vector_free(vector v)
+vector
+vector_reset(vector v)
{
if (!v)
- return;
+ return NULL;
if (v->slot)
FREE(v->slot);
v->allocated = 0;
v->slot = NULL;
+ return v;
+}
+
+/* Free memory vector allocation */
+void
+vector_free(vector v)
+{
+ if (!vector_reset(v))
+ return;
FREE(v);
}
diff --git a/libmultipath/vector.h b/libmultipath/vector.h
index 5cfd4d0..d69cd0b 100644
--- a/libmultipath/vector.h
+++ b/libmultipath/vector.h
@@ -45,6 +45,7 @@ typedef struct _vector *vector;
/* Prototypes */
extern vector vector_alloc(void);
extern void *vector_alloc_slot(vector v);
+vector vector_reset(vector v);
extern void vector_free(vector v);
extern void free_strvec(vector strvec);
extern void vector_set_slot(vector v, void *value);
diff --git a/multipathd/main.c b/multipathd/main.c
index efc39d7..2963bde 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -2228,7 +2228,7 @@ reconfigure (struct vectors * vecs)
/* Re-read any timezone changes */
tzset();
- dm_drv_version(conf->version, TGT_MPATH);
+ dm_tgt_version(conf->version, TGT_MPATH);
if (verbosity)
conf->verbosity = verbosity;
if (bindings_read_only)
--
2.7.4

View file

@ -1,26 +0,0 @@
From cc15379130e8aa068e97c64afd46be212b456d4f Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 15 Nov 2022 18:03:33 -0600
Subject: [PATCH] RH: compile with libreadline support
Since the license issue has been resolved, and there are problems with
the command completion with libedit, use libreadline.
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 936a622f..f475f70f 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -12,7 +12,7 @@
# Readline library to use, libedit, libreadline, or empty
# Caution: Using libreadline may make the multipathd binary undistributable,
# see https://github.com/opensvc/multipath-tools/issues/36
-READLINE :=
+READLINE := libreadline
# List of scsi device handler modules to load on boot, e.g.
# SCSI_DH_MODULES_PRELOAD := scsi_dh_alua scsi_dh_rdac

View file

@ -0,0 +1,643 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 6 Feb 2018 15:36:39 -0600
Subject: [PATCH] multipathd: RFC add new polling dmevents waiter thread
The current method of waiting for dmevents on multipath devices involves
creating a seperate thread for each device. This can become very
wasteful when there are large numbers of multipath devices. Also, since
multipathd needs to grab the vecs lock to update the devices, the
additional threads don't actually provide much parallelism.
The patch adds a new method of updating multipath devices on dmevents,
which uses the new device-mapper event polling interface. This means
that there is only one dmevent waiting thread which will wait for events
on all of the multipath devices. Currently the code to get the event
number from the list of device names and to re-arm the polling interface
is not in libdevmapper, so the patch does that work. Obviously, these
bits need to go into libdevmapper, so that multipathd can use a standard
interface.
I haven't touched any of the existing event waiting code, since event
polling was only added to device-mapper in version 4.37.0. multipathd
checks this version, and defaults to using the polling code if
device-mapper supports it. This can be overridden by running multipathd
with "-w", to force it to use the old event waiting code.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/Makefile | 3 +-
multipathd/dmevents.c | 396 ++++++++++++++++++++++++++++++++++++++++++++++++++
multipathd/dmevents.h | 13 ++
multipathd/main.c | 58 +++++++-
4 files changed, 461 insertions(+), 9 deletions(-)
create mode 100644 multipathd/dmevents.c
create mode 100644 multipathd/dmevents.h
diff --git a/multipathd/Makefile b/multipathd/Makefile
index 85f29a7..4c438f0 100644
--- a/multipathd/Makefile
+++ b/multipathd/Makefile
@@ -22,7 +22,8 @@ ifdef SYSTEMD
endif
endif
-OBJS = main.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o waiter.o
+OBJS = main.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o waiter.o \
+ dmevents.o
EXEC = multipathd
diff --git a/multipathd/dmevents.c b/multipathd/dmevents.c
new file mode 100644
index 0000000..a56c055
--- /dev/null
+++ b/multipathd/dmevents.c
@@ -0,0 +1,396 @@
+/*
+ * Copyright (c) 2004, 2005 Christophe Varoqui
+ * Copyright (c) 2005 Kiyoshi Ueda, NEC
+ * Copyright (c) 2005 Edward Goggin, EMC
+ * Copyright (c) 2005, 2018 Benjamin Marzinski, Redhat
+ */
+#include <unistd.h>
+#include <libdevmapper.h>
+#include <sys/mman.h>
+#include <pthread.h>
+#include <urcu.h>
+#include <poll.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <linux/dm-ioctl.h>
+#include <errno.h>
+
+#include "vector.h"
+#include "structs.h"
+#include "structs_vec.h"
+#include "devmapper.h"
+#include "debug.h"
+#include "dmevents.h"
+
+#ifndef DM_DEV_ARM_POLL
+#define DM_DEV_ARM_POLL _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD + 1, struct dm_ioctl)
+#endif
+
+enum event_actions {
+ EVENT_NOTHING,
+ EVENT_REMOVE,
+ EVENT_UPDATE,
+};
+
+struct dev_event {
+ char name[WWID_SIZE];
+ uint32_t evt_nr;
+ enum event_actions action;
+};
+
+struct dmevent_waiter {
+ int fd;
+ struct vectors *vecs;
+ vector events;
+ pthread_mutex_t events_lock;
+};
+
+static struct dmevent_waiter *waiter;
+
+int dmevent_poll_supported(void)
+{
+ unsigned int minv[3] = {4, 37, 0};
+ unsigned int v[3];
+
+ if (dm_drv_version(v))
+ return 0;
+
+ if (VERSION_GE(v, minv))
+ return 1;
+ return 0;
+}
+
+
+int alloc_dmevent_waiter(struct vectors *vecs)
+{
+ if (!vecs) {
+ condlog(0, "can't create waiter structure. invalid vectors");
+ goto fail;
+ }
+ waiter = (struct dmevent_waiter *)malloc(sizeof(struct dmevent_waiter));
+ if (!waiter) {
+ condlog(0, "failed to allocate waiter structure");
+ goto fail;
+ }
+ memset(waiter, 0, sizeof(struct dmevent_waiter));
+ waiter->events = vector_alloc();
+ if (!waiter->events) {
+ condlog(0, "failed to allocate waiter events vector");
+ goto fail_waiter;
+ }
+ waiter->fd = open("/dev/mapper/control", O_RDWR);
+ if (waiter->fd < 0) {
+ condlog(0, "failed to open /dev/mapper/control for waiter");
+ goto fail_events;
+ }
+ pthread_mutex_init(&waiter->events_lock, NULL);
+ waiter->vecs = vecs;
+
+ return 0;
+fail_events:
+ vector_free(waiter->events);
+fail_waiter:
+ free(waiter);
+fail:
+ waiter = NULL;
+ return -1;
+}
+
+void free_dmevent_waiter(void)
+{
+ struct dev_event *dev_evt;
+ int i;
+
+ if (!waiter)
+ return;
+ pthread_mutex_destroy(&waiter->events_lock);
+ close(waiter->fd);
+ vector_foreach_slot(waiter->events, dev_evt, i)
+ free(dev_evt);
+ vector_free(waiter->events);
+ free(waiter);
+ waiter = NULL;
+}
+
+static int arm_dm_event_poll(int fd)
+{
+ struct dm_ioctl dmi;
+ memset(&dmi, 0, sizeof(dmi));
+ dmi.version[0] = DM_VERSION_MAJOR;
+ dmi.version[1] = DM_VERSION_MINOR;
+ dmi.version[2] = DM_VERSION_PATCHLEVEL;
+ dmi.flags = 0x4;
+ dmi.data_start = offsetof(struct dm_ioctl, data);
+ dmi.data_size = sizeof(dmi);
+ return ioctl(fd, DM_DEV_ARM_POLL, &dmi);
+}
+
+/*
+ * As of version 4.37.0 device-mapper stores the event number in the
+ * dm_names structure after the name, when DM_DEVICE_LIST is called
+ */
+static uint32_t dm_event_nr(struct dm_names *n)
+{
+ return *(uint32_t *)(((uintptr_t)(strchr(n->name, 0) + 1) + 7) & ~7);
+}
+
+static int dm_get_events(void)
+{
+ struct dm_task *dmt;
+ struct dm_names *names;
+ struct dev_event *dev_evt;
+ int i;
+
+ if (!(dmt = libmp_dm_task_create(DM_DEVICE_LIST)))
+ return -1;
+
+ dm_task_no_open_count(dmt);
+
+ if (!dm_task_run(dmt))
+ goto fail;
+
+ if (!(names = dm_task_get_names(dmt)))
+ goto fail;
+
+ pthread_mutex_lock(&waiter->events_lock);
+ vector_foreach_slot(waiter->events, dev_evt, i)
+ dev_evt->action = EVENT_REMOVE;
+ while (names->dev) {
+ uint32_t event_nr;
+
+ if (!dm_is_mpath(names->name))
+ goto next;
+
+ event_nr = dm_event_nr(names);
+ vector_foreach_slot(waiter->events, dev_evt, i) {
+ if (!strcmp(dev_evt->name, names->name)) {
+ if (event_nr != dev_evt->evt_nr) {
+ dev_evt->evt_nr = event_nr;
+ dev_evt->action = EVENT_UPDATE;
+ } else
+ dev_evt->action = EVENT_NOTHING;
+ break;
+ }
+ }
+next:
+ if (!names->next)
+ break;
+ names = (void *)names + names->next;
+ }
+ pthread_mutex_unlock(&waiter->events_lock);
+ dm_task_destroy(dmt);
+ return 0;
+
+fail:
+ dm_task_destroy(dmt);
+ return -1;
+}
+
+/* You must call update_multipath() after calling this function, to
+ * deal with any events that came in before the device was added */
+int watch_dmevents(char *name)
+{
+ int event_nr;
+ struct dev_event *dev_evt, *old_dev_evt;
+ int i;
+
+ if (!dm_is_mpath(name)) {
+ condlog(0, "%s: not a multipath device. can't watch events",
+ name);
+ return -1;
+ }
+
+ if ((event_nr = dm_geteventnr(name)) < 0)
+ return -1;
+
+ dev_evt = (struct dev_event *)malloc(sizeof(struct dev_event));
+ if (!dev_evt) {
+ condlog(0, "%s: can't allocate event waiter structure", name);
+ return -1;
+ }
+
+ strncpy(dev_evt->name, name, WWID_SIZE);
+ dev_evt->name[WWID_SIZE - 1] = 0;
+ dev_evt->evt_nr = event_nr;
+ dev_evt->action = EVENT_NOTHING;
+
+ pthread_mutex_lock(&waiter->events_lock);
+ vector_foreach_slot(waiter->events, old_dev_evt, i){
+ if (!strcmp(dev_evt->name, old_dev_evt->name)) {
+ /* caller will be updating this device */
+ old_dev_evt->evt_nr = event_nr;
+ old_dev_evt->action = EVENT_NOTHING;
+ pthread_mutex_unlock(&waiter->events_lock);
+ condlog(2, "%s: already waiting for events on device",
+ name);
+ free(dev_evt);
+ return 0;
+ }
+ }
+ if (!vector_alloc_slot(waiter->events)) {
+ pthread_mutex_unlock(&waiter->events_lock);
+ free(dev_evt);
+ return -1;
+ }
+ vector_set_slot(waiter->events, dev_evt);
+ pthread_mutex_unlock(&waiter->events_lock);
+ return 0;
+}
+
+void unwatch_all_dmevents(void)
+{
+ struct dev_event *dev_evt;
+ int i;
+
+ pthread_mutex_lock(&waiter->events_lock);
+ vector_foreach_slot(waiter->events, dev_evt, i)
+ free(dev_evt);
+ vector_reset(waiter->events);
+ pthread_mutex_unlock(&waiter->events_lock);
+}
+
+static void unwatch_dmevents(char *name)
+{
+ struct dev_event *dev_evt;
+ int i;
+
+ pthread_mutex_lock(&waiter->events_lock);
+ vector_foreach_slot(waiter->events, dev_evt, i) {
+ if (!strcmp(dev_evt->name, name)) {
+ vector_del_slot(waiter->events, i);
+ free(dev_evt);
+ break;
+ }
+ }
+ pthread_mutex_unlock(&waiter->events_lock);
+}
+
+/*
+ * returns the reschedule delay
+ * negative means *stop*
+ */
+
+/* poll, arm, update, return */
+static int dmevent_loop (void)
+{
+ int r, i = 0;
+ struct pollfd pfd;
+ struct dev_event *dev_evt;
+
+ pfd.fd = waiter->fd;
+ pfd.events = POLLIN;
+ r = poll(&pfd, 1, -1);
+ if (r <= 0) {
+ condlog(0, "failed polling for dm events: %s", strerror(errno));
+ /* sleep 1s and hope things get better */
+ return 1;
+ }
+
+ if (arm_dm_event_poll(waiter->fd) != 0) {
+ condlog(0, "Cannot re-arm event polling: %s", strerror(errno));
+ /* sleep 1s and hope things get better */
+ return 1;
+ }
+
+ if (dm_get_events() != 0) {
+ condlog(0, "failed getting dm events: %s", strerror(errno));
+ /* sleep 1s and hope things get better */
+ return 1;
+ }
+
+ /*
+ * upon event ...
+ */
+
+ while (1) {
+ int done = 1;
+ struct dev_event curr_dev;
+ struct multipath *mpp;
+
+ pthread_mutex_lock(&waiter->events_lock);
+ vector_foreach_slot(waiter->events, dev_evt, i) {
+ if (dev_evt->action != EVENT_NOTHING) {
+ curr_dev = *dev_evt;
+ if (dev_evt->action == EVENT_REMOVE) {
+ vector_del_slot(waiter->events, i);
+ free(dev_evt);
+ } else
+ dev_evt->action = EVENT_NOTHING;
+ done = 0;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&waiter->events_lock);
+ if (done)
+ return 1;
+
+ condlog(3, "%s: devmap event #%i", curr_dev.name,
+ curr_dev.evt_nr);
+
+ /*
+ * event might be :
+ *
+ * 1) a table reload, which means our mpp structure is
+ * obsolete : refresh it through update_multipath()
+ * 2) a path failed by DM : mark as such through
+ * update_multipath()
+ * 3) map has gone away : stop the thread.
+ * 4) a path reinstate : nothing to do
+ * 5) a switch group : nothing to do
+ */
+ pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock);
+ lock(&waiter->vecs->lock);
+ pthread_testcancel();
+ r = 0;
+ if (curr_dev.action == EVENT_REMOVE) {
+ mpp = find_mp_by_alias(waiter->vecs->mpvec,
+ curr_dev.name);
+ if (mpp)
+ remove_map(mpp, waiter->vecs, 1);
+ } else
+ r = update_multipath(waiter->vecs, curr_dev.name, 1);
+ lock_cleanup_pop(&waiter->vecs->lock);
+
+ if (r) {
+ condlog(2, "%s: stopped watching dmevents",
+ curr_dev.name);
+ unwatch_dmevents(curr_dev.name);
+ }
+ }
+ condlog(0, "dmevent waiter thread unexpectedly quit");
+ return -1; /* never reach there */
+}
+
+static void rcu_unregister(void *param)
+{
+ rcu_unregister_thread();
+}
+
+void *wait_dmevents (void *unused)
+{
+ int r;
+
+
+ if (!waiter) {
+ condlog(0, "dmevents waiter not intialized");
+ return NULL;
+ }
+
+ pthread_cleanup_push(rcu_unregister, NULL);
+ rcu_register_thread();
+ mlockall(MCL_CURRENT | MCL_FUTURE);
+
+ while (1) {
+ r = dmevent_loop();
+
+ if (r < 0)
+ break;
+
+ sleep(r);
+ }
+
+ pthread_cleanup_pop(1);
+ return NULL;
+}
diff --git a/multipathd/dmevents.h b/multipathd/dmevents.h
new file mode 100644
index 0000000..569e855
--- /dev/null
+++ b/multipathd/dmevents.h
@@ -0,0 +1,13 @@
+#ifndef _DMEVENTS_H
+#define _DMEVENTS_H
+
+#include "structs_vec.h"
+
+int dmevent_poll_supported(void);
+int alloc_dmevent_waiter(struct vectors *vecs);
+void free_dmevent_waiter(void);
+int watch_dmevents(char *name);
+void unwatch_all_dmevents(void);
+void *wait_dmevents (void *unused);
+
+#endif /* _DMEVENTS_H */
diff --git a/multipathd/main.c b/multipathd/main.c
index 2963bde..6dabf2c 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -82,6 +82,7 @@ static int use_watchdog;
#include "cli_handlers.h"
#include "lock.h"
#include "waiter.h"
+#include "dmevents.h"
#include "io_err_stat.h"
#include "wwids.h"
#include "../third-party/valgrind/drd.h"
@@ -108,6 +109,7 @@ int uxsock_timeout;
int verbosity;
int bindings_read_only;
int ignore_new_devs;
+int poll_dmevents = 1;
enum daemon_status running_state = DAEMON_INIT;
pid_t daemon_pid;
pthread_mutex_t config_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -288,11 +290,23 @@ switch_pathgroup (struct multipath * mpp)
mpp->alias, mpp->bestpg);
}
+static int
+wait_for_events(struct multipath *mpp, struct vectors *vecs)
+{
+ if (poll_dmevents)
+ return watch_dmevents(mpp->alias);
+ else
+ return start_waiter_thread(mpp, vecs);
+}
+
static void
remove_map_and_stop_waiter(struct multipath *mpp, struct vectors *vecs,
int purge_vec)
{
- stop_waiter_thread(mpp, vecs);
+ /* devices are automatically removed by the dmevent polling code,
+ * so they don't need to be manually removed here */
+ if (!poll_dmevents)
+ stop_waiter_thread(mpp, vecs);
remove_map(mpp, vecs, purge_vec);
}
@@ -305,8 +319,12 @@ remove_maps_and_stop_waiters(struct vectors *vecs)
if (!vecs)
return;
- vector_foreach_slot(vecs->mpvec, mpp, i)
- stop_waiter_thread(mpp, vecs);
+ if (!poll_dmevents) {
+ vector_foreach_slot(vecs->mpvec, mpp, i)
+ stop_waiter_thread(mpp, vecs);
+ }
+ else
+ unwatch_all_dmevents();
remove_maps(vecs);
}
@@ -351,7 +369,7 @@ retry:
dm_lib_release();
fail:
- if (new_map && (retries < 0 || start_waiter_thread(mpp, vecs))) {
+ if (new_map && (retries < 0 || wait_for_events(mpp, vecs))) {
condlog(0, "%s: failed to create new map", mpp->alias);
remove_map(mpp, vecs, 1);
return 1;
@@ -870,7 +888,7 @@ retry:
if ((mpp->action == ACT_CREATE ||
(mpp->action == ACT_NOTHING && start_waiter && !mpp->waiter)) &&
- start_waiter_thread(mpp, vecs))
+ wait_for_events(mpp, vecs))
goto fail_map;
/*
@@ -2173,7 +2191,7 @@ configure (struct vectors * vecs)
* start dm event waiter threads for these new maps
*/
vector_foreach_slot(vecs->mpvec, mpp, i) {
- if (start_waiter_thread(mpp, vecs)) {
+ if (wait_for_events(mpp, vecs)) {
remove_map(mpp, vecs, 1);
i--;
continue;
@@ -2414,7 +2432,7 @@ set_oom_adj (void)
static int
child (void * param)
{
- pthread_t check_thr, uevent_thr, uxlsnr_thr, uevq_thr;
+ pthread_t check_thr, uevent_thr, uxlsnr_thr, uevq_thr, dmevent_thr;
pthread_attr_t log_attr, misc_attr, uevent_attr;
struct vectors * vecs;
struct multipath * mpp;
@@ -2476,6 +2494,8 @@ child (void * param)
goto failed;
}
+ if (poll_dmevents)
+ poll_dmevents = dmevent_poll_supported();
setlogmask(LOG_UPTO(conf->verbosity + 3));
envp = getenv("LimitNOFILE");
@@ -2542,6 +2562,19 @@ child (void * param)
init_path_check_interval(vecs);
+ if (poll_dmevents) {
+ if (alloc_dmevent_waiter(vecs)) {
+ condlog(0, "failed to allocate dmevents waiter info");
+ goto failed;
+ }
+ if ((rc = pthread_create(&dmevent_thr, &misc_attr,
+ wait_dmevents, NULL))) {
+ condlog(0, "failed to create dmevent waiter thread: %d",
+ rc);
+ goto failed;
+ }
+ }
+
/*
* Start uevent listener early to catch events
*/
@@ -2615,11 +2648,15 @@ child (void * param)
pthread_cancel(uevent_thr);
pthread_cancel(uxlsnr_thr);
pthread_cancel(uevq_thr);
+ if (poll_dmevents)
+ pthread_cancel(dmevent_thr);
pthread_join(check_thr, NULL);
pthread_join(uevent_thr, NULL);
pthread_join(uxlsnr_thr, NULL);
pthread_join(uevq_thr, NULL);
+ if (poll_dmevents)
+ pthread_join(dmevent_thr, NULL);
stop_io_err_stat_thread();
@@ -2634,6 +2671,8 @@ child (void * param)
cleanup_checkers();
cleanup_prio();
+ if (poll_dmevents)
+ free_dmevent_waiter();
dm_lib_release();
dm_lib_exit();
@@ -2765,7 +2804,7 @@ main (int argc, char *argv[])
udev = udev_new();
libmp_udev_set_sync_support(0);
- while ((arg = getopt(argc, argv, ":dsv:k::Bn")) != EOF ) {
+ while ((arg = getopt(argc, argv, ":dsv:k::Bniw")) != EOF ) {
switch(arg) {
case 'd':
foreground = 1;
@@ -2799,6 +2838,9 @@ main (int argc, char *argv[])
case 'n':
ignore_new_devs = 1;
break;
+ case 'w':
+ poll_dmevents = 0;
+ break;
default:
fprintf(stderr, "Invalid argument '-%c'\n",
optopt);
--
2.7.4

View file

@ -1,186 +0,0 @@
From 2ef5bd86052ba0b22f4d3a16e69cdf268d90a53a Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 7 Jul 2023 15:25:59 -0500
Subject: [PATCH] RH: Add mpathcleanup
mpathcleanup is a program that will remove a multipath device as well as
all of the scsi path devices that make it up.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/Makefile | 2 +
multipath/mpathcleanup | 145 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 147 insertions(+)
create mode 100755 multipath/mpathcleanup
diff --git a/multipath/Makefile b/multipath/Makefile
index 3dc241cc..47e82234 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -25,6 +25,7 @@ install:
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
$(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
$(Q)$(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/
+ $(Q)$(INSTALL_PROGRAM) -m 755 mpathcleanup $(DESTDIR)$(bindir)/
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 99-z-dm-mpath-late.rules $(DESTDIR)$(udevrulesdir)
@@ -49,6 +50,7 @@ endif
uninstall:
$(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC)
$(Q)$(RM) $(DESTDIR)$(bindir)/mpathconf
+ $(Q)$(RM) $(DESTDIR)$(bindir)/mpathcleanup
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/99-z-dm-mpath-late.rules
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf
diff --git a/multipath/mpathcleanup b/multipath/mpathcleanup
new file mode 100755
index 00000000..6fd921e4
--- /dev/null
+++ b/multipath/mpathcleanup
@@ -0,0 +1,145 @@
+#!/bin/bash
+#
+# Copyright (C) 2023 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
+
+unset PROGRAM FLUSH DEVICE DEVNAME MAJOR MINOR PATHDEVS PATHDEV HAVE_MULTIPATHD QUEUEING
+
+function usage
+{
+ echo "usage: $PROGRAM [-h] [--flush] <device>"
+ echo ""
+ echo "remove a multipath device and its scsi path devices"
+ echo ""
+ echo "options:"
+ echo " -h, --help show this help message and exit"
+ echo " --flush disable queuing on the multipath device and"
+ echo " flush the path devices before removing"
+}
+
+function parse_args
+{
+ while [ -n "$1" ]; do
+ case $1 in
+ --flush)
+ FLUSH=1
+ shift
+ ;;
+ --help | -h)
+ usage
+ exit 1
+ ;;
+ *)
+ if [ -n "$DEVICE" ]; then
+ usage
+ exit 1
+ fi
+ DEVICE=$1
+ shift
+ ;;
+ esac
+ done
+}
+
+function validate_device
+{
+ if [ -z "$DEVICE" ]; then
+ usage
+ exit 1
+ fi
+ if [[ "$DEVICE" =~ ^[[:digit:]]+:[[:digit:]]+$ ]]; then
+ MAJOR=${DEVICE%%:*}
+ MINOR=${DEVICE##*:}
+ DEVNAME=`dmsetup ls --target multipath | grep "($MAJOR, $MINOR)$" | awk '{print $1}'`
+ else
+ DEVNAME=`dmsetup ls --target multipath | awk '{print $1}' | grep "^$DEVICE$"`
+ fi
+ if [ -z "$DEVNAME" ]; then
+ DEVNAME=`multipath -v 1 -l $DEVICE 2>/dev/null`
+ if [ -z "$DEVNAME" ]; then
+ echo "$DEVICE is not a multipath device"
+ exit 1
+ fi
+ # verify that this is not a native nvme multipath device
+ dmsetup ls --target multipath | awk '{print $1}' | grep -q "^$DEVNAME$"
+ if test $? -eq 1; then
+ echo "$DEVICE is not a device-mapper multipath device"
+ exit 1
+ fi
+ fi
+ if [ -z "$MINOR" ]; then
+ MINOR=`dmsetup info -c --noheadings -o minor $DEVNAME`
+ fi
+}
+
+function get_paths
+{
+ PATHDEVS=`ls /sys/block/dm-$MINOR/slaves`
+ for PATHDEV in $PATHDEVS; do
+ if [[ ! "$PATHDEV" =~ ^sd[a-z]+$ ]]; then
+ echo "$PATHDEV is not a scsi device. $PROGRAM only works with scsi devices"
+ exit 1
+ fi
+ done
+}
+
+function remove_devs
+{
+ pidof multipathd > /dev/null
+ HAVE_MULTIPATHD=$?
+ multipath -v2 -l "$DEVNAME" | grep features | grep -q queue_if_no_path
+ QUEUEING=$?
+ if [ -n "$FLUSH" ] && [ "$QUEUEING" -eq 0 ]; then
+ if test $HAVE_MULTIPATHD -eq 0; then
+ multipathd disablequeueing map "$DEVNAME" > /dev/null
+ else
+ dmsetup message "$DEVNAME" 0 fail_if_no_path
+ fi
+ sleep 1
+ fi
+ if test $HAVE_MULTIPATHD -eq 0; then
+ multipath -f "$DEVNAME"
+ else
+ multipathd -Df "$DEVNAME"
+ fi
+ if test $? -eq 1; then
+ echo "$DEVICE cannot be removed"
+ exit 1
+ fi
+ for PATHDEV in $PATHDEVS; do
+ if [ -n "$FLUSH" ]; then
+ blockdev --flushbufs /dev/"$PATHDEV"
+ fi
+ echo 1 > /sys/block/"$PATHDEV"/device/delete
+ done
+}
+
+function verify_removal
+{
+ multipath -v 1 -d $DEVNAME | grep -q "^$DEVNAME$"
+ if test $? -eq 0; then
+ echo "$DEVICE removed but path devices still exist"
+ exit 1
+ fi
+ multipath -v 1 -l $DEVNAME | grep -q "^$DEVNAME$"
+ if test $? -eq 0; then
+ echo "$DEVICE removal succeeded, but device still exists"
+ exit 1
+ fi
+}
+
+PROGRAM="$0"
+parse_args "$@"
+validate_device
+get_paths
+remove_devs
+verify_removal

View file

@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Sat, 13 Jan 2018 22:19:21 +0100
Subject: [PATCH] libmultipath: condlog: log to stderr
Calling 'multipath' might result in various error messages, all
of which should be directed to stderr.
Having them intermixed with the actual output on stdout makes
parsing really hard.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/debug.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libmultipath/debug.c b/libmultipath/debug.c
index f89b264..f95a3e5 100644
--- a/libmultipath/debug.c
+++ b/libmultipath/debug.c
@@ -37,9 +37,9 @@ void dlog (int sink, int prio, const char * fmt, ...)
"%b %d %H:%M:%S", tb);
buff[sizeof(buff)-1] = '\0';
- fprintf(stdout, "%s | ", buff);
+ fprintf(stderr, "%s | ", buff);
}
- vfprintf(stdout, fmt, ap);
+ vfprintf(stderr, fmt, ap);
}
else
log_safe(prio + 3, fmt, ap);
--
2.7.4

View file

@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Sat, 13 Jan 2018 22:19:32 +0100
Subject: [PATCH] multipathd: fix compiler warning for uev_pathfail_check
gcc7 spits out an indentation warning for this function.
Fixes: 8392431 "multipath-tools: check null path before handle path-failed event"
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index 6dabf2c..596654c 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1142,8 +1142,8 @@ uev_pathfail_check(struct uevent *uev, struct vectors *vecs)
lock(&vecs->lock);
pthread_testcancel();
pp = find_path_by_devt(vecs->pathvec, devt);
- if (!pp)
- goto out_lock;
+ if (!pp)
+ goto out_lock;
r = io_err_stat_handle_pathfail(pp);
if (r)
condlog(3, "io_err_stat: %s: cannot handle pathfail uevent",
--
2.7.4

View file

@ -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 d953f5e..5145909 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 468c056..dda5565 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.7.4

View file

@ -0,0 +1,70 @@
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 | 15 ++++++---------
multipath/multipath.conf.5 | 4 ----
2 files changed, 6 insertions(+), 13 deletions(-)
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
index ee396e2..19d4697 100644
--- a/libmultipath/blacklist.c
+++ b/libmultipath/blacklist.c
@@ -181,12 +181,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 (_blacklist_device(conf->blist_device, hwe->vendor,
@@ -390,9 +384,12 @@ filter_property(struct config * conf, struct udev_device * udev)
* This is the inverse of the 'normal' matching;
* the environment variable _has_ to match.
*/
- log_filter(devname, NULL, NULL, NULL, NULL,
- MATCH_PROPERTY_BLIST_MISSING);
- return MATCH_PROPERTY_BLIST_MISSING;
+ if (VECTOR_SIZE(conf->elist_property)) {
+ log_filter(devname, NULL, NULL, NULL, NULL,
+ MATCH_PROPERTY_BLIST_MISSING);
+ return MATCH_PROPERTY_BLIST_MISSING;
+ }
+ return 0;
}
void
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index ab151e7..2201d7f 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1114,10 +1114,6 @@ The \fIWorld Wide Identification\fR of a device.
.TP
.B property
Regular expression of the udev property to be whitelisted.
-.RS
-.TP
-The default is: \fB(SCSI_IDENT_|ID_WWN)\fR
-.RE
.TP
.B device
Subsection for the device description. This subsection recognizes the
--
2.7.4

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 3d6a24c..27826fa 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 (struct hwentry *hwe1, struct hwentry *hwe2)
@@ -656,6 +657,20 @@ load_config (char * file)
factorize_hwtable(conf->hwtable, builtin_hwtable_size);
}
+ } 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 a20ac2a..21a3bbd 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 bc1a852..2bc0348 100644
--- a/multipath/multipath.rules
+++ b/multipath/multipath.rules
@@ -7,6 +7,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 5c96680..0515211 100644
--- a/multipathd/multipathd.8
+++ b/multipathd/multipathd.8
@@ -39,6 +39,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 fd66cf6..fafd088 100644
--- a/multipathd/multipathd.service
+++ b/multipathd/multipathd.service
@@ -4,6 +4,7 @@ Wants=systemd-udev-trigger.service systemd-udev-settle.service
Before=iscsi.service iscsid.service lvm2-lvmetad.service lvm2-activation-early.service
Before=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.7.4

View file

@ -0,0 +1,50 @@
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 | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 5145909..0b4ee17 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -82,13 +82,21 @@ TEST_CC_OPTION = $(shell \
echo "$(2)"; \
fi)
-STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)
-
-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 \
- -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
CFLAGS := $(OPTFLAGS) -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \
$(CFLAGS)
--
2.7.4

648
0019-RH-add-mpathconf.patch Normal file
View file

@ -0,0 +1,648 @@
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 | 1 +
multipath/Makefile | 5 +
multipath/mpathconf | 464 ++++++++++++++++++++++++++++++++++++++++++++++++++
multipath/mpathconf.8 | 101 +++++++++++
4 files changed, 571 insertions(+)
create mode 100644 multipath/mpathconf
create mode 100644 multipath/mpathconf.8
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 27826fa..9bf4fb7 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -659,6 +659,7 @@ load_config (char * file)
} else {
condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
+ condlog(0, "You can run /sbin/mpathconf to create or modify /etc/multipath.conf");
if (conf->blist_devnode == NULL) {
conf->blist_devnode = vector_alloc();
if (!conf->blist_devnode) {
diff --git a/multipath/Makefile b/multipath/Makefile
index dda5565..d35127a 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -18,10 +18,12 @@ $(EXEC): $(OBJS)
$(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:
$(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..4cd3267
--- /dev/null
+++ b/multipath/mpathconf.8
@@ -0,0 +1,101 @@
+.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.
+
+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.
+.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 --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.
+.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.7.4

View file

@ -0,0 +1,166 @@
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 | 5 ++++-
multipathd/multipathd.service | 1 +
5 files changed, 58 insertions(+), 3 deletions(-)
diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
index bc70a27..88bb72b 100644
--- a/libmultipath/wwids.c
+++ b/libmultipath/wwids.c
@@ -321,3 +321,47 @@ remember_wwid(char *wwid)
condlog(4, "wwid %s already in wwids file", wwid);
return 0;
}
+
+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 9527012..b665232 100644
--- a/libmultipath/wwids.h
+++ b/libmultipath/wwids.h
@@ -17,5 +17,6 @@ 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);
#endif /* _WWIDS_H */
diff --git a/multipath/main.c b/multipath/main.c
index d2415a9..ff570ac 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -102,7 +102,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\n", progname);
@@ -116,6 +116,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"
@@ -602,7 +604,7 @@ main (int argc, char *argv[])
exit(1);
multipath_conf = conf;
conf->retrigger_tries = 0;
- while ((arg = getopt(argc, argv, ":adcChl::FfM:v:p:b:BrR:itquUwW")) != EOF ) {
+ while ((arg = getopt(argc, argv, ":aAdcChl::FfM:v:p:b:BrR:itquUwW")) != EOF ) {
switch(arg) {
case 1: printf("optarg : %s\n",optarg);
break;
@@ -669,6 +671,10 @@ main (int argc, char *argv[])
case 't':
r = dump_config(conf);
goto out_free_config;
+ case 'A':
+ if (remember_cmdline_wwid() != 0)
+ exit(1);
+ exit(0);
case 'h':
usage(argv[0]);
exit(0);
diff --git a/multipath/multipath.8 b/multipath/multipath.8
index 56f8703..9fc2317 100644
--- a/multipath/multipath.8
+++ b/multipath/multipath.8
@@ -25,7 +25,7 @@ multipath \- Device mapper target autoconfig.
.RB [\| \-b\ \c
.IR bindings_file \|]
.RB [\| \-d \|]
-.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-C | \-q | \-r | \-i | \-a | \-u | \-U | \-w | \-W \|]
+.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-C | \-q | \-r | \-i | \-a | \-A | \-u | \-U | \-w | \-W \|]
.RB [\| \-p\ \c
.IR failover | multibus | group_by_serial | group_by_prio | group_by_node_name \|]
.RB [\| \-R\ \c
@@ -128,6 +128,9 @@ Add the WWID for the specified device to the WWIDs file.
Check if the device specified in the program environment should be
a path in a multipath device.
.
+.B \-A
+add wwids from any kernel command line mpath.wwid parameters to the wwids file
+.
.TP
.B \-U
Check if the device specified in the program environment is a multipath device
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
index fafd088..a623a3f 100644
--- 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
--
2.7.4

View file

@ -0,0 +1,156 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 24 Apr 2017 09:39:57 -0500
Subject: [PATCH] RH: trigger change uevent on new device creation
When multipath first sees a path device with user_friendly names
enabled, it can't know if the device should be multipathed. This means
that it will not claim the device in udev. If the device is eventually
multipathed, multipath should trigger a change uevent to update the udev
database to claim the device.
This also reverts commit 64e27ec066a001012f44550f095c93443e91d845 and
commit ffbb886a8a16cb063d669cd76a1e656fd3ec8c4b.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/configure.c | 26 ++++++++++++++++++++++++--
libmultipath/configure.h | 1 +
libmultipath/wwids.c | 4 ++--
multipath/main.c | 12 +-----------
multipathd/main.c | 7 ++-----
5 files changed, 30 insertions(+), 20 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 22c11a2..7011ef7 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -427,6 +427,28 @@ trigger_udev_change(const struct multipath *mpp)
udev_device_unref(udd);
}
+void
+trigger_paths_udev_change(const struct multipath *mpp)
+{
+ struct pathgroup * pgp;
+ struct path * pp;
+ int i, j;
+
+ if (!mpp || !mpp->pg)
+ return;
+
+ vector_foreach_slot (mpp->pg, pgp, i) {
+ if (!pgp->paths)
+ continue;
+ vector_foreach_slot(pgp->paths, pp, j) {
+ if (!pp->udev)
+ continue;
+ sysfs_attr_set_value(pp->udev, "uevent", "change",
+ strlen("change"));
+ }
+ }
+}
+
static int
is_mpp_known_to_udev(const struct multipath *mpp)
{
@@ -821,8 +843,8 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
* succeeded
*/
mpp->force_udev_reload = 0;
- if (mpp->action == ACT_CREATE)
- remember_wwid(mpp->wwid);
+ if (mpp->action == ACT_CREATE && remember_wwid(mpp->wwid) == 1)
+ trigger_paths_udev_change(mpp);
if (!is_daemon) {
/* multipath client mode */
dm_switchgroup(mpp->alias, mpp->bestpg);
diff --git a/libmultipath/configure.h b/libmultipath/configure.h
index 0ffc28e..09603ba 100644
--- a/libmultipath/configure.h
+++ b/libmultipath/configure.h
@@ -37,3 +37,4 @@ int get_refwwid (enum mpath_cmds cmd, char * dev, enum devtypes dev_type,
int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh, int is_daemon);
int sysfs_get_host_adapter_name(struct path *pp, char *adapter_name);
struct udev_device *get_udev_device(const char *dev, enum devtypes dev_type);
+void trigger_paths_udev_change(const struct multipath *mpp);
diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
index 88bb72b..249c6c1 100644
--- a/libmultipath/wwids.c
+++ b/libmultipath/wwids.c
@@ -319,7 +319,7 @@ remember_wwid(char *wwid)
condlog(3, "wrote wwid %s to wwids file", wwid);
else
condlog(4, "wwid %s already in wwids file", wwid);
- return 0;
+ return ret;
}
int remember_cmdline_wwid(void)
@@ -353,7 +353,7 @@ int remember_cmdline_wwid(void)
next++;
}
if (strlen(ptr)) {
- if (remember_wwid(ptr) != 0)
+ if (remember_wwid(ptr) < 0)
ret = -1;
}
else {
diff --git a/multipath/main.c b/multipath/main.c
index ff570ac..ae6b06e 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -416,7 +416,7 @@ configure (struct config *conf, enum mpath_cmds cmd,
}
if (cmd == CMD_ADD_WWID) {
r = remember_wwid(refwwid);
- if (r == 0)
+ if (r >= 0)
printf("wwid '%s' added\n", refwwid);
else
printf("failed adding '%s' to wwids file\n",
@@ -712,16 +712,6 @@ main (int argc, char *argv[])
}
}
- /*
- * FIXME: new device detection with find_multipaths currently
- * doesn't work reliably.
- */
- if (cmd == CMD_VALID_PATH &&
- conf->find_multipaths && conf->ignore_wwids) {
- condlog(2, "ignoring -i flag because find_multipath is set in multipath.conf");
- conf->ignore_wwids = 0;
- }
-
if (getuid() != 0) {
fprintf(stderr, "need to be root\n");
exit(1);
diff --git a/multipathd/main.c b/multipathd/main.c
index 596654c..c860e88 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -2172,7 +2172,8 @@ configure (struct vectors * vecs)
sync_maps_state(mpvec);
vector_foreach_slot(mpvec, mpp, i){
- remember_wwid(mpp->wwid);
+ if (remember_wwid(mpp->wwid) == 1)
+ trigger_paths_udev_change(mpp);
update_map_pr(mpp);
}
@@ -2251,10 +2252,6 @@ reconfigure (struct vectors * vecs)
conf->verbosity = verbosity;
if (bindings_read_only)
conf->bindings_read_only = bindings_read_only;
- if (conf->find_multipaths) {
- condlog(2, "find_multipaths is set: -n is implied");
- ignore_new_devs = 1;
- }
if (ignore_new_devs)
conf->ignore_new_devs = ignore_new_devs;
uxsock_timeout = conf->uxsock_timeout;
--
2.7.4

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 e52f1f7..31897cd 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -52,6 +52,21 @@ set_str(vector strvec, void *ptr)
}
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)
{
char * buff;
@@ -1200,7 +1215,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; \
\
@@ -1216,7 +1231,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; \
\
@@ -1311,16 +1326,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 c47d891..74b4efe 100644
--- a/libmultipath/parser.c
+++ b/libmultipath/parser.c
@@ -346,6 +346,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 519b805..96f40bd 100644
--- a/libmultipath/parser.h
+++ b/libmultipath/parser.h
@@ -73,6 +73,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.7.4

View file

@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 26 Jun 2018 16:45:48 -0500
Subject: [PATCH] libmutipath: remove unused IDE bus type
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/structs.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index bfa660a..3824f75 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -52,7 +52,6 @@ enum failback_mode {
enum sysfs_buses {
SYSFS_BUS_UNDEF,
SYSFS_BUS_SCSI,
- SYSFS_BUS_IDE,
SYSFS_BUS_CCW,
SYSFS_BUS_CCISS,
SYSFS_BUS_RBD,
--
2.7.4

View file

@ -0,0 +1,92 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 26 Jun 2018 17:04:57 -0500
Subject: [PATCH] multipathd: add new protocol path wildcard
This patch adds a new path wildcard 'P', that will print the path's
protocol. For scsi devices, it will additionally print the transport
protocol being used.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/print.c | 43 +++++++++++++++++++++++++++++++++++++++++++
libmultipath/print.h | 2 ++
2 files changed, 45 insertions(+)
diff --git a/libmultipath/print.c b/libmultipath/print.c
index 65a9824..00739bc 100644
--- a/libmultipath/print.c
+++ b/libmultipath/print.c
@@ -623,6 +623,48 @@ snprint_path_checker (char * buff, size_t len, struct path * pp)
return snprint_str(buff, len, c->name);
}
+/* if you add a protocol string bigger than "scsi:unspec" you must
+ * also change PROTOCOL_BUF_SIZE */
+int
+snprint_path_protocol(char * buff, size_t len, struct path * pp)
+{
+ switch (pp->bus) {
+ case SYSFS_BUS_SCSI:
+ switch (pp->sg_id.proto_id) {
+ case SCSI_PROTOCOL_FCP:
+ return snprintf(buff, len, "scsi:fcp");
+ case SCSI_PROTOCOL_SPI:
+ return snprintf(buff, len, "scsi:spi");
+ case SCSI_PROTOCOL_SSA:
+ return snprintf(buff, len, "scsi:ssa");
+ case SCSI_PROTOCOL_SBP:
+ return snprintf(buff, len, "scsi:sbp");
+ case SCSI_PROTOCOL_SRP:
+ return snprintf(buff, len, "scsi:srp");
+ case SCSI_PROTOCOL_ISCSI:
+ return snprintf(buff, len, "scsi:iscsi");
+ case SCSI_PROTOCOL_SAS:
+ return snprintf(buff, len, "scsi:sas");
+ case SCSI_PROTOCOL_ADT:
+ return snprintf(buff, len, "scsi:adt");
+ case SCSI_PROTOCOL_ATA:
+ return snprintf(buff, len, "scsi:ata");
+ case SCSI_PROTOCOL_UNSPEC:
+ default:
+ return snprintf(buff, len, "scsi:unspec");
+ }
+ case SYSFS_BUS_CCW:
+ return snprintf(buff, len, "ccw");
+ case SYSFS_BUS_CCISS:
+ return snprintf(buff, len, "cciss");
+ case SYSFS_BUS_NVME:
+ return snprintf(buff, len, "nvme");
+ case SYSFS_BUS_UNDEF:
+ default:
+ return snprintf(buff, len, "undef");
+ }
+}
+
struct multipath_data mpd[] = {
{'n', "name", 0, snprint_name},
{'w', "uuid", 0, snprint_multipath_uuid},
@@ -669,6 +711,7 @@ struct path_data pd[] = {
{'R', "host WWPN", 0, snprint_host_wwpn},
{'r', "target WWPN", 0, snprint_tgt_wwpn},
{'a', "host adapter", 0, snprint_host_adapter},
+ {'P', "protocol", 0, snprint_path_protocol},
{0, NULL, 0 , NULL}
};
diff --git a/libmultipath/print.h b/libmultipath/print.h
index b8c3436..d166b5c 100644
--- a/libmultipath/print.h
+++ b/libmultipath/print.h
@@ -117,6 +117,8 @@ int snprint_host_wwnn (char *, size_t, struct path *);
int snprint_host_wwpn (char *, size_t, struct path *);
int snprint_tgt_wwnn (char *, size_t, struct path *);
int snprint_tgt_wwpn (char *, size_t, struct path *);
+#define PROTOCOL_BUF_SIZE sizeof("scsi:unspec")
+int snprint_path_protocol(char *, size_t, struct path *);
void print_multipath_topology (struct multipath * mpp, int verbosity);
void print_path (struct path * pp, char * style);
--
2.7.4

View file

@ -0,0 +1,437 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 28 Jun 2018 13:16:11 -0500
Subject: [PATCH] libmultipath: add "protocol" blacklist option.
Multiple users have requested an easy way to setup blacklists that do
things such as blacklisting all non FC and iSCSI devices. Currently
there is no easy way to do this, without knowing in advance what the
devices are. Looking into the udev property values, I didn't see a
consistent set of values that would worked for all the different types
of requests like this (which would have allowed us to solve this by
extending the "property" blacklist option to allow comparing values,
instead of just keywords).
Instead I've opted to allow multipath to blacklist/whitelist devices
by the protocol strings printed by "multipathd: add new protocol path
wildcard". This check happens after multipath checks the "device"
keyword, and before it checks wwid. This gives users an easily
understandible method to set up these types of blacklists, without
needing to know the exact arrays being used.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/blacklist.c | 51 ++++++++++++++++++++++++++++++++++++++--------
libmultipath/blacklist.h | 3 +++
libmultipath/config.c | 15 ++++++++++++++
libmultipath/config.h | 2 ++
libmultipath/dict.c | 14 +++++++++++--
libmultipath/discovery.c | 5 +++--
libmultipath/print.c | 31 ++++++++++++++++++++++++++++
multipath/multipath.conf.5 | 15 ++++++++++++++
8 files changed, 124 insertions(+), 12 deletions(-)
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
index 19d4697..41dbf01 100644
--- a/libmultipath/blacklist.c
+++ b/libmultipath/blacklist.c
@@ -12,6 +12,8 @@
#include "structs.h"
#include "config.h"
#include "blacklist.h"
+#include "structs_vec.h"
+#include "print.h"
int store_ble(vector blist, char * str, int origin)
{
@@ -213,12 +215,14 @@ setup_default_blist (struct config * conf)
condlog(3, "%s: %s %s %s", dev, (M), wwid, (S)); \
else if (env) \
condlog(3, "%s: %s %s %s", dev, (M), env, (S)); \
+ else if (protocol) \
+ condlog(3, "%s: %s %s %s", dev, (M), protocol, (S)); \
else \
condlog(3, "%s: %s %s", dev, (M), (S))
void
log_filter (const char *dev, char *vendor, char *product, char *wwid,
- const char *env, int r)
+ const char *env, const char *protocol, int r)
{
/*
* Try to sort from most likely to least.
@@ -238,6 +242,9 @@ log_filter (const char *dev, char *vendor, char *product, char *wwid,
case MATCH_PROPERTY_BLIST:
LOG_BLIST("udev property", "blacklisted");
break;
+ case MATCH_PROTOCOL_BLIST:
+ LOG_BLIST("protocol", "blacklisted");
+ break;
case MATCH_DEVICE_BLIST_EXCEPT:
LOG_BLIST("vendor/product", "whitelisted");
break;
@@ -253,6 +260,9 @@ log_filter (const char *dev, char *vendor, char *product, char *wwid,
case MATCH_PROPERTY_BLIST_MISSING:
LOG_BLIST("blacklisted,", "udev property missing");
break;
+ case MATCH_PROTOCOL_BLIST_EXCEPT:
+ LOG_BLIST("protocol", "whitelisted");
+ break;
}
}
@@ -272,7 +282,7 @@ int
filter_device (vector blist, vector elist, char * vendor, char * product)
{
int r = _filter_device(blist, elist, vendor, product);
- log_filter(NULL, vendor, product, NULL, NULL, r);
+ log_filter(NULL, vendor, product, NULL, NULL, NULL, r);
return r;
}
@@ -292,7 +302,7 @@ int
filter_devnode (vector blist, vector elist, char * dev)
{
int r = _filter_devnode(blist, elist, dev);
- log_filter(dev, NULL, NULL, NULL, NULL, r);
+ log_filter(dev, NULL, NULL, NULL, NULL, NULL, r);
return r;
}
@@ -312,7 +322,29 @@ int
filter_wwid (vector blist, vector elist, char * wwid, char * dev)
{
int r = _filter_wwid(blist, elist, wwid);
- log_filter(dev, NULL, NULL, wwid, NULL, r);
+ log_filter(dev, NULL, NULL, wwid, NULL, NULL, r);
+ return r;
+}
+
+static int
+_filter_protocol (vector blist, vector elist, const char * protocol_str)
+{
+ if (_blacklist_exceptions(elist, protocol_str))
+ return MATCH_PROTOCOL_BLIST_EXCEPT;
+ if (_blacklist(blist, protocol_str))
+ return MATCH_PROTOCOL_BLIST;
+ return 0;
+}
+
+int
+filter_protocol(vector blist, vector elist, struct path * pp)
+{
+ char buf[PROTOCOL_BUF_SIZE];
+ int r;
+
+ snprint_path_protocol(buf, sizeof(buf), pp);
+ r = _filter_protocol(blist, elist, buf);
+ log_filter(pp->dev, NULL, NULL, NULL, NULL, buf, r);
return r;
}
@@ -324,7 +356,6 @@ _filter_path (struct config * conf, struct path * pp)
r = filter_property(conf, pp->udev);
if (r > 0)
return r;
-
r = _filter_devnode(conf->blist_devnode, conf->elist_devnode,pp->dev);
if (r > 0)
return r;
@@ -332,6 +363,9 @@ _filter_path (struct config * conf, struct path * pp)
pp->vendor_id, pp->product_id);
if (r > 0)
return r;
+ r = filter_protocol(conf->blist_protocol, conf->elist_protocol, pp);
+ if (r > 0)
+ return r;
r = _filter_wwid(conf->blist_wwid, conf->elist_wwid, pp->wwid);
return r;
}
@@ -340,7 +374,8 @@ int
filter_path (struct config * conf, struct path * pp)
{
int r=_filter_path(conf, pp);
- log_filter(pp->dev, pp->vendor_id, pp->product_id, pp->wwid, NULL, r);
+ log_filter(pp->dev, pp->vendor_id, pp->product_id, pp->wwid, NULL,
+ NULL, r);
return r;
}
@@ -375,7 +410,7 @@ filter_property(struct config * conf, struct udev_device * udev)
r = _filter_property(conf, env);
if (r) {
- log_filter(devname, NULL, NULL, NULL, env, r);
+ log_filter(devname, NULL, NULL, NULL, env, NULL, r);
return r;
}
}
@@ -385,7 +420,7 @@ filter_property(struct config * conf, struct udev_device * udev)
* the environment variable _has_ to match.
*/
if (VECTOR_SIZE(conf->elist_property)) {
- log_filter(devname, NULL, NULL, NULL, NULL,
+ log_filter(devname, NULL, NULL, NULL, NULL, NULL,
MATCH_PROPERTY_BLIST_MISSING);
return MATCH_PROPERTY_BLIST_MISSING;
}
diff --git a/libmultipath/blacklist.h b/libmultipath/blacklist.h
index 443025d..6797ac5 100644
--- a/libmultipath/blacklist.h
+++ b/libmultipath/blacklist.h
@@ -10,10 +10,12 @@
#define MATCH_DEVNODE_BLIST 3
#define MATCH_PROPERTY_BLIST 4
#define MATCH_PROPERTY_BLIST_MISSING 5
+#define MATCH_PROTOCOL_BLIST 6
#define MATCH_WWID_BLIST_EXCEPT -MATCH_WWID_BLIST
#define MATCH_DEVICE_BLIST_EXCEPT -MATCH_DEVICE_BLIST
#define MATCH_DEVNODE_BLIST_EXCEPT -MATCH_DEVNODE_BLIST
#define MATCH_PROPERTY_BLIST_EXCEPT -MATCH_PROPERTY_BLIST
+#define MATCH_PROTOCOL_BLIST_EXCEPT -MATCH_PROTOCOL_BLIST
struct blentry {
char * str;
@@ -36,6 +38,7 @@ int filter_wwid (vector, vector, char *, char *);
int filter_device (vector, vector, char *, char *);
int filter_path (struct config *, struct path *);
int filter_property(struct config *, struct udev_device *);
+int filter_protocol(vector, vector, struct path *);
int store_ble (vector, char *, int);
int set_ble_device (vector, char *, char *, int);
void free_blacklist (vector);
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 9bf4fb7..506c869 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -538,11 +538,13 @@ free_config (struct config * conf)
free_blacklist(conf->blist_devnode);
free_blacklist(conf->blist_wwid);
free_blacklist(conf->blist_property);
+ free_blacklist(conf->blist_protocol);
free_blacklist_device(conf->blist_device);
free_blacklist(conf->elist_devnode);
free_blacklist(conf->elist_wwid);
free_blacklist(conf->elist_property);
+ free_blacklist(conf->elist_protocol);
free_blacklist_device(conf->elist_device);
free_mptable(conf->mptable);
@@ -709,6 +711,12 @@ load_config (char * file)
if (!conf->blist_property)
goto out;
}
+ if (conf->blist_protocol == NULL) {
+ conf->blist_protocol = vector_alloc();
+
+ if (!conf->blist_protocol)
+ goto out;
+ }
if (conf->elist_devnode == NULL) {
conf->elist_devnode = vector_alloc();
@@ -736,6 +744,13 @@ load_config (char * file)
if (!conf->elist_property)
goto out;
}
+ if (conf->elist_protocol == NULL) {
+ conf->elist_protocol = vector_alloc();
+
+ if (!conf->elist_protocol)
+ goto out;
+ }
+
if (setup_default_blist(conf))
goto out;
diff --git a/libmultipath/config.h b/libmultipath/config.h
index 21a3bbd..6fa7f19 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -207,10 +207,12 @@ struct config {
vector blist_wwid;
vector blist_device;
vector blist_property;
+ vector blist_protocol;
vector elist_devnode;
vector elist_wwid;
vector elist_device;
vector elist_property;
+ vector elist_protocol;
};
extern struct udev * udev;
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index 31897cd..810ffaa 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -1179,9 +1179,12 @@ blacklist_handler(struct config *conf, vector strvec)
conf->blist_device = vector_alloc();
if (!conf->blist_property)
conf->blist_property = vector_alloc();
+ if (!conf->blist_protocol)
+ conf->blist_protocol = vector_alloc();
if (!conf->blist_devnode || !conf->blist_wwid ||
- !conf->blist_device || !conf->blist_property)
+ !conf->blist_device || !conf->blist_property ||
+ !conf->blist_protocol)
return 1;
return 0;
@@ -1198,9 +1201,12 @@ blacklist_exceptions_handler(struct config *conf, vector strvec)
conf->elist_device = vector_alloc();
if (!conf->elist_property)
conf->elist_property = vector_alloc();
+ if (!conf->elist_protocol)
+ conf->elist_protocol = vector_alloc();
if (!conf->elist_devnode || !conf->elist_wwid ||
- !conf->elist_device || !conf->elist_property)
+ !conf->elist_device || !conf->elist_property ||
+ !conf->elist_protocol)
return 1;
return 0;
@@ -1244,6 +1250,8 @@ declare_ble_handler(blist_wwid)
declare_ble_handler(elist_wwid)
declare_ble_handler(blist_property)
declare_ble_handler(elist_property)
+declare_ble_handler(blist_protocol)
+declare_ble_handler(elist_protocol)
static int
snprint_def_uxsock_timeout(struct config *conf, char * buff, int len, void * data)
@@ -1504,6 +1512,7 @@ init_keywords(vector keywords)
install_keyword_multi("devnode", &ble_blist_devnode_handler, &snprint_ble_simple);
install_keyword_multi("wwid", &ble_blist_wwid_handler, &snprint_ble_simple);
install_keyword_multi("property", &ble_blist_property_handler, &snprint_ble_simple);
+ install_keyword_multi("protocol", &ble_blist_protocol_handler, &snprint_ble_simple);
install_keyword_multi("device", &ble_device_handler, NULL);
install_sublevel();
install_keyword("vendor", &ble_blist_device_vendor_handler, &snprint_bled_vendor);
@@ -1513,6 +1522,7 @@ init_keywords(vector keywords)
install_keyword_multi("devnode", &ble_elist_devnode_handler, &snprint_ble_simple);
install_keyword_multi("wwid", &ble_elist_wwid_handler, &snprint_ble_simple);
install_keyword_multi("property", &ble_elist_property_handler, &snprint_ble_simple);
+ install_keyword_multi("protocol", &ble_elist_protocol_handler, &snprint_ble_simple);
install_keyword_multi("device", &ble_except_device_handler, NULL);
install_sublevel();
install_keyword("vendor", &ble_elist_device_vendor_handler, &snprint_bled_vendor);
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index f118800..e01ecdc 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1929,9 +1929,10 @@ int pathinfo(struct path *pp, struct config *conf, int mask)
if (mask & DI_BLACKLIST && mask & DI_SYSFS) {
if (filter_device(conf->blist_device, conf->elist_device,
- pp->vendor_id, pp->product_id) > 0) {
+ pp->vendor_id, pp->product_id) > 0 ||
+ filter_protocol(conf->blist_protocol, conf->elist_protocol,
+ pp) > 0)
return PATHINFO_SKIPPED;
- }
}
path_state = path_offline(pp);
diff --git a/libmultipath/print.c b/libmultipath/print.c
index 00739bc..ce3682d 100644
--- a/libmultipath/print.c
+++ b/libmultipath/print.c
@@ -1518,6 +1518,19 @@ int snprint_blacklist_report(struct config *conf, char *buff, int len)
if ((len - fwd - threshold) <= 0)
return len;
+ fwd += snprintf(buff + fwd, len - fwd, "protocol rules:\n"
+ "- blacklist:\n");
+ if (!snprint_blacklist_group(buff, len, &fwd, &conf->blist_protocol))
+ return len;
+
+ if ((len - fwd - threshold) <= 0)
+ return len;
+ fwd += snprintf(buff + fwd, len - fwd, "- exceptions:\n");
+ if (snprint_blacklist_group(buff, len, &fwd, &conf->elist_protocol) == 0)
+ return len;
+
+ if ((len - fwd - threshold) <= 0)
+ return len;
fwd += snprintf(buff + fwd, len - fwd, "wwid rules:\n"
"- blacklist:\n");
if (snprint_blacklist_group(buff, len, &fwd, &conf->blist_wwid) == 0)
@@ -1591,6 +1604,15 @@ int snprint_blacklist(struct config *conf, char *buff, int len)
if (fwd >= len)
return len;
}
+ vector_foreach_slot (conf->blist_protocol, ble, i) {
+ kw = find_keyword(conf->keywords, rootkw->sub, "protocol");
+ if (!kw)
+ return 0;
+ fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n",
+ kw, ble);
+ if (fwd >= len)
+ return len;
+ }
rootkw = find_keyword(conf->keywords, rootkw->sub, "device");
if (!rootkw)
return 0;
@@ -1667,6 +1689,15 @@ int snprint_blacklist_except(struct config *conf, char *buff, int len)
if (fwd >= len)
return len;
}
+ vector_foreach_slot (conf->elist_protocol, ele, i) {
+ kw = find_keyword(conf->keywords, rootkw->sub, "protocol");
+ if (!kw)
+ return 0;
+ fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n",
+ kw, ele);
+ if (fwd >= len)
+ return len;
+ }
rootkw = find_keyword(conf->keywords, rootkw->sub, "device");
if (!rootkw)
return 0;
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 2201d7f..2be5d2a 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1084,6 +1084,10 @@ The \fIWorld Wide Identification\fR of a device.
.B property
Regular expression of the udev property to be excluded.
.TP
+.B protocol
+Regular expression of the protocol to be excluded. See below for a
+list of recognized protocols
+.TP
.B device
Subsection for the device description. This subsection recognizes the
.B vendor
@@ -1091,6 +1095,13 @@ and
.B product
keywords. For a full description of these keywords please see the
\fIdevices\fR section description.
+.LP
+The protocol strings that multipath recognizes are \fIscsi:fcp\fR,
+\fIscsi:spi\fR, \fIscsi:ssa\fR, \fIscsi:sbp\fR, \fIscsi:srp\fR,
+\fIscsi:iscsi\fR, \fIscsi:sas\fR, \fIscsi:adt\fR, \fIscsi:ata\fR,
+\fIscsi:unspec\fR, \fIccw\fR, \fIcciss\fR, \fInvme\fR, and \fIundef\fR.
+The protocol that a path is using can be viewed by running
+\fBmultipathd show paths format "%d %P"\fR
.
.
.\" ----------------------------------------------------------------------------
@@ -1115,6 +1126,10 @@ The \fIWorld Wide Identification\fR of a device.
.B property
Regular expression of the udev property to be whitelisted.
.TP
+.B protocol
+Regular expression of the protocol to be whitelisted. See the
+\fBblacklist section\fR for a list of recognized protocols
+.TP
.B device
Subsection for the device description. This subsection recognizes the
.B vendor
--
2.7.4

View file

@ -1,60 +1,61 @@
Name: device-mapper-multipath
Version: 0.13.0
Release: 2%{?dist}
Summary: Tools to manage multipath devices using device-mapper
# readline uses GPL-3.0-only
License: GPL-2.0-only AND GPL-3.0-only
URL: http://christophe.varoqui.free.fr/
Name: device-mapper-multipath
Version: 0.7.4
Release: 3.git07e7bd5%{?dist}
License: GPL+
Group: System Environment/Base
URL: http://christophe.varoqui.free.fr/
# The source for this package was pulled from upstream's git repo. Use the
# following command to generate the tarball
# curl -L https://github.com/opensvc/multipath-tools/archive/0.13.0.tar.gz -o multipath-tools-0.13.0.tgz
Source0: multipath-tools-0.13.0.tgz
# curl "https://git.opensvc.com/?p=multipath-tools/.git;a=snapshot;h=07e7bd5;sf=tgz" -o multipath-tools-07e7bd5.tgz
Source0: multipath-tools-07e7bd5.tgz
Source1: multipath.conf
Patch0001: 0001-RH-fixup-udev-rules-for-redhat.patch
Patch0002: 0002-RH-Remove-the-property-blacklist-exception-builtin.patch
Patch0003: 0003-RH-don-t-start-without-a-config-file.patch
Patch0004: 0004-RH-Fix-nvme-function-missing-argument.patch
Patch0005: 0005-RH-use-rpm-optflags-if-present.patch
Patch0006: 0006-RH-add-mpathconf.patch
Patch0007: 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch
Patch0008: 0008-RH-reset-default-find_mutipaths-value-to-off.patch
Patch0009: 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch
Patch0010: 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch
Patch0011: 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch
Patch0012: 0012-RH-compile-with-libreadline-support.patch
Patch0013: 0013-RH-Add-mpathcleanup.patch
Patch0001: 0001-libmultipath-fix-tur-checker-locking.patch
Patch0002: 0002-multipath-fix-DEF_TIMEOUT-use.patch
Patch0003: 0003-multipathd-remove-coalesce_paths-from-ev_add_map.patch
Patch0004: 0004-multipathd-remove-unused-configure-parameter.patch
Patch0005: 0005-Fix-set_no_path_retry-regression.patch
Patch0006: 0006-multipathd-change-spurious-uevent-msg-priority.patch
Patch0007: 0007-multipath-print-sysfs-state-in-fast-list-mode.patch
Patch0008: 0008-libmultipath-move-remove_map-waiter-code-to-multipat.patch
Patch0009: 0009-move-waiter-code-from-libmultipath-to-multipathd.patch
Patch0010: 0010-call-start_waiter_thread-before-setup_multipath.patch
Patch0011: 0011-libmultipath-add-helper-functions.patch
Patch0012: 0012-multipathd-RFC-add-new-polling-dmevents-waiter-threa.patch
Patch0013: 0013-libmultipath-condlog-log-to-stderr.patch
Patch0014: 0014-multipathd-fix-compiler-warning-for-uev_pathfail_che.patch
Patch0015: 0015-RH-fixup-udev-rules-for-redhat.patch
Patch0016: 0016-RH-Remove-the-property-blacklist-exception-builtin.patch
Patch0017: 0017-RH-don-t-start-without-a-config-file.patch
Patch0018: 0018-RH-use-rpm-optflags-if-present.patch
Patch0019: 0019-RH-add-mpathconf.patch
Patch0020: 0020-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch
Patch0021: 0021-RH-trigger-change-uevent-on-new-device-creation.patch
Patch0022: 0022-RH-warn-on-invalid-regex-instead-of-failing.patch
Patch0023: 0023-libmutipath-remove-unused-IDE-bus-type.patch
Patch0024: 0024-multipathd-add-new-protocol-path-wildcard.patch
Patch0025: 0025-libmultipath-add-protocol-blacklist-option.patch
# runtime
Requires: %{name}-libs = %{version}-%{release}
Requires: kpartx = %{version}-%{release}
Requires: device-mapper >= 1.02.96
Requires: userspace-rcu
Requires: readline
Requires: libmount
Requires(post): systemd-units
Requires: initscripts
Requires(post): systemd-units systemd-sysv chkconfig
Requires(preun): systemd-units
Requires(postun): systemd-units
# Starting with 0.7.7-1, 62-multipath.rules changed in a way that is
# incompatible with 65-md-incremental.rules in earlier mdadm packages.
# Later mdadm packages are compatible with any version of
# device-mapper-multipath. See bz #1628192 for more details
Conflicts: mdadm < 4.1-rc2.0.2
# Starting with 0.7.7-1, 62-multipath.rules changed in a way that is
# incompatible with 80-udisks2.rules in earlier udisks2 packages.
# Later udisks2 packages are compatible with any version of
# device-mapper-multipath. See bz #1628192 for more details
Conflicts: udisks2 < 2.8.0-2
# build/setup
BuildRequires: libaio-devel, device-mapper-devel >= 1.02.89
BuildRequires: libselinux-devel, libsepol-devel
BuildRequires: readline-devel, ncurses-devel
BuildRequires: systemd-units, systemd-devel
BuildRequires: json-c-devel, perl-interpreter, pkgconfig, gcc
BuildRequires: json-c-devel, perl-interpreter, pkgconfig
BuildRequires: userspace-rcu-devel
BuildRequires: libmount-devel
BuildRequires: make
%ifarch x86_64
BuildRequires: librados-devel
%endif
%description
%{name} provides tools to manage multipath devices by
@ -65,8 +66,7 @@ The tools are :
%package libs
Summary: The %{name} modules and shared library
# only libmpathcmd is LGPL-2.1-or-later AND LGPL-2.0-or-later
License: GPL-2.0-or-later AND LGPL-2.1-or-later AND LGPL-2.0-or-later
Group: System Environment/Libraries
%description libs
The %{name}-libs provides the path checker
@ -76,6 +76,7 @@ libmultipath.
%package devel
Summary: Development libraries and headers for %{name}
Group: Development/Libraries
Requires: %{name} = %{version}-%{release}
Requires: %{name}-libs = %{version}-%{release}
@ -85,14 +86,14 @@ device-mapper-multipath's lbmpathpersist and libmpathcmd libraries.
%package -n kpartx
Summary: Partition device manager for device-mapper devices
Group: System Environment/Base
%description -n kpartx
kpartx manages partition creation and removal for device-mapper devices.
%package -n libdmmp
Summary: device-mapper-multipath C API library
# Automatically converted from old format: GPLv3+ - review is highly recommended.
License: GPL-3.0-or-later
Group: System Environment/Libraries
Requires: json-c
Requires: %{name} = %{version}-%{release}
Requires: %{name}-libs = %{version}-%{release}
@ -103,6 +104,7 @@ C API library.
%package -n libdmmp-devel
Summary: device-mapper-multipath C API library headers
Group: Development/Libraries
Requires: pkgconfig
Requires: libdmmp = %{version}-%{release}
@ -111,26 +113,52 @@ This package contains the files needed to develop applications that use
device-mapper-multipath's libdmmp C API library
%prep
%autosetup -n multipath-tools-0.13.0 -p1
%setup -q -n multipath-tools-07e7bd5
%patch0001 -p1
%patch0002 -p1
%patch0003 -p1
%patch0004 -p1
%patch0005 -p1
%patch0006 -p1
%patch0007 -p1
%patch0008 -p1
%patch0009 -p1
%patch0010 -p1
%patch0011 -p1
%patch0012 -p1
%patch0013 -p1
%patch0014 -p1
%patch0015 -p1
%patch0016 -p1
%patch0017 -p1
%patch0018 -p1
%patch0019 -p1
%patch0020 -p1
%patch0021 -p1
%patch0022 -p1
%patch0023 -p1
%patch0024 -p1
%patch0025 -p1
cp %{SOURCE1} .
%build
%define _sbindir /usr/sbin
%define _libdir /usr/%{_lib}
%define _libmpathdir %{_libdir}/multipath
%define _pkgconfdir %{_libdir}/pkgconfig
%make_build LIB=%{_lib}
make %{?_smp_mflags} LIB=%{_lib}
%install
%make_install \
make install \
DESTDIR=%{buildroot} \
bindir=%{_sbindir} \
syslibdir=%{_libdir} \
usrlibdir=%{_libdir} \
plugindir=%{_libmpathdir} \
mandir=%{_mandir} \
libdir=%{_libmpathdir} \
rcdir=%{_initrddir} \
unitdir=%{_unitdir} \
includedir=%{_includedir} \
pkgconfdir=%{_pkgconfdir} \
tmpfilesdir=%{_tmpfilesdir}
pkgconfdir=%{_pkgconfdir}
# tree fix up
install -d %{buildroot}/etc/multipath
@ -145,7 +173,7 @@ rm -rf %{buildroot}/%{_initrddir}
%postun
if [ $1 -ge 1 ] ; then
multipathd forcequeueing daemon > /dev/null 2>&1 || :
/sbin/multipathd forcequeueing daemon > /dev/null 2>&1 || :
fi
%systemd_postun_with_restart multipathd.service
@ -155,750 +183,92 @@ fi
/bin/systemctl --quiet is-enabled multipathd.service >/dev/null 2>&1 && /bin/systemctl reenable multipathd.service ||:
%files
%license LICENSES/GPL-2.0 LICENSES/LGPL-2.0 LICENSES/GPL-3.0
%defattr(-,root,root,-)
%{_sbindir}/multipath
%{_sbindir}/multipathd
%{_sbindir}/multipathc
%{_sbindir}/mpathconf
%{_sbindir}/mpathcleanup
%{_sbindir}/mpathpersist
%{_unitdir}/multipathd.service
%{_unitdir}/multipathd-queueing.service
%{_unitdir}/multipathd.socket
%{_mandir}/man5/multipath.conf.5*
%{_mandir}/man8/multipath.8*
%{_mandir}/man8/multipathd.8*
%{_mandir}/man8/multipathc.8*
%{_mandir}/man8/mpathconf.8*
%{_mandir}/man8/mpathpersist.8*
%{_mandir}/man5/multipath.conf.5.gz
%{_mandir}/man8/multipath.8.gz
%{_mandir}/man8/multipathd.8.gz
%{_mandir}/man8/mpathconf.8.gz
%{_mandir}/man8/mpathpersist.8.gz
%config /usr/lib/udev/rules.d/62-multipath.rules
%config /usr/lib/udev/rules.d/11-dm-mpath.rules
%config /usr/lib/udev/rules.d/99-z-dm-mpath-late.rules
%dir %{_modulesloaddir}
%{_modulesloaddir}/scsi_dh.conf
%{_tmpfilesdir}/multipath.conf
%doc README.md
%{!?_licensedir:%global license %%doc}
%license COPYING
%doc README
%doc README.alua
%doc multipath.conf
%dir /etc/multipath
%files libs
%license LICENSES/GPL-2.0 LICENSES/LGPL-2.0 LICENSES/LGPL-2.1
%doc README.md
%defattr(-,root,root,-)
%doc README
%{!?_licensedir:%global license %%doc}
%license COPYING
%{_libdir}/libmultipath.so
%{_libdir}/libmultipath.so.*
%{_libdir}/libmpathutil.so
%{_libdir}/libmpathutil.so.*
%{_libdir}/libmpathpersist.so.*
%{_libdir}/libmpathcmd.so.*
%{_libdir}/libmpathvalid.so.*
%dir %{_libmpathdir}
%{_libmpathdir}/*
%ldconfig_scriptlets libs
%post libs -p /sbin/ldconfig
%postun libs -p /sbin/ldconfig
%files devel
%doc README.md
%defattr(-,root,root,-)
%doc README COPYING
%{_libdir}/libmpathpersist.so
%{_libdir}/libmpathcmd.so
%{_libdir}/libmpathvalid.so
%{_includedir}/mpath_cmd.h
%{_includedir}/mpath_persist.h
%{_includedir}/mpath_valid.h
%{_mandir}/man3/mpath_persistent_reserve_in.3*
%{_mandir}/man3/mpath_persistent_reserve_out.3*
%{_mandir}/man3/mpath_persistent_reserve_in.3.gz
%{_mandir}/man3/mpath_persistent_reserve_out.3.gz
%files -n kpartx
%license LICENSES/GPL-2.0
%doc README.md
%defattr(-,root,root,-)
%doc README
%{!?_licensedir:%global license %%doc}
%license COPYING
%{_sbindir}/kpartx
/usr/lib/udev/kpartx_id
%{_mandir}/man8/kpartx.8*
%{_mandir}/man8/kpartx.8.gz
%config /usr/lib/udev/rules.d/11-dm-parts.rules
%config /usr/lib/udev/rules.d/66-kpartx.rules
%config /usr/lib/udev/rules.d/68-del-part-nodes.rules
%files -n libdmmp
%license LICENSES/GPL-3.0
%doc README.md
%defattr(-,root,root,-)
%doc README COPYING
%{_libdir}/libdmmp.so.*
%ldconfig_scriptlets -n libdmmp
%post -n libdmmp -p /sbin/ldconfig
%postun -n libdmmp -p /sbin/ldconfig
%files -n libdmmp-devel
%doc README.md
%defattr(-,root,root,-)
%doc README COPYING
%{_libdir}/libdmmp.so
%dir %{_includedir}/libdmmp
%{_includedir}/libdmmp/*
%{_mandir}/man3/dmmp_*
%{_mandir}/man3/libdmmp.h.3*
%{_mandir}/man3/libdmmp.h.3.gz
%{_pkgconfdir}/libdmmp.pc
%changelog
* Thu Nov 13 2025 Benjamin Marzinski <bmarzins@redhat.com> - 0.13.0-2
- Move STI tests to TMT
* Tue Nov 4 2025 Benjamin Marzinski <bmarzins@redhat.com> - 0.13.0-1
- Update source to upstream release 0.13.0
* Previous patches 0001-0004 are included in the tarball
- Install /lib/systemd/system/multipathd-queueing.service
- Rename redhat patches
* Previous patches 0005-0017 are now patches 0001-0013
* Wed Jul 23 2025 Fedora Release Engineering <releng@fedoraproject.org> - 0.11.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild
* Thu Feb 27 2025 Benjamin Marzinski <bmarzins@redhat.com> - 0.11.1-1
- Update source to upstream staging branch for 0.11.1 plus additional
stable branch patches.
* Previous patches 0001-0032 are included in the tarball
- Rename redhat patches
* Previous patches 0033-0045 are now patches 0005-0017
* Sat Feb 1 2025 Benjamin Marzinski <bmarzins@redhat.com> - 0.10.0-5
- Update source to upstream staging branch for 0.10.y (will be 0.10.2 when
merged).
- Rebase redhat patches
* Thu Jan 16 2025 Fedora Release Engineering <releng@fedoraproject.org> - 0.10.0-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild
* Sun Jan 12 2025 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 0.10.0-3
- Rebuilt for the bin-sbin merge (2nd attempt)
* Thu Aug 29 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.10.0-2
- update CI tests.
* Thu Aug 29 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.10.0-1
- Update source to upstream version 0.9.9
* Previous patch 0014-multipathd-fix-flush-check-in-flush_map.patch is
included in the source tarball
- Rebase redhat patches
* Fri Aug 9 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.9-6
- Add 0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch
* multipath features tracking on failed removes
* Mon Jul 29 2024 Miroslav Suchý <msuchy@redhat.com> - 0.9.9-5
- convert license to SPDX
* Thu Jul 25 2024 Miroslav Suchý <msuchy@redhat.com> - 0.9.9-4
- convert license to SPDX
* Wed Jul 17 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.9-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild
* Tue Jul 09 2024 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 0.9.9-2
- Rebuilt for the bin-sbin merge
* Thu Jun 13 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.9-1
- Update source to upstream version 0.9.9
* Previous patches 0001-0044 are included in the source tarball
- Rename redhat patches
* Previous patches 0045-0057 are now patches 0001-0013
* Mon May 20 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.8-1
- Update source to upstream version 0.9.8 plus latest staging branch
* Previous patches 0014 & 0015 are included in the source tarball
* patches 0001-0044 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0001-0013 are now patches 0045-0057
- Install /lib/udev/rules.d/99-z-dm-mpath-late.rules
* Wed Jan 24 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.7-7
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Fri Jan 19 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.7-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Tue Jan 16 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.7-5
- Add 0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch
* Fix auto_resize code to avoid a segfault
- Add 0015-multipathd-fix-auto-resize-configuration.patch
* Fix auto_resize default value
* Thu Nov 30 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.7-4
- Use modulesloaddir macro for installing scsi_dh.conf
* Wed Nov 29 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.7-3
- Fix multipath_conf_syntax test
- Fix restate_module test
* Tue Nov 28 2023 Paul Donohue <git@PaulSD.com> - 0.9.7-2
- Modify 0006-RH-add-mpathconf.patch
- Modify 0008-RH-reset-default-find_mutipaths-value-to-off.patch
* Fix find_multipaths values in docs and mpathconf
* Tue Nov 21 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.7-1
- Update source to upstream version 0.9.7
* Previous patches 0001-0040 are included in the source tarball
- Rename redhat patches
* Previous patches 0041-0053 are now patches 0001-0013
- Remove /usr/lib/modules-load.d/multipath.conf
* has been replaced with modprobe@dm_multipath.service unit Wants.
* Fri Sep 22 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.6-1
- Update to the head of the upstream staging branch
- Rename redhat patches
* Previous patches 0001-0012 are now patches 0041-0052
- Add 0053-RH-Add-mpathcleanup.patch
* add mpathcleanup program
* Wed Jul 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.5-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
* Tue May 16 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.5-1
- Update to the latest upstream release
* Previous patches 0001-0015 are included in the source tarball
- Rename redhat patches
* Previous patches 0016-0027 are now patches 0001-0012
* Thu Feb 2 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.4-2
- Update to the head of the upstream staging branch
* Patches 0011-0015 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0011-0022 are now patches 0016-0027
* Thu Jan 26 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.4-1
- Update to the head of the upstream staging branch
* Previous patches 0001-0032 are included in the source tarball
* Patches 0001-0010 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0033-0044 are now patches 0011-0022
- Add dependency on libmount
* Thu Jan 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
* Tue Nov 15 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.3-1
- Update to the head of the upstream staging branch
* Previous patches 0001-0042 are included in the source tarball
* Patches 0001-0032 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0043-0053 are now patches 0033-0043
- Change back to using readline instead of libedit
* The code the uses readline has been isolated from the code that
is licensed gpl v2 only.
- Add libmpathutil libraries to spec file
- Add multipathc program to spec file
- Add multipath.conf systemd tempfile configuration to spec file
- Misc spec file cleanups
* Fri Aug 19 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.0-3
- Update to the head of the upstream staging branch
* Patches 0005-0042 are from the upstream staging branch
* Previous patches 0005 & 0006 are now patches 0023 & 0005
- Rename redhat patches
* Previous patches 0007-0017 are now patches 0043-0053
- Change from using readline to libedit
* readline is licensed GPL v3, and multipathd includes code
licensed gpl v2.
- Remove README.alua
* information moved to README.md
* Thu Jul 21 2022 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
* Wed Jul 13 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.0-1
- Update source to upstream version 0.9.0
* Previous patches 0001-0005 are included in the commit.
* This version deprecates multiple options: mutlipath_dir, config_dir, and
getuid_callout, along with the "default_" prefixed alternate names for the
default section parameters.
- Add patches from upstream staging branch
* Patches 0001-0006 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0006-0016 are now patches 0007-0017
* Mon Mar 28 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.9-1
- Update source to upstream version 0.8.9
* Previous patches 0001-0024 & 0035 are included in the commit.
- Add patches from upstream staging branch
* Patches 0001-0005 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0025-0034 are now patches 0006-0015
- Combine redhat patches
* Previous patches 0036 & 0037 are now part of patch 0011
- Add 0016-RH-add-scsi-device-handlers-to-modules-load.d.patch
- Spec file changes
* Install multipath.conf and scsi_dh.conf to /usr/lib/modules-load.d
* Mon Feb 7 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-8
- Add 0036-RH-add-support-to-mpathconf-for-setting-arbitrary-de.patch
* add the ability for mpathconf to set arbitray options with --option
- Add 0037-RH-add-support-to-mpathconf-for-setting-recheck_wwid.patch
* add --recheck_wwid option to mpathconf
* Wed Jan 26 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-7
- Add 0035-libmultipath-use-asprintf-to-allocate-prefixed_uuid.patch
- Resolves: bz #2045309
* Thu Jan 20 2022 Fedora Release Engineering <releng@fedoraproject.org> - 0.8.7-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild
* Thu Jan 6 2022 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-5
- Modify 0030-RH-add-mpathconf.patch
* fix setting property_blacklist with no blacklist_exceptions section
* Mon Dec 13 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-4
- Update to the head of the upstream staging branch
* Patches 0013 - 0024 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0013-0022 are now patches 0025-0034
* Thu Oct 28 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-3
- Update to the head of the upstream staging branch
* Patches 0011 & 0012 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0011-0020 are now patches 0013-0022
* Wed Oct 6 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-2
- Modify 0013-RH-don-t-start-without-a-config-file.patch
* add condtion to multipathd.socket as well
* Wed Oct 6 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-1
- Update source to upstream version 0.8.7
* Previous patches 0001-0023 are included in the commit.
- Add patches from upstream staging branch
* Patches 0001-0010 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0024-0033 are now patches 0011-0020
* Fri Jul 30 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.6-5
- Update to the head of the upstream staging branch plus redhat patches
* Patches 0016-0018 are from the upstream staging branch
* Patches 0019-0024 have been submitted upstream
- Rename files
* Previous patches 0016-0025 are now patches 0024-0033
* Wed Jul 21 2021 Fedora Release Engineering <releng@fedoraproject.org> - 0.8.6-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
* Sat Jul 10 2021 Björn Esser <besser82@fedoraproject.org> - 0.8.6-3
- Rebuild for versioned symbols in json-c
* Thu Jul 1 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.6-2
- Pull in latest upstream post-tag commits
* Patches 0001-0015 are from
https://github.com/openSUSE/multipath-tools/tree/queue and are
already queued for upstream
- Rename files
* Previous patches 0001-0010 and now patches 0016-0025
* Wed Jun 23 2021 Cole Robinson <crobinso@redhat.com> - 0.8.6-1.fc35.1
- Rebuild for userspace-rcu soname bump
* Mon Apr 5 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.6-1
- Update Source to upstream version 0.8.6
* Previous patches 0001-0146 are included in the commit
- Rename files
* Previous patches 0147-0156 are now patches 0001-0010
- sync tests with RHEL repository
* Fri Mar 26 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.5-6
- Change patch format to remove Git version
* Patches 0001-0122 only have the patch format modified
- Update to the head of the upstream staging branch plus redhat patches
* Patches 0123-0134 & 1036-0142 are from the upstream staging branch
* Patches 0143-1046 have been submitted upstream
* Patch 0156 is a Red Hat only patch. Red Hat udev rules set ID_SERIAL
from 60-persistent-storage.rules instead of 55-scsi-sg3_id.rules.
Multipath's parse_vpd_pg83() function needs to match the ID_SERIAL
value from udev.
- Rename files
* Previous patches 0123-0132 are now patches 1035 & 0147-0155
* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 0.8.5-5
- Rebuilt for updated systemd-rpm-macros
See https://pagure.io/fesco/issue/2583.
* Thu Feb 11 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.5-4
- Update Source to upstream version 0.8.5 plus post tag commits
* Patches 0001-0121 are from
https://github.com/openSUSE/multipath-tools/tree/queue and are
already queued for upstream
* Patches 0122&0123 have been posted for upstream inclusion
- Rename files
* Previous patches 0103-0111 are now patches 0124-0132
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 0.8.5-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Tue Jan 19 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.5-2
- Fix build issues
* Tue Jan 19 2021 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.5-1
- Update Source to upstream version 0.8.5 plus post tag commits
* Patches 0001-0102 are from
https://github.com/openSUSE/multipath-tools/tree/queue and are
already queued for upstream.
- Rename files
* Previous patches 0059-0068 are now patches 0103-0111
* Sun Sep 27 2020 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.4-7
- Add 0073-libmultipath-util-constify-function-arguments.patch
- Add 0074-libmultipath-constify-file-argument-in-config-parser.patch
- Add 0075-libmultipath-provide-defaults-for-get-put-_multipath.patch
- Add 0076-libmpathpersist-allow-using-libmultipath-get-put-_mu.patch
- Add 0077-multipath-use-get_put-_multipath_config-from-libmult.patch
- Add 0078-mpathpersist-use-get-put-_multipath_config-from-libm.patch
- Add 0079-libmultipath-add-udev-and-logsink-symbols.patch
- Add 0080-multipath-remove-logsink-and-udev.patch
- Add 0081-libmpathpersist-call-libmultipath_-init-exit.patch
- Add 0082-mpathpersist-remove-logsink-and-udev.patch
- Add 0083-multipathd-remove-logsink-and-udev.patch
* Pull in upsteam library changes
- Add 0084-libmpathvalid-use-default-_multipath_config-udev-and.patch
- Add 0085-Revert-libmultipath-add-ignore_udev_uid-option.patch
- Add 0086-libmultipath-change-log-level-for-null-uid_attribute.patch
- Add 0087-libmultipath-orphan_paths-avoid-BUG-message.patch
* update libmpathvalid to use upstream library changes. changes
submitted upstream
* Mon Jul 27 2020 Fedora Release Engineering <releng@fedoraproject.org> - 0.8.4-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Tue Jul 21 2020 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.4-5
- Update CI tests to match RHEL
* This commit also pulls in changes from Lin Li <lilin@redhat.com>
and Bruno Goncalves <bgoncalv@redhat.com>
* Tue Jul 21 2020 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.4-4
- Rebased on top of additional commits staged for upstream
* Previous patches 0048-0060 are now patches 0053-0054 & 0059-0069
- Add 0048-libmultipath-add-device-to-hwtable.c.patch
- Add 0049-master-libmultipath-fix-use-after-free-when-iscsi-lo.patch
- Add 0050-libmultipath-warn-if-freeing-path-that-holds-mpp-hwe.patch
- Add 0051-libmultipath-warn-about-NULL-value-of-mpp-hwe.patch
- Add 0052-libmultipath-fix-mpp-hwe-handling-in-sync_paths.patch
- Add 0055-libmultipath-remove-code-duplication-in-path-countin.patch
- Add 0056-libmultipath-count-pending-paths-as-active-on-loads.patch
- Add 0057-libmultipath-deal-with-flushing-no-maps.patch
- Add 0058-multipath-deal-with-delegation-failures-correctly.patch
- Add 0070-multipath-add-libmpathvalid-library.patch
* adds the libmpathvalid.so library to determine if devices are
valid multipath paths.
- Add 0071-libmultipath-add-uid-failback-for-dasd-devices.patch
- Add 0072-libmultipath-add-ignore_udev_uid-option.patch
* Mon Jul 13 2020 Tom Stellard <tstellar@redhat.com> - 0.8.4-3
- Use make macros
- https://fedoraproject.org/wiki/Changes/UseMakeBuildInstallMacro
* Wed Jul 8 2020 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.4-2
- Rebased on top of Martin Wilck's queue of ACKed upstream commits
* https://github.com/openSUSE/multipath-tools/tree/upstream-queue
* All previous patches have been reordered, with the exception of
0011-libdmmp-Add-support-for-upcoming-json-c-0.14.0.patch
which has been replaced with
0029-fix-boolean-value-with-json-c-0.14.patch
- Modify 0054-RH-add-mpathconf.patch
* remove default enable_foreign and property blacklist_exceptions
settings, and deal with the builtin default change from
0031-libmultipath-set-enable_foreign-to-NONE-by-default.patch.
Fixes bz #1853668
- Add 0048-Makefile.inc-trim-extra-information-from-systemd-ver.patch
- Add 0049-kpartx-fix-Wsign-compare-error.patch
* The above two patches have been submitted upstream
* Fri May 29 2020 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.4-1
- Update Source to upstream version 0.8.4
* Previoud patches 0001-0020 & 0031 are included in this commit
- Rename files
* Previous patches 0021-0032 are now patches 0012-0022
- Add 0001-libmultipath-assign-variable-to-make-gcc-happy.patch
- Add 0002-libmutipath-don-t-close-fd-on-dm_lib_release.patch
- Add 0003-libmultipath-allow-force-reload-with-no-active-paths.patch
- Add 0004-libmpathpersist-depend-on-libmultipath.patch
- Add 0005-multipath-tools-Makefile-more-dependency-fixes-for-p.patch
- Add 0006-multipath-tools-Makefile.inc-set-Wno-error-clobbered.patch
- Add 0007-libmultipath-discovery.c-use-z-qualifier-for-size_t.patch
- Add 0008-libmultipath-eliminate-more-signed-unsigned-comparis.patch
- Add 0009-libmultipath-set_uint-fix-parsing-for-32bit.patch
- Add 0010-multipath-tools-Makefile-add-install-dependency.patch
- Add 0012-libmultipath-fix-condlog-NULL-argument-in-uevent_get.patch
- Add 0023-RH-work-around-gcc-10-format-truncation-issue.patch
* The above 10 patches have been submitted upstream
* Tue Apr 21 2020 Björn Esser <besser82@fedoraproject.org> - 0.8.2-6
- Rebuild (json-c)
* Mon Apr 13 2020 Björn Esser <besser82@fedoraproject.org> - 0.8.2-5
- Add 0032-add-support-for-upcoming-json-c-0.14.0.patch
* Mon Apr 13 2020 Björn Esser <besser82@fedoraproject.org> - 0.8.2-4
- Fix macro escaping in %%changelog
* Wed Feb 12 2020 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.2-3
- Add 0031-multipath-fix-issues-found-by-compiling-with-gcc-10.patch
* Patch submitted upstream
- Resolves bz #1799276
* Tue Jan 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 0.8.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Wed Sep 11 2019 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.2-1
- Update Source to upstream version 0.8.2
* Previoud patches 0001-0017 & 0027 are included in this commit
- Rename files
* Previous patches 0018-0026 & 0028 are not patches 0021-0030
- Add 0001-libmultipath-make-vector_foreach_slot_backwards-work.patch
- Add 0002-libmultipath-add-marginal-paths-and-groups-infrastru.patch
- Add 0003-tests-add-path-grouping-policy-unit-tests.patch
- Add 0004-libmultipath-add-wrapper-function-around-pgpolicyfn.patch
- Add 0005-tests-update-pgpolicy-tests-to-work-with-group_paths.patch
- Add 0006-libmultipath-fix-double-free-in-pgpolicyfn-error-pat.patch
- Add 0007-libmultipath-consolidate-group_by_-functions.patch
- Add 0008-libmultipath-make-pgpolicyfn-take-a-paths-vector.patch
- Add 0009-libmultipath-make-group_paths-handle-marginal-paths.patch
- Add 0010-tests-add-tests-for-grouping-marginal-paths.patch
- Add 0011-libmultipath-add-marginal_pathgroups-config-option.patch
- Add 0012-libmutipath-deprecate-delay_-_checks.patch
- Add 0013-multipathd-use-marginal_pathgroups.patch
- Add 0014-multipath-update-man-pages.patch
* The above 13 patches add the marinal_pathgroups option
- Add 0015-multipath.conf-add-enable_foreign-parameter.patch
- Add 0016-multipath.conf.5-document-foreign-library-support.patch
* The above 2 patches add the enable_foreign option
- Add 0017-mpathpersist-remove-broken-unused-code.patch
- Add 0018-libmultipath-EMC-PowerMax-NVMe-device-config.patch
- Add 0019-mpathpersist-fix-leaks.patch
- Add 0020-libmultipath-fix-mpcontext-initialization.patch
* The above 20 patches have been submitted upstream
* Wed Jul 24 2019 Fedora Release Engineering <releng@fedoraproject.org> - 0.8.0-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Fri Apr 12 2019 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.0-2
- Add 0028-RH-attempt-to-get-ANA-info-via-sysfs-first.patch
* try to get ANA state from sysfs first, with the ioctl as a fallback
* Thu Apr 4 2019 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.0-1
- Update Source to upstream version 0.8.0
* Previous patches 0006 & 0007 are included in this commit
- Rename files
* Previous patches 0008-0016 & 0100 are now patches 0018-0027
- Add 0006-multipathd-Fix-miscounting-active-paths.patch
- Add 0007-multipathd-ignore-failed-wwid-recheck.patch
* multipathd will no longer disable paths if it is unable to
get their wwid on a change event
- Add 0008-libmutipath-continue-to-use-old-state-on-PATH_PENDIN.patch
- Add 0009-multipathd-use-update_path_groups-instead-of-reload_.patch
- Add 0010-multipath.conf-add-missing-options-to-man-page.patch
- Add 0011-libmultipath-add-get_uid-fallback-code-for-NVMe-devi.patch
- Add 0012-libmulitpath-cleanup-uid_fallback-code.patch
- Add 0013-multipathd-handle-changed-wwids-by-removal-and-addit.patch
* if a path device changes wwid, it will now be removed and re-added
to the correct multipath device.
- Add 0014-multipathd-remove-wwid_changed-path-attribute.patch
- Add 0015-multipathd-ignore-disable_changed_wwids.patch
- Add 0016-multipathd-Don-t-use-fallback-code-after-getting-wwi.patch
- Add 0017-libmultipath-silence-dm_is_mpath-error-messages.patch
* The above 12 patches have been submitted upstream
* Sun Feb 17 2019 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 0.7.9-6.git2df6110
- Rebuild for readline 8.0
* Thu Jan 31 2019 Benjamin Marzinski <bmarzins@redhat.com> - 0.7.9-5.git2df6110
- Rename files
* Previous patch 0006-0014 are now patches 0008-0016
- Add 0006-multipathd-avoid-null-pointer-dereference-in-LOG_MSG.patch
- Add 0007-multipath-blacklist-zram-devices.patch
* The above 2 patches have been submitted upstream
- Resolves: bz #1672761
* Thu Jan 31 2019 Benjamin Marzinski <bmarzins@redhat.com> - 0.7.9-4.git2df6110
- Update Source to latest upstream commit
* previous patch 0001-libmultipath-dm_is_mpath-cleanup.patch is included
in this commit
- Rename files
* Previous patches 0002-0009 are now patches 0006-0013
- Add 0001-BZ-1668693-disable-user_friendly_names-for-NetApp.patch
- Add 0002-libmultipath-handle-existing-paths-in-marginal_path-.patch
- Add 0003-multipathd-cleanup-marginal-paths-checking-timers.patch
- Add 0004-libmultipath-fix-marginal-paths-queueing-errors.patch
- Add 0005-libmultipath-fix-marginal_paths-nr_active-check.patch
* The above 5 patches have been submitted upstream
- Add 0014-RH-Fix-nvme-compilation-warning.patch
* This change is only necessary because of Red Hat compilation
differences.
* Thu Jan 31 2019 Fedora Release Engineering <releng@fedoraproject.org> - 0.7.9-3.git17a6101
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Tue Jan 15 2019 Benjamin Marzinski <bmarzins@redhat.com> 0.7.9-2.git17a6101
- Update Source to latest upstream commit
* Previous patches 0001-0003 are included in this version
- Rename files
* Previous patches 0004-0011 are now patches 0002-0009
- Add 0001-libmultipath-dm_is_mpath-cleanup.patch
* This patch has been submitted upstream
* Mon Dec 3 2018 Benjamin Marzinski <bmarzins@redhat.com> 0.7.9-1
- Update Source to upstream version 0.7.9
* Previous patches 0001-0006 are included in this version
- Rename files
* Previous patches 0007-0014 are now patches 0004-0011
- Add 0001-multipathd-fix-mpp-hwe-handling-when-paths-are-freed.patch
- Add 0002-libmultipath-cleanup-pthread_cleanup_pop-call.patch
- Add 0003-libmultipath-fix-false-removes-in-dmevents-polling-c.patch
* The above 3 patches have been submitted upstream
* Wed Oct 10 2018 Benjamin Marzinski <bmarzins@redhat.com> 0.7.8-1
- Update Source to upstream version 0.7.8
* Previous patches 0001-0020 are included in this version
- Rename files
* Previous patches 0021-0025 are now patches 0001-0005
* Previous patches 0026-0033 are now patches 0007-0014
- Add 0006-libmultipath-timeout-on-unresponsive-tur-thread.patch
* has been submitted upstream
* Tue Oct 9 2018 Benjamin Marzinski <bmarzins@redhat.com> 0.7.7-7.gitb80318b
- Update Source to latest upstream commit
- Rename files
* Previous patches 0001-0020 are now patches 0002-0021
* Previous patches 0021-0028 are now patches 0026-0033
- Add 0001-kpartx-Use-absolute-paths-to-create-mappings.patch
- Add 0022-multipathd-check-for-NULL-udevice-in-cli_add_path.patch
- Add 0023-libmultipath-remove-max_fds-code-duplication.patch
- Add 0024-multipathd-set-return-code-for-multipathd-commands.patch
- Add 0025-mpathpersist-fix-registration-rollback-issue.patch
* The above 5 patches have been submitted upstream
* Thu Sep 27 2018 Benjamin Marzinski <bmarzins@redhat.com> 0.7.7-6.git1a8625a
- Update Source to latest upstream commit
* Previous patches 0001-0011 are included in this commit
- Rename files
* Previous patches 0012-0019 are now patches 0021-0028
- Add 0001-libmultipath-fix-tur-checker-timeout.patch
- Add 0002-libmultipath-fix-tur-checker-double-locking.patch
- Add 0003-libmultipath-fix-tur-memory-misuse.patch
- Add 0004-libmultipath-cleanup-tur-locking.patch
- Add 0005-libmultipath-fix-tur-checker-timeout-issue.patch
* The above 5 patches cleanup locking issues with the
tur checker threads
- Add 0006-libmultipath-fix-set_int-error-path.patch
- Add 0007-libmultipath-fix-length-issues-in-get_vpd_sgio.patch
- Add 0008-libmultipath-_install_keyword-cleanup.patch
- Add 0009-libmultipath-remove-unused-code.patch
- Add 0010-libmultipath-fix-memory-issue-in-path_latency-prio.patch
- Add 0011-libmultipath-fix-null-dereference-int-alloc_path_gro.patch
- Add 0012-libmutipath-don-t-use-malformed-uevents.patch
- Add 0013-multipath-fix-max-array-size-in-print_cmd_valid.patch
- Add 0014-multipathd-function-return-value-tweaks.patch
- Add 0015-multipathd-minor-fixes.patch
- Add 0016-multipathd-remove-useless-check-and-fix-format.patch
- Add 0017-multipathd-fix-memory-leak-on-error-in-configure.patch
* The above 12 patches fix minor issues found by coverity
- Add 0018-libmultipath-Don-t-blank-intialized-paths.patch
- Add 0019-libmultipath-Fixup-updating-paths.patch
* Fix issues with paths whose wwid was not set or later changes
- Add 0020-multipath-tweak-logging-style.patch
* multipathd interactive commands now send errors to stderr, instead
of syslog
* The above 20 patches have been submitted upstream
* Fri Sep 14 2018 Benjamin Marzinski <bmarzins@redhat.com> 0.7.7-5.gitef6d98b
- Add Conflicts for mdadm < 4.1-rc2.0.2 and udisks2 < 2.8.0-2
* Multipath udev rule update from 0.7.7-1 is incompatible with older versions
(bz #1628192)
* Thu Jul 12 2018 Benjamin Marzinski <bmarzins@redhat.com> 0.7.7-4.gitef6d98b
- Update Source to latest upstream commit
* Previous patches 0001-0018 are included in this commit
- Rename files
* Previous patches 0019-0028 are now patches 0002-0003 & 0012-0019
- Add 0001-libmultipath-remove-last-of-rbd-code.patch
- Add 0004-mpathpersist-add-param-alltgpt-option.patch
* mpathpersist now accepts --param-alltgpt
- Add 0005-libmutipath-remove-unused-IDE-bus-type.patch
- Add 0006-multipathd-add-new-protocol-path-wildcard.patch
* multipathd show paths format now accepts %%P for the path
protocol/transport
- Add 0007-libmultipath-add-protocol-blacklist-option.patch
* Wed Jul 18 2018 Benjamin Marzinski <bmarzins@redhat.com> 0.7.4-3.git07e7bd5
- Add 0023-libmutipath-remove-unused-IDE-bus-type.patch
- Add 0024-multipathd-add-new-protocol-path-wildcard.patch
* multipathd show paths format now accepts %P for the path protocol/transport
- Add 0025-libmultipath-add-protocol-blacklist-option.patch
* You can now use the "protocol" blacklist section parameter to blacklist
by protocol/transport
- Add 0008-libmultipath-remove-_filter_-blacklist-functions.patch
- Add 0009-multipath-tests-change-to-work-with-old-make-version.patch
- Add 0010-multipath-tests-add-blacklist-tests.patch
- Add 0011-mpathpersist-add-missing-param-rk-usage-info.patch
- Refresh 0013-RH-Remove-the-property-blacklist-exception-builtin.patch
- Modify 0016-RH-add-mpathconf.patch
* improve usage message and man page
* Thu Jul 12 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.7.7-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Sat Jun 30 2018 Peter Robinson <pbrobinson@fedoraproject.org> 0.7.7-2
- Spec cleanups, drop remains of initscripts dependencies
* Tue Jun 12 2018 Benjamin Marzinski <bmarzins@redhat.com> 0.7.7-1
- Update Source to 0.7.7
* Previous patches 0001-0009 & 0018 are included in this commit
- Add upstream patches since 0.7.7
* patches 0001-0012 are from upstream commits since 0.7.7
- Add 0015-mpathpersist-add-all_tg_pt-option.patch
* add new all_tg_pt multpiath.conf option. posted upstream
- Add 0016-libmultipath-remove-rbd-code.patch
* remove unused rbd code. posted upstream
- Add 0017-mpathpersist-fix-aptpl-support.patch
* add ":aptpl" suffix for reservation_key to fix aptpl support.
posted upstream
- Add 0018-multipath-don-t-check-timestamps-without-a-path.patch
* fix multipath null dereference crash. posted upstream
- Add 0019-libmultipath-fix-detect-alua-corner-case.patch
* fix alua detection with retain_hardware_handler set to off. posted
upstream
- Add 0020-multipath-fix-setting-conf-version.patch
* multipath wasn't setting the kernel version correctly. posted upstream
- Add 0028-RH-reset-default-find_mutipaths-value-to-off.patch
* default to RHEL7 and older device detection style. Redhat specific, to
keep customer experience the same.
- Rename files
* Previous patches 0010-0011 are now patches 0013-0014
* Previous patches 0012-0017 & 0019 are now patches 0021-0027
- Modify 0021-RH-fixup-udev-rules-for-redhat.patch
* Fix spurious compile warning with redhat compile options
* Tue May 15 2018 Benjamin Marzinski <bmarzins@redhat.com> 0.7.6-4.git1cb704b
- Add 0010-libmultipath-print-correct-default-for-delay_-_check.patch
* fix minor configuration printing issue
- Add 0011-multipath.conf.5-clarify-property-whitelist-handling.patch
* clarify property blacklist_excecptions handling in man page
- Rename files
* Previous patches 0010-0017 are now patches 0012-0019
- Modify 0013-RH-Remove-the-property-blacklist-exception-builtin.patch
* clarify changes in man page
* Tue Apr 24 2018 Benjamin Marzinski <bmarzins@redhat.com> 0.7.6-3.git1cb704b
- Add 0008-multipathd-add-failures-path-format-wildcard.patch
- Add 0009-multipathd-fix-reservation_key-check.patch
- Rename files
* Previous patches 0008-0015 are now patches 0010-0017
* Fri Apr 13 2018 Benjamin Marzinski <bmarzins@redhat.com> 0.7.6-2.git1cb704b
- Add 0007-libmultipath-Fix-logic-in-should_multipath.patch
* fix bug in identifying multipathable devices. posted upstream
- Rename files
* Previous patches 0007-0014 are now patches 0008-0015
* Mon Apr 02 2018 Benjamin Marzinski <bmarzins@redhat.com> 0.7.6-1.git1cb704b
- Update Source to the latest upstream commit
* Previous patches 0001-0014 are included in this commit
* Previous patches 0015-0022 are now patches 0007-0014
- 0001-multipathd-remove-incorrect-pthread_testcancel.patch
* Fixed pthread cancellation issue. posted upstream
- 0002-multipath-add-comments.patch
* Posted upstream
- 0003-multipathd-minor-dmevents-polling-code-cleanups.patch
* Fixed minor polling issues. posted upstream
- 0004-multipathd-remove-unneeded-function-parameter.patch
* Posted upstream
- 0005-mpathcmd-fix-libmpathcmd-license.patch
* License clarification. posted upstream
- 0006-libmultipath-don-t-print-undefined-values.patch
* Fixed bug in 'multipath show config'. posted upstream
* Tue Mar 06 2018 Björn Esser <besser82@fedoraproject.org> - 0.7.4-2.git07e7bd5
- Rebuilt for libjson-c.so.4 (json-c v0.13.1)

93
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
# }
#}

View file

@ -1,58 +0,0 @@
summary: basic functionality tests
provision:
hardware:
memory: ">= 2 GB"
prepare:
how: install
package:
- device-mapper-multipath
- perl
discover:
how: shell
tests:
- name: medium_error_scsi_debug
path: /tests/medium_error_scsi_debug
test: ./main.sh
duration: 15m
- name: squelch_scsi_id
path: /tests/squelch_scsi_id
test: ./main.sh
duration: 15m
- name: multipathd_oom
path: /tests/multipathd_oom
test: ./main.sh
duration: 15m
- name: user_friendly_names
path: /tests/user_friendly_names
test: ./main.sh
duration: 15m
- name: kpartx_4k_aligned
path: /tests/kpartx_4k_aligned
test: ./main.sh
duration: 15m
- name: bindings
path: /tests/bindings
test: ./main.sh
duration: 15m
- name: restate_module
path: /tests/restate_module
test: ./main.sh
duration: 15m
- name: find_multipaths
path: /tests/find_multipaths
test: ./main.sh
duration: 15m
- name: multipath_conf_syntax
path: /tests/multipath_conf_syntax
test: ./main.sh
duration: 15m
- name: alias_clash
path: /tests/alias_clash
test: ./main.sh
duration: 15m
execute:
how: tmt

View file

@ -1,2 +1,2 @@
SHA512 (multipath-tools-0.13.0.tgz) = 75c84524ee27590b8b751ea500898a44e5ac3d58d55be6bcab919d0d423049db3a4466fcb9135705cf63ba074416973bb651255063269e9f682f11d21ba57e59
SHA512 (multipath-tools-07e7bd5.tgz) = e84d451c8927119bac6612585d15497325da08d762ea6cde20d400a651fac599cb6edf4f9144204d91f92e04fec4ea3b955b9a9216ae82b513437b8ce516136a
SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942

View file

@ -1,675 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

View file

@ -1,20 +0,0 @@
verify that multipath doesn't try to assign new devices in-use user_friendly
aliases.
steps:
1. setup config file and remove existing bindings file
2. create scsi_debug devices
3. start multipathd to create devices and bindings file
4. look at path device ordering in multipathd output
5. stop multipathd and remove devices
6. blacklist the devices which were multipathed early in the config file
7. remove the bindings file
8. restart multipathd to create devices, where the later devices grab the
earlier user_friendly_names
9. stop multipathd
10. remove blacklists from the config file and remove bindings file
11. restart multipathd
12. Verify that all devices are there, the previously existing devices
still have the same alias, and all the devices match the bindings file
13. reconfigure multipathd
14. Verify that all devices are still there and still match.

View file

@ -1,122 +0,0 @@
#!/bin/bash
# Copyright (c) 2021 Red Hat, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Author: Benjamin Marzinski <bmarzins@redhat.com>
source ../include/ec.sh || exit 200
tlog "running $0"
cleanup ()
{
trun "multipathd disablequeueing maps"
sleep 5
trun "multipath -DF"
trun "service multipathd stop"
sleep 5
trun "udevadm settle"
trun "modprobe -r scsi_debug"
}
assert ()
{
local cmd="$*"
_trun_ "$cmd" 0
if test $? -eq 0; then
tpass_ "$cmd" ;
else
tfail_ "$cmd" ;
cleanup ;
tend ;
fi
}
tlog "running $0"
rpm -q device-mapper-multipath || dnf install -y device-mapper-multipath
# cleanup existing devices and restart
cleanup
trun "rm -f /etc/multipath.conf"
trun "rm -f /etc/multipath.conf.bak"
trun "rm -r /etc/multipath/bindings"
trun "mpathconf --enable --with_module y --with_multipathd n --find_multipaths n"
sed -i '/^blacklist[[:space:]]*{/ a\
device {\n vendor ".*"\n product ".*"\n }
' /etc/multipath.conf
if grep -qw blacklist_exceptions /etc/multipath.conf ; then
sed -i '/^blacklist_exceptions[[:space:]]*{/ a\
device {\n vendor Linux\n product scsi_debug\n }
' /etc/multipath.conf
else
cat << _EOF_ >> /etc/multipath.conf
blacklist_exceptions {
device {
vendor Linux
product scsi_debug
}
}
_EOF_
fi
trun "modprobe scsi_debug num_tgts=20 vpd_use_hostno=0"
sleep 5
trun "service multipathd start"
sleep 5
pathcount=`multipathd show paths raw format %w | wc -l`
assert "[[ $pathcount -eq 20 ]]"
wwids=`multipathd show paths raw format " wwid %w" | sed '11,$d'`
wwids="${wwids//$'\n'/\\n}"
trun "multipath -DF"
trun "service multipathd stop"
sleep 5
tnot "pidof multipathd"
tok "cp /etc/multipath.conf /etc/mulitpath.conf.bak"
sed -i '/^blacklist[[:space:]]*{/ a\
'"$wwids"'
' /etc/multipath.conf
tok "rm -f /etc/multipath/bindings"
trun "service multipathd start"
sleep 5
mapcount=`multipathd show maps raw format %w | wc -l`
assert "[[ $mapcount -eq 10 ]]"
orig_maps=`multipathd show maps raw format "%n %w"`
trun "service multipathd stop"
sleep 5
tnot "pidof multipathd"
tok "mv -f /etc/mulitpath.conf.bak /etc/multipath.conf"
tok "rm -f /etc/multipath/bindings"
trun "service multipathd start"
sleep 5
mapcount=`multipathd show maps raw format %w | wc -l`
assert "[[ $mapcount -eq 20 ]]"
new_maps=`multipathd show maps raw format "%n %w" | sort`
tlog "Checking if devices have been renamed"
while IFS= read -r line; do
echo "$new_maps" | grep "$line"
assert "[[ $? -eq 0 ]]"
done <<< "$orig_maps"
bindings=`cat /etc/multipath/bindings | sed '/^#.*$/d' | sort`
tlog "Checking if devices match bindings"
assert "[[ \"$new_maps\" = \"$bindings\" ]]"
trun "service multipathd reload"
sleep 5
mapcount=`multipathd show maps raw format %w | wc -l`
assert "[[ $mapcount -eq 20 ]]"
reload_maps=`multipathd show maps raw format "%n %w" | sort`
tlog "Checking if devices change on reconfigure"
assert "[[ \"$new_maps\" = \"$reload_maps\" ]]"
cleanup
tend

49
tests/bindings/Makefile Normal file
View file

@ -0,0 +1,49 @@
#!/bin/bash
# Copyright (c) 2016 Red Hat, Inc.
# #
# # This program is free software: you can redistribute it and/or modify
# # it under the terms of the GNU General Public License as published by
# # the Free Software Foundation, either version 3 of the License, or
# # (at your option) any later version.
# #
# # This program is distributed in the hope that it will be useful,
# # but WITHOUT ANY WARRANTY; without even the implied warranty of
# # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# # GNU General Public License for more details.
# #
# # You should have received a copy of the GNU General Public License
# # along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# # Author: Lin Li <lilin@redhat.com>
.PHONY: all install download clean
BUILT_FILES=
FILES=$(METADATA) Makefile PURPOSE main.sh
run: $(FILES) build
./main.sh
build: $(BUILT_FILES)
chmod a+x ./main.sh
clean:
rm -f *~ *.rpm $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@touch $(METADATA)
@echo "Owner: LiLin <lilin@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "License: GPLv3" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Description: bindings" >> $(METADATA)
@echo "TestTime: 15m" >> $(METADATA)
@echo "RunFor: device-mapper-multipath" >> $(METADATA)
@echo "Requires: device-mapper-multipath" >> $(METADATA)
rhts-lint $(METADATA)

View file

@ -18,110 +18,40 @@
# Author: Lin Li <lilin@redhat.com>
#set -x
source ../include/tc.sh || exit 200
source ../include/ec.sh || exit 200
tlog "running $0"
cleanup ()
{
local retries
if pidof multipathd; then
tlog "stopping multipathd"
trun "systemctl stop multipathd.service || pkill multipathd"
sleep 1
fi
retries=10
while pidof multipathd; do
((retries--))
if [[ $retries -le 0 ]]; then
tfail_ "failed to stop multipath"
tend
fi
tlog "waiting for multipathd to stop"
sleep 2
pidof multipathd && pkill multipathd
done
trun "multipath -l -v1"
retries=10
while [[ -n `multipath -l -v1` ]]; do
((retries--))
if [[ $retries -le 0 ]]; then
tfail_ "failed to remove deviece"
tend
fi
tlog "removing multipath device"
trun "udevadm settle"
trun "multipath -DF"
sleep 2
done
if lsmod | grep -q "^scsi_debug"; then
tlog "removing scsi_debug module"
tok "rmmod scsi_debug"
fi
trun "rm -f /etc/multipath.conf"
}
assert ()
{
local cmd="$*"
_trun_ "$cmd" 0
if test $? -eq 0; then
tpass_ "$cmd" ;
else
tfail_ "$cmd" ;
cleanup ;
tend ;
fi
}
setup_config ()
{
trun "mpathconf --enable --user_friendly_names y"
sed -i '/^blacklist[[:space:]]*{/ a\
device {\
vendor ".*"\
product ".*"\
}
' /etc/multipath.conf
cat << _EOF_ >> /etc/multipath.conf
blacklist_exceptions {
device {
vendor Linux
product scsi_debug
}
}
_EOF_
trun "cat /etc/multipath.conf"
}
do_reconfigure ()
{
tok "multipathd reconfigure"
sleep 5
}
rpm -q device-mapper-multipath || dnf install -y device-mapper-multipath
cleanup
setup_config
trun "rm -r /etc/multipath/bindings"
trun "modprobe scsi_debug vpd_use_hostno=0 add_host=2"
trun "service multipathd stop"
rpm -q device-mapper-multipath || yum install -y device-mapper-multipath
trun "mpathconf --enable --with_multipathd y --user_friendly_names y"
trun "service multipathd status"
sleep 5
trun "systemctl start multipathd.service"
while multipathd show daemon | grep -qv idle; do
tlog "waiting for multipathd to start"
sleep 1
done
trun 'multipathd show maps raw format "%n"'
mpath_name=`multipathd show maps raw format "%n" | head -1`
assert "[[ -n $mpath_name ]] && [[ $mpath_name != ok ]]"
trun "multipath -F"
sleep 5
terr "modprobe -r scsi_debug"
terr "modprobe scsi_debug dev_size_mb=1024 num_tgts=1 vpd_use_hostno=0 \
add_host=2 delay=20 max_luns=2 no_lun_0=1"
sleep 60
disk_path=$(get_scsi_debug_devices)
disk=$(basename $disk_path)
mpath_name=$(get_mpath_disk_by_scsi_device $disk)
new_alias="mpath_test_$$"
trun "sed -i 's/$mpath_name/$new_alias/' /etc/multipath/bindings"
do_reconfigure
trun 'multipathd show maps raw format "%n"'
mpath_name=`multipathd show maps raw format "%n" | head -1`
assert "[[ $mpath_name = $new_alias ]]"
trun "multipath -r"
sleep 5
tok "[[ -b /dev/mapper/$new_alias ]]"
tok is_mpath $new_alias
sleep 5
cleanup
trun "multipath -F"
sleep 5
trun "modprobe -r scsi_debug"
trun "service multipathd stop"
sleep 3
trun "multipath -W"
trun "rm /etc/multipath/bindings"
tend

View file

@ -0,0 +1,49 @@
#!/bin/bash
# Copyright (c) 2016 Red Hat, Inc.
# #
# # This program is free software: you can redistribute it and/or modify
# # it under the terms of the GNU General Public License as published by
# # the Free Software Foundation, either version 3 of the License, or
# # (at your option) any later version.
# #
# # This program is distributed in the hope that it will be useful,
# # but WITHOUT ANY WARRANTY; without even the implied warranty of
# # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# # GNU General Public License for more details.
# #
# # You should have received a copy of the GNU General Public License
# # along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# # Author: Lin Li <lilin@redhat.com>
.PHONY: all install download clean
BUILT_FILES=
FILES=$(METADATA) Makefile PURPOSE main.sh
run: $(FILES) build
./main.sh
build: $(BUILT_FILES)
chmod a+x ./main.sh
clean:
rm -f *~ *.rpm $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@touch $(METADATA)
@echo "Owner: LiLin <lilin@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "License: GPLv3" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Description: find_multipaths" >> $(METADATA)
@echo "TestTime: 15m" >> $(METADATA)
@echo "RunFor: device-mapper-multipath" >> $(METADATA)
@echo "Requires: device-mapper-multipath" >> $(METADATA)
rhts-lint $(METADATA)

View file

@ -18,162 +18,77 @@
# Author: Lin Li <lilin@redhat.com>
#set -x
source ../include/tc.sh || exit 200
source ../include/ec.sh || exit 200
tlog "running $0"
remove_devices ()
{
local retries
retries=10
while [[ -n `multipath -l -v1` ]]; do
((retries--))
if [[ $retries -le 0 ]]; then
tfail_ "failed to remove devices"
cleanup
tend
fi
tlog "removing multipath devices"
trun "udevadm settle"
trun "multipath -F"
sleep 2
done
}
# which not set find_multipaths yes, so multipath always create a multipath device for single device
# so stop service and reconfig with --find_multipaths y, and reload/start the service again.
trun "service multipathd stop"
rpm -q device-mapper-multipath || yum install -y device-mapper-multipath
cleanup ()
{
local retries
if pidof multipathd; then
tlog "stopping multipathd"
trun "systemctl stop multipathd.service || pkill multipathd"
sleep 1
fi
retries=10
while pidof multipathd; do
((retries--))
if [[ $retries -le 0 ]]; then
tfail_ "failed to stop multipath"
tend
fi
tlog "waiting for multipathd to stop"
sleep 2
pidof multipathd && pkill multipathd
done
trun "multipath -l -v1"
retries=10
while [[ -n `multipath -l -v1` ]]; do
((retries--))
if [[ $retries -le 0 ]]; then
tfail_ "failed to remove devices"
tend
fi
tlog "removing multipath devices"
trun "udevadm settle"
trun "multipath -DF"
sleep 2
done
if lsmod | grep -q "^scsi_debug"; then
tlog "removing scsi_debug module"
tok "rmmod scsi_debug"
fi
trun "rm -f /etc/multipath.conf"
trun "rm -f /etc/multipath/wwids"
trun "rm -r /etc/multipath/bindings"
}
assert ()
{
local cmd="$*"
_trun_ "$cmd" 0
if test $? -eq 0; then
tpass_ "$cmd" ;
else
tfail_ "$cmd" ;
cleanup ;
tend ;
fi
}
setup_config ()
{
trun "mpathconf --enable --user_friendly_names y --find_multipaths y"
sed -i '/^blacklist[[:space:]]*{/ a\
device {\
vendor ".*"\
product ".*"\
}
' /etc/multipath.conf
cat << _EOF_ >> /etc/multipath.conf
blacklist_exceptions {
device {
vendor Linux
product scsi_debug
}
}
_EOF_
trun "cat /etc/multipath.conf"
}
do_reconfigure ()
{
trun "cat /etc/multipath.conf"
tok "multipathd reconfigure"
sleep 5
}
trun "rpm -q device-mapper-multipath || dnf install -y device-mapper-multipath"
cleanup
setup_config
# test with find_multipath=y, will not multipath the single device
# test with find_multipath=y, will not multipath for the single device; reload/start the service to enable the config
trun "mpathconf --enable --user_friendly_names y --find_multipaths y --with_multipathd y"
trun "service multipathd status"
# use scsi_debug to simulate a drive
trun "multipath -F"
terr "modprobe -r scsi_debug"
trun "modprobe scsi_debug"
sleep 5
trun "systemctl start multipathd.service"
while multipathd show daemon | grep -qv idle; do
tlog "waiting for multipathd to start"
sleep 1
done
trun 'multipathd show paths raw format "%d %m"'
trun 'cat /etc/multipath/wwids'
mpath_name=`multipathd show paths raw format "%m" | head -1`
tok "[[ $mpath_name = '[orphan]' ]]"
remove_devices
# test with find_multipath=n, will multipath the single device
trun 'mpathconf --find_multipaths n'
do_reconfigure
trun 'multipathd show paths raw format "%d %m"'
trun 'cat /etc/multipath/wwids'
mpath_name=`multipathd show paths raw format "%m" | head -1`
tok "[[ -n $mpath_name ]] && [[ $mpath_name != '[orphan]' ]]"
remove_devices
# test with find_multipath=y, with multipath single device with known WWID
trun 'mpathconf --find_multipaths y'
do_reconfigure
trun 'multipathd show paths raw format "%d %m"'
trun 'cat /etc/multipath/wwids'
mpath_name=`multipathd show paths raw format "%m" | head -1`
tok "[[ -n $mpath_name ]] && [[ $mpath_name != '[orphan]' ]]"
remove_devices
# Clear WWID, test with find_multipath=y, will not multipath single device
sleep 3
trun "multipath -W"
do_reconfigure
trun 'multipathd show paths raw format "%d %m"'
trun 'cat /etc/multipath/wwids'
mpath_name=`multipathd show paths raw format "%m" | head -1`
tok "[[ $mpath_name = '[orphan]' ]]"
remove_devices
assert 'rmmod scsi_debug'
cat /etc/multipath/wwids
trun "multipath"
disk_path=$(get_scsi_debug_devices)
disk_node=$(basename $disk_path)
mpath_name=$(get_mpath_disk_by_scsi_device $disk_node)
tok '[[ -z $mpath_name ]]'
# test with find_multipath=n, will multipath for the single device
trun "mpathconf --enable --user_friendly_names y --find_multipaths n --with_multipathd y"
sleep 5
trun "multipath"
mpath_name=$(get_mpath_disk_by_scsi_device $disk_node)
tok "is_mpath $mpath_name"
# flush new created path
sleep 3
trun "multipath -F"
sleep 3
# test with find_multipath=y, A path has the same WWID as a multipath device that was previously created
trun "mpathconf --enable --user_friendly_names y --find_multipaths y --with_multipathd y"
sleep 5
trun "multipath"
mpath_name=$(get_mpath_disk_by_scsi_device $disk_node)
tok "is_mpath $mpath_name"
# Clear wwid, test with find_multipath=y, will not multipath for the single device
trun "multipath -W"
trun "mpathconf --disable --with_multipathd y"
sleep 5
mpath_name=$(get_mpath_disk_by_scsi_device $disk_node)
tok '[[ -z $mpath_name ]]'
trun "multipath -F"
sleep 5
trun "modprobe -r scsi_debug"
# test find_multipaths=y create device for paths have same wwid
trun "modprobe scsi_debug vpd_use_hostno=0 add_host=2"
sleep 5
trun 'multipathd show paths raw format "%d %m"'
trun 'cat /etc/multipath/wwids'
mpath_name=`multipathd show paths raw format "%m" | head -1`
tok "[[ -n $mpath_name ]] && [[ $mpath_name != '[orphan]' ]]"
tok "modprobe scsi_debug num_tgts=1 vpd_use_hostno=0 add_host=2 delay=20 max_luns=2 no_lun_0=1"
sleep 10
disk_paths=$(get_scsi_debug_devices)
disk_node=$(basename $disk_paths)
mpath_name=$(get_mpath_disk_by_scsi_device $disk_node)
tok "is_mpath $mpath_name"
cleanup
sleep 10
trun "multipath -F"
sleep 5
trun "modprobe -r scsi_debug"
# remove the scsi_debug wwid
trun "service multipathd stop"
sleep 3
trun "multipath -W"
cat /etc/multipath/wwids
tend

View file

@ -44,12 +44,9 @@ function _init (){
}
function _destroy (){
Cmd "multipathd disablequeueing maps"
sleep 10
Cmd "multipath -F"
sleep 5
Cmd "multipath -DF -R2"
Cmd "service multipathd stop"
sleep 5
Cmd "udevadm settle"
Cmd "modprobe -r scsi_debug"
}
@ -177,7 +174,16 @@ AA
fi
#setup scsi_debug
echo "INFO: Loading scsi_debug module for simulation of mpath"
modprobe scsi_debug vpd_use_hostno=0 add_host=2
local dev_size=100
if [ "CHK$(uname -m)" == "CHKi386" ] \
|| [ "CHK$(uname -m)" == "CHKi686" ]; then
#i386 platform cannot allocate 100 MiB in kernel space
dev_size=10
fi
modprobe scsi_debug dev_size_mb=${dev_size} \
num_tgts=1 vpd_use_hostno=0 \
add_host=4 delay=20 \
max_luns=2 no_lun_0=1 2>&1 1>/dev/null
echo "INFO: Waiting for udev to create /dev/sdX"
sleep 15s #wait for udev to create /dev/sdX
@ -189,6 +195,8 @@ AA
#enable multipath for scsi_debug.
cat << AA > /etc/multipath.conf
defaults {
#Enable multibus is for mutlbus testing
path_grouping_policy multibus
user_friendly_names yes
}
blacklist {

View file

@ -78,7 +78,8 @@ get_mpath_disk_by_scsi_device()
{
# multipathd_running || texit "multipathd is not running"
local disk=$1
local mpath=$(multipathd show paths raw format "%d,%m" | grep "^$disk\s*," \
wwid=$(get_wwid_of_disk $disk)
local mpath=$(multipathd show maps format %w,%n | grep "^$wwid\s*," \
| awk -F, '{ print $2 }' | sed 's/\s//g')
echo $mpath
}

View file

@ -0,0 +1,49 @@
#!/bin/bash
# Copyright (c) 2016 Red Hat, Inc.
# #
# # This program is free software: you can redistribute it and/or modify
# # it under the terms of the GNU General Public License as published by
# # the Free Software Foundation, either version 3 of the License, or
# # (at your option) any later version.
# #
# # This program is distributed in the hope that it will be useful,
# # but WITHOUT ANY WARRANTY; without even the implied warranty of
# # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# # GNU General Public License for more details.
# #
# # You should have received a copy of the GNU General Public License
# # along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# # Author: Lin Li <lilin@redhat.com>
.PHONY: all install download clean
BUILT_FILES=
FILES=$(METADATA) Makefile PURPOSE main.sh
run: $(FILES) build
./main.sh
build: $(BUILT_FILES)
chmod a+x ./main.sh
clean:
rm -f *~ *.rpm $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@touch $(METADATA)
@echo "Owner: LiLin <lilin@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "License: GPLv3" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Description: kpartx_4k_aligned" >> $(METADATA)
@echo "TestTime: 15m" >> $(METADATA)
@echo "RunFor: device-mapper-multipath" >> $(METADATA)
@echo "Requires: device-mapper-multipath" >> $(METADATA)
rhts-lint $(METADATA)

View file

@ -0,0 +1,47 @@
# Copyright (c) 2006 Red Hat, Inc. 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.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# 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., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# Author: LiLin <lilin@redhat.com>
.PHONY: all install download clean
BUILT_FILES=
FILES=$(METADATA) Makefile PURPOSE main.sh
run: $(FILES) build
./main.sh
build: $(BUILT_FILES)
chmod a+x ./main.sh
clean:
rm -f *~ *.rpm $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@touch $(METADATA)
@echo "Owner: LiLin <lilin@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "License: GPLv3" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Description: CEE feedback" >> $(METADATA)
@echo "TestTime: 15m" >> $(METADATA)
@echo "RunFor: device-mapper-multipath" >> $(METADATA)
@echo "Requires: device-mapper-multipath" >> $(METADATA)
rhts-lint $(METADATA)

View file

@ -1,8 +1,8 @@
multipath: Test that some fatal errors which should not be retried, for example a medium error, correctly generate an I/O error and do not get infinitely retried.
steps:
1.# modprobe scsi_debug num_tgts=1 vpd_use_hostno=0 add_host=2 delay=20 max_luns=2 no_lun_0=1 opts=2
1.# modprobe scsi_debug dev_size_mb=1024 num_tgts=1 vpd_use_hostno=0 add_host=2 delay=20 max_luns=2 no_lun_0=1 opts=2 every_nth=1
2.# multipath -ll | grep -C 5 scsi_debug
3.# dd if=/dev/zero of=/dev/mapper/$mpathdev bs=1024 seek=2330 count=10
3.# dd if=/dev/zero of=/dev/sdf bs=1024 count=262144
4. check if an I/O error generated

View file

@ -16,51 +16,40 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Author: LiLin <lilin@redhat.com>
source ../include/tc.sh || exit 200
cleanup()
function cleanup()
{
sleep 5
udevadm settle
trun "multipath -DF"
sleep 5
trun "modprobe -r scsi_debug"
multipath -F
service multipathd stop
sleep 15
modprobe -r scsi_debug
rt=$?
while [ $rt -ne 0 ]
do
sleep 15
modprobe -r scsi_debug
rt=$?
done
}
assert ()
{
local cmd="$*"
_trun_ "$cmd" 0
if test $? -eq 0; then
tpass_ "$cmd" ;
else
tfail_ "$cmd" ;
cleanup ;
tend ;
fi
}
tlog "running $0"
rpm -q device-mapper-multipath || dnf install -y device-mapper-multipath
trun "multipathd disablequeueing maps"
cleanup
trun "service multipathd stop"
trun "rm -f /etc/multipath.conf"
trun "mpathconf --enable"
trun "modprobe scsi_debug vpd_use_hostno=0 add_host=2 opts=2"
yum -y install device-mapper device-mapper-multipath
mpathconf --enable
modprobe scsi_debug dev_size_mb=1024 num_tgts=1 vpd_use_hostno=0 add_host=2 delay=20 max_luns=2 no_lun_0=1 opts=2 every_nth=1
sleep 5
trun "multipath"
sleep 5
trun "multipath -l"
mpathdev=`multipath -l | grep scsi_debug | awk '{print $1}' | head -1`
assert "[[ -n \"$mpathdev\" ]]"
before_active=`multipath -l $mpathdev | grep "active undef" | wc -l`
tlog "before active = ${before_active}"
service multipathd restart
sleep 10
disk1=`multipath -ll | grep -A 5 scsi_debug | grep -oE "sd." | head -1`
if [ -z "$disk1" ]; then
cleanup
exit 1
fi
IO_error=`dd if=/dev/zero of=/dev/mapper/$mpathdev bs=1024 seek=2330 count=10 2>&1 | grep -o "Input/output error" `
assert "[[ -n \"$IO_error\" ]]"
after_active=`multipath -l $mpathdev | grep "active undef" | wc -l`
tlog "after active = ${after_active}"
assert "[[ \"$before_active\" -eq \"$after_active\" ]]"
cleanup
tend
IO_error=`dd if=/dev/zero of=/dev/$disk1 bs=1024 count=262144 2>&1 | grep -o "Input/output error" `
if [ -n "$IO_error" ];then
echo "------- PASS, a medium error, correctly generate an I/O error and do not get infinitely retried -----"
cleanup
else
echo "------- FAIL, not generate an I/O error -----"
cleanup
exit -1
fi

View file

@ -17,129 +17,88 @@
# Author: Lin Li <lilin@redhat.com>
source ../include/ec.sh || exit 200
tlog "running $0"
cleanup ()
{
trun "multipathd disablequeueing maps"
sleep 5
trun "multipath -F"
trun "service multipathd stop"
sleep 5
trun "udevadm settle"
trun "modprobe -r scsi_debug"
}
# Include Beaker environment
. /usr/bin/rhts-environment.sh || exit 1
. /usr/share/beakerlib/beakerlib.sh || exit 1
assert ()
{
local cmd="$*"
_trun_ "$cmd" 0
if test $? -eq 0; then
tpass_ "$cmd" ;
else
tfail_ "$cmd" ;
cleanup ;
tend ;
fi
}
PACKAGE="device-mapper-multipath"
rpm -q device-mapper-multipath || yum install -y device-mapper-multipath
rlJournalStart
rlPhaseStartSetup
rlAssertRpm $PACKAGE
rlRun "multipath -F; sleep 5"
rlRun "modprobe -r scsi_debug" 0 "Remove if scsi_debug load before"
rlRun "rm -f /etc/multipath.conf"
rlRun "mpathconf --enable --with_module y --with_multipathd y --find_multipaths n" 0 "Set up multipath"
rlServiceStart multipathd
rlRun "cp /etc/multipath.conf /etc/multipath.conf.bak" 0 "Backup /etc/multipath.conf first"
rlPhaseEnd
# cleanup existing devices and restart
cleanup
trun "rm -f /etc/multipath.conf"
trun "mpathconf --enable --with_module y --with_multipathd n --find_multipaths n"
sed -i '/^blacklist[[:space:]]*{/ a\
device {\n vendor ".*"\n product ".*"\n }
' /etc/multipath.conf
if grep -qw blacklist_exceptions /etc/multipath.conf ; then
sed -i '/^blacklist_exceptions[[:space:]]*{/ a\
device {\n vendor Linux\n product scsi_debug\n }
' /etc/multipath.conf
else
cat << _EOF_ >> /etc/multipath.conf
blacklist_exceptions {
device {
vendor Linux
product scsi_debug
}
}
_EOF_
fi
trun "cp /etc/multipath.conf /etc/multipath.conf.bak"
trun "service multipathd stop"
trun "service multipathd start"
trun "modprobe scsi_debug"
sleep 5
trun "multipath -ll"
pathcount=`multipathd show maps format %w | grep -v uuid | wc -l`
assert "[[ $pathcount -eq 1 ]]"
wwid=`multipathd show maps format %w | grep -v uuid`
# test missing closing quote on alias
cat << _EOF_ >> /etc/multipath.conf
rlPhaseStartTest
rlRun "modprobe scsi_debug"
sleep 5
rlLogInfo "`multipath -ll`"
wwid=`multipathd show maps format %w | grep -v uuid`
# test missing closing quote on alias
cat << _EOF_ >> /etc/multipath.conf
multipaths {
multipath {
wwid "$wwid"
alias "mypath
}
multipath {
wwid "$wwid"
alias "mypath
}
}
_EOF_
tok "multipath 2>&1 | grep 'missing closing quotes on line'"
trun "multipath -r"
tok "multipath -ll | grep mypath"
rlRun "multipath 2>&1 | grep 'missing closing quotes on line'" 0 "test missing closing quote on alias"
rlRun "multipath -r |grep mypath" 0 "mpath rename to mypath"
# test no value for alias
trun "sed -i 's/alias.*$/alias/g' /etc/multipath.conf"
multipath
tok "multipath 2>&1 | grep \"missing value for option 'alias' on line\""
trun "multipath -r"
tok "multipath -ll | grep mpath"
# test no value for alias
rlRun "sed -i 's/alias.*$/alias/g' /etc/multipath.conf"
rlRun "multipath 2>&1 | grep \"missing value for option 'alias' on line\"" 0 "test no value for alias"
rlRun "multipath -r |grep mpath*" 0 "mpath rename to mpath* from mypath"
# test missing starting quote on alias
trun "sed -i 's/alias.*$/alias mypath\"/g' /etc/multipath.conf"
tok "multipath 2>&1 |grep 'ignoring extra data starting with'"
trun "multipath -r"
tok "multipath -ll | grep mypath"
# test missing starting quote on alias
rlRun "sed -i 's/alias.*$/alias mypath\"/g' /etc/multipath.conf"
rlRun "multipath 2>&1 |grep 'ignoring extra data starting with'" 0 "test missing starting quote on alias"
rlRun "multipath -r |grep mypath" 0 "mpath rename to mypath"
# test wrong quote on alias
trun "sed -i 's/alias.*$/alias <mypath>/g' /etc/multipath.conf"
tnot "multipath 2>&1 | grep config"
trun "multipath -r"
tok "multipath -ll | grep '<mypath>'"
# test wrong quote on alias
rlRun "sed -i 's/alias.*$/alias <mypath>/g' /etc/multipath.conf"
rlRun "multipath 2>&1 | grep config" 1 "no warning"
rlRun "multipath -r |grep '<mypath>'" 0 "mpath rename to <mypath>"
# test value has a space
trun "sed -i 's/alias.*$/alias mypath test/g' /etc/multipath.conf"
tok "multipath 2>&1 |grep 'ignoring extra data starting with'"
trun "multipath -r"
tok "multipath -ll | grep mypath"
# test value has a space
rlRun "sed -i 's/alias.*$/alias mypath test/g' /etc/multipath.conf"
rlRun "multipath 2>&1 |grep 'ignoring extra data starting with'" 0 "test value has a space"
rlRun "multipath -r |grep mypath" 0 "mpath rename to mypath"
# test wrong alias keyword
trun "sed -i 's/alias.*$/alia mypath/g' /etc/multipath.conf"
tok "multipath 2>&1 | grep 'invalid keyword in the multipath section: alia'"
trun "multipath -r"
tok "multipath -ll | grep mpath"
trun "sed -i 's/alia.*$/alias mypath/g' /etc/multipath.conf"
# test wrong alias keyword
rlRun "sed -i 's/alias.*$/alia mypath/g' /etc/multipath.conf"
rlRun "multipath 2>&1 |grep 'invalid keyword: alia'" 0 "invalid keyword: alia"
rlRun "multipath -r |grep mpath*" 0 "mpath rename to mpath* from mypath"
rlRun "sed -i 's/alia.*$/alias mypath/g' /etc/multipath.conf"
# test no space between the section name and the open bracket that followed it
# fix issue about if a section doesn't have a space between the section name
# and the open bracket, that section isn't read in.
trun "sed -i 's/multipaths.*/multipaths{/g' /etc/multipath.conf"
tnot "multipath 2>&1 | grep config"
trun "multipath -r"
tok "multipath -ll |grep mypath"
# test no space between the section name and the open bracket that followed it
# fix issue about if a section doesn't have a space between the section name and the open bracket, that section isn't read in.
rlRun "sed -i 's/multipaths.*/multipaths{/g' /etc/multipath.conf"
rlRun "multipath 2>&1 | grep config" 1 "no warning"
rlRun "multipath -r |grep mypath" 0 "mpath rename to mypath"
# test wrong section keywords
trun "sed -i 's/multipaths.*/ultipaths {/g' /etc/multipath.conf"
tok "multipath 2>&1 | grep 'invalid keyword: ultipaths'"
trun "sed -i 's/defaults.*/efaults {/g' /etc/multipath.conf"
tok "multipath 2>&1 | grep 'invalid keyword: efaults'"
trun "sed -i 's/blacklist {/lacklist {/g' /etc/multipath.conf"
tok "multipath 2>&1 | grep 'invalid keyword: lacklist'"
trun "mv /etc/multipath.conf.bak /etc/multipath.conf"
# test wrong section keywords
rlRun "sed -i 's/multipaths.*/ultipaths {/g' /etc/multipath.conf"
rlRun "multipath 2>&1 | grep 'invalid keyword: ultipaths'" 0 "test wrong multipaths section keyword"
rlRun "sed -i 's/defaults.*/efaults {/g' /etc/multipath.conf"
rlRun "multipath 2>&1 | grep 'invalid keyword: efaults'" 0 "test wrong defaults section keyword"
rlRun "sed -i 's/blacklist {/lacklist {/g' /etc/multipath.conf"
rlRun "multipath 2>&1 | grep 'invalid keyword: lacklist'" 0 "test wrong blacklist section keyword"
cleanup
tend
rlPhaseEnd
rlPhaseStartCleanup
rlRun "multipath -F" 0 "Flush all unused multipath device maps"
rlServiceStop multipathd
rlRun "modprobe -r scsi_debug" 0 "Remove scsi_debug"
rlRun "cp -f /etc/multipath.conf.bak /etc/multipath.conf" 0 "Recovery /etc/multipath.conf"
rlPhaseEnd
rlJournalPrintText
rlJournalEnd

View file

@ -0,0 +1,49 @@
#!/bin/bash
# Copyright (c) 2016 Red Hat, Inc.
# #
# # This program is free software: you can redistribute it and/or modify
# # it under the terms of the GNU General Public License as published by
# # the Free Software Foundation, either version 3 of the License, or
# # (at your option) any later version.
# #
# # This program is distributed in the hope that it will be useful,
# # but WITHOUT ANY WARRANTY; without even the implied warranty of
# # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# # GNU General Public License for more details.
# #
# # You should have received a copy of the GNU General Public License
# # along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# # Author: Lin Li <lilin@redhat.com>
.PHONY: all install download clean
BUILT_FILES=
FILES=$(METADATA) Makefile PURPOSE main.sh
run: $(FILES) build
./main.sh
build: $(BUILT_FILES)
chmod a+x ./main.sh
clean:
rm -f *~ *.rpm $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@touch $(METADATA)
@echo "Owner: LiLin <lilin@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "License: GPLv3" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Description: multipathd invoked oom-killer" >> $(METADATA)
@echo "TestTime: 15m" >> $(METADATA)
@echo "RunFor: device-mapper-multipath" >> $(METADATA)
@echo "Requires: device-mapper-multipath" >> $(METADATA)
rhts-lint $(METADATA)

View file

@ -18,78 +18,81 @@
# Author: Lin Li <lilin@redhat.com>
source ../include/ec.sh || exit 200
tlog "running $0"
cleanup ()
{
trun "multipathd disablequeueing maps"
trun "service multipathd stop"
sleep 5
trun "udevadm settle"
trun "multipath -F"
sleep 5
trun "modprobe -r scsi_debug"
}
assert ()
{
local cmd="$*"
_trun_ "$cmd" 0
if test $? -eq 0; then
tpass_ "$cmd" ;
else
tfail_ "$cmd" ;
cleanup ;
tend ;
fi
}
rpm -q device-mapper-multipath || yum install -y device-mapper-multipath
tlog "device-mapper-multipath is installed"
# cleanup existing devices
trun "rm /etc/multipath.conf"
trun "mpathconf --enable --with_module y --option max_polling_interval:10"
trun "mpathconf --option detect_pgpolicy_use_tpg:yes"
trun "service multipathd stop"
tlog "start running"
Result=FAILED
MulDevice=`rpm -qa|grep device-mapper-multipath | wc -l`
if [ $MulDevice != 2 ]; then
tlog "multi-device is not install"
exit 1
fi
tlog "multi-device is installed"
trun "mpathconf --enable --find_multipaths n --with_module y --with_multipathd y"
trun "echo '' > /var/log/messages"
trun "multipath -F"
sleep 5
trun "modprobe -r scsi_debug"
trun "dmsetup remove_all"
OriginalDev=`multipathd show paths | grep "running" | awk '{print $2}'`
OLD_IFS="$IFS"
IFS=" "
OriginalDevList=($OriginalDev)
IFS="$OLD_IFS"
#trun "service multipathd restart"
trun "service multipathd start"
trun "modprobe scsi_debug vpd_use_hostno=0 add_host=2"
sleep 5
mpathdev=`multipath -l | grep scsi_debug | awk '{print $1}' | head -1`
tlog "using multipathd device ${mpathdev}"
trun "multipath -ll ${mpathdev}"
pathcount=`multipathd show paths raw format "%m %t" | grep ${mpathdev} | grep "active" | wc -l`
tlog "Checking if active path count equals 2"
assert "[[ $pathcount -eq 2 ]]"
tlog "offline one path device"
pathname=`multipathd show paths raw format "%d %m %p" | grep ${mpathdev} | sort -k 3n | head -1 | awk '{print $1}'`
tlog "path to offline: ${pathname}"
trun "echo 'offline' > /sys/block/${pathname}/device/state"
tlog "waiting for multipathd to fail path"
sleep 15
#trun "service multipathd restart"
OriPathCount=`multipathd show paths | grep -i "running" |grep -v grep|wc -l`
tlog "Original MultPathDevice = ${OriPathCount}"
trun "modprobe scsi_debug vpd_use_hostno=0 add_host=2 dev_size_mb=1024"
trun "multipath -ll"
sleep 1s
OriPathCount=`multipathd show paths | grep -i "running" |grep -v grep|wc -l`
tlog "After add tow virturl device, MultPathDevice = ${OriPathCount}"
if [ $OriPathCount -eq 0 ];then
tlog "Virtual MultiPath is Fail"
exit 1
fi
tlog "offline one MultiPathDevice"
DeviceName=`multipath -ll | grep -i "sd[a|b|c|d|e|f|g|h]" | awk -F" " '{print $3}' | tail -1`
trun "echo 'offline' > /sys/block/${DeviceName}/device/state"
sleep 1s
trun "multipath -ll"
sleep 1s
trun "multipath -r"
sleep 1s
trun "multipathd show paths"
pathcount=`multipathd show paths raw format "%m %t" | grep ${mpathdev} | grep "active" | wc -l`
tlog "Checking if active path count equals 1"
assert "[[ $pathcount -eq 1 ]]"
sleep 5s
MulPathCount=`multipathd show paths | grep -i "running" |grep -v grep|wc -l`
let "RightPathCout=$OriPathCount-1"
if [ $MulPathCount != $RightPathCout ]; then
Result=FAIL
tlog "second check fail MulPathCount=$MulPathCount RightPathCout=$RightPathCout"
tlog "running result $Result"
exit 1
fi
tlog "second check is OK MulPathCount=$MulPathCount"
tlog "restore ${pathname}"
trun "echo 'running' > /sys/block/${pathname}/device/state"
sleep 10
tlog "running one Multipath"
trun "echo 'running' > /sys/block/${DeviceName}/device/state"
sleep 1s
trun "multipath -ll"
sleep 4s
#verified
multipathd_state=`service multipathd status | grep "Active: active (running)" | wc -l`
tlog "Checking if multipathd service is running"
assert "[[ $multipathd_state -eq 1 ]]"
pathcount=`multipathd show paths raw format "%m %t" | grep ${mpathdev} | grep "active" | wc -l`
tlog "Checking if active path count equals 2"
assert "[[ $pathcount -eq 2 ]]"
path_state=`multipathd show paths raw format "%d %t %T %o" | grep ${pathname} | grep "active ready running" | wc -l`
tlog "Checking state of ${pathname}"
assert "[[ $path_state -eq 1 ]]"
Condition1=`grep "reinstate failed" /var/log/messages | wc -l`
Condition2=`grep "segfault" /var/log/messages | wc -l`
trun "service multipathd status > tmp_file"
Condition3=`grep " DM message failed" tmp_file | wc -l`
trun "multipath -F"
trun "modprobe -r scsi_debug"
trun "dmsetup remove_all"
trun "rm -f tmp_file"
tlog "Condition1=${Condition1} Condition2=${Condition2} Condition3=${Condition3}"
RESULT=PASS
[[ $Condition1 -eq 1 ]]&&[[ $Condition2 -eq 1 ]]&&[[ $Condition3 -eq 1 ]]&&RESULT=FAIL
echo "Test Result = $RESULT"
[[ $RESULT = "FAIL" ]]&&exit 1
exit 0
cleanup
tend

View file

@ -0,0 +1,49 @@
#!/bin/bash
# Copyright (c) 2016 Red Hat, Inc.
# #
# # This program is free software: you can redistribute it and/or modify
# # it under the terms of the GNU General Public License as published by
# # the Free Software Foundation, either version 3 of the License, or
# # (at your option) any later version.
# #
# # This program is distributed in the hope that it will be useful,
# # but WITHOUT ANY WARRANTY; without even the implied warranty of
# # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# # GNU General Public License for more details.
# #
# # You should have received a copy of the GNU General Public License
# # along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# # Author: Lin Li <lilin@redhat.com>
.PHONY: all install download clean
BUILT_FILES=
FILES=$(METADATA) Makefile PURPOSE main.sh
run: $(FILES) build
./main.sh
build: $(BUILT_FILES)
chmod a+x ./main.sh
clean:
rm -f *~ *.rpm $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@touch $(METADATA)
@echo "Owner: LiLin <lilin@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "License: GPLv3" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Description: Squelch scsi_id on multipath -ll" >> $(METADATA)
@echo "TestTime: 15m" >> $(METADATA)
@echo "RunFor: device-mapper-multipath" >> $(METADATA)
@echo "Requires: device-mapper-multipath" >> $(METADATA)
rhts-lint $(METADATA)

View file

@ -21,7 +21,7 @@ source ../include/ec.sh || exit 200
function main (){
local exit_status=1
Multipath_installation || Fail "fail to install device-mapper-multipath"
Print_kernel_info
Print_multipath_pkginfo

20
tests/tests.yml Normal file
View file

@ -0,0 +1,20 @@
---
# No tests suitable for atomic environment
# No tests suitable for container environment
# Tests suitable for classic environment
- hosts: localhost
roles:
- role: standard-test-beakerlib
tags:
- classic
tests:
- medium_error_scsi_debug
- squelch_scsi_id
- multipathd_oom
- user_friendly_names
- multipath_conf_syntax
- kpartx_4k_aligned
- bindings
required_packages:
- device-mapper-multipath

View file

@ -0,0 +1,49 @@
#!/bin/bash
# Copyright (c) 2016 Red Hat, Inc.
# #
# # This program is free software: you can redistribute it and/or modify
# # it under the terms of the GNU General Public License as published by
# # the Free Software Foundation, either version 3 of the License, or
# # (at your option) any later version.
# #
# # This program is distributed in the hope that it will be useful,
# # but WITHOUT ANY WARRANTY; without even the implied warranty of
# # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# # GNU General Public License for more details.
# #
# # You should have received a copy of the GNU General Public License
# # along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# # Author: Lin Li <lilin@redhat.com>
.PHONY: all install download clean
BUILT_FILES=
FILES=$(METADATA) Makefile PURPOSE main.sh multipath.conf.no multipath.conf.yes
run: $(FILES) build
./main.sh
build: $(BUILT_FILES)
chmod a+x ./main.sh
clean:
rm -f *~ *.rpm $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@touch $(METADATA)
@echo "Owner: LiLin <lilin@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "License: GPLv3" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Description: user_friendly_names" >> $(METADATA)
@echo "TestTime: 15m" >> $(METADATA)
@echo "RunFor: device-mapper-multipath" >> $(METADATA)
@echo "Requires: device-mapper-multipath" >> $(METADATA)
rhts-lint $(METADATA)

View file

@ -13,129 +13,49 @@
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.cp /etc/multipath.conf /etc/multipath.conf.$$org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Author: Lin Li <lilin@redhat.com>
source ../include/tc.sh || exit 200
source ../include/ec.sh || exit 200
tlog "running $0"
cleanup ()
{
local retries
if pidof multipathd; then
tlog "stopping multipathd"
trun "systemctl stop multipathd.service || pkill multipathd"
sleep 1
fi
retries=10
while pidof multipathd; do
((retries--))
if [[ $retries -le 0 ]]; then
tfail_ "failed to stop multipath"
tend
fi
tlog "waiting for multipathd to stop"
sleep 2
pidof multipathd && pkill multipathd
done
trun "multipath -l -v1"
retries=10
while [[ -n `multipath -l -v1` ]]; do
((retries--))
if [[ $retries -le 0 ]]; then
tfail_ "failed to remove deviece"
tend
fi
tlog "removing multipath device"
trun "udevadm settle"
trun "multipath -DF"
sleep 2
done
if lsmod | grep -q "^scsi_debug"; then
tlog "removing scsi_debug module"
tok "rmmod scsi_debug"
fi
trun "rm -f /etc/multipath.conf"
}
trun "rpm -q device-mapper-multipath || yum install -y device-mapper-multipath"
trun "mpathconf --enable --with_multipathd y --user_friendly_names y"
assert ()
{
local cmd="$*"
_trun_ "$cmd" 0
if test $? -eq 0; then
tpass_ "$cmd" ;
else
tfail_ "$cmd" ;
cleanup ;
tend ;
fi
}
# backup the /etc/multipath.conf
trun "cp /etc/multipath.conf /etc/multipath.conf.$$"
trun "multipath -F"
setup_config ()
{
trun "mpathconf --enable --user_friendly_names y"
sed -i '/^blacklist[[:space:]]*{/ a\
device {\
vendor ".*"\
product ".*"\
}
' /etc/multipath.conf
cat << _EOF_ >> /etc/multipath.conf
trun "modprobe scsi_debug dev_size_mb=256 num_tgts=1 vpd_use_hostno=0 \
add_host=2 delay=20 max_luns=2 no_lun_0=1"
trun "multipath"
# wwid shown slowly on s390x by the script framework, but normally when run by multipath command directly
# so extend sleep time
sleep 20
blacklist_exceptions {
device {
vendor Linux
product scsi_debug
}
}
disk=$(get_scsi_debug_devices)
disk=$(basename $disk)
wwid=$(get_wwid_of_disk $disk)
mpath=$(get_mpath_disk_by_scsi_device $disk)
multipaths {
multipath {
wwid TEST_WWID
alias test
}
}
_EOF_
trun "cat /etc/multipath.conf"
}
# user_friendly_names = yes and mpath=test
#cur_dir=/mnt/tests/kernel/storage/multipath/user_friendly_names/
#cur_dir=/home/test/scratch/device-mapper-multipath/user_friendly_names
trun "cat multipath.conf.yes | sed 's/your_wwid/$wwid/g' > /etc/multipath.conf"
trun "multipath -r"
tok "multipath -ll | grep -w '^test'"
do_reconfigure ()
{
trun "cat /etc/multipath.conf"
tok "multipathd reconfigure"
sleep 5
}
# user_friendly_names = no
trun "cat multipath.conf.no > /etc/multipath.conf"
trun "multipath -r"
tok "multipath -ll | grep -w '^$wwid'"
sleep 10
tok "multipath -F $wwid"
sleep 10
trun "modprobe -r scsi_debug"
trun "rpm -q device-mapper-multipath || dnf install -y device-mapper-multipath"
cleanup
setup_config
trun "rm -r /etc/multipath/bindings"
trun "modprobe scsi_debug vpd_use_hostno=0 add_host=2"
sleep 5
trun "systemctl start multipathd.service"
while multipathd show daemon | grep -qv idle; do
tlog "waiting for multipathd to start"
sleep 1
done
trun 'multipathd show maps raw format "%n %w"'
# verify user_friendly_name
tok 'multipathd show maps raw format "%n" | head -1 | grep -q mpath'
wwid=`multipathd show maps raw format "%w" | head -1`
assert "[[ -n $wwid ]] && [[ $wwid != ok ]]"
sed -i 's/TEST_WWID/'"$wwid"'/' /etc/multipath.conf
do_reconfigure
trun 'multipathd show maps raw format "%n %w"'
# verify configured alias takes precedence over user_friendly_name
tok 'multipathd show maps raw format "%n" | head -1 | grep -q test'
trun "mpathconf --user_friendly_names n"
do_reconfigure
trun 'multipathd show maps raw format "%n %w"'
# verify configured alias takes precedence over wwid name
tok 'multipathd show maps raw format "%n" | head -1 | grep -q test'
sed -i 's/'"$wwid"'/TEST_WWID/' /etc/multipath.conf
do_reconfigure
trun 'multipathd show maps raw format "%n %w"'
tok 'multipathd show maps raw format "%n" | head -1 | grep -q '"$wwid"
cleanup
trun "cp /etc/multipath.conf.$$ /etc/multipath.conf"
trun "multipath -F; multipath"
tend

View file

@ -0,0 +1,3 @@
defaults {
user_friendly_names no
}

View file

@ -0,0 +1,11 @@
defaults {
user_friendly_names yes
}
multipaths {
multipath {
wwid your_wwid
alias test
}
}