RE: Limit hash table size

Chen, Kenneth W
2004-02-18T00:19:20Z

[-- Attachment #1: Type: text/plain, Size: 478 bytes --]

> I think it would be better to leave things as they are,
> with a boot option to scale the tables down.

OK, here is one that adds boot time parameters only and leave everything
else untouched.

> The below patch addresses the inode and dentry caches.
> Need to think a bit more about the networking ones.

Don't know what happened to my mailer, the mailing list archive shows
complete patch including the network part. Hope this time you receive
the whole thing.

[-- Attachment #2: hash5.patch --]
[-- Type: application/octet-stream, Size: 4055 bytes --]

diff -Nur linux-2.6.2-rc1/fs/dcache.c linux-2.6.2-rc1.ken/fs/dcache.c
--- linux-2.6.2-rc1/fs/dcache.c 2004-01-20 19:49:25.000000000 -0800
+++ linux-2.6.2-rc1.ken/fs/dcache.c 2004-02-17 15:31:35.000000000 -0800
@@ -1527,6 +1527,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;
@@ -1552,11 +1562,13 @@

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 *= sizeof(struct hlist_head);
+ for (order = 0; ((1UL << order) << PAGE_SHIFT) < dhash_entries; order++)
;

do {
diff -Nur linux-2.6.2-rc1/fs/inode.c linux-2.6.2-rc1.ken/fs/inode.c
--- linux-2.6.2-rc1/fs/inode.c 2004-01-20 19:50:41.000000000 -0800
+++ linux-2.6.2-rc1.ken/fs/inode.c 2004-02-17 15:30:51.000000000 -0800
@@ -1327,6 +1327,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 +1350,13 @@
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 *= sizeof(struct hlist_head);
+ for (order = 0; ((1UL << order) << PAGE_SHIFT) < ihash_entries; order++)
;

do {
diff -Nur linux-2.6.2-rc1/net/ipv4/route.c linux-2.6.2-rc1.ken/net/ipv4/route.c
--- linux-2.6.2-rc1/net/ipv4/route.c 2004-01-20 19:50:41.000000000 -0800
+++ linux-2.6.2-rc1.ken/net/ipv4/route.c 2004-02-17 15:43:59.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;
@@ -2742,8 +2752,10 @@
if (!ipv4_dst_ops.kmem_cachep)
panic("IP: failed to allocate ip_dst_cache\n");

- goal = num_physpages >> (26 - PAGE_SHIFT);
-
+ if (!rhash_entries)
+ goal = num_physpages >> (26 - PAGE_SHIFT);
+ else
+ goal = (rhash_entries * sizeof(struct rt_hash_bucket)) >> PAGE_SHIFT;
for (order = 0; (1UL << order) < goal; order++)
/* NOTHING */;

diff -Nur linux-2.6.2-rc1/net/ipv4/tcp.c linux-2.6.2-rc1.ken/net/ipv4/tcp.c
--- linux-2.6.2-rc1/net/ipv4/tcp.c 2004-01-20 19:49:36.000000000 -0800
+++ linux-2.6.2-rc1.ken/net/ipv4/tcp.c 2004-02-17 15:45:25.000000000 -0800
@@ -2569,6 +2569,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;
@@ -2610,6 +2620,8 @@
else
goal = num_physpages >> (23 - PAGE_SHIFT);

+ if (thash_entries)
+ goal = (thash_entries * sizeof(struct tcp_ehash_bucket)) >> PAGE_SHIFT;
for (order = 0; (1UL << order) < goal; order++)
;
do {