Sophie

Sophie

distrib > Mandriva > 8.2 > i586 > media > main-src > by-pkgid > 276c4c69ed5efcebe43ee6121194cf59 > files > 19

kernel22-2.2.20-9mdk.src.rpm

diff -urN 2.2.19pre13/fs/inode.c inode-dyn/fs/inode.c
--- 2.2.19pre13/fs/inode.c	Sun Feb 18 04:01:32 2001
+++ inode-dyn/fs/inode.c	Sun Feb 18 05:05:41 2001
@@ -11,6 +11,8 @@
 #include <linux/init.h>
 #include <linux/quotaops.h>
 #include <linux/random.h>
+#include <linux/bigmem.h>
+#include <linux/slab.h>
 
 /*
  * New inode.c implementation.
@@ -29,9 +31,8 @@
  * Inode lookup is no longer as critical as it used to be:
  * most of the lookups are going to be through the dcache.
  */
-#define HASH_BITS	8
-#define HASH_SIZE	(1UL << HASH_BITS)
-#define HASH_MASK	(HASH_SIZE-1)
+#define HASH_BITS	i_hash_bits
+#define HASH_MASK	i_hash_mask
 
 /*
  * Each inode can be on two separate lists. One is
@@ -47,7 +48,9 @@
 
 LIST_HEAD(inode_in_use);
 static LIST_HEAD(inode_unused);
-static struct list_head inode_hashtable[HASH_SIZE];
+static unsigned int i_hash_bits;
+static unsigned int i_hash_mask;
+static struct list_head *inode_hashtable;
 
 __u32 inode_generation_count = 0;
 
@@ -680,7 +683,7 @@
 
 static inline unsigned long hash(struct super_block *sb, unsigned long i_ino)
 {
-	unsigned long tmp = i_ino | (unsigned long) sb;
+	unsigned long tmp = i_ino + (unsigned long) sb / (sizeof(struct super_block) & ~(sizeof(struct super_block) - 1));
 	tmp = tmp + (tmp >> HASH_BITS);
 	return tmp & HASH_MASK;
 }
@@ -835,29 +838,84 @@
 	return 0;
 }
 
-/*
- * Initialize the hash tables and default
- * value for max inodes
- */
-#define MAX_INODE (16384)
-
 void __init inode_init(void)
 {
-	int i, max;
-	struct list_head *head = inode_hashtable;
+	int i, order;
+	struct list_head *d;
+	unsigned long nr_hash, hash_size, tmp;
+
+#ifndef CONFIG_BIGMEM
+	nr_hash = num_physpages;
+#else
+	nr_hash = bigmem_mapnr;
+#endif
+	nr_hash <<= PAGE_SHIFT;
+	nr_hash >>= 13;
+
+	/* scale logaritmically over 32768 inodes */
+	if (nr_hash > 16384) {
+		if (nr_hash > 32768)
+			nr_hash >>= 1;
+		else
+			nr_hash = 16384;
+	}
+	if (nr_hash > 32768) {
+		if (nr_hash > 65536)
+			nr_hash >>= 1;
+		else
+			nr_hash = 32768;
+	}
+
+	/* This limit triggers with more than 1G of RAM */
+	if (nr_hash > 65536)
+		nr_hash = 65536;
+
+	max_inodes = nr_hash;
+
+	hash_size = nr_hash * sizeof(struct list_head);
+
+	if (hash_size < PAGE_SIZE) {
+		/* Embedded systems */
+		inode_hashtable = kmalloc(hash_size, GFP_ATOMIC);
+
+		i_hash_mask = (nr_hash - 1);
 
-	i = HASH_SIZE;
+		tmp = nr_hash;
+		i_hash_bits = 0;
+		while((tmp >>= 1UL) != 0UL)
+			i_hash_bits++;
+	} else {
+		for (order = 0; ((1UL << order) << PAGE_SHIFT) < hash_size;
+		     order++);
+
+		do {
+			hash_size = 1UL << (order+PAGE_SHIFT);
+			nr_hash =  hash_size / sizeof(struct list_head);
+
+			i_hash_mask = (nr_hash - 1);
+
+			tmp = nr_hash;
+			i_hash_bits = 0;
+			while((tmp >>= 1UL) != 0UL)
+				i_hash_bits++;
+
+			inode_hashtable = (struct list_head *) __get_free_pages(GFP_ATOMIC, order);
+		} while(inode_hashtable == NULL && --order >= 0);
+	}
+
+	printk("Inode hash table entries: %lu (%ldk), inode-max: %d\n",
+	       nr_hash, hash_size >> 10, max_inodes);
+
+	if (!inode_hashtable)
+		panic("Failed to allocate inode hash table\n");
+
+	d = inode_hashtable;
+	i = nr_hash;
 	do {
-		INIT_LIST_HEAD(head);
-		head++;
+		INIT_LIST_HEAD(d);
+		d++;
 		i--;
 	} while (i);
-
-	/* Initial guess at reasonable inode number */
-	max = num_physpages >> 1;
-	if (max > MAX_INODE)
-		max = MAX_INODE;
-	max_inodes = max;
 
 	/* Get a random number. */
 	get_random_bytes (&inode_generation_count,