Code:
From 0a9f08ed3aed64ef14097f3e18ad8641b62ef1d7 Mon Sep 17 00:00:00 2001
From: Mikhail Malygin <[email protected]>
Date: Thu, 25 Mar 2021 19:30:04 +0300
Subject: [PATCH] Implement prlfs_write_iter and prlfs_read_iter functions on
top of prlfs_write and prlfs_read
---
.../SharedFolders/Guest/Linux/prl_fs/file.c | 100 +++++++++++++++++-
1 file changed, 96 insertions(+), 4 deletions(-)
diff --git a/prl_fs/SharedFolders/Guest/Linux/prl_fs/file.c b/prl_fs/SharedFolders/Guest/Linux/prl_fs/file.c
index e779cf7..48537dc 100644
--- a/prl_fs/SharedFolders/Guest/Linux/prl_fs/file.c
+++ b/prl_fs/SharedFolders/Guest/Linux/prl_fs/file.c
@@ -427,7 +427,7 @@ static ssize_t prlfs_read(struct file *filp, char *buf, size_t size,
struct dentry *dentry = FILE_DENTRY(filp);
struct inode *inode = dentry->d_inode;
- return prlfs_rw(inode, buf, size, off, 0, 1, TG_REQ_COMMON);
+ return prlfs_rw(inode, buf, size, off, 0, 0, TG_REQ_COMMON);
}
static ssize_t prlfs_write(struct file *filp, const char *buf, size_t size,
@@ -445,7 +445,7 @@ static ssize_t prlfs_write(struct file *filp, const char *buf, size_t size,
real_off = *off;
prlfs_inode_lock(inode);
- ret = prlfs_rw(inode, (char *)buf, size, &real_off, 1, 1, TG_REQ_COMMON);
+ ret = prlfs_rw(inode, (char *)buf, size, &real_off, 1, 0, TG_REQ_COMMON);
dentry->d_time = 0;
if (ret < 0)
goto out;
@@ -462,6 +462,98 @@ out:
return ret;
}
+static ssize_t prlfs_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+ ssize_t ret = 0;
+ size_t alloc_size = 512 * 1024;
+ size_t bytes_done = 0;
+
+ size_t buf_size = min_t(size_t, alloc_size, iter->count);
+ void *buf = kzalloc(buf_size, GFP_KERNEL);
+
+ if(!buf) {
+ printk("prlfs_read_iter: failed to allocate %ld bytes\n", buf_size);
+ return -ENOMEM;
+ }
+
+ DPRINTK("prlfs_read_iter: reading %ld bytes\n", iter->count);
+
+ while(iter->count) {
+ size_t to_read = min_t(size_t, alloc_size, iter->count);
+ DPRINTK("prlfs_read_iter: %ld bytes to be read from fs, remain %ld\n", to_read, iter->count);
+
+ ret = prlfs_read(iocb->ki_filp, buf, to_read, &iocb->ki_pos);
+
+ if(ret < 0) {
+ goto err;
+ }
+
+ ret = copy_to_iter(buf, ret, iter);
+
+ DPRINTK("prlfs_read_iter: %ld bytes copied to iter\n", ret);
+
+ bytes_done += ret;
+
+ if (ret == 0) {
+ break;
+ }
+ }
+
+ DPRINTK("prlfs_read_iter: %ld bytes read\n", bytes_done);
+
+
+ kfree(buf);
+ return bytes_done;
+
+err:
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t prlfs_write_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+ ssize_t ret = 0;
+ size_t alloc_size = 512 * 1024;
+ size_t bytes_done = 0;
+
+ size_t buf_size = min_t(size_t, alloc_size, iter->count);
+ void *buf = kzalloc(buf_size, GFP_KERNEL);
+
+ if(!buf) {
+ printk("prlfs_write_iter: failed to allocate %ld bytes\n", buf_size);
+ return -ENOMEM;
+ }
+
+ while(iter->count) {
+ size_t bytes = copy_from_iter(buf, min_t(ssize_t, buf_size, iter->count), iter);
+ size_t written = 0;
+
+ while(written < bytes) {
+ DPRINTK("prlfs_write_iter: %ld bytes to be written to fs", bytes);
+
+ ret = prlfs_write(iocb->ki_filp, buf + written, bytes - written, &iocb->ki_pos);
+
+ if(ret < 0) {
+ goto err;
+ }
+
+ written += ret;
+ bytes_done += ret;
+ }
+
+ if (ret == 0) {
+ break;
+ }
+ }
+
+ kfree(buf);
+ return bytes_done;
+
+err:
+ kfree(buf);
+ return ret;
+}
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
#ifdef PRL_SIMPLE_SYNC_FILE
int simple_sync_file(struct file *filp, struct dentry *dentry, int datasync)
@@ -473,8 +565,8 @@ int simple_sync_file(struct file *filp, struct dentry *dentry, int datasync)
struct file_operations prlfs_file_fops = {
.open = prlfs_open,
- .read = prlfs_read,
- .write = prlfs_write,
+ .read_iter = prlfs_read_iter,
+ .write_iter = prlfs_write_iter,
.llseek = generic_file_llseek,
.release = prlfs_release,
.mmap = generic_file_mmap,
--
2.24.3 (Apple Git-128)