]> git.proxmox.com Git - zfsonlinux.git/commitdiff
FPU/SIMD: separate ZFS and Kernel approach for less interference
authorThomas Lamprecht <t.lamprecht@proxmox.com>
Fri, 18 Oct 2019 18:03:00 +0000 (20:03 +0200)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Wed, 23 Oct 2019 15:09:58 +0000 (17:09 +0200)
github pull-request #9406[0].

[0]: https://github.com/zfsonlinux/zfs/pull/9406#event-2704412478

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
debian/patches/0006-Linux-5.0-compat-SIMD-compatibility.patch
debian/patches/0007-Fix-CONFIG_X86_DEBUG_FPU-build-failure.patch [deleted file]
debian/patches/0007-Perform-KABI-checks-in-parallel.patch [new file with mode: 0644]
debian/patches/0008-Linux-4.14-4.19-5.0-compat-SIMD-save-restore.patch [new file with mode: 0644]
debian/patches/0008-SIMD-FPU-register-save-restore-is-also-required-on-5.patch [deleted file]
debian/patches/0009-Fix-CONFIG_X86_DEBUG_FPU-build-failure.patch [new file with mode: 0644]
debian/patches/0009-Perform-KABI-checks-in-parallel.patch [deleted file]
debian/patches/0010-OpenZFS-restructuring-move-platform-specific-headers.patch [new file with mode: 0644]
debian/patches/0011-Allow-FPU-usage-in-user-and-kernel-thread-contexts.patch [new file with mode: 0644]
debian/patches/series

index d85991de0d9b64a5fd0efe97852a20bbfb43bc98..2a1f03cfaf8fb886ea601424ea4f44ce9dd23b5f 100644 (file)
@@ -2,9 +2,6 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Brian Behlendorf <behlendorf1@llnl.gov>
 Date: Fri, 12 Jul 2019 09:31:20 -0700
 Subject: [PATCH] Linux 5.0 compat: SIMD compatibility
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
 
 Restore the SIMD optimization for 4.19.38 LTS, 4.14.120 LTS,
 and 5.0 and newer kernels.  This is accomplished by leveraging
@@ -59,8 +56,6 @@ Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
 Closes #8754
 Closes #8793
 Closes #8965
-(cherry picked from commit e5db31349484e5e859c7a942eb15b98d68ce5b4d)
-Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
 Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
 ---
  cmd/ztest/ztest.c                           |   3 +
diff --git a/debian/patches/0007-Fix-CONFIG_X86_DEBUG_FPU-build-failure.patch b/debian/patches/0007-Fix-CONFIG_X86_DEBUG_FPU-build-failure.patch
deleted file mode 100644 (file)
index c4b2d2b..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Brian Behlendorf <behlendorf1@llnl.gov>
-Date: Wed, 17 Jul 2019 09:14:36 -0700
-Subject: [PATCH] Fix CONFIG_X86_DEBUG_FPU build failure
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-When CONFIG_X86_DEBUG_FPU is defined the alternatives_patched symbol
-is pulled in as a dependency which results in a build failure.  To
-prevent this undefine CONFIG_X86_DEBUG_FPU to disable the WARN_ON_FPU()
-macro and rely on WARN_ON_ONCE debugging checks which were previously
-added.
-
-Reviewed-by: Tony Hutter <hutter2@llnl.gov>
-Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
-Closes #9041
-Closes #9049
-(cherry picked from commit 095b5412b31c07cad5cec74a4eb5ace011c92b27)
-Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
-Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
----
- include/linux/simd_x86.h | 9 +++++++++
- 1 file changed, 9 insertions(+)
-
-diff --git a/include/linux/simd_x86.h b/include/linux/simd_x86.h
-index 641f43955..edd456098 100644
---- a/include/linux/simd_x86.h
-+++ b/include/linux/simd_x86.h
-@@ -84,6 +84,15 @@
- #if defined(_KERNEL)
-+/*
-+ * Disable the WARN_ON_FPU() macro to prevent additional dependencies
-+ * when providing the kfpu_* functions.  Relevant warnings are included
-+ * as appropriate and are unconditionally enabled.
-+ */
-+#if defined(CONFIG_X86_DEBUG_FPU) && !defined(KERNEL_EXPORTS_X86_FPU)
-+#undef CONFIG_X86_DEBUG_FPU
-+#endif
-+
- #if defined(HAVE_KERNEL_FPU_API_HEADER)
- #include <asm/fpu/api.h>
- #include <asm/fpu/internal.h>
diff --git a/debian/patches/0007-Perform-KABI-checks-in-parallel.patch b/debian/patches/0007-Perform-KABI-checks-in-parallel.patch
new file mode 100644 (file)
index 0000000..74025a7
--- /dev/null
@@ -0,0 +1,8805 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Brian Behlendorf <behlendorf1@llnl.gov>
+Date: Tue, 1 Oct 2019 12:50:34 -0700
+Subject: [PATCH] Perform KABI checks in parallel
+
+Reduce the time required for ./configure to perform the needed
+KABI checks by allowing kbuild to compile multiple test cases in
+parallel.  This was accomplished by splitting each test's source
+code from the logic handling whether that code could be compiled
+or not.
+
+By introducing this split it's possible to minimize the number of
+times kbuild needs to be invoked.  As importantly, it means all of
+the tests can be built in parallel.  This does require a little extra
+care since we expect some tests to fail, so the --keep-going (-k)
+option must be provided otherwise some tests may not get compiled.
+Furthermore, since a failure during the kbuild modpost phase will
+result in an early exit; the final linking phase is limited to tests
+which passed the initial compilation and produced an object file.
+
+Once everything has been built the configure script proceeds as
+previously.  The only significant difference is that it now merely
+needs to test for the existence of a .ko file to determine the
+result of a given test.  This vastly speeds up the entire process.
+
+New test cases should use ZFS_LINUX_TEST_SRC to declare their test
+source code and ZFS_LINUX_TEST_RESULT to check the result.  All of
+the existing kernel-*.m4 files have been updated accordingly, see
+config/kernel-current-time.m4 for a basic example.  The legacy
+ZFS_LINUX_TRY_COMPILE macro has been kept to handle special cases
+but it's use is not encouraged.
+
+                  master (secs)   patched (secs)
+                  -------------   ----------------
+autogen.sh        61              68
+configure         137             24  (~17% of current run time)
+make -j $(nproc)  44              44
+make rpms         287             150
+
+Reviewed-by: Tony Hutter <hutter2@llnl.gov>
+Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
+Closes #8547
+Closes #9132
+Closes #9341
+(cherry picked from commit 608f8749a1055e6769899788e11bd51fd396f9e5)
+Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
+---
+ .gitignore                                    |   1 +
+ Makefile.am                                   |   6 +-
+ config/iconv.m4                               |   3 +-
+ config/kernel-access-ok-type.m4               |  18 +-
+ config/kernel-acl.m4                          | 253 ++++--
+ config/kernel-aio-fsync.m4                    |  14 +-
+ config/kernel-automount.m4                    |  13 +-
+ config/kernel-bdev-logical-size.m4            |  17 +-
+ config/kernel-bdev-physical-size.m4           |  17 +-
+ config/kernel-bdi.m4                          |  78 +-
+ config/kernel-bio-bvec-iter.m4                |  13 +-
+ config/kernel-bio-end-io-t-args.m4            |  34 +-
+ config/kernel-bio-failfast.m4                 |  39 +-
+ config/kernel-bio-op.m4                       |  74 +-
+ config/kernel-bio-rw-barrier.m4               |  15 +-
+ config/kernel-bio-rw-discard.m4               |  15 +-
+ config/kernel-bio_set_dev.m4                  |  51 +-
+ config/kernel-blk-queue-bdi.m4                |  12 +-
+ config/kernel-blk-queue-discard.m4            |  41 +-
+ config/kernel-blk-queue-flags.m4              |  40 +-
+ config/kernel-blk-queue-flush.m4              |  64 +-
+ config/kernel-blk-queue-max-hw-sectors.m4     |  19 +-
+ config/kernel-blk-queue-max-segments.m4       |  21 +-
+ config/kernel-blk-queue-unplug.m4             |  48 +-
+ config/kernel-blkdev-get-by-path.m4           |  15 +-
+ config/kernel-blkdev-reread-part.m4           |  12 +-
+ config/kernel-block-device-operations.m4      |  46 +-
+ config/kernel-clear-inode.m4                  |  13 +-
+ config/kernel-commit-metadata.m4              |  15 +-
+ config/kernel-config-defined.m4               | 183 ++++
+ config/kernel-create-nameidata.m4             |  15 +-
+ config/kernel-ctl-table-name.m4               |  12 +-
+ config/kernel-current-time.m4                 |  13 +-
+ config/kernel-current_bio_tail.m4             |  30 +-
+ config/kernel-d-make-root.m4                  |  17 -
+ config/kernel-d-obtain-alias.m4               |  18 -
+ config/kernel-d-prune-aliases.m4              |  19 -
+ config/kernel-declare-event-class.m4          |   8 +-
+ config/kernel-dentry-operations.m4            | 174 +++-
+ config/kernel-dirty-inode.m4                  |  15 +-
+ config/kernel-discard-granularity.m4          |  15 +-
+ config/kernel-elevator-change.m4              |  21 +-
+ config/kernel-encode-fh-inode.m4              |  15 +-
+ config/kernel-evict-inode.m4                  |  13 +-
+ config/kernel-fallocate-pax.m4                |  19 -
+ config/kernel-fallocate.m4                    |  50 +-
+ config/kernel-file-dentry.m4                  |  12 +-
+ config/kernel-file-inode.m4                   |  12 +-
+ config/kernel-fmode-t.m4                      |  15 +-
+ config/kernel-follow-down-one.m4              |  12 +-
+ config/kernel-fpu.m4                          |  99 ++-
+ config/kernel-fst-mount.m4                    |  13 +-
+ config/kernel-fsync.m4                        |  83 +-
+ config/kernel-generic_io_acct.m4              |  63 +-
+ config/kernel-generic_readlink.m4             |  15 +-
+ config/kernel-get-disk-and-module.m4          |  13 +-
+ config/kernel-get-disk-ro.m4                  |  18 +-
+ config/kernel-get-link.m4                     | 126 +--
+ config/kernel-global_page_state.m4            |  72 +-
+ config/kernel-group-info.m4                   |  15 +-
+ config/kernel-in-compat-syscall.m4            |  12 +-
+ config/kernel-inode-getattr.m4                |  56 +-
+ config/kernel-inode-lock.m4                   |  15 +-
+ config/kernel-inode-set-flags.m4              |  12 +-
+ config/kernel-inode-set-iversion.m4           |  12 +-
+ config/kernel-inode-times.m4                  |  15 +-
+ config/kernel-insert-inode-locked.m4          |  15 +-
+ config/kernel-invalidate-bdev-args.m4         |  14 +-
+ config/kernel-is_owner_or_cap.m4              |  31 +-
+ config/kernel-kmap-atomic-args.m4             |  14 +-
+ config/kernel-kmem-cache.m4                   |  62 +-
+ config/kernel-kstrtoul.m4                     |  14 +-
+ config/kernel-ktime_get_coarse_real_ts64.m4   |  15 +-
+ config/kernel-kuid-helpers.m4                 |  12 +-
+ config/kernel-kuidgid.m4                      |  26 +-
+ config/kernel-lookup-bdev.m4                  |  32 +-
+ config/kernel-lookup-nameidata.m4             |  15 +-
+ config/kernel-lseek-execute.m4                |  16 +-
+ config/kernel-make-request-fn.m4              |  77 ++
+ config/kernel-misc-minor.m4                   |   2 +-
+ config/kernel-mk-request-fn.m4                |  65 --
+ config/kernel-mkdir-umode-t.m4                |  13 +-
+ config/kernel-mod-param.m4                    |  13 +-
+ config/kernel-objtool.m4                      |  47 +-
+ config/kernel-open-bdev-exclusive.m4          |  15 +-
+ config/kernel-pde-data.m4                     |  14 +-
+ config/kernel-put-link.m4                     |  57 +-
+ config/kernel-rename.m4                       |  16 +-
+ config/kernel-rw.m4                           |  40 +-
+ config/kernel-rwsem.m4                        |  65 +-
+ config/kernel-sched.m4                        |  53 +-
+ config/kernel-security-inode-init.m4          |  38 +-
+ config/kernel-set-nlink.m4                    |  15 +-
+ config/kernel-setattr-prepare.m4              |  16 +-
+ config/kernel-sget-args.m4                    |  13 +-
+ config/kernel-show-options.m4                 |  21 +-
+ config/kernel-shrink.m4                       | 219 +++--
+ config/kernel-submit_bio.m4                   |  12 +-
+ config/kernel-super-userns.m4                 |  14 +-
+ config/kernel-timer.m4                        |  52 +-
+ config/kernel-tmpfile.m4                      |  16 +-
+ config/kernel-totalhigh_pages.m4              |  14 +-
+ config/kernel-totalram-pages-func.m4          |  15 +-
+ config/kernel-truncate-range.m4               |  13 +-
+ config/kernel-truncate-setsize.m4             |  15 +-
+ config/kernel-userns-capabilities.m4          |  48 +-
+ ...urange-sleep.m4 => kernel-usleep_range.m4} |  19 +-
+ config/kernel-vfs-direct_IO.m4                | 145 ++--
+ config/kernel-vfs-fsync.m4                    |  12 +-
+ config/kernel-vfs-getattr.m4                  |  54 +-
+ config/kernel-vfs-iterate.m4                  |  84 +-
+ config/kernel-vfs-rw-iterate.m4               |  76 +-
+ config/kernel-wait.m4                         |  73 +-
+ config/kernel-xattr-handler.m4                | 442 +++++-----
+ config/kernel-zlib.m4                         |  57 +-
+ config/kernel.m4                              | 783 +++++++++++-------
+ config/zfs-build.m4                           |  11 +
+ config/zfs-meta.m4                            |  18 +
+ 118 files changed, 3245 insertions(+), 2127 deletions(-)
+ create mode 100644 config/kernel-config-defined.m4
+ delete mode 100644 config/kernel-d-make-root.m4
+ delete mode 100644 config/kernel-d-obtain-alias.m4
+ delete mode 100644 config/kernel-d-prune-aliases.m4
+ delete mode 100644 config/kernel-fallocate-pax.m4
+ create mode 100644 config/kernel-make-request-fn.m4
+ delete mode 100644 config/kernel-mk-request-fn.m4
+ rename config/{kernel-urange-sleep.m4 => kernel-usleep_range.m4} (60%)
+
+diff --git a/.gitignore b/.gitignore
+index ae9e22dfa..19377a7b1 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -36,6 +36,7 @@ Makefile.in
+ # Top level generated files specific to this top level dir
+ #
+ /bin
++/build
+ /configure
+ /config.log
+ /config.status
+diff --git a/Makefile.am b/Makefile.am
+index 9afe22954..5ee7c20be 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -40,7 +40,7 @@ gitrev:
+ BUILT_SOURCES = gitrev
+ distclean-local::
+-      -$(RM) -R autom4te*.cache
++      -$(RM) -R autom4te*.cache build
+       -find . \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS \
+               -o -name .pc -o -name .hg -o -name .git \) -prune -o \
+               \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
+@@ -87,8 +87,8 @@ commitcheck:
+       fi
+ cstyle:
+-      @find ${top_srcdir} -name '*.[hc]' ! -name 'zfs_config.*' \
+-              ! -name '*.mod.c' -type f \
++      @find ${top_srcdir} -name build -prune -o -name '*.[hc]' \
++              ! -name 'zfs_config.*' ! -name '*.mod.c' -type f \
+               -exec ${top_srcdir}/scripts/cstyle.pl -cpP {} \+
+ shellcheck:
+diff --git a/config/iconv.m4 b/config/iconv.m4
+index a285e9daa..fc915fde6 100644
+--- a/config/iconv.m4
++++ b/config/iconv.m4
+@@ -269,8 +269,7 @@ size_t iconv();
+         [am_cv_proto_iconv_arg1="const"])
+       am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
+     am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+-    AC_MSG_RESULT([
+-         $am_cv_proto_iconv])
++    AC_MSG_RESULT([$am_cv_proto_iconv])
+   else
+     dnl When compiling GNU libiconv on a system that does not have iconv yet,
+     dnl pick the POSIX compliant declaration without 'const'.
+diff --git a/config/kernel-access-ok-type.m4 b/config/kernel-access-ok-type.m4
+index 3b2878a55..dc9433458 100644
+--- a/config/kernel-access-ok-type.m4
++++ b/config/kernel-access-ok-type.m4
+@@ -4,17 +4,23 @@ dnl #
+ dnl # - access_ok(type, addr, size)
+ dnl # + access_ok(addr, size)
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_ACCESS_OK_TYPE], [
+-      AC_MSG_CHECKING([whether access_ok() has 'type' parameter])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_ACCESS_OK_TYPE], [
++      ZFS_LINUX_TEST_SRC([access_ok_type], [
+               #include <linux/uaccess.h>
+       ],[
+-              const void __user __attribute__((unused)) *addr = (void *) 0xdeadbeef;
++              const void __user __attribute__((unused)) *addr =
++                  (void *) 0xdeadbeef;
+               unsigned long __attribute__((unused)) size = 1;
+               int error __attribute__((unused)) = access_ok(0, addr, size);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_ACCESS_OK_TYPE], [
++      AC_MSG_CHECKING([whether access_ok() has 'type' parameter])
++      ZFS_LINUX_TEST_RESULT([access_ok_type], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_ACCESS_OK_TYPE, 1, [kernel has access_ok with 'type' parameter])
++              AC_DEFINE(HAVE_ACCESS_OK_TYPE, 1,
++                  [kernel has access_ok with 'type' parameter])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-acl.m4 b/config/kernel-acl.m4
+index 02cc020e5..68a72872d 100644
+--- a/config/kernel-acl.m4
++++ b/config/kernel-acl.m4
+@@ -3,32 +3,26 @@ dnl # Check if posix_acl_release can be used from a ZFS_META_LICENSED
+ dnl # module.  The is_owner_or_cap macro was replaced by
+ dnl # inode_owner_or_capable
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_RELEASE], [
+-      AC_MSG_CHECKING([whether posix_acl_release() is available])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_POSIX_ACL_RELEASE], [
++      ZFS_LINUX_TEST_SRC([posix_acl_release], [
+               #include <linux/cred.h>
+               #include <linux/fs.h>
+               #include <linux/posix_acl.h>
+-      ],[
+-              struct posix_acl* tmp = posix_acl_alloc(1, 0);
++      ], [
++              struct posix_acl *tmp = posix_acl_alloc(1, 0);
+               posix_acl_release(tmp);
+-      ],[
++      ], [], [$ZFS_META_LICENSE])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_RELEASE], [
++      AC_MSG_CHECKING([whether posix_acl_release() is available])
++      ZFS_LINUX_TEST_RESULT([posix_acl_release], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_POSIX_ACL_RELEASE, 1,
+                   [posix_acl_release() is available])
+               AC_MSG_CHECKING([whether posix_acl_release() is GPL-only])
+-              ZFS_LINUX_TRY_COMPILE([
+-                      #include <linux/module.h>
+-                      #include <linux/cred.h>
+-                      #include <linux/fs.h>
+-                      #include <linux/posix_acl.h>
+-
+-                      MODULE_LICENSE("$ZFS_META_LICENSE");
+-              ],[
+-                      struct posix_acl* tmp = posix_acl_alloc(1, 0);
+-                      posix_acl_release(tmp);
+-              ],[
++              ZFS_LINUX_TEST_RESULT([posix_acl_release_license], [
+                       AC_MSG_RESULT(no)
+               ],[
+                       AC_MSG_RESULT(yes)
+@@ -46,24 +40,25 @@ dnl # set_cached_acl() and forget_cached_acl() changed from inline to
+ dnl # EXPORT_SYMBOL. In the former case, they may not be usable because of
+ dnl # posix_acl_release. In the latter case, we can always use them.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_SET_CACHED_ACL_USABLE], [
+-      AC_MSG_CHECKING([whether set_cached_acl() is usable])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/module.h>
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SET_CACHED_ACL_USABLE], [
++      ZFS_LINUX_TEST_SRC([set_cached_acl], [
+               #include <linux/cred.h>
+               #include <linux/fs.h>
+               #include <linux/posix_acl.h>
+-
+-              MODULE_LICENSE("$ZFS_META_LICENSE");
+-      ],[
++      ], [
+               struct inode *ip = NULL;
+               struct posix_acl *acl = posix_acl_alloc(1, 0);
+               set_cached_acl(ip, ACL_TYPE_ACCESS, acl);
+               forget_cached_acl(ip, ACL_TYPE_ACCESS);
+-      ],[
++      ], [], [$ZFS_META_LICENSE])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SET_CACHED_ACL_USABLE], [
++      AC_MSG_CHECKING([whether set_cached_acl() is usable])
++      ZFS_LINUX_TEST_RESULT([set_cached_acl_license], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_SET_CACHED_ACL_USABLE, 1,
+-                  [posix_acl_release() is usable])
++                  [set_cached_acl() is usable])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+@@ -77,14 +72,25 @@ dnl #
+ dnl # 3.14 API change,
+ dnl # posix_acl_chmod() is changed to __posix_acl_chmod()
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_CHMOD], [
+-      AC_MSG_CHECKING([whether posix_acl_chmod exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_POSIX_ACL_CHMOD], [
++      ZFS_LINUX_TEST_SRC([posix_acl_chmod], [
+               #include <linux/fs.h>
+               #include <linux/posix_acl.h>
+       ],[
+               posix_acl_chmod(NULL, 0, 0)
++      ])
++
++      ZFS_LINUX_TEST_SRC([__posix_acl_chmod], [
++              #include <linux/fs.h>
++              #include <linux/posix_acl.h>
+       ],[
++              __posix_acl_chmod(NULL, 0, 0)
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_CHMOD], [
++      AC_MSG_CHECKING([whether posix_acl_chmod exists])
++      ZFS_LINUX_TEST_RESULT([posix_acl_chmod], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_POSIX_ACL_CHMOD, 1, [posix_acl_chmod() exists])
+       ],[
+@@ -92,14 +98,10 @@ AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_CHMOD], [
+       ])
+       AC_MSG_CHECKING([whether __posix_acl_chmod exists])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/fs.h>
+-              #include <linux/posix_acl.h>
+-      ],[
+-              __posix_acl_chmod(NULL, 0, 0)
+-      ],[
++      ZFS_LINUX_TEST_RESULT([__posix_acl_chmod], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE___POSIX_ACL_CHMOD, 1, [__posix_acl_chmod() exists])
++              AC_DEFINE(HAVE___POSIX_ACL_CHMOD, 1,
++                  [__posix_acl_chmod() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+@@ -109,18 +111,22 @@ dnl #
+ dnl # 3.1 API change,
+ dnl # posix_acl_equiv_mode now wants an umode_t* instead of a mode_t*
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T], [
+-      AC_MSG_CHECKING([whether posix_acl_equiv_mode() wants umode_t])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T], [
++      ZFS_LINUX_TEST_SRC([posix_acl_equiv_mode], [
+               #include <linux/fs.h>
+               #include <linux/posix_acl.h>
+       ],[
+               umode_t tmp;
+               posix_acl_equiv_mode(NULL,&tmp);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T], [
++      AC_MSG_CHECKING([whether posix_acl_equiv_mode() wants umode_t])
++      ZFS_LINUX_TEST_RESULT([posix_acl_equiv_mode], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_POSIX_ACL_EQUIV_MODE_UMODE_T, 1,
+-                  [ posix_acl_equiv_mode wants umode_t*])
++                  [posix_acl_equiv_mode wants umode_t*])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+@@ -130,9 +136,8 @@ dnl #
+ dnl # 4.8 API change,
+ dnl # The function posix_acl_valid now must be passed a namespace.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_VALID_WITH_NS], [
+-      AC_MSG_CHECKING([whether posix_acl_valid() wants user namespace])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_POSIX_ACL_VALID_WITH_NS], [
++      ZFS_LINUX_TEST_SRC([posix_acl_valid_with_ns], [
+               #include <linux/fs.h>
+               #include <linux/posix_acl.h>
+       ],[
+@@ -141,7 +146,12 @@ AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_VALID_WITH_NS], [
+               int error;
+               error = posix_acl_valid(user_ns, acl);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_VALID_WITH_NS], [
++      AC_MSG_CHECKING([whether posix_acl_valid() wants user namespace])
++      ZFS_LINUX_TEST_RESULT([posix_acl_valid_with_ns], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_POSIX_ACL_VALID_WITH_NS, 1,
+                   [posix_acl_valid() wants user namespace])
+@@ -155,9 +165,8 @@ dnl # 2.6.27 API change,
+ dnl # Check if inode_operations contains the function permission
+ dnl # and expects the nameidata structure to have been removed.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION], [
+-      AC_MSG_CHECKING([whether iops->permission() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_PERMISSION], [
++      ZFS_LINUX_TEST_SRC([inode_operations_permission], [
+               #include <linux/fs.h>
+               int permission_fn(struct inode *inode, int mask) { return 0; }
+@@ -166,8 +175,12 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION], [
+                   iops __attribute__ ((unused)) = {
+                       .permission = permission_fn,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION], [
++      AC_MSG_CHECKING([whether iops->permission() exists])
++      ZFS_LINUX_TEST_RESULT([inode_operations_permission], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_PERMISSION, 1, [iops->permission() exists])
+       ],[
+@@ -180,9 +193,8 @@ dnl # 2.6.26 API change,
+ dnl # Check if inode_operations contains the function permission
+ dnl # and expects the nameidata structure to be passed.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA], [
+-      AC_MSG_CHECKING([whether iops->permission() wants nameidata])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA], [
++      ZFS_LINUX_TEST_SRC([inode_operations_permission_with_nameidata], [
+               #include <linux/fs.h>
+               #include <linux/sched.h>
+@@ -193,8 +205,12 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA], [
+                   iops __attribute__ ((unused)) = {
+                       .permission = permission_fn,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA], [
++      AC_MSG_CHECKING([whether iops->permission() wants nameidata])
++      ZFS_LINUX_TEST_RESULT([inode_operations_permission_with_nameidata], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_PERMISSION, 1, [iops->permission() exists])
+               AC_DEFINE(HAVE_PERMISSION_WITH_NAMEIDATA, 1,
+@@ -208,9 +224,8 @@ dnl #
+ dnl # 2.6.32 API change,
+ dnl # Check if inode_operations contains the function check_acl
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL], [
+-      AC_MSG_CHECKING([whether iops->check_acl() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_CHECK_ACL], [
++      ZFS_LINUX_TEST_SRC([inode_operations_check_acl], [
+               #include <linux/fs.h>
+               int check_acl_fn(struct inode *inode, int mask) { return 0; }
+@@ -219,8 +234,12 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL], [
+                   iops __attribute__ ((unused)) = {
+                       .check_acl = check_acl_fn,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL], [
++      AC_MSG_CHECKING([whether iops->check_acl() exists])
++      ZFS_LINUX_TEST_RESULT([inode_operations_check_acl], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_CHECK_ACL, 1, [iops->check_acl() exists])
+       ],[
+@@ -232,9 +251,8 @@ dnl #
+ dnl # 2.6.38 API change,
+ dnl # The function check_acl gained a new parameter: flags
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS], [
+-      AC_MSG_CHECKING([whether iops->check_acl() wants flags])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS], [
++      ZFS_LINUX_TEST_SRC([inode_operations_check_acl_with_flags], [
+               #include <linux/fs.h>
+               int check_acl_fn(struct inode *inode, int mask,
+@@ -244,8 +262,12 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS], [
+                   iops __attribute__ ((unused)) = {
+                       .check_acl = check_acl_fn,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS], [
++      AC_MSG_CHECKING([whether iops->check_acl() wants flags])
++      ZFS_LINUX_TEST_RESULT([inode_operations_check_acl_with_flags], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_CHECK_ACL, 1, [iops->check_acl() exists])
+               AC_DEFINE(HAVE_CHECK_ACL_WITH_FLAGS, 1,
+@@ -259,9 +281,8 @@ dnl #
+ dnl # 3.1 API change,
+ dnl # Check if inode_operations contains the function get_acl
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [
+-      AC_MSG_CHECKING([whether iops->get_acl() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL], [
++      ZFS_LINUX_TEST_SRC([inode_operations_get_acl], [
+               #include <linux/fs.h>
+               struct posix_acl *get_acl_fn(struct inode *inode, int type)
+@@ -271,8 +292,12 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [
+                   iops __attribute__ ((unused)) = {
+                       .get_acl = get_acl_fn,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [
++      AC_MSG_CHECKING([whether iops->get_acl() exists])
++      ZFS_LINUX_TEST_RESULT([inode_operations_get_acl], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_GET_ACL, 1, [iops->get_acl() exists])
+       ],[
+@@ -284,20 +309,23 @@ dnl #
+ dnl # 3.14 API change,
+ dnl # Check if inode_operations contains the function set_acl
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL], [
+-      AC_MSG_CHECKING([whether iops->set_acl() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_SET_ACL], [
++      ZFS_LINUX_TEST_SRC([inode_operations_set_acl], [
+               #include <linux/fs.h>
+-              int set_acl_fn(struct inode *inode, struct posix_acl *acl, int type)
+-                  { return 0; }
++              int set_acl_fn(struct inode *inode, struct posix_acl *acl,
++                  int type) { return 0; }
+               static const struct inode_operations
+                   iops __attribute__ ((unused)) = {
+                       .set_acl = set_acl_fn,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL], [
++      AC_MSG_CHECKING([whether iops->set_acl() exists])
++      ZFS_LINUX_TEST_RESULT([inode_operations_set_acl], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists])
+       ],[
+@@ -311,16 +339,79 @@ dnl # The kernel get_acl will now check cache before calling i_op->get_acl and
+ dnl # do set_cached_acl after that, so i_op->get_acl don't need to do that
+ dnl # anymore.
+ dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_GET_ACL_HANDLE_CACHE], [
++      ZFS_LINUX_TEST_SRC([get_acl_handle_cache], [
++              #include <linux/fs.h>
++      ],[
++              void *sentinel __attribute__ ((unused)) =
++                  uncached_acl_sentinel(NULL);
++      ])
++])
++
+ AC_DEFUN([ZFS_AC_KERNEL_GET_ACL_HANDLE_CACHE], [
+       AC_MSG_CHECKING([whether uncached_acl_sentinel() exists])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/fs.h>
++      ZFS_LINUX_TEST_RESULT([get_acl_handle_cache], [
++              AC_MSG_RESULT(yes)
++              AC_DEFINE(HAVE_KERNEL_GET_ACL_HANDLE_CACHE, 1,
++                  [uncached_acl_sentinel() exists])
+       ],[
+-              void *sentinel __attribute__ ((unused)) = uncached_acl_sentinel(NULL);
++              AC_MSG_RESULT(no)
++      ])
++])
++
++dnl #
++dnl # 4.16 kernel: check if struct posix_acl acl.a_refcount is a refcount_t.
++dnl # It's an atomic_t on older kernels.
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_ACL_HAS_REFCOUNT], [
++      ZFS_LINUX_TEST_SRC([acl_refcount], [
++              #include <linux/backing-dev.h>
++              #include <linux/refcount.h>
++              #include <linux/posix_acl.h>
+       ],[
++              struct posix_acl acl;
++              refcount_t *r __attribute__ ((unused)) = &acl.a_refcount;
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_ACL_HAS_REFCOUNT], [
++      AC_MSG_CHECKING([whether posix_acl has refcount_t])
++      ZFS_LINUX_TEST_RESULT([acl_refcount], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_KERNEL_GET_ACL_HANDLE_CACHE, 1, [uncached_acl_sentinel() exists])
++              AC_DEFINE(HAVE_ACL_REFCOUNT, 1, [posix_acl has refcount_t])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+ ])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_ACL], [
++      ZFS_AC_KERNEL_SRC_POSIX_ACL_RELEASE
++      ZFS_AC_KERNEL_SRC_SET_CACHED_ACL_USABLE
++      ZFS_AC_KERNEL_SRC_POSIX_ACL_CHMOD
++      ZFS_AC_KERNEL_SRC_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T
++      ZFS_AC_KERNEL_SRC_POSIX_ACL_VALID_WITH_NS
++      ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_PERMISSION
++      ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA
++      ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_CHECK_ACL
++      ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS
++      ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL
++      ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_SET_ACL
++      ZFS_AC_KERNEL_SRC_GET_ACL_HANDLE_CACHE
++      ZFS_AC_KERNEL_SRC_ACL_HAS_REFCOUNT
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_ACL], [
++      ZFS_AC_KERNEL_POSIX_ACL_RELEASE
++      ZFS_AC_KERNEL_SET_CACHED_ACL_USABLE
++      ZFS_AC_KERNEL_POSIX_ACL_CHMOD
++      ZFS_AC_KERNEL_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T
++      ZFS_AC_KERNEL_POSIX_ACL_VALID_WITH_NS
++      ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION
++      ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA
++      ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL
++      ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS
++      ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL
++      ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL
++      ZFS_AC_KERNEL_GET_ACL_HANDLE_CACHE
++      ZFS_AC_KERNEL_ACL_HAS_REFCOUNT
++])
+diff --git a/config/kernel-aio-fsync.m4 b/config/kernel-aio-fsync.m4
+index 41b7a98a6..b4dbf29ba 100644
+--- a/config/kernel-aio-fsync.m4
++++ b/config/kernel-aio-fsync.m4
+@@ -1,21 +1,23 @@
+ dnl #
+ dnl # Linux 4.9-rc5+ ABI, removal of the .aio_fsync field
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_AIO_FSYNC], [
+-      AC_MSG_CHECKING([whether fops->aio_fsync() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_AIO_FSYNC], [
++      ZFS_LINUX_TEST_SRC([aio_fsync], [
+               #include <linux/fs.h>
+               static const struct file_operations
+                   fops __attribute__ ((unused)) = {
+                       .aio_fsync = NULL,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_AIO_FSYNC], [
++      AC_MSG_CHECKING([whether fops->aio_fsync() exists])
++      ZFS_LINUX_TEST_RESULT([aio_fsync], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_FILE_AIO_FSYNC, 1, [fops->aio_fsync() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+ ])
+-
+diff --git a/config/kernel-automount.m4 b/config/kernel-automount.m4
+index 1ee4c168d..93e14fa8d 100644
+--- a/config/kernel-automount.m4
++++ b/config/kernel-automount.m4
+@@ -5,16 +5,19 @@ dnl # solution to handling automounts.  Prior to this cifs/nfs clients
+ dnl # which required automount support would abuse the follow_link()
+ dnl # operation on directories for this purpose.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_AUTOMOUNT], [
+-      AC_MSG_CHECKING([whether dops->d_automount() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_AUTOMOUNT], [
++      ZFS_LINUX_TEST_SRC([dentry_operations_d_automount], [
+               #include <linux/dcache.h>
+               struct vfsmount *d_automount(struct path *p) { return NULL; }
+               struct dentry_operations dops __attribute__ ((unused)) = {
+                       .d_automount = d_automount,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_AUTOMOUNT], [
++      AC_MSG_CHECKING([whether dops->d_automount() exists])
++      ZFS_LINUX_TEST_RESULT([dentry_operations_d_automount], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_AUTOMOUNT, 1, [dops->automount() exists])
+       ],[
+diff --git a/config/kernel-bdev-logical-size.m4 b/config/kernel-bdev-logical-size.m4
+index a6194577a..0de9afd88 100644
+--- a/config/kernel-bdev-logical-size.m4
++++ b/config/kernel-bdev-logical-size.m4
+@@ -5,21 +5,22 @@ dnl # it has been true for a while that there was no strict 1:1 mapping
+ dnl # between physical sector size and logical block size this change makes
+ dnl # it explicit.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BDEV_LOGICAL_BLOCK_SIZE], [
+-      AC_MSG_CHECKING([whether bdev_logical_block_size() is available])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BDEV_LOGICAL_BLOCK_SIZE], [
++      ZFS_LINUX_TEST_SRC([bdev_logical_block_size], [
+               #include <linux/blkdev.h>
+       ],[
+               struct block_device *bdev = NULL;
+               bdev_logical_block_size(bdev);
+-      ],[
++      ], [$NO_UNUSED_BUT_SET_VARIABLE])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BDEV_LOGICAL_BLOCK_SIZE], [
++      AC_MSG_CHECKING([whether bdev_logical_block_size() is available])
++      ZFS_LINUX_TEST_RESULT([bdev_logical_block_size], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BDEV_LOGICAL_BLOCK_SIZE, 1,
+-                        [bdev_logical_block_size() is available])
++                  [bdev_logical_block_size() is available])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
+ ])
+diff --git a/config/kernel-bdev-physical-size.m4 b/config/kernel-bdev-physical-size.m4
+index 77746ee91..94d8172d3 100644
+--- a/config/kernel-bdev-physical-size.m4
++++ b/config/kernel-bdev-physical-size.m4
+@@ -19,21 +19,22 @@ dnl #
+ dnl # Unfortunately, this interface isn't entirely reliable because
+ dnl # drives are sometimes known to misreport this value.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BDEV_PHYSICAL_BLOCK_SIZE], [
+-      AC_MSG_CHECKING([whether bdev_physical_block_size() is available])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BDEV_PHYSICAL_BLOCK_SIZE], [
++      ZFS_LINUX_TEST_SRC([bdev_physical_block_size], [
+               #include <linux/blkdev.h>
+       ],[
+               struct block_device *bdev = NULL;
+               bdev_physical_block_size(bdev);
+-      ],[
++      ], [$NO_UNUSED_BUT_SET_VARIABLE])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BDEV_PHYSICAL_BLOCK_SIZE], [
++      AC_MSG_CHECKING([whether bdev_physical_block_size() is available])
++      ZFS_LINUX_TEST_RESULT([bdev_physical_block_size], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BDEV_PHYSICAL_BLOCK_SIZE, 1,
+-                        [bdev_physical_block_size() is available])
++                  [bdev_physical_block_size() is available])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
+ ])
+diff --git a/config/kernel-bdi.m4 b/config/kernel-bdi.m4
+index cb7479ee9..51516332a 100644
+--- a/config/kernel-bdi.m4
++++ b/config/kernel-bdi.m4
+@@ -1,55 +1,81 @@
+ dnl #
+-dnl # 2.6.32 - 2.6.33, bdi_setup_and_register() is not exported.
+-dnl # 2.6.34 - 3.19, bdi_setup_and_register() takes 3 arguments.
+-dnl # 4.0 - 4.11, bdi_setup_and_register() takes 2 arguments.
+-dnl # 4.12 - x.y, super_setup_bdi_name() new interface.
++dnl # Check available BDI interfaces.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BDI], [
+-      AC_MSG_CHECKING([whether super_setup_bdi_name() exists])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BDI], [
++      ZFS_LINUX_TEST_SRC([super_setup_bdi_name], [
+               #include <linux/fs.h>
+               struct super_block sb;
+       ], [
+               char *name = "bdi";
+               atomic_long_t zfs_bdi_seq;
+               int error __attribute__((unused)) =
+-                  super_setup_bdi_name(&sb, "%.28s-%ld", name, atomic_long_inc_return(&zfs_bdi_seq));
+-      ], [super_setup_bdi_name], [fs/super.c], [
++                  super_setup_bdi_name(&sb, "%.28s-%ld", name,
++                  atomic_long_inc_return(&zfs_bdi_seq));
++      ])
++
++      ZFS_LINUX_TEST_SRC([bdi_setup_and_register], [
++              #include <linux/backing-dev.h>
++              struct backing_dev_info bdi;
++      ], [
++              char *name = "bdi";
++              int error __attribute__((unused)) =
++                  bdi_setup_and_register(&bdi, name);
++      ])
++
++      ZFS_LINUX_TEST_SRC([bdi_setup_and_register_3args], [
++              #include <linux/backing-dev.h>
++              struct backing_dev_info bdi;
++      ], [
++              char *name = "bdi";
++              unsigned int cap = BDI_CAP_MAP_COPY;
++              int error __attribute__((unused)) =
++                  bdi_setup_and_register(&bdi, name, cap);
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BDI], [
++      dnl #
++      dnl # 4.12, super_setup_bdi_name() introduced.
++      dnl #
++      AC_MSG_CHECKING([whether super_setup_bdi_name() exists])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([super_setup_bdi_name],
++          [super_setup_bdi_name], [fs/super.c], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_SUPER_SETUP_BDI_NAME, 1,
+                     [super_setup_bdi_name() exits])
+       ], [
+               AC_MSG_RESULT(no)
++
++              dnl #
++              dnl # 4.0 - 4.11, bdi_setup_and_register() takes 2 arguments.
++              dnl #
+               AC_MSG_CHECKING(
+                   [whether bdi_setup_and_register() wants 2 args])
+-              ZFS_LINUX_TRY_COMPILE_SYMBOL([
+-                      #include <linux/backing-dev.h>
+-                      struct backing_dev_info bdi;
+-              ], [
+-                      char *name = "bdi";
+-                      int error __attribute__((unused)) =
+-                          bdi_setup_and_register(&bdi, name);
+-              ], [bdi_setup_and_register], [mm/backing-dev.c], [
++              ZFS_LINUX_TEST_RESULT_SYMBOL([bdi_setup_and_register],
++                  [bdi_setup_and_register], [mm/backing-dev.c], [
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_2ARGS_BDI_SETUP_AND_REGISTER, 1,
+                           [bdi_setup_and_register() wants 2 args])
+               ], [
+                       AC_MSG_RESULT(no)
++
++                      dnl #
++                      dnl # 2.6.34 - 3.19, bdi_setup_and_register()
++                      dnl # takes 3 arguments.
++                      dnl #
+                       AC_MSG_CHECKING(
+                           [whether bdi_setup_and_register() wants 3 args])
+-                      ZFS_LINUX_TRY_COMPILE_SYMBOL([
+-                              #include <linux/backing-dev.h>
+-                              struct backing_dev_info bdi;
+-                      ], [
+-                              char *name = "bdi";
+-                              unsigned int cap = BDI_CAP_MAP_COPY;
+-                              int error __attribute__((unused)) =
+-                                  bdi_setup_and_register(&bdi, name, cap);
+-                      ], [bdi_setup_and_register], [mm/backing-dev.c], [
++                      ZFS_LINUX_TEST_RESULT_SYMBOL(
++                          [bdi_setup_and_register_3args],
++                          [bdi_setup_and_register], [mm/backing-dev.c], [
+                               AC_MSG_RESULT(yes)
+                               AC_DEFINE(HAVE_3ARGS_BDI_SETUP_AND_REGISTER, 1,
+                                   [bdi_setup_and_register() wants 3 args])
+                       ], [
++                              dnl #
++                              dnl # 2.6.32 - 2.6.33, bdi_setup_and_register()
++                              dnl # is not exported.
++                              dnl #
+                               AC_MSG_RESULT(no)
+                       ])
+               ])
+diff --git a/config/kernel-bio-bvec-iter.m4 b/config/kernel-bio-bvec-iter.m4
+index 64c989386..f9a99cee6 100644
+--- a/config/kernel-bio-bvec-iter.m4
++++ b/config/kernel-bio-bvec-iter.m4
+@@ -3,18 +3,21 @@ dnl # 3.14 API change,
+ dnl # Immutable biovecs. A number of fields of struct bio are moved to
+ dnl # struct bvec_iter.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BIO_BVEC_ITER], [
+-      AC_MSG_CHECKING([whether bio has bi_iter])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_BVEC_ITER], [
++      ZFS_LINUX_TEST_SRC([bio_bvec_iter], [
+               #include <linux/bio.h>
+       ],[
+               struct bio bio;
+               bio.bi_iter.bi_sector = 0;
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BIO_BVEC_ITER], [
++      AC_MSG_CHECKING([whether bio has bi_iter])
++      ZFS_LINUX_TEST_RESULT([bio_bvec_iter], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BIO_BVEC_ITER, 1, [bio has bi_iter])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+ ])
+-
+diff --git a/config/kernel-bio-end-io-t-args.m4 b/config/kernel-bio-end-io-t-args.m4
+index 3c420cc0c..80a1fbeda 100644
+--- a/config/kernel-bio-end-io-t-args.m4
++++ b/config/kernel-bio-end-io-t-args.m4
+@@ -5,20 +5,21 @@ dnl # bio->bi_error. This also replaces bio->bi_flags value BIO_UPTODATE.
+ dnl # Introduced by torvalds/linux@4246a0b63bd8f56a1469b12eafeb875b1041a451
+ dnl # ("block: add a bi_error field to struct bio").
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BIO_END_IO_T_ARGS], [
+-      AC_MSG_CHECKING([whether bio_end_io_t wants 1 arg])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_END_IO_T_ARGS], [
++      ZFS_LINUX_TEST_SRC([bio_end_io_t_args], [
+               #include <linux/bio.h>
+-
+               void wanted_end_io(struct bio *bio) { return; }
+-
+               bio_end_io_t *end_io __attribute__ ((unused)) = wanted_end_io;
+-      ],[
+-      ],[
++      ], [])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BIO_END_IO_T_ARGS], [
++      AC_MSG_CHECKING([whether bio_end_io_t wants 1 arg])
++      ZFS_LINUX_TEST_RESULT([bio_end_io_t_args], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_1ARG_BIO_END_IO_T, 1,
+-                        [bio_end_io_t wants 1 arg])
+-      ],[
++                  [bio_end_io_t wants 1 arg])
++      ], [
+               AC_MSG_RESULT(no)
+       ])
+ ])
+@@ -28,16 +29,19 @@ dnl # 4.13 API change
+ dnl # The bio->bi_error field was replaced with bio->bi_status which is an
+ dnl # enum which describes all possible error types.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BIO_BI_STATUS], [
+-      AC_MSG_CHECKING([whether bio->bi_status exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_BI_STATUS], [
++      ZFS_LINUX_TEST_SRC([bio_bi_status], [
+               #include <linux/bio.h>
+-      ],[
++      ], [
+               struct bio bio __attribute__ ((unused));
+               blk_status_t status __attribute__ ((unused)) = BLK_STS_OK;
+-
+               bio.bi_status = status;
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BIO_BI_STATUS], [
++      AC_MSG_CHECKING([whether bio->bi_status exists])
++      ZFS_LINUX_TEST_RESULT([bio_bi_status], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BIO_BI_STATUS, 1, [bio->bi_status exists])
+       ],[
+diff --git a/config/kernel-bio-failfast.m4 b/config/kernel-bio-failfast.m4
+index cfbec0523..0c636f08c 100644
+--- a/config/kernel-bio-failfast.m4
++++ b/config/kernel-bio-failfast.m4
+@@ -3,37 +3,54 @@ dnl # Preferred interface for setting FAILFAST on a bio:
+ dnl #   2.6.28-2.6.35: BIO_RW_FAILFAST_{DEV|TRANSPORT|DRIVER}
+ dnl #       >= 2.6.36: REQ_FAILFAST_{DEV|TRANSPORT|DRIVER}
+ dnl #
+-
+-AC_DEFUN([ZFS_AC_KERNEL_BIO_FAILFAST_DTD], [
+-      AC_MSG_CHECKING([whether BIO_RW_FAILFAST_* are defined])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_FAILFAST_DTD], [
++      ZFS_LINUX_TEST_SRC([bio_failfast_dtd], [
+               #include <linux/bio.h>
+       ],[
+               int flags __attribute__ ((unused));
+               flags = ((1 << BIO_RW_FAILFAST_DEV) |
+                        (1 << BIO_RW_FAILFAST_TRANSPORT) |
+                        (1 << BIO_RW_FAILFAST_DRIVER));
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BIO_FAILFAST_DTD], [
++      AC_MSG_CHECKING([whether BIO_RW_FAILFAST_* are defined])
++      ZFS_LINUX_TEST_RESULT([bio_failfast_dtd], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BIO_RW_FAILFAST_DTD, 1,
+-                        [BIO_RW_FAILFAST_* are defined])
++                  [BIO_RW_FAILFAST_* are defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+ ])
+-AC_DEFUN([ZFS_AC_KERNEL_REQ_FAILFAST_MASK], [
+-      AC_MSG_CHECKING([whether REQ_FAILFAST_MASK is defined])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_REQ_FAILFAST_MASK], [
++      ZFS_LINUX_TEST_SRC([bio_failfast_mask], [
+               #include <linux/bio.h>
+       ],[
+               int flags __attribute__ ((unused));
+               flags = REQ_FAILFAST_MASK;
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_REQ_FAILFAST_MASK], [
++      AC_MSG_CHECKING([whether REQ_FAILFAST_MASK is defined])
++      ZFS_LINUX_TEST_RESULT([bio_failfast_mask], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_REQ_FAILFAST_MASK, 1,
+-                        [REQ_FAILFAST_MASK is defined])
++                  [REQ_FAILFAST_MASK is defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+ ])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_FAILFAST], [
++      ZFS_AC_KERNEL_SRC_BIO_FAILFAST_DTD
++      ZFS_AC_KERNEL_SRC_REQ_FAILFAST_MASK
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BIO_FAILFAST], [
++      ZFS_AC_KERNEL_BIO_FAILFAST_DTD
++      ZFS_AC_KERNEL_REQ_FAILFAST_MASK
++])
+diff --git a/config/kernel-bio-op.m4 b/config/kernel-bio-op.m4
+index 8299e490c..1f2d23791 100644
+--- a/config/kernel-bio-op.m4
++++ b/config/kernel-bio-op.m4
+@@ -5,13 +5,43 @@ dnl # The bio_op() helper was introduced as a replacement for explicitly
+ dnl # checking the bio->bi_rw flags.  The following checks are used to
+ dnl # detect if a specific operation is supported.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_REQ_OP_DISCARD], [
+-      AC_MSG_CHECKING([whether REQ_OP_DISCARD is defined])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_OPS], [
++      ZFS_LINUX_TEST_SRC([req_op_discard], [
+               #include <linux/blk_types.h>
+       ],[
+               int op __attribute__ ((unused)) = REQ_OP_DISCARD;
++      ])
++
++      ZFS_LINUX_TEST_SRC([req_op_secure_erase], [
++              #include <linux/blk_types.h>
+       ],[
++              int op __attribute__ ((unused)) = REQ_OP_SECURE_ERASE;
++      ])
++
++      ZFS_LINUX_TEST_SRC([req_op_flush], [
++              #include <linux/blk_types.h>
++      ],[
++              int op __attribute__ ((unused)) = REQ_OP_FLUSH;
++      ])
++
++      ZFS_LINUX_TEST_SRC([bio_bi_opf], [
++              #include <linux/bio.h>
++      ],[
++              struct bio bio __attribute__ ((unused));
++              bio.bi_opf = 0;
++      ])
++
++      ZFS_LINUX_TEST_SRC([bio_set_op_attrs], [
++              #include <linux/bio.h>
++      ],[
++              struct bio *bio __attribute__ ((unused)) = NULL;
++              bio_set_op_attrs(bio, 0, 0);
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_REQ_OP_DISCARD], [
++      AC_MSG_CHECKING([whether REQ_OP_DISCARD is defined])
++      ZFS_LINUX_TEST_RESULT([req_op_discard], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_REQ_OP_DISCARD, 1,
+                   [REQ_OP_DISCARD is defined])
+@@ -22,11 +52,7 @@ AC_DEFUN([ZFS_AC_KERNEL_REQ_OP_DISCARD], [
+ AC_DEFUN([ZFS_AC_KERNEL_REQ_OP_SECURE_ERASE], [
+       AC_MSG_CHECKING([whether REQ_OP_SECURE_ERASE is defined])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/blk_types.h>
+-      ],[
+-              int op __attribute__ ((unused)) = REQ_OP_SECURE_ERASE;
+-      ],[
++      ZFS_LINUX_TEST_RESULT([req_op_secure_erase], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_REQ_OP_SECURE_ERASE, 1,
+                   [REQ_OP_SECURE_ERASE is defined])
+@@ -38,14 +64,9 @@ AC_DEFUN([ZFS_AC_KERNEL_REQ_OP_SECURE_ERASE], [
+ AC_DEFUN([ZFS_AC_KERNEL_REQ_OP_FLUSH], [
+       AC_MSG_CHECKING([whether REQ_OP_FLUSH is defined])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/blk_types.h>
+-      ],[
+-              int op __attribute__ ((unused)) = REQ_OP_FLUSH;
+-      ],[
++      ZFS_LINUX_TEST_RESULT([req_op_flush], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_REQ_OP_FLUSH, 1,
+-                  [REQ_OP_FLUSH is defined])
++              AC_DEFINE(HAVE_REQ_OP_FLUSH, 1, [REQ_OP_FLUSH is defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+@@ -53,12 +74,7 @@ AC_DEFUN([ZFS_AC_KERNEL_REQ_OP_FLUSH], [
+ AC_DEFUN([ZFS_AC_KERNEL_BIO_BI_OPF], [
+       AC_MSG_CHECKING([whether bio->bi_opf is defined])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/bio.h>
+-      ],[
+-              struct bio bio __attribute__ ((unused));
+-              bio.bi_opf = 0;
+-      ],[
++      ZFS_LINUX_TEST_RESULT([bio_bi_opf], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BIO_BI_OPF, 1, [bio->bi_opf is defined])
+       ],[
+@@ -68,13 +84,7 @@ AC_DEFUN([ZFS_AC_KERNEL_BIO_BI_OPF], [
+ AC_DEFUN([ZFS_AC_KERNEL_HAVE_BIO_SET_OP_ATTRS], [
+       AC_MSG_CHECKING([whether bio_set_op_attrs is available])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/bio.h>
+-      ],[
+-              struct bio *bio __attribute__ ((unused)) = NULL;
+-
+-              bio_set_op_attrs(bio, 0, 0);
+-      ],[
++      ZFS_LINUX_TEST_RESULT([bio_set_op_attrs], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BIO_SET_OP_ATTRS, 1,
+                   [bio_set_op_attrs is available])
+@@ -82,3 +92,11 @@ AC_DEFUN([ZFS_AC_KERNEL_HAVE_BIO_SET_OP_ATTRS], [
+               AC_MSG_RESULT(no)
+       ])
+ ])
++
++AC_DEFUN([ZFS_AC_KERNEL_BIO_OPS], [
++      ZFS_AC_KERNEL_REQ_OP_DISCARD
++      ZFS_AC_KERNEL_REQ_OP_SECURE_ERASE
++      ZFS_AC_KERNEL_REQ_OP_FLUSH
++      ZFS_AC_KERNEL_BIO_BI_OPF
++      ZFS_AC_KERNEL_HAVE_BIO_SET_OP_ATTRS
++])
+diff --git a/config/kernel-bio-rw-barrier.m4 b/config/kernel-bio-rw-barrier.m4
+index bcf0f7ea0..f667d4884 100644
+--- a/config/kernel-bio-rw-barrier.m4
++++ b/config/kernel-bio-rw-barrier.m4
+@@ -3,20 +3,25 @@ dnl # Interface for issuing a discard bio:
+ dnl # 2.6.28-2.6.35: BIO_RW_BARRIER
+ dnl # 2.6.36-3.x:    REQ_BARRIER
+ dnl #
+-
++dnl #
+ dnl # Since REQ_BARRIER is a preprocessor definition, there is no need for an
+ dnl # autotools check for it. Also, REQ_BARRIER existed in the request layer
+ dnl # until torvalds/linux@7b6d91daee5cac6402186ff224c3af39d79f4a0e unified the
+ dnl # request layer and bio layer flags, so it would be wrong to assume that
+ dnl # the APIs are mutually exclusive contrary to the typical case.
+-AC_DEFUN([ZFS_AC_KERNEL_BIO_RW_BARRIER], [
+-      AC_MSG_CHECKING([whether BIO_RW_BARRIER is defined])
+-      ZFS_LINUX_TRY_COMPILE([
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_RW_BARRIER], [
++      ZFS_LINUX_TEST_SRC([bio_rw_barrier], [
+               #include <linux/bio.h>
+       ],[
+               int flags __attribute__ ((unused));
+               flags = BIO_RW_BARRIER;
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BIO_RW_BARRIER], [
++      AC_MSG_CHECKING([whether BIO_RW_BARRIER is defined])
++      ZFS_LINUX_TEST_RESULT([bio_rw_barrier], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BIO_RW_BARRIER, 1, [BIO_RW_BARRIER is defined])
+       ],[
+diff --git a/config/kernel-bio-rw-discard.m4 b/config/kernel-bio-rw-discard.m4
+index 0554b9a9d..34a89279c 100644
+--- a/config/kernel-bio-rw-discard.m4
++++ b/config/kernel-bio-rw-discard.m4
+@@ -3,20 +3,25 @@ dnl # Interface for issuing a discard bio:
+ dnl # 2.6.28-2.6.35: BIO_RW_DISCARD
+ dnl # 2.6.36-3.x:    REQ_DISCARD
+ dnl #
+-
++dnl #
+ dnl # Since REQ_DISCARD is a preprocessor definition, there is no need for an
+ dnl # autotools check for it. Also, REQ_DISCARD existed in the request layer
+ dnl # until torvalds/linux@7b6d91daee5cac6402186ff224c3af39d79f4a0e unified the
+ dnl # request layer and bio layer flags, so it would be wrong to assume that
+ dnl # the APIs are mutually exclusive contrary to the typical case.
+-AC_DEFUN([ZFS_AC_KERNEL_BIO_RW_DISCARD], [
+-      AC_MSG_CHECKING([whether BIO_RW_DISCARD is defined])
+-      ZFS_LINUX_TRY_COMPILE([
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_RW_DISCARD], [
++      ZFS_LINUX_TEST_SRC([bio_rw_discard], [
+               #include <linux/bio.h>
+       ],[
+               int flags __attribute__ ((unused));
+               flags = BIO_RW_DISCARD;
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BIO_RW_DISCARD], [
++      AC_MSG_CHECKING([whether BIO_RW_DISCARD is defined])
++      ZFS_LINUX_TEST_RESULT([bio_rw_discard], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BIO_RW_DISCARD, 1, [BIO_RW_DISCARD is defined])
+       ],[
+diff --git a/config/kernel-bio_set_dev.m4 b/config/kernel-bio_set_dev.m4
+index 71d47a893..b8e13f35a 100644
+--- a/config/kernel-bio_set_dev.m4
++++ b/config/kernel-bio_set_dev.m4
+@@ -3,51 +3,38 @@ dnl # Linux 4.14 API,
+ dnl #
+ dnl # The bio_set_dev() helper macro was introduced as part of the transition
+ dnl # to have struct gendisk in struct bio. 
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BIO_SET_DEV_MACRO], [
+-      AC_MSG_CHECKING([whether bio_set_dev() exists])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/bio.h>
+-              #include <linux/fs.h>
+-      ],[
+-              struct block_device *bdev = NULL;
+-              struct bio *bio = NULL;
+-              bio_set_dev(bio, bdev);
+-      ],[
+-              AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_BIO_SET_DEV, 1, [bio_set_dev() exists])
+-      ],[
+-              AC_MSG_RESULT(no)
+-      ])
+-])
+-
+ dnl #
+ dnl # Linux 5.0 API,
+ dnl #
+ dnl # The bio_set_dev() helper macro was updated to internally depend on
+ dnl # bio_associate_blkg() symbol which is exported GPL-only.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BIO_SET_DEV_GPL_ONLY], [
+-      AC_MSG_CHECKING([whether bio_set_dev() is GPL-only])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/module.h>
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_SET_DEV], [
++      ZFS_LINUX_TEST_SRC([bio_set_dev], [
+               #include <linux/bio.h>
+               #include <linux/fs.h>
+-              MODULE_LICENSE("$ZFS_META_LICENSE");
+       ],[
+               struct block_device *bdev = NULL;
+               struct bio *bio = NULL;
+               bio_set_dev(bio, bdev);
+-      ],[
+-              AC_MSG_RESULT(no)
+-      ],[
+-              AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_BIO_SET_DEV_GPL_ONLY, 1,
+-                  [bio_set_dev() GPL-only])
+-      ])
++      ], [], [$ZFS_META_LICENSE])
+ ])
+ AC_DEFUN([ZFS_AC_KERNEL_BIO_SET_DEV], [
+-      ZFS_AC_KERNEL_BIO_SET_DEV_MACRO
+-      ZFS_AC_KERNEL_BIO_SET_DEV_GPL_ONLY
++      AC_MSG_CHECKING([whether bio_set_dev() is available])
++      ZFS_LINUX_TEST_RESULT([bio_set_dev], [
++              AC_MSG_RESULT(yes)
++              AC_DEFINE(HAVE_BIO_SET_DEV, 1, [bio_set_dev() is available])
++
++              AC_MSG_CHECKING([whether bio_set_dev() is GPL-only])
++              ZFS_LINUX_TEST_RESULT([bio_set_dev_license], [
++                      AC_MSG_RESULT(no)
++              ],[
++                      AC_MSG_RESULT(yes)
++                      AC_DEFINE(HAVE_BIO_SET_DEV_GPL_ONLY, 1,
++                          [bio_set_dev() GPL-only])
++              ])
++      ],[
++              AC_MSG_RESULT(no)
++      ])
+ ])
+diff --git a/config/kernel-blk-queue-bdi.m4 b/config/kernel-blk-queue-bdi.m4
+index 816471166..28241c494 100644
+--- a/config/kernel-blk-queue-bdi.m4
++++ b/config/kernel-blk-queue-bdi.m4
+@@ -2,15 +2,19 @@ dnl #
+ dnl # 2.6.32 - 4.11, statically allocated bdi in request_queue
+ dnl # 4.12 - x.y, dynamically allocated bdi in request_queue
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_BDI], [
+-      AC_MSG_CHECKING([whether blk_queue bdi is dynamic])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_BDI], [
++      ZFS_LINUX_TEST_SRC([blk_queue_bdi], [
+               #include <linux/blkdev.h>
+       ],[
+               struct request_queue q;
+               struct backing_dev_info bdi;
+               q.backing_dev_info = &bdi;
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_BDI], [
++      AC_MSG_CHECKING([whether blk_queue bdi is dynamic])
++      ZFS_LINUX_TEST_RESULT([blk_queue_bdi], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BLK_QUEUE_BDI_DYNAMIC, 1,
+                   [blk queue backing_dev_info is dynamic])
+diff --git a/config/kernel-blk-queue-discard.m4 b/config/kernel-blk-queue-discard.m4
+index addbba814..85a29356d 100644
+--- a/config/kernel-blk-queue-discard.m4
++++ b/config/kernel-blk-queue-discard.m4
+@@ -2,16 +2,19 @@ dnl #
+ dnl # 2.6.32 - 4.x API,
+ dnl #   blk_queue_discard()
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_DISCARD], [
+-      AC_MSG_CHECKING([whether blk_queue_discard() is available])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_DISCARD], [
++      ZFS_LINUX_TEST_SRC([blk_queue_discard], [
+               #include <linux/blkdev.h>
+       ],[
+               struct request_queue *q __attribute__ ((unused)) = NULL;
+               int value __attribute__ ((unused));
+-
+               value = blk_queue_discard(q);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_DISCARD], [
++      AC_MSG_CHECKING([whether blk_queue_discard() is available])
++      ZFS_LINUX_TEST_RESULT([blk_queue_discard], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BLK_QUEUE_DISCARD, 1,
+                   [blk_queue_discard() is available])
+@@ -30,16 +33,27 @@ dnl #
+ dnl # 2.6.x - 2.6.35 API,
+ dnl #   Unsupported by kernel
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_SECURE_ERASE], [
+-      AC_MSG_CHECKING([whether blk_queue_secure_erase() is available])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_SECURE_ERASE], [
++      ZFS_LINUX_TEST_SRC([blk_queue_secure_erase], [
+               #include <linux/blkdev.h>
+       ],[
+               struct request_queue *q __attribute__ ((unused)) = NULL;
+               int value __attribute__ ((unused));
+-
+               value = blk_queue_secure_erase(q);
++      ])
++
++      ZFS_LINUX_TEST_SRC([blk_queue_secdiscard], [
++              #include <linux/blkdev.h>
+       ],[
++              struct request_queue *q __attribute__ ((unused)) = NULL;
++              int value __attribute__ ((unused));
++              value = blk_queue_secdiscard(q);
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_SECURE_ERASE], [
++      AC_MSG_CHECKING([whether blk_queue_secure_erase() is available])
++      ZFS_LINUX_TEST_RESULT([blk_queue_secure_erase], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BLK_QUEUE_SECURE_ERASE, 1,
+                   [blk_queue_secure_erase() is available])
+@@ -47,14 +61,7 @@ AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_SECURE_ERASE], [
+               AC_MSG_RESULT(no)
+               AC_MSG_CHECKING([whether blk_queue_secdiscard() is available])
+-              ZFS_LINUX_TRY_COMPILE([
+-                      #include <linux/blkdev.h>
+-              ],[
+-                      struct request_queue *q __attribute__ ((unused)) = NULL;
+-                      int value __attribute__ ((unused));
+-
+-                      value = blk_queue_secdiscard(q);
+-              ],[
++              ZFS_LINUX_TEST_RESULT([blk_queue_secdiscard], [
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_BLK_QUEUE_SECDISCARD, 1,
+                           [blk_queue_secdiscard() is available])
+diff --git a/config/kernel-blk-queue-flags.m4 b/config/kernel-blk-queue-flags.m4
+index b570245c7..9d4dfc159 100644
+--- a/config/kernel-blk-queue-flags.m4
++++ b/config/kernel-blk-queue-flags.m4
+@@ -3,36 +3,54 @@ dnl # API change
+ dnl # https://github.com/torvalds/linux/commit/8814ce8
+ dnl # Introduction of blk_queue_flag_set and blk_queue_flag_clear
+ dnl #
+-
+-AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_FLAG_SET], [
+-      AC_MSG_CHECKING([whether blk_queue_flag_set() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_FLAG_SET], [
++      ZFS_LINUX_TEST_SRC([blk_queue_flag_set], [
+               #include <linux/kernel.h>
+               #include <linux/blkdev.h>
+       ],[
+               struct request_queue *q = NULL;
+               blk_queue_flag_set(0, q);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_FLAG_SET], [
++      AC_MSG_CHECKING([whether blk_queue_flag_set() exists])
++      ZFS_LINUX_TEST_RESULT([blk_queue_flag_set], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_BLK_QUEUE_FLAG_SET, 1, [blk_queue_flag_set() exists])
++              AC_DEFINE(HAVE_BLK_QUEUE_FLAG_SET, 1,
++                  [blk_queue_flag_set() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+ ])
+-AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_FLAG_CLEAR], [
+-      AC_MSG_CHECKING([whether blk_queue_flag_clear() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_FLAG_CLEAR], [
++      ZFS_LINUX_TEST_SRC([blk_queue_flag_clear], [
+               #include <linux/kernel.h>
+               #include <linux/blkdev.h>
+       ],[
+               struct request_queue *q = NULL;
+               blk_queue_flag_clear(0, q);
+-      ],[
++      ])
++])
++AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_FLAG_CLEAR], [
++      AC_MSG_CHECKING([whether blk_queue_flag_clear() exists])
++      ZFS_LINUX_TEST_RESULT([blk_queue_flag_clear], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_BLK_QUEUE_FLAG_CLEAR, 1, [blk_queue_flag_clear() exists])
++              AC_DEFINE(HAVE_BLK_QUEUE_FLAG_CLEAR, 1,
++                  [blk_queue_flag_clear() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+ ])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_FLAGS], [
++      ZFS_AC_KERNEL_SRC_BLK_QUEUE_FLAG_SET
++      ZFS_AC_KERNEL_SRC_BLK_QUEUE_FLAG_CLEAR
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_FLAGS], [
++      ZFS_AC_KERNEL_BLK_QUEUE_FLAG_SET
++      ZFS_AC_KERNEL_BLK_QUEUE_FLAG_CLEAR
++])
+diff --git a/config/kernel-blk-queue-flush.m4 b/config/kernel-blk-queue-flush.m4
+index 1baab83a4..b546d9400 100644
+--- a/config/kernel-blk-queue-flush.m4
++++ b/config/kernel-blk-queue-flush.m4
+@@ -9,35 +9,37 @@ dnl # there we implement our own compatibility function, otherwise
+ dnl # we use the function.  The hope is that long term this function
+ dnl # will be opened up.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_FLUSH], [
+-      AC_MSG_CHECKING([whether blk_queue_flush() is available])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_FLUSH], [
++      ZFS_LINUX_TEST_SRC([blk_queue_flush], [
+               #include <linux/blkdev.h>
+-      ],[
++      ], [
+               struct request_queue *q = NULL;
+               (void) blk_queue_flush(q, REQ_FLUSH);
+-      ],[
++      ], [$NO_UNUSED_BUT_SET_VARIABLE], [$ZFS_META_LICENSE])
++
++      ZFS_LINUX_TEST_SRC([blk_queue_write_cache], [
++              #include <linux/kernel.h>
++              #include <linux/blkdev.h>
++      ], [
++              struct request_queue *q = NULL;
++              blk_queue_write_cache(q, true, true);
++      ], [$NO_UNUSED_BUT_SET_VARIABLE], [$ZFS_META_LICENSE])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_FLUSH], [
++      AC_MSG_CHECKING([whether blk_queue_flush() is available])
++      ZFS_LINUX_TEST_RESULT([blk_queue_flush], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BLK_QUEUE_FLUSH, 1,
+-                        [blk_queue_flush() is available])
++                  [blk_queue_flush() is available])
+               AC_MSG_CHECKING([whether blk_queue_flush() is GPL-only])
+-              ZFS_LINUX_TRY_COMPILE([
+-                      #include <linux/module.h>
+-                      #include <linux/blkdev.h>
+-
+-                      MODULE_LICENSE("$ZFS_META_LICENSE");
+-              ],[
+-                      struct request_queue *q = NULL;
+-                      (void) blk_queue_flush(q, REQ_FLUSH);
+-              ],[
++              ZFS_LINUX_TEST_RESULT([blk_queue_flush_license], [
+                       AC_MSG_RESULT(no)
+               ],[
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_BLK_QUEUE_FLUSH_GPL_ONLY, 1,
+-                                [blk_queue_flush() is GPL-only])
++                          [blk_queue_flush() is GPL-only])
+               ])
+       ],[
+               AC_MSG_RESULT(no)
+@@ -48,38 +50,20 @@ AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_FLUSH], [
+       dnl # Replace blk_queue_flush with blk_queue_write_cache
+       dnl #
+       AC_MSG_CHECKING([whether blk_queue_write_cache() exists])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/kernel.h>
+-              #include <linux/blkdev.h>
+-
+-      ],[
+-              struct request_queue *q = NULL;
+-              blk_queue_write_cache(q, true, true);
+-      ],[
++      ZFS_LINUX_TEST_RESULT([blk_queue_write_cache], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BLK_QUEUE_WRITE_CACHE, 1,
+-                      [blk_queue_write_cache() exists])
++                  [blk_queue_write_cache() exists])
+               AC_MSG_CHECKING([whether blk_queue_write_cache() is GPL-only])
+-              ZFS_LINUX_TRY_COMPILE([
+-                      #include <linux/kernel.h>
+-                      #include <linux/module.h>
+-                      #include <linux/blkdev.h>
+-
+-                      MODULE_LICENSE("$ZFS_META_LICENSE");
+-              ],[
+-                      struct request_queue *q = NULL;
+-                      blk_queue_write_cache(q, true, true);
+-              ],[
++              ZFS_LINUX_TEST_RESULT([blk_queue_write_cache_license], [
+                       AC_MSG_RESULT(no)
+               ],[
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_BLK_QUEUE_WRITE_CACHE_GPL_ONLY, 1,
+-                                [blk_queue_write_cache() is GPL-only])
++                          [blk_queue_write_cache() is GPL-only])
+               ])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+-
+-      EXTRA_KCFLAGS="$tmp_flags"
+ ])
+diff --git a/config/kernel-blk-queue-max-hw-sectors.m4 b/config/kernel-blk-queue-max-hw-sectors.m4
+index 2f5515dc6..7387f84de 100644
+--- a/config/kernel-blk-queue-max-hw-sectors.m4
++++ b/config/kernel-blk-queue-max-hw-sectors.m4
+@@ -2,21 +2,22 @@ dnl #
+ dnl # 2.6.34 API change
+ dnl # blk_queue_max_hw_sectors() replaces blk_queue_max_sectors().
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_MAX_HW_SECTORS], [
+-      AC_MSG_CHECKING([whether blk_queue_max_hw_sectors() is available])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_MAX_HW_SECTORS], [
++      ZFS_LINUX_TEST_SRC([blk_queue_max_hw_sectors], [
+               #include <linux/blkdev.h>
+-      ],[
++      ], [
+               struct request_queue *q = NULL;
+               (void) blk_queue_max_hw_sectors(q, BLK_SAFE_MAX_SECTORS);
+-      ],[
++      ], [$NO_UNUSED_BUT_SET_VARIABLE])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_MAX_HW_SECTORS], [
++      AC_MSG_CHECKING([whether blk_queue_max_hw_sectors() is available])
++      ZFS_LINUX_TEST_RESULT([blk_queue_max_hw_sectors], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BLK_QUEUE_MAX_HW_SECTORS, 1,
+-                        [blk_queue_max_hw_sectors() is available])
++                  [blk_queue_max_hw_sectors() is available])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
+ ])
+diff --git a/config/kernel-blk-queue-max-segments.m4 b/config/kernel-blk-queue-max-segments.m4
+index b2a40423a..1e4092df9 100644
+--- a/config/kernel-blk-queue-max-segments.m4
++++ b/config/kernel-blk-queue-max-segments.m4
+@@ -3,21 +3,22 @@ dnl # 2.6.34 API change
+ dnl # blk_queue_max_segments() consolidates blk_queue_max_hw_segments()
+ dnl # and blk_queue_max_phys_segments().
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_MAX_SEGMENTS], [
+-      AC_MSG_CHECKING([whether blk_queue_max_segments() is available])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_MAX_SEGMENTS], [
++      ZFS_LINUX_TEST_SRC([blk_queue_max_segments], [
+               #include <linux/blkdev.h>
+-      ],[
++      ], [
+               struct request_queue *q = NULL;
+               (void) blk_queue_max_segments(q, BLK_MAX_SEGMENTS);
+-      ],[
++      ], [$NO_UNUSED_BUT_SET_VARIABLE])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_MAX_SEGMENTS], [
++      AC_MSG_CHECKING([whether blk_queue_max_segments() is available])
++      ZFS_LINUX_TEST_RESULT([blk_queue_max_segments], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BLK_QUEUE_MAX_SEGMENTS, 1,
+-                        [blk_queue_max_segments() is available])
+-      ],[
++                  [blk_queue_max_segments() is available])
++      ], [
+               AC_MSG_RESULT(no)
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
+ ])
+diff --git a/config/kernel-blk-queue-unplug.m4 b/config/kernel-blk-queue-unplug.m4
+index 075fbccd1..f5d1814b8 100644
+--- a/config/kernel-blk-queue-unplug.m4
++++ b/config/kernel-blk-queue-unplug.m4
+@@ -2,43 +2,53 @@ dnl #
+ dnl # 2.6.32-2.6.35 API - The BIO_RW_UNPLUG enum can be used as a hint
+ dnl # to unplug the queue.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_HAVE_BIO_RW_UNPLUG], [
+-      AC_MSG_CHECKING([whether the BIO_RW_UNPLUG enum is available])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_RW_UNPLUG], [
++      ZFS_LINUX_TEST_SRC([blk_queue_bio_rw_unplug], [
+               #include <linux/blkdev.h>
+       ],[
+-              extern enum bio_rw_flags rw;
++              enum bio_rw_flags rw __attribute__ ((unused)) = BIO_RW_UNPLUG;
++      ])
++])
+-              rw = BIO_RW_UNPLUG;
+-      ],[
++AC_DEFUN([ZFS_AC_KERNEL_BIO_RW_UNPLUG], [
++      AC_MSG_CHECKING([whether the BIO_RW_UNPLUG enum is available])
++      ZFS_LINUX_TEST_RESULT([blk_queue_bio_rw_unplug], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BLK_QUEUE_HAVE_BIO_RW_UNPLUG, 1,
+-                        [BIO_RW_UNPLUG is available])
++                  [BIO_RW_UNPLUG is available])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
+ ])
+-AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_HAVE_BLK_PLUG], [
+-      AC_MSG_CHECKING([whether struct blk_plug is available])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_PLUG], [
++      ZFS_LINUX_TEST_SRC([blk_plug], [
+               #include <linux/blkdev.h>
+       ],[
+-              struct blk_plug plug;
++              struct blk_plug plug __attribute__ ((unused));
+               blk_start_plug(&plug);
+               blk_finish_plug(&plug);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BLK_PLUG], [
++      AC_MSG_CHECKING([whether struct blk_plug is available])
++      ZFS_LINUX_TEST_RESULT([blk_plug], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BLK_QUEUE_HAVE_BLK_PLUG, 1,
+-                        [struct blk_plug is available])
++                  [struct blk_plug is available])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_PLUG], [
++      ZFS_AC_KERNEL_SRC_BIO_RW_UNPLUG
++      ZFS_AC_KERNEL_SRC_BLK_PLUG
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_PLUG], [
++      ZFS_AC_KERNEL_BIO_RW_UNPLUG
++      ZFS_AC_KERNEL_BLK_PLUG
+ ])
+diff --git a/config/kernel-blkdev-get-by-path.m4 b/config/kernel-blkdev-get-by-path.m4
+index 40ecc06b6..fb0cea6af 100644
+--- a/config/kernel-blkdev-get-by-path.m4
++++ b/config/kernel-blkdev-get-by-path.m4
+@@ -3,16 +3,21 @@ dnl # 2.6.38 API change
+ dnl # open_bdev_exclusive() changed to blkdev_get_by_path()
+ dnl # close_bdev_exclusive() changed to blkdev_put()
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_GET_BY_PATH],
+-      [AC_MSG_CHECKING([whether blkdev_get_by_path() is available])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH], [
++      ZFS_LINUX_TEST_SRC([blkdev_get_by_path], [
+               #include <linux/fs.h>
+       ], [
+               blkdev_get_by_path(NULL, 0, NULL);
+-      ], [blkdev_get_by_path], [fs/block_dev.c], [
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_GET_BY_PATH], [
++      AC_MSG_CHECKING([whether blkdev_get_by_path() is available])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([blkdev_get_by_path],
++          [blkdev_get_by_path], [fs/block_dev.c], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BLKDEV_GET_BY_PATH, 1,
+-                        [blkdev_get_by_path() is available])
++                  [blkdev_get_by_path() is available])
+       ], [
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-blkdev-reread-part.m4 b/config/kernel-blkdev-reread-part.m4
+index 5664769a3..1bf1e7c3a 100644
+--- a/config/kernel-blkdev-reread-part.m4
++++ b/config/kernel-blkdev-reread-part.m4
+@@ -2,16 +2,20 @@ dnl #
+ dnl # 4.1 API, exported blkdev_reread_part() symbol, backported to the
+ dnl # 3.10.0 CentOS 7.x enterprise kernels.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_REREAD_PART], [
+-      AC_MSG_CHECKING([whether blkdev_reread_part() is available])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_REREAD_PART], [
++      ZFS_LINUX_TEST_SRC([blkdev_reread_part], [
+               #include <linux/fs.h>
+       ], [
+               struct block_device *bdev = NULL;
+               int error;
+               error = blkdev_reread_part(bdev);
+-      ], [
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_REREAD_PART], [
++      AC_MSG_CHECKING([whether blkdev_reread_part() is available])
++      ZFS_LINUX_TEST_RESULT([blkdev_reread_part], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BLKDEV_REREAD_PART, 1,
+                   [blkdev_reread_part() is available])
+diff --git a/config/kernel-block-device-operations.m4 b/config/kernel-block-device-operations.m4
+index 5f2811c15..c3d5eec52 100644
+--- a/config/kernel-block-device-operations.m4
++++ b/config/kernel-block-device-operations.m4
+@@ -1,11 +1,8 @@
+ dnl #
+ dnl # 2.6.38 API change
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS], [
+-      AC_MSG_CHECKING([whether bops->check_events() exists])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS], [
++      ZFS_LINUX_TEST_SRC([block_device_operations_check_events], [
+               #include <linux/blkdev.h>
+               unsigned int blk_check_events(struct gendisk *disk,
+@@ -15,25 +12,25 @@ AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS], [
+                   bops __attribute__ ((unused)) = {
+                       .check_events   = blk_check_events,
+               };
+-      ],[
+-      ],[
++      ], [], [$NO_UNUSED_BUT_SET_VARIABLE])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS], [
++      AC_MSG_CHECKING([whether bops->check_events() exists])
++      ZFS_LINUX_TEST_RESULT([block_device_operations_check_events], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS, 1,
+                   [bops->check_events() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
+ ])
+ dnl #
+ dnl # 3.10.x API change
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID], [
+-      AC_MSG_CHECKING([whether bops->release() is void])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID], [
++      ZFS_LINUX_TEST_SRC([block_device_operations_release_void], [
+               #include <linux/blkdev.h>
+               void blk_release(struct gendisk *g, fmode_t mode) { return; }
+@@ -45,13 +42,26 @@ AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID], [
+                       .ioctl          = NULL,
+                       .compat_ioctl   = NULL,
+               };
+-      ],[
+-      ],[
+-              AC_MSG_RESULT(void)
++      ], [], [$NO_UNUSED_BUT_SET_VARIABLE])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID], [
++      AC_MSG_CHECKING([whether bops->release() is void])
++      ZFS_LINUX_TEST_RESULT([block_device_operations_release_void], [
++              AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID, 1,
+                         [bops->release() returns void])
+       ],[
+-              AC_MSG_RESULT(int)
++              AC_MSG_RESULT(no)
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS], [
++      ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS
++      ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS], [
++      ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS
++      ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID
+ ])
+diff --git a/config/kernel-clear-inode.m4 b/config/kernel-clear-inode.m4
+index 8d880fcd8..3f454d7ec 100644
+--- a/config/kernel-clear-inode.m4
++++ b/config/kernel-clear-inode.m4
+@@ -19,13 +19,18 @@ dnl # Therefore, to ensure we have the correct API we only allow the
+ dnl # clear_inode() compatibility code to be defined iff the evict_inode()
+ dnl # functionality is also detected.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_CLEAR_INODE],
+-      [AC_MSG_CHECKING([whether clear_inode() is available])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_CLEAR_INODE], [
++      ZFS_LINUX_TEST_SRC([clear_inode], [
+               #include <linux/fs.h>
+       ], [
+               clear_inode(NULL);
+-      ], [clear_inode], [fs/inode.c], [
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_CLEAR_INODE], [
++      AC_MSG_CHECKING([whether clear_inode() is available])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([clear_inode],
++          [clear_inode], [fs/inode.c], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_CLEAR_INODE, 1, [clear_inode() is available])
+       ], [
+diff --git a/config/kernel-commit-metadata.m4 b/config/kernel-commit-metadata.m4
+index b66a16fd2..9bc3b6622 100644
+--- a/config/kernel-commit-metadata.m4
++++ b/config/kernel-commit-metadata.m4
+@@ -4,19 +4,22 @@ dnl # Added eops->commit_metadata() callback to allow the underlying
+ dnl # filesystem to determine the most efficient way to commit the inode.
+ dnl # Prior to this the nfs server would issue an explicit fsync().
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_COMMIT_METADATA], [
+-      AC_MSG_CHECKING([whether eops->commit_metadata() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_COMMIT_METADATA], [
++      ZFS_LINUX_TEST_SRC([export_operations_commit_metadata], [
+               #include <linux/exportfs.h>
+               int commit_metadata(struct inode *inode) { return 0; }
+               static struct export_operations eops __attribute__ ((unused))={
+                       .commit_metadata = commit_metadata,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_COMMIT_METADATA], [
++      AC_MSG_CHECKING([whether eops->commit_metadata() exists])
++      ZFS_LINUX_TEST_RESULT([export_operations_commit_metadata], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_COMMIT_METADATA, 1,
+-                        [eops->commit_metadata() exists])
++                  [eops->commit_metadata() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-config-defined.m4 b/config/kernel-config-defined.m4
+new file mode 100644
+index 000000000..0ee4231cc
+--- /dev/null
++++ b/config/kernel-config-defined.m4
+@@ -0,0 +1,183 @@
++dnl #
++dnl # Certain kernel build options are not supported.  These must be
++dnl # detected at configure time and cause a build failure.  Otherwise
++dnl # modules may be successfully built that behave incorrectly.
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_CONFIG_DEFINED], [
++      AS_IF([test "x$cross_compiling" != xyes], [
++              AC_RUN_IFELSE([
++                      AC_LANG_PROGRAM([
++                              #include "$LINUX/include/linux/license.h"
++                      ], [
++                              return !license_is_gpl_compatible(
++                                  "$ZFS_META_LICENSE");
++                      ])
++              ], [
++                      AC_DEFINE([ZFS_IS_GPL_COMPATIBLE], [1],
++                          [Define to 1 if GPL-only symbols can be used])
++              ], [
++              ])
++      ])
++
++      ZFS_AC_KERNEL_SRC_CONFIG_THREAD_SIZE
++      ZFS_AC_KERNEL_SRC_CONFIG_DEBUG_LOCK_ALLOC
++      ZFS_AC_KERNEL_SRC_CONFIG_TRIM_UNUSED_KSYMS
++      ZFS_AC_KERNEL_SRC_CONFIG_ZLIB_INFLATE
++      ZFS_AC_KERNEL_SRC_CONFIG_ZLIB_DEFLATE
++
++      AC_MSG_CHECKING([for kernel config option compatibility])
++      ZFS_LINUX_TEST_COMPILE_ALL([config])
++      AC_MSG_RESULT([done])
++
++      ZFS_AC_KERNEL_CONFIG_THREAD_SIZE
++      ZFS_AC_KERNEL_CONFIG_DEBUG_LOCK_ALLOC
++      ZFS_AC_KERNEL_CONFIG_TRIM_UNUSED_KSYMS
++      ZFS_AC_KERNEL_CONFIG_ZLIB_INFLATE
++      ZFS_AC_KERNEL_CONFIG_ZLIB_DEFLATE
++])
++
++dnl #
++dnl # Check configured THREAD_SIZE
++dnl #
++dnl # The stack size will vary by architecture, but as of Linux 3.15 on x86_64
++dnl # the default thread stack size was increased to 16K from 8K.  Therefore,
++dnl # on newer kernels and some architectures stack usage optimizations can be
++dnl # conditionally applied to improve performance without negatively impacting
++dnl # stability.
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_CONFIG_THREAD_SIZE], [
++      ZFS_LINUX_TEST_SRC([config_thread_size], [
++              #include <linux/module.h>
++      ],[
++              #if (THREAD_SIZE < 16384)
++              #error "THREAD_SIZE is less than 16K"
++              #endif
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_CONFIG_THREAD_SIZE], [
++      AC_MSG_CHECKING([whether kernel was built with 16K or larger stacks])
++      ZFS_LINUX_TEST_RESULT([config_thread_size], [
++              AC_MSG_RESULT([yes])
++              AC_DEFINE(HAVE_LARGE_STACKS, 1, [kernel has large stacks])
++      ],[
++              AC_MSG_RESULT([no])
++      ])
++])
++
++dnl #
++dnl # Check CONFIG_DEBUG_LOCK_ALLOC
++dnl #
++dnl # This is typically only set for debug kernels because it comes with
++dnl # a performance penalty.  However, when it is set it maps the non-GPL
++dnl # symbol mutex_lock() to the GPL-only mutex_lock_nested() symbol.
++dnl # This will cause a failure at link time which we'd rather know about
++dnl # at compile time.
++dnl #
++dnl # Since we plan to pursue making mutex_lock_nested() a non-GPL symbol
++dnl # with the upstream community we add a check to detect this case.
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_CONFIG_DEBUG_LOCK_ALLOC], [
++      ZFS_LINUX_TEST_SRC([config_debug_lock_alloc], [
++              #include <linux/mutex.h>
++      ],[
++              struct mutex lock;
++
++              mutex_init(&lock);
++              mutex_lock(&lock);
++              mutex_unlock(&lock);
++      ], [], [$ZFS_META_LICENSE])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_CONFIG_DEBUG_LOCK_ALLOC], [
++      AC_MSG_CHECKING([whether mutex_lock() is GPL-only])
++      ZFS_LINUX_TEST_RESULT([config_debug_lock_alloc], [
++              AC_MSG_RESULT(no)
++      ],[
++              AC_MSG_RESULT(yes)
++              AC_MSG_ERROR([
++      *** Kernel built with CONFIG_DEBUG_LOCK_ALLOC which is incompatible
++      *** with the CDDL license and will prevent the module linking stage
++      *** from succeeding.  You must rebuild your kernel without this
++      *** option enabled.])
++      ])
++])
++
++dnl #
++dnl # Check CONFIG_TRIM_UNUSED_KSYMS
++dnl #
++dnl # Verify the kernel has CONFIG_TRIM_UNUSED_KSYMS disabled.
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_CONFIG_TRIM_UNUSED_KSYMS], [
++      ZFS_LINUX_TEST_SRC([config_trim_unusued_ksyms], [
++              #if defined(CONFIG_TRIM_UNUSED_KSYMS)
++              #error CONFIG_TRIM_UNUSED_KSYMS not defined
++              #endif
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_CONFIG_TRIM_UNUSED_KSYMS], [
++      AC_MSG_CHECKING([whether CONFIG_TRIM_UNUSED_KSYM is disabled])
++      ZFS_LINUX_TEST_RESULT([config_trim_unusued_ksyms], [
++              AC_MSG_RESULT([yes])
++      ],[
++              AC_MSG_RESULT([no])
++              AS_IF([test "x$enable_linux_builtin" != xyes], [
++                      AC_MSG_ERROR([
++      *** This kernel has unused symbols trimming enabled, please disable.
++      *** Rebuild the kernel with CONFIG_TRIM_UNUSED_KSYMS=n set.])
++              ])
++      ])
++])
++
++dnl #
++dnl # Check CONFIG_ZLIB_INFLATE
++dnl #
++dnl # Verify the kernel has CONFIG_ZLIB_INFLATE support enabled.
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_CONFIG_ZLIB_INFLATE], [
++      ZFS_LINUX_TEST_SRC([config_zlib_inflate], [
++              #if !defined(CONFIG_ZLIB_INFLATE) && \
++                  !defined(CONFIG_ZLIB_INFLATE_MODULE)
++              #error CONFIG_ZLIB_INFLATE not defined
++              #endif
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_CONFIG_ZLIB_INFLATE], [
++      AC_MSG_CHECKING([whether CONFIG_ZLIB_INFLATE is defined])
++      ZFS_LINUX_TEST_RESULT([config_zlib_inflate], [
++              AC_MSG_RESULT([yes])
++      ],[
++              AC_MSG_RESULT([no])
++              AC_MSG_ERROR([
++      *** This kernel does not include the required zlib inflate support.
++      *** Rebuild the kernel with CONFIG_ZLIB_INFLATE=y|m set.])
++      ])
++])
++
++dnl #
++dnl # Check CONFIG_ZLIB_DEFLATE
++dnl #
++dnl # Verify the kernel has CONFIG_ZLIB_DEFLATE support enabled.
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_CONFIG_ZLIB_DEFLATE], [
++      ZFS_LINUX_TEST_SRC([config_zlib_deflate], [
++              #if !defined(CONFIG_ZLIB_DEFLATE) && \
++                  !defined(CONFIG_ZLIB_DEFLATE_MODULE)
++              #error CONFIG_ZLIB_DEFLATE not defined
++              #endif
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_CONFIG_ZLIB_DEFLATE], [
++      AC_MSG_CHECKING([whether CONFIG_ZLIB_DEFLATE is defined])
++      ZFS_LINUX_TEST_RESULT([config_zlib_deflate], [
++              AC_MSG_RESULT([yes])
++      ],[
++              AC_MSG_RESULT([no])
++              AC_MSG_ERROR([
++      *** This kernel does not include the required zlib deflate support.
++      *** Rebuild the kernel with CONFIG_ZLIB_DEFLATE=y|m set.])
++      ])
++])
+diff --git a/config/kernel-create-nameidata.m4 b/config/kernel-create-nameidata.m4
+index d4c155c57..c43ca5b85 100644
+--- a/config/kernel-create-nameidata.m4
++++ b/config/kernel-create-nameidata.m4
+@@ -1,9 +1,8 @@
+ dnl #
+ dnl # 3.6 API change
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_CREATE_NAMEIDATA], [
+-      AC_MSG_CHECKING([whether iops->create() passes nameidata])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE_NAMEIDATA], [
++      ZFS_LINUX_TEST_SRC([create_nameidata], [
+               #include <linux/fs.h>
+               #include <linux/sched.h>
+@@ -19,11 +18,15 @@ AC_DEFUN([ZFS_AC_KERNEL_CREATE_NAMEIDATA], [
+                   iops __attribute__ ((unused)) = {
+                       .create         = inode_create,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_CREATE_NAMEIDATA], [
++      AC_MSG_CHECKING([whether iops->create() passes nameidata])
++      ZFS_LINUX_TEST_RESULT([create_nameidata], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_CREATE_NAMEIDATA, 1,
+-                        [iops->create() passes nameidata])
++                  [iops->create() passes nameidata])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-ctl-table-name.m4 b/config/kernel-ctl-table-name.m4
+index 3ce499968..16f2ad544 100644
+--- a/config/kernel-ctl-table-name.m4
++++ b/config/kernel-ctl-table-name.m4
+@@ -2,14 +2,18 @@ dnl #
+ dnl # 2.6.33 API change,
+ dnl # Removed .ctl_name from struct ctl_table.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_CTL_NAME], [
+-      AC_MSG_CHECKING([whether struct ctl_table has ctl_name])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_CTL_NAME], [
++      ZFS_LINUX_TEST_SRC([ctl_name], [
+               #include <linux/sysctl.h>
+       ],[
+               struct ctl_table ctl __attribute__ ((unused));
+               ctl.ctl_name = 0;
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_CTL_NAME], [
++      AC_MSG_CHECKING([whether struct ctl_table has ctl_name])
++      ZFS_LINUX_TEST_RESULT([ctl_name], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_CTL_NAME, 1, [struct ctl_table has ctl_name])
+       ],[
+diff --git a/config/kernel-current-time.m4 b/config/kernel-current-time.m4
+index c7d5c9b52..3ceb5f63e 100644
+--- a/config/kernel-current-time.m4
++++ b/config/kernel-current-time.m4
+@@ -2,14 +2,19 @@ dnl #
+ dnl # 4.9, current_time() added
+ dnl # 4.18, return type changed from timespec to timespec64
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_CURRENT_TIME],
+-      [AC_MSG_CHECKING([whether current_time() exists])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_CURRENT_TIME], [
++      ZFS_LINUX_TEST_SRC([current_time], [
+               #include <linux/fs.h>
+       ], [
+               struct inode ip __attribute__ ((unused));
+               ip.i_atime = current_time(&ip);
+-      ], [current_time], [fs/inode.c], [
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_CURRENT_TIME], [
++      AC_MSG_CHECKING([whether current_time() exists])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([current_time],
++          [current_time], [fs/inode.c], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_CURRENT_TIME, 1, [current_time() exists])
+       ], [
+diff --git a/config/kernel-current_bio_tail.m4 b/config/kernel-current_bio_tail.m4
+index b72f21e8a..9dfc3e6e0 100644
+--- a/config/kernel-current_bio_tail.m4
++++ b/config/kernel-current_bio_tail.m4
+@@ -4,30 +4,36 @@ dnl # current->bio_tail and current->bio_list were struct bio pointers prior to
+ dnl # Linux 2.6.34. They were refactored into a struct bio_list pointer called
+ dnl # current->bio_list in Linux 2.6.34.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_CURRENT_BIO_TAIL], [
+-      AC_MSG_CHECKING([whether current->bio_tail exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_CURRENT_BIO_TAIL], [
++      ZFS_LINUX_TEST_SRC([current_bio_tail], [
+               #include <linux/sched.h>
+-      ],[
++      ], [
+               current->bio_tail = (struct bio **) NULL;
+-      ],[
++      ])
++
++      ZFS_LINUX_TEST_SRC([current_bio_list], [
++              #include <linux/sched.h>
++      ], [
++              current->bio_list = (struct bio_list *) NULL;
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_CURRENT_BIO_TAIL], [
++      AC_MSG_CHECKING([whether current->bio_tail exists])
++      ZFS_LINUX_TEST_RESULT([current_bio_tail], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_CURRENT_BIO_TAIL, 1,
+                   [current->bio_tail exists])
+       ],[
+               AC_MSG_RESULT(no)
++
+               AC_MSG_CHECKING([whether current->bio_list exists])
+-              ZFS_LINUX_TRY_COMPILE([
+-                      #include <linux/sched.h>
+-              ],[
+-                      current->bio_list = (struct bio_list *) NULL;
+-              ],[
++              ZFS_LINUX_TEST_RESULT([current_bio_list], [
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_CURRENT_BIO_LIST, 1,
+                           [current->bio_list exists])
+               ],[
+-                      AC_MSG_ERROR(no - Please file a bug report at
+-                          https://github.com/zfsonlinux/zfs/issues/new)
++                      ZFS_LINUX_TEST_ERROR([bio_list])
+               ])
+       ])
+ ])
+diff --git a/config/kernel-d-make-root.m4 b/config/kernel-d-make-root.m4
+deleted file mode 100644
+index 9c2b73dcb..000000000
+--- a/config/kernel-d-make-root.m4
++++ /dev/null
+@@ -1,17 +0,0 @@
+-dnl #
+-dnl # 3.4.0 API change
+-dnl # Added d_make_root() to replace previous d_alloc_root() function.
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_D_MAKE_ROOT],
+-      [AC_MSG_CHECKING([whether d_make_root() is available])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
+-              #include <linux/dcache.h>
+-      ], [
+-              d_make_root(NULL);
+-      ], [d_make_root], [fs/dcache.c], [
+-              AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_D_MAKE_ROOT, 1, [d_make_root() is available])
+-      ], [
+-              AC_MSG_RESULT(no)
+-      ])
+-])
+diff --git a/config/kernel-d-obtain-alias.m4 b/config/kernel-d-obtain-alias.m4
+deleted file mode 100644
+index 2b4b11ecc..000000000
+--- a/config/kernel-d-obtain-alias.m4
++++ /dev/null
+@@ -1,18 +0,0 @@
+-dnl #
+-dnl # 2.6.28 API change
+-dnl # Added d_obtain_alias() helper function.
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_D_OBTAIN_ALIAS],
+-      [AC_MSG_CHECKING([whether d_obtain_alias() is available])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
+-              #include <linux/dcache.h>
+-      ], [
+-              d_obtain_alias(NULL);
+-      ], [d_obtain_alias], [fs/dcache.c], [
+-              AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_D_OBTAIN_ALIAS, 1,
+-                        [d_obtain_alias() is available])
+-      ], [
+-              AC_MSG_RESULT(no)
+-      ])
+-])
+diff --git a/config/kernel-d-prune-aliases.m4 b/config/kernel-d-prune-aliases.m4
+deleted file mode 100644
+index d9c521b1d..000000000
+--- a/config/kernel-d-prune-aliases.m4
++++ /dev/null
+@@ -1,19 +0,0 @@
+-dnl #
+-dnl # 2.6.12 API change
+-dnl # d_prune_aliases() helper function available.
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_D_PRUNE_ALIASES],
+-      [AC_MSG_CHECKING([whether d_prune_aliases() is available])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
+-              #include <linux/dcache.h>
+-      ], [
+-              struct inode *ip = NULL;
+-              d_prune_aliases(ip);
+-      ], [d_prune_aliases], [fs/dcache.c], [
+-              AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_D_PRUNE_ALIASES, 1,
+-                        [d_prune_aliases() is available])
+-      ], [
+-              AC_MSG_RESULT(no)
+-      ])
+-])
+diff --git a/config/kernel-declare-event-class.m4 b/config/kernel-declare-event-class.m4
+index 7867d7517..6c78ee858 100644
+--- a/config/kernel-declare-event-class.m4
++++ b/config/kernel-declare-event-class.m4
+@@ -2,13 +2,10 @@ dnl #
+ dnl # Ensure the DECLARE_EVENT_CLASS macro is available to non-GPL modules.
+ dnl #
+ AC_DEFUN([ZFS_AC_KERNEL_DECLARE_EVENT_CLASS], [
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="-I\$(src)"
+-
+       AC_MSG_CHECKING([whether DECLARE_EVENT_CLASS() is available])
+       ZFS_LINUX_TRY_COMPILE_HEADER([
+               #include <linux/module.h>
+-              MODULE_LICENSE(ZFS_META_LICENSE);
++              MODULE_LICENSE("$ZFS_META_LICENSE");
+               #define CREATE_TRACE_POINTS
+               #include "conftest.h"
+@@ -18,7 +15,7 @@ AC_DEFUN([ZFS_AC_KERNEL_DECLARE_EVENT_CLASS], [
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_DECLARE_EVENT_CLASS, 1,
+-                        [DECLARE_EVENT_CLASS() is available])
++                  [DECLARE_EVENT_CLASS() is available])
+       ],[
+               AC_MSG_RESULT(no)
+       ],[
+@@ -55,5 +52,4 @@ AC_DEFUN([ZFS_AC_KERNEL_DECLARE_EVENT_CLASS], [
+               #define TRACE_INCLUDE_FILE conftest
+               #include <trace/define_trace.h>
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
+ ])
+diff --git a/config/kernel-dentry-operations.m4 b/config/kernel-dentry-operations.m4
+index 61f5a27af..f943dad4c 100644
+--- a/config/kernel-dentry-operations.m4
++++ b/config/kernel-dentry-operations.m4
+@@ -1,9 +1,103 @@
++dnl #
++dnl # 3.4.0 API change
++dnl # Added d_make_root() to replace previous d_alloc_root() function.
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_D_MAKE_ROOT], [
++      ZFS_LINUX_TEST_SRC([d_make_root], [
++              #include <linux/dcache.h>
++      ], [
++              d_make_root(NULL);
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_D_MAKE_ROOT], [
++      AC_MSG_CHECKING([whether d_make_root() is available])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([d_make_root],
++          [d_make_root], [fs/dcache.c], [
++              AC_MSG_RESULT(yes)
++              AC_DEFINE(HAVE_D_MAKE_ROOT, 1, [d_make_root() is available])
++      ], [
++              AC_MSG_RESULT(no)
++      ])
++])
++
++dnl #
++dnl # 2.6.28 API change
++dnl # Added d_obtain_alias() helper function.
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_D_OBTAIN_ALIAS], [
++      ZFS_LINUX_TEST_SRC([d_obtain_alias], [
++              #include <linux/dcache.h>
++      ], [
++              d_obtain_alias(NULL);
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_D_OBTAIN_ALIAS], [
++      AC_MSG_CHECKING([whether d_obtain_alias() is available])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([d_obtain_alias],
++          [d_obtain_alias], [fs/dcache.c], [
++              AC_MSG_RESULT(yes)
++              AC_DEFINE(HAVE_D_OBTAIN_ALIAS, 1,
++                        [d_obtain_alias() is available])
++      ], [
++              AC_MSG_RESULT(no)
++      ])
++])
++
++dnl #
++dnl # 2.6.12 API change
++dnl # d_prune_aliases() helper function available.
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_D_PRUNE_ALIASES], [
++      ZFS_LINUX_TEST_SRC([d_prune_aliases], [
++              #include <linux/dcache.h>
++      ], [
++              struct inode *ip = NULL;
++              d_prune_aliases(ip);
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_D_PRUNE_ALIASES], [
++      AC_MSG_CHECKING([whether d_prune_aliases() is available])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([d_prune_aliases],
++          [d_prune_aliases], [fs/dcache.c], [
++              AC_MSG_RESULT(yes)
++              AC_DEFINE(HAVE_D_PRUNE_ALIASES, 1,
++                  [d_prune_aliases() is available])
++      ], [
++              AC_MSG_RESULT(no)
++      ])
++])
++
++dnl #
++dnl # 2.6.38 API change
++dnl # Added d_set_d_op() helper function.
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_D_SET_D_OP], [
++      ZFS_LINUX_TEST_SRC([d_set_d_op], [
++              #include <linux/dcache.h>
++      ], [
++              d_set_d_op(NULL, NULL);
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_D_SET_D_OP], [
++      AC_MSG_CHECKING([whether d_set_d_op() is available])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([d_set_d_op],
++          [d_set_d_op], [fs/dcache.c], [
++              AC_MSG_RESULT(yes)
++              AC_DEFINE(HAVE_D_SET_D_OP, 1, [d_set_d_op() is available])
++      ], [
++              AC_MSG_RESULT(no)
++      ])
++])
++
+ dnl #
+ dnl # 3.6 API change
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_D_REVALIDATE_NAMEIDATA], [
+-      AC_MSG_CHECKING([whether dops->d_revalidate() takes struct nameidata])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_D_REVALIDATE_NAMEIDATA], [
++      ZFS_LINUX_TEST_SRC([dentry_operations_revalidate], [
+               #include <linux/dcache.h>
+               #include <linux/sched.h>
+@@ -14,11 +108,15 @@ AC_DEFUN([ZFS_AC_KERNEL_D_REVALIDATE_NAMEIDATA], [
+                   dops __attribute__ ((unused)) = {
+                       .d_revalidate   = revalidate,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_D_REVALIDATE_NAMEIDATA], [
++      AC_MSG_CHECKING([whether dops->d_revalidate() takes struct nameidata])
++      ZFS_LINUX_TEST_RESULT([dentry_operations_revalidate], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_D_REVALIDATE_NAMEIDATA, 1,
+-                        [dops->d_revalidate() operation takes nameidata])
++                  [dops->d_revalidate() operation takes nameidata])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+@@ -28,9 +126,8 @@ dnl #
+ dnl # 2.6.30 API change
+ dnl # The 'struct dentry_operations' was constified in the dentry structure.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_CONST_DENTRY_OPERATIONS], [
+-      AC_MSG_CHECKING([whether dentry uses const struct dentry_operations])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_CONST_DENTRY_OPERATIONS], [
++      ZFS_LINUX_TEST_SRC([dentry_operations_const], [
+               #include <linux/dcache.h>
+               const struct dentry_operations test_d_op = {
+@@ -38,32 +135,17 @@ AC_DEFUN([ZFS_AC_KERNEL_CONST_DENTRY_OPERATIONS], [
+               };
+       ],[
+               struct dentry d __attribute__ ((unused));
+-
+               d.d_op = &test_d_op;
+-      ],[
+-              AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_CONST_DENTRY_OPERATIONS, 1,
+-                        [dentry uses const struct dentry_operations])
+-      ],[
+-              AC_MSG_RESULT(no)
+       ])
+ ])
+-dnl #
+-dnl # 2.6.38 API change
+-dnl # Added d_set_d_op() helper function.
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_D_SET_D_OP],
+-      [AC_MSG_CHECKING([whether d_set_d_op() is available])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
+-              #include <linux/dcache.h>
+-      ], [
+-              d_set_d_op(NULL, NULL);
+-      ], [d_set_d_op], [fs/dcache.c], [
++AC_DEFUN([ZFS_AC_KERNEL_CONST_DENTRY_OPERATIONS], [
++      AC_MSG_CHECKING([whether dentry uses const struct dentry_operations])
++      ZFS_LINUX_TEST_RESULT([dentry_operations_const], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_D_SET_D_OP, 1,
+-                        [d_set_d_op() is available])
+-      ], [
++              AC_DEFINE(HAVE_CONST_DENTRY_OPERATIONS, 1,
++                  [dentry uses const struct dentry_operations])
++      ],[
+               AC_MSG_RESULT(no)
+       ])
+ ])
+@@ -72,17 +154,41 @@ dnl #
+ dnl # 2.6.38 API chage
+ dnl # Added sb->s_d_op default dentry_operations member
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_S_D_OP],
+-      [AC_MSG_CHECKING([whether super_block has s_d_op])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_S_D_OP], [
++      ZFS_LINUX_TEST_SRC([super_block_s_d_op], [
+               #include <linux/fs.h>
+       ],[
+               struct super_block sb __attribute__ ((unused));
+               sb.s_d_op = NULL;
+-      ], [
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_S_D_OP], [
++      AC_MSG_CHECKING([whether super_block has s_d_op])
++      ZFS_LINUX_TEST_RESULT([super_block_s_d_op], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_S_D_OP, 1, [struct super_block has s_d_op])
+       ], [
+               AC_MSG_RESULT(no)
+       ])
+ ])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_DENTRY], [
++        ZFS_AC_KERNEL_SRC_D_MAKE_ROOT
++        ZFS_AC_KERNEL_SRC_D_OBTAIN_ALIAS
++        ZFS_AC_KERNEL_SRC_D_PRUNE_ALIASES
++        ZFS_AC_KERNEL_SRC_D_SET_D_OP
++        ZFS_AC_KERNEL_SRC_D_REVALIDATE_NAMEIDATA
++        ZFS_AC_KERNEL_SRC_CONST_DENTRY_OPERATIONS
++        ZFS_AC_KERNEL_SRC_S_D_OP
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_DENTRY], [
++        ZFS_AC_KERNEL_D_MAKE_ROOT
++        ZFS_AC_KERNEL_D_OBTAIN_ALIAS
++        ZFS_AC_KERNEL_D_PRUNE_ALIASES
++        ZFS_AC_KERNEL_D_SET_D_OP
++        ZFS_AC_KERNEL_D_REVALIDATE_NAMEIDATA
++        ZFS_AC_KERNEL_CONST_DENTRY_OPERATIONS
++        ZFS_AC_KERNEL_S_D_OP
++])
+diff --git a/config/kernel-dirty-inode.m4 b/config/kernel-dirty-inode.m4
+index ffd87bb14..dc7667fa4 100644
+--- a/config/kernel-dirty-inode.m4
++++ b/config/kernel-dirty-inode.m4
+@@ -4,9 +4,8 @@ dnl # The sops->dirty_inode() callbacks were updated to take a flags
+ dnl # argument.  This allows the greater control over whether the
+ dnl # filesystem needs to push out a transaction or not.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_DIRTY_INODE_WITH_FLAGS], [
+-      AC_MSG_CHECKING([whether sops->dirty_inode() wants flags])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_DIRTY_INODE], [
++      ZFS_LINUX_TEST_SRC([dirty_inode_with_flags], [
+               #include <linux/fs.h>
+               void dirty_inode(struct inode *a, int b) { return; }
+@@ -15,11 +14,15 @@ AC_DEFUN([ZFS_AC_KERNEL_DIRTY_INODE_WITH_FLAGS], [
+                   sops __attribute__ ((unused)) = {
+                       .dirty_inode = dirty_inode,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_DIRTY_INODE], [
++      AC_MSG_CHECKING([whether sops->dirty_inode() wants flags])
++      ZFS_LINUX_TEST_RESULT([dirty_inode_with_flags], [
+               AC_MSG_RESULT([yes])
+               AC_DEFINE(HAVE_DIRTY_INODE_WITH_FLAGS, 1,
+-                      [sops->dirty_inode() wants flags])
++                  [sops->dirty_inode() wants flags])
+       ],[
+               AC_MSG_RESULT([no])
+       ])
+diff --git a/config/kernel-discard-granularity.m4 b/config/kernel-discard-granularity.m4
+index 2c677c909..c830d9aa9 100644
+--- a/config/kernel-discard-granularity.m4
++++ b/config/kernel-discard-granularity.m4
+@@ -2,18 +2,21 @@ dnl #
+ dnl # 2.6.33 API change
+ dnl # Discard granularity and alignment restrictions may now be set.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_DISCARD_GRANULARITY], [
+-      AC_MSG_CHECKING([whether ql->discard_granularity is available])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_DISCARD_GRANULARITY], [
++      ZFS_LINUX_TEST_SRC([discard_granularity], [
+               #include <linux/blkdev.h>
+       ],[
+               struct queue_limits ql __attribute__ ((unused));
+-
+               ql.discard_granularity = 0;
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_DISCARD_GRANULARITY], [
++      AC_MSG_CHECKING([whether ql->discard_granularity is available])
++      ZFS_LINUX_TEST_RESULT([discard_granularity], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_DISCARD_GRANULARITY, 1,
+-                        [ql->discard_granularity is available])
++                  [ql->discard_granularity is available])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-elevator-change.m4 b/config/kernel-elevator-change.m4
+index eba252579..3aa732040 100644
+--- a/config/kernel-elevator-change.m4
++++ b/config/kernel-elevator-change.m4
+@@ -2,24 +2,25 @@ dnl #
+ dnl # 2.6.36 API, exported elevator_change() symbol
+ dnl # 4.12 API, removed elevator_change() symbol
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_ELEVATOR_CHANGE], [
+-      AC_MSG_CHECKING([whether elevator_change() is available])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_ELEVATOR_CHANGE], [
++      ZFS_LINUX_TEST_SRC([elevator_change], [
+               #include <linux/blkdev.h>
+               #include <linux/elevator.h>
+       ],[
+-              int ret;
+               struct request_queue *q = NULL;
+               char *elevator = NULL;
+-              ret = elevator_change(q, elevator);
+-      ],[
++              int error __attribute__ ((unused)) =
++                  elevator_change(q, elevator);
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_ELEVATOR_CHANGE], [
++      AC_MSG_CHECKING([whether elevator_change() is available])
++      ZFS_LINUX_TEST_RESULT([elevator_change], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_ELEVATOR_CHANGE, 1,
+-                        [elevator_change() is available])
++                  [elevator_change() is available])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
+ ])
+diff --git a/config/kernel-encode-fh-inode.m4 b/config/kernel-encode-fh-inode.m4
+index 287f62a5e..9d4ba5f0f 100644
+--- a/config/kernel-encode-fh-inode.m4
++++ b/config/kernel-encode-fh-inode.m4
+@@ -4,20 +4,23 @@ dnl # torvalds/linux@b0b0382bb4904965a9e9fca77ad87514dfda0d1c changed the
+ dnl # ->encode_fh() callback to pass the child inode and its parents inode
+ dnl # rather than a dentry and a boolean saying whether we want the parent.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_ENCODE_FH_WITH_INODE], [
+-      AC_MSG_CHECKING([whether eops->encode_fh() wants inode])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_ENCODE_FH_WITH_INODE], [
++      ZFS_LINUX_TEST_SRC([export_operations_encode_fh], [
+               #include <linux/exportfs.h>
+               int encode_fh(struct inode *inode, __u32 *fh, int *max_len,
+                             struct inode *parent) { return 0; }
+               static struct export_operations eops __attribute__ ((unused))={
+                       .encode_fh = encode_fh,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_ENCODE_FH_WITH_INODE], [
++      AC_MSG_CHECKING([whether eops->encode_fh() wants inode])
++      ZFS_LINUX_TEST_RESULT([export_operations_encode_fh], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_ENCODE_FH_WITH_INODE, 1,
+-                        [eops->encode_fh() wants child and parent inodes])
++                  [eops->encode_fh() wants child and parent inodes])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-evict-inode.m4 b/config/kernel-evict-inode.m4
+index 683cedb6d..cd91c6669 100644
+--- a/config/kernel-evict-inode.m4
++++ b/config/kernel-evict-inode.m4
+@@ -3,16 +3,19 @@ dnl # 2.6.36 API change
+ dnl # The sops->delete_inode() and sops->clear_inode() callbacks have
+ dnl # replaced by a single sops->evict_inode() callback.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_EVICT_INODE], [
+-      AC_MSG_CHECKING([whether sops->evict_inode() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_EVICT_INODE], [
++      ZFS_LINUX_TEST_SRC([evict_inode], [
+               #include <linux/fs.h>
+               void evict_inode (struct inode * t) { return; }
+               static struct super_operations sops __attribute__ ((unused)) = {
+                       .evict_inode = evict_inode,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_EVICT_INODE], [
++      AC_MSG_CHECKING([whether sops->evict_inode() exists])
++      ZFS_LINUX_TEST_RESULT([evict_inode], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_EVICT_INODE, 1, [sops->evict_inode() exists])
+       ],[
+diff --git a/config/kernel-fallocate-pax.m4 b/config/kernel-fallocate-pax.m4
+deleted file mode 100644
+index e8948be17..000000000
+--- a/config/kernel-fallocate-pax.m4
++++ /dev/null
+@@ -1,19 +0,0 @@
+-dnl #
+-dnl # PaX Linux 2.6.38 - 3.x API
+-dnl #
+-AC_DEFUN([ZFS_AC_PAX_KERNEL_FILE_FALLOCATE], [
+-      AC_MSG_CHECKING([whether fops->fallocate() exists])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/fs.h>
+-      ],[
+-              long (*fallocate) (struct file *, int, loff_t, loff_t) = NULL;
+-              struct file_operations_no_const fops __attribute__ ((unused)) = {
+-                      .fallocate = fallocate,
+-              };
+-      ],[
+-              AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_FILE_FALLOCATE, 1, [fops->fallocate() exists])
+-      ],[
+-              AC_MSG_RESULT(no)
+-      ])
+-])
+diff --git a/config/kernel-fallocate.m4 b/config/kernel-fallocate.m4
+index 550906472..302957a6c 100644
+--- a/config/kernel-fallocate.m4
++++ b/config/kernel-fallocate.m4
+@@ -1,9 +1,11 @@
+ dnl #
+-dnl # Linux 2.6.38 - 3.x API
++dnl # The fallocate callback was moved from the inode_operations
++dnl # structure to the file_operations structure.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_FILE_FALLOCATE], [
+-      AC_MSG_CHECKING([whether fops->fallocate() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_FALLOCATE], [
++
++      dnl # Linux 2.6.38 - 3.x API
++      ZFS_LINUX_TEST_SRC([file_fallocate], [
+               #include <linux/fs.h>
+               long test_fallocate(struct file *file, int mode,
+@@ -13,21 +15,10 @@ AC_DEFUN([ZFS_AC_KERNEL_FILE_FALLOCATE], [
+                   fops __attribute__ ((unused)) = {
+                       .fallocate = test_fallocate,
+               };
+-      ],[
+-      ],[
+-              AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_FILE_FALLOCATE, 1, [fops->fallocate() exists])
+-      ],[
+-              AC_MSG_RESULT(no)
+-      ])
+-])
++      ], [])
+-dnl #
+-dnl # Linux 2.6.x - 2.6.37 API
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_INODE_FALLOCATE], [
+-      AC_MSG_CHECKING([whether iops->fallocate() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++      dnl # Linux 2.6.x - 2.6.37 API
++      ZFS_LINUX_TEST_SRC([inode_fallocate], [
+               #include <linux/fs.h>
+               long test_fallocate(struct inode *inode, int mode,
+@@ -37,20 +28,23 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_FALLOCATE], [
+                   fops __attribute__ ((unused)) = {
+                       .fallocate = test_fallocate,
+               };
++      ], [])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_FALLOCATE], [
++      AC_MSG_CHECKING([whether fops->fallocate() exists])
++      ZFS_LINUX_TEST_RESULT([file_fallocate], [
++              AC_MSG_RESULT(yes)
++              AC_DEFINE(HAVE_FILE_FALLOCATE, 1, [fops->fallocate() exists])
+       ],[
+-      ],[
++              AC_MSG_RESULT(no)
++      ])
++
++      AC_MSG_CHECKING([whether iops->fallocate() exists])
++      ZFS_LINUX_TEST_RESULT([inode_fallocate], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_INODE_FALLOCATE, 1, [fops->fallocate() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+ ])
+-
+-dnl #
+-dnl # The fallocate callback was moved from the inode_operations
+-dnl # structure to the file_operations structure.
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_FALLOCATE], [
+-      ZFS_AC_KERNEL_FILE_FALLOCATE
+-      ZFS_AC_KERNEL_INODE_FALLOCATE
+-])
+diff --git a/config/kernel-file-dentry.m4 b/config/kernel-file-dentry.m4
+index daf742ee1..9cb5869c3 100644
+--- a/config/kernel-file-dentry.m4
++++ b/config/kernel-file-dentry.m4
+@@ -4,14 +4,18 @@ dnl # struct access file->f_path.dentry was replaced by accessor function
+ dnl # since fix torvalds/linux@4bacc9c9234c ("overlayfs: Make f_path always
+ dnl # point to the overlay and f_inode to the underlay").
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_FILE_DENTRY], [
+-      AC_MSG_CHECKING([whether file_dentry() is available])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_FILE_DENTRY], [
++      ZFS_LINUX_TEST_SRC([file_dentry], [
+               #include <linux/fs.h>
+       ],[
+               struct file *f = NULL;
+               file_dentry(f);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_FILE_DENTRY], [
++      AC_MSG_CHECKING([whether file_dentry() is available])
++      ZFS_LINUX_TEST_RESULT([file_dentry], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_FILE_DENTRY, 1, [file_dentry() is available])
+       ],[
+diff --git a/config/kernel-file-inode.m4 b/config/kernel-file-inode.m4
+index 300188fa3..00a362165 100644
+--- a/config/kernel-file-inode.m4
++++ b/config/kernel-file-inode.m4
+@@ -3,14 +3,18 @@ dnl # 3.19 API change
+ dnl # struct access f->f_dentry->d_inode was replaced by accessor function
+ dnl # file_inode(f)
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_FILE_INODE], [
+-      AC_MSG_CHECKING([whether file_inode() is available])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_FILE_INODE], [
++      ZFS_LINUX_TEST_SRC([file_inode], [
+               #include <linux/fs.h>
+       ],[
+               struct file *f = NULL;
+               file_inode(f);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_FILE_INODE], [
++      AC_MSG_CHECKING([whether file_inode() is available])
++      ZFS_LINUX_TEST_RESULT([file_inode], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_FILE_INODE, 1, [file_inode() is available])
+       ],[
+diff --git a/config/kernel-fmode-t.m4 b/config/kernel-fmode-t.m4
+index 4a23c391d..bc0001b9e 100644
+--- a/config/kernel-fmode-t.m4
++++ b/config/kernel-fmode-t.m4
+@@ -2,16 +2,19 @@ dnl #
+ dnl # 2.6.28 API change,
+ dnl # check if fmode_t typedef is defined
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_TYPE_FMODE_T],
+-      [AC_MSG_CHECKING([whether kernel defines fmode_t])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_FMODE_T], [
++      ZFS_LINUX_TEST_SRC([type_fmode_t], [
+               #include <linux/types.h>
+       ],[
+               fmode_t *ptr __attribute__ ((unused));
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_FMODE_T], [
++      AC_MSG_CHECKING([whether kernel defines fmode_t])
++      ZFS_LINUX_TEST_RESULT([type_fmode_t], [
+               AC_MSG_RESULT([yes])
+-              AC_DEFINE(HAVE_FMODE_T, 1,
+-                        [kernel defines fmode_t])
++              AC_DEFINE(HAVE_FMODE_T, 1, [kernel defines fmode_t])
+       ],[
+               AC_MSG_RESULT([no])
+       ])
+diff --git a/config/kernel-follow-down-one.m4 b/config/kernel-follow-down-one.m4
+index 63fa779d8..94e4aeb8d 100644
+--- a/config/kernel-follow-down-one.m4
++++ b/config/kernel-follow-down-one.m4
+@@ -3,14 +3,18 @@ dnl # 2.6.38 API change
+ dnl # follow_down() renamed follow_down_one().  The original follow_down()
+ dnl # symbol still exists but will traverse down all the layers.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_FOLLOW_DOWN_ONE], [
+-      AC_MSG_CHECKING([whether follow_down_one() is available])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_FOLLOW_DOWN_ONE], [
++      ZFS_LINUX_TEST_SRC([follow_down_one], [
+               #include <linux/namei.h>
+       ],[
+               struct path *p = NULL;
+               follow_down_one(p);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_FOLLOW_DOWN_ONE], [
++      AC_MSG_CHECKING([whether follow_down_one() is available])
++      ZFS_LINUX_TEST_RESULT([follow_down_one], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_FOLLOW_DOWN_ONE, 1,
+                   [follow_down_one() is available])
+diff --git a/config/kernel-fpu.m4 b/config/kernel-fpu.m4
+index 0e622e859..a2c47d65a 100644
+--- a/config/kernel-fpu.m4
++++ b/config/kernel-fpu.m4
+@@ -18,8 +18,11 @@ dnl #
+ dnl # Pre-4.2:        Use kernel_fpu_{begin,end}()
+ dnl #         HAVE_KERNEL_FPU & KERNEL_EXPORTS_X86_FPU
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_FPU], [
+-      AC_MSG_CHECKING([which kernel_fpu header to use])
++dnl # N.B. The header check is performed before all other checks since it
++dnl # depends on HAVE_KERNEL_FPU_API_HEADER being set in confdefs.h.
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_FPU_HEADER], [
++      AC_MSG_CHECKING([whether fpu headers are available])
+       ZFS_LINUX_TRY_COMPILE([
+               #include <linux/module.h>
+               #include <asm/fpu/api.h>
+@@ -31,66 +34,88 @@ AC_DEFUN([ZFS_AC_KERNEL_FPU], [
+       ],[
+               AC_MSG_RESULT(i387.h & xcr.h)
+       ])
++])
+-      AC_MSG_CHECKING([which kernel_fpu function to use])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
+-              #include <linux/module.h>
++AC_DEFUN([ZFS_AC_KERNEL_SRC_FPU], [
++      ZFS_LINUX_TEST_SRC([kernel_fpu], [
+               #ifdef HAVE_KERNEL_FPU_API_HEADER
+               #include <asm/fpu/api.h>
+               #else
+               #include <asm/i387.h>
+               #include <asm/xcr.h>
+               #endif
+-              MODULE_LICENSE("$ZFS_META_LICENSE");
+-      ],[
++      ], [
+               kernel_fpu_begin();
+               kernel_fpu_end();
+-      ], [kernel_fpu_begin], [arch/x86/kernel/fpu/core.c], [
++      ], [], [$ZFS_META_LICENSE])
++
++      ZFS_LINUX_TEST_SRC([__kernel_fpu], [
++              #ifdef HAVE_KERNEL_FPU_API_HEADER
++              #include <asm/fpu/api.h>
++              #else
++              #include <asm/i387.h>
++              #include <asm/xcr.h>
++              #endif
++      ], [
++              __kernel_fpu_begin();
++              __kernel_fpu_end();
++      ], [], [$ZFS_META_LICENSE])
++
++      ZFS_LINUX_TEST_SRC([fpu_initialized], [
++              #include <linux/module.h>
++              #include <linux/sched.h>
++      ],[
++              struct fpu *fpu = &current->thread.fpu;
++              if (fpu->initialized) { return (0); };
++      ])
++
++      ZFS_LINUX_TEST_SRC([tif_need_fpu_load], [
++              #include <linux/module.h>
++              #include <asm/thread_info.h>
++
++              #if !defined(TIF_NEED_FPU_LOAD)
++              #error "TIF_NEED_FPU_LOAD undefined"
++              #endif
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_FPU], [
++      dnl #
++      dnl # Legacy kernel
++      dnl #
++      AC_MSG_CHECKING([whether kernel fpu is available])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([kernel_fpu_license],
++          [kernel_fpu_begin], [arch/x86/kernel/fpu/core.c], [
+               AC_MSG_RESULT(kernel_fpu_*)
+               AC_DEFINE(HAVE_KERNEL_FPU, 1,
+                   [kernel has kernel_fpu_* functions])
+               AC_DEFINE(KERNEL_EXPORTS_X86_FPU, 1,
+                   [kernel exports FPU functions])
+       ],[
+-              ZFS_LINUX_TRY_COMPILE_SYMBOL([
+-                      #include <linux/module.h>
+-                      #ifdef HAVE_KERNEL_FPU_API_HEADER
+-                      #include <asm/fpu/api.h>
+-                      #else
+-                      #include <asm/i387.h>
+-                      #include <asm/xcr.h>
+-                      #endif
+-                      MODULE_LICENSE("$ZFS_META_LICENSE");
+-              ],[
+-                      __kernel_fpu_begin();
+-                      __kernel_fpu_end();
+-              ], [__kernel_fpu_begin], [arch/x86/kernel/fpu/core.c arch/x86/kernel/i387.c], [
++              dnl #
++              dnl # Linux 4.2 kernel
++              dnl #
++              ZFS_LINUX_TEST_RESULT_SYMBOL([__kernel_fpu_license],
++                  [__kernel_fpu_begin],
++                  [arch/x86/kernel/fpu/core.c arch/x86/kernel/i387.c], [
+                       AC_MSG_RESULT(__kernel_fpu_*)
+                       AC_DEFINE(HAVE_UNDERSCORE_KERNEL_FPU, 1,
+                           [kernel has __kernel_fpu_* functions])
+                       AC_DEFINE(KERNEL_EXPORTS_X86_FPU, 1,
+                           [kernel exports FPU functions])
+               ],[
+-                      ZFS_LINUX_TRY_COMPILE([
+-                              #include <linux/module.h>
+-                              #include <linux/sched.h>
+-                      ],[
+-                              struct fpu *fpu = &current->thread.fpu;
+-                              if (fpu->initialized) { return (0); };
+-                      ],[
++                      dnl #
++                      dnl # Linux 5.0 kernel
++                      dnl #
++                      ZFS_LINUX_TEST_RESULT([fpu_initialized], [
+                               AC_MSG_RESULT(fpu.initialized)
+                               AC_DEFINE(HAVE_KERNEL_FPU_INITIALIZED, 1,
+                                   [kernel fpu.initialized exists])
+                       ],[
+-                              ZFS_LINUX_TRY_COMPILE([
+-                                      #include <linux/module.h>
+-                                      #include <asm/thread_info.h>
+-
+-                                      #if !defined(TIF_NEED_FPU_LOAD)
+-                                      #error "TIF_NEED_FPU_LOAD undefined"
+-                                      #endif
+-                              ],[
+-                              ],[
++                              dnl #
++                              dnl # Linux 5.2 kernel
++                              dnl #
++                              ZFS_LINUX_TEST_RESULT([tif_need_fpu_load], [
+                                       AC_MSG_RESULT(TIF_NEED_FPU_LOAD)
+                                       AC_DEFINE(
+                                           HAVE_KERNEL_TIF_NEED_FPU_LOAD, 1,
+diff --git a/config/kernel-fst-mount.m4 b/config/kernel-fst-mount.m4
+index a8ac50bdd..cec1ed4d6 100644
+--- a/config/kernel-fst-mount.m4
++++ b/config/kernel-fst-mount.m4
+@@ -3,9 +3,8 @@ dnl # 2.6.38 API change
+ dnl # The .get_sb callback has been replaced by a .mount callback
+ dnl # in the file_system_type structure.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_FST_MOUNT], [
+-        AC_MSG_CHECKING([whether fst->mount() exists])
+-        ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_FST_MOUNT], [
++        ZFS_LINUX_TEST_SRC([file_system_type_mount], [
+                 #include <linux/fs.h>
+                 static struct dentry *
+@@ -18,8 +17,12 @@ AC_DEFUN([ZFS_AC_KERNEL_FST_MOUNT], [
+                 static struct file_system_type fst __attribute__ ((unused)) = {
+                         .mount = mount,
+                 };
+-        ],[
+-        ],[
++        ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_FST_MOUNT], [
++        AC_MSG_CHECKING([whether fst->mount() exists])
++        ZFS_LINUX_TEST_RESULT([file_system_type_mount], [
+                 AC_MSG_RESULT(yes)
+                 AC_DEFINE(HAVE_FST_MOUNT, 1, [fst->mount() exists])
+         ],[
+diff --git a/config/kernel-fsync.m4 b/config/kernel-fsync.m4
+index e1f2d68b9..0494e31ad 100644
+--- a/config/kernel-fsync.m4
++++ b/config/kernel-fsync.m4
+@@ -1,8 +1,8 @@
+ dnl #
+-dnl # Linux 2.6.x - 2.6.34 API
++dnl # Check file_operations->fsync interface.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_FSYNC_WITH_DENTRY], [
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_FSYNC], [
++      ZFS_LINUX_TEST_SRC([fsync_with_dentry], [
+               #include <linux/fs.h>
+               int test_fsync(struct file *f, struct dentry *dentry, int x)
+@@ -12,20 +12,9 @@ AC_DEFUN([ZFS_AC_KERNEL_FSYNC_WITH_DENTRY], [
+                   fops __attribute__ ((unused)) = {
+                       .fsync = test_fsync,
+               };
+-      ],[
+-      ],[
+-              AC_MSG_RESULT([dentry])
+-              AC_DEFINE(HAVE_FSYNC_WITH_DENTRY, 1,
+-                      [fops->fsync() with dentry])
+-      ],[
+-      ])
+-])
++      ],[])
+-dnl #
+-dnl # Linux 2.6.35 - Linux 3.0 API
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_FSYNC_WITHOUT_DENTRY], [
+-      ZFS_LINUX_TRY_COMPILE([
++      ZFS_LINUX_TEST_SRC([fsync_without_dentry], [
+               #include <linux/fs.h>
+               int test_fsync(struct file *f, int x) { return 0; }
+@@ -34,20 +23,9 @@ AC_DEFUN([ZFS_AC_KERNEL_FSYNC_WITHOUT_DENTRY], [
+                   fops __attribute__ ((unused)) = {
+                       .fsync = test_fsync,
+               };
+-      ],[
+-      ],[
+-              AC_MSG_RESULT([no dentry])
+-              AC_DEFINE(HAVE_FSYNC_WITHOUT_DENTRY, 1,
+-                      [fops->fsync() without dentry])
+-      ],[
+-      ])
+-])
++      ],[])
+-dnl #
+-dnl # Linux 3.1 - 3.x API
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_FSYNC_RANGE], [
+-      ZFS_LINUX_TRY_COMPILE([
++      ZFS_LINUX_TEST_SRC([fsync_range], [
+               #include <linux/fs.h>
+               int test_fsync(struct file *f, loff_t a, loff_t b, int c)
+@@ -57,18 +35,43 @@ AC_DEFUN([ZFS_AC_KERNEL_FSYNC_RANGE], [
+                   fops __attribute__ ((unused)) = {
+                       .fsync = test_fsync,
+               };
+-      ],[
+-      ],[
+-              AC_MSG_RESULT([range])
+-              AC_DEFINE(HAVE_FSYNC_RANGE, 1,
+-                      [fops->fsync() with range])
+-      ],[
+-      ])
++      ],[])
+ ])
+ AC_DEFUN([ZFS_AC_KERNEL_FSYNC], [
+-      AC_MSG_CHECKING([whether fops->fsync() wants])
+-      ZFS_AC_KERNEL_FSYNC_WITH_DENTRY
+-      ZFS_AC_KERNEL_FSYNC_WITHOUT_DENTRY
+-      ZFS_AC_KERNEL_FSYNC_RANGE
++      dnl #
++      dnl # Linux 2.6.x - 2.6.34 API
++      dnl #
++      AC_MSG_CHECKING([whether fops->fsync() wants dentry])
++      ZFS_LINUX_TEST_RESULT([fsync_with_dentry], [
++              AC_MSG_RESULT([yes])
++              AC_DEFINE(HAVE_FSYNC_WITH_DENTRY, 1,
++                  [fops->fsync() with dentry])
++      ],[
++              AC_MSG_RESULT([no])
++
++              dnl #
++              dnl # Linux 2.6.35 - Linux 3.0 API
++              dnl #
++              AC_MSG_CHECKING([whether fops->fsync() wants no dentry])
++              ZFS_LINUX_TEST_RESULT([fsync_without_dentry], [
++                      AC_MSG_RESULT([yes])
++                      AC_DEFINE(HAVE_FSYNC_WITHOUT_DENTRY, 1,
++                          [fops->fsync() without dentry])
++              ],[
++                      AC_MSG_RESULT([no])
++
++                      dnl #
++                      dnl # Linux 3.1 - 3.x API
++                      dnl #
++                      AC_MSG_CHECKING([whether fops->fsync() wants range])
++                      ZFS_LINUX_TEST_RESULT([fsync_range], [
++                              AC_MSG_RESULT([range])
++                              AC_DEFINE(HAVE_FSYNC_RANGE, 1,
++                                  [fops->fsync() with range])
++                      ],[
++                              ZFS_LINUX_TEST_ERROR([fops->fsync])
++                      ])
++              ])
++      ])
+ ])
+diff --git a/config/kernel-generic_io_acct.m4 b/config/kernel-generic_io_acct.m4
+index 0aa762162..423b3e5a3 100644
+--- a/config/kernel-generic_io_acct.m4
++++ b/config/kernel-generic_io_acct.m4
+@@ -1,12 +1,8 @@
+ dnl #
+-dnl # 3.19 API addition
++dnl # Check for generic io accounting interface.
+ dnl #
+-dnl # torvalds/linux@394ffa503bc40e32d7f54a9b817264e81ce131b4 allows us to
+-dnl # increment iostat counters without generic_make_request().
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_GENERIC_IO_ACCT_3ARG], [
+-      AC_MSG_CHECKING([whether 3 arg generic IO accounting symbols are available])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_IO_ACCT], [
++      ZFS_LINUX_TEST_SRC([generic_acct_3args], [
+               #include <linux/bio.h>
+               void (*generic_start_io_acct_f)(int, unsigned long,
+@@ -16,24 +12,9 @@ AC_DEFUN([ZFS_AC_KERNEL_GENERIC_IO_ACCT_3ARG], [
+       ], [
+               generic_start_io_acct(0, 0, NULL);
+               generic_end_io_acct(0, NULL, 0);
+-      ], [generic_start_io_acct], [block/bio.c], [
+-              AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_GENERIC_IO_ACCT_3ARG, 1,
+-                  [generic_start_io_acct()/generic_end_io_acct() available])
+-      ], [
+-              AC_MSG_RESULT(no)
+       ])
+-])
+-dnl #
+-dnl # Linux 4.14 API,
+-dnl #
+-dnl # generic_start_io_acct/generic_end_io_acct now require request_queue to be
+-dnl # provided. No functional changes, but preparation for inflight accounting 
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_GENERIC_IO_ACCT_4ARG], [
+-      AC_MSG_CHECKING([whether 4 arg generic IO accounting symbols are available])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
++      ZFS_LINUX_TEST_SRC([generic_acct_4args], [
+               #include <linux/bio.h>
+               void (*generic_start_io_acct_f)(struct request_queue *, int,
+@@ -43,11 +24,41 @@ AC_DEFUN([ZFS_AC_KERNEL_GENERIC_IO_ACCT_4ARG], [
+       ], [
+               generic_start_io_acct(NULL, 0, 0, NULL);
+               generic_end_io_acct(NULL, 0, NULL, 0);
+-      ], [generic_start_io_acct], [block/bio.c], [
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_GENERIC_IO_ACCT], [
++      dnl #
++      dnl # 3.19 API addition
++      dnl #
++      dnl # torvalds/linux@394ffa50 allows us to increment iostat
++      dnl # counters without generic_make_request().
++      dnl #
++      AC_MSG_CHECKING([whether generic IO accounting wants 3 args])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([generic_acct_3args],
++          [generic_start_io_acct], [block/bio.c], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_GENERIC_IO_ACCT_4ARG, 1,
+-                  [generic_start_io_acct()/generic_end_io_acct() 4 arg available])
++              AC_DEFINE(HAVE_GENERIC_IO_ACCT_3ARG, 1,
++                  [generic_start_io_acct()/generic_end_io_acct() available])
+       ], [
+               AC_MSG_RESULT(no)
++
++              dnl #
++              dnl # Linux 4.14 API,
++              dnl #
++              dnl # generic_start_io_acct/generic_end_io_acct now require
++              dnl # request_queue to be provided. No functional changes,
++              dnl # but preparation for inflight accounting.
++              dnl #
++              AC_MSG_CHECKING([whether generic IO accounting wants 4 args])
++              ZFS_LINUX_TEST_RESULT_SYMBOL([generic_acct_4args],
++                  [generic_start_io_acct], [block/bio.c], [
++                      AC_MSG_RESULT(yes)
++                      AC_DEFINE(HAVE_GENERIC_IO_ACCT_4ARG, 1,
++                          [generic_start_io_acct()/generic_end_io_acct() ]
++                          [4 arg available])
++              ], [
++                      AC_MSG_RESULT(no)
++              ])
+       ])
+ ])
+diff --git a/config/kernel-generic_readlink.m4 b/config/kernel-generic_readlink.m4
+index 914431de4..a7a33b408 100644
+--- a/config/kernel-generic_readlink.m4
++++ b/config/kernel-generic_readlink.m4
+@@ -4,18 +4,21 @@ dnl #
+ dnl # NULL inode_operations.readlink implies generic_readlink(), which
+ dnl # has been made static.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_GENERIC_READLINK_GLOBAL], [
+-      AC_MSG_CHECKING([whether generic_readlink is global])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_READLINK_GLOBAL], [
++      ZFS_LINUX_TEST_SRC([generic_readlink_global], [
+               #include <linux/fs.h>
+       ],[
+               int i __attribute__ ((unused));
+-
+               i = generic_readlink(NULL, NULL, 0);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_GENERIC_READLINK_GLOBAL], [
++      AC_MSG_CHECKING([whether generic_readlink is global])
++      ZFS_LINUX_TEST_RESULT([generic_readlink_global], [
+               AC_MSG_RESULT([yes])
+               AC_DEFINE(HAVE_GENERIC_READLINK, 1,
+-                        [generic_readlink is global])
++                  [generic_readlink is global])
+       ],[
+               AC_MSG_RESULT([no])
+       ])
+diff --git a/config/kernel-get-disk-and-module.m4 b/config/kernel-get-disk-and-module.m4
+index 2a51a5af7..51cf7743c 100644
+--- a/config/kernel-get-disk-and-module.m4
++++ b/config/kernel-get-disk-and-module.m4
+@@ -2,14 +2,19 @@ dnl #
+ dnl # 4.16 API change
+ dnl # Verify if get_disk_and_module() symbol is available.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_GET_DISK_AND_MODULE],
+-      [AC_MSG_CHECKING([whether get_disk_and_module() is available])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_GET_DISK_AND_MODULE], [
++      ZFS_LINUX_TEST_SRC([get_disk_and_module], [
+               #include <linux/genhd.h>
+       ], [
+               struct gendisk *disk = NULL;
+               (void) get_disk_and_module(disk);
+-      ], [get_disk_and_module], [block/genhd.c], [
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_GET_DISK_AND_MODULE], [
++      AC_MSG_CHECKING([whether get_disk_and_module() is available])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([get_disk_and_module],
++          [get_disk_and_module], [block/genhd.c], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_GET_DISK_AND_MODULE,
+                   1, [get_disk_and_module() is available])
+diff --git a/config/kernel-get-disk-ro.m4 b/config/kernel-get-disk-ro.m4
+index 13ed81217..1e2abb475 100644
+--- a/config/kernel-get-disk-ro.m4
++++ b/config/kernel-get-disk-ro.m4
+@@ -1,21 +1,21 @@
+ dnl #
+ dnl # 2.6.x API change
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_GET_DISK_RO], [
+-      AC_MSG_CHECKING([whether get_disk_ro() is available])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_GET_DISK_RO], [
++      ZFS_LINUX_TEST_SRC([get_disk_ro], [
+               #include <linux/blkdev.h>
+       ],[
+               struct gendisk *disk = NULL;
+               (void) get_disk_ro(disk);
+-      ],[
++      ], [$NO_UNUSED_BUT_SET_VARIABLE])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_GET_DISK_RO], [
++      AC_MSG_CHECKING([whether get_disk_ro() is available])
++      ZFS_LINUX_TEST_RESULT([get_disk_ro], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_GET_DISK_RO, 1,
+-                        [blk_disk_ro() is available])
++              AC_DEFINE(HAVE_GET_DISK_RO, 1, [blk_disk_ro() is available])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
+ ])
+diff --git a/config/kernel-get-link.m4 b/config/kernel-get-link.m4
+index 3cda08c1b..e4f478e37 100644
+--- a/config/kernel-get-link.m4
++++ b/config/kernel-get-link.m4
+@@ -1,13 +1,29 @@
+ dnl #
+ dnl # Supported get_link() interfaces checked newest to oldest.
++dnl # Note this interface used to be named follow_link.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_FOLLOW_LINK], [
+-      dnl #
+-      dnl # 4.2 API change
+-      dnl # - This kernel retired the nameidata structure.
+-      dnl #
+-      AC_MSG_CHECKING([whether iops->follow_link() passes cookie])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_GET_LINK], [
++      ZFS_LINUX_TEST_SRC([inode_operations_get_link], [
++              #include <linux/fs.h>
++              const char *get_link(struct dentry *de, struct inode *ip,
++                  struct delayed_call *done) { return "symlink"; }
++              static struct inode_operations
++                   iops __attribute__ ((unused)) = {
++                      .get_link = get_link,
++              };
++      ],[])
++
++      ZFS_LINUX_TEST_SRC([inode_operations_get_link_cookie], [
++              #include <linux/fs.h>
++              const char *get_link(struct dentry *de, struct
++                  inode *ip, void **cookie) { return "symlink"; }
++              static struct inode_operations
++                   iops __attribute__ ((unused)) = {
++                      .get_link = get_link,
++              };
++      ],[])
++
++      ZFS_LINUX_TEST_SRC([inode_operations_follow_link], [
+               #include <linux/fs.h>
+               const char *follow_link(struct dentry *de,
+                   void **cookie) { return "symlink"; }
+@@ -15,35 +31,17 @@ AC_DEFUN([ZFS_AC_KERNEL_FOLLOW_LINK], [
+                   iops __attribute__ ((unused)) = {
+                       .follow_link = follow_link,
+               };
+-      ],[
+-      ],[
+-              AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_FOLLOW_LINK_COOKIE, 1,
+-                  [iops->follow_link() cookie])
+-      ],[
+-              dnl #
+-              dnl # 2.6.32 API
+-              dnl #
+-              AC_MSG_RESULT(no)
+-              AC_MSG_CHECKING(
+-                 [whether iops->follow_link() passes nameidata])
+-              ZFS_LINUX_TRY_COMPILE([
++      ],[])
++
++      ZFS_LINUX_TEST_SRC([inode_operations_follow_link_nameidata], [
+               #include <linux/fs.h>
+-                      void *follow_link(struct dentry *de, struct
+-                          nameidata *nd) { return (void *)NULL; }
+-                      static struct inode_operations
+-                          iops __attribute__ ((unused)) = {
+-                              .follow_link = follow_link,
+-                      };
+-              ],[
+-              ],[
+-                      AC_MSG_RESULT(yes)
+-                      AC_DEFINE(HAVE_FOLLOW_LINK_NAMEIDATA, 1,
+-                                [iops->follow_link() nameidata])
+-              ],[
+-                      AC_MSG_ERROR(no; please file a bug report)
+-              ])
+-      ])
++              void *follow_link(struct dentry *de, struct
++                  nameidata *nd) { return (void *)NULL; }
++              static struct inode_operations
++                  iops __attribute__ ((unused)) = {
++                      .follow_link = follow_link,
++              };
++      ],[])
+ ])
+ AC_DEFUN([ZFS_AC_KERNEL_GET_LINK], [
+@@ -53,20 +51,12 @@ AC_DEFUN([ZFS_AC_KERNEL_GET_LINK], [
+       dnl # used it to retire the put_link() interface.
+       dnl #
+       AC_MSG_CHECKING([whether iops->get_link() passes delayed])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/fs.h>
+-              const char *get_link(struct dentry *de, struct inode *ip,
+-                  struct delayed_call *done) { return "symlink"; }
+-              static struct inode_operations
+-                   iops __attribute__ ((unused)) = {
+-                      .get_link = get_link,
+-              };
+-      ],[
+-      ],[
++      ZFS_LINUX_TEST_RESULT([inode_operations_get_link], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_GET_LINK_DELAYED, 1,
+-                  [iops->get_link() delayed])
++              AC_DEFINE(HAVE_GET_LINK_DELAYED, 1, [iops->get_link() delayed])
+       ],[
++              AC_MSG_RESULT(no)
++
+               dnl #
+               dnl # 4.5 API change
+               dnl # The follow_link() interface has been replaced by
+@@ -74,27 +64,41 @@ AC_DEFUN([ZFS_AC_KERNEL_GET_LINK], [
+               dnl # - An inode is passed as a separate argument
+               dnl # - When called in RCU mode a NULL dentry is passed.
+               dnl #
+-              AC_MSG_RESULT(no)
+               AC_MSG_CHECKING([whether iops->get_link() passes cookie])
+-              ZFS_LINUX_TRY_COMPILE([
+-                      #include <linux/fs.h>
+-                      const char *get_link(struct dentry *de, struct
+-                          inode *ip, void **cookie) { return "symlink"; }
+-                      static struct inode_operations
+-                           iops __attribute__ ((unused)) = {
+-                              .get_link = get_link,
+-                      };
+-              ],[
+-              ],[
++              ZFS_LINUX_TEST_RESULT([inode_operations_get_link_cookie], [
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_GET_LINK_COOKIE, 1,
+                           [iops->get_link() cookie])
+               ],[
++                      AC_MSG_RESULT(no)
++
+                       dnl #
+-                      dnl # Check for the follow_link APIs.
++                      dnl # 4.2 API change
++                      dnl # This kernel retired the nameidata structure.
+                       dnl #
+-                      AC_MSG_RESULT(no)
+-                      ZFS_AC_KERNEL_FOLLOW_LINK
++                      AC_MSG_CHECKING(
++                          [whether iops->follow_link() passes cookie])
++                      ZFS_LINUX_TEST_RESULT([inode_operations_follow_link], [
++                              AC_MSG_RESULT(yes)
++                              AC_DEFINE(HAVE_FOLLOW_LINK_COOKIE, 1,
++                                  [iops->follow_link() cookie])
++                      ],[
++                              AC_MSG_RESULT(no)
++
++                              dnl #
++                              dnl # 2.6.32 API
++                              dnl #
++                              AC_MSG_CHECKING(
++                              [whether iops->follow_link() passes nameidata])
++                              ZFS_LINUX_TEST_RESULT(
++                                  [inode_operations_follow_link_nameidata],[
++                                      AC_MSG_RESULT(yes)
++                                      AC_DEFINE(HAVE_FOLLOW_LINK_NAMEIDATA, 1,
++                                          [iops->follow_link() nameidata])
++                              ],[
++                                      ZFS_LINUX_TEST_ERROR([get_link])
++                              ])
++                      ])
+               ])
+       ])
+ ])
+diff --git a/config/kernel-global_page_state.m4 b/config/kernel-global_page_state.m4
+index f4a40011f..a0cb9e2c8 100644
+--- a/config/kernel-global_page_state.m4
++++ b/config/kernel-global_page_state.m4
+@@ -4,16 +4,21 @@ dnl #
+ dnl # 75ef71840539 mm, vmstat: add infrastructure for per-node vmstats
+ dnl # 599d0c954f91 mm, vmscan: move LRU lists to node
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_NODE_PAGE_STATE], [
+-      AC_MSG_CHECKING([whether global_node_page_state() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_GLOBAL_NODE_PAGE_STATE], [
++      ZFS_LINUX_TEST_SRC([global_node_page_state], [
+               #include <linux/mm.h>
+               #include <linux/vmstat.h>
+       ],[
+               (void) global_node_page_state(0);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_NODE_PAGE_STATE], [
++      AC_MSG_CHECKING([whether global_node_page_state() exists])
++      ZFS_LINUX_TEST_RESULT([global_node_page_state], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(ZFS_GLOBAL_NODE_PAGE_STATE, 1, [global_node_page_state() exists])
++              AC_DEFINE(ZFS_GLOBAL_NODE_PAGE_STATE, 1,
++                  [global_node_page_state() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+@@ -24,16 +29,21 @@ dnl # 4.14 API change
+ dnl #
+ dnl # c41f012ade0b mm: rename global_page_state to global_zone_page_state
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE], [
+-      AC_MSG_CHECKING([whether global_zone_page_state() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_GLOBAL_ZONE_PAGE_STATE], [
++      ZFS_LINUX_TEST_SRC([global_zone_page_state], [
+               #include <linux/mm.h>
+               #include <linux/vmstat.h>
+       ],[
+               (void) global_zone_page_state(0);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE], [
++      AC_MSG_CHECKING([whether global_zone_page_state() exists])
++      ZFS_LINUX_TEST_RESULT([global_zone_page_state], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(ZFS_GLOBAL_ZONE_PAGE_STATE, 1, [global_zone_page_state() exists])
++              AC_DEFINE(ZFS_GLOBAL_ZONE_PAGE_STATE, 1,
++                  [global_zone_page_state() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+@@ -44,9 +54,11 @@ dnl # Create a define and autoconf variable for an enum member
+ dnl #
+ AC_DEFUN([ZFS_AC_KERNEL_ENUM_MEMBER], [
+       AC_MSG_CHECKING([whether enum $2 contains $1])
+-      AS_IF([AC_TRY_COMMAND("${srcdir}/scripts/enum-extract.pl" "$2" "$3" | egrep -qx $1)],[
++      AS_IF([AC_TRY_COMMAND(
++          "${srcdir}/scripts/enum-extract.pl" "$2" "$3" | egrep -qx $1)],[
+               AC_MSG_RESULT([yes])
+-              AC_DEFINE(m4_join([_], [ZFS_ENUM], m4_toupper($2), $1), 1, [enum $2 contains $1])
++              AC_DEFINE(m4_join([_], [ZFS_ENUM], m4_toupper($2), $1), 1,
++                  [enum $2 contains $1])
+               m4_join([_], [ZFS_ENUM], m4_toupper($2), $1)=1
+       ],[
+               AC_MSG_RESULT([no])
+@@ -59,8 +71,7 @@ dnl #
+ AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_ERROR],[
+       AC_MSG_RESULT(no)
+       AC_MSG_RESULT([$1 in either node_stat_item or zone_stat_item: $2])
+-      AC_MSG_RESULT([configure needs updating, see: config/kernel-global_page_state.m4])
+-      AC_MSG_FAILURE([SHUT 'ER DOWN CLANCY, SHE'S PUMPIN' MUD!])
++      ZFS_LINUX_TEST_ERROR([global page state])
+ ])
+ AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_CHECK], [
+@@ -75,10 +86,10 @@ AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_CHECK], [
+ ])
+ dnl #
+-dnl # Ensure the config tests are finding one and only one of each enum of interest
++dnl # Ensure the config tests are finding one and only one of each enum.
+ dnl #
+ AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE_SANITY], [
+-      AC_MSG_CHECKING([global_page_state enums are sane])
++      AC_MSG_CHECKING([whether global_page_state enums are sane])
+       ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_CHECK([NR_FILE_PAGES])
+       ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_CHECK([NR_INACTIVE_ANON])
+@@ -88,6 +99,11 @@ AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE_SANITY], [
+       AC_MSG_RESULT(yes)
+ ])
++AC_DEFUN([ZFS_AC_KERNEL_SRC_GLOBAL_PAGE_STATE], [
++      ZFS_AC_KERNEL_SRC_GLOBAL_NODE_PAGE_STATE
++      ZFS_AC_KERNEL_SRC_GLOBAL_ZONE_PAGE_STATE
++])
++
+ dnl #
+ dnl # enum members in which we're interested
+ dnl #
+@@ -95,15 +111,23 @@ AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_PAGE_STATE], [
+       ZFS_AC_KERNEL_GLOBAL_NODE_PAGE_STATE
+       ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE
+-      ZFS_AC_KERNEL_ENUM_MEMBER([NR_FILE_PAGES],              [node_stat_item], [$LINUX/include/linux/mmzone.h])
+-      ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_ANON],           [node_stat_item], [$LINUX/include/linux/mmzone.h])
+-      ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_FILE],           [node_stat_item], [$LINUX/include/linux/mmzone.h])
+-      ZFS_AC_KERNEL_ENUM_MEMBER([NR_SLAB_RECLAIMABLE],        [node_stat_item], [$LINUX/include/linux/mmzone.h])
++      ZFS_AC_KERNEL_ENUM_MEMBER([NR_FILE_PAGES],
++          [node_stat_item], [$LINUX/include/linux/mmzone.h])
++      ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_ANON],
++          [node_stat_item], [$LINUX/include/linux/mmzone.h])
++      ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_FILE],
++          [node_stat_item], [$LINUX/include/linux/mmzone.h])
++      ZFS_AC_KERNEL_ENUM_MEMBER([NR_SLAB_RECLAIMABLE],
++          [node_stat_item], [$LINUX/include/linux/mmzone.h])
+-      ZFS_AC_KERNEL_ENUM_MEMBER([NR_FILE_PAGES],              [zone_stat_item], [$LINUX/include/linux/mmzone.h])
+-      ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_ANON],           [zone_stat_item], [$LINUX/include/linux/mmzone.h])
+-      ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_FILE],           [zone_stat_item], [$LINUX/include/linux/mmzone.h])
+-      ZFS_AC_KERNEL_ENUM_MEMBER([NR_SLAB_RECLAIMABLE],        [zone_stat_item], [$LINUX/include/linux/mmzone.h])
++      ZFS_AC_KERNEL_ENUM_MEMBER([NR_FILE_PAGES],
++          [zone_stat_item], [$LINUX/include/linux/mmzone.h])
++      ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_ANON],
++          [zone_stat_item], [$LINUX/include/linux/mmzone.h])
++      ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_FILE],
++          [zone_stat_item], [$LINUX/include/linux/mmzone.h])
++      ZFS_AC_KERNEL_ENUM_MEMBER([NR_SLAB_RECLAIMABLE],
++          [zone_stat_item], [$LINUX/include/linux/mmzone.h])
+       ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE_SANITY
+ ])
+diff --git a/config/kernel-group-info.m4 b/config/kernel-group-info.m4
+index 849a1e246..0fee1d36d 100644
+--- a/config/kernel-group-info.m4
++++ b/config/kernel-group-info.m4
+@@ -2,20 +2,21 @@ dnl #
+ dnl # 4.9 API change
+ dnl # group_info changed from 2d array via >blocks to 1d array via ->gid
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_GROUP_INFO_GID], [
+-      AC_MSG_CHECKING([whether group_info->gid exists])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="-Werror"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_GROUP_INFO_GID], [
++      ZFS_LINUX_TEST_SRC([group_info_gid], [
+               #include <linux/cred.h>
+       ],[
+               struct group_info *gi = groups_alloc(1);
+               gi->gid[0] = KGIDT_INIT(0);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_GROUP_INFO_GID], [
++      AC_MSG_CHECKING([whether group_info->gid exists])
++      ZFS_LINUX_TEST_RESULT([group_info_gid], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_GROUP_INFO_GID, 1, [group_info->gid exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
+ ])
+diff --git a/config/kernel-in-compat-syscall.m4 b/config/kernel-in-compat-syscall.m4
+index 9fca9da20..baaac8c4f 100644
+--- a/config/kernel-in-compat-syscall.m4
++++ b/config/kernel-in-compat-syscall.m4
+@@ -4,13 +4,17 @@ dnl # Added in_compat_syscall() which can be overridden on a per-
+ dnl # architecture basis.  Prior to this is_compat_task() was the
+ dnl # provided interface.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_IN_COMPAT_SYSCALL], [
+-      AC_MSG_CHECKING([whether in_compat_syscall() is available])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_IN_COMPAT_SYSCALL], [
++      ZFS_LINUX_TEST_SRC([in_compat_syscall], [
+               #include <linux/compat.h>
+       ],[
+               in_compat_syscall();
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_IN_COMPAT_SYSCALL], [
++      AC_MSG_CHECKING([whether in_compat_syscall() is available])
++      ZFS_LINUX_TEST_RESULT([in_compat_syscall], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_IN_COMPAT_SYSCALL, 1,
+                   [in_compat_syscall() is available])
+diff --git a/config/kernel-inode-getattr.m4 b/config/kernel-inode-getattr.m4
+index f10e0b251..48391d66f 100644
+--- a/config/kernel-inode-getattr.m4
++++ b/config/kernel-inode-getattr.m4
+@@ -2,9 +2,8 @@ dnl #
+ dnl # Linux 4.11 API
+ dnl # See torvalds/linux@a528d35
+ dnl #
+-AC_DEFUN([ZFS_AC_PATH_KERNEL_IOPS_GETATTR], [
+-      AC_MSG_CHECKING([whether iops->getattr() takes a path])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GETATTR], [
++      ZFS_LINUX_TEST_SRC([inode_operations_getattr_path], [
+               #include <linux/fs.h>
+               int test_getattr(
+@@ -16,24 +15,9 @@ AC_DEFUN([ZFS_AC_PATH_KERNEL_IOPS_GETATTR], [
+                   iops __attribute__ ((unused)) = {
+                       .getattr = test_getattr,
+               };
+-      ],[
+-      ],[
+-              AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_PATH_IOPS_GETATTR, 1,
+-                  [iops->getattr() takes a path])
+-      ],[
+-              AC_MSG_RESULT(no)
+-      ])
+-])
+-
++      ],[])
+-
+-dnl #
+-dnl # Linux 3.9 - 4.10 API
+-dnl #
+-AC_DEFUN([ZFS_AC_VFSMOUNT_KERNEL_IOPS_GETATTR], [
+-      AC_MSG_CHECKING([whether iops->getattr() takes a vfsmount])
+-      ZFS_LINUX_TRY_COMPILE([
++      ZFS_LINUX_TEST_SRC([inode_operations_getattr_vfsmount], [
+               #include <linux/fs.h>
+               int test_getattr(
+@@ -45,23 +29,25 @@ AC_DEFUN([ZFS_AC_VFSMOUNT_KERNEL_IOPS_GETATTR], [
+                   iops __attribute__ ((unused)) = {
+                       .getattr = test_getattr,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_INODE_GETATTR], [
++      AC_MSG_CHECKING([whether iops->getattr() takes a path])
++      ZFS_LINUX_TEST_RESULT([inode_operations_getattr_path], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_VFSMOUNT_IOPS_GETATTR, 1,
+-                  [iops->getattr() takes a vfsmount])
++              AC_DEFINE(HAVE_PATH_IOPS_GETATTR, 1,
++                  [iops->getattr() takes a path])
+       ],[
+               AC_MSG_RESULT(no)
+-      ])
+-])
+-
+-dnl #
+-dnl # The interface of the getattr callback from the inode_operations
+-dnl # structure changed.  Also, the interface of the simple_getattr()
+-dnl # function provided by the kernel changed.
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GETATTR], [
+-      ZFS_AC_PATH_KERNEL_IOPS_GETATTR
+-      ZFS_AC_VFSMOUNT_KERNEL_IOPS_GETATTR
++              AC_MSG_CHECKING([whether iops->getattr() takes a vfsmount])
++              ZFS_LINUX_TEST_RESULT([inode_operations_getattr_vfsmount], [
++                      AC_MSG_RESULT(yes)
++                      AC_DEFINE(HAVE_VFSMOUNT_IOPS_GETATTR, 1,
++                          [iops->getattr() takes a vfsmount])
++              ],[
++                      AC_MSG_RESULT(no)
++              ])
++      ])
+ ])
+diff --git a/config/kernel-inode-lock.m4 b/config/kernel-inode-lock.m4
+index 8dee01422..5eb04af78 100644
+--- a/config/kernel-inode-lock.m4
++++ b/config/kernel-inode-lock.m4
+@@ -4,20 +4,21 @@ dnl # i_mutex is changed to i_rwsem. Instead of directly using
+ dnl # i_mutex/i_rwsem, we should use inode_lock() and inode_lock_shared()
+ dnl # We test inode_lock_shared because inode_lock is introduced earlier.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_INODE_LOCK], [
+-      AC_MSG_CHECKING([whether inode_lock_shared() exists])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="-Werror"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_LOCK], [
++      ZFS_LINUX_TEST_SRC([inode_lock], [
+               #include <linux/fs.h>
+       ],[
+               struct inode *inode = NULL;
+               inode_lock_shared(inode);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_INODE_LOCK], [
++      AC_MSG_CHECKING([whether inode_lock_shared() exists])
++      ZFS_LINUX_TEST_RESULT([inode_lock], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_INODE_LOCK_SHARED, 1, [yes])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
+ ])
+diff --git a/config/kernel-inode-set-flags.m4 b/config/kernel-inode-set-flags.m4
+index e0ad26796..133f666a9 100644
+--- a/config/kernel-inode-set-flags.m4
++++ b/config/kernel-inode-set-flags.m4
+@@ -2,14 +2,18 @@ dnl #
+ dnl # 3.15 API change
+ dnl # inode_set_flags introduced to set i_flags
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_INODE_SET_FLAGS], [
+-      AC_MSG_CHECKING([whether inode_set_flags() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_SET_FLAGS], [
++      ZFS_LINUX_TEST_SRC([inode_set_flags], [
+               #include <linux/fs.h>
+       ],[
+               struct inode inode;
+               inode_set_flags(&inode, S_IMMUTABLE, S_IMMUTABLE);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_INODE_SET_FLAGS], [
++      AC_MSG_CHECKING([whether inode_set_flags() exists])
++      ZFS_LINUX_TEST_RESULT([inode_set_flags], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_INODE_SET_FLAGS, 1, [inode_set_flags() exists])
+       ],[
+diff --git a/config/kernel-inode-set-iversion.m4 b/config/kernel-inode-set-iversion.m4
+index 9a7d7890e..dd415de32 100644
+--- a/config/kernel-inode-set-iversion.m4
++++ b/config/kernel-inode-set-iversion.m4
+@@ -2,14 +2,18 @@ dnl #
+ dnl # 4.16 API change
+ dnl # inode_set_iversion introduced to set i_version
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_INODE_SET_IVERSION], [
+-      AC_MSG_CHECKING([whether inode_set_iversion() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_SET_IVERSION], [
++      ZFS_LINUX_TEST_SRC([inode_set_iversion], [
+               #include <linux/iversion.h>
+       ],[
+               struct inode inode;
+               inode_set_iversion(&inode, 1);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_INODE_SET_IVERSION], [
++      AC_MSG_CHECKING([whether inode_set_iversion() exists])
++      ZFS_LINUX_TEST_RESULT([inode_set_iversion], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_INODE_SET_IVERSION, 1,
+                   [inode_set_iversion() exists])
+diff --git a/config/kernel-inode-times.m4 b/config/kernel-inode-times.m4
+index f5818411a..57e7f31fd 100644
+--- a/config/kernel-inode-times.m4
++++ b/config/kernel-inode-times.m4
+@@ -2,11 +2,8 @@ dnl #
+ dnl # 4.18 API change
+ dnl # i_atime, i_mtime, and i_ctime changed from timespec to timespec64.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_INODE_TIMES], [
+-      AC_MSG_CHECKING([whether inode->i_*time's are timespec64])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="-Werror"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_TIMES], [
++      ZFS_LINUX_TEST_SRC([inode_times], [
+               #include <linux/fs.h>
+       ],[
+               struct inode ip;
+@@ -14,12 +11,16 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_TIMES], [
+               memset(&ip, 0, sizeof(ip));
+               ts = ip.i_mtime;
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_INODE_TIMES], [
++      AC_MSG_CHECKING([whether inode->i_*time's are timespec64])
++      ZFS_LINUX_TEST_RESULT([inode_times], [
+               AC_MSG_RESULT(no)
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_INODE_TIMESPEC64_TIMES, 1,
+                   [inode->i_*time's are timespec64])
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
+ ])
+diff --git a/config/kernel-insert-inode-locked.m4 b/config/kernel-insert-inode-locked.m4
+index da141d180..4990399c3 100644
+--- a/config/kernel-insert-inode-locked.m4
++++ b/config/kernel-insert-inode-locked.m4
+@@ -2,16 +2,21 @@ dnl #
+ dnl # 2.6.28 API change
+ dnl # Added insert_inode_locked() helper function.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_INSERT_INODE_LOCKED],
+-      [AC_MSG_CHECKING([whether insert_inode_locked() is available])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_INSERT_INODE_LOCKED], [
++      ZFS_LINUX_TEST_SRC([insert_inode_locked], [
+               #include <linux/fs.h>
+       ], [
+               insert_inode_locked(NULL);
+-      ], [insert_inode_locked], [fs/inode.c], [
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_INSERT_INODE_LOCKED], [
++      AC_MSG_CHECKING([whether insert_inode_locked() is available])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([insert_inode_locked],
++          [insert_inode_locked], [fs/inode.c], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_INSERT_INODE_LOCKED, 1,
+-                        [insert_inode_locked() is available])
++                  [insert_inode_locked() is available])
+       ], [
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-invalidate-bdev-args.m4 b/config/kernel-invalidate-bdev-args.m4
+index 09c2ebf26..55a784dd9 100644
+--- a/config/kernel-invalidate-bdev-args.m4
++++ b/config/kernel-invalidate-bdev-args.m4
+@@ -2,17 +2,21 @@ dnl #
+ dnl # 2.6.22 API change
+ dnl # Unused destroy_dirty_buffers arg removed from prototype.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_INVALIDATE_BDEV_ARGS], [
+-      AC_MSG_CHECKING([whether invalidate_bdev() wants 1 arg])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_INVALIDATE_BDEV], [
++      ZFS_LINUX_TEST_SRC([invalidate_bdev], [
+               #include <linux/buffer_head.h>
+       ],[
+               struct block_device *bdev = NULL;
+               invalidate_bdev(bdev);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_INVALIDATE_BDEV], [
++      AC_MSG_CHECKING([whether invalidate_bdev() wants 1 arg])
++      ZFS_LINUX_TEST_RESULT([invalidate_bdev], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_1ARG_INVALIDATE_BDEV, 1,
+-                        [invalidate_bdev() wants 1 arg])
++                  [invalidate_bdev() wants 1 arg])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-is_owner_or_cap.m4 b/config/kernel-is_owner_or_cap.m4
+index da07e58dd..ab8072409 100644
+--- a/config/kernel-is_owner_or_cap.m4
++++ b/config/kernel-is_owner_or_cap.m4
+@@ -4,33 +4,40 @@ dnl # The is_owner_or_cap() macro was renamed to inode_owner_or_capable(),
+ dnl # This is used for permission checks in the xattr and file attribute call
+ dnl # paths.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE], [
+-      AC_MSG_CHECKING([whether inode_owner_or_capable() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OWNER_OR_CAPABLE], [
++      ZFS_LINUX_TEST_SRC([inode_owner_or_capable], [
+               #include <linux/fs.h>
+       ],[
+               struct inode *ip = NULL;
+               (void) inode_owner_or_capable(ip);
++      ])
++
++
++      ZFS_LINUX_TEST_SRC([is_owner_or_cap], [
++              #include <linux/fs.h>
++              #include <linux/sched.h>
+       ],[
++              struct inode *ip = NULL;
++              (void) is_owner_or_cap(ip);
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE], [
++      AC_MSG_CHECKING([whether inode_owner_or_capable() exists])
++      ZFS_LINUX_TEST_RESULT([inode_owner_or_capable], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_INODE_OWNER_OR_CAPABLE, 1,
+                   [inode_owner_or_capable() exists])
+       ],[
+               AC_MSG_RESULT(no)
+               AC_MSG_CHECKING([whether is_owner_or_cap() exists])
+-              ZFS_LINUX_TRY_COMPILE([
+-                      #include <linux/fs.h>
+-                      #include <linux/sched.h>
+-              ],[
+-                      struct inode *ip = NULL;
+-                      (void) is_owner_or_cap(ip);
+-              ],[
++
++              ZFS_LINUX_TEST_RESULT([is_owner_or_cap], [
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_IS_OWNER_OR_CAP, 1,
+                           [is_owner_or_cap() exists])
+               ],[
+-                      AC_MSG_ERROR(no - Please file a bug report at
+-                          https://github.com/zfsonlinux/zfs/issues/new)
++                      ZFS_LINUX_TEST_ERROR([capability])
+               ])
+       ])
+ ])
+diff --git a/config/kernel-kmap-atomic-args.m4 b/config/kernel-kmap-atomic-args.m4
+index beb1692e7..d09e93d7f 100644
+--- a/config/kernel-kmap-atomic-args.m4
++++ b/config/kernel-kmap-atomic-args.m4
+@@ -3,17 +3,21 @@ dnl # 2.6.37 API change
+ dnl # kmap_atomic changed from assigning hard-coded named slot to using
+ dnl # push/pop based dynamical allocation.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_KMAP_ATOMIC_ARGS], [
+-      AC_MSG_CHECKING([whether kmap_atomic wants 1 args])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_KMAP_ATOMIC_ARGS], [
++      ZFS_LINUX_TEST_SRC([kmap_atomic], [
+               #include <linux/pagemap.h>
+       ],[
+               struct page page;
+               kmap_atomic(&page);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_KMAP_ATOMIC_ARGS], [
++      AC_MSG_CHECKING([whether kmap_atomic wants 1 args])
++      ZFS_LINUX_TEST_RESULT([kmap_atomic], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_1ARG_KMAP_ATOMIC, 1,
+-                        [kmap_atomic wants 1 args])
++                  [kmap_atomic wants 1 args])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-kmem-cache.m4 b/config/kernel-kmem-cache.m4
+index 21cc53d34..7576e6cfd 100644
+--- a/config/kernel-kmem-cache.m4
++++ b/config/kernel-kmem-cache.m4
+@@ -5,30 +5,36 @@ dnl # private allocation flags which are applied when allocating a new slab
+ dnl # in kmem_getpages().  Unfortunately there is no public API for setting
+ dnl # non-default flags.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_KMEM_CACHE_ALLOCFLAGS], [
+-      AC_MSG_CHECKING([whether struct kmem_cache has allocflags])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_KMEM_CACHE_ALLOCFLAGS], [
++      ZFS_LINUX_TEST_SRC([kmem_cache_allocflags], [
+               #include <linux/slab.h>
+       ],[
+               struct kmem_cache cachep __attribute__ ((unused));
+               cachep.allocflags = GFP_KERNEL;
++      ])
++
++      ZFS_LINUX_TEST_SRC([kmem_cache_gfpflags], [
++              #include <linux/slab.h>
+       ],[
++              struct kmem_cache cachep __attribute__ ((unused));
++              cachep.gfpflags = GFP_KERNEL;
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_KMEM_CACHE_ALLOCFLAGS], [
++      AC_MSG_CHECKING([whether struct kmem_cache has allocflags])
++      ZFS_LINUX_TEST_RESULT([kmem_cache_allocflags], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_KMEM_CACHE_ALLOCFLAGS, 1,
+-                      [struct kmem_cache has allocflags])
++                  [struct kmem_cache has allocflags])
+       ],[
+               AC_MSG_RESULT(no)
+               AC_MSG_CHECKING([whether struct kmem_cache has gfpflags])
+-              ZFS_LINUX_TRY_COMPILE([
+-                      #include <linux/slab.h>
+-              ],[
+-                      struct kmem_cache cachep __attribute__ ((unused));
+-                      cachep.gfpflags = GFP_KERNEL;
+-              ],[
++              ZFS_LINUX_TEST_RESULT([kmem_cache_gfpflags], [
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_KMEM_CACHE_GFPFLAGS, 1,
+-                              [struct kmem_cache has gfpflags])
++                          [struct kmem_cache has gfpflags])
+               ],[
+                       AC_MSG_RESULT(no)
+               ])
+@@ -40,16 +46,10 @@ dnl # grsecurity API change,
+ dnl # kmem_cache_create() with SLAB_USERCOPY flag replaced by
+ dnl # kmem_cache_create_usercopy().
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_KMEM_CACHE_CREATE_USERCOPY], [
+-      AC_MSG_CHECKING([whether kmem_cache_create_usercopy() exists])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="-Werror"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_KMEM_CACHE_CREATE_USERCOPY], [
++      ZFS_LINUX_TEST_SRC([kmem_cache_create_usercopy], [
+               #include <linux/slab.h>
+-              static void ctor(void *foo)
+-              {
+-                      // fake ctor
+-              }
++              static void ctor(void *foo) { /* fake ctor */ }
+       ],[
+               struct kmem_cache *skc_linux_cache;
+               const char *name = "test";
+@@ -60,13 +60,27 @@ AC_DEFUN([ZFS_AC_KERNEL_KMEM_CACHE_CREATE_USERCOPY], [
+               size_t usersize = size - useroffset;
+               skc_linux_cache = kmem_cache_create_usercopy(
+-                      name, size, align, flags, useroffset, usersize, ctor);
+-      ],[
++                  name, size, align, flags, useroffset, usersize, ctor);
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_KMEM_CACHE_CREATE_USERCOPY], [
++      AC_MSG_CHECKING([whether kmem_cache_create_usercopy() exists])
++      ZFS_LINUX_TEST_RESULT([kmem_cache_create_usercopy], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_KMEM_CACHE_CREATE_USERCOPY, 1,
+-                              [kmem_cache_create_usercopy() exists])
++                  [kmem_cache_create_usercopy() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_KMEM_CACHE], [
++      ZFS_AC_KERNEL_SRC_KMEM_CACHE_ALLOCFLAGS
++      ZFS_AC_KERNEL_SRC_KMEM_CACHE_CREATE_USERCOPY
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_KMEM_CACHE], [
++      ZFS_AC_KERNEL_KMEM_CACHE_ALLOCFLAGS
++      ZFS_AC_KERNEL_KMEM_CACHE_CREATE_USERCOPY
+ ])
+diff --git a/config/kernel-kstrtoul.m4 b/config/kernel-kstrtoul.m4
+index 5530e0e2d..ef3c9843c 100644
+--- a/config/kernel-kstrtoul.m4
++++ b/config/kernel-kstrtoul.m4
+@@ -1,18 +1,20 @@
+ dnl #
+ dnl # 2.6.39 API change
+ dnl #
+-dnl # 33ee3b2e2eb9 kstrto*: converting strings to integers done (hopefully) right
+-dnl #
+ dnl # If kstrtoul() doesn't exist, fallback to use strict_strtoul() which has
+ dnl # existed since 2.6.25.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_KSTRTOUL], [
+-      AC_MSG_CHECKING([whether kstrtoul() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_KSTRTOUL], [
++      ZFS_LINUX_TEST_SRC([kstrtoul], [
+               #include <linux/kernel.h>
+       ],[
+               int ret __attribute__ ((unused)) = kstrtoul(NULL, 10, NULL);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_KSTRTOUL], [
++      AC_MSG_CHECKING([whether kstrtoul() exists])
++      ZFS_LINUX_TEST_RESULT([kstrtoul], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_KSTRTOUL, 1, [kstrtoul() exists])
+       ],[
+diff --git a/config/kernel-ktime_get_coarse_real_ts64.m4 b/config/kernel-ktime_get_coarse_real_ts64.m4
+index d6be8c418..28492bf04 100644
+--- a/config/kernel-ktime_get_coarse_real_ts64.m4
++++ b/config/kernel-ktime_get_coarse_real_ts64.m4
+@@ -2,16 +2,21 @@ dnl #
+ dnl # 4.18: ktime_get_coarse_real_ts64() added.  Use it in place of
+ dnl # current_kernel_time64().
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_KTIME_GET_COARSE_REAL_TS64],
+-      [AC_MSG_CHECKING([whether ktime_get_coarse_real_ts64() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_KTIME_GET_COARSE_REAL_TS64], [
++      ZFS_LINUX_TEST_SRC([ktime_get_coarse_real_ts64], [
+               #include <linux/mm.h>
+       ], [
+               struct timespec64 ts;
+               ktime_get_coarse_real_ts64(&ts);
+-      ], [
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_KTIME_GET_COARSE_REAL_TS64], [
++      AC_MSG_CHECKING([whether ktime_get_coarse_real_ts64() exists])
++      ZFS_LINUX_TEST_RESULT([ktime_get_coarse_real_ts64], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_KTIME_GET_COARSE_REAL_TS64, 1, [ktime_get_coarse_real_ts64() exists])
++              AC_DEFINE(HAVE_KTIME_GET_COARSE_REAL_TS64, 1,
++                  [ktime_get_coarse_real_ts64() exists])
+       ], [
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-kuid-helpers.m4 b/config/kernel-kuid-helpers.m4
+index 60713b9d3..4bc4e039d 100644
+--- a/config/kernel-kuid-helpers.m4
++++ b/config/kernel-kuid-helpers.m4
+@@ -5,14 +5,18 @@ dnl # became necessary to go through one more level of indirection
+ dnl # when dealing with uid/gid - namely the kuid type.
+ dnl #
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_KUID_HELPERS], [
+-      AC_MSG_CHECKING([whether i_(uid|gid)_(read|write) exist])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_KUID_HELPERS], [
++      ZFS_LINUX_TEST_SRC([i_uid_read], [
+               #include <linux/fs.h>
+       ],[
+               struct inode *ip = NULL;
+               (void) i_uid_read(ip);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_KUID_HELPERS], [
++      AC_MSG_CHECKING([whether i_(uid|gid)_(read|write) exist])
++      ZFS_LINUX_TEST_RESULT([i_uid_read], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_KUID_HELPERS, 1,
+                   [i_(uid|gid)_(read|write) exist])
+diff --git a/config/kernel-kuidgid.m4 b/config/kernel-kuidgid.m4
+index 82685d263..15bf98154 100644
+--- a/config/kernel-kuidgid.m4
++++ b/config/kernel-kuidgid.m4
+@@ -3,20 +3,26 @@ dnl # User namespaces, use kuid_t in place of uid_t
+ dnl # where available. Not strictly a user namespaces thing
+ dnl # but it should prevent surprises
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_KUIDGID_T], [
+-      AC_MSG_CHECKING([whether kuid_t/kgid_t is available])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_KUIDGID_T], [
++      ZFS_LINUX_TEST_SRC([kuidgid_t_init], [
+               #include <linux/uidgid.h>
+       ], [
+               kuid_t userid __attribute__ ((unused)) = KUIDT_INIT(0);
+               kgid_t groupid __attribute__ ((unused)) = KGIDT_INIT(0);
+-      ],[
+-              ZFS_LINUX_TRY_COMPILE([
+-                      #include <linux/uidgid.h>
+-              ], [
+-                      kuid_t userid __attribute__ ((unused)) = 0;
+-                      kgid_t groupid __attribute__ ((unused)) = 0;
+-              ],[
++      ])
++
++      ZFS_LINUX_TEST_SRC([kuidgid_t], [
++              #include <linux/uidgid.h>
++      ], [
++              kuid_t userid __attribute__ ((unused)) = 0;
++              kgid_t groupid __attribute__ ((unused)) = 0;
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_KUIDGID_T], [
++      AC_MSG_CHECKING([whether kuid_t/kgid_t is available])
++      ZFS_LINUX_TEST_RESULT([kuidgid_t_init], [
++              ZFS_LINUX_TEST_RESULT([kuidgid_t], [
+                       AC_MSG_RESULT(yes; optional)
+               ],[
+                       AC_MSG_RESULT(yes; mandatory)
+diff --git a/config/kernel-lookup-bdev.m4 b/config/kernel-lookup-bdev.m4
+index abbf55d9b..72b4993e1 100644
+--- a/config/kernel-lookup-bdev.m4
++++ b/config/kernel-lookup-bdev.m4
+@@ -2,23 +2,33 @@ dnl #
+ dnl # 2.6.27, lookup_bdev() was exported.
+ dnl # 4.4.0-6.21 - x.y on Ubuntu, lookup_bdev() takes 2 arguments.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_LOOKUP_BDEV],
+-      [AC_MSG_CHECKING([whether lookup_bdev() wants 1 arg])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_LOOKUP_BDEV], [
++      ZFS_LINUX_TEST_SRC([lookup_bdev_1arg], [
+               #include <linux/fs.h>
+       ], [
+               lookup_bdev(NULL);
+-      ], [lookup_bdev], [fs/block_dev.c], [
++      ])
++
++      ZFS_LINUX_TEST_SRC([lookup_bdev_2args], [
++              #include <linux/fs.h>
++      ], [
++              lookup_bdev(NULL, FMODE_READ);
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_LOOKUP_BDEV], [
++      AC_MSG_CHECKING([whether lookup_bdev() wants 1 arg])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([lookup_bdev_1arg],
++          [lookup_bdev], [fs/block_dev.c], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_1ARG_LOOKUP_BDEV, 1, [lookup_bdev() wants 1 arg])
++              AC_DEFINE(HAVE_1ARG_LOOKUP_BDEV, 1,
++                  [lookup_bdev() wants 1 arg])
+       ], [
+               AC_MSG_RESULT(no)
++
+               AC_MSG_CHECKING([whether lookup_bdev() wants 2 args])
+-              ZFS_LINUX_TRY_COMPILE_SYMBOL([
+-                      #include <linux/fs.h>
+-              ], [
+-                      lookup_bdev(NULL, FMODE_READ);
+-              ], [lookup_bdev], [fs/block_dev.c], [
++              ZFS_LINUX_TEST_RESULT_SYMBOL([lookup_bdev_2args],
++                  [lookup_bdev], [fs/block_dev.c], [
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_2ARGS_LOOKUP_BDEV, 1,
+                           [lookup_bdev() wants 2 args])
+@@ -26,4 +36,4 @@ AC_DEFUN([ZFS_AC_KERNEL_LOOKUP_BDEV],
+                       AC_MSG_RESULT(no)
+               ])
+       ])
+-])
+\ No newline at end of file
++])
+diff --git a/config/kernel-lookup-nameidata.m4 b/config/kernel-lookup-nameidata.m4
+index 5453be5e8..865b8aff8 100644
+--- a/config/kernel-lookup-nameidata.m4
++++ b/config/kernel-lookup-nameidata.m4
+@@ -1,9 +1,8 @@
+ dnl #
+ dnl # 3.6 API change
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_LOOKUP_NAMEIDATA], [
+-      AC_MSG_CHECKING([whether iops->lookup() passes nameidata])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_LOOKUP_NAMEIDATA], [
++      ZFS_LINUX_TEST_SRC([lookup_nameidata], [
+               #include <linux/fs.h>
+               #include <linux/sched.h>
+@@ -15,11 +14,15 @@ AC_DEFUN([ZFS_AC_KERNEL_LOOKUP_NAMEIDATA], [
+                   __attribute__ ((unused)) = {
+                       .lookup = inode_lookup,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_LOOKUP_NAMEIDATA], [
++      AC_MSG_CHECKING([whether iops->lookup() passes nameidata])
++      ZFS_LINUX_TEST_RESULT([lookup_nameidata], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_LOOKUP_NAMEIDATA, 1,
+-                        [iops->lookup() passes nameidata])
++                  [iops->lookup() passes nameidata])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-lseek-execute.m4 b/config/kernel-lseek-execute.m4
+index 8c4032b92..652f611f8 100644
+--- a/config/kernel-lseek-execute.m4
++++ b/config/kernel-lseek-execute.m4
+@@ -2,9 +2,8 @@ dnl #
+ dnl # 3.11 API change
+ dnl # lseek_execute helper exported
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_LSEEK_EXECUTE],
+-      [AC_MSG_CHECKING([whether lseek_execute() is available])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_LSEEK_EXECUTE], [
++      ZFS_LINUX_TEST_SRC([lseek_execute], [
+               #include <linux/fs.h>
+       ], [
+               struct file *fp __attribute__ ((unused)) = NULL;
+@@ -13,10 +12,15 @@ AC_DEFUN([ZFS_AC_KERNEL_LSEEK_EXECUTE],
+               loff_t maxsize __attribute__ ((unused)) = 0;
+               lseek_execute(fp, ip, offset, maxsize);
+-      ], [lseek_exclusive], [fs/read_write.c], [
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_LSEEK_EXECUTE], [
++      AC_MSG_CHECKING([whether lseek_execute() is available])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([lseek_execute],
++          [lseek_exclusive], [fs/read_write.c], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_LSEEK_EXECUTE, 1,
+-                        [lseek_execute() is available])
++              AC_DEFINE(HAVE_LSEEK_EXECUTE, 1, [lseek_execute() is available])
+       ], [
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-make-request-fn.m4 b/config/kernel-make-request-fn.m4
+new file mode 100644
+index 000000000..86339aa04
+--- /dev/null
++++ b/config/kernel-make-request-fn.m4
+@@ -0,0 +1,77 @@
++dnl #
++dnl # Check for make_request_fn interface.
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_MAKE_REQUEST_FN], [
++      ZFS_LINUX_TEST_SRC([make_request_fn_int], [
++              #include <linux/blkdev.h>
++              int make_request(struct request_queue *q,
++                  struct bio *bio) { return (0); }
++      ],[
++              blk_queue_make_request(NULL, &make_request);
++      ])
++
++      ZFS_LINUX_TEST_SRC([make_request_fn_void], [
++              #include <linux/blkdev.h>
++              void make_request(struct request_queue *q,
++                  struct bio *bio) { return; }
++      ],[
++              blk_queue_make_request(NULL, &make_request);
++      ])
++
++      ZFS_LINUX_TEST_SRC([make_request_fn_blk_qc_t], [
++              #include <linux/blkdev.h>
++              blk_qc_t make_request(struct request_queue *q,
++                  struct bio *bio) { return (BLK_QC_T_NONE); }
++      ],[
++              blk_queue_make_request(NULL, &make_request);
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_MAKE_REQUEST_FN], [
++      dnl #
++      dnl # Legacy API
++      dnl # make_request_fn returns int.
++      dnl #
++      AC_MSG_CHECKING([whether make_request_fn() returns int])
++      ZFS_LINUX_TEST_RESULT([make_request_fn_int], [
++              AC_MSG_RESULT(yes)
++              AC_DEFINE(MAKE_REQUEST_FN_RET, int,
++                  [make_request_fn() return type])
++              AC_DEFINE(HAVE_MAKE_REQUEST_FN_RET_INT, 1,
++                  [Noting that make_request_fn() returns int])
++      ],[
++              AC_MSG_RESULT(no)
++
++              dnl #
++              dnl # Linux 3.2 API Change
++              dnl # make_request_fn returns void.
++              dnl #
++              AC_MSG_CHECKING([whether make_request_fn() returns void])
++              ZFS_LINUX_TEST_RESULT([make_request_fn_void], [
++                      AC_MSG_RESULT(yes)
++                      AC_DEFINE(MAKE_REQUEST_FN_RET, void,
++                          [make_request_fn() return type])
++                      AC_DEFINE(HAVE_MAKE_REQUEST_FN_RET_VOID, 1,
++                          [Noting that make_request_fn() returns void])
++              ],[
++                      AC_MSG_RESULT(no)
++
++                      dnl #
++                      dnl # Linux 4.4 API Change
++                      dnl # make_request_fn returns blk_qc_t.
++                      dnl #
++                      AC_MSG_CHECKING(
++                          [whether make_request_fn() returns blk_qc_t])
++                      ZFS_LINUX_TEST_RESULT([make_request_fn_blk_qc_t], [
++                              AC_MSG_RESULT(yes)
++                              AC_DEFINE(MAKE_REQUEST_FN_RET, blk_qc_t,
++                                  [make_request_fn() return type])
++                              AC_DEFINE(HAVE_MAKE_REQUEST_FN_RET_QC, 1,
++                                  [Noting that make_request_fn() ]
++                                  [returns blk_qc_t])
++                      ],[
++                              ZFS_LINUX_TEST_ERROR([make_request_fn])
++                      ])
++              ])
++      ])
++])
+diff --git a/config/kernel-misc-minor.m4 b/config/kernel-misc-minor.m4
+index a020d2ebc..20fe2cd2f 100644
+--- a/config/kernel-misc-minor.m4
++++ b/config/kernel-misc-minor.m4
+@@ -6,7 +6,7 @@ dnl # number.  Start with a large known available unreserved minor and work
+ dnl # our way down to lower value if a collision is detected.
+ dnl #
+ AC_DEFUN([ZFS_AC_KERNEL_MISC_MINOR], [
+-      AC_MSG_CHECKING([for available /dev/zfs minor])
++      AC_MSG_CHECKING([whether /dev/zfs minor is available])
+       for i in $(seq 249 -1 200); do
+               if ! grep -q "^#define\s\+.*_MINOR\s\+.*$i" \
+diff --git a/config/kernel-mk-request-fn.m4 b/config/kernel-mk-request-fn.m4
+deleted file mode 100644
+index 57eebe23d..000000000
+--- a/config/kernel-mk-request-fn.m4
++++ /dev/null
+@@ -1,65 +0,0 @@
+-dnl #
+-dnl # Linux 3.2 API Change
+-dnl # make_request_fn returns void instead of int.
+-dnl #
+-dnl # Linux 4.4 API Change
+-dnl # make_request_fn returns blk_qc_t.
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_MAKE_REQUEST_FN], [
+-      AC_MSG_CHECKING([whether make_request_fn() returns int])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/blkdev.h>
+-
+-              int make_request(struct request_queue *q, struct bio *bio)
+-              {
+-                      return (0);
+-              }
+-      ],[
+-              blk_queue_make_request(NULL, &make_request);
+-      ],[
+-              AC_MSG_RESULT(yes)
+-              AC_DEFINE(MAKE_REQUEST_FN_RET, int,
+-                  [make_request_fn() returns int])
+-              AC_DEFINE(HAVE_MAKE_REQUEST_FN_RET_INT, 1,
+-                  [Noting that make_request_fn() returns int])
+-      ],[
+-              AC_MSG_RESULT(no)
+-              AC_MSG_CHECKING([whether make_request_fn() returns void])
+-              ZFS_LINUX_TRY_COMPILE([
+-                      #include <linux/blkdev.h>
+-
+-                      void make_request(struct request_queue *q, struct bio *bio)
+-                      {
+-                              return;
+-                      }
+-              ],[
+-                      blk_queue_make_request(NULL, &make_request);
+-              ],[
+-                      AC_MSG_RESULT(yes)
+-                      AC_DEFINE(MAKE_REQUEST_FN_RET, void,
+-                          [make_request_fn() returns void])
+-              ],[
+-                      AC_MSG_RESULT(no)
+-                      AC_MSG_CHECKING([whether make_request_fn() returns blk_qc_t])
+-                      ZFS_LINUX_TRY_COMPILE([
+-                              #include <linux/blkdev.h>
+-
+-                              blk_qc_t make_request(struct request_queue *q, struct bio *bio)
+-                              {
+-                                      return (BLK_QC_T_NONE);
+-                              }
+-                      ],[
+-                              blk_queue_make_request(NULL, &make_request);
+-                      ],[
+-                              AC_MSG_RESULT(yes)
+-                              AC_DEFINE(MAKE_REQUEST_FN_RET, blk_qc_t,
+-                                  [make_request_fn() returns blk_qc_t])
+-                              AC_DEFINE(HAVE_MAKE_REQUEST_FN_RET_QC, 1,
+-                                  [Noting that make_request_fn() returns blk_qc_t])
+-                      ],[
+-                              AC_MSG_ERROR(no - Please file a bug report at
+-                                  https://github.com/zfsonlinux/zfs/issues/new)
+-                      ])
+-              ])
+-      ])
+-])
+diff --git a/config/kernel-mkdir-umode-t.m4 b/config/kernel-mkdir-umode-t.m4
+index ebc21be9e..4cbfc0c31 100644
+--- a/config/kernel-mkdir-umode-t.m4
++++ b/config/kernel-mkdir-umode-t.m4
+@@ -6,9 +6,8 @@ dnl # would also change all three prototypes.  However, if it turns out that
+ dnl # some distribution doesn't backport the whole thing this could be
+ dnl # broken apart in to three separate checks.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_MKDIR_UMODE_T], [
+-      AC_MSG_CHECKING([whether iops->create()/mkdir()/mknod() take umode_t])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_MKDIR_UMODE_T], [
++      ZFS_LINUX_TEST_SRC([inode_operations_mkdir], [
+               #include <linux/fs.h>
+               int mkdir(struct inode *inode, struct dentry *dentry,
+@@ -18,8 +17,12 @@ AC_DEFUN([ZFS_AC_KERNEL_MKDIR_UMODE_T], [
+                   iops __attribute__ ((unused)) = {
+                       .mkdir = mkdir,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_MKDIR_UMODE_T], [
++      AC_MSG_CHECKING([whether iops->create()/mkdir()/mknod() take umode_t])
++      ZFS_LINUX_TEST_RESULT([inode_operations_mkdir], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_MKDIR_UMODE_T, 1,
+                   [iops->create()/mkdir()/mknod() take umode_t])
+diff --git a/config/kernel-mod-param.m4 b/config/kernel-mod-param.m4
+index b72be684a..e00f19d61 100644
+--- a/config/kernel-mod-param.m4
++++ b/config/kernel-mod-param.m4
+@@ -2,9 +2,8 @@ dnl #
+ dnl # Grsecurity kernel API change
+ dnl # constified parameters of module_param_call() methods
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_MODULE_PARAM_CALL_CONST], [
+-      AC_MSG_CHECKING([whether module_param_call() is hardened])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_MODULE_PARAM_CALL_CONST], [
++      ZFS_LINUX_TEST_SRC([module_param_call], [
+               #include <linux/module.h>
+               #include <linux/moduleparam.h>
+@@ -19,8 +18,12 @@ AC_DEFUN([ZFS_AC_KERNEL_MODULE_PARAM_CALL_CONST], [
+               }
+               module_param_call(p, param_set, param_get, NULL, 0644);
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_MODULE_PARAM_CALL_CONST], [
++      AC_MSG_CHECKING([whether module_param_call() is hardened])
++      ZFS_LINUX_TEST_RESULT([module_param_call], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(MODULE_PARAM_CALL_CONST, 1,
+                   [hardened module_param_call])
+diff --git a/config/kernel-objtool.m4 b/config/kernel-objtool.m4
+index 467329b25..bf60e7869 100644
+--- a/config/kernel-objtool.m4
++++ b/config/kernel-objtool.m4
+@@ -1,41 +1,44 @@
+ dnl #
+-dnl # 4.6 API for compile-time stack validation
++dnl # Check for objtool support.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_OBJTOOL], [
+-      AC_MSG_CHECKING([for compile-time stack validation (objtool)])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_OBJTOOL], [
++
++      dnl # 4.6 API for compile-time stack validation
++      ZFS_LINUX_TEST_SRC([objtool], [
+               #undef __ASSEMBLY__
+               #include <asm/frame.h>
+       ],[
+               #if !defined(FRAME_BEGIN)
+               CTASSERT(1);
+               #endif
+-      ],[
+-              AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_KERNEL_OBJTOOL, 1,
+-                  [kernel does stack verification])
+-
+-              ZFS_AC_KERNEL_STACK_FRAME_NON_STANDARD
+-      ],[
+-              AC_MSG_RESULT(no)
+       ])
+-])
+-dnl #
+-dnl # 4.6 API added STACK_FRAME_NON_STANDARD macro
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_STACK_FRAME_NON_STANDARD], [
+-      AC_MSG_CHECKING([whether STACK_FRAME_NON_STANDARD is defined])
+-      ZFS_LINUX_TRY_COMPILE([
++      dnl # 4.6 API added STACK_FRAME_NON_STANDARD macro
++      ZFS_LINUX_TEST_SRC([stack_frame_non_standard], [
+               #include <linux/frame.h>
+       ],[
+               #if !defined(STACK_FRAME_NON_STANDARD)
+               CTASSERT(1);
+               #endif
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_OBJTOOL], [
++      AC_MSG_CHECKING(
++          [whether compile-time stack validation (objtool) is available])
++      ZFS_LINUX_TEST_RESULT([objtool], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_STACK_FRAME_NON_STANDARD, 1,
+-                 [STACK_FRAME_NON_STANDARD is defined])
++              AC_DEFINE(HAVE_KERNEL_OBJTOOL, 1,
++                  [kernel does stack verification])
++
++              AC_MSG_CHECKING([whether STACK_FRAME_NON_STANDARD is defined])
++              ZFS_LINUX_TEST_RESULT([stack_frame_non_standard], [
++                      AC_MSG_RESULT(yes)
++                      AC_DEFINE(HAVE_STACK_FRAME_NON_STANDARD, 1,
++                         [STACK_FRAME_NON_STANDARD is defined])
++              ],[
++                      AC_MSG_RESULT(no)
++              ])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-open-bdev-exclusive.m4 b/config/kernel-open-bdev-exclusive.m4
+index 0661315a6..2e46b8876 100644
+--- a/config/kernel-open-bdev-exclusive.m4
++++ b/config/kernel-open-bdev-exclusive.m4
+@@ -2,16 +2,21 @@ dnl #
+ dnl # 2.6.28 API change
+ dnl # open/close_bdev_excl() renamed to open/close_bdev_exclusive()
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_OPEN_BDEV_EXCLUSIVE],
+-      [AC_MSG_CHECKING([whether open_bdev_exclusive() is available])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_BDEV_OPEN_EXCLUSIVE], [
++      ZFS_LINUX_TEST_SRC([open_bdev_exclusive], [
+               #include <linux/fs.h>
+       ], [
+               open_bdev_exclusive(NULL, 0, NULL);
+-      ], [open_bdev_exclusive], [fs/block_dev.c], [
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_BDEV_OPEN_EXCLUSIVE], [
++      AC_MSG_CHECKING([whether open_bdev_exclusive() is available])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([open_bdev_exclusive],
++          [open_bdev_exclusive], [fs/block_dev.c], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_OPEN_BDEV_EXCLUSIVE, 1,
+-                        [open_bdev_exclusive() is available])
++                  [open_bdev_exclusive() is available])
+       ], [
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-pde-data.m4 b/config/kernel-pde-data.m4
+index 8aa4c2204..928c5ef0d 100644
+--- a/config/kernel-pde-data.m4
++++ b/config/kernel-pde-data.m4
+@@ -2,15 +2,19 @@ dnl #
+ dnl # 3.10 API change,
+ dnl # PDE is replaced by PDE_DATA
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_PDE_DATA], [
+-      AC_MSG_CHECKING([whether PDE_DATA() is available])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_PDE_DATA], [
++      ZFS_LINUX_TEST_SRC([pde_data], [
+               #include <linux/proc_fs.h>
+       ], [
+               PDE_DATA(NULL);
+-      ], [PDE_DATA], [], [
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_PDE_DATA], [
++      AC_MSG_CHECKING([whether PDE_DATA() is available])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([pde_data], [PDE_DATA], [], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_PDE_DATA, 1, [yes])
++              AC_DEFINE(HAVE_PDE_DATA, 1, [PDE_DATA is available])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-put-link.m4 b/config/kernel-put-link.m4
+index a0bb36ef2..f03df9e99 100644
+--- a/config/kernel-put-link.m4
++++ b/config/kernel-put-link.m4
+@@ -1,17 +1,35 @@
+ dnl #
+ dnl # Supported symlink APIs
+ dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_PUT_LINK], [
++      ZFS_LINUX_TEST_SRC([put_link_cookie], [
++              #include <linux/fs.h>
++              void put_link(struct inode *ip, void *cookie)
++                  { return; }
++              static struct inode_operations
++                  iops __attribute__ ((unused)) = {
++                      .put_link = put_link,
++              };
++      ],[])
++
++      ZFS_LINUX_TEST_SRC([put_link_nameidata], [
++              #include <linux/fs.h>
++              void put_link(struct dentry *de, struct
++                  nameidata *nd, void *ptr) { return; }
++              static struct inode_operations
++                  iops __attribute__ ((unused)) = {
++                      .put_link = put_link,
++              };
++      ],[])
++])
++
+ AC_DEFUN([ZFS_AC_KERNEL_PUT_LINK], [
+       dnl #
+       dnl # 4.5 API change
+       dnl # get_link() uses delayed done, there is no put_link() interface.
++      dnl # This check intially uses the inode_operations_get_link result
+       dnl #
+-      ZFS_LINUX_TRY_COMPILE([
+-              #if !defined(HAVE_GET_LINK_DELAYED)
+-              #error "Expecting get_link() delayed done"
+-              #endif
+-      ],[
+-      ],[
++      ZFS_LINUX_TEST_RESULT([inode_operations_get_link], [
+               AC_DEFINE(HAVE_PUT_LINK_DELAYED, 1, [iops->put_link() delayed])
+       ],[
+               dnl #
+@@ -19,41 +37,24 @@ AC_DEFUN([ZFS_AC_KERNEL_PUT_LINK], [
+               dnl # This kernel retired the nameidata structure.
+               dnl #
+               AC_MSG_CHECKING([whether iops->put_link() passes cookie])
+-              ZFS_LINUX_TRY_COMPILE([
+-                      #include <linux/fs.h>
+-                      void put_link(struct inode *ip, void *cookie)
+-                          { return; }
+-                      static struct inode_operations
+-                          iops __attribute__ ((unused)) = {
+-                              .put_link = put_link,
+-                      };
+-              ],[
+-              ],[
++              ZFS_LINUX_TEST_RESULT([put_link_cookie], [
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_PUT_LINK_COOKIE, 1,
+                           [iops->put_link() cookie])
+               ],[
++                      AC_MSG_RESULT(no)
++
+                       dnl #
+                       dnl # 2.6.32 API
+                       dnl #
+-                      AC_MSG_RESULT(no)
+                       AC_MSG_CHECKING(
+                           [whether iops->put_link() passes nameidata])
+-                      ZFS_LINUX_TRY_COMPILE([
+-                              #include <linux/fs.h>
+-                              void put_link(struct dentry *de, struct
+-                                  nameidata *nd, void *ptr) { return; }
+-                              static struct inode_operations
+-                                  iops __attribute__ ((unused)) = {
+-                                      .put_link = put_link,
+-                              };
+-                      ],[
+-                      ],[
++                      ZFS_LINUX_TEST_RESULT([put_link_nameidata], [
+                               AC_MSG_RESULT(yes)
+                               AC_DEFINE(HAVE_PUT_LINK_NAMEIDATA, 1,
+                                   [iops->put_link() nameidata])
+                       ],[
+-                              AC_MSG_ERROR(no; please file a bug report)
++                              ZFS_LINUX_TEST_ERROR([put_link])
+                       ])
+               ])
+       ])
+diff --git a/config/kernel-rename.m4 b/config/kernel-rename.m4
+index 9f894fb4d..f70739153 100644
+--- a/config/kernel-rename.m4
++++ b/config/kernel-rename.m4
+@@ -3,9 +3,8 @@ dnl # 4.9 API change,
+ dnl # iops->rename2() merged into iops->rename(), and iops->rename() now wants
+ dnl # flags.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_RENAME_WANTS_FLAGS], [
+-      AC_MSG_CHECKING([whether iops->rename() wants flags])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME_WANTS_FLAGS], [
++      ZFS_LINUX_TEST_SRC([inode_operations_rename], [
+               #include <linux/fs.h>
+               int rename_fn(struct inode *sip, struct dentry *sdp,
+                       struct inode *tip, struct dentry *tdp,
+@@ -15,10 +14,15 @@ AC_DEFUN([ZFS_AC_KERNEL_RENAME_WANTS_FLAGS], [
+                   iops __attribute__ ((unused)) = {
+                       .rename = rename_fn,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_RENAME_WANTS_FLAGS], [
++      AC_MSG_CHECKING([whether iops->rename() wants flags])
++      ZFS_LINUX_TEST_RESULT([inode_operations_rename], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_RENAME_WANTS_FLAGS, 1, [iops->rename() wants flags])
++              AC_DEFINE(HAVE_RENAME_WANTS_FLAGS, 1,
++                  [iops->rename() wants flags])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-rw.m4 b/config/kernel-rw.m4
+index 1c8a265e0..85b47d5c6 100644
+--- a/config/kernel-rw.m4
++++ b/config/kernel-rw.m4
+@@ -3,11 +3,8 @@ 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([ZFS_AC_KERNEL_WRITE], [
+-      AC_MSG_CHECKING([whether kernel_write() takes loff_t pointer])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="-Werror"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_WRITE], [
++      ZFS_LINUX_TEST_SRC([kernel_write], [
+               #include <linux/fs.h>
+       ],[
+               struct file *file = NULL;
+@@ -17,14 +14,18 @@ AC_DEFUN([ZFS_AC_KERNEL_WRITE], [
+               ssize_t ret;
+               ret = kernel_write(file, buf, count, pos);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_WRITE], [
++      AC_MSG_CHECKING([whether kernel_write() takes loff_t pointer])
++      ZFS_LINUX_TEST_RESULT([kernel_write], [
+               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 #
+@@ -32,11 +33,8 @@ 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([ZFS_AC_KERNEL_READ], [
+-      AC_MSG_CHECKING([whether kernel_read() takes loff_t pointer])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="-Werror"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_READ], [
++      ZFS_LINUX_TEST_SRC([kernel_read], [
+               #include <linux/fs.h>
+       ],[
+               struct file *file = NULL;
+@@ -46,12 +44,26 @@ AC_DEFUN([ZFS_AC_KERNEL_READ], [
+               ssize_t ret;
+               ret = kernel_read(file, buf, count, pos);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_READ], [
++      AC_MSG_CHECKING([whether kernel_read() takes loff_t pointer])
++      ZFS_LINUX_TEST_RESULT([kernel_read], [
+               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"
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_RW], [
++      ZFS_AC_KERNEL_SRC_WRITE
++      ZFS_AC_KERNEL_SRC_READ
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_RW], [
++      ZFS_AC_KERNEL_WRITE
++      ZFS_AC_KERNEL_READ
+ ])
+diff --git a/config/kernel-rwsem.m4 b/config/kernel-rwsem.m4
+index 532c22718..67c5cf908 100644
+--- a/config/kernel-rwsem.m4
++++ b/config/kernel-rwsem.m4
+@@ -4,25 +4,26 @@ dnl #
+ dnl # The rw_semaphore.wait_lock member was changed from spinlock_t to
+ dnl # raw_spinlock_t at commit ddb6c9b58a19edcfac93ac670b066c836ff729f1.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_RWSEM_SPINLOCK_IS_RAW], [
+-      AC_MSG_CHECKING([whether struct rw_semaphore member wait_lock is raw])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="-Werror"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_RWSEM_SPINLOCK_IS_RAW], [
++      ZFS_LINUX_TEST_SRC([rwsem_spinlock_is_raw], [
+               #include <linux/rwsem.h>
+       ],[
+               struct rw_semaphore dummy_semaphore __attribute__ ((unused));
+               raw_spinlock_t dummy_lock __attribute__ ((unused)) =
+                   __RAW_SPIN_LOCK_INITIALIZER(dummy_lock);
+               dummy_semaphore.wait_lock = dummy_lock;
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_RWSEM_SPINLOCK_IS_RAW], [
++      AC_MSG_CHECKING([whether struct rw_semaphore member wait_lock is raw])
++      ZFS_LINUX_TEST_RESULT([rwsem_spinlock_is_raw], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(RWSEM_SPINLOCK_IS_RAW, 1,
+-              [struct rw_semaphore member wait_lock is raw_spinlock_t])
++                  [struct rw_semaphore member wait_lock is raw_spinlock_t])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
+ ])
+ dnl #
+@@ -30,23 +31,24 @@ dnl # 3.16 API Change
+ dnl #
+ dnl # rwsem-spinlock "->activity" changed to "->count"
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_RWSEM_ACTIVITY], [
+-      AC_MSG_CHECKING([whether struct rw_semaphore has member activity])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="-Werror"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_RWSEM_ACTIVITY], [
++      ZFS_LINUX_TEST_SRC([rwsem_activity], [
+               #include <linux/rwsem.h>
+       ],[
+               struct rw_semaphore dummy_semaphore __attribute__ ((unused));
+               dummy_semaphore.activity = 0;
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_RWSEM_ACTIVITY], [
++      AC_MSG_CHECKING([whether struct rw_semaphore has member activity])
++      ZFS_LINUX_TEST_RESULT([rwsem_activity], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_RWSEM_ACTIVITY, 1,
+-              [struct rw_semaphore has member activity])
++                  [struct rw_semaphore has member activity])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
+ ])
+ dnl #
+@@ -54,22 +56,35 @@ dnl # 4.8 API Change
+ dnl #
+ dnl # rwsem "->count" changed to atomic_long_t type
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_RWSEM_ATOMIC_LONG_COUNT], [
+-      AC_MSG_CHECKING(
+-      [whether struct rw_semaphore has atomic_long_t member count])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="-Werror"
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_RWSEM_ATOMIC_LONG_COUNT], [
++      ZFS_LINUX_TEST_SRC([rwsem_atomic_long_count], [
+               #include <linux/rwsem.h>
+       ],[
+               DECLARE_RWSEM(dummy_semaphore);
+               (void) atomic_long_read(&dummy_semaphore.count);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_RWSEM_ATOMIC_LONG_COUNT], [
++      AC_MSG_CHECKING(
++          [whether struct rw_semaphore has atomic_long_t member count])
++      ZFS_LINUX_TEST_RESULT([rwsem_atomic_long_count], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_RWSEM_ATOMIC_LONG_COUNT, 1,
+-              [struct rw_semaphore has atomic_long_t member count])
++                  [struct rw_semaphore has atomic_long_t member count])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_RWSEM], [
++      ZFS_AC_KERNEL_SRC_RWSEM_SPINLOCK_IS_RAW
++      ZFS_AC_KERNEL_SRC_RWSEM_ACTIVITY
++      ZFS_AC_KERNEL_SRC_RWSEM_ATOMIC_LONG_COUNT
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_RWSEM], [
++      ZFS_AC_KERNEL_RWSEM_SPINLOCK_IS_RAW
++      ZFS_AC_KERNEL_RWSEM_ACTIVITY
++      ZFS_AC_KERNEL_RWSEM_ATOMIC_LONG_COUNT
+ ])
+diff --git a/config/kernel-sched.m4 b/config/kernel-sched.m4
+index 640b008aa..4a7db970a 100644
+--- a/config/kernel-sched.m4
++++ b/config/kernel-sched.m4
+@@ -2,14 +2,18 @@ dnl #
+ dnl # 3.9 API change,
+ dnl # Moved things from linux/sched.h to linux/sched/rt.h
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_SCHED_RT_HEADER],
+-      [AC_MSG_CHECKING([whether header linux/sched/rt.h exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SCHED_RT_HEADER], [
++      ZFS_LINUX_TEST_SRC([sched_rt_header], [
+               #include <linux/sched.h>
+               #include <linux/sched/rt.h>
+       ],[
+               return 0;
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SCHED_RT_HEADER], [
++      AC_MSG_CHECKING([whether header linux/sched/rt.h exists])
++      ZFS_LINUX_TEST_RESULT([sched_rt_header], [
+               AC_DEFINE(HAVE_SCHED_RT_HEADER, 1, [linux/sched/rt.h exists])
+               AC_MSG_RESULT(yes)
+       ],[
+@@ -21,36 +25,59 @@ dnl #
+ dnl # 4.11 API change,
+ dnl # Moved things from linux/sched.h to linux/sched/signal.h
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_SCHED_SIGNAL_HEADER],
+-      [AC_MSG_CHECKING([whether header linux/sched/signal.h exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SCHED_SIGNAL_HEADER], [
++      ZFS_LINUX_TEST_SRC([sched_signal_header], [
+               #include <linux/sched.h>
+               #include <linux/sched/signal.h>
+       ],[
+               return 0;
+-      ],[
+-              AC_DEFINE(HAVE_SCHED_SIGNAL_HEADER, 1, [linux/sched/signal.h exists])
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SCHED_SIGNAL_HEADER], [
++      AC_MSG_CHECKING([whether header linux/sched/signal.h exists])
++      ZFS_LINUX_TEST_RESULT([sched_signal_header], [
++              AC_DEFINE(HAVE_SCHED_SIGNAL_HEADER, 1,
++                  [linux/sched/signal.h exists])
+               AC_MSG_RESULT(yes)
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+ ])
++
+ dnl #
+ dnl # 3.19 API change
+ dnl # The io_schedule_timeout() function is present in all 2.6.32 kernels
+ dnl # but it was not exported until Linux 3.19.  The RHEL 7.x kernels which
+ dnl # are based on a 3.10 kernel do export this symbol.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_IO_SCHEDULE_TIMEOUT], [
+-      AC_MSG_CHECKING([whether io_schedule_timeout() is available])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_IO_SCHEDULE_TIMEOUT], [
++      ZFS_LINUX_TEST_SRC([io_schedule_timeout], [
+               #include <linux/sched.h>
+       ], [
+               (void) io_schedule_timeout(1);
+-      ], [io_schedule_timeout], [], [
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_IO_SCHEDULE_TIMEOUT], [
++      AC_MSG_CHECKING([whether io_schedule_timeout() is available])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([io_schedule_timeout],
++      [io_schedule_timeout], [], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_IO_SCHEDULE_TIMEOUT, 1, [yes])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+ ])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SCHED], [
++      ZFS_AC_KERNEL_SRC_SCHED_RT_HEADER
++      ZFS_AC_KERNEL_SRC_SCHED_SIGNAL_HEADER
++      ZFS_AC_KERNEL_SRC_IO_SCHEDULE_TIMEOUT
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SCHED], [
++      ZFS_AC_KERNEL_SCHED_RT_HEADER
++      ZFS_AC_KERNEL_SCHED_SIGNAL_HEADER
++      ZFS_AC_KERNEL_IO_SCHEDULE_TIMEOUT
++])
+diff --git a/config/kernel-security-inode-init.m4 b/config/kernel-security-inode-init.m4
+index a62176d42..0dea7e392 100644
+--- a/config/kernel-security-inode-init.m4
++++ b/config/kernel-security-inode-init.m4
+@@ -5,9 +5,8 @@ dnl # qstr argument which must be passed in from the dentry if available.
+ dnl # Passing a NULL is safe when no qstr is available the relevant
+ dnl # security checks will just be skipped.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_6ARGS_SECURITY_INODE_INIT_SECURITY], [
+-      AC_MSG_CHECKING([whether security_inode_init_security wants 6 args])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SECURITY_INODE_INIT_SECURITY_6ARGS], [
++      ZFS_LINUX_TEST_SRC([security_inode_init_security_6args], [
+               #include <linux/security.h>
+       ],[
+               struct inode *ip __attribute__ ((unused)) = NULL;
+@@ -18,10 +17,15 @@ AC_DEFUN([ZFS_AC_KERNEL_6ARGS_SECURITY_INODE_INIT_SECURITY], [
+               size_t len __attribute__ ((unused)) = 0;
+               security_inode_init_security(ip, dip, str, &name, &value, &len);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SECURITY_INODE_INIT_SECURITY_6ARGS], [
++      AC_MSG_CHECKING([whether security_inode_init_security wants 6 args])
++      ZFS_LINUX_TEST_RESULT([security_inode_init_security_6args], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_6ARGS_SECURITY_INODE_INIT_SECURITY, 1,
+-                        [security_inode_init_security wants 6 args])
++                  [security_inode_init_security wants 6 args])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+@@ -34,9 +38,8 @@ dnl # a filesystem specific callback to write security extended attributes.
+ dnl # This was done to support the initialization of multiple LSM xattrs
+ dnl # and the EVM xattr.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_CALLBACK_SECURITY_INODE_INIT_SECURITY], [
+-      AC_MSG_CHECKING([whether security_inode_init_security wants callback])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SECURITY_INODE_INIT_SECURITY_CALLBACK], [
++      ZFS_LINUX_TEST_SRC([security_inode_init_security], [
+               #include <linux/security.h>
+       ],[
+               struct inode *ip __attribute__ ((unused)) = NULL;
+@@ -45,11 +48,26 @@ AC_DEFUN([ZFS_AC_KERNEL_CALLBACK_SECURITY_INODE_INIT_SECURITY], [
+               initxattrs func __attribute__ ((unused)) = NULL;
+               security_inode_init_security(ip, dip, str, func, NULL);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SECURITY_INODE_INIT_SECURITY_CALLBACK], [
++      AC_MSG_CHECKING([whether security_inode_init_security wants callback])
++      ZFS_LINUX_TEST_RESULT([security_inode_init_security], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_CALLBACK_SECURITY_INODE_INIT_SECURITY, 1,
+-                        [security_inode_init_security wants callback])
++                  [security_inode_init_security wants callback])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+ ])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SECURITY_INODE], [
++      ZFS_AC_KERNEL_SRC_SECURITY_INODE_INIT_SECURITY_6ARGS
++      ZFS_AC_KERNEL_SRC_SECURITY_INODE_INIT_SECURITY_CALLBACK
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SECURITY_INODE], [
++      ZFS_AC_KERNEL_SECURITY_INODE_INIT_SECURITY_6ARGS
++      ZFS_AC_KERNEL_SECURITY_INODE_INIT_SECURITY_CALLBACK
++])
+diff --git a/config/kernel-set-nlink.m4 b/config/kernel-set-nlink.m4
+index f7ffc0d3a..63a5a8c0d 100644
+--- a/config/kernel-set-nlink.m4
++++ b/config/kernel-set-nlink.m4
+@@ -2,18 +2,21 @@ dnl #
+ dnl # Linux v3.2-rc1 API change
+ dnl # SHA: bfe8684869601dacfcb2cd69ef8cfd9045f62170
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_SET_NLINK], [
+-      AC_MSG_CHECKING([whether set_nlink() is available])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SET_NLINK], [
++      ZFS_LINUX_TEST_SRC([set_nlink], [
+               #include <linux/fs.h>
+       ],[
+               struct inode node;
+               unsigned int link = 0;
+               (void) set_nlink(&node, link);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SET_NLINK], [
++      AC_MSG_CHECKING([whether set_nlink() is available])
++      ZFS_LINUX_TEST_RESULT([set_nlink], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_SET_NLINK, 1,
+-                        [set_nlink() is available])
++              AC_DEFINE(HAVE_SET_NLINK, 1, [set_nlink() is available])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-setattr-prepare.m4 b/config/kernel-setattr-prepare.m4
+index 32f7deb77..45408c45c 100644
+--- a/config/kernel-setattr-prepare.m4
++++ b/config/kernel-setattr-prepare.m4
+@@ -3,17 +3,21 @@ dnl # 4.9 API change
+ dnl # The inode_change_ok() function has been renamed setattr_prepare()
+ dnl # and updated to take a dentry rather than an inode.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_SETATTR_PREPARE],
+-      [AC_MSG_CHECKING([whether setattr_prepare() is available])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SETATTR_PREPARE], [
++      ZFS_LINUX_TEST_SRC([setattr_prepare], [
+               #include <linux/fs.h>
+       ], [
+               struct dentry *dentry = NULL;
+               struct iattr *attr = NULL;
+-              int error;
++              int error __attribute__ ((unused)) =
++                  setattr_prepare(dentry, attr);
++      ])
++])
+-              error = setattr_prepare(dentry, attr);
+-      ], [setattr_prepare], [fs/attr.c], [
++AC_DEFUN([ZFS_AC_KERNEL_SETATTR_PREPARE], [
++      AC_MSG_CHECKING([whether setattr_prepare() is available])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare],
++          [setattr_prepare], [fs/attr.c], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_SETATTR_PREPARE, 1,
+                   [setattr_prepare() is available])
+diff --git a/config/kernel-sget-args.m4 b/config/kernel-sget-args.m4
+index 9d1745925..13581399e 100644
+--- a/config/kernel-sget-args.m4
++++ b/config/kernel-sget-args.m4
+@@ -2,9 +2,8 @@ dnl #
+ dnl # 3.6 API change,
+ dnl # 'sget' now takes the mount flags as an argument.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_5ARG_SGET],
+-      [AC_MSG_CHECKING([whether sget() wants 5 args])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SGET], [
++      ZFS_LINUX_TEST_SRC([sget_5args], [
+               #include <linux/fs.h>
+       ],[
+               struct file_system_type *type = NULL;
+@@ -13,11 +12,15 @@ AC_DEFUN([ZFS_AC_KERNEL_5ARG_SGET],
+               int flags = 0;
+               void *data = NULL;
+               (void) sget(type, test, set, flags, data);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SGET], [
++      AC_MSG_CHECKING([whether sget() wants 5 args])
++      ZFS_LINUX_TEST_RESULT([sget_5args], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_5ARG_SGET, 1, [sget() wants 5 args])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+ ])
+-
+diff --git a/config/kernel-show-options.m4 b/config/kernel-show-options.m4
+index 67d683c55..9e426bc39 100644
+--- a/config/kernel-show-options.m4
++++ b/config/kernel-show-options.m4
+@@ -1,21 +1,26 @@
+ dnl #
+ dnl # Linux 3.3 API
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_SHOW_OPTIONS], [
+-      AC_MSG_CHECKING([whether sops->show_options() wants dentry])
+-
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SHOW_OPTIONS], [
++      ZFS_LINUX_TEST_SRC([super_operations_show_options], [
+               #include <linux/fs.h>
+-              int show_options (struct seq_file * x, struct dentry * y) { return 0; };
++              int show_options(struct seq_file * x, struct dentry * y) {
++                      return 0;
++              };
++
+               static struct super_operations sops __attribute__ ((unused)) = {
+                       .show_options = show_options,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SHOW_OPTIONS], [
++      AC_MSG_CHECKING([whether sops->show_options() wants dentry])
++      ZFS_LINUX_TEST_RESULT([super_operations_show_options], [
+               AC_MSG_RESULT([yes])
+               AC_DEFINE(HAVE_SHOW_OPTIONS_WITH_DENTRY, 1,
+-                      [sops->show_options() with dentry])
++                  [sops->show_options() with dentry])
+       ],[
+               AC_MSG_RESULT([no])
+       ])
+diff --git a/config/kernel-shrink.m4 b/config/kernel-shrink.m4
+index 405cbf42c..45b4b5d4b 100644
+--- a/config/kernel-shrink.m4
++++ b/config/kernel-shrink.m4
+@@ -4,9 +4,8 @@ dnl # The super_block structure now stores a per-filesystem shrinker.
+ dnl # This interface is preferable because it can be used to specifically
+ dnl # target only the zfs filesystem for pruning.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_SHRINK], [
+-      AC_MSG_CHECKING([whether super_block has s_shrink])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_SHRINK], [
++      ZFS_LINUX_TEST_SRC([super_block_s_shrink], [
+               #include <linux/fs.h>
+               int shrink(struct shrinker *s, struct shrink_control *sc)
+@@ -18,8 +17,12 @@ AC_DEFUN([ZFS_AC_KERNEL_SHRINK], [
+                       .s_shrink.seeks = DEFAULT_SEEKS,
+                       .s_shrink.batch = 0,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SUPER_BLOCK_S_SHRINK], [
++      AC_MSG_CHECKING([whether super_block has s_shrink])
++      ZFS_LINUX_TEST_RESULT([super_block_s_shrink], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_SHRINK, 1, [struct super_block has s_shrink])
+@@ -50,15 +53,18 @@ dnl # a list_head is used.  Then to prevent the spinning from occurring
+ dnl # the .next pointer is set to the fs_supers list_head which ensures
+ dnl # the iterate_supers_type() function will always terminate.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_S_INSTANCES_LIST_HEAD], [
+-      AC_MSG_CHECKING([whether super_block has s_instances list_head])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_INSTANCES_LIST_HEAD], [
++      ZFS_LINUX_TEST_SRC([super_block_s_instances_list_head], [
+               #include <linux/fs.h>
+       ],[
+               struct super_block sb __attribute__ ((unused));
+-
+               INIT_LIST_HEAD(&sb.s_instances);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SUPER_BLOCK_S_INSTANCES_LIST_HEAD], [
++      AC_MSG_CHECKING([whether super_block has s_instances list_head])
++      ZFS_LINUX_TEST_RESULT([super_block_s_instances_list_head], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_S_INSTANCES_LIST_HEAD, 1,
+                   [struct super_block has s_instances list_head])
+@@ -67,9 +73,8 @@ AC_DEFUN([ZFS_AC_KERNEL_S_INSTANCES_LIST_HEAD], [
+       ])
+ ])
+-AC_DEFUN([ZFS_AC_KERNEL_NR_CACHED_OBJECTS], [
+-      AC_MSG_CHECKING([whether sops->nr_cached_objects() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_NR_CACHED_OBJECTS], [
++      ZFS_LINUX_TEST_SRC([nr_cached_objects], [
+               #include <linux/fs.h>
+               int nr_cached_objects(struct super_block *sb) { return 0; }
+@@ -78,19 +83,22 @@ AC_DEFUN([ZFS_AC_KERNEL_NR_CACHED_OBJECTS], [
+                   sops __attribute__ ((unused)) = {
+                       .nr_cached_objects = nr_cached_objects,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_NR_CACHED_OBJECTS], [
++      AC_MSG_CHECKING([whether sops->nr_cached_objects() exists])
++      ZFS_LINUX_TEST_RESULT([nr_cached_objects], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_NR_CACHED_OBJECTS, 1,
+-                      [sops->nr_cached_objects() exists])
++                  [sops->nr_cached_objects() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+ ])
+-AC_DEFUN([ZFS_AC_KERNEL_FREE_CACHED_OBJECTS], [
+-      AC_MSG_CHECKING([whether sops->free_cached_objects() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_FREE_CACHED_OBJECTS], [
++      ZFS_LINUX_TEST_SRC([free_cached_objects], [
+               #include <linux/fs.h>
+               void free_cached_objects(struct super_block *sb, int x)
+@@ -100,11 +108,15 @@ AC_DEFUN([ZFS_AC_KERNEL_FREE_CACHED_OBJECTS], [
+                   sops __attribute__ ((unused)) = {
+                       .free_cached_objects = free_cached_objects,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_FREE_CACHED_OBJECTS], [
++      AC_MSG_CHECKING([whether sops->free_cached_objects() exists])
++      ZFS_LINUX_TEST_RESULT([free_cached_objects], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_FREE_CACHED_OBJECTS, 1,
+-                      [sops->free_cached_objects() exists])
++                  [sops->free_cached_objects() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+@@ -115,15 +127,19 @@ dnl # 3.12 API change
+ dnl # The nid member was added to struct shrink_control to support
+ dnl # NUMA-aware shrinkers.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_SHRINK_CONTROL_HAS_NID], [
+-      AC_MSG_CHECKING([whether shrink_control has nid])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINK_CONTROL_HAS_NID], [
++      ZFS_LINUX_TEST_SRC([shrink_control_nid], [
+               #include <linux/fs.h>
+       ],[
+               struct shrink_control sc __attribute__ ((unused));
+               unsigned long scnidsize __attribute__ ((unused)) =
+                   sizeof(sc.nid);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SHRINK_CONTROL_HAS_NID], [
++      AC_MSG_CHECKING([whether shrink_control has nid])
++      ZFS_LINUX_TEST_RESULT([shrink_control_nid], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(SHRINK_CONTROL_HAS_NID, 1,
+                   [struct shrink_control has nid])
+@@ -132,84 +148,96 @@ AC_DEFUN([ZFS_AC_KERNEL_SHRINK_CONTROL_HAS_NID], [
+       ])
+ ])
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINKER_CALLBACK], [
++      ZFS_LINUX_TEST_SRC([shrinker_cb_2arg], [
++              #include <linux/mm.h>
++              int shrinker_cb(int nr_to_scan, gfp_t gfp_mask) { return 0; }
++      ],[
++              struct shrinker cache_shrinker = {
++                      .shrink = shrinker_cb,
++                      .seeks = DEFAULT_SEEKS,
++              };
++              register_shrinker(&cache_shrinker);
++      ])
+-AC_DEFUN([ZFS_AC_KERNEL_SHRINKER_CALLBACK],[
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="-Werror"
+-      dnl #
+-      dnl # 2.6.23 to 2.6.34 API change
+-      dnl # ->shrink(int nr_to_scan, gfp_t gfp_mask)
+-      dnl #
+-      AC_MSG_CHECKING([whether old 2-argument shrinker exists])
+-      ZFS_LINUX_TRY_COMPILE([
++      ZFS_LINUX_TEST_SRC([shrinker_cb_3arg], [
+               #include <linux/mm.h>
++              int shrinker_cb(struct shrinker *shrink, int nr_to_scan,
++                  gfp_t gfp_mask) { return 0; }
++      ],[
++              struct shrinker cache_shrinker = {
++                      .shrink = shrinker_cb,
++                      .seeks = DEFAULT_SEEKS,
++              };
++              register_shrinker(&cache_shrinker);
++      ])
+-              int shrinker_cb(int nr_to_scan, gfp_t gfp_mask) {
+-                      return 0;
+-              }
++      ZFS_LINUX_TEST_SRC([shrinker_cb_shrink_control], [
++              #include <linux/mm.h>
++              int shrinker_cb(struct shrinker *shrink,
++                  struct shrink_control *sc) { return 0; }
+       ],[
+               struct shrinker cache_shrinker = {
+                       .shrink = shrinker_cb,
+                       .seeks = DEFAULT_SEEKS,
+               };
+               register_shrinker(&cache_shrinker);
++      ])
++
++      ZFS_LINUX_TEST_SRC([shrinker_cb_shrink_control_split], [
++              #include <linux/mm.h>
++              unsigned long shrinker_cb(struct shrinker *shrink,
++                  struct shrink_control *sc) { return 0; }
+       ],[
++              struct shrinker cache_shrinker = {
++                      .count_objects = shrinker_cb,
++                      .scan_objects = shrinker_cb,
++                      .seeks = DEFAULT_SEEKS,
++              };
++              register_shrinker(&cache_shrinker);
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SHRINKER_CALLBACK],[
++      dnl #
++      dnl # 2.6.23 to 2.6.34 API change
++      dnl # ->shrink(int nr_to_scan, gfp_t gfp_mask)
++      dnl #
++      AC_MSG_CHECKING([whether old 2-argument shrinker exists])
++      ZFS_LINUX_TEST_RESULT([shrinker_cb_2arg], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_2ARGS_OLD_SHRINKER_CALLBACK, 1,
+-                      [old shrinker callback wants 2 args])
++                  [old shrinker callback wants 2 args])
+       ],[
+               AC_MSG_RESULT(no)
++
+               dnl #
+               dnl # 2.6.35 - 2.6.39 API change
+               dnl # ->shrink(struct shrinker *,
+               dnl #          int nr_to_scan, gfp_t gfp_mask)
+               dnl #
+               AC_MSG_CHECKING([whether old 3-argument shrinker exists])
+-              ZFS_LINUX_TRY_COMPILE([
+-                      #include <linux/mm.h>
+-
+-                      int shrinker_cb(struct shrinker *shrink, int nr_to_scan,
+-                                      gfp_t gfp_mask) {
+-                              return 0;
+-                      }
+-              ],[
+-                      struct shrinker cache_shrinker = {
+-                              .shrink = shrinker_cb,
+-                              .seeks = DEFAULT_SEEKS,
+-                      };
+-                      register_shrinker(&cache_shrinker);
+-              ],[
++              ZFS_LINUX_TEST_RESULT([shrinker_cb_3arg], [
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_3ARGS_SHRINKER_CALLBACK, 1,
+                               [old shrinker callback wants 3 args])
+               ],[
+                       AC_MSG_RESULT(no)
++
+                       dnl #
+                       dnl # 3.0 - 3.11 API change
+                       dnl # ->shrink(struct shrinker *,
+                       dnl #          struct shrink_control *sc)
+                       dnl #
+                       AC_MSG_CHECKING(
+-                              [whether new 2-argument shrinker exists])
+-                      ZFS_LINUX_TRY_COMPILE([
+-                              #include <linux/mm.h>
+-
+-                              int shrinker_cb(struct shrinker *shrink,
+-                                              struct shrink_control *sc) {
+-                                      return 0;
+-                              }
+-                      ],[
+-                              struct shrinker cache_shrinker = {
+-                                      .shrink = shrinker_cb,
+-                                      .seeks = DEFAULT_SEEKS,
+-                              };
+-                              register_shrinker(&cache_shrinker);
+-                      ],[
++                          [whether new 2-argument shrinker exists])
++                      ZFS_LINUX_TEST_RESULT([shrinker_cb_shrink_control], [
+                               AC_MSG_RESULT(yes)
+                               AC_DEFINE(HAVE_2ARGS_NEW_SHRINKER_CALLBACK, 1,
+                                       [new shrinker callback wants 2 args])
+                       ],[
+                               AC_MSG_RESULT(no)
++
+                               dnl #
+                               dnl # 3.12 API change,
+                               dnl # ->shrink() is logically split in to
+@@ -217,52 +245,61 @@ AC_DEFUN([ZFS_AC_KERNEL_SHRINKER_CALLBACK],[
+                               dnl #
+                               AC_MSG_CHECKING(
+                                   [whether ->count_objects callback exists])
+-                              ZFS_LINUX_TRY_COMPILE([
+-                                      #include <linux/mm.h>
+-
+-                                      unsigned long shrinker_cb(
+-                                              struct shrinker *shrink,
+-                                              struct shrink_control *sc) {
+-                                              return 0;
+-                                      }
+-                              ],[
+-                                      struct shrinker cache_shrinker = {
+-                                              .count_objects = shrinker_cb,
+-                                              .scan_objects = shrinker_cb,
+-                                              .seeks = DEFAULT_SEEKS,
+-                                      };
+-                                      register_shrinker(&cache_shrinker);
+-                              ],[
++                              ZFS_LINUX_TEST_RESULT(
++                                  [shrinker_cb_shrink_control_split], [
+                                       AC_MSG_RESULT(yes)
+                                       AC_DEFINE(HAVE_SPLIT_SHRINKER_CALLBACK,
+                                               1, [->count_objects exists])
+                               ],[
+-                                      AC_MSG_ERROR(error)
++                                      ZFS_LINUX_TEST_ERROR([shrinker])
+                               ])
+                       ])
+               ])
+       ])
+-      EXTRA_KCFLAGS="$tmp_flags"
+ ])
+ dnl #
+ dnl # 2.6.39 API change,
+ dnl # Shrinker adjust to use common shrink_control structure.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_SHRINK_CONTROL_STRUCT], [
+-      AC_MSG_CHECKING([whether struct shrink_control exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINK_CONTROL_STRUCT], [
++      ZFS_LINUX_TEST_SRC([shrink_control_struct], [
+               #include <linux/mm.h>
+       ],[
+               struct shrink_control sc __attribute__ ((unused));
+               sc.nr_to_scan = 0;
+               sc.gfp_mask = GFP_KERNEL;
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SHRINK_CONTROL_STRUCT], [
++      AC_MSG_CHECKING([whether struct shrink_control exists])
++      ZFS_LINUX_TEST_RESULT([shrink_control_struct], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_SHRINK_CONTROL_STRUCT, 1,
+-                      [struct shrink_control exists])
++                  [struct shrink_control exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+ ])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINKER], [
++      ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_SHRINK
++      ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_INSTANCES_LIST_HEAD
++      ZFS_AC_KERNEL_SRC_NR_CACHED_OBJECTS
++      ZFS_AC_KERNEL_SRC_FREE_CACHED_OBJECTS
++      ZFS_AC_KERNEL_SRC_SHRINK_CONTROL_HAS_NID
++      ZFS_AC_KERNEL_SRC_SHRINKER_CALLBACK
++      ZFS_AC_KERNEL_SRC_SHRINK_CONTROL_STRUCT
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SHRINKER], [
++      ZFS_AC_KERNEL_SUPER_BLOCK_S_SHRINK
++      ZFS_AC_KERNEL_SUPER_BLOCK_S_INSTANCES_LIST_HEAD
++      ZFS_AC_KERNEL_NR_CACHED_OBJECTS
++      ZFS_AC_KERNEL_FREE_CACHED_OBJECTS
++      ZFS_AC_KERNEL_SHRINK_CONTROL_HAS_NID
++      ZFS_AC_KERNEL_SHRINKER_CALLBACK
++      ZFS_AC_KERNEL_SHRINK_CONTROL_STRUCT
++])
+diff --git a/config/kernel-submit_bio.m4 b/config/kernel-submit_bio.m4
+index da5f85ca7..cf80e9b83 100644
+--- a/config/kernel-submit_bio.m4
++++ b/config/kernel-submit_bio.m4
+@@ -3,15 +3,19 @@ dnl # 4.8 API change
+ dnl # The rw argument has been removed from submit_bio/submit_bio_wait.
+ dnl # Callers are now expected to set bio->bi_rw instead of passing it in.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_SUBMIT_BIO], [
+-      AC_MSG_CHECKING([whether submit_bio() wants 1 arg])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SUBMIT_BIO], [
++      ZFS_LINUX_TEST_SRC([submit_bio], [
+               #include <linux/bio.h>
+       ],[
+               blk_qc_t blk_qc;
+               struct bio *bio = NULL;
+               blk_qc = submit_bio(bio);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SUBMIT_BIO], [
++      AC_MSG_CHECKING([whether submit_bio() wants 1 arg])
++      ZFS_LINUX_TEST_RESULT([submit_bio], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_1ARG_SUBMIT_BIO, 1, [submit_bio() wants 1 arg])
+       ],[
+diff --git a/config/kernel-super-userns.m4 b/config/kernel-super-userns.m4
+index de94ad967..1ad35f2d1 100644
+--- a/config/kernel-super-userns.m4
++++ b/config/kernel-super-userns.m4
+@@ -3,15 +3,19 @@ dnl # 4.8 API change
+ dnl # struct user_namespace was added to struct super_block as
+ dnl # super->s_user_ns member
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_SUPER_USER_NS], [
+-      AC_MSG_CHECKING([whether super_block->s_user_ns exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_SUPER_USER_NS], [
++      ZFS_LINUX_TEST_SRC([super_user_ns], [
+               #include <linux/fs.h>
+               #include <linux/user_namespace.h>
+-      ],[
++      ], [
+               struct super_block super;
+               super.s_user_ns = (struct user_namespace *)NULL;
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SUPER_USER_NS], [
++      AC_MSG_CHECKING([whether super_block->s_user_ns exists])
++      ZFS_LINUX_TEST_RESULT([super_user_ns], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_SUPER_USER_NS, 1,
+                   [super_block->s_user_ns exists])
+diff --git a/config/kernel-timer.m4 b/config/kernel-timer.m4
+index b0e1afa15..5e8fc0d3a 100644
+--- a/config/kernel-timer.m4
++++ b/config/kernel-timer.m4
+@@ -8,13 +8,9 @@ dnl # kernels that support the new timer_list.func signature.
+ dnl #
+ dnl # Also check for the existance of flags in struct timer_list, they were
+ dnl # added in 4.1-rc8 via 0eeda71bc30d.
+-
+-AC_DEFUN([ZFS_AC_KERNEL_TIMER_SETUP], [
+-      AC_MSG_CHECKING([whether timer_setup() is available])
+-      tmp_flags="$EXTRA_KCFLAGS"
+-      EXTRA_KCFLAGS="-Werror"
+-
+-      ZFS_LINUX_TRY_COMPILE([
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_TIMER_SETUP], [
++      ZFS_LINUX_TEST_SRC([timer_setup], [
+               #include <linux/timer.h>
+               struct my_task_timer {
+@@ -24,13 +20,34 @@ AC_DEFUN([ZFS_AC_KERNEL_TIMER_SETUP], [
+               void task_expire(struct timer_list *tl)
+               {
+-                      struct my_task_timer *task_timer = from_timer(task_timer, tl, timer);
++                      struct my_task_timer *task_timer =
++                          from_timer(task_timer, tl, timer);
+                       task_timer->data = 42;
+               }
+       ],[
+               struct my_task_timer task_timer;
+               timer_setup(&task_timer.timer, task_expire, 0);
++      ])
++
++      ZFS_LINUX_TEST_SRC([timer_list_function], [
++              #include <linux/timer.h>
++              void task_expire(struct timer_list *tl) {}
+       ],[
++              struct timer_list tl;
++              tl.function = task_expire;
++      ])
++
++      ZFS_LINUX_TEST_SRC([timer_list_flags], [
++              #include <linux/timer.h>
++      ],[
++              struct timer_list tl;
++              tl.flags = 2;
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_TIMER_SETUP], [
++      AC_MSG_CHECKING([whether timer_setup() is available])
++      ZFS_LINUX_TEST_RESULT([timer_setup], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_KERNEL_TIMER_SETUP, 1,
+                   [timer_setup() is available])
+@@ -39,14 +56,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TIMER_SETUP], [
+       ])
+       AC_MSG_CHECKING([whether timer function expects timer_list])
+-
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/timer.h>
+-              void task_expire(struct timer_list *tl) {}
+-      ],[
+-              struct timer_list tl;
+-              tl.function = task_expire;
+-      ],[
++      ZFS_LINUX_TEST_RESULT([timer_list_function], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST, 1,
+                   [timer_list.function gets a timer_list])
+@@ -55,19 +65,11 @@ AC_DEFUN([ZFS_AC_KERNEL_TIMER_SETUP], [
+       ])
+       AC_MSG_CHECKING([whether struct timer_list has flags])
+-
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/timer.h>
+-      ],[
+-              struct timer_list tl;
+-              tl.flags = 2;
+-      ],[
++      ZFS_LINUX_TEST_RESULT([timer_list_flags], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_KERNEL_TIMER_LIST_FLAGS, 1,
+                   [struct timer_list has a flags member])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+-
+-      EXTRA_KCFLAGS="$tmp_flags"
+ ])
+diff --git a/config/kernel-tmpfile.m4 b/config/kernel-tmpfile.m4
+index 5aad90450..f510bfe6b 100644
+--- a/config/kernel-tmpfile.m4
++++ b/config/kernel-tmpfile.m4
+@@ -2,9 +2,8 @@ dnl #
+ dnl # 3.11 API change
+ dnl # Add support for i_op->tmpfile
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_TMPFILE], [
+-      AC_MSG_CHECKING([whether i_op->tmpfile() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_TMPFILE], [
++      ZFS_LINUX_TEST_SRC([inode_operations_tmpfile], [
+               #include <linux/fs.h>
+               int tmpfile(struct inode *inode, struct dentry *dentry,
+                   umode_t mode) { return 0; }
+@@ -12,11 +11,14 @@ AC_DEFUN([ZFS_AC_KERNEL_TMPFILE], [
+                   iops __attribute__ ((unused)) = {
+                       .tmpfile = tmpfile,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_TMPFILE], [
++      AC_MSG_CHECKING([whether i_op->tmpfile() exists])
++      ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_TMPFILE, 1,
+-                  [i_op->tmpfile() exists])
++              AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-totalhigh_pages.m4 b/config/kernel-totalhigh_pages.m4
+index b22e86d4d..4ecb03a50 100644
+--- a/config/kernel-totalhigh_pages.m4
++++ b/config/kernel-totalhigh_pages.m4
+@@ -1,16 +1,18 @@
+ dnl #
+ dnl # 5.0 API change
+ dnl #
+-dnl # ca79b0c211af mm: convert totalram_pages and totalhigh_pages variables to atomic
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_TOTALHIGH_PAGES], [
+-      AC_MSG_CHECKING([whether totalhigh_pages() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_TOTALHIGH_PAGES], [
++      ZFS_LINUX_TEST_SRC([totalhigh_pages], [
+               #include <linux/highmem.h>
+       ],[
+               unsigned long pages __attribute__ ((unused));
+               pages = totalhigh_pages();
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_TOTALHIGH_PAGES], [
++      AC_MSG_CHECKING([whether totalhigh_pages() exists])
++      ZFS_LINUX_TEST_RESULT([totalhigh_pages], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_TOTALHIGH_PAGES, 1, [totalhigh_pages() exists])
+       ],[
+diff --git a/config/kernel-totalram-pages-func.m4 b/config/kernel-totalram-pages-func.m4
+index a6eac6454..d0e812a8d 100644
+--- a/config/kernel-totalram-pages-func.m4
++++ b/config/kernel-totalram-pages-func.m4
+@@ -2,16 +2,21 @@ dnl #
+ dnl # Linux 5.0: totalram_pages is no longer a global variable, and must be
+ dnl # read via the totalram_pages() helper function.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_TOTALRAM_PAGES_FUNC], [
+-      AC_MSG_CHECKING([whether totalram_pages() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_TOTALRAM_PAGES_FUNC], [
++      ZFS_LINUX_TEST_SRC([totalram_pages], [
+               #include <linux/mm.h>
+       ],[
+               unsigned long pages __attribute__ ((unused));
+               pages = totalram_pages();
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_TOTALRAM_PAGES_FUNC], [
++      AC_MSG_CHECKING([whether totalram_pages() exists])
++      ZFS_LINUX_TEST_RESULT([totalram_pages], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_TOTALRAM_PAGES_FUNC, 1, [kernel has totalram_pages()])
++              AC_DEFINE(HAVE_TOTALRAM_PAGES_FUNC, 1,
++                  [kernel has totalram_pages()])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-truncate-range.m4 b/config/kernel-truncate-range.m4
+index da2cb50fc..8fdbb1086 100644
+--- a/config/kernel-truncate-range.m4
++++ b/config/kernel-truncate-range.m4
+@@ -4,17 +4,20 @@ dnl # torvalds/linux@17cf28afea2a1112f240a3a2da8af883be024811 removed
+ dnl # truncate_range(). The file hole punching functionality is now
+ dnl # provided by fallocate()
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_TRUNCATE_RANGE], [
+-      AC_MSG_CHECKING([whether iops->truncate_range() exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_TRUNCATE_RANGE], [
++      ZFS_LINUX_TEST_SRC([inode_operations_truncate_range], [
+               #include <linux/fs.h>
+               void truncate_range(struct inode *inode, loff_t start,
+                                   loff_t end) { return; }
+               static struct inode_operations iops __attribute__ ((unused)) = {
+                       .truncate_range = truncate_range,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_TRUNCATE_RANGE], [
++      AC_MSG_CHECKING([whether iops->truncate_range() exists])
++      ZFS_LINUX_TEST_RESULT([inode_operations_truncate_range], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_INODE_TRUNCATE_RANGE, 1,
+                         [iops->truncate_range() exists])
+diff --git a/config/kernel-truncate-setsize.m4 b/config/kernel-truncate-setsize.m4
+index 7e4aff479..e719c1444 100644
+--- a/config/kernel-truncate-setsize.m4
++++ b/config/kernel-truncate-setsize.m4
+@@ -2,16 +2,21 @@ dnl #
+ dnl # 2.6.35 API change
+ dnl # Added truncate_setsize() helper function.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_TRUNCATE_SETSIZE],
+-      [AC_MSG_CHECKING([whether truncate_setsize() is available])
+-      ZFS_LINUX_TRY_COMPILE_SYMBOL([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_TRUNCATE_SETSIZE], [
++      ZFS_LINUX_TEST_SRC([truncate_setsize], [
+               #include <linux/mm.h>
+       ], [
+               truncate_setsize(NULL, 0);
+-      ], [truncate_setsize], [mm/truncate.c], [
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_TRUNCATE_SETSIZE], [
++      AC_MSG_CHECKING([whether truncate_setsize() is available])
++      ZFS_LINUX_TEST_RESULT_SYMBOL([truncate_setsize],
++          [truncate_setsize], [mm/truncate.c], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_TRUNCATE_SETSIZE, 1,
+-                        [truncate_setsize() is available])
++                  [truncate_setsize() is available])
+       ], [
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-userns-capabilities.m4 b/config/kernel-userns-capabilities.m4
+index fa3381978..5dcbc03d3 100644
+--- a/config/kernel-userns-capabilities.m4
++++ b/config/kernel-userns-capabilities.m4
+@@ -2,16 +2,19 @@ dnl #
+ dnl # 2.6.38 API change
+ dnl # ns_capable() was introduced
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_NS_CAPABLE], [
+-      AC_MSG_CHECKING([whether ns_capable exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_NS_CAPABLE], [
++      ZFS_LINUX_TEST_SRC([ns_capable], [
+               #include <linux/capability.h>
+       ],[
+               ns_capable((struct user_namespace *)NULL, CAP_SYS_ADMIN);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_NS_CAPABLE], [
++      AC_MSG_CHECKING([whether ns_capable exists])
++      ZFS_LINUX_TEST_RESULT([ns_capable], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_NS_CAPABLE, 1,
+-                  [ns_capable exists])
++              AC_DEFINE(HAVE_NS_CAPABLE, 1, [ns_capable exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+@@ -23,17 +26,20 @@ dnl # struct user_namespace was added to struct cred_t as
+ dnl # cred->user_ns member
+ dnl # Note that current_user_ns() was added in 2.6.28.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_CRED_USER_NS], [
+-      AC_MSG_CHECKING([whether cred_t->user_ns exists])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_CRED_USER_NS], [
++      ZFS_LINUX_TEST_SRC([cred_user_ns], [
+               #include <linux/cred.h>
+       ],[
+               struct cred cr;
+               cr.user_ns = (struct user_namespace *)NULL;
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_CRED_USER_NS], [
++      AC_MSG_CHECKING([whether cred_t->user_ns exists])
++      ZFS_LINUX_TEST_RESULT([cred_user_ns], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_CRED_USER_NS, 1,
+-                  [cred_t->user_ns exists])
++              AC_DEFINE(HAVE_CRED_USER_NS, 1, [cred_t->user_ns exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+@@ -44,14 +50,18 @@ dnl # 3.4 API change
+ dnl # kuid_has_mapping() and kgid_has_mapping() were added to distinguish
+ dnl # between internal kernel uids/gids and user namespace uids/gids.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_KUID_HAS_MAPPING], [
+-      AC_MSG_CHECKING([whether kuid_has_mapping/kgid_has_mapping exist])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_KUID_HAS_MAPPING], [
++      ZFS_LINUX_TEST_SRC([kuid_has_mapping], [
+               #include <linux/uidgid.h>
+       ],[
+               kuid_has_mapping((struct user_namespace *)NULL, KUIDT_INIT(0));
+               kgid_has_mapping((struct user_namespace *)NULL, KGIDT_INIT(0));
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_KUID_HAS_MAPPING], [
++      AC_MSG_CHECKING([whether kuid_has_mapping/kgid_has_mapping exist])
++      ZFS_LINUX_TEST_RESULT([kuid_has_mapping], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_KUID_HAS_MAPPING, 1,
+                   [kuid_has_mapping/kgid_has_mapping exist])
+@@ -60,6 +70,12 @@ AC_DEFUN([ZFS_AC_KERNEL_KUID_HAS_MAPPING], [
+       ])
+ ])
++AC_DEFUN([ZFS_AC_KERNEL_SRC_USERNS_CAPABILITIES], [
++      ZFS_AC_KERNEL_SRC_NS_CAPABLE
++      ZFS_AC_KERNEL_SRC_CRED_USER_NS
++      ZFS_AC_KERNEL_SRC_KUID_HAS_MAPPING
++])
++
+ AC_DEFUN([ZFS_AC_KERNEL_USERNS_CAPABILITIES], [
+       ZFS_AC_KERNEL_NS_CAPABLE
+       ZFS_AC_KERNEL_CRED_USER_NS
+diff --git a/config/kernel-urange-sleep.m4 b/config/kernel-usleep_range.m4
+similarity index 60%
+rename from config/kernel-urange-sleep.m4
+rename to config/kernel-usleep_range.m4
+index b5764de3e..5bf051ab4 100644
+--- a/config/kernel-urange-sleep.m4
++++ b/config/kernel-usleep_range.m4
+@@ -1,20 +1,23 @@
+ dnl #
+-dnl # 2.6.36 API compatibility.
+-dnl # Added usleep_range timer.
++dnl # 2.6.36 API compatibility- Added usleep_range timer.
++dnl #
+ dnl # usleep_range is a finer precision implementation of msleep
+ dnl # designed to be a drop-in replacement for udelay where a precise
+ dnl # sleep / busy-wait is unnecessary.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_USLEEP_RANGE], [
+-      AC_MSG_CHECKING([whether usleep_range() is available])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_USLEEP_RANGE], [
++      ZFS_LINUX_TEST_SRC([usleep_range], [
+               #include <linux/delay.h>
+       ],[
+               usleep_range(0, 0);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_USLEEP_RANGE], [
++      AC_MSG_CHECKING([whether usleep_range() is available])
++      ZFS_LINUX_TEST_RESULT([usleep_range], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_USLEEP_RANGE, 1,
+-                        [usleep_range is available])
++              AC_DEFINE(HAVE_USLEEP_RANGE, 1, [usleep_range is available])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-vfs-direct_IO.m4 b/config/kernel-vfs-direct_IO.m4
+index cc50bfbe4..82583d52f 100644
+--- a/config/kernel-vfs-direct_IO.m4
++++ b/config/kernel-vfs-direct_IO.m4
+@@ -1,9 +1,8 @@
+ dnl #
+-dnl # Linux 4.6.x API change
++dnl # Check for direct IO interfaces.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER], [
+-      AC_MSG_CHECKING([whether aops->direct_IO() uses iov_iter])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_DIRECT_IO], [
++      ZFS_LINUX_TEST_SRC([direct_io_iter], [
+               #include <linux/fs.h>
+               ssize_t test_direct_IO(struct kiocb *kiocb,
+@@ -13,24 +12,9 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER], [
+                   aops __attribute__ ((unused)) = {
+                       .direct_IO = test_direct_IO,
+               };
+-      ],[
+-      ],[
+-              AC_MSG_RESULT([yes])
+-              AC_DEFINE(HAVE_VFS_DIRECT_IO_ITER, 1,
+-                  [aops->direct_IO() uses iov_iter without rw])
+-              zfs_ac_direct_io="yes"
+-      ],[
+-              AC_MSG_RESULT([no])
+-      ])
+-])
++      ],[])
+-dnl #
+-dnl # Linux 4.1.x API change
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER_OFFSET], [
+-      AC_MSG_CHECKING(
+-          [whether aops->direct_IO() uses iov_iter with offset])
+-      ZFS_LINUX_TRY_COMPILE([
++      ZFS_LINUX_TEST_SRC([direct_io_iter_offset], [
+               #include <linux/fs.h>
+               ssize_t test_direct_IO(struct kiocb *kiocb,
+@@ -40,24 +24,9 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER_OFFSET], [
+                   aops __attribute__ ((unused)) = {
+                       .direct_IO = test_direct_IO,
+               };
+-      ],[
+-      ],[
+-              AC_MSG_RESULT([yes])
+-              AC_DEFINE(HAVE_VFS_DIRECT_IO_ITER_OFFSET, 1,
+-                  [aops->direct_IO() uses iov_iter with offset])
+-              zfs_ac_direct_io="yes"
+-      ],[
+-              AC_MSG_RESULT([no])
+-      ])
+-])
++      ],[])
+-dnl #
+-dnl # Linux 3.16.x API change
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER_RW_OFFSET], [
+-      AC_MSG_CHECKING(
+-          [whether aops->direct_IO() uses iov_iter with rw and offset])
+-      ZFS_LINUX_TRY_COMPILE([
++      ZFS_LINUX_TEST_SRC([direct_io_iter_rw_offset], [
+               #include <linux/fs.h>
+               ssize_t test_direct_IO(int rw, struct kiocb *kiocb,
+@@ -67,23 +36,9 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER_RW_OFFSET], [
+                   aops __attribute__ ((unused)) = {
+                   .direct_IO = test_direct_IO,
+               };
+-      ],[
+-      ],[
+-              AC_MSG_RESULT([yes])
+-              AC_DEFINE(HAVE_VFS_DIRECT_IO_ITER_RW_OFFSET, 1,
+-                  [aops->direct_IO() uses iov_iter with rw and offset])
+-              zfs_ac_direct_io="yes"
+-      ],[
+-              AC_MSG_RESULT([no])
+-      ])
+-])
++      ],[])
+-dnl #
+-dnl # Ancient Linux API (predates git)
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_IOVEC], [
+-      AC_MSG_CHECKING([whether aops->direct_IO() uses iovec])
+-      ZFS_LINUX_TRY_COMPILE([
++      ZFS_LINUX_TEST_SRC([direct_io_iovec], [
+               #include <linux/fs.h>
+               ssize_t test_direct_IO(int rw, struct kiocb *kiocb,
+@@ -94,37 +49,61 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_IOVEC], [
+                   aops __attribute__ ((unused)) = {
+                   .direct_IO = test_direct_IO,
+               };
+-      ],[
+-      ],[
+-              AC_MSG_RESULT([yes])
+-              AC_DEFINE(HAVE_VFS_DIRECT_IO_IOVEC, 1,
+-                  [aops->direct_IO() uses iovec])
+-              zfs_ac_direct_io="yes"
+-      ],[
+-              AC_MSG_RESULT([no])
+-      ])
++      ],[])
+ ])
+ AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO], [
+-      zfs_ac_direct_io="no"
+-
+-      if test "$zfs_ac_direct_io" = "no"; then
+-              ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER
+-      fi
+-
+-      if test "$zfs_ac_direct_io" = "no"; then
+-              ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER_OFFSET
+-      fi
+-
+-      if test "$zfs_ac_direct_io" = "no"; then
+-              ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER_RW_OFFSET
+-      fi
+-
+-      if test "$zfs_ac_direct_io" = "no"; then
+-              ZFS_AC_KERNEL_VFS_DIRECT_IO_IOVEC
+-      fi
++      dnl #
++      dnl # Linux 4.6.x API change
++      dnl #
++      AC_MSG_CHECKING([whether aops->direct_IO() uses iov_iter])
++      ZFS_LINUX_TEST_RESULT([direct_io_iter], [
++              AC_MSG_RESULT([yes])
++              AC_DEFINE(HAVE_VFS_DIRECT_IO_ITER, 1,
++                  [aops->direct_IO() uses iov_iter without rw])
++      ],[
++              AC_MSG_RESULT([no])
+-      if test "$zfs_ac_direct_io" = "no"; then
+-              AC_MSG_ERROR([no; unknown direct IO interface])
+-      fi
++              dnl #
++              dnl # Linux 4.1.x API change
++              dnl #
++              AC_MSG_CHECKING(
++                  [whether aops->direct_IO() uses offset])
++              ZFS_LINUX_TEST_RESULT([direct_io_iter_offset], [
++                      AC_MSG_RESULT([yes])
++                      AC_DEFINE(HAVE_VFS_DIRECT_IO_ITER_OFFSET, 1,
++                          [aops->direct_IO() uses iov_iter with offset])
++
++              ],[
++                      AC_MSG_RESULT([no])
++
++                      dnl #
++                      dnl # Linux 3.16.x API change
++                      dnl #
++                      AC_MSG_CHECKING(
++                          [whether aops->direct_IO() uses rw and offset])
++                      ZFS_LINUX_TEST_RESULT([direct_io_iter_rw_offset], [
++                              AC_MSG_RESULT([yes])
++                              AC_DEFINE(HAVE_VFS_DIRECT_IO_ITER_RW_OFFSET, 1,
++                                  [aops->direct_IO() uses iov_iter with ]
++                                  [rw and offset])
++                      ],[
++                              AC_MSG_RESULT([no])
++
++                              dnl #
++                              dnl # Ancient Linux API (predates git)
++                              dnl #
++                              AC_MSG_CHECKING(
++                                  [whether aops->direct_IO() uses iovec])
++                              ZFS_LINUX_TEST_RESULT([direct_io_iovec], [
++                                      AC_MSG_RESULT([yes])
++                                      AC_DEFINE(HAVE_VFS_DIRECT_IO_IOVEC, 1,
++                                          [aops->direct_IO() uses iovec])
++                              ],[
++                                      ZFS_LINUX_TEST_ERROR([direct IO])
++                                      AC_MSG_RESULT([no])
++                              ])
++                      ])
++              ])
++      ])
+ ])
+diff --git a/config/kernel-vfs-fsync.m4 b/config/kernel-vfs-fsync.m4
+index a474f9f17..18a60d29a 100644
+--- a/config/kernel-vfs-fsync.m4
++++ b/config/kernel-vfs-fsync.m4
+@@ -2,13 +2,17 @@ dnl #
+ dnl # 2.6.35 API change,
+ dnl # Unused 'struct dentry *' removed from vfs_fsync() prototype.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_2ARGS_VFS_FSYNC], [
+-      AC_MSG_CHECKING([whether vfs_fsync() wants 2 args])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_FSYNC_2ARGS], [
++      ZFS_LINUX_TEST_SRC([vfs_fsync_2args], [
+               #include <linux/fs.h>
+       ],[
+               vfs_fsync(NULL, 0);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_VFS_FSYNC_2ARGS], [
++      AC_MSG_CHECKING([whether vfs_fsync() wants 2 args])
++      ZFS_LINUX_TEST_RESULT([vfs_fsync_2args], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_2ARGS_VFS_FSYNC, 1, [vfs_fsync() wants 2 args])
+       ],[
+diff --git a/config/kernel-vfs-getattr.m4 b/config/kernel-vfs-getattr.m4
+index b13723538..eb07853cc 100644
+--- a/config/kernel-vfs-getattr.m4
++++ b/config/kernel-vfs-getattr.m4
+@@ -2,19 +2,23 @@ dnl #
+ dnl # 4.11 API, a528d35e@torvalds/linux
+ dnl # vfs_getattr(const struct path *p, struct kstat *s, u32 m, unsigned int f)
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_4ARGS_VFS_GETATTR], [
+-      AC_MSG_CHECKING([whether vfs_getattr() wants 4 args])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_GETATTR_4ARGS], [
++      ZFS_LINUX_TEST_SRC([vfs_getattr_4args], [
+               #include <linux/fs.h>
+       ],[
+               vfs_getattr((const struct path *)NULL,
+                       (struct kstat *)NULL,
+                       (u32)0,
+                       (unsigned int)0);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_VFS_GETATTR_4ARGS], [
++      AC_MSG_CHECKING([whether vfs_getattr() wants 4 args])
++      ZFS_LINUX_TEST_RESULT([vfs_getattr_4args], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_4ARGS_VFS_GETATTR, 1,
+-                [vfs_getattr wants 4 args])
++                  [vfs_getattr wants 4 args])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+@@ -24,17 +28,21 @@ dnl #
+ dnl # 3.9 API
+ dnl # vfs_getattr(struct path *p, struct kstat *s)
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_2ARGS_VFS_GETATTR], [
+-      AC_MSG_CHECKING([whether vfs_getattr() wants 2 args])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_GETATTR_2ARGS], [
++      ZFS_LINUX_TEST_SRC([vfs_getattr_2args], [
+               #include <linux/fs.h>
+       ],[
+               vfs_getattr((struct path *) NULL,
+                       (struct kstat *)NULL);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_VFS_GETATTR_2ARGS], [
++      AC_MSG_CHECKING([whether vfs_getattr() wants 2 args])
++      ZFS_LINUX_TEST_RESULT([vfs_getattr_2args], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_2ARGS_VFS_GETATTR, 1,
+-                        [vfs_getattr wants 2 args])
++                  [vfs_getattr wants 2 args])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+@@ -44,19 +52,35 @@ dnl #
+ dnl # <3.9 API
+ dnl # vfs_getattr(struct vfsmount *v, struct dentry *d, struct kstat *k)
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_3ARGS_VFS_GETATTR], [
+-      AC_MSG_CHECKING([whether vfs_getattr() wants 3 args])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_GETATTR_3ARGS], [
++      ZFS_LINUX_TEST_SRC([vfs_getattr_3args], [
+               #include <linux/fs.h>
+       ],[
+               vfs_getattr((struct vfsmount *)NULL,
+                       (struct dentry *)NULL,
+                       (struct kstat *)NULL);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_VFS_GETATTR_3ARGS], [
++      AC_MSG_CHECKING([whether vfs_getattr() wants 3 args])
++      ZFS_LINUX_TEST_RESULT([vfs_getattr_3args], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_3ARGS_VFS_GETATTR, 1,
+-                [vfs_getattr wants 3 args])
++                  [vfs_getattr wants 3 args])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+ ])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_GETATTR], [
++      ZFS_AC_KERNEL_SRC_VFS_GETATTR_4ARGS
++      ZFS_AC_KERNEL_SRC_VFS_GETATTR_2ARGS
++      ZFS_AC_KERNEL_SRC_VFS_GETATTR_3ARGS
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_VFS_GETATTR], [
++      ZFS_AC_KERNEL_VFS_GETATTR_4ARGS
++      ZFS_AC_KERNEL_VFS_GETATTR_2ARGS
++      ZFS_AC_KERNEL_VFS_GETATTR_3ARGS
++])
+diff --git a/config/kernel-vfs-iterate.m4 b/config/kernel-vfs-iterate.m4
+index 5de901d44..172118eac 100644
+--- a/config/kernel-vfs-iterate.m4
++++ b/config/kernel-vfs-iterate.m4
+@@ -1,9 +1,5 @@
+-AC_DEFUN([ZFS_AC_KERNEL_VFS_ITERATE], [
+-      dnl #
+-      dnl # 4.7 API change
+-      dnl #
+-      AC_MSG_CHECKING([whether fops->iterate_shared() is available])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_ITERATE], [
++      ZFS_LINUX_TEST_SRC([file_operations_iterate_shared], [
+               #include <linux/fs.h>
+               int iterate(struct file *filp, struct dir_context * context)
+                   { return 0; }
+@@ -12,11 +8,44 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_ITERATE], [
+                   __attribute__ ((unused)) = {
+                       .iterate_shared  = iterate,
+               };
+-      ],[
+-      ],[
++      ],[])
++
++      ZFS_LINUX_TEST_SRC([file_operations_iterate], [
++              #include <linux/fs.h>
++              int iterate(struct file *filp,
++                  struct dir_context *context) { return 0; }
++
++              static const struct file_operations fops
++                  __attribute__ ((unused)) = {
++                      .iterate         = iterate,
++              };
++
++              #if defined(FMODE_KABI_ITERATE)
++              #error "RHEL 7.5, FMODE_KABI_ITERATE interface"
++              #endif
++      ],[])
++
++      ZFS_LINUX_TEST_SRC([file_operations_readdir], [
++              #include <linux/fs.h>
++              int readdir(struct file *filp, void *entry,
++                  filldir_t func) { return 0; }
++
++              static const struct file_operations fops
++                  __attribute__ ((unused)) = {
++                      .readdir = readdir,
++              };
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_VFS_ITERATE], [
++      dnl #
++      dnl # 4.7 API change
++      dnl #
++      AC_MSG_CHECKING([whether fops->iterate_shared() is available])
++      ZFS_LINUX_TEST_RESULT([file_operations_iterate_shared], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_VFS_ITERATE_SHARED, 1,
+-                        [fops->iterate_shared() is available])
++                  [fops->iterate_shared() is available])
+       ],[
+               AC_MSG_RESULT(no)
+@@ -31,44 +60,23 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_ITERATE], [
+               dnl # to using fops.readdir() to retain KABI compatibility.
+               dnl #
+               AC_MSG_CHECKING([whether fops->iterate() is available])
+-              ZFS_LINUX_TRY_COMPILE([
+-                      #include <linux/fs.h>
+-                      int iterate(struct file *filp,
+-                          struct dir_context *context) { return 0; }
+-
+-                      static const struct file_operations fops
+-                          __attribute__ ((unused)) = {
+-                              .iterate         = iterate,
+-                      };
+-
+-                      #if defined(FMODE_KABI_ITERATE)
+-                      #error "RHEL 7.5, FMODE_KABI_ITERATE interface"
+-                      #endif
+-              ],[
+-              ],[
++              ZFS_LINUX_TEST_RESULT([file_operations_iterate], [
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_VFS_ITERATE, 1,
+-                                [fops->iterate() is available])
++                          [fops->iterate() is available])
+               ],[
+                       AC_MSG_RESULT(no)
++                      dnl #
++                      dnl # readdir interface introduced
++                      dnl #
+                       AC_MSG_CHECKING([whether fops->readdir() is available])
+-                      ZFS_LINUX_TRY_COMPILE([
+-                              #include <linux/fs.h>
+-                              int readdir(struct file *filp, void *entry,
+-                                  filldir_t func) { return 0; }
+-
+-                              static const struct file_operations fops
+-                                  __attribute__ ((unused)) = {
+-                                      .readdir = readdir,
+-                              };
+-                      ],[
+-                      ],[
++                      ZFS_LINUX_TEST_RESULT([file_operations_readdir], [
+                               AC_MSG_RESULT(yes)
+                               AC_DEFINE(HAVE_VFS_READDIR, 1,
+-                                        [fops->readdir() is available])
++                                  [fops->readdir() is available])
+                       ],[
+-                              AC_MSG_ERROR(no; file a bug report with ZoL)
++                              ZFS_LINUX_TEST_ERROR([vfs_iterate])
+                       ])
+               ])
+       ])
+diff --git a/config/kernel-vfs-rw-iterate.m4 b/config/kernel-vfs-rw-iterate.m4
+index ace54f707..000353ec1 100644
+--- a/config/kernel-vfs-rw-iterate.m4
++++ b/config/kernel-vfs-rw-iterate.m4
+@@ -1,9 +1,8 @@
+ dnl #
+ dnl # Linux 3.16 API
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_VFS_RW_ITERATE],
+-      [AC_MSG_CHECKING([whether fops->read/write_iter() are available])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_RW_ITERATE], [
++      ZFS_LINUX_TEST_SRC([file_operations_rw], [
+               #include <linux/fs.h>
+               ssize_t test_read(struct kiocb *kiocb, struct iov_iter *to)
+@@ -16,39 +15,41 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_RW_ITERATE],
+                   .read_iter = test_read,
+                   .write_iter = test_write,
+               };
+-      ],[
+-      ],[
+-              AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_VFS_RW_ITERATE, 1,
+-                      [fops->read/write_iter() are available])
++      ],[])
+-              ZFS_AC_KERNEL_NEW_SYNC_READ
++      ZFS_LINUX_TEST_SRC([new_sync_rw], [
++              #include <linux/fs.h>
+       ],[
+-              AC_MSG_RESULT(no)
++              ssize_t ret __attribute__ ((unused));
++              struct file *filp = NULL;
++              char __user *rbuf = NULL;
++              const char __user *wbuf = NULL;
++              size_t len = 0;
++              loff_t ppos;
++
++              ret = new_sync_read(filp, rbuf, len, &ppos);
++              ret = new_sync_write(filp, wbuf, len, &ppos);
+       ])
+ ])
+-dnl #
+-dnl # Linux 4.1 API
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_NEW_SYNC_READ],
+-      [AC_MSG_CHECKING([whether new_sync_read/write() are available])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/fs.h>
+-      ],[
+-                      ssize_t ret __attribute__ ((unused));
+-                      struct file *filp = NULL;
+-                      char __user *rbuf = NULL;
+-                      const char __user *wbuf = NULL;
+-                      size_t len = 0;
+-                      loff_t ppos;
+-
+-                      ret = new_sync_read(filp, rbuf, len, &ppos);
+-                      ret = new_sync_write(filp, wbuf, len, &ppos);
+-      ],[
++AC_DEFUN([ZFS_AC_KERNEL_VFS_RW_ITERATE], [
++      AC_MSG_CHECKING([whether fops->read/write_iter() are available])
++      ZFS_LINUX_TEST_RESULT([file_operations_rw], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_NEW_SYNC_READ, 1,
+-                      [new_sync_read()/new_sync_write() are available])
++              AC_DEFINE(HAVE_VFS_RW_ITERATE, 1,
++                  [fops->read/write_iter() are available])
++
++              dnl #
++              dnl # Linux 4.1 API
++              dnl #
++              AC_MSG_CHECKING([whether new_sync_read/write() are available])
++              ZFS_LINUX_TEST_RESULT([new_sync_rw], [
++                      AC_MSG_RESULT(yes)
++                      AC_DEFINE(HAVE_NEW_SYNC_READ, 1,
++                          [new_sync_read()/new_sync_write() are available])
++              ],[
++                      AC_MSG_RESULT(no)
++              ])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+@@ -57,19 +58,22 @@ AC_DEFUN([ZFS_AC_KERNEL_NEW_SYNC_READ],
+ dnl #
+ dnl # Linux 4.1.x API
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_GENERIC_WRITE_CHECKS],
+-      [AC_MSG_CHECKING([whether generic_write_checks() takes kiocb])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_GENERIC_WRITE_CHECKS], [
++      ZFS_LINUX_TEST_SRC([generic_write_checks], [
+               #include <linux/fs.h>
+-
+       ],[
+               struct kiocb *iocb = NULL;
+               struct iov_iter *iov = NULL;
+               generic_write_checks(iocb, iov);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_VFS_GENERIC_WRITE_CHECKS], [
++      AC_MSG_CHECKING([whether generic_write_checks() takes kiocb])
++      ZFS_LINUX_TEST_RESULT([generic_write_checks], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_GENERIC_WRITE_CHECKS_KIOCB, 1,
+-                      [generic_write_checks() takes kiocb])
++                  [generic_write_checks() takes kiocb])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel-wait.m4 b/config/kernel-wait.m4
+index d6442c1df..0414242bf 100644
+--- a/config/kernel-wait.m4
++++ b/config/kernel-wait.m4
+@@ -1,3 +1,26 @@
++dnl #
++dnl # 4.13 API change
++dnl # Renamed struct wait_queue -> struct wait_queue_entry.
++dnl #
++dnl # N.B. The type check is performed before all other checks
++dnl # since ZFS_AC_KERNEL_SRC_WAIT_QUEUE_HEAD_ENTRY depends on
++dnl # HAVE_WAIT_QUEUE_ENTRY_T being set in confdefs.h.
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_WAIT_QUEUE_ENTRY_T], [
++      AC_MSG_CHECKING([whether wait_queue_entry_t exists])
++      ZFS_LINUX_TRY_COMPILE([
++              #include <linux/wait.h>
++      ],[
++              wait_queue_entry_t *entry __attribute__ ((unused));
++      ],[
++              AC_MSG_RESULT(yes)
++              AC_DEFINE(HAVE_WAIT_QUEUE_ENTRY_T, 1,
++                  [wait_queue_entry_t exists])
++      ],[
++              AC_MSG_RESULT(no)
++      ])
++])
++
+ dnl #
+ dnl # 3.17 API change,
+ dnl # wait_on_bit() no longer requires an action argument. The former
+@@ -8,34 +31,20 @@ dnl # of just two functions: one which uses io_schedule() and one which just
+ dnl # uses schedule().  This API change was made to consolidate all of those
+ dnl # redundant wait functions.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_WAIT_ON_BIT], [
+-      AC_MSG_CHECKING([whether wait_on_bit() takes an action])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_WAIT_ON_BIT], [
++      ZFS_LINUX_TEST_SRC([wait_on_bit], [
+               #include <linux/wait.h>
+       ],[
+               int (*action)(void *) = NULL;
+               wait_on_bit(NULL, 0, action, 0);
+-      ],[
+-              AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_WAIT_ON_BIT_ACTION, 1, [yes])
+-      ],[
+-              AC_MSG_RESULT(no)
+       ])
+ ])
+-dnl #
+-dnl # 4.13 API change
+-dnl # Renamed struct wait_queue -> struct wait_queue_entry.
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_WAIT_QUEUE_ENTRY_T], [
+-      AC_MSG_CHECKING([whether wait_queue_entry_t exists])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/wait.h>
+-      ],[
+-              wait_queue_entry_t *entry __attribute__ ((unused));
+-      ],[
++
++AC_DEFUN([ZFS_AC_KERNEL_WAIT_ON_BIT], [
++      AC_MSG_CHECKING([whether wait_on_bit() takes an action])
++      ZFS_LINUX_TEST_RESULT([wait_on_bit], [
+               AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_WAIT_QUEUE_ENTRY_T, 1,
+-                  [wait_queue_entry_t exists])
++              AC_DEFINE(HAVE_WAIT_ON_BIT_ACTION, 1, [yes])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+@@ -46,9 +55,8 @@ dnl # 4.13 API change
+ dnl # Renamed wait_queue_head::task_list -> wait_queue_head::head
+ dnl # Renamed wait_queue_entry::task_list -> wait_queue_entry::entry
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_WAIT_QUEUE_HEAD_ENTRY], [
+-      AC_MSG_CHECKING([whether wq_head->head and wq_entry->entry exist])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_WAIT_QUEUE_HEAD_ENTRY], [
++      ZFS_LINUX_TEST_SRC([wait_queue_head_entry], [
+               #include <linux/wait.h>
+               #ifdef HAVE_WAIT_QUEUE_ENTRY_T
+@@ -66,7 +74,12 @@ AC_DEFUN([ZFS_AC_KERNEL_WAIT_QUEUE_HEAD_ENTRY], [
+               head = &wq_head.head;
+               entry = &wq_entry.entry;
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_WAIT_QUEUE_HEAD_ENTRY], [
++      AC_MSG_CHECKING([whether wq_head->head and wq_entry->entry exist])
++      ZFS_LINUX_TEST_RESULT([wait_queue_head_entry], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_WAIT_QUEUE_HEAD_ENTRY, 1,
+                   [wq_head->head and wq_entry->entry exist])
+@@ -74,3 +87,13 @@ AC_DEFUN([ZFS_AC_KERNEL_WAIT_QUEUE_HEAD_ENTRY], [
+               AC_MSG_RESULT(no)
+       ])
+ ])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_WAIT], [
++      ZFS_AC_KERNEL_SRC_WAIT_ON_BIT
++      ZFS_AC_KERNEL_SRC_WAIT_QUEUE_HEAD_ENTRY
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_WAIT], [
++      ZFS_AC_KERNEL_WAIT_ON_BIT
++      ZFS_AC_KERNEL_WAIT_QUEUE_HEAD_ENTRY
++])
+diff --git a/config/kernel-xattr-handler.m4 b/config/kernel-xattr-handler.m4
+index 0b61b85b1..ed84c6390 100644
+--- a/config/kernel-xattr-handler.m4
++++ b/config/kernel-xattr-handler.m4
+@@ -3,9 +3,8 @@ dnl # 2.6.35 API change,
+ dnl # The 'struct xattr_handler' was constified in the generic
+ dnl # super_block structure.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_CONST_XATTR_HANDLER], [
+-      AC_MSG_CHECKING([whether super_block uses const struct xattr_handler])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_CONST_XATTR_HANDLER], [
++      ZFS_LINUX_TEST_SRC([const_xattr_handler], [
+               #include <linux/fs.h>
+               #include <linux/xattr.h>
+@@ -22,11 +21,15 @@ AC_DEFUN([ZFS_AC_KERNEL_CONST_XATTR_HANDLER], [
+               const struct super_block sb __attribute__ ((unused)) = {
+                       .s_xattr = xattr_handlers,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_CONST_XATTR_HANDLER], [
++      AC_MSG_CHECKING([whether super_block uses const struct xattr_handler])
++      ZFS_LINUX_TEST_RESULT([const_xattr_handler], [
+               AC_MSG_RESULT([yes])
+               AC_DEFINE(HAVE_CONST_XATTR_HANDLER, 1,
+-                        [super_block uses const struct xattr_handler])
++                  [super_block uses const struct xattr_handler])
+       ],[
+               AC_MSG_RESULT([no])
+       ])
+@@ -38,17 +41,20 @@ dnl # struct xattr_handler added new member "name".
+ dnl # xattr_handler which matches to whole name rather than prefix should use
+ dnl # "name" instead of "prefix", e.g. "system.posix_acl_access"
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_NAME], [
+-      AC_MSG_CHECKING([whether xattr_handler has name])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_NAME], [
++      ZFS_LINUX_TEST_SRC([xattr_handler_name], [
+               #include <linux/xattr.h>
+               static const struct xattr_handler
+                   xops __attribute__ ((unused)) = {
+                       .name = XATTR_NAME_POSIX_ACL_ACCESS,
+               };
+-      ],[
+-      ],[
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_NAME], [
++      AC_MSG_CHECKING([whether xattr_handler has name])
++      ZFS_LINUX_TEST_RESULT([xattr_handler_name], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_XATTR_HANDLER_NAME, 1,
+                   [xattr_handler has name])
+@@ -58,52 +64,65 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_NAME], [
+ ])
+ dnl #
+-dnl # 4.9 API change,
+-dnl # iops->{set,get,remove}xattr and generic_{set,get,remove}xattr are
+-dnl # removed. xattr operations will directly go through sb->s_xattr.
++dnl # Supported xattr handler get() interfaces checked newest to oldest.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_HAVE_GENERIC_SETXATTR], [
+-      AC_MSG_CHECKING([whether generic_setxattr() exists])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/fs.h>
++AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_GET], [
++      ZFS_LINUX_TEST_SRC([xattr_handler_get_dentry_inode], [
+               #include <linux/xattr.h>
+-              static const struct inode_operations
+-                  iops __attribute__ ((unused)) = {
+-                      .setxattr = generic_setxattr
++              int get(const struct xattr_handler *handler,
++                  struct dentry *dentry, struct inode *inode,
++                  const char *name, void *buffer, size_t size) { return 0; }
++              static const struct xattr_handler
++                  xops __attribute__ ((unused)) = {
++                      .get = get,
+               };
+-      ],[
+-      ],[
+-              AC_MSG_RESULT(yes)
+-              AC_DEFINE(HAVE_GENERIC_SETXATTR, 1,
+-                  [generic_setxattr() exists])
+-      ],[
+-              AC_MSG_RESULT(no)
+-      ])
+-])
++      ],[])
+-dnl #
+-dnl # Supported xattr handler get() interfaces checked newest to oldest.
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_GET], [
+-      dnl #
+-      dnl # 4.7 API change,
+-      dnl # The xattr_handler->get() callback was changed to take both
+-      dnl # dentry and inode.
+-      dnl #
+-      AC_MSG_CHECKING([whether xattr_handler->get() wants both dentry and inode])
+-      ZFS_LINUX_TRY_COMPILE([
++      ZFS_LINUX_TEST_SRC([xattr_handler_get_xattr_handler], [
+               #include <linux/xattr.h>
+               int get(const struct xattr_handler *handler,
+-                  struct dentry *dentry, struct inode *inode,
+-                  const char *name, void *buffer, size_t size) { return 0; }
++                  struct dentry *dentry, const char *name,
++                  void *buffer, size_t size) { return 0; }
+               static const struct xattr_handler
+                   xops __attribute__ ((unused)) = {
+                       .get = get,
+               };
+-      ],[
+-      ],[
++      ],[])
++
++      ZFS_LINUX_TEST_SRC([xattr_handler_get_dentry], [
++              #include <linux/xattr.h>
++
++              int get(struct dentry *dentry, const char *name,
++                  void *buffer, size_t size, int handler_flags)
++                  { return 0; }
++              static const struct xattr_handler
++                  xops __attribute__ ((unused)) = {
++                      .get = get,
++              };
++      ],[])
++
++      ZFS_LINUX_TEST_SRC([xattr_handler_get_inode], [
++              #include <linux/xattr.h>
++
++              int get(struct inode *ip, const char *name,
++                  void *buffer, size_t size) { return 0; }
++              static const struct xattr_handler
++                  xops __attribute__ ((unused)) = {
++                      .get = get,
++              };
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_GET], [
++      dnl #
++      dnl # 4.7 API change,
++      dnl # The xattr_handler->get() callback was changed to take both
++      dnl # dentry and inode.
++      dnl #
++      AC_MSG_CHECKING([whether xattr_handler->get() wants dentry and inode])
++      ZFS_LINUX_TEST_RESULT([xattr_handler_get_dentry_inode], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_XATTR_GET_DENTRY_INODE, 1,
+                   [xattr_handler->get() wants both dentry and inode])
+@@ -115,69 +134,40 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_GET], [
+               dnl # should be accessed by handler->flags.
+               dnl #
+               AC_MSG_RESULT(no)
+-              AC_MSG_CHECKING([whether xattr_handler->get() wants xattr_handler])
+-              ZFS_LINUX_TRY_COMPILE([
+-                      #include <linux/xattr.h>
+-
+-                      int get(const struct xattr_handler *handler,
+-                          struct dentry *dentry, const char *name,
+-                          void *buffer, size_t size) { return 0; }
+-                      static const struct xattr_handler
+-                          xops __attribute__ ((unused)) = {
+-                              .get = get,
+-                      };
+-              ],[
+-              ],[
++              AC_MSG_CHECKING(
++                  [whether xattr_handler->get() wants xattr_handler])
++              ZFS_LINUX_TEST_RESULT([xattr_handler_get_xattr_handler], [
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_XATTR_GET_HANDLER, 1,
+                           [xattr_handler->get() wants xattr_handler])
+               ],[
+                       dnl #
+                       dnl # 2.6.33 API change,
+-                      dnl # The xattr_handler->get() callback was changed to take
+-                      dnl # a dentry instead of an inode, and a handler_flags
+-                      dnl # argument was added.
++                      dnl # The xattr_handler->get() callback was changed
++                      dnl # to take a dentry instead of an inode, and a
++                      dnl # handler_flags argument was added.
+                       dnl #
+                       AC_MSG_RESULT(no)
+-                      AC_MSG_CHECKING([whether xattr_handler->get() wants dentry])
+-                      ZFS_LINUX_TRY_COMPILE([
+-                              #include <linux/xattr.h>
+-
+-                              int get(struct dentry *dentry, const char *name,
+-                                  void *buffer, size_t size, int handler_flags)
+-                                  { return 0; }
+-                              static const struct xattr_handler
+-                                  xops __attribute__ ((unused)) = {
+-                                      .get = get,
+-                              };
+-                      ],[
+-                      ],[
++                      AC_MSG_CHECKING(
++                          [whether xattr_handler->get() wants dentry])
++                      ZFS_LINUX_TEST_RESULT([xattr_handler_get_dentry], [
+                               AC_MSG_RESULT(yes)
+                               AC_DEFINE(HAVE_XATTR_GET_DENTRY, 1,
+                                   [xattr_handler->get() wants dentry])
+                       ],[
+                               dnl #
+-                              dnl # 2.6.32 API
++                              dnl # Legacy 2.6.32 API
+                               dnl #
+                               AC_MSG_RESULT(no)
+                               AC_MSG_CHECKING(
+                                   [whether xattr_handler->get() wants inode])
+-                              ZFS_LINUX_TRY_COMPILE([
+-                                      #include <linux/xattr.h>
+-
+-                                      int get(struct inode *ip, const char *name,
+-                                          void *buffer, size_t size) { return 0; }
+-                                      static const struct xattr_handler
+-                                          xops __attribute__ ((unused)) = {
+-                                              .get = get,
+-                                      };
+-                              ],[
+-                              ],[
++                              ZFS_LINUX_TEST_RESULT(
++                                  [xattr_handler_get_inode], [
+                                       AC_MSG_RESULT(yes)
+                                       AC_DEFINE(HAVE_XATTR_GET_INODE, 1,
+                                           [xattr_handler->get() wants inode])
+                               ],[
+-                                      AC_MSG_ERROR([no; please file a bug report])
++                                      ZFS_LINUX_TEST_ERROR([xattr get()])
+                               ])
+                       ])
+               ])
+@@ -187,14 +177,8 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_GET], [
+ dnl #
+ dnl # Supported xattr handler set() interfaces checked newest to oldest.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [
+-      dnl #
+-      dnl # 4.7 API change,
+-      dnl # The xattr_handler->set() callback was changed to take both
+-      dnl # dentry and inode.
+-      dnl #
+-      AC_MSG_CHECKING([whether xattr_handler->set() wants both dentry and inode])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_SET], [
++      ZFS_LINUX_TEST_SRC([xattr_handler_set_dentry_inode], [
+               #include <linux/xattr.h>
+               int set(const struct xattr_handler *handler,
+@@ -206,8 +190,54 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [
+                   xops __attribute__ ((unused)) = {
+                       .set = set,
+               };
+-      ],[
+-      ],[
++      ],[])
++
++      ZFS_LINUX_TEST_SRC([xattr_handler_set_xattr_handler], [
++              #include <linux/xattr.h>
++
++              int set(const struct xattr_handler *handler,
++                  struct dentry *dentry, const char *name,
++                  const void *buffer, size_t size, int flags)
++                  { return 0; }
++              static const struct xattr_handler
++                  xops __attribute__ ((unused)) = {
++                      .set = set,
++              };
++      ],[])
++
++      ZFS_LINUX_TEST_SRC([xattr_handler_set_dentry], [
++              #include <linux/xattr.h>
++
++              int set(struct dentry *dentry, const char *name,
++                  const void *buffer, size_t size, int flags,
++                  int handler_flags) { return 0; }
++              static const struct xattr_handler
++                  xops __attribute__ ((unused)) = {
++                      .set = set,
++              };
++      ],[])
++
++      ZFS_LINUX_TEST_SRC([xattr_handler_set_inode], [
++              #include <linux/xattr.h>
++
++              int set(struct inode *ip, const char *name,
++                  const void *buffer, size_t size, int flags)
++                  { return 0; }
++              static const struct xattr_handler
++                  xops __attribute__ ((unused)) = {
++                      .set = set,
++              };
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [
++      dnl #
++      dnl # 4.7 API change,
++      dnl # The xattr_handler->set() callback was changed to take both
++      dnl # dentry and inode.
++      dnl #
++      AC_MSG_CHECKING([whether xattr_handler->set() wants dentry and inode])
++      ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry_inode], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_XATTR_SET_DENTRY_INODE, 1,
+                   [xattr_handler->set() wants both dentry and inode])
+@@ -219,71 +249,40 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [
+               dnl # should be accessed by handler->flags.
+               dnl #
+               AC_MSG_RESULT(no)
+-              AC_MSG_CHECKING([whether xattr_handler->set() wants xattr_handler])
+-              ZFS_LINUX_TRY_COMPILE([
+-                      #include <linux/xattr.h>
+-
+-                      int set(const struct xattr_handler *handler,
+-                          struct dentry *dentry, const char *name,
+-                          const void *buffer, size_t size, int flags)
+-                          { return 0; }
+-                      static const struct xattr_handler
+-                          xops __attribute__ ((unused)) = {
+-                              .set = set,
+-                      };
+-              ],[
+-              ],[
++              AC_MSG_CHECKING(
++                  [whether xattr_handler->set() wants xattr_handler])
++              ZFS_LINUX_TEST_RESULT([xattr_handler_set_xattr_handler], [
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_XATTR_SET_HANDLER, 1,
+                           [xattr_handler->set() wants xattr_handler])
+               ],[
+                       dnl #
+                       dnl # 2.6.33 API change,
+-                      dnl # The xattr_handler->set() callback was changed to take a
+-                      dnl # dentry instead of an inode, and a handler_flags
+-                      dnl # argument was added.
++                      dnl # The xattr_handler->set() callback was changed
++                      dnl # to take a dentry instead of an inode, and a
++                      dnl # handler_flags argument was added.
+                       dnl #
+                       AC_MSG_RESULT(no)
+-                      AC_MSG_CHECKING([whether xattr_handler->set() wants dentry])
+-                      ZFS_LINUX_TRY_COMPILE([
+-                              #include <linux/xattr.h>
+-
+-                              int set(struct dentry *dentry, const char *name,
+-                                  const void *buffer, size_t size, int flags,
+-                                  int handler_flags) { return 0; }
+-                              static const struct xattr_handler
+-                                  xops __attribute__ ((unused)) = {
+-                                      .set = set,
+-                              };
+-                      ],[
+-                      ],[
++                      AC_MSG_CHECKING(
++                          [whether xattr_handler->set() wants dentry])
++                      ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry], [
+                               AC_MSG_RESULT(yes)
+                               AC_DEFINE(HAVE_XATTR_SET_DENTRY, 1,
+                                   [xattr_handler->set() wants dentry])
+                       ],[
+                               dnl #
+-                              dnl # 2.6.32 API
++                              dnl # Legacy 2.6.32 API
+                               dnl #
+                               AC_MSG_RESULT(no)
+                               AC_MSG_CHECKING(
+                                   [whether xattr_handler->set() wants inode])
+-                              ZFS_LINUX_TRY_COMPILE([
+-                                      #include <linux/xattr.h>
+-
+-                                      int set(struct inode *ip, const char *name,
+-                                          const void *buffer, size_t size, int flags)
+-                                          { return 0; }
+-                                      static const struct xattr_handler
+-                                          xops __attribute__ ((unused)) = {
+-                                              .set = set,
+-                                      };
+-                              ],[
+-                              ],[
++                              ZFS_LINUX_TEST_RESULT(
++                                  [xattr_handler_set_inode], [
+                                       AC_MSG_RESULT(yes)
+                                       AC_DEFINE(HAVE_XATTR_SET_INODE, 1,
+                                           [xattr_handler->set() wants inode])
+                               ],[
+-                                      AC_MSG_ERROR([no; please file a bug report])
++                                      ZFS_LINUX_TEST_ERROR([xattr set()])
+                               ])
+                       ])
+               ])
+@@ -293,12 +292,8 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [
+ dnl #
+ dnl # Supported xattr handler list() interfaces checked newest to oldest.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_LIST], [
+-      dnl # 4.5 API change,
+-      dnl # The xattr_handler->list() callback was changed to take only a
+-      dnl # dentry and it only needs to return if it's accessible.
+-      AC_MSG_CHECKING([whether xattr_handler->list() wants simple])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_LIST], [
++      ZFS_LINUX_TEST_SRC([xattr_handler_list_simple], [
+               #include <linux/xattr.h>
+               bool list(struct dentry *dentry) { return 0; }
+@@ -306,8 +301,52 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_LIST], [
+                   xops __attribute__ ((unused)) = {
+                       .list = list,
+               };
+-      ],[
+-      ],[
++      ],[])
++
++      ZFS_LINUX_TEST_SRC([xattr_handler_list_xattr_handler], [
++              #include <linux/xattr.h>
++
++              size_t list(const struct xattr_handler *handler,
++                  struct dentry *dentry, char *list, size_t list_size,
++                  const char *name, size_t name_len) { return 0; }
++              static const struct xattr_handler
++                  xops __attribute__ ((unused)) = {
++                      .list = list,
++              };
++      ],[])
++
++      ZFS_LINUX_TEST_SRC([xattr_handler_list_dentry], [
++              #include <linux/xattr.h>
++
++              size_t list(struct dentry *dentry,
++                  char *list, size_t list_size,
++                  const char *name, size_t name_len,
++                  int handler_flags) { return 0; }
++              static const struct xattr_handler
++                  xops __attribute__ ((unused)) = {
++                      .list = list,
++              };
++      ],[])
++
++      ZFS_LINUX_TEST_SRC([xattr_handler_list_inode], [
++              #include <linux/xattr.h>
++
++              size_t list(struct inode *ip, char *lst,
++                  size_t list_size, const char *name,
++                  size_t name_len) { return 0; }
++              static const struct xattr_handler
++                  xops __attribute__ ((unused)) = {
++                      .list = list,
++              };
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_LIST], [
++      dnl # 4.5 API change,
++      dnl # The xattr_handler->list() callback was changed to take only a
++      dnl # dentry and it only needs to return if it's accessible.
++      AC_MSG_CHECKING([whether xattr_handler->list() wants simple])
++      ZFS_LINUX_TEST_RESULT([xattr_handler_list_simple], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_XATTR_LIST_SIMPLE, 1,
+                   [xattr_handler->list() wants simple])
+@@ -321,18 +360,7 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_LIST], [
+               AC_MSG_RESULT(no)
+               AC_MSG_CHECKING(
+                   [whether xattr_handler->list() wants xattr_handler])
+-              ZFS_LINUX_TRY_COMPILE([
+-                      #include <linux/xattr.h>
+-
+-                      size_t list(const struct xattr_handler *handler,
+-                          struct dentry *dentry, char *list, size_t list_size,
+-                          const char *name, size_t name_len) { return 0; }
+-                      static const struct xattr_handler
+-                          xops __attribute__ ((unused)) = {
+-                              .list = list,
+-                      };
+-              ],[
+-              ],[
++              ZFS_LINUX_TEST_RESULT([xattr_handler_list_xattr_handler], [
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_XATTR_LIST_HANDLER, 1,
+                           [xattr_handler->list() wants xattr_handler])
+@@ -346,47 +374,24 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_LIST], [
+                       AC_MSG_RESULT(no)
+                       AC_MSG_CHECKING(
+                           [whether xattr_handler->list() wants dentry])
+-                      ZFS_LINUX_TRY_COMPILE([
+-                              #include <linux/xattr.h>
+-
+-                              size_t list(struct dentry *dentry,
+-                                  char *list, size_t list_size,
+-                                  const char *name, size_t name_len,
+-                                  int handler_flags) { return 0; }
+-                              static const struct xattr_handler
+-                                  xops __attribute__ ((unused)) = {
+-                                      .list = list,
+-                              };
+-                      ],[
+-                      ],[
++                      ZFS_LINUX_TEST_RESULT([xattr_handler_list_dentry], [
+                               AC_MSG_RESULT(yes)
+                               AC_DEFINE(HAVE_XATTR_LIST_DENTRY, 1,
+                                   [xattr_handler->list() wants dentry])
+                       ],[
+                               dnl #
+-                              dnl # 2.6.32 API
++                              dnl # Legacy 2.6.32 API
+                               dnl #
+                               AC_MSG_RESULT(no)
+                               AC_MSG_CHECKING(
+                                   [whether xattr_handler->list() wants inode])
+-                              ZFS_LINUX_TRY_COMPILE([
+-                                      #include <linux/xattr.h>
+-
+-                                      size_t list(struct inode *ip, char *lst,
+-                                          size_t list_size, const char *name,
+-                                          size_t name_len) { return 0; }
+-                                      static const struct xattr_handler
+-                                          xops __attribute__ ((unused)) = {
+-                                              .list = list,
+-                                      };
+-                              ],[
+-                              ],[
++                              ZFS_LINUX_TEST_RESULT(
++                                  [xattr_handler_list_inode], [
+                                       AC_MSG_RESULT(yes)
+                                       AC_DEFINE(HAVE_XATTR_LIST_INODE, 1,
+                                           [xattr_handler->list() wants inode])
+                               ],[
+-                                      AC_MSG_ERROR(
+-                                          [no; please file a bug report])
++                                      ZFS_LINUX_TEST_ERROR([xattr list()])
+                               ])
+                       ])
+               ])
+@@ -398,15 +403,19 @@ dnl # 3.7 API change,
+ dnl # The posix_acl_{from,to}_xattr functions gained a new
+ dnl # parameter: user_ns
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_FROM_XATTR_USERNS], [
+-      AC_MSG_CHECKING([whether posix_acl_from_xattr() needs user_ns])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_POSIX_ACL_FROM_XATTR_USERNS], [
++      ZFS_LINUX_TEST_SRC([posix_acl_from_xattr_userns], [
+               #include <linux/cred.h>
+               #include <linux/fs.h>
+               #include <linux/posix_acl_xattr.h>
+       ],[
+               posix_acl_from_xattr(&init_user_ns, NULL, 0);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_FROM_XATTR_USERNS], [
++      AC_MSG_CHECKING([whether posix_acl_from_xattr() needs user_ns])
++      ZFS_LINUX_TEST_RESULT([posix_acl_from_xattr_userns], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_POSIX_ACL_FROM_XATTR_USERNS, 1,
+                   [posix_acl_from_xattr() needs user_ns])
+@@ -415,3 +424,50 @@ AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_FROM_XATTR_USERNS], [
+       ])
+ ])
++dnl #
++dnl # 4.9 API change,
++dnl # iops->{set,get,remove}xattr and generic_{set,get,remove}xattr are
++dnl # removed. xattr operations will directly go through sb->s_xattr.
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_SETXATTR], [
++      ZFS_LINUX_TEST_SRC([have_generic_setxattr], [
++              #include <linux/fs.h>
++              #include <linux/xattr.h>
++
++              static const struct inode_operations
++                  iops __attribute__ ((unused)) = {
++                      .setxattr = generic_setxattr
++              };
++      ],[])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_GENERIC_SETXATTR], [
++      AC_MSG_CHECKING([whether generic_setxattr() exists])
++      ZFS_LINUX_TEST_RESULT([have_generic_setxattr], [
++              AC_MSG_RESULT(yes)
++              AC_DEFINE(HAVE_GENERIC_SETXATTR, 1,
++                  [generic_setxattr() exists])
++      ],[
++              AC_MSG_RESULT(no)
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR], [
++      ZFS_AC_KERNEL_SRC_CONST_XATTR_HANDLER
++      ZFS_AC_KERNEL_SRC_XATTR_HANDLER_NAME
++      ZFS_AC_KERNEL_SRC_XATTR_HANDLER_GET
++      ZFS_AC_KERNEL_SRC_XATTR_HANDLER_SET
++      ZFS_AC_KERNEL_SRC_XATTR_HANDLER_LIST
++      ZFS_AC_KERNEL_SRC_POSIX_ACL_FROM_XATTR_USERNS
++      ZFS_AC_KERNEL_SRC_GENERIC_SETXATTR
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_XATTR], [
++      ZFS_AC_KERNEL_CONST_XATTR_HANDLER
++      ZFS_AC_KERNEL_XATTR_HANDLER_NAME
++      ZFS_AC_KERNEL_XATTR_HANDLER_GET
++      ZFS_AC_KERNEL_XATTR_HANDLER_SET
++      ZFS_AC_KERNEL_XATTR_HANDLER_LIST
++      ZFS_AC_KERNEL_POSIX_ACL_FROM_XATTR_USERNS
++      ZFS_AC_KERNEL_GENERIC_SETXATTR
++])
+diff --git a/config/kernel-zlib.m4 b/config/kernel-zlib.m4
+index 3ca7cf682..d554d1168 100644
+--- a/config/kernel-zlib.m4
++++ b/config/kernel-zlib.m4
+@@ -1,62 +1,25 @@
+-dnl #
+-dnl # zlib inflate compat,
+-dnl # Verify the kernel has CONFIG_ZLIB_INFLATE support enabled.
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_CONFIG_ZLIB_INFLATE], [
+-      AC_MSG_CHECKING([whether CONFIG_ZLIB_INFLATE is defined])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #if !defined(CONFIG_ZLIB_INFLATE) && \
+-                  !defined(CONFIG_ZLIB_INFLATE_MODULE)
+-              #error CONFIG_ZLIB_INFLATE not defined
+-              #endif
+-      ],[ ],[
+-              AC_MSG_RESULT([yes])
+-      ],[
+-              AC_MSG_RESULT([no])
+-              AC_MSG_ERROR([
+-      *** This kernel does not include the required zlib inflate support.
+-      *** Rebuild the kernel with CONFIG_ZLIB_INFLATE=y|m set.])
+-      ])
+-])
+-
+-dnl #
+-dnl # zlib deflate compat,
+-dnl # Verify the kernel has CONFIG_ZLIB_DEFLATE support enabled.
+-dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_CONFIG_ZLIB_DEFLATE], [
+-      AC_MSG_CHECKING([whether CONFIG_ZLIB_DEFLATE is defined])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #if !defined(CONFIG_ZLIB_DEFLATE) && \
+-                  !defined(CONFIG_ZLIB_DEFLATE_MODULE)
+-              #error CONFIG_ZLIB_DEFLATE not defined
+-              #endif
+-      ],[ ],[
+-              AC_MSG_RESULT([yes])
+-      ],[
+-              AC_MSG_RESULT([no])
+-              AC_MSG_ERROR([
+-      *** This kernel does not include the required zlib deflate support.
+-      *** Rebuild the kernel with CONFIG_ZLIB_DEFLATE=y|m set.])
+-      ])
+-])
+-
+ dnl #
+ dnl # 2.6.39 API compat,
++dnl
+ dnl # The function zlib_deflate_workspacesize() now take 2 arguments.
+ dnl # This was done to avoid always having to allocate the maximum size
+ dnl # workspace (268K).  The caller can now specific the windowBits and
+ dnl # memLevel compression parameters to get a smaller workspace.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE],
+-      [AC_MSG_CHECKING([whether zlib_deflate_workspacesize() wants 2 args])
+-      ZFS_LINUX_TRY_COMPILE([
++AC_DEFUN([ZFS_AC_KERNEL_SRC_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE], [
++      ZFS_LINUX_TEST_SRC([2args_zlib_deflate_workspacesize], [
+               #include <linux/zlib.h>
+       ],[
+               return zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL);
+-      ],[
++      ])
++])
++
++AC_DEFUN([ZFS_AC_KERNEL_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE], [
++      AC_MSG_CHECKING([whether zlib_deflate_workspacesize() wants 2 args])
++      ZFS_LINUX_TEST_RESULT([2args_zlib_deflate_workspacesize], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE, 1,
+-                        [zlib_deflate_workspacesize() wants 2 args])
++                  [zlib_deflate_workspacesize() wants 2 args])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+diff --git a/config/kernel.m4 b/config/kernel.m4
+index 8e89c8014..b22a00cdd 100644
+--- a/config/kernel.m4
++++ b/config/kernel.m4
+@@ -2,111 +2,217 @@ dnl #
+ dnl # Default ZFS kernel configuration
+ dnl #
+ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
++      dnl # Setup the kernel build environment.
+       ZFS_AC_KERNEL
+       ZFS_AC_QAT
+-      ZFS_AC_KERNEL_ACCESS_OK_TYPE
+-      ZFS_AC_TEST_MODULE
++
++      dnl # Sanity checks for module building and CONFIG_* defines
++      ZFS_AC_KERNEL_TEST_MODULE
++      ZFS_AC_KERNEL_CONFIG_DEFINED
++
++      dnl # Sequential ZFS_LINUX_TRY_COMPILE tests
++      ZFS_AC_KERNEL_FPU_HEADER
++      ZFS_AC_KERNEL_WAIT_QUEUE_ENTRY_T
+       ZFS_AC_KERNEL_MISC_MINOR
++      ZFS_AC_KERNEL_DECLARE_EVENT_CLASS
++
++      dnl # Parallel ZFS_LINUX_TEST_SRC / ZFS_LINUX_TEST_RESULT tests
++      ZFS_AC_KERNEL_TEST_SRC
++      ZFS_AC_KERNEL_TEST_RESULT
++
++      AS_IF([test "$LINUX_OBJ" != "$LINUX"], [
++              KERNEL_MAKE="$KERNEL_MAKE O=$LINUX_OBJ"
++      ])
++
++      AC_SUBST(KERNEL_MAKE)
++])
++
++dnl #
++dnl # Generate and compile all of the kernel API test cases to determine
++dnl # which interfaces are available.  By invoking the kernel build system
++dnl # only once the compilation can be done in parallel significantly
++dnl # speeding up the process.
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
++      ZFS_AC_KERNEL_SRC_OBJTOOL
++      ZFS_AC_KERNEL_SRC_GLOBAL_PAGE_STATE
++      ZFS_AC_KERNEL_SRC_ACCESS_OK_TYPE
++      ZFS_AC_KERNEL_SRC_CTL_NAME
++      ZFS_AC_KERNEL_SRC_PDE_DATA
++      ZFS_AC_KERNEL_SRC_FALLOCATE
++      ZFS_AC_KERNEL_SRC_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE
++      ZFS_AC_KERNEL_SRC_RWSEM
++      ZFS_AC_KERNEL_SRC_SCHED
++      ZFS_AC_KERNEL_SRC_USLEEP_RANGE
++      ZFS_AC_KERNEL_SRC_KMEM_CACHE
++      ZFS_AC_KERNEL_SRC_WAIT
++      ZFS_AC_KERNEL_SRC_INODE_TIMES
++      ZFS_AC_KERNEL_SRC_INODE_LOCK
++      ZFS_AC_KERNEL_SRC_GROUP_INFO_GID
++      ZFS_AC_KERNEL_SRC_RW
++      ZFS_AC_KERNEL_SRC_TIMER_SETUP
++      ZFS_AC_KERNEL_SRC_CURRENT_BIO_TAIL
++      ZFS_AC_KERNEL_SRC_SUPER_USER_NS
++      ZFS_AC_KERNEL_SRC_SUBMIT_BIO
++      ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS
++      ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH
++      ZFS_AC_KERNEL_SRC_BLKDEV_REREAD_PART
++      ZFS_AC_KERNEL_SRC_INVALIDATE_BDEV
++      ZFS_AC_KERNEL_SRC_LOOKUP_BDEV
++      ZFS_AC_KERNEL_SRC_BDEV_OPEN_EXCLUSIVE
++      ZFS_AC_KERNEL_SRC_BDEV_LOGICAL_BLOCK_SIZE
++      ZFS_AC_KERNEL_SRC_BDEV_PHYSICAL_BLOCK_SIZE
++      ZFS_AC_KERNEL_SRC_BIO_BVEC_ITER
++      ZFS_AC_KERNEL_SRC_BIO_FAILFAST
++      ZFS_AC_KERNEL_SRC_BIO_SET_DEV
++      ZFS_AC_KERNEL_SRC_BIO_OPS
++      ZFS_AC_KERNEL_SRC_BIO_END_IO_T_ARGS
++      ZFS_AC_KERNEL_SRC_BIO_BI_STATUS
++      ZFS_AC_KERNEL_SRC_BIO_RW_BARRIER
++      ZFS_AC_KERNEL_SRC_BIO_RW_DISCARD
++      ZFS_AC_KERNEL_SRC_BLK_QUEUE_BDI
++      ZFS_AC_KERNEL_SRC_BLK_QUEUE_DISCARD
++      ZFS_AC_KERNEL_SRC_BLK_QUEUE_SECURE_ERASE
++      ZFS_AC_KERNEL_SRC_BLK_QUEUE_FLAGS
++      ZFS_AC_KERNEL_SRC_BLK_QUEUE_FLUSH
++      ZFS_AC_KERNEL_SRC_BLK_QUEUE_MAX_HW_SECTORS
++      ZFS_AC_KERNEL_SRC_BLK_QUEUE_MAX_SEGMENTS
++      ZFS_AC_KERNEL_SRC_BLK_QUEUE_PLUG
++      ZFS_AC_KERNEL_SRC_GET_DISK_AND_MODULE
++      ZFS_AC_KERNEL_SRC_GET_DISK_RO
++      ZFS_AC_KERNEL_SRC_GENERIC_READLINK_GLOBAL
++      ZFS_AC_KERNEL_SRC_DISCARD_GRANULARITY
++      ZFS_AC_KERNEL_SRC_INODE_OWNER_OR_CAPABLE
++      ZFS_AC_KERNEL_SRC_XATTR
++      ZFS_AC_KERNEL_SRC_ACL
++      ZFS_AC_KERNEL_SRC_INODE_GETATTR
++      ZFS_AC_KERNEL_SRC_INODE_SET_FLAGS
++      ZFS_AC_KERNEL_SRC_INODE_SET_IVERSION
++      ZFS_AC_KERNEL_SRC_SHOW_OPTIONS
++      ZFS_AC_KERNEL_SRC_FILE_INODE
++      ZFS_AC_KERNEL_SRC_FILE_DENTRY
++      ZFS_AC_KERNEL_SRC_FSYNC
++      ZFS_AC_KERNEL_SRC_AIO_FSYNC
++      ZFS_AC_KERNEL_SRC_EVICT_INODE
++      ZFS_AC_KERNEL_SRC_DIRTY_INODE
++      ZFS_AC_KERNEL_SRC_SHRINKER
++      ZFS_AC_KERNEL_SRC_MKDIR_UMODE_T
++      ZFS_AC_KERNEL_SRC_LOOKUP_NAMEIDATA
++      ZFS_AC_KERNEL_SRC_CREATE_NAMEIDATA
++      ZFS_AC_KERNEL_SRC_GET_LINK
++      ZFS_AC_KERNEL_SRC_PUT_LINK
++      ZFS_AC_KERNEL_SRC_TMPFILE
++      ZFS_AC_KERNEL_SRC_TRUNCATE_RANGE
++      ZFS_AC_KERNEL_SRC_AUTOMOUNT
++      ZFS_AC_KERNEL_SRC_ENCODE_FH_WITH_INODE
++      ZFS_AC_KERNEL_SRC_COMMIT_METADATA
++      ZFS_AC_KERNEL_SRC_CLEAR_INODE
++      ZFS_AC_KERNEL_SRC_SETATTR_PREPARE
++      ZFS_AC_KERNEL_SRC_INSERT_INODE_LOCKED
++      ZFS_AC_KERNEL_SRC_DENTRY
++      ZFS_AC_KERNEL_SRC_TRUNCATE_SETSIZE
++      ZFS_AC_KERNEL_SRC_SECURITY_INODE
++      ZFS_AC_KERNEL_SRC_FST_MOUNT
++      ZFS_AC_KERNEL_SRC_BDI
++      ZFS_AC_KERNEL_SRC_SET_NLINK
++      ZFS_AC_KERNEL_SRC_ELEVATOR_CHANGE
++      ZFS_AC_KERNEL_SRC_SGET
++      ZFS_AC_KERNEL_SRC_LSEEK_EXECUTE
++      ZFS_AC_KERNEL_SRC_VFS_GETATTR
++      ZFS_AC_KERNEL_SRC_VFS_FSYNC_2ARGS
++      ZFS_AC_KERNEL_SRC_VFS_ITERATE
++      ZFS_AC_KERNEL_SRC_VFS_DIRECT_IO
++      ZFS_AC_KERNEL_SRC_VFS_RW_ITERATE
++      ZFS_AC_KERNEL_SRC_VFS_GENERIC_WRITE_CHECKS
++      ZFS_AC_KERNEL_SRC_KMAP_ATOMIC_ARGS
++      ZFS_AC_KERNEL_SRC_FOLLOW_DOWN_ONE
++      ZFS_AC_KERNEL_SRC_MAKE_REQUEST_FN
++      ZFS_AC_KERNEL_SRC_GENERIC_IO_ACCT
++      ZFS_AC_KERNEL_SRC_FPU
++      ZFS_AC_KERNEL_SRC_FMODE_T
++      ZFS_AC_KERNEL_SRC_KUIDGID_T
++      ZFS_AC_KERNEL_SRC_KUID_HELPERS
++      ZFS_AC_KERNEL_SRC_MODULE_PARAM_CALL_CONST
++      ZFS_AC_KERNEL_SRC_RENAME_WANTS_FLAGS
++      ZFS_AC_KERNEL_SRC_CURRENT_TIME
++      ZFS_AC_KERNEL_SRC_USERNS_CAPABILITIES
++      ZFS_AC_KERNEL_SRC_IN_COMPAT_SYSCALL
++      ZFS_AC_KERNEL_SRC_KTIME_GET_COARSE_REAL_TS64
++      ZFS_AC_KERNEL_SRC_TOTALRAM_PAGES_FUNC
++      ZFS_AC_KERNEL_SRC_TOTALHIGH_PAGES
++      ZFS_AC_KERNEL_SRC_KSTRTOUL
++
++      AC_MSG_CHECKING([for available kernel interfaces])
++      ZFS_LINUX_TEST_COMPILE_ALL([kabi])
++      AC_MSG_RESULT([done])
++])
++
++dnl #
++dnl # Check results of kernel interface tests.
++dnl #
++AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
++      ZFS_AC_KERNEL_ACCESS_OK_TYPE
++      ZFS_AC_KERNEL_GLOBAL_PAGE_STATE
+       ZFS_AC_KERNEL_OBJTOOL
+-      ZFS_AC_KERNEL_CONFIG
+       ZFS_AC_KERNEL_CTL_NAME
+       ZFS_AC_KERNEL_PDE_DATA
+-      ZFS_AC_KERNEL_2ARGS_VFS_FSYNC
+-      ZFS_AC_KERNEL_KUIDGID_T
+       ZFS_AC_KERNEL_FALLOCATE
+       ZFS_AC_KERNEL_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE
+-      ZFS_AC_KERNEL_RWSEM_SPINLOCK_IS_RAW
+-      ZFS_AC_KERNEL_RWSEM_ACTIVITY
+-      ZFS_AC_KERNEL_RWSEM_ATOMIC_LONG_COUNT
+-      ZFS_AC_KERNEL_SCHED_RT_HEADER
+-      ZFS_AC_KERNEL_SCHED_SIGNAL_HEADER
+-      ZFS_AC_KERNEL_IO_SCHEDULE_TIMEOUT
+-      ZFS_AC_KERNEL_4ARGS_VFS_GETATTR
+-      ZFS_AC_KERNEL_3ARGS_VFS_GETATTR
+-      ZFS_AC_KERNEL_2ARGS_VFS_GETATTR
++      ZFS_AC_KERNEL_RWSEM
++      ZFS_AC_KERNEL_SCHED
+       ZFS_AC_KERNEL_USLEEP_RANGE
+-      ZFS_AC_KERNEL_KMEM_CACHE_ALLOCFLAGS
+-      ZFS_AC_KERNEL_KMEM_CACHE_CREATE_USERCOPY
+-      ZFS_AC_KERNEL_WAIT_ON_BIT
+-      ZFS_AC_KERNEL_WAIT_QUEUE_ENTRY_T
+-      ZFS_AC_KERNEL_WAIT_QUEUE_HEAD_ENTRY
++      ZFS_AC_KERNEL_KMEM_CACHE
++      ZFS_AC_KERNEL_WAIT
+       ZFS_AC_KERNEL_INODE_TIMES
+       ZFS_AC_KERNEL_INODE_LOCK
+       ZFS_AC_KERNEL_GROUP_INFO_GID
+-      ZFS_AC_KERNEL_WRITE
+-      ZFS_AC_KERNEL_READ
++      ZFS_AC_KERNEL_RW
+       ZFS_AC_KERNEL_TIMER_SETUP
+-      ZFS_AC_KERNEL_DECLARE_EVENT_CLASS
+       ZFS_AC_KERNEL_CURRENT_BIO_TAIL
+       ZFS_AC_KERNEL_SUPER_USER_NS
+       ZFS_AC_KERNEL_SUBMIT_BIO
+-      ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS
+-      ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID
+-      ZFS_AC_KERNEL_TYPE_FMODE_T
++      ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS
+       ZFS_AC_KERNEL_BLKDEV_GET_BY_PATH
+       ZFS_AC_KERNEL_BLKDEV_REREAD_PART
+-      ZFS_AC_KERNEL_OPEN_BDEV_EXCLUSIVE
++      ZFS_AC_KERNEL_INVALIDATE_BDEV
+       ZFS_AC_KERNEL_LOOKUP_BDEV
+-      ZFS_AC_KERNEL_INVALIDATE_BDEV_ARGS
++      ZFS_AC_KERNEL_BDEV_OPEN_EXCLUSIVE
+       ZFS_AC_KERNEL_BDEV_LOGICAL_BLOCK_SIZE
+       ZFS_AC_KERNEL_BDEV_PHYSICAL_BLOCK_SIZE
+       ZFS_AC_KERNEL_BIO_BVEC_ITER
+-      ZFS_AC_KERNEL_BIO_FAILFAST_DTD
++      ZFS_AC_KERNEL_BIO_FAILFAST
+       ZFS_AC_KERNEL_BIO_SET_DEV
+-      ZFS_AC_KERNEL_REQ_FAILFAST_MASK
+-      ZFS_AC_KERNEL_REQ_OP_DISCARD
+-      ZFS_AC_KERNEL_REQ_OP_SECURE_ERASE
+-      ZFS_AC_KERNEL_REQ_OP_FLUSH
+-      ZFS_AC_KERNEL_BIO_BI_OPF
++      ZFS_AC_KERNEL_BIO_OPS
+       ZFS_AC_KERNEL_BIO_END_IO_T_ARGS
+       ZFS_AC_KERNEL_BIO_BI_STATUS
+       ZFS_AC_KERNEL_BIO_RW_BARRIER
+       ZFS_AC_KERNEL_BIO_RW_DISCARD
+       ZFS_AC_KERNEL_BLK_QUEUE_BDI
+-      ZFS_AC_KERNEL_BLK_QUEUE_FLAG_CLEAR
+-      ZFS_AC_KERNEL_BLK_QUEUE_FLAG_SET
++      ZFS_AC_KERNEL_BLK_QUEUE_DISCARD
++      ZFS_AC_KERNEL_BLK_QUEUE_SECURE_ERASE
++      ZFS_AC_KERNEL_BLK_QUEUE_FLAGS
+       ZFS_AC_KERNEL_BLK_QUEUE_FLUSH
+       ZFS_AC_KERNEL_BLK_QUEUE_MAX_HW_SECTORS
+       ZFS_AC_KERNEL_BLK_QUEUE_MAX_SEGMENTS
+-      ZFS_AC_KERNEL_BLK_QUEUE_HAVE_BIO_RW_UNPLUG
+-      ZFS_AC_KERNEL_BLK_QUEUE_HAVE_BLK_PLUG
++      ZFS_AC_KERNEL_BLK_QUEUE_PLUG
+       ZFS_AC_KERNEL_GET_DISK_AND_MODULE
+       ZFS_AC_KERNEL_GET_DISK_RO
+-      ZFS_AC_KERNEL_HAVE_BIO_SET_OP_ATTRS
+       ZFS_AC_KERNEL_GENERIC_READLINK_GLOBAL
+       ZFS_AC_KERNEL_DISCARD_GRANULARITY
+-      ZFS_AC_KERNEL_CONST_XATTR_HANDLER
+-      ZFS_AC_KERNEL_XATTR_HANDLER_NAME
+-      ZFS_AC_KERNEL_XATTR_HANDLER_GET
+-      ZFS_AC_KERNEL_XATTR_HANDLER_SET
+-      ZFS_AC_KERNEL_XATTR_HANDLER_LIST
+       ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE
+-      ZFS_AC_KERNEL_POSIX_ACL_FROM_XATTR_USERNS
+-      ZFS_AC_KERNEL_POSIX_ACL_RELEASE
+-      ZFS_AC_KERNEL_SET_CACHED_ACL_USABLE
+-      ZFS_AC_KERNEL_POSIX_ACL_CHMOD
+-      ZFS_AC_KERNEL_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T
+-      ZFS_AC_KERNEL_POSIX_ACL_VALID_WITH_NS
+-      ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION
+-      ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA
+-      ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL
+-      ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS
+-      ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL
+-      ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL
+-      ZFS_AC_KERNEL_INODE_OPERATIONS_GETATTR
++      ZFS_AC_KERNEL_XATTR
++      ZFS_AC_KERNEL_ACL
++      ZFS_AC_KERNEL_INODE_GETATTR
+       ZFS_AC_KERNEL_INODE_SET_FLAGS
+       ZFS_AC_KERNEL_INODE_SET_IVERSION
+-      ZFS_AC_KERNEL_GET_ACL_HANDLE_CACHE
+       ZFS_AC_KERNEL_SHOW_OPTIONS
+       ZFS_AC_KERNEL_FILE_INODE
+       ZFS_AC_KERNEL_FILE_DENTRY
+       ZFS_AC_KERNEL_FSYNC
+-      ZFS_AC_KERNEL_EVICT_INODE
+-      ZFS_AC_KERNEL_DIRTY_INODE_WITH_FLAGS
+-      ZFS_AC_KERNEL_NR_CACHED_OBJECTS
+-      ZFS_AC_KERNEL_FREE_CACHED_OBJECTS
+-      ZFS_AC_KERNEL_FALLOCATE
+       ZFS_AC_KERNEL_AIO_FSYNC
++      ZFS_AC_KERNEL_EVICT_INODE
++      ZFS_AC_KERNEL_DIRTY_INODE
++      ZFS_AC_KERNEL_SHRINKER
+       ZFS_AC_KERNEL_MKDIR_UMODE_T
+       ZFS_AC_KERNEL_LOOKUP_NAMEIDATA
+       ZFS_AC_KERNEL_CREATE_NAMEIDATA
+@@ -120,58 +226,38 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
+       ZFS_AC_KERNEL_CLEAR_INODE
+       ZFS_AC_KERNEL_SETATTR_PREPARE
+       ZFS_AC_KERNEL_INSERT_INODE_LOCKED
+-      ZFS_AC_KERNEL_D_MAKE_ROOT
+-      ZFS_AC_KERNEL_D_OBTAIN_ALIAS
+-      ZFS_AC_KERNEL_D_PRUNE_ALIASES
+-      ZFS_AC_KERNEL_D_SET_D_OP
+-      ZFS_AC_KERNEL_D_REVALIDATE_NAMEIDATA
+-      ZFS_AC_KERNEL_CONST_DENTRY_OPERATIONS
++      ZFS_AC_KERNEL_DENTRY
+       ZFS_AC_KERNEL_TRUNCATE_SETSIZE
+-      ZFS_AC_KERNEL_6ARGS_SECURITY_INODE_INIT_SECURITY
+-      ZFS_AC_KERNEL_CALLBACK_SECURITY_INODE_INIT_SECURITY
++      ZFS_AC_KERNEL_SECURITY_INODE
+       ZFS_AC_KERNEL_FST_MOUNT
+-      ZFS_AC_KERNEL_SHRINK
+-      ZFS_AC_KERNEL_SHRINK_CONTROL_HAS_NID
+-      ZFS_AC_KERNEL_SHRINK_CONTROL_STRUCT
+-      ZFS_AC_KERNEL_SHRINKER_CALLBACK
+-      ZFS_AC_KERNEL_S_INSTANCES_LIST_HEAD
+-      ZFS_AC_KERNEL_S_D_OP
+       ZFS_AC_KERNEL_BDI
+       ZFS_AC_KERNEL_SET_NLINK
+       ZFS_AC_KERNEL_ELEVATOR_CHANGE
+-      ZFS_AC_KERNEL_5ARG_SGET
++      ZFS_AC_KERNEL_SGET
+       ZFS_AC_KERNEL_LSEEK_EXECUTE
++      ZFS_AC_KERNEL_VFS_GETATTR
++      ZFS_AC_KERNEL_VFS_FSYNC_2ARGS
+       ZFS_AC_KERNEL_VFS_ITERATE
+-      ZFS_AC_KERNEL_VFS_RW_ITERATE
+       ZFS_AC_KERNEL_VFS_DIRECT_IO
+-      ZFS_AC_KERNEL_GENERIC_WRITE_CHECKS
++      ZFS_AC_KERNEL_VFS_RW_ITERATE
++      ZFS_AC_KERNEL_VFS_GENERIC_WRITE_CHECKS
+       ZFS_AC_KERNEL_KMAP_ATOMIC_ARGS
+       ZFS_AC_KERNEL_FOLLOW_DOWN_ONE
+       ZFS_AC_KERNEL_MAKE_REQUEST_FN
+-      ZFS_AC_KERNEL_GENERIC_IO_ACCT_3ARG
+-      ZFS_AC_KERNEL_GENERIC_IO_ACCT_4ARG
++      ZFS_AC_KERNEL_GENERIC_IO_ACCT
+       ZFS_AC_KERNEL_FPU
++      ZFS_AC_KERNEL_FMODE_T
++      ZFS_AC_KERNEL_KUIDGID_T
+       ZFS_AC_KERNEL_KUID_HELPERS
+       ZFS_AC_KERNEL_MODULE_PARAM_CALL_CONST
+       ZFS_AC_KERNEL_RENAME_WANTS_FLAGS
+-      ZFS_AC_KERNEL_HAVE_GENERIC_SETXATTR
+       ZFS_AC_KERNEL_CURRENT_TIME
+-      ZFS_AC_KERNEL_GLOBAL_PAGE_STATE
+-      ZFS_AC_KERNEL_ACL_HAS_REFCOUNT
+       ZFS_AC_KERNEL_USERNS_CAPABILITIES
+       ZFS_AC_KERNEL_IN_COMPAT_SYSCALL
+       ZFS_AC_KERNEL_KTIME_GET_COARSE_REAL_TS64
+       ZFS_AC_KERNEL_TOTALRAM_PAGES_FUNC
+       ZFS_AC_KERNEL_TOTALHIGH_PAGES
+-      ZFS_AC_KERNEL_BLK_QUEUE_DISCARD
+-      ZFS_AC_KERNEL_BLK_QUEUE_SECURE_ERASE
+       ZFS_AC_KERNEL_KSTRTOUL
+-
+-      AS_IF([test "$LINUX_OBJ" != "$LINUX"], [
+-              KERNEL_MAKE="$KERNEL_MAKE O=$LINUX_OBJ"
+-      ])
+-
+-      AC_SUBST(KERNEL_MAKE)
+ ])
+ dnl #
+@@ -190,9 +276,10 @@ AC_DEFUN([ZFS_AC_MODULE_SYMVERS], [
+               AS_IF([test ! -f "$LINUX_OBJ/$LINUX_SYMBOLS"], [
+                       AC_MSG_ERROR([
+       *** Please make sure the kernel devel package for your distribution
+-      *** is installed.  If you are building with a custom kernel, make sure the
+-      *** kernel is configured, built, and the '--with-linux=PATH' configure
+-      *** option refers to the location of the kernel source.])
++      *** is installed.  If you are building with a custom kernel, make sure
++      *** the kernel is configured, built, and the '--with-linux=PATH'
++      *** configure option refers to the location of the kernel source.
++                      ])
+               ])
+       ], [
+               LINUX_SYMBOLS=NONE
+@@ -285,12 +372,16 @@ AC_DEFUN([ZFS_AC_KERNEL], [
+               AS_IF([test -z "$kernsrcver"], [
+                       AC_MSG_RESULT([Not found])
+-                      AC_MSG_ERROR([*** Cannot determine kernel version.])
++                      AC_MSG_ERROR([
++      *** Cannot determine kernel version.
++                      ])
+               ])
+       ], [
+               AC_MSG_RESULT([Not found])
+               if test "x$enable_linux_builtin" != xyes; then
+-                      AC_MSG_ERROR([*** Cannot find UTS_RELEASE definition.])
++                      AC_MSG_ERROR([
++      *** Cannot find UTS_RELEASE definition.
++                      ])
+               else
+                       AC_MSG_ERROR([
+       *** Cannot find UTS_RELEASE definition.
+@@ -312,24 +403,27 @@ AC_DEFUN([ZFS_AC_KERNEL], [
+ ])
+ dnl #
+-dnl # Detect the QAT module to be built against
+-dnl # QAT provides hardware acceleration for data compression:
+-dnl #         https://01.org/intel-quickassist-technology
+-dnl # * Download and install QAT driver from the above link
+-dnl # * Start QAT driver in your system:
+-dnl #         service qat_service start
+-dnl # * Enable QAT in ZFS, e.g.:
+-dnl #         ./configure --with-qat=<qat-driver-path>/QAT1.6
+-dnl # make
+-dnl # * Set GZIP compression in ZFS dataset:
+-dnl #         zfs set compression = gzip <dataset>
+-dnl # Then the data written to this ZFS pool is compressed
+-dnl # by QAT accelerator automatically, and de-compressed by
+-dnl # QAT when read from the pool.
+-dnl # * Get QAT hardware statistics by:
+-dnl # cat /proc/icp_dh895xcc_dev/qat
+-dnl # * To disable QAT:
+-dnl #         insmod zfs.ko zfs_qat_disable=1
++dnl # Detect the QAT module to be built against, QAT provides hardware
++dnl # acceleration for data compression:
++dnl #
++dnl # https://01.org/intel-quickassist-technology
++dnl #
++dnl # 1) Download and install QAT driver from the above link
++dnl # 2) Start QAT driver in your system:
++dnl #          service qat_service start
++dnl # 3) Enable QAT in ZFS, e.g.:
++dnl #          ./configure --with-qat=<qat-driver-path>/QAT1.6
++dnl #          make
++dnl # 4) Set GZIP compression in ZFS dataset:
++dnl #          zfs set compression = gzip <dataset>
++dnl #
++dnl # Then the data written to this ZFS pool is compressed by QAT accelerator
++dnl # automatically, and de-compressed by QAT when read from the pool.
++dnl #
++dnl # 1) Get QAT hardware statistics with:
++dnl #  cat /proc/icp_dh895xcc_dev/qat
++dnl # 2) To disable QAT:
++dnl #          insmod zfs.ko zfs_qat_disable=1
+ dnl #
+ AC_DEFUN([ZFS_AC_QAT], [
+       AC_ARG_WITH([qat],
+@@ -350,11 +444,11 @@ AC_DEFUN([ZFS_AC_QAT], [
+               QAT_SRC="${qatsrc}/quickassist"
+               AS_IF([ test ! -e "$QAT_SRC/include/cpa.h"], [
+                       AC_MSG_ERROR([
+-              *** Please make sure the qat driver package is installed
+-              *** and specify the location of the qat source with the
+-              *** '--with-qat=PATH' option then try again. Failed to
+-              *** find cpa.h in:
+-              ${QAT_SRC}/include])
++      *** Please make sure the qat driver package is installed
++      *** and specify the location of the qat source with the
++      *** '--with-qat=PATH' option then try again. Failed to
++      *** find cpa.h in:
++      ${QAT_SRC}/include])
+               ])
+       ])
+@@ -368,9 +462,9 @@ AC_DEFUN([ZFS_AC_QAT], [
+               QAT_OBJ=${qatbuild}
+               AS_IF([ ! test -e "$QAT_OBJ/icp_qa_al.ko" && ! test -e "$QAT_OBJ/qat_api.ko"], [
+                       AC_MSG_ERROR([
+-              *** Please make sure the qat driver is installed then try again.
+-              *** Failed to find icp_qa_al.ko or qat_api.ko in:
+-              $QAT_OBJ])
++      *** Please make sure the qat driver is installed then try again.
++      *** Failed to find icp_qa_al.ko or qat_api.ko in:
++      $QAT_OBJ])
+               ])
+               AC_SUBST(QAT_SRC)
+@@ -391,10 +485,10 @@ AC_DEFUN([ZFS_AC_QAT], [
+                       AC_MSG_RESULT([$QAT_SYMBOLS])
+                       AC_SUBST(QAT_SYMBOLS)
+               ],[
+-                       AC_MSG_ERROR([
+-                      *** Please make sure the qat driver is installed then try again.
+-                      *** Failed to find Module.symvers in:
+-                      $QAT_SYMBOLS])
++                      AC_MSG_ERROR([
++      *** Please make sure the qat driver is installed then try again.
++      *** Failed to find Module.symvers in:
++      $QAT_SYMBOLS
+                       ])
+               ])
+       ])
+@@ -403,14 +497,16 @@ AC_DEFUN([ZFS_AC_QAT], [
+ dnl #
+ dnl # Basic toolchain sanity check.
+ dnl #
+-AC_DEFUN([ZFS_AC_TEST_MODULE], [
++AC_DEFUN([ZFS_AC_KERNEL_TEST_MODULE], [
+       AC_MSG_CHECKING([whether modules can be built])
+-      ZFS_LINUX_TRY_COMPILE([],[],[
++      ZFS_LINUX_TRY_COMPILE([], [], [
+               AC_MSG_RESULT([yes])
+       ],[
+               AC_MSG_RESULT([no])
+               if test "x$enable_linux_builtin" != xyes; then
+-                      AC_MSG_ERROR([*** Unable to build an empty module.])
++                      AC_MSG_ERROR([
++      *** Unable to build an empty module.
++                      ])
+               else
+                       AC_MSG_ERROR([
+       *** Unable to build an empty module.
+@@ -420,207 +516,313 @@ AC_DEFUN([ZFS_AC_TEST_MODULE], [
+ ])
+ dnl #
+-dnl # Certain kernel build options are not supported.  These must be
+-dnl # detected at configure time and cause a build failure.  Otherwise
+-dnl # modules may be successfully built that behave incorrectly.
++dnl # ZFS_LINUX_CONFTEST_H
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_CONFIG], [
+-      AS_IF([test "x$cross_compiling" != xyes], [
+-              AC_RUN_IFELSE([
+-                      AC_LANG_PROGRAM([
+-                              #include "$LINUX/include/linux/license.h"
+-                      ], [
+-                              return !license_is_gpl_compatible("$ZFS_META_LICENSE");
+-                      ])
+-              ], [
+-                      AC_DEFINE([ZFS_IS_GPL_COMPATIBLE], [1],
+-                          [Define to 1 if GPL-only symbols can be used])
+-              ], [
+-              ])
+-      ])
++AC_DEFUN([ZFS_LINUX_CONFTEST_H], [
++test -d build/$2 || mkdir -p build/$2
++cat - <<_ACEOF >build/$2/$2.h
++$1
++_ACEOF
++])
+-      ZFS_AC_KERNEL_CONFIG_THREAD_SIZE
+-      ZFS_AC_KERNEL_CONFIG_DEBUG_LOCK_ALLOC
+-      ZFS_AC_KERNEL_CONFIG_TRIM_UNUSED_KSYMS
+-      ZFS_AC_KERNEL_CONFIG_ZLIB_INFLATE
+-      ZFS_AC_KERNEL_CONFIG_ZLIB_DEFLATE
++dnl #
++dnl # ZFS_LINUX_CONFTEST_C
++dnl #
++AC_DEFUN([ZFS_LINUX_CONFTEST_C], [
++test -d build/$2 || mkdir -p build/$2
++cat confdefs.h - <<_ACEOF >build/$2/$2.c
++$1
++_ACEOF
+ ])
+ dnl #
+-dnl # Check configured THREAD_SIZE
++dnl # ZFS_LINUX_CONFTEST_MAKEFILE
+ dnl #
+-dnl # The stack size will vary by architecture, but as of Linux 3.15 on x86_64
+-dnl # the default thread stack size was increased to 16K from 8K.  Therefore,
+-dnl # on newer kernels and some architectures stack usage optimizations can be
+-dnl # conditionally applied to improve performance without negatively impacting
+-dnl # stability.
++dnl # $1 - test case name
++dnl # $2 - add to top-level Makefile
++dnl # $3 - additional build flags
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_CONFIG_THREAD_SIZE], [
+-      AC_MSG_CHECKING([whether kernel was built with 16K or larger stacks])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/module.h>
+-      ],[
+-              #if (THREAD_SIZE < 16384)
+-              #error "THREAD_SIZE is less than 16K"
+-              #endif
+-      ],[
+-              AC_MSG_RESULT([yes])
+-              AC_DEFINE(HAVE_LARGE_STACKS, 1, [kernel has large stacks])
+-      ],[
+-              AC_MSG_RESULT([no])
+-      ])
++AC_DEFUN([ZFS_LINUX_CONFTEST_MAKEFILE], [
++      test -d build || mkdir -p build
++      test -d build/$1 || mkdir -p build/$1
++
++      file=build/$1/Makefile
++
++      dnl # Example command line to manually build source.
++      cat - <<_ACEOF >$file
++# Example command line to manually build source
++# make modules -C $LINUX_OBJ $ARCH_UM M=$PWD/build/$1
++
++ccflags-y := -Werror $FRAME_LARGER_THAN
++_ACEOF
++
++      dnl # Additional custom CFLAGS as requested.
++      m4_ifval($3, [echo "ccflags-y += $3" >>$file], [])
++
++      dnl # Test case source
++      echo "obj-m := $1.o" >>$file
++
++      AS_IF([test "x$2" = "xyes"], [echo "obj-m += $1/" >>build/Makefile], [])
+ ])
+ dnl #
+-dnl # Check CONFIG_DEBUG_LOCK_ALLOC
++dnl # ZFS_LINUX_TEST_PROGRAM(C)([PROLOGUE], [BODY])
+ dnl #
+-dnl # This is typically only set for debug kernels because it comes with
+-dnl # a performance penalty.  However, when it is set it maps the non-GPL
+-dnl # symbol mutex_lock() to the GPL-only mutex_lock_nested() symbol.
+-dnl # This will cause a failure at link time which we'd rather know about
+-dnl # at compile time.
++m4_define([ZFS_LINUX_TEST_PROGRAM], [
++$1
++int
++main (void)
++{
++$2
++      ;
++      return 0;
++}
++])
++
+ dnl #
+-dnl # Since we plan to pursue making mutex_lock_nested() a non-GPL symbol
+-dnl # with the upstream community we add a check to detect this case.
++dnl # ZFS_LINUX_TEST_REMOVE
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_CONFIG_DEBUG_LOCK_ALLOC], [
+-
+-      ZFS_LINUX_CONFIG([DEBUG_LOCK_ALLOC], [
+-              AC_MSG_CHECKING([whether mutex_lock() is GPL-only])
+-              tmp_flags="$EXTRA_KCFLAGS"
+-              ZFS_LINUX_TRY_COMPILE([
+-                      #include <linux/module.h>
+-                      #include <linux/mutex.h>
+-
+-                      MODULE_LICENSE("$ZFS_META_LICENSE");
+-              ],[
+-                      struct mutex lock;
++dnl # Removes the specified test source and results.
++dnl #
++AC_DEFUN([ZFS_LINUX_TEST_REMOVE], [
++      test -d build/$1 && rm -Rf build/$1
++      test -f build/Makefile && sed '/$1/d' build/Makefile
++])
+-                      mutex_init(&lock);
+-                      mutex_lock(&lock);
+-                      mutex_unlock(&lock);
+-              ],[
+-                      AC_MSG_RESULT(no)
+-              ],[
+-                      AC_MSG_RESULT(yes)
+-                      AC_MSG_ERROR([
+-      *** Kernel built with CONFIG_DEBUG_LOCK_ALLOC which is incompatible
+-      *** with the CDDL license and will prevent the module linking stage
+-      *** from succeeding.  You must rebuild your kernel without this
+-      *** option enabled.])
+-              ])
+-              EXTRA_KCFLAGS="$tmp_flags"
+-      ], [])
++dnl #
++dnl # ZFS_LINUX_COMPILE
++dnl #
++dnl # $1 - build dir
++dnl # $2 - test command
++dnl # $3 - pass command
++dnl # $4 - fail command
++dnl # $5 - set KBUILD_MODPOST_NOFINAL='yes'
++dnl # $6 - set KBUILD_MODPOST_WARN='yes'
++dnl #
++dnl # Used internally by ZFS_LINUX_TEST_{COMPILE,MODPOST}
++dnl #
++AC_DEFUN([ZFS_LINUX_COMPILE], [
++      AC_TRY_COMMAND([
++          KBUILD_MODPOST_NOFINAL="$5" KBUILD_MODPOST_WARN="$6"
++          make modules -k -j$TEST_JOBS -C $LINUX_OBJ $ARCH_UM
++          M=$PWD/$1 &>$1/build.log])
++      AS_IF([AC_TRY_COMMAND([$2])], [$3], [$4])
+ ])
+ dnl #
+-dnl # Check CONFIG_TRIM_UNUSED_KSYMS
++dnl # ZFS_LINUX_TEST_COMPILE
+ dnl #
+-dnl # Verify the kernel has CONFIG_TRIM_UNUSED_KSYMS disabled.
++dnl # Perform a full compile excluding the final modpost phase.
+ dnl #
+-AC_DEFUN([ZFS_AC_KERNEL_CONFIG_TRIM_UNUSED_KSYMS], [
+-      AC_MSG_CHECKING([whether CONFIG_TRIM_UNUSED_KSYM is disabled])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #if defined(CONFIG_TRIM_UNUSED_KSYMS)
+-              #error CONFIG_TRIM_UNUSED_KSYMS not defined
+-              #endif
+-      ],[ ],[
+-              AC_MSG_RESULT([yes])
++AC_DEFUN([ZFS_LINUX_TEST_COMPILE], [
++      ZFS_LINUX_COMPILE([$2], [test -f $2/build.log], [
++              mv $2/Makefile $2/Makefile.compile.$1
++              mv $2/build.log $2/build.log.$1
+       ],[
+-              AC_MSG_RESULT([no])
+-              AS_IF([test "x$enable_linux_builtin" != xyes], [
+-                      AC_MSG_ERROR([
+-      *** This kernel has unused symbols trimming enabled, please disable.
+-      *** Rebuild the kernel with CONFIG_TRIM_UNUSED_KSYMS=n set.])
+-      ])])
++              AC_MSG_ERROR([
++        *** Unable to compile test source to determine kernel interfaces.])
++      ], [yes], [])
+ ])
+ dnl #
+-dnl # ZFS_LINUX_CONFTEST_H
++dnl # ZFS_LINUX_TEST_MODPOST
+ dnl #
+-AC_DEFUN([ZFS_LINUX_CONFTEST_H], [
+-cat - <<_ACEOF >conftest.h
+-$1
+-_ACEOF
++dnl # Perform a full compile including the modpost phase.  This may
++dnl # be an incremental build if the objects have already been built.
++dnl #
++AC_DEFUN([ZFS_LINUX_TEST_MODPOST], [
++      ZFS_LINUX_COMPILE([$2], [test -f $2/build.log], [
++              mv $2/Makefile $2/Makefile.modpost.$1
++              cat $2/build.log >>build/build.log.$1
++      ],[
++              AC_MSG_ERROR([
++        *** Unable to modpost test source to determine kernel interfaces.])
++      ], [], [yes])
+ ])
+ dnl #
+-dnl # ZFS_LINUX_CONFTEST_C
++dnl # Perform the compilation of the test cases in two phases.
+ dnl #
+-AC_DEFUN([ZFS_LINUX_CONFTEST_C], [
+-cat confdefs.h - <<_ACEOF >conftest.c
+-$1
+-_ACEOF
++dnl # Phase 1) attempt to build the object files for all of the tests
++dnl #          defined by the ZFS_LINUX_TEST_SRC macro.  But do not
++dnl #          perform the final modpost stage.
++dnl #
++dnl # Phase 2) disable all tests which failed the initial compilation,
++dnl #          then invoke the final modpost step for the remaining tests.
++dnl #
++dnl # This allows us efficiently build the test cases in parallel while
++dnl # remaining resilient to build failures which are expected when
++dnl # detecting the available kernel interfaces.
++dnl #
++dnl # The maximum allowed parallelism can be controlled by setting the
++dnl # TEST_JOBS environment variable.  Otherwise, it default to $(nproc).
++dnl #
++AC_DEFUN([ZFS_LINUX_TEST_COMPILE_ALL], [
++      dnl # Phase 1 - Compilation only, final linking is skipped.
++      ZFS_LINUX_TEST_COMPILE([$1], [build])
++
++      dnl #
++      dnl # Phase 2 - When building external modules disable test cases
++      dnl # which failed to compile and invoke modpost to verify the
++      dnl # final linking.
++      dnl #
++      dnl # Test names suffixed with '_license' call modpost independently
++      dnl # to ensure that a single incompatibility does not result in the
++      dnl # modpost phase exiting early.  This check is not performed on
++      dnl # every symbol since the majority are compatible and doing so
++      dnl # would significantly slow down this phase.
++      dnl #
++      dnl # When configuring for builtin (--enable-linux-builtin)
++      dnl # fake the linking step artificially create the expected .ko
++      dnl # files for tests which did compile.  This is required for
++      dnl # kernels which do not have loadable module support or have
++      dnl # not yet been built.
++      dnl #
++      AS_IF([test "x$enable_linux_builtin" = "xno"], [
++              for dir in $(awk '/^obj-m/ { print [$]3 }' \
++                  build/Makefile.compile.$1); do
++                      name=${dir%/}
++                      AS_IF([test -f build/$name/$name.o], [
++                              AS_IF([test "${name##*_}" = "license"], [
++                                      ZFS_LINUX_TEST_MODPOST([$1],
++                                          [build/$name])
++                                      echo "obj-n += $dir" >>build/Makefile
++                              ], [
++                                      echo "obj-m += $dir" >>build/Makefile
++                              ])
++                      ], [
++                              echo "obj-n += $dir" >>build/Makefile
++                      ])
++              done
++
++              ZFS_LINUX_TEST_MODPOST([$1], [build])
++      ], [
++              for dir in $(awk '/^obj-m/ { print [$]3 }' \
++                  build/Makefile.compile.$1); do
++                      name=${dir%/}
++                      AS_IF([test -f build/$name/$name.o], [
++                              touch build/$name/$name.ko
++                      ])
++              done
++      ])
+ ])
+ dnl #
+-dnl # ZFS_LANG_PROGRAM(C)([PROLOGUE], [BODY])
++dnl # ZFS_LINUX_TEST_SRC
+ dnl #
+-m4_define([ZFS_LANG_PROGRAM], [
+-$1
+-int
+-main (void)
+-{
+-dnl Do *not* indent the following line: there may be CPP directives.
+-dnl Don't move the `;' right after for the same reason.
+-$2
+-  ;
+-  return 0;
+-}
++dnl # $1 - name
++dnl # $2 - global
++dnl # $3 - source
++dnl # $4 - extra cflags
++dnl # $5 - check license-compatibility
++dnl #
++dnl # N.B because all of the test cases are compiled in parallel they
++dnl # must never depend on the results of previous tests.  Each test
++dnl # needs to be entirely independent.
++dnl #
++AC_DEFUN([ZFS_LINUX_TEST_SRC], [
++      ZFS_LINUX_CONFTEST_C([ZFS_LINUX_TEST_PROGRAM([[$2]], [[$3]])], [$1])
++      ZFS_LINUX_CONFTEST_MAKEFILE([$1], [yes], [$4])
++
++      AS_IF([ test -n "$5" ], [
++              ZFS_LINUX_CONFTEST_C([ZFS_LINUX_TEST_PROGRAM([[
++                      #include <linux/module.h>
++                      MODULE_LICENSE("$5");
++                      $2]], [[$3]])], [$1_license])
++              ZFS_LINUX_CONFTEST_MAKEFILE([$1_license], [yes], [$4])
++      ])
+ ])
+ dnl #
+-dnl # ZFS_LINUX_COMPILE_IFELSE / like AC_COMPILE_IFELSE
++dnl # ZFS_LINUX_TEST_RESULT
+ dnl #
+-AC_DEFUN([ZFS_LINUX_COMPILE_IFELSE], [
+-      m4_ifvaln([$1], [ZFS_LINUX_CONFTEST_C([$1])])
+-      m4_ifvaln([$6], [ZFS_LINUX_CONFTEST_H([$6])], [ZFS_LINUX_CONFTEST_H([])])
+-      rm -Rf build && mkdir -p build && touch build/conftest.mod.c
+-      echo "obj-m := conftest.o" >build/Makefile
+-      modpost_flag=''
+-      test "x$enable_linux_builtin" = xyes && modpost_flag='modpost=true' # fake modpost stage
+-      AS_IF(
+-              [AC_TRY_COMMAND(cp conftest.c conftest.h build && make [$2] -C $LINUX_OBJ EXTRA_CFLAGS="-Werror $FRAME_LARGER_THAN $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build $modpost_flag) >/dev/null && AC_TRY_COMMAND([$3])],
+-              [$4],
+-              [_AC_MSG_LOG_CONFTEST m4_ifvaln([$5],[$5])]
+-      )
+-      rm -Rf build
++dnl # $1 - name of a test source (ZFS_LINUX_TEST_SRC)
++dnl # $2 - run on success (valid .ko generated)
++dnl # $3 - run on failure (unable to compile)
++dnl #
++AC_DEFUN([ZFS_LINUX_TEST_RESULT], [
++      AS_IF([test -d build/$1], [
++              AS_IF([test -f build/$1/$1.ko], [$2], [$3])
++      ], [
++              AC_MSG_ERROR([
++      *** No matching source for the "$1" test, check that
++      *** both the test source and result macros refer to the same name.
++              ])
++      ])
+ ])
+ dnl #
+-dnl # ZFS_LINUX_TRY_COMPILE like AC_TRY_COMPILE
++dnl # ZFS_LINUX_TEST_ERROR
+ dnl #
+-AC_DEFUN([ZFS_LINUX_TRY_COMPILE],
+-      [ZFS_LINUX_COMPILE_IFELSE(
+-      [AC_LANG_SOURCE([ZFS_LANG_PROGRAM([[$1]], [[$2]])])],
+-      [modules],
+-      [test -s build/conftest.o],
+-      [$3], [$4])
++dnl # Generic error message which can be used when none of the expected
++dnl # kernel interfaces were detected.
++dnl #
++AC_DEFUN([ZFS_LINUX_TEST_ERROR], [
++      AC_MSG_ERROR([
++      *** None of the expected "$1" interfaces were detected.
++      *** This may be because your kernel version is newer than what is
++      *** supported, or you are using a patched custom kernel with
++      *** incompatible modifications.
++      ***
++      *** ZFS Version: $ZFS_META_ALIAS
++      *** Compatible Kernels: $ZFS_META_KVER_MIN - $ZFS_META_KVER_MAX
++      ])
+ ])
+ dnl #
+-dnl # ZFS_LINUX_CONFIG
++dnl # ZFS_LINUX_TEST_RESULT_SYMBOL
+ dnl #
+-AC_DEFUN([ZFS_LINUX_CONFIG],
+-      [AC_MSG_CHECKING([whether kernel was built with CONFIG_$1])
+-      ZFS_LINUX_TRY_COMPILE([
+-              #include <linux/module.h>
+-      ],[
+-              #ifndef CONFIG_$1
+-              #error CONFIG_$1 not #defined
+-              #endif
+-      ],[
+-              AC_MSG_RESULT([yes])
+-              $2
+-      ],[
+-              AC_MSG_RESULT([no])
+-              $3
++dnl # Like ZFS_LINUX_TEST_RESULT except ZFS_CHECK_SYMBOL_EXPORT is called to
++dnl # verify symbol exports, unless --enable-linux-builtin was provided to
++dnl # configure.
++dnl #
++AC_DEFUN([ZFS_LINUX_TEST_RESULT_SYMBOL], [
++      AS_IF([ ! test -f build/$1/$1.ko], [
++              $5
++      ], [
++              AS_IF([test "x$enable_linux_builtin" != "xyes"], [
++                      ZFS_CHECK_SYMBOL_EXPORT([$2], [$3], [$4], [$5])
++              ], [
++                      $4
++              ])
+       ])
+ ])
++dnl #
++dnl # ZFS_LINUX_COMPILE_IFELSE
++dnl #
++AC_DEFUN([ZFS_LINUX_COMPILE_IFELSE], [
++      ZFS_LINUX_TEST_REMOVE([conftest])
++
++      m4_ifvaln([$1], [ZFS_LINUX_CONFTEST_C([$1], [conftest])])
++      m4_ifvaln([$5], [ZFS_LINUX_CONFTEST_H([$5], [conftest])],
++          [ZFS_LINUX_CONFTEST_H([], [conftest])])
++
++      ZFS_LINUX_CONFTEST_MAKEFILE([conftest], [no],
++          [m4_ifvaln([$5], [-I$PWD/build/conftest], [])])
++      ZFS_LINUX_COMPILE([build/conftest], [$2], [$3], [$4], [], [])
++])
++
++dnl #
++dnl # ZFS_LINUX_TRY_COMPILE
++dnl #
++dnl # $1 - global
++dnl # $2 - source
++dnl # $3 - run on success (valid .ko generated)
++dnl # $4 - run on failure (unable to compile)
++dnl #
++AC_DEFUN([ZFS_LINUX_TRY_COMPILE], [
++      ZFS_LINUX_COMPILE_IFELSE(
++          [ZFS_LINUX_TEST_PROGRAM([[$1]], [[$2]])],
++          [test -f build/conftest/conftest.ko],
++          [$3], [$4])
++])
++
+ dnl #
+ dnl # ZFS_CHECK_SYMBOL_EXPORT
+-dnl # check symbol exported or not
++dnl #
++dnl # Check if a symbol is exported on not by consulting the symbols
++dnl # file, or optionally the source code.
+ dnl #
+ AC_DEFUN([ZFS_CHECK_SYMBOL_EXPORT], [
+       grep -q -E '[[[:space:]]]$1[[[:space:]]]' \
+@@ -649,8 +851,10 @@ AC_DEFUN([ZFS_CHECK_SYMBOL_EXPORT], [
+ dnl #
+ dnl # ZFS_LINUX_TRY_COMPILE_SYMBOL
+-dnl # like ZFS_LINUX_TRY_COMPILE, except ZFS_CHECK_SYMBOL_EXPORT
+-dnl # is called if not compiling for builtin
++dnl #
++dnl # Like ZFS_LINUX_TRY_COMPILER except ZFS_CHECK_SYMBOL_EXPORT is called
++dnl # to verify symbol exports, unless --enable-linux-builtin was provided
++dnl # to configure.
+ dnl #
+ AC_DEFUN([ZFS_LINUX_TRY_COMPILE_SYMBOL], [
+       ZFS_LINUX_TRY_COMPILE([$1], [$2], [rc=0], [rc=1])
+@@ -673,10 +877,9 @@ dnl # ZFS_LINUX_TRY_COMPILE_HEADER
+ dnl # like ZFS_LINUX_TRY_COMPILE, except the contents conftest.h are
+ dnl # provided via the fifth parameter
+ dnl #
+-AC_DEFUN([ZFS_LINUX_TRY_COMPILE_HEADER],
+-      [ZFS_LINUX_COMPILE_IFELSE(
+-      [AC_LANG_SOURCE([ZFS_LANG_PROGRAM([[$1]], [[$2]])])],
+-      [modules],
+-      [test -s build/conftest.o],
+-      [$3], [$4], [$5])
++AC_DEFUN([ZFS_LINUX_TRY_COMPILE_HEADER], [
++      ZFS_LINUX_COMPILE_IFELSE(
++          [ZFS_LINUX_TEST_PROGRAM([[$1]], [[$2]])],
++          [test -f build/conftest/conftest.ko],
++          [$3], [$4], [$5])
+ ])
+diff --git a/config/zfs-build.m4 b/config/zfs-build.m4
+index 8e221f2d7..d2c355425 100644
+--- a/config/zfs-build.m4
++++ b/config/zfs-build.m4
+@@ -166,6 +166,17 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS], [
+ ])
+ AC_DEFUN([ZFS_AC_CONFIG], [
++
++        dnl # Remove the previous build test directory.
++        rm -Rf build
++
++      AC_ARG_VAR([TEST_JOBS],
++          [simultaneous jobs during configure (defaults to $(nproc))])
++      if test "x$ac_cv_env_TEST_JOBS_set" != "xset"; then
++              TEST_JOBS=$(nproc)
++      fi
++      AC_SUBST(TEST_JOBS)
++
+       ZFS_CONFIG=all
+       AC_ARG_WITH([config],
+               AS_HELP_STRING([--with-config=CONFIG],
+diff --git a/config/zfs-meta.m4 b/config/zfs-meta.m4
+index f525e2010..660d8ccb9 100644
+--- a/config/zfs-meta.m4
++++ b/config/zfs-meta.m4
+@@ -162,6 +162,24 @@ AC_DEFUN([ZFS_AC_META], [
+                       AC_SUBST([ZFS_META_AUTHOR])
+               fi
++              ZFS_META_KVER_MIN=_ZFS_AC_META_GETVAL([Linux-Minimum]);
++              if test -n "$ZFS_META_KVER_MIN"; then
++                      AC_DEFINE_UNQUOTED([ZFS_META_KVER_MIN],
++                          ["$ZFS_META_KVER_MIN"],
++                          [Define the minimum compatible kernel version.]
++                      )
++                      AC_SUBST([ZFS_META_KVER_MIN])
++              fi
++
++              ZFS_META_KVER_MAX=_ZFS_AC_META_GETVAL([Linux-Maximum]);
++              if test -n "$ZFS_META_KVER_MAX"; then
++                      AC_DEFINE_UNQUOTED([ZFS_META_KVER_MAX],
++                          ["$ZFS_META_KVER_MAX"],
++                          [Define the maximum compatible kernel version.]
++                      )
++                      AC_SUBST([ZFS_META_KVER_MAX])
++              fi
++
+               m4_pattern_allow([^LT_(CURRENT|REVISION|AGE)$])
+               ZFS_META_LT_CURRENT=_ZFS_AC_META_GETVAL([LT_Current]);
+               ZFS_META_LT_REVISION=_ZFS_AC_META_GETVAL([LT_Revision]);
diff --git a/debian/patches/0008-Linux-4.14-4.19-5.0-compat-SIMD-save-restore.patch b/debian/patches/0008-Linux-4.14-4.19-5.0-compat-SIMD-save-restore.patch
new file mode 100644 (file)
index 0000000..5b5ab1d
--- /dev/null
@@ -0,0 +1,333 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Brian Behlendorf <behlendorf1@llnl.gov>
+Date: Thu, 3 Oct 2019 00:03:20 +0000
+Subject: [PATCH] Linux 4.14, 4.19, 5.0+ compat: SIMD save/restore
+
+Contrary to initial testing we cannot rely on these kernels to
+invalidate the per-cpu FPU state and restore the FPU registers.
+Therefore, the kfpu_begin() and kfpu_end() functions have been
+updated to unconditionally save and restore the FPU state.
+
+Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
+Issue #9346
+(cherry picked from commit 813fd014a90229127f80b970a8fef5049fd4c713)
+Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
+---
+ config/kernel-fpu.m4     |  82 +++++++++++----------
+ include/linux/simd_x86.h | 152 ++++++++++++++++++++++++++++-----------
+ 2 files changed, 155 insertions(+), 79 deletions(-)
+
+diff --git a/config/kernel-fpu.m4 b/config/kernel-fpu.m4
+index a2c47d65a..9ed9b14ad 100644
+--- a/config/kernel-fpu.m4
++++ b/config/kernel-fpu.m4
+@@ -2,15 +2,9 @@ dnl #
+ dnl # Handle differences in kernel FPU code.
+ dnl #
+ dnl # Kernel
+-dnl # 5.2:    The fpu->initialized flag was replaced by TIF_NEED_FPU_LOAD.
+-dnl #         HAVE_KERNEL_TIF_NEED_FPU_LOAD
+-dnl #
+-dnl # 5.0:    As an optimization SIMD operations performed by kernel
+-dnl #         threads can skip saving and restoring their FPU context.
+-dnl #         Wrappers have been introduced to determine the running
+-dnl #         context and use either the SIMD or generic implementation.
++dnl # 5.0:    Wrappers have been introduced to save/restore the FPU state.
+ dnl #         This change was made to the 4.19.38 and 4.14.120 LTS kernels.
+-dnl #         HAVE_KERNEL_FPU_INITIALIZED
++dnl #         HAVE_KERNEL_FPU_INTERNAL
+ dnl #
+ dnl # 4.2:    Use __kernel_fpu_{begin,end}()
+ dnl #         HAVE_UNDERSCORE_KERNEL_FPU & KERNEL_EXPORTS_X86_FPU
+@@ -61,22 +55,47 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_FPU], [
+               __kernel_fpu_end();
+       ], [], [$ZFS_META_LICENSE])
+-      ZFS_LINUX_TEST_SRC([fpu_initialized], [
+-              #include <linux/module.h>
++      ZFS_LINUX_TEST_SRC([fpu_internal], [
++              #if defined(__x86_64) || defined(__x86_64__) || \
++                  defined(__i386) || defined(__i386__)
++              #if !defined(__x86)
++              #define __x86
++              #endif
++              #endif
++
++              #if !defined(__x86)
++              #error Unsupported architecture
++              #endif
++
+               #include <linux/sched.h>
+-      ],[
+-              struct fpu *fpu = &current->thread.fpu;
+-              if (fpu->initialized) { return (0); };
+-      ])
+-      ZFS_LINUX_TEST_SRC([tif_need_fpu_load], [
+-              #include <linux/module.h>
+-              #include <asm/thread_info.h>
++              #if !defined(PF_KTHREAD)
++              #error PF_KTHREAD not defined
++              #endif
+-              #if !defined(TIF_NEED_FPU_LOAD)
+-              #error "TIF_NEED_FPU_LOAD undefined"
++              #ifdef HAVE_KERNEL_FPU_API_HEADER
++              #include <asm/fpu/api.h>
++              #include <asm/fpu/internal.h>
++              #else
++              #include <asm/i387.h>
++              #include <asm/xcr.h>
++              #endif
++
++              #if !defined(XSTATE_XSAVE)
++              #error XSTATE_XSAVE not defined
++              #endif
++
++              #if !defined(XSTATE_XRESTORE)
++              #error XSTATE_XRESTORE not defined
+               #endif
+-      ],[])
++      ],[
++              struct fpu *fpu = &current->thread.fpu;
++              union fpregs_state *st = &fpu->state;
++              struct fregs_state *fr __attribute__ ((unused)) = &st->fsave;
++              struct fxregs_state *fxr __attribute__ ((unused)) = &st->fxsave;
++              struct xregs_state *xr __attribute__ ((unused)) = &st->xsave;
++              fpu->last_cpu = -1;
++      ])
+ ])
+ AC_DEFUN([ZFS_AC_KERNEL_FPU], [
+@@ -104,25 +123,12 @@ AC_DEFUN([ZFS_AC_KERNEL_FPU], [
+                       AC_DEFINE(KERNEL_EXPORTS_X86_FPU, 1,
+                           [kernel exports FPU functions])
+               ],[
+-                      dnl #
+-                      dnl # Linux 5.0 kernel
+-                      dnl #
+-                      ZFS_LINUX_TEST_RESULT([fpu_initialized], [
+-                              AC_MSG_RESULT(fpu.initialized)
+-                              AC_DEFINE(HAVE_KERNEL_FPU_INITIALIZED, 1,
+-                                  [kernel fpu.initialized exists])
++                      ZFS_LINUX_TEST_RESULT([fpu_internal], [
++                              AC_MSG_RESULT(internal)
++                              AC_DEFINE(HAVE_KERNEL_FPU_INTERNAL, 1,
++                                  [kernel fpu internal])
+                       ],[
+-                              dnl #
+-                              dnl # Linux 5.2 kernel
+-                              dnl #
+-                              ZFS_LINUX_TEST_RESULT([tif_need_fpu_load], [
+-                                      AC_MSG_RESULT(TIF_NEED_FPU_LOAD)
+-                                      AC_DEFINE(
+-                                          HAVE_KERNEL_TIF_NEED_FPU_LOAD, 1,
+-                                          [kernel TIF_NEED_FPU_LOAD exists])
+-                              ],[
+-                                      AC_MSG_RESULT(unavailable)
+-                              ])
++                              AC_MSG_RESULT(unavailable)
+                       ])
+               ])
+       ])
+diff --git a/include/linux/simd_x86.h b/include/linux/simd_x86.h
+index 641f43955..d1ded3af2 100644
+--- a/include/linux/simd_x86.h
++++ b/include/linux/simd_x86.h
+@@ -126,38 +126,68 @@
+ #endif
+ #else /* defined(KERNEL_EXPORTS_X86_FPU) */
++
+ /*
+  * When the kernel_fpu_* symbols are unavailable then provide our own
+  * versions which allow the FPU to be safely used in kernel threads.
+  * In practice, this is not a significant restriction for ZFS since the
+  * vast majority of SIMD operations are performed by the IO pipeline.
+  */
++#if defined(HAVE_KERNEL_FPU_INTERNAL)
+ /*
+- * Returns non-zero if FPU operations are allowed in the current context.
++ * FPU usage only allowed in dedicated kernel threads.
+  */
+-#if defined(HAVE_KERNEL_TIF_NEED_FPU_LOAD)
+-#define       kfpu_allowed()          ((current->flags & PF_KTHREAD) && \
+-                              test_thread_flag(TIF_NEED_FPU_LOAD))
+-#elif defined(HAVE_KERNEL_FPU_INITIALIZED)
+-#define       kfpu_allowed()          ((current->flags & PF_KTHREAD) && \
+-                              current->thread.fpu.initialized)
+-#else
+-#define       kfpu_allowed()          0
+-#endif
++#define       kfpu_allowed()          (current->flags & PF_KTHREAD)
++#define       ex_handler_fprestore    ex_handler_default
++
++/*
++ * FPU save and restore instructions.
++ */
++#define       __asm                   __asm__ __volatile__
++#define       kfpu_fxsave(addr)       __asm("fxsave %0" : "=m" (*(addr)))
++#define       kfpu_fxsaveq(addr)      __asm("fxsaveq %0" : "=m" (*(addr)))
++#define       kfpu_fnsave(addr)       __asm("fnsave %0; fwait" : "=m" (*(addr)))
++#define       kfpu_fxrstor(addr)      __asm("fxrstor %0" : : "m" (*(addr)))
++#define       kfpu_fxrstorq(addr)     __asm("fxrstorq %0" : : "m" (*(addr)))
++#define       kfpu_frstor(addr)       __asm("frstor %0" : : "m" (*(addr)))
++#define       kfpu_fxsr_clean(rval)   __asm("fnclex; emms; fildl %P[addr]" \
++                                  : : [addr] "m" (rval));
+ static inline void
+ kfpu_initialize(void)
+ {
+       WARN_ON_ONCE(!(current->flags & PF_KTHREAD));
+-#if defined(HAVE_KERNEL_TIF_NEED_FPU_LOAD)
+-      __fpu_invalidate_fpregs_state(&current->thread.fpu);
+-      set_thread_flag(TIF_NEED_FPU_LOAD);
+-#elif defined(HAVE_KERNEL_FPU_INITIALIZED)
+-      __fpu_invalidate_fpregs_state(&current->thread.fpu);
+-      current->thread.fpu.initialized = 1;
+-#endif
++      /* Invalidate the task's FPU state */
++      current->thread.fpu.last_cpu = -1;
++}
++
++static inline void
++kfpu_save_xsave(struct xregs_state *addr, uint64_t mask)
++{
++      uint32_t low, hi;
++      int err;
++
++      low = mask;
++      hi = mask >> 32;
++      XSTATE_XSAVE(addr, low, hi, err);
++      WARN_ON_ONCE(err);
++}
++
++static inline void
++kfpu_save_fxsr(struct fxregs_state *addr)
++{
++      if (IS_ENABLED(CONFIG_X86_32))
++              kfpu_fxsave(addr);
++      else
++              kfpu_fxsaveq(addr);
++}
++
++static inline void
++kfpu_save_fsave(struct fregs_state *addr)
++{
++      kfpu_fnsave(addr);
+ }
+ static inline void
+@@ -172,46 +202,86 @@ kfpu_begin(void)
+       preempt_disable();
+       local_irq_disable();
+-#if defined(HAVE_KERNEL_TIF_NEED_FPU_LOAD)
+       /*
+        * The current FPU registers need to be preserved by kfpu_begin()
+-       * and restored by kfpu_end().  This is required because we can
+-       * not call __cpu_invalidate_fpregs_state() to invalidate the
+-       * per-cpu FPU state and force them to be restored during a
+-       * context switch.
++       * and restored by kfpu_end().  This is always required because we
++       * can not call __cpu_invalidate_fpregs_state() to invalidate the
++       * per-cpu FPU state and force them to be restored.  Furthermore,
++       * this implementation relies on the space provided in the task
++       * structure to store the user FPU state.  As such, it can only
++       * be used with dedicated kernels which by definition will never
++       * store user FPU state.
+        */
+-      copy_fpregs_to_fpstate(&current->thread.fpu);
+-#elif defined(HAVE_KERNEL_FPU_INITIALIZED)
++      if (static_cpu_has(X86_FEATURE_XSAVE)) {
++              kfpu_save_xsave(&current->thread.fpu.state.xsave, ~0);
++      } else if (static_cpu_has(X86_FEATURE_FXSR)) {
++              kfpu_save_fxsr(&current->thread.fpu.state.fxsave);
++      } else {
++              kfpu_save_fsave(&current->thread.fpu.state.fsave);
++      }
++}
++
++static inline void
++kfpu_restore_xsave(struct xregs_state *addr, uint64_t mask)
++{
++      uint32_t low, hi;
++
++      low = mask;
++      hi = mask >> 32;
++      XSTATE_XRESTORE(addr, low, hi);
++}
++
++static inline void
++kfpu_restore_fxsr(struct fxregs_state *addr)
++{
+       /*
+-       * There is no need to preserve and restore the FPU registers.
+-       * They will always be restored from the task's stored FPU state
+-       * when switching contexts.
++       * On AuthenticAMD K7 and K8 processors the fxrstor instruction only
++       * restores the _x87 FOP, FIP, and FDP registers when an exception
++       * is pending.  Clean the _x87 state to force the restore.
+        */
+-      WARN_ON_ONCE(current->thread.fpu.initialized == 0);
+-#endif
++      if (unlikely(static_cpu_has_bug(X86_BUG_FXSAVE_LEAK)))
++              kfpu_fxsr_clean(addr);
++
++      if (IS_ENABLED(CONFIG_X86_32)) {
++              kfpu_fxrstor(addr);
++      } else {
++              kfpu_fxrstorq(addr);
++      }
+ }
+ static inline void
+-kfpu_end(void)
++kfpu_restore_fsave(struct fregs_state *addr)
+ {
+-#if defined(HAVE_KERNEL_TIF_NEED_FPU_LOAD)
+-      union fpregs_state *state = &current->thread.fpu.state;
+-      int error;
++      kfpu_frstor(addr);
++}
+-      if (use_xsave()) {
+-              error = copy_kernel_to_xregs_err(&state->xsave, -1);
+-      } else if (use_fxsr()) {
+-              error = copy_kernel_to_fxregs_err(&state->fxsave);
++static inline void
++kfpu_end(void)
++{
++      if (static_cpu_has(X86_FEATURE_XSAVE)) {
++              kfpu_restore_xsave(&current->thread.fpu.state.xsave, ~0);
++      } else if (static_cpu_has(X86_FEATURE_FXSR)) {
++              kfpu_restore_fxsr(&current->thread.fpu.state.fxsave);
+       } else {
+-              error = copy_kernel_to_fregs_err(&state->fsave);
++              kfpu_restore_fsave(&current->thread.fpu.state.fsave);
+       }
+-      WARN_ON_ONCE(error);
+-#endif
+       local_irq_enable();
+       preempt_enable();
+ }
+-#endif /* defined(HAVE_KERNEL_FPU) */
++
++#else
++
++/*
++ * FPU support is unavailable.
++ */
++#define       kfpu_allowed()          0
++#define       kfpu_initialize(tsk)    do {} while (0)
++#define       kfpu_begin()            do {} while (0)
++#define       kfpu_end()              do {} while (0)
++
++#endif /* defined(HAVE_KERNEL_FPU_INTERNAL) */
++#endif /* defined(KERNEL_EXPORTS_X86_FPU) */
+ #else /* defined(_KERNEL) */
+ /*
diff --git a/debian/patches/0008-SIMD-FPU-register-save-restore-is-also-required-on-5.patch b/debian/patches/0008-SIMD-FPU-register-save-restore-is-also-required-on-5.patch
deleted file mode 100644 (file)
index bd60e80..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Thomas Lamprecht <t.lamprecht@proxmox.com>
-Date: Wed, 25 Sep 2019 10:48:48 +0200
-Subject: [PATCH] [SIMD]: FPU register save/restore is also required on 5.0
- kernels
-
-NOTE: the kernel needs to have the copy_kernel_to_xregs_err,
-copy_kernel_to_fxregs_err and copy_kernel_to_fregs_err functions
-backported for this to work.
-
-Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
----
- include/linux/simd_x86.h | 11 ++++-------
- 1 file changed, 4 insertions(+), 7 deletions(-)
-
-diff --git a/include/linux/simd_x86.h b/include/linux/simd_x86.h
-index edd456098..98503a29e 100644
---- a/include/linux/simd_x86.h
-+++ b/include/linux/simd_x86.h
-@@ -181,7 +181,6 @@ kfpu_begin(void)
-       preempt_disable();
-       local_irq_disable();
--#if defined(HAVE_KERNEL_TIF_NEED_FPU_LOAD)
-       /*
-        * The current FPU registers need to be preserved by kfpu_begin()
-        * and restored by kfpu_end().  This is required because we can
-@@ -190,11 +189,11 @@ kfpu_begin(void)
-        * context switch.
-        */
-       copy_fpregs_to_fpstate(&current->thread.fpu);
--#elif defined(HAVE_KERNEL_FPU_INITIALIZED)
-+
-+
-+#if defined(HAVE_KERNEL_FPU_INITIALIZED)
-       /*
--       * There is no need to preserve and restore the FPU registers.
--       * They will always be restored from the task's stored FPU state
--       * when switching contexts.
-+       * Was removed with 5.2 as it was always set to 1 there
-        */
-       WARN_ON_ONCE(current->thread.fpu.initialized == 0);
- #endif
-@@ -203,7 +202,6 @@ kfpu_begin(void)
- static inline void
- kfpu_end(void)
- {
--#if defined(HAVE_KERNEL_TIF_NEED_FPU_LOAD)
-       union fpregs_state *state = &current->thread.fpu.state;
-       int error;
-@@ -215,7 +213,6 @@ kfpu_end(void)
-               error = copy_kernel_to_fregs_err(&state->fsave);
-       }
-       WARN_ON_ONCE(error);
--#endif
-       local_irq_enable();
-       preempt_enable();
diff --git a/debian/patches/0009-Fix-CONFIG_X86_DEBUG_FPU-build-failure.patch b/debian/patches/0009-Fix-CONFIG_X86_DEBUG_FPU-build-failure.patch
new file mode 100644 (file)
index 0000000..115ac4a
--- /dev/null
@@ -0,0 +1,40 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Brian Behlendorf <behlendorf1@llnl.gov>
+Date: Wed, 17 Jul 2019 09:14:36 -0700
+Subject: [PATCH] Fix CONFIG_X86_DEBUG_FPU build failure
+
+When CONFIG_X86_DEBUG_FPU is defined the alternatives_patched symbol
+is pulled in as a dependency which results in a build failure.  To
+prevent this undefine CONFIG_X86_DEBUG_FPU to disable the WARN_ON_FPU()
+macro and rely on WARN_ON_ONCE debugging checks which were previously
+added.
+
+Reviewed-by: Tony Hutter <hutter2@llnl.gov>
+Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
+Closes #9041
+Closes #9049
+Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
+---
+ include/linux/simd_x86.h | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/include/linux/simd_x86.h b/include/linux/simd_x86.h
+index d1ded3af2..b32bccc41 100644
+--- a/include/linux/simd_x86.h
++++ b/include/linux/simd_x86.h
+@@ -84,6 +84,15 @@
+ #if defined(_KERNEL)
++/*
++ * Disable the WARN_ON_FPU() macro to prevent additional dependencies
++ * when providing the kfpu_* functions.  Relevant warnings are included
++ * as appropriate and are unconditionally enabled.
++ */
++#if defined(CONFIG_X86_DEBUG_FPU) && !defined(KERNEL_EXPORTS_X86_FPU)
++#undef CONFIG_X86_DEBUG_FPU
++#endif
++
+ #if defined(HAVE_KERNEL_FPU_API_HEADER)
+ #include <asm/fpu/api.h>
+ #include <asm/fpu/internal.h>
diff --git a/debian/patches/0009-Perform-KABI-checks-in-parallel.patch b/debian/patches/0009-Perform-KABI-checks-in-parallel.patch
deleted file mode 100644 (file)
index 74025a7..0000000
+++ /dev/null
@@ -1,8805 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Brian Behlendorf <behlendorf1@llnl.gov>
-Date: Tue, 1 Oct 2019 12:50:34 -0700
-Subject: [PATCH] Perform KABI checks in parallel
-
-Reduce the time required for ./configure to perform the needed
-KABI checks by allowing kbuild to compile multiple test cases in
-parallel.  This was accomplished by splitting each test's source
-code from the logic handling whether that code could be compiled
-or not.
-
-By introducing this split it's possible to minimize the number of
-times kbuild needs to be invoked.  As importantly, it means all of
-the tests can be built in parallel.  This does require a little extra
-care since we expect some tests to fail, so the --keep-going (-k)
-option must be provided otherwise some tests may not get compiled.
-Furthermore, since a failure during the kbuild modpost phase will
-result in an early exit; the final linking phase is limited to tests
-which passed the initial compilation and produced an object file.
-
-Once everything has been built the configure script proceeds as
-previously.  The only significant difference is that it now merely
-needs to test for the existence of a .ko file to determine the
-result of a given test.  This vastly speeds up the entire process.
-
-New test cases should use ZFS_LINUX_TEST_SRC to declare their test
-source code and ZFS_LINUX_TEST_RESULT to check the result.  All of
-the existing kernel-*.m4 files have been updated accordingly, see
-config/kernel-current-time.m4 for a basic example.  The legacy
-ZFS_LINUX_TRY_COMPILE macro has been kept to handle special cases
-but it's use is not encouraged.
-
-                  master (secs)   patched (secs)
-                  -------------   ----------------
-autogen.sh        61              68
-configure         137             24  (~17% of current run time)
-make -j $(nproc)  44              44
-make rpms         287             150
-
-Reviewed-by: Tony Hutter <hutter2@llnl.gov>
-Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
-Closes #8547
-Closes #9132
-Closes #9341
-(cherry picked from commit 608f8749a1055e6769899788e11bd51fd396f9e5)
-Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
----
- .gitignore                                    |   1 +
- Makefile.am                                   |   6 +-
- config/iconv.m4                               |   3 +-
- config/kernel-access-ok-type.m4               |  18 +-
- config/kernel-acl.m4                          | 253 ++++--
- config/kernel-aio-fsync.m4                    |  14 +-
- config/kernel-automount.m4                    |  13 +-
- config/kernel-bdev-logical-size.m4            |  17 +-
- config/kernel-bdev-physical-size.m4           |  17 +-
- config/kernel-bdi.m4                          |  78 +-
- config/kernel-bio-bvec-iter.m4                |  13 +-
- config/kernel-bio-end-io-t-args.m4            |  34 +-
- config/kernel-bio-failfast.m4                 |  39 +-
- config/kernel-bio-op.m4                       |  74 +-
- config/kernel-bio-rw-barrier.m4               |  15 +-
- config/kernel-bio-rw-discard.m4               |  15 +-
- config/kernel-bio_set_dev.m4                  |  51 +-
- config/kernel-blk-queue-bdi.m4                |  12 +-
- config/kernel-blk-queue-discard.m4            |  41 +-
- config/kernel-blk-queue-flags.m4              |  40 +-
- config/kernel-blk-queue-flush.m4              |  64 +-
- config/kernel-blk-queue-max-hw-sectors.m4     |  19 +-
- config/kernel-blk-queue-max-segments.m4       |  21 +-
- config/kernel-blk-queue-unplug.m4             |  48 +-
- config/kernel-blkdev-get-by-path.m4           |  15 +-
- config/kernel-blkdev-reread-part.m4           |  12 +-
- config/kernel-block-device-operations.m4      |  46 +-
- config/kernel-clear-inode.m4                  |  13 +-
- config/kernel-commit-metadata.m4              |  15 +-
- config/kernel-config-defined.m4               | 183 ++++
- config/kernel-create-nameidata.m4             |  15 +-
- config/kernel-ctl-table-name.m4               |  12 +-
- config/kernel-current-time.m4                 |  13 +-
- config/kernel-current_bio_tail.m4             |  30 +-
- config/kernel-d-make-root.m4                  |  17 -
- config/kernel-d-obtain-alias.m4               |  18 -
- config/kernel-d-prune-aliases.m4              |  19 -
- config/kernel-declare-event-class.m4          |   8 +-
- config/kernel-dentry-operations.m4            | 174 +++-
- config/kernel-dirty-inode.m4                  |  15 +-
- config/kernel-discard-granularity.m4          |  15 +-
- config/kernel-elevator-change.m4              |  21 +-
- config/kernel-encode-fh-inode.m4              |  15 +-
- config/kernel-evict-inode.m4                  |  13 +-
- config/kernel-fallocate-pax.m4                |  19 -
- config/kernel-fallocate.m4                    |  50 +-
- config/kernel-file-dentry.m4                  |  12 +-
- config/kernel-file-inode.m4                   |  12 +-
- config/kernel-fmode-t.m4                      |  15 +-
- config/kernel-follow-down-one.m4              |  12 +-
- config/kernel-fpu.m4                          |  99 ++-
- config/kernel-fst-mount.m4                    |  13 +-
- config/kernel-fsync.m4                        |  83 +-
- config/kernel-generic_io_acct.m4              |  63 +-
- config/kernel-generic_readlink.m4             |  15 +-
- config/kernel-get-disk-and-module.m4          |  13 +-
- config/kernel-get-disk-ro.m4                  |  18 +-
- config/kernel-get-link.m4                     | 126 +--
- config/kernel-global_page_state.m4            |  72 +-
- config/kernel-group-info.m4                   |  15 +-
- config/kernel-in-compat-syscall.m4            |  12 +-
- config/kernel-inode-getattr.m4                |  56 +-
- config/kernel-inode-lock.m4                   |  15 +-
- config/kernel-inode-set-flags.m4              |  12 +-
- config/kernel-inode-set-iversion.m4           |  12 +-
- config/kernel-inode-times.m4                  |  15 +-
- config/kernel-insert-inode-locked.m4          |  15 +-
- config/kernel-invalidate-bdev-args.m4         |  14 +-
- config/kernel-is_owner_or_cap.m4              |  31 +-
- config/kernel-kmap-atomic-args.m4             |  14 +-
- config/kernel-kmem-cache.m4                   |  62 +-
- config/kernel-kstrtoul.m4                     |  14 +-
- config/kernel-ktime_get_coarse_real_ts64.m4   |  15 +-
- config/kernel-kuid-helpers.m4                 |  12 +-
- config/kernel-kuidgid.m4                      |  26 +-
- config/kernel-lookup-bdev.m4                  |  32 +-
- config/kernel-lookup-nameidata.m4             |  15 +-
- config/kernel-lseek-execute.m4                |  16 +-
- config/kernel-make-request-fn.m4              |  77 ++
- config/kernel-misc-minor.m4                   |   2 +-
- config/kernel-mk-request-fn.m4                |  65 --
- config/kernel-mkdir-umode-t.m4                |  13 +-
- config/kernel-mod-param.m4                    |  13 +-
- config/kernel-objtool.m4                      |  47 +-
- config/kernel-open-bdev-exclusive.m4          |  15 +-
- config/kernel-pde-data.m4                     |  14 +-
- config/kernel-put-link.m4                     |  57 +-
- config/kernel-rename.m4                       |  16 +-
- config/kernel-rw.m4                           |  40 +-
- config/kernel-rwsem.m4                        |  65 +-
- config/kernel-sched.m4                        |  53 +-
- config/kernel-security-inode-init.m4          |  38 +-
- config/kernel-set-nlink.m4                    |  15 +-
- config/kernel-setattr-prepare.m4              |  16 +-
- config/kernel-sget-args.m4                    |  13 +-
- config/kernel-show-options.m4                 |  21 +-
- config/kernel-shrink.m4                       | 219 +++--
- config/kernel-submit_bio.m4                   |  12 +-
- config/kernel-super-userns.m4                 |  14 +-
- config/kernel-timer.m4                        |  52 +-
- config/kernel-tmpfile.m4                      |  16 +-
- config/kernel-totalhigh_pages.m4              |  14 +-
- config/kernel-totalram-pages-func.m4          |  15 +-
- config/kernel-truncate-range.m4               |  13 +-
- config/kernel-truncate-setsize.m4             |  15 +-
- config/kernel-userns-capabilities.m4          |  48 +-
- ...urange-sleep.m4 => kernel-usleep_range.m4} |  19 +-
- config/kernel-vfs-direct_IO.m4                | 145 ++--
- config/kernel-vfs-fsync.m4                    |  12 +-
- config/kernel-vfs-getattr.m4                  |  54 +-
- config/kernel-vfs-iterate.m4                  |  84 +-
- config/kernel-vfs-rw-iterate.m4               |  76 +-
- config/kernel-wait.m4                         |  73 +-
- config/kernel-xattr-handler.m4                | 442 +++++-----
- config/kernel-zlib.m4                         |  57 +-
- config/kernel.m4                              | 783 +++++++++++-------
- config/zfs-build.m4                           |  11 +
- config/zfs-meta.m4                            |  18 +
- 118 files changed, 3245 insertions(+), 2127 deletions(-)
- create mode 100644 config/kernel-config-defined.m4
- delete mode 100644 config/kernel-d-make-root.m4
- delete mode 100644 config/kernel-d-obtain-alias.m4
- delete mode 100644 config/kernel-d-prune-aliases.m4
- delete mode 100644 config/kernel-fallocate-pax.m4
- create mode 100644 config/kernel-make-request-fn.m4
- delete mode 100644 config/kernel-mk-request-fn.m4
- rename config/{kernel-urange-sleep.m4 => kernel-usleep_range.m4} (60%)
-
-diff --git a/.gitignore b/.gitignore
-index ae9e22dfa..19377a7b1 100644
---- a/.gitignore
-+++ b/.gitignore
-@@ -36,6 +36,7 @@ Makefile.in
- # Top level generated files specific to this top level dir
- #
- /bin
-+/build
- /configure
- /config.log
- /config.status
-diff --git a/Makefile.am b/Makefile.am
-index 9afe22954..5ee7c20be 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -40,7 +40,7 @@ gitrev:
- BUILT_SOURCES = gitrev
- distclean-local::
--      -$(RM) -R autom4te*.cache
-+      -$(RM) -R autom4te*.cache build
-       -find . \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS \
-               -o -name .pc -o -name .hg -o -name .git \) -prune -o \
-               \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
-@@ -87,8 +87,8 @@ commitcheck:
-       fi
- cstyle:
--      @find ${top_srcdir} -name '*.[hc]' ! -name 'zfs_config.*' \
--              ! -name '*.mod.c' -type f \
-+      @find ${top_srcdir} -name build -prune -o -name '*.[hc]' \
-+              ! -name 'zfs_config.*' ! -name '*.mod.c' -type f \
-               -exec ${top_srcdir}/scripts/cstyle.pl -cpP {} \+
- shellcheck:
-diff --git a/config/iconv.m4 b/config/iconv.m4
-index a285e9daa..fc915fde6 100644
---- a/config/iconv.m4
-+++ b/config/iconv.m4
-@@ -269,8 +269,7 @@ size_t iconv();
-         [am_cv_proto_iconv_arg1="const"])
-       am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
-     am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
--    AC_MSG_RESULT([
--         $am_cv_proto_iconv])
-+    AC_MSG_RESULT([$am_cv_proto_iconv])
-   else
-     dnl When compiling GNU libiconv on a system that does not have iconv yet,
-     dnl pick the POSIX compliant declaration without 'const'.
-diff --git a/config/kernel-access-ok-type.m4 b/config/kernel-access-ok-type.m4
-index 3b2878a55..dc9433458 100644
---- a/config/kernel-access-ok-type.m4
-+++ b/config/kernel-access-ok-type.m4
-@@ -4,17 +4,23 @@ dnl #
- dnl # - access_ok(type, addr, size)
- dnl # + access_ok(addr, size)
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_ACCESS_OK_TYPE], [
--      AC_MSG_CHECKING([whether access_ok() has 'type' parameter])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_ACCESS_OK_TYPE], [
-+      ZFS_LINUX_TEST_SRC([access_ok_type], [
-               #include <linux/uaccess.h>
-       ],[
--              const void __user __attribute__((unused)) *addr = (void *) 0xdeadbeef;
-+              const void __user __attribute__((unused)) *addr =
-+                  (void *) 0xdeadbeef;
-               unsigned long __attribute__((unused)) size = 1;
-               int error __attribute__((unused)) = access_ok(0, addr, size);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_ACCESS_OK_TYPE], [
-+      AC_MSG_CHECKING([whether access_ok() has 'type' parameter])
-+      ZFS_LINUX_TEST_RESULT([access_ok_type], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_ACCESS_OK_TYPE, 1, [kernel has access_ok with 'type' parameter])
-+              AC_DEFINE(HAVE_ACCESS_OK_TYPE, 1,
-+                  [kernel has access_ok with 'type' parameter])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-acl.m4 b/config/kernel-acl.m4
-index 02cc020e5..68a72872d 100644
---- a/config/kernel-acl.m4
-+++ b/config/kernel-acl.m4
-@@ -3,32 +3,26 @@ dnl # Check if posix_acl_release can be used from a ZFS_META_LICENSED
- dnl # module.  The is_owner_or_cap macro was replaced by
- dnl # inode_owner_or_capable
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_RELEASE], [
--      AC_MSG_CHECKING([whether posix_acl_release() is available])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_POSIX_ACL_RELEASE], [
-+      ZFS_LINUX_TEST_SRC([posix_acl_release], [
-               #include <linux/cred.h>
-               #include <linux/fs.h>
-               #include <linux/posix_acl.h>
--      ],[
--              struct posix_acl* tmp = posix_acl_alloc(1, 0);
-+      ], [
-+              struct posix_acl *tmp = posix_acl_alloc(1, 0);
-               posix_acl_release(tmp);
--      ],[
-+      ], [], [$ZFS_META_LICENSE])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_RELEASE], [
-+      AC_MSG_CHECKING([whether posix_acl_release() is available])
-+      ZFS_LINUX_TEST_RESULT([posix_acl_release], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_POSIX_ACL_RELEASE, 1,
-                   [posix_acl_release() is available])
-               AC_MSG_CHECKING([whether posix_acl_release() is GPL-only])
--              ZFS_LINUX_TRY_COMPILE([
--                      #include <linux/module.h>
--                      #include <linux/cred.h>
--                      #include <linux/fs.h>
--                      #include <linux/posix_acl.h>
--
--                      MODULE_LICENSE("$ZFS_META_LICENSE");
--              ],[
--                      struct posix_acl* tmp = posix_acl_alloc(1, 0);
--                      posix_acl_release(tmp);
--              ],[
-+              ZFS_LINUX_TEST_RESULT([posix_acl_release_license], [
-                       AC_MSG_RESULT(no)
-               ],[
-                       AC_MSG_RESULT(yes)
-@@ -46,24 +40,25 @@ dnl # set_cached_acl() and forget_cached_acl() changed from inline to
- dnl # EXPORT_SYMBOL. In the former case, they may not be usable because of
- dnl # posix_acl_release. In the latter case, we can always use them.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_SET_CACHED_ACL_USABLE], [
--      AC_MSG_CHECKING([whether set_cached_acl() is usable])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/module.h>
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SET_CACHED_ACL_USABLE], [
-+      ZFS_LINUX_TEST_SRC([set_cached_acl], [
-               #include <linux/cred.h>
-               #include <linux/fs.h>
-               #include <linux/posix_acl.h>
--
--              MODULE_LICENSE("$ZFS_META_LICENSE");
--      ],[
-+      ], [
-               struct inode *ip = NULL;
-               struct posix_acl *acl = posix_acl_alloc(1, 0);
-               set_cached_acl(ip, ACL_TYPE_ACCESS, acl);
-               forget_cached_acl(ip, ACL_TYPE_ACCESS);
--      ],[
-+      ], [], [$ZFS_META_LICENSE])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SET_CACHED_ACL_USABLE], [
-+      AC_MSG_CHECKING([whether set_cached_acl() is usable])
-+      ZFS_LINUX_TEST_RESULT([set_cached_acl_license], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_SET_CACHED_ACL_USABLE, 1,
--                  [posix_acl_release() is usable])
-+                  [set_cached_acl() is usable])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-@@ -77,14 +72,25 @@ dnl #
- dnl # 3.14 API change,
- dnl # posix_acl_chmod() is changed to __posix_acl_chmod()
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_CHMOD], [
--      AC_MSG_CHECKING([whether posix_acl_chmod exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_POSIX_ACL_CHMOD], [
-+      ZFS_LINUX_TEST_SRC([posix_acl_chmod], [
-               #include <linux/fs.h>
-               #include <linux/posix_acl.h>
-       ],[
-               posix_acl_chmod(NULL, 0, 0)
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([__posix_acl_chmod], [
-+              #include <linux/fs.h>
-+              #include <linux/posix_acl.h>
-       ],[
-+              __posix_acl_chmod(NULL, 0, 0)
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_CHMOD], [
-+      AC_MSG_CHECKING([whether posix_acl_chmod exists])
-+      ZFS_LINUX_TEST_RESULT([posix_acl_chmod], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_POSIX_ACL_CHMOD, 1, [posix_acl_chmod() exists])
-       ],[
-@@ -92,14 +98,10 @@ AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_CHMOD], [
-       ])
-       AC_MSG_CHECKING([whether __posix_acl_chmod exists])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/fs.h>
--              #include <linux/posix_acl.h>
--      ],[
--              __posix_acl_chmod(NULL, 0, 0)
--      ],[
-+      ZFS_LINUX_TEST_RESULT([__posix_acl_chmod], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE___POSIX_ACL_CHMOD, 1, [__posix_acl_chmod() exists])
-+              AC_DEFINE(HAVE___POSIX_ACL_CHMOD, 1,
-+                  [__posix_acl_chmod() exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-@@ -109,18 +111,22 @@ dnl #
- dnl # 3.1 API change,
- dnl # posix_acl_equiv_mode now wants an umode_t* instead of a mode_t*
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T], [
--      AC_MSG_CHECKING([whether posix_acl_equiv_mode() wants umode_t])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T], [
-+      ZFS_LINUX_TEST_SRC([posix_acl_equiv_mode], [
-               #include <linux/fs.h>
-               #include <linux/posix_acl.h>
-       ],[
-               umode_t tmp;
-               posix_acl_equiv_mode(NULL,&tmp);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T], [
-+      AC_MSG_CHECKING([whether posix_acl_equiv_mode() wants umode_t])
-+      ZFS_LINUX_TEST_RESULT([posix_acl_equiv_mode], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_POSIX_ACL_EQUIV_MODE_UMODE_T, 1,
--                  [ posix_acl_equiv_mode wants umode_t*])
-+                  [posix_acl_equiv_mode wants umode_t*])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-@@ -130,9 +136,8 @@ dnl #
- dnl # 4.8 API change,
- dnl # The function posix_acl_valid now must be passed a namespace.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_VALID_WITH_NS], [
--      AC_MSG_CHECKING([whether posix_acl_valid() wants user namespace])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_POSIX_ACL_VALID_WITH_NS], [
-+      ZFS_LINUX_TEST_SRC([posix_acl_valid_with_ns], [
-               #include <linux/fs.h>
-               #include <linux/posix_acl.h>
-       ],[
-@@ -141,7 +146,12 @@ AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_VALID_WITH_NS], [
-               int error;
-               error = posix_acl_valid(user_ns, acl);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_VALID_WITH_NS], [
-+      AC_MSG_CHECKING([whether posix_acl_valid() wants user namespace])
-+      ZFS_LINUX_TEST_RESULT([posix_acl_valid_with_ns], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_POSIX_ACL_VALID_WITH_NS, 1,
-                   [posix_acl_valid() wants user namespace])
-@@ -155,9 +165,8 @@ dnl # 2.6.27 API change,
- dnl # Check if inode_operations contains the function permission
- dnl # and expects the nameidata structure to have been removed.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION], [
--      AC_MSG_CHECKING([whether iops->permission() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_PERMISSION], [
-+      ZFS_LINUX_TEST_SRC([inode_operations_permission], [
-               #include <linux/fs.h>
-               int permission_fn(struct inode *inode, int mask) { return 0; }
-@@ -166,8 +175,12 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION], [
-                   iops __attribute__ ((unused)) = {
-                       .permission = permission_fn,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION], [
-+      AC_MSG_CHECKING([whether iops->permission() exists])
-+      ZFS_LINUX_TEST_RESULT([inode_operations_permission], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_PERMISSION, 1, [iops->permission() exists])
-       ],[
-@@ -180,9 +193,8 @@ dnl # 2.6.26 API change,
- dnl # Check if inode_operations contains the function permission
- dnl # and expects the nameidata structure to be passed.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA], [
--      AC_MSG_CHECKING([whether iops->permission() wants nameidata])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA], [
-+      ZFS_LINUX_TEST_SRC([inode_operations_permission_with_nameidata], [
-               #include <linux/fs.h>
-               #include <linux/sched.h>
-@@ -193,8 +205,12 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA], [
-                   iops __attribute__ ((unused)) = {
-                       .permission = permission_fn,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA], [
-+      AC_MSG_CHECKING([whether iops->permission() wants nameidata])
-+      ZFS_LINUX_TEST_RESULT([inode_operations_permission_with_nameidata], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_PERMISSION, 1, [iops->permission() exists])
-               AC_DEFINE(HAVE_PERMISSION_WITH_NAMEIDATA, 1,
-@@ -208,9 +224,8 @@ dnl #
- dnl # 2.6.32 API change,
- dnl # Check if inode_operations contains the function check_acl
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL], [
--      AC_MSG_CHECKING([whether iops->check_acl() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_CHECK_ACL], [
-+      ZFS_LINUX_TEST_SRC([inode_operations_check_acl], [
-               #include <linux/fs.h>
-               int check_acl_fn(struct inode *inode, int mask) { return 0; }
-@@ -219,8 +234,12 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL], [
-                   iops __attribute__ ((unused)) = {
-                       .check_acl = check_acl_fn,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL], [
-+      AC_MSG_CHECKING([whether iops->check_acl() exists])
-+      ZFS_LINUX_TEST_RESULT([inode_operations_check_acl], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_CHECK_ACL, 1, [iops->check_acl() exists])
-       ],[
-@@ -232,9 +251,8 @@ dnl #
- dnl # 2.6.38 API change,
- dnl # The function check_acl gained a new parameter: flags
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS], [
--      AC_MSG_CHECKING([whether iops->check_acl() wants flags])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS], [
-+      ZFS_LINUX_TEST_SRC([inode_operations_check_acl_with_flags], [
-               #include <linux/fs.h>
-               int check_acl_fn(struct inode *inode, int mask,
-@@ -244,8 +262,12 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS], [
-                   iops __attribute__ ((unused)) = {
-                       .check_acl = check_acl_fn,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS], [
-+      AC_MSG_CHECKING([whether iops->check_acl() wants flags])
-+      ZFS_LINUX_TEST_RESULT([inode_operations_check_acl_with_flags], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_CHECK_ACL, 1, [iops->check_acl() exists])
-               AC_DEFINE(HAVE_CHECK_ACL_WITH_FLAGS, 1,
-@@ -259,9 +281,8 @@ dnl #
- dnl # 3.1 API change,
- dnl # Check if inode_operations contains the function get_acl
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [
--      AC_MSG_CHECKING([whether iops->get_acl() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL], [
-+      ZFS_LINUX_TEST_SRC([inode_operations_get_acl], [
-               #include <linux/fs.h>
-               struct posix_acl *get_acl_fn(struct inode *inode, int type)
-@@ -271,8 +292,12 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [
-                   iops __attribute__ ((unused)) = {
-                       .get_acl = get_acl_fn,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [
-+      AC_MSG_CHECKING([whether iops->get_acl() exists])
-+      ZFS_LINUX_TEST_RESULT([inode_operations_get_acl], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_GET_ACL, 1, [iops->get_acl() exists])
-       ],[
-@@ -284,20 +309,23 @@ dnl #
- dnl # 3.14 API change,
- dnl # Check if inode_operations contains the function set_acl
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL], [
--      AC_MSG_CHECKING([whether iops->set_acl() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_SET_ACL], [
-+      ZFS_LINUX_TEST_SRC([inode_operations_set_acl], [
-               #include <linux/fs.h>
--              int set_acl_fn(struct inode *inode, struct posix_acl *acl, int type)
--                  { return 0; }
-+              int set_acl_fn(struct inode *inode, struct posix_acl *acl,
-+                  int type) { return 0; }
-               static const struct inode_operations
-                   iops __attribute__ ((unused)) = {
-                       .set_acl = set_acl_fn,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL], [
-+      AC_MSG_CHECKING([whether iops->set_acl() exists])
-+      ZFS_LINUX_TEST_RESULT([inode_operations_set_acl], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists])
-       ],[
-@@ -311,16 +339,79 @@ dnl # The kernel get_acl will now check cache before calling i_op->get_acl and
- dnl # do set_cached_acl after that, so i_op->get_acl don't need to do that
- dnl # anymore.
- dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_GET_ACL_HANDLE_CACHE], [
-+      ZFS_LINUX_TEST_SRC([get_acl_handle_cache], [
-+              #include <linux/fs.h>
-+      ],[
-+              void *sentinel __attribute__ ((unused)) =
-+                  uncached_acl_sentinel(NULL);
-+      ])
-+])
-+
- AC_DEFUN([ZFS_AC_KERNEL_GET_ACL_HANDLE_CACHE], [
-       AC_MSG_CHECKING([whether uncached_acl_sentinel() exists])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/fs.h>
-+      ZFS_LINUX_TEST_RESULT([get_acl_handle_cache], [
-+              AC_MSG_RESULT(yes)
-+              AC_DEFINE(HAVE_KERNEL_GET_ACL_HANDLE_CACHE, 1,
-+                  [uncached_acl_sentinel() exists])
-       ],[
--              void *sentinel __attribute__ ((unused)) = uncached_acl_sentinel(NULL);
-+              AC_MSG_RESULT(no)
-+      ])
-+])
-+
-+dnl #
-+dnl # 4.16 kernel: check if struct posix_acl acl.a_refcount is a refcount_t.
-+dnl # It's an atomic_t on older kernels.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_ACL_HAS_REFCOUNT], [
-+      ZFS_LINUX_TEST_SRC([acl_refcount], [
-+              #include <linux/backing-dev.h>
-+              #include <linux/refcount.h>
-+              #include <linux/posix_acl.h>
-       ],[
-+              struct posix_acl acl;
-+              refcount_t *r __attribute__ ((unused)) = &acl.a_refcount;
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_ACL_HAS_REFCOUNT], [
-+      AC_MSG_CHECKING([whether posix_acl has refcount_t])
-+      ZFS_LINUX_TEST_RESULT([acl_refcount], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_KERNEL_GET_ACL_HANDLE_CACHE, 1, [uncached_acl_sentinel() exists])
-+              AC_DEFINE(HAVE_ACL_REFCOUNT, 1, [posix_acl has refcount_t])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
- ])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_ACL], [
-+      ZFS_AC_KERNEL_SRC_POSIX_ACL_RELEASE
-+      ZFS_AC_KERNEL_SRC_SET_CACHED_ACL_USABLE
-+      ZFS_AC_KERNEL_SRC_POSIX_ACL_CHMOD
-+      ZFS_AC_KERNEL_SRC_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T
-+      ZFS_AC_KERNEL_SRC_POSIX_ACL_VALID_WITH_NS
-+      ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_PERMISSION
-+      ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA
-+      ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_CHECK_ACL
-+      ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS
-+      ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL
-+      ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_SET_ACL
-+      ZFS_AC_KERNEL_SRC_GET_ACL_HANDLE_CACHE
-+      ZFS_AC_KERNEL_SRC_ACL_HAS_REFCOUNT
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_ACL], [
-+      ZFS_AC_KERNEL_POSIX_ACL_RELEASE
-+      ZFS_AC_KERNEL_SET_CACHED_ACL_USABLE
-+      ZFS_AC_KERNEL_POSIX_ACL_CHMOD
-+      ZFS_AC_KERNEL_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T
-+      ZFS_AC_KERNEL_POSIX_ACL_VALID_WITH_NS
-+      ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION
-+      ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA
-+      ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL
-+      ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS
-+      ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL
-+      ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL
-+      ZFS_AC_KERNEL_GET_ACL_HANDLE_CACHE
-+      ZFS_AC_KERNEL_ACL_HAS_REFCOUNT
-+])
-diff --git a/config/kernel-aio-fsync.m4 b/config/kernel-aio-fsync.m4
-index 41b7a98a6..b4dbf29ba 100644
---- a/config/kernel-aio-fsync.m4
-+++ b/config/kernel-aio-fsync.m4
-@@ -1,21 +1,23 @@
- dnl #
- dnl # Linux 4.9-rc5+ ABI, removal of the .aio_fsync field
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_AIO_FSYNC], [
--      AC_MSG_CHECKING([whether fops->aio_fsync() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_AIO_FSYNC], [
-+      ZFS_LINUX_TEST_SRC([aio_fsync], [
-               #include <linux/fs.h>
-               static const struct file_operations
-                   fops __attribute__ ((unused)) = {
-                       .aio_fsync = NULL,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_AIO_FSYNC], [
-+      AC_MSG_CHECKING([whether fops->aio_fsync() exists])
-+      ZFS_LINUX_TEST_RESULT([aio_fsync], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_FILE_AIO_FSYNC, 1, [fops->aio_fsync() exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
- ])
--
-diff --git a/config/kernel-automount.m4 b/config/kernel-automount.m4
-index 1ee4c168d..93e14fa8d 100644
---- a/config/kernel-automount.m4
-+++ b/config/kernel-automount.m4
-@@ -5,16 +5,19 @@ dnl # solution to handling automounts.  Prior to this cifs/nfs clients
- dnl # which required automount support would abuse the follow_link()
- dnl # operation on directories for this purpose.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_AUTOMOUNT], [
--      AC_MSG_CHECKING([whether dops->d_automount() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_AUTOMOUNT], [
-+      ZFS_LINUX_TEST_SRC([dentry_operations_d_automount], [
-               #include <linux/dcache.h>
-               struct vfsmount *d_automount(struct path *p) { return NULL; }
-               struct dentry_operations dops __attribute__ ((unused)) = {
-                       .d_automount = d_automount,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_AUTOMOUNT], [
-+      AC_MSG_CHECKING([whether dops->d_automount() exists])
-+      ZFS_LINUX_TEST_RESULT([dentry_operations_d_automount], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_AUTOMOUNT, 1, [dops->automount() exists])
-       ],[
-diff --git a/config/kernel-bdev-logical-size.m4 b/config/kernel-bdev-logical-size.m4
-index a6194577a..0de9afd88 100644
---- a/config/kernel-bdev-logical-size.m4
-+++ b/config/kernel-bdev-logical-size.m4
-@@ -5,21 +5,22 @@ dnl # it has been true for a while that there was no strict 1:1 mapping
- dnl # between physical sector size and logical block size this change makes
- dnl # it explicit.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BDEV_LOGICAL_BLOCK_SIZE], [
--      AC_MSG_CHECKING([whether bdev_logical_block_size() is available])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BDEV_LOGICAL_BLOCK_SIZE], [
-+      ZFS_LINUX_TEST_SRC([bdev_logical_block_size], [
-               #include <linux/blkdev.h>
-       ],[
-               struct block_device *bdev = NULL;
-               bdev_logical_block_size(bdev);
--      ],[
-+      ], [$NO_UNUSED_BUT_SET_VARIABLE])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BDEV_LOGICAL_BLOCK_SIZE], [
-+      AC_MSG_CHECKING([whether bdev_logical_block_size() is available])
-+      ZFS_LINUX_TEST_RESULT([bdev_logical_block_size], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BDEV_LOGICAL_BLOCK_SIZE, 1,
--                        [bdev_logical_block_size() is available])
-+                  [bdev_logical_block_size() is available])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
- ])
-diff --git a/config/kernel-bdev-physical-size.m4 b/config/kernel-bdev-physical-size.m4
-index 77746ee91..94d8172d3 100644
---- a/config/kernel-bdev-physical-size.m4
-+++ b/config/kernel-bdev-physical-size.m4
-@@ -19,21 +19,22 @@ dnl #
- dnl # Unfortunately, this interface isn't entirely reliable because
- dnl # drives are sometimes known to misreport this value.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BDEV_PHYSICAL_BLOCK_SIZE], [
--      AC_MSG_CHECKING([whether bdev_physical_block_size() is available])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BDEV_PHYSICAL_BLOCK_SIZE], [
-+      ZFS_LINUX_TEST_SRC([bdev_physical_block_size], [
-               #include <linux/blkdev.h>
-       ],[
-               struct block_device *bdev = NULL;
-               bdev_physical_block_size(bdev);
--      ],[
-+      ], [$NO_UNUSED_BUT_SET_VARIABLE])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BDEV_PHYSICAL_BLOCK_SIZE], [
-+      AC_MSG_CHECKING([whether bdev_physical_block_size() is available])
-+      ZFS_LINUX_TEST_RESULT([bdev_physical_block_size], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BDEV_PHYSICAL_BLOCK_SIZE, 1,
--                        [bdev_physical_block_size() is available])
-+                  [bdev_physical_block_size() is available])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
- ])
-diff --git a/config/kernel-bdi.m4 b/config/kernel-bdi.m4
-index cb7479ee9..51516332a 100644
---- a/config/kernel-bdi.m4
-+++ b/config/kernel-bdi.m4
-@@ -1,55 +1,81 @@
- dnl #
--dnl # 2.6.32 - 2.6.33, bdi_setup_and_register() is not exported.
--dnl # 2.6.34 - 3.19, bdi_setup_and_register() takes 3 arguments.
--dnl # 4.0 - 4.11, bdi_setup_and_register() takes 2 arguments.
--dnl # 4.12 - x.y, super_setup_bdi_name() new interface.
-+dnl # Check available BDI interfaces.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BDI], [
--      AC_MSG_CHECKING([whether super_setup_bdi_name() exists])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BDI], [
-+      ZFS_LINUX_TEST_SRC([super_setup_bdi_name], [
-               #include <linux/fs.h>
-               struct super_block sb;
-       ], [
-               char *name = "bdi";
-               atomic_long_t zfs_bdi_seq;
-               int error __attribute__((unused)) =
--                  super_setup_bdi_name(&sb, "%.28s-%ld", name, atomic_long_inc_return(&zfs_bdi_seq));
--      ], [super_setup_bdi_name], [fs/super.c], [
-+                  super_setup_bdi_name(&sb, "%.28s-%ld", name,
-+                  atomic_long_inc_return(&zfs_bdi_seq));
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([bdi_setup_and_register], [
-+              #include <linux/backing-dev.h>
-+              struct backing_dev_info bdi;
-+      ], [
-+              char *name = "bdi";
-+              int error __attribute__((unused)) =
-+                  bdi_setup_and_register(&bdi, name);
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([bdi_setup_and_register_3args], [
-+              #include <linux/backing-dev.h>
-+              struct backing_dev_info bdi;
-+      ], [
-+              char *name = "bdi";
-+              unsigned int cap = BDI_CAP_MAP_COPY;
-+              int error __attribute__((unused)) =
-+                  bdi_setup_and_register(&bdi, name, cap);
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BDI], [
-+      dnl #
-+      dnl # 4.12, super_setup_bdi_name() introduced.
-+      dnl #
-+      AC_MSG_CHECKING([whether super_setup_bdi_name() exists])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([super_setup_bdi_name],
-+          [super_setup_bdi_name], [fs/super.c], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_SUPER_SETUP_BDI_NAME, 1,
-                     [super_setup_bdi_name() exits])
-       ], [
-               AC_MSG_RESULT(no)
-+
-+              dnl #
-+              dnl # 4.0 - 4.11, bdi_setup_and_register() takes 2 arguments.
-+              dnl #
-               AC_MSG_CHECKING(
-                   [whether bdi_setup_and_register() wants 2 args])
--              ZFS_LINUX_TRY_COMPILE_SYMBOL([
--                      #include <linux/backing-dev.h>
--                      struct backing_dev_info bdi;
--              ], [
--                      char *name = "bdi";
--                      int error __attribute__((unused)) =
--                          bdi_setup_and_register(&bdi, name);
--              ], [bdi_setup_and_register], [mm/backing-dev.c], [
-+              ZFS_LINUX_TEST_RESULT_SYMBOL([bdi_setup_and_register],
-+                  [bdi_setup_and_register], [mm/backing-dev.c], [
-                       AC_MSG_RESULT(yes)
-                       AC_DEFINE(HAVE_2ARGS_BDI_SETUP_AND_REGISTER, 1,
-                           [bdi_setup_and_register() wants 2 args])
-               ], [
-                       AC_MSG_RESULT(no)
-+
-+                      dnl #
-+                      dnl # 2.6.34 - 3.19, bdi_setup_and_register()
-+                      dnl # takes 3 arguments.
-+                      dnl #
-                       AC_MSG_CHECKING(
-                           [whether bdi_setup_and_register() wants 3 args])
--                      ZFS_LINUX_TRY_COMPILE_SYMBOL([
--                              #include <linux/backing-dev.h>
--                              struct backing_dev_info bdi;
--                      ], [
--                              char *name = "bdi";
--                              unsigned int cap = BDI_CAP_MAP_COPY;
--                              int error __attribute__((unused)) =
--                                  bdi_setup_and_register(&bdi, name, cap);
--                      ], [bdi_setup_and_register], [mm/backing-dev.c], [
-+                      ZFS_LINUX_TEST_RESULT_SYMBOL(
-+                          [bdi_setup_and_register_3args],
-+                          [bdi_setup_and_register], [mm/backing-dev.c], [
-                               AC_MSG_RESULT(yes)
-                               AC_DEFINE(HAVE_3ARGS_BDI_SETUP_AND_REGISTER, 1,
-                                   [bdi_setup_and_register() wants 3 args])
-                       ], [
-+                              dnl #
-+                              dnl # 2.6.32 - 2.6.33, bdi_setup_and_register()
-+                              dnl # is not exported.
-+                              dnl #
-                               AC_MSG_RESULT(no)
-                       ])
-               ])
-diff --git a/config/kernel-bio-bvec-iter.m4 b/config/kernel-bio-bvec-iter.m4
-index 64c989386..f9a99cee6 100644
---- a/config/kernel-bio-bvec-iter.m4
-+++ b/config/kernel-bio-bvec-iter.m4
-@@ -3,18 +3,21 @@ dnl # 3.14 API change,
- dnl # Immutable biovecs. A number of fields of struct bio are moved to
- dnl # struct bvec_iter.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BIO_BVEC_ITER], [
--      AC_MSG_CHECKING([whether bio has bi_iter])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_BVEC_ITER], [
-+      ZFS_LINUX_TEST_SRC([bio_bvec_iter], [
-               #include <linux/bio.h>
-       ],[
-               struct bio bio;
-               bio.bi_iter.bi_sector = 0;
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BIO_BVEC_ITER], [
-+      AC_MSG_CHECKING([whether bio has bi_iter])
-+      ZFS_LINUX_TEST_RESULT([bio_bvec_iter], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BIO_BVEC_ITER, 1, [bio has bi_iter])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
- ])
--
-diff --git a/config/kernel-bio-end-io-t-args.m4 b/config/kernel-bio-end-io-t-args.m4
-index 3c420cc0c..80a1fbeda 100644
---- a/config/kernel-bio-end-io-t-args.m4
-+++ b/config/kernel-bio-end-io-t-args.m4
-@@ -5,20 +5,21 @@ dnl # bio->bi_error. This also replaces bio->bi_flags value BIO_UPTODATE.
- dnl # Introduced by torvalds/linux@4246a0b63bd8f56a1469b12eafeb875b1041a451
- dnl # ("block: add a bi_error field to struct bio").
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BIO_END_IO_T_ARGS], [
--      AC_MSG_CHECKING([whether bio_end_io_t wants 1 arg])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_END_IO_T_ARGS], [
-+      ZFS_LINUX_TEST_SRC([bio_end_io_t_args], [
-               #include <linux/bio.h>
--
-               void wanted_end_io(struct bio *bio) { return; }
--
-               bio_end_io_t *end_io __attribute__ ((unused)) = wanted_end_io;
--      ],[
--      ],[
-+      ], [])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BIO_END_IO_T_ARGS], [
-+      AC_MSG_CHECKING([whether bio_end_io_t wants 1 arg])
-+      ZFS_LINUX_TEST_RESULT([bio_end_io_t_args], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_1ARG_BIO_END_IO_T, 1,
--                        [bio_end_io_t wants 1 arg])
--      ],[
-+                  [bio_end_io_t wants 1 arg])
-+      ], [
-               AC_MSG_RESULT(no)
-       ])
- ])
-@@ -28,16 +29,19 @@ dnl # 4.13 API change
- dnl # The bio->bi_error field was replaced with bio->bi_status which is an
- dnl # enum which describes all possible error types.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BIO_BI_STATUS], [
--      AC_MSG_CHECKING([whether bio->bi_status exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_BI_STATUS], [
-+      ZFS_LINUX_TEST_SRC([bio_bi_status], [
-               #include <linux/bio.h>
--      ],[
-+      ], [
-               struct bio bio __attribute__ ((unused));
-               blk_status_t status __attribute__ ((unused)) = BLK_STS_OK;
--
-               bio.bi_status = status;
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BIO_BI_STATUS], [
-+      AC_MSG_CHECKING([whether bio->bi_status exists])
-+      ZFS_LINUX_TEST_RESULT([bio_bi_status], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BIO_BI_STATUS, 1, [bio->bi_status exists])
-       ],[
-diff --git a/config/kernel-bio-failfast.m4 b/config/kernel-bio-failfast.m4
-index cfbec0523..0c636f08c 100644
---- a/config/kernel-bio-failfast.m4
-+++ b/config/kernel-bio-failfast.m4
-@@ -3,37 +3,54 @@ dnl # Preferred interface for setting FAILFAST on a bio:
- dnl #   2.6.28-2.6.35: BIO_RW_FAILFAST_{DEV|TRANSPORT|DRIVER}
- dnl #       >= 2.6.36: REQ_FAILFAST_{DEV|TRANSPORT|DRIVER}
- dnl #
--
--AC_DEFUN([ZFS_AC_KERNEL_BIO_FAILFAST_DTD], [
--      AC_MSG_CHECKING([whether BIO_RW_FAILFAST_* are defined])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_FAILFAST_DTD], [
-+      ZFS_LINUX_TEST_SRC([bio_failfast_dtd], [
-               #include <linux/bio.h>
-       ],[
-               int flags __attribute__ ((unused));
-               flags = ((1 << BIO_RW_FAILFAST_DEV) |
-                        (1 << BIO_RW_FAILFAST_TRANSPORT) |
-                        (1 << BIO_RW_FAILFAST_DRIVER));
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BIO_FAILFAST_DTD], [
-+      AC_MSG_CHECKING([whether BIO_RW_FAILFAST_* are defined])
-+      ZFS_LINUX_TEST_RESULT([bio_failfast_dtd], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BIO_RW_FAILFAST_DTD, 1,
--                        [BIO_RW_FAILFAST_* are defined])
-+                  [BIO_RW_FAILFAST_* are defined])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
- ])
--AC_DEFUN([ZFS_AC_KERNEL_REQ_FAILFAST_MASK], [
--      AC_MSG_CHECKING([whether REQ_FAILFAST_MASK is defined])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_REQ_FAILFAST_MASK], [
-+      ZFS_LINUX_TEST_SRC([bio_failfast_mask], [
-               #include <linux/bio.h>
-       ],[
-               int flags __attribute__ ((unused));
-               flags = REQ_FAILFAST_MASK;
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_REQ_FAILFAST_MASK], [
-+      AC_MSG_CHECKING([whether REQ_FAILFAST_MASK is defined])
-+      ZFS_LINUX_TEST_RESULT([bio_failfast_mask], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_REQ_FAILFAST_MASK, 1,
--                        [REQ_FAILFAST_MASK is defined])
-+                  [REQ_FAILFAST_MASK is defined])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
- ])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_FAILFAST], [
-+      ZFS_AC_KERNEL_SRC_BIO_FAILFAST_DTD
-+      ZFS_AC_KERNEL_SRC_REQ_FAILFAST_MASK
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BIO_FAILFAST], [
-+      ZFS_AC_KERNEL_BIO_FAILFAST_DTD
-+      ZFS_AC_KERNEL_REQ_FAILFAST_MASK
-+])
-diff --git a/config/kernel-bio-op.m4 b/config/kernel-bio-op.m4
-index 8299e490c..1f2d23791 100644
---- a/config/kernel-bio-op.m4
-+++ b/config/kernel-bio-op.m4
-@@ -5,13 +5,43 @@ dnl # The bio_op() helper was introduced as a replacement for explicitly
- dnl # checking the bio->bi_rw flags.  The following checks are used to
- dnl # detect if a specific operation is supported.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_REQ_OP_DISCARD], [
--      AC_MSG_CHECKING([whether REQ_OP_DISCARD is defined])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_OPS], [
-+      ZFS_LINUX_TEST_SRC([req_op_discard], [
-               #include <linux/blk_types.h>
-       ],[
-               int op __attribute__ ((unused)) = REQ_OP_DISCARD;
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([req_op_secure_erase], [
-+              #include <linux/blk_types.h>
-       ],[
-+              int op __attribute__ ((unused)) = REQ_OP_SECURE_ERASE;
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([req_op_flush], [
-+              #include <linux/blk_types.h>
-+      ],[
-+              int op __attribute__ ((unused)) = REQ_OP_FLUSH;
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([bio_bi_opf], [
-+              #include <linux/bio.h>
-+      ],[
-+              struct bio bio __attribute__ ((unused));
-+              bio.bi_opf = 0;
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([bio_set_op_attrs], [
-+              #include <linux/bio.h>
-+      ],[
-+              struct bio *bio __attribute__ ((unused)) = NULL;
-+              bio_set_op_attrs(bio, 0, 0);
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_REQ_OP_DISCARD], [
-+      AC_MSG_CHECKING([whether REQ_OP_DISCARD is defined])
-+      ZFS_LINUX_TEST_RESULT([req_op_discard], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_REQ_OP_DISCARD, 1,
-                   [REQ_OP_DISCARD is defined])
-@@ -22,11 +52,7 @@ AC_DEFUN([ZFS_AC_KERNEL_REQ_OP_DISCARD], [
- AC_DEFUN([ZFS_AC_KERNEL_REQ_OP_SECURE_ERASE], [
-       AC_MSG_CHECKING([whether REQ_OP_SECURE_ERASE is defined])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/blk_types.h>
--      ],[
--              int op __attribute__ ((unused)) = REQ_OP_SECURE_ERASE;
--      ],[
-+      ZFS_LINUX_TEST_RESULT([req_op_secure_erase], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_REQ_OP_SECURE_ERASE, 1,
-                   [REQ_OP_SECURE_ERASE is defined])
-@@ -38,14 +64,9 @@ AC_DEFUN([ZFS_AC_KERNEL_REQ_OP_SECURE_ERASE], [
- AC_DEFUN([ZFS_AC_KERNEL_REQ_OP_FLUSH], [
-       AC_MSG_CHECKING([whether REQ_OP_FLUSH is defined])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/blk_types.h>
--      ],[
--              int op __attribute__ ((unused)) = REQ_OP_FLUSH;
--      ],[
-+      ZFS_LINUX_TEST_RESULT([req_op_flush], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_REQ_OP_FLUSH, 1,
--                  [REQ_OP_FLUSH is defined])
-+              AC_DEFINE(HAVE_REQ_OP_FLUSH, 1, [REQ_OP_FLUSH is defined])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-@@ -53,12 +74,7 @@ AC_DEFUN([ZFS_AC_KERNEL_REQ_OP_FLUSH], [
- AC_DEFUN([ZFS_AC_KERNEL_BIO_BI_OPF], [
-       AC_MSG_CHECKING([whether bio->bi_opf is defined])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/bio.h>
--      ],[
--              struct bio bio __attribute__ ((unused));
--              bio.bi_opf = 0;
--      ],[
-+      ZFS_LINUX_TEST_RESULT([bio_bi_opf], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BIO_BI_OPF, 1, [bio->bi_opf is defined])
-       ],[
-@@ -68,13 +84,7 @@ AC_DEFUN([ZFS_AC_KERNEL_BIO_BI_OPF], [
- AC_DEFUN([ZFS_AC_KERNEL_HAVE_BIO_SET_OP_ATTRS], [
-       AC_MSG_CHECKING([whether bio_set_op_attrs is available])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/bio.h>
--      ],[
--              struct bio *bio __attribute__ ((unused)) = NULL;
--
--              bio_set_op_attrs(bio, 0, 0);
--      ],[
-+      ZFS_LINUX_TEST_RESULT([bio_set_op_attrs], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BIO_SET_OP_ATTRS, 1,
-                   [bio_set_op_attrs is available])
-@@ -82,3 +92,11 @@ AC_DEFUN([ZFS_AC_KERNEL_HAVE_BIO_SET_OP_ATTRS], [
-               AC_MSG_RESULT(no)
-       ])
- ])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BIO_OPS], [
-+      ZFS_AC_KERNEL_REQ_OP_DISCARD
-+      ZFS_AC_KERNEL_REQ_OP_SECURE_ERASE
-+      ZFS_AC_KERNEL_REQ_OP_FLUSH
-+      ZFS_AC_KERNEL_BIO_BI_OPF
-+      ZFS_AC_KERNEL_HAVE_BIO_SET_OP_ATTRS
-+])
-diff --git a/config/kernel-bio-rw-barrier.m4 b/config/kernel-bio-rw-barrier.m4
-index bcf0f7ea0..f667d4884 100644
---- a/config/kernel-bio-rw-barrier.m4
-+++ b/config/kernel-bio-rw-barrier.m4
-@@ -3,20 +3,25 @@ dnl # Interface for issuing a discard bio:
- dnl # 2.6.28-2.6.35: BIO_RW_BARRIER
- dnl # 2.6.36-3.x:    REQ_BARRIER
- dnl #
--
-+dnl #
- dnl # Since REQ_BARRIER is a preprocessor definition, there is no need for an
- dnl # autotools check for it. Also, REQ_BARRIER existed in the request layer
- dnl # until torvalds/linux@7b6d91daee5cac6402186ff224c3af39d79f4a0e unified the
- dnl # request layer and bio layer flags, so it would be wrong to assume that
- dnl # the APIs are mutually exclusive contrary to the typical case.
--AC_DEFUN([ZFS_AC_KERNEL_BIO_RW_BARRIER], [
--      AC_MSG_CHECKING([whether BIO_RW_BARRIER is defined])
--      ZFS_LINUX_TRY_COMPILE([
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_RW_BARRIER], [
-+      ZFS_LINUX_TEST_SRC([bio_rw_barrier], [
-               #include <linux/bio.h>
-       ],[
-               int flags __attribute__ ((unused));
-               flags = BIO_RW_BARRIER;
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BIO_RW_BARRIER], [
-+      AC_MSG_CHECKING([whether BIO_RW_BARRIER is defined])
-+      ZFS_LINUX_TEST_RESULT([bio_rw_barrier], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BIO_RW_BARRIER, 1, [BIO_RW_BARRIER is defined])
-       ],[
-diff --git a/config/kernel-bio-rw-discard.m4 b/config/kernel-bio-rw-discard.m4
-index 0554b9a9d..34a89279c 100644
---- a/config/kernel-bio-rw-discard.m4
-+++ b/config/kernel-bio-rw-discard.m4
-@@ -3,20 +3,25 @@ dnl # Interface for issuing a discard bio:
- dnl # 2.6.28-2.6.35: BIO_RW_DISCARD
- dnl # 2.6.36-3.x:    REQ_DISCARD
- dnl #
--
-+dnl #
- dnl # Since REQ_DISCARD is a preprocessor definition, there is no need for an
- dnl # autotools check for it. Also, REQ_DISCARD existed in the request layer
- dnl # until torvalds/linux@7b6d91daee5cac6402186ff224c3af39d79f4a0e unified the
- dnl # request layer and bio layer flags, so it would be wrong to assume that
- dnl # the APIs are mutually exclusive contrary to the typical case.
--AC_DEFUN([ZFS_AC_KERNEL_BIO_RW_DISCARD], [
--      AC_MSG_CHECKING([whether BIO_RW_DISCARD is defined])
--      ZFS_LINUX_TRY_COMPILE([
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_RW_DISCARD], [
-+      ZFS_LINUX_TEST_SRC([bio_rw_discard], [
-               #include <linux/bio.h>
-       ],[
-               int flags __attribute__ ((unused));
-               flags = BIO_RW_DISCARD;
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BIO_RW_DISCARD], [
-+      AC_MSG_CHECKING([whether BIO_RW_DISCARD is defined])
-+      ZFS_LINUX_TEST_RESULT([bio_rw_discard], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BIO_RW_DISCARD, 1, [BIO_RW_DISCARD is defined])
-       ],[
-diff --git a/config/kernel-bio_set_dev.m4 b/config/kernel-bio_set_dev.m4
-index 71d47a893..b8e13f35a 100644
---- a/config/kernel-bio_set_dev.m4
-+++ b/config/kernel-bio_set_dev.m4
-@@ -3,51 +3,38 @@ dnl # Linux 4.14 API,
- dnl #
- dnl # The bio_set_dev() helper macro was introduced as part of the transition
- dnl # to have struct gendisk in struct bio. 
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BIO_SET_DEV_MACRO], [
--      AC_MSG_CHECKING([whether bio_set_dev() exists])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/bio.h>
--              #include <linux/fs.h>
--      ],[
--              struct block_device *bdev = NULL;
--              struct bio *bio = NULL;
--              bio_set_dev(bio, bdev);
--      ],[
--              AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_BIO_SET_DEV, 1, [bio_set_dev() exists])
--      ],[
--              AC_MSG_RESULT(no)
--      ])
--])
--
- dnl #
- dnl # Linux 5.0 API,
- dnl #
- dnl # The bio_set_dev() helper macro was updated to internally depend on
- dnl # bio_associate_blkg() symbol which is exported GPL-only.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BIO_SET_DEV_GPL_ONLY], [
--      AC_MSG_CHECKING([whether bio_set_dev() is GPL-only])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/module.h>
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_SET_DEV], [
-+      ZFS_LINUX_TEST_SRC([bio_set_dev], [
-               #include <linux/bio.h>
-               #include <linux/fs.h>
--              MODULE_LICENSE("$ZFS_META_LICENSE");
-       ],[
-               struct block_device *bdev = NULL;
-               struct bio *bio = NULL;
-               bio_set_dev(bio, bdev);
--      ],[
--              AC_MSG_RESULT(no)
--      ],[
--              AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_BIO_SET_DEV_GPL_ONLY, 1,
--                  [bio_set_dev() GPL-only])
--      ])
-+      ], [], [$ZFS_META_LICENSE])
- ])
- AC_DEFUN([ZFS_AC_KERNEL_BIO_SET_DEV], [
--      ZFS_AC_KERNEL_BIO_SET_DEV_MACRO
--      ZFS_AC_KERNEL_BIO_SET_DEV_GPL_ONLY
-+      AC_MSG_CHECKING([whether bio_set_dev() is available])
-+      ZFS_LINUX_TEST_RESULT([bio_set_dev], [
-+              AC_MSG_RESULT(yes)
-+              AC_DEFINE(HAVE_BIO_SET_DEV, 1, [bio_set_dev() is available])
-+
-+              AC_MSG_CHECKING([whether bio_set_dev() is GPL-only])
-+              ZFS_LINUX_TEST_RESULT([bio_set_dev_license], [
-+                      AC_MSG_RESULT(no)
-+              ],[
-+                      AC_MSG_RESULT(yes)
-+                      AC_DEFINE(HAVE_BIO_SET_DEV_GPL_ONLY, 1,
-+                          [bio_set_dev() GPL-only])
-+              ])
-+      ],[
-+              AC_MSG_RESULT(no)
-+      ])
- ])
-diff --git a/config/kernel-blk-queue-bdi.m4 b/config/kernel-blk-queue-bdi.m4
-index 816471166..28241c494 100644
---- a/config/kernel-blk-queue-bdi.m4
-+++ b/config/kernel-blk-queue-bdi.m4
-@@ -2,15 +2,19 @@ dnl #
- dnl # 2.6.32 - 4.11, statically allocated bdi in request_queue
- dnl # 4.12 - x.y, dynamically allocated bdi in request_queue
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_BDI], [
--      AC_MSG_CHECKING([whether blk_queue bdi is dynamic])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_BDI], [
-+      ZFS_LINUX_TEST_SRC([blk_queue_bdi], [
-               #include <linux/blkdev.h>
-       ],[
-               struct request_queue q;
-               struct backing_dev_info bdi;
-               q.backing_dev_info = &bdi;
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_BDI], [
-+      AC_MSG_CHECKING([whether blk_queue bdi is dynamic])
-+      ZFS_LINUX_TEST_RESULT([blk_queue_bdi], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BLK_QUEUE_BDI_DYNAMIC, 1,
-                   [blk queue backing_dev_info is dynamic])
-diff --git a/config/kernel-blk-queue-discard.m4 b/config/kernel-blk-queue-discard.m4
-index addbba814..85a29356d 100644
---- a/config/kernel-blk-queue-discard.m4
-+++ b/config/kernel-blk-queue-discard.m4
-@@ -2,16 +2,19 @@ dnl #
- dnl # 2.6.32 - 4.x API,
- dnl #   blk_queue_discard()
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_DISCARD], [
--      AC_MSG_CHECKING([whether blk_queue_discard() is available])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_DISCARD], [
-+      ZFS_LINUX_TEST_SRC([blk_queue_discard], [
-               #include <linux/blkdev.h>
-       ],[
-               struct request_queue *q __attribute__ ((unused)) = NULL;
-               int value __attribute__ ((unused));
--
-               value = blk_queue_discard(q);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_DISCARD], [
-+      AC_MSG_CHECKING([whether blk_queue_discard() is available])
-+      ZFS_LINUX_TEST_RESULT([blk_queue_discard], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BLK_QUEUE_DISCARD, 1,
-                   [blk_queue_discard() is available])
-@@ -30,16 +33,27 @@ dnl #
- dnl # 2.6.x - 2.6.35 API,
- dnl #   Unsupported by kernel
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_SECURE_ERASE], [
--      AC_MSG_CHECKING([whether blk_queue_secure_erase() is available])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_SECURE_ERASE], [
-+      ZFS_LINUX_TEST_SRC([blk_queue_secure_erase], [
-               #include <linux/blkdev.h>
-       ],[
-               struct request_queue *q __attribute__ ((unused)) = NULL;
-               int value __attribute__ ((unused));
--
-               value = blk_queue_secure_erase(q);
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([blk_queue_secdiscard], [
-+              #include <linux/blkdev.h>
-       ],[
-+              struct request_queue *q __attribute__ ((unused)) = NULL;
-+              int value __attribute__ ((unused));
-+              value = blk_queue_secdiscard(q);
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_SECURE_ERASE], [
-+      AC_MSG_CHECKING([whether blk_queue_secure_erase() is available])
-+      ZFS_LINUX_TEST_RESULT([blk_queue_secure_erase], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BLK_QUEUE_SECURE_ERASE, 1,
-                   [blk_queue_secure_erase() is available])
-@@ -47,14 +61,7 @@ AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_SECURE_ERASE], [
-               AC_MSG_RESULT(no)
-               AC_MSG_CHECKING([whether blk_queue_secdiscard() is available])
--              ZFS_LINUX_TRY_COMPILE([
--                      #include <linux/blkdev.h>
--              ],[
--                      struct request_queue *q __attribute__ ((unused)) = NULL;
--                      int value __attribute__ ((unused));
--
--                      value = blk_queue_secdiscard(q);
--              ],[
-+              ZFS_LINUX_TEST_RESULT([blk_queue_secdiscard], [
-                       AC_MSG_RESULT(yes)
-                       AC_DEFINE(HAVE_BLK_QUEUE_SECDISCARD, 1,
-                           [blk_queue_secdiscard() is available])
-diff --git a/config/kernel-blk-queue-flags.m4 b/config/kernel-blk-queue-flags.m4
-index b570245c7..9d4dfc159 100644
---- a/config/kernel-blk-queue-flags.m4
-+++ b/config/kernel-blk-queue-flags.m4
-@@ -3,36 +3,54 @@ dnl # API change
- dnl # https://github.com/torvalds/linux/commit/8814ce8
- dnl # Introduction of blk_queue_flag_set and blk_queue_flag_clear
- dnl #
--
--AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_FLAG_SET], [
--      AC_MSG_CHECKING([whether blk_queue_flag_set() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_FLAG_SET], [
-+      ZFS_LINUX_TEST_SRC([blk_queue_flag_set], [
-               #include <linux/kernel.h>
-               #include <linux/blkdev.h>
-       ],[
-               struct request_queue *q = NULL;
-               blk_queue_flag_set(0, q);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_FLAG_SET], [
-+      AC_MSG_CHECKING([whether blk_queue_flag_set() exists])
-+      ZFS_LINUX_TEST_RESULT([blk_queue_flag_set], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_BLK_QUEUE_FLAG_SET, 1, [blk_queue_flag_set() exists])
-+              AC_DEFINE(HAVE_BLK_QUEUE_FLAG_SET, 1,
-+                  [blk_queue_flag_set() exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
- ])
--AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_FLAG_CLEAR], [
--      AC_MSG_CHECKING([whether blk_queue_flag_clear() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_FLAG_CLEAR], [
-+      ZFS_LINUX_TEST_SRC([blk_queue_flag_clear], [
-               #include <linux/kernel.h>
-               #include <linux/blkdev.h>
-       ],[
-               struct request_queue *q = NULL;
-               blk_queue_flag_clear(0, q);
--      ],[
-+      ])
-+])
-+AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_FLAG_CLEAR], [
-+      AC_MSG_CHECKING([whether blk_queue_flag_clear() exists])
-+      ZFS_LINUX_TEST_RESULT([blk_queue_flag_clear], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_BLK_QUEUE_FLAG_CLEAR, 1, [blk_queue_flag_clear() exists])
-+              AC_DEFINE(HAVE_BLK_QUEUE_FLAG_CLEAR, 1,
-+                  [blk_queue_flag_clear() exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
- ])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_FLAGS], [
-+      ZFS_AC_KERNEL_SRC_BLK_QUEUE_FLAG_SET
-+      ZFS_AC_KERNEL_SRC_BLK_QUEUE_FLAG_CLEAR
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_FLAGS], [
-+      ZFS_AC_KERNEL_BLK_QUEUE_FLAG_SET
-+      ZFS_AC_KERNEL_BLK_QUEUE_FLAG_CLEAR
-+])
-diff --git a/config/kernel-blk-queue-flush.m4 b/config/kernel-blk-queue-flush.m4
-index 1baab83a4..b546d9400 100644
---- a/config/kernel-blk-queue-flush.m4
-+++ b/config/kernel-blk-queue-flush.m4
-@@ -9,35 +9,37 @@ dnl # there we implement our own compatibility function, otherwise
- dnl # we use the function.  The hope is that long term this function
- dnl # will be opened up.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_FLUSH], [
--      AC_MSG_CHECKING([whether blk_queue_flush() is available])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_FLUSH], [
-+      ZFS_LINUX_TEST_SRC([blk_queue_flush], [
-               #include <linux/blkdev.h>
--      ],[
-+      ], [
-               struct request_queue *q = NULL;
-               (void) blk_queue_flush(q, REQ_FLUSH);
--      ],[
-+      ], [$NO_UNUSED_BUT_SET_VARIABLE], [$ZFS_META_LICENSE])
-+
-+      ZFS_LINUX_TEST_SRC([blk_queue_write_cache], [
-+              #include <linux/kernel.h>
-+              #include <linux/blkdev.h>
-+      ], [
-+              struct request_queue *q = NULL;
-+              blk_queue_write_cache(q, true, true);
-+      ], [$NO_UNUSED_BUT_SET_VARIABLE], [$ZFS_META_LICENSE])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_FLUSH], [
-+      AC_MSG_CHECKING([whether blk_queue_flush() is available])
-+      ZFS_LINUX_TEST_RESULT([blk_queue_flush], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BLK_QUEUE_FLUSH, 1,
--                        [blk_queue_flush() is available])
-+                  [blk_queue_flush() is available])
-               AC_MSG_CHECKING([whether blk_queue_flush() is GPL-only])
--              ZFS_LINUX_TRY_COMPILE([
--                      #include <linux/module.h>
--                      #include <linux/blkdev.h>
--
--                      MODULE_LICENSE("$ZFS_META_LICENSE");
--              ],[
--                      struct request_queue *q = NULL;
--                      (void) blk_queue_flush(q, REQ_FLUSH);
--              ],[
-+              ZFS_LINUX_TEST_RESULT([blk_queue_flush_license], [
-                       AC_MSG_RESULT(no)
-               ],[
-                       AC_MSG_RESULT(yes)
-                       AC_DEFINE(HAVE_BLK_QUEUE_FLUSH_GPL_ONLY, 1,
--                                [blk_queue_flush() is GPL-only])
-+                          [blk_queue_flush() is GPL-only])
-               ])
-       ],[
-               AC_MSG_RESULT(no)
-@@ -48,38 +50,20 @@ AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_FLUSH], [
-       dnl # Replace blk_queue_flush with blk_queue_write_cache
-       dnl #
-       AC_MSG_CHECKING([whether blk_queue_write_cache() exists])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/kernel.h>
--              #include <linux/blkdev.h>
--
--      ],[
--              struct request_queue *q = NULL;
--              blk_queue_write_cache(q, true, true);
--      ],[
-+      ZFS_LINUX_TEST_RESULT([blk_queue_write_cache], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BLK_QUEUE_WRITE_CACHE, 1,
--                      [blk_queue_write_cache() exists])
-+                  [blk_queue_write_cache() exists])
-               AC_MSG_CHECKING([whether blk_queue_write_cache() is GPL-only])
--              ZFS_LINUX_TRY_COMPILE([
--                      #include <linux/kernel.h>
--                      #include <linux/module.h>
--                      #include <linux/blkdev.h>
--
--                      MODULE_LICENSE("$ZFS_META_LICENSE");
--              ],[
--                      struct request_queue *q = NULL;
--                      blk_queue_write_cache(q, true, true);
--              ],[
-+              ZFS_LINUX_TEST_RESULT([blk_queue_write_cache_license], [
-                       AC_MSG_RESULT(no)
-               ],[
-                       AC_MSG_RESULT(yes)
-                       AC_DEFINE(HAVE_BLK_QUEUE_WRITE_CACHE_GPL_ONLY, 1,
--                                [blk_queue_write_cache() is GPL-only])
-+                          [blk_queue_write_cache() is GPL-only])
-               ])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
--
--      EXTRA_KCFLAGS="$tmp_flags"
- ])
-diff --git a/config/kernel-blk-queue-max-hw-sectors.m4 b/config/kernel-blk-queue-max-hw-sectors.m4
-index 2f5515dc6..7387f84de 100644
---- a/config/kernel-blk-queue-max-hw-sectors.m4
-+++ b/config/kernel-blk-queue-max-hw-sectors.m4
-@@ -2,21 +2,22 @@ dnl #
- dnl # 2.6.34 API change
- dnl # blk_queue_max_hw_sectors() replaces blk_queue_max_sectors().
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_MAX_HW_SECTORS], [
--      AC_MSG_CHECKING([whether blk_queue_max_hw_sectors() is available])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_MAX_HW_SECTORS], [
-+      ZFS_LINUX_TEST_SRC([blk_queue_max_hw_sectors], [
-               #include <linux/blkdev.h>
--      ],[
-+      ], [
-               struct request_queue *q = NULL;
-               (void) blk_queue_max_hw_sectors(q, BLK_SAFE_MAX_SECTORS);
--      ],[
-+      ], [$NO_UNUSED_BUT_SET_VARIABLE])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_MAX_HW_SECTORS], [
-+      AC_MSG_CHECKING([whether blk_queue_max_hw_sectors() is available])
-+      ZFS_LINUX_TEST_RESULT([blk_queue_max_hw_sectors], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BLK_QUEUE_MAX_HW_SECTORS, 1,
--                        [blk_queue_max_hw_sectors() is available])
-+                  [blk_queue_max_hw_sectors() is available])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
- ])
-diff --git a/config/kernel-blk-queue-max-segments.m4 b/config/kernel-blk-queue-max-segments.m4
-index b2a40423a..1e4092df9 100644
---- a/config/kernel-blk-queue-max-segments.m4
-+++ b/config/kernel-blk-queue-max-segments.m4
-@@ -3,21 +3,22 @@ dnl # 2.6.34 API change
- dnl # blk_queue_max_segments() consolidates blk_queue_max_hw_segments()
- dnl # and blk_queue_max_phys_segments().
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_MAX_SEGMENTS], [
--      AC_MSG_CHECKING([whether blk_queue_max_segments() is available])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_MAX_SEGMENTS], [
-+      ZFS_LINUX_TEST_SRC([blk_queue_max_segments], [
-               #include <linux/blkdev.h>
--      ],[
-+      ], [
-               struct request_queue *q = NULL;
-               (void) blk_queue_max_segments(q, BLK_MAX_SEGMENTS);
--      ],[
-+      ], [$NO_UNUSED_BUT_SET_VARIABLE])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_MAX_SEGMENTS], [
-+      AC_MSG_CHECKING([whether blk_queue_max_segments() is available])
-+      ZFS_LINUX_TEST_RESULT([blk_queue_max_segments], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BLK_QUEUE_MAX_SEGMENTS, 1,
--                        [blk_queue_max_segments() is available])
--      ],[
-+                  [blk_queue_max_segments() is available])
-+      ], [
-               AC_MSG_RESULT(no)
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
- ])
-diff --git a/config/kernel-blk-queue-unplug.m4 b/config/kernel-blk-queue-unplug.m4
-index 075fbccd1..f5d1814b8 100644
---- a/config/kernel-blk-queue-unplug.m4
-+++ b/config/kernel-blk-queue-unplug.m4
-@@ -2,43 +2,53 @@ dnl #
- dnl # 2.6.32-2.6.35 API - The BIO_RW_UNPLUG enum can be used as a hint
- dnl # to unplug the queue.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_HAVE_BIO_RW_UNPLUG], [
--      AC_MSG_CHECKING([whether the BIO_RW_UNPLUG enum is available])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_RW_UNPLUG], [
-+      ZFS_LINUX_TEST_SRC([blk_queue_bio_rw_unplug], [
-               #include <linux/blkdev.h>
-       ],[
--              extern enum bio_rw_flags rw;
-+              enum bio_rw_flags rw __attribute__ ((unused)) = BIO_RW_UNPLUG;
-+      ])
-+])
--              rw = BIO_RW_UNPLUG;
--      ],[
-+AC_DEFUN([ZFS_AC_KERNEL_BIO_RW_UNPLUG], [
-+      AC_MSG_CHECKING([whether the BIO_RW_UNPLUG enum is available])
-+      ZFS_LINUX_TEST_RESULT([blk_queue_bio_rw_unplug], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BLK_QUEUE_HAVE_BIO_RW_UNPLUG, 1,
--                        [BIO_RW_UNPLUG is available])
-+                  [BIO_RW_UNPLUG is available])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
- ])
--AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_HAVE_BLK_PLUG], [
--      AC_MSG_CHECKING([whether struct blk_plug is available])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_PLUG], [
-+      ZFS_LINUX_TEST_SRC([blk_plug], [
-               #include <linux/blkdev.h>
-       ],[
--              struct blk_plug plug;
-+              struct blk_plug plug __attribute__ ((unused));
-               blk_start_plug(&plug);
-               blk_finish_plug(&plug);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BLK_PLUG], [
-+      AC_MSG_CHECKING([whether struct blk_plug is available])
-+      ZFS_LINUX_TEST_RESULT([blk_plug], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BLK_QUEUE_HAVE_BLK_PLUG, 1,
--                        [struct blk_plug is available])
-+                  [struct blk_plug is available])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_PLUG], [
-+      ZFS_AC_KERNEL_SRC_BIO_RW_UNPLUG
-+      ZFS_AC_KERNEL_SRC_BLK_PLUG
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_PLUG], [
-+      ZFS_AC_KERNEL_BIO_RW_UNPLUG
-+      ZFS_AC_KERNEL_BLK_PLUG
- ])
-diff --git a/config/kernel-blkdev-get-by-path.m4 b/config/kernel-blkdev-get-by-path.m4
-index 40ecc06b6..fb0cea6af 100644
---- a/config/kernel-blkdev-get-by-path.m4
-+++ b/config/kernel-blkdev-get-by-path.m4
-@@ -3,16 +3,21 @@ dnl # 2.6.38 API change
- dnl # open_bdev_exclusive() changed to blkdev_get_by_path()
- dnl # close_bdev_exclusive() changed to blkdev_put()
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_GET_BY_PATH],
--      [AC_MSG_CHECKING([whether blkdev_get_by_path() is available])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH], [
-+      ZFS_LINUX_TEST_SRC([blkdev_get_by_path], [
-               #include <linux/fs.h>
-       ], [
-               blkdev_get_by_path(NULL, 0, NULL);
--      ], [blkdev_get_by_path], [fs/block_dev.c], [
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_GET_BY_PATH], [
-+      AC_MSG_CHECKING([whether blkdev_get_by_path() is available])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([blkdev_get_by_path],
-+          [blkdev_get_by_path], [fs/block_dev.c], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BLKDEV_GET_BY_PATH, 1,
--                        [blkdev_get_by_path() is available])
-+                  [blkdev_get_by_path() is available])
-       ], [
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-blkdev-reread-part.m4 b/config/kernel-blkdev-reread-part.m4
-index 5664769a3..1bf1e7c3a 100644
---- a/config/kernel-blkdev-reread-part.m4
-+++ b/config/kernel-blkdev-reread-part.m4
-@@ -2,16 +2,20 @@ dnl #
- dnl # 4.1 API, exported blkdev_reread_part() symbol, backported to the
- dnl # 3.10.0 CentOS 7.x enterprise kernels.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_REREAD_PART], [
--      AC_MSG_CHECKING([whether blkdev_reread_part() is available])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_REREAD_PART], [
-+      ZFS_LINUX_TEST_SRC([blkdev_reread_part], [
-               #include <linux/fs.h>
-       ], [
-               struct block_device *bdev = NULL;
-               int error;
-               error = blkdev_reread_part(bdev);
--      ], [
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_REREAD_PART], [
-+      AC_MSG_CHECKING([whether blkdev_reread_part() is available])
-+      ZFS_LINUX_TEST_RESULT([blkdev_reread_part], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BLKDEV_REREAD_PART, 1,
-                   [blkdev_reread_part() is available])
-diff --git a/config/kernel-block-device-operations.m4 b/config/kernel-block-device-operations.m4
-index 5f2811c15..c3d5eec52 100644
---- a/config/kernel-block-device-operations.m4
-+++ b/config/kernel-block-device-operations.m4
-@@ -1,11 +1,8 @@
- dnl #
- dnl # 2.6.38 API change
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS], [
--      AC_MSG_CHECKING([whether bops->check_events() exists])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS], [
-+      ZFS_LINUX_TEST_SRC([block_device_operations_check_events], [
-               #include <linux/blkdev.h>
-               unsigned int blk_check_events(struct gendisk *disk,
-@@ -15,25 +12,25 @@ AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS], [
-                   bops __attribute__ ((unused)) = {
-                       .check_events   = blk_check_events,
-               };
--      ],[
--      ],[
-+      ], [], [$NO_UNUSED_BUT_SET_VARIABLE])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS], [
-+      AC_MSG_CHECKING([whether bops->check_events() exists])
-+      ZFS_LINUX_TEST_RESULT([block_device_operations_check_events], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS, 1,
-                   [bops->check_events() exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
- ])
- dnl #
- dnl # 3.10.x API change
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID], [
--      AC_MSG_CHECKING([whether bops->release() is void])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID], [
-+      ZFS_LINUX_TEST_SRC([block_device_operations_release_void], [
-               #include <linux/blkdev.h>
-               void blk_release(struct gendisk *g, fmode_t mode) { return; }
-@@ -45,13 +42,26 @@ AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID], [
-                       .ioctl          = NULL,
-                       .compat_ioctl   = NULL,
-               };
--      ],[
--      ],[
--              AC_MSG_RESULT(void)
-+      ], [], [$NO_UNUSED_BUT_SET_VARIABLE])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID], [
-+      AC_MSG_CHECKING([whether bops->release() is void])
-+      ZFS_LINUX_TEST_RESULT([block_device_operations_release_void], [
-+              AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID, 1,
-                         [bops->release() returns void])
-       ],[
--              AC_MSG_RESULT(int)
-+              AC_MSG_RESULT(no)
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS], [
-+      ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS
-+      ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS], [
-+      ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS
-+      ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID
- ])
-diff --git a/config/kernel-clear-inode.m4 b/config/kernel-clear-inode.m4
-index 8d880fcd8..3f454d7ec 100644
---- a/config/kernel-clear-inode.m4
-+++ b/config/kernel-clear-inode.m4
-@@ -19,13 +19,18 @@ dnl # Therefore, to ensure we have the correct API we only allow the
- dnl # clear_inode() compatibility code to be defined iff the evict_inode()
- dnl # functionality is also detected.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_CLEAR_INODE],
--      [AC_MSG_CHECKING([whether clear_inode() is available])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_CLEAR_INODE], [
-+      ZFS_LINUX_TEST_SRC([clear_inode], [
-               #include <linux/fs.h>
-       ], [
-               clear_inode(NULL);
--      ], [clear_inode], [fs/inode.c], [
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_CLEAR_INODE], [
-+      AC_MSG_CHECKING([whether clear_inode() is available])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([clear_inode],
-+          [clear_inode], [fs/inode.c], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_CLEAR_INODE, 1, [clear_inode() is available])
-       ], [
-diff --git a/config/kernel-commit-metadata.m4 b/config/kernel-commit-metadata.m4
-index b66a16fd2..9bc3b6622 100644
---- a/config/kernel-commit-metadata.m4
-+++ b/config/kernel-commit-metadata.m4
-@@ -4,19 +4,22 @@ dnl # Added eops->commit_metadata() callback to allow the underlying
- dnl # filesystem to determine the most efficient way to commit the inode.
- dnl # Prior to this the nfs server would issue an explicit fsync().
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_COMMIT_METADATA], [
--      AC_MSG_CHECKING([whether eops->commit_metadata() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_COMMIT_METADATA], [
-+      ZFS_LINUX_TEST_SRC([export_operations_commit_metadata], [
-               #include <linux/exportfs.h>
-               int commit_metadata(struct inode *inode) { return 0; }
-               static struct export_operations eops __attribute__ ((unused))={
-                       .commit_metadata = commit_metadata,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_COMMIT_METADATA], [
-+      AC_MSG_CHECKING([whether eops->commit_metadata() exists])
-+      ZFS_LINUX_TEST_RESULT([export_operations_commit_metadata], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_COMMIT_METADATA, 1,
--                        [eops->commit_metadata() exists])
-+                  [eops->commit_metadata() exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-config-defined.m4 b/config/kernel-config-defined.m4
-new file mode 100644
-index 000000000..0ee4231cc
---- /dev/null
-+++ b/config/kernel-config-defined.m4
-@@ -0,0 +1,183 @@
-+dnl #
-+dnl # Certain kernel build options are not supported.  These must be
-+dnl # detected at configure time and cause a build failure.  Otherwise
-+dnl # modules may be successfully built that behave incorrectly.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_CONFIG_DEFINED], [
-+      AS_IF([test "x$cross_compiling" != xyes], [
-+              AC_RUN_IFELSE([
-+                      AC_LANG_PROGRAM([
-+                              #include "$LINUX/include/linux/license.h"
-+                      ], [
-+                              return !license_is_gpl_compatible(
-+                                  "$ZFS_META_LICENSE");
-+                      ])
-+              ], [
-+                      AC_DEFINE([ZFS_IS_GPL_COMPATIBLE], [1],
-+                          [Define to 1 if GPL-only symbols can be used])
-+              ], [
-+              ])
-+      ])
-+
-+      ZFS_AC_KERNEL_SRC_CONFIG_THREAD_SIZE
-+      ZFS_AC_KERNEL_SRC_CONFIG_DEBUG_LOCK_ALLOC
-+      ZFS_AC_KERNEL_SRC_CONFIG_TRIM_UNUSED_KSYMS
-+      ZFS_AC_KERNEL_SRC_CONFIG_ZLIB_INFLATE
-+      ZFS_AC_KERNEL_SRC_CONFIG_ZLIB_DEFLATE
-+
-+      AC_MSG_CHECKING([for kernel config option compatibility])
-+      ZFS_LINUX_TEST_COMPILE_ALL([config])
-+      AC_MSG_RESULT([done])
-+
-+      ZFS_AC_KERNEL_CONFIG_THREAD_SIZE
-+      ZFS_AC_KERNEL_CONFIG_DEBUG_LOCK_ALLOC
-+      ZFS_AC_KERNEL_CONFIG_TRIM_UNUSED_KSYMS
-+      ZFS_AC_KERNEL_CONFIG_ZLIB_INFLATE
-+      ZFS_AC_KERNEL_CONFIG_ZLIB_DEFLATE
-+])
-+
-+dnl #
-+dnl # Check configured THREAD_SIZE
-+dnl #
-+dnl # The stack size will vary by architecture, but as of Linux 3.15 on x86_64
-+dnl # the default thread stack size was increased to 16K from 8K.  Therefore,
-+dnl # on newer kernels and some architectures stack usage optimizations can be
-+dnl # conditionally applied to improve performance without negatively impacting
-+dnl # stability.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_CONFIG_THREAD_SIZE], [
-+      ZFS_LINUX_TEST_SRC([config_thread_size], [
-+              #include <linux/module.h>
-+      ],[
-+              #if (THREAD_SIZE < 16384)
-+              #error "THREAD_SIZE is less than 16K"
-+              #endif
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_CONFIG_THREAD_SIZE], [
-+      AC_MSG_CHECKING([whether kernel was built with 16K or larger stacks])
-+      ZFS_LINUX_TEST_RESULT([config_thread_size], [
-+              AC_MSG_RESULT([yes])
-+              AC_DEFINE(HAVE_LARGE_STACKS, 1, [kernel has large stacks])
-+      ],[
-+              AC_MSG_RESULT([no])
-+      ])
-+])
-+
-+dnl #
-+dnl # Check CONFIG_DEBUG_LOCK_ALLOC
-+dnl #
-+dnl # This is typically only set for debug kernels because it comes with
-+dnl # a performance penalty.  However, when it is set it maps the non-GPL
-+dnl # symbol mutex_lock() to the GPL-only mutex_lock_nested() symbol.
-+dnl # This will cause a failure at link time which we'd rather know about
-+dnl # at compile time.
-+dnl #
-+dnl # Since we plan to pursue making mutex_lock_nested() a non-GPL symbol
-+dnl # with the upstream community we add a check to detect this case.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_CONFIG_DEBUG_LOCK_ALLOC], [
-+      ZFS_LINUX_TEST_SRC([config_debug_lock_alloc], [
-+              #include <linux/mutex.h>
-+      ],[
-+              struct mutex lock;
-+
-+              mutex_init(&lock);
-+              mutex_lock(&lock);
-+              mutex_unlock(&lock);
-+      ], [], [$ZFS_META_LICENSE])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_CONFIG_DEBUG_LOCK_ALLOC], [
-+      AC_MSG_CHECKING([whether mutex_lock() is GPL-only])
-+      ZFS_LINUX_TEST_RESULT([config_debug_lock_alloc], [
-+              AC_MSG_RESULT(no)
-+      ],[
-+              AC_MSG_RESULT(yes)
-+              AC_MSG_ERROR([
-+      *** Kernel built with CONFIG_DEBUG_LOCK_ALLOC which is incompatible
-+      *** with the CDDL license and will prevent the module linking stage
-+      *** from succeeding.  You must rebuild your kernel without this
-+      *** option enabled.])
-+      ])
-+])
-+
-+dnl #
-+dnl # Check CONFIG_TRIM_UNUSED_KSYMS
-+dnl #
-+dnl # Verify the kernel has CONFIG_TRIM_UNUSED_KSYMS disabled.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_CONFIG_TRIM_UNUSED_KSYMS], [
-+      ZFS_LINUX_TEST_SRC([config_trim_unusued_ksyms], [
-+              #if defined(CONFIG_TRIM_UNUSED_KSYMS)
-+              #error CONFIG_TRIM_UNUSED_KSYMS not defined
-+              #endif
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_CONFIG_TRIM_UNUSED_KSYMS], [
-+      AC_MSG_CHECKING([whether CONFIG_TRIM_UNUSED_KSYM is disabled])
-+      ZFS_LINUX_TEST_RESULT([config_trim_unusued_ksyms], [
-+              AC_MSG_RESULT([yes])
-+      ],[
-+              AC_MSG_RESULT([no])
-+              AS_IF([test "x$enable_linux_builtin" != xyes], [
-+                      AC_MSG_ERROR([
-+      *** This kernel has unused symbols trimming enabled, please disable.
-+      *** Rebuild the kernel with CONFIG_TRIM_UNUSED_KSYMS=n set.])
-+              ])
-+      ])
-+])
-+
-+dnl #
-+dnl # Check CONFIG_ZLIB_INFLATE
-+dnl #
-+dnl # Verify the kernel has CONFIG_ZLIB_INFLATE support enabled.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_CONFIG_ZLIB_INFLATE], [
-+      ZFS_LINUX_TEST_SRC([config_zlib_inflate], [
-+              #if !defined(CONFIG_ZLIB_INFLATE) && \
-+                  !defined(CONFIG_ZLIB_INFLATE_MODULE)
-+              #error CONFIG_ZLIB_INFLATE not defined
-+              #endif
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_CONFIG_ZLIB_INFLATE], [
-+      AC_MSG_CHECKING([whether CONFIG_ZLIB_INFLATE is defined])
-+      ZFS_LINUX_TEST_RESULT([config_zlib_inflate], [
-+              AC_MSG_RESULT([yes])
-+      ],[
-+              AC_MSG_RESULT([no])
-+              AC_MSG_ERROR([
-+      *** This kernel does not include the required zlib inflate support.
-+      *** Rebuild the kernel with CONFIG_ZLIB_INFLATE=y|m set.])
-+      ])
-+])
-+
-+dnl #
-+dnl # Check CONFIG_ZLIB_DEFLATE
-+dnl #
-+dnl # Verify the kernel has CONFIG_ZLIB_DEFLATE support enabled.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_CONFIG_ZLIB_DEFLATE], [
-+      ZFS_LINUX_TEST_SRC([config_zlib_deflate], [
-+              #if !defined(CONFIG_ZLIB_DEFLATE) && \
-+                  !defined(CONFIG_ZLIB_DEFLATE_MODULE)
-+              #error CONFIG_ZLIB_DEFLATE not defined
-+              #endif
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_CONFIG_ZLIB_DEFLATE], [
-+      AC_MSG_CHECKING([whether CONFIG_ZLIB_DEFLATE is defined])
-+      ZFS_LINUX_TEST_RESULT([config_zlib_deflate], [
-+              AC_MSG_RESULT([yes])
-+      ],[
-+              AC_MSG_RESULT([no])
-+              AC_MSG_ERROR([
-+      *** This kernel does not include the required zlib deflate support.
-+      *** Rebuild the kernel with CONFIG_ZLIB_DEFLATE=y|m set.])
-+      ])
-+])
-diff --git a/config/kernel-create-nameidata.m4 b/config/kernel-create-nameidata.m4
-index d4c155c57..c43ca5b85 100644
---- a/config/kernel-create-nameidata.m4
-+++ b/config/kernel-create-nameidata.m4
-@@ -1,9 +1,8 @@
- dnl #
- dnl # 3.6 API change
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_CREATE_NAMEIDATA], [
--      AC_MSG_CHECKING([whether iops->create() passes nameidata])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE_NAMEIDATA], [
-+      ZFS_LINUX_TEST_SRC([create_nameidata], [
-               #include <linux/fs.h>
-               #include <linux/sched.h>
-@@ -19,11 +18,15 @@ AC_DEFUN([ZFS_AC_KERNEL_CREATE_NAMEIDATA], [
-                   iops __attribute__ ((unused)) = {
-                       .create         = inode_create,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_CREATE_NAMEIDATA], [
-+      AC_MSG_CHECKING([whether iops->create() passes nameidata])
-+      ZFS_LINUX_TEST_RESULT([create_nameidata], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_CREATE_NAMEIDATA, 1,
--                        [iops->create() passes nameidata])
-+                  [iops->create() passes nameidata])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-ctl-table-name.m4 b/config/kernel-ctl-table-name.m4
-index 3ce499968..16f2ad544 100644
---- a/config/kernel-ctl-table-name.m4
-+++ b/config/kernel-ctl-table-name.m4
-@@ -2,14 +2,18 @@ dnl #
- dnl # 2.6.33 API change,
- dnl # Removed .ctl_name from struct ctl_table.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_CTL_NAME], [
--      AC_MSG_CHECKING([whether struct ctl_table has ctl_name])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_CTL_NAME], [
-+      ZFS_LINUX_TEST_SRC([ctl_name], [
-               #include <linux/sysctl.h>
-       ],[
-               struct ctl_table ctl __attribute__ ((unused));
-               ctl.ctl_name = 0;
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_CTL_NAME], [
-+      AC_MSG_CHECKING([whether struct ctl_table has ctl_name])
-+      ZFS_LINUX_TEST_RESULT([ctl_name], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_CTL_NAME, 1, [struct ctl_table has ctl_name])
-       ],[
-diff --git a/config/kernel-current-time.m4 b/config/kernel-current-time.m4
-index c7d5c9b52..3ceb5f63e 100644
---- a/config/kernel-current-time.m4
-+++ b/config/kernel-current-time.m4
-@@ -2,14 +2,19 @@ dnl #
- dnl # 4.9, current_time() added
- dnl # 4.18, return type changed from timespec to timespec64
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_CURRENT_TIME],
--      [AC_MSG_CHECKING([whether current_time() exists])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_CURRENT_TIME], [
-+      ZFS_LINUX_TEST_SRC([current_time], [
-               #include <linux/fs.h>
-       ], [
-               struct inode ip __attribute__ ((unused));
-               ip.i_atime = current_time(&ip);
--      ], [current_time], [fs/inode.c], [
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_CURRENT_TIME], [
-+      AC_MSG_CHECKING([whether current_time() exists])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([current_time],
-+          [current_time], [fs/inode.c], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_CURRENT_TIME, 1, [current_time() exists])
-       ], [
-diff --git a/config/kernel-current_bio_tail.m4 b/config/kernel-current_bio_tail.m4
-index b72f21e8a..9dfc3e6e0 100644
---- a/config/kernel-current_bio_tail.m4
-+++ b/config/kernel-current_bio_tail.m4
-@@ -4,30 +4,36 @@ dnl # current->bio_tail and current->bio_list were struct bio pointers prior to
- dnl # Linux 2.6.34. They were refactored into a struct bio_list pointer called
- dnl # current->bio_list in Linux 2.6.34.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_CURRENT_BIO_TAIL], [
--      AC_MSG_CHECKING([whether current->bio_tail exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_CURRENT_BIO_TAIL], [
-+      ZFS_LINUX_TEST_SRC([current_bio_tail], [
-               #include <linux/sched.h>
--      ],[
-+      ], [
-               current->bio_tail = (struct bio **) NULL;
--      ],[
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([current_bio_list], [
-+              #include <linux/sched.h>
-+      ], [
-+              current->bio_list = (struct bio_list *) NULL;
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_CURRENT_BIO_TAIL], [
-+      AC_MSG_CHECKING([whether current->bio_tail exists])
-+      ZFS_LINUX_TEST_RESULT([current_bio_tail], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_CURRENT_BIO_TAIL, 1,
-                   [current->bio_tail exists])
-       ],[
-               AC_MSG_RESULT(no)
-+
-               AC_MSG_CHECKING([whether current->bio_list exists])
--              ZFS_LINUX_TRY_COMPILE([
--                      #include <linux/sched.h>
--              ],[
--                      current->bio_list = (struct bio_list *) NULL;
--              ],[
-+              ZFS_LINUX_TEST_RESULT([current_bio_list], [
-                       AC_MSG_RESULT(yes)
-                       AC_DEFINE(HAVE_CURRENT_BIO_LIST, 1,
-                           [current->bio_list exists])
-               ],[
--                      AC_MSG_ERROR(no - Please file a bug report at
--                          https://github.com/zfsonlinux/zfs/issues/new)
-+                      ZFS_LINUX_TEST_ERROR([bio_list])
-               ])
-       ])
- ])
-diff --git a/config/kernel-d-make-root.m4 b/config/kernel-d-make-root.m4
-deleted file mode 100644
-index 9c2b73dcb..000000000
---- a/config/kernel-d-make-root.m4
-+++ /dev/null
-@@ -1,17 +0,0 @@
--dnl #
--dnl # 3.4.0 API change
--dnl # Added d_make_root() to replace previous d_alloc_root() function.
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_D_MAKE_ROOT],
--      [AC_MSG_CHECKING([whether d_make_root() is available])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
--              #include <linux/dcache.h>
--      ], [
--              d_make_root(NULL);
--      ], [d_make_root], [fs/dcache.c], [
--              AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_D_MAKE_ROOT, 1, [d_make_root() is available])
--      ], [
--              AC_MSG_RESULT(no)
--      ])
--])
-diff --git a/config/kernel-d-obtain-alias.m4 b/config/kernel-d-obtain-alias.m4
-deleted file mode 100644
-index 2b4b11ecc..000000000
---- a/config/kernel-d-obtain-alias.m4
-+++ /dev/null
-@@ -1,18 +0,0 @@
--dnl #
--dnl # 2.6.28 API change
--dnl # Added d_obtain_alias() helper function.
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_D_OBTAIN_ALIAS],
--      [AC_MSG_CHECKING([whether d_obtain_alias() is available])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
--              #include <linux/dcache.h>
--      ], [
--              d_obtain_alias(NULL);
--      ], [d_obtain_alias], [fs/dcache.c], [
--              AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_D_OBTAIN_ALIAS, 1,
--                        [d_obtain_alias() is available])
--      ], [
--              AC_MSG_RESULT(no)
--      ])
--])
-diff --git a/config/kernel-d-prune-aliases.m4 b/config/kernel-d-prune-aliases.m4
-deleted file mode 100644
-index d9c521b1d..000000000
---- a/config/kernel-d-prune-aliases.m4
-+++ /dev/null
-@@ -1,19 +0,0 @@
--dnl #
--dnl # 2.6.12 API change
--dnl # d_prune_aliases() helper function available.
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_D_PRUNE_ALIASES],
--      [AC_MSG_CHECKING([whether d_prune_aliases() is available])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
--              #include <linux/dcache.h>
--      ], [
--              struct inode *ip = NULL;
--              d_prune_aliases(ip);
--      ], [d_prune_aliases], [fs/dcache.c], [
--              AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_D_PRUNE_ALIASES, 1,
--                        [d_prune_aliases() is available])
--      ], [
--              AC_MSG_RESULT(no)
--      ])
--])
-diff --git a/config/kernel-declare-event-class.m4 b/config/kernel-declare-event-class.m4
-index 7867d7517..6c78ee858 100644
---- a/config/kernel-declare-event-class.m4
-+++ b/config/kernel-declare-event-class.m4
-@@ -2,13 +2,10 @@ dnl #
- dnl # Ensure the DECLARE_EVENT_CLASS macro is available to non-GPL modules.
- dnl #
- AC_DEFUN([ZFS_AC_KERNEL_DECLARE_EVENT_CLASS], [
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="-I\$(src)"
--
-       AC_MSG_CHECKING([whether DECLARE_EVENT_CLASS() is available])
-       ZFS_LINUX_TRY_COMPILE_HEADER([
-               #include <linux/module.h>
--              MODULE_LICENSE(ZFS_META_LICENSE);
-+              MODULE_LICENSE("$ZFS_META_LICENSE");
-               #define CREATE_TRACE_POINTS
-               #include "conftest.h"
-@@ -18,7 +15,7 @@ AC_DEFUN([ZFS_AC_KERNEL_DECLARE_EVENT_CLASS], [
-       ],[
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_DECLARE_EVENT_CLASS, 1,
--                        [DECLARE_EVENT_CLASS() is available])
-+                  [DECLARE_EVENT_CLASS() is available])
-       ],[
-               AC_MSG_RESULT(no)
-       ],[
-@@ -55,5 +52,4 @@ AC_DEFUN([ZFS_AC_KERNEL_DECLARE_EVENT_CLASS], [
-               #define TRACE_INCLUDE_FILE conftest
-               #include <trace/define_trace.h>
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
- ])
-diff --git a/config/kernel-dentry-operations.m4 b/config/kernel-dentry-operations.m4
-index 61f5a27af..f943dad4c 100644
---- a/config/kernel-dentry-operations.m4
-+++ b/config/kernel-dentry-operations.m4
-@@ -1,9 +1,103 @@
-+dnl #
-+dnl # 3.4.0 API change
-+dnl # Added d_make_root() to replace previous d_alloc_root() function.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_D_MAKE_ROOT], [
-+      ZFS_LINUX_TEST_SRC([d_make_root], [
-+              #include <linux/dcache.h>
-+      ], [
-+              d_make_root(NULL);
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_D_MAKE_ROOT], [
-+      AC_MSG_CHECKING([whether d_make_root() is available])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([d_make_root],
-+          [d_make_root], [fs/dcache.c], [
-+              AC_MSG_RESULT(yes)
-+              AC_DEFINE(HAVE_D_MAKE_ROOT, 1, [d_make_root() is available])
-+      ], [
-+              AC_MSG_RESULT(no)
-+      ])
-+])
-+
-+dnl #
-+dnl # 2.6.28 API change
-+dnl # Added d_obtain_alias() helper function.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_D_OBTAIN_ALIAS], [
-+      ZFS_LINUX_TEST_SRC([d_obtain_alias], [
-+              #include <linux/dcache.h>
-+      ], [
-+              d_obtain_alias(NULL);
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_D_OBTAIN_ALIAS], [
-+      AC_MSG_CHECKING([whether d_obtain_alias() is available])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([d_obtain_alias],
-+          [d_obtain_alias], [fs/dcache.c], [
-+              AC_MSG_RESULT(yes)
-+              AC_DEFINE(HAVE_D_OBTAIN_ALIAS, 1,
-+                        [d_obtain_alias() is available])
-+      ], [
-+              AC_MSG_RESULT(no)
-+      ])
-+])
-+
-+dnl #
-+dnl # 2.6.12 API change
-+dnl # d_prune_aliases() helper function available.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_D_PRUNE_ALIASES], [
-+      ZFS_LINUX_TEST_SRC([d_prune_aliases], [
-+              #include <linux/dcache.h>
-+      ], [
-+              struct inode *ip = NULL;
-+              d_prune_aliases(ip);
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_D_PRUNE_ALIASES], [
-+      AC_MSG_CHECKING([whether d_prune_aliases() is available])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([d_prune_aliases],
-+          [d_prune_aliases], [fs/dcache.c], [
-+              AC_MSG_RESULT(yes)
-+              AC_DEFINE(HAVE_D_PRUNE_ALIASES, 1,
-+                  [d_prune_aliases() is available])
-+      ], [
-+              AC_MSG_RESULT(no)
-+      ])
-+])
-+
-+dnl #
-+dnl # 2.6.38 API change
-+dnl # Added d_set_d_op() helper function.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_D_SET_D_OP], [
-+      ZFS_LINUX_TEST_SRC([d_set_d_op], [
-+              #include <linux/dcache.h>
-+      ], [
-+              d_set_d_op(NULL, NULL);
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_D_SET_D_OP], [
-+      AC_MSG_CHECKING([whether d_set_d_op() is available])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([d_set_d_op],
-+          [d_set_d_op], [fs/dcache.c], [
-+              AC_MSG_RESULT(yes)
-+              AC_DEFINE(HAVE_D_SET_D_OP, 1, [d_set_d_op() is available])
-+      ], [
-+              AC_MSG_RESULT(no)
-+      ])
-+])
-+
- dnl #
- dnl # 3.6 API change
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_D_REVALIDATE_NAMEIDATA], [
--      AC_MSG_CHECKING([whether dops->d_revalidate() takes struct nameidata])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_D_REVALIDATE_NAMEIDATA], [
-+      ZFS_LINUX_TEST_SRC([dentry_operations_revalidate], [
-               #include <linux/dcache.h>
-               #include <linux/sched.h>
-@@ -14,11 +108,15 @@ AC_DEFUN([ZFS_AC_KERNEL_D_REVALIDATE_NAMEIDATA], [
-                   dops __attribute__ ((unused)) = {
-                       .d_revalidate   = revalidate,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_D_REVALIDATE_NAMEIDATA], [
-+      AC_MSG_CHECKING([whether dops->d_revalidate() takes struct nameidata])
-+      ZFS_LINUX_TEST_RESULT([dentry_operations_revalidate], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_D_REVALIDATE_NAMEIDATA, 1,
--                        [dops->d_revalidate() operation takes nameidata])
-+                  [dops->d_revalidate() operation takes nameidata])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-@@ -28,9 +126,8 @@ dnl #
- dnl # 2.6.30 API change
- dnl # The 'struct dentry_operations' was constified in the dentry structure.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_CONST_DENTRY_OPERATIONS], [
--      AC_MSG_CHECKING([whether dentry uses const struct dentry_operations])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_CONST_DENTRY_OPERATIONS], [
-+      ZFS_LINUX_TEST_SRC([dentry_operations_const], [
-               #include <linux/dcache.h>
-               const struct dentry_operations test_d_op = {
-@@ -38,32 +135,17 @@ AC_DEFUN([ZFS_AC_KERNEL_CONST_DENTRY_OPERATIONS], [
-               };
-       ],[
-               struct dentry d __attribute__ ((unused));
--
-               d.d_op = &test_d_op;
--      ],[
--              AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_CONST_DENTRY_OPERATIONS, 1,
--                        [dentry uses const struct dentry_operations])
--      ],[
--              AC_MSG_RESULT(no)
-       ])
- ])
--dnl #
--dnl # 2.6.38 API change
--dnl # Added d_set_d_op() helper function.
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_D_SET_D_OP],
--      [AC_MSG_CHECKING([whether d_set_d_op() is available])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
--              #include <linux/dcache.h>
--      ], [
--              d_set_d_op(NULL, NULL);
--      ], [d_set_d_op], [fs/dcache.c], [
-+AC_DEFUN([ZFS_AC_KERNEL_CONST_DENTRY_OPERATIONS], [
-+      AC_MSG_CHECKING([whether dentry uses const struct dentry_operations])
-+      ZFS_LINUX_TEST_RESULT([dentry_operations_const], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_D_SET_D_OP, 1,
--                        [d_set_d_op() is available])
--      ], [
-+              AC_DEFINE(HAVE_CONST_DENTRY_OPERATIONS, 1,
-+                  [dentry uses const struct dentry_operations])
-+      ],[
-               AC_MSG_RESULT(no)
-       ])
- ])
-@@ -72,17 +154,41 @@ dnl #
- dnl # 2.6.38 API chage
- dnl # Added sb->s_d_op default dentry_operations member
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_S_D_OP],
--      [AC_MSG_CHECKING([whether super_block has s_d_op])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_S_D_OP], [
-+      ZFS_LINUX_TEST_SRC([super_block_s_d_op], [
-               #include <linux/fs.h>
-       ],[
-               struct super_block sb __attribute__ ((unused));
-               sb.s_d_op = NULL;
--      ], [
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_S_D_OP], [
-+      AC_MSG_CHECKING([whether super_block has s_d_op])
-+      ZFS_LINUX_TEST_RESULT([super_block_s_d_op], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_S_D_OP, 1, [struct super_block has s_d_op])
-       ], [
-               AC_MSG_RESULT(no)
-       ])
- ])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_DENTRY], [
-+        ZFS_AC_KERNEL_SRC_D_MAKE_ROOT
-+        ZFS_AC_KERNEL_SRC_D_OBTAIN_ALIAS
-+        ZFS_AC_KERNEL_SRC_D_PRUNE_ALIASES
-+        ZFS_AC_KERNEL_SRC_D_SET_D_OP
-+        ZFS_AC_KERNEL_SRC_D_REVALIDATE_NAMEIDATA
-+        ZFS_AC_KERNEL_SRC_CONST_DENTRY_OPERATIONS
-+        ZFS_AC_KERNEL_SRC_S_D_OP
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_DENTRY], [
-+        ZFS_AC_KERNEL_D_MAKE_ROOT
-+        ZFS_AC_KERNEL_D_OBTAIN_ALIAS
-+        ZFS_AC_KERNEL_D_PRUNE_ALIASES
-+        ZFS_AC_KERNEL_D_SET_D_OP
-+        ZFS_AC_KERNEL_D_REVALIDATE_NAMEIDATA
-+        ZFS_AC_KERNEL_CONST_DENTRY_OPERATIONS
-+        ZFS_AC_KERNEL_S_D_OP
-+])
-diff --git a/config/kernel-dirty-inode.m4 b/config/kernel-dirty-inode.m4
-index ffd87bb14..dc7667fa4 100644
---- a/config/kernel-dirty-inode.m4
-+++ b/config/kernel-dirty-inode.m4
-@@ -4,9 +4,8 @@ dnl # The sops->dirty_inode() callbacks were updated to take a flags
- dnl # argument.  This allows the greater control over whether the
- dnl # filesystem needs to push out a transaction or not.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_DIRTY_INODE_WITH_FLAGS], [
--      AC_MSG_CHECKING([whether sops->dirty_inode() wants flags])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_DIRTY_INODE], [
-+      ZFS_LINUX_TEST_SRC([dirty_inode_with_flags], [
-               #include <linux/fs.h>
-               void dirty_inode(struct inode *a, int b) { return; }
-@@ -15,11 +14,15 @@ AC_DEFUN([ZFS_AC_KERNEL_DIRTY_INODE_WITH_FLAGS], [
-                   sops __attribute__ ((unused)) = {
-                       .dirty_inode = dirty_inode,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_DIRTY_INODE], [
-+      AC_MSG_CHECKING([whether sops->dirty_inode() wants flags])
-+      ZFS_LINUX_TEST_RESULT([dirty_inode_with_flags], [
-               AC_MSG_RESULT([yes])
-               AC_DEFINE(HAVE_DIRTY_INODE_WITH_FLAGS, 1,
--                      [sops->dirty_inode() wants flags])
-+                  [sops->dirty_inode() wants flags])
-       ],[
-               AC_MSG_RESULT([no])
-       ])
-diff --git a/config/kernel-discard-granularity.m4 b/config/kernel-discard-granularity.m4
-index 2c677c909..c830d9aa9 100644
---- a/config/kernel-discard-granularity.m4
-+++ b/config/kernel-discard-granularity.m4
-@@ -2,18 +2,21 @@ dnl #
- dnl # 2.6.33 API change
- dnl # Discard granularity and alignment restrictions may now be set.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_DISCARD_GRANULARITY], [
--      AC_MSG_CHECKING([whether ql->discard_granularity is available])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_DISCARD_GRANULARITY], [
-+      ZFS_LINUX_TEST_SRC([discard_granularity], [
-               #include <linux/blkdev.h>
-       ],[
-               struct queue_limits ql __attribute__ ((unused));
--
-               ql.discard_granularity = 0;
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_DISCARD_GRANULARITY], [
-+      AC_MSG_CHECKING([whether ql->discard_granularity is available])
-+      ZFS_LINUX_TEST_RESULT([discard_granularity], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_DISCARD_GRANULARITY, 1,
--                        [ql->discard_granularity is available])
-+                  [ql->discard_granularity is available])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-elevator-change.m4 b/config/kernel-elevator-change.m4
-index eba252579..3aa732040 100644
---- a/config/kernel-elevator-change.m4
-+++ b/config/kernel-elevator-change.m4
-@@ -2,24 +2,25 @@ dnl #
- dnl # 2.6.36 API, exported elevator_change() symbol
- dnl # 4.12 API, removed elevator_change() symbol
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_ELEVATOR_CHANGE], [
--      AC_MSG_CHECKING([whether elevator_change() is available])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_ELEVATOR_CHANGE], [
-+      ZFS_LINUX_TEST_SRC([elevator_change], [
-               #include <linux/blkdev.h>
-               #include <linux/elevator.h>
-       ],[
--              int ret;
-               struct request_queue *q = NULL;
-               char *elevator = NULL;
--              ret = elevator_change(q, elevator);
--      ],[
-+              int error __attribute__ ((unused)) =
-+                  elevator_change(q, elevator);
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_ELEVATOR_CHANGE], [
-+      AC_MSG_CHECKING([whether elevator_change() is available])
-+      ZFS_LINUX_TEST_RESULT([elevator_change], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_ELEVATOR_CHANGE, 1,
--                        [elevator_change() is available])
-+                  [elevator_change() is available])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
- ])
-diff --git a/config/kernel-encode-fh-inode.m4 b/config/kernel-encode-fh-inode.m4
-index 287f62a5e..9d4ba5f0f 100644
---- a/config/kernel-encode-fh-inode.m4
-+++ b/config/kernel-encode-fh-inode.m4
-@@ -4,20 +4,23 @@ dnl # torvalds/linux@b0b0382bb4904965a9e9fca77ad87514dfda0d1c changed the
- dnl # ->encode_fh() callback to pass the child inode and its parents inode
- dnl # rather than a dentry and a boolean saying whether we want the parent.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_ENCODE_FH_WITH_INODE], [
--      AC_MSG_CHECKING([whether eops->encode_fh() wants inode])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_ENCODE_FH_WITH_INODE], [
-+      ZFS_LINUX_TEST_SRC([export_operations_encode_fh], [
-               #include <linux/exportfs.h>
-               int encode_fh(struct inode *inode, __u32 *fh, int *max_len,
-                             struct inode *parent) { return 0; }
-               static struct export_operations eops __attribute__ ((unused))={
-                       .encode_fh = encode_fh,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_ENCODE_FH_WITH_INODE], [
-+      AC_MSG_CHECKING([whether eops->encode_fh() wants inode])
-+      ZFS_LINUX_TEST_RESULT([export_operations_encode_fh], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_ENCODE_FH_WITH_INODE, 1,
--                        [eops->encode_fh() wants child and parent inodes])
-+                  [eops->encode_fh() wants child and parent inodes])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-evict-inode.m4 b/config/kernel-evict-inode.m4
-index 683cedb6d..cd91c6669 100644
---- a/config/kernel-evict-inode.m4
-+++ b/config/kernel-evict-inode.m4
-@@ -3,16 +3,19 @@ dnl # 2.6.36 API change
- dnl # The sops->delete_inode() and sops->clear_inode() callbacks have
- dnl # replaced by a single sops->evict_inode() callback.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_EVICT_INODE], [
--      AC_MSG_CHECKING([whether sops->evict_inode() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_EVICT_INODE], [
-+      ZFS_LINUX_TEST_SRC([evict_inode], [
-               #include <linux/fs.h>
-               void evict_inode (struct inode * t) { return; }
-               static struct super_operations sops __attribute__ ((unused)) = {
-                       .evict_inode = evict_inode,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_EVICT_INODE], [
-+      AC_MSG_CHECKING([whether sops->evict_inode() exists])
-+      ZFS_LINUX_TEST_RESULT([evict_inode], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_EVICT_INODE, 1, [sops->evict_inode() exists])
-       ],[
-diff --git a/config/kernel-fallocate-pax.m4 b/config/kernel-fallocate-pax.m4
-deleted file mode 100644
-index e8948be17..000000000
---- a/config/kernel-fallocate-pax.m4
-+++ /dev/null
-@@ -1,19 +0,0 @@
--dnl #
--dnl # PaX Linux 2.6.38 - 3.x API
--dnl #
--AC_DEFUN([ZFS_AC_PAX_KERNEL_FILE_FALLOCATE], [
--      AC_MSG_CHECKING([whether fops->fallocate() exists])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/fs.h>
--      ],[
--              long (*fallocate) (struct file *, int, loff_t, loff_t) = NULL;
--              struct file_operations_no_const fops __attribute__ ((unused)) = {
--                      .fallocate = fallocate,
--              };
--      ],[
--              AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_FILE_FALLOCATE, 1, [fops->fallocate() exists])
--      ],[
--              AC_MSG_RESULT(no)
--      ])
--])
-diff --git a/config/kernel-fallocate.m4 b/config/kernel-fallocate.m4
-index 550906472..302957a6c 100644
---- a/config/kernel-fallocate.m4
-+++ b/config/kernel-fallocate.m4
-@@ -1,9 +1,11 @@
- dnl #
--dnl # Linux 2.6.38 - 3.x API
-+dnl # The fallocate callback was moved from the inode_operations
-+dnl # structure to the file_operations structure.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_FILE_FALLOCATE], [
--      AC_MSG_CHECKING([whether fops->fallocate() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_FALLOCATE], [
-+
-+      dnl # Linux 2.6.38 - 3.x API
-+      ZFS_LINUX_TEST_SRC([file_fallocate], [
-               #include <linux/fs.h>
-               long test_fallocate(struct file *file, int mode,
-@@ -13,21 +15,10 @@ AC_DEFUN([ZFS_AC_KERNEL_FILE_FALLOCATE], [
-                   fops __attribute__ ((unused)) = {
-                       .fallocate = test_fallocate,
-               };
--      ],[
--      ],[
--              AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_FILE_FALLOCATE, 1, [fops->fallocate() exists])
--      ],[
--              AC_MSG_RESULT(no)
--      ])
--])
-+      ], [])
--dnl #
--dnl # Linux 2.6.x - 2.6.37 API
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_INODE_FALLOCATE], [
--      AC_MSG_CHECKING([whether iops->fallocate() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+      dnl # Linux 2.6.x - 2.6.37 API
-+      ZFS_LINUX_TEST_SRC([inode_fallocate], [
-               #include <linux/fs.h>
-               long test_fallocate(struct inode *inode, int mode,
-@@ -37,20 +28,23 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_FALLOCATE], [
-                   fops __attribute__ ((unused)) = {
-                       .fallocate = test_fallocate,
-               };
-+      ], [])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_FALLOCATE], [
-+      AC_MSG_CHECKING([whether fops->fallocate() exists])
-+      ZFS_LINUX_TEST_RESULT([file_fallocate], [
-+              AC_MSG_RESULT(yes)
-+              AC_DEFINE(HAVE_FILE_FALLOCATE, 1, [fops->fallocate() exists])
-       ],[
--      ],[
-+              AC_MSG_RESULT(no)
-+      ])
-+
-+      AC_MSG_CHECKING([whether iops->fallocate() exists])
-+      ZFS_LINUX_TEST_RESULT([inode_fallocate], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_INODE_FALLOCATE, 1, [fops->fallocate() exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
- ])
--
--dnl #
--dnl # The fallocate callback was moved from the inode_operations
--dnl # structure to the file_operations structure.
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_FALLOCATE], [
--      ZFS_AC_KERNEL_FILE_FALLOCATE
--      ZFS_AC_KERNEL_INODE_FALLOCATE
--])
-diff --git a/config/kernel-file-dentry.m4 b/config/kernel-file-dentry.m4
-index daf742ee1..9cb5869c3 100644
---- a/config/kernel-file-dentry.m4
-+++ b/config/kernel-file-dentry.m4
-@@ -4,14 +4,18 @@ dnl # struct access file->f_path.dentry was replaced by accessor function
- dnl # since fix torvalds/linux@4bacc9c9234c ("overlayfs: Make f_path always
- dnl # point to the overlay and f_inode to the underlay").
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_FILE_DENTRY], [
--      AC_MSG_CHECKING([whether file_dentry() is available])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_FILE_DENTRY], [
-+      ZFS_LINUX_TEST_SRC([file_dentry], [
-               #include <linux/fs.h>
-       ],[
-               struct file *f = NULL;
-               file_dentry(f);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_FILE_DENTRY], [
-+      AC_MSG_CHECKING([whether file_dentry() is available])
-+      ZFS_LINUX_TEST_RESULT([file_dentry], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_FILE_DENTRY, 1, [file_dentry() is available])
-       ],[
-diff --git a/config/kernel-file-inode.m4 b/config/kernel-file-inode.m4
-index 300188fa3..00a362165 100644
---- a/config/kernel-file-inode.m4
-+++ b/config/kernel-file-inode.m4
-@@ -3,14 +3,18 @@ dnl # 3.19 API change
- dnl # struct access f->f_dentry->d_inode was replaced by accessor function
- dnl # file_inode(f)
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_FILE_INODE], [
--      AC_MSG_CHECKING([whether file_inode() is available])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_FILE_INODE], [
-+      ZFS_LINUX_TEST_SRC([file_inode], [
-               #include <linux/fs.h>
-       ],[
-               struct file *f = NULL;
-               file_inode(f);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_FILE_INODE], [
-+      AC_MSG_CHECKING([whether file_inode() is available])
-+      ZFS_LINUX_TEST_RESULT([file_inode], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_FILE_INODE, 1, [file_inode() is available])
-       ],[
-diff --git a/config/kernel-fmode-t.m4 b/config/kernel-fmode-t.m4
-index 4a23c391d..bc0001b9e 100644
---- a/config/kernel-fmode-t.m4
-+++ b/config/kernel-fmode-t.m4
-@@ -2,16 +2,19 @@ dnl #
- dnl # 2.6.28 API change,
- dnl # check if fmode_t typedef is defined
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_TYPE_FMODE_T],
--      [AC_MSG_CHECKING([whether kernel defines fmode_t])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_FMODE_T], [
-+      ZFS_LINUX_TEST_SRC([type_fmode_t], [
-               #include <linux/types.h>
-       ],[
-               fmode_t *ptr __attribute__ ((unused));
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_FMODE_T], [
-+      AC_MSG_CHECKING([whether kernel defines fmode_t])
-+      ZFS_LINUX_TEST_RESULT([type_fmode_t], [
-               AC_MSG_RESULT([yes])
--              AC_DEFINE(HAVE_FMODE_T, 1,
--                        [kernel defines fmode_t])
-+              AC_DEFINE(HAVE_FMODE_T, 1, [kernel defines fmode_t])
-       ],[
-               AC_MSG_RESULT([no])
-       ])
-diff --git a/config/kernel-follow-down-one.m4 b/config/kernel-follow-down-one.m4
-index 63fa779d8..94e4aeb8d 100644
---- a/config/kernel-follow-down-one.m4
-+++ b/config/kernel-follow-down-one.m4
-@@ -3,14 +3,18 @@ dnl # 2.6.38 API change
- dnl # follow_down() renamed follow_down_one().  The original follow_down()
- dnl # symbol still exists but will traverse down all the layers.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_FOLLOW_DOWN_ONE], [
--      AC_MSG_CHECKING([whether follow_down_one() is available])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_FOLLOW_DOWN_ONE], [
-+      ZFS_LINUX_TEST_SRC([follow_down_one], [
-               #include <linux/namei.h>
-       ],[
-               struct path *p = NULL;
-               follow_down_one(p);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_FOLLOW_DOWN_ONE], [
-+      AC_MSG_CHECKING([whether follow_down_one() is available])
-+      ZFS_LINUX_TEST_RESULT([follow_down_one], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_FOLLOW_DOWN_ONE, 1,
-                   [follow_down_one() is available])
-diff --git a/config/kernel-fpu.m4 b/config/kernel-fpu.m4
-index 0e622e859..a2c47d65a 100644
---- a/config/kernel-fpu.m4
-+++ b/config/kernel-fpu.m4
-@@ -18,8 +18,11 @@ dnl #
- dnl # Pre-4.2:        Use kernel_fpu_{begin,end}()
- dnl #         HAVE_KERNEL_FPU & KERNEL_EXPORTS_X86_FPU
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_FPU], [
--      AC_MSG_CHECKING([which kernel_fpu header to use])
-+dnl # N.B. The header check is performed before all other checks since it
-+dnl # depends on HAVE_KERNEL_FPU_API_HEADER being set in confdefs.h.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_FPU_HEADER], [
-+      AC_MSG_CHECKING([whether fpu headers are available])
-       ZFS_LINUX_TRY_COMPILE([
-               #include <linux/module.h>
-               #include <asm/fpu/api.h>
-@@ -31,66 +34,88 @@ AC_DEFUN([ZFS_AC_KERNEL_FPU], [
-       ],[
-               AC_MSG_RESULT(i387.h & xcr.h)
-       ])
-+])
--      AC_MSG_CHECKING([which kernel_fpu function to use])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
--              #include <linux/module.h>
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_FPU], [
-+      ZFS_LINUX_TEST_SRC([kernel_fpu], [
-               #ifdef HAVE_KERNEL_FPU_API_HEADER
-               #include <asm/fpu/api.h>
-               #else
-               #include <asm/i387.h>
-               #include <asm/xcr.h>
-               #endif
--              MODULE_LICENSE("$ZFS_META_LICENSE");
--      ],[
-+      ], [
-               kernel_fpu_begin();
-               kernel_fpu_end();
--      ], [kernel_fpu_begin], [arch/x86/kernel/fpu/core.c], [
-+      ], [], [$ZFS_META_LICENSE])
-+
-+      ZFS_LINUX_TEST_SRC([__kernel_fpu], [
-+              #ifdef HAVE_KERNEL_FPU_API_HEADER
-+              #include <asm/fpu/api.h>
-+              #else
-+              #include <asm/i387.h>
-+              #include <asm/xcr.h>
-+              #endif
-+      ], [
-+              __kernel_fpu_begin();
-+              __kernel_fpu_end();
-+      ], [], [$ZFS_META_LICENSE])
-+
-+      ZFS_LINUX_TEST_SRC([fpu_initialized], [
-+              #include <linux/module.h>
-+              #include <linux/sched.h>
-+      ],[
-+              struct fpu *fpu = &current->thread.fpu;
-+              if (fpu->initialized) { return (0); };
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([tif_need_fpu_load], [
-+              #include <linux/module.h>
-+              #include <asm/thread_info.h>
-+
-+              #if !defined(TIF_NEED_FPU_LOAD)
-+              #error "TIF_NEED_FPU_LOAD undefined"
-+              #endif
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_FPU], [
-+      dnl #
-+      dnl # Legacy kernel
-+      dnl #
-+      AC_MSG_CHECKING([whether kernel fpu is available])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([kernel_fpu_license],
-+          [kernel_fpu_begin], [arch/x86/kernel/fpu/core.c], [
-               AC_MSG_RESULT(kernel_fpu_*)
-               AC_DEFINE(HAVE_KERNEL_FPU, 1,
-                   [kernel has kernel_fpu_* functions])
-               AC_DEFINE(KERNEL_EXPORTS_X86_FPU, 1,
-                   [kernel exports FPU functions])
-       ],[
--              ZFS_LINUX_TRY_COMPILE_SYMBOL([
--                      #include <linux/module.h>
--                      #ifdef HAVE_KERNEL_FPU_API_HEADER
--                      #include <asm/fpu/api.h>
--                      #else
--                      #include <asm/i387.h>
--                      #include <asm/xcr.h>
--                      #endif
--                      MODULE_LICENSE("$ZFS_META_LICENSE");
--              ],[
--                      __kernel_fpu_begin();
--                      __kernel_fpu_end();
--              ], [__kernel_fpu_begin], [arch/x86/kernel/fpu/core.c arch/x86/kernel/i387.c], [
-+              dnl #
-+              dnl # Linux 4.2 kernel
-+              dnl #
-+              ZFS_LINUX_TEST_RESULT_SYMBOL([__kernel_fpu_license],
-+                  [__kernel_fpu_begin],
-+                  [arch/x86/kernel/fpu/core.c arch/x86/kernel/i387.c], [
-                       AC_MSG_RESULT(__kernel_fpu_*)
-                       AC_DEFINE(HAVE_UNDERSCORE_KERNEL_FPU, 1,
-                           [kernel has __kernel_fpu_* functions])
-                       AC_DEFINE(KERNEL_EXPORTS_X86_FPU, 1,
-                           [kernel exports FPU functions])
-               ],[
--                      ZFS_LINUX_TRY_COMPILE([
--                              #include <linux/module.h>
--                              #include <linux/sched.h>
--                      ],[
--                              struct fpu *fpu = &current->thread.fpu;
--                              if (fpu->initialized) { return (0); };
--                      ],[
-+                      dnl #
-+                      dnl # Linux 5.0 kernel
-+                      dnl #
-+                      ZFS_LINUX_TEST_RESULT([fpu_initialized], [
-                               AC_MSG_RESULT(fpu.initialized)
-                               AC_DEFINE(HAVE_KERNEL_FPU_INITIALIZED, 1,
-                                   [kernel fpu.initialized exists])
-                       ],[
--                              ZFS_LINUX_TRY_COMPILE([
--                                      #include <linux/module.h>
--                                      #include <asm/thread_info.h>
--
--                                      #if !defined(TIF_NEED_FPU_LOAD)
--                                      #error "TIF_NEED_FPU_LOAD undefined"
--                                      #endif
--                              ],[
--                              ],[
-+                              dnl #
-+                              dnl # Linux 5.2 kernel
-+                              dnl #
-+                              ZFS_LINUX_TEST_RESULT([tif_need_fpu_load], [
-                                       AC_MSG_RESULT(TIF_NEED_FPU_LOAD)
-                                       AC_DEFINE(
-                                           HAVE_KERNEL_TIF_NEED_FPU_LOAD, 1,
-diff --git a/config/kernel-fst-mount.m4 b/config/kernel-fst-mount.m4
-index a8ac50bdd..cec1ed4d6 100644
---- a/config/kernel-fst-mount.m4
-+++ b/config/kernel-fst-mount.m4
-@@ -3,9 +3,8 @@ dnl # 2.6.38 API change
- dnl # The .get_sb callback has been replaced by a .mount callback
- dnl # in the file_system_type structure.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_FST_MOUNT], [
--        AC_MSG_CHECKING([whether fst->mount() exists])
--        ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_FST_MOUNT], [
-+        ZFS_LINUX_TEST_SRC([file_system_type_mount], [
-                 #include <linux/fs.h>
-                 static struct dentry *
-@@ -18,8 +17,12 @@ AC_DEFUN([ZFS_AC_KERNEL_FST_MOUNT], [
-                 static struct file_system_type fst __attribute__ ((unused)) = {
-                         .mount = mount,
-                 };
--        ],[
--        ],[
-+        ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_FST_MOUNT], [
-+        AC_MSG_CHECKING([whether fst->mount() exists])
-+        ZFS_LINUX_TEST_RESULT([file_system_type_mount], [
-                 AC_MSG_RESULT(yes)
-                 AC_DEFINE(HAVE_FST_MOUNT, 1, [fst->mount() exists])
-         ],[
-diff --git a/config/kernel-fsync.m4 b/config/kernel-fsync.m4
-index e1f2d68b9..0494e31ad 100644
---- a/config/kernel-fsync.m4
-+++ b/config/kernel-fsync.m4
-@@ -1,8 +1,8 @@
- dnl #
--dnl # Linux 2.6.x - 2.6.34 API
-+dnl # Check file_operations->fsync interface.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_FSYNC_WITH_DENTRY], [
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_FSYNC], [
-+      ZFS_LINUX_TEST_SRC([fsync_with_dentry], [
-               #include <linux/fs.h>
-               int test_fsync(struct file *f, struct dentry *dentry, int x)
-@@ -12,20 +12,9 @@ AC_DEFUN([ZFS_AC_KERNEL_FSYNC_WITH_DENTRY], [
-                   fops __attribute__ ((unused)) = {
-                       .fsync = test_fsync,
-               };
--      ],[
--      ],[
--              AC_MSG_RESULT([dentry])
--              AC_DEFINE(HAVE_FSYNC_WITH_DENTRY, 1,
--                      [fops->fsync() with dentry])
--      ],[
--      ])
--])
-+      ],[])
--dnl #
--dnl # Linux 2.6.35 - Linux 3.0 API
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_FSYNC_WITHOUT_DENTRY], [
--      ZFS_LINUX_TRY_COMPILE([
-+      ZFS_LINUX_TEST_SRC([fsync_without_dentry], [
-               #include <linux/fs.h>
-               int test_fsync(struct file *f, int x) { return 0; }
-@@ -34,20 +23,9 @@ AC_DEFUN([ZFS_AC_KERNEL_FSYNC_WITHOUT_DENTRY], [
-                   fops __attribute__ ((unused)) = {
-                       .fsync = test_fsync,
-               };
--      ],[
--      ],[
--              AC_MSG_RESULT([no dentry])
--              AC_DEFINE(HAVE_FSYNC_WITHOUT_DENTRY, 1,
--                      [fops->fsync() without dentry])
--      ],[
--      ])
--])
-+      ],[])
--dnl #
--dnl # Linux 3.1 - 3.x API
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_FSYNC_RANGE], [
--      ZFS_LINUX_TRY_COMPILE([
-+      ZFS_LINUX_TEST_SRC([fsync_range], [
-               #include <linux/fs.h>
-               int test_fsync(struct file *f, loff_t a, loff_t b, int c)
-@@ -57,18 +35,43 @@ AC_DEFUN([ZFS_AC_KERNEL_FSYNC_RANGE], [
-                   fops __attribute__ ((unused)) = {
-                       .fsync = test_fsync,
-               };
--      ],[
--      ],[
--              AC_MSG_RESULT([range])
--              AC_DEFINE(HAVE_FSYNC_RANGE, 1,
--                      [fops->fsync() with range])
--      ],[
--      ])
-+      ],[])
- ])
- AC_DEFUN([ZFS_AC_KERNEL_FSYNC], [
--      AC_MSG_CHECKING([whether fops->fsync() wants])
--      ZFS_AC_KERNEL_FSYNC_WITH_DENTRY
--      ZFS_AC_KERNEL_FSYNC_WITHOUT_DENTRY
--      ZFS_AC_KERNEL_FSYNC_RANGE
-+      dnl #
-+      dnl # Linux 2.6.x - 2.6.34 API
-+      dnl #
-+      AC_MSG_CHECKING([whether fops->fsync() wants dentry])
-+      ZFS_LINUX_TEST_RESULT([fsync_with_dentry], [
-+              AC_MSG_RESULT([yes])
-+              AC_DEFINE(HAVE_FSYNC_WITH_DENTRY, 1,
-+                  [fops->fsync() with dentry])
-+      ],[
-+              AC_MSG_RESULT([no])
-+
-+              dnl #
-+              dnl # Linux 2.6.35 - Linux 3.0 API
-+              dnl #
-+              AC_MSG_CHECKING([whether fops->fsync() wants no dentry])
-+              ZFS_LINUX_TEST_RESULT([fsync_without_dentry], [
-+                      AC_MSG_RESULT([yes])
-+                      AC_DEFINE(HAVE_FSYNC_WITHOUT_DENTRY, 1,
-+                          [fops->fsync() without dentry])
-+              ],[
-+                      AC_MSG_RESULT([no])
-+
-+                      dnl #
-+                      dnl # Linux 3.1 - 3.x API
-+                      dnl #
-+                      AC_MSG_CHECKING([whether fops->fsync() wants range])
-+                      ZFS_LINUX_TEST_RESULT([fsync_range], [
-+                              AC_MSG_RESULT([range])
-+                              AC_DEFINE(HAVE_FSYNC_RANGE, 1,
-+                                  [fops->fsync() with range])
-+                      ],[
-+                              ZFS_LINUX_TEST_ERROR([fops->fsync])
-+                      ])
-+              ])
-+      ])
- ])
-diff --git a/config/kernel-generic_io_acct.m4 b/config/kernel-generic_io_acct.m4
-index 0aa762162..423b3e5a3 100644
---- a/config/kernel-generic_io_acct.m4
-+++ b/config/kernel-generic_io_acct.m4
-@@ -1,12 +1,8 @@
- dnl #
--dnl # 3.19 API addition
-+dnl # Check for generic io accounting interface.
- dnl #
--dnl # torvalds/linux@394ffa503bc40e32d7f54a9b817264e81ce131b4 allows us to
--dnl # increment iostat counters without generic_make_request().
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_GENERIC_IO_ACCT_3ARG], [
--      AC_MSG_CHECKING([whether 3 arg generic IO accounting symbols are available])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_IO_ACCT], [
-+      ZFS_LINUX_TEST_SRC([generic_acct_3args], [
-               #include <linux/bio.h>
-               void (*generic_start_io_acct_f)(int, unsigned long,
-@@ -16,24 +12,9 @@ AC_DEFUN([ZFS_AC_KERNEL_GENERIC_IO_ACCT_3ARG], [
-       ], [
-               generic_start_io_acct(0, 0, NULL);
-               generic_end_io_acct(0, NULL, 0);
--      ], [generic_start_io_acct], [block/bio.c], [
--              AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_GENERIC_IO_ACCT_3ARG, 1,
--                  [generic_start_io_acct()/generic_end_io_acct() available])
--      ], [
--              AC_MSG_RESULT(no)
-       ])
--])
--dnl #
--dnl # Linux 4.14 API,
--dnl #
--dnl # generic_start_io_acct/generic_end_io_acct now require request_queue to be
--dnl # provided. No functional changes, but preparation for inflight accounting 
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_GENERIC_IO_ACCT_4ARG], [
--      AC_MSG_CHECKING([whether 4 arg generic IO accounting symbols are available])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
-+      ZFS_LINUX_TEST_SRC([generic_acct_4args], [
-               #include <linux/bio.h>
-               void (*generic_start_io_acct_f)(struct request_queue *, int,
-@@ -43,11 +24,41 @@ AC_DEFUN([ZFS_AC_KERNEL_GENERIC_IO_ACCT_4ARG], [
-       ], [
-               generic_start_io_acct(NULL, 0, 0, NULL);
-               generic_end_io_acct(NULL, 0, NULL, 0);
--      ], [generic_start_io_acct], [block/bio.c], [
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_GENERIC_IO_ACCT], [
-+      dnl #
-+      dnl # 3.19 API addition
-+      dnl #
-+      dnl # torvalds/linux@394ffa50 allows us to increment iostat
-+      dnl # counters without generic_make_request().
-+      dnl #
-+      AC_MSG_CHECKING([whether generic IO accounting wants 3 args])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([generic_acct_3args],
-+          [generic_start_io_acct], [block/bio.c], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_GENERIC_IO_ACCT_4ARG, 1,
--                  [generic_start_io_acct()/generic_end_io_acct() 4 arg available])
-+              AC_DEFINE(HAVE_GENERIC_IO_ACCT_3ARG, 1,
-+                  [generic_start_io_acct()/generic_end_io_acct() available])
-       ], [
-               AC_MSG_RESULT(no)
-+
-+              dnl #
-+              dnl # Linux 4.14 API,
-+              dnl #
-+              dnl # generic_start_io_acct/generic_end_io_acct now require
-+              dnl # request_queue to be provided. No functional changes,
-+              dnl # but preparation for inflight accounting.
-+              dnl #
-+              AC_MSG_CHECKING([whether generic IO accounting wants 4 args])
-+              ZFS_LINUX_TEST_RESULT_SYMBOL([generic_acct_4args],
-+                  [generic_start_io_acct], [block/bio.c], [
-+                      AC_MSG_RESULT(yes)
-+                      AC_DEFINE(HAVE_GENERIC_IO_ACCT_4ARG, 1,
-+                          [generic_start_io_acct()/generic_end_io_acct() ]
-+                          [4 arg available])
-+              ], [
-+                      AC_MSG_RESULT(no)
-+              ])
-       ])
- ])
-diff --git a/config/kernel-generic_readlink.m4 b/config/kernel-generic_readlink.m4
-index 914431de4..a7a33b408 100644
---- a/config/kernel-generic_readlink.m4
-+++ b/config/kernel-generic_readlink.m4
-@@ -4,18 +4,21 @@ dnl #
- dnl # NULL inode_operations.readlink implies generic_readlink(), which
- dnl # has been made static.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_GENERIC_READLINK_GLOBAL], [
--      AC_MSG_CHECKING([whether generic_readlink is global])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_READLINK_GLOBAL], [
-+      ZFS_LINUX_TEST_SRC([generic_readlink_global], [
-               #include <linux/fs.h>
-       ],[
-               int i __attribute__ ((unused));
--
-               i = generic_readlink(NULL, NULL, 0);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_GENERIC_READLINK_GLOBAL], [
-+      AC_MSG_CHECKING([whether generic_readlink is global])
-+      ZFS_LINUX_TEST_RESULT([generic_readlink_global], [
-               AC_MSG_RESULT([yes])
-               AC_DEFINE(HAVE_GENERIC_READLINK, 1,
--                        [generic_readlink is global])
-+                  [generic_readlink is global])
-       ],[
-               AC_MSG_RESULT([no])
-       ])
-diff --git a/config/kernel-get-disk-and-module.m4 b/config/kernel-get-disk-and-module.m4
-index 2a51a5af7..51cf7743c 100644
---- a/config/kernel-get-disk-and-module.m4
-+++ b/config/kernel-get-disk-and-module.m4
-@@ -2,14 +2,19 @@ dnl #
- dnl # 4.16 API change
- dnl # Verify if get_disk_and_module() symbol is available.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_GET_DISK_AND_MODULE],
--      [AC_MSG_CHECKING([whether get_disk_and_module() is available])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_GET_DISK_AND_MODULE], [
-+      ZFS_LINUX_TEST_SRC([get_disk_and_module], [
-               #include <linux/genhd.h>
-       ], [
-               struct gendisk *disk = NULL;
-               (void) get_disk_and_module(disk);
--      ], [get_disk_and_module], [block/genhd.c], [
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_GET_DISK_AND_MODULE], [
-+      AC_MSG_CHECKING([whether get_disk_and_module() is available])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([get_disk_and_module],
-+          [get_disk_and_module], [block/genhd.c], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_GET_DISK_AND_MODULE,
-                   1, [get_disk_and_module() is available])
-diff --git a/config/kernel-get-disk-ro.m4 b/config/kernel-get-disk-ro.m4
-index 13ed81217..1e2abb475 100644
---- a/config/kernel-get-disk-ro.m4
-+++ b/config/kernel-get-disk-ro.m4
-@@ -1,21 +1,21 @@
- dnl #
- dnl # 2.6.x API change
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_GET_DISK_RO], [
--      AC_MSG_CHECKING([whether get_disk_ro() is available])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_GET_DISK_RO], [
-+      ZFS_LINUX_TEST_SRC([get_disk_ro], [
-               #include <linux/blkdev.h>
-       ],[
-               struct gendisk *disk = NULL;
-               (void) get_disk_ro(disk);
--      ],[
-+      ], [$NO_UNUSED_BUT_SET_VARIABLE])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_GET_DISK_RO], [
-+      AC_MSG_CHECKING([whether get_disk_ro() is available])
-+      ZFS_LINUX_TEST_RESULT([get_disk_ro], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_GET_DISK_RO, 1,
--                        [blk_disk_ro() is available])
-+              AC_DEFINE(HAVE_GET_DISK_RO, 1, [blk_disk_ro() is available])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
- ])
-diff --git a/config/kernel-get-link.m4 b/config/kernel-get-link.m4
-index 3cda08c1b..e4f478e37 100644
---- a/config/kernel-get-link.m4
-+++ b/config/kernel-get-link.m4
-@@ -1,13 +1,29 @@
- dnl #
- dnl # Supported get_link() interfaces checked newest to oldest.
-+dnl # Note this interface used to be named follow_link.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_FOLLOW_LINK], [
--      dnl #
--      dnl # 4.2 API change
--      dnl # - This kernel retired the nameidata structure.
--      dnl #
--      AC_MSG_CHECKING([whether iops->follow_link() passes cookie])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_GET_LINK], [
-+      ZFS_LINUX_TEST_SRC([inode_operations_get_link], [
-+              #include <linux/fs.h>
-+              const char *get_link(struct dentry *de, struct inode *ip,
-+                  struct delayed_call *done) { return "symlink"; }
-+              static struct inode_operations
-+                   iops __attribute__ ((unused)) = {
-+                      .get_link = get_link,
-+              };
-+      ],[])
-+
-+      ZFS_LINUX_TEST_SRC([inode_operations_get_link_cookie], [
-+              #include <linux/fs.h>
-+              const char *get_link(struct dentry *de, struct
-+                  inode *ip, void **cookie) { return "symlink"; }
-+              static struct inode_operations
-+                   iops __attribute__ ((unused)) = {
-+                      .get_link = get_link,
-+              };
-+      ],[])
-+
-+      ZFS_LINUX_TEST_SRC([inode_operations_follow_link], [
-               #include <linux/fs.h>
-               const char *follow_link(struct dentry *de,
-                   void **cookie) { return "symlink"; }
-@@ -15,35 +31,17 @@ AC_DEFUN([ZFS_AC_KERNEL_FOLLOW_LINK], [
-                   iops __attribute__ ((unused)) = {
-                       .follow_link = follow_link,
-               };
--      ],[
--      ],[
--              AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_FOLLOW_LINK_COOKIE, 1,
--                  [iops->follow_link() cookie])
--      ],[
--              dnl #
--              dnl # 2.6.32 API
--              dnl #
--              AC_MSG_RESULT(no)
--              AC_MSG_CHECKING(
--                 [whether iops->follow_link() passes nameidata])
--              ZFS_LINUX_TRY_COMPILE([
-+      ],[])
-+
-+      ZFS_LINUX_TEST_SRC([inode_operations_follow_link_nameidata], [
-               #include <linux/fs.h>
--                      void *follow_link(struct dentry *de, struct
--                          nameidata *nd) { return (void *)NULL; }
--                      static struct inode_operations
--                          iops __attribute__ ((unused)) = {
--                              .follow_link = follow_link,
--                      };
--              ],[
--              ],[
--                      AC_MSG_RESULT(yes)
--                      AC_DEFINE(HAVE_FOLLOW_LINK_NAMEIDATA, 1,
--                                [iops->follow_link() nameidata])
--              ],[
--                      AC_MSG_ERROR(no; please file a bug report)
--              ])
--      ])
-+              void *follow_link(struct dentry *de, struct
-+                  nameidata *nd) { return (void *)NULL; }
-+              static struct inode_operations
-+                  iops __attribute__ ((unused)) = {
-+                      .follow_link = follow_link,
-+              };
-+      ],[])
- ])
- AC_DEFUN([ZFS_AC_KERNEL_GET_LINK], [
-@@ -53,20 +51,12 @@ AC_DEFUN([ZFS_AC_KERNEL_GET_LINK], [
-       dnl # used it to retire the put_link() interface.
-       dnl #
-       AC_MSG_CHECKING([whether iops->get_link() passes delayed])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/fs.h>
--              const char *get_link(struct dentry *de, struct inode *ip,
--                  struct delayed_call *done) { return "symlink"; }
--              static struct inode_operations
--                   iops __attribute__ ((unused)) = {
--                      .get_link = get_link,
--              };
--      ],[
--      ],[
-+      ZFS_LINUX_TEST_RESULT([inode_operations_get_link], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_GET_LINK_DELAYED, 1,
--                  [iops->get_link() delayed])
-+              AC_DEFINE(HAVE_GET_LINK_DELAYED, 1, [iops->get_link() delayed])
-       ],[
-+              AC_MSG_RESULT(no)
-+
-               dnl #
-               dnl # 4.5 API change
-               dnl # The follow_link() interface has been replaced by
-@@ -74,27 +64,41 @@ AC_DEFUN([ZFS_AC_KERNEL_GET_LINK], [
-               dnl # - An inode is passed as a separate argument
-               dnl # - When called in RCU mode a NULL dentry is passed.
-               dnl #
--              AC_MSG_RESULT(no)
-               AC_MSG_CHECKING([whether iops->get_link() passes cookie])
--              ZFS_LINUX_TRY_COMPILE([
--                      #include <linux/fs.h>
--                      const char *get_link(struct dentry *de, struct
--                          inode *ip, void **cookie) { return "symlink"; }
--                      static struct inode_operations
--                           iops __attribute__ ((unused)) = {
--                              .get_link = get_link,
--                      };
--              ],[
--              ],[
-+              ZFS_LINUX_TEST_RESULT([inode_operations_get_link_cookie], [
-                       AC_MSG_RESULT(yes)
-                       AC_DEFINE(HAVE_GET_LINK_COOKIE, 1,
-                           [iops->get_link() cookie])
-               ],[
-+                      AC_MSG_RESULT(no)
-+
-                       dnl #
--                      dnl # Check for the follow_link APIs.
-+                      dnl # 4.2 API change
-+                      dnl # This kernel retired the nameidata structure.
-                       dnl #
--                      AC_MSG_RESULT(no)
--                      ZFS_AC_KERNEL_FOLLOW_LINK
-+                      AC_MSG_CHECKING(
-+                          [whether iops->follow_link() passes cookie])
-+                      ZFS_LINUX_TEST_RESULT([inode_operations_follow_link], [
-+                              AC_MSG_RESULT(yes)
-+                              AC_DEFINE(HAVE_FOLLOW_LINK_COOKIE, 1,
-+                                  [iops->follow_link() cookie])
-+                      ],[
-+                              AC_MSG_RESULT(no)
-+
-+                              dnl #
-+                              dnl # 2.6.32 API
-+                              dnl #
-+                              AC_MSG_CHECKING(
-+                              [whether iops->follow_link() passes nameidata])
-+                              ZFS_LINUX_TEST_RESULT(
-+                                  [inode_operations_follow_link_nameidata],[
-+                                      AC_MSG_RESULT(yes)
-+                                      AC_DEFINE(HAVE_FOLLOW_LINK_NAMEIDATA, 1,
-+                                          [iops->follow_link() nameidata])
-+                              ],[
-+                                      ZFS_LINUX_TEST_ERROR([get_link])
-+                              ])
-+                      ])
-               ])
-       ])
- ])
-diff --git a/config/kernel-global_page_state.m4 b/config/kernel-global_page_state.m4
-index f4a40011f..a0cb9e2c8 100644
---- a/config/kernel-global_page_state.m4
-+++ b/config/kernel-global_page_state.m4
-@@ -4,16 +4,21 @@ dnl #
- dnl # 75ef71840539 mm, vmstat: add infrastructure for per-node vmstats
- dnl # 599d0c954f91 mm, vmscan: move LRU lists to node
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_NODE_PAGE_STATE], [
--      AC_MSG_CHECKING([whether global_node_page_state() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_GLOBAL_NODE_PAGE_STATE], [
-+      ZFS_LINUX_TEST_SRC([global_node_page_state], [
-               #include <linux/mm.h>
-               #include <linux/vmstat.h>
-       ],[
-               (void) global_node_page_state(0);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_NODE_PAGE_STATE], [
-+      AC_MSG_CHECKING([whether global_node_page_state() exists])
-+      ZFS_LINUX_TEST_RESULT([global_node_page_state], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(ZFS_GLOBAL_NODE_PAGE_STATE, 1, [global_node_page_state() exists])
-+              AC_DEFINE(ZFS_GLOBAL_NODE_PAGE_STATE, 1,
-+                  [global_node_page_state() exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-@@ -24,16 +29,21 @@ dnl # 4.14 API change
- dnl #
- dnl # c41f012ade0b mm: rename global_page_state to global_zone_page_state
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE], [
--      AC_MSG_CHECKING([whether global_zone_page_state() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_GLOBAL_ZONE_PAGE_STATE], [
-+      ZFS_LINUX_TEST_SRC([global_zone_page_state], [
-               #include <linux/mm.h>
-               #include <linux/vmstat.h>
-       ],[
-               (void) global_zone_page_state(0);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE], [
-+      AC_MSG_CHECKING([whether global_zone_page_state() exists])
-+      ZFS_LINUX_TEST_RESULT([global_zone_page_state], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(ZFS_GLOBAL_ZONE_PAGE_STATE, 1, [global_zone_page_state() exists])
-+              AC_DEFINE(ZFS_GLOBAL_ZONE_PAGE_STATE, 1,
-+                  [global_zone_page_state() exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-@@ -44,9 +54,11 @@ dnl # Create a define and autoconf variable for an enum member
- dnl #
- AC_DEFUN([ZFS_AC_KERNEL_ENUM_MEMBER], [
-       AC_MSG_CHECKING([whether enum $2 contains $1])
--      AS_IF([AC_TRY_COMMAND("${srcdir}/scripts/enum-extract.pl" "$2" "$3" | egrep -qx $1)],[
-+      AS_IF([AC_TRY_COMMAND(
-+          "${srcdir}/scripts/enum-extract.pl" "$2" "$3" | egrep -qx $1)],[
-               AC_MSG_RESULT([yes])
--              AC_DEFINE(m4_join([_], [ZFS_ENUM], m4_toupper($2), $1), 1, [enum $2 contains $1])
-+              AC_DEFINE(m4_join([_], [ZFS_ENUM], m4_toupper($2), $1), 1,
-+                  [enum $2 contains $1])
-               m4_join([_], [ZFS_ENUM], m4_toupper($2), $1)=1
-       ],[
-               AC_MSG_RESULT([no])
-@@ -59,8 +71,7 @@ dnl #
- AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_ERROR],[
-       AC_MSG_RESULT(no)
-       AC_MSG_RESULT([$1 in either node_stat_item or zone_stat_item: $2])
--      AC_MSG_RESULT([configure needs updating, see: config/kernel-global_page_state.m4])
--      AC_MSG_FAILURE([SHUT 'ER DOWN CLANCY, SHE'S PUMPIN' MUD!])
-+      ZFS_LINUX_TEST_ERROR([global page state])
- ])
- AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_CHECK], [
-@@ -75,10 +86,10 @@ AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_CHECK], [
- ])
- dnl #
--dnl # Ensure the config tests are finding one and only one of each enum of interest
-+dnl # Ensure the config tests are finding one and only one of each enum.
- dnl #
- AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE_SANITY], [
--      AC_MSG_CHECKING([global_page_state enums are sane])
-+      AC_MSG_CHECKING([whether global_page_state enums are sane])
-       ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_CHECK([NR_FILE_PAGES])
-       ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_CHECK([NR_INACTIVE_ANON])
-@@ -88,6 +99,11 @@ AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE_SANITY], [
-       AC_MSG_RESULT(yes)
- ])
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_GLOBAL_PAGE_STATE], [
-+      ZFS_AC_KERNEL_SRC_GLOBAL_NODE_PAGE_STATE
-+      ZFS_AC_KERNEL_SRC_GLOBAL_ZONE_PAGE_STATE
-+])
-+
- dnl #
- dnl # enum members in which we're interested
- dnl #
-@@ -95,15 +111,23 @@ AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_PAGE_STATE], [
-       ZFS_AC_KERNEL_GLOBAL_NODE_PAGE_STATE
-       ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE
--      ZFS_AC_KERNEL_ENUM_MEMBER([NR_FILE_PAGES],              [node_stat_item], [$LINUX/include/linux/mmzone.h])
--      ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_ANON],           [node_stat_item], [$LINUX/include/linux/mmzone.h])
--      ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_FILE],           [node_stat_item], [$LINUX/include/linux/mmzone.h])
--      ZFS_AC_KERNEL_ENUM_MEMBER([NR_SLAB_RECLAIMABLE],        [node_stat_item], [$LINUX/include/linux/mmzone.h])
-+      ZFS_AC_KERNEL_ENUM_MEMBER([NR_FILE_PAGES],
-+          [node_stat_item], [$LINUX/include/linux/mmzone.h])
-+      ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_ANON],
-+          [node_stat_item], [$LINUX/include/linux/mmzone.h])
-+      ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_FILE],
-+          [node_stat_item], [$LINUX/include/linux/mmzone.h])
-+      ZFS_AC_KERNEL_ENUM_MEMBER([NR_SLAB_RECLAIMABLE],
-+          [node_stat_item], [$LINUX/include/linux/mmzone.h])
--      ZFS_AC_KERNEL_ENUM_MEMBER([NR_FILE_PAGES],              [zone_stat_item], [$LINUX/include/linux/mmzone.h])
--      ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_ANON],           [zone_stat_item], [$LINUX/include/linux/mmzone.h])
--      ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_FILE],           [zone_stat_item], [$LINUX/include/linux/mmzone.h])
--      ZFS_AC_KERNEL_ENUM_MEMBER([NR_SLAB_RECLAIMABLE],        [zone_stat_item], [$LINUX/include/linux/mmzone.h])
-+      ZFS_AC_KERNEL_ENUM_MEMBER([NR_FILE_PAGES],
-+          [zone_stat_item], [$LINUX/include/linux/mmzone.h])
-+      ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_ANON],
-+          [zone_stat_item], [$LINUX/include/linux/mmzone.h])
-+      ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_FILE],
-+          [zone_stat_item], [$LINUX/include/linux/mmzone.h])
-+      ZFS_AC_KERNEL_ENUM_MEMBER([NR_SLAB_RECLAIMABLE],
-+          [zone_stat_item], [$LINUX/include/linux/mmzone.h])
-       ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE_SANITY
- ])
-diff --git a/config/kernel-group-info.m4 b/config/kernel-group-info.m4
-index 849a1e246..0fee1d36d 100644
---- a/config/kernel-group-info.m4
-+++ b/config/kernel-group-info.m4
-@@ -2,20 +2,21 @@ dnl #
- dnl # 4.9 API change
- dnl # group_info changed from 2d array via >blocks to 1d array via ->gid
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_GROUP_INFO_GID], [
--      AC_MSG_CHECKING([whether group_info->gid exists])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="-Werror"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_GROUP_INFO_GID], [
-+      ZFS_LINUX_TEST_SRC([group_info_gid], [
-               #include <linux/cred.h>
-       ],[
-               struct group_info *gi = groups_alloc(1);
-               gi->gid[0] = KGIDT_INIT(0);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_GROUP_INFO_GID], [
-+      AC_MSG_CHECKING([whether group_info->gid exists])
-+      ZFS_LINUX_TEST_RESULT([group_info_gid], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_GROUP_INFO_GID, 1, [group_info->gid exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
- ])
-diff --git a/config/kernel-in-compat-syscall.m4 b/config/kernel-in-compat-syscall.m4
-index 9fca9da20..baaac8c4f 100644
---- a/config/kernel-in-compat-syscall.m4
-+++ b/config/kernel-in-compat-syscall.m4
-@@ -4,13 +4,17 @@ dnl # Added in_compat_syscall() which can be overridden on a per-
- dnl # architecture basis.  Prior to this is_compat_task() was the
- dnl # provided interface.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_IN_COMPAT_SYSCALL], [
--      AC_MSG_CHECKING([whether in_compat_syscall() is available])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_IN_COMPAT_SYSCALL], [
-+      ZFS_LINUX_TEST_SRC([in_compat_syscall], [
-               #include <linux/compat.h>
-       ],[
-               in_compat_syscall();
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_IN_COMPAT_SYSCALL], [
-+      AC_MSG_CHECKING([whether in_compat_syscall() is available])
-+      ZFS_LINUX_TEST_RESULT([in_compat_syscall], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_IN_COMPAT_SYSCALL, 1,
-                   [in_compat_syscall() is available])
-diff --git a/config/kernel-inode-getattr.m4 b/config/kernel-inode-getattr.m4
-index f10e0b251..48391d66f 100644
---- a/config/kernel-inode-getattr.m4
-+++ b/config/kernel-inode-getattr.m4
-@@ -2,9 +2,8 @@ dnl #
- dnl # Linux 4.11 API
- dnl # See torvalds/linux@a528d35
- dnl #
--AC_DEFUN([ZFS_AC_PATH_KERNEL_IOPS_GETATTR], [
--      AC_MSG_CHECKING([whether iops->getattr() takes a path])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GETATTR], [
-+      ZFS_LINUX_TEST_SRC([inode_operations_getattr_path], [
-               #include <linux/fs.h>
-               int test_getattr(
-@@ -16,24 +15,9 @@ AC_DEFUN([ZFS_AC_PATH_KERNEL_IOPS_GETATTR], [
-                   iops __attribute__ ((unused)) = {
-                       .getattr = test_getattr,
-               };
--      ],[
--      ],[
--              AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_PATH_IOPS_GETATTR, 1,
--                  [iops->getattr() takes a path])
--      ],[
--              AC_MSG_RESULT(no)
--      ])
--])
--
-+      ],[])
--
--dnl #
--dnl # Linux 3.9 - 4.10 API
--dnl #
--AC_DEFUN([ZFS_AC_VFSMOUNT_KERNEL_IOPS_GETATTR], [
--      AC_MSG_CHECKING([whether iops->getattr() takes a vfsmount])
--      ZFS_LINUX_TRY_COMPILE([
-+      ZFS_LINUX_TEST_SRC([inode_operations_getattr_vfsmount], [
-               #include <linux/fs.h>
-               int test_getattr(
-@@ -45,23 +29,25 @@ AC_DEFUN([ZFS_AC_VFSMOUNT_KERNEL_IOPS_GETATTR], [
-                   iops __attribute__ ((unused)) = {
-                       .getattr = test_getattr,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_INODE_GETATTR], [
-+      AC_MSG_CHECKING([whether iops->getattr() takes a path])
-+      ZFS_LINUX_TEST_RESULT([inode_operations_getattr_path], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_VFSMOUNT_IOPS_GETATTR, 1,
--                  [iops->getattr() takes a vfsmount])
-+              AC_DEFINE(HAVE_PATH_IOPS_GETATTR, 1,
-+                  [iops->getattr() takes a path])
-       ],[
-               AC_MSG_RESULT(no)
--      ])
--])
--
--dnl #
--dnl # The interface of the getattr callback from the inode_operations
--dnl # structure changed.  Also, the interface of the simple_getattr()
--dnl # function provided by the kernel changed.
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GETATTR], [
--      ZFS_AC_PATH_KERNEL_IOPS_GETATTR
--      ZFS_AC_VFSMOUNT_KERNEL_IOPS_GETATTR
-+              AC_MSG_CHECKING([whether iops->getattr() takes a vfsmount])
-+              ZFS_LINUX_TEST_RESULT([inode_operations_getattr_vfsmount], [
-+                      AC_MSG_RESULT(yes)
-+                      AC_DEFINE(HAVE_VFSMOUNT_IOPS_GETATTR, 1,
-+                          [iops->getattr() takes a vfsmount])
-+              ],[
-+                      AC_MSG_RESULT(no)
-+              ])
-+      ])
- ])
-diff --git a/config/kernel-inode-lock.m4 b/config/kernel-inode-lock.m4
-index 8dee01422..5eb04af78 100644
---- a/config/kernel-inode-lock.m4
-+++ b/config/kernel-inode-lock.m4
-@@ -4,20 +4,21 @@ dnl # i_mutex is changed to i_rwsem. Instead of directly using
- dnl # i_mutex/i_rwsem, we should use inode_lock() and inode_lock_shared()
- dnl # We test inode_lock_shared because inode_lock is introduced earlier.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_INODE_LOCK], [
--      AC_MSG_CHECKING([whether inode_lock_shared() exists])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="-Werror"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_LOCK], [
-+      ZFS_LINUX_TEST_SRC([inode_lock], [
-               #include <linux/fs.h>
-       ],[
-               struct inode *inode = NULL;
-               inode_lock_shared(inode);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_INODE_LOCK], [
-+      AC_MSG_CHECKING([whether inode_lock_shared() exists])
-+      ZFS_LINUX_TEST_RESULT([inode_lock], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_INODE_LOCK_SHARED, 1, [yes])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
- ])
-diff --git a/config/kernel-inode-set-flags.m4 b/config/kernel-inode-set-flags.m4
-index e0ad26796..133f666a9 100644
---- a/config/kernel-inode-set-flags.m4
-+++ b/config/kernel-inode-set-flags.m4
-@@ -2,14 +2,18 @@ dnl #
- dnl # 3.15 API change
- dnl # inode_set_flags introduced to set i_flags
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_INODE_SET_FLAGS], [
--      AC_MSG_CHECKING([whether inode_set_flags() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_SET_FLAGS], [
-+      ZFS_LINUX_TEST_SRC([inode_set_flags], [
-               #include <linux/fs.h>
-       ],[
-               struct inode inode;
-               inode_set_flags(&inode, S_IMMUTABLE, S_IMMUTABLE);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_INODE_SET_FLAGS], [
-+      AC_MSG_CHECKING([whether inode_set_flags() exists])
-+      ZFS_LINUX_TEST_RESULT([inode_set_flags], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_INODE_SET_FLAGS, 1, [inode_set_flags() exists])
-       ],[
-diff --git a/config/kernel-inode-set-iversion.m4 b/config/kernel-inode-set-iversion.m4
-index 9a7d7890e..dd415de32 100644
---- a/config/kernel-inode-set-iversion.m4
-+++ b/config/kernel-inode-set-iversion.m4
-@@ -2,14 +2,18 @@ dnl #
- dnl # 4.16 API change
- dnl # inode_set_iversion introduced to set i_version
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_INODE_SET_IVERSION], [
--      AC_MSG_CHECKING([whether inode_set_iversion() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_SET_IVERSION], [
-+      ZFS_LINUX_TEST_SRC([inode_set_iversion], [
-               #include <linux/iversion.h>
-       ],[
-               struct inode inode;
-               inode_set_iversion(&inode, 1);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_INODE_SET_IVERSION], [
-+      AC_MSG_CHECKING([whether inode_set_iversion() exists])
-+      ZFS_LINUX_TEST_RESULT([inode_set_iversion], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_INODE_SET_IVERSION, 1,
-                   [inode_set_iversion() exists])
-diff --git a/config/kernel-inode-times.m4 b/config/kernel-inode-times.m4
-index f5818411a..57e7f31fd 100644
---- a/config/kernel-inode-times.m4
-+++ b/config/kernel-inode-times.m4
-@@ -2,11 +2,8 @@ dnl #
- dnl # 4.18 API change
- dnl # i_atime, i_mtime, and i_ctime changed from timespec to timespec64.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_INODE_TIMES], [
--      AC_MSG_CHECKING([whether inode->i_*time's are timespec64])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="-Werror"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_TIMES], [
-+      ZFS_LINUX_TEST_SRC([inode_times], [
-               #include <linux/fs.h>
-       ],[
-               struct inode ip;
-@@ -14,12 +11,16 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_TIMES], [
-               memset(&ip, 0, sizeof(ip));
-               ts = ip.i_mtime;
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_INODE_TIMES], [
-+      AC_MSG_CHECKING([whether inode->i_*time's are timespec64])
-+      ZFS_LINUX_TEST_RESULT([inode_times], [
-               AC_MSG_RESULT(no)
-       ],[
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_INODE_TIMESPEC64_TIMES, 1,
-                   [inode->i_*time's are timespec64])
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
- ])
-diff --git a/config/kernel-insert-inode-locked.m4 b/config/kernel-insert-inode-locked.m4
-index da141d180..4990399c3 100644
---- a/config/kernel-insert-inode-locked.m4
-+++ b/config/kernel-insert-inode-locked.m4
-@@ -2,16 +2,21 @@ dnl #
- dnl # 2.6.28 API change
- dnl # Added insert_inode_locked() helper function.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_INSERT_INODE_LOCKED],
--      [AC_MSG_CHECKING([whether insert_inode_locked() is available])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_INSERT_INODE_LOCKED], [
-+      ZFS_LINUX_TEST_SRC([insert_inode_locked], [
-               #include <linux/fs.h>
-       ], [
-               insert_inode_locked(NULL);
--      ], [insert_inode_locked], [fs/inode.c], [
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_INSERT_INODE_LOCKED], [
-+      AC_MSG_CHECKING([whether insert_inode_locked() is available])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([insert_inode_locked],
-+          [insert_inode_locked], [fs/inode.c], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_INSERT_INODE_LOCKED, 1,
--                        [insert_inode_locked() is available])
-+                  [insert_inode_locked() is available])
-       ], [
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-invalidate-bdev-args.m4 b/config/kernel-invalidate-bdev-args.m4
-index 09c2ebf26..55a784dd9 100644
---- a/config/kernel-invalidate-bdev-args.m4
-+++ b/config/kernel-invalidate-bdev-args.m4
-@@ -2,17 +2,21 @@ dnl #
- dnl # 2.6.22 API change
- dnl # Unused destroy_dirty_buffers arg removed from prototype.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_INVALIDATE_BDEV_ARGS], [
--      AC_MSG_CHECKING([whether invalidate_bdev() wants 1 arg])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_INVALIDATE_BDEV], [
-+      ZFS_LINUX_TEST_SRC([invalidate_bdev], [
-               #include <linux/buffer_head.h>
-       ],[
-               struct block_device *bdev = NULL;
-               invalidate_bdev(bdev);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_INVALIDATE_BDEV], [
-+      AC_MSG_CHECKING([whether invalidate_bdev() wants 1 arg])
-+      ZFS_LINUX_TEST_RESULT([invalidate_bdev], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_1ARG_INVALIDATE_BDEV, 1,
--                        [invalidate_bdev() wants 1 arg])
-+                  [invalidate_bdev() wants 1 arg])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-is_owner_or_cap.m4 b/config/kernel-is_owner_or_cap.m4
-index da07e58dd..ab8072409 100644
---- a/config/kernel-is_owner_or_cap.m4
-+++ b/config/kernel-is_owner_or_cap.m4
-@@ -4,33 +4,40 @@ dnl # The is_owner_or_cap() macro was renamed to inode_owner_or_capable(),
- dnl # This is used for permission checks in the xattr and file attribute call
- dnl # paths.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE], [
--      AC_MSG_CHECKING([whether inode_owner_or_capable() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OWNER_OR_CAPABLE], [
-+      ZFS_LINUX_TEST_SRC([inode_owner_or_capable], [
-               #include <linux/fs.h>
-       ],[
-               struct inode *ip = NULL;
-               (void) inode_owner_or_capable(ip);
-+      ])
-+
-+
-+      ZFS_LINUX_TEST_SRC([is_owner_or_cap], [
-+              #include <linux/fs.h>
-+              #include <linux/sched.h>
-       ],[
-+              struct inode *ip = NULL;
-+              (void) is_owner_or_cap(ip);
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE], [
-+      AC_MSG_CHECKING([whether inode_owner_or_capable() exists])
-+      ZFS_LINUX_TEST_RESULT([inode_owner_or_capable], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_INODE_OWNER_OR_CAPABLE, 1,
-                   [inode_owner_or_capable() exists])
-       ],[
-               AC_MSG_RESULT(no)
-               AC_MSG_CHECKING([whether is_owner_or_cap() exists])
--              ZFS_LINUX_TRY_COMPILE([
--                      #include <linux/fs.h>
--                      #include <linux/sched.h>
--              ],[
--                      struct inode *ip = NULL;
--                      (void) is_owner_or_cap(ip);
--              ],[
-+
-+              ZFS_LINUX_TEST_RESULT([is_owner_or_cap], [
-                       AC_MSG_RESULT(yes)
-                       AC_DEFINE(HAVE_IS_OWNER_OR_CAP, 1,
-                           [is_owner_or_cap() exists])
-               ],[
--                      AC_MSG_ERROR(no - Please file a bug report at
--                          https://github.com/zfsonlinux/zfs/issues/new)
-+                      ZFS_LINUX_TEST_ERROR([capability])
-               ])
-       ])
- ])
-diff --git a/config/kernel-kmap-atomic-args.m4 b/config/kernel-kmap-atomic-args.m4
-index beb1692e7..d09e93d7f 100644
---- a/config/kernel-kmap-atomic-args.m4
-+++ b/config/kernel-kmap-atomic-args.m4
-@@ -3,17 +3,21 @@ dnl # 2.6.37 API change
- dnl # kmap_atomic changed from assigning hard-coded named slot to using
- dnl # push/pop based dynamical allocation.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_KMAP_ATOMIC_ARGS], [
--      AC_MSG_CHECKING([whether kmap_atomic wants 1 args])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_KMAP_ATOMIC_ARGS], [
-+      ZFS_LINUX_TEST_SRC([kmap_atomic], [
-               #include <linux/pagemap.h>
-       ],[
-               struct page page;
-               kmap_atomic(&page);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_KMAP_ATOMIC_ARGS], [
-+      AC_MSG_CHECKING([whether kmap_atomic wants 1 args])
-+      ZFS_LINUX_TEST_RESULT([kmap_atomic], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_1ARG_KMAP_ATOMIC, 1,
--                        [kmap_atomic wants 1 args])
-+                  [kmap_atomic wants 1 args])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-kmem-cache.m4 b/config/kernel-kmem-cache.m4
-index 21cc53d34..7576e6cfd 100644
---- a/config/kernel-kmem-cache.m4
-+++ b/config/kernel-kmem-cache.m4
-@@ -5,30 +5,36 @@ dnl # private allocation flags which are applied when allocating a new slab
- dnl # in kmem_getpages().  Unfortunately there is no public API for setting
- dnl # non-default flags.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_KMEM_CACHE_ALLOCFLAGS], [
--      AC_MSG_CHECKING([whether struct kmem_cache has allocflags])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_KMEM_CACHE_ALLOCFLAGS], [
-+      ZFS_LINUX_TEST_SRC([kmem_cache_allocflags], [
-               #include <linux/slab.h>
-       ],[
-               struct kmem_cache cachep __attribute__ ((unused));
-               cachep.allocflags = GFP_KERNEL;
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([kmem_cache_gfpflags], [
-+              #include <linux/slab.h>
-       ],[
-+              struct kmem_cache cachep __attribute__ ((unused));
-+              cachep.gfpflags = GFP_KERNEL;
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_KMEM_CACHE_ALLOCFLAGS], [
-+      AC_MSG_CHECKING([whether struct kmem_cache has allocflags])
-+      ZFS_LINUX_TEST_RESULT([kmem_cache_allocflags], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_KMEM_CACHE_ALLOCFLAGS, 1,
--                      [struct kmem_cache has allocflags])
-+                  [struct kmem_cache has allocflags])
-       ],[
-               AC_MSG_RESULT(no)
-               AC_MSG_CHECKING([whether struct kmem_cache has gfpflags])
--              ZFS_LINUX_TRY_COMPILE([
--                      #include <linux/slab.h>
--              ],[
--                      struct kmem_cache cachep __attribute__ ((unused));
--                      cachep.gfpflags = GFP_KERNEL;
--              ],[
-+              ZFS_LINUX_TEST_RESULT([kmem_cache_gfpflags], [
-                       AC_MSG_RESULT(yes)
-                       AC_DEFINE(HAVE_KMEM_CACHE_GFPFLAGS, 1,
--                              [struct kmem_cache has gfpflags])
-+                          [struct kmem_cache has gfpflags])
-               ],[
-                       AC_MSG_RESULT(no)
-               ])
-@@ -40,16 +46,10 @@ dnl # grsecurity API change,
- dnl # kmem_cache_create() with SLAB_USERCOPY flag replaced by
- dnl # kmem_cache_create_usercopy().
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_KMEM_CACHE_CREATE_USERCOPY], [
--      AC_MSG_CHECKING([whether kmem_cache_create_usercopy() exists])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="-Werror"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_KMEM_CACHE_CREATE_USERCOPY], [
-+      ZFS_LINUX_TEST_SRC([kmem_cache_create_usercopy], [
-               #include <linux/slab.h>
--              static void ctor(void *foo)
--              {
--                      // fake ctor
--              }
-+              static void ctor(void *foo) { /* fake ctor */ }
-       ],[
-               struct kmem_cache *skc_linux_cache;
-               const char *name = "test";
-@@ -60,13 +60,27 @@ AC_DEFUN([ZFS_AC_KERNEL_KMEM_CACHE_CREATE_USERCOPY], [
-               size_t usersize = size - useroffset;
-               skc_linux_cache = kmem_cache_create_usercopy(
--                      name, size, align, flags, useroffset, usersize, ctor);
--      ],[
-+                  name, size, align, flags, useroffset, usersize, ctor);
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_KMEM_CACHE_CREATE_USERCOPY], [
-+      AC_MSG_CHECKING([whether kmem_cache_create_usercopy() exists])
-+      ZFS_LINUX_TEST_RESULT([kmem_cache_create_usercopy], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_KMEM_CACHE_CREATE_USERCOPY, 1,
--                              [kmem_cache_create_usercopy() exists])
-+                  [kmem_cache_create_usercopy() exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_KMEM_CACHE], [
-+      ZFS_AC_KERNEL_SRC_KMEM_CACHE_ALLOCFLAGS
-+      ZFS_AC_KERNEL_SRC_KMEM_CACHE_CREATE_USERCOPY
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_KMEM_CACHE], [
-+      ZFS_AC_KERNEL_KMEM_CACHE_ALLOCFLAGS
-+      ZFS_AC_KERNEL_KMEM_CACHE_CREATE_USERCOPY
- ])
-diff --git a/config/kernel-kstrtoul.m4 b/config/kernel-kstrtoul.m4
-index 5530e0e2d..ef3c9843c 100644
---- a/config/kernel-kstrtoul.m4
-+++ b/config/kernel-kstrtoul.m4
-@@ -1,18 +1,20 @@
- dnl #
- dnl # 2.6.39 API change
- dnl #
--dnl # 33ee3b2e2eb9 kstrto*: converting strings to integers done (hopefully) right
--dnl #
- dnl # If kstrtoul() doesn't exist, fallback to use strict_strtoul() which has
- dnl # existed since 2.6.25.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_KSTRTOUL], [
--      AC_MSG_CHECKING([whether kstrtoul() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_KSTRTOUL], [
-+      ZFS_LINUX_TEST_SRC([kstrtoul], [
-               #include <linux/kernel.h>
-       ],[
-               int ret __attribute__ ((unused)) = kstrtoul(NULL, 10, NULL);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_KSTRTOUL], [
-+      AC_MSG_CHECKING([whether kstrtoul() exists])
-+      ZFS_LINUX_TEST_RESULT([kstrtoul], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_KSTRTOUL, 1, [kstrtoul() exists])
-       ],[
-diff --git a/config/kernel-ktime_get_coarse_real_ts64.m4 b/config/kernel-ktime_get_coarse_real_ts64.m4
-index d6be8c418..28492bf04 100644
---- a/config/kernel-ktime_get_coarse_real_ts64.m4
-+++ b/config/kernel-ktime_get_coarse_real_ts64.m4
-@@ -2,16 +2,21 @@ dnl #
- dnl # 4.18: ktime_get_coarse_real_ts64() added.  Use it in place of
- dnl # current_kernel_time64().
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_KTIME_GET_COARSE_REAL_TS64],
--      [AC_MSG_CHECKING([whether ktime_get_coarse_real_ts64() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_KTIME_GET_COARSE_REAL_TS64], [
-+      ZFS_LINUX_TEST_SRC([ktime_get_coarse_real_ts64], [
-               #include <linux/mm.h>
-       ], [
-               struct timespec64 ts;
-               ktime_get_coarse_real_ts64(&ts);
--      ], [
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_KTIME_GET_COARSE_REAL_TS64], [
-+      AC_MSG_CHECKING([whether ktime_get_coarse_real_ts64() exists])
-+      ZFS_LINUX_TEST_RESULT([ktime_get_coarse_real_ts64], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_KTIME_GET_COARSE_REAL_TS64, 1, [ktime_get_coarse_real_ts64() exists])
-+              AC_DEFINE(HAVE_KTIME_GET_COARSE_REAL_TS64, 1,
-+                  [ktime_get_coarse_real_ts64() exists])
-       ], [
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-kuid-helpers.m4 b/config/kernel-kuid-helpers.m4
-index 60713b9d3..4bc4e039d 100644
---- a/config/kernel-kuid-helpers.m4
-+++ b/config/kernel-kuid-helpers.m4
-@@ -5,14 +5,18 @@ dnl # became necessary to go through one more level of indirection
- dnl # when dealing with uid/gid - namely the kuid type.
- dnl #
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_KUID_HELPERS], [
--      AC_MSG_CHECKING([whether i_(uid|gid)_(read|write) exist])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_KUID_HELPERS], [
-+      ZFS_LINUX_TEST_SRC([i_uid_read], [
-               #include <linux/fs.h>
-       ],[
-               struct inode *ip = NULL;
-               (void) i_uid_read(ip);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_KUID_HELPERS], [
-+      AC_MSG_CHECKING([whether i_(uid|gid)_(read|write) exist])
-+      ZFS_LINUX_TEST_RESULT([i_uid_read], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_KUID_HELPERS, 1,
-                   [i_(uid|gid)_(read|write) exist])
-diff --git a/config/kernel-kuidgid.m4 b/config/kernel-kuidgid.m4
-index 82685d263..15bf98154 100644
---- a/config/kernel-kuidgid.m4
-+++ b/config/kernel-kuidgid.m4
-@@ -3,20 +3,26 @@ dnl # User namespaces, use kuid_t in place of uid_t
- dnl # where available. Not strictly a user namespaces thing
- dnl # but it should prevent surprises
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_KUIDGID_T], [
--      AC_MSG_CHECKING([whether kuid_t/kgid_t is available])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_KUIDGID_T], [
-+      ZFS_LINUX_TEST_SRC([kuidgid_t_init], [
-               #include <linux/uidgid.h>
-       ], [
-               kuid_t userid __attribute__ ((unused)) = KUIDT_INIT(0);
-               kgid_t groupid __attribute__ ((unused)) = KGIDT_INIT(0);
--      ],[
--              ZFS_LINUX_TRY_COMPILE([
--                      #include <linux/uidgid.h>
--              ], [
--                      kuid_t userid __attribute__ ((unused)) = 0;
--                      kgid_t groupid __attribute__ ((unused)) = 0;
--              ],[
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([kuidgid_t], [
-+              #include <linux/uidgid.h>
-+      ], [
-+              kuid_t userid __attribute__ ((unused)) = 0;
-+              kgid_t groupid __attribute__ ((unused)) = 0;
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_KUIDGID_T], [
-+      AC_MSG_CHECKING([whether kuid_t/kgid_t is available])
-+      ZFS_LINUX_TEST_RESULT([kuidgid_t_init], [
-+              ZFS_LINUX_TEST_RESULT([kuidgid_t], [
-                       AC_MSG_RESULT(yes; optional)
-               ],[
-                       AC_MSG_RESULT(yes; mandatory)
-diff --git a/config/kernel-lookup-bdev.m4 b/config/kernel-lookup-bdev.m4
-index abbf55d9b..72b4993e1 100644
---- a/config/kernel-lookup-bdev.m4
-+++ b/config/kernel-lookup-bdev.m4
-@@ -2,23 +2,33 @@ dnl #
- dnl # 2.6.27, lookup_bdev() was exported.
- dnl # 4.4.0-6.21 - x.y on Ubuntu, lookup_bdev() takes 2 arguments.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_LOOKUP_BDEV],
--      [AC_MSG_CHECKING([whether lookup_bdev() wants 1 arg])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_LOOKUP_BDEV], [
-+      ZFS_LINUX_TEST_SRC([lookup_bdev_1arg], [
-               #include <linux/fs.h>
-       ], [
-               lookup_bdev(NULL);
--      ], [lookup_bdev], [fs/block_dev.c], [
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([lookup_bdev_2args], [
-+              #include <linux/fs.h>
-+      ], [
-+              lookup_bdev(NULL, FMODE_READ);
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_LOOKUP_BDEV], [
-+      AC_MSG_CHECKING([whether lookup_bdev() wants 1 arg])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([lookup_bdev_1arg],
-+          [lookup_bdev], [fs/block_dev.c], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_1ARG_LOOKUP_BDEV, 1, [lookup_bdev() wants 1 arg])
-+              AC_DEFINE(HAVE_1ARG_LOOKUP_BDEV, 1,
-+                  [lookup_bdev() wants 1 arg])
-       ], [
-               AC_MSG_RESULT(no)
-+
-               AC_MSG_CHECKING([whether lookup_bdev() wants 2 args])
--              ZFS_LINUX_TRY_COMPILE_SYMBOL([
--                      #include <linux/fs.h>
--              ], [
--                      lookup_bdev(NULL, FMODE_READ);
--              ], [lookup_bdev], [fs/block_dev.c], [
-+              ZFS_LINUX_TEST_RESULT_SYMBOL([lookup_bdev_2args],
-+                  [lookup_bdev], [fs/block_dev.c], [
-                       AC_MSG_RESULT(yes)
-                       AC_DEFINE(HAVE_2ARGS_LOOKUP_BDEV, 1,
-                           [lookup_bdev() wants 2 args])
-@@ -26,4 +36,4 @@ AC_DEFUN([ZFS_AC_KERNEL_LOOKUP_BDEV],
-                       AC_MSG_RESULT(no)
-               ])
-       ])
--])
-\ No newline at end of file
-+])
-diff --git a/config/kernel-lookup-nameidata.m4 b/config/kernel-lookup-nameidata.m4
-index 5453be5e8..865b8aff8 100644
---- a/config/kernel-lookup-nameidata.m4
-+++ b/config/kernel-lookup-nameidata.m4
-@@ -1,9 +1,8 @@
- dnl #
- dnl # 3.6 API change
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_LOOKUP_NAMEIDATA], [
--      AC_MSG_CHECKING([whether iops->lookup() passes nameidata])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_LOOKUP_NAMEIDATA], [
-+      ZFS_LINUX_TEST_SRC([lookup_nameidata], [
-               #include <linux/fs.h>
-               #include <linux/sched.h>
-@@ -15,11 +14,15 @@ AC_DEFUN([ZFS_AC_KERNEL_LOOKUP_NAMEIDATA], [
-                   __attribute__ ((unused)) = {
-                       .lookup = inode_lookup,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_LOOKUP_NAMEIDATA], [
-+      AC_MSG_CHECKING([whether iops->lookup() passes nameidata])
-+      ZFS_LINUX_TEST_RESULT([lookup_nameidata], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_LOOKUP_NAMEIDATA, 1,
--                        [iops->lookup() passes nameidata])
-+                  [iops->lookup() passes nameidata])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-lseek-execute.m4 b/config/kernel-lseek-execute.m4
-index 8c4032b92..652f611f8 100644
---- a/config/kernel-lseek-execute.m4
-+++ b/config/kernel-lseek-execute.m4
-@@ -2,9 +2,8 @@ dnl #
- dnl # 3.11 API change
- dnl # lseek_execute helper exported
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_LSEEK_EXECUTE],
--      [AC_MSG_CHECKING([whether lseek_execute() is available])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_LSEEK_EXECUTE], [
-+      ZFS_LINUX_TEST_SRC([lseek_execute], [
-               #include <linux/fs.h>
-       ], [
-               struct file *fp __attribute__ ((unused)) = NULL;
-@@ -13,10 +12,15 @@ AC_DEFUN([ZFS_AC_KERNEL_LSEEK_EXECUTE],
-               loff_t maxsize __attribute__ ((unused)) = 0;
-               lseek_execute(fp, ip, offset, maxsize);
--      ], [lseek_exclusive], [fs/read_write.c], [
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_LSEEK_EXECUTE], [
-+      AC_MSG_CHECKING([whether lseek_execute() is available])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([lseek_execute],
-+          [lseek_exclusive], [fs/read_write.c], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_LSEEK_EXECUTE, 1,
--                        [lseek_execute() is available])
-+              AC_DEFINE(HAVE_LSEEK_EXECUTE, 1, [lseek_execute() is available])
-       ], [
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-make-request-fn.m4 b/config/kernel-make-request-fn.m4
-new file mode 100644
-index 000000000..86339aa04
---- /dev/null
-+++ b/config/kernel-make-request-fn.m4
-@@ -0,0 +1,77 @@
-+dnl #
-+dnl # Check for make_request_fn interface.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_MAKE_REQUEST_FN], [
-+      ZFS_LINUX_TEST_SRC([make_request_fn_int], [
-+              #include <linux/blkdev.h>
-+              int make_request(struct request_queue *q,
-+                  struct bio *bio) { return (0); }
-+      ],[
-+              blk_queue_make_request(NULL, &make_request);
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([make_request_fn_void], [
-+              #include <linux/blkdev.h>
-+              void make_request(struct request_queue *q,
-+                  struct bio *bio) { return; }
-+      ],[
-+              blk_queue_make_request(NULL, &make_request);
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([make_request_fn_blk_qc_t], [
-+              #include <linux/blkdev.h>
-+              blk_qc_t make_request(struct request_queue *q,
-+                  struct bio *bio) { return (BLK_QC_T_NONE); }
-+      ],[
-+              blk_queue_make_request(NULL, &make_request);
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_MAKE_REQUEST_FN], [
-+      dnl #
-+      dnl # Legacy API
-+      dnl # make_request_fn returns int.
-+      dnl #
-+      AC_MSG_CHECKING([whether make_request_fn() returns int])
-+      ZFS_LINUX_TEST_RESULT([make_request_fn_int], [
-+              AC_MSG_RESULT(yes)
-+              AC_DEFINE(MAKE_REQUEST_FN_RET, int,
-+                  [make_request_fn() return type])
-+              AC_DEFINE(HAVE_MAKE_REQUEST_FN_RET_INT, 1,
-+                  [Noting that make_request_fn() returns int])
-+      ],[
-+              AC_MSG_RESULT(no)
-+
-+              dnl #
-+              dnl # Linux 3.2 API Change
-+              dnl # make_request_fn returns void.
-+              dnl #
-+              AC_MSG_CHECKING([whether make_request_fn() returns void])
-+              ZFS_LINUX_TEST_RESULT([make_request_fn_void], [
-+                      AC_MSG_RESULT(yes)
-+                      AC_DEFINE(MAKE_REQUEST_FN_RET, void,
-+                          [make_request_fn() return type])
-+                      AC_DEFINE(HAVE_MAKE_REQUEST_FN_RET_VOID, 1,
-+                          [Noting that make_request_fn() returns void])
-+              ],[
-+                      AC_MSG_RESULT(no)
-+
-+                      dnl #
-+                      dnl # Linux 4.4 API Change
-+                      dnl # make_request_fn returns blk_qc_t.
-+                      dnl #
-+                      AC_MSG_CHECKING(
-+                          [whether make_request_fn() returns blk_qc_t])
-+                      ZFS_LINUX_TEST_RESULT([make_request_fn_blk_qc_t], [
-+                              AC_MSG_RESULT(yes)
-+                              AC_DEFINE(MAKE_REQUEST_FN_RET, blk_qc_t,
-+                                  [make_request_fn() return type])
-+                              AC_DEFINE(HAVE_MAKE_REQUEST_FN_RET_QC, 1,
-+                                  [Noting that make_request_fn() ]
-+                                  [returns blk_qc_t])
-+                      ],[
-+                              ZFS_LINUX_TEST_ERROR([make_request_fn])
-+                      ])
-+              ])
-+      ])
-+])
-diff --git a/config/kernel-misc-minor.m4 b/config/kernel-misc-minor.m4
-index a020d2ebc..20fe2cd2f 100644
---- a/config/kernel-misc-minor.m4
-+++ b/config/kernel-misc-minor.m4
-@@ -6,7 +6,7 @@ dnl # number.  Start with a large known available unreserved minor and work
- dnl # our way down to lower value if a collision is detected.
- dnl #
- AC_DEFUN([ZFS_AC_KERNEL_MISC_MINOR], [
--      AC_MSG_CHECKING([for available /dev/zfs minor])
-+      AC_MSG_CHECKING([whether /dev/zfs minor is available])
-       for i in $(seq 249 -1 200); do
-               if ! grep -q "^#define\s\+.*_MINOR\s\+.*$i" \
-diff --git a/config/kernel-mk-request-fn.m4 b/config/kernel-mk-request-fn.m4
-deleted file mode 100644
-index 57eebe23d..000000000
---- a/config/kernel-mk-request-fn.m4
-+++ /dev/null
-@@ -1,65 +0,0 @@
--dnl #
--dnl # Linux 3.2 API Change
--dnl # make_request_fn returns void instead of int.
--dnl #
--dnl # Linux 4.4 API Change
--dnl # make_request_fn returns blk_qc_t.
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_MAKE_REQUEST_FN], [
--      AC_MSG_CHECKING([whether make_request_fn() returns int])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/blkdev.h>
--
--              int make_request(struct request_queue *q, struct bio *bio)
--              {
--                      return (0);
--              }
--      ],[
--              blk_queue_make_request(NULL, &make_request);
--      ],[
--              AC_MSG_RESULT(yes)
--              AC_DEFINE(MAKE_REQUEST_FN_RET, int,
--                  [make_request_fn() returns int])
--              AC_DEFINE(HAVE_MAKE_REQUEST_FN_RET_INT, 1,
--                  [Noting that make_request_fn() returns int])
--      ],[
--              AC_MSG_RESULT(no)
--              AC_MSG_CHECKING([whether make_request_fn() returns void])
--              ZFS_LINUX_TRY_COMPILE([
--                      #include <linux/blkdev.h>
--
--                      void make_request(struct request_queue *q, struct bio *bio)
--                      {
--                              return;
--                      }
--              ],[
--                      blk_queue_make_request(NULL, &make_request);
--              ],[
--                      AC_MSG_RESULT(yes)
--                      AC_DEFINE(MAKE_REQUEST_FN_RET, void,
--                          [make_request_fn() returns void])
--              ],[
--                      AC_MSG_RESULT(no)
--                      AC_MSG_CHECKING([whether make_request_fn() returns blk_qc_t])
--                      ZFS_LINUX_TRY_COMPILE([
--                              #include <linux/blkdev.h>
--
--                              blk_qc_t make_request(struct request_queue *q, struct bio *bio)
--                              {
--                                      return (BLK_QC_T_NONE);
--                              }
--                      ],[
--                              blk_queue_make_request(NULL, &make_request);
--                      ],[
--                              AC_MSG_RESULT(yes)
--                              AC_DEFINE(MAKE_REQUEST_FN_RET, blk_qc_t,
--                                  [make_request_fn() returns blk_qc_t])
--                              AC_DEFINE(HAVE_MAKE_REQUEST_FN_RET_QC, 1,
--                                  [Noting that make_request_fn() returns blk_qc_t])
--                      ],[
--                              AC_MSG_ERROR(no - Please file a bug report at
--                                  https://github.com/zfsonlinux/zfs/issues/new)
--                      ])
--              ])
--      ])
--])
-diff --git a/config/kernel-mkdir-umode-t.m4 b/config/kernel-mkdir-umode-t.m4
-index ebc21be9e..4cbfc0c31 100644
---- a/config/kernel-mkdir-umode-t.m4
-+++ b/config/kernel-mkdir-umode-t.m4
-@@ -6,9 +6,8 @@ dnl # would also change all three prototypes.  However, if it turns out that
- dnl # some distribution doesn't backport the whole thing this could be
- dnl # broken apart in to three separate checks.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_MKDIR_UMODE_T], [
--      AC_MSG_CHECKING([whether iops->create()/mkdir()/mknod() take umode_t])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_MKDIR_UMODE_T], [
-+      ZFS_LINUX_TEST_SRC([inode_operations_mkdir], [
-               #include <linux/fs.h>
-               int mkdir(struct inode *inode, struct dentry *dentry,
-@@ -18,8 +17,12 @@ AC_DEFUN([ZFS_AC_KERNEL_MKDIR_UMODE_T], [
-                   iops __attribute__ ((unused)) = {
-                       .mkdir = mkdir,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_MKDIR_UMODE_T], [
-+      AC_MSG_CHECKING([whether iops->create()/mkdir()/mknod() take umode_t])
-+      ZFS_LINUX_TEST_RESULT([inode_operations_mkdir], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_MKDIR_UMODE_T, 1,
-                   [iops->create()/mkdir()/mknod() take umode_t])
-diff --git a/config/kernel-mod-param.m4 b/config/kernel-mod-param.m4
-index b72be684a..e00f19d61 100644
---- a/config/kernel-mod-param.m4
-+++ b/config/kernel-mod-param.m4
-@@ -2,9 +2,8 @@ dnl #
- dnl # Grsecurity kernel API change
- dnl # constified parameters of module_param_call() methods
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_MODULE_PARAM_CALL_CONST], [
--      AC_MSG_CHECKING([whether module_param_call() is hardened])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_MODULE_PARAM_CALL_CONST], [
-+      ZFS_LINUX_TEST_SRC([module_param_call], [
-               #include <linux/module.h>
-               #include <linux/moduleparam.h>
-@@ -19,8 +18,12 @@ AC_DEFUN([ZFS_AC_KERNEL_MODULE_PARAM_CALL_CONST], [
-               }
-               module_param_call(p, param_set, param_get, NULL, 0644);
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_MODULE_PARAM_CALL_CONST], [
-+      AC_MSG_CHECKING([whether module_param_call() is hardened])
-+      ZFS_LINUX_TEST_RESULT([module_param_call], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(MODULE_PARAM_CALL_CONST, 1,
-                   [hardened module_param_call])
-diff --git a/config/kernel-objtool.m4 b/config/kernel-objtool.m4
-index 467329b25..bf60e7869 100644
---- a/config/kernel-objtool.m4
-+++ b/config/kernel-objtool.m4
-@@ -1,41 +1,44 @@
- dnl #
--dnl # 4.6 API for compile-time stack validation
-+dnl # Check for objtool support.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_OBJTOOL], [
--      AC_MSG_CHECKING([for compile-time stack validation (objtool)])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_OBJTOOL], [
-+
-+      dnl # 4.6 API for compile-time stack validation
-+      ZFS_LINUX_TEST_SRC([objtool], [
-               #undef __ASSEMBLY__
-               #include <asm/frame.h>
-       ],[
-               #if !defined(FRAME_BEGIN)
-               CTASSERT(1);
-               #endif
--      ],[
--              AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_KERNEL_OBJTOOL, 1,
--                  [kernel does stack verification])
--
--              ZFS_AC_KERNEL_STACK_FRAME_NON_STANDARD
--      ],[
--              AC_MSG_RESULT(no)
-       ])
--])
--dnl #
--dnl # 4.6 API added STACK_FRAME_NON_STANDARD macro
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_STACK_FRAME_NON_STANDARD], [
--      AC_MSG_CHECKING([whether STACK_FRAME_NON_STANDARD is defined])
--      ZFS_LINUX_TRY_COMPILE([
-+      dnl # 4.6 API added STACK_FRAME_NON_STANDARD macro
-+      ZFS_LINUX_TEST_SRC([stack_frame_non_standard], [
-               #include <linux/frame.h>
-       ],[
-               #if !defined(STACK_FRAME_NON_STANDARD)
-               CTASSERT(1);
-               #endif
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_OBJTOOL], [
-+      AC_MSG_CHECKING(
-+          [whether compile-time stack validation (objtool) is available])
-+      ZFS_LINUX_TEST_RESULT([objtool], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_STACK_FRAME_NON_STANDARD, 1,
--                 [STACK_FRAME_NON_STANDARD is defined])
-+              AC_DEFINE(HAVE_KERNEL_OBJTOOL, 1,
-+                  [kernel does stack verification])
-+
-+              AC_MSG_CHECKING([whether STACK_FRAME_NON_STANDARD is defined])
-+              ZFS_LINUX_TEST_RESULT([stack_frame_non_standard], [
-+                      AC_MSG_RESULT(yes)
-+                      AC_DEFINE(HAVE_STACK_FRAME_NON_STANDARD, 1,
-+                         [STACK_FRAME_NON_STANDARD is defined])
-+              ],[
-+                      AC_MSG_RESULT(no)
-+              ])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-open-bdev-exclusive.m4 b/config/kernel-open-bdev-exclusive.m4
-index 0661315a6..2e46b8876 100644
---- a/config/kernel-open-bdev-exclusive.m4
-+++ b/config/kernel-open-bdev-exclusive.m4
-@@ -2,16 +2,21 @@ dnl #
- dnl # 2.6.28 API change
- dnl # open/close_bdev_excl() renamed to open/close_bdev_exclusive()
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_OPEN_BDEV_EXCLUSIVE],
--      [AC_MSG_CHECKING([whether open_bdev_exclusive() is available])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_BDEV_OPEN_EXCLUSIVE], [
-+      ZFS_LINUX_TEST_SRC([open_bdev_exclusive], [
-               #include <linux/fs.h>
-       ], [
-               open_bdev_exclusive(NULL, 0, NULL);
--      ], [open_bdev_exclusive], [fs/block_dev.c], [
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_BDEV_OPEN_EXCLUSIVE], [
-+      AC_MSG_CHECKING([whether open_bdev_exclusive() is available])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([open_bdev_exclusive],
-+          [open_bdev_exclusive], [fs/block_dev.c], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_OPEN_BDEV_EXCLUSIVE, 1,
--                        [open_bdev_exclusive() is available])
-+                  [open_bdev_exclusive() is available])
-       ], [
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-pde-data.m4 b/config/kernel-pde-data.m4
-index 8aa4c2204..928c5ef0d 100644
---- a/config/kernel-pde-data.m4
-+++ b/config/kernel-pde-data.m4
-@@ -2,15 +2,19 @@ dnl #
- dnl # 3.10 API change,
- dnl # PDE is replaced by PDE_DATA
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_PDE_DATA], [
--      AC_MSG_CHECKING([whether PDE_DATA() is available])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_PDE_DATA], [
-+      ZFS_LINUX_TEST_SRC([pde_data], [
-               #include <linux/proc_fs.h>
-       ], [
-               PDE_DATA(NULL);
--      ], [PDE_DATA], [], [
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_PDE_DATA], [
-+      AC_MSG_CHECKING([whether PDE_DATA() is available])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([pde_data], [PDE_DATA], [], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_PDE_DATA, 1, [yes])
-+              AC_DEFINE(HAVE_PDE_DATA, 1, [PDE_DATA is available])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-put-link.m4 b/config/kernel-put-link.m4
-index a0bb36ef2..f03df9e99 100644
---- a/config/kernel-put-link.m4
-+++ b/config/kernel-put-link.m4
-@@ -1,17 +1,35 @@
- dnl #
- dnl # Supported symlink APIs
- dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_PUT_LINK], [
-+      ZFS_LINUX_TEST_SRC([put_link_cookie], [
-+              #include <linux/fs.h>
-+              void put_link(struct inode *ip, void *cookie)
-+                  { return; }
-+              static struct inode_operations
-+                  iops __attribute__ ((unused)) = {
-+                      .put_link = put_link,
-+              };
-+      ],[])
-+
-+      ZFS_LINUX_TEST_SRC([put_link_nameidata], [
-+              #include <linux/fs.h>
-+              void put_link(struct dentry *de, struct
-+                  nameidata *nd, void *ptr) { return; }
-+              static struct inode_operations
-+                  iops __attribute__ ((unused)) = {
-+                      .put_link = put_link,
-+              };
-+      ],[])
-+])
-+
- AC_DEFUN([ZFS_AC_KERNEL_PUT_LINK], [
-       dnl #
-       dnl # 4.5 API change
-       dnl # get_link() uses delayed done, there is no put_link() interface.
-+      dnl # This check intially uses the inode_operations_get_link result
-       dnl #
--      ZFS_LINUX_TRY_COMPILE([
--              #if !defined(HAVE_GET_LINK_DELAYED)
--              #error "Expecting get_link() delayed done"
--              #endif
--      ],[
--      ],[
-+      ZFS_LINUX_TEST_RESULT([inode_operations_get_link], [
-               AC_DEFINE(HAVE_PUT_LINK_DELAYED, 1, [iops->put_link() delayed])
-       ],[
-               dnl #
-@@ -19,41 +37,24 @@ AC_DEFUN([ZFS_AC_KERNEL_PUT_LINK], [
-               dnl # This kernel retired the nameidata structure.
-               dnl #
-               AC_MSG_CHECKING([whether iops->put_link() passes cookie])
--              ZFS_LINUX_TRY_COMPILE([
--                      #include <linux/fs.h>
--                      void put_link(struct inode *ip, void *cookie)
--                          { return; }
--                      static struct inode_operations
--                          iops __attribute__ ((unused)) = {
--                              .put_link = put_link,
--                      };
--              ],[
--              ],[
-+              ZFS_LINUX_TEST_RESULT([put_link_cookie], [
-                       AC_MSG_RESULT(yes)
-                       AC_DEFINE(HAVE_PUT_LINK_COOKIE, 1,
-                           [iops->put_link() cookie])
-               ],[
-+                      AC_MSG_RESULT(no)
-+
-                       dnl #
-                       dnl # 2.6.32 API
-                       dnl #
--                      AC_MSG_RESULT(no)
-                       AC_MSG_CHECKING(
-                           [whether iops->put_link() passes nameidata])
--                      ZFS_LINUX_TRY_COMPILE([
--                              #include <linux/fs.h>
--                              void put_link(struct dentry *de, struct
--                                  nameidata *nd, void *ptr) { return; }
--                              static struct inode_operations
--                                  iops __attribute__ ((unused)) = {
--                                      .put_link = put_link,
--                              };
--                      ],[
--                      ],[
-+                      ZFS_LINUX_TEST_RESULT([put_link_nameidata], [
-                               AC_MSG_RESULT(yes)
-                               AC_DEFINE(HAVE_PUT_LINK_NAMEIDATA, 1,
-                                   [iops->put_link() nameidata])
-                       ],[
--                              AC_MSG_ERROR(no; please file a bug report)
-+                              ZFS_LINUX_TEST_ERROR([put_link])
-                       ])
-               ])
-       ])
-diff --git a/config/kernel-rename.m4 b/config/kernel-rename.m4
-index 9f894fb4d..f70739153 100644
---- a/config/kernel-rename.m4
-+++ b/config/kernel-rename.m4
-@@ -3,9 +3,8 @@ dnl # 4.9 API change,
- dnl # iops->rename2() merged into iops->rename(), and iops->rename() now wants
- dnl # flags.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_RENAME_WANTS_FLAGS], [
--      AC_MSG_CHECKING([whether iops->rename() wants flags])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME_WANTS_FLAGS], [
-+      ZFS_LINUX_TEST_SRC([inode_operations_rename], [
-               #include <linux/fs.h>
-               int rename_fn(struct inode *sip, struct dentry *sdp,
-                       struct inode *tip, struct dentry *tdp,
-@@ -15,10 +14,15 @@ AC_DEFUN([ZFS_AC_KERNEL_RENAME_WANTS_FLAGS], [
-                   iops __attribute__ ((unused)) = {
-                       .rename = rename_fn,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_RENAME_WANTS_FLAGS], [
-+      AC_MSG_CHECKING([whether iops->rename() wants flags])
-+      ZFS_LINUX_TEST_RESULT([inode_operations_rename], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_RENAME_WANTS_FLAGS, 1, [iops->rename() wants flags])
-+              AC_DEFINE(HAVE_RENAME_WANTS_FLAGS, 1,
-+                  [iops->rename() wants flags])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-rw.m4 b/config/kernel-rw.m4
-index 1c8a265e0..85b47d5c6 100644
---- a/config/kernel-rw.m4
-+++ b/config/kernel-rw.m4
-@@ -3,11 +3,8 @@ 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([ZFS_AC_KERNEL_WRITE], [
--      AC_MSG_CHECKING([whether kernel_write() takes loff_t pointer])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="-Werror"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_WRITE], [
-+      ZFS_LINUX_TEST_SRC([kernel_write], [
-               #include <linux/fs.h>
-       ],[
-               struct file *file = NULL;
-@@ -17,14 +14,18 @@ AC_DEFUN([ZFS_AC_KERNEL_WRITE], [
-               ssize_t ret;
-               ret = kernel_write(file, buf, count, pos);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_WRITE], [
-+      AC_MSG_CHECKING([whether kernel_write() takes loff_t pointer])
-+      ZFS_LINUX_TEST_RESULT([kernel_write], [
-               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 #
-@@ -32,11 +33,8 @@ 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([ZFS_AC_KERNEL_READ], [
--      AC_MSG_CHECKING([whether kernel_read() takes loff_t pointer])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="-Werror"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_READ], [
-+      ZFS_LINUX_TEST_SRC([kernel_read], [
-               #include <linux/fs.h>
-       ],[
-               struct file *file = NULL;
-@@ -46,12 +44,26 @@ AC_DEFUN([ZFS_AC_KERNEL_READ], [
-               ssize_t ret;
-               ret = kernel_read(file, buf, count, pos);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_READ], [
-+      AC_MSG_CHECKING([whether kernel_read() takes loff_t pointer])
-+      ZFS_LINUX_TEST_RESULT([kernel_read], [
-               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"
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_RW], [
-+      ZFS_AC_KERNEL_SRC_WRITE
-+      ZFS_AC_KERNEL_SRC_READ
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_RW], [
-+      ZFS_AC_KERNEL_WRITE
-+      ZFS_AC_KERNEL_READ
- ])
-diff --git a/config/kernel-rwsem.m4 b/config/kernel-rwsem.m4
-index 532c22718..67c5cf908 100644
---- a/config/kernel-rwsem.m4
-+++ b/config/kernel-rwsem.m4
-@@ -4,25 +4,26 @@ dnl #
- dnl # The rw_semaphore.wait_lock member was changed from spinlock_t to
- dnl # raw_spinlock_t at commit ddb6c9b58a19edcfac93ac670b066c836ff729f1.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_RWSEM_SPINLOCK_IS_RAW], [
--      AC_MSG_CHECKING([whether struct rw_semaphore member wait_lock is raw])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="-Werror"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_RWSEM_SPINLOCK_IS_RAW], [
-+      ZFS_LINUX_TEST_SRC([rwsem_spinlock_is_raw], [
-               #include <linux/rwsem.h>
-       ],[
-               struct rw_semaphore dummy_semaphore __attribute__ ((unused));
-               raw_spinlock_t dummy_lock __attribute__ ((unused)) =
-                   __RAW_SPIN_LOCK_INITIALIZER(dummy_lock);
-               dummy_semaphore.wait_lock = dummy_lock;
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_RWSEM_SPINLOCK_IS_RAW], [
-+      AC_MSG_CHECKING([whether struct rw_semaphore member wait_lock is raw])
-+      ZFS_LINUX_TEST_RESULT([rwsem_spinlock_is_raw], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(RWSEM_SPINLOCK_IS_RAW, 1,
--              [struct rw_semaphore member wait_lock is raw_spinlock_t])
-+                  [struct rw_semaphore member wait_lock is raw_spinlock_t])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
- ])
- dnl #
-@@ -30,23 +31,24 @@ dnl # 3.16 API Change
- dnl #
- dnl # rwsem-spinlock "->activity" changed to "->count"
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_RWSEM_ACTIVITY], [
--      AC_MSG_CHECKING([whether struct rw_semaphore has member activity])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="-Werror"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_RWSEM_ACTIVITY], [
-+      ZFS_LINUX_TEST_SRC([rwsem_activity], [
-               #include <linux/rwsem.h>
-       ],[
-               struct rw_semaphore dummy_semaphore __attribute__ ((unused));
-               dummy_semaphore.activity = 0;
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_RWSEM_ACTIVITY], [
-+      AC_MSG_CHECKING([whether struct rw_semaphore has member activity])
-+      ZFS_LINUX_TEST_RESULT([rwsem_activity], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_RWSEM_ACTIVITY, 1,
--              [struct rw_semaphore has member activity])
-+                  [struct rw_semaphore has member activity])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
- ])
- dnl #
-@@ -54,22 +56,35 @@ dnl # 4.8 API Change
- dnl #
- dnl # rwsem "->count" changed to atomic_long_t type
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_RWSEM_ATOMIC_LONG_COUNT], [
--      AC_MSG_CHECKING(
--      [whether struct rw_semaphore has atomic_long_t member count])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="-Werror"
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_RWSEM_ATOMIC_LONG_COUNT], [
-+      ZFS_LINUX_TEST_SRC([rwsem_atomic_long_count], [
-               #include <linux/rwsem.h>
-       ],[
-               DECLARE_RWSEM(dummy_semaphore);
-               (void) atomic_long_read(&dummy_semaphore.count);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_RWSEM_ATOMIC_LONG_COUNT], [
-+      AC_MSG_CHECKING(
-+          [whether struct rw_semaphore has atomic_long_t member count])
-+      ZFS_LINUX_TEST_RESULT([rwsem_atomic_long_count], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_RWSEM_ATOMIC_LONG_COUNT, 1,
--              [struct rw_semaphore has atomic_long_t member count])
-+                  [struct rw_semaphore has atomic_long_t member count])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_RWSEM], [
-+      ZFS_AC_KERNEL_SRC_RWSEM_SPINLOCK_IS_RAW
-+      ZFS_AC_KERNEL_SRC_RWSEM_ACTIVITY
-+      ZFS_AC_KERNEL_SRC_RWSEM_ATOMIC_LONG_COUNT
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_RWSEM], [
-+      ZFS_AC_KERNEL_RWSEM_SPINLOCK_IS_RAW
-+      ZFS_AC_KERNEL_RWSEM_ACTIVITY
-+      ZFS_AC_KERNEL_RWSEM_ATOMIC_LONG_COUNT
- ])
-diff --git a/config/kernel-sched.m4 b/config/kernel-sched.m4
-index 640b008aa..4a7db970a 100644
---- a/config/kernel-sched.m4
-+++ b/config/kernel-sched.m4
-@@ -2,14 +2,18 @@ dnl #
- dnl # 3.9 API change,
- dnl # Moved things from linux/sched.h to linux/sched/rt.h
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_SCHED_RT_HEADER],
--      [AC_MSG_CHECKING([whether header linux/sched/rt.h exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SCHED_RT_HEADER], [
-+      ZFS_LINUX_TEST_SRC([sched_rt_header], [
-               #include <linux/sched.h>
-               #include <linux/sched/rt.h>
-       ],[
-               return 0;
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SCHED_RT_HEADER], [
-+      AC_MSG_CHECKING([whether header linux/sched/rt.h exists])
-+      ZFS_LINUX_TEST_RESULT([sched_rt_header], [
-               AC_DEFINE(HAVE_SCHED_RT_HEADER, 1, [linux/sched/rt.h exists])
-               AC_MSG_RESULT(yes)
-       ],[
-@@ -21,36 +25,59 @@ dnl #
- dnl # 4.11 API change,
- dnl # Moved things from linux/sched.h to linux/sched/signal.h
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_SCHED_SIGNAL_HEADER],
--      [AC_MSG_CHECKING([whether header linux/sched/signal.h exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SCHED_SIGNAL_HEADER], [
-+      ZFS_LINUX_TEST_SRC([sched_signal_header], [
-               #include <linux/sched.h>
-               #include <linux/sched/signal.h>
-       ],[
-               return 0;
--      ],[
--              AC_DEFINE(HAVE_SCHED_SIGNAL_HEADER, 1, [linux/sched/signal.h exists])
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SCHED_SIGNAL_HEADER], [
-+      AC_MSG_CHECKING([whether header linux/sched/signal.h exists])
-+      ZFS_LINUX_TEST_RESULT([sched_signal_header], [
-+              AC_DEFINE(HAVE_SCHED_SIGNAL_HEADER, 1,
-+                  [linux/sched/signal.h exists])
-               AC_MSG_RESULT(yes)
-       ],[
-               AC_MSG_RESULT(no)
-       ])
- ])
-+
- dnl #
- dnl # 3.19 API change
- dnl # The io_schedule_timeout() function is present in all 2.6.32 kernels
- dnl # but it was not exported until Linux 3.19.  The RHEL 7.x kernels which
- dnl # are based on a 3.10 kernel do export this symbol.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_IO_SCHEDULE_TIMEOUT], [
--      AC_MSG_CHECKING([whether io_schedule_timeout() is available])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_IO_SCHEDULE_TIMEOUT], [
-+      ZFS_LINUX_TEST_SRC([io_schedule_timeout], [
-               #include <linux/sched.h>
-       ], [
-               (void) io_schedule_timeout(1);
--      ], [io_schedule_timeout], [], [
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_IO_SCHEDULE_TIMEOUT], [
-+      AC_MSG_CHECKING([whether io_schedule_timeout() is available])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([io_schedule_timeout],
-+      [io_schedule_timeout], [], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_IO_SCHEDULE_TIMEOUT, 1, [yes])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
- ])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SCHED], [
-+      ZFS_AC_KERNEL_SRC_SCHED_RT_HEADER
-+      ZFS_AC_KERNEL_SRC_SCHED_SIGNAL_HEADER
-+      ZFS_AC_KERNEL_SRC_IO_SCHEDULE_TIMEOUT
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SCHED], [
-+      ZFS_AC_KERNEL_SCHED_RT_HEADER
-+      ZFS_AC_KERNEL_SCHED_SIGNAL_HEADER
-+      ZFS_AC_KERNEL_IO_SCHEDULE_TIMEOUT
-+])
-diff --git a/config/kernel-security-inode-init.m4 b/config/kernel-security-inode-init.m4
-index a62176d42..0dea7e392 100644
---- a/config/kernel-security-inode-init.m4
-+++ b/config/kernel-security-inode-init.m4
-@@ -5,9 +5,8 @@ dnl # qstr argument which must be passed in from the dentry if available.
- dnl # Passing a NULL is safe when no qstr is available the relevant
- dnl # security checks will just be skipped.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_6ARGS_SECURITY_INODE_INIT_SECURITY], [
--      AC_MSG_CHECKING([whether security_inode_init_security wants 6 args])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SECURITY_INODE_INIT_SECURITY_6ARGS], [
-+      ZFS_LINUX_TEST_SRC([security_inode_init_security_6args], [
-               #include <linux/security.h>
-       ],[
-               struct inode *ip __attribute__ ((unused)) = NULL;
-@@ -18,10 +17,15 @@ AC_DEFUN([ZFS_AC_KERNEL_6ARGS_SECURITY_INODE_INIT_SECURITY], [
-               size_t len __attribute__ ((unused)) = 0;
-               security_inode_init_security(ip, dip, str, &name, &value, &len);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SECURITY_INODE_INIT_SECURITY_6ARGS], [
-+      AC_MSG_CHECKING([whether security_inode_init_security wants 6 args])
-+      ZFS_LINUX_TEST_RESULT([security_inode_init_security_6args], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_6ARGS_SECURITY_INODE_INIT_SECURITY, 1,
--                        [security_inode_init_security wants 6 args])
-+                  [security_inode_init_security wants 6 args])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-@@ -34,9 +38,8 @@ dnl # a filesystem specific callback to write security extended attributes.
- dnl # This was done to support the initialization of multiple LSM xattrs
- dnl # and the EVM xattr.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_CALLBACK_SECURITY_INODE_INIT_SECURITY], [
--      AC_MSG_CHECKING([whether security_inode_init_security wants callback])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SECURITY_INODE_INIT_SECURITY_CALLBACK], [
-+      ZFS_LINUX_TEST_SRC([security_inode_init_security], [
-               #include <linux/security.h>
-       ],[
-               struct inode *ip __attribute__ ((unused)) = NULL;
-@@ -45,11 +48,26 @@ AC_DEFUN([ZFS_AC_KERNEL_CALLBACK_SECURITY_INODE_INIT_SECURITY], [
-               initxattrs func __attribute__ ((unused)) = NULL;
-               security_inode_init_security(ip, dip, str, func, NULL);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SECURITY_INODE_INIT_SECURITY_CALLBACK], [
-+      AC_MSG_CHECKING([whether security_inode_init_security wants callback])
-+      ZFS_LINUX_TEST_RESULT([security_inode_init_security], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_CALLBACK_SECURITY_INODE_INIT_SECURITY, 1,
--                        [security_inode_init_security wants callback])
-+                  [security_inode_init_security wants callback])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
- ])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SECURITY_INODE], [
-+      ZFS_AC_KERNEL_SRC_SECURITY_INODE_INIT_SECURITY_6ARGS
-+      ZFS_AC_KERNEL_SRC_SECURITY_INODE_INIT_SECURITY_CALLBACK
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SECURITY_INODE], [
-+      ZFS_AC_KERNEL_SECURITY_INODE_INIT_SECURITY_6ARGS
-+      ZFS_AC_KERNEL_SECURITY_INODE_INIT_SECURITY_CALLBACK
-+])
-diff --git a/config/kernel-set-nlink.m4 b/config/kernel-set-nlink.m4
-index f7ffc0d3a..63a5a8c0d 100644
---- a/config/kernel-set-nlink.m4
-+++ b/config/kernel-set-nlink.m4
-@@ -2,18 +2,21 @@ dnl #
- dnl # Linux v3.2-rc1 API change
- dnl # SHA: bfe8684869601dacfcb2cd69ef8cfd9045f62170
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_SET_NLINK], [
--      AC_MSG_CHECKING([whether set_nlink() is available])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SET_NLINK], [
-+      ZFS_LINUX_TEST_SRC([set_nlink], [
-               #include <linux/fs.h>
-       ],[
-               struct inode node;
-               unsigned int link = 0;
-               (void) set_nlink(&node, link);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SET_NLINK], [
-+      AC_MSG_CHECKING([whether set_nlink() is available])
-+      ZFS_LINUX_TEST_RESULT([set_nlink], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_SET_NLINK, 1,
--                        [set_nlink() is available])
-+              AC_DEFINE(HAVE_SET_NLINK, 1, [set_nlink() is available])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-setattr-prepare.m4 b/config/kernel-setattr-prepare.m4
-index 32f7deb77..45408c45c 100644
---- a/config/kernel-setattr-prepare.m4
-+++ b/config/kernel-setattr-prepare.m4
-@@ -3,17 +3,21 @@ dnl # 4.9 API change
- dnl # The inode_change_ok() function has been renamed setattr_prepare()
- dnl # and updated to take a dentry rather than an inode.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_SETATTR_PREPARE],
--      [AC_MSG_CHECKING([whether setattr_prepare() is available])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SETATTR_PREPARE], [
-+      ZFS_LINUX_TEST_SRC([setattr_prepare], [
-               #include <linux/fs.h>
-       ], [
-               struct dentry *dentry = NULL;
-               struct iattr *attr = NULL;
--              int error;
-+              int error __attribute__ ((unused)) =
-+                  setattr_prepare(dentry, attr);
-+      ])
-+])
--              error = setattr_prepare(dentry, attr);
--      ], [setattr_prepare], [fs/attr.c], [
-+AC_DEFUN([ZFS_AC_KERNEL_SETATTR_PREPARE], [
-+      AC_MSG_CHECKING([whether setattr_prepare() is available])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare],
-+          [setattr_prepare], [fs/attr.c], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_SETATTR_PREPARE, 1,
-                   [setattr_prepare() is available])
-diff --git a/config/kernel-sget-args.m4 b/config/kernel-sget-args.m4
-index 9d1745925..13581399e 100644
---- a/config/kernel-sget-args.m4
-+++ b/config/kernel-sget-args.m4
-@@ -2,9 +2,8 @@ dnl #
- dnl # 3.6 API change,
- dnl # 'sget' now takes the mount flags as an argument.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_5ARG_SGET],
--      [AC_MSG_CHECKING([whether sget() wants 5 args])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SGET], [
-+      ZFS_LINUX_TEST_SRC([sget_5args], [
-               #include <linux/fs.h>
-       ],[
-               struct file_system_type *type = NULL;
-@@ -13,11 +12,15 @@ AC_DEFUN([ZFS_AC_KERNEL_5ARG_SGET],
-               int flags = 0;
-               void *data = NULL;
-               (void) sget(type, test, set, flags, data);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SGET], [
-+      AC_MSG_CHECKING([whether sget() wants 5 args])
-+      ZFS_LINUX_TEST_RESULT([sget_5args], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_5ARG_SGET, 1, [sget() wants 5 args])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
- ])
--
-diff --git a/config/kernel-show-options.m4 b/config/kernel-show-options.m4
-index 67d683c55..9e426bc39 100644
---- a/config/kernel-show-options.m4
-+++ b/config/kernel-show-options.m4
-@@ -1,21 +1,26 @@
- dnl #
- dnl # Linux 3.3 API
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_SHOW_OPTIONS], [
--      AC_MSG_CHECKING([whether sops->show_options() wants dentry])
--
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SHOW_OPTIONS], [
-+      ZFS_LINUX_TEST_SRC([super_operations_show_options], [
-               #include <linux/fs.h>
--              int show_options (struct seq_file * x, struct dentry * y) { return 0; };
-+              int show_options(struct seq_file * x, struct dentry * y) {
-+                      return 0;
-+              };
-+
-               static struct super_operations sops __attribute__ ((unused)) = {
-                       .show_options = show_options,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SHOW_OPTIONS], [
-+      AC_MSG_CHECKING([whether sops->show_options() wants dentry])
-+      ZFS_LINUX_TEST_RESULT([super_operations_show_options], [
-               AC_MSG_RESULT([yes])
-               AC_DEFINE(HAVE_SHOW_OPTIONS_WITH_DENTRY, 1,
--                      [sops->show_options() with dentry])
-+                  [sops->show_options() with dentry])
-       ],[
-               AC_MSG_RESULT([no])
-       ])
-diff --git a/config/kernel-shrink.m4 b/config/kernel-shrink.m4
-index 405cbf42c..45b4b5d4b 100644
---- a/config/kernel-shrink.m4
-+++ b/config/kernel-shrink.m4
-@@ -4,9 +4,8 @@ dnl # The super_block structure now stores a per-filesystem shrinker.
- dnl # This interface is preferable because it can be used to specifically
- dnl # target only the zfs filesystem for pruning.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_SHRINK], [
--      AC_MSG_CHECKING([whether super_block has s_shrink])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_SHRINK], [
-+      ZFS_LINUX_TEST_SRC([super_block_s_shrink], [
-               #include <linux/fs.h>
-               int shrink(struct shrinker *s, struct shrink_control *sc)
-@@ -18,8 +17,12 @@ AC_DEFUN([ZFS_AC_KERNEL_SHRINK], [
-                       .s_shrink.seeks = DEFAULT_SEEKS,
-                       .s_shrink.batch = 0,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SUPER_BLOCK_S_SHRINK], [
-+      AC_MSG_CHECKING([whether super_block has s_shrink])
-+      ZFS_LINUX_TEST_RESULT([super_block_s_shrink], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_SHRINK, 1, [struct super_block has s_shrink])
-@@ -50,15 +53,18 @@ dnl # a list_head is used.  Then to prevent the spinning from occurring
- dnl # the .next pointer is set to the fs_supers list_head which ensures
- dnl # the iterate_supers_type() function will always terminate.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_S_INSTANCES_LIST_HEAD], [
--      AC_MSG_CHECKING([whether super_block has s_instances list_head])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_INSTANCES_LIST_HEAD], [
-+      ZFS_LINUX_TEST_SRC([super_block_s_instances_list_head], [
-               #include <linux/fs.h>
-       ],[
-               struct super_block sb __attribute__ ((unused));
--
-               INIT_LIST_HEAD(&sb.s_instances);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SUPER_BLOCK_S_INSTANCES_LIST_HEAD], [
-+      AC_MSG_CHECKING([whether super_block has s_instances list_head])
-+      ZFS_LINUX_TEST_RESULT([super_block_s_instances_list_head], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_S_INSTANCES_LIST_HEAD, 1,
-                   [struct super_block has s_instances list_head])
-@@ -67,9 +73,8 @@ AC_DEFUN([ZFS_AC_KERNEL_S_INSTANCES_LIST_HEAD], [
-       ])
- ])
--AC_DEFUN([ZFS_AC_KERNEL_NR_CACHED_OBJECTS], [
--      AC_MSG_CHECKING([whether sops->nr_cached_objects() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_NR_CACHED_OBJECTS], [
-+      ZFS_LINUX_TEST_SRC([nr_cached_objects], [
-               #include <linux/fs.h>
-               int nr_cached_objects(struct super_block *sb) { return 0; }
-@@ -78,19 +83,22 @@ AC_DEFUN([ZFS_AC_KERNEL_NR_CACHED_OBJECTS], [
-                   sops __attribute__ ((unused)) = {
-                       .nr_cached_objects = nr_cached_objects,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_NR_CACHED_OBJECTS], [
-+      AC_MSG_CHECKING([whether sops->nr_cached_objects() exists])
-+      ZFS_LINUX_TEST_RESULT([nr_cached_objects], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_NR_CACHED_OBJECTS, 1,
--                      [sops->nr_cached_objects() exists])
-+                  [sops->nr_cached_objects() exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
- ])
--AC_DEFUN([ZFS_AC_KERNEL_FREE_CACHED_OBJECTS], [
--      AC_MSG_CHECKING([whether sops->free_cached_objects() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_FREE_CACHED_OBJECTS], [
-+      ZFS_LINUX_TEST_SRC([free_cached_objects], [
-               #include <linux/fs.h>
-               void free_cached_objects(struct super_block *sb, int x)
-@@ -100,11 +108,15 @@ AC_DEFUN([ZFS_AC_KERNEL_FREE_CACHED_OBJECTS], [
-                   sops __attribute__ ((unused)) = {
-                       .free_cached_objects = free_cached_objects,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_FREE_CACHED_OBJECTS], [
-+      AC_MSG_CHECKING([whether sops->free_cached_objects() exists])
-+      ZFS_LINUX_TEST_RESULT([free_cached_objects], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_FREE_CACHED_OBJECTS, 1,
--                      [sops->free_cached_objects() exists])
-+                  [sops->free_cached_objects() exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-@@ -115,15 +127,19 @@ dnl # 3.12 API change
- dnl # The nid member was added to struct shrink_control to support
- dnl # NUMA-aware shrinkers.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_SHRINK_CONTROL_HAS_NID], [
--      AC_MSG_CHECKING([whether shrink_control has nid])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINK_CONTROL_HAS_NID], [
-+      ZFS_LINUX_TEST_SRC([shrink_control_nid], [
-               #include <linux/fs.h>
-       ],[
-               struct shrink_control sc __attribute__ ((unused));
-               unsigned long scnidsize __attribute__ ((unused)) =
-                   sizeof(sc.nid);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SHRINK_CONTROL_HAS_NID], [
-+      AC_MSG_CHECKING([whether shrink_control has nid])
-+      ZFS_LINUX_TEST_RESULT([shrink_control_nid], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(SHRINK_CONTROL_HAS_NID, 1,
-                   [struct shrink_control has nid])
-@@ -132,84 +148,96 @@ AC_DEFUN([ZFS_AC_KERNEL_SHRINK_CONTROL_HAS_NID], [
-       ])
- ])
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINKER_CALLBACK], [
-+      ZFS_LINUX_TEST_SRC([shrinker_cb_2arg], [
-+              #include <linux/mm.h>
-+              int shrinker_cb(int nr_to_scan, gfp_t gfp_mask) { return 0; }
-+      ],[
-+              struct shrinker cache_shrinker = {
-+                      .shrink = shrinker_cb,
-+                      .seeks = DEFAULT_SEEKS,
-+              };
-+              register_shrinker(&cache_shrinker);
-+      ])
--AC_DEFUN([ZFS_AC_KERNEL_SHRINKER_CALLBACK],[
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="-Werror"
--      dnl #
--      dnl # 2.6.23 to 2.6.34 API change
--      dnl # ->shrink(int nr_to_scan, gfp_t gfp_mask)
--      dnl #
--      AC_MSG_CHECKING([whether old 2-argument shrinker exists])
--      ZFS_LINUX_TRY_COMPILE([
-+      ZFS_LINUX_TEST_SRC([shrinker_cb_3arg], [
-               #include <linux/mm.h>
-+              int shrinker_cb(struct shrinker *shrink, int nr_to_scan,
-+                  gfp_t gfp_mask) { return 0; }
-+      ],[
-+              struct shrinker cache_shrinker = {
-+                      .shrink = shrinker_cb,
-+                      .seeks = DEFAULT_SEEKS,
-+              };
-+              register_shrinker(&cache_shrinker);
-+      ])
--              int shrinker_cb(int nr_to_scan, gfp_t gfp_mask) {
--                      return 0;
--              }
-+      ZFS_LINUX_TEST_SRC([shrinker_cb_shrink_control], [
-+              #include <linux/mm.h>
-+              int shrinker_cb(struct shrinker *shrink,
-+                  struct shrink_control *sc) { return 0; }
-       ],[
-               struct shrinker cache_shrinker = {
-                       .shrink = shrinker_cb,
-                       .seeks = DEFAULT_SEEKS,
-               };
-               register_shrinker(&cache_shrinker);
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([shrinker_cb_shrink_control_split], [
-+              #include <linux/mm.h>
-+              unsigned long shrinker_cb(struct shrinker *shrink,
-+                  struct shrink_control *sc) { return 0; }
-       ],[
-+              struct shrinker cache_shrinker = {
-+                      .count_objects = shrinker_cb,
-+                      .scan_objects = shrinker_cb,
-+                      .seeks = DEFAULT_SEEKS,
-+              };
-+              register_shrinker(&cache_shrinker);
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SHRINKER_CALLBACK],[
-+      dnl #
-+      dnl # 2.6.23 to 2.6.34 API change
-+      dnl # ->shrink(int nr_to_scan, gfp_t gfp_mask)
-+      dnl #
-+      AC_MSG_CHECKING([whether old 2-argument shrinker exists])
-+      ZFS_LINUX_TEST_RESULT([shrinker_cb_2arg], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_2ARGS_OLD_SHRINKER_CALLBACK, 1,
--                      [old shrinker callback wants 2 args])
-+                  [old shrinker callback wants 2 args])
-       ],[
-               AC_MSG_RESULT(no)
-+
-               dnl #
-               dnl # 2.6.35 - 2.6.39 API change
-               dnl # ->shrink(struct shrinker *,
-               dnl #          int nr_to_scan, gfp_t gfp_mask)
-               dnl #
-               AC_MSG_CHECKING([whether old 3-argument shrinker exists])
--              ZFS_LINUX_TRY_COMPILE([
--                      #include <linux/mm.h>
--
--                      int shrinker_cb(struct shrinker *shrink, int nr_to_scan,
--                                      gfp_t gfp_mask) {
--                              return 0;
--                      }
--              ],[
--                      struct shrinker cache_shrinker = {
--                              .shrink = shrinker_cb,
--                              .seeks = DEFAULT_SEEKS,
--                      };
--                      register_shrinker(&cache_shrinker);
--              ],[
-+              ZFS_LINUX_TEST_RESULT([shrinker_cb_3arg], [
-                       AC_MSG_RESULT(yes)
-                       AC_DEFINE(HAVE_3ARGS_SHRINKER_CALLBACK, 1,
-                               [old shrinker callback wants 3 args])
-               ],[
-                       AC_MSG_RESULT(no)
-+
-                       dnl #
-                       dnl # 3.0 - 3.11 API change
-                       dnl # ->shrink(struct shrinker *,
-                       dnl #          struct shrink_control *sc)
-                       dnl #
-                       AC_MSG_CHECKING(
--                              [whether new 2-argument shrinker exists])
--                      ZFS_LINUX_TRY_COMPILE([
--                              #include <linux/mm.h>
--
--                              int shrinker_cb(struct shrinker *shrink,
--                                              struct shrink_control *sc) {
--                                      return 0;
--                              }
--                      ],[
--                              struct shrinker cache_shrinker = {
--                                      .shrink = shrinker_cb,
--                                      .seeks = DEFAULT_SEEKS,
--                              };
--                              register_shrinker(&cache_shrinker);
--                      ],[
-+                          [whether new 2-argument shrinker exists])
-+                      ZFS_LINUX_TEST_RESULT([shrinker_cb_shrink_control], [
-                               AC_MSG_RESULT(yes)
-                               AC_DEFINE(HAVE_2ARGS_NEW_SHRINKER_CALLBACK, 1,
-                                       [new shrinker callback wants 2 args])
-                       ],[
-                               AC_MSG_RESULT(no)
-+
-                               dnl #
-                               dnl # 3.12 API change,
-                               dnl # ->shrink() is logically split in to
-@@ -217,52 +245,61 @@ AC_DEFUN([ZFS_AC_KERNEL_SHRINKER_CALLBACK],[
-                               dnl #
-                               AC_MSG_CHECKING(
-                                   [whether ->count_objects callback exists])
--                              ZFS_LINUX_TRY_COMPILE([
--                                      #include <linux/mm.h>
--
--                                      unsigned long shrinker_cb(
--                                              struct shrinker *shrink,
--                                              struct shrink_control *sc) {
--                                              return 0;
--                                      }
--                              ],[
--                                      struct shrinker cache_shrinker = {
--                                              .count_objects = shrinker_cb,
--                                              .scan_objects = shrinker_cb,
--                                              .seeks = DEFAULT_SEEKS,
--                                      };
--                                      register_shrinker(&cache_shrinker);
--                              ],[
-+                              ZFS_LINUX_TEST_RESULT(
-+                                  [shrinker_cb_shrink_control_split], [
-                                       AC_MSG_RESULT(yes)
-                                       AC_DEFINE(HAVE_SPLIT_SHRINKER_CALLBACK,
-                                               1, [->count_objects exists])
-                               ],[
--                                      AC_MSG_ERROR(error)
-+                                      ZFS_LINUX_TEST_ERROR([shrinker])
-                               ])
-                       ])
-               ])
-       ])
--      EXTRA_KCFLAGS="$tmp_flags"
- ])
- dnl #
- dnl # 2.6.39 API change,
- dnl # Shrinker adjust to use common shrink_control structure.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_SHRINK_CONTROL_STRUCT], [
--      AC_MSG_CHECKING([whether struct shrink_control exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINK_CONTROL_STRUCT], [
-+      ZFS_LINUX_TEST_SRC([shrink_control_struct], [
-               #include <linux/mm.h>
-       ],[
-               struct shrink_control sc __attribute__ ((unused));
-               sc.nr_to_scan = 0;
-               sc.gfp_mask = GFP_KERNEL;
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SHRINK_CONTROL_STRUCT], [
-+      AC_MSG_CHECKING([whether struct shrink_control exists])
-+      ZFS_LINUX_TEST_RESULT([shrink_control_struct], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_SHRINK_CONTROL_STRUCT, 1,
--                      [struct shrink_control exists])
-+                  [struct shrink_control exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
- ])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINKER], [
-+      ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_SHRINK
-+      ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_INSTANCES_LIST_HEAD
-+      ZFS_AC_KERNEL_SRC_NR_CACHED_OBJECTS
-+      ZFS_AC_KERNEL_SRC_FREE_CACHED_OBJECTS
-+      ZFS_AC_KERNEL_SRC_SHRINK_CONTROL_HAS_NID
-+      ZFS_AC_KERNEL_SRC_SHRINKER_CALLBACK
-+      ZFS_AC_KERNEL_SRC_SHRINK_CONTROL_STRUCT
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SHRINKER], [
-+      ZFS_AC_KERNEL_SUPER_BLOCK_S_SHRINK
-+      ZFS_AC_KERNEL_SUPER_BLOCK_S_INSTANCES_LIST_HEAD
-+      ZFS_AC_KERNEL_NR_CACHED_OBJECTS
-+      ZFS_AC_KERNEL_FREE_CACHED_OBJECTS
-+      ZFS_AC_KERNEL_SHRINK_CONTROL_HAS_NID
-+      ZFS_AC_KERNEL_SHRINKER_CALLBACK
-+      ZFS_AC_KERNEL_SHRINK_CONTROL_STRUCT
-+])
-diff --git a/config/kernel-submit_bio.m4 b/config/kernel-submit_bio.m4
-index da5f85ca7..cf80e9b83 100644
---- a/config/kernel-submit_bio.m4
-+++ b/config/kernel-submit_bio.m4
-@@ -3,15 +3,19 @@ dnl # 4.8 API change
- dnl # The rw argument has been removed from submit_bio/submit_bio_wait.
- dnl # Callers are now expected to set bio->bi_rw instead of passing it in.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_SUBMIT_BIO], [
--      AC_MSG_CHECKING([whether submit_bio() wants 1 arg])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SUBMIT_BIO], [
-+      ZFS_LINUX_TEST_SRC([submit_bio], [
-               #include <linux/bio.h>
-       ],[
-               blk_qc_t blk_qc;
-               struct bio *bio = NULL;
-               blk_qc = submit_bio(bio);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SUBMIT_BIO], [
-+      AC_MSG_CHECKING([whether submit_bio() wants 1 arg])
-+      ZFS_LINUX_TEST_RESULT([submit_bio], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_1ARG_SUBMIT_BIO, 1, [submit_bio() wants 1 arg])
-       ],[
-diff --git a/config/kernel-super-userns.m4 b/config/kernel-super-userns.m4
-index de94ad967..1ad35f2d1 100644
---- a/config/kernel-super-userns.m4
-+++ b/config/kernel-super-userns.m4
-@@ -3,15 +3,19 @@ dnl # 4.8 API change
- dnl # struct user_namespace was added to struct super_block as
- dnl # super->s_user_ns member
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_SUPER_USER_NS], [
--      AC_MSG_CHECKING([whether super_block->s_user_ns exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SUPER_USER_NS], [
-+      ZFS_LINUX_TEST_SRC([super_user_ns], [
-               #include <linux/fs.h>
-               #include <linux/user_namespace.h>
--      ],[
-+      ], [
-               struct super_block super;
-               super.s_user_ns = (struct user_namespace *)NULL;
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SUPER_USER_NS], [
-+      AC_MSG_CHECKING([whether super_block->s_user_ns exists])
-+      ZFS_LINUX_TEST_RESULT([super_user_ns], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_SUPER_USER_NS, 1,
-                   [super_block->s_user_ns exists])
-diff --git a/config/kernel-timer.m4 b/config/kernel-timer.m4
-index b0e1afa15..5e8fc0d3a 100644
---- a/config/kernel-timer.m4
-+++ b/config/kernel-timer.m4
-@@ -8,13 +8,9 @@ dnl # kernels that support the new timer_list.func signature.
- dnl #
- dnl # Also check for the existance of flags in struct timer_list, they were
- dnl # added in 4.1-rc8 via 0eeda71bc30d.
--
--AC_DEFUN([ZFS_AC_KERNEL_TIMER_SETUP], [
--      AC_MSG_CHECKING([whether timer_setup() is available])
--      tmp_flags="$EXTRA_KCFLAGS"
--      EXTRA_KCFLAGS="-Werror"
--
--      ZFS_LINUX_TRY_COMPILE([
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_TIMER_SETUP], [
-+      ZFS_LINUX_TEST_SRC([timer_setup], [
-               #include <linux/timer.h>
-               struct my_task_timer {
-@@ -24,13 +20,34 @@ AC_DEFUN([ZFS_AC_KERNEL_TIMER_SETUP], [
-               void task_expire(struct timer_list *tl)
-               {
--                      struct my_task_timer *task_timer = from_timer(task_timer, tl, timer);
-+                      struct my_task_timer *task_timer =
-+                          from_timer(task_timer, tl, timer);
-                       task_timer->data = 42;
-               }
-       ],[
-               struct my_task_timer task_timer;
-               timer_setup(&task_timer.timer, task_expire, 0);
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([timer_list_function], [
-+              #include <linux/timer.h>
-+              void task_expire(struct timer_list *tl) {}
-       ],[
-+              struct timer_list tl;
-+              tl.function = task_expire;
-+      ])
-+
-+      ZFS_LINUX_TEST_SRC([timer_list_flags], [
-+              #include <linux/timer.h>
-+      ],[
-+              struct timer_list tl;
-+              tl.flags = 2;
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_TIMER_SETUP], [
-+      AC_MSG_CHECKING([whether timer_setup() is available])
-+      ZFS_LINUX_TEST_RESULT([timer_setup], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_KERNEL_TIMER_SETUP, 1,
-                   [timer_setup() is available])
-@@ -39,14 +56,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TIMER_SETUP], [
-       ])
-       AC_MSG_CHECKING([whether timer function expects timer_list])
--
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/timer.h>
--              void task_expire(struct timer_list *tl) {}
--      ],[
--              struct timer_list tl;
--              tl.function = task_expire;
--      ],[
-+      ZFS_LINUX_TEST_RESULT([timer_list_function], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST, 1,
-                   [timer_list.function gets a timer_list])
-@@ -55,19 +65,11 @@ AC_DEFUN([ZFS_AC_KERNEL_TIMER_SETUP], [
-       ])
-       AC_MSG_CHECKING([whether struct timer_list has flags])
--
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/timer.h>
--      ],[
--              struct timer_list tl;
--              tl.flags = 2;
--      ],[
-+      ZFS_LINUX_TEST_RESULT([timer_list_flags], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_KERNEL_TIMER_LIST_FLAGS, 1,
-                   [struct timer_list has a flags member])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
--
--      EXTRA_KCFLAGS="$tmp_flags"
- ])
-diff --git a/config/kernel-tmpfile.m4 b/config/kernel-tmpfile.m4
-index 5aad90450..f510bfe6b 100644
---- a/config/kernel-tmpfile.m4
-+++ b/config/kernel-tmpfile.m4
-@@ -2,9 +2,8 @@ dnl #
- dnl # 3.11 API change
- dnl # Add support for i_op->tmpfile
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_TMPFILE], [
--      AC_MSG_CHECKING([whether i_op->tmpfile() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_TMPFILE], [
-+      ZFS_LINUX_TEST_SRC([inode_operations_tmpfile], [
-               #include <linux/fs.h>
-               int tmpfile(struct inode *inode, struct dentry *dentry,
-                   umode_t mode) { return 0; }
-@@ -12,11 +11,14 @@ AC_DEFUN([ZFS_AC_KERNEL_TMPFILE], [
-                   iops __attribute__ ((unused)) = {
-                       .tmpfile = tmpfile,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_TMPFILE], [
-+      AC_MSG_CHECKING([whether i_op->tmpfile() exists])
-+      ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_TMPFILE, 1,
--                  [i_op->tmpfile() exists])
-+              AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-totalhigh_pages.m4 b/config/kernel-totalhigh_pages.m4
-index b22e86d4d..4ecb03a50 100644
---- a/config/kernel-totalhigh_pages.m4
-+++ b/config/kernel-totalhigh_pages.m4
-@@ -1,16 +1,18 @@
- dnl #
- dnl # 5.0 API change
- dnl #
--dnl # ca79b0c211af mm: convert totalram_pages and totalhigh_pages variables to atomic
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_TOTALHIGH_PAGES], [
--      AC_MSG_CHECKING([whether totalhigh_pages() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_TOTALHIGH_PAGES], [
-+      ZFS_LINUX_TEST_SRC([totalhigh_pages], [
-               #include <linux/highmem.h>
-       ],[
-               unsigned long pages __attribute__ ((unused));
-               pages = totalhigh_pages();
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_TOTALHIGH_PAGES], [
-+      AC_MSG_CHECKING([whether totalhigh_pages() exists])
-+      ZFS_LINUX_TEST_RESULT([totalhigh_pages], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_TOTALHIGH_PAGES, 1, [totalhigh_pages() exists])
-       ],[
-diff --git a/config/kernel-totalram-pages-func.m4 b/config/kernel-totalram-pages-func.m4
-index a6eac6454..d0e812a8d 100644
---- a/config/kernel-totalram-pages-func.m4
-+++ b/config/kernel-totalram-pages-func.m4
-@@ -2,16 +2,21 @@ dnl #
- dnl # Linux 5.0: totalram_pages is no longer a global variable, and must be
- dnl # read via the totalram_pages() helper function.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_TOTALRAM_PAGES_FUNC], [
--      AC_MSG_CHECKING([whether totalram_pages() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_TOTALRAM_PAGES_FUNC], [
-+      ZFS_LINUX_TEST_SRC([totalram_pages], [
-               #include <linux/mm.h>
-       ],[
-               unsigned long pages __attribute__ ((unused));
-               pages = totalram_pages();
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_TOTALRAM_PAGES_FUNC], [
-+      AC_MSG_CHECKING([whether totalram_pages() exists])
-+      ZFS_LINUX_TEST_RESULT([totalram_pages], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_TOTALRAM_PAGES_FUNC, 1, [kernel has totalram_pages()])
-+              AC_DEFINE(HAVE_TOTALRAM_PAGES_FUNC, 1,
-+                  [kernel has totalram_pages()])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-truncate-range.m4 b/config/kernel-truncate-range.m4
-index da2cb50fc..8fdbb1086 100644
---- a/config/kernel-truncate-range.m4
-+++ b/config/kernel-truncate-range.m4
-@@ -4,17 +4,20 @@ dnl # torvalds/linux@17cf28afea2a1112f240a3a2da8af883be024811 removed
- dnl # truncate_range(). The file hole punching functionality is now
- dnl # provided by fallocate()
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_TRUNCATE_RANGE], [
--      AC_MSG_CHECKING([whether iops->truncate_range() exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_TRUNCATE_RANGE], [
-+      ZFS_LINUX_TEST_SRC([inode_operations_truncate_range], [
-               #include <linux/fs.h>
-               void truncate_range(struct inode *inode, loff_t start,
-                                   loff_t end) { return; }
-               static struct inode_operations iops __attribute__ ((unused)) = {
-                       .truncate_range = truncate_range,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_TRUNCATE_RANGE], [
-+      AC_MSG_CHECKING([whether iops->truncate_range() exists])
-+      ZFS_LINUX_TEST_RESULT([inode_operations_truncate_range], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_INODE_TRUNCATE_RANGE, 1,
-                         [iops->truncate_range() exists])
-diff --git a/config/kernel-truncate-setsize.m4 b/config/kernel-truncate-setsize.m4
-index 7e4aff479..e719c1444 100644
---- a/config/kernel-truncate-setsize.m4
-+++ b/config/kernel-truncate-setsize.m4
-@@ -2,16 +2,21 @@ dnl #
- dnl # 2.6.35 API change
- dnl # Added truncate_setsize() helper function.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_TRUNCATE_SETSIZE],
--      [AC_MSG_CHECKING([whether truncate_setsize() is available])
--      ZFS_LINUX_TRY_COMPILE_SYMBOL([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_TRUNCATE_SETSIZE], [
-+      ZFS_LINUX_TEST_SRC([truncate_setsize], [
-               #include <linux/mm.h>
-       ], [
-               truncate_setsize(NULL, 0);
--      ], [truncate_setsize], [mm/truncate.c], [
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_TRUNCATE_SETSIZE], [
-+      AC_MSG_CHECKING([whether truncate_setsize() is available])
-+      ZFS_LINUX_TEST_RESULT_SYMBOL([truncate_setsize],
-+          [truncate_setsize], [mm/truncate.c], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_TRUNCATE_SETSIZE, 1,
--                        [truncate_setsize() is available])
-+                  [truncate_setsize() is available])
-       ], [
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-userns-capabilities.m4 b/config/kernel-userns-capabilities.m4
-index fa3381978..5dcbc03d3 100644
---- a/config/kernel-userns-capabilities.m4
-+++ b/config/kernel-userns-capabilities.m4
-@@ -2,16 +2,19 @@ dnl #
- dnl # 2.6.38 API change
- dnl # ns_capable() was introduced
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_NS_CAPABLE], [
--      AC_MSG_CHECKING([whether ns_capable exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_NS_CAPABLE], [
-+      ZFS_LINUX_TEST_SRC([ns_capable], [
-               #include <linux/capability.h>
-       ],[
-               ns_capable((struct user_namespace *)NULL, CAP_SYS_ADMIN);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_NS_CAPABLE], [
-+      AC_MSG_CHECKING([whether ns_capable exists])
-+      ZFS_LINUX_TEST_RESULT([ns_capable], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_NS_CAPABLE, 1,
--                  [ns_capable exists])
-+              AC_DEFINE(HAVE_NS_CAPABLE, 1, [ns_capable exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-@@ -23,17 +26,20 @@ dnl # struct user_namespace was added to struct cred_t as
- dnl # cred->user_ns member
- dnl # Note that current_user_ns() was added in 2.6.28.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_CRED_USER_NS], [
--      AC_MSG_CHECKING([whether cred_t->user_ns exists])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_CRED_USER_NS], [
-+      ZFS_LINUX_TEST_SRC([cred_user_ns], [
-               #include <linux/cred.h>
-       ],[
-               struct cred cr;
-               cr.user_ns = (struct user_namespace *)NULL;
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_CRED_USER_NS], [
-+      AC_MSG_CHECKING([whether cred_t->user_ns exists])
-+      ZFS_LINUX_TEST_RESULT([cred_user_ns], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_CRED_USER_NS, 1,
--                  [cred_t->user_ns exists])
-+              AC_DEFINE(HAVE_CRED_USER_NS, 1, [cred_t->user_ns exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-@@ -44,14 +50,18 @@ dnl # 3.4 API change
- dnl # kuid_has_mapping() and kgid_has_mapping() were added to distinguish
- dnl # between internal kernel uids/gids and user namespace uids/gids.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_KUID_HAS_MAPPING], [
--      AC_MSG_CHECKING([whether kuid_has_mapping/kgid_has_mapping exist])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_KUID_HAS_MAPPING], [
-+      ZFS_LINUX_TEST_SRC([kuid_has_mapping], [
-               #include <linux/uidgid.h>
-       ],[
-               kuid_has_mapping((struct user_namespace *)NULL, KUIDT_INIT(0));
-               kgid_has_mapping((struct user_namespace *)NULL, KGIDT_INIT(0));
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_KUID_HAS_MAPPING], [
-+      AC_MSG_CHECKING([whether kuid_has_mapping/kgid_has_mapping exist])
-+      ZFS_LINUX_TEST_RESULT([kuid_has_mapping], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_KUID_HAS_MAPPING, 1,
-                   [kuid_has_mapping/kgid_has_mapping exist])
-@@ -60,6 +70,12 @@ AC_DEFUN([ZFS_AC_KERNEL_KUID_HAS_MAPPING], [
-       ])
- ])
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_USERNS_CAPABILITIES], [
-+      ZFS_AC_KERNEL_SRC_NS_CAPABLE
-+      ZFS_AC_KERNEL_SRC_CRED_USER_NS
-+      ZFS_AC_KERNEL_SRC_KUID_HAS_MAPPING
-+])
-+
- AC_DEFUN([ZFS_AC_KERNEL_USERNS_CAPABILITIES], [
-       ZFS_AC_KERNEL_NS_CAPABLE
-       ZFS_AC_KERNEL_CRED_USER_NS
-diff --git a/config/kernel-urange-sleep.m4 b/config/kernel-usleep_range.m4
-similarity index 60%
-rename from config/kernel-urange-sleep.m4
-rename to config/kernel-usleep_range.m4
-index b5764de3e..5bf051ab4 100644
---- a/config/kernel-urange-sleep.m4
-+++ b/config/kernel-usleep_range.m4
-@@ -1,20 +1,23 @@
- dnl #
--dnl # 2.6.36 API compatibility.
--dnl # Added usleep_range timer.
-+dnl # 2.6.36 API compatibility- Added usleep_range timer.
-+dnl #
- dnl # usleep_range is a finer precision implementation of msleep
- dnl # designed to be a drop-in replacement for udelay where a precise
- dnl # sleep / busy-wait is unnecessary.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_USLEEP_RANGE], [
--      AC_MSG_CHECKING([whether usleep_range() is available])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_USLEEP_RANGE], [
-+      ZFS_LINUX_TEST_SRC([usleep_range], [
-               #include <linux/delay.h>
-       ],[
-               usleep_range(0, 0);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_USLEEP_RANGE], [
-+      AC_MSG_CHECKING([whether usleep_range() is available])
-+      ZFS_LINUX_TEST_RESULT([usleep_range], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_USLEEP_RANGE, 1,
--                        [usleep_range is available])
-+              AC_DEFINE(HAVE_USLEEP_RANGE, 1, [usleep_range is available])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-vfs-direct_IO.m4 b/config/kernel-vfs-direct_IO.m4
-index cc50bfbe4..82583d52f 100644
---- a/config/kernel-vfs-direct_IO.m4
-+++ b/config/kernel-vfs-direct_IO.m4
-@@ -1,9 +1,8 @@
- dnl #
--dnl # Linux 4.6.x API change
-+dnl # Check for direct IO interfaces.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER], [
--      AC_MSG_CHECKING([whether aops->direct_IO() uses iov_iter])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_DIRECT_IO], [
-+      ZFS_LINUX_TEST_SRC([direct_io_iter], [
-               #include <linux/fs.h>
-               ssize_t test_direct_IO(struct kiocb *kiocb,
-@@ -13,24 +12,9 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER], [
-                   aops __attribute__ ((unused)) = {
-                       .direct_IO = test_direct_IO,
-               };
--      ],[
--      ],[
--              AC_MSG_RESULT([yes])
--              AC_DEFINE(HAVE_VFS_DIRECT_IO_ITER, 1,
--                  [aops->direct_IO() uses iov_iter without rw])
--              zfs_ac_direct_io="yes"
--      ],[
--              AC_MSG_RESULT([no])
--      ])
--])
-+      ],[])
--dnl #
--dnl # Linux 4.1.x API change
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER_OFFSET], [
--      AC_MSG_CHECKING(
--          [whether aops->direct_IO() uses iov_iter with offset])
--      ZFS_LINUX_TRY_COMPILE([
-+      ZFS_LINUX_TEST_SRC([direct_io_iter_offset], [
-               #include <linux/fs.h>
-               ssize_t test_direct_IO(struct kiocb *kiocb,
-@@ -40,24 +24,9 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER_OFFSET], [
-                   aops __attribute__ ((unused)) = {
-                       .direct_IO = test_direct_IO,
-               };
--      ],[
--      ],[
--              AC_MSG_RESULT([yes])
--              AC_DEFINE(HAVE_VFS_DIRECT_IO_ITER_OFFSET, 1,
--                  [aops->direct_IO() uses iov_iter with offset])
--              zfs_ac_direct_io="yes"
--      ],[
--              AC_MSG_RESULT([no])
--      ])
--])
-+      ],[])
--dnl #
--dnl # Linux 3.16.x API change
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER_RW_OFFSET], [
--      AC_MSG_CHECKING(
--          [whether aops->direct_IO() uses iov_iter with rw and offset])
--      ZFS_LINUX_TRY_COMPILE([
-+      ZFS_LINUX_TEST_SRC([direct_io_iter_rw_offset], [
-               #include <linux/fs.h>
-               ssize_t test_direct_IO(int rw, struct kiocb *kiocb,
-@@ -67,23 +36,9 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER_RW_OFFSET], [
-                   aops __attribute__ ((unused)) = {
-                   .direct_IO = test_direct_IO,
-               };
--      ],[
--      ],[
--              AC_MSG_RESULT([yes])
--              AC_DEFINE(HAVE_VFS_DIRECT_IO_ITER_RW_OFFSET, 1,
--                  [aops->direct_IO() uses iov_iter with rw and offset])
--              zfs_ac_direct_io="yes"
--      ],[
--              AC_MSG_RESULT([no])
--      ])
--])
-+      ],[])
--dnl #
--dnl # Ancient Linux API (predates git)
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_IOVEC], [
--      AC_MSG_CHECKING([whether aops->direct_IO() uses iovec])
--      ZFS_LINUX_TRY_COMPILE([
-+      ZFS_LINUX_TEST_SRC([direct_io_iovec], [
-               #include <linux/fs.h>
-               ssize_t test_direct_IO(int rw, struct kiocb *kiocb,
-@@ -94,37 +49,61 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_IOVEC], [
-                   aops __attribute__ ((unused)) = {
-                   .direct_IO = test_direct_IO,
-               };
--      ],[
--      ],[
--              AC_MSG_RESULT([yes])
--              AC_DEFINE(HAVE_VFS_DIRECT_IO_IOVEC, 1,
--                  [aops->direct_IO() uses iovec])
--              zfs_ac_direct_io="yes"
--      ],[
--              AC_MSG_RESULT([no])
--      ])
-+      ],[])
- ])
- AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO], [
--      zfs_ac_direct_io="no"
--
--      if test "$zfs_ac_direct_io" = "no"; then
--              ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER
--      fi
--
--      if test "$zfs_ac_direct_io" = "no"; then
--              ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER_OFFSET
--      fi
--
--      if test "$zfs_ac_direct_io" = "no"; then
--              ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER_RW_OFFSET
--      fi
--
--      if test "$zfs_ac_direct_io" = "no"; then
--              ZFS_AC_KERNEL_VFS_DIRECT_IO_IOVEC
--      fi
-+      dnl #
-+      dnl # Linux 4.6.x API change
-+      dnl #
-+      AC_MSG_CHECKING([whether aops->direct_IO() uses iov_iter])
-+      ZFS_LINUX_TEST_RESULT([direct_io_iter], [
-+              AC_MSG_RESULT([yes])
-+              AC_DEFINE(HAVE_VFS_DIRECT_IO_ITER, 1,
-+                  [aops->direct_IO() uses iov_iter without rw])
-+      ],[
-+              AC_MSG_RESULT([no])
--      if test "$zfs_ac_direct_io" = "no"; then
--              AC_MSG_ERROR([no; unknown direct IO interface])
--      fi
-+              dnl #
-+              dnl # Linux 4.1.x API change
-+              dnl #
-+              AC_MSG_CHECKING(
-+                  [whether aops->direct_IO() uses offset])
-+              ZFS_LINUX_TEST_RESULT([direct_io_iter_offset], [
-+                      AC_MSG_RESULT([yes])
-+                      AC_DEFINE(HAVE_VFS_DIRECT_IO_ITER_OFFSET, 1,
-+                          [aops->direct_IO() uses iov_iter with offset])
-+
-+              ],[
-+                      AC_MSG_RESULT([no])
-+
-+                      dnl #
-+                      dnl # Linux 3.16.x API change
-+                      dnl #
-+                      AC_MSG_CHECKING(
-+                          [whether aops->direct_IO() uses rw and offset])
-+                      ZFS_LINUX_TEST_RESULT([direct_io_iter_rw_offset], [
-+                              AC_MSG_RESULT([yes])
-+                              AC_DEFINE(HAVE_VFS_DIRECT_IO_ITER_RW_OFFSET, 1,
-+                                  [aops->direct_IO() uses iov_iter with ]
-+                                  [rw and offset])
-+                      ],[
-+                              AC_MSG_RESULT([no])
-+
-+                              dnl #
-+                              dnl # Ancient Linux API (predates git)
-+                              dnl #
-+                              AC_MSG_CHECKING(
-+                                  [whether aops->direct_IO() uses iovec])
-+                              ZFS_LINUX_TEST_RESULT([direct_io_iovec], [
-+                                      AC_MSG_RESULT([yes])
-+                                      AC_DEFINE(HAVE_VFS_DIRECT_IO_IOVEC, 1,
-+                                          [aops->direct_IO() uses iovec])
-+                              ],[
-+                                      ZFS_LINUX_TEST_ERROR([direct IO])
-+                                      AC_MSG_RESULT([no])
-+                              ])
-+                      ])
-+              ])
-+      ])
- ])
-diff --git a/config/kernel-vfs-fsync.m4 b/config/kernel-vfs-fsync.m4
-index a474f9f17..18a60d29a 100644
---- a/config/kernel-vfs-fsync.m4
-+++ b/config/kernel-vfs-fsync.m4
-@@ -2,13 +2,17 @@ dnl #
- dnl # 2.6.35 API change,
- dnl # Unused 'struct dentry *' removed from vfs_fsync() prototype.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_2ARGS_VFS_FSYNC], [
--      AC_MSG_CHECKING([whether vfs_fsync() wants 2 args])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_FSYNC_2ARGS], [
-+      ZFS_LINUX_TEST_SRC([vfs_fsync_2args], [
-               #include <linux/fs.h>
-       ],[
-               vfs_fsync(NULL, 0);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_VFS_FSYNC_2ARGS], [
-+      AC_MSG_CHECKING([whether vfs_fsync() wants 2 args])
-+      ZFS_LINUX_TEST_RESULT([vfs_fsync_2args], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_2ARGS_VFS_FSYNC, 1, [vfs_fsync() wants 2 args])
-       ],[
-diff --git a/config/kernel-vfs-getattr.m4 b/config/kernel-vfs-getattr.m4
-index b13723538..eb07853cc 100644
---- a/config/kernel-vfs-getattr.m4
-+++ b/config/kernel-vfs-getattr.m4
-@@ -2,19 +2,23 @@ dnl #
- dnl # 4.11 API, a528d35e@torvalds/linux
- dnl # vfs_getattr(const struct path *p, struct kstat *s, u32 m, unsigned int f)
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_4ARGS_VFS_GETATTR], [
--      AC_MSG_CHECKING([whether vfs_getattr() wants 4 args])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_GETATTR_4ARGS], [
-+      ZFS_LINUX_TEST_SRC([vfs_getattr_4args], [
-               #include <linux/fs.h>
-       ],[
-               vfs_getattr((const struct path *)NULL,
-                       (struct kstat *)NULL,
-                       (u32)0,
-                       (unsigned int)0);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_VFS_GETATTR_4ARGS], [
-+      AC_MSG_CHECKING([whether vfs_getattr() wants 4 args])
-+      ZFS_LINUX_TEST_RESULT([vfs_getattr_4args], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_4ARGS_VFS_GETATTR, 1,
--                [vfs_getattr wants 4 args])
-+                  [vfs_getattr wants 4 args])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-@@ -24,17 +28,21 @@ dnl #
- dnl # 3.9 API
- dnl # vfs_getattr(struct path *p, struct kstat *s)
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_2ARGS_VFS_GETATTR], [
--      AC_MSG_CHECKING([whether vfs_getattr() wants 2 args])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_GETATTR_2ARGS], [
-+      ZFS_LINUX_TEST_SRC([vfs_getattr_2args], [
-               #include <linux/fs.h>
-       ],[
-               vfs_getattr((struct path *) NULL,
-                       (struct kstat *)NULL);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_VFS_GETATTR_2ARGS], [
-+      AC_MSG_CHECKING([whether vfs_getattr() wants 2 args])
-+      ZFS_LINUX_TEST_RESULT([vfs_getattr_2args], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_2ARGS_VFS_GETATTR, 1,
--                        [vfs_getattr wants 2 args])
-+                  [vfs_getattr wants 2 args])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-@@ -44,19 +52,35 @@ dnl #
- dnl # <3.9 API
- dnl # vfs_getattr(struct vfsmount *v, struct dentry *d, struct kstat *k)
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_3ARGS_VFS_GETATTR], [
--      AC_MSG_CHECKING([whether vfs_getattr() wants 3 args])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_GETATTR_3ARGS], [
-+      ZFS_LINUX_TEST_SRC([vfs_getattr_3args], [
-               #include <linux/fs.h>
-       ],[
-               vfs_getattr((struct vfsmount *)NULL,
-                       (struct dentry *)NULL,
-                       (struct kstat *)NULL);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_VFS_GETATTR_3ARGS], [
-+      AC_MSG_CHECKING([whether vfs_getattr() wants 3 args])
-+      ZFS_LINUX_TEST_RESULT([vfs_getattr_3args], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_3ARGS_VFS_GETATTR, 1,
--                [vfs_getattr wants 3 args])
-+                  [vfs_getattr wants 3 args])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
- ])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_GETATTR], [
-+      ZFS_AC_KERNEL_SRC_VFS_GETATTR_4ARGS
-+      ZFS_AC_KERNEL_SRC_VFS_GETATTR_2ARGS
-+      ZFS_AC_KERNEL_SRC_VFS_GETATTR_3ARGS
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_VFS_GETATTR], [
-+      ZFS_AC_KERNEL_VFS_GETATTR_4ARGS
-+      ZFS_AC_KERNEL_VFS_GETATTR_2ARGS
-+      ZFS_AC_KERNEL_VFS_GETATTR_3ARGS
-+])
-diff --git a/config/kernel-vfs-iterate.m4 b/config/kernel-vfs-iterate.m4
-index 5de901d44..172118eac 100644
---- a/config/kernel-vfs-iterate.m4
-+++ b/config/kernel-vfs-iterate.m4
-@@ -1,9 +1,5 @@
--AC_DEFUN([ZFS_AC_KERNEL_VFS_ITERATE], [
--      dnl #
--      dnl # 4.7 API change
--      dnl #
--      AC_MSG_CHECKING([whether fops->iterate_shared() is available])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_ITERATE], [
-+      ZFS_LINUX_TEST_SRC([file_operations_iterate_shared], [
-               #include <linux/fs.h>
-               int iterate(struct file *filp, struct dir_context * context)
-                   { return 0; }
-@@ -12,11 +8,44 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_ITERATE], [
-                   __attribute__ ((unused)) = {
-                       .iterate_shared  = iterate,
-               };
--      ],[
--      ],[
-+      ],[])
-+
-+      ZFS_LINUX_TEST_SRC([file_operations_iterate], [
-+              #include <linux/fs.h>
-+              int iterate(struct file *filp,
-+                  struct dir_context *context) { return 0; }
-+
-+              static const struct file_operations fops
-+                  __attribute__ ((unused)) = {
-+                      .iterate         = iterate,
-+              };
-+
-+              #if defined(FMODE_KABI_ITERATE)
-+              #error "RHEL 7.5, FMODE_KABI_ITERATE interface"
-+              #endif
-+      ],[])
-+
-+      ZFS_LINUX_TEST_SRC([file_operations_readdir], [
-+              #include <linux/fs.h>
-+              int readdir(struct file *filp, void *entry,
-+                  filldir_t func) { return 0; }
-+
-+              static const struct file_operations fops
-+                  __attribute__ ((unused)) = {
-+                      .readdir = readdir,
-+              };
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_VFS_ITERATE], [
-+      dnl #
-+      dnl # 4.7 API change
-+      dnl #
-+      AC_MSG_CHECKING([whether fops->iterate_shared() is available])
-+      ZFS_LINUX_TEST_RESULT([file_operations_iterate_shared], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_VFS_ITERATE_SHARED, 1,
--                        [fops->iterate_shared() is available])
-+                  [fops->iterate_shared() is available])
-       ],[
-               AC_MSG_RESULT(no)
-@@ -31,44 +60,23 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_ITERATE], [
-               dnl # to using fops.readdir() to retain KABI compatibility.
-               dnl #
-               AC_MSG_CHECKING([whether fops->iterate() is available])
--              ZFS_LINUX_TRY_COMPILE([
--                      #include <linux/fs.h>
--                      int iterate(struct file *filp,
--                          struct dir_context *context) { return 0; }
--
--                      static const struct file_operations fops
--                          __attribute__ ((unused)) = {
--                              .iterate         = iterate,
--                      };
--
--                      #if defined(FMODE_KABI_ITERATE)
--                      #error "RHEL 7.5, FMODE_KABI_ITERATE interface"
--                      #endif
--              ],[
--              ],[
-+              ZFS_LINUX_TEST_RESULT([file_operations_iterate], [
-                       AC_MSG_RESULT(yes)
-                       AC_DEFINE(HAVE_VFS_ITERATE, 1,
--                                [fops->iterate() is available])
-+                          [fops->iterate() is available])
-               ],[
-                       AC_MSG_RESULT(no)
-+                      dnl #
-+                      dnl # readdir interface introduced
-+                      dnl #
-                       AC_MSG_CHECKING([whether fops->readdir() is available])
--                      ZFS_LINUX_TRY_COMPILE([
--                              #include <linux/fs.h>
--                              int readdir(struct file *filp, void *entry,
--                                  filldir_t func) { return 0; }
--
--                              static const struct file_operations fops
--                                  __attribute__ ((unused)) = {
--                                      .readdir = readdir,
--                              };
--                      ],[
--                      ],[
-+                      ZFS_LINUX_TEST_RESULT([file_operations_readdir], [
-                               AC_MSG_RESULT(yes)
-                               AC_DEFINE(HAVE_VFS_READDIR, 1,
--                                        [fops->readdir() is available])
-+                                  [fops->readdir() is available])
-                       ],[
--                              AC_MSG_ERROR(no; file a bug report with ZoL)
-+                              ZFS_LINUX_TEST_ERROR([vfs_iterate])
-                       ])
-               ])
-       ])
-diff --git a/config/kernel-vfs-rw-iterate.m4 b/config/kernel-vfs-rw-iterate.m4
-index ace54f707..000353ec1 100644
---- a/config/kernel-vfs-rw-iterate.m4
-+++ b/config/kernel-vfs-rw-iterate.m4
-@@ -1,9 +1,8 @@
- dnl #
- dnl # Linux 3.16 API
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_VFS_RW_ITERATE],
--      [AC_MSG_CHECKING([whether fops->read/write_iter() are available])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_RW_ITERATE], [
-+      ZFS_LINUX_TEST_SRC([file_operations_rw], [
-               #include <linux/fs.h>
-               ssize_t test_read(struct kiocb *kiocb, struct iov_iter *to)
-@@ -16,39 +15,41 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_RW_ITERATE],
-                   .read_iter = test_read,
-                   .write_iter = test_write,
-               };
--      ],[
--      ],[
--              AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_VFS_RW_ITERATE, 1,
--                      [fops->read/write_iter() are available])
-+      ],[])
--              ZFS_AC_KERNEL_NEW_SYNC_READ
-+      ZFS_LINUX_TEST_SRC([new_sync_rw], [
-+              #include <linux/fs.h>
-       ],[
--              AC_MSG_RESULT(no)
-+              ssize_t ret __attribute__ ((unused));
-+              struct file *filp = NULL;
-+              char __user *rbuf = NULL;
-+              const char __user *wbuf = NULL;
-+              size_t len = 0;
-+              loff_t ppos;
-+
-+              ret = new_sync_read(filp, rbuf, len, &ppos);
-+              ret = new_sync_write(filp, wbuf, len, &ppos);
-       ])
- ])
--dnl #
--dnl # Linux 4.1 API
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_NEW_SYNC_READ],
--      [AC_MSG_CHECKING([whether new_sync_read/write() are available])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/fs.h>
--      ],[
--                      ssize_t ret __attribute__ ((unused));
--                      struct file *filp = NULL;
--                      char __user *rbuf = NULL;
--                      const char __user *wbuf = NULL;
--                      size_t len = 0;
--                      loff_t ppos;
--
--                      ret = new_sync_read(filp, rbuf, len, &ppos);
--                      ret = new_sync_write(filp, wbuf, len, &ppos);
--      ],[
-+AC_DEFUN([ZFS_AC_KERNEL_VFS_RW_ITERATE], [
-+      AC_MSG_CHECKING([whether fops->read/write_iter() are available])
-+      ZFS_LINUX_TEST_RESULT([file_operations_rw], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_NEW_SYNC_READ, 1,
--                      [new_sync_read()/new_sync_write() are available])
-+              AC_DEFINE(HAVE_VFS_RW_ITERATE, 1,
-+                  [fops->read/write_iter() are available])
-+
-+              dnl #
-+              dnl # Linux 4.1 API
-+              dnl #
-+              AC_MSG_CHECKING([whether new_sync_read/write() are available])
-+              ZFS_LINUX_TEST_RESULT([new_sync_rw], [
-+                      AC_MSG_RESULT(yes)
-+                      AC_DEFINE(HAVE_NEW_SYNC_READ, 1,
-+                          [new_sync_read()/new_sync_write() are available])
-+              ],[
-+                      AC_MSG_RESULT(no)
-+              ])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-@@ -57,19 +58,22 @@ AC_DEFUN([ZFS_AC_KERNEL_NEW_SYNC_READ],
- dnl #
- dnl # Linux 4.1.x API
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_GENERIC_WRITE_CHECKS],
--      [AC_MSG_CHECKING([whether generic_write_checks() takes kiocb])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_GENERIC_WRITE_CHECKS], [
-+      ZFS_LINUX_TEST_SRC([generic_write_checks], [
-               #include <linux/fs.h>
--
-       ],[
-               struct kiocb *iocb = NULL;
-               struct iov_iter *iov = NULL;
-               generic_write_checks(iocb, iov);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_VFS_GENERIC_WRITE_CHECKS], [
-+      AC_MSG_CHECKING([whether generic_write_checks() takes kiocb])
-+      ZFS_LINUX_TEST_RESULT([generic_write_checks], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_GENERIC_WRITE_CHECKS_KIOCB, 1,
--                      [generic_write_checks() takes kiocb])
-+                  [generic_write_checks() takes kiocb])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel-wait.m4 b/config/kernel-wait.m4
-index d6442c1df..0414242bf 100644
---- a/config/kernel-wait.m4
-+++ b/config/kernel-wait.m4
-@@ -1,3 +1,26 @@
-+dnl #
-+dnl # 4.13 API change
-+dnl # Renamed struct wait_queue -> struct wait_queue_entry.
-+dnl #
-+dnl # N.B. The type check is performed before all other checks
-+dnl # since ZFS_AC_KERNEL_SRC_WAIT_QUEUE_HEAD_ENTRY depends on
-+dnl # HAVE_WAIT_QUEUE_ENTRY_T being set in confdefs.h.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_WAIT_QUEUE_ENTRY_T], [
-+      AC_MSG_CHECKING([whether wait_queue_entry_t exists])
-+      ZFS_LINUX_TRY_COMPILE([
-+              #include <linux/wait.h>
-+      ],[
-+              wait_queue_entry_t *entry __attribute__ ((unused));
-+      ],[
-+              AC_MSG_RESULT(yes)
-+              AC_DEFINE(HAVE_WAIT_QUEUE_ENTRY_T, 1,
-+                  [wait_queue_entry_t exists])
-+      ],[
-+              AC_MSG_RESULT(no)
-+      ])
-+])
-+
- dnl #
- dnl # 3.17 API change,
- dnl # wait_on_bit() no longer requires an action argument. The former
-@@ -8,34 +31,20 @@ dnl # of just two functions: one which uses io_schedule() and one which just
- dnl # uses schedule().  This API change was made to consolidate all of those
- dnl # redundant wait functions.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_WAIT_ON_BIT], [
--      AC_MSG_CHECKING([whether wait_on_bit() takes an action])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_WAIT_ON_BIT], [
-+      ZFS_LINUX_TEST_SRC([wait_on_bit], [
-               #include <linux/wait.h>
-       ],[
-               int (*action)(void *) = NULL;
-               wait_on_bit(NULL, 0, action, 0);
--      ],[
--              AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_WAIT_ON_BIT_ACTION, 1, [yes])
--      ],[
--              AC_MSG_RESULT(no)
-       ])
- ])
--dnl #
--dnl # 4.13 API change
--dnl # Renamed struct wait_queue -> struct wait_queue_entry.
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_WAIT_QUEUE_ENTRY_T], [
--      AC_MSG_CHECKING([whether wait_queue_entry_t exists])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/wait.h>
--      ],[
--              wait_queue_entry_t *entry __attribute__ ((unused));
--      ],[
-+
-+AC_DEFUN([ZFS_AC_KERNEL_WAIT_ON_BIT], [
-+      AC_MSG_CHECKING([whether wait_on_bit() takes an action])
-+      ZFS_LINUX_TEST_RESULT([wait_on_bit], [
-               AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_WAIT_QUEUE_ENTRY_T, 1,
--                  [wait_queue_entry_t exists])
-+              AC_DEFINE(HAVE_WAIT_ON_BIT_ACTION, 1, [yes])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-@@ -46,9 +55,8 @@ dnl # 4.13 API change
- dnl # Renamed wait_queue_head::task_list -> wait_queue_head::head
- dnl # Renamed wait_queue_entry::task_list -> wait_queue_entry::entry
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_WAIT_QUEUE_HEAD_ENTRY], [
--      AC_MSG_CHECKING([whether wq_head->head and wq_entry->entry exist])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_WAIT_QUEUE_HEAD_ENTRY], [
-+      ZFS_LINUX_TEST_SRC([wait_queue_head_entry], [
-               #include <linux/wait.h>
-               #ifdef HAVE_WAIT_QUEUE_ENTRY_T
-@@ -66,7 +74,12 @@ AC_DEFUN([ZFS_AC_KERNEL_WAIT_QUEUE_HEAD_ENTRY], [
-               head = &wq_head.head;
-               entry = &wq_entry.entry;
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_WAIT_QUEUE_HEAD_ENTRY], [
-+      AC_MSG_CHECKING([whether wq_head->head and wq_entry->entry exist])
-+      ZFS_LINUX_TEST_RESULT([wait_queue_head_entry], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_WAIT_QUEUE_HEAD_ENTRY, 1,
-                   [wq_head->head and wq_entry->entry exist])
-@@ -74,3 +87,13 @@ AC_DEFUN([ZFS_AC_KERNEL_WAIT_QUEUE_HEAD_ENTRY], [
-               AC_MSG_RESULT(no)
-       ])
- ])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_WAIT], [
-+      ZFS_AC_KERNEL_SRC_WAIT_ON_BIT
-+      ZFS_AC_KERNEL_SRC_WAIT_QUEUE_HEAD_ENTRY
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_WAIT], [
-+      ZFS_AC_KERNEL_WAIT_ON_BIT
-+      ZFS_AC_KERNEL_WAIT_QUEUE_HEAD_ENTRY
-+])
-diff --git a/config/kernel-xattr-handler.m4 b/config/kernel-xattr-handler.m4
-index 0b61b85b1..ed84c6390 100644
---- a/config/kernel-xattr-handler.m4
-+++ b/config/kernel-xattr-handler.m4
-@@ -3,9 +3,8 @@ dnl # 2.6.35 API change,
- dnl # The 'struct xattr_handler' was constified in the generic
- dnl # super_block structure.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_CONST_XATTR_HANDLER], [
--      AC_MSG_CHECKING([whether super_block uses const struct xattr_handler])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_CONST_XATTR_HANDLER], [
-+      ZFS_LINUX_TEST_SRC([const_xattr_handler], [
-               #include <linux/fs.h>
-               #include <linux/xattr.h>
-@@ -22,11 +21,15 @@ AC_DEFUN([ZFS_AC_KERNEL_CONST_XATTR_HANDLER], [
-               const struct super_block sb __attribute__ ((unused)) = {
-                       .s_xattr = xattr_handlers,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_CONST_XATTR_HANDLER], [
-+      AC_MSG_CHECKING([whether super_block uses const struct xattr_handler])
-+      ZFS_LINUX_TEST_RESULT([const_xattr_handler], [
-               AC_MSG_RESULT([yes])
-               AC_DEFINE(HAVE_CONST_XATTR_HANDLER, 1,
--                        [super_block uses const struct xattr_handler])
-+                  [super_block uses const struct xattr_handler])
-       ],[
-               AC_MSG_RESULT([no])
-       ])
-@@ -38,17 +41,20 @@ dnl # struct xattr_handler added new member "name".
- dnl # xattr_handler which matches to whole name rather than prefix should use
- dnl # "name" instead of "prefix", e.g. "system.posix_acl_access"
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_NAME], [
--      AC_MSG_CHECKING([whether xattr_handler has name])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_NAME], [
-+      ZFS_LINUX_TEST_SRC([xattr_handler_name], [
-               #include <linux/xattr.h>
-               static const struct xattr_handler
-                   xops __attribute__ ((unused)) = {
-                       .name = XATTR_NAME_POSIX_ACL_ACCESS,
-               };
--      ],[
--      ],[
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_NAME], [
-+      AC_MSG_CHECKING([whether xattr_handler has name])
-+      ZFS_LINUX_TEST_RESULT([xattr_handler_name], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_XATTR_HANDLER_NAME, 1,
-                   [xattr_handler has name])
-@@ -58,52 +64,65 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_NAME], [
- ])
- dnl #
--dnl # 4.9 API change,
--dnl # iops->{set,get,remove}xattr and generic_{set,get,remove}xattr are
--dnl # removed. xattr operations will directly go through sb->s_xattr.
-+dnl # Supported xattr handler get() interfaces checked newest to oldest.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_HAVE_GENERIC_SETXATTR], [
--      AC_MSG_CHECKING([whether generic_setxattr() exists])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/fs.h>
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_GET], [
-+      ZFS_LINUX_TEST_SRC([xattr_handler_get_dentry_inode], [
-               #include <linux/xattr.h>
--              static const struct inode_operations
--                  iops __attribute__ ((unused)) = {
--                      .setxattr = generic_setxattr
-+              int get(const struct xattr_handler *handler,
-+                  struct dentry *dentry, struct inode *inode,
-+                  const char *name, void *buffer, size_t size) { return 0; }
-+              static const struct xattr_handler
-+                  xops __attribute__ ((unused)) = {
-+                      .get = get,
-               };
--      ],[
--      ],[
--              AC_MSG_RESULT(yes)
--              AC_DEFINE(HAVE_GENERIC_SETXATTR, 1,
--                  [generic_setxattr() exists])
--      ],[
--              AC_MSG_RESULT(no)
--      ])
--])
-+      ],[])
--dnl #
--dnl # Supported xattr handler get() interfaces checked newest to oldest.
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_GET], [
--      dnl #
--      dnl # 4.7 API change,
--      dnl # The xattr_handler->get() callback was changed to take both
--      dnl # dentry and inode.
--      dnl #
--      AC_MSG_CHECKING([whether xattr_handler->get() wants both dentry and inode])
--      ZFS_LINUX_TRY_COMPILE([
-+      ZFS_LINUX_TEST_SRC([xattr_handler_get_xattr_handler], [
-               #include <linux/xattr.h>
-               int get(const struct xattr_handler *handler,
--                  struct dentry *dentry, struct inode *inode,
--                  const char *name, void *buffer, size_t size) { return 0; }
-+                  struct dentry *dentry, const char *name,
-+                  void *buffer, size_t size) { return 0; }
-               static const struct xattr_handler
-                   xops __attribute__ ((unused)) = {
-                       .get = get,
-               };
--      ],[
--      ],[
-+      ],[])
-+
-+      ZFS_LINUX_TEST_SRC([xattr_handler_get_dentry], [
-+              #include <linux/xattr.h>
-+
-+              int get(struct dentry *dentry, const char *name,
-+                  void *buffer, size_t size, int handler_flags)
-+                  { return 0; }
-+              static const struct xattr_handler
-+                  xops __attribute__ ((unused)) = {
-+                      .get = get,
-+              };
-+      ],[])
-+
-+      ZFS_LINUX_TEST_SRC([xattr_handler_get_inode], [
-+              #include <linux/xattr.h>
-+
-+              int get(struct inode *ip, const char *name,
-+                  void *buffer, size_t size) { return 0; }
-+              static const struct xattr_handler
-+                  xops __attribute__ ((unused)) = {
-+                      .get = get,
-+              };
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_GET], [
-+      dnl #
-+      dnl # 4.7 API change,
-+      dnl # The xattr_handler->get() callback was changed to take both
-+      dnl # dentry and inode.
-+      dnl #
-+      AC_MSG_CHECKING([whether xattr_handler->get() wants dentry and inode])
-+      ZFS_LINUX_TEST_RESULT([xattr_handler_get_dentry_inode], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_XATTR_GET_DENTRY_INODE, 1,
-                   [xattr_handler->get() wants both dentry and inode])
-@@ -115,69 +134,40 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_GET], [
-               dnl # should be accessed by handler->flags.
-               dnl #
-               AC_MSG_RESULT(no)
--              AC_MSG_CHECKING([whether xattr_handler->get() wants xattr_handler])
--              ZFS_LINUX_TRY_COMPILE([
--                      #include <linux/xattr.h>
--
--                      int get(const struct xattr_handler *handler,
--                          struct dentry *dentry, const char *name,
--                          void *buffer, size_t size) { return 0; }
--                      static const struct xattr_handler
--                          xops __attribute__ ((unused)) = {
--                              .get = get,
--                      };
--              ],[
--              ],[
-+              AC_MSG_CHECKING(
-+                  [whether xattr_handler->get() wants xattr_handler])
-+              ZFS_LINUX_TEST_RESULT([xattr_handler_get_xattr_handler], [
-                       AC_MSG_RESULT(yes)
-                       AC_DEFINE(HAVE_XATTR_GET_HANDLER, 1,
-                           [xattr_handler->get() wants xattr_handler])
-               ],[
-                       dnl #
-                       dnl # 2.6.33 API change,
--                      dnl # The xattr_handler->get() callback was changed to take
--                      dnl # a dentry instead of an inode, and a handler_flags
--                      dnl # argument was added.
-+                      dnl # The xattr_handler->get() callback was changed
-+                      dnl # to take a dentry instead of an inode, and a
-+                      dnl # handler_flags argument was added.
-                       dnl #
-                       AC_MSG_RESULT(no)
--                      AC_MSG_CHECKING([whether xattr_handler->get() wants dentry])
--                      ZFS_LINUX_TRY_COMPILE([
--                              #include <linux/xattr.h>
--
--                              int get(struct dentry *dentry, const char *name,
--                                  void *buffer, size_t size, int handler_flags)
--                                  { return 0; }
--                              static const struct xattr_handler
--                                  xops __attribute__ ((unused)) = {
--                                      .get = get,
--                              };
--                      ],[
--                      ],[
-+                      AC_MSG_CHECKING(
-+                          [whether xattr_handler->get() wants dentry])
-+                      ZFS_LINUX_TEST_RESULT([xattr_handler_get_dentry], [
-                               AC_MSG_RESULT(yes)
-                               AC_DEFINE(HAVE_XATTR_GET_DENTRY, 1,
-                                   [xattr_handler->get() wants dentry])
-                       ],[
-                               dnl #
--                              dnl # 2.6.32 API
-+                              dnl # Legacy 2.6.32 API
-                               dnl #
-                               AC_MSG_RESULT(no)
-                               AC_MSG_CHECKING(
-                                   [whether xattr_handler->get() wants inode])
--                              ZFS_LINUX_TRY_COMPILE([
--                                      #include <linux/xattr.h>
--
--                                      int get(struct inode *ip, const char *name,
--                                          void *buffer, size_t size) { return 0; }
--                                      static const struct xattr_handler
--                                          xops __attribute__ ((unused)) = {
--                                              .get = get,
--                                      };
--                              ],[
--                              ],[
-+                              ZFS_LINUX_TEST_RESULT(
-+                                  [xattr_handler_get_inode], [
-                                       AC_MSG_RESULT(yes)
-                                       AC_DEFINE(HAVE_XATTR_GET_INODE, 1,
-                                           [xattr_handler->get() wants inode])
-                               ],[
--                                      AC_MSG_ERROR([no; please file a bug report])
-+                                      ZFS_LINUX_TEST_ERROR([xattr get()])
-                               ])
-                       ])
-               ])
-@@ -187,14 +177,8 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_GET], [
- dnl #
- dnl # Supported xattr handler set() interfaces checked newest to oldest.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [
--      dnl #
--      dnl # 4.7 API change,
--      dnl # The xattr_handler->set() callback was changed to take both
--      dnl # dentry and inode.
--      dnl #
--      AC_MSG_CHECKING([whether xattr_handler->set() wants both dentry and inode])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_SET], [
-+      ZFS_LINUX_TEST_SRC([xattr_handler_set_dentry_inode], [
-               #include <linux/xattr.h>
-               int set(const struct xattr_handler *handler,
-@@ -206,8 +190,54 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [
-                   xops __attribute__ ((unused)) = {
-                       .set = set,
-               };
--      ],[
--      ],[
-+      ],[])
-+
-+      ZFS_LINUX_TEST_SRC([xattr_handler_set_xattr_handler], [
-+              #include <linux/xattr.h>
-+
-+              int set(const struct xattr_handler *handler,
-+                  struct dentry *dentry, const char *name,
-+                  const void *buffer, size_t size, int flags)
-+                  { return 0; }
-+              static const struct xattr_handler
-+                  xops __attribute__ ((unused)) = {
-+                      .set = set,
-+              };
-+      ],[])
-+
-+      ZFS_LINUX_TEST_SRC([xattr_handler_set_dentry], [
-+              #include <linux/xattr.h>
-+
-+              int set(struct dentry *dentry, const char *name,
-+                  const void *buffer, size_t size, int flags,
-+                  int handler_flags) { return 0; }
-+              static const struct xattr_handler
-+                  xops __attribute__ ((unused)) = {
-+                      .set = set,
-+              };
-+      ],[])
-+
-+      ZFS_LINUX_TEST_SRC([xattr_handler_set_inode], [
-+              #include <linux/xattr.h>
-+
-+              int set(struct inode *ip, const char *name,
-+                  const void *buffer, size_t size, int flags)
-+                  { return 0; }
-+              static const struct xattr_handler
-+                  xops __attribute__ ((unused)) = {
-+                      .set = set,
-+              };
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [
-+      dnl #
-+      dnl # 4.7 API change,
-+      dnl # The xattr_handler->set() callback was changed to take both
-+      dnl # dentry and inode.
-+      dnl #
-+      AC_MSG_CHECKING([whether xattr_handler->set() wants dentry and inode])
-+      ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry_inode], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_XATTR_SET_DENTRY_INODE, 1,
-                   [xattr_handler->set() wants both dentry and inode])
-@@ -219,71 +249,40 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [
-               dnl # should be accessed by handler->flags.
-               dnl #
-               AC_MSG_RESULT(no)
--              AC_MSG_CHECKING([whether xattr_handler->set() wants xattr_handler])
--              ZFS_LINUX_TRY_COMPILE([
--                      #include <linux/xattr.h>
--
--                      int set(const struct xattr_handler *handler,
--                          struct dentry *dentry, const char *name,
--                          const void *buffer, size_t size, int flags)
--                          { return 0; }
--                      static const struct xattr_handler
--                          xops __attribute__ ((unused)) = {
--                              .set = set,
--                      };
--              ],[
--              ],[
-+              AC_MSG_CHECKING(
-+                  [whether xattr_handler->set() wants xattr_handler])
-+              ZFS_LINUX_TEST_RESULT([xattr_handler_set_xattr_handler], [
-                       AC_MSG_RESULT(yes)
-                       AC_DEFINE(HAVE_XATTR_SET_HANDLER, 1,
-                           [xattr_handler->set() wants xattr_handler])
-               ],[
-                       dnl #
-                       dnl # 2.6.33 API change,
--                      dnl # The xattr_handler->set() callback was changed to take a
--                      dnl # dentry instead of an inode, and a handler_flags
--                      dnl # argument was added.
-+                      dnl # The xattr_handler->set() callback was changed
-+                      dnl # to take a dentry instead of an inode, and a
-+                      dnl # handler_flags argument was added.
-                       dnl #
-                       AC_MSG_RESULT(no)
--                      AC_MSG_CHECKING([whether xattr_handler->set() wants dentry])
--                      ZFS_LINUX_TRY_COMPILE([
--                              #include <linux/xattr.h>
--
--                              int set(struct dentry *dentry, const char *name,
--                                  const void *buffer, size_t size, int flags,
--                                  int handler_flags) { return 0; }
--                              static const struct xattr_handler
--                                  xops __attribute__ ((unused)) = {
--                                      .set = set,
--                              };
--                      ],[
--                      ],[
-+                      AC_MSG_CHECKING(
-+                          [whether xattr_handler->set() wants dentry])
-+                      ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry], [
-                               AC_MSG_RESULT(yes)
-                               AC_DEFINE(HAVE_XATTR_SET_DENTRY, 1,
-                                   [xattr_handler->set() wants dentry])
-                       ],[
-                               dnl #
--                              dnl # 2.6.32 API
-+                              dnl # Legacy 2.6.32 API
-                               dnl #
-                               AC_MSG_RESULT(no)
-                               AC_MSG_CHECKING(
-                                   [whether xattr_handler->set() wants inode])
--                              ZFS_LINUX_TRY_COMPILE([
--                                      #include <linux/xattr.h>
--
--                                      int set(struct inode *ip, const char *name,
--                                          const void *buffer, size_t size, int flags)
--                                          { return 0; }
--                                      static const struct xattr_handler
--                                          xops __attribute__ ((unused)) = {
--                                              .set = set,
--                                      };
--                              ],[
--                              ],[
-+                              ZFS_LINUX_TEST_RESULT(
-+                                  [xattr_handler_set_inode], [
-                                       AC_MSG_RESULT(yes)
-                                       AC_DEFINE(HAVE_XATTR_SET_INODE, 1,
-                                           [xattr_handler->set() wants inode])
-                               ],[
--                                      AC_MSG_ERROR([no; please file a bug report])
-+                                      ZFS_LINUX_TEST_ERROR([xattr set()])
-                               ])
-                       ])
-               ])
-@@ -293,12 +292,8 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [
- dnl #
- dnl # Supported xattr handler list() interfaces checked newest to oldest.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_LIST], [
--      dnl # 4.5 API change,
--      dnl # The xattr_handler->list() callback was changed to take only a
--      dnl # dentry and it only needs to return if it's accessible.
--      AC_MSG_CHECKING([whether xattr_handler->list() wants simple])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_LIST], [
-+      ZFS_LINUX_TEST_SRC([xattr_handler_list_simple], [
-               #include <linux/xattr.h>
-               bool list(struct dentry *dentry) { return 0; }
-@@ -306,8 +301,52 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_LIST], [
-                   xops __attribute__ ((unused)) = {
-                       .list = list,
-               };
--      ],[
--      ],[
-+      ],[])
-+
-+      ZFS_LINUX_TEST_SRC([xattr_handler_list_xattr_handler], [
-+              #include <linux/xattr.h>
-+
-+              size_t list(const struct xattr_handler *handler,
-+                  struct dentry *dentry, char *list, size_t list_size,
-+                  const char *name, size_t name_len) { return 0; }
-+              static const struct xattr_handler
-+                  xops __attribute__ ((unused)) = {
-+                      .list = list,
-+              };
-+      ],[])
-+
-+      ZFS_LINUX_TEST_SRC([xattr_handler_list_dentry], [
-+              #include <linux/xattr.h>
-+
-+              size_t list(struct dentry *dentry,
-+                  char *list, size_t list_size,
-+                  const char *name, size_t name_len,
-+                  int handler_flags) { return 0; }
-+              static const struct xattr_handler
-+                  xops __attribute__ ((unused)) = {
-+                      .list = list,
-+              };
-+      ],[])
-+
-+      ZFS_LINUX_TEST_SRC([xattr_handler_list_inode], [
-+              #include <linux/xattr.h>
-+
-+              size_t list(struct inode *ip, char *lst,
-+                  size_t list_size, const char *name,
-+                  size_t name_len) { return 0; }
-+              static const struct xattr_handler
-+                  xops __attribute__ ((unused)) = {
-+                      .list = list,
-+              };
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_LIST], [
-+      dnl # 4.5 API change,
-+      dnl # The xattr_handler->list() callback was changed to take only a
-+      dnl # dentry and it only needs to return if it's accessible.
-+      AC_MSG_CHECKING([whether xattr_handler->list() wants simple])
-+      ZFS_LINUX_TEST_RESULT([xattr_handler_list_simple], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_XATTR_LIST_SIMPLE, 1,
-                   [xattr_handler->list() wants simple])
-@@ -321,18 +360,7 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_LIST], [
-               AC_MSG_RESULT(no)
-               AC_MSG_CHECKING(
-                   [whether xattr_handler->list() wants xattr_handler])
--              ZFS_LINUX_TRY_COMPILE([
--                      #include <linux/xattr.h>
--
--                      size_t list(const struct xattr_handler *handler,
--                          struct dentry *dentry, char *list, size_t list_size,
--                          const char *name, size_t name_len) { return 0; }
--                      static const struct xattr_handler
--                          xops __attribute__ ((unused)) = {
--                              .list = list,
--                      };
--              ],[
--              ],[
-+              ZFS_LINUX_TEST_RESULT([xattr_handler_list_xattr_handler], [
-                       AC_MSG_RESULT(yes)
-                       AC_DEFINE(HAVE_XATTR_LIST_HANDLER, 1,
-                           [xattr_handler->list() wants xattr_handler])
-@@ -346,47 +374,24 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_LIST], [
-                       AC_MSG_RESULT(no)
-                       AC_MSG_CHECKING(
-                           [whether xattr_handler->list() wants dentry])
--                      ZFS_LINUX_TRY_COMPILE([
--                              #include <linux/xattr.h>
--
--                              size_t list(struct dentry *dentry,
--                                  char *list, size_t list_size,
--                                  const char *name, size_t name_len,
--                                  int handler_flags) { return 0; }
--                              static const struct xattr_handler
--                                  xops __attribute__ ((unused)) = {
--                                      .list = list,
--                              };
--                      ],[
--                      ],[
-+                      ZFS_LINUX_TEST_RESULT([xattr_handler_list_dentry], [
-                               AC_MSG_RESULT(yes)
-                               AC_DEFINE(HAVE_XATTR_LIST_DENTRY, 1,
-                                   [xattr_handler->list() wants dentry])
-                       ],[
-                               dnl #
--                              dnl # 2.6.32 API
-+                              dnl # Legacy 2.6.32 API
-                               dnl #
-                               AC_MSG_RESULT(no)
-                               AC_MSG_CHECKING(
-                                   [whether xattr_handler->list() wants inode])
--                              ZFS_LINUX_TRY_COMPILE([
--                                      #include <linux/xattr.h>
--
--                                      size_t list(struct inode *ip, char *lst,
--                                          size_t list_size, const char *name,
--                                          size_t name_len) { return 0; }
--                                      static const struct xattr_handler
--                                          xops __attribute__ ((unused)) = {
--                                              .list = list,
--                                      };
--                              ],[
--                              ],[
-+                              ZFS_LINUX_TEST_RESULT(
-+                                  [xattr_handler_list_inode], [
-                                       AC_MSG_RESULT(yes)
-                                       AC_DEFINE(HAVE_XATTR_LIST_INODE, 1,
-                                           [xattr_handler->list() wants inode])
-                               ],[
--                                      AC_MSG_ERROR(
--                                          [no; please file a bug report])
-+                                      ZFS_LINUX_TEST_ERROR([xattr list()])
-                               ])
-                       ])
-               ])
-@@ -398,15 +403,19 @@ dnl # 3.7 API change,
- dnl # The posix_acl_{from,to}_xattr functions gained a new
- dnl # parameter: user_ns
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_FROM_XATTR_USERNS], [
--      AC_MSG_CHECKING([whether posix_acl_from_xattr() needs user_ns])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_POSIX_ACL_FROM_XATTR_USERNS], [
-+      ZFS_LINUX_TEST_SRC([posix_acl_from_xattr_userns], [
-               #include <linux/cred.h>
-               #include <linux/fs.h>
-               #include <linux/posix_acl_xattr.h>
-       ],[
-               posix_acl_from_xattr(&init_user_ns, NULL, 0);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_FROM_XATTR_USERNS], [
-+      AC_MSG_CHECKING([whether posix_acl_from_xattr() needs user_ns])
-+      ZFS_LINUX_TEST_RESULT([posix_acl_from_xattr_userns], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_POSIX_ACL_FROM_XATTR_USERNS, 1,
-                   [posix_acl_from_xattr() needs user_ns])
-@@ -415,3 +424,50 @@ AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_FROM_XATTR_USERNS], [
-       ])
- ])
-+dnl #
-+dnl # 4.9 API change,
-+dnl # iops->{set,get,remove}xattr and generic_{set,get,remove}xattr are
-+dnl # removed. xattr operations will directly go through sb->s_xattr.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_SETXATTR], [
-+      ZFS_LINUX_TEST_SRC([have_generic_setxattr], [
-+              #include <linux/fs.h>
-+              #include <linux/xattr.h>
-+
-+              static const struct inode_operations
-+                  iops __attribute__ ((unused)) = {
-+                      .setxattr = generic_setxattr
-+              };
-+      ],[])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_GENERIC_SETXATTR], [
-+      AC_MSG_CHECKING([whether generic_setxattr() exists])
-+      ZFS_LINUX_TEST_RESULT([have_generic_setxattr], [
-+              AC_MSG_RESULT(yes)
-+              AC_DEFINE(HAVE_GENERIC_SETXATTR, 1,
-+                  [generic_setxattr() exists])
-+      ],[
-+              AC_MSG_RESULT(no)
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR], [
-+      ZFS_AC_KERNEL_SRC_CONST_XATTR_HANDLER
-+      ZFS_AC_KERNEL_SRC_XATTR_HANDLER_NAME
-+      ZFS_AC_KERNEL_SRC_XATTR_HANDLER_GET
-+      ZFS_AC_KERNEL_SRC_XATTR_HANDLER_SET
-+      ZFS_AC_KERNEL_SRC_XATTR_HANDLER_LIST
-+      ZFS_AC_KERNEL_SRC_POSIX_ACL_FROM_XATTR_USERNS
-+      ZFS_AC_KERNEL_SRC_GENERIC_SETXATTR
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_XATTR], [
-+      ZFS_AC_KERNEL_CONST_XATTR_HANDLER
-+      ZFS_AC_KERNEL_XATTR_HANDLER_NAME
-+      ZFS_AC_KERNEL_XATTR_HANDLER_GET
-+      ZFS_AC_KERNEL_XATTR_HANDLER_SET
-+      ZFS_AC_KERNEL_XATTR_HANDLER_LIST
-+      ZFS_AC_KERNEL_POSIX_ACL_FROM_XATTR_USERNS
-+      ZFS_AC_KERNEL_GENERIC_SETXATTR
-+])
-diff --git a/config/kernel-zlib.m4 b/config/kernel-zlib.m4
-index 3ca7cf682..d554d1168 100644
---- a/config/kernel-zlib.m4
-+++ b/config/kernel-zlib.m4
-@@ -1,62 +1,25 @@
--dnl #
--dnl # zlib inflate compat,
--dnl # Verify the kernel has CONFIG_ZLIB_INFLATE support enabled.
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_CONFIG_ZLIB_INFLATE], [
--      AC_MSG_CHECKING([whether CONFIG_ZLIB_INFLATE is defined])
--      ZFS_LINUX_TRY_COMPILE([
--              #if !defined(CONFIG_ZLIB_INFLATE) && \
--                  !defined(CONFIG_ZLIB_INFLATE_MODULE)
--              #error CONFIG_ZLIB_INFLATE not defined
--              #endif
--      ],[ ],[
--              AC_MSG_RESULT([yes])
--      ],[
--              AC_MSG_RESULT([no])
--              AC_MSG_ERROR([
--      *** This kernel does not include the required zlib inflate support.
--      *** Rebuild the kernel with CONFIG_ZLIB_INFLATE=y|m set.])
--      ])
--])
--
--dnl #
--dnl # zlib deflate compat,
--dnl # Verify the kernel has CONFIG_ZLIB_DEFLATE support enabled.
--dnl #
--AC_DEFUN([ZFS_AC_KERNEL_CONFIG_ZLIB_DEFLATE], [
--      AC_MSG_CHECKING([whether CONFIG_ZLIB_DEFLATE is defined])
--      ZFS_LINUX_TRY_COMPILE([
--              #if !defined(CONFIG_ZLIB_DEFLATE) && \
--                  !defined(CONFIG_ZLIB_DEFLATE_MODULE)
--              #error CONFIG_ZLIB_DEFLATE not defined
--              #endif
--      ],[ ],[
--              AC_MSG_RESULT([yes])
--      ],[
--              AC_MSG_RESULT([no])
--              AC_MSG_ERROR([
--      *** This kernel does not include the required zlib deflate support.
--      *** Rebuild the kernel with CONFIG_ZLIB_DEFLATE=y|m set.])
--      ])
--])
--
- dnl #
- dnl # 2.6.39 API compat,
-+dnl
- dnl # The function zlib_deflate_workspacesize() now take 2 arguments.
- dnl # This was done to avoid always having to allocate the maximum size
- dnl # workspace (268K).  The caller can now specific the windowBits and
- dnl # memLevel compression parameters to get a smaller workspace.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE],
--      [AC_MSG_CHECKING([whether zlib_deflate_workspacesize() wants 2 args])
--      ZFS_LINUX_TRY_COMPILE([
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE], [
-+      ZFS_LINUX_TEST_SRC([2args_zlib_deflate_workspacesize], [
-               #include <linux/zlib.h>
-       ],[
-               return zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL);
--      ],[
-+      ])
-+])
-+
-+AC_DEFUN([ZFS_AC_KERNEL_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE], [
-+      AC_MSG_CHECKING([whether zlib_deflate_workspacesize() wants 2 args])
-+      ZFS_LINUX_TEST_RESULT([2args_zlib_deflate_workspacesize], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE, 1,
--                        [zlib_deflate_workspacesize() wants 2 args])
-+                  [zlib_deflate_workspacesize() wants 2 args])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-diff --git a/config/kernel.m4 b/config/kernel.m4
-index 8e89c8014..b22a00cdd 100644
---- a/config/kernel.m4
-+++ b/config/kernel.m4
-@@ -2,111 +2,217 @@ dnl #
- dnl # Default ZFS kernel configuration
- dnl #
- AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
-+      dnl # Setup the kernel build environment.
-       ZFS_AC_KERNEL
-       ZFS_AC_QAT
--      ZFS_AC_KERNEL_ACCESS_OK_TYPE
--      ZFS_AC_TEST_MODULE
-+
-+      dnl # Sanity checks for module building and CONFIG_* defines
-+      ZFS_AC_KERNEL_TEST_MODULE
-+      ZFS_AC_KERNEL_CONFIG_DEFINED
-+
-+      dnl # Sequential ZFS_LINUX_TRY_COMPILE tests
-+      ZFS_AC_KERNEL_FPU_HEADER
-+      ZFS_AC_KERNEL_WAIT_QUEUE_ENTRY_T
-       ZFS_AC_KERNEL_MISC_MINOR
-+      ZFS_AC_KERNEL_DECLARE_EVENT_CLASS
-+
-+      dnl # Parallel ZFS_LINUX_TEST_SRC / ZFS_LINUX_TEST_RESULT tests
-+      ZFS_AC_KERNEL_TEST_SRC
-+      ZFS_AC_KERNEL_TEST_RESULT
-+
-+      AS_IF([test "$LINUX_OBJ" != "$LINUX"], [
-+              KERNEL_MAKE="$KERNEL_MAKE O=$LINUX_OBJ"
-+      ])
-+
-+      AC_SUBST(KERNEL_MAKE)
-+])
-+
-+dnl #
-+dnl # Generate and compile all of the kernel API test cases to determine
-+dnl # which interfaces are available.  By invoking the kernel build system
-+dnl # only once the compilation can be done in parallel significantly
-+dnl # speeding up the process.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
-+      ZFS_AC_KERNEL_SRC_OBJTOOL
-+      ZFS_AC_KERNEL_SRC_GLOBAL_PAGE_STATE
-+      ZFS_AC_KERNEL_SRC_ACCESS_OK_TYPE
-+      ZFS_AC_KERNEL_SRC_CTL_NAME
-+      ZFS_AC_KERNEL_SRC_PDE_DATA
-+      ZFS_AC_KERNEL_SRC_FALLOCATE
-+      ZFS_AC_KERNEL_SRC_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE
-+      ZFS_AC_KERNEL_SRC_RWSEM
-+      ZFS_AC_KERNEL_SRC_SCHED
-+      ZFS_AC_KERNEL_SRC_USLEEP_RANGE
-+      ZFS_AC_KERNEL_SRC_KMEM_CACHE
-+      ZFS_AC_KERNEL_SRC_WAIT
-+      ZFS_AC_KERNEL_SRC_INODE_TIMES
-+      ZFS_AC_KERNEL_SRC_INODE_LOCK
-+      ZFS_AC_KERNEL_SRC_GROUP_INFO_GID
-+      ZFS_AC_KERNEL_SRC_RW
-+      ZFS_AC_KERNEL_SRC_TIMER_SETUP
-+      ZFS_AC_KERNEL_SRC_CURRENT_BIO_TAIL
-+      ZFS_AC_KERNEL_SRC_SUPER_USER_NS
-+      ZFS_AC_KERNEL_SRC_SUBMIT_BIO
-+      ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS
-+      ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH
-+      ZFS_AC_KERNEL_SRC_BLKDEV_REREAD_PART
-+      ZFS_AC_KERNEL_SRC_INVALIDATE_BDEV
-+      ZFS_AC_KERNEL_SRC_LOOKUP_BDEV
-+      ZFS_AC_KERNEL_SRC_BDEV_OPEN_EXCLUSIVE
-+      ZFS_AC_KERNEL_SRC_BDEV_LOGICAL_BLOCK_SIZE
-+      ZFS_AC_KERNEL_SRC_BDEV_PHYSICAL_BLOCK_SIZE
-+      ZFS_AC_KERNEL_SRC_BIO_BVEC_ITER
-+      ZFS_AC_KERNEL_SRC_BIO_FAILFAST
-+      ZFS_AC_KERNEL_SRC_BIO_SET_DEV
-+      ZFS_AC_KERNEL_SRC_BIO_OPS
-+      ZFS_AC_KERNEL_SRC_BIO_END_IO_T_ARGS
-+      ZFS_AC_KERNEL_SRC_BIO_BI_STATUS
-+      ZFS_AC_KERNEL_SRC_BIO_RW_BARRIER
-+      ZFS_AC_KERNEL_SRC_BIO_RW_DISCARD
-+      ZFS_AC_KERNEL_SRC_BLK_QUEUE_BDI
-+      ZFS_AC_KERNEL_SRC_BLK_QUEUE_DISCARD
-+      ZFS_AC_KERNEL_SRC_BLK_QUEUE_SECURE_ERASE
-+      ZFS_AC_KERNEL_SRC_BLK_QUEUE_FLAGS
-+      ZFS_AC_KERNEL_SRC_BLK_QUEUE_FLUSH
-+      ZFS_AC_KERNEL_SRC_BLK_QUEUE_MAX_HW_SECTORS
-+      ZFS_AC_KERNEL_SRC_BLK_QUEUE_MAX_SEGMENTS
-+      ZFS_AC_KERNEL_SRC_BLK_QUEUE_PLUG
-+      ZFS_AC_KERNEL_SRC_GET_DISK_AND_MODULE
-+      ZFS_AC_KERNEL_SRC_GET_DISK_RO
-+      ZFS_AC_KERNEL_SRC_GENERIC_READLINK_GLOBAL
-+      ZFS_AC_KERNEL_SRC_DISCARD_GRANULARITY
-+      ZFS_AC_KERNEL_SRC_INODE_OWNER_OR_CAPABLE
-+      ZFS_AC_KERNEL_SRC_XATTR
-+      ZFS_AC_KERNEL_SRC_ACL
-+      ZFS_AC_KERNEL_SRC_INODE_GETATTR
-+      ZFS_AC_KERNEL_SRC_INODE_SET_FLAGS
-+      ZFS_AC_KERNEL_SRC_INODE_SET_IVERSION
-+      ZFS_AC_KERNEL_SRC_SHOW_OPTIONS
-+      ZFS_AC_KERNEL_SRC_FILE_INODE
-+      ZFS_AC_KERNEL_SRC_FILE_DENTRY
-+      ZFS_AC_KERNEL_SRC_FSYNC
-+      ZFS_AC_KERNEL_SRC_AIO_FSYNC
-+      ZFS_AC_KERNEL_SRC_EVICT_INODE
-+      ZFS_AC_KERNEL_SRC_DIRTY_INODE
-+      ZFS_AC_KERNEL_SRC_SHRINKER
-+      ZFS_AC_KERNEL_SRC_MKDIR_UMODE_T
-+      ZFS_AC_KERNEL_SRC_LOOKUP_NAMEIDATA
-+      ZFS_AC_KERNEL_SRC_CREATE_NAMEIDATA
-+      ZFS_AC_KERNEL_SRC_GET_LINK
-+      ZFS_AC_KERNEL_SRC_PUT_LINK
-+      ZFS_AC_KERNEL_SRC_TMPFILE
-+      ZFS_AC_KERNEL_SRC_TRUNCATE_RANGE
-+      ZFS_AC_KERNEL_SRC_AUTOMOUNT
-+      ZFS_AC_KERNEL_SRC_ENCODE_FH_WITH_INODE
-+      ZFS_AC_KERNEL_SRC_COMMIT_METADATA
-+      ZFS_AC_KERNEL_SRC_CLEAR_INODE
-+      ZFS_AC_KERNEL_SRC_SETATTR_PREPARE
-+      ZFS_AC_KERNEL_SRC_INSERT_INODE_LOCKED
-+      ZFS_AC_KERNEL_SRC_DENTRY
-+      ZFS_AC_KERNEL_SRC_TRUNCATE_SETSIZE
-+      ZFS_AC_KERNEL_SRC_SECURITY_INODE
-+      ZFS_AC_KERNEL_SRC_FST_MOUNT
-+      ZFS_AC_KERNEL_SRC_BDI
-+      ZFS_AC_KERNEL_SRC_SET_NLINK
-+      ZFS_AC_KERNEL_SRC_ELEVATOR_CHANGE
-+      ZFS_AC_KERNEL_SRC_SGET
-+      ZFS_AC_KERNEL_SRC_LSEEK_EXECUTE
-+      ZFS_AC_KERNEL_SRC_VFS_GETATTR
-+      ZFS_AC_KERNEL_SRC_VFS_FSYNC_2ARGS
-+      ZFS_AC_KERNEL_SRC_VFS_ITERATE
-+      ZFS_AC_KERNEL_SRC_VFS_DIRECT_IO
-+      ZFS_AC_KERNEL_SRC_VFS_RW_ITERATE
-+      ZFS_AC_KERNEL_SRC_VFS_GENERIC_WRITE_CHECKS
-+      ZFS_AC_KERNEL_SRC_KMAP_ATOMIC_ARGS
-+      ZFS_AC_KERNEL_SRC_FOLLOW_DOWN_ONE
-+      ZFS_AC_KERNEL_SRC_MAKE_REQUEST_FN
-+      ZFS_AC_KERNEL_SRC_GENERIC_IO_ACCT
-+      ZFS_AC_KERNEL_SRC_FPU
-+      ZFS_AC_KERNEL_SRC_FMODE_T
-+      ZFS_AC_KERNEL_SRC_KUIDGID_T
-+      ZFS_AC_KERNEL_SRC_KUID_HELPERS
-+      ZFS_AC_KERNEL_SRC_MODULE_PARAM_CALL_CONST
-+      ZFS_AC_KERNEL_SRC_RENAME_WANTS_FLAGS
-+      ZFS_AC_KERNEL_SRC_CURRENT_TIME
-+      ZFS_AC_KERNEL_SRC_USERNS_CAPABILITIES
-+      ZFS_AC_KERNEL_SRC_IN_COMPAT_SYSCALL
-+      ZFS_AC_KERNEL_SRC_KTIME_GET_COARSE_REAL_TS64
-+      ZFS_AC_KERNEL_SRC_TOTALRAM_PAGES_FUNC
-+      ZFS_AC_KERNEL_SRC_TOTALHIGH_PAGES
-+      ZFS_AC_KERNEL_SRC_KSTRTOUL
-+
-+      AC_MSG_CHECKING([for available kernel interfaces])
-+      ZFS_LINUX_TEST_COMPILE_ALL([kabi])
-+      AC_MSG_RESULT([done])
-+])
-+
-+dnl #
-+dnl # Check results of kernel interface tests.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
-+      ZFS_AC_KERNEL_ACCESS_OK_TYPE
-+      ZFS_AC_KERNEL_GLOBAL_PAGE_STATE
-       ZFS_AC_KERNEL_OBJTOOL
--      ZFS_AC_KERNEL_CONFIG
-       ZFS_AC_KERNEL_CTL_NAME
-       ZFS_AC_KERNEL_PDE_DATA
--      ZFS_AC_KERNEL_2ARGS_VFS_FSYNC
--      ZFS_AC_KERNEL_KUIDGID_T
-       ZFS_AC_KERNEL_FALLOCATE
-       ZFS_AC_KERNEL_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE
--      ZFS_AC_KERNEL_RWSEM_SPINLOCK_IS_RAW
--      ZFS_AC_KERNEL_RWSEM_ACTIVITY
--      ZFS_AC_KERNEL_RWSEM_ATOMIC_LONG_COUNT
--      ZFS_AC_KERNEL_SCHED_RT_HEADER
--      ZFS_AC_KERNEL_SCHED_SIGNAL_HEADER
--      ZFS_AC_KERNEL_IO_SCHEDULE_TIMEOUT
--      ZFS_AC_KERNEL_4ARGS_VFS_GETATTR
--      ZFS_AC_KERNEL_3ARGS_VFS_GETATTR
--      ZFS_AC_KERNEL_2ARGS_VFS_GETATTR
-+      ZFS_AC_KERNEL_RWSEM
-+      ZFS_AC_KERNEL_SCHED
-       ZFS_AC_KERNEL_USLEEP_RANGE
--      ZFS_AC_KERNEL_KMEM_CACHE_ALLOCFLAGS
--      ZFS_AC_KERNEL_KMEM_CACHE_CREATE_USERCOPY
--      ZFS_AC_KERNEL_WAIT_ON_BIT
--      ZFS_AC_KERNEL_WAIT_QUEUE_ENTRY_T
--      ZFS_AC_KERNEL_WAIT_QUEUE_HEAD_ENTRY
-+      ZFS_AC_KERNEL_KMEM_CACHE
-+      ZFS_AC_KERNEL_WAIT
-       ZFS_AC_KERNEL_INODE_TIMES
-       ZFS_AC_KERNEL_INODE_LOCK
-       ZFS_AC_KERNEL_GROUP_INFO_GID
--      ZFS_AC_KERNEL_WRITE
--      ZFS_AC_KERNEL_READ
-+      ZFS_AC_KERNEL_RW
-       ZFS_AC_KERNEL_TIMER_SETUP
--      ZFS_AC_KERNEL_DECLARE_EVENT_CLASS
-       ZFS_AC_KERNEL_CURRENT_BIO_TAIL
-       ZFS_AC_KERNEL_SUPER_USER_NS
-       ZFS_AC_KERNEL_SUBMIT_BIO
--      ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS
--      ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID
--      ZFS_AC_KERNEL_TYPE_FMODE_T
-+      ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS
-       ZFS_AC_KERNEL_BLKDEV_GET_BY_PATH
-       ZFS_AC_KERNEL_BLKDEV_REREAD_PART
--      ZFS_AC_KERNEL_OPEN_BDEV_EXCLUSIVE
-+      ZFS_AC_KERNEL_INVALIDATE_BDEV
-       ZFS_AC_KERNEL_LOOKUP_BDEV
--      ZFS_AC_KERNEL_INVALIDATE_BDEV_ARGS
-+      ZFS_AC_KERNEL_BDEV_OPEN_EXCLUSIVE
-       ZFS_AC_KERNEL_BDEV_LOGICAL_BLOCK_SIZE
-       ZFS_AC_KERNEL_BDEV_PHYSICAL_BLOCK_SIZE
-       ZFS_AC_KERNEL_BIO_BVEC_ITER
--      ZFS_AC_KERNEL_BIO_FAILFAST_DTD
-+      ZFS_AC_KERNEL_BIO_FAILFAST
-       ZFS_AC_KERNEL_BIO_SET_DEV
--      ZFS_AC_KERNEL_REQ_FAILFAST_MASK
--      ZFS_AC_KERNEL_REQ_OP_DISCARD
--      ZFS_AC_KERNEL_REQ_OP_SECURE_ERASE
--      ZFS_AC_KERNEL_REQ_OP_FLUSH
--      ZFS_AC_KERNEL_BIO_BI_OPF
-+      ZFS_AC_KERNEL_BIO_OPS
-       ZFS_AC_KERNEL_BIO_END_IO_T_ARGS
-       ZFS_AC_KERNEL_BIO_BI_STATUS
-       ZFS_AC_KERNEL_BIO_RW_BARRIER
-       ZFS_AC_KERNEL_BIO_RW_DISCARD
-       ZFS_AC_KERNEL_BLK_QUEUE_BDI
--      ZFS_AC_KERNEL_BLK_QUEUE_FLAG_CLEAR
--      ZFS_AC_KERNEL_BLK_QUEUE_FLAG_SET
-+      ZFS_AC_KERNEL_BLK_QUEUE_DISCARD
-+      ZFS_AC_KERNEL_BLK_QUEUE_SECURE_ERASE
-+      ZFS_AC_KERNEL_BLK_QUEUE_FLAGS
-       ZFS_AC_KERNEL_BLK_QUEUE_FLUSH
-       ZFS_AC_KERNEL_BLK_QUEUE_MAX_HW_SECTORS
-       ZFS_AC_KERNEL_BLK_QUEUE_MAX_SEGMENTS
--      ZFS_AC_KERNEL_BLK_QUEUE_HAVE_BIO_RW_UNPLUG
--      ZFS_AC_KERNEL_BLK_QUEUE_HAVE_BLK_PLUG
-+      ZFS_AC_KERNEL_BLK_QUEUE_PLUG
-       ZFS_AC_KERNEL_GET_DISK_AND_MODULE
-       ZFS_AC_KERNEL_GET_DISK_RO
--      ZFS_AC_KERNEL_HAVE_BIO_SET_OP_ATTRS
-       ZFS_AC_KERNEL_GENERIC_READLINK_GLOBAL
-       ZFS_AC_KERNEL_DISCARD_GRANULARITY
--      ZFS_AC_KERNEL_CONST_XATTR_HANDLER
--      ZFS_AC_KERNEL_XATTR_HANDLER_NAME
--      ZFS_AC_KERNEL_XATTR_HANDLER_GET
--      ZFS_AC_KERNEL_XATTR_HANDLER_SET
--      ZFS_AC_KERNEL_XATTR_HANDLER_LIST
-       ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE
--      ZFS_AC_KERNEL_POSIX_ACL_FROM_XATTR_USERNS
--      ZFS_AC_KERNEL_POSIX_ACL_RELEASE
--      ZFS_AC_KERNEL_SET_CACHED_ACL_USABLE
--      ZFS_AC_KERNEL_POSIX_ACL_CHMOD
--      ZFS_AC_KERNEL_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T
--      ZFS_AC_KERNEL_POSIX_ACL_VALID_WITH_NS
--      ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION
--      ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA
--      ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL
--      ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS
--      ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL
--      ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL
--      ZFS_AC_KERNEL_INODE_OPERATIONS_GETATTR
-+      ZFS_AC_KERNEL_XATTR
-+      ZFS_AC_KERNEL_ACL
-+      ZFS_AC_KERNEL_INODE_GETATTR
-       ZFS_AC_KERNEL_INODE_SET_FLAGS
-       ZFS_AC_KERNEL_INODE_SET_IVERSION
--      ZFS_AC_KERNEL_GET_ACL_HANDLE_CACHE
-       ZFS_AC_KERNEL_SHOW_OPTIONS
-       ZFS_AC_KERNEL_FILE_INODE
-       ZFS_AC_KERNEL_FILE_DENTRY
-       ZFS_AC_KERNEL_FSYNC
--      ZFS_AC_KERNEL_EVICT_INODE
--      ZFS_AC_KERNEL_DIRTY_INODE_WITH_FLAGS
--      ZFS_AC_KERNEL_NR_CACHED_OBJECTS
--      ZFS_AC_KERNEL_FREE_CACHED_OBJECTS
--      ZFS_AC_KERNEL_FALLOCATE
-       ZFS_AC_KERNEL_AIO_FSYNC
-+      ZFS_AC_KERNEL_EVICT_INODE
-+      ZFS_AC_KERNEL_DIRTY_INODE
-+      ZFS_AC_KERNEL_SHRINKER
-       ZFS_AC_KERNEL_MKDIR_UMODE_T
-       ZFS_AC_KERNEL_LOOKUP_NAMEIDATA
-       ZFS_AC_KERNEL_CREATE_NAMEIDATA
-@@ -120,58 +226,38 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
-       ZFS_AC_KERNEL_CLEAR_INODE
-       ZFS_AC_KERNEL_SETATTR_PREPARE
-       ZFS_AC_KERNEL_INSERT_INODE_LOCKED
--      ZFS_AC_KERNEL_D_MAKE_ROOT
--      ZFS_AC_KERNEL_D_OBTAIN_ALIAS
--      ZFS_AC_KERNEL_D_PRUNE_ALIASES
--      ZFS_AC_KERNEL_D_SET_D_OP
--      ZFS_AC_KERNEL_D_REVALIDATE_NAMEIDATA
--      ZFS_AC_KERNEL_CONST_DENTRY_OPERATIONS
-+      ZFS_AC_KERNEL_DENTRY
-       ZFS_AC_KERNEL_TRUNCATE_SETSIZE
--      ZFS_AC_KERNEL_6ARGS_SECURITY_INODE_INIT_SECURITY
--      ZFS_AC_KERNEL_CALLBACK_SECURITY_INODE_INIT_SECURITY
-+      ZFS_AC_KERNEL_SECURITY_INODE
-       ZFS_AC_KERNEL_FST_MOUNT
--      ZFS_AC_KERNEL_SHRINK
--      ZFS_AC_KERNEL_SHRINK_CONTROL_HAS_NID
--      ZFS_AC_KERNEL_SHRINK_CONTROL_STRUCT
--      ZFS_AC_KERNEL_SHRINKER_CALLBACK
--      ZFS_AC_KERNEL_S_INSTANCES_LIST_HEAD
--      ZFS_AC_KERNEL_S_D_OP
-       ZFS_AC_KERNEL_BDI
-       ZFS_AC_KERNEL_SET_NLINK
-       ZFS_AC_KERNEL_ELEVATOR_CHANGE
--      ZFS_AC_KERNEL_5ARG_SGET
-+      ZFS_AC_KERNEL_SGET
-       ZFS_AC_KERNEL_LSEEK_EXECUTE
-+      ZFS_AC_KERNEL_VFS_GETATTR
-+      ZFS_AC_KERNEL_VFS_FSYNC_2ARGS
-       ZFS_AC_KERNEL_VFS_ITERATE
--      ZFS_AC_KERNEL_VFS_RW_ITERATE
-       ZFS_AC_KERNEL_VFS_DIRECT_IO
--      ZFS_AC_KERNEL_GENERIC_WRITE_CHECKS
-+      ZFS_AC_KERNEL_VFS_RW_ITERATE
-+      ZFS_AC_KERNEL_VFS_GENERIC_WRITE_CHECKS
-       ZFS_AC_KERNEL_KMAP_ATOMIC_ARGS
-       ZFS_AC_KERNEL_FOLLOW_DOWN_ONE
-       ZFS_AC_KERNEL_MAKE_REQUEST_FN
--      ZFS_AC_KERNEL_GENERIC_IO_ACCT_3ARG
--      ZFS_AC_KERNEL_GENERIC_IO_ACCT_4ARG
-+      ZFS_AC_KERNEL_GENERIC_IO_ACCT
-       ZFS_AC_KERNEL_FPU
-+      ZFS_AC_KERNEL_FMODE_T
-+      ZFS_AC_KERNEL_KUIDGID_T
-       ZFS_AC_KERNEL_KUID_HELPERS
-       ZFS_AC_KERNEL_MODULE_PARAM_CALL_CONST
-       ZFS_AC_KERNEL_RENAME_WANTS_FLAGS
--      ZFS_AC_KERNEL_HAVE_GENERIC_SETXATTR
-       ZFS_AC_KERNEL_CURRENT_TIME
--      ZFS_AC_KERNEL_GLOBAL_PAGE_STATE
--      ZFS_AC_KERNEL_ACL_HAS_REFCOUNT
-       ZFS_AC_KERNEL_USERNS_CAPABILITIES
-       ZFS_AC_KERNEL_IN_COMPAT_SYSCALL
-       ZFS_AC_KERNEL_KTIME_GET_COARSE_REAL_TS64
-       ZFS_AC_KERNEL_TOTALRAM_PAGES_FUNC
-       ZFS_AC_KERNEL_TOTALHIGH_PAGES
--      ZFS_AC_KERNEL_BLK_QUEUE_DISCARD
--      ZFS_AC_KERNEL_BLK_QUEUE_SECURE_ERASE
-       ZFS_AC_KERNEL_KSTRTOUL
--
--      AS_IF([test "$LINUX_OBJ" != "$LINUX"], [
--              KERNEL_MAKE="$KERNEL_MAKE O=$LINUX_OBJ"
--      ])
--
--      AC_SUBST(KERNEL_MAKE)
- ])
- dnl #
-@@ -190,9 +276,10 @@ AC_DEFUN([ZFS_AC_MODULE_SYMVERS], [
-               AS_IF([test ! -f "$LINUX_OBJ/$LINUX_SYMBOLS"], [
-                       AC_MSG_ERROR([
-       *** Please make sure the kernel devel package for your distribution
--      *** is installed.  If you are building with a custom kernel, make sure the
--      *** kernel is configured, built, and the '--with-linux=PATH' configure
--      *** option refers to the location of the kernel source.])
-+      *** is installed.  If you are building with a custom kernel, make sure
-+      *** the kernel is configured, built, and the '--with-linux=PATH'
-+      *** configure option refers to the location of the kernel source.
-+                      ])
-               ])
-       ], [
-               LINUX_SYMBOLS=NONE
-@@ -285,12 +372,16 @@ AC_DEFUN([ZFS_AC_KERNEL], [
-               AS_IF([test -z "$kernsrcver"], [
-                       AC_MSG_RESULT([Not found])
--                      AC_MSG_ERROR([*** Cannot determine kernel version.])
-+                      AC_MSG_ERROR([
-+      *** Cannot determine kernel version.
-+                      ])
-               ])
-       ], [
-               AC_MSG_RESULT([Not found])
-               if test "x$enable_linux_builtin" != xyes; then
--                      AC_MSG_ERROR([*** Cannot find UTS_RELEASE definition.])
-+                      AC_MSG_ERROR([
-+      *** Cannot find UTS_RELEASE definition.
-+                      ])
-               else
-                       AC_MSG_ERROR([
-       *** Cannot find UTS_RELEASE definition.
-@@ -312,24 +403,27 @@ AC_DEFUN([ZFS_AC_KERNEL], [
- ])
- dnl #
--dnl # Detect the QAT module to be built against
--dnl # QAT provides hardware acceleration for data compression:
--dnl #         https://01.org/intel-quickassist-technology
--dnl # * Download and install QAT driver from the above link
--dnl # * Start QAT driver in your system:
--dnl #         service qat_service start
--dnl # * Enable QAT in ZFS, e.g.:
--dnl #         ./configure --with-qat=<qat-driver-path>/QAT1.6
--dnl # make
--dnl # * Set GZIP compression in ZFS dataset:
--dnl #         zfs set compression = gzip <dataset>
--dnl # Then the data written to this ZFS pool is compressed
--dnl # by QAT accelerator automatically, and de-compressed by
--dnl # QAT when read from the pool.
--dnl # * Get QAT hardware statistics by:
--dnl # cat /proc/icp_dh895xcc_dev/qat
--dnl # * To disable QAT:
--dnl #         insmod zfs.ko zfs_qat_disable=1
-+dnl # Detect the QAT module to be built against, QAT provides hardware
-+dnl # acceleration for data compression:
-+dnl #
-+dnl # https://01.org/intel-quickassist-technology
-+dnl #
-+dnl # 1) Download and install QAT driver from the above link
-+dnl # 2) Start QAT driver in your system:
-+dnl #          service qat_service start
-+dnl # 3) Enable QAT in ZFS, e.g.:
-+dnl #          ./configure --with-qat=<qat-driver-path>/QAT1.6
-+dnl #          make
-+dnl # 4) Set GZIP compression in ZFS dataset:
-+dnl #          zfs set compression = gzip <dataset>
-+dnl #
-+dnl # Then the data written to this ZFS pool is compressed by QAT accelerator
-+dnl # automatically, and de-compressed by QAT when read from the pool.
-+dnl #
-+dnl # 1) Get QAT hardware statistics with:
-+dnl #  cat /proc/icp_dh895xcc_dev/qat
-+dnl # 2) To disable QAT:
-+dnl #          insmod zfs.ko zfs_qat_disable=1
- dnl #
- AC_DEFUN([ZFS_AC_QAT], [
-       AC_ARG_WITH([qat],
-@@ -350,11 +444,11 @@ AC_DEFUN([ZFS_AC_QAT], [
-               QAT_SRC="${qatsrc}/quickassist"
-               AS_IF([ test ! -e "$QAT_SRC/include/cpa.h"], [
-                       AC_MSG_ERROR([
--              *** Please make sure the qat driver package is installed
--              *** and specify the location of the qat source with the
--              *** '--with-qat=PATH' option then try again. Failed to
--              *** find cpa.h in:
--              ${QAT_SRC}/include])
-+      *** Please make sure the qat driver package is installed
-+      *** and specify the location of the qat source with the
-+      *** '--with-qat=PATH' option then try again. Failed to
-+      *** find cpa.h in:
-+      ${QAT_SRC}/include])
-               ])
-       ])
-@@ -368,9 +462,9 @@ AC_DEFUN([ZFS_AC_QAT], [
-               QAT_OBJ=${qatbuild}
-               AS_IF([ ! test -e "$QAT_OBJ/icp_qa_al.ko" && ! test -e "$QAT_OBJ/qat_api.ko"], [
-                       AC_MSG_ERROR([
--              *** Please make sure the qat driver is installed then try again.
--              *** Failed to find icp_qa_al.ko or qat_api.ko in:
--              $QAT_OBJ])
-+      *** Please make sure the qat driver is installed then try again.
-+      *** Failed to find icp_qa_al.ko or qat_api.ko in:
-+      $QAT_OBJ])
-               ])
-               AC_SUBST(QAT_SRC)
-@@ -391,10 +485,10 @@ AC_DEFUN([ZFS_AC_QAT], [
-                       AC_MSG_RESULT([$QAT_SYMBOLS])
-                       AC_SUBST(QAT_SYMBOLS)
-               ],[
--                       AC_MSG_ERROR([
--                      *** Please make sure the qat driver is installed then try again.
--                      *** Failed to find Module.symvers in:
--                      $QAT_SYMBOLS])
-+                      AC_MSG_ERROR([
-+      *** Please make sure the qat driver is installed then try again.
-+      *** Failed to find Module.symvers in:
-+      $QAT_SYMBOLS
-                       ])
-               ])
-       ])
-@@ -403,14 +497,16 @@ AC_DEFUN([ZFS_AC_QAT], [
- dnl #
- dnl # Basic toolchain sanity check.
- dnl #
--AC_DEFUN([ZFS_AC_TEST_MODULE], [
-+AC_DEFUN([ZFS_AC_KERNEL_TEST_MODULE], [
-       AC_MSG_CHECKING([whether modules can be built])
--      ZFS_LINUX_TRY_COMPILE([],[],[
-+      ZFS_LINUX_TRY_COMPILE([], [], [
-               AC_MSG_RESULT([yes])
-       ],[
-               AC_MSG_RESULT([no])
-               if test "x$enable_linux_builtin" != xyes; then
--                      AC_MSG_ERROR([*** Unable to build an empty module.])
-+                      AC_MSG_ERROR([
-+      *** Unable to build an empty module.
-+                      ])
-               else
-                       AC_MSG_ERROR([
-       *** Unable to build an empty module.
-@@ -420,207 +516,313 @@ AC_DEFUN([ZFS_AC_TEST_MODULE], [
- ])
- dnl #
--dnl # Certain kernel build options are not supported.  These must be
--dnl # detected at configure time and cause a build failure.  Otherwise
--dnl # modules may be successfully built that behave incorrectly.
-+dnl # ZFS_LINUX_CONFTEST_H
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_CONFIG], [
--      AS_IF([test "x$cross_compiling" != xyes], [
--              AC_RUN_IFELSE([
--                      AC_LANG_PROGRAM([
--                              #include "$LINUX/include/linux/license.h"
--                      ], [
--                              return !license_is_gpl_compatible("$ZFS_META_LICENSE");
--                      ])
--              ], [
--                      AC_DEFINE([ZFS_IS_GPL_COMPATIBLE], [1],
--                          [Define to 1 if GPL-only symbols can be used])
--              ], [
--              ])
--      ])
-+AC_DEFUN([ZFS_LINUX_CONFTEST_H], [
-+test -d build/$2 || mkdir -p build/$2
-+cat - <<_ACEOF >build/$2/$2.h
-+$1
-+_ACEOF
-+])
--      ZFS_AC_KERNEL_CONFIG_THREAD_SIZE
--      ZFS_AC_KERNEL_CONFIG_DEBUG_LOCK_ALLOC
--      ZFS_AC_KERNEL_CONFIG_TRIM_UNUSED_KSYMS
--      ZFS_AC_KERNEL_CONFIG_ZLIB_INFLATE
--      ZFS_AC_KERNEL_CONFIG_ZLIB_DEFLATE
-+dnl #
-+dnl # ZFS_LINUX_CONFTEST_C
-+dnl #
-+AC_DEFUN([ZFS_LINUX_CONFTEST_C], [
-+test -d build/$2 || mkdir -p build/$2
-+cat confdefs.h - <<_ACEOF >build/$2/$2.c
-+$1
-+_ACEOF
- ])
- dnl #
--dnl # Check configured THREAD_SIZE
-+dnl # ZFS_LINUX_CONFTEST_MAKEFILE
- dnl #
--dnl # The stack size will vary by architecture, but as of Linux 3.15 on x86_64
--dnl # the default thread stack size was increased to 16K from 8K.  Therefore,
--dnl # on newer kernels and some architectures stack usage optimizations can be
--dnl # conditionally applied to improve performance without negatively impacting
--dnl # stability.
-+dnl # $1 - test case name
-+dnl # $2 - add to top-level Makefile
-+dnl # $3 - additional build flags
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_CONFIG_THREAD_SIZE], [
--      AC_MSG_CHECKING([whether kernel was built with 16K or larger stacks])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/module.h>
--      ],[
--              #if (THREAD_SIZE < 16384)
--              #error "THREAD_SIZE is less than 16K"
--              #endif
--      ],[
--              AC_MSG_RESULT([yes])
--              AC_DEFINE(HAVE_LARGE_STACKS, 1, [kernel has large stacks])
--      ],[
--              AC_MSG_RESULT([no])
--      ])
-+AC_DEFUN([ZFS_LINUX_CONFTEST_MAKEFILE], [
-+      test -d build || mkdir -p build
-+      test -d build/$1 || mkdir -p build/$1
-+
-+      file=build/$1/Makefile
-+
-+      dnl # Example command line to manually build source.
-+      cat - <<_ACEOF >$file
-+# Example command line to manually build source
-+# make modules -C $LINUX_OBJ $ARCH_UM M=$PWD/build/$1
-+
-+ccflags-y := -Werror $FRAME_LARGER_THAN
-+_ACEOF
-+
-+      dnl # Additional custom CFLAGS as requested.
-+      m4_ifval($3, [echo "ccflags-y += $3" >>$file], [])
-+
-+      dnl # Test case source
-+      echo "obj-m := $1.o" >>$file
-+
-+      AS_IF([test "x$2" = "xyes"], [echo "obj-m += $1/" >>build/Makefile], [])
- ])
- dnl #
--dnl # Check CONFIG_DEBUG_LOCK_ALLOC
-+dnl # ZFS_LINUX_TEST_PROGRAM(C)([PROLOGUE], [BODY])
- dnl #
--dnl # This is typically only set for debug kernels because it comes with
--dnl # a performance penalty.  However, when it is set it maps the non-GPL
--dnl # symbol mutex_lock() to the GPL-only mutex_lock_nested() symbol.
--dnl # This will cause a failure at link time which we'd rather know about
--dnl # at compile time.
-+m4_define([ZFS_LINUX_TEST_PROGRAM], [
-+$1
-+int
-+main (void)
-+{
-+$2
-+      ;
-+      return 0;
-+}
-+])
-+
- dnl #
--dnl # Since we plan to pursue making mutex_lock_nested() a non-GPL symbol
--dnl # with the upstream community we add a check to detect this case.
-+dnl # ZFS_LINUX_TEST_REMOVE
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_CONFIG_DEBUG_LOCK_ALLOC], [
--
--      ZFS_LINUX_CONFIG([DEBUG_LOCK_ALLOC], [
--              AC_MSG_CHECKING([whether mutex_lock() is GPL-only])
--              tmp_flags="$EXTRA_KCFLAGS"
--              ZFS_LINUX_TRY_COMPILE([
--                      #include <linux/module.h>
--                      #include <linux/mutex.h>
--
--                      MODULE_LICENSE("$ZFS_META_LICENSE");
--              ],[
--                      struct mutex lock;
-+dnl # Removes the specified test source and results.
-+dnl #
-+AC_DEFUN([ZFS_LINUX_TEST_REMOVE], [
-+      test -d build/$1 && rm -Rf build/$1
-+      test -f build/Makefile && sed '/$1/d' build/Makefile
-+])
--                      mutex_init(&lock);
--                      mutex_lock(&lock);
--                      mutex_unlock(&lock);
--              ],[
--                      AC_MSG_RESULT(no)
--              ],[
--                      AC_MSG_RESULT(yes)
--                      AC_MSG_ERROR([
--      *** Kernel built with CONFIG_DEBUG_LOCK_ALLOC which is incompatible
--      *** with the CDDL license and will prevent the module linking stage
--      *** from succeeding.  You must rebuild your kernel without this
--      *** option enabled.])
--              ])
--              EXTRA_KCFLAGS="$tmp_flags"
--      ], [])
-+dnl #
-+dnl # ZFS_LINUX_COMPILE
-+dnl #
-+dnl # $1 - build dir
-+dnl # $2 - test command
-+dnl # $3 - pass command
-+dnl # $4 - fail command
-+dnl # $5 - set KBUILD_MODPOST_NOFINAL='yes'
-+dnl # $6 - set KBUILD_MODPOST_WARN='yes'
-+dnl #
-+dnl # Used internally by ZFS_LINUX_TEST_{COMPILE,MODPOST}
-+dnl #
-+AC_DEFUN([ZFS_LINUX_COMPILE], [
-+      AC_TRY_COMMAND([
-+          KBUILD_MODPOST_NOFINAL="$5" KBUILD_MODPOST_WARN="$6"
-+          make modules -k -j$TEST_JOBS -C $LINUX_OBJ $ARCH_UM
-+          M=$PWD/$1 &>$1/build.log])
-+      AS_IF([AC_TRY_COMMAND([$2])], [$3], [$4])
- ])
- dnl #
--dnl # Check CONFIG_TRIM_UNUSED_KSYMS
-+dnl # ZFS_LINUX_TEST_COMPILE
- dnl #
--dnl # Verify the kernel has CONFIG_TRIM_UNUSED_KSYMS disabled.
-+dnl # Perform a full compile excluding the final modpost phase.
- dnl #
--AC_DEFUN([ZFS_AC_KERNEL_CONFIG_TRIM_UNUSED_KSYMS], [
--      AC_MSG_CHECKING([whether CONFIG_TRIM_UNUSED_KSYM is disabled])
--      ZFS_LINUX_TRY_COMPILE([
--              #if defined(CONFIG_TRIM_UNUSED_KSYMS)
--              #error CONFIG_TRIM_UNUSED_KSYMS not defined
--              #endif
--      ],[ ],[
--              AC_MSG_RESULT([yes])
-+AC_DEFUN([ZFS_LINUX_TEST_COMPILE], [
-+      ZFS_LINUX_COMPILE([$2], [test -f $2/build.log], [
-+              mv $2/Makefile $2/Makefile.compile.$1
-+              mv $2/build.log $2/build.log.$1
-       ],[
--              AC_MSG_RESULT([no])
--              AS_IF([test "x$enable_linux_builtin" != xyes], [
--                      AC_MSG_ERROR([
--      *** This kernel has unused symbols trimming enabled, please disable.
--      *** Rebuild the kernel with CONFIG_TRIM_UNUSED_KSYMS=n set.])
--      ])])
-+              AC_MSG_ERROR([
-+        *** Unable to compile test source to determine kernel interfaces.])
-+      ], [yes], [])
- ])
- dnl #
--dnl # ZFS_LINUX_CONFTEST_H
-+dnl # ZFS_LINUX_TEST_MODPOST
- dnl #
--AC_DEFUN([ZFS_LINUX_CONFTEST_H], [
--cat - <<_ACEOF >conftest.h
--$1
--_ACEOF
-+dnl # Perform a full compile including the modpost phase.  This may
-+dnl # be an incremental build if the objects have already been built.
-+dnl #
-+AC_DEFUN([ZFS_LINUX_TEST_MODPOST], [
-+      ZFS_LINUX_COMPILE([$2], [test -f $2/build.log], [
-+              mv $2/Makefile $2/Makefile.modpost.$1
-+              cat $2/build.log >>build/build.log.$1
-+      ],[
-+              AC_MSG_ERROR([
-+        *** Unable to modpost test source to determine kernel interfaces.])
-+      ], [], [yes])
- ])
- dnl #
--dnl # ZFS_LINUX_CONFTEST_C
-+dnl # Perform the compilation of the test cases in two phases.
- dnl #
--AC_DEFUN([ZFS_LINUX_CONFTEST_C], [
--cat confdefs.h - <<_ACEOF >conftest.c
--$1
--_ACEOF
-+dnl # Phase 1) attempt to build the object files for all of the tests
-+dnl #          defined by the ZFS_LINUX_TEST_SRC macro.  But do not
-+dnl #          perform the final modpost stage.
-+dnl #
-+dnl # Phase 2) disable all tests which failed the initial compilation,
-+dnl #          then invoke the final modpost step for the remaining tests.
-+dnl #
-+dnl # This allows us efficiently build the test cases in parallel while
-+dnl # remaining resilient to build failures which are expected when
-+dnl # detecting the available kernel interfaces.
-+dnl #
-+dnl # The maximum allowed parallelism can be controlled by setting the
-+dnl # TEST_JOBS environment variable.  Otherwise, it default to $(nproc).
-+dnl #
-+AC_DEFUN([ZFS_LINUX_TEST_COMPILE_ALL], [
-+      dnl # Phase 1 - Compilation only, final linking is skipped.
-+      ZFS_LINUX_TEST_COMPILE([$1], [build])
-+
-+      dnl #
-+      dnl # Phase 2 - When building external modules disable test cases
-+      dnl # which failed to compile and invoke modpost to verify the
-+      dnl # final linking.
-+      dnl #
-+      dnl # Test names suffixed with '_license' call modpost independently
-+      dnl # to ensure that a single incompatibility does not result in the
-+      dnl # modpost phase exiting early.  This check is not performed on
-+      dnl # every symbol since the majority are compatible and doing so
-+      dnl # would significantly slow down this phase.
-+      dnl #
-+      dnl # When configuring for builtin (--enable-linux-builtin)
-+      dnl # fake the linking step artificially create the expected .ko
-+      dnl # files for tests which did compile.  This is required for
-+      dnl # kernels which do not have loadable module support or have
-+      dnl # not yet been built.
-+      dnl #
-+      AS_IF([test "x$enable_linux_builtin" = "xno"], [
-+              for dir in $(awk '/^obj-m/ { print [$]3 }' \
-+                  build/Makefile.compile.$1); do
-+                      name=${dir%/}
-+                      AS_IF([test -f build/$name/$name.o], [
-+                              AS_IF([test "${name##*_}" = "license"], [
-+                                      ZFS_LINUX_TEST_MODPOST([$1],
-+                                          [build/$name])
-+                                      echo "obj-n += $dir" >>build/Makefile
-+                              ], [
-+                                      echo "obj-m += $dir" >>build/Makefile
-+                              ])
-+                      ], [
-+                              echo "obj-n += $dir" >>build/Makefile
-+                      ])
-+              done
-+
-+              ZFS_LINUX_TEST_MODPOST([$1], [build])
-+      ], [
-+              for dir in $(awk '/^obj-m/ { print [$]3 }' \
-+                  build/Makefile.compile.$1); do
-+                      name=${dir%/}
-+                      AS_IF([test -f build/$name/$name.o], [
-+                              touch build/$name/$name.ko
-+                      ])
-+              done
-+      ])
- ])
- dnl #
--dnl # ZFS_LANG_PROGRAM(C)([PROLOGUE], [BODY])
-+dnl # ZFS_LINUX_TEST_SRC
- dnl #
--m4_define([ZFS_LANG_PROGRAM], [
--$1
--int
--main (void)
--{
--dnl Do *not* indent the following line: there may be CPP directives.
--dnl Don't move the `;' right after for the same reason.
--$2
--  ;
--  return 0;
--}
-+dnl # $1 - name
-+dnl # $2 - global
-+dnl # $3 - source
-+dnl # $4 - extra cflags
-+dnl # $5 - check license-compatibility
-+dnl #
-+dnl # N.B because all of the test cases are compiled in parallel they
-+dnl # must never depend on the results of previous tests.  Each test
-+dnl # needs to be entirely independent.
-+dnl #
-+AC_DEFUN([ZFS_LINUX_TEST_SRC], [
-+      ZFS_LINUX_CONFTEST_C([ZFS_LINUX_TEST_PROGRAM([[$2]], [[$3]])], [$1])
-+      ZFS_LINUX_CONFTEST_MAKEFILE([$1], [yes], [$4])
-+
-+      AS_IF([ test -n "$5" ], [
-+              ZFS_LINUX_CONFTEST_C([ZFS_LINUX_TEST_PROGRAM([[
-+                      #include <linux/module.h>
-+                      MODULE_LICENSE("$5");
-+                      $2]], [[$3]])], [$1_license])
-+              ZFS_LINUX_CONFTEST_MAKEFILE([$1_license], [yes], [$4])
-+      ])
- ])
- dnl #
--dnl # ZFS_LINUX_COMPILE_IFELSE / like AC_COMPILE_IFELSE
-+dnl # ZFS_LINUX_TEST_RESULT
- dnl #
--AC_DEFUN([ZFS_LINUX_COMPILE_IFELSE], [
--      m4_ifvaln([$1], [ZFS_LINUX_CONFTEST_C([$1])])
--      m4_ifvaln([$6], [ZFS_LINUX_CONFTEST_H([$6])], [ZFS_LINUX_CONFTEST_H([])])
--      rm -Rf build && mkdir -p build && touch build/conftest.mod.c
--      echo "obj-m := conftest.o" >build/Makefile
--      modpost_flag=''
--      test "x$enable_linux_builtin" = xyes && modpost_flag='modpost=true' # fake modpost stage
--      AS_IF(
--              [AC_TRY_COMMAND(cp conftest.c conftest.h build && make [$2] -C $LINUX_OBJ EXTRA_CFLAGS="-Werror $FRAME_LARGER_THAN $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build $modpost_flag) >/dev/null && AC_TRY_COMMAND([$3])],
--              [$4],
--              [_AC_MSG_LOG_CONFTEST m4_ifvaln([$5],[$5])]
--      )
--      rm -Rf build
-+dnl # $1 - name of a test source (ZFS_LINUX_TEST_SRC)
-+dnl # $2 - run on success (valid .ko generated)
-+dnl # $3 - run on failure (unable to compile)
-+dnl #
-+AC_DEFUN([ZFS_LINUX_TEST_RESULT], [
-+      AS_IF([test -d build/$1], [
-+              AS_IF([test -f build/$1/$1.ko], [$2], [$3])
-+      ], [
-+              AC_MSG_ERROR([
-+      *** No matching source for the "$1" test, check that
-+      *** both the test source and result macros refer to the same name.
-+              ])
-+      ])
- ])
- dnl #
--dnl # ZFS_LINUX_TRY_COMPILE like AC_TRY_COMPILE
-+dnl # ZFS_LINUX_TEST_ERROR
- dnl #
--AC_DEFUN([ZFS_LINUX_TRY_COMPILE],
--      [ZFS_LINUX_COMPILE_IFELSE(
--      [AC_LANG_SOURCE([ZFS_LANG_PROGRAM([[$1]], [[$2]])])],
--      [modules],
--      [test -s build/conftest.o],
--      [$3], [$4])
-+dnl # Generic error message which can be used when none of the expected
-+dnl # kernel interfaces were detected.
-+dnl #
-+AC_DEFUN([ZFS_LINUX_TEST_ERROR], [
-+      AC_MSG_ERROR([
-+      *** None of the expected "$1" interfaces were detected.
-+      *** This may be because your kernel version is newer than what is
-+      *** supported, or you are using a patched custom kernel with
-+      *** incompatible modifications.
-+      ***
-+      *** ZFS Version: $ZFS_META_ALIAS
-+      *** Compatible Kernels: $ZFS_META_KVER_MIN - $ZFS_META_KVER_MAX
-+      ])
- ])
- dnl #
--dnl # ZFS_LINUX_CONFIG
-+dnl # ZFS_LINUX_TEST_RESULT_SYMBOL
- dnl #
--AC_DEFUN([ZFS_LINUX_CONFIG],
--      [AC_MSG_CHECKING([whether kernel was built with CONFIG_$1])
--      ZFS_LINUX_TRY_COMPILE([
--              #include <linux/module.h>
--      ],[
--              #ifndef CONFIG_$1
--              #error CONFIG_$1 not #defined
--              #endif
--      ],[
--              AC_MSG_RESULT([yes])
--              $2
--      ],[
--              AC_MSG_RESULT([no])
--              $3
-+dnl # Like ZFS_LINUX_TEST_RESULT except ZFS_CHECK_SYMBOL_EXPORT is called to
-+dnl # verify symbol exports, unless --enable-linux-builtin was provided to
-+dnl # configure.
-+dnl #
-+AC_DEFUN([ZFS_LINUX_TEST_RESULT_SYMBOL], [
-+      AS_IF([ ! test -f build/$1/$1.ko], [
-+              $5
-+      ], [
-+              AS_IF([test "x$enable_linux_builtin" != "xyes"], [
-+                      ZFS_CHECK_SYMBOL_EXPORT([$2], [$3], [$4], [$5])
-+              ], [
-+                      $4
-+              ])
-       ])
- ])
-+dnl #
-+dnl # ZFS_LINUX_COMPILE_IFELSE
-+dnl #
-+AC_DEFUN([ZFS_LINUX_COMPILE_IFELSE], [
-+      ZFS_LINUX_TEST_REMOVE([conftest])
-+
-+      m4_ifvaln([$1], [ZFS_LINUX_CONFTEST_C([$1], [conftest])])
-+      m4_ifvaln([$5], [ZFS_LINUX_CONFTEST_H([$5], [conftest])],
-+          [ZFS_LINUX_CONFTEST_H([], [conftest])])
-+
-+      ZFS_LINUX_CONFTEST_MAKEFILE([conftest], [no],
-+          [m4_ifvaln([$5], [-I$PWD/build/conftest], [])])
-+      ZFS_LINUX_COMPILE([build/conftest], [$2], [$3], [$4], [], [])
-+])
-+
-+dnl #
-+dnl # ZFS_LINUX_TRY_COMPILE
-+dnl #
-+dnl # $1 - global
-+dnl # $2 - source
-+dnl # $3 - run on success (valid .ko generated)
-+dnl # $4 - run on failure (unable to compile)
-+dnl #
-+AC_DEFUN([ZFS_LINUX_TRY_COMPILE], [
-+      ZFS_LINUX_COMPILE_IFELSE(
-+          [ZFS_LINUX_TEST_PROGRAM([[$1]], [[$2]])],
-+          [test -f build/conftest/conftest.ko],
-+          [$3], [$4])
-+])
-+
- dnl #
- dnl # ZFS_CHECK_SYMBOL_EXPORT
--dnl # check symbol exported or not
-+dnl #
-+dnl # Check if a symbol is exported on not by consulting the symbols
-+dnl # file, or optionally the source code.
- dnl #
- AC_DEFUN([ZFS_CHECK_SYMBOL_EXPORT], [
-       grep -q -E '[[[:space:]]]$1[[[:space:]]]' \
-@@ -649,8 +851,10 @@ AC_DEFUN([ZFS_CHECK_SYMBOL_EXPORT], [
- dnl #
- dnl # ZFS_LINUX_TRY_COMPILE_SYMBOL
--dnl # like ZFS_LINUX_TRY_COMPILE, except ZFS_CHECK_SYMBOL_EXPORT
--dnl # is called if not compiling for builtin
-+dnl #
-+dnl # Like ZFS_LINUX_TRY_COMPILER except ZFS_CHECK_SYMBOL_EXPORT is called
-+dnl # to verify symbol exports, unless --enable-linux-builtin was provided
-+dnl # to configure.
- dnl #
- AC_DEFUN([ZFS_LINUX_TRY_COMPILE_SYMBOL], [
-       ZFS_LINUX_TRY_COMPILE([$1], [$2], [rc=0], [rc=1])
-@@ -673,10 +877,9 @@ dnl # ZFS_LINUX_TRY_COMPILE_HEADER
- dnl # like ZFS_LINUX_TRY_COMPILE, except the contents conftest.h are
- dnl # provided via the fifth parameter
- dnl #
--AC_DEFUN([ZFS_LINUX_TRY_COMPILE_HEADER],
--      [ZFS_LINUX_COMPILE_IFELSE(
--      [AC_LANG_SOURCE([ZFS_LANG_PROGRAM([[$1]], [[$2]])])],
--      [modules],
--      [test -s build/conftest.o],
--      [$3], [$4], [$5])
-+AC_DEFUN([ZFS_LINUX_TRY_COMPILE_HEADER], [
-+      ZFS_LINUX_COMPILE_IFELSE(
-+          [ZFS_LINUX_TEST_PROGRAM([[$1]], [[$2]])],
-+          [test -f build/conftest/conftest.ko],
-+          [$3], [$4], [$5])
- ])
-diff --git a/config/zfs-build.m4 b/config/zfs-build.m4
-index 8e221f2d7..d2c355425 100644
---- a/config/zfs-build.m4
-+++ b/config/zfs-build.m4
-@@ -166,6 +166,17 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS], [
- ])
- AC_DEFUN([ZFS_AC_CONFIG], [
-+
-+        dnl # Remove the previous build test directory.
-+        rm -Rf build
-+
-+      AC_ARG_VAR([TEST_JOBS],
-+          [simultaneous jobs during configure (defaults to $(nproc))])
-+      if test "x$ac_cv_env_TEST_JOBS_set" != "xset"; then
-+              TEST_JOBS=$(nproc)
-+      fi
-+      AC_SUBST(TEST_JOBS)
-+
-       ZFS_CONFIG=all
-       AC_ARG_WITH([config],
-               AS_HELP_STRING([--with-config=CONFIG],
-diff --git a/config/zfs-meta.m4 b/config/zfs-meta.m4
-index f525e2010..660d8ccb9 100644
---- a/config/zfs-meta.m4
-+++ b/config/zfs-meta.m4
-@@ -162,6 +162,24 @@ AC_DEFUN([ZFS_AC_META], [
-                       AC_SUBST([ZFS_META_AUTHOR])
-               fi
-+              ZFS_META_KVER_MIN=_ZFS_AC_META_GETVAL([Linux-Minimum]);
-+              if test -n "$ZFS_META_KVER_MIN"; then
-+                      AC_DEFINE_UNQUOTED([ZFS_META_KVER_MIN],
-+                          ["$ZFS_META_KVER_MIN"],
-+                          [Define the minimum compatible kernel version.]
-+                      )
-+                      AC_SUBST([ZFS_META_KVER_MIN])
-+              fi
-+
-+              ZFS_META_KVER_MAX=_ZFS_AC_META_GETVAL([Linux-Maximum]);
-+              if test -n "$ZFS_META_KVER_MAX"; then
-+                      AC_DEFINE_UNQUOTED([ZFS_META_KVER_MAX],
-+                          ["$ZFS_META_KVER_MAX"],
-+                          [Define the maximum compatible kernel version.]
-+                      )
-+                      AC_SUBST([ZFS_META_KVER_MAX])
-+              fi
-+
-               m4_pattern_allow([^LT_(CURRENT|REVISION|AGE)$])
-               ZFS_META_LT_CURRENT=_ZFS_AC_META_GETVAL([LT_Current]);
-               ZFS_META_LT_REVISION=_ZFS_AC_META_GETVAL([LT_Revision]);
diff --git a/debian/patches/0010-OpenZFS-restructuring-move-platform-specific-headers.patch b/debian/patches/0010-OpenZFS-restructuring-move-platform-specific-headers.patch
new file mode 100644 (file)
index 0000000..553bb53
--- /dev/null
@@ -0,0 +1,2433 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Matthew Macy <mmacy@mattmacy.io>
+Date: Thu, 5 Sep 2019 09:34:54 -0700
+Subject: [PATCH] OpenZFS restructuring - move platform specific headers
+
+Move platform specific Linux headers under include/os/linux/.
+Update the build system accordingly to detect the platform.
+This lays some of the initial groundwork to supporting building
+for other platforms.
+
+As part of this change it was necessary to create both a user
+and kernel space sys/simd.h header which can be included in
+either context.  No functional change, the source has been
+refactored and the relevant #include's updated.
+
+Reviewed-by: Jorgen Lundman <lundman@lundman.net>
+Reviewed-by: Igor Kozhukhov <igor@dilos.org>
+Signed-off-by: Matthew Macy <mmacy@FreeBSD.org>
+Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
+Closes #9198
+(cherry picked from commit 006e9a40882468be68f276c946bae812b74ac35c)
+Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
+---
+ config/always-system.m4                       |  26 +
+ config/zfs-build.m4                           |   1 +
+ configure.ac                                  |  13 +-
+ copy-builtin                                  |   4 +-
+ include/.gitignore                            |   1 +
+ include/Makefile.am                           |   2 +-
+ include/linux/Makefile.am                     |  29 --
+ include/os/Makefile.am                        |   3 +
+ include/os/linux/Makefile.am                  |   1 +
+ include/os/linux/kernel/Makefile.am           |   1 +
+ include/os/linux/kernel/linux/Makefile.am     |  29 ++
+ .../linux/kernel}/linux/blkdev_compat.h       |   0
+ .../linux/kernel}/linux/compiler_compat.h     |   0
+ .../linux/kernel}/linux/dcache_compat.h       |   0
+ .../{ => os/linux/kernel}/linux/kmap_compat.h |   0
+ .../{ => os/linux/kernel}/linux/mod_compat.h  |   0
+ .../{ => os/linux/kernel}/linux/page_compat.h |   0
+ include/{ => os/linux/kernel}/linux/simd.h    |   8 +-
+ .../linux/kernel}/linux/simd_aarch64.h        |  18 +-
+ .../{ => os/linux/kernel}/linux/simd_x86.h    | 357 ++------------
+ .../linux/kernel}/linux/utsname_compat.h      |   0
+ .../{ => os/linux/kernel}/linux/vfs_compat.h  |   0
+ .../linux/kernel}/linux/xattr_compat.h        |   0
+ include/{ => os/linux}/spl/Makefile.am        |   0
+ include/{ => os/linux}/spl/rpc/Makefile.am    |   2 +-
+ include/{ => os/linux}/spl/rpc/xdr.h          |   0
+ include/os/linux/spl/sys/Makefile.am          |  62 +++
+ include/{ => os/linux}/spl/sys/acl.h          |   0
+ include/{ => os/linux}/spl/sys/atomic.h       |   0
+ include/{ => os/linux}/spl/sys/byteorder.h    |   0
+ include/{ => os/linux}/spl/sys/callb.h        |   0
+ include/{ => os/linux}/spl/sys/callo.h        |   0
+ include/{ => os/linux}/spl/sys/cmn_err.h      |   0
+ include/{ => os/linux}/spl/sys/condvar.h      |   0
+ include/{ => os/linux}/spl/sys/console.h      |   0
+ include/{ => os/linux}/spl/sys/cred.h         |   0
+ include/{ => os/linux}/spl/sys/ctype.h        |   0
+ include/{ => os/linux}/spl/sys/debug.h        |   0
+ include/{ => os/linux}/spl/sys/disp.h         |   0
+ include/{ => os/linux}/spl/sys/dkio.h         |   0
+ include/{ => os/linux}/spl/sys/errno.h        |   0
+ include/{ => os/linux}/spl/sys/fcntl.h        |   0
+ include/{ => os/linux}/spl/sys/file.h         |   0
+ include/{ => os/linux}/spl/sys/inttypes.h     |   0
+ include/{ => os/linux}/spl/sys/isa_defs.h     |   0
+ include/{ => os/linux}/spl/sys/kmem.h         |   0
+ include/{ => os/linux}/spl/sys/kmem_cache.h   |   0
+ include/{ => os/linux}/spl/sys/kobj.h         |   0
+ include/{ => os/linux}/spl/sys/kstat.h        |   0
+ include/{ => os/linux}/spl/sys/list.h         |   0
+ include/{ => os/linux}/spl/sys/mode.h         |   0
+ include/{ => os/linux}/spl/sys/mutex.h        |   0
+ include/{ => os/linux}/spl/sys/param.h        |   0
+ include/{ => os/linux}/spl/sys/proc.h         |   0
+ include/{ => os/linux}/spl/sys/processor.h    |   0
+ include/{ => os/linux}/spl/sys/procfs_list.h  |   0
+ include/{ => os/linux}/spl/sys/random.h       |   0
+ include/{ => os/linux}/spl/sys/rwlock.h       |   0
+ include/{ => os/linux}/spl/sys/shrinker.h     |   0
+ include/{ => os/linux}/spl/sys/sid.h          |   0
+ include/{ => os/linux}/spl/sys/signal.h       |   0
+ include/os/linux/spl/sys/simd.h               |  31 ++
+ include/{ => os/linux}/spl/sys/stat.h         |   0
+ include/{ => os/linux}/spl/sys/strings.h      |   0
+ include/{ => os/linux}/spl/sys/sunddi.h       |   0
+ include/{ => os/linux}/spl/sys/sysmacros.h    |   0
+ include/{ => os/linux}/spl/sys/systeminfo.h   |   0
+ include/{ => os/linux}/spl/sys/taskq.h        |   0
+ include/{ => os/linux}/spl/sys/thread.h       |   0
+ include/{ => os/linux}/spl/sys/time.h         |   0
+ include/{ => os/linux}/spl/sys/timer.h        |   0
+ include/{ => os/linux}/spl/sys/tsd.h          |   0
+ include/{ => os/linux}/spl/sys/types.h        |   0
+ include/{ => os/linux}/spl/sys/types32.h      |   0
+ include/{ => os/linux}/spl/sys/uio.h          |   0
+ include/{ => os/linux}/spl/sys/user.h         |   0
+ include/{ => os/linux}/spl/sys/vfs.h          |   0
+ include/{ => os/linux}/spl/sys/vmem.h         |   0
+ include/{ => os/linux}/spl/sys/vmsystm.h      |   0
+ include/{ => os/linux}/spl/sys/vnode.h        |   0
+ include/{ => os/linux}/spl/sys/wait.h         |   0
+ include/{ => os/linux}/spl/sys/zmod.h         |   0
+ include/{ => os/linux}/spl/sys/zone.h         |   0
+ include/os/linux/zfs/Makefile.am              |   1 +
+ include/os/linux/zfs/sys/Makefile.am          |  12 +
+ include/{ => os/linux/zfs}/sys/policy.h       |   0
+ include/{ => os/linux/zfs}/sys/zfs_ctldir.h   |   0
+ include/{ => os/linux/zfs}/sys/zfs_dir.h      |   0
+ include/{ => os/linux/zfs}/sys/zfs_vfsops.h   |   0
+ include/{ => os/linux/zfs}/sys/zfs_vnops.h    |   0
+ include/{ => os/linux/zfs}/sys/zpl.h          |   0
+ include/spl/sys/Makefile.am                   |  61 ---
+ include/sys/Makefile.am                       |   6 -
+ lib/libspl/include/sys/Makefile.am            |   1 +
+ lib/libspl/include/sys/simd.h                 | 448 ++++++++++++++++++
+ module/Makefile.in                            |   4 +-
+ module/icp/algs/aes/aes_impl.c                |   2 +-
+ module/icp/algs/aes/aes_impl_aesni.c          |   3 +-
+ module/icp/algs/aes/aes_impl_x86-64.c         |   2 +-
+ module/icp/algs/modes/gcm.c                   |   2 +-
+ module/icp/algs/modes/gcm_pclmulqdq.c         |   4 +-
+ module/icp/io/aes.c                           |   4 +-
+ module/spl/spl-taskq.c                        |   2 +-
+ module/spl/spl-thread.c                       |   2 +-
+ module/zcommon/zfs_fletcher.c                 |   4 +-
+ module/zcommon/zfs_fletcher_aarch64_neon.c    |   2 +-
+ module/zcommon/zfs_fletcher_avx512.c          |   2 +-
+ module/zcommon/zfs_fletcher_intel.c           |   2 +-
+ module/zcommon/zfs_fletcher_sse.c             |   2 +-
+ module/zfs/vdev_raidz_math.c                  |   2 +-
+ .../zfs/vdev_raidz_math_aarch64_neon_common.h |   2 +-
+ module/zfs/vdev_raidz_math_avx2.c             |   2 +-
+ module/zfs/vdev_raidz_math_avx512bw.c         |   2 +-
+ module/zfs/vdev_raidz_math_avx512f.c          |   2 +-
+ module/zfs/vdev_raidz_math_sse2.c             |   2 +-
+ module/zfs/vdev_raidz_math_ssse3.c            |   2 +-
+ 116 files changed, 699 insertions(+), 469 deletions(-)
+ create mode 100644 config/always-system.m4
+ delete mode 100644 include/linux/Makefile.am
+ create mode 100644 include/os/Makefile.am
+ create mode 100644 include/os/linux/Makefile.am
+ create mode 100644 include/os/linux/kernel/Makefile.am
+ create mode 100644 include/os/linux/kernel/linux/Makefile.am
+ rename include/{ => os/linux/kernel}/linux/blkdev_compat.h (100%)
+ rename include/{ => os/linux/kernel}/linux/compiler_compat.h (100%)
+ rename include/{ => os/linux/kernel}/linux/dcache_compat.h (100%)
+ rename include/{ => os/linux/kernel}/linux/kmap_compat.h (100%)
+ rename include/{ => os/linux/kernel}/linux/mod_compat.h (100%)
+ rename include/{ => os/linux/kernel}/linux/page_compat.h (100%)
+ rename include/{ => os/linux/kernel}/linux/simd.h (92%)
+ rename include/{ => os/linux/kernel}/linux/simd_aarch64.h (79%)
+ rename include/{ => os/linux/kernel}/linux/simd_x86.h (62%)
+ rename include/{ => os/linux/kernel}/linux/utsname_compat.h (100%)
+ rename include/{ => os/linux/kernel}/linux/vfs_compat.h (100%)
+ rename include/{ => os/linux/kernel}/linux/xattr_compat.h (100%)
+ rename include/{ => os/linux}/spl/Makefile.am (100%)
+ rename include/{ => os/linux}/spl/rpc/Makefile.am (72%)
+ rename include/{ => os/linux}/spl/rpc/xdr.h (100%)
+ create mode 100644 include/os/linux/spl/sys/Makefile.am
+ rename include/{ => os/linux}/spl/sys/acl.h (100%)
+ rename include/{ => os/linux}/spl/sys/atomic.h (100%)
+ rename include/{ => os/linux}/spl/sys/byteorder.h (100%)
+ rename include/{ => os/linux}/spl/sys/callb.h (100%)
+ rename include/{ => os/linux}/spl/sys/callo.h (100%)
+ rename include/{ => os/linux}/spl/sys/cmn_err.h (100%)
+ rename include/{ => os/linux}/spl/sys/condvar.h (100%)
+ rename include/{ => os/linux}/spl/sys/console.h (100%)
+ rename include/{ => os/linux}/spl/sys/cred.h (100%)
+ rename include/{ => os/linux}/spl/sys/ctype.h (100%)
+ rename include/{ => os/linux}/spl/sys/debug.h (100%)
+ rename include/{ => os/linux}/spl/sys/disp.h (100%)
+ rename include/{ => os/linux}/spl/sys/dkio.h (100%)
+ rename include/{ => os/linux}/spl/sys/errno.h (100%)
+ rename include/{ => os/linux}/spl/sys/fcntl.h (100%)
+ rename include/{ => os/linux}/spl/sys/file.h (100%)
+ rename include/{ => os/linux}/spl/sys/inttypes.h (100%)
+ rename include/{ => os/linux}/spl/sys/isa_defs.h (100%)
+ rename include/{ => os/linux}/spl/sys/kmem.h (100%)
+ rename include/{ => os/linux}/spl/sys/kmem_cache.h (100%)
+ rename include/{ => os/linux}/spl/sys/kobj.h (100%)
+ rename include/{ => os/linux}/spl/sys/kstat.h (100%)
+ rename include/{ => os/linux}/spl/sys/list.h (100%)
+ rename include/{ => os/linux}/spl/sys/mode.h (100%)
+ rename include/{ => os/linux}/spl/sys/mutex.h (100%)
+ rename include/{ => os/linux}/spl/sys/param.h (100%)
+ rename include/{ => os/linux}/spl/sys/proc.h (100%)
+ rename include/{ => os/linux}/spl/sys/processor.h (100%)
+ rename include/{ => os/linux}/spl/sys/procfs_list.h (100%)
+ rename include/{ => os/linux}/spl/sys/random.h (100%)
+ rename include/{ => os/linux}/spl/sys/rwlock.h (100%)
+ rename include/{ => os/linux}/spl/sys/shrinker.h (100%)
+ rename include/{ => os/linux}/spl/sys/sid.h (100%)
+ rename include/{ => os/linux}/spl/sys/signal.h (100%)
+ create mode 100644 include/os/linux/spl/sys/simd.h
+ rename include/{ => os/linux}/spl/sys/stat.h (100%)
+ rename include/{ => os/linux}/spl/sys/strings.h (100%)
+ rename include/{ => os/linux}/spl/sys/sunddi.h (100%)
+ rename include/{ => os/linux}/spl/sys/sysmacros.h (100%)
+ rename include/{ => os/linux}/spl/sys/systeminfo.h (100%)
+ rename include/{ => os/linux}/spl/sys/taskq.h (100%)
+ rename include/{ => os/linux}/spl/sys/thread.h (100%)
+ rename include/{ => os/linux}/spl/sys/time.h (100%)
+ rename include/{ => os/linux}/spl/sys/timer.h (100%)
+ rename include/{ => os/linux}/spl/sys/tsd.h (100%)
+ rename include/{ => os/linux}/spl/sys/types.h (100%)
+ rename include/{ => os/linux}/spl/sys/types32.h (100%)
+ rename include/{ => os/linux}/spl/sys/uio.h (100%)
+ rename include/{ => os/linux}/spl/sys/user.h (100%)
+ rename include/{ => os/linux}/spl/sys/vfs.h (100%)
+ rename include/{ => os/linux}/spl/sys/vmem.h (100%)
+ rename include/{ => os/linux}/spl/sys/vmsystm.h (100%)
+ rename include/{ => os/linux}/spl/sys/vnode.h (100%)
+ rename include/{ => os/linux}/spl/sys/wait.h (100%)
+ rename include/{ => os/linux}/spl/sys/zmod.h (100%)
+ rename include/{ => os/linux}/spl/sys/zone.h (100%)
+ create mode 100644 include/os/linux/zfs/Makefile.am
+ create mode 100644 include/os/linux/zfs/sys/Makefile.am
+ rename include/{ => os/linux/zfs}/sys/policy.h (100%)
+ rename include/{ => os/linux/zfs}/sys/zfs_ctldir.h (100%)
+ rename include/{ => os/linux/zfs}/sys/zfs_dir.h (100%)
+ rename include/{ => os/linux/zfs}/sys/zfs_vfsops.h (100%)
+ rename include/{ => os/linux/zfs}/sys/zfs_vnops.h (100%)
+ rename include/{ => os/linux/zfs}/sys/zpl.h (100%)
+ delete mode 100644 include/spl/sys/Makefile.am
+ create mode 100644 lib/libspl/include/sys/simd.h
+
+diff --git a/config/always-system.m4 b/config/always-system.m4
+new file mode 100644
+index 000000000..3225a52af
+--- /dev/null
++++ b/config/always-system.m4
+@@ -0,0 +1,26 @@
++dnl #
++dnl # Set the target system
++dnl #
++AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_SYSTEM], [
++      AC_MSG_CHECKING([for system type ($host_os)])
++      case $host_os in
++              *linux*)
++                      AC_DEFINE([SYSTEM_LINUX], [1],
++                              [True if ZFS is to be compiled for a Linux system])
++                      ac_system="Linux"
++                      ;;
++              *freebsd*)
++                      AC_DEFINE([SYSTEM_FREEBSD], [1],
++                              [True if ZFS is to be compiled for a FreeBSD system])
++                      ac_system="FreeBSD"
++                      ;;
++              *)
++                      ac_system="unknown"
++                      ;;
++      esac
++      AC_MSG_RESULT([$ac_system])
++      AC_SUBST([ac_system])
++
++      AM_CONDITIONAL([BUILD_LINUX], [test "x$ac_system" = "xLinux"])
++      AM_CONDITIONAL([BUILD_FREEBSD], [test "x$ac_system" = "xFreeBSD"])
++])
+diff --git a/config/zfs-build.m4 b/config/zfs-build.m4
+index d2c355425..f4cb97689 100644
+--- a/config/zfs-build.m4
++++ b/config/zfs-build.m4
+@@ -160,6 +160,7 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS], [
+       ZFS_AC_CONFIG_ALWAYS_CC_NO_OMIT_FRAME_POINTER
+       ZFS_AC_CONFIG_ALWAYS_CC_ASAN
+       ZFS_AC_CONFIG_ALWAYS_TOOLCHAIN_SIMD
++      ZFS_AC_CONFIG_ALWAYS_SYSTEM
+       ZFS_AC_CONFIG_ALWAYS_ARCH
+       ZFS_AC_CONFIG_ALWAYS_PYTHON
+       ZFS_AC_CONFIG_ALWAYS_PYZFS
+diff --git a/configure.ac b/configure.ac
+index a3ac134ff..4b51118ab 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -145,10 +145,15 @@ AC_CONFIG_FILES([
+       module/icp/Makefile
+       module/spl/Makefile
+       include/Makefile
+-      include/linux/Makefile
+-      include/spl/Makefile
+-      include/spl/rpc/Makefile
+-      include/spl/sys/Makefile
++      include/os/Makefile
++      include/os/linux/Makefile
++      include/os/linux/kernel/Makefile
++      include/os/linux/kernel/linux/Makefile
++      include/os/linux/spl/Makefile
++      include/os/linux/spl/rpc/Makefile
++      include/os/linux/spl/sys/Makefile
++      include/os/linux/zfs/Makefile
++      include/os/linux/zfs/sys/Makefile
+       include/sys/Makefile
+       include/sys/fs/Makefile
+       include/sys/fm/Makefile
+diff --git a/copy-builtin b/copy-builtin
+index 1dcfcb961..adb3bd544 100755
+--- a/copy-builtin
++++ b/copy-builtin
+@@ -62,7 +62,9 @@ EOF
+ {
+       cat <<-"EOF"
+       ZFS_MODULE_CFLAGS  = -I$(srctree)/include/zfs
+-      ZFS_MODULE_CFLAGS += -I$(srctree)/include/zfs/spl
++      ZFS_MODULE_CFLAGS += -I$(srctree)/include/zfs/os/linux/spl
++      ZFS_MODULE_CFLAGS += -I$(srctree)/include/zfs/os/linux/zfs
++      ZFS_MODULE_CFLAGS += -I$(srctree)/include/zfs/os/linux/kernel
+       ZFS_MODULE_CFLAGS += -include $(srctree)/include/zfs/zfs_config.h
+       ZFS_MODULE_CFLAGS += -std=gnu99 -Wno-declaration-after-statement
+       ZFS_MODULE_CPPFLAGS  = -D_KERNEL
+diff --git a/include/.gitignore b/include/.gitignore
+index e6eb2116f..416f36b9e 100644
+--- a/include/.gitignore
++++ b/include/.gitignore
+@@ -1 +1,2 @@
+ /zfs_gitrev.h
++/spl
+diff --git a/include/Makefile.am b/include/Makefile.am
+index bac47d98d..5b37dc765 100644
+--- a/include/Makefile.am
++++ b/include/Makefile.am
+@@ -1,4 +1,4 @@
+-SUBDIRS = linux spl sys
++SUBDIRS = sys os
+ COMMON_H = \
+       $(top_srcdir)/include/zfeature_common.h \
+diff --git a/include/linux/Makefile.am b/include/linux/Makefile.am
+deleted file mode 100644
+index 2455759e8..000000000
+--- a/include/linux/Makefile.am
++++ /dev/null
+@@ -1,29 +0,0 @@
+-COMMON_H =
+-
+-KERNEL_H = \
+-      $(top_srcdir)/include/linux/dcache_compat.h \
+-      $(top_srcdir)/include/linux/xattr_compat.h \
+-      $(top_srcdir)/include/linux/vfs_compat.h \
+-      $(top_srcdir)/include/linux/blkdev_compat.h \
+-      $(top_srcdir)/include/linux/utsname_compat.h \
+-      $(top_srcdir)/include/linux/kmap_compat.h \
+-      $(top_srcdir)/include/linux/simd.h \
+-      $(top_srcdir)/include/linux/simd_x86.h \
+-      $(top_srcdir)/include/linux/simd_aarch64.h \
+-      $(top_srcdir)/include/linux/mod_compat.h \
+-      $(top_srcdir)/include/linux/page_compat.h \
+-      $(top_srcdir)/include/linux/compiler_compat.h
+-
+-USER_H =
+-
+-EXTRA_DIST = $(COMMON_H) $(KERNEL_H) $(USER_H)
+-
+-if CONFIG_USER
+-libzfsdir = $(includedir)/libzfs/linux
+-libzfs_HEADERS = $(COMMON_H) $(USER_H)
+-endif
+-
+-if CONFIG_KERNEL
+-kerneldir = @prefix@/src/zfs-$(VERSION)/include/linux
+-kernel_HEADERS = $(COMMON_H) $(KERNEL_H)
+-endif
+diff --git a/include/os/Makefile.am b/include/os/Makefile.am
+new file mode 100644
+index 000000000..09c0beec4
+--- /dev/null
++++ b/include/os/Makefile.am
+@@ -0,0 +1,3 @@
++if BUILD_LINUX
++SUBDIRS = linux
++endif
+diff --git a/include/os/linux/Makefile.am b/include/os/linux/Makefile.am
+new file mode 100644
+index 000000000..605a1fcb7
+--- /dev/null
++++ b/include/os/linux/Makefile.am
+@@ -0,0 +1 @@
++SUBDIRS = kernel spl zfs
+diff --git a/include/os/linux/kernel/Makefile.am b/include/os/linux/kernel/Makefile.am
+new file mode 100644
+index 000000000..08b2f5fc5
+--- /dev/null
++++ b/include/os/linux/kernel/Makefile.am
+@@ -0,0 +1 @@
++SUBDIRS = linux
+diff --git a/include/os/linux/kernel/linux/Makefile.am b/include/os/linux/kernel/linux/Makefile.am
+new file mode 100644
+index 000000000..06ce7c7aa
+--- /dev/null
++++ b/include/os/linux/kernel/linux/Makefile.am
+@@ -0,0 +1,29 @@
++COMMON_H =
++
++KERNEL_H = \
++      $(top_srcdir)/include/os/linux/kernel/linux/dcache_compat.h \
++      $(top_srcdir)/include/os/linux/kernel/linux/xattr_compat.h \
++      $(top_srcdir)/include/os/linux/kernel/linux/vfs_compat.h \
++      $(top_srcdir)/include/os/linux/kernel/linux/blkdev_compat.h \
++      $(top_srcdir)/include/os/linux/kernel/linux/utsname_compat.h \
++      $(top_srcdir)/include/os/linux/kernel/linux/kmap_compat.h \
++      $(top_srcdir)/include/os/linux/kernel/linux/simd.h \
++      $(top_srcdir)/include/os/linux/kernel/linux/simd_x86.h \
++      $(top_srcdir)/include/os/linux/kernel/linux/simd_aarch64.h \
++      $(top_srcdir)/include/os/linux/kernel/linux/mod_compat.h \
++      $(top_srcdir)/include/os/linux/kernel/linux/page_compat.h \
++      $(top_srcdir)/include/os/linux/kernel/linux/compiler_compat.h
++
++USER_H =
++
++EXTRA_DIST = $(COMMON_H) $(KERNEL_H) $(USER_H)
++
++if CONFIG_USER
++libzfsdir = $(includedir)/libzfs/linux
++libzfs_HEADERS = $(COMMON_H) $(USER_H)
++endif
++
++if CONFIG_KERNEL
++kerneldir = @prefix@/src/zfs-$(VERSION)/include/linux
++kernel_HEADERS = $(COMMON_H) $(KERNEL_H)
++endif
+diff --git a/include/linux/blkdev_compat.h b/include/os/linux/kernel/linux/blkdev_compat.h
+similarity index 100%
+rename from include/linux/blkdev_compat.h
+rename to include/os/linux/kernel/linux/blkdev_compat.h
+diff --git a/include/linux/compiler_compat.h b/include/os/linux/kernel/linux/compiler_compat.h
+similarity index 100%
+rename from include/linux/compiler_compat.h
+rename to include/os/linux/kernel/linux/compiler_compat.h
+diff --git a/include/linux/dcache_compat.h b/include/os/linux/kernel/linux/dcache_compat.h
+similarity index 100%
+rename from include/linux/dcache_compat.h
+rename to include/os/linux/kernel/linux/dcache_compat.h
+diff --git a/include/linux/kmap_compat.h b/include/os/linux/kernel/linux/kmap_compat.h
+similarity index 100%
+rename from include/linux/kmap_compat.h
+rename to include/os/linux/kernel/linux/kmap_compat.h
+diff --git a/include/linux/mod_compat.h b/include/os/linux/kernel/linux/mod_compat.h
+similarity index 100%
+rename from include/linux/mod_compat.h
+rename to include/os/linux/kernel/linux/mod_compat.h
+diff --git a/include/linux/page_compat.h b/include/os/linux/kernel/linux/page_compat.h
+similarity index 100%
+rename from include/linux/page_compat.h
+rename to include/os/linux/kernel/linux/page_compat.h
+diff --git a/include/linux/simd.h b/include/os/linux/kernel/linux/simd.h
+similarity index 92%
+rename from include/linux/simd.h
+rename to include/os/linux/kernel/linux/simd.h
+index d2b60996a..1f6574a90 100644
+--- a/include/linux/simd.h
++++ b/include/os/linux/kernel/linux/simd.h
+@@ -22,8 +22,8 @@
+  * Copyright (C) 2019 Lawrence Livermore National Security, LLC.
+  */
+-#ifndef _SIMD_H
+-#define       _SIMD_H
++#ifndef _LINUX_SIMD_H
++#define       _LINUX_SIMD_H
+ #if defined(__x86)
+ #include <linux/simd_x86.h>
+@@ -32,10 +32,10 @@
+ #include <linux/simd_aarch64.h>
+ #else
+-#define       kfpu_allowed()          1
++#define       kfpu_allowed()          0
+ #define       kfpu_initialize(tsk)    do {} while (0)
+ #define       kfpu_begin()            do {} while (0)
+ #define       kfpu_end()              do {} while (0)
+ #endif
+-#endif /* _SIMD_H */
++#endif /* _LINUX_SIMD_H */
+diff --git a/include/linux/simd_aarch64.h b/include/os/linux/kernel/linux/simd_aarch64.h
+similarity index 79%
+rename from include/linux/simd_aarch64.h
+rename to include/os/linux/kernel/linux/simd_aarch64.h
+index b45d31c48..ac530d920 100644
+--- a/include/linux/simd_aarch64.h
++++ b/include/os/linux/kernel/linux/simd_aarch64.h
+@@ -32,31 +32,21 @@
+  *    kfpu_end()
+  */
+-#ifndef _SIMD_AARCH64_H
+-#define       _SIMD_AARCH64_H
++#ifndef _LINUX_SIMD_AARCH64_H
++#define       _LINUX_SIMD_AARCH64_H
+ #include <sys/isa_defs.h>
+ #if defined(__aarch64__)
+ #include <sys/types.h>
+-
+-#if defined(_KERNEL)
+ #include <asm/neon.h>
++
+ #define       kfpu_allowed()          1
+ #define       kfpu_initialize(tsk)    do {} while (0)
+ #define       kfpu_begin()            kernel_neon_begin()
+ #define       kfpu_end()              kernel_neon_end()
+-#else
+-/*
+- * fpu dummy methods for userspace
+- */
+-#define       kfpu_allowed()          1
+-#define       kfpu_initialize(tsk)    do {} while (0)
+-#define       kfpu_begin()            do {} while (0)
+-#define       kfpu_end()              do {} while (0)
+-#endif /* defined(_KERNEL) */
+ #endif /* __aarch64__ */
+-#endif /* _SIMD_AARCH64_H */
++#endif /* _LINUX_SIMD_AARCH64_H */
+diff --git a/include/linux/simd_x86.h b/include/os/linux/kernel/linux/simd_x86.h
+similarity index 62%
+rename from include/linux/simd_x86.h
+rename to include/os/linux/kernel/linux/simd_x86.h
+index b32bccc41..486e31845 100644
+--- a/include/linux/simd_x86.h
++++ b/include/os/linux/kernel/linux/simd_x86.h
+@@ -66,23 +66,14 @@
+  *                    also add zfs_avx512vl_available() to feature check.
+  */
+-#ifndef _SIMD_X86_H
+-#define       _SIMD_X86_H
+-
+-#include <sys/isa_defs.h>
++#ifndef _LINUX_SIMD_X86_H
++#define       _LINUX_SIMD_X86_H
+ /* only for __x86 */
+ #if defined(__x86)
+ #include <sys/types.h>
+-
+-#if defined(_KERNEL)
+ #include <asm/cpufeature.h>
+-#else
+-#include <cpuid.h>
+-#endif
+-
+-#if defined(_KERNEL)
+ /*
+  * Disable the WARN_ON_FPU() macro to prevent additional dependencies
+@@ -292,185 +283,9 @@ kfpu_end(void)
+ #endif /* defined(HAVE_KERNEL_FPU_INTERNAL) */
+ #endif /* defined(KERNEL_EXPORTS_X86_FPU) */
+-#else /* defined(_KERNEL) */
+ /*
+- * FPU dummy methods for user space.
++ * Linux kernel provides an interface for CPU feature testing.
+  */
+-#define       kfpu_allowed()          1
+-#define       kfpu_initialize(tsk)    do {} while (0)
+-#define       kfpu_begin()            do {} while (0)
+-#define       kfpu_end()              do {} while (0)
+-#endif /* defined(_KERNEL) */
+-
+-/*
+- * CPUID feature tests for user-space. Linux kernel provides an interface for
+- * CPU feature testing.
+- */
+-#if !defined(_KERNEL)
+-
+-/*
+- * x86 registers used implicitly by CPUID
+- */
+-typedef enum cpuid_regs {
+-      EAX = 0,
+-      EBX,
+-      ECX,
+-      EDX,
+-      CPUID_REG_CNT = 4
+-} cpuid_regs_t;
+-
+-/*
+- * List of instruction sets identified by CPUID
+- */
+-typedef enum cpuid_inst_sets {
+-      SSE = 0,
+-      SSE2,
+-      SSE3,
+-      SSSE3,
+-      SSE4_1,
+-      SSE4_2,
+-      OSXSAVE,
+-      AVX,
+-      AVX2,
+-      BMI1,
+-      BMI2,
+-      AVX512F,
+-      AVX512CD,
+-      AVX512DQ,
+-      AVX512BW,
+-      AVX512IFMA,
+-      AVX512VBMI,
+-      AVX512PF,
+-      AVX512ER,
+-      AVX512VL,
+-      AES,
+-      PCLMULQDQ
+-} cpuid_inst_sets_t;
+-
+-/*
+- * Instruction set descriptor.
+- */
+-typedef struct cpuid_feature_desc {
+-      uint32_t leaf;          /* CPUID leaf */
+-      uint32_t subleaf;       /* CPUID sub-leaf */
+-      uint32_t flag;          /* bit mask of the feature */
+-      cpuid_regs_t reg;       /* which CPUID return register to test */
+-} cpuid_feature_desc_t;
+-
+-#define       _AVX512F_BIT            (1U << 16)
+-#define       _AVX512CD_BIT           (_AVX512F_BIT | (1U << 28))
+-#define       _AVX512DQ_BIT           (_AVX512F_BIT | (1U << 17))
+-#define       _AVX512BW_BIT           (_AVX512F_BIT | (1U << 30))
+-#define       _AVX512IFMA_BIT         (_AVX512F_BIT | (1U << 21))
+-#define       _AVX512VBMI_BIT         (1U << 1) /* AVX512F_BIT is on another leaf  */
+-#define       _AVX512PF_BIT           (_AVX512F_BIT | (1U << 26))
+-#define       _AVX512ER_BIT           (_AVX512F_BIT | (1U << 27))
+-#define       _AVX512VL_BIT           (1U << 31) /* if used also check other levels */
+-#define       _AES_BIT                (1U << 25)
+-#define       _PCLMULQDQ_BIT          (1U << 1)
+-
+-/*
+- * Descriptions of supported instruction sets
+- */
+-static const cpuid_feature_desc_t cpuid_features[] = {
+-      [SSE]           = {1U, 0U,      1U << 25,       EDX     },
+-      [SSE2]          = {1U, 0U,      1U << 26,       EDX     },
+-      [SSE3]          = {1U, 0U,      1U << 0,        ECX     },
+-      [SSSE3]         = {1U, 0U,      1U << 9,        ECX     },
+-      [SSE4_1]        = {1U, 0U,      1U << 19,       ECX     },
+-      [SSE4_2]        = {1U, 0U,      1U << 20,       ECX     },
+-      [OSXSAVE]       = {1U, 0U,      1U << 27,       ECX     },
+-      [AVX]           = {1U, 0U,      1U << 28,       ECX     },
+-      [AVX2]          = {7U, 0U,      1U << 5,        EBX     },
+-      [BMI1]          = {7U, 0U,      1U << 3,        EBX     },
+-      [BMI2]          = {7U, 0U,      1U << 8,        EBX     },
+-      [AVX512F]       = {7U, 0U, _AVX512F_BIT,        EBX     },
+-      [AVX512CD]      = {7U, 0U, _AVX512CD_BIT,       EBX     },
+-      [AVX512DQ]      = {7U, 0U, _AVX512DQ_BIT,       EBX     },
+-      [AVX512BW]      = {7U, 0U, _AVX512BW_BIT,       EBX     },
+-      [AVX512IFMA]    = {7U, 0U, _AVX512IFMA_BIT,     EBX     },
+-      [AVX512VBMI]    = {7U, 0U, _AVX512VBMI_BIT,     ECX     },
+-      [AVX512PF]      = {7U, 0U, _AVX512PF_BIT,       EBX     },
+-      [AVX512ER]      = {7U, 0U, _AVX512ER_BIT,       EBX     },
+-      [AVX512VL]      = {7U, 0U, _AVX512ER_BIT,       EBX     },
+-      [AES]           = {1U, 0U, _AES_BIT,            ECX     },
+-      [PCLMULQDQ]     = {1U, 0U, _PCLMULQDQ_BIT,      ECX     },
+-};
+-
+-/*
+- * Check if OS supports AVX and AVX2 by checking XCR0
+- * Only call this function if CPUID indicates that AVX feature is
+- * supported by the CPU, otherwise it might be an illegal instruction.
+- */
+-static inline uint64_t
+-xgetbv(uint32_t index)
+-{
+-      uint32_t eax, edx;
+-      /* xgetbv - instruction byte code */
+-      __asm__ __volatile__(".byte 0x0f; .byte 0x01; .byte 0xd0"
+-          : "=a" (eax), "=d" (edx)
+-          : "c" (index));
+-
+-      return ((((uint64_t)edx)<<32) | (uint64_t)eax);
+-}
+-
+-/*
+- * Check if CPU supports a feature
+- */
+-static inline boolean_t
+-__cpuid_check_feature(const cpuid_feature_desc_t *desc)
+-{
+-      uint32_t r[CPUID_REG_CNT];
+-
+-      if (__get_cpuid_max(0, NULL) >= desc->leaf) {
+-              /*
+-               * __cpuid_count is needed to properly check
+-               * for AVX2. It is a macro, so return parameters
+-               * are passed by value.
+-               */
+-              __cpuid_count(desc->leaf, desc->subleaf,
+-                  r[EAX], r[EBX], r[ECX], r[EDX]);
+-              return ((r[desc->reg] & desc->flag) == desc->flag);
+-      }
+-      return (B_FALSE);
+-}
+-
+-#define       CPUID_FEATURE_CHECK(name, id)                           \
+-static inline boolean_t                                               \
+-__cpuid_has_ ## name(void)                                    \
+-{                                                             \
+-      return (__cpuid_check_feature(&cpuid_features[id]));    \
+-}
+-
+-/*
+- * Define functions for user-space CPUID features testing
+- */
+-CPUID_FEATURE_CHECK(sse, SSE);
+-CPUID_FEATURE_CHECK(sse2, SSE2);
+-CPUID_FEATURE_CHECK(sse3, SSE3);
+-CPUID_FEATURE_CHECK(ssse3, SSSE3);
+-CPUID_FEATURE_CHECK(sse4_1, SSE4_1);
+-CPUID_FEATURE_CHECK(sse4_2, SSE4_2);
+-CPUID_FEATURE_CHECK(avx, AVX);
+-CPUID_FEATURE_CHECK(avx2, AVX2);
+-CPUID_FEATURE_CHECK(osxsave, OSXSAVE);
+-CPUID_FEATURE_CHECK(bmi1, BMI1);
+-CPUID_FEATURE_CHECK(bmi2, BMI2);
+-CPUID_FEATURE_CHECK(avx512f, AVX512F);
+-CPUID_FEATURE_CHECK(avx512cd, AVX512CD);
+-CPUID_FEATURE_CHECK(avx512dq, AVX512DQ);
+-CPUID_FEATURE_CHECK(avx512bw, AVX512BW);
+-CPUID_FEATURE_CHECK(avx512ifma, AVX512IFMA);
+-CPUID_FEATURE_CHECK(avx512vbmi, AVX512VBMI);
+-CPUID_FEATURE_CHECK(avx512pf, AVX512PF);
+-CPUID_FEATURE_CHECK(avx512er, AVX512ER);
+-CPUID_FEATURE_CHECK(avx512vl, AVX512VL);
+-CPUID_FEATURE_CHECK(aes, AES);
+-CPUID_FEATURE_CHECK(pclmulqdq, PCLMULQDQ);
+-
+-#endif /* !defined(_KERNEL) */
+-
+-
+ /*
+  * Detect register set support
+  */
+@@ -480,16 +295,11 @@ __simd_state_enabled(const uint64_t state)
+       boolean_t has_osxsave;
+       uint64_t xcr0;
+-#if defined(_KERNEL)
+ #if defined(X86_FEATURE_OSXSAVE)
+       has_osxsave = !!boot_cpu_has(X86_FEATURE_OSXSAVE);
+ #else
+       has_osxsave = B_FALSE;
+ #endif
+-#elif !defined(_KERNEL)
+-      has_osxsave = __cpuid_has_osxsave();
+-#endif
+-
+       if (!has_osxsave)
+               return (B_FALSE);
+@@ -503,18 +313,13 @@ __simd_state_enabled(const uint64_t state)
+ #define       __ymm_enabled() __simd_state_enabled(_XSTATE_SSE_AVX)
+ #define       __zmm_enabled() __simd_state_enabled(_XSTATE_AVX512)
+-
+ /*
+  * Check if SSE instruction set is available
+  */
+ static inline boolean_t
+ zfs_sse_available(void)
+ {
+-#if defined(_KERNEL)
+       return (!!boot_cpu_has(X86_FEATURE_XMM));
+-#elif !defined(_KERNEL)
+-      return (__cpuid_has_sse());
+-#endif
+ }
+ /*
+@@ -523,11 +328,7 @@ zfs_sse_available(void)
+ static inline boolean_t
+ zfs_sse2_available(void)
+ {
+-#if defined(_KERNEL)
+       return (!!boot_cpu_has(X86_FEATURE_XMM2));
+-#elif !defined(_KERNEL)
+-      return (__cpuid_has_sse2());
+-#endif
+ }
+ /*
+@@ -536,11 +337,7 @@ zfs_sse2_available(void)
+ static inline boolean_t
+ zfs_sse3_available(void)
+ {
+-#if defined(_KERNEL)
+       return (!!boot_cpu_has(X86_FEATURE_XMM3));
+-#elif !defined(_KERNEL)
+-      return (__cpuid_has_sse3());
+-#endif
+ }
+ /*
+@@ -549,11 +346,7 @@ zfs_sse3_available(void)
+ static inline boolean_t
+ zfs_ssse3_available(void)
+ {
+-#if defined(_KERNEL)
+       return (!!boot_cpu_has(X86_FEATURE_SSSE3));
+-#elif !defined(_KERNEL)
+-      return (__cpuid_has_ssse3());
+-#endif
+ }
+ /*
+@@ -562,11 +355,7 @@ zfs_ssse3_available(void)
+ static inline boolean_t
+ zfs_sse4_1_available(void)
+ {
+-#if defined(_KERNEL)
+       return (!!boot_cpu_has(X86_FEATURE_XMM4_1));
+-#elif !defined(_KERNEL)
+-      return (__cpuid_has_sse4_1());
+-#endif
+ }
+ /*
+@@ -575,11 +364,7 @@ zfs_sse4_1_available(void)
+ static inline boolean_t
+ zfs_sse4_2_available(void)
+ {
+-#if defined(_KERNEL)
+       return (!!boot_cpu_has(X86_FEATURE_XMM4_2));
+-#elif !defined(_KERNEL)
+-      return (__cpuid_has_sse4_2());
+-#endif
+ }
+ /*
+@@ -588,14 +373,7 @@ zfs_sse4_2_available(void)
+ static inline boolean_t
+ zfs_avx_available(void)
+ {
+-      boolean_t has_avx;
+-#if defined(_KERNEL)
+-      has_avx = !!boot_cpu_has(X86_FEATURE_AVX);
+-#elif !defined(_KERNEL)
+-      has_avx = __cpuid_has_avx();
+-#endif
+-
+-      return (has_avx && __ymm_enabled());
++      return (boot_cpu_has(X86_FEATURE_AVX) && __ymm_enabled());
+ }
+ /*
+@@ -604,14 +382,7 @@ zfs_avx_available(void)
+ static inline boolean_t
+ zfs_avx2_available(void)
+ {
+-      boolean_t has_avx2;
+-#if defined(_KERNEL)
+-      has_avx2 = !!boot_cpu_has(X86_FEATURE_AVX2);
+-#elif !defined(_KERNEL)
+-      has_avx2 = __cpuid_has_avx2();
+-#endif
+-
+-      return (has_avx2 && __ymm_enabled());
++      return (boot_cpu_has(X86_FEATURE_AVX2) && __ymm_enabled());
+ }
+ /*
+@@ -620,15 +391,11 @@ zfs_avx2_available(void)
+ static inline boolean_t
+ zfs_bmi1_available(void)
+ {
+-#if defined(_KERNEL)
+ #if defined(X86_FEATURE_BMI1)
+       return (!!boot_cpu_has(X86_FEATURE_BMI1));
+ #else
+       return (B_FALSE);
+ #endif
+-#elif !defined(_KERNEL)
+-      return (__cpuid_has_bmi1());
+-#endif
+ }
+ /*
+@@ -637,15 +404,11 @@ zfs_bmi1_available(void)
+ static inline boolean_t
+ zfs_bmi2_available(void)
+ {
+-#if defined(_KERNEL)
+ #if defined(X86_FEATURE_BMI2)
+       return (!!boot_cpu_has(X86_FEATURE_BMI2));
+ #else
+       return (B_FALSE);
+ #endif
+-#elif !defined(_KERNEL)
+-      return (__cpuid_has_bmi2());
+-#endif
+ }
+ /*
+@@ -654,15 +417,11 @@ zfs_bmi2_available(void)
+ static inline boolean_t
+ zfs_aes_available(void)
+ {
+-#if defined(_KERNEL)
+ #if defined(X86_FEATURE_AES)
+       return (!!boot_cpu_has(X86_FEATURE_AES));
+ #else
+       return (B_FALSE);
+ #endif
+-#elif !defined(_KERNEL)
+-      return (__cpuid_has_aes());
+-#endif
+ }
+ /*
+@@ -671,15 +430,11 @@ zfs_aes_available(void)
+ static inline boolean_t
+ zfs_pclmulqdq_available(void)
+ {
+-#if defined(_KERNEL)
+ #if defined(X86_FEATURE_PCLMULQDQ)
+       return (!!boot_cpu_has(X86_FEATURE_PCLMULQDQ));
+ #else
+       return (B_FALSE);
+ #endif
+-#elif !defined(_KERNEL)
+-      return (__cpuid_has_pclmulqdq());
+-#endif
+ }
+ /*
+@@ -698,187 +453,141 @@ zfs_pclmulqdq_available(void)
+  * AVX512VBMI Vector Byte Manipulation Instructions
+  */
+-
+-/* Check if AVX512F instruction set is available */
++/*
++ * Check if AVX512F instruction set is available
++ */
+ static inline boolean_t
+ zfs_avx512f_available(void)
+ {
+       boolean_t has_avx512 = B_FALSE;
+-#if defined(_KERNEL)
+ #if defined(X86_FEATURE_AVX512F)
+       has_avx512 = !!boot_cpu_has(X86_FEATURE_AVX512F);
+-#else
+-      has_avx512 = B_FALSE;
+-#endif
+-#elif !defined(_KERNEL)
+-      has_avx512 = __cpuid_has_avx512f();
+ #endif
+-
+       return (has_avx512 && __zmm_enabled());
+ }
+-/* Check if AVX512CD instruction set is available */
++/*
++ * Check if AVX512CD instruction set is available
++ */
+ static inline boolean_t
+ zfs_avx512cd_available(void)
+ {
+       boolean_t has_avx512 = B_FALSE;
+-#if defined(_KERNEL)
+ #if defined(X86_FEATURE_AVX512CD)
+       has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) &&
+           boot_cpu_has(X86_FEATURE_AVX512CD);
+-#else
+-      has_avx512 = B_FALSE;
+ #endif
+-#elif !defined(_KERNEL)
+-      has_avx512 = __cpuid_has_avx512cd();
+-#endif
+-
+       return (has_avx512 && __zmm_enabled());
+ }
+-/* Check if AVX512ER instruction set is available */
++/*
++ * Check if AVX512ER instruction set is available
++ */
+ static inline boolean_t
+ zfs_avx512er_available(void)
+ {
+       boolean_t has_avx512 = B_FALSE;
+-#if defined(_KERNEL)
+ #if defined(X86_FEATURE_AVX512ER)
+       has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) &&
+           boot_cpu_has(X86_FEATURE_AVX512ER);
+-#else
+-      has_avx512 = B_FALSE;
+-#endif
+-#elif !defined(_KERNEL)
+-      has_avx512 = __cpuid_has_avx512er();
+ #endif
+-
+       return (has_avx512 && __zmm_enabled());
+ }
+-/* Check if AVX512PF instruction set is available */
++/*
++ * Check if AVX512PF instruction set is available
++ */
+ static inline boolean_t
+ zfs_avx512pf_available(void)
+ {
+       boolean_t has_avx512 = B_FALSE;
+-#if defined(_KERNEL)
+ #if defined(X86_FEATURE_AVX512PF)
+       has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) &&
+           boot_cpu_has(X86_FEATURE_AVX512PF);
+-#else
+-      has_avx512 = B_FALSE;
+-#endif
+-#elif !defined(_KERNEL)
+-      has_avx512 = __cpuid_has_avx512pf();
+ #endif
+-
+       return (has_avx512 && __zmm_enabled());
+ }
+-/* Check if AVX512BW instruction set is available */
++/*
++ * Check if AVX512BW instruction set is available
++ */
+ static inline boolean_t
+ zfs_avx512bw_available(void)
+ {
+       boolean_t has_avx512 = B_FALSE;
+-#if defined(_KERNEL)
+ #if defined(X86_FEATURE_AVX512BW)
+       has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) &&
+           boot_cpu_has(X86_FEATURE_AVX512BW);
+-#else
+-      has_avx512 = B_FALSE;
+-#endif
+-#elif !defined(_KERNEL)
+-      has_avx512 = __cpuid_has_avx512bw();
+ #endif
+       return (has_avx512 && __zmm_enabled());
+ }
+-/* Check if AVX512DQ instruction set is available */
++/*
++ * Check if AVX512DQ instruction set is available
++ */
+ static inline boolean_t
+ zfs_avx512dq_available(void)
+ {
+       boolean_t has_avx512 = B_FALSE;
+-#if defined(_KERNEL)
+ #if defined(X86_FEATURE_AVX512DQ)
+       has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) &&
+           boot_cpu_has(X86_FEATURE_AVX512DQ);
+-#else
+-      has_avx512 = B_FALSE;
+-#endif
+-#elif !defined(_KERNEL)
+-      has_avx512 = __cpuid_has_avx512dq();
+ #endif
+-
+       return (has_avx512 && __zmm_enabled());
+ }
+-/* Check if AVX512VL instruction set is available */
++/*
++ * Check if AVX512VL instruction set is available
++ */
+ static inline boolean_t
+ zfs_avx512vl_available(void)
+ {
+       boolean_t has_avx512 = B_FALSE;
+-#if defined(_KERNEL)
+ #if defined(X86_FEATURE_AVX512VL)
+       has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) &&
+           boot_cpu_has(X86_FEATURE_AVX512VL);
+-#else
+-      has_avx512 = B_FALSE;
+-#endif
+-#elif !defined(_KERNEL)
+-      has_avx512 = __cpuid_has_avx512vl();
+ #endif
+-
+       return (has_avx512 && __zmm_enabled());
+ }
+-/* Check if AVX512IFMA instruction set is available */
++/*
++ * Check if AVX512IFMA instruction set is available
++ */
+ static inline boolean_t
+ zfs_avx512ifma_available(void)
+ {
+       boolean_t has_avx512 = B_FALSE;
+-#if defined(_KERNEL)
+ #if defined(X86_FEATURE_AVX512IFMA)
+       has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) &&
+           boot_cpu_has(X86_FEATURE_AVX512IFMA);
+-#else
+-      has_avx512 = B_FALSE;
+-#endif
+-#elif !defined(_KERNEL)
+-      has_avx512 = __cpuid_has_avx512ifma();
+ #endif
+-
+       return (has_avx512 && __zmm_enabled());
+ }
+-/* Check if AVX512VBMI instruction set is available */
++/*
++ * Check if AVX512VBMI instruction set is available
++ */
+ static inline boolean_t
+ zfs_avx512vbmi_available(void)
+ {
+       boolean_t has_avx512 = B_FALSE;
+-#if defined(_KERNEL)
+ #if defined(X86_FEATURE_AVX512VBMI)
+       has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) &&
+           boot_cpu_has(X86_FEATURE_AVX512VBMI);
+-#else
+-      has_avx512 = B_FALSE;
+ #endif
+-#elif !defined(_KERNEL)
+-      has_avx512 = __cpuid_has_avx512f() &&
+-          __cpuid_has_avx512vbmi();
+-#endif
+-
+       return (has_avx512 && __zmm_enabled());
+ }
+ #endif /* defined(__x86) */
+-#endif /* _SIMD_X86_H */
++#endif /* _LINUX_SIMD_X86_H */
+diff --git a/include/linux/utsname_compat.h b/include/os/linux/kernel/linux/utsname_compat.h
+similarity index 100%
+rename from include/linux/utsname_compat.h
+rename to include/os/linux/kernel/linux/utsname_compat.h
+diff --git a/include/linux/vfs_compat.h b/include/os/linux/kernel/linux/vfs_compat.h
+similarity index 100%
+rename from include/linux/vfs_compat.h
+rename to include/os/linux/kernel/linux/vfs_compat.h
+diff --git a/include/linux/xattr_compat.h b/include/os/linux/kernel/linux/xattr_compat.h
+similarity index 100%
+rename from include/linux/xattr_compat.h
+rename to include/os/linux/kernel/linux/xattr_compat.h
+diff --git a/include/spl/Makefile.am b/include/os/linux/spl/Makefile.am
+similarity index 100%
+rename from include/spl/Makefile.am
+rename to include/os/linux/spl/Makefile.am
+diff --git a/include/spl/rpc/Makefile.am b/include/os/linux/spl/rpc/Makefile.am
+similarity index 72%
+rename from include/spl/rpc/Makefile.am
+rename to include/os/linux/spl/rpc/Makefile.am
+index 5110cc0f0..9477dd59d 100644
+--- a/include/spl/rpc/Makefile.am
++++ b/include/os/linux/spl/rpc/Makefile.am
+@@ -1,5 +1,5 @@
+ KERNEL_H = \
+-      $(top_srcdir)/include/spl/rpc/xdr.h
++      $(top_srcdir)/include/os/linux/spl/rpc/xdr.h
+ if CONFIG_KERNEL
+ kerneldir = @prefix@/src/zfs-$(VERSION)/include/spl/rpc
+diff --git a/include/spl/rpc/xdr.h b/include/os/linux/spl/rpc/xdr.h
+similarity index 100%
+rename from include/spl/rpc/xdr.h
+rename to include/os/linux/spl/rpc/xdr.h
+diff --git a/include/os/linux/spl/sys/Makefile.am b/include/os/linux/spl/sys/Makefile.am
+new file mode 100644
+index 000000000..de2f74d8c
+--- /dev/null
++++ b/include/os/linux/spl/sys/Makefile.am
+@@ -0,0 +1,62 @@
++KERNEL_H = \
++      $(top_srcdir)/include/os/linux/spl/sys/acl.h \
++      $(top_srcdir)/include/os/linux/spl/sys/atomic.h \
++      $(top_srcdir)/include/os/linux/spl/sys/byteorder.h \
++      $(top_srcdir)/include/os/linux/spl/sys/callb.h \
++      $(top_srcdir)/include/os/linux/spl/sys/callo.h \
++      $(top_srcdir)/include/os/linux/spl/sys/cmn_err.h \
++      $(top_srcdir)/include/os/linux/spl/sys/condvar.h \
++      $(top_srcdir)/include/os/linux/spl/sys/console.h \
++      $(top_srcdir)/include/os/linux/spl/sys/cred.h \
++      $(top_srcdir)/include/os/linux/spl/sys/ctype.h \
++      $(top_srcdir)/include/os/linux/spl/sys/debug.h \
++      $(top_srcdir)/include/os/linux/spl/sys/disp.h \
++      $(top_srcdir)/include/os/linux/spl/sys/dkio.h \
++      $(top_srcdir)/include/os/linux/spl/sys/errno.h \
++      $(top_srcdir)/include/os/linux/spl/sys/fcntl.h \
++      $(top_srcdir)/include/os/linux/spl/sys/file.h \
++      $(top_srcdir)/include/os/linux/spl/sys/inttypes.h \
++      $(top_srcdir)/include/os/linux/spl/sys/isa_defs.h \
++      $(top_srcdir)/include/os/linux/spl/sys/kmem_cache.h \
++      $(top_srcdir)/include/os/linux/spl/sys/kmem.h \
++      $(top_srcdir)/include/os/linux/spl/sys/kobj.h \
++      $(top_srcdir)/include/os/linux/spl/sys/kstat.h \
++      $(top_srcdir)/include/os/linux/spl/sys/list.h \
++      $(top_srcdir)/include/os/linux/spl/sys/mode.h \
++      $(top_srcdir)/include/os/linux/spl/sys/mutex.h \
++      $(top_srcdir)/include/os/linux/spl/sys/param.h \
++      $(top_srcdir)/include/os/linux/spl/sys/processor.h \
++      $(top_srcdir)/include/os/linux/spl/sys/proc.h \
++      $(top_srcdir)/include/os/linux/spl/sys/procfs_list.h \
++      $(top_srcdir)/include/os/linux/spl/sys/random.h \
++      $(top_srcdir)/include/os/linux/spl/sys/rwlock.h \
++      $(top_srcdir)/include/os/linux/spl/sys/shrinker.h \
++      $(top_srcdir)/include/os/linux/spl/sys/sid.h \
++      $(top_srcdir)/include/os/linux/spl/sys/signal.h \
++      $(top_srcdir)/include/os/linux/spl/sys/simd.h \
++      $(top_srcdir)/include/os/linux/spl/sys/stat.h \
++      $(top_srcdir)/include/os/linux/spl/sys/strings.h \
++      $(top_srcdir)/include/os/linux/spl/sys/sunddi.h \
++      $(top_srcdir)/include/os/linux/spl/sys/sysmacros.h \
++      $(top_srcdir)/include/os/linux/spl/sys/systeminfo.h \
++      $(top_srcdir)/include/os/linux/spl/sys/taskq.h \
++      $(top_srcdir)/include/os/linux/spl/sys/thread.h \
++      $(top_srcdir)/include/os/linux/spl/sys/time.h \
++      $(top_srcdir)/include/os/linux/spl/sys/timer.h \
++      $(top_srcdir)/include/os/linux/spl/sys/tsd.h \
++      $(top_srcdir)/include/os/linux/spl/sys/types32.h \
++      $(top_srcdir)/include/os/linux/spl/sys/types.h \
++      $(top_srcdir)/include/os/linux/spl/sys/uio.h \
++      $(top_srcdir)/include/os/linux/spl/sys/user.h \
++      $(top_srcdir)/include/os/linux/spl/sys/vfs.h \
++      $(top_srcdir)/include/os/linux/spl/sys/vmem.h \
++      $(top_srcdir)/include/os/linux/spl/sys/vmsystm.h \
++      $(top_srcdir)/include/os/linux/spl/sys/vnode.h \
++      $(top_srcdir)/include/os/linux/spl/sys/wait.h \
++      $(top_srcdir)/include/os/linux/spl/sys/zmod.h \
++      $(top_srcdir)/include/os/linux/spl/sys/zone.h
++
++if CONFIG_KERNEL
++kerneldir = @prefix@/src/zfs-$(VERSION)/include/spl/sys
++kernel_HEADERS = $(KERNEL_H)
++endif
+diff --git a/include/spl/sys/acl.h b/include/os/linux/spl/sys/acl.h
+similarity index 100%
+rename from include/spl/sys/acl.h
+rename to include/os/linux/spl/sys/acl.h
+diff --git a/include/spl/sys/atomic.h b/include/os/linux/spl/sys/atomic.h
+similarity index 100%
+rename from include/spl/sys/atomic.h
+rename to include/os/linux/spl/sys/atomic.h
+diff --git a/include/spl/sys/byteorder.h b/include/os/linux/spl/sys/byteorder.h
+similarity index 100%
+rename from include/spl/sys/byteorder.h
+rename to include/os/linux/spl/sys/byteorder.h
+diff --git a/include/spl/sys/callb.h b/include/os/linux/spl/sys/callb.h
+similarity index 100%
+rename from include/spl/sys/callb.h
+rename to include/os/linux/spl/sys/callb.h
+diff --git a/include/spl/sys/callo.h b/include/os/linux/spl/sys/callo.h
+similarity index 100%
+rename from include/spl/sys/callo.h
+rename to include/os/linux/spl/sys/callo.h
+diff --git a/include/spl/sys/cmn_err.h b/include/os/linux/spl/sys/cmn_err.h
+similarity index 100%
+rename from include/spl/sys/cmn_err.h
+rename to include/os/linux/spl/sys/cmn_err.h
+diff --git a/include/spl/sys/condvar.h b/include/os/linux/spl/sys/condvar.h
+similarity index 100%
+rename from include/spl/sys/condvar.h
+rename to include/os/linux/spl/sys/condvar.h
+diff --git a/include/spl/sys/console.h b/include/os/linux/spl/sys/console.h
+similarity index 100%
+rename from include/spl/sys/console.h
+rename to include/os/linux/spl/sys/console.h
+diff --git a/include/spl/sys/cred.h b/include/os/linux/spl/sys/cred.h
+similarity index 100%
+rename from include/spl/sys/cred.h
+rename to include/os/linux/spl/sys/cred.h
+diff --git a/include/spl/sys/ctype.h b/include/os/linux/spl/sys/ctype.h
+similarity index 100%
+rename from include/spl/sys/ctype.h
+rename to include/os/linux/spl/sys/ctype.h
+diff --git a/include/spl/sys/debug.h b/include/os/linux/spl/sys/debug.h
+similarity index 100%
+rename from include/spl/sys/debug.h
+rename to include/os/linux/spl/sys/debug.h
+diff --git a/include/spl/sys/disp.h b/include/os/linux/spl/sys/disp.h
+similarity index 100%
+rename from include/spl/sys/disp.h
+rename to include/os/linux/spl/sys/disp.h
+diff --git a/include/spl/sys/dkio.h b/include/os/linux/spl/sys/dkio.h
+similarity index 100%
+rename from include/spl/sys/dkio.h
+rename to include/os/linux/spl/sys/dkio.h
+diff --git a/include/spl/sys/errno.h b/include/os/linux/spl/sys/errno.h
+similarity index 100%
+rename from include/spl/sys/errno.h
+rename to include/os/linux/spl/sys/errno.h
+diff --git a/include/spl/sys/fcntl.h b/include/os/linux/spl/sys/fcntl.h
+similarity index 100%
+rename from include/spl/sys/fcntl.h
+rename to include/os/linux/spl/sys/fcntl.h
+diff --git a/include/spl/sys/file.h b/include/os/linux/spl/sys/file.h
+similarity index 100%
+rename from include/spl/sys/file.h
+rename to include/os/linux/spl/sys/file.h
+diff --git a/include/spl/sys/inttypes.h b/include/os/linux/spl/sys/inttypes.h
+similarity index 100%
+rename from include/spl/sys/inttypes.h
+rename to include/os/linux/spl/sys/inttypes.h
+diff --git a/include/spl/sys/isa_defs.h b/include/os/linux/spl/sys/isa_defs.h
+similarity index 100%
+rename from include/spl/sys/isa_defs.h
+rename to include/os/linux/spl/sys/isa_defs.h
+diff --git a/include/spl/sys/kmem.h b/include/os/linux/spl/sys/kmem.h
+similarity index 100%
+rename from include/spl/sys/kmem.h
+rename to include/os/linux/spl/sys/kmem.h
+diff --git a/include/spl/sys/kmem_cache.h b/include/os/linux/spl/sys/kmem_cache.h
+similarity index 100%
+rename from include/spl/sys/kmem_cache.h
+rename to include/os/linux/spl/sys/kmem_cache.h
+diff --git a/include/spl/sys/kobj.h b/include/os/linux/spl/sys/kobj.h
+similarity index 100%
+rename from include/spl/sys/kobj.h
+rename to include/os/linux/spl/sys/kobj.h
+diff --git a/include/spl/sys/kstat.h b/include/os/linux/spl/sys/kstat.h
+similarity index 100%
+rename from include/spl/sys/kstat.h
+rename to include/os/linux/spl/sys/kstat.h
+diff --git a/include/spl/sys/list.h b/include/os/linux/spl/sys/list.h
+similarity index 100%
+rename from include/spl/sys/list.h
+rename to include/os/linux/spl/sys/list.h
+diff --git a/include/spl/sys/mode.h b/include/os/linux/spl/sys/mode.h
+similarity index 100%
+rename from include/spl/sys/mode.h
+rename to include/os/linux/spl/sys/mode.h
+diff --git a/include/spl/sys/mutex.h b/include/os/linux/spl/sys/mutex.h
+similarity index 100%
+rename from include/spl/sys/mutex.h
+rename to include/os/linux/spl/sys/mutex.h
+diff --git a/include/spl/sys/param.h b/include/os/linux/spl/sys/param.h
+similarity index 100%
+rename from include/spl/sys/param.h
+rename to include/os/linux/spl/sys/param.h
+diff --git a/include/spl/sys/proc.h b/include/os/linux/spl/sys/proc.h
+similarity index 100%
+rename from include/spl/sys/proc.h
+rename to include/os/linux/spl/sys/proc.h
+diff --git a/include/spl/sys/processor.h b/include/os/linux/spl/sys/processor.h
+similarity index 100%
+rename from include/spl/sys/processor.h
+rename to include/os/linux/spl/sys/processor.h
+diff --git a/include/spl/sys/procfs_list.h b/include/os/linux/spl/sys/procfs_list.h
+similarity index 100%
+rename from include/spl/sys/procfs_list.h
+rename to include/os/linux/spl/sys/procfs_list.h
+diff --git a/include/spl/sys/random.h b/include/os/linux/spl/sys/random.h
+similarity index 100%
+rename from include/spl/sys/random.h
+rename to include/os/linux/spl/sys/random.h
+diff --git a/include/spl/sys/rwlock.h b/include/os/linux/spl/sys/rwlock.h
+similarity index 100%
+rename from include/spl/sys/rwlock.h
+rename to include/os/linux/spl/sys/rwlock.h
+diff --git a/include/spl/sys/shrinker.h b/include/os/linux/spl/sys/shrinker.h
+similarity index 100%
+rename from include/spl/sys/shrinker.h
+rename to include/os/linux/spl/sys/shrinker.h
+diff --git a/include/spl/sys/sid.h b/include/os/linux/spl/sys/sid.h
+similarity index 100%
+rename from include/spl/sys/sid.h
+rename to include/os/linux/spl/sys/sid.h
+diff --git a/include/spl/sys/signal.h b/include/os/linux/spl/sys/signal.h
+similarity index 100%
+rename from include/spl/sys/signal.h
+rename to include/os/linux/spl/sys/signal.h
+diff --git a/include/os/linux/spl/sys/simd.h b/include/os/linux/spl/sys/simd.h
+new file mode 100644
+index 000000000..f2048d9e1
+--- /dev/null
++++ b/include/os/linux/spl/sys/simd.h
+@@ -0,0 +1,31 @@
++/*
++ *  Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
++ *  Copyright (C) 2007 The Regents of the University of California.
++ *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
++ *  Written by Brian Behlendorf <behlendorf1@llnl.gov>.
++ *  UCRL-CODE-235197
++ *
++ *  This file is part of the SPL, Solaris Porting Layer.
++ *  For details, see <http://zfsonlinux.org/>.
++ *
++ *  The SPL is free software; you can redistribute it and/or modify it
++ *  under the terms of the GNU General Public License as published by the
++ *  Free Software Foundation; either version 2 of the License, or (at your
++ *  option) any later version.
++ *
++ *  The SPL is distributed in the hope that it will be useful, but WITHOUT
++ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ *  for more details.
++ *
++ *  You should have received a copy of the GNU General Public License along
++ *  with the SPL.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _SPL_SYS_SIMD_H
++#define       _SPL_SYS_SIMD_H
++
++#include <sys/isa_defs.h>
++#include <linux/simd.h>
++
++#endif /* _SPL_SYS_SIMD_H */
+diff --git a/include/spl/sys/stat.h b/include/os/linux/spl/sys/stat.h
+similarity index 100%
+rename from include/spl/sys/stat.h
+rename to include/os/linux/spl/sys/stat.h
+diff --git a/include/spl/sys/strings.h b/include/os/linux/spl/sys/strings.h
+similarity index 100%
+rename from include/spl/sys/strings.h
+rename to include/os/linux/spl/sys/strings.h
+diff --git a/include/spl/sys/sunddi.h b/include/os/linux/spl/sys/sunddi.h
+similarity index 100%
+rename from include/spl/sys/sunddi.h
+rename to include/os/linux/spl/sys/sunddi.h
+diff --git a/include/spl/sys/sysmacros.h b/include/os/linux/spl/sys/sysmacros.h
+similarity index 100%
+rename from include/spl/sys/sysmacros.h
+rename to include/os/linux/spl/sys/sysmacros.h
+diff --git a/include/spl/sys/systeminfo.h b/include/os/linux/spl/sys/systeminfo.h
+similarity index 100%
+rename from include/spl/sys/systeminfo.h
+rename to include/os/linux/spl/sys/systeminfo.h
+diff --git a/include/spl/sys/taskq.h b/include/os/linux/spl/sys/taskq.h
+similarity index 100%
+rename from include/spl/sys/taskq.h
+rename to include/os/linux/spl/sys/taskq.h
+diff --git a/include/spl/sys/thread.h b/include/os/linux/spl/sys/thread.h
+similarity index 100%
+rename from include/spl/sys/thread.h
+rename to include/os/linux/spl/sys/thread.h
+diff --git a/include/spl/sys/time.h b/include/os/linux/spl/sys/time.h
+similarity index 100%
+rename from include/spl/sys/time.h
+rename to include/os/linux/spl/sys/time.h
+diff --git a/include/spl/sys/timer.h b/include/os/linux/spl/sys/timer.h
+similarity index 100%
+rename from include/spl/sys/timer.h
+rename to include/os/linux/spl/sys/timer.h
+diff --git a/include/spl/sys/tsd.h b/include/os/linux/spl/sys/tsd.h
+similarity index 100%
+rename from include/spl/sys/tsd.h
+rename to include/os/linux/spl/sys/tsd.h
+diff --git a/include/spl/sys/types.h b/include/os/linux/spl/sys/types.h
+similarity index 100%
+rename from include/spl/sys/types.h
+rename to include/os/linux/spl/sys/types.h
+diff --git a/include/spl/sys/types32.h b/include/os/linux/spl/sys/types32.h
+similarity index 100%
+rename from include/spl/sys/types32.h
+rename to include/os/linux/spl/sys/types32.h
+diff --git a/include/spl/sys/uio.h b/include/os/linux/spl/sys/uio.h
+similarity index 100%
+rename from include/spl/sys/uio.h
+rename to include/os/linux/spl/sys/uio.h
+diff --git a/include/spl/sys/user.h b/include/os/linux/spl/sys/user.h
+similarity index 100%
+rename from include/spl/sys/user.h
+rename to include/os/linux/spl/sys/user.h
+diff --git a/include/spl/sys/vfs.h b/include/os/linux/spl/sys/vfs.h
+similarity index 100%
+rename from include/spl/sys/vfs.h
+rename to include/os/linux/spl/sys/vfs.h
+diff --git a/include/spl/sys/vmem.h b/include/os/linux/spl/sys/vmem.h
+similarity index 100%
+rename from include/spl/sys/vmem.h
+rename to include/os/linux/spl/sys/vmem.h
+diff --git a/include/spl/sys/vmsystm.h b/include/os/linux/spl/sys/vmsystm.h
+similarity index 100%
+rename from include/spl/sys/vmsystm.h
+rename to include/os/linux/spl/sys/vmsystm.h
+diff --git a/include/spl/sys/vnode.h b/include/os/linux/spl/sys/vnode.h
+similarity index 100%
+rename from include/spl/sys/vnode.h
+rename to include/os/linux/spl/sys/vnode.h
+diff --git a/include/spl/sys/wait.h b/include/os/linux/spl/sys/wait.h
+similarity index 100%
+rename from include/spl/sys/wait.h
+rename to include/os/linux/spl/sys/wait.h
+diff --git a/include/spl/sys/zmod.h b/include/os/linux/spl/sys/zmod.h
+similarity index 100%
+rename from include/spl/sys/zmod.h
+rename to include/os/linux/spl/sys/zmod.h
+diff --git a/include/spl/sys/zone.h b/include/os/linux/spl/sys/zone.h
+similarity index 100%
+rename from include/spl/sys/zone.h
+rename to include/os/linux/spl/sys/zone.h
+diff --git a/include/os/linux/zfs/Makefile.am b/include/os/linux/zfs/Makefile.am
+new file mode 100644
+index 000000000..081839c48
+--- /dev/null
++++ b/include/os/linux/zfs/Makefile.am
+@@ -0,0 +1 @@
++SUBDIRS = sys
+diff --git a/include/os/linux/zfs/sys/Makefile.am b/include/os/linux/zfs/sys/Makefile.am
+new file mode 100644
+index 000000000..5aa87da37
+--- /dev/null
++++ b/include/os/linux/zfs/sys/Makefile.am
+@@ -0,0 +1,12 @@
++KERNEL_H = \
++      $(top_srcdir)/include/os/linux/zfs/sys/policy.h \
++      $(top_srcdir)/include/os/linux/zfs/sys/zfs_ctldir.h \
++      $(top_srcdir)/include/os/linux/zfs/sys/zfs_dir.h \
++      $(top_srcdir)/include/os/linux/zfs/sys/zfs_vfsops.h \
++      $(top_srcdir)/include/os/linux/zfs/sys/zfs_vnops.h \
++      $(top_srcdir)/include/os/linux/zfs/sys/zpl.h
++
++if CONFIG_KERNEL
++kerneldir = @prefix@/src/zfs-$(VERSION)/include/sys
++kernel_HEADERS = $(KERNEL_H)
++endif
+diff --git a/include/sys/policy.h b/include/os/linux/zfs/sys/policy.h
+similarity index 100%
+rename from include/sys/policy.h
+rename to include/os/linux/zfs/sys/policy.h
+diff --git a/include/sys/zfs_ctldir.h b/include/os/linux/zfs/sys/zfs_ctldir.h
+similarity index 100%
+rename from include/sys/zfs_ctldir.h
+rename to include/os/linux/zfs/sys/zfs_ctldir.h
+diff --git a/include/sys/zfs_dir.h b/include/os/linux/zfs/sys/zfs_dir.h
+similarity index 100%
+rename from include/sys/zfs_dir.h
+rename to include/os/linux/zfs/sys/zfs_dir.h
+diff --git a/include/sys/zfs_vfsops.h b/include/os/linux/zfs/sys/zfs_vfsops.h
+similarity index 100%
+rename from include/sys/zfs_vfsops.h
+rename to include/os/linux/zfs/sys/zfs_vfsops.h
+diff --git a/include/sys/zfs_vnops.h b/include/os/linux/zfs/sys/zfs_vnops.h
+similarity index 100%
+rename from include/sys/zfs_vnops.h
+rename to include/os/linux/zfs/sys/zfs_vnops.h
+diff --git a/include/sys/zpl.h b/include/os/linux/zfs/sys/zpl.h
+similarity index 100%
+rename from include/sys/zpl.h
+rename to include/os/linux/zfs/sys/zpl.h
+diff --git a/include/spl/sys/Makefile.am b/include/spl/sys/Makefile.am
+deleted file mode 100644
+index 3b5b2755a..000000000
+--- a/include/spl/sys/Makefile.am
++++ /dev/null
+@@ -1,61 +0,0 @@
+-KERNEL_H = \
+-      $(top_srcdir)/include/spl/sys/acl.h \
+-      $(top_srcdir)/include/spl/sys/atomic.h \
+-      $(top_srcdir)/include/spl/sys/byteorder.h \
+-      $(top_srcdir)/include/spl/sys/callb.h \
+-      $(top_srcdir)/include/spl/sys/callo.h \
+-      $(top_srcdir)/include/spl/sys/cmn_err.h \
+-      $(top_srcdir)/include/spl/sys/condvar.h \
+-      $(top_srcdir)/include/spl/sys/console.h \
+-      $(top_srcdir)/include/spl/sys/cred.h \
+-      $(top_srcdir)/include/spl/sys/ctype.h \
+-      $(top_srcdir)/include/spl/sys/debug.h \
+-      $(top_srcdir)/include/spl/sys/disp.h \
+-      $(top_srcdir)/include/spl/sys/dkio.h \
+-      $(top_srcdir)/include/spl/sys/errno.h \
+-      $(top_srcdir)/include/spl/sys/fcntl.h \
+-      $(top_srcdir)/include/spl/sys/file.h \
+-      $(top_srcdir)/include/spl/sys/inttypes.h \
+-      $(top_srcdir)/include/spl/sys/isa_defs.h \
+-      $(top_srcdir)/include/spl/sys/kmem_cache.h \
+-      $(top_srcdir)/include/spl/sys/kmem.h \
+-      $(top_srcdir)/include/spl/sys/kobj.h \
+-      $(top_srcdir)/include/spl/sys/kstat.h \
+-      $(top_srcdir)/include/spl/sys/list.h \
+-      $(top_srcdir)/include/spl/sys/mode.h \
+-      $(top_srcdir)/include/spl/sys/mutex.h \
+-      $(top_srcdir)/include/spl/sys/param.h \
+-      $(top_srcdir)/include/spl/sys/processor.h \
+-      $(top_srcdir)/include/spl/sys/proc.h \
+-      $(top_srcdir)/include/spl/sys/procfs_list.h \
+-      $(top_srcdir)/include/spl/sys/random.h \
+-      $(top_srcdir)/include/spl/sys/rwlock.h \
+-      $(top_srcdir)/include/spl/sys/shrinker.h \
+-      $(top_srcdir)/include/spl/sys/sid.h \
+-      $(top_srcdir)/include/spl/sys/signal.h \
+-      $(top_srcdir)/include/spl/sys/stat.h \
+-      $(top_srcdir)/include/spl/sys/strings.h \
+-      $(top_srcdir)/include/spl/sys/sunddi.h \
+-      $(top_srcdir)/include/spl/sys/sysmacros.h \
+-      $(top_srcdir)/include/spl/sys/systeminfo.h \
+-      $(top_srcdir)/include/spl/sys/taskq.h \
+-      $(top_srcdir)/include/spl/sys/thread.h \
+-      $(top_srcdir)/include/spl/sys/time.h \
+-      $(top_srcdir)/include/spl/sys/timer.h \
+-      $(top_srcdir)/include/spl/sys/tsd.h \
+-      $(top_srcdir)/include/spl/sys/types32.h \
+-      $(top_srcdir)/include/spl/sys/types.h \
+-      $(top_srcdir)/include/spl/sys/uio.h \
+-      $(top_srcdir)/include/spl/sys/user.h \
+-      $(top_srcdir)/include/spl/sys/vfs.h \
+-      $(top_srcdir)/include/spl/sys/vmem.h \
+-      $(top_srcdir)/include/spl/sys/vmsystm.h \
+-      $(top_srcdir)/include/spl/sys/vnode.h \
+-      $(top_srcdir)/include/spl/sys/wait.h \
+-      $(top_srcdir)/include/spl/sys/zmod.h \
+-      $(top_srcdir)/include/spl/sys/zone.h
+-
+-if CONFIG_KERNEL
+-kerneldir = @prefix@/src/zfs-$(VERSION)/include/spl/sys
+-kernel_HEADERS = $(KERNEL_H)
+-endif
+diff --git a/include/sys/Makefile.am b/include/sys/Makefile.am
+index 31ffdfb4a..25ede0929 100644
+--- a/include/sys/Makefile.am
++++ b/include/sys/Makefile.am
+@@ -51,7 +51,6 @@ COMMON_H = \
+       $(top_srcdir)/include/sys/nvpair.h \
+       $(top_srcdir)/include/sys/nvpair_impl.h \
+       $(top_srcdir)/include/sys/pathname.h \
+-      $(top_srcdir)/include/sys/policy.h \
+       $(top_srcdir)/include/sys/range_tree.h \
+       $(top_srcdir)/include/sys/refcount.h \
+       $(top_srcdir)/include/sys/rrwlock.h \
+@@ -112,10 +111,8 @@ COMMON_H = \
+       $(top_srcdir)/include/sys/zfeature.h \
+       $(top_srcdir)/include/sys/zfs_acl.h \
+       $(top_srcdir)/include/sys/zfs_context.h \
+-      $(top_srcdir)/include/sys/zfs_ctldir.h \
+       $(top_srcdir)/include/sys/zfs_debug.h \
+       $(top_srcdir)/include/sys/zfs_delay.h \
+-      $(top_srcdir)/include/sys/zfs_dir.h \
+       $(top_srcdir)/include/sys/zfs_fuid.h \
+       $(top_srcdir)/include/sys/zfs_project.h \
+       $(top_srcdir)/include/sys/zfs_ratelimit.h \
+@@ -123,8 +120,6 @@ COMMON_H = \
+       $(top_srcdir)/include/sys/zfs_sa.h \
+       $(top_srcdir)/include/sys/zfs_stat.h \
+       $(top_srcdir)/include/sys/zfs_sysfs.h \
+-      $(top_srcdir)/include/sys/zfs_vfsops.h \
+-      $(top_srcdir)/include/sys/zfs_vnops.h \
+       $(top_srcdir)/include/sys/zfs_znode.h \
+       $(top_srcdir)/include/sys/zil.h \
+       $(top_srcdir)/include/sys/zil_impl.h \
+@@ -140,7 +135,6 @@ COMMON_H = \
+ KERNEL_H = \
+       $(top_srcdir)/include/sys/zfs_ioctl.h \
+       $(top_srcdir)/include/sys/zfs_onexit.h \
+-      ${top_srcdir}/include/sys/zpl.h \
+       $(top_srcdir)/include/sys/zvol.h
+ USER_H =
+diff --git a/lib/libspl/include/sys/Makefile.am b/lib/libspl/include/sys/Makefile.am
+index e7af317e0..5156e2912 100644
+--- a/lib/libspl/include/sys/Makefile.am
++++ b/lib/libspl/include/sys/Makefile.am
+@@ -33,6 +33,7 @@ libspl_HEADERS = \
+       $(top_srcdir)/lib/libspl/include/sys/priv.h \
+       $(top_srcdir)/lib/libspl/include/sys/processor.h \
+       $(top_srcdir)/lib/libspl/include/sys/signal.h \
++      $(top_srcdir)/lib/libspl/include/sys/simd.h \
+       $(top_srcdir)/lib/libspl/include/sys/stack.h \
+       $(top_srcdir)/lib/libspl/include/sys/stat.h \
+       $(top_srcdir)/lib/libspl/include/sys/stdtypes.h \
+diff --git a/lib/libspl/include/sys/simd.h b/lib/libspl/include/sys/simd.h
+new file mode 100644
+index 000000000..6a2b3a022
+--- /dev/null
++++ b/lib/libspl/include/sys/simd.h
+@@ -0,0 +1,448 @@
++/*
++ * CDDL HEADER START
++ *
++ * The contents of this file are subject to the terms of the
++ * Common Development and Distribution License, Version 1.0 only
++ * (the "License").  You may not use this file except in compliance
++ * with the License.
++ *
++ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
++ * or http://www.opensolaris.org/os/licensing.
++ * See the License for the specific language governing permissions
++ * and limitations under the License.
++ *
++ * When distributing Covered Code, include this CDDL HEADER in each
++ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
++ * If applicable, add the following below this CDDL HEADER, with the
++ * fields enclosed by brackets "[]" replaced with your own identifying
++ * information: Portions Copyright [yyyy] [name of copyright owner]
++ *
++ * CDDL HEADER END
++ */
++/*
++ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef _LIBSPL_SYS_SIMD_H
++#define       _LIBSPL_SYS_SIMD_H
++
++#include <sys/isa_defs.h>
++#include <sys/types.h>
++
++#if defined(__x86)
++#include <cpuid.h>
++
++#define       kfpu_allowed()          1
++#define       kfpu_initialize(tsk)    do {} while (0)
++#define       kfpu_begin()            do {} while (0)
++#define       kfpu_end()              do {} while (0)
++
++/*
++ * CPUID feature tests for user-space.
++ *
++ * x86 registers used implicitly by CPUID
++ */
++typedef enum cpuid_regs {
++      EAX = 0,
++      EBX,
++      ECX,
++      EDX,
++      CPUID_REG_CNT = 4
++} cpuid_regs_t;
++
++/*
++ * List of instruction sets identified by CPUID
++ */
++typedef enum cpuid_inst_sets {
++      SSE = 0,
++      SSE2,
++      SSE3,
++      SSSE3,
++      SSE4_1,
++      SSE4_2,
++      OSXSAVE,
++      AVX,
++      AVX2,
++      BMI1,
++      BMI2,
++      AVX512F,
++      AVX512CD,
++      AVX512DQ,
++      AVX512BW,
++      AVX512IFMA,
++      AVX512VBMI,
++      AVX512PF,
++      AVX512ER,
++      AVX512VL,
++      AES,
++      PCLMULQDQ
++} cpuid_inst_sets_t;
++
++/*
++ * Instruction set descriptor.
++ */
++typedef struct cpuid_feature_desc {
++      uint32_t leaf;          /* CPUID leaf */
++      uint32_t subleaf;       /* CPUID sub-leaf */
++      uint32_t flag;          /* bit mask of the feature */
++      cpuid_regs_t reg;       /* which CPUID return register to test */
++} cpuid_feature_desc_t;
++
++#define       _AVX512F_BIT            (1U << 16)
++#define       _AVX512CD_BIT           (_AVX512F_BIT | (1U << 28))
++#define       _AVX512DQ_BIT           (_AVX512F_BIT | (1U << 17))
++#define       _AVX512BW_BIT           (_AVX512F_BIT | (1U << 30))
++#define       _AVX512IFMA_BIT         (_AVX512F_BIT | (1U << 21))
++#define       _AVX512VBMI_BIT         (1U << 1) /* AVX512F_BIT is on another leaf  */
++#define       _AVX512PF_BIT           (_AVX512F_BIT | (1U << 26))
++#define       _AVX512ER_BIT           (_AVX512F_BIT | (1U << 27))
++#define       _AVX512VL_BIT           (1U << 31) /* if used also check other levels */
++#define       _AES_BIT                (1U << 25)
++#define       _PCLMULQDQ_BIT          (1U << 1)
++
++/*
++ * Descriptions of supported instruction sets
++ */
++static const cpuid_feature_desc_t cpuid_features[] = {
++      [SSE]           = {1U, 0U,      1U << 25,       EDX     },
++      [SSE2]          = {1U, 0U,      1U << 26,       EDX     },
++      [SSE3]          = {1U, 0U,      1U << 0,        ECX     },
++      [SSSE3]         = {1U, 0U,      1U << 9,        ECX     },
++      [SSE4_1]        = {1U, 0U,      1U << 19,       ECX     },
++      [SSE4_2]        = {1U, 0U,      1U << 20,       ECX     },
++      [OSXSAVE]       = {1U, 0U,      1U << 27,       ECX     },
++      [AVX]           = {1U, 0U,      1U << 28,       ECX     },
++      [AVX2]          = {7U, 0U,      1U << 5,        EBX     },
++      [BMI1]          = {7U, 0U,      1U << 3,        EBX     },
++      [BMI2]          = {7U, 0U,      1U << 8,        EBX     },
++      [AVX512F]       = {7U, 0U, _AVX512F_BIT,        EBX     },
++      [AVX512CD]      = {7U, 0U, _AVX512CD_BIT,       EBX     },
++      [AVX512DQ]      = {7U, 0U, _AVX512DQ_BIT,       EBX     },
++      [AVX512BW]      = {7U, 0U, _AVX512BW_BIT,       EBX     },
++      [AVX512IFMA]    = {7U, 0U, _AVX512IFMA_BIT,     EBX     },
++      [AVX512VBMI]    = {7U, 0U, _AVX512VBMI_BIT,     ECX     },
++      [AVX512PF]      = {7U, 0U, _AVX512PF_BIT,       EBX     },
++      [AVX512ER]      = {7U, 0U, _AVX512ER_BIT,       EBX     },
++      [AVX512VL]      = {7U, 0U, _AVX512ER_BIT,       EBX     },
++      [AES]           = {1U, 0U, _AES_BIT,            ECX     },
++      [PCLMULQDQ]     = {1U, 0U, _PCLMULQDQ_BIT,      ECX     },
++};
++
++/*
++ * Check if OS supports AVX and AVX2 by checking XCR0
++ * Only call this function if CPUID indicates that AVX feature is
++ * supported by the CPU, otherwise it might be an illegal instruction.
++ */
++static inline uint64_t
++xgetbv(uint32_t index)
++{
++      uint32_t eax, edx;
++      /* xgetbv - instruction byte code */
++      __asm__ __volatile__(".byte 0x0f; .byte 0x01; .byte 0xd0"
++          : "=a" (eax), "=d" (edx)
++          : "c" (index));
++
++      return ((((uint64_t)edx)<<32) | (uint64_t)eax);
++}
++
++/*
++ * Check if CPU supports a feature
++ */
++static inline boolean_t
++__cpuid_check_feature(const cpuid_feature_desc_t *desc)
++{
++      uint32_t r[CPUID_REG_CNT];
++
++      if (__get_cpuid_max(0, NULL) >= desc->leaf) {
++              /*
++               * __cpuid_count is needed to properly check
++               * for AVX2. It is a macro, so return parameters
++               * are passed by value.
++               */
++              __cpuid_count(desc->leaf, desc->subleaf,
++                  r[EAX], r[EBX], r[ECX], r[EDX]);
++              return ((r[desc->reg] & desc->flag) == desc->flag);
++      }
++      return (B_FALSE);
++}
++
++#define       CPUID_FEATURE_CHECK(name, id)                           \
++static inline boolean_t                                               \
++__cpuid_has_ ## name(void)                                    \
++{                                                             \
++      return (__cpuid_check_feature(&cpuid_features[id]));    \
++}
++
++/*
++ * Define functions for user-space CPUID features testing
++ */
++CPUID_FEATURE_CHECK(sse, SSE);
++CPUID_FEATURE_CHECK(sse2, SSE2);
++CPUID_FEATURE_CHECK(sse3, SSE3);
++CPUID_FEATURE_CHECK(ssse3, SSSE3);
++CPUID_FEATURE_CHECK(sse4_1, SSE4_1);
++CPUID_FEATURE_CHECK(sse4_2, SSE4_2);
++CPUID_FEATURE_CHECK(avx, AVX);
++CPUID_FEATURE_CHECK(avx2, AVX2);
++CPUID_FEATURE_CHECK(osxsave, OSXSAVE);
++CPUID_FEATURE_CHECK(bmi1, BMI1);
++CPUID_FEATURE_CHECK(bmi2, BMI2);
++CPUID_FEATURE_CHECK(avx512f, AVX512F);
++CPUID_FEATURE_CHECK(avx512cd, AVX512CD);
++CPUID_FEATURE_CHECK(avx512dq, AVX512DQ);
++CPUID_FEATURE_CHECK(avx512bw, AVX512BW);
++CPUID_FEATURE_CHECK(avx512ifma, AVX512IFMA);
++CPUID_FEATURE_CHECK(avx512vbmi, AVX512VBMI);
++CPUID_FEATURE_CHECK(avx512pf, AVX512PF);
++CPUID_FEATURE_CHECK(avx512er, AVX512ER);
++CPUID_FEATURE_CHECK(avx512vl, AVX512VL);
++CPUID_FEATURE_CHECK(aes, AES);
++CPUID_FEATURE_CHECK(pclmulqdq, PCLMULQDQ);
++
++/*
++ * Detect register set support
++ */
++static inline boolean_t
++__simd_state_enabled(const uint64_t state)
++{
++      boolean_t has_osxsave;
++      uint64_t xcr0;
++
++      has_osxsave = __cpuid_has_osxsave();
++      if (!has_osxsave)
++              return (B_FALSE);
++
++      xcr0 = xgetbv(0);
++      return ((xcr0 & state) == state);
++}
++
++#define       _XSTATE_SSE_AVX         (0x2 | 0x4)
++#define       _XSTATE_AVX512          (0xE0 | _XSTATE_SSE_AVX)
++
++#define       __ymm_enabled()         __simd_state_enabled(_XSTATE_SSE_AVX)
++#define       __zmm_enabled()         __simd_state_enabled(_XSTATE_AVX512)
++
++/*
++ * Check if SSE instruction set is available
++ */
++static inline boolean_t
++zfs_sse_available(void)
++{
++      return (__cpuid_has_sse());
++}
++
++/*
++ * Check if SSE2 instruction set is available
++ */
++static inline boolean_t
++zfs_sse2_available(void)
++{
++      return (__cpuid_has_sse2());
++}
++
++/*
++ * Check if SSE3 instruction set is available
++ */
++static inline boolean_t
++zfs_sse3_available(void)
++{
++      return (__cpuid_has_sse3());
++}
++
++/*
++ * Check if SSSE3 instruction set is available
++ */
++static inline boolean_t
++zfs_ssse3_available(void)
++{
++      return (__cpuid_has_ssse3());
++}
++
++/*
++ * Check if SSE4.1 instruction set is available
++ */
++static inline boolean_t
++zfs_sse4_1_available(void)
++{
++      return (__cpuid_has_sse4_1());
++}
++
++/*
++ * Check if SSE4.2 instruction set is available
++ */
++static inline boolean_t
++zfs_sse4_2_available(void)
++{
++      return (__cpuid_has_sse4_2());
++}
++
++/*
++ * Check if AVX instruction set is available
++ */
++static inline boolean_t
++zfs_avx_available(void)
++{
++      return (__cpuid_has_avx() && __ymm_enabled());
++}
++
++/*
++ * Check if AVX2 instruction set is available
++ */
++static inline boolean_t
++zfs_avx2_available(void)
++{
++      return (__cpuid_has_avx2() && __ymm_enabled());
++}
++
++/*
++ * Check if BMI1 instruction set is available
++ */
++static inline boolean_t
++zfs_bmi1_available(void)
++{
++      return (__cpuid_has_bmi1());
++}
++
++/*
++ * Check if BMI2 instruction set is available
++ */
++static inline boolean_t
++zfs_bmi2_available(void)
++{
++      return (__cpuid_has_bmi2());
++}
++
++/*
++ * Check if AES instruction set is available
++ */
++static inline boolean_t
++zfs_aes_available(void)
++{
++      return (__cpuid_has_aes());
++}
++
++/*
++ * Check if PCLMULQDQ instruction set is available
++ */
++static inline boolean_t
++zfs_pclmulqdq_available(void)
++{
++      return (__cpuid_has_pclmulqdq());
++}
++
++/*
++ * AVX-512 family of instruction sets:
++ *
++ * AVX512F    Foundation
++ * AVX512CD   Conflict Detection Instructions
++ * AVX512ER   Exponential and Reciprocal Instructions
++ * AVX512PF   Prefetch Instructions
++ *
++ * AVX512BW   Byte and Word Instructions
++ * AVX512DQ   Double-word and Quadword Instructions
++ * AVX512VL   Vector Length Extensions
++ *
++ * AVX512IFMA Integer Fused Multiply Add (Not supported by kernel 4.4)
++ * AVX512VBMI Vector Byte Manipulation Instructions
++ */
++
++/*
++ * Check if AVX512F instruction set is available
++ */
++static inline boolean_t
++zfs_avx512f_available(void)
++{
++      return (__cpuid_has_avx512f() && __zmm_enabled());
++}
++
++/*
++ * Check if AVX512CD instruction set is available
++ */
++static inline boolean_t
++zfs_avx512cd_available(void)
++{
++      return (__cpuid_has_avx512cd() && __zmm_enabled());
++}
++
++/*
++ * Check if AVX512ER instruction set is available
++ */
++static inline boolean_t
++zfs_avx512er_available(void)
++{
++      return (__cpuid_has_avx512er() && __zmm_enabled());
++}
++
++/*
++ * Check if AVX512PF instruction set is available
++ */
++static inline boolean_t
++zfs_avx512pf_available(void)
++{
++      return (__cpuid_has_avx512pf() && __zmm_enabled());
++}
++
++/*
++ * Check if AVX512BW instruction set is available
++ */
++static inline boolean_t
++zfs_avx512bw_available(void)
++{
++      return (__cpuid_has_avx512bw() && __zmm_enabled());
++}
++
++/*
++ * Check if AVX512DQ instruction set is available
++ */
++static inline boolean_t
++zfs_avx512dq_available(void)
++{
++      return (__cpuid_has_avx512dq() && __zmm_enabled());
++}
++
++/*
++ * Check if AVX512VL instruction set is available
++ */
++static inline boolean_t
++zfs_avx512vl_available(void)
++{
++      return (__cpuid_has_avx512vl() && __zmm_enabled());
++}
++
++/*
++ * Check if AVX512IFMA instruction set is available
++ */
++static inline boolean_t
++zfs_avx512ifma_available(void)
++{
++      return (__cpuid_has_avx512ifma() && __zmm_enabled());
++}
++
++/*
++ * Check if AVX512VBMI instruction set is available
++ */
++static inline boolean_t
++zfs_avx512vbmi_available(void)
++{
++      return (__cpuid_has_avx512f() && __cpuid_has_avx512vbmi() &&
++          __zmm_enabled());
++}
++
++#elif defined(__aarch64__)
++
++#define       kfpu_allowed()          1
++#define       kfpu_initialize(tsk)    do {} while (0)
++#define       kfpu_begin()            do {} while (0)
++#define       kfpu_end()              do {} while (0)
++
++#else
++
++#define       kfpu_allowed()          0
++#define       kfpu_initialize(tsk)    do {} while (0)
++#define       kfpu_begin()            do {} while (0)
++#define       kfpu_end()              do {} while (0)
++
++#endif
++
++#endif /* _LIBSPL_SYS_SIMD_H */
+diff --git a/module/Makefile.in b/module/Makefile.in
+index 7477dbe56..bf0eb101c 100644
+--- a/module/Makefile.in
++++ b/module/Makefile.in
+@@ -12,7 +12,9 @@ INSTALL_MOD_DIR ?= extra
+ ZFS_MODULE_CFLAGS += -std=gnu99 -Wno-declaration-after-statement
+ ZFS_MODULE_CFLAGS += @KERNEL_DEBUG_CFLAGS@
+ ZFS_MODULE_CFLAGS += -include @abs_top_builddir@/zfs_config.h
+-ZFS_MODULE_CFLAGS += -I@abs_top_srcdir@/include/spl
++ZFS_MODULE_CFLAGS += -I@abs_top_srcdir@/include/os/linux/kernel
++ZFS_MODULE_CFLAGS += -I@abs_top_srcdir@/include/os/linux/spl
++ZFS_MODULE_CFLAGS += -I@abs_top_srcdir@/include/os/linux/zfs
+ ZFS_MODULE_CFLAGS += -I@abs_top_srcdir@/include
+ ZFS_MODULE_CPPFLAGS += -D_KERNEL
+diff --git a/module/icp/algs/aes/aes_impl.c b/module/icp/algs/aes/aes_impl.c
+index 0f11f9999..b60b16cc0 100644
+--- a/module/icp/algs/aes/aes_impl.c
++++ b/module/icp/algs/aes/aes_impl.c
+@@ -25,9 +25,9 @@
+ #include <sys/zfs_context.h>
+ #include <sys/crypto/icp.h>
+ #include <sys/crypto/spi.h>
++#include <sys/simd.h>
+ #include <modes/modes.h>
+ #include <aes/aes_impl.h>
+-#include <linux/simd.h>
+ /*
+  * Initialize AES encryption and decryption key schedules.
+diff --git a/module/icp/algs/aes/aes_impl_aesni.c b/module/icp/algs/aes/aes_impl_aesni.c
+index 222c176aa..4b5eefd71 100644
+--- a/module/icp/algs/aes/aes_impl_aesni.c
++++ b/module/icp/algs/aes/aes_impl_aesni.c
+@@ -24,7 +24,8 @@
+ #if defined(__x86_64) && defined(HAVE_AES)
+-#include <linux/simd_x86.h>
++#include <sys/simd.h>
++#include <sys/types.h>
+ /* These functions are used to execute AES-NI instructions: */
+ extern int rijndael_key_setup_enc_intel(uint32_t rk[],
+diff --git a/module/icp/algs/aes/aes_impl_x86-64.c b/module/icp/algs/aes/aes_impl_x86-64.c
+index b4515fa22..0ee7ee99c 100644
+--- a/module/icp/algs/aes/aes_impl_x86-64.c
++++ b/module/icp/algs/aes/aes_impl_x86-64.c
+@@ -24,7 +24,7 @@
+ #if defined(__x86_64)
+-#include <linux/simd_x86.h>
++#include <sys/simd.h>
+ /* These functions are used to execute amd64 instructions for AMD or Intel: */
+ extern int rijndael_key_setup_enc_amd64(uint32_t rk[],
+diff --git a/module/icp/algs/modes/gcm.c b/module/icp/algs/modes/gcm.c
+index 423b70e2c..1fb8e256a 100644
+--- a/module/icp/algs/modes/gcm.c
++++ b/module/icp/algs/modes/gcm.c
+@@ -28,8 +28,8 @@
+ #include <sys/crypto/icp.h>
+ #include <sys/crypto/impl.h>
+ #include <sys/byteorder.h>
++#include <sys/simd.h>
+ #include <modes/gcm_impl.h>
+-#include <linux/simd.h>
+ #define       GHASH(c, d, t, o) \
+       xor_block((uint8_t *)(d), (uint8_t *)(c)->gcm_ghash); \
+diff --git a/module/icp/algs/modes/gcm_pclmulqdq.c b/module/icp/algs/modes/gcm_pclmulqdq.c
+index 8a43ba33a..05920115c 100644
+--- a/module/icp/algs/modes/gcm_pclmulqdq.c
++++ b/module/icp/algs/modes/gcm_pclmulqdq.c
+@@ -24,12 +24,12 @@
+ #if defined(__x86_64) && defined(HAVE_PCLMULQDQ)
+-#include <linux/simd_x86.h>
++#include <sys/types.h>
++#include <sys/simd.h>
+ /* These functions are used to execute pclmulqdq based assembly methods */
+ extern void gcm_mul_pclmulqdq(uint64_t *, uint64_t *, uint64_t *);
+-
+ #include <modes/gcm_impl.h>
+ /*
+diff --git a/module/icp/io/aes.c b/module/icp/io/aes.c
+index 51538bc60..4b2dbd6e1 100644
+--- a/module/icp/io/aes.c
++++ b/module/icp/io/aes.c
+@@ -212,8 +212,8 @@ aes_mod_init(void)
+        * are run in dedicated kernel threads to allow Linux 5.0+ kernels
+        * to use SIMD operations.  If for some reason this isn't possible,
+        * fallback to the generic implementations.  See the comment in
+-       * include/linux/simd_x86.h for additional details.  Additionally,
+-       * this has the benefit of allowing them to be run in parallel.
++       * linux/simd_x86.h for additional details.  Additionally, this has
++       * the benefit of allowing them to be run in parallel.
+        */
+       taskqid_t aes_id = taskq_dispatch(system_taskq, aes_impl_init,
+           NULL, TQ_SLEEP);
+diff --git a/module/spl/spl-taskq.c b/module/spl/spl-taskq.c
+index 69d591ff7..90e1d0a4d 100644
+--- a/module/spl/spl-taskq.c
++++ b/module/spl/spl-taskq.c
+@@ -28,7 +28,7 @@
+ #include <sys/taskq.h>
+ #include <sys/kmem.h>
+ #include <sys/tsd.h>
+-#include <linux/simd.h>
++#include <sys/simd.h>
+ int spl_taskq_thread_bind = 0;
+ module_param(spl_taskq_thread_bind, int, 0644);
+diff --git a/module/spl/spl-thread.c b/module/spl/spl-thread.c
+index 07e3a1bff..29de9252a 100644
+--- a/module/spl/spl-thread.c
++++ b/module/spl/spl-thread.c
+@@ -27,7 +27,7 @@
+ #include <sys/thread.h>
+ #include <sys/kmem.h>
+ #include <sys/tsd.h>
+-#include <linux/simd.h>
++#include <sys/simd.h>
+ /*
+  * Thread interfaces
+diff --git a/module/zcommon/zfs_fletcher.c b/module/zcommon/zfs_fletcher.c
+index 9187a7c1e..c14c95fa2 100644
+--- a/module/zcommon/zfs_fletcher.c
++++ b/module/zcommon/zfs_fletcher.c
+@@ -137,10 +137,10 @@
+ #include <sys/sysmacros.h>
+ #include <sys/byteorder.h>
+ #include <sys/spa.h>
++#include <sys/simd.h>
+ #include <sys/zio_checksum.h>
+ #include <sys/zfs_context.h>
+ #include <zfs_fletcher.h>
+-#include <linux/simd.h>
+ #define       FLETCHER_MIN_SIMD_SIZE  64
+@@ -773,7 +773,7 @@ fletcher_4_init(void)
+       /*
+        * For 5.0 and latter Linux kernels the fletcher 4 benchmarks are
+        * run in a kernel threads.  This is needed to take advantage of the
+-       * SIMD functionality, see include/linux/simd_x86.h for details.
++       * SIMD functionality, see linux/simd_x86.h for details.
+        */
+       taskqid_t id = taskq_dispatch(system_taskq, fletcher_4_benchmark,
+           NULL, TQ_SLEEP);
+diff --git a/module/zcommon/zfs_fletcher_aarch64_neon.c b/module/zcommon/zfs_fletcher_aarch64_neon.c
+index 3b3c1b52b..c95a71681 100644
+--- a/module/zcommon/zfs_fletcher_aarch64_neon.c
++++ b/module/zcommon/zfs_fletcher_aarch64_neon.c
+@@ -43,7 +43,7 @@
+ #if defined(__aarch64__)
+-#include <linux/simd_aarch64.h>
++#include <sys/simd.h>
+ #include <sys/spa_checksum.h>
+ #include <sys/strings.h>
+ #include <zfs_fletcher.h>
+diff --git a/module/zcommon/zfs_fletcher_avx512.c b/module/zcommon/zfs_fletcher_avx512.c
+index 0d4cff21a..43806f264 100644
+--- a/module/zcommon/zfs_fletcher_avx512.c
++++ b/module/zcommon/zfs_fletcher_avx512.c
+@@ -24,11 +24,11 @@
+ #if defined(__x86_64) && defined(HAVE_AVX512F)
+-#include <linux/simd_x86.h>
+ #include <sys/byteorder.h>
+ #include <sys/frame.h>
+ #include <sys/spa_checksum.h>
+ #include <sys/strings.h>
++#include <sys/simd.h>
+ #include <zfs_fletcher.h>
+ #define       __asm __asm__ __volatile__
+diff --git a/module/zcommon/zfs_fletcher_intel.c b/module/zcommon/zfs_fletcher_intel.c
+index 7f12efe6d..5136a01ec 100644
+--- a/module/zcommon/zfs_fletcher_intel.c
++++ b/module/zcommon/zfs_fletcher_intel.c
+@@ -42,8 +42,8 @@
+ #if defined(HAVE_AVX) && defined(HAVE_AVX2)
+-#include <linux/simd_x86.h>
+ #include <sys/spa_checksum.h>
++#include <sys/simd.h>
+ #include <sys/strings.h>
+ #include <zfs_fletcher.h>
+diff --git a/module/zcommon/zfs_fletcher_sse.c b/module/zcommon/zfs_fletcher_sse.c
+index e6389d6e5..15ce9b07f 100644
+--- a/module/zcommon/zfs_fletcher_sse.c
++++ b/module/zcommon/zfs_fletcher_sse.c
+@@ -43,7 +43,7 @@
+ #if defined(HAVE_SSE2)
+-#include <linux/simd_x86.h>
++#include <sys/simd.h>
+ #include <sys/spa_checksum.h>
+ #include <sys/byteorder.h>
+ #include <sys/strings.h>
+diff --git a/module/zfs/vdev_raidz_math.c b/module/zfs/vdev_raidz_math.c
+index ef514e9e1..86d4aabdc 100644
+--- a/module/zfs/vdev_raidz_math.c
++++ b/module/zfs/vdev_raidz_math.c
+@@ -29,7 +29,7 @@
+ #include <sys/zfs_debug.h>
+ #include <sys/vdev_raidz.h>
+ #include <sys/vdev_raidz_impl.h>
+-#include <linux/simd.h>
++#include <sys/simd.h>
+ extern boolean_t raidz_will_scalar_work(void);
+diff --git a/module/zfs/vdev_raidz_math_aarch64_neon_common.h b/module/zfs/vdev_raidz_math_aarch64_neon_common.h
+index 024917417..f47446753 100644
+--- a/module/zfs/vdev_raidz_math_aarch64_neon_common.h
++++ b/module/zfs/vdev_raidz_math_aarch64_neon_common.h
+@@ -23,7 +23,7 @@
+  */
+ #include <sys/types.h>
+-#include <linux/simd_aarch64.h>
++#include <sys/simd.h>
+ #define       __asm __asm__ __volatile__
+diff --git a/module/zfs/vdev_raidz_math_avx2.c b/module/zfs/vdev_raidz_math_avx2.c
+index a12eb6720..008e848d4 100644
+--- a/module/zfs/vdev_raidz_math_avx2.c
++++ b/module/zfs/vdev_raidz_math_avx2.c
+@@ -26,7 +26,7 @@
+ #if defined(__x86_64) && defined(HAVE_AVX2)
+ #include <sys/types.h>
+-#include <linux/simd_x86.h>
++#include <sys/simd.h>
+ #define       __asm __asm__ __volatile__
+diff --git a/module/zfs/vdev_raidz_math_avx512bw.c b/module/zfs/vdev_raidz_math_avx512bw.c
+index 2f545c9ec..38cdbedf7 100644
+--- a/module/zfs/vdev_raidz_math_avx512bw.c
++++ b/module/zfs/vdev_raidz_math_avx512bw.c
+@@ -28,7 +28,7 @@
+ #if defined(__x86_64) && defined(HAVE_AVX512BW)
+ #include <sys/types.h>
+-#include <linux/simd_x86.h>
++#include <sys/simd.h>
+ #define       __asm __asm__ __volatile__
+diff --git a/module/zfs/vdev_raidz_math_avx512f.c b/module/zfs/vdev_raidz_math_avx512f.c
+index 75af7a8ee..adbe9b0ef 100644
+--- a/module/zfs/vdev_raidz_math_avx512f.c
++++ b/module/zfs/vdev_raidz_math_avx512f.c
+@@ -28,7 +28,7 @@
+ #if defined(__x86_64) && defined(HAVE_AVX512F)
+ #include <sys/types.h>
+-#include <linux/simd_x86.h>
++#include <sys/simd.h>
+ #define       __asm __asm__ __volatile__
+diff --git a/module/zfs/vdev_raidz_math_sse2.c b/module/zfs/vdev_raidz_math_sse2.c
+index 5b3a9385c..70a21c10c 100644
+--- a/module/zfs/vdev_raidz_math_sse2.c
++++ b/module/zfs/vdev_raidz_math_sse2.c
+@@ -27,7 +27,7 @@
+ #if defined(__x86_64) && defined(HAVE_SSE2)
+ #include <sys/types.h>
+-#include <linux/simd_x86.h>
++#include <sys/simd.h>
+ #define       __asm __asm__ __volatile__
+diff --git a/module/zfs/vdev_raidz_math_ssse3.c b/module/zfs/vdev_raidz_math_ssse3.c
+index 62247cf8e..d5776a38a 100644
+--- a/module/zfs/vdev_raidz_math_ssse3.c
++++ b/module/zfs/vdev_raidz_math_ssse3.c
+@@ -27,7 +27,7 @@
+ #if defined(__x86_64) && defined(HAVE_SSSE3)
+ #include <sys/types.h>
+-#include <linux/simd_x86.h>
++#include <sys/simd.h>
+ #define       __asm __asm__ __volatile__
diff --git a/debian/patches/0011-Allow-FPU-usage-in-user-and-kernel-thread-contexts.patch b/debian/patches/0011-Allow-FPU-usage-in-user-and-kernel-thread-contexts.patch
new file mode 100644 (file)
index 0000000..38f94bd
--- /dev/null
@@ -0,0 +1,327 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Brian Behlendorf <behlendorf1@llnl.gov>
+Date: Wed, 9 Oct 2019 22:36:19 +0000
+Subject: [PATCH] Allow FPU usage in user and kernel thread contexts
+
+Even for dedicated kernel threads we apparently cannot be
+guaranteed that the kernel won't modify the FPU state which
+we saved in the task struck.  Allocate our own per-cpu state
+to preserve the saved register state.  Aside from correctness,
+this allows use of the FPU in user threads again.
+
+Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
+(cherry picked from commit 11170d9073edcbb613f5a4c992293cbb4e3c8e31)
+Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
+---
+ config/kernel-fpu.m4                         |  7 --
+ include/os/linux/kernel/linux/simd.h         |  1 -
+ include/os/linux/kernel/linux/simd_aarch64.h |  2 -
+ include/os/linux/kernel/linux/simd_x86.h     | 87 +++++++++++++-------
+ module/spl/spl-taskq.c                       |  2 -
+ module/spl/spl-thread.c                      |  2 -
+ module/zcommon/zfs_prop.c                    | 18 ++++
+ 7 files changed, 73 insertions(+), 46 deletions(-)
+
+diff --git a/config/kernel-fpu.m4 b/config/kernel-fpu.m4
+index 9ed9b14ad..15bea3c22 100644
+--- a/config/kernel-fpu.m4
++++ b/config/kernel-fpu.m4
+@@ -67,12 +67,6 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_FPU], [
+               #error Unsupported architecture
+               #endif
+-              #include <linux/sched.h>
+-
+-              #if !defined(PF_KTHREAD)
+-              #error PF_KTHREAD not defined
+-              #endif
+-
+               #ifdef HAVE_KERNEL_FPU_API_HEADER
+               #include <asm/fpu/api.h>
+               #include <asm/fpu/internal.h>
+@@ -94,7 +88,6 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_FPU], [
+               struct fregs_state *fr __attribute__ ((unused)) = &st->fsave;
+               struct fxregs_state *fxr __attribute__ ((unused)) = &st->fxsave;
+               struct xregs_state *xr __attribute__ ((unused)) = &st->xsave;
+-              fpu->last_cpu = -1;
+       ])
+ ])
+diff --git a/include/os/linux/kernel/linux/simd.h b/include/os/linux/kernel/linux/simd.h
+index 1f6574a90..5138a908b 100644
+--- a/include/os/linux/kernel/linux/simd.h
++++ b/include/os/linux/kernel/linux/simd.h
+@@ -33,7 +33,6 @@
+ #else
+ #define       kfpu_allowed()          0
+-#define       kfpu_initialize(tsk)    do {} while (0)
+ #define       kfpu_begin()            do {} while (0)
+ #define       kfpu_end()              do {} while (0)
+diff --git a/include/os/linux/kernel/linux/simd_aarch64.h b/include/os/linux/kernel/linux/simd_aarch64.h
+index ac530d920..f6cf3c377 100644
+--- a/include/os/linux/kernel/linux/simd_aarch64.h
++++ b/include/os/linux/kernel/linux/simd_aarch64.h
+@@ -27,7 +27,6 @@
+  *
+  * Kernel fpu methods:
+  *    kfpu_allowed()
+- *    kfpu_initialize()
+  *    kfpu_begin()
+  *    kfpu_end()
+  */
+@@ -43,7 +42,6 @@
+ #include <asm/neon.h>
+ #define       kfpu_allowed()          1
+-#define       kfpu_initialize(tsk)    do {} while (0)
+ #define       kfpu_begin()            kernel_neon_begin()
+ #define       kfpu_end()              kernel_neon_end()
+diff --git a/include/os/linux/kernel/linux/simd_x86.h b/include/os/linux/kernel/linux/simd_x86.h
+index 486e31845..c42ea918e 100644
+--- a/include/os/linux/kernel/linux/simd_x86.h
++++ b/include/os/linux/kernel/linux/simd_x86.h
+@@ -27,7 +27,6 @@
+  *
+  * Kernel fpu methods:
+  *    kfpu_allowed()
+- *    kfpu_initialize()
+  *    kfpu_begin()
+  *    kfpu_end()
+  *
+@@ -99,7 +98,6 @@
+ #if defined(KERNEL_EXPORTS_X86_FPU)
+ #define       kfpu_allowed()          1
+-#define       kfpu_initialize(tsk)    do {} while (0)
+ #if defined(HAVE_UNDERSCORE_KERNEL_FPU)
+ #define       kfpu_begin()            \
+@@ -129,16 +127,52 @@
+ /*
+  * When the kernel_fpu_* symbols are unavailable then provide our own
+- * versions which allow the FPU to be safely used in kernel threads.
+- * In practice, this is not a significant restriction for ZFS since the
+- * vast majority of SIMD operations are performed by the IO pipeline.
++ * versions which allow the FPU to be safely used.
+  */
+ #if defined(HAVE_KERNEL_FPU_INTERNAL)
++extern struct fpu **zfs_kfpu_fpregs;
++
+ /*
+- * FPU usage only allowed in dedicated kernel threads.
++ * Initialize per-cpu variables to store FPU state.
+  */
+-#define       kfpu_allowed()          (current->flags & PF_KTHREAD)
++static inline void
++kfpu_fini(void)
++{
++      int cpu;
++
++      for_each_possible_cpu(cpu) {
++              if (zfs_kfpu_fpregs[cpu] != NULL) {
++                      kfree(zfs_kfpu_fpregs[cpu]);
++              }
++      }
++
++      kfree(zfs_kfpu_fpregs);
++}
++
++static inline int
++kfpu_init(void)
++{
++      int cpu;
++
++      zfs_kfpu_fpregs = kzalloc(num_possible_cpus() *
++          sizeof (struct fpu *), GFP_KERNEL);
++      if (zfs_kfpu_fpregs == NULL)
++              return (ENOMEM);
++
++      for_each_possible_cpu(cpu) {
++              zfs_kfpu_fpregs[cpu] = kmalloc_node(sizeof (struct fpu),
++                  GFP_KERNEL, cpu_to_node(cpu));
++              if (zfs_kfpu_fpregs[cpu] == NULL) {
++                      kfpu_fini();
++                      return (ENOMEM);
++              }
++      }
++
++      return (0);
++}
++
++#define       kfpu_allowed()          1
+ #define       ex_handler_fprestore    ex_handler_default
+ /*
+@@ -154,15 +188,6 @@
+ #define       kfpu_fxsr_clean(rval)   __asm("fnclex; emms; fildl %P[addr]" \
+                                   : : [addr] "m" (rval));
+-static inline void
+-kfpu_initialize(void)
+-{
+-      WARN_ON_ONCE(!(current->flags & PF_KTHREAD));
+-
+-      /* Invalidate the task's FPU state */
+-      current->thread.fpu.last_cpu = -1;
+-}
+-
+ static inline void
+ kfpu_save_xsave(struct xregs_state *addr, uint64_t mask)
+ {
+@@ -193,8 +218,6 @@ kfpu_save_fsave(struct fregs_state *addr)
+ static inline void
+ kfpu_begin(void)
+ {
+-      WARN_ON_ONCE(!kfpu_allowed());
+-
+       /*
+        * Preemption and interrupts must be disabled for the critical
+        * region where the FPU state is being modified.
+@@ -204,20 +227,18 @@ kfpu_begin(void)
+       /*
+        * The current FPU registers need to be preserved by kfpu_begin()
+-       * and restored by kfpu_end().  This is always required because we
+-       * can not call __cpu_invalidate_fpregs_state() to invalidate the
+-       * per-cpu FPU state and force them to be restored.  Furthermore,
+-       * this implementation relies on the space provided in the task
+-       * structure to store the user FPU state.  As such, it can only
+-       * be used with dedicated kernels which by definition will never
+-       * store user FPU state.
++       * and restored by kfpu_end().  They are stored in a dedicated
++       * per-cpu variable, not in the task struct, this allows any user
++       * FPU state to be correctly preserved and restored.
+        */
++      struct fpu *fpu = zfs_kfpu_fpregs[smp_processor_id()];
++
+       if (static_cpu_has(X86_FEATURE_XSAVE)) {
+-              kfpu_save_xsave(&current->thread.fpu.state.xsave, ~0);
++              kfpu_save_xsave(&fpu->state.xsave, ~0);
+       } else if (static_cpu_has(X86_FEATURE_FXSR)) {
+-              kfpu_save_fxsr(&current->thread.fpu.state.fxsave);
++              kfpu_save_fxsr(&fpu->state.fxsave);
+       } else {
+-              kfpu_save_fsave(&current->thread.fpu.state.fsave);
++              kfpu_save_fsave(&fpu->state.fsave);
+       }
+ }
+@@ -258,12 +279,14 @@ kfpu_restore_fsave(struct fregs_state *addr)
+ static inline void
+ kfpu_end(void)
+ {
++      struct fpu *fpu = zfs_kfpu_fpregs[smp_processor_id()];
++
+       if (static_cpu_has(X86_FEATURE_XSAVE)) {
+-              kfpu_restore_xsave(&current->thread.fpu.state.xsave, ~0);
++              kfpu_restore_xsave(&fpu->state.xsave, ~0);
+       } else if (static_cpu_has(X86_FEATURE_FXSR)) {
+-              kfpu_restore_fxsr(&current->thread.fpu.state.fxsave);
++              kfpu_restore_fxsr(&fpu->state.fxsave);
+       } else {
+-              kfpu_restore_fsave(&current->thread.fpu.state.fsave);
++              kfpu_restore_fsave(&fpu->state.fsave);
+       }
+       local_irq_enable();
+@@ -276,7 +299,6 @@ kfpu_end(void)
+  * FPU support is unavailable.
+  */
+ #define       kfpu_allowed()          0
+-#define       kfpu_initialize(tsk)    do {} while (0)
+ #define       kfpu_begin()            do {} while (0)
+ #define       kfpu_end()              do {} while (0)
+@@ -286,6 +308,7 @@ kfpu_end(void)
+ /*
+  * Linux kernel provides an interface for CPU feature testing.
+  */
++
+ /*
+  * Detect register set support
+  */
+diff --git a/module/spl/spl-taskq.c b/module/spl/spl-taskq.c
+index 90e1d0a4d..a39f94e4c 100644
+--- a/module/spl/spl-taskq.c
++++ b/module/spl/spl-taskq.c
+@@ -28,7 +28,6 @@
+ #include <sys/taskq.h>
+ #include <sys/kmem.h>
+ #include <sys/tsd.h>
+-#include <sys/simd.h>
+ int spl_taskq_thread_bind = 0;
+ module_param(spl_taskq_thread_bind, int, 0644);
+@@ -854,7 +853,6 @@ taskq_thread(void *args)
+       sigfillset(&blocked);
+       sigprocmask(SIG_BLOCK, &blocked, NULL);
+       flush_signals(current);
+-      kfpu_initialize();
+       tsd_set(taskq_tsd, tq);
+       spin_lock_irqsave_nested(&tq->tq_lock, flags, tq->tq_lock_class);
+diff --git a/module/spl/spl-thread.c b/module/spl/spl-thread.c
+index 29de9252a..0352a31ea 100644
+--- a/module/spl/spl-thread.c
++++ b/module/spl/spl-thread.c
+@@ -27,7 +27,6 @@
+ #include <sys/thread.h>
+ #include <sys/kmem.h>
+ #include <sys/tsd.h>
+-#include <sys/simd.h>
+ /*
+  * Thread interfaces
+@@ -55,7 +54,6 @@ thread_generic_wrapper(void *arg)
+       args = tp->tp_args;
+       set_current_state(tp->tp_state);
+       set_user_nice((kthread_t *)current, PRIO_TO_NICE(tp->tp_pri));
+-      kfpu_initialize();
+       kmem_free(tp->tp_name, tp->tp_name_size);
+       kmem_free(tp, sizeof (thread_priv_t));
+diff --git a/module/zcommon/zfs_prop.c b/module/zcommon/zfs_prop.c
+index dab749138..b5fa1c2f4 100644
+--- a/module/zcommon/zfs_prop.c
++++ b/module/zcommon/zfs_prop.c
+@@ -853,10 +853,27 @@ zfs_prop_align_right(zfs_prop_t prop)
+ #endif
+ #if defined(_KERNEL)
++
++#if defined(HAVE_KERNEL_FPU_INTERNAL)
++#include <linux/simd.h>
++
++struct fpu **zfs_kfpu_fpregs;
++EXPORT_SYMBOL(zfs_kfpu_fpregs);
++
++#else
++#define       kfpu_init()     0
++#define       kfpu_fini()     ((void) 0)
++#endif /* HAVE_KERNEL_FPU_INTERNAL */
++
+ static int __init
+ zcommon_init(void)
+ {
++      int error = kfpu_init();
++      if (error)
++              return (-error);
++
+       fletcher_4_init();
++
+       return (0);
+ }
+@@ -864,6 +881,7 @@ static void __exit
+ zcommon_fini(void)
+ {
+       fletcher_4_fini();
++      kfpu_fini();
+ }
+ module_init(zcommon_init);
index d42473c6fbcde4d8503c9b8d9f0090a10b11b6dd..a1908e642fc399e4f50395dfb1551c5d77fc2e40 100644 (file)
@@ -4,6 +4,8 @@
 0004-import-with-d-dev-disk-by-id-in-scan-service.patch
 0005-Enable-zed-emails.patch
 0006-Linux-5.0-compat-SIMD-compatibility.patch
-0007-Fix-CONFIG_X86_DEBUG_FPU-build-failure.patch
-0008-SIMD-FPU-register-save-restore-is-also-required-on-5.patch
-0009-Perform-KABI-checks-in-parallel.patch
+0007-Perform-KABI-checks-in-parallel.patch
+0008-Linux-4.14-4.19-5.0-compat-SIMD-save-restore.patch
+0009-Fix-CONFIG_X86_DEBUG_FPU-build-failure.patch
+0010-OpenZFS-restructuring-move-platform-specific-headers.patch
+0011-Allow-FPU-usage-in-user-and-kernel-thread-contexts.patch