aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-10-02 05:17:46 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-02 10:57:17 -0400
commit6658d3a7bbfd1768a7b599def47939417f0ee8ef (patch)
treefd3ddac035bac92204836de1e11a0078fe54d5b9
parent24e36663c375df577d2dcae437713481ffd6850c (diff)
[PATCH] knfsd: remove nfsd_versbits as intermediate storage for desired versions
We have an array 'nfsd_version' which lists the available versions of nfsd, and 'nfsd_versions' (poor choice there :-() which lists the currently active versions. Then we have a bitmap - nfsd_versbits which says which versions are wanted. The bits in this bitset cause content to be copied from nfsd_version to nfsd_versions when nfsd starts. This patch removes nfsd_versbits and moves information directly from nfsd_version to nfsd_versions when requests for version changes arrive. Note that this doesn't make it possible to change versions while the server is running. This is because serv->sv_xdrsize is calculated when a service is created, and used when threads are created, and xdrsize depends on the active versions. Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/nfsd/nfsctl.c18
-rw-r--r--fs/nfsd/nfssvc.c93
-rw-r--r--include/linux/nfsd/nfsd.h4
-rw-r--r--include/linux/nfsd/syscall.h17
4 files changed, 62 insertions, 70 deletions
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 7046ac9cf97f..d6881774ea57 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -35,8 +35,6 @@
35 35
36#include <asm/uaccess.h> 36#include <asm/uaccess.h>
37 37
38unsigned int nfsd_versbits = ~0;
39
40/* 38/*
41 * We have a single directory with 9 nodes in it. 39 * We have a single directory with 9 nodes in it.
42 */ 40 */
@@ -372,6 +370,10 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size)
372 370
373 if (size>0) { 371 if (size>0) {
374 if (nfsd_serv) 372 if (nfsd_serv)
373 /* Cannot change versions without updating
374 * nfsd_serv->sv_xdrsize, and reallocing
375 * rq_argp and rq_resp
376 */
375 return -EBUSY; 377 return -EBUSY;
376 if (buf[size-1] != '\n') 378 if (buf[size-1] != '\n')
377 return -EINVAL; 379 return -EINVAL;
@@ -390,10 +392,7 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size)
390 case 2: 392 case 2:
391 case 3: 393 case 3:
392 case 4: 394 case 4:
393 if (sign != '-') 395 nfsd_vers(num, sign == '-' ? NFSD_CLEAR : NFSD_SET);
394 NFSCTL_VERSET(nfsd_versbits, num);
395 else
396 NFSCTL_VERUNSET(nfsd_versbits, num);
397 break; 396 break;
398 default: 397 default:
399 return -EINVAL; 398 return -EINVAL;
@@ -404,16 +403,15 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size)
404 /* If all get turned off, turn them back on, as 403 /* If all get turned off, turn them back on, as
405 * having no versions is BAD 404 * having no versions is BAD
406 */ 405 */
407 if ((nfsd_versbits & NFSCTL_VERALL)==0) 406 nfsd_reset_versions();
408 nfsd_versbits = NFSCTL_VERALL;
409 } 407 }
410 /* Now write current state into reply buffer */ 408 /* Now write current state into reply buffer */
411 len = 0; 409 len = 0;
412 sep = ""; 410 sep = "";
413 for (num=2 ; num <= 4 ; num++) 411 for (num=2 ; num <= 4 ; num++)
414 if (NFSCTL_VERISSET(NFSCTL_VERALL, num)) { 412 if (nfsd_vers(num, NFSD_AVAIL)) {
415 len += sprintf(buf+len, "%s%c%d", sep, 413 len += sprintf(buf+len, "%s%c%d", sep,
416 NFSCTL_VERISSET(nfsd_versbits, num)?'+':'-', 414 nfsd_vers(num, NFSD_TEST)?'+':'-',
417 num); 415 num);
418 sep = " "; 416 sep = " ";
419 } 417 }
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 0339b4ddfa3b..140e3a2d1b9f 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -117,6 +117,32 @@ struct svc_program nfsd_program = {
117 117
118}; 118};
119 119
120int nfsd_vers(int vers, enum vers_op change)
121{
122 if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS)
123 return -1;
124 switch(change) {
125 case NFSD_SET:
126 nfsd_versions[vers] = nfsd_version[vers];
127 break;
128#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
129 if (vers < NFSD_ACL_NRVERS)
130 nfsd_acl_version[vers] = nfsd_acl_version[vers];
131#endif
132 case NFSD_CLEAR:
133 nfsd_versions[vers] = NULL;
134#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
135 if (vers < NFSD_ACL_NRVERS)
136 nfsd_acl_version[vers] = NULL;
137#endif
138 break;
139 case NFSD_TEST:
140 return nfsd_versions[vers] != NULL;
141 case NFSD_AVAIL:
142 return nfsd_version[vers] != NULL;
143 }
144 return 0;
145}
120/* 146/*
121 * Maximum number of nfsd processes 147 * Maximum number of nfsd processes
122 */ 148 */
@@ -147,16 +173,36 @@ static void nfsd_last_thread(struct svc_serv *serv)
147 nfsd_export_flush(); 173 nfsd_export_flush();
148 } 174 }
149} 175}
176
177void nfsd_reset_versions(void)
178{
179 int found_one = 0;
180 int i;
181
182 for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) {
183 if (nfsd_program.pg_vers[i])
184 found_one = 1;
185 }
186
187 if (!found_one) {
188 for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++)
189 nfsd_program.pg_vers[i] = nfsd_version[i];
190#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
191 for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++)
192 nfsd_acl_program.pg_vers[i] =
193 nfsd_acl_version[i];
194#endif
195 }
196}
197
150int 198int
151nfsd_svc(unsigned short port, int nrservs) 199nfsd_svc(unsigned short port, int nrservs)
152{ 200{
153 int error; 201 int error;
154 int found_one, i;
155 struct list_head *victim; 202 struct list_head *victim;
156 203
157 lock_kernel(); 204 lock_kernel();
158 dprintk("nfsd: creating service: vers 0x%x\n", 205 dprintk("nfsd: creating service\n");
159 nfsd_versbits);
160 error = -EINVAL; 206 error = -EINVAL;
161 if (nrservs <= 0) 207 if (nrservs <= 0)
162 nrservs = 0; 208 nrservs = 0;
@@ -171,46 +217,7 @@ nfsd_svc(unsigned short port, int nrservs)
171 if (error<0) 217 if (error<0)
172 goto out; 218 goto out;
173 if (!nfsd_serv) { 219 if (!nfsd_serv) {
174 /* 220 nfsd_reset_versions();
175 * Use the nfsd_ctlbits to define which
176 * versions that will be advertised.
177 * If nfsd_ctlbits doesn't list any version,
178 * export them all.
179 */
180 found_one = 0;
181
182 for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) {
183 if (NFSCTL_VERISSET(nfsd_versbits, i)) {
184 nfsd_program.pg_vers[i] = nfsd_version[i];
185 found_one = 1;
186 } else
187 nfsd_program.pg_vers[i] = NULL;
188 }
189
190 if (!found_one) {
191 for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++)
192 nfsd_program.pg_vers[i] = nfsd_version[i];
193 }
194
195
196#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
197 found_one = 0;
198
199 for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) {
200 if (NFSCTL_VERISSET(nfsd_versbits, i)) {
201 nfsd_acl_program.pg_vers[i] =
202 nfsd_acl_version[i];
203 found_one = 1;
204 } else
205 nfsd_acl_program.pg_vers[i] = NULL;
206 }
207
208 if (!found_one) {
209 for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++)
210 nfsd_acl_program.pg_vers[i] =
211 nfsd_acl_version[i];
212 }
213#endif
214 221
215 atomic_set(&nfsd_busy, 0); 222 atomic_set(&nfsd_busy, 0);
216 error = -ENOMEM; 223 error = -ENOMEM;
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 2dcad295fece..46f1dc5b96dd 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -140,6 +140,10 @@ struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int);
140int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *); 140int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
141#endif 141#endif
142 142
143enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL };
144int nfsd_vers(int vers, enum vers_op change);
145void nfsd_reset_versions(void);
146
143 147
144/* 148/*
145 * NFSv4 State 149 * NFSv4 State
diff --git a/include/linux/nfsd/syscall.h b/include/linux/nfsd/syscall.h
index dae0faea2807..8bcddccb6c42 100644
--- a/include/linux/nfsd/syscall.h
+++ b/include/linux/nfsd/syscall.h
@@ -38,21 +38,6 @@
38#define NFSCTL_GETFD 7 /* get an fh by path (used by mountd) */ 38#define NFSCTL_GETFD 7 /* get an fh by path (used by mountd) */
39#define NFSCTL_GETFS 8 /* get an fh by path with max FH len */ 39#define NFSCTL_GETFS 8 /* get an fh by path with max FH len */
40 40
41/*
42 * Macros used to set version
43 */
44#define NFSCTL_VERSET(_cltbits, _v) ((_cltbits) |= (1 << (_v)))
45#define NFSCTL_VERUNSET(_cltbits, _v) ((_cltbits) &= ~(1 << (_v)))
46#define NFSCTL_VERISSET(_cltbits, _v) ((_cltbits) & (1 << (_v)))
47
48#if defined(CONFIG_NFSD_V4)
49#define NFSCTL_VERALL (0x1c /* 0b011100 */)
50#elif defined(CONFIG_NFSD_V3)
51#define NFSCTL_VERALL (0x0c /* 0b001100 */)
52#else
53#define NFSCTL_VERALL (0x04 /* 0b000100 */)
54#endif
55
56/* SVC */ 41/* SVC */
57struct nfsctl_svc { 42struct nfsctl_svc {
58 unsigned short svc_port; 43 unsigned short svc_port;
@@ -134,8 +119,6 @@ extern int exp_delclient(struct nfsctl_client *ncp);
134extern int exp_export(struct nfsctl_export *nxp); 119extern int exp_export(struct nfsctl_export *nxp);
135extern int exp_unexport(struct nfsctl_export *nxp); 120extern int exp_unexport(struct nfsctl_export *nxp);
136 121
137extern unsigned int nfsd_versbits;
138
139#endif /* __KERNEL__ */ 122#endif /* __KERNEL__ */
140 123
141#endif /* NFSD_SYSCALL_H */ 124#endif /* NFSD_SYSCALL_H */