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 | |
parent | 3c95f0dce82186de657d828cce420daa0edd9a19 (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.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, | |||
1593 | } | 1593 | } |
1594 | 1594 | ||
1595 | /* Fast lookup failed, do it the slow way */ | 1595 | /* Fast lookup failed, do it the slow way */ |
1596 | static struct dentry *lookup_slow(const struct qstr *name, | 1596 | static 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); |
1608 | again: | 1607 | again: |
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 | } |
1633 | out: | ||
1634 | inode_unlock_shared(inode); | ||
1635 | return dentry; | 1632 | return dentry; |
1636 | } | 1633 | } |
1637 | 1634 | ||
1635 | static 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 | |||
1638 | static inline int may_lookup(struct nameidata *nd) | 1647 | static inline int may_lookup(struct nameidata *nd) |
1639 | { | 1648 | { |
1640 | if (nd->flags & LOOKUP_RCU) { | 1649 | if (nd->flags & LOOKUP_RCU) { |