|
|
ab224c |
From 8e124174b62376b17ac909bc68622ef07bde6840 Mon Sep 17 00:00:00 2001
|
|
|
ab224c |
Message-Id: <8e124174b62376b17ac909bc68622ef07bde6840.1382323707.git.bhe@redhat.com>
|
|
|
ab224c |
From: Jingbai Ma <jingbai.ma@hp.com>
|
|
|
ab224c |
Date: Fri, 18 Oct 2013 18:53:38 +0900
|
|
|
ab224c |
Subject: [PATCH] [PATCH v4] Fix max_mapnr issue on system has over 44-bit
|
|
|
ab224c |
addressing.
|
|
|
ab224c |
|
|
|
ab224c |
This patch will fix a bug of makedumpfile doesn't work correctly on system
|
|
|
ab224c |
has over 44-bit addressing in compression dump mode.
|
|
|
ab224c |
This bug was posted here:
|
|
|
ab224c |
http://lists.infradead.org/pipermail/kexec/2013-September/009587.html
|
|
|
ab224c |
|
|
|
ab224c |
This patch will add 3 new fields in struct kdump_sub_header.
|
|
|
ab224c |
unsigned long long start_pfn_64; /* header_version 6 and later */
|
|
|
ab224c |
unsigned long long end_pfn_64; /* header_version 6 and later */
|
|
|
ab224c |
unsigned long long max_mapnr_64; /* header_version 6 and later */
|
|
|
ab224c |
|
|
|
ab224c |
And the old "unsigned int max_mapnr" in struct disk_dump_header will
|
|
|
ab224c |
not be used anymore, but still be there for compatibility purpose.
|
|
|
ab224c |
|
|
|
ab224c |
The max_mapnr_64 only exists in strcut kdump_sub_header, and that only
|
|
|
ab224c |
for compressed kdump format, so for ELF format kdump files (non-compressed),
|
|
|
ab224c |
only the max_mapnr is available, so it still may be truncated for addresses
|
|
|
ab224c |
exceed 44bit (above 16TB).
|
|
|
ab224c |
|
|
|
ab224c |
This patch will change the header_version to 6.
|
|
|
ab224c |
|
|
|
ab224c |
The corresponding patch for crash utility can be found here:
|
|
|
ab224c |
http://lists.infradead.org/pipermail/kexec/2013-October/009750.html
|
|
|
ab224c |
|
|
|
ab224c |
This patch doesn't change sadump_header.
|
|
|
ab224c |
|
|
|
ab224c |
Changelog:
|
|
|
ab224c |
v4:
|
|
|
ab224c |
- Do not change max_mapnr_64 in kdump_sub_header in memory for old kernel.
|
|
|
ab224c |
|
|
|
ab224c |
v3:
|
|
|
ab224c |
- Change notes for max_mapnr, start_pfn and end_pfn as obsolete.
|
|
|
ab224c |
- Remove "(32bit)" from debug messages of max_mapnr, start_pfn and end_pfn.
|
|
|
ab224c |
- Set the 32bit start_pfn and end_pfn to UINT_MAX.
|
|
|
ab224c |
- Remove bitmap writting enhancement to another seperate patch.
|
|
|
ab224c |
- Change type of len_bitmap in struct DumpInfo back to unsigned long.
|
|
|
ab224c |
|
|
|
ab224c |
v2:
|
|
|
ab224c |
- Rename max_mapnr in struct kdump_sub_header to max_mapnr_64.
|
|
|
ab224c |
- Change type of max_mapnr_64 from unsigned long to unsigned long long.
|
|
|
ab224c |
In x86 PAE mode on x86_32 kernel, the address may exceeds 44bit limit.
|
|
|
ab224c |
- Add start_pfn_64, end_pfn_64 for struct kdump_sub_header.
|
|
|
ab224c |
- Only print 64bit start_pfn_64, end_pfn_64 and max_mapnr_64
|
|
|
ab224c |
debug messages for disk dump header version >= 6.
|
|
|
ab224c |
- Change type of bitmap_len in struct DumpInfo, from unsigned long to
|
|
|
ab224c |
unsigned long long.
|
|
|
ab224c |
- Enhance bitmap writting function in reassemble_kdump_header().
|
|
|
ab224c |
Prevent bitmap writting failure if the size of bitmap is too large to
|
|
|
ab224c |
fit a sigle write.
|
|
|
ab224c |
|
|
|
ab224c |
v1:
|
|
|
ab224c |
- http://lists.infradead.org/pipermail/kexec/2013-September/009662.html
|
|
|
ab224c |
|
|
|
ab224c |
Signed-off-by: Jingbai Ma <jingbai.ma@hp.com>
|
|
|
ab224c |
Tested-by: Lisa Mitchell <lisa.mitchell@hp.com>
|
|
|
ab224c |
---
|
|
|
ab224c |
IMPLEMENTATION | 15 ++++++++++---
|
|
|
ab224c |
diskdump_mod.h | 15 ++++++++++---
|
|
|
ab224c |
makedumpfile.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++------------
|
|
|
ab224c |
3 files changed, 77 insertions(+), 20 deletions(-)
|
|
|
ab224c |
|
|
|
ab224c |
diff --git a/makedumpfile-1.5.4/IMPLEMENTATION b/makedumpfile-1.5.4/IMPLEMENTATION
|
|
|
ab224c |
index f0f3135..2f4cfd6 100644
|
|
|
ab224c |
--- a/makedumpfile-1.5.4/IMPLEMENTATION
|
|
|
ab224c |
+++ b/makedumpfile-1.5.4/IMPLEMENTATION
|
|
|
ab224c |
@@ -48,7 +48,9 @@
|
|
|
ab224c |
header in blocks */
|
|
|
ab224c |
unsigned int bitmap_blocks; /* Size of Memory bitmap in
|
|
|
ab224c |
block */
|
|
|
ab224c |
- unsigned int max_mapnr; /* = max_mapnr */
|
|
|
ab224c |
+ unsigned int max_mapnr; /* = max_mapnr, OBSOLETE!
|
|
|
ab224c |
+ 32bit only, full 64bit
|
|
|
ab224c |
+ in sub header. */
|
|
|
ab224c |
unsigned int total_ram_blocks;/* Number of blocks should be
|
|
|
ab224c |
written */
|
|
|
ab224c |
unsigned int device_blocks; /* Number of total blocks in
|
|
|
ab224c |
@@ -69,14 +71,21 @@
|
|
|
ab224c |
unsigned long phys_base;
|
|
|
ab224c |
int dump_level; /* header_version 1 and later */
|
|
|
ab224c |
int split; /* header_version 2 and later */
|
|
|
ab224c |
- unsigned long start_pfn; /* header_version 2 and later */
|
|
|
ab224c |
- unsigned long end_pfn; /* header_version 2 and later */
|
|
|
ab224c |
+ unsigned long start_pfn; /* header_version 2 and later,
|
|
|
ab224c |
+ OBSOLETE! 32bit only, full
|
|
|
ab224c |
+ 64bit in start_pfn_64. */
|
|
|
ab224c |
+ unsigned long end_pfn; /* header_version 2 and later,
|
|
|
ab224c |
+ OBSOLETE! 32bit only, full
|
|
|
ab224c |
+ 64bit in end_pfn_64. */
|
|
|
ab224c |
off_t offset_vmcoreinfo;/* header_version 3 and later */
|
|
|
ab224c |
unsigned long size_vmcoreinfo; /* header_version 3 and later */
|
|
|
ab224c |
off_t offset_note; /* header_version 4 and later */
|
|
|
ab224c |
unsigned long size_note; /* header_version 4 and later */
|
|
|
ab224c |
off_t offset_eraseinfo; /* header_version 5 and later */
|
|
|
ab224c |
unsigned long size_eraseinfo; /* header_version 5 and later */
|
|
|
ab224c |
+ unsigned long long start_pfn_64; /* header_version 6 and later */
|
|
|
ab224c |
+ unsigned long long end_pfn_64; /* header_version 6 and later */
|
|
|
ab224c |
+ unsigned long long max_mapnr_64; /* header_version 6 and later */
|
|
|
ab224c |
};
|
|
|
ab224c |
|
|
|
ab224c |
- 1st-bitmap
|
|
|
ab224c |
diff --git a/makedumpfile-1.5.4/diskdump_mod.h b/makedumpfile-1.5.4/diskdump_mod.h
|
|
|
ab224c |
index 00ab852..dd24eb2 100644
|
|
|
ab224c |
--- a/makedumpfile-1.5.4/diskdump_mod.h
|
|
|
ab224c |
+++ b/makedumpfile-1.5.4/diskdump_mod.h
|
|
|
ab224c |
@@ -52,7 +52,9 @@ struct disk_dump_header {
|
|
|
ab224c |
header in blocks */
|
|
|
ab224c |
unsigned int bitmap_blocks; /* Size of Memory bitmap in
|
|
|
ab224c |
block */
|
|
|
ab224c |
- unsigned int max_mapnr; /* = max_mapnr */
|
|
|
ab224c |
+ unsigned int max_mapnr; /* = max_mapnr, OBSOLETE!
|
|
|
ab224c |
+ 32bit only, full 64bit
|
|
|
ab224c |
+ in sub header. */
|
|
|
ab224c |
unsigned int total_ram_blocks;/* Number of blocks should be
|
|
|
ab224c |
written */
|
|
|
ab224c |
unsigned int device_blocks; /* Number of total blocks in
|
|
|
ab224c |
@@ -71,14 +73,21 @@ struct kdump_sub_header {
|
|
|
ab224c |
unsigned long phys_base;
|
|
|
ab224c |
int dump_level; /* header_version 1 and later */
|
|
|
ab224c |
int split; /* header_version 2 and later */
|
|
|
ab224c |
- unsigned long start_pfn; /* header_version 2 and later */
|
|
|
ab224c |
- unsigned long end_pfn; /* header_version 2 and later */
|
|
|
ab224c |
+ unsigned long start_pfn; /* header_version 2 and later,
|
|
|
ab224c |
+ OBSOLETE! 32bit only, full
|
|
|
ab224c |
+ 64bit in start_pfn_64. */
|
|
|
ab224c |
+ unsigned long end_pfn; /* header_version 2 and later,
|
|
|
ab224c |
+ OBSOLETE! 32bit only, full
|
|
|
ab224c |
+ 64bit in end_pfn_64. */
|
|
|
ab224c |
off_t offset_vmcoreinfo;/* header_version 3 and later */
|
|
|
ab224c |
unsigned long size_vmcoreinfo; /* header_version 3 and later */
|
|
|
ab224c |
off_t offset_note; /* header_version 4 and later */
|
|
|
ab224c |
unsigned long size_note; /* header_version 4 and later */
|
|
|
ab224c |
off_t offset_eraseinfo; /* header_version 5 and later */
|
|
|
ab224c |
unsigned long size_eraseinfo; /* header_version 5 and later */
|
|
|
ab224c |
+ unsigned long long start_pfn_64; /* header_version 6 and later */
|
|
|
ab224c |
+ unsigned long long end_pfn_64; /* header_version 6 and later */
|
|
|
ab224c |
+ unsigned long long max_mapnr_64; /* header_version 6 and later */
|
|
|
ab224c |
};
|
|
|
ab224c |
|
|
|
ab224c |
/* page flags */
|
|
|
ab224c |
diff --git a/makedumpfile-1.5.4/makedumpfile.c b/makedumpfile-1.5.4/makedumpfile.c
|
|
|
ab224c |
index 9892108..428c53e 100644
|
|
|
ab224c |
--- a/makedumpfile-1.5.4/makedumpfile.c
|
|
|
ab224c |
+++ b/makedumpfile-1.5.4/makedumpfile.c
|
|
|
ab224c |
@@ -23,6 +23,7 @@
|
|
|
ab224c |
#include <stddef.h>
|
|
|
ab224c |
#include <ctype.h>
|
|
|
ab224c |
#include <sys/time.h>
|
|
|
ab224c |
+#include <limits.h>
|
|
|
ab224c |
|
|
|
ab224c |
struct symbol_table symbol_table;
|
|
|
ab224c |
struct size_table size_table;
|
|
|
ab224c |
@@ -125,7 +126,10 @@ get_max_mapnr(void)
|
|
|
ab224c |
unsigned long long max_paddr;
|
|
|
ab224c |
|
|
|
ab224c |
if (info->flag_refiltering) {
|
|
|
ab224c |
- info->max_mapnr = info->dh_memory->max_mapnr;
|
|
|
ab224c |
+ if (info->dh_memory->header_version >= 6)
|
|
|
ab224c |
+ info->max_mapnr = info->kh_memory->max_mapnr_64;
|
|
|
ab224c |
+ else
|
|
|
ab224c |
+ info->max_mapnr = info->dh_memory->max_mapnr;
|
|
|
ab224c |
return TRUE;
|
|
|
ab224c |
}
|
|
|
ab224c |
|
|
|
ab224c |
@@ -802,6 +806,12 @@ get_kdump_compressed_header_info(char *filename)
|
|
|
ab224c |
DEBUG_MSG(" split : %d\n", kh.split);
|
|
|
ab224c |
DEBUG_MSG(" start_pfn : 0x%lx\n", kh.start_pfn);
|
|
|
ab224c |
DEBUG_MSG(" end_pfn : 0x%lx\n", kh.end_pfn);
|
|
|
ab224c |
+ if (dh.header_version >= 6) {
|
|
|
ab224c |
+ /* A dumpfile contains full 64bit values. */
|
|
|
ab224c |
+ DEBUG_MSG(" start_pfn_64 : 0x%llx\n", kh.start_pfn_64);
|
|
|
ab224c |
+ DEBUG_MSG(" end_pfn_64 : 0x%llx\n", kh.end_pfn_64);
|
|
|
ab224c |
+ DEBUG_MSG(" max_mapnr_64 : 0x%llx\n", kh.max_mapnr_64);
|
|
|
ab224c |
+ }
|
|
|
ab224c |
|
|
|
ab224c |
info->dh_memory = malloc(sizeof(dh));
|
|
|
ab224c |
if (info->dh_memory == NULL) {
|
|
|
ab224c |
@@ -2799,14 +2809,16 @@ int
|
|
|
ab224c |
initialize_bitmap_memory(void)
|
|
|
ab224c |
{
|
|
|
ab224c |
struct disk_dump_header *dh;
|
|
|
ab224c |
+ struct kdump_sub_header *kh;
|
|
|
ab224c |
struct dump_bitmap *bmp;
|
|
|
ab224c |
off_t bitmap_offset;
|
|
|
ab224c |
- int bitmap_len, max_sect_len;
|
|
|
ab224c |
+ off_t bitmap_len, max_sect_len;
|
|
|
ab224c |
unsigned long pfn;
|
|
|
ab224c |
int i, j;
|
|
|
ab224c |
long block_size;
|
|
|
ab224c |
|
|
|
ab224c |
dh = info->dh_memory;
|
|
|
ab224c |
+ kh = info->kh_memory;
|
|
|
ab224c |
block_size = dh->block_size;
|
|
|
ab224c |
|
|
|
ab224c |
bitmap_offset
|
|
|
ab224c |
@@ -2826,7 +2838,10 @@ initialize_bitmap_memory(void)
|
|
|
ab224c |
bmp->offset = bitmap_offset + bitmap_len / 2;
|
|
|
ab224c |
info->bitmap_memory = bmp;
|
|
|
ab224c |
|
|
|
ab224c |
- max_sect_len = divideup(dh->max_mapnr, BITMAP_SECT_LEN);
|
|
|
ab224c |
+ if (dh->header_version >= 6)
|
|
|
ab224c |
+ max_sect_len = divideup(kh->max_mapnr_64, BITMAP_SECT_LEN);
|
|
|
ab224c |
+ else
|
|
|
ab224c |
+ max_sect_len = divideup(dh->max_mapnr, BITMAP_SECT_LEN);
|
|
|
ab224c |
info->valid_pages = calloc(sizeof(ulong), max_sect_len);
|
|
|
ab224c |
if (info->valid_pages == NULL) {
|
|
|
ab224c |
ERRMSG("Can't allocate memory for the valid_pages. %s\n",
|
|
|
ab224c |
@@ -4743,7 +4758,7 @@ create_2nd_bitmap(void)
|
|
|
ab224c |
int
|
|
|
ab224c |
prepare_bitmap_buffer(void)
|
|
|
ab224c |
{
|
|
|
ab224c |
- unsigned long tmp;
|
|
|
ab224c |
+ unsigned long long tmp;
|
|
|
ab224c |
|
|
|
ab224c |
/*
|
|
|
ab224c |
* Create 2 bitmaps (1st-bitmap & 2nd-bitmap) on block_size boundary.
|
|
|
ab224c |
@@ -4775,7 +4790,7 @@ prepare_bitmap_buffer(void)
|
|
|
ab224c |
int
|
|
|
ab224c |
prepare_bitmap_buffer_cyclic(void)
|
|
|
ab224c |
{
|
|
|
ab224c |
- unsigned long tmp;
|
|
|
ab224c |
+ unsigned long long tmp;
|
|
|
ab224c |
|
|
|
ab224c |
/*
|
|
|
ab224c |
* Create 2 bitmaps (1st-bitmap & 2nd-bitmap) on block_size boundary.
|
|
|
ab224c |
@@ -5190,11 +5205,12 @@ write_kdump_header(void)
|
|
|
ab224c |
* Write common header
|
|
|
ab224c |
*/
|
|
|
ab224c |
strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE));
|
|
|
ab224c |
- dh->header_version = 5;
|
|
|
ab224c |
+ dh->header_version = 6;
|
|
|
ab224c |
dh->block_size = info->page_size;
|
|
|
ab224c |
dh->sub_hdr_size = sizeof(kh) + size_note;
|
|
|
ab224c |
dh->sub_hdr_size = divideup(dh->sub_hdr_size, dh->block_size);
|
|
|
ab224c |
- dh->max_mapnr = info->max_mapnr;
|
|
|
ab224c |
+ /* dh->max_mapnr may be truncated, full 64bit in kh.max_mapnr_64 */
|
|
|
ab224c |
+ dh->max_mapnr = MIN(info->max_mapnr, UINT_MAX);
|
|
|
ab224c |
dh->nr_cpus = get_nr_cpus();
|
|
|
ab224c |
dh->bitmap_blocks = divideup(info->len_bitmap, dh->block_size);
|
|
|
ab224c |
memcpy(&dh->timestamp, &info->timestamp, sizeof(dh->timestamp));
|
|
|
ab224c |
@@ -5219,12 +5235,22 @@ write_kdump_header(void)
|
|
|
ab224c |
*/
|
|
|
ab224c |
size = sizeof(struct kdump_sub_header);
|
|
|
ab224c |
memset(&kh, 0, size);
|
|
|
ab224c |
+ /* 64bit max_mapnr_64 */
|
|
|
ab224c |
+ kh.max_mapnr_64 = info->max_mapnr;
|
|
|
ab224c |
kh.phys_base = info->phys_base;
|
|
|
ab224c |
kh.dump_level = info->dump_level;
|
|
|
ab224c |
if (info->flag_split) {
|
|
|
ab224c |
kh.split = 1;
|
|
|
ab224c |
- kh.start_pfn = info->split_start_pfn;
|
|
|
ab224c |
- kh.end_pfn = info->split_end_pfn;
|
|
|
ab224c |
+ /*
|
|
|
ab224c |
+ * start_pfn and end_pfn may be truncated,
|
|
|
ab224c |
+ * only for compatibility purpose
|
|
|
ab224c |
+ */
|
|
|
ab224c |
+ kh.start_pfn = MIN(info->split_start_pfn, UINT_MAX);
|
|
|
ab224c |
+ kh.end_pfn = MIN(info->split_end_pfn, UINT_MAX);
|
|
|
ab224c |
+
|
|
|
ab224c |
+ /* 64bit start_pfn_64 and end_pfn_64 */
|
|
|
ab224c |
+ kh.start_pfn_64 = info->split_start_pfn;
|
|
|
ab224c |
+ kh.end_pfn_64 = info->split_end_pfn;
|
|
|
ab224c |
}
|
|
|
ab224c |
if (has_pt_note()) {
|
|
|
ab224c |
/*
|
|
|
ab224c |
@@ -6470,7 +6496,7 @@ int
|
|
|
ab224c |
write_kdump_bitmap(void)
|
|
|
ab224c |
{
|
|
|
ab224c |
struct cache_data bm;
|
|
|
ab224c |
- long buf_size;
|
|
|
ab224c |
+ long long buf_size;
|
|
|
ab224c |
off_t offset;
|
|
|
ab224c |
|
|
|
ab224c |
int ret = FALSE;
|
|
|
ab224c |
@@ -7853,10 +7879,8 @@ store_splitting_info(void)
|
|
|
ab224c |
|
|
|
ab224c |
if (i == 0) {
|
|
|
ab224c |
memcpy(&dh, &tmp_dh, sizeof(tmp_dh));
|
|
|
ab224c |
- info->max_mapnr = dh.max_mapnr;
|
|
|
ab224c |
if (!set_page_size(dh.block_size))
|
|
|
ab224c |
return FALSE;
|
|
|
ab224c |
- DEBUG_MSG("max_mapnr : %llx\n", info->max_mapnr);
|
|
|
ab224c |
DEBUG_MSG("page_size : %ld\n", info->page_size);
|
|
|
ab224c |
}
|
|
|
ab224c |
|
|
|
ab224c |
@@ -7873,11 +7897,24 @@ store_splitting_info(void)
|
|
|
ab224c |
return FALSE;
|
|
|
ab224c |
|
|
|
ab224c |
if (i == 0) {
|
|
|
ab224c |
+ if (dh.header_version >= 6)
|
|
|
ab224c |
+ info->max_mapnr = kh.max_mapnr_64;
|
|
|
ab224c |
+ else
|
|
|
ab224c |
+ info->max_mapnr = dh.max_mapnr;
|
|
|
ab224c |
+
|
|
|
ab224c |
+ DEBUG_MSG("max_mapnr : %llx\n", info->max_mapnr);
|
|
|
ab224c |
+
|
|
|
ab224c |
info->dump_level = kh.dump_level;
|
|
|
ab224c |
DEBUG_MSG("dump_level : %d\n", info->dump_level);
|
|
|
ab224c |
}
|
|
|
ab224c |
- SPLITTING_START_PFN(i) = kh.start_pfn;
|
|
|
ab224c |
- SPLITTING_END_PFN(i) = kh.end_pfn;
|
|
|
ab224c |
+
|
|
|
ab224c |
+ if (dh.header_version >= 6) {
|
|
|
ab224c |
+ SPLITTING_START_PFN(i) = kh.start_pfn_64;
|
|
|
ab224c |
+ SPLITTING_END_PFN(i) = kh.end_pfn_64;
|
|
|
ab224c |
+ } else {
|
|
|
ab224c |
+ SPLITTING_START_PFN(i) = kh.start_pfn;
|
|
|
ab224c |
+ SPLITTING_END_PFN(i) = kh.end_pfn;
|
|
|
ab224c |
+ }
|
|
|
ab224c |
SPLITTING_OFFSET_EI(i) = kh.offset_eraseinfo;
|
|
|
ab224c |
SPLITTING_SIZE_EI(i) = kh.size_eraseinfo;
|
|
|
ab224c |
}
|
|
|
ab224c |
@@ -8039,6 +8076,8 @@ reassemble_kdump_header(void)
|
|
|
ab224c |
kh.split = 0;
|
|
|
ab224c |
kh.start_pfn = 0;
|
|
|
ab224c |
kh.end_pfn = 0;
|
|
|
ab224c |
+ kh.start_pfn_64 = 0;
|
|
|
ab224c |
+ kh.end_pfn_64 = 0;
|
|
|
ab224c |
|
|
|
ab224c |
if (lseek(info->fd_dumpfile, info->page_size, SEEK_SET) < 0) {
|
|
|
ab224c |
ERRMSG("Can't seek a file(%s). %s\n",
|
|
|
ab224c |
--
|
|
|
ab224c |
1.8.3.1
|
|
|
ab224c |
|