From 120c09b125f656d6d03b979560f3ef6652217691 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 26 Jun 2008 14:02:39 -0700 Subject: From Steve Danneman @ Isilon. Attached is the companion patch to (037b9689d9042a398cb91e4628a82fcdfa913c21), which made handling of WINBINDD_LIST_GROUPS asynchronous. Because most all of the list_groups code was reusable, I abstracted it, and implemented both list_groups and list_users on top of it. On my large test domain a "wbinfo -u" call went from 70 seconds to 30 seconds with this patch. Plus, the parent process is no longer blocked from receiving new requests during that time. Steven Danneman | Software Development Engineer Isilon Systems P +1-206-315-7500 F +1-206-315-7501 www.isilon.com (This used to be commit 5188f2861137ff06d5399561d55d7d00c3a08644) --- source3/winbindd/winbindd_async.c | 85 ++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 10 deletions(-) (limited to 'source3/winbindd/winbindd_async.c') diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index bc0f9d836b..e47666462e 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -453,8 +453,8 @@ enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain, return WINBINDD_OK; } -/* This is the first callback after enumerating groups from a domain */ -static void listgroups_recv(TALLOC_CTX *mem_ctx, bool success, +/* This is the first callback after enumerating users/groups from a domain */ +static void listent_recv(TALLOC_CTX *mem_ctx, bool success, struct winbindd_response *response, void *c, void *private_data) { @@ -462,7 +462,7 @@ static void listgroups_recv(TALLOC_CTX *mem_ctx, bool success, (void (*)(void *, bool, fstring, char*))c; if (!success || response->result != WINBINDD_OK) { - DEBUG(5, ("list_groups() failed!\n")); + DEBUG(5, ("list_ent() failed!\n")); cont(private_data, False, response->data.name.dom_name, NULL); return; } @@ -473,30 +473,95 @@ static void listgroups_recv(TALLOC_CTX *mem_ctx, bool success, SAFE_FREE(response->extra_data.data); } -/* Request the name of all groups in a single domain */ -void winbindd_listgroups_async(TALLOC_CTX *mem_ctx, +/* Request the name of all users/groups in a single domain */ +void winbindd_listent_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, void (*cont)(void *private_data, bool success, fstring dom_name, char* extra_data), - void *private_data) + void *private_data, enum ent_type type) { struct winbindd_request request; ZERO_STRUCT(request); - request.cmd = WINBINDD_LIST_GROUPS; + if (type == LIST_USERS) + request.cmd = WINBINDD_LIST_USERS; + else if (type == LIST_GROUPS) + request.cmd = WINBINDD_LIST_GROUPS; - do_async_domain(mem_ctx, domain, &request, listgroups_recv, + do_async_domain(mem_ctx, domain, &request, listent_recv, (void *)cont, private_data); } + +enum winbindd_result winbindd_dual_list_users(struct winbindd_domain *domain, + struct winbindd_cli_state *state) +{ + WINBIND_USERINFO *info; + NTSTATUS status; + struct winbindd_methods *methods; + uint32 num_entries = 0; + char *extra_data = NULL; + uint32_t extra_data_len = 0, i; + + /* Must copy domain into response first for debugging in parent */ + fstrcpy(state->response.data.name.dom_name, domain->name); + + /* Query user info */ + methods = domain->methods; + status = methods->query_user_list(domain, state->mem_ctx, + &num_entries, &info); + + if (!NT_STATUS_IS_OK(status)) + return WINBINDD_ERROR; + + if (num_entries == 0) + return WINBINDD_OK; + + /* Allocate some memory for extra data. Note that we limit + account names to sizeof(fstring) = 256 characters. + +1 for the ',' between group names */ + extra_data = (char *)SMB_REALLOC(extra_data, + (sizeof(fstring) + 1) * num_entries); + + if (!extra_data) { + DEBUG(0,("failed to enlarge buffer!\n")); + return WINBINDD_ERROR; + } + + /* Pack user list into extra data fields */ + for (i = 0; i < num_entries; i++) { + fstring acct_name, name; + + if (info[i].acct_name == NULL) + fstrcpy(acct_name, ""); + else + fstrcpy(acct_name, info[i].acct_name); + + fill_domain_username(name, domain->name, acct_name, True); + /* Append to extra data */ + memcpy(&extra_data[extra_data_len], name, strlen(name)); + extra_data_len += strlen(name); + extra_data[extra_data_len++] = ','; + } + + /* Assign extra_data fields in response structure */ + if (extra_data) { + /* remove trailing ',' */ + extra_data[extra_data_len - 1] = '\0'; + state->response.extra_data.data = extra_data; + state->response.length += extra_data_len; + } + + return WINBINDD_OK; +} enum winbindd_result winbindd_dual_list_groups(struct winbindd_domain *domain, struct winbindd_cli_state *state) { struct getent_state groups = {}; char *extra_data = NULL; - unsigned int extra_data_len = 0, i; + uint32_t extra_data_len = 0, i; - /* Must copy domain into response first for bookeeping in parent */ + /* Must copy domain into response first for debugging in parent */ fstrcpy(state->response.data.name.dom_name, domain->name); fstrcpy(groups.domain_name, domain->name); -- cgit