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 <jingbai.ma(a)hp.com>
---
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 */