path_init(): set nd->inode earlier in cwd-relative case
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 6 Dec 2015 01:25:06 +0000 (20:25 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 7 Dec 2015 02:18:16 +0000 (21:18 -0500)
that allows to kill the recheck of nd->seq on the way out in
this case, and this check on the way out is left only for
absolute pathnames.

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

index f89fe5f7eac3895f370bb50afd8bf868c86109f4..a08018b1485c32cf21870bfaf53185ce63105d63 100644 (file)
@@ -2028,6 +2028,15 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
                        path_get(&nd->root);
                        nd->path = nd->root;
                }
+               nd->inode = nd->path.dentry->d_inode;
+               if (!(flags & LOOKUP_RCU))
+                       return s;
+               if (likely(!read_seqcount_retry(&nd->path.dentry->d_seq, nd->seq)))
+                       return s;
+               if (!(nd->flags & LOOKUP_ROOT))
+                       nd->root.mnt = NULL;
+               rcu_read_unlock();
+               return ERR_PTR(-ECHILD);
        } else if (nd->dfd == AT_FDCWD) {
                if (flags & LOOKUP_RCU) {
                        struct fs_struct *fs = current->fs;
@@ -2038,11 +2047,14 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
                        do {
                                seq = read_seqcount_begin(&fs->seq);
                                nd->path = fs->pwd;
+                               nd->inode = nd->path.dentry->d_inode;
                                nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
                        } while (read_seqcount_retry(&fs->seq, seq));
                } else {
                        get_fs_pwd(current->fs, &nd->path);
+                       nd->inode = nd->path.dentry->d_inode;
                }
+               return s;
        } else {
                /* Caller must check execute permissions on the starting path component */
                struct fd f = fdget_raw(nd->dfd);
@@ -2072,16 +2084,6 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
                fdput(f);
                return s;
        }
-
-       nd->inode = nd->path.dentry->d_inode;
-       if (!(flags & LOOKUP_RCU))
-               return s;
-       if (likely(!read_seqcount_retry(&nd->path.dentry->d_seq, nd->seq)))
-               return s;
-       if (!(nd->flags & LOOKUP_ROOT))
-               nd->root.mnt = NULL;
-       rcu_read_unlock();
-       return ERR_PTR(-ECHILD);
 }
 
 static const char *trailing_symlink(struct nameidata *nd)