Unfinished patch for winbind overload problem
Volker Lendecke
Volker.Lendecke at SerNet.DE
Wed Feb 14 10:45:24 UTC 2018
Hi!
For your information only: Attached find a patch that completes
b4384b7f0ec with just a single queue. For me it works, but Metze does
not want to extend tevent_queue. So he's working on an alternative
approach. For everybody interested, feel free to pick up this patch in
distros.
Volker
--
Besuchen Sie die verinice.XP 2018 in Berlin,
Anwenderkonferenz für Informationssicherheit
vom 21.-23.03.2018 im Sofitel Kurfürstendamm
Info & Anmeldung hier: http://veriniceXP.org
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
From 2e3852a2333699119b8b05abe26868dd44d2eae4 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 11 Feb 2018 19:49:19 +0100
Subject: [PATCH 1/4] tevent: Add a helper variable
Easier to read for me :-)
Signed-off-by: Volker Lendecke <vl at samba.org>
---
lib/tevent/tevent_queue.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/lib/tevent/tevent_queue.c b/lib/tevent/tevent_queue.c
index 5516c6cb1e5..2f82e28a4f6 100644
--- a/lib/tevent/tevent_queue.c
+++ b/lib/tevent/tevent_queue.c
@@ -136,17 +136,19 @@ static void tevent_queue_immediate_trigger(struct tevent_context *ev,
struct tevent_queue *q =
talloc_get_type_abort(private_data,
struct tevent_queue);
+ struct tevent_queue_entry *e;
if (!q->running) {
return;
}
- if (!q->list) {
+ e = q->list;
+ if (e == NULL) {
return;
}
- q->list->triggered = true;
- q->list->trigger(q->list->req, q->list->private_data);
+ e->triggered = true;
+ e->trigger(e->req, e->private_data);
}
static struct tevent_queue_entry *tevent_queue_add_internal(
--
2.11.0
From 467cba727791d3c33c9c3c21f645e6371682122e Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 11 Feb 2018 19:50:06 +0100
Subject: [PATCH 2/4] tevent: Simplify tevent_queue_add a bit
Easier to read for me :-)
Signed-off-by: Volker Lendecke <vl at samba.org>
---
lib/tevent/tevent_queue.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/lib/tevent/tevent_queue.c b/lib/tevent/tevent_queue.c
index 2f82e28a4f6..d76f4f126d0 100644
--- a/lib/tevent/tevent_queue.c
+++ b/lib/tevent/tevent_queue.c
@@ -239,11 +239,7 @@ bool tevent_queue_add(struct tevent_queue *queue,
e = tevent_queue_add_internal(queue, ev, req,
trigger, private_data, false);
- if (e == NULL) {
- return false;
- }
-
- return true;
+ return (e != NULL);
}
struct tevent_queue_entry *tevent_queue_add_entry(
--
2.11.0
From 7c1f45f29fc8a04c2ca513bd3f4d8c33000109f0 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 11 Feb 2018 19:51:12 +0100
Subject: [PATCH 3/4] tevent: Add tevent_queue_add_retryable_entry
---
lib/tevent/ABI/tevent-0.9.36.sigs | 100 ++++++++++++++++++++++++++++++++++++++
lib/tevent/tevent.h | 38 +++++++++++++++
lib/tevent/tevent_queue.c | 47 ++++++++++++++----
lib/tevent/wscript | 2 +-
4 files changed, 176 insertions(+), 11 deletions(-)
create mode 100644 lib/tevent/ABI/tevent-0.9.36.sigs
diff --git a/lib/tevent/ABI/tevent-0.9.36.sigs b/lib/tevent/ABI/tevent-0.9.36.sigs
new file mode 100644
index 00000000000..916d80e86e7
--- /dev/null
+++ b/lib/tevent/ABI/tevent-0.9.36.sigs
@@ -0,0 +1,100 @@
+_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
+_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
+_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
+_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *)
+_tevent_loop_once: int (struct tevent_context *, const char *)
+_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *)
+_tevent_loop_wait: int (struct tevent_context *, const char *)
+_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *)
+_tevent_req_callback_data: void *(struct tevent_req *)
+_tevent_req_cancel: bool (struct tevent_req *, const char *)
+_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *)
+_tevent_req_data: void *(struct tevent_req *)
+_tevent_req_done: void (struct tevent_req *, const char *)
+_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *)
+_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *)
+_tevent_req_notify_callback: void (struct tevent_req *, const char *)
+_tevent_req_oom: void (struct tevent_req *, const char *)
+_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
+_tevent_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *)
+tevent_backend_list: const char **(TALLOC_CTX *)
+tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *)
+tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
+tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
+tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
+tevent_common_add_timer_v2: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
+tevent_common_check_signal: int (struct tevent_context *)
+tevent_common_context_destructor: int (struct tevent_context *)
+tevent_common_fd_destructor: int (struct tevent_fd *)
+tevent_common_fd_get_flags: uint16_t (struct tevent_fd *)
+tevent_common_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
+tevent_common_fd_set_flags: void (struct tevent_fd *, uint16_t)
+tevent_common_have_events: bool (struct tevent_context *)
+tevent_common_loop_immediate: bool (struct tevent_context *)
+tevent_common_loop_timer_delay: struct timeval (struct tevent_context *)
+tevent_common_loop_wait: int (struct tevent_context *, const char *)
+tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
+tevent_common_threaded_activate_immediate: void (struct tevent_context *)
+tevent_common_wakeup: int (struct tevent_context *)
+tevent_common_wakeup_fd: int (int)
+tevent_common_wakeup_init: int (struct tevent_context *)
+tevent_context_init: struct tevent_context *(TALLOC_CTX *)
+tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *)
+tevent_context_init_ops: struct tevent_context *(TALLOC_CTX *, const struct tevent_ops *, void *)
+tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...)
+tevent_fd_get_flags: uint16_t (struct tevent_fd *)
+tevent_fd_set_auto_close: void (struct tevent_fd *)
+tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
+tevent_fd_set_flags: void (struct tevent_fd *, uint16_t)
+tevent_get_trace_callback: void (struct tevent_context *, tevent_trace_callback_t *, void *)
+tevent_loop_allow_nesting: void (struct tevent_context *)
+tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *)
+tevent_num_signals: size_t (void)
+tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
+tevent_queue_add_entry: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
+tevent_queue_add_optimize_empty: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
+tevent_queue_add_retryable_entry: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_retryable_trigger_fn_t, void *)
+tevent_queue_length: size_t (struct tevent_queue *)
+tevent_queue_running: bool (struct tevent_queue *)
+tevent_queue_start: void (struct tevent_queue *)
+tevent_queue_stop: void (struct tevent_queue *)
+tevent_queue_wait_recv: bool (struct tevent_req *)
+tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct tevent_queue *)
+tevent_re_initialise: int (struct tevent_context *)
+tevent_register_backend: bool (const char *, const struct tevent_ops *)
+tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *)
+tevent_req_defer_callback: void (struct tevent_req *, struct tevent_context *)
+tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *)
+tevent_req_is_in_progress: bool (struct tevent_req *)
+tevent_req_poll: bool (struct tevent_req *, struct tevent_context *)
+tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *)
+tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *)
+tevent_req_received: void (struct tevent_req *)
+tevent_req_reset_endtime: void (struct tevent_req *)
+tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *)
+tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn)
+tevent_req_set_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_fn)
+tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval)
+tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn)
+tevent_sa_info_queue_count: size_t (void)
+tevent_set_abort_fn: void (void (*)(const char *))
+tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *)
+tevent_set_debug_stderr: int (struct tevent_context *)
+tevent_set_default_backend: void (const char *)
+tevent_set_trace_callback: void (struct tevent_context *, tevent_trace_callback_t, void *)
+tevent_signal_support: bool (struct tevent_context *)
+tevent_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *)
+tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *)
+tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, struct tevent_context *)
+tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t)
+tevent_timeval_compare: int (const struct timeval *, const struct timeval *)
+tevent_timeval_current: struct timeval (void)
+tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t)
+tevent_timeval_is_zero: bool (const struct timeval *)
+tevent_timeval_set: struct timeval (uint32_t, uint32_t)
+tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *)
+tevent_timeval_zero: struct timeval (void)
+tevent_trace_point_callback: void (struct tevent_context *, enum tevent_trace_point)
+tevent_update_timer: void (struct tevent_timer *, struct timeval)
+tevent_wakeup_recv: bool (struct tevent_req *)
+tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval)
diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h
index 7284a8559d2..23756e63777 100644
--- a/lib/tevent/tevent.h
+++ b/lib/tevent/tevent.h
@@ -1541,6 +1541,8 @@ struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx,
*/
typedef void (*tevent_queue_trigger_fn_t)(struct tevent_req *req,
void *private_data);
+typedef bool (*tevent_queue_retryable_trigger_fn_t)(struct tevent_req *req,
+ void *private_data);
/**
* @brief Add a tevent request to the queue.
@@ -1601,6 +1603,42 @@ struct tevent_queue_entry *tevent_queue_add_entry(
void *private_data);
/**
+ * @brief Add a tevent request to the queue.
+ *
+ * The request can be removed from the queue by calling talloc_free()
+ * (or a similar function) on the returned queue entry. This
+ * is the only difference to tevent_queue_add().
+ *
+ * @param[in] queue The queue to add the request.
+ *
+ * @param[in] ev The event handle to use for the request.
+ *
+ * @param[in] req The tevent request to add to the queue.
+ *
+ * @param[in] trigger The function triggered by the queue when the request
+ * is called. Since tevent 0.9.14 it's possible to
+ * pass NULL, in order to just add a "blocker" to the
+ * queue. If the trigger returns false, the queue will
+ * implicitly stopped. Upon restart, the request that
+ * failed will be re-triggered.
+ *
+ * @param[in] private_data The private data passed to the trigger function.
+ *
+ * @return a pointer to the tevent_queue_entry if the request
+ * has been successfully added, NULL otherwise.
+ *
+ * @see tevent_queue_add()
+ * @see tevent_queue_add_optimize_empty()
+ */
+
+struct tevent_queue_entry *tevent_queue_add_retryable_entry(
+ struct tevent_queue *queue,
+ struct tevent_context *ev,
+ struct tevent_req *req,
+ tevent_queue_retryable_trigger_fn_t trigger,
+ void *private_data);
+
+/**
* @brief Add a tevent request to the queue using a possible optimization.
*
* This tries to optimize for the empty queue case and may calls
diff --git a/lib/tevent/tevent_queue.c b/lib/tevent/tevent_queue.c
index d76f4f126d0..1a1729d94ae 100644
--- a/lib/tevent/tevent_queue.c
+++ b/lib/tevent/tevent_queue.c
@@ -37,6 +37,7 @@ struct tevent_queue_entry {
struct tevent_context *ev;
tevent_queue_trigger_fn_t trigger;
+ tevent_queue_retryable_trigger_fn_t retryable_trigger;
void *private_data;
};
@@ -147,17 +148,31 @@ static void tevent_queue_immediate_trigger(struct tevent_context *ev,
return;
}
+ if (e->retryable_trigger != NULL) {
+ bool ok;
+
+ e->triggered = true;
+ ok = e->retryable_trigger(e->req, e->private_data);
+ if (ok) {
+ return;
+ }
+ e->triggered = false;
+ tevent_queue_stop(q);
+ return;
+ }
+
e->triggered = true;
e->trigger(e->req, e->private_data);
}
static struct tevent_queue_entry *tevent_queue_add_internal(
- struct tevent_queue *queue,
- struct tevent_context *ev,
- struct tevent_req *req,
- tevent_queue_trigger_fn_t trigger,
- void *private_data,
- bool allow_direct)
+ struct tevent_queue *queue,
+ struct tevent_context *ev,
+ struct tevent_req *req,
+ tevent_queue_trigger_fn_t trigger,
+ tevent_queue_retryable_trigger_fn_t retryable_trigger,
+ void *private_data,
+ bool allow_direct)
{
struct tevent_queue_entry *e;
@@ -170,12 +185,13 @@ static struct tevent_queue_entry *tevent_queue_add_internal(
e->req = req;
e->ev = ev;
e->trigger = trigger;
+ e->retryable_trigger = retryable_trigger;
e->private_data = private_data;
/*
* if there is no trigger, it is just a blocker
*/
- if (trigger == NULL) {
+ if ((trigger == NULL) && (retryable_trigger == NULL)) {
e->triggered = true;
}
@@ -238,7 +254,7 @@ bool tevent_queue_add(struct tevent_queue *queue,
struct tevent_queue_entry *e;
e = tevent_queue_add_internal(queue, ev, req,
- trigger, private_data, false);
+ trigger, NULL, private_data, false);
return (e != NULL);
}
@@ -250,7 +266,7 @@ struct tevent_queue_entry *tevent_queue_add_entry(
void *private_data)
{
return tevent_queue_add_internal(queue, ev, req,
- trigger, private_data, false);
+ trigger, NULL, private_data, false);
}
struct tevent_queue_entry *tevent_queue_add_optimize_empty(
@@ -261,7 +277,18 @@ struct tevent_queue_entry *tevent_queue_add_optimize_empty(
void *private_data)
{
return tevent_queue_add_internal(queue, ev, req,
- trigger, private_data, true);
+ trigger, NULL, private_data, true);
+}
+
+struct tevent_queue_entry *tevent_queue_add_retryable_entry(
+ struct tevent_queue *queue,
+ struct tevent_context *ev,
+ struct tevent_req *req,
+ tevent_queue_retryable_trigger_fn_t trigger,
+ void *private_data)
+{
+ return tevent_queue_add_internal(queue, ev, req, NULL,
+ trigger, private_data, false);
}
void tevent_queue_start(struct tevent_queue *queue)
diff --git a/lib/tevent/wscript b/lib/tevent/wscript
index 2c67f1f57ee..94d190f3b60 100644
--- a/lib/tevent/wscript
+++ b/lib/tevent/wscript
@@ -1,7 +1,7 @@
#!/usr/bin/env python
APPNAME = 'tevent'
-VERSION = '0.9.35'
+VERSION = '0.9.36'
blddir = 'bin'
--
2.11.0
From 6f46a85def62b710e3808f71ec0053c4da2b871b Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 13 Feb 2018 16:04:44 +0100
Subject: [PATCH 4/4] winbind: Use one queue for all domain children
---
source3/winbindd/winbindd.h | 3 ++
source3/winbindd/winbindd_dual.c | 71 +++++++++++++++++++++++++++++-------
source3/winbindd/winbindd_dual_ndr.c | 58 ++++++++++++++++++++++++++---
source3/winbindd/winbindd_util.c | 12 ++++++
4 files changed, 125 insertions(+), 19 deletions(-)
diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h
index 3e4b256ef32..081722f6a90 100644
--- a/source3/winbindd/winbindd.h
+++ b/source3/winbindd/winbindd.h
@@ -184,6 +184,9 @@ struct winbindd_domain {
struct winbindd_child *children;
+ struct tevent_queue *queue;
+ struct dcerpc_binding_handle *binding_handle;
+
/* Callback we use to try put us back online. */
uint32_t check_online_timeout;
diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c
index 7fb5aa899e4..b7b409da10e 100644
--- a/source3/winbindd/winbindd_dual.c
+++ b/source3/winbindd/winbindd_dual.c
@@ -277,14 +277,12 @@ struct winbindd_child *choose_domain_child(struct winbindd_domain *domain)
struct dcerpc_binding_handle *dom_child_handle(struct winbindd_domain *domain)
{
- struct winbindd_child *child;
-
- child = choose_domain_child(domain);
- return child->binding_handle;
+ return domain->binding_handle;
}
struct wb_domain_request_state {
struct tevent_context *ev;
+ struct tevent_queue_entry *queue_entry;
struct winbindd_domain *domain;
struct winbindd_child *child;
struct winbindd_request *request;
@@ -292,6 +290,8 @@ struct wb_domain_request_state {
struct winbindd_response *response;
};
+static bool wb_domain_request_trigger(struct tevent_req *req,
+ void *private_data);
static void wb_domain_request_gotdc(struct tevent_req *subreq);
static void wb_domain_request_initialized(struct tevent_req *subreq);
static void wb_domain_request_done(struct tevent_req *subreq);
@@ -310,21 +310,21 @@ struct tevent_req *wb_domain_request_send(TALLOC_CTX *mem_ctx,
return NULL;
}
- state->child = choose_domain_child(domain);
+ state->domain = domain;
+ state->ev = ev;
+ state->request = request;
if (domain->initialized) {
- subreq = wb_child_request_send(state, ev, state->child,
- request);
- if (tevent_req_nomem(subreq, req)) {
+ state->queue_entry = tevent_queue_add_retryable_entry(
+ domain->queue, ev, req, wb_domain_request_trigger,
+ NULL);
+ if (tevent_req_nomem(state->queue_entry, req)) {
return tevent_req_post(req, ev);
}
- tevent_req_set_callback(subreq, wb_domain_request_done, req);
return req;
}
- state->domain = domain;
- state->ev = ev;
- state->request = request;
+ state->child = choose_domain_child(domain);
state->init_req = talloc_zero(state, struct winbindd_request);
if (tevent_req_nomem(state->init_req, req)) {
@@ -359,7 +359,7 @@ struct tevent_req *wb_domain_request_send(TALLOC_CTX *mem_ctx,
state->init_req->cmd = WINBINDD_GETDCNAME;
fstrcpy(state->init_req->domain_name, domain->name);
- subreq = wb_child_request_send(state, ev, state->child, request);
+ subreq = wb_child_request_send(state, ev, state->child, state->request);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
@@ -367,6 +367,45 @@ struct tevent_req *wb_domain_request_send(TALLOC_CTX *mem_ctx,
return req;
}
+static bool wb_domain_request_trigger(struct tevent_req *req,
+ void *private_data)
+{
+ struct wb_domain_request_state *state = tevent_req_data(
+ req, struct wb_domain_request_state);
+ struct winbindd_domain *domain = state->domain;
+ struct winbindd_child *child = NULL;
+ struct tevent_req *subreq;
+ int i;
+
+ for (i=0; i<lp_winbind_max_domain_connections(); i++) {
+ struct winbindd_child *c = &domain->children[i];
+
+ if (tevent_queue_length(c->queue) == 0) {
+ child = c;
+ break;
+ }
+ }
+
+ if (child == NULL) {
+ return false;
+ }
+
+ subreq = wb_child_request_send(state, state->ev, child,
+ state->request);
+ if (tevent_req_nomem(subreq, req)) {
+ /* "true" means trigger was okay, try the next one */
+ return true;
+ }
+ tevent_req_set_callback(subreq, wb_domain_request_done, req);
+
+ /*
+ * Trigger the next entry, there might be more children idle
+ */
+ TALLOC_FREE(state->queue_entry);
+
+ return true;
+}
+
static void wb_domain_request_gotdc(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(
@@ -462,6 +501,7 @@ static void wb_domain_request_done(struct tevent_req *subreq)
subreq, struct tevent_req);
struct wb_domain_request_state *state = tevent_req_data(
req, struct wb_domain_request_state);
+ struct tevent_queue *queue = state->domain->queue;
int ret, err;
ret = wb_child_request_recv(subreq, talloc_tos(), &state->response,
@@ -472,6 +512,11 @@ static void wb_domain_request_done(struct tevent_req *subreq)
return;
}
tevent_req_done(req);
+
+ /*
+ * We just freed up a child. Trigger the domain queue
+ */
+ tevent_queue_start(queue);
}
int wb_domain_request_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
diff --git a/source3/winbindd/winbindd_dual_ndr.c b/source3/winbindd/winbindd_dual_ndr.c
index 00c7df1f863..479dec41bd4 100644
--- a/source3/winbindd/winbindd_dual_ndr.c
+++ b/source3/winbindd/winbindd_dual_ndr.c
@@ -42,7 +42,7 @@ static bool wbint_bh_is_connected(struct dcerpc_binding_handle *h)
struct wbint_bh_state *hs = dcerpc_binding_handle_data(h,
struct wbint_bh_state);
- if (!hs->child) {
+ if ((hs->domain == NULL) && (hs->child == NULL)) {
return false;
}
@@ -65,7 +65,8 @@ struct wbint_bh_raw_call_state {
DATA_BLOB out_data;
};
-static void wbint_bh_raw_call_done(struct tevent_req *subreq);
+static void wbint_bh_raw_call_child_done(struct tevent_req *subreq);
+static void wbint_bh_raw_call_domain_done(struct tevent_req *subreq);
static struct tevent_req *wbint_bh_raw_call_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
@@ -114,17 +115,28 @@ static struct tevent_req *wbint_bh_raw_call_send(TALLOC_CTX *mem_ctx,
state->request.extra_data.data = (char *)state->in_data.data;
state->request.extra_len = state->in_data.length;
- subreq = wb_child_request_send(state, ev, hs->child,
- &state->request);
+ if (hs->child != NULL) {
+ subreq = wb_child_request_send(state, ev, hs->child,
+ &state->request);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(
+ subreq, wbint_bh_raw_call_child_done, req);
+ return req;
+ }
+
+ subreq = wb_domain_request_send(state, ev, hs->domain,
+ &state->request);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
- tevent_req_set_callback(subreq, wbint_bh_raw_call_done, req);
+ tevent_req_set_callback(subreq, wbint_bh_raw_call_domain_done, req);
return req;
}
-static void wbint_bh_raw_call_done(struct tevent_req *subreq)
+static void wbint_bh_raw_call_child_done(struct tevent_req *subreq)
{
struct tevent_req *req =
tevent_req_callback_data(subreq,
@@ -158,6 +170,40 @@ static void wbint_bh_raw_call_done(struct tevent_req *subreq)
tevent_req_done(req);
}
+static void wbint_bh_raw_call_domain_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct wbint_bh_raw_call_state *state =
+ tevent_req_data(req,
+ struct wbint_bh_raw_call_state);
+ int ret, err;
+
+ ret = wb_domain_request_recv(subreq, state, &state->response, &err);
+ TALLOC_FREE(subreq);
+ if (ret == -1) {
+ NTSTATUS status = map_nt_error_from_unix(err);
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ state->out_data = data_blob_talloc(state,
+ state->response->extra_data.data,
+ state->response->length - sizeof(struct winbindd_response));
+ if (state->response->extra_data.data && !state->out_data.data) {
+ tevent_req_oom(req);
+ return;
+ }
+
+ if (state->domain != NULL) {
+ wcache_store_ndr(state->domain, state->opnum,
+ &state->in_data, &state->out_data);
+ }
+
+ tevent_req_done(req);
+}
+
static NTSTATUS wbint_bh_raw_call_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
uint8_t **out_data,
diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 6292cce9d51..1cd6fd72870 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -228,6 +228,18 @@ static NTSTATUS add_trusted_domain(const char *domain_name,
return NT_STATUS_NO_MEMORY;
}
+ domain->queue = tevent_queue_create(domain, "winbind_domain");
+ if (domain->queue == NULL) {
+ TALLOC_FREE(domain);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ domain->binding_handle = wbint_binding_handle(domain, domain, NULL);
+ if (domain->binding_handle == NULL) {
+ TALLOC_FREE(domain);
+ return NT_STATUS_NO_MEMORY;
+ }
+
domain->name = talloc_strdup(domain, domain_name);
if (domain->name == NULL) {
TALLOC_FREE(domain);
--
2.11.0
More information about the samba-technical
mailing list