You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'work.open3' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs open-related updates from Al Viro:
- "do we need fput() or put_filp()" rules are gone - it's always fput()
now. We keep track of that state where it belongs - in ->f_mode.
- int *opened mess killed - in finish_open(), in ->atomic_open()
instances and in fs/namei.c code around do_last()/lookup_open()/atomic_open().
- alloc_file() wrappers with saner calling conventions are introduced
(alloc_file_clone() and alloc_file_pseudo()); callers converted, with
much simplification.
- while we are at it, saner calling conventions for path_init() and
link_path_walk(), simplifying things inside fs/namei.c (both on
open-related paths and elsewhere).
* 'work.open3' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (40 commits)
few more cleanups of link_path_walk() callers
allow link_path_walk() to take ERR_PTR()
make path_init() unconditionally paired with terminate_walk()
document alloc_file() changes
make alloc_file() static
do_shmat(): grab shp->shm_file earlier, switch to alloc_file_clone()
new helper: alloc_file_clone()
create_pipe_files(): switch the first allocation to alloc_file_pseudo()
anon_inode_getfile(): switch to alloc_file_pseudo()
hugetlb_file_setup(): switch to alloc_file_pseudo()
ocxlflash_getfile(): switch to alloc_file_pseudo()
cxl_getfile(): switch to alloc_file_pseudo()
... and switch shmem_file_setup() to alloc_file_pseudo()
__shmem_file_setup(): reorder allocations
new wrapper: alloc_file_pseudo()
kill FILE_{CREATED,OPENED}
switch atomic_open() and lookup_open() to returning 0 in all success cases
document ->atomic_open() changes
->atomic_open(): return 0 in all success cases
get rid of 'opened' in path_openat() and the helpers downstream
...
This commit is contained in:
@@ -64,7 +64,7 @@ prototypes:
|
||||
void (*update_time)(struct inode *, struct timespec *, 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);
|
||||
|
||||
locking rules:
|
||||
|
||||
@@ -602,3 +602,23 @@ in your dentry operations instead.
|
||||
dentry separately, and it now has request_mask and query_flags arguments
|
||||
to specify the fields and sync type requested by statx. Filesystems not
|
||||
supporting any statx-specific features may ignore the new arguments.
|
||||
--
|
||||
[mandatory]
|
||||
->atomic_open() calling conventions have changed. Gone is int *opened,
|
||||
along with FILE_OPENED/FILE_CREATED. In place of those we have
|
||||
FMODE_OPENED/FMODE_CREATED, set in file->f_mode. Additionally, return
|
||||
value for 'called finish_no_open(), open it yourself' case has become
|
||||
0, not 1. Since finish_no_open() itself is returning 0 now, that part
|
||||
does not need any changes in ->atomic_open() instances.
|
||||
--
|
||||
[mandatory]
|
||||
alloc_file() has become static now; two wrappers are to be used instead.
|
||||
alloc_file_pseudo(inode, vfsmount, name, flags, ops) is for the cases
|
||||
when dentry needs to be created; that's the majority of old alloc_file()
|
||||
users. Calling conventions: on success a reference to new struct file
|
||||
is returned and callers reference to inode is subsumed by that. On
|
||||
failure, ERR_PTR() is returned and no caller's references are affected,
|
||||
so the caller needs to drop the inode reference it held.
|
||||
alloc_file_clone(file, flags, ops) does not affect any caller's references.
|
||||
On success you get a new struct file sharing the mount/dentry with the
|
||||
original, on failure - ERR_PTR().
|
||||
|
||||
@@ -386,7 +386,7 @@ struct inode_operations {
|
||||
ssize_t (*listxattr) (struct dentry *, char *, size_t);
|
||||
void (*update_time)(struct inode *, struct timespec *, int);
|
||||
int (*atomic_open)(struct inode *, struct dentry *, struct file *,
|
||||
unsigned open_flag, umode_t create_mode, int *opened);
|
||||
unsigned open_flag, umode_t create_mode);
|
||||
int (*tmpfile) (struct inode *, struct dentry *, umode_t);
|
||||
};
|
||||
|
||||
@@ -496,13 +496,15 @@ otherwise noted.
|
||||
|
||||
atomic_open: called on the last component of an open. Using this optional
|
||||
method the filesystem can look up, possibly create and open the file in
|
||||
one atomic operation. If it cannot perform this (e.g. the file type
|
||||
turned out to be wrong) it may signal this by returning 1 instead of
|
||||
usual 0 or -ve . This method is only called if the last component is
|
||||
negative or needs lookup. Cached positive dentries are still handled by
|
||||
f_op->open(). If the file was created, the FILE_CREATED flag should be
|
||||
set in "opened". In case of O_EXCL the method must only succeed if the
|
||||
file didn't exist and hence FILE_CREATED shall always be set on success.
|
||||
one atomic operation. If it wants to leave actual opening to the
|
||||
caller (e.g. if the file turned out to be a symlink, device, or just
|
||||
something filesystem won't do atomic open for), it may signal this by
|
||||
returning finish_no_open(file, dentry). This method is only called if
|
||||
the last component is negative or needs lookup. Cached positive dentries
|
||||
are still handled by f_op->open(). If the file was created,
|
||||
FMODE_CREATED flag should be set in file->f_mode. In case of O_EXCL
|
||||
the method must only succeed if the file didn't exist and hence FMODE_CREATED
|
||||
shall always be set on success.
|
||||
|
||||
tmpfile: called in the end of O_TMPFILE open(). Optional, equivalent to
|
||||
atomically creating, opening and unlinking a file in given directory.
|
||||
|
||||
@@ -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;
|
||||
|
||||
+4
-18
@@ -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,23 +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,
|
||||
flags & (O_ACCMODE | O_NONBLOCK), 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), fops);
|
||||
if (IS_ERR(file)) {
|
||||
path_put(&path);
|
||||
goto err_fs;
|
||||
}
|
||||
file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
|
||||
file->private_data = priv;
|
||||
|
||||
return file;
|
||||
|
||||
@@ -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,29 +114,15 @@ 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,
|
||||
flags & (O_ACCMODE | O_NONBLOCK), 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);
|
||||
file->private_data = priv;
|
||||
out:
|
||||
return file;
|
||||
|
||||
+3
-4
@@ -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;
|
||||
@@ -917,7 +916,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;
|
||||
|
||||
@@ -925,7 +924,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;
|
||||
|
||||
@@ -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;
|
||||
@@ -352,13 +351,13 @@ 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;
|
||||
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);
|
||||
|
||||
@@ -202,9 +202,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);
|
||||
@@ -213,31 +211,17 @@ 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]",
|
||||
O_RDWR, &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, &aio_ring_fops);
|
||||
if (IS_ERR(file)) {
|
||||
path_put(&path);
|
||||
return file;
|
||||
}
|
||||
|
||||
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))
|
||||
|
||||
+6
-24
@@ -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))
|
||||
@@ -81,40 +79,24 @@ struct file *anon_inode_getfile(const char *name,
|
||||
if (fops->owner && !try_module_get(fops->owner))
|
||||
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), fops);
|
||||
file = alloc_file_pseudo(anon_inode_inode, anon_inode_mnt, name,
|
||||
flags & (O_ACCMODE | O_NONBLOCK), 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);
|
||||
file->private_data = priv;
|
||||
|
||||
return file;
|
||||
|
||||
err_dput:
|
||||
path_put(&path);
|
||||
err_module:
|
||||
err:
|
||||
iput(anon_inode_inode);
|
||||
module_put(fops->owner);
|
||||
return file;
|
||||
}
|
||||
|
||||
+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;
|
||||
}
|
||||
|
||||
+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 {
|
||||
|
||||
+3
-4
@@ -429,8 +429,7 @@ out:
|
||||
* 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;
|
||||
@@ -507,9 +506,9 @@ 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, opened);
|
||||
err = finish_open(file, dentry, ceph_open);
|
||||
}
|
||||
out_req:
|
||||
if (!req->r_err && req->r_target_inode)
|
||||
|
||||
+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);
|
||||
|
||||
+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);
|
||||
|
||||
+3
-4
@@ -465,8 +465,7 @@ out_err:
|
||||
|
||||
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;
|
||||
@@ -539,9 +538,9 @@ 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, opened);
|
||||
rc = finish_open(file, direntry, generic_file_open);
|
||||
if (rc) {
|
||||
if (server->ops->close)
|
||||
server->ops->close(xid, tcon, &fid);
|
||||
|
||||
+58
-27
@@ -51,6 +51,7 @@ static void file_free_rcu(struct rcu_head *head)
|
||||
|
||||
static inline void file_free(struct file *f)
|
||||
{
|
||||
security_file_free(f);
|
||||
percpu_counter_dec(&nr_files);
|
||||
call_rcu(&f->f_u.fu_rcuhead, file_free_rcu);
|
||||
}
|
||||
@@ -100,9 +101,8 @@ int proc_nr_files(struct ctl_table *table, int write,
|
||||
* done, you will imbalance int the mount's writer count
|
||||
* and a warning at __fput() time.
|
||||
*/
|
||||
struct file *get_empty_filp(void)
|
||||
struct file *alloc_empty_file(int flags, const struct cred *cred)
|
||||
{
|
||||
const struct cred *cred = current_cred();
|
||||
static long old_max;
|
||||
struct file *f;
|
||||
int error;
|
||||
@@ -123,11 +123,10 @@ struct file *get_empty_filp(void)
|
||||
if (unlikely(!f))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
percpu_counter_inc(&nr_files);
|
||||
f->f_cred = get_cred(cred);
|
||||
error = security_file_alloc(f);
|
||||
if (unlikely(error)) {
|
||||
file_free(f);
|
||||
file_free_rcu(&f->f_u.fu_rcuhead);
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
|
||||
@@ -136,7 +135,10 @@ struct file *get_empty_filp(void)
|
||||
spin_lock_init(&f->f_lock);
|
||||
mutex_init(&f->f_pos_lock);
|
||||
eventpoll_init_file(f);
|
||||
f->f_flags = flags;
|
||||
f->f_mode = OPEN_FMODE(flags);
|
||||
/* f->f_version: 0 */
|
||||
percpu_counter_inc(&nr_files);
|
||||
return f;
|
||||
|
||||
over:
|
||||
@@ -152,15 +154,15 @@ over:
|
||||
* alloc_file - allocate and initialize a 'struct file'
|
||||
*
|
||||
* @path: the (dentry, vfsmount) pair for the new file
|
||||
* @mode: the mode with which the new file will be opened
|
||||
* @flags: O_... flags 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, int flags,
|
||||
const struct file_operations *fop)
|
||||
{
|
||||
struct file *file;
|
||||
|
||||
file = get_empty_filp();
|
||||
file = alloc_empty_file(flags, current_cred());
|
||||
if (IS_ERR(file))
|
||||
return file;
|
||||
|
||||
@@ -168,19 +170,56 @@ struct file *alloc_file(const struct path *path, fmode_t mode,
|
||||
file->f_inode = path->dentry->d_inode;
|
||||
file->f_mapping = path->dentry->d_inode->i_mapping;
|
||||
file->f_wb_err = filemap_sample_wb_err(file->f_mapping);
|
||||
if ((mode & FMODE_READ) &&
|
||||
if ((file->f_mode & FMODE_READ) &&
|
||||
likely(fop->read || fop->read_iter))
|
||||
mode |= FMODE_CAN_READ;
|
||||
if ((mode & FMODE_WRITE) &&
|
||||
file->f_mode |= FMODE_CAN_READ;
|
||||
if ((file->f_mode & FMODE_WRITE) &&
|
||||
likely(fop->write || fop->write_iter))
|
||||
mode |= FMODE_CAN_WRITE;
|
||||
file->f_mode = mode;
|
||||
file->f_mode |= FMODE_CAN_WRITE;
|
||||
file->f_mode |= FMODE_OPENED;
|
||||
file->f_op = fop;
|
||||
if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
|
||||
if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
|
||||
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, int flags,
|
||||
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, flags, fops);
|
||||
if (IS_ERR(file)) {
|
||||
ihold(inode);
|
||||
path_put(&path);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
EXPORT_SYMBOL(alloc_file_pseudo);
|
||||
|
||||
struct file *alloc_file_clone(struct file *base, int flags,
|
||||
const struct file_operations *fops)
|
||||
{
|
||||
struct file *f = alloc_file(&base->f_path, flags, 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
|
||||
*/
|
||||
@@ -190,6 +229,9 @@ static void __fput(struct file *file)
|
||||
struct vfsmount *mnt = file->f_path.mnt;
|
||||
struct inode *inode = file->f_inode;
|
||||
|
||||
if (unlikely(!(file->f_mode & FMODE_OPENED)))
|
||||
goto out;
|
||||
|
||||
might_sleep();
|
||||
|
||||
fsnotify_close(file);
|
||||
@@ -207,7 +249,6 @@ static void __fput(struct file *file)
|
||||
}
|
||||
if (file->f_op->release)
|
||||
file->f_op->release(inode, file);
|
||||
security_file_free(file);
|
||||
if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL &&
|
||||
!(file->f_mode & FMODE_PATH))) {
|
||||
cdev_put(inode->i_cdev);
|
||||
@@ -220,12 +261,10 @@ static void __fput(struct file *file)
|
||||
put_write_access(inode);
|
||||
__mnt_drop_write(mnt);
|
||||
}
|
||||
file->f_path.dentry = NULL;
|
||||
file->f_path.mnt = NULL;
|
||||
file->f_inode = NULL;
|
||||
file_free(file);
|
||||
dput(dentry);
|
||||
mntput(mnt);
|
||||
out:
|
||||
file_free(file);
|
||||
}
|
||||
|
||||
static LLIST_HEAD(delayed_fput_list);
|
||||
@@ -300,14 +339,6 @@ void __fput_sync(struct file *file)
|
||||
|
||||
EXPORT_SYMBOL(fput);
|
||||
|
||||
void put_filp(struct file *file)
|
||||
{
|
||||
if (atomic_long_dec_and_test(&file->f_count)) {
|
||||
security_file_free(file);
|
||||
file_free(file);
|
||||
}
|
||||
}
|
||||
|
||||
void __init files_init(void)
|
||||
{
|
||||
filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,
|
||||
|
||||
+5
-5
@@ -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;
|
||||
@@ -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 {
|
||||
@@ -489,7 +489,7 @@ out_err:
|
||||
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);
|
||||
@@ -508,12 +508,12 @@ 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;
|
||||
|
||||
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;
|
||||
|
||||
+15
-17
@@ -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;
|
||||
@@ -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);
|
||||
}
|
||||
@@ -767,8 +767,8 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
||||
mark_inode_dirty(inode);
|
||||
d_instantiate(dentry, inode);
|
||||
if (file) {
|
||||
*opened |= FILE_CREATED;
|
||||
error = finish_open(file, dentry, gfs2_open_common, opened);
|
||||
file->f_mode |= FMODE_CREATED;
|
||||
error = finish_open(file, dentry, gfs2_open_common);
|
||||
}
|
||||
gfs2_glock_dq_uninit(ghs);
|
||||
gfs2_glock_dq_uninit(ghs + 1);
|
||||
@@ -822,7 +822,7 @@ fail:
|
||||
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;
|
||||
@@ -866,7 +865,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) {
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1229,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);
|
||||
@@ -1244,13 +1242,13 @@ 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)
|
||||
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;
|
||||
@@ -1262,7 +1260,7 @@ skip_lookup:
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+16
-38
@@ -1310,10 +1310,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.
|
||||
@@ -1322,19 +1318,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()) {
|
||||
@@ -1350,45 +1345,28 @@ 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,
|
||||
&hugetlbfs_file_operations);
|
||||
if (IS_ERR(file))
|
||||
goto out_dentry; /* inode is already attached */
|
||||
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, O_RDWR,
|
||||
&hugetlbfs_file_operations);
|
||||
if (!IS_ERR(file))
|
||||
return 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;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user