diff options
author | Tim Bird <tim.bird@am.sony.com> | 2012-05-23 09:33:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-05-24 00:28:21 -0400 |
commit | 31fe62b9586643953f0c0c37a6357dafc69034e2 (patch) | |
tree | 69f9990423969df4ecbaea9d1e8de748284bea5e /net/ipv4/udp.c | |
parent | d0a24a3516fb36023bef28d2355fa34e7f32029f (diff) |
mm: add a low limit to alloc_large_system_hash
UDP stack needs a minimum hash size value for proper operation and also
uses alloc_large_system_hash() for proper NUMA distribution of its hash
tables and automatic sizing depending on available system memory.
On some low memory situations, udp_table_init() must ignore the
alloc_large_system_hash() result and reallocs a bigger memory area.
As we cannot easily free old hash table, we leak it and kmemleak can
issue a warning.
This patch adds a low limit parameter to alloc_large_system_hash() to
solve this problem.
We then specify UDP_HTABLE_SIZE_MIN for UDP/UDPLite hash table
allocation.
Reported-by: Mark Asselstine <mark.asselstine@windriver.com>
Reported-by: Tim Bird <tim.bird@am.sony.com>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r-- | net/ipv4/udp.c | 30 |
1 files changed, 10 insertions, 20 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 609397ee78fb..eaca73644e79 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -2192,26 +2192,16 @@ void __init udp_table_init(struct udp_table *table, const char *name) | |||
2192 | { | 2192 | { |
2193 | unsigned int i; | 2193 | unsigned int i; |
2194 | 2194 | ||
2195 | if (!CONFIG_BASE_SMALL) | 2195 | table->hash = alloc_large_system_hash(name, |
2196 | table->hash = alloc_large_system_hash(name, | 2196 | 2 * sizeof(struct udp_hslot), |
2197 | 2 * sizeof(struct udp_hslot), | 2197 | uhash_entries, |
2198 | uhash_entries, | 2198 | 21, /* one slot per 2 MB */ |
2199 | 21, /* one slot per 2 MB */ | 2199 | 0, |
2200 | 0, | 2200 | &table->log, |
2201 | &table->log, | 2201 | &table->mask, |
2202 | &table->mask, | 2202 | UDP_HTABLE_SIZE_MIN, |
2203 | 64 * 1024); | 2203 | 64 * 1024); |
2204 | /* | 2204 | |
2205 | * Make sure hash table has the minimum size | ||
2206 | */ | ||
2207 | if (CONFIG_BASE_SMALL || table->mask < UDP_HTABLE_SIZE_MIN - 1) { | ||
2208 | table->hash = kmalloc(UDP_HTABLE_SIZE_MIN * | ||
2209 | 2 * sizeof(struct udp_hslot), GFP_KERNEL); | ||
2210 | if (!table->hash) | ||
2211 | panic(name); | ||
2212 | table->log = ilog2(UDP_HTABLE_SIZE_MIN); | ||
2213 | table->mask = UDP_HTABLE_SIZE_MIN - 1; | ||
2214 | } | ||
2215 | table->hash2 = table->hash + (table->mask + 1); | 2205 | table->hash2 = table->hash + (table->mask + 1); |
2216 | for (i = 0; i <= table->mask; i++) { | 2206 | for (i = 0; i <= table->mask; i++) { |
2217 | INIT_HLIST_NULLS_HEAD(&table->hash[i].head, i); | 2207 | INIT_HLIST_NULLS_HEAD(&table->hash[i].head, i); |