diff -Nur linux-2.6.3-rc4/fs/dcache.c linux-2.6.3-rc4.hash/fs/dcache.c --- linux-2.6.3-rc4/fs/dcache.c 2004-02-16 18:21:54.000000000 -0800 +++ linux-2.6.3-rc4.hash/fs/dcache.c 2004-02-17 14:03:21.000000000 -0800 @@ -49,6 +49,7 @@ */ #define D_HASHBITS d_hash_shift #define D_HASHMASK d_hash_mask +#define D_HASHMAX (2*1024*1024UL) /* max number of entries */ static unsigned int d_hash_mask; static unsigned int d_hash_shift; @@ -1531,6 +1532,16 @@ return ino; } +static __initdata unsigned long dhash_entries; +static int __init set_dhash_entries(char *str) +{ + if (!str) + return 0; + dhash_entries = simple_strtoul(str, &str, 0); + return 1; +} +__setup("dhash_entries=", set_dhash_entries); + static void __init dcache_init(unsigned long mempages) { struct hlist_head *d; @@ -1556,11 +1567,14 @@ set_shrinker(DEFAULT_SEEKS, shrink_dcache_memory); -#if PAGE_SHIFT < 13 - mempages >>= (13 - PAGE_SHIFT); -#endif - mempages *= sizeof(struct hlist_head); - for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++) + if (!dhash_entries) { + dhash_entries = PAGE_SHIFT < 13 ? + mempages >> (13 - PAGE_SHIFT) : + mempages << (PAGE_SHIFT - 13); + dhash_entries = min(D_HASHMAX, dhash_entries); + } + dhash_entries *= sizeof(struct hlist_head); + for (order = 0; ((1UL << order) << PAGE_SHIFT) < dhash_entries; order++) ; do { diff -Nur linux-2.6.3-rc4/fs/inode.c linux-2.6.3-rc4.hash/fs/inode.c --- linux-2.6.3-rc4/fs/inode.c 2004-02-16 18:23:36.000000000 -0800 +++ linux-2.6.3-rc4.hash/fs/inode.c 2004-02-17 14:03:21.000000000 -0800 @@ -53,6 +53,7 @@ */ #define I_HASHBITS i_hash_shift #define I_HASHMASK i_hash_mask +#define I_HASHMAX (2*1024*1024UL) /* max number of entries */ static unsigned int i_hash_mask; static unsigned int i_hash_shift; @@ -1327,6 +1328,16 @@ wake_up_all(wq); } +static __initdata unsigned long ihash_entries; +static int __init set_ihash_entries(char *str) +{ + if (!str) + return 0; + ihash_entries = simple_strtoul(str, &str, 0); + return 1; +} +__setup("ihash_entries=", set_ihash_entries); + /* * Initialize the waitqueues and inode hash table. */ @@ -1340,9 +1351,14 @@ 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 *= sizeof(struct hlist_head); - for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++) + if (!ihash_entries) { + ihash_entries = PAGE_SHIFT < 14 ? + mempages >> (14 - PAGE_SHIFT) : + mempages << (PAGE_SHIFT - 14); + ihash_entries = min(I_HASHMAX, ihash_entries); + } + ihash_entries *= sizeof(struct hlist_head); + for (order = 0; ((1UL << order) << PAGE_SHIFT) < ihash_entries; order++) ; do { diff -Nur linux-2.6.3-rc4/net/ipv4/route.c linux-2.6.3-rc4.hash/net/ipv4/route.c --- linux-2.6.3-rc4/net/ipv4/route.c 2004-02-16 18:23:37.000000000 -0800 +++ linux-2.6.3-rc4.hash/net/ipv4/route.c 2004-02-17 14:03:21.000000000 -0800 @@ -2717,6 +2717,16 @@ #endif /* CONFIG_PROC_FS */ #endif /* CONFIG_NET_CLS_ROUTE */ +static __initdata unsigned long rhash_entries; +static int __init set_rhash_entries(char *str) +{ + if (!str) + return 0; + rhash_entries = simple_strtoul(str, &str, 0); + return 1; +} +__setup("rhash_entries=", set_rhash_entries); + int __init ip_rt_init(void) { int i, order, goal, rc = 0; @@ -2743,7 +2753,10 @@ panic("IP: failed to allocate ip_dst_cache\n"); goal = num_physpages >> (26 - PAGE_SHIFT); - + if (!rhash_entries) + goal = min(10, goal); + else + goal = (rhash_entries * sizeof(struct rt_hash_bucket)) >> PAGE_SHIFT; for (order = 0; (1UL << order) < goal; order++) /* NOTHING */; diff -Nur linux-2.6.3-rc4/net/ipv4/tcp.c linux-2.6.3-rc4.hash/net/ipv4/tcp.c --- linux-2.6.3-rc4/net/ipv4/tcp.c 2004-02-16 18:22:05.000000000 -0800 +++ linux-2.6.3-rc4.hash/net/ipv4/tcp.c 2004-02-17 14:03:21.000000000 -0800 @@ -2570,6 +2570,16 @@ extern void __skb_cb_too_small_for_tcp(int, int); extern void tcpdiag_init(void); +static __initdata unsigned long thash_entries; +static int __init set_thash_entries(char *str) +{ + if (!str) + return 0; + thash_entries = simple_strtoul(str, &str, 0); + return 1; +} +__setup("thash_entries=", set_thash_entries); + void __init tcp_init(void) { struct sk_buff *skb = NULL; @@ -2611,6 +2621,10 @@ else goal = num_physpages >> (23 - PAGE_SHIFT); + if (!thash_entries) + goal = min(10, goal); + else + goal = (thash_entries * sizeof(struct tcp_ehash_bucket)) >> PAGE_SHIFT; for (order = 0; (1UL << order) < goal; order++) ; do {