diff options
Diffstat (limited to 'fs/nfsd/nfs4idmap.c')
-rw-r--r-- | fs/nfsd/nfs4idmap.c | 121 |
1 files changed, 19 insertions, 102 deletions
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index c78dbf493424..55780a22fdbd 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c | |||
@@ -33,10 +33,11 @@ | |||
33 | */ | 33 | */ |
34 | 34 | ||
35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
36 | #include <linux/nfsd_idmap.h> | ||
37 | #include <linux/seq_file.h> | 36 | #include <linux/seq_file.h> |
38 | #include <linux/sched.h> | 37 | #include <linux/sched.h> |
39 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include "idmap.h" | ||
40 | #include "nfsd.h" | ||
40 | 41 | ||
41 | /* | 42 | /* |
42 | * Cache entry | 43 | * Cache entry |
@@ -62,7 +63,6 @@ struct ent { | |||
62 | 63 | ||
63 | #define ENT_HASHBITS 8 | 64 | #define ENT_HASHBITS 8 |
64 | #define ENT_HASHMAX (1 << ENT_HASHBITS) | 65 | #define ENT_HASHMAX (1 << ENT_HASHBITS) |
65 | #define ENT_HASHMASK (ENT_HASHMAX - 1) | ||
66 | 66 | ||
67 | static void | 67 | static void |
68 | ent_init(struct cache_head *cnew, struct cache_head *citm) | 68 | ent_init(struct cache_head *cnew, struct cache_head *citm) |
@@ -482,109 +482,26 @@ nfsd_idmap_shutdown(void) | |||
482 | cache_unregister(&nametoid_cache); | 482 | cache_unregister(&nametoid_cache); |
483 | } | 483 | } |
484 | 484 | ||
485 | /* | ||
486 | * Deferred request handling | ||
487 | */ | ||
488 | |||
489 | struct idmap_defer_req { | ||
490 | struct cache_req req; | ||
491 | struct cache_deferred_req deferred_req; | ||
492 | wait_queue_head_t waitq; | ||
493 | atomic_t count; | ||
494 | }; | ||
495 | |||
496 | static inline void | ||
497 | put_mdr(struct idmap_defer_req *mdr) | ||
498 | { | ||
499 | if (atomic_dec_and_test(&mdr->count)) | ||
500 | kfree(mdr); | ||
501 | } | ||
502 | |||
503 | static inline void | ||
504 | get_mdr(struct idmap_defer_req *mdr) | ||
505 | { | ||
506 | atomic_inc(&mdr->count); | ||
507 | } | ||
508 | |||
509 | static void | ||
510 | idmap_revisit(struct cache_deferred_req *dreq, int toomany) | ||
511 | { | ||
512 | struct idmap_defer_req *mdr = | ||
513 | container_of(dreq, struct idmap_defer_req, deferred_req); | ||
514 | |||
515 | wake_up(&mdr->waitq); | ||
516 | put_mdr(mdr); | ||
517 | } | ||
518 | |||
519 | static struct cache_deferred_req * | ||
520 | idmap_defer(struct cache_req *req) | ||
521 | { | ||
522 | struct idmap_defer_req *mdr = | ||
523 | container_of(req, struct idmap_defer_req, req); | ||
524 | |||
525 | mdr->deferred_req.revisit = idmap_revisit; | ||
526 | get_mdr(mdr); | ||
527 | return (&mdr->deferred_req); | ||
528 | } | ||
529 | |||
530 | static inline int | ||
531 | do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *), struct ent *key, | ||
532 | struct cache_detail *detail, struct ent **item, | ||
533 | struct idmap_defer_req *mdr) | ||
534 | { | ||
535 | *item = lookup_fn(key); | ||
536 | if (!*item) | ||
537 | return -ENOMEM; | ||
538 | return cache_check(detail, &(*item)->h, &mdr->req); | ||
539 | } | ||
540 | |||
541 | static inline int | ||
542 | do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *), | ||
543 | struct ent *key, struct cache_detail *detail, | ||
544 | struct ent **item) | ||
545 | { | ||
546 | int ret = -ENOMEM; | ||
547 | |||
548 | *item = lookup_fn(key); | ||
549 | if (!*item) | ||
550 | goto out_err; | ||
551 | ret = -ETIMEDOUT; | ||
552 | if (!test_bit(CACHE_VALID, &(*item)->h.flags) | ||
553 | || (*item)->h.expiry_time < get_seconds() | ||
554 | || detail->flush_time > (*item)->h.last_refresh) | ||
555 | goto out_put; | ||
556 | ret = -ENOENT; | ||
557 | if (test_bit(CACHE_NEGATIVE, &(*item)->h.flags)) | ||
558 | goto out_put; | ||
559 | return 0; | ||
560 | out_put: | ||
561 | cache_put(&(*item)->h, detail); | ||
562 | out_err: | ||
563 | *item = NULL; | ||
564 | return ret; | ||
565 | } | ||
566 | |||
567 | static int | 485 | static int |
568 | idmap_lookup(struct svc_rqst *rqstp, | 486 | idmap_lookup(struct svc_rqst *rqstp, |
569 | struct ent *(*lookup_fn)(struct ent *), struct ent *key, | 487 | struct ent *(*lookup_fn)(struct ent *), struct ent *key, |
570 | struct cache_detail *detail, struct ent **item) | 488 | struct cache_detail *detail, struct ent **item) |
571 | { | 489 | { |
572 | struct idmap_defer_req *mdr; | ||
573 | int ret; | 490 | int ret; |
574 | 491 | ||
575 | mdr = kzalloc(sizeof(*mdr), GFP_KERNEL); | 492 | *item = lookup_fn(key); |
576 | if (!mdr) | 493 | if (!*item) |
577 | return -ENOMEM; | 494 | return -ENOMEM; |
578 | atomic_set(&mdr->count, 1); | 495 | retry: |
579 | init_waitqueue_head(&mdr->waitq); | 496 | ret = cache_check(detail, &(*item)->h, &rqstp->rq_chandle); |
580 | mdr->req.defer = idmap_defer; | 497 | |
581 | ret = do_idmap_lookup(lookup_fn, key, detail, item, mdr); | 498 | if (ret == -ETIMEDOUT) { |
582 | if (ret == -EAGAIN) { | 499 | struct ent *prev_item = *item; |
583 | wait_event_interruptible_timeout(mdr->waitq, | 500 | *item = lookup_fn(key); |
584 | test_bit(CACHE_VALID, &(*item)->h.flags), 1 * HZ); | 501 | if (*item != prev_item) |
585 | ret = do_idmap_lookup_nowait(lookup_fn, key, detail, item); | 502 | goto retry; |
503 | cache_put(&(*item)->h, detail); | ||
586 | } | 504 | } |
587 | put_mdr(mdr); | ||
588 | return ret; | 505 | return ret; |
589 | } | 506 | } |
590 | 507 | ||
@@ -597,7 +514,7 @@ rqst_authname(struct svc_rqst *rqstp) | |||
597 | return clp->name; | 514 | return clp->name; |
598 | } | 515 | } |
599 | 516 | ||
600 | static int | 517 | static __be32 |
601 | idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, | 518 | idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, |
602 | uid_t *id) | 519 | uid_t *id) |
603 | { | 520 | { |
@@ -607,15 +524,15 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen | |||
607 | int ret; | 524 | int ret; |
608 | 525 | ||
609 | if (namelen + 1 > sizeof(key.name)) | 526 | if (namelen + 1 > sizeof(key.name)) |
610 | return -EINVAL; | 527 | return nfserr_badowner; |
611 | memcpy(key.name, name, namelen); | 528 | memcpy(key.name, name, namelen); |
612 | key.name[namelen] = '\0'; | 529 | key.name[namelen] = '\0'; |
613 | strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); | 530 | strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); |
614 | ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item); | 531 | ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item); |
615 | if (ret == -ENOENT) | 532 | if (ret == -ENOENT) |
616 | ret = -ESRCH; /* nfserr_badname */ | 533 | return nfserr_badowner; |
617 | if (ret) | 534 | if (ret) |
618 | return ret; | 535 | return nfserrno(ret); |
619 | *id = item->id; | 536 | *id = item->id; |
620 | cache_put(&item->h, &nametoid_cache); | 537 | cache_put(&item->h, &nametoid_cache); |
621 | return 0; | 538 | return 0; |
@@ -643,14 +560,14 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name) | |||
643 | return ret; | 560 | return ret; |
644 | } | 561 | } |
645 | 562 | ||
646 | int | 563 | __be32 |
647 | nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen, | 564 | nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen, |
648 | __u32 *id) | 565 | __u32 *id) |
649 | { | 566 | { |
650 | return idmap_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, id); | 567 | return idmap_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, id); |
651 | } | 568 | } |
652 | 569 | ||
653 | int | 570 | __be32 |
654 | nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen, | 571 | nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen, |
655 | __u32 *id) | 572 | __u32 *id) |
656 | { | 573 | { |