Blob Blame History Raw
Return-Path: yishimat@redhat.com
Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO
 zmta03.collab.prod.int.phx2.redhat.com) (10.5.81.10) by
 zmail24.collab.prod.int.phx2.redhat.com with LMTP; Thu, 2 Jul 2015 01:14:45
 -0400 (EDT)
Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23])
	by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4A6B242574;
	Thu,  2 Jul 2015 01:14:45 -0400 (EDT)
Received: from [10.3.112.13] ([10.3.112.13])
	by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t625EgU7006706;
	Thu, 2 Jul 2015 01:14:43 -0400
Subject: [RHEL7.2 PATCH resend v3 2/4] Make the incomplete dumpfile generated
 by ENOSPC error analyzable.
To: kexec-kdump-list@redhat.com
References: <55929BD5.7050709@redhat.com> <5594C856.6050503@redhat.com>
Cc: Minfei Huang <mhuang@redhat.com>, bhe@redhat.com, yishimat@redhat.com
From: Yasuaki Ishimatsu <yishimat@redhat.com>
Message-ID: <5594C8C2.8080603@redhat.com>
Date: Thu, 2 Jul 2015 01:14:42 -0400
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101
 Thunderbird/38.0.1
MIME-Version: 1.0
In-Reply-To: <5594C856.6050503@redhat.com>
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23
Content-Length: 5485

https://bugzilla.redhat.com/show_bug.cgi?id=1182377

The patch is back ported directory from the following upstream commit:

commit e39216fce9f73759509ec158e39c289e6c211125
Author: Wang Xiao <wangx.fnst@cn.fujitsu.com>
Date:   Mon Oct 20 13:39:03 2014 +0900

    [PATCH v4 2/4] Make the incomplete dumpfile generated by ENOSPC error analyzable.

    Since the incomplete dumpfile generated by ENOSPC error can't be anylyzed
    by crash utility, but sometimes this file may contain important information
    and the panic problem won't be reproduced, then we came up with an idea to
    modify the exist data of the incomplete dumpfile to make it analyzable by
    crash utility. And each of those dumpfiles has a flag to indicate that it
    has been modified. As there are two formats of these dumpfiles, different
    methods and flags are needed to deal with each of them,

    elf:
    This format use the "e_flags" of "elf header" to indicate that it has been
    modified.

    The method of dealing with "kdump-compressed" format dumpfiles is
    implemented
    in the next patch.

    Signed-of-by: Wang Xiao <wangx.fnst@cn.fujitsu.com>

Resolves: rhbz#1182377
Signed-off-by: Yasuaki Ishimatsu <yishimat@redhat.com>
Acked-by: Minfei Huang <mhuang@redhat.com>

---
 makedumpfile-1.5.7/makedumpfile.c |  115 +++++++++++++++++++++++++++++++++++-
 1 files changed, 111 insertions(+), 4 deletions(-)

diff --git a/makedumpfile-1.5.7/makedumpfile.c b/makedumpfile-1.5.7/makedumpfile.c
index b4d43d8..141d290 100644
--- a/makedumpfile-1.5.7/makedumpfile.c
+++ b/makedumpfile-1.5.7/makedumpfile.c
@@ -24,6 +24,7 @@
 #include <ctype.h>
 #include <sys/time.h>
 #include <limits.h>
+#include <assert.h>

 struct symbol_table	symbol_table;
 struct size_table	size_table;
@@ -3768,6 +3769,93 @@ read_flat_data_header(struct makedumpfile_data_header *fdh)
 }

 int
+reserve_diskspace(int fd, off_t start_offset, off_t end_offset, char *file_name)
+{
+	size_t buf_size;
+	char *buf = NULL;
+
+	int ret = FALSE;
+
+	assert(start_offset < end_offset);
+	buf_size = end_offset - start_offset;
+
+	if ((buf = malloc(buf_size)) == NULL) {
+		ERRMSG("Can't allocate memory for the size of reserved diskspace. %s\n",
+		       strerror(errno));
+		return FALSE;
+	}
+
+	memset(buf, 0, buf_size);
+	if (!write_buffer(fd, start_offset, buf, buf_size, file_name))
+		goto out;
+
+	ret = TRUE;
+out:
+	if (buf != NULL) {
+		free(buf);
+	}
+
+	return ret;
+}
+
+#define DUMP_ELF_INCOMPLETE 0x1
+int
+check_and_modify_elf_headers(char *filename)
+{
+	int fd, ret = FALSE;
+	Elf64_Ehdr ehdr64;
+	Elf32_Ehdr ehdr32;
+
+	if ((fd = open(filename, O_RDWR)) < 0) {
+		ERRMSG("Can't open the dump file(%s). %s\n",
+		       filename, strerror(errno));
+		return FALSE;
+	}
+
+	/*
+	 * the is_elf64_memory() function still can be used.
+	 */
+	/*
+	 * Set the incomplete flag to the e_flags of elf header.
+	 */
+	if (is_elf64_memory()) { /* ELF64 */
+		if (!get_elf64_ehdr(fd, filename, &ehdr64)) {
+			ERRMSG("Can't get ehdr64.\n");
+			goto out_close_file;
+		}
+		ehdr64.e_flags |= DUMP_ELF_INCOMPLETE;
+		if (!write_buffer(fd, 0, &ehdr64, sizeof(Elf64_Ehdr), filename))
+			goto out_close_file;
+
+	} else { /* ELF32 */
+		if (!get_elf32_ehdr(fd, filename, &ehdr32)) {
+			ERRMSG("Can't get ehdr32.\n");
+			goto out_close_file;
+		}
+		ehdr32.e_flags |= DUMP_ELF_INCOMPLETE;
+		if (!write_buffer(fd, 0, &ehdr32, sizeof(Elf32_Ehdr), filename))
+			goto out_close_file;
+
+	}
+	ret = TRUE;
+out_close_file:
+	if (close(fd) < 0) {
+		ERRMSG("Can't close the dump file(%s). %s\n",
+		       filename, strerror(errno));
+	}
+	return ret;
+}
+
+int
+check_and_modify_headers()
+{
+	if (info->flag_elf_dumpfile)
+		return check_and_modify_elf_headers(info->name_dumpfile);
+	return FALSE;
+}
+
+
+int
 rearrange_dumpdata(void)
 {
 	int read_size, tmp_read_size;
@@ -5498,6 +5586,13 @@ write_elf_header(struct cache_data *cd_header)
 	size_note          = note.p_filesz;

 	/*
+	 * Reserve a space to store the whole program headers.
+	 */
+	if (!reserve_diskspace(cd_header->fd, cd_header->offset,
+				offset_note_dumpfile, cd_header->file_name))
+		goto out;
+
+	/*
 	 * Modify the note size in PT_NOTE header to accomodate eraseinfo data.
 	 * Eraseinfo will be written later.
 	 */
@@ -8015,10 +8110,10 @@ writeout_dumpfile(void)
 			goto out;
 		if (info->flag_cyclic) {
 			if (!write_elf_pages_cyclic(&cd_header, &cd_page))
-				goto out;
+				goto write_cache_enospc;
 		} else {
 			if (!write_elf_pages(&cd_header, &cd_page))
-				goto out;
+				goto write_cache_enospc;
 		}
 		if (!write_elf_eraseinfo(&cd_header))
 			goto out;
@@ -8045,6 +8140,11 @@ writeout_dumpfile(void)
 	}

 	ret = TRUE;
+write_cache_enospc:
+	if ((ret == FALSE) && info->flag_nospace && !info->flag_flatten) {
+		if (!write_cache_bufsz(&cd_header))
+			ERRMSG("This dumpfile may lost some important data.\n");
+	}
 out:
 	free_cache_data(&cd_header);
 	free_cache_data(&cd_page);
@@ -8237,8 +8337,15 @@ retry:
 		 * to create a dumpfile with it again.
 		 */
 		num_retry++;
-		if ((info->dump_level = get_next_dump_level(num_retry)) < 0)
- 			return FALSE;
+		if ((info->dump_level = get_next_dump_level(num_retry)) < 0) {
+			if (!info->flag_flatten) {
+				if (check_and_modify_headers())
+					MSG("This is an incomplete dumpfile,"
+						" but might analyzable.\n");
+			}
+
+			return FALSE;
+		}
 		MSG("Retry to create a dumpfile by dump_level(%d).\n",
 		    info->dump_level);
 		if (!delete_dumpfile())
-- 
1.7.1