From 682f13c637b3bc03edf66fbe778a6127e85095aa Mon Sep 17 00:00:00 2001 From: Thomas Schoebel-Theuer Date: Mon, 9 Jan 2012 17:12:06 +0100 Subject: [PATCH] improved printk flooding (long filename paths) --- brick.h | 20 +------- brick_mem.c | 2 + brick_say.c | 139 ++++++++++++++++++++++++++++++++++++++++------------ brick_say.h | 11 +++-- mars.h | 4 +- 5 files changed, 120 insertions(+), 56 deletions(-) diff --git a/brick.h b/brick.h index bca3e61d..48a4559c 100644 --- a/brick.h +++ b/brick.h @@ -28,22 +28,6 @@ extern int brick_msleep(int msecs, bool shorten); // printk() replacements -#ifdef CONFIG_DEBUG_KERNEL -#define INLINE static inline -//#define INLINE __attribute__((__noinline__)) -extern void say(const char *fmt, ...); -extern void say_mark(void); -extern void brick_dump_stack(void); - -#else // CONFIG_DEBUG_KERNEL - -#define INLINE static inline -#define say printk -#define say_mark() /*empty*/ -#define brick_dump_stack() /*empty*/ - -#endif // CONFIG_DEBUG_KERNEL - #define SAFE_STR(str) ((str) ? (str) : "NULL") #define BRICK_FATAL "BRICK_FATAL " @@ -52,9 +36,7 @@ extern void brick_dump_stack(void); #define BRICK_INFO "BRICK_INFO " #define BRICK_DEBUG "BRICK_DEBUG " -#define _BRICK_FMT(_fmt) __BASE_FILE__ " %d %s(): " _fmt, __LINE__, __FUNCTION__ - -#define _BRICK_MSG(_dump, PREFIX, _fmt, _args...) do { say(PREFIX _BRICK_FMT(_fmt), ##_args); if (_dump) brick_dump_stack(); } while (0) +#define _BRICK_MSG(_dump, PREFIX, _fmt, _args...) do { brick_say(PREFIX, __BASE_FILE__, __LINE__, __FUNCTION__, _fmt, ##_args); if (_dump) brick_dump_stack(); } while (0) #define BRICK_FAT(_fmt, _args...) _BRICK_MSG(true, BRICK_FATAL, _fmt, ##_args) #define BRICK_ERR(_fmt, _args...) _BRICK_MSG(true, BRICK_ERROR, _fmt, ##_args) diff --git a/brick_mem.c b/brick_mem.c index e461bbf3..8810d48a 100644 --- a/brick_mem.c +++ b/brick_mem.c @@ -8,6 +8,7 @@ #include #include "brick_mem.h" +#include "brick_say.h" #include "brick_locks.h" #define BRICK_DEBUG_MEM 10000 @@ -589,6 +590,7 @@ void __exit exit_brick_mem(void) #endif brick_mem_statistics(); + exit_say(); } #ifndef CONFIG_MARS_HAVE_BIGMODULE diff --git a/brick_say.c b/brick_say.c index 76933806..5a90d257 100644 --- a/brick_say.c +++ b/brick_say.c @@ -11,51 +11,130 @@ // messaging -#ifdef CONFIG_DEBUG_KERNEL - +#include #include #include -static char say_buf[PAGE_SIZE * 8] = {}; -static int say_index = 0; +#define SAY_ORDER 0 +#define SAY_BUFMAX (PAGE_SIZE << SAY_ORDER) +#define MAX_FILELEN 16 + +static char *say_buf[NR_CPUS] = {}; +static int say_index[NR_CPUS] = {}; static int dump_max = 5; -/* This is racy. - * But we don't want to contend the CPUs neither by global locks nor by RCU. - * We just emit some limited kind of "garbage" upon overflow or races. - * This kind of informational garbage for humans will not hurt correctness - * of the real logic in any way, we just take it into account. - */ +static +void say_alloc(unsigned long cpu) +{ + if (cpu >= NR_CPUS || say_buf[cpu]) + goto done; + + say_buf[cpu] = (void*)__get_free_pages(GFP_ATOMIC, SAY_ORDER); + if (likely(say_buf[cpu])) { + say_buf[cpu][0] = '\0'; + say_index[cpu] = 0; + } + +done: ; +} + +static inline +void _say_mark(unsigned long cpu) +{ + if (preempt_count() & (PREEMPT_MASK | SOFTIRQ_MASK | HARDIRQ_MASK) || + cpu >= NR_CPUS) + goto done; + + say_alloc(cpu); + + if (!say_buf[cpu] || + !say_buf[cpu][0]) + goto done; + + printk("%s", say_buf[cpu]); + say_buf[cpu][0] = '\0'; + say_index[cpu] = 0; + +done: ; +} + void say_mark(void) { - if (say_buf[0]) { - printk("# %s", say_buf); - say_buf[0] = '\0'; - say_index = 0; - } + unsigned long cpu = get_cpu(); + _say_mark(cpu); + put_cpu(); } -EXPORT_SYMBOL(say_mark); +EXPORT_SYMBOL_GPL(say_mark); void say(const char *fmt, ...) { + unsigned long cpu = get_cpu(); va_list args; - if (preempt_count() & (PREEMPT_MASK | SOFTIRQ_MASK | HARDIRQ_MASK)) { - va_start(args, fmt); - say_index += vsnprintf(say_buf + say_index, sizeof(say_buf) - say_index, fmt, args); - va_end(args); - if (unlikely(say_index >= sizeof(say_buf))) { - say_index = sizeof(say_buf); - say_buf[say_index-1] = '\0'; - } - } else { - say_mark(); - va_start(args, fmt); - vprintk(fmt, args); - va_end(args); + _say_mark(cpu); + if (!say_buf[cpu]) + goto done; + + va_start(args, fmt); + say_index[cpu] += vsnprintf(say_buf[cpu] + say_index[cpu], SAY_BUFMAX - say_index[cpu], fmt, args); + va_end(args); + + if (unlikely(say_index[cpu] >= SAY_BUFMAX)) { + say_index[cpu] = SAY_BUFMAX; + say_buf[cpu][SAY_BUFMAX-1] = '\0'; + } + + _say_mark(cpu); +done: + put_cpu(); +} +EXPORT_SYMBOL_GPL(say); + +void brick_say(const char *prefix, const char *file, int line, const char *func, const char *fmt, ...) +{ + unsigned long cpu = get_cpu(); + int filelen; + va_list args; + + _say_mark(cpu); + if (!say_buf[cpu]) + goto done; + + // limit the + filelen = strlen(file); + if (filelen > MAX_FILELEN) + file += filelen - MAX_FILELEN; + + say_index[cpu] += snprintf(say_buf[cpu] + say_index[cpu], SAY_BUFMAX - say_index[cpu], "%s %s[%d] %s %d %s(): ", prefix, current->comm, (int)cpu, file, line, func); + + va_start(args, fmt); + say_index[cpu] += vsnprintf(say_buf[cpu] + say_index[cpu], SAY_BUFMAX - say_index[cpu], fmt, args); + va_end(args); + + if (unlikely(say_index[cpu] >= SAY_BUFMAX)) { + say_index[cpu] = SAY_BUFMAX; + say_buf[cpu][SAY_BUFMAX-1] = '\0'; + } + + _say_mark(cpu); +done: + put_cpu(); +} +EXPORT_SYMBOL_GPL(brick_say); + +extern void exit_say(void) +{ + int i; + for (i = 0; i < NR_CPUS; i++) { + if (!say_buf[i]) + continue; + __free_pages(virt_to_page((unsigned long)say_buf[i]), SAY_ORDER); + say_buf[i] = NULL; } } -EXPORT_SYMBOL(say); +EXPORT_SYMBOL_GPL(exit_say); + +#ifdef CONFIG_DEBUG_KERNEL void brick_dump_stack(void) { diff --git a/brick_say.h b/brick_say.h index e657dcd7..97b740fc 100644 --- a/brick_say.h +++ b/brick_say.h @@ -6,18 +6,21 @@ // printk() replacements +extern void say(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +extern void say_mark(void); + +extern void brick_say(const char *prefix, const char *file, int line, const char *func, const char *fmt, ...) __attribute__ ((format (printf, 5, 6))); + +extern void exit_say(void); + #ifdef CONFIG_DEBUG_KERNEL #define INLINE static inline //#define INLINE __attribute__((__noinline__)) -extern void say(const char *fmt, ...); -extern void say_mark(void); extern void brick_dump_stack(void); #else // CONFIG_DEBUG_KERNEL #define INLINE static inline -#define say printk -#define say_mark() /*empty*/ #define brick_dump_stack() /*empty*/ #endif // CONFIG_DEBUG_KERNEL diff --git a/mars.h b/mars.h index 910bca75..6447dbea 100644 --- a/mars.h +++ b/mars.h @@ -32,9 +32,7 @@ #define MARS_INFO "MARS_INFO " #define MARS_DEBUG "MARS_DEBUG " -#define _MARS_FMT(_fmt) "[%s] " __BASE_FILE__ " %d %s(): " _fmt, current->comm, __LINE__, __FUNCTION__ - -#define _MARS_MSG(_stacktrace, PREFIX, _fmt, _args...) do { say(PREFIX _MARS_FMT(_fmt), ##_args); MARS_DELAY; if (_stacktrace) dump_stack(); } while (0) +#define _MARS_MSG(_dump, PREFIX, _fmt, _args...) do { brick_say(PREFIX, __BASE_FILE__, __LINE__, __FUNCTION__, _fmt, ##_args); MARS_DELAY; if (_dump) brick_dump_stack(); } while (0) #define MARS_FAT(_fmt, _args...) _MARS_MSG(true, MARS_FATAL, _fmt, ##_args) #define MARS_ERR(_fmt, _args...) _MARS_MSG(true, MARS_ERROR, _fmt, ##_args)