diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2021-05-17 22:29:03 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2021-05-18 20:08:12 -0400 |
commit | 01a4428ee7068875995ee27e9ba5503874f23e3b (patch) | |
tree | 9838c58bfc7a38657b1965bf4f19956590ad59e4 /fs/d_path.c | |
parent | d8548232ea2858d1d130f3ac835185159d367caa (diff) | |
download | lwn-01a4428ee7068875995ee27e9ba5503874f23e3b.tar.gz lwn-01a4428ee7068875995ee27e9ba5503874f23e3b.zip |
d_path: lift -ENAMETOOLONG handling into callers of prepend_path()
The only negative value ever returned by prepend_path() is -ENAMETOOLONG
and callers can recognize that situation (overflow) by looking at the
sign of buflen. Lift that into the callers; we already have the
same logics (buf if buflen is non-negative, ERR_PTR(-ENAMETOOLONG) otherwise)
in several places and that'll become a new primitive several commits down
the road.
Make prepend_path() return 0 instead of -ENAMETOOLONG. That makes for
saner calling conventions (0/1/2/3/-ENAMETOOLONG is obnoxious) and
callers actually get simpler, especially once the aforementioned
primitive gets added.
In prepend_path() itself we switch prepending the / (in case of
empty path) to use of prepend() - no need to open-code that, compiler
will do the right thing. It's exactly the same logics as in
__dentry_path().
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/d_path.c')
-rw-r--r-- | fs/d_path.c | 39 |
1 files changed, 11 insertions, 28 deletions
diff --git a/fs/d_path.c b/fs/d_path.c index 72b8087aaf9c..327cc3744554 100644 --- a/fs/d_path.c +++ b/fs/d_path.c @@ -127,8 +127,7 @@ restart: } parent = dentry->d_parent; prefetch(parent); - error = prepend_name(&bptr, &blen, &dentry->d_name); - if (error) + if (unlikely(prepend_name(&bptr, &blen, &dentry->d_name) < 0)) break; dentry = parent; @@ -149,12 +148,9 @@ restart: } done_seqretry(&mount_lock, m_seq); - if (error >= 0 && bptr == *buffer) { - if (--blen < 0) - error = -ENAMETOOLONG; - else - *--bptr = '/'; - } + if (blen == *buflen) + prepend(&bptr, &blen, "/", 1); + *buffer = bptr; *buflen = blen; return error; @@ -181,16 +177,11 @@ char *__d_path(const struct path *path, char *buf, int buflen) { char *res = buf + buflen; - int error; prepend(&res, &buflen, "", 1); - error = prepend_path(path, root, &res, &buflen); - - if (error < 0) - return ERR_PTR(error); - if (error > 0) + if (prepend_path(path, root, &res, &buflen) > 0) return NULL; - return res; + return buflen >= 0 ? res : ERR_PTR(-ENAMETOOLONG); } char *d_absolute_path(const struct path *path, @@ -198,16 +189,11 @@ char *d_absolute_path(const struct path *path, { struct path root = {}; char *res = buf + buflen; - int error; prepend(&res, &buflen, "", 1); - error = prepend_path(path, &root, &res, &buflen); - - if (error > 1) - error = -EINVAL; - if (error < 0) - return ERR_PTR(error); - return res; + if (prepend_path(path, &root, &res, &buflen) > 1) + return ERR_PTR(-EINVAL); + return buflen >= 0 ? res : ERR_PTR(-ENAMETOOLONG); } static void get_fs_root_rcu(struct fs_struct *fs, struct path *root) @@ -240,7 +226,6 @@ char *d_path(const struct path *path, char *buf, int buflen) { char *res = buf + buflen; struct path root; - int error; /* * We have various synthetic filesystems that never get mounted. On @@ -263,12 +248,10 @@ char *d_path(const struct path *path, char *buf, int buflen) prepend(&res, &buflen, " (deleted)", 11); else prepend(&res, &buflen, "", 1); - error = prepend_path(path, &root, &res, &buflen); + prepend_path(path, &root, &res, &buflen); rcu_read_unlock(); - if (error < 0) - res = ERR_PTR(error); - return res; + return buflen >= 0 ? res : ERR_PTR(-ENAMETOOLONG); } EXPORT_SYMBOL(d_path); |