diff options
-rw-r--r-- | net/ipv4/route.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 9fcbb1b0a8d6..726ea5e8180a 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -54,7 +54,7 @@ | |||
54 | * Marc Boucher : routing by fwmark | 54 | * Marc Boucher : routing by fwmark |
55 | * Robert Olsson : Added rt_cache statistics | 55 | * Robert Olsson : Added rt_cache statistics |
56 | * Arnaldo C. Melo : Convert proc stuff to seq_file | 56 | * Arnaldo C. Melo : Convert proc stuff to seq_file |
57 | * Eric Dumazet : hashed spinlocks | 57 | * Eric Dumazet : hashed spinlocks and rt_check_expire() fixes. |
58 | * | 58 | * |
59 | * This program is free software; you can redistribute it and/or | 59 | * This program is free software; you can redistribute it and/or |
60 | * modify it under the terms of the GNU General Public License | 60 | * modify it under the terms of the GNU General Public License |
@@ -606,18 +606,25 @@ static struct rtable **rt_remove_balanced_route(struct rtable **chain_head, | |||
606 | /* This runs via a timer and thus is always in BH context. */ | 606 | /* This runs via a timer and thus is always in BH context. */ |
607 | static void rt_check_expire(unsigned long dummy) | 607 | static void rt_check_expire(unsigned long dummy) |
608 | { | 608 | { |
609 | static int rover; | 609 | static unsigned int rover; |
610 | int i = rover, t; | 610 | unsigned int i = rover, goal; |
611 | struct rtable *rth, **rthp; | 611 | struct rtable *rth, **rthp; |
612 | unsigned long now = jiffies; | 612 | unsigned long now = jiffies; |
613 | 613 | u64 mult; | |
614 | for (t = ip_rt_gc_interval << rt_hash_log; t >= 0; | 614 | |
615 | t -= ip_rt_gc_timeout) { | 615 | mult = ((u64)ip_rt_gc_interval) << rt_hash_log; |
616 | if (ip_rt_gc_timeout > 1) | ||
617 | do_div(mult, ip_rt_gc_timeout); | ||
618 | goal = (unsigned int)mult; | ||
619 | if (goal > rt_hash_mask) goal = rt_hash_mask + 1; | ||
620 | for (; goal > 0; goal--) { | ||
616 | unsigned long tmo = ip_rt_gc_timeout; | 621 | unsigned long tmo = ip_rt_gc_timeout; |
617 | 622 | ||
618 | i = (i + 1) & rt_hash_mask; | 623 | i = (i + 1) & rt_hash_mask; |
619 | rthp = &rt_hash_table[i].chain; | 624 | rthp = &rt_hash_table[i].chain; |
620 | 625 | ||
626 | if (*rthp == 0) | ||
627 | continue; | ||
621 | spin_lock(rt_hash_lock_addr(i)); | 628 | spin_lock(rt_hash_lock_addr(i)); |
622 | while ((rth = *rthp) != NULL) { | 629 | while ((rth = *rthp) != NULL) { |
623 | if (rth->u.dst.expires) { | 630 | if (rth->u.dst.expires) { |
@@ -658,7 +665,7 @@ static void rt_check_expire(unsigned long dummy) | |||
658 | break; | 665 | break; |
659 | } | 666 | } |
660 | rover = i; | 667 | rover = i; |
661 | mod_timer(&rt_periodic_timer, now + ip_rt_gc_interval); | 668 | mod_timer(&rt_periodic_timer, jiffies + ip_rt_gc_interval); |
662 | } | 669 | } |
663 | 670 | ||
664 | /* This can run from both BH and non-BH contexts, the latter | 671 | /* This can run from both BH and non-BH contexts, the latter |