aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/svcauth_unix.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-23 11:53:47 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-23 11:53:47 -0400
commitf63d395d47f37a4fe771e6d4b1db9d2cdae5ffc5 (patch)
tree3448a14ae965802adb963762cadeb9989ce4caa2 /net/sunrpc/svcauth_unix.c
parent643ac9fc5429e85b8b7f534544b80bcc4f34c367 (diff)
parent5a7c9eec9fde1da0e3adf0a4ddb64ff2a324a492 (diff)
Merge tag 'nfs-for-3.4-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates for Linux 3.4 from Trond Myklebust: "New features include: - Add NFS client support for containers. This should enable most of the necessary functionality, including lockd support, and support for rpc.statd, NFSv4 idmapper and RPCSEC_GSS upcalls into the correct network namespace from which the mount system call was issued. - NFSv4 idmapper scalability improvements Base the idmapper cache on the keyring interface to allow concurrent access to idmapper entries. Start the process of migrating users from the single-threaded daemon-based approach to the multi-threaded request-key based approach. - NFSv4.1 implementation id. Allows the NFSv4.1 client and server to mutually identify each other for logging and debugging purposes. - Support the 'vers=4.1' mount option for mounting NFSv4.1 instead of having to use the more counterintuitive 'vers=4,minorversion=1'. - SUNRPC tracepoints. Start the process of adding tracepoints in order to improve debugging of the RPC layer. - pNFS object layout support for autologin. Important bugfixes include: - Fix a bug in rpc_wake_up/rpc_wake_up_status that caused them to fail to wake up all tasks when applied to priority waitqueues. - Ensure that we handle read delegations correctly, when we try to truncate a file. - A number of fixes for NFSv4 state manager loops (mostly to do with delegation recovery)." * tag 'nfs-for-3.4-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (224 commits) NFS: fix sb->s_id in nfs debug prints xprtrdma: Remove assumption that each segment is <= PAGE_SIZE xprtrdma: The transport should not bug-check when a dup reply is received pnfs-obj: autologin: Add support for protocol autologin NFS: Remove nfs4_setup_sequence from generic rename code NFS: Remove nfs4_setup_sequence from generic unlink code NFS: Remove nfs4_setup_sequence from generic read code NFS: Remove nfs4_setup_sequence from generic write code NFS: Fix more NFS debug related build warnings SUNRPC/LOCKD: Fix build warnings when CONFIG_SUNRPC_DEBUG is undefined nfs: non void functions must return a value SUNRPC: Kill compiler warning when RPC_DEBUG is unset SUNRPC/NFS: Add Kbuild dependencies for NFS_DEBUG/RPC_DEBUG NFS: Use cond_resched_lock() to reduce latencies in the commit scans NFSv4: It is not safe to dereference lsp->ls_state in release_lockowner NFS: ncommit count is being double decremented SUNRPC: We must not use list_for_each_entry_safe() in rpc_wake_up() Try using machine credentials for RENEW calls NFSv4.1: Fix a few issues in filelayout_commit_pagelist NFSv4.1: Clean ups and bugfixes for the pNFS read/writeback/commit code ...
Diffstat (limited to 'net/sunrpc/svcauth_unix.c')
-rw-r--r--net/sunrpc/svcauth_unix.c126
1 files changed, 71 insertions, 55 deletions
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 01153ead1dba..bcd574f2ac56 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};
439static struct cache_head *gid_table[GID_HASHMAX];
440 439
441static void unix_gid_put(struct kref *kref) 440static 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
497static struct unix_gid *unix_gid_lookup(uid_t uid); 496static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid);
498extern struct cache_detail unix_gid_cache;
499 497
500static int unix_gid_parse(struct cache_detail *cd, 498static 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
590struct cache_detail unix_gid_cache = { 588static 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
605static struct unix_gid *unix_gid_lookup(uid_t uid) 602int 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
620void 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
631static 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
879static 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
852int ip_map_cache_create(struct net *net) 893int 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
887err_reg:
888 kfree(tbl);
889err_tbl:
890 kfree(cd);
891err_cd:
892 return err;
893} 909}
894 910
895void ip_map_cache_destroy(struct net *net) 911void 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}