From deb106c632d73c96b6b2b5ca71bacb8aef38fc7b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 8 May 2015 18:05:21 -0400 Subject: [PATCH] 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 --- fs/namei.c | 106 +++++++++++++++++------------------------------------ 1 file 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) * 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 @@ static int link_path_walk(const char *name, struct nameidata *nd) 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 @@ static int do_last(struct nameidata *nd, 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 @@ static int do_last(struct nameidata *nd, 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)) { -- GitLab