Loading fs/read_write.c +46 −0 Original line number Diff line number Diff line Loading @@ -333,6 +333,52 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high, } #endif ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos) { struct kiocb kiocb; ssize_t ret; if (!file->f_op->read_iter) return -EINVAL; init_sync_kiocb(&kiocb, file); kiocb.ki_pos = *ppos; kiocb.ki_nbytes = iov_iter_count(iter); iter->type |= READ; ret = file->f_op->read_iter(&kiocb, iter); if (ret == -EIOCBQUEUED) ret = wait_on_sync_kiocb(&kiocb); if (ret > 0) *ppos = kiocb.ki_pos; return ret; } EXPORT_SYMBOL(vfs_iter_read); ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos) { struct kiocb kiocb; ssize_t ret; if (!file->f_op->write_iter) return -EINVAL; init_sync_kiocb(&kiocb, file); kiocb.ki_pos = *ppos; kiocb.ki_nbytes = iov_iter_count(iter); iter->type |= WRITE; ret = file->f_op->write_iter(&kiocb, iter); if (ret == -EIOCBQUEUED) ret = wait_on_sync_kiocb(&kiocb); if (ret > 0) *ppos = kiocb.ki_pos; return ret; } EXPORT_SYMBOL(vfs_iter_write); /* * rw_verify_area doesn't like huge counts. We limit * them to something that fits in "int" so that others Loading fs/splice.c +2 −14 Original line number Diff line number Diff line Loading @@ -961,7 +961,6 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out, splice_from_pipe_begin(&sd); while (sd.total_len) { struct iov_iter from; struct kiocb kiocb; size_t left; int n, idx; Loading Loading @@ -1005,26 +1004,15 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out, left -= this_len; } /* ... iov_iter */ iov_iter_bvec(&from, ITER_BVEC | WRITE, array, n, sd.total_len - left); /* ... and iocb */ init_sync_kiocb(&kiocb, out); kiocb.ki_pos = sd.pos; kiocb.ki_nbytes = sd.total_len - left; /* now, send it */ ret = out->f_op->write_iter(&kiocb, &from); if (-EIOCBQUEUED == ret) ret = wait_on_sync_kiocb(&kiocb); ret = vfs_iter_write(out, &from, &sd.pos); if (ret <= 0) break; sd.num_spliced += ret; sd.total_len -= ret; *ppos = sd.pos = kiocb.ki_pos; *ppos = sd.pos; /* dismiss the fully eaten buffers, adjust the partial one */ while (ret) { Loading include/linux/fs.h +3 −0 Original line number Diff line number Diff line Loading @@ -2494,6 +2494,9 @@ extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t l extern ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos); extern ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos); ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos); ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos); /* fs/block_dev.c */ extern ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to); extern ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from); Loading Loading
fs/read_write.c +46 −0 Original line number Diff line number Diff line Loading @@ -333,6 +333,52 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high, } #endif ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos) { struct kiocb kiocb; ssize_t ret; if (!file->f_op->read_iter) return -EINVAL; init_sync_kiocb(&kiocb, file); kiocb.ki_pos = *ppos; kiocb.ki_nbytes = iov_iter_count(iter); iter->type |= READ; ret = file->f_op->read_iter(&kiocb, iter); if (ret == -EIOCBQUEUED) ret = wait_on_sync_kiocb(&kiocb); if (ret > 0) *ppos = kiocb.ki_pos; return ret; } EXPORT_SYMBOL(vfs_iter_read); ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos) { struct kiocb kiocb; ssize_t ret; if (!file->f_op->write_iter) return -EINVAL; init_sync_kiocb(&kiocb, file); kiocb.ki_pos = *ppos; kiocb.ki_nbytes = iov_iter_count(iter); iter->type |= WRITE; ret = file->f_op->write_iter(&kiocb, iter); if (ret == -EIOCBQUEUED) ret = wait_on_sync_kiocb(&kiocb); if (ret > 0) *ppos = kiocb.ki_pos; return ret; } EXPORT_SYMBOL(vfs_iter_write); /* * rw_verify_area doesn't like huge counts. We limit * them to something that fits in "int" so that others Loading
fs/splice.c +2 −14 Original line number Diff line number Diff line Loading @@ -961,7 +961,6 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out, splice_from_pipe_begin(&sd); while (sd.total_len) { struct iov_iter from; struct kiocb kiocb; size_t left; int n, idx; Loading Loading @@ -1005,26 +1004,15 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out, left -= this_len; } /* ... iov_iter */ iov_iter_bvec(&from, ITER_BVEC | WRITE, array, n, sd.total_len - left); /* ... and iocb */ init_sync_kiocb(&kiocb, out); kiocb.ki_pos = sd.pos; kiocb.ki_nbytes = sd.total_len - left; /* now, send it */ ret = out->f_op->write_iter(&kiocb, &from); if (-EIOCBQUEUED == ret) ret = wait_on_sync_kiocb(&kiocb); ret = vfs_iter_write(out, &from, &sd.pos); if (ret <= 0) break; sd.num_spliced += ret; sd.total_len -= ret; *ppos = sd.pos = kiocb.ki_pos; *ppos = sd.pos; /* dismiss the fully eaten buffers, adjust the partial one */ while (ret) { Loading
include/linux/fs.h +3 −0 Original line number Diff line number Diff line Loading @@ -2494,6 +2494,9 @@ extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t l extern ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos); extern ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos); ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos); ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos); /* fs/block_dev.c */ extern ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to); extern ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from); Loading