This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
this is a very strange beast. The Linux AIO implementation doesn't
this is _very_ experimental code
*/
-#include "includes.h"
#include "system/filesys.h"
-#include "lib/util/dlinklist.h"
-#include "lib/events/events.h"
-#include "lib/events/events_internal.h"
+#include "system/network.h"
+#include "events.h"
+#include "events_internal.h"
#include <sys/epoll.h>
#include <libaio.h>
/* a pointer back to the generic event_context */
struct event_context *ev;
+ /* list of filedescriptor events */
+ struct fd_event *fd_events;
+
/* number of registered fd event handlers */
int num_fd_events;
int epoll_fd;
int is_epoll_set;
+ pid_t pid;
};
struct aio_event {
return 0;
}
+static void epoll_add_event(struct aio_event_context *aio_ev, struct fd_event *fde);
+
+/*
+ reopen the epoll handle when our pid changes
+ see http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for an
+ demonstration of why this is needed
+ */
+static void epoll_check_reopen(struct aio_event_context *aio_ev)
+{
+ struct fd_event *fde;
+
+ if (aio_ev->pid == getpid()) {
+ return;
+ }
+
+ close(aio_ev->epoll_fd);
+ aio_ev->epoll_fd = epoll_create(MAX_AIO_QUEUE_DEPTH);
+ if (aio_ev->epoll_fd == -1) {
+ ev_debug(aio_ev->ev, EV_DEBUG_FATAL, "Failed to recreate epoll handle after fork\n");
+ return;
+ }
+ aio_ev->pid = getpid();
+ for (fde=aio_ev->fd_events;fde;fde=fde->next) {
+ epoll_add_event(aio_ev, fde);
+ }
+}
+
#define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0)
#define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1)
#define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2)
static void epoll_del_event(struct aio_event_context *aio_ev, struct fd_event *fde)
{
struct epoll_event event;
+
+ DLIST_REMOVE(aio_ev->fd_events, fde);
+
if (aio_ev->epoll_fd == -1) return;
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
/* there's no aio_event attached to the fde */
if (want_read || (want_write && !got_error)) {
+ DLIST_ADD(aio_ev->fd_events, fde);
epoll_add_event(aio_ev, fde);
return;
}
}
if (ret == 0 && tvalp) {
- common_event_loop_timer(aio_ev->ev);
+ /* we don't care about a possible delay here */
+ common_event_loop_timer_delay(aio_ev->ev);
return 0;
}
talloc_free(aio_ev);
return -1;
}
+ aio_ev->pid = getpid();
talloc_set_destructor(aio_ev, aio_ctx_destructor);
struct aio_event_context *aio_ev = talloc_get_type(ev->additional_data,
struct aio_event_context);
+ epoll_check_reopen(aio_ev);
+
aio_ev->num_fd_events--;
aio_ev->destruction_count++;
epoll_del_event(aio_ev, fde);
+ if (fde->flags & EVENT_FD_AUTOCLOSE) {
+ close(fde->fd);
+ fde->fd = -1;
+ }
+
return 0;
}
struct aio_event_context);
struct fd_event *fde;
+ epoll_check_reopen(aio_ev);
+
fde = talloc(mem_ctx?mem_ctx:ev, struct fd_event);
if (!fde) return NULL;
aio_ev->num_fd_events++;
talloc_set_destructor(fde, aio_event_fd_destructor);
+ DLIST_ADD(aio_ev->fd_events, fde);
epoll_add_event(aio_ev, fde);
return fde;
fde->flags = flags;
+ epoll_check_reopen(aio_ev);
+
epoll_change_event(aio_ev, fde);
}
struct aio_event_context);
struct timeval tval;
- tval = common_event_loop_delay(ev);
-
+ tval = common_event_loop_timer_delay(ev);
if (timeval_is_zero(&tval)) {
- common_event_loop_timer(ev);
return 0;
}
+ epoll_check_reopen(aio_ev);
+
return aio_event_loop(aio_ev, &tval);
}
return event_register_backend("aio", &aio_event_ops);
}
-#if _SAMBA_BUILD_
-NTSTATUS s4_events_aio_init(void)
-{
- if (!events_aio_init()) {
- return NT_STATUS_INTERNAL_ERROR;
- }
- return NT_STATUS_OK;
-}
-#endif