]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv6/ip6_fib.c
[NETNS][IPV6] ip6_fib - gc timer per namespace
[net-next-2.6.git] / net / ipv6 / ip6_fib.c
index 77ad1002c90479b05eb64f8c0b48f75ef6d49584..4aa67988f518a734ed88e1ddc079e41643af08cc 100644 (file)
@@ -95,8 +95,6 @@ static __u32 rt_sernum;
 
 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 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
        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 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
        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 @@ void fib6_run_gc(unsigned long expires, struct net *net)
        } 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 @@ void fib6_run_gc(unsigned long expires, struct net *net)
        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 void fib6_gc_timer_cb(unsigned long arg)
 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 @@ out_fib6_main_tbl:
 #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 @@ static struct pernet_operations fib6_net_ops = {
 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 @@ int __init fib6_init(void)
        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:
 
 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 @@ out_kmem_cache_create:
 
 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);
 }