|
|
a5a7cf |
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
a5a7cf |
From: Benjamin Marzinski <bmarzins@redhat.com>
|
|
|
a5a7cf |
Date: Mon, 25 Jan 2021 23:31:04 -0600
|
|
|
a5a7cf |
Subject: [PATCH] libmpathpersist: fix thread safety of default functions
|
|
|
a5a7cf |
|
|
|
a5a7cf |
commit a839e39e ("libmpathpersist: factor out initialization and
|
|
|
a5a7cf |
teardown") made mpath_presistent_reserve_{in,out} use share variables
|
|
|
a5a7cf |
for curmp and pathvec. There are users of this library that call these
|
|
|
a5a7cf |
functions in a multi-threaded process, and this change causes their
|
|
|
a5a7cf |
application to crash. config and udev are also shared variables, but
|
|
|
a5a7cf |
libmpathpersist doesn't write to the config in
|
|
|
a5a7cf |
mpath_presistent_reserve_{in,out}, and looking into the libudev code, I
|
|
|
a5a7cf |
don't see any place where libmpathpersist uses the udev object in a way
|
|
|
a5a7cf |
that isn't thread-safe.
|
|
|
a5a7cf |
|
|
|
a5a7cf |
This patch makes mpath_presistent_reserve_{in,out} go back to using
|
|
|
a5a7cf |
local variables for curmp and pathvec, so that multiple threads won't
|
|
|
a5a7cf |
be operating on these variables at the same time.
|
|
|
a5a7cf |
|
|
|
a5a7cf |
Fixes: a839e39e ("libmpathpersist: factor out initialization and teardown")
|
|
|
a5a7cf |
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
|
|
a5a7cf |
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
|
|
a5a7cf |
---
|
|
|
a5a7cf |
libmpathpersist/mpath_persist.c | 116 +++++++++++++++++++++-----------
|
|
|
a5a7cf |
libmpathpersist/mpath_persist.h | 24 +++++--
|
|
|
a5a7cf |
2 files changed, 94 insertions(+), 46 deletions(-)
|
|
|
a5a7cf |
|
|
|
a5a7cf |
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
|
|
a5a7cf |
index a01dfb0b..07a5f17f 100644
|
|
|
a5a7cf |
--- a/libmpathpersist/mpath_persist.c
|
|
|
a5a7cf |
+++ b/libmpathpersist/mpath_persist.c
|
|
|
a5a7cf |
@@ -147,72 +147,60 @@ mpath_prin_activepath (struct multipath *mpp, int rq_servact,
|
|
|
a5a7cf |
return ret;
|
|
|
a5a7cf |
}
|
|
|
a5a7cf |
|
|
|
a5a7cf |
-int mpath_persistent_reserve_in (int fd, int rq_servact,
|
|
|
a5a7cf |
- struct prin_resp *resp, int noisy, int verbose)
|
|
|
a5a7cf |
-{
|
|
|
a5a7cf |
- int ret = mpath_persistent_reserve_init_vecs(verbose);
|
|
|
a5a7cf |
-
|
|
|
a5a7cf |
- if (ret != MPATH_PR_SUCCESS)
|
|
|
a5a7cf |
- return ret;
|
|
|
a5a7cf |
- ret = __mpath_persistent_reserve_in(fd, rq_servact, resp, noisy);
|
|
|
a5a7cf |
- mpath_persistent_reserve_free_vecs();
|
|
|
a5a7cf |
- return ret;
|
|
|
a5a7cf |
-}
|
|
|
a5a7cf |
-
|
|
|
a5a7cf |
-int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
|
|
a5a7cf |
- unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, int verbose)
|
|
|
a5a7cf |
-{
|
|
|
a5a7cf |
- int ret = mpath_persistent_reserve_init_vecs(verbose);
|
|
|
a5a7cf |
-
|
|
|
a5a7cf |
- if (ret != MPATH_PR_SUCCESS)
|
|
|
a5a7cf |
- return ret;
|
|
|
a5a7cf |
- ret = __mpath_persistent_reserve_out(fd, rq_servact, rq_scope, rq_type,
|
|
|
a5a7cf |
- paramp, noisy);
|
|
|
a5a7cf |
- mpath_persistent_reserve_free_vecs();
|
|
|
a5a7cf |
- return ret;
|
|
|
a5a7cf |
-}
|
|
|
a5a7cf |
-
|
|
|
a5a7cf |
static vector curmp;
|
|
|
a5a7cf |
static vector pathvec;
|
|
|
a5a7cf |
|
|
|
a5a7cf |
-void mpath_persistent_reserve_free_vecs(void)
|
|
|
a5a7cf |
+static void __mpath_persistent_reserve_free_vecs(vector curmp, vector pathvec)
|
|
|
a5a7cf |
{
|
|
|
a5a7cf |
free_multipathvec(curmp, KEEP_PATHS);
|
|
|
a5a7cf |
free_pathvec(pathvec, FREE_PATHS);
|
|
|
a5a7cf |
+}
|
|
|
a5a7cf |
+
|
|
|
a5a7cf |
+void mpath_persistent_reserve_free_vecs(void)
|
|
|
a5a7cf |
+{
|
|
|
a5a7cf |
+ __mpath_persistent_reserve_free_vecs(curmp, pathvec);
|
|
|
a5a7cf |
curmp = pathvec = NULL;
|
|
|
a5a7cf |
}
|
|
|
a5a7cf |
|
|
|
a5a7cf |
-int mpath_persistent_reserve_init_vecs(int verbose)
|
|
|
a5a7cf |
+static int __mpath_persistent_reserve_init_vecs(vector *curmp_p,
|
|
|
a5a7cf |
+ vector *pathvec_p, int verbose)
|
|
|
a5a7cf |
{
|
|
|
a5a7cf |
struct config *conf = get_multipath_config();
|
|
|
a5a7cf |
|
|
|
a5a7cf |
conf->verbosity = verbose;
|
|
|
a5a7cf |
put_multipath_config(conf);
|
|
|
a5a7cf |
|
|
|
a5a7cf |
- if (curmp)
|
|
|
a5a7cf |
+ if (*curmp_p)
|
|
|
a5a7cf |
return MPATH_PR_SUCCESS;
|
|
|
a5a7cf |
/*
|
|
|
a5a7cf |
* allocate core vectors to store paths and multipaths
|
|
|
a5a7cf |
*/
|
|
|
a5a7cf |
- curmp = vector_alloc ();
|
|
|
a5a7cf |
- pathvec = vector_alloc ();
|
|
|
a5a7cf |
+ *curmp_p = vector_alloc ();
|
|
|
a5a7cf |
+ *pathvec_p = vector_alloc ();
|
|
|
a5a7cf |
|
|
|
a5a7cf |
- if (!curmp || !pathvec){
|
|
|
a5a7cf |
+ if (!*curmp_p || !*pathvec_p){
|
|
|
a5a7cf |
condlog (0, "vector allocation failed.");
|
|
|
a5a7cf |
goto err;
|
|
|
a5a7cf |
}
|
|
|
a5a7cf |
|
|
|
a5a7cf |
- if (dm_get_maps(curmp))
|
|
|
a5a7cf |
+ if (dm_get_maps(*curmp_p))
|
|
|
a5a7cf |
goto err;
|
|
|
a5a7cf |
|
|
|
a5a7cf |
return MPATH_PR_SUCCESS;
|
|
|
a5a7cf |
|
|
|
a5a7cf |
err:
|
|
|
a5a7cf |
- mpath_persistent_reserve_free_vecs();
|
|
|
a5a7cf |
+ __mpath_persistent_reserve_free_vecs(*curmp_p, *pathvec_p);
|
|
|
a5a7cf |
+ *curmp_p = *pathvec_p = NULL;
|
|
|
a5a7cf |
return MPATH_PR_DMMP_ERROR;
|
|
|
a5a7cf |
}
|
|
|
a5a7cf |
|
|
|
a5a7cf |
-static int mpath_get_map(int fd, char **palias, struct multipath **pmpp)
|
|
|
a5a7cf |
+int mpath_persistent_reserve_init_vecs(int verbose)
|
|
|
a5a7cf |
+{
|
|
|
a5a7cf |
+ return __mpath_persistent_reserve_init_vecs(&curmp, &pathvec, verbose);
|
|
|
a5a7cf |
+}
|
|
|
a5a7cf |
+
|
|
|
a5a7cf |
+static int mpath_get_map(vector curmp, vector pathvec, int fd, char **palias,
|
|
|
a5a7cf |
+ struct multipath **pmpp)
|
|
|
a5a7cf |
{
|
|
|
a5a7cf |
int ret = MPATH_PR_DMMP_ERROR;
|
|
|
a5a7cf |
struct stat info;
|
|
|
a5a7cf |
@@ -272,13 +260,13 @@ out:
|
|
|
a5a7cf |
return ret;
|
|
|
a5a7cf |
}
|
|
|
a5a7cf |
|
|
|
a5a7cf |
-int __mpath_persistent_reserve_in (int fd, int rq_servact,
|
|
|
a5a7cf |
- struct prin_resp *resp, int noisy)
|
|
|
a5a7cf |
+static int do_mpath_persistent_reserve_in (vector curmp, vector pathvec,
|
|
|
a5a7cf |
+ int fd, int rq_servact, struct prin_resp *resp, int noisy)
|
|
|
a5a7cf |
{
|
|
|
a5a7cf |
struct multipath *mpp;
|
|
|
a5a7cf |
int ret;
|
|
|
a5a7cf |
|
|
|
a5a7cf |
- ret = mpath_get_map(fd, NULL, &mpp;;
|
|
|
a5a7cf |
+ ret = mpath_get_map(curmp, pathvec, fd, NULL, &mpp;;
|
|
|
a5a7cf |
if (ret != MPATH_PR_SUCCESS)
|
|
|
a5a7cf |
return ret;
|
|
|
a5a7cf |
|
|
|
a5a7cf |
@@ -287,8 +275,17 @@ int __mpath_persistent_reserve_in (int fd, int rq_servact,
|
|
|
a5a7cf |
return ret;
|
|
|
a5a7cf |
}
|
|
|
a5a7cf |
|
|
|
a5a7cf |
-int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
|
|
a5a7cf |
- unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy)
|
|
|
a5a7cf |
+
|
|
|
a5a7cf |
+int __mpath_persistent_reserve_in (int fd, int rq_servact,
|
|
|
a5a7cf |
+ struct prin_resp *resp, int noisy)
|
|
|
a5a7cf |
+{
|
|
|
a5a7cf |
+ return do_mpath_persistent_reserve_in(curmp, pathvec, fd, rq_servact,
|
|
|
a5a7cf |
+ resp, noisy);
|
|
|
a5a7cf |
+}
|
|
|
a5a7cf |
+
|
|
|
a5a7cf |
+static int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd,
|
|
|
a5a7cf |
+ int rq_servact, int rq_scope, unsigned int rq_type,
|
|
|
a5a7cf |
+ struct prout_param_descriptor *paramp, int noisy)
|
|
|
a5a7cf |
{
|
|
|
a5a7cf |
struct multipath *mpp;
|
|
|
a5a7cf |
char *alias;
|
|
|
a5a7cf |
@@ -296,7 +293,7 @@ int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
|
|
a5a7cf |
uint64_t prkey;
|
|
|
a5a7cf |
struct config *conf;
|
|
|
a5a7cf |
|
|
|
a5a7cf |
- ret = mpath_get_map(fd, &alias, &mpp;;
|
|
|
a5a7cf |
+ ret = mpath_get_map(curmp, pathvec, fd, &alias, &mpp;;
|
|
|
a5a7cf |
if (ret != MPATH_PR_SUCCESS)
|
|
|
a5a7cf |
return ret;
|
|
|
a5a7cf |
|
|
|
a5a7cf |
@@ -366,6 +363,45 @@ out1:
|
|
|
a5a7cf |
return ret;
|
|
|
a5a7cf |
}
|
|
|
a5a7cf |
|
|
|
a5a7cf |
+
|
|
|
a5a7cf |
+int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
|
|
a5a7cf |
+ unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy)
|
|
|
a5a7cf |
+{
|
|
|
a5a7cf |
+ return do_mpath_persistent_reserve_out(curmp, pathvec, fd, rq_servact,
|
|
|
a5a7cf |
+ rq_scope, rq_type, paramp,
|
|
|
a5a7cf |
+ noisy);
|
|
|
a5a7cf |
+}
|
|
|
a5a7cf |
+
|
|
|
a5a7cf |
+int mpath_persistent_reserve_in (int fd, int rq_servact,
|
|
|
a5a7cf |
+ struct prin_resp *resp, int noisy, int verbose)
|
|
|
a5a7cf |
+{
|
|
|
a5a7cf |
+ vector curmp = NULL, pathvec;
|
|
|
a5a7cf |
+ int ret = __mpath_persistent_reserve_init_vecs(&curmp, &pathvec,
|
|
|
a5a7cf |
+ verbose);
|
|
|
a5a7cf |
+
|
|
|
a5a7cf |
+ if (ret != MPATH_PR_SUCCESS)
|
|
|
a5a7cf |
+ return ret;
|
|
|
a5a7cf |
+ ret = do_mpath_persistent_reserve_in(curmp, pathvec, fd, rq_servact,
|
|
|
a5a7cf |
+ resp, noisy);
|
|
|
a5a7cf |
+ __mpath_persistent_reserve_free_vecs(curmp, pathvec);
|
|
|
a5a7cf |
+ return ret;
|
|
|
a5a7cf |
+}
|
|
|
a5a7cf |
+
|
|
|
a5a7cf |
+int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
|
|
a5a7cf |
+ unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, int verbose)
|
|
|
a5a7cf |
+{
|
|
|
a5a7cf |
+ vector curmp = NULL, pathvec;
|
|
|
a5a7cf |
+ int ret = __mpath_persistent_reserve_init_vecs(&curmp, &pathvec,
|
|
|
a5a7cf |
+ verbose);
|
|
|
a5a7cf |
+
|
|
|
a5a7cf |
+ if (ret != MPATH_PR_SUCCESS)
|
|
|
a5a7cf |
+ return ret;
|
|
|
a5a7cf |
+ ret = do_mpath_persistent_reserve_out(curmp, pathvec, fd, rq_servact,
|
|
|
a5a7cf |
+ rq_scope, rq_type, paramp, noisy);
|
|
|
a5a7cf |
+ __mpath_persistent_reserve_free_vecs(curmp, pathvec);
|
|
|
a5a7cf |
+ return ret;
|
|
|
a5a7cf |
+}
|
|
|
a5a7cf |
+
|
|
|
a5a7cf |
int
|
|
|
a5a7cf |
get_mpvec (vector curmp, vector pathvec, char * refwwid)
|
|
|
a5a7cf |
{
|
|
|
a5a7cf |
diff --git a/libmpathpersist/mpath_persist.h b/libmpathpersist/mpath_persist.h
|
|
|
a5a7cf |
index 7cf4faf9..0e4e0e53 100644
|
|
|
a5a7cf |
--- a/libmpathpersist/mpath_persist.h
|
|
|
a5a7cf |
+++ b/libmpathpersist/mpath_persist.h
|
|
|
a5a7cf |
@@ -215,9 +215,13 @@ extern int mpath_persistent_reserve_in (int fd, int rq_servact, struct prin_resp
|
|
|
a5a7cf |
|
|
|
a5a7cf |
/*
|
|
|
a5a7cf |
* DESCRIPTION :
|
|
|
a5a7cf |
- * This function is like mpath_persistent_reserve_in(), except that it doesn't call
|
|
|
a5a7cf |
- * mpath_persistent_reserve_init_vecs() and mpath_persistent_reserve_free_vecs()
|
|
|
a5a7cf |
- * before and after the actual PR call.
|
|
|
a5a7cf |
+ * This function is like mpath_persistent_reserve_in(), except that it
|
|
|
a5a7cf |
+ * requires mpath_persistent_reserve_init_vecs() to be called before the
|
|
|
a5a7cf |
+ * PR call to set up internal variables. These must later be cleanup up
|
|
|
a5a7cf |
+ * by calling mpath_persistent_reserve_free_vecs().
|
|
|
a5a7cf |
+ *
|
|
|
a5a7cf |
+ * RESTRICTIONS:
|
|
|
a5a7cf |
+ * This function uses static internal variables, and is not thread-safe.
|
|
|
a5a7cf |
*/
|
|
|
a5a7cf |
extern int __mpath_persistent_reserve_in(int fd, int rq_servact,
|
|
|
a5a7cf |
struct prin_resp *resp, int noisy);
|
|
|
a5a7cf |
@@ -249,9 +253,13 @@ extern int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
|
|
a5a7cf |
int verbose);
|
|
|
a5a7cf |
/*
|
|
|
a5a7cf |
* DESCRIPTION :
|
|
|
a5a7cf |
- * This function is like mpath_persistent_reserve_out(), except that it doesn't call
|
|
|
a5a7cf |
- * mpath_persistent_reserve_init_vecs() and mpath_persistent_reserve_free_vecs()
|
|
|
a5a7cf |
- * before and after the actual PR call.
|
|
|
a5a7cf |
+ * This function is like mpath_persistent_reserve_out(), except that it
|
|
|
a5a7cf |
+ * requires mpath_persistent_reserve_init_vecs() to be called before the
|
|
|
a5a7cf |
+ * PR call to set up internal variables. These must later be cleanup up
|
|
|
a5a7cf |
+ * by calling mpath_persistent_reserve_free_vecs().
|
|
|
a5a7cf |
+ *
|
|
|
a5a7cf |
+ * RESTRICTIONS:
|
|
|
a5a7cf |
+ * This function uses static internal variables, and is not thread-safe.
|
|
|
a5a7cf |
*/
|
|
|
a5a7cf |
extern int __mpath_persistent_reserve_out( int fd, int rq_servact, int rq_scope,
|
|
|
a5a7cf |
unsigned int rq_type, struct prout_param_descriptor *paramp,
|
|
|
a5a7cf |
@@ -265,6 +273,7 @@ extern int __mpath_persistent_reserve_out( int fd, int rq_servact, int rq_scope,
|
|
|
a5a7cf |
* @verbose: Set verbosity level. Input argument. value:0 to 3. 0->disabled, 3->Max verbose
|
|
|
a5a7cf |
*
|
|
|
a5a7cf |
* RESTRICTIONS:
|
|
|
a5a7cf |
+ * This function uses static internal variables, and is not thread-safe.
|
|
|
a5a7cf |
*
|
|
|
a5a7cf |
* RETURNS: MPATH_PR_SUCCESS if successful else returns any of the status specified
|
|
|
a5a7cf |
* above in RETURN_STATUS.
|
|
|
a5a7cf |
@@ -275,6 +284,9 @@ int mpath_persistent_reserve_init_vecs(int verbose);
|
|
|
a5a7cf |
* DESCRIPTION :
|
|
|
a5a7cf |
* This function frees data structures allocated by
|
|
|
a5a7cf |
* mpath_persistent_reserve_init_vecs().
|
|
|
a5a7cf |
+ *
|
|
|
a5a7cf |
+ * RESTRICTIONS:
|
|
|
a5a7cf |
+ * This function uses static internal variables, and is not thread-safe.
|
|
|
a5a7cf |
*/
|
|
|
a5a7cf |
void mpath_persistent_reserve_free_vecs(void);
|
|
|
a5a7cf |
|
|
|
a5a7cf |
--
|
|
|
a5a7cf |
2.17.2
|
|
|
a5a7cf |
|