diff options
author | shishir gowda <shishirng@gluster.com> | 2011-03-23 03:53:28 +0000 |
---|---|---|
committer | Vijay Bellur <vijay@dev.gluster.com> | 2011-03-23 04:55:34 -0700 |
commit | bd132d8e410dbc24cbef751925cd937939f35747 (patch) | |
tree | 23b432233a93884ba13bc16cdc5f8774ecde483a | |
parent | 9bd4f25b6b0ea8103324b685fcc21525a29849a8 (diff) |
Prevent deadlock in io-stats list management of top.v3.2.0qa4
Senario: thread t1 has lock on the queue, and waits on the element lock to remove
it and unref it. Thread t2 has a lock on the element being removed from the queue,
but waiting on the queue on the list to update it.
The fix is to move list management to outside of the lock. Additonal to this change
is adding locks to ios_stat_ref
Signed-off-by: shishir gowda <shishirng@gluster.com>
Signed-off-by: Vijay Bellur <vijay@dev.gluster.com>
BUG: 2578 (Mountpoint hung while running the dbench)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2578
-rw-r--r-- | xlators/debug/io-stats/src/io-stats.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/xlators/debug/io-stats/src/io-stats.c b/xlators/debug/io-stats/src/io-stats.c index c96603b82..b7c522fe5 100644 --- a/xlators/debug/io-stats/src/io-stats.c +++ b/xlators/debug/io-stats/src/io-stats.c @@ -253,16 +253,18 @@ struct ios_local { #define BUMP_STATS(iosstat, type) \ do { \ struct ios_conf *conf = NULL; \ + uint64_t value = 0; \ \ conf = this->private; \ \ LOCK(&iosstat->lock); \ { \ iosstat->counters[type]++; \ - ios_stat_add_to_list (&conf->list[type], \ - iosstat->counters[type], iosstat); \ + value = iosstat->counters[type]; \ } \ UNLOCK (&iosstat->lock); \ + ios_stat_add_to_list (&conf->list[type], \ + value, iosstat); \ \ } while (0) @@ -273,6 +275,7 @@ struct ios_local { double elapsed; \ struct timeval *begin, *end; \ double throughput; \ + int flag = 0; \ \ begin = &frame->begin; \ end = &frame->end; \ @@ -290,11 +293,13 @@ struct ios_local { throughput; \ gettimeofday (&iosstat-> \ thru_counters[type].time, NULL); \ - ios_stat_add_to_list (&conf->thru_list[type], \ - throughput, iosstat); \ + flag = 1; \ } \ } \ UNLOCK (&iosstat->lock); \ + if (flag) \ + ios_stat_add_to_list (&conf->thru_list[type], \ + throughput, iosstat); \ } while (0) int @@ -329,7 +334,12 @@ ios_fd_ctx_set (fd_t *fd, xlator_t *this, struct ios_fd *iosfd) int ios_stat_ref (struct ios_stat *iosstat) { - iosstat->refcnt++; + LOCK (&iosstat->lock); + { + iosstat->refcnt++; + } + UNLOCK (&iosstat->lock); + return iosstat->refcnt; } |