Hello Zhou, I have combined our patches into the attached INCOMPLETE_DUMP_v2.patch. Please give it a test, and if all goes well, I'll queue it for crash-7.0.9. Thanks, Dave
diff --git a/crash.8 b/crash.8 index 16f2e8d..abe0f71 100644 --- a/crash.8 +++ b/crash.8 @@ -395,9 +395,11 @@ for older xendump dumpfiles that did not pass that information in the dumpfile header. .TP .B --zero_excluded -If a kdump dumpfile has been filtered to exclude various types of non-essential -pages, any attempt to read them will fail. With this flag, -reads from any of those pages will return zero-filled memory. +If the makedumpfile(8) facility has filtered a compressed kdump dumpfile to +exclude various types of non-essential pages, or has marked a compressed or +ELF kdump dumpfile as incomplete due to an ENOSPC or other error during its +creation, any attempt to read missing pages will fail. With this flag, reads +from any of those pages will return zero-filled memory. .TP .B --no_panic Do not attempt to find the task that was running when the kernel crashed. @@ -859,4 +861,5 @@ provides more complete and accurate documentation than this man page. utility. .PP .BR netdump (8), -.BR gdb (1) +.BR gdb (1), +.BR makedumpfile(8) diff --git a/defs.h b/defs.h index c5f8bee..e850904 100644 --- a/defs.h +++ b/defs.h @@ -504,9 +504,11 @@ struct program_context { #define VMCOREINFO (0x400ULL) #define ALLOW_FP (0x800ULL) #define REM_PAUSED_F (0x1000ULL) -#define RAMDUMP (0x2000ULL) +#define RAMDUMP (0x2000ULL) #define REMOTE_PAUSED() (pc->flags2 & REM_PAUSED_F) -#define OFFLINE_HIDE (0x4000ULL) +#define OFFLINE_HIDE (0x4000ULL) +#define INCOMPLETE_DUMP (0x8000ULL) +#define is_incomplete_dump() (pc->flags2 & INCOMPLETE_DUMP) char *cleanup; char *namelist_orig; char *namelist_debug_orig; diff --git a/diskdump.c b/diskdump.c index beedc2f..939f903 100644 --- a/diskdump.c +++ b/diskdump.c @@ -713,6 +713,10 @@ restart: dd->sub_header_kdump->size_vmcoreinfo) pc->flags2 |= VMCOREINFO; + if (KDUMP_CMPRS_VALID() && + (dd->header->status & DUMP_DH_COMPRESSED_INCOMPLETE)) + pc->flags2 |= INCOMPLETE_DUMP; + /* For split dumpfile */ if (KDUMP_CMPRS_VALID()) { is_split = ((dd->header->header_version >= 2) && @@ -995,6 +999,20 @@ cache_page(physaddr_t paddr) if (FLAT_FORMAT()) { if (!read_flattened_format(dd->dfd, pd.offset, dd->compressed_page, pd.size)) return READ_ERROR; + } else if (is_incomplete_dump() && (0 == pd.offset)) { + /* + * If the incomplete flag has been set in the header, + * first check whether zero_excluded has been set. + */ + if (*diskdump_flags & ZERO_EXCLUDED) { + if (CRASHDEBUG(8)) + fprintf(fp, + "read_diskdump/cache_page: zero-fill: " + "paddr/pfn: %llx/%lx\n", + (ulonglong)paddr, pfn); + memset(dd->compressed_page, 0, dd->block_size); + } else + return READ_ERROR; } else { if (lseek(dd->dfd, pd.offset, SEEK_SET) == failed) return SEEK_ERROR; @@ -1578,6 +1596,8 @@ __diskdump_memory_dump(FILE *fp) fprintf(fp, "DUMP_DH_COMPRESSED_LZO"); if (dh->status & DUMP_DH_COMPRESSED_SNAPPY) fprintf(fp, "DUMP_DH_COMPRESSED_SNAPPY"); + if (dh->status & DUMP_DH_COMPRESSED_INCOMPLETE) + fprintf(fp, "DUMP_DH_COMPRESSED_INCOMPLETE"); break; } fprintf(fp, ")\n"); @@ -1860,13 +1880,17 @@ show_split_dumpfiles(void) { int i; struct diskdump_data *ddp; + struct disk_dump_header *dh; for (i = 0; i < num_dumpfiles; i++) { ddp = dd_list[i]; - fprintf(fp, "%s%s %s", + dh = ddp->header; + fprintf(fp, "%s%s%s%s", i ? " " : "", ddp->filename, - is_partial_diskdump() ? "[PARTIAL DUMP]" : ""); + is_partial_diskdump() ? " [PARTIAL DUMP]" : "", + dh->status & DUMP_DH_COMPRESSED_INCOMPLETE ? + " [INCOMPLETE]" : ""); if ((i+1) < num_dumpfiles) fprintf(fp, "\n"); } diff --git a/diskdump.h b/diskdump.h index 88c5be9..2d697de 100644 --- a/diskdump.h +++ b/diskdump.h @@ -84,6 +84,7 @@ struct kdump_sub_header { #define DUMP_DH_COMPRESSED_ZLIB 0x1 /* page is compressed with zlib */ #define DUMP_DH_COMPRESSED_LZO 0x2 /* page is compressed with lzo */ #define DUMP_DH_COMPRESSED_SNAPPY 0x4 /* page is compressed with snappy */ +#define DUMP_DH_COMPRESSED_INCOMPLETE 0x8 /* dumpfile is incomplete */ /* descriptor of each page for vmcore */ typedef struct page_desc { diff --git a/help.c b/help.c index 723e79e..9c6129d 100644 --- a/help.c +++ b/help.c @@ -269,10 +269,12 @@ char *program_usage_info[] = { " that information in the dumpfile header.", "", " --zero_excluded", - " If a kdump dumpfile has been filtered to exclude various types of", - " non-essential pages, any attempt to read them will fail. With", - " this flag, reads from any of those pages will return zero-filled", - " memory.", + " If the makedumpfile(8) facility has filtered a compressed kdump", + " dumpfile to exclude various types of non-essential pages, or has", + " marked a compressed or ELF kdump dumpfile as incomplete due to", + " an ENOSPC or other error during its creation, any attempt to", + " read missing pages will fail. With this flag, reads from any", + " of those pages will return zero-filled memory.", "", " --no_panic", " Do not attempt to find the task that was running when the kernel", @@ -1043,8 +1045,9 @@ char *help_set[] = { " (scrolling is turned off if silent is on)", " edit vi | emacs set line editing mode (from .%src file only).", " namelist filename name of kernel (from .%src file only).", -" zero_excluded on | off controls whether excluded pages from a dumpfile", -" should return zero-filled memory.", +" zero_excluded on | off controls whether excluded pages, or pages that", +" are missing from an incomplete dumpfile, should", +" return zero-filled memory when read.", " null-stop on | off if on, gdb's printing of character arrays will", " stop at the first NULL encountered.", " gdb on | off if on, the %s session will be run in a mode", diff --git a/kernel.c b/kernel.c index 3144fe8..c0d3ced 100644 --- a/kernel.c +++ b/kernel.c @@ -4790,9 +4790,17 @@ display_sys_stats(void) if (NETDUMP_DUMPFILE() && is_partial_netdump()) fprintf(fp, " [PARTIAL DUMP]"); + if (KDUMP_DUMPFILE() && is_incomplete_dump()) + fprintf(fp, " [INCOMPLETE]"); + if (DISKDUMP_DUMPFILE() && !dumpfile_is_split() && - is_partial_diskdump()) - fprintf(fp, " [PARTIAL DUMP]"); + (is_partial_diskdump() || is_incomplete_dump())) { + fprintf(fp, " %s%s", + is_partial_diskdump() ? + " [PARTIAL DUMP]" : "", + is_incomplete_dump() ? + " [INCOMPLETE]" : ""); + } fprintf(fp, "\n"); diff --git a/main.c b/main.c index 8917f0f..cd8c37e 100644 --- a/main.c +++ b/main.c @@ -694,7 +694,14 @@ main_loop(void) "Kernel data has been erased from this dumpfile. This may " "cause\n the crash session to fail entirely, may " "cause commands to fail,\n or may result in " - "unpredictable runtime behavior.\n", + "unpredictable\n runtime behavior.\n", + pc->dumpfile); + + if (pc->flags2 & INCOMPLETE_DUMP) + error(WARNING, "\n%s:\n " + "This dumpfile is incomplete. This may cause the crash session" + "\n to fail entirely, may cause commands to fail, or may" + " result in\n unpredictable runtime behavior.\n", pc->dumpfile); if (!(pc->flags & GDB_INIT)) { @@ -1406,6 +1413,8 @@ dump_program_context(void) fprintf(fp, "%sRAMDUMP", others++ ? "|" : ""); if (pc->flags2 & OFFLINE_HIDE) fprintf(fp, "%sOFFLINE_HIDE", others++ ? "|" : ""); + if (pc->flags2 & INCOMPLETE_DUMP) + fprintf(fp, "%sINCOMPLETE_DUMP", others++ ? "|" : ""); fprintf(fp, ")\n"); fprintf(fp, " namelist: %s\n", pc->namelist); diff --git a/netdump.c b/netdump.c index 35e4e69..726c3f1 100644 --- a/netdump.c +++ b/netdump.c @@ -531,6 +531,7 @@ int read_netdump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr) { off_t offset; + ssize_t read_ret; struct pt_load_segment *pls; int i; @@ -608,7 +609,25 @@ read_netdump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr) "offset: %llx\n", (ulonglong)offset); return SEEK_ERROR; } - if (read(nd->ndfd, bufptr, cnt) != cnt) { + + read_ret = read(nd->ndfd, bufptr, cnt); + if (read_ret != cnt) { + /* + * If the incomplete flag has been set in the header, + * first check whether zero_excluded has been set. + */ + if (is_incomplete_dump() && (read_ret >= 0) && + (*diskdump_flags & ZERO_EXCLUDED)) { + if (CRASHDEBUG(8)) + fprintf(fp, "read_netdump: zero-fill: " + "addr: %lx paddr: %llx cnt: %d\n", + addr + read_ret, + (ulonglong)paddr + read_ret, + cnt - (int)read_ret); + bufptr += read_ret; + bzero(bufptr, cnt - read_ret); + return cnt; + } if (CRASHDEBUG(8)) fprintf(fp, "read_netdump: READ_ERROR: " "offset: %llx\n", (ulonglong)offset); @@ -1288,6 +1307,9 @@ dump_Elf32_Ehdr(Elf32_Ehdr *elf) netdump_print(" e_phoff: %lx\n", elf->e_phoff); netdump_print(" e_shoff: %lx\n", elf->e_shoff); netdump_print(" e_flags: %lx\n", elf->e_flags); + if ((elf->e_flags & DUMP_ELF_INCOMPLETE) && + (DUMPFILE_FORMAT(nd->flags) == KDUMP_ELF32)) + pc->flags2 |= INCOMPLETE_DUMP; netdump_print(" e_ehsize: %x\n", elf->e_ehsize); netdump_print(" e_phentsize: %x\n", elf->e_phentsize); netdump_print(" e_phnum: %x\n", elf->e_phnum); @@ -1447,6 +1469,9 @@ dump_Elf64_Ehdr(Elf64_Ehdr *elf) netdump_print(" e_phoff: %lx\n", elf->e_phoff); netdump_print(" e_shoff: %lx\n", elf->e_shoff); netdump_print(" e_flags: %lx\n", elf->e_flags); + if ((elf->e_flags & DUMP_ELF_INCOMPLETE) && + (DUMPFILE_FORMAT(nd->flags) == KDUMP_ELF64)) + pc->flags2 |= INCOMPLETE_DUMP; netdump_print(" e_ehsize: %x\n", elf->e_ehsize); netdump_print(" e_phentsize: %x\n", elf->e_phentsize); netdump_print(" e_phnum: %x\n", elf->e_phnum); diff --git a/netdump.h b/netdump.h index 7456855..05ae7e2 100644 --- a/netdump.h +++ b/netdump.h @@ -80,6 +80,8 @@ struct vmcore_data { ulonglong backup_offset; }; +#define DUMP_ELF_INCOMPLETE 0x1 /* dumpfile is incomplete */ + /* * ELF note types for Xen dom0/hypervisor kdumps. * The comments below are from xen/include/public/elfnote.h.
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility