Commit 90d51b02fd702d969eb05bd9d4ecc954759fbe23
Committed by
J. Bruce Fields
1 parent
4f42d0d53c
Exists in
master
and in
4 other branches
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>
Showing 3 changed files with 108 additions and 31 deletions Side-by-side Diff
net/sunrpc/netns.h
... | ... | @@ -4,11 +4,17 @@ |
4 | 4 | #include <net/net_namespace.h> |
5 | 5 | #include <net/netns/generic.h> |
6 | 6 | |
7 | +struct cache_detail; | |
8 | + | |
7 | 9 | struct sunrpc_net { |
8 | 10 | struct proc_dir_entry *proc_net_rpc; |
11 | + struct cache_detail *ip_map_cache; | |
9 | 12 | }; |
10 | 13 | |
11 | 14 | extern int sunrpc_net_id; |
15 | + | |
16 | +int ip_map_cache_create(struct net *); | |
17 | +void ip_map_cache_destroy(struct net *); | |
12 | 18 | |
13 | 19 | #endif |
net/sunrpc/sunrpc_syms.c
... | ... | @@ -34,14 +34,21 @@ |
34 | 34 | if (err) |
35 | 35 | goto err_proc; |
36 | 36 | |
37 | + err = ip_map_cache_create(net); | |
38 | + if (err) | |
39 | + goto err_ipmap; | |
40 | + | |
37 | 41 | return 0; |
38 | 42 | |
43 | +err_ipmap: | |
44 | + rpc_proc_exit(net); | |
39 | 45 | err_proc: |
40 | 46 | return err; |
41 | 47 | } |
42 | 48 | |
43 | 49 | static __net_exit void sunrpc_exit_net(struct net *net) |
44 | 50 | { |
51 | + ip_map_cache_destroy(net); | |
45 | 52 | rpc_proc_exit(net); |
46 | 53 | } |
47 | 54 | |
... | ... | @@ -52,7 +59,7 @@ |
52 | 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 | 64 | extern void cleanup_rpcb_clnt(void); |
58 | 65 | |
... | ... | @@ -77,7 +84,6 @@ |
77 | 84 | #ifdef RPC_DEBUG |
78 | 85 | rpc_register_sysctl(); |
79 | 86 | #endif |
80 | - cache_register(&ip_map_cache); | |
81 | 87 | cache_register(&unix_gid_cache); |
82 | 88 | svc_init_xprt_sock(); /* svc sock transport */ |
83 | 89 | init_socket_xprt(); /* clnt sock transport */ |
... | ... | @@ -102,7 +108,6 @@ |
102 | 108 | svc_cleanup_xprt_sock(); |
103 | 109 | unregister_rpc_pipefs(); |
104 | 110 | rpc_destroy_mempool(); |
105 | - cache_unregister(&ip_map_cache); | |
106 | 111 | cache_unregister(&unix_gid_cache); |
107 | 112 | unregister_pernet_subsys(&sunrpc_net_ops); |
108 | 113 | #ifdef RPC_DEBUG |
net/sunrpc/svcauth_unix.c
... | ... | @@ -18,6 +18,8 @@ |
18 | 18 | |
19 | 19 | #include <linux/sunrpc/clnt.h> |
20 | 20 | |
21 | +#include "netns.h" | |
22 | + | |
21 | 23 | /* |
22 | 24 | * AUTHUNIX and AUTHNULL credentials are both handled here. |
23 | 25 | * AUTHNULL is treated just like AUTHUNIX except that the uid/gid |
... | ... | @@ -92,7 +94,6 @@ |
92 | 94 | struct unix_domain *m_client; |
93 | 95 | int m_add_change; |
94 | 96 | }; |
95 | -static struct cache_head *ip_table[IP_HASHMAX]; | |
96 | 97 | |
97 | 98 | static void ip_map_put(struct kref *kref) |
98 | 99 | { |
... | ... | @@ -294,21 +295,6 @@ |
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 | 298 | static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, |
313 | 299 | struct in6_addr *addr) |
314 | 300 | { |
... | ... | @@ -330,7 +316,10 @@ |
330 | 316 | static inline struct ip_map *ip_map_lookup(struct net *net, char *class, |
331 | 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 | 325 | static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, |
... | ... | @@ -364,7 +353,10 @@ |
364 | 353 | static inline int ip_map_update(struct net *net, struct ip_map *ipm, |
365 | 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 | 362 | int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom) |
371 | 363 | |
372 | 364 | |
... | ... | @@ -400,12 +392,14 @@ |
400 | 392 | { |
401 | 393 | struct ip_map *ipm; |
402 | 394 | struct auth_domain *rv; |
395 | + struct sunrpc_net *sn; | |
403 | 396 | |
397 | + sn = net_generic(net, sunrpc_net_id); | |
404 | 398 | ipm = ip_map_lookup(net, "nfsd", addr); |
405 | 399 | |
406 | 400 | if (!ipm) |
407 | 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 | 403 | return NULL; |
410 | 404 | |
411 | 405 | if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) { |
412 | 406 | |
... | ... | @@ -416,14 +410,21 @@ |
416 | 410 | rv = &ipm->m_client->h; |
417 | 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 | 414 | return rv; |
421 | 415 | } |
422 | 416 | EXPORT_SYMBOL_GPL(auth_unix_lookup); |
423 | 417 | |
424 | 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 | 429 | EXPORT_SYMBOL_GPL(svcauth_unix_purge); |
429 | 430 | |
... | ... | @@ -431,6 +432,7 @@ |
431 | 432 | ip_map_cached_get(struct svc_xprt *xprt) |
432 | 433 | { |
433 | 434 | struct ip_map *ipm = NULL; |
435 | + struct sunrpc_net *sn; | |
434 | 436 | |
435 | 437 | if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) { |
436 | 438 | spin_lock(&xprt->xpt_lock); |
437 | 439 | |
... | ... | @@ -442,9 +444,10 @@ |
442 | 444 | * remembered, e.g. by a second mount from the |
443 | 445 | * same IP address. |
444 | 446 | */ |
447 | + sn = net_generic(xprt->xpt_net, sunrpc_net_id); | |
445 | 448 | xprt->xpt_auth_cache = NULL; |
446 | 449 | spin_unlock(&xprt->xpt_lock); |
447 | - cache_put(&ipm->h, &ip_map_cache); | |
450 | + cache_put(&ipm->h, sn->ip_map_cache); | |
448 | 451 | return NULL; |
449 | 452 | } |
450 | 453 | cache_get(&ipm->h); |
... | ... | @@ -466,8 +469,12 @@ |
466 | 469 | } |
467 | 470 | spin_unlock(&xprt->xpt_lock); |
468 | 471 | } |
469 | - if (ipm) | |
470 | - cache_put(&ipm->h, &ip_map_cache); | |
472 | + if (ipm) { | |
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 | 480 | void |
... | ... | @@ -476,8 +483,12 @@ |
476 | 483 | struct ip_map *ipm; |
477 | 484 | |
478 | 485 | ipm = xpt->xpt_auth_cache; |
479 | - if (ipm != NULL) | |
480 | - cache_put(&ipm->h, &ip_map_cache); | |
486 | + if (ipm != NULL) { | |
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 @@ |
707 | 718 | struct group_info *gi; |
708 | 719 | struct svc_cred *cred = &rqstp->rq_cred; |
709 | 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 | 724 | switch (rqstp->rq_addr.ss_family) { |
712 | 725 | case AF_INET: |
713 | 726 | |
... | ... | @@ -727,13 +740,13 @@ |
727 | 740 | |
728 | 741 | ipm = ip_map_cached_get(xprt); |
729 | 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 | 744 | &sin6->sin6_addr); |
732 | 745 | |
733 | 746 | if (ipm == NULL) |
734 | 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 | 750 | default: |
738 | 751 | BUG(); |
739 | 752 | case -ETIMEDOUT: |
... | ... | @@ -904,4 +917,58 @@ |
904 | 917 | .domain_release = svcauth_unix_domain_release, |
905 | 918 | .set_client = svcauth_unix_set_client, |
906 | 919 | }; |
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 | +} |