Fix race condition in mutex_exit()

On kernels with CONFIG_DEBUG_MUTEXES mutex_exit() clears the mutex
owner after releasing the mutex. This would cause mutex_owner()
to return an incorrect owner if another thread managed to lock the
mutex before mutex_exit() had a chance to clear the owner.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes ZFS issue #167
This commit is contained in:
Gunnar Beutner 2011-10-18 02:32:50 +02:00 committed by Brian Behlendorf
parent f3989ed322
commit 3160d4f56b

View File

@ -35,7 +35,7 @@ typedef enum {
MUTEX_ADAPTIVE = 2 MUTEX_ADAPTIVE = 2
} kmutex_type_t; } kmutex_type_t;
#if defined(HAVE_MUTEX_OWNER) && defined(CONFIG_SMP) #if defined(HAVE_MUTEX_OWNER) && defined(CONFIG_SMP) && !defined(CONFIG_DEBUG_MUTEXES)
/* /*
* We define a 1-field struct rather than a straight typedef to enforce type * We define a 1-field struct rather than a straight typedef to enforce type
@ -79,17 +79,7 @@ mutex_owner(kmutex_t *mp)
#define mutex_tryenter(mp) mutex_trylock(&(mp)->m) #define mutex_tryenter(mp) mutex_trylock(&(mp)->m)
#define mutex_enter(mp) mutex_lock(&(mp)->m) #define mutex_enter(mp) mutex_lock(&(mp)->m)
/* mutex->owner is not cleared when CONFIG_DEBUG_MUTEXES is set */
#ifdef CONFIG_DEBUG_MUTEXES
# define mutex_exit(mp) \
({ \
mutex_unlock(&(mp)->m); \
(mp)->m.owner = NULL; \
})
#else
#define mutex_exit(mp) mutex_unlock(&(mp)->m) #define mutex_exit(mp) mutex_unlock(&(mp)->m)
#endif /* CONFIG_DEBUG_MUTEXES */
#ifdef HAVE_GPL_ONLY_SYMBOLS #ifdef HAVE_GPL_ONLY_SYMBOLS
# define mutex_enter_nested(mp, sc) mutex_lock_nested(&(mp)->m, sc) # define mutex_enter_nested(mp, sc) mutex_lock_nested(&(mp)->m, sc)