1df6c8
From f199094cb61341a47c98a8ed91b293446182b5a9 Mon Sep 17 00:00:00 2001
1df6c8
From: Mohit Agrawal <moagrawal@redhat.com>
1df6c8
Date: Thu, 3 Oct 2019 14:06:52 +0530
1df6c8
Subject: [PATCH 333/335] rpc: Synchronize slot allocation code
1df6c8
1df6c8
Problem: Current slot allocation/deallocation code path is not
1df6c8
         synchronized.There are scenario when due to race condition
1df6c8
         in slot allocation/deallocation code path brick is crashed.
1df6c8
1df6c8
Solution: Synchronize slot allocation/deallocation code path to
1df6c8
          avoid the issue
1df6c8
1df6c8
> Change-Id: I4fb659a75234218ffa0e5e0bf9308f669f75fc25
1df6c8
> Fixes: bz#1763036
1df6c8
> Signed-off-by: Mohit Agrawal <moagrawal@redhat.com>
1df6c8
> (Reviewed on upstream link https://review.gluster.org/#/c/glusterfs/+/23508/)
1df6c8
> (Cherry pick from commit faf5ac13c4ee00a05e9451bf8da3be2a9043bbf2)
1df6c8
1df6c8
Change-Id: I4fb659a75234218ffa0e5e0bf9308f669f75fc25
1df6c8
BUG: 1741193
1df6c8
Signed-off-by: Mohit Agrawal <moagrawa@redhat.com>
1df6c8
Reviewed-on: https://code.engineering.redhat.com/gerrit/185827
1df6c8
Tested-by: RHGS Build Bot <nigelb@redhat.com>
1df6c8
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
1df6c8
---
1df6c8
 libglusterfs/src/event-epoll.c | 74 +++++++++++++++++++++++-------------------
1df6c8
 1 file changed, 41 insertions(+), 33 deletions(-)
1df6c8
1df6c8
diff --git a/libglusterfs/src/event-epoll.c b/libglusterfs/src/event-epoll.c
1df6c8
index 0cec47e..65f5efd 100644
1df6c8
--- a/libglusterfs/src/event-epoll.c
1df6c8
+++ b/libglusterfs/src/event-epoll.c
1df6c8
@@ -69,15 +69,27 @@ __event_newtable(struct event_pool *event_pool, int table_idx)
1df6c8
 }
1df6c8
 
1df6c8
 static int
1df6c8
+event_slot_ref(struct event_slot_epoll *slot)
1df6c8
+{
1df6c8
+    if (!slot)
1df6c8
+        return -1;
1df6c8
+
1df6c8
+    return GF_ATOMIC_INC(slot->ref);
1df6c8
+}
1df6c8
+
1df6c8
+static int
1df6c8
 __event_slot_alloc(struct event_pool *event_pool, int fd,
1df6c8
-                   char notify_poller_death)
1df6c8
+                   char notify_poller_death, struct event_slot_epoll **slot)
1df6c8
 {
1df6c8
     int i = 0;
1df6c8
+    int j = 0;
1df6c8
     int table_idx = -1;
1df6c8
     int gen = -1;
1df6c8
     struct event_slot_epoll *table = NULL;
1df6c8
 
1df6c8
-    for (i = 0; i < EVENT_EPOLL_TABLES; i++) {
1df6c8
+retry:
1df6c8
+
1df6c8
+    while (i < EVENT_EPOLL_TABLES) {
1df6c8
         switch (event_pool->slots_used[i]) {
1df6c8
             case EVENT_EPOLL_SLOTS:
1df6c8
                 continue;
1df6c8
@@ -98,6 +110,7 @@ __event_slot_alloc(struct event_pool *event_pool, int fd,
1df6c8
         if (table)
1df6c8
             /* break out of the loop */
1df6c8
             break;
1df6c8
+        i++;
1df6c8
     }
1df6c8
 
1df6c8
     if (!table)
1df6c8
@@ -105,20 +118,20 @@ __event_slot_alloc(struct event_pool *event_pool, int fd,
1df6c8
 
1df6c8
     table_idx = i;
1df6c8
 
1df6c8
-    for (i = 0; i < EVENT_EPOLL_SLOTS; i++) {
1df6c8
-        if (table[i].fd == -1) {
1df6c8
+    for (j = 0; j < EVENT_EPOLL_SLOTS; j++) {
1df6c8
+        if (table[j].fd == -1) {
1df6c8
             /* wipe everything except bump the generation */
1df6c8
-            gen = table[i].gen;
1df6c8
-            memset(&table[i], 0, sizeof(table[i]));
1df6c8
-            table[i].gen = gen + 1;
1df6c8
+            gen = table[j].gen;
1df6c8
+            memset(&table[j], 0, sizeof(table[j]));
1df6c8
+            table[j].gen = gen + 1;
1df6c8
 
1df6c8
-            LOCK_INIT(&table[i].lock);
1df6c8
-            INIT_LIST_HEAD(&table[i].poller_death);
1df6c8
+            LOCK_INIT(&table[j].lock);
1df6c8
+            INIT_LIST_HEAD(&table[j].poller_death);
1df6c8
 
1df6c8
-            table[i].fd = fd;
1df6c8
+            table[j].fd = fd;
1df6c8
             if (notify_poller_death) {
1df6c8
-                table[i].idx = table_idx * EVENT_EPOLL_SLOTS + i;
1df6c8
-                list_add_tail(&table[i].poller_death,
1df6c8
+                table[j].idx = table_idx * EVENT_EPOLL_SLOTS + j;
1df6c8
+                list_add_tail(&table[j].poller_death,
1df6c8
                               &event_pool->poller_death);
1df6c8
             }
1df6c8
 
1df6c8
@@ -128,18 +141,26 @@ __event_slot_alloc(struct event_pool *event_pool, int fd,
1df6c8
         }
1df6c8
     }
1df6c8
 
1df6c8
-    return table_idx * EVENT_EPOLL_SLOTS + i;
1df6c8
+    if (j == EVENT_EPOLL_SLOTS) {
1df6c8
+        table = NULL;
1df6c8
+        i++;
1df6c8
+        goto retry;
1df6c8
+    } else {
1df6c8
+        (*slot) = &table[j];
1df6c8
+        event_slot_ref(*slot);
1df6c8
+        return table_idx * EVENT_EPOLL_SLOTS + j;
1df6c8
+    }
1df6c8
 }
1df6c8
 
1df6c8
 static int
1df6c8
 event_slot_alloc(struct event_pool *event_pool, int fd,
1df6c8
-                 char notify_poller_death)
1df6c8
+                 char notify_poller_death, struct event_slot_epoll **slot)
1df6c8
 {
1df6c8
     int idx = -1;
1df6c8
 
1df6c8
     pthread_mutex_lock(&event_pool->mutex);
1df6c8
     {
1df6c8
-        idx = __event_slot_alloc(event_pool, fd, notify_poller_death);
1df6c8
+        idx = __event_slot_alloc(event_pool, fd, notify_poller_death, slot);
1df6c8
     }
1df6c8
     pthread_mutex_unlock(&event_pool->mutex);
1df6c8
 
1df6c8
@@ -153,6 +174,7 @@ __event_slot_dealloc(struct event_pool *event_pool, int idx)
1df6c8
     int offset = 0;
1df6c8
     struct event_slot_epoll *table = NULL;
1df6c8
     struct event_slot_epoll *slot = NULL;
1df6c8
+    int fd = -1;
1df6c8
 
1df6c8
     table_idx = idx / EVENT_EPOLL_SLOTS;
1df6c8
     offset = idx % EVENT_EPOLL_SLOTS;
1df6c8
@@ -164,11 +186,13 @@ __event_slot_dealloc(struct event_pool *event_pool, int idx)
1df6c8
     slot = &table[offset];
1df6c8
     slot->gen++;
1df6c8
 
1df6c8
+    fd = slot->fd;
1df6c8
     slot->fd = -1;
1df6c8
     slot->handled_error = 0;
1df6c8
     slot->in_handler = 0;
1df6c8
     list_del_init(&slot->poller_death);
1df6c8
-    event_pool->slots_used[table_idx]--;
1df6c8
+    if (fd != -1)
1df6c8
+        event_pool->slots_used[table_idx]--;
1df6c8
 
1df6c8
     return;
1df6c8
 }
1df6c8
@@ -185,15 +209,6 @@ event_slot_dealloc(struct event_pool *event_pool, int idx)
1df6c8
     return;
1df6c8
 }
1df6c8
 
1df6c8
-static int
1df6c8
-event_slot_ref(struct event_slot_epoll *slot)
1df6c8
-{
1df6c8
-    if (!slot)
1df6c8
-        return -1;
1df6c8
-
1df6c8
-    return GF_ATOMIC_INC(slot->ref);
1df6c8
-}
1df6c8
-
1df6c8
 static struct event_slot_epoll *
1df6c8
 event_slot_get(struct event_pool *event_pool, int idx)
1df6c8
 {
1df6c8
@@ -379,20 +394,13 @@ event_register_epoll(struct event_pool *event_pool, int fd,
1df6c8
     if (destroy == 1)
1df6c8
         goto out;
1df6c8
 
1df6c8
-    idx = event_slot_alloc(event_pool, fd, notify_poller_death);
1df6c8
+    idx = event_slot_alloc(event_pool, fd, notify_poller_death, &slot);
1df6c8
     if (idx == -1) {
1df6c8
         gf_msg("epoll", GF_LOG_ERROR, 0, LG_MSG_SLOT_NOT_FOUND,
1df6c8
                "could not find slot for fd=%d", fd);
1df6c8
         return -1;
1df6c8
     }
1df6c8
 
1df6c8
-    slot = event_slot_get(event_pool, idx);
1df6c8
-    if (!slot) {
1df6c8
-        gf_msg("epoll", GF_LOG_ERROR, 0, LG_MSG_SLOT_NOT_FOUND,
1df6c8
-               "could not find slot for fd=%d idx=%d", fd, idx);
1df6c8
-        return -1;
1df6c8
-    }
1df6c8
-
1df6c8
     assert(slot->fd == fd);
1df6c8
 
1df6c8
     LOCK(&slot->lock);
1df6c8
-- 
1df6c8
1.8.3.1
1df6c8