Commit 66ca0978 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] more dentry shrinkage

- d_vfs_flags can be removed - just use d_flags.  All modifications of
  dentry->d_flags are under dentry->d_lock.

On x86 this takes the internal string size up to 40 bytes.  The
internal/external ratio on my 1.5M files hits 96%.
parent b7b5563e
...@@ -168,7 +168,7 @@ void dput(struct dentry *dentry) ...@@ -168,7 +168,7 @@ void dput(struct dentry *dentry)
if (d_unhashed(dentry)) if (d_unhashed(dentry))
goto kill_it; goto kill_it;
if (list_empty(&dentry->d_lru)) { if (list_empty(&dentry->d_lru)) {
dentry->d_vfs_flags |= DCACHE_REFERENCED; dentry->d_flags |= DCACHE_REFERENCED;
list_add(&dentry->d_lru, &dentry_unused); list_add(&dentry->d_lru, &dentry_unused);
dentry_stat.nr_unused++; dentry_stat.nr_unused++;
} }
...@@ -401,8 +401,8 @@ static void prune_dcache(int count) ...@@ -401,8 +401,8 @@ static void prune_dcache(int count)
continue; continue;
} }
/* If the dentry was recently referenced, don't free it. */ /* If the dentry was recently referenced, don't free it. */
if (dentry->d_vfs_flags & DCACHE_REFERENCED) { if (dentry->d_flags & DCACHE_REFERENCED) {
dentry->d_vfs_flags &= ~DCACHE_REFERENCED; dentry->d_flags &= ~DCACHE_REFERENCED;
list_add(&dentry->d_lru, &dentry_unused); list_add(&dentry->d_lru, &dentry_unused);
dentry_stat.nr_unused++; dentry_stat.nr_unused++;
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
...@@ -707,9 +707,8 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) ...@@ -707,9 +707,8 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
dname[name->len] = 0; dname[name->len] = 0;
atomic_set(&dentry->d_count, 1); atomic_set(&dentry->d_count, 1);
dentry->d_vfs_flags = DCACHE_UNHASHED; dentry->d_flags = DCACHE_UNHASHED;
dentry->d_lock = SPIN_LOCK_UNLOCKED; dentry->d_lock = SPIN_LOCK_UNLOCKED;
dentry->d_flags = 0;
dentry->d_inode = NULL; dentry->d_inode = NULL;
dentry->d_parent = NULL; dentry->d_parent = NULL;
dentry->d_sb = NULL; dentry->d_sb = NULL;
...@@ -854,7 +853,7 @@ struct dentry * d_alloc_anon(struct inode *inode) ...@@ -854,7 +853,7 @@ struct dentry * d_alloc_anon(struct inode *inode)
res->d_inode = inode; res->d_inode = inode;
res->d_bucket = d_hash(res, res->d_name.hash); res->d_bucket = d_hash(res, res->d_name.hash);
res->d_flags |= DCACHE_DISCONNECTED; res->d_flags |= DCACHE_DISCONNECTED;
res->d_vfs_flags &= ~DCACHE_UNHASHED; res->d_flags &= ~DCACHE_UNHASHED;
list_add(&res->d_alias, &inode->i_dentry); list_add(&res->d_alias, &inode->i_dentry);
hlist_add_head(&res->d_hash, &inode->i_sb->s_anon); hlist_add_head(&res->d_hash, &inode->i_sb->s_anon);
spin_unlock(&res->d_lock); spin_unlock(&res->d_lock);
...@@ -1117,9 +1116,10 @@ void d_delete(struct dentry * dentry) ...@@ -1117,9 +1116,10 @@ void d_delete(struct dentry * dentry)
void d_rehash(struct dentry * entry) void d_rehash(struct dentry * entry)
{ {
struct hlist_head *list = d_hash(entry->d_parent, entry->d_name.hash); struct hlist_head *list = d_hash(entry->d_parent, entry->d_name.hash);
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
spin_lock(&entry->d_lock); spin_lock(&entry->d_lock);
entry->d_vfs_flags &= ~DCACHE_UNHASHED; entry->d_flags &= ~DCACHE_UNHASHED;
spin_unlock(&entry->d_lock); spin_unlock(&entry->d_lock);
entry->d_bucket = list; entry->d_bucket = list;
hlist_add_head_rcu(&entry->d_hash, list); hlist_add_head_rcu(&entry->d_hash, list);
...@@ -1217,14 +1217,14 @@ void d_move(struct dentry * dentry, struct dentry * target) ...@@ -1217,14 +1217,14 @@ void d_move(struct dentry * dentry, struct dentry * target)
} }
/* Move the dentry to the target hash queue, if on different bucket */ /* Move the dentry to the target hash queue, if on different bucket */
if (dentry->d_vfs_flags & DCACHE_UNHASHED) if (dentry->d_flags & DCACHE_UNHASHED)
goto already_unhashed; goto already_unhashed;
if (dentry->d_bucket != target->d_bucket) { if (dentry->d_bucket != target->d_bucket) {
hlist_del_rcu(&dentry->d_hash); hlist_del_rcu(&dentry->d_hash);
already_unhashed: already_unhashed:
dentry->d_bucket = target->d_bucket; dentry->d_bucket = target->d_bucket;
hlist_add_head_rcu(&dentry->d_hash, target->d_bucket); hlist_add_head_rcu(&dentry->d_hash, target->d_bucket);
dentry->d_vfs_flags &= ~DCACHE_UNHASHED; dentry->d_flags &= ~DCACHE_UNHASHED;
} }
/* Unhash the target: dput() will then get rid of it */ /* Unhash the target: dput() will then get rid of it */
......
...@@ -74,28 +74,28 @@ full_name_hash(const unsigned char *name, unsigned int len) ...@@ -74,28 +74,28 @@ full_name_hash(const unsigned char *name, unsigned int len)
} }
struct dcookie_struct; struct dcookie_struct;
struct dentry { struct dentry {
atomic_t d_count; atomic_t d_count;
unsigned int d_flags; /* protected by d_lock */
spinlock_t d_lock; /* per dentry lock */ spinlock_t d_lock; /* per dentry lock */
unsigned long d_vfs_flags; /* moved here to be on same cacheline */ struct inode *d_inode; /* Where the name belongs to - NULL is
struct inode * d_inode; /* Where the name belongs to - NULL is negative */ * negative */
struct list_head d_lru; /* LRU list */ struct list_head d_lru; /* LRU list */
struct list_head d_child; /* child of parent list */ struct list_head d_child; /* child of parent list */
struct list_head d_subdirs; /* our children */ struct list_head d_subdirs; /* our children */
struct list_head d_alias; /* inode alias list */ struct list_head d_alias; /* inode alias list */
unsigned long d_time; /* used by d_revalidate */ unsigned long d_time; /* used by d_revalidate */
struct dentry_operations *d_op; struct dentry_operations *d_op;
struct super_block * d_sb; /* The root of the dentry tree */ struct super_block *d_sb; /* The root of the dentry tree */
unsigned int d_flags;
int d_mounted; int d_mounted;
void * d_fsdata; /* fs-specific data */ void *d_fsdata; /* fs-specific data */
struct rcu_head d_rcu; struct rcu_head d_rcu;
struct dcookie_struct * d_cookie; /* cookie, if any */ struct dcookie_struct *d_cookie; /* cookie, if any */
struct dentry * d_parent; /* parent directory */ struct dentry *d_parent; /* parent directory */
struct qstr d_name; struct qstr d_name;
struct hlist_node d_hash; /* lookup hash list */ struct hlist_node d_hash; /* lookup hash list */
struct hlist_head * d_bucket; /* lookup hash bucket */ struct hlist_head *d_bucket; /* lookup hash bucket */
unsigned char d_iname[0]; /* small names */ unsigned char d_iname[0]; /* small names */
}; };
...@@ -168,8 +168,8 @@ extern spinlock_t dcache_lock; ...@@ -168,8 +168,8 @@ extern spinlock_t dcache_lock;
static inline void __d_drop(struct dentry *dentry) static inline void __d_drop(struct dentry *dentry)
{ {
if (!(dentry->d_vfs_flags & DCACHE_UNHASHED)) { if (!(dentry->d_flags & DCACHE_UNHASHED)) {
dentry->d_vfs_flags |= DCACHE_UNHASHED; dentry->d_flags |= DCACHE_UNHASHED;
hlist_del_rcu(&dentry->d_hash); hlist_del_rcu(&dentry->d_hash);
} }
} }
...@@ -280,7 +280,7 @@ extern struct dentry * dget_locked(struct dentry *); ...@@ -280,7 +280,7 @@ extern struct dentry * dget_locked(struct dentry *);
static inline int d_unhashed(struct dentry *dentry) static inline int d_unhashed(struct dentry *dentry)
{ {
return (dentry->d_vfs_flags & DCACHE_UNHASHED); return (dentry->d_flags & DCACHE_UNHASHED);
} }
static inline struct dentry *dget_parent(struct dentry *dentry) static inline struct dentry *dget_parent(struct dentry *dentry)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment