Skip to content

Commit

Permalink
[WIP] iter_write/read: splice(2) support for ZFS
Browse files Browse the repository at this point in the history
Inspired by openzfs/issues/1156

Fixes vpsfreecz/vpsadminos#36

Signed-off-by: Pavel Snajdr <snajpa@snajpa.net>
  • Loading branch information
snajpa committed Jun 18, 2020
1 parent 7546fb3 commit 2d6ade8
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 1 deletion.
1 change: 1 addition & 0 deletions module/os/linux/zfs/zfs_vnops.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,7 @@ zfs_read(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr)
}

if (error) {
dump_stack();
/* convert checksum errors into IO errors */
if (error == ECKSUM)
error = SET_ERROR(EIO);
Expand Down
61 changes: 61 additions & 0 deletions module/os/linux/zfs/zpl_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -985,6 +985,65 @@ const struct address_space_operations zpl_address_space_operations = {
.direct_IO = zpl_direct_IO,
};

ssize_t
zpl_iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
loff_t *ppos, size_t len, unsigned int flags)
{
ssize_t ret;
struct inode *ip = out->f_mapping->host;
int error;
fstrans_cookie_t cookie;

spl_inode_lock_shared(ip);
cookie = spl_fstrans_mark();
error = -zfs_holey(ip, SEEK_DATA, ppos);
spl_fstrans_unmark(cookie);
spl_inode_unlock_shared(ip);

ret = iter_file_splice_write(pipe, out, ppos, len, flags);
printk(KERN_INFO "%s:%d(pipe,out,%llu,%lu,%x):%li\n", __func__, __LINE__,
*ppos,len,flags,(long int)ret);
return ret;
}

ssize_t zpl_file_splice_read(struct file *in, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len,
unsigned int flags)
{
cred_t *cr = CRED();
ssize_t ret;
struct inode *ip = in->f_mapping->host;
znode_t *zp = ITOZ(ip);
uint64_t file_sz;
struct iov_iter to;
uio_seg_t seg = UIO_USERSPACE;
struct iovec fiovec; // fake iovec

fiovec.iov_len = len;
fiovec.iov_base = kmalloc(len, GFP_KERNEL);
fstrans_cookie_t cookie;

spl_inode_lock_shared(ip);
cookie = spl_fstrans_mark();
//file_sz = zp->z_size;
//if ((*ppos+len) > file_sz) {
// len = 10;
//}



//error = -zfs_holey(ip, SEEK_DATA, ppos);
spl_fstrans_unmark(cookie);
spl_inode_unlock_shared(ip);

ssize_t read = zpl_read_common(ip, fiovec.iov_base, len, ppos, seg, in->f_flags, cr);
ret = _copy_to_iter(fiovec.iov_base, len, &to);
printk(KERN_INFO "%s:%d(pipe,out,%llu,%lu,%x):%li\n", __func__, __LINE__,
*ppos,len,flags,(long int)read);
kfree(fiovec.iov_base);
return ret;
}

const struct file_operations zpl_file_operations = {
.open = zpl_open,
.release = zpl_release,
Expand Down Expand Up @@ -1012,6 +1071,8 @@ const struct file_operations zpl_file_operations = {
#ifdef CONFIG_COMPAT
.compat_ioctl = zpl_compat_ioctl,
#endif
.splice_read = zpl_file_splice_read,
.splice_write = zpl_iter_file_splice_write,
};

const struct file_operations zpl_dir_file_operations = {
Expand Down
6 changes: 5 additions & 1 deletion module/zcommon/zfs_uio.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,12 @@ uiomove_iov(void *p, size_t n, enum uio_rw rw, struct uio *uio)
* iov->iov_base = user data pointer
*/
if (rw == UIO_READ) {
if (copy_to_user(iov->iov_base+skip, p, cnt))
unsigned long b_left = copy_to_user(iov->iov_base+skip, p, cnt);
if (b_left > 0) {
printk(KERN_INFO "%s:%d(skip:%zu,cnt:%lu,%llx,%llx):%lu\n", __func__, __LINE__, skip,cnt,(uint64_t)iov->iov_base,(uint64_t)p,b_left);
dump_stack();
return (EFAULT);
}
} else {
unsigned long b_left = 0;
if (uio->uio_fault_disable) {
Expand Down

0 comments on commit 2d6ade8

Please sign in to comment.