summaryrefslogtreecommitdiffstats
path: root/fs
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
parent3c95f0dce82186de657d828cce420daa0edd9a19 (diff)
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')
-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,
1593} 1593}
1594 1594
1595/* Fast lookup failed, do it the slow way */ 1595/* Fast lookup failed, do it the slow way */
1596static struct dentry *lookup_slow(const struct qstr *name, 1596static struct dentry *__lookup_slow(const struct qstr *name,
1597 struct dentry *dir, 1597 struct dentry *dir,
1598 unsigned int flags) 1598 unsigned int flags)
1599{ 1599{
1600 struct dentry *dentry = ERR_PTR(-ENOENT), *old; 1600 struct dentry *dentry, *old;
1601 struct inode *inode = dir->d_inode; 1601 struct inode *inode = dir->d_inode;
1602 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); 1602 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
1603 1603
1604 inode_lock_shared(inode);
1605 /* Don't go there if it's already dead */ 1604 /* Don't go there if it's already dead */
1606 if (unlikely(IS_DEADDIR(inode))) 1605 if (unlikely(IS_DEADDIR(inode)))
1607 goto out; 1606 return ERR_PTR(-ENOENT);
1608again: 1607again:
1609 dentry = d_alloc_parallel(dir, name, &wq); 1608 dentry = d_alloc_parallel(dir, name, &wq);
1610 if (IS_ERR(dentry)) 1609 if (IS_ERR(dentry))
1611 goto out; 1610 return dentry;
1612 if (unlikely(!d_in_lookup(dentry))) { 1611 if (unlikely(!d_in_lookup(dentry))) {
1613 if (!(flags & LOOKUP_NO_REVAL)) { 1612 if (!(flags & LOOKUP_NO_REVAL)) {
1614 int error = d_revalidate(dentry, flags); 1613 int error = d_revalidate(dentry, flags);
@@ -1630,11 +1629,21 @@ again:
1630 dentry = old; 1629 dentry = old;
1631 } 1630 }
1632 } 1631 }
1633out:
1634 inode_unlock_shared(inode);
1635 return dentry; 1632 return dentry;
1636} 1633}
1637 1634
1635static struct dentry *lookup_slow(const struct qstr *name,
1636 struct dentry *dir,
1637 unsigned int flags)
1638{
1639 struct inode *inode = dir->d_inode;
1640 struct dentry *res;
1641 inode_lock_shared(inode);
1642 res = __lookup_slow(name, dir, flags);
1643 inode_unlock_shared(inode);
1644 return res;
1645}
1646
1638static inline int may_lookup(struct nameidata *nd) 1647static inline int may_lookup(struct nameidata *nd)
1639{ 1648{
1640 if (nd->flags & LOOKUP_RCU) { 1649 if (nd->flags & LOOKUP_RCU) {