summaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-04-28 01:09:25 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-04-28 01:09:25 +0000
commitb9ba7aeb165cffecdffb60aec8c3fa8d590d9ca9 (patch)
tree42d07b0c7246ae2536a702e7c5de9e2732341116 /fs/dcache.c
parent7406b0a326f2d70ade2671c37d1beef62249db97 (diff)
Merge with 2.3.99-pre6.
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c71
1 files changed, 51 insertions, 20 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 24e2f2568..3caf950eb 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -21,6 +21,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
+#include <linux/cache.h>
#include <asm/uaccess.h>
@@ -40,11 +41,12 @@ kmem_cache_t *dentry_cache;
* This hash-function tries to avoid losing too many bits of hash
* information, yet avoid using a prime hash-size or similar.
*/
-#define D_HASHBITS 14
-#define D_HASHSIZE (1UL << D_HASHBITS)
-#define D_HASHMASK (D_HASHSIZE-1)
+#define D_HASHBITS d_hash_shift
+#define D_HASHMASK d_hash_mask
-static struct list_head dentry_hashtable[D_HASHSIZE];
+static unsigned int d_hash_mask;
+static unsigned int d_hash_shift;
+static struct list_head *dentry_hashtable;
static LIST_HEAD(dentry_unused);
struct {
@@ -83,7 +85,7 @@ static inline void dentry_iput(struct dentry * dentry)
}
/*
- * dput
+ * This is dput
*
* This is complicated by the fact that we do not want to put
* dentries that are no longer on any hash chain on the unused
@@ -534,7 +536,7 @@ int shrink_dcache_memory(int priority, unsigned int gfp_mask, zone_t * zone)
* @parent: parent of entry to allocate
* @name: qstr of the name
*
- * Allocates a dentry. It returns NULL if there is insufficient memory
+ * Allocates a dentry. It returns %NULL if there is insufficient memory
* available. On a success the dentry is returned. The name passed in is
* copied and the copy passed in may be reused after this call.
*/
@@ -590,7 +592,7 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name)
/**
* d_instantiate - fill in inode information for a dentry
* @entry: dentry to complete
- * @inode: inode to attacheto this dentry
+ * @inode: inode to attach to this dentry
*
* Fill in inode information in the entry.
*
@@ -599,7 +601,7 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name)
*
* NOTE! This assumes that the inode count has been incremented
* (or otherwise set) by the caller to indicate that it is now
- * in use by the dcache..
+ * in use by the dcache.
*/
void d_instantiate(struct dentry *entry, struct inode * inode)
@@ -613,9 +615,9 @@ void d_instantiate(struct dentry *entry, struct inode * inode)
* d_alloc_root - allocate root dentry
* @root_inode: inode to allocate the root for
*
- * Allocate a root ('/') dentry for the inode given. The inode is
- * instantiated and returned. NULL is returned if there is insufficient
- * memory or the inode passed is NULL.
+ * Allocate a root ("/") dentry for the inode given. The inode is
+ * instantiated and returned. %NULL is returned if there is insufficient
+ * memory or the inode passed is %NULL.
*/
struct dentry * d_alloc_root(struct inode * root_inode)
@@ -635,7 +637,7 @@ struct dentry * d_alloc_root(struct inode * root_inode)
static inline struct list_head * d_hash(struct dentry * parent, unsigned long hash)
{
- hash += (unsigned long) parent;
+ hash += (unsigned long) parent / L1_CACHE_BYTES;
hash = hash ^ (hash >> D_HASHBITS) ^ (hash >> D_HASHBITS*2);
return dentry_hashtable + (hash & D_HASHMASK);
}
@@ -648,7 +650,7 @@ static inline struct list_head * d_hash(struct dentry * parent, unsigned long ha
* Searches the children of the parent dentry for the name in question. If
* the dentry is found its reference count is incremented and the dentry
* is returned. The caller must use d_put to free the entry when it has
- * finished using it. NULL is returned on failure.
+ * finished using it. %NULL is returned on failure.
*/
struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
@@ -780,7 +782,7 @@ void d_delete(struct dentry * dentry)
* d_rehash - add an entry back to the hash
* @entry: dentry to add to the hash
*
- * Adds a dentry to the hash according to its name
+ * Adds a dentry to the hash according to its name.
*/
void d_rehash(struct dentry * entry)
@@ -881,11 +883,11 @@ void d_move(struct dentry * dentry, struct dentry * target)
* @buffer: buffer to return value in
* @buflen: buffer length
*
- * Convert a dentry into an ascii path name. If the entry has been deleted
- * the string ' (deleted)' is appended. Note that this is ambiguous. Returns
+ * Convert a dentry into an ASCII path name. If the entry has been deleted
+ * the string " (deleted)" is appended. Note that this is ambiguous. Returns
* the buffer.
*
- * "buflen" should be PAGE_SIZE or more.
+ * "buflen" should be %PAGE_SIZE or more.
*/
char * __d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
struct dentry *root, struct vfsmount *rootmnt,
@@ -1054,10 +1056,12 @@ out:
return ino;
}
-void __init dcache_init(void)
+void __init dcache_init(unsigned long mempages)
{
+ struct list_head *d;
+ unsigned long order;
+ unsigned int nr_hash;
int i;
- struct list_head *d = dentry_hashtable;
/*
* A constructor could be added for stable state like the lists,
@@ -1075,7 +1079,34 @@ void __init dcache_init(void)
if (!dentry_cache)
panic("Cannot create dentry cache");
- i = D_HASHSIZE;
+ mempages >>= (13 - PAGE_SHIFT);
+ mempages *= sizeof(struct list_head);
+ for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++)
+ ;
+
+ do {
+ unsigned long tmp;
+
+ nr_hash = (1UL << order) * PAGE_SIZE /
+ sizeof(struct list_head);
+ d_hash_mask = (nr_hash - 1);
+
+ tmp = nr_hash;
+ d_hash_shift = 0;
+ while ((tmp >>= 1UL) != 0UL)
+ d_hash_shift++;
+
+ dentry_hashtable = (struct list_head *)
+ __get_free_pages(GFP_ATOMIC, order);
+ } while (dentry_hashtable == NULL && --order >= 0);
+
+ if (!dentry_hashtable)
+ panic("Failed to allocate dcache hash table\n");
+
+ printk("VFS: DCACHE hash table configured to %d entries\n", nr_hash);
+
+ d = dentry_hashtable;
+ i = nr_hash;
do {
INIT_LIST_HEAD(d);
d++;