|
@@ -2656,6 +2656,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
|
|
|
int acc_mode;
|
|
|
int create_error = 0;
|
|
|
struct dentry *const DENTRY_NOT_SET = (void *) -1UL;
|
|
|
+ bool excl;
|
|
|
|
|
|
BUG_ON(dentry->d_inode);
|
|
|
|
|
@@ -2669,10 +2670,9 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
|
|
|
if ((open_flag & O_CREAT) && !IS_POSIXACL(dir))
|
|
|
mode &= ~current_umask();
|
|
|
|
|
|
- if ((open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT)) {
|
|
|
+ excl = (open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT);
|
|
|
+ if (excl)
|
|
|
open_flag &= ~O_TRUNC;
|
|
|
- *opened |= FILE_CREATED;
|
|
|
- }
|
|
|
|
|
|
/*
|
|
|
* Checking write permission is tricky, bacuse we don't know if we are
|
|
@@ -2725,12 +2725,6 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- acc_mode = op->acc_mode;
|
|
|
- if (*opened & FILE_CREATED) {
|
|
|
- fsnotify_create(dir, dentry);
|
|
|
- acc_mode = MAY_OPEN;
|
|
|
- }
|
|
|
-
|
|
|
if (error) { /* returned 1, that is */
|
|
|
if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) {
|
|
|
error = -EIO;
|
|
@@ -2740,9 +2734,19 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
|
|
|
dput(dentry);
|
|
|
dentry = file->f_path.dentry;
|
|
|
}
|
|
|
- if (create_error && dentry->d_inode == NULL) {
|
|
|
- error = create_error;
|
|
|
- goto out;
|
|
|
+ if (*opened & FILE_CREATED)
|
|
|
+ fsnotify_create(dir, dentry);
|
|
|
+ if (!dentry->d_inode) {
|
|
|
+ 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;
|
|
|
}
|
|
@@ -2751,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
|
|
|
* 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);
|
|
|
if (error)
|
|
|
fput(file);
|