Add support for lockless ringbuffer
Release crash-7.2.9-2 Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
This commit is contained in:
parent
cd525b14e6
commit
724c99dde0
@ -4,7 +4,7 @@
|
||||
Summary: Kernel analysis utility for live systems, netdump, diskdump, kdump, LKCD or mcore dumpfiles
|
||||
Name: crash
|
||||
Version: 7.2.9
|
||||
Release: 1%{?dist}
|
||||
Release: 2%{?dist}
|
||||
License: GPLv3
|
||||
Source0: https://github.com/crash-utility/crash/archive/crash-%{version}.tar.gz
|
||||
Source1: http://ftp.gnu.org/gnu/gdb/gdb-7.6.tar.gz
|
||||
@ -18,6 +18,8 @@ Provides: bundled(libiberty)
|
||||
Provides: bundled(gdb) = 7.6
|
||||
Patch0: lzo_snappy.patch
|
||||
Patch1: use_system_readline_v3.patch
|
||||
Patch2: printk-add-support-for-lockless-ringbuffer.patch
|
||||
Patch3: printk-use-committed-finalized-state-values.patch
|
||||
|
||||
%description
|
||||
The core analysis suite is a self-contained tool that can be used to
|
||||
@ -39,6 +41,8 @@ offered by Mission Critical Linux, or the LKCD kernel patch.
|
||||
%setup -n %{name}-%{version} -q
|
||||
%patch0 -p1 -b lzo_snappy.patch
|
||||
%patch1 -p1 -b use_system_readline_v3.patch
|
||||
%patch2 -p1 -b printk-add-support-for-lockless-ringbuffer.patch
|
||||
%patch3 -p1 -b printk-use-committed-finalized-state-values.patch
|
||||
|
||||
%build
|
||||
# This package has an internal copy of GDB which has broken configure code for
|
||||
@ -70,6 +74,9 @@ cp -p defs.h %{buildroot}%{_includedir}/crash
|
||||
%{_includedir}/*
|
||||
|
||||
%changelog
|
||||
* Fri Dec 11 2020 Lianbo Jiang <lijiang@redhat.com> - 7.2.9-2
|
||||
- Add support for lockless ringbuffer
|
||||
|
||||
* Wed Nov 25 2020 Lianbo Jiang <lijiang@redhat.com> - 7.2.9-1
|
||||
- Update to latest upstream release
|
||||
|
||||
|
442
printk-add-support-for-lockless-ringbuffer.patch
Normal file
442
printk-add-support-for-lockless-ringbuffer.patch
Normal file
@ -0,0 +1,442 @@
|
||||
From a5531b24750e7949c35640d996ea14c0587938bc Mon Sep 17 00:00:00 2001
|
||||
From: John Ogness <john.ogness@linutronix.de>
|
||||
Date: Fri, 20 Nov 2020 05:56:59 +0000
|
||||
Subject: [PATCH 1/2] printk: add support for lockless ringbuffer
|
||||
|
||||
Linux 5.10 introduces a new lockless ringbuffer. The new ringbuffer
|
||||
is structured completely different to the previous iterations.
|
||||
Add support for dumping the ringbuffer with the "log" command.
|
||||
The new ringbuffer is detected based on the availability of
|
||||
the "prb" symbol.
|
||||
|
||||
Signed-off-by: John Ogness <john.ogness@linutronix.de>
|
||||
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
|
||||
---
|
||||
Makefile | 5 ++
|
||||
defs.h | 30 +++++++
|
||||
kernel.c | 7 +-
|
||||
printk.c | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
symbols.c | 27 ++++++
|
||||
5 files changed, 324 insertions(+), 1 deletion(-)
|
||||
create mode 100644 printk.c
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index d1857190c2fb..f66eba7418d1 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -61,6 +61,7 @@ VMWARE_HFILES=vmware_vmss.h
|
||||
|
||||
CFILES=main.c tools.c global_data.c memory.c filesys.c help.c task.c \
|
||||
kernel.c test.c gdb_interface.c configure.c net.c dev.c bpf.c \
|
||||
+ printk.c \
|
||||
alpha.c x86.c ppc.c ia64.c s390.c s390x.c s390dbf.c ppc64.c x86_64.c \
|
||||
arm.c arm64.c mips.c sparc64.c \
|
||||
extensions.c remote.c va_server.c va_server_v1.c symbols.c cmdline.c \
|
||||
@@ -80,6 +81,7 @@ SOURCE_FILES=${CFILES} ${GENERIC_HFILES} ${MCORE_HFILES} \
|
||||
|
||||
OBJECT_FILES=main.o tools.o global_data.o memory.o filesys.o help.o task.o \
|
||||
build_data.o kernel.o test.o gdb_interface.o net.o dev.o bpf.o \
|
||||
+ printk.o \
|
||||
alpha.o x86.o ppc.o ia64.o s390.o s390x.o s390dbf.o ppc64.o x86_64.o \
|
||||
arm.o arm64.o mips.o sparc64.o \
|
||||
extensions.o remote.o va_server.o va_server_v1.o symbols.o cmdline.o \
|
||||
@@ -363,6 +365,9 @@ task.o: ${GENERIC_HFILES} task.c
|
||||
kernel.o: ${GENERIC_HFILES} kernel.c
|
||||
${CC} -c ${CRASH_CFLAGS} kernel.c ${WARNING_OPTIONS} ${WARNING_ERROR}
|
||||
|
||||
+printk.o: ${GENERIC_HFILES} printk.c
|
||||
+ ${CC} -c ${CRASH_CFLAGS} printk.c ${WARNING_OPTIONS} ${WARNING_ERROR}
|
||||
+
|
||||
gdb_interface.o: ${GENERIC_HFILES} gdb_interface.c
|
||||
${CC} -c ${CRASH_CFLAGS} gdb_interface.c ${WARNING_OPTIONS} ${WARNING_ERROR}
|
||||
|
||||
diff --git a/defs.h b/defs.h
|
||||
index 95949507cae4..e1a18e9d0b4d 100644
|
||||
--- a/defs.h
|
||||
+++ b/defs.h
|
||||
@@ -2106,6 +2106,28 @@ struct offset_table { /* stash of commonly-used offsets */
|
||||
long irq_common_data_affinity;
|
||||
long irq_desc_irq_common_data;
|
||||
long uts_namespace_name;
|
||||
+ long printk_info_seq;
|
||||
+ long printk_info_ts_nsec;
|
||||
+ long printk_info_text_len;
|
||||
+ long printk_info_level;
|
||||
+ long printk_info_caller_id;
|
||||
+ long printk_info_dev_info;
|
||||
+ long dev_printk_info_subsystem;
|
||||
+ long dev_printk_info_device;
|
||||
+ long prb_desc_ring;
|
||||
+ long prb_text_data_ring;
|
||||
+ long prb_desc_ring_count_bits;
|
||||
+ long prb_desc_ring_descs;
|
||||
+ long prb_desc_ring_infos;
|
||||
+ long prb_desc_ring_head_id;
|
||||
+ long prb_desc_ring_tail_id;
|
||||
+ long prb_desc_state_var;
|
||||
+ long prb_desc_text_blk_lpos;
|
||||
+ long prb_data_blk_lpos_begin;
|
||||
+ long prb_data_blk_lpos_next;
|
||||
+ long prb_data_ring_size_bits;
|
||||
+ long prb_data_ring_data;
|
||||
+ long atomic_long_t_counter;
|
||||
};
|
||||
|
||||
struct size_table { /* stash of commonly-used sizes */
|
||||
@@ -2265,6 +2287,9 @@ struct size_table { /* stash of commonly-used sizes */
|
||||
long xa_node;
|
||||
long zram_table_entry;
|
||||
long irq_common_data;
|
||||
+ long printk_info;
|
||||
+ long printk_ringbuffer;
|
||||
+ long prb_desc;
|
||||
};
|
||||
|
||||
struct array_table {
|
||||
@@ -6696,6 +6721,11 @@ int vmware_guestdump_memory_dump(FILE *);
|
||||
*/
|
||||
int calc_kaslr_offset(ulong *, ulong *);
|
||||
|
||||
+/*
|
||||
+ * printk.c
|
||||
+ */
|
||||
+void dump_lockless_record_log(int);
|
||||
+
|
||||
/*
|
||||
* gnu_binutils.c
|
||||
*/
|
||||
diff --git a/kernel.c b/kernel.c
|
||||
index 98716372c8be..e722ff941527 100644
|
||||
--- a/kernel.c
|
||||
+++ b/kernel.c
|
||||
@@ -5042,6 +5042,11 @@ dump_log(int msg_flags)
|
||||
struct syment *nsp;
|
||||
int log_wrap, loglevel, log_buf_len;
|
||||
|
||||
+ if (kernel_symbol_exists("prb")) {
|
||||
+ dump_lockless_record_log(msg_flags);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (kernel_symbol_exists("log_first_idx") &&
|
||||
kernel_symbol_exists("log_next_idx")) {
|
||||
dump_variable_length_record_log(msg_flags);
|
||||
@@ -5289,7 +5294,7 @@ dump_log_entry(char *logptr, int msg_flags)
|
||||
}
|
||||
|
||||
/*
|
||||
- * Handle the new variable-length-record log_buf.
|
||||
+ * Handle the variable-length-record log_buf.
|
||||
*/
|
||||
static void
|
||||
dump_variable_length_record_log(int msg_flags)
|
||||
diff --git a/printk.c b/printk.c
|
||||
new file mode 100644
|
||||
index 000000000000..f6d54ce9d0d8
|
||||
--- /dev/null
|
||||
+++ b/printk.c
|
||||
@@ -0,0 +1,256 @@
|
||||
+#include "defs.h"
|
||||
+#include <ctype.h>
|
||||
+
|
||||
+#define DESC_SV_BITS (sizeof(unsigned long) * 8)
|
||||
+#define DESC_COMMITTED_MASK (1UL << (DESC_SV_BITS - 1))
|
||||
+#define DESC_REUSE_MASK (1UL << (DESC_SV_BITS - 2))
|
||||
+#define DESC_FLAGS_MASK (DESC_COMMITTED_MASK | DESC_REUSE_MASK)
|
||||
+#define DESC_ID_MASK (~DESC_FLAGS_MASK)
|
||||
+
|
||||
+/* convenience struct for passing many values to helper functions */
|
||||
+struct prb_map {
|
||||
+ char *prb;
|
||||
+
|
||||
+ char *desc_ring;
|
||||
+ unsigned long desc_ring_count;
|
||||
+ char *descs;
|
||||
+ char *infos;
|
||||
+
|
||||
+ char *text_data_ring;
|
||||
+ unsigned long text_data_ring_size;
|
||||
+ char *text_data;
|
||||
+};
|
||||
+
|
||||
+static void
|
||||
+init_offsets(void)
|
||||
+{
|
||||
+ char *n;
|
||||
+
|
||||
+ n = "printk_info";
|
||||
+ STRUCT_SIZE_INIT(printk_info, n);
|
||||
+ MEMBER_OFFSET_INIT(printk_info_seq, n, "seq");
|
||||
+ MEMBER_OFFSET_INIT(printk_info_ts_nsec, n, "ts_nsec");
|
||||
+ MEMBER_OFFSET_INIT(printk_info_text_len, n, "text_len");
|
||||
+ MEMBER_OFFSET_INIT(printk_info_level, n, "level");
|
||||
+ MEMBER_OFFSET_INIT(printk_info_caller_id, n, "caller_id");
|
||||
+ MEMBER_OFFSET_INIT(printk_info_dev_info, n, "dev_info");
|
||||
+
|
||||
+ n = "dev_printk_info";
|
||||
+ MEMBER_OFFSET_INIT(dev_printk_info_subsystem, n, "subsystem");
|
||||
+ MEMBER_OFFSET_INIT(dev_printk_info_device, n, "device");
|
||||
+
|
||||
+ n = "printk_ringbuffer";
|
||||
+ STRUCT_SIZE_INIT(printk_ringbuffer, n);
|
||||
+ MEMBER_OFFSET_INIT(prb_desc_ring, n, "desc_ring");
|
||||
+ MEMBER_OFFSET_INIT(prb_text_data_ring, n, "text_data_ring");
|
||||
+
|
||||
+ n = "prb_desc_ring";
|
||||
+ MEMBER_OFFSET_INIT(prb_desc_ring_count_bits, n, "count_bits");
|
||||
+ MEMBER_OFFSET_INIT(prb_desc_ring_descs, n, "descs");
|
||||
+ MEMBER_OFFSET_INIT(prb_desc_ring_infos, n, "infos");
|
||||
+ MEMBER_OFFSET_INIT(prb_desc_ring_head_id, n, "head_id");
|
||||
+ MEMBER_OFFSET_INIT(prb_desc_ring_tail_id, n, "tail_id");
|
||||
+
|
||||
+ n = "prb_desc";
|
||||
+ STRUCT_SIZE_INIT(prb_desc, n);
|
||||
+ MEMBER_OFFSET_INIT(prb_desc_state_var, n, "state_var");
|
||||
+ MEMBER_OFFSET_INIT(prb_desc_text_blk_lpos, n, "text_blk_lpos");
|
||||
+
|
||||
+ n = "prb_data_blk_lpos";
|
||||
+ MEMBER_OFFSET_INIT(prb_data_blk_lpos_begin, n, "begin");
|
||||
+ MEMBER_OFFSET_INIT(prb_data_blk_lpos_next, n, "next");
|
||||
+
|
||||
+ n = "prb_data_ring";
|
||||
+ MEMBER_OFFSET_INIT(prb_data_ring_size_bits, n, "size_bits");
|
||||
+ MEMBER_OFFSET_INIT(prb_data_ring_data, n, "data");
|
||||
+
|
||||
+ n = "atomic_long_t";
|
||||
+ MEMBER_OFFSET_INIT(atomic_long_t_counter, n, "counter");
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+dump_record(struct prb_map *m, unsigned long id, int msg_flags)
|
||||
+{
|
||||
+ unsigned short text_len;
|
||||
+ unsigned long state_var;
|
||||
+ unsigned int caller_id;
|
||||
+ unsigned char level;
|
||||
+ unsigned long begin;
|
||||
+ unsigned long next;
|
||||
+ char buf[BUFSIZE];
|
||||
+ uint64_t ts_nsec;
|
||||
+ ulonglong nanos;
|
||||
+ ulonglong seq;
|
||||
+ int ilen = 0, i;
|
||||
+ char *desc, *info, *text, *p;
|
||||
+ ulong rem;
|
||||
+
|
||||
+ desc = m->descs + ((id % m->desc_ring_count) * SIZE(prb_desc));
|
||||
+
|
||||
+ /* skip non-committed record */
|
||||
+ state_var = ULONG(desc + OFFSET(prb_desc_state_var) +
|
||||
+ OFFSET(atomic_long_t_counter));
|
||||
+ if ((state_var & DESC_FLAGS_MASK) != DESC_COMMITTED_MASK)
|
||||
+ return;
|
||||
+
|
||||
+ info = m->infos + ((id % m->desc_ring_count) * SIZE(printk_info));
|
||||
+
|
||||
+ seq = ULONGLONG(info + OFFSET(printk_info_seq));
|
||||
+ caller_id = UINT(info + OFFSET(printk_info_caller_id));
|
||||
+ if (CRASHDEBUG(1))
|
||||
+ fprintf(fp, "seq: %llu caller_id: %x (%s: %u)\n", seq, caller_id,
|
||||
+ caller_id & 0x80000000 ? "cpu" : "pid", caller_id & ~0x80000000);
|
||||
+
|
||||
+ text_len = USHORT(info + OFFSET(printk_info_text_len));
|
||||
+
|
||||
+ begin = ULONG(desc + OFFSET(prb_desc_text_blk_lpos) +
|
||||
+ OFFSET(prb_data_blk_lpos_begin)) %
|
||||
+ m->text_data_ring_size;
|
||||
+ next = ULONG(desc + OFFSET(prb_desc_text_blk_lpos) +
|
||||
+ OFFSET(prb_data_blk_lpos_next)) %
|
||||
+ m->text_data_ring_size;
|
||||
+
|
||||
+ /* skip data-less text blocks */
|
||||
+ if (begin == next)
|
||||
+ goto out;
|
||||
+
|
||||
+ if ((msg_flags & SHOW_LOG_TEXT) == 0) {
|
||||
+ ts_nsec = ULONGLONG(info + OFFSET(printk_info_ts_nsec));
|
||||
+ nanos = (ulonglong)ts_nsec / (ulonglong)1000000000;
|
||||
+ rem = (ulonglong)ts_nsec % (ulonglong)1000000000;
|
||||
+ if (msg_flags & SHOW_LOG_CTIME) {
|
||||
+ time_t t = kt->boot_date.tv_sec + nanos;
|
||||
+ sprintf(buf, "[%s] ", ctime_tz(&t));
|
||||
+ } else
|
||||
+ sprintf(buf, "[%5lld.%06ld] ", nanos, rem/1000);
|
||||
+
|
||||
+ ilen += strlen(buf);
|
||||
+ fprintf(fp, "%s", buf);
|
||||
+ }
|
||||
+
|
||||
+ if (msg_flags & SHOW_LOG_LEVEL) {
|
||||
+ level = UCHAR(info + OFFSET(printk_info_level)) >> 5;
|
||||
+ sprintf(buf, "<%x>", level);
|
||||
+ ilen += strlen(buf);
|
||||
+ fprintf(fp, "%s", buf);
|
||||
+ }
|
||||
+
|
||||
+ /* handle wrapping data block */
|
||||
+ if (begin > next)
|
||||
+ begin = 0;
|
||||
+
|
||||
+ /* skip over descriptor ID */
|
||||
+ begin += sizeof(unsigned long);
|
||||
+
|
||||
+ /* handle truncated messages */
|
||||
+ if (next - begin < text_len)
|
||||
+ text_len = next - begin;
|
||||
+
|
||||
+ text = m->text_data + begin;
|
||||
+
|
||||
+ for (i = 0, p = text; i < text_len; i++, p++) {
|
||||
+ if (*p == '\n')
|
||||
+ fprintf(fp, "\n%s", space(ilen));
|
||||
+ else if (isprint(*p) || isspace(*p))
|
||||
+ fputc(*p, fp);
|
||||
+ else
|
||||
+ fputc('.', fp);
|
||||
+ }
|
||||
+
|
||||
+ if (msg_flags & SHOW_LOG_DICT) {
|
||||
+ text = info + OFFSET(printk_info_dev_info) +
|
||||
+ OFFSET(dev_printk_info_subsystem);
|
||||
+ if (strlen(text))
|
||||
+ fprintf(fp, "\n%sSUBSYSTEM=%s", space(ilen), text);
|
||||
+
|
||||
+ text = info + OFFSET(printk_info_dev_info) +
|
||||
+ OFFSET(dev_printk_info_device);
|
||||
+ if (strlen(text))
|
||||
+ fprintf(fp, "\n%sDEVICE=%s", space(ilen), text);
|
||||
+ }
|
||||
+out:
|
||||
+ fprintf(fp, "\n");
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Handle the lockless printk_ringbuffer.
|
||||
+ */
|
||||
+void
|
||||
+dump_lockless_record_log(int msg_flags)
|
||||
+{
|
||||
+ unsigned long head_id;
|
||||
+ unsigned long tail_id;
|
||||
+ unsigned long kaddr;
|
||||
+ unsigned long id;
|
||||
+ struct prb_map m;
|
||||
+
|
||||
+ if (INVALID_SIZE(printk_info))
|
||||
+ init_offsets();
|
||||
+
|
||||
+ /* setup printk_ringbuffer */
|
||||
+ get_symbol_data("prb", sizeof(char *), &kaddr);
|
||||
+ m.prb = GETBUF(SIZE(printk_ringbuffer));
|
||||
+ if (!readmem(kaddr, KVADDR, m.prb, SIZE(printk_ringbuffer),
|
||||
+ "printk_ringbuffer contents", RETURN_ON_ERROR|QUIET)) {
|
||||
+ error(WARNING, "\ncannot read printk_ringbuffer contents\n");
|
||||
+ goto out_prb;
|
||||
+ }
|
||||
+
|
||||
+ /* setup descriptor ring */
|
||||
+ m.desc_ring = m.prb + OFFSET(prb_desc_ring);
|
||||
+ m.desc_ring_count = 1 << UINT(m.desc_ring + OFFSET(prb_desc_ring_count_bits));
|
||||
+
|
||||
+ kaddr = ULONG(m.desc_ring + OFFSET(prb_desc_ring_descs));
|
||||
+ m.descs = GETBUF(SIZE(prb_desc) * m.desc_ring_count);
|
||||
+ if (!readmem(kaddr, KVADDR, m.descs, SIZE(prb_desc) * m.desc_ring_count,
|
||||
+ "prb_desc_ring contents", RETURN_ON_ERROR|QUIET)) {
|
||||
+ error(WARNING, "\ncannot read prb_desc_ring contents\n");
|
||||
+ goto out_descs;
|
||||
+ }
|
||||
+
|
||||
+ kaddr = ULONG(m.desc_ring + OFFSET(prb_desc_ring_infos));
|
||||
+ m.infos = GETBUF(SIZE(printk_info) * m.desc_ring_count);
|
||||
+ if (!readmem(kaddr, KVADDR, m.infos, SIZE(printk_info) * m.desc_ring_count,
|
||||
+ "prb_info_ring contents", RETURN_ON_ERROR|QUIET)) {
|
||||
+ error(WARNING, "\ncannot read prb_info_ring contents\n");
|
||||
+ goto out_infos;
|
||||
+ }
|
||||
+
|
||||
+ /* setup text data ring */
|
||||
+ m.text_data_ring = m.prb + OFFSET(prb_text_data_ring);
|
||||
+ m.text_data_ring_size = 1 << UINT(m.text_data_ring + OFFSET(prb_data_ring_size_bits));
|
||||
+
|
||||
+ kaddr = ULONG(m.text_data_ring + OFFSET(prb_data_ring_data));
|
||||
+ m.text_data = GETBUF(m.text_data_ring_size);
|
||||
+ if (!readmem(kaddr, KVADDR, m.text_data, m.text_data_ring_size,
|
||||
+ "prb_text_data_ring contents", RETURN_ON_ERROR|QUIET)) {
|
||||
+ error(WARNING, "\ncannot read prb_text_data_ring contents\n");
|
||||
+ goto out_text_data;
|
||||
+ }
|
||||
+
|
||||
+ /* ready to go */
|
||||
+
|
||||
+ tail_id = ULONG(m.desc_ring + OFFSET(prb_desc_ring_tail_id) +
|
||||
+ OFFSET(atomic_long_t_counter));
|
||||
+ head_id = ULONG(m.desc_ring + OFFSET(prb_desc_ring_head_id) +
|
||||
+ OFFSET(atomic_long_t_counter));
|
||||
+
|
||||
+ hq_open();
|
||||
+
|
||||
+ for (id = tail_id; id != head_id; id = (id + 1) & DESC_ID_MASK)
|
||||
+ dump_record(&m, id, msg_flags);
|
||||
+
|
||||
+ /* dump head record */
|
||||
+ dump_record(&m, id, msg_flags);
|
||||
+
|
||||
+ hq_close();
|
||||
+
|
||||
+out_text_data:
|
||||
+ FREEBUF(m.text_data);
|
||||
+out_infos:
|
||||
+ FREEBUF(m.infos);
|
||||
+out_descs:
|
||||
+ FREEBUF(m.descs);
|
||||
+out_prb:
|
||||
+ FREEBUF(m.prb);
|
||||
+}
|
||||
diff --git a/symbols.c b/symbols.c
|
||||
index b2f4eb5402d1..a51078d58e6b 100644
|
||||
--- a/symbols.c
|
||||
+++ b/symbols.c
|
||||
@@ -10426,6 +10426,30 @@ dump_offset_table(char *spec, ulong makestruct)
|
||||
OFFSET(log_level));
|
||||
fprintf(fp, " log_flags_level: %ld\n",
|
||||
OFFSET(log_flags_level));
|
||||
+
|
||||
+ fprintf(fp, " printk_info_seq: %ld\n", OFFSET(printk_info_seq));
|
||||
+ fprintf(fp, " printk_info_ts_nseq: %ld\n", OFFSET(printk_info_ts_nsec));
|
||||
+ fprintf(fp, " printk_info_text_len: %ld\n", OFFSET(printk_info_text_len));
|
||||
+ fprintf(fp, " printk_info_level: %ld\n", OFFSET(printk_info_level));
|
||||
+ fprintf(fp, " printk_info_caller_id: %ld\n", OFFSET(printk_info_caller_id));
|
||||
+ fprintf(fp, " printk_info_dev_info: %ld\n", OFFSET(printk_info_dev_info));
|
||||
+ fprintf(fp, " dev_printk_info_subsystem: %ld\n", OFFSET(dev_printk_info_subsystem));
|
||||
+ fprintf(fp, " dev_printk_info_device: %ld\n", OFFSET(dev_printk_info_device));
|
||||
+ fprintf(fp, " prb_desc_ring: %ld\n", OFFSET(prb_desc_ring));
|
||||
+ fprintf(fp, " prb_text_data_ring: %ld\n", OFFSET(prb_text_data_ring));
|
||||
+ fprintf(fp, " prb_desc_ring_count_bits: %ld\n", OFFSET(prb_desc_ring_count_bits));
|
||||
+ fprintf(fp, " prb_desc_ring_descs: %ld\n", OFFSET(prb_desc_ring_descs));
|
||||
+ fprintf(fp, " prb_desc_ring_infos: %ld\n", OFFSET(prb_desc_ring_infos));
|
||||
+ fprintf(fp, " prb_desc_ring_head_id: %ld\n", OFFSET(prb_desc_ring_head_id));
|
||||
+ fprintf(fp, " prb_desc_ring_tail_id: %ld\n", OFFSET(prb_desc_ring_tail_id));
|
||||
+ fprintf(fp, " prb_desc_state_var: %ld\n", OFFSET(prb_desc_state_var));
|
||||
+ fprintf(fp, " prb_desc_text_blk_lpos: %ld\n", OFFSET(prb_desc_text_blk_lpos));
|
||||
+ fprintf(fp, " prb_data_blk_lpos_begin: %ld\n", OFFSET(prb_data_blk_lpos_begin));
|
||||
+ fprintf(fp, " prb_data_blk_lpos_next: %ld\n", OFFSET(prb_data_blk_lpos_next));
|
||||
+ fprintf(fp, " prb_data_ring_size_bits: %ld\n", OFFSET(prb_data_ring_size_bits));
|
||||
+ fprintf(fp, " prb_data_ring_data: %ld\n", OFFSET(prb_data_ring_data));
|
||||
+ fprintf(fp, " atomit_long_t_counter: %ld\n", OFFSET(atomic_long_t_counter));
|
||||
+
|
||||
fprintf(fp, " sched_rt_entity_my_q: %ld\n",
|
||||
OFFSET(sched_rt_entity_my_q));
|
||||
fprintf(fp, " task_group_parent: %ld\n",
|
||||
@@ -10850,6 +10874,9 @@ dump_offset_table(char *spec, ulong makestruct)
|
||||
SIZE(xarray));
|
||||
fprintf(fp, " xa_node: %ld\n",
|
||||
SIZE(xa_node));
|
||||
+ fprintf(fp, " printk_info: %ld\n", SIZE(printk_info));
|
||||
+ fprintf(fp, " printk_ringbuffer: %ld\n", SIZE(printk_ringbuffer));
|
||||
+ fprintf(fp, " prb_desc: %ld\n", SIZE(prb_desc));
|
||||
|
||||
|
||||
fprintf(fp, "\n array_table:\n");
|
||||
--
|
||||
2.17.1
|
||||
|
100
printk-use-committed-finalized-state-values.patch
Normal file
100
printk-use-committed-finalized-state-values.patch
Normal file
@ -0,0 +1,100 @@
|
||||
From 71e159c64000467e94e08aefc144f5e1cdaa4aa0 Mon Sep 17 00:00:00 2001
|
||||
From: John Ogness <john.ogness@linutronix.de>
|
||||
Date: Wed, 25 Nov 2020 05:27:53 +0106
|
||||
Subject: [PATCH 2/2] printk: use committed/finalized state values
|
||||
|
||||
An addendum to the previous crash commit a5531b24750e.
|
||||
The ringbuffer entries use 2 state values (committed and finalized)
|
||||
rather than a single flag to represent being available for reading.
|
||||
Copy the definitions and state lookup function directly from the
|
||||
kernel source and use the new states.
|
||||
|
||||
Signed-off-by: John Ogness <john.ogness@linutronix.de>
|
||||
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
|
||||
---
|
||||
printk.c | 48 +++++++++++++++++++++++++++++++++++++++++-------
|
||||
1 file changed, 41 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/printk.c b/printk.c
|
||||
index f6d54ce9d0d8..8658016e65bf 100644
|
||||
--- a/printk.c
|
||||
+++ b/printk.c
|
||||
@@ -1,12 +1,6 @@
|
||||
#include "defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
-#define DESC_SV_BITS (sizeof(unsigned long) * 8)
|
||||
-#define DESC_COMMITTED_MASK (1UL << (DESC_SV_BITS - 1))
|
||||
-#define DESC_REUSE_MASK (1UL << (DESC_SV_BITS - 2))
|
||||
-#define DESC_FLAGS_MASK (DESC_COMMITTED_MASK | DESC_REUSE_MASK)
|
||||
-#define DESC_ID_MASK (~DESC_FLAGS_MASK)
|
||||
-
|
||||
/* convenience struct for passing many values to helper functions */
|
||||
struct prb_map {
|
||||
char *prb;
|
||||
@@ -21,6 +15,44 @@ struct prb_map {
|
||||
char *text_data;
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * desc_state and DESC_* definitions taken from kernel source:
|
||||
+ *
|
||||
+ * kernel/printk/printk_ringbuffer.h
|
||||
+ */
|
||||
+
|
||||
+/* The possible responses of a descriptor state-query. */
|
||||
+enum desc_state {
|
||||
+ desc_miss = -1, /* ID mismatch (pseudo state) */
|
||||
+ desc_reserved = 0x0, /* reserved, in use by writer */
|
||||
+ desc_committed = 0x1, /* committed by writer, could get reopened */
|
||||
+ desc_finalized = 0x2, /* committed, no further modification allowed */
|
||||
+ desc_reusable = 0x3, /* free, not yet used by any writer */
|
||||
+};
|
||||
+
|
||||
+#define DESC_SV_BITS (sizeof(unsigned long) * 8)
|
||||
+#define DESC_FLAGS_SHIFT (DESC_SV_BITS - 2)
|
||||
+#define DESC_FLAGS_MASK (3UL << DESC_FLAGS_SHIFT)
|
||||
+#define DESC_STATE(sv) (3UL & (sv >> DESC_FLAGS_SHIFT))
|
||||
+#define DESC_ID_MASK (~DESC_FLAGS_MASK)
|
||||
+#define DESC_ID(sv) ((sv) & DESC_ID_MASK)
|
||||
+
|
||||
+/*
|
||||
+ * get_desc_state() taken from kernel source:
|
||||
+ *
|
||||
+ * kernel/printk/printk_ringbuffer.c
|
||||
+ */
|
||||
+
|
||||
+/* Query the state of a descriptor. */
|
||||
+static enum desc_state get_desc_state(unsigned long id,
|
||||
+ unsigned long state_val)
|
||||
+{
|
||||
+ if (id != DESC_ID(state_val))
|
||||
+ return desc_miss;
|
||||
+
|
||||
+ return DESC_STATE(state_val);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
init_offsets(void)
|
||||
{
|
||||
@@ -74,6 +106,7 @@ dump_record(struct prb_map *m, unsigned long id, int msg_flags)
|
||||
unsigned short text_len;
|
||||
unsigned long state_var;
|
||||
unsigned int caller_id;
|
||||
+ enum desc_state state;
|
||||
unsigned char level;
|
||||
unsigned long begin;
|
||||
unsigned long next;
|
||||
@@ -90,7 +123,8 @@ dump_record(struct prb_map *m, unsigned long id, int msg_flags)
|
||||
/* skip non-committed record */
|
||||
state_var = ULONG(desc + OFFSET(prb_desc_state_var) +
|
||||
OFFSET(atomic_long_t_counter));
|
||||
- if ((state_var & DESC_FLAGS_MASK) != DESC_COMMITTED_MASK)
|
||||
+ state = get_desc_state(id, state_var);
|
||||
+ if (state != desc_committed && state != desc_finalized)
|
||||
return;
|
||||
|
||||
info = m->infos + ((id % m->desc_ring_count) * SIZE(printk_info));
|
||||
--
|
||||
2.17.1
|
||||
|
Loading…
Reference in New Issue
Block a user