diff options
author | Denis V. Lunev <den@openvz.org> | 2008-07-05 22:06:12 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-05 22:06:12 -0400 |
commit | 32cb5b4e035e3d7b52f1e9de87920645a00e5234 (patch) | |
tree | 54c26b95e4083e9ed6bb4593a2f940829779979b /net | |
parent | e84f84f276473dcc673f360e8ff3203148bdf0e2 (diff) |
netns: selective flush of rt_cache
dst cache is marked as expired on the per/namespace basis by previous
path. Right now we have to implement selective cache shrinking. This
procedure has been ported from older OpenVz codebase.
Signed-off-by: Denis V. Lunev <den@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/route.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 67c3ed772c27..113cd2512ba7 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -699,6 +699,7 @@ static void rt_do_flush(int process_context) | |||
699 | { | 699 | { |
700 | unsigned int i; | 700 | unsigned int i; |
701 | struct rtable *rth, *next; | 701 | struct rtable *rth, *next; |
702 | struct rtable * tail; | ||
702 | 703 | ||
703 | for (i = 0; i <= rt_hash_mask; i++) { | 704 | for (i = 0; i <= rt_hash_mask; i++) { |
704 | if (process_context && need_resched()) | 705 | if (process_context && need_resched()) |
@@ -708,11 +709,39 @@ static void rt_do_flush(int process_context) | |||
708 | continue; | 709 | continue; |
709 | 710 | ||
710 | spin_lock_bh(rt_hash_lock_addr(i)); | 711 | spin_lock_bh(rt_hash_lock_addr(i)); |
712 | #ifdef CONFIG_NET_NS | ||
713 | { | ||
714 | struct rtable ** prev, * p; | ||
715 | |||
716 | rth = rt_hash_table[i].chain; | ||
717 | |||
718 | /* defer releasing the head of the list after spin_unlock */ | ||
719 | for (tail = rth; tail; tail = tail->u.dst.rt_next) | ||
720 | if (!rt_is_expired(tail)) | ||
721 | break; | ||
722 | if (rth != tail) | ||
723 | rt_hash_table[i].chain = tail; | ||
724 | |||
725 | /* call rt_free on entries after the tail requiring flush */ | ||
726 | prev = &rt_hash_table[i].chain; | ||
727 | for (p = *prev; p; p = next) { | ||
728 | next = p->u.dst.rt_next; | ||
729 | if (!rt_is_expired(p)) { | ||
730 | prev = &p->u.dst.rt_next; | ||
731 | } else { | ||
732 | *prev = next; | ||
733 | rt_free(p); | ||
734 | } | ||
735 | } | ||
736 | } | ||
737 | #else | ||
711 | rth = rt_hash_table[i].chain; | 738 | rth = rt_hash_table[i].chain; |
712 | rt_hash_table[i].chain = NULL; | 739 | rt_hash_table[i].chain = NULL; |
740 | tail = NULL; | ||
741 | #endif | ||
713 | spin_unlock_bh(rt_hash_lock_addr(i)); | 742 | spin_unlock_bh(rt_hash_lock_addr(i)); |
714 | 743 | ||
715 | for (; rth; rth = next) { | 744 | for (; rth != tail; rth = next) { |
716 | next = rth->u.dst.rt_next; | 745 | next = rth->u.dst.rt_next; |
717 | rt_free(rth); | 746 | rt_free(rth); |
718 | } | 747 | } |