summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/ddb/db_command.c24
-rw-r--r--sys/kern/kern_shutdown.c30
-rw-r--r--sys/sys/conf.h1
3 files changed, 41 insertions, 14 deletions
diff --git a/sys/ddb/db_command.c b/sys/ddb/db_command.c
index 21cb7c5..f2e2c42 100644
--- a/sys/ddb/db_command.c
+++ b/sys/ddb/db_command.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/signalvar.h>
#include <sys/systm.h>
#include <sys/cons.h>
+#include <sys/conf.h>
#include <sys/watchdog.h>
#include <sys/kernel.h>
@@ -64,6 +65,7 @@ db_addr_t db_last_addr;
db_addr_t db_prev;
db_addr_t db_next;
+static db_cmdfcn_t db_dump;
static db_cmdfcn_t db_fncall;
static db_cmdfcn_t db_gdb;
static db_cmdfcn_t db_halt;
@@ -102,6 +104,7 @@ static struct command db_cmds[] = {
{ "w", db_write_cmd, CS_MORE|CS_SET_DOT, 0 },
{ "delete", db_delete_cmd, 0, 0 },
{ "d", db_delete_cmd, 0, 0 },
+ { "dump", db_dump, 0, 0 },
{ "break", db_breakpoint_cmd, 0, 0 },
{ "b", db_breakpoint_cmd, 0, 0 },
{ "dwatch", db_deletewatch_cmd, 0, 0 },
@@ -526,6 +529,27 @@ db_error(s)
kdb_reenter();
}
+static void
+db_dump(db_expr_t dummy, boolean_t dummy2, db_expr_t dummy3, char *dummy4)
+{
+ int error;
+
+ error = doadump(FALSE);
+ if (error) {
+ db_printf("Cannot dump: ");
+ switch (error) {
+ case EBUSY:
+ db_printf("debugger got invoked while dumping.\n");
+ break;
+ case ENXIO:
+ db_printf("no dump device specified.\n");
+ break;
+ default:
+ db_printf("unknown error (error=%d).\n", error);
+ break;
+ }
+ }
+}
/*
* Call random function:
diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c
index 001da3d..da041fa 100644
--- a/sys/kern/kern_shutdown.c
+++ b/sys/kern/kern_shutdown.c
@@ -233,30 +233,32 @@ print_uptime(void)
printf("%lds\n", (long)ts.tv_sec);
}
-static void
-doadump(void)
+int
+doadump(boolean_t textdump)
{
+ boolean_t coredump;
- /*
- * Sometimes people have to call this from the kernel debugger.
- * (if 'panic' can not dump)
- * Give them a clue as to why they can't dump.
- */
- if (dumper.dumper == NULL) {
- printf("Cannot dump. Device not defined or unavailable.\n");
- return;
- }
+ if (dumping)
+ return (EBUSY);
+ if (dumper.dumper == NULL)
+ return (ENXIO);
savectx(&dumppcb);
dumptid = curthread->td_tid;
dumping++;
+
+ coredump = TRUE;
#ifdef DDB
- if (textdump_pending)
+ if (textdump && textdump_pending) {
+ coredump = FALSE;
textdump_dumpsys(&dumper);
- else
+ }
#endif
+ if (coredump)
dumpsys(&dumper);
+
dumping--;
+ return (0);
}
static int
@@ -425,7 +427,7 @@ kern_reboot(int howto)
EVENTHANDLER_INVOKE(shutdown_post_sync, howto);
if ((howto & (RB_HALT|RB_DUMP)) == RB_DUMP && !cold && !dumping)
- doadump();
+ doadump(TRUE);
/* Now that we're going to really halt the system... */
EVENTHANDLER_INVOKE(shutdown_final, howto);
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index 31fd34d..0c7ed41 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -332,6 +332,7 @@ struct dumperinfo {
int set_dumper(struct dumperinfo *);
int dump_write(struct dumperinfo *, void *, vm_offset_t, off_t, size_t);
void dumpsys(struct dumperinfo *);
+int doadump(boolean_t);
extern int dumping; /* system is dumping */
#endif /* _KERNEL */
OpenPOWER on IntegriCloud