Commit 90d51b02fd702d969eb05bd9d4ecc954759fbe23

Authored by Pavel Emelyanov
Committed by J. Bruce Fields
1 parent 4f42d0d53c

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

... ... @@ -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 +}