summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/event-epoll.c
diff options
context:
space:
mode:
Diffstat (limited to 'libglusterfs/src/event-epoll.c')
-rw-r--r--libglusterfs/src/event-epoll.c214
1 files changed, 98 insertions, 116 deletions
diff --git a/libglusterfs/src/event-epoll.c b/libglusterfs/src/event-epoll.c
index 041a7e6c583..fb4fb845b40 100644
--- a/libglusterfs/src/event-epoll.c
+++ b/libglusterfs/src/event-epoll.c
@@ -8,20 +8,14 @@
cases as published by the Free Software Foundation.
*/
-#include <sys/poll.h>
#include <pthread.h>
-#include <unistd.h>
-#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
-#include <string.h>
-#include "logging.h"
-#include "gf-event.h"
-#include "mem-pool.h"
-#include "common-utils.h"
-#include "syscall.h"
-#include "libglusterfs-messages.h"
+#include "glusterfs/gf-event.h"
+#include "glusterfs/common-utils.h"
+#include "glusterfs/syscall.h"
+#include "glusterfs/libglusterfs-messages.h"
#ifdef HAVE_SYS_EPOLL_H
#include <sys/epoll.h>
@@ -69,18 +63,30 @@ __event_newtable(struct event_pool *event_pool, int table_idx)
}
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 +104,7 @@ __event_slot_alloc(struct event_pool *event_pool, int fd,
if (table)
/* break out of the loop */
break;
+ i++;
}
if (!table)
@@ -105,20 +112,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 +135,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 +168,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 +180,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 +203,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)
{
@@ -287,9 +296,8 @@ event_pool_new_epoll(int count, int eventthreadcount)
epfd = epoll_create(count);
if (epfd == -1) {
- gf_msg("epoll", GF_LOG_ERROR, errno, LG_MSG_EPOLL_FD_CREATE_FAILED,
- "epoll fd creation "
- "failed");
+ gf_smsg("epoll", GF_LOG_ERROR, errno, LG_MSG_EPOLL_FD_CREATE_FAILED,
+ NULL);
GF_FREE(event_pool->reg);
GF_FREE(event_pool);
event_pool = NULL;
@@ -323,8 +331,8 @@ __slot_update_events(struct event_slot_epoll *slot, int poll_in, int poll_out)
/* do nothing */
break;
default:
- gf_msg("epoll", GF_LOG_ERROR, 0, LG_MSG_INVALID_POLL_IN,
- "invalid poll_in value %d", poll_in);
+ gf_smsg("epoll", GF_LOG_ERROR, 0, LG_MSG_INVALID_POLL_IN,
+ "value=%d", poll_in, NULL);
break;
}
@@ -339,8 +347,8 @@ __slot_update_events(struct event_slot_epoll *slot, int poll_in, int poll_out)
/* do nothing */
break;
default:
- gf_msg("epoll", GF_LOG_ERROR, 0, LG_MSG_INVALID_POLL_OUT,
- "invalid poll_out value %d", poll_out);
+ gf_smsg("epoll", GF_LOG_ERROR, 0, LG_MSG_INVALID_POLL_OUT,
+ "value=%d", poll_out, NULL);
break;
}
}
@@ -379,17 +387,10 @@ 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);
+ gf_smsg("epoll", GF_LOG_ERROR, 0, LG_MSG_SLOT_NOT_FOUND, "fd=%d", fd,
+ NULL);
return -1;
}
@@ -424,10 +425,8 @@ event_register_epoll(struct event_pool *event_pool, int fd,
UNLOCK(&slot->lock);
if (ret == -1) {
- gf_msg("epoll", GF_LOG_ERROR, errno, LG_MSG_EPOLL_FD_ADD_FAILED,
- "failed to add fd(=%d) to "
- "epoll fd(=%d)",
- fd, event_pool->fd);
+ gf_smsg("epoll", GF_LOG_ERROR, errno, LG_MSG_EPOLL_FD_ADD_FAILED,
+ "fd=%d", fd, "epoll_fd=%d", event_pool->fd, NULL);
event_slot_unref(event_pool, slot, idx);
idx = -1;
}
@@ -456,8 +455,8 @@ event_unregister_epoll_common(struct event_pool *event_pool, int fd, int idx,
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);
+ gf_smsg("epoll", GF_LOG_ERROR, 0, LG_MSG_SLOT_NOT_FOUND, "fd=%d", fd,
+ "idx=%d", idx, NULL);
return -1;
}
@@ -468,10 +467,8 @@ event_unregister_epoll_common(struct event_pool *event_pool, int fd, int idx,
ret = epoll_ctl(event_pool->fd, EPOLL_CTL_DEL, fd, NULL);
if (ret == -1) {
- gf_msg("epoll", GF_LOG_ERROR, errno, LG_MSG_EPOLL_FD_DEL_FAILED,
- "fail to del "
- "fd(=%d) from epoll fd(=%d)",
- fd, event_pool->fd);
+ gf_smsg("epoll", GF_LOG_ERROR, errno, LG_MSG_EPOLL_FD_DEL_FAILED,
+ "fd=%d", fd, "epoll_fd=%d", event_pool->fd, NULL);
goto unlock;
}
@@ -523,8 +520,8 @@ event_select_on_epoll(struct event_pool *event_pool, int fd, int idx,
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);
+ gf_smsg("epoll", GF_LOG_ERROR, 0, LG_MSG_SLOT_NOT_FOUND, "fd=%d", fd,
+ "idx=%d", idx, NULL);
return -1;
}
@@ -555,10 +552,8 @@ event_select_on_epoll(struct event_pool *event_pool, int fd, int idx,
ret = epoll_ctl(event_pool->fd, EPOLL_CTL_MOD, fd, &epoll_event);
if (ret == -1) {
- gf_msg("epoll", GF_LOG_ERROR, errno, LG_MSG_EPOLL_FD_MODIFY_FAILED,
- "failed to "
- "modify fd(=%d) events to %d",
- fd, epoll_event.events);
+ gf_smsg("epoll", GF_LOG_ERROR, errno, LG_MSG_EPOLL_FD_MODIFY_FAILED,
+ "fd=%d", fd, "events=%d", epoll_event.events, NULL);
}
}
unlock:
@@ -593,8 +588,8 @@ event_dispatch_epoll_handler(struct event_pool *event_pool,
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 idx=%d", idx);
+ gf_smsg("epoll", GF_LOG_ERROR, 0, LG_MSG_SLOT_NOT_FOUND, "idx=%d", idx,
+ NULL);
return -1;
}
@@ -602,20 +597,17 @@ event_dispatch_epoll_handler(struct event_pool *event_pool,
{
fd = slot->fd;
if (fd == -1) {
- gf_msg("epoll", GF_LOG_ERROR, 0, LG_MSG_STALE_FD_FOUND,
- "stale fd found on "
- "idx=%d, gen=%d, events=%d, slot->gen=%d",
- idx, gen, event->events, slot->gen);
+ gf_smsg("epoll", GF_LOG_ERROR, 0, LG_MSG_STALE_FD_FOUND, "idx=%d",
+ idx, "gen=%d", gen, "events=%d", event->events,
+ "slot->gen=%d", slot->gen, NULL);
/* fd got unregistered in another thread */
goto pre_unlock;
}
if (gen != slot->gen) {
- gf_msg("epoll", GF_LOG_ERROR, 0, LG_MSG_GENERATION_MISMATCH,
- "generation "
- "mismatch on idx=%d, gen=%d, slot->gen=%d, "
- "slot->fd=%d",
- idx, gen, slot->gen, slot->fd);
+ gf_smsg("epoll", GF_LOG_ERROR, 0, LG_MSG_GENERATION_MISMATCH,
+ "idx=%d", idx, "gen=%d", gen, "slot->gen=%d", slot->gen,
+ "slot->fd=%d", slot->fd, NULL);
/* slot was re-used and therefore is another fd! */
goto pre_unlock;
}
@@ -623,6 +615,12 @@ event_dispatch_epoll_handler(struct event_pool *event_pool,
handler = slot->handler;
data = slot->data;
+ if (slot->in_handler > 0) {
+ /* Another handler is inprogress, skip this one. */
+ handler = NULL;
+ goto pre_unlock;
+ }
+
if (slot->handled_error) {
handled_error_previously = _gf_true;
} else {
@@ -639,10 +637,9 @@ pre_unlock:
goto out;
if (!handled_error_previously) {
- ret = handler(fd, idx, gen, data,
- (event->events & (EPOLLIN | EPOLLPRI)),
- (event->events & (EPOLLOUT)),
- (event->events & (EPOLLERR | EPOLLHUP)), 0);
+ handler(fd, idx, gen, data, (event->events & (EPOLLIN | EPOLLPRI)),
+ (event->events & (EPOLLOUT)),
+ (event->events & (EPOLLERR | EPOLLHUP)), 0);
}
out:
event_slot_unref(event_pool, slot, idx);
@@ -669,10 +666,8 @@ event_dispatch_epoll_worker(void *data)
GF_VALIDATE_OR_GOTO("event", event_pool, out);
- gf_msg("epoll", GF_LOG_INFO, 0, LG_MSG_STARTED_EPOLL_THREAD,
- "Started"
- " thread with index %d",
- myindex - 1);
+ gf_smsg("epoll", GF_LOG_INFO, 0, LG_MSG_STARTED_EPOLL_THREAD, "index=%d",
+ myindex - 1, NULL);
pthread_mutex_lock(&event_pool->mutex);
{
@@ -736,8 +731,8 @@ event_dispatch_epoll_worker(void *data)
}
pthread_mutex_unlock(&event_pool->mutex);
- gf_msg("epoll", GF_LOG_INFO, 0, LG_MSG_EXITED_EPOLL_THREAD,
- "Exited thread with index %d", myindex);
+ gf_smsg("epoll", GF_LOG_INFO, 0, LG_MSG_EXITED_EPOLL_THREAD,
+ "index=%d", myindex, NULL);
goto out;
}
@@ -755,8 +750,8 @@ event_dispatch_epoll_worker(void *data)
ret = event_dispatch_epoll_handler(event_pool, &event);
if (ret) {
- gf_msg("epoll", GF_LOG_ERROR, 0, LG_MSG_EXITED_EPOLL_THREAD,
- "Failed to dispatch handler");
+ gf_smsg("epoll", GF_LOG_ERROR, 0, LG_MSG_DISPATCH_HANDLER_FAILED,
+ NULL);
}
}
out:
@@ -775,9 +770,6 @@ event_dispatch_epoll(struct event_pool *event_pool)
int pollercount = 0;
int ret = -1;
struct event_thread_data *ev_data = NULL;
- char thread_name[GF_THREAD_NAMEMAX] = {
- 0,
- };
/* Start the configured number of pollers */
pthread_mutex_lock(&event_pool->mutex);
@@ -811,10 +803,8 @@ event_dispatch_epoll(struct event_pool *event_pool)
ev_data->event_pool = event_pool;
ev_data->event_index = i + 1;
- snprintf(thread_name, sizeof(thread_name), "epoll%03hx",
- (i & 0x3ff));
ret = gf_thread_create(&t_id, NULL, event_dispatch_epoll_worker,
- ev_data, thread_name);
+ ev_data, "epoll%03hx", i & 0x3ff);
if (!ret) {
event_pool->pollers[i] = t_id;
@@ -825,9 +815,8 @@ event_dispatch_epoll(struct event_pool *event_pool)
if (i != 0)
pthread_detach(event_pool->pollers[i]);
} else {
- gf_msg("epoll", GF_LOG_WARNING, 0,
- LG_MSG_START_EPOLL_THREAD_FAILED,
- "Failed to start thread for index %d", i);
+ gf_smsg("epoll", GF_LOG_WARNING, 0,
+ LG_MSG_START_EPOLL_THREAD_FAILED, "index=%d", i, NULL);
if (i == 0) {
GF_FREE(ev_data);
break;
@@ -877,9 +866,6 @@ event_reconfigure_threads_epoll(struct event_pool *event_pool, int value)
pthread_t t_id;
int oldthreadcount;
struct event_thread_data *ev_data = NULL;
- char thread_name[GF_THREAD_NAMEMAX] = {
- 0,
- };
pthread_mutex_lock(&event_pool->mutex);
{
@@ -919,17 +905,13 @@ event_reconfigure_threads_epoll(struct event_pool *event_pool, int value)
ev_data->event_pool = event_pool;
ev_data->event_index = i + 1;
- snprintf(thread_name, sizeof(thread_name), "epoll%03hx",
- (i & 0x3ff));
ret = gf_thread_create(&t_id, NULL,
event_dispatch_epoll_worker, ev_data,
- thread_name);
+ "epoll%03hx", i & 0x3ff);
if (ret) {
- gf_msg("epoll", GF_LOG_WARNING, 0,
- LG_MSG_START_EPOLL_THREAD_FAILED,
- "Failed to start thread"
- " for index %d",
- i);
+ gf_smsg("epoll", GF_LOG_WARNING, 0,
+ LG_MSG_START_EPOLL_THREAD_FAILED, "index=%d", i,
+ NULL);
GF_FREE(ev_data);
} else {
pthread_detach(t_id);
@@ -992,8 +974,8 @@ event_handled_epoll(struct event_pool *event_pool, int fd, int idx, int gen)
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);
+ gf_smsg("epoll", GF_LOG_ERROR, 0, LG_MSG_SLOT_NOT_FOUND, "fd=%d", fd,
+ "idx=%d", idx, NULL);
return -1;
}
@@ -1012,7 +994,7 @@ event_handled_epoll(struct event_pool *event_pool, int fd, int idx, int gen)
" from gen=%d to slot->gen=%d, fd=%d, "
"slot->fd=%d",
idx, gen, slot->gen, fd, slot->fd);
- goto post_unlock;
+ goto unlock;
}
/* This call also picks up the changes made by another
@@ -1027,7 +1009,7 @@ event_handled_epoll(struct event_pool *event_pool, int fd, int idx, int gen)
ret = epoll_ctl(event_pool->fd, EPOLL_CTL_MOD, fd, &epoll_event);
}
}
-post_unlock:
+unlock:
UNLOCK(&slot->lock);
event_slot_unref(event_pool, slot, idx);