diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2015-12-05 20:51:58 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-12-06 21:18:21 -0500 |
commit | 248fb5b9557aa117f0b8c68b8cf2ce436e4d839d (patch) | |
tree | 496d169de9617a129c30c24271575bfd09c3f08b /fs/namei.c | |
parent | ef55d91700d54f29b9ac301658b5b8f377ef3206 (diff) |
namei.c: take "jump to root" into a new helper
... and use it both in path_init() (for absolute pathnames) and
get_link() (for absolute symlinks).
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 54 |
1 files changed, 26 insertions, 28 deletions
diff --git a/fs/namei.c b/fs/namei.c index a08018b1485c..0baf64b116bd 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -841,6 +841,26 @@ static inline void path_to_nameidata(const struct path *path, | |||
841 | nd->path.dentry = path->dentry; | 841 | nd->path.dentry = path->dentry; |
842 | } | 842 | } |
843 | 843 | ||
844 | static int nd_jump_root(struct nameidata *nd) | ||
845 | { | ||
846 | if (nd->flags & LOOKUP_RCU) { | ||
847 | struct dentry *d; | ||
848 | nd->path = nd->root; | ||
849 | d = nd->path.dentry; | ||
850 | nd->inode = d->d_inode; | ||
851 | nd->seq = nd->root_seq; | ||
852 | if (unlikely(read_seqcount_retry(&d->d_seq, nd->seq))) | ||
853 | return -ECHILD; | ||
854 | } else { | ||
855 | path_put(&nd->path); | ||
856 | nd->path = nd->root; | ||
857 | path_get(&nd->path); | ||
858 | nd->inode = nd->path.dentry->d_inode; | ||
859 | } | ||
860 | nd->flags |= LOOKUP_JUMPED; | ||
861 | return 0; | ||
862 | } | ||
863 | |||
844 | /* | 864 | /* |
845 | * Helper to directly jump to a known parsed path from ->follow_link, | 865 | * Helper to directly jump to a known parsed path from ->follow_link, |
846 | * caller must have taken a reference to path beforehand. | 866 | * caller must have taken a reference to path beforehand. |
@@ -1017,21 +1037,8 @@ const char *get_link(struct nameidata *nd) | |||
1017 | if (*res == '/') { | 1037 | if (*res == '/') { |
1018 | if (!nd->root.mnt) | 1038 | if (!nd->root.mnt) |
1019 | set_root(nd); | 1039 | set_root(nd); |
1020 | if (nd->flags & LOOKUP_RCU) { | 1040 | if (unlikely(nd_jump_root(nd))) |
1021 | struct dentry *d; | 1041 | return ERR_PTR(-ECHILD); |
1022 | nd->path = nd->root; | ||
1023 | d = nd->path.dentry; | ||
1024 | nd->inode = d->d_inode; | ||
1025 | nd->seq = nd->root_seq; | ||
1026 | if (unlikely(read_seqcount_retry(&d->d_seq, nd->seq))) | ||
1027 | return ERR_PTR(-ECHILD); | ||
1028 | } else { | ||
1029 | path_put(&nd->path); | ||
1030 | nd->path = nd->root; | ||
1031 | path_get(&nd->root); | ||
1032 | nd->inode = nd->path.dentry->d_inode; | ||
1033 | } | ||
1034 | nd->flags |= LOOKUP_JUMPED; | ||
1035 | while (unlikely(*++res == '/')) | 1042 | while (unlikely(*++res == '/')) |
1036 | ; | 1043 | ; |
1037 | } | 1044 | } |
@@ -2015,26 +2022,17 @@ static const char *path_init(struct nameidata *nd, unsigned flags) | |||
2015 | } | 2022 | } |
2016 | 2023 | ||
2017 | nd->root.mnt = NULL; | 2024 | nd->root.mnt = NULL; |
2025 | nd->path.mnt = NULL; | ||
2026 | nd->path.dentry = NULL; | ||
2018 | 2027 | ||
2019 | nd->m_seq = read_seqbegin(&mount_lock); | 2028 | nd->m_seq = read_seqbegin(&mount_lock); |
2020 | if (*s == '/') { | 2029 | if (*s == '/') { |
2021 | if (flags & LOOKUP_RCU) | 2030 | if (flags & LOOKUP_RCU) |
2022 | rcu_read_lock(); | 2031 | rcu_read_lock(); |
2023 | set_root(nd); | 2032 | set_root(nd); |
2024 | if (flags & LOOKUP_RCU) { | 2033 | if (likely(!nd_jump_root(nd))) |
2025 | nd->seq = nd->root_seq; | ||
2026 | nd->path = nd->root; | ||
2027 | } else { | ||
2028 | path_get(&nd->root); | ||
2029 | nd->path = nd->root; | ||
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; | 2034 | return s; |
2036 | if (!(nd->flags & LOOKUP_ROOT)) | 2035 | nd->root.mnt = NULL; |
2037 | nd->root.mnt = NULL; | ||
2038 | rcu_read_unlock(); | 2036 | rcu_read_unlock(); |
2039 | return ERR_PTR(-ECHILD); | 2037 | return ERR_PTR(-ECHILD); |
2040 | } else if (nd->dfd == AT_FDCWD) { | 2038 | } else if (nd->dfd == AT_FDCWD) { |