ipv6/addrconf: allocate a per netns hash table
Add a per netns hash table and a dedicated spinlock, first step to get rid of the global inet6_addr_lst[] one. Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: David Ahern <dsahern@kernel.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
b2309a71c1
commit
21a216a8fc
2 changed files with 24 additions and 0 deletions
|
@ -92,6 +92,10 @@ struct netns_ipv6 {
|
||||||
struct sock *tcp_sk;
|
struct sock *tcp_sk;
|
||||||
struct sock *igmp_sk;
|
struct sock *igmp_sk;
|
||||||
struct sock *mc_autojoin_sk;
|
struct sock *mc_autojoin_sk;
|
||||||
|
|
||||||
|
struct hlist_head *inet6_addr_lst;
|
||||||
|
spinlock_t addrconf_hash_lock;
|
||||||
|
|
||||||
#ifdef CONFIG_IPV6_MROUTE
|
#ifdef CONFIG_IPV6_MROUTE
|
||||||
#ifndef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
|
#ifndef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
|
||||||
struct mr_table *mrt6;
|
struct mr_table *mrt6;
|
||||||
|
|
|
@ -7111,6 +7111,13 @@ static int __net_init addrconf_init_net(struct net *net)
|
||||||
int err = -ENOMEM;
|
int err = -ENOMEM;
|
||||||
struct ipv6_devconf *all, *dflt;
|
struct ipv6_devconf *all, *dflt;
|
||||||
|
|
||||||
|
spin_lock_init(&net->ipv6.addrconf_hash_lock);
|
||||||
|
net->ipv6.inet6_addr_lst = kcalloc(IN6_ADDR_HSIZE,
|
||||||
|
sizeof(struct hlist_head),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!net->ipv6.inet6_addr_lst)
|
||||||
|
goto err_alloc_addr;
|
||||||
|
|
||||||
all = kmemdup(&ipv6_devconf, sizeof(ipv6_devconf), GFP_KERNEL);
|
all = kmemdup(&ipv6_devconf, sizeof(ipv6_devconf), GFP_KERNEL);
|
||||||
if (!all)
|
if (!all)
|
||||||
goto err_alloc_all;
|
goto err_alloc_all;
|
||||||
|
@ -7172,11 +7179,15 @@ err_reg_all:
|
||||||
err_alloc_dflt:
|
err_alloc_dflt:
|
||||||
kfree(all);
|
kfree(all);
|
||||||
err_alloc_all:
|
err_alloc_all:
|
||||||
|
kfree(net->ipv6.inet6_addr_lst);
|
||||||
|
err_alloc_addr:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit addrconf_exit_net(struct net *net)
|
static void __net_exit addrconf_exit_net(struct net *net)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
#ifdef CONFIG_SYSCTL
|
#ifdef CONFIG_SYSCTL
|
||||||
__addrconf_sysctl_unregister(net, net->ipv6.devconf_dflt,
|
__addrconf_sysctl_unregister(net, net->ipv6.devconf_dflt,
|
||||||
NETCONFA_IFINDEX_DEFAULT);
|
NETCONFA_IFINDEX_DEFAULT);
|
||||||
|
@ -7187,6 +7198,15 @@ static void __net_exit addrconf_exit_net(struct net *net)
|
||||||
net->ipv6.devconf_dflt = NULL;
|
net->ipv6.devconf_dflt = NULL;
|
||||||
kfree(net->ipv6.devconf_all);
|
kfree(net->ipv6.devconf_all);
|
||||||
net->ipv6.devconf_all = NULL;
|
net->ipv6.devconf_all = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check hash table, then free it.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < IN6_ADDR_HSIZE; i++)
|
||||||
|
WARN_ON_ONCE(!hlist_empty(&net->ipv6.inet6_addr_lst[i]));
|
||||||
|
|
||||||
|
kfree(net->ipv6.inet6_addr_lst);
|
||||||
|
net->ipv6.inet6_addr_lst = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pernet_operations addrconf_ops = {
|
static struct pernet_operations addrconf_ops = {
|
||||||
|
|
Loading…
Add table
Reference in a new issue