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:
Родитель
dc6f55e9f8
Коммит
914edb1bb2
|
@ -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.
|
||||
|
|
Загрузка…
Ссылка в новой задаче