]> git.ipfire.org Git - people/ms/linux.git/commitdiff
step_into(): lose inode argument
authorAl Viro <viro@zeniv.linux.org.uk>
Mon, 4 Jul 2022 02:07:32 +0000 (22:07 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Wed, 6 Jul 2022 17:15:52 +0000 (13:15 -0400)
make handle_mounts() always fetch it.  This is just the first step -
the callers of step_into() will stop trying to calculate the sucker,
etc.

The passed value should be equal to dentry->d_inode in all cases;
in RCU mode - fetched after we'd sampled ->d_seq.  Might as well
fetch it here.  We do need to validate ->d_seq, which duplicates
the check currently done in lookup_fast(); that duplication will
go away shortly.

After that change handle_mounts() always ignores the initial value of
*inode and always sets it on success.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/namei.c

index 8dd7874816cc05dfd25d265fd54feb38d16d0082..60e17152374a5248c46ce17b0c1c857f529bd488 100644 (file)
@@ -1536,6 +1536,9 @@ static inline int handle_mounts(struct nameidata *nd, struct dentry *dentry,
        path->dentry = dentry;
        if (nd->flags & LOOKUP_RCU) {
                unsigned int seq = nd->next_seq;
+               *inode = dentry->d_inode;
+               if (read_seqcount_retry(&dentry->d_seq, seq))
+                       return -ECHILD;
                if (unlikely(!*inode))
                        return -ENOENT;
                if (likely(__follow_mount_rcu(nd, path, inode)))
@@ -1848,9 +1851,10 @@ all_done: // pure jump
  * NOTE: dentry must be what nd->next_seq had been sampled from.
  */
 static const char *step_into(struct nameidata *nd, int flags,
-                    struct dentry *dentry, struct inode *inode)
+                    struct dentry *dentry)
 {
        struct path path;
+       struct inode *inode;
        int err = handle_mounts(nd, dentry, &path, &inode);
 
        if (err < 0)
@@ -1976,7 +1980,7 @@ static const char *handle_dots(struct nameidata *nd, int type)
                        parent = follow_dotdot(nd, &inode);
                if (IS_ERR(parent))
                        return ERR_CAST(parent);
-               error = step_into(nd, WALK_NOFOLLOW, parent, inode);
+               error = step_into(nd, WALK_NOFOLLOW, parent);
                if (unlikely(error))
                        return error;
 
@@ -2021,7 +2025,7 @@ static const char *walk_component(struct nameidata *nd, int flags)
        }
        if (!(flags & WALK_MORE) && nd->depth)
                put_link(nd);
-       return step_into(nd, flags, dentry, inode);
+       return step_into(nd, flags, dentry);
 }
 
 /*
@@ -2480,8 +2484,7 @@ static int handle_lookup_down(struct nameidata *nd)
        if (!(nd->flags & LOOKUP_RCU))
                dget(nd->path.dentry);
        nd->next_seq = nd->seq;
-       return PTR_ERR(step_into(nd, WALK_NOFOLLOW,
-                       nd->path.dentry, nd->inode));
+       return PTR_ERR(step_into(nd, WALK_NOFOLLOW, nd->path.dentry));
 }
 
 /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
@@ -3470,7 +3473,7 @@ static const char *open_last_lookups(struct nameidata *nd,
 finish_lookup:
        if (nd->depth)
                put_link(nd);
-       res = step_into(nd, WALK_TRAILING, dentry, inode);
+       res = step_into(nd, WALK_TRAILING, dentry);
        if (unlikely(res))
                nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
        return res;