From 588d900433b03e33e4bbbfee7309bd15f71148fb Mon Sep 17 00:00:00 2001 From: Darik Horn Date: Wed, 11 Jan 2012 11:44:34 -0600 Subject: [PATCH] Linux 3.2 compat: rw_semaphore.wait_lock is raw MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The wait_lock member of the rw_semaphore struct became a raw_spinlock_t in Linux 3.2 at torvalds/linux@ddb6c9b58a19edcfac93ac670b066c836ff729f1. Wrap spin_lock_* function calls in a new spl_rwsem_* interface to ensure type safety if raw_spinlock_t becomes architecture specific, and to satisfy these compiler warnings: warning: passing argument 1 of ‘spinlock_check’ from incompatible pointer type [enabled by default] note: expected ‘struct spinlock_t *’ but argument is of type ‘struct raw_spinlock_t *’ Signed-off-by: Brian Behlendorf Closes: #76 Closes: zfsonlinux/zfs#463 --- config/spl-build.m4 | 27 +++++++ configure | 140 +++++++++++++++++++++++++++++++++++ include/linux/rwsem_compat.h | 36 +++++++-- include/sys/rwlock.h | 16 ++-- spl_config.h.in | 3 + 5 files changed, 206 insertions(+), 16 deletions(-) diff --git a/config/spl-build.m4 b/config/spl-build.m4 index 90ff68084..27b2c4298 100644 --- a/config/spl-build.m4 +++ b/config/spl-build.m4 @@ -85,6 +85,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [ SPL_AC_KERN_PATH_PARENT_SYMBOL SPL_AC_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE SPL_AC_SHRINK_CONTROL_STRUCT + SPL_AC_RWSEM_SPINLOCK_IS_RAW ]) AC_DEFUN([SPL_AC_MODULE_SYMVERS], [ @@ -1973,3 +1974,29 @@ AC_DEFUN([SPL_AC_SHRINK_CONTROL_STRUCT], [ AC_MSG_RESULT(no) ]) ]) + +dnl # +dnl # 3.1 API Change +dnl # +dnl # The rw_semaphore.wait_lock member was changed from spinlock_t to +dnl # raw_spinlock_t at commit ddb6c9b58a19edcfac93ac670b066c836ff729f1. +dnl # +AC_DEFUN([SPL_AC_RWSEM_SPINLOCK_IS_RAW], [ + AC_MSG_CHECKING([whether struct rw_semaphore member wait_lock is raw]) + tmp_flags="$EXTRA_KCFLAGS" + EXTRA_KCFLAGS="-Werror" + SPL_LINUX_TRY_COMPILE([ + #include + ],[ + struct rw_semaphore dummy_semaphore __attribute__ ((unused)); + raw_spinlock_t dummy_lock __attribute__ ((unused)); + dummy_semaphore.wait_lock = dummy_lock; + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(RWSEM_SPINLOCK_IS_RAW, 1, + [struct rw_semaphore member wait_lock is raw_spinlock_t]) + ],[ + AC_MSG_RESULT(no) + ]) + EXTRA_KCFLAGS="$tmp_flags" +]) diff --git a/configure b/configure index 9d95d7654..621773d9d 100755 --- a/configure +++ b/configure @@ -16025,6 +16025,76 @@ fi + + { $as_echo "$as_me:$LINENO: checking whether struct rw_semaphore member wait_lock is raw" >&5 +$as_echo_n "checking whether struct rw_semaphore member wait_lock is raw... " >&6; } + tmp_flags="$EXTRA_KCFLAGS" + EXTRA_KCFLAGS="-Werror" + + +cat confdefs.h - <<_ACEOF >conftest.c +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + + #include + +int +main (void) +{ + + struct rw_semaphore dummy_semaphore __attribute__ ((unused)); + raw_spinlock_t dummy_lock __attribute__ ((unused)); + dummy_semaphore.wait_lock = dummy_lock; + + ; + return 0; +} + +_ACEOF + + + rm -Rf build && mkdir -p build + echo "obj-m := conftest.o" >build/Makefile + if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define RWSEM_SPINLOCK_IS_RAW 1 +_ACEOF + + +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + + + +fi + + rm -Rf build + + + EXTRA_KCFLAGS="$tmp_flags" + ;; user) ;; all) @@ -20335,6 +20405,76 @@ fi + { $as_echo "$as_me:$LINENO: checking whether struct rw_semaphore member wait_lock is raw" >&5 +$as_echo_n "checking whether struct rw_semaphore member wait_lock is raw... " >&6; } + tmp_flags="$EXTRA_KCFLAGS" + EXTRA_KCFLAGS="-Werror" + + +cat confdefs.h - <<_ACEOF >conftest.c +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + + #include + +int +main (void) +{ + + struct rw_semaphore dummy_semaphore __attribute__ ((unused)); + raw_spinlock_t dummy_lock __attribute__ ((unused)); + dummy_semaphore.wait_lock = dummy_lock; + + ; + return 0; +} + +_ACEOF + + + rm -Rf build && mkdir -p build + echo "obj-m := conftest.o" >build/Makefile + if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define RWSEM_SPINLOCK_IS_RAW 1 +_ACEOF + + +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + + + +fi + + rm -Rf build + + + EXTRA_KCFLAGS="$tmp_flags" + + ;; srpm) ;; *) diff --git a/include/linux/rwsem_compat.h b/include/linux/rwsem_compat.h index 67a82bb44..fe69f0154 100644 --- a/include/linux/rwsem_compat.h +++ b/include/linux/rwsem_compat.h @@ -27,6 +27,26 @@ #include +#ifdef RWSEM_SPINLOCK_IS_RAW +#define spl_rwsem_lock_irqsave(lock, flags) \ +({ \ + raw_spin_lock_irqsave(lock, flags); \ +}) +#define spl_rwsem_unlock_irqrestore(lock, flags) \ +({ \ + raw_spin_unlock_irqrestore(lock, flags); \ +}) +#else +#define spl_rwsem_lock_irqsave(lock, flags) \ +({ \ + spin_lock_irqsave(lock, flags); \ +}) +#define spl_rwsem_unlock_irqrestore(lock, flags) \ +({ \ + spin_unlock_irqrestore(lock, flags); \ +}) +#endif /* RWSEM_SPINLOCK_IS_RAW */ + #ifdef RWSEM_IS_LOCKED_TAKES_WAIT_LOCK /* * A race condition in rwsem_is_locked() was fixed in Linux 2.6.33 and the fix @@ -48,14 +68,14 @@ #else -#define spl_rwsem_is_locked(rwsem) \ -({ \ - unsigned long _flags_; \ - int _rc_; \ - spin_lock_irqsave(&rwsem->wait_lock, _flags_); \ - _rc_ = rwsem_is_locked(rwsem); \ - spin_unlock_irqrestore(&rwsem->wait_lock, _flags_); \ - _rc_; \ +#define spl_rwsem_is_locked(rwsem) \ +({ \ + unsigned long _flags_; \ + int _rc_; \ + spl_rwsem_lock_irqsave(&rwsem->wait_lock, _flags_); \ + _rc_ = rwsem_is_locked(rwsem); \ + spl_rwsem_unlock_irqrestore(&rwsem->wait_lock, _flags_); \ + _rc_; \ }) #endif /* RWSEM_IS_LOCKED_TAKES_WAIT_LOCK */ diff --git a/include/sys/rwlock.h b/include/sys/rwlock.h index 3d9808599..9d29ad679 100644 --- a/include/sys/rwlock.h +++ b/include/sys/rwlock.h @@ -52,9 +52,9 @@ spl_rw_set_owner(krwlock_t *rwp) { unsigned long flags; - spin_lock_irqsave(&SEM(rwp)->wait_lock, flags); + spl_rwsem_lock_irqsave(&SEM(rwp)->wait_lock, flags); rwp->rw_owner = current; - spin_unlock_irqrestore(&SEM(rwp)->wait_lock, flags); + spl_rwsem_unlock_irqrestore(&SEM(rwp)->wait_lock, flags); } static inline void @@ -62,9 +62,9 @@ spl_rw_clear_owner(krwlock_t *rwp) { unsigned long flags; - spin_lock_irqsave(&SEM(rwp)->wait_lock, flags); + spl_rwsem_lock_irqsave(&SEM(rwp)->wait_lock, flags); rwp->rw_owner = NULL; - spin_unlock_irqrestore(&SEM(rwp)->wait_lock, flags); + spl_rwsem_unlock_irqrestore(&SEM(rwp)->wait_lock, flags); } static inline kthread_t * @@ -73,9 +73,9 @@ rw_owner(krwlock_t *rwp) unsigned long flags; kthread_t *owner; - spin_lock_irqsave(&SEM(rwp)->wait_lock, flags); + spl_rwsem_lock_irqsave(&SEM(rwp)->wait_lock, flags); owner = rwp->rw_owner; - spin_unlock_irqrestore(&SEM(rwp)->wait_lock, flags); + spl_rwsem_unlock_irqrestore(&SEM(rwp)->wait_lock, flags); return owner; } @@ -187,14 +187,14 @@ extern int __down_write_trylock_locked(struct rw_semaphore *); unsigned long _flags_; \ int _rc_ = 0; \ \ - spin_lock_irqsave(&SEM(rwp)->wait_lock, _flags_); \ + spl_rwsem_lock_irqsave(&SEM(rwp)->wait_lock, _flags_); \ if ((list_empty(&SEM(rwp)->wait_list)) && \ (SEM(rwp)->activity == 1)) { \ __up_read_locked(SEM(rwp)); \ VERIFY(_rc_ = __down_write_trylock_locked(SEM(rwp))); \ (rwp)->rw_owner = current; \ } \ - spin_unlock_irqrestore(&SEM(rwp)->wait_lock, _flags_); \ + spl_rwsem_unlock_irqrestore(&SEM(rwp)->wait_lock, _flags_); \ _rc_; \ }) #else diff --git a/spl_config.h.in b/spl_config.h.in index 94e28e70d..847da2137 100644 --- a/spl_config.h.in +++ b/spl_config.h.in @@ -271,6 +271,9 @@ /* rwsem_is_locked() acquires sem->wait_lock */ #undef RWSEM_IS_LOCKED_TAKES_WAIT_LOCK +/* struct rw_semaphore member wait_lock is raw_spinlock_t */ +#undef RWSEM_SPINLOCK_IS_RAW + /* Define the project alias string. */ #undef SPL_META_ALIAS