aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /fs/lockd
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'fs/lockd')
-rw-r--r--fs/lockd/clnt4xdr.c12
-rw-r--r--fs/lockd/clntlock.c16
-rw-r--r--fs/lockd/clntproc.c17
-rw-r--r--fs/lockd/clntxdr.c20
-rw-r--r--fs/lockd/grace.c16
-rw-r--r--fs/lockd/host.c158
-rw-r--r--fs/lockd/mon.c109
-rw-r--r--fs/lockd/netns.h23
-rw-r--r--fs/lockd/svc.c284
-rw-r--r--fs/lockd/svc4proc.c14
-rw-r--r--fs/lockd/svclock.c79
-rw-r--r--fs/lockd/svcproc.c19
-rw-r--r--fs/lockd/svcsubs.c21
13 files changed, 279 insertions, 509 deletions
diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c
index 00ec0b9c94d..f848b52c67b 100644
--- a/fs/lockd/clnt4xdr.c
+++ b/fs/lockd/clnt4xdr.c
@@ -64,6 +64,10 @@ static void nlm4_compute_offsets(const struct nlm_lock *lock,
64{ 64{
65 const struct file_lock *fl = &lock->fl; 65 const struct file_lock *fl = &lock->fl;
66 66
67 BUG_ON(fl->fl_start > NLM4_OFFSET_MAX);
68 BUG_ON(fl->fl_end > NLM4_OFFSET_MAX &&
69 fl->fl_end != OFFSET_MAX);
70
67 *l_offset = loff_t_to_s64(fl->fl_start); 71 *l_offset = loff_t_to_s64(fl->fl_start);
68 if (fl->fl_end == OFFSET_MAX) 72 if (fl->fl_end == OFFSET_MAX)
69 *l_len = 0; 73 *l_len = 0;
@@ -118,6 +122,7 @@ static void encode_netobj(struct xdr_stream *xdr,
118{ 122{
119 __be32 *p; 123 __be32 *p;
120 124
125 BUG_ON(length > XDR_MAX_NETOBJ);
121 p = xdr_reserve_space(xdr, 4 + length); 126 p = xdr_reserve_space(xdr, 4 + length);
122 xdr_encode_opaque(p, data, length); 127 xdr_encode_opaque(p, data, length);
123} 128}
@@ -151,6 +156,7 @@ out_overflow:
151static void encode_cookie(struct xdr_stream *xdr, 156static void encode_cookie(struct xdr_stream *xdr,
152 const struct nlm_cookie *cookie) 157 const struct nlm_cookie *cookie)
153{ 158{
159 BUG_ON(cookie->len > NLM_MAXCOOKIELEN);
154 encode_netobj(xdr, (u8 *)&cookie->data, cookie->len); 160 encode_netobj(xdr, (u8 *)&cookie->data, cookie->len);
155} 161}
156 162
@@ -192,6 +198,7 @@ out_overflow:
192 */ 198 */
193static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh) 199static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh)
194{ 200{
201 BUG_ON(fh->size > NFS3_FHSIZE);
195 encode_netobj(xdr, (u8 *)&fh->data, fh->size); 202 encode_netobj(xdr, (u8 *)&fh->data, fh->size);
196} 203}
197 204
@@ -234,7 +241,7 @@ static int decode_nlm4_stat(struct xdr_stream *xdr, __be32 *stat)
234 p = xdr_inline_decode(xdr, 4); 241 p = xdr_inline_decode(xdr, 4);
235 if (unlikely(p == NULL)) 242 if (unlikely(p == NULL))
236 goto out_overflow; 243 goto out_overflow;
237 if (unlikely(ntohl(*p) > ntohl(nlm4_failed))) 244 if (unlikely(*p > nlm4_failed))
238 goto out_bad_xdr; 245 goto out_bad_xdr;
239 *stat = *p; 246 *stat = *p;
240 return 0; 247 return 0;
@@ -329,6 +336,7 @@ static void encode_caller_name(struct xdr_stream *xdr, const char *name)
329 u32 length = strlen(name); 336 u32 length = strlen(name);
330 __be32 *p; 337 __be32 *p;
331 338
339 BUG_ON(length > NLM_MAXSTRLEN);
332 p = xdr_reserve_space(xdr, 4 + length); 340 p = xdr_reserve_space(xdr, 4 + length);
333 xdr_encode_opaque(p, name, length); 341 xdr_encode_opaque(p, name, length);
334} 342}
@@ -590,7 +598,7 @@ static struct rpc_procinfo nlm4_procedures[] = {
590 PROC(GRANTED_RES, res, norep), 598 PROC(GRANTED_RES, res, norep),
591}; 599};
592 600
593const struct rpc_version nlm_version4 = { 601struct rpc_version nlm_version4 = {
594 .number = 4, 602 .number = 4,
595 .nrprocs = ARRAY_SIZE(nlm4_procedures), 603 .nrprocs = ARRAY_SIZE(nlm4_procedures),
596 .procs = nlm4_procedures, 604 .procs = nlm4_procedures,
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index ca0a0800144..8d4ea8351e3 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -56,16 +56,15 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init)
56 u32 nlm_version = (nlm_init->nfs_version == 2) ? 1 : 4; 56 u32 nlm_version = (nlm_init->nfs_version == 2) ? 1 : 4;
57 int status; 57 int status;
58 58
59 status = lockd_up(nlm_init->net); 59 status = lockd_up();
60 if (status < 0) 60 if (status < 0)
61 return ERR_PTR(status); 61 return ERR_PTR(status);
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);
67 if (host == NULL) { 66 if (host == NULL) {
68 lockd_down(nlm_init->net); 67 lockd_down();
69 return ERR_PTR(-ENOLCK); 68 return ERR_PTR(-ENOLCK);
70 } 69 }
71 70
@@ -80,10 +79,8 @@ EXPORT_SYMBOL_GPL(nlmclnt_init);
80 */ 79 */
81void nlmclnt_done(struct nlm_host *host) 80void nlmclnt_done(struct nlm_host *host)
82{ 81{
83 struct net *net = host->net;
84
85 nlmclnt_release_host(host); 82 nlmclnt_release_host(host);
86 lockd_down(net); 83 lockd_down();
87} 84}
88EXPORT_SYMBOL_GPL(nlmclnt_done); 85EXPORT_SYMBOL_GPL(nlmclnt_done);
89 86
@@ -222,12 +219,11 @@ reclaimer(void *ptr)
222 struct nlm_wait *block; 219 struct nlm_wait *block;
223 struct file_lock *fl, *next; 220 struct file_lock *fl, *next;
224 u32 nsmstate; 221 u32 nsmstate;
225 struct net *net = host->net;
226 222
227 allow_signal(SIGKILL); 223 allow_signal(SIGKILL);
228 224
229 down_write(&host->h_rwsem); 225 down_write(&host->h_rwsem);
230 lockd_up(net); /* note: this cannot fail as lockd is already running */ 226 lockd_up(); /* note: this cannot fail as lockd is already running */
231 227
232 dprintk("lockd: reclaiming locks for host %s\n", host->h_name); 228 dprintk("lockd: reclaiming locks for host %s\n", host->h_name);
233 229
@@ -278,6 +274,6 @@ restart:
278 274
279 /* Release host handle after use */ 275 /* Release host handle after use */
280 nlmclnt_release_host(host); 276 nlmclnt_release_host(host);
281 lockd_down(net); 277 lockd_down();
282 return 0; 278 return 0;
283} 279}
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 54f9e6ce043..8392cb85bd5 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -141,7 +141,7 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
141 141
142static void nlmclnt_release_lockargs(struct nlm_rqst *req) 142static void nlmclnt_release_lockargs(struct nlm_rqst *req)
143{ 143{
144 WARN_ON_ONCE(req->a_args.lock.fl.fl_ops != NULL); 144 BUG_ON(req->a_args.lock.fl.fl_ops != NULL);
145} 145}
146 146
147/** 147/**
@@ -156,16 +156,12 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
156 struct nlm_rqst *call; 156 struct nlm_rqst *call;
157 int status; 157 int status;
158 158
159 nlm_get_host(host);
159 call = nlm_alloc_call(host); 160 call = nlm_alloc_call(host);
160 if (call == NULL) 161 if (call == NULL)
161 return -ENOMEM; 162 return -ENOMEM;
162 163
163 nlmclnt_locks_init_private(fl, host); 164 nlmclnt_locks_init_private(fl, host);
164 if (!fl->fl_u.nfs_fl.owner) {
165 /* lockowner allocation has failed */
166 nlmclnt_release_call(call);
167 return -ENOMEM;
168 }
169 /* Set up the argument struct */ 165 /* Set up the argument struct */
170 nlmclnt_setlockargs(call, fl); 166 nlmclnt_setlockargs(call, fl);
171 167
@@ -189,6 +185,9 @@ EXPORT_SYMBOL_GPL(nlmclnt_proc);
189 185
190/* 186/*
191 * Allocate an NLM RPC call struct 187 * Allocate an NLM RPC call struct
188 *
189 * Note: the caller must hold a reference to host. In case of failure,
190 * this reference will be released.
192 */ 191 */
193struct nlm_rqst *nlm_alloc_call(struct nlm_host *host) 192struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
194{ 193{
@@ -200,7 +199,7 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
200 atomic_set(&call->a_count, 1); 199 atomic_set(&call->a_count, 1);
201 locks_init_lock(&call->a_args.lock.fl); 200 locks_init_lock(&call->a_args.lock.fl);
202 locks_init_lock(&call->a_res.lock.fl); 201 locks_init_lock(&call->a_res.lock.fl);
203 call->a_host = nlm_get_host(host); 202 call->a_host = host;
204 return call; 203 return call;
205 } 204 }
206 if (signalled()) 205 if (signalled())
@@ -208,6 +207,7 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
208 printk("nlm_alloc_call: failed, waiting for memory\n"); 207 printk("nlm_alloc_call: failed, waiting for memory\n");
209 schedule_timeout_interruptible(5*HZ); 208 schedule_timeout_interruptible(5*HZ);
210 } 209 }
210 nlmclnt_release_host(host);
211 return NULL; 211 return NULL;
212} 212}
213 213
@@ -465,6 +465,7 @@ static const struct file_lock_operations nlmclnt_lock_ops = {
465 465
466static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host) 466static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host)
467{ 467{
468 BUG_ON(fl->fl_ops != NULL);
468 fl->fl_u.nfs_fl.state = 0; 469 fl->fl_u.nfs_fl.state = 0;
469 fl->fl_u.nfs_fl.owner = nlm_find_lockowner(host, fl->fl_owner); 470 fl->fl_u.nfs_fl.owner = nlm_find_lockowner(host, fl->fl_owner);
470 INIT_LIST_HEAD(&fl->fl_u.nfs_fl.list); 471 INIT_LIST_HEAD(&fl->fl_u.nfs_fl.list);
@@ -749,7 +750,7 @@ static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl
749 dprintk("lockd: blocking lock attempt was interrupted by a signal.\n" 750 dprintk("lockd: blocking lock attempt was interrupted by a signal.\n"
750 " Attempting to cancel lock.\n"); 751 " Attempting to cancel lock.\n");
751 752
752 req = nlm_alloc_call(host); 753 req = nlm_alloc_call(nlm_get_host(host));
753 if (!req) 754 if (!req)
754 return -ENOMEM; 755 return -ENOMEM;
755 req->a_flags = RPC_TASK_ASYNC; 756 req->a_flags = RPC_TASK_ASYNC;
diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c
index 9a55797a1cd..180ac34feb9 100644
--- a/fs/lockd/clntxdr.c
+++ b/fs/lockd/clntxdr.c
@@ -60,6 +60,10 @@ static void nlm_compute_offsets(const struct nlm_lock *lock,
60{ 60{
61 const struct file_lock *fl = &lock->fl; 61 const struct file_lock *fl = &lock->fl;
62 62
63 BUG_ON(fl->fl_start > NLM_OFFSET_MAX);
64 BUG_ON(fl->fl_end > NLM_OFFSET_MAX &&
65 fl->fl_end != OFFSET_MAX);
66
63 *l_offset = loff_t_to_s32(fl->fl_start); 67 *l_offset = loff_t_to_s32(fl->fl_start);
64 if (fl->fl_end == OFFSET_MAX) 68 if (fl->fl_end == OFFSET_MAX)
65 *l_len = 0; 69 *l_len = 0;
@@ -115,6 +119,7 @@ static void encode_netobj(struct xdr_stream *xdr,
115{ 119{
116 __be32 *p; 120 __be32 *p;
117 121
122 BUG_ON(length > XDR_MAX_NETOBJ);
118 p = xdr_reserve_space(xdr, 4 + length); 123 p = xdr_reserve_space(xdr, 4 + length);
119 xdr_encode_opaque(p, data, length); 124 xdr_encode_opaque(p, data, length);
120} 125}
@@ -148,6 +153,7 @@ out_overflow:
148static void encode_cookie(struct xdr_stream *xdr, 153static void encode_cookie(struct xdr_stream *xdr,
149 const struct nlm_cookie *cookie) 154 const struct nlm_cookie *cookie)
150{ 155{
156 BUG_ON(cookie->len > NLM_MAXCOOKIELEN);
151 encode_netobj(xdr, (u8 *)&cookie->data, cookie->len); 157 encode_netobj(xdr, (u8 *)&cookie->data, cookie->len);
152} 158}
153 159
@@ -189,6 +195,7 @@ out_overflow:
189 */ 195 */
190static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh) 196static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh)
191{ 197{
198 BUG_ON(fh->size != NFS2_FHSIZE);
192 encode_netobj(xdr, (u8 *)&fh->data, NFS2_FHSIZE); 199 encode_netobj(xdr, (u8 *)&fh->data, NFS2_FHSIZE);
193} 200}
194 201
@@ -216,7 +223,7 @@ static void encode_nlm_stat(struct xdr_stream *xdr,
216{ 223{
217 __be32 *p; 224 __be32 *p;
218 225
219 WARN_ON_ONCE(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD); 226 BUG_ON(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD);
220 p = xdr_reserve_space(xdr, 4); 227 p = xdr_reserve_space(xdr, 4);
221 *p = stat; 228 *p = stat;
222} 229}
@@ -229,7 +236,7 @@ static int decode_nlm_stat(struct xdr_stream *xdr,
229 p = xdr_inline_decode(xdr, 4); 236 p = xdr_inline_decode(xdr, 4);
230 if (unlikely(p == NULL)) 237 if (unlikely(p == NULL))
231 goto out_overflow; 238 goto out_overflow;
232 if (unlikely(ntohl(*p) > ntohl(nlm_lck_denied_grace_period))) 239 if (unlikely(*p > nlm_lck_denied_grace_period))
233 goto out_enum; 240 goto out_enum;
234 *stat = *p; 241 *stat = *p;
235 return 0; 242 return 0;
@@ -323,6 +330,7 @@ static void encode_caller_name(struct xdr_stream *xdr, const char *name)
323 u32 length = strlen(name); 330 u32 length = strlen(name);
324 __be32 *p; 331 __be32 *p;
325 332
333 BUG_ON(length > NLM_MAXSTRLEN);
326 p = xdr_reserve_space(xdr, 4 + length); 334 p = xdr_reserve_space(xdr, 4 + length);
327 xdr_encode_opaque(p, name, length); 335 xdr_encode_opaque(p, name, length);
328} 336}
@@ -588,19 +596,19 @@ static struct rpc_procinfo nlm_procedures[] = {
588 PROC(GRANTED_RES, res, norep), 596 PROC(GRANTED_RES, res, norep),
589}; 597};
590 598
591static const struct rpc_version nlm_version1 = { 599static struct rpc_version nlm_version1 = {
592 .number = 1, 600 .number = 1,
593 .nrprocs = ARRAY_SIZE(nlm_procedures), 601 .nrprocs = ARRAY_SIZE(nlm_procedures),
594 .procs = nlm_procedures, 602 .procs = nlm_procedures,
595}; 603};
596 604
597static const struct rpc_version nlm_version3 = { 605static struct rpc_version nlm_version3 = {
598 .number = 3, 606 .number = 3,
599 .nrprocs = ARRAY_SIZE(nlm_procedures), 607 .nrprocs = ARRAY_SIZE(nlm_procedures),
600 .procs = nlm_procedures, 608 .procs = nlm_procedures,
601}; 609};
602 610
603static const struct rpc_version *nlm_versions[] = { 611static struct rpc_version *nlm_versions[] = {
604 [1] = &nlm_version1, 612 [1] = &nlm_version1,
605 [3] = &nlm_version3, 613 [3] = &nlm_version3,
606#ifdef CONFIG_LOCKD_V4 614#ifdef CONFIG_LOCKD_V4
@@ -610,7 +618,7 @@ static const struct rpc_version *nlm_versions[] = {
610 618
611static struct rpc_stat nlm_rpc_stats; 619static struct rpc_stat nlm_rpc_stats;
612 620
613const struct rpc_program nlm_program = { 621struct rpc_program nlm_program = {
614 .name = "lockd", 622 .name = "lockd",
615 .number = NLM_PROGRAM, 623 .number = NLM_PROGRAM,
616 .nrvers = ARRAY_SIZE(nlm_versions), 624 .nrvers = ARRAY_SIZE(nlm_versions),
diff --git a/fs/lockd/grace.c b/fs/lockd/grace.c
index 6d1ee7204c8..183cc1f0af1 100644
--- a/fs/lockd/grace.c
+++ b/fs/lockd/grace.c
@@ -4,10 +4,8 @@
4 4
5#include <linux/module.h> 5#include <linux/module.h>
6#include <linux/lockd/bind.h> 6#include <linux/lockd/bind.h>
7#include <net/net_namespace.h>
8
9#include "netns.h"
10 7
8static LIST_HEAD(grace_list);
11static DEFINE_SPINLOCK(grace_lock); 9static DEFINE_SPINLOCK(grace_lock);
12 10
13/** 11/**
@@ -21,12 +19,10 @@ static DEFINE_SPINLOCK(grace_lock);
21 * 19 *
22 * This function is called to start a grace period. 20 * This function is called to start a grace period.
23 */ 21 */
24void locks_start_grace(struct net *net, struct lock_manager *lm) 22void locks_start_grace(struct lock_manager *lm)
25{ 23{
26 struct lockd_net *ln = net_generic(net, lockd_net_id);
27
28 spin_lock(&grace_lock); 24 spin_lock(&grace_lock);
29 list_add(&lm->list, &ln->grace_list); 25 list_add(&lm->list, &grace_list);
30 spin_unlock(&grace_lock); 26 spin_unlock(&grace_lock);
31} 27}
32EXPORT_SYMBOL_GPL(locks_start_grace); 28EXPORT_SYMBOL_GPL(locks_start_grace);
@@ -56,10 +52,8 @@ EXPORT_SYMBOL_GPL(locks_end_grace);
56 * to answer ordinary lock requests, and when they should accept only 52 * to answer ordinary lock requests, and when they should accept only
57 * lock reclaims. 53 * lock reclaims.
58 */ 54 */
59int locks_in_grace(struct net *net) 55int locks_in_grace(void)
60{ 56{
61 struct lockd_net *ln = net_generic(net, lockd_net_id); 57 return !list_empty(&grace_list);
62
63 return !list_empty(&ln->grace_list);
64} 58}
65EXPORT_SYMBOL_GPL(locks_in_grace); 59EXPORT_SYMBOL_GPL(locks_in_grace);
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 0e17090c310..b7c99bfb3da 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -17,12 +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
22#include <net/ipv6.h> 20#include <net/ipv6.h>
23 21
24#include "netns.h"
25
26#define NLMDBG_FACILITY NLMDBG_HOSTCACHE 22#define NLMDBG_FACILITY NLMDBG_HOSTCACHE
27#define NLM_HOST_NRHASH 32 23#define NLM_HOST_NRHASH 32
28#define NLM_HOST_REBIND (60 * HZ) 24#define NLM_HOST_REBIND (60 * HZ)
@@ -43,10 +39,11 @@ static struct hlist_head nlm_client_hosts[NLM_HOST_NRHASH];
43 hlist_for_each_entry_safe((host), (pos), (next), \ 39 hlist_for_each_entry_safe((host), (pos), (next), \
44 (chain), h_hash) 40 (chain), h_hash)
45 41
42static unsigned long next_gc;
46static unsigned long nrhosts; 43static unsigned long nrhosts;
47static DEFINE_MUTEX(nlm_host_mutex); 44static DEFINE_MUTEX(nlm_host_mutex);
48 45
49static void nlm_gc_hosts(struct net *net); 46static void nlm_gc_hosts(void);
50 47
51struct nlm_lookup_host_info { 48struct nlm_lookup_host_info {
52 const int server; /* search for server|client */ 49 const int server; /* search for server|client */
@@ -57,7 +54,6 @@ struct nlm_lookup_host_info {
57 const char *hostname; /* remote's hostname */ 54 const char *hostname; /* remote's hostname */
58 const size_t hostname_len; /* it's length */ 55 const size_t hostname_len; /* it's length */
59 const int noresvport; /* use non-priv port */ 56 const int noresvport; /* use non-priv port */
60 struct net *net; /* network namespace to bind */
61}; 57};
62 58
63/* 59/*
@@ -159,7 +155,6 @@ static struct nlm_host *nlm_alloc_host(struct nlm_lookup_host_info *ni,
159 INIT_LIST_HEAD(&host->h_reclaim); 155 INIT_LIST_HEAD(&host->h_reclaim);
160 host->h_nsmhandle = nsm; 156 host->h_nsmhandle = nsm;
161 host->h_addrbuf = nsm->sm_addrbuf; 157 host->h_addrbuf = nsm->sm_addrbuf;
162 host->net = ni->net;
163 158
164out: 159out:
165 return host; 160 return host;
@@ -173,10 +168,12 @@ out:
173static void nlm_destroy_host_locked(struct nlm_host *host) 168static void nlm_destroy_host_locked(struct nlm_host *host)
174{ 169{
175 struct rpc_clnt *clnt; 170 struct rpc_clnt *clnt;
176 struct lockd_net *ln = net_generic(host->net, lockd_net_id);
177 171
178 dprintk("lockd: destroy host %s\n", host->h_name); 172 dprintk("lockd: destroy host %s\n", host->h_name);
179 173
174 BUG_ON(!list_empty(&host->h_lockowners));
175 BUG_ON(atomic_read(&host->h_count));
176
180 hlist_del_init(&host->h_hash); 177 hlist_del_init(&host->h_hash);
181 178
182 nsm_unmonitor(host); 179 nsm_unmonitor(host);
@@ -187,7 +184,6 @@ static void nlm_destroy_host_locked(struct nlm_host *host)
187 rpc_shutdown_client(clnt); 184 rpc_shutdown_client(clnt);
188 kfree(host); 185 kfree(host);
189 186
190 ln->nrhosts--;
191 nrhosts--; 187 nrhosts--;
192} 188}
193 189
@@ -210,8 +206,7 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
210 const unsigned short protocol, 206 const unsigned short protocol,
211 const u32 version, 207 const u32 version,
212 const char *hostname, 208 const char *hostname,
213 int noresvport, 209 int noresvport)
214 struct net *net)
215{ 210{
216 struct nlm_lookup_host_info ni = { 211 struct nlm_lookup_host_info ni = {
217 .server = 0, 212 .server = 0,
@@ -222,13 +217,11 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
222 .hostname = hostname, 217 .hostname = hostname,
223 .hostname_len = strlen(hostname), 218 .hostname_len = strlen(hostname),
224 .noresvport = noresvport, 219 .noresvport = noresvport,
225 .net = net,
226 }; 220 };
227 struct hlist_head *chain; 221 struct hlist_head *chain;
228 struct hlist_node *pos; 222 struct hlist_node *pos;
229 struct nlm_host *host; 223 struct nlm_host *host;
230 struct nsm_handle *nsm = NULL; 224 struct nsm_handle *nsm = NULL;
231 struct lockd_net *ln = net_generic(net, lockd_net_id);
232 225
233 dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__, 226 dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__,
234 (hostname ? hostname : "<none>"), version, 227 (hostname ? hostname : "<none>"), version,
@@ -238,8 +231,6 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
238 231
239 chain = &nlm_client_hosts[nlm_hash_address(sap)]; 232 chain = &nlm_client_hosts[nlm_hash_address(sap)];
240 hlist_for_each_entry(host, pos, chain, h_hash) { 233 hlist_for_each_entry(host, pos, chain, h_hash) {
241 if (host->net != net)
242 continue;
243 if (!rpc_cmp_addr(nlm_addr(host), sap)) 234 if (!rpc_cmp_addr(nlm_addr(host), sap))
244 continue; 235 continue;
245 236
@@ -263,7 +254,6 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
263 goto out; 254 goto out;
264 255
265 hlist_add_head(&host->h_hash, chain); 256 hlist_add_head(&host->h_hash, chain);
266 ln->nrhosts++;
267 nrhosts++; 257 nrhosts++;
268 258
269 dprintk("lockd: %s created host %s (%s)\n", __func__, 259 dprintk("lockd: %s created host %s (%s)\n", __func__,
@@ -286,12 +276,13 @@ void nlmclnt_release_host(struct nlm_host *host)
286 276
287 dprintk("lockd: release client host %s\n", host->h_name); 277 dprintk("lockd: release client host %s\n", host->h_name);
288 278
289 WARN_ON_ONCE(host->h_server); 279 BUG_ON(atomic_read(&host->h_count) < 0);
280 BUG_ON(host->h_server);
290 281
291 if (atomic_dec_and_test(&host->h_count)) { 282 if (atomic_dec_and_test(&host->h_count)) {
292 WARN_ON_ONCE(!list_empty(&host->h_lockowners)); 283 BUG_ON(!list_empty(&host->h_lockowners));
293 WARN_ON_ONCE(!list_empty(&host->h_granted)); 284 BUG_ON(!list_empty(&host->h_granted));
294 WARN_ON_ONCE(!list_empty(&host->h_reclaim)); 285 BUG_ON(!list_empty(&host->h_reclaim));
295 286
296 mutex_lock(&nlm_host_mutex); 287 mutex_lock(&nlm_host_mutex);
297 nlm_destroy_host_locked(host); 288 nlm_destroy_host_locked(host);
@@ -325,9 +316,14 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
325 struct hlist_node *pos; 316 struct hlist_node *pos;
326 struct nlm_host *host = NULL; 317 struct nlm_host *host = NULL;
327 struct nsm_handle *nsm = NULL; 318 struct nsm_handle *nsm = NULL;
328 struct sockaddr *src_sap = svc_daddr(rqstp); 319 struct sockaddr_in sin = {
329 size_t src_len = rqstp->rq_daddrlen; 320 .sin_family = AF_INET,
330 struct net *net = SVC_NET(rqstp); 321 };
322 struct sockaddr_in6 sin6 = {
323 .sin6_family = AF_INET6,
324 };
325 struct sockaddr *src_sap;
326 size_t src_len = rqstp->rq_addrlen;
331 struct nlm_lookup_host_info ni = { 327 struct nlm_lookup_host_info ni = {
332 .server = 1, 328 .server = 1,
333 .sap = svc_addr(rqstp), 329 .sap = svc_addr(rqstp),
@@ -336,9 +332,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
336 .version = rqstp->rq_vers, 332 .version = rqstp->rq_vers,
337 .hostname = hostname, 333 .hostname = hostname,
338 .hostname_len = hostname_len, 334 .hostname_len = hostname_len,
339 .net = net,
340 }; 335 };
341 struct lockd_net *ln = net_generic(net, lockd_net_id);
342 336
343 dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__, 337 dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__,
344 (int)hostname_len, hostname, rqstp->rq_vers, 338 (int)hostname_len, hostname, rqstp->rq_vers,
@@ -346,13 +340,26 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
346 340
347 mutex_lock(&nlm_host_mutex); 341 mutex_lock(&nlm_host_mutex);
348 342
349 if (time_after_eq(jiffies, ln->next_gc)) 343 switch (ni.sap->sa_family) {
350 nlm_gc_hosts(net); 344 case AF_INET:
345 sin.sin_addr.s_addr = rqstp->rq_daddr.addr.s_addr;
346 src_sap = (struct sockaddr *)&sin;
347 break;
348 case AF_INET6:
349 ipv6_addr_copy(&sin6.sin6_addr, &rqstp->rq_daddr.addr6);
350 src_sap = (struct sockaddr *)&sin6;
351 break;
352 default:
353 dprintk("lockd: %s failed; unrecognized address family\n",
354 __func__);
355 goto out;
356 }
357
358 if (time_after_eq(jiffies, next_gc))
359 nlm_gc_hosts();
351 360
352 chain = &nlm_server_hosts[nlm_hash_address(ni.sap)]; 361 chain = &nlm_server_hosts[nlm_hash_address(ni.sap)];
353 hlist_for_each_entry(host, pos, chain, h_hash) { 362 hlist_for_each_entry(host, pos, chain, h_hash) {
354 if (host->net != net)
355 continue;
356 if (!rpc_cmp_addr(nlm_addr(host), ni.sap)) 363 if (!rpc_cmp_addr(nlm_addr(host), ni.sap))
357 continue; 364 continue;
358 365
@@ -384,7 +391,6 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
384 memcpy(nlm_srcaddr(host), src_sap, src_len); 391 memcpy(nlm_srcaddr(host), src_sap, src_len);
385 host->h_srcaddrlen = src_len; 392 host->h_srcaddrlen = src_len;
386 hlist_add_head(&host->h_hash, chain); 393 hlist_add_head(&host->h_hash, chain);
387 ln->nrhosts++;
388 nrhosts++; 394 nrhosts++;
389 395
390 dprintk("lockd: %s created host %s (%s)\n", 396 dprintk("lockd: %s created host %s (%s)\n",
@@ -408,7 +414,8 @@ void nlmsvc_release_host(struct nlm_host *host)
408 414
409 dprintk("lockd: release server host %s\n", host->h_name); 415 dprintk("lockd: release server host %s\n", host->h_name);
410 416
411 WARN_ON_ONCE(!host->h_server); 417 BUG_ON(atomic_read(&host->h_count) < 0);
418 BUG_ON(!host->h_server);
412 atomic_dec(&host->h_count); 419 atomic_dec(&host->h_count);
413} 420}
414 421
@@ -445,7 +452,7 @@ nlm_bind_host(struct nlm_host *host)
445 .to_retries = 5U, 452 .to_retries = 5U,
446 }; 453 };
447 struct rpc_create_args args = { 454 struct rpc_create_args args = {
448 .net = host->net, 455 .net = &init_net,
449 .protocol = host->h_proto, 456 .protocol = host->h_proto,
450 .address = nlm_addr(host), 457 .address = nlm_addr(host),
451 .addrsize = host->h_addrlen, 458 .addrsize = host->h_addrlen,
@@ -567,49 +574,23 @@ void nlm_host_rebooted(const struct nlm_reboot *info)
567 nsm_release(nsm); 574 nsm_release(nsm);
568} 575}
569 576
570static void nlm_complain_hosts(struct net *net) 577/*
571{ 578 * Shut down the hosts module.
572 struct hlist_head *chain; 579 * Note that this routine is called only at server shutdown time.
573 struct hlist_node *pos; 580 */
574 struct nlm_host *host;
575
576 if (net) {
577 struct lockd_net *ln = net_generic(net, lockd_net_id);
578
579 if (ln->nrhosts == 0)
580 return;
581 printk(KERN_WARNING "lockd: couldn't shutdown host module for net %p!\n", net);
582 dprintk("lockd: %lu hosts left in net %p:\n", ln->nrhosts, net);
583 } else {
584 if (nrhosts == 0)
585 return;
586 printk(KERN_WARNING "lockd: couldn't shutdown host module!\n");
587 dprintk("lockd: %lu hosts left:\n", nrhosts);
588 }
589
590 for_each_host(host, pos, chain, nlm_server_hosts) {
591 if (net && host->net != net)
592 continue;
593 dprintk(" %s (cnt %d use %d exp %ld net %p)\n",
594 host->h_name, atomic_read(&host->h_count),
595 host->h_inuse, host->h_expires, host->net);
596 }
597}
598
599void 581void
600nlm_shutdown_hosts_net(struct net *net) 582nlm_shutdown_hosts(void)
601{ 583{
602 struct hlist_head *chain; 584 struct hlist_head *chain;
603 struct hlist_node *pos; 585 struct hlist_node *pos;
604 struct nlm_host *host; 586 struct nlm_host *host;
605 587
588 dprintk("lockd: shutting down host module\n");
606 mutex_lock(&nlm_host_mutex); 589 mutex_lock(&nlm_host_mutex);
607 590
608 /* First, make all hosts eligible for gc */ 591 /* First, make all hosts eligible for gc */
609 dprintk("lockd: nuking all hosts in net %p...\n", net); 592 dprintk("lockd: nuking all hosts...\n");
610 for_each_host(host, pos, chain, nlm_server_hosts) { 593 for_each_host(host, pos, chain, nlm_server_hosts) {
611 if (net && host->net != net)
612 continue;
613 host->h_expires = jiffies - 1; 594 host->h_expires = jiffies - 1;
614 if (host->h_rpcclnt) { 595 if (host->h_rpcclnt) {
615 rpc_shutdown_client(host->h_rpcclnt); 596 rpc_shutdown_client(host->h_rpcclnt);
@@ -618,21 +599,19 @@ nlm_shutdown_hosts_net(struct net *net)
618 } 599 }
619 600
620 /* Then, perform a garbage collection pass */ 601 /* Then, perform a garbage collection pass */
621 nlm_gc_hosts(net); 602 nlm_gc_hosts();
622 mutex_unlock(&nlm_host_mutex); 603 mutex_unlock(&nlm_host_mutex);
623 604
624 nlm_complain_hosts(net); 605 /* complain if any hosts are left */
625} 606 if (nrhosts != 0) {
626 607 printk(KERN_WARNING "lockd: couldn't shutdown host module!\n");
627/* 608 dprintk("lockd: %lu hosts left:\n", nrhosts);
628 * Shut down the hosts module. 609 for_each_host(host, pos, chain, nlm_server_hosts) {
629 * Note that this routine is called only at server shutdown time. 610 dprintk(" %s (cnt %d use %d exp %ld)\n",
630 */ 611 host->h_name, atomic_read(&host->h_count),
631void 612 host->h_inuse, host->h_expires);
632nlm_shutdown_hosts(void) 613 }
633{ 614 }
634 dprintk("lockd: shutting down host module\n");
635 nlm_shutdown_hosts_net(NULL);
636} 615}
637 616
638/* 617/*
@@ -641,39 +620,30 @@ nlm_shutdown_hosts(void)
641 * mark & sweep for resources held by remote clients. 620 * mark & sweep for resources held by remote clients.
642 */ 621 */
643static void 622static void
644nlm_gc_hosts(struct net *net) 623nlm_gc_hosts(void)
645{ 624{
646 struct hlist_head *chain; 625 struct hlist_head *chain;
647 struct hlist_node *pos, *next; 626 struct hlist_node *pos, *next;
648 struct nlm_host *host; 627 struct nlm_host *host;
649 628
650 dprintk("lockd: host garbage collection for net %p\n", net); 629 dprintk("lockd: host garbage collection\n");
651 for_each_host(host, pos, chain, nlm_server_hosts) { 630 for_each_host(host, pos, chain, nlm_server_hosts)
652 if (net && host->net != net)
653 continue;
654 host->h_inuse = 0; 631 host->h_inuse = 0;
655 }
656 632
657 /* Mark all hosts that hold locks, blocks or shares */ 633 /* Mark all hosts that hold locks, blocks or shares */
658 nlmsvc_mark_resources(net); 634 nlmsvc_mark_resources();
659 635
660 for_each_host_safe(host, pos, next, chain, nlm_server_hosts) { 636 for_each_host_safe(host, pos, next, chain, nlm_server_hosts) {
661 if (net && host->net != net)
662 continue;
663 if (atomic_read(&host->h_count) || host->h_inuse 637 if (atomic_read(&host->h_count) || host->h_inuse
664 || time_before(jiffies, host->h_expires)) { 638 || time_before(jiffies, host->h_expires)) {
665 dprintk("nlm_gc_hosts skipping %s " 639 dprintk("nlm_gc_hosts skipping %s "
666 "(cnt %d use %d exp %ld net %p)\n", 640 "(cnt %d use %d exp %ld)\n",
667 host->h_name, atomic_read(&host->h_count), 641 host->h_name, atomic_read(&host->h_count),
668 host->h_inuse, host->h_expires, host->net); 642 host->h_inuse, host->h_expires);
669 continue; 643 continue;
670 } 644 }
671 nlm_destroy_host_locked(host); 645 nlm_destroy_host_locked(host);
672 } 646 }
673 647
674 if (net) { 648 next_gc = jiffies + NLM_HOST_COLLECT;
675 struct lockd_net *ln = net_generic(net, lockd_net_id);
676
677 ln->next_gc = jiffies + NLM_HOST_COLLECT;
678 }
679} 649}
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 3c2cfc68363..23d7451b293 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -7,6 +7,7 @@
7 */ 7 */
8 8
9#include <linux/types.h> 9#include <linux/types.h>
10#include <linux/utsname.h>
10#include <linux/kernel.h> 11#include <linux/kernel.h>
11#include <linux/ktime.h> 12#include <linux/ktime.h>
12#include <linux/slab.h> 13#include <linux/slab.h>
@@ -18,8 +19,6 @@
18 19
19#include <asm/unaligned.h> 20#include <asm/unaligned.h>
20 21
21#include "netns.h"
22
23#define NLMDBG_FACILITY NLMDBG_MONITOR 22#define NLMDBG_FACILITY NLMDBG_MONITOR
24#define NSM_PROGRAM 100024 23#define NSM_PROGRAM 100024
25#define NSM_VERSION 1 24#define NSM_VERSION 1
@@ -41,7 +40,6 @@ struct nsm_args {
41 u32 proc; 40 u32 proc;
42 41
43 char *mon_name; 42 char *mon_name;
44 char *nodename;
45}; 43};
46 44
47struct nsm_res { 45struct nsm_res {
@@ -49,7 +47,7 @@ struct nsm_res {
49 u32 state; 47 u32 state;
50}; 48};
51 49
52static const struct rpc_program nsm_program; 50static struct rpc_program nsm_program;
53static LIST_HEAD(nsm_handles); 51static LIST_HEAD(nsm_handles);
54static DEFINE_SPINLOCK(nsm_lock); 52static DEFINE_SPINLOCK(nsm_lock);
55 53
@@ -57,22 +55,22 @@ static DEFINE_SPINLOCK(nsm_lock);
57 * Local NSM state 55 * Local NSM state
58 */ 56 */
59u32 __read_mostly nsm_local_state; 57u32 __read_mostly nsm_local_state;
60bool __read_mostly nsm_use_hostnames; 58int __read_mostly nsm_use_hostnames;
61 59
62static inline struct sockaddr *nsm_addr(const struct nsm_handle *nsm) 60static inline struct sockaddr *nsm_addr(const struct nsm_handle *nsm)
63{ 61{
64 return (struct sockaddr *)&nsm->sm_addr; 62 return (struct sockaddr *)&nsm->sm_addr;
65} 63}
66 64
67static struct rpc_clnt *nsm_create(struct net *net) 65static struct rpc_clnt *nsm_create(void)
68{ 66{
69 struct sockaddr_in sin = { 67 struct sockaddr_in sin = {
70 .sin_family = AF_INET, 68 .sin_family = AF_INET,
71 .sin_addr.s_addr = htonl(INADDR_LOOPBACK), 69 .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
72 }; 70 };
73 struct rpc_create_args args = { 71 struct rpc_create_args args = {
74 .net = net, 72 .net = &init_net,
75 .protocol = XPRT_TRANSPORT_TCP, 73 .protocol = XPRT_TRANSPORT_UDP,
76 .address = (struct sockaddr *)&sin, 74 .address = (struct sockaddr *)&sin,
77 .addrsize = sizeof(sin), 75 .addrsize = sizeof(sin),
78 .servername = "rpc.statd", 76 .servername = "rpc.statd",
@@ -85,61 +83,9 @@ static struct rpc_clnt *nsm_create(struct net *net)
85 return rpc_create(&args); 83 return rpc_create(&args);
86} 84}
87 85
88static struct rpc_clnt *nsm_client_set(struct lockd_net *ln, 86static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
89 struct rpc_clnt *clnt)
90{
91 spin_lock(&ln->nsm_clnt_lock);
92 if (ln->nsm_users == 0) {
93 if (clnt == NULL)
94 goto out;
95 ln->nsm_clnt = clnt;
96 }
97 clnt = ln->nsm_clnt;
98 ln->nsm_users++;
99out:
100 spin_unlock(&ln->nsm_clnt_lock);
101 return clnt;
102}
103
104static struct rpc_clnt *nsm_client_get(struct net *net)
105{
106 struct rpc_clnt *clnt, *new;
107 struct lockd_net *ln = net_generic(net, lockd_net_id);
108
109 clnt = nsm_client_set(ln, NULL);
110 if (clnt != NULL)
111 goto out;
112
113 clnt = new = nsm_create(net);
114 if (IS_ERR(clnt))
115 goto out;
116
117 clnt = nsm_client_set(ln, new);
118 if (clnt != new)
119 rpc_shutdown_client(new);
120out:
121 return clnt;
122}
123
124static void nsm_client_put(struct net *net)
125{
126 struct lockd_net *ln = net_generic(net, lockd_net_id);
127 struct rpc_clnt *clnt = NULL;
128
129 spin_lock(&ln->nsm_clnt_lock);
130 ln->nsm_users--;
131 if (ln->nsm_users == 0) {
132 clnt = ln->nsm_clnt;
133 ln->nsm_clnt = NULL;
134 }
135 spin_unlock(&ln->nsm_clnt_lock);
136 if (clnt != NULL)
137 rpc_shutdown_client(clnt);
138}
139
140static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
141 struct rpc_clnt *clnt)
142{ 87{
88 struct rpc_clnt *clnt;
143 int status; 89 int status;
144 struct nsm_args args = { 90 struct nsm_args args = {
145 .priv = &nsm->sm_priv, 91 .priv = &nsm->sm_priv,
@@ -147,22 +93,31 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
147 .vers = 3, 93 .vers = 3,
148 .proc = NLMPROC_NSM_NOTIFY, 94 .proc = NLMPROC_NSM_NOTIFY,
149 .mon_name = nsm->sm_mon_name, 95 .mon_name = nsm->sm_mon_name,
150 .nodename = clnt->cl_nodename,
151 }; 96 };
152 struct rpc_message msg = { 97 struct rpc_message msg = {
153 .rpc_argp = &args, 98 .rpc_argp = &args,
154 .rpc_resp = res, 99 .rpc_resp = res,
155 }; 100 };
156 101
102 clnt = nsm_create();
103 if (IS_ERR(clnt)) {
104 status = PTR_ERR(clnt);
105 dprintk("lockd: failed to create NSM upcall transport, "
106 "status=%d\n", status);
107 goto out;
108 }
109
157 memset(res, 0, sizeof(*res)); 110 memset(res, 0, sizeof(*res));
158 111
159 msg.rpc_proc = &clnt->cl_procinfo[proc]; 112 msg.rpc_proc = &clnt->cl_procinfo[proc];
160 status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN); 113 status = rpc_call_sync(clnt, &msg, 0);
161 if (status < 0) 114 if (status < 0)
162 dprintk("lockd: NSM upcall RPC failed, status=%d\n", 115 dprintk("lockd: NSM upcall RPC failed, status=%d\n",
163 status); 116 status);
164 else 117 else
165 status = 0; 118 status = 0;
119 rpc_shutdown_client(clnt);
120 out:
166 return status; 121 return status;
167} 122}
168 123
@@ -182,7 +137,6 @@ int nsm_monitor(const struct nlm_host *host)
182 struct nsm_handle *nsm = host->h_nsmhandle; 137 struct nsm_handle *nsm = host->h_nsmhandle;
183 struct nsm_res res; 138 struct nsm_res res;
184 int status; 139 int status;
185 struct rpc_clnt *clnt;
186 140
187 dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name); 141 dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);
188 142
@@ -195,15 +149,7 @@ int nsm_monitor(const struct nlm_host *host)
195 */ 149 */
196 nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf; 150 nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
197 151
198 clnt = nsm_client_get(host->net); 152 status = nsm_mon_unmon(nsm, NSMPROC_MON, &res);
199 if (IS_ERR(clnt)) {
200 status = PTR_ERR(clnt);
201 dprintk("lockd: failed to create NSM upcall transport, "
202 "status=%d, net=%p\n", status, host->net);
203 return status;
204 }
205
206 status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, clnt);
207 if (unlikely(res.status != 0)) 153 if (unlikely(res.status != 0))
208 status = -EIO; 154 status = -EIO;
209 if (unlikely(status < 0)) { 155 if (unlikely(status < 0)) {
@@ -235,11 +181,9 @@ void nsm_unmonitor(const struct nlm_host *host)
235 181
236 if (atomic_read(&nsm->sm_count) == 1 182 if (atomic_read(&nsm->sm_count) == 1
237 && nsm->sm_monitored && !nsm->sm_sticky) { 183 && nsm->sm_monitored && !nsm->sm_sticky) {
238 struct lockd_net *ln = net_generic(host->net, lockd_net_id);
239
240 dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name); 184 dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
241 185
242 status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, ln->nsm_clnt); 186 status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res);
243 if (res.status != 0) 187 if (res.status != 0)
244 status = -EIO; 188 status = -EIO;
245 if (status < 0) 189 if (status < 0)
@@ -247,8 +191,6 @@ void nsm_unmonitor(const struct nlm_host *host)
247 nsm->sm_name); 191 nsm->sm_name);
248 else 192 else
249 nsm->sm_monitored = 0; 193 nsm->sm_monitored = 0;
250
251 nsm_client_put(host->net);
252 } 194 }
253} 195}
254 196
@@ -464,6 +406,7 @@ static void encode_nsm_string(struct xdr_stream *xdr, const char *string)
464 const u32 len = strlen(string); 406 const u32 len = strlen(string);
465 __be32 *p; 407 __be32 *p;
466 408
409 BUG_ON(len > SM_MAXSTRLEN);
467 p = xdr_reserve_space(xdr, 4 + len); 410 p = xdr_reserve_space(xdr, 4 + len);
468 xdr_encode_opaque(p, string, len); 411 xdr_encode_opaque(p, string, len);
469} 412}
@@ -486,7 +429,7 @@ static void encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp)
486{ 429{
487 __be32 *p; 430 __be32 *p;
488 431
489 encode_nsm_string(xdr, argp->nodename); 432 encode_nsm_string(xdr, utsname()->nodename);
490 p = xdr_reserve_space(xdr, 4 + 4 + 4); 433 p = xdr_reserve_space(xdr, 4 + 4 + 4);
491 *p++ = cpu_to_be32(argp->prog); 434 *p++ = cpu_to_be32(argp->prog);
492 *p++ = cpu_to_be32(argp->vers); 435 *p++ = cpu_to_be32(argp->vers);
@@ -591,19 +534,19 @@ static struct rpc_procinfo nsm_procedures[] = {
591 }, 534 },
592}; 535};
593 536
594static const struct rpc_version nsm_version1 = { 537static struct rpc_version nsm_version1 = {
595 .number = 1, 538 .number = 1,
596 .nrprocs = ARRAY_SIZE(nsm_procedures), 539 .nrprocs = ARRAY_SIZE(nsm_procedures),
597 .procs = nsm_procedures 540 .procs = nsm_procedures
598}; 541};
599 542
600static const struct rpc_version *nsm_version[] = { 543static struct rpc_version * nsm_version[] = {
601 [1] = &nsm_version1, 544 [1] = &nsm_version1,
602}; 545};
603 546
604static struct rpc_stat nsm_stats; 547static struct rpc_stat nsm_stats;
605 548
606static const struct rpc_program nsm_program = { 549static struct rpc_program nsm_program = {
607 .name = "statd", 550 .name = "statd",
608 .number = NSM_PROGRAM, 551 .number = NSM_PROGRAM,
609 .nrvers = ARRAY_SIZE(nsm_version), 552 .nrvers = ARRAY_SIZE(nsm_version),
diff --git a/fs/lockd/netns.h b/fs/lockd/netns.h
deleted file mode 100644
index 5010b55628b..00000000000
--- a/fs/lockd/netns.h
+++ /dev/null
@@ -1,23 +0,0 @@
1#ifndef __LOCKD_NETNS_H__
2#define __LOCKD_NETNS_H__
3
4#include <linux/fs.h>
5#include <net/netns/generic.h>
6
7struct lockd_net {
8 unsigned int nlmsvc_users;
9 unsigned long next_gc;
10 unsigned long nrhosts;
11
12 struct delayed_work grace_period_end;
13 struct lock_manager lockd_manager;
14 struct list_head grace_list;
15
16 spinlock_t nsm_clnt_lock;
17 unsigned int nsm_users;
18 struct rpc_clnt *nsm_clnt;
19};
20
21extern int lockd_net_id;
22
23#endif
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index a2aa97d4567..abfff9d7979 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -35,8 +35,6 @@
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
40#define NLMDBG_FACILITY NLMDBG_SVC 38#define NLMDBG_FACILITY NLMDBG_SVC
41#define LOCKD_BUFSIZE (1024 + NLMSVC_XDRSIZE) 39#define LOCKD_BUFSIZE (1024 + NLMSVC_XDRSIZE)
42#define ALLOWED_SIGS (sigmask(SIGKILL)) 40#define ALLOWED_SIGS (sigmask(SIGKILL))
@@ -52,8 +50,6 @@ static struct task_struct *nlmsvc_task;
52static struct svc_rqst *nlmsvc_rqst; 50static struct svc_rqst *nlmsvc_rqst;
53unsigned long nlmsvc_timeout; 51unsigned long nlmsvc_timeout;
54 52
55int lockd_net_id;
56
57/* 53/*
58 * These can be set at insmod time (useful for NFS as root filesystem), 54 * These can be set at insmod time (useful for NFS as root filesystem),
59 * and also changed through the sysctl interface. -- Jamie Lokier, Aug 2003 55 * and also changed through the sysctl interface. -- Jamie Lokier, Aug 2003
@@ -87,36 +83,32 @@ static unsigned long get_lockd_grace_period(void)
87 return nlm_timeout * 5 * HZ; 83 return nlm_timeout * 5 * HZ;
88} 84}
89 85
90static void grace_ender(struct work_struct *grace) 86static struct lock_manager lockd_manager = {
91{ 87};
92 struct delayed_work *dwork = container_of(grace, struct delayed_work,
93 work);
94 struct lockd_net *ln = container_of(dwork, struct lockd_net,
95 grace_period_end);
96 88
97 locks_end_grace(&ln->lockd_manager); 89static void grace_ender(struct work_struct *not_used)
90{
91 locks_end_grace(&lockd_manager);
98} 92}
99 93
100static void set_grace_period(struct net *net) 94static DECLARE_DELAYED_WORK(grace_period_end, grace_ender);
95
96static void set_grace_period(void)
101{ 97{
102 unsigned long grace_period = get_lockd_grace_period(); 98 unsigned long grace_period = get_lockd_grace_period();
103 struct lockd_net *ln = net_generic(net, lockd_net_id);
104 99
105 locks_start_grace(net, &ln->lockd_manager); 100 locks_start_grace(&lockd_manager);
106 cancel_delayed_work_sync(&ln->grace_period_end); 101 cancel_delayed_work_sync(&grace_period_end);
107 schedule_delayed_work(&ln->grace_period_end, grace_period); 102 schedule_delayed_work(&grace_period_end, grace_period);
108} 103}
109 104
110static void restart_grace(void) 105static void restart_grace(void)
111{ 106{
112 if (nlmsvc_ops) { 107 if (nlmsvc_ops) {
113 struct net *net = &init_net; 108 cancel_delayed_work_sync(&grace_period_end);
114 struct lockd_net *ln = net_generic(net, lockd_net_id); 109 locks_end_grace(&lockd_manager);
115
116 cancel_delayed_work_sync(&ln->grace_period_end);
117 locks_end_grace(&ln->lockd_manager);
118 nlmsvc_invalidate_all(); 110 nlmsvc_invalidate_all();
119 set_grace_period(net); 111 set_grace_period();
120 } 112 }
121} 113}
122 114
@@ -126,7 +118,7 @@ static void restart_grace(void)
126static int 118static int
127lockd(void *vrqstp) 119lockd(void *vrqstp)
128{ 120{
129 int err = 0; 121 int err = 0, preverr = 0;
130 struct svc_rqst *rqstp = vrqstp; 122 struct svc_rqst *rqstp = vrqstp;
131 123
132 /* try_to_freeze() is called from svc_recv() */ 124 /* try_to_freeze() is called from svc_recv() */
@@ -141,6 +133,8 @@ lockd(void *vrqstp)
141 nlm_timeout = LOCKD_DFLT_TIMEO; 133 nlm_timeout = LOCKD_DFLT_TIMEO;
142 nlmsvc_timeout = nlm_timeout * HZ; 134 nlmsvc_timeout = nlm_timeout * HZ;
143 135
136 set_grace_period();
137
144 /* 138 /*
145 * The main request loop. We don't terminate until the last 139 * The main request loop. We don't terminate until the last
146 * NFS mount or NFS daemon has gone away. 140 * NFS mount or NFS daemon has gone away.
@@ -165,14 +159,29 @@ lockd(void *vrqstp)
165 * recvfrom routine. 159 * recvfrom routine.
166 */ 160 */
167 err = svc_recv(rqstp, timeout); 161 err = svc_recv(rqstp, timeout);
168 if (err == -EAGAIN || err == -EINTR) 162 if (err == -EAGAIN || err == -EINTR) {
163 preverr = err;
164 continue;
165 }
166 if (err < 0) {
167 if (err != preverr) {
168 printk(KERN_WARNING "%s: unexpected error "
169 "from svc_recv (%d)\n", __func__, err);
170 preverr = err;
171 }
172 schedule_timeout_interruptible(HZ);
169 continue; 173 continue;
174 }
175 preverr = err;
176
170 dprintk("lockd: request from %s\n", 177 dprintk("lockd: request from %s\n",
171 svc_print_addr(rqstp, buf, sizeof(buf))); 178 svc_print_addr(rqstp, buf, sizeof(buf)));
172 179
173 svc_process(rqstp); 180 svc_process(rqstp);
174 } 181 }
175 flush_signals(current); 182 flush_signals(current);
183 cancel_delayed_work_sync(&grace_period_end);
184 locks_end_grace(&lockd_manager);
176 if (nlmsvc_ops) 185 if (nlmsvc_ops)
177 nlmsvc_invalidate_all(); 186 nlmsvc_invalidate_all();
178 nlm_shutdown_hosts(); 187 nlm_shutdown_hosts();
@@ -180,29 +189,27 @@ lockd(void *vrqstp)
180} 189}
181 190
182static int create_lockd_listener(struct svc_serv *serv, const char *name, 191static int create_lockd_listener(struct svc_serv *serv, const char *name,
183 struct net *net, const int family, 192 const int family, const unsigned short port)
184 const unsigned short port)
185{ 193{
186 struct svc_xprt *xprt; 194 struct svc_xprt *xprt;
187 195
188 xprt = svc_find_xprt(serv, name, net, family, 0); 196 xprt = svc_find_xprt(serv, name, family, 0);
189 if (xprt == NULL) 197 if (xprt == NULL)
190 return svc_create_xprt(serv, name, net, family, port, 198 return svc_create_xprt(serv, name, &init_net, family, port,
191 SVC_SOCK_DEFAULTS); 199 SVC_SOCK_DEFAULTS);
192 svc_xprt_put(xprt); 200 svc_xprt_put(xprt);
193 return 0; 201 return 0;
194} 202}
195 203
196static int create_lockd_family(struct svc_serv *serv, struct net *net, 204static int create_lockd_family(struct svc_serv *serv, const int family)
197 const int family)
198{ 205{
199 int err; 206 int err;
200 207
201 err = create_lockd_listener(serv, "udp", net, family, nlm_udpport); 208 err = create_lockd_listener(serv, "udp", family, nlm_udpport);
202 if (err < 0) 209 if (err < 0)
203 return err; 210 return err;
204 211
205 return create_lockd_listener(serv, "tcp", net, family, nlm_tcpport); 212 return create_lockd_listener(serv, "tcp", family, nlm_tcpport);
206} 213}
207 214
208/* 215/*
@@ -215,16 +222,16 @@ static int create_lockd_family(struct svc_serv *serv, struct net *net,
215 * Returns zero if all listeners are available; otherwise a 222 * Returns zero if all listeners are available; otherwise a
216 * negative errno value is returned. 223 * negative errno value is returned.
217 */ 224 */
218static int make_socks(struct svc_serv *serv, struct net *net) 225static int make_socks(struct svc_serv *serv)
219{ 226{
220 static int warned; 227 static int warned;
221 int err; 228 int err;
222 229
223 err = create_lockd_family(serv, net, PF_INET); 230 err = create_lockd_family(serv, PF_INET);
224 if (err < 0) 231 if (err < 0)
225 goto out_err; 232 goto out_err;
226 233
227 err = create_lockd_family(serv, net, PF_INET6); 234 err = create_lockd_family(serv, PF_INET6);
228 if (err < 0 && err != -EAFNOSUPPORT) 235 if (err < 0 && err != -EAFNOSUPPORT)
229 goto out_err; 236 goto out_err;
230 237
@@ -238,68 +245,51 @@ out_err:
238 return err; 245 return err;
239} 246}
240 247
241static int lockd_up_net(struct svc_serv *serv, struct net *net) 248/*
249 * Bring up the lockd process if it's not already up.
250 */
251int lockd_up(void)
242{ 252{
243 struct lockd_net *ln = net_generic(net, lockd_net_id); 253 struct svc_serv *serv;
244 int error; 254 int error = 0;
245
246 if (ln->nlmsvc_users++)
247 return 0;
248
249 error = svc_bind(serv, net);
250 if (error)
251 goto err_bind;
252 255
253 error = make_socks(serv, net); 256 mutex_lock(&nlmsvc_mutex);
254 if (error < 0) 257 /*
255 goto err_socks; 258 * Check whether we're already up and running.
256 set_grace_period(net); 259 */
257 dprintk("lockd_up_net: per-net data created; net=%p\n", net); 260 if (nlmsvc_rqst)
258 return 0; 261 goto out;
259 262
260err_socks: 263 /*
261 svc_rpcb_cleanup(serv, net); 264 * Sanity check: if there's no pid,
262err_bind: 265 * we should be the first user ...
263 ln->nlmsvc_users--; 266 */
264 return error; 267 if (nlmsvc_users)
265} 268 printk(KERN_WARNING
269 "lockd_up: no pid, %d users??\n", nlmsvc_users);
266 270
267static void lockd_down_net(struct svc_serv *serv, struct net *net) 271 error = -ENOMEM;
268{ 272 serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL);
269 struct lockd_net *ln = net_generic(net, lockd_net_id); 273 if (!serv) {
270 274 printk(KERN_WARNING "lockd_up: create service failed\n");
271 if (ln->nlmsvc_users) { 275 goto out;
272 if (--ln->nlmsvc_users == 0) {
273 nlm_shutdown_hosts_net(net);
274 cancel_delayed_work_sync(&ln->grace_period_end);
275 locks_end_grace(&ln->lockd_manager);
276 svc_shutdown_net(serv, net);
277 dprintk("lockd_down_net: per-net data destroyed; net=%p\n", net);
278 }
279 } else {
280 printk(KERN_ERR "lockd_down_net: no users! task=%p, net=%p\n",
281 nlmsvc_task, net);
282 BUG();
283 } 276 }
284}
285
286static int lockd_start_svc(struct svc_serv *serv)
287{
288 int error;
289 277
290 if (nlmsvc_rqst) 278 error = make_socks(serv);
291 return 0; 279 if (error < 0)
280 goto destroy_and_out;
292 281
293 /* 282 /*
294 * Create the kernel thread and wait for it to start. 283 * Create the kernel thread and wait for it to start.
295 */ 284 */
296 nlmsvc_rqst = svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE); 285 nlmsvc_rqst = svc_prepare_thread(serv, &serv->sv_pools[0]);
297 if (IS_ERR(nlmsvc_rqst)) { 286 if (IS_ERR(nlmsvc_rqst)) {
298 error = PTR_ERR(nlmsvc_rqst); 287 error = PTR_ERR(nlmsvc_rqst);
288 nlmsvc_rqst = NULL;
299 printk(KERN_WARNING 289 printk(KERN_WARNING
300 "lockd_up: svc_rqst allocation failed, error=%d\n", 290 "lockd_up: svc_rqst allocation failed, error=%d\n",
301 error); 291 error);
302 goto out_rqst; 292 goto destroy_and_out;
303 } 293 }
304 294
305 svc_sock_update_bufs(serv); 295 svc_sock_update_bufs(serv);
@@ -308,92 +298,25 @@ static int lockd_start_svc(struct svc_serv *serv)
308 nlmsvc_task = kthread_run(lockd, nlmsvc_rqst, serv->sv_name); 298 nlmsvc_task = kthread_run(lockd, nlmsvc_rqst, serv->sv_name);
309 if (IS_ERR(nlmsvc_task)) { 299 if (IS_ERR(nlmsvc_task)) {
310 error = PTR_ERR(nlmsvc_task); 300 error = PTR_ERR(nlmsvc_task);
301 svc_exit_thread(nlmsvc_rqst);
302 nlmsvc_task = NULL;
303 nlmsvc_rqst = NULL;
311 printk(KERN_WARNING 304 printk(KERN_WARNING
312 "lockd_up: kthread_run failed, error=%d\n", error); 305 "lockd_up: kthread_run failed, error=%d\n", error);
313 goto out_task; 306 goto destroy_and_out;
314 }
315 dprintk("lockd_up: service started\n");
316 return 0;
317
318out_task:
319 svc_exit_thread(nlmsvc_rqst);
320 nlmsvc_task = NULL;
321out_rqst:
322 nlmsvc_rqst = NULL;
323 return error;
324}
325
326static struct svc_serv *lockd_create_svc(void)
327{
328 struct svc_serv *serv;
329
330 /*
331 * Check whether we're already up and running.
332 */
333 if (nlmsvc_rqst) {
334 /*
335 * Note: increase service usage, because later in case of error
336 * svc_destroy() will be called.
337 */
338 svc_get(nlmsvc_rqst->rq_server);
339 return nlmsvc_rqst->rq_server;
340 }
341
342 /*
343 * Sanity check: if there's no pid,
344 * we should be the first user ...
345 */
346 if (nlmsvc_users)
347 printk(KERN_WARNING
348 "lockd_up: no pid, %d users??\n", nlmsvc_users);
349
350 serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL);
351 if (!serv) {
352 printk(KERN_WARNING "lockd_up: create service failed\n");
353 return ERR_PTR(-ENOMEM);
354 }
355 dprintk("lockd_up: service created\n");
356 return serv;
357}
358
359/*
360 * Bring up the lockd process if it's not already up.
361 */
362int lockd_up(struct net *net)
363{
364 struct svc_serv *serv;
365 int error;
366
367 mutex_lock(&nlmsvc_mutex);
368
369 serv = lockd_create_svc();
370 if (IS_ERR(serv)) {
371 error = PTR_ERR(serv);
372 goto err_create;
373 } 307 }
374 308
375 error = lockd_up_net(serv, net);
376 if (error < 0)
377 goto err_net;
378
379 error = lockd_start_svc(serv);
380 if (error < 0)
381 goto err_start;
382
383 nlmsvc_users++;
384 /* 309 /*
385 * Note: svc_serv structures have an initial use count of 1, 310 * Note: svc_serv structures have an initial use count of 1,
386 * so we exit through here on both success and failure. 311 * so we exit through here on both success and failure.
387 */ 312 */
388err_net: 313destroy_and_out:
389 svc_destroy(serv); 314 svc_destroy(serv);
390err_create: 315out:
316 if (!error)
317 nlmsvc_users++;
391 mutex_unlock(&nlmsvc_mutex); 318 mutex_unlock(&nlmsvc_mutex);
392 return error; 319 return error;
393
394err_start:
395 lockd_down_net(serv, net);
396 goto err_net;
397} 320}
398EXPORT_SYMBOL_GPL(lockd_up); 321EXPORT_SYMBOL_GPL(lockd_up);
399 322
@@ -401,10 +324,9 @@ EXPORT_SYMBOL_GPL(lockd_up);
401 * Decrement the user count and bring down lockd if we're the last. 324 * Decrement the user count and bring down lockd if we're the last.
402 */ 325 */
403void 326void
404lockd_down(struct net *net) 327lockd_down(void)
405{ 328{
406 mutex_lock(&nlmsvc_mutex); 329 mutex_lock(&nlmsvc_mutex);
407 lockd_down_net(nlmsvc_rqst->rq_server, net);
408 if (nlmsvc_users) { 330 if (nlmsvc_users) {
409 if (--nlmsvc_users) 331 if (--nlmsvc_users)
410 goto out; 332 goto out;
@@ -419,9 +341,7 @@ lockd_down(struct net *net)
419 BUG(); 341 BUG();
420 } 342 }
421 kthread_stop(nlmsvc_task); 343 kthread_stop(nlmsvc_task);
422 dprintk("lockd_down: service stopped\n");
423 svc_exit_thread(nlmsvc_rqst); 344 svc_exit_thread(nlmsvc_rqst);
424 dprintk("lockd_down: service destroyed\n");
425 nlmsvc_task = NULL; 345 nlmsvc_task = NULL;
426 nlmsvc_rqst = NULL; 346 nlmsvc_rqst = NULL;
427out: 347out:
@@ -520,7 +440,7 @@ static int param_set_##name(const char *val, struct kernel_param *kp) \
520 __typeof__(type) num = which_strtol(val, &endp, 0); \ 440 __typeof__(type) num = which_strtol(val, &endp, 0); \
521 if (endp == val || *endp || num < (min) || num > (max)) \ 441 if (endp == val || *endp || num < (min) || num > (max)) \
522 return -EINVAL; \ 442 return -EINVAL; \
523 *((type *) kp->arg) = num; \ 443 *((int *) kp->arg) = num; \
524 return 0; \ 444 return 0; \
525} 445}
526 446
@@ -577,60 +497,24 @@ module_param_call(nlm_tcpport, param_set_port, param_get_int,
577module_param(nsm_use_hostnames, bool, 0644); 497module_param(nsm_use_hostnames, bool, 0644);
578module_param(nlm_max_connections, uint, 0644); 498module_param(nlm_max_connections, uint, 0644);
579 499
580static int lockd_init_net(struct net *net)
581{
582 struct lockd_net *ln = net_generic(net, lockd_net_id);
583
584 INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender);
585 INIT_LIST_HEAD(&ln->grace_list);
586 spin_lock_init(&ln->nsm_clnt_lock);
587 return 0;
588}
589
590static void lockd_exit_net(struct net *net)
591{
592}
593
594static struct pernet_operations lockd_net_ops = {
595 .init = lockd_init_net,
596 .exit = lockd_exit_net,
597 .id = &lockd_net_id,
598 .size = sizeof(struct lockd_net),
599};
600
601
602/* 500/*
603 * Initialising and terminating the module. 501 * Initialising and terminating the module.
604 */ 502 */
605 503
606static int __init init_nlm(void) 504static int __init init_nlm(void)
607{ 505{
608 int err;
609
610#ifdef CONFIG_SYSCTL 506#ifdef CONFIG_SYSCTL
611 err = -ENOMEM;
612 nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root); 507 nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root);
613 if (nlm_sysctl_table == NULL) 508 return nlm_sysctl_table ? 0 : -ENOMEM;
614 goto err_sysctl; 509#else
615#endif
616 err = register_pernet_subsys(&lockd_net_ops);
617 if (err)
618 goto err_pernet;
619 return 0; 510 return 0;
620
621err_pernet:
622#ifdef CONFIG_SYSCTL
623 unregister_sysctl_table(nlm_sysctl_table);
624#endif 511#endif
625err_sysctl:
626 return err;
627} 512}
628 513
629static void __exit exit_nlm(void) 514static void __exit exit_nlm(void)
630{ 515{
631 /* FIXME: delete all NLM clients */ 516 /* FIXME: delete all NLM clients */
632 nlm_shutdown_hosts(); 517 nlm_shutdown_hosts();
633 unregister_pernet_subsys(&lockd_net_ops);
634#ifdef CONFIG_SYSCTL 518#ifdef CONFIG_SYSCTL
635 unregister_sysctl_table(nlm_sysctl_table); 519 unregister_sysctl_table(nlm_sysctl_table);
636#endif 520#endif
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index b147d1ae71f..9a41fdc1951 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -11,7 +11,6 @@
11#include <linux/time.h> 11#include <linux/time.h>
12#include <linux/lockd/lockd.h> 12#include <linux/lockd/lockd.h>
13#include <linux/lockd/share.h> 13#include <linux/lockd/share.h>
14#include <linux/sunrpc/svc_xprt.h>
15 14
16#define NLMDBG_FACILITY NLMDBG_CLIENT 15#define NLMDBG_FACILITY NLMDBG_CLIENT
17 16
@@ -152,7 +151,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
152 resp->cookie = argp->cookie; 151 resp->cookie = argp->cookie;
153 152
154 /* Don't accept requests during grace period */ 153 /* Don't accept requests during grace period */
155 if (locks_in_grace(SVC_NET(rqstp))) { 154 if (locks_in_grace()) {
156 resp->status = nlm_lck_denied_grace_period; 155 resp->status = nlm_lck_denied_grace_period;
157 return rpc_success; 156 return rpc_success;
158 } 157 }
@@ -162,7 +161,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
162 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 161 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
163 162
164 /* Try to cancel request. */ 163 /* Try to cancel request. */
165 resp->status = nlmsvc_cancel_blocked(SVC_NET(rqstp), file, &argp->lock); 164 resp->status = nlmsvc_cancel_blocked(file, &argp->lock);
166 165
167 dprintk("lockd: CANCEL status %d\n", ntohl(resp->status)); 166 dprintk("lockd: CANCEL status %d\n", ntohl(resp->status));
168 nlmsvc_release_host(host); 167 nlmsvc_release_host(host);
@@ -185,7 +184,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
185 resp->cookie = argp->cookie; 184 resp->cookie = argp->cookie;
186 185
187 /* Don't accept new lock requests during grace period */ 186 /* Don't accept new lock requests during grace period */
188 if (locks_in_grace(SVC_NET(rqstp))) { 187 if (locks_in_grace()) {
189 resp->status = nlm_lck_denied_grace_period; 188 resp->status = nlm_lck_denied_grace_period;
190 return rpc_success; 189 return rpc_success;
191 } 190 }
@@ -195,7 +194,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
195 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 194 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
196 195
197 /* Now try to remove the lock */ 196 /* Now try to remove the lock */
198 resp->status = nlmsvc_unlock(SVC_NET(rqstp), file, &argp->lock); 197 resp->status = nlmsvc_unlock(file, &argp->lock);
199 198
200 dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status)); 199 dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status));
201 nlmsvc_release_host(host); 200 nlmsvc_release_host(host);
@@ -257,7 +256,6 @@ static __be32 nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args
257 return rpc_system_err; 256 return rpc_system_err;
258 257
259 call = nlm_alloc_call(host); 258 call = nlm_alloc_call(host);
260 nlmsvc_release_host(host);
261 if (call == NULL) 259 if (call == NULL)
262 return rpc_system_err; 260 return rpc_system_err;
263 261
@@ -323,7 +321,7 @@ nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
323 resp->cookie = argp->cookie; 321 resp->cookie = argp->cookie;
324 322
325 /* Don't accept new lock requests during grace period */ 323 /* Don't accept new lock requests during grace period */
326 if (locks_in_grace(SVC_NET(rqstp)) && !argp->reclaim) { 324 if (locks_in_grace() && !argp->reclaim) {
327 resp->status = nlm_lck_denied_grace_period; 325 resp->status = nlm_lck_denied_grace_period;
328 return rpc_success; 326 return rpc_success;
329 } 327 }
@@ -356,7 +354,7 @@ nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
356 resp->cookie = argp->cookie; 354 resp->cookie = argp->cookie;
357 355
358 /* Don't accept requests during grace period */ 356 /* Don't accept requests during grace period */
359 if (locks_in_grace(SVC_NET(rqstp))) { 357 if (locks_in_grace()) {
360 resp->status = nlm_lck_denied_grace_period; 358 resp->status = nlm_lck_denied_grace_period;
361 return rpc_success; 359 return rpc_success;
362 } 360 }
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 8d80c990dff..f0179c3745d 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -26,7 +26,7 @@
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/sched.h> 27#include <linux/sched.h>
28#include <linux/sunrpc/clnt.h> 28#include <linux/sunrpc/clnt.h>
29#include <linux/sunrpc/svc_xprt.h> 29#include <linux/sunrpc/svc.h>
30#include <linux/lockd/nlm.h> 30#include <linux/lockd/nlm.h>
31#include <linux/lockd/lockd.h> 31#include <linux/lockd/lockd.h>
32#include <linux/kthread.h> 32#include <linux/kthread.h>
@@ -46,6 +46,7 @@ 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);
49 50
50/* 51/*
51 * The list of blocked locks to retry 52 * The list of blocked locks to retry
@@ -53,35 +54,6 @@ static const struct rpc_call_ops nlmsvc_grant_ops;
53static LIST_HEAD(nlm_blocked); 54static LIST_HEAD(nlm_blocked);
54static DEFINE_SPINLOCK(nlm_blocked_lock); 55static DEFINE_SPINLOCK(nlm_blocked_lock);
55 56
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
85/* 57/*
86 * Insert a blocked lock into the global list 58 * Insert a blocked lock into the global list
87 */ 59 */
@@ -219,6 +191,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_host *host,
219 struct nlm_block *block; 191 struct nlm_block *block;
220 struct nlm_rqst *call = NULL; 192 struct nlm_rqst *call = NULL;
221 193
194 nlm_get_host(host);
222 call = nlm_alloc_call(host); 195 call = nlm_alloc_call(host);
223 if (call == NULL) 196 if (call == NULL)
224 return NULL; 197 return NULL;
@@ -289,6 +262,7 @@ static void nlmsvc_free_block(struct kref *kref)
289 dprintk("lockd: freeing block %p...\n", block); 262 dprintk("lockd: freeing block %p...\n", block);
290 263
291 /* Remove block from file's list of blocks */ 264 /* Remove block from file's list of blocks */
265 mutex_lock(&file->f_mutex);
292 list_del_init(&block->b_flist); 266 list_del_init(&block->b_flist);
293 mutex_unlock(&file->f_mutex); 267 mutex_unlock(&file->f_mutex);
294 268
@@ -302,7 +276,7 @@ static void nlmsvc_free_block(struct kref *kref)
302static void nlmsvc_release_block(struct nlm_block *block) 276static void nlmsvc_release_block(struct nlm_block *block)
303{ 277{
304 if (block != NULL) 278 if (block != NULL)
305 kref_put_mutex(&block->b_count, nlmsvc_free_block, &block->b_file->f_mutex); 279 kref_put(&block->b_count, nlmsvc_free_block);
306} 280}
307 281
308/* 282/*
@@ -445,11 +419,11 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
445 goto out; 419 goto out;
446 } 420 }
447 421
448 if (locks_in_grace(SVC_NET(rqstp)) && !reclaim) { 422 if (locks_in_grace() && !reclaim) {
449 ret = nlm_lck_denied_grace_period; 423 ret = nlm_lck_denied_grace_period;
450 goto out; 424 goto out;
451 } 425 }
452 if (reclaim && !locks_in_grace(SVC_NET(rqstp))) { 426 if (reclaim && !locks_in_grace()) {
453 ret = nlm_lck_denied_grace_period; 427 ret = nlm_lck_denied_grace_period;
454 goto out; 428 goto out;
455 } 429 }
@@ -557,7 +531,7 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
557 goto out; 531 goto out;
558 } 532 }
559 533
560 if (locks_in_grace(SVC_NET(rqstp))) { 534 if (locks_in_grace()) {
561 ret = nlm_lck_denied_grace_period; 535 ret = nlm_lck_denied_grace_period;
562 goto out; 536 goto out;
563 } 537 }
@@ -601,7 +575,7 @@ out:
601 * must be removed. 575 * must be removed.
602 */ 576 */
603__be32 577__be32
604nlmsvc_unlock(struct net *net, struct nlm_file *file, struct nlm_lock *lock) 578nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
605{ 579{
606 int error; 580 int error;
607 581
@@ -613,7 +587,7 @@ nlmsvc_unlock(struct net *net, struct nlm_file *file, struct nlm_lock *lock)
613 (long long)lock->fl.fl_end); 587 (long long)lock->fl.fl_end);
614 588
615 /* First, cancel any lock that might be there */ 589 /* First, cancel any lock that might be there */
616 nlmsvc_cancel_blocked(net, file, lock); 590 nlmsvc_cancel_blocked(file, lock);
617 591
618 lock->fl.fl_type = F_UNLCK; 592 lock->fl.fl_type = F_UNLCK;
619 error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL); 593 error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);
@@ -629,7 +603,7 @@ nlmsvc_unlock(struct net *net, struct nlm_file *file, struct nlm_lock *lock)
629 * The calling procedure must check whether the file can be closed. 603 * The calling procedure must check whether the file can be closed.
630 */ 604 */
631__be32 605__be32
632nlmsvc_cancel_blocked(struct net *net, struct nlm_file *file, struct nlm_lock *lock) 606nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
633{ 607{
634 struct nlm_block *block; 608 struct nlm_block *block;
635 int status = 0; 609 int status = 0;
@@ -641,7 +615,7 @@ nlmsvc_cancel_blocked(struct net *net, struct nlm_file *file, struct nlm_lock *l
641 (long long)lock->fl.fl_start, 615 (long long)lock->fl.fl_start,
642 (long long)lock->fl.fl_end); 616 (long long)lock->fl.fl_end);
643 617
644 if (locks_in_grace(net)) 618 if (locks_in_grace())
645 return nlm_lck_denied_grace_period; 619 return nlm_lck_denied_grace_period;
646 620
647 mutex_lock(&file->f_mutex); 621 mutex_lock(&file->f_mutex);
@@ -961,3 +935,32 @@ nlmsvc_retry_blocked(void)
961 935
962 return timeout; 936 return timeout;
963} 937}
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
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 21171f0c647..d27aab11f32 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -11,7 +11,6 @@
11#include <linux/time.h> 11#include <linux/time.h>
12#include <linux/lockd/lockd.h> 12#include <linux/lockd/lockd.h>
13#include <linux/lockd/share.h> 13#include <linux/lockd/share.h>
14#include <linux/sunrpc/svc_xprt.h>
15 14
16#define NLMDBG_FACILITY NLMDBG_CLIENT 15#define NLMDBG_FACILITY NLMDBG_CLIENT
17 16
@@ -68,8 +67,7 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
68 67
69 /* Obtain file pointer. Not used by FREE_ALL call. */ 68 /* Obtain file pointer. Not used by FREE_ALL call. */
70 if (filp != NULL) { 69 if (filp != NULL) {
71 error = cast_status(nlm_lookup_file(rqstp, &file, &lock->fh)); 70 if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0)
72 if (error != 0)
73 goto no_locks; 71 goto no_locks;
74 *filp = file; 72 *filp = file;
75 73
@@ -177,14 +175,13 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
177{ 175{
178 struct nlm_host *host; 176 struct nlm_host *host;
179 struct nlm_file *file; 177 struct nlm_file *file;
180 struct net *net = SVC_NET(rqstp);
181 178
182 dprintk("lockd: CANCEL called\n"); 179 dprintk("lockd: CANCEL called\n");
183 180
184 resp->cookie = argp->cookie; 181 resp->cookie = argp->cookie;
185 182
186 /* Don't accept requests during grace period */ 183 /* Don't accept requests during grace period */
187 if (locks_in_grace(net)) { 184 if (locks_in_grace()) {
188 resp->status = nlm_lck_denied_grace_period; 185 resp->status = nlm_lck_denied_grace_period;
189 return rpc_success; 186 return rpc_success;
190 } 187 }
@@ -194,7 +191,7 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
194 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 191 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
195 192
196 /* Try to cancel request. */ 193 /* Try to cancel request. */
197 resp->status = cast_status(nlmsvc_cancel_blocked(net, file, &argp->lock)); 194 resp->status = cast_status(nlmsvc_cancel_blocked(file, &argp->lock));
198 195
199 dprintk("lockd: CANCEL status %d\n", ntohl(resp->status)); 196 dprintk("lockd: CANCEL status %d\n", ntohl(resp->status));
200 nlmsvc_release_host(host); 197 nlmsvc_release_host(host);
@@ -211,14 +208,13 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
211{ 208{
212 struct nlm_host *host; 209 struct nlm_host *host;
213 struct nlm_file *file; 210 struct nlm_file *file;
214 struct net *net = SVC_NET(rqstp);
215 211
216 dprintk("lockd: UNLOCK called\n"); 212 dprintk("lockd: UNLOCK called\n");
217 213
218 resp->cookie = argp->cookie; 214 resp->cookie = argp->cookie;
219 215
220 /* Don't accept new lock requests during grace period */ 216 /* Don't accept new lock requests during grace period */
221 if (locks_in_grace(net)) { 217 if (locks_in_grace()) {
222 resp->status = nlm_lck_denied_grace_period; 218 resp->status = nlm_lck_denied_grace_period;
223 return rpc_success; 219 return rpc_success;
224 } 220 }
@@ -228,7 +224,7 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
228 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 224 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
229 225
230 /* Now try to remove the lock */ 226 /* Now try to remove the lock */
231 resp->status = cast_status(nlmsvc_unlock(net, file, &argp->lock)); 227 resp->status = cast_status(nlmsvc_unlock(file, &argp->lock));
232 228
233 dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status)); 229 dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status));
234 nlmsvc_release_host(host); 230 nlmsvc_release_host(host);
@@ -298,7 +294,6 @@ static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args
298 return rpc_system_err; 294 return rpc_system_err;
299 295
300 call = nlm_alloc_call(host); 296 call = nlm_alloc_call(host);
301 nlmsvc_release_host(host);
302 if (call == NULL) 297 if (call == NULL)
303 return rpc_system_err; 298 return rpc_system_err;
304 299
@@ -366,7 +361,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
366 resp->cookie = argp->cookie; 361 resp->cookie = argp->cookie;
367 362
368 /* Don't accept new lock requests during grace period */ 363 /* Don't accept new lock requests during grace period */
369 if (locks_in_grace(SVC_NET(rqstp)) && !argp->reclaim) { 364 if (locks_in_grace() && !argp->reclaim) {
370 resp->status = nlm_lck_denied_grace_period; 365 resp->status = nlm_lck_denied_grace_period;
371 return rpc_success; 366 return rpc_success;
372 } 367 }
@@ -399,7 +394,7 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
399 resp->cookie = argp->cookie; 394 resp->cookie = argp->cookie;
400 395
401 /* Don't accept requests during grace period */ 396 /* Don't accept requests during grace period */
402 if (locks_in_grace(SVC_NET(rqstp))) { 397 if (locks_in_grace()) {
403 resp->status = nlm_lck_denied_grace_period; 398 resp->status = nlm_lck_denied_grace_period;
404 return rpc_success; 399 return rpc_success;
405 } 400 }
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index 0deb5f6c9dd..1ca0679c80b 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -309,8 +309,7 @@ nlm_release_file(struct nlm_file *file)
309 * Helpers function for resource traversal 309 * Helpers function for resource traversal
310 * 310 *
311 * nlmsvc_mark_host: 311 * nlmsvc_mark_host:
312 * used by the garbage collector; simply sets h_inuse only for those 312 * used by the garbage collector; simply sets h_inuse.
313 * hosts, which passed network check.
314 * Always returns 0. 313 * Always returns 0.
315 * 314 *
316 * nlmsvc_same_host: 315 * nlmsvc_same_host:
@@ -321,15 +320,12 @@ nlm_release_file(struct nlm_file *file)
321 * returns 1 iff the host is a client. 320 * returns 1 iff the host is a client.
322 * Used by nlmsvc_invalidate_all 321 * Used by nlmsvc_invalidate_all
323 */ 322 */
324
325static int 323static int
326nlmsvc_mark_host(void *data, struct nlm_host *hint) 324nlmsvc_mark_host(void *data, struct nlm_host *dummy)
327{ 325{
328 struct nlm_host *host = data; 326 struct nlm_host *host = data;
329 327
330 if ((hint->net == NULL) || 328 host->h_inuse = 1;
331 (host->net == hint->net))
332 host->h_inuse = 1;
333 return 0; 329 return 0;
334} 330}
335 331
@@ -362,13 +358,10 @@ nlmsvc_is_client(void *data, struct nlm_host *dummy)
362 * Mark all hosts that still hold resources 358 * Mark all hosts that still hold resources
363 */ 359 */
364void 360void
365nlmsvc_mark_resources(struct net *net) 361nlmsvc_mark_resources(void)
366{ 362{
367 struct nlm_host hint; 363 dprintk("lockd: nlmsvc_mark_resources\n");
368 364 nlm_traverse_files(NULL, nlmsvc_mark_host, NULL);
369 dprintk("lockd: nlmsvc_mark_resources for net %p\n", net);
370 hint.net = net;
371 nlm_traverse_files(&hint, nlmsvc_mark_host, NULL);
372} 365}
373 366
374/* 367/*
@@ -410,7 +403,7 @@ nlmsvc_match_sb(void *datap, struct nlm_file *file)
410{ 403{
411 struct super_block *sb = datap; 404 struct super_block *sb = datap;
412 405
413 return sb == file->f_file->f_path.dentry->d_sb; 406 return sb == file->f_file->f_path.mnt->mnt_sb;
414} 407}
415 408
416/** 409/**