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);
}