aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-28 21:02:55 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-28 21:02:55 -0500
commitb6669737d3db7df79fad07180837c23dbe581db5 (patch)
tree671a9d13fe5ab00d6a3c7c5c5c466802ca96d38a /fs
parent1cf0209c431fa7790253c532039d53b0773193aa (diff)
parentdc107402ae06286a9ed33c32daf3f35514a7cb8d (diff)
Merge branch 'for-3.9' of git://linux-nfs.org/~bfields/linux
Pull nfsd changes from J Bruce Fields: "Miscellaneous bugfixes, plus: - An overhaul of the DRC cache by Jeff Layton. The main effect is just to make it larger. This decreases the chances of intermittent errors especially in the UDP case. But we'll need to watch for any reports of performance regressions. - Containerized nfsd: with some limitations, we now support per-container nfs-service, thanks to extensive work from Stanislav Kinsbursky over the last year." Some notes about conflicts, since there were *two* non-data semantic conflicts here: - idr_remove_all() had been added by a memory leak fix, but has since become deprecated since idr_destroy() does it for us now. - xs_local_connect() had been added by this branch to make AF_LOCAL connections be synchronous, but in the meantime Trond had changed the calling convention in order to avoid a RCU dereference. There were a couple of more obvious actual source-level conflicts due to the hlist traversal changes and one just due to code changes next to each other, but those were trivial. * 'for-3.9' of git://linux-nfs.org/~bfields/linux: (49 commits) SUNRPC: make AF_LOCAL connect synchronous nfsd: fix compiler warning about ambiguous types in nfsd_cache_csum svcrpc: fix rpc server shutdown races svcrpc: make svc_age_temp_xprts enqueue under sv_lock lockd: nlmclnt_reclaim(): avoid stack overflow nfsd: enable NFSv4 state in containers nfsd: disable usermode helper client tracker in container nfsd: use proper net while reading "exports" file nfsd: containerize NFSd filesystem nfsd: fix comments on nfsd_cache_lookup SUNRPC: move cache_detail->cache_request callback call to cache_read() SUNRPC: remove "cache_request" argument in sunrpc_cache_pipe_upcall() function SUNRPC: rework cache upcall logic SUNRPC: introduce cache_detail->cache_request callback NFS: simplify and clean cache library NFS: use SUNRPC cache creation and destruction helper for DNS cache nfsd4: free_stid can be static nfsd: keep a checksum of the first 256 bytes of request sunrpc: trim off trailing checksum before returning decrypted or integrity authenticated buffer sunrpc: fix comment in struct xdr_buf definition ...
Diffstat (limited to 'fs')
-rw-r--r--fs/lockd/clntlock.c14
-rw-r--r--fs/lockd/clntproc.c6
-rw-r--r--fs/lockd/host.c1
-rw-r--r--fs/lockd/mon.c1
-rw-r--r--fs/lockd/svcsubs.c2
-rw-r--r--fs/nfs/cache_lib.c12
-rw-r--r--fs/nfs/cache_lib.h2
-rw-r--r--fs/nfs/dns_resolve.c67
-rw-r--r--fs/nfs/nfs4client.c1
-rw-r--r--fs/nfs/nfs4filelayoutdev.c1
-rw-r--r--fs/nfs/nfs4namespace.c1
-rw-r--r--fs/nfs/super.c1
-rw-r--r--fs/nfsd/cache.h17
-rw-r--r--fs/nfsd/export.c16
-rw-r--r--fs/nfsd/fault_inject.c2
-rw-r--r--fs/nfsd/nfs4idmap.c16
-rw-r--r--fs/nfsd/nfs4proc.c7
-rw-r--r--fs/nfsd/nfs4recover.c6
-rw-r--r--fs/nfsd/nfs4state.c101
-rw-r--r--fs/nfsd/nfs4xdr.c21
-rw-r--r--fs/nfsd/nfscache.c352
-rw-r--r--fs/nfsd/nfsctl.c81
-rw-r--r--fs/nfsd/nfssvc.c6
-rw-r--r--fs/nfsd/xdr4.h2
24 files changed, 489 insertions, 247 deletions
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index a2717408c478..0796c45d0d4d 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -11,7 +11,7 @@
11#include <linux/slab.h> 11#include <linux/slab.h>
12#include <linux/time.h> 12#include <linux/time.h>
13#include <linux/nfs_fs.h> 13#include <linux/nfs_fs.h>
14#include <linux/sunrpc/clnt.h> 14#include <linux/sunrpc/addr.h>
15#include <linux/sunrpc/svc.h> 15#include <linux/sunrpc/svc.h>
16#include <linux/lockd/lockd.h> 16#include <linux/lockd/lockd.h>
17#include <linux/kthread.h> 17#include <linux/kthread.h>
@@ -220,10 +220,19 @@ reclaimer(void *ptr)
220{ 220{
221 struct nlm_host *host = (struct nlm_host *) ptr; 221 struct nlm_host *host = (struct nlm_host *) ptr;
222 struct nlm_wait *block; 222 struct nlm_wait *block;
223 struct nlm_rqst *req;
223 struct file_lock *fl, *next; 224 struct file_lock *fl, *next;
224 u32 nsmstate; 225 u32 nsmstate;
225 struct net *net = host->net; 226 struct net *net = host->net;
226 227
228 req = kmalloc(sizeof(*req), GFP_KERNEL);
229 if (!req) {
230 printk(KERN_ERR "lockd: reclaimer unable to alloc memory."
231 " Locks for %s won't be reclaimed!\n",
232 host->h_name);
233 return 0;
234 }
235
227 allow_signal(SIGKILL); 236 allow_signal(SIGKILL);
228 237
229 down_write(&host->h_rwsem); 238 down_write(&host->h_rwsem);
@@ -253,7 +262,7 @@ restart:
253 */ 262 */
254 if (signalled()) 263 if (signalled())
255 continue; 264 continue;
256 if (nlmclnt_reclaim(host, fl) != 0) 265 if (nlmclnt_reclaim(host, fl, req) != 0)
257 continue; 266 continue;
258 list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted); 267 list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted);
259 if (host->h_nsmstate != nsmstate) { 268 if (host->h_nsmstate != nsmstate) {
@@ -279,5 +288,6 @@ restart:
279 /* Release host handle after use */ 288 /* Release host handle after use */
280 nlmclnt_release_host(host); 289 nlmclnt_release_host(host);
281 lockd_down(net); 290 lockd_down(net);
291 kfree(req);
282 return 0; 292 return 0;
283} 293}
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 366277190b82..7e529c3c45c0 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -618,17 +618,15 @@ out_unlock:
618 * RECLAIM: Try to reclaim a lock 618 * RECLAIM: Try to reclaim a lock
619 */ 619 */
620int 620int
621nlmclnt_reclaim(struct nlm_host *host, struct file_lock *fl) 621nlmclnt_reclaim(struct nlm_host *host, struct file_lock *fl,
622 struct nlm_rqst *req)
622{ 623{
623 struct nlm_rqst reqst, *req;
624 int status; 624 int status;
625 625
626 req = &reqst;
627 memset(req, 0, sizeof(*req)); 626 memset(req, 0, sizeof(*req));
628 locks_init_lock(&req->a_args.lock.fl); 627 locks_init_lock(&req->a_args.lock.fl);
629 locks_init_lock(&req->a_res.lock.fl); 628 locks_init_lock(&req->a_res.lock.fl);
630 req->a_host = host; 629 req->a_host = host;
631 req->a_flags = 0;
632 630
633 /* Set up the argument struct */ 631 /* Set up the argument struct */
634 nlmclnt_setlockargs(req, fl); 632 nlmclnt_setlockargs(req, fl);
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index abdd75d44dd4..969d589c848d 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -13,6 +13,7 @@
13#include <linux/in.h> 13#include <linux/in.h>
14#include <linux/in6.h> 14#include <linux/in6.h>
15#include <linux/sunrpc/clnt.h> 15#include <linux/sunrpc/clnt.h>
16#include <linux/sunrpc/addr.h>
16#include <linux/sunrpc/svc.h> 17#include <linux/sunrpc/svc.h>
17#include <linux/lockd/lockd.h> 18#include <linux/lockd/lockd.h>
18#include <linux/mutex.h> 19#include <linux/mutex.h>
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 3c2cfc683631..1812f026960c 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -12,6 +12,7 @@
12#include <linux/slab.h> 12#include <linux/slab.h>
13 13
14#include <linux/sunrpc/clnt.h> 14#include <linux/sunrpc/clnt.h>
15#include <linux/sunrpc/addr.h>
15#include <linux/sunrpc/xprtsock.h> 16#include <linux/sunrpc/xprtsock.h>
16#include <linux/sunrpc/svc.h> 17#include <linux/sunrpc/svc.h>
17#include <linux/lockd/lockd.h> 18#include <linux/lockd/lockd.h>
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index d17bb62b06d6..97e87415b145 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -13,7 +13,7 @@
13#include <linux/slab.h> 13#include <linux/slab.h>
14#include <linux/mutex.h> 14#include <linux/mutex.h>
15#include <linux/sunrpc/svc.h> 15#include <linux/sunrpc/svc.h>
16#include <linux/sunrpc/clnt.h> 16#include <linux/sunrpc/addr.h>
17#include <linux/nfsd/nfsfh.h> 17#include <linux/nfsd/nfsfh.h>
18#include <linux/nfsd/export.h> 18#include <linux/nfsd/export.h>
19#include <linux/lockd/lockd.h> 19#include <linux/lockd/lockd.h>
diff --git a/fs/nfs/cache_lib.c b/fs/nfs/cache_lib.c
index 862a2f16db64..5f7b053720ee 100644
--- a/fs/nfs/cache_lib.c
+++ b/fs/nfs/cache_lib.c
@@ -128,10 +128,13 @@ int nfs_cache_register_net(struct net *net, struct cache_detail *cd)
128 struct super_block *pipefs_sb; 128 struct super_block *pipefs_sb;
129 int ret = 0; 129 int ret = 0;
130 130
131 sunrpc_init_cache_detail(cd);
131 pipefs_sb = rpc_get_sb_net(net); 132 pipefs_sb = rpc_get_sb_net(net);
132 if (pipefs_sb) { 133 if (pipefs_sb) {
133 ret = nfs_cache_register_sb(pipefs_sb, cd); 134 ret = nfs_cache_register_sb(pipefs_sb, cd);
134 rpc_put_sb_net(net); 135 rpc_put_sb_net(net);
136 if (ret)
137 sunrpc_destroy_cache_detail(cd);
135 } 138 }
136 return ret; 139 return ret;
137} 140}
@@ -151,14 +154,5 @@ void nfs_cache_unregister_net(struct net *net, struct cache_detail *cd)
151 nfs_cache_unregister_sb(pipefs_sb, cd); 154 nfs_cache_unregister_sb(pipefs_sb, cd);
152 rpc_put_sb_net(net); 155 rpc_put_sb_net(net);
153 } 156 }
154}
155
156void nfs_cache_init(struct cache_detail *cd)
157{
158 sunrpc_init_cache_detail(cd);
159}
160
161void nfs_cache_destroy(struct cache_detail *cd)
162{
163 sunrpc_destroy_cache_detail(cd); 157 sunrpc_destroy_cache_detail(cd);
164} 158}
diff --git a/fs/nfs/cache_lib.h b/fs/nfs/cache_lib.h
index 317db95e37f8..4116d2c3f52f 100644
--- a/fs/nfs/cache_lib.h
+++ b/fs/nfs/cache_lib.h
@@ -23,8 +23,6 @@ extern struct nfs_cache_defer_req *nfs_cache_defer_req_alloc(void);
23extern void nfs_cache_defer_req_put(struct nfs_cache_defer_req *dreq); 23extern void nfs_cache_defer_req_put(struct nfs_cache_defer_req *dreq);
24extern int nfs_cache_wait_for_upcall(struct nfs_cache_defer_req *dreq); 24extern int nfs_cache_wait_for_upcall(struct nfs_cache_defer_req *dreq);
25 25
26extern void nfs_cache_init(struct cache_detail *cd);
27extern void nfs_cache_destroy(struct cache_detail *cd);
28extern int nfs_cache_register_net(struct net *net, struct cache_detail *cd); 26extern int nfs_cache_register_net(struct net *net, struct cache_detail *cd);
29extern void nfs_cache_unregister_net(struct net *net, struct cache_detail *cd); 27extern void nfs_cache_unregister_net(struct net *net, struct cache_detail *cd);
30extern int nfs_cache_register_sb(struct super_block *sb, 28extern int nfs_cache_register_sb(struct super_block *sb,
diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c
index ca4b11ec87a2..945527092295 100644
--- a/fs/nfs/dns_resolve.c
+++ b/fs/nfs/dns_resolve.c
@@ -10,6 +10,7 @@
10 10
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/sunrpc/clnt.h> 12#include <linux/sunrpc/clnt.h>
13#include <linux/sunrpc/addr.h>
13#include <linux/dns_resolver.h> 14#include <linux/dns_resolver.h>
14#include "dns_resolve.h" 15#include "dns_resolve.h"
15 16
@@ -42,6 +43,7 @@ EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
42#include <linux/seq_file.h> 43#include <linux/seq_file.h>
43#include <linux/inet.h> 44#include <linux/inet.h>
44#include <linux/sunrpc/clnt.h> 45#include <linux/sunrpc/clnt.h>
46#include <linux/sunrpc/addr.h>
45#include <linux/sunrpc/cache.h> 47#include <linux/sunrpc/cache.h>
46#include <linux/sunrpc/svcauth.h> 48#include <linux/sunrpc/svcauth.h>
47#include <linux/sunrpc/rpc_pipe_fs.h> 49#include <linux/sunrpc/rpc_pipe_fs.h>
@@ -142,7 +144,7 @@ static int nfs_dns_upcall(struct cache_detail *cd,
142 144
143 ret = nfs_cache_upcall(cd, key->hostname); 145 ret = nfs_cache_upcall(cd, key->hostname);
144 if (ret) 146 if (ret)
145 ret = sunrpc_cache_pipe_upcall(cd, ch, nfs_dns_request); 147 ret = sunrpc_cache_pipe_upcall(cd, ch);
146 return ret; 148 return ret;
147} 149}
148 150
@@ -351,60 +353,47 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name,
351} 353}
352EXPORT_SYMBOL_GPL(nfs_dns_resolve_name); 354EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
353 355
356static struct cache_detail nfs_dns_resolve_template = {
357 .owner = THIS_MODULE,
358 .hash_size = NFS_DNS_HASHTBL_SIZE,
359 .name = "dns_resolve",
360 .cache_put = nfs_dns_ent_put,
361 .cache_upcall = nfs_dns_upcall,
362 .cache_request = nfs_dns_request,
363 .cache_parse = nfs_dns_parse,
364 .cache_show = nfs_dns_show,
365 .match = nfs_dns_match,
366 .init = nfs_dns_ent_init,
367 .update = nfs_dns_ent_update,
368 .alloc = nfs_dns_ent_alloc,
369};
370
371
354int nfs_dns_resolver_cache_init(struct net *net) 372int nfs_dns_resolver_cache_init(struct net *net)
355{ 373{
356 int err = -ENOMEM; 374 int err;
357 struct nfs_net *nn = net_generic(net, nfs_net_id); 375 struct nfs_net *nn = net_generic(net, nfs_net_id);
358 struct cache_detail *cd;
359 struct cache_head **tbl;
360 376
361 cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL); 377 nn->nfs_dns_resolve = cache_create_net(&nfs_dns_resolve_template, net);
362 if (cd == NULL) 378 if (IS_ERR(nn->nfs_dns_resolve))
363 goto err_cd; 379 return PTR_ERR(nn->nfs_dns_resolve);
364 380
365 tbl = kzalloc(NFS_DNS_HASHTBL_SIZE * sizeof(struct cache_head *), 381 err = nfs_cache_register_net(net, nn->nfs_dns_resolve);
366 GFP_KERNEL);
367 if (tbl == NULL)
368 goto err_tbl;
369
370 cd->owner = THIS_MODULE,
371 cd->hash_size = NFS_DNS_HASHTBL_SIZE,
372 cd->hash_table = tbl,
373 cd->name = "dns_resolve",
374 cd->cache_put = nfs_dns_ent_put,
375 cd->cache_upcall = nfs_dns_upcall,
376 cd->cache_parse = nfs_dns_parse,
377 cd->cache_show = nfs_dns_show,
378 cd->match = nfs_dns_match,
379 cd->init = nfs_dns_ent_init,
380 cd->update = nfs_dns_ent_update,
381 cd->alloc = nfs_dns_ent_alloc,
382
383 nfs_cache_init(cd);
384 err = nfs_cache_register_net(net, cd);
385 if (err) 382 if (err)
386 goto err_reg; 383 goto err_reg;
387 nn->nfs_dns_resolve = cd;
388 return 0; 384 return 0;
389 385
390err_reg: 386err_reg:
391 nfs_cache_destroy(cd); 387 cache_destroy_net(nn->nfs_dns_resolve, net);
392 kfree(cd->hash_table);
393err_tbl:
394 kfree(cd);
395err_cd:
396 return err; 388 return err;
397} 389}
398 390
399void nfs_dns_resolver_cache_destroy(struct net *net) 391void nfs_dns_resolver_cache_destroy(struct net *net)
400{ 392{
401 struct nfs_net *nn = net_generic(net, nfs_net_id); 393 struct nfs_net *nn = net_generic(net, nfs_net_id);
402 struct cache_detail *cd = nn->nfs_dns_resolve;
403 394
404 nfs_cache_unregister_net(net, cd); 395 nfs_cache_unregister_net(net, nn->nfs_dns_resolve);
405 nfs_cache_destroy(cd); 396 cache_destroy_net(nn->nfs_dns_resolve, net);
406 kfree(cd->hash_table);
407 kfree(cd);
408} 397}
409 398
410static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, 399static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index 47d100872390..ac4fc9a8fdbc 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -6,6 +6,7 @@
6#include <linux/nfs_fs.h> 6#include <linux/nfs_fs.h>
7#include <linux/nfs_idmap.h> 7#include <linux/nfs_idmap.h>
8#include <linux/nfs_mount.h> 8#include <linux/nfs_mount.h>
9#include <linux/sunrpc/addr.h>
9#include <linux/sunrpc/auth.h> 10#include <linux/sunrpc/auth.h>
10#include <linux/sunrpc/xprt.h> 11#include <linux/sunrpc/xprt.h>
11#include <linux/sunrpc/bc_xprt.h> 12#include <linux/sunrpc/bc_xprt.h>
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
index b720064bcd7f..1fe284f01f8b 100644
--- a/fs/nfs/nfs4filelayoutdev.c
+++ b/fs/nfs/nfs4filelayoutdev.c
@@ -31,6 +31,7 @@
31#include <linux/nfs_fs.h> 31#include <linux/nfs_fs.h>
32#include <linux/vmalloc.h> 32#include <linux/vmalloc.h>
33#include <linux/module.h> 33#include <linux/module.h>
34#include <linux/sunrpc/addr.h>
34 35
35#include "internal.h" 36#include "internal.h"
36#include "nfs4session.h" 37#include "nfs4session.h"
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index 1e09eb78543b..0dd766079e1c 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -14,6 +14,7 @@
14#include <linux/slab.h> 14#include <linux/slab.h>
15#include <linux/string.h> 15#include <linux/string.h>
16#include <linux/sunrpc/clnt.h> 16#include <linux/sunrpc/clnt.h>
17#include <linux/sunrpc/addr.h>
17#include <linux/vfs.h> 18#include <linux/vfs.h>
18#include <linux/inet.h> 19#include <linux/inet.h>
19#include "internal.h" 20#include "internal.h"
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index a9dc5fc29955..17b32b722457 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -31,6 +31,7 @@
31#include <linux/errno.h> 31#include <linux/errno.h>
32#include <linux/unistd.h> 32#include <linux/unistd.h>
33#include <linux/sunrpc/clnt.h> 33#include <linux/sunrpc/clnt.h>
34#include <linux/sunrpc/addr.h>
34#include <linux/sunrpc/stats.h> 35#include <linux/sunrpc/stats.h>
35#include <linux/sunrpc/metrics.h> 36#include <linux/sunrpc/metrics.h>
36#include <linux/sunrpc/xprtsock.h> 37#include <linux/sunrpc/xprtsock.h>
diff --git a/fs/nfsd/cache.h b/fs/nfsd/cache.h
index 93cc9d34c459..87fd1410b737 100644
--- a/fs/nfsd/cache.h
+++ b/fs/nfsd/cache.h
@@ -12,6 +12,10 @@
12 12
13/* 13/*
14 * Representation of a reply cache entry. 14 * Representation of a reply cache entry.
15 *
16 * Note that we use a sockaddr_in6 to hold the address instead of the more
17 * typical sockaddr_storage. This is for space reasons, since sockaddr_storage
18 * is much larger than a sockaddr_in6.
15 */ 19 */
16struct svc_cacherep { 20struct svc_cacherep {
17 struct hlist_node c_hash; 21 struct hlist_node c_hash;
@@ -20,11 +24,13 @@ struct svc_cacherep {
20 unsigned char c_state, /* unused, inprog, done */ 24 unsigned char c_state, /* unused, inprog, done */
21 c_type, /* status, buffer */ 25 c_type, /* status, buffer */
22 c_secure : 1; /* req came from port < 1024 */ 26 c_secure : 1; /* req came from port < 1024 */
23 struct sockaddr_in c_addr; 27 struct sockaddr_in6 c_addr;
24 __be32 c_xid; 28 __be32 c_xid;
25 u32 c_prot; 29 u32 c_prot;
26 u32 c_proc; 30 u32 c_proc;
27 u32 c_vers; 31 u32 c_vers;
32 unsigned int c_len;
33 __wsum c_csum;
28 unsigned long c_timestamp; 34 unsigned long c_timestamp;
29 union { 35 union {
30 struct kvec u_vec; 36 struct kvec u_vec;
@@ -46,8 +52,7 @@ enum {
46enum { 52enum {
47 RC_DROPIT, 53 RC_DROPIT,
48 RC_REPLY, 54 RC_REPLY,
49 RC_DOIT, 55 RC_DOIT
50 RC_INTR
51}; 56};
52 57
53/* 58/*
@@ -67,6 +72,12 @@ enum {
67 */ 72 */
68#define RC_DELAY (HZ/5) 73#define RC_DELAY (HZ/5)
69 74
75/* Cache entries expire after this time period */
76#define RC_EXPIRE (120 * HZ)
77
78/* Checksum this amount of the request */
79#define RC_CSUMLEN (256U)
80
70int nfsd_reply_cache_init(void); 81int nfsd_reply_cache_init(void);
71void nfsd_reply_cache_shutdown(void); 82void nfsd_reply_cache_shutdown(void);
72int nfsd_cache_lookup(struct svc_rqst *); 83int nfsd_cache_lookup(struct svc_rqst *);
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 5681c5906f08..5f38ea36e266 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -67,11 +67,6 @@ static void expkey_request(struct cache_detail *cd,
67 (*bpp)[-1] = '\n'; 67 (*bpp)[-1] = '\n';
68} 68}
69 69
70static int expkey_upcall(struct cache_detail *cd, struct cache_head *h)
71{
72 return sunrpc_cache_pipe_upcall(cd, h, expkey_request);
73}
74
75static struct svc_expkey *svc_expkey_update(struct cache_detail *cd, struct svc_expkey *new, 70static struct svc_expkey *svc_expkey_update(struct cache_detail *cd, struct svc_expkey *new,
76 struct svc_expkey *old); 71 struct svc_expkey *old);
77static struct svc_expkey *svc_expkey_lookup(struct cache_detail *cd, struct svc_expkey *); 72static struct svc_expkey *svc_expkey_lookup(struct cache_detail *cd, struct svc_expkey *);
@@ -245,7 +240,7 @@ static struct cache_detail svc_expkey_cache_template = {
245 .hash_size = EXPKEY_HASHMAX, 240 .hash_size = EXPKEY_HASHMAX,
246 .name = "nfsd.fh", 241 .name = "nfsd.fh",
247 .cache_put = expkey_put, 242 .cache_put = expkey_put,
248 .cache_upcall = expkey_upcall, 243 .cache_request = expkey_request,
249 .cache_parse = expkey_parse, 244 .cache_parse = expkey_parse,
250 .cache_show = expkey_show, 245 .cache_show = expkey_show,
251 .match = expkey_match, 246 .match = expkey_match,
@@ -315,6 +310,7 @@ static void svc_export_put(struct kref *ref)
315 path_put(&exp->ex_path); 310 path_put(&exp->ex_path);
316 auth_domain_put(exp->ex_client); 311 auth_domain_put(exp->ex_client);
317 nfsd4_fslocs_free(&exp->ex_fslocs); 312 nfsd4_fslocs_free(&exp->ex_fslocs);
313 kfree(exp->ex_uuid);
318 kfree(exp); 314 kfree(exp);
319} 315}
320 316
@@ -337,11 +333,6 @@ static void svc_export_request(struct cache_detail *cd,
337 (*bpp)[-1] = '\n'; 333 (*bpp)[-1] = '\n';
338} 334}
339 335
340static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h)
341{
342 return sunrpc_cache_pipe_upcall(cd, h, svc_export_request);
343}
344
345static struct svc_export *svc_export_update(struct svc_export *new, 336static struct svc_export *svc_export_update(struct svc_export *new,
346 struct svc_export *old); 337 struct svc_export *old);
347static struct svc_export *svc_export_lookup(struct svc_export *); 338static struct svc_export *svc_export_lookup(struct svc_export *);
@@ -674,6 +665,7 @@ static void svc_export_init(struct cache_head *cnew, struct cache_head *citem)
674 new->ex_fslocs.locations = NULL; 665 new->ex_fslocs.locations = NULL;
675 new->ex_fslocs.locations_count = 0; 666 new->ex_fslocs.locations_count = 0;
676 new->ex_fslocs.migrated = 0; 667 new->ex_fslocs.migrated = 0;
668 new->ex_uuid = NULL;
677 new->cd = item->cd; 669 new->cd = item->cd;
678} 670}
679 671
@@ -715,7 +707,7 @@ static struct cache_detail svc_export_cache_template = {
715 .hash_size = EXPORT_HASHMAX, 707 .hash_size = EXPORT_HASHMAX,
716 .name = "nfsd.export", 708 .name = "nfsd.export",
717 .cache_put = svc_export_put, 709 .cache_put = svc_export_put,
718 .cache_upcall = svc_export_upcall, 710 .cache_request = svc_export_request,
719 .cache_parse = svc_export_parse, 711 .cache_parse = svc_export_parse,
720 .cache_show = svc_export_show, 712 .cache_show = svc_export_show,
721 .match = svc_export_match, 713 .match = svc_export_match,
diff --git a/fs/nfsd/fault_inject.c b/fs/nfsd/fault_inject.c
index 497584c70366..d620e7f81429 100644
--- a/fs/nfsd/fault_inject.c
+++ b/fs/nfsd/fault_inject.c
@@ -9,7 +9,7 @@
9#include <linux/debugfs.h> 9#include <linux/debugfs.h>
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/nsproxy.h> 11#include <linux/nsproxy.h>
12#include <linux/sunrpc/clnt.h> 12#include <linux/sunrpc/addr.h>
13#include <asm/uaccess.h> 13#include <asm/uaccess.h>
14 14
15#include "state.h" 15#include "state.h"
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index 0ce12346df9c..4832fd819f88 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -140,12 +140,6 @@ idtoname_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
140} 140}
141 141
142static int 142static int
143idtoname_upcall(struct cache_detail *cd, struct cache_head *ch)
144{
145 return sunrpc_cache_pipe_upcall(cd, ch, idtoname_request);
146}
147
148static int
149idtoname_match(struct cache_head *ca, struct cache_head *cb) 143idtoname_match(struct cache_head *ca, struct cache_head *cb)
150{ 144{
151 struct ent *a = container_of(ca, struct ent, h); 145 struct ent *a = container_of(ca, struct ent, h);
@@ -192,7 +186,7 @@ static struct cache_detail idtoname_cache_template = {
192 .hash_size = ENT_HASHMAX, 186 .hash_size = ENT_HASHMAX,
193 .name = "nfs4.idtoname", 187 .name = "nfs4.idtoname",
194 .cache_put = ent_put, 188 .cache_put = ent_put,
195 .cache_upcall = idtoname_upcall, 189 .cache_request = idtoname_request,
196 .cache_parse = idtoname_parse, 190 .cache_parse = idtoname_parse,
197 .cache_show = idtoname_show, 191 .cache_show = idtoname_show,
198 .warn_no_listener = warn_no_idmapd, 192 .warn_no_listener = warn_no_idmapd,
@@ -321,12 +315,6 @@ nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
321} 315}
322 316
323static int 317static int
324nametoid_upcall(struct cache_detail *cd, struct cache_head *ch)
325{
326 return sunrpc_cache_pipe_upcall(cd, ch, nametoid_request);
327}
328
329static int
330nametoid_match(struct cache_head *ca, struct cache_head *cb) 318nametoid_match(struct cache_head *ca, struct cache_head *cb)
331{ 319{
332 struct ent *a = container_of(ca, struct ent, h); 320 struct ent *a = container_of(ca, struct ent, h);
@@ -365,7 +353,7 @@ static struct cache_detail nametoid_cache_template = {
365 .hash_size = ENT_HASHMAX, 353 .hash_size = ENT_HASHMAX,
366 .name = "nfs4.nametoid", 354 .name = "nfs4.nametoid",
367 .cache_put = ent_put, 355 .cache_put = ent_put,
368 .cache_upcall = nametoid_upcall, 356 .cache_request = nametoid_request,
369 .cache_parse = nametoid_parse, 357 .cache_parse = nametoid_parse,
370 .cache_show = nametoid_show, 358 .cache_show = nametoid_show,
371 .warn_no_listener = warn_no_idmapd, 359 .warn_no_listener = warn_no_idmapd,
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 9d1c5dba2bbb..ae73175e6e68 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -993,14 +993,15 @@ _nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
993 if (!buf) 993 if (!buf)
994 return nfserr_jukebox; 994 return nfserr_jukebox;
995 995
996 p = buf;
996 status = nfsd4_encode_fattr(&cstate->current_fh, 997 status = nfsd4_encode_fattr(&cstate->current_fh,
997 cstate->current_fh.fh_export, 998 cstate->current_fh.fh_export,
998 cstate->current_fh.fh_dentry, buf, 999 cstate->current_fh.fh_dentry, &p,
999 &count, verify->ve_bmval, 1000 count, verify->ve_bmval,
1000 rqstp, 0); 1001 rqstp, 0);
1001 1002
1002 /* this means that nfsd4_encode_fattr() ran out of space */ 1003 /* this means that nfsd4_encode_fattr() ran out of space */
1003 if (status == nfserr_resource && count == 0) 1004 if (status == nfserr_resource)
1004 status = nfserr_not_same; 1005 status = nfserr_not_same;
1005 if (status) 1006 if (status)
1006 goto out_kfree; 1007 goto out_kfree;
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 4914af4a817e..899ca26dd194 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -1185,6 +1185,12 @@ bin_to_hex_dup(const unsigned char *src, int srclen)
1185static int 1185static int
1186nfsd4_umh_cltrack_init(struct net __attribute__((unused)) *net) 1186nfsd4_umh_cltrack_init(struct net __attribute__((unused)) *net)
1187{ 1187{
1188 /* XXX: The usermode helper s not working in container yet. */
1189 if (net != &init_net) {
1190 WARN(1, KERN_ERR "NFSD: attempt to initialize umh client "
1191 "tracking in a container!\n");
1192 return -EINVAL;
1193 }
1188 return nfsd4_umh_cltrack_upcall("init", NULL, NULL); 1194 return nfsd4_umh_cltrack_upcall("init", NULL, NULL);
1189} 1195}
1190 1196
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 9e7103b6e0ad..16d39c6c4fbb 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -40,7 +40,7 @@
40#include <linux/pagemap.h> 40#include <linux/pagemap.h>
41#include <linux/ratelimit.h> 41#include <linux/ratelimit.h>
42#include <linux/sunrpc/svcauth_gss.h> 42#include <linux/sunrpc/svcauth_gss.h>
43#include <linux/sunrpc/clnt.h> 43#include <linux/sunrpc/addr.h>
44#include "xdr4.h" 44#include "xdr4.h"
45#include "vfs.h" 45#include "vfs.h"
46#include "current_stateid.h" 46#include "current_stateid.h"
@@ -261,33 +261,46 @@ static inline int get_new_stid(struct nfs4_stid *stid)
261 return new_stid; 261 return new_stid;
262} 262}
263 263
264static void init_stid(struct nfs4_stid *stid, struct nfs4_client *cl, unsigned char type) 264static struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct
265kmem_cache *slab)
265{ 266{
266 stateid_t *s = &stid->sc_stateid; 267 struct idr *stateids = &cl->cl_stateids;
268 static int min_stateid = 0;
269 struct nfs4_stid *stid;
267 int new_id; 270 int new_id;
268 271
269 stid->sc_type = type; 272 stid = kmem_cache_alloc(slab, GFP_KERNEL);
273 if (!stid)
274 return NULL;
275
276 if (!idr_pre_get(stateids, GFP_KERNEL))
277 goto out_free;
278 if (idr_get_new_above(stateids, stid, min_stateid, &new_id))
279 goto out_free;
270 stid->sc_client = cl; 280 stid->sc_client = cl;
271 s->si_opaque.so_clid = cl->cl_clientid; 281 stid->sc_type = 0;
272 new_id = get_new_stid(stid); 282 stid->sc_stateid.si_opaque.so_id = new_id;
273 s->si_opaque.so_id = (u32)new_id; 283 stid->sc_stateid.si_opaque.so_clid = cl->cl_clientid;
274 /* Will be incremented before return to client: */ 284 /* Will be incremented before return to client: */
275 s->si_generation = 0; 285 stid->sc_stateid.si_generation = 0;
276}
277
278static struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct kmem_cache *slab)
279{
280 struct idr *stateids = &cl->cl_stateids;
281 286
282 if (!idr_pre_get(stateids, GFP_KERNEL))
283 return NULL;
284 /* 287 /*
285 * Note: if we fail here (or any time between now and the time 288 * It shouldn't be a problem to reuse an opaque stateid value.
286 * we actually get the new idr), we won't need to undo the idr 289 * I don't think it is for 4.1. But with 4.0 I worry that, for
287 * preallocation, since the idr code caps the number of 290 * example, a stray write retransmission could be accepted by
288 * preallocated entries. 291 * the server when it should have been rejected. Therefore,
292 * adopt a trick from the sctp code to attempt to maximize the
293 * amount of time until an id is reused, by ensuring they always
294 * "increase" (mod INT_MAX):
289 */ 295 */
290 return kmem_cache_alloc(slab, GFP_KERNEL); 296
297 min_stateid = new_id+1;
298 if (min_stateid == INT_MAX)
299 min_stateid = 0;
300 return stid;
301out_free:
302 kfree(stid);
303 return NULL;
291} 304}
292 305
293static struct nfs4_ol_stateid * nfs4_alloc_stateid(struct nfs4_client *clp) 306static struct nfs4_ol_stateid * nfs4_alloc_stateid(struct nfs4_client *clp)
@@ -316,7 +329,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct sv
316 dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab)); 329 dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab));
317 if (dp == NULL) 330 if (dp == NULL)
318 return dp; 331 return dp;
319 init_stid(&dp->dl_stid, clp, NFS4_DELEG_STID); 332 dp->dl_stid.sc_type = NFS4_DELEG_STID;
320 /* 333 /*
321 * delegation seqid's are never incremented. The 4.1 special 334 * delegation seqid's are never incremented. The 4.1 special
322 * meaning of seqid 0 isn't meaningful, really, but let's avoid 335 * meaning of seqid 0 isn't meaningful, really, but let's avoid
@@ -337,13 +350,21 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct sv
337 return dp; 350 return dp;
338} 351}
339 352
353static void free_stid(struct nfs4_stid *s, struct kmem_cache *slab)
354{
355 struct idr *stateids = &s->sc_client->cl_stateids;
356
357 idr_remove(stateids, s->sc_stateid.si_opaque.so_id);
358 kmem_cache_free(slab, s);
359}
360
340void 361void
341nfs4_put_delegation(struct nfs4_delegation *dp) 362nfs4_put_delegation(struct nfs4_delegation *dp)
342{ 363{
343 if (atomic_dec_and_test(&dp->dl_count)) { 364 if (atomic_dec_and_test(&dp->dl_count)) {
344 dprintk("NFSD: freeing dp %p\n",dp); 365 dprintk("NFSD: freeing dp %p\n",dp);
345 put_nfs4_file(dp->dl_file); 366 put_nfs4_file(dp->dl_file);
346 kmem_cache_free(deleg_slab, dp); 367 free_stid(&dp->dl_stid, deleg_slab);
347 num_delegations--; 368 num_delegations--;
348 } 369 }
349} 370}
@@ -360,9 +381,7 @@ static void nfs4_put_deleg_lease(struct nfs4_file *fp)
360 381
361static void unhash_stid(struct nfs4_stid *s) 382static void unhash_stid(struct nfs4_stid *s)
362{ 383{
363 struct idr *stateids = &s->sc_client->cl_stateids; 384 s->sc_type = 0;
364
365 idr_remove(stateids, s->sc_stateid.si_opaque.so_id);
366} 385}
367 386
368/* Called under the state lock. */ 387/* Called under the state lock. */
@@ -519,7 +538,7 @@ static void close_generic_stateid(struct nfs4_ol_stateid *stp)
519 538
520static void free_generic_stateid(struct nfs4_ol_stateid *stp) 539static void free_generic_stateid(struct nfs4_ol_stateid *stp)
521{ 540{
522 kmem_cache_free(stateid_slab, stp); 541 free_stid(&stp->st_stid, stateid_slab);
523} 542}
524 543
525static void release_lock_stateid(struct nfs4_ol_stateid *stp) 544static void release_lock_stateid(struct nfs4_ol_stateid *stp)
@@ -905,7 +924,7 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan,
905 924
906 new = __alloc_session(slotsize, numslots); 925 new = __alloc_session(slotsize, numslots);
907 if (!new) { 926 if (!new) {
908 nfsd4_put_drc_mem(slotsize, fchan->maxreqs); 927 nfsd4_put_drc_mem(slotsize, numslots);
909 return NULL; 928 return NULL;
910 } 929 }
911 init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize, nn); 930 init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize, nn);
@@ -1048,7 +1067,7 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
1048static inline void 1067static inline void
1049free_client(struct nfs4_client *clp) 1068free_client(struct nfs4_client *clp)
1050{ 1069{
1051 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1070 struct nfsd_net __maybe_unused *nn = net_generic(clp->net, nfsd_net_id);
1052 1071
1053 lockdep_assert_held(&nn->client_lock); 1072 lockdep_assert_held(&nn->client_lock);
1054 while (!list_empty(&clp->cl_sessions)) { 1073 while (!list_empty(&clp->cl_sessions)) {
@@ -1060,6 +1079,7 @@ free_client(struct nfs4_client *clp)
1060 } 1079 }
1061 free_svc_cred(&clp->cl_cred); 1080 free_svc_cred(&clp->cl_cred);
1062 kfree(clp->cl_name.data); 1081 kfree(clp->cl_name.data);
1082 idr_destroy(&clp->cl_stateids);
1063 kfree(clp); 1083 kfree(clp);
1064} 1084}
1065 1085
@@ -1258,7 +1278,12 @@ static void gen_confirm(struct nfs4_client *clp)
1258 1278
1259static struct nfs4_stid *find_stateid(struct nfs4_client *cl, stateid_t *t) 1279static struct nfs4_stid *find_stateid(struct nfs4_client *cl, stateid_t *t)
1260{ 1280{
1261 return idr_find(&cl->cl_stateids, t->si_opaque.so_id); 1281 struct nfs4_stid *ret;
1282
1283 ret = idr_find(&cl->cl_stateids, t->si_opaque.so_id);
1284 if (!ret || !ret->sc_type)
1285 return NULL;
1286 return ret;
1262} 1287}
1263 1288
1264static struct nfs4_stid *find_stateid_by_type(struct nfs4_client *cl, stateid_t *t, char typemask) 1289static struct nfs4_stid *find_stateid_by_type(struct nfs4_client *cl, stateid_t *t, char typemask)
@@ -1844,11 +1869,12 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1844 1869
1845 /* cache solo and embedded create sessions under the state lock */ 1870 /* cache solo and embedded create sessions under the state lock */
1846 nfsd4_cache_create_session(cr_ses, cs_slot, status); 1871 nfsd4_cache_create_session(cr_ses, cs_slot, status);
1847out:
1848 nfs4_unlock_state(); 1872 nfs4_unlock_state();
1873out:
1849 dprintk("%s returns %d\n", __func__, ntohl(status)); 1874 dprintk("%s returns %d\n", __func__, ntohl(status));
1850 return status; 1875 return status;
1851out_free_conn: 1876out_free_conn:
1877 nfs4_unlock_state();
1852 free_conn(conn); 1878 free_conn(conn);
1853out_free_session: 1879out_free_session:
1854 __free_session(new); 1880 __free_session(new);
@@ -2443,9 +2469,8 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
2443 2469
2444static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *open) { 2470static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *open) {
2445 struct nfs4_openowner *oo = open->op_openowner; 2471 struct nfs4_openowner *oo = open->op_openowner;
2446 struct nfs4_client *clp = oo->oo_owner.so_client;
2447 2472
2448 init_stid(&stp->st_stid, clp, NFS4_OPEN_STID); 2473 stp->st_stid.sc_type = NFS4_OPEN_STID;
2449 INIT_LIST_HEAD(&stp->st_lockowners); 2474 INIT_LIST_HEAD(&stp->st_lockowners);
2450 list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids); 2475 list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids);
2451 list_add(&stp->st_perfile, &fp->fi_stateids); 2476 list_add(&stp->st_perfile, &fp->fi_stateids);
@@ -4031,7 +4056,7 @@ alloc_init_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp, struct
4031 stp = nfs4_alloc_stateid(clp); 4056 stp = nfs4_alloc_stateid(clp);
4032 if (stp == NULL) 4057 if (stp == NULL)
4033 return NULL; 4058 return NULL;
4034 init_stid(&stp->st_stid, clp, NFS4_LOCK_STID); 4059 stp->st_stid.sc_type = NFS4_LOCK_STID;
4035 list_add(&stp->st_perfile, &fp->fi_stateids); 4060 list_add(&stp->st_perfile, &fp->fi_stateids);
4036 list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids); 4061 list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids);
4037 stp->st_stateowner = &lo->lo_owner; 4062 stp->st_stateowner = &lo->lo_owner;
@@ -4913,16 +4938,6 @@ nfs4_state_start_net(struct net *net)
4913 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 4938 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
4914 int ret; 4939 int ret;
4915 4940
4916 /*
4917 * FIXME: For now, we hang most of the pernet global stuff off of
4918 * init_net until nfsd is fully containerized. Eventually, we'll
4919 * need to pass a net pointer into this function, take a reference
4920 * to that instead and then do most of the rest of this on a per-net
4921 * basis.
4922 */
4923 if (net != &init_net)
4924 return -EINVAL;
4925
4926 ret = nfs4_state_create_net(net); 4941 ret = nfs4_state_create_net(net);
4927 if (ret) 4942 if (ret)
4928 return ret; 4943 return ret;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 8ca6d17f6cf3..01168865dd37 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2024,12 +2024,11 @@ static int get_parent_attributes(struct svc_export *exp, struct kstat *stat)
2024 * Note: @fhp can be NULL; in this case, we might have to compose the filehandle 2024 * Note: @fhp can be NULL; in this case, we might have to compose the filehandle
2025 * ourselves. 2025 * ourselves.
2026 * 2026 *
2027 * @countp is the buffer size in _words_; upon successful return this becomes 2027 * countp is the buffer size in _words_
2028 * replaced with the number of words written.
2029 */ 2028 */
2030__be32 2029__be32
2031nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, 2030nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
2032 struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval, 2031 struct dentry *dentry, __be32 **buffer, int count, u32 *bmval,
2033 struct svc_rqst *rqstp, int ignore_crossmnt) 2032 struct svc_rqst *rqstp, int ignore_crossmnt)
2034{ 2033{
2035 u32 bmval0 = bmval[0]; 2034 u32 bmval0 = bmval[0];
@@ -2038,12 +2037,12 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
2038 struct kstat stat; 2037 struct kstat stat;
2039 struct svc_fh tempfh; 2038 struct svc_fh tempfh;
2040 struct kstatfs statfs; 2039 struct kstatfs statfs;
2041 int buflen = *countp << 2; 2040 int buflen = count << 2;
2042 __be32 *attrlenp; 2041 __be32 *attrlenp;
2043 u32 dummy; 2042 u32 dummy;
2044 u64 dummy64; 2043 u64 dummy64;
2045 u32 rdattr_err = 0; 2044 u32 rdattr_err = 0;
2046 __be32 *p = buffer; 2045 __be32 *p = *buffer;
2047 __be32 status; 2046 __be32 status;
2048 int err; 2047 int err;
2049 int aclsupport = 0; 2048 int aclsupport = 0;
@@ -2447,7 +2446,7 @@ out_acl:
2447 } 2446 }
2448 2447
2449 *attrlenp = htonl((char *)p - (char *)attrlenp - 4); 2448 *attrlenp = htonl((char *)p - (char *)attrlenp - 4);
2450 *countp = p - buffer; 2449 *buffer = p;
2451 status = nfs_ok; 2450 status = nfs_ok;
2452 2451
2453out: 2452out:
@@ -2459,7 +2458,6 @@ out_nfserr:
2459 status = nfserrno(err); 2458 status = nfserrno(err);
2460 goto out; 2459 goto out;
2461out_resource: 2460out_resource:
2462 *countp = 0;
2463 status = nfserr_resource; 2461 status = nfserr_resource;
2464 goto out; 2462 goto out;
2465out_serverfault: 2463out_serverfault:
@@ -2478,7 +2476,7 @@ static inline int attributes_need_mount(u32 *bmval)
2478 2476
2479static __be32 2477static __be32
2480nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd, 2478nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
2481 const char *name, int namlen, __be32 *p, int *buflen) 2479 const char *name, int namlen, __be32 **p, int buflen)
2482{ 2480{
2483 struct svc_export *exp = cd->rd_fhp->fh_export; 2481 struct svc_export *exp = cd->rd_fhp->fh_export;
2484 struct dentry *dentry; 2482 struct dentry *dentry;
@@ -2584,10 +2582,9 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
2584 p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */ 2582 p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */
2585 p = xdr_encode_array(p, name, namlen); /* name length & name */ 2583 p = xdr_encode_array(p, name, namlen); /* name length & name */
2586 2584
2587 nfserr = nfsd4_encode_dirent_fattr(cd, name, namlen, p, &buflen); 2585 nfserr = nfsd4_encode_dirent_fattr(cd, name, namlen, &p, buflen);
2588 switch (nfserr) { 2586 switch (nfserr) {
2589 case nfs_ok: 2587 case nfs_ok:
2590 p += buflen;
2591 break; 2588 break;
2592 case nfserr_resource: 2589 case nfserr_resource:
2593 nfserr = nfserr_toosmall; 2590 nfserr = nfserr_toosmall;
@@ -2714,10 +2711,8 @@ nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
2714 2711
2715 buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2); 2712 buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2);
2716 nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry, 2713 nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry,
2717 resp->p, &buflen, getattr->ga_bmval, 2714 &resp->p, buflen, getattr->ga_bmval,
2718 resp->rqstp, 0); 2715 resp->rqstp, 0);
2719 if (!nfserr)
2720 resp->p += buflen;
2721 return nfserr; 2716 return nfserr;
2722} 2717}
2723 2718
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index da3dbd0f8979..62c1ee128aeb 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -9,22 +9,22 @@
9 */ 9 */
10 10
11#include <linux/slab.h> 11#include <linux/slab.h>
12#include <linux/sunrpc/addr.h>
13#include <linux/highmem.h>
14#include <net/checksum.h>
12 15
13#include "nfsd.h" 16#include "nfsd.h"
14#include "cache.h" 17#include "cache.h"
15 18
16/* Size of reply cache. Common values are: 19#define NFSDDBG_FACILITY NFSDDBG_REPCACHE
17 * 4.3BSD: 128 20
18 * 4.4BSD: 256
19 * Solaris2: 1024
20 * DEC Unix: 512-4096
21 */
22#define CACHESIZE 1024
23#define HASHSIZE 64 21#define HASHSIZE 64
24 22
25static struct hlist_head * cache_hash; 23static struct hlist_head * cache_hash;
26static struct list_head lru_head; 24static struct list_head lru_head;
27static int cache_disabled = 1; 25static struct kmem_cache *drc_slab;
26static unsigned int num_drc_entries;
27static unsigned int max_drc_entries;
28 28
29/* 29/*
30 * Calculate the hash index from an XID. 30 * Calculate the hash index from an XID.
@@ -37,6 +37,14 @@ static inline u32 request_hash(u32 xid)
37} 37}
38 38
39static int nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *vec); 39static int nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *vec);
40static void cache_cleaner_func(struct work_struct *unused);
41static int nfsd_reply_cache_shrink(struct shrinker *shrink,
42 struct shrink_control *sc);
43
44struct shrinker nfsd_reply_cache_shrinker = {
45 .shrink = nfsd_reply_cache_shrink,
46 .seeks = 1,
47};
40 48
41/* 49/*
42 * locking for the reply cache: 50 * locking for the reply cache:
@@ -44,30 +52,86 @@ static int nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *vec);
44 * Otherwise, it when accessing _prev or _next, the lock must be held. 52 * Otherwise, it when accessing _prev or _next, the lock must be held.
45 */ 53 */
46static DEFINE_SPINLOCK(cache_lock); 54static DEFINE_SPINLOCK(cache_lock);
55static DECLARE_DELAYED_WORK(cache_cleaner, cache_cleaner_func);
47 56
48int nfsd_reply_cache_init(void) 57/*
58 * Put a cap on the size of the DRC based on the amount of available
59 * low memory in the machine.
60 *
61 * 64MB: 8192
62 * 128MB: 11585
63 * 256MB: 16384
64 * 512MB: 23170
65 * 1GB: 32768
66 * 2GB: 46340
67 * 4GB: 65536
68 * 8GB: 92681
69 * 16GB: 131072
70 *
71 * ...with a hard cap of 256k entries. In the worst case, each entry will be
72 * ~1k, so the above numbers should give a rough max of the amount of memory
73 * used in k.
74 */
75static unsigned int
76nfsd_cache_size_limit(void)
77{
78 unsigned int limit;
79 unsigned long low_pages = totalram_pages - totalhigh_pages;
80
81 limit = (16 * int_sqrt(low_pages)) << (PAGE_SHIFT-10);
82 return min_t(unsigned int, limit, 256*1024);
83}
84
85static struct svc_cacherep *
86nfsd_reply_cache_alloc(void)
49{ 87{
50 struct svc_cacherep *rp; 88 struct svc_cacherep *rp;
51 int i;
52 89
53 INIT_LIST_HEAD(&lru_head); 90 rp = kmem_cache_alloc(drc_slab, GFP_KERNEL);
54 i = CACHESIZE; 91 if (rp) {
55 while (i) {
56 rp = kmalloc(sizeof(*rp), GFP_KERNEL);
57 if (!rp)
58 goto out_nomem;
59 list_add(&rp->c_lru, &lru_head);
60 rp->c_state = RC_UNUSED; 92 rp->c_state = RC_UNUSED;
61 rp->c_type = RC_NOCACHE; 93 rp->c_type = RC_NOCACHE;
94 INIT_LIST_HEAD(&rp->c_lru);
62 INIT_HLIST_NODE(&rp->c_hash); 95 INIT_HLIST_NODE(&rp->c_hash);
63 i--;
64 } 96 }
97 return rp;
98}
65 99
66 cache_hash = kcalloc (HASHSIZE, sizeof(struct hlist_head), GFP_KERNEL); 100static void
101nfsd_reply_cache_free_locked(struct svc_cacherep *rp)
102{
103 if (rp->c_type == RC_REPLBUFF)
104 kfree(rp->c_replvec.iov_base);
105 hlist_del(&rp->c_hash);
106 list_del(&rp->c_lru);
107 --num_drc_entries;
108 kmem_cache_free(drc_slab, rp);
109}
110
111static void
112nfsd_reply_cache_free(struct svc_cacherep *rp)
113{
114 spin_lock(&cache_lock);
115 nfsd_reply_cache_free_locked(rp);
116 spin_unlock(&cache_lock);
117}
118
119int nfsd_reply_cache_init(void)
120{
121 register_shrinker(&nfsd_reply_cache_shrinker);
122 drc_slab = kmem_cache_create("nfsd_drc", sizeof(struct svc_cacherep),
123 0, 0, NULL);
124 if (!drc_slab)
125 goto out_nomem;
126
127 cache_hash = kcalloc(HASHSIZE, sizeof(struct hlist_head), GFP_KERNEL);
67 if (!cache_hash) 128 if (!cache_hash)
68 goto out_nomem; 129 goto out_nomem;
69 130
70 cache_disabled = 0; 131 INIT_LIST_HEAD(&lru_head);
132 max_drc_entries = nfsd_cache_size_limit();
133 num_drc_entries = 0;
134
71 return 0; 135 return 0;
72out_nomem: 136out_nomem:
73 printk(KERN_ERR "nfsd: failed to allocate reply cache\n"); 137 printk(KERN_ERR "nfsd: failed to allocate reply cache\n");
@@ -79,27 +143,33 @@ void nfsd_reply_cache_shutdown(void)
79{ 143{
80 struct svc_cacherep *rp; 144 struct svc_cacherep *rp;
81 145
146 unregister_shrinker(&nfsd_reply_cache_shrinker);
147 cancel_delayed_work_sync(&cache_cleaner);
148
82 while (!list_empty(&lru_head)) { 149 while (!list_empty(&lru_head)) {
83 rp = list_entry(lru_head.next, struct svc_cacherep, c_lru); 150 rp = list_entry(lru_head.next, struct svc_cacherep, c_lru);
84 if (rp->c_state == RC_DONE && rp->c_type == RC_REPLBUFF) 151 nfsd_reply_cache_free_locked(rp);
85 kfree(rp->c_replvec.iov_base);
86 list_del(&rp->c_lru);
87 kfree(rp);
88 } 152 }
89 153
90 cache_disabled = 1;
91
92 kfree (cache_hash); 154 kfree (cache_hash);
93 cache_hash = NULL; 155 cache_hash = NULL;
156
157 if (drc_slab) {
158 kmem_cache_destroy(drc_slab);
159 drc_slab = NULL;
160 }
94} 161}
95 162
96/* 163/*
97 * Move cache entry to end of LRU list 164 * Move cache entry to end of LRU list, and queue the cleaner to run if it's
165 * not already scheduled.
98 */ 166 */
99static void 167static void
100lru_put_end(struct svc_cacherep *rp) 168lru_put_end(struct svc_cacherep *rp)
101{ 169{
170 rp->c_timestamp = jiffies;
102 list_move_tail(&rp->c_lru, &lru_head); 171 list_move_tail(&rp->c_lru, &lru_head);
172 schedule_delayed_work(&cache_cleaner, RC_EXPIRE);
103} 173}
104 174
105/* 175/*
@@ -112,82 +182,214 @@ hash_refile(struct svc_cacherep *rp)
112 hlist_add_head(&rp->c_hash, cache_hash + request_hash(rp->c_xid)); 182 hlist_add_head(&rp->c_hash, cache_hash + request_hash(rp->c_xid));
113} 183}
114 184
185static inline bool
186nfsd_cache_entry_expired(struct svc_cacherep *rp)
187{
188 return rp->c_state != RC_INPROG &&
189 time_after(jiffies, rp->c_timestamp + RC_EXPIRE);
190}
191
192/*
193 * Walk the LRU list and prune off entries that are older than RC_EXPIRE.
194 * Also prune the oldest ones when the total exceeds the max number of entries.
195 */
196static void
197prune_cache_entries(void)
198{
199 struct svc_cacherep *rp, *tmp;
200
201 list_for_each_entry_safe(rp, tmp, &lru_head, c_lru) {
202 if (!nfsd_cache_entry_expired(rp) &&
203 num_drc_entries <= max_drc_entries)
204 break;
205 nfsd_reply_cache_free_locked(rp);
206 }
207
208 /*
209 * Conditionally rearm the job. If we cleaned out the list, then
210 * cancel any pending run (since there won't be any work to do).
211 * Otherwise, we rearm the job or modify the existing one to run in
212 * RC_EXPIRE since we just ran the pruner.
213 */
214 if (list_empty(&lru_head))
215 cancel_delayed_work(&cache_cleaner);
216 else
217 mod_delayed_work(system_wq, &cache_cleaner, RC_EXPIRE);
218}
219
220static void
221cache_cleaner_func(struct work_struct *unused)
222{
223 spin_lock(&cache_lock);
224 prune_cache_entries();
225 spin_unlock(&cache_lock);
226}
227
228static int
229nfsd_reply_cache_shrink(struct shrinker *shrink, struct shrink_control *sc)
230{
231 unsigned int num;
232
233 spin_lock(&cache_lock);
234 if (sc->nr_to_scan)
235 prune_cache_entries();
236 num = num_drc_entries;
237 spin_unlock(&cache_lock);
238
239 return num;
240}
241
242/*
243 * Walk an xdr_buf and get a CRC for at most the first RC_CSUMLEN bytes
244 */
245static __wsum
246nfsd_cache_csum(struct svc_rqst *rqstp)
247{
248 int idx;
249 unsigned int base;
250 __wsum csum;
251 struct xdr_buf *buf = &rqstp->rq_arg;
252 const unsigned char *p = buf->head[0].iov_base;
253 size_t csum_len = min_t(size_t, buf->head[0].iov_len + buf->page_len,
254 RC_CSUMLEN);
255 size_t len = min(buf->head[0].iov_len, csum_len);
256
257 /* rq_arg.head first */
258 csum = csum_partial(p, len, 0);
259 csum_len -= len;
260
261 /* Continue into page array */
262 idx = buf->page_base / PAGE_SIZE;
263 base = buf->page_base & ~PAGE_MASK;
264 while (csum_len) {
265 p = page_address(buf->pages[idx]) + base;
266 len = min_t(size_t, PAGE_SIZE - base, csum_len);
267 csum = csum_partial(p, len, csum);
268 csum_len -= len;
269 base = 0;
270 ++idx;
271 }
272 return csum;
273}
274
275/*
276 * Search the request hash for an entry that matches the given rqstp.
277 * Must be called with cache_lock held. Returns the found entry or
278 * NULL on failure.
279 */
280static struct svc_cacherep *
281nfsd_cache_search(struct svc_rqst *rqstp, __wsum csum)
282{
283 struct svc_cacherep *rp;
284 struct hlist_head *rh;
285 __be32 xid = rqstp->rq_xid;
286 u32 proto = rqstp->rq_prot,
287 vers = rqstp->rq_vers,
288 proc = rqstp->rq_proc;
289
290 rh = &cache_hash[request_hash(xid)];
291 hlist_for_each_entry(rp, rh, c_hash) {
292 if (xid == rp->c_xid && proc == rp->c_proc &&
293 proto == rp->c_prot && vers == rp->c_vers &&
294 rqstp->rq_arg.len == rp->c_len && csum == rp->c_csum &&
295 rpc_cmp_addr(svc_addr(rqstp), (struct sockaddr *)&rp->c_addr) &&
296 rpc_get_port(svc_addr(rqstp)) == rpc_get_port((struct sockaddr *)&rp->c_addr))
297 return rp;
298 }
299 return NULL;
300}
301
115/* 302/*
116 * Try to find an entry matching the current call in the cache. When none 303 * Try to find an entry matching the current call in the cache. When none
117 * is found, we grab the oldest unlocked entry off the LRU list. 304 * is found, we try to grab the oldest expired entry off the LRU list. If
118 * Note that no operation within the loop may sleep. 305 * a suitable one isn't there, then drop the cache_lock and allocate a
306 * new one, then search again in case one got inserted while this thread
307 * didn't hold the lock.
119 */ 308 */
120int 309int
121nfsd_cache_lookup(struct svc_rqst *rqstp) 310nfsd_cache_lookup(struct svc_rqst *rqstp)
122{ 311{
123 struct hlist_head *rh; 312 struct svc_cacherep *rp, *found;
124 struct svc_cacherep *rp;
125 __be32 xid = rqstp->rq_xid; 313 __be32 xid = rqstp->rq_xid;
126 u32 proto = rqstp->rq_prot, 314 u32 proto = rqstp->rq_prot,
127 vers = rqstp->rq_vers, 315 vers = rqstp->rq_vers,
128 proc = rqstp->rq_proc; 316 proc = rqstp->rq_proc;
317 __wsum csum;
129 unsigned long age; 318 unsigned long age;
130 int type = rqstp->rq_cachetype; 319 int type = rqstp->rq_cachetype;
131 int rtn; 320 int rtn;
132 321
133 rqstp->rq_cacherep = NULL; 322 rqstp->rq_cacherep = NULL;
134 if (cache_disabled || type == RC_NOCACHE) { 323 if (type == RC_NOCACHE) {
135 nfsdstats.rcnocache++; 324 nfsdstats.rcnocache++;
136 return RC_DOIT; 325 return RC_DOIT;
137 } 326 }
138 327
328 csum = nfsd_cache_csum(rqstp);
329
139 spin_lock(&cache_lock); 330 spin_lock(&cache_lock);
140 rtn = RC_DOIT; 331 rtn = RC_DOIT;
141 332
142 rh = &cache_hash[request_hash(xid)]; 333 rp = nfsd_cache_search(rqstp, csum);
143 hlist_for_each_entry(rp, rh, c_hash) { 334 if (rp)
144 if (rp->c_state != RC_UNUSED && 335 goto found_entry;
145 xid == rp->c_xid && proc == rp->c_proc && 336
146 proto == rp->c_prot && vers == rp->c_vers && 337 /* Try to use the first entry on the LRU */
147 time_before(jiffies, rp->c_timestamp + 120*HZ) && 338 if (!list_empty(&lru_head)) {
148 memcmp((char*)&rqstp->rq_addr, (char*)&rp->c_addr, sizeof(rp->c_addr))==0) { 339 rp = list_first_entry(&lru_head, struct svc_cacherep, c_lru);
149 nfsdstats.rchits++; 340 if (nfsd_cache_entry_expired(rp) ||
150 goto found_entry; 341 num_drc_entries >= max_drc_entries) {
342 lru_put_end(rp);
343 prune_cache_entries();
344 goto setup_entry;
151 } 345 }
152 } 346 }
153 nfsdstats.rcmisses++;
154 347
155 /* This loop shouldn't take more than a few iterations normally */ 348 /* Drop the lock and allocate a new entry */
156 { 349 spin_unlock(&cache_lock);
157 int safe = 0; 350 rp = nfsd_reply_cache_alloc();
158 list_for_each_entry(rp, &lru_head, c_lru) { 351 if (!rp) {
159 if (rp->c_state != RC_INPROG) 352 dprintk("nfsd: unable to allocate DRC entry!\n");
160 break; 353 return RC_DOIT;
161 if (safe++ > CACHESIZE) {
162 printk("nfsd: loop in repcache LRU list\n");
163 cache_disabled = 1;
164 goto out;
165 }
166 } 354 }
355 spin_lock(&cache_lock);
356 ++num_drc_entries;
357
358 /*
359 * Must search again just in case someone inserted one
360 * after we dropped the lock above.
361 */
362 found = nfsd_cache_search(rqstp, csum);
363 if (found) {
364 nfsd_reply_cache_free_locked(rp);
365 rp = found;
366 goto found_entry;
167 } 367 }
168 368
169 /* All entries on the LRU are in-progress. This should not happen */ 369 /*
170 if (&rp->c_lru == &lru_head) { 370 * We're keeping the one we just allocated. Are we now over the
171 static int complaints; 371 * limit? Prune one off the tip of the LRU in trade for the one we
172 372 * just allocated if so.
173 printk(KERN_WARNING "nfsd: all repcache entries locked!\n"); 373 */
174 if (++complaints > 5) { 374 if (num_drc_entries >= max_drc_entries)
175 printk(KERN_WARNING "nfsd: disabling repcache.\n"); 375 nfsd_reply_cache_free_locked(list_first_entry(&lru_head,
176 cache_disabled = 1; 376 struct svc_cacherep, c_lru));
177 }
178 goto out;
179 }
180 377
378setup_entry:
379 nfsdstats.rcmisses++;
181 rqstp->rq_cacherep = rp; 380 rqstp->rq_cacherep = rp;
182 rp->c_state = RC_INPROG; 381 rp->c_state = RC_INPROG;
183 rp->c_xid = xid; 382 rp->c_xid = xid;
184 rp->c_proc = proc; 383 rp->c_proc = proc;
185 memcpy(&rp->c_addr, svc_addr_in(rqstp), sizeof(rp->c_addr)); 384 rpc_copy_addr((struct sockaddr *)&rp->c_addr, svc_addr(rqstp));
385 rpc_set_port((struct sockaddr *)&rp->c_addr, rpc_get_port(svc_addr(rqstp)));
186 rp->c_prot = proto; 386 rp->c_prot = proto;
187 rp->c_vers = vers; 387 rp->c_vers = vers;
188 rp->c_timestamp = jiffies; 388 rp->c_len = rqstp->rq_arg.len;
389 rp->c_csum = csum;
189 390
190 hash_refile(rp); 391 hash_refile(rp);
392 lru_put_end(rp);
191 393
192 /* release any buffer */ 394 /* release any buffer */
193 if (rp->c_type == RC_REPLBUFF) { 395 if (rp->c_type == RC_REPLBUFF) {
@@ -200,9 +402,9 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
200 return rtn; 402 return rtn;
201 403
202found_entry: 404found_entry:
405 nfsdstats.rchits++;
203 /* We found a matching entry which is either in progress or done. */ 406 /* We found a matching entry which is either in progress or done. */
204 age = jiffies - rp->c_timestamp; 407 age = jiffies - rp->c_timestamp;
205 rp->c_timestamp = jiffies;
206 lru_put_end(rp); 408 lru_put_end(rp);
207 409
208 rtn = RC_DROPIT; 410 rtn = RC_DROPIT;
@@ -231,7 +433,7 @@ found_entry:
231 break; 433 break;
232 default: 434 default:
233 printk(KERN_WARNING "nfsd: bad repcache type %d\n", rp->c_type); 435 printk(KERN_WARNING "nfsd: bad repcache type %d\n", rp->c_type);
234 rp->c_state = RC_UNUSED; 436 nfsd_reply_cache_free_locked(rp);
235 } 437 }
236 438
237 goto out; 439 goto out;
@@ -256,11 +458,11 @@ found_entry:
256void 458void
257nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, __be32 *statp) 459nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, __be32 *statp)
258{ 460{
259 struct svc_cacherep *rp; 461 struct svc_cacherep *rp = rqstp->rq_cacherep;
260 struct kvec *resv = &rqstp->rq_res.head[0], *cachv; 462 struct kvec *resv = &rqstp->rq_res.head[0], *cachv;
261 int len; 463 int len;
262 464
263 if (!(rp = rqstp->rq_cacherep) || cache_disabled) 465 if (!rp)
264 return; 466 return;
265 467
266 len = resv->iov_len - ((char*)statp - (char*)resv->iov_base); 468 len = resv->iov_len - ((char*)statp - (char*)resv->iov_base);
@@ -268,7 +470,7 @@ nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, __be32 *statp)
268 470
269 /* Don't cache excessive amounts of data and XDR failures */ 471 /* Don't cache excessive amounts of data and XDR failures */
270 if (!statp || len > (256 >> 2)) { 472 if (!statp || len > (256 >> 2)) {
271 rp->c_state = RC_UNUSED; 473 nfsd_reply_cache_free(rp);
272 return; 474 return;
273 } 475 }
274 476
@@ -282,21 +484,21 @@ nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, __be32 *statp)
282 cachv = &rp->c_replvec; 484 cachv = &rp->c_replvec;
283 cachv->iov_base = kmalloc(len << 2, GFP_KERNEL); 485 cachv->iov_base = kmalloc(len << 2, GFP_KERNEL);
284 if (!cachv->iov_base) { 486 if (!cachv->iov_base) {
285 spin_lock(&cache_lock); 487 nfsd_reply_cache_free(rp);
286 rp->c_state = RC_UNUSED;
287 spin_unlock(&cache_lock);
288 return; 488 return;
289 } 489 }
290 cachv->iov_len = len << 2; 490 cachv->iov_len = len << 2;
291 memcpy(cachv->iov_base, statp, len << 2); 491 memcpy(cachv->iov_base, statp, len << 2);
292 break; 492 break;
493 case RC_NOCACHE:
494 nfsd_reply_cache_free(rp);
495 return;
293 } 496 }
294 spin_lock(&cache_lock); 497 spin_lock(&cache_lock);
295 lru_put_end(rp); 498 lru_put_end(rp);
296 rp->c_secure = rqstp->rq_secure; 499 rp->c_secure = rqstp->rq_secure;
297 rp->c_type = cachetype; 500 rp->c_type = cachetype;
298 rp->c_state = RC_DONE; 501 rp->c_state = RC_DONE;
299 rp->c_timestamp = jiffies;
300 spin_unlock(&cache_lock); 502 spin_unlock(&cache_lock);
301 return; 503 return;
302} 504}
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 2db7021b01ae..13a21c8fca49 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -10,7 +10,7 @@
10 10
11#include <linux/sunrpc/svcsock.h> 11#include <linux/sunrpc/svcsock.h>
12#include <linux/lockd/lockd.h> 12#include <linux/lockd/lockd.h>
13#include <linux/sunrpc/clnt.h> 13#include <linux/sunrpc/addr.h>
14#include <linux/sunrpc/gss_api.h> 14#include <linux/sunrpc/gss_api.h>
15#include <linux/sunrpc/gss_krb5_enctypes.h> 15#include <linux/sunrpc/gss_krb5_enctypes.h>
16#include <linux/sunrpc/rpc_pipe_fs.h> 16#include <linux/sunrpc/rpc_pipe_fs.h>
@@ -125,11 +125,11 @@ static const struct file_operations transaction_ops = {
125 .llseek = default_llseek, 125 .llseek = default_llseek,
126}; 126};
127 127
128static int exports_open(struct inode *inode, struct file *file) 128static int exports_net_open(struct net *net, struct file *file)
129{ 129{
130 int err; 130 int err;
131 struct seq_file *seq; 131 struct seq_file *seq;
132 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 132 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
133 133
134 err = seq_open(file, &nfs_exports_op); 134 err = seq_open(file, &nfs_exports_op);
135 if (err) 135 if (err)
@@ -140,8 +140,26 @@ static int exports_open(struct inode *inode, struct file *file)
140 return 0; 140 return 0;
141} 141}
142 142
143static const struct file_operations exports_operations = { 143static int exports_proc_open(struct inode *inode, struct file *file)
144 .open = exports_open, 144{
145 return exports_net_open(current->nsproxy->net_ns, file);
146}
147
148static const struct file_operations exports_proc_operations = {
149 .open = exports_proc_open,
150 .read = seq_read,
151 .llseek = seq_lseek,
152 .release = seq_release,
153 .owner = THIS_MODULE,
154};
155
156static int exports_nfsd_open(struct inode *inode, struct file *file)
157{
158 return exports_net_open(inode->i_sb->s_fs_info, file);
159}
160
161static const struct file_operations exports_nfsd_operations = {
162 .open = exports_nfsd_open,
145 .read = seq_read, 163 .read = seq_read,
146 .llseek = seq_lseek, 164 .llseek = seq_lseek,
147 .release = seq_release, 165 .release = seq_release,
@@ -220,6 +238,7 @@ static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
220 struct sockaddr *sap = (struct sockaddr *)&address; 238 struct sockaddr *sap = (struct sockaddr *)&address;
221 size_t salen = sizeof(address); 239 size_t salen = sizeof(address);
222 char *fo_path; 240 char *fo_path;
241 struct net *net = file->f_dentry->d_sb->s_fs_info;
223 242
224 /* sanity check */ 243 /* sanity check */
225 if (size == 0) 244 if (size == 0)
@@ -232,7 +251,7 @@ static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
232 if (qword_get(&buf, fo_path, size) < 0) 251 if (qword_get(&buf, fo_path, size) < 0)
233 return -EINVAL; 252 return -EINVAL;
234 253
235 if (rpc_pton(&init_net, fo_path, size, sap, salen) == 0) 254 if (rpc_pton(net, fo_path, size, sap, salen) == 0)
236 return -EINVAL; 255 return -EINVAL;
237 256
238 return nlmsvc_unlock_all_by_ip(sap); 257 return nlmsvc_unlock_all_by_ip(sap);
@@ -317,6 +336,7 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
317 int len; 336 int len;
318 struct auth_domain *dom; 337 struct auth_domain *dom;
319 struct knfsd_fh fh; 338 struct knfsd_fh fh;
339 struct net *net = file->f_dentry->d_sb->s_fs_info;
320 340
321 if (size == 0) 341 if (size == 0)
322 return -EINVAL; 342 return -EINVAL;
@@ -352,7 +372,7 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
352 if (!dom) 372 if (!dom)
353 return -ENOMEM; 373 return -ENOMEM;
354 374
355 len = exp_rootfh(&init_net, dom, path, &fh, maxsize); 375 len = exp_rootfh(net, dom, path, &fh, maxsize);
356 auth_domain_put(dom); 376 auth_domain_put(dom);
357 if (len) 377 if (len)
358 return len; 378 return len;
@@ -396,7 +416,7 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
396{ 416{
397 char *mesg = buf; 417 char *mesg = buf;
398 int rv; 418 int rv;
399 struct net *net = &init_net; 419 struct net *net = file->f_dentry->d_sb->s_fs_info;
400 420
401 if (size > 0) { 421 if (size > 0) {
402 int newthreads; 422 int newthreads;
@@ -447,7 +467,7 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
447 int len; 467 int len;
448 int npools; 468 int npools;
449 int *nthreads; 469 int *nthreads;
450 struct net *net = &init_net; 470 struct net *net = file->f_dentry->d_sb->s_fs_info;
451 471
452 mutex_lock(&nfsd_mutex); 472 mutex_lock(&nfsd_mutex);
453 npools = nfsd_nrpools(net); 473 npools = nfsd_nrpools(net);
@@ -510,7 +530,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
510 unsigned minor; 530 unsigned minor;
511 ssize_t tlen = 0; 531 ssize_t tlen = 0;
512 char *sep; 532 char *sep;
513 struct net *net = &init_net; 533 struct net *net = file->f_dentry->d_sb->s_fs_info;
514 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 534 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
515 535
516 if (size>0) { 536 if (size>0) {
@@ -534,7 +554,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
534 else 554 else
535 num = simple_strtol(vers, &minorp, 0); 555 num = simple_strtol(vers, &minorp, 0);
536 if (*minorp == '.') { 556 if (*minorp == '.') {
537 if (num < 4) 557 if (num != 4)
538 return -EINVAL; 558 return -EINVAL;
539 minor = simple_strtoul(minorp+1, NULL, 0); 559 minor = simple_strtoul(minorp+1, NULL, 0);
540 if (minor == 0) 560 if (minor == 0)
@@ -792,7 +812,7 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size,
792static ssize_t write_ports(struct file *file, char *buf, size_t size) 812static ssize_t write_ports(struct file *file, char *buf, size_t size)
793{ 813{
794 ssize_t rv; 814 ssize_t rv;
795 struct net *net = &init_net; 815 struct net *net = file->f_dentry->d_sb->s_fs_info;
796 816
797 mutex_lock(&nfsd_mutex); 817 mutex_lock(&nfsd_mutex);
798 rv = __write_ports(file, buf, size, net); 818 rv = __write_ports(file, buf, size, net);
@@ -827,7 +847,7 @@ int nfsd_max_blksize;
827static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) 847static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
828{ 848{
829 char *mesg = buf; 849 char *mesg = buf;
830 struct net *net = &init_net; 850 struct net *net = file->f_dentry->d_sb->s_fs_info;
831 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 851 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
832 852
833 if (size > 0) { 853 if (size > 0) {
@@ -923,7 +943,8 @@ static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size,
923 */ 943 */
924static ssize_t write_leasetime(struct file *file, char *buf, size_t size) 944static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
925{ 945{
926 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 946 struct net *net = file->f_dentry->d_sb->s_fs_info;
947 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
927 return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease, nn); 948 return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease, nn);
928} 949}
929 950
@@ -939,7 +960,8 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
939 */ 960 */
940static ssize_t write_gracetime(struct file *file, char *buf, size_t size) 961static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
941{ 962{
942 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 963 struct net *net = file->f_dentry->d_sb->s_fs_info;
964 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
943 return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace, nn); 965 return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace, nn);
944} 966}
945 967
@@ -995,7 +1017,8 @@ static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size,
995static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) 1017static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
996{ 1018{
997 ssize_t rv; 1019 ssize_t rv;
998 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 1020 struct net *net = file->f_dentry->d_sb->s_fs_info;
1021 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
999 1022
1000 mutex_lock(&nfsd_mutex); 1023 mutex_lock(&nfsd_mutex);
1001 rv = __write_recoverydir(file, buf, size, nn); 1024 rv = __write_recoverydir(file, buf, size, nn);
@@ -1013,7 +1036,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
1013static int nfsd_fill_super(struct super_block * sb, void * data, int silent) 1036static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
1014{ 1037{
1015 static struct tree_descr nfsd_files[] = { 1038 static struct tree_descr nfsd_files[] = {
1016 [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, 1039 [NFSD_List] = {"exports", &exports_nfsd_operations, S_IRUGO},
1017 [NFSD_Export_features] = {"export_features", 1040 [NFSD_Export_features] = {"export_features",
1018 &export_features_operations, S_IRUGO}, 1041 &export_features_operations, S_IRUGO},
1019 [NFSD_FO_UnlockIP] = {"unlock_ip", 1042 [NFSD_FO_UnlockIP] = {"unlock_ip",
@@ -1037,20 +1060,35 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
1037#endif 1060#endif
1038 /* last one */ {""} 1061 /* last one */ {""}
1039 }; 1062 };
1040 return simple_fill_super(sb, 0x6e667364, nfsd_files); 1063 struct net *net = data;
1064 int ret;
1065
1066 ret = simple_fill_super(sb, 0x6e667364, nfsd_files);
1067 if (ret)
1068 return ret;
1069 sb->s_fs_info = get_net(net);
1070 return 0;
1041} 1071}
1042 1072
1043static struct dentry *nfsd_mount(struct file_system_type *fs_type, 1073static struct dentry *nfsd_mount(struct file_system_type *fs_type,
1044 int flags, const char *dev_name, void *data) 1074 int flags, const char *dev_name, void *data)
1045{ 1075{
1046 return mount_single(fs_type, flags, data, nfsd_fill_super); 1076 return mount_ns(fs_type, flags, current->nsproxy->net_ns, nfsd_fill_super);
1077}
1078
1079static void nfsd_umount(struct super_block *sb)
1080{
1081 struct net *net = sb->s_fs_info;
1082
1083 kill_litter_super(sb);
1084 put_net(net);
1047} 1085}
1048 1086
1049static struct file_system_type nfsd_fs_type = { 1087static struct file_system_type nfsd_fs_type = {
1050 .owner = THIS_MODULE, 1088 .owner = THIS_MODULE,
1051 .name = "nfsd", 1089 .name = "nfsd",
1052 .mount = nfsd_mount, 1090 .mount = nfsd_mount,
1053 .kill_sb = kill_litter_super, 1091 .kill_sb = nfsd_umount,
1054}; 1092};
1055 1093
1056#ifdef CONFIG_PROC_FS 1094#ifdef CONFIG_PROC_FS
@@ -1061,7 +1099,8 @@ static int create_proc_exports_entry(void)
1061 entry = proc_mkdir("fs/nfs", NULL); 1099 entry = proc_mkdir("fs/nfs", NULL);
1062 if (!entry) 1100 if (!entry)
1063 return -ENOMEM; 1101 return -ENOMEM;
1064 entry = proc_create("exports", 0, entry, &exports_operations); 1102 entry = proc_create("exports", 0, entry,
1103 &exports_proc_operations);
1065 if (!entry) 1104 if (!entry)
1066 return -ENOMEM; 1105 return -ENOMEM;
1067 return 0; 1106 return 0;
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index be7af509930c..262df5ccbf59 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -652,7 +652,6 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
652 652
653 /* Check whether we have this call in the cache. */ 653 /* Check whether we have this call in the cache. */
654 switch (nfsd_cache_lookup(rqstp)) { 654 switch (nfsd_cache_lookup(rqstp)) {
655 case RC_INTR:
656 case RC_DROPIT: 655 case RC_DROPIT:
657 return 0; 656 return 0;
658 case RC_REPLY: 657 case RC_REPLY:
@@ -703,8 +702,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
703int nfsd_pool_stats_open(struct inode *inode, struct file *file) 702int nfsd_pool_stats_open(struct inode *inode, struct file *file)
704{ 703{
705 int ret; 704 int ret;
706 struct net *net = &init_net; 705 struct nfsd_net *nn = net_generic(inode->i_sb->s_fs_info, nfsd_net_id);
707 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
708 706
709 mutex_lock(&nfsd_mutex); 707 mutex_lock(&nfsd_mutex);
710 if (nn->nfsd_serv == NULL) { 708 if (nn->nfsd_serv == NULL) {
@@ -721,7 +719,7 @@ int nfsd_pool_stats_open(struct inode *inode, struct file *file)
721int nfsd_pool_stats_release(struct inode *inode, struct file *file) 719int nfsd_pool_stats_release(struct inode *inode, struct file *file)
722{ 720{
723 int ret = seq_release(inode, file); 721 int ret = seq_release(inode, file);
724 struct net *net = &init_net; 722 struct net *net = inode->i_sb->s_fs_info;
725 723
726 mutex_lock(&nfsd_mutex); 724 mutex_lock(&nfsd_mutex);
727 /* this function really, really should have been called svc_put() */ 725 /* this function really, really should have been called svc_put() */
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 0889bfb43dc9..546f8983ecf1 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -563,7 +563,7 @@ __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *, u32);
563void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *); 563void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *);
564void nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op); 564void nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op);
565__be32 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, 565__be32 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
566 struct dentry *dentry, __be32 *buffer, int *countp, 566 struct dentry *dentry, __be32 **buffer, int countp,
567 u32 *bmval, struct svc_rqst *, int ignore_crossmnt); 567 u32 *bmval, struct svc_rqst *, int ignore_crossmnt);
568extern __be32 nfsd4_setclientid(struct svc_rqst *rqstp, 568extern __be32 nfsd4_setclientid(struct svc_rqst *rqstp,
569 struct nfsd4_compound_state *, 569 struct nfsd4_compound_state *,