From 99c99e557020775714f028b28a147edda290c783 Mon Sep 17 00:00:00 2001 From: Michal Zidek Date: Tue, 11 Sep 2012 18:44:52 +0200 Subject: sss_cache tool invalidates records in memory cache. --- src/monitor/monitor.c | 12 +++++- src/monitor/monitor_interfaces.h | 1 + src/responder/nss/nsssrv.c | 77 ++++++++++++++++++++++++++++++++++- src/responder/nss/nsssrv_mmap_cache.c | 46 +++++++++++++++++++++ src/responder/nss/nsssrv_mmap_cache.h | 5 +++ src/tools/sss_cache.c | 26 ++++++++++++ src/util/util.h | 2 + 7 files changed, 166 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c index 50b2e9523..a94227878 100644 --- a/src/monitor/monitor.c +++ b/src/monitor/monitor.c @@ -51,6 +51,7 @@ #include "dbus/dbus.h" #include "sbus/sssd_dbus.h" #include "monitor/monitor_interfaces.h" +#include "responder/nss/nsssrv.h" #ifdef USE_KEYRING #include @@ -701,6 +702,10 @@ static int service_signal_rotate(struct mt_svc *svc) { return service_signal(svc, MON_CLI_METHOD_ROTATE); } +static int service_signal_clear_memcache(struct mt_svc *svc) +{ + return service_signal(svc, MON_CLI_METHOD_CLEAR_MEMCACHE); +} static int check_domain_ranges(struct sss_domain_info *domains) { @@ -1177,10 +1182,15 @@ static void monitor_hup(struct tevent_context *ev, DEBUG(1, ("Received SIGHUP.\n")); - /* Signal all services to rotate debug files */ + /* Send D-Bus message to other services to rotate their logs. + * NSS service receives also message to clear memory caches. */ for(cur_svc = ctx->svc_list; cur_svc; cur_svc = cur_svc->next) { service_signal_rotate(cur_svc); + if (!strcmp(NSS_SBUS_SERVICE_NAME, cur_svc->name)) { + service_signal_clear_memcache(cur_svc); + } } + } static int monitor_cleanup(void) diff --git a/src/monitor/monitor_interfaces.h b/src/monitor/monitor_interfaces.h index 51ac254cd..abe905035 100644 --- a/src/monitor/monitor_interfaces.h +++ b/src/monitor/monitor_interfaces.h @@ -45,6 +45,7 @@ #define MON_CLI_METHOD_OFFLINE "goOffline" /* Applicable only to providers */ #define MON_CLI_METHOD_RESET_OFFLINE "resetOffline" /* Applicable only to providers */ #define MON_CLI_METHOD_ROTATE "rotateLogs" +#define MON_CLI_METHOD_CLEAR_MEMCACHE "clearMemcache" #define SSSD_SERVICE_PIPE "private/sbus-monitor" diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c index 64267e868..5fa72494e 100644 --- a/src/responder/nss/nsssrv.c +++ b/src/responder/nss/nsssrv.c @@ -51,10 +51,14 @@ #define SHELL_REALLOC_INCREMENT 5 #define SHELL_REALLOC_MAX 50 +static int nss_clear_memcache(DBusMessage *message, + struct sbus_connection *conn); + struct sbus_method monitor_nss_methods[] = { { MON_CLI_METHOD_PING, monitor_common_pong }, { MON_CLI_METHOD_RES_INIT, monitor_common_res_init }, { MON_CLI_METHOD_ROTATE, responder_logrotate }, + { MON_CLI_METHOD_CLEAR_MEMCACHE, nss_clear_memcache}, { NULL, NULL } }; @@ -66,6 +70,65 @@ struct sbus_interface monitor_nss_interface = { NULL }; +static int nss_clear_memcache(DBusMessage *message, + struct sbus_connection *conn) +{ + errno_t ret; + int memcache_timeout; + struct resp_ctx *rctx = talloc_get_type(sbus_conn_get_private_data(conn), + struct resp_ctx); + struct nss_ctx *nctx = (struct nss_ctx*) rctx->pvt_ctx; + + ret = unlink(SSS_NSS_MCACHE_DIR"/"CLEAR_MC_FLAG); + if (ret != 0) { + ret = errno; + if (ret == ENOENT) { + DEBUG(SSSDBG_TRACE_FUNC, + ("CLEAR_MC_FLAG not found. Nothing to do.\n")); + goto done; + } else { + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to unlink file: %s.\n", + strerror(ret))); + return ret; + } + } + + /* CLEAR_MC_FLAG removed successfully. Clearing memory caches. */ + + ret = confdb_get_int(rctx->cdb, + CONFDB_NSS_CONF_ENTRY, + CONFDB_MEMCACHE_TIMEOUT, + 300, &memcache_timeout); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, + ("Unable to get memory cache entry timeout.\n")); + return ret; + } + + /* TODO: read cache sizes from configuration */ + DEBUG(SSSDBG_TRACE_FUNC, ("Clearing memory caches.\n")); + ret = sss_mmap_cache_reinit(nctx, SSS_MC_CACHE_ELEMENTS, + (time_t) memcache_timeout, + &nctx->pwd_mc_ctx); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("passwd mmap cache invalidation failed\n")); + return ret; + } + + ret = sss_mmap_cache_reinit(nctx, SSS_MC_CACHE_ELEMENTS, + (time_t) memcache_timeout, + &nctx->grp_mc_ctx); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("group mmap cache invalidation failed\n")); + return ret; + } + +done: + return monitor_common_pong(message, conn); +} + static errno_t nss_get_etc_shells(TALLOC_CTX *mem_ctx, char ***_shells) { int i = 0; @@ -328,6 +391,16 @@ int nss_process_init(TALLOC_CTX *mem_ctx, } /* create mmap caches */ + /* Remove the CLEAR_MC_FLAG file if exists. */ + ret = unlink(SSS_NSS_MCACHE_DIR"/"CLEAR_MC_FLAG); + if (ret != 0 && errno != ENOENT) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, + ("Failed to unlink file [%s]. This can cause memory cache to " + "be purged when next log rotation is requested. %d: %s\n", + SSS_NSS_MCACHE_DIR"/"CLEAR_MC_FLAG, ret, strerror(ret))); + } + ret = confdb_get_int(nctx->rctx->cdb, CONFDB_NSS_CONF_ENTRY, CONFDB_MEMCACHE_TIMEOUT, @@ -339,14 +412,14 @@ int nss_process_init(TALLOC_CTX *mem_ctx, /* TODO: read cache sizes from configuration */ ret = sss_mmap_cache_init(nctx, "passwd", SSS_MC_PASSWD, - 50000, (time_t)memcache_timeout, + SSS_MC_CACHE_ELEMENTS, (time_t)memcache_timeout, &nctx->pwd_mc_ctx); if (ret) { DEBUG(SSSDBG_CRIT_FAILURE, ("passwd mmap cache is DISABLED\n")); } ret = sss_mmap_cache_init(nctx, "group", SSS_MC_GROUP, - 50000, (time_t)memcache_timeout, + SSS_MC_CACHE_ELEMENTS, (time_t)memcache_timeout, &nctx->grp_mc_ctx); if (ret) { DEBUG(SSSDBG_CRIT_FAILURE, ("group mmap cache is DISABLED\n")); diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c index 07498a9b7..f40256472 100644 --- a/src/responder/nss/nsssrv_mmap_cache.c +++ b/src/responder/nss/nsssrv_mmap_cache.c @@ -725,3 +725,49 @@ done: return ret; } +errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx, size_t n_elem, + time_t timeout, struct sss_mc_ctx **mc_ctx) +{ + errno_t ret; + TALLOC_CTX* tmp_ctx = NULL; + char *name; + enum sss_mc_type type; + + if (mc_ctx == NULL || (*mc_ctx) == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Unable to re-init unitialized memory cache.\n")); + return EINVAL; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory.\n")); + return ENOMEM; + } + + name = talloc_strdup(tmp_ctx, (*mc_ctx)->name); + if (name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory.\n")); + ret = ENOMEM; + goto done; + } + + type = (*mc_ctx)->type; + ret = talloc_free(*mc_ctx); + if (ret != 0) { + /* This can happen only if destructor is associated with this + * context */ + DEBUG(SSSDBG_MINOR_FAILURE, ("Destructor asociated with memory" + " context failed.\n")); + } + + ret = sss_mmap_cache_init(mem_ctx, name, type, n_elem, timeout, mc_ctx); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to re-initialize mmap cache.\n")); + goto done; + } + +done: + talloc_free(tmp_ctx); + return ret; +} diff --git a/src/responder/nss/nsssrv_mmap_cache.h b/src/responder/nss/nsssrv_mmap_cache.h index 81241b24d..2a0712c88 100644 --- a/src/responder/nss/nsssrv_mmap_cache.h +++ b/src/responder/nss/nsssrv_mmap_cache.h @@ -22,6 +22,8 @@ #ifndef _NSSSRV_MMAP_CACHE_H_ #define _NSSSRV_MMAP_CACHE_H_ +#define SSS_MC_CACHE_ELEMENTS 50000 + struct sss_mc_ctx; enum sss_mc_type { @@ -48,4 +50,7 @@ errno_t sss_mmap_cache_gr_store(struct sss_mc_ctx *mcc, gid_t gid, size_t memnum, char *membuf, size_t memsize); +errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx, size_t n_elem, + time_t timeout, struct sss_mc_ctx **mc_ctx); + #endif /* _NSSSRV_MMAP_CACHE_H_ */ diff --git a/src/tools/sss_cache.c b/src/tools/sss_cache.c index 950ff1c16..73d99651b 100644 --- a/src/tools/sss_cache.c +++ b/src/tools/sss_cache.c @@ -100,6 +100,7 @@ int main(int argc, const char *argv[]) struct sysdb_ctx *sysdb; int i; bool skipped; + FILE *clear_mc_flag; ret = init_context(argc, argv, &tctx); if (ret != EOK) { @@ -141,6 +142,31 @@ int main(int argc, const char *argv[]) ERROR("No cache object matched the specified search\n"); ret = ENOENT; goto done; + } else { + /*Local cache changed -> signal monitor to invalidate fastcache */ + clear_mc_flag = fopen(SSS_NSS_MCACHE_DIR"/"CLEAR_MC_FLAG, "w"); + if (clear_mc_flag == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Failed to create clear_mc_flag file. " + "Memory cache will not be cleared.\n")); + goto done; + } + ret = fclose(clear_mc_flag); + if (ret != 0) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, + ("Unable to close file descriptor: %s\n", + strerror(ret))); + goto done; + } + + DEBUG(SSSDBG_TRACE_FUNC, ("Sending SIGHUP to monitor.\n")); + ret = signal_sssd(SIGHUP); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Failed to send SIGHUP to monitor.\n")); + goto done; + } } } diff --git a/src/util/util.h b/src/util/util.h index 685702fc9..df739ab6c 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -54,6 +54,8 @@ typedef int errno_t; #define ENUM_INDICATOR "*" +#define CLEAR_MC_FLAG "clear_mc_flag" + extern const char *debug_prg_name; extern int debug_level; extern int debug_timestamps; -- cgit