[PATCH v3 1/7] log: introduce -s option

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Introduce a new option -s for log command which outputs
unflushed logs of the printk safe buffers
(safe_print_seq/nmi_print_seq) as follows:

PRINTK_SAFE_SEQ_BUF: nmi_print_seq
CPU: 0  ADDR: ffff8ca4fbc19ce0 LEN: 150  MESSAGE_LOST: 0
Uhhuh. NMI received for unknown reason 20 on CPU 0.
Do you have a strange power saving mode enabled?
Dazed and confused, but trying to continue

The buffers are displayed for each CPU. For an empty
buffer, '(empty)' will be printed.

Signed-off-by: Shogo Matsumoto <shogo.matsumoto@xxxxxxxxxxx>
---
 defs.h   |   5 +++
 kernel.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 111 insertions(+), 1 deletion(-)

diff --git a/defs.h b/defs.h
index b63741c..c26e604 100644
--- a/defs.h
+++ b/defs.h
@@ -2146,6 +2146,9 @@ struct offset_table {                    /* stash of commonly-used offsets */
 	long wait_queue_entry_private;
 	long wait_queue_head_head;
 	long wait_queue_entry_entry;
+	long printk_safe_seq_buf_len;
+	long printk_safe_seq_buf_message_lost;
+	long printk_safe_seq_buf_buffer;
 };
 
 struct size_table {         /* stash of commonly-used sizes */
@@ -2310,6 +2313,7 @@ struct size_table {         /* stash of commonly-used sizes */
 	long prb_desc;
 	long wait_queue_entry;
 	long task_struct_state;
+	long printk_safe_seq_buf_buffer;
 };
 
 struct array_table {
@@ -5699,6 +5703,7 @@ void dump_log(int);
 #define SHOW_LOG_TEXT  (0x4)
 #define SHOW_LOG_AUDIT (0x8)
 #define SHOW_LOG_CTIME (0x10)
+#define SHOW_LOG_SAFE  (0x20)
 void set_cpu(int);
 void clear_machdep_cache(void);
 struct stack_hook *gather_text_list(struct bt_info *);
diff --git a/kernel.c b/kernel.c
index 37b7af7..461a5f2 100644
--- a/kernel.c
+++ b/kernel.c
@@ -93,6 +93,7 @@ static void source_tree_init(void);
 static ulong dump_audit_skb_queue(ulong);
 static ulong __dump_audit(char *);
 static void dump_audit(void);
+static void dump_printk_safe_seq_buf(int);
 static char *vmcoreinfo_read_string(const char *);
 static void check_vmcoreinfo(void);
 static int is_pvops_xen(void);
@@ -4998,7 +4999,7 @@ cmd_log(void)
 
 	msg_flags = 0;
 
-        while ((c = getopt(argcnt, args, "Ttdma")) != EOF) {
+        while ((c = getopt(argcnt, args, "Ttdmas")) != EOF) {
                 switch(c)
                 {
 		case 'T':
@@ -5016,6 +5017,9 @@ cmd_log(void)
 		case 'a':
 			msg_flags |= SHOW_LOG_AUDIT;
 			break;
+		case 's':
+			msg_flags |= SHOW_LOG_SAFE;
+			break;
                 default:
                         argerrs++;
                         break;
@@ -5047,6 +5051,11 @@ cmd_log(void)
 		return;
 	}
 
+	if (msg_flags & SHOW_LOG_SAFE) {
+		dump_printk_safe_seq_buf(msg_flags);
+		return;
+	}
+
 	dump_log(msg_flags);
 }
 
@@ -11544,6 +11553,102 @@ dump_audit(void)
 		error(INFO, "kernel audit log is empty\n");
 }
 
+static void
+__dump_printk_safe_seq_buf(char *buf_name, int msg_flags)
+{
+	int cpu, buffer_size;
+	char *buffer;
+	ulong base_addr, len_addr, message_lost_addr, buffer_addr;
+
+	if (!symbol_exists(buf_name)) {
+		return;
+	}
+
+	base_addr = symbol_value(buf_name);
+	len_addr = base_addr + OFFSET(printk_safe_seq_buf_len)
+			+ OFFSET(atomic_t_counter);
+	message_lost_addr = base_addr
+			+ OFFSET(printk_safe_seq_buf_message_lost)
+			+ OFFSET(atomic_t_counter);
+	buffer_addr = base_addr + OFFSET(printk_safe_seq_buf_buffer);
+	buffer_size = SIZE(printk_safe_seq_buf_buffer);
+	buffer = GETBUF(buffer_size);
+
+	fprintf(fp, "PRINTK_SAFE_SEQ_BUF: %s\n", buf_name);
+	for (cpu = 0; cpu < kt->cpus; cpu++) {
+		int len, message_lost;
+		ulong per_cpu_offset;
+		per_cpu_offset = kt->__per_cpu_offset[cpu];
+
+		readmem(len_addr + per_cpu_offset, KVADDR, &len, sizeof(int),
+			"printk_safe_seq_buf len", FAULT_ON_ERROR);
+		readmem(message_lost_addr + per_cpu_offset, KVADDR,
+			&message_lost, sizeof(int),
+			"printk_safe_seq_buf message_lost", FAULT_ON_ERROR);
+		fprintf(fp, "CPU: %d  ADDR: %lx LEN: %d  MESSAGE_LOST: %d\n",
+			cpu, base_addr + per_cpu_offset, len, message_lost);
+
+		if (len > 0) {
+			int i, n;
+			char *p;
+
+			readmem(buffer_addr + per_cpu_offset, KVADDR,
+				buffer, buffer_size,
+				"printk_safe_seq_buf buffer", FAULT_ON_ERROR);
+
+			n = (len <= buffer_size) ? len : buffer_size;
+			for (i = 0, p = buffer; i < n; i++, p++) {
+				if (*p == 0x1) { //SOH
+					i++; p++;
+					continue;
+				} else {
+					if (isprint(*p) || isspace(*p)) {
+						fputc(*p, fp);
+					} else {
+						fputc('.', fp);
+					}
+				}
+			}
+			fputc('\n', fp);
+		} else {
+			fprintf(fp, "(empty)\n\n");
+		}
+	}
+	FREEBUF(buffer);
+}
+
+static void
+dump_printk_safe_seq_buf(int msg_flags)
+{
+	if (!STRUCT_EXISTS("printk_safe_seq_buf"))
+		return;
+
+	if (INVALID_SIZE(printk_safe_seq_buf_buffer)) {
+		MEMBER_OFFSET_INIT(printk_safe_seq_buf_len,
+			"printk_safe_seq_buf", "len");
+		MEMBER_OFFSET_INIT(printk_safe_seq_buf_message_lost,
+			"printk_safe_seq_buf", "message_lost");
+		MEMBER_OFFSET_INIT(printk_safe_seq_buf_buffer,
+			"printk_safe_seq_buf", "buffer");
+
+		if (!INVALID_MEMBER(printk_safe_seq_buf_buffer)) {
+			MEMBER_SIZE_INIT(printk_safe_seq_buf_buffer,
+				"printk_safe_seq_buf", "buffer");
+		}
+	}
+
+	if (INVALID_MEMBER(printk_safe_seq_buf_len) ||
+	    INVALID_MEMBER(printk_safe_seq_buf_message_lost) ||
+	    INVALID_MEMBER(printk_safe_seq_buf_buffer) ||
+	    INVALID_SIZE(printk_safe_seq_buf_buffer)) {
+		error(INFO, "-s not supported with this kernel version\n");
+		return;
+	}
+
+	__dump_printk_safe_seq_buf("nmi_print_seq", msg_flags);
+	__dump_printk_safe_seq_buf("safe_print_seq", msg_flags);
+}
+
 /*
  * Reads a string value from the VMCOREINFO data stored in (live) memory.
  *
-- 
2.29.2


--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://listman.redhat.com/mailman/listinfo/crash-utility




[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux