Hello,

I think it could be useful to store the corrupted memory cache
before reset. We have very little info about what was really
wrong in the cache when it was in inconsistent state. This way we
could ask users to send us copy of the corrupted cache if they
hit this issue. It could provide some more answers.

Patch is attached. It stores the corrupted cache in
/var/lib/sss/mc/<cache_name>_corrupted.

Thanks
Michal
>From babd61e49fef092fc2d5b85241b1b6bf003df68a Mon Sep 17 00:00:00 2001
From: Michal Zidek <[email protected]>
Date: Mon, 12 Aug 2013 16:23:59 +0200
Subject: [PATCH] mmap_cache: Store corrupted mmap cache before reset

This patch adds function to store corrupted mmap cache file to
disk for further analysis.
---
 src/responder/nss/nsssrv_mmap_cache.c | 63 +++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c
index cd5a643..8cc2916 100644
--- a/src/responder/nss/nsssrv_mmap_cache.c
+++ b/src/responder/nss/nsssrv_mmap_cache.c
@@ -93,6 +93,65 @@ struct sss_mc_ctx {
     else used = false; \
 } while (0)
 
+/* This function will store corrupted memcache to disk for later
+ * analysis. */
+static void  sss_mc_save_corrupted(struct sss_mc_ctx *mc_ctx)
+{
+    int err;
+    int fd = -1;
+    ssize_t written;
+    char *file = NULL;
+    TALLOC_CTX *tmp_ctx;
+
+    if (mc_ctx == NULL) {
+        DEBUG(SSSDBG_TRACE_FUNC,
+              ("Cannot store uninitialized cache. Nothing to do.\n"));
+        return;
+    }
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory.\n"));
+        return;
+    }
+
+    file = talloc_asprintf(tmp_ctx, "%s_%s",
+                           mc_ctx->file, "corrupted");
+    if (file == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory.\n"));
+        goto done;
+    }
+
+    /* We will always store only the last problematic cache state */
+    fd = creat(file, 0600);
+    if (fd == -1) {
+        err = errno;
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              ("Failed to open file '%s' [%d]: %s\n",
+               file, err, strerror(err)));
+        goto done;
+    }
+
+    written = write(fd, mc_ctx->mmap_base, mc_ctx->mmap_size);
+    if (written != mc_ctx->mmap_size) {
+        if (written == -1) {
+            err = errno;
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  ("write() failed [%d]: %s\n", err, strerror(err)));
+        } else {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  ("write() returned %zd (expected (%zd))\n",
+                   written, mc_ctx->mmap_size));
+        }
+    }
+
+done:
+    if (fd != -1) {
+        close(fd);
+    }
+    talloc_free(tmp_ctx);
+}
+
 static uint32_t sss_mc_hash(struct sss_mc_ctx *mcc,
                             const char *key, size_t len)
 {
@@ -376,6 +435,7 @@ static struct sss_mc_rec *sss_mc_find_record(struct sss_mc_ctx *mcc,
         if (slot > MC_SIZE_TO_SLOTS(mcc->dt_size)) {
             DEBUG(SSSDBG_FATAL_FAILURE,
                   ("Corrupted fastcache. Slot number too big.\n"));
+            sss_mc_save_corrupted(mcc);
             sss_mmap_cache_reset(mcc);
             return NULL;
         }
@@ -387,6 +447,7 @@ static struct sss_mc_rec *sss_mc_find_record(struct sss_mc_ctx *mcc,
         if (name_ptr != offsetof(struct sss_mc_pwd_data, strs)) {
             DEBUG(SSSDBG_FATAL_FAILURE,
                   ("Corrupted fastcache. name_ptr value is %u.\n", name_ptr));
+            sss_mc_save_corrupted(mcc);
             sss_mmap_cache_reset(mcc);
             return NULL;
         }
@@ -625,6 +686,7 @@ errno_t sss_mmap_cache_pw_invalidate_uid(struct sss_mc_ctx *mcc, uid_t uid)
     while (slot != MC_INVALID_VAL) {
         if (slot > MC_SIZE_TO_SLOTS(mcc->dt_size)) {
             DEBUG(SSSDBG_FATAL_FAILURE, ("Corrupted fastcache.\n"));
+            sss_mc_save_corrupted(mcc);
             sss_mmap_cache_reset(mcc);
             ret = ENOENT;
             goto done;
@@ -763,6 +825,7 @@ errno_t sss_mmap_cache_gr_invalidate_gid(struct sss_mc_ctx *mcc, gid_t gid)
     while (slot != MC_INVALID_VAL) {
         if (slot > MC_SIZE_TO_SLOTS(mcc->dt_size)) {
             DEBUG(SSSDBG_FATAL_FAILURE, ("Corrupted fastcache.\n"));
+            sss_mc_save_corrupted(mcc);
             sss_mmap_cache_reset(mcc);
             ret = ENOENT;
             goto done;
-- 
1.7.11.2

_______________________________________________
sssd-devel mailing list
[email protected]
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to