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

Colin King colin.king at canonical.com
Wed Mar 28 15:39:40 UTC 2018


From: Colin Ian King <colin.king at 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.

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.

Signed-off-by: Colin Ian King <colin.king at 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           |  2 ++
 zfs/configure                     | 71 +++++++++++++++++++++++++++++++++++++++
 zfs/include/Makefile.in           |  2 ++
 zfs/include/linux/Makefile.in     |  2 ++
 zfs/include/sys/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/module/zfs/zfs_vnops.c        |  2 +-
 zfs/zfs_config.h.in               |  3 ++
 15 files changed, 108 insertions(+), 2 deletions(-)
 create mode 100644 zfs/config/user-libaio.m4

diff --git a/zfs/META b/zfs/META
index 476e914..8d835fa 100644
--- a/zfs/META
+++ b/zfs/META
@@ -2,7 +2,7 @@ Meta:         1
 Name:         zfs
 Branch:       1.0
 Version:      0.6.5.11
-Release:      1ubuntu3.2
+Release:      1ubuntu3.3
 Release-Tags: relext
 License:      CDDL
 Author:       OpenZFS on Linux
diff --git a/zfs/Makefile.in b/zfs/Makefile.in
index 0793205..3089589 100644
--- a/zfs/Makefile.in
+++ b/zfs/Makefile.in
@@ -184,6 +184,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-no-bool-compare.m4 \
 	$(top_srcdir)/config/user-arch.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-libblkid.m4 \
 	$(top_srcdir)/config/user-libuuid.m4 \
 	$(top_srcdir)/config/user-makedev.m4 \
@@ -412,6 +413,7 @@ KERNELCPPFLAGS = @KERNELCPPFLAGS@
 KERNELMAKE_PARAMS = @KERNELMAKE_PARAMS@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
+LIBAIO = @LIBAIO@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
diff --git a/zfs/aclocal.m4 b/zfs/aclocal.m4
index 4be3696..a27355f 100644
--- a/zfs/aclocal.m4
+++ b/zfs/aclocal.m4
@@ -1292,6 +1292,7 @@ m4_include([config/mount-helper.m4])
 m4_include([config/user-arch.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-libblkid.m4])
 m4_include([config/user-libuuid.m4])
 m4_include([config/user-makedev.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 8732393..29c81cd 100644
--- a/zfs/config/user.m4
+++ b/zfs/config/user.m4
@@ -5,6 +5,7 @@ AC_DEFUN([ZFS_AC_CONFIG_USER], [
 	ZFS_AC_DKMS_INHIBIT
 	ZFS_AC_CONFIG_USER_MOUNT_HELPER
 	ZFS_AC_CONFIG_USER_UDEV
+	ZFS_AC_CONFIG_USER_LIBAIO
 	ZFS_AC_CONFIG_USER_SYSTEMD
 	ZFS_AC_CONFIG_USER_SYSVINIT
 	ZFS_AC_CONFIG_USER_DRACUT
diff --git a/zfs/config/zfs-build.m4 b/zfs/config/zfs-build.m4
index facd302..65325ce 100644
--- a/zfs/config/zfs-build.m4
+++ b/zfs/config/zfs-build.m4
@@ -103,6 +103,8 @@ 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([WANT_MMAP_LIBAIO], [test "x$user_libaio" = xyes ])
 ])
 
 dnl #
diff --git a/zfs/configure b/zfs/configure
index 9634569..02ce407 100755
--- a/zfs/configure
+++ b/zfs/configure
@@ -636,6 +636,10 @@ DEBUG_DMU_TX
 DEBUG_ZFS
 DEBUG_STACKFLAGS
 DEBUG_CFLAGS
+WANT_MMAP_LIBAIO_FALSE
+WANT_MMAP_LIBAIO_TRUE
+WANT_DEVNAME2DEVID_FALSE
+WANT_DEVNAME2DEVID_TRUE
 CONFIG_KERNEL_FALSE
 CONFIG_KERNEL_TRUE
 CONFIG_USER_FALSE
@@ -662,6 +666,7 @@ systemdpresetdir
 systemdunitdir
 ZFS_MODULE_LOAD
 ZFS_INIT_SYSTEMD
+LIBAIO
 udevruledir
 udevdir
 mounthelperdir
@@ -12901,6 +12906,27 @@ fi
 $as_echo "$udevdir;$udevruledir" >&6; }
 
 
+	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
+
+
+
+
 	# Check whether --enable-systemd was given.
 if test "${enable_systemd+set}" = set; then :
   enableval=$enable_systemd;
@@ -37116,6 +37142,27 @@ fi
 $as_echo "$udevdir;$udevruledir" >&6; }
 
 
+	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
+
+
+
+
 	# Check whether --enable-systemd was given.
 if test "${enable_systemd+set}" = set; then :
   enableval=$enable_systemd;
@@ -37899,6 +37946,22 @@ else
   CONFIG_KERNEL_FALSE=
 fi
 
+	 if test "x$user_libudev" = xyes ; then
+  WANT_DEVNAME2DEVID_TRUE=
+  WANT_DEVNAME2DEVID_FALSE='#'
+else
+  WANT_DEVNAME2DEVID_TRUE='#'
+  WANT_DEVNAME2DEVID_FALSE=
+fi
+
+	 if test "x$user_libaio" = xyes ; then
+  WANT_MMAP_LIBAIO_TRUE=
+  WANT_MMAP_LIBAIO_FALSE='#'
+else
+  WANT_MMAP_LIBAIO_TRUE='#'
+  WANT_MMAP_LIBAIO_FALSE=
+fi
+
 
 
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether debugging is enabled" >&5
@@ -38120,6 +38183,14 @@ 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 "${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 "${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
 
 : "${CONFIG_STATUS=./config.status}"
 ac_write_fail=0
diff --git a/zfs/include/Makefile.in b/zfs/include/Makefile.in
index bd90322..7c77b15 100644
--- a/zfs/include/Makefile.in
+++ b/zfs/include/Makefile.in
@@ -176,6 +176,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-no-bool-compare.m4 \
 	$(top_srcdir)/config/user-arch.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-libblkid.m4 \
 	$(top_srcdir)/config/user-libuuid.m4 \
 	$(top_srcdir)/config/user-makedev.m4 \
@@ -387,6 +388,7 @@ KERNELCPPFLAGS = @KERNELCPPFLAGS@
 KERNELMAKE_PARAMS = @KERNELMAKE_PARAMS@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
+LIBAIO = @LIBAIO@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
diff --git a/zfs/include/linux/Makefile.in b/zfs/include/linux/Makefile.in
index 9deb2b6..b774eb2 100644
--- a/zfs/include/linux/Makefile.in
+++ b/zfs/include/linux/Makefile.in
@@ -176,6 +176,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-no-bool-compare.m4 \
 	$(top_srcdir)/config/user-arch.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-libblkid.m4 \
 	$(top_srcdir)/config/user-libuuid.m4 \
 	$(top_srcdir)/config/user-makedev.m4 \
@@ -329,6 +330,7 @@ KERNELCPPFLAGS = @KERNELCPPFLAGS@
 KERNELMAKE_PARAMS = @KERNELMAKE_PARAMS@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
+LIBAIO = @LIBAIO@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
diff --git a/zfs/include/sys/Makefile.in b/zfs/include/sys/Makefile.in
index 68f4a7b..eb1b7d1 100644
--- a/zfs/include/sys/Makefile.in
+++ b/zfs/include/sys/Makefile.in
@@ -176,6 +176,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-no-bool-compare.m4 \
 	$(top_srcdir)/config/user-arch.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-libblkid.m4 \
 	$(top_srcdir)/config/user-libuuid.m4 \
 	$(top_srcdir)/config/user-makedev.m4 \
@@ -561,6 +562,7 @@ KERNELCPPFLAGS = @KERNELCPPFLAGS@
 KERNELMAKE_PARAMS = @KERNELMAKE_PARAMS@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
+LIBAIO = @LIBAIO@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
diff --git a/zfs/include/sys/fm/Makefile.in b/zfs/include/sys/fm/Makefile.in
index aaa8bf9..8ef5437 100644
--- a/zfs/include/sys/fm/Makefile.in
+++ b/zfs/include/sys/fm/Makefile.in
@@ -176,6 +176,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-no-bool-compare.m4 \
 	$(top_srcdir)/config/user-arch.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-libblkid.m4 \
 	$(top_srcdir)/config/user-libuuid.m4 \
 	$(top_srcdir)/config/user-makedev.m4 \
@@ -369,6 +370,7 @@ KERNELCPPFLAGS = @KERNELCPPFLAGS@
 KERNELMAKE_PARAMS = @KERNELMAKE_PARAMS@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
+LIBAIO = @LIBAIO@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
diff --git a/zfs/include/sys/fm/fs/Makefile.in b/zfs/include/sys/fm/fs/Makefile.in
index a0a9a7e..e1277f7 100644
--- a/zfs/include/sys/fm/fs/Makefile.in
+++ b/zfs/include/sys/fm/fs/Makefile.in
@@ -176,6 +176,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-no-bool-compare.m4 \
 	$(top_srcdir)/config/user-arch.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-libblkid.m4 \
 	$(top_srcdir)/config/user-libuuid.m4 \
 	$(top_srcdir)/config/user-makedev.m4 \
@@ -325,6 +326,7 @@ KERNELCPPFLAGS = @KERNELCPPFLAGS@
 KERNELMAKE_PARAMS = @KERNELMAKE_PARAMS@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
+LIBAIO = @LIBAIO@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
diff --git a/zfs/include/sys/fs/Makefile.in b/zfs/include/sys/fs/Makefile.in
index c556d05..1016d24 100644
--- a/zfs/include/sys/fs/Makefile.in
+++ b/zfs/include/sys/fs/Makefile.in
@@ -176,6 +176,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-no-bool-compare.m4 \
 	$(top_srcdir)/config/user-arch.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-libblkid.m4 \
 	$(top_srcdir)/config/user-libuuid.m4 \
 	$(top_srcdir)/config/user-makedev.m4 \
@@ -325,6 +326,7 @@ KERNELCPPFLAGS = @KERNELCPPFLAGS@
 KERNELMAKE_PARAMS = @KERNELMAKE_PARAMS@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
+LIBAIO = @LIBAIO@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
diff --git a/zfs/module/zfs/zfs_vnops.c b/zfs/module/zfs/zfs_vnops.c
index 437a63a..2a5b76d 100644
--- a/zfs/module/zfs/zfs_vnops.c
+++ b/zfs/module/zfs/zfs_vnops.c
@@ -391,6 +391,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);
@@ -400,7 +401,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 94bbeb9..679f31a 100644
--- a/zfs/zfs_config.h.in
+++ b/zfs/zfs_config.h.in
@@ -258,6 +258,9 @@
 /* kernel has large stacks */
 #undef HAVE_LARGE_STACKS
 
+/* Define if you have libaio */
+#undef HAVE_LIBAIO
+
 /* Define if you have libblkid */
 #undef HAVE_LIBBLKID
 
-- 
2.7.4





More information about the kernel-team mailing list