Commit 914edb1b authored by Stanislav Kinsbursky's avatar Stanislav Kinsbursky Committed by Trond Myklebust

SUNRPC: introduce helpers for reference counted rpcbind clients

v6:
1) added write memory barrier to rpcb_set_local to make sure, that rpcbind
clients become valid before rpcb_users assignment
2) explicitly set rpcb_users to 1 instead of incrementing it (looks clearer from
my pow).

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. If rpcbind
clients has been created already, then we just increase rpcb_users.
Signed-off-by: default avatarStanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent dc6f55e9
...@@ -114,6 +114,9 @@ static struct rpc_program rpcb_program; ...@@ -114,6 +114,9 @@ static struct rpc_program rpcb_program;
static struct rpc_clnt * rpcb_local_clnt; static struct rpc_clnt * rpcb_local_clnt;
static struct rpc_clnt * rpcb_local_clnt4; static struct rpc_clnt * rpcb_local_clnt4;
DEFINE_SPINLOCK(rpcb_clnt_lock);
unsigned int rpcb_users;
struct rpcbind_args { struct rpcbind_args {
struct rpc_xprt * r_xprt; struct rpc_xprt * r_xprt;
...@@ -161,6 +164,56 @@ static void rpcb_map_release(void *data) ...@@ -161,6 +164,56 @@ static void rpcb_map_release(void *data)
kfree(map); 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;
}
shutdown = !rpcb_users;
spin_unlock(&rpcb_clnt_lock);
if (shutdown) {
/*
* cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister
*/
if (clnt4)
rpc_shutdown_client(clnt4);
if (clnt)
rpc_shutdown_client(clnt);
}
}
static void rpcb_set_local(struct rpc_clnt *clnt, struct rpc_clnt *clnt4)
{
/* Protected by rpcb_create_local_mutex */
rpcb_local_clnt = clnt;
rpcb_local_clnt4 = clnt4;
smp_wmb();
rpcb_users = 1;
dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: "
"%p, rpcb_local_clnt4: %p)\n", rpcb_local_clnt,
rpcb_local_clnt4);
}
/* /*
* Returns zero on success, otherwise a negative errno value * Returns zero on success, otherwise a negative errno value
* is returned. * is returned.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment