diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-03-09 00:36:45 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-03-14 09:15:27 -0400 |
commit | ca344a894b41a133dab07dfbbdf652c053f6658c (patch) | |
tree | 2ff61ce7ff0595b3200fa2d9b69e93a87e6c8427 /fs/namei.c | |
parent | 9b44f1b3928b6f41532c9a1dc9a6fc665989ad5b (diff) |
do_last: unify may_open() call and everyting after it
We have a bunch of diverging codepaths in do_last(); some of
them converge, but the case of having to create a new file
duplicates large part of common tail of the rest and exits
separately. Massage them so that they could be merged.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 59 |
1 files changed, 22 insertions, 37 deletions
diff --git a/fs/namei.c b/fs/namei.c index def63e7c058d..63844776484c 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -2114,7 +2114,10 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
2114 | const struct open_flags *op, const char *pathname) | 2114 | const struct open_flags *op, const char *pathname) |
2115 | { | 2115 | { |
2116 | struct dentry *dir = nd->path.dentry; | 2116 | struct dentry *dir = nd->path.dentry; |
2117 | int open_flag = op->open_flag; | ||
2117 | int will_truncate; | 2118 | int will_truncate; |
2119 | int want_write = 0; | ||
2120 | int skip_perm = 0; | ||
2118 | struct file *filp; | 2121 | struct file *filp; |
2119 | struct inode *inode; | 2122 | struct inode *inode; |
2120 | int error; | 2123 | int error; |
@@ -2138,7 +2141,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
2138 | if (error) | 2141 | if (error) |
2139 | goto exit; | 2142 | goto exit; |
2140 | audit_inode(pathname, nd->path.dentry); | 2143 | audit_inode(pathname, nd->path.dentry); |
2141 | if (op->open_flag & O_CREAT) { | 2144 | if (open_flag & O_CREAT) { |
2142 | error = -EISDIR; | 2145 | error = -EISDIR; |
2143 | goto exit; | 2146 | goto exit; |
2144 | } | 2147 | } |
@@ -2152,7 +2155,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
2152 | goto ok; | 2155 | goto ok; |
2153 | } | 2156 | } |
2154 | 2157 | ||
2155 | if (!(op->open_flag & O_CREAT)) { | 2158 | if (!(open_flag & O_CREAT)) { |
2156 | if (nd->last.name[nd->last.len]) | 2159 | if (nd->last.name[nd->last.len]) |
2157 | nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; | 2160 | nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; |
2158 | /* we _can_ be in RCU mode here */ | 2161 | /* we _can_ be in RCU mode here */ |
@@ -2230,28 +2233,15 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
2230 | error = mnt_want_write(nd->path.mnt); | 2233 | error = mnt_want_write(nd->path.mnt); |
2231 | if (error) | 2234 | if (error) |
2232 | goto exit_mutex_unlock; | 2235 | goto exit_mutex_unlock; |
2233 | error = __open_namei_create(nd, path, op->open_flag, op->mode); | 2236 | want_write = 1; |
2234 | if (error) { | 2237 | will_truncate = 0; |
2235 | mnt_drop_write(nd->path.mnt); | 2238 | error = __open_namei_create(nd, path, open_flag, op->mode); |
2239 | if (error) | ||
2236 | goto exit; | 2240 | goto exit; |
2237 | } | ||
2238 | /* Don't check for write permission, don't truncate */ | 2241 | /* Don't check for write permission, don't truncate */ |
2239 | error = may_open(&nd->path, 0, op->open_flag & ~O_TRUNC); | 2242 | open_flag &= ~O_TRUNC; |
2240 | if (error) { | 2243 | skip_perm = 1; |
2241 | mnt_drop_write(nd->path.mnt); | 2244 | goto common; |
2242 | goto exit; | ||
2243 | } | ||
2244 | filp = nameidata_to_filp(nd); | ||
2245 | mnt_drop_write(nd->path.mnt); | ||
2246 | path_put(&nd->path); | ||
2247 | if (!IS_ERR(filp)) { | ||
2248 | error = ima_file_check(filp, op->acc_mode); | ||
2249 | if (error) { | ||
2250 | fput(filp); | ||
2251 | filp = ERR_PTR(error); | ||
2252 | } | ||
2253 | } | ||
2254 | return filp; | ||
2255 | } | 2245 | } |
2256 | 2246 | ||
2257 | /* | 2247 | /* |
@@ -2261,7 +2251,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
2261 | audit_inode(pathname, path->dentry); | 2251 | audit_inode(pathname, path->dentry); |
2262 | 2252 | ||
2263 | error = -EEXIST; | 2253 | error = -EEXIST; |
2264 | if (op->open_flag & O_EXCL) | 2254 | if (open_flag & O_EXCL) |
2265 | goto exit_dput; | 2255 | goto exit_dput; |
2266 | 2256 | ||
2267 | error = follow_managed(path, nd->flags); | 2257 | error = follow_managed(path, nd->flags); |
@@ -2281,18 +2271,17 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
2281 | if (S_ISDIR(nd->inode->i_mode)) | 2271 | if (S_ISDIR(nd->inode->i_mode)) |
2282 | goto exit; | 2272 | goto exit; |
2283 | ok: | 2273 | ok: |
2284 | will_truncate = open_will_truncate(op->open_flag, nd->path.dentry->d_inode); | 2274 | will_truncate = open_will_truncate(open_flag, nd->path.dentry->d_inode); |
2285 | if (will_truncate) { | 2275 | if (will_truncate) { |
2286 | error = mnt_want_write(nd->path.mnt); | 2276 | error = mnt_want_write(nd->path.mnt); |
2287 | if (error) | 2277 | if (error) |
2288 | goto exit; | 2278 | goto exit; |
2279 | want_write = 1; | ||
2289 | } | 2280 | } |
2290 | error = may_open(&nd->path, op->acc_mode, op->open_flag); | 2281 | common: |
2291 | if (error) { | 2282 | error = may_open(&nd->path, skip_perm ? 0 : op->acc_mode, open_flag); |
2292 | if (will_truncate) | 2283 | if (error) |
2293 | mnt_drop_write(nd->path.mnt); | ||
2294 | goto exit; | 2284 | goto exit; |
2295 | } | ||
2296 | filp = nameidata_to_filp(nd); | 2285 | filp = nameidata_to_filp(nd); |
2297 | if (!IS_ERR(filp)) { | 2286 | if (!IS_ERR(filp)) { |
2298 | error = ima_file_check(filp, op->acc_mode); | 2287 | error = ima_file_check(filp, op->acc_mode); |
@@ -2310,12 +2299,8 @@ ok: | |||
2310 | } | 2299 | } |
2311 | } | 2300 | } |
2312 | } | 2301 | } |
2313 | /* | 2302 | out: |
2314 | * It is now safe to drop the mnt write | 2303 | if (want_write) |
2315 | * because the filp has had a write taken | ||
2316 | * on its behalf. | ||
2317 | */ | ||
2318 | if (will_truncate) | ||
2319 | mnt_drop_write(nd->path.mnt); | 2304 | mnt_drop_write(nd->path.mnt); |
2320 | path_put(&nd->path); | 2305 | path_put(&nd->path); |
2321 | return filp; | 2306 | return filp; |
@@ -2325,8 +2310,8 @@ exit_mutex_unlock: | |||
2325 | exit_dput: | 2310 | exit_dput: |
2326 | path_put_conditional(path, nd); | 2311 | path_put_conditional(path, nd); |
2327 | exit: | 2312 | exit: |
2328 | path_put(&nd->path); | 2313 | filp = ERR_PTR(error); |
2329 | return ERR_PTR(error); | 2314 | goto out; |
2330 | } | 2315 | } |
2331 | 2316 | ||
2332 | static struct file *path_openat(int dfd, const char *pathname, | 2317 | static struct file *path_openat(int dfd, const char *pathname, |