From 4cb54ca2069903121e4c03ec427147c47bed5755 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Fri, 20 Jan 2012 16:50:53 +0400 Subject: SUNRPC: search for service transports in network namespace context Service transports are parametrized by network namespace. And thus lookup of transport instance have to take network namespace into account. Signed-off-by: Stanislav Kinsbursky Signed-off-by: Trond Myklebust Acked-by: J. Bruce Fields --- fs/lockd/svc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/lockd/svc.c') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index c061b9aa7dd..ff379ff7761 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -193,7 +193,7 @@ static int create_lockd_listener(struct svc_serv *serv, const char *name, { struct svc_xprt *xprt; - xprt = svc_find_xprt(serv, name, family, 0); + xprt = svc_find_xprt(serv, name, &init_net, family, 0); if (xprt == NULL) return svc_create_xprt(serv, name, &init_net, family, port, SVC_SOCK_DEFAULTS); -- cgit v1.2.3 From c228fa2038a33bb3b87f567482124f452e162a71 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Tue, 31 Jan 2012 15:07:48 +0400 Subject: Lockd: create permanent lockd sockets in current network namespace This patch parametrizes Lockd permanent sockets creation routine by network namespace context. It also replaces hard-coded init_net with current network namespace context in Lockd sockets creation routines. This approach looks safe, because Lockd is created during NFS mount (or NFS server start) and thus socket is required exactly in current network namespace context. But in the same time it means, that Lockd sockets inherits first Lockd requester network namespace. This issue will be fixed in further patches of the series. Signed-off-by: Stanislav Kinsbursky Signed-off-by: Trond Myklebust --- fs/lockd/svc.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'fs/lockd/svc.c') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index ff379ff7761..cba35984dde 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -189,27 +189,29 @@ lockd(void *vrqstp) } static int create_lockd_listener(struct svc_serv *serv, const char *name, - const int family, const unsigned short port) + struct net *net, const int family, + const unsigned short port) { struct svc_xprt *xprt; - xprt = svc_find_xprt(serv, name, &init_net, family, 0); + xprt = svc_find_xprt(serv, name, net, family, 0); if (xprt == NULL) - return svc_create_xprt(serv, name, &init_net, family, port, + return svc_create_xprt(serv, name, net, family, port, SVC_SOCK_DEFAULTS); svc_xprt_put(xprt); return 0; } -static int create_lockd_family(struct svc_serv *serv, const int family) +static int create_lockd_family(struct svc_serv *serv, struct net *net, + const int family) { int err; - err = create_lockd_listener(serv, "udp", family, nlm_udpport); + err = create_lockd_listener(serv, "udp", net, family, nlm_udpport); if (err < 0) return err; - return create_lockd_listener(serv, "tcp", family, nlm_tcpport); + return create_lockd_listener(serv, "tcp", net, family, nlm_tcpport); } /* @@ -222,16 +224,16 @@ static int create_lockd_family(struct svc_serv *serv, const int family) * Returns zero if all listeners are available; otherwise a * negative errno value is returned. */ -static int make_socks(struct svc_serv *serv) +static int make_socks(struct svc_serv *serv, struct net *net) { static int warned; int err; - err = create_lockd_family(serv, PF_INET); + err = create_lockd_family(serv, net, PF_INET); if (err < 0) goto out_err; - err = create_lockd_family(serv, PF_INET6); + err = create_lockd_family(serv, net, PF_INET6); if (err < 0 && err != -EAFNOSUPPORT) goto out_err; @@ -252,6 +254,7 @@ int lockd_up(void) { struct svc_serv *serv; int error = 0; + struct net *net = current->nsproxy->net_ns; mutex_lock(&nlmsvc_mutex); /* @@ -275,7 +278,7 @@ int lockd_up(void) goto out; } - error = make_socks(serv); + error = make_socks(serv, net); if (error < 0) goto destroy_and_out; -- cgit v1.2.3 From a9c5d73a8d8cb37601f8c39b35b9b4128e1a5254 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Tue, 31 Jan 2012 15:07:57 +0400 Subject: Lockd: pernet usage counter introduced Lockd is going to be shared between network namespaces - i.e. going to be able to handle lock requests from different network namespaces. This means, that network namespace related resources have to be allocated not once (like now), but for every network namespace context, from which service is requested to operate. This patch implements Lockd per-net users accounting. New per-net counter is used to determine, when per-net resources have to be freed. Signed-off-by: Stanislav Kinsbursky Signed-off-by: Trond Myklebust --- fs/lockd/svc.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) (limited to 'fs/lockd/svc.c') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index cba35984dde..73c9ebf0930 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -35,6 +35,8 @@ #include #include +#include "netns.h" + #define NLMDBG_FACILITY NLMDBG_SVC #define LOCKD_BUFSIZE (1024 + NLMSVC_XDRSIZE) #define ALLOWED_SIGS (sigmask(SIGKILL)) @@ -50,6 +52,8 @@ static struct task_struct *nlmsvc_task; static struct svc_rqst *nlmsvc_rqst; unsigned long nlmsvc_timeout; +int lockd_net_id; + /* * These can be set at insmod time (useful for NFS as root filesystem), * and also changed through the sysctl interface. -- Jamie Lokier, Aug 2003 @@ -316,8 +320,12 @@ int lockd_up(void) destroy_and_out: svc_destroy(serv); out: - if (!error) + if (!error) { + struct lockd_net *ln = net_generic(net, lockd_net_id); + + ln->nlmsvc_users++; nlmsvc_users++; + } mutex_unlock(&nlmsvc_mutex); return error; } @@ -500,24 +508,55 @@ module_param_call(nlm_tcpport, param_set_port, param_get_int, module_param(nsm_use_hostnames, bool, 0644); module_param(nlm_max_connections, uint, 0644); +static int lockd_init_net(struct net *net) +{ + return 0; +} + +static void lockd_exit_net(struct net *net) +{ +} + +static struct pernet_operations lockd_net_ops = { + .init = lockd_init_net, + .exit = lockd_exit_net, + .id = &lockd_net_id, + .size = sizeof(struct lockd_net), +}; + + /* * Initialising and terminating the module. */ static int __init init_nlm(void) { + int err; + #ifdef CONFIG_SYSCTL + err = -ENOMEM; nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root); - return nlm_sysctl_table ? 0 : -ENOMEM; -#else + if (nlm_sysctl_table == NULL) + goto err_sysctl; +#endif + err = register_pernet_subsys(&lockd_net_ops); + if (err) + goto err_pernet; return 0; + +err_pernet: +#ifdef CONFIG_SYSCTL + unregister_sysctl_table(nlm_sysctl_table); #endif +err_sysctl: + return err; } static void __exit exit_nlm(void) { /* FIXME: delete all NLM clients */ nlm_shutdown_hosts(); + unregister_pernet_subsys(&lockd_net_ops); #ifdef CONFIG_SYSCTL unregister_sysctl_table(nlm_sysctl_table); #endif -- cgit v1.2.3 From bb2224df5ffe4f864f5b696199b17db1ce77bc0a Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Tue, 31 Jan 2012 15:08:05 +0400 Subject: Lockd: per-net up and down routines introduced This patch introduces per-net Lockd initialization and destruction routines. The logic is the same as in global Lockd up and down routines. Probably the solution is not the best one. But at least it looks clear. So per-net "up" routine are called only in case of lockd is running already. If per-net resources are not allocated yet, then service is being registered with local portmapper and lockd sockets created. Per-net "down" routine is called on every lockd_down() call in case of global users counter is not zero. Signed-off-by: Stanislav Kinsbursky Signed-off-by: Trond Myklebust --- fs/lockd/svc.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) (limited to 'fs/lockd/svc.c') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 73c9ebf0930..90dec426bfd 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -251,6 +251,45 @@ out_err: return err; } +static int lockd_up_net(struct net *net) +{ + struct lockd_net *ln = net_generic(net, lockd_net_id); + struct svc_serv *serv = nlmsvc_rqst->rq_server; + int error; + + if (ln->nlmsvc_users) + return 0; + + error = svc_rpcb_setup(serv, net); + if (error) + goto err_rpcb; + + error = make_socks(serv, net); + if (error < 0) + goto err_socks; + return 0; + +err_socks: + svc_rpcb_cleanup(serv, net); +err_rpcb: + return error; +} + +static void lockd_down_net(struct net *net) +{ + struct lockd_net *ln = net_generic(net, lockd_net_id); + struct svc_serv *serv = nlmsvc_rqst->rq_server; + + if (ln->nlmsvc_users) { + if (--ln->nlmsvc_users == 0) + svc_shutdown_net(serv, net); + } else { + printk(KERN_ERR "lockd_down_net: no users! task=%p, net=%p\n", + nlmsvc_task, net); + BUG(); + } +} + /* * Bring up the lockd process if it's not already up. */ @@ -264,8 +303,10 @@ int lockd_up(void) /* * Check whether we're already up and running. */ - if (nlmsvc_rqst) + if (nlmsvc_rqst) { + error = lockd_up_net(net); goto out; + } /* * Sanity check: if there's no pid, @@ -339,8 +380,10 @@ lockd_down(void) { mutex_lock(&nlmsvc_mutex); if (nlmsvc_users) { - if (--nlmsvc_users) + if (--nlmsvc_users) { + lockd_down_net(current->nsproxy->net_ns); goto out; + } } else { printk(KERN_ERR "lockd_down: no users! task=%p\n", nlmsvc_task); -- cgit v1.2.3 From 3b64739fb928c34b13db6b5adcb0d3efb19e78be Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Tue, 31 Jan 2012 15:08:29 +0400 Subject: Lockd: shutdown NLM hosts in network namespace context Lockd now managed in network namespace context. And this patch introduces network namespace related NLM hosts shutdown in case of releasing per-net Lockd resources. Signed-off-by: Stanislav Kinsbursky Signed-off-by: Trond Myklebust --- fs/lockd/svc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'fs/lockd/svc.c') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 90dec426bfd..2774e1013b3 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -281,8 +281,10 @@ static void lockd_down_net(struct net *net) struct svc_serv *serv = nlmsvc_rqst->rq_server; if (ln->nlmsvc_users) { - if (--ln->nlmsvc_users == 0) + if (--ln->nlmsvc_users == 0) { + nlm_shutdown_hosts_net(net); svc_shutdown_net(serv, net); + } } else { printk(KERN_ERR "lockd_down_net: no users! task=%p, net=%p\n", nlmsvc_task, net); -- cgit v1.2.3 From de5b8e8e047534aac6bc9803f96e7257436aef9c Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 7 Feb 2012 15:35:42 +1100 Subject: lockd: fix arg parsing for grace_period and timeout. If you try to set grace_period or timeout via a module parameter to lockd, and do this on a big-endian machine where sizeof(int) != sizeof(unsigned long) it won't work. This number given will be effectively shifted right by the difference in those two sizes. So cast kp->arg properly to get correct result. Cc: stable@kernel.org Signed-off-by: NeilBrown Signed-off-by: J. Bruce Fields --- fs/lockd/svc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/lockd/svc.c') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index c061b9aa7dd..2444780f5cf 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -440,7 +440,7 @@ static int param_set_##name(const char *val, struct kernel_param *kp) \ __typeof__(type) num = which_strtol(val, &endp, 0); \ if (endp == val || *endp || num < (min) || num > (max)) \ return -EINVAL; \ - *((int *) kp->arg) = num; \ + *((type *) kp->arg) = num; \ return 0; \ } -- cgit v1.2.3 From e3f70eadb7dddfb5a2bb9afff7abfc6ee17a29d0 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Thu, 29 Mar 2012 18:54:33 +0400 Subject: Lockd: pass network namespace to creation and destruction routines v2: dereference of most probably already released nlm_host removed in nlmclnt_done() and reclaimer(). These routines are called from locks reclaimer() kernel thread. This thread works in "init_net" network context and currently relays on persence on lockd thread and it's per-net resources. Thus lockd_up() and lockd_down() can't relay on current network context. So let's pass corrent one into them. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields --- fs/lockd/svc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'fs/lockd/svc.c') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index f49b9afc443..1ead0750cdb 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -295,11 +295,10 @@ static void lockd_down_net(struct net *net) /* * Bring up the lockd process if it's not already up. */ -int lockd_up(void) +int lockd_up(struct net *net) { struct svc_serv *serv; int error = 0; - struct net *net = current->nsproxy->net_ns; mutex_lock(&nlmsvc_mutex); /* @@ -378,12 +377,12 @@ EXPORT_SYMBOL_GPL(lockd_up); * Decrement the user count and bring down lockd if we're the last. */ void -lockd_down(void) +lockd_down(struct net *net) { mutex_lock(&nlmsvc_mutex); if (nlmsvc_users) { if (--nlmsvc_users) { - lockd_down_net(current->nsproxy->net_ns); + lockd_down_net(net); goto out; } } else { -- cgit v1.2.3 From 9793f7c88937e7ac07305ab1af1a519225836823 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 2 May 2012 16:08:38 +0400 Subject: SUNRPC: new svc_bind() routine introduced This new routine is responsible for service registration in a specified network context. The idea is to separate service creation from per-net operations. Note also: since registering service with svc_bind() can fail, the service will be destroyed and during destruction it will try to unregister itself from rpcbind. In this case unregistration has to be skipped. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields --- fs/lockd/svc.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'fs/lockd/svc.c') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 1ead0750cdb..b7e92ed5688 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -324,6 +324,12 @@ int lockd_up(struct net *net) goto out; } + error = svc_bind(serv, net); + if (error < 0) { + printk(KERN_WARNING "lockd_up: bind service failed\n"); + goto destroy_and_out; + } + error = make_socks(serv, net); if (error < 0) goto destroy_and_out; -- cgit v1.2.3 From 786185b5f8abefa6a8a16695bb4a59c164d5a071 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Fri, 4 May 2012 12:49:41 +0400 Subject: SUNRPC: move per-net operations from svc_destroy() The idea is to separate service destruction and per-net operations, because these are two different things and the mix looks ugly. Notes: 1) For NFS server this patch looks ugly (sorry for that). But these place will be rewritten soon during NFSd containerization. 2) LockD per-net counter increase int lockd_up() was moved prior to make_socks() to make lockd_down_net() call safe in case of error. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields --- fs/lockd/svc.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'fs/lockd/svc.c') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index b7e92ed5688..3250f280a17 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -257,7 +257,7 @@ static int lockd_up_net(struct net *net) struct svc_serv *serv = nlmsvc_rqst->rq_server; int error; - if (ln->nlmsvc_users) + if (ln->nlmsvc_users++) return 0; error = svc_rpcb_setup(serv, net); @@ -272,6 +272,7 @@ static int lockd_up_net(struct net *net) err_socks: svc_rpcb_cleanup(serv, net); err_rpcb: + ln->nlmsvc_users--; return error; } @@ -299,6 +300,7 @@ int lockd_up(struct net *net) { struct svc_serv *serv; int error = 0; + struct lockd_net *ln = net_generic(net, lockd_net_id); mutex_lock(&nlmsvc_mutex); /* @@ -330,9 +332,11 @@ int lockd_up(struct net *net) goto destroy_and_out; } + ln->nlmsvc_users++; + error = make_socks(serv, net); if (error < 0) - goto destroy_and_out; + goto err_start; /* * Create the kernel thread and wait for it to start. @@ -344,7 +348,7 @@ int lockd_up(struct net *net) printk(KERN_WARNING "lockd_up: svc_rqst allocation failed, error=%d\n", error); - goto destroy_and_out; + goto err_start; } svc_sock_update_bufs(serv); @@ -358,7 +362,7 @@ int lockd_up(struct net *net) nlmsvc_rqst = NULL; printk(KERN_WARNING "lockd_up: kthread_run failed, error=%d\n", error); - goto destroy_and_out; + goto err_start; } /* @@ -368,14 +372,14 @@ int lockd_up(struct net *net) destroy_and_out: svc_destroy(serv); out: - if (!error) { - struct lockd_net *ln = net_generic(net, lockd_net_id); - - ln->nlmsvc_users++; + if (!error) nlmsvc_users++; - } mutex_unlock(&nlmsvc_mutex); return error; + +err_start: + lockd_down_net(net); + goto destroy_and_out; } EXPORT_SYMBOL_GPL(lockd_up); @@ -386,11 +390,10 @@ void lockd_down(struct net *net) { mutex_lock(&nlmsvc_mutex); + lockd_down_net(net); if (nlmsvc_users) { - if (--nlmsvc_users) { - lockd_down_net(net); + if (--nlmsvc_users) goto out; - } } else { printk(KERN_ERR "lockd_down: no users! task=%p\n", nlmsvc_task); -- cgit v1.2.3 From 4db77695bf5738bdafa83d1b58b64cbecc6f55e7 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 25 Apr 2012 18:22:40 +0400 Subject: LockD: pass service to per-net up and down functions Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields --- fs/lockd/svc.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'fs/lockd/svc.c') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 3250f280a17..58ddc38cfcc 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -251,10 +251,9 @@ out_err: return err; } -static int lockd_up_net(struct net *net) +static int lockd_up_net(struct svc_serv *serv, struct net *net) { struct lockd_net *ln = net_generic(net, lockd_net_id); - struct svc_serv *serv = nlmsvc_rqst->rq_server; int error; if (ln->nlmsvc_users++) @@ -276,10 +275,9 @@ err_rpcb: return error; } -static void lockd_down_net(struct net *net) +static void lockd_down_net(struct svc_serv *serv, struct net *net) { struct lockd_net *ln = net_generic(net, lockd_net_id); - struct svc_serv *serv = nlmsvc_rqst->rq_server; if (ln->nlmsvc_users) { if (--ln->nlmsvc_users == 0) { @@ -307,7 +305,7 @@ int lockd_up(struct net *net) * Check whether we're already up and running. */ if (nlmsvc_rqst) { - error = lockd_up_net(net); + error = lockd_up_net(nlmsvc_rqst->rq_server, net); goto out; } @@ -378,7 +376,7 @@ out: return error; err_start: - lockd_down_net(net); + lockd_down_net(serv, net); goto destroy_and_out; } EXPORT_SYMBOL_GPL(lockd_up); @@ -390,7 +388,7 @@ void lockd_down(struct net *net) { mutex_lock(&nlmsvc_mutex); - lockd_down_net(net); + lockd_down_net(nlmsvc_rqst->rq_server, net); if (nlmsvc_users) { if (--nlmsvc_users) goto out; -- cgit v1.2.3 From dbf9b5d74ceae787607e3d7db626fffa8be3c03d Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 25 Apr 2012 18:22:47 +0400 Subject: LockD: use existing per-net data function on service creation This patch also replaces svc_rpcb_setup() with svc_bind(). Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields --- fs/lockd/svc.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) (limited to 'fs/lockd/svc.c') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 58ddc38cfcc..71c6c3122d3 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -259,9 +259,9 @@ static int lockd_up_net(struct svc_serv *serv, struct net *net) if (ln->nlmsvc_users++) return 0; - error = svc_rpcb_setup(serv, net); + error = svc_bind(serv, net); if (error) - goto err_rpcb; + goto err_bind; error = make_socks(serv, net); if (error < 0) @@ -270,7 +270,7 @@ static int lockd_up_net(struct svc_serv *serv, struct net *net) err_socks: svc_rpcb_cleanup(serv, net); -err_rpcb: +err_bind: ln->nlmsvc_users--; return error; } @@ -298,7 +298,6 @@ int lockd_up(struct net *net) { struct svc_serv *serv; int error = 0; - struct lockd_net *ln = net_generic(net, lockd_net_id); mutex_lock(&nlmsvc_mutex); /* @@ -324,17 +323,9 @@ int lockd_up(struct net *net) goto out; } - error = svc_bind(serv, net); - if (error < 0) { - printk(KERN_WARNING "lockd_up: bind service failed\n"); - goto destroy_and_out; - } - - ln->nlmsvc_users++; - - error = make_socks(serv, net); + error = lockd_up_net(serv, net); if (error < 0) - goto err_start; + goto err_net; /* * Create the kernel thread and wait for it to start. @@ -367,7 +358,7 @@ int lockd_up(struct net *net) * Note: svc_serv structures have an initial use count of 1, * so we exit through here on both success and failure. */ -destroy_and_out: +err_net: svc_destroy(serv); out: if (!error) @@ -377,7 +368,7 @@ out: err_start: lockd_down_net(serv, net); - goto destroy_and_out; + goto err_net; } EXPORT_SYMBOL_GPL(lockd_up); -- cgit v1.2.3 From 24452239094a8b52f54fd4403f6e177837cecf67 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 25 Apr 2012 18:22:54 +0400 Subject: LockD: service creation function introduced This function creates service if it doesn't exist, or increases usage counter if it does, and returns a pointer to it. The usage counter will be droppepd by svc_destroy() later in lockd_up(). Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields --- fs/lockd/svc.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) (limited to 'fs/lockd/svc.c') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 71c6c3122d3..ad11ea77758 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -291,21 +291,20 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net) } } -/* - * Bring up the lockd process if it's not already up. - */ -int lockd_up(struct net *net) +static struct svc_serv *lockd_create_svc(void) { struct svc_serv *serv; - int error = 0; - mutex_lock(&nlmsvc_mutex); /* * Check whether we're already up and running. */ if (nlmsvc_rqst) { - error = lockd_up_net(nlmsvc_rqst->rq_server, net); - goto out; + /* + * Note: increase service usage, because later in case of error + * svc_destroy() will be called. + */ + svc_get(nlmsvc_rqst->rq_server); + return nlmsvc_rqst->rq_server; } /* @@ -316,11 +315,28 @@ int lockd_up(struct net *net) printk(KERN_WARNING "lockd_up: no pid, %d users??\n", nlmsvc_users); - error = -ENOMEM; serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL); if (!serv) { printk(KERN_WARNING "lockd_up: create service failed\n"); - goto out; + return ERR_PTR(-ENOMEM); + } + return serv; +} + +/* + * Bring up the lockd process if it's not already up. + */ +int lockd_up(struct net *net) +{ + struct svc_serv *serv; + int error = 0; + + mutex_lock(&nlmsvc_mutex); + + serv = lockd_create_svc(); + if (IS_ERR(serv)) { + error = PTR_ERR(serv); + goto err_create; } error = lockd_up_net(serv, net); @@ -360,9 +376,9 @@ int lockd_up(struct net *net) */ err_net: svc_destroy(serv); -out: if (!error) nlmsvc_users++; +err_create: mutex_unlock(&nlmsvc_mutex); return error; -- cgit v1.2.3 From 7d13ec761ae45d5e401965c73d855840ff8cdd23 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 25 Apr 2012 18:23:02 +0400 Subject: LockD: move global usage counter manipulation from error path Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields --- fs/lockd/svc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'fs/lockd/svc.c') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index ad11ea77758..53cd69ef2ad 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -329,7 +329,7 @@ static struct svc_serv *lockd_create_svc(void) int lockd_up(struct net *net) { struct svc_serv *serv; - int error = 0; + int error; mutex_lock(&nlmsvc_mutex); @@ -370,14 +370,13 @@ int lockd_up(struct net *net) goto err_start; } + nlmsvc_users++; /* * Note: svc_serv structures have an initial use count of 1, * so we exit through here on both success and failure. */ err_net: svc_destroy(serv); - if (!error) - nlmsvc_users++; err_create: mutex_unlock(&nlmsvc_mutex); return error; -- cgit v1.2.3 From 3d1221dfa95ca876535c5947626f3834343e8fbc Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 25 Apr 2012 18:23:09 +0400 Subject: LockD: service start function introduced This is just a code move, which from my POV makes the code look better. I.e. now on start we have 3 different stages: 1) Service creation. 2) Service per-net data allocation. 3) Service start. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields --- fs/lockd/svc.c | 67 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 25 deletions(-) (limited to 'fs/lockd/svc.c') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 53cd69ef2ad..b47bf775500 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -291,6 +291,46 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net) } } +static int lockd_start_svc(struct svc_serv *serv) +{ + int error; + + if (nlmsvc_rqst) + return 0; + + /* + * Create the kernel thread and wait for it to start. + */ + nlmsvc_rqst = svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE); + if (IS_ERR(nlmsvc_rqst)) { + error = PTR_ERR(nlmsvc_rqst); + printk(KERN_WARNING + "lockd_up: svc_rqst allocation failed, error=%d\n", + error); + goto out_rqst; + } + + svc_sock_update_bufs(serv); + serv->sv_maxconn = nlm_max_connections; + + nlmsvc_task = kthread_run(lockd, nlmsvc_rqst, serv->sv_name); + if (IS_ERR(nlmsvc_task)) { + error = PTR_ERR(nlmsvc_task); + printk(KERN_WARNING + "lockd_up: kthread_run failed, error=%d\n", error); + goto out_task; + } + dprintk("lockd_up: service started\n"); + return 0; + +out_task: + svc_exit_thread(nlmsvc_rqst); + nlmsvc_task = NULL; +out_rqst: + nlmsvc_rqst = NULL; + return error; +} + static struct svc_serv *lockd_create_svc(void) { struct svc_serv *serv; @@ -343,32 +383,9 @@ int lockd_up(struct net *net) if (error < 0) goto err_net; - /* - * Create the kernel thread and wait for it to start. - */ - nlmsvc_rqst = svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE); - if (IS_ERR(nlmsvc_rqst)) { - error = PTR_ERR(nlmsvc_rqst); - nlmsvc_rqst = NULL; - printk(KERN_WARNING - "lockd_up: svc_rqst allocation failed, error=%d\n", - error); - goto err_start; - } - - svc_sock_update_bufs(serv); - serv->sv_maxconn = nlm_max_connections; - - nlmsvc_task = kthread_run(lockd, nlmsvc_rqst, serv->sv_name); - if (IS_ERR(nlmsvc_task)) { - error = PTR_ERR(nlmsvc_task); - svc_exit_thread(nlmsvc_rqst); - nlmsvc_task = NULL; - nlmsvc_rqst = NULL; - printk(KERN_WARNING - "lockd_up: kthread_run failed, error=%d\n", error); + error = lockd_start_svc(serv); + if (error < 0) goto err_start; - } nlmsvc_users++; /* -- cgit v1.2.3 From 8dbf28e495337b0c66657e3e278ae0ff175b7140 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 25 Apr 2012 18:23:16 +0400 Subject: LockD: add debug message to start and stop functions Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields --- fs/lockd/svc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'fs/lockd/svc.c') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index b47bf775500..80938fda67e 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -266,6 +266,7 @@ static int lockd_up_net(struct svc_serv *serv, struct net *net) error = make_socks(serv, net); if (error < 0) goto err_socks; + dprintk("lockd_up_net: per-net data created; net=%p\n", net); return 0; err_socks: @@ -283,6 +284,7 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net) if (--ln->nlmsvc_users == 0) { nlm_shutdown_hosts_net(net); svc_shutdown_net(serv, net); + dprintk("lockd_down_net: per-net data destroyed; net=%p\n", net); } } else { printk(KERN_ERR "lockd_down_net: no users! task=%p, net=%p\n", @@ -360,6 +362,7 @@ static struct svc_serv *lockd_create_svc(void) printk(KERN_WARNING "lockd_up: create service failed\n"); return ERR_PTR(-ENOMEM); } + dprintk("lockd_up: service created\n"); return serv; } @@ -426,7 +429,9 @@ lockd_down(struct net *net) BUG(); } kthread_stop(nlmsvc_task); + dprintk("lockd_down: service stopped\n"); svc_exit_thread(nlmsvc_rqst); + dprintk("lockd_down: service destroyed\n"); nlmsvc_task = NULL; nlmsvc_rqst = NULL; out: -- cgit v1.2.3