aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-05-09 11:19:16 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-05-15 01:10:41 -0400
commit391172c46e6f9d5d03855ff3ae5720d9826f3b59 (patch)
treece3a96b6caf2efaf7d8ac66bf3ac0cab0e37d273 /fs/namei.c
parentabc9f5beb1ca97b5157914c83c85d67a6b665d74 (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.c84
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. */
2148static int path_parentat(int dfd, const struct filename *name, 2148static 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
2164static int filename_parentat(int dfd, struct filename *name, 2169static 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,
2183struct dentry *kern_path_locked(const char *name, struct path *path) 2192struct 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;
2211out: 2219out:
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;
3451fail: 3453fail:
3452 dput(dentry); 3454 dput(dentry);
3453 dentry = ERR_PTR(error); 3455 dentry = ERR_PTR(error);
3454unlock: 3456unlock:
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);
3458out: 3460out:
3459 path_put(&nd.path); 3461 path_put(path);
3460 return dentry; 3462 return dentry;
3461} 3463}
3462 3464