summary refs log tree commit diff
path: root/pkgs/os-specific/linux/zfs/kernel-4.1-compat.patch
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/os-specific/linux/zfs/kernel-4.1-compat.patch')
-rw-r--r--pkgs/os-specific/linux/zfs/kernel-4.1-compat.patch149
1 files changed, 149 insertions, 0 deletions
diff --git a/pkgs/os-specific/linux/zfs/kernel-4.1-compat.patch b/pkgs/os-specific/linux/zfs/kernel-4.1-compat.patch
new file mode 100644
index 00000000000..7e75e843af3
--- /dev/null
+++ b/pkgs/os-specific/linux/zfs/kernel-4.1-compat.patch
@@ -0,0 +1,149 @@
+diff --git a/config/kernel-vfs-rw-iterate.m4 b/config/kernel-vfs-rw-iterate.m4
+new file mode 100644
+index 0000000..f8dc422
+--- /dev/null
++++ b/config/kernel-vfs-rw-iterate.m4
+@@ -0,0 +1,27 @@
++dnl #
++dnl # Linux 4.1.x API
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_VFS_RW_ITERATE],
++	[AC_MSG_CHECKING([whether fops->read/write_iter() are available])
++	ZFS_LINUX_TRY_COMPILE([
++		#include <linux/fs.h>
++
++		ssize_t test_read(struct kiocb *kiocb, struct iov_iter *to)
++		    { return 0; }
++		ssize_t test_write(struct kiocb *kiocb, struct iov_iter *from)
++		    { return 0; }
++
++		static const struct file_operations
++		    fops __attribute__ ((unused)) = {
++		    .read_iter = test_read,
++		    .write_iter = test_write,
++		};
++	],[
++	],[
++		AC_MSG_RESULT(yes)
++		AC_DEFINE(HAVE_VFS_RW_ITERATE, 1,
++			[fops->read/write_iter() are available])
++	],[
++		AC_MSG_RESULT(no)
++	])
++])
+diff --git a/config/kernel.m4 b/config/kernel.m4
+index a9f2f58..fe42e17 100644
+--- a/config/kernel.m4
++++ b/config/kernel.m4
+@@ -96,6 +96,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
+ 	ZFS_AC_KERNEL_5ARG_SGET
+ 	ZFS_AC_KERNEL_LSEEK_EXECUTE
+ 	ZFS_AC_KERNEL_VFS_ITERATE
++	ZFS_AC_KERNEL_VFS_RW_ITERATE
+ 
+ 	AS_IF([test "$LINUX_OBJ" != "$LINUX"], [
+ 		KERNELMAKE_PARAMS="$KERNELMAKE_PARAMS O=$LINUX_OBJ"
+diff --git a/module/zfs/zpl_file.c b/module/zfs/zpl_file.c
+index 66db113..5471140 100644
+--- a/module/zfs/zpl_file.c
++++ b/module/zfs/zpl_file.c
+@@ -196,8 +196,7 @@ zpl_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
+ static int
+ zpl_aio_fsync(struct kiocb *kiocb, int datasync)
+ {
+-	return (zpl_fsync(kiocb->ki_filp, kiocb->ki_pos,
+-	    kiocb->ki_pos + kiocb->ki_nbytes, datasync));
++	return (zpl_fsync(kiocb->ki_filp, kiocb->ki_pos, -1, datasync));
+ }
+ #else
+ #error "Unsupported fops->fsync() implementation"
+@@ -261,12 +260,11 @@ zpl_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
+ }
+ 
+ static ssize_t
+-zpl_aio_read(struct kiocb *kiocb, const struct iovec *iovp,
+-	unsigned long nr_segs, loff_t pos)
++zpl_iter_read_common(struct kiocb *kiocb, const struct iovec *iovp,
++    unsigned long nr_segs, size_t count)
+ {
+ 	cred_t *cr = CRED();
+ 	struct file *filp = kiocb->ki_filp;
+-	size_t count = kiocb->ki_nbytes;
+ 	ssize_t read;
+ 	size_t alloc_size = sizeof (struct iovec) * nr_segs;
+ 	struct iovec *iov_tmp = kmem_alloc(alloc_size, KM_SLEEP);
+@@ -284,6 +282,22 @@ zpl_aio_read(struct kiocb *kiocb, const struct iovec *iovp,
+ 	return (read);
+ }
+ 
++#if defined(HAVE_VFS_RW_ITERATE)
++static ssize_t
++zpl_iter_read(struct kiocb *kiocb, struct iov_iter *to)
++{
++	return (zpl_iter_read_common(kiocb, to->iov, to->nr_segs,
++	    iov_iter_count(to)));
++}
++#else
++static ssize_t
++zpl_aio_read(struct kiocb *kiocb, const struct iovec *iovp,
++    unsigned long nr_segs, loff_t pos)
++{
++	return (zpl_iter_read_common(kiocb, iovp, nr_segs, kiocb->ki_nbytes));
++}
++#endif /* HAVE_VFS_RW_ITERATE */
++
+ static inline ssize_t
+ zpl_write_common_iovec(struct inode *ip, const struct iovec *iovp, size_t count,
+     unsigned long nr_segs, loff_t *ppos, uio_seg_t segment,
+@@ -344,12 +358,11 @@ zpl_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
+ }
+ 
+ static ssize_t
+-zpl_aio_write(struct kiocb *kiocb, const struct iovec *iovp,
+-	unsigned long nr_segs, loff_t pos)
++zpl_iter_write_common(struct kiocb *kiocb, const struct iovec *iovp,
++    unsigned long nr_segs, size_t count)
+ {
+ 	cred_t *cr = CRED();
+ 	struct file *filp = kiocb->ki_filp;
+-	size_t count = kiocb->ki_nbytes;
+ 	ssize_t wrote;
+ 	size_t alloc_size = sizeof (struct iovec) * nr_segs;
+ 	struct iovec *iov_tmp = kmem_alloc(alloc_size, KM_SLEEP);
+@@ -367,6 +380,22 @@ zpl_aio_write(struct kiocb *kiocb, const struct iovec *iovp,
+ 	return (wrote);
+ }
+ 
++#if defined(HAVE_VFS_RW_ITERATE)
++static ssize_t
++zpl_iter_write(struct kiocb *kiocb, struct iov_iter *from)
++{
++	return (zpl_iter_write_common(kiocb, from->iov, from->nr_segs,
++	    iov_iter_count(from)));
++}
++#else
++static ssize_t
++zpl_aio_write(struct kiocb *kiocb, const struct iovec *iovp,
++    unsigned long nr_segs, loff_t pos)
++{
++	return (zpl_iter_write_common(kiocb, iovp, nr_segs, kiocb->ki_nbytes));
++}
++#endif /* HAVE_VFS_RW_ITERATE */
++
+ static loff_t
+ zpl_llseek(struct file *filp, loff_t offset, int whence)
+ {
+@@ -778,8 +807,13 @@ const struct file_operations zpl_file_operations = {
+ 	.llseek		= zpl_llseek,
+ 	.read		= zpl_read,
+ 	.write		= zpl_write,
++#ifdef HAVE_VFS_RW_ITERATE
++	.read_iter	= zpl_iter_read,
++	.write_iter	= zpl_iter_write,
++#else
+ 	.aio_read	= zpl_aio_read,
+ 	.aio_write	= zpl_aio_write,
++#endif
+ 	.mmap		= zpl_mmap,
+ 	.fsync		= zpl_fsync,
+ 	.aio_fsync	= zpl_aio_fsync,