The branch, v3-5-test has been updated via 76c570f s3-utils: Use ads_do_search_retry in net ads search via 8572ce0 s3-libads: Use a reducing page size to try and cope with a slow LDAP server via 5daa8d2 s3-winbindd: Always map the LDAP error code to an NTSTATUS via d113c69 s3-libads: Map LDAP_TIMELIMIT_EXCEEDED as NT_STATUS_IO_TIMEOUT from b9d3f82 Fix the loop unrolling inside resolve_ads().
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-5-test - Log ----------------------------------------------------------------- commit 76c570fe6be4d6b5b254ec3264a97cb13864a6df Author: Andrew Bartlett <abart...@samba.org> Date: Fri May 18 22:02:57 2012 +1000 s3-utils: Use ads_do_search_retry in net ads search This makes it possible to search against a slow server, as will fallback from 1000 to (eventually) 125 users at a time. Andrew Bartlett The last 4 patches addres bug #8943 (Slow but responsive DC can lock up winbindd for > 10 minutes at a time). commit 8572ce0e5ff17bfe0df2823078119be9182a0378 Author: Andrew Bartlett <abart...@samba.org> Date: Fri May 18 22:01:14 2012 +1000 s3-libads: Use a reducing page size to try and cope with a slow LDAP server If we cannot get 1000 users downloaded in 15seconds, try with 500, 250 and then 125 users at a time. Andrew Bartlett commit 5daa8d2f7fa7d15ac6d6b0238e299f69c70be024 Author: Andrew Bartlett <abart...@samba.org> Date: Fri May 18 17:40:59 2012 +1000 s3-winbindd: Always map the LDAP error code to an NTSTATUS We do this so that we catch LDAP_TIMELIMIT_EXCEEDED as NT_STATUS_IO_TIMEOUT, which has special handling in winbindd_cache.c Andrew Bartlett commit d113c69edb57c7a3d72e3ab122cec44858a5313e Author: Andrew Bartlett <abart...@samba.org> Date: Fri May 18 17:38:48 2012 +1000 s3-libads: Map LDAP_TIMELIMIT_EXCEEDED as NT_STATUS_IO_TIMEOUT This allows Samba to then handle this error in the same way it would for RPC connections Andrew Bartlett ----------------------------------------------------------------------- Summary of changes: source3/include/ads.h | 1 + source3/libads/ads_status.c | 3 +++ source3/libads/ads_struct.c | 4 ++++ source3/libads/ldap.c | 4 ++-- source3/libads/ldap_utils.c | 7 +++++++ source3/utils/net_ads.c | 2 +- source3/winbindd/winbindd_ads.c | 28 ++++++++++++++++++++++------ 7 files changed, 40 insertions(+), 9 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/include/ads.h b/source3/include/ads.h index 62d51ce..ff3dc12 100644 --- a/source3/include/ads.h +++ b/source3/include/ads.h @@ -108,6 +108,7 @@ typedef struct ads_struct { time_t current_time; char *schema_path; char *config_path; + int ldap_page_size; } config; /* info about the current LDAP connection */ diff --git a/source3/libads/ads_status.c b/source3/libads/ads_status.c index 6680766..392e82f 100644 --- a/source3/libads/ads_status.c +++ b/source3/libads/ads_status.c @@ -79,6 +79,9 @@ NTSTATUS ads_ntstatus(ADS_STATUS status) if (status.err.rc == LDAP_SUCCESS) { return NT_STATUS_OK; } + if (status.err.rc == LDAP_TIMELIMIT_EXCEEDED) { + return NT_STATUS_IO_TIMEOUT; + } return NT_STATUS_LDAP(status.err.rc); #endif #ifdef HAVE_KRB5 diff --git a/source3/libads/ads_struct.c b/source3/libads/ads_struct.c index aef35ad..2d9ea17 100644 --- a/source3/libads/ads_struct.c +++ b/source3/libads/ads_struct.c @@ -148,6 +148,10 @@ ADS_STRUCT *ads_init(const char *realm, ads->auth.flags = wrap_flags; + /* Start with a page size of 1000 when the connection is new, + * we will drop it by half we get a timeout. */ + ads->config.ldap_page_size = 1000; + return ads; } diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index f18ded1..99ec2e4 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -924,11 +924,11 @@ static ADS_STATUS ads_do_paged_search_args(ADS_STRUCT *ads, cookie_be = ber_alloc_t(LBER_USE_DER); if (*cookie) { - ber_printf(cookie_be, "{iO}", (ber_int_t) 1000, *cookie); + ber_printf(cookie_be, "{iO}", (ber_int_t) ads->config.ldap_page_size, *cookie); ber_bvfree(*cookie); /* don't need it from last time */ *cookie = NULL; } else { - ber_printf(cookie_be, "{io}", (ber_int_t) 1000, "", 0); + ber_printf(cookie_be, "{io}", (ber_int_t) ads->config.ldap_page_size, "", 0); } ber_flatten(cookie_be, &cookie_bv); PagedResults.ldctl_oid = CONST_DISCARD(char *, ADS_PAGE_CTL_OID); diff --git a/source3/libads/ldap_utils.c b/source3/libads/ldap_utils.c index 871449a..dee3c03 100644 --- a/source3/libads/ldap_utils.c +++ b/source3/libads/ldap_utils.c @@ -68,6 +68,13 @@ static ADS_STATUS ads_do_search_retry_internal(ADS_STRUCT *ads, const char *bind while (--count) { + if (NT_STATUS_EQUAL(ads_ntstatus(status), NT_STATUS_IO_TIMEOUT) && ads->config.ldap_page_size >= 250) { + int new_page_size = (ads->config.ldap_page_size / 2); + DEBUG(1, ("Reducing LDAP page size from %d to %d due to IO_TIMEOUT\n", + ads->config.ldap_page_size, new_page_size)); + ads->config.ldap_page_size = new_page_size; + } + if (*res) ads_msgfree(ads, *res); *res = NULL; diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 83aef18..e5e76be 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -2156,7 +2156,7 @@ static int net_ads_search(struct net_context *c, int argc, const char **argv) ldap_exp = argv[0]; attrs = (argv + 1); - rc = ads_do_search_all(ads, ads->config.bind_path, + rc = ads_do_search_retry(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE, ldap_exp, attrs, &res); if (!ADS_ERR_OK(rc)) { diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index b0ca9b8..4a9bd35 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -180,8 +180,12 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, } rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs); - if (!ADS_ERR_OK(rc) || !res) { + if (!ADS_ERR_OK(rc)) { DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc))); + status = ads_ntstatus(rc); + } else if (!res) { + DEBUG(1,("query_user_list ads_search returned NULL res\n")); + goto done; } @@ -325,9 +329,13 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, } rc = ads_search_retry(ads, &res, filter, attrs); - if (!ADS_ERR_OK(rc) || !res) { + if (!ADS_ERR_OK(rc)) { + status = ads_ntstatus(rc); DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc))); goto done; + } else if (!res) { + DEBUG(1,("enum_dom_groups ads_search returned NULL res\n")); + goto done; } count = ads_count_replies(ads, res); @@ -532,12 +540,16 @@ static NTSTATUS query_user(struct winbindd_domain *domain, goto done; } rc = ads_search_retry(ads, &msg, ldap_exp, attrs); - free(ldap_exp); + SAFE_FREE(ldap_exp); TALLOC_FREE(sidstr); - if (!ADS_ERR_OK(rc) || !msg) { + if (!ADS_ERR_OK(rc)) { DEBUG(1,("query_user(sid=%s) ads_search: %s\n", sid_string_dbg(sid), ads_errstr(rc))); - goto done; + return ads_ntstatus(rc); + } else if (!msg) { + DEBUG(1,("query_user(sid=%s) ads_search returned NULL res\n", + sid_string_dbg(sid))); + return NT_STATUS_INTERNAL_ERROR; } count = ads_count_replies(ads, msg); @@ -632,11 +644,15 @@ static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain, rc = ads_search_retry(ads, &res, ldap_exp, group_attrs); - if (!ADS_ERR_OK(rc) || !res) { + if (!ADS_ERR_OK(rc)) { DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc))); return ads_ntstatus(rc); + } else if (!res) { + DEBUG(1,("lookup_usergroups ads_search returned NULL res\n")); + return NT_STATUS_INTERNAL_ERROR; } + count = ads_count_replies(ads, res); *user_sids = NULL; -- Samba Shared Repository