diff options
Diffstat (limited to 'fs/nfsd/export.c')
-rw-r--r-- | fs/nfsd/export.c | 368 |
1 files changed, 250 insertions, 118 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 417ec02df44f..c340be0a3f59 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -57,27 +57,17 @@ static int exp_verify_string(char *cp, int max); | |||
57 | #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) | 57 | #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) |
58 | static struct cache_head *expkey_table[EXPKEY_HASHMAX]; | 58 | static struct cache_head *expkey_table[EXPKEY_HASHMAX]; |
59 | 59 | ||
60 | static inline int svc_expkey_hash(struct svc_expkey *item) | 60 | static void expkey_put(struct kref *ref) |
61 | { | 61 | { |
62 | int hash = item->ek_fsidtype; | 62 | struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref); |
63 | char * cp = (char*)item->ek_fsid; | ||
64 | int len = key_len(item->ek_fsidtype); | ||
65 | 63 | ||
66 | hash ^= hash_mem(cp, len, EXPKEY_HASHBITS); | 64 | if (test_bit(CACHE_VALID, &key->h.flags) && |
67 | hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS); | 65 | !test_bit(CACHE_NEGATIVE, &key->h.flags)) { |
68 | return hash & EXPKEY_HASHMASK; | 66 | dput(key->ek_dentry); |
69 | } | 67 | mntput(key->ek_mnt); |
70 | |||
71 | void expkey_put(struct cache_head *item, struct cache_detail *cd) | ||
72 | { | ||
73 | if (cache_put(item, cd)) { | ||
74 | struct svc_expkey *key = container_of(item, struct svc_expkey, h); | ||
75 | if (test_bit(CACHE_VALID, &item->flags) && | ||
76 | !test_bit(CACHE_NEGATIVE, &item->flags)) | ||
77 | exp_put(key->ek_export); | ||
78 | auth_domain_put(key->ek_client); | ||
79 | kfree(key); | ||
80 | } | 68 | } |
69 | auth_domain_put(key->ek_client); | ||
70 | kfree(key); | ||
81 | } | 71 | } |
82 | 72 | ||
83 | static void expkey_request(struct cache_detail *cd, | 73 | static void expkey_request(struct cache_detail *cd, |
@@ -95,7 +85,10 @@ static void expkey_request(struct cache_detail *cd, | |||
95 | (*bpp)[-1] = '\n'; | 85 | (*bpp)[-1] = '\n'; |
96 | } | 86 | } |
97 | 87 | ||
98 | static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *, int); | 88 | static struct svc_expkey *svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old); |
89 | static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *); | ||
90 | static struct cache_detail svc_expkey_cache; | ||
91 | |||
99 | static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) | 92 | static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) |
100 | { | 93 | { |
101 | /* client fsidtype fsid [path] */ | 94 | /* client fsidtype fsid [path] */ |
@@ -106,6 +99,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
106 | int fsidtype; | 99 | int fsidtype; |
107 | char *ep; | 100 | char *ep; |
108 | struct svc_expkey key; | 101 | struct svc_expkey key; |
102 | struct svc_expkey *ek; | ||
109 | 103 | ||
110 | if (mesg[mlen-1] != '\n') | 104 | if (mesg[mlen-1] != '\n') |
111 | return -EINVAL; | 105 | return -EINVAL; |
@@ -150,40 +144,38 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
150 | key.ek_fsidtype = fsidtype; | 144 | key.ek_fsidtype = fsidtype; |
151 | memcpy(key.ek_fsid, buf, len); | 145 | memcpy(key.ek_fsid, buf, len); |
152 | 146 | ||
147 | ek = svc_expkey_lookup(&key); | ||
148 | err = -ENOMEM; | ||
149 | if (!ek) | ||
150 | goto out; | ||
151 | |||
153 | /* now we want a pathname, or empty meaning NEGATIVE */ | 152 | /* now we want a pathname, or empty meaning NEGATIVE */ |
153 | err = -EINVAL; | ||
154 | if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0) | 154 | if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0) |
155 | goto out; | 155 | goto out; |
156 | dprintk("Path seems to be <%s>\n", buf); | 156 | dprintk("Path seems to be <%s>\n", buf); |
157 | err = 0; | 157 | err = 0; |
158 | if (len == 0) { | 158 | if (len == 0) { |
159 | struct svc_expkey *ek; | ||
160 | set_bit(CACHE_NEGATIVE, &key.h.flags); | 159 | set_bit(CACHE_NEGATIVE, &key.h.flags); |
161 | ek = svc_expkey_lookup(&key, 1); | 160 | ek = svc_expkey_update(&key, ek); |
162 | if (ek) | 161 | if (ek) |
163 | expkey_put(&ek->h, &svc_expkey_cache); | 162 | cache_put(&ek->h, &svc_expkey_cache); |
163 | else err = -ENOMEM; | ||
164 | } else { | 164 | } else { |
165 | struct nameidata nd; | 165 | struct nameidata nd; |
166 | struct svc_expkey *ek; | ||
167 | struct svc_export *exp; | ||
168 | err = path_lookup(buf, 0, &nd); | 166 | err = path_lookup(buf, 0, &nd); |
169 | if (err) | 167 | if (err) |
170 | goto out; | 168 | goto out; |
171 | 169 | ||
172 | dprintk("Found the path %s\n", buf); | 170 | dprintk("Found the path %s\n", buf); |
173 | exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL); | 171 | key.ek_mnt = nd.mnt; |
174 | 172 | key.ek_dentry = nd.dentry; | |
175 | err = -ENOENT; | ||
176 | if (!exp) | ||
177 | goto out_nd; | ||
178 | key.ek_export = exp; | ||
179 | dprintk("And found export\n"); | ||
180 | 173 | ||
181 | ek = svc_expkey_lookup(&key, 1); | 174 | ek = svc_expkey_update(&key, ek); |
182 | if (ek) | 175 | if (ek) |
183 | expkey_put(&ek->h, &svc_expkey_cache); | 176 | cache_put(&ek->h, &svc_expkey_cache); |
184 | exp_put(exp); | 177 | else |
185 | err = 0; | 178 | err = -ENOMEM; |
186 | out_nd: | ||
187 | path_release(&nd); | 179 | path_release(&nd); |
188 | } | 180 | } |
189 | cache_flush(); | 181 | cache_flush(); |
@@ -214,35 +206,31 @@ static int expkey_show(struct seq_file *m, | |||
214 | if (test_bit(CACHE_VALID, &h->flags) && | 206 | if (test_bit(CACHE_VALID, &h->flags) && |
215 | !test_bit(CACHE_NEGATIVE, &h->flags)) { | 207 | !test_bit(CACHE_NEGATIVE, &h->flags)) { |
216 | seq_printf(m, " "); | 208 | seq_printf(m, " "); |
217 | seq_path(m, ek->ek_export->ex_mnt, ek->ek_export->ex_dentry, "\\ \t\n"); | 209 | seq_path(m, ek->ek_mnt, ek->ek_dentry, "\\ \t\n"); |
218 | } | 210 | } |
219 | seq_printf(m, "\n"); | 211 | seq_printf(m, "\n"); |
220 | return 0; | 212 | return 0; |
221 | } | 213 | } |
222 | |||
223 | struct cache_detail svc_expkey_cache = { | ||
224 | .owner = THIS_MODULE, | ||
225 | .hash_size = EXPKEY_HASHMAX, | ||
226 | .hash_table = expkey_table, | ||
227 | .name = "nfsd.fh", | ||
228 | .cache_put = expkey_put, | ||
229 | .cache_request = expkey_request, | ||
230 | .cache_parse = expkey_parse, | ||
231 | .cache_show = expkey_show, | ||
232 | }; | ||
233 | 214 | ||
234 | static inline int svc_expkey_match (struct svc_expkey *a, struct svc_expkey *b) | 215 | static inline int expkey_match (struct cache_head *a, struct cache_head *b) |
235 | { | 216 | { |
236 | if (a->ek_fsidtype != b->ek_fsidtype || | 217 | struct svc_expkey *orig = container_of(a, struct svc_expkey, h); |
237 | a->ek_client != b->ek_client || | 218 | struct svc_expkey *new = container_of(b, struct svc_expkey, h); |
238 | memcmp(a->ek_fsid, b->ek_fsid, key_len(a->ek_fsidtype)) != 0) | 219 | |
220 | if (orig->ek_fsidtype != new->ek_fsidtype || | ||
221 | orig->ek_client != new->ek_client || | ||
222 | memcmp(orig->ek_fsid, new->ek_fsid, key_len(orig->ek_fsidtype)) != 0) | ||
239 | return 0; | 223 | return 0; |
240 | return 1; | 224 | return 1; |
241 | } | 225 | } |
242 | 226 | ||
243 | static inline void svc_expkey_init(struct svc_expkey *new, struct svc_expkey *item) | 227 | static inline void expkey_init(struct cache_head *cnew, |
228 | struct cache_head *citem) | ||
244 | { | 229 | { |
245 | cache_get(&item->ek_client->h); | 230 | struct svc_expkey *new = container_of(cnew, struct svc_expkey, h); |
231 | struct svc_expkey *item = container_of(citem, struct svc_expkey, h); | ||
232 | |||
233 | kref_get(&item->ek_client->ref); | ||
246 | new->ek_client = item->ek_client; | 234 | new->ek_client = item->ek_client; |
247 | new->ek_fsidtype = item->ek_fsidtype; | 235 | new->ek_fsidtype = item->ek_fsidtype; |
248 | new->ek_fsid[0] = item->ek_fsid[0]; | 236 | new->ek_fsid[0] = item->ek_fsid[0]; |
@@ -250,39 +238,94 @@ static inline void svc_expkey_init(struct svc_expkey *new, struct svc_expkey *it | |||
250 | new->ek_fsid[2] = item->ek_fsid[2]; | 238 | new->ek_fsid[2] = item->ek_fsid[2]; |
251 | } | 239 | } |
252 | 240 | ||
253 | static inline void svc_expkey_update(struct svc_expkey *new, struct svc_expkey *item) | 241 | static inline void expkey_update(struct cache_head *cnew, |
242 | struct cache_head *citem) | ||
243 | { | ||
244 | struct svc_expkey *new = container_of(cnew, struct svc_expkey, h); | ||
245 | struct svc_expkey *item = container_of(citem, struct svc_expkey, h); | ||
246 | |||
247 | new->ek_mnt = mntget(item->ek_mnt); | ||
248 | new->ek_dentry = dget(item->ek_dentry); | ||
249 | } | ||
250 | |||
251 | static struct cache_head *expkey_alloc(void) | ||
254 | { | 252 | { |
255 | cache_get(&item->ek_export->h); | 253 | struct svc_expkey *i = kmalloc(sizeof(*i), GFP_KERNEL); |
256 | new->ek_export = item->ek_export; | 254 | if (i) |
255 | return &i->h; | ||
256 | else | ||
257 | return NULL; | ||
257 | } | 258 | } |
258 | 259 | ||
259 | static DefineSimpleCacheLookup(svc_expkey,0) /* no inplace updates */ | 260 | static struct cache_detail svc_expkey_cache = { |
261 | .owner = THIS_MODULE, | ||
262 | .hash_size = EXPKEY_HASHMAX, | ||
263 | .hash_table = expkey_table, | ||
264 | .name = "nfsd.fh", | ||
265 | .cache_put = expkey_put, | ||
266 | .cache_request = expkey_request, | ||
267 | .cache_parse = expkey_parse, | ||
268 | .cache_show = expkey_show, | ||
269 | .match = expkey_match, | ||
270 | .init = expkey_init, | ||
271 | .update = expkey_update, | ||
272 | .alloc = expkey_alloc, | ||
273 | }; | ||
260 | 274 | ||
261 | #define EXPORT_HASHBITS 8 | 275 | static struct svc_expkey * |
262 | #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) | 276 | svc_expkey_lookup(struct svc_expkey *item) |
263 | #define EXPORT_HASHMASK (EXPORT_HASHMAX -1) | 277 | { |
278 | struct cache_head *ch; | ||
279 | int hash = item->ek_fsidtype; | ||
280 | char * cp = (char*)item->ek_fsid; | ||
281 | int len = key_len(item->ek_fsidtype); | ||
264 | 282 | ||
265 | static struct cache_head *export_table[EXPORT_HASHMAX]; | 283 | hash ^= hash_mem(cp, len, EXPKEY_HASHBITS); |
284 | hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS); | ||
285 | hash &= EXPKEY_HASHMASK; | ||
266 | 286 | ||
267 | static inline int svc_export_hash(struct svc_export *item) | 287 | ch = sunrpc_cache_lookup(&svc_expkey_cache, &item->h, |
288 | hash); | ||
289 | if (ch) | ||
290 | return container_of(ch, struct svc_expkey, h); | ||
291 | else | ||
292 | return NULL; | ||
293 | } | ||
294 | |||
295 | static struct svc_expkey * | ||
296 | svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old) | ||
268 | { | 297 | { |
269 | int rv; | 298 | struct cache_head *ch; |
299 | int hash = new->ek_fsidtype; | ||
300 | char * cp = (char*)new->ek_fsid; | ||
301 | int len = key_len(new->ek_fsidtype); | ||
270 | 302 | ||
271 | rv = hash_ptr(item->ex_client, EXPORT_HASHBITS); | 303 | hash ^= hash_mem(cp, len, EXPKEY_HASHBITS); |
272 | rv ^= hash_ptr(item->ex_dentry, EXPORT_HASHBITS); | 304 | hash ^= hash_ptr(new->ek_client, EXPKEY_HASHBITS); |
273 | rv ^= hash_ptr(item->ex_mnt, EXPORT_HASHBITS); | 305 | hash &= EXPKEY_HASHMASK; |
274 | return rv; | 306 | |
307 | ch = sunrpc_cache_update(&svc_expkey_cache, &new->h, | ||
308 | &old->h, hash); | ||
309 | if (ch) | ||
310 | return container_of(ch, struct svc_expkey, h); | ||
311 | else | ||
312 | return NULL; | ||
275 | } | 313 | } |
276 | 314 | ||
277 | void svc_export_put(struct cache_head *item, struct cache_detail *cd) | 315 | |
316 | #define EXPORT_HASHBITS 8 | ||
317 | #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) | ||
318 | #define EXPORT_HASHMASK (EXPORT_HASHMAX -1) | ||
319 | |||
320 | static struct cache_head *export_table[EXPORT_HASHMAX]; | ||
321 | |||
322 | static void svc_export_put(struct kref *ref) | ||
278 | { | 323 | { |
279 | if (cache_put(item, cd)) { | 324 | struct svc_export *exp = container_of(ref, struct svc_export, h.ref); |
280 | struct svc_export *exp = container_of(item, struct svc_export, h); | 325 | dput(exp->ex_dentry); |
281 | dput(exp->ex_dentry); | 326 | mntput(exp->ex_mnt); |
282 | mntput(exp->ex_mnt); | 327 | auth_domain_put(exp->ex_client); |
283 | auth_domain_put(exp->ex_client); | 328 | kfree(exp); |
284 | kfree(exp); | ||
285 | } | ||
286 | } | 329 | } |
287 | 330 | ||
288 | static void svc_export_request(struct cache_detail *cd, | 331 | static void svc_export_request(struct cache_detail *cd, |
@@ -304,7 +347,9 @@ static void svc_export_request(struct cache_detail *cd, | |||
304 | (*bpp)[-1] = '\n'; | 347 | (*bpp)[-1] = '\n'; |
305 | } | 348 | } |
306 | 349 | ||
307 | static struct svc_export *svc_export_lookup(struct svc_export *, int); | 350 | static struct svc_export *svc_export_update(struct svc_export *new, |
351 | struct svc_export *old); | ||
352 | static struct svc_export *svc_export_lookup(struct svc_export *); | ||
308 | 353 | ||
309 | static int check_export(struct inode *inode, int flags) | 354 | static int check_export(struct inode *inode, int flags) |
310 | { | 355 | { |
@@ -417,11 +462,16 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
417 | if (err) goto out; | 462 | if (err) goto out; |
418 | } | 463 | } |
419 | 464 | ||
420 | expp = svc_export_lookup(&exp, 1); | 465 | expp = svc_export_lookup(&exp); |
421 | if (expp) | 466 | if (expp) |
422 | exp_put(expp); | 467 | expp = svc_export_update(&exp, expp); |
423 | err = 0; | 468 | else |
469 | err = -ENOMEM; | ||
424 | cache_flush(); | 470 | cache_flush(); |
471 | if (expp == NULL) | ||
472 | err = -ENOMEM; | ||
473 | else | ||
474 | exp_put(expp); | ||
425 | out: | 475 | out: |
426 | if (nd.dentry) | 476 | if (nd.dentry) |
427 | path_release(&nd); | 477 | path_release(&nd); |
@@ -455,6 +505,46 @@ static int svc_export_show(struct seq_file *m, | |||
455 | seq_puts(m, ")\n"); | 505 | seq_puts(m, ")\n"); |
456 | return 0; | 506 | return 0; |
457 | } | 507 | } |
508 | static int svc_export_match(struct cache_head *a, struct cache_head *b) | ||
509 | { | ||
510 | struct svc_export *orig = container_of(a, struct svc_export, h); | ||
511 | struct svc_export *new = container_of(b, struct svc_export, h); | ||
512 | return orig->ex_client == new->ex_client && | ||
513 | orig->ex_dentry == new->ex_dentry && | ||
514 | orig->ex_mnt == new->ex_mnt; | ||
515 | } | ||
516 | |||
517 | static void svc_export_init(struct cache_head *cnew, struct cache_head *citem) | ||
518 | { | ||
519 | struct svc_export *new = container_of(cnew, struct svc_export, h); | ||
520 | struct svc_export *item = container_of(citem, struct svc_export, h); | ||
521 | |||
522 | kref_get(&item->ex_client->ref); | ||
523 | new->ex_client = item->ex_client; | ||
524 | new->ex_dentry = dget(item->ex_dentry); | ||
525 | new->ex_mnt = mntget(item->ex_mnt); | ||
526 | } | ||
527 | |||
528 | static void export_update(struct cache_head *cnew, struct cache_head *citem) | ||
529 | { | ||
530 | struct svc_export *new = container_of(cnew, struct svc_export, h); | ||
531 | struct svc_export *item = container_of(citem, struct svc_export, h); | ||
532 | |||
533 | new->ex_flags = item->ex_flags; | ||
534 | new->ex_anon_uid = item->ex_anon_uid; | ||
535 | new->ex_anon_gid = item->ex_anon_gid; | ||
536 | new->ex_fsid = item->ex_fsid; | ||
537 | } | ||
538 | |||
539 | static struct cache_head *svc_export_alloc(void) | ||
540 | { | ||
541 | struct svc_export *i = kmalloc(sizeof(*i), GFP_KERNEL); | ||
542 | if (i) | ||
543 | return &i->h; | ||
544 | else | ||
545 | return NULL; | ||
546 | } | ||
547 | |||
458 | struct cache_detail svc_export_cache = { | 548 | struct cache_detail svc_export_cache = { |
459 | .owner = THIS_MODULE, | 549 | .owner = THIS_MODULE, |
460 | .hash_size = EXPORT_HASHMAX, | 550 | .hash_size = EXPORT_HASHMAX, |
@@ -464,34 +554,49 @@ struct cache_detail svc_export_cache = { | |||
464 | .cache_request = svc_export_request, | 554 | .cache_request = svc_export_request, |
465 | .cache_parse = svc_export_parse, | 555 | .cache_parse = svc_export_parse, |
466 | .cache_show = svc_export_show, | 556 | .cache_show = svc_export_show, |
557 | .match = svc_export_match, | ||
558 | .init = svc_export_init, | ||
559 | .update = export_update, | ||
560 | .alloc = svc_export_alloc, | ||
467 | }; | 561 | }; |
468 | 562 | ||
469 | static inline int svc_export_match(struct svc_export *a, struct svc_export *b) | 563 | static struct svc_export * |
564 | svc_export_lookup(struct svc_export *exp) | ||
470 | { | 565 | { |
471 | return a->ex_client == b->ex_client && | 566 | struct cache_head *ch; |
472 | a->ex_dentry == b->ex_dentry && | 567 | int hash; |
473 | a->ex_mnt == b->ex_mnt; | 568 | hash = hash_ptr(exp->ex_client, EXPORT_HASHBITS); |
474 | } | 569 | hash ^= hash_ptr(exp->ex_dentry, EXPORT_HASHBITS); |
475 | static inline void svc_export_init(struct svc_export *new, struct svc_export *item) | 570 | hash ^= hash_ptr(exp->ex_mnt, EXPORT_HASHBITS); |
476 | { | 571 | |
477 | cache_get(&item->ex_client->h); | 572 | ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h, |
478 | new->ex_client = item->ex_client; | 573 | hash); |
479 | new->ex_dentry = dget(item->ex_dentry); | 574 | if (ch) |
480 | new->ex_mnt = mntget(item->ex_mnt); | 575 | return container_of(ch, struct svc_export, h); |
576 | else | ||
577 | return NULL; | ||
481 | } | 578 | } |
482 | 579 | ||
483 | static inline void svc_export_update(struct svc_export *new, struct svc_export *item) | 580 | static struct svc_export * |
581 | svc_export_update(struct svc_export *new, struct svc_export *old) | ||
484 | { | 582 | { |
485 | new->ex_flags = item->ex_flags; | 583 | struct cache_head *ch; |
486 | new->ex_anon_uid = item->ex_anon_uid; | 584 | int hash; |
487 | new->ex_anon_gid = item->ex_anon_gid; | 585 | hash = hash_ptr(old->ex_client, EXPORT_HASHBITS); |
488 | new->ex_fsid = item->ex_fsid; | 586 | hash ^= hash_ptr(old->ex_dentry, EXPORT_HASHBITS); |
587 | hash ^= hash_ptr(old->ex_mnt, EXPORT_HASHBITS); | ||
588 | |||
589 | ch = sunrpc_cache_update(&svc_export_cache, &new->h, | ||
590 | &old->h, | ||
591 | hash); | ||
592 | if (ch) | ||
593 | return container_of(ch, struct svc_export, h); | ||
594 | else | ||
595 | return NULL; | ||
489 | } | 596 | } |
490 | 597 | ||
491 | static DefineSimpleCacheLookup(svc_export,1) /* allow inplace updates */ | ||
492 | 598 | ||
493 | 599 | static struct svc_expkey * | |
494 | struct svc_expkey * | ||
495 | exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) | 600 | exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) |
496 | { | 601 | { |
497 | struct svc_expkey key, *ek; | 602 | struct svc_expkey key, *ek; |
@@ -504,7 +609,7 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) | |||
504 | key.ek_fsidtype = fsid_type; | 609 | key.ek_fsidtype = fsid_type; |
505 | memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); | 610 | memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); |
506 | 611 | ||
507 | ek = svc_expkey_lookup(&key, 0); | 612 | ek = svc_expkey_lookup(&key); |
508 | if (ek != NULL) | 613 | if (ek != NULL) |
509 | if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp))) | 614 | if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp))) |
510 | ek = ERR_PTR(err); | 615 | ek = ERR_PTR(err); |
@@ -519,13 +624,16 @@ static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv, | |||
519 | key.ek_client = clp; | 624 | key.ek_client = clp; |
520 | key.ek_fsidtype = fsid_type; | 625 | key.ek_fsidtype = fsid_type; |
521 | memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); | 626 | memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); |
522 | key.ek_export = exp; | 627 | key.ek_mnt = exp->ex_mnt; |
628 | key.ek_dentry = exp->ex_dentry; | ||
523 | key.h.expiry_time = NEVER; | 629 | key.h.expiry_time = NEVER; |
524 | key.h.flags = 0; | 630 | key.h.flags = 0; |
525 | 631 | ||
526 | ek = svc_expkey_lookup(&key, 1); | 632 | ek = svc_expkey_lookup(&key); |
633 | if (ek) | ||
634 | ek = svc_expkey_update(&key,ek); | ||
527 | if (ek) { | 635 | if (ek) { |
528 | expkey_put(&ek->h, &svc_expkey_cache); | 636 | cache_put(&ek->h, &svc_expkey_cache); |
529 | return 0; | 637 | return 0; |
530 | } | 638 | } |
531 | return -ENOMEM; | 639 | return -ENOMEM; |
@@ -573,7 +681,7 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry, | |||
573 | key.ex_mnt = mnt; | 681 | key.ex_mnt = mnt; |
574 | key.ex_dentry = dentry; | 682 | key.ex_dentry = dentry; |
575 | 683 | ||
576 | exp = svc_export_lookup(&key, 0); | 684 | exp = svc_export_lookup(&key); |
577 | if (exp != NULL) | 685 | if (exp != NULL) |
578 | switch (cache_check(&svc_export_cache, &exp->h, reqp)) { | 686 | switch (cache_check(&svc_export_cache, &exp->h, reqp)) { |
579 | case 0: break; | 687 | case 0: break; |
@@ -654,7 +762,7 @@ static void exp_fsid_unhash(struct svc_export *exp) | |||
654 | ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid); | 762 | ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid); |
655 | if (ek && !IS_ERR(ek)) { | 763 | if (ek && !IS_ERR(ek)) { |
656 | ek->h.expiry_time = get_seconds()-1; | 764 | ek->h.expiry_time = get_seconds()-1; |
657 | expkey_put(&ek->h, &svc_expkey_cache); | 765 | cache_put(&ek->h, &svc_expkey_cache); |
658 | } | 766 | } |
659 | svc_expkey_cache.nextcheck = get_seconds(); | 767 | svc_expkey_cache.nextcheck = get_seconds(); |
660 | } | 768 | } |
@@ -692,7 +800,7 @@ static void exp_unhash(struct svc_export *exp) | |||
692 | ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino); | 800 | ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino); |
693 | if (ek && !IS_ERR(ek)) { | 801 | if (ek && !IS_ERR(ek)) { |
694 | ek->h.expiry_time = get_seconds()-1; | 802 | ek->h.expiry_time = get_seconds()-1; |
695 | expkey_put(&ek->h, &svc_expkey_cache); | 803 | cache_put(&ek->h, &svc_expkey_cache); |
696 | } | 804 | } |
697 | svc_expkey_cache.nextcheck = get_seconds(); | 805 | svc_expkey_cache.nextcheck = get_seconds(); |
698 | } | 806 | } |
@@ -741,8 +849,8 @@ exp_export(struct nfsctl_export *nxp) | |||
741 | if ((nxp->ex_flags & NFSEXP_FSID) && | 849 | if ((nxp->ex_flags & NFSEXP_FSID) && |
742 | (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) && | 850 | (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) && |
743 | !IS_ERR(fsid_key) && | 851 | !IS_ERR(fsid_key) && |
744 | fsid_key->ek_export && | 852 | fsid_key->ek_mnt && |
745 | fsid_key->ek_export != exp) | 853 | (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) ) |
746 | goto finish; | 854 | goto finish; |
747 | 855 | ||
748 | if (exp) { | 856 | if (exp) { |
@@ -775,13 +883,13 @@ exp_export(struct nfsctl_export *nxp) | |||
775 | new.ex_anon_gid = nxp->ex_anon_gid; | 883 | new.ex_anon_gid = nxp->ex_anon_gid; |
776 | new.ex_fsid = nxp->ex_dev; | 884 | new.ex_fsid = nxp->ex_dev; |
777 | 885 | ||
778 | exp = svc_export_lookup(&new, 1); | 886 | exp = svc_export_lookup(&new); |
887 | if (exp) | ||
888 | exp = svc_export_update(&new, exp); | ||
779 | 889 | ||
780 | if (exp == NULL) | 890 | if (!exp) |
781 | goto finish; | 891 | goto finish; |
782 | 892 | ||
783 | err = 0; | ||
784 | |||
785 | if (exp_hash(clp, exp) || | 893 | if (exp_hash(clp, exp) || |
786 | exp_fsid_hash(clp, exp)) { | 894 | exp_fsid_hash(clp, exp)) { |
787 | /* failed to create at least one index */ | 895 | /* failed to create at least one index */ |
@@ -794,7 +902,7 @@ finish: | |||
794 | if (exp) | 902 | if (exp) |
795 | exp_put(exp); | 903 | exp_put(exp); |
796 | if (fsid_key && !IS_ERR(fsid_key)) | 904 | if (fsid_key && !IS_ERR(fsid_key)) |
797 | expkey_put(&fsid_key->h, &svc_expkey_cache); | 905 | cache_put(&fsid_key->h, &svc_expkey_cache); |
798 | if (clp) | 906 | if (clp) |
799 | auth_domain_put(clp); | 907 | auth_domain_put(clp); |
800 | path_release(&nd); | 908 | path_release(&nd); |
@@ -912,6 +1020,24 @@ out: | |||
912 | return err; | 1020 | return err; |
913 | } | 1021 | } |
914 | 1022 | ||
1023 | struct svc_export * | ||
1024 | exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, | ||
1025 | struct cache_req *reqp) | ||
1026 | { | ||
1027 | struct svc_export *exp; | ||
1028 | struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp); | ||
1029 | if (!ek || IS_ERR(ek)) | ||
1030 | return ERR_PTR(PTR_ERR(ek)); | ||
1031 | |||
1032 | exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp); | ||
1033 | cache_put(&ek->h, &svc_expkey_cache); | ||
1034 | |||
1035 | if (!exp || IS_ERR(exp)) | ||
1036 | return ERR_PTR(PTR_ERR(exp)); | ||
1037 | return exp; | ||
1038 | } | ||
1039 | |||
1040 | |||
915 | /* | 1041 | /* |
916 | * Called when we need the filehandle for the root of the pseudofs, | 1042 | * Called when we need the filehandle for the root of the pseudofs, |
917 | * for a given NFSv4 client. The root is defined to be the | 1043 | * for a given NFSv4 client. The root is defined to be the |
@@ -922,6 +1048,7 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp, | |||
922 | struct cache_req *creq) | 1048 | struct cache_req *creq) |
923 | { | 1049 | { |
924 | struct svc_expkey *fsid_key; | 1050 | struct svc_expkey *fsid_key; |
1051 | struct svc_export *exp; | ||
925 | int rv; | 1052 | int rv; |
926 | u32 fsidv[2]; | 1053 | u32 fsidv[2]; |
927 | 1054 | ||
@@ -933,9 +1060,15 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp, | |||
933 | if (!fsid_key || IS_ERR(fsid_key)) | 1060 | if (!fsid_key || IS_ERR(fsid_key)) |
934 | return nfserr_perm; | 1061 | return nfserr_perm; |
935 | 1062 | ||
936 | rv = fh_compose(fhp, fsid_key->ek_export, | 1063 | exp = exp_get_by_name(clp, fsid_key->ek_mnt, fsid_key->ek_dentry, creq); |
937 | fsid_key->ek_export->ex_dentry, NULL); | 1064 | if (exp == NULL) |
938 | expkey_put(&fsid_key->h, &svc_expkey_cache); | 1065 | rv = nfserr_perm; |
1066 | else if (IS_ERR(exp)) | ||
1067 | rv = nfserrno(PTR_ERR(exp)); | ||
1068 | else | ||
1069 | rv = fh_compose(fhp, exp, | ||
1070 | fsid_key->ek_dentry, NULL); | ||
1071 | cache_put(&fsid_key->h, &svc_expkey_cache); | ||
939 | return rv; | 1072 | return rv; |
940 | } | 1073 | } |
941 | 1074 | ||
@@ -1054,7 +1187,7 @@ static int e_show(struct seq_file *m, void *p) | |||
1054 | cache_get(&exp->h); | 1187 | cache_get(&exp->h); |
1055 | if (cache_check(&svc_export_cache, &exp->h, NULL)) | 1188 | if (cache_check(&svc_export_cache, &exp->h, NULL)) |
1056 | return 0; | 1189 | return 0; |
1057 | if (cache_put(&exp->h, &svc_export_cache)) BUG(); | 1190 | cache_put(&exp->h, &svc_export_cache); |
1058 | return svc_export_show(m, &svc_export_cache, cp); | 1191 | return svc_export_show(m, &svc_export_cache, cp); |
1059 | } | 1192 | } |
1060 | 1193 | ||
@@ -1129,7 +1262,6 @@ exp_delclient(struct nfsctl_client *ncp) | |||
1129 | */ | 1262 | */ |
1130 | if (dom) { | 1263 | if (dom) { |
1131 | err = auth_unix_forget_old(dom); | 1264 | err = auth_unix_forget_old(dom); |
1132 | dom->h.expiry_time = get_seconds(); | ||
1133 | auth_domain_put(dom); | 1265 | auth_domain_put(dom); |
1134 | } | 1266 | } |
1135 | 1267 | ||