lkml.org 
[lkml]   [2015]   [May]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 70/79] namei: new calling conventions for walk_component()
    Date
    From: Al Viro <viro@zeniv.linux.org.uk>

    instead of a single flag (!= 0 => we want to follow symlinks) pass
    two bits - WALK_GET (want to follow symlinks) and WALK_PUT (put_link()
    once we are done looking at the name). The latter matters only for
    success exits - on failure the caller will discard everything anyway.

    Suggestions for better variant are welcome; what this thing aims for
    is making sure that pending put_link() is done *before* walk_component()
    decides to pick a symlink up, rather than between picking it up and
    acting upon it. See the next commit for payoff.

    Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
    ---
    fs/namei.c | 30 ++++++++++++++++++++----------
    1 file changed, 20 insertions(+), 10 deletions(-)

    diff --git a/fs/namei.c b/fs/namei.c
    index 49ed4b5..5eb8b0c 100644
    --- a/fs/namei.c
    +++ b/fs/namei.c
    @@ -1569,7 +1569,9 @@ static inline int should_follow_link(struct dentry *dentry, int follow)
    return unlikely(d_is_symlink(dentry)) ? follow : 0;
    }

    -static int walk_component(struct nameidata *nd, int follow)
    +enum {WALK_GET = 1, WALK_PUT = 2};
    +
    +static int walk_component(struct nameidata *nd, int flags)
    {
    struct path path;
    struct inode *inode;
    @@ -1579,8 +1581,12 @@ static int walk_component(struct nameidata *nd, int follow)
    * to be able to know about the current root directory and
    * parent relationships.
    */
    - if (unlikely(nd->last_type != LAST_NORM))
    - return handle_dots(nd, nd->last_type);
    + if (unlikely(nd->last_type != LAST_NORM)) {
    + err = handle_dots(nd, nd->last_type);
    + if (flags & WALK_PUT)
    + put_link(nd);
    + return err;
    + }
    err = lookup_fast(nd, &path, &inode);
    if (unlikely(err)) {
    if (err < 0)
    @@ -1596,7 +1602,9 @@ static int walk_component(struct nameidata *nd, int follow)
    if (d_is_negative(path.dentry))
    goto out_path_put;

    - if (should_follow_link(path.dentry, follow)) {
    + if (flags & WALK_PUT)
    + put_link(nd);
    + if (should_follow_link(path.dentry, flags & WALK_GET)) {
    if (nd->flags & LOOKUP_RCU) {
    if (unlikely(nd->path.mnt != path.mnt ||
    unlazy_walk(nd, path.dentry))) {
    @@ -1808,10 +1816,9 @@ OK:
    if (!name)
    return 0;
    /* last component of nested symlink */
    - err = walk_component(nd, LOOKUP_FOLLOW);
    - put_link(nd);
    + err = walk_component(nd, WALK_GET | WALK_PUT);
    } else {
    - err = walk_component(nd, LOOKUP_FOLLOW);
    + err = walk_component(nd, WALK_GET);
    }
    if (err < 0)
    break;
    @@ -2009,9 +2016,12 @@ static inline int lookup_last(struct nameidata *nd)
    nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;

    nd->flags &= ~LOOKUP_PARENT;
    - err = walk_component(nd, nd->flags & LOOKUP_FOLLOW);
    - if (nd->depth)
    - put_link(nd);
    + err = walk_component(nd,
    + nd->flags & LOOKUP_FOLLOW
    + ? nd->depth
    + ? WALK_PUT | WALK_GET
    + : WALK_GET
    + : 0);
    if (err < 0)
    terminate_walk(nd);
    return err;
    --
    2.1.4


    \
     
     \ /
      Last update: 2015-05-05 07:41    [W:4.220 / U:0.108 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site