diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2018-04-06 16:43:47 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2018-04-06 16:43:47 -0400 |
commit | 88d8331afb0f76ad856770c49a0c0909d123b59c (patch) | |
tree | b99afdee1dd3247aeee30d8b02fe61822fb9672d /fs/namei.c | |
parent | 3c95f0dce82186de657d828cce420daa0edd9a19 (diff) | |
download | lwn-88d8331afb0f76ad856770c49a0c0909d123b59c.tar.gz lwn-88d8331afb0f76ad856770c49a0c0909d123b59c.zip |
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.c | 27 |
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) { |