aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-12-05 20:25:06 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2015-12-06 21:18:16 -0500
commitef55d91700d54f29b9ac301658b5b8f377ef3206 (patch)
treebc40a635ac5368b450197b540502a558a8a9efe8 /fs/namei.c
parent9e6697e26f9888cdb6088664d31c3772b0dff0a4 (diff)
path_init(): set nd->inode earlier in cwd-relative case
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>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/fs/namei.c b/fs/namei.c
index f89fe5f7eac3..a08018b1485c 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2028,6 +2028,15 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
2028 path_get(&nd->root); 2028 path_get(&nd->root);
2029 nd->path = nd->root; 2029 nd->path = nd->root;
2030 } 2030 }
2031 nd->inode = nd->path.dentry->d_inode;
2032 if (!(flags & LOOKUP_RCU))
2033 return s;
2034 if (likely(!read_seqcount_retry(&nd->path.dentry->d_seq, nd->seq)))
2035 return s;
2036 if (!(nd->flags & LOOKUP_ROOT))
2037 nd->root.mnt = NULL;
2038 rcu_read_unlock();
2039 return ERR_PTR(-ECHILD);
2031 } else if (nd->dfd == AT_FDCWD) { 2040 } else if (nd->dfd == AT_FDCWD) {
2032 if (flags & LOOKUP_RCU) { 2041 if (flags & LOOKUP_RCU) {
2033 struct fs_struct *fs = current->fs; 2042 struct fs_struct *fs = current->fs;
@@ -2038,11 +2047,14 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
2038 do { 2047 do {
2039 seq = read_seqcount_begin(&fs->seq); 2048 seq = read_seqcount_begin(&fs->seq);
2040 nd->path = fs->pwd; 2049 nd->path = fs->pwd;
2050 nd->inode = nd->path.dentry->d_inode;
2041 nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); 2051 nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
2042 } while (read_seqcount_retry(&fs->seq, seq)); 2052 } while (read_seqcount_retry(&fs->seq, seq));
2043 } else { 2053 } else {
2044 get_fs_pwd(current->fs, &nd->path); 2054 get_fs_pwd(current->fs, &nd->path);
2055 nd->inode = nd->path.dentry->d_inode;
2045 } 2056 }
2057 return s;
2046 } else { 2058 } else {
2047 /* Caller must check execute permissions on the starting path component */ 2059 /* Caller must check execute permissions on the starting path component */
2048 struct fd f = fdget_raw(nd->dfd); 2060 struct fd f = fdget_raw(nd->dfd);
@@ -2072,16 +2084,6 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
2072 fdput(f); 2084 fdput(f);
2073 return s; 2085 return s;
2074 } 2086 }
2075
2076 nd->inode = nd->path.dentry->d_inode;
2077 if (!(flags & LOOKUP_RCU))
2078 return s;
2079 if (likely(!read_seqcount_retry(&nd->path.dentry->d_seq, nd->seq)))
2080 return s;
2081 if (!(nd->flags & LOOKUP_ROOT))
2082 nd->root.mnt = NULL;
2083 rcu_read_unlock();
2084 return ERR_PTR(-ECHILD);
2085} 2087}
2086 2088
2087static const char *trailing_symlink(struct nameidata *nd) 2089static const char *trailing_symlink(struct nameidata *nd)