diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-09-14 17:37:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-09-14 17:37:36 -0700 |
commit | 83373f702829dd9f6dcc56d275978d986fafee48 (patch) | |
tree | 6e816715ce2e9ea73da8b8462953262f47460897 /fs/dcache.c | |
parent | 9226b5b440f2b4fbb3b797f3cb74a9a627220660 (diff) | |
parent | 4023bfc9f351a7994fb6a7d515476c320f94a574 (diff) | |
download | linux-stable-83373f702829dd9f6dcc56d275978d986fafee48.tar.gz linux-stable-83373f702829dd9f6dcc56d275978d986fafee48.tar.bz2 linux-stable-83373f702829dd9f6dcc56d275978d986fafee48.zip |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro:
"double iput() on failure exit in lustre, racy removal of spliced
dentries from ->s_anon in __d_materialise_dentry() plus a bunch of
assorted RCU pathwalk fixes"
The RCU pathwalk fixes end up fixing a couple of cases where we
incorrectly dropped out of RCU walking, due to incorrect initialization
and testing of the sequence locks in some corner cases. Since dropping
out of RCU walk mode forces the slow locked accesses, those corner cases
slowed down quite dramatically.
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
be careful with nd->inode in path_init() and follow_dotdot_rcu()
don't bugger nd->seq on set_root_rcu() from follow_dotdot_rcu()
fix bogus read_seqretry() checks introduced in b37199e
move the call of __d_drop(anon) into __d_materialise_unique(dentry, anon)
[fix] lustre: d_make_root() does iput() on dentry allocation failure
Diffstat (limited to 'fs/dcache.c')
-rw-r--r-- | fs/dcache.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 4023e77b800e..7a5b51440afa 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -2655,6 +2655,12 @@ static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon) dentry->d_parent = dentry; list_del_init(&dentry->d_u.d_child); anon->d_parent = dparent; + if (likely(!d_unhashed(anon))) { + hlist_bl_lock(&anon->d_sb->s_anon); + __hlist_bl_del(&anon->d_hash); + anon->d_hash.pprev = NULL; + hlist_bl_unlock(&anon->d_sb->s_anon); + } list_move(&anon->d_u.d_child, &dparent->d_subdirs); write_seqcount_end(&dentry->d_seq); @@ -2713,7 +2719,6 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) write_seqlock(&rename_lock); __d_materialise_dentry(dentry, new); write_sequnlock(&rename_lock); - __d_drop(new); _d_rehash(new); spin_unlock(&new->d_lock); spin_unlock(&inode->i_lock); @@ -2777,7 +2782,6 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) * could splice into our tree? */ __d_materialise_dentry(dentry, alias); write_sequnlock(&rename_lock); - __d_drop(alias); goto found; } else { /* Nope, but we must(!) avoid directory |