cb8e9e
From 9b237463a8f5c75cff66364d07278217f8e4e586 Mon Sep 17 00:00:00 2001
cb8e9e
From: Anand Avati <avati@redhat.com>
cb8e9e
Date: Fri, 6 Dec 2013 17:31:57 -0800
cb8e9e
Subject: [PATCH 243/244] timer: fix race between gf_timer_call_cancel() and gf_timer_proc()
cb8e9e
cb8e9e
        Backport of http://review.gluster.org/6459
cb8e9e
cb8e9e
Change-Id: Ie264d3d591352e4a8ddaa90ae2174d9c552396f1
cb8e9e
BUG: 1242423
cb8e9e
Signed-off-by: Anand Avati <avati@redhat.com>
cb8e9e
Reviewed-on: https://code.engineering.redhat.com/gerrit/53060
cb8e9e
Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
cb8e9e
Tested-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
cb8e9e
---
cb8e9e
 libglusterfs/src/timer.c |   53 ++++++++++++++-------------------------------
cb8e9e
 libglusterfs/src/timer.h |    2 +-
cb8e9e
 2 files changed, 18 insertions(+), 37 deletions(-)
cb8e9e
cb8e9e
diff --git a/libglusterfs/src/timer.c b/libglusterfs/src/timer.c
cb8e9e
index 8344c9b..a4d1890 100644
cb8e9e
--- a/libglusterfs/src/timer.c
cb8e9e
+++ b/libglusterfs/src/timer.c
cb8e9e
@@ -85,31 +85,11 @@ gf_timer_call_after (glusterfs_ctx_t *ctx,
cb8e9e
 }
cb8e9e
 
cb8e9e
 int32_t
cb8e9e
-gf_timer_call_stale (gf_timer_registry_t *reg,
cb8e9e
-                     gf_timer_t *event)
cb8e9e
-{
cb8e9e
-        if (reg == NULL || event == NULL)
cb8e9e
-        {
cb8e9e
-                gf_msg_callingfn ("timer", GF_LOG_ERROR, EINVAL,
cb8e9e
-                                  LG_MSG_INVALID_ARG, "invalid argument");
cb8e9e
-                return 0;
cb8e9e
-        }
cb8e9e
-
cb8e9e
-        event->next->prev = event->prev;
cb8e9e
-        event->prev->next = event->next;
cb8e9e
-        event->next = &reg->stale;
cb8e9e
-        event->prev = event->next->prev;
cb8e9e
-        event->next->prev = event;
cb8e9e
-        event->prev->next = event;
cb8e9e
-
cb8e9e
-        return 0;
cb8e9e
-}
cb8e9e
-
cb8e9e
-int32_t
cb8e9e
 gf_timer_call_cancel (glusterfs_ctx_t *ctx,
cb8e9e
                       gf_timer_t *event)
cb8e9e
 {
cb8e9e
         gf_timer_registry_t *reg = NULL;
cb8e9e
+        gf_boolean_t fired = _gf_false;
cb8e9e
 
cb8e9e
         if (ctx == NULL || event == NULL)
cb8e9e
         {
cb8e9e
@@ -128,13 +108,21 @@ gf_timer_call_cancel (glusterfs_ctx_t *ctx,
cb8e9e
 
cb8e9e
         pthread_mutex_lock (&reg->lock);
cb8e9e
         {
cb8e9e
+		fired = event->fired;
cb8e9e
+		if (fired)
cb8e9e
+			goto unlock;
cb8e9e
+
cb8e9e
                 event->next->prev = event->prev;
cb8e9e
                 event->prev->next = event->next;
cb8e9e
         }
cb8e9e
+unlock:
cb8e9e
         pthread_mutex_unlock (&reg->lock);
cb8e9e
 
cb8e9e
-        GF_FREE (event);
cb8e9e
-        return 0;
cb8e9e
+	if (!fired) {
cb8e9e
+		GF_FREE (event);
cb8e9e
+		return 0;
cb8e9e
+        }
cb8e9e
+        return -1;
cb8e9e
 }
cb8e9e
 
cb8e9e
 static inline void __delete_entry (gf_timer_t *event) {
cb8e9e
@@ -181,7 +169,9 @@ gf_timer_proc (void *ctx)
cb8e9e
                                 at = TS (event->at);
cb8e9e
                                 if (event != &reg->active && now >= at) {
cb8e9e
                                         need_cbk = 1;
cb8e9e
-                                        gf_timer_call_stale (reg, event);
cb8e9e
+                                        event->next->prev = event->prev;
cb8e9e
+                                        event->prev->next = event->next;
cb8e9e
+                                        event->fired = 1;
cb8e9e
                                 }
cb8e9e
                         }
cb8e9e
                         pthread_mutex_unlock (&reg->lock);
cb8e9e
@@ -192,15 +182,13 @@ gf_timer_proc (void *ctx)
cb8e9e
                                         THIS = event->xl;
cb8e9e
                                 }
cb8e9e
                                 event->callbk (event->data);
cb8e9e
-                                /*This callbk above would have freed the event
cb8e9e
-                                 * by calling timer_cancel, don't ever touch it
cb8e9e
-                                 * again*/
cb8e9e
+                                GF_FREE (event);
cb8e9e
                                 if (old_THIS) {
cb8e9e
                                         THIS = old_THIS;
cb8e9e
                                 }
cb8e9e
-                        }
cb8e9e
-                        else
cb8e9e
+                        } else {
cb8e9e
                                 break;
cb8e9e
+                        }
cb8e9e
                 }
cb8e9e
                 nanosleep (&sleepts, NULL);
cb8e9e
         }
cb8e9e
@@ -216,11 +204,6 @@ gf_timer_proc (void *ctx)
cb8e9e
                          * list_head*/
cb8e9e
                         __delete_entry (event);
cb8e9e
                 }
cb8e9e
-
cb8e9e
-                while (reg->stale.next != &reg->stale) {
cb8e9e
-                        event = reg->stale.next;
cb8e9e
-                        __delete_entry (event);
cb8e9e
-                }
cb8e9e
         }
cb8e9e
         pthread_mutex_unlock (&reg->lock);
cb8e9e
         pthread_mutex_destroy (&reg->lock);
cb8e9e
@@ -249,8 +232,6 @@ gf_timer_registry_init (glusterfs_ctx_t *ctx)
cb8e9e
                 pthread_mutex_init (&reg->lock, NULL);
cb8e9e
                 reg->active.next = &reg->active;
cb8e9e
                 reg->active.prev = &reg->active;
cb8e9e
-                reg->stale.next = &reg->stale;
cb8e9e
-                reg->stale.prev = &reg->stale;
cb8e9e
 
cb8e9e
                 ctx->timer = reg;
cb8e9e
                 gf_thread_create (&reg->th, NULL, gf_timer_proc, ctx);
cb8e9e
diff --git a/libglusterfs/src/timer.h b/libglusterfs/src/timer.h
cb8e9e
index e64b350..35d99be 100644
cb8e9e
--- a/libglusterfs/src/timer.h
cb8e9e
+++ b/libglusterfs/src/timer.h
cb8e9e
@@ -29,12 +29,12 @@ struct _gf_timer {
cb8e9e
         gf_timer_cbk_t    callbk;
cb8e9e
         void             *data;
cb8e9e
         xlator_t         *xl;
cb8e9e
+	gf_boolean_t      fired;
cb8e9e
 };
cb8e9e
 
cb8e9e
 struct _gf_timer_registry {
cb8e9e
         pthread_t        th;
cb8e9e
         char             fin;
cb8e9e
-        struct _gf_timer stale;
cb8e9e
         struct _gf_timer active;
cb8e9e
         pthread_mutex_t  lock;
cb8e9e
 };
cb8e9e
-- 
cb8e9e
1.7.1
cb8e9e