aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4proc.c2
-rw-r--r--fs/nfsd/nfsctl.c26
-rw-r--r--fs/nfsd/nfssvc.c24
-rw-r--r--include/linux/nfsd/nfsd.h2
4 files changed, 50 insertions, 4 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index db208dd8fdca..52bb14debb30 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -921,7 +921,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
921 * According to RFC3010, this takes precedence over all other errors. 921 * According to RFC3010, this takes precedence over all other errors.
922 */ 922 */
923 status = nfserr_minor_vers_mismatch; 923 status = nfserr_minor_vers_mismatch;
924 if (args->minorversion > NFSD_SUPPORTED_MINOR_VERSION) 924 if (args->minorversion > nfsd_supported_minorversion)
925 goto out; 925 goto out;
926 926
927 if (!nfs41_op_ordering_ok(args)) { 927 if (!nfs41_op_ordering_ok(args)) {
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 4adebb6312c4..a9b8c75bf0bf 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -792,8 +792,9 @@ out_free:
792static ssize_t __write_versions(struct file *file, char *buf, size_t size) 792static ssize_t __write_versions(struct file *file, char *buf, size_t size)
793{ 793{
794 char *mesg = buf; 794 char *mesg = buf;
795 char *vers, sign; 795 char *vers, *minorp, sign;
796 int len, num; 796 int len, num;
797 unsigned minor;
797 ssize_t tlen = 0; 798 ssize_t tlen = 0;
798 char *sep; 799 char *sep;
799 800
@@ -814,9 +815,20 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
814 do { 815 do {
815 sign = *vers; 816 sign = *vers;
816 if (sign == '+' || sign == '-') 817 if (sign == '+' || sign == '-')
817 num = simple_strtol((vers+1), NULL, 0); 818 num = simple_strtol((vers+1), &minorp, 0);
818 else 819 else
819 num = simple_strtol(vers, NULL, 0); 820 num = simple_strtol(vers, &minorp, 0);
821 if (*minorp == '.') {
822 if (num < 4)
823 return -EINVAL;
824 minor = simple_strtoul(minorp+1, NULL, 0);
825 if (minor == 0)
826 return -EINVAL;
827 if (nfsd_minorversion(minor, sign == '-' ?
828 NFSD_CLEAR : NFSD_SET) < 0)
829 return -EINVAL;
830 goto next;
831 }
820 switch(num) { 832 switch(num) {
821 case 2: 833 case 2:
822 case 3: 834 case 3:
@@ -826,6 +838,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
826 default: 838 default:
827 return -EINVAL; 839 return -EINVAL;
828 } 840 }
841 next:
829 vers += len + 1; 842 vers += len + 1;
830 tlen += len; 843 tlen += len;
831 } while ((len = qword_get(&mesg, vers, size)) > 0); 844 } 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 num); 857 num);
845 sep = " "; 858 sep = " ";
846 } 859 }
860 if (nfsd_vers(4, NFSD_AVAIL))
861 for (minor = 1; minor <= NFSD_SUPPORTED_MINOR_VERSION; minor++)
862 len += sprintf(buf+len, " %c4.%u",
863 (nfsd_vers(4, NFSD_TEST) &&
864 nfsd_minorversion(minor, NFSD_TEST)) ?
865 '+' : '-',
866 minor);
847 len += sprintf(buf+len, "\n"); 867 len += sprintf(buf+len, "\n");
848 return len; 868 return len;
849} 869}
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index b53a098e97a4..e9d57734a348 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -121,6 +121,8 @@ struct svc_program nfsd_program = {
121 121
122}; 122};
123 123
124u32 nfsd_supported_minorversion;
125
124int nfsd_vers(int vers, enum vers_op change) 126int nfsd_vers(int vers, enum vers_op change)
125{ 127{
126 if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS) 128 if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS)
@@ -147,6 +149,28 @@ int nfsd_vers(int vers, enum vers_op change)
147 } 149 }
148 return 0; 150 return 0;
149} 151}
152
153int nfsd_minorversion(u32 minorversion, enum vers_op change)
154{
155 if (minorversion > NFSD_SUPPORTED_MINOR_VERSION)
156 return -1;
157 switch(change) {
158 case NFSD_SET:
159 nfsd_supported_minorversion = minorversion;
160 break;
161 case NFSD_CLEAR:
162 if (minorversion == 0)
163 return -1;
164 nfsd_supported_minorversion = minorversion - 1;
165 break;
166 case NFSD_TEST:
167 return minorversion <= nfsd_supported_minorversion;
168 case NFSD_AVAIL:
169 return minorversion <= NFSD_SUPPORTED_MINOR_VERSION;
170 }
171 return 0;
172}
173
150/* 174/*
151 * Maximum number of nfsd processes 175 * Maximum number of nfsd processes
152 */ 176 */
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 1f063d495159..70339b7b83c0 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -53,6 +53,7 @@ typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int);
53extern struct svc_program nfsd_program; 53extern struct svc_program nfsd_program;
54extern struct svc_version nfsd_version2, nfsd_version3, 54extern struct svc_version nfsd_version2, nfsd_version3,
55 nfsd_version4; 55 nfsd_version4;
56extern u32 nfsd_supported_minorversion;
56extern struct mutex nfsd_mutex; 57extern struct mutex nfsd_mutex;
57extern struct svc_serv *nfsd_serv; 58extern struct svc_serv *nfsd_serv;
58 59
@@ -149,6 +150,7 @@ int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
149 150
150enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL }; 151enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL };
151int nfsd_vers(int vers, enum vers_op change); 152int nfsd_vers(int vers, enum vers_op change);
153int nfsd_minorversion(u32 minorversion, enum vers_op change);
152void nfsd_reset_versions(void); 154void nfsd_reset_versions(void);
153int nfsd_create_serv(void); 155int nfsd_create_serv(void);
154 156