linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC][PATCHES] open()-related cleanups
@ 2018-07-09  4:53 Al Viro
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
  0 siblings, 1 reply; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:53 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel, linux-fsdevel

	This is an update of open()-related work last posted a month
ago.  Series lives in vfs.git#work.open (and its beginning is in
#fixes).  Individual patches are in followups, shortlog (with outlines)
follows:
1) some prep fixes:
	* drm_lease.c uses alloc_file() for no good reason - it's
open-coding filp_clone_open() and gets failure handling wrong; failing
->open() should *not* be followed by fput().  Use the real thing instead.
	* cxl_getfile() also buggers failure exits around alloc_file() -
it follows path_put() with iput(), resulting in double iput()
	* ocxlflash_getfile(): same story.

      drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open()
      cxl_getfile(): fix double-iput() on alloc_file() failures
      ocxlflash_getfile(): fix double-iput() on alloc_file() failures

2) We want saner rules for put_filp()/fput() logics.  At some point in
struct file lifecycle it switches from 'clean the things up manually and
do put_filp()' to 'just use fput() from now on'.  Choosing the right one
during the open (especially when ->atomic_open() is involved) is painful
and convoluted.  Things become much simpler if we use struct file itself
to carry that information.
	* make it provable that do_dentry_open() is never called on the
same struct file twice.  That's certainly what we intended all along;
the problems could happen if bogus ->open() returned *positive* for an
error.  That could confuse the living hell out of atomic_open() and friends;
make sure it won't happen.
	* mark the 'should we just use fput() from now on' in ->f_mode.
	* don't pass 'opened' to ->atomic_open()/finish_open(); make the
(very few) callers pick the information we would've passed via
*opened & FILE_OPENED from file->f_mode & FMODE_OPENED instead.
	* massage path_openat() and the helpers it calls, consolidate all
fput()-causing failure handling into path_openat() itself and switch all
checks to FMODE_OPENED.

      make sure do_dentry_open() won't return positive as an error
      introduce FMODE_OPENED
      get rid of 'opened' argument of finish_open()
      lift fput() on late failures into path_openat()
      switch all remaining checks for FILE_OPENED to FMODE_OPENED

3) first payoff: now we can fold open_check_o_direct() into do_dentry_open().
The problem with doing that had been exactly in fput()/put_filp() rules -
we relied upon "failures without do_dentry_open() ever called => put_filp(),
failure after do_dentry_open() succeeded => fput(), failure in do_dentry_open()
itself => put_filp()" (and heaven help us to keep track which case had it
been).  O_DIRECT checks are done past the point where we need fput() and
doing those in do_dentry_open() would've made for "failure in do_dentry_open()
means put_filp(), except when it's a late failure, in which case we want
fput()", without any way for caller of do_dentry_open() to tell which one
it is.  With FMODE_OPENED we *can* tell.

      now we can fold open_check_o_direct() into do_dentry_open()

4) ->atomic_open() and friends are passing two bits of state ("did we get past
opening it" and "did we create it") in a very ugly way - pointer to int
('opened') is passed as an argument, and the variable it points to is used
to store those two bits.  We are not far from getting rid of it for good -
one bit (FILE_OPENED) is already replaced with ->f_mode & FMODE_OPENED and 
and we can use ->f_mode to get rid of FILE_CREATED as well.
	* introduce FMODE_CREATED, set it to parallel *opened & FILE_CREATED
	* get rid of FILE_CREATED in checks
	* get rid of now unused 'opened' in ->atomic_open() and its callers
	* kill now unused FILE_{OPENED,CREATED}

      introduce FMODE_CREATED and switch to it
      IMA: don't propagate opened through the entire thing
      Preparation to killing ->atomic_open() 'opened' argument.
      get rid of 'opened' argument of ->atomic_open()
      get rid of 'opened' in path_openat() and the helpers downstream
      kill FILE_{CREATED,OPENED}

5) sort alloc_file() callers out.  Calling conventions, especially wrt cleanups
on failure, are convoluted (and easy to get wrong).  Callers fall into two
classes and we'd be better off with a couple of wrappers suited for those.
	* introduce alloc_file_pseudo(), convert to its use
	* introduce alloc_file_clone(), convert to its use
	* make alloc_file() itself static

      new wrapper: alloc_file_pseudo()
      __shmem_file_setup(): reorder allocations
      ... and switch shmem_file_setup() to alloc_file_pseudo()
      cxl_getfile(): switch to alloc_file_pseudo()
      ocxlflash_getfile(): switch to alloc_file_pseudo()
      hugetlb_file_setup(): switch to alloc_file_pseudo()
      anon_inode_getfile(): switch to alloc_file_pseudo()
      create_pipe_files(): switch the first allocation to alloc_file_pseudo()
      new helper: alloc_file_clone()
      do_shmat(): grab shp->shm_file earlier, switch to alloc_file_clone()
      make alloc_file() static

6) turn filp_clone_open() into a wrapper for dentry_open(), rename it to
file_clone_open().

      turn filp_clone_open() into inline wrapper for dentry_open()

Diffstat:
 arch/ia64/kernel/perfmon.c            |  1 +
 drivers/gpu/drm/drm_lease.c           | 16 +------
 drivers/misc/cxl/api.c                | 21 ++-------
 drivers/scsi/cxlflash/ocxl_hw.c       | 24 ++--------
 fs/9p/vfs_inode.c                     |  7 ++-
 fs/9p/vfs_inode_dotl.c                |  7 ++-
 fs/aio.c                              | 26 +++--------
 fs/anon_inodes.c                      | 29 +++----------
 fs/bad_inode.c                        |  2 +-
 fs/binfmt_misc.c                      |  2 +-
 fs/ceph/file.c                        |  7 ++-
 fs/ceph/super.h                       |  3 +-
 fs/cifs/cifsfs.h                      |  3 +-
 fs/cifs/dir.c                         |  7 ++-
 fs/file_table.c                       | 41 +++++++++++++++++-
 fs/fuse/dir.c                         | 10 ++---
 fs/gfs2/inode.c                       | 32 +++++++-------
 fs/hugetlbfs/inode.c                  | 55 ++++++++---------------
 fs/internal.h                         |  2 -
 fs/namei.c                            | 82 ++++++++++++++---------------------
 fs/nfs/dir.c                          | 14 +++---
 fs/nfs/nfs4_fs.h                      |  2 +-
 fs/nfs/nfs4proc.c                     |  2 +-
 fs/nfsd/vfs.c                         |  2 +-
 fs/open.c                             | 68 ++++++++---------------------
 fs/pipe.c                             | 38 ++++------------
 include/linux/file.h                  |  7 ++-
 include/linux/fs.h                    | 17 +++++---
 include/linux/ima.h                   |  4 +-
 ipc/shm.c                             | 39 ++++++++---------
 mm/shmem.c                            | 50 +++++----------------
 net/socket.c                          | 27 ++----------
 security/integrity/ima/ima.h          |  4 +-
 security/integrity/ima/ima_appraise.c |  4 +-
 security/integrity/ima/ima_main.c     | 16 +++----
 35 files changed, 247 insertions(+), 423 deletions(-)

Please, review:

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open()
  2018-07-09  4:53 [RFC][PATCHES] open()-related cleanups Al Viro
@ 2018-07-09  4:53 ` Al Viro
  2018-07-09  4:53   ` [RFC][PATCH 02/27] cxl_getfile(): fix double-iput() on alloc_file() failures Al Viro
                     ` (25 more replies)
  0 siblings, 26 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:53 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

Failure of ->open() should *not* be followed by fput().  Fixed by
using filp_clone_open(), which gets the cleanups right.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 drivers/gpu/drm/drm_lease.c | 16 +---------------
 fs/internal.h               |  1 -
 include/linux/fs.h          |  1 +
 3 files changed, 2 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
index 50c73c0a20b9..d638c0fb3418 100644
--- a/drivers/gpu/drm/drm_lease.c
+++ b/drivers/gpu/drm/drm_lease.c
@@ -553,24 +553,13 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
 
 	/* Clone the lessor file to create a new file for us */
 	DRM_DEBUG_LEASE("Allocating lease file\n");
-	path_get(&lessor_file->f_path);
-	lessee_file = alloc_file(&lessor_file->f_path,
-				 lessor_file->f_mode,
-				 fops_get(lessor_file->f_inode->i_fop));
-
+	lessee_file = filp_clone_open(lessor_file);
 	if (IS_ERR(lessee_file)) {
 		ret = PTR_ERR(lessee_file);
 		goto out_lessee;
 	}
 
-	/* Initialize the new file for DRM */
-	DRM_DEBUG_LEASE("Initializing the file with %p\n", lessee_file->f_op->open);
-	ret = lessee_file->f_op->open(lessee_file->f_inode, lessee_file);
-	if (ret)
-		goto out_lessee_file;
-
 	lessee_priv = lessee_file->private_data;
-
 	/* Change the file to a master one */
 	drm_master_put(&lessee_priv->master);
 	lessee_priv->master = lessee;
@@ -588,9 +577,6 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
 	DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl succeeded\n");
 	return 0;
 
-out_lessee_file:
-	fput(lessee_file);
-
 out_lessee:
 	drm_master_put(&lessee);
 
diff --git a/fs/internal.h b/fs/internal.h
index 980d005b21b4..5645b4ebf494 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -127,7 +127,6 @@ int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group,
 
 extern int open_check_o_direct(struct file *f);
 extern int vfs_open(const struct path *, struct file *, const struct cred *);
-extern struct file *filp_clone_open(struct file *);
 
 /*
  * inode.c
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 5c91108846db..aa9b4c169ed2 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2422,6 +2422,7 @@ extern struct file *filp_open(const char *, int, umode_t);
 extern struct file *file_open_root(struct dentry *, struct vfsmount *,
 				   const char *, int, umode_t);
 extern struct file * dentry_open(const struct path *, int, const struct cred *);
+extern struct file *filp_clone_open(struct file *);
 extern int filp_close(struct file *, fl_owner_t id);
 
 extern struct filename *getname_flags(const char __user *, int, int *);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 02/27] cxl_getfile(): fix double-iput() on alloc_file() failures
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
@ 2018-07-09  4:53   ` Al Viro
  2018-07-09  4:53   ` [RFC][PATCH 03/27] ocxlflash_getfile(): " Al Viro
                     ` (24 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:53 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel, stable

From: Al Viro <viro@zeniv.linux.org.uk>

Doing iput() after path_put() is wrong.

Cc: stable@kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 drivers/misc/cxl/api.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c
index 753b1a698fc4..6b16946f9b05 100644
--- a/drivers/misc/cxl/api.c
+++ b/drivers/misc/cxl/api.c
@@ -103,15 +103,15 @@ static struct file *cxl_getfile(const char *name,
 	d_instantiate(path.dentry, inode);
 
 	file = alloc_file(&path, OPEN_FMODE(flags), fops);
-	if (IS_ERR(file))
-		goto err_dput;
+	if (IS_ERR(file)) {
+		path_put(&path);
+		goto err_fs;
+	}
 	file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
 	file->private_data = priv;
 
 	return file;
 
-err_dput:
-	path_put(&path);
 err_inode:
 	iput(inode);
 err_fs:
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 03/27] ocxlflash_getfile(): fix double-iput() on alloc_file() failures
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
  2018-07-09  4:53   ` [RFC][PATCH 02/27] cxl_getfile(): fix double-iput() on alloc_file() failures Al Viro
@ 2018-07-09  4:53   ` Al Viro
  2018-07-09  4:53   ` [RFC][PATCH 04/27] make sure do_dentry_open() won't return positive as an error Al Viro
                     ` (23 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:53 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel, stable

From: Al Viro <viro@zeniv.linux.org.uk>

Cc: stable@kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 drivers/scsi/cxlflash/ocxl_hw.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 0a95b5f25380..497a68389461 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -134,15 +134,14 @@ static struct file *ocxlflash_getfile(struct device *dev, const char *name,
 		rc = PTR_ERR(file);
 		dev_err(dev, "%s: alloc_file failed rc=%d\n",
 			__func__, rc);
-		goto err5;
+		path_put(&path);
+		goto err3;
 	}
 
 	file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
 	file->private_data = priv;
 out:
 	return file;
-err5:
-	path_put(&path);
 err4:
 	iput(inode);
 err3:
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 04/27] make sure do_dentry_open() won't return positive as an error
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
  2018-07-09  4:53   ` [RFC][PATCH 02/27] cxl_getfile(): fix double-iput() on alloc_file() failures Al Viro
  2018-07-09  4:53   ` [RFC][PATCH 03/27] ocxlflash_getfile(): " Al Viro
@ 2018-07-09  4:53   ` Al Viro
  2018-07-09  4:53   ` [RFC][PATCH 05/27] introduce FMODE_OPENED Al Viro
                     ` (22 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:53 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

An ->open() instances really, really should not be doing that.  There's
a lot of places e.g. around atomic_open() that could be confused by that,
so let's catch that early.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/open.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/fs/open.c b/fs/open.c
index d0e955b558ad..40658ef912d2 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -812,6 +812,10 @@ static int do_dentry_open(struct file *f,
 	return 0;
 
 cleanup_all:
+	if (unlikely(error > 0)) {
+		WARN_ON(1);
+		error = -EINVAL;
+	}
 	fops_put(f->f_op);
 	if (f->f_mode & FMODE_WRITER) {
 		put_write_access(inode);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 05/27] introduce FMODE_OPENED
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (2 preceding siblings ...)
  2018-07-09  4:53   ` [RFC][PATCH 04/27] make sure do_dentry_open() won't return positive as an error Al Viro
@ 2018-07-09  4:53   ` Al Viro
  2018-07-09  4:53   ` [RFC][PATCH 06/27] get rid of 'opened' argument of finish_open() Al Viro
                     ` (21 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:53 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

basically, "is that instance set up enough for regular fput(), or
do we want put_filp() for that one".

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 arch/ia64/kernel/perfmon.c | 1 +
 drivers/misc/cxl/api.c     | 2 +-
 fs/aio.c                   | 3 ++-
 fs/anon_inodes.c           | 2 +-
 fs/hugetlbfs/inode.c       | 2 +-
 fs/open.c                  | 3 ++-
 fs/pipe.c                  | 2 ++
 include/linux/fs.h         | 3 +++
 ipc/shm.c                  | 2 +-
 mm/shmem.c                 | 2 +-
 net/socket.c               | 2 +-
 11 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 3b38c717008a..017c568bb8a4 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -2684,6 +2684,7 @@ pfm_context_create(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
 	 * initialize soft PMU state
 	 */
 	pfm_reset_pmu_state(ctx);
+	filp->f_mode |= FMODE_OPENED;
 
 	fd_install(fd, filp);
 
diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c
index 6b16946f9b05..146a12fe6cb8 100644
--- a/drivers/misc/cxl/api.c
+++ b/drivers/misc/cxl/api.c
@@ -102,7 +102,7 @@ static struct file *cxl_getfile(const char *name,
 	path.mnt = mntget(cxl_vfs_mount);
 	d_instantiate(path.dentry, inode);
 
-	file = alloc_file(&path, OPEN_FMODE(flags), fops);
+	file = alloc_file(&path, OPEN_FMODE(flags) | FMODE_OPENED, fops);
 	if (IS_ERR(file)) {
 		path_put(&path);
 		goto err_fs;
diff --git a/fs/aio.c b/fs/aio.c
index e1d20124ec0e..4d63e8e4d1b5 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -234,7 +234,8 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages)
 	path.mnt = mntget(aio_mnt);
 
 	d_instantiate(path.dentry, inode);
-	file = alloc_file(&path, FMODE_READ | FMODE_WRITE, &aio_ring_fops);
+	file = alloc_file(&path, FMODE_READ | FMODE_WRITE | FMODE_OPENED,
+			  &aio_ring_fops);
 	if (IS_ERR(file)) {
 		path_put(&path);
 		return file;
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 3168ee4e77f4..bf952939a1d3 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -102,7 +102,7 @@ struct file *anon_inode_getfile(const char *name,
 
 	d_instantiate(path.dentry, anon_inode_inode);
 
-	file = alloc_file(&path, OPEN_FMODE(flags), fops);
+	file = alloc_file(&path, OPEN_FMODE(flags) | FMODE_OPENED, fops);
 	if (IS_ERR(file))
 		goto err_dput;
 	file->f_mapping = anon_inode_inode->i_mapping;
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index d508c7844681..e0b8cc89169c 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -1375,7 +1375,7 @@ struct file *hugetlb_file_setup(const char *name, size_t size,
 	inode->i_size = size;
 	clear_nlink(inode);
 
-	file = alloc_file(&path, FMODE_WRITE | FMODE_READ,
+	file = alloc_file(&path, FMODE_WRITE | FMODE_READ | FMODE_OPENED,
 			&hugetlbfs_file_operations);
 	if (IS_ERR(file))
 		goto out_dentry; /* inode is already attached */
diff --git a/fs/open.c b/fs/open.c
index 40658ef912d2..aec2686130b1 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -753,7 +753,7 @@ static int do_dentry_open(struct file *f,
 	f->f_wb_err = filemap_sample_wb_err(f->f_mapping);
 
 	if (unlikely(f->f_flags & O_PATH)) {
-		f->f_mode = FMODE_PATH;
+		f->f_mode = FMODE_PATH | FMODE_OPENED;
 		f->f_op = &empty_fops;
 		return 0;
 	}
@@ -795,6 +795,7 @@ static int do_dentry_open(struct file *f,
 		if (error)
 			goto cleanup_all;
 	}
+	f->f_mode |= FMODE_OPENED;
 	if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
 		i_readcount_inc(inode);
 	if ((f->f_mode & FMODE_READ) &&
diff --git a/fs/pipe.c b/fs/pipe.c
index bb0840e234f3..4d62c935f675 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -775,6 +775,8 @@ int create_pipe_files(struct file **res, int flags)
 		goto err_file;
 	}
 
+	res[0]->f_mode |= FMODE_OPENED;
+	f->f_mode |= FMODE_OPENED;
 	path_get(&path);
 	res[0]->private_data = inode->i_pipe;
 	res[0]->f_flags = O_RDONLY | (flags & O_NONBLOCK);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index aa9b4c169ed2..d1ce90634d8b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -148,12 +148,15 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 /* Has write method(s) */
 #define FMODE_CAN_WRITE         ((__force fmode_t)0x40000)
 
+#define FMODE_OPENED		((__force fmode_t)0x80000)
+
 /* File was opened by fanotify and shouldn't generate fanotify events */
 #define FMODE_NONOTIFY		((__force fmode_t)0x4000000)
 
 /* File is capable of returning -EAGAIN if I/O will block */
 #define FMODE_NOWAIT	((__force fmode_t)0x8000000)
 
+
 /*
  * Flag for rw_copy_check_uvector and compat_rw_copy_check_uvector
  * that indicates that they should check the contents of the iovec are
diff --git a/ipc/shm.c b/ipc/shm.c
index 051a3e1fb8df..e37931121070 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -1449,7 +1449,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
 		goto out_nattch;
 	}
 
-	file = alloc_file(&path, f_mode,
+	file = alloc_file(&path, f_mode | FMODE_OPENED,
 			  is_file_hugepages(shp->shm_file) ?
 				&shm_file_operations_huge :
 				&shm_file_operations);
diff --git a/mm/shmem.c b/mm/shmem.c
index 2cab84403055..a76adc3802d1 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -3942,7 +3942,7 @@ static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, l
 	if (IS_ERR(res))
 		goto put_path;
 
-	res = alloc_file(&path, FMODE_WRITE | FMODE_READ,
+	res = alloc_file(&path, FMODE_WRITE | FMODE_READ | FMODE_OPENED,
 		  &shmem_file_operations);
 	if (IS_ERR(res))
 		goto put_path;
diff --git a/net/socket.c b/net/socket.c
index 8a109012608a..eff9db5fd99f 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -411,7 +411,7 @@ struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
 
 	d_instantiate(path.dentry, SOCK_INODE(sock));
 
-	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
+	file = alloc_file(&path, FMODE_READ | FMODE_WRITE | FMODE_OPENED,
 		  &socket_file_ops);
 	if (IS_ERR(file)) {
 		/* drop dentry, keep inode for a bit */
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 06/27] get rid of 'opened' argument of finish_open()
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (3 preceding siblings ...)
  2018-07-09  4:53   ` [RFC][PATCH 05/27] introduce FMODE_OPENED Al Viro
@ 2018-07-09  4:53   ` Al Viro
  2018-07-09  4:53   ` [RFC][PATCH 07/27] lift fput() on late failures into path_openat() Al Viro
                     ` (20 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:53 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

We only deal with opened & FILE_OPENED in it and it's parallel to
file->f_mode & FMODE_OPENED.  So let the callers deal with the latter
instead.  Most of the call chains go through fs/namei.c:atomic_open()
and do not look at FILE_OPENED between the return from finish_open()
and return to atomic_open(), which reduces the size of patch nicely -
we propagate to *opened in atomic_open() and that leaves us with
do_tmpfile() (where we do the same) and gfs2_atomic_open() (where we
check ->f_mode instead of *opened).

Signed-off-by Al Viro <viro@zeniv.linux.org.uk>
---
 fs/9p/vfs_inode.c      |  2 +-
 fs/9p/vfs_inode_dotl.c |  2 +-
 fs/ceph/file.c         |  2 +-
 fs/cifs/dir.c          |  2 +-
 fs/fuse/dir.c          |  2 +-
 fs/gfs2/inode.c        |  8 ++++----
 fs/namei.c             |  6 +++++-
 fs/nfs/dir.c           |  2 +-
 fs/open.c              | 12 +++---------
 include/linux/fs.h     |  3 +--
 10 files changed, 19 insertions(+), 22 deletions(-)

diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 42e102e2e74a..73dd18e44e5c 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -917,7 +917,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
 		v9inode->writeback_fid = (void *) inode_fid;
 	}
 	mutex_unlock(&v9inode->v_mutex);
-	err = finish_open(file, dentry, generic_file_open, opened);
+	err = finish_open(file, dentry, generic_file_open);
 	if (err)
 		goto error;
 
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 7f6ae21a27b3..0b79872848c1 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -352,7 +352,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	}
 	mutex_unlock(&v9inode->v_mutex);
 	/* Since we are opening a file, assign the open fid to the file */
-	err = finish_open(file, dentry, generic_file_open, opened);
+	err = finish_open(file, dentry, generic_file_open);
 	if (err)
 		goto err_clunk_old_fid;
 	file->private_data = ofid;
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index ad0bed99b1d5..47afcec3792a 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -509,7 +509,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
 			ceph_init_inode_acls(d_inode(dentry), &acls);
 			*opened |= FILE_CREATED;
 		}
-		err = finish_open(file, dentry, ceph_open, opened);
+		err = finish_open(file, dentry, ceph_open);
 	}
 out_req:
 	if (!req->r_err && req->r_target_inode)
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index ddae52bd1993..fa5b642bc492 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -541,7 +541,7 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
 	if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
 		*opened |= FILE_CREATED;
 
-	rc = finish_open(file, direntry, generic_file_open, opened);
+	rc = finish_open(file, direntry, generic_file_open);
 	if (rc) {
 		if (server->ops->close)
 			server->ops->close(xid, tcon, &fid);
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 56231b31f806..657b4be22d65 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -469,7 +469,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
 	d_instantiate(entry, inode);
 	fuse_change_entry_timeout(entry, &outentry);
 	fuse_invalidate_attr(dir);
-	err = finish_open(file, entry, generic_file_open, opened);
+	err = finish_open(file, entry, generic_file_open);
 	if (err) {
 		fuse_sync_release(ff, flags);
 	} else {
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index feda55f67050..7604844c28a6 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -626,7 +626,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 		error = 0;
 		if (file) {
 			if (S_ISREG(inode->i_mode))
-				error = finish_open(file, dentry, gfs2_open_common, opened);
+				error = finish_open(file, dentry, gfs2_open_common);
 			else
 				error = finish_no_open(file, NULL);
 		}
@@ -768,7 +768,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 	d_instantiate(dentry, inode);
 	if (file) {
 		*opened |= FILE_CREATED;
-		error = finish_open(file, dentry, gfs2_open_common, opened);
+		error = finish_open(file, dentry, gfs2_open_common);
 	}
 	gfs2_glock_dq_uninit(ghs);
 	gfs2_glock_dq_uninit(ghs + 1);
@@ -866,7 +866,7 @@ static struct dentry *__gfs2_lookup(struct inode *dir, struct dentry *dentry,
 		return d;
 	}
 	if (file && S_ISREG(inode->i_mode))
-		error = finish_open(file, dentry, gfs2_open_common, opened);
+		error = finish_open(file, dentry, gfs2_open_common);
 
 	gfs2_glock_dq_uninit(&gh);
 	if (error) {
@@ -1250,7 +1250,7 @@ static int gfs2_atomic_open(struct inode *dir, struct dentry *dentry,
 	if (d != NULL)
 		dentry = d;
 	if (d_really_is_positive(dentry)) {
-		if (!(*opened & FILE_OPENED))
+		if (!(file->f_mode & FMODE_OPENED))
 			return finish_no_open(file, d);
 		dput(d);
 		return 0;
diff --git a/fs/namei.c b/fs/namei.c
index 734cef54fdf8..a58e00076ba1 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3061,6 +3061,8 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
 		 * permission here.
 		 */
 		int acc_mode = op->acc_mode;
+		if (file->f_mode & FMODE_OPENED)
+			*opened |= FILE_OPENED;
 		if (*opened & FILE_CREATED) {
 			WARN_ON(!(open_flag & O_CREAT));
 			fsnotify_create(dir, dentry);
@@ -3480,9 +3482,11 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags,
 	if (error)
 		goto out2;
 	file->f_path.mnt = path.mnt;
-	error = finish_open(file, child, NULL, opened);
+	error = finish_open(file, child, NULL);
 	if (error)
 		goto out2;
+	if (file->f_mode & FMODE_OPENED)
+		*opened |= FILE_OPENED;
 	error = open_check_o_direct(file);
 	if (error)
 		fput(file);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 7a9c14426855..076c4b855cf9 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1439,7 +1439,7 @@ static int nfs_finish_open(struct nfs_open_context *ctx,
 {
 	int err;
 
-	err = finish_open(file, dentry, do_open, opened);
+	err = finish_open(file, dentry, do_open);
 	if (err)
 		goto out;
 	if (S_ISREG(file->f_path.dentry->d_inode->i_mode))
diff --git a/fs/open.c b/fs/open.c
index aec2686130b1..6405f079264d 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -852,19 +852,13 @@ static int do_dentry_open(struct file *f,
  * Returns zero on success or -errno if the open failed.
  */
 int finish_open(struct file *file, struct dentry *dentry,
-		int (*open)(struct inode *, struct file *),
-		int *opened)
+		int (*open)(struct inode *, struct file *))
 {
-	int error;
-	BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
+	BUG_ON(file->f_mode & FMODE_OPENED); /* once it's opened, it's opened */
 
 	file->f_path.dentry = dentry;
-	error = do_dentry_open(file, d_backing_inode(dentry), open,
+	return do_dentry_open(file, d_backing_inode(dentry), open,
 			       current_cred());
-	if (!error)
-		*opened |= FILE_OPENED;
-
-	return error;
 }
 EXPORT_SYMBOL(finish_open);
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index d1ce90634d8b..a9664953be9f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2438,8 +2438,7 @@ enum {
 	FILE_OPENED = 2
 };
 extern int finish_open(struct file *file, struct dentry *dentry,
-			int (*open)(struct inode *, struct file *),
-			int *opened);
+			int (*open)(struct inode *, struct file *));
 extern int finish_no_open(struct file *file, struct dentry *dentry);
 
 /* fs/ioctl.c */
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 07/27] lift fput() on late failures into path_openat()
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (4 preceding siblings ...)
  2018-07-09  4:53   ` [RFC][PATCH 06/27] get rid of 'opened' argument of finish_open() Al Viro
@ 2018-07-09  4:53   ` Al Viro
  2018-07-09  4:53   ` [RFC][PATCH 08/27] switch all remaining checks for FILE_OPENED to FMODE_OPENED Al Viro
                     ` (19 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:53 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/namei.c | 31 +++++++++++++++----------------
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index a58e00076ba1..36c2fa804e26 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3409,8 +3409,6 @@ static int do_last(struct nameidata *nd,
 	if (!error && will_truncate)
 		error = handle_truncate(file);
 out:
-	if (unlikely(error) && (*opened & FILE_OPENED))
-		fput(file);
 	if (unlikely(error > 0)) {
 		WARN_ON(1);
 		error = -EINVAL;
@@ -3488,8 +3486,6 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags,
 	if (file->f_mode & FMODE_OPENED)
 		*opened |= FILE_OPENED;
 	error = open_check_o_direct(file);
-	if (error)
-		fput(file);
 out2:
 	mnt_drop_write(path.mnt);
 out:
@@ -3551,20 +3547,23 @@ static struct file *path_openat(struct nameidata *nd,
 	}
 	terminate_walk(nd);
 out2:
-	if (!(opened & FILE_OPENED)) {
-		BUG_ON(!error);
-		put_filp(file);
+	if (likely(!error)) {
+		if (likely(opened & FILE_OPENED))
+			return file;
+		WARN_ON(1);
+		error = -EINVAL;
 	}
-	if (unlikely(error)) {
-		if (error == -EOPENSTALE) {
-			if (flags & LOOKUP_RCU)
-				error = -ECHILD;
-			else
-				error = -ESTALE;
-		}
-		file = ERR_PTR(error);
+	if (opened & FILE_OPENED)
+		fput(file);
+	else
+		put_filp(file);
+	if (error == -EOPENSTALE) {
+		if (flags & LOOKUP_RCU)
+			error = -ECHILD;
+		else
+			error = -ESTALE;
 	}
-	return file;
+	return ERR_PTR(error);
 }
 
 struct file *do_filp_open(int dfd, struct filename *pathname,
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 08/27] switch all remaining checks for FILE_OPENED to FMODE_OPENED
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (5 preceding siblings ...)
  2018-07-09  4:53   ` [RFC][PATCH 07/27] lift fput() on late failures into path_openat() Al Viro
@ 2018-07-09  4:53   ` Al Viro
  2018-07-09  4:53   ` [RFC][PATCH 09/27] now we can fold open_check_o_direct() into do_dentry_open() Al Viro
                     ` (18 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:53 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

... and don't bother with setting FILE_OPENED at all.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/namei.c | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 36c2fa804e26..b324f59f8209 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3061,8 +3061,6 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
 		 * permission here.
 		 */
 		int acc_mode = op->acc_mode;
-		if (file->f_mode & FMODE_OPENED)
-			*opened |= FILE_OPENED;
 		if (*opened & FILE_CREATED) {
 			WARN_ON(!(open_flag & O_CREAT));
 			fsnotify_create(dir, dentry);
@@ -3397,11 +3395,10 @@ static int do_last(struct nameidata *nd,
 	error = may_open(&nd->path, acc_mode, open_flag);
 	if (error)
 		goto out;
-	BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
+	BUG_ON(file->f_mode & FMODE_OPENED); /* once it's opened, it's opened */
 	error = vfs_open(&nd->path, file, current_cred());
 	if (error)
 		goto out;
-	*opened |= FILE_OPENED;
 opened:
 	error = open_check_o_direct(file);
 	if (!error)
@@ -3483,8 +3480,6 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags,
 	error = finish_open(file, child, NULL);
 	if (error)
 		goto out2;
-	if (file->f_mode & FMODE_OPENED)
-		*opened |= FILE_OPENED;
 	error = open_check_o_direct(file);
 out2:
 	mnt_drop_write(path.mnt);
@@ -3526,8 +3521,6 @@ static struct file *path_openat(struct nameidata *nd,
 
 	if (unlikely(file->f_flags & O_PATH)) {
 		error = do_o_path(nd, flags, file);
-		if (!error)
-			opened |= FILE_OPENED;
 		goto out2;
 	}
 
@@ -3548,12 +3541,12 @@ static struct file *path_openat(struct nameidata *nd,
 	terminate_walk(nd);
 out2:
 	if (likely(!error)) {
-		if (likely(opened & FILE_OPENED))
+		if (likely(file->f_mode & FMODE_OPENED))
 			return file;
 		WARN_ON(1);
 		error = -EINVAL;
 	}
-	if (opened & FILE_OPENED)
+	if (file->f_mode & FMODE_OPENED)
 		fput(file);
 	else
 		put_filp(file);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 09/27] now we can fold open_check_o_direct() into do_dentry_open()
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (6 preceding siblings ...)
  2018-07-09  4:53   ` [RFC][PATCH 08/27] switch all remaining checks for FILE_OPENED to FMODE_OPENED Al Viro
@ 2018-07-09  4:53   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 10/27] introduce FMODE_CREATED and switch to it Al Viro
                     ` (17 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:53 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/internal.h |  1 -
 fs/namei.c    |  7 +------
 fs/open.c     | 27 +++++++++------------------
 3 files changed, 10 insertions(+), 25 deletions(-)

diff --git a/fs/internal.h b/fs/internal.h
index 5645b4ebf494..08ac9cdee1b4 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -125,7 +125,6 @@ int do_fchmodat(int dfd, const char __user *filename, umode_t mode);
 int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group,
 		int flag);
 
-extern int open_check_o_direct(struct file *f);
 extern int vfs_open(const struct path *, struct file *, const struct cred *);
 
 /*
diff --git a/fs/namei.c b/fs/namei.c
index b324f59f8209..598dbc65189b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3400,9 +3400,7 @@ static int do_last(struct nameidata *nd,
 	if (error)
 		goto out;
 opened:
-	error = open_check_o_direct(file);
-	if (!error)
-		error = ima_file_check(file, op->acc_mode, *opened);
+	error = ima_file_check(file, op->acc_mode, *opened);
 	if (!error && will_truncate)
 		error = handle_truncate(file);
 out:
@@ -3478,9 +3476,6 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags,
 		goto out2;
 	file->f_path.mnt = path.mnt;
 	error = finish_open(file, child, NULL);
-	if (error)
-		goto out2;
-	error = open_check_o_direct(file);
 out2:
 	mnt_drop_write(path.mnt);
 out:
diff --git a/fs/open.c b/fs/open.c
index 6405f079264d..d5856c33c418 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -724,16 +724,6 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
 	return ksys_fchown(fd, user, group);
 }
 
-int open_check_o_direct(struct file *f)
-{
-	/* NB: we're sure to have correct a_ops only after f_op->open */
-	if (f->f_flags & O_DIRECT) {
-		if (!f->f_mapping->a_ops || !f->f_mapping->a_ops->direct_IO)
-			return -EINVAL;
-	}
-	return 0;
-}
-
 static int do_dentry_open(struct file *f,
 			  struct inode *inode,
 			  int (*open)(struct inode *, struct file *),
@@ -810,6 +800,11 @@ static int do_dentry_open(struct file *f,
 
 	file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);
 
+	/* NB: we're sure to have correct a_ops only after f_op->open */
+	if (f->f_flags & O_DIRECT) {
+		if (!f->f_mapping->a_ops || !f->f_mapping->a_ops->direct_IO)
+			return -EINVAL;
+	}
 	return 0;
 
 cleanup_all:
@@ -922,15 +917,11 @@ struct file *dentry_open(const struct path *path, int flags,
 	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 */
-			error = open_check_o_direct(f);
-			if (error) {
+		if (error) {
+			if (f->f_mode & FMODE_OPENED)
 				fput(f);
-				f = ERR_PTR(error);
-			}
-		} else { 
-			put_filp(f);
+			else
+				put_filp(f);
 			f = ERR_PTR(error);
 		}
 	}
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 10/27] introduce FMODE_CREATED and switch to it
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (7 preceding siblings ...)
  2018-07-09  4:53   ` [RFC][PATCH 09/27] now we can fold open_check_o_direct() into do_dentry_open() Al Viro
@ 2018-07-09  4:54   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 11/27] IMA: don't propagate opened through the entire thing Al Viro
                     ` (16 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

Parallel to FILE_CREATED, goes into ->f_mode instead of *opened.
NFS is a bit of a wart here - it doesn't have file at the point
where FILE_CREATED used to be set, so we need to propagate it
there (for now).  IMA is another one (here and everywhere)...

Note that this needs do_dentry_open() to leave old bits in ->f_mode
alone - we want it to preserve FMODE_CREATED if it had been already
set (no other bit can be there).

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/9p/vfs_inode.c      |  2 +-
 fs/9p/vfs_inode_dotl.c |  2 +-
 fs/ceph/file.c         |  2 +-
 fs/cifs/dir.c          |  2 +-
 fs/fuse/dir.c          |  2 +-
 fs/gfs2/inode.c        |  2 +-
 fs/namei.c             | 15 ++++++++-------
 fs/nfs/dir.c           |  5 ++++-
 fs/nfs/nfs4proc.c      |  2 +-
 fs/open.c              |  2 +-
 include/linux/fs.h     |  1 +
 11 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 73dd18e44e5c..7b6ff3275d9c 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -925,7 +925,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
 	if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
 		v9fs_cache_inode_set_cookie(d_inode(dentry), file);
 
-	*opened |= FILE_CREATED;
+	file->f_mode |= FMODE_CREATED;
 out:
 	dput(res);
 	return err;
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 0b79872848c1..c6939b7cb18c 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -358,7 +358,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	file->private_data = ofid;
 	if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
 		v9fs_cache_inode_set_cookie(inode, file);
-	*opened |= FILE_CREATED;
+	file->f_mode |= FMODE_CREATED;
 out:
 	v9fs_put_acl(dacl, pacl);
 	dput(res);
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 47afcec3792a..38b28cb2fac1 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -507,7 +507,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
 		dout("atomic_open finish_open on dn %p\n", dn);
 		if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
 			ceph_init_inode_acls(d_inode(dentry), &acls);
-			*opened |= FILE_CREATED;
+			file->f_mode |= FMODE_CREATED;
 		}
 		err = finish_open(file, dentry, ceph_open);
 	}
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index fa5b642bc492..891bfd62e67a 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -539,7 +539,7 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
 	}
 
 	if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
-		*opened |= FILE_CREATED;
+		file->f_mode |= FMODE_CREATED;
 
 	rc = finish_open(file, direntry, generic_file_open);
 	if (rc) {
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 657b4be22d65..a5b1f5ff8cb7 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -508,7 +508,7 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
 		goto no_open;
 
 	/* Only creates */
-	*opened |= FILE_CREATED;
+	file->f_mode |= FMODE_CREATED;
 
 	if (fc->no_create)
 		goto mknod;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 7604844c28a6..59f695e96d63 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -767,7 +767,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 	mark_inode_dirty(inode);
 	d_instantiate(dentry, inode);
 	if (file) {
-		*opened |= FILE_CREATED;
+		file->f_mode |= FMODE_CREATED;
 		error = finish_open(file, dentry, gfs2_open_common);
 	}
 	gfs2_glock_dq_uninit(ghs);
diff --git a/fs/namei.c b/fs/namei.c
index 598dbc65189b..955a28a62f78 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3061,7 +3061,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
 		 * permission here.
 		 */
 		int acc_mode = op->acc_mode;
-		if (*opened & FILE_CREATED) {
+		if (file->f_mode & FMODE_CREATED) {
 			WARN_ON(!(open_flag & O_CREAT));
 			fsnotify_create(dir, dentry);
 			acc_mode = 0;
@@ -3077,7 +3077,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
 				dput(dentry);
 				dentry = file->f_path.dentry;
 			}
-			if (*opened & FILE_CREATED)
+			if (file->f_mode & FMODE_CREATED)
 				fsnotify_create(dir, dentry);
 			if (unlikely(d_is_negative(dentry))) {
 				error = -ENOENT;
@@ -3126,7 +3126,7 @@ static int lookup_open(struct nameidata *nd, struct path *path,
 	if (unlikely(IS_DEADDIR(dir_inode)))
 		return -ENOENT;
 
-	*opened &= ~FILE_CREATED;
+	file->f_mode &= ~FMODE_CREATED;
 	dentry = d_lookup(dir, &nd->last);
 	for (;;) {
 		if (!dentry) {
@@ -3211,7 +3211,7 @@ static int lookup_open(struct nameidata *nd, struct path *path,
 
 	/* Negative dentry, just create the file */
 	if (!dentry->d_inode && (open_flag & O_CREAT)) {
-		*opened |= FILE_CREATED;
+		file->f_mode |= FMODE_CREATED;
 		audit_inode_child(dir_inode, dentry, AUDIT_TYPE_CHILD_CREATE);
 		if (!dir_inode->i_op->create) {
 			error = -EACCES;
@@ -3318,7 +3318,7 @@ static int do_last(struct nameidata *nd,
 		if (error)
 			goto out;
 
-		if ((*opened & FILE_CREATED) ||
+		if ((file->f_mode & FMODE_CREATED) ||
 		    !S_ISREG(file_inode(file)->i_mode))
 			will_truncate = false;
 
@@ -3326,7 +3326,7 @@ static int do_last(struct nameidata *nd,
 		goto opened;
 	}
 
-	if (*opened & FILE_CREATED) {
+	if (file->f_mode & FMODE_CREATED) {
 		/* Don't check for write permission, don't truncate */
 		open_flag &= ~O_TRUNC;
 		will_truncate = false;
@@ -3400,7 +3400,8 @@ static int do_last(struct nameidata *nd,
 	if (error)
 		goto out;
 opened:
-	error = ima_file_check(file, op->acc_mode, *opened);
+	error = ima_file_check(file, op->acc_mode,
+				file->f_mode & FMODE_CREATED ? FILE_CREATED : 0);
 	if (!error && will_truncate)
 		error = handle_truncate(file);
 out:
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 076c4b855cf9..22176a3818d5 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1461,6 +1461,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
 	struct inode *inode;
 	unsigned int lookup_flags = 0;
 	bool switched = false;
+	int created = 0;
 	int err;
 
 	/* Expect a negative dentry */
@@ -1521,7 +1522,9 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
 		goto out;
 
 	trace_nfs_atomic_open_enter(dir, ctx, open_flags);
-	inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr, opened);
+	inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr, &created);
+	if (created)
+		file->f_mode |= FMODE_CREATED;
 	if (IS_ERR(inode)) {
 		err = PTR_ERR(inode);
 		trace_nfs_atomic_open_exit(dir, ctx, open_flags, err);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ed45090e4df6..2c4df0ffbca1 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2951,7 +2951,7 @@ static int _nfs4_do_open(struct inode *dir,
 		}
 	}
 	if (opened && opendata->file_created)
-		*opened |= FILE_CREATED;
+		*opened = 1;
 
 	if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server)) {
 		*ctx_th = opendata->f_attr.mdsthreshold;
diff --git a/fs/open.c b/fs/open.c
index d5856c33c418..0836c86fd0ce 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -732,7 +732,7 @@ 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 |
+	f->f_mode |= OPEN_FMODE(f->f_flags) | FMODE_LSEEK |
 				FMODE_PREAD | FMODE_PWRITE;
 
 	path_get(&f->f_path);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index a9664953be9f..e5ef4627856e 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -149,6 +149,7 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 #define FMODE_CAN_WRITE         ((__force fmode_t)0x40000)
 
 #define FMODE_OPENED		((__force fmode_t)0x80000)
+#define FMODE_CREATED		((__force fmode_t)0x100000)
 
 /* File was opened by fanotify and shouldn't generate fanotify events */
 #define FMODE_NONOTIFY		((__force fmode_t)0x4000000)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 11/27] IMA: don't propagate opened through the entire thing
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (8 preceding siblings ...)
  2018-07-09  4:54   ` [RFC][PATCH 10/27] introduce FMODE_CREATED and switch to it Al Viro
@ 2018-07-09  4:54   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 12/27] Preparation to killing ->atomic_open() 'opened' argument Al Viro
                     ` (15 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

just check ->f_mode in ima_appraise_measurement()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/namei.c                            |  3 +--
 fs/nfsd/vfs.c                         |  2 +-
 include/linux/ima.h                   |  4 ++--
 security/integrity/ima/ima.h          |  4 ++--
 security/integrity/ima/ima_appraise.c |  4 ++--
 security/integrity/ima/ima_main.c     | 16 ++++++++--------
 6 files changed, 16 insertions(+), 17 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 955a28a62f78..5e3eefca676a 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3400,8 +3400,7 @@ static int do_last(struct nameidata *nd,
 	if (error)
 		goto out;
 opened:
-	error = ima_file_check(file, op->acc_mode,
-				file->f_mode & FMODE_CREATED ? FILE_CREATED : 0);
+	error = ima_file_check(file, op->acc_mode);
 	if (!error && will_truncate)
 		error = handle_truncate(file);
 out:
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index b0555d7d8200..55a099e47ba2 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -763,7 +763,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
 		goto out_nfserr;
 	}
 
-	host_err = ima_file_check(file, may_flags, 0);
+	host_err = ima_file_check(file, may_flags);
 	if (host_err) {
 		fput(file);
 		goto out_nfserr;
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 0e4647e0eb60..d9ba3fc363b7 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -16,7 +16,7 @@ struct linux_binprm;
 
 #ifdef CONFIG_IMA
 extern int ima_bprm_check(struct linux_binprm *bprm);
-extern int ima_file_check(struct file *file, int mask, int opened);
+extern int ima_file_check(struct file *file, int mask);
 extern void ima_file_free(struct file *file);
 extern int ima_file_mmap(struct file *file, unsigned long prot);
 extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
@@ -34,7 +34,7 @@ static inline int ima_bprm_check(struct linux_binprm *bprm)
 	return 0;
 }
 
-static inline int ima_file_check(struct file *file, int mask, int opened)
+static inline int ima_file_check(struct file *file, int mask)
 {
 	return 0;
 }
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 354bb5716ce3..e4c1a236976c 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -238,7 +238,7 @@ int ima_appraise_measurement(enum ima_hooks func,
 			     struct integrity_iint_cache *iint,
 			     struct file *file, const unsigned char *filename,
 			     struct evm_ima_xattr_data *xattr_value,
-			     int xattr_len, int opened);
+			     int xattr_len);
 int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func);
 void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
 enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
@@ -254,7 +254,7 @@ static inline int ima_appraise_measurement(enum ima_hooks func,
 					   struct file *file,
 					   const unsigned char *filename,
 					   struct evm_ima_xattr_data *xattr_value,
-					   int xattr_len, int opened)
+					   int xattr_len)
 {
 	return INTEGRITY_UNKNOWN;
 }
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 8bd7a0733e51..deec1804a00a 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -212,7 +212,7 @@ int ima_appraise_measurement(enum ima_hooks func,
 			     struct integrity_iint_cache *iint,
 			     struct file *file, const unsigned char *filename,
 			     struct evm_ima_xattr_data *xattr_value,
-			     int xattr_len, int opened)
+			     int xattr_len)
 {
 	static const char op[] = "appraise_data";
 	const char *cause = "unknown";
@@ -231,7 +231,7 @@ int ima_appraise_measurement(enum ima_hooks func,
 		cause = iint->flags & IMA_DIGSIG_REQUIRED ?
 				"IMA-signature-required" : "missing-hash";
 		status = INTEGRITY_NOLABEL;
-		if (opened & FILE_CREATED)
+		if (file->f_mode & FMODE_CREATED)
 			iint->flags |= IMA_NEW_FILE;
 		if ((iint->flags & IMA_NEW_FILE) &&
 		    (!(iint->flags & IMA_DIGSIG_REQUIRED) ||
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index dca44cf7838e..b286f37712d5 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -168,7 +168,7 @@ void ima_file_free(struct file *file)
 
 static int process_measurement(struct file *file, const struct cred *cred,
 			       u32 secid, char *buf, loff_t size, int mask,
-			       enum ima_hooks func, int opened)
+			       enum ima_hooks func)
 {
 	struct inode *inode = file_inode(file);
 	struct integrity_iint_cache *iint = NULL;
@@ -294,7 +294,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
 	if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) {
 		inode_lock(inode);
 		rc = ima_appraise_measurement(func, iint, file, pathname,
-					      xattr_value, xattr_len, opened);
+					      xattr_value, xattr_len);
 		inode_unlock(inode);
 	}
 	if (action & IMA_AUDIT)
@@ -338,7 +338,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
 	if (file && (prot & PROT_EXEC)) {
 		security_task_getsecid(current, &secid);
 		return process_measurement(file, current_cred(), secid, NULL,
-					   0, MAY_EXEC, MMAP_CHECK, 0);
+					   0, MAY_EXEC, MMAP_CHECK);
 	}
 
 	return 0;
@@ -364,13 +364,13 @@ int ima_bprm_check(struct linux_binprm *bprm)
 
 	security_task_getsecid(current, &secid);
 	ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0,
-				  MAY_EXEC, BPRM_CHECK, 0);
+				  MAY_EXEC, BPRM_CHECK);
 	if (ret)
 		return ret;
 
 	security_cred_getsecid(bprm->cred, &secid);
 	return process_measurement(bprm->file, bprm->cred, secid, NULL, 0,
-				   MAY_EXEC, CREDS_CHECK, 0);
+				   MAY_EXEC, CREDS_CHECK);
 }
 
 /**
@@ -383,14 +383,14 @@ int ima_bprm_check(struct linux_binprm *bprm)
  * On success return 0.  On integrity appraisal error, assuming the file
  * is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
  */
-int ima_file_check(struct file *file, int mask, int opened)
+int ima_file_check(struct file *file, int mask)
 {
 	u32 secid;
 
 	security_task_getsecid(current, &secid);
 	return process_measurement(file, current_cred(), secid, NULL, 0,
 				   mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
-					   MAY_APPEND), FILE_CHECK, opened);
+					   MAY_APPEND), FILE_CHECK);
 }
 EXPORT_SYMBOL_GPL(ima_file_check);
 
@@ -493,7 +493,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
 	func = read_idmap[read_id] ?: FILE_CHECK;
 	security_task_getsecid(current, &secid);
 	return process_measurement(file, current_cred(), secid, buf, size,
-				   MAY_READ, func, 0);
+				   MAY_READ, func);
 }
 
 static int __init init_ima(void)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 12/27] Preparation to killing ->atomic_open() 'opened' argument.
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (9 preceding siblings ...)
  2018-07-09  4:54   ` [RFC][PATCH 11/27] IMA: don't propagate opened through the entire thing Al Viro
@ 2018-07-09  4:54   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 13/27] get rid of 'opened' argument of ->atomic_open() Al Viro
                     ` (14 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

__gfs2_lookup(), gfs2_create_inode(), nfs_finish_open() and fuse_create_open()
don't need 'opened' anymore.  Get rid of that argument in those.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/fuse/dir.c   |  4 ++--
 fs/gfs2/inode.c | 19 +++++++++----------
 fs/nfs/dir.c    |  5 ++---
 3 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index a5b1f5ff8cb7..b8d7e9d423c8 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -399,7 +399,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
  */
 static int fuse_create_open(struct inode *dir, struct dentry *entry,
 			    struct file *file, unsigned flags,
-			    umode_t mode, int *opened)
+			    umode_t mode)
 {
 	int err;
 	struct inode *inode;
@@ -513,7 +513,7 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
 	if (fc->no_create)
 		goto mknod;
 
-	err = fuse_create_open(dir, entry, file, flags, mode, opened);
+	err = fuse_create_open(dir, entry, file, flags, mode);
 	if (err == -ENOSYS) {
 		fc->no_create = 1;
 		goto mknod;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 59f695e96d63..15e2a8a3b917 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -580,7 +580,7 @@ static int gfs2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
 static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 			     struct file *file,
 			     umode_t mode, dev_t dev, const char *symname,
-			     unsigned int size, int excl, int *opened)
+			     unsigned int size, int excl)
 {
 	const struct qstr *name = &dentry->d_name;
 	struct posix_acl *default_acl, *acl;
@@ -822,7 +822,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 static int gfs2_create(struct inode *dir, struct dentry *dentry,
 		       umode_t mode, bool excl)
 {
-	return gfs2_create_inode(dir, dentry, NULL, S_IFREG | mode, 0, NULL, 0, excl, NULL);
+	return gfs2_create_inode(dir, dentry, NULL, S_IFREG | mode, 0, NULL, 0, excl);
 }
 
 /**
@@ -830,14 +830,13 @@ static int gfs2_create(struct inode *dir, struct dentry *dentry,
  * @dir: The directory inode
  * @dentry: The dentry of the new inode
  * @file: File to be opened
- * @opened: atomic_open flags
  *
  *
  * Returns: errno
  */
 
 static struct dentry *__gfs2_lookup(struct inode *dir, struct dentry *dentry,
-				    struct file *file, int *opened)
+				    struct file *file)
 {
 	struct inode *inode;
 	struct dentry *d;
@@ -879,7 +878,7 @@ static struct dentry *__gfs2_lookup(struct inode *dir, struct dentry *dentry,
 static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry,
 				  unsigned flags)
 {
-	return __gfs2_lookup(dir, dentry, NULL, NULL);
+	return __gfs2_lookup(dir, dentry, NULL);
 }
 
 /**
@@ -1189,7 +1188,7 @@ static int gfs2_symlink(struct inode *dir, struct dentry *dentry,
 	if (size >= gfs2_max_stuffed_size(GFS2_I(dir)))
 		return -ENAMETOOLONG;
 
-	return gfs2_create_inode(dir, dentry, NULL, S_IFLNK | S_IRWXUGO, 0, symname, size, 0, NULL);
+	return gfs2_create_inode(dir, dentry, NULL, S_IFLNK | S_IRWXUGO, 0, symname, size, 0);
 }
 
 /**
@@ -1204,7 +1203,7 @@ static int gfs2_symlink(struct inode *dir, struct dentry *dentry,
 static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
 	unsigned dsize = gfs2_max_stuffed_size(GFS2_I(dir));
-	return gfs2_create_inode(dir, dentry, NULL, S_IFDIR | mode, 0, NULL, dsize, 0, NULL);
+	return gfs2_create_inode(dir, dentry, NULL, S_IFDIR | mode, 0, NULL, dsize, 0);
 }
 
 /**
@@ -1219,7 +1218,7 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 static int gfs2_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
 		      dev_t dev)
 {
-	return gfs2_create_inode(dir, dentry, NULL, mode, dev, NULL, 0, 0, NULL);
+	return gfs2_create_inode(dir, dentry, NULL, mode, dev, NULL, 0, 0);
 }
 
 /**
@@ -1244,7 +1243,7 @@ static int gfs2_atomic_open(struct inode *dir, struct dentry *dentry,
 	if (!d_in_lookup(dentry))
 		goto skip_lookup;
 
-	d = __gfs2_lookup(dir, dentry, file, opened);
+	d = __gfs2_lookup(dir, dentry, file);
 	if (IS_ERR(d))
 		return PTR_ERR(d);
 	if (d != NULL)
@@ -1262,7 +1261,7 @@ static int gfs2_atomic_open(struct inode *dir, struct dentry *dentry,
 	if (!(flags & O_CREAT))
 		return -ENOENT;
 
-	return gfs2_create_inode(dir, dentry, file, S_IFREG | mode, 0, NULL, 0, excl, opened);
+	return gfs2_create_inode(dir, dentry, file, S_IFREG | mode, 0, NULL, 0, excl);
 }
 
 /*
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 22176a3818d5..71ae3cc3e53a 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1434,8 +1434,7 @@ static int do_open(struct inode *inode, struct file *filp)
 
 static int nfs_finish_open(struct nfs_open_context *ctx,
 			   struct dentry *dentry,
-			   struct file *file, unsigned open_flags,
-			   int *opened)
+			   struct file *file, unsigned open_flags)
 {
 	int err;
 
@@ -1549,7 +1548,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
 		goto out;
 	}
 
-	err = nfs_finish_open(ctx, ctx->dentry, file, open_flags, opened);
+	err = nfs_finish_open(ctx, ctx->dentry, file, open_flags);
 	trace_nfs_atomic_open_exit(dir, ctx, open_flags, err);
 	put_nfs_open_context(ctx);
 out:
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 13/27] get rid of 'opened' argument of ->atomic_open()
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (10 preceding siblings ...)
  2018-07-09  4:54   ` [RFC][PATCH 12/27] Preparation to killing ->atomic_open() 'opened' argument Al Viro
@ 2018-07-09  4:54   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 14/27] get rid of 'opened' in path_openat() and the helpers downstream Al Viro
                     ` (13 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

not used anymore

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/9p/vfs_inode.c      | 3 +--
 fs/9p/vfs_inode_dotl.c | 3 +--
 fs/bad_inode.c         | 2 +-
 fs/ceph/file.c         | 3 +--
 fs/ceph/super.h        | 3 +--
 fs/cifs/cifsfs.h       | 3 +--
 fs/cifs/dir.c          | 3 +--
 fs/fuse/dir.c          | 2 +-
 fs/gfs2/inode.c        | 3 +--
 fs/namei.c             | 3 +--
 fs/nfs/dir.c           | 2 +-
 fs/nfs/nfs4_fs.h       | 2 +-
 include/linux/fs.h     | 2 +-
 13 files changed, 13 insertions(+), 21 deletions(-)

diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 7b6ff3275d9c..85ff859d3af5 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -859,8 +859,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
 
 static int
 v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
-		     struct file *file, unsigned flags, umode_t mode,
-		     int *opened)
+		     struct file *file, unsigned flags, umode_t mode)
 {
 	int err;
 	u32 perm;
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index c6939b7cb18c..4823e1c46999 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -241,8 +241,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
 
 static int
 v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
-			  struct file *file, unsigned flags, umode_t omode,
-			  int *opened)
+			  struct file *file, unsigned flags, umode_t omode)
 {
 	int err = 0;
 	kgid_t gid;
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 125e8bbd22a2..8035d2a44561 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -134,7 +134,7 @@ static int bad_inode_update_time(struct inode *inode, struct timespec64 *time,
 
 static int bad_inode_atomic_open(struct inode *inode, struct dentry *dentry,
 				 struct file *file, unsigned int open_flag,
-				 umode_t create_mode, int *opened)
+				 umode_t create_mode)
 {
 	return -EIO;
 }
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 38b28cb2fac1..e2679e8a2535 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -429,8 +429,7 @@ int ceph_open(struct inode *inode, struct file *file)
  * file or symlink, return 1 so the VFS can retry.
  */
 int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
-		     struct file *file, unsigned flags, umode_t mode,
-		     int *opened)
+		     struct file *file, unsigned flags, umode_t mode)
 {
 	struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
 	struct ceph_mds_client *mdsc = fsc->mdsc;
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index a7077a0c989f..971328b99ede 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -1025,8 +1025,7 @@ extern const struct file_operations ceph_file_fops;
 extern int ceph_renew_caps(struct inode *inode);
 extern int ceph_open(struct inode *inode, struct file *file);
 extern int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
-			    struct file *file, unsigned flags, umode_t mode,
-			    int *opened);
+			    struct file *file, unsigned flags, umode_t mode);
 extern int ceph_release(struct inode *inode, struct file *filp);
 extern void ceph_fill_inline_data(struct inode *inode, struct page *locked_page,
 				  char *data, size_t len);
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 5f0231803431..f3a78efc3109 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -65,8 +65,7 @@ extern struct inode *cifs_root_iget(struct super_block *);
 extern int cifs_create(struct inode *, struct dentry *, umode_t,
 		       bool excl);
 extern int cifs_atomic_open(struct inode *, struct dentry *,
-			    struct file *, unsigned, umode_t,
-			    int *);
+			    struct file *, unsigned, umode_t);
 extern struct dentry *cifs_lookup(struct inode *, struct dentry *,
 				  unsigned int);
 extern int cifs_unlink(struct inode *dir, struct dentry *dentry);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 891bfd62e67a..3713d22b95a7 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -465,8 +465,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
 
 int
 cifs_atomic_open(struct inode *inode, struct dentry *direntry,
-		 struct file *file, unsigned oflags, umode_t mode,
-		 int *opened)
+		 struct file *file, unsigned oflags, umode_t mode)
 {
 	int rc;
 	unsigned int xid;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index b8d7e9d423c8..c979329311c8 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -489,7 +489,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
 static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
 static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
 			    struct file *file, unsigned flags,
-			    umode_t mode, int *opened)
+			    umode_t mode)
 {
 	int err;
 	struct fuse_conn *fc = get_fuse_conn(dir);
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 15e2a8a3b917..648f0ca1ad57 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -1228,14 +1228,13 @@ static int gfs2_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
  * @file: The proposed new struct file
  * @flags: open flags
  * @mode: File mode
- * @opened: Flag to say whether the file has been opened or not
  *
  * Returns: error code or 0 for success
  */
 
 static int gfs2_atomic_open(struct inode *dir, struct dentry *dentry,
 			    struct file *file, unsigned flags,
-			    umode_t mode, int *opened)
+			    umode_t mode)
 {
 	struct dentry *d;
 	bool excl = !!(flags & O_EXCL);
diff --git a/fs/namei.c b/fs/namei.c
index 5e3eefca676a..7270cac785b0 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3052,8 +3052,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
 	file->f_path.dentry = DENTRY_NOT_SET;
 	file->f_path.mnt = nd->path.mnt;
 	error = dir->i_op->atomic_open(dir, dentry, file,
-				       open_to_namei_flags(open_flag),
-				       mode, opened);
+				       open_to_namei_flags(open_flag), mode);
 	d_lookup_done(dentry);
 	if (!error) {
 		/*
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 71ae3cc3e53a..f447b1a24350 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1451,7 +1451,7 @@ static int nfs_finish_open(struct nfs_open_context *ctx,
 
 int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
 		    struct file *file, unsigned open_flags,
-		    umode_t mode, int *opened)
+		    umode_t mode)
 {
 	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
 	struct nfs_open_context *ctx;
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 137e18abb7e7..51beb6e38c90 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -258,7 +258,7 @@ extern const struct dentry_operations nfs4_dentry_operations;
 
 /* dir.c */
 int nfs_atomic_open(struct inode *, struct dentry *, struct file *,
-		    unsigned, umode_t, int *);
+		    unsigned, umode_t);
 
 /* super.c */
 extern struct file_system_type nfs4_fs_type;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index e5ef4627856e..80fec0332fdd 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1782,7 +1782,7 @@ struct inode_operations {
 	int (*update_time)(struct inode *, struct timespec64 *, int);
 	int (*atomic_open)(struct inode *, struct dentry *,
 			   struct file *, unsigned open_flag,
-			   umode_t create_mode, int *opened);
+			   umode_t create_mode);
 	int (*tmpfile) (struct inode *, struct dentry *, umode_t);
 	int (*set_acl)(struct inode *, struct posix_acl *, int);
 } ____cacheline_aligned;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 14/27] get rid of 'opened' in path_openat() and the helpers downstream
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (11 preceding siblings ...)
  2018-07-09  4:54   ` [RFC][PATCH 13/27] get rid of 'opened' argument of ->atomic_open() Al Viro
@ 2018-07-09  4:54   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 15/27] kill FILE_{CREATED,OPENED} Al Viro
                     ` (12 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

unused now

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/namei.c | 22 ++++++++--------------
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 7270cac785b0..5d7aa567c958 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3036,8 +3036,7 @@ static int may_o_create(const struct path *dir, struct dentry *dentry, umode_t m
 static int atomic_open(struct nameidata *nd, struct dentry *dentry,
 			struct path *path, struct file *file,
 			const struct open_flags *op,
-			int open_flag, umode_t mode,
-			int *opened)
+			int open_flag, umode_t mode)
 {
 	struct dentry *const DENTRY_NOT_SET = (void *) -1UL;
 	struct inode *dir =  nd->path.dentry->d_inode;
@@ -3105,14 +3104,11 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
  * specified then a negative dentry may be returned.
  *
  * An error code is returned otherwise.
- *
- * FILE_CREATE will be set in @*opened if the dentry was created and will be
- * cleared otherwise prior to returning.
  */
 static int lookup_open(struct nameidata *nd, struct path *path,
 			struct file *file,
 			const struct open_flags *op,
-			bool got_write, int *opened)
+			bool got_write)
 {
 	struct dentry *dir = nd->path.dentry;
 	struct inode *dir_inode = dir->d_inode;
@@ -3187,7 +3183,7 @@ static int lookup_open(struct nameidata *nd, struct path *path,
 
 	if (dir_inode->i_op->atomic_open) {
 		error = atomic_open(nd, dentry, path, file, op, open_flag,
-				    mode, opened);
+				    mode);
 		if (unlikely(error == -ENOENT) && create_error)
 			error = create_error;
 		return error;
@@ -3240,8 +3236,7 @@ static int lookup_open(struct nameidata *nd, struct path *path,
  * Handle the last step of open()
  */
 static int do_last(struct nameidata *nd,
-		   struct file *file, const struct open_flags *op,
-		   int *opened)
+		   struct file *file, const struct open_flags *op)
 {
 	struct dentry *dir = nd->path.dentry;
 	int open_flag = op->open_flag;
@@ -3307,7 +3302,7 @@ static int do_last(struct nameidata *nd,
 		inode_lock(dir->d_inode);
 	else
 		inode_lock_shared(dir->d_inode);
-	error = lookup_open(nd, &path, file, op, got_write, opened);
+	error = lookup_open(nd, &path, file, op, got_write);
 	if (open_flag & O_CREAT)
 		inode_unlock(dir->d_inode);
 	else
@@ -3452,7 +3447,7 @@ EXPORT_SYMBOL(vfs_tmpfile);
 
 static int do_tmpfile(struct nameidata *nd, unsigned flags,
 		const struct open_flags *op,
-		struct file *file, int *opened)
+		struct file *file)
 {
 	struct dentry *child;
 	struct path path;
@@ -3499,7 +3494,6 @@ static struct file *path_openat(struct nameidata *nd,
 {
 	const char *s;
 	struct file *file;
-	int opened = 0;
 	int error;
 
 	file = get_empty_filp();
@@ -3509,7 +3503,7 @@ static struct file *path_openat(struct nameidata *nd,
 	file->f_flags = op->open_flag;
 
 	if (unlikely(file->f_flags & __O_TMPFILE)) {
-		error = do_tmpfile(nd, flags, op, file, &opened);
+		error = do_tmpfile(nd, flags, op, file);
 		goto out2;
 	}
 
@@ -3524,7 +3518,7 @@ static struct file *path_openat(struct nameidata *nd,
 		return ERR_CAST(s);
 	}
 	while (!(error = link_path_walk(s, nd)) &&
-		(error = do_last(nd, file, op, &opened)) > 0) {
+		(error = do_last(nd, file, op)) > 0) {
 		nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
 		s = trailing_symlink(nd);
 		if (IS_ERR(s)) {
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 15/27] kill FILE_{CREATED,OPENED}
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (12 preceding siblings ...)
  2018-07-09  4:54   ` [RFC][PATCH 14/27] get rid of 'opened' in path_openat() and the helpers downstream Al Viro
@ 2018-07-09  4:54   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 16/27] new wrapper: alloc_file_pseudo() Al Viro
                     ` (11 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

no users left

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 include/linux/fs.h | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 80fec0332fdd..b3240025ce1a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2434,10 +2434,6 @@ extern struct filename *getname(const char __user *);
 extern struct filename *getname_kernel(const char *);
 extern void putname(struct filename *name);
 
-enum {
-	FILE_CREATED = 1,
-	FILE_OPENED = 2
-};
 extern int finish_open(struct file *file, struct dentry *dentry,
 			int (*open)(struct inode *, struct file *));
 extern int finish_no_open(struct file *file, struct dentry *dentry);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 16/27] new wrapper: alloc_file_pseudo()
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (13 preceding siblings ...)
  2018-07-09  4:54   ` [RFC][PATCH 15/27] kill FILE_{CREATED,OPENED} Al Viro
@ 2018-07-09  4:54   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 17/27] __shmem_file_setup(): reorder allocations Al Viro
                     ` (10 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

takes inode, vfsmount, name, mode and file_operations and either
returns a new struct file (in which case inode reference we held
is consumed) or returns ERR_PTR(), in which case no refcounts are
altered.

converted aio_private_file() and sock_alloc_file() to it

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/aio.c             | 27 ++++++---------------------
 fs/file_table.c      | 27 +++++++++++++++++++++++++++
 include/linux/file.h |  3 +++
 net/socket.c         | 27 ++++-----------------------
 4 files changed, 40 insertions(+), 44 deletions(-)

diff --git a/fs/aio.c b/fs/aio.c
index 4d63e8e4d1b5..c5244c68f90e 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -215,9 +215,7 @@ static const struct address_space_operations aio_ctx_aops;
 
 static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages)
 {
-	struct qstr this = QSTR_INIT("[aio]", 5);
 	struct file *file;
-	struct path path;
 	struct inode *inode = alloc_anon_inode(aio_mnt->mnt_sb);
 	if (IS_ERR(inode))
 		return ERR_CAST(inode);
@@ -226,32 +224,19 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages)
 	inode->i_mapping->private_data = ctx;
 	inode->i_size = PAGE_SIZE * nr_pages;
 
-	path.dentry = d_alloc_pseudo(aio_mnt->mnt_sb, &this);
-	if (!path.dentry) {
+	file = alloc_file_pseudo(inode, aio_mnt, "[aio]",
+				FMODE_READ | FMODE_WRITE, &aio_ring_fops);
+	if (IS_ERR(file))
 		iput(inode);
-		return ERR_PTR(-ENOMEM);
-	}
-	path.mnt = mntget(aio_mnt);
-
-	d_instantiate(path.dentry, inode);
-	file = alloc_file(&path, FMODE_READ | FMODE_WRITE | FMODE_OPENED,
-			  &aio_ring_fops);
-	if (IS_ERR(file)) {
-		path_put(&path);
-		return file;
-	}
-
-	file->f_flags = O_RDWR;
+	else
+		file->f_flags = O_RDWR;
 	return file;
 }
 
 static struct dentry *aio_mount(struct file_system_type *fs_type,
 				int flags, const char *dev_name, void *data)
 {
-	static const struct dentry_operations ops = {
-		.d_dname	= simple_dname,
-	};
-	struct dentry *root = mount_pseudo(fs_type, "aio:", NULL, &ops,
+	struct dentry *root = mount_pseudo(fs_type, "aio:", NULL, NULL,
 					   AIO_RING_MAGIC);
 
 	if (!IS_ERR(root))
diff --git a/fs/file_table.c b/fs/file_table.c
index 7ec0b3e5f05d..d78bc97f926f 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -182,6 +182,33 @@ struct file *alloc_file(const struct path *path, fmode_t mode,
 }
 EXPORT_SYMBOL(alloc_file);
 
+struct file *alloc_file_pseudo(struct inode *inode, struct vfsmount *mnt,
+				const char *name, fmode_t mode,
+				const struct file_operations *fops)
+{
+	static const struct dentry_operations anon_ops = {
+		.d_dname = simple_dname
+	};
+	struct qstr this = QSTR_INIT(name, strlen(name));
+	struct path path;
+	struct file *file;
+
+	path.dentry = d_alloc_pseudo(mnt->mnt_sb, &this);
+	if (!path.dentry)
+		return ERR_PTR(-ENOMEM);
+	if (!mnt->mnt_sb->s_d_op)
+		d_set_d_op(path.dentry, &anon_ops);
+	path.mnt = mntget(mnt);
+	d_instantiate(path.dentry, inode);
+	file = alloc_file(&path, mode | FMODE_OPENED, fops);
+	if (IS_ERR(file)) {
+		ihold(inode);
+		path_put(&path);
+	}
+	return file;
+}
+EXPORT_SYMBOL(alloc_file_pseudo);
+
 /* the real guts of fput() - releasing the last reference to file
  */
 static void __fput(struct file *file)
diff --git a/include/linux/file.h b/include/linux/file.h
index 279720db984a..37a4d2c166de 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -17,9 +17,12 @@ extern void fput(struct file *);
 struct file_operations;
 struct vfsmount;
 struct dentry;
+struct inode;
 struct path;
 extern struct file *alloc_file(const struct path *, fmode_t mode,
 	const struct file_operations *fop);
+extern struct file *alloc_file_pseudo(struct inode *, struct vfsmount *,
+	const char *, fmode_t, const struct file_operations *);
 
 static inline void fput_light(struct file *file, int fput_needed)
 {
diff --git a/net/socket.c b/net/socket.c
index eff9db5fd99f..81cf9906cae5 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -391,33 +391,14 @@ static struct file_system_type sock_fs_type = {
 
 struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
 {
-	struct qstr name = { .name = "" };
-	struct path path;
 	struct file *file;
 
-	if (dname) {
-		name.name = dname;
-		name.len = strlen(name.name);
-	} else if (sock->sk) {
-		name.name = sock->sk->sk_prot_creator->name;
-		name.len = strlen(name.name);
-	}
-	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
-	if (unlikely(!path.dentry)) {
-		sock_release(sock);
-		return ERR_PTR(-ENOMEM);
-	}
-	path.mnt = mntget(sock_mnt);
-
-	d_instantiate(path.dentry, SOCK_INODE(sock));
+	if (!dname)
+		dname = sock->sk ? sock->sk->sk_prot_creator->name : "";
 
-	file = alloc_file(&path, FMODE_READ | FMODE_WRITE | FMODE_OPENED,
-		  &socket_file_ops);
+	file = alloc_file_pseudo(SOCK_INODE(sock), sock_mnt, dname,
+				FMODE_READ | FMODE_WRITE, &socket_file_ops);
 	if (IS_ERR(file)) {
-		/* drop dentry, keep inode for a bit */
-		ihold(d_inode(path.dentry));
-		path_put(&path);
-		/* ... and now kill it properly */
 		sock_release(sock);
 		return file;
 	}
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 17/27] __shmem_file_setup(): reorder allocations
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (14 preceding siblings ...)
  2018-07-09  4:54   ` [RFC][PATCH 16/27] new wrapper: alloc_file_pseudo() Al Viro
@ 2018-07-09  4:54   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 18/27] ... and switch shmem_file_setup() to alloc_file_pseudo() Al Viro
                     ` (9 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

grab inode and reserve memory first.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 mm/shmem.c | 43 ++++++++++++++++++++-----------------------
 1 file changed, 20 insertions(+), 23 deletions(-)

diff --git a/mm/shmem.c b/mm/shmem.c
index a76adc3802d1..0aa290f849ee 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -3918,41 +3918,38 @@ static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, l
 	if (shmem_acct_size(flags, size))
 		return ERR_PTR(-ENOMEM);
 
-	res = ERR_PTR(-ENOMEM);
+	sb = mnt->mnt_sb;
+	inode = shmem_get_inode(sb, NULL, S_IFREG | S_IRWXUGO, 0, flags);
+	if (unlikely(!inode)) {
+		shmem_unacct_size(flags, size);
+		return ERR_PTR(-ENOSPC);
+	}
+	inode->i_flags |= i_flags;
+	inode->i_size = size;
+	clear_nlink(inode);	/* It is unlinked */
+	res = ERR_PTR(ramfs_nommu_expand_for_mapping(inode, size));
+	if (IS_ERR(res)) {
+		iput(inode);
+		return res;
+	}
+
 	this.name = name;
 	this.len = strlen(name);
 	this.hash = 0; /* will go */
-	sb = mnt->mnt_sb;
 	path.mnt = mntget(mnt);
 	path.dentry = d_alloc_pseudo(sb, &this);
-	if (!path.dentry)
-		goto put_memory;
+	if (!path.dentry) {
+		iput(inode);
+		return ERR_PTR(-ENOMEM);
+	}
 	d_set_d_op(path.dentry, &anon_ops);
 
-	res = ERR_PTR(-ENOSPC);
-	inode = shmem_get_inode(sb, NULL, S_IFREG | 0777, 0, flags);
-	if (!inode)
-		goto put_memory;
-
-	inode->i_flags |= i_flags;
 	d_instantiate(path.dentry, inode);
-	inode->i_size = size;
-	clear_nlink(inode);	/* It is unlinked */
-	res = ERR_PTR(ramfs_nommu_expand_for_mapping(inode, size));
-	if (IS_ERR(res))
-		goto put_path;
 
 	res = alloc_file(&path, FMODE_WRITE | FMODE_READ | FMODE_OPENED,
 		  &shmem_file_operations);
 	if (IS_ERR(res))
-		goto put_path;
-
-	return res;
-
-put_memory:
-	shmem_unacct_size(flags, size);
-put_path:
-	path_put(&path);
+		path_put(&path);
 	return res;
 }
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 18/27] ... and switch shmem_file_setup() to alloc_file_pseudo()
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (15 preceding siblings ...)
  2018-07-09  4:54   ` [RFC][PATCH 17/27] __shmem_file_setup(): reorder allocations Al Viro
@ 2018-07-09  4:54   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 19/27] cxl_getfile(): switch " Al Viro
                     ` (8 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 mm/shmem.c | 39 ++++++++-------------------------------
 1 file changed, 8 insertions(+), 31 deletions(-)

diff --git a/mm/shmem.c b/mm/shmem.c
index 0aa290f849ee..fd21df189f32 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -3896,18 +3896,11 @@ EXPORT_SYMBOL_GPL(shmem_truncate_range);
 
 /* common code */
 
-static const struct dentry_operations anon_ops = {
-	.d_dname = simple_dname
-};
-
 static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, loff_t size,
 				       unsigned long flags, unsigned int i_flags)
 {
-	struct file *res;
 	struct inode *inode;
-	struct path path;
-	struct super_block *sb;
-	struct qstr this;
+	struct file *res;
 
 	if (IS_ERR(mnt))
 		return ERR_CAST(mnt);
@@ -3918,8 +3911,8 @@ static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, l
 	if (shmem_acct_size(flags, size))
 		return ERR_PTR(-ENOMEM);
 
-	sb = mnt->mnt_sb;
-	inode = shmem_get_inode(sb, NULL, S_IFREG | S_IRWXUGO, 0, flags);
+	inode = shmem_get_inode(mnt->mnt_sb, NULL, S_IFREG | S_IRWXUGO, 0,
+				flags);
 	if (unlikely(!inode)) {
 		shmem_unacct_size(flags, size);
 		return ERR_PTR(-ENOSPC);
@@ -3928,28 +3921,12 @@ static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, l
 	inode->i_size = size;
 	clear_nlink(inode);	/* It is unlinked */
 	res = ERR_PTR(ramfs_nommu_expand_for_mapping(inode, size));
-	if (IS_ERR(res)) {
-		iput(inode);
-		return res;
-	}
-
-	this.name = name;
-	this.len = strlen(name);
-	this.hash = 0; /* will go */
-	path.mnt = mntget(mnt);
-	path.dentry = d_alloc_pseudo(sb, &this);
-	if (!path.dentry) {
-		iput(inode);
-		return ERR_PTR(-ENOMEM);
-	}
-	d_set_d_op(path.dentry, &anon_ops);
-
-	d_instantiate(path.dentry, inode);
-
-	res = alloc_file(&path, FMODE_WRITE | FMODE_READ | FMODE_OPENED,
-		  &shmem_file_operations);
+	if (!IS_ERR(res))
+		res = alloc_file_pseudo(inode, mnt, name,
+				FMODE_WRITE | FMODE_READ,
+				&shmem_file_operations);
 	if (IS_ERR(res))
-		path_put(&path);
+		iput(inode);
 	return res;
 }
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 19/27] cxl_getfile(): switch to alloc_file_pseudo()
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (16 preceding siblings ...)
  2018-07-09  4:54   ` [RFC][PATCH 18/27] ... and switch shmem_file_setup() to alloc_file_pseudo() Al Viro
@ 2018-07-09  4:54   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 20/27] ocxlflash_getfile(): " Al Viro
                     ` (7 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 drivers/misc/cxl/api.c | 21 ++++-----------------
 1 file changed, 4 insertions(+), 17 deletions(-)

diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c
index 146a12fe6cb8..e0b9c00aecde 100644
--- a/drivers/misc/cxl/api.c
+++ b/drivers/misc/cxl/api.c
@@ -67,10 +67,8 @@ static struct file *cxl_getfile(const char *name,
 				const struct file_operations *fops,
 				void *priv, int flags)
 {
-	struct qstr this;
-	struct path path;
 	struct file *file;
-	struct inode *inode = NULL;
+	struct inode *inode;
 	int rc;
 
 	/* strongly inspired by anon_inode_getfile() */
@@ -91,22 +89,11 @@ static struct file *cxl_getfile(const char *name,
 		goto err_fs;
 	}
 
-	file = ERR_PTR(-ENOMEM);
-	this.name = name;
-	this.len = strlen(name);
-	this.hash = 0;
-	path.dentry = d_alloc_pseudo(cxl_vfs_mount->mnt_sb, &this);
-	if (!path.dentry)
+	file = alloc_file_pseudo(inode, cxl_vfs_mount, name,
+				 OPEN_FMODE(flags), fops);
+	if (IS_ERR(file))
 		goto err_inode;
 
-	path.mnt = mntget(cxl_vfs_mount);
-	d_instantiate(path.dentry, inode);
-
-	file = alloc_file(&path, OPEN_FMODE(flags) | FMODE_OPENED, fops);
-	if (IS_ERR(file)) {
-		path_put(&path);
-		goto err_fs;
-	}
 	file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
 	file->private_data = priv;
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 20/27] ocxlflash_getfile(): switch to alloc_file_pseudo()
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (17 preceding siblings ...)
  2018-07-09  4:54   ` [RFC][PATCH 19/27] cxl_getfile(): switch " Al Viro
@ 2018-07-09  4:54   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 21/27] hugetlb_file_setup(): " Al Viro
                     ` (6 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 drivers/scsi/cxlflash/ocxl_hw.c | 23 ++++-------------------
 1 file changed, 4 insertions(+), 19 deletions(-)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 497a68389461..6d0632174ec6 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -88,10 +88,8 @@ static struct file *ocxlflash_getfile(struct device *dev, const char *name,
 				      const struct file_operations *fops,
 				      void *priv, int flags)
 {
-	struct qstr this;
-	struct path path;
 	struct file *file;
-	struct inode *inode = NULL;
+	struct inode *inode;
 	int rc;
 
 	if (fops->owner && !try_module_get(fops->owner)) {
@@ -116,26 +114,13 @@ static struct file *ocxlflash_getfile(struct device *dev, const char *name,
 		goto err3;
 	}
 
-	this.name = name;
-	this.len = strlen(name);
-	this.hash = 0;
-	path.dentry = d_alloc_pseudo(ocxlflash_vfs_mount->mnt_sb, &this);
-	if (!path.dentry) {
-		dev_err(dev, "%s: d_alloc_pseudo failed\n", __func__);
-		rc = -ENOMEM;
-		goto err4;
-	}
-
-	path.mnt = mntget(ocxlflash_vfs_mount);
-	d_instantiate(path.dentry, inode);
-
-	file = alloc_file(&path, OPEN_FMODE(flags), fops);
+	file = alloc_file_pseudo(inode, ocxlflash_vfs_mount, name,
+				 OPEN_FMODE(flags), fops);
 	if (IS_ERR(file)) {
 		rc = PTR_ERR(file);
 		dev_err(dev, "%s: alloc_file failed rc=%d\n",
 			__func__, rc);
-		path_put(&path);
-		goto err3;
+		goto err4;
 	}
 
 	file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 21/27] hugetlb_file_setup(): switch to alloc_file_pseudo()
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (18 preceding siblings ...)
  2018-07-09  4:54   ` [RFC][PATCH 20/27] ocxlflash_getfile(): " Al Viro
@ 2018-07-09  4:54   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 22/27] anon_inode_getfile(): " Al Viro
                     ` (5 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/hugetlbfs/inode.c | 55 ++++++++++++++++------------------------------------
 1 file changed, 17 insertions(+), 38 deletions(-)

diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index e0b8cc89169c..86ffe04f73d6 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -1308,10 +1308,6 @@ static int get_hstate_idx(int page_size_log)
 	return h - hstates;
 }
 
-static const struct dentry_operations anon_ops = {
-	.d_dname = simple_dname
-};
-
 /*
  * Note that size should be aligned to proper hugepage size in caller side,
  * otherwise hugetlb_reserve_pages reserves one less hugepages than intended.
@@ -1320,19 +1316,18 @@ struct file *hugetlb_file_setup(const char *name, size_t size,
 				vm_flags_t acctflag, struct user_struct **user,
 				int creat_flags, int page_size_log)
 {
-	struct file *file = ERR_PTR(-ENOMEM);
 	struct inode *inode;
-	struct path path;
-	struct super_block *sb;
-	struct qstr quick_string;
+	struct vfsmount *mnt;
 	int hstate_idx;
+	struct file *file;
 
 	hstate_idx = get_hstate_idx(page_size_log);
 	if (hstate_idx < 0)
 		return ERR_PTR(-ENODEV);
 
 	*user = NULL;
-	if (!hugetlbfs_vfsmount[hstate_idx])
+	mnt = hugetlbfs_vfsmount[hstate_idx];
+	if (!mnt)
 		return ERR_PTR(-ENOENT);
 
 	if (creat_flags == HUGETLB_SHMFS_INODE && !can_do_hugetlb_shm()) {
@@ -1348,45 +1343,29 @@ struct file *hugetlb_file_setup(const char *name, size_t size,
 		}
 	}
 
-	sb = hugetlbfs_vfsmount[hstate_idx]->mnt_sb;
-	quick_string.name = name;
-	quick_string.len = strlen(quick_string.name);
-	quick_string.hash = 0;
-	path.dentry = d_alloc_pseudo(sb, &quick_string);
-	if (!path.dentry)
-		goto out_shm_unlock;
-
-	d_set_d_op(path.dentry, &anon_ops);
-	path.mnt = mntget(hugetlbfs_vfsmount[hstate_idx]);
 	file = ERR_PTR(-ENOSPC);
-	inode = hugetlbfs_get_inode(sb, NULL, S_IFREG | S_IRWXUGO, 0);
+	inode = hugetlbfs_get_inode(mnt->mnt_sb, NULL, S_IFREG | S_IRWXUGO, 0);
 	if (!inode)
-		goto out_dentry;
+		goto out;
 	if (creat_flags == HUGETLB_SHMFS_INODE)
 		inode->i_flags |= S_PRIVATE;
 
-	file = ERR_PTR(-ENOMEM);
-	if (hugetlb_reserve_pages(inode, 0,
-			size >> huge_page_shift(hstate_inode(inode)), NULL,
-			acctflag))
-		goto out_inode;
-
-	d_instantiate(path.dentry, inode);
 	inode->i_size = size;
 	clear_nlink(inode);
 
-	file = alloc_file(&path, FMODE_WRITE | FMODE_READ | FMODE_OPENED,
-			&hugetlbfs_file_operations);
-	if (IS_ERR(file))
-		goto out_dentry; /* inode is already attached */
-
-	return file;
+	if (hugetlb_reserve_pages(inode, 0,
+			size >> huge_page_shift(hstate_inode(inode)), NULL,
+			acctflag))
+		file = ERR_PTR(-ENOMEM);
+	else
+		file = alloc_file_pseudo(inode, mnt, name,
+					FMODE_WRITE | FMODE_READ,
+					&hugetlbfs_file_operations);
+	if (!IS_ERR(file))
+		return file;
 
-out_inode:
 	iput(inode);
-out_dentry:
-	path_put(&path);
-out_shm_unlock:
+out:
 	if (*user) {
 		user_shm_unlock(size, *user);
 		*user = NULL;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 22/27] anon_inode_getfile(): switch to alloc_file_pseudo()
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (19 preceding siblings ...)
  2018-07-09  4:54   ` [RFC][PATCH 21/27] hugetlb_file_setup(): " Al Viro
@ 2018-07-09  4:54   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 23/27] create_pipe_files(): switch the first allocation " Al Viro
                     ` (4 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/anon_inodes.c | 29 ++++++-----------------------
 1 file changed, 6 insertions(+), 23 deletions(-)

diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index bf952939a1d3..7e13edd23db1 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -71,8 +71,6 @@ struct file *anon_inode_getfile(const char *name,
 				const struct file_operations *fops,
 				void *priv, int flags)
 {
-	struct qstr this;
-	struct path path;
 	struct file *file;
 
 	if (IS_ERR(anon_inode_inode))
@@ -82,29 +80,15 @@ struct file *anon_inode_getfile(const char *name,
 		return ERR_PTR(-ENOENT);
 
 	/*
-	 * Link the inode to a directory entry by creating a unique name
-	 * using the inode sequence number.
-	 */
-	file = ERR_PTR(-ENOMEM);
-	this.name = name;
-	this.len = strlen(name);
-	this.hash = 0;
-	path.dentry = d_alloc_pseudo(anon_inode_mnt->mnt_sb, &this);
-	if (!path.dentry)
-		goto err_module;
-
-	path.mnt = mntget(anon_inode_mnt);
-	/*
 	 * We know the anon_inode inode count is always greater than zero,
 	 * so ihold() is safe.
 	 */
 	ihold(anon_inode_inode);
-
-	d_instantiate(path.dentry, anon_inode_inode);
-
-	file = alloc_file(&path, OPEN_FMODE(flags) | FMODE_OPENED, fops);
+	file = alloc_file_pseudo(anon_inode_inode, anon_inode_mnt, name,
+				 OPEN_FMODE(flags), fops);
 	if (IS_ERR(file))
-		goto err_dput;
+		goto err;
+
 	file->f_mapping = anon_inode_inode->i_mapping;
 
 	file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
@@ -112,9 +96,8 @@ struct file *anon_inode_getfile(const char *name,
 
 	return file;
 
-err_dput:
-	path_put(&path);
-err_module:
+err:
+	iput(anon_inode_inode);
 	module_put(fops->owner);
 	return file;
 }
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 23/27] create_pipe_files(): switch the first allocation to alloc_file_pseudo()
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (20 preceding siblings ...)
  2018-07-09  4:54   ` [RFC][PATCH 22/27] anon_inode_getfile(): " Al Viro
@ 2018-07-09  4:54   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 24/27] new helper: alloc_file_clone() Al Viro
                     ` (3 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/pipe.c | 41 ++++++++++-------------------------------
 1 file changed, 10 insertions(+), 31 deletions(-)

diff --git a/fs/pipe.c b/fs/pipe.c
index 4d62c935f675..312af057f03a 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -744,56 +744,35 @@ static struct inode * get_pipe_inode(void)
 
 int create_pipe_files(struct file **res, int flags)
 {
-	int err;
 	struct inode *inode = get_pipe_inode();
 	struct file *f;
-	struct path path;
 
 	if (!inode)
 		return -ENFILE;
 
-	err = -ENOMEM;
-	path.dentry = d_alloc_pseudo(pipe_mnt->mnt_sb, &empty_name);
-	if (!path.dentry)
-		goto err_inode;
-	path.mnt = mntget(pipe_mnt);
-
-	d_instantiate(path.dentry, inode);
-
-	f = alloc_file(&path, FMODE_WRITE, &pipefifo_fops);
+	f = alloc_file_pseudo(inode, pipe_mnt, "", FMODE_WRITE, &pipefifo_fops);
 	if (IS_ERR(f)) {
-		err = PTR_ERR(f);
-		goto err_dentry;
+		free_pipe_info(inode->i_pipe);
+		iput(inode);
+		return PTR_ERR(f);
 	}
 
 	f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT));
 	f->private_data = inode->i_pipe;
 
-	res[0] = alloc_file(&path, FMODE_READ, &pipefifo_fops);
+	res[0] = alloc_file(&f->f_path, FMODE_READ | FMODE_OPENED,
+				&pipefifo_fops);
 	if (IS_ERR(res[0])) {
-		err = PTR_ERR(res[0]);
-		goto err_file;
+		put_pipe_info(inode, inode->i_pipe);
+		fput(f);
+		return PTR_ERR(res[0]);
 	}
 
-	res[0]->f_mode |= FMODE_OPENED;
-	f->f_mode |= FMODE_OPENED;
-	path_get(&path);
+	path_get(&f->f_path);
 	res[0]->private_data = inode->i_pipe;
 	res[0]->f_flags = O_RDONLY | (flags & O_NONBLOCK);
 	res[1] = f;
 	return 0;
-
-err_file:
-	put_filp(f);
-err_dentry:
-	free_pipe_info(inode->i_pipe);
-	path_put(&path);
-	return err;
-
-err_inode:
-	free_pipe_info(inode->i_pipe);
-	iput(inode);
-	return err;
 }
 
 static int __do_pipe_flags(int *fd, struct file **files, int flags)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 24/27] new helper: alloc_file_clone()
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (21 preceding siblings ...)
  2018-07-09  4:54   ` [RFC][PATCH 23/27] create_pipe_files(): switch the first allocation " Al Viro
@ 2018-07-09  4:54   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 25/27] do_shmat(): grab shp->shm_file earlier, switch to alloc_file_clone() Al Viro
                     ` (2 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

alloc_file_clone(old_file, mode, ops): create a new struct file with
->f_path equal to that of old_file.  pipe converted.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/file_table.c      | 11 +++++++++++
 fs/pipe.c            |  5 +----
 include/linux/file.h |  2 ++
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/fs/file_table.c b/fs/file_table.c
index d78bc97f926f..fb7c3b007630 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -209,6 +209,17 @@ struct file *alloc_file_pseudo(struct inode *inode, struct vfsmount *mnt,
 }
 EXPORT_SYMBOL(alloc_file_pseudo);
 
+struct file *alloc_file_clone(struct file *base, fmode_t mode,
+				const struct file_operations *fops)
+{
+	struct file *f = alloc_file(&base->f_path, mode | FMODE_OPENED, fops);
+	if (!IS_ERR(f)) {
+		path_get(&f->f_path);
+		f->f_mapping = base->f_mapping;
+	}
+	return f;
+}
+
 /* the real guts of fput() - releasing the last reference to file
  */
 static void __fput(struct file *file)
diff --git a/fs/pipe.c b/fs/pipe.c
index 312af057f03a..94323a1d7c92 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -760,15 +760,12 @@ int create_pipe_files(struct file **res, int flags)
 	f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT));
 	f->private_data = inode->i_pipe;
 
-	res[0] = alloc_file(&f->f_path, FMODE_READ | FMODE_OPENED,
-				&pipefifo_fops);
+	res[0] = alloc_file_clone(f, FMODE_READ, &pipefifo_fops);
 	if (IS_ERR(res[0])) {
 		put_pipe_info(inode, inode->i_pipe);
 		fput(f);
 		return PTR_ERR(res[0]);
 	}
-
-	path_get(&f->f_path);
 	res[0]->private_data = inode->i_pipe;
 	res[0]->f_flags = O_RDONLY | (flags & O_NONBLOCK);
 	res[1] = f;
diff --git a/include/linux/file.h b/include/linux/file.h
index 37a4d2c166de..c2e38ec2ee7f 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -23,6 +23,8 @@ extern struct file *alloc_file(const struct path *, fmode_t mode,
 	const struct file_operations *fop);
 extern struct file *alloc_file_pseudo(struct inode *, struct vfsmount *,
 	const char *, fmode_t, const struct file_operations *);
+extern struct file *alloc_file_clone(struct file *, fmode_t,
+	const struct file_operations *);
 
 static inline void fput_light(struct file *file, int fput_needed)
 {
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 25/27] do_shmat(): grab shp->shm_file earlier, switch to alloc_file_clone()
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (22 preceding siblings ...)
  2018-07-09  4:54   ` [RFC][PATCH 24/27] new helper: alloc_file_clone() Al Viro
@ 2018-07-09  4:54   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 26/27] make alloc_file() static Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 27/27] turn filp_clone_open() into inline wrapper for dentry_open() Al Viro
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 ipc/shm.c | 39 ++++++++++++++++++---------------------
 1 file changed, 18 insertions(+), 21 deletions(-)

diff --git a/ipc/shm.c b/ipc/shm.c
index e37931121070..0cebcf74b669 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -1354,14 +1354,13 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
 	struct shmid_kernel *shp;
 	unsigned long addr = (unsigned long)shmaddr;
 	unsigned long size;
-	struct file *file;
+	struct file *file, *base;
 	int    err;
 	unsigned long flags = MAP_SHARED;
 	unsigned long prot;
 	int acc_mode;
 	struct ipc_namespace *ns;
 	struct shm_file_data *sfd;
-	struct path path;
 	fmode_t f_mode;
 	unsigned long populate = 0;
 
@@ -1435,46 +1434,44 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
 		goto out_unlock;
 	}
 
-	path = shp->shm_file->f_path;
-	path_get(&path);
+	/*
+	 * We need to take a reference to the real shm file to prevent the
+	 * pointer from becoming stale in cases where the lifetime of the outer
+	 * file extends beyond that of the shm segment.  It's not usually
+	 * possible, but it can happen during remap_file_pages() emulation as
+	 * that unmaps the memory, then does ->mmap() via file reference only.
+	 * We'll deny the ->mmap() if the shm segment was since removed, but to
+	 * detect shm ID reuse we need to compare the file pointers.
+	 */
+	base = get_file(shp->shm_file);
 	shp->shm_nattch++;
-	size = i_size_read(d_inode(path.dentry));
+	size = i_size_read(file_inode(base));
 	ipc_unlock_object(&shp->shm_perm);
 	rcu_read_unlock();
 
 	err = -ENOMEM;
 	sfd = kzalloc(sizeof(*sfd), GFP_KERNEL);
 	if (!sfd) {
-		path_put(&path);
+		fput(base);
 		goto out_nattch;
 	}
 
-	file = alloc_file(&path, f_mode | FMODE_OPENED,
-			  is_file_hugepages(shp->shm_file) ?
+	file = alloc_file_clone(base, f_mode,
+			  is_file_hugepages(base) ?
 				&shm_file_operations_huge :
 				&shm_file_operations);
 	err = PTR_ERR(file);
 	if (IS_ERR(file)) {
 		kfree(sfd);
-		path_put(&path);
+		fput(base);
 		goto out_nattch;
 	}
 
-	file->private_data = sfd;
-	file->f_mapping = shp->shm_file->f_mapping;
 	sfd->id = shp->shm_perm.id;
 	sfd->ns = get_ipc_ns(ns);
-	/*
-	 * We need to take a reference to the real shm file to prevent the
-	 * pointer from becoming stale in cases where the lifetime of the outer
-	 * file extends beyond that of the shm segment.  It's not usually
-	 * possible, but it can happen during remap_file_pages() emulation as
-	 * that unmaps the memory, then does ->mmap() via file reference only.
-	 * We'll deny the ->mmap() if the shm segment was since removed, but to
-	 * detect shm ID reuse we need to compare the file pointers.
-	 */
-	sfd->file = get_file(shp->shm_file);
+	sfd->file = base;
 	sfd->vm_ops = NULL;
+	file->private_data = sfd;
 
 	err = security_mmap_file(file, prot, flags);
 	if (err)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 26/27] make alloc_file() static
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (23 preceding siblings ...)
  2018-07-09  4:54   ` [RFC][PATCH 25/27] do_shmat(): grab shp->shm_file earlier, switch to alloc_file_clone() Al Viro
@ 2018-07-09  4:54   ` Al Viro
  2018-07-09  4:54   ` [RFC][PATCH 27/27] turn filp_clone_open() into inline wrapper for dentry_open() Al Viro
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/file_table.c      | 3 +--
 include/linux/file.h | 2 --
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/fs/file_table.c b/fs/file_table.c
index fb7c3b007630..ffb0036a24f6 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -155,7 +155,7 @@ struct file *get_empty_filp(void)
  * @mode: the mode with which the new file will be opened
  * @fop: the 'struct file_operations' for the new file
  */
-struct file *alloc_file(const struct path *path, fmode_t mode,
+static struct file *alloc_file(const struct path *path, fmode_t mode,
 		const struct file_operations *fop)
 {
 	struct file *file;
@@ -180,7 +180,6 @@ struct file *alloc_file(const struct path *path, fmode_t mode,
 		i_readcount_inc(path->dentry->d_inode);
 	return file;
 }
-EXPORT_SYMBOL(alloc_file);
 
 struct file *alloc_file_pseudo(struct inode *inode, struct vfsmount *mnt,
 				const char *name, fmode_t mode,
diff --git a/include/linux/file.h b/include/linux/file.h
index c2e38ec2ee7f..233780fec647 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -19,8 +19,6 @@ struct vfsmount;
 struct dentry;
 struct inode;
 struct path;
-extern struct file *alloc_file(const struct path *, fmode_t mode,
-	const struct file_operations *fop);
 extern struct file *alloc_file_pseudo(struct inode *, struct vfsmount *,
 	const char *, fmode_t, const struct file_operations *);
 extern struct file *alloc_file_clone(struct file *, fmode_t,
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC][PATCH 27/27] turn filp_clone_open() into inline wrapper for dentry_open()
  2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
                     ` (24 preceding siblings ...)
  2018-07-09  4:54   ` [RFC][PATCH 26/27] make alloc_file() static Al Viro
@ 2018-07-09  4:54   ` Al Viro
  25 siblings, 0 replies; 28+ messages in thread
From: Al Viro @ 2018-07-09  4:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fsdevel, linux-kernel

From: Al Viro <viro@zeniv.linux.org.uk>

it's exactly the same thing as
	dentry_open(&file->f_path, file->f_flags, file->f_cred)

... and rename it to file_clone_open(), while we are at it.
'filp' naming convention is bogus; sure, it's "file pointer",
but we generally don't do that kind of Hungarian notation.
Some of the instances have too many callers to touch, but this
one has only two, so let's sanitize it while we can...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 drivers/gpu/drm/drm_lease.c |  2 +-
 fs/binfmt_misc.c            |  2 +-
 fs/open.c                   | 20 --------------------
 include/linux/fs.h          |  5 ++++-
 4 files changed, 6 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
index d638c0fb3418..b54fb78a283c 100644
--- a/drivers/gpu/drm/drm_lease.c
+++ b/drivers/gpu/drm/drm_lease.c
@@ -553,7 +553,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
 
 	/* Clone the lessor file to create a new file for us */
 	DRM_DEBUG_LEASE("Allocating lease file\n");
-	lessee_file = filp_clone_open(lessor_file);
+	lessee_file = file_clone_open(lessor_file);
 	if (IS_ERR(lessee_file)) {
 		ret = PTR_ERR(lessee_file);
 		goto out_lessee;
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 4b5fff31ef27..aa4a7a23ff99 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -205,7 +205,7 @@ static int load_misc_binary(struct linux_binprm *bprm)
 		goto error;
 
 	if (fmt->flags & MISC_FMT_OPEN_FILE) {
-		interp_file = filp_clone_open(fmt->interp_file);
+		interp_file = file_clone_open(fmt->interp_file);
 		if (!IS_ERR(interp_file))
 			deny_write_access(interp_file);
 	} else {
diff --git a/fs/open.c b/fs/open.c
index 0836c86fd0ce..39dcbf13031c 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -1053,26 +1053,6 @@ struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
 }
 EXPORT_SYMBOL(file_open_root);
 
-struct file *filp_clone_open(struct file *oldfile)
-{
-	struct file *file;
-	int retval;
-
-	file = get_empty_filp();
-	if (IS_ERR(file))
-		return file;
-
-	file->f_flags = oldfile->f_flags;
-	retval = vfs_open(&oldfile->f_path, file, oldfile->f_cred);
-	if (retval) {
-		put_filp(file);
-		return ERR_PTR(retval);
-	}
-
-	return file;
-}
-EXPORT_SYMBOL(filp_clone_open);
-
 long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
 {
 	struct open_flags op;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b3240025ce1a..b3aeb2098fc6 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2426,7 +2426,10 @@ extern struct file *filp_open(const char *, int, umode_t);
 extern struct file *file_open_root(struct dentry *, struct vfsmount *,
 				   const char *, int, umode_t);
 extern struct file * dentry_open(const struct path *, int, const struct cred *);
-extern struct file *filp_clone_open(struct file *);
+static inline struct file *file_clone_open(struct file *file)
+{
+	return dentry_open(&file->f_path, file->f_flags, file->f_cred);
+}
 extern int filp_close(struct file *, fl_owner_t id);
 
 extern struct filename *getname_flags(const char __user *, int, int *);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2018-07-09  4:54 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-09  4:53 [RFC][PATCHES] open()-related cleanups Al Viro
2018-07-09  4:53 ` [RFC][PATCH 01/27] drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() Al Viro
2018-07-09  4:53   ` [RFC][PATCH 02/27] cxl_getfile(): fix double-iput() on alloc_file() failures Al Viro
2018-07-09  4:53   ` [RFC][PATCH 03/27] ocxlflash_getfile(): " Al Viro
2018-07-09  4:53   ` [RFC][PATCH 04/27] make sure do_dentry_open() won't return positive as an error Al Viro
2018-07-09  4:53   ` [RFC][PATCH 05/27] introduce FMODE_OPENED Al Viro
2018-07-09  4:53   ` [RFC][PATCH 06/27] get rid of 'opened' argument of finish_open() Al Viro
2018-07-09  4:53   ` [RFC][PATCH 07/27] lift fput() on late failures into path_openat() Al Viro
2018-07-09  4:53   ` [RFC][PATCH 08/27] switch all remaining checks for FILE_OPENED to FMODE_OPENED Al Viro
2018-07-09  4:53   ` [RFC][PATCH 09/27] now we can fold open_check_o_direct() into do_dentry_open() Al Viro
2018-07-09  4:54   ` [RFC][PATCH 10/27] introduce FMODE_CREATED and switch to it Al Viro
2018-07-09  4:54   ` [RFC][PATCH 11/27] IMA: don't propagate opened through the entire thing Al Viro
2018-07-09  4:54   ` [RFC][PATCH 12/27] Preparation to killing ->atomic_open() 'opened' argument Al Viro
2018-07-09  4:54   ` [RFC][PATCH 13/27] get rid of 'opened' argument of ->atomic_open() Al Viro
2018-07-09  4:54   ` [RFC][PATCH 14/27] get rid of 'opened' in path_openat() and the helpers downstream Al Viro
2018-07-09  4:54   ` [RFC][PATCH 15/27] kill FILE_{CREATED,OPENED} Al Viro
2018-07-09  4:54   ` [RFC][PATCH 16/27] new wrapper: alloc_file_pseudo() Al Viro
2018-07-09  4:54   ` [RFC][PATCH 17/27] __shmem_file_setup(): reorder allocations Al Viro
2018-07-09  4:54   ` [RFC][PATCH 18/27] ... and switch shmem_file_setup() to alloc_file_pseudo() Al Viro
2018-07-09  4:54   ` [RFC][PATCH 19/27] cxl_getfile(): switch " Al Viro
2018-07-09  4:54   ` [RFC][PATCH 20/27] ocxlflash_getfile(): " Al Viro
2018-07-09  4:54   ` [RFC][PATCH 21/27] hugetlb_file_setup(): " Al Viro
2018-07-09  4:54   ` [RFC][PATCH 22/27] anon_inode_getfile(): " Al Viro
2018-07-09  4:54   ` [RFC][PATCH 23/27] create_pipe_files(): switch the first allocation " Al Viro
2018-07-09  4:54   ` [RFC][PATCH 24/27] new helper: alloc_file_clone() Al Viro
2018-07-09  4:54   ` [RFC][PATCH 25/27] do_shmat(): grab shp->shm_file earlier, switch to alloc_file_clone() Al Viro
2018-07-09  4:54   ` [RFC][PATCH 26/27] make alloc_file() static Al Viro
2018-07-09  4:54   ` [RFC][PATCH 27/27] turn filp_clone_open() into inline wrapper for dentry_open() Al Viro

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).