Blame SOURCES/0059-libmpathpersist-fix-thread-safety-of-default-functio.patch

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