Commit 3bdba28b authored by Al Viro's avatar Al Viro

namei: lift link_path_walk() call out of trailing_symlink()

Make trailing_symlink() return the pathname to traverse or ERR_PTR(-E...).
A subtle point is that for "magic" symlinks it returns "" now - that
leads to link_path_walk("", nd), which is immediately returning 0 and
we are back to the treatment of the last component, at whereever the
damn thing has left us.

Reduces the stack footprint - link_path_walk() called on more shallow
stack now.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 368ee9ba
...@@ -1970,24 +1970,24 @@ static void path_cleanup(struct nameidata *nd) ...@@ -1970,24 +1970,24 @@ static void path_cleanup(struct nameidata *nd)
} }
} }
static int trailing_symlink(struct nameidata *nd) static const char *trailing_symlink(struct nameidata *nd)
{ {
const char *s; const char *s;
int error = may_follow_link(nd); int error = may_follow_link(nd);
if (unlikely(error)) { if (unlikely(error)) {
terminate_walk(nd); terminate_walk(nd);
return error; return ERR_PTR(error);
} }
nd->flags |= LOOKUP_PARENT; nd->flags |= LOOKUP_PARENT;
nd->stack[0].name = NULL; nd->stack[0].name = NULL;
s = get_link(nd); s = get_link(nd);
if (unlikely(IS_ERR(s))) { if (unlikely(IS_ERR(s))) {
terminate_walk(nd); terminate_walk(nd);
return PTR_ERR(s); return s;
} }
if (unlikely(!s)) if (unlikely(!s))
return 0; s = "";
return link_path_walk(s, nd); return s;
} }
static inline int lookup_last(struct nameidata *nd) static inline int lookup_last(struct nameidata *nd)
...@@ -2017,12 +2017,12 @@ static int path_lookupat(int dfd, const struct filename *name, ...@@ -2017,12 +2017,12 @@ static int path_lookupat(int dfd, const struct filename *name,
if (IS_ERR(s)) if (IS_ERR(s))
return PTR_ERR(s); return PTR_ERR(s);
err = link_path_walk(s, nd); while (!(err = link_path_walk(s, nd))
if (!err) { && ((err = lookup_last(nd)) > 0)) {
while ((err = lookup_last(nd)) > 0) { s = trailing_symlink(nd);
err = trailing_symlink(nd); if (IS_ERR(s)) {
if (err) err = PTR_ERR(s);
break; break;
} }
} }
...@@ -2401,16 +2401,14 @@ path_mountpoint(int dfd, const struct filename *name, struct path *path, ...@@ -2401,16 +2401,14 @@ path_mountpoint(int dfd, const struct filename *name, struct path *path,
int err; int err;
if (IS_ERR(s)) if (IS_ERR(s))
return PTR_ERR(s); return PTR_ERR(s);
err = link_path_walk(s, nd); while (!(err = link_path_walk(s, nd)) &&
if (unlikely(err)) (err = mountpoint_last(nd, path)) > 0) {
goto out; s = trailing_symlink(nd);
if (IS_ERR(s)) {
while ((err = mountpoint_last(nd, path)) > 0) { err = PTR_ERR(s);
err = trailing_symlink(nd);
if (err)
break; break;
}
} }
out:
path_cleanup(nd); path_cleanup(nd);
return err; return err;
} }
...@@ -3282,17 +3280,15 @@ static struct file *path_openat(int dfd, struct filename *pathname, ...@@ -3282,17 +3280,15 @@ static struct file *path_openat(int dfd, struct filename *pathname,
put_filp(file); put_filp(file);
return ERR_CAST(s); return ERR_CAST(s);
} }
error = link_path_walk(s, nd); while (!(error = link_path_walk(s, nd)) &&
if (unlikely(error)) (error = do_last(nd, file, op, &opened, pathname)) > 0) {
goto out;
while ((error = do_last(nd, file, op, &opened, pathname)) > 0) {
nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL); nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
error = trailing_symlink(nd); s = trailing_symlink(nd);
if (unlikely(error)) if (IS_ERR(s)) {
error = PTR_ERR(s);
break; break;
}
} }
out:
path_cleanup(nd); path_cleanup(nd);
out2: out2:
if (!(opened & FILE_OPENED)) { if (!(opened & FILE_OPENED)) {
......
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