summaryrefslogtreecommitdiffstats
path: root/libglusterfs
diff options
context:
space:
mode:
authorKrishnan Parthasarathi <kparthas@redhat.com>2013-05-20 17:17:05 +0530
committerVijay Bellur <vbellur@redhat.com>2013-05-21 06:03:40 -0700
commit418f763303ec4003f4b805867ff306a2e43bca76 (patch)
tree86547bd3fcc2adad79fbcb60087c75372115229e /libglusterfs
parentf8e19c6b6f21142aadabd2f30dc3b960a6ec1fa2 (diff)
syncop: Remove task from syncbarrier's waitq before 'wake'
Backport of http://review.gluster.org/5047 Removing task from syncbarrier's waitq after wake could result in a subsequent syncbarrier_wake, wake'ing up the already running task. This fix makes the removal from waitq and wake 'atomic' The root cause and the fix are similar in spirit to what was observed in synclock's waitq implementation. Change-Id: I7dd9e6ad5945742bcda20eb5a06a9376bb18528e BUG: 948686 Signed-off-by: Krishnan Parthasarathi <kparthas@redhat.com> Reviewed-on: http://review.gluster.org/5054 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Diffstat (limited to 'libglusterfs')
-rw-r--r--libglusterfs/src/syncop.c12
1 files changed, 5 insertions, 7 deletions
diff --git a/libglusterfs/src/syncop.c b/libglusterfs/src/syncop.c
index aa46f6219ce..964e6dd2a95 100644
--- a/libglusterfs/src/syncop.c
+++ b/libglusterfs/src/syncop.c
@@ -688,13 +688,10 @@ __syncbarrier_wait (struct syncbarrier *barrier, int waitfor)
if (task) {
/* called within a synctask */
list_add_tail (&task->waitq, &barrier->waitq);
- {
- pthread_mutex_unlock (&barrier->guard);
- synctask_yawn (task);
- synctask_yield (task);
- pthread_mutex_lock (&barrier->guard);
- }
- list_del_init (&task->waitq);
+ pthread_mutex_unlock (&barrier->guard);
+ synctask_yawn (task);
+ synctask_yield (task);
+ pthread_mutex_lock (&barrier->guard);
} else {
/* called by a non-synctask */
pthread_cond_wait (&barrier->cond, &barrier->guard);
@@ -737,6 +734,7 @@ __syncbarrier_wake (struct syncbarrier *barrier)
pthread_cond_signal (&barrier->cond);
if (!list_empty (&barrier->waitq)) {
task = list_entry (barrier->waitq.next, struct synctask, waitq);
+ list_del_init (&task->waitq);
synctask_wake (task);
}