aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c60
1 files changed, 27 insertions, 33 deletions
diff --git a/fs/namei.c b/fs/namei.c
index f415c6683a83..0ab9e6756f3d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2256,19 +2256,22 @@ umount_lookup_last(struct nameidata *nd, struct path *path)
2256 struct dentry *dentry; 2256 struct dentry *dentry;
2257 struct dentry *dir = nd->path.dentry; 2257 struct dentry *dir = nd->path.dentry;
2258 2258
2259 if (unlikely(nd->flags & LOOKUP_RCU)) { 2259 /* If we're in rcuwalk, drop out of it to handle last component */
2260 WARN_ON_ONCE(1); 2260 if (nd->flags & LOOKUP_RCU) {
2261 error = -ECHILD; 2261 if (unlazy_walk(nd, NULL)) {
2262 goto error_check; 2262 error = -ECHILD;
2263 goto out;
2264 }
2263 } 2265 }
2264 2266
2265 nd->flags &= ~LOOKUP_PARENT; 2267 nd->flags &= ~LOOKUP_PARENT;
2266 2268
2267 if (unlikely(nd->last_type != LAST_NORM)) { 2269 if (unlikely(nd->last_type != LAST_NORM)) {
2268 error = handle_dots(nd, nd->last_type); 2270 error = handle_dots(nd, nd->last_type);
2269 if (!error) 2271 if (error)
2270 dentry = dget(nd->path.dentry); 2272 goto out;
2271 goto error_check; 2273 dentry = dget(nd->path.dentry);
2274 goto done;
2272 } 2275 }
2273 2276
2274 mutex_lock(&dir->d_inode->i_mutex); 2277 mutex_lock(&dir->d_inode->i_mutex);
@@ -2282,28 +2285,28 @@ umount_lookup_last(struct nameidata *nd, struct path *path)
2282 dentry = d_alloc(dir, &nd->last); 2285 dentry = d_alloc(dir, &nd->last);
2283 if (!dentry) { 2286 if (!dentry) {
2284 error = -ENOMEM; 2287 error = -ENOMEM;
2285 } else { 2288 goto out;
2286 dentry = lookup_real(dir->d_inode, dentry, nd->flags);
2287 if (IS_ERR(dentry))
2288 error = PTR_ERR(dentry);
2289 } 2289 }
2290 dentry = lookup_real(dir->d_inode, dentry, nd->flags);
2291 error = PTR_ERR(dentry);
2292 if (IS_ERR(dentry))
2293 goto out;
2290 } 2294 }
2291 mutex_unlock(&dir->d_inode->i_mutex); 2295 mutex_unlock(&dir->d_inode->i_mutex);
2292 2296
2293error_check: 2297done:
2294 if (!error) { 2298 if (!dentry->d_inode) {
2295 if (!dentry->d_inode) { 2299 error = -ENOENT;
2296 error = -ENOENT; 2300 dput(dentry);
2297 dput(dentry); 2301 goto out;
2298 } else {
2299 path->dentry = dentry;
2300 path->mnt = mntget(nd->path.mnt);
2301 if (should_follow_link(dentry->d_inode,
2302 nd->flags & LOOKUP_FOLLOW))
2303 return 1;
2304 follow_mount(path);
2305 }
2306 } 2302 }
2303 path->dentry = dentry;
2304 path->mnt = mntget(nd->path.mnt);
2305 if (should_follow_link(dentry->d_inode, nd->flags & LOOKUP_FOLLOW))
2306 return 1;
2307 follow_mount(path);
2308 error = 0;
2309out:
2307 terminate_walk(nd); 2310 terminate_walk(nd);
2308 return error; 2311 return error;
2309} 2312}
@@ -2334,15 +2337,6 @@ path_umountat(int dfd, const char *name, struct path *path, unsigned int flags)
2334 if (err) 2337 if (err)
2335 goto out; 2338 goto out;
2336 2339
2337 /* If we're in rcuwalk, drop out of it to handle last component */
2338 if (nd.flags & LOOKUP_RCU) {
2339 err = unlazy_walk(&nd, NULL);
2340 if (err) {
2341 terminate_walk(&nd);
2342 goto out;
2343 }
2344 }
2345
2346 err = umount_lookup_last(&nd, path); 2340 err = umount_lookup_last(&nd, path);
2347 while (err > 0) { 2341 while (err > 0) {
2348 void *cookie; 2342 void *cookie;