aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/namei.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/fs/namei.c b/fs/namei.c
index fe47e6d8e85f..d07bc1b206c3 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1142,6 +1142,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
1142 1142
1143static int follow_dotdot_rcu(struct nameidata *nd) 1143static int follow_dotdot_rcu(struct nameidata *nd)
1144{ 1144{
1145 struct inode *inode = nd->inode;
1145 if (!nd->root.mnt) 1146 if (!nd->root.mnt)
1146 set_root_rcu(nd); 1147 set_root_rcu(nd);
1147 1148
@@ -1155,6 +1156,7 @@ static int follow_dotdot_rcu(struct nameidata *nd)
1155 struct dentry *parent = old->d_parent; 1156 struct dentry *parent = old->d_parent;
1156 unsigned seq; 1157 unsigned seq;
1157 1158
1159 inode = parent->d_inode;
1158 seq = read_seqcount_begin(&parent->d_seq); 1160 seq = read_seqcount_begin(&parent->d_seq);
1159 if (read_seqcount_retry(&old->d_seq, nd->seq)) 1161 if (read_seqcount_retry(&old->d_seq, nd->seq))
1160 goto failed; 1162 goto failed;
@@ -1164,6 +1166,7 @@ static int follow_dotdot_rcu(struct nameidata *nd)
1164 } 1166 }
1165 if (!follow_up_rcu(&nd->path)) 1167 if (!follow_up_rcu(&nd->path))
1166 break; 1168 break;
1169 inode = nd->path.dentry->d_inode;
1167 nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); 1170 nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
1168 } 1171 }
1169 while (d_mountpoint(nd->path.dentry)) { 1172 while (d_mountpoint(nd->path.dentry)) {
@@ -1173,11 +1176,12 @@ static int follow_dotdot_rcu(struct nameidata *nd)
1173 break; 1176 break;
1174 nd->path.mnt = &mounted->mnt; 1177 nd->path.mnt = &mounted->mnt;
1175 nd->path.dentry = mounted->mnt.mnt_root; 1178 nd->path.dentry = mounted->mnt.mnt_root;
1179 inode = nd->path.dentry->d_inode;
1176 nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); 1180 nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
1177 if (read_seqretry(&mount_lock, nd->m_seq)) 1181 if (read_seqretry(&mount_lock, nd->m_seq))
1178 goto failed; 1182 goto failed;
1179 } 1183 }
1180 nd->inode = nd->path.dentry->d_inode; 1184 nd->inode = inode;
1181 return 0; 1185 return 0;
1182 1186
1183failed: 1187failed:
@@ -1904,7 +1908,14 @@ static int path_init(int dfd, const char *name, unsigned int flags,
1904 } 1908 }
1905 1909
1906 nd->inode = nd->path.dentry->d_inode; 1910 nd->inode = nd->path.dentry->d_inode;
1907 return 0; 1911 if (!(flags & LOOKUP_RCU))
1912 return 0;
1913 if (likely(!read_seqcount_retry(&nd->path.dentry->d_seq, nd->seq)))
1914 return 0;
1915 if (!(nd->flags & LOOKUP_ROOT))
1916 nd->root.mnt = NULL;
1917 rcu_read_unlock();
1918 return -ECHILD;
1908} 1919}
1909 1920
1910static inline int lookup_last(struct nameidata *nd, struct path *path) 1921static inline int lookup_last(struct nameidata *nd, struct path *path)