diff options
90 files changed, 598 insertions, 1185 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index f91926f2f482..c3cd6279e92e 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -429,8 +429,6 @@ prototypes: 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 (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); - ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); ssize_t (*read_iter) (struct kiocb *, struct iov_iter *); ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); int (*iterate) (struct file *, struct dir_context *); diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index fa2db081505e..e69274de8d0c 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting @@ -471,3 +471,15 @@ in your dentry operations instead. [mandatory] f_dentry is gone; use f_path.dentry, or, better yet, see if you can avoid it entirely. +-- +[mandatory] + never call ->read() and ->write() directly; use __vfs_{read,write} or + wrappers; instead of checking for ->write or ->read being NULL, look for + FMODE_CAN_{WRITE,READ} in file->f_mode. +-- +[mandatory] + do _not_ use new_sync_{read,write} for ->read/->write; leave it NULL + instead. +-- +[mandatory] + ->aio_read/->aio_write are gone. Use ->read_iter/->write_iter. diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 966b22829f3b..207cdca68bed 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -804,8 +804,6 @@ 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 (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); - ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); ssize_t (*read_iter) (struct kiocb *, struct iov_iter *); ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); int (*iterate) (struct file *, struct dir_context *); @@ -838,14 +836,10 @@ otherwise noted. read: called by read(2) and related system calls - aio_read: vectored, possibly asynchronous read - read_iter: possibly asynchronous read with iov_iter as destination write: called by write(2) and related system calls - aio_write: vectored, possibly asynchronous write - write_iter: possibly asynchronous write with iov_iter as source iterate: called when the VFS needs to read the directory contents diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c index df7d8cbee377..3f5c799b7fb5 100644 --- a/arch/s390/hypfs/inode.c +++ b/arch/s390/hypfs/inode.c @@ -437,8 +437,6 @@ struct dentry *hypfs_create_str(struct dentry *dir, static const struct file_operations hypfs_file_ops = { .open = hypfs_open, .release = hypfs_release, - .read = new_sync_read, - .write = new_sync_write, .read_iter = hypfs_read_iter, .write_iter = hypfs_write_iter, .llseek = no_llseek, diff --git a/drivers/block/loop.c b/drivers/block/loop.c index d1f168b73634..c4fd1e45ce1e 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -75,6 +75,7 @@ #include <linux/sysfs.h> #include <linux/miscdevice.h> #include <linux/falloc.h> +#include <linux/uio.h> #include "loop.h" #include <asm/uaccess.h> @@ -229,13 +230,14 @@ lo_do_transfer(struct loop_device *lo, int cmd, static int __do_lo_send_write(struct file *file, u8 *buf, const int len, loff_t pos) { + struct kvec kvec = {.iov_base = buf, .iov_len = len}; + struct iov_iter from; ssize_t bw; - mm_segment_t old_fs = get_fs(); + + iov_iter_kvec(&from, ITER_KVEC | WRITE, &kvec, 1, len); file_start_write(file); - set_fs(get_ds()); - bw = file->f_op->write(file, buf, len, &pos); - set_fs(old_fs); + bw = vfs_iter_write(file, &from, &pos); file_end_write(file); if (likely(bw == len)) return 0; @@ -767,7 +769,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, goto out_putf; if (!(file->f_mode & FMODE_WRITE) || !(mode & FMODE_WRITE) || - !file->f_op->write) + !file->f_op->write_iter) lo_flags |= LO_FLAGS_READ_ONLY; lo_blocksize = S_ISBLK(inode->i_mode) ? diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 9c4fd7a8e2e5..6b1721f978c2 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -607,16 +607,16 @@ static ssize_t write_null(struct file *file, const char __user *buf, return count; } -static ssize_t aio_read_null(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) +static ssize_t read_iter_null(struct kiocb *iocb, struct iov_iter *to) { return 0; } -static ssize_t aio_write_null(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) +static ssize_t write_iter_null(struct kiocb *iocb, struct iov_iter *from) { - return iov_length(iov, nr_segs); + size_t count = iov_iter_count(from); + iov_iter_advance(from, count); + return count; } static int pipe_to_null(struct pipe_inode_info *info, struct pipe_buffer *buf, @@ -718,7 +718,7 @@ static int open_port(struct inode *inode, struct file *filp) #define zero_lseek null_lseek #define full_lseek null_lseek #define write_zero write_null -#define aio_write_zero aio_write_null +#define write_iter_zero write_iter_null #define open_mem open_port #define open_kmem open_mem @@ -750,8 +750,8 @@ static const struct file_operations null_fops = { .llseek = null_lseek, .read = read_null, .write = write_null, - .aio_read = aio_read_null, - .aio_write = aio_write_null, + .read_iter = read_iter_null, + .write_iter = write_iter_null, .splice_write = splice_write_null, }; @@ -764,10 +764,9 @@ static const struct file_operations __maybe_unused port_fops = { static const struct file_operations zero_fops = { .llseek = zero_lseek, - .read = new_sync_read, .write = write_zero, .read_iter = read_iter_zero, - .aio_write = aio_write_zero, + .write_iter = write_iter_zero, .mmap = mmap_zero, #ifndef CONFIG_MMU .mmap_capabilities = zero_mmap_capabilities, @@ -776,7 +775,6 @@ static const struct file_operations zero_fops = { static const struct file_operations full_fops = { .llseek = full_lseek, - .read = new_sync_read, .read_iter = read_iter_zero, .write = write_full, }; diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 6e29bf2db536..5fc291c6157e 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -282,9 +282,7 @@ static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd, #endif static const struct file_operations raw_fops = { - .read = new_sync_read, .read_iter = blkdev_read_iter, - .write = new_sync_write, .write_iter = blkdev_write_iter, .fsync = blkdev_fsync, .open = raw_open, diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c index aed8afee56da..450d15965005 100644 --- a/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c @@ -42,6 +42,7 @@ #include <linux/io.h> #include <linux/jiffies.h> #include <linux/cpu.h> +#include <linux/uio.h> #include <asm/pgtable.h> #include "ipath_kernel.h" @@ -52,15 +53,19 @@ static int ipath_open(struct inode *, struct file *); static int ipath_close(struct inode *, struct file *); static ssize_t ipath_write(struct file *, const char __user *, size_t, loff_t *); -static ssize_t ipath_writev(struct kiocb *, const struct iovec *, - unsigned long , loff_t); +static ssize_t ipath_write_iter(struct kiocb *, struct iov_iter *from); static unsigned int ipath_poll(struct file *, struct poll_table_struct *); static int ipath_mmap(struct file *, struct vm_area_struct *); +/* + * This is really, really weird shit - write() and writev() here + * have completely unrelated semantics. Sucky userland ABI, + * film at 11. + */ static const struct file_operations ipath_file_ops = { .owner = THIS_MODULE, .write = ipath_write, - .aio_write = ipath_writev, + .write_iter = ipath_write_iter, .open = ipath_open, .release = ipath_close, .poll = ipath_poll, @@ -2413,18 +2418,17 @@ bail: return ret; } -static ssize_t ipath_writev(struct kiocb *iocb, const struct iovec *iov, - unsigned long dim, loff_t off) +static ssize_t ipath_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *filp = iocb->ki_filp; struct ipath_filedata *fp = filp->private_data; struct ipath_portdata *pd = port_fp(filp); struct ipath_user_sdma_queue *pq = fp->pq; - if (!dim) + if (!iter_is_iovec(from) || !from->nr_segs) return -EINVAL; - return ipath_user_sdma_writev(pd->port_dd, pq, iov, dim); + return ipath_user_sdma_writev(pd->port_dd, pq, from->iov, from->nr_segs); } static struct class *ipath_class; diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c index 14046f5a37fa..9ea6c440a00c 100644 --- a/drivers/infiniband/hw/qib/qib_file_ops.c +++ b/drivers/infiniband/hw/qib/qib_file_ops.c @@ -43,6 +43,7 @@ #include <asm/pgtable.h> #include <linux/delay.h> #include <linux/export.h> +#include <linux/uio.h> #include "qib.h" #include "qib_common.h" @@ -54,15 +55,19 @@ static int qib_open(struct inode *, struct file *); static int qib_close(struct inode *, struct file *); static ssize_t qib_write(struct file *, const char __user *, size_t, loff_t *); -static ssize_t qib_aio_write(struct kiocb *, const struct iovec *, - unsigned long, loff_t); +static ssize_t qib_write_iter(struct kiocb *, struct iov_iter *); static unsigned int qib_poll(struct file *, struct poll_table_struct *); static int qib_mmapf(struct file *, struct vm_area_struct *); +/* + * This is really, really weird shit - write() and writev() here + * have completely unrelated semantics. Sucky userland ABI, + * film at 11. + */ static const struct file_operations qib_file_ops = { .owner = THIS_MODULE, .write = qib_write, - .aio_write = qib_aio_write, + .write_iter = qib_write_iter, .open = qib_open, .release = qib_close, .poll = qib_poll, @@ -2248,17 +2253,16 @@ bail: return ret; } -static ssize_t qib_aio_write(struct kiocb *iocb, const struct iovec *iov, - unsigned long dim, loff_t off) +static ssize_t qib_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct qib_filedata *fp = iocb->ki_filp->private_data; struct qib_ctxtdata *rcd = ctxt_fp(iocb->ki_filp); struct qib_user_sdma_queue *pq = fp->pq; - if (!dim || !pq) + if (!iter_is_iovec(from) || !from->nr_segs || !pq) return -EINVAL; - - return qib_user_sdma_writev(rcd, pq, iov, dim); + + return qib_user_sdma_writev(rcd, pq, from->iov, from->nr_segs); } static struct class *qib_class; diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 8362aef0c15e..9c91ff872485 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -1118,8 +1118,6 @@ static const struct file_operations macvtap_fops = { .owner = THIS_MODULE, .open = macvtap_open, .release = macvtap_release, - .read = new_sync_read, - .write = new_sync_write, .read_iter = macvtap_read_iter, .write_iter = macvtap_write_iter, .poll = macvtap_poll, diff --git a/drivers/net/tun.c b/drivers/net/tun.c index b96b94cee760..e470ae59d405 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -2223,8 +2223,6 @@ static void tun_chr_show_fdinfo(struct seq_file *m, struct file *f) static const struct file_operations tun_fops = { .owner = THIS_MODULE, .llseek = no_llseek, - .read = new_sync_read, - .write = new_sync_write, .read_iter = tun_chr_read_iter, .write_iter = tun_chr_write_iter, .poll = tun_chr_poll, diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index d140b733940c..c5c037ccf32c 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -310,7 +310,7 @@ static ssize_t ashmem_read(struct file *file, char __user *buf, * be destroyed until all references to the file are dropped and * ashmem_release is called. */ - ret = asma->file->f_op->read(asma->file, buf, len, pos); + ret = __vfs_read(asma->file, buf, len, pos); if (ret >= 0) { /** Update backing file pos, since f_ops->read() doesn't */ asma->file->f_pos = *pos; diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index ad35ed6e93f0..304ebff119ee 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -108,24 +108,16 @@ static int serial2002_tty_write(struct file *f, unsigned char *buf, int count) { const char __user *p = (__force const char __user *)buf; int result; + loff_t offset = 0; mm_segment_t oldfs; oldfs = get_fs(); set_fs(KERNEL_DS); - f->f_pos = 0; - result = f->f_op->write(f, p, count, &f->f_pos); + result = __vfs_write(f, p, count, &offset); set_fs(oldfs); return result; } -static int serial2002_tty_readb(struct file *f, unsigned char *buf) -{ - char __user *p = (__force char __user *)buf; - - f->f_pos = 0; - return f->f_op->read(f, p, 1, &f->f_pos); -} - static void serial2002_tty_read_poll_wait(struct file *f, int timeout) { struct poll_wqueues table; @@ -161,13 +153,15 @@ static int serial2002_tty_read(struct file *f, int timeout) result = -1; if (!IS_ERR(f)) { mm_segment_t oldfs; + char __user *p = (__force char __user *)&ch; + loff_t offset = 0; oldfs = get_fs(); set_fs(KERNEL_DS); if (f->f_op->poll) { serial2002_tty_read_poll_wait(f, timeout); - if (serial2002_tty_readb(f, &ch) == 1) + if (__vfs_read(f, p, 1, &offset) == 1) result = ch; } else { /* Device does not support poll, busy wait */ @@ -178,7 +172,7 @@ static int serial2002_tty_read(struct file *f, int timeout) if (retries >= timeout) break; - if (serial2002_tty_readb(f, &ch) == 1) { + if (__vfs_read(f, p, 1, &offset) == 1) { result = ch; break; } diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 85e74d18d1c7..529062ea112b 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/ |