mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2025-01-13 11:40:25 +03:00
Linux 4.14 compat: vfs_read & vfs_write
The kernel_read & kernel_write functions have always wrapped the vfs_read & vfs_write functions respectively. However, they could not be used by vn_rdwr() since the offset wasn't passed as a pointer. This prevented us from being able to properly update the file offset. Linux 4.14 unexported vfs_read & vfs_write but also changed the signature of kernel_read & kernel_write to provide the needed functionality. Use these updated functions when available. Reviewed-by: Pritam Baral <pritam@pritambaral.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #656 Closes #667
This commit is contained in:
parent
35a44fcb8d
commit
ed19bccfb6
@ -52,6 +52,8 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [
|
|||||||
SPL_AC_KMEM_CACHE_CREATE_USERCOPY
|
SPL_AC_KMEM_CACHE_CREATE_USERCOPY
|
||||||
SPL_AC_WAIT_QUEUE_ENTRY_T
|
SPL_AC_WAIT_QUEUE_ENTRY_T
|
||||||
SPL_AC_WAIT_QUEUE_HEAD_ENTRY
|
SPL_AC_WAIT_QUEUE_HEAD_ENTRY
|
||||||
|
SPL_AC_KERNEL_WRITE
|
||||||
|
SPL_AC_KERNEL_READ
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN([SPL_AC_MODULE_SYMVERS], [
|
AC_DEFUN([SPL_AC_MODULE_SYMVERS], [
|
||||||
@ -1594,3 +1596,61 @@ AC_DEFUN([SPL_AC_WAIT_QUEUE_HEAD_ENTRY], [
|
|||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dnl #
|
||||||
|
dnl # 4.14 API change
|
||||||
|
dnl # kernel_write() which was introduced in 3.9 was updated to take
|
||||||
|
dnl # the offset as a pointer which is needed by vn_rdwr().
|
||||||
|
dnl #
|
||||||
|
AC_DEFUN([SPL_AC_KERNEL_WRITE], [
|
||||||
|
AC_MSG_CHECKING([whether kernel_write() takes loff_t pointer])
|
||||||
|
tmp_flags="$EXTRA_KCFLAGS"
|
||||||
|
EXTRA_KCFLAGS="-Werror"
|
||||||
|
SPL_LINUX_TRY_COMPILE([
|
||||||
|
#include <linux/fs.h>
|
||||||
|
],[
|
||||||
|
struct file *file = NULL;
|
||||||
|
const void *buf = NULL;
|
||||||
|
size_t count = 0;
|
||||||
|
loff_t *pos = NULL;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
ret = kernel_write(file, buf, count, pos);
|
||||||
|
],[
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
AC_DEFINE(HAVE_KERNEL_WRITE_PPOS, 1,
|
||||||
|
[kernel_write() take loff_t pointer])
|
||||||
|
],[
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
])
|
||||||
|
EXTRA_KCFLAGS="$tmp_flags"
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl #
|
||||||
|
dnl # 4.14 API change
|
||||||
|
dnl # kernel_read() which has existed for forever was updated to take
|
||||||
|
dnl # the offset as a pointer which is needed by vn_rdwr().
|
||||||
|
dnl #
|
||||||
|
AC_DEFUN([SPL_AC_KERNEL_READ], [
|
||||||
|
AC_MSG_CHECKING([whether kernel_read() takes loff_t pointer])
|
||||||
|
tmp_flags="$EXTRA_KCFLAGS"
|
||||||
|
EXTRA_KCFLAGS="-Werror"
|
||||||
|
SPL_LINUX_TRY_COMPILE([
|
||||||
|
#include <linux/fs.h>
|
||||||
|
],[
|
||||||
|
struct file *file = NULL;
|
||||||
|
void *buf = NULL;
|
||||||
|
size_t count = 0;
|
||||||
|
loff_t *pos = NULL;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
ret = kernel_read(file, buf, count, pos);
|
||||||
|
],[
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
AC_DEFINE(HAVE_KERNEL_READ_PPOS, 1,
|
||||||
|
[kernel_read() take loff_t pointer])
|
||||||
|
],[
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
])
|
||||||
|
EXTRA_KCFLAGS="$tmp_flags"
|
||||||
|
])
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#define _SPL_FILE_COMPAT_H
|
#define _SPL_FILE_COMPAT_H
|
||||||
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
#ifdef HAVE_FDTABLE_HEADER
|
#ifdef HAVE_FDTABLE_HEADER
|
||||||
#include <linux/fdtable.h>
|
#include <linux/fdtable.h>
|
||||||
#endif
|
#endif
|
||||||
@ -70,6 +71,46 @@ spl_filp_fallocate(struct file *fp, int mode, loff_t offset, loff_t len)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline ssize_t
|
||||||
|
spl_kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_KERNEL_WRITE_PPOS)
|
||||||
|
return (kernel_write(file, buf, count, pos));
|
||||||
|
#else
|
||||||
|
mm_segment_t saved_fs;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
saved_fs = get_fs();
|
||||||
|
set_fs(get_ds());
|
||||||
|
|
||||||
|
ret = vfs_write(file, (__force const char __user *)buf, count, pos);
|
||||||
|
|
||||||
|
set_fs(saved_fs);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline ssize_t
|
||||||
|
spl_kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_KERNEL_READ_PPOS)
|
||||||
|
return (kernel_read(file, buf, count, pos));
|
||||||
|
#else
|
||||||
|
mm_segment_t saved_fs;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
saved_fs = get_fs();
|
||||||
|
set_fs(get_ds());
|
||||||
|
|
||||||
|
ret = vfs_read(file, (void __user *)buf, count, pos);
|
||||||
|
|
||||||
|
set_fs(saved_fs);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_2ARGS_VFS_FSYNC
|
#ifdef HAVE_2ARGS_VFS_FSYNC
|
||||||
#define spl_filp_fsync(fp, sync) vfs_fsync(fp, sync)
|
#define spl_filp_fsync(fp, sync) vfs_fsync(fp, sync)
|
||||||
#else
|
#else
|
||||||
|
@ -211,35 +211,22 @@ int
|
|||||||
vn_rdwr(uio_rw_t uio, vnode_t *vp, void *addr, ssize_t len, offset_t off,
|
vn_rdwr(uio_rw_t uio, vnode_t *vp, void *addr, ssize_t len, offset_t off,
|
||||||
uio_seg_t seg, int ioflag, rlim64_t x2, void *x3, ssize_t *residp)
|
uio_seg_t seg, int ioflag, rlim64_t x2, void *x3, ssize_t *residp)
|
||||||
{
|
{
|
||||||
loff_t offset;
|
struct file *fp = vp->v_file;
|
||||||
mm_segment_t saved_fs;
|
loff_t offset = off;
|
||||||
struct file *fp;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
ASSERT(uio == UIO_WRITE || uio == UIO_READ);
|
ASSERT(uio == UIO_WRITE || uio == UIO_READ);
|
||||||
ASSERT(vp);
|
|
||||||
ASSERT(vp->v_file);
|
|
||||||
ASSERT(seg == UIO_SYSSPACE);
|
ASSERT(seg == UIO_SYSSPACE);
|
||||||
ASSERT((ioflag & ~FAPPEND) == 0);
|
ASSERT((ioflag & ~FAPPEND) == 0);
|
||||||
|
|
||||||
fp = vp->v_file;
|
|
||||||
|
|
||||||
offset = off;
|
|
||||||
if (ioflag & FAPPEND)
|
if (ioflag & FAPPEND)
|
||||||
offset = fp->f_pos;
|
offset = fp->f_pos;
|
||||||
|
|
||||||
/* Writable user data segment must be briefly increased for this
|
|
||||||
* process so we can use the user space read call paths to write
|
|
||||||
* in to memory allocated by the kernel. */
|
|
||||||
saved_fs = get_fs();
|
|
||||||
set_fs(get_ds());
|
|
||||||
|
|
||||||
if (uio & UIO_WRITE)
|
if (uio & UIO_WRITE)
|
||||||
rc = vfs_write(fp, addr, len, &offset);
|
rc = spl_kernel_write(fp, addr, len, &offset);
|
||||||
else
|
else
|
||||||
rc = vfs_read(fp, addr, len, &offset);
|
rc = spl_kernel_read(fp, addr, len, &offset);
|
||||||
|
|
||||||
set_fs(saved_fs);
|
|
||||||
fp->f_pos = offset;
|
fp->f_pos = offset;
|
||||||
|
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user