Loading fs/dcache.c +16 −26 Original line number Original line Diff line number Diff line Loading @@ -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); Loading Loading @@ -327,30 +327,21 @@ 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); /* __hlist_bl_del(&dentry->d_hash); * We may not actually need to put DCACHE_UNHASHED dentry->d_hash.pprev = NULL; * manipulations under the hash lock, but follow * the principle of least surprise. */ dentry->d_flags |= DCACHE_UNHASHED; hlist_bl_del_rcu(&dentry->d_hash); spin_unlock_bucket(b); spin_unlock_bucket(b); dentry_rcuwalk_barrier(dentry); dentry_rcuwalk_barrier(dentry); } } } } } EXPORT_SYMBOL(__d_drop); EXPORT_SYMBOL(__d_drop); void d_drop(struct dentry *dentry) void d_drop(struct dentry *dentry) Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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); } } Loading include/linux/dcache.h +2 −2 Original line number Original line Diff line number Diff line Loading @@ -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 */ Loading Loading @@ -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) Loading Loading
fs/dcache.c +16 −26 Original line number Original line Diff line number Diff line Loading @@ -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); Loading Loading @@ -327,30 +327,21 @@ 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); /* __hlist_bl_del(&dentry->d_hash); * We may not actually need to put DCACHE_UNHASHED dentry->d_hash.pprev = NULL; * manipulations under the hash lock, but follow * the principle of least surprise. */ dentry->d_flags |= DCACHE_UNHASHED; hlist_bl_del_rcu(&dentry->d_hash); spin_unlock_bucket(b); spin_unlock_bucket(b); dentry_rcuwalk_barrier(dentry); dentry_rcuwalk_barrier(dentry); } } } } } EXPORT_SYMBOL(__d_drop); EXPORT_SYMBOL(__d_drop); void d_drop(struct dentry *dentry) void d_drop(struct dentry *dentry) Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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); } } Loading
include/linux/dcache.h +2 −2 Original line number Original line Diff line number Diff line Loading @@ -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 */ Loading Loading @@ -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) Loading