diff options
-rw-r--r-- | fs/nfsd/nfsctl.c | 33 | ||||
-rw-r--r-- | fs/nfsd/nfssvc.c | 19 | ||||
-rw-r--r-- | include/linux/nfsd/const.h | 4 | ||||
-rw-r--r-- | include/linux/nfsd/nfsd.h | 1 |
4 files changed, 54 insertions, 3 deletions
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 6c2ddfed2cfc..39aed901514b 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
@@ -57,6 +57,7 @@ enum { | |||
57 | NFSD_Pool_Threads, | 57 | NFSD_Pool_Threads, |
58 | NFSD_Versions, | 58 | NFSD_Versions, |
59 | NFSD_Ports, | 59 | NFSD_Ports, |
60 | NFSD_MaxBlkSize, | ||
60 | /* | 61 | /* |
61 | * The below MUST come last. Otherwise we leave a hole in nfsd_files[] | 62 | * The below MUST come last. Otherwise we leave a hole in nfsd_files[] |
62 | * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops | 63 | * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops |
@@ -82,6 +83,7 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size); | |||
82 | static ssize_t write_pool_threads(struct file *file, char *buf, size_t size); | 83 | static ssize_t write_pool_threads(struct file *file, char *buf, size_t size); |
83 | static ssize_t write_versions(struct file *file, char *buf, size_t size); | 84 | static ssize_t write_versions(struct file *file, char *buf, size_t size); |
84 | static ssize_t write_ports(struct file *file, char *buf, size_t size); | 85 | static ssize_t write_ports(struct file *file, char *buf, size_t size); |
86 | static ssize_t write_maxblksize(struct file *file, char *buf, size_t size); | ||
85 | #ifdef CONFIG_NFSD_V4 | 87 | #ifdef CONFIG_NFSD_V4 |
86 | static ssize_t write_leasetime(struct file *file, char *buf, size_t size); | 88 | static ssize_t write_leasetime(struct file *file, char *buf, size_t size); |
87 | static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); | 89 | static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); |
@@ -100,6 +102,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = { | |||
100 | [NFSD_Pool_Threads] = write_pool_threads, | 102 | [NFSD_Pool_Threads] = write_pool_threads, |
101 | [NFSD_Versions] = write_versions, | 103 | [NFSD_Versions] = write_versions, |
102 | [NFSD_Ports] = write_ports, | 104 | [NFSD_Ports] = write_ports, |
105 | [NFSD_MaxBlkSize] = write_maxblksize, | ||
103 | #ifdef CONFIG_NFSD_V4 | 106 | #ifdef CONFIG_NFSD_V4 |
104 | [NFSD_Leasetime] = write_leasetime, | 107 | [NFSD_Leasetime] = write_leasetime, |
105 | [NFSD_RecoveryDir] = write_recoverydir, | 108 | [NFSD_RecoveryDir] = write_recoverydir, |
@@ -555,6 +558,35 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size) | |||
555 | return -EINVAL; | 558 | return -EINVAL; |
556 | } | 559 | } |
557 | 560 | ||
561 | int nfsd_max_blksize; | ||
562 | |||
563 | static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) | ||
564 | { | ||
565 | char *mesg = buf; | ||
566 | if (size > 0) { | ||
567 | int bsize; | ||
568 | int rv = get_int(&mesg, &bsize); | ||
569 | if (rv) | ||
570 | return rv; | ||
571 | /* force bsize into allowed range and | ||
572 | * required alignment. | ||
573 | */ | ||
574 | if (bsize < 1024) | ||
575 | bsize = 1024; | ||
576 | if (bsize > NFSSVC_MAXBLKSIZE) | ||
577 | bsize = NFSSVC_MAXBLKSIZE; | ||
578 | bsize &= ~(1024-1); | ||
579 | lock_kernel(); | ||
580 | if (nfsd_serv && nfsd_serv->sv_nrthreads) { | ||
581 | unlock_kernel(); | ||
582 | return -EBUSY; | ||
583 | } | ||
584 | nfsd_max_blksize = bsize; | ||
585 | unlock_kernel(); | ||
586 | } | ||
587 | return sprintf(buf, "%d\n", nfsd_max_blksize); | ||
588 | } | ||
589 | |||
558 | #ifdef CONFIG_NFSD_V4 | 590 | #ifdef CONFIG_NFSD_V4 |
559 | extern time_t nfs4_leasetime(void); | 591 | extern time_t nfs4_leasetime(void); |
560 | 592 | ||
@@ -620,6 +652,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) | |||
620 | [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR}, | 652 | [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR}, |
621 | [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, | 653 | [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, |
622 | [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, | 654 | [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, |
655 | [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, | ||
623 | #ifdef CONFIG_NFSD_V4 | 656 | #ifdef CONFIG_NFSD_V4 |
624 | [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, | 657 | [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, |
625 | [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR}, | 658 | [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR}, |
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 19443056ec30..0603baad5426 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
@@ -198,9 +198,26 @@ int nfsd_create_serv(void) | |||
198 | unlock_kernel(); | 198 | unlock_kernel(); |
199 | return 0; | 199 | return 0; |
200 | } | 200 | } |
201 | if (nfsd_max_blksize == 0) { | ||
202 | /* choose a suitable default */ | ||
203 | struct sysinfo i; | ||
204 | si_meminfo(&i); | ||
205 | /* Aim for 1/4096 of memory per thread | ||
206 | * This gives 1MB on 4Gig machines | ||
207 | * But only uses 32K on 128M machines. | ||
208 | * Bottom out at 8K on 32M and smaller. | ||
209 | * Of course, this is only a default. | ||
210 | */ | ||
211 | nfsd_max_blksize = NFSSVC_MAXBLKSIZE; | ||
212 | i.totalram >>= 12; | ||
213 | while (nfsd_max_blksize > i.totalram && | ||
214 | nfsd_max_blksize >= 8*1024*2) | ||
215 | nfsd_max_blksize /= 2; | ||
216 | } | ||
201 | 217 | ||
202 | atomic_set(&nfsd_busy, 0); | 218 | atomic_set(&nfsd_busy, 0); |
203 | nfsd_serv = svc_create_pooled(&nfsd_program, NFSD_BUFSIZE, | 219 | nfsd_serv = svc_create_pooled(&nfsd_program, |
220 | NFSD_BUFSIZE - NFSSVC_MAXBLKSIZE + nfsd_max_blksize, | ||
204 | nfsd_last_thread, | 221 | nfsd_last_thread, |
205 | nfsd, SIG_NOCLEAN, THIS_MODULE); | 222 | nfsd, SIG_NOCLEAN, THIS_MODULE); |
206 | if (nfsd_serv == NULL) | 223 | if (nfsd_serv == NULL) |
diff --git a/include/linux/nfsd/const.h b/include/linux/nfsd/const.h index adbddf007898..f478066f9cd5 100644 --- a/include/linux/nfsd/const.h +++ b/include/linux/nfsd/const.h | |||
@@ -21,9 +21,9 @@ | |||
21 | #define NFSSVC_MAXVERS 3 | 21 | #define NFSSVC_MAXVERS 3 |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * Maximum blocksize supported by daemon currently at 32K | 24 | * Maximum blocksizes supported by daemon under various circumstances. |
25 | */ | 25 | */ |
26 | #define NFSSVC_MAXBLKSIZE (32*1024) | 26 | #define NFSSVC_MAXBLKSIZE RPCSVC_MAXPAYLOAD |
27 | /* NFSv2 is limited by the protocol specification, see RFC 1094 */ | 27 | /* NFSv2 is limited by the protocol specification, see RFC 1094 */ |
28 | #define NFSSVC_MAXBLKSIZE_V2 (8*1024) | 28 | #define NFSSVC_MAXBLKSIZE_V2 (8*1024) |
29 | 29 | ||
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index e1dbc86c270b..259841bb2f6c 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h | |||
@@ -145,6 +145,7 @@ int nfsd_vers(int vers, enum vers_op change); | |||
145 | void nfsd_reset_versions(void); | 145 | void nfsd_reset_versions(void); |
146 | int nfsd_create_serv(void); | 146 | int nfsd_create_serv(void); |
147 | 147 | ||
148 | extern int nfsd_max_blksize; | ||
148 | 149 | ||
149 | /* | 150 | /* |
150 | * NFSv4 State | 151 | * NFSv4 State |