diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2015-05-09 11:19:16 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-05-15 01:10:41 -0400 |
commit | 391172c46e6f9d5d03855ff3ae5720d9826f3b59 (patch) | |
tree | ce3a96b6caf2efaf7d8ac66bf3ac0cab0e37d273 /fs/namei.c | |
parent | abc9f5beb1ca97b5157914c83c85d67a6b665d74 (diff) |
namei: shift nameidata down into filename_parentat()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 84 |
1 files changed, 43 insertions, 41 deletions
diff --git a/fs/namei.c b/fs/namei.c index a9c593e4f35e..593cf3b01e74 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -2146,7 +2146,8 @@ static int filename_lookup(int dfd, struct filename *name, unsigned flags, | |||
2146 | 2146 | ||
2147 | /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ | 2147 | /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ |
2148 | static int path_parentat(int dfd, const struct filename *name, | 2148 | static int path_parentat(int dfd, const struct filename *name, |
2149 | unsigned int flags, struct nameidata *nd) | 2149 | unsigned int flags, struct nameidata *nd, |
2150 | struct path *parent) | ||
2150 | { | 2151 | { |
2151 | const char *s = path_init(dfd, name, flags, nd); | 2152 | const char *s = path_init(dfd, name, flags, nd); |
2152 | int err; | 2153 | int err; |
@@ -2155,26 +2156,34 @@ static int path_parentat(int dfd, const struct filename *name, | |||
2155 | err = link_path_walk(s, nd); | 2156 | err = link_path_walk(s, nd); |
2156 | if (!err) | 2157 | if (!err) |
2157 | err = complete_walk(nd); | 2158 | err = complete_walk(nd); |
2158 | if (err) | 2159 | if (!err) { |
2159 | terminate_walk(nd); | 2160 | *parent = nd->path; |
2161 | nd->path.mnt = NULL; | ||
2162 | nd->path.dentry = NULL; | ||
2163 | } | ||
2164 | terminate_walk(nd); | ||
2160 | path_cleanup(nd); | 2165 | path_cleanup(nd); |
2161 | return err; | 2166 | return err; |
2162 | } | 2167 | } |
2163 | 2168 | ||
2164 | static int filename_parentat(int dfd, struct filename *name, | 2169 | static int filename_parentat(int dfd, struct filename *name, |
2165 | unsigned int flags, struct nameidata *nd) | 2170 | unsigned int flags, struct path *parent, |
2171 | struct qstr *last, int *type) | ||
2166 | { | 2172 | { |
2167 | int retval; | 2173 | int retval; |
2168 | struct nameidata *saved_nd = set_nameidata(nd); | 2174 | struct nameidata nd, *saved_nd = set_nameidata(&nd); |
2169 | 2175 | ||
2170 | retval = path_parentat(dfd, name, flags | LOOKUP_RCU, nd); | 2176 | retval = path_parentat(dfd, name, flags | LOOKUP_RCU, &nd, parent); |
2171 | if (unlikely(retval == -ECHILD)) | 2177 | if (unlikely(retval == -ECHILD)) |
2172 | retval = path_parentat(dfd, name, flags, nd); | 2178 | retval = path_parentat(dfd, name, flags, &nd, parent); |
2173 | if (unlikely(retval == -ESTALE)) | 2179 | if (unlikely(retval == -ESTALE)) |
2174 | retval = path_parentat(dfd, name, flags | LOOKUP_REVAL, nd); | 2180 | retval = path_parentat(dfd, name, flags | LOOKUP_REVAL, |
2175 | 2181 | &nd, parent); | |
2176 | if (likely(!retval)) | 2182 | if (likely(!retval)) { |
2177 | audit_inode(name, nd->path.dentry, LOOKUP_PARENT); | 2183 | *last = nd.last; |
2184 | *type = nd.last_type; | ||
2185 | audit_inode(name, parent->dentry, LOOKUP_PARENT); | ||
2186 | } | ||
2178 | restore_nameidata(saved_nd); | 2187 | restore_nameidata(saved_nd); |
2179 | return retval; | 2188 | return retval; |
2180 | } | 2189 | } |
@@ -2183,31 +2192,30 @@ static int filename_parentat(int dfd, struct filename *name, | |||
2183 | struct dentry *kern_path_locked(const char *name, struct path *path) | 2192 | struct dentry *kern_path_locked(const char *name, struct path *path) |
2184 | { | 2193 | { |
2185 | struct filename *filename = getname_kernel(name); | 2194 | struct filename *filename = getname_kernel(name); |
2186 | struct nameidata nd; | 2195 | struct qstr last; |
2196 | int type; | ||
2187 | struct dentry *d; | 2197 | struct dentry *d; |
2188 | int err; | 2198 | int err; |
2189 | 2199 | ||
2190 | if (IS_ERR(filename)) | 2200 | if (IS_ERR(filename)) |
2191 | return ERR_CAST(filename); | 2201 | return ERR_CAST(filename); |
2192 | 2202 | ||
2193 | err = filename_parentat(AT_FDCWD, filename, 0, &nd); | 2203 | err = filename_parentat(AT_FDCWD, filename, 0, path, &last, &type); |
2194 | if (err) { | 2204 | if (err) { |
2195 | d = ERR_PTR(err); | 2205 | d = ERR_PTR(err); |
2196 | goto out; | 2206 | goto out; |
2197 | } | 2207 | } |
2198 | if (nd.last_type != LAST_NORM) { | 2208 | if (type != LAST_NORM) { |
2199 | path_put(&nd.path); | 2209 | path_put(path); |
2200 | d = ERR_PTR(-EINVAL); | 2210 | d = ERR_PTR(-EINVAL); |
2201 | goto out; | 2211 | goto out; |
2202 | } | 2212 | } |
2203 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); | 2213 | mutex_lock_nested(&path->dentry->d_inode->i_mutex, I_MUTEX_PARENT); |
2204 | d = __lookup_hash(&nd.last, nd.path.dentry, 0); | 2214 | d = __lookup_hash(&last, path->dentry, 0); |
2205 | if (IS_ERR(d)) { | 2215 | if (IS_ERR(d)) { |
2206 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2216 | mutex_unlock(&path->dentry->d_inode->i_mutex); |
2207 | path_put(&nd.path); | 2217 | path_put(path); |
2208 | goto out; | ||
2209 | } | 2218 | } |
2210 | *path = nd.path; | ||
2211 | out: | 2219 | out: |
2212 | putname(filename); | 2220 | putname(filename); |
2213 | return d; | 2221 | return d; |
@@ -2317,7 +2325,6 @@ user_path_parent(int dfd, const char __user *path, | |||
2317 | int *type, | 2325 | int *type, |
2318 | unsigned int flags) | 2326 | unsigned int flags) |
2319 | { | 2327 | { |
2320 | struct nameidata nd; | ||
2321 | struct filename *s = getname(path); | 2328 | struct filename *s = getname(path); |
2322 | int error; | 2329 | int error; |
2323 | 2330 | ||
@@ -2327,15 +2334,11 @@ user_path_parent(int dfd, const char __user *path, | |||
2327 | if (IS_ERR(s)) | 2334 | if (IS_ERR(s)) |
2328 | return s; | 2335 | return s; |
2329 | 2336 | ||
2330 | error = filename_parentat(dfd, s, flags, &nd); | 2337 | error = filename_parentat(dfd, s, flags, parent, last, type); |
2331 | if (error) { | 2338 | if (error) { |
2332 | putname(s); | 2339 | putname(s); |
2333 | return ERR_PTR(error); | 2340 | s = ERR_PTR(error); |
2334 | } | 2341 | } |
2335 | *parent = nd.path; | ||
2336 | *last = nd.last; | ||
2337 | *type = nd.last_type; | ||
2338 | |||
2339 | return s; | 2342 | return s; |
2340 | } | 2343 | } |
2341 | 2344 | ||
@@ -3394,7 +3397,8 @@ static struct dentry *filename_create(int dfd, struct filename *name, | |||
3394 | struct path *path, unsigned int lookup_flags) | 3397 | struct path *path, unsigned int lookup_flags) |
3395 | { | 3398 | { |
3396 | struct dentry *dentry = ERR_PTR(-EEXIST); | 3399 | struct dentry *dentry = ERR_PTR(-EEXIST); |
3397 | struct nameidata nd; | 3400 | struct qstr last; |
3401 | int type; | ||
3398 | int err2; | 3402 | int err2; |
3399 | int error; | 3403 | int error; |
3400 | bool is_dir = (lookup_flags & LOOKUP_DIRECTORY); | 3404 | bool is_dir = (lookup_flags & LOOKUP_DIRECTORY); |
@@ -3405,7 +3409,7 @@ static struct dentry *filename_create(int dfd, struct filename *name, | |||
3405 | */ | 3409 | */ |
3406 | lookup_flags &= LOOKUP_REVAL; | 3410 | lookup_flags &= LOOKUP_REVAL; |
3407 | 3411 | ||
3408 | error = filename_parentat(dfd, name, lookup_flags, &nd); | 3412 | error = filename_parentat(dfd, name, lookup_flags, path, &last, &type); |
3409 | if (error) | 3413 | if (error) |
3410 | return ERR_PTR(error); | 3414 | return ERR_PTR(error); |
3411 | 3415 | ||
@@ -3413,18 +3417,17 @@ static struct dentry *filename_create(int dfd, struct filename *name, | |||
3413 | * Yucky last component or no last component at all? | 3417 | * Yucky last component or no last component at all? |
3414 | * (foo/., foo/.., /////) | 3418 | * (foo/., foo/.., /////) |
3415 | */ | 3419 | */ |
3416 | if (nd.last_type != LAST_NORM) | 3420 | if (type != LAST_NORM) |
3417 | goto out; | 3421 | goto out; |
3418 | nd.flags &= ~LOOKUP_PARENT; | ||
3419 | nd.flags |= LOOKUP_CREATE | LOOKUP_EXCL; | ||
3420 | 3422 | ||
3421 | /* don't fail immediately if it's r/o, at least try to report other errors */ | 3423 | /* don't fail immediately if it's r/o, at least try to report other errors */ |
3422 | err2 = mnt_want_write(nd.path.mnt); | 3424 | err2 = mnt_want_write(path->mnt); |
3423 | /* | 3425 | /* |
3424 | * Do the final lookup. | 3426 | * Do the final lookup. |
3425 | */ | 3427 | */ |
3426 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); | 3428 | lookup_flags |= LOOKUP_CREATE | LOOKUP_EXCL; |
3427 | dentry = __lookup_hash(&nd.last, nd.path.dentry, nd.flags); | 3429 | mutex_lock_nested(&path->dentry->d_inode->i_mutex, I_MUTEX_PARENT); |
3430 | dentry = __lookup_hash(&last, path->dentry, lookup_flags); | ||
3428 | if (IS_ERR(dentry)) | 3431 | if (IS_ERR(dentry)) |
3429 | goto unlock; | 3432 | goto unlock; |
3430 | 3433 | ||
@@ -3438,7 +3441,7 @@ static struct dentry *filename_create(int dfd, struct filename *name, | |||
3438 | * all is fine. Let's be bastards - you had / on the end, you've | 3441 | * all is fine. Let's be bastards - you had / on the end, you've |
3439 | * been asking for (non-existent) directory. -ENOENT for you. | 3442 | * been asking for (non-existent) directory. -ENOENT for you. |
3440 | */ | 3443 | */ |
3441 | if (unlikely(!is_dir && nd.last.name[nd.last.len])) { | 3444 | if (unlikely(!is_dir && last.name[last.len])) { |
3442 | error = -ENOENT; | 3445 | error = -ENOENT; |
3443 | goto fail; | 3446 | goto fail; |
3444 | } | 3447 | } |
@@ -3446,17 +3449,16 @@ static struct dentry *filename_create(int dfd, struct filename *name, | |||
3446 | error = err2; | 3449 | error = err2; |
3447 | goto fail; | 3450 | goto fail; |
3448 | } | 3451 | } |
3449 | *path = nd.path; | ||
3450 | return dentry; | 3452 | return dentry; |
3451 | fail: | 3453 | fail: |
3452 | dput(dentry); | 3454 | dput(dentry); |
3453 | dentry = ERR_PTR(error); | 3455 | dentry = ERR_PTR(error); |
3454 | unlock: | 3456 | unlock: |
3455 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 3457 | mutex_unlock(&path->dentry->d_inode->i_mutex); |
3456 | if (!err2) | 3458 | if (!err2) |
3457 | mnt_drop_write(nd.path.mnt); | 3459 | mnt_drop_write(path->mnt); |
3458 | out: | 3460 | out: |
3459 | path_put(&nd.path); | 3461 | path_put(path); |
3460 | return dentry; | 3462 | return dentry; |
3461 | } | 3463 | } |
3462 | 3464 | ||