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: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
Stanislav Kinsbursky 2011-10-25 14:16:36 +03:00 committed by Trond Myklebust
parent dc6f55e9f8
commit 914edb1bb2
1 changed files with 53 additions and 0 deletions

View File

@ -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;
}
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
* is returned.