diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2015-05-12 16:36:12 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-05-15 01:10:39 -0400 |
commit | 625b6d105446e82e95ddb28d6fd3d25f84f6c479 (patch) | |
tree | 583bc42760d8c50e470e32f1125d3a7617353b3c /fs/namei.c | |
parent | 18d8c860112f96b62899819f933912833398cd58 (diff) |
namei: pass the struct path to store the result down into path_lookupat()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 72 |
1 files changed, 34 insertions, 38 deletions
diff --git a/fs/namei.c b/fs/namei.c index 177934c79a04..f4c9c0774b26 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -2086,8 +2086,8 @@ static inline int lookup_last(struct nameidata *nd) | |||
2086 | } | 2086 | } |
2087 | 2087 | ||
2088 | /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ | 2088 | /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ |
2089 | static int path_lookupat(int dfd, const struct filename *name, | 2089 | static int path_lookupat(int dfd, const struct filename *name, unsigned flags, |
2090 | unsigned int flags, struct nameidata *nd) | 2090 | struct nameidata *nd, struct path *path) |
2091 | { | 2091 | { |
2092 | const char *s = path_init(dfd, name, flags, nd); | 2092 | const char *s = path_init(dfd, name, flags, nd); |
2093 | int err; | 2093 | int err; |
@@ -2108,27 +2108,31 @@ static int path_lookupat(int dfd, const struct filename *name, | |||
2108 | if (!err && nd->flags & LOOKUP_DIRECTORY) | 2108 | if (!err && nd->flags & LOOKUP_DIRECTORY) |
2109 | if (!d_can_lookup(nd->path.dentry)) | 2109 | if (!d_can_lookup(nd->path.dentry)) |
2110 | err = -ENOTDIR; | 2110 | err = -ENOTDIR; |
2111 | if (err) | 2111 | if (!err) { |
2112 | terminate_walk(nd); | 2112 | *path = nd->path; |
2113 | 2113 | nd->path.mnt = NULL; | |
2114 | nd->path.dentry = NULL; | ||
2115 | } | ||
2116 | terminate_walk(nd); | ||
2114 | path_cleanup(nd); | 2117 | path_cleanup(nd); |
2115 | return err; | 2118 | return err; |
2116 | } | 2119 | } |
2117 | 2120 | ||
2118 | static int filename_lookup(int dfd, struct filename *name, | 2121 | static int filename_lookup(int dfd, struct filename *name, unsigned flags, |
2119 | unsigned int flags, struct nameidata *nd) | 2122 | struct nameidata *nd, struct path *path) |
2120 | { | 2123 | { |
2121 | int retval; | 2124 | int retval; |
2122 | struct nameidata *saved_nd = set_nameidata(nd); | 2125 | struct nameidata *saved_nd = set_nameidata(nd); |
2123 | 2126 | ||
2124 | retval = path_lookupat(dfd, name, flags | LOOKUP_RCU, nd); | 2127 | retval = path_lookupat(dfd, name, flags | LOOKUP_RCU, nd, path); |
2125 | if (unlikely(retval == -ECHILD)) | 2128 | if (unlikely(retval == -ECHILD)) |
2126 | retval = path_lookupat(dfd, name, flags, nd); | 2129 | retval = path_lookupat(dfd, name, flags, nd, path); |
2127 | if (unlikely(retval == -ESTALE)) | 2130 | if (unlikely(retval == -ESTALE)) |
2128 | retval = path_lookupat(dfd, name, flags | LOOKUP_REVAL, nd); | 2131 | retval = path_lookupat(dfd, name, flags | LOOKUP_REVAL, |
2132 | nd, path); | ||
2129 | 2133 | ||
2130 | if (likely(!retval)) | 2134 | if (likely(!retval)) |
2131 | audit_inode(name, nd->path.dentry, flags & LOOKUP_PARENT); | 2135 | audit_inode(name, path->dentry, flags & LOOKUP_PARENT); |
2132 | restore_nameidata(saved_nd); | 2136 | restore_nameidata(saved_nd); |
2133 | return retval; | 2137 | return retval; |
2134 | } | 2138 | } |
@@ -2209,10 +2213,8 @@ int kern_path(const char *name, unsigned int flags, struct path *path) | |||
2209 | int res = PTR_ERR(filename); | 2213 | int res = PTR_ERR(filename); |
2210 | 2214 | ||
2211 | if (!IS_ERR(filename)) { | 2215 | if (!IS_ERR(filename)) { |
2212 | res = filename_lookup(AT_FDCWD, filename, flags, &nd); | 2216 | res = filename_lookup(AT_FDCWD, filename, flags, &nd, path); |
2213 | putname(filename); | 2217 | putname(filename); |
2214 | if (!res) | ||
2215 | *path = nd.path; | ||
2216 | } | 2218 | } |
2217 | return res; | 2219 | return res; |
2218 | } | 2220 | } |
@@ -2241,9 +2243,7 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, | |||
2241 | nd.root.dentry = dentry; | 2243 | nd.root.dentry = dentry; |
2242 | nd.root.mnt = mnt; | 2244 | nd.root.mnt = mnt; |
2243 | err = filename_lookup(AT_FDCWD, filename, | 2245 | err = filename_lookup(AT_FDCWD, filename, |
2244 | flags | LOOKUP_ROOT, &nd); | 2246 | flags | LOOKUP_ROOT, &nd, path); |
2245 | if (!err) | ||
2246 | *path = nd.path; | ||
2247 | putname(filename); | 2247 | putname(filename); |
2248 | } | 2248 | } |
2249 | return err; | 2249 | return err; |
@@ -2311,10 +2311,8 @@ int user_path_at_empty(int dfd, const char __user *name, unsigned flags, | |||
2311 | 2311 | ||
2312 | BUG_ON(flags & LOOKUP_PARENT); | 2312 | BUG_ON(flags & LOOKUP_PARENT); |
2313 | 2313 | ||
2314 | err = filename_lookup(dfd, tmp, flags, &nd); | 2314 | err = filename_lookup(dfd, tmp, flags, &nd, path); |
2315 | putname(tmp); | 2315 | putname(tmp); |
2316 | if (!err) | ||
2317 | *path = nd.path; | ||
2318 | } | 2316 | } |
2319 | return err; | 2317 | return err; |
2320 | } | 2318 | } |
@@ -3261,44 +3259,42 @@ static int do_tmpfile(int dfd, struct filename *pathname, | |||
3261 | struct file *file, int *opened) | 3259 | struct file *file, int *opened) |
3262 | { | 3260 | { |
3263 | static const struct qstr name = QSTR_INIT("/", 1); | 3261 | static const struct qstr name = QSTR_INIT("/", 1); |
3264 | struct dentry *dentry, *child; | 3262 | struct dentry *child; |
3265 | struct inode *dir; | 3263 | struct inode *dir; |
3264 | struct path path; | ||
3266 | int error = path_lookupat(dfd, pathname, | 3265 | int error = path_lookupat(dfd, pathname, |
3267 | flags | LOOKUP_DIRECTORY, nd); | 3266 | flags | LOOKUP_DIRECTORY, nd, &path); |
3268 | if (unlikely(error)) | 3267 | if (unlikely(error)) |
3269 | return error; | 3268 | return error; |
3270 | error = mnt_want_write(nd->path.mnt); | 3269 | error = mnt_want_write(path.mnt); |
3271 | if (unlikely(error)) | 3270 | if (unlikely(error)) |
3272 | goto out; | 3271 | goto out; |
3272 | dir = path.dentry->d_inode; | ||
3273 | /* we want directory to be writable */ | 3273 | /* we want directory to be writable */ |
3274 | error = inode_permission(nd->inode, MAY_WRITE | MAY_EXEC); | 3274 | error = inode_permission(dir, MAY_WRITE | MAY_EXEC); |
3275 | if (error) | 3275 | if (error) |
3276 | goto out2; | 3276 | goto out2; |
3277 | dentry = nd->path.dentry; | ||
3278 | dir = dentry->d_inode; | ||
3279 | if (!dir->i_op->tmpfile) { | 3277 | if (!dir->i_op->tmpfile) { |
3280 | error = -EOPNOTSUPP; | 3278 | error = -EOPNOTSUPP; |
3281 | goto out2; | 3279 | goto out2; |
3282 | } | 3280 | } |
3283 | child = d_alloc(dentry, &name); | 3281 | child = d_alloc(path.dentry, &name); |
3284 | if (unlikely(!child)) { | 3282 | if (unlikely(!child)) { |
3285 | error = -ENOMEM; | 3283 | error = -ENOMEM; |
3286 | goto out2; | 3284 | goto out2; |
3287 | } | 3285 | } |
3288 | nd->flags &= ~LOOKUP_DIRECTORY; | 3286 | dput(path.dentry); |
3289 | nd->flags |= op->intent; | 3287 | path.dentry = child; |
3290 | dput(nd->path.dentry); | 3288 | error = dir->i_op->tmpfile(dir, child, op->mode); |
3291 | nd->path.dentry = child; | ||
3292 | error = dir->i_op->tmpfile(dir, nd->path.dentry, op->mode); | ||
3293 | if (error) | 3289 | if (error) |
3294 | goto out2; | 3290 | goto out2; |
3295 | audit_inode(pathname, nd->path.dentry, 0); | 3291 | audit_inode(pathname, child, 0); |
3296 | /* Don't check for other permissions, the inode was just created */ | 3292 | /* Don't check for other permissions, the inode was just created */ |
3297 | error = may_open(&nd->path, MAY_OPEN, op->open_flag); | 3293 | error = may_open(&path, MAY_OPEN, op->open_flag); |
3298 | if (error) | 3294 | if (error) |
3299 | goto out2; | 3295 | goto out2; |
3300 | file->f_path.mnt = nd->path.mnt; | 3296 | file->f_path.mnt = path.mnt; |
3301 | error = finish_open(file, nd->path.dentry, NULL, opened); | 3297 | error = finish_open(file, child, NULL, opened); |
3302 | if (error) | 3298 | if (error) |
3303 | goto out2; | 3299 | goto out2; |
3304 | error = open_check_o_direct(file); | 3300 | error = open_check_o_direct(file); |
@@ -3311,9 +3307,9 @@ static int do_tmpfile(int dfd, struct filename *pathname, | |||
3311 | spin_unlock(&inode->i_lock); | 3307 | spin_unlock(&inode->i_lock); |
3312 | } | 3308 | } |
3313 | out2: | 3309 | out2: |
3314 | mnt_drop_write(nd->path.mnt); | 3310 | mnt_drop_write(path.mnt); |
3315 | out: | 3311 | out: |
3316 | path_put(&nd->path); | 3312 | path_put(&path); |
3317 | return error; | 3313 | return error; |
3318 | } | 3314 | } |
3319 | 3315 | ||