From: Al Viro Date: Fri, 8 May 2015 21:37:07 +0000 (-0400) Subject: namei: lift link_path_walk() call out of trailing_symlink() X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=3bdba28b72f5d2e7f3df031b04008b9a6fbdc775;p=linux-beck.git 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: Al Viro --- diff --git a/fs/namei.c b/fs/namei.c index 06c71200be48..46f4266d1f7f 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)) {