diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2015-12-05 20:25:06 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-12-06 21:18:16 -0500 |
commit | ef55d91700d54f29b9ac301658b5b8f377ef3206 (patch) | |
tree | bc40a635ac5368b450197b540502a558a8a9efe8 /fs/namei.c | |
parent | 9e6697e26f9888cdb6088664d31c3772b0dff0a4 (diff) | |
download | linux-ef55d91700d54f29b9ac301658b5b8f377ef3206.tar.gz linux-ef55d91700d54f29b9ac301658b5b8f377ef3206.tar.bz2 linux-ef55d91700d54f29b9ac301658b5b8f377ef3206.zip |
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.c | 22 |
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) 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) |