const struct file_operations generic_ro_fops = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.mmap = generic_file_readonly_mmap,
.splice_read = generic_file_splice_read,
};
return count > MAX_RW_COUNT ? MAX_RW_COUNT : count;
}
+ssize_t do_aio_read(struct kiocb *kiocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
+{
+ struct file *file = kiocb->ki_filp;
+
+ if (file->f_op->read_iter) {
+ size_t count;
+ struct iov_iter iter;
+ int ret;
+
+ count = 0;
+ ret = generic_segment_checks(iov, &nr_segs, &count,
+ VERIFY_WRITE);
+ if (ret)
+ return ret;
+
+ iov_iter_init(&iter, iov, nr_segs, count, 0);
+ return file->f_op->read_iter(kiocb, &iter, pos);
+ }
+
+ return file->f_op->aio_read(kiocb, iov, nr_segs, pos);
+}
+
ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
{
struct iovec iov = { .iov_base = buf, .iov_len = len };
kiocb.ki_pos = *ppos;
kiocb.ki_nbytes = len;
- ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
+ ret = do_aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos;
EXPORT_SYMBOL(vfs_read);
+ssize_t do_aio_write(struct kiocb *kiocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
+{
+ struct file *file = kiocb->ki_filp;
+
+ if (file->f_op->write_iter) {
+ size_t count;
+ struct iov_iter iter;
+ int ret;
+
+ count = 0;
+ ret = generic_segment_checks(iov, &nr_segs, &count,
+ VERIFY_READ);
+ if (ret)
+ return ret;
+
+ iov_iter_init(&iter, iov, nr_segs, count, 0);
+ return file->f_op->write_iter(kiocb, &iter, pos);
+ }
+
+ return file->f_op->aio_write(kiocb, iov, nr_segs, pos);
+}
+
ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
{
struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };
kiocb.ki_pos = *ppos;
kiocb.ki_nbytes = len;
- ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
+ ret = do_aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos;
fnv = NULL;
if (type == READ) {
fn = file->f_op->read;
- fnv = file->f_op->aio_read;
+ if (file->f_op->aio_read || file->f_op->read_iter)
+ fnv = do_aio_read;
} else {
fn = (io_fn_t)file->f_op->write;
- fnv = file->f_op->aio_write;
+ if (file->f_op->aio_write || file->f_op->write_iter)
+ fnv = do_aio_write;
file_start_write(file);
}
fnv = NULL;
if (type == READ) {
fn = file->f_op->read;
- fnv = file->f_op->aio_read;
+ if (file->f_op->aio_read || file->f_op->read_iter)
+ fnv = do_aio_read;
} else {
fn = (io_fn_t)file->f_op->write;
- fnv = file->f_op->aio_write;
+ if (file->f_op->aio_write || file->f_op->write_iter)
+ fnv = do_aio_write;
file_start_write(file);
}