summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--fs/file_table.c8
-rw-r--r--fs/internal.h2
-rw-r--r--fs/namei.c4
-rw-r--r--fs/open.c8
4 files changed, 9 insertions, 13 deletions
diff --git a/fs/file_table.c b/fs/file_table.c
index 76cfa4c43e13..705f486f7007 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -101,7 +101,7 @@ int proc_nr_files(struct ctl_table *table, int write,
  * done, you will imbalance int the mount's writer count
  * and a warning at __fput() time.
  */
-struct file *alloc_empty_file(const struct cred *cred)
+struct file *alloc_empty_file(int flags, const struct cred *cred)
 {
 	static long old_max;
 	struct file *f;
@@ -135,6 +135,8 @@ struct file *alloc_empty_file(const struct cred *cred)
 	spin_lock_init(&f->f_lock);
 	mutex_init(&f->f_pos_lock);
 	eventpoll_init_file(f);
+	f->f_flags = flags;
+	f->f_mode = OPEN_FMODE(flags);
 	/* f->f_version: 0 */
 	percpu_counter_inc(&nr_files);
 	return f;
@@ -160,12 +162,10 @@ struct file *alloc_file(const struct path *path, int flags,
 {
 	struct file *file;
 
-	file = alloc_empty_file(current_cred());
+	file = alloc_empty_file(flags, current_cred());
 	if (IS_ERR(file))
 		return file;
 
-	file->f_mode = OPEN_FMODE(flags);
-	file->f_flags = flags;
 	file->f_path = *path;
 	file->f_inode = path->dentry->d_inode;
 	file->f_mapping = path->dentry->d_inode->i_mapping;
diff --git a/fs/internal.h b/fs/internal.h
index 66473bf388e4..661c314aba30 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -93,7 +93,7 @@ extern void chroot_fs_refs(const struct path *, const struct path *);
 /*
  * file_table.c
  */
-extern struct file *alloc_empty_file(const struct cred *);
+extern struct file *alloc_empty_file(int, const struct cred *);
 
 /*
  * super.c
diff --git a/fs/namei.c b/fs/namei.c
index af2ec1803f57..223925e30adb 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3513,12 +3513,10 @@ static struct file *path_openat(struct nameidata *nd,
 	int opened = 0;
 	int error;
 
-	file = alloc_empty_file(current_cred());
+	file = alloc_empty_file(op->open_flag, current_cred());
 	if (IS_ERR(file))
 		return file;
 
-	file->f_flags = op->open_flag;
-
 	if (unlikely(file->f_flags & __O_TMPFILE)) {
 		error = do_tmpfile(nd, flags, op, file, &opened);
 		goto out2;
diff --git a/fs/open.c b/fs/open.c
index 0061f9ea044d..15d2c3ab91ff 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -742,9 +742,6 @@ static int do_dentry_open(struct file *f,
 	static const struct file_operations empty_fops = {};
 	int error;
 
-	f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK |
-				FMODE_PREAD | FMODE_PWRITE;
-
 	path_get(&f->f_path);
 	f->f_inode = inode;
 	f->f_mapping = inode->i_mapping;
@@ -788,6 +785,8 @@ static int do_dentry_open(struct file *f,
 	if (error)
 		goto cleanup_all;
 
+	/* normally all 3 are set; ->open() can clear them if needed */
+	f->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
 	if (!open)
 		open = f->f_op->open;
 	if (open) {
@@ -921,9 +920,8 @@ struct file *dentry_open(const struct path *path, int flags,
 	/* We must always pass in a valid mount pointer. */
 	BUG_ON(!path->mnt);
 
-	f = alloc_empty_file(cred);
+	f = alloc_empty_file(flags, cred);
 	if (!IS_ERR(f)) {
-		f->f_flags = flags;
 		error = vfs_open(path, f, cred);
 		if (!error) {
 			/* from now on we need fput() to dispose of f */