Compare commits

..

No commits in common. "rawhide" and "f32" have entirely different histories.

66 changed files with 6594 additions and 3008 deletions

View file

@ -1 +0,0 @@
1

16
.gitignore vendored
View file

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

View file

@ -0,0 +1,301 @@
From 668bc6e2f142ed81936329de144f57026c90edf2 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 1 Jul 2019 15:19:29 -0500
Subject: [PATCH] libmultipath: add marginal paths and groups infrastructure
This commit adds a marginal variable ot the paths and pathgroups structs.
The marginal paths variable can be set by
multipathd path <path> setmarginal
and cleared by
multipathd path <path> unsetmarginal
All of the marginal paths on a multipath device can be cleared by
multipathd map <map> unsetmarginal
Currently, the marginal variable of a pathgroup will not change. This
will be added by a future commit. The marginal state of a path or
pathgroup is printable with the %M wildcard, and is displayed in the
json output.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/print.c | 18 ++++++++
libmultipath/print.h | 6 ++-
libmultipath/structs.h | 2 +
multipathd/cli.c | 5 +++
multipathd/cli.h | 4 ++
multipathd/cli_handlers.c | 91 +++++++++++++++++++++++++++++++++++++++
multipathd/cli_handlers.h | 3 ++
multipathd/main.c | 3 ++
8 files changed, 130 insertions(+), 2 deletions(-)
diff --git a/libmultipath/print.c b/libmultipath/print.c
index fc40b0f0..907469ad 100644
--- a/libmultipath/print.c
+++ b/libmultipath/print.c
@@ -502,6 +502,14 @@ snprint_pg_state (char * buff, size_t len, const struct pathgroup * pgp)
}
}
+static int
+snprint_pg_marginal (char * buff, size_t len, const struct pathgroup * pgp)
+{
+ if (pgp->marginal)
+ return snprintf(buff, len, "marginal");
+ return snprintf(buff, len, "normal");
+}
+
static int
snprint_path_size (char * buff, size_t len, const struct path * pp)
{
@@ -672,6 +680,14 @@ snprint_path_protocol(char * buff, size_t len, const struct path * pp)
}
}
+int
+snprint_path_marginal(char * buff, size_t len, const struct path * pp)
+{
+ if (pp->marginal)
+ return snprintf(buff, len, "marginal");
+ return snprintf(buff, len, "normal");
+}
+
struct multipath_data mpd[] = {
{'n', "name", 0, snprint_name},
{'w', "uuid", 0, snprint_multipath_uuid},
@@ -713,6 +729,7 @@ struct path_data pd[] = {
{'p', "pri", 0, snprint_pri},
{'S', "size", 0, snprint_path_size},
{'z', "serial", 0, snprint_path_serial},
+ {'M', "marginal_st", 0, snprint_path_marginal},
{'m', "multipath", 0, snprint_path_mpp},
{'N', "host WWNN", 0, snprint_host_wwnn},
{'n', "target WWNN", 0, snprint_tgt_wwnn},
@@ -729,6 +746,7 @@ struct pathgroup_data pgd[] = {
{'s', "selector", 0, snprint_pg_selector},
{'p', "pri", 0, snprint_pg_pri},
{'t', "dm_st", 0, snprint_pg_state},
+ {'M', "marginal_st", 0, snprint_pg_marginal},
{0, NULL, 0 , NULL}
};
diff --git a/libmultipath/print.h b/libmultipath/print.h
index e2fb865c..7e36ec63 100644
--- a/libmultipath/print.h
+++ b/libmultipath/print.h
@@ -50,7 +50,8 @@
#define PRINT_JSON_GROUP "{\n" \
" \"selector\" : \"%s\",\n" \
" \"pri\" : %p,\n" \
- " \"dm_st\" : \"%t\","
+ " \"dm_st\" : \"%t\",\n" \
+ " \"marginal_st\" : \"%M\","
#define PRINT_JSON_GROUP_NUM " \"group\" : %d,\n"
@@ -66,7 +67,8 @@
" \"target_wwnn\" : \"%n\",\n" \
" \"host_wwpn\" : \"%R\",\n" \
" \"target_wwpn\" : \"%r\",\n" \
- " \"host_adapter\" : \"%a\""
+ " \"host_adapter\" : \"%a\",\n" \
+ " \"marginal_st\" : \"%M\""
#define MAX_LINE_LEN 80
#define MAX_LINES 64
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index 7879d763..1a3d827b 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -289,6 +289,7 @@ struct path {
int io_err_pathfail_cnt;
int io_err_pathfail_starttime;
int find_multipaths_timeout;
+ int marginal;
/* configlet pointers */
vector hwe;
struct gen_path generic_path;
@@ -403,6 +404,7 @@ struct pathgroup {
int status;
int priority;
int enabled_paths;
+ int marginal;
vector paths;
struct multipath *mpp;
struct gen_pathgroup generic_pg;
diff --git a/multipathd/cli.c b/multipathd/cli.c
index 17795b61..800c0fbe 100644
--- a/multipathd/cli.c
+++ b/multipathd/cli.c
@@ -215,6 +215,8 @@ load_keys (void)
r += add_key(keys, "unsetprkey", UNSETPRKEY, 0);
r += add_key(keys, "key", KEY, 1);
r += add_key(keys, "local", LOCAL, 0);
+ r += add_key(keys, "setmarginal", SETMARGINAL, 0);
+ r += add_key(keys, "unsetmarginal", UNSETMARGINAL, 0);
if (r) {
@@ -589,6 +591,9 @@ cli_init (void) {
add_handler(UNSETPRKEY+MAP, NULL);
add_handler(FORCEQ+DAEMON, NULL);
add_handler(RESTOREQ+DAEMON, NULL);
+ add_handler(SETMARGINAL+PATH, NULL);
+ add_handler(UNSETMARGINAL+PATH, NULL);
+ add_handler(UNSETMARGINAL+MAP, NULL);
return 0;
}
diff --git a/multipathd/cli.h b/multipathd/cli.h
index 32dcffac..fdfb9aed 100644
--- a/multipathd/cli.h
+++ b/multipathd/cli.h
@@ -45,6 +45,8 @@ enum {
__UNSETPRKEY,
__KEY,
__LOCAL,
+ __SETMARGINAL,
+ __UNSETMARGINAL,
};
#define LIST (1 << __LIST)
@@ -89,6 +91,8 @@ enum {
#define UNSETPRKEY (1ULL << __UNSETPRKEY)
#define KEY (1ULL << __KEY)
#define LOCAL (1ULL << __LOCAL)
+#define SETMARGINAL (1ULL << __SETMARGINAL)
+#define UNSETMARGINAL (1ULL << __UNSETMARGINAL)
#define INITIAL_REPLY_LEN 1200
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index 4c32d953..8a899049 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -1537,3 +1537,94 @@ cli_setprkey(void * v, char ** reply, int * len, void * data)
return ret;
}
+
+int cli_set_marginal(void * v, char ** reply, int * len, void * data)
+{
+ struct vectors * vecs = (struct vectors *)data;
+ char * param = get_keyparam(v, PATH);
+ struct path * pp;
+
+ param = convert_dev(param, 1);
+ pp = find_path_by_dev(vecs->pathvec, param);
+
+ if (!pp)
+ pp = find_path_by_devt(vecs->pathvec, param);
+
+ if (!pp || !pp->mpp || !pp->mpp->alias)
+ return 1;
+
+ condlog(2, "%s: set marginal path %s (operator)",
+ pp->mpp->alias, pp->dev_t);
+ if (pp->mpp->wait_for_udev) {
+ condlog(2, "%s: device not fully created, failing set marginal",
+ pp->mpp->alias);
+ return 1;
+ }
+ pp->marginal = 1;
+
+ return update_path_groups(pp->mpp, vecs, 0);
+}
+
+int cli_unset_marginal(void * v, char ** reply, int * len, void * data)
+{
+ struct vectors * vecs = (struct vectors *)data;
+ char * param = get_keyparam(v, PATH);
+ struct path * pp;
+
+ param = convert_dev(param, 1);
+ pp = find_path_by_dev(vecs->pathvec, param);
+
+ if (!pp)
+ pp = find_path_by_devt(vecs->pathvec, param);
+
+ if (!pp || !pp->mpp || !pp->mpp->alias)
+ return 1;
+
+ condlog(2, "%s: unset marginal path %s (operator)",
+ pp->mpp->alias, pp->dev_t);
+ if (pp->mpp->wait_for_udev) {
+ condlog(2, "%s: device not fully created, "
+ "failing unset marginal", pp->mpp->alias);
+ return 1;
+ }
+ pp->marginal = 0;
+
+ return update_path_groups(pp->mpp, vecs, 0);
+}
+
+int cli_unset_all_marginal(void * v, char ** reply, int * len, void * data)
+{
+ struct vectors * vecs = (struct vectors *)data;
+ char * mapname = get_keyparam(v, MAP);
+ struct multipath *mpp;
+ struct pathgroup * pgp;
+ struct path * pp;
+ unsigned int i, j;
+ int minor;
+
+ mapname = convert_dev(mapname, 0);
+ condlog(2, "%s: unset all marginal paths (operator)",
+ mapname);
+
+ if (sscanf(mapname, "dm-%d", &minor) == 1)
+ mpp = find_mp_by_minor(vecs->mpvec, minor);
+ else
+ mpp = find_mp_by_alias(vecs->mpvec, mapname);
+
+ if (!mpp) {
+ condlog(0, "%s: invalid map name. "
+ "cannot unset marginal paths", mapname);
+ return 1;
+ }
+ if (mpp->wait_for_udev) {
+ condlog(2, "%s: device not fully created, "
+ "failing unset all marginal", mpp->alias);
+ return 1;
+ }
+
+ vector_foreach_slot (mpp->pg, pgp, i)
+ vector_foreach_slot (pgp->paths, pp, j)
+ pp->marginal = 0;
+
+ return update_path_groups(mpp, vecs, 0);
+}
diff --git a/multipathd/cli_handlers.h b/multipathd/cli_handlers.h
index edbdf063..0f451064 100644
--- a/multipathd/cli_handlers.h
+++ b/multipathd/cli_handlers.h
@@ -49,3 +49,6 @@ int cli_unsetprstatus(void * v, char ** reply, int * len, void * data);
int cli_getprkey(void * v, char ** reply, int * len, void * data);
int cli_setprkey(void * v, char ** reply, int * len, void * data);
int cli_unsetprkey(void * v, char ** reply, int * len, void * data);
+int cli_set_marginal(void * v, char ** reply, int * len, void * data);
+int cli_unset_marginal(void * v, char ** reply, int * len, void * data);
+int cli_unset_all_marginal(void * v, char ** reply, int * len, void * data);
diff --git a/multipathd/main.c b/multipathd/main.c
index 7a5cd115..7db15736 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1609,6 +1609,9 @@ uxlsnrloop (void * ap)
set_handler_callback(GETPRKEY+MAP, cli_getprkey);
set_handler_callback(SETPRKEY+MAP+KEY, cli_setprkey);
set_handler_callback(UNSETPRKEY+MAP, cli_unsetprkey);
+ set_handler_callback(SETMARGINAL+PATH, cli_set_marginal);
+ set_handler_callback(UNSETMARGINAL+PATH, cli_unset_marginal);
+ set_handler_callback(UNSETMARGINAL+MAP, cli_unset_all_marginal);
umask(077);
uxsock_listen(&uxsock_trigger, ux_sock, ap);
--
2.17.2

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,749 @@
From a8f8ac6519aa46c4514c0f16073c2c6a7cb48a6a Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 9 Jul 2019 16:31:25 -0500
Subject: [PATCH] tests: add path grouping policy unit tests.
In preparation for changing the path grouping code, add some unit tests
to verify that it works correctly. The only test that currently fails
(and so it being skipped) is using MULTIBUS when mp->paths is empty. All
the other path grouping policies free mp->paths, even if it is empty.
one_group() should as well. This will be fixed when the path grouping
code is updated.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
tests/Makefile | 2 +-
tests/pgpolicy.c | 708 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 709 insertions(+), 1 deletion(-)
create mode 100644 tests/pgpolicy.c
diff --git a/tests/Makefile b/tests/Makefile
index bf159b2d..a5cdf390 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -3,7 +3,7 @@ include ../Makefile.inc
CFLAGS += $(BIN_CFLAGS) -I$(multipathdir) -I$(mpathcmddir)
LIBDEPS += -L$(multipathdir) -lmultipath -lcmocka
-TESTS := uevent parser util dmevents hwtable blacklist unaligned vpd
+TESTS := uevent parser util dmevents hwtable blacklist unaligned vpd pgpolicy
.SILENT: $(TESTS:%=%.o)
.PRECIOUS: $(TESTS:%=%-test)
diff --git a/tests/pgpolicy.c b/tests/pgpolicy.c
new file mode 100644
index 00000000..fbb8589e
--- /dev/null
+++ b/tests/pgpolicy.c
@@ -0,0 +1,708 @@
+/*
+ * Copyright (c) 2018 Benjamin Marzinski, Redhat
+ *
+ * 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 2
+ * 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <cmocka.h>
+
+#include "globals.c"
+#include "pgpolicies.h"
+
+struct multipath mp8, mp4, mp1, mp0, mp_null;
+struct path p8[8], p4[4], p1[1];
+
+
+static void set_priority(struct path *pp, int *prio, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ pp[i].priority = prio[i];
+ }
+}
+
+static void set_tgt_node_name(struct path *pp, char **tgt_node_name, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ strcpy(pp[i].tgt_node_name, tgt_node_name[i]);
+ }
+}
+
+static void set_serial(struct path *pp, char **serial, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ strcpy(pp[i].serial, serial[i]);
+ }
+}
+
+static int setup(void **state)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ sprintf(p8[i].dev, "p8_%d", i);
+ sprintf(p8[i].dev_t, "8:%d", i);
+ p8[i].state = PATH_UP;
+ }
+ for (i = 0; i < 4; i++) {
+ sprintf(p4[i].dev, "p4_%d", i);
+ sprintf(p4[i].dev_t, "4:%d", i);
+ p4[i].state = PATH_UP;
+ }
+ sprintf(p1[0].dev, "p1_0");
+ sprintf(p1[0].dev_t, "4:0");
+ p1[0].state = PATH_UP;
+ return 0;
+}
+
+static int setupX(struct multipath *mp, struct path *pp, int size)
+{
+ int i;
+ int prio[8] = {10, 10, 10, 10, 10, 10, 10, 10};
+
+ mp->paths = vector_alloc();
+ if (!mp->paths)
+ return -1;
+ for (i = 0; i < size; i++) {
+ if (!vector_alloc_slot(mp->paths))
+ return -1;
+ vector_set_slot(mp->paths, &pp[i]);
+ }
+ set_priority(pp, prio, size);
+ return 0;
+}
+
+static int setup8(void **state)
+{
+ return setupX(&mp8, p8, 8);
+}
+
+static int setup4(void **state)
+{
+ return setupX(&mp4, p4, 4);
+}
+
+static int setup1(void **state)
+{
+ return setupX(&mp1, p1, 1);
+}
+
+static int setup0(void **state)
+{
+ return setupX(&mp0, NULL, 0);
+}
+
+static int setup_null(void **state)
+{
+ return 0;
+}
+
+static int teardownX(struct multipath *mp)
+{
+ free_pgvec(mp->pg, KEEP_PATHS);
+ mp->pg = NULL;
+ return 0;
+}
+
+static int teardown8(void **state)
+{
+ return teardownX(&mp8);
+}
+
+static int teardown4(void **state)
+{
+ return teardownX(&mp4);
+}
+
+static int teardown1(void **state)
+{
+ return teardownX(&mp1);
+}
+
+static int teardown0(void **state)
+{
+ return teardownX(&mp0);
+}
+
+static int teardown_null(void **state)
+{
+ return teardownX(&mp_null);
+}
+
+static void
+verify_pathgroups(struct multipath *mp, struct path *pp, int **groups,
+ int *group_size, int size)
+{
+ int i, j;
+ struct pathgroup *pgp;
+
+ assert_null(mp->paths);
+ assert_non_null(mp->pg);
+ assert_int_equal(VECTOR_SIZE(mp->pg), size);
+ for (i = 0; i < size; i++) {
+ pgp = VECTOR_SLOT(mp->pg, i);
+ assert_non_null(pgp);
+ assert_non_null(pgp->paths);
+ assert_int_equal(VECTOR_SIZE(pgp->paths), group_size[i]);
+ for (j = 0; j < group_size[i]; j++) {
+ int path_nr = groups[i][j];
+ struct path *pgp_path = VECTOR_SLOT(pgp->paths, j);
+ struct path *pp_path = &pp[path_nr];
+ /* Test names instead of pointers to get a more
+ * useful error message */
+ assert_string_equal(pgp_path->dev, pp_path->dev);
+ /* This test is just a backkup in case the
+ * something wenth wrong naming the paths */
+ assert_ptr_equal(pgp_path, pp_path);
+ }
+ }
+}
+
+static void test_one_group8(void **state)
+{
+ int paths[] = {0,1,2,3,4,5,6,7};
+ int *groups[] = {paths};
+ int group_size[] = {8};
+
+ assert_int_equal(one_group(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 1);
+}
+
+static void test_one_group4(void **state)
+{
+ int paths[] = {0,1,2,3};
+ int *groups[] = {paths};
+ int group_size[] = {4};
+
+ assert_int_equal(one_group(&mp4), 0);
+ verify_pathgroups(&mp4, p4, groups, group_size, 1);
+}
+
+static void test_one_group1(void **state)
+{
+ int paths[] = {0};
+ int *groups[] = {paths};
+ int group_size[] = {1};
+
+ assert_int_equal(one_group(&mp1), 0);
+ verify_pathgroups(&mp1, p1, groups, group_size, 1);
+}
+
+static void test_one_group0(void **state)
+{
+ assert_int_equal(one_group(&mp0), 0);
+ skip(); /* BROKEN */
+ verify_pathgroups(&mp0, NULL, NULL, NULL, 0);
+}
+
+static void test_one_group_null(void **state)
+{
+ assert_int_equal(one_group(&mp_null), 0);
+ verify_pathgroups(&mp_null, NULL, NULL, NULL, 0);
+}
+
+static void test_one_path_per_group_same8(void **state)
+{
+ int paths[] = {0,1,2,3,4,5,6,7};
+ int *groups[] = {&paths[0], &paths[1], &paths[2], &paths[3],
+ &paths[4], &paths[5], &paths[6], &paths[7]};
+ int group_size[] = {1,1,1,1,1,1,1,1};
+
+ assert_int_equal(one_path_per_group(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 8);
+}
+
+static void test_one_path_per_group_increasing8(void **state)
+{
+ int prio[] = {1,2,3,4,5,6,7,8};
+ int paths[] = {7,6,5,4,3,2,1,0};
+ int *groups[] = {&paths[0], &paths[1], &paths[2], &paths[3],
+ &paths[4], &paths[5], &paths[6], &paths[7]};
+ int group_size[] = {1,1,1,1,1,1,1,1};
+
+ set_priority(p8, prio, 8);
+ assert_int_equal(one_path_per_group(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 8);
+}
+
+static void test_one_path_per_group_decreasing8(void **state)
+{
+ int prio[] = {8,7,6,5,4,3,2,1};
+ int paths[] = {0,1,2,3,4,5,6,7};
+ int *groups[] = {&paths[0], &paths[1], &paths[2], &paths[3],
+ &paths[4], &paths[5], &paths[6], &paths[7]};
+ int group_size[] = {1,1,1,1,1,1,1,1};
+
+ set_priority(p8, prio, 8);
+ assert_int_equal(one_path_per_group(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 8);
+}
+
+static void test_one_path_per_group_mixed8(void **state)
+{
+ int prio[] = {7,1,3,3,5,2,8,2};
+ int paths[] = {6,0,4,2,3,5,7,1};
+ int *groups[] = {&paths[0], &paths[1], &paths[2], &paths[3],
+ &paths[4], &paths[5], &paths[6], &paths[7]};
+ int group_size[] = {1,1,1,1,1,1,1,1};
+
+ set_priority(p8, prio, 8);
+ assert_int_equal(one_path_per_group(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 8);
+}
+
+static void test_one_path_per_group4(void **state)
+{
+ int paths[] = {0,1,2,3};
+ int *groups[] = {&paths[0], &paths[1], &paths[2], &paths[3]};
+ int group_size[] = {1,1,1,1};
+
+ assert_int_equal(one_path_per_group(&mp4), 0);
+ verify_pathgroups(&mp4, p4, groups, group_size, 4);
+}
+
+static void test_one_path_per_group1(void **state)
+{
+ int paths[] = {0};
+ int *groups[] = {paths};
+ int group_size[] = {1};
+
+ assert_int_equal(one_path_per_group(&mp1), 0);
+ verify_pathgroups(&mp1, p1, groups, group_size, 1);
+}
+
+static void test_one_path_per_group0(void **state)
+{
+ assert_int_equal(one_path_per_group(&mp0), 0);
+ verify_pathgroups(&mp0, NULL, NULL, NULL, 0);
+}
+
+static void test_one_path_per_group_null(void **state)
+{
+ assert_int_equal(one_path_per_group(&mp_null), 0);
+ verify_pathgroups(&mp_null, NULL, NULL, NULL, 0);
+}
+
+static void test_group_by_prio_same8(void **state)
+{
+ int paths[] = {0,1,2,3,4,5,6,7};
+ int *groups[] = {paths};
+ int group_size[] = {8};
+
+ assert_int_equal(group_by_prio(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 1);
+}
+
+static void test_group_by_prio_increasing8(void **state)
+{
+ int prio[] = {1,2,3,4,5,6,7,8};
+ int paths[] = {7,6,5,4,3,2,1,0};
+ int *groups[] = {&paths[0], &paths[1], &paths[2], &paths[3],
+ &paths[4], &paths[5], &paths[6], &paths[7]};
+ int group_size[] = {1,1,1,1,1,1,1,1};
+
+ set_priority(p8, prio, 8);
+ assert_int_equal(group_by_prio(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 8);
+}
+
+static void test_group_by_prio_decreasing8(void **state)
+{
+ int prio[] = {8,7,6,5,4,3,2,1};
+ int paths[] = {0,1,2,3,4,5,6,7};
+ int *groups[] = {&paths[0], &paths[1], &paths[2], &paths[3],
+ &paths[4], &paths[5], &paths[6], &paths[7]};
+ int group_size[] = {1,1,1,1,1,1,1,1};
+
+ set_priority(p8, prio, 8);
+ assert_int_equal(group_by_prio(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 8);
+}
+
+static void test_group_by_prio_mixed8(void **state)
+{
+ int prio[] = {7,1,3,3,5,2,8,2};
+ int group0[] = {6};
+ int group1[] = {0};
+ int group2[] = {4};
+ int group3[] = {2,3};
+ int group4[] = {5,7};
+ int group5[] = {1};
+ int *groups[] = {group0, group1, group2, group3,
+ group4, group5};
+ int group_size[] = {1,1,1,2,2,1};
+
+ set_priority(p8, prio, 8);
+ assert_int_equal(group_by_prio(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 6);
+}
+
+static void test_group_by_prio_2_groups8(void **state)
+{
+ int prio[] = {1,2,2,1,2,1,1,2};
+ int group0[] = {1,2,4,7};
+ int group1[] = {0,3,5,6};
+ int *groups[] = {group0, group1};
+ int group_size[] = {4,4};
+
+ set_priority(p8, prio, 8);
+ assert_int_equal(group_by_prio(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 2);
+}
+
+static void test_group_by_prio_mixed4(void **state)
+{
+ int prio[] = {2,3,1,3};
+ int group0[] = {1,3};
+ int group1[] = {0};
+ int group2[] = {2};
+ int *groups[] = {group0, group1, group2};
+ int group_size[] = {2,1,1};
+
+ set_priority(p4, prio, 4);
+ assert_int_equal(group_by_prio(&mp4), 0);
+ verify_pathgroups(&mp4, p4, groups, group_size, 3);
+}
+
+static void test_group_by_prio_2_groups4(void **state)
+{
+ int prio[] = {2,1,1,2};
+ int group0[] = {0,3};
+ int group1[] = {1,2};
+ int *groups[] = {group0, group1};
+ int group_size[] = {2,2};
+
+ set_priority(p4, prio, 4);
+ assert_int_equal(group_by_prio(&mp4), 0);
+ verify_pathgroups(&mp4, p4, groups, group_size, 2);
+}
+
+static void test_group_by_prio1(void **state)
+{
+ int paths[] = {0};
+ int *groups[] = {paths};
+ int group_size[] = {1};
+
+ assert_int_equal(group_by_prio(&mp1), 0);
+ verify_pathgroups(&mp1, p1, groups, group_size, 1);
+}
+
+static void test_group_by_prio0(void **state)
+{
+ assert_int_equal(group_by_prio(&mp0), 0);
+ verify_pathgroups(&mp0, NULL, NULL, NULL, 0);
+}
+
+static void test_group_by_prio_null(void **state)
+{
+ assert_int_equal(group_by_prio(&mp_null), 0);
+ verify_pathgroups(&mp_null, NULL, NULL, NULL, 0);
+}
+
+static void test_group_by_node_name_same8(void **state)
+{
+ char *node_name[] = {"a","a","a","a","a","a","a","a"};
+ int paths[] = {0,1,2,3,4,5,6,7};
+ int *groups[] = {paths};
+ int group_size[] = {8};
+
+ set_tgt_node_name(p8, node_name, 8);
+ assert_int_equal(group_by_node_name(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 1);
+}
+
+static void test_group_by_node_name_increasing8(void **state)
+{
+ char *node_name[] = {"a","b","c","d","e","f","g","h"};
+ int prio[] = {1,2,3,4,5,6,7,8};
+ int paths[] = {7,6,5,4,3,2,1,0};
+ int *groups[] = {&paths[0], &paths[1], &paths[2], &paths[3],
+ &paths[4], &paths[5], &paths[6], &paths[7]};
+ int group_size[] = {1,1,1,1,1,1,1,1};
+
+ set_priority(p8, prio, 8);
+ set_tgt_node_name(p8, node_name, 8);
+ assert_int_equal(group_by_node_name(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 8);
+}
+
+static void test_group_by_node_name_3_groups8(void **state)
+{
+ char *node_name[] = {"a","b","a","c","b","c","c","a"};
+ int prio[] = {4,1,4,1,1,1,1,4};
+ int group0[] = {0,2,7};
+ int group1[] = {3,5,6};
+ int group2[] = {1,4};
+ int *groups[] = {group0, group1, group2};
+ int group_size[] = {3,3,2};
+
+ set_priority(p8, prio, 8);
+ set_tgt_node_name(p8, node_name, 8);
+ assert_int_equal(group_by_node_name(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 3);
+}
+
+static void test_group_by_node_name_2_groups8(void **state)
+{
+ char *node_name[] = {"a", "a", "b", "a", "b", "b", "b", "a"};
+ int prio[] = {4,1,2,1,2,2,2,1};
+ int group0[] = {2,4,5,6};
+ int group1[] = {0,1,3,7};
+ int *groups[] = {group0, group1};
+ int group_size[] = {4,4};
+
+ set_priority(p8, prio, 8);
+ set_tgt_node_name(p8, node_name, 8);
+ assert_int_equal(group_by_node_name(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 2);
+}
+
+static void test_group_by_node_name_3_groups4(void **state)
+{
+ char *node_name[] = {"a","b","c","a"};
+ int prio[] = {3,1,3,1};
+ int group0[] = {2};
+ int group1[] = {0,3};
+ int group2[] = {1};
+ int *groups[] = {group0, group1, group2};
+ int group_size[] = {1,2,1};
+
+ set_priority(p4, prio, 4);
+ set_tgt_node_name(p4, node_name, 4);
+ assert_int_equal(group_by_node_name(&mp4), 0);
+ verify_pathgroups(&mp4, p4, groups, group_size, 3);
+}
+
+static void test_group_by_node_name_2_groups4(void **state)
+{
+ char *node_name[] = {"a","b","b","a"};
+ int prio[] = {2,1,1,2};
+ int group0[] = {0,3};
+ int group1[] = {1,2};
+ int *groups[] = {group0, group1};
+ int group_size[] = {2,2};
+
+ set_priority(p4, prio, 4);
+ set_tgt_node_name(p4, node_name, 4);
+ assert_int_equal(group_by_node_name(&mp4), 0);
+ verify_pathgroups(&mp4, p4, groups, group_size, 2);
+}
+
+static void test_group_by_node_name1(void **state)
+{
+ char *node_name[] = {"a"};
+ int paths[] = {0};
+ int *groups[] = {paths};
+ int group_size[] = {1};
+
+ set_tgt_node_name(p1, node_name, 1);
+ assert_int_equal(group_by_node_name(&mp1), 0);
+ verify_pathgroups(&mp1, p1, groups, group_size, 1);
+}
+
+static void test_group_by_node_name0(void **state)
+{
+ assert_int_equal(group_by_node_name(&mp0), 0);
+ verify_pathgroups(&mp0, NULL, NULL, NULL, 0);
+}
+
+static void test_group_by_node_name_null(void **state)
+{
+ assert_int_equal(group_by_node_name(&mp_null), 0);
+ verify_pathgroups(&mp_null, NULL, NULL, NULL, 0);
+}
+
+static void test_group_by_serial_same8(void **state)
+{
+ char *serial[] = {"1","1","1","1","1","1","1","1"};
+ int paths[] = {0,1,2,3,4,5,6,7};
+ int *groups[] = {paths};
+ int group_size[] = {8};
+
+ set_serial(p8, serial, 8);
+ assert_int_equal(group_by_serial(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 1);
+}
+
+static void test_group_by_serial_increasing8(void **state)
+{
+ char *serial[] = {"1","2","3","4","5","6","7","8"};
+ int prio[] = {1,2,3,4,5,6,7,8};
+ int paths[] = {7,6,5,4,3,2,1,0};
+ int *groups[] = {&paths[0], &paths[1], &paths[2], &paths[3],
+ &paths[4], &paths[5], &paths[6], &paths[7]};
+ int group_size[] = {1,1,1,1,1,1,1,1};
+
+ set_priority(p8, prio, 8);
+ set_serial(p8, serial, 8);
+ assert_int_equal(group_by_serial(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 8);
+}
+
+static void test_group_by_serial_3_groups8(void **state)
+{
+ char *serial[] = {"1","2","1","3","2","3","2","1"};
+ int prio[] = {4,1,4,3,1,3,1,4};
+ int group0[] = {0,2,7};
+ int group1[] = {3,5};
+ int group2[] = {1,4,6};
+ int *groups[] = {group0, group1, group2};
+ int group_size[] = {3,2,3};
+
+ set_priority(p8, prio, 8);
+ set_serial(p8, serial, 8);
+ assert_int_equal(group_by_serial(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 3);
+}
+
+static void test_group_by_serial_2_groups8(void **state)
+{
+ char *serial[] = {"1", "2", "1", "1", "2", "2", "1", "2"};
+ int prio[] = {3,2,2,1,2,2,1,2};
+ int group0[] = {1,4,5,7};
+ int group1[] = {0,2,3,6};
+ int *groups[] = {group0, group1};
+ int group_size[] = {4,4};
+
+ set_priority(p8, prio, 8);
+ set_serial(p8, serial, 8);
+ assert_int_equal(group_by_serial(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, 2);
+}
+
+static void test_group_by_serial_3_groups4(void **state)
+{
+ char *serial[] = {"1","2","3","2"};
+ int prio[] = {3,1,3,1};
+ int group0[] = {0};
+ int group1[] = {2};
+ int group2[] = {1,3};
+ int *groups[] = {group0, group1, group2};
+ int group_size[] = {1,1,2};
+
+ set_priority(p4, prio, 4);
+ set_serial(p4, serial, 4);
+ assert_int_equal(group_by_serial(&mp4), 0);
+ verify_pathgroups(&mp4, p4, groups, group_size, 3);
+}
+
+static void test_group_by_serial_2_groups4(void **state)
+{
+ char *serial[] = {"1","2","1","2"};
+ int prio[] = {3,1,3,1};
+ int group0[] = {0,2};
+ int group1[] = {1,3};
+ int *groups[] = {group0, group1};
+ int group_size[] = {2,2};
+
+ set_priority(p4, prio, 4);
+ set_serial(p4, serial, 4);
+ assert_int_equal(group_by_serial(&mp4), 0);
+ verify_pathgroups(&mp4, p4, groups, group_size, 2);
+}
+
+static void test_group_by_serial1(void **state)
+{
+ char *serial[1] = {"1"};
+ int paths[1] = {0};
+ int *groups[1] = {paths};
+ int group_size[1] = {1};
+
+ set_serial(p1, serial, 1);
+ assert_int_equal(group_by_serial(&mp1), 0);
+ verify_pathgroups(&mp1, p1, groups, group_size, 1);
+}
+
+static void test_group_by_serial0(void **state)
+{
+ assert_int_equal(group_by_serial(&mp0), 0);
+ verify_pathgroups(&mp0, NULL, NULL, NULL, 0);
+}
+
+static void test_group_by_serial_null(void **state)
+{
+ assert_int_equal(group_by_serial(&mp_null), 0);
+ verify_pathgroups(&mp_null, NULL, NULL, NULL, 0);
+}
+
+#define setup_test(name, nr) \
+cmocka_unit_test_setup_teardown(name ## nr, setup ## nr, teardown ## nr)
+
+int test_pgpolicies(void)
+{
+ const struct CMUnitTest tests[] = {
+ setup_test(test_one_group, 8),
+ setup_test(test_one_group, 4),
+ setup_test(test_one_group, 1),
+ setup_test(test_one_group, 0),
+ setup_test(test_one_group, _null),
+ setup_test(test_one_path_per_group_same, 8),
+ setup_test(test_one_path_per_group_increasing, 8),
+ setup_test(test_one_path_per_group_decreasing, 8),
+ setup_test(test_one_path_per_group_mixed, 8),
+ setup_test(test_one_path_per_group, 4),
+ setup_test(test_one_path_per_group, 1),
+ setup_test(test_one_path_per_group, 0),
+ setup_test(test_one_path_per_group, _null),
+ setup_test(test_group_by_prio_same, 8),
+ setup_test(test_group_by_prio_increasing, 8),
+ setup_test(test_group_by_prio_decreasing, 8),
+ setup_test(test_group_by_prio_mixed, 8),
+ setup_test(test_group_by_prio_2_groups, 8),
+ setup_test(test_group_by_prio_mixed, 4),
+ setup_test(test_group_by_prio_2_groups, 4),
+ setup_test(test_group_by_prio, 1),
+ setup_test(test_group_by_prio, 0),
+ setup_test(test_group_by_prio, _null),
+ setup_test(test_group_by_node_name_same, 8),
+ setup_test(test_group_by_node_name_increasing, 8),
+ setup_test(test_group_by_node_name_3_groups, 8),
+ setup_test(test_group_by_node_name_2_groups, 8),
+ setup_test(test_group_by_node_name_3_groups, 4),
+ setup_test(test_group_by_node_name_2_groups, 4),
+ setup_test(test_group_by_node_name, 1),
+ setup_test(test_group_by_node_name, 0),
+ setup_test(test_group_by_node_name, _null),
+ setup_test(test_group_by_serial_same, 8),
+ setup_test(test_group_by_serial_increasing, 8),
+ setup_test(test_group_by_serial_3_groups, 8),
+ setup_test(test_group_by_serial_2_groups, 8),
+ setup_test(test_group_by_serial_3_groups, 4),
+ setup_test(test_group_by_serial_2_groups, 4),
+ setup_test(test_group_by_serial, 1),
+ setup_test(test_group_by_serial, 0),
+ setup_test(test_group_by_serial, _null),
+ };
+ return cmocka_run_group_tests(tests, setup, NULL);
+}
+
+int main(void)
+{
+ int ret = 0;
+
+ ret += test_pgpolicies();
+ return ret;
+}
--
2.17.2

View file

@ -0,0 +1,260 @@
From cc1f4c53100ae50e0fba379c40ac8e1fe72c1fb1 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 2 Jul 2019 16:28:16 -0500
Subject: [PATCH] libmultipath: add wrapper function around pgpolicyfn
group_paths() is a wrapper around the pgpolicy functions, that pulls out
the common code from the beginning and the end. For this to work,
one_group() needs to change how it sets up the pathgroups vector to work
like the other pgpolicy functions. This does means that the pathgroups
in group_by_prio are now needlessly sorted afterwards. That will be
dealt with in a later patch. Also, since store_pathgroup() is only
called by add_pathgroup(), it doesn't need to exist as a seperate
function.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/configure.c | 2 +-
libmultipath/pgpolicies.c | 83 ++++++++++++++-------------------------
libmultipath/pgpolicies.h | 2 +-
libmultipath/structs.c | 16 ++------
libmultipath/structs.h | 1 -
5 files changed, 35 insertions(+), 69 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index b09ef529..3c309d64 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -387,7 +387,7 @@ int setup_map(struct multipath *mpp, char *params, int params_size,
vector_free(mpp->pg);
mpp->pg = NULL;
}
- if (mpp->pgpolicyfn && mpp->pgpolicyfn(mpp))
+ if (group_paths(mpp))
return 1;
/*
diff --git a/libmultipath/pgpolicies.c b/libmultipath/pgpolicies.c
index 660768a4..1b59485c 100644
--- a/libmultipath/pgpolicies.c
+++ b/libmultipath/pgpolicies.c
@@ -84,6 +84,26 @@ sort_pathgroups (struct multipath *mp) {
}
+int group_paths(struct multipath *mp)
+{
+ if (!mp->pg)
+ mp->pg = vector_alloc();
+ if (!mp->pg)
+ return 1;
+
+ if (VECTOR_SIZE(mp->paths) > 0 &&
+ (!mp->pgpolicyfn || mp->pgpolicyfn(mp))) {
+ vector_free(mp->pg);
+ mp->pg = NULL;
+ return 1;
+ }
+
+ sort_pathgroups(mp);
+ vector_free(mp->paths);
+ mp->paths = NULL;
+ return 0;
+}
+
/*
* One path group per unique tgt_node_name present in the path vector
*/
@@ -95,12 +115,6 @@ int group_by_node_name(struct multipath * mp)
struct pathgroup * pgp;
struct path * pp2;
- if (!mp->pg)
- mp->pg = vector_alloc();
-
- if (!mp->pg)
- return 1;
-
/* init the bitmap */
bitmap = (int *)MALLOC(VECTOR_SIZE(mp->paths) * sizeof (int));
@@ -146,9 +160,6 @@ int group_by_node_name(struct multipath * mp)
}
}
FREE(bitmap);
- sort_pathgroups(mp);
- free_pathvec(mp->paths, KEEP_PATHS);
- mp->paths = NULL;
return 0;
out2:
free_pathgroup(pgp, KEEP_PATHS);
@@ -171,12 +182,6 @@ int group_by_serial(struct multipath * mp)
struct pathgroup * pgp;
struct path * pp2;
- if (!mp->pg)
- mp->pg = vector_alloc();
-
- if (!mp->pg)
- return 1;
-
/* init the bitmap */
bitmap = (int *)MALLOC(VECTOR_SIZE(mp->paths) * sizeof (int));
@@ -221,9 +226,6 @@ int group_by_serial(struct multipath * mp)
}
}
FREE(bitmap);
- sort_pathgroups(mp);
- free_pathvec(mp->paths, KEEP_PATHS);
- mp->paths = NULL;
return 0;
out2:
free_pathgroup(pgp, KEEP_PATHS);
@@ -241,12 +243,6 @@ int one_path_per_group(struct multipath *mp)
struct path * pp;
struct pathgroup * pgp;
- if (!mp->pg)
- mp->pg = vector_alloc();
-
- if (!mp->pg)
- return 1;
-
for (i = 0; i < VECTOR_SIZE(mp->paths); i++) {
pp = VECTOR_SLOT(mp->paths, i);
pgp = alloc_pathgroup();
@@ -260,9 +256,6 @@ int one_path_per_group(struct multipath *mp)
if (store_path(pgp->paths, pp))
goto out1;
}
- sort_pathgroups(mp);
- free_pathvec(mp->paths, KEEP_PATHS);
- mp->paths = NULL;
return 0;
out1:
free_pathgroup(pgp, KEEP_PATHS);
@@ -274,32 +267,24 @@ out:
int one_group(struct multipath *mp) /* aka multibus */
{
+ int i;
+ struct path * pp;
struct pathgroup * pgp;
- if (VECTOR_SIZE(mp->paths) < 0)
- return 0;
+ pgp = alloc_pathgroup();
- if (!mp->pg)
- mp->pg = vector_alloc();
+ if (!pgp)
+ goto out;
- if (!mp->pg)
- return 1;
+ if (add_pathgroup(mp, pgp))
+ goto out1;
- if (VECTOR_SIZE(mp->paths) > 0) {
- pgp = alloc_pathgroup();
+ for (i = 0; i < VECTOR_SIZE(mp->paths); i++) {
+ pp = VECTOR_SLOT(mp->paths, i);
- if (!pgp)
+ if (store_path(pgp->paths, pp))
goto out;
-
- vector_free(pgp->paths);
-
- if (add_pathgroup(mp, pgp))
- goto out1;
-
- pgp->paths = mp->paths;
- mp->paths = NULL;
}
-
return 0;
out1:
free_pathgroup(pgp, KEEP_PATHS);
@@ -317,12 +302,6 @@ int group_by_prio(struct multipath *mp)
struct pathgroup * pgp;
vector pathvec = NULL;
- if (!mp->pg)
- mp->pg = vector_alloc();
-
- if (!mp->pg)
- return 1;
-
pathvec = vector_alloc();
if (!pathvec)
goto out;
@@ -387,8 +366,6 @@ int group_by_prio(struct multipath *mp)
}
}
free_pathvec(pathvec, KEEP_PATHS);
- free_pathvec(mp->paths, KEEP_PATHS);
- mp->paths = NULL;
return 0;
out2:
free_pathgroup(pgp, KEEP_PATHS);
diff --git a/libmultipath/pgpolicies.h b/libmultipath/pgpolicies.h
index c0eaa7f4..11834011 100644
--- a/libmultipath/pgpolicies.h
+++ b/libmultipath/pgpolicies.h
@@ -21,7 +21,7 @@ enum iopolicies {
int get_pgpolicy_id(char *);
int get_pgpolicy_name (char *, int, int);
-
+int group_paths(struct multipath *);
/*
* policies
*/
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
index fee899bd..bf7fdd73 100644
--- a/libmultipath/structs.c
+++ b/libmultipath/structs.c
@@ -318,23 +318,13 @@ store_path (vector pathvec, struct path * pp)
return 0;
}
-int
-store_pathgroup (vector pgvec, struct pathgroup * pgp)
+int add_pathgroup(struct multipath *mpp, struct pathgroup *pgp)
{
- if (!vector_alloc_slot(pgvec))
+ if (!vector_alloc_slot(mpp->pg))
return 1;
- vector_set_slot(pgvec, pgp);
-
- return 0;
-}
-
-int add_pathgroup(struct multipath *mpp, struct pathgroup *pgp)
-{
- int ret = store_pathgroup(mpp->pg, pgp);
+ vector_set_slot(mpp->pg, pgp);
- if (ret)
- return ret;
pgp->mpp = mpp;
return 0;
}
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index 1a3d827b..893074eb 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -445,7 +445,6 @@ int store_adaptergroup(vector adapters, struct adapter_group *agp);
int store_hostgroup(vector hostgroupvec, struct host_group *hgp);
int store_path (vector pathvec, struct path * pp);
-int store_pathgroup (vector pgvec, struct pathgroup * pgp);
int add_pathgroup(struct multipath*, struct pathgroup *);
struct multipath * find_mp_by_alias (const struct _vector *mp, const char *alias);
--
2.17.2

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

@ -0,0 +1,420 @@
From 03741e7467fdef6cd2fc91457a406ad60047f50e Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 9 Jul 2019 17:41:32 -0500
Subject: [PATCH] tests: update pgpolicy tests to work with group_paths()
The pgpolicy unit tests now work again, using group_paths().
test_one_group0(), which was skipped with the old path grouping code
because it failed, is now working correctly.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
tests/pgpolicy.c | 125 +++++++++++++++++++++++++++++++----------------
1 file changed, 83 insertions(+), 42 deletions(-)
diff --git a/tests/pgpolicy.c b/tests/pgpolicy.c
index fbb8589e..04a77c4c 100644
--- a/tests/pgpolicy.c
+++ b/tests/pgpolicy.c
@@ -92,6 +92,7 @@ static int setupX(struct multipath *mp, struct path *pp, int size)
vector_set_slot(mp->paths, &pp[i]);
}
set_priority(pp, prio, size);
+ mp->pgpolicyfn = NULL;
return 0;
}
@@ -187,7 +188,8 @@ static void test_one_group8(void **state)
int *groups[] = {paths};
int group_size[] = {8};
- assert_int_equal(one_group(&mp8), 0);
+ mp8.pgpolicyfn = one_group;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 1);
}
@@ -197,7 +199,8 @@ static void test_one_group4(void **state)
int *groups[] = {paths};
int group_size[] = {4};
- assert_int_equal(one_group(&mp4), 0);
+ mp4.pgpolicyfn = one_group;
+ assert_int_equal(group_paths(&mp4), 0);
verify_pathgroups(&mp4, p4, groups, group_size, 1);
}
@@ -207,20 +210,22 @@ static void test_one_group1(void **state)
int *groups[] = {paths};
int group_size[] = {1};
- assert_int_equal(one_group(&mp1), 0);
+ mp1.pgpolicyfn = one_group;
+ assert_int_equal(group_paths(&mp1), 0);
verify_pathgroups(&mp1, p1, groups, group_size, 1);
}
static void test_one_group0(void **state)
{
- assert_int_equal(one_group(&mp0), 0);
- skip(); /* BROKEN */
+ mp0.pgpolicyfn = one_group;
+ assert_int_equal(group_paths(&mp0), 0);
verify_pathgroups(&mp0, NULL, NULL, NULL, 0);
}
static void test_one_group_null(void **state)
{
- assert_int_equal(one_group(&mp_null), 0);
+ mp_null.pgpolicyfn = one_group;
+ assert_int_equal(group_paths(&mp_null), 0);
verify_pathgroups(&mp_null, NULL, NULL, NULL, 0);
}
@@ -231,7 +236,8 @@ static void test_one_path_per_group_same8(void **state)
&paths[4], &paths[5], &paths[6], &paths[7]};
int group_size[] = {1,1,1,1,1,1,1,1};
- assert_int_equal(one_path_per_group(&mp8), 0);
+ mp8.pgpolicyfn = one_path_per_group;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 8);
}
@@ -244,7 +250,8 @@ static void test_one_path_per_group_increasing8(void **state)
int group_size[] = {1,1,1,1,1,1,1,1};
set_priority(p8, prio, 8);
- assert_int_equal(one_path_per_group(&mp8), 0);
+ mp8.pgpolicyfn = one_path_per_group;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 8);
}
@@ -257,7 +264,8 @@ static void test_one_path_per_group_decreasing8(void **state)
int group_size[] = {1,1,1,1,1,1,1,1};
set_priority(p8, prio, 8);
- assert_int_equal(one_path_per_group(&mp8), 0);
+ mp8.pgpolicyfn = one_path_per_group;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 8);
}
@@ -270,7 +278,8 @@ static void test_one_path_per_group_mixed8(void **state)
int group_size[] = {1,1,1,1,1,1,1,1};
set_priority(p8, prio, 8);
- assert_int_equal(one_path_per_group(&mp8), 0);
+ mp8.pgpolicyfn = one_path_per_group;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 8);
}
@@ -280,7 +289,8 @@ static void test_one_path_per_group4(void **state)
int *groups[] = {&paths[0], &paths[1], &paths[2], &paths[3]};
int group_size[] = {1,1,1,1};
- assert_int_equal(one_path_per_group(&mp4), 0);
+ mp4.pgpolicyfn = one_path_per_group;
+ assert_int_equal(group_paths(&mp4), 0);
verify_pathgroups(&mp4, p4, groups, group_size, 4);
}
@@ -290,19 +300,22 @@ static void test_one_path_per_group1(void **state)
int *groups[] = {paths};
int group_size[] = {1};
- assert_int_equal(one_path_per_group(&mp1), 0);
+ mp1.pgpolicyfn = one_path_per_group;
+ assert_int_equal(group_paths(&mp1), 0);
verify_pathgroups(&mp1, p1, groups, group_size, 1);
}
static void test_one_path_per_group0(void **state)
{
- assert_int_equal(one_path_per_group(&mp0), 0);
+ mp0.pgpolicyfn = one_path_per_group;
+ assert_int_equal(group_paths(&mp0), 0);
verify_pathgroups(&mp0, NULL, NULL, NULL, 0);
}
static void test_one_path_per_group_null(void **state)
{
- assert_int_equal(one_path_per_group(&mp_null), 0);
+ mp_null.pgpolicyfn = one_path_per_group;
+ assert_int_equal(group_paths(&mp_null), 0);
verify_pathgroups(&mp_null, NULL, NULL, NULL, 0);
}
@@ -312,7 +325,8 @@ static void test_group_by_prio_same8(void **state)
int *groups[] = {paths};
int group_size[] = {8};
- assert_int_equal(group_by_prio(&mp8), 0);
+ mp8.pgpolicyfn = group_by_prio;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 1);
}
@@ -325,7 +339,8 @@ static void test_group_by_prio_increasing8(void **state)
int group_size[] = {1,1,1,1,1,1,1,1};
set_priority(p8, prio, 8);
- assert_int_equal(group_by_prio(&mp8), 0);
+ mp8.pgpolicyfn = group_by_prio;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 8);
}
@@ -338,7 +353,8 @@ static void test_group_by_prio_decreasing8(void **state)
int group_size[] = {1,1,1,1,1,1,1,1};
set_priority(p8, prio, 8);
- assert_int_equal(group_by_prio(&mp8), 0);
+ mp8.pgpolicyfn = group_by_prio;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 8);
}
@@ -356,7 +372,8 @@ static void test_group_by_prio_mixed8(void **state)
int group_size[] = {1,1,1,2,2,1};
set_priority(p8, prio, 8);
- assert_int_equal(group_by_prio(&mp8), 0);
+ mp8.pgpolicyfn = group_by_prio;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 6);
}
@@ -369,7 +386,8 @@ static void test_group_by_prio_2_groups8(void **state)
int group_size[] = {4,4};
set_priority(p8, prio, 8);
- assert_int_equal(group_by_prio(&mp8), 0);
+ mp8.pgpolicyfn = group_by_prio;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 2);
}
@@ -383,7 +401,8 @@ static void test_group_by_prio_mixed4(void **state)
int group_size[] = {2,1,1};
set_priority(p4, prio, 4);
- assert_int_equal(group_by_prio(&mp4), 0);
+ mp4.pgpolicyfn = group_by_prio;
+ assert_int_equal(group_paths(&mp4), 0);
verify_pathgroups(&mp4, p4, groups, group_size, 3);
}
@@ -396,7 +415,8 @@ static void test_group_by_prio_2_groups4(void **state)
int group_size[] = {2,2};
set_priority(p4, prio, 4);
- assert_int_equal(group_by_prio(&mp4), 0);
+ mp4.pgpolicyfn = group_by_prio;
+ assert_int_equal(group_paths(&mp4), 0);
verify_pathgroups(&mp4, p4, groups, group_size, 2);
}
@@ -406,19 +426,22 @@ static void test_group_by_prio1(void **state)
int *groups[] = {paths};
int group_size[] = {1};
- assert_int_equal(group_by_prio(&mp1), 0);
+ mp1.pgpolicyfn = group_by_prio;
+ assert_int_equal(group_paths(&mp1), 0);
verify_pathgroups(&mp1, p1, groups, group_size, 1);
}
static void test_group_by_prio0(void **state)
{
- assert_int_equal(group_by_prio(&mp0), 0);
+ mp0.pgpolicyfn = group_by_prio;
+ assert_int_equal(group_paths(&mp0), 0);
verify_pathgroups(&mp0, NULL, NULL, NULL, 0);
}
static void test_group_by_prio_null(void **state)
{
- assert_int_equal(group_by_prio(&mp_null), 0);
+ mp_null.pgpolicyfn = group_by_prio;
+ assert_int_equal(group_paths(&mp_null), 0);
verify_pathgroups(&mp_null, NULL, NULL, NULL, 0);
}
@@ -430,7 +453,8 @@ static void test_group_by_node_name_same8(void **state)
int group_size[] = {8};
set_tgt_node_name(p8, node_name, 8);
- assert_int_equal(group_by_node_name(&mp8), 0);
+ mp8.pgpolicyfn = group_by_node_name;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 1);
}
@@ -445,7 +469,8 @@ static void test_group_by_node_name_increasing8(void **state)
set_priority(p8, prio, 8);
set_tgt_node_name(p8, node_name, 8);
- assert_int_equal(group_by_node_name(&mp8), 0);
+ mp8.pgpolicyfn = group_by_node_name;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 8);
}
@@ -461,7 +486,8 @@ static void test_group_by_node_name_3_groups8(void **state)
set_priority(p8, prio, 8);
set_tgt_node_name(p8, node_name, 8);
- assert_int_equal(group_by_node_name(&mp8), 0);
+ mp8.pgpolicyfn = group_by_node_name;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 3);
}
@@ -476,7 +502,8 @@ static void test_group_by_node_name_2_groups8(void **state)
set_priority(p8, prio, 8);
set_tgt_node_name(p8, node_name, 8);
- assert_int_equal(group_by_node_name(&mp8), 0);
+ mp8.pgpolicyfn = group_by_node_name;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 2);
}
@@ -492,7 +519,8 @@ static void test_group_by_node_name_3_groups4(void **state)
set_priority(p4, prio, 4);
set_tgt_node_name(p4, node_name, 4);
- assert_int_equal(group_by_node_name(&mp4), 0);
+ mp4.pgpolicyfn = group_by_node_name;
+ assert_int_equal(group_paths(&mp4), 0);
verify_pathgroups(&mp4, p4, groups, group_size, 3);
}
@@ -507,7 +535,8 @@ static void test_group_by_node_name_2_groups4(void **state)
set_priority(p4, prio, 4);
set_tgt_node_name(p4, node_name, 4);
- assert_int_equal(group_by_node_name(&mp4), 0);
+ mp4.pgpolicyfn = group_by_node_name;
+ assert_int_equal(group_paths(&mp4), 0);
verify_pathgroups(&mp4, p4, groups, group_size, 2);
}
@@ -519,19 +548,22 @@ static void test_group_by_node_name1(void **state)
int group_size[] = {1};
set_tgt_node_name(p1, node_name, 1);
- assert_int_equal(group_by_node_name(&mp1), 0);
+ mp1.pgpolicyfn = group_by_node_name;
+ assert_int_equal(group_paths(&mp1), 0);
verify_pathgroups(&mp1, p1, groups, group_size, 1);
}
static void test_group_by_node_name0(void **state)
{
- assert_int_equal(group_by_node_name(&mp0), 0);
+ mp0.pgpolicyfn = group_by_node_name;
+ assert_int_equal(group_paths(&mp0), 0);
verify_pathgroups(&mp0, NULL, NULL, NULL, 0);
}
static void test_group_by_node_name_null(void **state)
{
- assert_int_equal(group_by_node_name(&mp_null), 0);
+ mp_null.pgpolicyfn = group_by_node_name;
+ assert_int_equal(group_paths(&mp_null), 0);
verify_pathgroups(&mp_null, NULL, NULL, NULL, 0);
}
@@ -543,7 +575,8 @@ static void test_group_by_serial_same8(void **state)
int group_size[] = {8};
set_serial(p8, serial, 8);
- assert_int_equal(group_by_serial(&mp8), 0);
+ mp8.pgpolicyfn = group_by_serial;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 1);
}
@@ -558,7 +591,8 @@ static void test_group_by_serial_increasing8(void **state)
set_priority(p8, prio, 8);
set_serial(p8, serial, 8);
- assert_int_equal(group_by_serial(&mp8), 0);
+ mp8.pgpolicyfn = group_by_serial;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 8);
}
@@ -574,7 +608,8 @@ static void test_group_by_serial_3_groups8(void **state)
set_priority(p8, prio, 8);
set_serial(p8, serial, 8);
- assert_int_equal(group_by_serial(&mp8), 0);
+ mp8.pgpolicyfn = group_by_serial;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 3);
}
@@ -589,7 +624,8 @@ static void test_group_by_serial_2_groups8(void **state)
set_priority(p8, prio, 8);
set_serial(p8, serial, 8);
- assert_int_equal(group_by_serial(&mp8), 0);
+ mp8.pgpolicyfn = group_by_serial;
+ assert_int_equal(group_paths(&mp8), 0);
verify_pathgroups(&mp8, p8, groups, group_size, 2);
}
@@ -605,7 +641,8 @@ static void test_group_by_serial_3_groups4(void **state)
set_priority(p4, prio, 4);
set_serial(p4, serial, 4);
- assert_int_equal(group_by_serial(&mp4), 0);
+ mp4.pgpolicyfn = group_by_serial;
+ assert_int_equal(group_paths(&mp4), 0);
verify_pathgroups(&mp4, p4, groups, group_size, 3);
}
@@ -620,7 +657,8 @@ static void test_group_by_serial_2_groups4(void **state)
set_priority(p4, prio, 4);
set_serial(p4, serial, 4);
- assert_int_equal(group_by_serial(&mp4), 0);
+ mp4.pgpolicyfn = group_by_serial;
+ assert_int_equal(group_paths(&mp4), 0);
verify_pathgroups(&mp4, p4, groups, group_size, 2);
}
@@ -632,19 +670,22 @@ static void test_group_by_serial1(void **state)
int group_size[1] = {1};
set_serial(p1, serial, 1);
- assert_int_equal(group_by_serial(&mp1), 0);
+ mp1.pgpolicyfn = group_by_serial;
+ assert_int_equal(group_paths(&mp1), 0);
verify_pathgroups(&mp1, p1, groups, group_size, 1);
}
static void test_group_by_serial0(void **state)
{
- assert_int_equal(group_by_serial(&mp0), 0);
+ mp0.pgpolicyfn = group_by_serial;
+ assert_int_equal(group_paths(&mp0), 0);
verify_pathgroups(&mp0, NULL, NULL, NULL, 0);
}
static void test_group_by_serial_null(void **state)
{
- assert_int_equal(group_by_serial(&mp_null), 0);
+ mp_null.pgpolicyfn = group_by_serial;
+ assert_int_equal(group_paths(&mp_null), 0);
verify_pathgroups(&mp_null, NULL, NULL, NULL, 0);
}
--
2.17.2

View file

@ -0,0 +1,79 @@
From 3209740e5a3e80b5f76dbc2ddaa63f2045aafd53 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 2 Jul 2019 17:30:32 -0500
Subject: [PATCH] libmultipath: fix double free in pgpolicyfn error paths
In the pgpolicy functions, if an error is encountered after
alloc_pathgroup() is called, but before the path group is added to a
multipath device with add_pathgroup(), the pathgroup needs to be cleaned
up by calling free_pathgroup(). However, after the pathgroup has been
added to the multipath device, calling free_pgvec() will clean it up. In
this case, if free_pathgroup() is called first, the recently added
pathgroup will be freed twice.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/pgpolicies.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/libmultipath/pgpolicies.c b/libmultipath/pgpolicies.c
index 1b59485c..1af42f52 100644
--- a/libmultipath/pgpolicies.c
+++ b/libmultipath/pgpolicies.c
@@ -139,7 +139,7 @@ int group_by_node_name(struct multipath * mp)
/* feed the first path */
if (store_path(pgp->paths, pp))
- goto out2;
+ goto out1;
bitmap[i] = 1;
@@ -153,7 +153,7 @@ int group_by_node_name(struct multipath * mp)
if (!strncmp(pp->tgt_node_name, pp2->tgt_node_name,
NODE_NAME_SIZE)) {
if (store_path(pgp->paths, pp2))
- goto out2;
+ goto out1;
bitmap[j] = 1;
}
@@ -206,7 +206,7 @@ int group_by_serial(struct multipath * mp)
/* feed the first path */
if (store_path(pgp->paths, pp))
- goto out2;
+ goto out1;
bitmap[i] = 1;
@@ -219,7 +219,7 @@ int group_by_serial(struct multipath * mp)
if (0 == strcmp(pp->serial, pp2->serial)) {
if (store_path(pgp->paths, pp2))
- goto out2;
+ goto out1;
bitmap[j] = 1;
}
@@ -254,7 +254,7 @@ int one_path_per_group(struct multipath *mp)
goto out1;
if (store_path(pgp->paths, pp))
- goto out1;
+ goto out;
}
return 0;
out1:
@@ -358,7 +358,7 @@ int group_by_prio(struct multipath *mp)
vector_foreach_slot(pathvec, pp, i) {
if (pp->priority == prio) {
if (store_path(pgp->paths, pp))
- goto out2;
+ goto out1;
vector_del_slot(pathvec, i);
i--;
--
2.17.2

View file

@ -0,0 +1,253 @@
From 9cccb06523154911282fd5b0840c6cfa6edd017e Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 3 Jul 2019 14:46:40 -0500
Subject: [PATCH] libmultipath: consolidate group_by_* functions
group_by_node_name() and group_by_serial() are exactly the same except
for how the paths are compared. group_by_prio() is different but its
pathvec solves the same issue as the bitmap from the other two
functions, and since we are always running sort_pathgroups() after
calling pgpriorityfn, there is no need to sort the pathgroups in
group_by_prio(). This means that all three functions can be replaced
with one function, group_by_match() that takes a match function as an
argument.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/pgpolicies.c | 189 +++++++++-----------------------------
1 file changed, 41 insertions(+), 148 deletions(-)
diff --git a/libmultipath/pgpolicies.c b/libmultipath/pgpolicies.c
index 1af42f52..2e4db74c 100644
--- a/libmultipath/pgpolicies.c
+++ b/libmultipath/pgpolicies.c
@@ -4,6 +4,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdbool.h>
#include "checkers.h"
#include "util.h"
@@ -104,10 +105,29 @@ int group_paths(struct multipath *mp)
return 0;
}
-/*
- * One path group per unique tgt_node_name present in the path vector
- */
-int group_by_node_name(struct multipath * mp)
+typedef bool (path_match_fn)(struct path *pp1, struct path *pp2);
+
+bool
+node_names_match(struct path *pp1, struct path *pp2)
+{
+ return (strncmp(pp1->tgt_node_name, pp2->tgt_node_name,
+ NODE_NAME_SIZE) == 0);
+}
+
+bool
+serials_match(struct path *pp1, struct path *pp2)
+{
+ return (strncmp(pp1->serial, pp2->serial, SERIAL_SIZE) == 0);
+}
+
+bool
+prios_match(struct path *pp1, struct path *pp2)
+{
+ return (pp1->priority == pp2->priority);
+}
+
+int group_by_match(struct multipath * mp,
+ bool (*path_match_fn)(struct path *, struct path *))
{
int i, j;
int * bitmap;
@@ -150,8 +170,7 @@ int group_by_node_name(struct multipath * mp)
pp2 = VECTOR_SLOT(mp->paths, j);
- if (!strncmp(pp->tgt_node_name, pp2->tgt_node_name,
- NODE_NAME_SIZE)) {
+ if (path_match_fn(pp, pp2)) {
if (store_path(pgp->paths, pp2))
goto out1;
@@ -171,70 +190,28 @@ out:
return 1;
}
+/*
+ * One path group per unique tgt_node_name present in the path vector
+ */
+int group_by_node_name(struct multipath * mp)
+{
+ return group_by_match(mp, node_names_match);
+}
+
/*
* One path group per unique serial number present in the path vector
*/
int group_by_serial(struct multipath * mp)
{
- int i, j;
- int * bitmap;
- struct path * pp;
- struct pathgroup * pgp;
- struct path * pp2;
-
- /* init the bitmap */
- bitmap = (int *)MALLOC(VECTOR_SIZE(mp->paths) * sizeof (int));
-
- if (!bitmap)
- goto out;
-
- for (i = 0; i < VECTOR_SIZE(mp->paths); i++) {
-
- if (bitmap[i])
- continue;
-
- pp = VECTOR_SLOT(mp->paths, i);
-
- /* here, we really got a new pg */
- pgp = alloc_pathgroup();
-
- if (!pgp)
- goto out1;
-
- if (add_pathgroup(mp, pgp))
- goto out2;
-
- /* feed the first path */
- if (store_path(pgp->paths, pp))
- goto out1;
-
- bitmap[i] = 1;
-
- for (j = i + 1; j < VECTOR_SIZE(mp->paths); j++) {
-
- if (bitmap[j])
- continue;
-
- pp2 = VECTOR_SLOT(mp->paths, j);
-
- if (0 == strcmp(pp->serial, pp2->serial)) {
- if (store_path(pgp->paths, pp2))
- goto out1;
+ return group_by_match(mp, serials_match);
+}
- bitmap[j] = 1;
- }
- }
- }
- FREE(bitmap);
- return 0;
-out2:
- free_pathgroup(pgp, KEEP_PATHS);
-out1:
- FREE(bitmap);
-out:
- free_pgvec(mp->pg, KEEP_PATHS);
- mp->pg = NULL;
- return 1;
+/*
+ * One path group per priority present in the path vector
+ */
+int group_by_prio(struct multipath *mp)
+{
+ return group_by_match(mp, prios_match);
}
int one_path_per_group(struct multipath *mp)
@@ -293,87 +270,3 @@ out:
mp->pg = NULL;
return 1;
}
-
-int group_by_prio(struct multipath *mp)
-{
- int i;
- int prio;
- struct path * pp;
- struct pathgroup * pgp;
- vector pathvec = NULL;
-
- pathvec = vector_alloc();
- if (!pathvec)
- goto out;
-
- vector_foreach_slot(mp->paths, pp, i) {
- if (!vector_alloc_slot(pathvec))
- goto out1;
- vector_set_slot(pathvec, pp);
- }
-
- while (VECTOR_SIZE(pathvec) > 0) {
- pp = VECTOR_SLOT(pathvec, 0);
- prio = pp->priority;
-
- /*
- * Find the position to insert the new path group. All groups
- * are ordered by the priority value (higher value first).
- */
- vector_foreach_slot(mp->pg, pgp, i) {
- pp = VECTOR_SLOT(pgp->paths, 0);
-
- if (prio > pp->priority)
- break;
- }
-
- /*
- * Initialize the new path group.
- */
- pgp = alloc_pathgroup();
-
- if (!pgp)
- goto out1;
-
- if (store_path(pgp->paths, VECTOR_SLOT(pathvec, 0)))
- goto out2;
-
- vector_del_slot(pathvec, 0);
-
- /*
- * Store the new path group into the vector.
- */
- if (i < VECTOR_SIZE(mp->pg)) {
- if (!vector_insert_slot(mp->pg, i, pgp))
- goto out2;
- pgp->mpp = mp;
- } else {
- if (add_pathgroup(mp, pgp))
- goto out2;
- }
-
- /*
- * add the other paths with the same prio
- */
- vector_foreach_slot(pathvec, pp, i) {
- if (pp->priority == prio) {
- if (store_path(pgp->paths, pp))
- goto out1;
-
- vector_del_slot(pathvec, i);
- i--;
- }
- }
- }
- free_pathvec(pathvec, KEEP_PATHS);
- return 0;
-out2:
- free_pathgroup(pgp, KEEP_PATHS);
-out1:
- free_pathvec(pathvec, KEEP_PATHS);
-out:
- free_pgvec(mp->pg, KEEP_PATHS);
- mp->pg = NULL;
- return 1;
-
-}
--
2.17.2

View file

@ -0,0 +1,174 @@
From 1e45eb6db98185ac8917c0c8feec69b7c0226230 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 11 Jul 2019 18:13:06 -0500
Subject: [PATCH] libmultipath: make pgpolicyfn take a paths vector
To enable future changes, mp->pgpolicyfn() now takes a vector of
paths instead of always using mp->paths.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/pgpolicies.c | 38 +++++++++++++++++++-------------------
libmultipath/pgpolicies.h | 10 +++++-----
libmultipath/structs.h | 2 +-
3 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/libmultipath/pgpolicies.c b/libmultipath/pgpolicies.c
index 2e4db74c..2e7c0502 100644
--- a/libmultipath/pgpolicies.c
+++ b/libmultipath/pgpolicies.c
@@ -93,7 +93,7 @@ int group_paths(struct multipath *mp)
return 1;
if (VECTOR_SIZE(mp->paths) > 0 &&
- (!mp->pgpolicyfn || mp->pgpolicyfn(mp))) {
+ (!mp->pgpolicyfn || mp->pgpolicyfn(mp, mp->paths))) {
vector_free(mp->pg);
mp->pg = NULL;
return 1;
@@ -126,7 +126,7 @@ prios_match(struct path *pp1, struct path *pp2)
return (pp1->priority == pp2->priority);
}
-int group_by_match(struct multipath * mp,
+int group_by_match(struct multipath * mp, vector paths,
bool (*path_match_fn)(struct path *, struct path *))
{
int i, j;
@@ -136,17 +136,17 @@ int group_by_match(struct multipath * mp,
struct path * pp2;
/* init the bitmap */
- bitmap = (int *)MALLOC(VECTOR_SIZE(mp->paths) * sizeof (int));
+ bitmap = (int *)MALLOC(VECTOR_SIZE(paths) * sizeof (int));
if (!bitmap)
goto out;
- for (i = 0; i < VECTOR_SIZE(mp->paths); i++) {
+ for (i = 0; i < VECTOR_SIZE(paths); i++) {
if (bitmap[i])
continue;
- pp = VECTOR_SLOT(mp->paths, i);
+ pp = VECTOR_SLOT(paths, i);
/* here, we really got a new pg */
pgp = alloc_pathgroup();
@@ -163,12 +163,12 @@ int group_by_match(struct multipath * mp,
bitmap[i] = 1;
- for (j = i + 1; j < VECTOR_SIZE(mp->paths); j++) {
+ for (j = i + 1; j < VECTOR_SIZE(paths); j++) {
if (bitmap[j])
continue;
- pp2 = VECTOR_SLOT(mp->paths, j);
+ pp2 = VECTOR_SLOT(paths, j);
if (path_match_fn(pp, pp2)) {
if (store_path(pgp->paths, pp2))
@@ -193,35 +193,35 @@ out:
/*
* One path group per unique tgt_node_name present in the path vector
*/
-int group_by_node_name(struct multipath * mp)
+int group_by_node_name(struct multipath * mp, vector paths)
{
- return group_by_match(mp, node_names_match);
+ return group_by_match(mp, paths, node_names_match);
}
/*
* One path group per unique serial number present in the path vector
*/
-int group_by_serial(struct multipath * mp)
+int group_by_serial(struct multipath * mp, vector paths)
{
- return group_by_match(mp, serials_match);
+ return group_by_match(mp, paths, serials_match);
}
/*
* One path group per priority present in the path vector
*/
-int group_by_prio(struct multipath *mp)
+int group_by_prio(struct multipath *mp, vector paths)
{
- return group_by_match(mp, prios_match);
+ return group_by_match(mp, paths, prios_match);
}
-int one_path_per_group(struct multipath *mp)
+int one_path_per_group(struct multipath *mp, vector paths)
{
int i;
struct path * pp;
struct pathgroup * pgp;
- for (i = 0; i < VECTOR_SIZE(mp->paths); i++) {
- pp = VECTOR_SLOT(mp->paths, i);
+ for (i = 0; i < VECTOR_SIZE(paths); i++) {
+ pp = VECTOR_SLOT(paths, i);
pgp = alloc_pathgroup();
if (!pgp)
@@ -242,7 +242,7 @@ out:
return 1;
}
-int one_group(struct multipath *mp) /* aka multibus */
+int one_group(struct multipath *mp, vector paths) /* aka multibus */
{
int i;
struct path * pp;
@@ -256,8 +256,8 @@ int one_group(struct multipath *mp) /* aka multibus */
if (add_pathgroup(mp, pgp))
goto out1;
- for (i = 0; i < VECTOR_SIZE(mp->paths); i++) {
- pp = VECTOR_SLOT(mp->paths, i);
+ for (i = 0; i < VECTOR_SIZE(paths); i++) {
+ pp = VECTOR_SLOT(paths, i);
if (store_path(pgp->paths, pp))
goto out;
diff --git a/libmultipath/pgpolicies.h b/libmultipath/pgpolicies.h
index 11834011..7532d75f 100644
--- a/libmultipath/pgpolicies.h
+++ b/libmultipath/pgpolicies.h
@@ -25,10 +25,10 @@ int group_paths(struct multipath *);
/*
* policies
*/
-int one_path_per_group(struct multipath *);
-int one_group(struct multipath *);
-int group_by_serial(struct multipath *);
-int group_by_prio(struct multipath *);
-int group_by_node_name(struct multipath *);
+int one_path_per_group(struct multipath *, vector);
+int one_group(struct multipath *, vector);
+int group_by_serial(struct multipath *, vector);
+int group_by_prio(struct multipath *, vector);
+int group_by_node_name(struct multipath *, vector);
#endif
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index 893074eb..a8b9d325 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -295,7 +295,7 @@ struct path {
struct gen_path generic_path;
};
-typedef int (pgpolicyfn) (struct multipath *);
+typedef int (pgpolicyfn) (struct multipath *, vector);
struct multipath {
char wwid[WWID_SIZE];
--
2.17.2

View file

@ -0,0 +1,185 @@
From 227a9fceb8c20f153f4f136caeb28faff5bd80fe Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 12 Jul 2019 15:39:26 -0500
Subject: [PATCH] libmultipath: make group_paths handle marginal paths
group_paths() will now create seperate path groups for marginal and
normal paths, and place all of the marginal path groups after the normal
ones, in order by priority.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/pgpolicies.c | 83 +++++++++++++++++++++++++++++++++-----
libmultipath/switchgroup.c | 15 ++++++-
2 files changed, 88 insertions(+), 10 deletions(-)
diff --git a/libmultipath/pgpolicies.c b/libmultipath/pgpolicies.c
index 2e7c0502..6fb2d28a 100644
--- a/libmultipath/pgpolicies.c
+++ b/libmultipath/pgpolicies.c
@@ -72,9 +72,11 @@ sort_pathgroups (struct multipath *mp) {
pgp2 = VECTOR_SLOT(mp->pg, j);
if (!pgp2)
continue;
- if (pgp2->priority > pgp1->priority ||
- (pgp2->priority == pgp1->priority &&
- pgp2->enabled_paths >= pgp1->enabled_paths)) {
+ if (pgp2->marginal < pgp1->marginal ||
+ (pgp2->marginal == pgp1->marginal &&
+ (pgp2->priority > pgp1->priority ||
+ (pgp2->priority == pgp1->priority &&
+ pgp2->enabled_paths >= pgp1->enabled_paths)))) {
vector_move_up(mp->pg, i, j + 1);
break;
}
@@ -84,25 +86,88 @@ sort_pathgroups (struct multipath *mp) {
}
}
+static int
+split_marginal_paths(vector paths, vector *normal_p, vector *marginal_p)
+{
+ int i;
+ int has_marginal = 0;
+ int has_normal = 0;
+ struct path *pp;
+ vector normal = NULL;
+ vector marginal = NULL;
+
+ *normal_p = *marginal_p = NULL;
+ vector_foreach_slot(paths, pp, i) {
+ if (pp->marginal)
+ has_marginal = 1;
+ else
+ has_normal = 1;
+ }
+
+ if (!has_marginal || !has_normal)
+ return -1;
+
+ normal = vector_alloc();
+ marginal = vector_alloc();
+ if (!normal || !marginal)
+ goto fail;
+
+ vector_foreach_slot(paths, pp, i) {
+ if (pp->marginal) {
+ if (store_path(marginal, pp))
+ goto fail;
+ }
+ else {
+ if (store_path(normal, pp))
+ goto fail;
+ }
+ }
+ *normal_p = normal;
+ *marginal_p = marginal;
+ return 0;
+fail:
+ vector_free(normal);
+ vector_free(marginal);
+ return -1;
+}
int group_paths(struct multipath *mp)
{
+ vector normal, marginal;
+
if (!mp->pg)
mp->pg = vector_alloc();
if (!mp->pg)
return 1;
- if (VECTOR_SIZE(mp->paths) > 0 &&
- (!mp->pgpolicyfn || mp->pgpolicyfn(mp, mp->paths))) {
- vector_free(mp->pg);
- mp->pg = NULL;
- return 1;
+ if (VECTOR_SIZE(mp->paths) == 0)
+ goto out;
+ if (!mp->pgpolicyfn)
+ goto fail;
+
+ if (split_marginal_paths(mp->paths, &normal, &marginal) != 0) {
+ if (mp->pgpolicyfn(mp, mp->paths) != 0)
+ goto fail;
+ } else {
+ if (mp->pgpolicyfn(mp, normal) != 0)
+ goto fail_marginal;
+ if (mp->pgpolicyfn(mp, marginal) != 0)
+ goto fail_marginal;
+ vector_free(normal);
+ vector_free(marginal);
}
-
sort_pathgroups(mp);
+out:
vector_free(mp->paths);
mp->paths = NULL;
return 0;
+fail_marginal:
+ vector_free(normal);
+ vector_free(marginal);
+fail:
+ vector_free(mp->pg);
+ mp->pg = NULL;
+ return 1;
}
typedef bool (path_match_fn)(struct path *pp1, struct path *pp2);
diff --git a/libmultipath/switchgroup.c b/libmultipath/switchgroup.c
index 9632ce2d..6fdfcfa7 100644
--- a/libmultipath/switchgroup.c
+++ b/libmultipath/switchgroup.c
@@ -11,6 +11,7 @@ void path_group_prio_update(struct pathgroup *pgp)
{
int i;
int priority = 0;
+ int marginal = 0;
struct path * pp;
pgp->enabled_paths = 0;
@@ -19,6 +20,8 @@ void path_group_prio_update(struct pathgroup *pgp)
return;
}
vector_foreach_slot (pgp->paths, pp, i) {
+ if (pp->marginal)
+ marginal++;
if (pp->state == PATH_UP ||
pp->state == PATH_GHOST) {
priority += pp->priority;
@@ -29,11 +32,14 @@ void path_group_prio_update(struct pathgroup *pgp)
pgp->priority = priority / pgp->enabled_paths;
else
pgp->priority = 0;
+ if (marginal && marginal == i)
+ pgp->marginal = 1;
}
int select_path_group(struct multipath *mpp)
{
int i;
+ int normal_pgp = 0;
int max_priority = 0;
int bestpg = 1;
int max_enabled_paths = 1;
@@ -47,8 +53,15 @@ int select_path_group(struct multipath *mpp)
continue;
path_group_prio_update(pgp);
+ if (pgp->marginal && normal_pgp)
+ continue;
if (pgp->enabled_paths) {
- if (pgp->priority > max_priority) {
+ if (!pgp->marginal && !normal_pgp) {
+ normal_pgp = 1;
+ max_priority = pgp->priority;
+ max_enabled_paths = pgp->enabled_paths;
+ bestpg = i + 1;
+ } else if (pgp->priority > max_priority) {
max_priority = pgp->priority;
max_enabled_paths = pgp->enabled_paths;
bestpg = i + 1;
--
2.17.2

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,701 @@
From ede846d1761709e2832c0a4c777369ae89692841 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 23 Jul 2019 13:21:12 -0500
Subject: [PATCH] tests: add tests for grouping marginal paths.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
tests/pgpolicy.c | 337 +++++++++++++++++++++++++++++++++++++++++------
1 file changed, 295 insertions(+), 42 deletions(-)
diff --git a/tests/pgpolicy.c b/tests/pgpolicy.c
index 04a77c4c..ab09f91c 100644
--- a/tests/pgpolicy.c
+++ b/tests/pgpolicy.c
@@ -40,6 +40,15 @@ static void set_priority(struct path *pp, int *prio, int size)
}
}
+static void set_marginal(struct path *pp, int *marginal, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ pp[i].marginal = marginal[i];
+ }
+}
+
static void set_tgt_node_name(struct path *pp, char **tgt_node_name, int size)
{
int i;
@@ -82,6 +91,7 @@ static int setupX(struct multipath *mp, struct path *pp, int size)
{
int i;
int prio[8] = {10, 10, 10, 10, 10, 10, 10, 10};
+ int marginal[8] = {0, 0, 0, 0, 0, 0, 0, 0};
mp->paths = vector_alloc();
if (!mp->paths)
@@ -92,6 +102,7 @@ static int setupX(struct multipath *mp, struct path *pp, int size)
vector_set_slot(mp->paths, &pp[i]);
}
set_priority(pp, prio, size);
+ set_marginal(pp, marginal, size);
mp->pgpolicyfn = NULL;
return 0;
}
@@ -155,7 +166,7 @@ static int teardown_null(void **state)
static void
verify_pathgroups(struct multipath *mp, struct path *pp, int **groups,
- int *group_size, int size)
+ int *group_size, int *marginal, int size)
{
int i, j;
struct pathgroup *pgp;
@@ -168,6 +179,10 @@ verify_pathgroups(struct multipath *mp, struct path *pp, int **groups,
assert_non_null(pgp);
assert_non_null(pgp->paths);
assert_int_equal(VECTOR_SIZE(pgp->paths), group_size[i]);
+ if (marginal)
+ assert_int_equal(pgp->marginal, marginal[i]);
+ else
+ assert_int_equal(pgp->marginal, 0);
for (j = 0; j < group_size[i]; j++) {
int path_nr = groups[i][j];
struct path *pgp_path = VECTOR_SLOT(pgp->paths, j);
@@ -190,7 +205,7 @@ static void test_one_group8(void **state)
mp8.pgpolicyfn = one_group;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 1);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 1);
}
static void test_one_group4(void **state)
@@ -201,7 +216,7 @@ static void test_one_group4(void **state)
mp4.pgpolicyfn = one_group;
assert_int_equal(group_paths(&mp4), 0);
- verify_pathgroups(&mp4, p4, groups, group_size, 1);
+ verify_pathgroups(&mp4, p4, groups, group_size, NULL, 1);
}
static void test_one_group1(void **state)
@@ -212,21 +227,65 @@ static void test_one_group1(void **state)
mp1.pgpolicyfn = one_group;
assert_int_equal(group_paths(&mp1), 0);
- verify_pathgroups(&mp1, p1, groups, group_size, 1);
+ verify_pathgroups(&mp1, p1, groups, group_size, NULL, 1);
}
static void test_one_group0(void **state)
{
mp0.pgpolicyfn = one_group;
assert_int_equal(group_paths(&mp0), 0);
- verify_pathgroups(&mp0, NULL, NULL, NULL, 0);
+ verify_pathgroups(&mp0, NULL, NULL, NULL, NULL, 0);
}
static void test_one_group_null(void **state)
{
mp_null.pgpolicyfn = one_group;
assert_int_equal(group_paths(&mp_null), 0);
- verify_pathgroups(&mp_null, NULL, NULL, NULL, 0);
+ verify_pathgroups(&mp_null, NULL, NULL, NULL, NULL, 0);
+}
+
+static void test_one_group_all_marginal8(void **state)
+{
+ int paths[] = {0,1,2,3,4,5,6,7};
+ int marginal[] = {1,1,1,1,1,1,1,1};
+ int *groups[] = {paths};
+ int group_size[] = {8};
+ int group_marginal[] = {1};
+
+ set_marginal(p8, marginal, 8);
+ mp8.pgpolicyfn = one_group;
+ assert_int_equal(group_paths(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 1);
+}
+
+static void test_one_group_half_marginal8(void **state)
+{
+ int marginal[] = {1,0,1,0,1,1,0,0};
+ int group0[] = {1,3,6,7};
+ int group1[] = {0,2,4,5};
+ int *groups[] = {group0, group1};
+ int group_size[] = {4,4};
+ int group_marginal[] = {0,1};
+
+ set_marginal(p8, marginal, 8);
+ mp8.pgpolicyfn = one_group;
+ assert_int_equal(group_paths(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 2);
+}
+
+static void test_one_group_one_marginal8(void **state)
+{
+ int marginal[] = {0,0,0,0,0,1,0,0};
+ int group0[] = {0,1,2,3,4,6,7};
+ int group1[] = {5};
+ int *groups[] = {group0, group1};
+ int group_size[] = {7,1};
+ int group_marginal[] = {0,1};
+
+ set_marginal(p8, marginal, 8);
+ mp8.pgpolicyfn = one_group;
+ assert_int_equal(group_paths(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 2);
}
static void test_one_path_per_group_same8(void **state)
@@ -238,7 +297,7 @@ static void test_one_path_per_group_same8(void **state)
mp8.pgpolicyfn = one_path_per_group;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 8);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 8);
}
static void test_one_path_per_group_increasing8(void **state)
@@ -252,7 +311,7 @@ static void test_one_path_per_group_increasing8(void **state)
set_priority(p8, prio, 8);
mp8.pgpolicyfn = one_path_per_group;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 8);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 8);
}
static void test_one_path_per_group_decreasing8(void **state)
@@ -266,7 +325,7 @@ static void test_one_path_per_group_decreasing8(void **state)
set_priority(p8, prio, 8);
mp8.pgpolicyfn = one_path_per_group;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 8);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 8);
}
static void test_one_path_per_group_mixed8(void **state)
@@ -280,7 +339,7 @@ static void test_one_path_per_group_mixed8(void **state)
set_priority(p8, prio, 8);
mp8.pgpolicyfn = one_path_per_group;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 8);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 8);
}
static void test_one_path_per_group4(void **state)
@@ -291,7 +350,7 @@ static void test_one_path_per_group4(void **state)
mp4.pgpolicyfn = one_path_per_group;
assert_int_equal(group_paths(&mp4), 0);
- verify_pathgroups(&mp4, p4, groups, group_size, 4);
+ verify_pathgroups(&mp4, p4, groups, group_size, NULL, 4);
}
static void test_one_path_per_group1(void **state)
@@ -302,21 +361,55 @@ static void test_one_path_per_group1(void **state)
mp1.pgpolicyfn = one_path_per_group;
assert_int_equal(group_paths(&mp1), 0);
- verify_pathgroups(&mp1, p1, groups, group_size, 1);
+ verify_pathgroups(&mp1, p1, groups, group_size, NULL, 1);
}
static void test_one_path_per_group0(void **state)
{
mp0.pgpolicyfn = one_path_per_group;
assert_int_equal(group_paths(&mp0), 0);
- verify_pathgroups(&mp0, NULL, NULL, NULL, 0);
+ verify_pathgroups(&mp0, NULL, NULL, NULL, NULL, 0);
}
static void test_one_path_per_group_null(void **state)
{
mp_null.pgpolicyfn = one_path_per_group;
assert_int_equal(group_paths(&mp_null), 0);
- verify_pathgroups(&mp_null, NULL, NULL, NULL, 0);
+ verify_pathgroups(&mp_null, NULL, NULL, NULL, NULL, 0);
+}
+
+static void test_one_path_per_group_mixed_all_marginal8(void **state)
+{
+ int prio[] = {7,1,3,3,5,2,8,2};
+ int marginal[] = {1,1,1,1,1,1,1,1};
+ int paths[] = {6,0,4,2,3,5,7,1};
+ int *groups[] = {&paths[0], &paths[1], &paths[2], &paths[3],
+ &paths[4], &paths[5], &paths[6], &paths[7]};
+ int group_size[] = {1,1,1,1,1,1,1,1};
+ int group_marginal[] = {1,1,1,1,1,1,1,1};
+
+ set_priority(p8, prio, 8);
+ set_marginal(p8, marginal, 8);
+ mp8.pgpolicyfn = one_path_per_group;
+ assert_int_equal(group_paths(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 8);
+}
+
+static void test_one_path_per_group_mixed_half_marginal8(void **state)
+{
+ int prio[] = {7,1,3,3,5,2,8,2};
+ int marginal[] = {0,1,1,0,0,0,1,1};
+ int paths[] = {0,4,3,5,6,2,7,1};
+ int *groups[] = {&paths[0], &paths[1], &paths[2], &paths[3],
+ &paths[4], &paths[5], &paths[6], &paths[7]};
+ int group_size[] = {1,1,1,1,1,1,1,1};
+ int group_marginal[] = {0,0,0,0,1,1,1,1};
+
+ set_priority(p8, prio, 8);
+ set_marginal(p8, marginal, 8);
+ mp8.pgpolicyfn = one_path_per_group;
+ assert_int_equal(group_paths(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 8);
}
static void test_group_by_prio_same8(void **state)
@@ -327,7 +420,7 @@ static void test_group_by_prio_same8(void **state)
mp8.pgpolicyfn = group_by_prio;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 1);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 1);
}
static void test_group_by_prio_increasing8(void **state)
@@ -341,7 +434,7 @@ static void test_group_by_prio_increasing8(void **state)
set_priority(p8, prio, 8);
mp8.pgpolicyfn = group_by_prio;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 8);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 8);
}
static void test_group_by_prio_decreasing8(void **state)
@@ -355,7 +448,7 @@ static void test_group_by_prio_decreasing8(void **state)
set_priority(p8, prio, 8);
mp8.pgpolicyfn = group_by_prio;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 8);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 8);
}
static void test_group_by_prio_mixed8(void **state)
@@ -374,7 +467,7 @@ static void test_group_by_prio_mixed8(void **state)
set_priority(p8, prio, 8);
mp8.pgpolicyfn = group_by_prio;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 6);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 6);
}
static void test_group_by_prio_2_groups8(void **state)
@@ -388,7 +481,7 @@ static void test_group_by_prio_2_groups8(void **state)
set_priority(p8, prio, 8);
mp8.pgpolicyfn = group_by_prio;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 2);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 2);
}
static void test_group_by_prio_mixed4(void **state)
@@ -403,7 +496,7 @@ static void test_group_by_prio_mixed4(void **state)
set_priority(p4, prio, 4);
mp4.pgpolicyfn = group_by_prio;
assert_int_equal(group_paths(&mp4), 0);
- verify_pathgroups(&mp4, p4, groups, group_size, 3);
+ verify_pathgroups(&mp4, p4, groups, group_size, NULL, 3);
}
static void test_group_by_prio_2_groups4(void **state)
@@ -417,7 +510,7 @@ static void test_group_by_prio_2_groups4(void **state)
set_priority(p4, prio, 4);
mp4.pgpolicyfn = group_by_prio;
assert_int_equal(group_paths(&mp4), 0);
- verify_pathgroups(&mp4, p4, groups, group_size, 2);
+ verify_pathgroups(&mp4, p4, groups, group_size, NULL, 2);
}
static void test_group_by_prio1(void **state)
@@ -428,21 +521,89 @@ static void test_group_by_prio1(void **state)
mp1.pgpolicyfn = group_by_prio;
assert_int_equal(group_paths(&mp1), 0);
- verify_pathgroups(&mp1, p1, groups, group_size, 1);
+ verify_pathgroups(&mp1, p1, groups, group_size, NULL, 1);
}
static void test_group_by_prio0(void **state)
{
mp0.pgpolicyfn = group_by_prio;
assert_int_equal(group_paths(&mp0), 0);
- verify_pathgroups(&mp0, NULL, NULL, NULL, 0);
+ verify_pathgroups(&mp0, NULL, NULL, NULL, NULL, 0);
}
static void test_group_by_prio_null(void **state)
{
mp_null.pgpolicyfn = group_by_prio;
assert_int_equal(group_paths(&mp_null), 0);
- verify_pathgroups(&mp_null, NULL, NULL, NULL, 0);
+ verify_pathgroups(&mp_null, NULL, NULL, NULL, NULL, 0);
+}
+
+static void test_group_by_prio_mixed_all_marginal8(void **state)
+{
+ int prio[] = {7,1,3,3,5,2,8,2};
+ int marginal[] = {1,1,1,1,1,1,1,1};
+ int group0[] = {6};
+ int group1[] = {0};
+ int group2[] = {4};
+ int group3[] = {2,3};
+ int group4[] = {5,7};
+ int group5[] = {1};
+ int *groups[] = {group0, group1, group2, group3,
+ group4, group5};
+ int group_size[] = {1,1,1,2,2,1};
+ int group_marginal[] = {1,1,1,1,1,1};
+
+ set_priority(p8, prio, 8);
+ set_marginal(p8, marginal, 8);
+ mp8.pgpolicyfn = group_by_prio;
+ assert_int_equal(group_paths(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 6);
+}
+
+static void test_group_by_prio_mixed_half_marginal8(void **state)
+{
+ int prio[] = {7,1,3,3,5,2,8,2};
+ int marginal[] = {0,0,0,1,0,1,1,1};
+ int group0[] = {0};
+ int group1[] = {4};
+ int group2[] = {2};
+ int group3[] = {1};
+ int group4[] = {6};
+ int group5[] = {3};
+ int group6[] = {5,7};
+ int *groups[] = {group0, group1, group2, group3,
+ group4, group5, group6};
+ int group_size[] = {1,1,1,1,1,1,2};
+ int group_marginal[] = {0,0,0,0,1,1,1};
+
+ set_priority(p8, prio, 8);
+ set_marginal(p8, marginal, 8);
+ mp8.pgpolicyfn = group_by_prio;
+ assert_int_equal(group_paths(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 7);
+}
+
+static void test_group_by_prio_mixed_one_marginal8(void **state)
+{
+ int prio[] = {7,1,3,3,5,2,8,2};
+ int marginal[] = {0,0,0,0,0,1,0,0};
+ int group0[] = {6};
+ int group1[] = {0};
+ int group2[] = {4};
+ int group3[] = {2,3};
+ int group4[] = {7};
+ int group5[] = {1};
+ int group6[] = {5};
+ int *groups[] = {group0, group1, group2, group3,
+ group4, group5, group6};
+ int group_size[] = {1,1,1,2,1,1,1};
+ int group_marginal[] = {0,0,0,0,0,0,1};
+
+ set_priority(p8, prio, 8);
+ set_marginal(p8, marginal, 8);
+ mp8.pgpolicyfn = group_by_prio;
+ assert_int_equal(group_paths(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 7);
}
static void test_group_by_node_name_same8(void **state)
@@ -455,7 +616,7 @@ static void test_group_by_node_name_same8(void **state)
set_tgt_node_name(p8, node_name, 8);
mp8.pgpolicyfn = group_by_node_name;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 1);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 1);
}
static void test_group_by_node_name_increasing8(void **state)
@@ -471,7 +632,7 @@ static void test_group_by_node_name_increasing8(void **state)
set_tgt_node_name(p8, node_name, 8);
mp8.pgpolicyfn = group_by_node_name;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 8);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 8);
}
static void test_group_by_node_name_3_groups8(void **state)
@@ -488,7 +649,7 @@ static void test_group_by_node_name_3_groups8(void **state)
set_tgt_node_name(p8, node_name, 8);
mp8.pgpolicyfn = group_by_node_name;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 3);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 3);
}
static void test_group_by_node_name_2_groups8(void **state)
@@ -504,7 +665,7 @@ static void test_group_by_node_name_2_groups8(void **state)
set_tgt_node_name(p8, node_name, 8);
mp8.pgpolicyfn = group_by_node_name;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 2);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 2);
}
static void test_group_by_node_name_3_groups4(void **state)
@@ -521,7 +682,7 @@ static void test_group_by_node_name_3_groups4(void **state)
set_tgt_node_name(p4, node_name, 4);
mp4.pgpolicyfn = group_by_node_name;
assert_int_equal(group_paths(&mp4), 0);
- verify_pathgroups(&mp4, p4, groups, group_size, 3);
+ verify_pathgroups(&mp4, p4, groups, group_size, NULL, 3);
}
static void test_group_by_node_name_2_groups4(void **state)
@@ -537,7 +698,7 @@ static void test_group_by_node_name_2_groups4(void **state)
set_tgt_node_name(p4, node_name, 4);
mp4.pgpolicyfn = group_by_node_name;
assert_int_equal(group_paths(&mp4), 0);
- verify_pathgroups(&mp4, p4, groups, group_size, 2);
+ verify_pathgroups(&mp4, p4, groups, group_size, NULL, 2);
}
static void test_group_by_node_name1(void **state)
@@ -550,21 +711,61 @@ static void test_group_by_node_name1(void **state)
set_tgt_node_name(p1, node_name, 1);
mp1.pgpolicyfn = group_by_node_name;
assert_int_equal(group_paths(&mp1), 0);
- verify_pathgroups(&mp1, p1, groups, group_size, 1);
+ verify_pathgroups(&mp1, p1, groups, group_size, NULL, 1);
}
static void test_group_by_node_name0(void **state)
{
mp0.pgpolicyfn = group_by_node_name;
assert_int_equal(group_paths(&mp0), 0);
- verify_pathgroups(&mp0, NULL, NULL, NULL, 0);
+ verify_pathgroups(&mp0, NULL, NULL, NULL, NULL, 0);
}
static void test_group_by_node_name_null(void **state)
{
mp_null.pgpolicyfn = group_by_node_name;
assert_int_equal(group_paths(&mp_null), 0);
- verify_pathgroups(&mp_null, NULL, NULL, NULL, 0);
+ verify_pathgroups(&mp_null, NULL, NULL, NULL, NULL, 0);
+}
+
+static void test_group_by_node_name_2_groups_all_marginal8(void **state)
+{
+ char *node_name[] = {"a", "a", "b", "a", "b", "b", "b", "a"};
+ int prio[] = {4,1,2,1,2,2,2,1};
+ int marginal[] = {1,1,1,1,1,1,1,1};
+ int group0[] = {2,4,5,6};
+ int group1[] = {0,1,3,7};
+ int *groups[] = {group0, group1};
+ int group_size[] = {4,4};
+ int group_marginal[] = {1,1};
+
+ set_priority(p8, prio, 8);
+ set_marginal(p8, marginal, 8);
+ set_tgt_node_name(p8, node_name, 8);
+ mp8.pgpolicyfn = group_by_node_name;
+ assert_int_equal(group_paths(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 2);
+}
+
+static void test_group_by_node_name_2_groups_half_marginal8(void **state)
+{
+ char *node_name[] = {"a", "a", "b", "a", "b", "b", "b", "a"};
+ int prio[] = {4,1,2,1,2,2,2,1};
+ int marginal[] = {1,0,1,1,0,1,0,0};
+ int group0[] = {4,6};
+ int group1[] = {1,7};
+ int group2[] = {0,3};
+ int group3[] = {2,5};
+ int *groups[] = {group0, group1, group2, group3};
+ int group_size[] = {2,2,2,2};
+ int group_marginal[] = {0,0,1,1};
+
+ set_priority(p8, prio, 8);
+ set_marginal(p8, marginal, 8);
+ set_tgt_node_name(p8, node_name, 8);
+ mp8.pgpolicyfn = group_by_node_name;
+ assert_int_equal(group_paths(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 4);
}
static void test_group_by_serial_same8(void **state)
@@ -577,7 +778,7 @@ static void test_group_by_serial_same8(void **state)
set_serial(p8, serial, 8);
mp8.pgpolicyfn = group_by_serial;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 1);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 1);
}
static void test_group_by_serial_increasing8(void **state)
@@ -593,7 +794,7 @@ static void test_group_by_serial_increasing8(void **state)
set_serial(p8, serial, 8);
mp8.pgpolicyfn = group_by_serial;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 8);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 8);
}
static void test_group_by_serial_3_groups8(void **state)
@@ -610,7 +811,7 @@ static void test_group_by_serial_3_groups8(void **state)
set_serial(p8, serial, 8);
mp8.pgpolicyfn = group_by_serial;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 3);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 3);
}
static void test_group_by_serial_2_groups8(void **state)
@@ -626,7 +827,7 @@ static void test_group_by_serial_2_groups8(void **state)
set_serial(p8, serial, 8);
mp8.pgpolicyfn = group_by_serial;
assert_int_equal(group_paths(&mp8), 0);
- verify_pathgroups(&mp8, p8, groups, group_size, 2);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 2);
}
static void test_group_by_serial_3_groups4(void **state)
@@ -643,7 +844,7 @@ static void test_group_by_serial_3_groups4(void **state)
set_serial(p4, serial, 4);
mp4.pgpolicyfn = group_by_serial;
assert_int_equal(group_paths(&mp4), 0);
- verify_pathgroups(&mp4, p4, groups, group_size, 3);
+ verify_pathgroups(&mp4, p4, groups, group_size, NULL, 3);
}
static void test_group_by_serial_2_groups4(void **state)
@@ -659,7 +860,7 @@ static void test_group_by_serial_2_groups4(void **state)
set_serial(p4, serial, 4);
mp4.pgpolicyfn = group_by_serial;
assert_int_equal(group_paths(&mp4), 0);
- verify_pathgroups(&mp4, p4, groups, group_size, 2);
+ verify_pathgroups(&mp4, p4, groups, group_size, NULL, 2);
}
static void test_group_by_serial1(void **state)
@@ -672,21 +873,61 @@ static void test_group_by_serial1(void **state)
set_serial(p1, serial, 1);
mp1.pgpolicyfn = group_by_serial;
assert_int_equal(group_paths(&mp1), 0);
- verify_pathgroups(&mp1, p1, groups, group_size, 1);
+ verify_pathgroups(&mp1, p1, groups, group_size, NULL, 1);
}
static void test_group_by_serial0(void **state)
{
mp0.pgpolicyfn = group_by_serial;
assert_int_equal(group_paths(&mp0), 0);
- verify_pathgroups(&mp0, NULL, NULL, NULL, 0);
+ verify_pathgroups(&mp0, NULL, NULL, NULL, NULL, 0);
}
static void test_group_by_serial_null(void **state)
{
mp_null.pgpolicyfn = group_by_serial;
assert_int_equal(group_paths(&mp_null), 0);
- verify_pathgroups(&mp_null, NULL, NULL, NULL, 0);
+ verify_pathgroups(&mp_null, NULL, NULL, NULL, NULL, 0);
+}
+
+static void test_group_by_serial_2_groups8_all_marginal8(void **state)
+{
+ char *serial[] = {"1", "2", "1", "1", "2", "2", "1", "2"};
+ int marginal[] = {1,1,1,1,1,1,1,1};
+ int prio[] = {3,2,2,1,2,2,1,2};
+ int group0[] = {1,4,5,7};
+ int group1[] = {0,2,3,6};
+ int *groups[] = {group0, group1};
+ int group_size[] = {4,4};
+ int group_marginal[] = {1,1};
+
+ set_priority(p8, prio, 8);
+ set_serial(p8, serial, 8);
+ set_marginal(p8, marginal, 8);
+ mp8.pgpolicyfn = group_by_serial;
+ assert_int_equal(group_paths(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 2);
+}
+
+static void test_group_by_serial_2_groups8_half_marginal8(void **state)
+{
+ char *serial[] = {"1", "2", "1", "1", "2", "2", "1", "2"};
+ int marginal[] = {0,0,1,1,1,1,0,0};
+ int prio[] = {3,2,2,1,2,2,1,2};
+ int group0[] = {0,6};
+ int group1[] = {1,7};
+ int group2[] = {4,5};
+ int group3[] = {2,3};
+ int *groups[] = {group0, group1, group2, group3};
+ int group_size[] = {2,2,2,2};
+ int group_marginal[] = {0,0,1,1};
+
+ set_priority(p8, prio, 8);
+ set_serial(p8, serial, 8);
+ set_marginal(p8, marginal, 8);
+ mp8.pgpolicyfn = group_by_serial;
+ assert_int_equal(group_paths(&mp8), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 4);
}
#define setup_test(name, nr) \
@@ -700,6 +941,9 @@ int test_pgpolicies(void)
setup_test(test_one_group, 1),
setup_test(test_one_group, 0),
setup_test(test_one_group, _null),
+ setup_test(test_one_group_all_marginal, 8),
+ setup_test(test_one_group_half_marginal, 8),
+ setup_test(test_one_group_one_marginal, 8),
setup_test(test_one_path_per_group_same, 8),
setup_test(test_one_path_per_group_increasing, 8),
setup_test(test_one_path_per_group_decreasing, 8),
@@ -708,6 +952,8 @@ int test_pgpolicies(void)
setup_test(test_one_path_per_group, 1),
setup_test(test_one_path_per_group, 0),
setup_test(test_one_path_per_group, _null),
+ setup_test(test_one_path_per_group_mixed_all_marginal, 8),
+ setup_test(test_one_path_per_group_mixed_half_marginal, 8),
setup_test(test_group_by_prio_same, 8),
setup_test(test_group_by_prio_increasing, 8),
setup_test(test_group_by_prio_decreasing, 8),
@@ -718,6 +964,9 @@ int test_pgpolicies(void)
setup_test(test_group_by_prio, 1),
setup_test(test_group_by_prio, 0),
setup_test(test_group_by_prio, _null),
+ setup_test(test_group_by_prio_mixed_all_marginal, 8),
+ setup_test(test_group_by_prio_mixed_half_marginal, 8),
+ setup_test(test_group_by_prio_mixed_one_marginal, 8),
setup_test(test_group_by_node_name_same, 8),
setup_test(test_group_by_node_name_increasing, 8),
setup_test(test_group_by_node_name_3_groups, 8),
@@ -727,6 +976,8 @@ int test_pgpolicies(void)
setup_test(test_group_by_node_name, 1),
setup_test(test_group_by_node_name, 0),
setup_test(test_group_by_node_name, _null),
+ setup_test(test_group_by_node_name_2_groups_all_marginal, 8),
+ setup_test(test_group_by_node_name_2_groups_half_marginal, 8),
setup_test(test_group_by_serial_same, 8),
setup_test(test_group_by_serial_increasing, 8),
setup_test(test_group_by_serial_3_groups, 8),
@@ -736,6 +987,8 @@ int test_pgpolicies(void)
setup_test(test_group_by_serial, 1),
setup_test(test_group_by_serial, 0),
setup_test(test_group_by_serial, _null),
+ setup_test(test_group_by_serial_2_groups8_all_marginal, 8),
+ setup_test(test_group_by_serial_2_groups8_half_marginal, 8),
};
return cmocka_run_group_tests(tests, setup, NULL);
}
--
2.17.2

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,642 @@
From febf9b26fcc67d94ad06f06fc599f0ef90d84132 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 24 Jul 2019 10:04:40 -0500
Subject: [PATCH] libmultipath: add marginal_pathgroups config option
group_paths now gets passed this to determine whether to enable
marginal pathgroups. The unit tests have also been updated.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/config.h | 1 +
libmultipath/configure.c | 5 +-
libmultipath/dict.c | 3 +
libmultipath/pgpolicies.c | 5 +-
libmultipath/pgpolicies.h | 2 +-
tests/pgpolicy.c | 140 +++++++++++++++++++++++---------------
6 files changed, 98 insertions(+), 58 deletions(-)
diff --git a/libmultipath/config.h b/libmultipath/config.h
index ff2b4e86..0b978970 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -186,6 +186,7 @@ struct config {
int max_sectors_kb;
int ghost_delay;
int find_multipaths_timeout;
+ int marginal_pathgroups;
unsigned int version[3];
char * multipath_dir;
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 3c309d64..3238d485 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -297,7 +297,7 @@ int setup_map(struct multipath *mpp, char *params, int params_size,
{
struct pathgroup * pgp;
struct config *conf;
- int i, n_paths;
+ int i, n_paths, marginal_pathgroups;
/*
* don't bother if devmap size is unknown
@@ -357,6 +357,7 @@ int setup_map(struct multipath *mpp, char *params, int params_size,
select_flush_on_last_del(conf, mpp);
sysfs_set_scsi_tmo(mpp, conf->checkint);
+ marginal_pathgroups = conf->marginal_pathgroups;
pthread_cleanup_pop(1);
if (marginal_path_check_enabled(mpp)) {
@@ -387,7 +388,7 @@ int setup_map(struct multipath *mpp, char *params, int params_size,
vector_free(mpp->pg);
mpp->pg = NULL;
}
- if (group_paths(mpp))
+ if (group_paths(mpp, marginal_pathgroups))
return 1;
/*
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index c6eba0f6..b5feb884 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -1339,6 +1339,8 @@ declare_ovr_snprint(all_tg_pt, print_yes_no_undef)
declare_hw_handler(all_tg_pt, set_yes_no_undef)
declare_hw_snprint(all_tg_pt, print_yes_no_undef)
+declare_def_handler(marginal_pathgroups, set_yes_no)
+declare_def_snprint(marginal_pathgroups, print_yes_no)
static int
def_uxsock_timeout_handler(struct config *conf, vector strvec)
@@ -1710,6 +1712,7 @@ init_keywords(vector keywords)
install_keyword("find_multipaths_timeout",
&def_find_multipaths_timeout_handler,
&snprint_def_find_multipaths_timeout);
+ install_keyword("marginal_pathgroups", &def_marginal_pathgroups_handler, &snprint_def_marginal_pathgroups);
__deprecated install_keyword("default_selector", &def_selector_handler, NULL);
__deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
__deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL);
diff --git a/libmultipath/pgpolicies.c b/libmultipath/pgpolicies.c
index 6fb2d28a..8f7c6b13 100644
--- a/libmultipath/pgpolicies.c
+++ b/libmultipath/pgpolicies.c
@@ -131,7 +131,7 @@ fail:
return -1;
}
-int group_paths(struct multipath *mp)
+int group_paths(struct multipath *mp, int marginal_pathgroups)
{
vector normal, marginal;
@@ -145,7 +145,8 @@ int group_paths(struct multipath *mp)
if (!mp->pgpolicyfn)
goto fail;
- if (split_marginal_paths(mp->paths, &normal, &marginal) != 0) {
+ if (!marginal_pathgroups ||
+ split_marginal_paths(mp->paths, &normal, &marginal) != 0) {
if (mp->pgpolicyfn(mp, mp->paths) != 0)
goto fail;
} else {
diff --git a/libmultipath/pgpolicies.h b/libmultipath/pgpolicies.h
index 7532d75f..15927610 100644
--- a/libmultipath/pgpolicies.h
+++ b/libmultipath/pgpolicies.h
@@ -21,7 +21,7 @@ enum iopolicies {
int get_pgpolicy_id(char *);
int get_pgpolicy_name (char *, int, int);
-int group_paths(struct multipath *);
+int group_paths(struct multipath *, int);
/*
* policies
*/
diff --git a/tests/pgpolicy.c b/tests/pgpolicy.c
index ab09f91c..3f61b123 100644
--- a/tests/pgpolicy.c
+++ b/tests/pgpolicy.c
@@ -204,7 +204,7 @@ static void test_one_group8(void **state)
int group_size[] = {8};
mp8.pgpolicyfn = one_group;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 1);
}
@@ -215,7 +215,7 @@ static void test_one_group4(void **state)
int group_size[] = {4};
mp4.pgpolicyfn = one_group;
- assert_int_equal(group_paths(&mp4), 0);
+ assert_int_equal(group_paths(&mp4, 0), 0);
verify_pathgroups(&mp4, p4, groups, group_size, NULL, 1);
}
@@ -226,21 +226,21 @@ static void test_one_group1(void **state)
int group_size[] = {1};
mp1.pgpolicyfn = one_group;
- assert_int_equal(group_paths(&mp1), 0);
+ assert_int_equal(group_paths(&mp1, 0), 0);
verify_pathgroups(&mp1, p1, groups, group_size, NULL, 1);
}
static void test_one_group0(void **state)
{
mp0.pgpolicyfn = one_group;
- assert_int_equal(group_paths(&mp0), 0);
+ assert_int_equal(group_paths(&mp0, 0), 0);
verify_pathgroups(&mp0, NULL, NULL, NULL, NULL, 0);
}
static void test_one_group_null(void **state)
{
mp_null.pgpolicyfn = one_group;
- assert_int_equal(group_paths(&mp_null), 0);
+ assert_int_equal(group_paths(&mp_null, 0), 0);
verify_pathgroups(&mp_null, NULL, NULL, NULL, NULL, 0);
}
@@ -254,7 +254,7 @@ static void test_one_group_all_marginal8(void **state)
set_marginal(p8, marginal, 8);
mp8.pgpolicyfn = one_group;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 1), 0);
verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 1);
}
@@ -269,10 +269,23 @@ static void test_one_group_half_marginal8(void **state)
set_marginal(p8, marginal, 8);
mp8.pgpolicyfn = one_group;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 1), 0);
verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 2);
}
+static void test_one_group_ignore_marginal8(void **state)
+{
+ int marginal[] = {1,0,1,0,1,1,0,0};
+ int paths[] = {0,1,2,3,4,5,6,7};
+ int *groups[] = {paths};
+ int group_size[] = {8};
+
+ set_marginal(p8, marginal, 8);
+ mp8.pgpolicyfn = one_group;
+ assert_int_equal(group_paths(&mp8, 0), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 1);
+}
+
static void test_one_group_one_marginal8(void **state)
{
int marginal[] = {0,0,0,0,0,1,0,0};
@@ -284,7 +297,7 @@ static void test_one_group_one_marginal8(void **state)
set_marginal(p8, marginal, 8);
mp8.pgpolicyfn = one_group;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 1), 0);
verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 2);
}
@@ -296,7 +309,7 @@ static void test_one_path_per_group_same8(void **state)
int group_size[] = {1,1,1,1,1,1,1,1};
mp8.pgpolicyfn = one_path_per_group;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 8);
}
@@ -310,7 +323,7 @@ static void test_one_path_per_group_increasing8(void **state)
set_priority(p8, prio, 8);
mp8.pgpolicyfn = one_path_per_group;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 8);
}
@@ -324,7 +337,7 @@ static void test_one_path_per_group_decreasing8(void **state)
set_priority(p8, prio, 8);
mp8.pgpolicyfn = one_path_per_group;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 8);
}
@@ -338,7 +351,7 @@ static void test_one_path_per_group_mixed8(void **state)
set_priority(p8, prio, 8);
mp8.pgpolicyfn = one_path_per_group;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 8);
}
@@ -349,7 +362,7 @@ static void test_one_path_per_group4(void **state)
int group_size[] = {1,1,1,1};
mp4.pgpolicyfn = one_path_per_group;
- assert_int_equal(group_paths(&mp4), 0);
+ assert_int_equal(group_paths(&mp4, 0), 0);
verify_pathgroups(&mp4, p4, groups, group_size, NULL, 4);
}
@@ -360,21 +373,21 @@ static void test_one_path_per_group1(void **state)
int group_size[] = {1};
mp1.pgpolicyfn = one_path_per_group;
- assert_int_equal(group_paths(&mp1), 0);
+ assert_int_equal(group_paths(&mp1, 0), 0);
verify_pathgroups(&mp1, p1, groups, group_size, NULL, 1);
}
static void test_one_path_per_group0(void **state)
{
mp0.pgpolicyfn = one_path_per_group;
- assert_int_equal(group_paths(&mp0), 0);
+ assert_int_equal(group_paths(&mp0, 0), 0);
verify_pathgroups(&mp0, NULL, NULL, NULL, NULL, 0);
}
static void test_one_path_per_group_null(void **state)
{
mp_null.pgpolicyfn = one_path_per_group;
- assert_int_equal(group_paths(&mp_null), 0);
+ assert_int_equal(group_paths(&mp_null, 0), 0);
verify_pathgroups(&mp_null, NULL, NULL, NULL, NULL, 0);
}
@@ -391,7 +404,7 @@ static void test_one_path_per_group_mixed_all_marginal8(void **state)
set_priority(p8, prio, 8);
set_marginal(p8, marginal, 8);
mp8.pgpolicyfn = one_path_per_group;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 1), 0);
verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 8);
}
@@ -408,7 +421,7 @@ static void test_one_path_per_group_mixed_half_marginal8(void **state)
set_priority(p8, prio, 8);
set_marginal(p8, marginal, 8);
mp8.pgpolicyfn = one_path_per_group;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 1), 0);
verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 8);
}
@@ -419,7 +432,7 @@ static void test_group_by_prio_same8(void **state)
int group_size[] = {8};
mp8.pgpolicyfn = group_by_prio;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 1);
}
@@ -433,7 +446,7 @@ static void test_group_by_prio_increasing8(void **state)
set_priority(p8, prio, 8);
mp8.pgpolicyfn = group_by_prio;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 8);
}
@@ -447,7 +460,7 @@ static void test_group_by_prio_decreasing8(void **state)
set_priority(p8, prio, 8);
mp8.pgpolicyfn = group_by_prio;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 8);
}
@@ -466,7 +479,26 @@ static void test_group_by_prio_mixed8(void **state)
set_priority(p8, prio, 8);
mp8.pgpolicyfn = group_by_prio;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
+ verify_pathgroups(&mp8, p8, groups, group_size, NULL, 6);
+}
+
+static void test_group_by_prio_mixed_no_marginal8(void **state)
+{
+ int prio[] = {7,1,3,3,5,2,8,2};
+ int group0[] = {6};
+ int group1[] = {0};
+ int group2[] = {4};
+ int group3[] = {2,3};
+ int group4[] = {5,7};
+ int group5[] = {1};
+ int *groups[] = {group0, group1, group2, group3,
+ group4, group5};
+ int group_size[] = {1,1,1,2,2,1};
+
+ set_priority(p8, prio, 8);
+ mp8.pgpolicyfn = group_by_prio;
+ assert_int_equal(group_paths(&mp8, 1), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 6);
}
@@ -480,7 +512,7 @@ static void test_group_by_prio_2_groups8(void **state)
set_priority(p8, prio, 8);
mp8.pgpolicyfn = group_by_prio;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 2);
}
@@ -495,7 +527,7 @@ static void test_group_by_prio_mixed4(void **state)
set_priority(p4, prio, 4);
mp4.pgpolicyfn = group_by_prio;
- assert_int_equal(group_paths(&mp4), 0);
+ assert_int_equal(group_paths(&mp4, 0), 0);
verify_pathgroups(&mp4, p4, groups, group_size, NULL, 3);
}
@@ -509,7 +541,7 @@ static void test_group_by_prio_2_groups4(void **state)
set_priority(p4, prio, 4);
mp4.pgpolicyfn = group_by_prio;
- assert_int_equal(group_paths(&mp4), 0);
+ assert_int_equal(group_paths(&mp4, 0), 0);
verify_pathgroups(&mp4, p4, groups, group_size, NULL, 2);
}
@@ -520,21 +552,21 @@ static void test_group_by_prio1(void **state)
int group_size[] = {1};
mp1.pgpolicyfn = group_by_prio;
- assert_int_equal(group_paths(&mp1), 0);
+ assert_int_equal(group_paths(&mp1, 0), 0);
verify_pathgroups(&mp1, p1, groups, group_size, NULL, 1);
}
static void test_group_by_prio0(void **state)
{
mp0.pgpolicyfn = group_by_prio;
- assert_int_equal(group_paths(&mp0), 0);
+ assert_int_equal(group_paths(&mp0, 0), 0);
verify_pathgroups(&mp0, NULL, NULL, NULL, NULL, 0);
}
static void test_group_by_prio_null(void **state)
{
mp_null.pgpolicyfn = group_by_prio;
- assert_int_equal(group_paths(&mp_null), 0);
+ assert_int_equal(group_paths(&mp_null, 0), 0);
verify_pathgroups(&mp_null, NULL, NULL, NULL, NULL, 0);
}
@@ -556,7 +588,7 @@ static void test_group_by_prio_mixed_all_marginal8(void **state)
set_priority(p8, prio, 8);
set_marginal(p8, marginal, 8);
mp8.pgpolicyfn = group_by_prio;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 1), 0);
verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 6);
}
@@ -579,7 +611,7 @@ static void test_group_by_prio_mixed_half_marginal8(void **state)
set_priority(p8, prio, 8);
set_marginal(p8, marginal, 8);
mp8.pgpolicyfn = group_by_prio;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 1), 0);
verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 7);
}
@@ -602,7 +634,7 @@ static void test_group_by_prio_mixed_one_marginal8(void **state)
set_priority(p8, prio, 8);
set_marginal(p8, marginal, 8);
mp8.pgpolicyfn = group_by_prio;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 1), 0);
verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 7);
}
@@ -615,7 +647,7 @@ static void test_group_by_node_name_same8(void **state)
set_tgt_node_name(p8, node_name, 8);
mp8.pgpolicyfn = group_by_node_name;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 1);
}
@@ -631,7 +663,7 @@ static void test_group_by_node_name_increasing8(void **state)
set_priority(p8, prio, 8);
set_tgt_node_name(p8, node_name, 8);
mp8.pgpolicyfn = group_by_node_name;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 8);
}
@@ -648,7 +680,7 @@ static void test_group_by_node_name_3_groups8(void **state)
set_priority(p8, prio, 8);
set_tgt_node_name(p8, node_name, 8);
mp8.pgpolicyfn = group_by_node_name;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 3);
}
@@ -664,7 +696,7 @@ static void test_group_by_node_name_2_groups8(void **state)
set_priority(p8, prio, 8);
set_tgt_node_name(p8, node_name, 8);
mp8.pgpolicyfn = group_by_node_name;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 2);
}
@@ -681,7 +713,7 @@ static void test_group_by_node_name_3_groups4(void **state)
set_priority(p4, prio, 4);
set_tgt_node_name(p4, node_name, 4);
mp4.pgpolicyfn = group_by_node_name;
- assert_int_equal(group_paths(&mp4), 0);
+ assert_int_equal(group_paths(&mp4, 0), 0);
verify_pathgroups(&mp4, p4, groups, group_size, NULL, 3);
}
@@ -697,7 +729,7 @@ static void test_group_by_node_name_2_groups4(void **state)
set_priority(p4, prio, 4);
set_tgt_node_name(p4, node_name, 4);
mp4.pgpolicyfn = group_by_node_name;
- assert_int_equal(group_paths(&mp4), 0);
+ assert_int_equal(group_paths(&mp4, 0), 0);
verify_pathgroups(&mp4, p4, groups, group_size, NULL, 2);
}
@@ -710,21 +742,21 @@ static void test_group_by_node_name1(void **state)
set_tgt_node_name(p1, node_name, 1);
mp1.pgpolicyfn = group_by_node_name;
- assert_int_equal(group_paths(&mp1), 0);
+ assert_int_equal(group_paths(&mp1,0), 0);
verify_pathgroups(&mp1, p1, groups, group_size, NULL, 1);
}
static void test_group_by_node_name0(void **state)
{
mp0.pgpolicyfn = group_by_node_name;
- assert_int_equal(group_paths(&mp0), 0);
+ assert_int_equal(group_paths(&mp0, 0), 0);
verify_pathgroups(&mp0, NULL, NULL, NULL, NULL, 0);
}
static void test_group_by_node_name_null(void **state)
{
mp_null.pgpolicyfn = group_by_node_name;
- assert_int_equal(group_paths(&mp_null), 0);
+ assert_int_equal(group_paths(&mp_null, 0), 0);
verify_pathgroups(&mp_null, NULL, NULL, NULL, NULL, 0);
}
@@ -743,7 +775,7 @@ static void test_group_by_node_name_2_groups_all_marginal8(void **state)
set_marginal(p8, marginal, 8);
set_tgt_node_name(p8, node_name, 8);
mp8.pgpolicyfn = group_by_node_name;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 1), 0);
verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 2);
}
@@ -764,7 +796,7 @@ static void test_group_by_node_name_2_groups_half_marginal8(void **state)
set_marginal(p8, marginal, 8);
set_tgt_node_name(p8, node_name, 8);
mp8.pgpolicyfn = group_by_node_name;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 1), 0);
verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 4);
}
@@ -777,7 +809,7 @@ static void test_group_by_serial_same8(void **state)
set_serial(p8, serial, 8);
mp8.pgpolicyfn = group_by_serial;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 1);
}
@@ -793,7 +825,7 @@ static void test_group_by_serial_increasing8(void **state)
set_priority(p8, prio, 8);
set_serial(p8, serial, 8);
mp8.pgpolicyfn = group_by_serial;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 8);
}
@@ -810,7 +842,7 @@ static void test_group_by_serial_3_groups8(void **state)
set_priority(p8, prio, 8);
set_serial(p8, serial, 8);
mp8.pgpolicyfn = group_by_serial;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 3);
}
@@ -826,7 +858,7 @@ static void test_group_by_serial_2_groups8(void **state)
set_priority(p8, prio, 8);
set_serial(p8, serial, 8);
mp8.pgpolicyfn = group_by_serial;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 0), 0);
verify_pathgroups(&mp8, p8, groups, group_size, NULL, 2);
}
@@ -843,7 +875,7 @@ static void test_group_by_serial_3_groups4(void **state)
set_priority(p4, prio, 4);
set_serial(p4, serial, 4);
mp4.pgpolicyfn = group_by_serial;
- assert_int_equal(group_paths(&mp4), 0);
+ assert_int_equal(group_paths(&mp4, 0), 0);
verify_pathgroups(&mp4, p4, groups, group_size, NULL, 3);
}
@@ -859,7 +891,7 @@ static void test_group_by_serial_2_groups4(void **state)
set_priority(p4, prio, 4);
set_serial(p4, serial, 4);
mp4.pgpolicyfn = group_by_serial;
- assert_int_equal(group_paths(&mp4), 0);
+ assert_int_equal(group_paths(&mp4, 0), 0);
verify_pathgroups(&mp4, p4, groups, group_size, NULL, 2);
}
@@ -872,21 +904,21 @@ static void test_group_by_serial1(void **state)
set_serial(p1, serial, 1);
mp1.pgpolicyfn = group_by_serial;
- assert_int_equal(group_paths(&mp1), 0);
+ assert_int_equal(group_paths(&mp1, 0), 0);
verify_pathgroups(&mp1, p1, groups, group_size, NULL, 1);
}
static void test_group_by_serial0(void **state)
{
mp0.pgpolicyfn = group_by_serial;
- assert_int_equal(group_paths(&mp0), 0);
+ assert_int_equal(group_paths(&mp0, 0), 0);
verify_pathgroups(&mp0, NULL, NULL, NULL, NULL, 0);
}
static void test_group_by_serial_null(void **state)
{
mp_null.pgpolicyfn = group_by_serial;
- assert_int_equal(group_paths(&mp_null), 0);
+ assert_int_equal(group_paths(&mp_null, 0), 0);
verify_pathgroups(&mp_null, NULL, NULL, NULL, NULL, 0);
}
@@ -905,7 +937,7 @@ static void test_group_by_serial_2_groups8_all_marginal8(void **state)
set_serial(p8, serial, 8);
set_marginal(p8, marginal, 8);
mp8.pgpolicyfn = group_by_serial;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 1), 0);
verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 2);
}
@@ -926,7 +958,7 @@ static void test_group_by_serial_2_groups8_half_marginal8(void **state)
set_serial(p8, serial, 8);
set_marginal(p8, marginal, 8);
mp8.pgpolicyfn = group_by_serial;
- assert_int_equal(group_paths(&mp8), 0);
+ assert_int_equal(group_paths(&mp8, 1), 0);
verify_pathgroups(&mp8, p8, groups, group_size, group_marginal, 4);
}
@@ -943,6 +975,7 @@ int test_pgpolicies(void)
setup_test(test_one_group, _null),
setup_test(test_one_group_all_marginal, 8),
setup_test(test_one_group_half_marginal, 8),
+ setup_test(test_one_group_ignore_marginal, 8),
setup_test(test_one_group_one_marginal, 8),
setup_test(test_one_path_per_group_same, 8),
setup_test(test_one_path_per_group_increasing, 8),
@@ -958,6 +991,7 @@ int test_pgpolicies(void)
setup_test(test_group_by_prio_increasing, 8),
setup_test(test_group_by_prio_decreasing, 8),
setup_test(test_group_by_prio_mixed, 8),
+ setup_test(test_group_by_prio_mixed_no_marginal, 8),
setup_test(test_group_by_prio_2_groups, 8),
setup_test(test_group_by_prio_mixed, 4),
setup_test(test_group_by_prio_2_groups, 4),
--
2.17.2

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,381 @@
From ef0b288867f20b4a1a532d693ac7b64e088b235a Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 30 Jul 2019 11:09:07 -0500
Subject: [PATCH] libmutipath: deprecate delay_*_checks
The delay_checks shaky paths detection method works the same way as the
san_path_err method, but not as well, with less configurability, and
with the code spread all over check_path(). The only real difference is
that marks the path as marginal for a certain number of path checks
instead of for a specific time. This patch deprecates the delay_checks
method and maps it to the the san_path_err method.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/configure.c | 18 +-------
libmultipath/propsel.c | 89 ++++++++++++++++++++++++++++----------
libmultipath/propsel.h | 3 +-
libmultipath/structs.h | 10 -----
multipath/multipath.conf.5 | 40 +++++++++--------
multipathd/main.c | 34 ++-------------
6 files changed, 96 insertions(+), 98 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 3238d485..9897cc37 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -342,8 +342,6 @@ int setup_map(struct multipath *mpp, char *params, int params_size,
select_dev_loss(conf, mpp);
select_reservation_key(conf, mpp);
select_deferred_remove(conf, mpp);
- select_delay_watch_checks(conf, mpp);
- select_delay_wait_checks(conf, mpp);
select_marginal_path_err_sample_time(conf, mpp);
select_marginal_path_err_rate_threshold(conf, mpp);
select_marginal_path_err_recheck_gap_time(conf, mpp);
@@ -351,6 +349,7 @@ int setup_map(struct multipath *mpp, char *params, int params_size,
select_san_path_err_threshold(conf, mpp);
select_san_path_err_forget_rate(conf, mpp);
select_san_path_err_recovery_time(conf, mpp);
+ select_delay_checks(conf, mpp);
select_skip_kpartx(conf, mpp);
select_max_sectors_kb(conf, mpp);
select_ghost_delay(conf, mpp);
@@ -360,21 +359,8 @@ int setup_map(struct multipath *mpp, char *params, int params_size,
marginal_pathgroups = conf->marginal_pathgroups;
pthread_cleanup_pop(1);
- if (marginal_path_check_enabled(mpp)) {
- if (delay_check_enabled(mpp)) {
- condlog(1, "%s: WARNING: both marginal_path and delay_checks error detection selected",
- mpp->alias);
- condlog(0, "%s: unexpected behavior may occur!",
- mpp->alias);
- }
+ if (marginal_path_check_enabled(mpp))
start_io_err_stat_thread(vecs);
- }
- if (san_path_check_enabled(mpp) && delay_check_enabled(mpp)) {
- condlog(1, "%s: WARNING: both san_path_err and delay_checks error detection selected",
- mpp->alias);
- condlog(0, "%s: unexpected behavior may occur!",
- mpp->alias);
- }
n_paths = VECTOR_SIZE(mpp->paths);
/*
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
index 6af2513d..27e8d68a 100644
--- a/libmultipath/propsel.c
+++ b/libmultipath/propsel.c
@@ -85,6 +85,10 @@ static const char autodetect_origin[] =
"(setting: storage device autodetected)";
static const char marginal_path_origin[] =
"(setting: implied by marginal_path check)";
+static const char delay_watch_origin[] =
+ "(setting: implied by delay_watch_checks)";
+static const char delay_wait_origin[] =
+ "(setting: implied by delay_wait_checks)";
#define do_default(dest, value) \
do { \
@@ -877,39 +881,80 @@ out:
return 0;
}
-int select_delay_watch_checks(struct config *conf, struct multipath *mp)
+static inline int san_path_check_options_set(const struct multipath *mp)
{
- const char *origin;
+ return mp->san_path_err_threshold > 0 ||
+ mp->san_path_err_forget_rate > 0 ||
+ mp->san_path_err_recovery_time > 0;
+}
+
+static int
+use_delay_watch_checks(struct config *conf, struct multipath *mp)
+{
+ int value = NU_UNDEF;
+ const char *origin = default_origin;
char buff[12];
- mp_set_mpe(delay_watch_checks);
- mp_set_ovr(delay_watch_checks);
- mp_set_hwe(delay_watch_checks);
- mp_set_conf(delay_watch_checks);
- mp_set_default(delay_watch_checks, DEFAULT_DELAY_CHECKS);
+ do_set(delay_watch_checks, mp->mpe, value, multipaths_origin);
+ do_set(delay_watch_checks, conf->overrides, value, overrides_origin);
+ do_set_from_hwe(delay_watch_checks, mp, value, hwe_origin);
+ do_set(delay_watch_checks, conf, value, conf_origin);
out:
- if (print_off_int_undef(buff, 12, mp->delay_watch_checks) != 0)
- condlog(3, "%s: delay_watch_checks = %s %s",
- mp->alias, buff, origin);
- return 0;
+ if (print_off_int_undef(buff, 12, value) != 0)
+ condlog(3, "%s: delay_watch_checks = %s %s", mp->alias, buff,
+ origin);
+ return value;
}
-int select_delay_wait_checks(struct config *conf, struct multipath *mp)
+static int
+use_delay_wait_checks(struct config *conf, struct multipath *mp)
{
- const char *origin;
+ int value = NU_UNDEF;
+ const char *origin = default_origin;
char buff[12];
- mp_set_mpe(delay_wait_checks);
- mp_set_ovr(delay_wait_checks);
- mp_set_hwe(delay_wait_checks);
- mp_set_conf(delay_wait_checks);
- mp_set_default(delay_wait_checks, DEFAULT_DELAY_CHECKS);
+ do_set(delay_wait_checks, mp->mpe, value, multipaths_origin);
+ do_set(delay_wait_checks, conf->overrides, value, overrides_origin);
+ do_set_from_hwe(delay_wait_checks, mp, value, hwe_origin);
+ do_set(delay_wait_checks, conf, value, conf_origin);
out:
- if (print_off_int_undef(buff, 12, mp->delay_wait_checks) != 0)
- condlog(3, "%s: delay_wait_checks = %s %s",
- mp->alias, buff, origin);
- return 0;
+ if (print_off_int_undef(buff, 12, value) != 0)
+ condlog(3, "%s: delay_wait_checks = %s %s", mp->alias, buff,
+ origin);
+ return value;
+}
+
+int select_delay_checks(struct config *conf, struct multipath *mp)
+{
+ int watch_checks, wait_checks;
+ char buff[12];
+ watch_checks = use_delay_watch_checks(conf, mp);
+ wait_checks = use_delay_wait_checks(conf, mp);
+ if (watch_checks <= 0 && wait_checks <= 0)
+ return 0;
+ if (san_path_check_options_set(mp)) {
+ condlog(3, "%s: both marginal_path and delay_checks error detection options selected", mp->alias);
+ condlog(3, "%s: ignoring delay_checks options", mp->alias);
+ return 0;
+ }
+ mp->san_path_err_threshold = 1;
+ condlog(3, "%s: san_path_err_threshold = 1 %s", mp->alias,
+ (watch_checks > 0)? delay_watch_origin : delay_wait_origin);
+ if (watch_checks > 0) {
+ mp->san_path_err_forget_rate = watch_checks;
+ print_off_int_undef(buff, 12, mp->san_path_err_forget_rate);
+ condlog(3, "%s: san_path_err_forget_rate = %s %s", mp->alias,
+ buff, delay_watch_origin);
+ }
+ if (wait_checks > 0) {
+ mp->san_path_err_recovery_time = wait_checks *
+ conf->max_checkint;
+ print_off_int_undef(buff, 12, mp->san_path_err_recovery_time);
+ condlog(3, "%s: san_path_err_recovery_time = %s %s", mp->alias,
+ buff, delay_wait_origin);
+ }
+ return 0;
}
static int san_path_deprecated_warned;
diff --git a/libmultipath/propsel.h b/libmultipath/propsel.h
index b352c16a..ddfd6262 100644
--- a/libmultipath/propsel.h
+++ b/libmultipath/propsel.h
@@ -22,8 +22,7 @@ int select_retain_hwhandler (struct config *conf, struct multipath * mp);
int select_detect_prio(struct config *conf, struct path * pp);
int select_detect_checker(struct config *conf, struct path * pp);
int select_deferred_remove(struct config *conf, struct multipath *mp);
-int select_delay_watch_checks (struct config *conf, struct multipath * mp);
-int select_delay_wait_checks (struct config *conf, struct multipath * mp);
+int select_delay_checks(struct config *conf, struct multipath * mp);
int select_skip_kpartx (struct config *conf, struct multipath * mp);
int select_max_sectors_kb (struct config *conf, struct multipath * mp);
int select_san_path_err_forget_rate(struct config *conf, struct multipath *mp);
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index a8b9d325..a3adf906 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -268,8 +268,6 @@ struct path {
int pgindex;
int detect_prio;
int detect_checker;
- int watch_checks;
- int wait_checks;
int tpgs;
char * uid_attribute;
char * getuid;
@@ -321,8 +319,6 @@ struct multipath {
int fast_io_fail;
int retain_hwhandler;
int deferred_remove;
- int delay_watch_checks;
- int delay_wait_checks;
int san_path_err_threshold;
int san_path_err_forget_rate;
int san_path_err_recovery_time;
@@ -393,12 +389,6 @@ static inline int san_path_check_enabled(const struct multipath *mpp)
mpp->san_path_err_recovery_time > 0;
}
-static inline int delay_check_enabled(const struct multipath *mpp)
-{
- return mpp->delay_watch_checks != NU_NO ||
- mpp->delay_wait_checks != NU_NO;
-}
-
struct pathgroup {
long id;
int status;
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index f7d21b4c..08297a41 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1013,10 +1013,12 @@ The default is: \fBno\fR
.
.TP
.B delay_watch_checks
-If set to a value greater than 0, multipathd will watch paths that have
-recently become valid for this many checks. If they fail again while they are
-being watched, when they next become valid, they will not be used until they
-have stayed up for \fIdelay_wait_checks\fR checks. See "Shaky paths detection" below.
+This option is \fBdeprecated\fR, and mapped to \fIsan_path_err_forget_rate\fR.
+If this is set to a value greater than 0 and no \fIsan_path_err\fR options
+are set, \fIsan_path_err_forget_rate\fR will be set to the value of
+\fIdelay_watch_checks\fR and \fIsan_path_err_threshold\fR will be set to 1.
+See the \fIsan_path_err_forget_rate\fR and \fIsan_path_err_threshold\fR
+options, and "Shaky paths detection" below for more information.
.RS
.TP
The default is: \fBno\fR
@@ -1025,10 +1027,14 @@ The default is: \fBno\fR
.
.TP
.B delay_wait_checks
-If set to a value greater than 0, when a device that has recently come back
-online fails again within \fIdelay_watch_checks\fR checks, the next time it
-comes back online, it will marked and delayed, and not used until it has passed
-\fIdelay_wait_checks\fR checks. See "Shaky paths detection" below.
+This option is \fBdeprecated\fR, and mapped to \fIsan_path_err_recovery_time\fR.
+If this is set to a value greater than 0 and no \fIsan_path_err\fR options
+are set, \fIsan_path_err_recovery_time\fR will be set to the value of
+\fIdelay_wait_checks\fR times \fImax_polling_interval\fR. This will give
+approximately the same wait time as delay_wait_checks previously did.
+Also, \fIsan_path_err_threshold\fR will be set to 1. See the
+\fIsan_path_err_recovery_time\fR and \fIsan_path_err_threshold\fR
+options, and "Shaky paths detection" below for more information.
.RS
.TP
The default is: \fBno\fR
@@ -1689,13 +1695,10 @@ if the healthy state appears to be stable. The logic of determining
differs between the three methods.
.TP 8
.B \(dqdelay_checks\(dq failure tracking
-If a path fails again within a
-\fIdelay_watch_checks\fR interval after a failure, don't
-reinstate it until it passes a \fIdelay_wait_checks\fR interval
-in always good status.
-The intervals are measured in \(dqticks\(dq, i.e. the
-time between path checks by multipathd, which is variable and controlled by the
-\fIpolling_interval\fR and \fImax_polling_interval\fR parameters.
+This method is \fBdeprecated\fR and mapped to the \(dqsan_path_err\(dq method.
+See the \fIdelay_watch_checks\fR and \fIdelay_wait_checks\fR options above
+for more information.
+
.TP
.B \(dqmarginal_path\(dq failure tracking
If a second failure event (good->bad transition) occurs within
@@ -1712,12 +1715,13 @@ in seconds.
.B \(dqsan_path_err\(dq failure tracking
multipathd counts path failures for each path. Once the number of failures
exceeds the value given by \fIsan_path_err_threshold\fR, the path is not
-reinstated for \fIsan_path_err_recovery_time\fR ticks. While counting
+reinstated for \fIsan_path_err_recovery_time\fR seconds. While counting
failures, multipathd \(dqforgets\(dq one past failure every
\(dqsan_path_err_forget_rate\(dq ticks; thus if errors don't occur more
often then once in the forget rate interval, the failure count doesn't
-increase and the threshold is never reached. As for the \fIdelay_xy\fR method,
-intervals are measured in \(dqticks\(dq.
+increase and the threshold is never reached. Ticks are the time between
+path checks by multipathd, which is variable and controlled by the
+\fIpolling_interval\fR and \fImax_polling_interval\fR parameters.
.
.RS 8
.LP
diff --git a/multipathd/main.c b/multipathd/main.c
index 7db15736..dca2214c 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -2122,16 +2122,6 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
return 1;
}
- if ((newstate == PATH_UP || newstate == PATH_GHOST) &&
- pp->wait_checks > 0) {
- if (pp->mpp->nr_active > 0) {
- pp->state = PATH_DELAYED;
- pp->wait_checks--;
- return 1;
- } else
- pp->wait_checks = 0;
- }
-
/*
* don't reinstate failed path, if its in stand-by
* and if target supports only implicit tpgs mode.
@@ -2162,19 +2152,10 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
* proactively fail path in the DM
*/
if (oldstate == PATH_UP ||
- oldstate == PATH_GHOST) {
+ oldstate == PATH_GHOST)
fail_path(pp, 1);
- if (pp->mpp->delay_wait_checks > 0 &&
- pp->watch_checks > 0) {
- pp->wait_checks = pp->mpp->delay_wait_checks;
- pp->watch_checks = 0;
- }
- } else {
+ else
fail_path(pp, 0);
- if (pp->wait_checks > 0)
- pp->wait_checks =
- pp->mpp->delay_wait_checks;
- }
/*
* cancel scheduled failback
@@ -2200,15 +2181,10 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
* reinstate this path
*/
if (oldstate != PATH_UP &&
- oldstate != PATH_GHOST) {
- if (pp->mpp->delay_watch_checks > 0)
- pp->watch_checks = pp->mpp->delay_watch_checks;
+ oldstate != PATH_GHOST)
add_active = 1;
- } else {
- if (pp->watch_checks > 0)
- pp->watch_checks--;
+ else
add_active = 0;
- }
if (!disable_reinstate && reinstate_path(pp, add_active)) {
condlog(3, "%s: reload map", pp->dev);
ev_add_path(pp, vecs, 1);
@@ -2253,8 +2229,6 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
condlog(4, "%s: delay next check %is",
pp->dev_t, pp->checkint);
}
- if (pp->watch_checks > 0)
- pp->watch_checks--;
pp->tick = pp->checkint;
}
}
--
2.17.2

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,111 @@
From d43ffc1112c0385737f88bab1c884e4ff4c316f5 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 31 Jul 2019 18:11:41 -0500
Subject: [PATCH] multipathd: use marginal_pathgroups
This commit makes the marginal_pathgroups option work with the
existing methods for determining marginal paths. It also merges the
code for the marginal_path and sand_path_err methods. This has the
side effect of making the marginal_path code set a marginal path's state
to "delayed" instead of "shaky" like it previously did.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/main.c | 53 +++++++++++++++++++++++++++++++++--------------
1 file changed, 38 insertions(+), 15 deletions(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index dca2214c..04b2b56a 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1960,6 +1960,18 @@ reinstate_path:
return 0;
}
+static int
+should_skip_path(struct path *pp){
+ if (marginal_path_check_enabled(pp->mpp)) {
+ if (pp->io_err_disable_reinstate && need_io_err_check(pp))
+ return 1;
+ } else if (san_path_check_enabled(pp->mpp)) {
+ if (check_path_reinstate_state(pp))
+ return 1;
+ }
+ return 0;
+}
+
/*
* Returns '1' if the path has been checked, '-1' if it was blacklisted
* and '0' otherwise
@@ -1975,6 +1987,7 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
int oldchkrstate = pp->chkrstate;
int retrigger_tries, checkint, max_checkint, verbosity;
struct config *conf;
+ int marginal_pathgroups, marginal_changed = 0;
int ret;
if ((pp->initialized == INIT_OK ||
@@ -1991,6 +2004,7 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
checkint = conf->checkint;
max_checkint = conf->max_checkint;
verbosity = conf->verbosity;
+ marginal_pathgroups = conf->marginal_pathgroups;
put_multipath_config(conf);
if (pp->checkint == CHECKINT_UNDEF) {
@@ -2106,20 +2120,27 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
set_no_path_retry(pp->mpp);
if ((newstate == PATH_UP || newstate == PATH_GHOST) &&
- check_path_reinstate_state(pp)) {
- pp->state = PATH_DELAYED;
- return 1;
- }
-
- if ((newstate == PATH_UP || newstate == PATH_GHOST) &&
- pp->io_err_disable_reinstate && need_io_err_check(pp)) {
- pp->state = PATH_SHAKY;
- /*
- * to reschedule as soon as possible,so that this path can
- * be recoverd in time
- */
- pp->tick = 1;
- return 1;
+ (san_path_check_enabled(pp->mpp) ||
+ marginal_path_check_enabled(pp->mpp))) {
+ int was_marginal = pp->marginal;
+ if (should_skip_path(pp)) {
+ if (!marginal_pathgroups) {
+ if (marginal_path_check_enabled(pp->mpp))
+ /* to reschedule as soon as possible,
+ * so that this path can be recovered
+ * in time */
+ pp->tick = 1;
+ pp->state = PATH_DELAYED;
+ return 1;
+ }
+ if (!was_marginal) {
+ pp->marginal = 1;
+ marginal_changed = 1;
+ }
+ } else if (marginal_pathgroups && was_marginal) {
+ pp->marginal = 0;
+ marginal_changed = 1;
+ }
}
/*
@@ -2258,7 +2279,9 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
*/
condlog(4, "path prio refresh");
- if (update_prio(pp, new_path_up) &&
+ if (marginal_changed)
+ update_path_groups(pp->mpp, vecs, 1);
+ else if (update_prio(pp, new_path_up) &&
(pp->mpp->pgpolicyfn == (pgpolicyfn *)group_by_prio) &&
pp->mpp->pgfailback == -FAILBACK_IMMEDIATE)
update_path_groups(pp->mpp, vecs, !new_path_up);
--
2.17.2

View file

@ -0,0 +1,99 @@
From 0992a545413cf2bcbde18c90f04b9e5b1077fd62 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 1 Aug 2019 16:29:41 -0500
Subject: [PATCH] multipath: update man pages
Add documentation for the marginal_pathgroups option and the
(un)setmarginal commands.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/multipath.conf.5 | 34 ++++++++++++++++++++++++++++++----
multipathd/multipathd.8 | 19 +++++++++++++++++++
2 files changed, 49 insertions(+), 4 deletions(-)
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 08297a41..ac8eadd0 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1042,6 +1042,28 @@ The default is: \fBno\fR
.
.
.TP
+.B marginal_pathgroups
+If set to \fIno\fR, the \fIdelay_*_checks\fR, \fImarginal_path_*\fR, and
+\fIsan_path_err_*\fR options will keep marginal, or \(dqshaky\(dq, paths from
+being reinstated until they have been monitored for some time. This can cause
+situations where all non-marginal paths are down, and no paths are usable
+until multipathd detects this and reinstates a marginal path. If the multipath
+device is not configured to queue IO in this case, it can cause IO errors to
+occur, even though there are marginal paths available. However, if this
+option is set to \fIyes\fR, when one of the marginal path detecting methods
+determines that a path is marginal, it will be reinstated and placed in a
+seperate pathgroup that will only be used after all the non-marginal pathgroups
+have been tried first. This prevents the possibility of IO errors occuring
+while marginal paths are still usable. After the path has been monitored
+for the configured time, and is declared healthy, it will be returned to its
+normal pathgroup. See "Shaky paths detection" below for more information.
+.RS
+.TP
+The default is: \fBno\fR
+.RE
+.
+.
+.TP
.B find_multipaths
This option controls whether multipath and multipathd try to create multipath
maps over non-blacklisted devices they encounter. This matters a) when a device is
@@ -1689,10 +1711,14 @@ events. \fImultipathd\fR supports three different methods for detecting this
situation and dealing with it. All methods share the same basic mode of
operation: If a path is found to be \(dqshaky\(dq or \(dqflipping\(dq,
and appears to be in healthy status, it is not reinstated (put back to use)
-immediately. Instead, it is watched for some time, and only reinstated
-if the healthy state appears to be stable. The logic of determining
-\(dqshaky\(dq condition, as well as the logic when to reinstate,
-differs between the three methods.
+immediately. Instead, it is placed in the \(dqdelayed\(dq state and watched
+for some time, and only reinstated if the healthy state appears to be stable.
+If the \fImarginal_pathgroups\fR option is set, the path will reinstated
+immediately, but placed in a special pathgroup for marginal paths. Marginal
+pathgroups will not be used until all other pathgroups have been tried. At the
+time when the path would normally be reinstated, it will be returned to its
+normal pathgroup. The logic of determining \(dqshaky\(dq condition, as well as
+the logic when to reinstate, differs between the three methods.
.TP 8
.B \(dqdelay_checks\(dq failure tracking
This method is \fBdeprecated\fR and mapped to the \(dqsan_path_err\(dq method.
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8
index edac7a92..048a838d 100644
--- a/multipathd/multipathd.8
+++ b/multipathd/multipathd.8
@@ -277,6 +277,25 @@ Remove the persistent reservation key associated with $map from the
\fIreservation_key\fR is set to \fBfile\fR in \fI/etc/multipath.conf\fR.
.
.TP
+.B path $path setmarginal
+move $path to a marginal pathgroup. The path will remain in the marginal
+path group until \fIunsetmarginal\fR is called. This command will only
+work if \fImarginal_pathgroups\fR is enabled and there is no Shaky paths
+detection method configured (see the multipath.conf man page for details).
+.
+.TP
+.B path $path unsetmarginal
+return marginal path $path to its normal pathgroup. This command will only
+work if \fImarginal_pathgroups\fR is enabled and there is no Shaky paths
+detection method configured (see the multipath.conf man page for details).
+.
+.TP
+.B map $map unsetmarginal
+return all marginal paths in $map to their normal pathgroups. This command
+will only work if \fImarginal_pathgroups\fR is enabled and there is no Shaky
+paths detection method configured (see the multipath.conf man page for details).
+.
+.TP
.B quit|exit
End interactive session.
.
--
2.17.2

View file

@ -0,0 +1,230 @@
From 959cf306b6ad0bbfc73e7745161ef4edfa821a47 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Thu, 15 Aug 2019 14:46:54 +0000
Subject: [PATCH] multipath.conf: add "enable_foreign" parameter
This new configuration parameter can be used to selectively
enable foreign libraries. The value is a regular expression,
against which foreign library names such as "nvme" are matched.
By setting this to a value that matches no foreign library
(e.g. "^$" or "NONE"), foreign code is completely disabled.
By default, all available foreign libraries are loaded.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/config.h | 1 +
libmultipath/defaults.h | 2 ++
libmultipath/dict.c | 6 +++++
libmultipath/foreign.c | 53 +++++++++++++++++++++++++++++++++++++----
libmultipath/foreign.h | 3 ++-
multipath/main.c | 2 +-
multipathd/main.c | 2 +-
7 files changed, 62 insertions(+), 7 deletions(-)
diff --git a/libmultipath/config.h b/libmultipath/config.h
index 0b978970..ffec3103 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -225,6 +225,7 @@ struct config {
vector elist_device;
vector elist_property;
vector elist_protocol;
+ char *enable_foreign;
};
extern struct udev * udev;
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index decc9335..4dfe007c 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -48,6 +48,8 @@
#define DEFAULT_FIND_MULTIPATHS_TIMEOUT -10
#define DEFAULT_UNKNOWN_FIND_MULTIPATHS_TIMEOUT 1
#define DEFAULT_ALL_TG_PT ALL_TG_PT_OFF
+/* Enable all foreign libraries by default */
+#define DEFAULT_ENABLE_FOREIGN ""
#define CHECKINT_UNDEF (~0U)
#define DEFAULT_CHECKINT 5
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index b5feb884..1b3d0373 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -610,6 +610,10 @@ declare_def_handler(find_multipaths_timeout, set_int)
declare_def_snprint_defint(find_multipaths_timeout, print_int,
DEFAULT_FIND_MULTIPATHS_TIMEOUT)
+declare_def_handler(enable_foreign, set_str)
+declare_def_snprint_defstr(enable_foreign, print_str,
+ DEFAULT_ENABLE_FOREIGN)
+
static int
def_config_dir_handler(struct config *conf, vector strvec)
{
@@ -1713,6 +1717,8 @@ init_keywords(vector keywords)
&def_find_multipaths_timeout_handler,
&snprint_def_find_multipaths_timeout);
install_keyword("marginal_pathgroups", &def_marginal_pathgroups_handler, &snprint_def_marginal_pathgroups);
+ install_keyword("enable_foreign", &def_enable_foreign_handler,
+ &snprint_def_enable_foreign);
__deprecated install_keyword("default_selector", &def_selector_handler, NULL);
__deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
__deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL);
diff --git a/libmultipath/foreign.c b/libmultipath/foreign.c
index 48e8d247..4b34e141 100644
--- a/libmultipath/foreign.c
+++ b/libmultipath/foreign.c
@@ -16,6 +16,7 @@
*/
#include <sys/sysmacros.h>
+#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -25,6 +26,7 @@
#include <fnmatch.h>
#include <dlfcn.h>
#include <libudev.h>
+#include <regex.h>
#include "vector.h"
#include "debug.h"
#include "util.h"
@@ -111,17 +113,45 @@ static int select_foreign_libs(const struct dirent *di)
return fnmatch(foreign_pattern, di->d_name, FNM_FILE_NAME) == 0;
}
-static int _init_foreign(const char *multipath_dir)
+static void free_pre(void *arg)
+{
+ regex_t **pre = arg;
+
+ if (pre != NULL && *pre != NULL) {
+ regfree(*pre);
+ free(*pre);
+ *pre = NULL;
+ }
+}
+
+static int _init_foreign(const char *multipath_dir, const char *enable)
{
char pathbuf[PATH_MAX];
struct dirent **di;
struct scandir_result sr;
int r, i;
+ regex_t *enable_re = NULL;
foreigns = vector_alloc();
if (foreigns == NULL)
return -ENOMEM;
+ pthread_cleanup_push(free_pre, &enable_re);
+ enable_re = calloc(1, sizeof(*enable_re));
+ if (enable_re) {
+ const char *str = enable ? enable : DEFAULT_ENABLE_FOREIGN;
+
+ r = regcomp(enable_re, str, REG_EXTENDED|REG_NOSUB);
+ if (r != 0) {
+ char errbuf[64];
+
+ (void)regerror(r, enable_re, errbuf, sizeof(errbuf));
+ condlog (2, "%s: error compiling enable_foreign = \"%s\": \"%s\"",
+ __func__, str, errbuf);
+ free_pre(&enable_re);
+ }
+ }
+
r = scandir(multipath_dir, &di, select_foreign_libs, alphasort);
if (r == 0) {
@@ -163,6 +193,20 @@ static int _init_foreign(const char *multipath_dir)
memset(fgn, 0, sizeof(*fgn));
strlcpy((char*)fgn + offsetof(struct foreign, name), c, namesz);
+ if (enable_re != NULL) {
+ int ret = regexec(enable_re, fgn->name, 0, NULL, 0);
+
+ if (ret == REG_NOMATCH) {
+ condlog(3, "%s: foreign library \"%s\" is not enabled",
+ __func__, fgn->name);
+ free(fgn);
+ continue;
+ } else if (ret != 0)
+ /* assume it matches */
+ condlog(2, "%s: error %d in regexec() for %s",
+ __func__, ret, fgn->name);
+ }
+
snprintf(pathbuf, sizeof(pathbuf), "%s/%s", multipath_dir, fn);
fgn->handle = dlopen(pathbuf, RTLD_NOW|RTLD_LOCAL);
msg = dlerror();
@@ -205,11 +249,12 @@ static int _init_foreign(const char *multipath_dir)
dl_err:
free_foreign(fgn);
}
- pthread_cleanup_pop(1);
+ pthread_cleanup_pop(1); /* free_scandir_result */
+ pthread_cleanup_pop(1); /* free_pre */
return 0;
}
-int init_foreign(const char *multipath_dir)
+int init_foreign(const char *multipath_dir, const char *enable)
{
int ret;
@@ -222,7 +267,7 @@ int init_foreign(const char *multipath_dir)
}
pthread_cleanup_push(unlock_foreigns, NULL);
- ret = _init_foreign(multipath_dir);
+ ret = _init_foreign(multipath_dir, enable);
pthread_cleanup_pop(1);
return ret;
diff --git a/libmultipath/foreign.h b/libmultipath/foreign.h
index 697f12f8..acd33601 100644
--- a/libmultipath/foreign.h
+++ b/libmultipath/foreign.h
@@ -195,9 +195,10 @@ struct foreign {
* init_foreign(dir)
* load and initialize foreign multipath libraries in dir (libforeign-*.so).
* @param dir: directory to search
+ * @param enable: regex to match foreign library name ("*" above) against
* @returns: 0 on success, negative value on failure.
*/
-int init_foreign(const char *multipath_dir);
+int init_foreign(const char *multipath_dir, const char *enable);
/**
* cleanup_foreign(dir)
diff --git a/multipath/main.c b/multipath/main.c
index 96a11468..4f4d8e89 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -1050,7 +1050,7 @@ main (int argc, char *argv[])
goto out;
}
/* Failing here is non-fatal */
- init_foreign(conf->multipath_dir);
+ init_foreign(conf->multipath_dir, conf->enable_foreign);
if (cmd == CMD_USABLE_PATHS) {
r = check_usable_paths(conf, dev, dev_type) ?
RTVL_FAIL : RTVL_OK;
diff --git a/multipathd/main.c b/multipathd/main.c
index 04b2b56a..8826620d 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -2848,7 +2848,7 @@ child (void * param)
}
/* Failing this is non-fatal */
- init_foreign(conf->multipath_dir);
+ init_foreign(conf->multipath_dir, conf->enable_foreign);
if (poll_dmevents)
poll_dmevents = dmevent_poll_supported();
--
2.17.2

View file

@ -0,0 +1,75 @@
From 1439bf7acc88b6a398e1a390045dcac9e3163e53 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Thu, 15 Aug 2019 14:46:56 +0000
Subject: [PATCH] multipath.conf.5: document foreign library support
Add documentation for foreign library support, and for the
"enable_foreign" parameter.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/multipath.conf.5 | 40 ++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index ac8eadd0..101e1a88 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1222,6 +1222,21 @@ makes multipath immediately mark a device with only ghost paths as ready.
The default is: \fBno\fR
.RE
.
+.
+.TP
+.B enable_foreign
+Enables or disables foreign libraries (see section
+.I FOREIGN MULTIPATH SUPPORT
+below). The value is a regular expression; foreign libraries are loaded
+if their name (e.g. \(dqnvme\(dq) matches the expression. By default,
+all foreign libraries are enabled.
+.RS
+.TP
+The default is: \fB\(dq\(dq\fR (the empty regular expression)
+.RE
+.
+.
+
.
.\" ----------------------------------------------------------------------------
.SH "blacklist and blacklist_exceptions sections"
@@ -1765,6 +1780,31 @@ unpredictable ways. If the \(dqmarginal_path\(dq method is active, the
.
.
.\" ----------------------------------------------------------------------------
+.SH "FOREIGN MULTIPATH SUPPORT"
+.\" ----------------------------------------------------------------------------
+.
+multipath and multipathd can load \(dqforeign\(dq libraries to add
+support for other multipathing technologies besides the Linux device mapper.
+Currently this support is limited to printing detected information about
+multipath setup. In topology output, the names of foreign maps are prefixed by
+the foreign library name in square brackets, as in this example:
+.
+.P
+.EX
+# multipath -ll
+uuid.fedcba98-3579-4567-8765-123456789abc [nvme]:nvme4n9 NVMe,Some NVMe controller,FFFFFFFF
+size=167772160 features='n/a' hwhandler='ANA' wp=rw
+|-+- policy='n/a' prio=50 status=optimized
+| `- 4:38:1 nvme4c38n1 0:0 n/a optimized live
+`-+- policy='n/a' prio=50 status=optimized
+ `- 4:39:1 nvme4c39n1 0:0 n/a optimized live
+.EE
+.
+.P
+The \(dqnvme\(dq foreign library provides support for NVMe native multipathing
+in the kernel. It is part of the standard multipath package.
+.
+.\" ----------------------------------------------------------------------------
.SH "KNOWN ISSUES"
.\" ----------------------------------------------------------------------------
.
--
2.17.2

View file

@ -0,0 +1,51 @@
From 826c100b0cbe72c5d770614cea8898afec09628c Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 9 Sep 2019 16:18:33 -0500
Subject: [PATCH] mpathpersist: remove broken/unused code
The test for an empty pp->dev in updatepaths() dates back to when
disassemble_map() didn't fill in pp->dev for newly added paths, and it
was meant to catch paths that got added by disassemble_map(). With the
mpathpersist speedup code, all paths get added by disassemble_map().
However, disassemble_map() now calls devt2devname() to set pp->dev if
possible. This means that there is no point in calling devt2devname()
again in updatepaths(). If for some reason it did return success, the
current code would still fail, since it doesn't set pp->udev in this
code path. The best thing to do if disassemble_map() couldn't set
pp->dev is simply to fail the path.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmpathpersist/mpath_persist.c | 16 ++++------------
1 file changed, 4 insertions(+), 12 deletions(-)
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
index 53022f5b..603cfc3b 100644
--- a/libmpathpersist/mpath_persist.c
+++ b/libmpathpersist/mpath_persist.c
@@ -82,18 +82,10 @@ updatepaths (struct multipath * mpp)
vector_foreach_slot (pgp->paths, pp, j){
if (!strlen(pp->dev)){
- if (devt2devname(pp->dev, FILE_NAME_SIZE,
- pp->dev_t)){
- /*
- * path is not in sysfs anymore
- */
- pp->state = PATH_DOWN;
- continue;
- }
- pp->mpp = mpp;
- conf = get_multipath_config();
- pathinfo(pp, conf, DI_ALL);
- put_multipath_config(conf);
+ /*
+ * path is not in sysfs anymore
+ */
+ pp->state = PATH_DOWN;
continue;
}
pp->mpp = mpp;
--
2.17.2

View file

@ -0,0 +1,33 @@
From 16116095d5a11c5134e0696398a9908dafc415bc Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 9 Sep 2019 17:18:08 -0500
Subject: [PATCH] libmultipath: EMC PowerMax NVMe device config
Got this config from Dell.
Cc: heyi <yi.he@dell.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/hwtable.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index 96e8b25d..ca217e65 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -360,6 +360,12 @@ static struct hwentry default_hw[] = {
.pgfailback = -FAILBACK_IMMEDIATE,
.no_path_retry = 30,
},
+ {
+ /* EMC PowerMax NVMe */
+ .vendor = "NVME",
+ .product = "^EMC PowerMax_",
+ .pgpolicy = MULTIBUS,
+ },
/*
* Fujitsu
*/
--
2.17.2

View file

@ -0,0 +1,132 @@
From 385f0a62f83af67eb0b4b67f3af43e149619c0af Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 10 Sep 2019 10:44:50 -0500
Subject: [PATCH] mpathpersist: fix leaks
If handle_args() fails while looping through the argument list, it needs
to free batch_fn, if it has been set. Also handle_args() needs to make
sure to free the file descriptor after it has been opened.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
mpathpersist/main.c | 31 ++++++++++++++++++++-----------
1 file changed, 20 insertions(+), 11 deletions(-)
diff --git a/mpathpersist/main.c b/mpathpersist/main.c
index 5ad06a97..2368b429 100644
--- a/mpathpersist/main.c
+++ b/mpathpersist/main.c
@@ -155,7 +155,8 @@ static int do_batch_file(const char *batch_fn)
static int handle_args(int argc, char * argv[], int nline)
{
- int fd, c;
+ int c;
+ int fd = -1;
const char *device_name = NULL;
int num_prin_sa = 0;
int num_prout_sa = 0;
@@ -213,7 +214,8 @@ static int handle_args(int argc, char * argv[], int nline)
if (nline == 0 && 1 != sscanf (optarg, "%d", &loglevel))
{
fprintf (stderr, "bad argument to '--verbose'\n");
- return MPATH_PR_SYNTAX_ERROR;
+ ret = MPATH_PR_SYNTAX_ERROR;
+ goto out;
}
break;
@@ -228,6 +230,7 @@ static int handle_args(int argc, char * argv[], int nline)
case 'h':
usage ();
+ free(batch_fn);
return 0;
case 'H':
@@ -254,7 +257,8 @@ static int handle_args(int argc, char * argv[], int nline)
if (1 != sscanf (optarg, "%" SCNx64 "", &param_rk))
{
fprintf (stderr, "bad argument to '--param-rk'\n");
- return MPATH_PR_SYNTAX_ERROR;
+ ret = MPATH_PR_SYNTAX_ERROR;
+ goto out;
}
++num_prout_param;
break;
@@ -263,7 +267,8 @@ static int handle_args(int argc, char * argv[], int nline)
if (1 != sscanf (optarg, "%" SCNx64 "", &param_sark))
{
fprintf (stderr, "bad argument to '--param-sark'\n");
- return MPATH_PR_SYNTAX_ERROR;
+ ret = MPATH_PR_SYNTAX_ERROR;
+ goto out;
}
++num_prout_param;
break;
@@ -282,7 +287,8 @@ static int handle_args(int argc, char * argv[], int nline)
if (1 != sscanf (optarg, "%x", &prout_type))
{
fprintf (stderr, "bad argument to '--prout-type'\n");
- return MPATH_PR_SYNTAX_ERROR;
+ ret = MPATH_PR_SYNTAX_ERROR;
+ goto out;
}
++num_prout_param;
break;
@@ -330,7 +336,8 @@ static int handle_args(int argc, char * argv[], int nline)
case 'X':
if (0 != construct_transportid(optarg, transportids, num_transport)) {
fprintf(stderr, "bad argument to '--transport-id'\n");
- return MPATH_PR_SYNTAX_ERROR;
+ ret = MPATH_PR_SYNTAX_ERROR;
+ goto out;
}
++num_transport;
@@ -339,11 +346,13 @@ static int handle_args(int argc, char * argv[], int nline)
case 'l':
if (1 != sscanf(optarg, "%u", &mpath_mx_alloc_len)) {
fprintf(stderr, "bad argument to '--alloc-length'\n");
- return MPATH_PR_SYNTAX_ERROR;
+ ret = MPATH_PR_SYNTAX_ERROR;
+ goto out;
} else if (MPATH_MAX_PARAM_LEN < mpath_mx_alloc_len) {
fprintf(stderr, "'--alloc-length' argument exceeds maximum"
" limit(%d)\n", MPATH_MAX_PARAM_LEN);
- return MPATH_PR_SYNTAX_ERROR;
+ ret = MPATH_PR_SYNTAX_ERROR;
+ goto out;
}
break;
@@ -481,14 +490,14 @@ static int handle_args(int argc, char * argv[], int nline)
{
fprintf (stderr, "failed to allocate PRIN response buffer\n");
ret = MPATH_PR_OTHER;
- goto out;
+ goto out_fd;
}
ret = __mpath_persistent_reserve_in (fd, prin_sa, resp, noisy);
if (ret != MPATH_PR_SUCCESS )
{
fprintf (stderr, "Persistent Reserve IN command failed\n");
- goto out;
+ goto out_fd;
}
switch(prin_sa)
@@ -568,8 +577,8 @@ static int handle_args(int argc, char * argv[], int nline)
printf("PR out: command failed\n");
}
+out_fd:
close (fd);
-
out :
if (ret == MPATH_PR_SYNTAX_ERROR) {
free(batch_fn);
--
2.17.2

View file

@ -0,0 +1,232 @@
From 33a6f6b05d7041716142f080a2708db351c92eaa Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 10 Sep 2019 15:46:28 -0500
Subject: [PATCH] libmultipath: fix mpcontext initialization
If a path is discovered before there is a multipath device for it to
belong to, the checker will not have its mpcontext initialized, even if
that path later belongs to a multipath device. A checker's mpcontext is
only set when the checker is selected, and is set to NULL if there is no
multipath device associated with the path. This only impacts the emc
checker. However, it makes the emc checker unable to determine if a
passive path is connected to an inactive snapshot or not.
This can be solved by adding a new checker class function, mp_init().
This is called when the checker is first initialized, and whenever the
checker is called, if the checker's mpcontext hasn't been initialized.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/checkers.c | 29 ++++++++++++++++++++++++++--
libmultipath/checkers.h | 1 +
libmultipath/checkers/cciss_tur.c | 5 +++++
libmultipath/checkers/directio.c | 5 +++++
libmultipath/checkers/emc_clariion.c | 7 +++++++
libmultipath/checkers/hp_sw.c | 5 +++++
libmultipath/checkers/rdac.c | 5 +++++
libmultipath/checkers/readsector0.c | 5 +++++
libmultipath/checkers/tur.c | 5 +++++
libmultipath/discovery.c | 2 ++
10 files changed, 67 insertions(+), 2 deletions(-)
diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c
index f4fdcae9..240b0f29 100644
--- a/libmultipath/checkers.c
+++ b/libmultipath/checkers.c
@@ -16,6 +16,7 @@ struct checker_class {
char name[CHECKER_NAME_LEN];
int (*check)(struct checker *);
int (*init)(struct checker *); /* to allocate the context */
+ int (*mp_init)(struct checker *); /* to allocate the mpcontext */
void (*free)(struct checker *); /* to free the context */
const char **msgtable;
short msgtable_size;
@@ -140,6 +141,13 @@ static struct checker_class *add_checker_class(const char *multipath_dir,
if (!c->init)
goto out;
+ c->mp_init = (int (*)(struct checker *)) dlsym(c->handle, "libcheck_mp_init");
+ errstr = dlerror();
+ if (errstr != NULL)
+ condlog(0, "A dynamic linking error occurred: (%s)", errstr);
+ if (!c->mp_init)
+ goto out;
+
c->free = (void (*)(struct checker *)) dlsym(c->handle, "libcheck_free");
errstr = dlerror();
if (errstr != NULL)
@@ -212,8 +220,25 @@ int checker_init (struct checker * c, void ** mpctxt_addr)
if (!c || !c->cls)
return 1;
c->mpcontext = mpctxt_addr;
- if (c->cls->init)
- return c->cls->init(c);
+ if (c->cls->init && c->cls->init(c) != 0)
+ return 1;
+ if (mpctxt_addr && *mpctxt_addr == NULL && c->cls->mp_init &&
+ c->cls->mp_init(c) != 0) /* continue even if mp_init fails */
+ c->mpcontext = NULL;
+ return 0;
+}
+
+int checker_mp_init(struct checker * c, void ** mpctxt_addr)
+{
+ if (!c || !c->cls)
+ return 1;
+ if (c->cls->mp_init && !c->mpcontext && mpctxt_addr) {
+ c->mpcontext = mpctxt_addr;
+ if (c->cls->mp_init(c) != 0) {
+ c->mpcontext = NULL;
+ return 1;
+ }
+ }
return 0;
}
diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h
index dab197f9..5237e7ec 100644
--- a/libmultipath/checkers.h
+++ b/libmultipath/checkers.h
@@ -138,6 +138,7 @@ const char *checker_state_name(int);
int init_checkers(const char *);
void cleanup_checkers (void);
int checker_init (struct checker *, void **);
+int checker_mp_init(struct checker *, void **);
void checker_clear (struct checker *);
void checker_put (struct checker *);
void checker_reset (struct checker *);
diff --git a/libmultipath/checkers/cciss_tur.c b/libmultipath/checkers/cciss_tur.c
index ea843742..b570ed65 100644
--- a/libmultipath/checkers/cciss_tur.c
+++ b/libmultipath/checkers/cciss_tur.c
@@ -51,6 +51,11 @@ int libcheck_init (struct checker * c)
return 0;
}
+int libcheck_mp_init (struct checker * c)
+{
+ return 0;
+}
+
void libcheck_free (struct checker * c)
{
return;
diff --git a/libmultipath/checkers/directio.c b/libmultipath/checkers/directio.c
index 1b00b775..96f223b2 100644
--- a/libmultipath/checkers/directio.c
+++ b/libmultipath/checkers/directio.c
@@ -103,6 +103,11 @@ out:
return 1;
}
+int libcheck_mp_init(struct checker * c)
+{
+ return 0;
+}
+
void libcheck_free (struct checker * c)
{
struct directio_context * ct = (struct directio_context *)c->context;
diff --git a/libmultipath/checkers/emc_clariion.c b/libmultipath/checkers/emc_clariion.c
index 6fc89113..5cd63aca 100644
--- a/libmultipath/checkers/emc_clariion.c
+++ b/libmultipath/checkers/emc_clariion.c
@@ -107,11 +107,18 @@ int libcheck_init (struct checker * c)
return 1;
((struct emc_clariion_checker_path_context *)c->context)->wwn_set = 0;
+ return 0;
+}
+
+int libcheck_mp_init (struct checker * c)
+{
/*
* Allocate and initialize the multi-path global context.
*/
if (c->mpcontext && *c->mpcontext == NULL) {
void * mpctxt = malloc(sizeof(int));
+ if (!mpctxt)
+ return 1;
*c->mpcontext = mpctxt;
CLR_INACTIVE_SNAP(c);
}
diff --git a/libmultipath/checkers/hp_sw.c b/libmultipath/checkers/hp_sw.c
index 1a820223..35aca204 100644
--- a/libmultipath/checkers/hp_sw.c
+++ b/libmultipath/checkers/hp_sw.c
@@ -37,6 +37,11 @@ int libcheck_init (struct checker * c)
return 0;
}
+int libcheck_mp_init(struct checker * c)
+{
+ return 0;
+}
+
void libcheck_free (struct checker * c)
{
return;
diff --git a/libmultipath/checkers/rdac.c b/libmultipath/checkers/rdac.c
index 8a3b73ec..805d153e 100644
--- a/libmultipath/checkers/rdac.c
+++ b/libmultipath/checkers/rdac.c
@@ -133,6 +133,11 @@ out:
return 0;
}
+int libcheck_mp_init(struct checker * c)
+{
+ return 0;
+}
+
void libcheck_free (struct checker * c)
{
return;
diff --git a/libmultipath/checkers/readsector0.c b/libmultipath/checkers/readsector0.c
index cf79e067..71db9f80 100644
--- a/libmultipath/checkers/readsector0.c
+++ b/libmultipath/checkers/readsector0.c
@@ -15,6 +15,11 @@ int libcheck_init (struct checker * c)
return 0;
}
+int libcheck_mp_init(struct checker * c)
+{
+ return 0;
+}
+
void libcheck_free (struct checker * c)
{
return;
diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c
index 6b08dbbb..138b9e58 100644
--- a/libmultipath/checkers/tur.c
+++ b/libmultipath/checkers/tur.c
@@ -79,6 +79,11 @@ int libcheck_init (struct checker * c)
return 0;
}
+int libcheck_mp_init(struct checker * c)
+{
+ return 0;
+}
+
static void cleanup_context(struct tur_checker_context *ct)
{
pthread_mutex_destroy(&ct->lock);
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index acca466c..72f455e8 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1608,6 +1608,8 @@ get_state (struct path * pp, struct config *conf, int daemon, int oldstate)
return PATH_UNCHECKED;
}
}
+ if (pp->mpp && !c->mpcontext)
+ checker_mp_init(c, &pp->mpp->mpcontext);
checker_clear_message(c);
if (daemon) {
if (conf->force_sync == 0)
--
2.17.2

View file

@ -0,0 +1,66 @@
From c1df27f4efd0c36d6ceecf5c850a68859e7d5fe5 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 56c3eda0..2e8946ca 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -53,7 +53,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 8f990494..8a3a1718 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 0828a8f7..b9bbb3cf 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -24,7 +24,7 @@ install:
$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
- $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
+ $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man8dir)
$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(man8dir)
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir)
@@ -33,7 +33,7 @@ install:
uninstall:
$(RM) $(DESTDIR)$(bindir)/$(EXEC)
$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
- $(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
+ $(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
$(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz
$(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
--
2.17.2

View file

@ -1,4 +1,4 @@
From f7be16ac9fce97585a4552d49f3d3c54a93c9c17 Mon Sep 17 00:00:00 2001
From 46cfd1a474d1c3e2724782c493d0ea72c8438807 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
@ -13,25 +13,29 @@ 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(-)
libmultipath/blacklist.c | 9 ++-------
multipath/multipath.conf.5 | 12 ++++++------
tests/blacklist.c | 6 ++----
3 files changed, 10 insertions(+), 17 deletions(-)
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
index 17e1b54a..10d13e98 100644
index 00e8dbdb..d9691b17 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;
@@ -204,12 +204,6 @@ setup_default_blist (struct config * conf)
if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
return 1;
- str = STRDUP("(SCSI_IDENT_|ID_WWN)");
- if (!str)
- return 1;
- if (store_ble(conf->elist_property, str, ORIGIN_DEFAULT))
- return 1;
-
vector_foreach_slot (conf->hwtable, hwe, i) {
if (hwe->bl_product) {
@@ -438,7 +436,8 @@ filter_property(const struct config *conf, struct udev_device *udev,
if (find_blacklist_device(conf->blist_device,
@@ -411,7 +405,8 @@ filter_property(struct config *conf, struct udev_device *udev, int lvl,
*uid_attribute != '\0';
bool uid_attr_seen = false;
@ -41,11 +45,11 @@ index 17e1b54a..10d13e98 100644
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
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 101e1a88..b4837b15 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1287,9 +1287,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,
@ -61,7 +65,7 @@ index 3c9ae097..ba291e11 100644
.
.RS
.PP
@@ -1483,10 +1488,6 @@ Blacklisting by missing properties is only applied to devices which do have the
@@ -1300,11 +1305,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.
@ -69,25 +73,24 @@ index 3c9ae097..ba291e11 100644
-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
-.RE
.TP
.B protocol
Regular expression for the protocol of a device to be excluded/included.
diff --git a/tests/blacklist.c b/tests/blacklist.c
index ab3da619..52ae03e0 100644
index 362c44d9..ea284939 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 } };
@@ -291,7 +291,7 @@ static void test_property_missing(void **state)
conf.blist_property = blist_property_wwn;
- expect_condlog(3, "sdb: blacklisted, udev property missing\n");
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)
@@ -383,9 +383,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;
@ -98,3 +101,6 @@ index ab3da619..52ae03e0 100644
}
/* This one matches the property whitelist, to test the other missing
--
2.17.2

View file

@ -0,0 +1,106 @@
From 4e4c589657eecfe5d37636ce91eb2945f63fc0a6 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 20e3b8bf..c36bc69c 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -26,6 +26,7 @@
#include "devmapper.h"
#include "mpath_cmd.h"
#include "propsel.h"
+#include "version.h"
static int
hwe_strmatch (const struct hwentry *hwe1, const struct hwentry *hwe2)
@@ -743,6 +744,20 @@ load_config (char * file)
goto out;
}
factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
+ } else {
+ condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
+ if (conf->blist_devnode == NULL) {
+ conf->blist_devnode = vector_alloc();
+ if (!conf->blist_devnode) {
+ condlog(0, "cannot allocate blacklist\n");
+ goto out;
+ }
+ }
+ if (store_ble(conf->blist_devnode, strdup(".*"),
+ ORIGIN_NO_CONFIG)) {
+ condlog(0, "cannot store default no-config blacklist\n");
+ goto out;
+ }
}
conf->processed_main_config = 1;
diff --git a/libmultipath/config.h b/libmultipath/config.h
index ffec3103..6dbf553d 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 9df11a95..0486bf70 100644
--- a/multipath/multipath.rules
+++ b/multipath/multipath.rules
@@ -9,6 +9,7 @@ IMPORT{cmdline}="nompath"
ENV{nompath}=="?*", GOTO="end_mpath"
IMPORT{cmdline}="multipath"
ENV{multipath}=="off", GOTO="end_mpath"
+TEST!="/etc/multipath.conf", GOTO="end_mpath"
ENV{DEVTYPE}!="partition", GOTO="test_dev"
IMPORT{parent}="DM_MULTIPATH_DEVICE_PATH"
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8
index 048a838d..8bd47a80 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 ba24983e..17434cef 100644
--- a/multipathd/multipathd.service
+++ b/multipathd/multipathd.service
@@ -4,6 +4,7 @@ Wants=systemd-udev-trigger.service systemd-udev-settle.service
Before=iscsi.service iscsid.service lvm2-activation-early.service
Before=local-fs-pre.target blk-availability.service
After=multipathd.socket systemd-udev-trigger.service systemd-udev-settle.service
+ConditionPathExists=/etc/multipath.conf
DefaultDependencies=no
Conflicts=shutdown.target
ConditionKernelCommandLine=!nompath
--
2.17.2

View file

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

View file

@ -1,4 +1,4 @@
From 29e5c6d6e2177e73d1be2ed2af66c1007487bf60 Mon Sep 17 00:00:00 2001
From 64b336a47365eb0ee91a917d6b98c6c695775a36 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
@ -10,48 +10,22 @@ 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(+)
libmultipath/config.c | 2 +
multipath/Makefile | 5 +
multipath/mpathconf | 464 ++++++++++++++++++++++++++++++++++++++++++
multipath/mpathconf.8 | 119 +++++++++++
4 files changed, 590 insertions(+)
create mode 100644 multipath/mpathconf
create mode 100644 multipath/mpathconf.8
diff --git a/.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
index c36bc69c..fcd17dd4 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);
@@ -746,6 +746,8 @@ load_config (char * file)
factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
} else {
condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
+ condlog(0, "You can run \"/sbin/mpathconf --enable\" to create");
@ -60,46 +34,45 @@ index b8317f4d..0bbaa981 100644
conf->blist_devnode = vector_alloc();
if (!conf->blist_devnode) {
diff --git a/multipath/Makefile b/multipath/Makefile
index 2ea9e528..3dc241cc 100644
index b9bbb3cf..e720c7f6 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -24,6 +24,7 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
@@ -18,10 +18,12 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
$(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS) $(LIBDEPS)
$(GZIP) $(EXEC).8 > $(EXEC).8.gz
$(GZIP) $(EXEC).conf.5 > $(EXEC).conf.5.gz
+ $(GZIP) mpathconf.8 > mpathconf.8.gz
install:
$(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
$(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:
$(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
$(RM) $(DESTDIR)$(bindir)/$(EXEC)
$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
$(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
+ $(RM) $(DESTDIR)$(bindir)/mpathconf
$(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz
$(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
+ $(RM) $(DESTDIR)$(man8dir)/mpathconf.8.gz
clean: dep_clean
$(RM) core *.o $(EXEC) *.gz
diff --git a/multipath/mpathconf b/multipath/mpathconf
new file mode 100644
index 00000000..ce430075
index 00000000..e8391347
--- /dev/null
+++ b/multipath/mpathconf
@@ -0,0 +1,658 @@
@@ -0,0 +1,464 @@
+#!/bin/bash
+#
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
@ -119,7 +92,7 @@ index 00000000..ce430075
+# 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
+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
+
@ -133,7 +106,11 @@ index 00000000..ce430075
+
+defaults {
+ user_friendly_names yes
+ find_multipaths on
+ find_multipaths yes
+}
+
+blacklist_exceptions {
+ property \"(SCSI_IDENT_|ID_WWN)\"
+}"
+
+CONFIGFILE="/etc/multipath.conf"
@ -151,11 +128,7 @@ index 00000000..ce430075
+ 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 "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>"
@ -248,15 +221,6 @@ index 00000000..ce430075
+ 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
@ -266,38 +230,6 @@ index 00000000..ce430075
+ 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
@ -335,54 +267,21 @@ index 00000000..ce430075
+
+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
+ if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$MODULE" ]; 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'"
+ if [ -n "$FIND" ] && [ "$FIND" != "y" -a "$FIND" != "n" ]; then
+ echo "--find_multipaths 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
+ if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" ]; then
+ SHOW_STATUS=1
+ fi
+ if [ -n "$MODULE" ] && [ "$MODULE" != "y" -a "$MODULE" != "n" ]; then
@ -457,64 +356,32 @@ index 00000000..ce430075
+fi
+
+if [ "$HAVE_BLACKLIST" = "1" ]; then
+ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"" ; 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[[:space:]][[:space:]]*\"\.\?\*\"" ; then
+ 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[[:space:]][[:space:]]*\"\.\?\*\"" ; 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[[:space:]][[:space:]]*\"\.\?\*\"" ; then
+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"" ; 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"
+ 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:]][[:space:]]*\(yes\|1\)" ; then
+ 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:]][[:space:]]*\(no\|0\)" ; then
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[: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
@ -523,35 +390,16 @@ index 00000000..ce430075
+ else
+ echo "multipath is disabled"
+ fi
+ if [ -z "$HAVE_FIND" ]; then
+ echo "find_multipaths is off"
+ if [ -z "$HAVE_FIND" -o "$HAVE_FIND" = 0 ]; then
+ echo "find_multipaths is disabled"
+ else
+ echo "find_multipaths is $HAVE_FIND"
+ 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 [ -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"
@ -592,14 +440,14 @@ index 00000000..ce430075
+
+if [ "$ENABLE" = 2 ]; then
+ if [ "$HAVE_DISABLE" = 1 ]; then
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"/# devnode ".*"/' $TMPFILE
+ 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[[:space:]][[:space:]]*\"\.\?\*\"/ wwid ".*"/' $TMPFILE
+ 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
@ -613,7 +461,7 @@ index 00000000..ce430075
+ add_blacklist_exceptions
+elif [ "$ENABLE" = 1 ]; then
+ if [ "$HAVE_DISABLE" = 1 ]; then
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"/# devnode ".*"/' $TMPFILE
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE
+ fi
+elif [ "$ENABLE" = 0 ]; then
+ if [ -z "$HAVE_DISABLE" ]; then
@ -621,25 +469,30 @@ index 00000000..ce430075
+ devnode ".*"
+' $TMPFILE
+ elif [ "$HAVE_DISABLE" = 0 ]; then
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"/ devnode ".*"/' $TMPFILE
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"/ devnode ".*"/' $TMPFILE
+ fi
+fi
+
+if [ -n "$FIND" ]; then
+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 '"$FIND"'
+ find_multipaths yes
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$FIND" != "$HAVE_FIND" ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:blank:]]*find_multipaths[[:blank:]][[:blank:]]*[^[:blank:]]*/ find_multipaths '"$FIND"'/' $TMPFILE
+ 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:]][[:space:]]*\(yes\|1\)/ user_friendly_names no/' $TMPFILE
+ 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
@ -649,85 +502,11 @@ index 00000000..ce430075
+' $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
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[: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
@ -760,10 +539,10 @@ index 00000000..ce430075
+fi
diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8
new file mode 100644
index 00000000..ec4e5c56
index 00000000..5b7ae0c3
--- /dev/null
+++ b/multipath/mpathconf.8
@@ -0,0 +1,151 @@
@@ -0,0 +1,119 @@
+.TH MPATHCONF 8 "June 2010" "" "Linux Administrator's Manual"
+.SH NAME
+mpathconf - A tool for configuring device-mapper-multipath
@ -804,12 +583,12 @@ index 00000000..ec4e5c56
+already exists, mpathconf will edit it. If it does not exist, mpathconf will
+create a default file with
+.B user_friendly_names
+set and
+and
+.B find_multipaths
+set to \fBon\fP. To disable these, use the
+set. To disable these, use the
+.B --user_friendly_names n
+and
+.B --find_multipaths off
+.B --find_multipaths n
+options
+.SH COMMANDS
+.TP
@ -835,7 +614,7 @@ index 00000000..ec4e5c56
+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 }
+.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
@ -843,45 +622,13 @@ index 00000000..ec4e5c56
+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 }
+.B --find_multipaths\fP { \fBy\fP | \fBn\fP }
+If set to \fBy\fP, this adds the line
+.B recheck_wwid yes
+.B find_multipaths 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.
+defaults section. If set to \fBn\fP, this removes the line, if present. This
+command can be used aldong with any other command.
+.TP
+.B --outfile \fB<filename>\fP
+Write the resulting multipath configuration to \fB<filename>\fP instead of
@ -902,7 +649,7 @@ index 00000000..ec4e5c56
+.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
+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
@ -915,3 +662,6 @@ index 00000000..ec4e5c56
+.BR service (8),
+.SH AUTHOR
+Benjamin Marzinski <bmarzins@redhat.com>
--
2.17.2

View file

@ -1,4 +1,4 @@
From d6ad888bad3850bb0a342ebcdc9fd78773eb3b2a Mon Sep 17 00:00:00 2001
From bba3bc3cfd910921ab5887acdc9503610e7efa18 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
@ -14,38 +14,23 @@ 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(-)
libmultipath/wwids.c | 44 +++++++++++++++++++++++++++++++++++
libmultipath/wwids.h | 1 +
multipath/main.c | 10 ++++++--
multipath/multipath.8 | 7 +++++-
multipathd/multipathd.service | 1 +
5 files changed, 60 insertions(+), 3 deletions(-)
diff --git a/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)
diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
index ef748125..349da8b7 100644
--- a/libmultipath/wwids.c
+++ b/libmultipath/wwids.c
@@ -444,3 +444,47 @@ int op ## _wwid(const char *wwid) \
declare_failed_wwid_op(is_failed, false)
declare_failed_wwid_op(mark_failed, true)
declare_failed_wwid_op(unmark_failed, true)
+
+int remember_cmdline_wwid(void)
+{
+ FILE *f = NULL;
+ char buf[LINE_MAX], *next, *ptr;
@ -88,20 +73,50 @@ index 31012874..a667c2ee 100644
+ }
+ 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 ) {
diff --git a/libmultipath/wwids.h b/libmultipath/wwids.h
index 0c6ee54d..e32a0b0e 100644
--- a/libmultipath/wwids.h
+++ b/libmultipath/wwids.h
@@ -17,6 +17,7 @@ int remember_wwid(char *wwid);
int check_wwids_file(char *wwid, int write_wwid);
int remove_wwid(char *wwid);
int replace_wwids(vector mp);
+int remember_cmdline_wwid(void);
enum {
WWID_IS_NOT_FAILED = 0,
diff --git a/multipath/main.c b/multipath/main.c
index 4f4d8e89..22aff7be 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -138,7 +138,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);
@@ -151,6 +151,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"
@@ -905,7 +907,7 @@ main (int argc, char *argv[])
exit(RTVL_FAIL);
multipath_conf = conf;
conf->retrigger_tries = 0;
- while ((arg = getopt(argc, argv, ":adcChl::FfM:v:p:b:BrR:itTquUwW")) != EOF ) {
+ while ((arg = getopt(argc, argv, ":aAdcChl::FfM:v:p:b:BrR:itTquUwW")) != EOF ) {
switch(arg) {
case 'v':
if (!isdigit(optarg[0])) {
@@ -922,6 +968,10 @@ main (int argc, char *argv[])
case 1: printf("optarg : %s\n",optarg);
break;
@@ -975,6 +977,10 @@ main (int argc, char *argv[])
case 'T':
cmd = CMD_DUMP_CONFIG;
break;
@ -112,11 +127,11 @@ index 31012874..a667c2ee 100644
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.
diff --git a/multipath/multipath.8 b/multipath/multipath.8
index 9cdd05a3..8befc45a 100644
--- a/multipath/multipath.8
+++ b/multipath/multipath.8
@@ -63,7 +63,7 @@ multipath \- Device mapper target autoconfig.
.B multipath
.RB [\| \-v\ \c
.IR level \|]
@ -125,7 +140,7 @@ index b88e9a4c..edd742aa 100644
.
.LP
.B multipath
@@ -146,6 +146,11 @@ device mapper, path checkers ...).
@@ -145,6 +145,11 @@ device mapper, path checkers ...).
Add the WWID for the specified device to the WWIDs file.
.
.TP
@ -137,15 +152,18 @@ index b88e9a4c..edd742aa 100644
.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
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
index 17434cef..0fbcc46b 100644
--- a/multipathd/multipathd.service
+++ b/multipathd/multipathd.service
@@ -15,6 +15,7 @@ Type=notify
NotifyAccess=main
+ExecStartPre=-@BINDIR@/multipath -A
ExecStart=@BINDIR@/multipathd -d -s
ExecReload=@BINDIR@/multipathd reconfigure
Restart=on-failure
LimitCORE=infinity
ExecStartPre=-/sbin/modprobe -a scsi_dh_alua scsi_dh_emc scsi_dh_rdac dm-multipath
+ExecStartPre=-/sbin/multipath -A
ExecStart=/sbin/multipathd -d -s
ExecReload=/sbin/multipathd reconfigure
TasksMax=infinity
--
2.17.2

View file

@ -0,0 +1,121 @@
From 779d51dcaff09fc8910d5a71e74d735f573ece9e 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 1b3d0373..695c8404 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -58,6 +58,21 @@ set_str(vector strvec, void *ptr)
return 0;
}
+static int
+set_regex(vector strvec, void *ptr)
+{
+ char **str_ptr = (char **)ptr;
+
+ if (*str_ptr)
+ FREE(*str_ptr);
+ *str_ptr = set_regex_value(strvec);
+
+ if (!*str_ptr)
+ return 1;
+
+ return 0;
+}
+
static int
set_yes_no(vector strvec, void *ptr)
{
@@ -1422,7 +1437,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; \
\
@@ -1438,7 +1453,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; \
\
@@ -1541,16 +1556,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 e00c5fff..15495d26 100644
--- a/libmultipath/parser.c
+++ b/libmultipath/parser.c
@@ -382,6 +382,19 @@ oom:
return NULL;
}
+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 62906e98..b7917052 100644
--- a/libmultipath/parser.h
+++ b/libmultipath/parser.h
@@ -77,6 +77,7 @@ extern void dump_keywords(vector keydump, int level);
extern void free_keywords(vector keywords);
extern vector alloc_strvec(char *string);
extern void *set_value(vector strvec);
+extern void *set_regex_value(vector strvec);
extern int process_file(struct config *conf, char *conf_file);
extern struct keyword * find_keyword(vector keywords, vector v, char * name);
int snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw,
--
2.17.2

View file

@ -1,4 +1,4 @@
From 064d761121e7e2c7b63ab280e341d8010a413119 Mon Sep 17 00:00:00 2001
From 1f5156bc77ef05f5d93e7a9df6e270a587eb6a30 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
@ -6,18 +6,16 @@ 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(-)
libmultipath/defaults.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index 134b690a..e2fe7ac4 100644
index 4dfe007c..d910da51 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -24,7 +24,7 @@
@@ -20,7 +20,7 @@
#define DEFAULT_NO_PATH_RETRY NO_PATH_RETRY_UNDEF
#define DEFAULT_VERBOSITY 2
#define DEFAULT_REASSIGN_MAPS 0
@ -26,16 +24,6 @@ index 134b690a..e2fe7ac4 100644
#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
.
.
--
2.17.2

View file

@ -1,10 +1,7 @@
From 283b5dd645663a2cf16f2813581772d7a84db6ad Mon Sep 17 00:00:00 2001
From 938d211bf5e8d96849bfbf4d2707507adc7f718e 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.
Subject: [PATCH] RH: Fix nvme compilation warning
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
@ -12,10 +9,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/nvme/argconfig.h b/libmultipath/nvme/argconfig.h
index b3caa7be..f91504c9 100644
index adb192b6..bfd10ef8 100644
--- a/libmultipath/nvme/argconfig.h
+++ b/libmultipath/nvme/argconfig.h
@@ -63,7 +63,7 @@ struct argconfig_commandline_options {
@@ -76,7 +76,7 @@ struct argconfig_commandline_options {
extern "C" {
#endif
@ -24,3 +21,6 @@ index b3caa7be..f91504c9 100644
void argconfig_append_usage(const char *str);
void argconfig_print_help(const char *program_desc,
const struct argconfig_commandline_options *options);
--
2.17.2

View file

@ -1,4 +1,4 @@
From 335b8eb2773b07a602e84e14c1f3e289a9b25b5a Mon Sep 17 00:00:00 2001
From cff4e6981d8b168cabd81b3de6f9f97735de7e1a 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
@ -13,10 +13,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/libmultipath/prioritizers/ana.c b/libmultipath/prioritizers/ana.c
index 34527b22..4eaa3cc3 100644
index 2673d9d9..f34ade28 100644
--- a/libmultipath/prioritizers/ana.c
+++ b/libmultipath/prioritizers/ana.c
@@ -23,6 +23,7 @@
@@ -24,6 +24,7 @@
#include "prio.h"
#include "util.h"
#include "structs.h"
@ -24,7 +24,7 @@ index 34527b22..4eaa3cc3 100644
enum {
ANA_ERR_GETCTRL_FAILED = 1,
@@ -35,6 +36,7 @@ enum {
@@ -36,6 +37,7 @@ enum {
ANA_ERR_GETNS_FAILED,
ANA_ERR_NO_MEMORY,
ANA_ERR_NO_INFORMATION,
@ -32,7 +32,7 @@ index 34527b22..4eaa3cc3 100644
};
static const char *ana_errmsg[] = {
@@ -48,6 +50,7 @@ static const char *ana_errmsg[] = {
@@ -49,6 +51,7 @@ static const char *ana_errmsg[] = {
[ANA_ERR_GETNS_FAILED] = "couldn't get namespace info",
[ANA_ERR_NO_MEMORY] = "out of memory",
[ANA_ERR_NO_INFORMATION] = "invalid fd",
@ -44,7 +44,7 @@ index 34527b22..4eaa3cc3 100644
return -ANA_ERR_GETANAS_NOTFOUND;
}
+static int get_ana_info_sysfs(struct path *pp)
+int get_ana_info_sysfs(struct path *pp)
+{
+ char state[32];
+
@ -65,20 +65,23 @@ index 34527b22..4eaa3cc3 100644
+ return -ANA_ERR_INVALID_STATE;
+}
+
static int get_ana_info(struct path * pp)
int get_ana_info(struct path * pp, unsigned int timeout)
{
int rc;
@@ -208,8 +232,11 @@ int getprio(struct path *pp, __attribute__((unused)) char *args)
@@ -208,8 +232,11 @@ int getprio(struct path *pp, char *args, unsigned int timeout)
if (pp->fd < 0)
rc = -ANA_ERR_NO_INFORMATION;
- else
- rc = get_ana_info(pp);
- rc = get_ana_info(pp, timeout);
+ else {
+ rc = get_ana_info_sysfs(pp);
+ if (rc < 0)
+ rc = get_ana_info(pp);
+ rc = get_ana_info(pp, timeout);
+ }
switch (rc) {
case NVME_ANA_OPTIMIZED:
--
2.17.2

View file

@ -0,0 +1,119 @@
From b665961ce1acc273b936ef8593e328c413d35ba7 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 11 Feb 2020 17:01:08 -0600
Subject: [PATCH] multipath: fix issues found by compiling with gcc 10
Compiling with gcc 10 raised a number of warings about buffer sizes,
and an error based on declaring ___error1___ in multiple c files,
do to it being in structs.h. fix these
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
kpartx/dasd.c | 6 +++---
libmultipath/print.c | 3 ++-
libmultipath/structs.c | 6 ++++++
libmultipath/structs.h | 5 -----
multipath/main.c | 2 +-
5 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/kpartx/dasd.c b/kpartx/dasd.c
index d95d8ca0..42986e78 100644
--- a/kpartx/dasd.c
+++ b/kpartx/dasd.c
@@ -188,7 +188,7 @@ read_dasd_pt(int fd, struct slice all, struct slice *sp, int ns)
goto out;
}
- if ((!info.FBA_layout) && (!strcmp(info.type, "ECKD")))
+ if ((!info.FBA_layout) && (!strncmp(info.type, "ECKD", 4)))
memcpy (&vlabel, data, sizeof(vlabel));
else {
bzero(&vlabel,4);
@@ -218,7 +218,7 @@ read_dasd_pt(int fd, struct slice all, struct slice *sp, int ns)
sp[0].size = size - sp[0].start;
retval = 1;
} else if ((strncmp(type, "VOL1", 4) == 0) &&
- (!info.FBA_layout) && (!strcmp(info.type, "ECKD"))) {
+ (!info.FBA_layout) && (!strncmp(info.type, "ECKD",4))) {
/*
* New style VOL1 labeled disk
*/
@@ -267,7 +267,7 @@ read_dasd_pt(int fd, struct slice all, struct slice *sp, int ns)
if (vlabel.ldl_version == 0xf2) {
fmt_size = sectors512(vlabel.formatted_blocks,
blocksize);
- } else if (!strcmp(info.type, "ECKD")) {
+ } else if (!strncmp(info.type, "ECKD",4)) {
/* formatted w/o large volume support */
fmt_size = geo.cylinders * geo.heads
* geo.sectors * (blocksize >> 9);
diff --git a/libmultipath/print.c b/libmultipath/print.c
index 907469ad..61e123de 100644
--- a/libmultipath/print.c
+++ b/libmultipath/print.c
@@ -29,6 +29,7 @@
#include "uevent.h"
#include "debug.h"
#include "discovery.h"
+#include "util.h"
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
#define MIN(x,y) (((x) > (y)) ? (y) : (x))
@@ -2028,7 +2029,7 @@ int snprint_devices(struct config *conf, char * buff, int len,
devptr = devpath + 11;
*devptr = '\0';
- strncat(devptr, blkdev->d_name, PATH_MAX-12);
+ strlcpy(devptr, blkdev->d_name, PATH_MAX-11);
if (stat(devpath, &statbuf) < 0)
continue;
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
index bf7fdd73..46e8bb18 100644
--- a/libmultipath/structs.c
+++ b/libmultipath/structs.c
@@ -20,6 +20,12 @@
#include "prioritizers/alua_spc3.h"
#include "dm-generic.h"
+/*
+ * _FIND_MULTIPATHS_F must have the same value as YNU_YES.
+ * Generate a compile time error if that isn't the case.
+ */
+char ___error1___[-(_FIND_MULTIPATHS_F != YNU_YES)];
+
struct adapter_group *
alloc_adaptergroup(void)
{
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index a3adf906..191a5945 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -102,11 +102,6 @@ enum yes_no_undef_states {
#define _FIND_MULTIPATHS_F (1 << 1)
#define _FIND_MULTIPATHS_I (1 << 2)
#define _FIND_MULTIPATHS_N (1 << 3)
-/*
- * _FIND_MULTIPATHS_F must have the same value as YNU_YES.
- * Generate a compile time error if that isn't the case.
- */
-char ___error1___[-(_FIND_MULTIPATHS_F != YNU_YES)];
#define find_multipaths_on(conf) \
(!!((conf)->find_multipaths & _FIND_MULTIPATHS_F))
diff --git a/multipath/main.c b/multipath/main.c
index 22aff7be..ed214183 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -1029,7 +1029,7 @@ main (int argc, char *argv[])
if (!dev)
goto out;
- strncpy(dev, argv[optind], FILE_NAME_SIZE);
+ strlcpy(dev, argv[optind], FILE_NAME_SIZE);
if (dev_type != DEV_UEVENT)
dev_type = get_dev_type(dev);
if (dev_type == DEV_NONE) {
--
2.17.2

View file

@ -1,37 +1,52 @@
Name: device-mapper-multipath
Version: 0.13.0
Release: 2%{?dist}
Version: 0.8.2
Release: 4%{?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
License: GPLv2
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=refs/tags/0.8.2;sf=tgz" -o multipath-tools-0.8.2.tgz
Source0: multipath-tools-0.8.2.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-make-vector_foreach_slot_backwards-work.patch
Patch0002: 0002-libmultipath-add-marginal-paths-and-groups-infrastru.patch
Patch0003: 0003-tests-add-path-grouping-policy-unit-tests.patch
Patch0004: 0004-libmultipath-add-wrapper-function-around-pgpolicyfn.patch
Patch0005: 0005-tests-update-pgpolicy-tests-to-work-with-group_paths.patch
Patch0006: 0006-libmultipath-fix-double-free-in-pgpolicyfn-error-pat.patch
Patch0007: 0007-libmultipath-consolidate-group_by_-functions.patch
Patch0008: 0008-libmultipath-make-pgpolicyfn-take-a-paths-vector.patch
Patch0009: 0009-libmultipath-make-group_paths-handle-marginal-paths.patch
Patch0010: 0010-tests-add-tests-for-grouping-marginal-paths.patch
Patch0011: 0011-libmultipath-add-marginal_pathgroups-config-option.patch
Patch0012: 0012-libmutipath-deprecate-delay_-_checks.patch
Patch0013: 0013-multipathd-use-marginal_pathgroups.patch
Patch0014: 0014-multipath-update-man-pages.patch
Patch0015: 0015-multipath.conf-add-enable_foreign-parameter.patch
Patch0016: 0016-multipath.conf.5-document-foreign-library-support.patch
Patch0017: 0017-mpathpersist-remove-broken-unused-code.patch
Patch0018: 0018-libmultipath-EMC-PowerMax-NVMe-device-config.patch
Patch0019: 0019-mpathpersist-fix-leaks.patch
Patch0020: 0020-libmultipath-fix-mpcontext-initialization.patch
Patch0021: 0021-RH-fixup-udev-rules-for-redhat.patch
Patch0022: 0022-RH-Remove-the-property-blacklist-exception-builtin.patch
Patch0023: 0023-RH-don-t-start-without-a-config-file.patch
Patch0024: 0024-RH-use-rpm-optflags-if-present.patch
Patch0025: 0025-RH-add-mpathconf.patch
Patch0026: 0026-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch
Patch0027: 0027-RH-warn-on-invalid-regex-instead-of-failing.patch
Patch0028: 0028-RH-reset-default-find_mutipaths-value-to-off.patch
Patch0029: 0029-RH-Fix-nvme-compilation-warning.patch
Patch0030: 0030-RH-attempt-to-get-ANA-info-via-sysfs-first.patch
Patch0031: 0031-multipath-fix-issues-found-by-compiling-with-gcc-10.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(preun): systemd-units
Requires(postun): systemd-units
@ -53,8 +68,6 @@ BuildRequires: readline-devel, ncurses-devel
BuildRequires: systemd-units, systemd-devel
BuildRequires: json-c-devel, perl-interpreter, pkgconfig, gcc
BuildRequires: userspace-rcu-devel
BuildRequires: libmount-devel
BuildRequires: make
%description
%{name} provides tools to manage multipath devices by
@ -65,8 +78,8 @@ 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
# only libmpathcmd is LGPLv2+
License: GPLv2 and LGPLv2+
%description libs
The %{name}-libs provides the path checker
@ -91,8 +104,7 @@ 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
License: GPLv3+
Requires: json-c
Requires: %{name} = %{version}-%{release}
Requires: %{name}-libs = %{version}-%{release}
@ -111,26 +123,27 @@ 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
%autosetup -n multipath-tools-0.8.2 -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 +158,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,477 +168,73 @@ 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
%license LICENSES/GPL-2.0 LICENSES/LGPL-2.0
%{_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
%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
%license LICENSES/GPL-2.0 LICENSES/LGPL-2.0
%doc README
%{_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
%files devel
%doc README.md
%doc README
%{_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
%doc README
%{_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
%doc README
%{_libdir}/libdmmp.so.*
%ldconfig_scriptlets -n libdmmp
%files -n libdmmp-devel
%doc README.md
%doc README
%{_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
@ -883,7 +492,7 @@ fi
- 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
* Tue Apr 02 2018 Björn Esser <besser82@fedoraproject.org> - 0.7.6-1.git1cb704b
- Update Source to the latest upstream commit
* Previous patches 0001-0014 are included in this commit
* Previous patches 0015-0022 are now patches 0007-0014

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-0.8.2.tgz) = 31cc4054a2f645fa40b7a16aa8715871b848167a32bf3f34e1c900714f61a46f5d79cbda373bda7f8a8fd2280b96e045c1fd27f4b87aa84fc5305097d72edcd6
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
}
}