diff options
author | Zhou Zhengping <johnzzpcrystal@gmail.com> | 2016-06-26 19:56:58 -0400 |
---|---|---|
committer | Jeff Darcy <jdarcy@redhat.com> | 2016-07-09 06:50:31 -0700 |
commit | 693eccd456c4fc7dfadb72069da906544cf19733 (patch) | |
tree | ace3705b6ada28d89e770df6fce538061f48503d | |
parent | 9886d568a7a8839bf3acc81cb1111fa372ac5270 (diff) |
libglusterfs: race condition when set ctx->timer in function gf_timer_registry_init
1.fix race conditon when set ctx->timer
2.use typical list_head operation instead of verbose list's operation
3.add file "tags" into .gitignore
Signed-off-by: Zhou Zhengping <johnzzpcrystal@gmail.com>
Change-Id: I4ec55e41356633cf1399536d202c58e19b309f00
BUG: 1350191
Reviewed-on: http://review.gluster.org/14800
Smoke: Gluster Build System <jenkins@build.gluster.org>
Tested-by: Zhou Zhengping <johnzzpcrystal@gmail.com>
CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
Reviewed-by: Jeff Darcy <jdarcy@redhat.com>
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | libglusterfs/src/timer.c | 77 | ||||
-rw-r--r-- | libglusterfs/src/timer.h | 10 |
3 files changed, 39 insertions, 49 deletions
diff --git a/.gitignore b/.gitignore index e5c699beaf8..33f6e0905b5 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ build config.* configure cscope.* +tags depcomp INSTALL install-sh diff --git a/libglusterfs/src/timer.c b/libglusterfs/src/timer.c index bcdc5da5571..a24a07804a8 100644 --- a/libglusterfs/src/timer.c +++ b/libglusterfs/src/timer.c @@ -57,16 +57,11 @@ gf_timer_call_after (glusterfs_ctx_t *ctx, event->xl = THIS; LOCK (®->lock); { - trav = reg->active.prev; - while (trav != ®->active) { + list_for_each_entry_reverse (trav, ®->active, list) { if (TS (trav->at) < at) break; - trav = trav->prev; } - event->prev = trav; - event->next = event->prev->next; - event->prev->next = event; - event->next->prev = event; + list_add (&event->list, &trav->list); } UNLOCK (®->lock); return event; @@ -105,9 +100,7 @@ gf_timer_call_cancel (glusterfs_ctx_t *ctx, fired = event->fired; if (fired) goto unlock; - - event->next->prev = event->prev; - event->prev->next = event->next; + list_del (&event->list); } unlock: UNLOCK (®->lock); @@ -120,20 +113,13 @@ unlock: } -static void -__delete_entry (gf_timer_t *event) { - event->next->prev = event->prev; - event->prev->next = event->next; - GF_FREE (event); -} - - static void * gf_timer_proc (void *data) { gf_timer_registry_t *reg = data; const struct timespec sleepts = {.tv_sec = 1, .tv_nsec = 0, }; gf_timer_t *event = NULL; + gf_timer_t *tmp = NULL; xlator_t *old_THIS = NULL; while (!reg->fin) { @@ -148,13 +134,15 @@ gf_timer_proc (void *data) LOCK (®->lock); { - event = reg->active.next; - at = TS (event->at); - if (event != ®->active && now >= at) { - need_cbk = 1; - event->next->prev = event->prev; - event->prev->next = event->next; - event->fired = _gf_true; + list_for_each_entry_safe (event, + tmp, ®->active, list) { + at = TS (event->at); + if (now >= at) { + need_cbk = 1; + event->fired = _gf_true; + list_del (&event->list); + break; + } } } UNLOCK (®->lock); @@ -181,11 +169,9 @@ gf_timer_proc (void *data) /* Do not call gf_timer_call_cancel(), * it will lead to deadlock */ - while (reg->active.next != ®->active) { - event = reg->active.next; - /* cannot call list_del as the event doesnt have - * list_head*/ - __delete_entry (event); + list_for_each_entry_safe (event, tmp, ®->active, list) { + list_del (&event->list); + GF_FREE (event); } } UNLOCK (®->lock); @@ -216,26 +202,23 @@ gf_timer_registry_init (glusterfs_ctx_t *ctx) LOCK (&ctx->lock); { reg = ctx->timer; - } - UNLOCK (&ctx->lock); - if (!reg) { + if (reg) { + UNLOCK (&ctx->lock); + goto out; + } reg = GF_CALLOC (1, sizeof (*reg), - gf_common_mt_gf_timer_registry_t); - if (!reg) - return NULL; - - LOCK_INIT (®->lock); - reg->active.next = ®->active; - reg->active.prev = ®->active; - - LOCK (&ctx->lock); - { - ctx->timer = reg; + gf_common_mt_gf_timer_registry_t); + if (!reg) { + UNLOCK (&ctx->lock); + goto out; } - UNLOCK (&ctx->lock); - gf_thread_create (®->th, NULL, gf_timer_proc, reg); + ctx->timer = reg; + LOCK_INIT (®->lock); + INIT_LIST_HEAD (®->active); } - + UNLOCK (&ctx->lock); + gf_thread_create (®->th, NULL, gf_timer_proc, reg); +out: return reg; } diff --git a/libglusterfs/src/timer.h b/libglusterfs/src/timer.h index 0224b0897f9..32b246cf00d 100644 --- a/libglusterfs/src/timer.h +++ b/libglusterfs/src/timer.h @@ -19,7 +19,13 @@ typedef void (*gf_timer_cbk_t) (void *); struct _gf_timer { - struct _gf_timer *next, *prev; + union { + struct list_head list; + struct { + struct _gf_timer *next; + struct _gf_timer *prev; + }; + }; struct timespec at; gf_timer_cbk_t callbk; void *data; @@ -30,7 +36,7 @@ struct _gf_timer { struct _gf_timer_registry { pthread_t th; char fin; - struct _gf_timer active; + struct list_head active; gf_lock_t lock; }; |