summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2018-02-24 04:11:34 +0100
committerAl Viro <viro@zeniv.linux.org.uk>2018-03-29 21:07:42 +0200
commit8b987a46a1e0e93d4cb4babea06ea274e2e2b658 (patch)
tree3aef2007f7a60a820066cd3c1203d66bb3eee810
parentnow lock_parent() can't run into killed dentry (diff)
downloadlinux-8b987a46a1e0e93d4cb4babea06ea274e2e2b658.tar.xz
linux-8b987a46a1e0e93d4cb4babea06ea274e2e2b658.zip
split the slow part of lock_parent() off
Turn the "trylock failed" part into uninlined __lock_parent(). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/dcache.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 916fd57b9d18..61819fb32e13 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -588,13 +588,9 @@ static void __dentry_kill(struct dentry *dentry)
dentry_free(dentry);
}
-static inline struct dentry *lock_parent(struct dentry *dentry)
+static struct dentry *__lock_parent(struct dentry *dentry)
{
- struct dentry *parent = dentry->d_parent;
- if (IS_ROOT(dentry))
- return NULL;
- if (likely(spin_trylock(&parent->d_lock)))
- return parent;
+ struct dentry *parent;
rcu_read_lock();
spin_unlock(&dentry->d_lock);
again:
@@ -620,6 +616,16 @@ again:
return parent;
}
+static inline struct dentry *lock_parent(struct dentry *dentry)
+{
+ struct dentry *parent = dentry->d_parent;
+ if (IS_ROOT(dentry))
+ return NULL;
+ if (likely(spin_trylock(&parent->d_lock)))
+ return parent;
+ return __lock_parent(dentry);
+}
+
/*
* Finish off a dentry we've decided to kill.
* dentry->d_lock must be held, returns with it unlocked.