diff options
author | Daniel Lezcano <dlezcano@fr.ibm.com> | 2008-03-04 02:31:11 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-03-04 02:31:11 -0500 |
commit | 63152fc0de4dfe83da543bf133cef73d885a50fc (patch) | |
tree | 2b6546f2ebd5b3fa6d48bfd7ca4085d0f96e771f | |
parent | 450d19f8ab35fad4ef2b129cb383a5b8d1326611 (diff) |
[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>
-rw-r--r-- | include/net/ip6_route.h | 2 | ||||
-rw-r--r-- | include/net/netns/ipv6.h | 1 | ||||
-rw-r--r-- | net/ipv6/ip6_fib.c | 56 | ||||
-rw-r--r-- | net/ipv6/route.c | 5 |
4 files changed, 34 insertions, 30 deletions
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index a158abe71933..79dce496f4d4 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h | |||
@@ -78,7 +78,7 @@ extern struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
78 | struct in6_addr *addr); | 78 | struct in6_addr *addr); |
79 | extern int icmp6_dst_gc(int *more); | 79 | extern int icmp6_dst_gc(int *more); |
80 | 80 | ||
81 | extern void fib6_force_start_gc(void); | 81 | extern void fib6_force_start_gc(struct net *net); |
82 | 82 | ||
83 | extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | 83 | extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, |
84 | const struct in6_addr *addr, | 84 | const struct in6_addr *addr, |
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h index b0653261c5a3..5279cd6a00ba 100644 --- a/include/net/netns/ipv6.h +++ b/include/net/netns/ipv6.h | |||
@@ -36,6 +36,7 @@ struct netns_ipv6 { | |||
36 | struct xt_table *ip6table_mangle; | 36 | struct xt_table *ip6table_mangle; |
37 | struct xt_table *ip6table_raw; | 37 | struct xt_table *ip6table_raw; |
38 | #endif | 38 | #endif |
39 | struct timer_list *ip6_fib_timer; | ||
39 | struct hlist_head *fib_table_hash; | 40 | struct hlist_head *fib_table_hash; |
40 | struct fib6_table *fib6_main_tbl; | 41 | struct fib6_table *fib6_main_tbl; |
41 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 42 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 77ad1002c904..4aa67988f518 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -95,8 +95,6 @@ static __u32 rt_sernum; | |||
95 | 95 | ||
96 | static void fib6_gc_timer_cb(unsigned long arg); | 96 | static void fib6_gc_timer_cb(unsigned long arg); |
97 | 97 | ||
98 | static struct timer_list *ip6_fib_timer; | ||
99 | |||
100 | static struct fib6_walker_t fib6_walker_list = { | 98 | static struct fib6_walker_t fib6_walker_list = { |
101 | .prev = &fib6_walker_list, | 99 | .prev = &fib6_walker_list, |
102 | .next = &fib6_walker_list, | 100 | .next = &fib6_walker_list, |
@@ -663,19 +661,19 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
663 | return 0; | 661 | return 0; |
664 | } | 662 | } |
665 | 663 | ||
666 | static __inline__ void fib6_start_gc(struct rt6_info *rt) | 664 | static __inline__ void fib6_start_gc(struct net *net, struct rt6_info *rt) |
667 | { | 665 | { |
668 | if (ip6_fib_timer->expires == 0 && | 666 | if (net->ipv6.ip6_fib_timer->expires == 0 && |
669 | (rt->rt6i_flags & (RTF_EXPIRES|RTF_CACHE))) | 667 | (rt->rt6i_flags & (RTF_EXPIRES|RTF_CACHE))) |
670 | mod_timer(ip6_fib_timer, jiffies + | 668 | mod_timer(net->ipv6.ip6_fib_timer, jiffies + |
671 | init_net.ipv6.sysctl.ip6_rt_gc_interval); | 669 | net->ipv6.sysctl.ip6_rt_gc_interval); |
672 | } | 670 | } |
673 | 671 | ||
674 | void fib6_force_start_gc(void) | 672 | void fib6_force_start_gc(struct net *net) |
675 | { | 673 | { |
676 | if (ip6_fib_timer->expires == 0) | 674 | if (net->ipv6.ip6_fib_timer->expires == 0) |
677 | mod_timer(ip6_fib_timer, jiffies + | 675 | mod_timer(net->ipv6.ip6_fib_timer, jiffies + |
678 | init_net.ipv6.sysctl.ip6_rt_gc_interval); | 676 | net->ipv6.sysctl.ip6_rt_gc_interval); |
679 | } | 677 | } |
680 | 678 | ||
681 | /* | 679 | /* |
@@ -762,7 +760,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) | |||
762 | err = fib6_add_rt2node(fn, rt, info); | 760 | err = fib6_add_rt2node(fn, rt, info); |
763 | 761 | ||
764 | if (err == 0) { | 762 | if (err == 0) { |
765 | fib6_start_gc(rt); | 763 | fib6_start_gc(info->nl_net, rt); |
766 | if (!(rt->rt6i_flags&RTF_CACHE)) | 764 | if (!(rt->rt6i_flags&RTF_CACHE)) |
767 | fib6_prune_clones(pn, rt); | 765 | fib6_prune_clones(pn, rt); |
768 | } | 766 | } |
@@ -1443,7 +1441,7 @@ void fib6_run_gc(unsigned long expires, struct net *net) | |||
1443 | } else { | 1441 | } else { |
1444 | local_bh_disable(); | 1442 | local_bh_disable(); |
1445 | if (!spin_trylock(&fib6_gc_lock)) { | 1443 | if (!spin_trylock(&fib6_gc_lock)) { |
1446 | mod_timer(ip6_fib_timer, jiffies + HZ); | 1444 | mod_timer(net->ipv6.ip6_fib_timer, jiffies + HZ); |
1447 | local_bh_enable(); | 1445 | local_bh_enable(); |
1448 | return; | 1446 | return; |
1449 | } | 1447 | } |
@@ -1456,11 +1454,11 @@ void fib6_run_gc(unsigned long expires, struct net *net) | |||
1456 | fib6_clean_all(net, fib6_age, 0, NULL); | 1454 | fib6_clean_all(net, fib6_age, 0, NULL); |
1457 | 1455 | ||
1458 | if (gc_args.more) | 1456 | if (gc_args.more) |
1459 | mod_timer(ip6_fib_timer, jiffies + | 1457 | mod_timer(net->ipv6.ip6_fib_timer, jiffies + |
1460 | net->ipv6.sysctl.ip6_rt_gc_interval); | 1458 | net->ipv6.sysctl.ip6_rt_gc_interval); |
1461 | else { | 1459 | else { |
1462 | del_timer(ip6_fib_timer); | 1460 | del_timer(net->ipv6.ip6_fib_timer); |
1463 | ip6_fib_timer->expires = 0; | 1461 | net->ipv6.ip6_fib_timer->expires = 0; |
1464 | } | 1462 | } |
1465 | spin_unlock_bh(&fib6_gc_lock); | 1463 | spin_unlock_bh(&fib6_gc_lock); |
1466 | } | 1464 | } |
@@ -1473,13 +1471,21 @@ static void fib6_gc_timer_cb(unsigned long arg) | |||
1473 | static int fib6_net_init(struct net *net) | 1471 | static int fib6_net_init(struct net *net) |
1474 | { | 1472 | { |
1475 | int ret; | 1473 | int ret; |
1474 | struct timer_list *timer; | ||
1476 | 1475 | ||
1477 | ret = -ENOMEM; | 1476 | ret = -ENOMEM; |
1477 | timer = kzalloc(sizeof(*timer), GFP_KERNEL); | ||
1478 | if (!timer) | ||
1479 | goto out; | ||
1480 | |||
1481 | setup_timer(timer, fib6_gc_timer_cb, (unsigned long)net); | ||
1482 | net->ipv6.ip6_fib_timer = timer; | ||
1483 | |||
1478 | net->ipv6.fib_table_hash = | 1484 | net->ipv6.fib_table_hash = |
1479 | kzalloc(sizeof(*net->ipv6.fib_table_hash)*FIB_TABLE_HASHSZ, | 1485 | kzalloc(sizeof(*net->ipv6.fib_table_hash)*FIB_TABLE_HASHSZ, |
1480 | GFP_KERNEL); | 1486 | GFP_KERNEL); |
1481 | if (!net->ipv6.fib_table_hash) | 1487 | if (!net->ipv6.fib_table_hash) |
1482 | goto out; | 1488 | goto out_timer; |
1483 | 1489 | ||
1484 | net->ipv6.fib6_main_tbl = kzalloc(sizeof(*net->ipv6.fib6_main_tbl), | 1490 | net->ipv6.fib6_main_tbl = kzalloc(sizeof(*net->ipv6.fib6_main_tbl), |
1485 | GFP_KERNEL); | 1491 | GFP_KERNEL); |
@@ -1513,11 +1519,15 @@ out_fib6_main_tbl: | |||
1513 | #endif | 1519 | #endif |
1514 | out_fib_table_hash: | 1520 | out_fib_table_hash: |
1515 | kfree(net->ipv6.fib_table_hash); | 1521 | kfree(net->ipv6.fib_table_hash); |
1522 | out_timer: | ||
1523 | kfree(timer); | ||
1516 | goto out; | 1524 | goto out; |
1517 | } | 1525 | } |
1518 | 1526 | ||
1519 | static void fib6_net_exit(struct net *net) | 1527 | static void fib6_net_exit(struct net *net) |
1520 | { | 1528 | { |
1529 | del_timer(net->ipv6.ip6_fib_timer); | ||
1530 | kfree(net->ipv6.ip6_fib_timer); | ||
1521 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 1531 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
1522 | kfree(net->ipv6.fib6_local_tbl); | 1532 | kfree(net->ipv6.fib6_local_tbl); |
1523 | #endif | 1533 | #endif |
@@ -1533,6 +1543,7 @@ static struct pernet_operations fib6_net_ops = { | |||
1533 | int __init fib6_init(void) | 1543 | int __init fib6_init(void) |
1534 | { | 1544 | { |
1535 | int ret = -ENOMEM; | 1545 | int ret = -ENOMEM; |
1546 | |||
1536 | fib6_node_kmem = kmem_cache_create("fib6_nodes", | 1547 | fib6_node_kmem = kmem_cache_create("fib6_nodes", |
1537 | sizeof(struct fib6_node), | 1548 | sizeof(struct fib6_node), |
1538 | 0, SLAB_HWCACHE_ALIGN, | 1549 | 0, SLAB_HWCACHE_ALIGN, |
@@ -1540,16 +1551,9 @@ int __init fib6_init(void) | |||
1540 | if (!fib6_node_kmem) | 1551 | if (!fib6_node_kmem) |
1541 | goto out; | 1552 | goto out; |
1542 | 1553 | ||
1543 | ret = -ENOMEM; | ||
1544 | ip6_fib_timer = kzalloc(sizeof(*ip6_fib_timer), GFP_KERNEL); | ||
1545 | if (!ip6_fib_timer) | ||
1546 | goto out_kmem_cache_create; | ||
1547 | |||
1548 | setup_timer(ip6_fib_timer, fib6_gc_timer_cb, (unsigned long)&init_net); | ||
1549 | |||
1550 | ret = register_pernet_subsys(&fib6_net_ops); | 1554 | ret = register_pernet_subsys(&fib6_net_ops); |
1551 | if (ret) | 1555 | if (ret) |
1552 | goto out_timer; | 1556 | goto out_kmem_cache_create; |
1553 | 1557 | ||
1554 | ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib); | 1558 | ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib); |
1555 | if (ret) | 1559 | if (ret) |
@@ -1559,8 +1563,6 @@ out: | |||
1559 | 1563 | ||
1560 | out_unregister_subsys: | 1564 | out_unregister_subsys: |
1561 | unregister_pernet_subsys(&fib6_net_ops); | 1565 | unregister_pernet_subsys(&fib6_net_ops); |
1562 | out_timer: | ||
1563 | kfree(ip6_fib_timer); | ||
1564 | out_kmem_cache_create: | 1566 | out_kmem_cache_create: |
1565 | kmem_cache_destroy(fib6_node_kmem); | 1567 | kmem_cache_destroy(fib6_node_kmem); |
1566 | goto out; | 1568 | goto out; |
@@ -1568,8 +1570,6 @@ out_kmem_cache_create: | |||
1568 | 1570 | ||
1569 | void fib6_gc_cleanup(void) | 1571 | void fib6_gc_cleanup(void) |
1570 | { | 1572 | { |
1571 | del_timer(ip6_fib_timer); | ||
1572 | kfree(ip6_fib_timer); | ||
1573 | unregister_pernet_subsys(&fib6_net_ops); | 1573 | unregister_pernet_subsys(&fib6_net_ops); |
1574 | kmem_cache_destroy(fib6_node_kmem); | 1574 | kmem_cache_destroy(fib6_node_kmem); |
1575 | } | 1575 | } |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index fd44721abebb..b13eb0111270 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -952,7 +952,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
952 | icmp6_dst_gc_list = &rt->u.dst; | 952 | icmp6_dst_gc_list = &rt->u.dst; |
953 | spin_unlock_bh(&icmp6_dst_lock); | 953 | spin_unlock_bh(&icmp6_dst_lock); |
954 | 954 | ||
955 | fib6_force_start_gc(); | 955 | fib6_force_start_gc(dev->nd_net); |
956 | 956 | ||
957 | out: | 957 | out: |
958 | return &rt->u.dst; | 958 | return &rt->u.dst; |
@@ -1230,6 +1230,9 @@ install_route: | |||
1230 | rt->u.dst.dev = dev; | 1230 | rt->u.dst.dev = dev; |
1231 | rt->rt6i_idev = idev; | 1231 | rt->rt6i_idev = idev; |
1232 | rt->rt6i_table = table; | 1232 | rt->rt6i_table = table; |
1233 | |||
1234 | cfg->fc_nlinfo.nl_net = dev->nd_net; | ||
1235 | |||
1233 | return __ip6_ins_rt(rt, &cfg->fc_nlinfo); | 1236 | return __ip6_ins_rt(rt, &cfg->fc_nlinfo); |
1234 | 1237 | ||
1235 | out: | 1238 | out: |