open()-related cleanups
Subsystems (21)
Al Viro
maintainerRFC PATCH 1/1 open()-related cleanups
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:
Al Viro
maintainerRFC PATCH 1/27 drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open()
From: Al Viro <[email protected]>
Failure of ->open() should *not* be followed by fput(). Fixed by using filp_clone_open(), which gets the cleanups right.
--- drivers/gpu/drm/drm_lease.c | 16 +--------------- fs/internal.h | 1 - include/linux/fs.h | 1 + 3 files changed, 2 insertions(+), 16 deletions(-)
drivers/gpu/drm/drm_lease.c +1 -15
@@ -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);
fs/internal.h +0 -1
@@ -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
include/linux/fs.h +1 -0
@@ -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 *);
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 2/27 cxl_getfile(): fix double-iput() on alloc_file() failures
From: Al Viro <[email protected]>
Doing iput() after path_put() is wrong.
--- drivers/misc/cxl/api.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/misc/cxl/api.c +4 -4
@@ -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:
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 3/27 ocxlflash_getfile(): fix double-iput() on alloc_file() failures
In reply to Al ViroFrom: Al Viro <[email protected]>
--- drivers/scsi/cxlflash/ocxl_hw.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/scsi/cxlflash/ocxl_hw.c +2 -3
@@ -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:
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 4/27 make sure do_dentry_open() won't return positive as an error
In reply to Al ViroFrom: Al Viro <[email protected]>
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.
--- fs/open.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/open.c +4 -0
@@ -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);
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 5/27 introduce FMODE_OPENED
In reply to Al ViroFrom: Al Viro <[email protected]>
basically, "is that instance set up enough for regular fput(), or do we want put_filp() for that one".
--- 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(-)
arch/ia64/kernel/perfmon.c +1 -0
@@ -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);
drivers/misc/cxl/api.c +1 -1
@@ -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;
fs/aio.c +2 -1
@@ -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;
fs/anon_inodes.c +1 -1
@@ -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;
fs/hugetlbfs/inode.c +1 -1
@@ -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 */
fs/open.c +2 -1
@@ -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) &&
fs/pipe.c +2 -0
@@ -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 );
include/linux/fs.h +3 -0
@@ -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
ipc/shm.c +1 -1
@@ -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);
mm/shmem.c +1 -1
@@ -3942,7 +3942,7 @@ static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, lif (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;
net/socket.c +1 -1
@@ -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 */
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 6/27 get rid of 'opened' argument of finish_open()
In reply to Al ViroFrom: Al Viro <[email protected]>
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 <[email protected]>
--- 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(-)
fs/9p/vfs_inode.c +1 -1
@@ -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;
fs/9p/vfs_inode_dotl.c +1 -1
@@ -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;
fs/ceph/file.c +1 -1
@@ -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)
fs/cifs/dir.c +1 -1
@@ -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);
fs/fuse/dir.c +1 -1
@@ -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 {
fs/gfs2/inode.c +4 -4
@@ -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 ;
fs/namei.c +5 -1
@@ -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);
fs/nfs/dir.c +1 -1
@@ -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))
fs/open.c +3 -9
@@ -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);
include/linux/fs.h +1 -2
@@ -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 */
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 7/27 lift fput() on late failures into path_openat()
In reply to Al ViroFrom: Al Viro <[email protected]>
--- fs/namei.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-)
fs/namei.c +15 -16
@@ -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,
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 8/27 switch all remaining checks for FILE_OPENED to FMODE_OPENED
In reply to Al ViroFrom: Al Viro <[email protected]>
... and don't bother with setting FILE_OPENED at all.
--- fs/namei.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-)
fs/namei.c +3 -10
@@ -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);
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 9/27 now we can fold open_check_o_direct() into do_dentry_open()
In reply to Al ViroFrom: Al Viro <[email protected]>
--- fs/internal.h | 1 - fs/namei.c | 7 +------ fs/open.c | 27 +++++++++------------------ 3 files changed, 10 insertions(+), 25 deletions(-)
fs/internal.h +0 -1
@@ -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 *);/*
fs/namei.c +1 -6
@@ -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:
fs/open.c +9 -18
@@ -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); } }
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 10/27 introduce FMODE_CREATED and switch to it
In reply to Al ViroFrom: Al Viro <[email protected]>
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).
--- 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(-)
fs/9p/vfs_inode.c +1 -1
@@ -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;
fs/9p/vfs_inode_dotl.c +1 -1
@@ -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);
fs/ceph/file.c +1 -1
@@ -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); }
fs/cifs/dir.c +1 -1
@@ -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) {
fs/fuse/dir.c +1 -1
@@ -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;
fs/gfs2/inode.c +1 -1
@@ -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);
fs/namei.c +8 -7
@@ -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:
fs/nfs/dir.c +4 -1
@@ -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);
fs/nfs/nfs4proc.c +1 -1
@@ -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;
fs/open.c +1 -1
@@ -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);
include/linux/fs.h +1 -0
@@ -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)
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 11/27 IMA: don't propagate opened through the entire thing
In reply to Al ViroFrom: Al Viro <[email protected]>
just check ->f_mode in ima_appraise_measurement()
--- 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(-)
fs/namei.c +1 -2
@@ -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:
fs/nfsd/vfs.c +1 -1
@@ -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;
include/linux/ima.h +2 -2
@@ -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 ; }
security/integrity/ima/ima.h +2 -2
@@ -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; }
security/integrity/ima/ima_appraise.c +2 -2
@@ -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) ||
security/integrity/ima/ima_main.c +8 -8
@@ -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 )
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 12/27 Preparation to killing ->atomic_open() 'opened' argument.
In reply to Al ViroFrom: Al Viro <[email protected]>
__gfs2_lookup(), gfs2_create_inode(), nfs_finish_open() and fuse_create_open() don't need 'opened' anymore. Get rid of that argument in those.
--- fs/fuse/dir.c | 4 ++-- fs/gfs2/inode.c | 19 +++++++++---------- fs/nfs/dir.c | 5 ++--- 3 files changed, 13 insertions(+), 15 deletions(-)
fs/fuse/dir.c +2 -2
@@ -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;
fs/gfs2/inode.c +9 -10
@@ -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); }/*
fs/nfs/dir.c +2 -3
@@ -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:
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 13/27 get rid of 'opened' argument of ->atomic_open()
In reply to Al ViroFrom: Al Viro <[email protected]>
not used anymore
--- 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(-)
fs/9p/vfs_inode.c +1 -2
@@ -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;
fs/9p/vfs_inode_dotl.c +1 -2
@@ -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;
fs/bad_inode.c +1 -1
@@ -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 ; }
fs/ceph/file.c +1 -2
@@ -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;
fs/ceph/super.h +1 -2
@@ -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);
fs/cifs/cifsfs.h +1 -2
@@ -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);
fs/cifs/dir.c +1 -2
@@ -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;
fs/fuse/dir.c +1 -1
@@ -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);
fs/gfs2/inode.c +1 -2
@@ -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 );
fs/namei.c +1 -2
@@ -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) {/*
fs/nfs/dir.c +1 -1
@@ -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;
fs/nfs/nfs4_fs.h +1 -1
@@ -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;
include/linux/fs.h +1 -1
@@ -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 ;
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 14/27 get rid of 'opened' in path_openat() and the helpers downstream
In reply to Al ViroFrom: Al Viro <[email protected]>
unused now
--- fs/namei.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-)
fs/namei.c +8 -14
@@ -3036,8 +3036,7 @@ static int may_o_create(const struct path *dir, struct dentry *dentry, umode_t mstatic 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)) {
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 15/27 kill FILE_{CREATED,OPENED}
In reply to Al ViroFrom: Al Viro <[email protected]>
no users left
--- include/linux/fs.h | 4 ---- 1 file changed, 4 deletions(-)
include/linux/fs.h +0 -4
@@ -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);
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 16/27 new wrapper: alloc_file_pseudo()
In reply to Al ViroFrom: Al Viro <[email protected]>
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
--- 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(-)
fs/aio.c +6 -21
@@ -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))
fs/file_table.c +27 -0
@@ -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)
include/linux/file.h +3 -0
@@ -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) {
net/socket.c +4 -23
@@ -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; }
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 17/27 __shmem_file_setup(): reorder allocations
In reply to Al ViroFrom: Al Viro <[email protected]>
grab inode and reserve memory first.
--- mm/shmem.c | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-)
mm/shmem.c +20 -23
@@ -3918,41 +3918,38 @@ static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, lif (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; }
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 18/27 ... and switch shmem_file_setup() to alloc_file_pseudo()
In reply to Al ViroFrom: Al Viro <[email protected]>
--- mm/shmem.c | 39 ++++++++------------------------------- 1 file changed, 8 insertions(+), 31 deletions(-)
mm/shmem.c +8 -31
@@ -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, lif (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; }
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 19/27 cxl_getfile(): switch to alloc_file_pseudo()
In reply to Al ViroFrom: Al Viro <[email protected]>
--- drivers/misc/cxl/api.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-)
drivers/misc/cxl/api.c +4 -17
@@ -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;
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 20/27 ocxlflash_getfile(): switch to alloc_file_pseudo()
In reply to Al ViroFrom: Al Viro <[email protected]>
--- drivers/scsi/cxlflash/ocxl_hw.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-)
drivers/scsi/cxlflash/ocxl_hw.c +4 -19
@@ -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 );
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 21/27 hugetlb_file_setup(): switch to alloc_file_pseudo()
In reply to Al ViroFrom: Al Viro <[email protected]>
--- fs/hugetlbfs/inode.c | 55 ++++++++++++++++------------------------------------ 1 file changed, 17 insertions(+), 38 deletions(-)
fs/hugetlbfs/inode.c +17 -38
@@ -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 ;
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 22/27 anon_inode_getfile(): switch to alloc_file_pseudo()
In reply to Al ViroFrom: Al Viro <[email protected]>
--- fs/anon_inodes.c | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-)
fs/anon_inodes.c +6 -23
@@ -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; }
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 23/27 create_pipe_files(): switch the first allocation to alloc_file_pseudo()
In reply to Al ViroFrom: Al Viro <[email protected]>
--- fs/pipe.c | 41 ++++++++++------------------------------- 1 file changed, 10 insertions(+), 31 deletions(-)
fs/pipe.c +10 -31
@@ -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)
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 24/27 new helper: alloc_file_clone()
In reply to Al ViroFrom: Al Viro <[email protected]>
alloc_file_clone(old_file, mode, ops): create a new struct file with ->f_path equal to that of old_file. pipe converted.
--- fs/file_table.c | 11 +++++++++++ fs/pipe.c | 5 +---- include/linux/file.h | 2 ++ 3 files changed, 14 insertions(+), 4 deletions(-)
fs/file_table.c +11 -0
@@ -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)
fs/pipe.c +1 -4
@@ -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;
include/linux/file.h +2 -0
@@ -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) {
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 25/27 do_shmat(): grab shp->shm_file earlier, switch to alloc_file_clone()
In reply to Al ViroFrom: Al Viro <[email protected]>
--- ipc/shm.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-)
ipc/shm.c +18 -21
@@ -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)
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 26/27 make alloc_file() static
In reply to Al ViroFrom: Al Viro <[email protected]>
--- fs/file_table.c | 3 +-- include/linux/file.h | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-)
fs/file_table.c +1 -2
@@ -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,
include/linux/file.h +0 -2
@@ -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,
Signature · 1 line
2.11.0
Al Viro
maintainerRFC PATCH 27/27 turn filp_clone_open() into inline wrapper for dentry_open()
In reply to Al ViroFrom: Al Viro <[email protected]>
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...
--- 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(-)
drivers/gpu/drm/drm_lease.c +1 -1
@@ -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;
fs/binfmt_misc.c +1 -1
@@ -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 {
fs/open.c +0 -20
@@ -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;
include/linux/fs.h +4 -1
@@ -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 *);
Signature · 1 line
2.11.0