summaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2018-04-06 16:43:47 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2018-04-06 16:43:47 -0400
commit88d8331afb0f76ad856770c49a0c0909d123b59c (patch)
treeb99afdee1dd3247aeee30d8b02fe61822fb9672d /fs/namei.c
parent3c95f0dce82186de657d828cce420daa0edd9a19 (diff)
downloadlinux-88d8331afb0f76ad856770c49a0c0909d123b59c.tar.bz2
new helper: __lookup_slow()
lookup_slow() sans locking/unlocking the directory Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/fs/namei.c b/fs/namei.c
index b803c6c6ac95..ba48e154409b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1593,22 +1593,21 @@ static int lookup_fast(struct nameidata *nd,
}
/* Fast lookup failed, do it the slow way */
-static struct dentry *lookup_slow(const struct qstr *name,
- struct dentry *dir,
- unsigned int flags)
+static struct dentry *__lookup_slow(const struct qstr *name,
+ struct dentry *dir,
+ unsigned int flags)
{
- struct dentry *dentry = ERR_PTR(-ENOENT), *old;
+ struct dentry *dentry, *old;
struct inode *inode = dir->d_inode;
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
- inode_lock_shared(inode);
/* Don't go there if it's already dead */
if (unlikely(IS_DEADDIR(inode)))
- goto out;
+ return ERR_PTR(-ENOENT);
again:
dentry = d_alloc_parallel(dir, name, &wq);
if (IS_ERR(dentry))
- goto out;
+ return dentry;
if (unlikely(!d_in_lookup(dentry))) {
if (!(flags & LOOKUP_NO_REVAL)) {
int error = d_revalidate(dentry, flags);
@@ -1630,11 +1629,21 @@ again:
dentry = old;
}
}
-out:
- inode_unlock_shared(inode);
return dentry;
}
+static struct dentry *lookup_slow(const struct qstr *name,
+ struct dentry *dir,
+ unsigned int flags)
+{
+ struct inode *inode = dir->d_inode;
+ struct dentry *res;
+ inode_lock_shared(inode);
+ res = __lookup_slow(name, dir, flags);
+ inode_unlock_shared(inode);
+ return res;
+}
+
static inline int may_lookup(struct nameidata *nd)
{
if (nd->flags & LOOKUP_RCU) {