mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-03-10 20:36:21 +03:00
zhack: add -G option to dump debug buffer
Add a -G option to zhack to dump the internal debug buffer on exit. We were able to use the same code from zdb for this which was nice. Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Tony Hutter <hutter2@llnl.gov> Reviewed-by: Olaf Faaland <faaland1@llnl.gov> Reviewed-by: Akash B <akash-b@hpe.com>
This commit is contained in:
parent
20176224ee
commit
731ff0a5ac
76
cmd/zhack.c
76
cmd/zhack.c
@ -52,6 +52,7 @@
|
||||
#include <sys/zio_compress.h>
|
||||
#include <sys/zfeature.h>
|
||||
#include <sys/dmu_tx.h>
|
||||
#include <sys/backtrace.h>
|
||||
#include <zfeature_common.h>
|
||||
#include <libzutil.h>
|
||||
#include <sys/metaslab_impl.h>
|
||||
@ -60,6 +61,7 @@
|
||||
static importargs_t g_importargs;
|
||||
static char *g_pool;
|
||||
static boolean_t g_readonly;
|
||||
static boolean_t g_dump_dbgmsg;
|
||||
|
||||
typedef enum {
|
||||
ZHACK_REPAIR_OP_UNKNOWN = 0,
|
||||
@ -71,12 +73,19 @@ static __attribute__((noreturn)) void
|
||||
usage(void)
|
||||
{
|
||||
(void) fprintf(stderr,
|
||||
"Usage: zhack [-o tunable] [-c cachefile] [-d dir] <subcommand> "
|
||||
"<args> ...\n"
|
||||
"where <subcommand> <args> is one of the following:\n"
|
||||
"Usage: zhack [-o tunable] [-c cachefile] [-d dir] [-G] "
|
||||
"<subcommand> <args> ...\n"
|
||||
" where <subcommand> <args> is one of the following:\n"
|
||||
"\n");
|
||||
|
||||
(void) fprintf(stderr,
|
||||
" global options:\n"
|
||||
" -c <cachefile> reads config from the given cachefile\n"
|
||||
" -d <dir> directory with vdevs for import\n"
|
||||
" -o var=value... set global variable to an unsigned "
|
||||
"32-bit integer\n"
|
||||
" -G dump zfs_dbgmsg buffer before exiting\n"
|
||||
"\n"
|
||||
" feature stat <pool>\n"
|
||||
" print information about enabled features\n"
|
||||
" feature enable [-r] [-d desc] <pool> <feature>\n"
|
||||
@ -103,6 +112,39 @@ usage(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_debug_buffer(void)
|
||||
{
|
||||
ssize_t ret __attribute__((unused));
|
||||
|
||||
if (!g_dump_dbgmsg)
|
||||
return;
|
||||
|
||||
/*
|
||||
* We use write() instead of printf() so that this function
|
||||
* is safe to call from a signal handler.
|
||||
*/
|
||||
ret = write(STDERR_FILENO, "\n", 1);
|
||||
zfs_dbgmsg_print(STDERR_FILENO, "zhack");
|
||||
}
|
||||
|
||||
static void sig_handler(int signo)
|
||||
{
|
||||
struct sigaction action;
|
||||
|
||||
libspl_backtrace(STDERR_FILENO);
|
||||
dump_debug_buffer();
|
||||
|
||||
/*
|
||||
* Restore default action and re-raise signal so SIGSEGV and
|
||||
* SIGABRT can trigger a core dump.
|
||||
*/
|
||||
action.sa_handler = SIG_DFL;
|
||||
sigemptyset(&action.sa_mask);
|
||||
action.sa_flags = 0;
|
||||
(void) sigaction(signo, &action, NULL);
|
||||
raise(signo);
|
||||
}
|
||||
|
||||
static __attribute__((format(printf, 3, 4))) __attribute__((noreturn)) void
|
||||
fatal(spa_t *spa, const void *tag, const char *fmt, ...)
|
||||
@ -120,6 +162,8 @@ fatal(spa_t *spa, const void *tag, const char *fmt, ...)
|
||||
va_end(ap);
|
||||
(void) fputc('\n', stderr);
|
||||
|
||||
dump_debug_buffer();
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -1183,17 +1227,35 @@ zhack_do_label(int argc, char **argv)
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct sigaction action;
|
||||
char *path[MAX_NUM_PATHS];
|
||||
const char *subcommand;
|
||||
int rv = 0;
|
||||
int c;
|
||||
|
||||
/*
|
||||
* Set up signal handlers, so if we crash due to bad on-disk data we
|
||||
* can get more info. Unlike ztest, we don't bail out if we can't set
|
||||
* up signal handlers, because zhack is very useful without them.
|
||||
*/
|
||||
action.sa_handler = sig_handler;
|
||||
sigemptyset(&action.sa_mask);
|
||||
action.sa_flags = 0;
|
||||
if (sigaction(SIGSEGV, &action, NULL) < 0) {
|
||||
(void) fprintf(stderr, "zhack: cannot catch SIGSEGV: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
if (sigaction(SIGABRT, &action, NULL) < 0) {
|
||||
(void) fprintf(stderr, "zhack: cannot catch SIGABRT: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
g_importargs.path = path;
|
||||
|
||||
dprintf_setup(&argc, argv);
|
||||
zfs_prop_init();
|
||||
|
||||
while ((c = getopt(argc, argv, "+c:d:o:")) != -1) {
|
||||
while ((c = getopt(argc, argv, "+c:d:Go:")) != -1) {
|
||||
switch (c) {
|
||||
case 'c':
|
||||
g_importargs.cachefile = optarg;
|
||||
@ -1202,6 +1264,9 @@ main(int argc, char **argv)
|
||||
assert(g_importargs.paths < MAX_NUM_PATHS);
|
||||
g_importargs.path[g_importargs.paths++] = optarg;
|
||||
break;
|
||||
case 'G':
|
||||
g_dump_dbgmsg = B_TRUE;
|
||||
break;
|
||||
case 'o':
|
||||
if (handle_tunable_option(optarg, B_FALSE) != 0)
|
||||
exit(1);
|
||||
@ -1240,6 +1305,9 @@ main(int argc, char **argv)
|
||||
"changes may not be committed to disk\n");
|
||||
}
|
||||
|
||||
if (g_dump_dbgmsg)
|
||||
dump_debug_buffer();
|
||||
|
||||
kernel_fini();
|
||||
|
||||
return (rv);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user