]> granicus.if.org Git - spl/commitdiff
Linux 4.8 compat: rw_semaphore atomic_long_t count
authorBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 26 Jul 2016 23:37:46 +0000 (23:37 +0000)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 29 Jul 2016 21:17:53 +0000 (14:17 -0700)
For non-rwsem-spinlocks the "count" member was changed from a
"long" to "atomic_long_t" type.  A configure check has been
added to detect this change along with new versions of the
_rwsem_tryupgrade() function and RWSEM_COUNT() macro.  See
https://github.com/torvalds/linux/commit/8ee62b18 for complete
details.

Signed-off-by: Tim Chase <tim@chase2k.com>
Signed-off-by: Chunwei Chen <david.chen@osnexus.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #563

config/spl-build.m4
include/linux/rwsem_compat.h
module/spl/spl-rwlock.c

index d705c6531babb414a3b4da198de0562d05472fc4..e9eb77861ee81f33ce733323d763652db069f03f 100644 (file)
@@ -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
@@ -1341,6 +1342,31 @@ AC_DEFUN([SPL_AC_RWSEM_ACTIVITY], [
        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
index 9a4df26738c8bac289040126e5fa6af20dac8552..c874885b0c9de4f79abc889c6f9a341ee79a7307 100644 (file)
 #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
index 9b356a843950218bfb4379ccce2ca82a6331b0a3..77f46f2d6fdf5119132424fe396de23378d4e644 100644 (file)
@@ -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)