diff options
Diffstat (limited to 'net/sunrpc/svcauth_unix.c')
-rw-r--r-- | net/sunrpc/svcauth_unix.c | 126 |
1 files changed, 71 insertions, 55 deletions
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 6ab35736d88f..521d8f7dc833 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -211,7 +211,7 @@ static int ip_map_parse(struct cache_detail *cd, | |||
211 | len = qword_get(&mesg, buf, mlen); | 211 | len = qword_get(&mesg, buf, mlen); |
212 | if (len <= 0) return -EINVAL; | 212 | if (len <= 0) return -EINVAL; |
213 | 213 | ||
214 | if (rpc_pton(buf, len, &address.sa, sizeof(address)) == 0) | 214 | if (rpc_pton(cd->net, buf, len, &address.sa, sizeof(address)) == 0) |
215 | return -EINVAL; | 215 | return -EINVAL; |
216 | switch (address.sa.sa_family) { | 216 | switch (address.sa.sa_family) { |
217 | case AF_INET: | 217 | case AF_INET: |
@@ -436,7 +436,6 @@ struct unix_gid { | |||
436 | uid_t uid; | 436 | uid_t uid; |
437 | struct group_info *gi; | 437 | struct group_info *gi; |
438 | }; | 438 | }; |
439 | static struct cache_head *gid_table[GID_HASHMAX]; | ||
440 | 439 | ||
441 | static void unix_gid_put(struct kref *kref) | 440 | static void unix_gid_put(struct kref *kref) |
442 | { | 441 | { |
@@ -494,8 +493,7 @@ static int unix_gid_upcall(struct cache_detail *cd, struct cache_head *h) | |||
494 | return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request); | 493 | return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request); |
495 | } | 494 | } |
496 | 495 | ||
497 | static struct unix_gid *unix_gid_lookup(uid_t uid); | 496 | static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid); |
498 | extern struct cache_detail unix_gid_cache; | ||
499 | 497 | ||
500 | static int unix_gid_parse(struct cache_detail *cd, | 498 | static int unix_gid_parse(struct cache_detail *cd, |
501 | char *mesg, int mlen) | 499 | char *mesg, int mlen) |
@@ -539,19 +537,19 @@ static int unix_gid_parse(struct cache_detail *cd, | |||
539 | GROUP_AT(ug.gi, i) = gid; | 537 | GROUP_AT(ug.gi, i) = gid; |
540 | } | 538 | } |
541 | 539 | ||
542 | ugp = unix_gid_lookup(uid); | 540 | ugp = unix_gid_lookup(cd, uid); |
543 | if (ugp) { | 541 | if (ugp) { |
544 | struct cache_head *ch; | 542 | struct cache_head *ch; |
545 | ug.h.flags = 0; | 543 | ug.h.flags = 0; |
546 | ug.h.expiry_time = expiry; | 544 | ug.h.expiry_time = expiry; |
547 | ch = sunrpc_cache_update(&unix_gid_cache, | 545 | ch = sunrpc_cache_update(cd, |
548 | &ug.h, &ugp->h, | 546 | &ug.h, &ugp->h, |
549 | hash_long(uid, GID_HASHBITS)); | 547 | hash_long(uid, GID_HASHBITS)); |
550 | if (!ch) | 548 | if (!ch) |
551 | err = -ENOMEM; | 549 | err = -ENOMEM; |
552 | else { | 550 | else { |
553 | err = 0; | 551 | err = 0; |
554 | cache_put(ch, &unix_gid_cache); | 552 | cache_put(ch, cd); |
555 | } | 553 | } |
556 | } else | 554 | } else |
557 | err = -ENOMEM; | 555 | err = -ENOMEM; |
@@ -587,10 +585,9 @@ static int unix_gid_show(struct seq_file *m, | |||
587 | return 0; | 585 | return 0; |
588 | } | 586 | } |
589 | 587 | ||
590 | struct cache_detail unix_gid_cache = { | 588 | static struct cache_detail unix_gid_cache_template = { |
591 | .owner = THIS_MODULE, | 589 | .owner = THIS_MODULE, |
592 | .hash_size = GID_HASHMAX, | 590 | .hash_size = GID_HASHMAX, |
593 | .hash_table = gid_table, | ||
594 | .name = "auth.unix.gid", | 591 | .name = "auth.unix.gid", |
595 | .cache_put = unix_gid_put, | 592 | .cache_put = unix_gid_put, |
596 | .cache_upcall = unix_gid_upcall, | 593 | .cache_upcall = unix_gid_upcall, |
@@ -602,14 +599,42 @@ struct cache_detail unix_gid_cache = { | |||
602 | .alloc = unix_gid_alloc, | 599 | .alloc = unix_gid_alloc, |
603 | }; | 600 | }; |
604 | 601 | ||
605 | static struct unix_gid *unix_gid_lookup(uid_t uid) | 602 | int unix_gid_cache_create(struct net *net) |
603 | { | ||
604 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
605 | struct cache_detail *cd; | ||
606 | int err; | ||
607 | |||
608 | cd = cache_create_net(&unix_gid_cache_template, net); | ||
609 | if (IS_ERR(cd)) | ||
610 | return PTR_ERR(cd); | ||
611 | err = cache_register_net(cd, net); | ||
612 | if (err) { | ||
613 | cache_destroy_net(cd, net); | ||
614 | return err; | ||
615 | } | ||
616 | sn->unix_gid_cache = cd; | ||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | void unix_gid_cache_destroy(struct net *net) | ||
621 | { | ||
622 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
623 | struct cache_detail *cd = sn->unix_gid_cache; | ||
624 | |||
625 | sn->unix_gid_cache = NULL; | ||
626 | cache_purge(cd); | ||
627 | cache_unregister_net(cd, net); | ||
628 | cache_destroy_net(cd, net); | ||
629 | } | ||
630 | |||
631 | static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid) | ||
606 | { | 632 | { |
607 | struct unix_gid ug; | 633 | struct unix_gid ug; |
608 | struct cache_head *ch; | 634 | struct cache_head *ch; |
609 | 635 | ||
610 | ug.uid = uid; | 636 | ug.uid = uid; |
611 | ch = sunrpc_cache_lookup(&unix_gid_cache, &ug.h, | 637 | ch = sunrpc_cache_lookup(cd, &ug.h, hash_long(uid, GID_HASHBITS)); |
612 | hash_long(uid, GID_HASHBITS)); | ||
613 | if (ch) | 638 | if (ch) |
614 | return container_of(ch, struct unix_gid, h); | 639 | return container_of(ch, struct unix_gid, h); |
615 | else | 640 | else |
@@ -621,11 +646,13 @@ static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp) | |||
621 | struct unix_gid *ug; | 646 | struct unix_gid *ug; |
622 | struct group_info *gi; | 647 | struct group_info *gi; |
623 | int ret; | 648 | int ret; |
649 | struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, | ||
650 | sunrpc_net_id); | ||
624 | 651 | ||
625 | ug = unix_gid_lookup(uid); | 652 | ug = unix_gid_lookup(sn->unix_gid_cache, uid); |
626 | if (!ug) | 653 | if (!ug) |
627 | return ERR_PTR(-EAGAIN); | 654 | return ERR_PTR(-EAGAIN); |
628 | ret = cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle); | 655 | ret = cache_check(sn->unix_gid_cache, &ug->h, &rqstp->rq_chandle); |
629 | switch (ret) { | 656 | switch (ret) { |
630 | case -ENOENT: | 657 | case -ENOENT: |
631 | return ERR_PTR(-ENOENT); | 658 | return ERR_PTR(-ENOENT); |
@@ -633,7 +660,7 @@ static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp) | |||
633 | return ERR_PTR(-ESHUTDOWN); | 660 | return ERR_PTR(-ESHUTDOWN); |
634 | case 0: | 661 | case 0: |
635 | gi = get_group_info(ug->gi); | 662 | gi = get_group_info(ug->gi); |
636 | cache_put(&ug->h, &unix_gid_cache); | 663 | cache_put(&ug->h, sn->unix_gid_cache); |
637 | return gi; | 664 | return gi; |
638 | default: | 665 | default: |
639 | return ERR_PTR(-EAGAIN); | 666 | return ERR_PTR(-EAGAIN); |
@@ -849,56 +876,45 @@ struct auth_ops svcauth_unix = { | |||
849 | .set_client = svcauth_unix_set_client, | 876 | .set_client = svcauth_unix_set_client, |
850 | }; | 877 | }; |
851 | 878 | ||
879 | static struct cache_detail ip_map_cache_template = { | ||
880 | .owner = THIS_MODULE, | ||
881 | .hash_size = IP_HASHMAX, | ||
882 | .name = "auth.unix.ip", | ||
883 | .cache_put = ip_map_put, | ||
884 | .cache_upcall = ip_map_upcall, | ||
885 | .cache_parse = ip_map_parse, | ||
886 | .cache_show = ip_map_show, | ||
887 | .match = ip_map_match, | ||
888 | .init = ip_map_init, | ||
889 | .update = update, | ||
890 | .alloc = ip_map_alloc, | ||
891 | }; | ||
892 | |||
852 | int ip_map_cache_create(struct net *net) | 893 | int ip_map_cache_create(struct net *net) |
853 | { | 894 | { |
854 | int err = -ENOMEM; | ||
855 | struct cache_detail *cd; | ||
856 | struct cache_head **tbl; | ||
857 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 895 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
896 | struct cache_detail *cd; | ||
897 | int err; | ||
858 | 898 | ||
859 | cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL); | 899 | cd = cache_create_net(&ip_map_cache_template, net); |
860 | if (cd == NULL) | 900 | if (IS_ERR(cd)) |
861 | goto err_cd; | 901 | return PTR_ERR(cd); |
862 | |||
863 | tbl = kzalloc(IP_HASHMAX * sizeof(struct cache_head *), GFP_KERNEL); | ||
864 | if (tbl == NULL) | ||
865 | goto err_tbl; | ||
866 | |||
867 | cd->owner = THIS_MODULE, | ||
868 | cd->hash_size = IP_HASHMAX, | ||
869 | cd->hash_table = tbl, | ||
870 | cd->name = "auth.unix.ip", | ||
871 | cd->cache_put = ip_map_put, | ||
872 | cd->cache_upcall = ip_map_upcall, | ||
873 | cd->cache_parse = ip_map_parse, | ||
874 | cd->cache_show = ip_map_show, | ||
875 | cd->match = ip_map_match, | ||
876 | cd->init = ip_map_init, | ||
877 | cd->update = update, | ||
878 | cd->alloc = ip_map_alloc, | ||
879 | |||
880 | err = cache_register_net(cd, net); | 902 | err = cache_register_net(cd, net); |
881 | if (err) | 903 | if (err) { |
882 | goto err_reg; | 904 | cache_destroy_net(cd, net); |
883 | 905 | return err; | |
906 | } | ||
884 | sn->ip_map_cache = cd; | 907 | sn->ip_map_cache = cd; |
885 | return 0; | 908 | return 0; |
886 | |||
887 | err_reg: | ||
888 | kfree(tbl); | ||
889 | err_tbl: | ||
890 | kfree(cd); | ||
891 | err_cd: | ||
892 | return err; | ||
893 | } | 909 | } |
894 | 910 | ||
895 | void ip_map_cache_destroy(struct net *net) | 911 | void ip_map_cache_destroy(struct net *net) |
896 | { | 912 | { |
897 | struct sunrpc_net *sn; | 913 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
914 | struct cache_detail *cd = sn->ip_map_cache; | ||
898 | 915 | ||
899 | sn = net_generic(net, sunrpc_net_id); | 916 | sn->ip_map_cache = NULL; |
900 | cache_purge(sn->ip_map_cache); | 917 | cache_purge(cd); |
901 | cache_unregister_net(sn->ip_map_cache, net); | 918 | cache_unregister_net(cd, net); |
902 | kfree(sn->ip_map_cache->hash_table); | 919 | cache_destroy_net(cd, net); |
903 | kfree(sn->ip_map_cache); | ||
904 | } | 920 | } |