@@ -141,7 +141,8 @@ static int hypfs_open(struct inode *inode, struct file *filp)
return nonseekable_open(inode, filp);
}
-static ssize_t hypfs_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t hypfs_read_iter(struct kiocb *iocb, struct iov_iter *to,
+ bool rwf)
{
struct file *file = iocb->ki_filp;
char *data = file->private_data;
@@ -539,7 +539,7 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
if (rw == WRITE)
ret = call_write_iter(file, &cmd->iocb, &iter);
else
- ret = call_read_iter(file, &cmd->iocb, &iter);
+ ret = call_read_iter(file, &cmd->iocb, &iter, 0);
lo_rw_aio_do_completion(cmd);
@@ -635,7 +635,8 @@ static ssize_t write_null(struct file *file, const char __user *buf,
return count;
}
-static ssize_t read_iter_null(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t read_iter_null(struct kiocb *iocb, struct iov_iter *to,
+ bool rwf)
{
return 0;
}
@@ -659,7 +660,8 @@ static ssize_t splice_write_null(struct pipe_inode_info *pipe, struct file *out,
return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null);
}
-static ssize_t read_iter_zero(struct kiocb *iocb, struct iov_iter *iter)
+static ssize_t read_iter_zero(struct kiocb *iocb, struct iov_iter *iter,
+ bool rwf)
{
size_t written = 0;
@@ -141,7 +141,8 @@ static loff_t auxdev_llseek(struct file *file, loff_t offset, int whence)
return fixed_size_llseek(file, offset, whence, AUX_MAX_OFFSET);
}
-static ssize_t auxdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t auxdev_read_iter(struct kiocb *iocb, struct iov_iter *to,
+ bool rwf)
{
struct drm_dp_aux_dev *aux_dev = iocb->ki_filp->private_data;
loff_t pos = iocb->ki_pos;
@@ -869,7 +869,8 @@ static ssize_t tap_do_read(struct tap_queue *q,
return ret;
}
-static ssize_t tap_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t tap_read_iter(struct kiocb *iocb, struct iov_iter *to,
+ bool rwf)
{
struct file *file = iocb->ki_filp;
struct tap_queue *q = file->private_data;
@@ -1750,7 +1750,8 @@ static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
return ret;
}
-static ssize_t tun_chr_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t tun_chr_read_iter(struct kiocb *iocb, struct iov_iter *to,
+ bool rwf)
{
struct file *file = iocb->ki_filp;
struct tun_file *tfile = file->private_data;
@@ -294,7 +294,8 @@ static int ashmem_release(struct inode *ignored, struct file *file)
return 0;
}
-static ssize_t ashmem_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+static ssize_t ashmem_read_iter(struct kiocb *iocb, struct iov_iter *iter,
+ bool rwf)
{
struct ashmem_area *asma = iocb->ki_filp->private_data;
int ret = 0;
@@ -1150,7 +1150,8 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,
return result > 0 ? result : rc;
}
-static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to,
+ bool rwf)
{
struct lu_env *env;
struct vvp_io_args *args;
@@ -719,7 +719,7 @@ static int vvp_io_read_start(const struct lu_env *env,
/* BUG: 5972 */
file_accessed(file);
LASSERT(vio->vui_iocb->ki_pos == pos);
- result = generic_file_read_iter(vio->vui_iocb, vio->vui_iter);
+ result = generic_file_read_iter(vio->vui_iocb, vio->vui_iter, 0);
out:
if (result >= 0) {
@@ -1123,7 +1123,8 @@ static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from)
return res;
}
-static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to)
+static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to,
+ bool rwf)
{
struct ffs_io_data io_data, *p = &io_data;
ssize_t res;
@@ -572,7 +572,7 @@ static ssize_t ep_aio(struct kiocb *iocb,
}
static ssize_t
-ep_read_iter(struct kiocb *iocb, struct iov_iter *to)
+ep_read_iter(struct kiocb *iocb, struct iov_iter *to, bool rwf)
{
struct file *file = iocb->ki_filp;
struct ep_data *epdata = file->private_data;
@@ -1337,7 +1337,8 @@ static long vhost_net_compat_ioctl(struct file *f, unsigned int ioctl,
}
#endif
-static ssize_t vhost_net_chr_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t vhost_net_chr_read_iter(struct kiocb *iocb, struct iov_iter *to,
+ bool rwf)
{
struct file *file = iocb->ki_filp;
struct vhost_net *n = file->private_data;
@@ -375,11 +375,12 @@ static int v9fs_file_flock_dotl(struct file *filp, int cmd,
* @udata: user data buffer to read data into
* @count: size of buffer
* @offset: offset at which to read data
+ * @rwf: i_rwsem taken exclusively
*
*/
static ssize_t
-v9fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+v9fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to, bool rwf)
{
struct p9_fid *fid = iocb->ki_filp->private_data;
int ret, err = 0;
@@ -569,13 +570,14 @@ v9fs_vm_page_mkwrite(struct vm_fault *vmf)
* @data: user data buffer to read data into
* @count: size of buffer
* @offset: offset at which to read data
+ * @rwf: i_rwsem taken exclusively
*
*/
static ssize_t
-v9fs_mmap_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+v9fs_mmap_file_read_iter(struct kiocb *iocb, struct iov_iter *to, bool rwf)
{
/* TODO: Check if there are dirty pages */
- return v9fs_file_read_iter(iocb, to);
+ return v9fs_file_read_iter(iocb, to, rwf);
}
/**
@@ -1508,7 +1508,7 @@ static ssize_t aio_read(struct kiocb *req, struct iocb *iocb, bool vectored,
return ret;
ret = rw_verify_area(READ, file, &req->ki_pos, iov_iter_count(&iter));
if (!ret)
- ret = aio_ret(req, call_read_iter(file, req, &iter));
+ ret = aio_ret(req, call_read_iter(file, req, &iter, 0));
kfree(iovec);
return ret;
}
@@ -1908,7 +1908,7 @@ ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
}
EXPORT_SYMBOL_GPL(blkdev_write_iter);
-ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
+ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to, bool rwf)
{
struct file *file = iocb->ki_filp;
struct inode *bd_inode = bdev_file_inode(file);
@@ -1920,7 +1920,7 @@ ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
size -= pos;
iov_iter_truncate(to, size);
- return generic_file_read_iter(iocb, to);
+ return generic_file_read_iter(iocb, to, rwf);
}
EXPORT_SYMBOL_GPL(blkdev_read_iter);
@@ -1153,7 +1153,8 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
*
* Hmm, the sync read case isn't actually async... should it be?
*/
-static ssize_t ceph_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t ceph_read_iter(struct kiocb *iocb, struct iov_iter *to,
+ bool rwf)
{
struct file *filp = iocb->ki_filp;
struct ceph_file_info *fi = filp->private_data;
@@ -1202,7 +1203,7 @@ static ssize_t ceph_read_iter(struct kiocb *iocb, struct iov_iter *to)
inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len,
ceph_cap_string(got));
current->journal_info = filp;
- ret = generic_file_read_iter(iocb, to);
+ ret = generic_file_read_iter(iocb, to, rwf);
current->journal_info = NULL;
}
dout("aio_read %p %llx.%llx dropping cap refs on %s = %d\n",
@@ -765,19 +765,19 @@ cifs_do_mount(struct file_system_type *fs_type,
}
static ssize_t
-cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter, bool rwf)
{
ssize_t rc;
struct inode *inode = file_inode(iocb->ki_filp);
if (iocb->ki_filp->f_flags & O_DIRECT)
- return cifs_user_readv(iocb, iter);
+ return cifs_user_readv(iocb, iter, rwf);
rc = cifs_revalidate_mapping(inode);
if (rc)
return rc;
- return generic_file_read_iter(iocb, iter);
+ return generic_file_read_iter(iocb, iter, rwf);
}
static ssize_t cifs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
@@ -101,8 +101,8 @@ extern const struct file_operations cifs_file_strict_nobrl_ops;
extern int cifs_open(struct inode *inode, struct file *file);
extern int cifs_close(struct inode *inode, struct file *file);
extern int cifs_closedir(struct inode *inode, struct file *file);
-extern ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to);
-extern ssize_t cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to);
+extern ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to, bool rwf);
+extern ssize_t cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to, bool rwf);
extern ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from);
extern ssize_t cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from);
extern int cifs_lock(struct file *, int, struct file_lock *);
@@ -3249,7 +3249,7 @@ collect_uncached_read_data(struct cifs_aio_ctx *ctx)
complete(&ctx->done);
}
-ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to)
+ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to, bool rwf)
{
struct file *file = iocb->ki_filp;
ssize_t rc;
@@ -3337,7 +3337,7 @@ ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to)
}
ssize_t
-cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to)
+cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to, bool rwf)
{
struct inode *inode = file_inode(iocb->ki_filp);
struct cifsInodeInfo *cinode = CIFS_I(inode);
@@ -3356,12 +3356,12 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to)
* pos+len-1.
*/
if (!CIFS_CACHE_READ(cinode))
- return cifs_user_readv(iocb, to);
+ return cifs_user_readv(iocb, to, rwf);
if (cap_unix(tcon->ses) &&
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
- return generic_file_read_iter(iocb, to);
+ return generic_file_read_iter(iocb, to, rwf);
/*
* We need to hold the sem to be sure nobody modifies lock list
@@ -3371,7 +3371,7 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to)
if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(to),
tcon->ses->server->vals->shared_lock_type,
NULL, CIFS_READ_OP))
- rc = generic_file_read_iter(iocb, to);
+ rc = generic_file_read_iter(iocb, to, rwf);
up_read(&cinode->lock_sem);
return rc;
}
@@ -27,7 +27,7 @@
#include "coda_int.h"
static ssize_t
-coda_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+coda_file_read_iter(struct kiocb *iocb, struct iov_iter *to, bool rwf)
{
struct file *coda_file = iocb->ki_filp;
struct coda_file_info *cfi = CODA_FTOC(coda_file);
@@ -44,13 +44,13 @@
* The function to be used for directory reads is ecryptfs_read.
*/
static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
- struct iov_iter *to)
+ struct iov_iter *to, bool rwf)
{
ssize_t rc;
struct path *path;
struct file *file = iocb->ki_filp;
- rc = generic_file_read_iter(iocb, to);
+ rc = generic_file_read_iter(iocb, to, rwf);
if (rc >= 0) {
path = ecryptfs_dentry_to_lower_path(file->f_path.dentry);
touch_atime(path);
@@ -65,7 +65,7 @@ static ssize_t efivarfs_file_write(struct file *file,
}
static ssize_t efivarfs_file_read_iter(struct kiocb *iocb,
- struct iov_iter *iter)
+ struct iov_iter *iter, bool rwf)
{
struct file *file = iocb->ki_filp;
struct efivar_entry *var = file->private_data;
@@ -29,7 +29,8 @@
#include "acl.h"
#ifdef CONFIG_FS_DAX
-static ssize_t ext2_dax_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t ext2_dax_read_iter(struct kiocb *iocb, struct iov_iter *to,
+ bool rwf)
{
struct inode *inode = iocb->ki_filp->f_mapping->host;
ssize_t ret;
@@ -160,13 +161,14 @@ int ext2_fsync(struct file *file, loff_t start, loff_t end, int datasync)
return ret;
}
-static ssize_t ext2_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t ext2_file_read_iter(struct kiocb *iocb, struct iov_iter *to,
+ bool rwf)
{
#ifdef CONFIG_FS_DAX
if (IS_DAX(iocb->ki_filp->f_mapping->host))
- return ext2_dax_read_iter(iocb, to);
+ return ext2_dax_read_iter(iocb, to, rwf);
#endif
- return generic_file_read_iter(iocb, to);
+ return generic_file_read_iter(iocb, to, rwf);
}
static ssize_t ext2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
@@ -32,7 +32,8 @@
#include "acl.h"
#ifdef CONFIG_FS_DAX
-static ssize_t ext4_dax_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t ext4_dax_read_iter(struct kiocb *iocb, struct iov_iter *to,
+ bool rwf)
{
struct inode *inode = file_inode(iocb->ki_filp);
ssize_t ret;
@@ -49,7 +50,7 @@ static ssize_t ext4_dax_read_iter(struct kiocb *iocb, struct iov_iter *to)
if (!IS_DAX(inode)) {
inode_unlock_shared(inode);
/* Fallback to buffered IO in case we cannot support DAX */
- return generic_file_read_iter(iocb, to);
+ return generic_file_read_iter(iocb, to, rwf);
}
ret = dax_iomap_rw(iocb, to, &ext4_iomap_ops);
inode_unlock_shared(inode);
@@ -59,7 +60,8 @@ static ssize_t ext4_dax_read_iter(struct kiocb *iocb, struct iov_iter *to)
}
#endif
-static ssize_t ext4_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t ext4_file_read_iter(struct kiocb *iocb, struct iov_iter *to,
+ bool rwf)
{
if (unlikely(ext4_forced_shutdown(EXT4_SB(file_inode(iocb->ki_filp)->i_sb))))
return -EIO;
@@ -69,9 +71,9 @@ static ssize_t ext4_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
#ifdef CONFIG_FS_DAX
if (IS_DAX(file_inode(iocb->ki_filp)))
- return ext4_dax_read_iter(iocb, to);
+ return ext4_dax_read_iter(iocb, to, rwf);
#endif
- return generic_file_read_iter(iocb, to);
+ return generic_file_read_iter(iocb, to, rwf);
}
/*
@@ -88,7 +88,8 @@ static struct list_head *cuse_conntbl_head(dev_t devt)
* FUSE file.
*/
-static ssize_t cuse_read_iter(struct kiocb *kiocb, struct iov_iter *to)
+static ssize_t cuse_read_iter(struct kiocb *kiocb, struct iov_iter *to,
+ bool rwf)
{
struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(kiocb);
loff_t pos = 0;
@@ -1331,7 +1331,8 @@ static int fuse_dev_open(struct inode *inode, struct file *file)
return 0;
}
-static ssize_t fuse_dev_read(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t fuse_dev_read(struct kiocb *iocb, struct iov_iter *to,
+ bool rwf)
{
struct fuse_copy_state cs;
struct file *file = iocb->ki_filp;
@@ -913,7 +913,8 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
return err;
}
-static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to,
+ bool rwf)
{
struct inode *inode = iocb->ki_filp->f_mapping->host;
struct fuse_conn *fc = get_fuse_conn(inode);
@@ -931,7 +932,7 @@ static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
return err;
}
- return generic_file_read_iter(iocb, to);
+ return generic_file_read_iter(iocb, to, rwf);
}
static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff,
@@ -1421,7 +1422,8 @@ static ssize_t __fuse_direct_read(struct fuse_io_priv *io,
return res;
}
-static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to,
+ bool rwf)
{
struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb);
return __fuse_direct_read(&io, to, &iocb->ki_pos);
@@ -248,7 +248,8 @@ hugetlbfs_read_actor(struct page *page, unsigned long offset,
* data. Its *very* similar to do_generic_mapping_read(), we can't use that
* since it has PAGE_SIZE assumptions.
*/
-static ssize_t hugetlbfs_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t hugetlbfs_read_iter(struct kiocb *iocb, struct iov_iter *to,
+ bool rwf)
{
struct file *file = iocb->ki_filp;
struct hstate *h = hstate_file(file);
@@ -98,7 +98,7 @@ int ncp_make_open(struct inode *inode, int right)
}
static ssize_t
-ncp_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+ncp_file_read_iter(struct kiocb *iocb, struct iov_iter *to, bool rwf)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file);
@@ -151,7 +151,7 @@ nfs_file_flush(struct file *file, fl_owner_t id)
}
ssize_t
-nfs_file_read(struct kiocb *iocb, struct iov_iter *to)
+nfs_file_read(struct kiocb *iocb, struct iov_iter *to, bool rwf)
{
struct inode *inode = file_inode(iocb->ki_filp);
ssize_t result;
@@ -166,7 +166,7 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to)
nfs_start_io_read(inode);
result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
if (!result) {
- result = generic_file_read_iter(iocb, to);
+ result = generic_file_read_iter(iocb, to, rwf);
if (result > 0)
nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, result);
}
@@ -368,7 +368,7 @@ int nfs_rename(struct inode *, struct dentry *,
/* file.c */
int nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync);
loff_t nfs_file_llseek(struct file *, loff_t, int);
-ssize_t nfs_file_read(struct kiocb *, struct iov_iter *);
+ssize_t nfs_file_read(struct kiocb *, struct iov_iter *, bool rwf);
int nfs_file_mmap(struct file *, struct vm_area_struct *);
ssize_t nfs_file_write(struct kiocb *, struct iov_iter *);
int nfs_file_release(struct inode *, struct file *);
@@ -2345,7 +2345,8 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
}
static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
- struct iov_iter *to)
+ struct iov_iter *to,
+ bool rwf)
{
int ret = 0, rw_level = -1, lock_level = 0;
struct file *filp = iocb->ki_filp;
@@ -2395,7 +2396,7 @@ static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
}
ocfs2_inode_unlock(inode, lock_level);
- ret = generic_file_read_iter(iocb, to);
+ ret = generic_file_read_iter(iocb, to, rwf);
trace_generic_file_aio_read_ret(ret);
/* buffered aio wouldn't have proper lock coverage today */
@@ -442,7 +442,8 @@ ssize_t orangefs_inode_read(struct inode *inode,
return ret;
}
-static ssize_t orangefs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+static ssize_t orangefs_file_read_iter(struct kiocb *iocb,
+ struct iov_iter *iter, bool rwf)
{
struct file *file = iocb->ki_filp;
loff_t pos = *(&iocb->ki_pos);
@@ -247,7 +247,7 @@ static const struct pipe_buf_operations packet_pipe_buf_ops = {
};
static ssize_t
-pipe_read(struct kiocb *iocb, struct iov_iter *to)
+pipe_read(struct kiocb *iocb, struct iov_iter *to, bool rwf)
{
size_t total_len = iov_iter_count(to);
struct file *filp = iocb->ki_filp;
@@ -397,7 +397,7 @@ static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, lo
kiocb.ki_pos = *ppos;
iov_iter_init(&iter, READ, &iov, 1, len);
- ret = call_read_iter(filp, &kiocb, &iter);
+ ret = call_read_iter(filp, &kiocb, &iter, 0);
BUG_ON(ret == -EIOCBQUEUED);
*ppos = kiocb.ki_pos;
return ret;
@@ -668,7 +668,7 @@ static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter,
kiocb.ki_pos = *ppos;
if (type == READ)
- ret = call_read_iter(filp, &kiocb, iter);
+ ret = call_read_iter(filp, &kiocb, iter, 0);
else
ret = call_write_iter(filp, &kiocb, iter);
BUG_ON(ret == -EIOCBQUEUED);
@@ -304,7 +304,7 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
idx = to.idx;
init_sync_kiocb(&kiocb, in);
kiocb.ki_pos = *ppos;
- ret = call_read_iter(in, &kiocb, &to);
+ ret = call_read_iter(in, &kiocb, &to, 0);
if (ret > 0) {
*ppos = kiocb.ki_pos;
file_accessed(in);
@@ -203,7 +203,8 @@ xfs_file_fsync(
STATIC ssize_t
xfs_file_dio_aio_read(
struct kiocb *iocb,
- struct iov_iter *to)
+ struct iov_iter *to,
+ bool rwf)
{
struct xfs_inode *ip = XFS_I(file_inode(iocb->ki_filp));
size_t count = iov_iter_count(to);
@@ -226,7 +227,8 @@ xfs_file_dio_aio_read(
static noinline ssize_t
xfs_file_dax_read(
struct kiocb *iocb,
- struct iov_iter *to)
+ struct iov_iter *to,
+ bool rwf)
{
struct xfs_inode *ip = XFS_I(iocb->ki_filp->f_mapping->host);
size_t count = iov_iter_count(to);
@@ -252,7 +254,8 @@ xfs_file_dax_read(
STATIC ssize_t
xfs_file_buffered_aio_read(
struct kiocb *iocb,
- struct iov_iter *to)
+ struct iov_iter *to,
+ bool rwf)
{
struct xfs_inode *ip = XFS_I(file_inode(iocb->ki_filp));
ssize_t ret;
@@ -264,7 +267,7 @@ xfs_file_buffered_aio_read(
return -EAGAIN;
xfs_ilock(ip, XFS_IOLOCK_SHARED);
}
- ret = generic_file_read_iter(iocb, to);
+ ret = generic_file_read_iter(iocb, to, rwf);
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
return ret;
@@ -273,7 +276,8 @@ xfs_file_buffered_aio_read(
STATIC ssize_t
xfs_file_read_iter(
struct kiocb *iocb,
- struct iov_iter *to)
+ struct iov_iter *to,
+ bool rwf)
{
struct inode *inode = file_inode(iocb->ki_filp);
struct xfs_mount *mp = XFS_I(inode)->i_mount;
@@ -285,11 +289,11 @@ xfs_file_read_iter(
return -EIO;
if (IS_DAX(inode))
- ret = xfs_file_dax_read(iocb, to);
+ ret = xfs_file_dax_read(iocb, to, rwf);
else if (iocb->ki_flags & IOCB_DIRECT)
- ret = xfs_file_dio_aio_read(iocb, to);
+ ret = xfs_file_dio_aio_read(iocb, to, rwf);
else
- ret = xfs_file_buffered_aio_read(iocb, to);
+ ret = xfs_file_buffered_aio_read(iocb, to, rwf);
if (ret > 0)
XFS_STATS_ADD(mp, xs_read_bytes, ret);
@@ -1693,7 +1693,7 @@ struct file_operations {
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
- ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
+ ssize_t (*read_iter) (struct kiocb *, struct iov_iter *, bool rwf);
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
int (*iterate) (struct file *, struct dir_context *);
int (*iterate_shared) (struct file *, struct dir_context *);
@@ -1759,9 +1759,9 @@ struct inode_operations {
} ____cacheline_aligned;
static inline ssize_t call_read_iter(struct file *file, struct kiocb *kio,
- struct iov_iter *iter)
+ struct iov_iter *iter, bool rwf)
{
- return file->f_op->read_iter(kio, iter);
+ return file->f_op->read_iter(kio, iter, rwf);
}
static inline ssize_t call_write_iter(struct file *file, struct kiocb *kio,
@@ -2910,7 +2910,7 @@ extern int sb_min_blocksize(struct super_block *, int);
extern int generic_file_mmap(struct file *, struct vm_area_struct *);
extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *);
extern ssize_t generic_write_checks(struct kiocb *, struct iov_iter *);
-extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *);
+extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *, bool rwf);
extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *);
extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *);
extern ssize_t generic_file_direct_write(struct kiocb *, struct iov_iter *);
@@ -2922,7 +2922,7 @@ ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos,
rwf_t flags);
/* fs/block_dev.c */
-extern ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to);
+extern ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to, bool rwf);
extern ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from);
extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end,
int datasync);
@@ -2185,12 +2185,13 @@ static ssize_t generic_file_buffered_read(struct kiocb *iocb,
* generic_file_read_iter - generic filesystem read routine
* @iocb: kernel I/O control block
* @iter: destination for the data read
+ * @rwf: i_rwsem taken exclusively
*
* This is the "read_iter()" routine for all filesystems
* that can use the page cache directly.
*/
ssize_t
-generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter, bool rwf)
{
size_t count = iov_iter_count(iter);
ssize_t retval = 0;
@@ -2406,7 +2406,8 @@ shmem_write_end(struct file *file, struct address_space *mapping,
return copied;
}
-static ssize_t shmem_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t shmem_file_read_iter(struct kiocb *iocb, struct iov_iter *to,
+ bool rwf)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file);
@@ -113,7 +113,7 @@ unsigned int sysctl_net_busy_read __read_mostly;
unsigned int sysctl_net_busy_poll __read_mostly;
#endif
-static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to);
+static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to, bool rwf);
static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
static int sock_mmap(struct file *file, struct vm_area_struct *vma);
@@ -870,7 +870,7 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
return sock->ops->splice_read(sock, ppos, pipe, len, flags);
}
-static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to, bool rwf)
{
struct file *file = iocb->ki_filp;
struct socket *sock = file->private_data;
@@ -3061,7 +3061,7 @@ static ssize_t snd_pcm_write(struct file *file, const char __user *buf,
return result;
}
-static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to, bool rwf)
{
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream;
Writing extended attributes requires exclusively taking the i_rwsem lock. To synchronize the file hash calculation and writing the file hash as security.ima xattr, IMA-appraisal takes the i_rwsem lock exclusively before calculating the file hash. (Once the file hash is calculated, the result is cached. Taking the lock exclusively prevents calculating the file hash multiple times.) Some filesystems have recently replaced their filesystem dependent lock with the global i_rwsem to read a file. As a result, when IMA attempts to calculate the file hash, reading the file attempts to take the i_rwsem again. To resolve this problem, this patch defines a new read_iter flag named "rwf" to indicate that the i_rwsem has already been taken exclusively. Subsequent patches will set or test the "rwf" flag. Fixes: Commit 6552321831dc "xfs: remove i_iolock and use i_rwsem in the VFS inode instead" Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> --- arch/s390/hypfs/inode.c | 3 ++- drivers/block/loop.c | 2 +- drivers/char/mem.c | 6 ++++-- drivers/gpu/drm/drm_dp_aux_dev.c | 3 ++- drivers/net/tap.c | 3 ++- drivers/net/tun.c | 3 ++- drivers/staging/android/ashmem.c | 3 ++- drivers/staging/lustre/lustre/llite/file.c | 3 ++- drivers/staging/lustre/lustre/llite/vvp_io.c | 2 +- drivers/usb/gadget/function/f_fs.c | 3 ++- drivers/usb/gadget/legacy/inode.c | 2 +- drivers/vhost/net.c | 3 ++- fs/9p/vfs_file.c | 8 +++++--- fs/aio.c | 2 +- fs/block_dev.c | 4 ++-- fs/ceph/file.c | 5 +++-- fs/cifs/cifsfs.c | 6 +++--- fs/cifs/cifsfs.h | 4 ++-- fs/cifs/file.c | 10 +++++----- fs/coda/file.c | 2 +- fs/ecryptfs/file.c | 4 ++-- fs/efivarfs/file.c | 2 +- fs/ext2/file.c | 10 ++++++---- fs/ext4/file.c | 12 +++++++----- fs/fuse/cuse.c | 3 ++- fs/fuse/dev.c | 3 ++- fs/fuse/file.c | 8 +++++--- fs/hugetlbfs/inode.c | 3 ++- fs/ncpfs/file.c | 2 +- fs/nfs/file.c | 4 ++-- fs/nfs/internal.h | 2 +- fs/ocfs2/file.c | 5 +++-- fs/orangefs/file.c | 3 ++- fs/pipe.c | 2 +- fs/read_write.c | 4 ++-- fs/splice.c | 2 +- fs/xfs/xfs_file.c | 20 ++++++++++++-------- include/linux/fs.h | 10 +++++----- mm/filemap.c | 3 ++- mm/shmem.c | 3 ++- net/socket.c | 4 ++-- sound/core/pcm_native.c | 2 +- 42 files changed, 109 insertions(+), 79 deletions(-)