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.2.tgz
|
||||||
/multipath-tools-0.8.4.tgz
|
/multipath-tools-0.8.4.tgz
|
||||||
/multipath-tools-0.8.5.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(-)
|
3 files changed, 4 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
diff --git a/Makefile.inc b/Makefile.inc
|
diff --git a/Makefile.inc b/Makefile.inc
|
||||||
index 05429307..24e943d5 100644
|
index f1e23131..c593fd3b 100644
|
||||||
--- a/Makefile.inc
|
--- a/Makefile.inc
|
||||||
+++ b/Makefile.inc
|
+++ b/Makefile.inc
|
||||||
@@ -53,7 +53,7 @@ endif
|
@@ -55,7 +55,7 @@ endif
|
||||||
prefix =
|
prefix =
|
||||||
exec_prefix = $(prefix)
|
exec_prefix = $(prefix)
|
||||||
usr_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(-)
|
1 file changed, 18 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
diff --git a/Makefile.inc b/Makefile.inc
|
diff --git a/Makefile.inc b/Makefile.inc
|
||||||
index 24e943d5..e978d306 100644
|
index c593fd3b..87fb39f2 100644
|
||||||
--- a/Makefile.inc
|
--- a/Makefile.inc
|
||||||
+++ b/Makefile.inc
|
+++ b/Makefile.inc
|
||||||
@@ -90,15 +90,27 @@ TEST_CC_OPTION = $(shell \
|
@@ -92,15 +92,27 @@ TEST_CC_OPTION = $(shell \
|
||||||
echo "$(2)"; \
|
echo "$(2)"; \
|
||||||
fi)
|
fi)
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ index 24e943d5..e978d306 100644
|
|||||||
CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \
|
CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \
|
||||||
-DBIN_DIR=\"$(bindir)\" -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \
|
-DBIN_DIR=\"$(bindir)\" -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \
|
||||||
-MMD -MP
|
-MMD -MP
|
||||||
@@ -136,4 +148,4 @@ check_file = $(shell \
|
@@ -138,4 +150,4 @@ check_file = $(shell \
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
@echo building $@ because of $?
|
@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(-)
|
1 file changed, 2 insertions(+), 16 deletions(-)
|
||||||
|
|
||||||
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
index f8044141..e6590d07 100644
|
index ec99a7aa..2704270e 100644
|
||||||
--- a/libmultipath/discovery.c
|
--- a/libmultipath/discovery.c
|
||||||
+++ b/libmultipath/discovery.c
|
+++ b/libmultipath/discovery.c
|
||||||
@@ -1135,12 +1135,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
|
@@ -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