diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-09-17 01:22:33 +0200 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-09-17 23:08:50 +0200 |
commit | 03da633aa7b08bdc4d86e9c2780bb89277b65cd6 (patch) | |
tree | f663ce0d2f49867c6b4f9b0631976a9e7ea9556a /fs/namei.c | |
parent | vfs: don't set FILE_CREATED before calling ->atomic_open() (diff) | |
download | linux-03da633aa7b08bdc4d86e9c2780bb89277b65cd6.tar.xz linux-03da633aa7b08bdc4d86e9c2780bb89277b65cd6.zip |
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>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 33 |
1 files changed, 19 insertions, 14 deletions
diff --git a/fs/namei.c b/fs/namei.c index 22eb5484774c..645268f23eb6 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2725,16 +2725,6 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, 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 (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) { error = -EIO; @@ -2744,10 +2734,19 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, dput(dentry); dentry = file->f_path.dentry; } - WARN_ON(!dentry->d_inode && (*opened & FILE_CREATED)); - 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; } @@ -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 * 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); |