]> git.proxmox.com Git - mirror_spl.git/blobdiff - config/spl-build.m4
Linux 4.11 compat: vfs_getattr() takes 4 args
[mirror_spl.git] / config / spl-build.m4
index 264989d5c1caf9cbf3dd54698bd4fef6824e3c29..fc0efcf39cbdf1132d3cb28d699989603f697543 100644 (file)
@@ -18,43 +18,41 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [
        AC_SUBST(KERNELCPPFLAGS)
 
        SPL_AC_DEBUG
-       SPL_AC_DEBUG_LOG
        SPL_AC_DEBUG_KMEM
        SPL_AC_DEBUG_KMEM_TRACKING
        SPL_AC_TEST_MODULE
        SPL_AC_ATOMIC_SPINLOCK
        SPL_AC_SHRINKER_CALLBACK
        SPL_AC_CTL_NAME
+       SPL_AC_CONFIG_TRIM_UNUSED_KSYMS
        SPL_AC_PDE_DATA
-       SPL_AC_MUTEX_OWNER
-       SPL_AC_MUTEX_OWNER_TASK_STRUCT
-       SPL_AC_SET_FS_PWD
        SPL_AC_SET_FS_PWD_WITH_CONST
        SPL_AC_2ARGS_VFS_UNLINK
        SPL_AC_4ARGS_VFS_RENAME
-       SPL_AC_VFS_FSYNC
        SPL_AC_2ARGS_VFS_FSYNC
        SPL_AC_INODE_TRUNCATE_RANGE
        SPL_AC_FS_STRUCT_SPINLOCK
-       SPL_AC_CRED_STRUCT
        SPL_AC_KUIDGID_T
-       SPL_AC_GROUPS_SEARCH
        SPL_AC_PUT_TASK_STRUCT
-       SPL_AC_5ARGS_PROC_HANDLER
-       SPL_AC_KVASPRINTF
-       SPL_AC_EXPORTED_RWSEM_IS_LOCKED
        SPL_AC_KERNEL_FALLOCATE
-       SPL_AC_KERN_PATH
        SPL_AC_CONFIG_ZLIB_INFLATE
        SPL_AC_CONFIG_ZLIB_DEFLATE
        SPL_AC_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE
        SPL_AC_SHRINK_CONTROL_STRUCT
        SPL_AC_RWSEM_SPINLOCK_IS_RAW
+       SPL_AC_RWSEM_ACTIVITY
+       SPL_AC_RWSEM_ATOMIC_LONG_COUNT
        SPL_AC_SCHED_RT_HEADER
+       SPL_AC_4ARGS_VFS_GETATTR
+       SPL_AC_3ARGS_VFS_GETATTR
        SPL_AC_2ARGS_VFS_GETATTR
        SPL_AC_USLEEP_RANGE
        SPL_AC_KMEM_CACHE_ALLOCFLAGS
        SPL_AC_WAIT_ON_BIT
+       SPL_AC_MUTEX_OWNER
+       SPL_AC_INODE_LOCK
+       SPL_AC_GROUP_INFO_GID
+       SPL_AC_KMEM_CACHE_CREATE_USERCOPY
 ])
 
 AC_DEFUN([SPL_AC_MODULE_SYMVERS], [
@@ -226,7 +224,7 @@ AC_DEFUN([SPL_AC_RPM], [
                AC_MSG_RESULT([$HAVE_RPMBUILD])
        ])
 
-       RPM_DEFINE_COMMON='--define "$(DEBUG_SPL) 1" --define "$(DEBUG_LOG) 1" --define "$(DEBUG_KMEM) 1" --define "$(DEBUG_KMEM_TRACKING) 1"'
+       RPM_DEFINE_COMMON='--define "$(DEBUG_SPL) 1" --define "$(DEBUG_KMEM) 1" --define "$(DEBUG_KMEM_TRACKING) 1"'
        RPM_DEFINE_UTIL=
        RPM_DEFINE_KMOD='--define "kernels $(LINUX_VERSION)"'
        RPM_DEFINE_DKMS=
@@ -239,7 +237,7 @@ AC_DEFUN([SPL_AC_RPM], [
        RPM_SPEC_DIR="rpm/generic"
        AC_ARG_WITH([spec],
                AS_HELP_STRING([--with-spec=SPEC],
-               [Spec files 'generic|fedora']),
+               [Spec files 'generic|redhat']),
                [RPM_SPEC_DIR="rpm/$withval"])
 
        AC_MSG_CHECKING([whether spec files are available])
@@ -459,52 +457,18 @@ AC_DEFUN([SPL_AC_DEBUG], [
        AC_MSG_RESULT([$enable_debug])
 ])
 
-dnl #
-dnl # Enabled by default it provides a basic debug log infrastructure.
-dnl # Each subsystem registers itself with a name and logs messages
-dnl # using predefined types.  If the debug mask it set to allow the
-dnl # message type it will be written to the internal log.  The log
-dnl # can be dumped to a file by echoing 1 to the 'dump' proc entry,
-dnl # after dumping the log it must be decoded using the spl utility.
-dnl #
-dnl # echo 1 >/proc/sys/kernel/spl/debug/dump
-dnl # spl /tmp/spl-log.xxx.yyy /tmp/spl-log.xxx.yyy.txt
-dnl #
-AC_DEFUN([SPL_AC_DEBUG_LOG], [
-       AC_ARG_ENABLE([debug-log],
-               [AS_HELP_STRING([--enable-debug-log],
-               [Enable basic debug logging @<:@default=yes@:>@])],
-               [],
-               [enable_debug_log=yes])
-
-       AS_IF([test "x$enable_debug_log" = xyes],
-       [
-               KERNELCPPFLAGS="${KERNELCPPFLAGS} -DDEBUG_LOG"
-               DEBUG_LOG="_with_debug_log"
-               AC_DEFINE([DEBUG_LOG], [1],
-               [Define to 1 to enable basic debug logging])
-       ], [
-               DEBUG_LOG="_without_debug_log"
-       ])
-
-       AC_SUBST(DEBUG_LOG)
-       AC_MSG_CHECKING([whether basic debug logging is enabled])
-       AC_MSG_RESULT([$enable_debug_log])
-])
-
 dnl #
 dnl # Enabled by default it provides a minimal level of memory tracking.
 dnl # A total count of bytes allocated is kept for each alloc and free.
 dnl # Then at module unload time a report to the console will be printed
-dnl # if memory was leaked.  Additionally, /proc/spl/kmem/slab will exist
-dnl # and provide an easy way to inspect the kmem based slab.
+dnl # if memory was leaked.
 dnl #
 AC_DEFUN([SPL_AC_DEBUG_KMEM], [
        AC_ARG_ENABLE([debug-kmem],
                [AS_HELP_STRING([--enable-debug-kmem],
-               [Enable basic kmem accounting @<:@default=yes@:>@])],
+               [Enable basic kmem accounting @<:@default=no@:>@])],
                [],
-               [enable_debug_kmem=yes])
+               [enable_debug_kmem=no])
 
        AS_IF([test "x$enable_debug_kmem" = xyes],
        [
@@ -718,16 +682,19 @@ AC_DEFUN([SPL_AC_TEST_MODULE],
                fi
        ])
 
-       AC_RUN_IFELSE([
-               AC_LANG_PROGRAM([
-                       #include "$LINUX/include/linux/license.h"
+       AS_IF([test "x$cross_compiling" != xyes], [
+               AC_RUN_IFELSE([
+                       AC_LANG_PROGRAM([
+                               #include "$LINUX/include/linux/license.h"
+                       ], [
+                               return !license_is_gpl_compatible(
+                                   "$SPL_META_LICENSE");
+                       ])
+               ], [
+                       AC_DEFINE([SPL_IS_GPL_COMPATIBLE], [1],
+                           [Define to 1 if GPL-only symbols can be used])
                ], [
-                       return !license_is_gpl_compatible("$SPL_META_LICENSE");
                ])
-       ], [
-               AC_DEFINE([SPL_IS_GPL_COMPATIBLE], [1],
-                   [Define to 1 if GPL-only symbols can be used])
-       ], [
        ])
 ])
 
@@ -906,54 +873,6 @@ AC_DEFUN([SPL_AC_CTL_NAME], [
        ])
 ])
 
-dnl #
-dnl # 2.6.29 API change,
-dnl # Adaptive mutexs were introduced which track the mutex owner.  The
-dnl # mutex wrappers leverage this functionality to avoid tracking the
-dnl # owner multipe times.
-dnl #
-AC_DEFUN([SPL_AC_MUTEX_OWNER], [
-       AC_MSG_CHECKING([whether struct mutex has owner])
-       SPL_LINUX_TRY_COMPILE([
-               #include <linux/mutex.h>
-       ],[
-               struct mutex mtx __attribute__ ((unused));
-               mtx.owner = NULL;
-       ],[
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_MUTEX_OWNER, 1, [struct mutex has owner])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-])
-
-dnl #
-dnl # 2.6.39 API change,
-dnl # Owner type change.  A Linux mutex prior to 2.6.39 would store
-dnl # the owner as a thread_info pointer when CONFIG_DEBUG_MUTEXES
-dnl # was defined.  As of 2.6.39 this was changed to a task_struct
-dnl # pointer which frankly makes a lot more sense.
-dnl #
-AC_DEFUN([SPL_AC_MUTEX_OWNER_TASK_STRUCT], [
-       AC_MSG_CHECKING([whether struct mutex owner is a task_struct])
-       tmp_flags="$EXTRA_KCFLAGS"
-       EXTRA_KCFLAGS="-Werror"
-       SPL_LINUX_TRY_COMPILE([
-               #include <linux/mutex.h>
-               #include <linux/sched.h>
-       ],[
-               struct mutex mtx __attribute__ ((unused));
-               mtx.owner = current;
-       ],[
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_MUTEX_OWNER_TASK_STRUCT, 1,
-               [struct mutex owner is a task_struct])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-       EXTRA_KCFLAGS="$tmp_flags"
-])
-
 dnl #
 dnl # 3.10 API change,
 dnl # PDE is replaced by PDE_DATA
@@ -972,24 +891,6 @@ AC_DEFUN([SPL_AC_PDE_DATA], [
        ])
 ])
 
-dnl #
-dnl # Symbol available in RHEL kernels not in stock kernels.
-dnl #
-AC_DEFUN([SPL_AC_SET_FS_PWD],
-       [AC_MSG_CHECKING([whether set_fs_pwd() is available])
-       SPL_LINUX_TRY_COMPILE_SYMBOL([
-               #include <linux/spinlock.h>
-               #include <linux/fs_struct.h>
-       ], [
-               (void) set_fs_pwd;
-       ], [set_fs_pwd], [], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_SET_FS_PWD, 1, [set_fs_pwd() is available])
-       ], [
-               AC_MSG_RESULT(no)
-       ])
-])
-
 dnl #
 dnl # 3.9 API change
 dnl # set_fs_pwd takes const struct path *
@@ -1030,6 +931,10 @@ AC_DEFUN([SPL_AC_SET_FS_PWD_WITH_CONST],
        EXTRA_KCFLAGS="$tmp_flags"
 ])
 
+dnl #
+dnl # 3.13 API change
+dnl # vfs_unlink() updated to take a third delegated_inode argument.
+dnl #
 AC_DEFUN([SPL_AC_2ARGS_VFS_UNLINK],
        [AC_MSG_CHECKING([whether vfs_unlink() wants 2 args])
        SPL_LINUX_TRY_COMPILE([
@@ -1064,6 +969,10 @@ AC_DEFUN([SPL_AC_2ARGS_VFS_UNLINK],
        ])
 ])
 
+dnl #
+dnl # 3.13 and 3.15 API changes
+dnl # Added delegated inode and flags argument.
+dnl #
 AC_DEFUN([SPL_AC_4ARGS_VFS_RENAME],
        [AC_MSG_CHECKING([whether vfs_rename() wants 4 args])
        SPL_LINUX_TRY_COMPILE([
@@ -1134,7 +1043,7 @@ AC_DEFUN([SPL_AC_FS_STRUCT_SPINLOCK], [
                #include <linux/sched.h>
                #include <linux/fs_struct.h>
        ],[
-               struct fs_struct fs;
+               static struct fs_struct fs;
                spin_lock_init(&fs.lock);
        ],[
                AC_MSG_RESULT(yes)
@@ -1146,26 +1055,6 @@ AC_DEFUN([SPL_AC_FS_STRUCT_SPINLOCK], [
        EXTRA_KCFLAGS="$tmp_flags"
 ])
 
-dnl #
-dnl # 2.6.29 API change,
-dnl # check whether 'struct cred' exists
-dnl #
-AC_DEFUN([SPL_AC_CRED_STRUCT], [
-       AC_MSG_CHECKING([whether struct cred exists])
-       SPL_LINUX_TRY_COMPILE([
-               #include <linux/cred.h>
-       ],[
-               struct cred *cr __attribute__ ((unused));
-               cr  = NULL;
-       ],[
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_CRED_STRUCT, 1, [struct cred exists])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-])
-
-
 dnl #
 dnl # User namespaces, use kuid_t in place of uid_t
 dnl # where available. Not strictly a user namespaces thing
@@ -1196,32 +1085,8 @@ AC_DEFUN([SPL_AC_KUIDGID_T], [
 ])
 
 dnl #
-dnl # Custom SPL patch may export this symbol.
-dnl #
-AC_DEFUN([SPL_AC_GROUPS_SEARCH],
-       [AC_MSG_CHECKING([whether groups_search() is available])
-       SPL_LINUX_TRY_COMPILE_SYMBOL([
-               #include <linux/cred.h>
-               #ifdef HAVE_KUIDGID_T
-               #include <linux/uidgid.h>
-               #endif
-       ], [
-               #ifdef HAVE_KUIDGID_T
-               groups_search(NULL, KGIDT_INIT(0));
-               #else
-               groups_search(NULL, 0);
-               #endif
-       ], [groups_search], [], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_GROUPS_SEARCH, 1, [groups_search() is available])
-       ], [
-               AC_MSG_RESULT(no)
-       ])
-])
-
-dnl #
-dnl # 2.6.x API change,
-dnl # __put_task_struct() was exported in RHEL5 but unavailable elsewhere.
+dnl # 2.6.39 API change,
+dnl # __put_task_struct() was exported by the mainline kernel.
 dnl #
 AC_DEFUN([SPL_AC_PUT_TASK_STRUCT],
        [AC_MSG_CHECKING([whether __put_task_struct() is available])
@@ -1238,61 +1103,6 @@ AC_DEFUN([SPL_AC_PUT_TASK_STRUCT],
        ])
 ])
 
-dnl #
-dnl # 2.6.32 API change,
-dnl # Unused 'struct file *' removed from prototype.
-dnl #
-AC_DEFUN([SPL_AC_5ARGS_PROC_HANDLER], [
-       AC_MSG_CHECKING([whether proc_handler() wants 5 args])
-       SPL_LINUX_TRY_COMPILE([
-               #include <linux/sysctl.h>
-       ],[
-               proc_dostring(NULL, 0, NULL, NULL, NULL);
-       ],[
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_5ARGS_PROC_HANDLER, 1,
-                         [proc_handler() wants 5 args])
-       ],[
-               AC_MSG_RESULT(no)
-       ])
-])
-
-dnl #
-dnl # 2.6.x API change,
-dnl # kvasprintf() function added.
-dnl #
-AC_DEFUN([SPL_AC_KVASPRINTF],
-       [AC_MSG_CHECKING([whether kvasprintf() is available])
-       SPL_LINUX_TRY_COMPILE_SYMBOL([
-               #include <linux/kernel.h>
-       ], [
-               kvasprintf(0, NULL, *((va_list*)NULL));
-       ], [kvasprintf], [], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_KVASPRINTF, 1, [kvasprintf() is available])
-       ], [
-               AC_MSG_RESULT(no)
-       ])
-])
-
-dnl #
-dnl # 2.6.29 API change,
-dnl # vfs_fsync() funcation added, prior to this use file_fsync().
-dnl #
-AC_DEFUN([SPL_AC_VFS_FSYNC],
-       [AC_MSG_CHECKING([whether vfs_fsync() is available])
-       SPL_LINUX_TRY_COMPILE_SYMBOL([
-               #include <linux/fs.h>
-       ], [
-               (void) vfs_fsync;
-       ], [vfs_fsync], [fs/sync.c], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_VFS_FSYNC, 1, [vfs_fsync() is available])
-       ], [
-               AC_MSG_RESULT(no)
-       ])
-])
-
 dnl #
 dnl # 2.6.35 API change,
 dnl # Unused 'struct dentry *' removed from vfs_fsync() prototype.
@@ -1401,65 +1211,6 @@ AC_DEFUN([SPL_AC_KERNEL_FALLOCATE], [
        SPL_AC_PAX_KERNEL_FILE_FALLOCATE
 ])
 
-dnl #
-dnl # 2.6.33 API change. Also backported in RHEL5 as of 2.6.18-190.el5.
-dnl # Earlier versions of rwsem_is_locked() were inline and had a race
-dnl # condition.  The fixed version is exported as a symbol.  The race
-dnl # condition is fixed by acquiring sem->wait_lock, so we must not
-dnl # call that version while holding sem->wait_lock.
-dnl #
-AC_DEFUN([SPL_AC_EXPORTED_RWSEM_IS_LOCKED],
-       [AC_MSG_CHECKING([whether rwsem_is_locked() acquires sem->wait_lock])
-       SPL_LINUX_TRY_COMPILE_SYMBOL([
-               #include <linux/rwsem.h>
-               int rwsem_is_locked(struct rw_semaphore *sem) { return 0; }
-       ], [], [rwsem_is_locked], [lib/rwsem-spinlock.c], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(RWSEM_IS_LOCKED_TAKES_WAIT_LOCK, 1,
-                         [rwsem_is_locked() acquires sem->wait_lock])
-       ], [
-               AC_MSG_RESULT(no)
-       ])
-])
-
-dnl #
-dnl # 2.6.28 API change
-dnl # The kern_path() function has been introduced. We adopt it as the new way
-dnl # of looking up paths. When it is not available, we emulate it using the
-dnl # older interfaces.
-dnl #
-AC_DEFUN([SPL_AC_KERN_PATH],
-       [AC_MSG_CHECKING([whether kern_path() is available])
-       SPL_LINUX_TRY_COMPILE_SYMBOL([
-               #include <linux/namei.h>
-       ], [
-               int r = kern_path(NULL, 0, NULL);
-       ], [kern_path], [fs/namei.c], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_KERN_PATH, 1,
-                         [kern_path() is available])
-       ], [
-               AC_MSG_RESULT(no)
-               AC_MSG_CHECKING([whether path_lookup() is available])
-               SPL_LINUX_TRY_COMPILE_SYMBOL([
-                       #include <linux/namei.h>
-               ], [
-                       int r = path_lookup(NULL, 0, NULL);
-               ], [path_lookup], [fs/namei.c], [
-                       AC_MSG_RESULT(yes)
-                       AC_DEFINE(HAVE_KERN_PATH, 1,
-                                 [kern_path() is available])
-               ], [
-                       AC_MSG_RESULT(no)
-                       AC_MSG_ERROR([
-       *** Neither kern_path() nor path_lookup() is available.
-       *** Please file an issue:
-       *** https://github.com/zfsonlinux/spl/issues/new])
-
-               ])
-       ])
-])
-
 dnl #
 dnl # zlib inflate compat,
 dnl # Verify the kernel has CONFIG_ZLIB_INFLATE support enabled.
@@ -1502,6 +1253,26 @@ AC_DEFUN([SPL_AC_CONFIG_ZLIB_DEFLATE], [
        ])
 ])
 
+dnl #
+dnl # config trim unused symbols,
+dnl # Verify the kernel has CONFIG_TRIM_UNUSED_KSYMS DISABLED.
+dnl #
+AC_DEFUN([SPL_AC_CONFIG_TRIM_UNUSED_KSYMS], [
+       AC_MSG_CHECKING([whether CONFIG_TRIM_UNUSED_KSYM is disabled])
+       SPL_LINUX_TRY_COMPILE([
+               #if defined(CONFIG_TRIM_UNUSED_KSYMS)
+               #error CONFIG_TRIM_UNUSED_KSYMS not defined
+               #endif
+       ],[ ],[
+               AC_MSG_RESULT([yes])
+       ],[
+               AC_MSG_RESULT([no])
+               AC_MSG_ERROR([
+       *** This kernel has unused symbols trimming enabled, please disable.
+       *** Rebuild the kernel with CONFIG_TRIM_UNUSED_KSYMS=n set.])
+       ])
+])
+
 dnl #
 dnl # 2.6.39 API compat,
 dnl # The function zlib_deflate_workspacesize() now take 2 arguments.
@@ -1572,6 +1343,55 @@ AC_DEFUN([SPL_AC_RWSEM_SPINLOCK_IS_RAW], [
        EXTRA_KCFLAGS="$tmp_flags"
 ])
 
+dnl #
+dnl # 3.16 API Change
+dnl #
+dnl # rwsem-spinlock "->activity" changed to "->count"
+dnl #
+AC_DEFUN([SPL_AC_RWSEM_ACTIVITY], [
+       AC_MSG_CHECKING([whether struct rw_semaphore has member activity])
+       tmp_flags="$EXTRA_KCFLAGS"
+       EXTRA_KCFLAGS="-Werror"
+       SPL_LINUX_TRY_COMPILE([
+               #include <linux/rwsem.h>
+       ],[
+               struct rw_semaphore dummy_semaphore __attribute__ ((unused));
+               dummy_semaphore.activity = 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_RWSEM_ACTIVITY, 1,
+               [struct rw_semaphore has member activity])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+       EXTRA_KCFLAGS="$tmp_flags"
+])
+
+dnl #
+dnl # 4.8 API Change
+dnl #
+dnl # rwsem "->count" changed to atomic_long_t type
+dnl #
+AC_DEFUN([SPL_AC_RWSEM_ATOMIC_LONG_COUNT], [
+       AC_MSG_CHECKING(
+       [whether struct rw_semaphore has atomic_long_t member count])
+       tmp_flags="$EXTRA_KCFLAGS"
+       EXTRA_KCFLAGS="-Werror"
+       SPL_LINUX_TRY_COMPILE([
+               #include <linux/rwsem.h>
+       ],[
+               DECLARE_RWSEM(dummy_semaphore);
+               (void) atomic_long_read(&dummy_semaphore.count);
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_RWSEM_ATOMIC_LONG_COUNT, 1,
+               [struct rw_semaphore has atomic_long_t member count])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+       EXTRA_KCFLAGS="$tmp_flags"
+])
+
 dnl #
 dnl # 3.9 API change,
 dnl # Moved things from linux/sched.h to linux/sched/rt.h
@@ -1591,34 +1411,67 @@ AC_DEFUN([SPL_AC_SCHED_RT_HEADER],
        ])
 ])
 
+
 dnl #
-dnl # 3.9 API change,
-dnl # vfs_getattr() uses 2 args
-dnl # It takes struct path * instead of struct vfsmount * and struct dentry *
+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([SPL_AC_4ARGS_VFS_GETATTR], [
+       AC_MSG_CHECKING([whether vfs_getattr() wants 4 args])
+       SPL_LINUX_TRY_COMPILE([
+               #include <linux/fs.h>
+       ],[
+               vfs_getattr((const struct path *)NULL,
+                       (struct kstat *)NULL,
+                       (u32)0,
+                       (unsigned int)0);
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_4ARGS_VFS_GETATTR, 1,
+                 [vfs_getattr wants 4 args])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+])
+
+dnl #
+dnl # 3.9 API 
+dnl # vfs_getattr(struct path *p, struct kstat *s)
 dnl #
 AC_DEFUN([SPL_AC_2ARGS_VFS_GETATTR], [
-       AC_MSG_CHECKING([whether vfs_getattr() wants])
+       AC_MSG_CHECKING([whether vfs_getattr() wants 2 args])
        SPL_LINUX_TRY_COMPILE([
                #include <linux/fs.h>
        ],[
                vfs_getattr((struct path *) NULL,
                        (struct kstat *)NULL);
        ],[
-               AC_MSG_RESULT(2 args)
+               AC_MSG_RESULT(yes)
                AC_DEFINE(HAVE_2ARGS_VFS_GETATTR, 1,
-                         [vfs_getattr wants 2 args])
+                         [vfs_getattr wants 2 args])
        ],[
-               SPL_LINUX_TRY_COMPILE([
-                       #include <linux/fs.h>
-               ],[
-                       vfs_getattr((struct vfsmount *)NULL,
-                               (struct dentry *)NULL,
-                               (struct kstat *)NULL);
-               ],[
-                       AC_MSG_RESULT(3 args)
-               ],[
-                       AC_MSG_ERROR(unknown)
-               ])
+               AC_MSG_RESULT(no)
+       ])
+])
+
+dnl #
+dnl # <3.9 API 
+dnl # vfs_getattr(struct vfsmount *v, struct dentry *d, struct kstat *k)
+dnl #
+AC_DEFUN([SPL_AC_3ARGS_VFS_GETATTR], [
+       AC_MSG_CHECKING([whether vfs_getattr() wants 3 args])
+       SPL_LINUX_TRY_COMPILE([
+               #include <linux/fs.h>
+       ],[
+               vfs_getattr((struct vfsmount *)NULL,
+                       (struct dentry *)NULL,
+                       (struct kstat *)NULL);
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_3ARGS_VFS_GETATTR, 1,
+                 [vfs_getattr wants 3 args])
+       ],[
+               AC_MSG_RESULT(no)
        ])
 ])
 
@@ -1705,3 +1558,114 @@ AC_DEFUN([SPL_AC_WAIT_ON_BIT], [
                AC_MSG_RESULT(no)
        ])
 ])
+
+dnl #
+dnl # Check whether mutex has owner with task_struct type.
+dnl #
+dnl # Note that before Linux 3.0, mutex owner is of type thread_info.
+dnl #
+dnl # Note that in Linux 3.18, the condition for owner is changed from
+dnl # defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_SMP) to
+dnl # defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_MUTEX_SPIN_ON_OWNER)
+dnl #
+AC_DEFUN([SPL_AC_MUTEX_OWNER], [
+       AC_MSG_CHECKING([whether mutex has owner])
+       tmp_flags="$EXTRA_KCFLAGS"
+       EXTRA_KCFLAGS="-Werror"
+       SPL_LINUX_TRY_COMPILE([
+               #include <linux/mutex.h>
+               #include <linux/spinlock.h>
+       ],[
+               DEFINE_MUTEX(m);
+               struct task_struct *t __attribute__ ((unused));
+               t = m.owner;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_MUTEX_OWNER, 1, [yes])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+       EXTRA_KCFLAGS="$tmp_flags"
+])
+
+dnl #
+dnl # 4.7 API change
+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([SPL_AC_INODE_LOCK], [
+       AC_MSG_CHECKING([whether inode_lock_shared() exists])
+       tmp_flags="$EXTRA_KCFLAGS"
+       EXTRA_KCFLAGS="-Werror"
+       SPL_LINUX_TRY_COMPILE([
+               #include <linux/fs.h>
+       ],[
+               struct inode *inode = NULL;
+               inode_lock_shared(inode);
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_INODE_LOCK_SHARED, 1, [yes])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+       EXTRA_KCFLAGS="$tmp_flags"
+])
+
+dnl #
+dnl # 4.9 API change
+dnl # group_info changed from 2d array via >blocks to 1d array via ->gid
+dnl #
+AC_DEFUN([SPL_AC_GROUP_INFO_GID], [
+       AC_MSG_CHECKING([whether group_info->gid exists])
+       tmp_flags="$EXTRA_KCFLAGS"
+       EXTRA_KCFLAGS="-Werror"
+       SPL_LINUX_TRY_COMPILE([
+               #include <linux/cred.h>
+       ],[
+               struct group_info *gi = groups_alloc(1);
+               gi->gid[0] = KGIDT_INIT(0);
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_GROUP_INFO_GID, 1, [group_info->gid exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+       EXTRA_KCFLAGS="$tmp_flags"
+])
+
+dnl #
+dnl # grsecurity API change,
+dnl # kmem_cache_create() with SLAB_USERCOPY flag replaced by
+dnl # kmem_cache_create_usercopy().
+dnl #
+AC_DEFUN([SPL_AC_KMEM_CACHE_CREATE_USERCOPY], [
+       AC_MSG_CHECKING([whether kmem_cache_create_usercopy() exists])
+       tmp_flags="$EXTRA_KCFLAGS"
+       EXTRA_KCFLAGS="-Werror"
+       SPL_LINUX_TRY_COMPILE([
+               #include <linux/slab.h>
+               static void ctor(void *foo)
+               {
+                       // fake ctor
+               }
+       ],[
+               struct kmem_cache *skc_linux_cache;
+               const char *name = "test";
+               size_t size = 4096;
+               size_t align = 8;
+               unsigned long flags = 0;
+               size_t useroffset = 0;
+               size_t usersize = size - useroffset;
+
+               skc_linux_cache = kmem_cache_create_usercopy(
+                       name, size, align, flags, useroffset, usersize, ctor);
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_KMEM_CACHE_CREATE_USERCOPY, 1,
+                               [kmem_cache_create_usercopy() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+       EXTRA_KCFLAGS="$tmp_flags"
+])