mirror of
https://git.proxmox.com/git/mirror_zfs
synced 2025-04-28 16:36:26 +00:00

Originally #16856 updated Linux Direct I/O requests to use the new pin_user_pages API. However, it was an oversight that this PR only handled iov_iter's of type ITER_IOVEC and ITER_UBUF. Other iov_iter types may try and use the pin_user_pages API if it is available. This can lead to panics as the iov_iter is not being iterated over correctly in zfs_uio_pin_user_pages(). Unfortunately, generic iov_iter API's that call pin_user_page_fast() are protected as GPL only. Rather than update zfs_uio_pin_user_pages() to account for all iov_iter types, we can simply just call zfs_uio_get_dio_page_iov_iter() if the iov_iter type is not ITER_IOVEC or ITER_UBUF. zfs_uio_get_dio_page_iov_iter() calls the iov_iter_get_pages() calls that can handle any iov_iter type. In the future it might be worth using the exposed iov_iter iterator functions that are included in the header iov_iter.h since v6.7. These functions allow for any iov_iter type to be iterated over and advanced while applying a step function during iteration. This could possibly be leveraged in zfs_uio_pin_user_pages(). A new ZFS test case was added to test that a ITER_BVEC is handled correctly using this new code path. This test case was provided though issue #16956. Reviewed-by: Alexander Motin <mav@FreeBSD.org> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Ameer Hamza <ahamza@ixsystems.com> Signed-off-by: Brian Atkinson <batkinson@lanl.gov> Closes #16956 Closes #17006
121 lines
3.1 KiB
Plaintext
121 lines
3.1 KiB
Plaintext
dnl #
|
|
dnl # Check for available iov_iter functionality.
|
|
dnl #
|
|
AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_IOV_ITER], [
|
|
ZFS_LINUX_TEST_SRC([fault_in_iov_iter_readable], [
|
|
#include <linux/fs.h>
|
|
#include <linux/uio.h>
|
|
],[
|
|
struct iov_iter iter = { 0 };
|
|
size_t size = 512;
|
|
int error __attribute__ ((unused));
|
|
|
|
error = fault_in_iov_iter_readable(&iter, size);
|
|
])
|
|
|
|
ZFS_LINUX_TEST_SRC([iov_iter_type], [
|
|
#include <linux/fs.h>
|
|
#include <linux/uio.h>
|
|
],[
|
|
struct iov_iter iter = { 0 };
|
|
__attribute__((unused)) enum iter_type i = iov_iter_type(&iter);
|
|
])
|
|
|
|
ZFS_LINUX_TEST_SRC([iov_iter_get_pages2], [
|
|
#include <linux/uio.h>
|
|
],[
|
|
struct iov_iter iter = { 0 };
|
|
struct page **pages = NULL;
|
|
size_t maxsize = 4096;
|
|
unsigned maxpages = 1;
|
|
size_t start;
|
|
size_t ret __attribute__ ((unused));
|
|
|
|
ret = iov_iter_get_pages2(&iter, pages, maxsize, maxpages,
|
|
&start);
|
|
])
|
|
|
|
ZFS_LINUX_TEST_SRC([iter_is_ubuf], [
|
|
#include <linux/uio.h>
|
|
],[
|
|
struct iov_iter iter = { 0 };
|
|
bool ret __attribute__((unused));
|
|
|
|
ret = iter_is_ubuf(&iter);
|
|
])
|
|
|
|
ZFS_LINUX_TEST_SRC([iter_iov], [
|
|
#include <linux/fs.h>
|
|
#include <linux/uio.h>
|
|
],[
|
|
struct iov_iter iter = { 0 };
|
|
__attribute__((unused)) const struct iovec *iov = iter_iov(&iter);
|
|
])
|
|
])
|
|
|
|
AC_DEFUN([ZFS_AC_KERNEL_VFS_IOV_ITER], [
|
|
|
|
AC_MSG_CHECKING([whether fault_in_iov_iter_readable() is available])
|
|
ZFS_LINUX_TEST_RESULT([fault_in_iov_iter_readable], [
|
|
AC_MSG_RESULT(yes)
|
|
AC_DEFINE(HAVE_FAULT_IN_IOV_ITER_READABLE, 1,
|
|
[fault_in_iov_iter_readable() is available])
|
|
],[
|
|
AC_MSG_RESULT(no)
|
|
])
|
|
|
|
dnl #
|
|
dnl # This checks for iov_iter_type() in linux/uio.h. It is not
|
|
dnl # required, however, and the module will compiled without it
|
|
dnl # using direct access of the member attribute
|
|
dnl #
|
|
AC_MSG_CHECKING([whether iov_iter_type() is available])
|
|
ZFS_LINUX_TEST_RESULT([iov_iter_type], [
|
|
AC_MSG_RESULT(yes)
|
|
AC_DEFINE(HAVE_IOV_ITER_TYPE, 1,
|
|
[iov_iter_type() is available])
|
|
],[
|
|
AC_MSG_RESULT(no)
|
|
])
|
|
|
|
|
|
dnl #
|
|
dnl # Kernel 6.0 changed iov_iter_get_pages() to iov_iter_get_pages2().
|
|
dnl #
|
|
AC_MSG_CHECKING([whether iov_iter_get_pages2() is available])
|
|
ZFS_LINUX_TEST_RESULT([iov_iter_get_pages2], [
|
|
AC_MSG_RESULT(yes)
|
|
AC_DEFINE(HAVE_IOV_ITER_GET_PAGES2, 1,
|
|
[iov_iter_get_pages2() is available])
|
|
],[
|
|
AC_MSG_RESULT(no)
|
|
])
|
|
|
|
dnl #
|
|
dnl # Kernel 6.0 introduced the ITER_UBUF iov_iter type. iter_is_ubuf()
|
|
dnl # was also added to determine if the iov_iter is an ITER_UBUF.
|
|
dnl #
|
|
AC_MSG_CHECKING([whether iter_is_ubuf() is available])
|
|
ZFS_LINUX_TEST_RESULT([iter_is_ubuf], [
|
|
AC_MSG_RESULT(yes)
|
|
AC_DEFINE(HAVE_ITER_IS_UBUF, 1, [iter_is_ubuf() is available])
|
|
],[
|
|
AC_MSG_RESULT(no)
|
|
])
|
|
|
|
dnl #
|
|
dnl # Kernel 6.5 introduces the iter_iov() function that returns the
|
|
dnl # __iov member of an iov_iter*. The iov member was renamed to this
|
|
dnl # __iov member, and is intended to be accessed via the helper
|
|
dnl # function now.
|
|
dnl #
|
|
AC_MSG_CHECKING([whether iter_iov() is available])
|
|
ZFS_LINUX_TEST_RESULT([iter_iov], [
|
|
AC_MSG_RESULT(yes)
|
|
AC_DEFINE(HAVE_ITER_IOV, 1,
|
|
[iter_iov() is available])
|
|
],[
|
|
AC_MSG_RESULT(no)
|
|
])
|
|
])
|