diff mbox series

[2/2,BIONIC] UBUNTU: SAUCE: Fix non-prefaulted page deadlock (LP: #1754584)

Message ID 20180328101925.13457-3-colin.king@canonical.com
State New
Headers show
Series Fix non-prefaulted page deadlock | expand

Commit Message

Colin Ian King March 28, 2018, 10:19 a.m. UTC
From: Colin Ian King <colin.king@canonical.com>

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 do not deadlock and replaces the original
fix as it is a far better solution.

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.

This is an improved fix from the original fix which ensures the pages don't
deadlock and removes the original potentially racy pre-faulting fix
    
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 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/module/zfs/zfs_vnops.c           |  2 +-
 zfs/zfs_config.h.in                  |  3 ++
 17 files changed, 108 insertions(+), 14 deletions(-)
 create mode 100644 zfs/config/user-libaio.m4
diff mbox series

Patch

diff --git a/zfs/META b/zfs/META
index 67f3b42..9531bb8 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:      1ubuntu12
 Release-Tags: relext
 License:      CDDL
 Author:       OpenZFS on Linux
diff --git a/zfs/Makefile.in b/zfs/Makefile.in
index 9dd300b..ed2c430 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 84d98a9..7d89c6e 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 0000000..d7a7cb5
--- /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 2b033f5..d5d0a90 100644
--- a/zfs/config/user.m4
+++ b/zfs/config/user.m4
@@ -14,6 +14,7 @@  AC_DEFUN([ZFS_AC_CONFIG_USER], [
 	ZFS_AC_CONFIG_USER_LIBBLKID
 	ZFS_AC_CONFIG_USER_LIBATTR
 	ZFS_AC_CONFIG_USER_LIBUDEV
+	ZFS_AC_CONFIG_USER_LIBAIO
 	ZFS_AC_CONFIG_USER_FRAME_LARGER_THAN
 	ZFS_AC_CONFIG_USER_RUNSTATEDIR
 	ZFS_AC_CONFIG_USER_MAKEDEV_IN_SYSMACROS
diff --git a/zfs/config/zfs-build.m4 b/zfs/config/zfs-build.m4
index 7651dc2..1224682 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 aebe4bb..157b196 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
@@ -647,6 +649,7 @@  RM
 ZONENAME
 NO_FORMAT_TRUNCATION
 FRAME_LARGER_THAN
+LIBAIO
 LIBUDEV
 LIBATTR
 LIBBLKID
@@ -26990,6 +26993,27 @@  fi
 
 
 
+	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
+
+
+
+
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wframe-larger-than=<size> support" >&5
 $as_echo_n "checking for -Wframe-larger-than=<size> support... " >&6; }
 
@@ -28018,6 +28042,27 @@  fi
 
 
 
+	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
+
+
+
+
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wframe-larger-than=<size> support" >&5
 $as_echo_n "checking for -Wframe-larger-than=<size> support... " >&6; }
 
@@ -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 ae748a9..acd99dc 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 0f6c8c3..1002d83 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 25d1f71..c24010a 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 fa2f570..79a03c5 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 85019a1..a73b969 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 42a85e5..03e3298 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 d22d5fc..8ea51c9 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 12c0912..2a9b504 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/module/zfs/zfs_vnops.c b/zfs/module/zfs/zfs_vnops.c
index 6a1dab5..41eb49d 100644
--- a/zfs/module/zfs/zfs_vnops.c
+++ b/zfs/module/zfs/zfs_vnops.c
@@ -398,6 +398,7 @@  mappedread(struct inode *ip, int nbytes, uio_t *uio)
 		pp = find_lock_page(mp, start >> PAGE_SHIFT);
 		if (pp) {
 			ASSERT(PageUptodate(pp));
+			unlock_page(pp);
 
 			pb = kmap(pp);
 			error = uiomove(pb + off, bytes, UIO_READ, uio);
@@ -407,7 +408,6 @@  mappedread(struct inode *ip, int nbytes, uio_t *uio)
 				flush_dcache_page(pp);
 
 			mark_page_accessed(pp);
-			unlock_page(pp);
 			put_page(pp);
 		} else {
 			error = dmu_read_uio_dbuf(sa_get_db(zp->z_sa_hdl),
diff --git a/zfs/zfs_config.h.in b/zfs/zfs_config.h.in
index ac41b5a..a87d6ac 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