[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1431367690-5223-90-git-send-email-viro@ZenIV.linux.org.uk>
Date: Mon, 11 May 2015 19:07:50 +0100
From: Al Viro <viro@...IV.linux.org.uk>
To: Linus Torvalds <torvalds@...ux-foundation.org>
Cc: Neil Brown <neilb@...e.de>, Christoph Hellwig <hch@...radead.org>,
linux-kernel@...r.kernel.org, linux-fsdevel@...r.kernel.org
Subject: [PATCH v3 090/110] namei: lift terminate_walk() all the way up
From: Al Viro <viro@...iv.linux.org.uk>
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@...iv.linux.org.uk>
---
fs/namei.c | 106 ++++++++++++++++++++-----------------------------------------
1 file changed, 34 insertions(+), 72 deletions(-)
diff --git a/fs/namei.c b/fs/namei.c
index 46f4266..27c3859 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 @@ 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)) {
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists