Print this page
9525 kmem_dump_size is a corrupting influence

@@ -22,11 +22,11 @@
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 /*
- * Copyright 2011 Joyent, Inc.  All rights reserved.
+ * Copyright 2018 Joyent, Inc.  All rights reserved.
  * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #include <mdb/mdb_param.h>
 #include <mdb/mdb_modapi.h>

@@ -3010,11 +3010,11 @@
 
 typedef struct kmem_verify {
         uint64_t *kmv_buf;              /* buffer to read cache contents into */
         size_t kmv_size;                /* number of bytes in kmv_buf */
         int kmv_corruption;             /* > 0 if corruption found. */
-        int kmv_besilent;               /* report actual corruption sites */
+        uint_t kmv_flags;               /* dcmd flags */
         struct kmem_cache kmv_cache;    /* the cache we're operating on */
 } kmem_verify_t;
 
 /*
  * verify_pattern()

@@ -3055,11 +3055,11 @@
         kmem_verify_t *kmv = (kmem_verify_t *)private;
         uint64_t *buf = kmv->kmv_buf;   /* buf to validate */
         int64_t corrupt;                /* corruption offset */
         kmem_buftag_t *buftagp;         /* ptr to buftag */
         kmem_cache_t *cp = &kmv->kmv_cache;
-        int besilent = kmv->kmv_besilent;
+        boolean_t besilent = !!(kmv->kmv_flags & (DCMD_LOOP | DCMD_PIPE_OUT));
 
         /*LINTED*/
         buftagp = KMEM_BUFTAG(cp, buf);
 
         /*

@@ -3101,10 +3101,12 @@
                 goto corrupt;
         }
 
         return (WALK_NEXT);
 corrupt:
+        if (kmv->kmv_flags & DCMD_PIPE_OUT)
+                mdb_printf("%p\n", addr);
         kmv->kmv_corruption++;
         return (WALK_NEXT);
 }
 
 /*

@@ -3122,11 +3124,11 @@
         /*LINTED*/
         kmem_buftag_t *buftagp = KMEM_BUFTAG(cp, buf);
         uint32_t *ip = (uint32_t *)buftagp;
         uint8_t *bp = (uint8_t *)buf;
         int looks_ok = 0, size_ok = 1;  /* flags for finding corruption */
-        int besilent = kmv->kmv_besilent;
+        boolean_t besilent = !!(kmv->kmv_flags & (DCMD_LOOP | DCMD_PIPE_OUT));
 
         /*
          * Read the buffer to check.
          */
         if (mdb_vread(buf, kmv->kmv_size, addr) == -1) {

@@ -3180,10 +3182,13 @@
                 goto corrupt;
         }
 
         return (WALK_NEXT);
 corrupt:
+        if (kmv->kmv_flags & DCMD_PIPE_OUT)
+                mdb_printf("%p\n", addr);
+
         kmv->kmv_corruption++;
         return (WALK_NEXT);
 }
 
 /*ARGSUSED2*/

@@ -3198,14 +3203,22 @@
                     addr) == -1) {
                         mdb_warn("couldn't read kmem_cache %p", addr);
                         return (DCMD_ERR);
                 }
 
+                if ((kmv.kmv_cache.cache_dump.kd_unsafe ||
+                    kmv.kmv_cache.cache_dump.kd_alloc_fails) &&
+                    !(flags & (DCMD_LOOP | DCMD_PIPE_OUT))) {
+                        mdb_warn("WARNING: cache was used during dump: "
+                            "corruption may be incorrectly reported\n");
+                }
+
                 kmv.kmv_size = kmv.kmv_cache.cache_buftag +
                     sizeof (kmem_buftag_t);
                 kmv.kmv_buf = mdb_alloc(kmv.kmv_size, UM_SLEEP | UM_GC);
                 kmv.kmv_corruption = 0;
+                kmv.kmv_flags = flags;
 
                 if ((kmv.kmv_cache.cache_flags & KMF_REDZONE)) {
                         check_alloc = 1;
                         if (kmv.kmv_cache.cache_flags & KMF_DEADBEEF)
                                 check_free = 1;

@@ -3216,61 +3229,70 @@
                                     kmv.kmv_cache.cache_name);
                         }
                         return (DCMD_ERR);
                 }
 
-                if (flags & DCMD_LOOP) {
-                        /*
-                         * table mode, don't print out every corrupt buffer
-                         */
-                        kmv.kmv_besilent = 1;
-                } else {
+                if (!(flags & (DCMD_LOOP | DCMD_PIPE_OUT))) {
                         mdb_printf("Summary for cache '%s'\n",
                             kmv.kmv_cache.cache_name);
                         mdb_inc_indent(2);
-                        kmv.kmv_besilent = 0;
                 }
 
                 if (check_alloc)
                         (void) mdb_pwalk("kmem", verify_alloc, &kmv, addr);
                 if (check_free)
                         (void) mdb_pwalk("freemem", verify_free, &kmv, addr);
 
+                if (!(flags & DCMD_PIPE_OUT)) {
                 if (flags & DCMD_LOOP) {
                         if (kmv.kmv_corruption == 0) {
                                 mdb_printf("%-*s %?p clean\n",
                                     KMEM_CACHE_NAMELEN,
                                     kmv.kmv_cache.cache_name, addr);
                         } else {
-                                char *s = "";   /* optional s in "buffer[s]" */
-                                if (kmv.kmv_corruption > 1)
-                                        s = "s";
-
-                                mdb_printf("%-*s %?p %d corrupt buffer%s\n",
-                                    KMEM_CACHE_NAMELEN,
+                                        mdb_printf("%-*s %?p %d corrupt "
+                                            "buffer%s\n", KMEM_CACHE_NAMELEN,
                                     kmv.kmv_cache.cache_name, addr,
-                                    kmv.kmv_corruption, s);
+                                            kmv.kmv_corruption,
+                                            kmv.kmv_corruption > 1 ? "s" : "");
                         }
                 } else {
                         /*
-                         * This is the more verbose mode, when the user has
-                         * type addr::kmem_verify.  If the cache was clean,
-                         * nothing will have yet been printed. So say something.
+                                 * This is the more verbose mode, when the user
+                                 * typed addr::kmem_verify.  If the cache was
+                                 * clean, nothing will have yet been printed. So
+                                 * say something.
                          */
                         if (kmv.kmv_corruption == 0)
                                 mdb_printf("clean\n");
 
                         mdb_dec_indent(2);
                 }
+                }
         } else {
                 /*
                  * If the user didn't specify a cache to verify, we'll walk all
                  * kmem_cache's, specifying ourself as a callback for each...
                  * this is the equivalent of '::walk kmem_cache .::kmem_verify'
                  */
-                mdb_printf("%<u>%-*s %-?s %-20s%</b>\n", KMEM_CACHE_NAMELEN,
-                    "Cache Name", "Addr", "Cache Integrity");
+
+                if (!(flags & DCMD_PIPE_OUT)) {
+                        uintptr_t dump_curr;
+                        uintptr_t dump_end;
+
+                        if (mdb_readvar(&dump_curr, "kmem_dump_curr") != -1 &&
+                            mdb_readvar(&dump_end, "kmem_dump_end") != -1 &&
+                            dump_curr == dump_end) {
+                                mdb_warn("WARNING: exceeded kmem_dump_size; "
+                                    "corruption may be incorrectly reported\n");
+                        }
+
+                        mdb_printf("%<u>%-*s %-?s %-20s%</b>\n",
+                            KMEM_CACHE_NAMELEN, "Cache Name", "Addr",
+                            "Cache Integrity");
+                }
+
                 (void) (mdb_walk_dcmd("kmem_cache", "kmem_verify", 0, NULL));
         }
 
         return (DCMD_OK);
 }