--- /dev/null
+From 1d94210adc6e0bb8a08fbfc1a516a0f958dbf744 Mon Sep 17 00:00:00 2001
+From: Volker Lendecke <vl@samba.org>
+Date: Wed, 16 Jan 2013 12:00:00 +0100
+Subject: [PATCH 1/2] winbind: Use standard tevent_context_init
+
+This makes winbind use epoll instead of poll
+---
+ source3/winbindd/winbindd.c | 38 ++++++++++++++++++++++++++++++++-----
+ source3/winbindd/winbindd.h | 2 --
+ source3/winbindd/winbindd_proto.h | 1 +
+ 3 files changed, 34 insertions(+), 7 deletions(-)
+
+Index: samba-3.6.22/source3/winbindd/winbindd.c
+===================================================================
+--- samba-3.6.22.orig/source3/winbindd/winbindd.c
++++ samba-3.6.22/source3/winbindd/winbindd.c
+@@ -48,14 +48,42 @@ static bool interactive = False;
+
+ extern bool override_logfile;
+
++struct tevent_context *winbind_event_context(void)
++{
++ static struct tevent_context *ev = NULL;
++
++ if (ev != NULL) {
++ return ev;
++ }
++
++ /*
++ * Note we MUST use the NULL context here, not the autofree context,
++ * to avoid side effects in forked children exiting.
++ */
++ ev = tevent_context_init(NULL);
++ if (ev == NULL) {
++ smb_panic("Could not init winbindd's messaging context.\n");
++ }
++ return ev;
++}
++
+ struct messaging_context *winbind_messaging_context(void)
+ {
+- struct messaging_context *msg_ctx = server_messaging_context();
+- if (likely(msg_ctx != NULL)) {
+- return msg_ctx;
++ static struct messaging_context *msg = NULL;
++
++ if (msg != NULL) {
++ return msg;
++ }
++
++ /*
++ * Note we MUST use the NULL context here, not the autofree context,
++ * to avoid side effects in forked children exiting.
++ */
++ msg = messaging_init(NULL, procid_self(), winbind_event_context());
++ if (msg == NULL) {
++ smb_panic("Could not init winbindd's messaging context.\n");
+ }
+- smb_panic("Could not init winbindd's messaging context.\n");
+- return NULL;
++ return msg;
+ }
+
+ /* Reload configuration */
+Index: samba-3.6.22/source3/winbindd/winbindd.h
+===================================================================
+--- samba-3.6.22.orig/source3/winbindd/winbindd.h
++++ samba-3.6.22/source3/winbindd/winbindd.h
+@@ -397,6 +397,4 @@ struct WINBINDD_CCACHE_ENTRY {
+ #define WINBINDD_PAM_AUTH_KRB5_RENEW_TIME 2592000 /* one month */
+ #define DOM_SEQUENCE_NONE ((uint32)-1)
+
+-#define winbind_event_context server_event_context
+-
+ #endif /* _WINBINDD_H */
+Index: samba-3.6.22/source3/winbindd/winbindd_proto.h
+===================================================================
+--- samba-3.6.22.orig/source3/winbindd/winbindd_proto.h
++++ samba-3.6.22/source3/winbindd/winbindd_proto.h
+@@ -34,6 +34,7 @@ bool winbindd_use_cache(void);
+ void winbindd_register_handlers(void);
+ const char *get_winbind_pipe_dir(void);
+ char *get_winbind_priv_pipe_dir(void);
++struct tevent_context *winbind_event_context(void);
+ int main(int argc, char **argv, char **envp);
+
+ /* The following definitions come from winbindd/winbindd_ads.c */
+Index: samba-3.6.22/source3/winbindd/winbindd_dual.c
+===================================================================
+--- samba-3.6.22.orig/source3/winbindd/winbindd_dual.c
++++ samba-3.6.22/source3/winbindd/winbindd_dual.c
+@@ -1284,6 +1284,66 @@ NTSTATUS winbindd_reinit_after_fork(cons
+ return NT_STATUS_OK;
+ }
+
++struct child_handler_state {
++ struct winbindd_child *child;
++ struct winbindd_cli_state *cli_state;
++};
++
++static void child_handler(struct tevent_context *ev, struct tevent_fd *fde,
++ uint16_t flags, void *private_data)
++{
++ struct child_handler_state *ch_state =
++ (struct child_handler_state *)private_data;
++ struct winbindd_cli_state *state = ch_state->cli_state;
++ struct iovec iov[2];
++ int iov_count;
++ NTSTATUS status;
++
++ if ((flags & TEVENT_FD_READ) == 0) {
++ return;
++ }
++
++ /* fetch a request from the main daemon */
++ status = child_read_request(state);
++
++ if (!NT_STATUS_IS_OK(status)) {
++ /* we lost contact with our parent */
++ _exit(0);
++ }
++
++ DEBUG(4,("child daemon request %d\n", (int)state->request->cmd));
++
++ ZERO_STRUCTP(state->response);
++ state->request->null_term = '\0';
++ state->mem_ctx = talloc_tos();
++ child_process_request(ch_state->child, state);
++
++ DEBUG(4, ("Finished processing child request %d\n",
++ (int)state->request->cmd));
++
++ SAFE_FREE(state->request->extra_data.data);
++
++ iov[0].iov_base = (void *)state->response;
++ iov[0].iov_len = sizeof(struct winbindd_response);
++ iov_count = 1;
++
++ if (state->response->length > sizeof(struct winbindd_response)) {
++ iov[1].iov_base =
++ (void *)state->response->extra_data.data;
++ iov[1].iov_len = state->response->length-iov[0].iov_len;
++ iov_count = 2;
++ }
++
++ DEBUG(10, ("Writing %d bytes to parent\n",
++ (int)state->response->length));
++
++ if (write_data_iov(state->sock, iov, iov_count) !=
++ state->response->length) {
++ DEBUG(0, ("Could not write result\n"));
++ exit(1);
++ }
++}
++
+ /*
+ * In a child there will be only one domain, reference that here.
+ */
+@@ -1301,6 +1361,7 @@ static bool fork_domain_child(struct win
+ struct winbindd_request request;
+ struct winbindd_response response;
+ struct winbindd_domain *primary_domain = NULL;
++ struct child_handler_state ch_state;
+ NTSTATUS status;
+ ssize_t nwritten;
+
+@@ -1322,6 +1383,9 @@ static bool fork_domain_child(struct win
+ state.request = &request;
+ state.response = &response;
+
++ ch_state.child = child;
++ ch_state.cli_state = &state;
++
+ child->pid = sys_fork();
+
+ if (child->pid == -1) {
+@@ -1464,22 +1528,14 @@ static bool fork_domain_child(struct win
+ }
+ }
+
+- while (1) {
++ if (tevent_add_fd(winbind_event_context(), NULL, state.sock,
++ TEVENT_FD_READ, child_handler, &ch_state) == NULL) {
++ DEBUG(1, ("tevent_add_fd failed\n"));
++ exit(1);
++ }
+
+- int ret;
+- struct pollfd *pfds;
+- int num_pfds;
+- int timeout;
+- struct timeval t;
+- struct timeval *tp;
++ while (1) {
+ TALLOC_CTX *frame = talloc_stackframe();
+- struct iovec iov[2];
+- int iov_count;
+-
+- if (run_events_poll(winbind_event_context(), 0, NULL, 0)) {
+- TALLOC_FREE(frame);
+- continue;
+- }
+
+ if (child->domain && child->domain->startup &&
+ (time_mono(NULL) > child->domain->startup_time + 30)) {
+@@ -1489,99 +1545,12 @@ static bool fork_domain_child(struct win
+ child->domain->startup = False;
+ }
+
+- pfds = TALLOC_ZERO_P(talloc_tos(), struct pollfd);
+- if (pfds == NULL) {
+- DEBUG(1, ("talloc failed\n"));
+- _exit(1);
+- }
+-
+- pfds->fd = state.sock;
+- pfds->events = POLLIN|POLLHUP;
+- num_pfds = 1;
+-
+- timeout = INT_MAX;
+-
+- if (!event_add_to_poll_args(
+- winbind_event_context(), talloc_tos(),
+- &pfds, &num_pfds, &timeout)) {
+- DEBUG(1, ("event_add_to_poll_args failed\n"));
+- _exit(1);
+- }
+- tp = get_timed_events_timeout(winbind_event_context(), &t);
+- if (tp) {
+- DEBUG(11,("select will use timeout of %u.%u seconds\n",
+- (unsigned int)tp->tv_sec, (unsigned int)tp->tv_usec ));
+- }
+-
+- ret = sys_poll(pfds, num_pfds, timeout);
+-
+- if (run_events_poll(winbind_event_context(), ret,
+- pfds, num_pfds)) {
+- /* We got a signal - continue. */
+- TALLOC_FREE(frame);
+- continue;
+- }
+-
+- TALLOC_FREE(pfds);
+-
+- if (ret == 0) {
+- DEBUG(11,("nothing is ready yet, continue\n"));
+- TALLOC_FREE(frame);
+- continue;
+- }
+-
+- if (ret == -1 && errno == EINTR) {
+- /* We got a signal - continue. */
+- TALLOC_FREE(frame);
+- continue;
+- }
+-
+- if (ret == -1 && errno != EINTR) {
+- DEBUG(0,("poll error occured\n"));
+- TALLOC_FREE(frame);
+- perror("poll");
++ if (tevent_loop_once(winbind_event_context()) != 0) {
++ DEBUG(1, ("tevent_loop_once failed: %s\n",
++ strerror(errno)));
+ _exit(1);
+ }
+
+- /* fetch a request from the main daemon */
+- status = child_read_request(&state);
+-
+- if (!NT_STATUS_IS_OK(status)) {
+- /* we lost contact with our parent */
+- _exit(0);
+- }
+-
+- DEBUG(4,("child daemon request %d\n", (int)state.request->cmd));
+-
+- ZERO_STRUCTP(state.response);
+- state.request->null_term = '\0';
+- state.mem_ctx = frame;
+- child_process_request(child, &state);
+-
+- DEBUG(4, ("Finished processing child request %d\n",
+- (int)state.request->cmd));
+-
+- SAFE_FREE(state.request->extra_data.data);
+-
+- iov[0].iov_base = (void *)state.response;
+- iov[0].iov_len = sizeof(struct winbindd_response);
+- iov_count = 1;
+-
+- if (state.response->length > sizeof(struct winbindd_response)) {
+- iov[1].iov_base =
+- (void *)state.response->extra_data.data;
+- iov[1].iov_len = state.response->length-iov[0].iov_len;
+- iov_count = 2;
+- }
+-
+- DEBUG(10, ("Writing %d bytes to parent\n",
+- (int)state.response->length));
+-
+- if (write_data_iov(state.sock, iov, iov_count) !=
+- state.response->length) {
+- DEBUG(0, ("Could not write result\n"));
+- exit(1);
+- }
+ TALLOC_FREE(frame);
+ }
+ }