diff options
Diffstat (limited to 'fs/nfsd/export.c')
-rw-r--r-- | fs/nfsd/export.c | 125 |
1 files changed, 88 insertions, 37 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index c591761a1ad6..2ebd77d758bc 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -258,16 +258,6 @@ static DefineSimpleCacheLookup(svc_expkey, svc_expkey) | |||
258 | 258 | ||
259 | static struct cache_head *export_table[EXPORT_HASHMAX]; | 259 | static struct cache_head *export_table[EXPORT_HASHMAX]; |
260 | 260 | ||
261 | static inline int svc_export_hash(struct svc_export *item) | ||
262 | { | ||
263 | int rv; | ||
264 | |||
265 | rv = hash_ptr(item->ex_client, EXPORT_HASHBITS); | ||
266 | rv ^= hash_ptr(item->ex_dentry, EXPORT_HASHBITS); | ||
267 | rv ^= hash_ptr(item->ex_mnt, EXPORT_HASHBITS); | ||
268 | return rv; | ||
269 | } | ||
270 | |||
271 | void svc_export_put(struct cache_head *item, struct cache_detail *cd) | 261 | void svc_export_put(struct cache_head *item, struct cache_detail *cd) |
272 | { | 262 | { |
273 | if (cache_put(item, cd)) { | 263 | if (cache_put(item, cd)) { |
@@ -298,7 +288,8 @@ static void svc_export_request(struct cache_detail *cd, | |||
298 | (*bpp)[-1] = '\n'; | 288 | (*bpp)[-1] = '\n'; |
299 | } | 289 | } |
300 | 290 | ||
301 | static struct svc_export *svc_export_lookup(struct svc_export *, int); | 291 | struct svc_export *svc_export_update(struct svc_export *new, struct svc_export *old); |
292 | static struct svc_export *svc_export_lookup(struct svc_export *); | ||
302 | 293 | ||
303 | static int check_export(struct inode *inode, int flags) | 294 | static int check_export(struct inode *inode, int flags) |
304 | { | 295 | { |
@@ -411,11 +402,16 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
411 | if (err) goto out; | 402 | if (err) goto out; |
412 | } | 403 | } |
413 | 404 | ||
414 | expp = svc_export_lookup(&exp, 1); | 405 | expp = svc_export_lookup(&exp); |
415 | if (expp) | 406 | if (expp) |
416 | exp_put(expp); | 407 | expp = svc_export_update(&exp, expp); |
417 | err = 0; | 408 | else |
409 | err = -ENOMEM; | ||
418 | cache_flush(); | 410 | cache_flush(); |
411 | if (expp == NULL) | ||
412 | err = -ENOMEM; | ||
413 | else | ||
414 | exp_put(expp); | ||
419 | out: | 415 | out: |
420 | if (nd.dentry) | 416 | if (nd.dentry) |
421 | path_release(&nd); | 417 | path_release(&nd); |
@@ -449,40 +445,95 @@ static int svc_export_show(struct seq_file *m, | |||
449 | seq_puts(m, ")\n"); | 445 | seq_puts(m, ")\n"); |
450 | return 0; | 446 | return 0; |
451 | } | 447 | } |
452 | struct cache_detail svc_export_cache = { | 448 | static int svc_export_match(struct cache_head *a, struct cache_head *b) |
453 | .owner = THIS_MODULE, | ||
454 | .hash_size = EXPORT_HASHMAX, | ||
455 | .hash_table = export_table, | ||
456 | .name = "nfsd.export", | ||
457 | .cache_put = svc_export_put, | ||
458 | .cache_request = svc_export_request, | ||
459 | .cache_parse = svc_export_parse, | ||
460 | .cache_show = svc_export_show, | ||
461 | }; | ||
462 | |||
463 | static inline int svc_export_match(struct svc_export *a, struct svc_export *b) | ||
464 | { | 449 | { |
465 | return a->ex_client == b->ex_client && | 450 | struct svc_export *orig = container_of(a, struct svc_export, h); |
466 | a->ex_dentry == b->ex_dentry && | 451 | struct svc_export *new = container_of(b, struct svc_export, h); |
467 | a->ex_mnt == b->ex_mnt; | 452 | return orig->ex_client == new->ex_client && |
453 | orig->ex_dentry == new->ex_dentry && | ||
454 | orig->ex_mnt == new->ex_mnt; | ||
468 | } | 455 | } |
469 | static inline void svc_export_init(struct svc_export *new, struct svc_export *item) | 456 | |
457 | static void svc_export_init(struct cache_head *cnew, struct cache_head *citem) | ||
470 | { | 458 | { |
459 | struct svc_export *new = container_of(cnew, struct svc_export, h); | ||
460 | struct svc_export *item = container_of(citem, struct svc_export, h); | ||
461 | |||
471 | kref_get(&item->ex_client->ref); | 462 | kref_get(&item->ex_client->ref); |
472 | new->ex_client = item->ex_client; | 463 | new->ex_client = item->ex_client; |
473 | new->ex_dentry = dget(item->ex_dentry); | 464 | new->ex_dentry = dget(item->ex_dentry); |
474 | new->ex_mnt = mntget(item->ex_mnt); | 465 | new->ex_mnt = mntget(item->ex_mnt); |
475 | } | 466 | } |
476 | 467 | ||
477 | static inline void svc_export_update(struct svc_export *new, struct svc_export *item) | 468 | static void export_update(struct cache_head *cnew, struct cache_head *citem) |
478 | { | 469 | { |
470 | struct svc_export *new = container_of(cnew, struct svc_export, h); | ||
471 | struct svc_export *item = container_of(citem, struct svc_export, h); | ||
472 | |||
479 | new->ex_flags = item->ex_flags; | 473 | new->ex_flags = item->ex_flags; |
480 | new->ex_anon_uid = item->ex_anon_uid; | 474 | new->ex_anon_uid = item->ex_anon_uid; |
481 | new->ex_anon_gid = item->ex_anon_gid; | 475 | new->ex_anon_gid = item->ex_anon_gid; |
482 | new->ex_fsid = item->ex_fsid; | 476 | new->ex_fsid = item->ex_fsid; |
483 | } | 477 | } |
484 | 478 | ||
485 | static DefineSimpleCacheLookup(svc_export, svc_export) | 479 | static struct cache_head *svc_export_alloc(void) |
480 | { | ||
481 | struct svc_export *i = kmalloc(sizeof(*i), GFP_KERNEL); | ||
482 | if (i) | ||
483 | return &i->h; | ||
484 | else | ||
485 | return NULL; | ||
486 | } | ||
487 | |||
488 | struct cache_detail svc_export_cache = { | ||
489 | .owner = THIS_MODULE, | ||
490 | .hash_size = EXPORT_HASHMAX, | ||
491 | .hash_table = export_table, | ||
492 | .name = "nfsd.export", | ||
493 | .cache_put = svc_export_put, | ||
494 | .cache_request = svc_export_request, | ||
495 | .cache_parse = svc_export_parse, | ||
496 | .cache_show = svc_export_show, | ||
497 | .match = svc_export_match, | ||
498 | .init = svc_export_init, | ||
499 | .update = export_update, | ||
500 | .alloc = svc_export_alloc, | ||
501 | }; | ||
502 | |||
503 | static struct svc_export * | ||
504 | svc_export_lookup(struct svc_export *exp) | ||
505 | { | ||
506 | struct cache_head *ch; | ||
507 | int hash; | ||
508 | hash = hash_ptr(exp->ex_client, EXPORT_HASHBITS); | ||
509 | hash ^= hash_ptr(exp->ex_dentry, EXPORT_HASHBITS); | ||
510 | hash ^= hash_ptr(exp->ex_mnt, EXPORT_HASHBITS); | ||
511 | |||
512 | ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h, | ||
513 | hash); | ||
514 | if (ch) | ||
515 | return container_of(ch, struct svc_export, h); | ||
516 | else | ||
517 | return NULL; | ||
518 | } | ||
519 | |||
520 | struct svc_export * | ||
521 | svc_export_update(struct svc_export *new, struct svc_export *old) | ||
522 | { | ||
523 | struct cache_head *ch; | ||
524 | int hash; | ||
525 | hash = hash_ptr(old->ex_client, EXPORT_HASHBITS); | ||
526 | hash ^= hash_ptr(old->ex_dentry, EXPORT_HASHBITS); | ||
527 | hash ^= hash_ptr(old->ex_mnt, EXPORT_HASHBITS); | ||
528 | |||
529 | ch = sunrpc_cache_update(&svc_export_cache, &new->h, | ||
530 | &old->h, | ||
531 | hash); | ||
532 | if (ch) | ||
533 | return container_of(ch, struct svc_export, h); | ||
534 | else | ||
535 | return NULL; | ||
536 | } | ||
486 | 537 | ||
487 | 538 | ||
488 | struct svc_expkey * | 539 | struct svc_expkey * |
@@ -568,7 +619,7 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry, | |||
568 | key.ex_mnt = mnt; | 619 | key.ex_mnt = mnt; |
569 | key.ex_dentry = dentry; | 620 | key.ex_dentry = dentry; |
570 | 621 | ||
571 | exp = svc_export_lookup(&key, 0); | 622 | exp = svc_export_lookup(&key); |
572 | if (exp != NULL) | 623 | if (exp != NULL) |
573 | switch (cache_check(&svc_export_cache, &exp->h, reqp)) { | 624 | switch (cache_check(&svc_export_cache, &exp->h, reqp)) { |
574 | case 0: break; | 625 | case 0: break; |
@@ -770,13 +821,13 @@ exp_export(struct nfsctl_export *nxp) | |||
770 | new.ex_anon_gid = nxp->ex_anon_gid; | 821 | new.ex_anon_gid = nxp->ex_anon_gid; |
771 | new.ex_fsid = nxp->ex_dev; | 822 | new.ex_fsid = nxp->ex_dev; |
772 | 823 | ||
773 | exp = svc_export_lookup(&new, 1); | 824 | exp = svc_export_lookup(&new); |
825 | if (exp) | ||
826 | exp = svc_export_update(&new, exp); | ||
774 | 827 | ||
775 | if (exp == NULL) | 828 | if (!exp) |
776 | goto finish; | 829 | goto finish; |
777 | 830 | ||
778 | err = 0; | ||
779 | |||
780 | if (exp_hash(clp, exp) || | 831 | if (exp_hash(clp, exp) || |
781 | exp_fsid_hash(clp, exp)) { | 832 | exp_fsid_hash(clp, exp)) { |
782 | /* failed to create at least one index */ | 833 | /* failed to create at least one index */ |