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

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