summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/os/dumpsubr.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/os/dumpsubr.c')
-rw-r--r--usr/src/uts/common/os/dumpsubr.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/usr/src/uts/common/os/dumpsubr.c b/usr/src/uts/common/os/dumpsubr.c
index 1c766842de..0ae9c3d390 100644
--- a/usr/src/uts/common/os/dumpsubr.c
+++ b/usr/src/uts/common/os/dumpsubr.c
@@ -107,6 +107,7 @@ int dump_timeout = 120; /* timeout for dumping pages */
int dump_timeleft; /* portion of dump_timeout remaining */
int dump_ioerr; /* dump i/o error */
int dump_check_used; /* enable check for used pages */
+char *dump_stack_scratch; /* scratch area for saving stack summary */
/*
* Tunables for dump compression and parallelism. These can be set via
@@ -258,6 +259,12 @@ struct cbuf {
int off; /* byte offset to first pfn */
};
+static char dump_osimage_uuid[36 + 1];
+
+#define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
+#define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \
+ ((ch) >= 'A' && (ch) <= 'F'))
+
/*
* cqueue_t queues: a uni-directional channel for communication
* from the master to helper tasks or vice-versa using put and
@@ -1103,6 +1110,9 @@ dumphdr_init(void)
dumpcfg.pids = kmem_alloc(v.v_proc * sizeof (pid_t), KM_SLEEP);
dumpcfg.helpermap = kmem_zalloc(BT_SIZEOFMAP(NCPU), KM_SLEEP);
LOCK_INIT_HELD(&dumpcfg.helper_lock);
+ dump_stack_scratch = kmem_alloc(STACK_BUF_SIZE, KM_SLEEP);
+ (void) strncpy(dumphdr->dump_uuid, dump_get_uuid(),
+ sizeof (dumphdr->dump_uuid));
}
npages = num_phys_pages();
@@ -1436,6 +1446,48 @@ dump_process(pid_t pid)
return (0);
}
+/*
+ * The following functions (dump_summary(), dump_ereports(), and
+ * dump_messages()), write data to an uncompressed area within the
+ * crashdump. The layout of these is
+ *
+ * +------------------------------------------------------------+
+ * | compressed pages | summary | ereports | messages |
+ * +------------------------------------------------------------+
+ *
+ * With the advent of saving a compressed crash dump by default, we
+ * need to save a little more data to describe the failure mode in
+ * an uncompressed buffer available before savecore uncompresses
+ * the dump. Initially this is a copy of the stack trace. Additional
+ * summary information should be added here.
+ */
+
+void
+dump_summary(void)
+{
+ u_offset_t dumpvp_start;
+ summary_dump_t sd;
+
+ if (dumpvp == NULL || dumphdr == NULL)
+ return;
+
+ dumpbuf.cur = dumpbuf.start;
+
+ dumpbuf.vp_limit = dumpvp_size - (DUMP_OFFSET + DUMP_LOGSIZE +
+ DUMP_ERPTSIZE);
+ dumpvp_start = dumpbuf.vp_limit - DUMP_SUMMARYSIZE;
+ dumpbuf.vp_off = dumpvp_start;
+
+ sd.sd_magic = SUMMARY_MAGIC;
+ sd.sd_ssum = checksum32(dump_stack_scratch, STACK_BUF_SIZE);
+ dumpvp_write(&sd, sizeof (sd));
+ dumpvp_write(dump_stack_scratch, STACK_BUF_SIZE);
+
+ sd.sd_magic = 0; /* indicate end of summary */
+ dumpvp_write(&sd, sizeof (sd));
+ (void) dumpvp_flush();
+}
+
void
dump_ereports(void)
{
@@ -2859,6 +2911,10 @@ dumpsys(void)
size -= datahdr.dump_metrics;
}
+ /* record in the header whether this is a fault-management panic */
+ if (panicstr)
+ dumphdr->dump_fm_panic = is_fm_panic();
+
/* compression info in data header */
datahdr.dump_datahdr_magic = DUMP_DATAHDR_MAGIC;
datahdr.dump_datahdr_version = DUMP_DATAHDR_VERSION;
@@ -2905,6 +2961,7 @@ dumpsys(void)
* thing we do because the dump process itself emits messages.
*/
if (panicstr) {
+ dump_summary();
dump_ereports();
dump_messages();
}
@@ -2967,3 +3024,47 @@ dumpvp_resize()
mutex_exit(&dump_lock);
return (0);
}
+
+int
+dump_set_uuid(const char *uuidstr)
+{
+ const char *ptr;
+ int i;
+
+ if (uuidstr == NULL || strnlen(uuidstr, 36 + 1) != 36)
+ return (EINVAL);
+
+ /* uuid_parse is not common code so check manually */
+ for (i = 0, ptr = uuidstr; i < 36; i++, ptr++) {
+ switch (i) {
+ case 8:
+ case 13:
+ case 18:
+ case 23:
+ if (*ptr != '-')
+ return (EINVAL);
+ break;
+
+ default:
+ if (!isxdigit(*ptr))
+ return (EINVAL);
+ break;
+ }
+ }
+
+ if (dump_osimage_uuid[0] != '\0')
+ return (EALREADY);
+
+ (void) strncpy(dump_osimage_uuid, uuidstr, 36 + 1);
+
+ cmn_err(CE_CONT, "?This Solaris instance has UUID %s",
+ dump_osimage_uuid);
+
+ return (0);
+}
+
+const char *
+dump_get_uuid(void)
+{
+ return (dump_osimage_uuid[0] != '\0' ? dump_osimage_uuid : "");
+}