Skip to content

Commit

Permalink
Linux 4.1 compat: use read_iter() / write_iter()
Browse files Browse the repository at this point in the history
Linux 3.15 commit torvalds/linux@293bc98 introduced two new methods.
The ->read_iter() and ->write_iter() methods were designed to replace
the ->aio_read() and ->aio_write() interfaces.  Both interfaces were
preserved for several kernel releases in order to migrate all existing
consumers to the new interfaces.  But as of Linux 4.1 the legacy
interface has been retired and the ZFS code must be updated to use
the new interfaces.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #3352
  • Loading branch information
mk01 authored and behlendorf committed Jun 18, 2015
1 parent ec1c11d commit 57ae840
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 8 deletions.
27 changes: 27 additions & 0 deletions config/kernel-vfs-rw-iterate.m4
Original file line number Diff line number Diff line change
@@ -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)
])
])
1 change: 1 addition & 0 deletions config/kernel.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
50 changes: 42 additions & 8 deletions module/zfs/zpl_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand All @@ -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,
Expand Down Expand Up @@ -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);
Expand All @@ -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)
{
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 57ae840

Please sign in to comment.