aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfsctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfsctl.c')
-rw-r--r--fs/nfsd/nfsctl.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 2a99a0bf54f6..a0871b3efeb7 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -23,6 +23,7 @@
23#include <linux/seq_file.h> 23#include <linux/seq_file.h>
24#include <linux/pagemap.h> 24#include <linux/pagemap.h>
25#include <linux/init.h> 25#include <linux/init.h>
26#include <linux/string.h>
26 27
27#include <linux/nfs.h> 28#include <linux/nfs.h>
28#include <linux/nfsd_idmap.h> 29#include <linux/nfsd_idmap.h>
@@ -35,6 +36,8 @@
35 36
36#include <asm/uaccess.h> 37#include <asm/uaccess.h>
37 38
39unsigned int nfsd_versbits = ~0;
40
38/* 41/*
39 * We have a single directory with 9 nodes in it. 42 * We have a single directory with 9 nodes in it.
40 */ 43 */
@@ -50,8 +53,15 @@ enum {
50 NFSD_List, 53 NFSD_List,
51 NFSD_Fh, 54 NFSD_Fh,
52 NFSD_Threads, 55 NFSD_Threads,
56 NFSD_Versions,
57 /*
58 * The below MUST come last. Otherwise we leave a hole in nfsd_files[]
59 * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops
60 */
61#ifdef CONFIG_NFSD_V4
53 NFSD_Leasetime, 62 NFSD_Leasetime,
54 NFSD_RecoveryDir, 63 NFSD_RecoveryDir,
64#endif
55}; 65};
56 66
57/* 67/*
@@ -66,8 +76,11 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size);
66static ssize_t write_getfs(struct file *file, char *buf, size_t size); 76static ssize_t write_getfs(struct file *file, char *buf, size_t size);
67static ssize_t write_filehandle(struct file *file, char *buf, size_t size); 77static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
68static ssize_t write_threads(struct file *file, char *buf, size_t size); 78static ssize_t write_threads(struct file *file, char *buf, size_t size);
79static ssize_t write_versions(struct file *file, char *buf, size_t size);
80#ifdef CONFIG_NFSD_V4
69static ssize_t write_leasetime(struct file *file, char *buf, size_t size); 81static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
70static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); 82static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
83#endif
71 84
72static ssize_t (*write_op[])(struct file *, char *, size_t) = { 85static ssize_t (*write_op[])(struct file *, char *, size_t) = {
73 [NFSD_Svc] = write_svc, 86 [NFSD_Svc] = write_svc,
@@ -79,8 +92,11 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
79 [NFSD_Getfs] = write_getfs, 92 [NFSD_Getfs] = write_getfs,
80 [NFSD_Fh] = write_filehandle, 93 [NFSD_Fh] = write_filehandle,
81 [NFSD_Threads] = write_threads, 94 [NFSD_Threads] = write_threads,
95 [NFSD_Versions] = write_versions,
96#ifdef CONFIG_NFSD_V4
82 [NFSD_Leasetime] = write_leasetime, 97 [NFSD_Leasetime] = write_leasetime,
83 [NFSD_RecoveryDir] = write_recoverydir, 98 [NFSD_RecoveryDir] = write_recoverydir,
99#endif
84}; 100};
85 101
86static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) 102static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
@@ -343,6 +359,70 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
343 return strlen(buf); 359 return strlen(buf);
344} 360}
345 361
362static ssize_t write_versions(struct file *file, char *buf, size_t size)
363{
364 /*
365 * Format:
366 * [-/+]vers [-/+]vers ...
367 */
368 char *mesg = buf;
369 char *vers, sign;
370 int len, num;
371 ssize_t tlen = 0;
372 char *sep;
373
374 if (size>0) {
375 if (nfsd_serv)
376 return -EBUSY;
377 if (buf[size-1] != '\n')
378 return -EINVAL;
379 buf[size-1] = 0;
380
381 vers = mesg;
382 len = qword_get(&mesg, vers, size);
383 if (len <= 0) return -EINVAL;
384 do {
385 sign = *vers;
386 if (sign == '+' || sign == '-')
387 num = simple_strtol((vers+1), NULL, 0);
388 else
389 num = simple_strtol(vers, NULL, 0);
390 switch(num) {
391 case 2:
392 case 3:
393 case 4:
394 if (sign != '-')
395 NFSCTL_VERSET(nfsd_versbits, num);
396 else
397 NFSCTL_VERUNSET(nfsd_versbits, num);
398 break;
399 default:
400 return -EINVAL;
401 }
402 vers += len + 1;
403 tlen += len;
404 } while ((len = qword_get(&mesg, vers, size)) > 0);
405 /* If all get turned off, turn them back on, as
406 * having no versions is BAD
407 */
408 if ((nfsd_versbits & NFSCTL_VERALL)==0)
409 nfsd_versbits = NFSCTL_VERALL;
410 }
411 /* Now write current state into reply buffer */
412 len = 0;
413 sep = "";
414 for (num=2 ; num <= 4 ; num++)
415 if (NFSCTL_VERISSET(NFSCTL_VERALL, num)) {
416 len += sprintf(buf+len, "%s%c%d", sep,
417 NFSCTL_VERISSET(nfsd_versbits, num)?'+':'-',
418 num);
419 sep = " ";
420 }
421 len += sprintf(buf+len, "\n");
422 return len;
423}
424
425#ifdef CONFIG_NFSD_V4
346extern time_t nfs4_leasetime(void); 426extern time_t nfs4_leasetime(void);
347 427
348static ssize_t write_leasetime(struct file *file, char *buf, size_t size) 428static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
@@ -384,6 +464,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
384 status = nfs4_reset_recoverydir(recdir); 464 status = nfs4_reset_recoverydir(recdir);
385 return strlen(buf); 465 return strlen(buf);
386} 466}
467#endif
387 468
388/*----------------------------------------------------------------------------*/ 469/*----------------------------------------------------------------------------*/
389/* 470/*
@@ -403,6 +484,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
403 [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, 484 [NFSD_List] = {"exports", &exports_operations, S_IRUGO},
404 [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR}, 485 [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
405 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, 486 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
487 [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
406#ifdef CONFIG_NFSD_V4 488#ifdef CONFIG_NFSD_V4
407 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, 489 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
408 [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR}, 490 [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},