Merge branch 'dcache-cleanup'
* dcache-cleanup: vfs: get rid of insane dentry hashing rules
This commit is contained in:
42
fs/dcache.c
42
fs/dcache.c
@@ -164,8 +164,8 @@ static void d_free(struct dentry *dentry)
|
|||||||
if (dentry->d_op && dentry->d_op->d_release)
|
if (dentry->d_op && dentry->d_op->d_release)
|
||||||
dentry->d_op->d_release(dentry);
|
dentry->d_op->d_release(dentry);
|
||||||
|
|
||||||
/* if dentry was never inserted into hash, immediate free is OK */
|
/* if dentry was never visible to RCU, immediate free is OK */
|
||||||
if (hlist_bl_unhashed(&dentry->d_hash))
|
if (!(dentry->d_flags & DCACHE_RCUACCESS))
|
||||||
__d_free(&dentry->d_u.d_rcu);
|
__d_free(&dentry->d_u.d_rcu);
|
||||||
else
|
else
|
||||||
call_rcu(&dentry->d_u.d_rcu, __d_free);
|
call_rcu(&dentry->d_u.d_rcu, __d_free);
|
||||||
@@ -327,28 +327,19 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
|
|||||||
*/
|
*/
|
||||||
void __d_drop(struct dentry *dentry)
|
void __d_drop(struct dentry *dentry)
|
||||||
{
|
{
|
||||||
if (!(dentry->d_flags & DCACHE_UNHASHED)) {
|
if (!d_unhashed(dentry)) {
|
||||||
struct hlist_bl_head *b;
|
struct hlist_bl_head *b;
|
||||||
if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) {
|
if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED))
|
||||||
b = &dentry->d_sb->s_anon;
|
b = &dentry->d_sb->s_anon;
|
||||||
spin_lock_bucket(b);
|
else
|
||||||
dentry->d_flags |= DCACHE_UNHASHED;
|
|
||||||
hlist_bl_del_init(&dentry->d_hash);
|
|
||||||
spin_unlock_bucket(b);
|
|
||||||
} else {
|
|
||||||
struct hlist_bl_head *b;
|
|
||||||
b = d_hash(dentry->d_parent, dentry->d_name.hash);
|
b = d_hash(dentry->d_parent, dentry->d_name.hash);
|
||||||
spin_lock_bucket(b);
|
|
||||||
/*
|
spin_lock_bucket(b);
|
||||||
* We may not actually need to put DCACHE_UNHASHED
|
__hlist_bl_del(&dentry->d_hash);
|
||||||
* manipulations under the hash lock, but follow
|
dentry->d_hash.pprev = NULL;
|
||||||
* the principle of least surprise.
|
spin_unlock_bucket(b);
|
||||||
*/
|
|
||||||
dentry->d_flags |= DCACHE_UNHASHED;
|
dentry_rcuwalk_barrier(dentry);
|
||||||
hlist_bl_del_rcu(&dentry->d_hash);
|
|
||||||
spin_unlock_bucket(b);
|
|
||||||
dentry_rcuwalk_barrier(dentry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__d_drop);
|
EXPORT_SYMBOL(__d_drop);
|
||||||
@@ -1301,7 +1292,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
|
|||||||
dname[name->len] = 0;
|
dname[name->len] = 0;
|
||||||
|
|
||||||
dentry->d_count = 1;
|
dentry->d_count = 1;
|
||||||
dentry->d_flags = DCACHE_UNHASHED;
|
dentry->d_flags = 0;
|
||||||
spin_lock_init(&dentry->d_lock);
|
spin_lock_init(&dentry->d_lock);
|
||||||
seqcount_init(&dentry->d_seq);
|
seqcount_init(&dentry->d_seq);
|
||||||
dentry->d_inode = NULL;
|
dentry->d_inode = NULL;
|
||||||
@@ -1603,10 +1594,9 @@ struct dentry *d_obtain_alias(struct inode *inode)
|
|||||||
tmp->d_inode = inode;
|
tmp->d_inode = inode;
|
||||||
tmp->d_flags |= DCACHE_DISCONNECTED;
|
tmp->d_flags |= DCACHE_DISCONNECTED;
|
||||||
list_add(&tmp->d_alias, &inode->i_dentry);
|
list_add(&tmp->d_alias, &inode->i_dentry);
|
||||||
bit_spin_lock(0, (unsigned long *)&tmp->d_sb->s_anon.first);
|
spin_lock_bucket(&tmp->d_sb->s_anon);
|
||||||
tmp->d_flags &= ~DCACHE_UNHASHED;
|
|
||||||
hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon);
|
hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon);
|
||||||
__bit_spin_unlock(0, (unsigned long *)&tmp->d_sb->s_anon.first);
|
spin_unlock_bucket(&tmp->d_sb->s_anon);
|
||||||
spin_unlock(&tmp->d_lock);
|
spin_unlock(&tmp->d_lock);
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
security_d_instantiate(tmp, inode);
|
security_d_instantiate(tmp, inode);
|
||||||
@@ -2087,7 +2077,7 @@ static void __d_rehash(struct dentry * entry, struct hlist_bl_head *b)
|
|||||||
{
|
{
|
||||||
BUG_ON(!d_unhashed(entry));
|
BUG_ON(!d_unhashed(entry));
|
||||||
spin_lock_bucket(b);
|
spin_lock_bucket(b);
|
||||||
entry->d_flags &= ~DCACHE_UNHASHED;
|
entry->d_flags |= DCACHE_RCUACCESS;
|
||||||
hlist_bl_add_head_rcu(&entry->d_hash, b);
|
hlist_bl_add_head_rcu(&entry->d_hash, b);
|
||||||
spin_unlock_bucket(b);
|
spin_unlock_bucket(b);
|
||||||
}
|
}
|
||||||
|
@@ -197,7 +197,7 @@ struct dentry_operations {
|
|||||||
* typically using d_splice_alias. */
|
* typically using d_splice_alias. */
|
||||||
|
|
||||||
#define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */
|
#define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */
|
||||||
#define DCACHE_UNHASHED 0x0010
|
#define DCACHE_RCUACCESS 0x0010 /* Entry has ever been RCU-visible */
|
||||||
#define DCACHE_INOTIFY_PARENT_WATCHED 0x0020
|
#define DCACHE_INOTIFY_PARENT_WATCHED 0x0020
|
||||||
/* Parent inode is watched by inotify */
|
/* Parent inode is watched by inotify */
|
||||||
|
|
||||||
@@ -384,7 +384,7 @@ extern struct dentry *dget_parent(struct dentry *dentry);
|
|||||||
|
|
||||||
static inline int d_unhashed(struct dentry *dentry)
|
static inline int d_unhashed(struct dentry *dentry)
|
||||||
{
|
{
|
||||||
return (dentry->d_flags & DCACHE_UNHASHED);
|
return hlist_bl_unhashed(&dentry->d_hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int d_unlinked(struct dentry *dentry)
|
static inline int d_unlinked(struct dentry *dentry)
|
||||||
|
Reference in New Issue
Block a user