diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 31 |
1 files changed, 14 insertions, 17 deletions
diff --git a/fs/namei.c b/fs/namei.c index 385f7817bfcc..4b491b431990 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1109,7 +1109,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, | |||
1109 | return false; | 1109 | return false; |
1110 | 1110 | ||
1111 | if (!d_mountpoint(path->dentry)) | 1111 | if (!d_mountpoint(path->dentry)) |
1112 | break; | 1112 | return true; |
1113 | 1113 | ||
1114 | mounted = __lookup_mnt(path->mnt, path->dentry); | 1114 | mounted = __lookup_mnt(path->mnt, path->dentry); |
1115 | if (!mounted) | 1115 | if (!mounted) |
@@ -1125,20 +1125,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, | |||
1125 | */ | 1125 | */ |
1126 | *inode = path->dentry->d_inode; | 1126 | *inode = path->dentry->d_inode; |
1127 | } | 1127 | } |
1128 | return true; | 1128 | return read_seqretry(&mount_lock, nd->m_seq); |
1129 | } | ||
1130 | |||
1131 | static void follow_mount_rcu(struct nameidata *nd) | ||
1132 | { | ||
1133 | while (d_mountpoint(nd->path.dentry)) { | ||
1134 | struct mount *mounted; | ||
1135 | mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry); | ||
1136 | if (!mounted) | ||
1137 | break; | ||
1138 | nd->path.mnt = &mounted->mnt; | ||
1139 | nd->path.dentry = mounted->mnt.mnt_root; | ||
1140 | nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); | ||
1141 | } | ||
1142 | } | 1129 | } |
1143 | 1130 | ||
1144 | static int follow_dotdot_rcu(struct nameidata *nd) | 1131 | static int follow_dotdot_rcu(struct nameidata *nd) |
@@ -1166,7 +1153,17 @@ static int follow_dotdot_rcu(struct nameidata *nd) | |||
1166 | break; | 1153 | break; |
1167 | nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); | 1154 | nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); |
1168 | } | 1155 | } |
1169 | follow_mount_rcu(nd); | 1156 | while (d_mountpoint(nd->path.dentry)) { |
1157 | struct mount *mounted; | ||
1158 | mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry); | ||
1159 | if (!mounted) | ||
1160 | break; | ||
1161 | nd->path.mnt = &mounted->mnt; | ||
1162 | nd->path.dentry = mounted->mnt.mnt_root; | ||
1163 | nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); | ||
1164 | if (!read_seqretry(&mount_lock, nd->m_seq)) | ||
1165 | goto failed; | ||
1166 | } | ||
1170 | nd->inode = nd->path.dentry->d_inode; | 1167 | nd->inode = nd->path.dentry->d_inode; |
1171 | return 0; | 1168 | return 0; |
1172 | 1169 | ||
@@ -1884,7 +1881,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
1884 | 1881 | ||
1885 | nd->path = f.file->f_path; | 1882 | nd->path = f.file->f_path; |
1886 | if (flags & LOOKUP_RCU) { | 1883 | if (flags & LOOKUP_RCU) { |
1887 | if (f.need_put) | 1884 | if (f.flags & FDPUT_FPUT) |
1888 | *fp = f.file; | 1885 | *fp = f.file; |
1889 | nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); | 1886 | nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); |
1890 | rcu_read_lock(); | 1887 | rcu_read_lock(); |