atomic_open: take care of EEXIST in no-open case with O_CREAT|O_EXCL in fs/namei.c

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2013-09-16 19:22:33 -04:00
parent 116cc02253
commit 03da633aa7
2 changed files with 20 additions and 21 deletions

View File

@ -267,14 +267,8 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
} }
/* Only creates */ /* Only creates */
if (!(flags & O_CREAT)) if (!(flags & O_CREAT) || dentry->d_inode)
return finish_no_open(file, res); return finish_no_open(file, res);
else if (dentry->d_inode) {
if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
return -EEXIST;
else
return finish_no_open(file, res);
}
v9ses = v9fs_inode2v9ses(dir); v9ses = v9fs_inode2v9ses(dir);

View File

@ -2725,16 +2725,6 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
goto out; goto out;
} }
acc_mode = op->acc_mode;
if (WARN_ON(excl && !(*opened & FILE_CREATED)))
*opened |= FILE_CREATED;
if (*opened & FILE_CREATED) {
WARN_ON(!(open_flag & O_CREAT));
fsnotify_create(dir, dentry);
acc_mode = MAY_OPEN;
}
if (error) { /* returned 1, that is */ if (error) { /* returned 1, that is */
if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) { if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) {
error = -EIO; error = -EIO;
@ -2744,10 +2734,19 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
dput(dentry); dput(dentry);
dentry = file->f_path.dentry; dentry = file->f_path.dentry;
} }
WARN_ON(!dentry->d_inode && (*opened & FILE_CREATED)); if (*opened & FILE_CREATED)
if (create_error && dentry->d_inode == NULL) { fsnotify_create(dir, dentry);
error = create_error; if (!dentry->d_inode) {
goto out; WARN_ON(*opened & FILE_CREATED);
if (create_error) {
error = create_error;
goto out;
}
} else {
if (excl && !(*opened & FILE_CREATED)) {
error = -EEXIST;
goto out;
}
} }
goto looked_up; goto looked_up;
} }
@ -2756,6 +2755,12 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
* We didn't have the inode before the open, so check open permission * We didn't have the inode before the open, so check open permission
* here. * here.
*/ */
acc_mode = op->acc_mode;
if (*opened & FILE_CREATED) {
WARN_ON(!(open_flag & O_CREAT));
fsnotify_create(dir, dentry);
acc_mode = MAY_OPEN;
}
error = may_open(&file->f_path, acc_mode, open_flag); error = may_open(&file->f_path, acc_mode, open_flag);
if (error) if (error)
fput(file); fput(file);