-----Original Message-----If
From: Jeff Layton [mailto:jlayton@xxxxxxxxxx]
Sent: Tuesday, September 20, 2011 10:25 AM
To: Stanislav Kinsbursky
Cc: Myklebust, Trond; linux-nfs@xxxxxxxxxxxxxxx; Pavel Emelianov;
neilb@xxxxxxx; netdev@xxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx;
bfields@xxxxxxxxxxxx; davem@xxxxxxxxxxxxx
Subject: Re: [PATCH v5 1/8] SUNRPC: introduce helpers for reference
counted rpcbind clients
On Tue, 20 Sep 2011 17:49:27 +0400
Stanislav Kinsbursky<skinsbursky@xxxxxxxxxxxxx> wrote:
v5: fixed races with rpcb_users in rpcb_get_local()
This helpers will be used for dynamical creation and destruction of
rpcbind clients.
Variable rpcb_users is actually a counter of lauched RPC services.
rpcb_users.rpcbind clients has been created already, then we just increaseprotected by++++++++++++++++++++++++++++++++++++++++++++++++
Signed-off-by: Stanislav Kinsbursky<skinsbursky@xxxxxxxxxxxxx>
---
net/sunrpc/rpcb_clnt.c | 53
1 files changed, 53 insertions(+), 0 deletions(-)
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index
e45d2fb..5f4a406 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -114,6 +114,9 @@ static struct rpc_program rpcb_program;
static struct rpc_clnt * rpcb_local_clnt;
static struct rpc_clnt * rpcb_local_clnt4;
+DEFINE_SPINLOCK(rpcb_clnt_lock);
+unsigned int rpcb_users;
+
struct rpcbind_args {
struct rpc_xprt * r_xprt;
@@ -161,6 +164,56 @@ static void rpcb_map_release(void *data)
kfree(map);
}
+static int rpcb_get_local(void)
+{
+ int cnt;
+
+ spin_lock(&rpcb_clnt_lock);
+ if (rpcb_users)
+ rpcb_users++;
+ cnt = rpcb_users;
+ spin_unlock(&rpcb_clnt_lock);
+
+ return cnt;
+}
+
+void rpcb_put_local(void)
+{
+ struct rpc_clnt *clnt = rpcb_local_clnt;
+ struct rpc_clnt *clnt4 = rpcb_local_clnt4;
+ int shutdown;
+
+ spin_lock(&rpcb_clnt_lock);
+ if (--rpcb_users == 0) {
+ rpcb_local_clnt = NULL;
+ rpcb_local_clnt4 = NULL;
+ }
In the function below, you mention that the above pointers arerpcb_create_local_mutex, but it looks like they get reset here withoutthatbeing held?one of
Might it be simpler to just protect rpcb_users with the
rpcb_create_local_mutex and ensure that it's held whenever you call
these routines? None of these are codepaths are particularly hot.
Alternatively, if you do
if (rpcb_users == 1) {
rpcb_local_clnt = NULL;
rpcb_local_clnt4 = NULL;
smp_wmb();
rpcb_users = 0;
} else
rpcb_users--;
then the spinlock protection in rpbc_get_local() is still good enough to
guarantee correctness.