diff options
author | Pavel Emelyanov <xemul@parallels.com> | 2010-09-27 06:02:29 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2010-09-27 10:16:12 -0400 |
commit | 90d51b02fd702d969eb05bd9d4ecc954759fbe23 (patch) | |
tree | fb5409d3ed5844be89a284097a930e1ff5ea37de /net/sunrpc | |
parent | 4f42d0d53ca4737f82937edb0efc83564c124853 (diff) |
sunrpc: Make the ip_map_cache be per-net
Everything that is required for that already exists:
* the per-net cache registration with respective proc entries
* the context (struct net) is available in all the users
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/netns.h | 6 | ||||
-rw-r--r-- | net/sunrpc/sunrpc_syms.c | 11 | ||||
-rw-r--r-- | net/sunrpc/svcauth_unix.c | 122 |
3 files changed, 108 insertions, 31 deletions
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h index e52ce897dde5..d013bf211cae 100644 --- a/net/sunrpc/netns.h +++ b/net/sunrpc/netns.h | |||
@@ -4,10 +4,16 @@ | |||
4 | #include <net/net_namespace.h> | 4 | #include <net/net_namespace.h> |
5 | #include <net/netns/generic.h> | 5 | #include <net/netns/generic.h> |
6 | 6 | ||
7 | struct cache_detail; | ||
8 | |||
7 | struct sunrpc_net { | 9 | struct sunrpc_net { |
8 | struct proc_dir_entry *proc_net_rpc; | 10 | struct proc_dir_entry *proc_net_rpc; |
11 | struct cache_detail *ip_map_cache; | ||
9 | }; | 12 | }; |
10 | 13 | ||
11 | extern int sunrpc_net_id; | 14 | extern int sunrpc_net_id; |
12 | 15 | ||
16 | int ip_map_cache_create(struct net *); | ||
17 | void ip_map_cache_destroy(struct net *); | ||
18 | |||
13 | #endif | 19 | #endif |
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index c076af8535db..9d0809160994 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -34,14 +34,21 @@ static __net_init int sunrpc_init_net(struct net *net) | |||
34 | if (err) | 34 | if (err) |
35 | goto err_proc; | 35 | goto err_proc; |
36 | 36 | ||
37 | err = ip_map_cache_create(net); | ||
38 | if (err) | ||
39 | goto err_ipmap; | ||
40 | |||
37 | return 0; | 41 | return 0; |
38 | 42 | ||
43 | err_ipmap: | ||
44 | rpc_proc_exit(net); | ||
39 | err_proc: | 45 | err_proc: |
40 | return err; | 46 | return err; |
41 | } | 47 | } |
42 | 48 | ||
43 | static __net_exit void sunrpc_exit_net(struct net *net) | 49 | static __net_exit void sunrpc_exit_net(struct net *net) |
44 | { | 50 | { |
51 | ip_map_cache_destroy(net); | ||
45 | rpc_proc_exit(net); | 52 | rpc_proc_exit(net); |
46 | } | 53 | } |
47 | 54 | ||
@@ -52,7 +59,7 @@ static struct pernet_operations sunrpc_net_ops = { | |||
52 | .size = sizeof(struct sunrpc_net), | 59 | .size = sizeof(struct sunrpc_net), |
53 | }; | 60 | }; |
54 | 61 | ||
55 | extern struct cache_detail ip_map_cache, unix_gid_cache; | 62 | extern struct cache_detail unix_gid_cache; |
56 | 63 | ||
57 | extern void cleanup_rpcb_clnt(void); | 64 | extern void cleanup_rpcb_clnt(void); |
58 | 65 | ||
@@ -77,7 +84,6 @@ init_sunrpc(void) | |||
77 | #ifdef RPC_DEBUG | 84 | #ifdef RPC_DEBUG |
78 | rpc_register_sysctl(); | 85 | rpc_register_sysctl(); |
79 | #endif | 86 | #endif |
80 | cache_register(&ip_map_cache); | ||
81 | cache_register(&unix_gid_cache); | 87 | cache_register(&unix_gid_cache); |
82 | svc_init_xprt_sock(); /* svc sock transport */ | 88 | svc_init_xprt_sock(); /* svc sock transport */ |
83 | init_socket_xprt(); /* clnt sock transport */ | 89 | init_socket_xprt(); /* clnt sock transport */ |
@@ -102,7 +108,6 @@ cleanup_sunrpc(void) | |||
102 | svc_cleanup_xprt_sock(); | 108 | svc_cleanup_xprt_sock(); |
103 | unregister_rpc_pipefs(); | 109 | unregister_rpc_pipefs(); |
104 | rpc_destroy_mempool(); | 110 | rpc_destroy_mempool(); |
105 | cache_unregister(&ip_map_cache); | ||
106 | cache_unregister(&unix_gid_cache); | 111 | cache_unregister(&unix_gid_cache); |
107 | unregister_pernet_subsys(&sunrpc_net_ops); | 112 | unregister_pernet_subsys(&sunrpc_net_ops); |
108 | #ifdef RPC_DEBUG | 113 | #ifdef RPC_DEBUG |
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 2a76c7cf603e..8b378f91f255 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -18,6 +18,8 @@ | |||
18 | 18 | ||
19 | #include <linux/sunrpc/clnt.h> | 19 | #include <linux/sunrpc/clnt.h> |
20 | 20 | ||
21 | #include "netns.h" | ||
22 | |||
21 | /* | 23 | /* |
22 | * AUTHUNIX and AUTHNULL credentials are both handled here. | 24 | * AUTHUNIX and AUTHNULL credentials are both handled here. |
23 | * AUTHNULL is treated just like AUTHUNIX except that the uid/gid | 25 | * AUTHNULL is treated just like AUTHUNIX except that the uid/gid |
@@ -92,7 +94,6 @@ struct ip_map { | |||
92 | struct unix_domain *m_client; | 94 | struct unix_domain *m_client; |
93 | int m_add_change; | 95 | int m_add_change; |
94 | }; | 96 | }; |
95 | static struct cache_head *ip_table[IP_HASHMAX]; | ||
96 | 97 | ||
97 | static void ip_map_put(struct kref *kref) | 98 | static void ip_map_put(struct kref *kref) |
98 | { | 99 | { |
@@ -294,21 +295,6 @@ static int ip_map_show(struct seq_file *m, | |||
294 | } | 295 | } |
295 | 296 | ||
296 | 297 | ||
297 | struct cache_detail ip_map_cache = { | ||
298 | .owner = THIS_MODULE, | ||
299 | .hash_size = IP_HASHMAX, | ||
300 | .hash_table = ip_table, | ||
301 | .name = "auth.unix.ip", | ||
302 | .cache_put = ip_map_put, | ||
303 | .cache_upcall = ip_map_upcall, | ||
304 | .cache_parse = ip_map_parse, | ||
305 | .cache_show = ip_map_show, | ||
306 | .match = ip_map_match, | ||
307 | .init = ip_map_init, | ||
308 | .update = update, | ||
309 | .alloc = ip_map_alloc, | ||
310 | }; | ||
311 | |||
312 | static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, | 298 | static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, |
313 | struct in6_addr *addr) | 299 | struct in6_addr *addr) |
314 | { | 300 | { |
@@ -330,7 +316,10 @@ static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, | |||
330 | static inline struct ip_map *ip_map_lookup(struct net *net, char *class, | 316 | static inline struct ip_map *ip_map_lookup(struct net *net, char *class, |
331 | struct in6_addr *addr) | 317 | struct in6_addr *addr) |
332 | { | 318 | { |
333 | return __ip_map_lookup(&ip_map_cache, class, addr); | 319 | struct sunrpc_net *sn; |
320 | |||
321 | sn = net_generic(net, sunrpc_net_id); | ||
322 | return __ip_map_lookup(sn->ip_map_cache, class, addr); | ||
334 | } | 323 | } |
335 | 324 | ||
336 | static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, | 325 | static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, |
@@ -364,7 +353,10 @@ static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, | |||
364 | static inline int ip_map_update(struct net *net, struct ip_map *ipm, | 353 | static inline int ip_map_update(struct net *net, struct ip_map *ipm, |
365 | struct unix_domain *udom, time_t expiry) | 354 | struct unix_domain *udom, time_t expiry) |
366 | { | 355 | { |
367 | return __ip_map_update(&ip_map_cache, ipm, udom, expiry); | 356 | struct sunrpc_net *sn; |
357 | |||
358 | sn = net_generic(net, sunrpc_net_id); | ||
359 | return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry); | ||
368 | } | 360 | } |
369 | 361 | ||
370 | int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom) | 362 | int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom) |
@@ -400,12 +392,14 @@ struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr) | |||
400 | { | 392 | { |
401 | struct ip_map *ipm; | 393 | struct ip_map *ipm; |
402 | struct auth_domain *rv; | 394 | struct auth_domain *rv; |
395 | struct sunrpc_net *sn; | ||
403 | 396 | ||
397 | sn = net_generic(net, sunrpc_net_id); | ||
404 | ipm = ip_map_lookup(net, "nfsd", addr); | 398 | ipm = ip_map_lookup(net, "nfsd", addr); |
405 | 399 | ||
406 | if (!ipm) | 400 | if (!ipm) |
407 | return NULL; | 401 | return NULL; |
408 | if (cache_check(&ip_map_cache, &ipm->h, NULL)) | 402 | if (cache_check(sn->ip_map_cache, &ipm->h, NULL)) |
409 | return NULL; | 403 | return NULL; |
410 | 404 | ||
411 | if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) { | 405 | if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) { |
@@ -416,14 +410,21 @@ struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr) | |||
416 | rv = &ipm->m_client->h; | 410 | rv = &ipm->m_client->h; |
417 | kref_get(&rv->ref); | 411 | kref_get(&rv->ref); |
418 | } | 412 | } |
419 | cache_put(&ipm->h, &ip_map_cache); | 413 | cache_put(&ipm->h, sn->ip_map_cache); |
420 | return rv; | 414 | return rv; |
421 | } | 415 | } |
422 | EXPORT_SYMBOL_GPL(auth_unix_lookup); | 416 | EXPORT_SYMBOL_GPL(auth_unix_lookup); |
423 | 417 | ||
424 | void svcauth_unix_purge(void) | 418 | void svcauth_unix_purge(void) |
425 | { | 419 | { |
426 | cache_purge(&ip_map_cache); | 420 | struct net *net; |
421 | |||
422 | for_each_net(net) { | ||
423 | struct sunrpc_net *sn; | ||
424 | |||
425 | sn = net_generic(net, sunrpc_net_id); | ||
426 | cache_purge(sn->ip_map_cache); | ||
427 | } | ||
427 | } | 428 | } |
428 | EXPORT_SYMBOL_GPL(svcauth_unix_purge); | 429 | EXPORT_SYMBOL_GPL(svcauth_unix_purge); |
429 | 430 | ||
@@ -431,6 +432,7 @@ static inline struct ip_map * | |||
431 | ip_map_cached_get(struct svc_xprt *xprt) | 432 | ip_map_cached_get(struct svc_xprt *xprt) |
432 | { | 433 | { |
433 | struct ip_map *ipm = NULL; | 434 | struct ip_map *ipm = NULL; |
435 | struct sunrpc_net *sn; | ||
434 | 436 | ||
435 | if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) { | 437 | if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) { |
436 | spin_lock(&xprt->xpt_lock); | 438 | spin_lock(&xprt->xpt_lock); |
@@ -442,9 +444,10 @@ ip_map_cached_get(struct svc_xprt *xprt) | |||
442 | * remembered, e.g. by a second mount from the | 444 | * remembered, e.g. by a second mount from the |
443 | * same IP address. | 445 | * same IP address. |
444 | */ | 446 | */ |
447 | sn = net_generic(xprt->xpt_net, sunrpc_net_id); | ||
445 | xprt->xpt_auth_cache = NULL; | 448 | xprt->xpt_auth_cache = NULL; |
446 | spin_unlock(&xprt->xpt_lock); | 449 | spin_unlock(&xprt->xpt_lock); |
447 | cache_put(&ipm->h, &ip_map_cache); | 450 | cache_put(&ipm->h, sn->ip_map_cache); |
448 | return NULL; | 451 | return NULL; |
449 | } | 452 | } |
450 | cache_get(&ipm->h); | 453 | cache_get(&ipm->h); |
@@ -466,8 +469,12 @@ ip_map_cached_put(struct svc_xprt *xprt, struct ip_map *ipm) | |||
466 | } | 469 | } |
467 | spin_unlock(&xprt->xpt_lock); | 470 | spin_unlock(&xprt->xpt_lock); |
468 | } | 471 | } |
469 | if (ipm) | 472 | if (ipm) { |
470 | cache_put(&ipm->h, &ip_map_cache); | 473 | struct sunrpc_net *sn; |
474 | |||
475 | sn = net_generic(xprt->xpt_net, sunrpc_net_id); | ||
476 | cache_put(&ipm->h, sn->ip_map_cache); | ||
477 | } | ||
471 | } | 478 | } |
472 | 479 | ||
473 | void | 480 | void |
@@ -476,8 +483,12 @@ svcauth_unix_info_release(struct svc_xprt *xpt) | |||
476 | struct ip_map *ipm; | 483 | struct ip_map *ipm; |
477 | 484 | ||
478 | ipm = xpt->xpt_auth_cache; | 485 | ipm = xpt->xpt_auth_cache; |
479 | if (ipm != NULL) | 486 | if (ipm != NULL) { |
480 | cache_put(&ipm->h, &ip_map_cache); | 487 | struct sunrpc_net *sn; |
488 | |||
489 | sn = net_generic(xpt->xpt_net, sunrpc_net_id); | ||
490 | cache_put(&ipm->h, sn->ip_map_cache); | ||
491 | } | ||
481 | } | 492 | } |
482 | 493 | ||
483 | /**************************************************************************** | 494 | /**************************************************************************** |
@@ -707,6 +718,8 @@ svcauth_unix_set_client(struct svc_rqst *rqstp) | |||
707 | struct group_info *gi; | 718 | struct group_info *gi; |
708 | struct svc_cred *cred = &rqstp->rq_cred; | 719 | struct svc_cred *cred = &rqstp->rq_cred; |
709 | struct svc_xprt *xprt = rqstp->rq_xprt; | 720 | struct svc_xprt *xprt = rqstp->rq_xprt; |
721 | struct net *net = xprt->xpt_net; | ||
722 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
710 | 723 | ||
711 | switch (rqstp->rq_addr.ss_family) { | 724 | switch (rqstp->rq_addr.ss_family) { |
712 | case AF_INET: | 725 | case AF_INET: |
@@ -727,13 +740,13 @@ svcauth_unix_set_client(struct svc_rqst *rqstp) | |||
727 | 740 | ||
728 | ipm = ip_map_cached_get(xprt); | 741 | ipm = ip_map_cached_get(xprt); |
729 | if (ipm == NULL) | 742 | if (ipm == NULL) |
730 | ipm = ip_map_lookup(&init_net, rqstp->rq_server->sv_program->pg_class, | 743 | ipm = __ip_map_lookup(sn->ip_map_cache, rqstp->rq_server->sv_program->pg_class, |
731 | &sin6->sin6_addr); | 744 | &sin6->sin6_addr); |
732 | 745 | ||
733 | if (ipm == NULL) | 746 | if (ipm == NULL) |
734 | return SVC_DENIED; | 747 | return SVC_DENIED; |
735 | 748 | ||
736 | switch (cache_check(&ip_map_cache, &ipm->h, &rqstp->rq_chandle)) { | 749 | switch (cache_check(sn->ip_map_cache, &ipm->h, &rqstp->rq_chandle)) { |
737 | default: | 750 | default: |
738 | BUG(); | 751 | BUG(); |
739 | case -ETIMEDOUT: | 752 | case -ETIMEDOUT: |
@@ -905,3 +918,56 @@ struct auth_ops svcauth_unix = { | |||
905 | .set_client = svcauth_unix_set_client, | 918 | .set_client = svcauth_unix_set_client, |
906 | }; | 919 | }; |
907 | 920 | ||
921 | int ip_map_cache_create(struct net *net) | ||
922 | { | ||
923 | int err = -ENOMEM; | ||
924 | struct cache_detail *cd; | ||
925 | struct cache_head **tbl; | ||
926 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
927 | |||
928 | cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL); | ||
929 | if (cd == NULL) | ||
930 | goto err_cd; | ||
931 | |||
932 | tbl = kzalloc(IP_HASHMAX * sizeof(struct cache_head *), GFP_KERNEL); | ||
933 | if (tbl == NULL) | ||
934 | goto err_tbl; | ||
935 | |||
936 | cd->owner = THIS_MODULE, | ||
937 | cd->hash_size = IP_HASHMAX, | ||
938 | cd->hash_table = tbl, | ||
939 | cd->name = "auth.unix.ip", | ||
940 | cd->cache_put = ip_map_put, | ||
941 | cd->cache_upcall = ip_map_upcall, | ||
942 | cd->cache_parse = ip_map_parse, | ||
943 | cd->cache_show = ip_map_show, | ||
944 | cd->match = ip_map_match, | ||
945 | cd->init = ip_map_init, | ||
946 | cd->update = update, | ||
947 | cd->alloc = ip_map_alloc, | ||
948 | |||
949 | err = cache_register_net(cd, net); | ||
950 | if (err) | ||
951 | goto err_reg; | ||
952 | |||
953 | sn->ip_map_cache = cd; | ||
954 | return 0; | ||
955 | |||
956 | err_reg: | ||
957 | kfree(tbl); | ||
958 | err_tbl: | ||
959 | kfree(cd); | ||
960 | err_cd: | ||
961 | return err; | ||
962 | } | ||
963 | |||
964 | void ip_map_cache_destroy(struct net *net) | ||
965 | { | ||
966 | struct sunrpc_net *sn; | ||
967 | |||
968 | sn = net_generic(net, sunrpc_net_id); | ||
969 | cache_purge(sn->ip_map_cache); | ||
970 | cache_unregister_net(sn->ip_map_cache, net); | ||
971 | kfree(sn->ip_map_cache->hash_table); | ||
972 | kfree(sn->ip_map_cache); | ||
973 | } | ||