aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-02-23 17:54:08 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2011-03-14 09:15:25 -0400
commit13aab428a73d3200b9283b61b7fdf5713181ac66 (patch)
treeb7350283378b60366609dca7b02c412b4632879e
parent47c805dc2d2dff686962f5f0baa6bac2d703ba19 (diff)
separate -ESTALE/-ECHILD retries in do_filp_open() from real work
new helper: path_openat(). Does what do_filp_open() does, except that it tries only the walk mode (RCU/normal/force revalidation) it had been told to. Both create and non-create branches are using path_lookupat() now. Fixed the double audit_inode() in non-create branch. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/namei.c49
1 files changed, 20 insertions, 29 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 9c7fa946abe1..01a17dd2f151 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2292,19 +2292,14 @@ exit:
2292 return ERR_PTR(error); 2292 return ERR_PTR(error);
2293} 2293}
2294 2294
2295/* 2295static struct file *path_openat(int dfd, const char *pathname,
2296 * Note that the low bits of the passed in "open_flag"
2297 * are not the same as in the local variable "flag". See
2298 * open_to_namei_flags() for more details.
2299 */
2300struct file *do_filp_open(int dfd, const char *pathname,
2301 const struct open_flags *op, int flags) 2296 const struct open_flags *op, int flags)
2302{ 2297{
2303 struct file *filp; 2298 struct file *filp;
2304 struct nameidata nd; 2299 struct nameidata nd;
2305 int error;
2306 struct path path; 2300 struct path path;
2307 int count = 0; 2301 int count = 0;
2302 int error;
2308 2303
2309 filp = get_empty_filp(); 2304 filp = get_empty_filp();
2310 if (!filp) 2305 if (!filp)
@@ -2319,42 +2314,27 @@ struct file *do_filp_open(int dfd, const char *pathname,
2319 goto creat; 2314 goto creat;
2320 2315
2321 /* !O_CREAT, simple open */ 2316 /* !O_CREAT, simple open */
2322 error = do_path_lookup(dfd, pathname, flags | op->intent, &nd); 2317 error = path_lookupat(dfd, pathname, flags | op->intent, &nd);
2323 if (unlikely(error)) 2318 if (unlikely(error))
2324 goto out_filp2; 2319 goto out_filp;
2325 error = -ELOOP; 2320 error = -ELOOP;
2326 if (!(nd.flags & LOOKUP_FOLLOW)) { 2321 if (!(nd.flags & LOOKUP_FOLLOW)) {
2327 if (nd.inode->i_op->follow_link) 2322 if (nd.inode->i_op->follow_link)
2328 goto out_path2; 2323 goto out_path;
2329 } 2324 }
2330 error = -ENOTDIR; 2325 error = -ENOTDIR;
2331 if (nd.flags & LOOKUP_DIRECTORY) { 2326 if (nd.flags & LOOKUP_DIRECTORY) {
2332 if (!nd.inode->i_op->lookup) 2327 if (!nd.inode->i_op->lookup)
2333 goto out_path2; 2328 goto out_path;
2334 } 2329 }
2335 audit_inode(pathname, nd.path.dentry); 2330 audit_inode(pathname, nd.path.dentry);
2336 filp = finish_open(&nd, op->open_flag, op->acc_mode); 2331 filp = finish_open(&nd, op->open_flag, op->acc_mode);
2337out2:
2338 release_open_intent(&nd); 2332 release_open_intent(&nd);
2339 return filp; 2333 return filp;
2340 2334
2341out_path2:
2342 path_put(&nd.path);
2343out_filp2:
2344 filp = ERR_PTR(error);
2345 goto out2;
2346
2347creat: 2335creat:
2348 /* OK, have to create the file. Find the parent. */ 2336 /* OK, have to create the file. Find the parent. */
2349 error = path_lookupat(dfd, pathname, 2337 error = path_lookupat(dfd, pathname, LOOKUP_PARENT | flags, &nd);
2350 LOOKUP_PARENT | LOOKUP_RCU | flags, &nd);
2351 if (unlikely(error == -ECHILD))
2352 error = path_lookupat(dfd, pathname, LOOKUP_PARENT | flags, &nd);
2353 if (unlikely(error == -ESTALE)) {
2354reval:
2355 flags |= LOOKUP_REVAL;
2356 error = path_lookupat(dfd, pathname, LOOKUP_PARENT | flags, &nd);
2357 }
2358 if (unlikely(error)) 2338 if (unlikely(error))
2359 goto out_filp; 2339 goto out_filp;
2360 if (unlikely(!audit_dummy_context())) 2340 if (unlikely(!audit_dummy_context()))
@@ -2398,8 +2378,6 @@ reval:
2398out: 2378out:
2399 if (nd.root.mnt) 2379 if (nd.root.mnt)
2400 path_put(&nd.root); 2380 path_put(&nd.root);
2401 if (filp == ERR_PTR(-ESTALE) && !(flags & LOOKUP_REVAL))
2402 goto reval;
2403 release_open_intent(&nd); 2381 release_open_intent(&nd);
2404 return filp; 2382 return filp;
2405 2383
@@ -2412,6 +2390,19 @@ out_filp:
2412 goto out; 2390 goto out;
2413} 2391}
2414 2392
2393struct file *do_filp_open(int dfd, const char *pathname,
2394 const struct open_flags *op, int flags)
2395{
2396 struct file *filp;
2397
2398 filp = path_openat(dfd, pathname, op, flags | LOOKUP_RCU);
2399 if (unlikely(filp == ERR_PTR(-ECHILD)))
2400 filp = path_openat(dfd, pathname, op, flags);
2401 if (unlikely(filp == ERR_PTR(-ESTALE)))
2402 filp = path_openat(dfd, pathname, op, flags | LOOKUP_REVAL);
2403 return filp;
2404}
2405
2415/** 2406/**
2416 * lookup_create - lookup a dentry, creating it if it doesn't exist 2407 * lookup_create - lookup a dentry, creating it if it doesn't exist
2417 * @nd: nameidata info 2408 * @nd: nameidata info