diff options
| author | Fabiano Fidêncio <fidencio@redhat.com> | 2017-02-22 08:07:45 +0100 |
|---|---|---|
| committer | Jakub Hrozek <jhrozek@redhat.com> | 2017-03-14 12:35:01 +0100 |
| commit | 8bb6680637ead03e24a38d15ec5265d11a920a1d (patch) | |
| tree | f5e4cc597dcf9012c54fd4e83a25e27029d8558b /src/responder | |
| parent | 9286d0d4143bcb4e36b91022107e307998122bbb (diff) | |
| download | sssd-8bb6680637ead03e24a38d15ec5265d11a920a1d.tar.gz sssd-8bb6680637ead03e24a38d15ec5265d11a920a1d.tar.xz sssd-8bb6680637ead03e24a38d15ec5265d11a920a1d.zip | |
CACHE_REQ: Check the caches first
This patch introduces a new configurable option to define whether the
responder should query all domains' caches before querying the Data
Providers.
This new option is called cache_first and, by default, it's disabled,
meaning that, for each provider, the responder may contact the cache and
the data provider in the same iteration.
Co-Author: Pavel Březina <pbrezina@redhat.com>
Related:
https://pagure.io/SSSD/sssd/issue/3001
Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
Diffstat (limited to 'src/responder')
| -rw-r--r-- | src/responder/common/cache_req/cache_req.c | 151 | ||||
| -rw-r--r-- | src/responder/common/cache_req/cache_req_private.h | 6 | ||||
| -rw-r--r-- | src/responder/common/cache_req/cache_req_search.c | 11 | ||||
| -rw-r--r-- | src/responder/common/responder.h | 1 | ||||
| -rw-r--r-- | src/responder/common/responder_common.c | 11 |
5 files changed, 145 insertions, 35 deletions
diff --git a/src/responder/common/cache_req/cache_req.c b/src/responder/common/cache_req/cache_req.c index 7a836c93c..aca150d69 100644 --- a/src/responder/common/cache_req/cache_req.c +++ b/src/responder/common/cache_req/cache_req.c @@ -118,6 +118,9 @@ cache_req_create(TALLOC_CTX *mem_ctx, return NULL; } + cr->cache_first = rctx->cache_first; + cr->bypass_cache = cr->plugin->bypass_cache || cr->data->bypass_cache; + return cr; } @@ -319,27 +322,21 @@ struct cache_req_search_domains_state { size_t num_results; bool check_next; bool dp_success; + bool bypass_cache; + bool bypass_dp; }; -static struct tevent_req * -cache_req_search_domains_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct cache_req *cr, - struct sss_domain_info *domain, - bool check_next); - static errno_t cache_req_search_domains_next(struct tevent_req *req); -static errno_t cache_req_select_domains(struct tevent_req *req, - const char *domain_name); - static void cache_req_search_domains_done(struct tevent_req *subreq); struct tevent_req *cache_req_search_domains_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cache_req *cr, struct sss_domain_info *domain, - bool check_next) + bool check_next, + bool bypass_cache, + bool bypass_dp) { struct tevent_req *req; struct cache_req_search_domains_state *state = NULL; @@ -358,6 +355,8 @@ struct tevent_req *cache_req_search_domains_send(TALLOC_CTX *mem_ctx, state->domain = domain; state->check_next = check_next; state->dp_success = true; + state->bypass_cache = bypass_cache; + state->bypass_dp = bypass_dp; ret = cache_req_search_domains_next(req); if (ret == EAGAIN) { @@ -418,7 +417,8 @@ static errno_t cache_req_search_domains_next(struct tevent_req *req) return ret; } - subreq = cache_req_search_send(state, state->ev, cr); + subreq = cache_req_search_send(state, state->ev, cr, + state->bypass_cache, state->bypass_dp); if (subreq == NULL) { return ENOMEM; } @@ -462,7 +462,6 @@ static void cache_req_search_domains_done(struct tevent_req *subreq) struct cache_req_search_domains_state *state; struct ldb_result *result; struct tevent_req *req; - struct tevent_req *req_send; bool dp_success; errno_t ret; @@ -499,25 +498,12 @@ static void cache_req_search_domains_done(struct tevent_req *subreq) break; case ENOENT: if (state->check_next == false) { - /* Lookup domain was specified as input. - * We don't want to try the next domain, - * but we may want to try UPN search. */ - - if (cache_req_assume_upn(state->cr)) { - /* Here we need to access the request created by cache_req_send() - * in order to pass it down to cache_req_select_domains() */ - req_send = tevent_req_callback_data(req, struct tevent_req); - - /* Try UPN now. */ - ret = cache_req_select_domains(req_send, NULL); - goto done; - } - /* Not found. */ ret = ENOENT; goto done; } + /* Continue with next domain. */ break; default: /* Some serious error has happened. Finish. */ @@ -565,14 +551,68 @@ cache_req_search_domains_recv(TALLOC_CTX *mem_ctx, return EOK; } +/** + * Return true if we should issue another search. + */ +static bool cache_req_search_schema(struct cache_req *cr, + const char *input_domain, + bool first_iteration, + bool *_bypass_cache, + bool *_bypass_dp) +{ + bool bypass_cache; + bool bypass_dp; + + if (cr->bypass_cache) { + /* The caller wants to contact Data Provider first + * or it is inferred by cache_req plug-in. */ + bypass_cache = true; + bypass_dp = false; + + if (!first_iteration) { + return false; + } + } else if (input_domain != NULL) { + /* We will search only one domain. */ + bypass_cache = false; + bypass_dp = false; + + if (!first_iteration) { + return false; + } + } else if (!cr->cache_first) { + /* We will search cache and on cache-miss + * contact domain provider sequentially. */ + bypass_cache = false; + bypass_dp = false; + + if (!first_iteration) { + return false; + } + } else { + /* We will first search the cache in all domains. If we don't get + * any match we will then contact Data Provider starting with the + * first domain again. */ + bypass_cache = first_iteration ? false : true; + bypass_dp = first_iteration ? true : false; + } + + *_bypass_cache = bypass_cache; + *_bypass_dp = bypass_dp; + + return true; +} + struct cache_req_state { /* input data */ struct tevent_context *ev; struct cache_req *cr; + const char *domain_name; /* work data */ struct cache_req_result **results; size_t num_results; + bool first_iteration; }; static errno_t cache_req_process_input(TALLOC_CTX *mem_ctx, @@ -582,9 +622,14 @@ static errno_t cache_req_process_input(TALLOC_CTX *mem_ctx, static void cache_req_input_parsed(struct tevent_req *subreq); +static errno_t cache_req_select_domains(struct tevent_req *req, + const char *domain_name); + static errno_t cache_req_search_domains(struct tevent_req *req, struct sss_domain_info *domain, - bool check_next); + bool check_next, + bool bypass_cache, + bool bypass_dp); static void cache_req_done(struct tevent_req *subreq); @@ -614,6 +659,7 @@ struct tevent_req *cache_req_send(TALLOC_CTX *mem_ctx, ret = ENOMEM; goto done; } + state->first_iteration = true; CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "New request '%s'\n", cr->reqname); @@ -631,6 +677,7 @@ struct tevent_req *cache_req_send(TALLOC_CTX *mem_ctx, goto done; } + state->domain_name = domain; ret = cache_req_select_domains(req, domain); done: @@ -719,6 +766,7 @@ static void cache_req_input_parsed(struct tevent_req *subreq) return; } + state->domain_name = domain; ret = cache_req_select_domains(req, domain); if (ret != EAGAIN) { tevent_req_error(req, ret); @@ -732,9 +780,20 @@ static errno_t cache_req_select_domains(struct tevent_req *req, struct cache_req_state *state = NULL; struct sss_domain_info *domain; bool check_next; + bool bypass_cache; + bool bypass_dp; + bool search; state = tevent_req_data(req, struct cache_req_state); + search = cache_req_search_schema(state->cr, domain_name, + state->first_iteration, + &bypass_cache, &bypass_dp); + if (!search) { + /* We're done here. */ + return EOK; + } + if (domain_name != NULL) { CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr, "Performing a single domain search\n"); @@ -753,20 +812,28 @@ static errno_t cache_req_select_domains(struct tevent_req *req, check_next = true; } - return cache_req_search_domains(req, domain, check_next); + return cache_req_search_domains(req, domain, check_next, + bypass_cache, bypass_dp); } static errno_t cache_req_search_domains(struct tevent_req *req, struct sss_domain_info *domain, - bool check_next) + bool check_next, + bool bypass_cache, + bool bypass_dp) { struct tevent_req *subreq; struct cache_req_state *state = NULL; state = tevent_req_data(req, struct cache_req_state); + CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr, + "Search will %s the cache and %s the data provider\n", + bypass_cache ? "bypass" : "check", + bypass_dp ? "bypass" : "check"); + subreq = cache_req_search_domains_send(state, state->ev, state->cr, domain, - check_next); + check_next, bypass_cache, bypass_dp); if (subreq == NULL) { return ENOMEM; } @@ -787,6 +854,28 @@ static void cache_req_done(struct tevent_req *subreq) ret = cache_req_search_domains_recv(state, subreq, &state->results); talloc_zfree(subreq); + if (ret == ENOENT && state->first_iteration) { + /* Try again different search schema. */ + state->first_iteration = false; + ret = cache_req_select_domains(req, state->domain_name); + if (ret == EOK) { + /* We're done searching and we have found nothing. */ + ret = ENOENT; + + if (state->domain_name != NULL) { + /* Lookup domain was specified as input. Since we haven't + * found anything yet we may want to try UPN search with + * some plug-ins. */ + + if (cache_req_assume_upn(state->cr)) { + /* Try UPN now. */ + state->first_iteration = true; + ret = cache_req_select_domains(req, NULL); + } + } + } + } + switch (ret) { case EOK: CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr, "Finished: Success\n"); diff --git a/src/responder/common/cache_req/cache_req_private.h b/src/responder/common/cache_req/cache_req_private.h index adde06b84..2d3c18707 100644 --- a/src/responder/common/cache_req/cache_req_private.h +++ b/src/responder/common/cache_req/cache_req_private.h @@ -40,6 +40,8 @@ struct cache_req { /* Domain related informations. */ struct sss_domain_info *domain; + bool cache_first; + bool bypass_cache; /* Debug information */ uint32_t reqid; @@ -91,7 +93,9 @@ struct cache_req_data { struct tevent_req * cache_req_search_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct cache_req *cr); + struct cache_req *cr, + bool bypass_cache, + bool bypass_dp); errno_t cache_req_search_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, diff --git a/src/responder/common/cache_req/cache_req_search.c b/src/responder/common/cache_req/cache_req_search.c index 612f194d9..2205ae1a5 100644 --- a/src/responder/common/cache_req/cache_req_search.c +++ b/src/responder/common/cache_req/cache_req_search.c @@ -181,7 +181,9 @@ static void cache_req_search_done(struct tevent_req *subreq); struct tevent_req * cache_req_search_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct cache_req *cr) + struct cache_req *cr, + bool bypass_cache, + bool bypass_dp) { struct cache_req_search_state *state; enum cache_object_status status; @@ -214,7 +216,7 @@ cache_req_search_send(TALLOC_CTX *mem_ctx, */ state->result = NULL; status = CACHE_OBJECT_MISSING; - if (!cr->plugin->bypass_cache && !cr->data->bypass_cache) { + if (!bypass_cache) { ret = cache_req_search_cache(state, cr, &state->result); if (ret != EOK && ret != ENOENT) { goto done; @@ -229,7 +231,10 @@ cache_req_search_send(TALLOC_CTX *mem_ctx, } } - ret = cache_req_search_dp(req, status); + if (!bypass_dp) { + ret = cache_req_search_dp(req, status); + } + if (ret != EAGAIN) { goto done; } diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h index 5717d6a82..4d1048a1e 100644 --- a/src/responder/common/responder.h +++ b/src/responder/common/responder.h @@ -138,6 +138,7 @@ struct resp_ctx { bool shutting_down; bool socket_activated; bool dbus_activated; + bool cache_first; }; struct cli_creds; diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c index 5c59f0d8f..76f436096 100644 --- a/src/responder/common/responder_common.c +++ b/src/responder/common/responder_common.c @@ -1101,6 +1101,17 @@ int sss_process_init(TALLOC_CTX *mem_ctx, } } + ret = confdb_get_bool(rctx->cdb, rctx->confdb_service_path, + CONFDB_RESPONDER_CACHE_FIRST, + false, &rctx->cache_first); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Cannot get \"cache_first_option\".\n" + "Querying the caches first before querying the " + "Data Providers will not be enforced [%d]: %s.\n", + ret, sss_strerror(ret)); + } + ret = confdb_get_int(rctx->cdb, rctx->confdb_service_path, CONFDB_RESPONDER_GET_DOMAINS_TIMEOUT, GET_DOMAINS_DEFAULT_TIMEOUT, &rctx->domains_timeout); |
