aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2012-03-21 16:42:14 -0400
committerJ. Bruce Fields <bfields@redhat.com>2012-03-26 11:48:54 -0400
commit1df00640c9111c881633d9b219f18e66c52599ec (patch)
treee36d3924d84f47ec93f6650ff1fd5b8ea7d10d24 /fs/lockd
parentab4684d1560f8d77f6ce82bd3f1f82937070d397 (diff)
parent5a7c9eec9fde1da0e3adf0a4ddb64ff2a324a492 (diff)
Merge nfs containerization work from Trond's tree
The nfs containerization work is a prerequisite for Jeff Layton's reboot recovery rework.
Diffstat (limited to 'fs/lockd')
-rw-r--r--fs/lockd/clnt4xdr.c2
-rw-r--r--fs/lockd/clntlock.c3
-rw-r--r--fs/lockd/clntxdr.c8
-rw-r--r--fs/lockd/host.c42
-rw-r--r--fs/lockd/mon.c21
-rw-r--r--fs/lockd/netns.h12
-rw-r--r--fs/lockd/svc.c117
-rw-r--r--fs/lockd/svclock.c59
8 files changed, 194 insertions, 70 deletions
diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c
index f848b52c67b1..3ddcbb1c0a43 100644
--- a/fs/lockd/clnt4xdr.c
+++ b/fs/lockd/clnt4xdr.c
@@ -598,7 +598,7 @@ static struct rpc_procinfo nlm4_procedures[] = {
598 PROC(GRANTED_RES, res, norep), 598 PROC(GRANTED_RES, res, norep),
599}; 599};
600 600
601struct rpc_version nlm_version4 = { 601const struct rpc_version nlm_version4 = {
602 .number = 4, 602 .number = 4,
603 .nrprocs = ARRAY_SIZE(nlm4_procedures), 603 .nrprocs = ARRAY_SIZE(nlm4_procedures),
604 .procs = nlm4_procedures, 604 .procs = nlm4_procedures,
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index 8d4ea8351e3d..ba1dc2eebd1e 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -62,7 +62,8 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init)
62 62
63 host = nlmclnt_lookup_host(nlm_init->address, nlm_init->addrlen, 63 host = nlmclnt_lookup_host(nlm_init->address, nlm_init->addrlen,
64 nlm_init->protocol, nlm_version, 64 nlm_init->protocol, nlm_version,
65 nlm_init->hostname, nlm_init->noresvport); 65 nlm_init->hostname, nlm_init->noresvport,
66 nlm_init->net);
66 if (host == NULL) { 67 if (host == NULL) {
67 lockd_down(); 68 lockd_down();
68 return ERR_PTR(-ENOLCK); 69 return ERR_PTR(-ENOLCK);
diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c
index 180ac34feb9a..3d35e3e80c1c 100644
--- a/fs/lockd/clntxdr.c
+++ b/fs/lockd/clntxdr.c
@@ -596,19 +596,19 @@ static struct rpc_procinfo nlm_procedures[] = {
596 PROC(GRANTED_RES, res, norep), 596 PROC(GRANTED_RES, res, norep),
597}; 597};
598 598
599static struct rpc_version nlm_version1 = { 599static const struct rpc_version nlm_version1 = {
600 .number = 1, 600 .number = 1,
601 .nrprocs = ARRAY_SIZE(nlm_procedures), 601 .nrprocs = ARRAY_SIZE(nlm_procedures),
602 .procs = nlm_procedures, 602 .procs = nlm_procedures,
603}; 603};
604 604
605static struct rpc_version nlm_version3 = { 605static const struct rpc_version nlm_version3 = {
606 .number = 3, 606 .number = 3,
607 .nrprocs = ARRAY_SIZE(nlm_procedures), 607 .nrprocs = ARRAY_SIZE(nlm_procedures),
608 .procs = nlm_procedures, 608 .procs = nlm_procedures,
609}; 609};
610 610
611static struct rpc_version *nlm_versions[] = { 611static const struct rpc_version *nlm_versions[] = {
612 [1] = &nlm_version1, 612 [1] = &nlm_version1,
613 [3] = &nlm_version3, 613 [3] = &nlm_version3,
614#ifdef CONFIG_LOCKD_V4 614#ifdef CONFIG_LOCKD_V4
@@ -618,7 +618,7 @@ static struct rpc_version *nlm_versions[] = {
618 618
619static struct rpc_stat nlm_rpc_stats; 619static struct rpc_stat nlm_rpc_stats;
620 620
621struct rpc_program nlm_program = { 621const struct rpc_program nlm_program = {
622 .name = "lockd", 622 .name = "lockd",
623 .number = NLM_PROGRAM, 623 .number = NLM_PROGRAM,
624 .nrvers = ARRAY_SIZE(nlm_versions), 624 .nrvers = ARRAY_SIZE(nlm_versions),
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 6f29836ec0cb..eb75ca7c2d6e 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -17,6 +17,8 @@
17#include <linux/lockd/lockd.h> 17#include <linux/lockd/lockd.h>
18#include <linux/mutex.h> 18#include <linux/mutex.h>
19 19
20#include <linux/sunrpc/svc_xprt.h>
21
20#include <net/ipv6.h> 22#include <net/ipv6.h>
21 23
22#define NLMDBG_FACILITY NLMDBG_HOSTCACHE 24#define NLMDBG_FACILITY NLMDBG_HOSTCACHE
@@ -54,6 +56,7 @@ struct nlm_lookup_host_info {
54 const char *hostname; /* remote's hostname */ 56 const char *hostname; /* remote's hostname */
55 const size_t hostname_len; /* it's length */ 57 const size_t hostname_len; /* it's length */
56 const int noresvport; /* use non-priv port */ 58 const int noresvport; /* use non-priv port */
59 struct net *net; /* network namespace to bind */
57}; 60};
58 61
59/* 62/*
@@ -155,6 +158,7 @@ static struct nlm_host *nlm_alloc_host(struct nlm_lookup_host_info *ni,
155 INIT_LIST_HEAD(&host->h_reclaim); 158 INIT_LIST_HEAD(&host->h_reclaim);
156 host->h_nsmhandle = nsm; 159 host->h_nsmhandle = nsm;
157 host->h_addrbuf = nsm->sm_addrbuf; 160 host->h_addrbuf = nsm->sm_addrbuf;
161 host->net = ni->net;
158 162
159out: 163out:
160 return host; 164 return host;
@@ -206,7 +210,8 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
206 const unsigned short protocol, 210 const unsigned short protocol,
207 const u32 version, 211 const u32 version,
208 const char *hostname, 212 const char *hostname,
209 int noresvport) 213 int noresvport,
214 struct net *net)
210{ 215{
211 struct nlm_lookup_host_info ni = { 216 struct nlm_lookup_host_info ni = {
212 .server = 0, 217 .server = 0,
@@ -217,6 +222,7 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
217 .hostname = hostname, 222 .hostname = hostname,
218 .hostname_len = strlen(hostname), 223 .hostname_len = strlen(hostname),
219 .noresvport = noresvport, 224 .noresvport = noresvport,
225 .net = net,
220 }; 226 };
221 struct hlist_head *chain; 227 struct hlist_head *chain;
222 struct hlist_node *pos; 228 struct hlist_node *pos;
@@ -231,6 +237,8 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
231 237
232 chain = &nlm_client_hosts[nlm_hash_address(sap)]; 238 chain = &nlm_client_hosts[nlm_hash_address(sap)];
233 hlist_for_each_entry(host, pos, chain, h_hash) { 239 hlist_for_each_entry(host, pos, chain, h_hash) {
240 if (host->net != net)
241 continue;
234 if (!rpc_cmp_addr(nlm_addr(host), sap)) 242 if (!rpc_cmp_addr(nlm_addr(host), sap))
235 continue; 243 continue;
236 244
@@ -318,6 +326,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
318 struct nsm_handle *nsm = NULL; 326 struct nsm_handle *nsm = NULL;
319 struct sockaddr *src_sap = svc_daddr(rqstp); 327 struct sockaddr *src_sap = svc_daddr(rqstp);
320 size_t src_len = rqstp->rq_daddrlen; 328 size_t src_len = rqstp->rq_daddrlen;
329 struct net *net = rqstp->rq_xprt->xpt_net;
321 struct nlm_lookup_host_info ni = { 330 struct nlm_lookup_host_info ni = {
322 .server = 1, 331 .server = 1,
323 .sap = svc_addr(rqstp), 332 .sap = svc_addr(rqstp),
@@ -326,6 +335,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
326 .version = rqstp->rq_vers, 335 .version = rqstp->rq_vers,
327 .hostname = hostname, 336 .hostname = hostname,
328 .hostname_len = hostname_len, 337 .hostname_len = hostname_len,
338 .net = net,
329 }; 339 };
330 340
331 dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__, 341 dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__,
@@ -339,6 +349,8 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
339 349
340 chain = &nlm_server_hosts[nlm_hash_address(ni.sap)]; 350 chain = &nlm_server_hosts[nlm_hash_address(ni.sap)];
341 hlist_for_each_entry(host, pos, chain, h_hash) { 351 hlist_for_each_entry(host, pos, chain, h_hash) {
352 if (host->net != net)
353 continue;
342 if (!rpc_cmp_addr(nlm_addr(host), ni.sap)) 354 if (!rpc_cmp_addr(nlm_addr(host), ni.sap))
343 continue; 355 continue;
344 356
@@ -431,7 +443,7 @@ nlm_bind_host(struct nlm_host *host)
431 .to_retries = 5U, 443 .to_retries = 5U,
432 }; 444 };
433 struct rpc_create_args args = { 445 struct rpc_create_args args = {
434 .net = &init_net, 446 .net = host->net,
435 .protocol = host->h_proto, 447 .protocol = host->h_proto,
436 .address = nlm_addr(host), 448 .address = nlm_addr(host),
437 .addrsize = host->h_addrlen, 449 .addrsize = host->h_addrlen,
@@ -553,12 +565,8 @@ void nlm_host_rebooted(const struct nlm_reboot *info)
553 nsm_release(nsm); 565 nsm_release(nsm);
554} 566}
555 567
556/*
557 * Shut down the hosts module.
558 * Note that this routine is called only at server shutdown time.
559 */
560void 568void
561nlm_shutdown_hosts(void) 569nlm_shutdown_hosts_net(struct net *net)
562{ 570{
563 struct hlist_head *chain; 571 struct hlist_head *chain;
564 struct hlist_node *pos; 572 struct hlist_node *pos;
@@ -570,6 +578,8 @@ nlm_shutdown_hosts(void)
570 /* First, make all hosts eligible for gc */ 578 /* First, make all hosts eligible for gc */
571 dprintk("lockd: nuking all hosts...\n"); 579 dprintk("lockd: nuking all hosts...\n");
572 for_each_host(host, pos, chain, nlm_server_hosts) { 580 for_each_host(host, pos, chain, nlm_server_hosts) {
581 if (net && host->net != net)
582 continue;
573 host->h_expires = jiffies - 1; 583 host->h_expires = jiffies - 1;
574 if (host->h_rpcclnt) { 584 if (host->h_rpcclnt) {
575 rpc_shutdown_client(host->h_rpcclnt); 585 rpc_shutdown_client(host->h_rpcclnt);
@@ -580,15 +590,29 @@ nlm_shutdown_hosts(void)
580 /* Then, perform a garbage collection pass */ 590 /* Then, perform a garbage collection pass */
581 nlm_gc_hosts(); 591 nlm_gc_hosts();
582 mutex_unlock(&nlm_host_mutex); 592 mutex_unlock(&nlm_host_mutex);
593}
594
595/*
596 * Shut down the hosts module.
597 * Note that this routine is called only at server shutdown time.
598 */
599void
600nlm_shutdown_hosts(void)
601{
602 struct hlist_head *chain;
603 struct hlist_node *pos;
604 struct nlm_host *host;
605
606 nlm_shutdown_hosts_net(NULL);
583 607
584 /* complain if any hosts are left */ 608 /* complain if any hosts are left */
585 if (nrhosts != 0) { 609 if (nrhosts != 0) {
586 printk(KERN_WARNING "lockd: couldn't shutdown host module!\n"); 610 printk(KERN_WARNING "lockd: couldn't shutdown host module!\n");
587 dprintk("lockd: %lu hosts left:\n", nrhosts); 611 dprintk("lockd: %lu hosts left:\n", nrhosts);
588 for_each_host(host, pos, chain, nlm_server_hosts) { 612 for_each_host(host, pos, chain, nlm_server_hosts) {
589 dprintk(" %s (cnt %d use %d exp %ld)\n", 613 dprintk(" %s (cnt %d use %d exp %ld net %p)\n",
590 host->h_name, atomic_read(&host->h_count), 614 host->h_name, atomic_read(&host->h_count),
591 host->h_inuse, host->h_expires); 615 host->h_inuse, host->h_expires, host->net);
592 } 616 }
593 } 617 }
594} 618}
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 65ba36b80a9e..7ef14b3c5bee 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -47,7 +47,7 @@ struct nsm_res {
47 u32 state; 47 u32 state;
48}; 48};
49 49
50static struct rpc_program nsm_program; 50static const struct rpc_program nsm_program;
51static LIST_HEAD(nsm_handles); 51static LIST_HEAD(nsm_handles);
52static DEFINE_SPINLOCK(nsm_lock); 52static DEFINE_SPINLOCK(nsm_lock);
53 53
@@ -62,14 +62,14 @@ static inline struct sockaddr *nsm_addr(const struct nsm_handle *nsm)
62 return (struct sockaddr *)&nsm->sm_addr; 62 return (struct sockaddr *)&nsm->sm_addr;
63} 63}
64 64
65static struct rpc_clnt *nsm_create(void) 65static struct rpc_clnt *nsm_create(struct net *net)
66{ 66{
67 struct sockaddr_in sin = { 67 struct sockaddr_in sin = {
68 .sin_family = AF_INET, 68 .sin_family = AF_INET,
69 .sin_addr.s_addr = htonl(INADDR_LOOPBACK), 69 .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
70 }; 70 };
71 struct rpc_create_args args = { 71 struct rpc_create_args args = {
72 .net = &init_net, 72 .net = net,
73 .protocol = XPRT_TRANSPORT_UDP, 73 .protocol = XPRT_TRANSPORT_UDP,
74 .address = (struct sockaddr *)&sin, 74 .address = (struct sockaddr *)&sin,
75 .addrsize = sizeof(sin), 75 .addrsize = sizeof(sin),
@@ -83,7 +83,8 @@ static struct rpc_clnt *nsm_create(void)
83 return rpc_create(&args); 83 return rpc_create(&args);
84} 84}
85 85
86static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res) 86static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
87 struct net *net)
87{ 88{
88 struct rpc_clnt *clnt; 89 struct rpc_clnt *clnt;
89 int status; 90 int status;
@@ -99,7 +100,7 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
99 .rpc_resp = res, 100 .rpc_resp = res,
100 }; 101 };
101 102
102 clnt = nsm_create(); 103 clnt = nsm_create(net);
103 if (IS_ERR(clnt)) { 104 if (IS_ERR(clnt)) {
104 status = PTR_ERR(clnt); 105 status = PTR_ERR(clnt);
105 dprintk("lockd: failed to create NSM upcall transport, " 106 dprintk("lockd: failed to create NSM upcall transport, "
@@ -149,7 +150,7 @@ int nsm_monitor(const struct nlm_host *host)
149 */ 150 */
150 nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf; 151 nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
151 152
152 status = nsm_mon_unmon(nsm, NSMPROC_MON, &res); 153 status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, host->net);
153 if (unlikely(res.status != 0)) 154 if (unlikely(res.status != 0))
154 status = -EIO; 155 status = -EIO;
155 if (unlikely(status < 0)) { 156 if (unlikely(status < 0)) {
@@ -183,7 +184,7 @@ void nsm_unmonitor(const struct nlm_host *host)
183 && nsm->sm_monitored && !nsm->sm_sticky) { 184 && nsm->sm_monitored && !nsm->sm_sticky) {
184 dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name); 185 dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
185 186
186 status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res); 187 status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, host->net);
187 if (res.status != 0) 188 if (res.status != 0)
188 status = -EIO; 189 status = -EIO;
189 if (status < 0) 190 if (status < 0)
@@ -534,19 +535,19 @@ static struct rpc_procinfo nsm_procedures[] = {
534 }, 535 },
535}; 536};
536 537
537static struct rpc_version nsm_version1 = { 538static const struct rpc_version nsm_version1 = {
538 .number = 1, 539 .number = 1,
539 .nrprocs = ARRAY_SIZE(nsm_procedures), 540 .nrprocs = ARRAY_SIZE(nsm_procedures),
540 .procs = nsm_procedures 541 .procs = nsm_procedures
541}; 542};
542 543
543static struct rpc_version * nsm_version[] = { 544static const struct rpc_version *nsm_version[] = {
544 [1] = &nsm_version1, 545 [1] = &nsm_version1,
545}; 546};
546 547
547static struct rpc_stat nsm_stats; 548static struct rpc_stat nsm_stats;
548 549
549static struct rpc_program nsm_program = { 550static const struct rpc_program nsm_program = {
550 .name = "statd", 551 .name = "statd",
551 .number = NSM_PROGRAM, 552 .number = NSM_PROGRAM,
552 .nrvers = ARRAY_SIZE(nsm_version), 553 .nrvers = ARRAY_SIZE(nsm_version),
diff --git a/fs/lockd/netns.h b/fs/lockd/netns.h
new file mode 100644
index 000000000000..ce227e0fbc5c
--- /dev/null
+++ b/fs/lockd/netns.h
@@ -0,0 +1,12 @@
1#ifndef __LOCKD_NETNS_H__
2#define __LOCKD_NETNS_H__
3
4#include <net/netns/generic.h>
5
6struct lockd_net {
7 unsigned int nlmsvc_users;
8};
9
10extern int lockd_net_id;
11
12#endif
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 2444780f5cfa..f49b9afc4436 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -35,6 +35,8 @@
35#include <linux/lockd/lockd.h> 35#include <linux/lockd/lockd.h>
36#include <linux/nfs.h> 36#include <linux/nfs.h>
37 37
38#include "netns.h"
39
38#define NLMDBG_FACILITY NLMDBG_SVC 40#define NLMDBG_FACILITY NLMDBG_SVC
39#define LOCKD_BUFSIZE (1024 + NLMSVC_XDRSIZE) 41#define LOCKD_BUFSIZE (1024 + NLMSVC_XDRSIZE)
40#define ALLOWED_SIGS (sigmask(SIGKILL)) 42#define ALLOWED_SIGS (sigmask(SIGKILL))
@@ -50,6 +52,8 @@ static struct task_struct *nlmsvc_task;
50static struct svc_rqst *nlmsvc_rqst; 52static struct svc_rqst *nlmsvc_rqst;
51unsigned long nlmsvc_timeout; 53unsigned long nlmsvc_timeout;
52 54
55int lockd_net_id;
56
53/* 57/*
54 * These can be set at insmod time (useful for NFS as root filesystem), 58 * These can be set at insmod time (useful for NFS as root filesystem),
55 * and also changed through the sysctl interface. -- Jamie Lokier, Aug 2003 59 * and also changed through the sysctl interface. -- Jamie Lokier, Aug 2003
@@ -189,27 +193,29 @@ lockd(void *vrqstp)
189} 193}
190 194
191static int create_lockd_listener(struct svc_serv *serv, const char *name, 195static int create_lockd_listener(struct svc_serv *serv, const char *name,
192 const int family, const unsigned short port) 196 struct net *net, const int family,
197 const unsigned short port)
193{ 198{
194 struct svc_xprt *xprt; 199 struct svc_xprt *xprt;
195 200
196 xprt = svc_find_xprt(serv, name, family, 0); 201 xprt = svc_find_xprt(serv, name, net, family, 0);
197 if (xprt == NULL) 202 if (xprt == NULL)
198 return svc_create_xprt(serv, name, &init_net, family, port, 203 return svc_create_xprt(serv, name, net, family, port,
199 SVC_SOCK_DEFAULTS); 204 SVC_SOCK_DEFAULTS);
200 svc_xprt_put(xprt); 205 svc_xprt_put(xprt);
201 return 0; 206 return 0;
202} 207}
203 208
204static int create_lockd_family(struct svc_serv *serv, const int family) 209static int create_lockd_family(struct svc_serv *serv, struct net *net,
210 const int family)
205{ 211{
206 int err; 212 int err;
207 213
208 err = create_lockd_listener(serv, "udp", family, nlm_udpport); 214 err = create_lockd_listener(serv, "udp", net, family, nlm_udpport);
209 if (err < 0) 215 if (err < 0)
210 return err; 216 return err;
211 217
212 return create_lockd_listener(serv, "tcp", family, nlm_tcpport); 218 return create_lockd_listener(serv, "tcp", net, family, nlm_tcpport);
213} 219}
214 220
215/* 221/*
@@ -222,16 +228,16 @@ static int create_lockd_family(struct svc_serv *serv, const int family)
222 * Returns zero if all listeners are available; otherwise a 228 * Returns zero if all listeners are available; otherwise a
223 * negative errno value is returned. 229 * negative errno value is returned.
224 */ 230 */
225static int make_socks(struct svc_serv *serv) 231static int make_socks(struct svc_serv *serv, struct net *net)
226{ 232{
227 static int warned; 233 static int warned;
228 int err; 234 int err;
229 235
230 err = create_lockd_family(serv, PF_INET); 236 err = create_lockd_family(serv, net, PF_INET);
231 if (err < 0) 237 if (err < 0)
232 goto out_err; 238 goto out_err;
233 239
234 err = create_lockd_family(serv, PF_INET6); 240 err = create_lockd_family(serv, net, PF_INET6);
235 if (err < 0 && err != -EAFNOSUPPORT) 241 if (err < 0 && err != -EAFNOSUPPORT)
236 goto out_err; 242 goto out_err;
237 243
@@ -245,6 +251,47 @@ out_err:
245 return err; 251 return err;
246} 252}
247 253
254static int lockd_up_net(struct net *net)
255{
256 struct lockd_net *ln = net_generic(net, lockd_net_id);
257 struct svc_serv *serv = nlmsvc_rqst->rq_server;
258 int error;
259
260 if (ln->nlmsvc_users)
261 return 0;
262
263 error = svc_rpcb_setup(serv, net);
264 if (error)
265 goto err_rpcb;
266
267 error = make_socks(serv, net);
268 if (error < 0)
269 goto err_socks;
270 return 0;
271
272err_socks:
273 svc_rpcb_cleanup(serv, net);
274err_rpcb:
275 return error;
276}
277
278static void lockd_down_net(struct net *net)
279{
280 struct lockd_net *ln = net_generic(net, lockd_net_id);
281 struct svc_serv *serv = nlmsvc_rqst->rq_server;
282
283 if (ln->nlmsvc_users) {
284 if (--ln->nlmsvc_users == 0) {
285 nlm_shutdown_hosts_net(net);
286 svc_shutdown_net(serv, net);
287 }
288 } else {
289 printk(KERN_ERR "lockd_down_net: no users! task=%p, net=%p\n",
290 nlmsvc_task, net);
291 BUG();
292 }
293}
294
248/* 295/*
249 * Bring up the lockd process if it's not already up. 296 * Bring up the lockd process if it's not already up.
250 */ 297 */
@@ -252,13 +299,16 @@ int lockd_up(void)
252{ 299{
253 struct svc_serv *serv; 300 struct svc_serv *serv;
254 int error = 0; 301 int error = 0;
302 struct net *net = current->nsproxy->net_ns;
255 303
256 mutex_lock(&nlmsvc_mutex); 304 mutex_lock(&nlmsvc_mutex);
257 /* 305 /*
258 * Check whether we're already up and running. 306 * Check whether we're already up and running.
259 */ 307 */
260 if (nlmsvc_rqst) 308 if (nlmsvc_rqst) {
309 error = lockd_up_net(net);
261 goto out; 310 goto out;
311 }
262 312
263 /* 313 /*
264 * Sanity check: if there's no pid, 314 * Sanity check: if there's no pid,
@@ -275,7 +325,7 @@ int lockd_up(void)
275 goto out; 325 goto out;
276 } 326 }
277 327
278 error = make_socks(serv); 328 error = make_socks(serv, net);
279 if (error < 0) 329 if (error < 0)
280 goto destroy_and_out; 330 goto destroy_and_out;
281 331
@@ -313,8 +363,12 @@ int lockd_up(void)
313destroy_and_out: 363destroy_and_out:
314 svc_destroy(serv); 364 svc_destroy(serv);
315out: 365out:
316 if (!error) 366 if (!error) {
367 struct lockd_net *ln = net_generic(net, lockd_net_id);
368
369 ln->nlmsvc_users++;
317 nlmsvc_users++; 370 nlmsvc_users++;
371 }
318 mutex_unlock(&nlmsvc_mutex); 372 mutex_unlock(&nlmsvc_mutex);
319 return error; 373 return error;
320} 374}
@@ -328,8 +382,10 @@ lockd_down(void)
328{ 382{
329 mutex_lock(&nlmsvc_mutex); 383 mutex_lock(&nlmsvc_mutex);
330 if (nlmsvc_users) { 384 if (nlmsvc_users) {
331 if (--nlmsvc_users) 385 if (--nlmsvc_users) {
386 lockd_down_net(current->nsproxy->net_ns);
332 goto out; 387 goto out;
388 }
333 } else { 389 } else {
334 printk(KERN_ERR "lockd_down: no users! task=%p\n", 390 printk(KERN_ERR "lockd_down: no users! task=%p\n",
335 nlmsvc_task); 391 nlmsvc_task);
@@ -497,24 +553,55 @@ module_param_call(nlm_tcpport, param_set_port, param_get_int,
497module_param(nsm_use_hostnames, bool, 0644); 553module_param(nsm_use_hostnames, bool, 0644);
498module_param(nlm_max_connections, uint, 0644); 554module_param(nlm_max_connections, uint, 0644);
499 555
556static int lockd_init_net(struct net *net)
557{
558 return 0;
559}
560
561static void lockd_exit_net(struct net *net)
562{
563}
564
565static struct pernet_operations lockd_net_ops = {
566 .init = lockd_init_net,
567 .exit = lockd_exit_net,
568 .id = &lockd_net_id,
569 .size = sizeof(struct lockd_net),
570};
571
572
500/* 573/*
501 * Initialising and terminating the module. 574 * Initialising and terminating the module.
502 */ 575 */
503 576
504static int __init init_nlm(void) 577static int __init init_nlm(void)
505{ 578{
579 int err;
580
506#ifdef CONFIG_SYSCTL 581#ifdef CONFIG_SYSCTL
582 err = -ENOMEM;
507 nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root); 583 nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root);
508 return nlm_sysctl_table ? 0 : -ENOMEM; 584 if (nlm_sysctl_table == NULL)
509#else 585 goto err_sysctl;
586#endif
587 err = register_pernet_subsys(&lockd_net_ops);
588 if (err)
589 goto err_pernet;
510 return 0; 590 return 0;
591
592err_pernet:
593#ifdef CONFIG_SYSCTL
594 unregister_sysctl_table(nlm_sysctl_table);
511#endif 595#endif
596err_sysctl:
597 return err;
512} 598}
513 599
514static void __exit exit_nlm(void) 600static void __exit exit_nlm(void)
515{ 601{
516 /* FIXME: delete all NLM clients */ 602 /* FIXME: delete all NLM clients */
517 nlm_shutdown_hosts(); 603 nlm_shutdown_hosts();
604 unregister_pernet_subsys(&lockd_net_ops);
518#ifdef CONFIG_SYSCTL 605#ifdef CONFIG_SYSCTL
519 unregister_sysctl_table(nlm_sysctl_table); 606 unregister_sysctl_table(nlm_sysctl_table);
520#endif 607#endif
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index f0179c3745d2..e46353f41a42 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -46,7 +46,6 @@ static void nlmsvc_remove_block(struct nlm_block *block);
46static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock); 46static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock);
47static void nlmsvc_freegrantargs(struct nlm_rqst *call); 47static void nlmsvc_freegrantargs(struct nlm_rqst *call);
48static const struct rpc_call_ops nlmsvc_grant_ops; 48static const struct rpc_call_ops nlmsvc_grant_ops;
49static const char *nlmdbg_cookie2a(const struct nlm_cookie *cookie);
50 49
51/* 50/*
52 * The list of blocked locks to retry 51 * The list of blocked locks to retry
@@ -54,6 +53,35 @@ static const char *nlmdbg_cookie2a(const struct nlm_cookie *cookie);
54static LIST_HEAD(nlm_blocked); 53static LIST_HEAD(nlm_blocked);
55static DEFINE_SPINLOCK(nlm_blocked_lock); 54static DEFINE_SPINLOCK(nlm_blocked_lock);
56 55
56#ifdef LOCKD_DEBUG
57static const char *nlmdbg_cookie2a(const struct nlm_cookie *cookie)
58{
59 /*
60 * We can get away with a static buffer because we're only
61 * called with BKL held.
62 */
63 static char buf[2*NLM_MAXCOOKIELEN+1];
64 unsigned int i, len = sizeof(buf);
65 char *p = buf;
66
67 len--; /* allow for trailing \0 */
68 if (len < 3)
69 return "???";
70 for (i = 0 ; i < cookie->len ; i++) {
71 if (len < 2) {
72 strcpy(p-3, "...");
73 break;
74 }
75 sprintf(p, "%02x", cookie->data[i]);
76 p += 2;
77 len -= 2;
78 }
79 *p = '\0';
80
81 return buf;
82}
83#endif
84
57/* 85/*
58 * Insert a blocked lock into the global list 86 * Insert a blocked lock into the global list
59 */ 87 */
@@ -935,32 +963,3 @@ nlmsvc_retry_blocked(void)
935 963
936 return timeout; 964 return timeout;
937} 965}
938
939#ifdef RPC_DEBUG
940static const char *nlmdbg_cookie2a(const struct nlm_cookie *cookie)
941{
942 /*
943 * We can get away with a static buffer because we're only
944 * called with BKL held.
945 */
946 static char buf[2*NLM_MAXCOOKIELEN+1];
947 unsigned int i, len = sizeof(buf);
948 char *p = buf;
949
950 len--; /* allow for trailing \0 */
951 if (len < 3)
952 return "???";
953 for (i = 0 ; i < cookie->len ; i++) {
954 if (len < 2) {
955 strcpy(p-3, "...");
956 break;
957 }
958 sprintf(p, "%02x", cookie->data[i]);
959 p += 2;
960 len -= 2;
961 }
962 *p = '\0';
963
964 return buf;
965}
966#endif