diff --git a/pkgs/os-specific/linux/zfs/default.nix b/pkgs/os-specific/linux/zfs/default.nix index bd4b0c23c8b1..6ed168c70bec 100644 --- a/pkgs/os-specific/linux/zfs/default.nix +++ b/pkgs/os-specific/linux/zfs/default.nix @@ -10,5 +10,8 @@ callPackage ./generic.nix (args // rec { sha256 = "15fh1b2rvzvx4j3vgkwrgy2sd553bzwcvk1zai6phjhb6i2rw8v4"; }; - patches = [ ./nix-build.patch ]; + patches = [ + ./nix-build.patch + ./kernel-4.1-compat.patch + ]; }) 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 000000000000..7e75e843af3e --- /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 ++ ++ 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,