@@ -1687,31 +1687,29 @@ static const char *step_into(struct nameidata *nd, int flags,
1687
1687
return pick_link (nd , & path , inode , seq , flags );
1688
1688
}
1689
1689
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 )
1691
1693
{
1692
- struct dentry * parent = NULL ;
1693
- struct inode * inode = nd -> inode ;
1694
- unsigned seq ;
1695
-
1696
1694
while (1 ) {
1697
1695
if (path_equal (& nd -> path , & nd -> root ))
1698
1696
break ;
1699
1697
if (nd -> path .dentry != nd -> path .mnt -> mnt_root ) {
1700
1698
struct dentry * old = nd -> path .dentry ;
1699
+ struct dentry * parent = old -> d_parent ;
1701
1700
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 );
1705
1703
if (unlikely (read_seqcount_retry (& old -> d_seq , nd -> seq )))
1706
1704
return ERR_PTR (- ECHILD );
1707
1705
if (unlikely (!path_connected (nd -> path .mnt , parent )))
1708
1706
return ERR_PTR (- ECHILD );
1709
- break ;
1707
+ return parent ;
1710
1708
} else {
1711
1709
struct mount * mnt = real_mount (nd -> path .mnt );
1712
1710
struct mount * mparent = mnt -> mnt_parent ;
1713
1711
struct dentry * mountpoint = mnt -> mnt_mountpoint ;
1714
- struct inode * inode2 = mountpoint -> d_inode ;
1712
+ struct inode * inode = mountpoint -> d_inode ;
1715
1713
unsigned seq = read_seqcount_begin (& mountpoint -> d_seq );
1716
1714
if (unlikely (read_seqretry (& mount_lock , nd -> m_seq )))
1717
1715
return ERR_PTR (- ECHILD );
@@ -1722,65 +1720,70 @@ static const char *follow_dotdot_rcu(struct nameidata *nd)
1722
1720
/* we know that mountpoint was pinned */
1723
1721
nd -> path .dentry = mountpoint ;
1724
1722
nd -> path .mnt = & mparent -> mnt ;
1725
- inode = nd -> inode = inode2 ;
1723
+ nd -> inode = inode ;
1726
1724
nd -> seq = seq ;
1727
1725
}
1728
1726
}
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 ;
1737
1730
}
1738
1731
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 )
1740
1735
{
1741
- struct dentry * parent = NULL ;
1742
1736
while (1 ) {
1743
1737
if (path_equal (& nd -> path , & nd -> root ))
1744
1738
break ;
1745
1739
if (nd -> path .dentry != nd -> path .mnt -> mnt_root ) {
1746
1740
/* rare case of legitimate dget_parent()... */
1747
- parent = dget_parent (nd -> path .dentry );
1741
+ struct dentry * parent = dget_parent (nd -> path .dentry );
1748
1742
if (unlikely (!path_connected (nd -> path .mnt , parent ))) {
1749
1743
dput (parent );
1750
1744
return ERR_PTR (- ENOENT );
1751
1745
}
1752
- break ;
1746
+ * seqp = 0 ;
1747
+ * inodep = parent -> d_inode ;
1748
+ return parent ;
1753
1749
}
1754
1750
if (!follow_up (& nd -> path ))
1755
1751
break ;
1756
1752
if (unlikely (nd -> flags & LOOKUP_NO_XDEV ))
1757
1753
return ERR_PTR (- EXDEV );
1758
1754
}
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 ;
1767
1759
}
1768
1760
1769
1761
static const char * handle_dots (struct nameidata * nd , int type )
1770
1762
{
1771
1763
if (type == LAST_DOTDOT ) {
1772
1764
const char * error = NULL ;
1765
+ struct dentry * parent ;
1766
+ struct inode * inode ;
1767
+ unsigned seq ;
1773
1768
1774
1769
if (!nd -> root .mnt ) {
1775
1770
error = ERR_PTR (set_root (nd ));
1776
1771
if (error )
1777
1772
return error ;
1778
1773
}
1779
1774
if (nd -> flags & LOOKUP_RCU )
1780
- error = follow_dotdot_rcu (nd );
1775
+ parent = follow_dotdot_rcu (nd , & inode , & seq );
1781
1776
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 ))
1784
1787
return error ;
1785
1788
1786
1789
if (unlikely (nd -> flags & LOOKUP_IS_SCOPED )) {
0 commit comments