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 a new field in struct kdump_sub_header.
unsigned long   max_mapnr;

And the old "unsigned int max_mapnr" in struct disk_dump_header will
not be used anymore. But still be there for compatibility purpose.

This patch will change the header_version to 6.

The corresponding patch for crash utility will be sent out separately.

This patch doesn't change sadump_header.
Because of in sadump file, there is no any sub-header, it has to change
the sadump_header itself.
And if do so, will cause backwards-compatibility issue.
So it could be a separate patch if needed.

Signed-off-by: Jingbai Ma <[email protected]>
---
 IMPLEMENTATION |    1 +
 diskdump_mod.h |    5 ++++-
 makedumpfile.c |   28 ++++++++++++++++++++++------
 3 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/IMPLEMENTATION b/IMPLEMENTATION
index f0f3135..d576811 100644
--- a/IMPLEMENTATION
+++ b/IMPLEMENTATION
@@ -77,6 +77,7 @@
        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   max_mapnr;        /* header_version 6 and later */
     };
 
   - 1st-bitmap
diff --git a/diskdump_mod.h b/diskdump_mod.h
index af060b6..30306a5 100644
--- a/diskdump_mod.h
+++ b/diskdump_mod.h
@@ -48,7 +48,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, 32bit only,
+                                                  full 64bit in sub header.
+                                                  Do not use this anymore! */
        unsigned int            total_ram_blocks;/* Number of blocks should be
                                                   written */
        unsigned int            device_blocks;  /* Number of total blocks in
@@ -75,6 +77,7 @@ struct kdump_sub_header {
        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   max_mapnr;        /* header_version 6 and later */
 };
 
 /* page flags */
diff --git a/makedumpfile.c b/makedumpfile.c
index b42565c..a444adf 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -125,7 +125,7 @@ get_max_mapnr(void)
        unsigned long long max_paddr;
 
        if (info->flag_refiltering) {
-               info->max_mapnr = info->dh_memory->max_mapnr;
+               info->max_mapnr = info->kh_memory->max_mapnr;
                return TRUE;
        }
 
@@ -783,6 +783,10 @@ get_kdump_compressed_header_info(char *filename)
                ERRMSG("header does not have dump_level member\n");
                return FALSE;
        }
+
+       if (dh.header_version < 6)
+               kh.max_mapnr = dh.max_mapnr;
+
        DEBUG_MSG("diskdump main header\n");
        DEBUG_MSG("  signature        : %s\n", dh.signature);
        DEBUG_MSG("  header_version   : %d\n", dh.header_version);
@@ -790,7 +794,7 @@ get_kdump_compressed_header_info(char *filename)
        DEBUG_MSG("  block_size       : %d\n", dh.block_size);
        DEBUG_MSG("  sub_hdr_size     : %d\n", dh.sub_hdr_size);
        DEBUG_MSG("  bitmap_blocks    : %d\n", dh.bitmap_blocks);
-       DEBUG_MSG("  max_mapnr        : 0x%x\n", dh.max_mapnr);
+       DEBUG_MSG("  max_mapnr(32bit) : 0x%x\n", dh.max_mapnr);
        DEBUG_MSG("  total_ram_blocks : %d\n", dh.total_ram_blocks);
        DEBUG_MSG("  device_blocks    : %d\n", dh.device_blocks);
        DEBUG_MSG("  written_blocks   : %d\n", dh.written_blocks);
@@ -802,6 +806,7 @@ 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);
+       DEBUG_MSG("  max_mapnr(64bit) : 0x%lx\n", kh.max_mapnr);
 
        info->dh_memory = malloc(sizeof(dh));
        if (info->dh_memory == NULL) {
@@ -2766,6 +2771,7 @@ 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;
@@ -2774,6 +2780,7 @@ initialize_bitmap_memory(void)
        long block_size;
 
        dh = info->dh_memory;
+       kh = info->kh_memory;
        block_size = dh->block_size;
 
        bitmap_offset
@@ -2793,7 +2800,7 @@ 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);
+       max_sect_len = divideup(kh->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",
@@ -5153,10 +5160,11 @@ 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 may be truncated here, full 64bit in kh.max_mapnr */
        dh->max_mapnr      = info->max_mapnr;
        dh->nr_cpus        = get_nr_cpus();
        dh->bitmap_blocks  = divideup(info->len_bitmap, dh->block_size);
@@ -5172,6 +5180,7 @@ write_kdump_header(void)
         */
        size = sizeof(struct kdump_sub_header);
        memset(&kh, 0, size);
+       kh.max_mapnr = info->max_mapnr;
        kh.phys_base  = info->phys_base;
        kh.dump_level = info->dump_level;
        if (info->flag_split) {
@@ -7796,10 +7805,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);
                }
 
@@ -7816,6 +7823,15 @@ store_splitting_info(void)
                        return FALSE;
 
                if (i == 0) {
+                       if (dh.header_version >= 6)
+                               info->max_mapnr = kh.max_mapnr;
+                       else
+                               info->max_mapnr = dh.max_mapnr;
+
+                       DEBUG_MSG("max_mapnr    : %llx\n", info->max_mapnr);
+               }
+
+               if (i == 0) {
                        info->dump_level = kh.dump_level;
                        DEBUG_MSG("dump_level   : %d\n", info->dump_level);
                }


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to