diff options
Diffstat (limited to 'libglusterfs/src/event-epoll.c')
| -rw-r--r-- | libglusterfs/src/event-epoll.c | 214 |
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); |
