diff options
-rw-r--r-- | server/examples/sssd.conf | 9 | ||||
-rw-r--r-- | server/man/sssd.conf.5.xml | 13 | ||||
-rw-r--r-- | server/responder/nss/nsssrv.c | 16 | ||||
-rw-r--r-- | server/responder/nss/nsssrv.h | 4 | ||||
-rw-r--r-- | server/responder/nss/nsssrv_cmd.c | 35 |
5 files changed, 75 insertions, 2 deletions
diff --git a/server/examples/sssd.conf b/server/examples/sssd.conf index 90e0c8d1..b47ab9dd 100644 --- a/server/examples/sssd.conf +++ b/server/examples/sssd.conf @@ -13,6 +13,15 @@ description = NSS Responder Configuration filterGroups = root filterUsers = root +# The EntryCacheTimeout indicates the number of seconds to retain before +# an entry in cache is considered stale and must block to refresh. +# The EntryCacheNoWaitRefreshTimeout indicates the number of seconds to +# wait before updating the cache out-of-band. (NSS requests will still +# be returned from cache until the full EntryCacheTimeout). Setting this +# value to 0 turns this feature off (default) +; EntryCacheTimeout = 600 +; EntryCacheNoWaitRefreshTimeout = 300 + [services/dp] description = Data Provider Configuration diff --git a/server/man/sssd.conf.5.xml b/server/man/sssd.conf.5.xml index b64899a0..827dd96b 100644 --- a/server/man/sssd.conf.5.xml +++ b/server/man/sssd.conf.5.xml @@ -336,6 +336,19 @@ </listitem> </varlistentry> <varlistentry> + <term>EntryCacheNoWaitRefreshTimeout (integer)</term> + <listitem> + <para> + How long should nss_sss return cached entries before + initiating an out-of-band cache refresh (0 disables + this feature) + </para> + <para> + Default: 0 + </para> + </listitem> + </varlistentry> + <varlistentry> <term>EntryNegativeTimeout (integer)</term> <listitem> <para> diff --git a/server/responder/nss/nsssrv.c b/server/responder/nss/nsssrv.c index ad804389..3920189a 100644 --- a/server/responder/nss/nsssrv.c +++ b/server/responder/nss/nsssrv.c @@ -107,6 +107,22 @@ static int nss_get_config(struct nss_ctx *nctx, &nctx->filter_users_in_groups); if (ret != EOK) goto done; + + ret = confdb_get_int(cdb, nctx, NSS_SRV_CONFIG, + "EntryCacheNoWaitRefreshTimeout", 0, + &nctx->cache_refresh_timeout); + if (ret != EOK) goto done; + if (nctx->cache_refresh_timeout >= nctx->cache_timeout) { + DEBUG(0,("Configuration error: EntryCacheNoWaitRefreshTimeout exceeds" + "EntryCacheTimeout. Disabling feature.\n")); + nctx->cache_refresh_timeout = 0; + } + if (nctx->cache_refresh_timeout < 0) { + DEBUG(0,("Configuration error: EntryCacheNoWaitRefreshTimeout is" + "invalid. Disabling feature.\n")); + nctx->cache_refresh_timeout = 0; + } + ret = confdb_get_string_as_list(cdb, tmpctx, NSS_SRV_CONFIG, "filterUsers", &filter_list); if (ret == ENOENT) filter_list = NULL; diff --git a/server/responder/nss/nsssrv.h b/server/responder/nss/nsssrv.h index c5a7bb30..a5adbaf8 100644 --- a/server/responder/nss/nsssrv.h +++ b/server/responder/nss/nsssrv.h @@ -46,10 +46,12 @@ struct getent_ctx; struct nss_ctx { struct resp_ctx *rctx; - int cache_timeout; int neg_timeout; struct nss_nc_ctx *ncache; + int cache_timeout; + int cache_refresh_timeout; + int enum_cache_timeout; time_t last_user_enum; time_t last_group_enum; diff --git a/server/responder/nss/nsssrv_cmd.c b/server/responder/nss/nsssrv_cmd.c index 3b0f867e..92600933 100644 --- a/server/responder/nss/nsssrv_cmd.c +++ b/server/responder/nss/nsssrv_cmd.c @@ -278,26 +278,50 @@ static errno_t check_cache(struct nss_dom_ctx *dctx, { errno_t ret; int timeout; + int refresh_timeout; time_t now; uint64_t lastUpdate; struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct cli_ctx *cctx = cmdctx->cctx; bool call_provider = false; + sss_dp_callback_t cb = NULL; if (dctx->check_provider) { switch (res->count) { case 0: + /* This is a cache miss. We need to get the updated user + * information before returning it. + */ call_provider = true; + cb = callback; break; case 1: timeout = nctx->cache_timeout; + refresh_timeout = nctx->cache_refresh_timeout; now = time(NULL); lastUpdate = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_LAST_UPDATE, 0); if (lastUpdate + timeout < now) { + /* This is a cache miss. We need to get the updated user + * information before returning it. + */ call_provider = true; + cb = callback; + } + else if (refresh_timeout && (lastUpdate + refresh_timeout < now)) { + /* We're past the the cache refresh timeout + * We'll return the value from the cache, but we'll also + * queue the cache entry for update out-of-band. + */ + call_provider = true; + cb = NULL; + } + else { + /* Cache is still valid. Just return it. */ + call_provider = false; + cb = NULL; } break; @@ -340,7 +364,16 @@ static errno_t check_cache(struct nss_dom_ctx *dctx, /* Tell the calling function to return so the dp callback * can resolve */ - return EAGAIN; + if (cb) { + return EAGAIN; + } + + /* No callback required + * This was an out-of-band update. We'll return EOK + * so the calling function can return the cached entry + * immediately. + */ + DEBUG(3, ("Updating cache out-of-band\n")); } return EOK; |