Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Pavel Emelyanov and committed by
J. Bruce Fields
90d51b02 4f42d0d5

+108 -31
+6
net/sunrpc/netns.h
··· 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
+8 -3
net/sunrpc/sunrpc_syms.c
··· 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 ··· 59 52 .size = sizeof(struct sunrpc_net), 60 53 }; 61 54 62 - extern struct cache_detail ip_map_cache, unix_gid_cache; 55 + extern struct cache_detail unix_gid_cache; 63 56 64 57 extern void cleanup_rpcb_clnt(void); 65 58 ··· 84 77 #ifdef RPC_DEBUG 85 78 rpc_register_sysctl(); 86 79 #endif 87 - cache_register(&ip_map_cache); 88 80 cache_register(&unix_gid_cache); 89 81 svc_init_xprt_sock(); /* svc sock transport */ 90 82 init_socket_xprt(); /* clnt sock transport */ ··· 108 102 svc_cleanup_xprt_sock(); 109 103 unregister_rpc_pipefs(); 110 104 rpc_destroy_mempool(); 111 - cache_unregister(&ip_map_cache); 112 105 cache_unregister(&unix_gid_cache); 113 106 unregister_pernet_subsys(&sunrpc_net_ops); 114 107 #ifdef RPC_DEBUG
+94 -28
net/sunrpc/svcauth_unix.c
··· 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 ··· 94 92 struct unix_domain *m_client; 95 93 int m_add_change; 96 94 }; 97 - static struct cache_head *ip_table[IP_HASHMAX]; 98 95 99 96 static void ip_map_put(struct kref *kref) 100 97 { ··· 295 294 } 296 295 297 296 298 - struct cache_detail ip_map_cache = { 299 - .owner = THIS_MODULE, 300 - .hash_size = IP_HASHMAX, 301 - .hash_table = ip_table, 302 - .name = "auth.unix.ip", 303 - .cache_put = ip_map_put, 304 - .cache_upcall = ip_map_upcall, 305 - .cache_parse = ip_map_parse, 306 - .cache_show = ip_map_show, 307 - .match = ip_map_match, 308 - .init = ip_map_init, 309 - .update = update, 310 - .alloc = ip_map_alloc, 311 - }; 312 - 313 297 static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, 314 298 struct in6_addr *addr) 315 299 { ··· 316 330 static inline struct ip_map *ip_map_lookup(struct net *net, char *class, 317 331 struct in6_addr *addr) 318 332 { 319 - return __ip_map_lookup(&ip_map_cache, class, addr); 333 + struct sunrpc_net *sn; 334 + 335 + sn = net_generic(net, sunrpc_net_id); 336 + return __ip_map_lookup(sn->ip_map_cache, class, addr); 320 337 } 321 338 322 339 static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, ··· 353 364 static inline int ip_map_update(struct net *net, struct ip_map *ipm, 354 365 struct unix_domain *udom, time_t expiry) 355 366 { 356 - return __ip_map_update(&ip_map_cache, ipm, udom, expiry); 367 + struct sunrpc_net *sn; 368 + 369 + sn = net_generic(net, sunrpc_net_id); 370 + return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry); 357 371 } 358 372 359 373 int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom) ··· 392 400 { 393 401 struct ip_map *ipm; 394 402 struct auth_domain *rv; 403 + struct sunrpc_net *sn; 395 404 405 + sn = net_generic(net, sunrpc_net_id); 396 406 ipm = ip_map_lookup(net, "nfsd", addr); 397 407 398 408 if (!ipm) 399 409 return NULL; 400 - if (cache_check(&ip_map_cache, &ipm->h, NULL)) 410 + if (cache_check(sn->ip_map_cache, &ipm->h, NULL)) 401 411 return NULL; 402 412 403 413 if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) { ··· 410 416 rv = &ipm->m_client->h; 411 417 kref_get(&rv->ref); 412 418 } 413 - cache_put(&ipm->h, &ip_map_cache); 419 + cache_put(&ipm->h, sn->ip_map_cache); 414 420 return rv; 415 421 } 416 422 EXPORT_SYMBOL_GPL(auth_unix_lookup); 417 423 418 424 void svcauth_unix_purge(void) 419 425 { 420 - cache_purge(&ip_map_cache); 426 + struct net *net; 427 + 428 + for_each_net(net) { 429 + struct sunrpc_net *sn; 430 + 431 + sn = net_generic(net, sunrpc_net_id); 432 + cache_purge(sn->ip_map_cache); 433 + } 421 434 } 422 435 EXPORT_SYMBOL_GPL(svcauth_unix_purge); 423 436 ··· 432 431 ip_map_cached_get(struct svc_xprt *xprt) 433 432 { 434 433 struct ip_map *ipm = NULL; 434 + struct sunrpc_net *sn; 435 435 436 436 if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) { 437 437 spin_lock(&xprt->xpt_lock); ··· 444 442 * remembered, e.g. by a second mount from the 445 443 * same IP address. 446 444 */ 445 + sn = net_generic(xprt->xpt_net, sunrpc_net_id); 447 446 xprt->xpt_auth_cache = NULL; 448 447 spin_unlock(&xprt->xpt_lock); 449 - cache_put(&ipm->h, &ip_map_cache); 448 + cache_put(&ipm->h, sn->ip_map_cache); 450 449 return NULL; 451 450 } 452 451 cache_get(&ipm->h); ··· 469 466 } 470 467 spin_unlock(&xprt->xpt_lock); 471 468 } 472 - if (ipm) 473 - cache_put(&ipm->h, &ip_map_cache); 469 + if (ipm) { 470 + struct sunrpc_net *sn; 471 + 472 + sn = net_generic(xprt->xpt_net, sunrpc_net_id); 473 + cache_put(&ipm->h, sn->ip_map_cache); 474 + } 474 475 } 475 476 476 477 void ··· 483 476 struct ip_map *ipm; 484 477 485 478 ipm = xpt->xpt_auth_cache; 486 - if (ipm != NULL) 487 - cache_put(&ipm->h, &ip_map_cache); 479 + if (ipm != NULL) { 480 + struct sunrpc_net *sn; 481 + 482 + sn = net_generic(xpt->xpt_net, sunrpc_net_id); 483 + cache_put(&ipm->h, sn->ip_map_cache); 484 + } 488 485 } 489 486 490 487 /**************************************************************************** ··· 718 707 struct group_info *gi; 719 708 struct svc_cred *cred = &rqstp->rq_cred; 720 709 struct svc_xprt *xprt = rqstp->rq_xprt; 710 + struct net *net = xprt->xpt_net; 711 + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 721 712 722 713 switch (rqstp->rq_addr.ss_family) { 723 714 case AF_INET: ··· 740 727 741 728 ipm = ip_map_cached_get(xprt); 742 729 if (ipm == NULL) 743 - ipm = ip_map_lookup(&init_net, rqstp->rq_server->sv_program->pg_class, 730 + ipm = __ip_map_lookup(sn->ip_map_cache, rqstp->rq_server->sv_program->pg_class, 744 731 &sin6->sin6_addr); 745 732 746 733 if (ipm == NULL) 747 734 return SVC_DENIED; 748 735 749 - switch (cache_check(&ip_map_cache, &ipm->h, &rqstp->rq_chandle)) { 736 + switch (cache_check(sn->ip_map_cache, &ipm->h, &rqstp->rq_chandle)) { 750 737 default: 751 738 BUG(); 752 739 case -ETIMEDOUT: ··· 918 905 .set_client = svcauth_unix_set_client, 919 906 }; 920 907 908 + int ip_map_cache_create(struct net *net) 909 + { 910 + int err = -ENOMEM; 911 + struct cache_detail *cd; 912 + struct cache_head **tbl; 913 + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 914 + 915 + cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL); 916 + if (cd == NULL) 917 + goto err_cd; 918 + 919 + tbl = kzalloc(IP_HASHMAX * sizeof(struct cache_head *), GFP_KERNEL); 920 + if (tbl == NULL) 921 + goto err_tbl; 922 + 923 + cd->owner = THIS_MODULE, 924 + cd->hash_size = IP_HASHMAX, 925 + cd->hash_table = tbl, 926 + cd->name = "auth.unix.ip", 927 + cd->cache_put = ip_map_put, 928 + cd->cache_upcall = ip_map_upcall, 929 + cd->cache_parse = ip_map_parse, 930 + cd->cache_show = ip_map_show, 931 + cd->match = ip_map_match, 932 + cd->init = ip_map_init, 933 + cd->update = update, 934 + cd->alloc = ip_map_alloc, 935 + 936 + err = cache_register_net(cd, net); 937 + if (err) 938 + goto err_reg; 939 + 940 + sn->ip_map_cache = cd; 941 + return 0; 942 + 943 + err_reg: 944 + kfree(tbl); 945 + err_tbl: 946 + kfree(cd); 947 + err_cd: 948 + return err; 949 + } 950 + 951 + void ip_map_cache_destroy(struct net *net) 952 + { 953 + struct sunrpc_net *sn; 954 + 955 + sn = net_generic(net, sunrpc_net_id); 956 + cache_purge(sn->ip_map_cache); 957 + cache_unregister_net(sn->ip_map_cache, net); 958 + kfree(sn->ip_map_cache->hash_table); 959 + kfree(sn->ip_map_cache); 960 + }