diff options
Diffstat (limited to 'fs/nfsd/nfsctl.c')
-rw-r--r-- | fs/nfsd/nfsctl.c | 70 |
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); | |||
78 | static ssize_t write_getfs(struct file *file, char *buf, size_t size); | 79 | static ssize_t write_getfs(struct file *file, char *buf, size_t size); |
79 | static ssize_t write_filehandle(struct file *file, char *buf, size_t size); | 80 | static ssize_t write_filehandle(struct file *file, char *buf, size_t size); |
80 | static ssize_t write_threads(struct file *file, char *buf, size_t size); | 81 | 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); | ||
81 | static ssize_t write_versions(struct file *file, char *buf, size_t size); | 83 | static ssize_t write_versions(struct file *file, char *buf, size_t size); |
82 | static ssize_t write_ports(struct file *file, char *buf, size_t size); | 84 | static 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 | ||
369 | extern int nfsd_nrpools(void); | ||
370 | extern int nfsd_get_nrthreads(int n, int *); | ||
371 | extern int nfsd_set_nrthreads(int n, int *); | ||
372 | |||
373 | static 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 | |||
430 | out_free: | ||
431 | kfree(nthreads); | ||
432 | return rv; | ||
433 | } | ||
434 | |||
366 | static ssize_t write_versions(struct file *file, char *buf, size_t size) | 435 | static 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 |