device-mapper-multipath-0.8.6-1
Update Source to upstream version 0.8.6 * Previous patches 0001-0146 are included in the commit Rename files * Previous patches 0147-0156 are now patches 0001-0010 sync tests with RHEL repository
This commit is contained in:
parent
b05147c356
commit
ac4e55e1c0
1
.gitignore
vendored
1
.gitignore
vendored
@ -21,3 +21,4 @@ multipath-tools-091027.tar.gz
|
||||
/multipath-tools-0.8.2.tgz
|
||||
/multipath-tools-0.8.4.tgz
|
||||
/multipath-tools-0.8.5.tgz
|
||||
/multipath-tools-0.8.6.tgz
|
||||
|
@ -1,27 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Varoqui <christophe.varoqui@opensvc.com>
|
||||
Date: Mon, 14 Dec 2020 11:05:24 +0100
|
||||
Subject: [PATCH] Change the multipath.conf manpage uxsock_timeout default
|
||||
value
|
||||
|
||||
Fixes: 7db0c44 ("multipathd: Set CLI timeout correctly")
|
||||
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipath/multipath.conf.5 | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
||||
index d2101ed6..7242d39b 100644
|
||||
--- a/multipath/multipath.conf.5
|
||||
+++ b/multipath/multipath.conf.5
|
||||
@@ -1153,7 +1153,7 @@ In these cases it is recommended to increase the CLI timeout to avoid
|
||||
those issues.
|
||||
.RS
|
||||
.TP
|
||||
-The default is: \fB1000\fR
|
||||
+The default is: \fB4000\fR
|
||||
.RE
|
||||
.
|
||||
.
|
@ -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 05429307..24e943d5 100644
|
||||
index f1e23131..c593fd3b 100644
|
||||
--- a/Makefile.inc
|
||||
+++ b/Makefile.inc
|
||||
@@ -53,7 +53,7 @@ endif
|
||||
@@ -55,7 +55,7 @@ endif
|
||||
prefix =
|
||||
exec_prefix = $(prefix)
|
||||
usr_prefix = $(prefix)
|
@ -1,24 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 16 Sep 2020 21:59:11 +0200
|
||||
Subject: [PATCH] libmultipath: find_mpe(): don't match with empty WWID
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/config.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||
index b9bdbdbc..df0f8f45 100644
|
||||
--- a/libmultipath/config.c
|
||||
+++ b/libmultipath/config.c
|
||||
@@ -147,7 +147,7 @@ struct mpentry *find_mpe(vector mptable, char *wwid)
|
||||
int i;
|
||||
struct mpentry * mpe;
|
||||
|
||||
- if (!wwid)
|
||||
+ if (!wwid || !*wwid)
|
||||
return NULL;
|
||||
|
||||
vector_foreach_slot (mptable, mpe, i)
|
@ -1,257 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 16 Sep 2020 22:22:36 +0200
|
||||
Subject: [PATCH] libmultipath: copy mpp->hwe from pp->hwe
|
||||
|
||||
Since f0462f0 ("libmultipath: use vector for for pp->hwe and mp->hwe"),
|
||||
we've been trying to fix issues caused by paths getting freed and mpp->hwe
|
||||
dangling. This approach couldn't work because we need mpp->hwe to persist,
|
||||
even if all paths are removed from the map. Before f0462f0, a simple
|
||||
assignment worked, because the lifetime of the hwe wasn't bound to the
|
||||
path. But now, we need to copy the vector. It turns out that we need to set
|
||||
mpp->hwe only in two places, add_map_with_path() and setup_map(), and
|
||||
that the code is simplified overall.
|
||||
|
||||
Even now, it can happen that a map is added with add_map_without_paths(),
|
||||
and has no paths. In that case, calling do_set_from_hwe() with a NULL
|
||||
pointer is not a bug, so remove the message.
|
||||
|
||||
Fixes: f0462f0 ("libmultipath: use vector for for pp->hwe and mp->hwe")
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/configure.c | 7 +++++
|
||||
libmultipath/propsel.c | 4 +--
|
||||
libmultipath/structs.c | 15 +++++++++++
|
||||
libmultipath/structs.h | 1 +
|
||||
libmultipath/structs_vec.c | 54 ++++++++++++++++----------------------
|
||||
multipathd/main.c | 10 -------
|
||||
6 files changed, 46 insertions(+), 45 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
||||
index 6fb477fc..d7afc915 100644
|
||||
--- a/libmultipath/configure.c
|
||||
+++ b/libmultipath/configure.c
|
||||
@@ -311,6 +311,13 @@ int setup_map(struct multipath *mpp, char *params, int params_size,
|
||||
if (mpp->disable_queueing && VECTOR_SIZE(mpp->paths) != 0)
|
||||
mpp->disable_queueing = 0;
|
||||
|
||||
+ /*
|
||||
+ * If this map was created with add_map_without_path(),
|
||||
+ * mpp->hwe might not be set yet.
|
||||
+ */
|
||||
+ if (!mpp->hwe)
|
||||
+ extract_hwe_from_path(mpp);
|
||||
+
|
||||
/*
|
||||
* properties selectors
|
||||
*
|
||||
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
||||
index 7e6e0d68..40201344 100644
|
||||
--- a/libmultipath/propsel.c
|
||||
+++ b/libmultipath/propsel.c
|
||||
@@ -65,9 +65,7 @@ do { \
|
||||
__do_set_from_vec(struct hwentry, var, (src)->hwe, dest)
|
||||
|
||||
#define do_set_from_hwe(var, src, dest, msg) \
|
||||
- if (!src->hwe) { \
|
||||
- condlog(0, "BUG: do_set_from_hwe called with hwe == NULL"); \
|
||||
- } else if (__do_set_from_hwe(var, src, dest)) { \
|
||||
+ if (src->hwe && __do_set_from_hwe(var, src, dest)) { \
|
||||
origin = msg; \
|
||||
goto out; \
|
||||
}
|
||||
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
|
||||
index 464596fc..2efad6f0 100644
|
||||
--- a/libmultipath/structs.c
|
||||
+++ b/libmultipath/structs.c
|
||||
@@ -234,6 +234,17 @@ alloc_multipath (void)
|
||||
return mpp;
|
||||
}
|
||||
|
||||
+void *set_mpp_hwe(struct multipath *mpp, const struct path *pp)
|
||||
+{
|
||||
+ if (!mpp || !pp || !pp->hwe)
|
||||
+ return NULL;
|
||||
+ if (mpp->hwe)
|
||||
+ return mpp->hwe;
|
||||
+ mpp->hwe = vector_convert(NULL, pp->hwe,
|
||||
+ struct hwentry, identity);
|
||||
+ return mpp->hwe;
|
||||
+}
|
||||
+
|
||||
void free_multipath_attributes(struct multipath *mpp)
|
||||
{
|
||||
if (!mpp)
|
||||
@@ -290,6 +301,10 @@ free_multipath (struct multipath * mpp, enum free_path_mode free_paths)
|
||||
|
||||
free_pathvec(mpp->paths, free_paths);
|
||||
free_pgvec(mpp->pg, free_paths);
|
||||
+ if (mpp->hwe) {
|
||||
+ vector_free(mpp->hwe);
|
||||
+ mpp->hwe = NULL;
|
||||
+ }
|
||||
FREE_PTR(mpp->mpcontext);
|
||||
FREE(mpp);
|
||||
}
|
||||
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
||||
index 7de93d6c..4ce30551 100644
|
||||
--- a/libmultipath/structs.h
|
||||
+++ b/libmultipath/structs.h
|
||||
@@ -422,6 +422,7 @@ struct host_group {
|
||||
struct path * alloc_path (void);
|
||||
struct pathgroup * alloc_pathgroup (void);
|
||||
struct multipath * alloc_multipath (void);
|
||||
+void *set_mpp_hwe(struct multipath *mpp, const struct path *pp);
|
||||
void uninitialize_path(struct path *pp);
|
||||
void free_path (struct path *);
|
||||
void free_pathvec (vector vec, enum free_path_mode free_paths);
|
||||
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
|
||||
index 8895fa77..f7f45f11 100644
|
||||
--- a/libmultipath/structs_vec.c
|
||||
+++ b/libmultipath/structs_vec.c
|
||||
@@ -294,11 +294,6 @@ err:
|
||||
void orphan_path(struct path *pp, const char *reason)
|
||||
{
|
||||
condlog(3, "%s: orphan path, %s", pp->dev, reason);
|
||||
- if (pp->mpp && pp->hwe && pp->mpp->hwe == pp->hwe) {
|
||||
- condlog(0, "BUG: orphaning path %s that holds hwe of %s",
|
||||
- pp->dev, pp->mpp->alias);
|
||||
- pp->mpp->hwe = NULL;
|
||||
- }
|
||||
pp->mpp = NULL;
|
||||
uninitialize_path(pp);
|
||||
}
|
||||
@@ -308,8 +303,6 @@ void orphan_paths(vector pathvec, struct multipath *mpp, const char *reason)
|
||||
int i;
|
||||
struct path * pp;
|
||||
|
||||
- /* Avoid BUG message from orphan_path() */
|
||||
- mpp->hwe = NULL;
|
||||
vector_foreach_slot (pathvec, pp, i) {
|
||||
if (pp->mpp == mpp) {
|
||||
if (pp->initialized == INIT_REMOVED) {
|
||||
@@ -397,24 +390,26 @@ extract_hwe_from_path(struct multipath * mpp)
|
||||
if (mpp->hwe || !mpp->paths)
|
||||
return;
|
||||
|
||||
- condlog(3, "%s: searching paths for valid hwe", mpp->alias);
|
||||
+ condlog(4, "%s: searching paths for valid hwe", mpp->alias);
|
||||
/* doing this in two passes seems like paranoia to me */
|
||||
vector_foreach_slot(mpp->paths, pp, i) {
|
||||
- if (pp->state != PATH_UP)
|
||||
- continue;
|
||||
- if (pp->hwe) {
|
||||
- mpp->hwe = pp->hwe;
|
||||
- return;
|
||||
- }
|
||||
+ if (pp->state == PATH_UP &&
|
||||
+ pp->initialized != INIT_REMOVED && pp->hwe)
|
||||
+ goto done;
|
||||
}
|
||||
vector_foreach_slot(mpp->paths, pp, i) {
|
||||
- if (pp->state == PATH_UP)
|
||||
- continue;
|
||||
- if (pp->hwe) {
|
||||
- mpp->hwe = pp->hwe;
|
||||
- return;
|
||||
- }
|
||||
+ if (pp->state != PATH_UP &&
|
||||
+ pp->initialized != INIT_REMOVED && pp->hwe)
|
||||
+ goto done;
|
||||
}
|
||||
+done:
|
||||
+ if (i < VECTOR_SIZE(mpp->paths))
|
||||
+ (void)set_mpp_hwe(mpp, pp);
|
||||
+
|
||||
+ if (mpp->hwe)
|
||||
+ condlog(3, "%s: got hwe from path %s", mpp->alias, pp->dev);
|
||||
+ else
|
||||
+ condlog(2, "%s: no hwe found", mpp->alias);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -514,8 +509,6 @@ void sync_paths(struct multipath *mpp, vector pathvec)
|
||||
}
|
||||
if (!found) {
|
||||
condlog(3, "%s dropped path %s", mpp->alias, pp->dev);
|
||||
- if (mpp->hwe == pp->hwe)
|
||||
- mpp->hwe = NULL;
|
||||
vector_del_slot(mpp->paths, i--);
|
||||
orphan_path(pp, "path removed externally");
|
||||
}
|
||||
@@ -524,8 +517,6 @@ void sync_paths(struct multipath *mpp, vector pathvec)
|
||||
update_mpp_paths(mpp, pathvec);
|
||||
vector_foreach_slot (mpp->paths, pp, i)
|
||||
pp->mpp = mpp;
|
||||
- if (mpp->hwe == NULL)
|
||||
- extract_hwe_from_path(mpp);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -701,9 +692,15 @@ struct multipath *add_map_with_path(struct vectors *vecs, struct path *pp,
|
||||
|
||||
conf = get_multipath_config();
|
||||
mpp->mpe = find_mpe(conf->mptable, pp->wwid);
|
||||
- mpp->hwe = pp->hwe;
|
||||
put_multipath_config(conf);
|
||||
|
||||
+ /*
|
||||
+ * We need to call this before select_alias(),
|
||||
+ * because that accesses hwe properties.
|
||||
+ */
|
||||
+ if (pp->hwe && !set_mpp_hwe(mpp, pp))
|
||||
+ goto out;
|
||||
+
|
||||
strcpy(mpp->wwid, pp->wwid);
|
||||
find_existing_alias(mpp, vecs);
|
||||
if (select_alias(conf, mpp))
|
||||
@@ -754,12 +751,6 @@ int verify_paths(struct multipath *mpp)
|
||||
vector_del_slot(mpp->paths, i);
|
||||
i--;
|
||||
|
||||
- /* Make sure mpp->hwe doesn't point to freed memory.
|
||||
- * We call extract_hwe_from_path() below to restore
|
||||
- * mpp->hwe
|
||||
- */
|
||||
- if (mpp->hwe == pp->hwe)
|
||||
- mpp->hwe = NULL;
|
||||
/*
|
||||
* Don't delete path from pathvec yet. We'll do this
|
||||
* after the path has been removed from the map, in
|
||||
@@ -771,7 +762,6 @@ int verify_paths(struct multipath *mpp)
|
||||
mpp->alias, pp->dev, pp->dev_t);
|
||||
}
|
||||
}
|
||||
- extract_hwe_from_path(mpp);
|
||||
return count;
|
||||
}
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index a4abbb27..eedc6c10 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -1153,13 +1153,6 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map)
|
||||
if (i != -1)
|
||||
vector_del_slot(mpp->paths, i);
|
||||
|
||||
- /*
|
||||
- * Make sure mpp->hwe doesn't point to freed memory
|
||||
- * We call extract_hwe_from_path() below to restore mpp->hwe
|
||||
- */
|
||||
- if (mpp->hwe == pp->hwe)
|
||||
- mpp->hwe = NULL;
|
||||
-
|
||||
/*
|
||||
* remove the map IF removing the last path
|
||||
*/
|
||||
@@ -1191,9 +1184,6 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map)
|
||||
*/
|
||||
}
|
||||
|
||||
- if (mpp->hwe == NULL)
|
||||
- extract_hwe_from_path(mpp);
|
||||
-
|
||||
if (setup_map(mpp, params, PARAMS_SIZE, vecs)) {
|
||||
condlog(0, "%s: failed to setup map for"
|
||||
" removal of path %s", mpp->alias, pp->dev);
|
@ -1,28 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 22 Sep 2020 14:24:41 +0200
|
||||
Subject: [PATCH] libmultipath: dm_map_present_by_uuid(): fix dm_task_create()
|
||||
call
|
||||
|
||||
libmultipath shouldn't call dm_task_create() directly any more.
|
||||
|
||||
Fixes: 90535a3 ("multipath: centralize validation code")
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
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 7f093617..0bc1d16e 100644
|
||||
--- a/libmultipath/devmapper.c
|
||||
+++ b/libmultipath/devmapper.c
|
||||
@@ -836,7 +836,7 @@ dm_map_present_by_uuid(const char *uuid)
|
||||
if (safe_sprintf(prefixed_uuid, UUID_PREFIX "%s", uuid))
|
||||
goto out;
|
||||
|
||||
- if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
|
||||
+ if (!(dmt = libmp_dm_task_create(DM_DEVICE_INFO)))
|
||||
goto out;
|
||||
|
||||
dm_task_no_open_count(dmt);
|
@ -13,10 +13,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
1 file changed, 18 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/Makefile.inc b/Makefile.inc
|
||||
index 24e943d5..e978d306 100644
|
||||
index c593fd3b..87fb39f2 100644
|
||||
--- a/Makefile.inc
|
||||
+++ b/Makefile.inc
|
||||
@@ -90,15 +90,27 @@ TEST_CC_OPTION = $(shell \
|
||||
@@ -92,15 +92,27 @@ TEST_CC_OPTION = $(shell \
|
||||
echo "$(2)"; \
|
||||
fi)
|
||||
|
||||
@ -49,7 +49,7 @@ index 24e943d5..e978d306 100644
|
||||
CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \
|
||||
-DBIN_DIR=\"$(bindir)\" -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \
|
||||
-MMD -MP
|
||||
@@ -136,4 +148,4 @@ check_file = $(shell \
|
||||
@@ -138,4 +150,4 @@ check_file = $(shell \
|
||||
|
||||
%.o: %.c
|
||||
@echo building $@ because of $?
|
@ -1,40 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 22 Sep 2020 12:10:35 +0200
|
||||
Subject: [PATCH] libdmmp tests: fix compilation
|
||||
|
||||
These tests don't compile with -Werror=unused-parameter. Fix it.
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libdmmp/test/libdmmp_speed_test.c | 2 +-
|
||||
libdmmp/test/libdmmp_test.c | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/libdmmp/test/libdmmp_speed_test.c b/libdmmp/test/libdmmp_speed_test.c
|
||||
index 372cd390..d91ba50a 100644
|
||||
--- a/libdmmp/test/libdmmp_speed_test.c
|
||||
+++ b/libdmmp/test/libdmmp_speed_test.c
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#include <libdmmp/libdmmp.h>
|
||||
|
||||
-int main(int argc, char *argv[])
|
||||
+int main(void)
|
||||
{
|
||||
struct dmmp_context *ctx = NULL;
|
||||
struct dmmp_mpath **dmmp_mps = NULL;
|
||||
diff --git a/libdmmp/test/libdmmp_test.c b/libdmmp/test/libdmmp_test.c
|
||||
index d944e1e3..a940b576 100644
|
||||
--- a/libdmmp/test/libdmmp_test.c
|
||||
+++ b/libdmmp/test/libdmmp_test.c
|
||||
@@ -102,7 +102,7 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
-int main(int argc, char *argv[])
|
||||
+int main(void)
|
||||
{
|
||||
struct dmmp_context *ctx = NULL;
|
||||
struct dmmp_mpath **dmmp_mps = NULL;
|
@ -1,50 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Fri, 18 Sep 2020 23:57:22 +0200
|
||||
Subject: [PATCH] libmultipath: prio: constify some function parameters
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/prio.c | 4 ++--
|
||||
libmultipath/prio.h | 4 ++--
|
||||
2 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/prio.c b/libmultipath/prio.c
|
||||
index 194563c4..3a718ba5 100644
|
||||
--- a/libmultipath/prio.c
|
||||
+++ b/libmultipath/prio.c
|
||||
@@ -18,7 +18,7 @@ unsigned int get_prio_timeout(unsigned int timeout_ms,
|
||||
return default_timeout;
|
||||
}
|
||||
|
||||
-int init_prio (char *multipath_dir)
|
||||
+int init_prio (const char *multipath_dir)
|
||||
{
|
||||
if (!add_prio(multipath_dir, DEFAULT_PRIO))
|
||||
return 1;
|
||||
@@ -87,7 +87,7 @@ int prio_set_args (struct prio * p, const char * args)
|
||||
return snprintf(p->args, PRIO_ARGS_LEN, "%s", args);
|
||||
}
|
||||
|
||||
-struct prio * add_prio (char *multipath_dir, char * name)
|
||||
+struct prio * add_prio (const char *multipath_dir, const char * name)
|
||||
{
|
||||
char libname[LIB_PRIO_NAMELEN];
|
||||
struct stat stbuf;
|
||||
diff --git a/libmultipath/prio.h b/libmultipath/prio.h
|
||||
index 599d1d88..26754f78 100644
|
||||
--- a/libmultipath/prio.h
|
||||
+++ b/libmultipath/prio.h
|
||||
@@ -55,9 +55,9 @@ struct prio {
|
||||
|
||||
unsigned int get_prio_timeout(unsigned int checker_timeout,
|
||||
unsigned int default_timeout);
|
||||
-int init_prio (char *);
|
||||
+int init_prio (const char *);
|
||||
void cleanup_prio (void);
|
||||
-struct prio * add_prio (char *, char *);
|
||||
+struct prio * add_prio (const char *, const char *);
|
||||
int prio_getprio (struct prio *, struct path *, unsigned int);
|
||||
void prio_get (char *, struct prio *, char *, char *);
|
||||
void prio_put (struct prio *);
|
@ -1,87 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Fri, 18 Sep 2020 23:58:15 +0200
|
||||
Subject: [PATCH] libmultipath: checkers/prio: allow non-lazy .so loading
|
||||
|
||||
If compiled with -DLOAD_ALL_SHARED_LIBS, all known prioritizers
|
||||
and checkers will be loaded immediately on startup. This is useful
|
||||
for determining symbol usage (start executables with LD_BIND_NOW=1).
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/checkers.c | 17 +++++++++++++++++
|
||||
libmultipath/prio.c | 22 ++++++++++++++++++++++
|
||||
2 files changed, 39 insertions(+)
|
||||
|
||||
diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c
|
||||
index f7ddd536..18b1f5eb 100644
|
||||
--- a/libmultipath/checkers.c
|
||||
+++ b/libmultipath/checkers.c
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "debug.h"
|
||||
#include "checkers.h"
|
||||
#include "vector.h"
|
||||
+#include "util.h"
|
||||
|
||||
struct checker_class {
|
||||
struct list_head node;
|
||||
@@ -375,7 +376,23 @@ void checker_get(const char *multipath_dir, struct checker *dst,
|
||||
|
||||
int init_checkers(const char *multipath_dir)
|
||||
{
|
||||
+#ifdef LOAD_ALL_SHARED_LIBS
|
||||
+ static const char *const all_checkers[] = {
|
||||
+ DIRECTIO,
|
||||
+ TUR,
|
||||
+ HP_SW,
|
||||
+ RDAC,
|
||||
+ EMC_CLARIION,
|
||||
+ READSECTOR0,
|
||||
+ CCISS_TUR,
|
||||
+ };
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(all_checkers); i++)
|
||||
+ add_checker_class(multipath_dir, all_checkers[i]);
|
||||
+#else
|
||||
if (!add_checker_class(multipath_dir, DEFAULT_CHECKER))
|
||||
return 1;
|
||||
+#endif
|
||||
return 0;
|
||||
}
|
||||
diff --git a/libmultipath/prio.c b/libmultipath/prio.c
|
||||
index 3a718ba5..c92bde7f 100644
|
||||
--- a/libmultipath/prio.c
|
||||
+++ b/libmultipath/prio.c
|
||||
@@ -20,8 +20,30 @@ unsigned int get_prio_timeout(unsigned int timeout_ms,
|
||||
|
||||
int init_prio (const char *multipath_dir)
|
||||
{
|
||||
+#ifdef LOAD_ALL_SHARED_LIBS
|
||||
+ static const char *const all_prios[] = {
|
||||
+ PRIO_ALUA,
|
||||
+ PRIO_CONST,
|
||||
+ PRIO_DATACORE,
|
||||
+ PRIO_EMC,
|
||||
+ PRIO_HDS,
|
||||
+ PRIO_HP_SW,
|
||||
+ PRIO_ONTAP,
|
||||
+ PRIO_RANDOM,
|
||||
+ PRIO_RDAC,
|
||||
+ PRIO_WEIGHTED_PATH,
|
||||
+ PRIO_SYSFS,
|
||||
+ PRIO_PATH_LATENCY,
|
||||
+ PRIO_ANA,
|
||||
+ };
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(all_prios); i++)
|
||||
+ add_prio(multipath_dir, all_prios[i]);
|
||||
+#else
|
||||
if (!add_prio(multipath_dir, DEFAULT_PRIO))
|
||||
return 1;
|
||||
+#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,93 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 22 Sep 2020 12:52:49 +0200
|
||||
Subject: [PATCH] multipath-tools Makefiles: separate rules for .so and man
|
||||
pages
|
||||
|
||||
Rely more on "make" functionality than on sequential command execution.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmpathcmd/Makefile | 8 +++++---
|
||||
libmpathpersist/Makefile | 10 +++++++---
|
||||
libmultipath/Makefile | 8 +++++---
|
||||
3 files changed, 17 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/libmpathcmd/Makefile b/libmpathcmd/Makefile
|
||||
index 0f6b8166..08ccb811 100644
|
||||
--- a/libmpathcmd/Makefile
|
||||
+++ b/libmpathcmd/Makefile
|
||||
@@ -8,13 +8,15 @@ CFLAGS += $(LIB_CFLAGS)
|
||||
|
||||
OBJS = mpath_cmd.o
|
||||
|
||||
-all: $(LIBS)
|
||||
+all: $(DEVLIB)
|
||||
|
||||
$(LIBS): $(OBJS)
|
||||
$(CC) $(LDFLAGS) $(SHARED_FLAGS) -Wl,-soname=$@ -o $@ $(OBJS) $(LIBDEPS)
|
||||
- $(LN) $@ $(DEVLIB)
|
||||
|
||||
-install: $(LIBS)
|
||||
+$(DEVLIB): $(LIBS)
|
||||
+ $(LN) $(LIBS) $@
|
||||
+
|
||||
+install: all
|
||||
$(INSTALL_PROGRAM) -d $(DESTDIR)$(syslibdir)
|
||||
$(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(syslibdir)/$(LIBS)
|
||||
$(LN) $(LIBS) $(DESTDIR)$(syslibdir)/$(DEVLIB)
|
||||
diff --git a/libmpathpersist/Makefile b/libmpathpersist/Makefile
|
||||
index 21fdad80..9e869fdc 100644
|
||||
--- a/libmpathpersist/Makefile
|
||||
+++ b/libmpathpersist/Makefile
|
||||
@@ -11,15 +11,19 @@ LIBDEPS += -lpthread -ldevmapper -ldl -L$(multipathdir) -lmultipath \
|
||||
|
||||
OBJS = mpath_persist.o mpath_updatepr.o mpath_pr_ioctl.o
|
||||
|
||||
-all: $(LIBS)
|
||||
+all: $(DEVLIB) man
|
||||
|
||||
$(LIBS): $(OBJS)
|
||||
$(CC) $(LDFLAGS) $(SHARED_FLAGS) $(LIBDEPS) -Wl,-soname=$@ -o $@ $(OBJS)
|
||||
- $(LN) $(LIBS) $(DEVLIB)
|
||||
+
|
||||
+$(DEVLIB): $(LIBS)
|
||||
+ $(LN) $(LIBS) $@
|
||||
+
|
||||
+man:
|
||||
$(GZIP) mpath_persistent_reserve_in.3 > mpath_persistent_reserve_in.3.gz
|
||||
$(GZIP) mpath_persistent_reserve_out.3 > mpath_persistent_reserve_out.3.gz
|
||||
|
||||
-install: $(LIBS)
|
||||
+install: all
|
||||
$(INSTALL_PROGRAM) -d $(DESTDIR)$(syslibdir)
|
||||
$(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(syslibdir)/$(LIBS)
|
||||
$(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(syslibdir)
|
||||
diff --git a/libmultipath/Makefile b/libmultipath/Makefile
|
||||
index 62ba16e8..40028556 100644
|
||||
--- a/libmultipath/Makefile
|
||||
+++ b/libmultipath/Makefile
|
||||
@@ -54,7 +54,7 @@ OBJS = memory.o parser.o vector.o devmapper.o callout.o \
|
||||
io_err_stat.o dm-generic.o generic.o foreign.o nvme-lib.o \
|
||||
libsg.o valid.o
|
||||
|
||||
-all: $(LIBS)
|
||||
+all: $(DEVLIB)
|
||||
|
||||
nvme-lib.o: nvme-lib.c nvme-ioctl.c nvme-ioctl.h
|
||||
$(CC) $(CFLAGS) -Wno-unused-function -c -o $@ $<
|
||||
@@ -74,9 +74,11 @@ nvme-ioctl.h: nvme/nvme-ioctl.h
|
||||
|
||||
$(LIBS): $(OBJS)
|
||||
$(CC) $(LDFLAGS) $(SHARED_FLAGS) -Wl,-soname=$@ -o $@ $(OBJS) $(LIBDEPS)
|
||||
- $(LN) $@ $(DEVLIB)
|
||||
|
||||
-install:
|
||||
+$(DEVLIB): $(LIBS)
|
||||
+ $(LN) $(LIBS) $@
|
||||
+
|
||||
+install: all
|
||||
$(INSTALL_PROGRAM) -d $(DESTDIR)$(syslibdir)
|
||||
$(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(syslibdir)/$(LIBS)
|
||||
$(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(libdir)
|
@ -1,84 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Sat, 19 Sep 2020 00:29:45 +0200
|
||||
Subject: [PATCH] libmultipath: create separate .so for unit tests
|
||||
|
||||
The unit tests use a lot of internal symbols that we don't want
|
||||
to add to the ABI if we don't have to. As long as we don't
|
||||
have to make incompatible changes to functions, we can work around
|
||||
that by simply using a non-versioned library for the unit tests.
|
||||
Therefore we add a seperate rule here. Do this before actually
|
||||
adding a version script, to avoid breakage during bisection.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/Makefile | 7 +++++++
|
||||
tests/Makefile | 10 ++++++----
|
||||
2 files changed, 13 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/Makefile b/libmultipath/Makefile
|
||||
index 40028556..12bf6300 100644
|
||||
--- a/libmultipath/Makefile
|
||||
+++ b/libmultipath/Makefile
|
||||
@@ -78,6 +78,13 @@ $(LIBS): $(OBJS)
|
||||
$(DEVLIB): $(LIBS)
|
||||
$(LN) $(LIBS) $@
|
||||
|
||||
+../tests/$(LIBS): $(OBJS) $(VERSION_SCRIPT)
|
||||
+ $(CC) $(LDFLAGS) $(SHARED_FLAGS) -Wl,-soname=`basename $@` \
|
||||
+ -o $@ $(OBJS) $(LIBDEPS)
|
||||
+ $(LN) $@ ${@:.so.0=.so}
|
||||
+
|
||||
+test-lib: ../tests/$(LIBS)
|
||||
+
|
||||
install: all
|
||||
$(INSTALL_PROGRAM) -d $(DESTDIR)$(syslibdir)
|
||||
$(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(syslibdir)/$(LIBS)
|
||||
diff --git a/tests/Makefile b/tests/Makefile
|
||||
index d26b3ce7..9658c9fd 100644
|
||||
--- a/tests/Makefile
|
||||
+++ b/tests/Makefile
|
||||
@@ -10,7 +10,7 @@ W_MISSING_INITIALIZERS := $(call TEST_MISSING_INITIALIZERS)
|
||||
|
||||
CFLAGS += $(BIN_CFLAGS) -I$(multipathdir) -I$(mpathcmddir) \
|
||||
-Wno-unused-parameter $(W_MISSING_INITIALIZERS)
|
||||
-LIBDEPS += -L$(multipathdir) -L$(mpathcmddir) -lmultipath -lmpathcmd -lcmocka
|
||||
+LIBDEPS += -L. -L$(mpathcmddir) -lmultipath -lmpathcmd -lcmocka
|
||||
|
||||
TESTS := uevent parser util dmevents hwtable blacklist unaligned vpd pgpolicy \
|
||||
alias directio valid devt
|
||||
@@ -68,7 +68,7 @@ lib/libchecktur.so:
|
||||
|
||||
%.out: %-test lib/libchecktur.so
|
||||
@echo == running $< ==
|
||||
- @LD_LIBRARY_PATH=$(multipathdir):$(mpathcmddir) ./$< >$@
|
||||
+ @LD_LIBRARY_PATH=.:$(mpathcmddir) ./$< >$@
|
||||
|
||||
%.vgr: %-test lib/libchecktur.so
|
||||
@echo == running valgrind for $< ==
|
||||
@@ -78,7 +78,7 @@ lib/libchecktur.so:
|
||||
OBJS = $(TESTS:%=%.o) $(HELPERS)
|
||||
|
||||
test_clean:
|
||||
- $(RM) $(TESTS:%=%.out) $(TESTS:%=%.vgr)
|
||||
+ $(RM) $(TESTS:%=%.out) $(TESTS:%=%.vgr) *.so*
|
||||
|
||||
valgrind_clean:
|
||||
$(RM) $(TESTS:%=%.vgr)
|
||||
@@ -98,12 +98,14 @@ dep_clean:
|
||||
@sed -n 's/^.*__wrap_\([a-zA-Z0-9_]*\).*$$/-Wl,--wrap=\1/p' $< | \
|
||||
sort -u | tr '\n' ' ' >$@
|
||||
|
||||
+libmultipath.so.0:
|
||||
+ $(MAKE) -C $(multipathdir) test-lib
|
||||
|
||||
# COLON will get expanded during second expansion below
|
||||
COLON:=:
|
||||
.SECONDEXPANSION:
|
||||
%-test: %.o %.o.wrap $$($$@_OBJDEPS) $$($$@_TESTDEPS) $$($$@_TESTDEPS$$(COLON).o=.o.wrap) \
|
||||
- $(multipathdir)/libmultipath.so Makefile
|
||||
+ libmultipath.so.0 Makefile
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $< $($@_TESTDEPS) $($@_OBJDEPS) \
|
||||
$(LIBDEPS) $($@_LIBDEPS) \
|
||||
$(shell cat $<.wrap) $(foreach dep,$($@_TESTDEPS),$(shell cat $(dep).wrap))
|
@ -13,7 +13,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
1 file changed, 2 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||
index f8044141..e6590d07 100644
|
||||
index ec99a7aa..2704270e 100644
|
||||
--- a/libmultipath/discovery.c
|
||||
+++ b/libmultipath/discovery.c
|
||||
@@ -1135,12 +1135,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
|
@ -1,300 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Sat, 19 Sep 2020 00:00:18 +0200
|
||||
Subject: [PATCH] libmultipath: add linker version script
|
||||
|
||||
This version script documents the current ABI of libmultipath,
|
||||
as used by multipath, multipathd, (lib)mpathpersist, and the
|
||||
dynamically loaded libraries (prioritizers, checkers, and foreign).
|
||||
The initial version string is set to "LIBMULTIPATH_1.0.0".
|
||||
|
||||
This reduces the amount of exported symbols of libmultipath.so.0
|
||||
by more than a half (199 vs. 434).
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/Makefile | 7 +-
|
||||
libmultipath/libmultipath.version | 248 ++++++++++++++++++++++++++++++
|
||||
2 files changed, 253 insertions(+), 2 deletions(-)
|
||||
create mode 100644 libmultipath/libmultipath.version
|
||||
|
||||
diff --git a/libmultipath/Makefile b/libmultipath/Makefile
|
||||
index 12bf6300..e7254f39 100644
|
||||
--- a/libmultipath/Makefile
|
||||
+++ b/libmultipath/Makefile
|
||||
@@ -6,6 +6,7 @@ include ../Makefile.inc
|
||||
SONAME = 0
|
||||
DEVLIB = libmultipath.so
|
||||
LIBS = $(DEVLIB).$(SONAME)
|
||||
+VERSION_SCRIPT := libmultipath.version
|
||||
|
||||
CFLAGS += $(LIB_CFLAGS) -I$(mpathcmddir) -I$(mpathpersistdir) -I$(nvmedir)
|
||||
|
||||
@@ -72,8 +73,10 @@ nvme-ioctl.c: nvme/nvme-ioctl.c
|
||||
nvme-ioctl.h: nvme/nvme-ioctl.h
|
||||
$(call make_static,$<,$@)
|
||||
|
||||
-$(LIBS): $(OBJS)
|
||||
- $(CC) $(LDFLAGS) $(SHARED_FLAGS) -Wl,-soname=$@ -o $@ $(OBJS) $(LIBDEPS)
|
||||
+
|
||||
+$(LIBS): $(OBJS) $(VERSION_SCRIPT)
|
||||
+ $(CC) $(LDFLAGS) $(SHARED_FLAGS) -Wl,-soname=$@ \
|
||||
+ -Wl,--version-script=$(VERSION_SCRIPT) -o $@ $(OBJS) $(LIBDEPS)
|
||||
|
||||
$(DEVLIB): $(LIBS)
|
||||
$(LN) $(LIBS) $@
|
||||
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
|
||||
new file mode 100644
|
||||
index 00000000..a6bf8218
|
||||
--- /dev/null
|
||||
+++ b/libmultipath/libmultipath.version
|
||||
@@ -0,0 +1,248 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2020 SUSE LLC
|
||||
+ * SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+ *
|
||||
+ * libmultipath ABI
|
||||
+ *
|
||||
+ * libmultipath doesn't have a stable ABI in the usual sense. In particular,
|
||||
+ * the library does not attempt to ship different versions of the same symbol
|
||||
+ * for backward compatibility.
|
||||
+ *
|
||||
+ * The ABI versioning only serves to avoid linking with a non-matching ABI, to
|
||||
+ * cut down the set of exported symbols, and to describe it.
|
||||
+ * The version string is LIBMULTIPATH_$MAJOR.$MINOR.$REL.
|
||||
+ *
|
||||
+ * Policy:
|
||||
+ *
|
||||
+ * * Bump $MAJOR for incompatible changes, like:
|
||||
+ * - symbols removed
|
||||
+ * - parameter list or return values changed for existing functions
|
||||
+ * - externally visible data structures changed in incompatible ways
|
||||
+ * (like offsets of previously existing struct members)
|
||||
+ * In this case, the new version doesn't inherit the previous versions,
|
||||
+ * because the new library doesn't provide the full previous ABI any more.
|
||||
+ * All predecessors are merged into the new version.
|
||||
+ *
|
||||
+ * * Bump $MINOR for compatible changes, like adding symbols.
|
||||
+ * The new version inherits the previous ones.
|
||||
+ *
|
||||
+ * * Bump $REL to describe deviations from upstream, e.g. in
|
||||
+ * multipath-tools packages shipped by distributions.
|
||||
+ * The new version inherits the previous ones.
|
||||
+ */
|
||||
+
|
||||
+LIBMULTIPATH_1.0.0 {
|
||||
+global:
|
||||
+ /* symbols referenced by multipath and multipathd */
|
||||
+ add_foreign;
|
||||
+ add_map_with_path;
|
||||
+ adopt_paths;
|
||||
+ alloc_multipath;
|
||||
+ alloc_path;
|
||||
+ alloc_path_with_pathinfo;
|
||||
+ alloc_strvec;
|
||||
+ change_foreign;
|
||||
+ check_alias_settings;
|
||||
+ checker_clear_message;
|
||||
+ checker_disable;
|
||||
+ checker_enable;
|
||||
+ checker_is_sync;
|
||||
+ checker_message;
|
||||
+ checker_name;
|
||||
+ checker_state_name;
|
||||
+ check_foreign;
|
||||
+ cleanup_checkers;
|
||||
+ cleanup_foreign;
|
||||
+ cleanup_lock;
|
||||
+ cleanup_prio;
|
||||
+ close_fd;
|
||||
+ coalesce_paths;
|
||||
+ convert_dev;
|
||||
+ count_active_paths;
|
||||
+ delete_all_foreign;
|
||||
+ delete_foreign;
|
||||
+ disassemble_map;
|
||||
+ disassemble_status;
|
||||
+ dlog;
|
||||
+ dm_cancel_deferred_remove;
|
||||
+ dm_drv_version;
|
||||
+ dm_enablegroup;
|
||||
+ dm_fail_path;
|
||||
+ _dm_flush_map;
|
||||
+ dm_flush_map_nopaths;
|
||||
+ dm_flush_maps;
|
||||
+ dm_geteventnr;
|
||||
+ dm_get_info;
|
||||
+ dm_get_major_minor;
|
||||
+ dm_get_map;
|
||||
+ dm_get_maps;
|
||||
+ dm_get_multipath;
|
||||
+ dm_get_status;
|
||||
+ dm_get_uuid;
|
||||
+ dm_is_mpath;
|
||||
+ dm_mapname;
|
||||
+ dm_map_present;
|
||||
+ dm_queue_if_no_path;
|
||||
+ dm_reassign;
|
||||
+ dm_reinstate_path;
|
||||
+ dm_simplecmd_noflush;
|
||||
+ dm_switchgroup;
|
||||
+ dm_tgt_version;
|
||||
+ domap;
|
||||
+ ensure_directories_exist;
|
||||
+ extract_hwe_from_path;
|
||||
+ filter_devnode;
|
||||
+ filter_path;
|
||||
+ filter_wwid;
|
||||
+ find_mp_by_alias;
|
||||
+ find_mp_by_minor;
|
||||
+ find_mp_by_str;
|
||||
+ find_mp_by_wwid;
|
||||
+ find_mpe;
|
||||
+ find_path_by_dev;
|
||||
+ find_path_by_devt;
|
||||
+ find_slot;
|
||||
+ foreign_multipath_layout;
|
||||
+ foreign_path_layout;
|
||||
+ free_config;
|
||||
+ free_multipath;
|
||||
+ free_multipathvec;
|
||||
+ free_path;
|
||||
+ free_pathvec;
|
||||
+ free_strvec;
|
||||
+ get_monotonic_time;
|
||||
+ get_multipath_layout;
|
||||
+ get_path_layout;
|
||||
+ get_pgpolicy_id;
|
||||
+ get_refwwid;
|
||||
+ get_state;
|
||||
+ get_udev_device;
|
||||
+ get_uid;
|
||||
+ get_used_hwes;
|
||||
+ group_by_prio;
|
||||
+ init_checkers;
|
||||
+ init_foreign;
|
||||
+ init_prio;
|
||||
+ io_err_stat_attr;
|
||||
+ io_err_stat_handle_pathfail;
|
||||
+ is_path_valid;
|
||||
+ is_quote;
|
||||
+ libmp_dm_task_create;
|
||||
+ libmp_udev_set_sync_support;
|
||||
+ load_config;
|
||||
+ log_thread_reset;
|
||||
+ log_thread_start;
|
||||
+ log_thread_stop;
|
||||
+ need_io_err_check;
|
||||
+ normalize_timespec;
|
||||
+ orphan_path;
|
||||
+ orphan_paths;
|
||||
+ parse_prkey_flags;
|
||||
+ pathcount;
|
||||
+ path_discovery;
|
||||
+ path_get_tpgs;
|
||||
+ pathinfo;
|
||||
+ path_offline;
|
||||
+ print_all_paths;
|
||||
+ print_foreign_topology;
|
||||
+ _print_multipath_topology;
|
||||
+ pthread_cond_init_mono;
|
||||
+ recv_packet;
|
||||
+ recv_packet_from_client;
|
||||
+ reinstate_paths;
|
||||
+ remember_wwid;
|
||||
+ remove_map;
|
||||
+ remove_map_by_alias;
|
||||
+ remove_maps;
|
||||
+ remove_wwid;
|
||||
+ replace_wwids;
|
||||
+ reset_checker_classes;
|
||||
+ select_all_tg_pt;
|
||||
+ select_action;
|
||||
+ select_find_multipaths_timeout;
|
||||
+ select_no_path_retry;
|
||||
+ select_path_group;
|
||||
+ select_reservation_key;
|
||||
+ send_packet;
|
||||
+ set_max_fds;
|
||||
+ __set_no_path_retry;
|
||||
+ set_path_removed;
|
||||
+ set_prkey;
|
||||
+ setup_map;
|
||||
+ setup_thread_attr;
|
||||
+ should_multipath;
|
||||
+ snprint_blacklist_report;
|
||||
+ snprint_config;
|
||||
+ snprint_devices;
|
||||
+ snprint_foreign_multipaths;
|
||||
+ snprint_foreign_paths;
|
||||
+ snprint_foreign_topology;
|
||||
+ _snprint_multipath;
|
||||
+ snprint_multipath_header;
|
||||
+ snprint_multipath_map_json;
|
||||
+ _snprint_multipath_topology;
|
||||
+ snprint_multipath_topology_json;
|
||||
+ _snprint_path;
|
||||
+ snprint_path_header;
|
||||
+ snprint_status;
|
||||
+ snprint_wildcards;
|
||||
+ stop_io_err_stat_thread;
|
||||
+ store_path;
|
||||
+ store_pathinfo;
|
||||
+ strchop;
|
||||
+ strlcpy;
|
||||
+ sync_map_state;
|
||||
+ sysfs_attr_set_value;
|
||||
+ sysfs_get_size;
|
||||
+ sysfs_is_multipathed;
|
||||
+ timespecsub;
|
||||
+ trigger_paths_udev_change;
|
||||
+ uevent_dispatch;
|
||||
+ uevent_get_dm_str;
|
||||
+ uevent_get_env_positive_int;
|
||||
+ uevent_is_mpath;
|
||||
+ uevent_listen;
|
||||
+ update_mpp_paths;
|
||||
+ update_multipath_status;
|
||||
+ update_multipath_strings;
|
||||
+ update_multipath_table;
|
||||
+ update_pathvec_from_dm;
|
||||
+ update_queue_mode_add_path;
|
||||
+ update_queue_mode_del_path;
|
||||
+ ux_socket_listen;
|
||||
+ valid_alias;
|
||||
+ vector_alloc;
|
||||
+ vector_alloc_slot;
|
||||
+ vector_del_slot;
|
||||
+ vector_free;
|
||||
+ vector_reset;
|
||||
+ vector_set_slot;
|
||||
+ verify_paths;
|
||||
+
|
||||
+ /* checkers */
|
||||
+ sg_read;
|
||||
+
|
||||
+ /* prioritizers */
|
||||
+ get_asymmetric_access_state;
|
||||
+ get_prio_timeout;
|
||||
+ get_target_port_group;
|
||||
+ get_target_port_group_support;
|
||||
+ libmp_nvme_ana_log;
|
||||
+ libmp_nvme_get_nsid;
|
||||
+ libmp_nvme_identify_ns;
|
||||
+ log_nvme_errcode;
|
||||
+ nvme_id_ctrl_ana;
|
||||
+ snprint_host_wwnn;
|
||||
+ snprint_host_wwpn;
|
||||
+ snprint_path_serial;
|
||||
+ snprint_tgt_wwnn;
|
||||
+ snprint_tgt_wwpn;
|
||||
+ sysfs_get_asymmetric_access_state;
|
||||
+
|
||||
+ /* foreign */
|
||||
+ free_scandir_result;
|
||||
+ sysfs_attr_get_value;
|
||||
+
|
||||
+local:
|
||||
+ *;
|
||||
+};
|
@ -1,78 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Sat, 19 Sep 2020 00:02:16 +0200
|
||||
Subject: [PATCH] libmpathpersist: add linker version script
|
||||
|
||||
This defines the ABI of libmpathpersist in the current state.
|
||||
The initial version is set to "LIBMPATHPERSIST_1.0.0".
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmpathpersist/Makefile | 6 +++--
|
||||
libmpathpersist/libmpathpersist.version | 32 +++++++++++++++++++++++++
|
||||
2 files changed, 36 insertions(+), 2 deletions(-)
|
||||
create mode 100644 libmpathpersist/libmpathpersist.version
|
||||
|
||||
diff --git a/libmpathpersist/Makefile b/libmpathpersist/Makefile
|
||||
index 9e869fdc..456ce4cf 100644
|
||||
--- a/libmpathpersist/Makefile
|
||||
+++ b/libmpathpersist/Makefile
|
||||
@@ -3,6 +3,7 @@ include ../Makefile.inc
|
||||
SONAME = 0
|
||||
DEVLIB = libmpathpersist.so
|
||||
LIBS = $(DEVLIB).$(SONAME)
|
||||
+VERSION_SCRIPT := libmpathpersist.version
|
||||
|
||||
CFLAGS += $(LIB_CFLAGS) -I$(multipathdir) -I$(mpathpersistdir) -I$(mpathcmddir)
|
||||
|
||||
@@ -13,8 +14,9 @@ OBJS = mpath_persist.o mpath_updatepr.o mpath_pr_ioctl.o
|
||||
|
||||
all: $(DEVLIB) man
|
||||
|
||||
-$(LIBS): $(OBJS)
|
||||
- $(CC) $(LDFLAGS) $(SHARED_FLAGS) $(LIBDEPS) -Wl,-soname=$@ -o $@ $(OBJS)
|
||||
+$(LIBS): $(OBJS) $(VERSION_SCRIPT)
|
||||
+ $(CC) $(LDFLAGS) $(SHARED_FLAGS) $(LIBDEPS) -Wl,-soname=$@ \
|
||||
+ -Wl,--version-script=$(VERSION_SCRIPT) -o $@ $(OBJS)
|
||||
|
||||
$(DEVLIB): $(LIBS)
|
||||
$(LN) $(LIBS) $@
|
||||
diff --git a/libmpathpersist/libmpathpersist.version b/libmpathpersist/libmpathpersist.version
|
||||
new file mode 100644
|
||||
index 00000000..dc648ce6
|
||||
--- /dev/null
|
||||
+++ b/libmpathpersist/libmpathpersist.version
|
||||
@@ -0,0 +1,32 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2020 SUSE LLC
|
||||
+ * SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+ *
|
||||
+ * libmpathpersist ABI
|
||||
+ *
|
||||
+ * The ABI of libmpathpersist is supposed to remain stable. Removing symbols
|
||||
+ * or altering existing symbols' semantics is not allowed. When changing a
|
||||
+ * a symbol, either use a new name, or explicit symver directives.
|
||||
+ *
|
||||
+ * See libmultipath.version for general policy about version numbers.
|
||||
+ */
|
||||
+LIBMPATHPERSIST_1.0.0 {
|
||||
+global:
|
||||
+
|
||||
+ __mpath_persistent_reserve_in;
|
||||
+ __mpath_persistent_reserve_out;
|
||||
+ dumpHex;
|
||||
+ mpath_alloc_prin_response;
|
||||
+ mpath_lib_exit;
|
||||
+ mpath_lib_init;
|
||||
+ mpath_mx_alloc_len;
|
||||
+ mpath_persistent_reserve_in;
|
||||
+ mpath_persistent_reserve_init_vecs;
|
||||
+ mpath_persistent_reserve_out;
|
||||
+ mpath_persistent_reserve_free_vecs;
|
||||
+ prin_do_scsi_ioctl;
|
||||
+ prout_do_scsi_ioctl;
|
||||
+ update_map_pr;
|
||||
+
|
||||
+local: *;
|
||||
+};
|
@ -1,71 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 22 Sep 2020 12:54:20 +0200
|
||||
Subject: [PATCH] libmpathcmd: add linker version script
|
||||
|
||||
For completeness, this isn't really necessary.
|
||||
The version string is set to "LIBMPATHCMD_1.0.0".
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmpathcmd/Makefile | 6 ++++--
|
||||
libmpathcmd/libmpathcmd.version | 25 +++++++++++++++++++++++++
|
||||
2 files changed, 29 insertions(+), 2 deletions(-)
|
||||
create mode 100644 libmpathcmd/libmpathcmd.version
|
||||
|
||||
diff --git a/libmpathcmd/Makefile b/libmpathcmd/Makefile
|
||||
index 08ccb811..25910194 100644
|
||||
--- a/libmpathcmd/Makefile
|
||||
+++ b/libmpathcmd/Makefile
|
||||
@@ -3,6 +3,7 @@ include ../Makefile.inc
|
||||
SONAME = 0
|
||||
DEVLIB = libmpathcmd.so
|
||||
LIBS = $(DEVLIB).$(SONAME)
|
||||
+VERSION_SCRIPT := libmpathcmd.version
|
||||
|
||||
CFLAGS += $(LIB_CFLAGS)
|
||||
|
||||
@@ -10,8 +11,9 @@ OBJS = mpath_cmd.o
|
||||
|
||||
all: $(DEVLIB)
|
||||
|
||||
-$(LIBS): $(OBJS)
|
||||
- $(CC) $(LDFLAGS) $(SHARED_FLAGS) -Wl,-soname=$@ -o $@ $(OBJS) $(LIBDEPS)
|
||||
+$(LIBS): $(OBJS) $(VERSION_SCRIPT)
|
||||
+ $(CC) $(LDFLAGS) $(SHARED_FLAGS) -Wl,-soname=$@ \
|
||||
+ -Wl,--version-script=$(VERSION_SCRIPT) -o $@ $(OBJS) $(LIBDEPS)
|
||||
|
||||
$(DEVLIB): $(LIBS)
|
||||
$(LN) $(LIBS) $@
|
||||
diff --git a/libmpathcmd/libmpathcmd.version b/libmpathcmd/libmpathcmd.version
|
||||
new file mode 100644
|
||||
index 00000000..f1006280
|
||||
--- /dev/null
|
||||
+++ b/libmpathcmd/libmpathcmd.version
|
||||
@@ -0,0 +1,25 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2020 SUSE LLC
|
||||
+ * SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+ *
|
||||
+ * libmpathcmd ABI
|
||||
+ *
|
||||
+ * The ABI of libmpathcmd is supposed to remain stable. Removing symbols
|
||||
+ * or altering existing symbols' semantics is not allowed. When changing a
|
||||
+ * a symbol, either use a new name, or explicit symver directives.
|
||||
+ *
|
||||
+ * See libmultipath.version for general policy about version numbers.
|
||||
+ */
|
||||
+LIBMPATHCMD_1.0.0 {
|
||||
+global:
|
||||
+ __mpath_connect;
|
||||
+ mpath_connect;
|
||||
+ mpath_disconnect;
|
||||
+ mpath_process_cmd;
|
||||
+ mpath_recv_reply;
|
||||
+ mpath_recv_reply_len;
|
||||
+ mpath_recv_reply_data;
|
||||
+ mpath_send_cmd;
|
||||
+local:
|
||||
+ *;
|
||||
+};
|
@ -1,35 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Fri, 25 Sep 2020 21:37:16 +0200
|
||||
Subject: [PATCH] libmpathpersist: initialize mpp->hwe in get_mpvec()
|
||||
|
||||
In __mpath_persistent_reserve_out, we call select_all_tg_pt(),
|
||||
which requires mpp->hwe to be set. Initialize it in get_mpvec().
|
||||
|
||||
Fixes: 5b54e77 ("mpathpersist: add all_tg_pt option")
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmpathpersist/mpath_persist.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||
index 1f9817ed..4b3f3e0d 100644
|
||||
--- a/libmpathpersist/mpath_persist.c
|
||||
+++ b/libmpathpersist/mpath_persist.c
|
||||
@@ -341,11 +341,13 @@ get_mpvec (vector curmp, vector pathvec, char * refwwid)
|
||||
continue;
|
||||
|
||||
if (update_multipath_table(mpp, pathvec, DI_CHECKER) != DMP_OK ||
|
||||
- update_multipath_status(mpp) != DMP_OK) {
|
||||
+ update_multipath_status(mpp) != DMP_OK ||
|
||||
+ update_mpp_paths(mpp, pathvec)) {
|
||||
condlog(1, "error parsing map %s", mpp->wwid);
|
||||
remove_map(mpp, pathvec, curmp, PURGE_VEC);
|
||||
i--;
|
||||
- }
|
||||
+ } else
|
||||
+ extract_hwe_from_path(mpp);
|
||||
}
|
||||
return MPATH_PR_SUCCESS ;
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Fri, 4 Jan 2019 16:59:49 +0100
|
||||
Subject: [PATCH] multipathd: allow shutdown during configure()
|
||||
|
||||
reconfigure() can be a long-running operation; both initial path
|
||||
discovery and initial map setup can take a long time. Allow
|
||||
the main program to indicate that the process should be
|
||||
interrupted if a shutdown signal was received.
|
||||
|
||||
We take advantage of the dynamic linker's symbol lookup ordering
|
||||
here. The default implementation of should_exit never returns
|
||||
true, but callers (like multipathd) can override it.
|
||||
|
||||
Cc: Chongyun Wu <wu.chongyun@h3c.com>
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/configure.c | 6 ++++++
|
||||
libmultipath/discovery.c | 3 +++
|
||||
libmultipath/util.c | 5 +++++
|
||||
libmultipath/util.h | 1 +
|
||||
multipathd/main.c | 17 +++++++++++++++++
|
||||
5 files changed, 32 insertions(+)
|
||||
|
||||
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
||||
index d7afc915..1c8aac08 100644
|
||||
--- a/libmultipath/configure.c
|
||||
+++ b/libmultipath/configure.c
|
||||
@@ -1173,6 +1173,12 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
|
||||
|
||||
vector_foreach_slot (pathvec, pp1, k) {
|
||||
int invalid;
|
||||
+
|
||||
+ if (should_exit()) {
|
||||
+ ret = CP_FAIL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
/* skip this path for some reason */
|
||||
|
||||
/* 1. if path has no unique id or wwid blacklisted */
|
||||
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||
index c2e1754c..e7084664 100644
|
||||
--- a/libmultipath/discovery.c
|
||||
+++ b/libmultipath/discovery.c
|
||||
@@ -200,6 +200,9 @@ path_discovery (vector pathvec, int flag)
|
||||
const char *devtype;
|
||||
const char *devpath;
|
||||
|
||||
+ if (should_exit())
|
||||
+ break;
|
||||
+
|
||||
devpath = udev_list_entry_get_name(entry);
|
||||
condlog(4, "Discover device %s", devpath);
|
||||
udevice = udev_device_new_from_syspath(udev, devpath);
|
||||
diff --git a/libmultipath/util.c b/libmultipath/util.c
|
||||
index 1748eafe..1f977792 100644
|
||||
--- a/libmultipath/util.c
|
||||
+++ b/libmultipath/util.c
|
||||
@@ -445,3 +445,8 @@ void _log_bitfield_overflow(const char *f, unsigned int bit, unsigned int len)
|
||||
{
|
||||
condlog(0, "%s: bitfield overflow: %u >= %u", f, bit, len);
|
||||
}
|
||||
+
|
||||
+int should_exit(void)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/libmultipath/util.h b/libmultipath/util.h
|
||||
index 2b9703ac..ac19473e 100644
|
||||
--- a/libmultipath/util.h
|
||||
+++ b/libmultipath/util.h
|
||||
@@ -27,6 +27,7 @@ int parse_prkey(const char *ptr, uint64_t *prkey);
|
||||
int parse_prkey_flags(const char *ptr, uint64_t *prkey, uint8_t *flags);
|
||||
int safe_write(int fd, const void *buf, size_t count);
|
||||
void set_max_fds(rlim_t max_fds);
|
||||
+int should_exit(void);
|
||||
|
||||
#define KERNEL_VERSION(maj, min, ptc) ((((maj) * 256) + (min)) * 256 + (ptc))
|
||||
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index eedc6c10..fa53e963 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -141,6 +141,11 @@ static inline enum daemon_status get_running_state(void)
|
||||
return st;
|
||||
}
|
||||
|
||||
+int should_exit(void)
|
||||
+{
|
||||
+ return get_running_state() == DAEMON_SHUTDOWN;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* global copy of vecs for use in sig handlers
|
||||
*/
|
||||
@@ -2570,6 +2575,9 @@ configure (struct vectors * vecs)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
+ if (should_exit())
|
||||
+ goto fail;
|
||||
+
|
||||
conf = get_multipath_config();
|
||||
pthread_cleanup_push(put_multipath_config, conf);
|
||||
vector_foreach_slot (vecs->pathvec, pp, i){
|
||||
@@ -2586,6 +2594,9 @@ configure (struct vectors * vecs)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
+ if (should_exit())
|
||||
+ goto fail;
|
||||
+
|
||||
/*
|
||||
* create new set of maps & push changed ones into dm
|
||||
* In the first call, use FORCE_RELOAD_WEAK to avoid making
|
||||
@@ -2600,6 +2611,9 @@ configure (struct vectors * vecs)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
+ if (should_exit())
|
||||
+ goto fail;
|
||||
+
|
||||
/*
|
||||
* may need to remove some maps which are no longer relevant
|
||||
* e.g., due to blacklist changes in conf file
|
||||
@@ -2611,6 +2625,9 @@ configure (struct vectors * vecs)
|
||||
|
||||
dm_lib_release();
|
||||
|
||||
+ if (should_exit())
|
||||
+ goto fail;
|
||||
+
|
||||
sync_maps_state(mpvec);
|
||||
vector_foreach_slot(mpvec, mpp, i){
|
||||
if (remember_wwid(mpp->wwid) == 1)
|
@ -1,64 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 15 Sep 2020 10:23:05 +0200
|
||||
Subject: [PATCH] multipathd: avoid sending "READY=1" to systemd on early
|
||||
shutdown
|
||||
|
||||
If multipathd gets a shutdown request during initial reconfigure(),
|
||||
it shouldn't send "READY=1" to systemd. Ensure this by sending
|
||||
"READY=1" via post_config_state().
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 16 +++++++---------
|
||||
1 file changed, 7 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index fa53e963..53a22a43 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -189,6 +189,8 @@ static void do_sd_notify(enum daemon_status old_state,
|
||||
{
|
||||
char notify_msg[MSG_SIZE];
|
||||
const char *msg;
|
||||
+ static bool startup_done = false;
|
||||
+
|
||||
/*
|
||||
* Checkerloop switches back and forth between idle and running state.
|
||||
* No need to tell systemd each time.
|
||||
@@ -205,6 +207,11 @@ static void do_sd_notify(enum daemon_status old_state,
|
||||
|
||||
if (msg && !safe_sprintf(notify_msg, "STATUS=%s", msg))
|
||||
sd_notify(0, notify_msg);
|
||||
+
|
||||
+ if (new_state == DAEMON_IDLE && !startup_done) {
|
||||
+ sd_notify(0, "READY=1");
|
||||
+ startup_done = true;
|
||||
+ }
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2903,9 +2910,6 @@ child (__attribute__((unused)) void *param)
|
||||
struct vectors * vecs;
|
||||
struct multipath * mpp;
|
||||
int i;
|
||||
-#ifdef USE_SYSTEMD
|
||||
- int startup_done = 0;
|
||||
-#endif
|
||||
int rc;
|
||||
int pid_fd = -1;
|
||||
struct config *conf;
|
||||
@@ -3065,12 +3069,6 @@ child (__attribute__((unused)) void *param)
|
||||
}
|
||||
lock_cleanup_pop(vecs->lock);
|
||||
post_config_state(DAEMON_IDLE);
|
||||
-#ifdef USE_SYSTEMD
|
||||
- if (!startup_done) {
|
||||
- sd_notify(0, "READY=1");
|
||||
- startup_done = 1;
|
||||
- }
|
||||
-#endif
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 15 Sep 2020 10:47:52 +0200
|
||||
Subject: [PATCH] multipathd: send "STOPPING=1" to systemd on shutdown
|
||||
|
||||
Inform systemd that the daemon is shutting down. See sd_notify(3).
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 53a22a43..c264351c 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -208,7 +208,9 @@ static void do_sd_notify(enum daemon_status old_state,
|
||||
if (msg && !safe_sprintf(notify_msg, "STATUS=%s", msg))
|
||||
sd_notify(0, notify_msg);
|
||||
|
||||
- if (new_state == DAEMON_IDLE && !startup_done) {
|
||||
+ if (new_state == DAEMON_SHUTDOWN)
|
||||
+ sd_notify(0, "STOPPING=1");
|
||||
+ else if (new_state == DAEMON_IDLE && !startup_done) {
|
||||
sd_notify(0, "READY=1");
|
||||
startup_done = true;
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 15 Sep 2020 10:57:22 +0200
|
||||
Subject: [PATCH] multipathd: send "RELOADING=1" to systemd on DAEMON_CONFIGURE
|
||||
state
|
||||
|
||||
The logic is as follows: child() sets DAEMON_IDLE status after
|
||||
DAEMON_CONFIGURE when reconfigure() has finished. The only other state change
|
||||
that can race with that is DAEMON_SHUTDOWN. Other state changes will wait for
|
||||
DAEMON_IDLE first (see set_config_state()). When DAEMON_CONFIGURE is entered,
|
||||
and we are not just starting up, send a "RELOADING=1" message to
|
||||
systemd. After that, we must send "READY=1" when we're done reloading. Also
|
||||
do that on startup, when DAEMON_IDLE is set for the first time.
|
||||
See sd_notify(3).
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index c264351c..e3f2328d 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -210,10 +210,11 @@ static void do_sd_notify(enum daemon_status old_state,
|
||||
|
||||
if (new_state == DAEMON_SHUTDOWN)
|
||||
sd_notify(0, "STOPPING=1");
|
||||
- else if (new_state == DAEMON_IDLE && !startup_done) {
|
||||
+ else if (new_state == DAEMON_IDLE && old_state == DAEMON_CONFIGURE) {
|
||||
sd_notify(0, "READY=1");
|
||||
startup_done = true;
|
||||
- }
|
||||
+ } else if (new_state == DAEMON_CONFIGURE && startup_done)
|
||||
+ sd_notify(0, "RELOADING=1");
|
||||
}
|
||||
#endif
|
||||
|
@ -1,28 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 15 Sep 2020 12:44:59 +0200
|
||||
Subject: [PATCH] multipathd: use volatile qualifier for running_state
|
||||
|
||||
While we access running_state only under the config_lock,
|
||||
we sometimes do in a loop. Use the volatile qualifier to make
|
||||
sure compilers can't optimize away the loads.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index e3f2328d..d081b3e9 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -126,7 +126,7 @@ int poll_dmevents = 0;
|
||||
int poll_dmevents = 1;
|
||||
#endif
|
||||
/* Don't access this variable without holding config_lock */
|
||||
-enum daemon_status running_state = DAEMON_INIT;
|
||||
+volatile enum daemon_status running_state = DAEMON_INIT;
|
||||
pid_t daemon_pid;
|
||||
pthread_mutex_t config_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_cond_t config_cond;
|
@ -1,69 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 15 Sep 2020 12:46:36 +0200
|
||||
Subject: [PATCH] multipathd: generalize and fix wait_for_state_change_if()
|
||||
|
||||
It's unlikely but not impossible that other threads change the state
|
||||
while we're waiting, and if we grab the lock again, it's still not
|
||||
what we wanted. We need to continue waiting until either the condition
|
||||
is met, or time timeout expired.
|
||||
|
||||
Moreover, generalize this code so that it can also be used in
|
||||
set_config_state().
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 25 ++++++++++++++++++-------
|
||||
1 file changed, 18 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index d081b3e9..1fb0ee62 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -223,6 +223,23 @@ static void config_cleanup(__attribute__((unused)) void *arg)
|
||||
pthread_mutex_unlock(&config_lock);
|
||||
}
|
||||
|
||||
+#define __wait_for_state_change(condition, ms) \
|
||||
+ ({ \
|
||||
+ struct timespec tmo; \
|
||||
+ int rc = 0; \
|
||||
+ \
|
||||
+ if (condition) { \
|
||||
+ get_monotonic_time(&tmo); \
|
||||
+ tmo.tv_nsec += (ms) * 1000 * 1000; \
|
||||
+ normalize_timespec(&tmo); \
|
||||
+ do \
|
||||
+ rc = pthread_cond_timedwait( \
|
||||
+ &config_cond, &config_lock, &tmo); \
|
||||
+ while (rc == 0 && (condition)); \
|
||||
+ } \
|
||||
+ rc; \
|
||||
+ })
|
||||
+
|
||||
/*
|
||||
* If the current status is @oldstate, wait for at most @ms milliseconds
|
||||
* for the state to change, and return the new state, which may still be
|
||||
@@ -232,20 +249,14 @@ enum daemon_status wait_for_state_change_if(enum daemon_status oldstate,
|
||||
unsigned long ms)
|
||||
{
|
||||
enum daemon_status st;
|
||||
- struct timespec tmo;
|
||||
|
||||
if (oldstate == DAEMON_SHUTDOWN)
|
||||
return DAEMON_SHUTDOWN;
|
||||
|
||||
pthread_mutex_lock(&config_lock);
|
||||
pthread_cleanup_push(config_cleanup, NULL);
|
||||
+ __wait_for_state_change(running_state == oldstate, ms);
|
||||
st = running_state;
|
||||
- if (st == oldstate && clock_gettime(CLOCK_MONOTONIC, &tmo) == 0) {
|
||||
- tmo.tv_nsec += ms * 1000 * 1000;
|
||||
- normalize_timespec(&tmo);
|
||||
- (void)pthread_cond_timedwait(&config_cond, &config_lock, &tmo);
|
||||
- st = running_state;
|
||||
- }
|
||||
pthread_cleanup_pop(1);
|
||||
return st;
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 15 Sep 2020 12:48:55 +0200
|
||||
Subject: [PATCH] multipathd: set_config_state(): avoid code duplication
|
||||
|
||||
Use __post_config_state() and __wait_for_state_change(). This
|
||||
way __post_config_state() is the only place where running_state
|
||||
is ever changed, and we avoid code duplication.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 23 +++++------------------
|
||||
1 file changed, 5 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 1fb0ee62..39aea4ad 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -292,27 +292,14 @@ int set_config_state(enum daemon_status state)
|
||||
pthread_cleanup_push(config_cleanup, NULL);
|
||||
pthread_mutex_lock(&config_lock);
|
||||
if (running_state != state) {
|
||||
-#ifdef USE_SYSTEMD
|
||||
- enum daemon_status old_state = running_state;
|
||||
-#endif
|
||||
|
||||
if (running_state == DAEMON_SHUTDOWN)
|
||||
rc = EINVAL;
|
||||
- else if (running_state != DAEMON_IDLE) {
|
||||
- struct timespec ts;
|
||||
-
|
||||
- get_monotonic_time(&ts);
|
||||
- ts.tv_sec += 1;
|
||||
- rc = pthread_cond_timedwait(&config_cond,
|
||||
- &config_lock, &ts);
|
||||
- }
|
||||
- if (!rc && (running_state != DAEMON_SHUTDOWN)) {
|
||||
- running_state = state;
|
||||
- pthread_cond_broadcast(&config_cond);
|
||||
-#ifdef USE_SYSTEMD
|
||||
- do_sd_notify(old_state, state);
|
||||
-#endif
|
||||
- }
|
||||
+ else
|
||||
+ rc = __wait_for_state_change(
|
||||
+ running_state != DAEMON_IDLE, 1000);
|
||||
+ if (!rc)
|
||||
+ __post_config_state(state);
|
||||
}
|
||||
pthread_cleanup_pop(1);
|
||||
return rc;
|
@ -1,58 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Fri, 4 Jan 2019 17:10:25 +0100
|
||||
Subject: [PATCH] multipathd: cancel threads early during shutdown
|
||||
|
||||
Cancel the other threads before taking vecs->lock. This avoids
|
||||
delays during shutdown caused e.g. by the checker thread holding
|
||||
the vecs lock.
|
||||
|
||||
Note: this makes it possible that cancelled threads leak memory,
|
||||
because they can now be cancelled before having released the vecs
|
||||
lock. I believe this is acceptable, as only threads are affected
|
||||
that are cancelled during multipathd shutdown.
|
||||
|
||||
Cc: Chongyun Wu <wu.chongyun@h3c.com>
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 17 +++++++++--------
|
||||
1 file changed, 9 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 39aea4ad..d1f8cc1b 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -3073,23 +3073,24 @@ child (__attribute__((unused)) void *param)
|
||||
}
|
||||
}
|
||||
|
||||
- lock(&vecs->lock);
|
||||
+ pthread_cancel(check_thr);
|
||||
+ pthread_cancel(uevent_thr);
|
||||
+ pthread_cancel(uxlsnr_thr);
|
||||
+ pthread_cancel(uevq_thr);
|
||||
+ if (poll_dmevents)
|
||||
+ pthread_cancel(dmevent_thr);
|
||||
+
|
||||
conf = get_multipath_config();
|
||||
queue_without_daemon = conf->queue_without_daemon;
|
||||
put_multipath_config(conf);
|
||||
+
|
||||
+ lock(&vecs->lock);
|
||||
if (queue_without_daemon == QUE_NO_DAEMON_OFF)
|
||||
vector_foreach_slot(vecs->mpvec, mpp, i)
|
||||
dm_queue_if_no_path(mpp->alias, 0);
|
||||
remove_maps_and_stop_waiters(vecs);
|
||||
unlock(&vecs->lock);
|
||||
|
||||
- pthread_cancel(check_thr);
|
||||
- pthread_cancel(uevent_thr);
|
||||
- pthread_cancel(uxlsnr_thr);
|
||||
- pthread_cancel(uevq_thr);
|
||||
- if (poll_dmevents)
|
||||
- pthread_cancel(dmevent_thr);
|
||||
-
|
||||
pthread_join(check_thr, NULL);
|
||||
pthread_join(uevent_thr, NULL);
|
||||
pthread_join(uxlsnr_thr, NULL);
|
@ -1,162 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 15 Sep 2020 17:57:16 +0200
|
||||
Subject: [PATCH] multipath-tools: don't call dm_lib_release() any more
|
||||
|
||||
The purpose of dm_lib_release() is to release stacked device node
|
||||
operations in libdevmapper. This is functionality we don't need and
|
||||
use any more, as we rely on udev to set up device nodes and symlinks.
|
||||
|
||||
We always set DM_UDEV_DISABLE_LIBRARY_FALLBACK when we run dm tasks.
|
||||
In the standard CREATE and REMOVE cases, libdevmapper doesn't
|
||||
stack any operations if this flag is set. The only exceptions are
|
||||
|
||||
a) RESUME operations with DM_ADD_NODE_ON_RESUME set. This happens
|
||||
implicity when we create new maps
|
||||
b) RENAME operations
|
||||
|
||||
In both cases, we call dm_udev_wait() after the libdm operation, which
|
||||
calls update_devs() and thus has the same effect as dm_lib_release(),
|
||||
cleaning out stacked operations.
|
||||
|
||||
OTOH, dm_lib_releases() accesses static variables in libdevmapper, so
|
||||
calling it might be racy.
|
||||
|
||||
Drop the calls to dm_lib_release().
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
kpartx/kpartx.c | 1 -
|
||||
libmpathpersist/mpath_persist.c | 1 -
|
||||
multipath/main.c | 1 -
|
||||
multipathd/cli_handlers.c | 2 --
|
||||
multipathd/main.c | 15 ++-------------
|
||||
5 files changed, 2 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c
|
||||
index 4a0aae93..6a7933fa 100644
|
||||
--- a/kpartx/kpartx.c
|
||||
+++ b/kpartx/kpartx.c
|
||||
@@ -681,7 +681,6 @@ main(int argc, char **argv){
|
||||
}
|
||||
|
||||
end:
|
||||
- dm_lib_release();
|
||||
dm_lib_exit();
|
||||
|
||||
return r;
|
||||
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||
index 4b3f3e0d..cc4a088d 100644
|
||||
--- a/libmpathpersist/mpath_persist.c
|
||||
+++ b/libmpathpersist/mpath_persist.c
|
||||
@@ -56,7 +56,6 @@ mpath_lib_init (void)
|
||||
int
|
||||
mpath_lib_exit (struct config *conf)
|
||||
{
|
||||
- dm_lib_release();
|
||||
dm_lib_exit();
|
||||
cleanup_prio();
|
||||
cleanup_checkers();
|
||||
diff --git a/multipath/main.c b/multipath/main.c
|
||||
index 9e920d89..dc4974b9 100644
|
||||
--- a/multipath/main.c
|
||||
+++ b/multipath/main.c
|
||||
@@ -1063,7 +1063,6 @@ main (int argc, char *argv[])
|
||||
condlog(3, "restart multipath configuration process");
|
||||
|
||||
out:
|
||||
- dm_lib_release();
|
||||
dm_lib_exit();
|
||||
|
||||
cleanup_foreign();
|
||||
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
|
||||
index 235e2a2e..54635738 100644
|
||||
--- a/multipathd/cli_handlers.c
|
||||
+++ b/multipathd/cli_handlers.c
|
||||
@@ -860,7 +860,6 @@ cli_add_map (void * v, char ** reply, int * len, void * data)
|
||||
!= CP_OK)
|
||||
condlog(2, "%s: coalesce_paths failed",
|
||||
param);
|
||||
- dm_lib_release();
|
||||
FREE(refwwid);
|
||||
}
|
||||
} /*we attempt to create device only once*/
|
||||
@@ -1032,7 +1031,6 @@ cli_resize(void *v, char **reply, int *len, void *data)
|
||||
if (resize_map(mpp, size, vecs) != 0)
|
||||
return 1;
|
||||
|
||||
- dm_lib_release();
|
||||
if (setup_multipath(vecs, mpp) != 0)
|
||||
return 1;
|
||||
sync_map_state(mpp);
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index d1f8cc1b..5cc34357 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -510,7 +510,6 @@ retry:
|
||||
sleep(1);
|
||||
goto retry;
|
||||
}
|
||||
- dm_lib_release();
|
||||
|
||||
fail:
|
||||
if (new_map && (retries < 0 || wait_for_events(mpp, vecs))) {
|
||||
@@ -611,10 +610,8 @@ coalesce_maps(struct vectors *vecs, vector nmpv)
|
||||
vector_del_slot(ompv, i);
|
||||
i--;
|
||||
}
|
||||
- else {
|
||||
- dm_lib_release();
|
||||
+ else
|
||||
condlog(2, "%s devmap removed", ompp->alias);
|
||||
- }
|
||||
} else if (reassign_maps) {
|
||||
condlog(3, "%s: Reassign existing device-mapper"
|
||||
" devices", ompp->alias);
|
||||
@@ -660,10 +657,8 @@ flush_map(struct multipath * mpp, struct vectors * vecs, int nopaths)
|
||||
}
|
||||
return r;
|
||||
}
|
||||
- else {
|
||||
- dm_lib_release();
|
||||
+ else
|
||||
condlog(2, "%s: map flushed", mpp->alias);
|
||||
- }
|
||||
|
||||
orphan_paths(vecs->pathvec, mpp, "map flushed");
|
||||
remove_map_and_stop_waiter(mpp, vecs);
|
||||
@@ -1080,7 +1075,6 @@ rescan:
|
||||
else
|
||||
goto fail_map;
|
||||
}
|
||||
- dm_lib_release();
|
||||
|
||||
if ((mpp->action == ACT_CREATE ||
|
||||
(mpp->action == ACT_NOTHING && start_waiter && !mpp->waiter)) &&
|
||||
@@ -1947,8 +1941,6 @@ int reload_and_sync_map(struct multipath *mpp,
|
||||
{
|
||||
if (reload_map(vecs, mpp, refresh, 1))
|
||||
return 1;
|
||||
-
|
||||
- dm_lib_release();
|
||||
if (setup_multipath(vecs, mpp) != 0)
|
||||
return 2;
|
||||
sync_map_state(mpp);
|
||||
@@ -2631,8 +2623,6 @@ configure (struct vectors * vecs)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- dm_lib_release();
|
||||
-
|
||||
if (should_exit())
|
||||
goto fail;
|
||||
|
||||
@@ -3115,7 +3105,6 @@ child (__attribute__((unused)) void *param)
|
||||
if (poll_dmevents)
|
||||
cleanup_dmevent_waiter();
|
||||
|
||||
- dm_lib_release();
|
||||
dm_lib_exit();
|
||||
|
||||
/* We're done here */
|
@ -1,503 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 15 Sep 2020 23:12:15 +0200
|
||||
Subject: [PATCH] libmultipath: devmapper: refactor libdm version determination
|
||||
|
||||
As one step towards bundling all possibly racy libdm init calls into a single
|
||||
function, split the code for determining and checking versions of
|
||||
libdm and kernel components. Provide a generic helper
|
||||
libmp_get_version() that makes sure the versions are "lazily" initialized.
|
||||
|
||||
External callers may use dm_prereq(), like before.
|
||||
Minor API change: dm_prereq() does not nullify the argument any more
|
||||
if an error is encountered.
|
||||
|
||||
Remove the conf->version field, which isn't needed any more after this
|
||||
change. This makes it necessary to fixup the hwtable test. Also, it
|
||||
represents an incompatible ABI change as offsets in "struct config" are
|
||||
changed, and two symbols removed. Bump the ABI major version to 2.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/config.h | 1 -
|
||||
libmultipath/devmapper.c | 162 ++++++++++++++++++++----------
|
||||
libmultipath/devmapper.h | 10 +-
|
||||
libmultipath/libmultipath.version | 5 +-
|
||||
libmultipath/propsel.c | 10 +-
|
||||
multipathd/dmevents.c | 2 +-
|
||||
multipathd/main.c | 1 -
|
||||
tests/Makefile | 2 +-
|
||||
tests/hwtable.c | 3 -
|
||||
tests/test-lib.c | 13 +++
|
||||
10 files changed, 141 insertions(+), 68 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||
index 290aea58..7af19844 100644
|
||||
--- a/libmultipath/config.h
|
||||
+++ b/libmultipath/config.h
|
||||
@@ -192,7 +192,6 @@ struct config {
|
||||
int find_multipaths_timeout;
|
||||
int marginal_pathgroups;
|
||||
int skip_delegate;
|
||||
- unsigned int version[3];
|
||||
unsigned int sequence_nr;
|
||||
|
||||
char * multipath_dir;
|
||||
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||
index 0bc1d16e..3e36129b 100644
|
||||
--- a/libmultipath/devmapper.c
|
||||
+++ b/libmultipath/devmapper.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "sysfs.h"
|
||||
#include "config.h"
|
||||
#include "wwids.h"
|
||||
+#include "version.h"
|
||||
|
||||
#include "log_pthread.h"
|
||||
#include <sys/types.h>
|
||||
@@ -34,7 +35,13 @@
|
||||
#define MAX_WAIT 5
|
||||
#define LOOPS_PER_SEC 5
|
||||
|
||||
+#define INVALID_VERSION ~0U
|
||||
+static unsigned int dm_library_version[3] = { INVALID_VERSION, };
|
||||
+static unsigned int dm_kernel_version[3] = { INVALID_VERSION, };
|
||||
+static unsigned int dm_mpath_target_version[3] = { INVALID_VERSION, };
|
||||
+
|
||||
static pthread_once_t dm_initialized = PTHREAD_ONCE_INIT;
|
||||
+static pthread_once_t versions_initialized = PTHREAD_ONCE_INIT;
|
||||
|
||||
static int dm_conf_verbosity;
|
||||
|
||||
@@ -102,7 +109,7 @@ dm_write_log (int level, const char *file, int line, const char *f, ...)
|
||||
return;
|
||||
}
|
||||
|
||||
-void dm_init(int v)
|
||||
+static void dm_init(int v)
|
||||
{
|
||||
/*
|
||||
* This maps libdm's standard loglevel _LOG_WARN (= 4), which is rather
|
||||
@@ -112,61 +119,68 @@ void dm_init(int v)
|
||||
dm_log_init(&dm_write_log);
|
||||
}
|
||||
|
||||
+static void init_dm_library_version(void)
|
||||
+{
|
||||
+ char version[64];
|
||||
+ unsigned int v[3];
|
||||
+
|
||||
+ dm_get_library_version(version, sizeof(version));
|
||||
+ if (sscanf(version, "%u.%u.%u ", &v[0], &v[1], &v[2]) != 3) {
|
||||
+ condlog(0, "invalid libdevmapper version %s", version);
|
||||
+ return;
|
||||
+ }
|
||||
+ memcpy(dm_library_version, v, sizeof(dm_library_version));
|
||||
+ condlog(3, "libdevmapper version %u.%.2u.%.2u",
|
||||
+ dm_library_version[0], dm_library_version[1],
|
||||
+ dm_library_version[2]);
|
||||
+}
|
||||
+
|
||||
static int
|
||||
dm_lib_prereq (void)
|
||||
{
|
||||
- char version[64];
|
||||
- int v[3];
|
||||
+
|
||||
#if defined(LIBDM_API_HOLD_CONTROL)
|
||||
- int minv[3] = {1, 2, 111};
|
||||
+ unsigned int minv[3] = {1, 2, 111};
|
||||
#elif defined(LIBDM_API_GET_ERRNO)
|
||||
- int minv[3] = {1, 2, 99};
|
||||
+ unsigned int minv[3] = {1, 2, 99};
|
||||
#elif defined(LIBDM_API_DEFERRED)
|
||||
- int minv[3] = {1, 2, 89};
|
||||
+ unsigned int minv[3] = {1, 2, 89};
|
||||
#elif defined(DM_SUBSYSTEM_UDEV_FLAG0)
|
||||
- int minv[3] = {1, 2, 82};
|
||||
+ unsigned int minv[3] = {1, 2, 82};
|
||||
#elif defined(LIBDM_API_COOKIE)
|
||||
- int minv[3] = {1, 2, 38};
|
||||
+ unsigned int minv[3] = {1, 2, 38};
|
||||
#else
|
||||
- int minv[3] = {1, 2, 8};
|
||||
+ unsigned int minv[3] = {1, 2, 8};
|
||||
#endif
|
||||
|
||||
- dm_get_library_version(version, sizeof(version));
|
||||
- condlog(3, "libdevmapper version %s", version);
|
||||
- if (sscanf(version, "%d.%d.%d ", &v[0], &v[1], &v[2]) != 3) {
|
||||
- condlog(0, "invalid libdevmapper version %s", version);
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- if VERSION_GE(v, minv)
|
||||
+ if (VERSION_GE(dm_library_version, minv))
|
||||
return 0;
|
||||
- condlog(0, "libdevmapper version must be >= %d.%.2d.%.2d",
|
||||
+ condlog(0, "libdevmapper version must be >= %u.%.2u.%.2u",
|
||||
minv[0], minv[1], minv[2]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
-int
|
||||
-dm_drv_version(unsigned int *v)
|
||||
+static void init_dm_drv_version(void)
|
||||
{
|
||||
char buff[64];
|
||||
-
|
||||
- v[0] = 0;
|
||||
- v[1] = 0;
|
||||
- v[2] = 0;
|
||||
+ unsigned int v[3];
|
||||
|
||||
if (!dm_driver_version(buff, sizeof(buff))) {
|
||||
condlog(0, "cannot get kernel dm version");
|
||||
- return 1;
|
||||
+ return;
|
||||
}
|
||||
if (sscanf(buff, "%u.%u.%u ", &v[0], &v[1], &v[2]) != 3) {
|
||||
condlog(0, "invalid kernel dm version '%s'", buff);
|
||||
- return 1;
|
||||
+ return;
|
||||
}
|
||||
- return 0;
|
||||
+ memcpy(dm_kernel_version, v, sizeof(dm_library_version));
|
||||
+ condlog(3, "kernel device mapper v%u.%u.%u",
|
||||
+ dm_kernel_version[0],
|
||||
+ dm_kernel_version[1],
|
||||
+ dm_kernel_version[2]);
|
||||
}
|
||||
|
||||
-int
|
||||
-dm_tgt_version (unsigned int * version, char * str)
|
||||
+static int dm_tgt_version (unsigned int *version, char *str)
|
||||
{
|
||||
int r = 2;
|
||||
struct dm_task *dmt;
|
||||
@@ -174,10 +188,11 @@ dm_tgt_version (unsigned int * version, char * str)
|
||||
struct dm_versions *last_target;
|
||||
unsigned int *v;
|
||||
|
||||
- version[0] = 0;
|
||||
- version[1] = 0;
|
||||
- version[2] = 0;
|
||||
-
|
||||
+ /*
|
||||
+ * We have to call dm_task_create() and not libmp_dm_task_create()
|
||||
+ * here to avoid a recursive invocation of
|
||||
+ * pthread_once(&dm_initialized), which would cause a deadlock.
|
||||
+ */
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
|
||||
return 1;
|
||||
|
||||
@@ -213,26 +228,25 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
-static int
|
||||
-dm_tgt_prereq (unsigned int *ver)
|
||||
+static void init_dm_mpath_version(void)
|
||||
{
|
||||
- unsigned int minv[3] = {1, 0, 3};
|
||||
- unsigned int version[3] = {0, 0, 0};
|
||||
- unsigned int * v = version;
|
||||
-
|
||||
- if (dm_tgt_version(v, TGT_MPATH)) {
|
||||
- /* in doubt return not capable */
|
||||
- return 1;
|
||||
- }
|
||||
+ if (!dm_tgt_version(dm_mpath_target_version, TGT_MPATH))
|
||||
+ condlog(3, "DM multipath kernel driver v%u.%u.%u",
|
||||
+ dm_mpath_target_version[0],
|
||||
+ dm_mpath_target_version[1],
|
||||
+ dm_mpath_target_version[2]);
|
||||
+}
|
||||
|
||||
- /* test request based multipath capability */
|
||||
- condlog(3, "DM multipath kernel driver v%u.%u.%u",
|
||||
- v[0], v[1], v[2]);
|
||||
+static int dm_tgt_prereq (unsigned int *ver)
|
||||
+{
|
||||
+ unsigned int minv[3] = {1, 0, 3};
|
||||
|
||||
- if (VERSION_GE(v, minv)) {
|
||||
- ver[0] = v[0];
|
||||
- ver[1] = v[1];
|
||||
- ver[2] = v[2];
|
||||
+ if (VERSION_GE(dm_mpath_target_version, minv)) {
|
||||
+ if (ver) {
|
||||
+ ver[0] = dm_mpath_target_version[0];
|
||||
+ ver[1] = dm_mpath_target_version[1];
|
||||
+ ver[2] = dm_mpath_target_version[2];
|
||||
+ }
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -241,13 +255,60 @@ dm_tgt_prereq (unsigned int *ver)
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static void _init_versions(void)
|
||||
+{
|
||||
+ dlog(logsink, 3, VERSION_STRING);
|
||||
+ init_dm_library_version();
|
||||
+ init_dm_drv_version();
|
||||
+ init_dm_mpath_version();
|
||||
+}
|
||||
+
|
||||
+static int init_versions(void) {
|
||||
+ pthread_once(&versions_initialized, _init_versions);
|
||||
+ return (dm_library_version[0] == INVALID_VERSION ||
|
||||
+ dm_kernel_version[0] == INVALID_VERSION ||
|
||||
+ dm_mpath_target_version[0] == INVALID_VERSION);
|
||||
+}
|
||||
+
|
||||
int dm_prereq(unsigned int *v)
|
||||
{
|
||||
+ if (init_versions())
|
||||
+ return 1;
|
||||
if (dm_lib_prereq())
|
||||
return 1;
|
||||
return dm_tgt_prereq(v);
|
||||
}
|
||||
|
||||
+int libmp_get_version(int which, unsigned int version[3])
|
||||
+{
|
||||
+ unsigned int *src_version;
|
||||
+
|
||||
+ init_versions();
|
||||
+ switch (which) {
|
||||
+ case DM_LIBRARY_VERSION:
|
||||
+ src_version = dm_library_version;
|
||||
+ break;
|
||||
+ case DM_KERNEL_VERSION:
|
||||
+ src_version = dm_kernel_version;
|
||||
+ break;
|
||||
+ case DM_MPATH_TARGET_VERSION:
|
||||
+ src_version = dm_mpath_target_version;
|
||||
+ break;
|
||||
+ case MULTIPATH_VERSION:
|
||||
+ version[0] = (VERSION_CODE >> 16) & 0xff;
|
||||
+ version[1] = (VERSION_CODE >> 8) & 0xff;
|
||||
+ version[2] = VERSION_CODE & 0xff;
|
||||
+ return 0;
|
||||
+ default:
|
||||
+ condlog(0, "%s: invalid value for 'which'", __func__);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ if (src_version[0] == INVALID_VERSION)
|
||||
+ return 1;
|
||||
+ memcpy(version, src_version, 3 * sizeof(*version));
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int libmp_dm_udev_sync = 0;
|
||||
|
||||
void libmp_udev_set_sync_support(int on)
|
||||
@@ -265,7 +326,6 @@ static void libmp_dm_init(void)
|
||||
exit(1);
|
||||
conf = get_multipath_config();
|
||||
verbosity = conf->verbosity;
|
||||
- memcpy(conf->version, version, sizeof(version));
|
||||
put_multipath_config(conf);
|
||||
dm_init(verbosity);
|
||||
#ifdef LIBDM_API_HOLD_CONTROL
|
||||
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
|
||||
index f469c98a..a0bcd137 100644
|
||||
--- a/libmultipath/devmapper.h
|
||||
+++ b/libmultipath/devmapper.h
|
||||
@@ -33,13 +33,10 @@ enum {
|
||||
DMP_NOT_FOUND,
|
||||
};
|
||||
|
||||
-void dm_init(int verbosity);
|
||||
int dm_prereq(unsigned int *v);
|
||||
void skip_libmp_dm_init(void);
|
||||
void libmp_udev_set_sync_support(int on);
|
||||
struct dm_task *libmp_dm_task_create(int task);
|
||||
-int dm_drv_version (unsigned int * version);
|
||||
-int dm_tgt_version (unsigned int * version, char * str);
|
||||
int dm_simplecmd_flush (int, const char *, uint16_t);
|
||||
int dm_simplecmd_noflush (int, const char *, uint16_t);
|
||||
int dm_addmap_create (struct multipath *mpp, char *params);
|
||||
@@ -89,6 +86,13 @@ struct multipath *dm_get_multipath(const char *name);
|
||||
#include <errno.h>
|
||||
#define dm_task_get_errno(x) errno
|
||||
#endif
|
||||
+enum {
|
||||
+ DM_LIBRARY_VERSION,
|
||||
+ DM_KERNEL_VERSION,
|
||||
+ DM_MPATH_TARGET_VERSION,
|
||||
+ MULTIPATH_VERSION
|
||||
+};
|
||||
+int libmp_get_version(int which, unsigned int version[3]);
|
||||
|
||||
#define dm_log_error(lvl, cmd, dmt) \
|
||||
condlog(lvl, "%s: libdm task=%d error: %s", __func__, \
|
||||
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
|
||||
index a6bf8218..ab5bb0ad 100644
|
||||
--- a/libmultipath/libmultipath.version
|
||||
+++ b/libmultipath/libmultipath.version
|
||||
@@ -31,7 +31,7 @@
|
||||
* The new version inherits the previous ones.
|
||||
*/
|
||||
|
||||
-LIBMULTIPATH_1.0.0 {
|
||||
+LIBMULTIPATH_2.0.0 {
|
||||
global:
|
||||
/* symbols referenced by multipath and multipathd */
|
||||
add_foreign;
|
||||
@@ -65,7 +65,6 @@ global:
|
||||
disassemble_status;
|
||||
dlog;
|
||||
dm_cancel_deferred_remove;
|
||||
- dm_drv_version;
|
||||
dm_enablegroup;
|
||||
dm_fail_path;
|
||||
_dm_flush_map;
|
||||
@@ -87,7 +86,6 @@ global:
|
||||
dm_reinstate_path;
|
||||
dm_simplecmd_noflush;
|
||||
dm_switchgroup;
|
||||
- dm_tgt_version;
|
||||
domap;
|
||||
ensure_directories_exist;
|
||||
extract_hwe_from_path;
|
||||
@@ -128,6 +126,7 @@ global:
|
||||
is_path_valid;
|
||||
is_quote;
|
||||
libmp_dm_task_create;
|
||||
+ libmp_get_version;
|
||||
libmp_udev_set_sync_support;
|
||||
load_config;
|
||||
log_thread_reset;
|
||||
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
||||
index 40201344..3f2c2cfa 100644
|
||||
--- a/libmultipath/propsel.c
|
||||
+++ b/libmultipath/propsel.c
|
||||
@@ -735,9 +735,10 @@ out:
|
||||
|
||||
int select_minio(struct config *conf, struct multipath *mp)
|
||||
{
|
||||
- unsigned int minv_dmrq[3] = {1, 1, 0};
|
||||
+ unsigned int minv_dmrq[3] = {1, 1, 0}, version[3];
|
||||
|
||||
- if (VERSION_GE(conf->version, minv_dmrq))
|
||||
+ if (!libmp_get_version(DM_MPATH_TARGET_VERSION, version)
|
||||
+ && VERSION_GE(version, minv_dmrq))
|
||||
return select_minio_rq(conf, mp);
|
||||
else
|
||||
return select_minio_bio(conf, mp);
|
||||
@@ -820,9 +821,10 @@ out:
|
||||
int select_retain_hwhandler(struct config *conf, struct multipath *mp)
|
||||
{
|
||||
const char *origin;
|
||||
- unsigned int minv_dm_retain[3] = {1, 5, 0};
|
||||
+ unsigned int minv_dm_retain[3] = {1, 5, 0}, version[3];
|
||||
|
||||
- if (!VERSION_GE(conf->version, minv_dm_retain)) {
|
||||
+ if (!libmp_get_version(DM_MPATH_TARGET_VERSION, version) &&
|
||||
+ !VERSION_GE(version, minv_dm_retain)) {
|
||||
mp->retain_hwhandler = RETAIN_HWHANDLER_OFF;
|
||||
origin = "(setting: WARNING, requires kernel dm-mpath version >= 1.5.0)";
|
||||
goto out;
|
||||
diff --git a/multipathd/dmevents.c b/multipathd/dmevents.c
|
||||
index 5f2d210d..fc97c8a2 100644
|
||||
--- a/multipathd/dmevents.c
|
||||
+++ b/multipathd/dmevents.c
|
||||
@@ -60,7 +60,7 @@ int dmevent_poll_supported(void)
|
||||
{
|
||||
unsigned int v[3];
|
||||
|
||||
- if (dm_drv_version(v))
|
||||
+ if (libmp_get_version(DM_KERNEL_VERSION, v))
|
||||
return 0;
|
||||
|
||||
if (VERSION_GE(v, DM_VERSION_FOR_ARM_POLL))
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 5cc34357..00b66ba4 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -2709,7 +2709,6 @@ reconfigure (struct vectors * vecs)
|
||||
/* Re-read any timezone changes */
|
||||
tzset();
|
||||
|
||||
- dm_tgt_version(conf->version, TGT_MPATH);
|
||||
if (verbosity)
|
||||
conf->verbosity = verbosity;
|
||||
if (bindings_read_only)
|
||||
diff --git a/tests/Makefile b/tests/Makefile
|
||||
index 9658c9fd..78777bec 100644
|
||||
--- a/tests/Makefile
|
||||
+++ b/tests/Makefile
|
||||
@@ -43,7 +43,7 @@ endif
|
||||
dmevents-test_LIBDEPS = -lpthread -ldevmapper -lurcu
|
||||
hwtable-test_TESTDEPS := test-lib.o
|
||||
hwtable-test_OBJDEPS := ../libmultipath/discovery.o ../libmultipath/blacklist.o \
|
||||
- ../libmultipath/structs.o
|
||||
+ ../libmultipath/structs.o ../libmultipath/propsel.o
|
||||
hwtable-test_LIBDEPS := -ludev -lpthread -ldl
|
||||
blacklist-test_TESTDEPS := test-log.o
|
||||
blacklist-test_OBJDEPS := ../libmultipath/blacklist.o
|
||||
diff --git a/tests/hwtable.c b/tests/hwtable.c
|
||||
index 12660da2..57f832b7 100644
|
||||
--- a/tests/hwtable.c
|
||||
+++ b/tests/hwtable.c
|
||||
@@ -30,8 +30,6 @@
|
||||
#define N_CONF_FILES 2
|
||||
|
||||
static const char tmplate[] = "/tmp/hwtable-XXXXXX";
|
||||
-/* pretend new dm, use minio_rq */
|
||||
-static const unsigned int dm_tgt_version[3] = { 1, 1, 1 };
|
||||
|
||||
struct key_value {
|
||||
const char *key;
|
||||
@@ -360,7 +358,6 @@ static void write_device(FILE *ff, int nkv, const struct key_value *kv)
|
||||
assert_ptr_not_equal(__cf, NULL); \
|
||||
assert_ptr_not_equal(__cf->hwtable, NULL); \
|
||||
__cf->verbosity = VERBOSITY; \
|
||||
- memcpy(&__cf->version, dm_tgt_version, sizeof(__cf->version)); \
|
||||
__cf; })
|
||||
|
||||
#define FREE_CONFIG(conf) do { \
|
||||
diff --git a/tests/test-lib.c b/tests/test-lib.c
|
||||
index b7c09cc2..e7663f9a 100644
|
||||
--- a/tests/test-lib.c
|
||||
+++ b/tests/test-lib.c
|
||||
@@ -56,6 +56,15 @@ int __wrap_execute_program(char *path, char *value, int len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int __wrap_libmp_get_version(int which, unsigned int version[3])
|
||||
+{
|
||||
+ unsigned int *vers = mock_ptr_type(unsigned int *);
|
||||
+
|
||||
+ condlog(4, "%s: %d", __func__, which);
|
||||
+ memcpy(version, vers, 3 * sizeof(unsigned int));
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
struct udev_list_entry
|
||||
*__wrap_udev_device_get_properties_list_entry(struct udev_device *ud)
|
||||
{
|
||||
@@ -339,6 +348,8 @@ struct multipath *__mock_multipath(struct vectors *vecs, struct path *pp)
|
||||
struct multipath *mp;
|
||||
struct config *conf;
|
||||
struct mocked_path mop;
|
||||
+ /* pretend new dm, use minio_rq, */
|
||||
+ static const unsigned int fake_dm_tgt_version[3] = { 1, 1, 1 };
|
||||
|
||||
mocked_path_from_path(&mop, pp);
|
||||
/* pathinfo() call in adopt_paths */
|
||||
@@ -351,7 +362,9 @@ struct multipath *__mock_multipath(struct vectors *vecs, struct path *pp)
|
||||
conf = get_multipath_config();
|
||||
select_pgpolicy(conf, mp);
|
||||
select_no_path_retry(conf, mp);
|
||||
+ will_return(__wrap_libmp_get_version, fake_dm_tgt_version);
|
||||
select_retain_hwhandler(conf, mp);
|
||||
+ will_return(__wrap_libmp_get_version, fake_dm_tgt_version);
|
||||
select_minio(conf, mp);
|
||||
put_multipath_config(conf);
|
||||
|
@ -1,434 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 15 Sep 2020 23:38:48 +0200
|
||||
Subject: [PATCH] libmultipath: protect racy libdevmapper calls with a mutex
|
||||
|
||||
dm_udev_wait() and dm_task_run() may access global / static state
|
||||
in libdevmapper. They need to be protected by a lock in in our
|
||||
multithreaded library.
|
||||
|
||||
The modified call sequence requires fixing the dmevents test:
|
||||
devmapper.c must be added to dmevents-test_OBJDEPS to catch calls
|
||||
to dm_task_run(). Also, the call to dmevent_poll_supported() in
|
||||
setup() will cause init_versions() to be called, which requires
|
||||
bypassing the wrappers in the test setup phase.
|
||||
|
||||
Cc: lixiaokeng@huawei.com
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/devmapper.c | 73 +++++++++++++++++++------------
|
||||
libmultipath/devmapper.h | 2 +
|
||||
libmultipath/libmultipath.version | 6 +++
|
||||
libmultipath/util.c | 5 +++
|
||||
libmultipath/util.h | 1 +
|
||||
multipathd/dmevents.c | 2 +-
|
||||
multipathd/waiter.c | 2 +-
|
||||
tests/Makefile | 1 +
|
||||
tests/dmevents.c | 12 +++++
|
||||
9 files changed, 75 insertions(+), 29 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||
index 3e36129b..4eb6f539 100644
|
||||
--- a/libmultipath/devmapper.c
|
||||
+++ b/libmultipath/devmapper.c
|
||||
@@ -42,6 +42,7 @@ static unsigned int dm_mpath_target_version[3] = { INVALID_VERSION, };
|
||||
|
||||
static pthread_once_t dm_initialized = PTHREAD_ONCE_INIT;
|
||||
static pthread_once_t versions_initialized = PTHREAD_ONCE_INIT;
|
||||
+static pthread_mutex_t libmp_dm_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static int dm_conf_verbosity;
|
||||
|
||||
@@ -59,16 +60,34 @@ static inline int dm_task_set_cookie(struct dm_task *dmt, uint32_t *c, int a)
|
||||
return 1;
|
||||
}
|
||||
|
||||
-void dm_udev_wait(unsigned int c)
|
||||
+static void libmp_udev_wait(unsigned int c)
|
||||
{
|
||||
}
|
||||
|
||||
-void dm_udev_set_sync_support(int c)
|
||||
+static void dm_udev_set_sync_support(int c)
|
||||
{
|
||||
}
|
||||
-
|
||||
+#else
|
||||
+static void libmp_udev_wait(unsigned int c)
|
||||
+{
|
||||
+ pthread_mutex_lock(&libmp_dm_lock);
|
||||
+ pthread_cleanup_push(cleanup_mutex, &libmp_dm_lock);
|
||||
+ dm_udev_wait(c);
|
||||
+ pthread_cleanup_pop(1);
|
||||
+}
|
||||
#endif
|
||||
|
||||
+int libmp_dm_task_run(struct dm_task *dmt)
|
||||
+{
|
||||
+ int r;
|
||||
+
|
||||
+ pthread_mutex_lock(&libmp_dm_lock);
|
||||
+ pthread_cleanup_push(cleanup_mutex, &libmp_dm_lock);
|
||||
+ r = dm_task_run(dmt);
|
||||
+ pthread_cleanup_pop(1);
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
__attribute__((format(printf, 4, 5))) static void
|
||||
dm_write_log (int level, const char *file, int line, const char *f, ...)
|
||||
{
|
||||
@@ -198,7 +217,7 @@ static int dm_tgt_version (unsigned int *version, char *str)
|
||||
|
||||
dm_task_no_open_count(dmt);
|
||||
|
||||
- if (!dm_task_run(dmt)) {
|
||||
+ if (!libmp_dm_task_run(dmt)) {
|
||||
dm_log_error(2, DM_DEVICE_LIST_VERSIONS, dmt);
|
||||
condlog(0, "Can not communicate with kernel DM");
|
||||
goto out;
|
||||
@@ -382,12 +401,12 @@ dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t
|
||||
DM_UDEV_DISABLE_LIBRARY_FALLBACK | udev_flags))
|
||||
goto out;
|
||||
|
||||
- r = dm_task_run (dmt);
|
||||
+ r = libmp_dm_task_run (dmt);
|
||||
if (!r)
|
||||
dm_log_error(2, task, dmt);
|
||||
|
||||
if (udev_wait_flag)
|
||||
- dm_udev_wait(cookie);
|
||||
+ libmp_udev_wait(cookie);
|
||||
out:
|
||||
dm_task_destroy (dmt);
|
||||
return r;
|
||||
@@ -474,12 +493,12 @@ dm_addmap (int task, const char *target, struct multipath *mpp,
|
||||
!dm_task_set_cookie(dmt, &cookie, udev_flags))
|
||||
goto freeout;
|
||||
|
||||
- r = dm_task_run (dmt);
|
||||
+ r = libmp_dm_task_run (dmt);
|
||||
if (!r)
|
||||
dm_log_error(2, task, dmt);
|
||||
|
||||
if (task == DM_DEVICE_CREATE)
|
||||
- dm_udev_wait(cookie);
|
||||
+ libmp_udev_wait(cookie);
|
||||
freeout:
|
||||
if (prefixed_uuid)
|
||||
FREE(prefixed_uuid);
|
||||
@@ -589,7 +608,7 @@ do_get_info(const char *name, struct dm_info *info)
|
||||
|
||||
dm_task_no_open_count(dmt);
|
||||
|
||||
- if (!dm_task_run(dmt)) {
|
||||
+ if (!libmp_dm_task_run(dmt)) {
|
||||
dm_log_error(3, DM_DEVICE_INFO, dmt);
|
||||
goto out;
|
||||
}
|
||||
@@ -630,7 +649,7 @@ int dm_get_map(const char *name, unsigned long long *size, char *outparams)
|
||||
dm_task_no_open_count(dmt);
|
||||
|
||||
errno = 0;
|
||||
- if (!dm_task_run(dmt)) {
|
||||
+ if (!libmp_dm_task_run(dmt)) {
|
||||
dm_log_error(3, DM_DEVICE_TABLE, dmt);
|
||||
if (dm_task_get_errno(dmt) == ENXIO)
|
||||
r = DMP_NOT_FOUND;
|
||||
@@ -672,7 +691,7 @@ dm_get_prefixed_uuid(const char *name, char *uuid, int uuid_len)
|
||||
if (!dm_task_set_name (dmt, name))
|
||||
goto uuidout;
|
||||
|
||||
- if (!dm_task_run(dmt)) {
|
||||
+ if (!libmp_dm_task_run(dmt)) {
|
||||
dm_log_error(3, DM_DEVICE_INFO, dmt);
|
||||
goto uuidout;
|
||||
}
|
||||
@@ -743,7 +762,7 @@ int dm_get_status(const char *name, char *outstatus)
|
||||
dm_task_no_open_count(dmt);
|
||||
|
||||
errno = 0;
|
||||
- if (!dm_task_run(dmt)) {
|
||||
+ if (!libmp_dm_task_run(dmt)) {
|
||||
dm_log_error(3, DM_DEVICE_STATUS, dmt);
|
||||
if (dm_task_get_errno(dmt) == ENXIO)
|
||||
r = DMP_NOT_FOUND;
|
||||
@@ -796,7 +815,7 @@ int dm_type(const char *name, char *type)
|
||||
|
||||
dm_task_no_open_count(dmt);
|
||||
|
||||
- if (!dm_task_run(dmt)) {
|
||||
+ if (!libmp_dm_task_run(dmt)) {
|
||||
dm_log_error(3, DM_DEVICE_TABLE, dmt);
|
||||
goto out;
|
||||
}
|
||||
@@ -840,7 +859,7 @@ int dm_is_mpath(const char *name)
|
||||
|
||||
dm_task_no_open_count(dmt);
|
||||
|
||||
- if (!dm_task_run(dmt)) {
|
||||
+ if (!libmp_dm_task_run(dmt)) {
|
||||
dm_log_error(3, DM_DEVICE_TABLE, dmt);
|
||||
goto out_task;
|
||||
}
|
||||
@@ -904,7 +923,7 @@ dm_map_present_by_uuid(const char *uuid)
|
||||
if (!dm_task_set_uuid(dmt, prefixed_uuid))
|
||||
goto out_task;
|
||||
|
||||
- if (!dm_task_run(dmt)) {
|
||||
+ if (!libmp_dm_task_run(dmt)) {
|
||||
dm_log_error(3, DM_DEVICE_INFO, dmt);
|
||||
goto out_task;
|
||||
}
|
||||
@@ -950,7 +969,7 @@ dm_get_opencount (const char * mapname)
|
||||
if (!dm_task_set_name(dmt, mapname))
|
||||
goto out;
|
||||
|
||||
- if (!dm_task_run(dmt)) {
|
||||
+ if (!libmp_dm_task_run(dmt)) {
|
||||
dm_log_error(3, DM_DEVICE_INFO, dmt);
|
||||
goto out;
|
||||
}
|
||||
@@ -1110,7 +1129,7 @@ int dm_flush_maps (int need_suspend, int retries)
|
||||
|
||||
dm_task_no_open_count(dmt);
|
||||
|
||||
- if (!dm_task_run (dmt)) {
|
||||
+ if (!libmp_dm_task_run (dmt)) {
|
||||
dm_log_error(3, DM_DEVICE_LIST, dmt);
|
||||
goto out;
|
||||
}
|
||||
@@ -1156,7 +1175,7 @@ dm_message(const char * mapname, char * message)
|
||||
|
||||
dm_task_no_open_count(dmt);
|
||||
|
||||
- if (!dm_task_run(dmt)) {
|
||||
+ if (!libmp_dm_task_run(dmt)) {
|
||||
dm_log_error(2, DM_DEVICE_TARGET_MSG, dmt);
|
||||
goto out;
|
||||
}
|
||||
@@ -1276,7 +1295,7 @@ dm_get_maps (vector mp)
|
||||
|
||||
dm_task_no_open_count(dmt);
|
||||
|
||||
- if (!dm_task_run(dmt)) {
|
||||
+ if (!libmp_dm_task_run(dmt)) {
|
||||
dm_log_error(3, DM_DEVICE_LIST, dmt);
|
||||
goto out;
|
||||
}
|
||||
@@ -1361,7 +1380,7 @@ dm_mapname(int major, int minor)
|
||||
* daemon uev_trigger -> uev_add_map
|
||||
*/
|
||||
while (--loop) {
|
||||
- r = dm_task_run(dmt);
|
||||
+ r = libmp_dm_task_run(dmt);
|
||||
|
||||
if (r)
|
||||
break;
|
||||
@@ -1406,7 +1425,7 @@ do_foreach_partmaps (const char * mapname,
|
||||
|
||||
dm_task_no_open_count(dmt);
|
||||
|
||||
- if (!dm_task_run(dmt)) {
|
||||
+ if (!libmp_dm_task_run(dmt)) {
|
||||
dm_log_error(3, DM_DEVICE_LIST, dmt);
|
||||
goto out;
|
||||
}
|
||||
@@ -1641,11 +1660,11 @@ dm_rename (const char * old, char * new, char *delim, int skip_kpartx)
|
||||
|
||||
if (!dm_task_set_cookie(dmt, &cookie, udev_flags))
|
||||
goto out;
|
||||
- r = dm_task_run(dmt);
|
||||
+ r = libmp_dm_task_run(dmt);
|
||||
if (!r)
|
||||
dm_log_error(2, DM_DEVICE_RENAME, dmt);
|
||||
|
||||
- dm_udev_wait(cookie);
|
||||
+ libmp_udev_wait(cookie);
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
@@ -1687,7 +1706,7 @@ int dm_reassign_table(const char *name, char *old, char *new)
|
||||
|
||||
dm_task_no_open_count(dmt);
|
||||
|
||||
- if (!dm_task_run(dmt)) {
|
||||
+ if (!libmp_dm_task_run(dmt)) {
|
||||
dm_log_error(3, DM_DEVICE_TABLE, dmt);
|
||||
goto out;
|
||||
}
|
||||
@@ -1720,7 +1739,7 @@ int dm_reassign_table(const char *name, char *old, char *new)
|
||||
if (modified) {
|
||||
dm_task_no_open_count(reload_dmt);
|
||||
|
||||
- if (!dm_task_run(reload_dmt)) {
|
||||
+ if (!libmp_dm_task_run(reload_dmt)) {
|
||||
dm_log_error(3, DM_DEVICE_RELOAD, reload_dmt);
|
||||
condlog(3, "%s: failed to reassign targets", name);
|
||||
goto out_reload;
|
||||
@@ -1767,7 +1786,7 @@ int dm_reassign(const char *mapname)
|
||||
|
||||
dm_task_no_open_count(dmt);
|
||||
|
||||
- if (!dm_task_run(dmt)) {
|
||||
+ if (!libmp_dm_task_run(dmt)) {
|
||||
dm_log_error(3, DM_DEVICE_DEPS, dmt);
|
||||
goto out;
|
||||
}
|
||||
@@ -1835,7 +1854,7 @@ int dm_setgeometry(struct multipath *mpp)
|
||||
goto out;
|
||||
}
|
||||
|
||||
- r = dm_task_run(dmt);
|
||||
+ r = libmp_dm_task_run(dmt);
|
||||
if (!r)
|
||||
dm_log_error(3, DM_DEVICE_SET_GEOMETRY, dmt);
|
||||
out:
|
||||
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
|
||||
index a0bcd137..fa6b3c53 100644
|
||||
--- a/libmultipath/devmapper.h
|
||||
+++ b/libmultipath/devmapper.h
|
||||
@@ -93,6 +93,8 @@ enum {
|
||||
MULTIPATH_VERSION
|
||||
};
|
||||
int libmp_get_version(int which, unsigned int version[3]);
|
||||
+struct dm_task;
|
||||
+int libmp_dm_task_run(struct dm_task *dmt);
|
||||
|
||||
#define dm_log_error(lvl, cmd, dmt) \
|
||||
condlog(lvl, "%s: libdm task=%d error: %s", __func__, \
|
||||
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
|
||||
index ab5bb0ad..97acdbb2 100644
|
||||
--- a/libmultipath/libmultipath.version
|
||||
+++ b/libmultipath/libmultipath.version
|
||||
@@ -245,3 +245,9 @@ global:
|
||||
local:
|
||||
*;
|
||||
};
|
||||
+
|
||||
+LIBMULTIPATH_2.1.0 {
|
||||
+global:
|
||||
+ libmp_dm_task_run;
|
||||
+ cleanup_mutex;
|
||||
+} LIBMULTIPATH_2.0.0;
|
||||
diff --git a/libmultipath/util.c b/libmultipath/util.c
|
||||
index 1f977792..0e37f3ff 100644
|
||||
--- a/libmultipath/util.c
|
||||
+++ b/libmultipath/util.c
|
||||
@@ -424,6 +424,11 @@ void cleanup_free_ptr(void *arg)
|
||||
free(*p);
|
||||
}
|
||||
|
||||
+void cleanup_mutex(void *arg)
|
||||
+{
|
||||
+ pthread_mutex_unlock(arg);
|
||||
+}
|
||||
+
|
||||
struct bitfield *alloc_bitfield(unsigned int maxbit)
|
||||
{
|
||||
unsigned int n;
|
||||
diff --git a/libmultipath/util.h b/libmultipath/util.h
|
||||
index ac19473e..e9b48f9f 100644
|
||||
--- a/libmultipath/util.h
|
||||
+++ b/libmultipath/util.h
|
||||
@@ -49,6 +49,7 @@ int should_exit(void);
|
||||
|
||||
void close_fd(void *arg);
|
||||
void cleanup_free_ptr(void *arg);
|
||||
+void cleanup_mutex(void *arg);
|
||||
|
||||
struct scandir_result {
|
||||
struct dirent **di;
|
||||
diff --git a/multipathd/dmevents.c b/multipathd/dmevents.c
|
||||
index fc97c8a2..b561cbfd 100644
|
||||
--- a/multipathd/dmevents.c
|
||||
+++ b/multipathd/dmevents.c
|
||||
@@ -156,7 +156,7 @@ static int dm_get_events(void)
|
||||
|
||||
dm_task_no_open_count(dmt);
|
||||
|
||||
- if (!dm_task_run(dmt)) {
|
||||
+ if (!libmp_dm_task_run(dmt)) {
|
||||
dm_log_error(3, DM_DEVICE_LIST, dmt);
|
||||
goto fail;
|
||||
}
|
||||
diff --git a/multipathd/waiter.c b/multipathd/waiter.c
|
||||
index 3bc69807..bbe6c2a1 100644
|
||||
--- a/multipathd/waiter.c
|
||||
+++ b/multipathd/waiter.c
|
||||
@@ -118,7 +118,7 @@ static int waiteventloop (struct event_thread *waiter)
|
||||
pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
|
||||
|
||||
pthread_testcancel();
|
||||
- r = dm_task_run(waiter->dmt);
|
||||
+ r = libmp_dm_task_run(waiter->dmt);
|
||||
if (!r)
|
||||
dm_log_error(2, DM_DEVICE_WAITEVENT, waiter->dmt);
|
||||
pthread_testcancel();
|
||||
diff --git a/tests/Makefile b/tests/Makefile
|
||||
index 78777bec..908407ea 100644
|
||||
--- a/tests/Makefile
|
||||
+++ b/tests/Makefile
|
||||
@@ -40,6 +40,7 @@ endif
|
||||
# linker input file).
|
||||
# XYZ-test_LIBDEPS: Additional libs to link for this test
|
||||
|
||||
+dmevents-test_OBJDEPS = ../libmultipath/devmapper.o
|
||||
dmevents-test_LIBDEPS = -lpthread -ldevmapper -lurcu
|
||||
hwtable-test_TESTDEPS := test-lib.o
|
||||
hwtable-test_OBJDEPS := ../libmultipath/discovery.o ../libmultipath/blacklist.o \
|
||||
diff --git a/tests/dmevents.c b/tests/dmevents.c
|
||||
index bee117ac..b7c5122b 100644
|
||||
--- a/tests/dmevents.c
|
||||
+++ b/tests/dmevents.c
|
||||
@@ -179,6 +179,8 @@ struct dm_names *build_dm_names(void)
|
||||
return names;
|
||||
}
|
||||
|
||||
+static bool setup_done;
|
||||
+
|
||||
static int setup(void **state)
|
||||
{
|
||||
if (dmevent_poll_supported()) {
|
||||
@@ -186,6 +188,7 @@ static int setup(void **state)
|
||||
*state = &data;
|
||||
} else
|
||||
*state = NULL;
|
||||
+ setup_done = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -262,14 +265,20 @@ struct dm_task *__wrap_libmp_dm_task_create(int task)
|
||||
return mock_type(struct dm_task *);
|
||||
}
|
||||
|
||||
+int __real_dm_task_no_open_count(struct dm_task *dmt);
|
||||
int __wrap_dm_task_no_open_count(struct dm_task *dmt)
|
||||
{
|
||||
+ if (!setup_done)
|
||||
+ return __real_dm_task_no_open_count(dmt);
|
||||
assert_ptr_equal((struct test_data *)dmt, &data);
|
||||
return mock_type(int);
|
||||
}
|
||||
|
||||
+int __real_dm_task_run(struct dm_task *dmt);
|
||||
int __wrap_dm_task_run(struct dm_task *dmt)
|
||||
{
|
||||
+ if (!setup_done)
|
||||
+ return __real_dm_task_run(dmt);
|
||||
assert_ptr_equal((struct test_data *)dmt, &data);
|
||||
return mock_type(int);
|
||||
}
|
||||
@@ -291,8 +300,11 @@ struct dm_names * __wrap_dm_task_get_names(struct dm_task *dmt)
|
||||
return data.names;
|
||||
}
|
||||
|
||||
+void __real_dm_task_destroy(struct dm_task *dmt);
|
||||
void __wrap_dm_task_destroy(struct dm_task *dmt)
|
||||
{
|
||||
+ if (!setup_done)
|
||||
+ return __real_dm_task_destroy(dmt);
|
||||
assert_ptr_equal((struct test_data *)dmt, &data);
|
||||
|
||||
if (data.names) {
|
@ -1,95 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 16 Sep 2020 12:02:01 +0200
|
||||
Subject: [PATCH] libmultipath: constify file argument in config parser
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/config.c | 3 +--
|
||||
libmultipath/config.h | 2 +-
|
||||
libmultipath/parser.c | 9 +++++----
|
||||
libmultipath/parser.h | 2 +-
|
||||
4 files changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||
index df0f8f45..5c91a09d 100644
|
||||
--- a/libmultipath/config.c
|
||||
+++ b/libmultipath/config.c
|
||||
@@ -719,8 +719,7 @@ static void set_max_checkint_from_watchdog(struct config *conf)
|
||||
}
|
||||
#endif
|
||||
|
||||
-struct config *
|
||||
-load_config (char * file)
|
||||
+struct config *load_config(const char *file)
|
||||
{
|
||||
struct config *conf = alloc_config();
|
||||
|
||||
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||
index 7af19844..ace403b8 100644
|
||||
--- a/libmultipath/config.h
|
||||
+++ b/libmultipath/config.h
|
||||
@@ -251,7 +251,7 @@ void free_mptable (vector mptable);
|
||||
|
||||
int store_hwe (vector hwtable, struct hwentry *);
|
||||
|
||||
-struct config *load_config (char * file);
|
||||
+struct config *load_config (const char *file);
|
||||
struct config * alloc_config (void);
|
||||
void free_config (struct config * conf);
|
||||
extern struct config *get_multipath_config(void);
|
||||
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
|
||||
index ed6d5d6d..163ffbc9 100644
|
||||
--- a/libmultipath/parser.c
|
||||
+++ b/libmultipath/parser.c
|
||||
@@ -390,7 +390,7 @@ oom:
|
||||
/* non-recursive configuration stream handler */
|
||||
static int kw_level = 0;
|
||||
|
||||
-int warn_on_duplicates(vector uniques, char *str, char *file)
|
||||
+int warn_on_duplicates(vector uniques, char *str, const char *file)
|
||||
{
|
||||
char *tmp;
|
||||
int i;
|
||||
@@ -434,7 +434,7 @@ is_sublevel_keyword(char *str)
|
||||
}
|
||||
|
||||
int
|
||||
-validate_config_strvec(vector strvec, char *file)
|
||||
+validate_config_strvec(vector strvec, const char *file)
|
||||
{
|
||||
char *str = NULL;
|
||||
int i;
|
||||
@@ -499,7 +499,8 @@ validate_config_strvec(vector strvec, char *file)
|
||||
}
|
||||
|
||||
static int
|
||||
-process_stream(struct config *conf, FILE *stream, vector keywords, char *file)
|
||||
+process_stream(struct config *conf, FILE *stream, vector keywords,
|
||||
+ const char *file)
|
||||
{
|
||||
int i;
|
||||
int r = 0, t;
|
||||
@@ -584,7 +585,7 @@ out:
|
||||
|
||||
/* Data initialization */
|
||||
int
|
||||
-process_file(struct config *conf, char *file)
|
||||
+process_file(struct config *conf, const char *file)
|
||||
{
|
||||
int r;
|
||||
FILE *stream;
|
||||
diff --git a/libmultipath/parser.h b/libmultipath/parser.h
|
||||
index 62906e98..06666ccf 100644
|
||||
--- a/libmultipath/parser.h
|
||||
+++ b/libmultipath/parser.h
|
||||
@@ -77,7 +77,7 @@ extern void dump_keywords(vector keydump, int level);
|
||||
extern void free_keywords(vector keywords);
|
||||
extern vector alloc_strvec(char *string);
|
||||
extern void *set_value(vector strvec);
|
||||
-extern int process_file(struct config *conf, char *conf_file);
|
||||
+extern int process_file(struct config *conf, const char *conf_file);
|
||||
extern struct keyword * find_keyword(vector keywords, vector v, char * name);
|
||||
int snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw,
|
||||
const void *data);
|
@ -1,201 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 16 Sep 2020 12:06:56 +0200
|
||||
Subject: [PATCH] libmultipath: provide defaults for {get,put}_multipath_config
|
||||
|
||||
Add an implementation of get_multipath_config() and put_multipath_config()
|
||||
to libmultipath. The linker's symbol lookup rules will make sure that
|
||||
applications can override these functions if they need to. Defining
|
||||
these functions in libmultipath avoids the need to provide stubs
|
||||
for these functions in every appliation linking to libmultipath.
|
||||
|
||||
libmultipath's internal functions simply refer to a static "struct config".
|
||||
It must be initialized with init_config() rather than load_config(),
|
||||
which always allocates a new struct for backward compatibility, and must
|
||||
be teared down using uninit_config().
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/config.c | 75 ++++++++++++++++++++++++++-----
|
||||
libmultipath/config.h | 21 +++++++--
|
||||
libmultipath/libmultipath.version | 10 +++++
|
||||
3 files changed, 93 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||
index 5c91a09d..01b77dfe 100644
|
||||
--- a/libmultipath/config.c
|
||||
+++ b/libmultipath/config.c
|
||||
@@ -27,6 +27,26 @@
|
||||
#include "mpath_cmd.h"
|
||||
#include "propsel.h"
|
||||
|
||||
+static struct config __internal_config;
|
||||
+struct config *libmp_get_multipath_config(void)
|
||||
+{
|
||||
+ if (!__internal_config.hwtable)
|
||||
+ /* not initialized */
|
||||
+ return NULL;
|
||||
+ return &__internal_config;
|
||||
+}
|
||||
+
|
||||
+struct config *get_multipath_config(void)
|
||||
+ __attribute__((weak, alias("libmp_get_multipath_config")));
|
||||
+
|
||||
+void libmp_put_multipath_config(void *conf __attribute__((unused)))
|
||||
+{
|
||||
+ /* empty */
|
||||
+}
|
||||
+
|
||||
+void put_multipath_config(void *conf)
|
||||
+ __attribute__((weak, alias("libmp_put_multipath_config")));
|
||||
+
|
||||
static int
|
||||
hwe_strmatch (const struct hwentry *hwe1, const struct hwentry *hwe2)
|
||||
{
|
||||
@@ -574,17 +594,15 @@ restart:
|
||||
return;
|
||||
}
|
||||
|
||||
-struct config *
|
||||
-alloc_config (void)
|
||||
+static struct config *alloc_config (void)
|
||||
{
|
||||
return (struct config *)MALLOC(sizeof(struct config));
|
||||
}
|
||||
|
||||
-void
|
||||
-free_config (struct config * conf)
|
||||
+static void _uninit_config(struct config *conf)
|
||||
{
|
||||
if (!conf)
|
||||
- return;
|
||||
+ conf = &__internal_config;
|
||||
|
||||
if (conf->multipath_dir)
|
||||
FREE(conf->multipath_dir);
|
||||
@@ -650,7 +668,27 @@ free_config (struct config * conf)
|
||||
free_hwtable(conf->hwtable);
|
||||
free_hwe(conf->overrides);
|
||||
free_keywords(conf->keywords);
|
||||
- FREE(conf);
|
||||
+
|
||||
+ memset(conf, 0, sizeof(*conf));
|
||||
+}
|
||||
+
|
||||
+void uninit_config(void)
|
||||
+{
|
||||
+ _uninit_config(&__internal_config);
|
||||
+}
|
||||
+
|
||||
+void free_config(struct config *conf)
|
||||
+{
|
||||
+ if (!conf)
|
||||
+ return;
|
||||
+ else if (conf == &__internal_config) {
|
||||
+ condlog(0, "ERROR: %s called for internal config. Use uninit_config() instead",
|
||||
+ __func__);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ _uninit_config(conf);
|
||||
+ free(conf);
|
||||
}
|
||||
|
||||
/* if multipath fails to process the config directory, it should continue,
|
||||
@@ -719,12 +757,29 @@ static void set_max_checkint_from_watchdog(struct config *conf)
|
||||
}
|
||||
#endif
|
||||
|
||||
+static int _init_config (const char *file, struct config *conf);
|
||||
+
|
||||
+int init_config(const char *file)
|
||||
+{
|
||||
+ return _init_config(file, &__internal_config);
|
||||
+}
|
||||
+
|
||||
struct config *load_config(const char *file)
|
||||
{
|
||||
struct config *conf = alloc_config();
|
||||
|
||||
+ if (conf && !_init_config(file, conf))
|
||||
+ return conf;
|
||||
+
|
||||
+ free(conf);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+int _init_config (const char *file, struct config *conf)
|
||||
+{
|
||||
+
|
||||
if (!conf)
|
||||
- return NULL;
|
||||
+ conf = &__internal_config;
|
||||
|
||||
/*
|
||||
* internal defaults
|
||||
@@ -896,10 +951,10 @@ struct config *load_config(const char *file)
|
||||
!conf->wwids_file || !conf->prkeys_file)
|
||||
goto out;
|
||||
|
||||
- return conf;
|
||||
+ return 0;
|
||||
out:
|
||||
- free_config(conf);
|
||||
- return NULL;
|
||||
+ _uninit_config(conf);
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
char *get_uid_attribute_by_attrs(struct config *conf,
|
||||
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||
index ace403b8..0329de29 100644
|
||||
--- a/libmultipath/config.h
|
||||
+++ b/libmultipath/config.h
|
||||
@@ -252,10 +252,25 @@ void free_mptable (vector mptable);
|
||||
int store_hwe (vector hwtable, struct hwentry *);
|
||||
|
||||
struct config *load_config (const char *file);
|
||||
-struct config * alloc_config (void);
|
||||
void free_config (struct config * conf);
|
||||
-extern struct config *get_multipath_config(void);
|
||||
-extern void put_multipath_config(void *);
|
||||
+int init_config(const char *file);
|
||||
+void uninit_config(void);
|
||||
+
|
||||
+/*
|
||||
+ * libmultipath provides default implementations of
|
||||
+ * get_multipath_config() and put_multipath_config().
|
||||
+ * Applications using these should use init_config(file, NULL)
|
||||
+ * to load the configuration, rather than load_config(file).
|
||||
+ * Likewise, uninit_config() should be used for teardown, but
|
||||
+ * using free_config() for that is supported, too.
|
||||
+ * Applications can define their own {get,put}_multipath_config()
|
||||
+ * functions, which override the library-internal ones, but
|
||||
+ * could still call libmp_{get,put}_multipath_config().
|
||||
+ */
|
||||
+struct config *libmp_get_multipath_config(void);
|
||||
+struct config *get_multipath_config(void);
|
||||
+void libmp_put_multipath_config(void *);
|
||||
+void put_multipath_config(void *);
|
||||
|
||||
int parse_uid_attrs(char *uid_attrs, struct config *conf);
|
||||
char *get_uid_attribute_by_attrs(struct config *conf,
|
||||
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
|
||||
index 97acdbb2..3e780fce 100644
|
||||
--- a/libmultipath/libmultipath.version
|
||||
+++ b/libmultipath/libmultipath.version
|
||||
@@ -251,3 +251,13 @@ global:
|
||||
libmp_dm_task_run;
|
||||
cleanup_mutex;
|
||||
} LIBMULTIPATH_2.0.0;
|
||||
+
|
||||
+LIBMULTIPATH_2.2.0 {
|
||||
+global:
|
||||
+ libmp_get_multipath_config;
|
||||
+ get_multipath_config;
|
||||
+ libmp_put_multipath_config;
|
||||
+ put_multipath_config;
|
||||
+ init_config;
|
||||
+ uninit_config;
|
||||
+} LIBMULTIPATH_2.1.0;
|
@ -1,153 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 16 Sep 2020 12:11:46 +0200
|
||||
Subject: [PATCH] libmpathpersist: allow using libmultipath
|
||||
{get,put}_multipath_config
|
||||
|
||||
Provide an alternative init function libmpathpersist_init() which
|
||||
avoids allocating a new struct config, simply using libmultipath's
|
||||
internal implementation. This causes a minor version bump for
|
||||
libmpathpersist.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmpathpersist/libmpathpersist.version | 6 ++++
|
||||
libmpathpersist/mpath_persist.c | 42 +++++++++++++++++++++----
|
||||
libmpathpersist/mpath_persist.h | 28 +++++++++++++++++
|
||||
3 files changed, 70 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/libmpathpersist/libmpathpersist.version b/libmpathpersist/libmpathpersist.version
|
||||
index dc648ce6..e0748138 100644
|
||||
--- a/libmpathpersist/libmpathpersist.version
|
||||
+++ b/libmpathpersist/libmpathpersist.version
|
||||
@@ -30,3 +30,9 @@ global:
|
||||
|
||||
local: *;
|
||||
};
|
||||
+
|
||||
+LIBMPATHPERSIST_1.1.0 {
|
||||
+global:
|
||||
+ libmpathpersist_init;
|
||||
+ libmpathpersist_exit;
|
||||
+} LIBMPATHPERSIST_1.0.0;
|
||||
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||
index cc4a088d..febf4758 100644
|
||||
--- a/libmpathpersist/mpath_persist.c
|
||||
+++ b/libmpathpersist/mpath_persist.c
|
||||
@@ -37,6 +37,27 @@
|
||||
|
||||
extern struct udev *udev;
|
||||
|
||||
+static void adapt_config(struct config *conf)
|
||||
+{
|
||||
+ conf->force_sync = 1;
|
||||
+ set_max_fds(conf->max_fds);
|
||||
+}
|
||||
+
|
||||
+int libmpathpersist_init(void)
|
||||
+{
|
||||
+ struct config *conf;
|
||||
+ int rc = 0;
|
||||
+
|
||||
+ if (init_config(DEFAULT_CONFIGFILE)) {
|
||||
+ condlog(0, "Failed to initialize multipath config.");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ conf = libmp_get_multipath_config();
|
||||
+ adapt_config(conf);
|
||||
+ libmp_put_multipath_config(conf);
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
struct config *
|
||||
mpath_lib_init (void)
|
||||
{
|
||||
@@ -47,20 +68,29 @@ mpath_lib_init (void)
|
||||
condlog(0, "Failed to initialize multipath config.");
|
||||
return NULL;
|
||||
}
|
||||
- conf->force_sync = 1;
|
||||
- set_max_fds(conf->max_fds);
|
||||
-
|
||||
+ adapt_config(conf);
|
||||
return conf;
|
||||
}
|
||||
|
||||
-int
|
||||
-mpath_lib_exit (struct config *conf)
|
||||
+static void libmpathpersist_cleanup(void)
|
||||
{
|
||||
dm_lib_exit();
|
||||
cleanup_prio();
|
||||
cleanup_checkers();
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+mpath_lib_exit (struct config *conf)
|
||||
+{
|
||||
+ libmpathpersist_cleanup();
|
||||
free_config(conf);
|
||||
- conf = NULL;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int libmpathpersist_exit(void)
|
||||
+{
|
||||
+ libmpathpersist_cleanup();
|
||||
+ uninit_config();
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/libmpathpersist/mpath_persist.h b/libmpathpersist/mpath_persist.h
|
||||
index 7cf4faf9..91606efc 100644
|
||||
--- a/libmpathpersist/mpath_persist.h
|
||||
+++ b/libmpathpersist/mpath_persist.h
|
||||
@@ -175,6 +175,22 @@ struct prout_param_descriptor { /* PROUT parameter descriptor */
|
||||
* DESCRIPTION :
|
||||
* Initialize device mapper multipath configuration. This function must be invoked first
|
||||
* before performing reservation management functions.
|
||||
+ * Either this function or mpath_lib_init() may be used.
|
||||
+ * Use this function to work with libmultipath's internal "struct config".
|
||||
+ * Call libmpathpersist_exit() for cleanup.
|
||||
+ * RESTRICTIONS:
|
||||
+ *
|
||||
+ * RETURNS: 0->Success, 1->Failed.
|
||||
+ */
|
||||
+extern int libmpathpersist_init (void);
|
||||
+
|
||||
+/*
|
||||
+ * DESCRIPTION :
|
||||
+ * Initialize device mapper multipath configuration. This function must be invoked first
|
||||
+ * before performing reservation management functions.
|
||||
+ * Either this function or libmpathpersist_init() may be used.
|
||||
+ * Use this function to work with an application-specific "struct config".
|
||||
+ * Call mpath_lib_exit() for cleanup.
|
||||
* RESTRICTIONS:
|
||||
*
|
||||
* RETURNS: struct config ->Success, NULL->Failed.
|
||||
@@ -186,12 +202,24 @@ extern struct config * mpath_lib_init (void);
|
||||
* DESCRIPTION :
|
||||
* Release device mapper multipath configuration. This function must be invoked after
|
||||
* performing reservation management functions.
|
||||
+ * Use this after initialization with mpath_lib_init().
|
||||
* RESTRICTIONS:
|
||||
*
|
||||
* RETURNS: 0->Success, 1->Failed.
|
||||
*/
|
||||
extern int mpath_lib_exit (struct config *conf);
|
||||
|
||||
+/*
|
||||
+ * DESCRIPTION :
|
||||
+ * Release device mapper multipath configuration. This function must be invoked after
|
||||
+ * performing reservation management functions.
|
||||
+ * Use this after initialization with libmpathpersist_init().
|
||||
+ * RESTRICTIONS:
|
||||
+ *
|
||||
+ * RETURNS: 0->Success, 1->Failed.
|
||||
+ */
|
||||
+extern int libmpathpersist_exit (void);
|
||||
+
|
||||
|
||||
/*
|
||||
* DESCRIPTION :
|
@ -1,64 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 16 Sep 2020 12:27:09 +0200
|
||||
Subject: [PATCH] multipath: use {get_put}_multipath_config from libmultipath
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipath/main.c | 20 ++++----------------
|
||||
1 file changed, 4 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/multipath/main.c b/multipath/main.c
|
||||
index dc4974b9..4bbfce9a 100644
|
||||
--- a/multipath/main.c
|
||||
+++ b/multipath/main.c
|
||||
@@ -68,7 +68,6 @@
|
||||
|
||||
int logsink;
|
||||
struct udev *udev;
|
||||
-struct config *multipath_conf;
|
||||
|
||||
/*
|
||||
* Return values of configure(), check_path_valid(), and main().
|
||||
@@ -79,16 +78,6 @@ enum {
|
||||
RTVL_RETRY, /* returned by configure(), not by main() */
|
||||
};
|
||||
|
||||
-struct config *get_multipath_config(void)
|
||||
-{
|
||||
- return multipath_conf;
|
||||
-}
|
||||
-
|
||||
-void put_multipath_config(__attribute__((unused)) void *arg)
|
||||
-{
|
||||
- /* Noop for now */
|
||||
-}
|
||||
-
|
||||
static int
|
||||
dump_config (struct config *conf, vector hwes, vector mpvec)
|
||||
{
|
||||
@@ -823,10 +812,9 @@ main (int argc, char *argv[])
|
||||
|
||||
udev = udev_new();
|
||||
logsink = 0;
|
||||
- conf = load_config(DEFAULT_CONFIGFILE);
|
||||
- if (!conf)
|
||||
+ if (init_config(DEFAULT_CONFIGFILE))
|
||||
exit(RTVL_FAIL);
|
||||
- multipath_conf = conf;
|
||||
+ conf = get_multipath_config();
|
||||
conf->retrigger_tries = 0;
|
||||
conf->force_sync = 1;
|
||||
while ((arg = getopt(argc, argv, ":adDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
|
||||
@@ -1078,8 +1066,8 @@ out_free_config:
|
||||
* the logging function (dm_write_log()), which is called there,
|
||||
* references the config.
|
||||
*/
|
||||
- free_config(conf);
|
||||
- conf = NULL;
|
||||
+ put_multipath_config(conf);
|
||||
+ uninit_config();
|
||||
udev_unref(udev);
|
||||
if (dev)
|
||||
FREE(dev);
|
@ -1,52 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 16 Sep 2020 12:39:01 +0200
|
||||
Subject: [PATCH] mpathpersist: use {get,put}_multipath_config() from
|
||||
libmultipath
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
mpathpersist/main.c | 16 ++--------------
|
||||
1 file changed, 2 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/mpathpersist/main.c b/mpathpersist/main.c
|
||||
index a6a3bcf6..278e48f7 100644
|
||||
--- a/mpathpersist/main.c
|
||||
+++ b/mpathpersist/main.c
|
||||
@@ -43,17 +43,6 @@ void mpath_print_transport_id(struct prin_fulldescr *fdesc);
|
||||
int construct_transportid(const char * inp, struct transportid transid[], int num_transportids);
|
||||
|
||||
int logsink;
|
||||
-struct config *multipath_conf;
|
||||
-
|
||||
-struct config *get_multipath_config(void)
|
||||
-{
|
||||
- return multipath_conf;
|
||||
-}
|
||||
-
|
||||
-void put_multipath_config(__attribute__((unused)) void * arg)
|
||||
-{
|
||||
- /* Noop for now */
|
||||
-}
|
||||
|
||||
void rcu_register_thread_memb(void) {}
|
||||
|
||||
@@ -653,15 +642,14 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
udev = udev_new();
|
||||
- multipath_conf = mpath_lib_init();
|
||||
- if(!multipath_conf) {
|
||||
+ if (libmpathpersist_init()) {
|
||||
udev_unref(udev);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = handle_args(argc, argv, 0);
|
||||
|
||||
- mpath_lib_exit(multipath_conf);
|
||||
+ libmpathpersist_exit();
|
||||
udev_unref(udev);
|
||||
|
||||
return (ret >= 0) ? ret : MPATH_PR_OTHER;
|
@ -1,165 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 16 Sep 2020 15:06:12 +0200
|
||||
Subject: [PATCH] libmultipath: add udev and logsink symbols
|
||||
|
||||
With these symbols added, applications using libmultipath don't
|
||||
need to define global variables "udev" and "logsink" any more.
|
||||
This comes at the cost of having to call an init function.
|
||||
Currently, libmultipath_init() does nothing but initialize
|
||||
"udev".
|
||||
|
||||
The linker's symbol lookup order still allows applications to use
|
||||
their own "logsink" and "udev" variables, which will take precendence
|
||||
over libmultipath's internal ones. In this case, calling
|
||||
libmultipath_init() can be skipped, but like before,
|
||||
udev should be initialized (using udev_new()) before making any
|
||||
libmultipath calls.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/config.c | 41 +++++++++++++++++++++++++++
|
||||
libmultipath/config.h | 46 ++++++++++++++++++++++++++++++-
|
||||
libmultipath/debug.c | 2 ++
|
||||
libmultipath/libmultipath.version | 8 ++++++
|
||||
4 files changed, 96 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||
index 01b77dfe..f74417c6 100644
|
||||
--- a/libmultipath/config.c
|
||||
+++ b/libmultipath/config.c
|
||||
@@ -27,6 +27,47 @@
|
||||
#include "mpath_cmd.h"
|
||||
#include "propsel.h"
|
||||
|
||||
+/*
|
||||
+ * We don't support re-initialization after
|
||||
+ * libmultipath_exit().
|
||||
+ */
|
||||
+static bool libmultipath_exit_called;
|
||||
+static pthread_once_t _init_once = PTHREAD_ONCE_INIT;
|
||||
+static pthread_once_t _exit_once = PTHREAD_ONCE_INIT;
|
||||
+struct udev *udev;
|
||||
+
|
||||
+static void _udev_init(void)
|
||||
+{
|
||||
+ if (udev)
|
||||
+ udev_ref(udev);
|
||||
+ else
|
||||
+ udev = udev_new();
|
||||
+ if (!udev)
|
||||
+ condlog(0, "%s: failed to initialize udev", __func__);
|
||||
+}
|
||||
+
|
||||
+static bool _is_libmultipath_initialized(void)
|
||||
+{
|
||||
+ return !libmultipath_exit_called && !!udev;
|
||||
+}
|
||||
+
|
||||
+int libmultipath_init(void)
|
||||
+{
|
||||
+ pthread_once(&_init_once, _udev_init);
|
||||
+ return !_is_libmultipath_initialized();
|
||||
+}
|
||||
+
|
||||
+static void _libmultipath_exit(void)
|
||||
+{
|
||||
+ libmultipath_exit_called = true;
|
||||
+ udev_unref(udev);
|
||||
+}
|
||||
+
|
||||
+void libmultipath_exit(void)
|
||||
+{
|
||||
+ pthread_once(&_exit_once, _libmultipath_exit);
|
||||
+}
|
||||
+
|
||||
static struct config __internal_config;
|
||||
struct config *libmp_get_multipath_config(void)
|
||||
{
|
||||
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||
index 0329de29..f478df71 100644
|
||||
--- a/libmultipath/config.h
|
||||
+++ b/libmultipath/config.h
|
||||
@@ -233,7 +233,51 @@ struct config {
|
||||
char *enable_foreign;
|
||||
};
|
||||
|
||||
-extern struct udev * udev;
|
||||
+/**
|
||||
+ * extern variable: udev
|
||||
+ *
|
||||
+ * A &struct udev instance used by libmultipath. libmultipath expects
|
||||
+ * a valid, initialized &struct udev in this variable.
|
||||
+ * An application can define this variable itself, in which case
|
||||
+ * the applications's instance will take precedence.
|
||||
+ * The application can initialize and destroy this variable by
|
||||
+ * calling libmultipath_init() and libmultipath_exit(), respectively,
|
||||
+ * whether or not it defines the variable itself.
|
||||
+ * An application can initialize udev with udev_new() before calling
|
||||
+ * libmultipath_init(), e.g. if it has to make libudev calls before
|
||||
+ * libmultipath calls. If an application wants to keep using the
|
||||
+ * udev variable after calling libmultipath_exit(), it should have taken
|
||||
+ * an additional reference on it beforehand. This is the case e.g.
|
||||
+ * after initiazing udev with udev_new().
|
||||
+ */
|
||||
+extern struct udev *udev;
|
||||
+
|
||||
+/**
|
||||
+ * libmultipath_init() - library initialization
|
||||
+ *
|
||||
+ * This function initializes libmultipath data structures.
|
||||
+ * It is light-weight; some other initializations, like device-mapper
|
||||
+ * initialization, are done lazily when the respective functionality
|
||||
+ * is required.
|
||||
+ *
|
||||
+ * Clean up by libmultipath_exit() when the program terminates.
|
||||
+ * It is an error to call libmultipath_init() after libmultipath_exit().
|
||||
+ * Return: 0 on success, 1 on failure.
|
||||
+ */
|
||||
+int libmultipath_init(void);
|
||||
+
|
||||
+/**
|
||||
+ * libmultipath_exit() - library un-initialization
|
||||
+ *
|
||||
+ * This function un-initializes libmultipath data structures.
|
||||
+ * It is recommended to call this function at program exit.
|
||||
+ *
|
||||
+ * Calls to libmultipath_init() after libmultipath_exit() will fail
|
||||
+ * (in other words, libmultipath can't be re-initialized).
|
||||
+ * Any other libmultipath calls after libmultipath_exit() may cause
|
||||
+ * undefined behavior.
|
||||
+ */
|
||||
+void libmultipath_exit(void);
|
||||
|
||||
int find_hwe (const struct _vector *hwtable,
|
||||
const char * vendor, const char * product, const char *revision,
|
||||
diff --git a/libmultipath/debug.c b/libmultipath/debug.c
|
||||
index 4128cb90..b3a1de9e 100644
|
||||
--- a/libmultipath/debug.c
|
||||
+++ b/libmultipath/debug.c
|
||||
@@ -15,6 +15,8 @@
|
||||
#include "defaults.h"
|
||||
#include "debug.h"
|
||||
|
||||
+int logsink;
|
||||
+
|
||||
void dlog (int sink, int prio, const char * fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
|
||||
index 3e780fce..0c300c81 100644
|
||||
--- a/libmultipath/libmultipath.version
|
||||
+++ b/libmultipath/libmultipath.version
|
||||
@@ -261,3 +261,11 @@ global:
|
||||
init_config;
|
||||
uninit_config;
|
||||
} LIBMULTIPATH_2.1.0;
|
||||
+
|
||||
+LIBMULTIPATH_2.3.0 {
|
||||
+global:
|
||||
+ udev;
|
||||
+ logsink;
|
||||
+ libmultipath_init;
|
||||
+ libmultipath_exit;
|
||||
+} LIBMULTIPATH_2.2.0;
|
@ -1,45 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 16 Sep 2020 16:06:17 +0200
|
||||
Subject: [PATCH] multipath: remove logsink and udev
|
||||
|
||||
We can use libmultipath's symbols now.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipath/main.c | 7 ++-----
|
||||
1 file changed, 2 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/multipath/main.c b/multipath/main.c
|
||||
index 4bbfce9a..9ae46ed5 100644
|
||||
--- a/multipath/main.c
|
||||
+++ b/multipath/main.c
|
||||
@@ -66,9 +66,6 @@
|
||||
#include "valid.h"
|
||||
#include "alias.h"
|
||||
|
||||
-int logsink;
|
||||
-struct udev *udev;
|
||||
-
|
||||
/*
|
||||
* Return values of configure(), check_path_valid(), and main().
|
||||
*/
|
||||
@@ -810,7 +807,7 @@ main (int argc, char *argv[])
|
||||
int retries = -1;
|
||||
bool enable_foreign = false;
|
||||
|
||||
- udev = udev_new();
|
||||
+ libmultipath_init();
|
||||
logsink = 0;
|
||||
if (init_config(DEFAULT_CONFIGFILE))
|
||||
exit(RTVL_FAIL);
|
||||
@@ -1068,7 +1065,7 @@ out_free_config:
|
||||
*/
|
||||
put_multipath_config(conf);
|
||||
uninit_config();
|
||||
- udev_unref(udev);
|
||||
+ libmultipath_exit();
|
||||
if (dev)
|
||||
FREE(dev);
|
||||
#ifdef _DEBUG_
|
@ -1,93 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 22 Sep 2020 14:23:14 +0200
|
||||
Subject: [PATCH] libmpathpersist: call libmultipath_{init,exit}()
|
||||
|
||||
Have libmpathpersist_{init,exit} do the udev initialization, too.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmpathpersist/mpath_persist.c | 11 ++++++++---
|
||||
libmpathpersist/mpath_persist.h | 9 ++++++---
|
||||
2 files changed, 14 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||
index febf4758..e1d1cb76 100644
|
||||
--- a/libmpathpersist/mpath_persist.c
|
||||
+++ b/libmpathpersist/mpath_persist.c
|
||||
@@ -48,6 +48,10 @@ int libmpathpersist_init(void)
|
||||
struct config *conf;
|
||||
int rc = 0;
|
||||
|
||||
+ if (libmultipath_init()) {
|
||||
+ condlog(0, "Failed to initialize libmultipath.");
|
||||
+ return 1;
|
||||
+ }
|
||||
if (init_config(DEFAULT_CONFIGFILE)) {
|
||||
condlog(0, "Failed to initialize multipath config.");
|
||||
return 1;
|
||||
@@ -74,23 +78,24 @@ mpath_lib_init (void)
|
||||
|
||||
static void libmpathpersist_cleanup(void)
|
||||
{
|
||||
- dm_lib_exit();
|
||||
cleanup_prio();
|
||||
cleanup_checkers();
|
||||
+ libmultipath_exit();
|
||||
+ dm_lib_exit();
|
||||
}
|
||||
|
||||
int
|
||||
mpath_lib_exit (struct config *conf)
|
||||
{
|
||||
- libmpathpersist_cleanup();
|
||||
free_config(conf);
|
||||
+ libmpathpersist_cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int libmpathpersist_exit(void)
|
||||
{
|
||||
- libmpathpersist_cleanup();
|
||||
uninit_config();
|
||||
+ libmpathpersist_cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/libmpathpersist/mpath_persist.h b/libmpathpersist/mpath_persist.h
|
||||
index 91606efc..5435eae4 100644
|
||||
--- a/libmpathpersist/mpath_persist.h
|
||||
+++ b/libmpathpersist/mpath_persist.h
|
||||
@@ -176,7 +176,8 @@ struct prout_param_descriptor { /* PROUT parameter descriptor */
|
||||
* Initialize device mapper multipath configuration. This function must be invoked first
|
||||
* before performing reservation management functions.
|
||||
* Either this function or mpath_lib_init() may be used.
|
||||
- * Use this function to work with libmultipath's internal "struct config".
|
||||
+ * Use this function to work with libmultipath's internal "struct config"
|
||||
+ * and "struct udev". The latter will be initialized automatically.
|
||||
* Call libmpathpersist_exit() for cleanup.
|
||||
* RESTRICTIONS:
|
||||
*
|
||||
@@ -189,7 +190,8 @@ extern int libmpathpersist_init (void);
|
||||
* Initialize device mapper multipath configuration. This function must be invoked first
|
||||
* before performing reservation management functions.
|
||||
* Either this function or libmpathpersist_init() may be used.
|
||||
- * Use this function to work with an application-specific "struct config".
|
||||
+ * Use this function to work with an application-specific "struct config"
|
||||
+ * and "struct udev". The latter must be initialized by the application.
|
||||
* Call mpath_lib_exit() for cleanup.
|
||||
* RESTRICTIONS:
|
||||
*
|
||||
@@ -211,9 +213,10 @@ extern int mpath_lib_exit (struct config *conf);
|
||||
|
||||
/*
|
||||
* DESCRIPTION :
|
||||
- * Release device mapper multipath configuration. This function must be invoked after
|
||||
+ * Release device mapper multipath configuration a. This function must be invoked after
|
||||
* performing reservation management functions.
|
||||
* Use this after initialization with libmpathpersist_init().
|
||||
+ * Calling libmpathpersist_init() after libmpathpersist_exit() will fail.
|
||||
* RESTRICTIONS:
|
||||
*
|
||||
* RETURNS: 0->Success, 1->Failed.
|
@ -1,49 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 16 Sep 2020 16:08:43 +0200
|
||||
Subject: [PATCH] mpathpersist: remove logsink and udev
|
||||
|
||||
We can use libmultipath's internal symbols now. The libmultipath
|
||||
initialization is taken care of by libmpathpersist_init().
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
mpathpersist/main.c | 6 ------
|
||||
1 file changed, 6 deletions(-)
|
||||
|
||||
diff --git a/mpathpersist/main.c b/mpathpersist/main.c
|
||||
index 278e48f7..3c2e6576 100644
|
||||
--- a/mpathpersist/main.c
|
||||
+++ b/mpathpersist/main.c
|
||||
@@ -42,13 +42,10 @@ void * mpath_alloc_prin_response(int prin_sa);
|
||||
void mpath_print_transport_id(struct prin_fulldescr *fdesc);
|
||||
int construct_transportid(const char * inp, struct transportid transid[], int num_transportids);
|
||||
|
||||
-int logsink;
|
||||
-
|
||||
void rcu_register_thread_memb(void) {}
|
||||
|
||||
void rcu_unregister_thread_memb(void) {}
|
||||
|
||||
-struct udev *udev;
|
||||
|
||||
static int verbose, loglevel, noisy;
|
||||
|
||||
@@ -641,16 +638,13 @@ int main(int argc, char *argv[])
|
||||
exit (1);
|
||||
}
|
||||
|
||||
- udev = udev_new();
|
||||
if (libmpathpersist_init()) {
|
||||
- udev_unref(udev);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = handle_args(argc, argv, 0);
|
||||
|
||||
libmpathpersist_exit();
|
||||
- udev_unref(udev);
|
||||
|
||||
return (ret >= 0) ? ret : MPATH_PR_OTHER;
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 11:28:22 +0200
|
||||
Subject: [PATCH] multipathd: remove logsink and udev
|
||||
|
||||
We can use the symbols from libmultipath now.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 9 +++------
|
||||
1 file changed, 3 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 00b66ba4..c5c374b7 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -115,7 +115,6 @@ struct mpath_event_param
|
||||
struct multipath *mpp;
|
||||
};
|
||||
|
||||
-int logsink;
|
||||
int uxsock_timeout;
|
||||
int verbosity;
|
||||
int bindings_read_only;
|
||||
@@ -151,8 +150,6 @@ int should_exit(void)
|
||||
*/
|
||||
struct vectors * gvecs;
|
||||
|
||||
-struct udev * udev;
|
||||
-
|
||||
struct config *multipath_conf;
|
||||
|
||||
/* Local variables */
|
||||
@@ -3123,8 +3120,6 @@ child (__attribute__((unused)) void *param)
|
||||
conf = rcu_dereference(multipath_conf);
|
||||
rcu_assign_pointer(multipath_conf, NULL);
|
||||
call_rcu(&conf->rcu, rcu_free_config);
|
||||
- udev_unref(udev);
|
||||
- udev = NULL;
|
||||
pthread_attr_destroy(&waiter_attr);
|
||||
pthread_attr_destroy(&io_err_stat_attr);
|
||||
#ifdef _DEBUG_
|
||||
@@ -3228,7 +3223,9 @@ main (int argc, char *argv[])
|
||||
|
||||
pthread_cond_init_mono(&config_cond);
|
||||
|
||||
- udev = udev_new();
|
||||
+ libmultipath_init();
|
||||
+ if (atexit(libmultipath_exit))
|
||||
+ condlog(3, "failed to register exit handler for libmultipath");
|
||||
libmp_udev_set_sync_support(0);
|
||||
|
||||
while ((arg = getopt(argc, argv, ":dsv:k::Bniw")) != EOF ) {
|
@ -1,37 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Xose Vazquez Perez <xose.vazquez@gmail.com>
|
||||
Date: Wed, 16 Dec 2020 23:17:39 +0100
|
||||
Subject: [PATCH] multipath-tools: add Vexata(by StorCentric) VX arrays
|
||||
|
||||
https://support.sas.com/resources/papers/performance-tuning-sas-vexata-systems.pdf
|
||||
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
Cc: Martin Wilck <mwilck@suse.com>
|
||||
Cc: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Cc: Christophe Varoqui <christophe.varoqui@opensvc.com>
|
||||
Cc: DM-DEVEL ML <dm-devel@redhat.com>
|
||||
Signed-off-by: Xose Vazquez Perez <xose.vazquez@gmail.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/hwtable.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
|
||||
index cd65afcc..c1d6f7ae 100644
|
||||
--- a/libmultipath/hwtable.c
|
||||
+++ b/libmultipath/hwtable.c
|
||||
@@ -1191,6 +1191,14 @@ static struct hwentry default_hw[] = {
|
||||
.product = "Magnitude",
|
||||
.pgpolicy = MULTIBUS,
|
||||
.no_path_retry = 30,
|
||||
+ },
|
||||
+ /* Vexata */
|
||||
+ {
|
||||
+ /* VX */
|
||||
+ .vendor = "Vexata",
|
||||
+ .product = "VX",
|
||||
+ .pgpolicy = MULTIBUS,
|
||||
+ .no_path_retry = 30,
|
||||
},
|
||||
/*
|
||||
* Promise Technology
|
@ -1,42 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Xose Vazquez Perez <xose.vazquez@gmail.com>
|
||||
Date: Wed, 16 Dec 2020 23:17:40 +0100
|
||||
Subject: [PATCH] multipath-tools: Violin and Nexsan were bought by StorCentric
|
||||
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
Cc: Martin Wilck <mwilck@suse.com>
|
||||
Cc: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Cc: Christophe Varoqui <christophe.varoqui@opensvc.com>
|
||||
Cc: DM-DEVEL ML <dm-devel@redhat.com>
|
||||
Signed-off-by: Xose Vazquez Perez <xose.vazquez@gmail.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/hwtable.c | 7 +++----
|
||||
1 file changed, 3 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
|
||||
index c1d6f7ae..a54cc0a3 100644
|
||||
--- a/libmultipath/hwtable.c
|
||||
+++ b/libmultipath/hwtable.c
|
||||
@@ -1113,8 +1113,9 @@ static struct hwentry default_hw[] = {
|
||||
.pgpolicy = MULTIBUS,
|
||||
},
|
||||
/*
|
||||
- * Imation/Nexsan
|
||||
+ * StorCentric
|
||||
*/
|
||||
+ /* Nexsan */
|
||||
{
|
||||
/* E-Series */
|
||||
.vendor = "NEXSAN",
|
||||
@@ -1143,9 +1144,7 @@ static struct hwentry default_hw[] = {
|
||||
.prio_name = PRIO_ALUA,
|
||||
.no_path_retry = 30,
|
||||
},
|
||||
- /*
|
||||
- * Violin Systems
|
||||
- */
|
||||
+ /* Violin Systems */
|
||||
{
|
||||
/* 3000 / 6000 Series */
|
||||
.vendor = "VIOLIN",
|
@ -1,114 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: lixiaokeng <lixiaokeng@huawei.com>
|
||||
Date: Mon, 9 Nov 2020 12:32:05 +0800
|
||||
Subject: [PATCH] libmultipath: fix memory leaks in coalesce_paths
|
||||
|
||||
When multipath -F are executed first and multipath -v2 or
|
||||
-d are executed later, asan will warn memory leaks. The
|
||||
reason is that the mpp allocated in coalesce_paths isn't
|
||||
freed. Here we use newmp to store mpp. If newmp need not
|
||||
be copied to mpvec, we free newmp at the end of the func.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Lixiaokeng <lixiaokeng@huawei.com>
|
||||
Signed-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
|
||||
Signed-off-by: Linfeilong <linfeilong@huawei.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/configure.c | 40 +++++++++++++++++++++++++++++-----------
|
||||
1 file changed, 29 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
||||
index 1c8aac08..d36f0d0d 100644
|
||||
--- a/libmultipath/configure.c
|
||||
+++ b/libmultipath/configure.c
|
||||
@@ -1139,7 +1139,7 @@ out:
|
||||
* FORCE_RELOAD_WEAK: existing maps are compared to the current conf and only
|
||||
* reloaded in DM if there's a difference. This is useful during startup.
|
||||
*/
|
||||
-int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
|
||||
+int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,
|
||||
int force_reload, enum mpath_cmds cmd)
|
||||
{
|
||||
int ret = CP_FAIL;
|
||||
@@ -1151,6 +1151,7 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
|
||||
struct path * pp2;
|
||||
vector curmp = vecs->mpvec;
|
||||
vector pathvec = vecs->pathvec;
|
||||
+ vector newmp;
|
||||
struct config *conf;
|
||||
int allow_queueing;
|
||||
struct bitfield *size_mismatch_seen;
|
||||
@@ -1171,6 +1172,15 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
|
||||
if (size_mismatch_seen == NULL)
|
||||
return CP_FAIL;
|
||||
|
||||
+ if (mpvec)
|
||||
+ newmp = mpvec;
|
||||
+ else
|
||||
+ newmp = vector_alloc();
|
||||
+ if (!newmp) {
|
||||
+ condlog(0, "can not allocate newmp");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
vector_foreach_slot (pathvec, pp1, k) {
|
||||
int invalid;
|
||||
|
||||
@@ -1283,8 +1293,14 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
- if (r == DOMAP_DRY)
|
||||
+ if (r == DOMAP_DRY) {
|
||||
+ if (!vector_alloc_slot(newmp)) {
|
||||
+ remove_map(mpp, vecs->pathvec, vecs->mpvec, KEEP_VEC);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ vector_set_slot(newmp, mpp);
|
||||
continue;
|
||||
+ }
|
||||
|
||||
if (r == DOMAP_EXIST && mpp->action == ACT_NOTHING &&
|
||||
force_reload == FORCE_RELOAD_WEAK)
|
||||
@@ -1320,22 +1336,22 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
|
||||
print_multipath_topology(mpp, verbosity);
|
||||
}
|
||||
|
||||
- if (newmp) {
|
||||
- if (mpp->action != ACT_REJECT) {
|
||||
- if (!vector_alloc_slot(newmp))
|
||||
- goto out;
|
||||
- vector_set_slot(newmp, mpp);
|
||||
+ if (mpp->action != ACT_REJECT) {
|
||||
+ if (!vector_alloc_slot(newmp)) {
|
||||
+ remove_map(mpp, vecs->pathvec, vecs->mpvec, KEEP_VEC);
|
||||
+ goto out;
|
||||
}
|
||||
- else
|
||||
- remove_map(mpp, vecs->pathvec, vecs->mpvec,
|
||||
- KEEP_VEC);
|
||||
+ vector_set_slot(newmp, mpp);
|
||||
}
|
||||
+ else
|
||||
+ remove_map(mpp, vecs->pathvec, vecs->mpvec,
|
||||
+ KEEP_VEC);
|
||||
}
|
||||
/*
|
||||
* Flush maps with only dead paths (ie not in sysfs)
|
||||
* Keep maps with only failed paths
|
||||
*/
|
||||
- if (newmp) {
|
||||
+ if (mpvec) {
|
||||
vector_foreach_slot (newmp, mpp, i) {
|
||||
char alias[WWID_SIZE];
|
||||
|
||||
@@ -1358,6 +1374,8 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid,
|
||||
ret = CP_OK;
|
||||
out:
|
||||
free(size_mismatch_seen);
|
||||
+ if (!mpvec)
|
||||
+ free_multipathvec(newmp, KEEP_PATHS);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Xose Vazquez Perez <xose.vazquez@gmail.com>
|
||||
Date: Thu, 17 Dec 2020 16:49:38 +0100
|
||||
Subject: [PATCH] multipath-tools: replace hidden tab by space in hwtable
|
||||
|
||||
Cc: Martin Wilck <mwilck@suse.com>
|
||||
Cc: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Cc: Christophe Varoqui <christophe.varoqui@opensvc.com>
|
||||
Cc: DM-DEVEL ML <dm-devel@redhat.com>
|
||||
Signed-off-by: Xose Vazquez Perez <xose.vazquez@gmail.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/hwtable.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
|
||||
index a54cc0a3..921aadc5 100644
|
||||
--- a/libmultipath/hwtable.c
|
||||
+++ b/libmultipath/hwtable.c
|
||||
@@ -819,7 +819,7 @@ static struct hwentry default_hw[] = {
|
||||
*
|
||||
* The hwtable is searched backwards, so place this after "Generic NVMe"
|
||||
*/
|
||||
- .vendor = "NVME",
|
||||
+ .vendor = "NVME",
|
||||
.product = "^NetApp ONTAP Controller",
|
||||
.pgpolicy = MULTIBUS,
|
||||
.no_path_retry = NO_PATH_RETRY_QUEUE,
|
@ -1,102 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 22 Sep 2020 20:59:25 +0200
|
||||
Subject: [PATCH] multipathd: uxlsnr: avoid deadlock on exit
|
||||
|
||||
The uxlsnr wouldn't always release the client lock when cancelled,
|
||||
causing a deadlock in uxsock_cleanup(). While this hasn't been
|
||||
caused by commit 3d611a2, the deadlock seems to have become much
|
||||
more likely after that patch. Solving this means that we have to
|
||||
treat reallocation failure of the pollfd array differently.
|
||||
We will now just ignore any clients above the last valid pfd index.
|
||||
That's a minor problem, as we're in an OOM situation anyway.
|
||||
|
||||
Moreover, client_lock is not a "struct lock", but a plain
|
||||
pthread_mutex_t.
|
||||
|
||||
Fixes: 3d611a2 ("multipathd: cancel threads early during shutdown")
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/uxlsnr.c | 24 ++++++++++++++----------
|
||||
1 file changed, 14 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/multipathd/uxlsnr.c b/multipathd/uxlsnr.c
|
||||
index 1c5ce9d2..ce2b6800 100644
|
||||
--- a/multipathd/uxlsnr.c
|
||||
+++ b/multipathd/uxlsnr.c
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "config.h"
|
||||
#include "mpath_cmd.h"
|
||||
#include "time-util.h"
|
||||
+#include "util.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "cli.h"
|
||||
@@ -116,7 +117,7 @@ static void _dead_client(struct client *c)
|
||||
|
||||
static void dead_client(struct client *c)
|
||||
{
|
||||
- pthread_cleanup_push(cleanup_lock, &client_lock);
|
||||
+ pthread_cleanup_push(cleanup_mutex, &client_lock);
|
||||
pthread_mutex_lock(&client_lock);
|
||||
_dead_client(c);
|
||||
pthread_cleanup_pop(1);
|
||||
@@ -302,10 +303,11 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, long ux_sock,
|
||||
sigdelset(&mask, SIGUSR1);
|
||||
while (1) {
|
||||
struct client *c, *tmp;
|
||||
- int i, poll_count, num_clients;
|
||||
+ int i, n_pfds, poll_count, num_clients;
|
||||
|
||||
/* setup for a poll */
|
||||
pthread_mutex_lock(&client_lock);
|
||||
+ pthread_cleanup_push(cleanup_mutex, &client_lock);
|
||||
num_clients = 0;
|
||||
list_for_each_entry(c, &clients, node) {
|
||||
num_clients++;
|
||||
@@ -322,14 +324,13 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, long ux_sock,
|
||||
sizeof(struct pollfd));
|
||||
}
|
||||
if (!new) {
|
||||
- pthread_mutex_unlock(&client_lock);
|
||||
condlog(0, "%s: failed to realloc %d poll fds",
|
||||
"uxsock", 2 + num_clients);
|
||||
- sched_yield();
|
||||
- continue;
|
||||
+ num_clients = old_clients;
|
||||
+ } else {
|
||||
+ old_clients = num_clients;
|
||||
+ polls = new;
|
||||
}
|
||||
- old_clients = num_clients;
|
||||
- polls = new;
|
||||
}
|
||||
polls[0].fd = ux_sock;
|
||||
polls[0].events = POLLIN;
|
||||
@@ -347,11 +348,14 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, long ux_sock,
|
||||
polls[i].fd = c->fd;
|
||||
polls[i].events = POLLIN;
|
||||
i++;
|
||||
+ if (i >= 2 + num_clients)
|
||||
+ break;
|
||||
}
|
||||
- pthread_mutex_unlock(&client_lock);
|
||||
+ n_pfds = i;
|
||||
+ pthread_cleanup_pop(1);
|
||||
|
||||
/* most of our life is spent in this call */
|
||||
- poll_count = ppoll(polls, i, &sleep_time, &mask);
|
||||
+ poll_count = ppoll(polls, n_pfds, &sleep_time, &mask);
|
||||
|
||||
handle_signals(false);
|
||||
if (poll_count == -1) {
|
||||
@@ -384,7 +388,7 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, long ux_sock,
|
||||
}
|
||||
|
||||
/* see if a client wants to speak to us */
|
||||
- for (i = 2; i < num_clients + 2; i++) {
|
||||
+ for (i = 2; i < n_pfds; i++) {
|
||||
if (polls[i].revents & POLLIN) {
|
||||
struct timespec start_time;
|
||||
|
@ -1,95 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 18:02:39 +0200
|
||||
Subject: [PATCH] multipathd: Fix liburcu memory leak
|
||||
|
||||
Fix this leak in multipathd, reported by valgrind, that messes up
|
||||
multipathd's otherwise clean leak report:
|
||||
|
||||
==23823== 336 bytes in 1 blocks are possibly lost in loss record 3 of 3
|
||||
==23823== at 0x483AB65: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
|
||||
==23823== by 0x4012F16: _dl_allocate_tls (in /lib64/ld-2.31.so)
|
||||
==23823== by 0x493BB8E: pthread_create@@GLIBC_2.2.5 (in /lib64/libpthread-2.31.so)
|
||||
==23823== by 0x492A9A9: call_rcu_data_init (urcu-call-rcu-impl.h:437)
|
||||
==23823== by 0x492AD2F: UnknownInlinedFun (urcu-call-rcu-impl.h:492)
|
||||
==23823== by 0x492AD2F: create_call_rcu_data_memb (urcu-call-rcu-impl.h:504)
|
||||
==23823== by 0x1164E3: child.constprop.0.isra.0 (main.c:2915)
|
||||
==23823== by 0x10F50C: main (main.c:3335)
|
||||
==23823==
|
||||
==23823== LEAK SUMMARY:
|
||||
==23823== definitely lost: 0 bytes in 0 blocks
|
||||
==23823== indirectly lost: 0 bytes in 0 blocks
|
||||
==23823== possibly lost: 336 bytes in 1 blocks
|
||||
|
||||
The problem is caused by using liburcu's default RCU call handler,
|
||||
which liburcu refuses to stop/join. See comments in the code.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 44 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index c5c374b7..ce14bb66 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -2889,6 +2889,48 @@ set_oom_adj (void)
|
||||
condlog(0, "couldn't adjust oom score");
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Use a non-default call_rcu_data for child().
|
||||
+ *
|
||||
+ * We do this to avoid a memory leak from liburcu.
|
||||
+ * liburcu never frees the default rcu handler (see comments on
|
||||
+ * call_rcu_data_free() in urcu-call-rcu-impl.h), its thread
|
||||
+ * can't be joined with pthread_join(), leaving a memory leak.
|
||||
+ *
|
||||
+ * Therefore we create our own, which can be destroyed and joined.
|
||||
+ */
|
||||
+static struct call_rcu_data *setup_rcu(void)
|
||||
+{
|
||||
+ struct call_rcu_data *crdp;
|
||||
+
|
||||
+ rcu_init();
|
||||
+ rcu_register_thread();
|
||||
+ crdp = create_call_rcu_data(0UL, -1);
|
||||
+ if (crdp != NULL)
|
||||
+ set_thread_call_rcu_data(crdp);
|
||||
+ return crdp;
|
||||
+}
|
||||
+
|
||||
+static struct call_rcu_data *mp_rcu_data;
|
||||
+
|
||||
+static void cleanup_rcu(void)
|
||||
+{
|
||||
+ pthread_t rcu_thread;
|
||||
+
|
||||
+ /* Wait for any pending RCU calls */
|
||||
+ rcu_barrier();
|
||||
+ if (mp_rcu_data != NULL) {
|
||||
+ rcu_thread = get_call_rcu_thread(mp_rcu_data);
|
||||
+ /* detach this thread from the RCU thread */
|
||||
+ set_thread_call_rcu_data(NULL);
|
||||
+ synchronize_rcu();
|
||||
+ /* tell RCU thread to exit */
|
||||
+ call_rcu_data_free(mp_rcu_data);
|
||||
+ pthread_join(rcu_thread, NULL);
|
||||
+ }
|
||||
+ rcu_unregister_thread();
|
||||
+}
|
||||
+
|
||||
static int
|
||||
child (__attribute__((unused)) void *param)
|
||||
{
|
||||
@@ -2906,7 +2948,8 @@ child (__attribute__((unused)) void *param)
|
||||
|
||||
mlockall(MCL_CURRENT | MCL_FUTURE);
|
||||
signal_init();
|
||||
- rcu_init();
|
||||
+ mp_rcu_data = setup_rcu();
|
||||
+ atexit(cleanup_rcu);
|
||||
|
||||
setup_thread_attr(&misc_attr, 64 * 1024, 0);
|
||||
setup_thread_attr(&uevent_attr, DEFAULT_UEVENT_STACKSIZE * 1024, 0);
|
@ -1,143 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 10:33:12 +0200
|
||||
Subject: [PATCH] multipathd: move handling of io_err_stat_attr into
|
||||
libmultipath
|
||||
|
||||
This thread attribute can be dynamically initialized and destroyed.
|
||||
No need to carry it along in multipathd. Removal of the symbol
|
||||
requires to bump the ABI version to 3.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/io_err_stat.c | 7 +++++--
|
||||
libmultipath/libmultipath.version | 23 ++++++++---------------
|
||||
multipathd/main.c | 2 --
|
||||
3 files changed, 13 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
|
||||
index 58bc1dd2..5363049d 100644
|
||||
--- a/libmultipath/io_err_stat.c
|
||||
+++ b/libmultipath/io_err_stat.c
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "lock.h"
|
||||
#include "time-util.h"
|
||||
#include "io_err_stat.h"
|
||||
+#include "util.h"
|
||||
|
||||
#define TIMEOUT_NO_IO_NSEC 10000000 /*10ms = 10000000ns*/
|
||||
#define FLAKY_PATHFAIL_THRESHOLD 2
|
||||
@@ -70,8 +71,7 @@ struct io_err_stat_path {
|
||||
int err_rate_threshold;
|
||||
};
|
||||
|
||||
-pthread_t io_err_stat_thr;
|
||||
-pthread_attr_t io_err_stat_attr;
|
||||
+static pthread_t io_err_stat_thr;
|
||||
|
||||
static pthread_mutex_t io_err_thread_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t io_err_thread_cond = PTHREAD_COND_INITIALIZER;
|
||||
@@ -727,6 +727,7 @@ static void *io_err_stat_loop(void *data)
|
||||
int start_io_err_stat_thread(void *data)
|
||||
{
|
||||
int ret;
|
||||
+ pthread_attr_t io_err_stat_attr;
|
||||
|
||||
if (uatomic_read(&io_err_thread_running) == 1)
|
||||
return 0;
|
||||
@@ -739,6 +740,7 @@ int start_io_err_stat_thread(void *data)
|
||||
if (!paths)
|
||||
goto destroy_ctx;
|
||||
|
||||
+ setup_thread_attr(&io_err_stat_attr, 32 * 1024, 0);
|
||||
pthread_mutex_lock(&io_err_thread_lock);
|
||||
pthread_cleanup_push(cleanup_unlock, &io_err_thread_lock);
|
||||
|
||||
@@ -750,6 +752,7 @@ int start_io_err_stat_thread(void *data)
|
||||
&io_err_thread_lock) == 0);
|
||||
|
||||
pthread_cleanup_pop(1);
|
||||
+ pthread_attr_destroy(&io_err_stat_attr);
|
||||
|
||||
if (ret) {
|
||||
io_err_stat_log(0, "cannot create io_error statistic thread");
|
||||
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
|
||||
index 0c300c81..84beb7f0 100644
|
||||
--- a/libmultipath/libmultipath.version
|
||||
+++ b/libmultipath/libmultipath.version
|
||||
@@ -31,7 +31,7 @@
|
||||
* The new version inherits the previous ones.
|
||||
*/
|
||||
|
||||
-LIBMULTIPATH_2.0.0 {
|
||||
+LIBMULTIPATH_3.0.0 {
|
||||
global:
|
||||
/* symbols referenced by multipath and multipathd */
|
||||
add_foreign;
|
||||
@@ -121,7 +121,6 @@ global:
|
||||
init_checkers;
|
||||
init_foreign;
|
||||
init_prio;
|
||||
- io_err_stat_attr;
|
||||
io_err_stat_handle_pathfail;
|
||||
is_path_valid;
|
||||
is_quote;
|
||||
@@ -242,30 +241,24 @@ global:
|
||||
free_scandir_result;
|
||||
sysfs_attr_get_value;
|
||||
|
||||
-local:
|
||||
- *;
|
||||
-};
|
||||
-
|
||||
-LIBMULTIPATH_2.1.0 {
|
||||
-global:
|
||||
+ /* added in 2.1.0 */
|
||||
libmp_dm_task_run;
|
||||
cleanup_mutex;
|
||||
-} LIBMULTIPATH_2.0.0;
|
||||
|
||||
-LIBMULTIPATH_2.2.0 {
|
||||
-global:
|
||||
+ /* added in 2.2.0 */
|
||||
libmp_get_multipath_config;
|
||||
get_multipath_config;
|
||||
libmp_put_multipath_config;
|
||||
put_multipath_config;
|
||||
init_config;
|
||||
uninit_config;
|
||||
-} LIBMULTIPATH_2.1.0;
|
||||
|
||||
-LIBMULTIPATH_2.3.0 {
|
||||
-global:
|
||||
+ /* added in 2.3.0 */
|
||||
udev;
|
||||
logsink;
|
||||
libmultipath_init;
|
||||
libmultipath_exit;
|
||||
-} LIBMULTIPATH_2.2.0;
|
||||
+
|
||||
+local:
|
||||
+ *;
|
||||
+};
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index ce14bb66..abc6a9f7 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -2954,7 +2954,6 @@ child (__attribute__((unused)) void *param)
|
||||
setup_thread_attr(&misc_attr, 64 * 1024, 0);
|
||||
setup_thread_attr(&uevent_attr, DEFAULT_UEVENT_STACKSIZE * 1024, 0);
|
||||
setup_thread_attr(&waiter_attr, 32 * 1024, 1);
|
||||
- setup_thread_attr(&io_err_stat_attr, 32 * 1024, 0);
|
||||
|
||||
if (logsink == 1) {
|
||||
setup_thread_attr(&log_attr, 64 * 1024, 0);
|
||||
@@ -3164,7 +3163,6 @@ child (__attribute__((unused)) void *param)
|
||||
rcu_assign_pointer(multipath_conf, NULL);
|
||||
call_rcu(&conf->rcu, rcu_free_config);
|
||||
pthread_attr_destroy(&waiter_attr);
|
||||
- pthread_attr_destroy(&io_err_stat_attr);
|
||||
#ifdef _DEBUG_
|
||||
dbg_free_final(NULL);
|
||||
#endif
|
@ -1,122 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 18:05:40 +0200
|
||||
Subject: [PATCH] multipathd: move vecs desctruction into cleanup function
|
||||
|
||||
This will make it easer to move the stuff around later.
|
||||
The only functional change is that map destuction now happens after
|
||||
joining all threads, which should actually improve robustness.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 64 +++++++++++++++++++++++++++++------------------
|
||||
1 file changed, 40 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index abc6a9f7..3da0d7cc 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -148,7 +148,7 @@ int should_exit(void)
|
||||
/*
|
||||
* global copy of vecs for use in sig handlers
|
||||
*/
|
||||
-struct vectors * gvecs;
|
||||
+static struct vectors * gvecs;
|
||||
|
||||
struct config *multipath_conf;
|
||||
|
||||
@@ -2889,6 +2889,44 @@ set_oom_adj (void)
|
||||
condlog(0, "couldn't adjust oom score");
|
||||
}
|
||||
|
||||
+static void cleanup_maps(struct vectors *vecs)
|
||||
+{
|
||||
+ int queue_without_daemon, i;
|
||||
+ struct multipath *mpp;
|
||||
+ struct config *conf;
|
||||
+
|
||||
+ conf = get_multipath_config();
|
||||
+ queue_without_daemon = conf->queue_without_daemon;
|
||||
+ put_multipath_config(conf);
|
||||
+ if (queue_without_daemon == QUE_NO_DAEMON_OFF)
|
||||
+ vector_foreach_slot(vecs->mpvec, mpp, i)
|
||||
+ dm_queue_if_no_path(mpp->alias, 0);
|
||||
+ remove_maps_and_stop_waiters(vecs);
|
||||
+ vecs->mpvec = NULL;
|
||||
+}
|
||||
+
|
||||
+static void cleanup_paths(struct vectors *vecs)
|
||||
+{
|
||||
+ free_pathvec(vecs->pathvec, FREE_PATHS);
|
||||
+ vecs->pathvec = NULL;
|
||||
+}
|
||||
+
|
||||
+static void cleanup_vecs(void)
|
||||
+{
|
||||
+ if (!gvecs)
|
||||
+ return;
|
||||
+ /*
|
||||
+ * We can't take the vecs lock here, because exit() may
|
||||
+ * have been called from the child() thread, holding the lock already.
|
||||
+ * Anyway, by the time we get here, all threads that might access
|
||||
+ * vecs should have been joined already (in cleanup_threads).
|
||||
+ */
|
||||
+ cleanup_maps(gvecs);
|
||||
+ cleanup_paths(gvecs);
|
||||
+ pthread_mutex_destroy(&gvecs->lock.mutex);
|
||||
+ FREE(gvecs);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Use a non-default call_rcu_data for child().
|
||||
*
|
||||
@@ -2937,13 +2975,10 @@ child (__attribute__((unused)) void *param)
|
||||
pthread_t check_thr, uevent_thr, uxlsnr_thr, uevq_thr, dmevent_thr;
|
||||
pthread_attr_t log_attr, misc_attr, uevent_attr;
|
||||
struct vectors * vecs;
|
||||
- struct multipath * mpp;
|
||||
- int i;
|
||||
int rc;
|
||||
int pid_fd = -1;
|
||||
struct config *conf;
|
||||
char *envp;
|
||||
- int queue_without_daemon;
|
||||
enum daemon_status state;
|
||||
|
||||
mlockall(MCL_CURRENT | MCL_FUTURE);
|
||||
@@ -3108,17 +3143,6 @@ child (__attribute__((unused)) void *param)
|
||||
if (poll_dmevents)
|
||||
pthread_cancel(dmevent_thr);
|
||||
|
||||
- conf = get_multipath_config();
|
||||
- queue_without_daemon = conf->queue_without_daemon;
|
||||
- put_multipath_config(conf);
|
||||
-
|
||||
- lock(&vecs->lock);
|
||||
- if (queue_without_daemon == QUE_NO_DAEMON_OFF)
|
||||
- vector_foreach_slot(vecs->mpvec, mpp, i)
|
||||
- dm_queue_if_no_path(mpp->alias, 0);
|
||||
- remove_maps_and_stop_waiters(vecs);
|
||||
- unlock(&vecs->lock);
|
||||
-
|
||||
pthread_join(check_thr, NULL);
|
||||
pthread_join(uevent_thr, NULL);
|
||||
pthread_join(uxlsnr_thr, NULL);
|
||||
@@ -3128,15 +3152,7 @@ child (__attribute__((unused)) void *param)
|
||||
|
||||
stop_io_err_stat_thread();
|
||||
|
||||
- lock(&vecs->lock);
|
||||
- free_pathvec(vecs->pathvec, FREE_PATHS);
|
||||
- vecs->pathvec = NULL;
|
||||
- unlock(&vecs->lock);
|
||||
-
|
||||
- pthread_mutex_destroy(&vecs->lock.mutex);
|
||||
- FREE(vecs);
|
||||
- vecs = NULL;
|
||||
-
|
||||
+ cleanup_vecs();
|
||||
cleanup_foreign();
|
||||
cleanup_checkers();
|
||||
cleanup_prio();
|
@ -1,42 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 11:18:02 +0200
|
||||
Subject: [PATCH] multipathd: make some globals static
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 14 +++++++-------
|
||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 3da0d7cc..eb760a71 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -116,19 +116,19 @@ struct mpath_event_param
|
||||
};
|
||||
|
||||
int uxsock_timeout;
|
||||
-int verbosity;
|
||||
-int bindings_read_only;
|
||||
+static int verbosity;
|
||||
+static int bindings_read_only;
|
||||
int ignore_new_devs;
|
||||
#ifdef NO_DMEVENTS_POLL
|
||||
-int poll_dmevents = 0;
|
||||
+static int poll_dmevents = 0;
|
||||
#else
|
||||
-int poll_dmevents = 1;
|
||||
+static int poll_dmevents = 1;
|
||||
#endif
|
||||
/* Don't access this variable without holding config_lock */
|
||||
-volatile enum daemon_status running_state = DAEMON_INIT;
|
||||
+static volatile enum daemon_status running_state = DAEMON_INIT;
|
||||
pid_t daemon_pid;
|
||||
-pthread_mutex_t config_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
-pthread_cond_t config_cond;
|
||||
+static pthread_mutex_t config_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
+static pthread_cond_t config_cond;
|
||||
|
||||
static inline enum daemon_status get_running_state(void)
|
||||
{
|
@ -1,161 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 11:18:44 +0200
|
||||
Subject: [PATCH] multipathd: move threads destruction into separate function
|
||||
|
||||
Also, introduce booleans that indicate a certain thread has
|
||||
been started successfully. Using these booleans, we can avoid
|
||||
crashing by cancelling threads that have never been started.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 76 +++++++++++++++++++++++++++++++----------------
|
||||
1 file changed, 51 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index eb760a71..9eb658d4 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -129,6 +129,9 @@ static volatile enum daemon_status running_state = DAEMON_INIT;
|
||||
pid_t daemon_pid;
|
||||
static pthread_mutex_t config_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t config_cond;
|
||||
+static pthread_t check_thr, uevent_thr, uxlsnr_thr, uevq_thr, dmevent_thr;
|
||||
+static bool check_thr_started, uevent_thr_started, uxlsnr_thr_started,
|
||||
+ uevq_thr_started, dmevent_thr_started;
|
||||
|
||||
static inline enum daemon_status get_running_state(void)
|
||||
{
|
||||
@@ -2927,6 +2930,39 @@ static void cleanup_vecs(void)
|
||||
FREE(gvecs);
|
||||
}
|
||||
|
||||
+static void cleanup_threads(void)
|
||||
+{
|
||||
+ stop_io_err_stat_thread();
|
||||
+
|
||||
+ if (check_thr_started)
|
||||
+ pthread_cancel(check_thr);
|
||||
+ if (uevent_thr_started)
|
||||
+ pthread_cancel(uevent_thr);
|
||||
+ if (uxlsnr_thr_started)
|
||||
+ pthread_cancel(uxlsnr_thr);
|
||||
+ if (uevq_thr_started)
|
||||
+ pthread_cancel(uevq_thr);
|
||||
+ if (dmevent_thr_started)
|
||||
+ pthread_cancel(dmevent_thr);
|
||||
+
|
||||
+ if (check_thr_started)
|
||||
+ pthread_join(check_thr, NULL);
|
||||
+ if (uevent_thr_started)
|
||||
+ pthread_join(uevent_thr, NULL);
|
||||
+ if (uxlsnr_thr_started)
|
||||
+ pthread_join(uxlsnr_thr, NULL);
|
||||
+ if (uevq_thr_started)
|
||||
+ pthread_join(uevq_thr, NULL);
|
||||
+ if (dmevent_thr_started)
|
||||
+ pthread_join(dmevent_thr, NULL);
|
||||
+
|
||||
+ /*
|
||||
+ * As all threads are joined now, and we're in DAEMON_SHUTDOWN
|
||||
+ * state, no new waiter threads will be created any more.
|
||||
+ */
|
||||
+ pthread_attr_destroy(&waiter_attr);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Use a non-default call_rcu_data for child().
|
||||
*
|
||||
@@ -2972,7 +3008,6 @@ static void cleanup_rcu(void)
|
||||
static int
|
||||
child (__attribute__((unused)) void *param)
|
||||
{
|
||||
- pthread_t check_thr, uevent_thr, uxlsnr_thr, uevq_thr, dmevent_thr;
|
||||
pthread_attr_t log_attr, misc_attr, uevent_attr;
|
||||
struct vectors * vecs;
|
||||
int rc;
|
||||
@@ -3070,9 +3105,12 @@ child (__attribute__((unused)) void *param)
|
||||
condlog(0, "failed to create cli listener: %d", rc);
|
||||
goto failed;
|
||||
}
|
||||
- else if (state != DAEMON_CONFIGURE) {
|
||||
- condlog(0, "cli listener failed to start");
|
||||
- goto failed;
|
||||
+ else {
|
||||
+ uxlsnr_thr_started = true;
|
||||
+ if (state != DAEMON_CONFIGURE) {
|
||||
+ condlog(0, "cli listener failed to start");
|
||||
+ goto failed;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (poll_dmevents) {
|
||||
@@ -3085,7 +3123,8 @@ child (__attribute__((unused)) void *param)
|
||||
condlog(0, "failed to create dmevent waiter thread: %d",
|
||||
rc);
|
||||
goto failed;
|
||||
- }
|
||||
+ } else
|
||||
+ dmevent_thr_started = true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3094,7 +3133,8 @@ child (__attribute__((unused)) void *param)
|
||||
if ((rc = pthread_create(&uevent_thr, &uevent_attr, ueventloop, udev))) {
|
||||
condlog(0, "failed to create uevent thread: %d", rc);
|
||||
goto failed;
|
||||
- }
|
||||
+ } else
|
||||
+ uevent_thr_started = true;
|
||||
pthread_attr_destroy(&uevent_attr);
|
||||
|
||||
/*
|
||||
@@ -3103,11 +3143,13 @@ child (__attribute__((unused)) void *param)
|
||||
if ((rc = pthread_create(&check_thr, &misc_attr, checkerloop, vecs))) {
|
||||
condlog(0,"failed to create checker loop thread: %d", rc);
|
||||
goto failed;
|
||||
- }
|
||||
+ } else
|
||||
+ check_thr_started = true;
|
||||
if ((rc = pthread_create(&uevq_thr, &misc_attr, uevqloop, vecs))) {
|
||||
condlog(0, "failed to create uevent dispatcher: %d", rc);
|
||||
goto failed;
|
||||
- }
|
||||
+ } else
|
||||
+ uevq_thr_started = true;
|
||||
pthread_attr_destroy(&misc_attr);
|
||||
|
||||
while (1) {
|
||||
@@ -3136,22 +3178,7 @@ child (__attribute__((unused)) void *param)
|
||||
}
|
||||
}
|
||||
|
||||
- pthread_cancel(check_thr);
|
||||
- pthread_cancel(uevent_thr);
|
||||
- pthread_cancel(uxlsnr_thr);
|
||||
- pthread_cancel(uevq_thr);
|
||||
- if (poll_dmevents)
|
||||
- pthread_cancel(dmevent_thr);
|
||||
-
|
||||
- pthread_join(check_thr, NULL);
|
||||
- pthread_join(uevent_thr, NULL);
|
||||
- pthread_join(uxlsnr_thr, NULL);
|
||||
- pthread_join(uevq_thr, NULL);
|
||||
- if (poll_dmevents)
|
||||
- pthread_join(dmevent_thr, NULL);
|
||||
-
|
||||
- stop_io_err_stat_thread();
|
||||
-
|
||||
+ cleanup_threads();
|
||||
cleanup_vecs();
|
||||
cleanup_foreign();
|
||||
cleanup_checkers();
|
||||
@@ -3178,7 +3205,6 @@ child (__attribute__((unused)) void *param)
|
||||
conf = rcu_dereference(multipath_conf);
|
||||
rcu_assign_pointer(multipath_conf, NULL);
|
||||
call_rcu(&conf->rcu, rcu_free_config);
|
||||
- pthread_attr_destroy(&waiter_attr);
|
||||
#ifdef _DEBUG_
|
||||
dbg_free_final(NULL);
|
||||
#endif
|
@ -1,53 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 12:38:50 +0200
|
||||
Subject: [PATCH] multipathd: move conf destruction into separate function
|
||||
|
||||
Also removing the comment about dlog() and dm_write_log().
|
||||
dlog() can cope with get_multipath_config() returning NULL,
|
||||
and dm_write_log() hasn't accessed the configuration for a while.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 20 +++++++++++---------
|
||||
1 file changed, 11 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 9eb658d4..07973e85 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -2892,6 +2892,16 @@ set_oom_adj (void)
|
||||
condlog(0, "couldn't adjust oom score");
|
||||
}
|
||||
|
||||
+static void cleanup_conf(void) {
|
||||
+ struct config *conf;
|
||||
+
|
||||
+ conf = rcu_dereference(multipath_conf);
|
||||
+ if (!conf)
|
||||
+ return;
|
||||
+ rcu_assign_pointer(multipath_conf, NULL);
|
||||
+ call_rcu(&conf->rcu, rcu_free_config);
|
||||
+}
|
||||
+
|
||||
static void cleanup_maps(struct vectors *vecs)
|
||||
{
|
||||
int queue_without_daemon, i;
|
||||
@@ -3196,15 +3206,7 @@ child (__attribute__((unused)) void *param)
|
||||
|
||||
if (logsink == 1)
|
||||
log_thread_stop();
|
||||
-
|
||||
- /*
|
||||
- * Freeing config must be done after condlog() and dm_lib_exit(),
|
||||
- * because logging functions like dlog() and dm_write_log()
|
||||
- * reference the config.
|
||||
- */
|
||||
- conf = rcu_dereference(multipath_conf);
|
||||
- rcu_assign_pointer(multipath_conf, NULL);
|
||||
- call_rcu(&conf->rcu, rcu_free_config);
|
||||
+ cleanup_conf();
|
||||
#ifdef _DEBUG_
|
||||
dbg_free_final(NULL);
|
||||
#endif
|
@ -1,39 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 16:10:19 +0200
|
||||
Subject: [PATCH] multipathd: move pid destruction into separate function
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 10 +++++++---
|
||||
1 file changed, 7 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 07973e85..fc1f8d7f 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -2892,6 +2892,12 @@ set_oom_adj (void)
|
||||
condlog(0, "couldn't adjust oom score");
|
||||
}
|
||||
|
||||
+static void cleanup_pidfile(void)
|
||||
+{
|
||||
+ condlog(3, "unlink pidfile");
|
||||
+ unlink(DEFAULT_PIDFILE);
|
||||
+}
|
||||
+
|
||||
static void cleanup_conf(void) {
|
||||
struct config *conf;
|
||||
|
||||
@@ -3199,9 +3205,7 @@ child (__attribute__((unused)) void *param)
|
||||
dm_lib_exit();
|
||||
|
||||
/* We're done here */
|
||||
- condlog(3, "unlink pidfile");
|
||||
- unlink(DEFAULT_PIDFILE);
|
||||
-
|
||||
+ cleanup_pidfile();
|
||||
condlog(2, "--------shut down-------");
|
||||
|
||||
if (logsink == 1)
|
@ -1,42 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 16:27:33 +0200
|
||||
Subject: [PATCH] multipathd: close pidfile on exit
|
||||
|
||||
It seems we've been doing this only in the failure case, for ages.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index fc1f8d7f..f6b80668 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -132,6 +132,7 @@ static pthread_cond_t config_cond;
|
||||
static pthread_t check_thr, uevent_thr, uxlsnr_thr, uevq_thr, dmevent_thr;
|
||||
static bool check_thr_started, uevent_thr_started, uxlsnr_thr_started,
|
||||
uevq_thr_started, dmevent_thr_started;
|
||||
+static int pid_fd = -1;
|
||||
|
||||
static inline enum daemon_status get_running_state(void)
|
||||
{
|
||||
@@ -2894,6 +2895,8 @@ set_oom_adj (void)
|
||||
|
||||
static void cleanup_pidfile(void)
|
||||
{
|
||||
+ if (pid_fd >= 0)
|
||||
+ close(pid_fd);
|
||||
condlog(3, "unlink pidfile");
|
||||
unlink(DEFAULT_PIDFILE);
|
||||
}
|
||||
@@ -3027,7 +3030,6 @@ child (__attribute__((unused)) void *param)
|
||||
pthread_attr_t log_attr, misc_attr, uevent_attr;
|
||||
struct vectors * vecs;
|
||||
int rc;
|
||||
- int pid_fd = -1;
|
||||
struct config *conf;
|
||||
char *envp;
|
||||
enum daemon_status state;
|
@ -1,57 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 17:49:02 +0200
|
||||
Subject: [PATCH] multipathd: add helper for systemd notification at exit
|
||||
|
||||
Add sd_notify_exit().
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 22 +++++++++++++---------
|
||||
1 file changed, 13 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index f6b80668..07068e4a 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -3024,6 +3024,17 @@ static void cleanup_rcu(void)
|
||||
rcu_unregister_thread();
|
||||
}
|
||||
|
||||
+static int sd_notify_exit(int err)
|
||||
+{
|
||||
+#ifdef USE_SYSTEMD
|
||||
+ char msg[24];
|
||||
+
|
||||
+ snprintf(msg, sizeof(msg), "ERRNO=%d", err);
|
||||
+ sd_notify(0, msg);
|
||||
+#endif
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
static int
|
||||
child (__attribute__((unused)) void *param)
|
||||
{
|
||||
@@ -3216,19 +3227,12 @@ child (__attribute__((unused)) void *param)
|
||||
#ifdef _DEBUG_
|
||||
dbg_free_final(NULL);
|
||||
#endif
|
||||
-
|
||||
-#ifdef USE_SYSTEMD
|
||||
- sd_notify(0, "ERRNO=0");
|
||||
-#endif
|
||||
- exit(0);
|
||||
+ exit(sd_notify_exit(0));
|
||||
|
||||
failed:
|
||||
-#ifdef USE_SYSTEMD
|
||||
- sd_notify(0, "ERRNO=1");
|
||||
-#endif
|
||||
if (pid_fd >= 0)
|
||||
close(pid_fd);
|
||||
- exit(1);
|
||||
+ exit(sd_notify_exit(1));
|
||||
}
|
||||
|
||||
static int
|
@ -1,49 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 17:57:16 +0200
|
||||
Subject: [PATCH] multipathd: child(): call cleanups in failure case, too
|
||||
|
||||
So far we haven't called any cleanup code if child() failed.
|
||||
Fix it.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 10 ++++------
|
||||
1 file changed, 4 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 07068e4a..6b9e323e 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -3044,6 +3044,7 @@ child (__attribute__((unused)) void *param)
|
||||
struct config *conf;
|
||||
char *envp;
|
||||
enum daemon_status state;
|
||||
+ int exit_code = 1;
|
||||
|
||||
mlockall(MCL_CURRENT | MCL_FUTURE);
|
||||
signal_init();
|
||||
@@ -3207,6 +3208,8 @@ child (__attribute__((unused)) void *param)
|
||||
}
|
||||
}
|
||||
|
||||
+ exit_code = 0;
|
||||
+failed:
|
||||
cleanup_threads();
|
||||
cleanup_vecs();
|
||||
cleanup_foreign();
|
||||
@@ -3227,12 +3230,7 @@ child (__attribute__((unused)) void *param)
|
||||
#ifdef _DEBUG_
|
||||
dbg_free_final(NULL);
|
||||
#endif
|
||||
- exit(sd_notify_exit(0));
|
||||
-
|
||||
-failed:
|
||||
- if (pid_fd >= 0)
|
||||
- close(pid_fd);
|
||||
- exit(sd_notify_exit(1));
|
||||
+ return sd_notify_exit(exit_code);
|
||||
}
|
||||
|
||||
static int
|
@ -1,25 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 18:45:30 +0200
|
||||
Subject: [PATCH] multipathd: unwatch_all_dmevents: check if waiter is
|
||||
initialized
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/dmevents.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/multipathd/dmevents.c b/multipathd/dmevents.c
|
||||
index b561cbfd..f52f5970 100644
|
||||
--- a/multipathd/dmevents.c
|
||||
+++ b/multipathd/dmevents.c
|
||||
@@ -257,6 +257,8 @@ void unwatch_all_dmevents(void)
|
||||
struct dev_event *dev_evt;
|
||||
int i;
|
||||
|
||||
+ if (!waiter)
|
||||
+ return;
|
||||
pthread_mutex_lock(&waiter->events_lock);
|
||||
vector_foreach_slot(waiter->events, dev_evt, i)
|
||||
free(dev_evt);
|
@ -1,27 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 18:45:51 +0200
|
||||
Subject: [PATCH] multipathd: print error message if config can't be loaded
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 6b9e323e..7ab3eab8 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -3074,8 +3074,10 @@ child (__attribute__((unused)) void *param)
|
||||
condlog(2, "read " DEFAULT_CONFIGFILE);
|
||||
|
||||
conf = load_config(DEFAULT_CONFIGFILE);
|
||||
- if (!conf)
|
||||
+ if (!conf) {
|
||||
+ condlog(0, "failed to load configuration");
|
||||
goto failed;
|
||||
+ }
|
||||
|
||||
if (verbosity)
|
||||
conf->verbosity = verbosity;
|
@ -1,89 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 21:02:45 +0200
|
||||
Subject: [PATCH] libmultipath: add libmp_dm_exit()
|
||||
|
||||
This function prepares for calling dm_lib_exit() on program exit.
|
||||
It undoes changes to libdm internals done by libmultipath.
|
||||
It doesn't call dm_lib_exit(), as the caller may want to keep
|
||||
libdm active.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/config.c | 1 +
|
||||
libmultipath/config.h | 2 ++
|
||||
libmultipath/devmapper.c | 15 +++++++++++++++
|
||||
libmultipath/devmapper.h | 1 +
|
||||
4 files changed, 19 insertions(+)
|
||||
|
||||
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||
index f74417c6..b9cb4131 100644
|
||||
--- a/libmultipath/config.c
|
||||
+++ b/libmultipath/config.c
|
||||
@@ -60,6 +60,7 @@ int libmultipath_init(void)
|
||||
static void _libmultipath_exit(void)
|
||||
{
|
||||
libmultipath_exit_called = true;
|
||||
+ libmp_dm_exit();
|
||||
udev_unref(udev);
|
||||
}
|
||||
|
||||
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||
index f478df71..5d460359 100644
|
||||
--- a/libmultipath/config.h
|
||||
+++ b/libmultipath/config.h
|
||||
@@ -271,6 +271,8 @@ int libmultipath_init(void);
|
||||
*
|
||||
* This function un-initializes libmultipath data structures.
|
||||
* It is recommended to call this function at program exit.
|
||||
+ * If the application also calls dm_lib_exit(), it should do so
|
||||
+ * after libmultipath_exit().
|
||||
*
|
||||
* Calls to libmultipath_init() after libmultipath_exit() will fail
|
||||
* (in other words, libmultipath can't be re-initialized).
|
||||
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||
index 4eb6f539..e60ab493 100644
|
||||
--- a/libmultipath/devmapper.c
|
||||
+++ b/libmultipath/devmapper.c
|
||||
@@ -335,6 +335,20 @@ void libmp_udev_set_sync_support(int on)
|
||||
libmp_dm_udev_sync = !!on;
|
||||
}
|
||||
|
||||
+static bool libmp_dm_init_called;
|
||||
+void libmp_dm_exit(void)
|
||||
+{
|
||||
+ if (!libmp_dm_init_called)
|
||||
+ return;
|
||||
+
|
||||
+ /* switch back to default libdm logging */
|
||||
+ dm_log_init(NULL);
|
||||
+#ifdef LIBDM_API_HOLD_CONTROL
|
||||
+ /* make sure control fd is closed in dm_lib_release() */
|
||||
+ dm_hold_control_dev(0);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
static void libmp_dm_init(void)
|
||||
{
|
||||
struct config *conf;
|
||||
@@ -351,6 +365,7 @@ static void libmp_dm_init(void)
|
||||
dm_hold_control_dev(1);
|
||||
#endif
|
||||
dm_udev_set_sync_support(libmp_dm_udev_sync);
|
||||
+ libmp_dm_init_called = true;
|
||||
}
|
||||
|
||||
static void _do_skip_libmp_dm_init(void)
|
||||
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
|
||||
index fa6b3c53..e29b4d41 100644
|
||||
--- a/libmultipath/devmapper.h
|
||||
+++ b/libmultipath/devmapper.h
|
||||
@@ -35,6 +35,7 @@ enum {
|
||||
|
||||
int dm_prereq(unsigned int *v);
|
||||
void skip_libmp_dm_init(void);
|
||||
+void libmp_dm_exit(void);
|
||||
void libmp_udev_set_sync_support(int on);
|
||||
struct dm_task *libmp_dm_task_create(int task);
|
||||
int dm_simplecmd_flush (int, const char *, uint16_t);
|
@ -1,37 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 21:06:13 +0200
|
||||
Subject: [PATCH] multipathd: fixup libdm deinitialization
|
||||
|
||||
With libmp_dm_exit() in place, we can make sure that the
|
||||
calls are made in the right order.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 7ab3eab8..4c4e2eab 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -3220,8 +3220,6 @@ failed:
|
||||
if (poll_dmevents)
|
||||
cleanup_dmevent_waiter();
|
||||
|
||||
- dm_lib_exit();
|
||||
-
|
||||
/* We're done here */
|
||||
cleanup_pidfile();
|
||||
condlog(2, "--------shut down-------");
|
||||
@@ -3318,6 +3316,9 @@ main (int argc, char *argv[])
|
||||
|
||||
pthread_cond_init_mono(&config_cond);
|
||||
|
||||
+ if (atexit(dm_lib_exit))
|
||||
+ condlog(3, "failed to register exit handler for libdm");
|
||||
+
|
||||
libmultipath_init();
|
||||
if (atexit(libmultipath_exit))
|
||||
condlog(3, "failed to register exit handler for libmultipath");
|
@ -1,26 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 21:04:04 +0200
|
||||
Subject: [PATCH] libmultipath: log_thread_stop(): check if logarea is
|
||||
initialized
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/log_pthread.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/libmultipath/log_pthread.c b/libmultipath/log_pthread.c
|
||||
index 15baef88..0c327ffc 100644
|
||||
--- a/libmultipath/log_pthread.c
|
||||
+++ b/libmultipath/log_pthread.c
|
||||
@@ -112,6 +112,9 @@ void log_thread_reset (void)
|
||||
|
||||
void log_thread_stop (void)
|
||||
{
|
||||
+ if (!la)
|
||||
+ return;
|
||||
+
|
||||
logdbg(stderr,"enter log_thread_stop\n");
|
||||
|
||||
pthread_mutex_lock(&logev_lock);
|
@ -1,92 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 21:08:19 +0200
|
||||
Subject: [PATCH] multipathd: add cleanup_child() exit handler
|
||||
|
||||
cleanup_child() calls all cleanups in the right order, in an
|
||||
exit handler.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 45 +++++++++++++++++++++++++--------------------
|
||||
1 file changed, 25 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 4c4e2eab..50cc3356 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -3024,6 +3024,27 @@ static void cleanup_rcu(void)
|
||||
rcu_unregister_thread();
|
||||
}
|
||||
|
||||
+static void cleanup_child(void)
|
||||
+{
|
||||
+ cleanup_threads();
|
||||
+ cleanup_vecs();
|
||||
+ cleanup_foreign();
|
||||
+ cleanup_checkers();
|
||||
+ cleanup_prio();
|
||||
+ if (poll_dmevents)
|
||||
+ cleanup_dmevent_waiter();
|
||||
+
|
||||
+ cleanup_pidfile();
|
||||
+ if (logsink == 1)
|
||||
+ log_thread_stop();
|
||||
+
|
||||
+ cleanup_conf();
|
||||
+
|
||||
+#ifdef _DEBUG_
|
||||
+ dbg_free_final(NULL);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
static int sd_notify_exit(int err)
|
||||
{
|
||||
#ifdef USE_SYSTEMD
|
||||
@@ -3049,7 +3070,9 @@ child (__attribute__((unused)) void *param)
|
||||
mlockall(MCL_CURRENT | MCL_FUTURE);
|
||||
signal_init();
|
||||
mp_rcu_data = setup_rcu();
|
||||
- atexit(cleanup_rcu);
|
||||
+
|
||||
+ if (atexit(cleanup_rcu) || atexit(cleanup_child))
|
||||
+ fprintf(stderr, "failed to register cleanup handlers\n");
|
||||
|
||||
setup_thread_attr(&misc_attr, 64 * 1024, 0);
|
||||
setup_thread_attr(&uevent_attr, DEFAULT_UEVENT_STACKSIZE * 1024, 0);
|
||||
@@ -3063,8 +3086,6 @@ child (__attribute__((unused)) void *param)
|
||||
pid_fd = pidfile_create(DEFAULT_PIDFILE, daemon_pid);
|
||||
if (pid_fd < 0) {
|
||||
condlog(1, "failed to create pidfile");
|
||||
- if (logsink == 1)
|
||||
- log_thread_stop();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -3212,24 +3233,8 @@ child (__attribute__((unused)) void *param)
|
||||
|
||||
exit_code = 0;
|
||||
failed:
|
||||
- cleanup_threads();
|
||||
- cleanup_vecs();
|
||||
- cleanup_foreign();
|
||||
- cleanup_checkers();
|
||||
- cleanup_prio();
|
||||
- if (poll_dmevents)
|
||||
- cleanup_dmevent_waiter();
|
||||
-
|
||||
- /* We're done here */
|
||||
- cleanup_pidfile();
|
||||
condlog(2, "--------shut down-------");
|
||||
-
|
||||
- if (logsink == 1)
|
||||
- log_thread_stop();
|
||||
- cleanup_conf();
|
||||
-#ifdef _DEBUG_
|
||||
- dbg_free_final(NULL);
|
||||
-#endif
|
||||
+ /* All cleanup is done in the cleanup_child() exit handler */
|
||||
return sd_notify_exit(exit_code);
|
||||
}
|
||||
|
@ -1,145 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Mon, 26 Oct 2020 16:44:32 +0100
|
||||
Subject: [PATCH] libmultipath: fix log_thread startup and teardown
|
||||
|
||||
This fixes several issues with the log_thread. First, the running flag
|
||||
logq_running should be set by the thread itself, not by
|
||||
log_thread_start()/_stop(). Second, the thread was both cancelled and
|
||||
terminated via a flag (again, logq_running). It's sufficient to just cancel
|
||||
and join it. Third, the locking wasn't cancel-safe in some places. Forth,
|
||||
log_thread_start() didn't wait for startup properly. Fifth, using (pthread_t)0
|
||||
is wrong (pthread_t is opaque; there's no guarantee that 0 is not a valid
|
||||
pthread_t value). Sixth, pthread_cancel() was called under logq_lock, which
|
||||
doesn't make sense to me.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/log_pthread.c | 62 +++++++++++++++++++++++++++-----------
|
||||
1 file changed, 45 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/log_pthread.c b/libmultipath/log_pthread.c
|
||||
index 0c327ffc..3a2566ae 100644
|
||||
--- a/libmultipath/log_pthread.c
|
||||
+++ b/libmultipath/log_pthread.c
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "log_pthread.h"
|
||||
#include "log.h"
|
||||
#include "lock.h"
|
||||
+#include "util.h"
|
||||
|
||||
static pthread_t log_thr;
|
||||
|
||||
@@ -56,35 +57,52 @@ static void flush_logqueue (void)
|
||||
} while (empty == 0);
|
||||
}
|
||||
|
||||
+static void cleanup_log_thread(__attribute((unused)) void *arg)
|
||||
+{
|
||||
+ logdbg(stderr, "log thread exiting");
|
||||
+ pthread_mutex_lock(&logev_lock);
|
||||
+ logq_running = 0;
|
||||
+ pthread_mutex_unlock(&logev_lock);
|
||||
+}
|
||||
+
|
||||
static void * log_thread (__attribute__((unused)) void * et)
|
||||
{
|
||||
int running;
|
||||
|
||||
pthread_mutex_lock(&logev_lock);
|
||||
- logq_running = 1;
|
||||
+ running = logq_running;
|
||||
+ if (!running)
|
||||
+ logq_running = 1;
|
||||
+ pthread_cond_signal(&logev_cond);
|
||||
pthread_mutex_unlock(&logev_lock);
|
||||
+ if (running)
|
||||
+ /* already started */
|
||||
+ return NULL;
|
||||
+ pthread_cleanup_push(cleanup_log_thread, NULL);
|
||||
|
||||
mlockall(MCL_CURRENT | MCL_FUTURE);
|
||||
logdbg(stderr,"enter log_thread\n");
|
||||
|
||||
while (1) {
|
||||
pthread_mutex_lock(&logev_lock);
|
||||
- if (logq_running && !log_messages_pending)
|
||||
+ pthread_cleanup_push(cleanup_mutex, &logev_lock);
|
||||
+ while (!log_messages_pending)
|
||||
+ /* this is a cancellation point */
|
||||
pthread_cond_wait(&logev_cond, &logev_lock);
|
||||
log_messages_pending = 0;
|
||||
- running = logq_running;
|
||||
- pthread_mutex_unlock(&logev_lock);
|
||||
- if (!running)
|
||||
- break;
|
||||
+ pthread_cleanup_pop(1);
|
||||
+
|
||||
flush_logqueue();
|
||||
}
|
||||
+ pthread_cleanup_pop(1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void log_thread_start (pthread_attr_t *attr)
|
||||
{
|
||||
- logdbg(stderr,"enter log_thread_start\n");
|
||||
+ int running = 0;
|
||||
|
||||
+ logdbg(stderr,"enter log_thread_start\n");
|
||||
pthread_mutex_init(&logq_lock, NULL);
|
||||
pthread_mutex_init(&logev_lock, NULL);
|
||||
pthread_cond_init(&logev_cond, NULL);
|
||||
@@ -93,7 +111,15 @@ void log_thread_start (pthread_attr_t *attr)
|
||||
fprintf(stderr,"can't initialize log buffer\n");
|
||||
exit(1);
|
||||
}
|
||||
- if (pthread_create(&log_thr, attr, log_thread, NULL)) {
|
||||
+
|
||||
+ pthread_mutex_lock(&logev_lock);
|
||||
+ pthread_cleanup_push(cleanup_mutex, &logev_lock);
|
||||
+ if (!pthread_create(&log_thr, attr, log_thread, NULL))
|
||||
+ while (!(running = logq_running))
|
||||
+ pthread_cond_wait(&logev_cond, &logev_lock);
|
||||
+ pthread_cleanup_pop(1);
|
||||
+
|
||||
+ if (!running) {
|
||||
fprintf(stderr,"can't start log thread\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -112,23 +138,25 @@ void log_thread_reset (void)
|
||||
|
||||
void log_thread_stop (void)
|
||||
{
|
||||
+ int running;
|
||||
+
|
||||
if (!la)
|
||||
return;
|
||||
|
||||
logdbg(stderr,"enter log_thread_stop\n");
|
||||
|
||||
pthread_mutex_lock(&logev_lock);
|
||||
- logq_running = 0;
|
||||
- pthread_cond_signal(&logev_cond);
|
||||
- pthread_mutex_unlock(&logev_lock);
|
||||
-
|
||||
- pthread_mutex_lock(&logq_lock);
|
||||
- pthread_cancel(log_thr);
|
||||
- pthread_mutex_unlock(&logq_lock);
|
||||
- pthread_join(log_thr, NULL);
|
||||
- log_thr = (pthread_t)0;
|
||||
+ pthread_cleanup_push(cleanup_mutex, &logev_lock);
|
||||
+ running = logq_running;
|
||||
+ if (running) {
|
||||
+ pthread_cancel(log_thr);
|
||||
+ pthread_cond_signal(&logev_cond);
|
||||
+ }
|
||||
+ pthread_cleanup_pop(1);
|
||||
|
||||
flush_logqueue();
|
||||
+ if (running)
|
||||
+ pthread_join(log_thr, NULL);
|
||||
|
||||
pthread_mutex_destroy(&logq_lock);
|
||||
pthread_mutex_destroy(&logev_lock);
|
@ -1,90 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 21:57:22 +0200
|
||||
Subject: [PATCH] multipathd: move cleanup_{prio,checkers,foreign} to
|
||||
libmultipath_exit
|
||||
|
||||
This requires another major ABI bump.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmpathpersist/mpath_persist.c | 2 --
|
||||
libmultipath/config.c | 4 ++++
|
||||
libmultipath/libmultipath.version | 5 +----
|
||||
multipathd/main.c | 3 ---
|
||||
4 files changed, 5 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||
index e1d1cb76..9ebf91dd 100644
|
||||
--- a/libmpathpersist/mpath_persist.c
|
||||
+++ b/libmpathpersist/mpath_persist.c
|
||||
@@ -78,8 +78,6 @@ mpath_lib_init (void)
|
||||
|
||||
static void libmpathpersist_cleanup(void)
|
||||
{
|
||||
- cleanup_prio();
|
||||
- cleanup_checkers();
|
||||
libmultipath_exit();
|
||||
dm_lib_exit();
|
||||
}
|
||||
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||
index b9cb4131..52b1447b 100644
|
||||
--- a/libmultipath/config.c
|
||||
+++ b/libmultipath/config.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "devmapper.h"
|
||||
#include "mpath_cmd.h"
|
||||
#include "propsel.h"
|
||||
+#include "foreign.h"
|
||||
|
||||
/*
|
||||
* We don't support re-initialization after
|
||||
@@ -60,6 +61,9 @@ int libmultipath_init(void)
|
||||
static void _libmultipath_exit(void)
|
||||
{
|
||||
libmultipath_exit_called = true;
|
||||
+ cleanup_foreign();
|
||||
+ cleanup_checkers();
|
||||
+ cleanup_prio();
|
||||
libmp_dm_exit();
|
||||
udev_unref(udev);
|
||||
}
|
||||
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
|
||||
index 84beb7f0..800cff22 100644
|
||||
--- a/libmultipath/libmultipath.version
|
||||
+++ b/libmultipath/libmultipath.version
|
||||
@@ -31,7 +31,7 @@
|
||||
* The new version inherits the previous ones.
|
||||
*/
|
||||
|
||||
-LIBMULTIPATH_3.0.0 {
|
||||
+LIBMULTIPATH_4.0.0 {
|
||||
global:
|
||||
/* symbols referenced by multipath and multipathd */
|
||||
add_foreign;
|
||||
@@ -51,10 +51,7 @@ global:
|
||||
checker_name;
|
||||
checker_state_name;
|
||||
check_foreign;
|
||||
- cleanup_checkers;
|
||||
- cleanup_foreign;
|
||||
cleanup_lock;
|
||||
- cleanup_prio;
|
||||
close_fd;
|
||||
coalesce_paths;
|
||||
convert_dev;
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 50cc3356..4de0978e 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -3028,9 +3028,6 @@ static void cleanup_child(void)
|
||||
{
|
||||
cleanup_threads();
|
||||
cleanup_vecs();
|
||||
- cleanup_foreign();
|
||||
- cleanup_checkers();
|
||||
- cleanup_prio();
|
||||
if (poll_dmevents)
|
||||
cleanup_dmevent_waiter();
|
||||
|
@ -1,107 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 00:30:02 +0200
|
||||
Subject: [PATCH] multipath: use atexit() for cleanup handlers
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipath/main.c | 37 ++++++++++++++++---------------------
|
||||
1 file changed, 16 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/multipath/main.c b/multipath/main.c
|
||||
index 9ae46ed5..1949a1cd 100644
|
||||
--- a/multipath/main.c
|
||||
+++ b/multipath/main.c
|
||||
@@ -452,13 +452,19 @@ static bool released_to_systemd(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static struct vectors vecs;
|
||||
+static void cleanup_vecs(void)
|
||||
+{
|
||||
+ free_multipathvec(vecs.mpvec, KEEP_PATHS);
|
||||
+ free_pathvec(vecs.pathvec, FREE_PATHS);
|
||||
+}
|
||||
+
|
||||
static int
|
||||
configure (struct config *conf, enum mpath_cmds cmd,
|
||||
enum devtypes dev_type, char *devpath)
|
||||
{
|
||||
vector curmp = NULL;
|
||||
vector pathvec = NULL;
|
||||
- struct vectors vecs;
|
||||
int r = RTVL_FAIL, rc;
|
||||
int di_flag = 0;
|
||||
char * refwwid = NULL;
|
||||
@@ -469,6 +475,7 @@ configure (struct config *conf, enum mpath_cmds cmd,
|
||||
*/
|
||||
curmp = vector_alloc();
|
||||
pathvec = vector_alloc();
|
||||
+ atexit(cleanup_vecs);
|
||||
|
||||
if (!curmp || !pathvec) {
|
||||
condlog(0, "can not allocate memory");
|
||||
@@ -580,9 +587,6 @@ out:
|
||||
if (refwwid)
|
||||
FREE(refwwid);
|
||||
|
||||
- free_multipathvec(curmp, KEEP_PATHS);
|
||||
- free_pathvec(pathvec, FREE_PATHS);
|
||||
-
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -808,9 +812,13 @@ main (int argc, char *argv[])
|
||||
bool enable_foreign = false;
|
||||
|
||||
libmultipath_init();
|
||||
+ if (atexit(dm_lib_exit) || atexit(libmultipath_exit))
|
||||
+ condlog(1, "failed to register cleanup handler for libmultipath: %m");
|
||||
logsink = 0;
|
||||
if (init_config(DEFAULT_CONFIGFILE))
|
||||
exit(RTVL_FAIL);
|
||||
+ if (atexit(uninit_config))
|
||||
+ condlog(1, "failed to register cleanup handler for config: %m");
|
||||
conf = get_multipath_config();
|
||||
conf->retrigger_tries = 0;
|
||||
conf->force_sync = 1;
|
||||
@@ -887,7 +895,7 @@ main (int argc, char *argv[])
|
||||
break;
|
||||
case 't':
|
||||
r = dump_config(conf, NULL, NULL) ? RTVL_FAIL : RTVL_OK;
|
||||
- goto out_free_config;
|
||||
+ goto out;
|
||||
case 'T':
|
||||
cmd = CMD_DUMP_CONFIG;
|
||||
break;
|
||||
@@ -1048,26 +1056,13 @@ main (int argc, char *argv[])
|
||||
condlog(3, "restart multipath configuration process");
|
||||
|
||||
out:
|
||||
- dm_lib_exit();
|
||||
-
|
||||
- cleanup_foreign();
|
||||
- cleanup_prio();
|
||||
- cleanup_checkers();
|
||||
+ put_multipath_config(conf);
|
||||
+ if (dev)
|
||||
+ FREE(dev);
|
||||
|
||||
if (dev_type == DEV_UEVENT)
|
||||
closelog();
|
||||
|
||||
-out_free_config:
|
||||
- /*
|
||||
- * Freeing config must be done after dm_lib_exit(), because
|
||||
- * the logging function (dm_write_log()), which is called there,
|
||||
- * references the config.
|
||||
- */
|
||||
- put_multipath_config(conf);
|
||||
- uninit_config();
|
||||
- libmultipath_exit();
|
||||
- if (dev)
|
||||
- FREE(dev);
|
||||
#ifdef _DEBUG_
|
||||
dbg_free_final(NULL);
|
||||
#endif
|
@ -1,29 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 00:32:48 +0200
|
||||
Subject: [PATCH] mpathpersist: use atexit() for cleanup handlers
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
mpathpersist/main.c | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/mpathpersist/main.c b/mpathpersist/main.c
|
||||
index 3c2e6576..14245cc3 100644
|
||||
--- a/mpathpersist/main.c
|
||||
+++ b/mpathpersist/main.c
|
||||
@@ -641,11 +641,10 @@ int main(int argc, char *argv[])
|
||||
if (libmpathpersist_init()) {
|
||||
exit(1);
|
||||
}
|
||||
+ if (atexit((void(*)(void))libmpathpersist_exit))
|
||||
+ fprintf(stderr, "failed to register cleanup handler for libmpathpersist: %m");
|
||||
|
||||
ret = handle_args(argc, argv, 0);
|
||||
-
|
||||
- libmpathpersist_exit();
|
||||
-
|
||||
return (ret >= 0) ? ret : MPATH_PR_OTHER;
|
||||
}
|
||||
|
@ -1,92 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 23 Sep 2020 23:30:50 +0200
|
||||
Subject: [PATCH] multipath: fix leak in check_path_valid()
|
||||
|
||||
If path status was successfully determined before calling store_pathvec(),
|
||||
free_path() wasn't called.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipath/main.c | 30 ++++++++++++++++++++----------
|
||||
1 file changed, 20 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/multipath/main.c b/multipath/main.c
|
||||
index 1949a1cd..043d8fa7 100644
|
||||
--- a/multipath/main.c
|
||||
+++ b/multipath/main.c
|
||||
@@ -93,7 +93,7 @@ void rcu_register_thread_memb(void) {}
|
||||
void rcu_unregister_thread_memb(void) {}
|
||||
|
||||
static int
|
||||
-filter_pathvec (vector pathvec, char * refwwid)
|
||||
+filter_pathvec (vector pathvec, const char *refwwid)
|
||||
{
|
||||
int i;
|
||||
struct path * pp;
|
||||
@@ -594,8 +594,9 @@ static int
|
||||
check_path_valid(const char *name, struct config *conf, bool is_uevent)
|
||||
{
|
||||
int fd, r = PATH_IS_ERROR;
|
||||
- struct path *pp = NULL;
|
||||
+ struct path *pp;
|
||||
vector pathvec = NULL;
|
||||
+ const char *wwid;
|
||||
|
||||
pp = alloc_path();
|
||||
if (!pp)
|
||||
@@ -664,14 +665,19 @@ check_path_valid(const char *name, struct config *conf, bool is_uevent)
|
||||
|
||||
if (store_path(pathvec, pp) != 0) {
|
||||
free_path(pp);
|
||||
+ pp = NULL;
|
||||
goto fail;
|
||||
+ } else {
|
||||
+ /* make sure path isn't freed twice */
|
||||
+ wwid = pp->wwid;
|
||||
+ pp = NULL;
|
||||
}
|
||||
|
||||
/* For find_multipaths = SMART, if there is more than one path
|
||||
* matching the refwwid, then the path is valid */
|
||||
if (path_discovery(pathvec, DI_SYSFS | DI_WWID) < 0)
|
||||
goto fail;
|
||||
- filter_pathvec(pathvec, pp->wwid);
|
||||
+ filter_pathvec(pathvec, wwid);
|
||||
if (VECTOR_SIZE(pathvec) > 1)
|
||||
r = PATH_IS_VALID;
|
||||
else
|
||||
@@ -679,21 +685,25 @@ check_path_valid(const char *name, struct config *conf, bool is_uevent)
|
||||
|
||||
out:
|
||||
r = print_cmd_valid(r, pathvec, conf);
|
||||
- free_pathvec(pathvec, FREE_PATHS);
|
||||
/*
|
||||
* multipath -u must exit with status 0, otherwise udev won't
|
||||
* import its output.
|
||||
*/
|
||||
if (!is_uevent && r == PATH_IS_NOT_VALID)
|
||||
- return RTVL_FAIL;
|
||||
- return RTVL_OK;
|
||||
+ r = RTVL_FAIL;
|
||||
+ else
|
||||
+ r = RTVL_OK;
|
||||
+ goto cleanup;
|
||||
|
||||
fail:
|
||||
- if (pathvec)
|
||||
- free_pathvec(pathvec, FREE_PATHS);
|
||||
- else
|
||||
+ r = RTVL_FAIL;
|
||||
+
|
||||
+cleanup:
|
||||
+ if (pp != NULL)
|
||||
free_path(pp);
|
||||
- return RTVL_FAIL;
|
||||
+ if (pathvec != NULL)
|
||||
+ free_pathvec(pathvec, FREE_PATHS);
|
||||
+ return r;
|
||||
}
|
||||
|
||||
static int
|
@ -1,59 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Thu, 24 Sep 2020 15:13:06 +0200
|
||||
Subject: [PATCH] multipath-tools: mpath-tools.supp: file with valgrind
|
||||
suppressions
|
||||
|
||||
These leaks are caused by other libraries (libsystemd, glibc,
|
||||
libgcrypt) and should be ignored when debugging with valgrind
|
||||
|
||||
Usage example:
|
||||
|
||||
valgrind --suppressions=mpath-tools.supp \
|
||||
--leak-check=full --show-leak-kinds=all $COMMAND
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
third-party/valgrind/mpath-tools.supp | 32 +++++++++++++++++++++++++++
|
||||
1 file changed, 32 insertions(+)
|
||||
create mode 100644 third-party/valgrind/mpath-tools.supp
|
||||
|
||||
diff --git a/third-party/valgrind/mpath-tools.supp b/third-party/valgrind/mpath-tools.supp
|
||||
new file mode 100644
|
||||
index 00000000..0537fd56
|
||||
--- /dev/null
|
||||
+++ b/third-party/valgrind/mpath-tools.supp
|
||||
@@ -0,0 +1,32 @@
|
||||
+{
|
||||
+ glibc _dlerror_run leak: https://stackoverflow.com/questions/1542457/memory-leak-reported-by-valgrind-in-dlopen
|
||||
+ Memcheck:Leak
|
||||
+ match-leak-kinds: reachable
|
||||
+ fun:calloc
|
||||
+ fun:_dlerror_run
|
||||
+ fun:dlopen*
|
||||
+}
|
||||
+
|
||||
+{
|
||||
+ systemd mempools are never freed: https://bugzilla.redhat.com/show_bug.cgi?id=1215670
|
||||
+ Memcheck:Leak
|
||||
+ match-leak-kinds: reachable
|
||||
+ fun:malloc
|
||||
+ fun:mempool_alloc_tile
|
||||
+ fun:mempool_alloc0_tile
|
||||
+ fun:hashmap_base_new
|
||||
+ fun:hashmap_base_ensure_allocated
|
||||
+}
|
||||
+
|
||||
+{
|
||||
+ libgcrypt library initialization
|
||||
+ Memcheck:Leak
|
||||
+ match-leak-kinds: reachable
|
||||
+ fun:malloc
|
||||
+ ...
|
||||
+ fun:_gcry_xmalloc
|
||||
+ ...
|
||||
+ fun:global_init.*
|
||||
+ ...
|
||||
+ fun:_dl_init
|
||||
+}
|
@ -1,438 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Sat, 26 Sep 2020 00:04:53 +0200
|
||||
Subject: [PATCH] libmultipath: use libmp_verbosity to track verbosity
|
||||
|
||||
Introduce a new global variable to set the verbosity of libmultipath.
|
||||
This avoids accessing the configuration in every dlog() call.
|
||||
When libmultipath reads its configuration in init_config() or
|
||||
load_config(), it will use the current value of libmp_verbosity
|
||||
for logging. Immediately before returning, libmp_verbosity will be
|
||||
overwritten with the verbosity value from the configuration file,
|
||||
if it was set there. An application is free to set libmp_verbosity
|
||||
back to the previous value or not after that, depending on whether
|
||||
command line options or configuration file settings should take
|
||||
precedence.
|
||||
|
||||
Replace internal access to conf->verbosity with the new variable.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmpathpersist/mpath_persist.c | 5 +---
|
||||
libmultipath/config.c | 9 +++++--
|
||||
libmultipath/configure.c | 16 +++----------
|
||||
libmultipath/debug.c | 10 ++------
|
||||
libmultipath/debug.h | 1 +
|
||||
libmultipath/devmapper.c | 7 +-----
|
||||
libmultipath/libmultipath.version | 5 ++++
|
||||
multipath/main.c | 21 ++++++----------
|
||||
multipathd/main.c | 40 ++++++++++++++++++-------------
|
||||
tests/alias.c | 1 +
|
||||
tests/blacklist.c | 2 ++
|
||||
11 files changed, 53 insertions(+), 64 deletions(-)
|
||||
|
||||
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||
index 9ebf91dd..79322e86 100644
|
||||
--- a/libmpathpersist/mpath_persist.c
|
||||
+++ b/libmpathpersist/mpath_persist.c
|
||||
@@ -170,10 +170,7 @@ void mpath_persistent_reserve_free_vecs(void)
|
||||
|
||||
int mpath_persistent_reserve_init_vecs(int verbose)
|
||||
{
|
||||
- struct config *conf = get_multipath_config();
|
||||
-
|
||||
- conf->verbosity = verbose;
|
||||
- put_multipath_config(conf);
|
||||
+ libmp_verbosity = verbose;
|
||||
|
||||
if (curmp)
|
||||
return MPATH_PR_SUCCESS;
|
||||
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||
index 52b1447b..49e7fb81 100644
|
||||
--- a/libmultipath/config.c
|
||||
+++ b/libmultipath/config.c
|
||||
@@ -828,10 +828,14 @@ int _init_config (const char *file, struct config *conf)
|
||||
conf = &__internal_config;
|
||||
|
||||
/*
|
||||
- * internal defaults
|
||||
+ * Processing the config file will overwrite conf->verbosity if set
|
||||
+ * When we return, we'll copy the config value back
|
||||
*/
|
||||
- conf->verbosity = DEFAULT_VERBOSITY;
|
||||
+ conf->verbosity = libmp_verbosity;
|
||||
|
||||
+ /*
|
||||
+ * internal defaults
|
||||
+ */
|
||||
get_sys_max_fds(&conf->max_fds);
|
||||
conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
|
||||
conf->wwids_file = set_default(DEFAULT_WWIDS_FILE);
|
||||
@@ -997,6 +1001,7 @@ int _init_config (const char *file, struct config *conf)
|
||||
!conf->wwids_file || !conf->prkeys_file)
|
||||
goto out;
|
||||
|
||||
+ libmp_verbosity = conf->verbosity;
|
||||
return 0;
|
||||
out:
|
||||
_uninit_config(conf);
|
||||
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
||||
index d36f0d0d..20536e60 100644
|
||||
--- a/libmultipath/configure.c
|
||||
+++ b/libmultipath/configure.c
|
||||
@@ -934,16 +934,12 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
|
||||
{
|
||||
int r = DOMAP_FAIL;
|
||||
struct config *conf;
|
||||
- int verbosity;
|
||||
|
||||
/*
|
||||
* last chance to quit before touching the devmaps
|
||||
*/
|
||||
if (mpp->action == ACT_DRY_RUN) {
|
||||
- conf = get_multipath_config();
|
||||
- verbosity = conf->verbosity;
|
||||
- put_multipath_config(conf);
|
||||
- print_multipath_topology(mpp, verbosity);
|
||||
+ print_multipath_topology(mpp, libmp_verbosity);
|
||||
return DOMAP_DRY;
|
||||
}
|
||||
|
||||
@@ -1327,14 +1323,8 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,
|
||||
"queue_if_no_path");
|
||||
}
|
||||
|
||||
- if (!is_daemon && mpp->action != ACT_NOTHING) {
|
||||
- int verbosity;
|
||||
-
|
||||
- conf = get_multipath_config();
|
||||
- verbosity = conf->verbosity;
|
||||
- put_multipath_config(conf);
|
||||
- print_multipath_topology(mpp, verbosity);
|
||||
- }
|
||||
+ if (!is_daemon && mpp->action != ACT_NOTHING)
|
||||
+ print_multipath_topology(mpp, libmp_verbosity);
|
||||
|
||||
if (mpp->action != ACT_REJECT) {
|
||||
if (!vector_alloc_slot(newmp)) {
|
||||
diff --git a/libmultipath/debug.c b/libmultipath/debug.c
|
||||
index b3a1de9e..a1713b95 100644
|
||||
--- a/libmultipath/debug.c
|
||||
+++ b/libmultipath/debug.c
|
||||
@@ -16,21 +16,15 @@
|
||||
#include "debug.h"
|
||||
|
||||
int logsink;
|
||||
+int libmp_verbosity = DEFAULT_VERBOSITY;
|
||||
|
||||
void dlog (int sink, int prio, const char * fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
- int thres;
|
||||
- struct config *conf;
|
||||
|
||||
va_start(ap, fmt);
|
||||
- conf = get_multipath_config();
|
||||
- ANNOTATE_IGNORE_READS_BEGIN();
|
||||
- thres = (conf) ? conf->verbosity : DEFAULT_VERBOSITY;
|
||||
- ANNOTATE_IGNORE_READS_END();
|
||||
- put_multipath_config(conf);
|
||||
|
||||
- if (prio <= thres) {
|
||||
+ if (prio <= libmp_verbosity) {
|
||||
if (sink < 1) {
|
||||
if (sink == 0) {
|
||||
time_t t = time(NULL);
|
||||
diff --git a/libmultipath/debug.h b/libmultipath/debug.h
|
||||
index c6120c1d..1f3bc8be 100644
|
||||
--- a/libmultipath/debug.h
|
||||
+++ b/libmultipath/debug.h
|
||||
@@ -8,6 +8,7 @@ void dlog (int sink, int prio, const char * fmt, ...)
|
||||
#include "log_pthread.h"
|
||||
|
||||
extern int logsink;
|
||||
+extern int libmp_verbosity;
|
||||
|
||||
#define condlog(prio, fmt, args...) \
|
||||
dlog(logsink, prio, fmt "\n", ##args)
|
||||
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||
index e60ab493..dfe95d2f 100644
|
||||
--- a/libmultipath/devmapper.c
|
||||
+++ b/libmultipath/devmapper.c
|
||||
@@ -351,16 +351,11 @@ void libmp_dm_exit(void)
|
||||
|
||||
static void libmp_dm_init(void)
|
||||
{
|
||||
- struct config *conf;
|
||||
- int verbosity;
|
||||
unsigned int version[3];
|
||||
|
||||
if (dm_prereq(version))
|
||||
exit(1);
|
||||
- conf = get_multipath_config();
|
||||
- verbosity = conf->verbosity;
|
||||
- put_multipath_config(conf);
|
||||
- dm_init(verbosity);
|
||||
+ dm_init(libmp_verbosity);
|
||||
#ifdef LIBDM_API_HOLD_CONTROL
|
||||
dm_hold_control_dev(1);
|
||||
#endif
|
||||
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
|
||||
index 800cff22..67a7379f 100644
|
||||
--- a/libmultipath/libmultipath.version
|
||||
+++ b/libmultipath/libmultipath.version
|
||||
@@ -259,3 +259,8 @@ global:
|
||||
local:
|
||||
*;
|
||||
};
|
||||
+
|
||||
+LIBMULTIPATH_4.1.0 {
|
||||
+global:
|
||||
+ libmp_verbosity;
|
||||
+} LIBMULTIPATH_4.0.0;
|
||||
diff --git a/multipath/main.c b/multipath/main.c
|
||||
index 043d8fa7..98d93c58 100644
|
||||
--- a/multipath/main.c
|
||||
+++ b/multipath/main.c
|
||||
@@ -208,22 +208,15 @@ get_dm_mpvec (enum mpath_cmds cmd, vector curmp, vector pathvec, char * refwwid)
|
||||
mpp->bestpg = select_path_group(mpp);
|
||||
|
||||
if (cmd == CMD_LIST_SHORT ||
|
||||
- cmd == CMD_LIST_LONG) {
|
||||
- struct config *conf = get_multipath_config();
|
||||
- print_multipath_topology(mpp, conf->verbosity);
|
||||
- put_multipath_config(conf);
|
||||
- }
|
||||
+ cmd == CMD_LIST_LONG)
|
||||
+ print_multipath_topology(mpp, libmp_verbosity);
|
||||
|
||||
if (cmd == CMD_CREATE)
|
||||
reinstate_paths(mpp);
|
||||
}
|
||||
|
||||
- if (cmd == CMD_LIST_SHORT || cmd == CMD_LIST_LONG) {
|
||||
- struct config *conf = get_multipath_config();
|
||||
-
|
||||
- print_foreign_topology(conf->verbosity);
|
||||
- put_multipath_config(conf);
|
||||
- }
|
||||
+ if (cmd == CMD_LIST_SHORT || cmd == CMD_LIST_LONG)
|
||||
+ print_foreign_topology(libmp_verbosity);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -552,7 +545,7 @@ configure (struct config *conf, enum mpath_cmds cmd,
|
||||
if (path_discovery(pathvec, di_flag) < 0)
|
||||
goto out;
|
||||
|
||||
- if (conf->verbosity > 2)
|
||||
+ if (libmp_verbosity > 2)
|
||||
print_all_paths(pathvec, 1);
|
||||
|
||||
get_path_layout(pathvec, 0);
|
||||
@@ -843,7 +836,7 @@ main (int argc, char *argv[])
|
||||
exit(RTVL_FAIL);
|
||||
}
|
||||
|
||||
- conf->verbosity = atoi(optarg);
|
||||
+ libmp_verbosity = atoi(optarg);
|
||||
break;
|
||||
case 'b':
|
||||
conf->bindings_file = strdup(optarg);
|
||||
@@ -974,7 +967,7 @@ main (int argc, char *argv[])
|
||||
}
|
||||
if (dev_type == DEV_UEVENT) {
|
||||
openlog("multipath", 0, LOG_DAEMON);
|
||||
- setlogmask(LOG_UPTO(conf->verbosity + 3));
|
||||
+ setlogmask(LOG_UPTO(libmp_verbosity + 3));
|
||||
logsink = 1;
|
||||
}
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 4de0978e..ba257515 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -88,10 +88,10 @@
|
||||
#define CMDSIZE 160
|
||||
#define MSG_SIZE 32
|
||||
|
||||
-#define LOG_MSG(lvl, verb, pp) \
|
||||
+#define LOG_MSG(lvl, pp) \
|
||||
do { \
|
||||
if (pp->mpp && checker_selected(&pp->checker) && \
|
||||
- lvl <= verb) { \
|
||||
+ lvl <= libmp_verbosity) { \
|
||||
if (pp->offline) \
|
||||
condlog(lvl, "%s: %s - path offline", \
|
||||
pp->mpp->alias, pp->dev); \
|
||||
@@ -2070,7 +2070,7 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||
int chkr_new_path_up = 0;
|
||||
int disable_reinstate = 0;
|
||||
int oldchkrstate = pp->chkrstate;
|
||||
- int retrigger_tries, verbosity;
|
||||
+ int retrigger_tries;
|
||||
unsigned int checkint, max_checkint;
|
||||
struct config *conf;
|
||||
int marginal_pathgroups, marginal_changed = 0;
|
||||
@@ -2090,7 +2090,6 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||
retrigger_tries = conf->retrigger_tries;
|
||||
checkint = conf->checkint;
|
||||
max_checkint = conf->max_checkint;
|
||||
- verbosity = conf->verbosity;
|
||||
marginal_pathgroups = conf->marginal_pathgroups;
|
||||
put_multipath_config(conf);
|
||||
|
||||
@@ -2152,7 +2151,7 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||
if (newstate == PATH_WILD || newstate == PATH_UNCHECKED) {
|
||||
condlog(2, "%s: unusable path (%s) - checker failed",
|
||||
pp->dev, checker_state_name(newstate));
|
||||
- LOG_MSG(2, verbosity, pp);
|
||||
+ LOG_MSG(2, pp);
|
||||
conf = get_multipath_config();
|
||||
pthread_cleanup_push(put_multipath_config, conf);
|
||||
pathinfo(pp, conf, 0);
|
||||
@@ -2257,7 +2256,7 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||
int oldstate = pp->state;
|
||||
pp->state = newstate;
|
||||
|
||||
- LOG_MSG(1, verbosity, pp);
|
||||
+ LOG_MSG(1, pp);
|
||||
|
||||
/*
|
||||
* upon state change, reset the checkint
|
||||
@@ -2321,7 +2320,7 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||
/* Clear IO errors */
|
||||
reinstate_path(pp);
|
||||
else {
|
||||
- LOG_MSG(4, verbosity, pp);
|
||||
+ LOG_MSG(4, pp);
|
||||
if (pp->checkint != max_checkint) {
|
||||
/*
|
||||
* double the next check delay.
|
||||
@@ -2349,9 +2348,9 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||
log_checker_err = conf->log_checker_err;
|
||||
put_multipath_config(conf);
|
||||
if (log_checker_err == LOG_CHKR_ERR_ONCE)
|
||||
- LOG_MSG(3, verbosity, pp);
|
||||
+ LOG_MSG(3, pp);
|
||||
else
|
||||
- LOG_MSG(2, verbosity, pp);
|
||||
+ LOG_MSG(2, pp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2696,6 +2695,10 @@ reconfigure (struct vectors * vecs)
|
||||
if (!conf)
|
||||
return 1;
|
||||
|
||||
+ if (verbosity)
|
||||
+ libmp_verbosity = verbosity;
|
||||
+ setlogmask(LOG_UPTO(libmp_verbosity + 3));
|
||||
+
|
||||
/*
|
||||
* free old map and path vectors ... they use old conf state
|
||||
*/
|
||||
@@ -2710,8 +2713,6 @@ reconfigure (struct vectors * vecs)
|
||||
/* Re-read any timezone changes */
|
||||
tzset();
|
||||
|
||||
- if (verbosity)
|
||||
- conf->verbosity = verbosity;
|
||||
if (bindings_read_only)
|
||||
conf->bindings_read_only = bindings_read_only;
|
||||
check_alias_settings(conf);
|
||||
@@ -3091,14 +3092,18 @@ child (__attribute__((unused)) void *param)
|
||||
condlog(2, "--------start up--------");
|
||||
condlog(2, "read " DEFAULT_CONFIGFILE);
|
||||
|
||||
+ if (verbosity)
|
||||
+ libmp_verbosity = verbosity;
|
||||
conf = load_config(DEFAULT_CONFIGFILE);
|
||||
+ if (verbosity)
|
||||
+ libmp_verbosity = verbosity;
|
||||
+ setlogmask(LOG_UPTO(libmp_verbosity + 3));
|
||||
+
|
||||
if (!conf) {
|
||||
condlog(0, "failed to load configuration");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
- if (verbosity)
|
||||
- conf->verbosity = verbosity;
|
||||
if (bindings_read_only)
|
||||
conf->bindings_read_only = bindings_read_only;
|
||||
uxsock_timeout = conf->uxsock_timeout;
|
||||
@@ -3117,7 +3122,6 @@ child (__attribute__((unused)) void *param)
|
||||
|
||||
if (poll_dmevents)
|
||||
poll_dmevents = dmevent_poll_supported();
|
||||
- setlogmask(LOG_UPTO(conf->verbosity + 3));
|
||||
|
||||
envp = getenv("LimitNOFILE");
|
||||
|
||||
@@ -3339,7 +3343,7 @@ main (int argc, char *argv[])
|
||||
!isdigit(optarg[0]))
|
||||
exit(1);
|
||||
|
||||
- verbosity = atoi(optarg);
|
||||
+ libmp_verbosity = verbosity = atoi(optarg);
|
||||
break;
|
||||
case 's':
|
||||
logsink = -1;
|
||||
@@ -3350,7 +3354,7 @@ main (int argc, char *argv[])
|
||||
if (!conf)
|
||||
exit(1);
|
||||
if (verbosity)
|
||||
- conf->verbosity = verbosity;
|
||||
+ libmp_verbosity = verbosity;
|
||||
uxsock_timeout = conf->uxsock_timeout;
|
||||
err = uxclnt(optarg, uxsock_timeout + 100);
|
||||
free_config(conf);
|
||||
@@ -3376,11 +3380,13 @@ main (int argc, char *argv[])
|
||||
char * c = s;
|
||||
|
||||
logsink = 0;
|
||||
+ if (verbosity)
|
||||
+ libmp_verbosity = verbosity;
|
||||
conf = load_config(DEFAULT_CONFIGFILE);
|
||||
if (!conf)
|
||||
exit(1);
|
||||
if (verbosity)
|
||||
- conf->verbosity = verbosity;
|
||||
+ libmp_verbosity = verbosity;
|
||||
uxsock_timeout = conf->uxsock_timeout;
|
||||
memset(cmd, 0x0, CMDSIZE);
|
||||
while (optind < argc) {
|
||||
diff --git a/tests/alias.c b/tests/alias.c
|
||||
index 7fda679d..0311faa6 100644
|
||||
--- a/tests/alias.c
|
||||
+++ b/tests/alias.c
|
||||
@@ -735,6 +735,7 @@ static int test_allocate_binding(void)
|
||||
int main(void)
|
||||
{
|
||||
int ret = 0;
|
||||
+ libmp_verbosity = conf.verbosity;
|
||||
|
||||
ret += test_format_devname();
|
||||
ret += test_scan_devname();
|
||||
diff --git a/tests/blacklist.c b/tests/blacklist.c
|
||||
index 84a3ba2f..0b42e255 100644
|
||||
--- a/tests/blacklist.c
|
||||
+++ b/tests/blacklist.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "globals.c"
|
||||
#include "blacklist.h"
|
||||
#include "test-log.h"
|
||||
+#include "debug.h"
|
||||
|
||||
struct udev_device {
|
||||
const char *sysname;
|
||||
@@ -152,6 +153,7 @@ static int setup(void **state)
|
||||
store_ble(blist_property_wwn_inv, "!ID_WWN", ORIGIN_CONFIG))
|
||||
return -1;
|
||||
|
||||
+ libmp_verbosity = conf.verbosity = 4;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,182 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Sat, 26 Sep 2020 00:32:05 +0200
|
||||
Subject: [PATCH] libmultipath: introduce symbolic values for logsink
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/debug.c | 4 ++--
|
||||
libmultipath/debug.h | 6 ++++++
|
||||
libmultipath/devmapper.c | 4 ++--
|
||||
multipath/main.c | 4 ++--
|
||||
multipathd/main.c | 17 ++++++++---------
|
||||
tests/globals.c | 3 ++-
|
||||
tests/hwtable.c | 2 +-
|
||||
7 files changed, 23 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/debug.c b/libmultipath/debug.c
|
||||
index a1713b95..f9b77552 100644
|
||||
--- a/libmultipath/debug.c
|
||||
+++ b/libmultipath/debug.c
|
||||
@@ -25,8 +25,8 @@ void dlog (int sink, int prio, const char * fmt, ...)
|
||||
va_start(ap, fmt);
|
||||
|
||||
if (prio <= libmp_verbosity) {
|
||||
- if (sink < 1) {
|
||||
- if (sink == 0) {
|
||||
+ if (sink != LOGSINK_SYSLOG) {
|
||||
+ if (sink == LOGSINK_STDERR_WITH_TIME) {
|
||||
time_t t = time(NULL);
|
||||
struct tm *tb = localtime(&t);
|
||||
char buff[16];
|
||||
diff --git a/libmultipath/debug.h b/libmultipath/debug.h
|
||||
index 1f3bc8be..b6ce70a7 100644
|
||||
--- a/libmultipath/debug.h
|
||||
+++ b/libmultipath/debug.h
|
||||
@@ -12,3 +12,9 @@ extern int libmp_verbosity;
|
||||
|
||||
#define condlog(prio, fmt, args...) \
|
||||
dlog(logsink, prio, fmt "\n", ##args)
|
||||
+
|
||||
+enum {
|
||||
+ LOGSINK_STDERR_WITH_TIME = 0,
|
||||
+ LOGSINK_STDERR_WITHOUT_TIME = -1,
|
||||
+ LOGSINK_SYSLOG = 1,
|
||||
+};
|
||||
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||
index dfe95d2f..f8b180e1 100644
|
||||
--- a/libmultipath/devmapper.c
|
||||
+++ b/libmultipath/devmapper.c
|
||||
@@ -104,8 +104,8 @@ dm_write_log (int level, const char *file, int line, const char *f, ...)
|
||||
return;
|
||||
|
||||
va_start(ap, f);
|
||||
- if (logsink < 1) {
|
||||
- if (logsink == 0) {
|
||||
+ if (logsink != LOGSINK_SYSLOG) {
|
||||
+ if (logsink == LOGSINK_STDERR_WITH_TIME) {
|
||||
time_t t = time(NULL);
|
||||
struct tm *tb = localtime(&t);
|
||||
char buff[16];
|
||||
diff --git a/multipath/main.c b/multipath/main.c
|
||||
index 98d93c58..9ac42869 100644
|
||||
--- a/multipath/main.c
|
||||
+++ b/multipath/main.c
|
||||
@@ -817,7 +817,7 @@ main (int argc, char *argv[])
|
||||
libmultipath_init();
|
||||
if (atexit(dm_lib_exit) || atexit(libmultipath_exit))
|
||||
condlog(1, "failed to register cleanup handler for libmultipath: %m");
|
||||
- logsink = 0;
|
||||
+ logsink = LOGSINK_STDERR_WITH_TIME;
|
||||
if (init_config(DEFAULT_CONFIGFILE))
|
||||
exit(RTVL_FAIL);
|
||||
if (atexit(uninit_config))
|
||||
@@ -968,7 +968,7 @@ main (int argc, char *argv[])
|
||||
if (dev_type == DEV_UEVENT) {
|
||||
openlog("multipath", 0, LOG_DAEMON);
|
||||
setlogmask(LOG_UPTO(libmp_verbosity + 3));
|
||||
- logsink = 1;
|
||||
+ logsink = LOGSINK_SYSLOG;
|
||||
}
|
||||
|
||||
set_max_fds(conf->max_fds);
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index ba257515..867f0f84 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -2780,7 +2780,7 @@ handle_signals(bool nonfatal)
|
||||
}
|
||||
if (log_reset_sig) {
|
||||
condlog(2, "reset log (signal)");
|
||||
- if (logsink == 1)
|
||||
+ if (logsink == LOGSINK_SYSLOG)
|
||||
log_thread_reset();
|
||||
}
|
||||
reconfig_sig = 0;
|
||||
@@ -3033,7 +3033,7 @@ static void cleanup_child(void)
|
||||
cleanup_dmevent_waiter();
|
||||
|
||||
cleanup_pidfile();
|
||||
- if (logsink == 1)
|
||||
+ if (logsink == LOGSINK_SYSLOG)
|
||||
log_thread_stop();
|
||||
|
||||
cleanup_conf();
|
||||
@@ -3076,7 +3076,7 @@ child (__attribute__((unused)) void *param)
|
||||
setup_thread_attr(&uevent_attr, DEFAULT_UEVENT_STACKSIZE * 1024, 0);
|
||||
setup_thread_attr(&waiter_attr, 32 * 1024, 1);
|
||||
|
||||
- if (logsink == 1) {
|
||||
+ if (logsink == LOGSINK_SYSLOG) {
|
||||
setup_thread_attr(&log_attr, 64 * 1024, 0);
|
||||
log_thread_start(&log_attr);
|
||||
pthread_attr_destroy(&log_attr);
|
||||
@@ -3307,7 +3307,7 @@ main (int argc, char *argv[])
|
||||
ANNOTATE_BENIGN_RACE_SIZED(&uxsock_timeout, sizeof(uxsock_timeout),
|
||||
"Suppress complaints about this scalar variable");
|
||||
|
||||
- logsink = 1;
|
||||
+ logsink = LOGSINK_SYSLOG;
|
||||
|
||||
if (getuid() != 0) {
|
||||
fprintf(stderr, "need to be root\n");
|
||||
@@ -3334,9 +3334,8 @@ main (int argc, char *argv[])
|
||||
switch(arg) {
|
||||
case 'd':
|
||||
foreground = 1;
|
||||
- if (logsink > 0)
|
||||
- logsink = 0;
|
||||
- //debug=1; /* ### comment me out ### */
|
||||
+ if (logsink == LOGSINK_SYSLOG)
|
||||
+ logsink = LOGSINK_STDERR_WITH_TIME;
|
||||
break;
|
||||
case 'v':
|
||||
if (sizeof(optarg) > sizeof(char *) ||
|
||||
@@ -3346,7 +3345,7 @@ main (int argc, char *argv[])
|
||||
libmp_verbosity = verbosity = atoi(optarg);
|
||||
break;
|
||||
case 's':
|
||||
- logsink = -1;
|
||||
+ logsink = LOGSINK_STDERR_WITHOUT_TIME;
|
||||
break;
|
||||
case 'k':
|
||||
logsink = 0;
|
||||
@@ -3379,7 +3378,7 @@ main (int argc, char *argv[])
|
||||
char * s = cmd;
|
||||
char * c = s;
|
||||
|
||||
- logsink = 0;
|
||||
+ logsink = LOGSINK_STDERR_WITH_TIME;
|
||||
if (verbosity)
|
||||
libmp_verbosity = verbosity;
|
||||
conf = load_config(DEFAULT_CONFIGFILE);
|
||||
diff --git a/tests/globals.c b/tests/globals.c
|
||||
index 8add5eb7..fc0c07ad 100644
|
||||
--- a/tests/globals.c
|
||||
+++ b/tests/globals.c
|
||||
@@ -1,9 +1,10 @@
|
||||
#include "structs.h"
|
||||
#include "config.h"
|
||||
+#include "debug.h"
|
||||
|
||||
/* Required globals */
|
||||
struct udev *udev;
|
||||
-int logsink = -1;
|
||||
+int logsink = LOGSINK_STDERR_WITHOUT_TIME;
|
||||
struct config conf = {
|
||||
.verbosity = 4,
|
||||
};
|
||||
diff --git a/tests/hwtable.c b/tests/hwtable.c
|
||||
index 57f832b7..4dd0873b 100644
|
||||
--- a/tests/hwtable.c
|
||||
+++ b/tests/hwtable.c
|
||||
@@ -53,7 +53,7 @@ struct hwt_state {
|
||||
|
||||
static struct config *_conf;
|
||||
struct udev *udev;
|
||||
-int logsink = -1;
|
||||
+int logsink = LOGSINK_STDERR_WITHOUT_TIME;
|
||||
|
||||
struct config *get_multipath_config(void)
|
||||
{
|
@ -1,149 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Sat, 26 Sep 2020 00:39:22 +0200
|
||||
Subject: [PATCH] libmultipath: simplify dlog()
|
||||
|
||||
By checking the log level in condlog() directly, we can simplify
|
||||
dlog(). Also, it's now possible to limit the log level at compile
|
||||
time by setting MAX_VERBOSITY, enabling the compiler to optimize
|
||||
away log messages with higher loglevel.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/debug.c | 30 +++++++++++++-----------------
|
||||
libmultipath/debug.h | 20 ++++++++++++++++----
|
||||
libmultipath/devmapper.c | 4 +++-
|
||||
tests/test-log.c | 4 ++--
|
||||
tests/test-log.h | 3 ++-
|
||||
5 files changed, 36 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/debug.c b/libmultipath/debug.c
|
||||
index f9b77552..429f2699 100644
|
||||
--- a/libmultipath/debug.c
|
||||
+++ b/libmultipath/debug.c
|
||||
@@ -18,29 +18,25 @@
|
||||
int logsink;
|
||||
int libmp_verbosity = DEFAULT_VERBOSITY;
|
||||
|
||||
-void dlog (int sink, int prio, const char * fmt, ...)
|
||||
+void dlog(int prio, const char * fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
+ if (logsink != LOGSINK_SYSLOG) {
|
||||
+ if (logsink == LOGSINK_STDERR_WITH_TIME) {
|
||||
+ time_t t = time(NULL);
|
||||
+ struct tm *tb = localtime(&t);
|
||||
+ char buff[16];
|
||||
|
||||
- if (prio <= libmp_verbosity) {
|
||||
- if (sink != LOGSINK_SYSLOG) {
|
||||
- if (sink == LOGSINK_STDERR_WITH_TIME) {
|
||||
- time_t t = time(NULL);
|
||||
- struct tm *tb = localtime(&t);
|
||||
- char buff[16];
|
||||
-
|
||||
- strftime(buff, sizeof(buff),
|
||||
- "%b %d %H:%M:%S", tb);
|
||||
- buff[sizeof(buff)-1] = '\0';
|
||||
-
|
||||
- fprintf(stderr, "%s | ", buff);
|
||||
- }
|
||||
- vfprintf(stderr, fmt, ap);
|
||||
+ strftime(buff, sizeof(buff),
|
||||
+ "%b %d %H:%M:%S", tb);
|
||||
+ buff[sizeof(buff)-1] = '\0';
|
||||
+ fprintf(stderr, "%s | ", buff);
|
||||
}
|
||||
- else
|
||||
- log_safe(prio + 3, fmt, ap);
|
||||
+ vfprintf(stderr, fmt, ap);
|
||||
}
|
||||
+ else
|
||||
+ log_safe(prio + 3, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
diff --git a/libmultipath/debug.h b/libmultipath/debug.h
|
||||
index b6ce70a7..705a5d73 100644
|
||||
--- a/libmultipath/debug.h
|
||||
+++ b/libmultipath/debug.h
|
||||
@@ -1,5 +1,7 @@
|
||||
-void dlog (int sink, int prio, const char * fmt, ...)
|
||||
- __attribute__((format(printf, 3, 4)));
|
||||
+#ifndef _DEBUG_H
|
||||
+#define _DEBUG_H
|
||||
+void dlog (int prio, const char *fmt, ...)
|
||||
+ __attribute__((format(printf, 2, 3)));
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
@@ -10,11 +12,21 @@ void dlog (int sink, int prio, const char * fmt, ...)
|
||||
extern int logsink;
|
||||
extern int libmp_verbosity;
|
||||
|
||||
-#define condlog(prio, fmt, args...) \
|
||||
- dlog(logsink, prio, fmt "\n", ##args)
|
||||
+#ifndef MAX_VERBOSITY
|
||||
+#define MAX_VERBOSITY 4
|
||||
+#endif
|
||||
|
||||
enum {
|
||||
LOGSINK_STDERR_WITH_TIME = 0,
|
||||
LOGSINK_STDERR_WITHOUT_TIME = -1,
|
||||
LOGSINK_SYSLOG = 1,
|
||||
};
|
||||
+
|
||||
+#define condlog(prio, fmt, args...) \
|
||||
+ do { \
|
||||
+ int __p = (prio); \
|
||||
+ \
|
||||
+ if (__p <= MAX_VERBOSITY && __p <= libmp_verbosity) \
|
||||
+ dlog(__p, fmt "\n", ##args); \
|
||||
+ } while (0)
|
||||
+#endif /* _DEBUG_H */
|
||||
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||
index f8b180e1..4977b311 100644
|
||||
--- a/libmultipath/devmapper.c
|
||||
+++ b/libmultipath/devmapper.c
|
||||
@@ -276,7 +276,9 @@ static int dm_tgt_prereq (unsigned int *ver)
|
||||
|
||||
static void _init_versions(void)
|
||||
{
|
||||
- dlog(logsink, 3, VERSION_STRING);
|
||||
+ /* Can't use condlog here because of how VERSION_STRING is defined */
|
||||
+ if (3 <= libmp_verbosity)
|
||||
+ dlog(3, VERSION_STRING);
|
||||
init_dm_library_version();
|
||||
init_dm_drv_version();
|
||||
init_dm_mpath_version();
|
||||
diff --git a/tests/test-log.c b/tests/test-log.c
|
||||
index 1c901cba..14f25b9b 100644
|
||||
--- a/tests/test-log.c
|
||||
+++ b/tests/test-log.c
|
||||
@@ -7,8 +7,8 @@
|
||||
#include "log.h"
|
||||
#include "test-log.h"
|
||||
|
||||
-__attribute__((format(printf, 3, 0)))
|
||||
-void __wrap_dlog (int sink, int prio, const char * fmt, ...)
|
||||
+__attribute__((format(printf, 2, 0)))
|
||||
+void __wrap_dlog (int prio, const char * fmt, ...)
|
||||
{
|
||||
char buff[MAX_MSG_SIZE];
|
||||
va_list ap;
|
||||
diff --git a/tests/test-log.h b/tests/test-log.h
|
||||
index 2c878c63..6d22cd23 100644
|
||||
--- a/tests/test-log.h
|
||||
+++ b/tests/test-log.h
|
||||
@@ -1,7 +1,8 @@
|
||||
#ifndef _TEST_LOG_H
|
||||
#define _TEST_LOG_H
|
||||
|
||||
-void __wrap_dlog (int sink, int prio, const char * fmt, ...);
|
||||
+__attribute__((format(printf, 2, 0)))
|
||||
+void __wrap_dlog (int prio, const char * fmt, ...);
|
||||
void expect_condlog(int prio, char *string);
|
||||
|
||||
#endif
|
@ -1,84 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Sat, 26 Sep 2020 00:43:12 +0200
|
||||
Subject: [PATCH] multipathd: common code for "-k" and command args
|
||||
|
||||
'multipathd -k"cmd"' and 'multipath cmd' are the same thing.
|
||||
Treat it with common code.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 37 +++++++++++++++++++------------------
|
||||
1 file changed, 19 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 867f0f84..b6a5f5b7 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -3301,6 +3301,8 @@ main (int argc, char *argv[])
|
||||
int err;
|
||||
int foreground = 0;
|
||||
struct config *conf;
|
||||
+ char *opt_k_arg = NULL;
|
||||
+ bool opt_k = false;
|
||||
|
||||
ANNOTATE_BENIGN_RACE_SIZED(&multipath_conf, sizeof(multipath_conf),
|
||||
"Manipulated through RCU");
|
||||
@@ -3348,16 +3350,9 @@ main (int argc, char *argv[])
|
||||
logsink = LOGSINK_STDERR_WITHOUT_TIME;
|
||||
break;
|
||||
case 'k':
|
||||
- logsink = 0;
|
||||
- conf = load_config(DEFAULT_CONFIGFILE);
|
||||
- if (!conf)
|
||||
- exit(1);
|
||||
- if (verbosity)
|
||||
- libmp_verbosity = verbosity;
|
||||
- uxsock_timeout = conf->uxsock_timeout;
|
||||
- err = uxclnt(optarg, uxsock_timeout + 100);
|
||||
- free_config(conf);
|
||||
- return err;
|
||||
+ opt_k = true;
|
||||
+ opt_k_arg = optarg;
|
||||
+ break;
|
||||
case 'B':
|
||||
bindings_read_only = 1;
|
||||
break;
|
||||
@@ -3373,7 +3368,7 @@ main (int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
- if (optind < argc) {
|
||||
+ if (opt_k || optind < argc) {
|
||||
char cmd[CMDSIZE];
|
||||
char * s = cmd;
|
||||
char * c = s;
|
||||
@@ -3388,14 +3383,20 @@ main (int argc, char *argv[])
|
||||
libmp_verbosity = verbosity;
|
||||
uxsock_timeout = conf->uxsock_timeout;
|
||||
memset(cmd, 0x0, CMDSIZE);
|
||||
- while (optind < argc) {
|
||||
- if (strchr(argv[optind], ' '))
|
||||
- c += snprintf(c, s + CMDSIZE - c, "\"%s\" ", argv[optind]);
|
||||
- else
|
||||
- c += snprintf(c, s + CMDSIZE - c, "%s ", argv[optind]);
|
||||
- optind++;
|
||||
+ if (opt_k)
|
||||
+ s = opt_k_arg;
|
||||
+ else {
|
||||
+ while (optind < argc) {
|
||||
+ if (strchr(argv[optind], ' '))
|
||||
+ c += snprintf(c, s + CMDSIZE - c,
|
||||
+ "\"%s\" ", argv[optind]);
|
||||
+ else
|
||||
+ c += snprintf(c, s + CMDSIZE - c,
|
||||
+ "%s ", argv[optind]);
|
||||
+ optind++;
|
||||
+ }
|
||||
+ c += snprintf(c, s + CMDSIZE - c, "\n");
|
||||
}
|
||||
- c += snprintf(c, s + CMDSIZE - c, "\n");
|
||||
err = uxclnt(s, uxsock_timeout + 100);
|
||||
free_config(conf);
|
||||
return err;
|
@ -1,154 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Sat, 26 Sep 2020 15:22:34 +0200
|
||||
Subject: [PATCH] multipathd: sanitize uxsock_listen()
|
||||
|
||||
We were allocating 1025 poll fds, which is weird. Change it to a power of two,
|
||||
and make this more easily customizable in general. Use POLLFDS_BASE rather
|
||||
than the hard-coded "2" for the number of fds we poll besides client
|
||||
connections. Introduce a maximum number of clients that can connect. When
|
||||
this number is reached, we simply stop polling the accept socket, so that new
|
||||
connections aren't accepted any more. Don't attempt to realloc() the pollfd
|
||||
array if the number of clients decreases. It's unlikely to ever be more than
|
||||
one or two pages. Finally, there's no need to wake up every 5s. Our signal
|
||||
handling is robust. Just sleep forever in ppoll() if nothing happens.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/uxlsnr.c | 70 ++++++++++++++++++++++++++++-----------------
|
||||
1 file changed, 43 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/multipathd/uxlsnr.c b/multipathd/uxlsnr.c
|
||||
index ce2b6800..cd462b6d 100644
|
||||
--- a/multipathd/uxlsnr.c
|
||||
+++ b/multipathd/uxlsnr.c
|
||||
@@ -41,14 +41,25 @@
|
||||
#include "cli.h"
|
||||
#include "uxlsnr.h"
|
||||
|
||||
-static struct timespec sleep_time = {5, 0};
|
||||
-
|
||||
struct client {
|
||||
struct list_head node;
|
||||
int fd;
|
||||
};
|
||||
|
||||
-#define MIN_POLLS 1023
|
||||
+/* The number of fds we poll on, other than individual client connections */
|
||||
+#define POLLFDS_BASE 2
|
||||
+#define POLLFD_CHUNK (4096 / sizeof(struct pollfd))
|
||||
+/* Minimum mumber of pollfds to reserve for clients */
|
||||
+#define MIN_POLLS (POLLFD_CHUNK - POLLFDS_BASE)
|
||||
+/*
|
||||
+ * Max number of client connections allowed
|
||||
+ * During coldplug, there may be a large number of "multipath -u"
|
||||
+ * processes connecting.
|
||||
+ */
|
||||
+#define MAX_CLIENTS (16384 - POLLFDS_BASE)
|
||||
+
|
||||
+/* Compile-time error if POLLFD_CHUNK is too small */
|
||||
+static __attribute__((unused)) char ___a[-(MIN_POLLS <= 0)];
|
||||
|
||||
static LIST_HEAD(clients);
|
||||
static pthread_mutex_t client_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
@@ -282,13 +293,13 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, long ux_sock,
|
||||
char *inbuf;
|
||||
char *reply;
|
||||
sigset_t mask;
|
||||
- int old_clients = MIN_POLLS;
|
||||
+ int max_pfds = MIN_POLLS + POLLFDS_BASE;
|
||||
/* conf->sequence_nr will be 1 when uxsock_listen is first called */
|
||||
unsigned int sequence_nr = 0;
|
||||
struct watch_descriptors wds = { .conf_wd = -1, .dir_wd = -1 };
|
||||
|
||||
condlog(3, "uxsock: startup listener");
|
||||
- polls = (struct pollfd *)MALLOC((MIN_POLLS + 2) * sizeof(struct pollfd));
|
||||
+ polls = MALLOC(max_pfds * sizeof(*polls));
|
||||
if (!polls) {
|
||||
condlog(0, "uxsock: failed to allocate poll fds");
|
||||
exit_daemon();
|
||||
@@ -312,28 +323,33 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, long ux_sock,
|
||||
list_for_each_entry(c, &clients, node) {
|
||||
num_clients++;
|
||||
}
|
||||
- if (num_clients != old_clients) {
|
||||
+ if (num_clients + POLLFDS_BASE > max_pfds) {
|
||||
struct pollfd *new;
|
||||
- if (num_clients <= MIN_POLLS && old_clients > MIN_POLLS) {
|
||||
- new = REALLOC(polls, (2 + MIN_POLLS) *
|
||||
- sizeof(struct pollfd));
|
||||
- } else if (num_clients <= MIN_POLLS && old_clients <= MIN_POLLS) {
|
||||
- new = polls;
|
||||
- } else {
|
||||
- new = REALLOC(polls, (2 + num_clients) *
|
||||
- sizeof(struct pollfd));
|
||||
- }
|
||||
- if (!new) {
|
||||
- condlog(0, "%s: failed to realloc %d poll fds",
|
||||
- "uxsock", 2 + num_clients);
|
||||
- num_clients = old_clients;
|
||||
- } else {
|
||||
- old_clients = num_clients;
|
||||
+ int n_new = max_pfds + POLLFD_CHUNK;
|
||||
+
|
||||
+ new = REALLOC(polls, n_new * sizeof(*polls));
|
||||
+ if (new) {
|
||||
+ max_pfds = n_new;
|
||||
polls = new;
|
||||
+ } else {
|
||||
+ condlog(1, "%s: realloc failure, %d clients not served",
|
||||
+ __func__,
|
||||
+ num_clients + POLLFDS_BASE - max_pfds);
|
||||
+ num_clients = max_pfds - POLLFDS_BASE;
|
||||
}
|
||||
}
|
||||
- polls[0].fd = ux_sock;
|
||||
- polls[0].events = POLLIN;
|
||||
+ if (num_clients < MAX_CLIENTS) {
|
||||
+ polls[0].fd = ux_sock;
|
||||
+ polls[0].events = POLLIN;
|
||||
+ } else {
|
||||
+ /*
|
||||
+ * New clients can't connect, num_clients won't grow
|
||||
+ * to MAX_CLIENTS or higher
|
||||
+ */
|
||||
+ condlog(1, "%s: max client connections reached, pausing polling",
|
||||
+ __func__);
|
||||
+ polls[0].fd = -1;
|
||||
+ }
|
||||
|
||||
reset_watch(notify_fd, &wds, &sequence_nr);
|
||||
if (notify_fd == -1 || (wds.conf_wd == -1 && wds.dir_wd == -1))
|
||||
@@ -343,19 +359,19 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, long ux_sock,
|
||||
polls[1].events = POLLIN;
|
||||
|
||||
/* setup the clients */
|
||||
- i = 2;
|
||||
+ i = POLLFDS_BASE;
|
||||
list_for_each_entry(c, &clients, node) {
|
||||
polls[i].fd = c->fd;
|
||||
polls[i].events = POLLIN;
|
||||
i++;
|
||||
- if (i >= 2 + num_clients)
|
||||
+ if (i >= max_pfds)
|
||||
break;
|
||||
}
|
||||
n_pfds = i;
|
||||
pthread_cleanup_pop(1);
|
||||
|
||||
/* most of our life is spent in this call */
|
||||
- poll_count = ppoll(polls, n_pfds, &sleep_time, &mask);
|
||||
+ poll_count = ppoll(polls, n_pfds, NULL, &mask);
|
||||
|
||||
handle_signals(false);
|
||||
if (poll_count == -1) {
|
||||
@@ -388,7 +404,7 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, long ux_sock,
|
||||
}
|
||||
|
||||
/* see if a client wants to speak to us */
|
||||
- for (i = 2; i < n_pfds; i++) {
|
||||
+ for (i = POLLFDS_BASE; i < n_pfds; i++) {
|
||||
if (polls[i].revents & POLLIN) {
|
||||
struct timespec start_time;
|
||||
|
@ -1,104 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Thu, 15 Oct 2020 16:13:14 +0200
|
||||
Subject: [PATCH] libmultipath: fix race between log_safe and log_thread_stop()
|
||||
|
||||
log_safe() could race with log_thread_stop(); simply
|
||||
checking the value of log_thr has never been safe. By converting the
|
||||
mutexes to static initializers, we avoid having to destroy them, and thus
|
||||
possibly accessing a destroyed mutex in log_safe(). Furthermore, taking
|
||||
both the logev_lock and the logq_lock makes sure the logarea isn't freed
|
||||
while we are writing to it.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/log_pthread.c | 48 +++++++++++++++++++++-----------------
|
||||
1 file changed, 26 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/log_pthread.c b/libmultipath/log_pthread.c
|
||||
index 3a2566ae..0d48c52c 100644
|
||||
--- a/libmultipath/log_pthread.c
|
||||
+++ b/libmultipath/log_pthread.c
|
||||
@@ -17,31 +17,42 @@
|
||||
|
||||
static pthread_t log_thr;
|
||||
|
||||
-static pthread_mutex_t logq_lock;
|
||||
-static pthread_mutex_t logev_lock;
|
||||
-static pthread_cond_t logev_cond;
|
||||
+/* logev_lock must not be taken with logq_lock held */
|
||||
+static pthread_mutex_t logq_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
+static pthread_mutex_t logev_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
+static pthread_cond_t logev_cond = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
static int logq_running;
|
||||
static int log_messages_pending;
|
||||
|
||||
void log_safe (int prio, const char * fmt, va_list ap)
|
||||
{
|
||||
+ bool running;
|
||||
+
|
||||
if (prio > LOG_DEBUG)
|
||||
prio = LOG_DEBUG;
|
||||
|
||||
- if (log_thr == (pthread_t)0) {
|
||||
- vsyslog(prio, fmt, ap);
|
||||
- return;
|
||||
- }
|
||||
+ /*
|
||||
+ * logev_lock protects logq_running. By holding it, we avoid a race
|
||||
+ * with log_thread_stop() -> log_close(), which would free the logarea.
|
||||
+ */
|
||||
+ pthread_mutex_lock(&logev_lock);
|
||||
+ pthread_cleanup_push(cleanup_mutex, &logev_lock);
|
||||
+ running = logq_running;
|
||||
|
||||
- pthread_mutex_lock(&logq_lock);
|
||||
- log_enqueue(prio, fmt, ap);
|
||||
- pthread_mutex_unlock(&logq_lock);
|
||||
+ if (running) {
|
||||
+ pthread_mutex_lock(&logq_lock);
|
||||
+ pthread_cleanup_push(cleanup_mutex, &logq_lock);
|
||||
+ log_enqueue(prio, fmt, ap);
|
||||
+ pthread_cleanup_pop(1);
|
||||
|
||||
- pthread_mutex_lock(&logev_lock);
|
||||
- log_messages_pending = 1;
|
||||
- pthread_cond_signal(&logev_cond);
|
||||
- pthread_mutex_unlock(&logev_lock);
|
||||
+ log_messages_pending = 1;
|
||||
+ pthread_cond_signal(&logev_cond);
|
||||
+ }
|
||||
+ pthread_cleanup_pop(1);
|
||||
+
|
||||
+ if (!running)
|
||||
+ vsyslog(prio, fmt, ap);
|
||||
}
|
||||
|
||||
static void flush_logqueue (void)
|
||||
@@ -103,9 +114,6 @@ void log_thread_start (pthread_attr_t *attr)
|
||||
int running = 0;
|
||||
|
||||
logdbg(stderr,"enter log_thread_start\n");
|
||||
- pthread_mutex_init(&logq_lock, NULL);
|
||||
- pthread_mutex_init(&logev_lock, NULL);
|
||||
- pthread_cond_init(&logev_cond, NULL);
|
||||
|
||||
if (log_init("multipathd", 0)) {
|
||||
fprintf(stderr,"can't initialize log buffer\n");
|
||||
@@ -154,13 +162,9 @@ void log_thread_stop (void)
|
||||
}
|
||||
pthread_cleanup_pop(1);
|
||||
|
||||
- flush_logqueue();
|
||||
if (running)
|
||||
pthread_join(log_thr, NULL);
|
||||
|
||||
- pthread_mutex_destroy(&logq_lock);
|
||||
- pthread_mutex_destroy(&logev_lock);
|
||||
- pthread_cond_destroy(&logev_cond);
|
||||
-
|
||||
+ flush_logqueue();
|
||||
log_close();
|
||||
}
|
@ -1,502 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Wed, 21 Oct 2020 16:39:23 -0500
|
||||
Subject: [PATCH] multipath: add libmpathvalid library
|
||||
|
||||
This library allows other programs to check if a path should be claimed
|
||||
by multipath. It exports an init function, that needs to be called
|
||||
before and after all other library calls, an exit function, that needs
|
||||
to be called after all library calls, a function to reread the multipath
|
||||
configuration files, and two more functions.
|
||||
|
||||
mpath_get_mode() get the configured find_multipaths mode.
|
||||
mpath_is_path() returns whether the device is claimed by multipath, and
|
||||
optionally returns the wwid. This code works slightly different than
|
||||
the multipath -c/u code for SMART mode. Instead of checking all the
|
||||
existing paths to see if another has the same wwid, it expects the
|
||||
caller to pass in an array of the already known path wwids, and checks
|
||||
if the current path matches any of those.
|
||||
|
||||
The library also doesn't set up the device-mapper library. It leaves
|
||||
this up to the caller.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
Makefile | 3 +-
|
||||
libmpathvalid/Makefile | 39 ++++++
|
||||
libmpathvalid/libmpathvalid.version | 10 ++
|
||||
libmpathvalid/mpath_valid.c | 202 ++++++++++++++++++++++++++++
|
||||
libmpathvalid/mpath_valid.h | 155 +++++++++++++++++++++
|
||||
libmultipath/libmultipath.version | 6 +
|
||||
6 files changed, 414 insertions(+), 1 deletion(-)
|
||||
create mode 100644 libmpathvalid/Makefile
|
||||
create mode 100644 libmpathvalid/libmpathvalid.version
|
||||
create mode 100644 libmpathvalid/mpath_valid.c
|
||||
create mode 100644 libmpathvalid/mpath_valid.h
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 4a3491da..f127ff91 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -9,6 +9,7 @@ BUILDDIRS := \
|
||||
libmultipath/checkers \
|
||||
libmultipath/foreign \
|
||||
libmpathpersist \
|
||||
+ libmpathvalid \
|
||||
multipath \
|
||||
multipathd \
|
||||
mpathpersist \
|
||||
@@ -29,7 +30,7 @@ $(BUILDDIRS):
|
||||
$(MAKE) -C $@
|
||||
|
||||
libmultipath libdmmp: libmpathcmd
|
||||
-libmpathpersist multipath multipathd: libmultipath
|
||||
+libmpathpersist libmpathvalid multipath multipathd: libmultipath
|
||||
mpathpersist multipathd: libmpathpersist
|
||||
|
||||
libmultipath/checkers.install \
|
||||
diff --git a/libmpathvalid/Makefile b/libmpathvalid/Makefile
|
||||
new file mode 100644
|
||||
index 00000000..6bea4bcd
|
||||
--- /dev/null
|
||||
+++ b/libmpathvalid/Makefile
|
||||
@@ -0,0 +1,39 @@
|
||||
+include ../Makefile.inc
|
||||
+
|
||||
+SONAME = 0
|
||||
+DEVLIB = libmpathvalid.so
|
||||
+LIBS = $(DEVLIB).$(SONAME)
|
||||
+VERSION_SCRIPT := libmpathvalid.version
|
||||
+
|
||||
+CFLAGS += $(LIB_CFLAGS) -I$(multipathdir) -I$(mpathcmddir)
|
||||
+
|
||||
+LIBDEPS += -lpthread -ldevmapper -ldl -L$(multipathdir) \
|
||||
+ -lmultipath -L$(mpathcmddir) -lmpathcmd -ludev
|
||||
+
|
||||
+OBJS = mpath_valid.o
|
||||
+
|
||||
+all: $(LIBS)
|
||||
+
|
||||
+$(LIBS): $(OBJS) $(VERSION_SCRIPT)
|
||||
+ $(CC) $(LDFLAGS) $(SHARED_FLAGS) -Wl,-soname=$@ -o $@ $(OBJS) $(LIBDEPS) -Wl,--version-script=libmpathvalid.version
|
||||
+ $(LN) $(LIBS) $(DEVLIB)
|
||||
+
|
||||
+install: $(LIBS)
|
||||
+ $(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(syslibdir)
|
||||
+ $(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(syslibdir)/$(LIBS)
|
||||
+ $(LN) $(LIBS) $(DESTDIR)$(syslibdir)/$(DEVLIB)
|
||||
+ $(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(includedir)
|
||||
+ $(INSTALL_PROGRAM) -m 644 mpath_valid.h $(DESTDIR)$(includedir)
|
||||
+
|
||||
+uninstall:
|
||||
+ $(RM) $(DESTDIR)$(syslibdir)/$(LIBS)
|
||||
+ $(RM) $(DESTDIR)$(syslibdir)/$(DEVLIB)
|
||||
+ $(RM) $(DESTDIR)$(includedir)/mpath_valid.h
|
||||
+
|
||||
+clean: dep_clean
|
||||
+ $(RM) core *.a *.o *.so *.so.* *.gz
|
||||
+
|
||||
+include $(wildcard $(OBJS:.o=.d))
|
||||
+
|
||||
+dep_clean:
|
||||
+ $(RM) $(OBJS:.o=.d)
|
||||
diff --git a/libmpathvalid/libmpathvalid.version b/libmpathvalid/libmpathvalid.version
|
||||
new file mode 100644
|
||||
index 00000000..3bd0d3c5
|
||||
--- /dev/null
|
||||
+++ b/libmpathvalid/libmpathvalid.version
|
||||
@@ -0,0 +1,10 @@
|
||||
+MPATH_1.0 {
|
||||
+ global:
|
||||
+ mpathvalid_init;
|
||||
+ mpathvalid_reload_config;
|
||||
+ mpathvalid_exit;
|
||||
+ mpathvalid_is_path;
|
||||
+ mpathvalid_get_mode;
|
||||
+ local:
|
||||
+ *;
|
||||
+};
|
||||
diff --git a/libmpathvalid/mpath_valid.c b/libmpathvalid/mpath_valid.c
|
||||
new file mode 100644
|
||||
index 00000000..7073d17d
|
||||
--- /dev/null
|
||||
+++ b/libmpathvalid/mpath_valid.c
|
||||
@@ -0,0 +1,202 @@
|
||||
+#include <stdlib.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdint.h>
|
||||
+#include <libdevmapper.h>
|
||||
+#include <libudev.h>
|
||||
+#include <errno.h>
|
||||
+
|
||||
+#include "devmapper.h"
|
||||
+#include "structs.h"
|
||||
+#include "util.h"
|
||||
+#include "config.h"
|
||||
+#include "discovery.h"
|
||||
+#include "wwids.h"
|
||||
+#include "sysfs.h"
|
||||
+#include "mpath_cmd.h"
|
||||
+#include "valid.h"
|
||||
+#include "mpath_valid.h"
|
||||
+#include "debug.h"
|
||||
+
|
||||
+static unsigned int
|
||||
+get_conf_mode(struct config *conf)
|
||||
+{
|
||||
+ if (conf->find_multipaths == FIND_MULTIPATHS_SMART)
|
||||
+ return MPATH_SMART;
|
||||
+ if (conf->find_multipaths == FIND_MULTIPATHS_GREEDY)
|
||||
+ return MPATH_GREEDY;
|
||||
+ return MPATH_STRICT;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+set_conf_mode(struct config *conf, unsigned int mode)
|
||||
+{
|
||||
+ if (mode == MPATH_SMART)
|
||||
+ conf->find_multipaths = FIND_MULTIPATHS_SMART;
|
||||
+ else if (mode == MPATH_GREEDY)
|
||||
+ conf->find_multipaths = FIND_MULTIPATHS_GREEDY;
|
||||
+ else
|
||||
+ conf->find_multipaths = FIND_MULTIPATHS_STRICT;
|
||||
+}
|
||||
+
|
||||
+unsigned int
|
||||
+mpathvalid_get_mode(void)
|
||||
+{
|
||||
+ int mode;
|
||||
+ struct config *conf;
|
||||
+
|
||||
+ conf = get_multipath_config();
|
||||
+ if (!conf)
|
||||
+ mode = MPATH_MODE_ERROR;
|
||||
+ else
|
||||
+ mode = get_conf_mode(conf);
|
||||
+ put_multipath_config(conf);
|
||||
+ return mode;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+convert_result(int result) {
|
||||
+ switch (result) {
|
||||
+ case PATH_IS_ERROR:
|
||||
+ return MPATH_IS_ERROR;
|
||||
+ case PATH_IS_NOT_VALID:
|
||||
+ return MPATH_IS_NOT_VALID;
|
||||
+ case PATH_IS_VALID:
|
||||
+ return MPATH_IS_VALID;
|
||||
+ case PATH_IS_VALID_NO_CHECK:
|
||||
+ return MPATH_IS_VALID_NO_CHECK;
|
||||
+ case PATH_IS_MAYBE_VALID:
|
||||
+ return MPATH_IS_MAYBE_VALID;
|
||||
+ }
|
||||
+ return MPATH_IS_ERROR;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+set_log_style(int log_style)
|
||||
+{
|
||||
+ /*
|
||||
+ * convert MPATH_LOG_* to LOGSINK_*
|
||||
+ * currently there is no work to do here.
|
||||
+ */
|
||||
+ logsink = log_style;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+load_default_config(int verbosity)
|
||||
+{
|
||||
+ /* need to set verbosity here to control logging during init_config() */
|
||||
+ libmp_verbosity = verbosity;
|
||||
+ if (init_config(DEFAULT_CONFIGFILE))
|
||||
+ return -1;
|
||||
+ /* Need to override verbosity from init_config() */
|
||||
+ libmp_verbosity = verbosity;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+mpathvalid_init(int verbosity, int log_style)
|
||||
+{
|
||||
+ unsigned int version[3];
|
||||
+
|
||||
+ set_log_style(log_style);
|
||||
+ if (libmultipath_init())
|
||||
+ return -1;
|
||||
+
|
||||
+ skip_libmp_dm_init();
|
||||
+ if (load_default_config(verbosity))
|
||||
+ goto fail;
|
||||
+
|
||||
+ if (dm_prereq(version))
|
||||
+ goto fail_config;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+fail_config:
|
||||
+ uninit_config();
|
||||
+fail:
|
||||
+ libmultipath_exit();
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+mpathvalid_reload_config(void)
|
||||
+{
|
||||
+ uninit_config();
|
||||
+ return load_default_config(libmp_verbosity);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+mpathvalid_exit(void)
|
||||
+{
|
||||
+ uninit_config();
|
||||
+ libmultipath_exit();
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * name: name of path to check
|
||||
+ * mode: mode to use for determination. MPATH_DEFAULT uses configured mode
|
||||
+ * info: on success, contains the path wwid
|
||||
+ * paths: array of the returned mpath_info from other claimed paths
|
||||
+ * nr_paths: the size of the paths array
|
||||
+ */
|
||||
+int
|
||||
+mpathvalid_is_path(const char *name, unsigned int mode, char **wwid,
|
||||
+ const char **path_wwids, unsigned int nr_paths)
|
||||
+{
|
||||
+ struct config *conf;
|
||||
+ int find_multipaths_saved, r = MPATH_IS_ERROR;
|
||||
+ unsigned int i;
|
||||
+ struct path *pp;
|
||||
+
|
||||
+ if (!name || mode >= MPATH_MODE_ERROR)
|
||||
+ return r;
|
||||
+ if (nr_paths > 0 && !path_wwids)
|
||||
+ return r;
|
||||
+ if (!udev)
|
||||
+ return r;
|
||||
+
|
||||
+ pp = alloc_path();
|
||||
+ if (!pp)
|
||||
+ return r;
|
||||
+
|
||||
+ if (wwid) {
|
||||
+ *wwid = (char *)malloc(WWID_SIZE);
|
||||
+ if (!*wwid)
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ conf = get_multipath_config();
|
||||
+ if (!conf)
|
||||
+ goto out_wwid;
|
||||
+ find_multipaths_saved = conf->find_multipaths;
|
||||
+ if (mode != MPATH_DEFAULT)
|
||||
+ set_conf_mode(conf, mode);
|
||||
+ r = convert_result(is_path_valid(name, conf, pp, true));
|
||||
+ conf->find_multipaths = find_multipaths_saved;
|
||||
+ put_multipath_config(conf);
|
||||
+
|
||||
+ if (r == MPATH_IS_MAYBE_VALID) {
|
||||
+ for (i = 0; i < nr_paths; i++) {
|
||||
+ if (path_wwids[i] &&
|
||||
+ strncmp(path_wwids[i], pp->wwid, WWID_SIZE) == 0) {
|
||||
+ r = MPATH_IS_VALID;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+out_wwid:
|
||||
+ if (wwid) {
|
||||
+ if (r == MPATH_IS_VALID || r == MPATH_IS_VALID_NO_CHECK ||
|
||||
+ r == MPATH_IS_MAYBE_VALID)
|
||||
+ strlcpy(*wwid, pp->wwid, WWID_SIZE);
|
||||
+ else {
|
||||
+ free(*wwid);
|
||||
+ *wwid = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+out:
|
||||
+ free_path(pp);
|
||||
+ return r;
|
||||
+}
|
||||
diff --git a/libmpathvalid/mpath_valid.h b/libmpathvalid/mpath_valid.h
|
||||
new file mode 100644
|
||||
index 00000000..63de4e1c
|
||||
--- /dev/null
|
||||
+++ b/libmpathvalid/mpath_valid.h
|
||||
@@ -0,0 +1,155 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2015 Red Hat, Inc.
|
||||
+ *
|
||||
+ * This file is part of the device-mapper multipath userspace tools.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU Lesser General Public License
|
||||
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+#ifndef LIB_MPATH_VALID_H
|
||||
+#define LIB_MPATH_VALID_H
|
||||
+
|
||||
+#ifdef __cpluscplus
|
||||
+extern "C" {
|
||||
+#endif
|
||||
+
|
||||
+enum mpath_valid_mode {
|
||||
+ MPATH_DEFAULT,
|
||||
+ MPATH_STRICT,
|
||||
+ MPATH_SMART,
|
||||
+ MPATH_GREEDY,
|
||||
+ MPATH_MODE_ERROR,
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * MPATH_IS_VALID_NO_CHECK is used to indicate that it is safe to skip
|
||||
+ * checks to see if the device has already been released to the system
|
||||
+ * for use by things other that multipath.
|
||||
+ * MPATH_IS_MAYBE_VALID is used to indicate that this device would
|
||||
+ * be a valid multipath path device if another device with the same
|
||||
+ * wwid existed */
|
||||
+enum mpath_valid_result {
|
||||
+ MPATH_IS_ERROR = -1,
|
||||
+ MPATH_IS_NOT_VALID,
|
||||
+ MPATH_IS_VALID,
|
||||
+ MPATH_IS_VALID_NO_CHECK,
|
||||
+ MPATH_IS_MAYBE_VALID,
|
||||
+};
|
||||
+
|
||||
+enum mpath_valid_log_style {
|
||||
+ MPATH_LOG_STDERR = -1, /* log to STDERR */
|
||||
+ MPATH_LOG_STDERR_TIMESTAMP, /* log to STDERR, with timestamps */
|
||||
+ MPATH_LOG_SYSLOG, /* log to system log */
|
||||
+};
|
||||
+
|
||||
+enum mpath_valid_verbosity {
|
||||
+ MPATH_LOG_PRIO_NOLOG = -1, /* log nothing */
|
||||
+ MPATH_LOG_PRIO_ERR,
|
||||
+ MPATH_LOG_PRIO_WARN,
|
||||
+ MPATH_LOG_PRIO_NOTICE,
|
||||
+ MPATH_LOG_PRIO_INFO,
|
||||
+ MPATH_LOG_PRIO_DEBUG,
|
||||
+};
|
||||
+
|
||||
+/* Function declarations */
|
||||
+
|
||||
+/*
|
||||
+ * DESCRIPTION:
|
||||
+ * Initialize the device mapper multipath configuration. This
|
||||
+ * function must be invoked before calling any other
|
||||
+ * libmpathvalid functions. Call mpathvalid_exit() to cleanup.
|
||||
+ * @verbosity: the logging level (mpath_valid_verbosity)
|
||||
+ * @log_style: the logging style (mpath_valid_log_style)
|
||||
+ *
|
||||
+ * RESTRICTIONS:
|
||||
+ * Calling mpathvalid_init() after calling mpathvalid_exit() has no
|
||||
+ * effect.
|
||||
+ *
|
||||
+ * RETURNS: 0 = Success, -1 = Failure
|
||||
+ */
|
||||
+int mpathvalid_init(int verbosity, int log_style);
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * DESCRIPTION:
|
||||
+ * Reread the multipath configuration files and reinitalize
|
||||
+ * the device mapper multipath configuration. This function can
|
||||
+ * be called as many times as necessary.
|
||||
+ *
|
||||
+ * RETURNS: 0 = Success, -1 = Failure
|
||||
+ */
|
||||
+int mpathvalid_reload_config(void);
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * DESCRIPTION:
|
||||
+ * Release the device mapper multipath configuration. This
|
||||
+ * function must be called to cleanup resoures allocated by
|
||||
+ * mpathvalid_init(). After calling this function, no futher
|
||||
+ * libmpathvalid functions may be called.
|
||||
+ *
|
||||
+ * RETURNS: 0 = Success, -1 = Failure
|
||||
+ */
|
||||
+int mpathvalid_exit(void);
|
||||
+
|
||||
+/*
|
||||
+ * DESCRIPTION:
|
||||
+ * Return the configured find_multipaths claim mode, using the
|
||||
+ * configuration from either mpathvalid_init() or
|
||||
+ * mpathvalid_reload_config()
|
||||
+ *
|
||||
+ * RETURNS:
|
||||
+ * MPATH_STRICT, MPATH_SMART, MPATH_GREEDY, or MPATH_MODE_ERROR
|
||||
+ *
|
||||
+ * MPATH_STRICT = find_multiapths (yes|on|no|off)
|
||||
+ * MPATH_SMART = find_multipaths smart
|
||||
+ * MPATH_GREEDY = find_multipaths greedy
|
||||
+ * MPATH_MODE_ERROR = multipath configuration not initialized
|
||||
+ */
|
||||
+unsigned int mpathvalid_get_mode(void);
|
||||
+/*
|
||||
+ * DESCRIPTION:
|
||||
+ * Return whether device-mapper multipath claims a path device,
|
||||
+ * using the configuration read from either mpathvalid_init() or
|
||||
+ * mpathvalid_reload_config(). If the device is either claimed or
|
||||
+ * potentially claimed (MPATH_IS_VALID, MPATH_IS_VALID_NO_CHECK,
|
||||
+ * or MPATH_IS_MAYBE_VALID) and wwid is not NULL, then *wiid will
|
||||
+ * be set to point to the wwid of device. If set, *wwid must be
|
||||
+ * freed by the caller. path_wwids is an obptional parameter that
|
||||
+ * points to an array of wwids, that were returned from previous
|
||||
+ * calls to mpathvalid_is_path(). These are wwids of existing
|
||||
+ * devices that are or potentially are claimed by device-mapper
|
||||
+ * multipath. path_wwids is used with the MPATH_SMART claim mode,
|
||||
+ * to claim devices when another device with the same wwid exists.
|
||||
+ * nr_paths must either be set to the number of elements of
|
||||
+ * path_wwids, or 0, if path_wwids is NULL.
|
||||
+ * @name: The kernel name of the device. input argument
|
||||
+ * @mode: the find_multipaths claim mode (mpath_valid_mode). input argument
|
||||
+ * @wwid: address of a pointer to the path wwid, or NULL. Output argument.
|
||||
+ * Set if path is/may be claimed. If set, must be freed by caller
|
||||
+ * @path_wwids: Array of pointers to path wwids, or NULL. input argument
|
||||
+ * @nr_paths: number of elements in path_wwids array. input argument.
|
||||
+ *
|
||||
+ * RETURNS: device claim result (mpath_valid_result)
|
||||
+ * Also sets *wwid if wwid is not NULL, and the claim result is
|
||||
+ * MPATH_IS_VALID, MPATH_IS_VALID_NO_CHECK, or
|
||||
+ * MPATH_IS_MAYBE_VALID
|
||||
+ */
|
||||
+int mpathvalid_is_path(const char *name, unsigned int mode, char **wwid,
|
||||
+ const char **path_wwids, unsigned int nr_paths);
|
||||
+
|
||||
+#ifdef __cplusplus
|
||||
+}
|
||||
+#endif
|
||||
+#endif /* LIB_PATH_VALID_H */
|
||||
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
|
||||
index 67a7379f..2e3583f5 100644
|
||||
--- a/libmultipath/libmultipath.version
|
||||
+++ b/libmultipath/libmultipath.version
|
||||
@@ -264,3 +264,9 @@ LIBMULTIPATH_4.1.0 {
|
||||
global:
|
||||
libmp_verbosity;
|
||||
} LIBMULTIPATH_4.0.0;
|
||||
+
|
||||
+LIBMULTIPATH_4.2.0 {
|
||||
+global:
|
||||
+ dm_prereq;
|
||||
+ skip_libmp_dm_init;
|
||||
+} LIBMULTIPATH_4.1.0;
|
@ -1,529 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Wed, 21 Oct 2020 16:39:24 -0500
|
||||
Subject: [PATCH] multipath-tools tests: and unit tests for libmpathvalid
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
Makefile.inc | 1 +
|
||||
tests/Makefile | 5 +-
|
||||
tests/mpathvalid.c | 467 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 472 insertions(+), 1 deletion(-)
|
||||
create mode 100644 tests/mpathvalid.c
|
||||
|
||||
diff --git a/Makefile.inc b/Makefile.inc
|
||||
index e05f3a91..13587a9f 100644
|
||||
--- a/Makefile.inc
|
||||
+++ b/Makefile.inc
|
||||
@@ -66,6 +66,7 @@ libdir = $(prefix)/$(LIB)/multipath
|
||||
unitdir = $(prefix)/$(SYSTEMDPATH)/systemd/system
|
||||
mpathpersistdir = $(TOPDIR)/libmpathpersist
|
||||
mpathcmddir = $(TOPDIR)/libmpathcmd
|
||||
+mpathvaliddir = $(TOPDIR)/libmpathvalid
|
||||
thirdpartydir = $(TOPDIR)/third-party
|
||||
libdmmpdir = $(TOPDIR)/libdmmp
|
||||
nvmedir = $(TOPDIR)/libmultipath/nvme
|
||||
diff --git a/tests/Makefile b/tests/Makefile
|
||||
index 908407ea..54da774e 100644
|
||||
--- a/tests/Makefile
|
||||
+++ b/tests/Makefile
|
||||
@@ -13,7 +13,7 @@ CFLAGS += $(BIN_CFLAGS) -I$(multipathdir) -I$(mpathcmddir) \
|
||||
LIBDEPS += -L. -L$(mpathcmddir) -lmultipath -lmpathcmd -lcmocka
|
||||
|
||||
TESTS := uevent parser util dmevents hwtable blacklist unaligned vpd pgpolicy \
|
||||
- alias directio valid devt
|
||||
+ alias directio valid devt mpathvalid
|
||||
HELPERS := test-lib.o test-log.o
|
||||
|
||||
.SILENT: $(TESTS:%=%.o)
|
||||
@@ -31,6 +31,7 @@ endif
|
||||
ifneq ($(DIO_TEST_DEV),)
|
||||
directio-test_FLAGS := -DDIO_TEST_DEV=\"$(DIO_TEST_DEV)\"
|
||||
endif
|
||||
+mpathvalid-test_FLAGS := -I$(mpathvaliddir)
|
||||
|
||||
# test-specific linker flags
|
||||
# XYZ-test_TESTDEPS: test libraries containing __wrap_xyz functions
|
||||
@@ -56,6 +57,8 @@ alias-test_LIBDEPS := -lpthread -ldl
|
||||
valid-test_OBJDEPS := ../libmultipath/valid.o
|
||||
valid-test_LIBDEPS := -ludev -lpthread -ldl
|
||||
devt-test_LIBDEPS := -ludev
|
||||
+mpathvalid-test_LIBDEPS := -ludev -lpthread -ldl
|
||||
+mpathvalid-test_OBJDEPS := ../libmpathvalid/mpath_valid.o
|
||||
ifneq ($(DIO_TEST_DEV),)
|
||||
directio-test_LIBDEPS := -laio
|
||||
endif
|
||||
diff --git a/tests/mpathvalid.c b/tests/mpathvalid.c
|
||||
new file mode 100644
|
||||
index 00000000..5ffabb9d
|
||||
--- /dev/null
|
||||
+++ b/tests/mpathvalid.c
|
||||
@@ -0,0 +1,467 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2020 Benjamin Marzinski, Red Hat
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+ */
|
||||
+#include <stdbool.h>
|
||||
+#include <stdarg.h>
|
||||
+#include <stddef.h>
|
||||
+#include <setjmp.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <unistd.h>
|
||||
+#include <libudev.h>
|
||||
+#include <cmocka.h>
|
||||
+#include "structs.h"
|
||||
+#include "config.h"
|
||||
+#include "mpath_valid.h"
|
||||
+#include "util.h"
|
||||
+#include "debug.h"
|
||||
+
|
||||
+const char *test_dev = "test_name";
|
||||
+#define TEST_WWID "WWID_123"
|
||||
+#define CONF_TEMPLATE "mpathvalid-testconf-XXXXXXXX"
|
||||
+char conf_name[] = CONF_TEMPLATE;
|
||||
+bool initialized;
|
||||
+
|
||||
+#if 0
|
||||
+static int mode_to_findmp(unsigned int mode)
|
||||
+{
|
||||
+ switch (mode) {
|
||||
+ case MPATH_SMART:
|
||||
+ return FIND_MULTIPATHS_SMART;
|
||||
+ case MPATH_GREEDY:
|
||||
+ return FIND_MULTIPATHS_GREEDY;
|
||||
+ case MPATH_STRICT:
|
||||
+ return FIND_MULTIPATHS_STRICT;
|
||||
+ }
|
||||
+ fail_msg("invalid mode: %u", mode);
|
||||
+ return FIND_MULTIPATHS_UNDEF;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static unsigned int findmp_to_mode(int findmp)
|
||||
+{
|
||||
+ switch (findmp) {
|
||||
+ case FIND_MULTIPATHS_SMART:
|
||||
+ return MPATH_SMART;
|
||||
+ case FIND_MULTIPATHS_GREEDY:
|
||||
+ return MPATH_GREEDY;
|
||||
+ case FIND_MULTIPATHS_STRICT:
|
||||
+ case FIND_MULTIPATHS_OFF:
|
||||
+ case FIND_MULTIPATHS_ON:
|
||||
+ return MPATH_STRICT;
|
||||
+ }
|
||||
+ fail_msg("invalid find_multipaths value: %d", findmp);
|
||||
+ return MPATH_DEFAULT;
|
||||
+}
|
||||
+
|
||||
+int __wrap_is_path_valid(const char *name, struct config *conf, struct path *pp,
|
||||
+ bool check_multipathd)
|
||||
+{
|
||||
+ int r = mock_type(int);
|
||||
+ int findmp = mock_type(int);
|
||||
+
|
||||
+ assert_ptr_equal(name, test_dev);
|
||||
+ assert_ptr_not_equal(conf, NULL);
|
||||
+ assert_ptr_not_equal(pp, NULL);
|
||||
+ assert_true(check_multipathd);
|
||||
+
|
||||
+ assert_int_equal(findmp, conf->find_multipaths);
|
||||
+ if (r == MPATH_IS_ERROR || r == MPATH_IS_NOT_VALID)
|
||||
+ return r;
|
||||
+
|
||||
+ strlcpy(pp->wwid, mock_ptr_type(char *), WWID_SIZE);
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+int __wrap_libmultipath_init(void)
|
||||
+{
|
||||
+ int r = mock_type(int);
|
||||
+
|
||||
+ assert_false(initialized);
|
||||
+ if (r != 0)
|
||||
+ return r;
|
||||
+ initialized = true;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void __wrap_libmultipath_exit(void)
|
||||
+{
|
||||
+ assert_true(initialized);
|
||||
+ initialized = false;
|
||||
+}
|
||||
+
|
||||
+int __wrap_dm_prereq(unsigned int *v)
|
||||
+{
|
||||
+ assert_ptr_not_equal(v, NULL);
|
||||
+ return mock_type(int);
|
||||
+}
|
||||
+
|
||||
+int __real_init_config(const char *file);
|
||||
+
|
||||
+int __wrap_init_config(const char *file)
|
||||
+{
|
||||
+ int r = mock_type(int);
|
||||
+ struct config *conf;
|
||||
+
|
||||
+ assert_ptr_equal(file, DEFAULT_CONFIGFILE);
|
||||
+ if (r != 0)
|
||||
+ return r;
|
||||
+
|
||||
+ assert_string_not_equal(conf_name, CONF_TEMPLATE);
|
||||
+ r = __real_init_config(conf_name);
|
||||
+ conf = get_multipath_config();
|
||||
+ assert_ptr_not_equal(conf, NULL);
|
||||
+ assert_int_equal(conf->find_multipaths, mock_type(int));
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const char * const find_multipaths_optvals[] = {
|
||||
+ [FIND_MULTIPATHS_OFF] = "off",
|
||||
+ [FIND_MULTIPATHS_ON] = "on",
|
||||
+ [FIND_MULTIPATHS_STRICT] = "strict",
|
||||
+ [FIND_MULTIPATHS_GREEDY] = "greedy",
|
||||
+ [FIND_MULTIPATHS_SMART] = "smart",
|
||||
+};
|
||||
+
|
||||
+void make_config_file(int findmp)
|
||||
+{
|
||||
+ int r, fd;
|
||||
+ char buf[64];
|
||||
+
|
||||
+ assert_true(findmp > FIND_MULTIPATHS_UNDEF &&
|
||||
+ findmp < __FIND_MULTIPATHS_LAST);
|
||||
+
|
||||
+ r = snprintf(buf, sizeof(buf), "defaults {\nfind_multipaths %s\n}\n",
|
||||
+ find_multipaths_optvals[findmp]);
|
||||
+ assert_true(r > 0 && (long unsigned int)r < sizeof(buf));
|
||||
+
|
||||
+ memcpy(conf_name, CONF_TEMPLATE, sizeof(conf_name));
|
||||
+ fd = mkstemp(conf_name);
|
||||
+ assert_true(fd >= 0);
|
||||
+ assert_int_equal(safe_write(fd, buf, r), 0);
|
||||
+ assert_int_equal(close(fd), 0);
|
||||
+}
|
||||
+
|
||||
+int setup(void **state)
|
||||
+{
|
||||
+ initialized = false;
|
||||
+ udev = udev_new();
|
||||
+ if (udev == NULL)
|
||||
+ return -1;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int teardown(void **state)
|
||||
+{
|
||||
+ struct config *conf;
|
||||
+ conf = get_multipath_config();
|
||||
+ put_multipath_config(conf);
|
||||
+ if (conf)
|
||||
+ uninit_config();
|
||||
+ if (strcmp(conf_name, CONF_TEMPLATE) != 0)
|
||||
+ unlink(conf_name);
|
||||
+ udev_unref(udev);
|
||||
+ udev = NULL;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void check_config(bool valid_config)
|
||||
+{
|
||||
+ struct config *conf;
|
||||
+
|
||||
+ conf = get_multipath_config();
|
||||
+ put_multipath_config(conf);
|
||||
+ if (valid_config)
|
||||
+ assert_ptr_not_equal(conf, NULL);
|
||||
+}
|
||||
+
|
||||
+/* libmultipath_init fails */
|
||||
+static void test_mpathvalid_init_bad1(void **state)
|
||||
+{
|
||||
+ will_return(__wrap_libmultipath_init, 1);
|
||||
+ assert_int_equal(mpathvalid_init(MPATH_LOG_PRIO_DEBUG,
|
||||
+ MPATH_LOG_STDERR), -1);
|
||||
+ assert_false(initialized);
|
||||
+ check_config(false);
|
||||
+}
|
||||
+
|
||||
+/* init_config fails */
|
||||
+static void test_mpathvalid_init_bad2(void **state)
|
||||
+{
|
||||
+ will_return(__wrap_libmultipath_init, 0);
|
||||
+ will_return(__wrap_init_config, 1);
|
||||
+ assert_int_equal(mpathvalid_init(MPATH_LOG_PRIO_ERR,
|
||||
+ MPATH_LOG_STDERR_TIMESTAMP), -1);
|
||||
+ assert_false(initialized);
|
||||
+ check_config(false);
|
||||
+}
|
||||
+
|
||||
+/* dm_prereq fails */
|
||||
+static void test_mpathvalid_init_bad3(void **state)
|
||||
+{
|
||||
+ make_config_file(FIND_MULTIPATHS_STRICT);
|
||||
+ will_return(__wrap_libmultipath_init, 0);
|
||||
+ will_return(__wrap_init_config, 0);
|
||||
+ will_return(__wrap_init_config, FIND_MULTIPATHS_STRICT);
|
||||
+ will_return(__wrap_dm_prereq, 1);
|
||||
+ assert_int_equal(mpathvalid_init(MPATH_LOG_STDERR, MPATH_LOG_PRIO_ERR),
|
||||
+ -1);
|
||||
+ assert_false(initialized);
|
||||
+ check_config(false);
|
||||
+}
|
||||
+
|
||||
+static void check_mpathvalid_init(int findmp, int prio, int log_style)
|
||||
+{
|
||||
+ make_config_file(findmp);
|
||||
+ will_return(__wrap_libmultipath_init, 0);
|
||||
+ will_return(__wrap_init_config, 0);
|
||||
+ will_return(__wrap_init_config, findmp);
|
||||
+ will_return(__wrap_dm_prereq, 0);
|
||||
+ assert_int_equal(mpathvalid_init(prio, log_style), 0);
|
||||
+ assert_true(initialized);
|
||||
+ check_config(true);
|
||||
+ assert_int_equal(logsink, log_style);
|
||||
+ assert_int_equal(libmp_verbosity, prio);
|
||||
+ assert_int_equal(findmp_to_mode(findmp), mpathvalid_get_mode());
|
||||
+}
|
||||
+
|
||||
+static void check_mpathvalid_exit(void)
|
||||
+{
|
||||
+ assert_int_equal(mpathvalid_exit(), 0);
|
||||
+ assert_false(initialized);
|
||||
+ check_config(false);
|
||||
+}
|
||||
+
|
||||
+static void test_mpathvalid_init_good1(void **state)
|
||||
+{
|
||||
+ check_mpathvalid_init(FIND_MULTIPATHS_OFF, MPATH_LOG_PRIO_ERR,
|
||||
+ MPATH_LOG_STDERR_TIMESTAMP);
|
||||
+}
|
||||
+
|
||||
+static void test_mpathvalid_init_good2(void **state)
|
||||
+{
|
||||
+ check_mpathvalid_init(FIND_MULTIPATHS_STRICT, MPATH_LOG_PRIO_DEBUG,
|
||||
+ MPATH_LOG_STDERR);
|
||||
+}
|
||||
+
|
||||
+static void test_mpathvalid_init_good3(void **state)
|
||||
+{
|
||||
+ check_mpathvalid_init(FIND_MULTIPATHS_ON, MPATH_LOG_PRIO_NOLOG,
|
||||
+ MPATH_LOG_SYSLOG);
|
||||
+}
|
||||
+
|
||||
+static void test_mpathvalid_exit(void **state)
|
||||
+{
|
||||
+ check_mpathvalid_init(FIND_MULTIPATHS_ON, MPATH_LOG_PRIO_ERR,
|
||||
+ MPATH_LOG_STDERR);
|
||||
+ check_mpathvalid_exit();
|
||||
+}
|
||||
+
|
||||
+/* fails if config hasn't been set */
|
||||
+static void test_mpathvalid_get_mode_bad(void **state)
|
||||
+{
|
||||
+#if 1
|
||||
+ assert_int_equal(mpathvalid_get_mode(), MPATH_MODE_ERROR);
|
||||
+#else
|
||||
+ assert_int_equal(mpathvalid_get_mode(), 1);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+/*fails if config hasn't been set */
|
||||
+static void test_mpathvalid_reload_config_bad1(void **state)
|
||||
+{
|
||||
+#if 1
|
||||
+ will_return(__wrap_init_config, 1);
|
||||
+#endif
|
||||
+ assert_int_equal(mpathvalid_reload_config(), -1);
|
||||
+ check_config(false);
|
||||
+}
|
||||
+
|
||||
+/* init_config fails */
|
||||
+static void test_mpathvalid_reload_config_bad2(void **state)
|
||||
+{
|
||||
+ check_mpathvalid_init(FIND_MULTIPATHS_ON, MPATH_LOG_PRIO_ERR,
|
||||
+ MPATH_LOG_STDERR);
|
||||
+ will_return(__wrap_init_config, 1);
|
||||
+ assert_int_equal(mpathvalid_reload_config(), -1);
|
||||
+ check_config(false);
|
||||
+ check_mpathvalid_exit();
|
||||
+}
|
||||
+
|
||||
+static void check_mpathvalid_reload_config(int findmp)
|
||||
+{
|
||||
+ assert_string_not_equal(conf_name, CONF_TEMPLATE);
|
||||
+ unlink(conf_name);
|
||||
+ make_config_file(findmp);
|
||||
+ will_return(__wrap_init_config, 0);
|
||||
+ will_return(__wrap_init_config, findmp);
|
||||
+ assert_int_equal(mpathvalid_reload_config(), 0);
|
||||
+ check_config(true);
|
||||
+ assert_int_equal(findmp_to_mode(findmp), mpathvalid_get_mode());
|
||||
+}
|
||||
+
|
||||
+static void test_mpathvalid_reload_config_good(void **state)
|
||||
+{
|
||||
+ check_mpathvalid_init(FIND_MULTIPATHS_OFF, MPATH_LOG_PRIO_ERR,
|
||||
+ MPATH_LOG_STDERR);
|
||||
+ check_mpathvalid_reload_config(FIND_MULTIPATHS_ON);
|
||||
+ check_mpathvalid_reload_config(FIND_MULTIPATHS_GREEDY);
|
||||
+ check_mpathvalid_reload_config(FIND_MULTIPATHS_SMART);
|
||||
+ check_mpathvalid_reload_config(FIND_MULTIPATHS_STRICT);
|
||||
+ check_mpathvalid_exit();
|
||||
+}
|
||||
+
|
||||
+/* NULL name */
|
||||
+static void test_mpathvalid_is_path_bad1(void **state)
|
||||
+{
|
||||
+ assert_int_equal(mpathvalid_is_path(NULL, MPATH_STRICT, NULL, NULL, 0),
|
||||
+ MPATH_IS_ERROR);
|
||||
+}
|
||||
+
|
||||
+/* bad mode */
|
||||
+static void test_mpathvalid_is_path_bad2(void **state)
|
||||
+{
|
||||
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_MODE_ERROR, NULL,
|
||||
+ NULL, 0), MPATH_IS_ERROR);
|
||||
+}
|
||||
+
|
||||
+/* NULL path_wwids and non-zero nr_paths */
|
||||
+static void test_mpathvalid_is_path_bad3(void **state)
|
||||
+{
|
||||
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_MODE_ERROR, NULL,
|
||||
+ NULL, 1), MPATH_IS_ERROR);
|
||||
+}
|
||||
+
|
||||
+/*fails if config hasn't been set */
|
||||
+static void test_mpathvalid_is_path_bad4(void **state)
|
||||
+{
|
||||
+#if 0
|
||||
+ will_return(__wrap_is_path_valid, MPATH_IS_ERROR);
|
||||
+ will_return(__wrap_is_path_valid, FIND_MULTIPATHS_STRICT);
|
||||
+#endif
|
||||
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_STRICT, NULL,
|
||||
+ NULL, 0), MPATH_IS_ERROR);
|
||||
+}
|
||||
+
|
||||
+/* is_path_valid fails */
|
||||
+static void test_mpathvalid_is_path_bad5(void **state)
|
||||
+{
|
||||
+ check_mpathvalid_init(FIND_MULTIPATHS_OFF, MPATH_LOG_PRIO_ERR,
|
||||
+ MPATH_LOG_STDERR);
|
||||
+ will_return(__wrap_is_path_valid, MPATH_IS_ERROR);
|
||||
+ will_return(__wrap_is_path_valid, FIND_MULTIPATHS_GREEDY);
|
||||
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_GREEDY, NULL,
|
||||
+ NULL, 0), MPATH_IS_ERROR);
|
||||
+ check_mpathvalid_exit();
|
||||
+}
|
||||
+
|
||||
+static void test_mpathvalid_is_path_good1(void **state)
|
||||
+{
|
||||
+ char *wwid;
|
||||
+ check_mpathvalid_init(FIND_MULTIPATHS_STRICT, MPATH_LOG_PRIO_ERR,
|
||||
+ MPATH_LOG_STDERR);
|
||||
+ will_return(__wrap_is_path_valid, MPATH_IS_NOT_VALID);
|
||||
+ will_return(__wrap_is_path_valid, FIND_MULTIPATHS_STRICT);
|
||||
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_DEFAULT, &wwid,
|
||||
+ NULL, 0), MPATH_IS_NOT_VALID);
|
||||
+ assert_ptr_equal(wwid, NULL);
|
||||
+ check_mpathvalid_exit();
|
||||
+}
|
||||
+
|
||||
+static void test_mpathvalid_is_path_good2(void **state)
|
||||
+{
|
||||
+ const char *wwids[] = { "WWID_A", "WWID_B", "WWID_C", "WWID_D" };
|
||||
+ char *wwid;
|
||||
+ check_mpathvalid_init(FIND_MULTIPATHS_ON, MPATH_LOG_PRIO_ERR,
|
||||
+ MPATH_LOG_STDERR);
|
||||
+ will_return(__wrap_is_path_valid, MPATH_IS_VALID);
|
||||
+ will_return(__wrap_is_path_valid, FIND_MULTIPATHS_ON);
|
||||
+ will_return(__wrap_is_path_valid, TEST_WWID);
|
||||
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_DEFAULT, &wwid,
|
||||
+ wwids, 4), MPATH_IS_VALID);
|
||||
+ assert_string_equal(wwid, TEST_WWID);
|
||||
+}
|
||||
+
|
||||
+static void test_mpathvalid_is_path_good3(void **state)
|
||||
+{
|
||||
+ const char *wwids[] = { "WWID_A", "WWID_B", "WWID_C", "WWID_D" };
|
||||
+ char *wwid;
|
||||
+ check_mpathvalid_init(FIND_MULTIPATHS_OFF, MPATH_LOG_PRIO_ERR,
|
||||
+ MPATH_LOG_STDERR);
|
||||
+ will_return(__wrap_is_path_valid, MPATH_IS_VALID);
|
||||
+ will_return(__wrap_is_path_valid, FIND_MULTIPATHS_SMART);
|
||||
+ will_return(__wrap_is_path_valid, TEST_WWID);
|
||||
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_SMART, &wwid,
|
||||
+ wwids, 4), MPATH_IS_VALID);
|
||||
+ assert_string_equal(wwid, TEST_WWID);
|
||||
+}
|
||||
+
|
||||
+/* mabybe valid with no matching paths */
|
||||
+static void test_mpathvalid_is_path_good4(void **state)
|
||||
+{
|
||||
+ const char *wwids[] = { "WWID_A", "WWID_B", "WWID_C", "WWID_D" };
|
||||
+ char *wwid;
|
||||
+ check_mpathvalid_init(FIND_MULTIPATHS_SMART, MPATH_LOG_PRIO_ERR,
|
||||
+ MPATH_LOG_STDERR);
|
||||
+ will_return(__wrap_is_path_valid, MPATH_IS_MAYBE_VALID);
|
||||
+ will_return(__wrap_is_path_valid, FIND_MULTIPATHS_SMART);
|
||||
+ will_return(__wrap_is_path_valid, TEST_WWID);
|
||||
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_DEFAULT, &wwid,
|
||||
+ wwids, 4), MPATH_IS_MAYBE_VALID);
|
||||
+ assert_string_equal(wwid, TEST_WWID);
|
||||
+}
|
||||
+
|
||||
+/* maybe valid with matching paths */
|
||||
+static void test_mpathvalid_is_path_good5(void **state)
|
||||
+{
|
||||
+ const char *wwids[] = { "WWID_A", "WWID_B", TEST_WWID, "WWID_D" };
|
||||
+ char *wwid;
|
||||
+ check_mpathvalid_init(FIND_MULTIPATHS_SMART, MPATH_LOG_PRIO_ERR,
|
||||
+ MPATH_LOG_STDERR);
|
||||
+ will_return(__wrap_is_path_valid, MPATH_IS_MAYBE_VALID);
|
||||
+ will_return(__wrap_is_path_valid, FIND_MULTIPATHS_SMART);
|
||||
+ will_return(__wrap_is_path_valid, TEST_WWID);
|
||||
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_DEFAULT, &wwid,
|
||||
+ wwids, 4), MPATH_IS_VALID);
|
||||
+ assert_string_equal(wwid, TEST_WWID);
|
||||
+}
|
||||
+
|
||||
+#define setup_test(name) \
|
||||
+ cmocka_unit_test_setup_teardown(name, setup, teardown)
|
||||
+
|
||||
+int test_mpathvalid(void)
|
||||
+{
|
||||
+ const struct CMUnitTest tests[] = {
|
||||
+ setup_test(test_mpathvalid_init_bad1),
|
||||
+ setup_test(test_mpathvalid_init_bad2),
|
||||
+ setup_test(test_mpathvalid_init_bad3),
|
||||
+ setup_test(test_mpathvalid_init_good1),
|
||||
+ setup_test(test_mpathvalid_init_good2),
|
||||
+ setup_test(test_mpathvalid_init_good3),
|
||||
+ setup_test(test_mpathvalid_exit),
|
||||
+ setup_test(test_mpathvalid_get_mode_bad),
|
||||
+ setup_test(test_mpathvalid_reload_config_bad1),
|
||||
+ setup_test(test_mpathvalid_reload_config_bad2),
|
||||
+ setup_test(test_mpathvalid_reload_config_good),
|
||||
+ setup_test(test_mpathvalid_is_path_bad1),
|
||||
+ setup_test(test_mpathvalid_is_path_bad2),
|
||||
+ setup_test(test_mpathvalid_is_path_bad3),
|
||||
+ setup_test(test_mpathvalid_is_path_bad4),
|
||||
+ setup_test(test_mpathvalid_is_path_bad5),
|
||||
+ setup_test(test_mpathvalid_is_path_good1),
|
||||
+ setup_test(test_mpathvalid_is_path_good2),
|
||||
+ setup_test(test_mpathvalid_is_path_good3),
|
||||
+ setup_test(test_mpathvalid_is_path_good4),
|
||||
+ setup_test(test_mpathvalid_is_path_good5),
|
||||
+ };
|
||||
+ return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
+}
|
||||
+
|
||||
+int main(void)
|
||||
+{
|
||||
+ int r = 0;
|
||||
+
|
||||
+ r += test_mpathvalid();
|
||||
+ return r;
|
||||
+}
|
@ -1,87 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Wed, 21 Oct 2020 16:39:25 -0500
|
||||
Subject: [PATCH] libmultipath: add uid failback for dasd devices
|
||||
|
||||
Add failback code to get the uid for dasd devices from sysfs. Copied
|
||||
from dasdinfo
|
||||
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/defaults.h | 1 +
|
||||
libmultipath/discovery.c | 37 ++++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 37 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
|
||||
index 39a5e415..947ba467 100644
|
||||
--- a/libmultipath/defaults.h
|
||||
+++ b/libmultipath/defaults.h
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
#define DEFAULT_UID_ATTRIBUTE "ID_SERIAL"
|
||||
#define DEFAULT_NVME_UID_ATTRIBUTE "ID_WWN"
|
||||
+#define DEFAULT_DASD_UID_ATTRIBUTE "ID_UID"
|
||||
#define DEFAULT_UDEVDIR "/dev"
|
||||
#define DEFAULT_MULTIPATHDIR "/" LIB_STRING "/multipath"
|
||||
#define DEFAULT_SELECTOR "service-time 0"
|
||||
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||
index e7084664..877e8f2b 100644
|
||||
--- a/libmultipath/discovery.c
|
||||
+++ b/libmultipath/discovery.c
|
||||
@@ -1959,12 +1959,44 @@ get_vpd_uid(struct path * pp)
|
||||
return get_vpd_sysfs(parent, 0x83, pp->wwid, WWID_SIZE);
|
||||
}
|
||||
|
||||
+/* based on code from s390-tools/dasdinfo/dasdinfo.c */
|
||||
+static ssize_t dasd_get_uid(struct path *pp)
|
||||
+{
|
||||
+ struct udev_device *parent;
|
||||
+ char value[80];
|
||||
+ char *p;
|
||||
+ int i;
|
||||
+
|
||||
+ parent = udev_device_get_parent_with_subsystem_devtype(pp->udev, "ccw",
|
||||
+ NULL);
|
||||
+ if (!parent)
|
||||
+ return -1;
|
||||
+
|
||||
+ if (sysfs_attr_get_value(parent, "uid", value, 80) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ p = value - 1;
|
||||
+ /* look for the 4th '.' and cut there */
|
||||
+ for (i = 0; i < 4; i++) {
|
||||
+ p = index(p + 1, '.');
|
||||
+ if (!p)
|
||||
+ break;
|
||||
+ }
|
||||
+ if (p)
|
||||
+ *p = '\0';
|
||||
+
|
||||
+ return strlcpy(pp->wwid, value, WWID_SIZE);
|
||||
+}
|
||||
+
|
||||
static ssize_t uid_fallback(struct path *pp, int path_state,
|
||||
const char **origin)
|
||||
{
|
||||
ssize_t len = -1;
|
||||
|
||||
- if (pp->bus == SYSFS_BUS_SCSI) {
|
||||
+ if (pp->bus == SYSFS_BUS_CCW) {
|
||||
+ len = dasd_get_uid(pp);
|
||||
+ *origin = "sysfs";
|
||||
+ } else if (pp->bus == SYSFS_BUS_SCSI) {
|
||||
len = get_vpd_uid(pp);
|
||||
*origin = "sysfs";
|
||||
if (len < 0 && path_state == PATH_UP) {
|
||||
@@ -2012,6 +2044,9 @@ static bool has_uid_fallback(struct path *pp)
|
||||
!strcmp(pp->uid_attribute, ""))) ||
|
||||
(pp->bus == SYSFS_BUS_NVME &&
|
||||
(!strcmp(pp->uid_attribute, DEFAULT_NVME_UID_ATTRIBUTE) ||
|
||||
+ !strcmp(pp->uid_attribute, ""))) ||
|
||||
+ (pp->bus == SYSFS_BUS_CCW &&
|
||||
+ (!strcmp(pp->uid_attribute, DEFAULT_DASD_UID_ATTRIBUTE) ||
|
||||
!strcmp(pp->uid_attribute, ""))));
|
||||
}
|
||||
|
@ -1,42 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Wed, 21 Oct 2020 16:39:26 -0500
|
||||
Subject: [PATCH] libmultipath: change log level for null uid_attribute
|
||||
|
||||
If uid_attribute is explicitly set to an empty string, multipath should
|
||||
log the uid at the default log level, since using the fallback code is
|
||||
the expected behavior.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmultipath/discovery.c | 8 ++++++--
|
||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||
index 877e8f2b..c74f13bf 100644
|
||||
--- a/libmultipath/discovery.c
|
||||
+++ b/libmultipath/discovery.c
|
||||
@@ -2086,8 +2086,11 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev,
|
||||
len = strlen(pp->wwid);
|
||||
origin = "callout";
|
||||
} else {
|
||||
- bool udev_available = udev && pp->uid_attribute
|
||||
+ bool valid_uid_attr = pp->uid_attribute
|
||||
&& *pp->uid_attribute;
|
||||
+ bool empty_uid_attr = pp->uid_attribute
|
||||
+ && !*pp->uid_attribute;
|
||||
+ bool udev_available = udev && valid_uid_attr;
|
||||
|
||||
if (udev_available) {
|
||||
len = get_udev_uid(pp, pp->uid_attribute, udev);
|
||||
@@ -2097,7 +2100,8 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev,
|
||||
}
|
||||
if ((!udev_available || (len <= 0 && allow_fallback))
|
||||
&& has_uid_fallback(pp)) {
|
||||
- used_fallback = 1;
|
||||
+ if (!udev || !empty_uid_attr)
|
||||
+ used_fallback = 1;
|
||||
len = uid_fallback(pp, path_state, &origin);
|
||||
}
|
||||
}
|
@ -1,157 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Thu, 17 Dec 2020 16:50:59 -0600
|
||||
Subject: [PATCH] libmultipath: move fast_io_fail defines to structs.h
|
||||
|
||||
Since fast_io_fail is part of the multipath struct, its symbolic values
|
||||
belong in structs.h. Also, make it an instance of a general enum, which
|
||||
will be used again in future patches, and change the set/print functions
|
||||
which use it to use the general enum instead.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmultipath/config.h | 8 --------
|
||||
libmultipath/dict.c | 30 +++++++++++++++---------------
|
||||
libmultipath/dict.h | 2 +-
|
||||
libmultipath/propsel.c | 2 +-
|
||||
libmultipath/structs.h | 17 +++++++++++++++++
|
||||
5 files changed, 34 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||
index 5d460359..661dd586 100644
|
||||
--- a/libmultipath/config.h
|
||||
+++ b/libmultipath/config.h
|
||||
@@ -10,14 +10,6 @@
|
||||
#define ORIGIN_DEFAULT 0
|
||||
#define ORIGIN_CONFIG 1
|
||||
|
||||
-/*
|
||||
- * In kernel, fast_io_fail == 0 means immediate failure on rport delete.
|
||||
- * OTOH '0' means not-configured in various places in multipath-tools.
|
||||
- */
|
||||
-#define MP_FAST_IO_FAIL_UNSET (0)
|
||||
-#define MP_FAST_IO_FAIL_OFF (-1)
|
||||
-#define MP_FAST_IO_FAIL_ZERO (-2)
|
||||
-
|
||||
enum devtypes {
|
||||
DEV_NONE,
|
||||
DEV_DEVT,
|
||||
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||
index f12c2e5c..f4357da1 100644
|
||||
--- a/libmultipath/dict.c
|
||||
+++ b/libmultipath/dict.c
|
||||
@@ -822,7 +822,7 @@ declare_mp_attr_handler(gid, set_gid)
|
||||
declare_mp_attr_snprint(gid, print_gid)
|
||||
|
||||
static int
|
||||
-set_fast_io_fail(vector strvec, void *ptr)
|
||||
+set_undef_off_zero(vector strvec, void *ptr)
|
||||
{
|
||||
char * buff;
|
||||
int *int_ptr = (int *)ptr;
|
||||
@@ -832,36 +832,36 @@ set_fast_io_fail(vector strvec, void *ptr)
|
||||
return 1;
|
||||
|
||||
if (strcmp(buff, "off") == 0)
|
||||
- *int_ptr = MP_FAST_IO_FAIL_OFF;
|
||||
+ *int_ptr = UOZ_OFF;
|
||||
else if (sscanf(buff, "%d", int_ptr) != 1 ||
|
||||
- *int_ptr < MP_FAST_IO_FAIL_ZERO)
|
||||
- *int_ptr = MP_FAST_IO_FAIL_UNSET;
|
||||
+ *int_ptr < UOZ_ZERO)
|
||||
+ *int_ptr = UOZ_UNDEF;
|
||||
else if (*int_ptr == 0)
|
||||
- *int_ptr = MP_FAST_IO_FAIL_ZERO;
|
||||
+ *int_ptr = UOZ_ZERO;
|
||||
|
||||
FREE(buff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
-print_fast_io_fail(char * buff, int len, long v)
|
||||
+print_undef_off_zero(char * buff, int len, long v)
|
||||
{
|
||||
- if (v == MP_FAST_IO_FAIL_UNSET)
|
||||
+ if (v == UOZ_UNDEF)
|
||||
return 0;
|
||||
- if (v == MP_FAST_IO_FAIL_OFF)
|
||||
+ if (v == UOZ_OFF)
|
||||
return snprintf(buff, len, "\"off\"");
|
||||
- if (v == MP_FAST_IO_FAIL_ZERO)
|
||||
+ if (v == UOZ_ZERO)
|
||||
return snprintf(buff, len, "0");
|
||||
return snprintf(buff, len, "%ld", v);
|
||||
}
|
||||
|
||||
-declare_def_handler(fast_io_fail, set_fast_io_fail)
|
||||
-declare_def_snprint_defint(fast_io_fail, print_fast_io_fail,
|
||||
+declare_def_handler(fast_io_fail, set_undef_off_zero)
|
||||
+declare_def_snprint_defint(fast_io_fail, print_undef_off_zero,
|
||||
DEFAULT_FAST_IO_FAIL)
|
||||
-declare_ovr_handler(fast_io_fail, set_fast_io_fail)
|
||||
-declare_ovr_snprint(fast_io_fail, print_fast_io_fail)
|
||||
-declare_hw_handler(fast_io_fail, set_fast_io_fail)
|
||||
-declare_hw_snprint(fast_io_fail, print_fast_io_fail)
|
||||
+declare_ovr_handler(fast_io_fail, set_undef_off_zero)
|
||||
+declare_ovr_snprint(fast_io_fail, print_undef_off_zero)
|
||||
+declare_hw_handler(fast_io_fail, set_undef_off_zero)
|
||||
+declare_hw_snprint(fast_io_fail, print_undef_off_zero)
|
||||
|
||||
static int
|
||||
set_dev_loss(vector strvec, void *ptr)
|
||||
diff --git a/libmultipath/dict.h b/libmultipath/dict.h
|
||||
index a40ac66f..a917e1ca 100644
|
||||
--- a/libmultipath/dict.h
|
||||
+++ b/libmultipath/dict.h
|
||||
@@ -13,7 +13,7 @@ int print_rr_weight(char *buff, int len, long v);
|
||||
int print_pgfailback(char *buff, int len, long v);
|
||||
int print_pgpolicy(char *buff, int len, long v);
|
||||
int print_no_path_retry(char *buff, int len, long v);
|
||||
-int print_fast_io_fail(char *buff, int len, long v);
|
||||
+int print_undef_off_zero(char *buff, int len, long v);
|
||||
int print_dev_loss(char *buff, int len, unsigned long v);
|
||||
int print_reservation_key(char * buff, int len, struct be64 key, uint8_t
|
||||
flags, int source);
|
||||
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
||||
index 3f2c2cfa..67d025cf 100644
|
||||
--- a/libmultipath/propsel.c
|
||||
+++ b/libmultipath/propsel.c
|
||||
@@ -754,7 +754,7 @@ int select_fast_io_fail(struct config *conf, struct multipath *mp)
|
||||
mp_set_conf(fast_io_fail);
|
||||
mp_set_default(fast_io_fail, DEFAULT_FAST_IO_FAIL);
|
||||
out:
|
||||
- print_fast_io_fail(buff, 12, mp->fast_io_fail);
|
||||
+ print_undef_off_zero(buff, 12, mp->fast_io_fail);
|
||||
condlog(3, "%s: fast_io_fail_tmo = %s %s", mp->alias, buff, origin);
|
||||
return 0;
|
||||
}
|
||||
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
||||
index 4ce30551..cfa7b649 100644
|
||||
--- a/libmultipath/structs.h
|
||||
+++ b/libmultipath/structs.h
|
||||
@@ -219,6 +219,23 @@ enum vpd_vendor_ids {
|
||||
VPD_VP_ARRAY_SIZE, /* This must remain the last entry */
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * Multipath treats 0 as undefined for optional config parameters.
|
||||
+ * Use this for cases where 0 is a valid option for systems multipath
|
||||
+ * is communicating with
|
||||
+ */
|
||||
+enum undefined_off_zero {
|
||||
+ UOZ_UNDEF = 0,
|
||||
+ UOZ_OFF = -1,
|
||||
+ UOZ_ZERO = -2,
|
||||
+};
|
||||
+
|
||||
+enum fast_io_fail_states {
|
||||
+ MP_FAST_IO_FAIL_UNSET = UOZ_UNDEF,
|
||||
+ MP_FAST_IO_FAIL_OFF = UOZ_OFF,
|
||||
+ MP_FAST_IO_FAIL_ZERO = UOZ_ZERO,
|
||||
+};
|
||||
+
|
||||
struct vpd_vendor_page {
|
||||
int pg;
|
||||
const char *name;
|
@ -1,335 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Thu, 17 Dec 2020 16:51:00 -0600
|
||||
Subject: [PATCH] libmultipath: add eh_deadline multipath.conf parameter
|
||||
|
||||
There are times a fc rport is never lost, meaning that fast_io_fail_tmo
|
||||
and dev_loss_tmo never trigger, but scsi commands still hang. This can
|
||||
cause problems in cases where users have strict timing requirements, and
|
||||
the easiest way to solve these issues is to set eh_deadline. Since it's
|
||||
already possible to set fast_io_fail_tmo and dev_loss_tmo from
|
||||
multipath.conf, and have multipath take care of setting it correctly for
|
||||
the scsi devices in sysfs, it makes sense to allow users to set
|
||||
eh_deadline here as well.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmultipath/config.c | 2 ++
|
||||
libmultipath/config.h | 2 ++
|
||||
libmultipath/configure.c | 1 +
|
||||
libmultipath/dict.c | 10 +++++++
|
||||
libmultipath/discovery.c | 60 +++++++++++++++++++++++++++++++++-----
|
||||
libmultipath/propsel.c | 17 +++++++++++
|
||||
libmultipath/propsel.h | 1 +
|
||||
libmultipath/structs.h | 7 +++++
|
||||
multipath/multipath.conf.5 | 16 ++++++++++
|
||||
9 files changed, 109 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||
index 49e7fb81..9f3cb38d 100644
|
||||
--- a/libmultipath/config.c
|
||||
+++ b/libmultipath/config.c
|
||||
@@ -424,6 +424,7 @@ merge_hwe (struct hwentry * dst, struct hwentry * src)
|
||||
merge_num(flush_on_last_del);
|
||||
merge_num(fast_io_fail);
|
||||
merge_num(dev_loss);
|
||||
+ merge_num(eh_deadline);
|
||||
merge_num(user_friendly_names);
|
||||
merge_num(retain_hwhandler);
|
||||
merge_num(detect_prio);
|
||||
@@ -579,6 +580,7 @@ store_hwe (vector hwtable, struct hwentry * dhwe)
|
||||
hwe->flush_on_last_del = dhwe->flush_on_last_del;
|
||||
hwe->fast_io_fail = dhwe->fast_io_fail;
|
||||
hwe->dev_loss = dhwe->dev_loss;
|
||||
+ hwe->eh_deadline = dhwe->eh_deadline;
|
||||
hwe->user_friendly_names = dhwe->user_friendly_names;
|
||||
hwe->retain_hwhandler = dhwe->retain_hwhandler;
|
||||
hwe->detect_prio = dhwe->detect_prio;
|
||||
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||
index 661dd586..9ce37f16 100644
|
||||
--- a/libmultipath/config.h
|
||||
+++ b/libmultipath/config.h
|
||||
@@ -63,6 +63,7 @@ struct hwentry {
|
||||
int flush_on_last_del;
|
||||
int fast_io_fail;
|
||||
unsigned int dev_loss;
|
||||
+ int eh_deadline;
|
||||
int user_friendly_names;
|
||||
int retain_hwhandler;
|
||||
int detect_prio;
|
||||
@@ -148,6 +149,7 @@ struct config {
|
||||
int attribute_flags;
|
||||
int fast_io_fail;
|
||||
unsigned int dev_loss;
|
||||
+ int eh_deadline;
|
||||
int log_checker_err;
|
||||
int allow_queueing;
|
||||
int allow_usb_devices;
|
||||
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
||||
index 20536e60..c076be72 100644
|
||||
--- a/libmultipath/configure.c
|
||||
+++ b/libmultipath/configure.c
|
||||
@@ -368,6 +368,7 @@ int setup_map(struct multipath *mpp, char *params, int params_size,
|
||||
select_gid(conf, mpp);
|
||||
select_fast_io_fail(conf, mpp);
|
||||
select_dev_loss(conf, mpp);
|
||||
+ select_eh_deadline(conf, mpp);
|
||||
select_reservation_key(conf, mpp);
|
||||
select_deferred_remove(conf, mpp);
|
||||
select_marginal_path_err_sample_time(conf, mpp);
|
||||
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||
index f4357da1..bab96146 100644
|
||||
--- a/libmultipath/dict.c
|
||||
+++ b/libmultipath/dict.c
|
||||
@@ -899,6 +899,13 @@ declare_ovr_snprint(dev_loss, print_dev_loss)
|
||||
declare_hw_handler(dev_loss, set_dev_loss)
|
||||
declare_hw_snprint(dev_loss, print_dev_loss)
|
||||
|
||||
+declare_def_handler(eh_deadline, set_undef_off_zero)
|
||||
+declare_def_snprint(eh_deadline, print_undef_off_zero)
|
||||
+declare_ovr_handler(eh_deadline, set_undef_off_zero)
|
||||
+declare_ovr_snprint(eh_deadline, print_undef_off_zero)
|
||||
+declare_hw_handler(eh_deadline, set_undef_off_zero)
|
||||
+declare_hw_snprint(eh_deadline, print_undef_off_zero)
|
||||
+
|
||||
static int
|
||||
set_pgpolicy(vector strvec, void *ptr)
|
||||
{
|
||||
@@ -1771,6 +1778,7 @@ init_keywords(vector keywords)
|
||||
install_keyword("gid", &def_gid_handler, &snprint_def_gid);
|
||||
install_keyword("fast_io_fail_tmo", &def_fast_io_fail_handler, &snprint_def_fast_io_fail);
|
||||
install_keyword("dev_loss_tmo", &def_dev_loss_handler, &snprint_def_dev_loss);
|
||||
+ install_keyword("eh_deadline", &def_eh_deadline_handler, &snprint_def_eh_deadline);
|
||||
install_keyword("bindings_file", &def_bindings_file_handler, &snprint_def_bindings_file);
|
||||
install_keyword("wwids_file", &def_wwids_file_handler, &snprint_def_wwids_file);
|
||||
install_keyword("prkeys_file", &def_prkeys_file_handler, &snprint_def_prkeys_file);
|
||||
@@ -1880,6 +1888,7 @@ init_keywords(vector keywords)
|
||||
install_keyword("flush_on_last_del", &hw_flush_on_last_del_handler, &snprint_hw_flush_on_last_del);
|
||||
install_keyword("fast_io_fail_tmo", &hw_fast_io_fail_handler, &snprint_hw_fast_io_fail);
|
||||
install_keyword("dev_loss_tmo", &hw_dev_loss_handler, &snprint_hw_dev_loss);
|
||||
+ install_keyword("eh_deadline", &hw_eh_deadline_handler, &snprint_hw_eh_deadline);
|
||||
install_keyword("user_friendly_names", &hw_user_friendly_names_handler, &snprint_hw_user_friendly_names);
|
||||
install_keyword("retain_attached_hw_handler", &hw_retain_hwhandler_handler, &snprint_hw_retain_hwhandler);
|
||||
install_keyword("detect_prio", &hw_detect_prio_handler, &snprint_hw_detect_prio);
|
||||
@@ -1920,6 +1929,7 @@ init_keywords(vector keywords)
|
||||
install_keyword("flush_on_last_del", &ovr_flush_on_last_del_handler, &snprint_ovr_flush_on_last_del);
|
||||
install_keyword("fast_io_fail_tmo", &ovr_fast_io_fail_handler, &snprint_ovr_fast_io_fail);
|
||||
install_keyword("dev_loss_tmo", &ovr_dev_loss_handler, &snprint_ovr_dev_loss);
|
||||
+ install_keyword("eh_deadline", &ovr_eh_deadline_handler, &snprint_ovr_eh_deadline);
|
||||
install_keyword("user_friendly_names", &ovr_user_friendly_names_handler, &snprint_ovr_user_friendly_names);
|
||||
install_keyword("retain_attached_hw_handler", &ovr_retain_hwhandler_handler, &snprint_ovr_retain_hwhandler);
|
||||
install_keyword("detect_prio", &ovr_detect_prio_handler, &snprint_ovr_detect_prio);
|
||||
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||
index c74f13bf..add7bb97 100644
|
||||
--- a/libmultipath/discovery.c
|
||||
+++ b/libmultipath/discovery.c
|
||||
@@ -587,6 +587,42 @@ sysfs_get_asymmetric_access_state(struct path *pp, char *buff, int buflen)
|
||||
return !!preferred;
|
||||
}
|
||||
|
||||
+static int
|
||||
+sysfs_set_eh_deadline(struct multipath *mpp, struct path *pp)
|
||||
+{
|
||||
+ struct udev_device *hostdev;
|
||||
+ char host_name[HOST_NAME_LEN], value[16];
|
||||
+ int ret, len;
|
||||
+
|
||||
+ if (mpp->eh_deadline == EH_DEADLINE_UNSET)
|
||||
+ return 0;
|
||||
+
|
||||
+ sprintf(host_name, "host%d", pp->sg_id.host_no);
|
||||
+ hostdev = udev_device_new_from_subsystem_sysname(udev,
|
||||
+ "scsi_host", host_name);
|
||||
+ if (!hostdev)
|
||||
+ return 1;
|
||||
+
|
||||
+ if (mpp->eh_deadline == EH_DEADLINE_OFF)
|
||||
+ len = sprintf(value, "off");
|
||||
+ else if (mpp->eh_deadline == EH_DEADLINE_ZERO)
|
||||
+ len = sprintf(value, "0");
|
||||
+ else
|
||||
+ len = sprintf(value, "%d", mpp->eh_deadline);
|
||||
+
|
||||
+ ret = sysfs_attr_set_value(hostdev, "eh_deadline",
|
||||
+ value, len + 1);
|
||||
+ /*
|
||||
+ * not all scsi drivers support setting eh_deadline, so failing
|
||||
+ * is totally reasonable
|
||||
+ */
|
||||
+ if (ret <= 0)
|
||||
+ condlog(3, "%s: failed to set eh_deadline to %s, error %d", udev_device_get_sysname(hostdev), value, -ret);
|
||||
+
|
||||
+ udev_device_unref(hostdev);
|
||||
+ return (ret <= 0);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
|
||||
{
|
||||
@@ -596,6 +632,10 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
|
||||
unsigned int tmo;
|
||||
int ret;
|
||||
|
||||
+ if (mpp->dev_loss == DEV_LOSS_TMO_UNSET &&
|
||||
+ mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)
|
||||
+ return;
|
||||
+
|
||||
sprintf(rport_id, "rport-%d:%d-%d",
|
||||
pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id);
|
||||
rport_dev = udev_device_new_from_subsystem_sysname(udev,
|
||||
@@ -703,6 +743,11 @@ sysfs_set_session_tmo(struct multipath *mpp, struct path *pp)
|
||||
char session_id[64];
|
||||
char value[11];
|
||||
|
||||
+ if (mpp->dev_loss != DEV_LOSS_TMO_UNSET)
|
||||
+ condlog(3, "%s: ignoring dev_loss_tmo on iSCSI", pp->dev);
|
||||
+ if (mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)
|
||||
+ return;
|
||||
+
|
||||
sprintf(session_id, "session%d", pp->sg_id.transport_id);
|
||||
session_dev = udev_device_new_from_subsystem_sysname(udev,
|
||||
"iscsi_session", session_id);
|
||||
@@ -714,9 +759,6 @@ sysfs_set_session_tmo(struct multipath *mpp, struct path *pp)
|
||||
condlog(4, "target%d:%d:%d -> %s", pp->sg_id.host_no,
|
||||
pp->sg_id.channel, pp->sg_id.scsi_id, session_id);
|
||||
|
||||
- if (mpp->dev_loss != DEV_LOSS_TMO_UNSET) {
|
||||
- condlog(3, "%s: ignoring dev_loss_tmo on iSCSI", pp->dev);
|
||||
- }
|
||||
if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
|
||||
if (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF) {
|
||||
condlog(3, "%s: can't switch off fast_io_fail_tmo "
|
||||
@@ -744,6 +786,8 @@ sysfs_set_nexus_loss_tmo(struct multipath *mpp, struct path *pp)
|
||||
char end_dev_id[64];
|
||||
char value[11];
|
||||
|
||||
+ if (mpp->dev_loss == DEV_LOSS_TMO_UNSET)
|
||||
+ return;
|
||||
sprintf(end_dev_id, "end_device-%d:%d",
|
||||
pp->sg_id.host_no, pp->sg_id.transport_id);
|
||||
sas_dev = udev_device_new_from_subsystem_sysname(udev,
|
||||
@@ -801,7 +845,8 @@ sysfs_set_scsi_tmo (struct multipath *mpp, unsigned int checkint)
|
||||
mpp->fast_io_fail = MP_FAST_IO_FAIL_OFF;
|
||||
}
|
||||
if (mpp->dev_loss == DEV_LOSS_TMO_UNSET &&
|
||||
- mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)
|
||||
+ mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET &&
|
||||
+ mpp->eh_deadline == EH_DEADLINE_UNSET)
|
||||
return 0;
|
||||
|
||||
vector_foreach_slot(mpp->paths, pp, i) {
|
||||
@@ -814,17 +859,18 @@ sysfs_set_scsi_tmo (struct multipath *mpp, unsigned int checkint)
|
||||
switch (pp->sg_id.proto_id) {
|
||||
case SCSI_PROTOCOL_FCP:
|
||||
sysfs_set_rport_tmo(mpp, pp);
|
||||
- continue;
|
||||
+ break;
|
||||
case SCSI_PROTOCOL_ISCSI:
|
||||
sysfs_set_session_tmo(mpp, pp);
|
||||
- continue;
|
||||
+ break;
|
||||
case SCSI_PROTOCOL_SAS:
|
||||
sysfs_set_nexus_loss_tmo(mpp, pp);
|
||||
- continue;
|
||||
+ break;
|
||||
default:
|
||||
if (!err_path)
|
||||
err_path = pp;
|
||||
}
|
||||
+ sysfs_set_eh_deadline(mpp, pp);
|
||||
}
|
||||
|
||||
if (err_path) {
|
||||
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
||||
index 67d025cf..fa4ac5d9 100644
|
||||
--- a/libmultipath/propsel.c
|
||||
+++ b/libmultipath/propsel.c
|
||||
@@ -775,6 +775,23 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int select_eh_deadline(struct config *conf, struct multipath *mp)
|
||||
+{
|
||||
+ const char *origin;
|
||||
+ char buff[12];
|
||||
+
|
||||
+ mp_set_ovr(eh_deadline);
|
||||
+ mp_set_hwe(eh_deadline);
|
||||
+ mp_set_conf(eh_deadline);
|
||||
+ mp->eh_deadline = EH_DEADLINE_UNSET;
|
||||
+ /* not changing sysfs in default cause, so don't print anything */
|
||||
+ return 0;
|
||||
+out:
|
||||
+ print_undef_off_zero(buff, 12, mp->eh_deadline);
|
||||
+ condlog(3, "%s: eh_deadline = %s %s", mp->alias, buff, origin);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int select_flush_on_last_del(struct config *conf, struct multipath *mp)
|
||||
{
|
||||
const char *origin;
|
||||
diff --git a/libmultipath/propsel.h b/libmultipath/propsel.h
|
||||
index 3d6edd8a..a68bacf0 100644
|
||||
--- a/libmultipath/propsel.h
|
||||
+++ b/libmultipath/propsel.h
|
||||
@@ -17,6 +17,7 @@ int select_uid(struct config *conf, struct multipath *mp);
|
||||
int select_gid(struct config *conf, struct multipath *mp);
|
||||
int select_fast_io_fail(struct config *conf, struct multipath *mp);
|
||||
int select_dev_loss(struct config *conf, struct multipath *mp);
|
||||
+int select_eh_deadline(struct config *conf, struct multipath *mp);
|
||||
int select_reservation_key(struct config *conf, struct multipath *mp);
|
||||
int select_retain_hwhandler (struct config *conf, struct multipath * mp);
|
||||
int select_detect_prio(struct config *conf, struct path * pp);
|
||||
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
||||
index cfa7b649..d6ff6762 100644
|
||||
--- a/libmultipath/structs.h
|
||||
+++ b/libmultipath/structs.h
|
||||
@@ -236,6 +236,12 @@ enum fast_io_fail_states {
|
||||
MP_FAST_IO_FAIL_ZERO = UOZ_ZERO,
|
||||
};
|
||||
|
||||
+enum eh_deadline_states {
|
||||
+ EH_DEADLINE_UNSET = UOZ_UNDEF,
|
||||
+ EH_DEADLINE_OFF = UOZ_OFF,
|
||||
+ EH_DEADLINE_ZERO = UOZ_ZERO,
|
||||
+};
|
||||
+
|
||||
struct vpd_vendor_page {
|
||||
int pg;
|
||||
const char *name;
|
||||
@@ -356,6 +362,7 @@ struct multipath {
|
||||
int ghost_delay;
|
||||
int ghost_delay_tick;
|
||||
unsigned int dev_loss;
|
||||
+ int eh_deadline;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
mode_t mode;
|
||||
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
||||
index 7242d39b..ea66a01e 100644
|
||||
--- a/multipath/multipath.conf.5
|
||||
+++ b/multipath/multipath.conf.5
|
||||
@@ -717,6 +717,22 @@ The default is: \fB600\fR
|
||||
.
|
||||
.
|
||||
.TP
|
||||
+.B eh_deadline
|
||||
+Specify the maximum number of seconds the SCSI layer will spend doing error
|
||||
+handling when scsi devices fail. After this timeout the scsi layer will perform
|
||||
+a full HBA reset. Setting this may be necessary in cases where the rport is
|
||||
+never lost, so \fIfast_io_fail_tmo\fR and \fIdev_loss_tmo\fR will never
|
||||
+trigger, but (frequently do to load) scsi commands still hang. \fBNote:\fR when
|
||||
+the scsi error handler performs the HBA reset, all target paths on that HBA
|
||||
+will be affected. eh_deadline should only be set in cases where all targets on
|
||||
+the affected HBAs are multipathed.
|
||||
+.RS
|
||||
+.TP
|
||||
+The default is: \fB<unset>\fR
|
||||
+.RE
|
||||
+.
|
||||
+.
|
||||
+.TP
|
||||
.B bindings_file
|
||||
The full pathname of the binding file to be used when the user_friendly_names
|
||||
option is set.
|
@ -1,34 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Thu, 17 Dec 2020 16:51:01 -0600
|
||||
Subject: [PATCH] multipathd: remove redundant vector_free() int configure
|
||||
|
||||
remove_maps(vecs) already calls vector_free(vecs->mpvec)
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
multipathd/main.c | 8 ++------
|
||||
1 file changed, 2 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index b6a5f5b7..2eab4854 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -2634,14 +2634,10 @@ configure (struct vectors * vecs)
|
||||
}
|
||||
|
||||
/*
|
||||
- * purge dm of old maps
|
||||
+ * purge dm of old maps and save new set of maps formed by
|
||||
+ * considering current path state
|
||||
*/
|
||||
remove_maps(vecs);
|
||||
-
|
||||
- /*
|
||||
- * save new set of maps formed by considering current path state
|
||||
- */
|
||||
- vector_free(vecs->mpvec);
|
||||
vecs->mpvec = mpvec;
|
||||
|
||||
/*
|
@ -1,63 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Thu, 17 Dec 2020 16:51:02 -0600
|
||||
Subject: [PATCH] libmultipath: factor out code to get vpd page data
|
||||
|
||||
A future patch will reuse the code to get the vpd page data, so factor
|
||||
it out from get_vpd_sgio().
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmultipath/discovery.c | 27 +++++++++++++++++++--------
|
||||
1 file changed, 19 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||
index add7bb97..f901e9ff 100644
|
||||
--- a/libmultipath/discovery.c
|
||||
+++ b/libmultipath/discovery.c
|
||||
@@ -1321,14 +1321,13 @@ get_vpd_sysfs (struct udev_device *parent, int pg, char * str, int maxlen)
|
||||
return len;
|
||||
}
|
||||
|
||||
-int
|
||||
-get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen)
|
||||
+static int
|
||||
+fetch_vpd_page(int fd, int pg, unsigned char *buff, int maxlen)
|
||||
{
|
||||
- int len, buff_len;
|
||||
- unsigned char buff[4096];
|
||||
+ int buff_len;
|
||||
|
||||
- memset(buff, 0x0, 4096);
|
||||
- if (sgio_get_vpd(buff, 4096, fd, pg) < 0) {
|
||||
+ memset(buff, 0x0, maxlen);
|
||||
+ if (sgio_get_vpd(buff, maxlen, fd, pg) < 0) {
|
||||
int lvl = pg == 0x80 || pg == 0x83 ? 3 : 4;
|
||||
|
||||
condlog(lvl, "failed to issue vpd inquiry for pg%02x",
|
||||
@@ -1342,10 +1341,22 @@ get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen)
|
||||
return -ENODATA;
|
||||
}
|
||||
buff_len = get_unaligned_be16(&buff[2]) + 4;
|
||||
- if (buff_len > 4096) {
|
||||
+ if (buff_len > maxlen) {
|
||||
condlog(3, "vpd pg%02x page truncated", pg);
|
||||
- buff_len = 4096;
|
||||
+ buff_len = maxlen;
|
||||
}
|
||||
+ return buff_len;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen)
|
||||
+{
|
||||
+ int len, buff_len;
|
||||
+ unsigned char buff[4096];
|
||||
+
|
||||
+ buff_len = fetch_vpd_page(fd, pg, buff, sizeof(buff));
|
||||
+ if (buff_len < 0)
|
||||
+ return buff_len;
|
||||
if (pg == 0x80)
|
||||
len = parse_vpd_pg80(buff, str, maxlen);
|
||||
else if (pg == 0x83)
|
@ -1,88 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Thu, 17 Dec 2020 16:51:03 -0600
|
||||
Subject: [PATCH] libmultipath: limit reading 0xc9 vpd page
|
||||
|
||||
Only rdac arrays support 0xC9 vpd page inquiries. All other arrays will
|
||||
return a failure. Only do the rdac inquiry when detecting array
|
||||
capabilities if the array's path checker is explicitly set to rdac, or
|
||||
the path checker is not set, and the array reports that it supports vpd
|
||||
page 0xC9 in the Supported VPD Pages (0x00) vpd page.
|
||||
|
||||
Multipath was doing the check if either the path checker was set to
|
||||
rdac, or no path checker was set. This means that for almost all
|
||||
non-rdac arrays, multipath was issuing a bad inquiry. This was annoying
|
||||
users.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmultipath/discovery.c | 17 +++++++++++++++++
|
||||
libmultipath/discovery.h | 1 +
|
||||
libmultipath/propsel.c | 10 ++++++----
|
||||
3 files changed, 24 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||
index f901e9ff..e818585a 100644
|
||||
--- a/libmultipath/discovery.c
|
||||
+++ b/libmultipath/discovery.c
|
||||
@@ -1348,6 +1348,23 @@ fetch_vpd_page(int fd, int pg, unsigned char *buff, int maxlen)
|
||||
return buff_len;
|
||||
}
|
||||
|
||||
+/* based on sg_inq.c from sg3_utils */
|
||||
+bool
|
||||
+is_vpd_page_supported(int fd, int pg)
|
||||
+{
|
||||
+ int i, len;
|
||||
+ unsigned char buff[4096];
|
||||
+
|
||||
+ len = fetch_vpd_page(fd, 0x00, buff, sizeof(buff));
|
||||
+ if (len < 0)
|
||||
+ return false;
|
||||
+
|
||||
+ for (i = 4; i < len; ++i)
|
||||
+ if (buff[i] == pg)
|
||||
+ return true;
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
int
|
||||
get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen)
|
||||
{
|
||||
diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h
|
||||
index 6444887d..d3193daf 100644
|
||||
--- a/libmultipath/discovery.h
|
||||
+++ b/libmultipath/discovery.h
|
||||
@@ -56,6 +56,7 @@ 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 allow_fallback);
|
||||
+bool is_vpd_page_supported(int fd, int pg);
|
||||
|
||||
/*
|
||||
* discovery bitmask
|
||||
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
||||
index fa4ac5d9..f771a830 100644
|
||||
--- a/libmultipath/propsel.c
|
||||
+++ b/libmultipath/propsel.c
|
||||
@@ -496,13 +496,15 @@ check_rdac(struct path * pp)
|
||||
{
|
||||
int len;
|
||||
char buff[44];
|
||||
- const char *checker_name;
|
||||
+ const char *checker_name = NULL;
|
||||
|
||||
if (pp->bus != SYSFS_BUS_SCSI)
|
||||
return 0;
|
||||
- /* Avoid ioctl if this is likely not an RDAC array */
|
||||
- if (__do_set_from_hwe(checker_name, pp, checker_name) &&
|
||||
- strcmp(checker_name, RDAC))
|
||||
+ /* Avoid checking 0xc9 if this is likely not an RDAC array */
|
||||
+ if (!__do_set_from_hwe(checker_name, pp, checker_name) &&
|
||||
+ !is_vpd_page_supported(pp->fd, 0xC9))
|
||||
+ return 0;
|
||||
+ if (checker_name && strcmp(checker_name, RDAC))
|
||||
return 0;
|
||||
len = get_vpd_sgio(pp->fd, 0xC9, 0, buff, 44);
|
||||
if (len <= 0)
|
@ -1,138 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Mon, 26 Oct 2020 22:01:18 +0100
|
||||
Subject: [PATCH] libmultipath: move logq_lock handling to log.c
|
||||
|
||||
logq_lock protects internal data structures of log.c, and should
|
||||
be handled there. This patch doesn't change functionality, except
|
||||
improving cancel-safety somewhat.
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/log.c | 34 ++++++++++++++++++++++++++++++++--
|
||||
libmultipath/log_pthread.c | 9 ---------
|
||||
2 files changed, 32 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/log.c b/libmultipath/log.c
|
||||
index debd36de..7f337879 100644
|
||||
--- a/libmultipath/log.c
|
||||
+++ b/libmultipath/log.c
|
||||
@@ -9,13 +9,16 @@
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
+#include <pthread.h>
|
||||
|
||||
#include "memory.h"
|
||||
#include "log.h"
|
||||
+#include "util.h"
|
||||
|
||||
#define ALIGN(len, s) (((len)+(s)-1)/(s)*(s))
|
||||
|
||||
struct logarea* la;
|
||||
+static pthread_mutex_t logq_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
#if LOGDBG
|
||||
static void dump_logarea (void)
|
||||
@@ -101,12 +104,17 @@ void log_close (void)
|
||||
|
||||
void log_reset (char *program_name)
|
||||
{
|
||||
+ pthread_mutex_lock(&logq_lock);
|
||||
+ pthread_cleanup_push(cleanup_mutex, &logq_lock);
|
||||
+
|
||||
closelog();
|
||||
tzset();
|
||||
openlog(program_name, 0, LOG_DAEMON);
|
||||
+
|
||||
+ pthread_cleanup_pop(1);
|
||||
}
|
||||
|
||||
-int log_enqueue (int prio, const char * fmt, va_list ap)
|
||||
+static int _log_enqueue(int prio, const char * fmt, va_list ap)
|
||||
{
|
||||
int len, fwd;
|
||||
char buff[MAX_MSG_SIZE];
|
||||
@@ -165,7 +173,18 @@ int log_enqueue (int prio, const char * fmt, va_list ap)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int log_dequeue (void * buff)
|
||||
+int log_enqueue(int prio, const char *fmt, va_list ap)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ pthread_mutex_lock(&logq_lock);
|
||||
+ pthread_cleanup_push(cleanup_mutex, &logq_lock);
|
||||
+ ret = _log_enqueue(prio, fmt, ap);
|
||||
+ pthread_cleanup_pop(1);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int _log_dequeue(void *buff)
|
||||
{
|
||||
struct logmsg * src = (struct logmsg *)la->head;
|
||||
struct logmsg * dst = (struct logmsg *)buff;
|
||||
@@ -194,6 +213,17 @@ int log_dequeue (void * buff)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int log_dequeue(void *buff)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ pthread_mutex_lock(&logq_lock);
|
||||
+ pthread_cleanup_push(cleanup_mutex, &logq_lock);
|
||||
+ ret = _log_dequeue(buff);
|
||||
+ pthread_cleanup_pop(1);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* this one can block under memory pressure
|
||||
*/
|
||||
diff --git a/libmultipath/log_pthread.c b/libmultipath/log_pthread.c
|
||||
index 0d48c52c..65992101 100644
|
||||
--- a/libmultipath/log_pthread.c
|
||||
+++ b/libmultipath/log_pthread.c
|
||||
@@ -18,7 +18,6 @@
|
||||
static pthread_t log_thr;
|
||||
|
||||
/* logev_lock must not be taken with logq_lock held */
|
||||
-static pthread_mutex_t logq_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t logev_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t logev_cond = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
@@ -41,10 +40,7 @@ void log_safe (int prio, const char * fmt, va_list ap)
|
||||
running = logq_running;
|
||||
|
||||
if (running) {
|
||||
- pthread_mutex_lock(&logq_lock);
|
||||
- pthread_cleanup_push(cleanup_mutex, &logq_lock);
|
||||
log_enqueue(prio, fmt, ap);
|
||||
- pthread_cleanup_pop(1);
|
||||
|
||||
log_messages_pending = 1;
|
||||
pthread_cond_signal(&logev_cond);
|
||||
@@ -60,9 +56,7 @@ static void flush_logqueue (void)
|
||||
int empty;
|
||||
|
||||
do {
|
||||
- pthread_mutex_lock(&logq_lock);
|
||||
empty = log_dequeue(la->buff);
|
||||
- pthread_mutex_unlock(&logq_lock);
|
||||
if (!empty)
|
||||
log_syslog(la->buff);
|
||||
} while (empty == 0);
|
||||
@@ -138,10 +132,7 @@ void log_thread_start (pthread_attr_t *attr)
|
||||
void log_thread_reset (void)
|
||||
{
|
||||
logdbg(stderr,"resetting log\n");
|
||||
-
|
||||
- pthread_mutex_lock(&logq_lock);
|
||||
log_reset("multipathd");
|
||||
- pthread_mutex_unlock(&logq_lock);
|
||||
}
|
||||
|
||||
void log_thread_stop (void)
|
@ -1,107 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Mon, 26 Oct 2020 22:13:40 +0100
|
||||
Subject: [PATCH] libmultipath: protect logarea with logq_lock
|
||||
|
||||
Make sure the global logarea (la) is only allocated and freed
|
||||
hile holding logq_lock. This avoids invalid memory access.
|
||||
|
||||
This patch makes free_logarea() static. libmultipath.version
|
||||
is unchanged, as free_logarea() wasn't exported anyway.
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/log.c | 32 +++++++++++++++++++++++---------
|
||||
libmultipath/log.h | 1 -
|
||||
2 files changed, 23 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/log.c b/libmultipath/log.c
|
||||
index 7f337879..95c8f01a 100644
|
||||
--- a/libmultipath/log.c
|
||||
+++ b/libmultipath/log.c
|
||||
@@ -77,16 +77,23 @@ static int logarea_init (int size)
|
||||
|
||||
int log_init(char *program_name, int size)
|
||||
{
|
||||
+ int ret = 1;
|
||||
+
|
||||
logdbg(stderr,"enter log_init\n");
|
||||
+
|
||||
+ pthread_mutex_lock(&logq_lock);
|
||||
+ pthread_cleanup_push(cleanup_mutex, &logq_lock);
|
||||
+
|
||||
openlog(program_name, 0, LOG_DAEMON);
|
||||
+ if (!la)
|
||||
+ ret = logarea_init(size);
|
||||
|
||||
- if (logarea_init(size))
|
||||
- return 1;
|
||||
+ pthread_cleanup_pop(1);
|
||||
|
||||
- return 0;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
-void free_logarea (void)
|
||||
+static void free_logarea (void)
|
||||
{
|
||||
FREE(la->start);
|
||||
FREE(la->buff);
|
||||
@@ -96,9 +103,14 @@ void free_logarea (void)
|
||||
|
||||
void log_close (void)
|
||||
{
|
||||
- free_logarea();
|
||||
+ pthread_mutex_lock(&logq_lock);
|
||||
+ pthread_cleanup_push(cleanup_mutex, &logq_lock);
|
||||
+
|
||||
+ if (la)
|
||||
+ free_logarea();
|
||||
closelog();
|
||||
|
||||
+ pthread_cleanup_pop(1);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -175,11 +187,12 @@ static int _log_enqueue(int prio, const char * fmt, va_list ap)
|
||||
|
||||
int log_enqueue(int prio, const char *fmt, va_list ap)
|
||||
{
|
||||
- int ret;
|
||||
+ int ret = 1;
|
||||
|
||||
pthread_mutex_lock(&logq_lock);
|
||||
pthread_cleanup_push(cleanup_mutex, &logq_lock);
|
||||
- ret = _log_enqueue(prio, fmt, ap);
|
||||
+ if (la)
|
||||
+ ret = _log_enqueue(prio, fmt, ap);
|
||||
pthread_cleanup_pop(1);
|
||||
return ret;
|
||||
}
|
||||
@@ -215,11 +228,12 @@ static int _log_dequeue(void *buff)
|
||||
|
||||
int log_dequeue(void *buff)
|
||||
{
|
||||
- int ret;
|
||||
+ int ret = 1;
|
||||
|
||||
pthread_mutex_lock(&logq_lock);
|
||||
pthread_cleanup_push(cleanup_mutex, &logq_lock);
|
||||
- ret = _log_dequeue(buff);
|
||||
+ if (la)
|
||||
+ ret = _log_dequeue(buff);
|
||||
pthread_cleanup_pop(1);
|
||||
return ret;
|
||||
}
|
||||
diff --git a/libmultipath/log.h b/libmultipath/log.h
|
||||
index d2448f6a..fa224e4d 100644
|
||||
--- a/libmultipath/log.h
|
||||
+++ b/libmultipath/log.h
|
||||
@@ -39,6 +39,5 @@ int log_enqueue (int prio, const char * fmt, va_list ap)
|
||||
int log_dequeue (void *);
|
||||
void log_syslog (void *);
|
||||
void dump_logmsg (void *);
|
||||
-void free_logarea (void);
|
||||
|
||||
#endif /* LOG_H */
|
@ -1,281 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Thu, 5 Nov 2020 12:43:25 +0100
|
||||
Subject: [PATCH] libmultipath: prevent DSO unloading with astray checker
|
||||
threads
|
||||
|
||||
The multipathd tur checker thread is designed to be able to finish at
|
||||
any time, even after the tur checker itself has been freed. The
|
||||
multipathd shutdown code makes sure all the checkers have been freed
|
||||
before freeing the checker_class and calling dlclose() to unload the
|
||||
DSO, but this doesn't guarantee that the checker threads have finished.
|
||||
If one hasn't, the DSO will get unloaded while the thread still running
|
||||
code from it, causing a segfault.
|
||||
|
||||
This patch fixes the issue by further incrementing the DSO's refcount
|
||||
for every running thread. To avoid race conditions leading to segfaults,
|
||||
the thread's entrypoint must be in libmultipath, not in the DSO itself.
|
||||
Therefore we add a new optional checker method, libcheck_thread().
|
||||
Checkers defining this method may create a detached thread with
|
||||
entrypoint checker_thread_entry(), which will call the DSO's
|
||||
libcheck_thread and take care of the refcount handling.
|
||||
|
||||
Reported-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/checkers.c | 68 +++++++++++++++++++++++++++----
|
||||
libmultipath/checkers.h | 25 ++++++++++++
|
||||
libmultipath/checkers/tur.c | 12 +++---
|
||||
libmultipath/libmultipath.version | 5 +++
|
||||
4 files changed, 97 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c
|
||||
index 18b1f5eb..2dd9915d 100644
|
||||
--- a/libmultipath/checkers.c
|
||||
+++ b/libmultipath/checkers.c
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <stddef.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/stat.h>
|
||||
+#include <urcu.h>
|
||||
+#include <urcu/uatomic.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "checkers.h"
|
||||
@@ -20,6 +22,7 @@ struct checker_class {
|
||||
int (*mp_init)(struct checker *); /* to allocate the mpcontext */
|
||||
void (*free)(struct checker *); /* to free the context */
|
||||
void (*reset)(void); /* to reset the global variables */
|
||||
+ void *(*thread)(void *); /* async thread entry point */
|
||||
const char **msgtable;
|
||||
short msgtable_size;
|
||||
};
|
||||
@@ -55,19 +58,32 @@ static struct checker_class *alloc_checker_class(void)
|
||||
c = MALLOC(sizeof(struct checker_class));
|
||||
if (c) {
|
||||
INIT_LIST_HEAD(&c->node);
|
||||
- c->refcount = 1;
|
||||
+ uatomic_set(&c->refcount, 1);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
+/* Use uatomic_{sub,add}_return() to ensure proper memory barriers */
|
||||
+static int checker_class_ref(struct checker_class *cls)
|
||||
+{
|
||||
+ return uatomic_add_return(&cls->refcount, 1);
|
||||
+}
|
||||
+
|
||||
+static int checker_class_unref(struct checker_class *cls)
|
||||
+{
|
||||
+ return uatomic_sub_return(&cls->refcount, 1);
|
||||
+}
|
||||
+
|
||||
void free_checker_class(struct checker_class *c)
|
||||
{
|
||||
+ int cnt;
|
||||
+
|
||||
if (!c)
|
||||
return;
|
||||
- c->refcount--;
|
||||
- if (c->refcount) {
|
||||
- condlog(4, "%s checker refcount %d",
|
||||
- c->name, c->refcount);
|
||||
+ cnt = checker_class_unref(c);
|
||||
+ if (cnt != 0) {
|
||||
+ condlog(cnt < 0 ? 1 : 4, "%s checker refcount %d",
|
||||
+ c->name, cnt);
|
||||
return;
|
||||
}
|
||||
condlog(3, "unloading %s checker", c->name);
|
||||
@@ -161,7 +177,8 @@ static struct checker_class *add_checker_class(const char *multipath_dir,
|
||||
|
||||
c->mp_init = (int (*)(struct checker *)) dlsym(c->handle, "libcheck_mp_init");
|
||||
c->reset = (void (*)(void)) dlsym(c->handle, "libcheck_reset");
|
||||
- /* These 2 functions can be NULL. call dlerror() to clear out any
|
||||
+ c->thread = (void *(*)(void*)) dlsym(c->handle, "libcheck_thread");
|
||||
+ /* These 3 functions can be NULL. call dlerror() to clear out any
|
||||
* error string */
|
||||
dlerror();
|
||||
|
||||
@@ -347,6 +364,43 @@ bad_id:
|
||||
return generic_msg[CHECKER_MSGID_NONE];
|
||||
}
|
||||
|
||||
+static void checker_cleanup_thread(void *arg)
|
||||
+{
|
||||
+ struct checker_class *cls = arg;
|
||||
+
|
||||
+ (void)checker_class_unref(cls);
|
||||
+ rcu_unregister_thread();
|
||||
+}
|
||||
+
|
||||
+static void *checker_thread_entry(void *arg)
|
||||
+{
|
||||
+ struct checker_context *ctx = arg;
|
||||
+ void *rv;
|
||||
+
|
||||
+ rcu_register_thread();
|
||||
+ pthread_cleanup_push(checker_cleanup_thread, ctx->cls);
|
||||
+ rv = ctx->cls->thread(ctx);
|
||||
+ pthread_cleanup_pop(1);
|
||||
+ return rv;
|
||||
+}
|
||||
+
|
||||
+int start_checker_thread(pthread_t *thread, const pthread_attr_t *attr,
|
||||
+ struct checker_context *ctx)
|
||||
+{
|
||||
+ int rv;
|
||||
+
|
||||
+ assert(ctx && ctx->cls && ctx->cls->thread);
|
||||
+ /* Take a ref here, lest the class be freed before the thread starts */
|
||||
+ (void)checker_class_ref(ctx->cls);
|
||||
+ rv = pthread_create(thread, attr, checker_thread_entry, ctx);
|
||||
+ if (rv != 0) {
|
||||
+ condlog(1, "failed to start checker thread for %s: %m",
|
||||
+ ctx->cls->name);
|
||||
+ checker_class_unref(ctx->cls);
|
||||
+ }
|
||||
+ return rv;
|
||||
+}
|
||||
+
|
||||
void checker_clear_message (struct checker *c)
|
||||
{
|
||||
if (!c)
|
||||
@@ -371,7 +425,7 @@ void checker_get(const char *multipath_dir, struct checker *dst,
|
||||
if (!src)
|
||||
return;
|
||||
|
||||
- src->refcount++;
|
||||
+ (void)checker_class_ref(dst->cls);
|
||||
}
|
||||
|
||||
int init_checkers(const char *multipath_dir)
|
||||
diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h
|
||||
index 9d5f90b9..2fd1d1c6 100644
|
||||
--- a/libmultipath/checkers.h
|
||||
+++ b/libmultipath/checkers.h
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef _CHECKERS_H
|
||||
#define _CHECKERS_H
|
||||
|
||||
+#include <pthread.h>
|
||||
#include "list.h"
|
||||
#include "memory.h"
|
||||
#include "defaults.h"
|
||||
@@ -148,6 +149,28 @@ void checker_set_async (struct checker *);
|
||||
void checker_set_fd (struct checker *, int);
|
||||
void checker_enable (struct checker *);
|
||||
void checker_disable (struct checker *);
|
||||
+/*
|
||||
+ * start_checker_thread(): start async path checker thread
|
||||
+ *
|
||||
+ * This function provides a wrapper around pthread_create().
|
||||
+ * The created thread will call the DSO's "libcheck_thread" function with the
|
||||
+ * checker context as argument.
|
||||
+ *
|
||||
+ * Rationale:
|
||||
+ * Path checkers that do I/O may hang forever. To avoid blocking, some
|
||||
+ * checkers therefore use asyncronous, detached threads for checking
|
||||
+ * the paths. These threads may continue hanging if multipathd is stopped.
|
||||
+ * In this case, we can't unload the checker DSO at exit. In order to
|
||||
+ * avoid race conditions and crashes, the entry point of the thread
|
||||
+ * needs to be in libmultipath, not in the DSO itself.
|
||||
+ *
|
||||
+ * @param arg: pointer to struct checker_context.
|
||||
+ */
|
||||
+struct checker_context {
|
||||
+ struct checker_class *cls;
|
||||
+};
|
||||
+int start_checker_thread (pthread_t *thread, const pthread_attr_t *attr,
|
||||
+ struct checker_context *ctx);
|
||||
int checker_check (struct checker *, int);
|
||||
int checker_is_sync(const struct checker *);
|
||||
const char *checker_name (const struct checker *);
|
||||
@@ -164,6 +187,8 @@ void checker_get(const char *, struct checker *, const char *);
|
||||
int libcheck_check(struct checker *);
|
||||
int libcheck_init(struct checker *);
|
||||
void libcheck_free(struct checker *);
|
||||
+void *libcheck_thread(struct checker_context *ctx);
|
||||
+
|
||||
/*
|
||||
* msgid => message map.
|
||||
*
|
||||
diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c
|
||||
index e886fcf8..a4b4a213 100644
|
||||
--- a/libmultipath/checkers/tur.c
|
||||
+++ b/libmultipath/checkers/tur.c
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
-#include <urcu.h>
|
||||
#include <urcu/uatomic.h>
|
||||
|
||||
#include "checkers.h"
|
||||
@@ -55,6 +54,7 @@ struct tur_checker_context {
|
||||
pthread_cond_t active;
|
||||
int holders; /* uatomic access only */
|
||||
int msgid;
|
||||
+ struct checker_context ctx;
|
||||
};
|
||||
|
||||
int libcheck_init (struct checker * c)
|
||||
@@ -74,6 +74,7 @@ int libcheck_init (struct checker * c)
|
||||
pthread_mutex_init(&ct->lock, NULL);
|
||||
if (fstat(c->fd, &sb) == 0)
|
||||
ct->devt = sb.st_rdev;
|
||||
+ ct->ctx.cls = c->cls;
|
||||
c->context = ct;
|
||||
|
||||
return 0;
|
||||
@@ -204,7 +205,6 @@ static void cleanup_func(void *data)
|
||||
holders = uatomic_sub_return(&ct->holders, 1);
|
||||
if (!holders)
|
||||
cleanup_context(ct);
|
||||
- rcu_unregister_thread();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -251,15 +251,15 @@ static void tur_deep_sleep(const struct tur_checker_context *ct)
|
||||
#define tur_deep_sleep(x) do {} while (0)
|
||||
#endif /* TUR_TEST_MAJOR */
|
||||
|
||||
-static void *tur_thread(void *ctx)
|
||||
+void *libcheck_thread(struct checker_context *ctx)
|
||||
{
|
||||
- struct tur_checker_context *ct = ctx;
|
||||
+ struct tur_checker_context *ct =
|
||||
+ container_of(ctx, struct tur_checker_context, ctx);
|
||||
int state, running;
|
||||
short msgid;
|
||||
|
||||
/* This thread can be canceled, so setup clean up */
|
||||
tur_thread_cleanup_push(ct);
|
||||
- rcu_register_thread();
|
||||
|
||||
condlog(4, "%d:%d : tur checker starting up", major(ct->devt),
|
||||
minor(ct->devt));
|
||||
@@ -394,7 +394,7 @@ int libcheck_check(struct checker * c)
|
||||
uatomic_set(&ct->running, 1);
|
||||
tur_set_async_timeout(c);
|
||||
setup_thread_attr(&attr, 32 * 1024, 1);
|
||||
- r = pthread_create(&ct->thread, &attr, tur_thread, ct);
|
||||
+ r = start_checker_thread(&ct->thread, &attr, &ct->ctx);
|
||||
pthread_attr_destroy(&attr);
|
||||
if (r) {
|
||||
uatomic_sub(&ct->holders, 1);
|
||||
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
|
||||
index 2e3583f5..751099dc 100644
|
||||
--- a/libmultipath/libmultipath.version
|
||||
+++ b/libmultipath/libmultipath.version
|
||||
@@ -270,3 +270,8 @@ global:
|
||||
dm_prereq;
|
||||
skip_libmp_dm_init;
|
||||
} LIBMULTIPATH_4.1.0;
|
||||
+
|
||||
+LIBMULTIPATH_4.3.0 {
|
||||
+global:
|
||||
+ start_checker_thread;
|
||||
+} LIBMULTIPATH_4.2.0;
|
@ -1,148 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Mon, 14 Dec 2020 18:22:55 +0100
|
||||
Subject: [PATCH] libmultipath: force map reload if udev incomplete
|
||||
|
||||
We've recently observed various cases of incompletely processed uevents
|
||||
during initrd processing. Typically, this would leave a dm device in
|
||||
the state it had after the initial "add" uevent, which is basically unusable,
|
||||
because udevd had been killed by systemd before processing the subsequent
|
||||
"change" event. After switching root, the coldplug event would re-read
|
||||
the db file, which would be in unusable state, and would not do anything.
|
||||
In such cases, a RELOAD action with force_udev_reload=1 is in order to
|
||||
make udev re-process the device completely (DM_UDEV_PRIMARY_SOURCE_FLAG=1 and
|
||||
DM_SUBSYSTEM_UDEV_FLAG0=0).
|
||||
|
||||
The previous commits
|
||||
|
||||
2b25a9e libmultipath: select_action(): force udev reload for uninitialized maps
|
||||
cb10d38 multipathd: uev_trigger(): handle incomplete ADD events
|
||||
|
||||
addressed the same issue, but incompletely. They would miss cases where the
|
||||
map was configured correctly but none of the RELOAD criteria were met.
|
||||
This patch partially reverts 2b25a9e by converting select_reload_action() into
|
||||
a trivial helper. Instead, we now check for incompletely initialized udev now
|
||||
before checking any of the other reload criteria.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/configure.c | 45 ++++++++++++++++++++++++++--------------
|
||||
1 file changed, 29 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
||||
index c076be72..d9fd9cb8 100644
|
||||
--- a/libmultipath/configure.c
|
||||
+++ b/libmultipath/configure.c
|
||||
@@ -696,12 +696,11 @@ sysfs_set_max_sectors_kb(struct multipath *mpp, int is_reload)
|
||||
return err;
|
||||
}
|
||||
|
||||
-static void
|
||||
-select_reload_action(struct multipath *mpp, const struct multipath *cmpp,
|
||||
- const char *reason)
|
||||
+static bool is_udev_ready(struct multipath *cmpp)
|
||||
{
|
||||
struct udev_device *mpp_ud;
|
||||
const char *env;
|
||||
+ bool rc;
|
||||
|
||||
/*
|
||||
* MPATH_DEVICE_READY != 1 can mean two things:
|
||||
@@ -713,14 +712,20 @@ select_reload_action(struct multipath *mpp, const struct multipath *cmpp,
|
||||
*/
|
||||
|
||||
mpp_ud = get_udev_for_mpp(cmpp);
|
||||
+ if (!mpp_ud)
|
||||
+ return true;
|
||||
env = udev_device_get_property_value(mpp_ud, "MPATH_DEVICE_READY");
|
||||
- if ((!env || strcmp(env, "1")) && count_active_paths(mpp) > 0)
|
||||
- mpp->force_udev_reload = 1;
|
||||
+ rc = (env != NULL && !strcmp(env, "1"));
|
||||
udev_device_unref(mpp_ud);
|
||||
+ condlog(4, "%s: %s: \"%s\" -> %d\n", __func__, cmpp->alias, env, rc);
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+select_reload_action(struct multipath *mpp, const char *reason)
|
||||
+{
|
||||
mpp->action = ACT_RELOAD;
|
||||
- condlog(3, "%s: set ACT_RELOAD (%s%s)", mpp->alias,
|
||||
- mpp->force_udev_reload ? "forced, " : "",
|
||||
- reason);
|
||||
+ condlog(3, "%s: set ACT_RELOAD (%s)", mpp->alias, reason);
|
||||
}
|
||||
|
||||
void select_action (struct multipath *mpp, const struct _vector *curmp,
|
||||
@@ -789,10 +794,18 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (!is_udev_ready(cmpp) && count_active_paths(mpp) > 0) {
|
||||
+ mpp->force_udev_reload = 1;
|
||||
+ mpp->action = ACT_RELOAD;
|
||||
+ condlog(3, "%s: set ACT_RELOAD (udev incomplete)",
|
||||
+ mpp->alias);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
|
||||
!!strstr(mpp->features, "queue_if_no_path") !=
|
||||
!!strstr(cmpp->features, "queue_if_no_path")) {
|
||||
- select_reload_action(mpp, cmpp, "no_path_retry change");
|
||||
+ select_reload_action(mpp, "no_path_retry change");
|
||||
return;
|
||||
}
|
||||
if ((mpp->retain_hwhandler != RETAIN_HWHANDLER_ON ||
|
||||
@@ -800,7 +813,7 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
|
||||
(strlen(cmpp->hwhandler) != strlen(mpp->hwhandler) ||
|
||||
strncmp(cmpp->hwhandler, mpp->hwhandler,
|
||||
strlen(mpp->hwhandler)))) {
|
||||
- select_reload_action(mpp, cmpp, "hwhandler change");
|
||||
+ select_reload_action(mpp, "hwhandler change");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -808,7 +821,7 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
|
||||
!!strstr(mpp->features, "retain_attached_hw_handler") !=
|
||||
!!strstr(cmpp->features, "retain_attached_hw_handler") &&
|
||||
get_linux_version_code() < KERNEL_VERSION(4, 3, 0)) {
|
||||
- select_reload_action(mpp, cmpp, "retain_hwhandler change");
|
||||
+ select_reload_action(mpp, "retain_hwhandler change");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -820,7 +833,7 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
|
||||
remove_feature(&cmpp_feat, "queue_if_no_path");
|
||||
remove_feature(&cmpp_feat, "retain_attached_hw_handler");
|
||||
if (strncmp(mpp_feat, cmpp_feat, PARAMS_SIZE)) {
|
||||
- select_reload_action(mpp, cmpp, "features change");
|
||||
+ select_reload_action(mpp, "features change");
|
||||
FREE(cmpp_feat);
|
||||
FREE(mpp_feat);
|
||||
return;
|
||||
@@ -831,19 +844,19 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
|
||||
|
||||
if (!cmpp->selector || strncmp(cmpp->selector, mpp->selector,
|
||||
strlen(mpp->selector))) {
|
||||
- select_reload_action(mpp, cmpp, "selector change");
|
||||
+ select_reload_action(mpp, "selector change");
|
||||
return;
|
||||
}
|
||||
if (cmpp->minio != mpp->minio) {
|
||||
- select_reload_action(mpp, cmpp, "minio change");
|
||||
+ select_reload_action(mpp, "minio change");
|
||||
return;
|
||||
}
|
||||
if (!cmpp->pg || VECTOR_SIZE(cmpp->pg) != VECTOR_SIZE(mpp->pg)) {
|
||||
- select_reload_action(mpp, cmpp, "path group number change");
|
||||
+ select_reload_action(mpp, "path group number change");
|
||||
return;
|
||||
}
|
||||
if (pgcmp(mpp, cmpp)) {
|
||||
- select_reload_action(mpp, cmpp, "path group topology change");
|
||||
+ select_reload_action(mpp, "path group topology change");
|
||||
return;
|
||||
}
|
||||
if (cmpp->nextpg != mpp->bestpg) {
|
@ -1,109 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 15 Dec 2020 17:09:49 +0100
|
||||
Subject: [PATCH] multipath-tools: avoid access to /etc/localtime
|
||||
|
||||
If the root file system is multipathed, and IO is queued because all paths
|
||||
are failed, multipathd may block trying to access the root FS, and thus be
|
||||
unable to reinstate paths. One file that is frequently accessed is
|
||||
/etc/localtime. Avoid that by printing monotonic timestamps instead.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/debug.c | 14 ++++++++------
|
||||
libmultipath/devmapper.c | 12 ++++++------
|
||||
libmultipath/log.c | 1 -
|
||||
multipathd/main.c | 3 ---
|
||||
4 files changed, 14 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/debug.c b/libmultipath/debug.c
|
||||
index 429f2699..510e15e5 100644
|
||||
--- a/libmultipath/debug.c
|
||||
+++ b/libmultipath/debug.c
|
||||
@@ -14,6 +14,8 @@
|
||||
#include "config.h"
|
||||
#include "defaults.h"
|
||||
#include "debug.h"
|
||||
+#include "time-util.h"
|
||||
+#include "util.h"
|
||||
|
||||
int logsink;
|
||||
int libmp_verbosity = DEFAULT_VERBOSITY;
|
||||
@@ -25,13 +27,13 @@ void dlog(int prio, const char * fmt, ...)
|
||||
va_start(ap, fmt);
|
||||
if (logsink != LOGSINK_SYSLOG) {
|
||||
if (logsink == LOGSINK_STDERR_WITH_TIME) {
|
||||
- time_t t = time(NULL);
|
||||
- struct tm *tb = localtime(&t);
|
||||
- char buff[16];
|
||||
+ struct timespec ts;
|
||||
+ char buff[32];
|
||||
|
||||
- strftime(buff, sizeof(buff),
|
||||
- "%b %d %H:%M:%S", tb);
|
||||
- buff[sizeof(buff)-1] = '\0';
|
||||
+ get_monotonic_time(&ts);
|
||||
+ safe_sprintf(buff, "%ld.%06ld",
|
||||
+ (long)ts.tv_sec,
|
||||
+ ts.tv_nsec/1000);
|
||||
fprintf(stderr, "%s | ", buff);
|
||||
}
|
||||
vfprintf(stderr, fmt, ap);
|
||||
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||
index 4977b311..095cbc0c 100644
|
||||
--- a/libmultipath/devmapper.c
|
||||
+++ b/libmultipath/devmapper.c
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "config.h"
|
||||
#include "wwids.h"
|
||||
#include "version.h"
|
||||
+#include "time-util.h"
|
||||
|
||||
#include "log_pthread.h"
|
||||
#include <sys/types.h>
|
||||
@@ -106,13 +107,12 @@ dm_write_log (int level, const char *file, int line, const char *f, ...)
|
||||
va_start(ap, f);
|
||||
if (logsink != LOGSINK_SYSLOG) {
|
||||
if (logsink == LOGSINK_STDERR_WITH_TIME) {
|
||||
- time_t t = time(NULL);
|
||||
- struct tm *tb = localtime(&t);
|
||||
- char buff[16];
|
||||
-
|
||||
- strftime(buff, sizeof(buff), "%b %d %H:%M:%S", tb);
|
||||
- buff[sizeof(buff)-1] = '\0';
|
||||
+ struct timespec ts;
|
||||
+ char buff[32];
|
||||
|
||||
+ get_monotonic_time(&ts);
|
||||
+ safe_sprintf(buff, "%ld.%06ld",
|
||||
+ (long)ts.tv_sec, ts.tv_nsec/1000);
|
||||
fprintf(stderr, "%s | ", buff);
|
||||
}
|
||||
fprintf(stderr, "libdevmapper: %s(%i): ", file, line);
|
||||
diff --git a/libmultipath/log.c b/libmultipath/log.c
|
||||
index 95c8f01a..6498c88c 100644
|
||||
--- a/libmultipath/log.c
|
||||
+++ b/libmultipath/log.c
|
||||
@@ -120,7 +120,6 @@ void log_reset (char *program_name)
|
||||
pthread_cleanup_push(cleanup_mutex, &logq_lock);
|
||||
|
||||
closelog();
|
||||
- tzset();
|
||||
openlog(program_name, 0, LOG_DAEMON);
|
||||
|
||||
pthread_cleanup_pop(1);
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 2eab4854..4417860b 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -2706,9 +2706,6 @@ reconfigure (struct vectors * vecs)
|
||||
delete_all_foreign();
|
||||
|
||||
reset_checker_classes();
|
||||
- /* Re-read any timezone changes */
|
||||
- tzset();
|
||||
-
|
||||
if (bindings_read_only)
|
||||
conf->bindings_read_only = bindings_read_only;
|
||||
check_alias_settings(conf);
|
@ -1,146 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Wed, 16 Dec 2020 23:14:59 +0100
|
||||
Subject: [PATCH] multipath-tools: make sure plugin DSOs use symbol versions
|
||||
|
||||
By adding -Wl,-z,defs, we'll get warnings about unresolved symbols
|
||||
at the linking stage. This way we make sure our plugins (checkers etc.)
|
||||
will use versioned symbols from libmultipath, and incompatible plugins
|
||||
can't be loaded any more. Doing this requires explicitly linking
|
||||
the plugins with all libraries they use, in particular libmultipath.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
Makefile | 1 +
|
||||
Makefile.inc | 2 +-
|
||||
libmpathpersist/Makefile | 8 ++++----
|
||||
libmultipath/checkers/Makefile | 7 +++----
|
||||
libmultipath/foreign/Makefile | 4 +++-
|
||||
libmultipath/prioritizers/Makefile | 7 +++----
|
||||
6 files changed, 15 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index f127ff91..bddb2bf7 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -31,6 +31,7 @@ $(BUILDDIRS):
|
||||
|
||||
libmultipath libdmmp: libmpathcmd
|
||||
libmpathpersist libmpathvalid multipath multipathd: libmultipath
|
||||
+libmultipath/prioritizers libmultipath/checkers libmultipath/foreign: libmultipath
|
||||
mpathpersist multipathd: libmpathpersist
|
||||
|
||||
libmultipath/checkers.install \
|
||||
diff --git a/Makefile.inc b/Makefile.inc
|
||||
index 13587a9f..05429307 100644
|
||||
--- a/Makefile.inc
|
||||
+++ b/Makefile.inc
|
||||
@@ -105,7 +105,7 @@ CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \
|
||||
BIN_CFLAGS = -fPIE -DPIE
|
||||
LIB_CFLAGS = -fPIC
|
||||
SHARED_FLAGS = -shared
|
||||
-LDFLAGS := $(LDFLAGS) -Wl,-z,relro -Wl,-z,now
|
||||
+LDFLAGS := $(LDFLAGS) -Wl,-z,relro -Wl,-z,now -Wl,-z,defs
|
||||
BIN_LDFLAGS = -pie
|
||||
|
||||
# Check whether a function with name $1 has been declared in header file $2.
|
||||
diff --git a/libmpathpersist/Makefile b/libmpathpersist/Makefile
|
||||
index 456ce4cf..57103e58 100644
|
||||
--- a/libmpathpersist/Makefile
|
||||
+++ b/libmpathpersist/Makefile
|
||||
@@ -6,17 +6,17 @@ LIBS = $(DEVLIB).$(SONAME)
|
||||
VERSION_SCRIPT := libmpathpersist.version
|
||||
|
||||
CFLAGS += $(LIB_CFLAGS) -I$(multipathdir) -I$(mpathpersistdir) -I$(mpathcmddir)
|
||||
+LDFLAGS += -L$(multipathdir) -L$(mpathcmddir)
|
||||
|
||||
-LIBDEPS += -lpthread -ldevmapper -ldl -L$(multipathdir) -lmultipath \
|
||||
- -L$(mpathcmddir) -lmpathcmd
|
||||
+LIBDEPS += -lmultipath -lmpathcmd -ldevmapper -lpthread -ldl
|
||||
|
||||
OBJS = mpath_persist.o mpath_updatepr.o mpath_pr_ioctl.o
|
||||
|
||||
all: $(DEVLIB) man
|
||||
|
||||
$(LIBS): $(OBJS) $(VERSION_SCRIPT)
|
||||
- $(CC) $(LDFLAGS) $(SHARED_FLAGS) $(LIBDEPS) -Wl,-soname=$@ \
|
||||
- -Wl,--version-script=$(VERSION_SCRIPT) -o $@ $(OBJS)
|
||||
+ $(CC) $(LDFLAGS) $(SHARED_FLAGS) -Wl,-soname=$@ \
|
||||
+ -Wl,--version-script=$(VERSION_SCRIPT) -o $@ $(OBJS) $(LIBDEPS)
|
||||
|
||||
$(DEVLIB): $(LIBS)
|
||||
$(LN) $(LIBS) $@
|
||||
diff --git a/libmultipath/checkers/Makefile b/libmultipath/checkers/Makefile
|
||||
index 01c04510..8e0ed5e9 100644
|
||||
--- a/libmultipath/checkers/Makefile
|
||||
+++ b/libmultipath/checkers/Makefile
|
||||
@@ -4,6 +4,8 @@
|
||||
include ../../Makefile.inc
|
||||
|
||||
CFLAGS += $(LIB_CFLAGS) -I..
|
||||
+LDFLAGS += -L.. -lmultipath
|
||||
+LIBDEPS = -lmultipath -laio -lpthread -lrt
|
||||
|
||||
# If you add or remove a checker also update multipath/multipath.conf.5
|
||||
LIBS= \
|
||||
@@ -17,11 +19,8 @@ LIBS= \
|
||||
|
||||
all: $(LIBS)
|
||||
|
||||
-libcheckdirectio.so: directio.o
|
||||
- $(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^ -laio
|
||||
-
|
||||
libcheck%.so: %.o
|
||||
- $(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^
|
||||
+ $(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^ $(LIBDEPS)
|
||||
|
||||
install:
|
||||
$(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(libdir)
|
||||
diff --git a/libmultipath/foreign/Makefile b/libmultipath/foreign/Makefile
|
||||
index fae58a0d..f447a1c4 100644
|
||||
--- a/libmultipath/foreign/Makefile
|
||||
+++ b/libmultipath/foreign/Makefile
|
||||
@@ -5,13 +5,15 @@ TOPDIR=../..
|
||||
include ../../Makefile.inc
|
||||
|
||||
CFLAGS += $(LIB_CFLAGS) -I.. -I$(nvmedir)
|
||||
+LDFLAGS += -L..
|
||||
+LIBDEPS = -lmultipath -ludev -lpthread -lrt
|
||||
|
||||
LIBS = libforeign-nvme.so
|
||||
|
||||
all: $(LIBS)
|
||||
|
||||
libforeign-%.so: %.o
|
||||
- $(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^
|
||||
+ $(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^ $(LIBDEPS)
|
||||
|
||||
install:
|
||||
$(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(libdir)
|
||||
diff --git a/libmultipath/prioritizers/Makefile b/libmultipath/prioritizers/Makefile
|
||||
index fc6e0e0c..8d34ae32 100644
|
||||
--- a/libmultipath/prioritizers/Makefile
|
||||
+++ b/libmultipath/prioritizers/Makefile
|
||||
@@ -4,6 +4,8 @@
|
||||
include ../../Makefile.inc
|
||||
|
||||
CFLAGS += $(LIB_CFLAGS) -I..
|
||||
+LDFLAGS += -L..
|
||||
+LIBDEPS = -lmultipath -lm -lpthread -lrt
|
||||
|
||||
# If you add or remove a prioritizer also update multipath/multipath.conf.5
|
||||
LIBS = \
|
||||
@@ -28,11 +30,8 @@ endif
|
||||
|
||||
all: $(LIBS)
|
||||
|
||||
-libpriopath_latency.so: path_latency.o
|
||||
- $(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^ -lm
|
||||
-
|
||||
libprio%.so: %.o
|
||||
- $(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^
|
||||
+ $(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^ $(LIBDEPS)
|
||||
|
||||
install: $(LIBS)
|
||||
$(INSTALL_PROGRAM) -m 755 libprio*.so $(DESTDIR)$(libdir)
|
@ -1,27 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Thu, 17 Dec 2020 01:30:30 +0100
|
||||
Subject: [PATCH] libmultipath.version: add missing symbol
|
||||
|
||||
The weightedpath prioritizer uses get_next_string(). I'd overlooked
|
||||
this before. This was found with the help of the previous patch.
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/libmultipath.version | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
|
||||
index 751099dc..2228f4ec 100644
|
||||
--- a/libmultipath/libmultipath.version
|
||||
+++ b/libmultipath/libmultipath.version
|
||||
@@ -275,3 +275,8 @@ LIBMULTIPATH_4.3.0 {
|
||||
global:
|
||||
start_checker_thread;
|
||||
} LIBMULTIPATH_4.2.0;
|
||||
+
|
||||
+LIBMULTIPATH_4.4.0 {
|
||||
+global:
|
||||
+ get_next_string;
|
||||
+} LIBMULTIPATH_4.3.0;
|
@ -1,27 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Fri, 18 Dec 2020 23:11:47 +0100
|
||||
Subject: [PATCH] multipath-tools tests: unversioned .so for valgrind tests
|
||||
|
||||
We need to the same thing for valgrind tests as we did in
|
||||
448752f ("libmultipath: create separate .so for unit tests").
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
tests/Makefile | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tests/Makefile b/tests/Makefile
|
||||
index 54da774e..50673fae 100644
|
||||
--- a/tests/Makefile
|
||||
+++ b/tests/Makefile
|
||||
@@ -76,7 +76,7 @@ lib/libchecktur.so:
|
||||
|
||||
%.vgr: %-test lib/libchecktur.so
|
||||
@echo == running valgrind for $< ==
|
||||
- @LD_LIBRARY_PATH=$(multipathdir):$(mpathcmddir) \
|
||||
+ @LD_LIBRARY_PATH=.:$(mpathcmddir) \
|
||||
valgrind --leak-check=full --error-exitcode=128 ./$< >$@ 2>&1
|
||||
|
||||
OBJS = $(TESTS:%=%.o) $(HELPERS)
|
@ -1,50 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Fri, 18 Dec 2020 23:17:48 +0100
|
||||
Subject: [PATCH] multipath-tools unit tests: fix memory leaks in mpathvalid
|
||||
tests
|
||||
|
||||
They break "make valgrind-test".
|
||||
|
||||
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
tests/mpathvalid.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/tests/mpathvalid.c b/tests/mpathvalid.c
|
||||
index 5ffabb9d..cfe4bae1 100644
|
||||
--- a/tests/mpathvalid.c
|
||||
+++ b/tests/mpathvalid.c
|
||||
@@ -381,6 +381,7 @@ static void test_mpathvalid_is_path_good2(void **state)
|
||||
assert_int_equal(mpathvalid_is_path(test_dev, MPATH_DEFAULT, &wwid,
|
||||
wwids, 4), MPATH_IS_VALID);
|
||||
assert_string_equal(wwid, TEST_WWID);
|
||||
+ free(wwid);
|
||||
}
|
||||
|
||||
static void test_mpathvalid_is_path_good3(void **state)
|
||||
@@ -395,6 +396,7 @@ static void test_mpathvalid_is_path_good3(void **state)
|
||||
assert_int_equal(mpathvalid_is_path(test_dev, MPATH_SMART, &wwid,
|
||||
wwids, 4), MPATH_IS_VALID);
|
||||
assert_string_equal(wwid, TEST_WWID);
|
||||
+ free(wwid);
|
||||
}
|
||||
|
||||
/* mabybe valid with no matching paths */
|
||||
@@ -410,6 +412,7 @@ static void test_mpathvalid_is_path_good4(void **state)
|
||||
assert_int_equal(mpathvalid_is_path(test_dev, MPATH_DEFAULT, &wwid,
|
||||
wwids, 4), MPATH_IS_MAYBE_VALID);
|
||||
assert_string_equal(wwid, TEST_WWID);
|
||||
+ free(wwid);
|
||||
}
|
||||
|
||||
/* maybe valid with matching paths */
|
||||
@@ -425,6 +428,7 @@ static void test_mpathvalid_is_path_good5(void **state)
|
||||
assert_int_equal(mpathvalid_is_path(test_dev, MPATH_DEFAULT, &wwid,
|
||||
wwids, 4), MPATH_IS_VALID);
|
||||
assert_string_equal(wwid, TEST_WWID);
|
||||
+ free(wwid);
|
||||
}
|
||||
|
||||
#define setup_test(name) \
|
@ -1,31 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Fri, 18 Dec 2020 17:06:37 -0600
|
||||
Subject: [PATCH] mpathpersist: Fix Register and Ignore with 0x00 SARK
|
||||
|
||||
When the Register and Ignore command is run with sg_persist, if a 0x00
|
||||
Service Action Reservation Key is given or the --param-sark option is
|
||||
not used at all, sg_persist will clear the registration. mpathpersist
|
||||
will fail with an error. This patch fixes mpathpersist to work like
|
||||
sg_persist in this case.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmpathpersist/mpath_persist.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||
index 79322e86..41789c46 100644
|
||||
--- a/libmpathpersist/mpath_persist.c
|
||||
+++ b/libmpathpersist/mpath_persist.c
|
||||
@@ -304,7 +304,8 @@ int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||
}
|
||||
|
||||
if (memcmp(paramp->key, &mpp->reservation_key, 8) &&
|
||||
- memcmp(paramp->sa_key, &mpp->reservation_key, 8)) {
|
||||
+ memcmp(paramp->sa_key, &mpp->reservation_key, 8) &&
|
||||
+ (prkey || rq_servact != MPATH_PROUT_REG_IGN_SA)) {
|
||||
condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64, alias, get_be64(mpp->reservation_key));
|
||||
ret = MPATH_PR_SYNTAX_ERROR;
|
||||
goto out1;
|
@ -1,36 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Fri, 18 Dec 2020 17:06:38 -0600
|
||||
Subject: [PATCH] mpathpersist: update prkeys file on changing registrations
|
||||
|
||||
When the "reservation_key" option is set to "file" and Register command
|
||||
is run with both the current Reservation Key and a new Service Action
|
||||
Reservation Key, mpathpersist will change the registration, but will not
|
||||
update the prkeys file. This means that future paths that come online
|
||||
will not be able to register, since multipathd is still using the old
|
||||
reservation key. Fix this.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmpathpersist/mpath_persist.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||
index 41789c46..08077936 100644
|
||||
--- a/libmpathpersist/mpath_persist.c
|
||||
+++ b/libmpathpersist/mpath_persist.c
|
||||
@@ -290,9 +290,10 @@ int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||
|
||||
memcpy(&prkey, paramp->sa_key, 8);
|
||||
if (mpp->prkey_source == PRKEY_SOURCE_FILE && prkey &&
|
||||
- ((!get_be64(mpp->reservation_key) &&
|
||||
- rq_servact == MPATH_PROUT_REG_SA) ||
|
||||
- rq_servact == MPATH_PROUT_REG_IGN_SA)) {
|
||||
+ (rq_servact == MPATH_PROUT_REG_IGN_SA ||
|
||||
+ (rq_servact == MPATH_PROUT_REG_SA &&
|
||||
+ (!get_be64(mpp->reservation_key) ||
|
||||
+ memcmp(paramp->key, &mpp->reservation_key, 8) == 0)))) {
|
||||
memcpy(&mpp->reservation_key, paramp->sa_key, 8);
|
||||
if (update_prkey_flags(alias, get_be64(mpp->reservation_key),
|
||||
paramp->sa_flags)) {
|
@ -1,39 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Fri, 18 Dec 2020 17:06:39 -0600
|
||||
Subject: [PATCH] libmultipath: warn about missing braces at end of
|
||||
multipath.conf
|
||||
|
||||
Multipath doesn't warn when multipath.conf is missing closing braces at
|
||||
the end of the file. This has confused people about the correct config
|
||||
file syntax, so add a warning.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmultipath/parser.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
|
||||
index 163ffbc9..c70243c3 100644
|
||||
--- a/libmultipath/parser.c
|
||||
+++ b/libmultipath/parser.c
|
||||
@@ -537,7 +537,7 @@ process_stream(struct config *conf, FILE *stream, vector keywords,
|
||||
if (!strcmp(str, EOB)) {
|
||||
if (kw_level > 0) {
|
||||
free_strvec(strvec);
|
||||
- break;
|
||||
+ goto out;
|
||||
}
|
||||
condlog(0, "unmatched '%s' at line %d of %s",
|
||||
EOB, line_nr, file);
|
||||
@@ -576,7 +576,8 @@ process_stream(struct config *conf, FILE *stream, vector keywords,
|
||||
|
||||
free_strvec(strvec);
|
||||
}
|
||||
-
|
||||
+ if (kw_level == 1)
|
||||
+ condlog(1, "missing '%s' at end of %s", EOB, file);
|
||||
out:
|
||||
FREE(buf);
|
||||
free_uniques(uniques);
|
@ -1,34 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Fri, 18 Dec 2020 17:06:40 -0600
|
||||
Subject: [PATCH] libmultipath: ignore multipaths sections without wwid option
|
||||
|
||||
"multipathd show config local" was crashing in find_mp_by_wwid() if
|
||||
the multipath configuration included a multipaths section that did
|
||||
not set a wwid option. There is no reason to keep a mpentry that
|
||||
didn't set its wwid. Remove it in merge_mptable().
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmultipath/config.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||
index 9f3cb38d..a643703e 100644
|
||||
--- a/libmultipath/config.c
|
||||
+++ b/libmultipath/config.c
|
||||
@@ -509,6 +509,13 @@ void merge_mptable(vector mptable)
|
||||
int i, j;
|
||||
|
||||
vector_foreach_slot(mptable, mp1, i) {
|
||||
+ /* drop invalid multipath configs */
|
||||
+ if (!mp1->wwid) {
|
||||
+ condlog(0, "multipaths config section missing wwid");
|
||||
+ vector_del_slot(mptable, i--);
|
||||
+ free_mpe(mp1);
|
||||
+ continue;
|
||||
+ }
|
||||
j = i + 1;
|
||||
vector_foreach_slot_after(mptable, mp2, j) {
|
||||
if (strcmp(mp1->wwid, mp2->wwid))
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user