aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/lockd/grace.c16
-rw-r--r--fs/lockd/host.c92
-rw-r--r--fs/lockd/netns.h7
-rw-r--r--fs/lockd/svc.c43
-rw-r--r--fs/lockd/svc4proc.c13
-rw-r--r--fs/lockd/svclock.c16
-rw-r--r--fs/lockd/svcproc.c15
-rw-r--r--fs/lockd/svcsubs.c19
-rw-r--r--fs/locks.c28
-rw-r--r--fs/nfs/callback_xdr.c4
-rw-r--r--fs/nfsd/export.c10
-rw-r--r--fs/nfsd/netns.h4
-rw-r--r--fs/nfsd/nfs4callback.c1
-rw-r--r--fs/nfsd/nfs4idmap.c4
-rw-r--r--fs/nfsd/nfs4proc.c18
-rw-r--r--fs/nfsd/nfs4state.c201
-rw-r--r--fs/nfsd/nfs4xdr.c2
-rw-r--r--fs/nfsd/nfsctl.c8
-rw-r--r--fs/nfsd/nfsd.h13
-rw-r--r--fs/nfsd/nfssvc.c24
-rw-r--r--fs/nfsd/state.h5
-rw-r--r--fs/nfsd/vfs.c10
-rw-r--r--include/linux/fs.h5
-rw-r--r--include/linux/lockd/lockd.h6
-rw-r--r--include/linux/sunrpc/cache.h34
-rw-r--r--include/linux/sunrpc/svc.h2
-rw-r--r--net/sunrpc/cache.c5
27 files changed, 368 insertions, 237 deletions
diff --git a/fs/lockd/grace.c b/fs/lockd/grace.c
index 183cc1f0af1c..6d1ee7204c88 100644
--- a/fs/lockd/grace.c
+++ b/fs/lockd/grace.c
@@ -4,8 +4,10 @@
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"
7 10
8static LIST_HEAD(grace_list);
9static DEFINE_SPINLOCK(grace_lock); 11static DEFINE_SPINLOCK(grace_lock);
10 12
11/** 13/**
@@ -19,10 +21,12 @@ static DEFINE_SPINLOCK(grace_lock);
19 * 21 *
20 * This function is called to start a grace period. 22 * This function is called to start a grace period.
21 */ 23 */
22void locks_start_grace(struct lock_manager *lm) 24void locks_start_grace(struct net *net, struct lock_manager *lm)
23{ 25{
26 struct lockd_net *ln = net_generic(net, lockd_net_id);
27
24 spin_lock(&grace_lock); 28 spin_lock(&grace_lock);
25 list_add(&lm->list, &grace_list); 29 list_add(&lm->list, &ln->grace_list);
26 spin_unlock(&grace_lock); 30 spin_unlock(&grace_lock);
27} 31}
28EXPORT_SYMBOL_GPL(locks_start_grace); 32EXPORT_SYMBOL_GPL(locks_start_grace);
@@ -52,8 +56,10 @@ EXPORT_SYMBOL_GPL(locks_end_grace);
52 * to answer ordinary lock requests, and when they should accept only 56 * to answer ordinary lock requests, and when they should accept only
53 * lock reclaims. 57 * lock reclaims.
54 */ 58 */
55int locks_in_grace(void) 59int locks_in_grace(struct net *net)
56{ 60{
57 return !list_empty(&grace_list); 61 struct lockd_net *ln = net_generic(net, lockd_net_id);
62
63 return !list_empty(&ln->grace_list);
58} 64}
59EXPORT_SYMBOL_GPL(locks_in_grace); 65EXPORT_SYMBOL_GPL(locks_in_grace);
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index eb75ca7c2d6e..f9b22e58f78f 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -21,6 +21,8 @@
21 21
22#include <net/ipv6.h> 22#include <net/ipv6.h>
23 23
24#include "netns.h"
25
24#define NLMDBG_FACILITY NLMDBG_HOSTCACHE 26#define NLMDBG_FACILITY NLMDBG_HOSTCACHE
25#define NLM_HOST_NRHASH 32 27#define NLM_HOST_NRHASH 32
26#define NLM_HOST_REBIND (60 * HZ) 28#define NLM_HOST_REBIND (60 * HZ)
@@ -41,11 +43,10 @@ static struct hlist_head nlm_client_hosts[NLM_HOST_NRHASH];
41 hlist_for_each_entry_safe((host), (pos), (next), \ 43 hlist_for_each_entry_safe((host), (pos), (next), \
42 (chain), h_hash) 44 (chain), h_hash)
43 45
44static unsigned long next_gc;
45static unsigned long nrhosts; 46static unsigned long nrhosts;
46static DEFINE_MUTEX(nlm_host_mutex); 47static DEFINE_MUTEX(nlm_host_mutex);
47 48
48static void nlm_gc_hosts(void); 49static void nlm_gc_hosts(struct net *net);
49 50
50struct nlm_lookup_host_info { 51struct nlm_lookup_host_info {
51 const int server; /* search for server|client */ 52 const int server; /* search for server|client */
@@ -172,6 +173,7 @@ out:
172static void nlm_destroy_host_locked(struct nlm_host *host) 173static void nlm_destroy_host_locked(struct nlm_host *host)
173{ 174{
174 struct rpc_clnt *clnt; 175 struct rpc_clnt *clnt;
176 struct lockd_net *ln = net_generic(host->net, lockd_net_id);
175 177
176 dprintk("lockd: destroy host %s\n", host->h_name); 178 dprintk("lockd: destroy host %s\n", host->h_name);
177 179
@@ -188,6 +190,7 @@ static void nlm_destroy_host_locked(struct nlm_host *host)
188 rpc_shutdown_client(clnt); 190 rpc_shutdown_client(clnt);
189 kfree(host); 191 kfree(host);
190 192
193 ln->nrhosts--;
191 nrhosts--; 194 nrhosts--;
192} 195}
193 196
@@ -228,6 +231,7 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
228 struct hlist_node *pos; 231 struct hlist_node *pos;
229 struct nlm_host *host; 232 struct nlm_host *host;
230 struct nsm_handle *nsm = NULL; 233 struct nsm_handle *nsm = NULL;
234 struct lockd_net *ln = net_generic(net, lockd_net_id);
231 235
232 dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__, 236 dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__,
233 (hostname ? hostname : "<none>"), version, 237 (hostname ? hostname : "<none>"), version,
@@ -262,6 +266,7 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
262 goto out; 266 goto out;
263 267
264 hlist_add_head(&host->h_hash, chain); 268 hlist_add_head(&host->h_hash, chain);
269 ln->nrhosts++;
265 nrhosts++; 270 nrhosts++;
266 271
267 dprintk("lockd: %s created host %s (%s)\n", __func__, 272 dprintk("lockd: %s created host %s (%s)\n", __func__,
@@ -326,7 +331,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
326 struct nsm_handle *nsm = NULL; 331 struct nsm_handle *nsm = NULL;
327 struct sockaddr *src_sap = svc_daddr(rqstp); 332 struct sockaddr *src_sap = svc_daddr(rqstp);
328 size_t src_len = rqstp->rq_daddrlen; 333 size_t src_len = rqstp->rq_daddrlen;
329 struct net *net = rqstp->rq_xprt->xpt_net; 334 struct net *net = SVC_NET(rqstp);
330 struct nlm_lookup_host_info ni = { 335 struct nlm_lookup_host_info ni = {
331 .server = 1, 336 .server = 1,
332 .sap = svc_addr(rqstp), 337 .sap = svc_addr(rqstp),
@@ -337,6 +342,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
337 .hostname_len = hostname_len, 342 .hostname_len = hostname_len,
338 .net = net, 343 .net = net,
339 }; 344 };
345 struct lockd_net *ln = net_generic(net, lockd_net_id);
340 346
341 dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__, 347 dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__,
342 (int)hostname_len, hostname, rqstp->rq_vers, 348 (int)hostname_len, hostname, rqstp->rq_vers,
@@ -344,8 +350,8 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
344 350
345 mutex_lock(&nlm_host_mutex); 351 mutex_lock(&nlm_host_mutex);
346 352
347 if (time_after_eq(jiffies, next_gc)) 353 if (time_after_eq(jiffies, ln->next_gc))
348 nlm_gc_hosts(); 354 nlm_gc_hosts(net);
349 355
350 chain = &nlm_server_hosts[nlm_hash_address(ni.sap)]; 356 chain = &nlm_server_hosts[nlm_hash_address(ni.sap)];
351 hlist_for_each_entry(host, pos, chain, h_hash) { 357 hlist_for_each_entry(host, pos, chain, h_hash) {
@@ -382,6 +388,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
382 memcpy(nlm_srcaddr(host), src_sap, src_len); 388 memcpy(nlm_srcaddr(host), src_sap, src_len);
383 host->h_srcaddrlen = src_len; 389 host->h_srcaddrlen = src_len;
384 hlist_add_head(&host->h_hash, chain); 390 hlist_add_head(&host->h_hash, chain);
391 ln->nrhosts++;
385 nrhosts++; 392 nrhosts++;
386 393
387 dprintk("lockd: %s created host %s (%s)\n", 394 dprintk("lockd: %s created host %s (%s)\n",
@@ -565,6 +572,35 @@ void nlm_host_rebooted(const struct nlm_reboot *info)
565 nsm_release(nsm); 572 nsm_release(nsm);
566} 573}
567 574
575static void nlm_complain_hosts(struct net *net)
576{
577 struct hlist_head *chain;
578 struct hlist_node *pos;
579 struct nlm_host *host;
580
581 if (net) {
582 struct lockd_net *ln = net_generic(net, lockd_net_id);
583
584 if (ln->nrhosts == 0)
585 return;
586 printk(KERN_WARNING "lockd: couldn't shutdown host module for net %p!\n", net);
587 dprintk("lockd: %lu hosts left in net %p:\n", ln->nrhosts, net);
588 } else {
589 if (nrhosts == 0)
590 return;
591 printk(KERN_WARNING "lockd: couldn't shutdown host module!\n");
592 dprintk("lockd: %lu hosts left:\n", nrhosts);
593 }
594
595 for_each_host(host, pos, chain, nlm_server_hosts) {
596 if (net && host->net != net)
597 continue;
598 dprintk(" %s (cnt %d use %d exp %ld net %p)\n",
599 host->h_name, atomic_read(&host->h_count),
600 host->h_inuse, host->h_expires, host->net);
601 }
602}
603
568void 604void
569nlm_shutdown_hosts_net(struct net *net) 605nlm_shutdown_hosts_net(struct net *net)
570{ 606{
@@ -572,11 +608,10 @@ nlm_shutdown_hosts_net(struct net *net)
572 struct hlist_node *pos; 608 struct hlist_node *pos;
573 struct nlm_host *host; 609 struct nlm_host *host;
574 610
575 dprintk("lockd: shutting down host module\n");
576 mutex_lock(&nlm_host_mutex); 611 mutex_lock(&nlm_host_mutex);
577 612
578 /* First, make all hosts eligible for gc */ 613 /* First, make all hosts eligible for gc */
579 dprintk("lockd: nuking all hosts...\n"); 614 dprintk("lockd: nuking all hosts in net %p...\n", net);
580 for_each_host(host, pos, chain, nlm_server_hosts) { 615 for_each_host(host, pos, chain, nlm_server_hosts) {
581 if (net && host->net != net) 616 if (net && host->net != net)
582 continue; 617 continue;
@@ -588,8 +623,10 @@ nlm_shutdown_hosts_net(struct net *net)
588 } 623 }
589 624
590 /* Then, perform a garbage collection pass */ 625 /* Then, perform a garbage collection pass */
591 nlm_gc_hosts(); 626 nlm_gc_hosts(net);
592 mutex_unlock(&nlm_host_mutex); 627 mutex_unlock(&nlm_host_mutex);
628
629 nlm_complain_hosts(net);
593} 630}
594 631
595/* 632/*
@@ -599,22 +636,8 @@ nlm_shutdown_hosts_net(struct net *net)
599void 636void
600nlm_shutdown_hosts(void) 637nlm_shutdown_hosts(void)
601{ 638{
602 struct hlist_head *chain; 639 dprintk("lockd: shutting down host module\n");
603 struct hlist_node *pos;
604 struct nlm_host *host;
605
606 nlm_shutdown_hosts_net(NULL); 640 nlm_shutdown_hosts_net(NULL);
607
608 /* complain if any hosts are left */
609 if (nrhosts != 0) {
610 printk(KERN_WARNING "lockd: couldn't shutdown host module!\n");
611 dprintk("lockd: %lu hosts left:\n", nrhosts);
612 for_each_host(host, pos, chain, nlm_server_hosts) {
613 dprintk(" %s (cnt %d use %d exp %ld net %p)\n",
614 host->h_name, atomic_read(&host->h_count),
615 host->h_inuse, host->h_expires, host->net);
616 }
617 }
618} 641}
619 642
620/* 643/*
@@ -623,30 +646,39 @@ nlm_shutdown_hosts(void)
623 * mark & sweep for resources held by remote clients. 646 * mark & sweep for resources held by remote clients.
624 */ 647 */
625static void 648static void
626nlm_gc_hosts(void) 649nlm_gc_hosts(struct net *net)
627{ 650{
628 struct hlist_head *chain; 651 struct hlist_head *chain;
629 struct hlist_node *pos, *next; 652 struct hlist_node *pos, *next;
630 struct nlm_host *host; 653 struct nlm_host *host;
631 654
632 dprintk("lockd: host garbage collection\n"); 655 dprintk("lockd: host garbage collection for net %p\n", net);
633 for_each_host(host, pos, chain, nlm_server_hosts) 656 for_each_host(host, pos, chain, nlm_server_hosts) {
657 if (net && host->net != net)
658 continue;
634 host->h_inuse = 0; 659 host->h_inuse = 0;
660 }
635 661
636 /* Mark all hosts that hold locks, blocks or shares */ 662 /* Mark all hosts that hold locks, blocks or shares */
637 nlmsvc_mark_resources(); 663 nlmsvc_mark_resources(net);
638 664
639 for_each_host_safe(host, pos, next, chain, nlm_server_hosts) { 665 for_each_host_safe(host, pos, next, chain, nlm_server_hosts) {
666 if (net && host->net != net)
667 continue;
640 if (atomic_read(&host->h_count) || host->h_inuse 668 if (atomic_read(&host->h_count) || host->h_inuse
641 || time_before(jiffies, host->h_expires)) { 669 || time_before(jiffies, host->h_expires)) {
642 dprintk("nlm_gc_hosts skipping %s " 670 dprintk("nlm_gc_hosts skipping %s "
643 "(cnt %d use %d exp %ld)\n", 671 "(cnt %d use %d exp %ld net %p)\n",
644 host->h_name, atomic_read(&host->h_count), 672 host->h_name, atomic_read(&host->h_count),
645 host->h_inuse, host->h_expires); 673 host->h_inuse, host->h_expires, host->net);
646 continue; 674 continue;
647 } 675 }
648 nlm_destroy_host_locked(host); 676 nlm_destroy_host_locked(host);
649 } 677 }
650 678
651 next_gc = jiffies + NLM_HOST_COLLECT; 679 if (net) {
680 struct lockd_net *ln = net_generic(net, lockd_net_id);
681
682 ln->next_gc = jiffies + NLM_HOST_COLLECT;
683 }
652} 684}
diff --git a/fs/lockd/netns.h b/fs/lockd/netns.h
index ce227e0fbc5c..4eee248ba96e 100644
--- a/fs/lockd/netns.h
+++ b/fs/lockd/netns.h
@@ -1,10 +1,17 @@
1#ifndef __LOCKD_NETNS_H__ 1#ifndef __LOCKD_NETNS_H__
2#define __LOCKD_NETNS_H__ 2#define __LOCKD_NETNS_H__
3 3
4#include <linux/fs.h>
4#include <net/netns/generic.h> 5#include <net/netns/generic.h>
5 6
6struct lockd_net { 7struct lockd_net {
7 unsigned int nlmsvc_users; 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;
8}; 15};
9 16
10extern int lockd_net_id; 17extern int lockd_net_id;
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 80938fda67e0..31a63f87b806 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -87,32 +87,36 @@ static unsigned long get_lockd_grace_period(void)
87 return nlm_timeout * 5 * HZ; 87 return nlm_timeout * 5 * HZ;
88} 88}
89 89
90static struct lock_manager lockd_manager = { 90static void grace_ender(struct work_struct *grace)
91};
92
93static void grace_ender(struct work_struct *not_used)
94{ 91{
95 locks_end_grace(&lockd_manager); 92 struct delayed_work *dwork = container_of(grace, struct delayed_work,
96} 93 work);
94 struct lockd_net *ln = container_of(dwork, struct lockd_net,
95 grace_period_end);
97 96
98static DECLARE_DELAYED_WORK(grace_period_end, grace_ender); 97 locks_end_grace(&ln->lockd_manager);
98}
99 99
100static void set_grace_period(void) 100static void set_grace_period(struct net *net)
101{ 101{
102 unsigned long grace_period = get_lockd_grace_period(); 102 unsigned long grace_period = get_lockd_grace_period();
103 struct lockd_net *ln = net_generic(net, lockd_net_id);
103 104
104 locks_start_grace(&lockd_manager); 105 locks_start_grace(net, &ln->lockd_manager);
105 cancel_delayed_work_sync(&grace_period_end); 106 cancel_delayed_work_sync(&ln->grace_period_end);
106 schedule_delayed_work(&grace_period_end, grace_period); 107 schedule_delayed_work(&ln->grace_period_end, grace_period);
107} 108}
108 109
109static void restart_grace(void) 110static void restart_grace(void)
110{ 111{
111 if (nlmsvc_ops) { 112 if (nlmsvc_ops) {
112 cancel_delayed_work_sync(&grace_period_end); 113 struct net *net = &init_net;
113 locks_end_grace(&lockd_manager); 114 struct lockd_net *ln = net_generic(net, lockd_net_id);
115
116 cancel_delayed_work_sync(&ln->grace_period_end);
117 locks_end_grace(&ln->lockd_manager);
114 nlmsvc_invalidate_all(); 118 nlmsvc_invalidate_all();
115 set_grace_period(); 119 set_grace_period(net);
116 } 120 }
117} 121}
118 122
@@ -137,8 +141,6 @@ lockd(void *vrqstp)
137 nlm_timeout = LOCKD_DFLT_TIMEO; 141 nlm_timeout = LOCKD_DFLT_TIMEO;
138 nlmsvc_timeout = nlm_timeout * HZ; 142 nlmsvc_timeout = nlm_timeout * HZ;
139 143
140 set_grace_period();
141
142 /* 144 /*
143 * The main request loop. We don't terminate until the last 145 * The main request loop. We don't terminate until the last
144 * NFS mount or NFS daemon has gone away. 146 * NFS mount or NFS daemon has gone away.
@@ -184,8 +186,6 @@ lockd(void *vrqstp)
184 svc_process(rqstp); 186 svc_process(rqstp);
185 } 187 }
186 flush_signals(current); 188 flush_signals(current);
187 cancel_delayed_work_sync(&grace_period_end);
188 locks_end_grace(&lockd_manager);
189 if (nlmsvc_ops) 189 if (nlmsvc_ops)
190 nlmsvc_invalidate_all(); 190 nlmsvc_invalidate_all();
191 nlm_shutdown_hosts(); 191 nlm_shutdown_hosts();
@@ -266,6 +266,7 @@ static int lockd_up_net(struct svc_serv *serv, struct net *net)
266 error = make_socks(serv, net); 266 error = make_socks(serv, net);
267 if (error < 0) 267 if (error < 0)
268 goto err_socks; 268 goto err_socks;
269 set_grace_period(net);
269 dprintk("lockd_up_net: per-net data created; net=%p\n", net); 270 dprintk("lockd_up_net: per-net data created; net=%p\n", net);
270 return 0; 271 return 0;
271 272
@@ -283,6 +284,8 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net)
283 if (ln->nlmsvc_users) { 284 if (ln->nlmsvc_users) {
284 if (--ln->nlmsvc_users == 0) { 285 if (--ln->nlmsvc_users == 0) {
285 nlm_shutdown_hosts_net(net); 286 nlm_shutdown_hosts_net(net);
287 cancel_delayed_work_sync(&ln->grace_period_end);
288 locks_end_grace(&ln->lockd_manager);
286 svc_shutdown_net(serv, net); 289 svc_shutdown_net(serv, net);
287 dprintk("lockd_down_net: per-net data destroyed; net=%p\n", net); 290 dprintk("lockd_down_net: per-net data destroyed; net=%p\n", net);
288 } 291 }
@@ -589,6 +592,10 @@ module_param(nlm_max_connections, uint, 0644);
589 592
590static int lockd_init_net(struct net *net) 593static int lockd_init_net(struct net *net)
591{ 594{
595 struct lockd_net *ln = net_generic(net, lockd_net_id);
596
597 INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender);
598 INIT_LIST_HEAD(&ln->grace_list);
592 return 0; 599 return 0;
593} 600}
594 601
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index 9a41fdc19511..4a43d253c045 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -11,6 +11,7 @@
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>
14 15
15#define NLMDBG_FACILITY NLMDBG_CLIENT 16#define NLMDBG_FACILITY NLMDBG_CLIENT
16 17
@@ -151,7 +152,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
151 resp->cookie = argp->cookie; 152 resp->cookie = argp->cookie;
152 153
153 /* Don't accept requests during grace period */ 154 /* Don't accept requests during grace period */
154 if (locks_in_grace()) { 155 if (locks_in_grace(SVC_NET(rqstp))) {
155 resp->status = nlm_lck_denied_grace_period; 156 resp->status = nlm_lck_denied_grace_period;
156 return rpc_success; 157 return rpc_success;
157 } 158 }
@@ -161,7 +162,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
161 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 162 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
162 163
163 /* Try to cancel request. */ 164 /* Try to cancel request. */
164 resp->status = nlmsvc_cancel_blocked(file, &argp->lock); 165 resp->status = nlmsvc_cancel_blocked(SVC_NET(rqstp), file, &argp->lock);
165 166
166 dprintk("lockd: CANCEL status %d\n", ntohl(resp->status)); 167 dprintk("lockd: CANCEL status %d\n", ntohl(resp->status));
167 nlmsvc_release_host(host); 168 nlmsvc_release_host(host);
@@ -184,7 +185,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
184 resp->cookie = argp->cookie; 185 resp->cookie = argp->cookie;
185 186
186 /* Don't accept new lock requests during grace period */ 187 /* Don't accept new lock requests during grace period */
187 if (locks_in_grace()) { 188 if (locks_in_grace(SVC_NET(rqstp))) {
188 resp->status = nlm_lck_denied_grace_period; 189 resp->status = nlm_lck_denied_grace_period;
189 return rpc_success; 190 return rpc_success;
190 } 191 }
@@ -194,7 +195,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
194 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 195 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
195 196
196 /* Now try to remove the lock */ 197 /* Now try to remove the lock */
197 resp->status = nlmsvc_unlock(file, &argp->lock); 198 resp->status = nlmsvc_unlock(SVC_NET(rqstp), file, &argp->lock);
198 199
199 dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status)); 200 dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status));
200 nlmsvc_release_host(host); 201 nlmsvc_release_host(host);
@@ -321,7 +322,7 @@ nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
321 resp->cookie = argp->cookie; 322 resp->cookie = argp->cookie;
322 323
323 /* Don't accept new lock requests during grace period */ 324 /* Don't accept new lock requests during grace period */
324 if (locks_in_grace() && !argp->reclaim) { 325 if (locks_in_grace(SVC_NET(rqstp)) && !argp->reclaim) {
325 resp->status = nlm_lck_denied_grace_period; 326 resp->status = nlm_lck_denied_grace_period;
326 return rpc_success; 327 return rpc_success;
327 } 328 }
@@ -354,7 +355,7 @@ nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
354 resp->cookie = argp->cookie; 355 resp->cookie = argp->cookie;
355 356
356 /* Don't accept requests during grace period */ 357 /* Don't accept requests during grace period */
357 if (locks_in_grace()) { 358 if (locks_in_grace(SVC_NET(rqstp))) {
358 resp->status = nlm_lck_denied_grace_period; 359 resp->status = nlm_lck_denied_grace_period;
359 return rpc_success; 360 return rpc_success;
360 } 361 }
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index e46353f41a42..afe4488c33d8 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.h> 29#include <linux/sunrpc/svc_xprt.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>
@@ -447,11 +447,11 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
447 goto out; 447 goto out;
448 } 448 }
449 449
450 if (locks_in_grace() && !reclaim) { 450 if (locks_in_grace(SVC_NET(rqstp)) && !reclaim) {
451 ret = nlm_lck_denied_grace_period; 451 ret = nlm_lck_denied_grace_period;
452 goto out; 452 goto out;
453 } 453 }
454 if (reclaim && !locks_in_grace()) { 454 if (reclaim && !locks_in_grace(SVC_NET(rqstp))) {
455 ret = nlm_lck_denied_grace_period; 455 ret = nlm_lck_denied_grace_period;
456 goto out; 456 goto out;
457 } 457 }
@@ -559,7 +559,7 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
559 goto out; 559 goto out;
560 } 560 }
561 561
562 if (locks_in_grace()) { 562 if (locks_in_grace(SVC_NET(rqstp))) {
563 ret = nlm_lck_denied_grace_period; 563 ret = nlm_lck_denied_grace_period;
564 goto out; 564 goto out;
565 } 565 }
@@ -603,7 +603,7 @@ out:
603 * must be removed. 603 * must be removed.
604 */ 604 */
605__be32 605__be32
606nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock) 606nlmsvc_unlock(struct net *net, struct nlm_file *file, struct nlm_lock *lock)
607{ 607{
608 int error; 608 int error;
609 609
@@ -615,7 +615,7 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
615 (long long)lock->fl.fl_end); 615 (long long)lock->fl.fl_end);
616 616
617 /* First, cancel any lock that might be there */ 617 /* First, cancel any lock that might be there */
618 nlmsvc_cancel_blocked(file, lock); 618 nlmsvc_cancel_blocked(net, file, lock);
619 619
620 lock->fl.fl_type = F_UNLCK; 620 lock->fl.fl_type = F_UNLCK;
621 error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL); 621 error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);
@@ -631,7 +631,7 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
631 * The calling procedure must check whether the file can be closed. 631 * The calling procedure must check whether the file can be closed.
632 */ 632 */
633__be32 633__be32
634nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) 634nlmsvc_cancel_blocked(struct net *net, struct nlm_file *file, struct nlm_lock *lock)
635{ 635{
636 struct nlm_block *block; 636 struct nlm_block *block;
637 int status = 0; 637 int status = 0;
@@ -643,7 +643,7 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
643 (long long)lock->fl.fl_start, 643 (long long)lock->fl.fl_start,
644 (long long)lock->fl.fl_end); 644 (long long)lock->fl.fl_end);
645 645
646 if (locks_in_grace()) 646 if (locks_in_grace(net))
647 return nlm_lck_denied_grace_period; 647 return nlm_lck_denied_grace_period;
648 648
649 mutex_lock(&file->f_mutex); 649 mutex_lock(&file->f_mutex);
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index d27aab11f324..de8f2caa2235 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -11,6 +11,7 @@
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>
14 15
15#define NLMDBG_FACILITY NLMDBG_CLIENT 16#define NLMDBG_FACILITY NLMDBG_CLIENT
16 17
@@ -175,13 +176,14 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
175{ 176{
176 struct nlm_host *host; 177 struct nlm_host *host;
177 struct nlm_file *file; 178 struct nlm_file *file;
179 struct net *net = SVC_NET(rqstp);
178 180
179 dprintk("lockd: CANCEL called\n"); 181 dprintk("lockd: CANCEL called\n");
180 182
181 resp->cookie = argp->cookie; 183 resp->cookie = argp->cookie;
182 184
183 /* Don't accept requests during grace period */ 185 /* Don't accept requests during grace period */
184 if (locks_in_grace()) { 186 if (locks_in_grace(net)) {
185 resp->status = nlm_lck_denied_grace_period; 187 resp->status = nlm_lck_denied_grace_period;
186 return rpc_success; 188 return rpc_success;
187 } 189 }
@@ -191,7 +193,7 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
191 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 193 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
192 194
193 /* Try to cancel request. */ 195 /* Try to cancel request. */
194 resp->status = cast_status(nlmsvc_cancel_blocked(file, &argp->lock)); 196 resp->status = cast_status(nlmsvc_cancel_blocked(net, file, &argp->lock));
195 197
196 dprintk("lockd: CANCEL status %d\n", ntohl(resp->status)); 198 dprintk("lockd: CANCEL status %d\n", ntohl(resp->status));
197 nlmsvc_release_host(host); 199 nlmsvc_release_host(host);
@@ -208,13 +210,14 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
208{ 210{
209 struct nlm_host *host; 211 struct nlm_host *host;
210 struct nlm_file *file; 212 struct nlm_file *file;
213 struct net *net = SVC_NET(rqstp);
211 214
212 dprintk("lockd: UNLOCK called\n"); 215 dprintk("lockd: UNLOCK called\n");
213 216
214 resp->cookie = argp->cookie; 217 resp->cookie = argp->cookie;
215 218
216 /* Don't accept new lock requests during grace period */ 219 /* Don't accept new lock requests during grace period */
217 if (locks_in_grace()) { 220 if (locks_in_grace(net)) {
218 resp->status = nlm_lck_denied_grace_period; 221 resp->status = nlm_lck_denied_grace_period;
219 return rpc_success; 222 return rpc_success;
220 } 223 }
@@ -224,7 +227,7 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
224 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 227 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
225 228
226 /* Now try to remove the lock */ 229 /* Now try to remove the lock */
227 resp->status = cast_status(nlmsvc_unlock(file, &argp->lock)); 230 resp->status = cast_status(nlmsvc_unlock(net, file, &argp->lock));
228 231
229 dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status)); 232 dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status));
230 nlmsvc_release_host(host); 233 nlmsvc_release_host(host);
@@ -361,7 +364,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
361 resp->cookie = argp->cookie; 364 resp->cookie = argp->cookie;
362 365
363 /* Don't accept new lock requests during grace period */ 366 /* Don't accept new lock requests during grace period */
364 if (locks_in_grace() && !argp->reclaim) { 367 if (locks_in_grace(SVC_NET(rqstp)) && !argp->reclaim) {
365 resp->status = nlm_lck_denied_grace_period; 368 resp->status = nlm_lck_denied_grace_period;
366 return rpc_success; 369 return rpc_success;
367 } 370 }
@@ -394,7 +397,7 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
394 resp->cookie = argp->cookie; 397 resp->cookie = argp->cookie;
395 398
396 /* Don't accept requests during grace period */ 399 /* Don't accept requests during grace period */
397 if (locks_in_grace()) { 400 if (locks_in_grace(SVC_NET(rqstp))) {
398 resp->status = nlm_lck_denied_grace_period; 401 resp->status = nlm_lck_denied_grace_period;
399 return rpc_success; 402 return rpc_success;
400 } 403 }
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index 2240d384d787..0deb5f6c9dd4 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -309,7 +309,8 @@ 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. 312 * used by the garbage collector; simply sets h_inuse only for those
313 * hosts, which passed network check.
313 * Always returns 0. 314 * Always returns 0.
314 * 315 *
315 * nlmsvc_same_host: 316 * nlmsvc_same_host:
@@ -320,12 +321,15 @@ nlm_release_file(struct nlm_file *file)
320 * returns 1 iff the host is a client. 321 * returns 1 iff the host is a client.
321 * Used by nlmsvc_invalidate_all 322 * Used by nlmsvc_invalidate_all
322 */ 323 */
324
323static int 325static int
324nlmsvc_mark_host(void *data, struct nlm_host *dummy) 326nlmsvc_mark_host(void *data, struct nlm_host *hint)
325{ 327{
326 struct nlm_host *host = data; 328 struct nlm_host *host = data;
327 329
328 host->h_inuse = 1; 330 if ((hint->net == NULL) ||
331 (host->net == hint->net))
332 host->h_inuse = 1;
329 return 0; 333 return 0;
330} 334}
331 335
@@ -358,10 +362,13 @@ nlmsvc_is_client(void *data, struct nlm_host *dummy)
358 * Mark all hosts that still hold resources 362 * Mark all hosts that still hold resources
359 */ 363 */
360void 364void
361nlmsvc_mark_resources(void) 365nlmsvc_mark_resources(struct net *net)
362{ 366{
363 dprintk("lockd: nlmsvc_mark_resources\n"); 367 struct nlm_host hint;
364 nlm_traverse_files(NULL, nlmsvc_mark_host, NULL); 368
369 dprintk("lockd: nlmsvc_mark_resources for net %p\n", net);
370 hint.net = net;
371 nlm_traverse_files(&hint, nlmsvc_mark_host, NULL);
365} 372}
366 373
367/* 374/*
diff --git a/fs/locks.c b/fs/locks.c
index 82c353304f9e..cdcf219a7391 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -427,18 +427,8 @@ static void lease_break_callback(struct file_lock *fl)
427 kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG); 427 kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG);
428} 428}
429 429
430static void lease_release_private_callback(struct file_lock *fl)
431{
432 if (!fl->fl_file)
433 return;
434
435 f_delown(fl->fl_file);
436 fl->fl_file->f_owner.signum = 0;
437}
438
439static const struct lock_manager_operations lease_manager_ops = { 430static const struct lock_manager_operations lease_manager_ops = {
440 .lm_break = lease_break_callback, 431 .lm_break = lease_break_callback,
441 .lm_release_private = lease_release_private_callback,
442 .lm_change = lease_modify, 432 .lm_change = lease_modify,
443}; 433};
444 434
@@ -580,12 +570,6 @@ static void locks_delete_lock(struct file_lock **thisfl_p)
580 fl->fl_next = NULL; 570 fl->fl_next = NULL;
581 list_del_init(&fl->fl_link); 571 list_del_init(&fl->fl_link);
582 572
583 fasync_helper(0, fl->fl_file, 0, &fl->fl_fasync);
584 if (fl->fl_fasync != NULL) {
585 printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync);
586 fl->fl_fasync = NULL;
587 }
588
589 if (fl->fl_nspid) { 573 if (fl->fl_nspid) {
590 put_pid(fl->fl_nspid); 574 put_pid(fl->fl_nspid);
591 fl->fl_nspid = NULL; 575 fl->fl_nspid = NULL;
@@ -1155,8 +1139,18 @@ int lease_modify(struct file_lock **before, int arg)
1155 return error; 1139 return error;
1156 lease_clear_pending(fl, arg); 1140 lease_clear_pending(fl, arg);
1157 locks_wake_up_blocks(fl); 1141 locks_wake_up_blocks(fl);
1158 if (arg == F_UNLCK) 1142 if (arg == F_UNLCK) {
1143 struct file *filp = fl->fl_file;
1144
1145 f_delown(filp);
1146 filp->f_owner.signum = 0;
1147 fasync_helper(0, fl->fl_file, 0, &fl->fl_fasync);
1148 if (fl->fl_fasync != NULL) {
1149 printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync);
1150 fl->fl_fasync = NULL;
1151 }
1159 locks_delete_lock(before); 1152 locks_delete_lock(before);
1153 }
1160 return 0; 1154 return 0;
1161} 1155}
1162 1156
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index e64b01d2a338..742ff4ffced7 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -863,7 +863,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
863 .drc_status = 0, 863 .drc_status = 0,
864 .clp = NULL, 864 .clp = NULL,
865 .slotid = NFS4_NO_SLOT, 865 .slotid = NFS4_NO_SLOT,
866 .net = rqstp->rq_xprt->xpt_net, 866 .net = SVC_NET(rqstp),
867 }; 867 };
868 unsigned int nops = 0; 868 unsigned int nops = 0;
869 869
@@ -879,7 +879,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
879 return rpc_garbage_args; 879 return rpc_garbage_args;
880 880
881 if (hdr_arg.minorversion == 0) { 881 if (hdr_arg.minorversion == 0) {
882 cps.clp = nfs4_find_client_ident(rqstp->rq_xprt->xpt_net, hdr_arg.cb_ident); 882 cps.clp = nfs4_find_client_ident(SVC_NET(rqstp), hdr_arg.cb_ident);
883 if (!cps.clp || !check_gss_callback_principal(cps.clp, rqstp)) 883 if (!cps.clp || !check_gss_callback_principal(cps.clp, rqstp))
884 return rpc_drop_reply; 884 return rpc_drop_reply;
885 } 885 }
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index ba233499b9a5..a3946cf13fc8 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -398,7 +398,7 @@ fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc)
398 int migrated, i, err; 398 int migrated, i, err;
399 399
400 /* listsize */ 400 /* listsize */
401 err = get_int(mesg, &fsloc->locations_count); 401 err = get_uint(mesg, &fsloc->locations_count);
402 if (err) 402 if (err)
403 return err; 403 return err;
404 if (fsloc->locations_count > MAX_FS_LOCATIONS) 404 if (fsloc->locations_count > MAX_FS_LOCATIONS)
@@ -456,7 +456,7 @@ static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp)
456 return -EINVAL; 456 return -EINVAL;
457 457
458 for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) { 458 for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) {
459 err = get_int(mesg, &f->pseudoflavor); 459 err = get_uint(mesg, &f->pseudoflavor);
460 if (err) 460 if (err)
461 return err; 461 return err;
462 /* 462 /*
@@ -465,7 +465,7 @@ static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp)
465 * problem at export time instead of when a client fails 465 * problem at export time instead of when a client fails
466 * to authenticate. 466 * to authenticate.
467 */ 467 */
468 err = get_int(mesg, &f->flags); 468 err = get_uint(mesg, &f->flags);
469 if (err) 469 if (err)
470 return err; 470 return err;
471 /* Only some flags are allowed to differ between flavors: */ 471 /* Only some flags are allowed to differ between flavors: */
@@ -929,7 +929,7 @@ struct svc_export *
929rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path) 929rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path)
930{ 930{
931 struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); 931 struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
932 struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); 932 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
933 struct cache_detail *cd = nn->svc_export_cache; 933 struct cache_detail *cd = nn->svc_export_cache;
934 934
935 if (rqstp->rq_client == NULL) 935 if (rqstp->rq_client == NULL)
@@ -960,7 +960,7 @@ struct svc_export *
960rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv) 960rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv)
961{ 961{
962 struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); 962 struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
963 struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); 963 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
964 struct cache_detail *cd = nn->svc_export_cache; 964 struct cache_detail *cd = nn->svc_export_cache;
965 965
966 if (rqstp->rq_client == NULL) 966 if (rqstp->rq_client == NULL)
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index 39365636b244..65c2431ea32f 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -34,6 +34,10 @@ struct nfsd_net {
34 34
35 struct cache_detail *idtoname_cache; 35 struct cache_detail *idtoname_cache;
36 struct cache_detail *nametoid_cache; 36 struct cache_detail *nametoid_cache;
37
38 struct lock_manager nfsd4_manager;
39 bool grace_ended;
40 time_t boot_time;
37}; 41};
38 42
39extern int nfsd_net_id; 43extern int nfsd_net_id;
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index a5fd6b982f27..cbaf4f8bb7b7 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -756,7 +756,6 @@ static void do_probe_callback(struct nfs4_client *clp)
756 */ 756 */
757void nfsd4_probe_callback(struct nfs4_client *clp) 757void nfsd4_probe_callback(struct nfs4_client *clp)
758{ 758{
759 /* XXX: atomicity? Also, should we be using cl_flags? */
760 clp->cl_cb_state = NFSD4_CB_UNKNOWN; 759 clp->cl_cb_state = NFSD4_CB_UNKNOWN;
761 set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags); 760 set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags);
762 do_probe_callback(clp); 761 do_probe_callback(clp);
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index dae36f1dee95..fdc91a6fc9c4 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -546,7 +546,7 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen
546 .type = type, 546 .type = type,
547 }; 547 };
548 int ret; 548 int ret;
549 struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); 549 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
550 550
551 if (namelen + 1 > sizeof(key.name)) 551 if (namelen + 1 > sizeof(key.name))
552 return nfserr_badowner; 552 return nfserr_badowner;
@@ -571,7 +571,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
571 .type = type, 571 .type = type,
572 }; 572 };
573 int ret; 573 int ret;
574 struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); 574 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
575 575
576 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); 576 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
577 ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item); 577 ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item);
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 987e719fbae8..c9c1c0a25417 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -354,10 +354,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
354 /* Openowner is now set, so sequence id will get bumped. Now we need 354 /* Openowner is now set, so sequence id will get bumped. Now we need
355 * these checks before we do any creates: */ 355 * these checks before we do any creates: */
356 status = nfserr_grace; 356 status = nfserr_grace;
357 if (locks_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) 357 if (locks_in_grace(SVC_NET(rqstp)) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
358 goto out; 358 goto out;
359 status = nfserr_no_grace; 359 status = nfserr_no_grace;
360 if (!locks_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) 360 if (!locks_in_grace(SVC_NET(rqstp)) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
361 goto out; 361 goto out;
362 362
363 switch (open->op_claim_type) { 363 switch (open->op_claim_type) {
@@ -686,7 +686,8 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
686 686
687 nfs4_lock_state(); 687 nfs4_lock_state();
688 /* check stateid */ 688 /* check stateid */
689 if ((status = nfs4_preprocess_stateid_op(cstate, &read->rd_stateid, 689 if ((status = nfs4_preprocess_stateid_op(SVC_NET(rqstp),
690 cstate, &read->rd_stateid,
690 RD_STATE, &read->rd_filp))) { 691 RD_STATE, &read->rd_filp))) {
691 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n"); 692 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
692 goto out; 693 goto out;
@@ -741,7 +742,7 @@ nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
741{ 742{
742 __be32 status; 743 __be32 status;
743 744
744 if (locks_in_grace()) 745 if (locks_in_grace(SVC_NET(rqstp)))
745 return nfserr_grace; 746 return nfserr_grace;
746 status = nfsd_unlink(rqstp, &cstate->current_fh, 0, 747 status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
747 remove->rm_name, remove->rm_namelen); 748 remove->rm_name, remove->rm_namelen);
@@ -760,8 +761,8 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
760 761
761 if (!cstate->save_fh.fh_dentry) 762 if (!cstate->save_fh.fh_dentry)
762 return status; 763 return status;
763 if (locks_in_grace() && !(cstate->save_fh.fh_export->ex_flags 764 if (locks_in_grace(SVC_NET(rqstp)) &&
764 & NFSEXP_NOSUBTREECHECK)) 765 !(cstate->save_fh.fh_export->ex_flags & NFSEXP_NOSUBTREECHECK))
765 return nfserr_grace; 766 return nfserr_grace;
766 status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname, 767 status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
767 rename->rn_snamelen, &cstate->current_fh, 768 rename->rn_snamelen, &cstate->current_fh,
@@ -845,7 +846,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
845 846
846 if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { 847 if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
847 nfs4_lock_state(); 848 nfs4_lock_state();
848 status = nfs4_preprocess_stateid_op(cstate, 849 status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), cstate,
849 &setattr->sa_stateid, WR_STATE, NULL); 850 &setattr->sa_stateid, WR_STATE, NULL);
850 nfs4_unlock_state(); 851 nfs4_unlock_state();
851 if (status) { 852 if (status) {
@@ -890,7 +891,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
890 return nfserr_inval; 891 return nfserr_inval;
891 892
892 nfs4_lock_state(); 893 nfs4_lock_state();
893 status = nfs4_preprocess_stateid_op(cstate, stateid, WR_STATE, &filp); 894 status = nfs4_preprocess_stateid_op(SVC_NET(rqstp),
895 cstate, stateid, WR_STATE, &filp);
894 if (filp) 896 if (filp)
895 get_file(filp); 897 get_file(filp);
896 nfs4_unlock_state(); 898 nfs4_unlock_state();
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 94effd5bc4a1..cc894eda385a 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -38,18 +38,21 @@
38#include <linux/namei.h> 38#include <linux/namei.h>
39#include <linux/swap.h> 39#include <linux/swap.h>
40#include <linux/pagemap.h> 40#include <linux/pagemap.h>
41#include <linux/ratelimit.h>
41#include <linux/sunrpc/svcauth_gss.h> 42#include <linux/sunrpc/svcauth_gss.h>
42#include <linux/sunrpc/clnt.h> 43#include <linux/sunrpc/clnt.h>
43#include "xdr4.h" 44#include "xdr4.h"
44#include "vfs.h" 45#include "vfs.h"
45#include "current_stateid.h" 46#include "current_stateid.h"
47#include "fault_inject.h"
48
49#include "netns.h"
46 50
47#define NFSDDBG_FACILITY NFSDDBG_PROC 51#define NFSDDBG_FACILITY NFSDDBG_PROC
48 52
49/* Globals */ 53/* Globals */
50time_t nfsd4_lease = 90; /* default lease time */ 54time_t nfsd4_lease = 90; /* default lease time */
51time_t nfsd4_grace = 90; 55time_t nfsd4_grace = 90;
52static time_t boot_time;
53 56
54#define all_ones {{~0,~0},~0} 57#define all_ones {{~0,~0},~0}
55static const stateid_t one_stateid = { 58static const stateid_t one_stateid = {
@@ -862,6 +865,11 @@ static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses,
862 if (ret) 865 if (ret)
863 /* oops; xprt is already down: */ 866 /* oops; xprt is already down: */
864 nfsd4_conn_lost(&conn->cn_xpt_user); 867 nfsd4_conn_lost(&conn->cn_xpt_user);
868 if (ses->se_client->cl_cb_state == NFSD4_CB_DOWN &&
869 dir & NFS4_CDFC4_BACK) {
870 /* callback channel may be back up */
871 nfsd4_probe_callback(ses->se_client);
872 }
865 return nfs_ok; 873 return nfs_ok;
866} 874}
867 875
@@ -1047,12 +1055,12 @@ renew_client(struct nfs4_client *clp)
1047 1055
1048/* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */ 1056/* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */
1049static int 1057static int
1050STALE_CLIENTID(clientid_t *clid) 1058STALE_CLIENTID(clientid_t *clid, struct nfsd_net *nn)
1051{ 1059{
1052 if (clid->cl_boot == boot_time) 1060 if (clid->cl_boot == nn->boot_time)
1053 return 0; 1061 return 0;
1054 dprintk("NFSD stale clientid (%08x/%08x) boot_time %08lx\n", 1062 dprintk("NFSD stale clientid (%08x/%08x) boot_time %08lx\n",
1055 clid->cl_boot, clid->cl_id, boot_time); 1063 clid->cl_boot, clid->cl_id, nn->boot_time);
1056 return 1; 1064 return 1;
1057} 1065}
1058 1066
@@ -1215,7 +1223,7 @@ static bool groups_equal(struct group_info *g1, struct group_info *g2)
1215 return true; 1223 return true;
1216} 1224}
1217 1225
1218static int 1226static bool
1219same_creds(struct svc_cred *cr1, struct svc_cred *cr2) 1227same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
1220{ 1228{
1221 if ((cr1->cr_flavor != cr2->cr_flavor) 1229 if ((cr1->cr_flavor != cr2->cr_flavor)
@@ -1227,14 +1235,15 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
1227 return true; 1235 return true;
1228 if (!cr1->cr_principal || !cr2->cr_principal) 1236 if (!cr1->cr_principal || !cr2->cr_principal)
1229 return false; 1237 return false;
1230 return 0 == strcmp(cr1->cr_principal, cr1->cr_principal); 1238 return 0 == strcmp(cr1->cr_principal, cr2->cr_principal);
1231} 1239}
1232 1240
1233static void gen_clid(struct nfs4_client *clp) 1241static void gen_clid(struct nfs4_client *clp)
1234{ 1242{
1235 static u32 current_clientid = 1; 1243 static u32 current_clientid = 1;
1244 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
1236 1245
1237 clp->cl_clientid.cl_boot = boot_time; 1246 clp->cl_clientid.cl_boot = nn->boot_time;
1238 clp->cl_clientid.cl_id = current_clientid++; 1247 clp->cl_clientid.cl_id = current_clientid++;
1239} 1248}
1240 1249
@@ -2217,8 +2226,9 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
2217 nfs4_verifier confirm = setclientid_confirm->sc_confirm; 2226 nfs4_verifier confirm = setclientid_confirm->sc_confirm;
2218 clientid_t * clid = &setclientid_confirm->sc_clientid; 2227 clientid_t * clid = &setclientid_confirm->sc_clientid;
2219 __be32 status; 2228 __be32 status;
2229 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
2220 2230
2221 if (STALE_CLIENTID(clid)) 2231 if (STALE_CLIENTID(clid, nn))
2222 return nfserr_stale_clientid; 2232 return nfserr_stale_clientid;
2223 nfs4_lock_state(); 2233 nfs4_lock_state();
2224 2234
@@ -2577,8 +2587,9 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate,
2577 unsigned int strhashval; 2587 unsigned int strhashval;
2578 struct nfs4_openowner *oo = NULL; 2588 struct nfs4_openowner *oo = NULL;
2579 __be32 status; 2589 __be32 status;
2590 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
2580 2591
2581 if (STALE_CLIENTID(&open->op_clientid)) 2592 if (STALE_CLIENTID(&open->op_clientid, nn))
2582 return nfserr_stale_clientid; 2593 return nfserr_stale_clientid;
2583 /* 2594 /*
2584 * In case we need it later, after we've already created the 2595 * In case we need it later, after we've already created the
@@ -2876,7 +2887,8 @@ static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
2876 * Attempt to hand out a delegation. 2887 * Attempt to hand out a delegation.
2877 */ 2888 */
2878static void 2889static void
2879nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_stateid *stp) 2890nfs4_open_delegation(struct net *net, struct svc_fh *fh,
2891 struct nfsd4_open *open, struct nfs4_ol_stateid *stp)
2880{ 2892{
2881 struct nfs4_delegation *dp; 2893 struct nfs4_delegation *dp;
2882 struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner); 2894 struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner);
@@ -2897,7 +2909,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_
2897 case NFS4_OPEN_CLAIM_NULL: 2909 case NFS4_OPEN_CLAIM_NULL:
2898 /* Let's not give out any delegations till everyone's 2910 /* Let's not give out any delegations till everyone's
2899 * had the chance to reclaim theirs.... */ 2911 * had the chance to reclaim theirs.... */
2900 if (locks_in_grace()) 2912 if (locks_in_grace(net))
2901 goto out; 2913 goto out;
2902 if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED)) 2914 if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED))
2903 goto out; 2915 goto out;
@@ -3007,14 +3019,12 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
3007 status = nfs4_get_vfs_file(rqstp, fp, current_fh, open); 3019 status = nfs4_get_vfs_file(rqstp, fp, current_fh, open);
3008 if (status) 3020 if (status)
3009 goto out; 3021 goto out;
3022 status = nfsd4_truncate(rqstp, current_fh, open);
3023 if (status)
3024 goto out;
3010 stp = open->op_stp; 3025 stp = open->op_stp;
3011 open->op_stp = NULL; 3026 open->op_stp = NULL;
3012 init_open_stateid(stp, fp, open); 3027 init_open_stateid(stp, fp, open);
3013 status = nfsd4_truncate(rqstp, current_fh, open);
3014 if (status) {
3015 release_open_stateid(stp);
3016 goto out;
3017 }
3018 } 3028 }
3019 update_stateid(&stp->st_stid.sc_stateid); 3029 update_stateid(&stp->st_stid.sc_stateid);
3020 memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); 3030 memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
@@ -3033,7 +3043,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
3033 * Attempt to hand out a delegation. No error return, because the 3043 * Attempt to hand out a delegation. No error return, because the
3034 * OPEN succeeds even if we fail. 3044 * OPEN succeeds even if we fail.
3035 */ 3045 */
3036 nfs4_open_delegation(current_fh, open, stp); 3046 nfs4_open_delegation(SVC_NET(rqstp), current_fh, open, stp);
3037nodeleg: 3047nodeleg:
3038 status = nfs_ok; 3048 status = nfs_ok;
3039 3049
@@ -3087,12 +3097,13 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3087{ 3097{
3088 struct nfs4_client *clp; 3098 struct nfs4_client *clp;
3089 __be32 status; 3099 __be32 status;
3100 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
3090 3101
3091 nfs4_lock_state(); 3102 nfs4_lock_state();
3092 dprintk("process_renew(%08x/%08x): starting\n", 3103 dprintk("process_renew(%08x/%08x): starting\n",
3093 clid->cl_boot, clid->cl_id); 3104 clid->cl_boot, clid->cl_id);
3094 status = nfserr_stale_clientid; 3105 status = nfserr_stale_clientid;
3095 if (STALE_CLIENTID(clid)) 3106 if (STALE_CLIENTID(clid, nn))
3096 goto out; 3107 goto out;
3097 clp = find_confirmed_client(clid); 3108 clp = find_confirmed_client(clid);
3098 status = nfserr_expired; 3109 status = nfserr_expired;
@@ -3111,22 +3122,19 @@ out:
3111 return status; 3122 return status;
3112} 3123}
3113 3124
3114static struct lock_manager nfsd4_manager = {
3115};
3116
3117static bool grace_ended;
3118
3119static void 3125static void
3120nfsd4_end_grace(void) 3126nfsd4_end_grace(struct net *net)
3121{ 3127{
3128 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
3129
3122 /* do nothing if grace period already ended */ 3130 /* do nothing if grace period already ended */
3123 if (grace_ended) 3131 if (nn->grace_ended)
3124 return; 3132 return;
3125 3133
3126 dprintk("NFSD: end of grace period\n"); 3134 dprintk("NFSD: end of grace period\n");
3127 grace_ended = true; 3135 nn->grace_ended = true;
3128 nfsd4_record_grace_done(&init_net, boot_time); 3136 nfsd4_record_grace_done(net, nn->boot_time);
3129 locks_end_grace(&nfsd4_manager); 3137 locks_end_grace(&nn->nfsd4_manager);
3130 /* 3138 /*
3131 * Now that every NFSv4 client has had the chance to recover and 3139 * Now that every NFSv4 client has had the chance to recover and
3132 * to see the (possibly new, possibly shorter) lease time, we 3140 * to see the (possibly new, possibly shorter) lease time, we
@@ -3149,7 +3157,7 @@ nfs4_laundromat(void)
3149 nfs4_lock_state(); 3157 nfs4_lock_state();
3150 3158
3151 dprintk("NFSD: laundromat service - starting\n"); 3159 dprintk("NFSD: laundromat service - starting\n");
3152 nfsd4_end_grace(); 3160 nfsd4_end_grace(&init_net);
3153 INIT_LIST_HEAD(&reaplist); 3161 INIT_LIST_HEAD(&reaplist);
3154 spin_lock(&client_lock); 3162 spin_lock(&client_lock);
3155 list_for_each_safe(pos, next, &client_lru) { 3163 list_for_each_safe(pos, next, &client_lru) {
@@ -3231,9 +3239,9 @@ static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_ol_stateid *s
3231} 3239}
3232 3240
3233static int 3241static int
3234STALE_STATEID(stateid_t *stateid) 3242STALE_STATEID(stateid_t *stateid, struct nfsd_net *nn)
3235{ 3243{
3236 if (stateid->si_opaque.so_clid.cl_boot == boot_time) 3244 if (stateid->si_opaque.so_clid.cl_boot == nn->boot_time)
3237 return 0; 3245 return 0;
3238 dprintk("NFSD: stale stateid " STATEID_FMT "!\n", 3246 dprintk("NFSD: stale stateid " STATEID_FMT "!\n",
3239 STATEID_VAL(stateid)); 3247 STATEID_VAL(stateid));
@@ -3273,11 +3281,11 @@ out:
3273} 3281}
3274 3282
3275static inline __be32 3283static inline __be32
3276check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags) 3284check_special_stateids(struct net *net, svc_fh *current_fh, stateid_t *stateid, int flags)
3277{ 3285{
3278 if (ONE_STATEID(stateid) && (flags & RD_STATE)) 3286 if (ONE_STATEID(stateid) && (flags & RD_STATE))
3279 return nfs_ok; 3287 return nfs_ok;
3280 else if (locks_in_grace()) { 3288 else if (locks_in_grace(net)) {
3281 /* Answer in remaining cases depends on existence of 3289 /* Answer in remaining cases depends on existence of
3282 * conflicting state; so we must wait out the grace period. */ 3290 * conflicting state; so we must wait out the grace period. */
3283 return nfserr_grace; 3291 return nfserr_grace;
@@ -3294,9 +3302,9 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
3294 * that are not able to provide mandatory locking. 3302 * that are not able to provide mandatory locking.
3295 */ 3303 */
3296static inline int 3304static inline int
3297grace_disallows_io(struct inode *inode) 3305grace_disallows_io(struct net *net, struct inode *inode)
3298{ 3306{
3299 return locks_in_grace() && mandatory_lock(inode); 3307 return locks_in_grace(net) && mandatory_lock(inode);
3300} 3308}
3301 3309
3302/* Returns true iff a is later than b: */ 3310/* Returns true iff a is later than b: */
@@ -3333,18 +3341,26 @@ static __be32 check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_s
3333 return nfserr_old_stateid; 3341 return nfserr_old_stateid;
3334} 3342}
3335 3343
3336__be32 nfs4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid) 3344static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
3337{ 3345{
3338 struct nfs4_stid *s; 3346 struct nfs4_stid *s;
3339 struct nfs4_ol_stateid *ols; 3347 struct nfs4_ol_stateid *ols;
3340 __be32 status; 3348 __be32 status;
3341 3349
3342 if (STALE_STATEID(stateid)) 3350 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
3343 return nfserr_stale_stateid; 3351 return nfserr_bad_stateid;
3344 3352 /* Client debugging aid. */
3353 if (!same_clid(&stateid->si_opaque.so_clid, &cl->cl_clientid)) {
3354 char addr_str[INET6_ADDRSTRLEN];
3355 rpc_ntop((struct sockaddr *)&cl->cl_addr, addr_str,
3356 sizeof(addr_str));
3357 pr_warn_ratelimited("NFSD: client %s testing state ID "
3358 "with incorrect client ID\n", addr_str);
3359 return nfserr_bad_stateid;
3360 }
3345 s = find_stateid(cl, stateid); 3361 s = find_stateid(cl, stateid);
3346 if (!s) 3362 if (!s)
3347 return nfserr_stale_stateid; 3363 return nfserr_bad_stateid;
3348 status = check_stateid_generation(stateid, &s->sc_stateid, 1); 3364 status = check_stateid_generation(stateid, &s->sc_stateid, 1);
3349 if (status) 3365 if (status)
3350 return status; 3366 return status;
@@ -3360,10 +3376,11 @@ __be32 nfs4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
3360static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s) 3376static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s)
3361{ 3377{
3362 struct nfs4_client *cl; 3378 struct nfs4_client *cl;
3379 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
3363 3380
3364 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) 3381 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
3365 return nfserr_bad_stateid; 3382 return nfserr_bad_stateid;
3366 if (STALE_STATEID(stateid)) 3383 if (STALE_STATEID(stateid, nn))
3367 return nfserr_stale_stateid; 3384 return nfserr_stale_stateid;
3368 cl = find_confirmed_client(&stateid->si_opaque.so_clid); 3385 cl = find_confirmed_client(&stateid->si_opaque.so_clid);
3369 if (!cl) 3386 if (!cl)
@@ -3379,7 +3396,7 @@ static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, s
3379* Checks for stateid operations 3396* Checks for stateid operations
3380*/ 3397*/
3381__be32 3398__be32
3382nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, 3399nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
3383 stateid_t *stateid, int flags, struct file **filpp) 3400 stateid_t *stateid, int flags, struct file **filpp)
3384{ 3401{
3385 struct nfs4_stid *s; 3402 struct nfs4_stid *s;
@@ -3392,11 +3409,11 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
3392 if (filpp) 3409 if (filpp)
3393 *filpp = NULL; 3410 *filpp = NULL;
3394 3411
3395 if (grace_disallows_io(ino)) 3412 if (grace_disallows_io(net, ino))
3396 return nfserr_grace; 3413 return nfserr_grace;
3397 3414
3398 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) 3415 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
3399 return check_special_stateids(current_fh, stateid, flags); 3416 return check_special_stateids(net, current_fh, stateid, flags);
3400 3417
3401 status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s); 3418 status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s);
3402 if (status) 3419 if (status)
@@ -3463,7 +3480,8 @@ nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3463 3480
3464 nfs4_lock_state(); 3481 nfs4_lock_state();
3465 list_for_each_entry(stateid, &test_stateid->ts_stateid_list, ts_id_list) 3482 list_for_each_entry(stateid, &test_stateid->ts_stateid_list, ts_id_list)
3466 stateid->ts_id_status = nfs4_validate_stateid(cl, &stateid->ts_id_stateid); 3483 stateid->ts_id_status =
3484 nfsd4_validate_stateid(cl, &stateid->ts_id_stateid);
3467 nfs4_unlock_state(); 3485 nfs4_unlock_state();
3468 3486
3469 return nfs_ok; 3487 return nfs_ok;
@@ -3750,12 +3768,19 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3750 nfsd4_close_open_stateid(stp); 3768 nfsd4_close_open_stateid(stp);
3751 oo->oo_last_closed_stid = stp; 3769 oo->oo_last_closed_stid = stp;
3752 3770
3753 /* place unused nfs4_stateowners on so_close_lru list to be 3771 if (list_empty(&oo->oo_owner.so_stateids)) {
3754 * released by the laundromat service after the lease period 3772 if (cstate->minorversion) {
3755 * to enable us to handle CLOSE replay 3773 release_openowner(oo);
3756 */ 3774 cstate->replay_owner = NULL;
3757 if (list_empty(&oo->oo_owner.so_stateids)) 3775 } else {
3758 move_to_close_lru(oo); 3776 /*
3777 * In the 4.0 case we need to keep the owners around a
3778 * little while to handle CLOSE replay.
3779 */
3780 if (list_empty(&oo->oo_owner.so_stateids))
3781 move_to_close_lru(oo);
3782 }
3783 }
3759out: 3784out:
3760 if (!cstate->replay_owner) 3785 if (!cstate->replay_owner)
3761 nfs4_unlock_state(); 3786 nfs4_unlock_state();
@@ -4027,6 +4052,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4027 bool new_state = false; 4052 bool new_state = false;
4028 int lkflg; 4053 int lkflg;
4029 int err; 4054 int err;
4055 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
4030 4056
4031 dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n", 4057 dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
4032 (long long) lock->lk_offset, 4058 (long long) lock->lk_offset,
@@ -4044,11 +4070,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4044 nfs4_lock_state(); 4070 nfs4_lock_state();
4045 4071
4046 if (lock->lk_is_new) { 4072 if (lock->lk_is_new) {
4047 /*
4048 * Client indicates that this is a new lockowner.
4049 * Use open owner and open stateid to create lock owner and
4050 * lock stateid.
4051 */
4052 struct nfs4_ol_stateid *open_stp = NULL; 4073 struct nfs4_ol_stateid *open_stp = NULL;
4053 4074
4054 if (nfsd4_has_session(cstate)) 4075 if (nfsd4_has_session(cstate))
@@ -4058,7 +4079,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4058 sizeof(clientid_t)); 4079 sizeof(clientid_t));
4059 4080
4060 status = nfserr_stale_clientid; 4081 status = nfserr_stale_clientid;
4061 if (STALE_CLIENTID(&lock->lk_new_clientid)) 4082 if (STALE_CLIENTID(&lock->lk_new_clientid, nn))
4062 goto out; 4083 goto out;
4063 4084
4064 /* validate and update open stateid and open seqid */ 4085 /* validate and update open stateid and open seqid */
@@ -4075,17 +4096,13 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4075 goto out; 4096 goto out;
4076 status = lookup_or_create_lock_state(cstate, open_stp, lock, 4097 status = lookup_or_create_lock_state(cstate, open_stp, lock,
4077 &lock_stp, &new_state); 4098 &lock_stp, &new_state);
4078 if (status) 4099 } else
4079 goto out;
4080 } else {
4081 /* lock (lock owner + lock stateid) already exists */
4082 status = nfs4_preprocess_seqid_op(cstate, 4100 status = nfs4_preprocess_seqid_op(cstate,
4083 lock->lk_old_lock_seqid, 4101 lock->lk_old_lock_seqid,
4084 &lock->lk_old_lock_stateid, 4102 &lock->lk_old_lock_stateid,
4085 NFS4_LOCK_STID, &lock_stp); 4103 NFS4_LOCK_STID, &lock_stp);
4086 if (status) 4104 if (status)
4087 goto out; 4105 goto out;
4088 }
4089 lock_sop = lockowner(lock_stp->st_stateowner); 4106 lock_sop = lockowner(lock_stp->st_stateowner);
4090 4107
4091 lkflg = setlkflg(lock->lk_type); 4108 lkflg = setlkflg(lock->lk_type);
@@ -4094,10 +4111,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4094 goto out; 4111 goto out;
4095 4112
4096 status = nfserr_grace; 4113 status = nfserr_grace;
4097 if (locks_in_grace() && !lock->lk_reclaim) 4114 if (locks_in_grace(SVC_NET(rqstp)) && !lock->lk_reclaim)
4098 goto out; 4115 goto out;
4099 status = nfserr_no_grace; 4116 status = nfserr_no_grace;
4100 if (!locks_in_grace() && lock->lk_reclaim) 4117 if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim)
4101 goto out; 4118 goto out;
4102 4119
4103 locks_init_lock(&file_lock); 4120 locks_init_lock(&file_lock);
@@ -4196,8 +4213,9 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4196 struct file_lock file_lock; 4213 struct file_lock file_lock;
4197 struct nfs4_lockowner *lo; 4214 struct nfs4_lockowner *lo;
4198 __be32 status; 4215 __be32 status;
4216 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
4199 4217
4200 if (locks_in_grace()) 4218 if (locks_in_grace(SVC_NET(rqstp)))
4201 return nfserr_grace; 4219 return nfserr_grace;
4202 4220
4203 if (check_lock_length(lockt->lt_offset, lockt->lt_length)) 4221 if (check_lock_length(lockt->lt_offset, lockt->lt_length))
@@ -4206,7 +4224,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4206 nfs4_lock_state(); 4224 nfs4_lock_state();
4207 4225
4208 status = nfserr_stale_clientid; 4226 status = nfserr_stale_clientid;
4209 if (!nfsd4_has_session(cstate) && STALE_CLIENTID(&lockt->lt_clientid)) 4227 if (!nfsd4_has_session(cstate) && STALE_CLIENTID(&lockt->lt_clientid, nn))
4210 goto out; 4228 goto out;
4211 4229
4212 if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) 4230 if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
@@ -4355,6 +4373,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
4355 struct list_head matches; 4373 struct list_head matches;
4356 unsigned int hashval = ownerstr_hashval(clid->cl_id, owner); 4374 unsigned int hashval = ownerstr_hashval(clid->cl_id, owner);
4357 __be32 status; 4375 __be32 status;
4376 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
4358 4377
4359 dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n", 4378 dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
4360 clid->cl_boot, clid->cl_id); 4379 clid->cl_boot, clid->cl_id);
@@ -4362,7 +4381,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
4362 /* XXX check for lease expiration */ 4381 /* XXX check for lease expiration */
4363 4382
4364 status = nfserr_stale_clientid; 4383 status = nfserr_stale_clientid;
4365 if (STALE_CLIENTID(clid)) 4384 if (STALE_CLIENTID(clid, nn))
4366 return status; 4385 return status;
4367 4386
4368 nfs4_lock_state(); 4387 nfs4_lock_state();
@@ -4564,7 +4583,7 @@ void nfsd_forget_openowners(u64 num)
4564 printk(KERN_INFO "NFSD: Forgot %d open owners", count); 4583 printk(KERN_INFO "NFSD: Forgot %d open owners", count);
4565} 4584}
4566 4585
4567int nfsd_process_n_delegations(u64 num, void (*deleg_func)(struct nfs4_delegation *)) 4586int nfsd_process_n_delegations(u64 num, struct list_head *list)
4568{ 4587{
4569 int i, count = 0; 4588 int i, count = 0;
4570 struct nfs4_file *fp, *fnext; 4589 struct nfs4_file *fp, *fnext;
@@ -4573,7 +4592,7 @@ int nfsd_process_n_delegations(u64 num, void (*deleg_func)(struct nfs4_delegatio
4573 for (i = 0; i < FILE_HASH_SIZE; i++) { 4592 for (i = 0; i < FILE_HASH_SIZE; i++) {
4574 list_for_each_entry_safe(fp, fnext, &file_hashtbl[i], fi_hash) { 4593 list_for_each_entry_safe(fp, fnext, &file_hashtbl[i], fi_hash) {
4575 list_for_each_entry_safe(dp, dnext, &fp->fi_delegations, dl_perfile) { 4594 list_for_each_entry_safe(dp, dnext, &fp->fi_delegations, dl_perfile) {
4576 deleg_func(dp); 4595 list_move(&dp->dl_recall_lru, list);
4577 if (++count == num) 4596 if (++count == num)
4578 return count; 4597 return count;
4579 } 4598 }
@@ -4586,9 +4605,16 @@ int nfsd_process_n_delegations(u64 num, void (*deleg_func)(struct nfs4_delegatio
4586void nfsd_forget_delegations(u64 num) 4605void nfsd_forget_delegations(u64 num)
4587{ 4606{
4588 unsigned int count; 4607 unsigned int count;
4608 LIST_HEAD(victims);
4609 struct nfs4_delegation *dp, *dnext;
4610
4611 spin_lock(&recall_lock);
4612 count = nfsd_process_n_delegations(num, &victims);
4613 spin_unlock(&recall_lock);
4589 4614
4590 nfs4_lock_state(); 4615 nfs4_lock_state();
4591 count = nfsd_process_n_delegations(num, unhash_delegation); 4616 list_for_each_entry_safe(dp, dnext, &victims, dl_recall_lru)
4617 unhash_delegation(dp);
4592 nfs4_unlock_state(); 4618 nfs4_unlock_state();
4593 4619
4594 printk(KERN_INFO "NFSD: Forgot %d delegations", count); 4620 printk(KERN_INFO "NFSD: Forgot %d delegations", count);
@@ -4597,12 +4623,16 @@ void nfsd_forget_delegations(u64 num)
4597void nfsd_recall_delegations(u64 num) 4623void nfsd_recall_delegations(u64 num)
4598{ 4624{
4599 unsigned int count; 4625 unsigned int count;
4626 LIST_HEAD(victims);
4627 struct nfs4_delegation *dp, *dnext;
4600 4628
4601 nfs4_lock_state();
4602 spin_lock(&recall_lock); 4629 spin_lock(&recall_lock);
4603 count = nfsd_process_n_delegations(num, nfsd_break_one_deleg); 4630 count = nfsd_process_n_delegations(num, &victims);
4631 list_for_each_entry_safe(dp, dnext, &victims, dl_recall_lru) {
4632 list_del(&dp->dl_recall_lru);
4633 nfsd_break_one_deleg(dp);
4634 }
4604 spin_unlock(&recall_lock); 4635 spin_unlock(&recall_lock);
4605 nfs4_unlock_state();
4606 4636
4607 printk(KERN_INFO "NFSD: Recalled %d delegations", count); 4637 printk(KERN_INFO "NFSD: Recalled %d delegations", count);
4608} 4638}
@@ -4665,6 +4695,8 @@ set_max_delegations(void)
4665int 4695int
4666nfs4_state_start(void) 4696nfs4_state_start(void)
4667{ 4697{
4698 struct net *net = &init_net;
4699 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
4668 int ret; 4700 int ret;
4669 4701
4670 /* 4702 /*
@@ -4674,11 +4706,11 @@ nfs4_state_start(void)
4674 * to that instead and then do most of the rest of this on a per-net 4706 * to that instead and then do most of the rest of this on a per-net
4675 * basis. 4707 * basis.
4676 */ 4708 */
4677 get_net(&init_net); 4709 get_net(net);
4678 nfsd4_client_tracking_init(&init_net); 4710 nfsd4_client_tracking_init(net);
4679 boot_time = get_seconds(); 4711 nn->boot_time = get_seconds();
4680 locks_start_grace(&nfsd4_manager); 4712 locks_start_grace(net, &nn->nfsd4_manager);
4681 grace_ended = false; 4713 nn->grace_ended = false;
4682 printk(KERN_INFO "NFSD: starting %ld-second grace period\n", 4714 printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
4683 nfsd4_grace); 4715 nfsd4_grace);
4684 ret = set_callback_cred(); 4716 ret = set_callback_cred();
@@ -4700,8 +4732,8 @@ nfs4_state_start(void)
4700out_free_laundry: 4732out_free_laundry:
4701 destroy_workqueue(laundry_wq); 4733 destroy_workqueue(laundry_wq);
4702out_recovery: 4734out_recovery:
4703 nfsd4_client_tracking_exit(&init_net); 4735 nfsd4_client_tracking_exit(net);
4704 put_net(&init_net); 4736 put_net(net);
4705 return ret; 4737 return ret;
4706} 4738}
4707 4739
@@ -4742,9 +4774,12 @@ __nfs4_state_shutdown(void)
4742void 4774void
4743nfs4_state_shutdown(void) 4775nfs4_state_shutdown(void)
4744{ 4776{
4777 struct net *net = &init_net;
4778 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
4779
4745 cancel_delayed_work_sync(&laundromat_work); 4780 cancel_delayed_work_sync(&laundromat_work);
4746 destroy_workqueue(laundry_wq); 4781 destroy_workqueue(laundry_wq);
4747 locks_end_grace(&nfsd4_manager); 4782 locks_end_grace(&nn->nfsd4_manager);
4748 nfs4_lock_state(); 4783 nfs4_lock_state();
4749 __nfs4_state_shutdown(); 4784 __nfs4_state_shutdown();
4750 nfs4_unlock_state(); 4785 nfs4_unlock_state();
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 4949667c84ea..6322df36031f 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2259,7 +2259,7 @@ out_acl:
2259 if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) { 2259 if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) {
2260 if ((buflen -= 4) < 0) 2260 if ((buflen -= 4) < 0)
2261 goto out_resource; 2261 goto out_resource;
2262 WRITE32(1); 2262 WRITE32(0);
2263 } 2263 }
2264 if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) { 2264 if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) {
2265 if ((buflen -= 4) < 0) 2265 if ((buflen -= 4) < 0)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index c55298ed5772..fa49cff5ee65 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -673,9 +673,7 @@ static ssize_t __write_ports_addfd(char *buf)
673 673
674 err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); 674 err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT);
675 if (err < 0) { 675 if (err < 0) {
676 if (nfsd_serv->sv_nrthreads == 1) 676 nfsd_destroy(net);
677 svc_shutdown_net(nfsd_serv, net);
678 svc_destroy(nfsd_serv);
679 return err; 677 return err;
680 } 678 }
681 679
@@ -744,9 +742,7 @@ out_close:
744 svc_xprt_put(xprt); 742 svc_xprt_put(xprt);
745 } 743 }
746out_err: 744out_err:
747 if (nfsd_serv->sv_nrthreads == 1) 745 nfsd_destroy(net);
748 svc_shutdown_net(nfsd_serv, net);
749 svc_destroy(nfsd_serv);
750 return err; 746 return err;
751} 747}
752 748
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 1671429ffa66..2244222368ab 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -72,6 +72,19 @@ int nfsd_nrthreads(void);
72int nfsd_nrpools(void); 72int nfsd_nrpools(void);
73int nfsd_get_nrthreads(int n, int *); 73int nfsd_get_nrthreads(int n, int *);
74int nfsd_set_nrthreads(int n, int *); 74int nfsd_set_nrthreads(int n, int *);
75int nfsd_pool_stats_open(struct inode *, struct file *);
76int nfsd_pool_stats_release(struct inode *, struct file *);
77
78static inline void nfsd_destroy(struct net *net)
79{
80 int destroy = (nfsd_serv->sv_nrthreads == 1);
81
82 if (destroy)
83 svc_shutdown_net(nfsd_serv, net);
84 svc_destroy(nfsd_serv);
85 if (destroy)
86 nfsd_serv = NULL;
87}
75 88
76#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 89#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
77#ifdef CONFIG_NFSD_V2_ACL 90#ifdef CONFIG_NFSD_V2_ACL
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index ee709fc8f58b..240473cb708f 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -254,8 +254,6 @@ static void nfsd_shutdown(void)
254 254
255static void nfsd_last_thread(struct svc_serv *serv, struct net *net) 255static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
256{ 256{
257 /* When last nfsd thread exits we need to do some clean-up */
258 nfsd_serv = NULL;
259 nfsd_shutdown(); 257 nfsd_shutdown();
260 258
261 svc_rpcb_cleanup(serv, net); 259 svc_rpcb_cleanup(serv, net);
@@ -332,6 +330,7 @@ static int nfsd_get_default_max_blksize(void)
332int nfsd_create_serv(void) 330int nfsd_create_serv(void)
333{ 331{
334 int error; 332 int error;
333 struct net *net = current->nsproxy->net_ns;
335 334
336 WARN_ON(!mutex_is_locked(&nfsd_mutex)); 335 WARN_ON(!mutex_is_locked(&nfsd_mutex));
337 if (nfsd_serv) { 336 if (nfsd_serv) {
@@ -346,7 +345,7 @@ int nfsd_create_serv(void)
346 if (nfsd_serv == NULL) 345 if (nfsd_serv == NULL)
347 return -ENOMEM; 346 return -ENOMEM;
348 347
349 error = svc_bind(nfsd_serv, current->nsproxy->net_ns); 348 error = svc_bind(nfsd_serv, net);
350 if (error < 0) { 349 if (error < 0) {
351 svc_destroy(nfsd_serv); 350 svc_destroy(nfsd_serv);
352 return error; 351 return error;
@@ -427,11 +426,7 @@ int nfsd_set_nrthreads(int n, int *nthreads)
427 if (err) 426 if (err)
428 break; 427 break;
429 } 428 }
430 429 nfsd_destroy(net);
431 if (nfsd_serv->sv_nrthreads == 1)
432 svc_shutdown_net(nfsd_serv, net);
433 svc_destroy(nfsd_serv);
434
435 return err; 430 return err;
436} 431}
437 432
@@ -478,9 +473,7 @@ out_shutdown:
478 if (error < 0 && !nfsd_up_before) 473 if (error < 0 && !nfsd_up_before)
479 nfsd_shutdown(); 474 nfsd_shutdown();
480out_destroy: 475out_destroy:
481 if (nfsd_serv->sv_nrthreads == 1) 476 nfsd_destroy(net); /* Release server */
482 svc_shutdown_net(nfsd_serv, net);
483 svc_destroy(nfsd_serv); /* Release server */
484out: 477out:
485 mutex_unlock(&nfsd_mutex); 478 mutex_unlock(&nfsd_mutex);
486 return error; 479 return error;
@@ -563,12 +556,13 @@ nfsd(void *vrqstp)
563 nfsdstats.th_cnt --; 556 nfsdstats.th_cnt --;
564 557
565out: 558out:
566 if (rqstp->rq_server->sv_nrthreads == 1) 559 rqstp->rq_server = NULL;
567 svc_shutdown_net(rqstp->rq_server, &init_net);
568 560
569 /* Release the thread */ 561 /* Release the thread */
570 svc_exit_thread(rqstp); 562 svc_exit_thread(rqstp);
571 563
564 nfsd_destroy(&init_net);
565
572 /* Release module */ 566 /* Release module */
573 mutex_unlock(&nfsd_mutex); 567 mutex_unlock(&nfsd_mutex);
574 module_put_and_exit(0); 568 module_put_and_exit(0);
@@ -682,9 +676,7 @@ int nfsd_pool_stats_release(struct inode *inode, struct file *file)
682 676
683 mutex_lock(&nfsd_mutex); 677 mutex_lock(&nfsd_mutex);
684 /* this function really, really should have been called svc_put() */ 678 /* this function really, really should have been called svc_put() */
685 if (nfsd_serv->sv_nrthreads == 1) 679 nfsd_destroy(net);
686 svc_shutdown_net(nfsd_serv, net);
687 svc_destroy(nfsd_serv);
688 mutex_unlock(&nfsd_mutex); 680 mutex_unlock(&nfsd_mutex);
689 return ret; 681 return ret;
690} 682}
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 849091e16ea6..e6173147f982 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -450,8 +450,10 @@ static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s)
450#define WR_STATE 0x00000020 450#define WR_STATE 0x00000020
451 451
452struct nfsd4_compound_state; 452struct nfsd4_compound_state;
453struct nfsd_net;
453 454
454extern __be32 nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, 455extern __be32 nfs4_preprocess_stateid_op(struct net *net,
456 struct nfsd4_compound_state *cstate,
455 stateid_t *stateid, int flags, struct file **filp); 457 stateid_t *stateid, int flags, struct file **filp);
456extern void nfs4_lock_state(void); 458extern void nfs4_lock_state(void);
457extern void nfs4_unlock_state(void); 459extern void nfs4_unlock_state(void);
@@ -475,7 +477,6 @@ extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
475extern int nfs4_client_to_reclaim(const char *name); 477extern int nfs4_client_to_reclaim(const char *name);
476extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id); 478extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id);
477extern void release_session_client(struct nfsd4_session *); 479extern void release_session_client(struct nfsd4_session *);
478extern __be32 nfs4_validate_stateid(struct nfs4_client *, stateid_t *);
479extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *); 480extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *);
480 481
481/* nfs4recover operations */ 482/* nfs4recover operations */
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 4700a0a929d7..702f64e820c3 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -757,8 +757,16 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
757 * If we get here, then the client has already done an "open", 757 * If we get here, then the client has already done an "open",
758 * and (hopefully) checked permission - so allow OWNER_OVERRIDE 758 * and (hopefully) checked permission - so allow OWNER_OVERRIDE
759 * in case a chmod has now revoked permission. 759 * in case a chmod has now revoked permission.
760 *
761 * Arguably we should also allow the owner override for
762 * directories, but we never have and it doesn't seem to have
763 * caused anyone a problem. If we were to change this, note
764 * also that our filldir callbacks would need a variant of
765 * lookup_one_len that doesn't check permissions.
760 */ 766 */
761 err = fh_verify(rqstp, fhp, type, may_flags | NFSD_MAY_OWNER_OVERRIDE); 767 if (type == S_IFREG)
768 may_flags |= NFSD_MAY_OWNER_OVERRIDE;
769 err = fh_verify(rqstp, fhp, type, may_flags);
762 if (err) 770 if (err)
763 goto out; 771 goto out;
764 772
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 8fabb037a48d..b178f9e91e23 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1163,9 +1163,10 @@ struct lock_manager {
1163 struct list_head list; 1163 struct list_head list;
1164}; 1164};
1165 1165
1166void locks_start_grace(struct lock_manager *); 1166struct net;
1167void locks_start_grace(struct net *, struct lock_manager *);
1167void locks_end_grace(struct lock_manager *); 1168void locks_end_grace(struct lock_manager *);
1168int locks_in_grace(void); 1169int locks_in_grace(struct net *);
1169 1170
1170/* that will die - we need it for nfs_lock_info */ 1171/* that will die - we need it for nfs_lock_info */
1171#include <linux/nfs_fs_i.h> 1172#include <linux/nfs_fs_i.h>
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index f04ce6ac6d04..f5a051a79273 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -262,11 +262,11 @@ typedef int (*nlm_host_match_fn_t)(void *cur, struct nlm_host *ref);
262__be32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *, 262__be32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *,
263 struct nlm_host *, struct nlm_lock *, int, 263 struct nlm_host *, struct nlm_lock *, int,
264 struct nlm_cookie *, int); 264 struct nlm_cookie *, int);
265__be32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *); 265__be32 nlmsvc_unlock(struct net *net, struct nlm_file *, struct nlm_lock *);
266__be32 nlmsvc_testlock(struct svc_rqst *, struct nlm_file *, 266__be32 nlmsvc_testlock(struct svc_rqst *, struct nlm_file *,
267 struct nlm_host *, struct nlm_lock *, 267 struct nlm_host *, struct nlm_lock *,
268 struct nlm_lock *, struct nlm_cookie *); 268 struct nlm_lock *, struct nlm_cookie *);
269__be32 nlmsvc_cancel_blocked(struct nlm_file *, struct nlm_lock *); 269__be32 nlmsvc_cancel_blocked(struct net *net, struct nlm_file *, struct nlm_lock *);
270unsigned long nlmsvc_retry_blocked(void); 270unsigned long nlmsvc_retry_blocked(void);
271void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *, 271void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *,
272 nlm_host_match_fn_t match); 272 nlm_host_match_fn_t match);
@@ -279,7 +279,7 @@ void nlmsvc_release_call(struct nlm_rqst *);
279__be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **, 279__be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **,
280 struct nfs_fh *); 280 struct nfs_fh *);
281void nlm_release_file(struct nlm_file *); 281void nlm_release_file(struct nlm_file *);
282void nlmsvc_mark_resources(void); 282void nlmsvc_mark_resources(struct net *);
283void nlmsvc_free_host_resources(struct nlm_host *); 283void nlmsvc_free_host_resources(struct nlm_host *);
284void nlmsvc_invalidate_all(void); 284void nlmsvc_invalidate_all(void);
285 285
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
index f5fd6160dbca..f792794f6634 100644
--- a/include/linux/sunrpc/cache.h
+++ b/include/linux/sunrpc/cache.h
@@ -217,14 +217,32 @@ extern int qword_get(char **bpp, char *dest, int bufsize);
217static inline int get_int(char **bpp, int *anint) 217static inline int get_int(char **bpp, int *anint)
218{ 218{
219 char buf[50]; 219 char buf[50];
220 char *ep; 220 int len = qword_get(bpp, buf, sizeof(buf));
221 int rv; 221
222 int len = qword_get(bpp, buf, 50); 222 if (len < 0)
223 if (len < 0) return -EINVAL; 223 return -EINVAL;
224 if (len ==0) return -ENOENT; 224 if (len == 0)
225 rv = simple_strtol(buf, &ep, 0); 225 return -ENOENT;
226 if (*ep) return -EINVAL; 226
227 *anint = rv; 227 if (kstrtoint(buf, 0, anint))
228 return -EINVAL;
229
230 return 0;
231}
232
233static inline int get_uint(char **bpp, unsigned int *anint)
234{
235 char buf[50];
236 int len = qword_get(bpp, buf, sizeof(buf));
237
238 if (len < 0)
239 return -EINVAL;
240 if (len == 0)
241 return -ENOENT;
242
243 if (kstrtouint(buf, 0, anint))
244 return -EINVAL;
245
228 return 0; 246 return 0;
229} 247}
230 248
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 40e0a273faea..d83db800fe02 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -278,6 +278,8 @@ struct svc_rqst {
278 struct task_struct *rq_task; /* service thread */ 278 struct task_struct *rq_task; /* service thread */
279}; 279};
280 280
281#define SVC_NET(svc_rqst) (svc_rqst->rq_xprt->xpt_net)
282
281/* 283/*
282 * Rigorous type checking on sockaddr type conversions 284 * Rigorous type checking on sockaddr type conversions
283 */ 285 */
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 47ad2666fdf6..2afd2a84dc35 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -1349,8 +1349,11 @@ static int c_show(struct seq_file *m, void *p)
1349 if (cache_check(cd, cp, NULL)) 1349 if (cache_check(cd, cp, NULL))
1350 /* cache_check does a cache_put on failure */ 1350 /* cache_check does a cache_put on failure */
1351 seq_printf(m, "# "); 1351 seq_printf(m, "# ");
1352 else 1352 else {
1353 if (cache_is_expired(cd, cp))
1354 seq_printf(m, "# ");
1353 cache_put(cp, cd); 1355 cache_put(cp, cd);
1356 }
1354 1357
1355 return cd->cache_show(m, cd, cp); 1358 return cd->cache_show(m, cd, cp);
1356} 1359}