Skip to content

Commit

Permalink
Linux 4.8 compat: rw_semaphore atomic_long_t count
Browse files Browse the repository at this point in the history
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
torvalds/linux@8ee62b18 for complete
details.

Signed-off-by: Tim Chase <[email protected]>
Signed-off-by: Chunwei Chen <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes openzfs#563
  • Loading branch information
behlendorf committed Jul 29, 2016
1 parent d2f97b2 commit b7c7008
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 3 deletions.
26 changes: 26 additions & 0 deletions config/spl-build.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
7 changes: 5 additions & 2 deletions include/linux/rwsem_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 10 additions & 1 deletion module/spl/spl-rwlock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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)
Expand Down

0 comments on commit b7c7008

Please sign in to comment.