aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-10 15:44:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-10 15:44:24 -0400
commitb05430fc9341fea7a6228a3611c850a476809596 (patch)
tree91bd662d269a3478db78d6a04a34901f0cfe521b /fs/namei.c
parentd0d272771035a36a7839bb70ab6ebae3f4f4960b (diff)
parent48f5ec21d9c67e881ff35343988e290ef5cf933f (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs pile 3 (of many) from Al Viro: "Waiman's conversion of d_path() and bits related to it, kern_path_mountpoint(), several cleanups and fixes (exportfs one is -stable fodder, IMO). There definitely will be more... ;-/" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: split read_seqretry_or_unlock(), convert d_walk() to resulting primitives dcache: Translating dentry into pathname without taking rename_lock autofs4 - fix device ioctl mount lookup introduce kern_path_mountpoint() rename user_path_umountat() to user_path_mountpoint_at() take unlazy_walk() into umount_lookup_last() Kill indirect include of file.h from eventfd.h, use fdget() in cgroup.c prune_super(): sb->s_op is never NULL exportfs: don't assume that ->iterate() won't feed us too long entries afs: get rid of redundant ->d_name.len checks
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c112
1 files changed, 59 insertions, 53 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 5e6aaadc1dcd..409a441ba2ae 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2209,7 +2209,7 @@ user_path_parent(int dfd, const char __user *path, struct nameidata *nd,
2209} 2209}
2210 2210
2211/** 2211/**
2212 * umount_lookup_last - look up last component for umount 2212 * mountpoint_last - look up last component for umount
2213 * @nd: pathwalk nameidata - currently pointing at parent directory of "last" 2213 * @nd: pathwalk nameidata - currently pointing at parent directory of "last"
2214 * @path: pointer to container for result 2214 * @path: pointer to container for result
2215 * 2215 *
@@ -2236,25 +2236,28 @@ user_path_parent(int dfd, const char __user *path, struct nameidata *nd,
2236 * to the link, and nd->path will *not* be put. 2236 * to the link, and nd->path will *not* be put.
2237 */ 2237 */
2238static int 2238static int
2239umount_lookup_last(struct nameidata *nd, struct path *path) 2239mountpoint_last(struct nameidata *nd, struct path *path)
2240{ 2240{
2241 int error = 0; 2241 int error = 0;
2242 struct dentry *dentry; 2242 struct dentry *dentry;
2243 struct dentry *dir = nd->path.dentry; 2243 struct dentry *dir = nd->path.dentry;
2244 2244
2245 if (unlikely(nd->flags & LOOKUP_RCU)) { 2245 /* If we're in rcuwalk, drop out of it to handle last component */
2246 WARN_ON_ONCE(1); 2246 if (nd->flags & LOOKUP_RCU) {
2247 error = -ECHILD; 2247 if (unlazy_walk(nd, NULL)) {
2248 goto error_check; 2248 error = -ECHILD;
2249 goto out;
2250 }
2249 } 2251 }
2250 2252
2251 nd->flags &= ~LOOKUP_PARENT; 2253 nd->flags &= ~LOOKUP_PARENT;
2252 2254
2253 if (unlikely(nd->last_type != LAST_NORM)) { 2255 if (unlikely(nd->last_type != LAST_NORM)) {
2254 error = handle_dots(nd, nd->last_type); 2256 error = handle_dots(nd, nd->last_type);
2255 if (!error) 2257 if (error)
2256 dentry = dget(nd->path.dentry); 2258 goto out;
2257 goto error_check; 2259 dentry = dget(nd->path.dentry);
2260 goto done;
2258 } 2261 }
2259 2262
2260 mutex_lock(&dir->d_inode->i_mutex); 2263 mutex_lock(&dir->d_inode->i_mutex);
@@ -2268,44 +2271,43 @@ umount_lookup_last(struct nameidata *nd, struct path *path)
2268 dentry = d_alloc(dir, &nd->last); 2271 dentry = d_alloc(dir, &nd->last);
2269 if (!dentry) { 2272 if (!dentry) {
2270 error = -ENOMEM; 2273 error = -ENOMEM;
2271 } else { 2274 goto out;
2272 dentry = lookup_real(dir->d_inode, dentry, nd->flags);
2273 if (IS_ERR(dentry))
2274 error = PTR_ERR(dentry);
2275 } 2275 }
2276 dentry = lookup_real(dir->d_inode, dentry, nd->flags);
2277 error = PTR_ERR(dentry);
2278 if (IS_ERR(dentry))
2279 goto out;
2276 } 2280 }
2277 mutex_unlock(&dir->d_inode->i_mutex); 2281 mutex_unlock(&dir->d_inode->i_mutex);
2278 2282
2279error_check: 2283done:
2280 if (!error) { 2284 if (!dentry->d_inode) {
2281 if (!dentry->d_inode) { 2285 error = -ENOENT;
2282 error = -ENOENT; 2286 dput(dentry);
2283 dput(dentry); 2287 goto out;
2284 } else {
2285 path->dentry = dentry;
2286 path->mnt = mntget(nd->path.mnt);
2287 if (should_follow_link(dentry->d_inode,
2288 nd->flags & LOOKUP_FOLLOW))
2289 return 1;
2290 follow_mount(path);
2291 }
2292 } 2288 }
2289 path->dentry = dentry;
2290 path->mnt = mntget(nd->path.mnt);
2291 if (should_follow_link(dentry->d_inode, nd->flags & LOOKUP_FOLLOW))
2292 return 1;
2293 follow_mount(path);
2294 error = 0;
2295out:
2293 terminate_walk(nd); 2296 terminate_walk(nd);
2294 return error; 2297 return error;
2295} 2298}
2296 2299
2297/** 2300/**
2298 * path_umountat - look up a path to be umounted 2301 * path_mountpoint - look up a path to be umounted
2299 * @dfd: directory file descriptor to start walk from 2302 * @dfd: directory file descriptor to start walk from
2300 * @name: full pathname to walk 2303 * @name: full pathname to walk
2301 * @flags: lookup flags 2304 * @flags: lookup flags
2302 * @nd: pathwalk nameidata
2303 * 2305 *
2304 * Look up the given name, but don't attempt to revalidate the last component. 2306 * Look up the given name, but don't attempt to revalidate the last component.
2305 * Returns 0 and "path" will be valid on success; Retuns error otherwise. 2307 * Returns 0 and "path" will be valid on success; Retuns error otherwise.
2306 */ 2308 */
2307static int 2309static int
2308path_umountat(int dfd, const char *name, struct path *path, unsigned int flags) 2310path_mountpoint(int dfd, const char *name, struct path *path, unsigned int flags)
2309{ 2311{
2310 struct file *base = NULL; 2312 struct file *base = NULL;
2311 struct nameidata nd; 2313 struct nameidata nd;
@@ -2320,16 +2322,7 @@ path_umountat(int dfd, const char *name, struct path *path, unsigned int flags)
2320 if (err) 2322 if (err)
2321 goto out; 2323 goto out;
2322 2324
2323 /* If we're in rcuwalk, drop out of it to handle last component */ 2325 err = mountpoint_last(&nd, path);
2324 if (nd.flags & LOOKUP_RCU) {
2325 err = unlazy_walk(&nd, NULL);
2326 if (err) {
2327 terminate_walk(&nd);
2328 goto out;
2329 }
2330 }
2331
2332 err = umount_lookup_last(&nd, path);
2333 while (err > 0) { 2326 while (err > 0) {
2334 void *cookie; 2327 void *cookie;
2335 struct path link = *path; 2328 struct path link = *path;
@@ -2340,7 +2333,7 @@ path_umountat(int dfd, const char *name, struct path *path, unsigned int flags)
2340 err = follow_link(&link, &nd, &cookie); 2333 err = follow_link(&link, &nd, &cookie);
2341 if (err) 2334 if (err)
2342 break; 2335 break;
2343 err = umount_lookup_last(&nd, path); 2336 err = mountpoint_last(&nd, path);
2344 put_link(&nd, &link, cookie); 2337 put_link(&nd, &link, cookie);
2345 } 2338 }
2346out: 2339out:
@@ -2353,8 +2346,22 @@ out:
2353 return err; 2346 return err;
2354} 2347}
2355 2348
2349static int
2350filename_mountpoint(int dfd, struct filename *s, struct path *path,
2351 unsigned int flags)
2352{
2353 int error = path_mountpoint(dfd, s->name, path, flags | LOOKUP_RCU);
2354 if (unlikely(error == -ECHILD))
2355 error = path_mountpoint(dfd, s->name, path, flags);
2356 if (unlikely(error == -ESTALE))
2357 error = path_mountpoint(dfd, s->name, path, flags | LOOKUP_REVAL);
2358 if (likely(!error))
2359 audit_inode(s, path->dentry, 0);
2360 return error;
2361}
2362
2356/** 2363/**
2357 * user_path_umountat - lookup a path from userland in order to umount it 2364 * user_path_mountpoint_at - lookup a path from userland in order to umount it
2358 * @dfd: directory file descriptor 2365 * @dfd: directory file descriptor
2359 * @name: pathname from userland 2366 * @name: pathname from userland
2360 * @flags: lookup flags 2367 * @flags: lookup flags
@@ -2368,28 +2375,27 @@ out:
2368 * Returns 0 and populates "path" on success. 2375 * Returns 0 and populates "path" on success.
2369 */ 2376 */
2370int 2377int
2371user_path_umountat(int dfd, const char __user *name, unsigned int flags, 2378user_path_mountpoint_at(int dfd, const char __user *name, unsigned int flags,
2372 struct path *path) 2379 struct path *path)
2373{ 2380{
2374 struct filename *s = getname(name); 2381 struct filename *s = getname(name);
2375 int error; 2382 int error;
2376
2377 if (IS_ERR(s)) 2383 if (IS_ERR(s))
2378 return PTR_ERR(s); 2384 return PTR_ERR(s);
2379 2385 error = filename_mountpoint(dfd, s, path, flags);
2380 error = path_umountat(dfd, s->name, path, flags | LOOKUP_RCU);
2381 if (unlikely(error == -ECHILD))
2382 error = path_umountat(dfd, s->name, path, flags);
2383 if (unlikely(error == -ESTALE))
2384 error = path_umountat(dfd, s->name, path, flags | LOOKUP_REVAL);
2385
2386 if (likely(!error))
2387 audit_inode(s, path->dentry, 0);
2388
2389 putname(s); 2386 putname(s);
2390 return error; 2387 return error;
2391} 2388}
2392 2389
2390int
2391kern_path_mountpoint(int dfd, const char *name, struct path *path,
2392 unsigned int flags)
2393{
2394 struct filename s = {.name = name};
2395 return filename_mountpoint(dfd, &s, path, flags);
2396}
2397EXPORT_SYMBOL(kern_path_mountpoint);
2398
2393/* 2399/*
2394 * It's inline, so penalty for filesystems that don't use sticky bit is 2400 * It's inline, so penalty for filesystems that don't use sticky bit is
2395 * minimal. 2401 * minimal.