diff options
| author | Pavel Emelyanov <xemul@parallels.com> | 2010-10-27 22:00:43 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2010-10-28 13:27:03 -0400 |
| commit | 4aa2c466a7733af093a526e9d1cdd0b3b90d47e9 (patch) | |
| tree | 093d99b6c728867a8eb9548463d94661e3d0799e /net | |
| parent | b1424ed91076db0b19ba4141856150df9b717dde (diff) | |
fib: Fix fib zone and its hash leak on namespace stop
When we stop a namespace we flush the table and free one, but the
added fn_zone-s (and their hashes if grown) are leaked. Need to free.
Tries releases all its stuff in the flushing code.
Shame on us - this bug exists since the very first make-fib-per-net
patches in 2.6.27 :(
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
| -rw-r--r-- | net/ipv4/fib_frontend.c | 2 | ||||
| -rw-r--r-- | net/ipv4/fib_hash.c | 18 | ||||
| -rw-r--r-- | net/ipv4/fib_trie.c | 5 |
3 files changed, 24 insertions, 1 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 36e27c2107de..eb6f69a8f27a 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
| @@ -1052,7 +1052,7 @@ static void ip_fib_net_exit(struct net *net) | |||
| 1052 | hlist_for_each_entry_safe(tb, node, tmp, head, tb_hlist) { | 1052 | hlist_for_each_entry_safe(tb, node, tmp, head, tb_hlist) { |
| 1053 | hlist_del(node); | 1053 | hlist_del(node); |
| 1054 | fib_table_flush(tb); | 1054 | fib_table_flush(tb); |
| 1055 | kfree(tb); | 1055 | fib_free_table(tb); |
| 1056 | } | 1056 | } |
| 1057 | } | 1057 | } |
| 1058 | kfree(net->ipv4.fib_table_hash); | 1058 | kfree(net->ipv4.fib_table_hash); |
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c index b232375a0b75..b3acb0417b21 100644 --- a/net/ipv4/fib_hash.c +++ b/net/ipv4/fib_hash.c | |||
| @@ -716,6 +716,24 @@ int fib_table_flush(struct fib_table *tb) | |||
| 716 | return found; | 716 | return found; |
| 717 | } | 717 | } |
| 718 | 718 | ||
| 719 | void fib_free_table(struct fib_table *tb) | ||
| 720 | { | ||
| 721 | struct fn_hash *table = (struct fn_hash *) tb->tb_data; | ||
| 722 | struct fn_zone *fz, *next; | ||
| 723 | |||
| 724 | next = table->fn_zone_list; | ||
| 725 | while (next != NULL) { | ||
| 726 | fz = next; | ||
| 727 | next = fz->fz_next; | ||
| 728 | |||
| 729 | if (fz->fz_hash != fz->fz_embedded_hash) | ||
| 730 | fz_hash_free(fz->fz_hash, fz->fz_divisor); | ||
| 731 | |||
| 732 | kfree(fz); | ||
| 733 | } | ||
| 734 | |||
| 735 | kfree(tb); | ||
| 736 | } | ||
| 719 | 737 | ||
| 720 | static inline int | 738 | static inline int |
| 721 | fn_hash_dump_bucket(struct sk_buff *skb, struct netlink_callback *cb, | 739 | fn_hash_dump_bucket(struct sk_buff *skb, struct netlink_callback *cb, |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index b14450895102..200eb538fbb3 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
| @@ -1797,6 +1797,11 @@ int fib_table_flush(struct fib_table *tb) | |||
| 1797 | return found; | 1797 | return found; |
| 1798 | } | 1798 | } |
| 1799 | 1799 | ||
| 1800 | void fib_free_table(struct fib_table *tb) | ||
| 1801 | { | ||
| 1802 | kfree(tb); | ||
| 1803 | } | ||
| 1804 | |||
| 1800 | void fib_table_select_default(struct fib_table *tb, | 1805 | void fib_table_select_default(struct fib_table *tb, |
| 1801 | const struct flowi *flp, | 1806 | const struct flowi *flp, |
| 1802 | struct fib_result *res) | 1807 | struct fib_result *res) |
