diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-02-23 17:54:08 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-03-14 09:15:25 -0400 |
commit | 13aab428a73d3200b9283b61b7fdf5713181ac66 (patch) | |
tree | b7350283378b60366609dca7b02c412b4632879e /fs/namei.c | |
parent | 47c805dc2d2dff686962f5f0baa6bac2d703ba19 (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>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 49 |
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 | /* | 2295 | static 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 | */ | ||
2300 | struct 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); |
2337 | out2: | ||
2338 | release_open_intent(&nd); | 2332 | release_open_intent(&nd); |
2339 | return filp; | 2333 | return filp; |
2340 | 2334 | ||
2341 | out_path2: | ||
2342 | path_put(&nd.path); | ||
2343 | out_filp2: | ||
2344 | filp = ERR_PTR(error); | ||
2345 | goto out2; | ||
2346 | |||
2347 | creat: | 2335 | creat: |
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)) { | ||
2354 | reval: | ||
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: | |||
2398 | out: | 2378 | out: |
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 | ||
2393 | struct 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 |