[NETNS][IPV6] ip6_fib - gc timer per namespace
Move the timer initialization at the network namespace creation and
store the network namespace in the timer argument.
That enables multiple timers (one per network namespace) to do garbage
collecting.
Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 77ad100..4aa6798 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -95,8 +95,6 @@
static void fib6_gc_timer_cb(unsigned long arg);
-static struct timer_list *ip6_fib_timer;
-
static struct fib6_walker_t fib6_walker_list = {
.prev = &fib6_walker_list,
.next = &fib6_walker_list,
@@ -663,19 +661,19 @@
return 0;
}
-static __inline__ void fib6_start_gc(struct rt6_info *rt)
+static __inline__ void fib6_start_gc(struct net *net, struct rt6_info *rt)
{
- if (ip6_fib_timer->expires == 0 &&
+ if (net->ipv6.ip6_fib_timer->expires == 0 &&
(rt->rt6i_flags & (RTF_EXPIRES|RTF_CACHE)))
- mod_timer(ip6_fib_timer, jiffies +
- init_net.ipv6.sysctl.ip6_rt_gc_interval);
+ mod_timer(net->ipv6.ip6_fib_timer, jiffies +
+ net->ipv6.sysctl.ip6_rt_gc_interval);
}
-void fib6_force_start_gc(void)
+void fib6_force_start_gc(struct net *net)
{
- if (ip6_fib_timer->expires == 0)
- mod_timer(ip6_fib_timer, jiffies +
- init_net.ipv6.sysctl.ip6_rt_gc_interval);
+ if (net->ipv6.ip6_fib_timer->expires == 0)
+ mod_timer(net->ipv6.ip6_fib_timer, jiffies +
+ net->ipv6.sysctl.ip6_rt_gc_interval);
}
/*
@@ -762,7 +760,7 @@
err = fib6_add_rt2node(fn, rt, info);
if (err == 0) {
- fib6_start_gc(rt);
+ fib6_start_gc(info->nl_net, rt);
if (!(rt->rt6i_flags&RTF_CACHE))
fib6_prune_clones(pn, rt);
}
@@ -1443,7 +1441,7 @@
} else {
local_bh_disable();
if (!spin_trylock(&fib6_gc_lock)) {
- mod_timer(ip6_fib_timer, jiffies + HZ);
+ mod_timer(net->ipv6.ip6_fib_timer, jiffies + HZ);
local_bh_enable();
return;
}
@@ -1456,11 +1454,11 @@
fib6_clean_all(net, fib6_age, 0, NULL);
if (gc_args.more)
- mod_timer(ip6_fib_timer, jiffies +
+ mod_timer(net->ipv6.ip6_fib_timer, jiffies +
net->ipv6.sysctl.ip6_rt_gc_interval);
else {
- del_timer(ip6_fib_timer);
- ip6_fib_timer->expires = 0;
+ del_timer(net->ipv6.ip6_fib_timer);
+ net->ipv6.ip6_fib_timer->expires = 0;
}
spin_unlock_bh(&fib6_gc_lock);
}
@@ -1473,13 +1471,21 @@
static int fib6_net_init(struct net *net)
{
int ret;
+ struct timer_list *timer;
ret = -ENOMEM;
+ timer = kzalloc(sizeof(*timer), GFP_KERNEL);
+ if (!timer)
+ goto out;
+
+ setup_timer(timer, fib6_gc_timer_cb, (unsigned long)net);
+ net->ipv6.ip6_fib_timer = timer;
+
net->ipv6.fib_table_hash =
kzalloc(sizeof(*net->ipv6.fib_table_hash)*FIB_TABLE_HASHSZ,
GFP_KERNEL);
if (!net->ipv6.fib_table_hash)
- goto out;
+ goto out_timer;
net->ipv6.fib6_main_tbl = kzalloc(sizeof(*net->ipv6.fib6_main_tbl),
GFP_KERNEL);
@@ -1513,11 +1519,15 @@
#endif
out_fib_table_hash:
kfree(net->ipv6.fib_table_hash);
+out_timer:
+ kfree(timer);
goto out;
}
static void fib6_net_exit(struct net *net)
{
+ del_timer(net->ipv6.ip6_fib_timer);
+ kfree(net->ipv6.ip6_fib_timer);
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
kfree(net->ipv6.fib6_local_tbl);
#endif
@@ -1533,6 +1543,7 @@
int __init fib6_init(void)
{
int ret = -ENOMEM;
+
fib6_node_kmem = kmem_cache_create("fib6_nodes",
sizeof(struct fib6_node),
0, SLAB_HWCACHE_ALIGN,
@@ -1540,16 +1551,9 @@
if (!fib6_node_kmem)
goto out;
- ret = -ENOMEM;
- ip6_fib_timer = kzalloc(sizeof(*ip6_fib_timer), GFP_KERNEL);
- if (!ip6_fib_timer)
- goto out_kmem_cache_create;
-
- setup_timer(ip6_fib_timer, fib6_gc_timer_cb, (unsigned long)&init_net);
-
ret = register_pernet_subsys(&fib6_net_ops);
if (ret)
- goto out_timer;
+ goto out_kmem_cache_create;
ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
if (ret)
@@ -1559,8 +1563,6 @@
out_unregister_subsys:
unregister_pernet_subsys(&fib6_net_ops);
-out_timer:
- kfree(ip6_fib_timer);
out_kmem_cache_create:
kmem_cache_destroy(fib6_node_kmem);
goto out;
@@ -1568,8 +1570,6 @@
void fib6_gc_cleanup(void)
{
- del_timer(ip6_fib_timer);
- kfree(ip6_fib_timer);
unregister_pernet_subsys(&fib6_net_ops);
kmem_cache_destroy(fib6_node_kmem);
}