[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Fri Feb 23 08:05:04 UTC 2018


The branch, master has been updated
       via  7f2d45a winbind: Use one queue for all domain children
       via  b518cb0 winbind: Maintain a binding handle per domain and always go via wb_domain_request_send()
       via  5116aff winbind: make choose_domain_child() static
       via  44ebaaa winbind: add locator_child_handle() and use it instead of child->binding_handle
       via  c2d78a0 winbind: add idmap_child_handle() and use it instead of child->binding_handle
       via  1f41193 winbind: improve wb_domain_request_send() to use wb_dsgetdcname_send() for a foreign domain
       via  4d804f5 winbind: use state->{ev,request} in wb_domain_request_send()
       via  d73e3d4 winbind: avoid using fstrcpy(dcname,...) in _dual_init_connection
       via  b158d4e winbind: cleanup winbindd_cli_state->pwent_state if winbindd_getpwent_recv() returns an error
       via  b7789da winbind: cleanup winbindd_cli_state->grent_state if winbindd_getgrent_recv() returns an error
       via  6548b82 winbind: call lp_winbind_enum_{users,groups}() already in set{pw,gr}ent()
       via  43af57d winbind: protect a pending wb_child_request against a talloc_free()
       via  d29dda1 winbind: use tevent_queue_wait_send/recv in wb_child_request_*()
       via  f00c7cf tevent: version 0.9.36
       via  5c6f316 tevent: add tevent_queue_entry_untrigger()
       via  88d6703 tevent: improve documentation of tevent_queue_add_optimize_empty()
      from  5776222 s4:auth_sam: allow logons with an empty domain name

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 7f2d45a6c2a88dd8833fc66d314ec21507dd52c3
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Feb 14 15:04:01 2018 +0100

    winbind: Use one queue for all domain children
    
    If we have multiple domain children, it's important
    that the first idle child takes over the next waiting request.
    
    Before we had the problem that a request could get stuck in the
    queue of a busy child, while later requests could get served fine by
    other children.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13292
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    
    Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
    Autobuild-Date(master): Fri Feb 23 09:04:23 CET 2018 on sn-devel-144

commit b518cb0597d269002105644302c58ca8f9f0f717
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Feb 13 16:04:44 2018 +0100

    winbind: Maintain a binding handle per domain and always go via wb_domain_request_send()
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13292
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Signed-off-by: Volker Lendecke <vl at samba.org>

commit 5116aff286bdffe4abc9ddda09cf64ab999fd13e
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Feb 20 14:43:38 2018 +0100

    winbind: make choose_domain_child() static
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13292
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>

commit 44ebaaac8933f5fc16a043b8c15a9449746af47b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Feb 14 13:24:54 2018 +0100

    winbind: add locator_child_handle() and use it instead of child->binding_handle
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13292
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>

commit c2d78a0a0a3f9b9ade61cf707f23e59a1a16c61b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Feb 14 13:24:54 2018 +0100

    winbind: add idmap_child_handle() and use it instead of child->binding_handle
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13292
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>

commit 1f41193e005df37401a28004f0a95d4d73b98ccd
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Feb 14 15:11:50 2018 +0100

    winbind: improve wb_domain_request_send() to use wb_dsgetdcname_send() for a foreign domain
    
    Commit ed3bc614cccec6167c64ac58d78344b6426cd019 got the logic wrong while
    trying to implement the logic we had in init_child_connection(),
    which was removed by commit d61f3626b79e0523beadff355453145aa7b0195c.
    
    Instead of doing a WINBINDD_GETDCNAME request (which would caused an error
    because the implementation was removed in commit
    958fdaf5c3ba17969a5110e6b2b08babb9096d7e), we sent the callers request
    and interpreted the result as WINBINDD_GETDCNAME response, which
    led to an empty dcname variable. As result the domain child
    opened a connection to the primary domain in order to lookup
    a dc.
    
    If we want to connect the primary domain from the parent via
    a domain child of the primary domain.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13295
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>

commit 4d804f5f3e65df0e2f646d4f88793cab8e2f32d1
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Feb 14 15:09:51 2018 +0100

    winbind: use state->{ev,request} in wb_domain_request_send()
    
    This will reduce the diff for the following changes.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13295
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>

commit d73e3d451976e692c6c346f98547d7123f7b9006
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 15 16:00:33 2018 +0100

    winbind: avoid using fstrcpy(dcname,...) in _dual_init_connection
    
    domain->dcname was converted from fstring to char * by commit
    14bae61ba36814ea5eca7c51cf1cc039e9e6803f.
    
    Luckily this was only ever called with an empty string in
    state->request->data.init_conn.dcname.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13294
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>

commit b158d4e4c1c3fee0a8884bc5e8f0c5a5ce49687f
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 16 16:13:16 2018 +0100

    winbind: cleanup winbindd_cli_state->pwent_state if winbindd_getpwent_recv() returns an error
    
    A client may skip the explicit endpwent() if getgrent() fails.
    
    This allows client_is_idle() return true in more cases.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13293
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>

commit b7789da8468c3f070727011639d5f74aca76cb59
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 16 16:13:16 2018 +0100

    winbind: cleanup winbindd_cli_state->grent_state if winbindd_getgrent_recv() returns an error
    
    A client may skip the explicit endgrent() if getgrent() fails.
    
    This allows client_is_idle() return true in more cases.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13293
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>

commit 6548b82b5c1ed30ce14e17e4ba9d4bc24ab49c42
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 16 16:09:58 2018 +0100

    winbind: call lp_winbind_enum_{users,groups}() already in set{pw,gr}ent()
    
    This way we don't keep winbindd_cli_state->{pw,gr}ent_state arround forever,
    if the client forgets an explicit end{pw,gr}ent().
    
    This allows client_is_idle() return true in more cases.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13293
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>

commit 43af57d8728883c5ddbe169e1483181246fb68a8
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 16 15:05:57 2018 +0100

    winbind: protect a pending wb_child_request against a talloc_free()
    
    If the (winbind) client gave up we call TALLOC_FREE(state->mem_ctx)
    in remove_client(). This triggers a recursive talloc_free() for all
    in flight requests.
    
    In order to maintain the winbindd parent-child protocol, we need
    to keep the orphaned wb_simple_trans request until the parent
    got the response from the child.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13290
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>

commit d29dda141e08af42c535e8718226f95c45aadab8
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 16 15:02:42 2018 +0100

    winbind: use tevent_queue_wait_send/recv in wb_child_request_*()
    
    We need a way to keep the child->queue blocked without relying on
    the current 'req' (wb_child_request_state).
    
    The next commit will make use of this.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13290
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>

commit f00c7cf9f5f325de0b754b127fcc0f07bea2d825
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Feb 20 13:54:49 2018 +0100

    tevent: version 0.9.36
    
    * improve documentation of tevent_queue_add_optimize_empty()
    * add tevent_queue_entry_untrigger()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>

commit 5c6f31697a8edb03d36eece5c79581b952743b5b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 15 14:47:25 2018 +0100

    tevent: add tevent_queue_entry_untrigger()
    
    Pair-Programmed-With: Volker Lendecke <vl at samba.org>
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Signed-off-by: Volker Lendecke <vl at samba.org>

commit 88d6703b89f9a7f847b6ec47d97569432927dcff
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 16 16:47:57 2018 +0100

    tevent: improve documentation of tevent_queue_add_optimize_empty()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 .../ABI/{tevent-0.9.34.sigs => tevent-0.9.36.sigs} |   1 +
 lib/tevent/tevent.h                                |  25 ++
 lib/tevent/tevent_queue.c                          |  13 ++
 lib/tevent/wscript                                 |   2 +-
 source3/winbindd/wb_dsgetdcname.c                  |   8 +-
 source3/winbindd/wb_sids2xids.c                    |   6 +-
 source3/winbindd/winbindd.h                        |   3 +
 source3/winbindd/winbindd_allocate_gid.c           |   6 +-
 source3/winbindd/winbindd_allocate_uid.c           |   6 +-
 source3/winbindd/winbindd_dsgetdcname.c            |   6 +-
 source3/winbindd/winbindd_dual.c                   | 251 +++++++++++++++++----
 source3/winbindd/winbindd_dual_ndr.c               |  61 ++++-
 source3/winbindd/winbindd_getgrent.c               |   9 +-
 source3/winbindd/winbindd_getpwent.c               |   6 +-
 source3/winbindd/winbindd_idmap.c                  |   5 +
 source3/winbindd/winbindd_locator.c                |   5 +
 source3/winbindd/winbindd_proto.h                  |   3 +-
 source3/winbindd/winbindd_setgrent.c               |   5 +
 source3/winbindd/winbindd_setpwent.c               |   5 +
 source3/winbindd/winbindd_util.c                   |  19 +-
 20 files changed, 361 insertions(+), 84 deletions(-)
 copy lib/tevent/ABI/{tevent-0.9.34.sigs => tevent-0.9.36.sigs} (99%)


Changeset truncated at 500 lines:

diff --git a/lib/tevent/ABI/tevent-0.9.34.sigs b/lib/tevent/ABI/tevent-0.9.36.sigs
similarity index 99%
copy from lib/tevent/ABI/tevent-0.9.34.sigs
copy to lib/tevent/ABI/tevent-0.9.36.sigs
index 7a6a236..8a579c8 100644
--- a/lib/tevent/ABI/tevent-0.9.34.sigs
+++ b/lib/tevent/ABI/tevent-0.9.36.sigs
@@ -53,6 +53,7 @@ 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_entry_untrigger: void (struct tevent_queue_entry *)
 tevent_queue_length: size_t (struct tevent_queue *)
 tevent_queue_running: bool (struct tevent_queue *)
 tevent_queue_start: void (struct tevent_queue *)
diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h
index 7284a85..7bb9c61 100644
--- a/lib/tevent/tevent.h
+++ b/lib/tevent/tevent.h
@@ -1611,6 +1611,9 @@ struct tevent_queue_entry *tevent_queue_add_entry(
  * already called tevent_req_notify_callback(), tevent_req_error(),
  * tevent_req_done() or a similar function.
  *
+ * The trigger function has no chance to see the returned
+ * queue_entry in the optimized case.
+ *
  * The request can be removed from the queue by calling talloc_free()
  * (or a similar function) on the returned queue entry.
  *
@@ -1641,6 +1644,28 @@ struct tevent_queue_entry *tevent_queue_add_optimize_empty(
 					void *private_data);
 
 /**
+ * @brief Untrigger an already triggered queue entry.
+ *
+ * If a trigger function detects that it needs to remain
+ * in the queue, it needs to call tevent_queue_stop()
+ * followed by tevent_queue_entry_untrigger().
+ *
+ * @note In order to call tevent_queue_entry_untrigger()
+ * the queue must be already stopped and the given queue_entry
+ * must be the first one in the queue! Otherwise it calls abort().
+ *
+ * @note You can't use this together with tevent_queue_add_optimize_empty()
+ * because the trigger function don't have access to the quene entry
+ * in the case of an empty queue.
+ *
+ * @param[in]  queue_entry The queue entry to rearm.
+ *
+ * @see tevent_queue_add_entry()
+ * @see tevent_queue_stop()
+ */
+void tevent_queue_entry_untrigger(struct tevent_queue_entry *entry);
+
+/**
  * @brief Start a tevent queue.
  *
  * The queue is started by default.
diff --git a/lib/tevent/tevent_queue.c b/lib/tevent/tevent_queue.c
index 5516c6c..9c3973b 100644
--- a/lib/tevent/tevent_queue.c
+++ b/lib/tevent/tevent_queue.c
@@ -266,6 +266,19 @@ struct tevent_queue_entry *tevent_queue_add_optimize_empty(
 					 trigger, private_data, true);
 }
 
+void tevent_queue_entry_untrigger(struct tevent_queue_entry *entry)
+{
+	if (entry->queue->running) {
+		abort();
+	}
+
+	if (entry->queue->list != entry) {
+		abort();
+	}
+
+	entry->triggered = false;
+}
+
 void tevent_queue_start(struct tevent_queue *queue)
 {
 	if (queue->running) {
diff --git a/lib/tevent/wscript b/lib/tevent/wscript
index 2c67f1f..94d190f 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'
 
diff --git a/source3/winbindd/wb_dsgetdcname.c b/source3/winbindd/wb_dsgetdcname.c
index 8bd7419..2f450c7 100644
--- a/source3/winbindd/wb_dsgetdcname.c
+++ b/source3/winbindd/wb_dsgetdcname.c
@@ -37,7 +37,7 @@ struct tevent_req *wb_dsgetdcname_send(TALLOC_CTX *mem_ctx,
 {
 	struct tevent_req *req, *subreq;
 	struct wb_dsgetdcname_state *state;
-	struct winbindd_child *child;
+	struct dcerpc_binding_handle *child_binding_handle = NULL;
 	struct GUID guid;
 	struct GUID *guid_ptr = NULL;
 
@@ -72,10 +72,10 @@ struct tevent_req *wb_dsgetdcname_send(TALLOC_CTX *mem_ctx,
 		/*
 		 * We have to figure out the DC ourselves
 		 */
-		child = locator_child();
+		child_binding_handle = locator_child_handle();
 	} else {
 		struct winbindd_domain *domain = find_our_domain();
-		child = choose_domain_child(domain);
+		child_binding_handle = dom_child_handle(domain);
 	}
 
 	if (domain_guid != NULL) {
@@ -85,7 +85,7 @@ struct tevent_req *wb_dsgetdcname_send(TALLOC_CTX *mem_ctx,
 	}
 
 	subreq = dcerpc_wbint_DsGetDcName_send(
-		state, ev, child->binding_handle, domain_name, guid_ptr, site_name,
+		state, ev, child_binding_handle, domain_name, guid_ptr, site_name,
 		flags, &state->dcinfo);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c
index b8ad300..c687f70 100644
--- a/source3/winbindd/wb_sids2xids.c
+++ b/source3/winbindd/wb_sids2xids.c
@@ -167,7 +167,7 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq)
 		req, struct wb_sids2xids_state);
 	struct lsa_RefDomainList *domains = NULL;
 	struct lsa_TransNameArray *names = NULL;
-	struct winbindd_child *child;
+	struct dcerpc_binding_handle *child_binding_handle = NULL;
 	NTSTATUS status;
 	int i;
 
@@ -237,7 +237,7 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq)
 	TALLOC_FREE(names);
 	TALLOC_FREE(domains);
 
-	child = idmap_child();
+	child_binding_handle = idmap_child_handle();
 
 	state->dom_ids = wb_sids2xids_extract_for_domain_index(
 		state, &state->ids, state->dom_index);
@@ -252,7 +252,7 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq)
 	};
 
 	subreq = dcerpc_wbint_Sids2UnixIDs_send(
-		state, state->ev, child->binding_handle, &state->idmap_dom,
+		state, state->ev, child_binding_handle, &state->idmap_dom,
 		state->dom_ids);
 	if (tevent_req_nomem(subreq, req)) {
 		return;
diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h
index 3e4b256..081722f 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_allocate_gid.c b/source3/winbindd/winbindd_allocate_gid.c
index a9236bb..85aa136 100644
--- a/source3/winbindd/winbindd_allocate_gid.c
+++ b/source3/winbindd/winbindd_allocate_gid.c
@@ -34,7 +34,7 @@ struct tevent_req *winbindd_allocate_gid_send(TALLOC_CTX *mem_ctx,
 {
 	struct tevent_req *req, *subreq;
 	struct winbindd_allocate_gid_state *state;
-	struct winbindd_child *child;
+	struct dcerpc_binding_handle *child_binding_handle = NULL;
 
 	req = tevent_req_create(mem_ctx, &state,
 				struct winbindd_allocate_gid_state);
@@ -44,9 +44,9 @@ struct tevent_req *winbindd_allocate_gid_send(TALLOC_CTX *mem_ctx,
 
 	DEBUG(3, ("allocate_gid\n"));
 
-	child = idmap_child();
+	child_binding_handle = idmap_child_handle();
 
-	subreq = dcerpc_wbint_AllocateGid_send(state, ev, child->binding_handle,
+	subreq = dcerpc_wbint_AllocateGid_send(state, ev, child_binding_handle,
 					       &state->gid);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
diff --git a/source3/winbindd/winbindd_allocate_uid.c b/source3/winbindd/winbindd_allocate_uid.c
index 99c0bda..69ce61c 100644
--- a/source3/winbindd/winbindd_allocate_uid.c
+++ b/source3/winbindd/winbindd_allocate_uid.c
@@ -34,7 +34,7 @@ struct tevent_req *winbindd_allocate_uid_send(TALLOC_CTX *mem_ctx,
 {
 	struct tevent_req *req, *subreq;
 	struct winbindd_allocate_uid_state *state;
-	struct winbindd_child *child;
+	struct dcerpc_binding_handle *child_binding_handle = NULL;
 
 	req = tevent_req_create(mem_ctx, &state,
 				struct winbindd_allocate_uid_state);
@@ -44,9 +44,9 @@ struct tevent_req *winbindd_allocate_uid_send(TALLOC_CTX *mem_ctx,
 
 	DEBUG(3, ("allocate_uid\n"));
 
-	child = idmap_child();
+	child_binding_handle = idmap_child_handle();
 
-	subreq = dcerpc_wbint_AllocateUid_send(state, ev, child->binding_handle,
+	subreq = dcerpc_wbint_AllocateUid_send(state, ev, child_binding_handle,
 					       &state->uid);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
diff --git a/source3/winbindd/winbindd_dsgetdcname.c b/source3/winbindd/winbindd_dsgetdcname.c
index 8eb1de7..fd9270f 100644
--- a/source3/winbindd/winbindd_dsgetdcname.c
+++ b/source3/winbindd/winbindd_dsgetdcname.c
@@ -35,7 +35,7 @@ struct tevent_req *winbindd_dsgetdcname_send(TALLOC_CTX *mem_ctx,
 					     struct winbindd_request *request)
 {
 	struct tevent_req *req, *subreq;
-	struct winbindd_child *child;
+	struct dcerpc_binding_handle *child_binding_handle = NULL;
 	struct winbindd_dsgetdcname_state *state;
 	struct GUID *guid_ptr = NULL;
 	uint32_t ds_flags = 0;
@@ -65,10 +65,10 @@ struct tevent_req *winbindd_dsgetdcname_send(TALLOC_CTX *mem_ctx,
 		guid_ptr = &state->guid;
 	}
 
-	child = locator_child();
+	child_binding_handle = locator_child_handle();
 
 	subreq = dcerpc_wbint_DsGetDcName_send(
-		state, ev, child->binding_handle,
+		state, ev, child_binding_handle,
 		request->data.dsgetdcname.domain_name, guid_ptr,
 		request->data.dsgetdcname.site_name,
 		ds_flags, &state->dc_info);
diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c
index 7fb5aa8..874d556 100644
--- a/source3/winbindd/winbindd_dual.c
+++ b/source3/winbindd/winbindd_dual.c
@@ -119,6 +119,7 @@ static NTSTATUS child_write_response(int sock, struct winbindd_response *wrsp)
 
 struct wb_child_request_state {
 	struct tevent_context *ev;
+	struct tevent_req *queue_subreq;
 	struct tevent_req *subreq;
 	struct winbindd_child *child;
 	struct winbindd_request *request;
@@ -127,9 +128,9 @@ struct wb_child_request_state {
 
 static bool fork_domain_child(struct winbindd_child *child);
 
-static void wb_child_request_trigger(struct tevent_req *req,
-					    void *private_data);
+static void wb_child_request_waited(struct tevent_req *subreq);
 static void wb_child_request_done(struct tevent_req *subreq);
+static void wb_child_request_orphaned(struct tevent_req *subreq);
 
 static void wb_child_request_cleanup(struct tevent_req *req,
 				     enum tevent_req_state req_state);
@@ -141,6 +142,7 @@ struct tevent_req *wb_child_request_send(TALLOC_CTX *mem_ctx,
 {
 	struct tevent_req *req;
 	struct wb_child_request_state *state;
+	struct tevent_req *subreq;
 
 	req = tevent_req_create(mem_ctx, &state,
 				struct wb_child_request_state);
@@ -152,23 +154,36 @@ struct tevent_req *wb_child_request_send(TALLOC_CTX *mem_ctx,
 	state->child = child;
 	state->request = request;
 
-	if (!tevent_queue_add(child->queue, ev, req,
-			      wb_child_request_trigger, NULL)) {
-		tevent_req_oom(req);
+	subreq = tevent_queue_wait_send(state, ev, child->queue);
+	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
 	}
+	tevent_req_set_callback(subreq, wb_child_request_waited, req);
+	state->queue_subreq = subreq;
 
 	tevent_req_set_cleanup_fn(req, wb_child_request_cleanup);
 
 	return req;
 }
 
-static void wb_child_request_trigger(struct tevent_req *req,
-				     void *private_data)
+static void wb_child_request_waited(struct tevent_req *subreq)
 {
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
 	struct wb_child_request_state *state = tevent_req_data(
 		req, struct wb_child_request_state);
-	struct tevent_req *subreq;
+	bool ok;
+
+	ok = tevent_queue_wait_recv(subreq);
+	if (!ok) {
+		tevent_req_oom(req);
+		return;
+	}
+	/*
+	 * We need to keep state->queue_subreq
+	 * in order to block the queue.
+	 */
+	subreq = NULL;
 
 	if ((state->child->sock == -1) && (!fork_domain_child(state->child))) {
 		tevent_req_error(req, errno);
@@ -206,6 +221,25 @@ static void wb_child_request_done(struct tevent_req *subreq)
 	tevent_req_done(req);
 }
 
+static void wb_child_request_orphaned(struct tevent_req *subreq)
+{
+	struct winbindd_child *child =
+		(struct winbindd_child *)tevent_req_callback_data_void(subreq);
+
+	DBG_WARNING("cleanup orphaned subreq[%p]\n", subreq);
+	TALLOC_FREE(subreq);
+
+	if (child->domain != NULL) {
+		/*
+		 * If the child is attached to a domain,
+		 * we need to make sure the domain queue
+		 * can move forward, after the orphaned
+		 * request is done.
+		 */
+		tevent_queue_start(child->domain->queue);
+	}
+}
+
 int wb_child_request_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
 			  struct winbindd_response **presponse, int *err)
 {
@@ -230,7 +264,40 @@ static void wb_child_request_cleanup(struct tevent_req *req,
 		return;
 	}
 
+	if (req_state == TEVENT_REQ_RECEIVED) {
+		struct tevent_req *subreq = NULL;
+
+		/*
+		 * Our caller gave up, but we need to keep
+		 * the low level request (wb_simple_trans)
+		 * in order to maintain the parent child protocol.
+		 *
+		 * We also need to keep the child queue blocked
+		 * until we got the response from the child.
+		 */
+
+		subreq = talloc_move(state->child->queue, &state->subreq);
+		talloc_move(subreq, &state->queue_subreq);
+		tevent_req_set_callback(subreq,
+					wb_child_request_orphaned,
+					state->child);
+
+		DBG_WARNING("keep orphaned subreq[%p]\n", subreq);
+		return;
+	}
+
 	TALLOC_FREE(state->subreq);
+	TALLOC_FREE(state->queue_subreq);
+
+	if (state->child->domain != NULL) {
+		/*
+		 * If the child is attached to a domain,
+		 * we need to make sure the domain queue
+		 * can move forward, after the request
+		 * is done.
+		 */
+		tevent_queue_start(state->child->domain->queue);
+	}
 
 	if (req_state == TEVENT_REQ_DONE) {
 		/* transmitted request and got response */
@@ -248,7 +315,7 @@ static void wb_child_request_cleanup(struct tevent_req *req,
 	DLIST_REMOVE(winbindd_children, state->child);
 }
 
-struct winbindd_child *choose_domain_child(struct winbindd_domain *domain)
+static struct winbindd_child *choose_domain_child(struct winbindd_domain *domain)
 {
 	struct winbindd_child *shortest = &domain->children[0];
 	struct winbindd_child *current;
@@ -277,21 +344,40 @@ 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;
 	struct winbindd_request *init_req;
 	struct winbindd_response *response;
+	struct tevent_req *pending_subreq;
 };
 
+static void wb_domain_request_cleanup(struct tevent_req *req,
+				      enum tevent_req_state req_state)
+{
+	struct wb_domain_request_state *state = tevent_req_data(
+		req, struct wb_domain_request_state);
+
+	/*
+	 * If we're completely done or got a failure.
+	 * we should remove ourself from the domain queue,
+	 * after removing the child subreq from the child queue
+	 * and give the next one in the queue the chance
+	 * to check for an idle child.
+	 */
+	TALLOC_FREE(state->pending_subreq);
+	TALLOC_FREE(state->queue_entry);
+	tevent_queue_start(state->domain->queue);
+}
+
+static void 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);
@@ -301,7 +387,7 @@ struct tevent_req *wb_domain_request_send(TALLOC_CTX *mem_ctx,
 					  struct winbindd_domain *domain,
 					  struct winbindd_request *request)
 {
-	struct tevent_req *req, *subreq;
+	struct tevent_req *req;
 	struct wb_domain_request_state *state;
 
 	req = tevent_req_create(mem_ctx, &state,
@@ -310,25 +396,70 @@ struct tevent_req *wb_domain_request_send(TALLOC_CTX *mem_ctx,
 		return NULL;
 	}
 
+	state->domain = domain;
+	state->ev = ev;
+	state->request = request;
+
+	tevent_req_set_cleanup_fn(req, wb_domain_request_cleanup);
+
+	state->queue_entry = tevent_queue_add_entry(
+			domain->queue, state->ev, req,
+			wb_domain_request_trigger, NULL);
+	if (tevent_req_nomem(state->queue_entry, req)) {
+		return tevent_req_post(req, ev);
+	}
+
+	return req;
+}
+
+static void 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 tevent_req *subreq = NULL;
+	size_t shortest_queue_length;
+
 	state->child = choose_domain_child(domain);
+	shortest_queue_length = tevent_queue_length(state->child->queue);
+	if (shortest_queue_length > 0) {
+		/*
+		 * All children are busy, we need to stop
+		 * the queue and untrigger our own queue
+		 * entry. Once a pending request
+		 * is done it calls tevent_queue_start
+		 * and we get retriggered.
+		 */
+		state->child = NULL;
+		tevent_queue_stop(state->domain->queue);
+		tevent_queue_entry_untrigger(state->queue_entry);
+		return;
+	}


-- 
Samba Shared Repository



More information about the samba-cvs mailing list