From 3d3f74fdf195f9cec3c9c79ae8f2fa50720fd09f Mon Sep 17 00:00:00 2001 From: Mohit Agrawal Date: Thu, 3 Oct 2019 14:06:52 +0530 Subject: rpc: Synchronize slot allocation code Problem: Current slot allocation/deallocation code path is not synchronized.There are scenario when due to race condition in slot allocation/deallocation code path brick is crashed. Solution: Synchronize slot allocation/deallocation code path to avoid the issue > Change-Id: I4fb659a75234218ffa0e5e0bf9308f669f75fc25 > Fixes: bz#1763036 > Signed-off-by: Mohit Agrawal > (cherry picked from commit faf5ac13c4ee00a05e9451bf8da3be2a9043bbf2) Change-Id: I4fb659a75234218ffa0e5e0bf9308f669f75fc25 Fixes: bz#1778182 Signed-off-by: Mohit Agrawal --- libglusterfs/src/event-epoll.c | 76 +++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/libglusterfs/src/event-epoll.c b/libglusterfs/src/event-epoll.c index 0cec47e6050..5afb2f22c2a 100644 --- a/libglusterfs/src/event-epoll.c +++ b/libglusterfs/src/event-epoll.c @@ -68,19 +68,31 @@ __event_newtable(struct event_pool *event_pool, int table_idx) return table; } +static int +event_slot_ref(struct event_slot_epoll *slot) +{ + if (!slot) + return -1; + + return GF_ATOMIC_INC(slot->ref); +} + static int __event_slot_alloc(struct event_pool *event_pool, int fd, - char notify_poller_death) + char notify_poller_death, struct event_slot_epoll **slot) { int i = 0; + int j = 0; int table_idx = -1; int gen = -1; struct event_slot_epoll *table = NULL; - for (i = 0; i < EVENT_EPOLL_TABLES; i++) { +retry: + + while (i < EVENT_EPOLL_TABLES) { switch (event_pool->slots_used[i]) { case EVENT_EPOLL_SLOTS: - continue; + break; case 0: if (!event_pool->ereg[i]) { table = __event_newtable(event_pool, i); @@ -98,6 +110,7 @@ __event_slot_alloc(struct event_pool *event_pool, int fd, if (table) /* break out of the loop */ break; + i++; } if (!table) @@ -105,20 +118,20 @@ __event_slot_alloc(struct event_pool *event_pool, int fd, table_idx = i; - for (i = 0; i < EVENT_EPOLL_SLOTS; i++) { - if (table[i].fd == -1) { + for (j = 0; j < EVENT_EPOLL_SLOTS; j++) { + if (table[j].fd == -1) { /* wipe everything except bump the generation */ - gen = table[i].gen; - memset(&table[i], 0, sizeof(table[i])); - table[i].gen = gen + 1; + gen = table[j].gen; + memset(&table[j], 0, sizeof(table[j])); + table[j].gen = gen + 1; - LOCK_INIT(&table[i].lock); - INIT_LIST_HEAD(&table[i].poller_death); + LOCK_INIT(&table[j].lock); + INIT_LIST_HEAD(&table[j].poller_death); - table[i].fd = fd; + table[j].fd = fd; if (notify_poller_death) { - table[i].idx = table_idx * EVENT_EPOLL_SLOTS + i; - list_add_tail(&table[i].poller_death, + table[j].idx = table_idx * EVENT_EPOLL_SLOTS + j; + list_add_tail(&table[j].poller_death, &event_pool->poller_death); } @@ -128,18 +141,26 @@ __event_slot_alloc(struct event_pool *event_pool, int fd, } } - return table_idx * EVENT_EPOLL_SLOTS + i; + if (j == EVENT_EPOLL_SLOTS) { + table = NULL; + i++; + goto retry; + } else { + (*slot) = &table[j]; + event_slot_ref(*slot); + return table_idx * EVENT_EPOLL_SLOTS + j; + } } static int event_slot_alloc(struct event_pool *event_pool, int fd, - char notify_poller_death) + char notify_poller_death, struct event_slot_epoll **slot) { int idx = -1; pthread_mutex_lock(&event_pool->mutex); { - idx = __event_slot_alloc(event_pool, fd, notify_poller_death); + idx = __event_slot_alloc(event_pool, fd, notify_poller_death, slot); } pthread_mutex_unlock(&event_pool->mutex); @@ -153,6 +174,7 @@ __event_slot_dealloc(struct event_pool *event_pool, int idx) int offset = 0; struct event_slot_epoll *table = NULL; struct event_slot_epoll *slot = NULL; + int fd = -1; table_idx = idx / EVENT_EPOLL_SLOTS; offset = idx % EVENT_EPOLL_SLOTS; @@ -164,11 +186,13 @@ __event_slot_dealloc(struct event_pool *event_pool, int idx) slot = &table[offset]; slot->gen++; + fd = slot->fd; slot->fd = -1; slot->handled_error = 0; slot->in_handler = 0; list_del_init(&slot->poller_death); - event_pool->slots_used[table_idx]--; + if (fd != -1) + event_pool->slots_used[table_idx]--; return; } @@ -185,15 +209,6 @@ event_slot_dealloc(struct event_pool *event_pool, int idx) return; } -static int -event_slot_ref(struct event_slot_epoll *slot) -{ - if (!slot) - return -1; - - return GF_ATOMIC_INC(slot->ref); -} - static struct event_slot_epoll * event_slot_get(struct event_pool *event_pool, int idx) { @@ -379,20 +394,13 @@ event_register_epoll(struct event_pool *event_pool, int fd, if (destroy == 1) goto out; - idx = event_slot_alloc(event_pool, fd, notify_poller_death); + idx = event_slot_alloc(event_pool, fd, notify_poller_death, &slot); if (idx == -1) { gf_msg("epoll", GF_LOG_ERROR, 0, LG_MSG_SLOT_NOT_FOUND, "could not find slot for fd=%d", fd); return -1; } - slot = event_slot_get(event_pool, idx); - if (!slot) { - gf_msg("epoll", GF_LOG_ERROR, 0, LG_MSG_SLOT_NOT_FOUND, - "could not find slot for fd=%d idx=%d", fd, idx); - return -1; - } - assert(slot->fd == fd); LOCK(&slot->lock); -- cgit