Commit 8daf220a authored by Benny Halevy's avatar Benny Halevy Committed by J. Bruce Fields

nfsd41: control nfsv4.1 svc via /proc/fs/nfsd/versions

Support enabling and disabling nfsv4.1 via /proc/fs/nfsd/versions
by writing the strings "+4.1" or "-4.1" correspondingly.

Use user mode nfs-utils (rpc.nfsd option) to enable.
This will allow us to get rid of CONFIG_NFSD_V4_1

[nfsd41: disable support for minorversion by default]
Signed-off-by: default avatarBenny Halevy <bhalevy@panasas.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
parent 84459a11
...@@ -921,7 +921,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, ...@@ -921,7 +921,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
* According to RFC3010, this takes precedence over all other errors. * According to RFC3010, this takes precedence over all other errors.
*/ */
status = nfserr_minor_vers_mismatch; status = nfserr_minor_vers_mismatch;
if (args->minorversion > NFSD_SUPPORTED_MINOR_VERSION) if (args->minorversion > nfsd_supported_minorversion)
goto out; goto out;
if (!nfs41_op_ordering_ok(args)) { if (!nfs41_op_ordering_ok(args)) {
......
...@@ -792,8 +792,9 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size) ...@@ -792,8 +792,9 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
static ssize_t __write_versions(struct file *file, char *buf, size_t size) static ssize_t __write_versions(struct file *file, char *buf, size_t size)
{ {
char *mesg = buf; char *mesg = buf;
char *vers, sign; char *vers, *minorp, sign;
int len, num; int len, num;
unsigned minor;
ssize_t tlen = 0; ssize_t tlen = 0;
char *sep; char *sep;
...@@ -814,9 +815,20 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size) ...@@ -814,9 +815,20 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
do { do {
sign = *vers; sign = *vers;
if (sign == '+' || sign == '-') if (sign == '+' || sign == '-')
num = simple_strtol((vers+1), NULL, 0); num = simple_strtol((vers+1), &minorp, 0);
else else
num = simple_strtol(vers, NULL, 0); num = simple_strtol(vers, &minorp, 0);
if (*minorp == '.') {
if (num < 4)
return -EINVAL;
minor = simple_strtoul(minorp+1, NULL, 0);
if (minor == 0)
return -EINVAL;
if (nfsd_minorversion(minor, sign == '-' ?
NFSD_CLEAR : NFSD_SET) < 0)
return -EINVAL;
goto next;
}
switch(num) { switch(num) {
case 2: case 2:
case 3: case 3:
...@@ -826,6 +838,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size) ...@@ -826,6 +838,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
default: default:
return -EINVAL; return -EINVAL;
} }
next:
vers += len + 1; vers += len + 1;
tlen += len; tlen += len;
} while ((len = qword_get(&mesg, vers, size)) > 0); } while ((len = qword_get(&mesg, vers, size)) > 0);
...@@ -844,6 +857,13 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size) ...@@ -844,6 +857,13 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
num); num);
sep = " "; sep = " ";
} }
if (nfsd_vers(4, NFSD_AVAIL))
for (minor = 1; minor <= NFSD_SUPPORTED_MINOR_VERSION; minor++)
len += sprintf(buf+len, " %c4.%u",
(nfsd_vers(4, NFSD_TEST) &&
nfsd_minorversion(minor, NFSD_TEST)) ?
'+' : '-',
minor);
len += sprintf(buf+len, "\n"); len += sprintf(buf+len, "\n");
return len; return len;
} }
......
...@@ -121,6 +121,8 @@ struct svc_program nfsd_program = { ...@@ -121,6 +121,8 @@ struct svc_program nfsd_program = {
}; };
u32 nfsd_supported_minorversion;
int nfsd_vers(int vers, enum vers_op change) int nfsd_vers(int vers, enum vers_op change)
{ {
if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS) if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS)
...@@ -147,6 +149,28 @@ int nfsd_vers(int vers, enum vers_op change) ...@@ -147,6 +149,28 @@ int nfsd_vers(int vers, enum vers_op change)
} }
return 0; return 0;
} }
int nfsd_minorversion(u32 minorversion, enum vers_op change)
{
if (minorversion > NFSD_SUPPORTED_MINOR_VERSION)
return -1;
switch(change) {
case NFSD_SET:
nfsd_supported_minorversion = minorversion;
break;
case NFSD_CLEAR:
if (minorversion == 0)
return -1;
nfsd_supported_minorversion = minorversion - 1;
break;
case NFSD_TEST:
return minorversion <= nfsd_supported_minorversion;
case NFSD_AVAIL:
return minorversion <= NFSD_SUPPORTED_MINOR_VERSION;
}
return 0;
}
/* /*
* Maximum number of nfsd processes * Maximum number of nfsd processes
*/ */
......
...@@ -53,6 +53,7 @@ typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int); ...@@ -53,6 +53,7 @@ typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int);
extern struct svc_program nfsd_program; extern struct svc_program nfsd_program;
extern struct svc_version nfsd_version2, nfsd_version3, extern struct svc_version nfsd_version2, nfsd_version3,
nfsd_version4; nfsd_version4;
extern u32 nfsd_supported_minorversion;
extern struct mutex nfsd_mutex; extern struct mutex nfsd_mutex;
extern struct svc_serv *nfsd_serv; extern struct svc_serv *nfsd_serv;
...@@ -149,6 +150,7 @@ int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *); ...@@ -149,6 +150,7 @@ int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL }; enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL };
int nfsd_vers(int vers, enum vers_op change); int nfsd_vers(int vers, enum vers_op change);
int nfsd_minorversion(u32 minorversion, enum vers_op change);
void nfsd_reset_versions(void); void nfsd_reset_versions(void);
int nfsd_create_serv(void); int nfsd_create_serv(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment