@@ -605,10 +605,9 @@ static void terminate_walk(struct nameidata *nd)
605
605
}
606
606
607
607
/* path_put is needed afterwards regardless of success or failure */
608
- static bool legitimize_path (struct nameidata * nd ,
609
- struct path * path , unsigned seq )
608
+ static bool __legitimize_path (struct path * path , unsigned seq , unsigned mseq )
610
609
{
611
- int res = __legitimize_mnt (path -> mnt , nd -> m_seq );
610
+ int res = __legitimize_mnt (path -> mnt , mseq );
612
611
if (unlikely (res )) {
613
612
if (res > 0 )
614
613
path -> mnt = NULL ;
@@ -622,6 +621,12 @@ static bool legitimize_path(struct nameidata *nd,
622
621
return !read_seqcount_retry (& path -> dentry -> d_seq , seq );
623
622
}
624
623
624
+ static inline bool legitimize_path (struct nameidata * nd ,
625
+ struct path * path , unsigned seq )
626
+ {
627
+ return __legitimize_path (path , nd -> m_seq , seq );
628
+ }
629
+
625
630
static bool legitimize_links (struct nameidata * nd )
626
631
{
627
632
int i ;
@@ -1154,6 +1159,31 @@ static bool choose_mountpoint_rcu(struct mount *m, const struct path *root,
1154
1159
return false;
1155
1160
}
1156
1161
1162
+ static bool choose_mountpoint (struct mount * m , const struct path * root ,
1163
+ struct path * path )
1164
+ {
1165
+ bool found ;
1166
+
1167
+ rcu_read_lock ();
1168
+ while (1 ) {
1169
+ unsigned seq , mseq = read_seqbegin (& mount_lock );
1170
+
1171
+ found = choose_mountpoint_rcu (m , root , path , & seq );
1172
+ if (unlikely (!found )) {
1173
+ if (!read_seqretry (& mount_lock , mseq ))
1174
+ break ;
1175
+ } else {
1176
+ if (likely (__legitimize_path (path , seq , mseq )))
1177
+ break ;
1178
+ rcu_read_unlock ();
1179
+ path_put (path );
1180
+ rcu_read_lock ();
1181
+ }
1182
+ }
1183
+ rcu_read_unlock ();
1184
+ return found ;
1185
+ }
1186
+
1157
1187
/*
1158
1188
* Perform an automount
1159
1189
* - return -EISDIR to tell follow_managed() to stop and return the path we
@@ -1756,22 +1786,14 @@ static struct dentry *follow_dotdot(struct nameidata *nd,
1756
1786
if (path_equal (& nd -> path , & nd -> root ))
1757
1787
goto in_root ;
1758
1788
if (unlikely (nd -> path .dentry == nd -> path .mnt -> mnt_root )) {
1759
- struct path path = nd -> path ;
1760
- path_get (& path );
1761
- while (1 ) {
1762
- if (!follow_up (& path )) {
1763
- path_put (& path );
1764
- goto in_root ;
1765
- }
1766
- if (path_equal (& path , & nd -> root )) {
1767
- path_put (& path );
1768
- goto in_root ;
1769
- }
1770
- if (path .dentry != nd -> path .mnt -> mnt_root )
1771
- break ;
1772
- }
1789
+ struct path path ;
1790
+
1791
+ if (!choose_mountpoint (real_mount (nd -> path .mnt ),
1792
+ & nd -> root , & path ))
1793
+ goto in_root ;
1773
1794
path_put (& nd -> path );
1774
1795
nd -> path = path ;
1796
+ nd -> inode = path .dentry -> d_inode ;
1775
1797
if (unlikely (nd -> flags & LOOKUP_NO_XDEV ))
1776
1798
return ERR_PTR (- EXDEV );
1777
1799
}
0 commit comments