[kexec-tools/f19] Fix max_mapnr issue on system has over 44-bit addressing.

WANG Chao wangchao at fedoraproject.org
Tue Oct 29 06:43:53 UTC 2013


commit e689cf7c12d548d99de5db234eb35a78d07fcf0a
Author: Baoquan He <bhe at redhat.com>
Date:   Tue Oct 22 17:08:03 2013 +0800

    Fix max_mapnr issue on system has over 44-bit addressing.
    
    The dumpfile header has this field, which was inherited from
    the old "diskdump" facility:
    
     struct disk_dump_header {
     ...
            unsigned int            max_mapnr;      /* = max_mapnr */
     ...
    and which, among other things, is used by the crash utility as a
    delimiter to determine whether a physical address read request is
    legitimate.  And obviously the field cannot handle PFN values greater
    than 32-bits.
    
    The makedumpfile source code does have its own max_mapnr representation
    in its DumpInfo structure in "makedumpfile.h":
    
     struct DumpInfo {
     ...
            unsigned long long      max_mapnr;   /* number of page descriptor */
     ...
    But in its "diskdump_mod.h" file, it carries forward the old diskdump
    header format, which has the 32-bit field:
    
     struct disk_dump_header {
     ...
            unsigned int            max_mapnr;      /* = max_mapnr */
     ...
    And here in "makedumpfile.c", the inadvertent truncation occurs
    when the PFN is greater than 32-bits:
    
     int
     write_kdump_header(void)
     {
     ...
            dh->max_mapnr      = info->max_mapnr;
     ...
    Now upstream has below commit to fix this, back port it:
    
    commit 8e124174b62376b17ac909bc68622ef07bde6840
    Author: Jingbai Ma <jingbai.ma at hp.com>
    Date:   Fri Oct 18 18:53:38 2013 +0900
    
    Signed-off-by: Baoquan He <bhe at redhat.com>
    Acked-by: Vivek Goyal <vgoyal at redhat.com>
    Acked-by: WANG Chao <chaowang at redhat.com>

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


More information about the scm-commits mailing list