From: Brian Behlendorf Date: Fri, 24 Jun 2011 18:57:14 +0000 (-0700) Subject: Linux 2.6.39 compat, mutex owner X-Git-Tag: zfs-0.8.0-rc1~152^2~452 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=86fd39f354778eb10e77a7c1660b59ca16ffcc16;p=zfs Linux 2.6.39 compat, mutex owner 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. --- diff --git a/config/spl-build.m4 b/config/spl-build.m4 index 75267bb83..ea5078507 100644 --- a/config/spl-build.m4 +++ b/config/spl-build.m4 @@ -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 + ],[ + 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, diff --git a/configure b/configure index c537b9817..cf396e484 100755 --- a/configure +++ b/configure @@ -13687,6 +13687,75 @@ fi + { $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 + +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; } @@ -17818,6 +17887,75 @@ fi + { $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 + +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; } diff --git a/include/sys/mutex.h b/include/sys/mutex.h index ebf9151f1..659214f50 100644 --- a/include/sys/mutex.h +++ b/include/sys/mutex.h @@ -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 diff --git a/spl_config.h.in b/spl_config.h.in index 95394e6e2..97f0e06f3 100644 --- a/spl_config.h.in +++ b/spl_config.h.in @@ -135,6 +135,9 @@ /* 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