7f4c2a
From 92952a767ffe126e1dfa548be003ce2b0461065e Mon Sep 17 00:00:00 2001
7f4c2a
From: Pranith Kumar K <pkarampu@redhat.com>
7f4c2a
Date: Sat, 18 Jul 2015 10:04:13 +0530
7f4c2a
Subject: [PATCH 245/245] Revert "timer: fix race between gf_timer_call_cancel() and gf_timer_proc()"
7f4c2a
7f4c2a
This reverts commit 9b237463a8f5c75cff66364d07278217f8e4e586.
7f4c2a
7f4c2a
BUG: 1244187
7f4c2a
Change-Id: Ibb6c04ab6167071e62c7a33e114b3dd5931825c8
7f4c2a
Signed-off-by: Pranith Kumar K <pkarampu@redhat.com>
7f4c2a
Reviewed-on: https://code.engineering.redhat.com/gerrit/53266
7f4c2a
Reviewed-by: Krishnan Parthasarathi <kparthas@redhat.com>
7f4c2a
Reviewed-by: Kaushal Madappa <kaushal@redhat.com>
7f4c2a
---
7f4c2a
 libglusterfs/src/timer.c |   48 +++++++++++++++++++++++++++++++--------------
7f4c2a
 libglusterfs/src/timer.h |    2 +-
7f4c2a
 2 files changed, 34 insertions(+), 16 deletions(-)
7f4c2a
7f4c2a
diff --git a/libglusterfs/src/timer.c b/libglusterfs/src/timer.c
7f4c2a
index a4d1890..e103f05 100644
7f4c2a
--- a/libglusterfs/src/timer.c
7f4c2a
+++ b/libglusterfs/src/timer.c
7f4c2a
@@ -85,11 +85,30 @@ gf_timer_call_after (glusterfs_ctx_t *ctx,
7f4c2a
 }
7f4c2a
 
7f4c2a
 int32_t
7f4c2a
+gf_timer_call_stale (gf_timer_registry_t *reg,
7f4c2a
+                     gf_timer_t *event)
7f4c2a
+{
7f4c2a
+        if (reg == NULL || event == NULL) {
7f4c2a
+                gf_msg_callingfn ("timer", GF_LOG_ERROR, EINVAL,
7f4c2a
+                                  LG_MSG_INVALID_ARG, "invalid argument");
7f4c2a
+                return 0;
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        event->next->prev = event->prev;
7f4c2a
+        event->prev->next = event->next;
7f4c2a
+        event->next = &reg->stale;
7f4c2a
+        event->prev = event->next->prev;
7f4c2a
+        event->next->prev = event;
7f4c2a
+        event->prev->next = event;
7f4c2a
+
7f4c2a
+        return 0;
7f4c2a
+}
7f4c2a
+
7f4c2a
+int32_t
7f4c2a
 gf_timer_call_cancel (glusterfs_ctx_t *ctx,
7f4c2a
                       gf_timer_t *event)
7f4c2a
 {
7f4c2a
         gf_timer_registry_t *reg = NULL;
7f4c2a
-        gf_boolean_t fired = _gf_false;
7f4c2a
 
7f4c2a
         if (ctx == NULL || event == NULL)
7f4c2a
         {
7f4c2a
@@ -108,21 +127,13 @@ gf_timer_call_cancel (glusterfs_ctx_t *ctx,
7f4c2a
 
7f4c2a
         pthread_mutex_lock (&reg->lock);
7f4c2a
         {
7f4c2a
-		fired = event->fired;
7f4c2a
-		if (fired)
7f4c2a
-			goto unlock;
7f4c2a
-
7f4c2a
                 event->next->prev = event->prev;
7f4c2a
                 event->prev->next = event->next;
7f4c2a
         }
7f4c2a
-unlock:
7f4c2a
         pthread_mutex_unlock (&reg->lock);
7f4c2a
 
7f4c2a
-	if (!fired) {
7f4c2a
-		GF_FREE (event);
7f4c2a
-		return 0;
7f4c2a
-        }
7f4c2a
-        return -1;
7f4c2a
+        GF_FREE (event);
7f4c2a
+        return 0;
7f4c2a
 }
7f4c2a
 
7f4c2a
 static inline void __delete_entry (gf_timer_t *event) {
7f4c2a
@@ -169,9 +180,7 @@ gf_timer_proc (void *ctx)
7f4c2a
                                 at = TS (event->at);
7f4c2a
                                 if (event != &reg->active && now >= at) {
7f4c2a
                                         need_cbk = 1;
7f4c2a
-                                        event->next->prev = event->prev;
7f4c2a
-                                        event->prev->next = event->next;
7f4c2a
-                                        event->fired = 1;
7f4c2a
+                                        gf_timer_call_stale (reg, event);
7f4c2a
                                 }
7f4c2a
                         }
7f4c2a
                         pthread_mutex_unlock (&reg->lock);
7f4c2a
@@ -182,7 +191,9 @@ gf_timer_proc (void *ctx)
7f4c2a
                                         THIS = event->xl;
7f4c2a
                                 }
7f4c2a
                                 event->callbk (event->data);
7f4c2a
-                                GF_FREE (event);
7f4c2a
+                                /*This callbk above would have freed the event
7f4c2a
+                                 * by calling timer_cancel, don't ever touch it
7f4c2a
+                                 * again*/
7f4c2a
                                 if (old_THIS) {
7f4c2a
                                         THIS = old_THIS;
7f4c2a
                                 }
7f4c2a
@@ -204,6 +215,11 @@ gf_timer_proc (void *ctx)
7f4c2a
                          * list_head*/
7f4c2a
                         __delete_entry (event);
7f4c2a
                 }
7f4c2a
+
7f4c2a
+                while (reg->stale.next != &reg->stale) {
7f4c2a
+                        event = reg->stale.next;
7f4c2a
+                        __delete_entry (event);
7f4c2a
+                }
7f4c2a
         }
7f4c2a
         pthread_mutex_unlock (&reg->lock);
7f4c2a
         pthread_mutex_destroy (&reg->lock);
7f4c2a
@@ -232,6 +248,8 @@ gf_timer_registry_init (glusterfs_ctx_t *ctx)
7f4c2a
                 pthread_mutex_init (&reg->lock, NULL);
7f4c2a
                 reg->active.next = &reg->active;
7f4c2a
                 reg->active.prev = &reg->active;
7f4c2a
+                reg->stale.next = &reg->stale;
7f4c2a
+                reg->stale.prev = &reg->stale;
7f4c2a
 
7f4c2a
                 ctx->timer = reg;
7f4c2a
                 gf_thread_create (&reg->th, NULL, gf_timer_proc, ctx);
7f4c2a
diff --git a/libglusterfs/src/timer.h b/libglusterfs/src/timer.h
7f4c2a
index 35d99be..e64b350 100644
7f4c2a
--- a/libglusterfs/src/timer.h
7f4c2a
+++ b/libglusterfs/src/timer.h
7f4c2a
@@ -29,12 +29,12 @@ struct _gf_timer {
7f4c2a
         gf_timer_cbk_t    callbk;
7f4c2a
         void             *data;
7f4c2a
         xlator_t         *xl;
7f4c2a
-	gf_boolean_t      fired;
7f4c2a
 };
7f4c2a
 
7f4c2a
 struct _gf_timer_registry {
7f4c2a
         pthread_t        th;
7f4c2a
         char             fin;
7f4c2a
+        struct _gf_timer stale;
7f4c2a
         struct _gf_timer active;
7f4c2a
         pthread_mutex_t  lock;
7f4c2a
 };
7f4c2a
-- 
7f4c2a
1.7.1
7f4c2a