From 304ce93959464f3867296f596c25d3158737879f Mon Sep 17 00:00:00 2001 From: Michal Zidek Date: Nov 06 2012 11:31:54 +0000 Subject: sss_cache: Remove fastcache even if sssd is not running. https://fedorahosted.org/sssd/ticket/1584 --- diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c index f402564..524aa47 100644 --- a/src/responder/nss/nsssrv_mmap_cache.c +++ b/src/responder/nss/nsssrv_mmap_cache.c @@ -537,14 +537,21 @@ static errno_t sss_mc_create_file(struct sss_mc_ctx *mc_ctx) mode_t old_mask; int ofd; int ret; + useconds_t t = 50000; + int retries = 3; ofd = open(mc_ctx->file, O_RDWR); if (ofd != -1) { + ret = sss_br_lock_file(ofd, 0, 1, retries, t); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, + ("Failed to lock file %s.\n", mc_ctx->file)); + } ret = sss_mc_set_recycled(ofd); if (ret) { - DEBUG(SSSDBG_TRACE_FUNC, ("Failed to mark mmap file %s as" - " recycled: %d(%s)\n", - mc_ctx->file, ret, strerror(ret))); + DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to mark mmap file %s as" + " recycled: %d(%s)\n", + mc_ctx->file, ret, strerror(ret))); } close(ofd); @@ -568,11 +575,24 @@ static errno_t sss_mc_create_file(struct sss_mc_ctx *mc_ctx) ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to open mmap file %s: %d(%s)\n", mc_ctx->file, ret, strerror(ret))); + goto done; + } + + ret = sss_br_lock_file(mc_ctx->fd, 0, 1, retries, t); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, + ("Failed to lock file %s.\n", mc_ctx->file)); + goto done; } +done: /* reset mask back */ umask(old_mask); + if (ret) { + close(mc_ctx->fd); + } + return ret; } diff --git a/src/tools/sss_cache.c b/src/tools/sss_cache.c index 8582fb5..267b8ac 100644 --- a/src/tools/sss_cache.c +++ b/src/tools/sss_cache.c @@ -92,6 +92,7 @@ errno_t invalidate_entry(TALLOC_CTX *ctx, struct sysdb_ctx *sysdb, bool invalidate_entries(TALLOC_CTX *ctx, struct sysdb_ctx *sysdb, enum sss_cache_entry entry_type, const char *filter, const char *name); +static int clear_fastcache(bool *sssd_nss_is_off); int main(int argc, const char *argv[]) { @@ -99,6 +100,7 @@ int main(int argc, const char *argv[]) struct cache_tool_ctx *tctx = NULL; struct sysdb_ctx *sysdb; int i; + bool sssd_nss_is_off; bool skipped = true; FILE *clear_mc_flag; @@ -143,29 +145,36 @@ int main(int argc, const char *argv[]) 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")); + ret = clear_fastcache(&sssd_nss_is_off); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to clear caches.\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; - } + if (!sssd_nss_is_off) { + /* sssd_nss is running -> 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; + 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; + } } } @@ -174,6 +183,33 @@ done: return ret; } +static int clear_fastcache(bool *sssd_nss_is_off) +{ + int ret; + ret = sss_memcache_invalidate(SSS_NSS_MCACHE_DIR"/passwd"); + if (ret != EOK) { + if (ret == EACCES) { + *sssd_nss_is_off = false; + return EOK; + } else { + return ret; + } + } + + ret = sss_memcache_invalidate(SSS_NSS_MCACHE_DIR"/group"); + if (ret != EOK) { + if (ret == EACCES) { + *sssd_nss_is_off = false; + return EOK; + } else { + return ret; + } + } + + *sssd_nss_is_off = true; + return EOK; +} + bool invalidate_entries(TALLOC_CTX *ctx, struct sysdb_ctx *sysdb, enum sss_cache_entry entry_type, const char *filter, const char *name) diff --git a/src/tools/tools_util.c b/src/tools/tools_util.c index 049a4f5..99b79f1 100644 --- a/src/tools/tools_util.c +++ b/src/tools/tools_util.c @@ -35,6 +35,7 @@ #include "db/sysdb.h" #include "tools/tools_util.h" #include "tools/sss_sync_ops.h" +#include "util/mmap_cache.h" static int setup_db(struct tools_ctx *ctx) { @@ -671,3 +672,96 @@ errno_t signal_sssd(int signum) return EOK; } + +static errno_t sss_mc_set_recycled(int fd) +{ + uint32_t w = SSS_MC_HEADER_RECYCLED; + struct sss_mc_header h; + off_t offset; + off_t pos; + int ret; + + + offset = MC_PTR_DIFF(&h.status, &h); + + pos = lseek(fd, offset, SEEK_SET); + if (pos == -1) { + /* What do we do now ? */ + return errno; + } + + errno = 0; + ret = sss_atomic_write_s(fd, (uint8_t *)&w, sizeof(h.status)); + if (ret == -1) { + return errno; + } + + if (ret != sizeof(h.status)) { + /* Write error */ + return EIO; + } + + return EOK; +} + +errno_t sss_memcache_invalidate(const char *mc_filename) +{ + int mc_fd = -1; + errno_t ret; + errno_t pret; + useconds_t t = 50000; + int retries = 2; + + if (!mc_filename) { + return EINVAL; + } + + mc_fd = open(mc_filename, O_RDWR); + if (mc_fd == -1) { + ret = errno; + if (ret == ENOENT) { + DEBUG(SSSDBG_TRACE_FUNC,("Memory cache file %s " + "does not exist.\n", mc_filename)); + return EOK; + } else { + DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to open file %s: %s\n", + mc_filename, strerror(ret))); + return ret; + } + } + + ret = sss_br_lock_file(mc_fd, 0, 1, retries, t); + if (ret == EACCES) { + DEBUG(SSSDBG_TRACE_FUNC, + ("File %s already locked by someone else.\n", mc_filename)); + goto done; + } else if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to lock file %s.\n", mc_filename)); + goto done; + } + /* Mark the mc file as recycled. */ + ret = sss_mc_set_recycled(mc_fd); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to mark memory cache file %s " + "as recycled.\n", mc_filename)); + goto done; + } + + ret = EOK; +done: + if (mc_fd != -1) { + /* Closing the file also releases the lock */ + close(mc_fd); + + /* Only unlink the file if invalidation was succesful */ + if (ret == EOK) { + pret = unlink(mc_filename); + if (pret == -1) { + DEBUG(SSSDBG_MINOR_FAILURE, + ("Failed to unlink file %s. " + "Will be unlinked later by sssd_nss.\n")); + } + } + } + return ret; +} diff --git a/src/tools/tools_util.h b/src/tools/tools_util.h index 1be17e8..a83c8ee 100644 --- a/src/tools/tools_util.h +++ b/src/tools/tools_util.h @@ -104,6 +104,8 @@ int run_userdel_cmd(struct tools_ctx *tctx); errno_t signal_sssd(int signum); +errno_t sss_memcache_invalidate(const char *mc_filename); + /* from files.c */ int remove_tree(const char *root);