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 #include #include +#include +#include /* * 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,