device-mapper-multipath-0.8.2-1

Update Source to upstream version 0.8.2
  * Previoud patches 0001-0017 & 0027 are included in this commit
Rename files
  * Previous patches 0018-0026 & 0028 are not patches 0021-0030
Add 0001-libmultipath-make-vector_foreach_slot_backwards-work.patch
Add 0002-libmultipath-add-marginal-paths-and-groups-infrastru.patch
Add 0003-tests-add-path-grouping-policy-unit-tests.patch
Add 0004-libmultipath-add-wrapper-function-around-pgpolicyfn.patch
Add 0005-tests-update-pgpolicy-tests-to-work-with-group_paths.patch
Add 0006-libmultipath-fix-double-free-in-pgpolicyfn-error-pat.patch
Add 0007-libmultipath-consolidate-group_by_-functions.patch
Add 0008-libmultipath-make-pgpolicyfn-take-a-paths-vector.patch
Add 0009-libmultipath-make-group_paths-handle-marginal-paths.patch
Add 0010-tests-add-tests-for-grouping-marginal-paths.patch
Add 0011-libmultipath-add-marginal_pathgroups-config-option.patch
Add 0012-libmutipath-deprecate-delay_-_checks.patch
Add 0013-multipathd-use-marginal_pathgroups.patch
Add 0014-multipath-update-man-pages.patch
  * The above 13 patches add the marinal_pathgroups option
Add 0015-multipath.conf-add-enable_foreign-parameter.patch
Add 0016-multipath.conf.5-document-foreign-library-support.patch
  * The above 2 patches add the enable_foreign option
Add 0017-mpathpersist-remove-broken-unused-code.patch
Add 0018-libmultipath-EMC-PowerMax-NVMe-device-config.patch
Add 0019-mpathpersist-fix-leaks.patch
Add 0020-libmultipath-fix-mpcontext-initialization.patch
  * The above 20 patches have been submitted upstream
This commit is contained in:
Benjamin Marzinski 2019-09-11 17:06:10 -05:00
parent 78ea7f5afb
commit 942c9b6ed8
51 changed files with 5309 additions and 1449 deletions

1
.gitignore vendored
View File

@ -18,3 +18,4 @@ multipath-tools-091027.tar.gz
/multipath-tools-17a6101.tgz
/multipath-tools-2df6110.tgz
/multipath-tools-0.8.0.tgz
/multipath-tools-0.8.2.tgz

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,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

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

View File

@ -0,0 +1,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

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

View File

@ -0,0 +1,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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,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

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

View File

@ -0,0 +1,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

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

View File

@ -0,0 +1,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

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

View File

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

View File

@ -0,0 +1,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

@ -1,4 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
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
@ -15,10 +15,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index fc728ca..2f0bcea 100644
index 56c3eda0..2e8946ca 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -48,7 +48,7 @@ endif
@@ -53,7 +53,7 @@ endif
prefix =
exec_prefix = $(prefix)
usr_prefix = $(prefix)
@ -28,7 +28,7 @@ index fc728ca..2f0bcea 100644
udevrulesdir = $(libudevdir)/rules.d
multipathdir = $(TOPDIR)/libmultipath
diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
index 8f99049..8a3a171 100644
index 8f990494..8a3a1718 100644
--- a/kpartx/kpartx.rules
+++ b/kpartx/kpartx.rules
@@ -32,6 +32,6 @@ LABEL="mpath_kpartx_end"
@ -40,7 +40,7 @@ index 8f99049..8a3a171 100644
LABEL="kpartx_end"
diff --git a/multipath/Makefile b/multipath/Makefile
index 0828a8f..b9bbb3c 100644
index 0828a8f7..b9bbb3cf 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -24,7 +24,7 @@ install:

View File

@ -1,4 +1,4 @@
From 0000000000000000000000000000000000000000 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,12 +13,13 @@ it.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/blacklist.c | 12 ++++--------
multipath/multipath.conf.5 | 14 ++++++--------
2 files changed, 10 insertions(+), 16 deletions(-)
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 e0d0279..556c0b9 100644
index 00e8dbdb..d9691b17 100644
--- a/libmultipath/blacklist.c
+++ b/libmultipath/blacklist.c
@@ -204,12 +204,6 @@ setup_default_blist (struct config * conf)
@ -34,14 +35,10 @@ index e0d0279..556c0b9 100644
vector_foreach_slot (conf->hwtable, hwe, i) {
if (hwe->bl_product) {
if (find_blacklist_device(conf->blist_device,
@@ -394,9 +388,11 @@ filter_property(struct config *conf, struct udev_device *udev, int lvl)
if (udev) {
/*
* This is the inverse of the 'normal' matching;
- * the environment variable _has_ to match.
+ * the environment variable _has_ to match
+ * if a whitelist is present.
*/
@@ -411,7 +405,8 @@ filter_property(struct config *conf, struct udev_device *udev, int lvl,
*uid_attribute != '\0';
bool uid_attr_seen = false;
- r = MATCH_PROPERTY_BLIST_MISSING;
+ if (VECTOR_SIZE(conf->elist_property))
+ r = MATCH_PROPERTY_BLIST_MISSING;
@ -49,10 +46,10 @@ index e0d0279..556c0b9 100644
udev_device_get_properties_list_entry(udev)) {
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 646c156..768ab83 100644
index 101e1a88..b4837b15 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1235,16 +1235,14 @@ keywords. Both are regular expressions. For a full description of these keywords
@@ -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,20 +58,49 @@ index 646c156..768ab83 100644
+least one whitelisted udev property;
otherwise they're treated as blacklisted, and the message
"\fIblacklisted, udev property missing\fR" is displayed in the logs.
-.
-.RS
+For example, setting the property blacklist_exception to
+\fB(SCSI_IDENT_|ID_WWN)\fR, will cause well-behaved SCSI devices and devices
+that provide a WWN (World Wide Number) to be included, and all others to be
+excluded. This works to exclude most non-multipathable devices.
.
.RS
.PP
@@ -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.
-.PP
-The default \fIblacklist exception\fR is: \fB(SCSI_IDENT_|ID_WWN)\fR, causing
-well-behaved SCSI devices and devices that provide a WWN (World Wide Number)
-to be included, and all others to be excluded.
-.RE
+For example, setting the property blacklist_exception to
+\fB(SCSI_IDENT_|ID_WWN)\fR, will cause well-behaved SCSI devices and devices
+that provide a WWN (World Wide Number) to be included, and all others to be
+excluded. This works to exclude most non-multipathable devices.
.TP
.B protocol
Regular expression for the protocol of a device to be excluded/included.
diff --git a/tests/blacklist.c b/tests/blacklist.c
index 362c44d9..ea284939 100644
--- a/tests/blacklist.c
+++ b/tests/blacklist.c
@@ -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");
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, ""),
@@ -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;
- expect_condlog(3, "sdb: blacklisted, udev property missing\n");
- assert_int_equal(filter_path(&conf, &miss1_pp),
- MATCH_PROPERTY_BLIST_MISSING);
+ assert_int_equal(filter_path(&conf, &miss1_pp), MATCH_NOTHING);
}
/* This one matches the property whitelist, to test the other missing
--
2.17.2

View File

@ -1,4 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
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
@ -20,7 +20,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
5 files changed, 20 insertions(+)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 141f092..544d2fb 100644
index 20e3b8bf..c36bc69c 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -26,6 +26,7 @@
@ -31,7 +31,7 @@ index 141f092..544d2fb 100644
static int
hwe_strmatch (const struct hwentry *hwe1, const struct hwentry *hwe2)
@@ -745,6 +746,20 @@ load_config (char * file)
@@ -743,6 +744,20 @@ load_config (char * file)
goto out;
}
factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
@ -53,7 +53,7 @@ index 141f092..544d2fb 100644
conf->processed_main_config = 1;
diff --git a/libmultipath/config.h b/libmultipath/config.h
index f5bf5b1..8803967 100644
index ffec3103..6dbf553d 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -9,6 +9,7 @@
@ -65,7 +65,7 @@ index f5bf5b1..8803967 100644
/*
* In kernel, fast_io_fail == 0 means immediate failure on rport delete.
diff --git a/multipath/multipath.rules b/multipath/multipath.rules
index 9df11a9..0486bf7 100644
index 9df11a95..0486bf70 100644
--- a/multipath/multipath.rules
+++ b/multipath/multipath.rules
@@ -9,6 +9,7 @@ IMPORT{cmdline}="nompath"
@ -77,10 +77,10 @@ index 9df11a9..0486bf7 100644
ENV{DEVTYPE}!="partition", GOTO="test_dev"
IMPORT{parent}="DM_MULTIPATH_DEVICE_PATH"
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8
index 94c3f97..ed13efd 100644
index 048a838d..8bd47a80 100644
--- a/multipathd/multipathd.8
+++ b/multipathd/multipathd.8
@@ -38,6 +38,8 @@ map regains its maximum performance and redundancy.
@@ -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.
@ -90,7 +90,7 @@ index 94c3f97..ed13efd 100644
.
.\" ----------------------------------------------------------------------------
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
index ba24983..17434ce 100644
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

View File

@ -1,4 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
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
@ -13,10 +13,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 2f0bcea..b98800a 100644
index 2e8946ca..1b2f47a8 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -83,15 +83,23 @@ TEST_CC_OPTION = $(shell \
@@ -88,15 +88,23 @@ TEST_CC_OPTION = $(shell \
echo "$(2)"; \
fi)

View File

@ -1,4 +1,4 @@
From 0000000000000000000000000000000000000000 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
@ -21,10 +21,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
create mode 100644 multipath/mpathconf.8
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 544d2fb..deb80c2 100644
index c36bc69c..fcd17dd4 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -748,6 +748,8 @@ load_config (char * 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.");
@ -34,7 +34,7 @@ index 544d2fb..deb80c2 100644
conf->blist_devnode = vector_alloc();
if (!conf->blist_devnode) {
diff --git a/multipath/Makefile b/multipath/Makefile
index b9bbb3c..e720c7f 100644
index b9bbb3cf..e720c7f6 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -18,10 +18,12 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
@ -69,7 +69,7 @@ index b9bbb3c..e720c7f 100644
$(RM) core *.o $(EXEC) *.gz
diff --git a/multipath/mpathconf b/multipath/mpathconf
new file mode 100644
index 0000000..e839134
index 00000000..e8391347
--- /dev/null
+++ b/multipath/mpathconf
@@ -0,0 +1,464 @@
@ -539,7 +539,7 @@ index 0000000..e839134
+fi
diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8
new file mode 100644
index 0000000..5b7ae0c
index 00000000..5b7ae0c3
--- /dev/null
+++ b/multipath/mpathconf.8
@@ -0,0 +1,119 @@

View File

@ -1,4 +1,4 @@
From 0000000000000000000000000000000000000000 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
@ -22,10 +22,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
5 files changed, 60 insertions(+), 3 deletions(-)
diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
index 53e7951..39e08cd 100644
index ef748125..349da8b7 100644
--- a/libmultipath/wwids.c
+++ b/libmultipath/wwids.c
@@ -443,3 +443,47 @@ int op ## _wwid(const char *wwid) \
@@ -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)
@ -74,7 +74,7 @@ index 53e7951..39e08cd 100644
+ return ret;
+}
diff --git a/libmultipath/wwids.h b/libmultipath/wwids.h
index 0c6ee54..e32a0b0 100644
index 0c6ee54d..e32a0b0e 100644
--- a/libmultipath/wwids.h
+++ b/libmultipath/wwids.h
@@ -17,6 +17,7 @@ int remember_wwid(char *wwid);
@ -86,19 +86,19 @@ index 0c6ee54..e32a0b0 100644
enum {
WWID_IS_NOT_FAILED = 0,
diff --git a/multipath/main.c b/multipath/main.c
index 69141db..e7771c0 100644
index 4f4d8e89..22aff7be 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -133,7 +133,7 @@ usage (char * progname)
{
fprintf (stderr, VERSION_STRING);
fprintf (stderr, "Usage:\n");
- fprintf (stderr, " %s [-a|-c|-w|-W] [-d] [-r] [-i] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname);
+ fprintf (stderr, " %s [-a|-A|-c|-w|-W] [-d] [-r] [-i] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname);
fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [-R num] [dev]\n", progname);
fprintf (stderr, " %s -F [-v lvl] [-R num]\n", progname);
fprintf (stderr, " %s [-t|-T]\n", progname);
@@ -147,6 +147,8 @@ usage (char * progname)
@@ -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"
@ -107,7 +107,7 @@ index 69141db..e7771c0 100644
" -c check if a device should be a path in a multipath device\n"
" -C check if a multipath device has usable paths\n"
" -q allow queue_if_no_path when multipathd is not running\n"
@@ -870,7 +872,7 @@ main (int argc, char *argv[])
@@ -905,7 +907,7 @@ main (int argc, char *argv[])
exit(RTVL_FAIL);
multipath_conf = conf;
conf->retrigger_tries = 0;
@ -116,7 +116,7 @@ index 69141db..e7771c0 100644
switch(arg) {
case 1: printf("optarg : %s\n",optarg);
break;
@@ -940,6 +942,10 @@ main (int argc, char *argv[])
@@ -975,6 +977,10 @@ main (int argc, char *argv[])
case 'T':
cmd = CMD_DUMP_CONFIG;
break;
@ -128,7 +128,7 @@ index 69141db..e7771c0 100644
usage(argv[0]);
exit(RTVL_OK);
diff --git a/multipath/multipath.8 b/multipath/multipath.8
index 9cdd05a..8befc45 100644
index 9cdd05a3..8befc45a 100644
--- a/multipath/multipath.8
+++ b/multipath/multipath.8
@@ -63,7 +63,7 @@ multipath \- Device mapper target autoconfig.
@ -153,7 +153,7 @@ index 9cdd05a..8befc45 100644
Remove the WWID for the specified device from the WWIDs file.
.
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
index 17434ce..0fbcc46 100644
index 17434cef..0fbcc46b 100644
--- a/multipathd/multipathd.service
+++ b/multipathd/multipathd.service
@@ -15,6 +15,7 @@ Type=notify

View File

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

View File

@ -1,4 +1,4 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
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
@ -16,7 +16,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
3 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index 96815f8..3b1b652 100644
index 1b3d0373..695c8404 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -58,6 +58,21 @@ set_str(vector strvec, void *ptr)
@ -41,7 +41,7 @@ index 96815f8..3b1b652 100644
static int
set_yes_no(vector strvec, void *ptr)
{
@@ -1386,7 +1401,7 @@ ble_ ## option ## _handler (struct config *conf, vector strvec) \
@@ -1422,7 +1437,7 @@ ble_ ## option ## _handler (struct config *conf, vector strvec) \
if (!conf->option) \
return 1; \
\
@ -50,7 +50,7 @@ index 96815f8..3b1b652 100644
if (!buff) \
return 1; \
\
@@ -1402,7 +1417,7 @@ ble_ ## option ## _ ## name ## _handler (struct config *conf, vector strvec) \
@@ -1438,7 +1453,7 @@ ble_ ## option ## _ ## name ## _handler (struct config *conf, vector strvec) \
if (!conf->option) \
return 1; \
\
@ -59,7 +59,7 @@ index 96815f8..3b1b652 100644
if (!buff) \
return 1; \
\
@@ -1505,16 +1520,16 @@ device_handler(struct config *conf, vector strvec)
@@ -1541,16 +1556,16 @@ device_handler(struct config *conf, vector strvec)
return 0;
}
@ -81,11 +81,11 @@ index 96815f8..3b1b652 100644
declare_hw_handler(hwhandler, set_str)
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
index 92ef7cf..4289336 100644
index e00c5fff..15495d26 100644
--- a/libmultipath/parser.c
+++ b/libmultipath/parser.c
@@ -384,6 +384,19 @@ set_value(vector strvec)
return alloc;
@@ -382,6 +382,19 @@ oom:
return NULL;
}
+void *
@ -105,7 +105,7 @@ index 92ef7cf..4289336 100644
static int kw_level = 0;
diff --git a/libmultipath/parser.h b/libmultipath/parser.h
index 62906e9..b791705 100644
index 62906e98..b7917052 100644
--- a/libmultipath/parser.h
+++ b/libmultipath/parser.h
@@ -77,6 +77,7 @@ extern void dump_keywords(vector keydump, int level);

View File

@ -1,4 +1,4 @@
From 0000000000000000000000000000000000000000 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
@ -12,10 +12,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index 6576939..2ad6308 100644
index 4dfe007c..d910da51 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -17,7 +17,7 @@
@@ -20,7 +20,7 @@
#define DEFAULT_NO_PATH_RETRY NO_PATH_RETRY_UNDEF
#define DEFAULT_VERBOSITY 2
#define DEFAULT_REASSIGN_MAPS 0

View File

@ -1,4 +1,4 @@
From 0000000000000000000000000000000000000000 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 compilation warning
@ -9,7 +9,7 @@ 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 adb192b..bfd10ef 100644
index adb192b6..bfd10ef8 100644
--- a/libmultipath/nvme/argconfig.h
+++ b/libmultipath/nvme/argconfig.h
@@ -76,7 +76,7 @@ struct argconfig_commandline_options {

View File

@ -1,4 +1,4 @@
From 0000000000000000000000000000000000000000 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,7 +13,7 @@ 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 990d935..d84571b 100644
index 2673d9d9..f34ade28 100644
--- a/libmultipath/prioritizers/ana.c
+++ b/libmultipath/prioritizers/ana.c
@@ -24,6 +24,7 @@

View File

@ -1,43 +1,45 @@
Name: device-mapper-multipath
Version: 0.8.0
Release: 3%{?dist}
Version: 0.8.2
Release: 1%{?dist}
Summary: Tools to manage multipath devices using device-mapper
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 "https://git.opensvc.com/?p=multipath-tools/.git;a=snapshot;h=17a6101;sf=tgz" -o multipath-tools-17a6101.tgz
Source0: multipath-tools-0.8.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-BZ-1668693-disable-user_friendly_names-for-NetApp.patch
Patch0002: 0002-libmultipath-handle-existing-paths-in-marginal_path-.patch
Patch0003: 0003-multipathd-cleanup-marginal-paths-checking-timers.patch
Patch0004: 0004-libmultipath-fix-marginal-paths-queueing-errors.patch
Patch0005: 0005-libmultipath-fix-marginal_paths-nr_active-check.patch
Patch0006: 0006-multipathd-Fix-miscounting-active-paths.patch
Patch0007: 0007-multipathd-ignore-failed-wwid-recheck.patch
Patch0008: 0008-libmutipath-continue-to-use-old-state-on-PATH_PENDIN.patch
Patch0009: 0009-multipathd-use-update_path_groups-instead-of-reload_.patch
Patch0010: 0010-multipath.conf-add-missing-options-to-man-page.patch
Patch0011: 0011-libmultipath-add-get_uid-fallback-code-for-NVMe-devi.patch
Patch0012: 0012-libmulitpath-cleanup-uid_fallback-code.patch
Patch0013: 0013-multipathd-handle-changed-wwids-by-removal-and-addit.patch
Patch0014: 0014-multipathd-remove-wwid_changed-path-attribute.patch
Patch0015: 0015-multipathd-ignore-disable_changed_wwids.patch
Patch0016: 0016-multipathd-Don-t-use-fallback-code-after-getting-wwi.patch
Patch0017: 0017-libmultipath-silence-dm_is_mpath-error-messages.patch
Patch0018: 0018-RH-fixup-udev-rules-for-redhat.patch
Patch0019: 0019-RH-Remove-the-property-blacklist-exception-builtin.patch
Patch0020: 0020-RH-don-t-start-without-a-config-file.patch
Patch0021: 0021-RH-use-rpm-optflags-if-present.patch
Patch0022: 0022-RH-add-mpathconf.patch
Patch0023: 0023-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch
Patch0024: 0024-RH-warn-on-invalid-regex-instead-of-failing.patch
Patch0025: 0025-RH-reset-default-find_mutipaths-value-to-off.patch
Patch0026: 0026-RH-Fix-nvme-compilation-warning.patch
Patch0027: 0027-Fix-systemd-version-detection.patch
Patch0028: 0028-RH-attempt-to-get-ANA-info-via-sysfs-first.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
# runtime
Requires: %{name}-libs = %{version}-%{release}
@ -120,7 +122,7 @@ 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.8.0 -p1
%autosetup -n multipath-tools-0.8.2 -p1
cp %{SOURCE1} .
%build
@ -232,6 +234,35 @@ fi
%{_pkgconfdir}/libdmmp.pc
%changelog
* Wed Sep 11 2019 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.2-1
- Update Source to upstream version 0.8.2
* Previoud patches 0001-0017 & 0027 are included in this commit
- Rename files
* Previous patches 0018-0026 & 0028 are not patches 0021-0030
- Add 0001-libmultipath-make-vector_foreach_slot_backwards-work.patch
- Add 0002-libmultipath-add-marginal-paths-and-groups-infrastru.patch
- Add 0003-tests-add-path-grouping-policy-unit-tests.patch
- Add 0004-libmultipath-add-wrapper-function-around-pgpolicyfn.patch
- Add 0005-tests-update-pgpolicy-tests-to-work-with-group_paths.patch
- Add 0006-libmultipath-fix-double-free-in-pgpolicyfn-error-pat.patch
- Add 0007-libmultipath-consolidate-group_by_-functions.patch
- Add 0008-libmultipath-make-pgpolicyfn-take-a-paths-vector.patch
- Add 0009-libmultipath-make-group_paths-handle-marginal-paths.patch
- Add 0010-tests-add-tests-for-grouping-marginal-paths.patch
- Add 0011-libmultipath-add-marginal_pathgroups-config-option.patch
- Add 0012-libmutipath-deprecate-delay_-_checks.patch
- Add 0013-multipathd-use-marginal_pathgroups.patch
- Add 0014-multipath-update-man-pages.patch
* The above 13 patches add the marinal_pathgroups option
- Add 0015-multipath.conf-add-enable_foreign-parameter.patch
- Add 0016-multipath.conf.5-document-foreign-library-support.patch
* The above 2 patches add the enable_foreign option
- Add 0017-mpathpersist-remove-broken-unused-code.patch
- Add 0018-libmultipath-EMC-PowerMax-NVMe-device-config.patch
- Add 0019-mpathpersist-fix-leaks.patch
- Add 0020-libmultipath-fix-mpcontext-initialization.patch
* The above 20 patches have been submitted upstream
* Wed Jul 24 2019 Fedora Release Engineering <releng@fedoraproject.org> - 0.8.0-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild

View File

@ -1,2 +1,2 @@
SHA512 (multipath-tools-0.8.0.tgz) = e2ed6936f76da8b703babea22b6b02be19abea3ba55105a13596f306e483c453d105316c2416027be3524e49834ea27ff745963e86e933ffe4c9ee729a2371ba
SHA512 (multipath-tools-0.8.2.tgz) = 31cc4054a2f645fa40b7a16aa8715871b848167a32bf3f34e1c900714f61a46f5d79cbda373bda7f8a8fd2280b96e045c1fd27f4b87aa84fc5305097d72edcd6
SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942