| From 49a18d86f66d33a20144ecb5a34bba0d1856b260 Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Michal=20Kube=C4=8Dek?= <mkubecek@suse.cz> |
| Date: Thu, 1 Aug 2013 10:04:24 +0200 |
| Subject: ipv6: update ip6_rt_last_gc every time GC is run |
| |
| commit 49a18d86f66d33a20144ecb5a34bba0d1856b260 upstream. |
| |
| As pointed out by Eric Dumazet, net->ipv6.ip6_rt_last_gc should |
| hold the last time garbage collector was run so that we should |
| update it whenever fib6_run_gc() calls fib6_clean_all(), not only |
| if we got there from ip6_dst_gc(). |
| |
| Signed-off-by: Michal Kubecek <mkubecek@suse.cz> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Zefan Li <lizefan@huawei.com> |
| --- |
| net/ipv6/ip6_fib.c | 6 +++++- |
| net/ipv6/route.c | 4 +--- |
| 2 files changed, 6 insertions(+), 4 deletions(-) |
| |
| --- a/net/ipv6/ip6_fib.c |
| +++ b/net/ipv6/ip6_fib.c |
| @@ -1595,6 +1595,8 @@ static DEFINE_SPINLOCK(fib6_gc_lock); |
| |
| void fib6_run_gc(unsigned long expires, struct net *net, bool force) |
| { |
| + unsigned long now; |
| + |
| if (force) { |
| spin_lock_bh(&fib6_gc_lock); |
| } else if (!spin_trylock_bh(&fib6_gc_lock)) { |
| @@ -1607,10 +1609,12 @@ void fib6_run_gc(unsigned long expires, |
| gc_args.more = icmp6_dst_gc(); |
| |
| fib6_clean_all(net, fib6_age, 0, NULL); |
| + now = jiffies; |
| + net->ipv6.ip6_rt_last_gc = now; |
| |
| if (gc_args.more) |
| mod_timer(&net->ipv6.ip6_fib_timer, |
| - round_jiffies(jiffies |
| + round_jiffies(now |
| + net->ipv6.sysctl.ip6_rt_gc_interval)); |
| else |
| del_timer(&net->ipv6.ip6_fib_timer); |
| --- a/net/ipv6/route.c |
| +++ b/net/ipv6/route.c |
| @@ -1230,7 +1230,6 @@ static void icmp6_clean_all(int (*func)( |
| |
| static int ip6_dst_gc(struct dst_ops *ops) |
| { |
| - unsigned long now = jiffies; |
| struct net *net = container_of(ops, struct net, ipv6.ip6_dst_ops); |
| int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval; |
| int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size; |
| @@ -1240,13 +1239,12 @@ static int ip6_dst_gc(struct dst_ops *op |
| int entries; |
| |
| entries = dst_entries_get_fast(ops); |
| - if (time_after(rt_last_gc + rt_min_interval, now) && |
| + if (time_after(rt_last_gc + rt_min_interval, jiffies) && |
| entries <= rt_max_size) |
| goto out; |
| |
| net->ipv6.ip6_rt_gc_expire++; |
| fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net, entries > rt_max_size); |
| - net->ipv6.ip6_rt_last_gc = now; |
| entries = dst_entries_get_slow(ops); |
| if (entries < ops->gc_thresh) |
| net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1; |