Commit 191d7f73 authored by Al Viro's avatar Al Viro

namei: take put_link() into {lookup,mountpoint,do}_last()

rationale: we'll need to have terminate_walk() do put_link() on
everything, which will mean that in some cases ..._last() will do
put_link() anyway.  Easier to have them do it in all cases.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 1bc4b813
...@@ -2018,6 +2018,8 @@ static inline int lookup_last(struct nameidata *nd) ...@@ -2018,6 +2018,8 @@ static inline int lookup_last(struct nameidata *nd)
nd->flags &= ~LOOKUP_PARENT; nd->flags &= ~LOOKUP_PARENT;
err = walk_component(nd, nd->flags & LOOKUP_FOLLOW); err = walk_component(nd, nd->flags & LOOKUP_FOLLOW);
if (nd->depth)
put_link(nd);
if (err < 0) if (err < 0)
terminate_walk(nd); terminate_walk(nd);
return err; return err;
...@@ -2045,13 +2047,10 @@ static int path_lookupat(int dfd, const struct filename *name, ...@@ -2045,13 +2047,10 @@ static int path_lookupat(int dfd, const struct filename *name,
*/ */
err = path_init(dfd, name, flags, nd); err = path_init(dfd, name, flags, nd);
if (!err && !(flags & LOOKUP_PARENT)) { if (!err && !(flags & LOOKUP_PARENT)) {
err = lookup_last(nd); while ((err = lookup_last(nd)) > 0) {
while (err > 0) {
err = trailing_symlink(nd); err = trailing_symlink(nd);
if (err) if (err)
break; break;
err = lookup_last(nd);
put_link(nd);
} }
} }
...@@ -2362,6 +2361,8 @@ mountpoint_last(struct nameidata *nd, struct path *path) ...@@ -2362,6 +2361,8 @@ mountpoint_last(struct nameidata *nd, struct path *path)
dput(dentry); dput(dentry);
goto out; goto out;
} }
if (nd->depth)
put_link(nd);
path->dentry = dentry; path->dentry = dentry;
path->mnt = nd->path.mnt; path->mnt = nd->path.mnt;
if (should_follow_link(dentry, nd->flags & LOOKUP_FOLLOW)) { if (should_follow_link(dentry, nd->flags & LOOKUP_FOLLOW)) {
...@@ -2373,6 +2374,8 @@ mountpoint_last(struct nameidata *nd, struct path *path) ...@@ -2373,6 +2374,8 @@ mountpoint_last(struct nameidata *nd, struct path *path)
error = 0; error = 0;
out: out:
terminate_walk(nd); terminate_walk(nd);
if (nd->depth)
put_link(nd);
return error; return error;
} }
...@@ -2394,13 +2397,10 @@ path_mountpoint(int dfd, const struct filename *name, struct path *path, ...@@ -2394,13 +2397,10 @@ path_mountpoint(int dfd, const struct filename *name, struct path *path,
if (unlikely(err)) if (unlikely(err))
goto out; goto out;
err = mountpoint_last(nd, path); while ((err = mountpoint_last(nd, path)) > 0) {
while (err > 0) {
err = trailing_symlink(nd); err = trailing_symlink(nd);
if (err) if (err)
break; break;
err = mountpoint_last(nd, path);
put_link(nd);
} }
out: out:
path_cleanup(nd); path_cleanup(nd);
...@@ -2978,6 +2978,8 @@ static int do_last(struct nameidata *nd, ...@@ -2978,6 +2978,8 @@ static int do_last(struct nameidata *nd,
error = handle_dots(nd, nd->last_type); error = handle_dots(nd, nd->last_type);
if (unlikely(error)) { if (unlikely(error)) {
terminate_walk(nd); terminate_walk(nd);
if (nd->depth)
put_link(nd);
return error; return error;
} }
goto finish_open; goto finish_open;
...@@ -3003,8 +3005,11 @@ static int do_last(struct nameidata *nd, ...@@ -3003,8 +3005,11 @@ static int do_last(struct nameidata *nd,
* about to look up * about to look up
*/ */
error = complete_walk(nd); error = complete_walk(nd);
if (error) if (error) {
if (nd->depth)
put_link(nd);
return error; return error;
}
audit_inode(name, dir, LOOKUP_PARENT); audit_inode(name, dir, LOOKUP_PARENT);
error = -EISDIR; error = -EISDIR;
...@@ -3093,6 +3098,8 @@ static int do_last(struct nameidata *nd, ...@@ -3093,6 +3098,8 @@ static int do_last(struct nameidata *nd,
} }
} }
BUG_ON(inode != path.dentry->d_inode); BUG_ON(inode != path.dentry->d_inode);
if (nd->depth)
put_link(nd);
nd->link = path; nd->link = path;
return 1; return 1;
} }
...@@ -3116,6 +3123,8 @@ static int do_last(struct nameidata *nd, ...@@ -3116,6 +3123,8 @@ static int do_last(struct nameidata *nd,
finish_open: finish_open:
error = complete_walk(nd); error = complete_walk(nd);
if (error) { if (error) {
if (nd->depth)
put_link(nd);
path_put(&save_parent); path_put(&save_parent);
return error; return error;
} }
...@@ -3167,6 +3176,8 @@ static int do_last(struct nameidata *nd, ...@@ -3167,6 +3176,8 @@ static int do_last(struct nameidata *nd,
mnt_drop_write(nd->path.mnt); mnt_drop_write(nd->path.mnt);
path_put(&save_parent); path_put(&save_parent);
terminate_walk(nd); terminate_walk(nd);
if (nd->depth)
put_link(nd);
return error; return error;
exit_dput: exit_dput:
...@@ -3279,14 +3290,11 @@ static struct file *path_openat(int dfd, struct filename *pathname, ...@@ -3279,14 +3290,11 @@ static struct file *path_openat(int dfd, struct filename *pathname,
if (unlikely(error)) if (unlikely(error))
goto out; goto out;
error = do_last(nd, file, op, &opened, pathname); while ((error = do_last(nd, file, op, &opened, pathname)) > 0) {
while (unlikely(error > 0)) { /* trailing symlink */
nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL); nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
error = trailing_symlink(nd); error = trailing_symlink(nd);
if (unlikely(error)) if (unlikely(error))
break; break;
error = do_last(nd, file, op, &opened, pathname);
put_link(nd);
} }
out: out:
path_cleanup(nd); path_cleanup(nd);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment