linux
"Double lock when debugging diskquota
In between a spin_lock and spin_unlock pair, there is a conditional call to inode_get_rsv_space when QUOTA_DEBUG is enabled, this function acquires the very same lock, thus introducing a double lock. Note that spin locks are not reentrant."
Bug fixed by commit d7e9711760a
Type | DoubleLock |
Config | "QUOTA_DEBUG" (1st degree) |
Fix-in | code |
Location | fs/quota/ |
#include <pthread.h> #include <stdlib.h> static pthread_mutex_t i_lock = PTHREAD_MUTEX_INITIALIZER; static int inode_get_rsv_space(void) { pthread_mutex_lock(&i_lock); // (4) ERROR // do something pthread_mutex_unlock(&i_lock); return 0; } static void add_dquot_ref(void) { #ifdef CONFIG_QUOTA_DEBUG int reserved = 0; #endif int i, j; for (i=0; i<10; i++) { pthread_mutex_lock(&i_lock); // (2) lock is acquired if (rand() % 2) { // evaluates to false pthread_mutex_unlock(&i_lock); continue; } #ifdef CONFIG_QUOTA_DEBUG if (inode_get_rsv_space() > 0) // (3) reserved = 1; #endif pthread_mutex_unlock(&i_lock); } } int main(int argc, char** arv) { add_dquot_ref(); // (1) return 0; }
diff --git a/simple/d7e9711.c b/simple/d7e9711.c --- a/simple/d7e9711.c +++ b/simple/d7e9711.c @@ -26,12 +26,12 @@ continue; } + pthread_mutex_unlock(&i_lock); + #ifdef CONFIG_QUOTA_DEBUG if (inode_get_rsv_space() > 0) // (3) reserved = 1; #endif - - pthread_mutex_unlock(&i_lock); } }
#include <pthread.h> #include <stdlib.h> static pthread_mutex_t i_lock = PTHREAD_MUTEX_INITIALIZER; int main(int argc, char** arv) { // add_dquot_ref(); #ifdef CONFIG_QUOTA_DEBUG int reserved = 0; #endif int i, j; for (i=0; i<10; i++) { pthread_mutex_lock(&i_lock); if (rand() % 2) { pthread_mutex_unlock(&i_lock); continue; } #ifdef CONFIG_QUOTA_DEBUG pthread_mutex_lock(&i_lock); // ERROR // do something pthread_mutex_unlock(&i_lock); int i = 0; if (i > 0) reserved = 1; #endif pthread_mutex_unlock(&i_lock); } return 0; }
. call fs/quota/dquot.c:894:add_dquot_ref() . 903: spin_lock(&inode->i_lock); . 911: if (unlikely(inode_get_rsv_space(inode) > 0)) .. call fs/quota/dquot.c:1517: inode_get_rsv_space() .. ERROR 1523: spin_lock(&inode->i_lock);