>From d996cc4dd34ae62f1be790ad0e6921601ace17bc Mon Sep 17 00:00:00 2001
From: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
Date: Mon, 2 Feb 2015 11:29:17 +0900
Subject: [PATCH] sadump: Support more than 16TB physical memory space

This patch makes sadump format support more than 16TB physical memory
space.

The limitation is caused by several members of dump_header structure:
max_mapnr and the others. They have 4 byte length only. In particular,
max_mapnr member gets overflow if more than 16TB physical memory space
is given.

To support more than 16TB physical memory space, this patch adds new 4
64-bit length members in dump_header structure:

- max_mapnr_64
- total_ram_blocks_64
- device_blocks_64
- written_blocks_64

Next table shows correspondence between the 32-bit version and the
64-bit version members:

    | 32-bit version         | 64-bit version            |
    |------------------------+---------------------------|
    | max_mapnr              | max_mapnr_64              |
    | total_ram_blocks       | total_ram_blocks_64       |
    | device_blocks          | device_blocks_64          |
    | written_blocks         | written_blocks_64         |

In addition, header_version member of dump_header structure is
increased to 1 in this extended new format.

Old crash utility can access the new sadump format under 16TB
correctly.

Current implementation treats vmcore with kernel version 2 or later as
kernel version 1, assuming backward compatibility.

Signed-off-by: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
---
 sadump.c | 30 ++++++++++++++++++++++++++++--
 sadump.h | 10 ++++++++++
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/sadump.c b/sadump.c
index d7c6701..bc67354 100644
--- a/sadump.c
+++ b/sadump.c
@@ -20,6 +20,7 @@
 #include "sadump.h"
 #include <arpa/inet.h> /* htonl, htons */
 #include <elf.h>
+#include <inttypes.h>
 
 enum {
 	failed = -1
@@ -325,6 +326,20 @@ restart:
 
 	flags |= SADUMP_LOCAL;
 
+	switch (sh->header_version) {
+	case 0:
+		sd->max_mapnr = (uint64_t)sh->max_mapnr;
+		break;
+	default:
+		error(WARNING,
+		      "sadump: unsupported header version: %u\n"
+		      "sadump: assuming header version: 1\n",
+		      sh->header_version);
+	case 1:
+		sd->max_mapnr = sh->max_mapnr_64;
+		break;
+	}
+
 	if (sh->sub_hdr_size > 0) {
 		if (!read_device(&smram_cpu_state_size, sizeof(uint32_t),
 				 &offset)) {
@@ -772,7 +787,7 @@ int read_sadump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
 	curpaddr = paddr & ~((physaddr_t)(sd->block_size-1));
 	page_offset = paddr & ((physaddr_t)(sd->block_size-1));
 
-	if ((pfn >= sd->dump_header->max_mapnr) || !page_is_ram(pfn))
+	if ((pfn >= sd->max_mapnr) || !page_is_ram(pfn))
 		return SEEK_ERROR;
 	if (!page_is_dumpable(pfn)) {
 		if (sd->flags & SADUMP_ZERO_EXCLUDED)
@@ -979,6 +994,17 @@ int sadump_memory_dump(FILE *fp)
 	fprintf(fp, "      written_blocks: %u\n", sh->written_blocks);
 	fprintf(fp, "         current_cpu: %u\n", sh->current_cpu);
 	fprintf(fp, "             nr_cpus: %u\n", sh->nr_cpus);
+	if (sh->header_version >= 1) {
+		fprintf(fp,
+			"        max_mapnr_64: %" PRIu64 "\n"
+			" total_ram_blocks_64: %" PRIu64 "\n"
+			"    device_blocks_64: %" PRIu64 "\n"
+			"   written_blocks_64: %" PRIu64 "\n",
+			sh->max_mapnr_64,
+			sh->total_ram_blocks_64,
+			sh->device_blocks_64,
+			sh->written_blocks_64);
+	}
 
 	fprintf(fp, "\n    dump sub heaer: ");
 	if (sh->sub_hdr_size > 0) {
@@ -1556,7 +1582,7 @@ static int block_table_init(void)
 {
 	uint64_t pfn, section, max_section, *block_table;
 
-	max_section = divideup(sd->dump_header->max_mapnr, SADUMP_PF_SECTION_NUM);
+	max_section = divideup(sd->max_mapnr, SADUMP_PF_SECTION_NUM);
 
 	block_table = calloc(sizeof(uint64_t), max_section);
 	if (!block_table) {
diff --git a/sadump.h b/sadump.h
index 09e313e..7f8e384 100644
--- a/sadump.h
+++ b/sadump.h
@@ -103,6 +103,14 @@ struct sadump_header {
 	uint32_t written_blocks;	/* Number of written blocks */
 	uint32_t current_cpu;	/* CPU# which handles dump */
 	uint32_t nr_cpus;	/* Number of CPUs */
+	/*
+	 * The members from below are supported in header version 1
+	 * and later.
+	 */
+	uint64_t max_mapnr_64;
+	uint64_t total_ram_blocks_64;
+	uint64_t device_blocks_64;
+	uint64_t written_blocks_64;
 };
 
 struct sadump_apic_state {
@@ -209,6 +217,8 @@ struct sadump_data {
 	ulonglong backup_src_start;
 	ulong backup_src_size;
 	ulonglong backup_offset;
+
+	uint64_t max_mapnr;
 };
 
 struct sadump_data *sadump_get_sadump_data(void);
-- 
1.9.3

