aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd/svc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/lockd/svc.c')
-rw-r--r--fs/lockd/svc.c117
1 files changed, 102 insertions, 15 deletions
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index c061b9aa7ddb..2774e1013b34 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