forked from luck/tmp_suning_uos_patched
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>
This commit is contained in:
parent
3bdba28b72
commit
deb106c632
106
fs/namei.c
106
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)) {
|
||||
|
Loading…
Reference in New Issue
Block a user