[Crash-utility] [PATCH] Fix for "kmem -n" option on Linux 5.4-rc1

Masayoshi Mizuma msys.mizuma at gmail.com
Thu Oct 17 02:33:21 UTC 2019


From: Masayoshi Mizuma <m.mizuma at jp.fujitsu.com>

Fix for Linux 5.4-rc1 and later kernels that contain commit
b6c88d3b9d38 ("drivers/base/memory.c: don't store end_section_nr
in memory blocks"). Without this patch, kmem -n stops as the following:

  crash> kmem -n
  ...

  kmem: invalid structure member offset: memory_block_end_section_nr
        FILE: memory.c  LINE: 17426  FUNCTION: print_memory_block()

  [./crash] error trace: 4b0b83 => 4b00fe => 5430e1 => 543063

    543063: OFFSET_verify.part.28+51
    5430e1: OFFSET_verify+49
    4b00fe: print_memory_block+147
    4b0b83: dump_memory_blocks+813

To fix this, use either memory_block_size_probed. If the symbol
doesn't exist, then use memory_block.end_section_nr. Either value
should be available on the kernel.
And the start section number is enough to get the memory block,
so change the output to show the start section number.

Signed-off-by: Masayoshi Mizuma <m.mizuma at jp.fujitsu.com>
---
 help.c   |  2 +-
 memory.c | 42 +++++++++++++++++++++++++-----------------
 2 files changed, 26 insertions(+), 18 deletions(-)

diff --git a/help.c b/help.c
index a5218a7..cfd46c3 100644
--- a/help.c
+++ b/help.c
@@ -7177,7 +7177,7 @@ char *help_kmem[] = {
 "     6  ffff88003d4d90c0  ffffea0000000000  ffffea0000c00000   PM   196608",
 "     7  ffff88003d4d90e0  ffffea0000000000  ffffea0000e00000   PM   229376",
 "    ",
-"       MEM_BLOCK        NAME     PHYSICAL RANGE      STATE          SECTIONS",
+"       MEM_BLOCK        NAME     PHYSICAL RANGE      STATE          START_SECTION_NO",
 "     ffff88003a707c00  memory0          0 - 7ffffff  ONLINE         0",
 "     ffff88003a6e0000  memory1    8000000 - fffffff  ONLINE         1",
 "     ffff88003a6e1000  memory2   10000000 - 17ffffff ONLINE         2",
diff --git a/memory.c b/memory.c
index fe82fac..a7ed915 100644
--- a/memory.c
+++ b/memory.c
@@ -17402,20 +17402,18 @@ fill_memory_block_name(ulong memblock, char *name)
 }
 
 static void
-fill_memory_block_srange(ulong start_sec, ulong end_sec, char *srange)
+fill_memory_block_srange(ulong start_sec, char *srange)
 {
 	memset(srange, 0, sizeof(*srange) * BUFSIZE);
 
-	if (start_sec == end_sec)
-		sprintf(srange, "%lu", start_sec);
-	else
-		sprintf(srange, "%lu-%lu", start_sec, end_sec);
+	sprintf(srange, "%lu", start_sec);
 }
 
 static void
 print_memory_block(ulong memory_block)
 {
 	ulong start_sec, end_sec, start_pfn, end_pfn, nid;
+	ulong memblock_size, mbs, start_addr, end_addr;
 	char statebuf[BUFSIZE];
 	char srangebuf[BUFSIZE];
 	char name[BUFSIZE];
@@ -17430,15 +17428,25 @@ print_memory_block(ulong memory_block)
 	readmem(memory_block + OFFSET(memory_block_start_section_nr), KVADDR,
 		&start_sec, sizeof(void *), "memory_block start_section_nr",
 		FAULT_ON_ERROR);
-	readmem(memory_block + OFFSET(memory_block_end_section_nr), KVADDR,
-		&end_sec, sizeof(void *), "memory_block end_section_nr",
-		FAULT_ON_ERROR);
 
-	start_pfn = section_nr_to_pfn(start_sec);
-	end_pfn = section_nr_to_pfn(end_sec + 1);
+	start_addr = pfn_to_phys(section_nr_to_pfn(start_sec));
+
+	if (symbol_exists("memory_block_size_probed")) {
+		memblock_size = symbol_value("memory_block_size_probed");
+		readmem(memblock_size, KVADDR,
+			&mbs, sizeof(ulong), "memory_block_size_probed",
+			FAULT_ON_ERROR);
+		end_addr = start_addr + mbs - 1;
+	} else {
+	        readmem(memory_block + OFFSET(memory_block_end_section_nr), KVADDR,
+			&end_sec, sizeof(void *), "memory_block end_section_nr",
+			FAULT_ON_ERROR);
+		end_addr = pfn_to_phys(section_nr_to_pfn(end_sec + 1)) - 1;
+	}
+
 	fill_memory_block_state(memory_block, statebuf);
 	fill_memory_block_name(memory_block, name);
-	fill_memory_block_srange(start_sec, end_sec, srangebuf);
+	fill_memory_block_srange(start_sec, srangebuf);
 
 	if (MEMBER_EXISTS("memory_block", "nid")) {
 		readmem(memory_block + OFFSET(memory_block_nid), KVADDR, &nid,
@@ -17448,9 +17456,9 @@ print_memory_block(ulong memory_block)
 			MKSTR(memory_block)),
 			mkstring(buf2, 12, CENTER, name),
 			mkstring(buf3, PADDR_PRLEN, RJUST|LONG_HEX,
-			MKSTR(pfn_to_phys(start_pfn))),
+			MKSTR(start_addr)),
 			mkstring(buf4, PADDR_PRLEN, LJUST|LONG_HEX,
-			MKSTR(pfn_to_phys(end_pfn) - 1)),
+			MKSTR(end_addr)),
 			mkstring(buf5, strlen("NODE"), CENTER|LONG_DEC,
 			MKSTR(nid)),
 			mkstring(buf6, strlen("CANCEL_OFFLINE"), LJUST,
@@ -17462,9 +17470,9 @@ print_memory_block(ulong memory_block)
 			MKSTR(memory_block)),
 			mkstring(buf2, 10, CENTER, name),
 			mkstring(buf3, PADDR_PRLEN, RJUST|LONG_HEX,
-			MKSTR(pfn_to_phys(start_pfn))),
+			MKSTR(start_addr)),
 			mkstring(buf4, PADDR_PRLEN, LJUST|LONG_HEX,
-			MKSTR(pfn_to_phys(end_pfn) - 1)),
+			MKSTR(end_addr)),
 			mkstring(buf5, strlen("CANCEL_OFFLINE"), LJUST,
 			statebuf),
 			mkstring(buf6, 12, LJUST, srangebuf));
@@ -17552,14 +17560,14 @@ dump_memory_blocks(int initialize)
 			mkstring(buf3, PADDR_PRLEN*2 + 2, CENTER, "PHYSICAL RANGE"),
 			mkstring(buf4, strlen("NODE"), CENTER, "NODE"),
 			mkstring(buf5, strlen("CANCEL_OFFLINE"), LJUST, "STATE"),
-			mkstring(buf6, 12, LJUST, "SECTIONS"));
+			mkstring(buf6, 12, LJUST, "START_SECTION_NO"));
 	else
 		sprintf(mb_hdr, "\n%s %s %s     %s %s\n",
 			mkstring(buf1, VADDR_PRLEN, CENTER|LJUST, "MEM_BLOCK"),
 			mkstring(buf2, 10, CENTER, "NAME"),
 			mkstring(buf3, PADDR_PRLEN*2, CENTER, "PHYSICAL RANGE"),
 			mkstring(buf4, strlen("CANCEL_OFFLINE"), LJUST, "STATE"),
-			mkstring(buf5, 12, LJUST, "SECTIONS"));
+			mkstring(buf5, 12, LJUST, "START_SECTION_NO"));
 	fprintf(fp, "%s", mb_hdr);
 
 	for (i = 0; i < klistcnt; i++) {
-- 
2.18.1




More information about the Crash-utility mailing list