aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config/spl-build.m426
-rw-r--r--include/linux/rwsem_compat.h7
-rw-r--r--module/spl/spl-rwlock.c11
3 files changed, 41 insertions, 3 deletions
diff --git a/config/spl-build.m4 b/config/spl-build.m4
index d705c6531..e9eb77861 100644
--- a/config/spl-build.m4
+++ b/config/spl-build.m4
@@ -40,6 +40,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [
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_2ARGS_VFS_GETATTR
SPL_AC_USLEEP_RANGE
@@ -1342,6 +1343,31 @@ AC_DEFUN([SPL_AC_RWSEM_ACTIVITY], [
])
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
dnl #
diff --git a/include/linux/rwsem_compat.h b/include/linux/rwsem_compat.h
index 9a4df2673..c874885b0 100644
--- a/include/linux/rwsem_compat.h
+++ b/include/linux/rwsem_compat.h
@@ -35,9 +35,12 @@
#define SPL_RWSEM_SINGLE_WRITER_VALUE (RWSEM_ACTIVE_WRITE_BIAS)
#endif
-/* Linux 3.16 change activity to count for rwsem-spinlock */
-#ifdef HAVE_RWSEM_ACTIVITY
+/* Linux 3.16 changed activity to count for rwsem-spinlock */
+#if defined(HAVE_RWSEM_ACTIVITY)
#define RWSEM_COUNT(sem) sem->activity
+/* Linux 4.8 changed count to an atomic_long_t for !rwsem-spinlock */
+#elif defined(HAVE_RWSEM_ATOMIC_LONG_COUNT)
+#define RWSEM_COUNT(sem) atomic_long_read(&(sem)->count)
#else
#define RWSEM_COUNT(sem) sem->count
#endif
diff --git a/module/spl/spl-rwlock.c b/module/spl/spl-rwlock.c
index 9b356a843..77f46f2d6 100644
--- a/module/spl/spl-rwlock.c
+++ b/module/spl/spl-rwlock.c
@@ -32,7 +32,7 @@
#define DEBUG_SUBSYSTEM S_RWLOCK
-#ifdef CONFIG_RWSEM_GENERIC_SPINLOCK
+#if defined(CONFIG_RWSEM_GENERIC_SPINLOCK)
static int
__rwsem_tryupgrade(struct rw_semaphore *rwsem)
{
@@ -47,6 +47,15 @@ __rwsem_tryupgrade(struct rw_semaphore *rwsem)
spl_rwsem_unlock_irqrestore(&rwsem->wait_lock, flags);
return (ret);
}
+#elif defined(HAVE_RWSEM_ATOMIC_LONG_COUNT)
+static int
+__rwsem_tryupgrade(struct rw_semaphore *rwsem)
+{
+ long val;
+ val = atomic_long_cmpxchg(&rwsem->count, SPL_RWSEM_SINGLE_READER_VALUE,
+ SPL_RWSEM_SINGLE_WRITER_VALUE);
+ return (val == SPL_RWSEM_SINGLE_READER_VALUE);
+}
#else
static int
__rwsem_tryupgrade(struct rw_semaphore *rwsem)