aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfsctl.c
diff options
context:
space:
mode:
authorGreg Banks <gnb@melbourne.sgi.com>2006-10-02 05:18:02 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-02 10:57:20 -0400
commiteed2965af1bae30f746e936d80ad4fabb9e208c8 (patch)
treebcb8d2f435f612f6b0d3cc6eac8b39e8dd22f45b /fs/nfsd/nfsctl.c
parentbfd241600a3b0db4fe43c859f1460d0a958d924a (diff)
[PATCH] knfsd: allow admin to set nthreads per node
Add /proc/fs/nfsd/pool_threads which allows the sysadmin (or a userspace daemon) to read and change the number of nfsd threads in each pool. The format is a list of space-separated integers, one per pool. 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>
Diffstat (limited to 'fs/nfsd/nfsctl.c')
-rw-r--r--fs/nfsd/nfsctl.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 36e8e135d5a6..5c6a477c20ec 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -54,6 +54,7 @@ enum {
54 NFSD_List, 54 NFSD_List,
55 NFSD_Fh, 55 NFSD_Fh,
56 NFSD_Threads, 56 NFSD_Threads,
57 NFSD_Pool_Threads,
57 NFSD_Versions, 58 NFSD_Versions,
58 NFSD_Ports, 59 NFSD_Ports,
59 /* 60 /*
@@ -78,6 +79,7 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size);
78static ssize_t write_getfs(struct file *file, char *buf, size_t size); 79static ssize_t write_getfs(struct file *file, char *buf, size_t size);
79static ssize_t write_filehandle(struct file *file, char *buf, size_t size); 80static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
80static ssize_t write_threads(struct file *file, char *buf, size_t size); 81static ssize_t write_threads(struct file *file, char *buf, size_t size);
82static ssize_t write_pool_threads(struct file *file, char *buf, size_t size);
81static ssize_t write_versions(struct file *file, char *buf, size_t size); 83static ssize_t write_versions(struct file *file, char *buf, size_t size);
82static ssize_t write_ports(struct file *file, char *buf, size_t size); 84static ssize_t write_ports(struct file *file, char *buf, size_t size);
83#ifdef CONFIG_NFSD_V4 85#ifdef CONFIG_NFSD_V4
@@ -95,6 +97,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
95 [NFSD_Getfs] = write_getfs, 97 [NFSD_Getfs] = write_getfs,
96 [NFSD_Fh] = write_filehandle, 98 [NFSD_Fh] = write_filehandle,
97 [NFSD_Threads] = write_threads, 99 [NFSD_Threads] = write_threads,
100 [NFSD_Pool_Threads] = write_pool_threads,
98 [NFSD_Versions] = write_versions, 101 [NFSD_Versions] = write_versions,
99 [NFSD_Ports] = write_ports, 102 [NFSD_Ports] = write_ports,
100#ifdef CONFIG_NFSD_V4 103#ifdef CONFIG_NFSD_V4
@@ -363,6 +366,72 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
363 return strlen(buf); 366 return strlen(buf);
364} 367}
365 368
369extern int nfsd_nrpools(void);
370extern int nfsd_get_nrthreads(int n, int *);
371extern int nfsd_set_nrthreads(int n, int *);
372
373static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
374{
375 /* if size > 0, look for an array of number of threads per node
376 * and apply them then write out number of threads per node as reply
377 */
378 char *mesg = buf;
379 int i;
380 int rv;
381 int len;
382 int npools = nfsd_nrpools();
383 int *nthreads;
384
385 if (npools == 0) {
386 /*
387 * NFS is shut down. The admin can start it by
388 * writing to the threads file but NOT the pool_threads
389 * file, sorry. Report zero threads.
390 */
391 strcpy(buf, "0\n");
392 return strlen(buf);
393 }
394
395 nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL);
396 if (nthreads == NULL)
397 return -ENOMEM;
398
399 if (size > 0) {
400 for (i = 0; i < npools; i++) {
401 rv = get_int(&mesg, &nthreads[i]);
402 if (rv == -ENOENT)
403 break; /* fewer numbers than pools */
404 if (rv)
405 goto out_free; /* syntax error */
406 rv = -EINVAL;
407 if (nthreads[i] < 0)
408 goto out_free;
409 }
410 rv = nfsd_set_nrthreads(i, nthreads);
411 if (rv)
412 goto out_free;
413 }
414
415 rv = nfsd_get_nrthreads(npools, nthreads);
416 if (rv)
417 goto out_free;
418
419 mesg = buf;
420 size = SIMPLE_TRANSACTION_LIMIT;
421 for (i = 0; i < npools && size > 0; i++) {
422 snprintf(mesg, size, "%d%c", nthreads[i], (i == npools-1 ? '\n' : ' '));
423 len = strlen(mesg);
424 size -= len;
425 mesg += len;
426 }
427
428 return (mesg-buf);
429
430out_free:
431 kfree(nthreads);
432 return rv;
433}
434
366static ssize_t write_versions(struct file *file, char *buf, size_t size) 435static ssize_t write_versions(struct file *file, char *buf, size_t size)
367{ 436{
368 /* 437 /*
@@ -544,6 +613,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
544 [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, 613 [NFSD_List] = {"exports", &exports_operations, S_IRUGO},
545 [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR}, 614 [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
546 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, 615 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
616 [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},
547 [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, 617 [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
548 [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, 618 [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
549#ifdef CONFIG_NFSD_V4 619#ifdef CONFIG_NFSD_V4