X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=module%2Fspl%2Fspl-err.c;h=2f66b6e23cb6fc5d4eecc72e34d97ebb9ab146d3;hb=ec06701b5473894514b25e4054dd5597e25a22e8;hp=1d520282704c2f546336d70bbd04bba86402bc9b;hpb=716154c5926eb391eb8178203496430ffa7ebed8;p=mirror_spl-debian.git diff --git a/module/spl/spl-err.c b/module/spl/spl-err.c index 1d52028..2f66b6e 100644 --- a/module/spl/spl-err.c +++ b/module/spl/spl-err.c @@ -6,7 +6,7 @@ * UCRL-CODE-235197 * * This file is part of the SPL, Solaris Porting Layer. - * For details, see . + * For details, see . * * The SPL is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -26,44 +26,95 @@ #include #include +#include -#ifdef DEBUG_SUBSYSTEM -#undef DEBUG_SUBSYSTEM -#endif +/* + * It is often useful to actually have the panic crash the node so you + * can then get notified of the event, get the crashdump for later + * analysis and other such goodies. + * But we would still default to the current default of not to do that. + */ +unsigned int spl_panic_halt; +module_param(spl_panic_halt, uint, 0644); +MODULE_PARM_DESC(spl_panic_halt, + "Cause kernel panic on assertion failures"); -#define DEBUG_SUBSYSTEM S_GENERIC - -#ifndef NDEBUG -static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" }; -static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" }; -#endif +/* + * Limit the number of stack traces dumped to not more than 5 every + * 60 seconds to prevent denial-of-service attacks from debug code. + */ +DEFINE_RATELIMIT_STATE(dumpstack_ratelimit_state, 60 * HZ, 5); void -vpanic(const char *fmt, va_list ap) +spl_dumpstack(void) { + if (__ratelimit(&dumpstack_ratelimit_state)) { + printk("Showing stack for process %d\n", current->pid); + dump_stack(); + } +} +EXPORT_SYMBOL(spl_dumpstack); + +int +spl_panic(const char *file, const char *func, int line, const char *fmt, ...) { + const char *newfile; char msg[MAXMSGLEN]; + va_list ap; - vsnprintf(msg, MAXMSGLEN - 1, fmt, ap); - panic("%s", msg); -} /* vpanic() */ -EXPORT_SYMBOL(vpanic); + newfile = strrchr(file, '/'); + if (newfile != NULL) + newfile = newfile + 1; + else + newfile = file; + + va_start(ap, fmt); + (void) vsnprintf(msg, sizeof (msg), fmt, ap); + va_end(ap); + + printk(KERN_EMERG "%s", msg); + printk(KERN_EMERG "PANIC at %s:%d:%s()\n", newfile, line, func); + if (spl_panic_halt) + panic("%s", msg); + + spl_dumpstack(); + + /* Halt the thread to facilitate further debugging */ + set_current_state(TASK_UNINTERRUPTIBLE); + while (1) + schedule(); + + /* Unreachable */ + return (1); +} +EXPORT_SYMBOL(spl_panic); void vcmn_err(int ce, const char *fmt, va_list ap) { char msg[MAXMSGLEN]; - if (ce == CE_PANIC) - vpanic(fmt, ap); + vsnprintf(msg, MAXMSGLEN - 1, fmt, ap); - if (ce != CE_NOTE) { - vsnprintf(msg, MAXMSGLEN - 1, fmt, ap); + switch (ce) { + case CE_IGNORE: + break; + case CE_CONT: + printk("%s", msg); + break; + case CE_NOTE: + printk(KERN_NOTICE "NOTICE: %s\n", msg); + break; + case CE_WARN: + printk(KERN_WARNING "WARNING: %s\n", msg); + break; + case CE_PANIC: + printk(KERN_EMERG "PANIC: %s\n", msg); + spl_dumpstack(); - if (fmt[0] == '!') - CDEBUG(D_INFO, "%s%s%s", - ce_prefix[ce], msg, ce_suffix[ce]); - else - CERROR("%s%s%s", ce_prefix[ce], msg, ce_suffix[ce]); + /* Halt the thread to facilitate further debugging */ + set_current_state(TASK_UNINTERRUPTIBLE); + while (1) + schedule(); } } /* vcmn_err() */ EXPORT_SYMBOL(vcmn_err); @@ -78,4 +129,3 @@ cmn_err(int ce, const char *fmt, ...) va_end(ap); } /* cmn_err() */ EXPORT_SYMBOL(cmn_err); -