The patch will add support for new compressed dumpfile header_version 6.

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.

Signed-off-by: Jingbai Ma <[email protected]>
---
 diskdump.c |   36 +++++++++++++++++++++++++-----------
 diskdump.h |    5 ++++-
 2 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/diskdump.c b/diskdump.c
index 0819a3f..8a2928b 100644
--- a/diskdump.c
+++ b/diskdump.c
@@ -199,22 +199,23 @@ get_bit(char *map, int byte, int bit)
 }
 
 static inline int 
-page_is_ram(unsigned int nr)
+page_is_ram(unsigned long nr)
 {
        return get_bit(dd->bitmap, nr >> 3, nr & 7);
 }
 
 static inline int 
-page_is_dumpable(unsigned int nr)
+page_is_dumpable(unsigned long nr)
 {
        return dd->dumpable_bitmap[nr>>3] & (1 << (nr & 7));
 }
 
 static inline int 
-dump_is_partial(const struct disk_dump_header *header)
+dump_is_partial(const struct disk_dump_header *header,
+       const struct kdump_sub_header *sub_header)
 {
        return header->bitmap_blocks >=
-           divideup(divideup(header->max_mapnr, 8), dd->block_size) * 2;
+           divideup(divideup(sub_header->max_mapnr, 8), dd->block_size) * 2;
 }
 
 static int 
@@ -321,6 +322,7 @@ x86_process_elf_notes(void *note_ptr, unsigned long 
size_note)
  * [40]    unsigned long   size_note;          /  header_version 4 and later  /
  * [44]    off_t           offset_eraseinfo;   /  header_version 5 and later  /
  * [52]    unsigned long   size_eraseinfo;     /  header_version 5 and later  /
+ * [56]    unsigned long   max_mapnr;          /  header_version 6 and later  /
  * };
  * 
  * But when compiled on an ARM processor, each 64-bit "off_t" would be pushed
@@ -338,6 +340,7 @@ x86_process_elf_notes(void *note_ptr, unsigned long 
size_note)
  * [48]    unsigned long   size_note;          /  header_version 4 and later  /
  * [56]    off_t           offset_eraseinfo;   /  header_version 5 and later  /
  * [62]    unsigned long   size_eraseinfo;     /  header_version 5 and later  /
+ * [66]    unsigned long   max_mapnr;          /  header_version 6 and later  /
  * };
  * 
  */
@@ -357,6 +360,7 @@ struct kdump_sub_header_ARM_target {
        int             pad3;   
         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 */
 };
 
 static void
@@ -380,6 +384,8 @@ arm_kdump_header_adjust(int header_version)
                kdsh->offset_eraseinfo = kdsh_ARM_target->offset_eraseinfo;
                kdsh->size_eraseinfo = kdsh_ARM_target->size_eraseinfo;
        }
+       if (header_version >= 6)
+               kdsh->max_mapnr = kdsh_ARM_target->map_mapnr;
 }
 #endif  /* __i386__ && ARM */
 
@@ -578,7 +584,10 @@ restart:
                }
        }
 
-       if (dump_is_partial(header))
+       if (header->header_version < 6)
+               sub_header_kdump->max_mapnr = header->max_mapnr;
+
+       if (dump_is_partial(header, sub_header_kdump))
                memcpy(dd->dumpable_bitmap, dd->bitmap + bitmap_len/2,
                       bitmap_len/2);
        else
@@ -679,7 +688,8 @@ restart:
        }
 
        if (!is_split) {
-               max_sect_len = divideup(header->max_mapnr, BITMAP_SECT_LEN);
+               max_sect_len = divideup(sub_header_kdump->max_mapnr,
+                       BITMAP_SECT_LEN);
                pfn = 0;
                dd->filename = file;
        }
@@ -1058,14 +1068,14 @@ read_diskdump(int fd, void *bufptr, int cnt, ulong 
addr, physaddr_t paddr)
        curpaddr = paddr & ~((physaddr_t)(dd->block_size-1));
        page_offset = paddr & ((physaddr_t)(dd->block_size-1));
 
-       if ((pfn >= dd->header->max_mapnr) || !page_is_ram(pfn)) {
+       if ((pfn >= dd->sub_header_kdump->max_mapnr) || !page_is_ram(pfn)) {
                if (CRASHDEBUG(8)) {
                        fprintf(fp, "read_diskdump: SEEK_ERROR: "
                            "paddr/pfn: %llx/%lx ",
                                (ulonglong)paddr, pfn);
-                       if (pfn >= dd->header->max_mapnr)
-                               fprintf(fp, "max_mapnr: %x\n",
-                                       dd->header->max_mapnr);
+                       if (pfn >= dd->sub_header_kdump->max_mapnr)
+                               fprintf(fp, "max_mapnr: %lx\n",
+                                       dd->sub_header_kdump->max_mapnr);
                        else
                                fprintf(fp, "!page_is_ram\n");
                }
@@ -1517,7 +1527,11 @@ __diskdump_memory_dump(FILE *fp)
        fprintf(fp, "          block_size: %d\n", dh->block_size);
        fprintf(fp, "        sub_hdr_size: %d\n", dh->sub_hdr_size);
        fprintf(fp, "       bitmap_blocks: %u\n", dh->bitmap_blocks);
-       fprintf(fp, "           max_mapnr: %u\n", dh->max_mapnr);
+       if (dh->header_version >= 6)
+               fprintf(fp, "           max_mapnr: %lu\n",
+                       dd->sub_header_kdump->max_mapnr);
+       else
+               fprintf(fp, "           max_mapnr: %u\n", dh->max_mapnr);
        fprintf(fp, "    total_ram_blocks: %u\n", dh->total_ram_blocks);
        fprintf(fp, "       device_blocks: %u\n", dh->device_blocks);
        fprintf(fp, "      written_blocks: %u\n", dh->written_blocks);
diff --git a/diskdump.h b/diskdump.h
index 9ab10b6..17642b6 100644
--- a/diskdump.h
+++ b/diskdump.h
@@ -42,7 +42,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
@@ -69,6 +71,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 */


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

Reply via email to