[PATCH v3 089/110] namei: lift link_path_walk() call out of trailing_symlink()

From: Al Viro
Date: Mon May 11 2015 - 14:19:21 EST


From: Al Viro <viro@xxxxxxxxxxxxxxxxxx>

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: Al Viro <viro@xxxxxxxxxxxxxxxxxx>
---
fs/namei.c | 50 +++++++++++++++++++++++---------------------------
1 file changed, 23 insertions(+), 27 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 06c7120..46f4266 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -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;
int error = may_follow_link(nd);
if (unlikely(error)) {
terminate_walk(nd);
- return 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 PTR_ERR(s);
+ return s;
}
if (unlikely(!s))
- return 0;
- return link_path_walk(s, nd);
+ s = "";
+ return s;
}

static inline int lookup_last(struct nameidata *nd)
@@ -2017,12 +2017,12 @@ static int path_lookupat(int dfd, const struct filename *name,

if (IS_ERR(s))
return PTR_ERR(s);
- err = link_path_walk(s, nd);
- if (!err) {
- while ((err = lookup_last(nd)) > 0) {
- err = trailing_symlink(nd);
- if (err)
- break;
+ while (!(err = link_path_walk(s, nd))
+ && ((err = lookup_last(nd)) > 0)) {
+ s = trailing_symlink(nd);
+ if (IS_ERR(s)) {
+ err = PTR_ERR(s);
+ break;
}
}

@@ -2401,16 +2401,14 @@ path_mountpoint(int dfd, const struct filename *name, struct path *path,
int err;
if (IS_ERR(s))
return PTR_ERR(s);
- err = link_path_walk(s, nd);
- if (unlikely(err))
- goto out;
-
- while ((err = mountpoint_last(nd, path)) > 0) {
- err = trailing_symlink(nd);
- if (err)
+ while (!(err = link_path_walk(s, nd)) &&
+ (err = mountpoint_last(nd, path)) > 0) {
+ s = trailing_symlink(nd);
+ if (IS_ERR(s)) {
+ err = PTR_ERR(s);
break;
+ }
}
-out:
path_cleanup(nd);
return err;
}
@@ -3282,17 +3280,15 @@ static struct file *path_openat(int dfd, struct filename *pathname,
put_filp(file);
return ERR_CAST(s);
}
- error = link_path_walk(s, nd);
- if (unlikely(error))
- goto out;
-
- while ((error = do_last(nd, file, op, &opened, pathname)) > 0) {
+ while (!(error = link_path_walk(s, nd)) &&
+ (error = do_last(nd, file, op, &opened, pathname)) > 0) {
nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
- error = trailing_symlink(nd);
- if (unlikely(error))
+ s = trailing_symlink(nd);
+ if (IS_ERR(s)) {
+ error = PTR_ERR(s);
break;
+ }
}
-out:
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@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/