SUNRPC: move rpcbind internals to sunrpc part of network namespace context

This patch makes rpcbind logic works in network namespace context. IOW each
network namespace will have it's own unique rpcbind internals (clients and
friends) required for registering svc services per network namespace.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
Stanislav Kinsbursky 2012-01-13 12:52:10 +04:00 committed by Trond Myklebust
parent 961a828df6
commit dff02d499c
2 changed files with 40 additions and 29 deletions

View File

@ -15,6 +15,11 @@ struct sunrpc_net {
struct list_head all_clients; struct list_head all_clients;
spinlock_t rpc_client_lock; spinlock_t rpc_client_lock;
struct rpc_clnt *rpcb_local_clnt;
struct rpc_clnt *rpcb_local_clnt4;
spinlock_t rpcb_clnt_lock;
unsigned int rpcb_users;
}; };
extern int sunrpc_net_id; extern int sunrpc_net_id;

View File

@ -23,12 +23,15 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/nsproxy.h>
#include <net/ipv6.h> #include <net/ipv6.h>
#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/sched.h> #include <linux/sunrpc/sched.h>
#include <linux/sunrpc/xprtsock.h> #include <linux/sunrpc/xprtsock.h>
#include "netns.h"
#ifdef RPC_DEBUG #ifdef RPC_DEBUG
# define RPCDBG_FACILITY RPCDBG_BIND # define RPCDBG_FACILITY RPCDBG_BIND
#endif #endif
@ -111,12 +114,6 @@ static void rpcb_getport_done(struct rpc_task *, void *);
static void rpcb_map_release(void *data); static void rpcb_map_release(void *data);
static struct rpc_program rpcb_program; 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 rpcbind_args {
struct rpc_xprt * r_xprt; struct rpc_xprt * r_xprt;
@ -167,29 +164,31 @@ static void rpcb_map_release(void *data)
static int rpcb_get_local(void) static int rpcb_get_local(void)
{ {
int cnt; int cnt;
struct sunrpc_net *sn = net_generic(&init_net, sunrpc_net_id);
spin_lock(&rpcb_clnt_lock); spin_lock(&sn->rpcb_clnt_lock);
if (rpcb_users) if (sn->rpcb_users)
rpcb_users++; sn->rpcb_users++;
cnt = rpcb_users; cnt = sn->rpcb_users;
spin_unlock(&rpcb_clnt_lock); spin_unlock(&sn->rpcb_clnt_lock);
return cnt; return cnt;
} }
void rpcb_put_local(void) void rpcb_put_local(void)
{ {
struct rpc_clnt *clnt = rpcb_local_clnt; struct sunrpc_net *sn = net_generic(&init_net, sunrpc_net_id);
struct rpc_clnt *clnt4 = rpcb_local_clnt4; struct rpc_clnt *clnt = sn->rpcb_local_clnt;
struct rpc_clnt *clnt4 = sn->rpcb_local_clnt4;
int shutdown; int shutdown;
spin_lock(&rpcb_clnt_lock); spin_lock(&sn->rpcb_clnt_lock);
if (--rpcb_users == 0) { if (--sn->rpcb_users == 0) {
rpcb_local_clnt = NULL; sn->rpcb_local_clnt = NULL;
rpcb_local_clnt4 = NULL; sn->rpcb_local_clnt4 = NULL;
} }
shutdown = !rpcb_users; shutdown = !sn->rpcb_users;
spin_unlock(&rpcb_clnt_lock); spin_unlock(&sn->rpcb_clnt_lock);
if (shutdown) { if (shutdown) {
/* /*
@ -204,14 +203,16 @@ void rpcb_put_local(void)
static void rpcb_set_local(struct rpc_clnt *clnt, struct rpc_clnt *clnt4) static void rpcb_set_local(struct rpc_clnt *clnt, struct rpc_clnt *clnt4)
{ {
struct sunrpc_net *sn = net_generic(&init_net, sunrpc_net_id);
/* Protected by rpcb_create_local_mutex */ /* Protected by rpcb_create_local_mutex */
rpcb_local_clnt = clnt; sn->rpcb_local_clnt = clnt;
rpcb_local_clnt4 = clnt4; sn->rpcb_local_clnt4 = clnt4;
smp_wmb(); smp_wmb();
rpcb_users = 1; sn->rpcb_users = 1;
dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: " dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: "
"%p, rpcb_local_clnt4: %p)\n", rpcb_local_clnt, "%p, rpcb_local_clnt4: %p)\n", sn->rpcb_local_clnt,
rpcb_local_clnt4); sn->rpcb_local_clnt4);
} }
/* /*
@ -431,6 +432,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port)
struct rpc_message msg = { struct rpc_message msg = {
.rpc_argp = &map, .rpc_argp = &map,
}; };
struct sunrpc_net *sn = net_generic(&init_net, sunrpc_net_id);
dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " dprintk("RPC: %sregistering (%u, %u, %d, %u) with local "
"rpcbind\n", (port ? "" : "un"), "rpcbind\n", (port ? "" : "un"),
@ -440,7 +442,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port)
if (port) if (port)
msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET];
return rpcb_register_call(rpcb_local_clnt, &msg); return rpcb_register_call(sn->rpcb_local_clnt, &msg);
} }
/* /*
@ -453,6 +455,7 @@ static int rpcb_register_inet4(const struct sockaddr *sap,
struct rpcbind_args *map = msg->rpc_argp; struct rpcbind_args *map = msg->rpc_argp;
unsigned short port = ntohs(sin->sin_port); unsigned short port = ntohs(sin->sin_port);
int result; int result;
struct sunrpc_net *sn = net_generic(&init_net, sunrpc_net_id);
map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL);
@ -465,7 +468,7 @@ static int rpcb_register_inet4(const struct sockaddr *sap,
if (port) if (port)
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
result = rpcb_register_call(rpcb_local_clnt4, msg); result = rpcb_register_call(sn->rpcb_local_clnt4, msg);
kfree(map->r_addr); kfree(map->r_addr);
return result; return result;
} }
@ -480,6 +483,7 @@ static int rpcb_register_inet6(const struct sockaddr *sap,
struct rpcbind_args *map = msg->rpc_argp; struct rpcbind_args *map = msg->rpc_argp;
unsigned short port = ntohs(sin6->sin6_port); unsigned short port = ntohs(sin6->sin6_port);
int result; int result;
struct sunrpc_net *sn = net_generic(&init_net, sunrpc_net_id);
map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL);
@ -492,7 +496,7 @@ static int rpcb_register_inet6(const struct sockaddr *sap,
if (port) if (port)
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
result = rpcb_register_call(rpcb_local_clnt4, msg); result = rpcb_register_call(sn->rpcb_local_clnt4, msg);
kfree(map->r_addr); kfree(map->r_addr);
return result; return result;
} }
@ -500,6 +504,7 @@ static int rpcb_register_inet6(const struct sockaddr *sap,
static int rpcb_unregister_all_protofamilies(struct rpc_message *msg) static int rpcb_unregister_all_protofamilies(struct rpc_message *msg)
{ {
struct rpcbind_args *map = msg->rpc_argp; struct rpcbind_args *map = msg->rpc_argp;
struct sunrpc_net *sn = net_generic(&init_net, sunrpc_net_id);
dprintk("RPC: unregistering [%u, %u, '%s'] with " dprintk("RPC: unregistering [%u, %u, '%s'] with "
"local rpcbind\n", "local rpcbind\n",
@ -508,7 +513,7 @@ static int rpcb_unregister_all_protofamilies(struct rpc_message *msg)
map->r_addr = ""; map->r_addr = "";
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
return rpcb_register_call(rpcb_local_clnt4, msg); return rpcb_register_call(sn->rpcb_local_clnt4, msg);
} }
/** /**
@ -566,8 +571,9 @@ int rpcb_v4_register(const u32 program, const u32 version,
struct rpc_message msg = { struct rpc_message msg = {
.rpc_argp = &map, .rpc_argp = &map,
}; };
struct sunrpc_net *sn = net_generic(&init_net, sunrpc_net_id);
if (rpcb_local_clnt4 == NULL) if (sn->rpcb_local_clnt4 == NULL)
return -EPROTONOSUPPORT; return -EPROTONOSUPPORT;
if (address == NULL) if (address == NULL)