namei: lift terminate_walk() all the way up
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 8 May 2015 22:05:21 +0000 (18:05 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 11 May 2015 12:13:08 +0000 (08:13 -0400)
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>
fs/namei.c

index 46f4266d1f7febc90a6467a0f0475edb85148fc6..27c38591b4ecafc7089629652050492eebcb79b3 100644 (file)
@@ -563,8 +563,6 @@ static inline int nd_alloc_stack(struct nameidata *nd)
  * to restart the path walk from the beginning in ref-walk mode.
  */
 
-static void terminate_walk(struct nameidata *nd);
-
 /**
  * unlazy_walk - try to switch to ref-walk mode.
  * @nd: nameidata pathwalk data
@@ -673,10 +671,8 @@ static int complete_walk(struct nameidata *nd)
        if (nd->flags & LOOKUP_RCU) {
                if (!(nd->flags & LOOKUP_ROOT))
                        nd->root.mnt = NULL;
-               if (unlikely(unlazy_walk(nd, NULL))) {
-                       terminate_walk(nd);
+               if (unlikely(unlazy_walk(nd, NULL)))
                        return -ECHILD;
-               }
        }
 
        if (likely(!(nd->flags & LOOKUP_JUMPED)))
@@ -692,7 +688,6 @@ static int complete_walk(struct nameidata *nd)
        if (!status)
                status = -ESTALE;
 
-       terminate_walk(nd);
        return status;
 }
 
@@ -1858,7 +1853,6 @@ OK:
                        break;
                }
        }
-       terminate_walk(nd);
        return err;
 }
 
@@ -1974,38 +1968,26 @@ static const char *trailing_symlink(struct nameidata *nd)
 {
        const char *s;
        int error = may_follow_link(nd);
-       if (unlikely(error)) {
-               terminate_walk(nd);
+       if (unlikely(error))
                return ERR_PTR(error);
-       }
        nd->flags |= LOOKUP_PARENT;
        nd->stack[0].name = NULL;
        s = get_link(nd);
-       if (unlikely(IS_ERR(s))) {
-               terminate_walk(nd);
-               return s;
-       }
-       if (unlikely(!s))
-               s = "";
-       return s;
+       return s ? s : "";
 }
 
 static inline int lookup_last(struct nameidata *nd)
 {
-       int err;
        if (nd->last_type == LAST_NORM && nd->last.name[nd->last.len])
                nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
 
        nd->flags &= ~LOOKUP_PARENT;
-       err = walk_component(nd,
+       return walk_component(nd,
                        nd->flags & LOOKUP_FOLLOW
                                ? nd->depth
                                        ? WALK_PUT | WALK_GET
                                        : WALK_GET
                                : 0);
-       if (err < 0)
-               terminate_walk(nd);
-       return err;
 }
 
 /* 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,
                        break;
                }
        }
-
        if (!err)
                err = complete_walk(nd);
 
-       if (!err && nd->flags & LOOKUP_DIRECTORY) {
-               if (!d_can_lookup(nd->path.dentry)) {
-                       path_put(&nd->path);
+       if (!err && nd->flags & LOOKUP_DIRECTORY)
+               if (!d_can_lookup(nd->path.dentry))
                        err = -ENOTDIR;
-               }
-       }
+       if (err)
+               terminate_walk(nd);
 
        path_cleanup(nd);
        return err;
@@ -2069,6 +2049,8 @@ static int path_parentat(int dfd, const struct filename *name,
        err = link_path_walk(s, nd);
        if (!err)
                err = complete_walk(nd);
+       if (err)
+               terminate_walk(nd);
        path_cleanup(nd);
        return err;
 }
@@ -2320,10 +2302,8 @@ mountpoint_last(struct nameidata *nd, struct path *path)
 
        /* If we're in rcuwalk, drop out of it to handle last component */
        if (nd->flags & LOOKUP_RCU) {
-               if (unlazy_walk(nd, NULL)) {
-                       error = -ECHILD;
-                       goto out;
-               }
+               if (unlazy_walk(nd, NULL))
+                       return -ECHILD;
        }
 
        nd->flags &= ~LOOKUP_PARENT;
@@ -2331,7 +2311,7 @@ mountpoint_last(struct nameidata *nd, struct path *path)
        if (unlikely(nd->last_type != LAST_NORM)) {
                error = handle_dots(nd, nd->last_type);
                if (error)
-                       goto out;
+                       return error;
                dentry = dget(nd->path.dentry);
                goto done;
        }
@@ -2346,41 +2326,32 @@ mountpoint_last(struct nameidata *nd, struct path *path)
                 */
                dentry = d_alloc(dir, &nd->last);
                if (!dentry) {
-                       error = -ENOMEM;
                        mutex_unlock(&dir->d_inode->i_mutex);
-                       goto out;
+                       return -ENOMEM;
                }
                dentry = lookup_real(dir->d_inode, dentry, nd->flags);
-               error = PTR_ERR(dentry);
                if (IS_ERR(dentry)) {
                        mutex_unlock(&dir->d_inode->i_mutex);
-                       goto out;
+                       return PTR_ERR(dentry);
                }
        }
        mutex_unlock(&dir->d_inode->i_mutex);
 
 done:
        if (d_is_negative(dentry)) {
-               error = -ENOENT;
                dput(dentry);
-               goto out;
+               return -ENOENT;
        }
        if (nd->depth)
                put_link(nd);
        path->dentry = dentry;
        path->mnt = nd->path.mnt;
        error = should_follow_link(nd, path, nd->flags & LOOKUP_FOLLOW);
-       if (unlikely(error)) {
-               if (error < 0)
-                       goto out;
+       if (unlikely(error))
                return error;
-       }
        mntget(path->mnt);
        follow_mount(path);
-       error = 0;
-out:
-       terminate_walk(nd);
-       return error;
+       return 0;
 }
 
 /**
@@ -2409,6 +2380,7 @@ path_mountpoint(int dfd, const struct filename *name, struct path *path,
                        break;
                }
        }
+       terminate_walk(nd);
        path_cleanup(nd);
        return err;
 }
@@ -2982,10 +2954,8 @@ static int do_last(struct nameidata *nd,
 
        if (nd->last_type != LAST_NORM) {
                error = handle_dots(nd, nd->last_type);
-               if (unlikely(error)) {
-                       terminate_walk(nd);
+               if (unlikely(error))
                        return error;
-               }
                goto finish_open;
        }
 
@@ -2998,7 +2968,7 @@ static int do_last(struct nameidata *nd,
                        goto finish_lookup;
 
                if (error < 0)
-                       goto out;
+                       return error;
 
                BUG_ON(nd->inode != dir->d_inode);
        } else {
@@ -3013,10 +2983,9 @@ static int do_last(struct nameidata *nd,
                        return error;
 
                audit_inode(name, dir, LOOKUP_PARENT);
-               error = -EISDIR;
                /* trailing slashes? */
-               if (nd->last.name[nd->last.len])
-                       goto out;
+               if (unlikely(nd->last.name[nd->last.len]))
+                       return -EISDIR;
        }
 
 retry_lookup:
@@ -3071,35 +3040,31 @@ retry_lookup:
                got_write = false;
        }
 
-       error = -EEXIST;
-       if ((open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT))
-               goto exit_dput;
+       if (unlikely((open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT))) {
+               path_to_nameidata(&path, nd);
+               return -EEXIST;
+       }
 
        error = follow_managed(&path, nd);
-       if (error < 0)
-               goto out;
+       if (unlikely(error < 0))
+               return error;
 
        BUG_ON(nd->flags & LOOKUP_RCU);
        inode = path.dentry->d_inode;
-       error = -ENOENT;
-       if (d_is_negative(path.dentry)) {
+       if (unlikely(d_is_negative(path.dentry))) {
                path_to_nameidata(&path, nd);
-               goto out;
+               return -ENOENT;
        }
 finish_lookup:
        if (nd->depth)
                put_link(nd);
        error = should_follow_link(nd, &path, nd->flags & LOOKUP_FOLLOW);
-       if (unlikely(error)) {
-               if (error < 0)
-                       goto out;
+       if (unlikely(error))
                return error;
-       }
 
        if (unlikely(d_is_symlink(path.dentry)) && !(open_flag & O_PATH)) {
                path_to_nameidata(&path, nd);
-               error = -ELOOP;
-               goto out;
+               return -ELOOP;
        }
 
        if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path.mnt) {
@@ -3165,12 +3130,8 @@ out:
        if (got_write)
                mnt_drop_write(nd->path.mnt);
        path_put(&save_parent);
-       terminate_walk(nd);
        return error;
 
-exit_dput:
-       path_put_conditional(&path, nd);
-       goto out;
 exit_fput:
        fput(file);
        goto out;
@@ -3289,6 +3250,7 @@ static struct file *path_openat(int dfd, struct filename *pathname,
                        break;
                }
        }
+       terminate_walk(nd);
        path_cleanup(nd);
 out2:
        if (!(opened & FILE_OPENED)) {