Print this page
9525 kmem_dump_size is a corrupting influence

@@ -2209,37 +2209,10 @@
 
 #define KMEM_DUMPCTL(cp, buf)   \
         ((kmem_dumpctl_t *)P2ROUNDUP((uintptr_t)(buf) + (cp)->cache_bufsize, \
             sizeof (void *)))
 
-/* Keep some simple stats. */
-#define KMEM_DUMP_LOGS  (100)
-
-typedef struct kmem_dump_log {
-        kmem_cache_t    *kdl_cache;
-        uint_t          kdl_allocs;             /* # of dump allocations */
-        uint_t          kdl_frees;              /* # of dump frees */
-        uint_t          kdl_alloc_fails;        /* # of allocation failures */
-        uint_t          kdl_free_nondump;       /* # of non-dump frees */
-        uint_t          kdl_unsafe;             /* cache was used, but unsafe */
-} kmem_dump_log_t;
-
-static kmem_dump_log_t *kmem_dump_log;
-static int kmem_dump_log_idx;
-
-#define KDI_LOG(cp, stat) {                                             \
-        kmem_dump_log_t *kdl;                                           \
-        if ((kdl = (kmem_dump_log_t *)((cp)->cache_dumplog)) != NULL) { \
-                kdl->stat++;                                            \
-        } else if (kmem_dump_log_idx < KMEM_DUMP_LOGS) {                \
-                kdl = &kmem_dump_log[kmem_dump_log_idx++];              \
-                kdl->stat++;                                            \
-                kdl->kdl_cache = (cp);                                  \
-                (cp)->cache_dumplog = kdl;                              \
-        }                                                               \
-}
-
 /* set non zero for full report */
 uint_t kmem_dump_verbose = 0;
 
 /* stats for overize heap */
 uint_t kmem_dump_oversize_allocs = 0;

@@ -2265,29 +2238,21 @@
  * Called when dumpadm(1M) configures dump parameters.
  */
 void
 kmem_dump_init(size_t size)
 {
+        /* Our caller ensures size is always set. */
+        ASSERT3U(size, >, 0);
+
         if (kmem_dump_start != NULL)
                 kmem_free(kmem_dump_start, kmem_dump_size);
 
-        if (kmem_dump_log == NULL)
-                kmem_dump_log = (kmem_dump_log_t *)kmem_zalloc(KMEM_DUMP_LOGS *
-                    sizeof (kmem_dump_log_t), KM_SLEEP);
-
         kmem_dump_start = kmem_alloc(size, KM_SLEEP);
-
-        if (kmem_dump_start != NULL) {
                 kmem_dump_size = size;
                 kmem_dump_curr = kmem_dump_start;
                 kmem_dump_end = (void *)((char *)kmem_dump_start + size);
                 copy_pattern(KMEM_UNINITIALIZED_PATTERN, kmem_dump_start, size);
-        } else {
-                kmem_dump_size = 0;
-                kmem_dump_curr = NULL;
-                kmem_dump_end = NULL;
-        }
 }
 
 /*
  * Set flag for each kmem_cache_t if is safe to use alternate dump
  * memory. Called just before panic crash dump starts. Set the flag

@@ -2294,14 +2259,14 @@
  * for the calling CPU.
  */
 void
 kmem_dump_begin(void)
 {
-        ASSERT(panicstr != NULL);
-        if (kmem_dump_start != NULL) {
                 kmem_cache_t *cp;
 
+        ASSERT(panicstr != NULL);
+
                 for (cp = list_head(&kmem_caches); cp != NULL;
                     cp = list_next(&kmem_caches, cp)) {
                         kmem_cpu_cache_t *ccp = KMEM_CPU_CACHE(cp);
 
                         if (cp->cache_arena->vm_cflags & VMC_DUMPSAFE) {

@@ -2313,11 +2278,10 @@
                         } else {
                                 cp->cache_flags |= KMF_DUMPUNSAFE;
                                 ccp->cc_flags |= KMF_DUMPUNSAFE;
                         }
                 }
-        }
 }
 
 /*
  * finished dump intercept
  * print any warnings on the console

@@ -2324,22 +2288,22 @@
  * return verbose information to dumpsys() in the given buffer
  */
 size_t
 kmem_dump_finish(char *buf, size_t size)
 {
-        int kdi_idx;
-        int kdi_end = kmem_dump_log_idx;
         int percent = 0;
-        int header = 0;
-        int warn = 0;
         size_t used;
-        kmem_cache_t *cp;
-        kmem_dump_log_t *kdl;
         char *e = buf + size;
         char *p = buf;
 
-        if (kmem_dump_size == 0 || kmem_dump_verbose == 0)
+        if (kmem_dump_curr == kmem_dump_end) {
+                cmn_err(CE_WARN, "exceeded kmem_dump space of %lu "
+                    "bytes: kmem state in dump may be inconsistent",
+                    kmem_dump_size);
+        }
+
+        if (kmem_dump_verbose == 0)
                 return (0);
 
         used = (char *)kmem_dump_curr - (char *)kmem_dump_start;
         percent = (used * 100) / kmem_dump_size;
 

@@ -2349,29 +2313,10 @@
         kmem_dumppr(&p, e, "Oversize allocs,%d\n",
             kmem_dump_oversize_allocs);
         kmem_dumppr(&p, e, "Oversize max size,%ld\n",
             kmem_dump_oversize_max);
 
-        for (kdi_idx = 0; kdi_idx < kdi_end; kdi_idx++) {
-                kdl = &kmem_dump_log[kdi_idx];
-                cp = kdl->kdl_cache;
-                if (cp == NULL)
-                        break;
-                if (kdl->kdl_alloc_fails)
-                        ++warn;
-                if (header == 0) {
-                        kmem_dumppr(&p, e,
-                            "Cache Name,Allocs,Frees,Alloc Fails,"
-                            "Nondump Frees,Unsafe Allocs/Frees\n");
-                        header = 1;
-                }
-                kmem_dumppr(&p, e, "%s,%d,%d,%d,%d,%d\n",
-                    cp->cache_name, kdl->kdl_allocs, kdl->kdl_frees,
-                    kdl->kdl_alloc_fails, kdl->kdl_free_nondump,
-                    kdl->kdl_unsafe);
-        }
-
         /* return buffer size used */
         if (p < e)
                 bzero(p, e - p);
         return (p - buf);
 }

@@ -2385,13 +2330,12 @@
         void *buf;
         void *curr;
         char *bufend;
 
         /* return a constructed object */
-        if ((buf = cp->cache_dumpfreelist) != NULL) {
-                cp->cache_dumpfreelist = KMEM_DUMPCTL(cp, buf)->kdc_next;
-                KDI_LOG(cp, kdl_allocs);
+        if ((buf = cp->cache_dump.kd_freelist) != NULL) {
+                cp->cache_dump.kd_freelist = KMEM_DUMPCTL(cp, buf)->kdc_next;
                 return (buf);
         }
 
         /* create a new constructed object */
         curr = kmem_dump_curr;

@@ -2408,11 +2352,11 @@
         }
 
         /* fall back to normal alloc if reserved area is used up */
         if (bufend > (char *)kmem_dump_end) {
                 kmem_dump_curr = kmem_dump_end;
-                KDI_LOG(cp, kdl_alloc_fails);
+                cp->cache_dump.kd_alloc_fails++;
                 return (NULL);
         }
 
         /*
          * Must advance curr pointer before calling a constructor that

@@ -2430,16 +2374,15 @@
 #endif
                 /* reset curr pointer iff no allocs were done */
                 if (kmem_dump_curr == bufend)
                         kmem_dump_curr = curr;
 
+                cp->cache_dump.kd_alloc_fails++;
                 /* fall back to normal alloc if the constructor fails */
-                KDI_LOG(cp, kdl_alloc_fails);
                 return (NULL);
         }
 
-        KDI_LOG(cp, kdl_allocs);
         return (buf);
 }
 
 /*
  * Free a constructed object in alternate dump memory.

@@ -2448,19 +2391,15 @@
 kmem_cache_free_dump(kmem_cache_t *cp, void *buf)
 {
         /* save constructed buffers for next time */
         if ((char *)buf >= (char *)kmem_dump_start &&
             (char *)buf < (char *)kmem_dump_end) {
-                KMEM_DUMPCTL(cp, buf)->kdc_next = cp->cache_dumpfreelist;
-                cp->cache_dumpfreelist = buf;
-                KDI_LOG(cp, kdl_frees);
+                KMEM_DUMPCTL(cp, buf)->kdc_next = cp->cache_dump.kd_freelist;
+                cp->cache_dump.kd_freelist = buf;
                 return (0);
         }
 
-        /* count all non-dump buf frees */
-        KDI_LOG(cp, kdl_free_nondump);
-
         /* just drop buffers that were allocated before dump started */
         if (kmem_dump_curr < kmem_dump_end)
                 return (0);
 
         /* fall back to normal free if reserved area is used up */

@@ -2489,11 +2428,11 @@
                         mutex_exit(&ccp->cc_lock);
                         if (ccp->cc_flags & (KMF_BUFTAG | KMF_DUMPUNSAFE)) {
                                 if (ccp->cc_flags & KMF_DUMPUNSAFE) {
                                         ASSERT(!(ccp->cc_flags &
                                             KMF_DUMPDIVERT));
-                                        KDI_LOG(cp, kdl_unsafe);
+                                        cp->cache_dump.kd_unsafe++;
                                 }
                                 if ((ccp->cc_flags & KMF_BUFTAG) &&
                                     kmem_cache_alloc_debug(cp, buf, kmflag, 0,
                                     caller()) != 0) {
                                         if (kmflag & KM_NOSLEEP)

@@ -2520,11 +2459,11 @@
                  */
                 if (ccp->cc_flags & (KMF_DUMPDIVERT | KMF_DUMPUNSAFE)) {
                         if (ccp->cc_flags & KMF_DUMPUNSAFE) {
                                 ASSERT(!(ccp->cc_flags & KMF_DUMPDIVERT));
                                 /* log it so that we can warn about it */
-                                KDI_LOG(cp, kdl_unsafe);
+                                cp->cache_dump.kd_unsafe++;
                         } else {
                                 if ((buf = kmem_cache_alloc_dump(cp, kmflag)) !=
                                     NULL) {
                                         mutex_exit(&ccp->cc_lock);
                                         return (buf);

@@ -2716,11 +2655,11 @@
 
         if (ccp->cc_flags & (KMF_BUFTAG | KMF_DUMPDIVERT | KMF_DUMPUNSAFE)) {
                 if (ccp->cc_flags & KMF_DUMPUNSAFE) {
                         ASSERT(!(ccp->cc_flags & KMF_DUMPDIVERT));
                         /* log it so that we can warn about it */
-                        KDI_LOG(cp, kdl_unsafe);
+                        cp->cache_dump.kd_unsafe++;
                 } else if (KMEM_DUMPCC(ccp) && !kmem_cache_free_dump(cp, buf)) {
                         return;
                 }
                 if (ccp->cc_flags & KMF_BUFTAG) {
                         if (kmem_cache_free_debug(cp, buf, caller()) == -1)