aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>2018-12-17 16:05:04 -0500
committerPetr Mladek <pmladek@suse.com>2018-12-18 04:53:14 -0500
commit15ff2069cb7f967dae6a8f8c176ba51447c75f00 (patch)
treeb3e4f0437c240668ad73e32b194d4e827669dbaa /kernel
parent07c17732bd687567802aaa5fa5c101c2776565d1 (diff)
printk: Add caller information to printk() output.
Sometimes we want to print a series of printk() messages to consoles without being disturbed by concurrent printk() from interrupts and/or other threads. But we can't enforce printk() callers to use their local buffers because we need to ask them to make too much changes. Also, even buffering up to one line inside printk() might cause failing to emit an important clue under critical situation. Therefore, instead of trying to help buffering, let's try to help reconstructing messages by saving caller information as of calling log_store() and adding it as "[T$thread_id]" or "[C$processor_id]" upon printing to consoles. Some examples for console output: [ 1.222773][ T1] x86: Booting SMP configuration: [ 2.779635][ T1] pci 0000:00:01.0: PCI bridge to [bus 01] [ 5.069193][ T268] Fusion MPT base driver 3.04.20 [ 9.316504][ C2] random: fast init done [ 13.413336][ T3355] Initialized host personality Some examples for /dev/kmsg output: 6,496,1222773,-,caller=T1;x86: Booting SMP configuration: 6,968,2779635,-,caller=T1;pci 0000:00:01.0: PCI bridge to [bus 01] SUBSYSTEM=pci DEVICE=+pci:0000:00:01.0 6,1353,5069193,-,caller=T268;Fusion MPT base driver 3.04.20 5,1526,9316504,-,caller=C2;random: fast init done 6,1575,13413336,-,caller=T3355;Initialized host personality Note that this patch changes max length of messages which can be printed by printk() or written to /dev/kmsg interface from 992 bytes to 976 bytes, based on an assumption that userspace won't try to write messages hitting that border line to /dev/kmsg interface. Link: http://lkml.kernel.org/r/93f19e57-5051-c67d-9af4-b17624062d44@i-love.sakura.ne.jp Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: LKML <linux-kernel@vger.kernel.org> Cc: syzkaller <syzkaller@googlegroups.com> Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Acked-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Signed-off-by: Petr Mladek <pmladek@suse.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/printk/printk.c55
1 files changed, 51 insertions, 4 deletions
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 91db332ccf4d..e3d977bbc7ab 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -357,6 +357,9 @@ struct printk_log {
357 u8 facility; /* syslog facility */ 357 u8 facility; /* syslog facility */
358 u8 flags:5; /* internal record flags */ 358 u8 flags:5; /* internal record flags */
359 u8 level:3; /* syslog level */ 359 u8 level:3; /* syslog level */
360#ifdef CONFIG_PRINTK_CALLER
361 u32 caller_id; /* thread id or processor id */
362#endif
360} 363}
361#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 364#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
362__packed __aligned(4) 365__packed __aligned(4)
@@ -423,7 +426,11 @@ static u64 exclusive_console_stop_seq;
423static u64 clear_seq; 426static u64 clear_seq;
424static u32 clear_idx; 427static u32 clear_idx;
425 428
429#ifdef CONFIG_PRINTK_CALLER
430#define PREFIX_MAX 48
431#else
426#define PREFIX_MAX 32 432#define PREFIX_MAX 32
433#endif
427#define LOG_LINE_MAX (1024 - PREFIX_MAX) 434#define LOG_LINE_MAX (1024 - PREFIX_MAX)
428 435
429#define LOG_LEVEL(v) ((v) & 0x07) 436#define LOG_LEVEL(v) ((v) & 0x07)
@@ -626,6 +633,12 @@ static int log_store(int facility, int level,
626 msg->ts_nsec = ts_nsec; 633 msg->ts_nsec = ts_nsec;
627 else 634 else
628 msg->ts_nsec = local_clock(); 635 msg->ts_nsec = local_clock();
636#ifdef CONFIG_PRINTK_CALLER
637 if (in_task())
638 msg->caller_id = task_pid_nr(current);
639 else
640 msg->caller_id = 0x80000000 + raw_smp_processor_id();
641#endif
629 memset(log_dict(msg) + dict_len, 0, pad_len); 642 memset(log_dict(msg) + dict_len, 0, pad_len);
630 msg->len = size; 643 msg->len = size;
631 644
@@ -689,12 +702,21 @@ static ssize_t msg_print_ext_header(char *buf, size_t size,
689 struct printk_log *msg, u64 seq) 702 struct printk_log *msg, u64 seq)
690{ 703{
691 u64 ts_usec = msg->ts_nsec; 704 u64 ts_usec = msg->ts_nsec;
705 char caller[20];
706#ifdef CONFIG_PRINTK_CALLER
707 u32 id = msg->caller_id;
708
709 snprintf(caller, sizeof(caller), ",caller=%c%u",
710 id & 0x80000000 ? 'C' : 'T', id & ~0x80000000);
711#else
712 caller[0] = '\0';
713#endif
692 714
693 do_div(ts_usec, 1000); 715 do_div(ts_usec, 1000);
694 716
695 return scnprintf(buf, size, "%u,%llu,%llu,%c;", 717 return scnprintf(buf, size, "%u,%llu,%llu,%c%s;",
696 (msg->facility << 3) | msg->level, seq, ts_usec, 718 (msg->facility << 3) | msg->level, seq, ts_usec,
697 msg->flags & LOG_CONT ? 'c' : '-'); 719 msg->flags & LOG_CONT ? 'c' : '-', caller);
698} 720}
699 721
700static ssize_t msg_print_ext_body(char *buf, size_t size, 722static ssize_t msg_print_ext_body(char *buf, size_t size,
@@ -1039,6 +1061,9 @@ void log_buf_vmcoreinfo_setup(void)
1039 VMCOREINFO_OFFSET(printk_log, len); 1061 VMCOREINFO_OFFSET(printk_log, len);
1040 VMCOREINFO_OFFSET(printk_log, text_len); 1062 VMCOREINFO_OFFSET(printk_log, text_len);
1041 VMCOREINFO_OFFSET(printk_log, dict_len); 1063 VMCOREINFO_OFFSET(printk_log, dict_len);
1064#ifdef CONFIG_PRINTK_CALLER
1065 VMCOREINFO_OFFSET(printk_log, caller_id);
1066#endif
1042} 1067}
1043#endif 1068#endif
1044 1069
@@ -1237,10 +1262,23 @@ static size_t print_time(u64 ts, char *buf)
1237{ 1262{
1238 unsigned long rem_nsec = do_div(ts, 1000000000); 1263 unsigned long rem_nsec = do_div(ts, 1000000000);
1239 1264
1240 return sprintf(buf, "[%5lu.%06lu] ", 1265 return sprintf(buf, "[%5lu.%06lu]",
1241 (unsigned long)ts, rem_nsec / 1000); 1266 (unsigned long)ts, rem_nsec / 1000);
1242} 1267}
1243 1268
1269#ifdef CONFIG_PRINTK_CALLER
1270static size_t print_caller(u32 id, char *buf)
1271{
1272 char caller[12];
1273
1274 snprintf(caller, sizeof(caller), "%c%u",
1275 id & 0x80000000 ? 'C' : 'T', id & ~0x80000000);
1276 return sprintf(buf, "[%6s]", caller);
1277}
1278#else
1279#define print_caller(id, buf) 0
1280#endif
1281
1244static size_t print_prefix(const struct printk_log *msg, bool syslog, 1282static size_t print_prefix(const struct printk_log *msg, bool syslog,
1245 bool time, char *buf) 1283 bool time, char *buf)
1246{ 1284{
@@ -1248,8 +1286,17 @@ static size_t print_prefix(const struct printk_log *msg, bool syslog,
1248 1286
1249 if (syslog) 1287 if (syslog)
1250 len = print_syslog((msg->facility << 3) | msg->level, buf); 1288 len = print_syslog((msg->facility << 3) | msg->level, buf);
1289
1251 if (time) 1290 if (time)
1252 len += print_time(msg->ts_nsec, buf + len); 1291 len += print_time(msg->ts_nsec, buf + len);
1292
1293 len += print_caller(msg->caller_id, buf + len);
1294
1295 if (IS_ENABLED(CONFIG_PRINTK_CALLER) || time) {
1296 buf[len++] = ' ';
1297 buf[len] = '\0';
1298 }
1299
1253 return len; 1300 return len;
1254} 1301}
1255 1302