All of lore.kernel.org
 help / color / mirror / Atom feed
From: Benjamin Marzinski <bmarzins@redhat.com>
To: Christophe Varoqui <christophe.varoqui@opensvc.com>
Cc: device-mapper development <dm-devel@redhat.com>,
	Martin Wilck <Martin.Wilck@suse.com>
Subject: [dm-devel] [PATCH] libmpathpersist: fix thread safety of default functions
Date: Mon, 25 Jan 2021 23:31:04 -0600	[thread overview]
Message-ID: <1611639064-8187-1-git-send-email-bmarzins@redhat.com> (raw)

commit a839e39e ("libmpathpersist: factor out initialization and
teardown") made mpath_presistent_reserve_{in,out} use share variables
for curmp and pathvec.  There are users of this library that call these
functions in a multi-threaded process, and this change causes their
application to crash. config and udev are also shared variables, but
libmpathpersist doesn't write to the config in
mpath_presistent_reserve_{in,out}, and looking into the libudev code, I
don't see any place where libmpathpersist uses the udev object in a way
that isn't thread-safe.

This patch makes mpath_presistent_reserve_{in,out} go back to using
local variables for curmp and pathvec, so that multiple threads won't
be operating on these variables at the same time.

Fixes: a839e39e ("libmpathpersist: factor out initialization and teardown")
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
 libmpathpersist/mpath_persist.c | 116 +++++++++++++++++++++-----------
 libmpathpersist/mpath_persist.h |  24 +++++--
 2 files changed, 94 insertions(+), 46 deletions(-)

diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
index 08077936..e4c24b93 100644
--- a/libmpathpersist/mpath_persist.c
+++ b/libmpathpersist/mpath_persist.c
@@ -133,69 +133,57 @@ mpath_prin_activepath (struct multipath *mpp, int rq_servact,
 	return ret;
 }
 
-int mpath_persistent_reserve_in (int fd, int rq_servact,
-	struct prin_resp *resp, int noisy, int verbose)
-{
-	int ret = mpath_persistent_reserve_init_vecs(verbose);
-
-	if (ret != MPATH_PR_SUCCESS)
-		return ret;
-	ret = __mpath_persistent_reserve_in(fd, rq_servact, resp, noisy);
-	mpath_persistent_reserve_free_vecs();
-	return ret;
-}
-
-int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
-	unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, int verbose)
-{
-	int ret = mpath_persistent_reserve_init_vecs(verbose);
-
-	if (ret != MPATH_PR_SUCCESS)
-		return ret;
-	ret = __mpath_persistent_reserve_out(fd, rq_servact, rq_scope, rq_type,
-					     paramp, noisy);
-	mpath_persistent_reserve_free_vecs();
-	return ret;
-}
-
 static vector curmp;
 static vector pathvec;
 
-void mpath_persistent_reserve_free_vecs(void)
+static void __mpath_persistent_reserve_free_vecs(vector curmp, vector pathvec)
 {
 	free_multipathvec(curmp, KEEP_PATHS);
 	free_pathvec(pathvec, FREE_PATHS);
+}
+
+void mpath_persistent_reserve_free_vecs(void)
+{
+	__mpath_persistent_reserve_free_vecs(curmp, pathvec);
 	curmp = pathvec = NULL;
 }
 
-int mpath_persistent_reserve_init_vecs(int verbose)
+static int __mpath_persistent_reserve_init_vecs(vector *curmp_p,
+						vector *pathvec_p, int verbose)
 {
 	libmp_verbosity = verbose;
 
-	if (curmp)
+	if (*curmp_p)
 		return MPATH_PR_SUCCESS;
 	/*
 	 * allocate core vectors to store paths and multipaths
 	 */
-	curmp = vector_alloc ();
-	pathvec = vector_alloc ();
+	*curmp_p = vector_alloc ();
+	*pathvec_p = vector_alloc ();
 
-	if (!curmp || !pathvec){
+	if (!*curmp_p || !*pathvec_p){
 		condlog (0, "vector allocation failed.");
 		goto err;
 	}
 
-	if (dm_get_maps(curmp))
+	if (dm_get_maps(*curmp_p))
 		goto err;
 
 	return MPATH_PR_SUCCESS;
 
 err:
-	mpath_persistent_reserve_free_vecs();
+	__mpath_persistent_reserve_free_vecs(*curmp_p, *pathvec_p);
+	*curmp_p = *pathvec_p = NULL;
 	return MPATH_PR_DMMP_ERROR;
 }
 
-static int mpath_get_map(int fd, char **palias, struct multipath **pmpp)
+int mpath_persistent_reserve_init_vecs(int verbose)
+{
+	return __mpath_persistent_reserve_init_vecs(&curmp, &pathvec, verbose);
+}
+
+static int mpath_get_map(vector curmp, vector pathvec, int fd, char **palias,
+			 struct multipath **pmpp)
 {
 	int ret = MPATH_PR_DMMP_ERROR;
 	struct stat info;
@@ -255,13 +243,13 @@ out:
 	return ret;
 }
 
-int __mpath_persistent_reserve_in (int fd, int rq_servact,
-	struct prin_resp *resp, int noisy)
+static int do_mpath_persistent_reserve_in (vector curmp, vector pathvec,
+	int fd, int rq_servact, struct prin_resp *resp, int noisy)
 {
 	struct multipath *mpp;
 	int ret;
 
-	ret = mpath_get_map(fd, NULL, &mpp);
+	ret = mpath_get_map(curmp, pathvec, fd, NULL, &mpp);
 	if (ret != MPATH_PR_SUCCESS)
 		return ret;
 
@@ -270,8 +258,17 @@ int __mpath_persistent_reserve_in (int fd, int rq_servact,
 	return ret;
 }
 
-int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
-	unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy)
+
+int __mpath_persistent_reserve_in (int fd, int rq_servact,
+	struct prin_resp *resp, int noisy)
+{
+	return do_mpath_persistent_reserve_in(curmp, pathvec, fd, rq_servact,
+					      resp, noisy);
+}
+
+static int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd,
+	int rq_servact, int rq_scope, unsigned int rq_type,
+	struct prout_param_descriptor *paramp, int noisy)
 {
 	struct multipath *mpp;
 	char *alias;
@@ -279,7 +276,7 @@ int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
 	uint64_t prkey;
 	struct config *conf;
 
-	ret = mpath_get_map(fd, &alias, &mpp);
+	ret = mpath_get_map(curmp, pathvec, fd, &alias, &mpp);
 	if (ret != MPATH_PR_SUCCESS)
 		return ret;
 
@@ -349,6 +346,45 @@ out1:
 	return ret;
 }
 
+
+int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
+	unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy)
+{
+	return do_mpath_persistent_reserve_out(curmp, pathvec, fd, rq_servact,
+					       rq_scope, rq_type, paramp,
+					       noisy);
+}
+
+int mpath_persistent_reserve_in (int fd, int rq_servact,
+	struct prin_resp *resp, int noisy, int verbose)
+{
+	vector curmp, pathvec;
+	int ret = __mpath_persistent_reserve_init_vecs(&curmp, &pathvec,
+						       verbose);
+
+	if (ret != MPATH_PR_SUCCESS)
+		return ret;
+	ret = do_mpath_persistent_reserve_in(curmp, pathvec, fd, rq_servact,
+					     resp, noisy);
+	__mpath_persistent_reserve_free_vecs(curmp, pathvec);
+	return ret;
+}
+
+int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
+	unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, int verbose)
+{
+	vector curmp, pathvec;
+	int ret = __mpath_persistent_reserve_init_vecs(&curmp, &pathvec,
+						       verbose);
+
+	if (ret != MPATH_PR_SUCCESS)
+		return ret;
+	ret = do_mpath_persistent_reserve_out(curmp, pathvec, fd, rq_servact,
+					      rq_scope, rq_type, paramp, noisy);
+	__mpath_persistent_reserve_free_vecs(curmp, pathvec);
+	return ret;
+}
+
 int
 get_mpvec (vector curmp, vector pathvec, char * refwwid)
 {
diff --git a/libmpathpersist/mpath_persist.h b/libmpathpersist/mpath_persist.h
index 5435eae4..9e9c0a82 100644
--- a/libmpathpersist/mpath_persist.h
+++ b/libmpathpersist/mpath_persist.h
@@ -246,9 +246,13 @@ extern int mpath_persistent_reserve_in (int fd, int rq_servact, struct prin_resp
 
 /*
  * DESCRIPTION :
- * This function is like mpath_persistent_reserve_in(), except that it doesn't call
- * mpath_persistent_reserve_init_vecs() and mpath_persistent_reserve_free_vecs()
- * before and after the actual PR call.
+ * This function is like mpath_persistent_reserve_in(), except that it
+ * requires mpath_persistent_reserve_init_vecs() to be called before the
+ * PR call to set up internal variables. These must later be cleanup up
+ * by calling mpath_persistent_reserve_free_vecs().
+ *
+ * RESTRICTIONS:
+ * This function uses static internal variables, and is not thread-safe.
  */
 extern int __mpath_persistent_reserve_in(int fd, int rq_servact,
 		struct prin_resp *resp, int noisy);
@@ -280,9 +284,13 @@ extern int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
 		int verbose);
 /*
  * DESCRIPTION :
- * This function is like mpath_persistent_reserve_out(), except that it doesn't call
- * mpath_persistent_reserve_init_vecs() and mpath_persistent_reserve_free_vecs()
- * before and after the actual PR call.
+ * This function is like mpath_persistent_reserve_out(), except that it
+ * requires mpath_persistent_reserve_init_vecs() to be called before the
+ * PR call to set up internal variables. These must later be cleanup up
+ * by calling mpath_persistent_reserve_free_vecs().
+ *
+ * RESTRICTIONS:
+ * This function uses static internal variables, and is not thread-safe.
  */
 extern int __mpath_persistent_reserve_out( int fd, int rq_servact, int rq_scope,
 		unsigned int rq_type, struct prout_param_descriptor *paramp,
@@ -296,6 +304,7 @@ extern int __mpath_persistent_reserve_out( int fd, int rq_servact, int rq_scope,
  * @verbose: Set verbosity level. Input argument. value:0 to 3. 0->disabled, 3->Max verbose
  *
  * RESTRICTIONS:
+ * This function uses static internal variables, and is not thread-safe.
  *
  * RETURNS: MPATH_PR_SUCCESS if successful else returns any of the status specified
  *       above in RETURN_STATUS.
@@ -306,6 +315,9 @@ int mpath_persistent_reserve_init_vecs(int verbose);
  * DESCRIPTION :
  * This function frees data structures allocated by
  * mpath_persistent_reserve_init_vecs().
+ *
+ * RESTRICTIONS:
+ * This function uses static internal variables, and is not thread-safe.
  */
 void mpath_persistent_reserve_free_vecs(void);
 
-- 
2.17.2

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel


             reply	other threads:[~2021-01-26  5:31 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-26  5:31 Benjamin Marzinski [this message]
2021-01-26  9:36 ` [dm-devel] [PATCH] libmpathpersist: fix thread safety of default functions Martin Wilck
2021-01-26 15:30   ` Benjamin Marzinski
2021-01-26 10:04 ` Martin Wilck
2021-01-26 15:32   ` Benjamin Marzinski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1611639064-8187-1-git-send-email-bmarzins@redhat.com \
    --to=bmarzins@redhat.com \
    --cc=Martin.Wilck@suse.com \
    --cc=christophe.varoqui@opensvc.com \
    --cc=dm-devel@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.