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);