Re: add support for incomplete elf dump file

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux