aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2012-06-05 09:10:15 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-07-14 08:33:01 -0400
commitd58ffd35c1e595df2cf8ac4803f178c8be95ca7a (patch)
treec0cb0b2201a641521a4d26f702b5b18b15541772
parent7157486541bffc0dfec912e21ae639b029dae3d3 (diff)
vfs: add lookup_open()
Split out lookup + maybe create from do_last(). This is the part under i_mutex protection. The function is called lookup_open() and returns a filp even though the open part is not used yet. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/namei.c99
1 files changed, 61 insertions, 38 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 285e62e925f7..fad7117dbb28 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2197,19 +2197,73 @@ static inline int open_to_namei_flags(int flag)
2197} 2197}
2198 2198
2199/* 2199/*
2200 * Lookup, maybe create and open the last component
2201 *
2202 * Must be called with i_mutex held on parent.
2203 *
2204 * Returns open file or NULL on success, error otherwise. NULL means no open
2205 * was performed, only lookup.
2206 */
2207static struct file *lookup_open(struct nameidata *nd, struct path *path,
2208 const struct open_flags *op,
2209 int *want_write, bool *created)
2210{
2211 struct dentry *dir = nd->path.dentry;
2212 struct dentry *dentry;
2213 int error;
2214
2215 *created = false;
2216 dentry = lookup_hash(nd);
2217 if (IS_ERR(dentry))
2218 return ERR_CAST(dentry);
2219
2220 /* Negative dentry, just create the file */
2221 if (!dentry->d_inode && (op->open_flag & O_CREAT)) {
2222 umode_t mode = op->mode;
2223 if (!IS_POSIXACL(dir->d_inode))
2224 mode &= ~current_umask();
2225 /*
2226 * This write is needed to ensure that a
2227 * rw->ro transition does not occur between
2228 * the time when the file is created and when
2229 * a permanent write count is taken through
2230 * the 'struct file' in nameidata_to_filp().
2231 */
2232 error = mnt_want_write(nd->path.mnt);
2233 if (error)
2234 goto out_dput;
2235 *want_write = 1;
2236 *created = true;
2237 error = security_path_mknod(&nd->path, dentry, mode, 0);
2238 if (error)
2239 goto out_dput;
2240 error = vfs_create(dir->d_inode, dentry, mode, nd);
2241 if (error)
2242 goto out_dput;
2243 }
2244 path->dentry = dentry;
2245 path->mnt = nd->path.mnt;
2246 return NULL;
2247
2248out_dput:
2249 dput(dentry);
2250 return ERR_PTR(error);
2251}
2252
2253/*
2200 * Handle the last step of open() 2254 * Handle the last step of open()
2201 */ 2255 */
2202static struct file *do_last(struct nameidata *nd, struct path *path, 2256static struct file *do_last(struct nameidata *nd, struct path *path,
2203 const struct open_flags *op, const char *pathname) 2257 const struct open_flags *op, const char *pathname)
2204{ 2258{
2205 struct dentry *dir = nd->path.dentry; 2259 struct dentry *dir = nd->path.dentry;
2206 struct dentry *dentry;
2207 int open_flag = op->open_flag; 2260 int open_flag = op->open_flag;
2208 int will_truncate = open_flag & O_TRUNC; 2261 int will_truncate = open_flag & O_TRUNC;
2209 int want_write = 0; 2262 int want_write = 0;
2210 int acc_mode = op->acc_mode; 2263 int acc_mode = op->acc_mode;
2211 struct file *filp; 2264 struct file *filp;
2212 struct inode *inode; 2265 struct inode *inode;
2266 bool created;
2213 int symlink_ok = 0; 2267 int symlink_ok = 0;
2214 struct path save_parent = { .dentry = NULL, .mnt = NULL }; 2268 struct path save_parent = { .dentry = NULL, .mnt = NULL };
2215 bool retried = false; 2269 bool retried = false;
@@ -2277,53 +2331,24 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2277 2331
2278retry_lookup: 2332retry_lookup:
2279 mutex_lock(&dir->d_inode->i_mutex); 2333 mutex_lock(&dir->d_inode->i_mutex);
2334 filp = lookup_open(nd, path, op, &want_write, &created);
2335 mutex_unlock(&dir->d_inode->i_mutex);
2280 2336
2281 dentry = lookup_hash(nd); 2337 if (IS_ERR(filp))
2282 error = PTR_ERR(dentry); 2338 goto out;
2283 if (IS_ERR(dentry)) {
2284 mutex_unlock(&dir->d_inode->i_mutex);
2285 goto exit;
2286 }
2287
2288 path->dentry = dentry;
2289 path->mnt = nd->path.mnt;
2290 2339
2291 /* Negative dentry, just create the file */ 2340 if (created) {
2292 if (!dentry->d_inode && (open_flag & O_CREAT)) {
2293 umode_t mode = op->mode;
2294 if (!IS_POSIXACL(dir->d_inode))
2295 mode &= ~current_umask();
2296 /*
2297 * This write is needed to ensure that a
2298 * rw->ro transition does not occur between
2299 * the time when the file is created and when
2300 * a permanent write count is taken through
2301 * the 'struct file' in nameidata_to_filp().
2302 */
2303 error = mnt_want_write(nd->path.mnt);
2304 if (error)
2305 goto exit_mutex_unlock;
2306 want_write = 1;
2307 /* Don't check for write permission, don't truncate */ 2341 /* Don't check for write permission, don't truncate */
2308 open_flag &= ~O_TRUNC; 2342 open_flag &= ~O_TRUNC;
2309 will_truncate = 0; 2343 will_truncate = 0;
2310 acc_mode = MAY_OPEN; 2344 acc_mode = MAY_OPEN;
2311 error = security_path_mknod(&nd->path, dentry, mode, 0); 2345 path_to_nameidata(path, nd);
2312 if (error)
2313 goto exit_mutex_unlock;
2314 error = vfs_create(dir->d_inode, dentry, mode, nd);
2315 if (error)
2316 goto exit_mutex_unlock;
2317 mutex_unlock(&dir->d_inode->i_mutex);
2318 dput(nd->path.dentry);
2319 nd->path.dentry = dentry;
2320 goto common; 2346 goto common;
2321 } 2347 }
2322 2348
2323 /* 2349 /*
2324 * It already exists. 2350 * It already exists.
2325 */ 2351 */
2326 mutex_unlock(&dir->d_inode->i_mutex);
2327 audit_inode(pathname, path->dentry); 2352 audit_inode(pathname, path->dentry);
2328 2353
2329 error = -EEXIST; 2354 error = -EEXIST;
@@ -2432,8 +2457,6 @@ out:
2432 terminate_walk(nd); 2457 terminate_walk(nd);
2433 return filp; 2458 return filp;
2434 2459
2435exit_mutex_unlock:
2436 mutex_unlock(&dir->d_inode->i_mutex);
2437exit_dput: 2460exit_dput:
2438 path_put_conditional(path, nd); 2461 path_put_conditional(path, nd);
2439exit: 2462exit: