summaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-05-08 18:05:21 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-05-11 08:13:08 -0400
commitdeb106c632d73c96b6b2b5ca71bacb8aef38fc7b (patch)
tree87ffe76ba593ac0a061f2058fcb418eb6183d1a4 /fs/namei.c
parent3bdba28b72f5d2e7f3df031b04008b9a6fbdc775 (diff)
namei: lift terminate_walk() all the way up
Lift it from link_path_walk(), trailing_symlink(), lookup_last(), mountpoint_last(), complete_walk() and do_last(). A _lot_ of those suckers merge. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c106
1 files changed, 34 insertions, 72 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 46f4266d1f7f..27c38591b4ec 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -563,8 +563,6 @@ static inline int nd_alloc_stack(struct nameidata *nd)
563 * to restart the path walk from the beginning in ref-walk mode. 563 * to restart the path walk from the beginning in ref-walk mode.
564 */ 564 */
565 565
566static void terminate_walk(struct nameidata *nd);
567
568/** 566/**
569 * unlazy_walk - try to switch to ref-walk mode. 567 * unlazy_walk - try to switch to ref-walk mode.
570 * @nd: nameidata pathwalk data 568 * @nd: nameidata pathwalk data
@@ -673,10 +671,8 @@ static int complete_walk(struct nameidata *nd)
673 if (nd->flags & LOOKUP_RCU) { 671 if (nd->flags & LOOKUP_RCU) {
674 if (!(nd->flags & LOOKUP_ROOT)) 672 if (!(nd->flags & LOOKUP_ROOT))
675 nd->root.mnt = NULL; 673 nd->root.mnt = NULL;
676 if (unlikely(unlazy_walk(nd, NULL))) { 674 if (unlikely(unlazy_walk(nd, NULL)))
677 terminate_walk(nd);
678 return -ECHILD; 675 return -ECHILD;
679 }
680 } 676 }
681 677
682 if (likely(!(nd->flags & LOOKUP_JUMPED))) 678 if (likely(!(nd->flags & LOOKUP_JUMPED)))
@@ -692,7 +688,6 @@ static int complete_walk(struct nameidata *nd)
692 if (!status) 688 if (!status)
693 status = -ESTALE; 689 status = -ESTALE;
694 690
695 terminate_walk(nd);
696 return status; 691 return status;
697} 692}
698 693
@@ -1858,7 +1853,6 @@ OK:
1858 break; 1853 break;
1859 } 1854 }
1860 } 1855 }
1861 terminate_walk(nd);
1862 return err; 1856 return err;
1863} 1857}
1864 1858
@@ -1974,38 +1968,26 @@ static const char *trailing_symlink(struct nameidata *nd)
1974{ 1968{
1975 const char *s; 1969 const char *s;
1976 int error = may_follow_link(nd); 1970 int error = may_follow_link(nd);
1977 if (unlikely(error)) { 1971 if (unlikely(error))
1978 terminate_walk(nd);
1979 return ERR_PTR(error); 1972 return ERR_PTR(error);
1980 }
1981 nd->flags |= LOOKUP_PARENT; 1973 nd->flags |= LOOKUP_PARENT;
1982 nd->stack[0].name = NULL; 1974 nd->stack[0].name = NULL;
1983 s = get_link(nd); 1975 s = get_link(nd);
1984 if (unlikely(IS_ERR(s))) { 1976 return s ? s : "";
1985 terminate_walk(nd);
1986 return s;
1987 }
1988 if (unlikely(!s))
1989 s = "";
1990 return s;
1991} 1977}
1992 1978
1993static inline int lookup_last(struct nameidata *nd) 1979static inline int lookup_last(struct nameidata *nd)
1994{ 1980{
1995 int err;
1996 if (nd->last_type == LAST_NORM && nd->last.name[nd->last.len]) 1981 if (nd->last_type == LAST_NORM && nd->last.name[nd->last.len])
1997 nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; 1982 nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
1998 1983
1999 nd->flags &= ~LOOKUP_PARENT; 1984 nd->flags &= ~LOOKUP_PARENT;
2000 err = walk_component(nd, 1985 return walk_component(nd,
2001 nd->flags & LOOKUP_FOLLOW 1986 nd->flags & LOOKUP_FOLLOW
2002 ? nd->depth 1987 ? nd->depth
2003 ? WALK_PUT | WALK_GET 1988 ? WALK_PUT | WALK_GET
2004 : WALK_GET 1989 : WALK_GET
2005 : 0); 1990 : 0);
2006 if (err < 0)
2007 terminate_walk(nd);
2008 return err;
2009} 1991}
2010 1992
2011/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ 1993/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
@@ -2025,16 +2007,14 @@ static int path_lookupat(int dfd, const struct filename *name,
2025 break; 2007 break;
2026 } 2008 }
2027 } 2009 }
2028
2029 if (!err) 2010 if (!err)
2030 err = complete_walk(nd); 2011 err = complete_walk(nd);
2031 2012
2032 if (!err && nd->flags & LOOKUP_DIRECTORY) { 2013 if (!err && nd->flags & LOOKUP_DIRECTORY)
2033 if (!d_can_lookup(nd->path.dentry)) { 2014 if (!d_can_lookup(nd->path.dentry))
2034 path_put(&nd->path);
2035 err = -ENOTDIR; 2015 err = -ENOTDIR;
2036 } 2016 if (err)
2037 } 2017 terminate_walk(nd);
2038 2018
2039 path_cleanup(nd); 2019 path_cleanup(nd);
2040 return err; 2020 return err;
@@ -2069,6 +2049,8 @@ static int path_parentat(int dfd, const struct filename *name,
2069 err = link_path_walk(s, nd); 2049 err = link_path_walk(s, nd);
2070 if (!err) 2050 if (!err)
2071 err = complete_walk(nd); 2051 err = complete_walk(nd);
2052 if (err)
2053 terminate_walk(nd);
2072 path_cleanup(nd); 2054 path_cleanup(nd);
2073 return err; 2055 return err;
2074} 2056}
@@ -2320,10 +2302,8 @@ mountpoint_last(struct nameidata *nd, struct path *path)
2320 2302
2321 /* If we're in rcuwalk, drop out of it to handle last component */ 2303 /* If we're in rcuwalk, drop out of it to handle last component */
2322 if (nd->flags & LOOKUP_RCU) { 2304 if (nd->flags & LOOKUP_RCU) {
2323 if (unlazy_walk(nd, NULL)) { 2305 if (unlazy_walk(nd, NULL))
2324 error = -ECHILD; 2306 return -ECHILD;
2325 goto out;
2326 }
2327 } 2307 }
2328 2308
2329 nd->flags &= ~LOOKUP_PARENT; 2309 nd->flags &= ~LOOKUP_PARENT;
@@ -2331,7 +2311,7 @@ mountpoint_last(struct nameidata *nd, struct path *path)
2331 if (unlikely(nd->last_type != LAST_NORM)) { 2311 if (unlikely(nd->last_type != LAST_NORM)) {
2332 error = handle_dots(nd, nd->last_type); 2312 error = handle_dots(nd, nd->last_type);
2333 if (error) 2313 if (error)
2334 goto out; 2314 return error;
2335 dentry = dget(nd->path.dentry); 2315 dentry = dget(nd->path.dentry);
2336 goto done; 2316 goto done;
2337 } 2317 }
@@ -2346,41 +2326,32 @@ mountpoint_last(struct nameidata *nd, struct path *path)
2346 */ 2326 */
2347 dentry = d_alloc(dir, &nd->last); 2327 dentry = d_alloc(dir, &nd->last);
2348 if (!dentry) { 2328 if (!dentry) {
2349 error = -ENOMEM;
2350 mutex_unlock(&dir->d_inode->i_mutex); 2329 mutex_unlock(&dir->d_inode->i_mutex);
2351 goto out; 2330 return -ENOMEM;
2352 } 2331 }
2353 dentry = lookup_real(dir->d_inode, dentry, nd->flags); 2332 dentry = lookup_real(dir->d_inode, dentry, nd->flags);
2354 error = PTR_ERR(dentry);
2355 if (IS_ERR(dentry)) { 2333 if (IS_ERR(dentry)) {
2356 mutex_unlock(&dir->d_inode->i_mutex); 2334 mutex_unlock(&dir->d_inode->i_mutex);
2357 goto out; 2335 return PTR_ERR(dentry);
2358 } 2336 }
2359 } 2337 }
2360 mutex_unlock(&dir->d_inode->i_mutex); 2338 mutex_unlock(&dir->d_inode->i_mutex);
2361 2339
2362done: 2340done:
2363 if (d_is_negative(dentry)) { 2341 if (d_is_negative(dentry)) {
2364 error = -ENOENT;
2365 dput(dentry); 2342 dput(dentry);
2366 goto out; 2343 return -ENOENT;
2367 } 2344 }
2368 if (nd->depth) 2345 if (nd->depth)
2369 put_link(nd); 2346 put_link(nd);
2370 path->dentry = dentry; 2347 path->dentry = dentry;
2371 path->mnt = nd->path.mnt; 2348 path->mnt = nd->path.mnt;
2372 error = should_follow_link(nd, path, nd->flags & LOOKUP_FOLLOW); 2349 error = should_follow_link(nd, path, nd->flags & LOOKUP_FOLLOW);
2373 if (unlikely(error)) { 2350 if (unlikely(error))
2374 if (error < 0)
2375 goto out;
2376 return error; 2351 return error;
2377 }
2378 mntget(path->mnt); 2352 mntget(path->mnt);
2379 follow_mount(path); 2353 follow_mount(path);
2380 error = 0; 2354 return 0;
2381out:
2382 terminate_walk(nd);
2383 return error;
2384} 2355}
2385 2356
2386/** 2357/**
@@ -2409,6 +2380,7 @@ path_mountpoint(int dfd, const struct filename *name, struct path *path,
2409 break; 2380 break;
2410 } 2381 }
2411 } 2382 }
2383 terminate_walk(nd);
2412 path_cleanup(nd); 2384 path_cleanup(nd);
2413 return err; 2385 return err;
2414} 2386}
@@ -2982,10 +2954,8 @@ static int do_last(struct nameidata *nd,
2982 2954
2983 if (nd->last_type != LAST_NORM) { 2955 if (nd->last_type != LAST_NORM) {
2984 error = handle_dots(nd, nd->last_type); 2956 error = handle_dots(nd, nd->last_type);
2985 if (unlikely(error)) { 2957 if (unlikely(error))
2986 terminate_walk(nd);
2987 return error; 2958 return error;
2988 }
2989 goto finish_open; 2959 goto finish_open;
2990 } 2960 }
2991 2961
@@ -2998,7 +2968,7 @@ static int do_last(struct nameidata *nd,
2998 goto finish_lookup; 2968 goto finish_lookup;
2999 2969
3000 if (error < 0) 2970 if (error < 0)
3001 goto out; 2971 return error;
3002 2972
3003 BUG_ON(nd->inode != dir->d_inode); 2973 BUG_ON(nd->inode != dir->d_inode);
3004 } else { 2974 } else {
@@ -3013,10 +2983,9 @@ static int do_last(struct nameidata *nd,
3013 return error; 2983 return error;
3014 2984
3015 audit_inode(name, dir, LOOKUP_PARENT); 2985 audit_inode(name, dir, LOOKUP_PARENT);
3016 error = -EISDIR;
3017 /* trailing slashes? */ 2986 /* trailing slashes? */
3018 if (nd->last.name[nd->last.len]) 2987 if (unlikely(nd->last.name[nd->last.len]))
3019 goto out; 2988 return -EISDIR;
3020 } 2989 }
3021 2990
3022retry_lookup: 2991retry_lookup:
@@ -3071,35 +3040,31 @@ retry_lookup:
3071 got_write = false; 3040 got_write = false;
3072 } 3041 }
3073 3042
3074 error = -EEXIST; 3043 if (unlikely((open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT))) {
3075 if ((open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT)) 3044 path_to_nameidata(&path, nd);
3076 goto exit_dput; 3045 return -EEXIST;
3046 }
3077 3047
3078 error = follow_managed(&path, nd); 3048 error = follow_managed(&path, nd);
3079 if (error < 0) 3049 if (unlikely(error < 0))
3080 goto out; 3050 return error;
3081 3051
3082 BUG_ON(nd->flags & LOOKUP_RCU); 3052 BUG_ON(nd->flags & LOOKUP_RCU);
3083 inode = path.dentry->d_inode; 3053 inode = path.dentry->d_inode;
3084 error = -ENOENT; 3054 if (unlikely(d_is_negative(path.dentry))) {
3085 if (d_is_negative(path.dentry)) {
3086 path_to_nameidata(&path, nd); 3055 path_to_nameidata(&path, nd);
3087 goto out; 3056 return -ENOENT;
3088 } 3057 }
3089finish_lookup: 3058finish_lookup:
3090 if (nd->depth) 3059 if (nd->depth)
3091 put_link(nd); 3060 put_link(nd);
3092 error = should_follow_link(nd, &path, nd->flags & LOOKUP_FOLLOW); 3061 error = should_follow_link(nd, &path, nd->flags & LOOKUP_FOLLOW);
3093 if (unlikely(error)) { 3062 if (unlikely(error))
3094 if (error < 0)
3095 goto out;
3096 return error; 3063 return error;
3097 }
3098 3064
3099 if (unlikely(d_is_symlink(path.dentry)) && !(open_flag & O_PATH)) { 3065 if (unlikely(d_is_symlink(path.dentry)) && !(open_flag & O_PATH)) {
3100 path_to_nameidata(&path, nd); 3066 path_to_nameidata(&path, nd);
3101 error = -ELOOP; 3067 return -ELOOP;
3102 goto out;
3103 } 3068 }
3104 3069
3105 if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path.mnt) { 3070 if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path.mnt) {
@@ -3165,12 +3130,8 @@ out:
3165 if (got_write) 3130 if (got_write)
3166 mnt_drop_write(nd->path.mnt); 3131 mnt_drop_write(nd->path.mnt);
3167 path_put(&save_parent); 3132 path_put(&save_parent);
3168 terminate_walk(nd);
3169 return error; 3133 return error;
3170 3134
3171exit_dput:
3172 path_put_conditional(&path, nd);
3173 goto out;
3174exit_fput: 3135exit_fput:
3175 fput(file); 3136 fput(file);
3176 goto out; 3137 goto out;
@@ -3289,6 +3250,7 @@ static struct file *path_openat(int dfd, struct filename *pathname,
3289 break; 3250 break;
3290 } 3251 }
3291 } 3252 }
3253 terminate_walk(nd);
3292 path_cleanup(nd); 3254 path_cleanup(nd);
3293out2: 3255out2:
3294 if (!(opened & FILE_OPENED)) { 3256 if (!(opened & FILE_OPENED)) {