summaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorTrond Myklebust <trondmy@gmail.com>2019-04-09 11:46:19 -0400
committerJ. Bruce Fields <bfields@redhat.com>2019-04-24 09:46:35 -0400
commite333f3bbefe3e25e2bcff58063f920a2eaba224b (patch)
treedcc70057be9950c50a87f76c8b31468b4fa1be6f /fs/nfsd
parent029be5d03357f0797d1b9a6b5aab5e7e311fd76a (diff)
nfsd: Allow containers to set supported nfs versions
Support use of the --nfs-version/--no-nfs-version arguments to rpc.nfsd in containers. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/netns.h8
-rw-r--r--fs/nfsd/nfs4proc.c3
-rw-r--r--fs/nfsd/nfsctl.c25
-rw-r--r--fs/nfsd/nfsd.h8
-rw-r--r--fs/nfsd/nfssvc.c214
5 files changed, 197 insertions, 61 deletions
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index b42aaa22fba2..789abc4dd1d2 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -134,10 +134,18 @@ struct nfsd_net {
134 u32 s2s_cp_cl_id; 134 u32 s2s_cp_cl_id;
135 struct idr s2s_cp_stateids; 135 struct idr s2s_cp_stateids;
136 spinlock_t s2s_cp_lock; 136 spinlock_t s2s_cp_lock;
137
138 /*
139 * Version information
140 */
141 bool *nfsd_versions;
142 bool *nfsd4_minorversions;
137}; 143};
138 144
139/* Simple check to find out if a given net was properly initialized */ 145/* Simple check to find out if a given net was properly initialized */
140#define nfsd_netns_ready(nn) ((nn)->sessionid_hashtbl) 146#define nfsd_netns_ready(nn) ((nn)->sessionid_hashtbl)
141 147
148extern void nfsd_netns_free_versions(struct nfsd_net *nn);
149
142extern unsigned int nfsd_net_id; 150extern unsigned int nfsd_net_id;
143#endif /* __NFSD_NETNS_H__ */ 151#endif /* __NFSD_NETNS_H__ */
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 0cfd257ffdaf..b0ad72d701b1 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1926,6 +1926,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
1926 struct nfsd4_compound_state *cstate = &resp->cstate; 1926 struct nfsd4_compound_state *cstate = &resp->cstate;
1927 struct svc_fh *current_fh = &cstate->current_fh; 1927 struct svc_fh *current_fh = &cstate->current_fh;
1928 struct svc_fh *save_fh = &cstate->save_fh; 1928 struct svc_fh *save_fh = &cstate->save_fh;
1929 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
1929 __be32 status; 1930 __be32 status;
1930 1931
1931 svcxdr_init_encode(rqstp, resp); 1932 svcxdr_init_encode(rqstp, resp);
@@ -1948,7 +1949,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
1948 * According to RFC3010, this takes precedence over all other errors. 1949 * According to RFC3010, this takes precedence over all other errors.
1949 */ 1950 */
1950 status = nfserr_minor_vers_mismatch; 1951 status = nfserr_minor_vers_mismatch;
1951 if (nfsd_minorversion(args->minorversion, NFSD_TEST) <= 0) 1952 if (nfsd_minorversion(nn, args->minorversion, NFSD_TEST) <= 0)
1952 goto out; 1953 goto out;
1953 status = nfserr_resource; 1954 status = nfserr_resource;
1954 if (args->opcnt > NFSD_MAX_OPS_PER_COMPOUND) 1955 if (args->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 6667d3a4f839..630d629090be 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -537,14 +537,14 @@ out_free:
537} 537}
538 538
539static ssize_t 539static ssize_t
540nfsd_print_version_support(char *buf, int remaining, const char *sep, 540nfsd_print_version_support(struct nfsd_net *nn, char *buf, int remaining,
541 unsigned vers, int minor) 541 const char *sep, unsigned vers, int minor)
542{ 542{
543 const char *format = minor < 0 ? "%s%c%u" : "%s%c%u.%u"; 543 const char *format = minor < 0 ? "%s%c%u" : "%s%c%u.%u";
544 bool supported = !!nfsd_vers(vers, NFSD_TEST); 544 bool supported = !!nfsd_vers(nn, vers, NFSD_TEST);
545 545
546 if (vers == 4 && minor >= 0 && 546 if (vers == 4 && minor >= 0 &&
547 !nfsd_minorversion(minor, NFSD_TEST)) 547 !nfsd_minorversion(nn, minor, NFSD_TEST))
548 supported = false; 548 supported = false;
549 if (minor == 0 && supported) 549 if (minor == 0 && supported)
550 /* 550 /*
@@ -599,20 +599,20 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
599 switch(num) { 599 switch(num) {
600 case 2: 600 case 2:
601 case 3: 601 case 3:
602 nfsd_vers(num, cmd); 602 nfsd_vers(nn, num, cmd);
603 break; 603 break;
604 case 4: 604 case 4:
605 if (*minorp == '.') { 605 if (*minorp == '.') {
606 if (nfsd_minorversion(minor, cmd) < 0) 606 if (nfsd_minorversion(nn, minor, cmd) < 0)
607 return -EINVAL; 607 return -EINVAL;
608 } else if ((cmd == NFSD_SET) != nfsd_vers(num, NFSD_TEST)) { 608 } else if ((cmd == NFSD_SET) != nfsd_vers(nn, num, NFSD_TEST)) {
609 /* 609 /*
610 * Either we have +4 and no minors are enabled, 610 * Either we have +4 and no minors are enabled,
611 * or we have -4 and at least one minor is enabled. 611 * or we have -4 and at least one minor is enabled.
612 * In either case, propagate 'cmd' to all minors. 612 * In either case, propagate 'cmd' to all minors.
613 */ 613 */
614 minor = 0; 614 minor = 0;
615 while (nfsd_minorversion(minor, cmd) >= 0) 615 while (nfsd_minorversion(nn, minor, cmd) >= 0)
616 minor++; 616 minor++;
617 } 617 }
618 break; 618 break;
@@ -624,7 +624,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
624 /* If all get turned off, turn them back on, as 624 /* If all get turned off, turn them back on, as
625 * having no versions is BAD 625 * having no versions is BAD
626 */ 626 */
627 nfsd_reset_versions(); 627 nfsd_reset_versions(nn);
628 } 628 }
629 629
630 /* Now write current state into reply buffer */ 630 /* Now write current state into reply buffer */
@@ -633,12 +633,12 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
633 remaining = SIMPLE_TRANSACTION_LIMIT; 633 remaining = SIMPLE_TRANSACTION_LIMIT;
634 for (num=2 ; num <= 4 ; num++) { 634 for (num=2 ; num <= 4 ; num++) {
635 int minor; 635 int minor;
636 if (!nfsd_vers(num, NFSD_AVAIL)) 636 if (!nfsd_vers(nn, num, NFSD_AVAIL))
637 continue; 637 continue;
638 638
639 minor = -1; 639 minor = -1;
640 do { 640 do {
641 len = nfsd_print_version_support(buf, remaining, 641 len = nfsd_print_version_support(nn, buf, remaining,
642 sep, num, minor); 642 sep, num, minor);
643 if (len >= remaining) 643 if (len >= remaining)
644 goto out; 644 goto out;
@@ -1239,6 +1239,8 @@ static __net_init int nfsd_init_net(struct net *net)
1239 retval = nfsd_idmap_init(net); 1239 retval = nfsd_idmap_init(net);
1240 if (retval) 1240 if (retval)
1241 goto out_idmap_error; 1241 goto out_idmap_error;
1242 nn->nfsd_versions = NULL;
1243 nn->nfsd4_minorversions = NULL;
1242 nn->nfsd4_lease = 90; /* default lease time */ 1244 nn->nfsd4_lease = 90; /* default lease time */
1243 nn->nfsd4_grace = 90; 1245 nn->nfsd4_grace = 90;
1244 nn->somebody_reclaimed = false; 1246 nn->somebody_reclaimed = false;
@@ -1261,6 +1263,7 @@ static __net_exit void nfsd_exit_net(struct net *net)
1261{ 1263{
1262 nfsd_idmap_shutdown(net); 1264 nfsd_idmap_shutdown(net);
1263 nfsd_export_shutdown(net); 1265 nfsd_export_shutdown(net);
1266 nfsd_netns_free_versions(net_generic(net, nfsd_net_id));
1264} 1267}
1265 1268
1266static struct pernet_operations nfsd_net_ops = { 1269static struct pernet_operations nfsd_net_ops = {
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 066899929863..6bae2554b2b2 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -98,10 +98,12 @@ extern const struct svc_version nfsd_acl_version3;
98#endif 98#endif
99#endif 99#endif
100 100
101struct nfsd_net;
102
101enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL }; 103enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL };
102int nfsd_vers(int vers, enum vers_op change); 104int nfsd_vers(struct nfsd_net *nn, int vers, enum vers_op change);
103int nfsd_minorversion(u32 minorversion, enum vers_op change); 105int nfsd_minorversion(struct nfsd_net *nn, u32 minorversion, enum vers_op change);
104void nfsd_reset_versions(void); 106void nfsd_reset_versions(struct nfsd_net *nn);
105int nfsd_create_serv(struct net *net); 107int nfsd_create_serv(struct net *net);
106 108
107extern int nfsd_max_blksize; 109extern int nfsd_max_blksize;
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 378edcfe9701..520757774614 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -38,12 +38,18 @@ static int nfsd_acl_rpcbind_set(struct net *,
38 u32, int, 38 u32, int,
39 unsigned short, 39 unsigned short,
40 unsigned short); 40 unsigned short);
41static __be32 nfsd_acl_init_request(struct svc_rqst *,
42 const struct svc_program *,
43 struct svc_process_info *);
41#endif 44#endif
42static int nfsd_rpcbind_set(struct net *, 45static int nfsd_rpcbind_set(struct net *,
43 const struct svc_program *, 46 const struct svc_program *,
44 u32, int, 47 u32, int,
45 unsigned short, 48 unsigned short,
46 unsigned short); 49 unsigned short);
50static __be32 nfsd_init_request(struct svc_rqst *,
51 const struct svc_program *,
52 struct svc_process_info *);
47 53
48/* 54/*
49 * nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and the members 55 * nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and the members
@@ -98,7 +104,7 @@ static struct svc_program nfsd_acl_program = {
98 .pg_class = "nfsd", 104 .pg_class = "nfsd",
99 .pg_stats = &nfsd_acl_svcstats, 105 .pg_stats = &nfsd_acl_svcstats,
100 .pg_authenticate = &svc_set_client, 106 .pg_authenticate = &svc_set_client,
101 .pg_init_request = svc_generic_init_request, 107 .pg_init_request = nfsd_acl_init_request,
102 .pg_rpcbind_set = nfsd_acl_rpcbind_set, 108 .pg_rpcbind_set = nfsd_acl_rpcbind_set,
103}; 109};
104 110
@@ -119,7 +125,6 @@ static const struct svc_version *nfsd_version[] = {
119 125
120#define NFSD_MINVERS 2 126#define NFSD_MINVERS 2
121#define NFSD_NRVERS ARRAY_SIZE(nfsd_version) 127#define NFSD_NRVERS ARRAY_SIZE(nfsd_version)
122static const struct svc_version *nfsd_versions[NFSD_NRVERS];
123 128
124struct svc_program nfsd_program = { 129struct svc_program nfsd_program = {
125#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 130#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
@@ -127,78 +132,136 @@ struct svc_program nfsd_program = {
127#endif 132#endif
128 .pg_prog = NFS_PROGRAM, /* program number */ 133 .pg_prog = NFS_PROGRAM, /* program number */
129 .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */ 134 .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */
130 .pg_vers = nfsd_versions, /* version table */ 135 .pg_vers = nfsd_version, /* version table */
131 .pg_name = "nfsd", /* program name */ 136 .pg_name = "nfsd", /* program name */
132 .pg_class = "nfsd", /* authentication class */ 137 .pg_class = "nfsd", /* authentication class */
133 .pg_stats = &nfsd_svcstats, /* version table */ 138 .pg_stats = &nfsd_svcstats, /* version table */
134 .pg_authenticate = &svc_set_client, /* export authentication */ 139 .pg_authenticate = &svc_set_client, /* export authentication */
135 .pg_init_request = svc_generic_init_request, 140 .pg_init_request = nfsd_init_request,
136 .pg_rpcbind_set = nfsd_rpcbind_set, 141 .pg_rpcbind_set = nfsd_rpcbind_set,
137}; 142};
138 143
139static bool nfsd_supported_minorversions[NFSD_SUPPORTED_MINOR_VERSION + 1] = { 144static bool
140 [0] = 1, 145nfsd_support_version(int vers)
141 [1] = 1, 146{
142 [2] = 1, 147 if (vers >= NFSD_MINVERS && vers < NFSD_NRVERS)
143}; 148 return nfsd_version[vers] != NULL;
149 return false;
150}
151
152static bool *
153nfsd_alloc_versions(void)
154{
155 bool *vers = kmalloc_array(NFSD_NRVERS, sizeof(bool), GFP_KERNEL);
156 unsigned i;
157
158 if (vers) {
159 /* All compiled versions are enabled by default */
160 for (i = 0; i < NFSD_NRVERS; i++)
161 vers[i] = nfsd_support_version(i);
162 }
163 return vers;
164}
165
166static bool *
167nfsd_alloc_minorversions(void)
168{
169 bool *vers = kmalloc_array(NFSD_SUPPORTED_MINOR_VERSION + 1,
170 sizeof(bool), GFP_KERNEL);
171 unsigned i;
144 172
145int nfsd_vers(int vers, enum vers_op change) 173 if (vers) {
174 /* All minor versions are enabled by default */
175 for (i = 0; i <= NFSD_SUPPORTED_MINOR_VERSION; i++)
176 vers[i] = nfsd_support_version(4);
177 }
178 return vers;
179}
180
181void
182nfsd_netns_free_versions(struct nfsd_net *nn)
183{
184 kfree(nn->nfsd_versions);
185 kfree(nn->nfsd4_minorversions);
186 nn->nfsd_versions = NULL;
187 nn->nfsd4_minorversions = NULL;
188}
189
190static void
191nfsd_netns_init_versions(struct nfsd_net *nn)
192{
193 if (!nn->nfsd_versions) {
194 nn->nfsd_versions = nfsd_alloc_versions();
195 nn->nfsd4_minorversions = nfsd_alloc_minorversions();
196 if (!nn->nfsd_versions || !nn->nfsd4_minorversions)
197 nfsd_netns_free_versions(nn);
198 }
199}
200
201int nfsd_vers(struct nfsd_net *nn, int vers, enum vers_op change)
146{ 202{
147 if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS) 203 if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS)
148 return 0; 204 return 0;
149 switch(change) { 205 switch(change) {
150 case NFSD_SET: 206 case NFSD_SET:
151 nfsd_versions[vers] = nfsd_version[vers]; 207 if (nn->nfsd_versions)
152#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 208 nn->nfsd_versions[vers] = nfsd_support_version(vers);
153 if (vers < NFSD_ACL_NRVERS)
154 nfsd_acl_versions[vers] = nfsd_acl_version[vers];
155#endif
156 break; 209 break;
157 case NFSD_CLEAR: 210 case NFSD_CLEAR:
158 nfsd_versions[vers] = NULL; 211 nfsd_netns_init_versions(nn);
159#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 212 if (nn->nfsd_versions)
160 if (vers < NFSD_ACL_NRVERS) 213 nn->nfsd_versions[vers] = false;
161 nfsd_acl_versions[vers] = NULL;
162#endif
163 break; 214 break;
164 case NFSD_TEST: 215 case NFSD_TEST:
165 return nfsd_versions[vers] != NULL; 216 if (nn->nfsd_versions)
217 return nn->nfsd_versions[vers];
218 /* Fallthrough */
166 case NFSD_AVAIL: 219 case NFSD_AVAIL:
167 return nfsd_version[vers] != NULL; 220 return nfsd_support_version(vers);
168 } 221 }
169 return 0; 222 return 0;
170} 223}
171 224
172static void 225static void
173nfsd_adjust_nfsd_versions4(void) 226nfsd_adjust_nfsd_versions4(struct nfsd_net *nn)
174{ 227{
175 unsigned i; 228 unsigned i;
176 229
177 for (i = 0; i <= NFSD_SUPPORTED_MINOR_VERSION; i++) { 230 for (i = 0; i <= NFSD_SUPPORTED_MINOR_VERSION; i++) {
178 if (nfsd_supported_minorversions[i]) 231 if (nn->nfsd4_minorversions[i])
179 return; 232 return;
180 } 233 }
181 nfsd_vers(4, NFSD_CLEAR); 234 nfsd_vers(nn, 4, NFSD_CLEAR);
182} 235}
183 236
184int nfsd_minorversion(u32 minorversion, enum vers_op change) 237int nfsd_minorversion(struct nfsd_net *nn, u32 minorversion, enum vers_op change)
185{ 238{
186 if (minorversion > NFSD_SUPPORTED_MINOR_VERSION && 239 if (minorversion > NFSD_SUPPORTED_MINOR_VERSION &&
187 change != NFSD_AVAIL) 240 change != NFSD_AVAIL)
188 return -1; 241 return -1;
242
189 switch(change) { 243 switch(change) {
190 case NFSD_SET: 244 case NFSD_SET:
191 nfsd_supported_minorversions[minorversion] = true; 245 if (nn->nfsd4_minorversions) {
192 nfsd_vers(4, NFSD_SET); 246 nfsd_vers(nn, 4, NFSD_SET);
247 nn->nfsd4_minorversions[minorversion] =
248 nfsd_vers(nn, 4, NFSD_TEST);
249 }
193 break; 250 break;
194 case NFSD_CLEAR: 251 case NFSD_CLEAR:
195 nfsd_supported_minorversions[minorversion] = false; 252 nfsd_netns_init_versions(nn);
196 nfsd_adjust_nfsd_versions4(); 253 if (nn->nfsd4_minorversions) {
254 nn->nfsd4_minorversions[minorversion] = false;
255 nfsd_adjust_nfsd_versions4(nn);
256 }
197 break; 257 break;
198 case NFSD_TEST: 258 case NFSD_TEST:
199 return nfsd_supported_minorversions[minorversion]; 259 if (nn->nfsd4_minorversions)
260 return nn->nfsd4_minorversions[minorversion];
261 return nfsd_vers(nn, 4, NFSD_TEST);
200 case NFSD_AVAIL: 262 case NFSD_AVAIL:
201 return minorversion <= NFSD_SUPPORTED_MINOR_VERSION; 263 return minorversion <= NFSD_SUPPORTED_MINOR_VERSION &&
264 nfsd_vers(nn, 4, NFSD_AVAIL);
202 } 265 }
203 return 0; 266 return 0;
204} 267}
@@ -280,13 +343,9 @@ static void nfsd_shutdown_generic(void)
280 nfsd_racache_shutdown(); 343 nfsd_racache_shutdown();
281} 344}
282 345
283static bool nfsd_needs_lockd(void) 346static bool nfsd_needs_lockd(struct nfsd_net *nn)
284{ 347{
285#if defined(CONFIG_NFSD_V3) 348 return nfsd_vers(nn, 2, NFSD_TEST) || nfsd_vers(nn, 3, NFSD_TEST);
286 return (nfsd_versions[2] != NULL) || (nfsd_versions[3] != NULL);
287#else
288 return (nfsd_versions[2] != NULL);
289#endif
290} 349}
291 350
292static int nfsd_startup_net(int nrservs, struct net *net) 351static int nfsd_startup_net(int nrservs, struct net *net)
@@ -304,7 +363,7 @@ static int nfsd_startup_net(int nrservs, struct net *net)
304 if (ret) 363 if (ret)
305 goto out_socks; 364 goto out_socks;
306 365
307 if (nfsd_needs_lockd() && !nn->lockd_up) { 366 if (nfsd_needs_lockd(nn) && !nn->lockd_up) {
308 ret = lockd_up(net); 367 ret = lockd_up(net);
309 if (ret) 368 if (ret)
310 goto out_socks; 369 goto out_socks;
@@ -437,20 +496,20 @@ static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
437 nfsd_export_flush(net); 496 nfsd_export_flush(net);
438} 497}
439 498
440void nfsd_reset_versions(void) 499void nfsd_reset_versions(struct nfsd_net *nn)
441{ 500{
442 int i; 501 int i;
443 502
444 for (i = 0; i < NFSD_NRVERS; i++) 503 for (i = 0; i < NFSD_NRVERS; i++)
445 if (nfsd_vers(i, NFSD_TEST)) 504 if (nfsd_vers(nn, i, NFSD_TEST))
446 return; 505 return;
447 506
448 for (i = 0; i < NFSD_NRVERS; i++) 507 for (i = 0; i < NFSD_NRVERS; i++)
449 if (i != 4) 508 if (i != 4)
450 nfsd_vers(i, NFSD_SET); 509 nfsd_vers(nn, i, NFSD_SET);
451 else { 510 else {
452 int minor = 0; 511 int minor = 0;
453 while (nfsd_minorversion(minor, NFSD_SET) >= 0) 512 while (nfsd_minorversion(nn, minor, NFSD_SET) >= 0)
454 minor++; 513 minor++;
455 } 514 }
456} 515}
@@ -518,7 +577,7 @@ int nfsd_create_serv(struct net *net)
518 } 577 }
519 if (nfsd_max_blksize == 0) 578 if (nfsd_max_blksize == 0)
520 nfsd_max_blksize = nfsd_get_default_max_blksize(); 579 nfsd_max_blksize = nfsd_get_default_max_blksize();
521 nfsd_reset_versions(); 580 nfsd_reset_versions(nn);
522 nn->nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize, 581 nn->nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
523 &nfsd_thread_sv_ops); 582 &nfsd_thread_sv_ops);
524 if (nn->nfsd_serv == NULL) 583 if (nn->nfsd_serv == NULL)
@@ -697,11 +756,44 @@ nfsd_acl_rpcbind_set(struct net *net, const struct svc_program *progp,
697 unsigned short port) 756 unsigned short port)
698{ 757{
699 if (!nfsd_support_acl_version(version) || 758 if (!nfsd_support_acl_version(version) ||
700 !nfsd_vers(version, NFSD_TEST)) 759 !nfsd_vers(net_generic(net, nfsd_net_id), version, NFSD_TEST))
701 return 0; 760 return 0;
702 return svc_generic_rpcbind_set(net, progp, version, family, 761 return svc_generic_rpcbind_set(net, progp, version, family,
703 proto, port); 762 proto, port);
704} 763}
764
765static __be32
766nfsd_acl_init_request(struct svc_rqst *rqstp,
767 const struct svc_program *progp,
768 struct svc_process_info *ret)
769{
770 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
771 int i;
772
773 if (likely(nfsd_support_acl_version(rqstp->rq_vers) &&
774 nfsd_vers(nn, rqstp->rq_vers, NFSD_TEST)))
775 return svc_generic_init_request(rqstp, progp, ret);
776
777 ret->mismatch.lovers = NFSD_ACL_NRVERS;
778 for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) {
779 if (nfsd_support_acl_version(rqstp->rq_vers) &&
780 nfsd_vers(nn, i, NFSD_TEST)) {
781 ret->mismatch.lovers = i;
782 break;
783 }
784 }
785 if (ret->mismatch.lovers == NFSD_ACL_NRVERS)
786 return rpc_prog_unavail;
787 ret->mismatch.hivers = NFSD_ACL_MINVERS;
788 for (i = NFSD_ACL_NRVERS - 1; i >= NFSD_ACL_MINVERS; i--) {
789 if (nfsd_support_acl_version(rqstp->rq_vers) &&
790 nfsd_vers(nn, i, NFSD_TEST)) {
791 ret->mismatch.hivers = i;
792 break;
793 }
794 }
795 return rpc_prog_mismatch;
796}
705#endif 797#endif
706 798
707static int 799static int
@@ -709,12 +801,42 @@ nfsd_rpcbind_set(struct net *net, const struct svc_program *progp,
709 u32 version, int family, unsigned short proto, 801 u32 version, int family, unsigned short proto,
710 unsigned short port) 802 unsigned short port)
711{ 803{
712 if (!nfsd_vers(version, NFSD_TEST)) 804 if (!nfsd_vers(net_generic(net, nfsd_net_id), version, NFSD_TEST))
713 return 0; 805 return 0;
714 return svc_generic_rpcbind_set(net, progp, version, family, 806 return svc_generic_rpcbind_set(net, progp, version, family,
715 proto, port); 807 proto, port);
716} 808}
717 809
810static __be32
811nfsd_init_request(struct svc_rqst *rqstp,
812 const struct svc_program *progp,
813 struct svc_process_info *ret)
814{
815 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
816 int i;
817
818 if (likely(nfsd_vers(nn, rqstp->rq_vers, NFSD_TEST)))
819 return svc_generic_init_request(rqstp, progp, ret);
820
821 ret->mismatch.lovers = NFSD_NRVERS;
822 for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) {
823 if (nfsd_vers(nn, i, NFSD_TEST)) {
824 ret->mismatch.lovers = i;
825 break;
826 }
827 }
828 if (ret->mismatch.lovers == NFSD_NRVERS)
829 return rpc_prog_unavail;
830 ret->mismatch.hivers = NFSD_MINVERS;
831 for (i = NFSD_NRVERS - 1; i >= NFSD_MINVERS; i--) {
832 if (nfsd_vers(nn, i, NFSD_TEST)) {
833 ret->mismatch.hivers = i;
834 break;
835 }
836 }
837 return rpc_prog_mismatch;
838}
839
718/* 840/*
719 * This is the NFS server kernel thread 841 * This is the NFS server kernel thread
720 */ 842 */