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 <jingbai.ma at hp.com> --- 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); }