The Samba-Bugzilla – Attachment 14002 Details for
Bug 13292
winbind requests could get stuck in the queue of a busy child, while later requests could get served fine by other children.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for 4.8 cherry-picked from master
bug13292-v48.patch (text/plain), 26.62 KB, created by
Ralph Böhme
on 2018-02-27 11:01:38 UTC
(
hide
)
Description:
Patch for 4.8 cherry-picked from master
Filename:
MIME Type:
Creator:
Ralph Böhme
Created:
2018-02-27 11:01:38 UTC
Size:
26.62 KB
patch
obsolete
>From cd9eadc314880473b696a374aba2693360beea19 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 14 Feb 2018 13:24:54 +0100 >Subject: [PATCH 1/5] 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@samba.org> >Reviewed-by: Volker Lendecke <vl@samba.org> >(cherry picked from commit c2d78a0a0a3f9b9ade61cf707f23e59a1a16c61b) >--- > source3/winbindd/wb_sids2xids.c | 6 +++--- > source3/winbindd/winbindd_allocate_gid.c | 6 +++--- > source3/winbindd/winbindd_allocate_uid.c | 6 +++--- > source3/winbindd/winbindd_idmap.c | 5 +++++ > source3/winbindd/winbindd_proto.h | 1 + > 5 files changed, 15 insertions(+), 9 deletions(-) > >diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c >index b8ad300ba3c..c687f7064bb 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_allocate_gid.c b/source3/winbindd/winbindd_allocate_gid.c >index a9236bbf23d..85aa1369473 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 99c0bdac102..69ce61c872e 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_idmap.c b/source3/winbindd/winbindd_idmap.c >index 028026087d6..2ee436bc7dc 100644 >--- a/source3/winbindd/winbindd_idmap.c >+++ b/source3/winbindd/winbindd_idmap.c >@@ -34,6 +34,11 @@ struct winbindd_child *idmap_child(void) > return &static_idmap_child; > } > >+struct dcerpc_binding_handle *idmap_child_handle(void) >+{ >+ return static_idmap_child.binding_handle; >+} >+ > static const struct winbindd_child_dispatch_table idmap_dispatch_table[] = { > { > .name = "PING", >diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h >index d09176d954a..66d4a19617c 100644 >--- a/source3/winbindd/winbindd_proto.h >+++ b/source3/winbindd/winbindd_proto.h >@@ -351,6 +351,7 @@ NTSTATUS winbindd_print_groupmembers(struct db_context *members, > > void init_idmap_child(void); > struct winbindd_child *idmap_child(void); >+struct dcerpc_binding_handle *idmap_child_handle(void); > struct idmap_domain *idmap_find_domain_with_sid(const char *domname, > const struct dom_sid *sid); > const char *idmap_config_const_string(const char *domname, const char *option, >-- >2.13.6 > > >From 59027a05dfae6391be56f0914381664ccbbbdf38 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 14 Feb 2018 13:24:54 +0100 >Subject: [PATCH 2/5] 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@samba.org> >Reviewed-by: Volker Lendecke <vl@samba.org> >(cherry picked from commit 44ebaaac8933f5fc16a043b8c15a9449746af47b) >--- > source3/winbindd/wb_dsgetdcname.c | 8 ++++---- > source3/winbindd/winbindd_dsgetdcname.c | 6 +++--- > source3/winbindd/winbindd_locator.c | 5 +++++ > source3/winbindd/winbindd_proto.h | 1 + > 4 files changed, 13 insertions(+), 7 deletions(-) > >diff --git a/source3/winbindd/wb_dsgetdcname.c b/source3/winbindd/wb_dsgetdcname.c >index 8bd74198bcb..2f450c7a2b4 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/winbindd_dsgetdcname.c b/source3/winbindd/winbindd_dsgetdcname.c >index 8eb1de74d92..fd9270f106c 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_locator.c b/source3/winbindd/winbindd_locator.c >index 59e8614fdbc..55b64555376 100644 >--- a/source3/winbindd/winbindd_locator.c >+++ b/source3/winbindd/winbindd_locator.c >@@ -34,6 +34,11 @@ struct winbindd_child *locator_child(void) > return &static_locator_child; > } > >+struct dcerpc_binding_handle *locator_child_handle(void) >+{ >+ return static_locator_child.binding_handle; >+} >+ > static const struct winbindd_child_dispatch_table locator_dispatch_table[] = { > { > .name = "PING", >diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h >index 66d4a19617c..5d31490ff16 100644 >--- a/source3/winbindd/winbindd_proto.h >+++ b/source3/winbindd/winbindd_proto.h >@@ -367,6 +367,7 @@ bool lp_scan_idmap_domains(bool (*fn)(const char *domname, > > void init_locator_child(void); > struct winbindd_child *locator_child(void); >+struct dcerpc_binding_handle *locator_child_handle(void); > > /* The following definitions come from winbindd/winbindd_misc.c */ > >-- >2.13.6 > > >From 5bb5a4c032fe933634512b9dea14cf5c20cd9fa9 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 20 Feb 2018 14:43:38 +0100 >Subject: [PATCH 3/5] winbind: make choose_domain_child() static > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=13292 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Volker Lendecke <vl@samba.org> >(cherry picked from commit 5116aff286bdffe4abc9ddda09cf64ab999fd13e) >--- > source3/winbindd/winbindd_dual.c | 2 +- > source3/winbindd/winbindd_proto.h | 1 - > 2 files changed, 1 insertion(+), 2 deletions(-) > >diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c >index 3d44e2027ae..e756aff98de 100644 >--- a/source3/winbindd/winbindd_dual.c >+++ b/source3/winbindd/winbindd_dual.c >@@ -292,7 +292,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; >diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h >index 5d31490ff16..704a8dd2924 100644 >--- a/source3/winbindd/winbindd_proto.h >+++ b/source3/winbindd/winbindd_proto.h >@@ -272,7 +272,6 @@ void setup_domain_child(struct winbindd_domain *domain); > /* The following definitions come from winbindd/winbindd_dual.c */ > > struct dcerpc_binding_handle *dom_child_handle(struct winbindd_domain *domain); >-struct winbindd_child *choose_domain_child(struct winbindd_domain *domain); > > struct tevent_req *wb_child_request_send(TALLOC_CTX *mem_ctx, > struct tevent_context *ev, >-- >2.13.6 > > >From a8414c6c8710caff8691c70da8351e03c05cb99e Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Tue, 13 Feb 2018 16:04:44 +0100 >Subject: [PATCH 4/5] winbind: Maintain a binding handle per domain and always > go via wb_domain_request_send() > >Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=13292 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Signed-off-by: Volker Lendecke <vl@samba.org> >(cherry picked from commit b518cb0597d269002105644302c58ca8f9f0f717) >--- > source3/winbindd/winbindd.h | 2 ++ > source3/winbindd/winbindd_dual.c | 11 +++---- > source3/winbindd/winbindd_dual_ndr.c | 61 +++++++++++++++++++++++++++++++----- > source3/winbindd/winbindd_util.c | 6 ++++ > 4 files changed, 66 insertions(+), 14 deletions(-) > >diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h >index 3e4b256ef32..8a44f37789b 100644 >--- a/source3/winbindd/winbindd.h >+++ b/source3/winbindd/winbindd.h >@@ -184,6 +184,8 @@ struct winbindd_domain { > > struct winbindd_child *children; > >+ 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 e756aff98de..263e5e598b7 100644 >--- a/source3/winbindd/winbindd_dual.c >+++ b/source3/winbindd/winbindd_dual.c >@@ -321,10 +321,7 @@ static 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 { >@@ -608,8 +605,10 @@ void setup_child(struct winbindd_domain *domain, struct winbindd_child *child, > child->table = table; > child->queue = tevent_queue_create(NULL, "winbind_child"); > SMB_ASSERT(child->queue != NULL); >- child->binding_handle = wbint_binding_handle(NULL, domain, child); >- SMB_ASSERT(child->binding_handle != NULL); >+ if (domain == NULL) { >+ child->binding_handle = wbint_binding_handle(NULL, NULL, child); >+ SMB_ASSERT(child->binding_handle != NULL); >+ } > } > > void winbind_child_died(pid_t pid) >diff --git a/source3/winbindd/winbindd_dual_ndr.c b/source3/winbindd/winbindd_dual_ndr.c >index 00c7df1f863..25e7445edc6 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, >@@ -209,9 +255,8 @@ static struct tevent_req *wbint_bh_disconnect_send(TALLOC_CTX *mem_ctx, > > /* > * TODO: do a real async disconnect ... >- * >- * For now the caller needs to free rpc_cli > */ >+ hs->domain = NULL; > hs->child = NULL; > > tevent_req_done(req); >diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c >index 9950c669629..78f526cdea8 100644 >--- a/source3/winbindd/winbindd_util.c >+++ b/source3/winbindd/winbindd_util.c >@@ -228,6 +228,12 @@ static NTSTATUS add_trusted_domain(const char *domain_name, > 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.13.6 > > >From 71c8069686192aad122f212ac58c85a7ab6022dd Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 14 Feb 2018 15:04:01 +0100 >Subject: [PATCH 5/5] 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@samba.org> >Reviewed-by: Volker Lendecke <vl@samba.org> > >Autobuild-User(master): Stefan Metzmacher <metze@samba.org> >Autobuild-Date(master): Fri Feb 23 09:04:23 CET 2018 on sn-devel-144 > >(cherry picked from commit 7f2d45a6c2a88dd8833fc66d314ec21507dd52c3) >--- > source3/winbindd/winbindd.h | 1 + > source3/winbindd/winbindd_dual.c | 127 ++++++++++++++++++++++++++++++++++++--- > source3/winbindd/winbindd_util.c | 6 ++ > 3 files changed, 125 insertions(+), 9 deletions(-) > >diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h >index 8a44f37789b..081722f6a90 100644 >--- a/source3/winbindd/winbindd.h >+++ b/source3/winbindd/winbindd.h >@@ -184,6 +184,7 @@ 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. */ >diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c >index 263e5e598b7..2ae21b09c43 100644 >--- a/source3/winbindd/winbindd_dual.c >+++ b/source3/winbindd/winbindd_dual.c >@@ -223,8 +223,21 @@ static void wb_child_request_done(struct tevent_req *subreq) > > 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, >@@ -267,7 +280,7 @@ static void wb_child_request_cleanup(struct tevent_req *req, > talloc_move(subreq, &state->queue_subreq); > tevent_req_set_callback(subreq, > wb_child_request_orphaned, >- NULL); >+ state->child); > > DBG_WARNING("keep orphaned subreq[%p]\n", subreq); > return; >@@ -276,6 +289,16 @@ static void wb_child_request_cleanup(struct tevent_req *req, > 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 */ > return; >@@ -326,13 +349,35 @@ struct dcerpc_binding_handle *dom_child_handle(struct winbindd_domain *domain) > > 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); >@@ -342,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, >@@ -355,21 +400,66 @@ struct tevent_req *wb_domain_request_send(TALLOC_CTX *mem_ctx, > 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; >+ } > > if (domain->initialized) { > subreq = wb_child_request_send(state, state->ev, state->child, > state->request); > if (tevent_req_nomem(subreq, req)) { >- return tevent_req_post(req, ev); >+ return; > } > tevent_req_set_callback(subreq, wb_domain_request_done, req); >- return req; >+ state->pending_subreq = subreq; >+ >+ /* >+ * Once the domain is initialized and >+ * once we placed our real request into the child queue, >+ * we can remove ourself from the domain queue >+ * and give the next one in the queue the chance >+ * to check for an idle child. >+ */ >+ TALLOC_FREE(state->queue_entry); >+ return; > } > > state->init_req = talloc_zero(state, struct winbindd_request); > if (tevent_req_nomem(state->init_req, req)) { >- return tevent_req_post(req, ev); >+ return; > } > > if (IS_DC || domain->primary || domain->internal) { >@@ -382,11 +472,12 @@ struct tevent_req *wb_domain_request_send(TALLOC_CTX *mem_ctx, > subreq = wb_child_request_send(state, state->ev, state->child, > state->init_req); > if (tevent_req_nomem(subreq, req)) { >- return tevent_req_post(req, ev); >+ return; > } > tevent_req_set_callback(subreq, wb_domain_request_initialized, > req); >- return req; >+ state->pending_subreq = subreq; >+ return; > } > > /* >@@ -403,10 +494,11 @@ struct tevent_req *wb_domain_request_send(TALLOC_CTX *mem_ctx, > NULL, /* site_name */ > DS_RETURN_DNS_NAME); /* flags */ > if (tevent_req_nomem(subreq, req)) { >- return tevent_req_post(req, ev); >+ return; > } > tevent_req_set_callback(subreq, wb_domain_request_gotdc, req); >- return req; >+ state->pending_subreq = subreq; >+ return; > } > > static void wb_domain_request_gotdc(struct tevent_req *subreq) >@@ -419,6 +511,8 @@ static void wb_domain_request_gotdc(struct tevent_req *subreq) > NTSTATUS status; > const char *dcname = NULL; > >+ state->pending_subreq = NULL; >+ > status = wb_dsgetdcname_recv(subreq, state, &dcinfo); > TALLOC_FREE(subreq); > if (tevent_req_nterror(req, status)) { >@@ -442,6 +536,7 @@ static void wb_domain_request_gotdc(struct tevent_req *subreq) > return; > } > tevent_req_set_callback(subreq, wb_domain_request_initialized, req); >+ state->pending_subreq = subreq; > } > > static void wb_domain_request_initialized(struct tevent_req *subreq) >@@ -453,6 +548,8 @@ static void wb_domain_request_initialized(struct tevent_req *subreq) > struct winbindd_response *response; > int ret, err; > >+ state->pending_subreq = NULL; >+ > ret = wb_child_request_recv(subreq, talloc_tos(), &response, &err); > TALLOC_FREE(subreq); > if (ret == -1) { >@@ -500,6 +597,16 @@ static void wb_domain_request_initialized(struct tevent_req *subreq) > return; > } > tevent_req_set_callback(subreq, wb_domain_request_done, req); >+ state->pending_subreq = subreq; >+ >+ /* >+ * Once the domain is initialized and >+ * once we placed our real request into the child queue, >+ * we can remove ourself from the domain queue >+ * and give the next one in the queue the chance >+ * to check for an idle child. >+ */ >+ TALLOC_FREE(state->queue_entry); > } > > static void wb_domain_request_done(struct tevent_req *subreq) >@@ -510,6 +617,8 @@ static void wb_domain_request_done(struct tevent_req *subreq) > req, struct wb_domain_request_state); > int ret, err; > >+ state->pending_subreq = NULL; >+ > ret = wb_child_request_recv(subreq, talloc_tos(), &state->response, > &err); > TALLOC_FREE(subreq); >diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c >index 78f526cdea8..73e6b76ec73 100644 >--- a/source3/winbindd/winbindd_util.c >+++ b/source3/winbindd/winbindd_util.c >@@ -228,6 +228,12 @@ 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); >-- >2.13.6 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
metze
:
review+
Actions:
View
Attachments on
bug 13292
: 14002 |
14151
|
14157