Index: head/sys/conf/NOTES =================================================================== --- head/sys/conf/NOTES +++ head/sys/conf/NOTES @@ -554,6 +554,14 @@ options INVARIANT_SUPPORT # +# The KASSERT_PANIC_OPTIONAL option allows kasserts to fire without +# necessarily inducing a panic. Panic is the default behavior, but +# runtime options can configure it either entirely off, or off with a +# limit. +# +options KASSERT_PANIC_OPTIONAL + +# # The DIAGNOSTIC option is used to enable extra debugging information # from some parts of the kernel. As this makes everything more noisy, # it is disabled by default. Index: head/sys/conf/options =================================================================== --- head/sys/conf/options +++ head/sys/conf/options @@ -605,6 +605,7 @@ DIAGNOSTIC opt_global.h INVARIANT_SUPPORT opt_global.h INVARIANTS opt_global.h +KASSERT_PANIC_OPTIONAL opt_global.h MAXCPU opt_global.h MAXMEMDOM opt_global.h MAXPHYS opt_global.h Index: head/sys/kern/kern_shutdown.c =================================================================== --- head/sys/kern/kern_shutdown.c +++ head/sys/kern/kern_shutdown.c @@ -652,40 +652,47 @@ SYSCTL_NODE(_debug, OID_AUTO, kassert, CTLFLAG_RW, NULL, "kassert options"); -SYSCTL_INT(_debug_kassert, OID_AUTO, warn_only, CTLFLAG_RWTUN, +#ifdef KASSERT_PANIC_OPTIONAL +#define KASSERT_RWTUN CTLFLAG_RWTUN +#else +#define KASSERT_RWTUN CTLFLAG_RDTUN +#endif + +SYSCTL_INT(_debug_kassert, OID_AUTO, warn_only, KASSERT_RWTUN, &kassert_warn_only, 0, - "KASSERT triggers a panic (1) or just a warning (0)"); + "KASSERT triggers a panic (0) or just a warning (1)"); #ifdef KDB -SYSCTL_INT(_debug_kassert, OID_AUTO, do_kdb, CTLFLAG_RWTUN, +SYSCTL_INT(_debug_kassert, OID_AUTO, do_kdb, KASSERT_RWTUN, &kassert_do_kdb, 0, "KASSERT will enter the debugger"); #endif #ifdef KTR -SYSCTL_UINT(_debug_kassert, OID_AUTO, do_ktr, CTLFLAG_RWTUN, +SYSCTL_UINT(_debug_kassert, OID_AUTO, do_ktr, KASSERT_RWTUN, &kassert_do_ktr, 0, "KASSERT does a KTR, set this to the KTRMASK you want"); #endif -SYSCTL_INT(_debug_kassert, OID_AUTO, do_log, CTLFLAG_RWTUN, +SYSCTL_INT(_debug_kassert, OID_AUTO, do_log, KASSERT_RWTUN, &kassert_do_log, 0, "If warn_only is enabled, log (1) or do not log (0) assertion violations"); -SYSCTL_INT(_debug_kassert, OID_AUTO, warnings, CTLFLAG_RWTUN, +SYSCTL_INT(_debug_kassert, OID_AUTO, warnings, KASSERT_RWTUN, &kassert_warnings, 0, "number of KASSERTs that have been triggered"); -SYSCTL_INT(_debug_kassert, OID_AUTO, log_panic_at, CTLFLAG_RWTUN, +SYSCTL_INT(_debug_kassert, OID_AUTO, log_panic_at, KASSERT_RWTUN, &kassert_log_panic_at, 0, "max number of KASSERTS before we will panic"); -SYSCTL_INT(_debug_kassert, OID_AUTO, log_pps_limit, CTLFLAG_RWTUN, +SYSCTL_INT(_debug_kassert, OID_AUTO, log_pps_limit, KASSERT_RWTUN, &kassert_log_pps_limit, 0, "limit number of log messages per second"); -SYSCTL_INT(_debug_kassert, OID_AUTO, log_mute_at, CTLFLAG_RWTUN, +SYSCTL_INT(_debug_kassert, OID_AUTO, log_mute_at, KASSERT_RWTUN, &kassert_log_mute_at, 0, "max number of KASSERTS to log"); -SYSCTL_INT(_debug_kassert, OID_AUTO, suppress_in_panic, CTLFLAG_RWTUN, +SYSCTL_INT(_debug_kassert, OID_AUTO, suppress_in_panic, KASSERT_RWTUN, &kassert_suppress_in_panic, 0, "KASSERTs will be suppressed while handling a panic"); +#undef KASSERT_RWTUN static int kassert_sysctl_kassert(SYSCTL_HANDLER_ARGS); @@ -709,6 +716,7 @@ return (0); } +#ifdef KASSERT_PANIC_OPTIONAL /* * Called by KASSERT, this decides if we will panic * or if we will log via printf and/or ktr. @@ -774,6 +782,7 @@ #endif atomic_add_int(&kassert_warnings, 1); } +#endif /* KASSERT_PANIC_OPTIONAL */ #endif /* Index: head/sys/sys/systm.h =================================================================== --- head/sys/sys/systm.h +++ head/sys/sys/systm.h @@ -80,9 +80,22 @@ enum VM_GUEST { VM_GUEST_NO = 0, VM_GUEST_VM, VM_GUEST_XEN, VM_GUEST_HV, VM_GUEST_VMWARE, VM_GUEST_KVM, VM_GUEST_BHYVE, VM_LAST }; +/* + * These functions need to be declared before the KASSERT macro is invoked in + * !KASSERT_PANIC_OPTIONAL builds, so their declarations are sort of out of + * place compared to other function definitions in this header. On the other + * hand, this header is a bit disorganized anyway. + */ +void panic(const char *, ...) __dead2 __printflike(1, 2); +void vpanic(const char *, __va_list) __dead2 __printflike(1, 0); + #if defined(WITNESS) || defined(INVARIANT_SUPPORT) +#ifdef KASSERT_PANIC_OPTIONAL void kassert_panic(const char *fmt, ...) __printflike(1, 2); +#else +#define kassert_panic panic #endif +#endif #ifdef INVARIANTS /* The option is always available */ #define KASSERT(exp,msg) do { \ @@ -212,9 +225,6 @@ void *phashinit_flags(int count, struct malloc_type *type, u_long *nentries, int flags); void g_waitidle(void); - -void panic(const char *, ...) __dead2 __printflike(1, 2); -void vpanic(const char *, __va_list) __dead2 __printflike(1, 0); void cpu_boot(int); void cpu_flush_dcache(void *, size_t);