From bc0adba16e0600a898435fa22c803f15e3caa866 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 26 Mar 2018 12:11:18 +0100 Subject: [PATCH] UBUNTU: SAUCE: Fix non-prefaulted page deadlock (LP: #1754584) BugLink: https://bugs.launchpad.net/bugs/1754584 Fix mmap'd libaio read on non-prefaulted page deadlock. This is a hot fix from ZFS upstream that ensure pages are pre-faulted in to avoid deadlock. Performing a read with the target data in a mmap'd page that is map'd into the same blocks that are being read causes a lock on the page and a further lock on the same page when the page is being faulted in, causing deadlock. The current workaround is to prefault the page(s) before the pages are read. This is no current upstream commit ID for this fix, as it landed late on Friday and it's not commited to upstream ZFS. The fix has passed our ZFS regression tests and fixes the issue, so I'd like to get this included into Bionic sooner than later. Signed-off-by: Colin Ian King Signed-off-by: Thadeu Lima de Souza Cascardo --- zfs/META | 2 +- zfs/Makefile.in | 2 + zfs/aclocal.m4 | 1 + zfs/config/user-libaio.m4 | 14 +++++ zfs/config/user.m4 | 1 + zfs/config/zfs-build.m4 | 4 +- zfs/configure | 77 ++++++++++++++++++++++---- zfs/include/Makefile.in | 2 + zfs/include/linux/Makefile.in | 2 + zfs/include/sys/Makefile.in | 2 + zfs/include/sys/crypto/Makefile.in | 2 + zfs/include/sys/fm/Makefile.in | 2 + zfs/include/sys/fm/fs/Makefile.in | 2 + zfs/include/sys/fs/Makefile.in | 2 + zfs/include/sys/sysevent/Makefile.in | 2 + zfs/include/sys/uio_impl.h | 2 +- zfs/module/zcommon/zfs_uio.c | 83 ++++++++++++---------------- zfs/module/zfs/zfs_vnops.c | 8 ++- zfs/zfs_config.h.in | 3 + 19 files changed, 149 insertions(+), 64 deletions(-) create mode 100644 zfs/config/user-libaio.m4 diff --git a/zfs/META b/zfs/META index 67f3b429d5c2..049b610095a3 100644 --- a/zfs/META +++ b/zfs/META @@ -2,7 +2,7 @@ Meta: 1 Name: zfs Branch: 1.0 Version: 0.7.5 -Release: 1ubuntu8 +Release: 1ubuntu11 Release-Tags: relext License: CDDL Author: OpenZFS on Linux diff --git a/zfs/Makefile.in b/zfs/Makefile.in index 9dd300bcc845..ed2c4302788d 100644 --- a/zfs/Makefile.in +++ b/zfs/Makefile.in @@ -195,6 +195,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \ $(top_srcdir)/config/toolchain-simd.m4 \ $(top_srcdir)/config/user-dracut.m4 \ $(top_srcdir)/config/user-frame-larger-than.m4 \ + $(top_srcdir)/config/user-libaio.m4 \ $(top_srcdir)/config/user-libattr.m4 \ $(top_srcdir)/config/user-libblkid.m4 \ $(top_srcdir)/config/user-libtirpc.m4 \ @@ -426,6 +427,7 @@ KERNELCPPFLAGS = @KERNELCPPFLAGS@ KERNELMAKE_PARAMS = @KERNELMAKE_PARAMS@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBAIO = @LIBAIO@ LIBATTR = @LIBATTR@ LIBBLKID = @LIBBLKID@ LIBOBJS = @LIBOBJS@ diff --git a/zfs/aclocal.m4 b/zfs/aclocal.m4 index 84d98a9b5f04..7d89c6e7978f 100644 --- a/zfs/aclocal.m4 +++ b/zfs/aclocal.m4 @@ -1303,6 +1303,7 @@ m4_include([config/mount-helper.m4]) m4_include([config/toolchain-simd.m4]) m4_include([config/user-dracut.m4]) m4_include([config/user-frame-larger-than.m4]) +m4_include([config/user-libaio.m4]) m4_include([config/user-libattr.m4]) m4_include([config/user-libblkid.m4]) m4_include([config/user-libtirpc.m4]) diff --git a/zfs/config/user-libaio.m4 b/zfs/config/user-libaio.m4 new file mode 100644 index 000000000000..d7a7cb508df8 --- /dev/null +++ b/zfs/config/user-libaio.m4 @@ -0,0 +1,14 @@ +dnl # +dnl # Check for libaio - only used for libaiot test cases. +dnl # +AC_DEFUN([ZFS_AC_CONFIG_USER_LIBAIO], [ + LIBAIO= + + AC_CHECK_HEADER([libaio.h], [ + user_libaio=yes + AC_SUBST([LIBAIO], ["-laio"]) + AC_DEFINE([HAVE_LIBAIO], 1, [Define if you have libaio]) + ], [ + user_libaio=no + ]) +]) diff --git a/zfs/config/user.m4 b/zfs/config/user.m4 index 2b033f5a57c5..941fcf03c215 100644 --- a/zfs/config/user.m4 +++ b/zfs/config/user.m4 @@ -13,6 +13,7 @@ AC_DEFUN([ZFS_AC_CONFIG_USER], [ ZFS_AC_CONFIG_USER_LIBTIRPC ZFS_AC_CONFIG_USER_LIBBLKID ZFS_AC_CONFIG_USER_LIBATTR + ZFS_AC_CONFIG_USER_LIBAIO ZFS_AC_CONFIG_USER_LIBUDEV ZFS_AC_CONFIG_USER_FRAME_LARGER_THAN ZFS_AC_CONFIG_USER_RUNSTATEDIR diff --git a/zfs/config/zfs-build.m4 b/zfs/config/zfs-build.m4 index 7651dc2c12e4..1224682fe53f 100644 --- a/zfs/config/zfs-build.m4 +++ b/zfs/config/zfs-build.m4 @@ -79,11 +79,11 @@ AC_DEFUN([ZFS_AC_CONFIG], [ AM_CONDITIONAL([CONFIG_KERNEL], [test "$ZFS_CONFIG" = kernel -o "$ZFS_CONFIG" = all] && [test "x$enable_linux_builtin" != xyes ]) - AM_CONDITIONAL([WANT_DEVNAME2DEVID], - [test "x$user_libudev" = xyes ]) AM_CONDITIONAL([CONFIG_QAT], [test "$ZFS_CONFIG" = kernel -o "$ZFS_CONFIG" = all] && [test "x$qatsrc" != x ]) + AM_CONDITIONAL([WANT_DEVNAME2DEVID], [test "x$user_libudev" = xyes ]) + AM_CONDITIONAL([WANT_MMAP_LIBAIO], [test "x$user_libaio" = xyes ]) ]) dnl # diff --git a/zfs/configure b/zfs/configure index aebe4bbe9984..ea023e85cfac 100755 --- a/zfs/configure +++ b/zfs/configure @@ -635,10 +635,12 @@ LIBOBJS DEBUG_ZFS DEBUG_STACKFLAGS DEBUG_CFLAGS -CONFIG_QAT_FALSE -CONFIG_QAT_TRUE +WANT_MMAP_LIBAIO_FALSE +WANT_MMAP_LIBAIO_TRUE WANT_DEVNAME2DEVID_FALSE WANT_DEVNAME2DEVID_TRUE +CONFIG_QAT_FALSE +CONFIG_QAT_TRUE CONFIG_KERNEL_FALSE CONFIG_KERNEL_TRUE CONFIG_USER_FALSE @@ -648,6 +650,7 @@ ZONENAME NO_FORMAT_TRUNCATION FRAME_LARGER_THAN LIBUDEV +LIBAIO LIBATTR LIBBLKID LIBTIRPC_CFLAGS @@ -26908,6 +26911,27 @@ $as_echo "#define HAVE_LIBATTR 1" >>confdefs.h + LIBAIO= + + ac_fn_c_check_header_mongrel "$LINENO" "libaio.h" "ac_cv_header_libaio_h" "$ac_includes_default" +if test "x$ac_cv_header_libaio_h" = xyes; then : + + user_libaio=yes + LIBAIO="-laio" + + +$as_echo "#define HAVE_LIBAIO 1" >>confdefs.h + + +else + + user_libaio=no + +fi + + + + LIBUDEV= ac_fn_c_check_header_mongrel "$LINENO" "libudev.h" "ac_cv_header_libudev_h" "$ac_includes_default" @@ -27936,6 +27960,27 @@ $as_echo "#define HAVE_LIBATTR 1" >>confdefs.h + LIBAIO= + + ac_fn_c_check_header_mongrel "$LINENO" "libaio.h" "ac_cv_header_libaio_h" "$ac_includes_default" +if test "x$ac_cv_header_libaio_h" = xyes; then : + + user_libaio=yes + LIBAIO="-laio" + + +$as_echo "#define HAVE_LIBAIO 1" >>confdefs.h + + +else + + user_libaio=no + +fi + + + + LIBUDEV= ac_fn_c_check_header_mongrel "$LINENO" "libudev.h" "ac_cv_header_libudev_h" "$ac_includes_default" @@ -40914,6 +40959,15 @@ else CONFIG_KERNEL_FALSE= fi + if test "$ZFS_CONFIG" = kernel -o "$ZFS_CONFIG" = all && + test "x$qatsrc" != x ; then + CONFIG_QAT_TRUE= + CONFIG_QAT_FALSE='#' +else + CONFIG_QAT_TRUE='#' + CONFIG_QAT_FALSE= +fi + if test "x$user_libudev" = xyes ; then WANT_DEVNAME2DEVID_TRUE= WANT_DEVNAME2DEVID_FALSE='#' @@ -40922,13 +40976,12 @@ else WANT_DEVNAME2DEVID_FALSE= fi - if test "$ZFS_CONFIG" = kernel -o "$ZFS_CONFIG" = all && - test "x$qatsrc" != x ; then - CONFIG_QAT_TRUE= - CONFIG_QAT_FALSE='#' + if test "x$user_libaio" = xyes ; then + WANT_MMAP_LIBAIO_TRUE= + WANT_MMAP_LIBAIO_FALSE='#' else - CONFIG_QAT_TRUE='#' - CONFIG_QAT_FALSE= + WANT_MMAP_LIBAIO_TRUE='#' + WANT_MMAP_LIBAIO_FALSE= fi @@ -41136,12 +41189,16 @@ if test -z "${CONFIG_KERNEL_TRUE}" && test -z "${CONFIG_KERNEL_FALSE}"; then as_fn_error $? "conditional \"CONFIG_KERNEL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${CONFIG_QAT_TRUE}" && test -z "${CONFIG_QAT_FALSE}"; then + as_fn_error $? "conditional \"CONFIG_QAT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${WANT_DEVNAME2DEVID_TRUE}" && test -z "${WANT_DEVNAME2DEVID_FALSE}"; then as_fn_error $? "conditional \"WANT_DEVNAME2DEVID\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${CONFIG_QAT_TRUE}" && test -z "${CONFIG_QAT_FALSE}"; then - as_fn_error $? "conditional \"CONFIG_QAT\" was never defined. +if test -z "${WANT_MMAP_LIBAIO_TRUE}" && test -z "${WANT_MMAP_LIBAIO_FALSE}"; then + as_fn_error $? "conditional \"WANT_MMAP_LIBAIO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi diff --git a/zfs/include/Makefile.in b/zfs/include/Makefile.in index ae748a95e4bc..acd99dcf2e15 100644 --- a/zfs/include/Makefile.in +++ b/zfs/include/Makefile.in @@ -187,6 +187,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \ $(top_srcdir)/config/toolchain-simd.m4 \ $(top_srcdir)/config/user-dracut.m4 \ $(top_srcdir)/config/user-frame-larger-than.m4 \ + $(top_srcdir)/config/user-libaio.m4 \ $(top_srcdir)/config/user-libattr.m4 \ $(top_srcdir)/config/user-libblkid.m4 \ $(top_srcdir)/config/user-libtirpc.m4 \ @@ -400,6 +401,7 @@ KERNELCPPFLAGS = @KERNELCPPFLAGS@ KERNELMAKE_PARAMS = @KERNELMAKE_PARAMS@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBAIO = @LIBAIO@ LIBATTR = @LIBATTR@ LIBBLKID = @LIBBLKID@ LIBOBJS = @LIBOBJS@ diff --git a/zfs/include/linux/Makefile.in b/zfs/include/linux/Makefile.in index 0f6c8c36afff..1002d8347086 100644 --- a/zfs/include/linux/Makefile.in +++ b/zfs/include/linux/Makefile.in @@ -187,6 +187,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \ $(top_srcdir)/config/toolchain-simd.m4 \ $(top_srcdir)/config/user-dracut.m4 \ $(top_srcdir)/config/user-frame-larger-than.m4 \ + $(top_srcdir)/config/user-libaio.m4 \ $(top_srcdir)/config/user-libattr.m4 \ $(top_srcdir)/config/user-libblkid.m4 \ $(top_srcdir)/config/user-libtirpc.m4 \ @@ -345,6 +346,7 @@ KERNELCPPFLAGS = @KERNELCPPFLAGS@ KERNELMAKE_PARAMS = @KERNELMAKE_PARAMS@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBAIO = @LIBAIO@ LIBATTR = @LIBATTR@ LIBBLKID = @LIBBLKID@ LIBOBJS = @LIBOBJS@ diff --git a/zfs/include/sys/Makefile.in b/zfs/include/sys/Makefile.in index 25d1f71541d5..c24010a0b962 100644 --- a/zfs/include/sys/Makefile.in +++ b/zfs/include/sys/Makefile.in @@ -187,6 +187,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \ $(top_srcdir)/config/toolchain-simd.m4 \ $(top_srcdir)/config/user-dracut.m4 \ $(top_srcdir)/config/user-frame-larger-than.m4 \ + $(top_srcdir)/config/user-libaio.m4 \ $(top_srcdir)/config/user-libattr.m4 \ $(top_srcdir)/config/user-libblkid.m4 \ $(top_srcdir)/config/user-libtirpc.m4 \ @@ -606,6 +607,7 @@ KERNELCPPFLAGS = @KERNELCPPFLAGS@ KERNELMAKE_PARAMS = @KERNELMAKE_PARAMS@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBAIO = @LIBAIO@ LIBATTR = @LIBATTR@ LIBBLKID = @LIBBLKID@ LIBOBJS = @LIBOBJS@ diff --git a/zfs/include/sys/crypto/Makefile.in b/zfs/include/sys/crypto/Makefile.in index fa2f570a08ab..79a03c57caaa 100644 --- a/zfs/include/sys/crypto/Makefile.in +++ b/zfs/include/sys/crypto/Makefile.in @@ -187,6 +187,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \ $(top_srcdir)/config/toolchain-simd.m4 \ $(top_srcdir)/config/user-dracut.m4 \ $(top_srcdir)/config/user-frame-larger-than.m4 \ + $(top_srcdir)/config/user-libaio.m4 \ $(top_srcdir)/config/user-libattr.m4 \ $(top_srcdir)/config/user-libblkid.m4 \ $(top_srcdir)/config/user-libtirpc.m4 \ @@ -342,6 +343,7 @@ KERNELCPPFLAGS = @KERNELCPPFLAGS@ KERNELMAKE_PARAMS = @KERNELMAKE_PARAMS@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBAIO = @LIBAIO@ LIBATTR = @LIBATTR@ LIBBLKID = @LIBBLKID@ LIBOBJS = @LIBOBJS@ diff --git a/zfs/include/sys/fm/Makefile.in b/zfs/include/sys/fm/Makefile.in index 85019a12269d..a73b969694ad 100644 --- a/zfs/include/sys/fm/Makefile.in +++ b/zfs/include/sys/fm/Makefile.in @@ -187,6 +187,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \ $(top_srcdir)/config/toolchain-simd.m4 \ $(top_srcdir)/config/user-dracut.m4 \ $(top_srcdir)/config/user-frame-larger-than.m4 \ + $(top_srcdir)/config/user-libaio.m4 \ $(top_srcdir)/config/user-libattr.m4 \ $(top_srcdir)/config/user-libblkid.m4 \ $(top_srcdir)/config/user-libtirpc.m4 \ @@ -382,6 +383,7 @@ KERNELCPPFLAGS = @KERNELCPPFLAGS@ KERNELMAKE_PARAMS = @KERNELMAKE_PARAMS@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBAIO = @LIBAIO@ LIBATTR = @LIBATTR@ LIBBLKID = @LIBBLKID@ LIBOBJS = @LIBOBJS@ diff --git a/zfs/include/sys/fm/fs/Makefile.in b/zfs/include/sys/fm/fs/Makefile.in index 42a85e5602d6..03e329892083 100644 --- a/zfs/include/sys/fm/fs/Makefile.in +++ b/zfs/include/sys/fm/fs/Makefile.in @@ -187,6 +187,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \ $(top_srcdir)/config/toolchain-simd.m4 \ $(top_srcdir)/config/user-dracut.m4 \ $(top_srcdir)/config/user-frame-larger-than.m4 \ + $(top_srcdir)/config/user-libaio.m4 \ $(top_srcdir)/config/user-libattr.m4 \ $(top_srcdir)/config/user-libblkid.m4 \ $(top_srcdir)/config/user-libtirpc.m4 \ @@ -338,6 +339,7 @@ KERNELCPPFLAGS = @KERNELCPPFLAGS@ KERNELMAKE_PARAMS = @KERNELMAKE_PARAMS@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBAIO = @LIBAIO@ LIBATTR = @LIBATTR@ LIBBLKID = @LIBBLKID@ LIBOBJS = @LIBOBJS@ diff --git a/zfs/include/sys/fs/Makefile.in b/zfs/include/sys/fs/Makefile.in index d22d5fc458b1..8ea51c9fc7bf 100644 --- a/zfs/include/sys/fs/Makefile.in +++ b/zfs/include/sys/fs/Makefile.in @@ -187,6 +187,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \ $(top_srcdir)/config/toolchain-simd.m4 \ $(top_srcdir)/config/user-dracut.m4 \ $(top_srcdir)/config/user-frame-larger-than.m4 \ + $(top_srcdir)/config/user-libaio.m4 \ $(top_srcdir)/config/user-libattr.m4 \ $(top_srcdir)/config/user-libblkid.m4 \ $(top_srcdir)/config/user-libtirpc.m4 \ @@ -338,6 +339,7 @@ KERNELCPPFLAGS = @KERNELCPPFLAGS@ KERNELMAKE_PARAMS = @KERNELMAKE_PARAMS@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBAIO = @LIBAIO@ LIBATTR = @LIBATTR@ LIBBLKID = @LIBBLKID@ LIBOBJS = @LIBOBJS@ diff --git a/zfs/include/sys/sysevent/Makefile.in b/zfs/include/sys/sysevent/Makefile.in index 12c09129c2cd..2a9b50475320 100644 --- a/zfs/include/sys/sysevent/Makefile.in +++ b/zfs/include/sys/sysevent/Makefile.in @@ -187,6 +187,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \ $(top_srcdir)/config/toolchain-simd.m4 \ $(top_srcdir)/config/user-dracut.m4 \ $(top_srcdir)/config/user-frame-larger-than.m4 \ + $(top_srcdir)/config/user-libaio.m4 \ $(top_srcdir)/config/user-libattr.m4 \ $(top_srcdir)/config/user-libblkid.m4 \ $(top_srcdir)/config/user-libtirpc.m4 \ @@ -342,6 +343,7 @@ KERNELCPPFLAGS = @KERNELCPPFLAGS@ KERNELMAKE_PARAMS = @KERNELMAKE_PARAMS@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBAIO = @LIBAIO@ LIBATTR = @LIBATTR@ LIBBLKID = @LIBBLKID@ LIBOBJS = @LIBOBJS@ diff --git a/zfs/include/sys/uio_impl.h b/zfs/include/sys/uio_impl.h index 37e283da0f8b..01ca723c0612 100644 --- a/zfs/include/sys/uio_impl.h +++ b/zfs/include/sys/uio_impl.h @@ -42,7 +42,7 @@ #include extern int uiomove(void *, size_t, enum uio_rw, uio_t *); -extern void uio_prefaultpages(ssize_t, uio_t *); +extern int uio_prefaultpages(ssize_t, enum uio_rw, uio_t *); extern int uiocopy(void *, size_t, enum uio_rw, uio_t *, size_t *); extern void uioskip(uio_t *, size_t); diff --git a/zfs/module/zcommon/zfs_uio.c b/zfs/module/zcommon/zfs_uio.c index 7b4175bbeeeb..0001f9510a5d 100644 --- a/zfs/module/zcommon/zfs_uio.c +++ b/zfs/module/zcommon/zfs_uio.c @@ -148,64 +148,51 @@ uiomove(void *p, size_t n, enum uio_rw rw, struct uio *uio) } EXPORT_SYMBOL(uiomove); -#define fuword8(uptr, vptr) get_user((*vptr), (uptr)) - /* - * Fault in the pages of the first n bytes specified by the uio structure. - * 1 byte in each page is touched and the uio struct is unmodified. Any - * error will terminate the process as this is only a best attempt to get - * the pages resident. + * Fault in the user space pages specified by the uio structure. Note that + * when faulting in pages with UIO_READ they may have zeros written to them + * which is OK because we know they'll be overwritten. */ -void -uio_prefaultpages(ssize_t n, struct uio *uio) +int +uio_prefaultpages(ssize_t n, enum uio_rw rw, struct uio *uio) { - const struct iovec *iov; - ulong_t cnt, incr; - caddr_t p; - uint8_t tmp; - int iovcnt; - size_t skip; + const struct iovec *iov = uio->uio_iov; + size_t skip = uio->uio_skip; + int iovcnt = uio->uio_iovcnt; + uio_seg_t seg = uio->uio_segflg; + char __user *p; + ulong_t cnt; + int error; - /* no need to fault in kernel pages */ - switch (uio->uio_segflg) { - case UIO_SYSSPACE: - case UIO_BVEC: - return; - case UIO_USERSPACE: - case UIO_USERISPACE: - break; - default: - ASSERT(0); - } + /* No need to fault in kernel pages */ + if (seg == UIO_SYSSPACE || seg == UIO_BVEC) + return (0); - iov = uio->uio_iov; - iovcnt = uio->uio_iovcnt; - skip = uio->uio_skip; + ASSERT(seg == UIO_USERSPACE || seg == UIO_USERISPACE); - for (; n > 0 && iovcnt > 0; iov++, iovcnt--, skip = 0) { + while ((n > 0) && (iovcnt > 0)) { cnt = MIN(iov->iov_len - skip, n); - /* empty iov */ - if (cnt == 0) - continue; - n -= cnt; - /* - * touch each page in this segment. - */ p = iov->iov_base + skip; - while (cnt) { - if (fuword8((uint8_t *)p, &tmp)) - return; - incr = MIN(cnt, PAGESIZE); - p += incr; - cnt -= incr; + + if (rw == UIO_READ) + error = -fault_in_pages_writeable(p, cnt); + else + error = -fault_in_pages_readable(p, cnt); + + if (error) + return (error); + + skip += cnt; + if (skip == iov->iov_len) { + skip = 0; + iov++; + iovcnt--; } - /* - * touch the last byte in case it straddles a page. - */ - p--; - if (fuword8((uint8_t *)p, &tmp)) - return; + + n -= cnt; } + + return (0); } EXPORT_SYMBOL(uio_prefaultpages); diff --git a/zfs/module/zfs/zfs_vnops.c b/zfs/module/zfs/zfs_vnops.c index 6a1dab5c984e..9338bb041727 100644 --- a/zfs/module/zfs/zfs_vnops.c +++ b/zfs/module/zfs/zfs_vnops.c @@ -390,6 +390,10 @@ mappedread(struct inode *ip, int nbytes, uio_t *uio) int error = 0; void *pb; + error = uio_prefaultpages(nbytes, UIO_READ, uio); + if (error) + return (error); + start = uio->uio_loffset; off = start & (PAGE_SIZE-1); for (start &= PAGE_MASK; len > 0; start += PAGE_SIZE) { @@ -675,7 +679,7 @@ zfs_write(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr) xuio = (xuio_t *)uio; else #endif - uio_prefaultpages(MIN(n, max_blksz), uio); + uio_prefaultpages(MIN(n, max_blksz), UIO_WRITE, uio); /* * If in append mode, set the io offset pointer to eof. @@ -921,7 +925,7 @@ zfs_write(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr) n -= nbytes; if (!xuio && n > 0) - uio_prefaultpages(MIN(n, max_blksz), uio); + uio_prefaultpages(MIN(n, max_blksz), UIO_WRITE, uio); } zfs_inode_update(zp); diff --git a/zfs/zfs_config.h.in b/zfs/zfs_config.h.in index ac41b5a9dcee..a87d6ac187b0 100644 --- a/zfs/zfs_config.h.in +++ b/zfs/zfs_config.h.in @@ -312,6 +312,9 @@ /* kernel has large stacks */ #undef HAVE_LARGE_STACKS +/* Define if you have libaio */ +#undef HAVE_LIBAIO + /* Define if you have libattr */ #undef HAVE_LIBATTR -- 2.39.2