From: "Chen, Kenneth W" The issue of exceedingly large hash tables has been discussed on the mailing list a while back, but seems to slip through the cracks. What we found is it's not a problem for x86 (and most other architectures) because __get_free_pages won't be able to get anything beyond order MAX_ORDER-1 (10) which means at most those hash tables are 4MB each (assume 4K page size). However, on ia64, in order to support larger hugeTLB page size, the MAX_ORDER is bumped up to 18, which now means a 2GB upper limits enforced by the page allocator (assume 16K page size). PPC64 is another example that bumps up MAX_ORDER. Last time I checked, the tcp ehash table is taking a whooping (insane!) 2GB on one of our large machine. dentry and inode hash tables also take considerable amount of memory. This patch just enforces all the hash tables to have a max order of 10, which limits them down to 16MB each on ia64. People can clean up other part of table size calculation. But minimally, this patch doesn't change any hash sizes already in use on x86. --- fs/dcache.c | 6 ++---- fs/inode.c | 4 ++-- net/ipv4/route.c | 2 +- net/ipv4/tcp.c | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff -puN fs/dcache.c~limit-hash-table-sizes fs/dcache.c --- 25/fs/dcache.c~limit-hash-table-sizes 2004-01-09 01:23:31.000000000 -0800 +++ 25-akpm/fs/dcache.c 2004-01-09 01:23:31.000000000 -0800 @@ -1552,11 +1552,9 @@ static void __init dcache_init(unsigned set_shrinker(DEFAULT_SEEKS, shrink_dcache_memory); -#if PAGE_SHIFT < 13 - mempages >>= (13 - PAGE_SHIFT); -#endif + mempages >>= 1; mempages *= sizeof(struct hlist_head); - for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++) + for (order = 0; (order < 10) && (((1UL << order) << PAGE_SHIFT) < mempages); order++) ; do { diff -puN fs/inode.c~limit-hash-table-sizes fs/inode.c --- 25/fs/inode.c~limit-hash-table-sizes 2004-01-09 01:23:31.000000000 -0800 +++ 25-akpm/fs/inode.c 2004-01-09 01:23:31.000000000 -0800 @@ -1325,9 +1325,9 @@ void __init inode_init(unsigned long mem for (i = 0; i < ARRAY_SIZE(i_wait_queue_heads); i++) init_waitqueue_head(&i_wait_queue_heads[i].wqh); - mempages >>= (14 - PAGE_SHIFT); + mempages >>= 2; mempages *= sizeof(struct hlist_head); - for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++) + for (order = 0; (order < 10) && (((1UL << order) << PAGE_SHIFT) < mempages); order++) ; do { diff -puN net/ipv4/route.c~limit-hash-table-sizes net/ipv4/route.c --- 25/net/ipv4/route.c~limit-hash-table-sizes 2004-01-09 01:23:31.000000000 -0800 +++ 25-akpm/net/ipv4/route.c 2004-01-09 01:23:31.000000000 -0800 @@ -2744,7 +2744,7 @@ int __init ip_rt_init(void) goal = num_physpages >> (26 - PAGE_SHIFT); - for (order = 0; (1UL << order) < goal; order++) + for (order = 0; (order < 10) && ((1UL << order) < goal); order++) /* NOTHING */; do { diff -puN net/ipv4/tcp.c~limit-hash-table-sizes net/ipv4/tcp.c --- 25/net/ipv4/tcp.c~limit-hash-table-sizes 2004-01-09 01:23:31.000000000 -0800 +++ 25-akpm/net/ipv4/tcp.c 2004-01-09 01:23:31.000000000 -0800 @@ -2610,7 +2610,7 @@ void __init tcp_init(void) else goal = num_physpages >> (23 - PAGE_SHIFT); - for (order = 0; (1UL << order) < goal; order++) + for (order = 0; (order < 10) && ((1UL << order) < goal); order++) ; do { tcp_ehash_size = (1UL << order) * PAGE_SIZE / _