aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Banks <gnb@melbourne.sgi.com>2006-10-04 05:15:47 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-04 10:55:16 -0400
commit7adae489fe794e3e203ff168595f635d0b845e59 (patch)
treef20544b72bdaea7cff0d340b5b4e5bfcaf2ce8fb
parent3cc03b164cf01c6f36e64720b58610d292fb26f7 (diff)
[PATCH] knfsd: Prepare knfsd for support of rsize/wsize of up to 1MB, over TCP
The limit over UDP remains at 32K. Also, make some of the apparently arbitrary sizing constants clearer. The biggest change here involves replacing NFSSVC_MAXBLKSIZE by a function of the rqstp. This allows it to be different for different protocols (udp/tcp) and also allows it to depend on the servers declared sv_bufsiz. Note that we don't actually increase sv_bufsz for nfs yet. That comes next. Signed-off-by: Greg Banks <gnb@melbourne.sgi.com> Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/nfsd/nfs3proc.c14
-rw-r--r--fs/nfsd/nfs3xdr.c13
-rw-r--r--fs/nfsd/nfs4xdr.c6
-rw-r--r--fs/nfsd/nfsproc.c6
-rw-r--r--fs/nfsd/nfsxdr.c10
-rw-r--r--include/linux/nfsd/const.h15
-rw-r--r--include/linux/sunrpc/auth.h3
-rw-r--r--include/linux/sunrpc/msg_prot.h40
-rw-r--r--include/linux/sunrpc/svc.h23
-rw-r--r--include/linux/sunrpc/xprt.h8
-rw-r--r--net/sunrpc/svc.c15
11 files changed, 119 insertions, 34 deletions
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 0c4fab018791..a5ebc7dbb384 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -160,6 +160,7 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
160 struct nfsd3_readres *resp) 160 struct nfsd3_readres *resp)
161{ 161{
162 int nfserr; 162 int nfserr;
163 u32 max_blocksize = svc_max_payload(rqstp);
163 164
164 dprintk("nfsd: READ(3) %s %lu bytes at %lu\n", 165 dprintk("nfsd: READ(3) %s %lu bytes at %lu\n",
165 SVCFH_fmt(&argp->fh), 166 SVCFH_fmt(&argp->fh),
@@ -172,8 +173,8 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
172 */ 173 */
173 174
174 resp->count = argp->count; 175 resp->count = argp->count;
175 if (NFSSVC_MAXBLKSIZE < resp->count) 176 if (max_blocksize < resp->count)
176 resp->count = NFSSVC_MAXBLKSIZE; 177 resp->count = max_blocksize;
177 178
178 svc_reserve(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4); 179 svc_reserve(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
179 180
@@ -538,15 +539,16 @@ nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
538 struct nfsd3_fsinfores *resp) 539 struct nfsd3_fsinfores *resp)
539{ 540{
540 int nfserr; 541 int nfserr;
542 u32 max_blocksize = svc_max_payload(rqstp);
541 543
542 dprintk("nfsd: FSINFO(3) %s\n", 544 dprintk("nfsd: FSINFO(3) %s\n",
543 SVCFH_fmt(&argp->fh)); 545 SVCFH_fmt(&argp->fh));
544 546
545 resp->f_rtmax = NFSSVC_MAXBLKSIZE; 547 resp->f_rtmax = max_blocksize;
546 resp->f_rtpref = NFSSVC_MAXBLKSIZE; 548 resp->f_rtpref = max_blocksize;
547 resp->f_rtmult = PAGE_SIZE; 549 resp->f_rtmult = PAGE_SIZE;
548 resp->f_wtmax = NFSSVC_MAXBLKSIZE; 550 resp->f_wtmax = max_blocksize;
549 resp->f_wtpref = NFSSVC_MAXBLKSIZE; 551 resp->f_wtpref = max_blocksize;
550 resp->f_wtmult = PAGE_SIZE; 552 resp->f_wtmult = PAGE_SIZE;
551 resp->f_dtpref = PAGE_SIZE; 553 resp->f_dtpref = PAGE_SIZE;
552 resp->f_maxfilesize = ~(u32) 0; 554 resp->f_maxfilesize = ~(u32) 0;
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 4b9aefbcc93c..247d518248bf 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -330,6 +330,7 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, u32 *p,
330{ 330{
331 unsigned int len; 331 unsigned int len;
332 int v,pn; 332 int v,pn;
333 u32 max_blocksize = svc_max_payload(rqstp);
333 334
334 if (!(p = decode_fh(p, &args->fh)) 335 if (!(p = decode_fh(p, &args->fh))
335 || !(p = xdr_decode_hyper(p, &args->offset))) 336 || !(p = xdr_decode_hyper(p, &args->offset)))
@@ -337,8 +338,8 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, u32 *p,
337 338
338 len = args->count = ntohl(*p++); 339 len = args->count = ntohl(*p++);
339 340
340 if (len > NFSSVC_MAXBLKSIZE) 341 if (len > max_blocksize)
341 len = NFSSVC_MAXBLKSIZE; 342 len = max_blocksize;
342 343
343 /* set up the kvec */ 344 /* set up the kvec */
344 v=0; 345 v=0;
@@ -358,6 +359,7 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
358 struct nfsd3_writeargs *args) 359 struct nfsd3_writeargs *args)
359{ 360{
360 unsigned int len, v, hdr; 361 unsigned int len, v, hdr;
362 u32 max_blocksize = svc_max_payload(rqstp);
361 363
362 if (!(p = decode_fh(p, &args->fh)) 364 if (!(p = decode_fh(p, &args->fh))
363 || !(p = xdr_decode_hyper(p, &args->offset))) 365 || !(p = xdr_decode_hyper(p, &args->offset)))
@@ -375,8 +377,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
375 rqstp->rq_vec[0].iov_base = (void*)p; 377 rqstp->rq_vec[0].iov_base = (void*)p;
376 rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr; 378 rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
377 379
378 if (len > NFSSVC_MAXBLKSIZE) 380 if (len > max_blocksize)
379 len = NFSSVC_MAXBLKSIZE; 381 len = max_blocksize;
380 v= 0; 382 v= 0;
381 while (len > rqstp->rq_vec[v].iov_len) { 383 while (len > rqstp->rq_vec[v].iov_len) {
382 len -= rqstp->rq_vec[v].iov_len; 384 len -= rqstp->rq_vec[v].iov_len;
@@ -564,6 +566,7 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, u32 *p,
564 struct nfsd3_readdirargs *args) 566 struct nfsd3_readdirargs *args)
565{ 567{
566 int len, pn; 568 int len, pn;
569 u32 max_blocksize = svc_max_payload(rqstp);
567 570
568 if (!(p = decode_fh(p, &args->fh))) 571 if (!(p = decode_fh(p, &args->fh)))
569 return 0; 572 return 0;
@@ -572,7 +575,7 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, u32 *p,
572 args->dircount = ntohl(*p++); 575 args->dircount = ntohl(*p++);
573 args->count = ntohl(*p++); 576 args->count = ntohl(*p++);
574 577
575 len = (args->count > NFSSVC_MAXBLKSIZE) ? NFSSVC_MAXBLKSIZE : 578 len = (args->count > max_blocksize) ? max_blocksize :
576 args->count; 579 args->count;
577 args->count = len; 580 args->count = len;
578 581
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index df341956254e..4cfacc557b40 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1536,12 +1536,12 @@ out_acl:
1536 if (bmval0 & FATTR4_WORD0_MAXREAD) { 1536 if (bmval0 & FATTR4_WORD0_MAXREAD) {
1537 if ((buflen -= 8) < 0) 1537 if ((buflen -= 8) < 0)
1538 goto out_resource; 1538 goto out_resource;
1539 WRITE64((u64) NFSSVC_MAXBLKSIZE); 1539 WRITE64((u64) svc_max_payload(rqstp));
1540 } 1540 }
1541 if (bmval0 & FATTR4_WORD0_MAXWRITE) { 1541 if (bmval0 & FATTR4_WORD0_MAXWRITE) {
1542 if ((buflen -= 8) < 0) 1542 if ((buflen -= 8) < 0)
1543 goto out_resource; 1543 goto out_resource;
1544 WRITE64((u64) NFSSVC_MAXBLKSIZE); 1544 WRITE64((u64) svc_max_payload(rqstp));
1545 } 1545 }
1546 if (bmval1 & FATTR4_WORD1_MODE) { 1546 if (bmval1 & FATTR4_WORD1_MODE) {
1547 if ((buflen -= 4) < 0) 1547 if ((buflen -= 4) < 0)
@@ -2055,7 +2055,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr,
2055 2055
2056 RESERVE_SPACE(8); /* eof flag and byte count */ 2056 RESERVE_SPACE(8); /* eof flag and byte count */
2057 2057
2058 maxcount = NFSSVC_MAXBLKSIZE; 2058 maxcount = svc_max_payload(resp->rqstp);
2059 if (maxcount > read->rd_length) 2059 if (maxcount > read->rd_length)
2060 maxcount = read->rd_length; 2060 maxcount = read->rd_length;
2061 2061
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index ca4973150218..9ee1dab5d44a 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -146,13 +146,13 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
146 * status, 17 words for fattr, and 1 word for the byte count. 146 * status, 17 words for fattr, and 1 word for the byte count.
147 */ 147 */
148 148
149 if (NFSSVC_MAXBLKSIZE < argp->count) { 149 if (NFSSVC_MAXBLKSIZE_V2 < argp->count) {
150 printk(KERN_NOTICE 150 printk(KERN_NOTICE
151 "oversized read request from %u.%u.%u.%u:%d (%d bytes)\n", 151 "oversized read request from %u.%u.%u.%u:%d (%d bytes)\n",
152 NIPQUAD(rqstp->rq_addr.sin_addr.s_addr), 152 NIPQUAD(rqstp->rq_addr.sin_addr.s_addr),
153 ntohs(rqstp->rq_addr.sin_port), 153 ntohs(rqstp->rq_addr.sin_port),
154 argp->count); 154 argp->count);
155 argp->count = NFSSVC_MAXBLKSIZE; 155 argp->count = NFSSVC_MAXBLKSIZE_V2;
156 } 156 }
157 svc_reserve(rqstp, (19<<2) + argp->count + 4); 157 svc_reserve(rqstp, (19<<2) + argp->count + 4);
158 158
@@ -553,7 +553,7 @@ static struct svc_procedure nfsd_procedures2[18] = {
553 PROC(none, void, void, none, RC_NOCACHE, ST), 553 PROC(none, void, void, none, RC_NOCACHE, ST),
554 PROC(lookup, diropargs, diropres, fhandle, RC_NOCACHE, ST+FH+AT), 554 PROC(lookup, diropargs, diropres, fhandle, RC_NOCACHE, ST+FH+AT),
555 PROC(readlink, readlinkargs, readlinkres, none, RC_NOCACHE, ST+1+NFS_MAXPATHLEN/4), 555 PROC(readlink, readlinkargs, readlinkres, none, RC_NOCACHE, ST+1+NFS_MAXPATHLEN/4),
556 PROC(read, readargs, readres, fhandle, RC_NOCACHE, ST+AT+1+NFSSVC_MAXBLKSIZE/4), 556 PROC(read, readargs, readres, fhandle, RC_NOCACHE, ST+AT+1+NFSSVC_MAXBLKSIZE_V2/4),
557 PROC(none, void, void, none, RC_NOCACHE, ST), 557 PROC(none, void, void, none, RC_NOCACHE, ST),
558 PROC(write, writeargs, attrstat, fhandle, RC_REPLBUFF, ST+AT), 558 PROC(write, writeargs, attrstat, fhandle, RC_REPLBUFF, ST+AT),
559 PROC(create, createargs, diropres, fhandle, RC_REPLBUFF, ST+FH+AT), 559 PROC(create, createargs, diropres, fhandle, RC_REPLBUFF, ST+FH+AT),
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index ab6745e78d16..1135c0d14557 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -254,8 +254,8 @@ nfssvc_decode_readargs(struct svc_rqst *rqstp, u32 *p,
254 len = args->count = ntohl(*p++); 254 len = args->count = ntohl(*p++);
255 p++; /* totalcount - unused */ 255 p++; /* totalcount - unused */
256 256
257 if (len > NFSSVC_MAXBLKSIZE) 257 if (len > NFSSVC_MAXBLKSIZE_V2)
258 len = NFSSVC_MAXBLKSIZE; 258 len = NFSSVC_MAXBLKSIZE_V2;
259 259
260 /* set up somewhere to store response. 260 /* set up somewhere to store response.
261 * We take pages, put them on reslist and include in iovec 261 * We take pages, put them on reslist and include in iovec
@@ -288,8 +288,8 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
288 rqstp->rq_vec[0].iov_base = (void*)p; 288 rqstp->rq_vec[0].iov_base = (void*)p;
289 rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - 289 rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len -
290 (((void*)p) - rqstp->rq_arg.head[0].iov_base); 290 (((void*)p) - rqstp->rq_arg.head[0].iov_base);
291 if (len > NFSSVC_MAXBLKSIZE) 291 if (len > NFSSVC_MAXBLKSIZE_V2)
292 len = NFSSVC_MAXBLKSIZE; 292 len = NFSSVC_MAXBLKSIZE_V2;
293 v = 0; 293 v = 0;
294 while (len > rqstp->rq_vec[v].iov_len) { 294 while (len > rqstp->rq_vec[v].iov_len) {
295 len -= rqstp->rq_vec[v].iov_len; 295 len -= rqstp->rq_vec[v].iov_len;
@@ -458,7 +458,7 @@ nfssvc_encode_statfsres(struct svc_rqst *rqstp, u32 *p,
458{ 458{
459 struct kstatfs *stat = &resp->stats; 459 struct kstatfs *stat = &resp->stats;
460 460
461 *p++ = htonl(NFSSVC_MAXBLKSIZE); /* max transfer size */ 461 *p++ = htonl(NFSSVC_MAXBLKSIZE_V2); /* max transfer size */
462 *p++ = htonl(stat->f_bsize); 462 *p++ = htonl(stat->f_bsize);
463 *p++ = htonl(stat->f_blocks); 463 *p++ = htonl(stat->f_blocks);
464 *p++ = htonl(stat->f_bfree); 464 *p++ = htonl(stat->f_bfree);
diff --git a/include/linux/nfsd/const.h b/include/linux/nfsd/const.h
index b75bb1b38d09..adbddf007898 100644
--- a/include/linux/nfsd/const.h
+++ b/include/linux/nfsd/const.h
@@ -13,6 +13,7 @@
13#include <linux/nfs2.h> 13#include <linux/nfs2.h>
14#include <linux/nfs3.h> 14#include <linux/nfs3.h>
15#include <linux/nfs4.h> 15#include <linux/nfs4.h>
16#include <linux/sunrpc/msg_prot.h>
16 17
17/* 18/*
18 * Maximum protocol version supported by knfsd 19 * Maximum protocol version supported by knfsd
@@ -23,6 +24,8 @@
23 * Maximum blocksize supported by daemon currently at 32K 24 * Maximum blocksize supported by daemon currently at 32K
24 */ 25 */
25#define NFSSVC_MAXBLKSIZE (32*1024) 26#define NFSSVC_MAXBLKSIZE (32*1024)
27/* NFSv2 is limited by the protocol specification, see RFC 1094 */
28#define NFSSVC_MAXBLKSIZE_V2 (8*1024)
26 29
27#ifdef __KERNEL__ 30#ifdef __KERNEL__
28 31
@@ -30,7 +33,17 @@
30# define NFS_SUPER_MAGIC 0x6969 33# define NFS_SUPER_MAGIC 0x6969
31#endif 34#endif
32 35
33#define NFSD_BUFSIZE (1024 + NFSSVC_MAXBLKSIZE) 36/*
37 * Largest number of bytes we need to allocate for an NFS
38 * call or reply. Used to control buffer sizes. We use
39 * the length of v3 WRITE, READDIR and READDIR replies
40 * which are an RPC header, up to 26 XDR units of reply
41 * data, and some page data.
42 *
43 * Note that accuracy here doesn't matter too much as the
44 * size is rounded up to a page size when allocating space.
45 */
46#define NFSD_BUFSIZE ((RPC_MAX_HEADER_WITH_AUTH+26)*XDR_UNIT + NFSSVC_MAXBLKSIZE)
34 47
35#ifdef CONFIG_NFSD_V4 48#ifdef CONFIG_NFSD_V4
36# define NFSSVC_XDRSIZE NFS4_SVC_XDRSIZE 49# define NFSSVC_XDRSIZE NFS4_SVC_XDRSIZE
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index 862c0d8c8381..534cdc7be58d 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -20,9 +20,6 @@
20/* size of the nodename buffer */ 20/* size of the nodename buffer */
21#define UNX_MAXNODENAME 32 21#define UNX_MAXNODENAME 32
22 22
23/* Maximum size (in bytes) of an rpc credential or verifier */
24#define RPC_MAX_AUTH_SIZE (400)
25
26/* Work around the lack of a VFS credential */ 23/* Work around the lack of a VFS credential */
27struct auth_cred { 24struct auth_cred {
28 uid_t uid; 25 uid_t uid;
diff --git a/include/linux/sunrpc/msg_prot.h b/include/linux/sunrpc/msg_prot.h
index 8d10d148834e..1e65f2dd80e5 100644
--- a/include/linux/sunrpc/msg_prot.h
+++ b/include/linux/sunrpc/msg_prot.h
@@ -11,6 +11,9 @@
11 11
12#define RPC_VERSION 2 12#define RPC_VERSION 2
13 13
14/* size of an XDR encoding unit in bytes, i.e. 32bit */
15#define XDR_UNIT (4)
16
14/* spec defines authentication flavor as an unsigned 32 bit integer */ 17/* spec defines authentication flavor as an unsigned 32 bit integer */
15typedef u32 rpc_authflavor_t; 18typedef u32 rpc_authflavor_t;
16 19
@@ -34,6 +37,9 @@ enum rpc_auth_flavors {
34 RPC_AUTH_GSS_SPKMP = 390011, 37 RPC_AUTH_GSS_SPKMP = 390011,
35}; 38};
36 39
40/* Maximum size (in bytes) of an rpc credential or verifier */
41#define RPC_MAX_AUTH_SIZE (400)
42
37enum rpc_msg_type { 43enum rpc_msg_type {
38 RPC_CALL = 0, 44 RPC_CALL = 0,
39 RPC_REPLY = 1 45 RPC_REPLY = 1
@@ -101,5 +107,39 @@ typedef __be32 rpc_fraghdr;
101#define RPC_FRAGMENT_SIZE_MASK (~RPC_LAST_STREAM_FRAGMENT) 107#define RPC_FRAGMENT_SIZE_MASK (~RPC_LAST_STREAM_FRAGMENT)
102#define RPC_MAX_FRAGMENT_SIZE ((1U << 31) - 1) 108#define RPC_MAX_FRAGMENT_SIZE ((1U << 31) - 1)
103 109
110/*
111 * RPC call and reply header size as number of 32bit words (verifier
112 * size computed separately, see below)
113 */
114#define RPC_CALLHDRSIZE (6)
115#define RPC_REPHDRSIZE (4)
116
117
118/*
119 * Maximum RPC header size, including authentication,
120 * as number of 32bit words (see RFCs 1831, 1832).
121 *
122 * xid 1 xdr unit = 4 bytes
123 * mtype 1
124 * rpc_version 1
125 * program 1
126 * prog_version 1
127 * procedure 1
128 * cred {
129 * flavor 1
130 * length 1
131 * body<RPC_MAX_AUTH_SIZE> 100 xdr units = 400 bytes
132 * }
133 * verf {
134 * flavor 1
135 * length 1
136 * body<RPC_MAX_AUTH_SIZE> 100 xdr units = 400 bytes
137 * }
138 * TOTAL 210 xdr units = 840 bytes
139 */
140#define RPC_MAX_HEADER_WITH_AUTH \
141 (RPC_CALLHDRSIZE + 2*(2+RPC_MAX_AUTH_SIZE/4))
142
143
104#endif /* __KERNEL__ */ 144#endif /* __KERNEL__ */
105#endif /* _LINUX_SUNRPC_MSGPROT_H_ */ 145#endif /* _LINUX_SUNRPC_MSGPROT_H_ */
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index cb0ed9beb227..74e52c245da4 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -13,6 +13,7 @@
13#include <linux/in.h> 13#include <linux/in.h>
14#include <linux/sunrpc/types.h> 14#include <linux/sunrpc/types.h>
15#include <linux/sunrpc/xdr.h> 15#include <linux/sunrpc/xdr.h>
16#include <linux/sunrpc/auth.h>
16#include <linux/sunrpc/svcauth.h> 17#include <linux/sunrpc/svcauth.h>
17#include <linux/wait.h> 18#include <linux/wait.h>
18#include <linux/mm.h> 19#include <linux/mm.h>
@@ -95,8 +96,28 @@ static inline void svc_get(struct svc_serv *serv)
95 * Maximum payload size supported by a kernel RPC server. 96 * Maximum payload size supported by a kernel RPC server.
96 * This is use to determine the max number of pages nfsd is 97 * This is use to determine the max number of pages nfsd is
97 * willing to return in a single READ operation. 98 * willing to return in a single READ operation.
99 *
100 * These happen to all be powers of 2, which is not strictly
101 * necessary but helps enforce the real limitation, which is
102 * that they should be multiples of PAGE_CACHE_SIZE.
103 *
104 * For UDP transports, a block plus NFS,RPC, and UDP headers
105 * has to fit into the IP datagram limit of 64K. The largest
106 * feasible number for all known page sizes is probably 48K,
107 * but we choose 32K here. This is the same as the historical
108 * Linux limit; someone who cares more about NFS/UDP performance
109 * can test a larger number.
110 *
111 * For TCP transports we have more freedom. A size of 1MB is
112 * chosen to match the client limit. Other OSes are known to
113 * have larger limits, but those numbers are probably beyond
114 * the point of diminishing returns.
98 */ 115 */
99#define RPCSVC_MAXPAYLOAD (64*1024u) 116#define RPCSVC_MAXPAYLOAD (1*1024*1024u)
117#define RPCSVC_MAXPAYLOAD_TCP RPCSVC_MAXPAYLOAD
118#define RPCSVC_MAXPAYLOAD_UDP (32*1024u)
119
120extern u32 svc_max_payload(const struct svc_rqst *rqstp);
100 121
101/* 122/*
102 * RPC Requsts and replies are stored in one or more pages. 123 * RPC Requsts and replies are stored in one or more pages.
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 6cf626580752..60394fbc4c70 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -15,6 +15,7 @@
15#include <linux/kref.h> 15#include <linux/kref.h>
16#include <linux/sunrpc/sched.h> 16#include <linux/sunrpc/sched.h>
17#include <linux/sunrpc/xdr.h> 17#include <linux/sunrpc/xdr.h>
18#include <linux/sunrpc/msg_prot.h>
18 19
19extern unsigned int xprt_udp_slot_table_entries; 20extern unsigned int xprt_udp_slot_table_entries;
20extern unsigned int xprt_tcp_slot_table_entries; 21extern unsigned int xprt_tcp_slot_table_entries;
@@ -24,13 +25,6 @@ extern unsigned int xprt_tcp_slot_table_entries;
24#define RPC_MAX_SLOT_TABLE (128U) 25#define RPC_MAX_SLOT_TABLE (128U)
25 26
26/* 27/*
27 * RPC call and reply header size as number of 32bit words (verifier
28 * size computed separately)
29 */
30#define RPC_CALLHDRSIZE 6
31#define RPC_REPHDRSIZE 4
32
33/*
34 * Parameters for choosing a free port 28 * Parameters for choosing a free port
35 */ 29 */
36extern unsigned int xprt_min_resvport; 30extern unsigned int xprt_min_resvport;
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index f4a509a925b5..b252401c8601 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -919,3 +919,18 @@ err_bad:
919 svc_putnl(resv, ntohl(rpc_stat)); 919 svc_putnl(resv, ntohl(rpc_stat));
920 goto sendit; 920 goto sendit;
921} 921}
922
923/*
924 * Return (transport-specific) limit on the rpc payload.
925 */
926u32 svc_max_payload(const struct svc_rqst *rqstp)
927{
928 int max = RPCSVC_MAXPAYLOAD_TCP;
929
930 if (rqstp->rq_sock->sk_sock->type == SOCK_DGRAM)
931 max = RPCSVC_MAXPAYLOAD_UDP;
932 if (rqstp->rq_server->sv_bufsz < max)
933 max = rqstp->rq_server->sv_bufsz;
934 return max;
935}
936EXPORT_SYMBOL_GPL(svc_max_payload);