aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStanislav Kinsbursky <skinsbursky@parallels.com>2012-01-19 12:42:29 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-01-31 19:28:15 -0500
commit73393232d6a425b6bb4cee590e3e66fc52532a15 (patch)
treee0df6bd41e665a307856b29c216473969fe88575
parent0a402d5a653ee2b613aaba3092a87b1e964622ce (diff)
SUNRPC: create unix gid cache per network namespace
v2: 1) fixed silly usage of template cache as a real one (this code left from static global cache for all) This patch makes unix_gid_cache cache detail allocated and registered per network namespace context. Thus with this patch unix_gid_cache contents for network namespace "X" are controlled from proc file system mount for the same network namespace "X". Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Acked-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--net/sunrpc/netns.h1
-rw-r--r--net/sunrpc/sunrpc_syms.c14
-rw-r--r--net/sunrpc/svcauth_unix.c55
3 files changed, 52 insertions, 18 deletions
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h
index 1fdeb1ba84b..309f88ddb06 100644
--- a/net/sunrpc/netns.h
+++ b/net/sunrpc/netns.h
@@ -9,6 +9,7 @@ struct cache_detail;
9struct sunrpc_net { 9struct sunrpc_net {
10 struct proc_dir_entry *proc_net_rpc; 10 struct proc_dir_entry *proc_net_rpc;
11 struct cache_detail *ip_map_cache; 11 struct cache_detail *ip_map_cache;
12 struct cache_detail *unix_gid_cache;
12 13
13 struct super_block *pipefs_sb; 14 struct super_block *pipefs_sb;
14 struct mutex pipefs_sb_lock; 15 struct mutex pipefs_sb_lock;
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index b4217dc8599..38a72a1b465 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -26,6 +26,9 @@
26 26
27int sunrpc_net_id; 27int sunrpc_net_id;
28 28
29extern int unix_gid_cache_create(struct net *net);
30extern int unix_gid_cache_destroy(struct net *net);
31
29static __net_init int sunrpc_init_net(struct net *net) 32static __net_init int sunrpc_init_net(struct net *net)
30{ 33{
31 int err; 34 int err;
@@ -39,11 +42,17 @@ static __net_init int sunrpc_init_net(struct net *net)
39 if (err) 42 if (err)
40 goto err_ipmap; 43 goto err_ipmap;
41 44
45 err = unix_gid_cache_create(net);
46 if (err)
47 goto err_unixgid;
48
42 rpc_pipefs_init_net(net); 49 rpc_pipefs_init_net(net);
43 INIT_LIST_HEAD(&sn->all_clients); 50 INIT_LIST_HEAD(&sn->all_clients);
44 spin_lock_init(&sn->rpc_client_lock); 51 spin_lock_init(&sn->rpc_client_lock);
45 return 0; 52 return 0;
46 53
54err_unixgid:
55 ip_map_cache_destroy(net);
47err_ipmap: 56err_ipmap:
48 rpc_proc_exit(net); 57 rpc_proc_exit(net);
49err_proc: 58err_proc:
@@ -52,6 +61,7 @@ err_proc:
52 61
53static __net_exit void sunrpc_exit_net(struct net *net) 62static __net_exit void sunrpc_exit_net(struct net *net)
54{ 63{
64 unix_gid_cache_destroy(net);
55 ip_map_cache_destroy(net); 65 ip_map_cache_destroy(net);
56 rpc_proc_exit(net); 66 rpc_proc_exit(net);
57} 67}
@@ -63,8 +73,6 @@ static struct pernet_operations sunrpc_net_ops = {
63 .size = sizeof(struct sunrpc_net), 73 .size = sizeof(struct sunrpc_net),
64}; 74};
65 75
66extern struct cache_detail unix_gid_cache;
67
68static int __init 76static int __init
69init_sunrpc(void) 77init_sunrpc(void)
70{ 78{
@@ -86,7 +94,6 @@ init_sunrpc(void)
86#ifdef RPC_DEBUG 94#ifdef RPC_DEBUG
87 rpc_register_sysctl(); 95 rpc_register_sysctl();
88#endif 96#endif
89 cache_register(&unix_gid_cache);
90 svc_init_xprt_sock(); /* svc sock transport */ 97 svc_init_xprt_sock(); /* svc sock transport */
91 init_socket_xprt(); /* clnt sock transport */ 98 init_socket_xprt(); /* clnt sock transport */
92 return 0; 99 return 0;
@@ -109,7 +116,6 @@ cleanup_sunrpc(void)
109 svc_cleanup_xprt_sock(); 116 svc_cleanup_xprt_sock();
110 unregister_rpc_pipefs(); 117 unregister_rpc_pipefs();
111 rpc_destroy_mempool(); 118 rpc_destroy_mempool();
112 cache_unregister(&unix_gid_cache);
113 unregister_pernet_subsys(&sunrpc_net_ops); 119 unregister_pernet_subsys(&sunrpc_net_ops);
114#ifdef RPC_DEBUG 120#ifdef RPC_DEBUG
115 rpc_unregister_sysctl(); 121 rpc_unregister_sysctl();
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 2f8c426c138..a6eef38fb35 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -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);