Use the crash dump bitmap to speedup memory pages classification process. Signed-off-by: Jingbai Ma <jingbai.ma at hp.com> --- makedumpfile.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ makedumpfile.h | 38 +++++++++++++++++ 2 files changed, 157 insertions(+), 3 deletions(-) diff --git a/makedumpfile.c b/makedumpfile.c index acb1b21..f29b6a5 100644 --- a/makedumpfile.c +++ b/makedumpfile.c @@ -34,6 +34,10 @@ struct srcfile_table srcfile_table; struct vm_table vt = { 0 }; struct DumpInfo *info = NULL; +struct crash_dump_bitmap_info crash_dump_bitmap_info; + +const unsigned int CURRENT_BITMAP_INFO_VERSION = 1; + char filename_stdout[] = FILENAME_STDOUT; /* @@ -892,6 +896,7 @@ get_symbol_info(void) SYMBOL_INIT(node_remap_start_vaddr, "node_remap_start_vaddr"); SYMBOL_INIT(node_remap_end_vaddr, "node_remap_end_vaddr"); SYMBOL_INIT(node_remap_start_pfn, "node_remap_start_pfn"); + SYMBOL_INIT(crash_dump_bitmap_info, "crash_dump_bitmap_info"); if (SYMBOL(node_data) != NOT_FOUND_SYMBOL) SYMBOL_ARRAY_TYPE_INIT(node_data, "node_data"); @@ -1704,6 +1709,8 @@ read_vmcoreinfo(void) READ_SYMBOL("node_remap_end_vaddr", node_remap_end_vaddr); READ_SYMBOL("node_remap_start_pfn", node_remap_start_pfn); + READ_SYMBOL("crash_dump_bitmap_info", crash_dump_bitmap_info); + READ_STRUCTURE_SIZE("page", page); READ_STRUCTURE_SIZE("mem_section", mem_section); READ_STRUCTURE_SIZE("pglist_data", pglist_data); @@ -4423,6 +4430,74 @@ copy_bitmap(void) int create_2nd_bitmap(void) { + off_t offset_page; + char buf1[info->page_size], buf2[info->page_size]; + int i; + + if (info->flag_crash_dump_bitmap) { + offset_page = 0; + while (offset_page < (info->len_bitmap / 2)) { + if (lseek(info->bitmap1->fd, info->bitmap1->offset + + offset_page, SEEK_SET) < 0) { + ERRMSG("Can't seek the bitmap(%s). %s\n", + info->bitmap1->file_name, strerror(errno)); + return FALSE; + } + + if (read(info->bitmap1->fd, buf1, info->page_size) + != info->page_size) { + ERRMSG("Can't read bitmap(%s). %s\n", + info->bitmap1->file_name, + strerror(errno)); + return FALSE; + } + + if (readmem(PADDR, crash_dump_bitmap_info.bitmap + + offset_page, buf2, info->page_size) + != info->page_size) { + ERRMSG("Can't read bitmap1! addr=%llx\n", + crash_dump_bitmap_info.bitmap + + offset_page); + return FALSE; + } + + if (crash_dump_bitmap_info.version + != CURRENT_BITMAP_INFO_VERSION) { + ERRMSG("bitmap version! expected=%d, got=%d\n", + CURRENT_BITMAP_INFO_VERSION, + crash_dump_bitmap_info.version); + return FALSE; + } + + for (i = 0; i < info->page_size; i++) + buf2[i] = buf1[i] & buf2[i]; + + if (lseek(info->bitmap2->fd, info->bitmap2->offset + + offset_page, SEEK_SET) < 0) { + ERRMSG("Can't seek the bitmap(%s). %s\n", + info->bitmap2->file_name, strerror(errno)); + return FALSE; + } + + if (write(info->bitmap2->fd, buf2, info->page_size) + != info->page_size) { + ERRMSG("Can't write the bitmap(%s). %s\n", + info->bitmap2->file_name, strerror(errno)); + return FALSE; + } + + offset_page += info->page_size; + } + + pfn_cache = crash_dump_bitmap_info.cache_pages; + pfn_cache_private = crash_dump_bitmap_info.cache_private_pages; + pfn_user = crash_dump_bitmap_info.user_pages; + pfn_free = crash_dump_bitmap_info.free_pages; + pfn_hwpoison = crash_dump_bitmap_info.hwpoison_pages; + + return TRUE; + } + /* * Copy 1st-bitmap to 2nd-bitmap. */ @@ -4587,6 +4662,46 @@ create_dump_bitmap(void) if (!prepare_bitmap_buffer()) goto out; + if (info->flag_crash_dump_bitmap + && (SYMBOL(crash_dump_bitmap_info) + != NOT_FOUND_SYMBOL)) { + /* Read crash_dump_bitmap_info from old kernel */ + readmem(VADDR, SYMBOL(crash_dump_bitmap_info), + &crash_dump_bitmap_info, + sizeof(struct crash_dump_bitmap_info)); + + if (!crash_dump_bitmap_info.bitmap_size + || !crash_dump_bitmap_info.bitmap) { + ERRMSG("Can't get crash_dump bitmap info! "); + ERRMSG("Failback to legacy mode.\n"); + ERRMSG("crash_dump_bitmap_info=0x%llx, ", + SYMBOL(crash_dump_bitmap_info)); + ERRMSG("bitmap=0x%llx, ", + crash_dump_bitmap_info.bitmap); + ERRMSG("bitmap_size=%lld\n", + crash_dump_bitmap_info.bitmap_size); + + info->flag_crash_dump_bitmap = FALSE; + } else { + MSG("crash_dump_bitmap: "); + MSG("crash_dump_bitmap_info=0x%llx, ", + SYMBOL(crash_dump_bitmap_info)); + MSG("bitmap=0x%llx, ", + crash_dump_bitmap_info.bitmap); + MSG("bitmap_size=%lld, ", + crash_dump_bitmap_info.bitmap_size); + MSG("cache_pages=0x%lx, ", + crash_dump_bitmap_info.cache_pages); + MSG("cache_private_pages=0x%lx, ", + crash_dump_bitmap_info + .cache_private_pages); + MSG("user_pages=0x%lx, ", + crash_dump_bitmap_info.user_pages); + MSG("free_pages=0x%lx\n", + crash_dump_bitmap_info.free_pages); + } + } + if (!create_1st_bitmap()) goto out; @@ -8454,7 +8569,8 @@ main(int argc, char *argv[]) info->block_order = DEFAULT_ORDER; message_level = DEFAULT_MSG_LEVEL; - while ((opt = getopt_long(argc, argv, "b:cDd:EFfg:hi:lMpRrsvXx:", longopts, + while ((opt = getopt_long(argc, argv, "b:cDd:EFfg:hi:lMpqRrsvXx:", + longopts, NULL)) != -1) { switch (opt) { case 'b': @@ -8518,6 +8634,10 @@ main(int argc, char *argv[]) case 'P': info->xen_phys_start = strtoul(optarg, NULL, 0); break; + case 'q': + info->flag_crash_dump_bitmap = TRUE; + info->flag_cyclic = FALSE; + break; case 'R': info->flag_rearrange = 1; break; diff --git a/makedumpfile.h b/makedumpfile.h index 272273e..6404b16 100644 --- a/makedumpfile.h +++ b/makedumpfile.h @@ -41,6 +41,8 @@ #include "dwarf_info.h" #include "diskdump_mod.h" #include "sadump_mod.h" +#include "print_info.h" + /* * Result of command @@ -889,6 +891,7 @@ struct DumpInfo { int flag_refiltering; /* refilter from kdump-compressed file */ int flag_force; /* overwrite existing stuff */ int flag_exclude_xen_dom;/* exclude Domain-U from xen-kdump */ + int flag_crash_dump_bitmap;/* crash dump bitmap */ int flag_dmesg; /* dump the dmesg log out of the vmcore file */ int flag_nospace; /* the flag of "No space on device" error */ unsigned long vaddr_for_vtop; /* virtual address for debugging */ @@ -1153,6 +1156,11 @@ struct symbol_table { unsigned long long __per_cpu_load; unsigned long long cpu_online_mask; unsigned long long kexec_crash_image; + + /* + * for crash_dump_bitmap + */ + unsigned long long crash_dump_bitmap_info; }; struct size_table { @@ -1381,6 +1389,20 @@ struct srcfile_table { char pud_t[LEN_SRCFILE]; }; +/* + * for crash_dump_bitmap + */ +struct crash_dump_bitmap_info { + unsigned int version; + unsigned long long bitmap; + unsigned long long bitmap_size; + unsigned long cache_pages; + unsigned long cache_private_pages; + unsigned long user_pages; + unsigned long free_pages; + unsigned long hwpoison_pages; +}; + extern struct symbol_table symbol_table; extern struct size_table size_table; extern struct offset_table offset_table; @@ -1541,8 +1563,20 @@ is_dumpable(struct dump_bitmap *bitmap, unsigned long long pfn) off_t offset; if (pfn == 0 || bitmap->no_block != pfn/PFN_BUFBITMAP) { offset = bitmap->offset + BUFSIZE_BITMAP*(pfn/PFN_BUFBITMAP); - lseek(bitmap->fd, offset, SEEK_SET); - read(bitmap->fd, bitmap->buf, BUFSIZE_BITMAP); + if (lseek(bitmap->fd, offset, SEEK_SET) < 0) { + ERRMSG("Can't seek bitmap file %s:(%d), ", + bitmap->file_name, bitmap->fd); + ERRMSG("offset=%ld, error: %s\n", + offset, strerror(errno)); + } + + if (read(bitmap->fd, bitmap->buf, BUFSIZE_BITMAP) < 0) { + ERRMSG("Can't read bitmap file %s:(%d), ", + bitmap->file_name, bitmap->fd); + ERRMSG("offset=%ld, error: %s\n", + offset, strerror(errno)); + } + if (pfn == 0) bitmap->no_block = 0; else