Skip to content

Commit c2df196

Browse files
author
Al Viro
committed
lift all calls of step_into() out of follow_dotdot/follow_dotdot_rcu
lift step_into() into handle_dots() (where they merge with each other); have follow_... return dentry and pass inode/seq to the caller. [braino fix folded; kudos to Qian Cai <[email protected]> for reporting it] Signed-off-by: Al Viro <[email protected]>
1 parent 6dfd9fe commit c2df196

File tree

1 file changed

+37
-34
lines changed

1 file changed

+37
-34
lines changed

fs/namei.c

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1687,31 +1687,29 @@ static const char *step_into(struct nameidata *nd, int flags,
16871687
return pick_link(nd, &path, inode, seq, flags);
16881688
}
16891689

1690-
static const char *follow_dotdot_rcu(struct nameidata *nd)
1690+
static struct dentry *follow_dotdot_rcu(struct nameidata *nd,
1691+
struct inode **inodep,
1692+
unsigned *seqp)
16911693
{
1692-
struct dentry *parent = NULL;
1693-
struct inode *inode = nd->inode;
1694-
unsigned seq;
1695-
16961694
while (1) {
16971695
if (path_equal(&nd->path, &nd->root))
16981696
break;
16991697
if (nd->path.dentry != nd->path.mnt->mnt_root) {
17001698
struct dentry *old = nd->path.dentry;
1699+
struct dentry *parent = old->d_parent;
17011700

1702-
parent = old->d_parent;
1703-
inode = parent->d_inode;
1704-
seq = read_seqcount_begin(&parent->d_seq);
1701+
*inodep = parent->d_inode;
1702+
*seqp = read_seqcount_begin(&parent->d_seq);
17051703
if (unlikely(read_seqcount_retry(&old->d_seq, nd->seq)))
17061704
return ERR_PTR(-ECHILD);
17071705
if (unlikely(!path_connected(nd->path.mnt, parent)))
17081706
return ERR_PTR(-ECHILD);
1709-
break;
1707+
return parent;
17101708
} else {
17111709
struct mount *mnt = real_mount(nd->path.mnt);
17121710
struct mount *mparent = mnt->mnt_parent;
17131711
struct dentry *mountpoint = mnt->mnt_mountpoint;
1714-
struct inode *inode2 = mountpoint->d_inode;
1712+
struct inode *inode = mountpoint->d_inode;
17151713
unsigned seq = read_seqcount_begin(&mountpoint->d_seq);
17161714
if (unlikely(read_seqretry(&mount_lock, nd->m_seq)))
17171715
return ERR_PTR(-ECHILD);
@@ -1722,65 +1720,70 @@ static const char *follow_dotdot_rcu(struct nameidata *nd)
17221720
/* we know that mountpoint was pinned */
17231721
nd->path.dentry = mountpoint;
17241722
nd->path.mnt = &mparent->mnt;
1725-
inode = nd->inode = inode2;
1723+
nd->inode = inode;
17261724
nd->seq = seq;
17271725
}
17281726
}
1729-
if (unlikely(!parent)) {
1730-
if (unlikely(nd->flags & LOOKUP_BENEATH))
1731-
return ERR_PTR(-ECHILD);
1732-
return step_into(nd, WALK_NOFOLLOW,
1733-
nd->path.dentry, nd->inode, nd->seq);
1734-
} else {
1735-
return step_into(nd, WALK_NOFOLLOW, parent, inode, seq);
1736-
}
1727+
if (unlikely(nd->flags & LOOKUP_BENEATH))
1728+
return ERR_PTR(-ECHILD);
1729+
return NULL;
17371730
}
17381731

1739-
static const char *follow_dotdot(struct nameidata *nd)
1732+
static struct dentry *follow_dotdot(struct nameidata *nd,
1733+
struct inode **inodep,
1734+
unsigned *seqp)
17401735
{
1741-
struct dentry *parent = NULL;
17421736
while (1) {
17431737
if (path_equal(&nd->path, &nd->root))
17441738
break;
17451739
if (nd->path.dentry != nd->path.mnt->mnt_root) {
17461740
/* rare case of legitimate dget_parent()... */
1747-
parent = dget_parent(nd->path.dentry);
1741+
struct dentry *parent = dget_parent(nd->path.dentry);
17481742
if (unlikely(!path_connected(nd->path.mnt, parent))) {
17491743
dput(parent);
17501744
return ERR_PTR(-ENOENT);
17511745
}
1752-
break;
1746+
*seqp = 0;
1747+
*inodep = parent->d_inode;
1748+
return parent;
17531749
}
17541750
if (!follow_up(&nd->path))
17551751
break;
17561752
if (unlikely(nd->flags & LOOKUP_NO_XDEV))
17571753
return ERR_PTR(-EXDEV);
17581754
}
1759-
if (unlikely(!parent)) {
1760-
if (unlikely(nd->flags & LOOKUP_BENEATH))
1761-
return ERR_PTR(-EXDEV);
1762-
return step_into(nd, WALK_NOFOLLOW,
1763-
dget(nd->path.dentry), nd->inode, nd->seq);
1764-
} else {
1765-
return step_into(nd, WALK_NOFOLLOW, parent, parent->d_inode, 0);
1766-
}
1755+
if (unlikely(nd->flags & LOOKUP_BENEATH))
1756+
return ERR_PTR(-EXDEV);
1757+
dget(nd->path.dentry);
1758+
return NULL;
17671759
}
17681760

17691761
static const char *handle_dots(struct nameidata *nd, int type)
17701762
{
17711763
if (type == LAST_DOTDOT) {
17721764
const char *error = NULL;
1765+
struct dentry *parent;
1766+
struct inode *inode;
1767+
unsigned seq;
17731768

17741769
if (!nd->root.mnt) {
17751770
error = ERR_PTR(set_root(nd));
17761771
if (error)
17771772
return error;
17781773
}
17791774
if (nd->flags & LOOKUP_RCU)
1780-
error = follow_dotdot_rcu(nd);
1775+
parent = follow_dotdot_rcu(nd, &inode, &seq);
17811776
else
1782-
error = follow_dotdot(nd);
1783-
if (error)
1777+
parent = follow_dotdot(nd, &inode, &seq);
1778+
if (IS_ERR(parent))
1779+
return ERR_CAST(parent);
1780+
if (unlikely(!parent))
1781+
error = step_into(nd, WALK_NOFOLLOW,
1782+
nd->path.dentry, nd->inode, nd->seq);
1783+
else
1784+
error = step_into(nd, WALK_NOFOLLOW,
1785+
parent, inode, seq);
1786+
if (unlikely(error))
17841787
return error;
17851788

17861789
if (unlikely(nd->flags & LOOKUP_IS_SCOPED)) {

0 commit comments

Comments
 (0)