summaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2018-02-24 04:07:35 +0100
committerAl Viro <viro@zeniv.linux.org.uk>2018-03-29 21:07:42 +0200
commit65d8eb5a8f5480756105173de147ef5d60163e2f (patch)
treeb06ff6ae3eb019432b827bf8620a38630a0f011f /fs/dcache.c
parentget rid of trylock loop in locking dentries on shrink list (diff)
downloadlinux-65d8eb5a8f5480756105173de147ef5d60163e2f.tar.xz
linux-65d8eb5a8f5480756105173de147ef5d60163e2f.zip
now lock_parent() can't run into killed dentry
all remaining callers hold either a reference or ->i_lock Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c13
1 files changed, 3 insertions, 10 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index af8501489af5..916fd57b9d18 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -593,8 +593,6 @@ static inline struct dentry *lock_parent(struct dentry *dentry)
struct dentry *parent = dentry->d_parent;
if (IS_ROOT(dentry))
return NULL;
- if (unlikely(dentry->d_lockref.count < 0))
- return NULL;
if (likely(spin_trylock(&parent->d_lock)))
return parent;
rcu_read_lock();
@@ -614,16 +612,11 @@ again:
spin_unlock(&parent->d_lock);
goto again;
}
- if (parent != dentry) {
+ rcu_read_unlock();
+ if (parent != dentry)
spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
- if (unlikely(dentry->d_lockref.count < 0)) {
- spin_unlock(&parent->d_lock);
- parent = NULL;
- }
- } else {
+ else
parent = NULL;
- }
- rcu_read_unlock();
return parent;
}