]> granicus.if.org Git - zfs/commitdiff
Linux 2.6.39 compat, mutex owner
authorBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 24 Jun 2011 18:57:14 +0000 (11:57 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 24 Jun 2011 20:00:08 +0000 (13:00 -0700)
Prior to Linux 2.6.39 when CONFIG_DEBUG_MUTEXES was defined
the kernel stored a thread_info pointer as the mutex owner.
From this you could get the pointer of the current task_struct
to compare with get_current().

As of Linux 2.6.39 this behavior has changed and now the mutex
stores a pointer to the task_struct.  This commit detects the
type of pointer stored in the mutex and adjusts the mutex_owner()
and mutex_owned() functions to perform the correct comparision.

config/spl-build.m4
configure
include/sys/mutex.h
spl_config.h.in

index 75267bb839b2d8ed47233a67f46cce1644f34d4b..ea50785071212adb9d6e88a3b15ef80301753a4e 100644 (file)
@@ -48,6 +48,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [
        SPL_AC_MONOTONIC_CLOCK
        SPL_AC_INODE_I_MUTEX
        SPL_AC_MUTEX_OWNER
+       SPL_AC_MUTEX_OWNER_TASK_STRUCT
        SPL_AC_MUTEX_LOCK_NESTED
        SPL_AC_3ARGS_ON_EACH_CPU
        SPL_AC_KALLSYMS_LOOKUP_NAME
@@ -1128,6 +1129,32 @@ AC_DEFUN([SPL_AC_MUTEX_OWNER], [
        ])
 ])
 
+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>
+       ],[
+               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 # 2.6.18 API change,
 dnl # First introduced 'mutex_lock_nested()' in include/linux/mutex.h,
index c537b9817a074ac80bec38b4cfc364f7871d53b6..cf396e484803ce8db102ed0113f51c965c710907 100755 (executable)
--- a/configure
+++ b/configure
 
 
 
+       { $as_echo "$as_me:$LINENO: checking whether struct mutex owner is a task_struct" >&5
+$as_echo_n "checking whether struct mutex owner is a task_struct... " >&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 <linux/mutex.h>
+
+int
+main (void)
+{
+
+               struct mutex mtx __attribute__ ((unused));
+               mtx.owner = current;
+
+  ;
+  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 HAVE_MUTEX_OWNER_TASK_STRUCT 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"
+
+
        { $as_echo "$as_me:$LINENO: checking whether mutex_lock_nested() is available" >&5
 $as_echo_n "checking whether mutex_lock_nested() is available... " >&6; }
 
 
 
 
+       { $as_echo "$as_me:$LINENO: checking whether struct mutex owner is a task_struct" >&5
+$as_echo_n "checking whether struct mutex owner is a task_struct... " >&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 <linux/mutex.h>
+
+int
+main (void)
+{
+
+               struct mutex mtx __attribute__ ((unused));
+               mtx.owner = current;
+
+  ;
+  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 HAVE_MUTEX_OWNER_TASK_STRUCT 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"
+
+
        { $as_echo "$as_me:$LINENO: checking whether mutex_lock_nested() is available" >&5
 $as_echo_n "checking whether mutex_lock_nested() is available... " >&6; }
 
index ebf9151f16615fdcc7906039f0ad7edaf521e56f..659214f508af56375d86a4584862dde3048476ee 100644 (file)
@@ -48,21 +48,18 @@ typedef struct {
 static inline kthread_t *
 mutex_owner(kmutex_t *mp)
 {
-        struct thread_info *owner;
-
-        owner = ACCESS_ONCE(mp->m.owner);
-        if (owner)
-                return owner->task;
-
-        return NULL;
-}
+#if defined(HAVE_MUTEX_OWNER_TASK_STRUCT)
+       return ACCESS_ONCE(mp->m.owner);
+#else
+       struct thread_info *owner = ACCESS_ONCE(mp->m.owner);
+       if (owner)
+               return owner->task;
 
-static inline int
-mutex_owned(kmutex_t *mp)
-{
-        return (ACCESS_ONCE(mp->m.owner) == current_thread_info());
+       return NULL;
+#endif
 }
 
+#define mutex_owned(mp)         (mutex_owner(mp) == current)
 #define MUTEX_HELD(mp)          mutex_owned(mp)
 #define MUTEX_NOT_HELD(mp)      (!MUTEX_HELD(mp))
 #undef mutex_init
index 95394e6e2e1ebaf1bee315b96ba0504f6fff982a..97f0e06f310d3c1f1a90dc9ac498fdfee89eaf61 100644 (file)
 /* struct mutex has owner */
 #undef HAVE_MUTEX_OWNER
 
+/* struct mutex owner is a task_struct */
+#undef HAVE_MUTEX_OWNER_TASK_STRUCT
+
 /* next_online_pgdat() is available */
 #undef HAVE_NEXT_ONLINE_PGDAT