diff --git a/fs/dcache.c b/fs/dcache.c index 7c38f39958bc..ba11d2047e73 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -103,13 +103,25 @@ EXPORT_SYMBOL(slash_name); static unsigned int d_hash_shift __read_mostly; -static struct hlist_bl_head *dentry_hashtable __read_mostly; +struct _hlist_bl_head { + struct hlist_bl_head head; + int count; +}; -static inline struct hlist_bl_head *d_hash(unsigned int hash) +static int nentries, nbuckets, maxcount; + +static struct _hlist_bl_head *dentry_hashtable __read_mostly; + +static inline struct _hlist_bl_head *_d_hash(unsigned int hash) { return dentry_hashtable + (hash >> d_hash_shift); } +static inline struct hlist_bl_head *d_hash(unsigned int hash) +{ + return &_d_hash(hash)->head; +} + #define IN_LOOKUP_SHIFT 10 static struct hlist_bl_head in_lookup_hashtable[1 << IN_LOOKUP_SHIFT]; @@ -174,7 +186,7 @@ int proc_nr_dentry(struct ctl_table *table, int write, void __user *buffer, * Compare 2 name strings, return 0 if they match, otherwise non-zero. * The strings are both count bytes long, and count is non-zero. */ -#ifdef CONFIG_DCACHE_WORD_ACCESS +#if 0//def CONFIG_DCACHE_WORD_ACCESS #include /* @@ -471,19 +483,28 @@ static void dentry_lru_add(struct dentry *dentry) static void ___d_drop(struct dentry *dentry) { if (!d_unhashed(dentry)) { + struct _hlist_bl_head *_b; struct hlist_bl_head *b; /* * Hashed dentries are normally on the dentry hashtable, * with the exception of those newly allocated by * d_obtain_root, which are always IS_ROOT: */ - if (unlikely(IS_ROOT(dentry))) + if (unlikely(IS_ROOT(dentry))) { + _b = NULL; b = &dentry->d_sb->s_roots; - else - b = d_hash(dentry->d_name.hash); - + } else { + _b = _d_hash(dentry->d_name.hash); + b = &_b->head; + } hlist_bl_lock(b); __hlist_bl_del(&dentry->d_hash); + if (_b) { + _b->count--; + if (!_b->count) + nbuckets--; + nentries--; + } hlist_bl_unlock(b); /* After this call, in-progress rcu-walk path lookup will fail. */ write_seqcount_invalidate(&dentry->d_seq); @@ -2406,10 +2427,20 @@ EXPORT_SYMBOL(d_delete); static void __d_rehash(struct dentry *entry) { - struct hlist_bl_head *b = d_hash(entry->d_name.hash); + struct _hlist_bl_head *_b = _d_hash(entry->d_name.hash); + struct hlist_bl_head *b = &_b->head; hlist_bl_lock(b); hlist_bl_add_head_rcu(&entry->d_hash, b); + if (!_b->count) + nbuckets++; + _b->count++; + nentries++; + if (_b->count > maxcount) { + maxcount = _b->count; + pr_info("dcache: d_hash_shift = %d, nentries = %d, nbuckets = %d, maxcount = %d\n", + d_hash_shift, nentries, nbuckets, maxcount); + } hlist_bl_unlock(b); } @@ -3610,7 +3641,7 @@ static void __init dcache_init_early(void) dentry_hashtable = alloc_large_system_hash("Dentry cache", - sizeof(struct hlist_bl_head), + sizeof(struct _hlist_bl_head), dhash_entries, 13, HASH_EARLY | HASH_ZERO, @@ -3618,7 +3649,7 @@ static void __init dcache_init_early(void) NULL, 0, 0); - d_hash_shift = 32 - d_hash_shift; + d_hash_shift = 32 - 12;//d_hash_shift; } static void __init dcache_init(void) @@ -3638,7 +3669,7 @@ static void __init dcache_init(void) dentry_hashtable = alloc_large_system_hash("Dentry cache", - sizeof(struct hlist_bl_head), + sizeof(struct _hlist_bl_head), dhash_entries, 13, HASH_ZERO, @@ -3646,7 +3677,7 @@ static void __init dcache_init(void) NULL, 0, 0); - d_hash_shift = 32 - d_hash_shift; + d_hash_shift = 32 - 12;//d_hash_shift; } /* SLAB cache for __getname() consumers */ diff --git a/fs/namei.c b/fs/namei.c index afe2a8af9ce4..e11200c12351 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1798,7 +1798,7 @@ static int walk_component(struct nameidata *nd, int flags) * the final mask". Again, that could be replaced with a * efficient population count instruction or similar. */ -#ifdef CONFIG_DCACHE_WORD_ACCESS +#if 0//def CONFIG_DCACHE_WORD_ACCESS #include @@ -1985,6 +1985,9 @@ unsigned long full_name_long_hash(const void *salt, const char *name, } EXPORT_SYMBOL(full_name_long_hash); +// define end_name_hash to NOOP +//#define end_name_hash (unsigned int) + unsigned int full_name_hash(const void *salt, const char *name, unsigned int len) {