diff options
-rw-r--r-- | sys/ddb/db_command.c | 24 | ||||
-rw-r--r-- | sys/kern/kern_shutdown.c | 30 | ||||
-rw-r--r-- | sys/sys/conf.h | 1 |
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 */ |