diff options
author | NeilBrown <neilb@suse.de> | 2006-10-02 05:17:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-02 10:57:17 -0400 |
commit | 6658d3a7bbfd1768a7b599def47939417f0ee8ef (patch) | |
tree | fd3ddac035bac92204836de1e11a0078fe54d5b9 | |
parent | 24e36663c375df577d2dcae437713481ffd6850c (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.c | 18 | ||||
-rw-r--r-- | fs/nfsd/nfssvc.c | 93 | ||||
-rw-r--r-- | include/linux/nfsd/nfsd.h | 4 | ||||
-rw-r--r-- | include/linux/nfsd/syscall.h | 17 |
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 | ||
38 | unsigned 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 | ||
120 | int 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 | |||
177 | void 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 | |||
150 | int | 198 | int |
151 | nfsd_svc(unsigned short port, int nrservs) | 199 | nfsd_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); | |||
140 | int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *); | 140 | int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *); |
141 | #endif | 141 | #endif |
142 | 142 | ||
143 | enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL }; | ||
144 | int nfsd_vers(int vers, enum vers_op change); | ||
145 | void 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 */ |
57 | struct nfsctl_svc { | 42 | struct nfsctl_svc { |
58 | unsigned short svc_port; | 43 | unsigned short svc_port; |
@@ -134,8 +119,6 @@ extern int exp_delclient(struct nfsctl_client *ncp); | |||
134 | extern int exp_export(struct nfsctl_export *nxp); | 119 | extern int exp_export(struct nfsctl_export *nxp); |
135 | extern int exp_unexport(struct nfsctl_export *nxp); | 120 | extern int exp_unexport(struct nfsctl_export *nxp); |
136 | 121 | ||
137 | extern unsigned int nfsd_versbits; | ||
138 | |||
139 | #endif /* __KERNEL__ */ | 122 | #endif /* __KERNEL__ */ |
140 | 123 | ||
141 | #endif /* NFSD_SYSCALL_H */ | 124 | #endif /* NFSD_SYSCALL_H */ |