Kexec Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/2] makedumpfile: make the incomplete vmcore generated by ENOSPC error analyzable
@ 2014-09-16  9:48 Wang, Xiao/Wang Xiao
  2014-09-17  6:47 ` Petr Tesarik
  2014-09-18 12:29 ` HATAYAMA, Daisuke
  0 siblings, 2 replies; 12+ messages in thread
From: Wang, Xiao/Wang Xiao @ 2014-09-16  9:48 UTC (permalink / raw)
  To: kexec

Since the incomplete vmcore 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 vmcore file to make it analyzable
by crash utility. As there are two formats of the vmcore file, different
methods are needed to deal with each of them,

elf:
Modify the value of the PT_LOAD program header to reflect the actual size
of the incomplete vmcore file. This method can't be used to modify the
vmcore written in flattened mode.

kdump-compressed:
Dump the bitmap before any page header and page data.

Signed-of-by: Wang Xiao <wangx.fnst@cn.fujitsu.com>
---
  makedumpfile.c |  150 
+++++++++++++++++++++++++++++++++++++++++++++++++++++---
  1 files changed, 143 insertions(+), 7 deletions(-)

diff --git a/makedumpfile.c b/makedumpfile.c
index ce4a866..debc15b 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -3621,6 +3621,128 @@ write_cache(struct cache_data *cd, void *buf, 
size_t size)
  }

  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;
+
+	if (start_offset >= end_offset) {
+		ERRMSG("The start offset of diskspace to be reserved must smaller than "
+		       "the end offset.\n");
+		return FALSE;
+	}
+
+	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;
+}
+
+int
+check_and_modify_elf_header() {
+	int i, phnum;
+	off_t file_end, offset, end_offset;
+	Elf64_Ehdr ehdr64;
+	Elf32_Ehdr ehdr32;
+	Elf64_Phdr phdr64;
+	Elf32_Phdr phdr32;
+
+	/*
+	 * the is_elf64_memory() function still can be used.
+	 */
+	if (is_elf64_memory()) { /* ELF64 */
+		if (!get_elf64_ehdr(info->fd_dumpfile, info->name_dumpfile, &ehdr64)) {
+			ERRMSG("Can't get ehdr64.\n");
+			return FALSE;
+		}
+		phnum = ehdr64.e_phnum;
+	} else { /* ELF32 */
+		if (!get_elf32_ehdr(info->fd_dumpfile, info->name_dumpfile, &ehdr32)) {
+			ERRMSG("Can't get ehdr32.\n");
+			return FALSE;
+		}
+		phnum = ehdr32.e_phnum;
+	}
+
+	file_end = lseek(info->fd_dumpfile, 0, SEEK_END);
+	if (file_end < 0) {
+		ERRMSG("Can't detect the size of %s. %s\n",
+		       info->name_dumpfile,
+		       strerror(errno));
+		return FALSE;
+	}
+
+	for (i = 0; i < phnum; i++) {
+		if (is_elf64_memory()) {
+			if (!get_elf64_phdr(info->fd_dumpfile,
+			                    info->name_dumpfile,
+			                    i, &phdr64)) {
+				ERRMSG("Can't find Phdr %d.\n", i);
+				return FALSE;
+			}
+
+			offset = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * i;
+			end_offset = phdr64.p_offset + phdr64.p_filesz;
+
+			/*
+			 * Check the program header and modify its value according
+			 * to the actual written size.
+			 */
+			if (file_end >= end_offset)
+				continue;
+			else if (file_end >= phdr64.p_offset && file_end < end_offset)
+				phdr64.p_filesz = file_end - phdr64.p_offset;
+			else if (file_end < phdr64.p_offset)
+				memset(&phdr64, 0, sizeof(Elf64_Phdr));
+
+			if (!write_buffer(info->fd_dumpfile, offset, &phdr64,
+			                  sizeof(Elf64_Phdr), info->name_dumpfile))
+				return FALSE;
+		} else {
+			if (!get_elf32_phdr(info->fd_dumpfile,
+			                    info->name_dumpfile,
+			                    i, &phdr32)) {
+				ERRMSG("Can't find Phdr %d.\n", i);
+				return FALSE;
+			}
+
+			offset = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * i;
+			end_offset = phdr32.p_offset + phdr32.p_filesz;
+
+			if (file_end >= end_offset)
+				continue;
+			else if (file_end >= phdr32.p_offset && file_end < end_offset)
+				phdr32.p_filesz = file_end - phdr32.p_offset;
+			else if (file_end < phdr32.p_offset)
+				memset(&phdr32, 0, sizeof(Elf32_Phdr));
+
+			if (!write_buffer(info->fd_dumpfile, offset, &phdr32,
+			                  sizeof(Elf32_Phdr), info->name_dumpfile))
+				return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+int
  write_cache_bufsz(struct cache_data *cd)
  {
  	if (!cd->buf_size)
@@ -5432,6 +5554,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.
  	 */
@@ -6956,11 +7085,11 @@ write_kdump_pages_and_bitmap_cyclic(struct 
cache_data *cd_header, struct cache_d
  		if (!exclude_unnecessary_pages_cyclic(&cycle))
  			return FALSE;

-		if (!write_kdump_pages_cyclic(cd_header, cd_page, &pd_zero,
-					&offset_data, &cycle))
+		if (!write_kdump_bitmap2_cyclic(&cycle))
  			return FALSE;

-		if (!write_kdump_bitmap2_cyclic(&cycle))
+		if (!write_kdump_pages_cyclic(cd_header, cd_page, &pd_zero,
+					&offset_data, &cycle))
  			return FALSE;
  	}

@@ -7906,10 +8035,10 @@ writeout_dumpfile(void)
  			goto out;
  		if (info->flag_cyclic) {
  			if (!write_elf_pages_cyclic(&cd_header, &cd_page))
-				goto out;
+				goto chk_enospc;
  		} else {
  			if (!write_elf_pages(&cd_header, &cd_page))
-				goto out;
+				goto chk_enospc;
  		}
  		if (!write_elf_eraseinfo(&cd_header))
  			goto out;
@@ -7923,12 +8052,12 @@ writeout_dumpfile(void)
  	} else {
  		if (!write_kdump_header())
  			goto out;
+		if (!write_kdump_bitmap())
+			goto out;
  		if (!write_kdump_pages(&cd_header, &cd_page))
  			goto out;
  		if (!write_kdump_eraseinfo(&cd_page))
  			goto out;
-		if (!write_kdump_bitmap())
-			goto out;
  	}
  	if (info->flag_flatten) {
  		if (!write_end_flat_header())
@@ -7936,6 +8065,13 @@ writeout_dumpfile(void)
  	}

  	ret = TRUE;
+chk_enospc:
+	if ((ret == FALSE) && info->flag_nospace && !info->flag_flatten) {
+		if (!write_cache_bufsz(&cd_header))
+			goto out;
+		if (!check_and_modify_elf_header())
+			ERRMSG("Can't modify the elf header.\n");
+	}
  out:
  	free_cache_data(&cd_header);
  	free_cache_data(&cd_page);
-- 
1.7.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] makedumpfile: make the incomplete vmcore generated by ENOSPC error analyzable
       [not found] <mailman.12983.1410860958.22890.kexec@lists.infradead.org>
@ 2014-09-16 13:20 ` Dave Anderson
  2014-09-17  2:41   ` Wang, Xiao/Wang Xiao
  0 siblings, 1 reply; 12+ messages in thread
From: Dave Anderson @ 2014-09-16 13:20 UTC (permalink / raw)
  To: kexec; +Cc: wangx.fnst



----- Original Message -----

> Date: Tue, 16 Sep 2014 17:48:49 +0800
> From: "Wang, Xiao/Wang Xiao" <wangx.fnst@cn.fujitsu.com>
> To: <kexec@lists.infradead.org>
> Subject: [PATCH 2/2] makedumpfile: make the incomplete vmcore
> 	generated by ENOSPC error analyzable
> Message-ID: <54180781.2080702@cn.fujitsu.com>
> Content-Type: text/plain; charset="UTF-8"; format=flowed
> 
> Since the incomplete vmcore 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 vmcore file to make it analyzable
> by crash utility. As there are two formats of the vmcore file, different
> methods are needed to deal with each of them,

This patch bothers me -- how would the crash utility know that the "fixed" 
vmcore file was truncated/bogus to begin with?  Are you simply presuming
that the user (when running makedumpfile) will change the output dumpfile
name to something that indicates that it's incomplete?

Typically incomplete vmcores fail to initialize due to some missing data,
and it will confuse the issue if the PT_LOAD segments indicate that everything 
is just fine.  There really should be some kind of indication/flag/note in the
compressed dumpfile or ELF header that it's a bogus/truncated vmcore. 

Dave

> 
> elf:
> Modify the value of the PT_LOAD program header to reflect the actual size
> of the incomplete vmcore file. This method can't be used to modify the
> vmcore written in flattened mode.
> 
> kdump-compressed:
> Dump the bitmap before any page header and page data.
> 
> Signed-of-by: Wang Xiao <wangx.fnst@cn.fujitsu.com>
> ---
>   makedumpfile.c |  150
> +++++++++++++++++++++++++++++++++++++++++++++++++++++---
>   1 files changed, 143 insertions(+), 7 deletions(-)
> 
> diff --git a/makedumpfile.c b/makedumpfile.c
> index ce4a866..debc15b 100644
> --- a/makedumpfile.c
> +++ b/makedumpfile.c
> @@ -3621,6 +3621,128 @@ write_cache(struct cache_data *cd, void *buf,
> size_t size)
>   }
> 
>   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;
> +
> +	if (start_offset >= end_offset) {
> +		ERRMSG("The start offset of diskspace to be reserved must smaller than "
> +		       "the end offset.\n");
> +		return FALSE;
> +	}
> +
> +	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;
> +}
> +
> +int
> +check_and_modify_elf_header() {
> +	int i, phnum;
> +	off_t file_end, offset, end_offset;
> +	Elf64_Ehdr ehdr64;
> +	Elf32_Ehdr ehdr32;
> +	Elf64_Phdr phdr64;
> +	Elf32_Phdr phdr32;
> +
> +	/*
> +	 * the is_elf64_memory() function still can be used.
> +	 */
> +	if (is_elf64_memory()) { /* ELF64 */
> +		if (!get_elf64_ehdr(info->fd_dumpfile, info->name_dumpfile, &ehdr64)) {
> +			ERRMSG("Can't get ehdr64.\n");
> +			return FALSE;
> +		}
> +		phnum = ehdr64.e_phnum;
> +	} else { /* ELF32 */
> +		if (!get_elf32_ehdr(info->fd_dumpfile, info->name_dumpfile, &ehdr32)) {
> +			ERRMSG("Can't get ehdr32.\n");
> +			return FALSE;
> +		}
> +		phnum = ehdr32.e_phnum;
> +	}
> +
> +	file_end = lseek(info->fd_dumpfile, 0, SEEK_END);
> +	if (file_end < 0) {
> +		ERRMSG("Can't detect the size of %s. %s\n",
> +		       info->name_dumpfile,
> +		       strerror(errno));
> +		return FALSE;
> +	}
> +
> +	for (i = 0; i < phnum; i++) {
> +		if (is_elf64_memory()) {
> +			if (!get_elf64_phdr(info->fd_dumpfile,
> +			                    info->name_dumpfile,
> +			                    i, &phdr64)) {
> +				ERRMSG("Can't find Phdr %d.\n", i);
> +				return FALSE;
> +			}
> +
> +			offset = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * i;
> +			end_offset = phdr64.p_offset + phdr64.p_filesz;
> +
> +			/*
> +			 * Check the program header and modify its value according
> +			 * to the actual written size.
> +			 */
> +			if (file_end >= end_offset)
> +				continue;
> +			else if (file_end >= phdr64.p_offset && file_end < end_offset)
> +				phdr64.p_filesz = file_end - phdr64.p_offset;
> +			else if (file_end < phdr64.p_offset)
> +				memset(&phdr64, 0, sizeof(Elf64_Phdr));
> +
> +			if (!write_buffer(info->fd_dumpfile, offset, &phdr64,
> +			                  sizeof(Elf64_Phdr), info->name_dumpfile))
> +				return FALSE;
> +		} else {
> +			if (!get_elf32_phdr(info->fd_dumpfile,
> +			                    info->name_dumpfile,
> +			                    i, &phdr32)) {
> +				ERRMSG("Can't find Phdr %d.\n", i);
> +				return FALSE;
> +			}
> +
> +			offset = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * i;
> +			end_offset = phdr32.p_offset + phdr32.p_filesz;
> +
> +			if (file_end >= end_offset)
> +				continue;
> +			else if (file_end >= phdr32.p_offset && file_end < end_offset)
> +				phdr32.p_filesz = file_end - phdr32.p_offset;
> +			else if (file_end < phdr32.p_offset)
> +				memset(&phdr32, 0, sizeof(Elf32_Phdr));
> +
> +			if (!write_buffer(info->fd_dumpfile, offset, &phdr32,
> +			                  sizeof(Elf32_Phdr), info->name_dumpfile))
> +				return FALSE;
> +		}
> +	}
> +
> +	return TRUE;
> +}
> +
> +int
>   write_cache_bufsz(struct cache_data *cd)
>   {
>   	if (!cd->buf_size)
> @@ -5432,6 +5554,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.
>   	 */
> @@ -6956,11 +7085,11 @@ write_kdump_pages_and_bitmap_cyclic(struct
> cache_data *cd_header, struct cache_d
>   		if (!exclude_unnecessary_pages_cyclic(&cycle))
>   			return FALSE;
> 
> -		if (!write_kdump_pages_cyclic(cd_header, cd_page, &pd_zero,
> -					&offset_data, &cycle))
> +		if (!write_kdump_bitmap2_cyclic(&cycle))
>   			return FALSE;
> 
> -		if (!write_kdump_bitmap2_cyclic(&cycle))
> +		if (!write_kdump_pages_cyclic(cd_header, cd_page, &pd_zero,
> +					&offset_data, &cycle))
>   			return FALSE;
>   	}
> 
> @@ -7906,10 +8035,10 @@ writeout_dumpfile(void)
>   			goto out;
>   		if (info->flag_cyclic) {
>   			if (!write_elf_pages_cyclic(&cd_header, &cd_page))
> -				goto out;
> +				goto chk_enospc;
>   		} else {
>   			if (!write_elf_pages(&cd_header, &cd_page))
> -				goto out;
> +				goto chk_enospc;
>   		}
>   		if (!write_elf_eraseinfo(&cd_header))
>   			goto out;
> @@ -7923,12 +8052,12 @@ writeout_dumpfile(void)
>   	} else {
>   		if (!write_kdump_header())
>   			goto out;
> +		if (!write_kdump_bitmap())
> +			goto out;
>   		if (!write_kdump_pages(&cd_header, &cd_page))
>   			goto out;
>   		if (!write_kdump_eraseinfo(&cd_page))
>   			goto out;
> -		if (!write_kdump_bitmap())
> -			goto out;
>   	}
>   	if (info->flag_flatten) {
>   		if (!write_end_flat_header())
> @@ -7936,6 +8065,13 @@ writeout_dumpfile(void)
>   	}
> 
>   	ret = TRUE;
> +chk_enospc:
> +	if ((ret == FALSE) && info->flag_nospace && !info->flag_flatten) {
> +		if (!write_cache_bufsz(&cd_header))
> +			goto out;
> +		if (!check_and_modify_elf_header())
> +			ERRMSG("Can't modify the elf header.\n");
> +	}
>   out:
>   	free_cache_data(&cd_header);
>   	free_cache_data(&cd_page);
> --
> 1.7.1
> 
> 
> 
> 
> ------------------------------
> 
> Subject: Digest Footer
> 
> _______________________________________________
> kexec mailing list
> kexec@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec
> 
> 
> ------------------------------
> 
> End of kexec Digest, Vol 90, Issue 22
> *************************************
> 

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] makedumpfile: make the incomplete vmcore generated by ENOSPC error analyzable
  2014-09-16 13:20 ` [PATCH 2/2] makedumpfile: make the incomplete vmcore generated by ENOSPC error analyzable Dave Anderson
@ 2014-09-17  2:41   ` Wang, Xiao/Wang Xiao
  2014-09-17 13:55     ` Dave Anderson
  0 siblings, 1 reply; 12+ messages in thread
From: Wang, Xiao/Wang Xiao @ 2014-09-17  2:41 UTC (permalink / raw)
  To: Dave Anderson, kexec

Hello Dave,

Thanks for your reply.

We can use two methods to indicate that the incomplete vmcore is a 
"fixed" one,
1. Use a flag in elf/kdump dumpfile(like "e_flags" in ELF header and 
"status"
    in disk_dump_header) to indicate it has been "fixed". But actually the
    kdump-compressed file needn't to use such a flag, for we just change the
    data write order of this format.
2. We can just let makedumpfile change the "fixed" dumpfile's filename 
automatically.
    Such as add a "-truncated" flag after those dumpfiles.

On 2014/9/16 21:20, Dave Anderson wrote:
> This patch bothers me -- how would the crash utility know that the "fixed"
> vmcore file was truncated/bogus to begin with?  Are you simply presuming
> that the user (when running makedumpfile) will change the output dumpfile
> name to something that indicates that it's incomplete?
>
> Typically incomplete vmcores fail to initialize due to some missing data,
> and it will confuse the issue if the PT_LOAD segments indicate that everything
> is just fine.  There really should be some kind of indication/flag/note in the
> compressed dumpfile or ELF header that it's a bogus/truncated vmcore.

-- 
Regards
Wang Xiao

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] makedumpfile: make the incomplete vmcore generated by ENOSPC error analyzable
  2014-09-16  9:48 [PATCH 2/2] makedumpfile: make the incomplete vmcore generated by ENOSPC error analyzable Wang, Xiao/Wang Xiao
@ 2014-09-17  6:47 ` Petr Tesarik
  2014-09-18  7:26   ` Wang, Xiao/Wang Xiao
  2014-09-18 12:29 ` HATAYAMA, Daisuke
  1 sibling, 1 reply; 12+ messages in thread
From: Petr Tesarik @ 2014-09-17  6:47 UTC (permalink / raw)
  To: Wang, Xiao/Wang Xiao; +Cc: kexec

On Tue, 16 Sep 2014 17:48:49 +0800
"Wang, Xiao/Wang Xiao" <wangx.fnst@cn.fujitsu.com> wrote:

> Since the incomplete vmcore generated by ENOSPC error can't be anylyzed by
> crash utility, but sometimes this file may contain important information

Hello 王萧,

first of all, I like your patch. It has always annoyed me that any
incomplete dump was utterly useless. Just one small question: why is
this limited to ENOSPC? Why not e.g. EIO? EFBIG?
I think writing the (incomplete) bitmap should always be attempted.

Petr Tesarik

> and the panic problem won't be reproduced, then we came up with an idea to
> modify the exist data of the incomplete vmcore file to make it analyzable
> by crash utility. As there are two formats of the vmcore file, different
> methods are needed to deal with each of them,
> 
> elf:
> Modify the value of the PT_LOAD program header to reflect the actual size
> of the incomplete vmcore file. This method can't be used to modify the
> vmcore written in flattened mode.
> 
> kdump-compressed:
> Dump the bitmap before any page header and page data.
> 
> Signed-of-by: Wang Xiao <wangx.fnst@cn.fujitsu.com>
> ---
>   makedumpfile.c |  150 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++---
>   1 files changed, 143 insertions(+), 7 deletions(-)
> 
> diff --git a/makedumpfile.c b/makedumpfile.c
> index ce4a866..debc15b 100644
> --- a/makedumpfile.c
> +++ b/makedumpfile.c
> @@ -3621,6 +3621,128 @@ write_cache(struct cache_data *cd, void *buf, 
> size_t size)
>   }
> 
>   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;
> +
> +	if (start_offset >= end_offset) {
> +		ERRMSG("The start offset of diskspace to be reserved must smaller than "
> +		       "the end offset.\n");
> +		return FALSE;
> +	}
> +
> +	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;
> +}
> +
> +int
> +check_and_modify_elf_header() {
> +	int i, phnum;
> +	off_t file_end, offset, end_offset;
> +	Elf64_Ehdr ehdr64;
> +	Elf32_Ehdr ehdr32;
> +	Elf64_Phdr phdr64;
> +	Elf32_Phdr phdr32;
> +
> +	/*
> +	 * the is_elf64_memory() function still can be used.
> +	 */
> +	if (is_elf64_memory()) { /* ELF64 */
> +		if (!get_elf64_ehdr(info->fd_dumpfile, info->name_dumpfile, &ehdr64)) {
> +			ERRMSG("Can't get ehdr64.\n");
> +			return FALSE;
> +		}
> +		phnum = ehdr64.e_phnum;
> +	} else { /* ELF32 */
> +		if (!get_elf32_ehdr(info->fd_dumpfile, info->name_dumpfile, &ehdr32)) {
> +			ERRMSG("Can't get ehdr32.\n");
> +			return FALSE;
> +		}
> +		phnum = ehdr32.e_phnum;
> +	}
> +
> +	file_end = lseek(info->fd_dumpfile, 0, SEEK_END);
> +	if (file_end < 0) {
> +		ERRMSG("Can't detect the size of %s. %s\n",
> +		       info->name_dumpfile,
> +		       strerror(errno));
> +		return FALSE;
> +	}
> +
> +	for (i = 0; i < phnum; i++) {
> +		if (is_elf64_memory()) {
> +			if (!get_elf64_phdr(info->fd_dumpfile,
> +			                    info->name_dumpfile,
> +			                    i, &phdr64)) {
> +				ERRMSG("Can't find Phdr %d.\n", i);
> +				return FALSE;
> +			}
> +
> +			offset = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * i;
> +			end_offset = phdr64.p_offset + phdr64.p_filesz;
> +
> +			/*
> +			 * Check the program header and modify its value according
> +			 * to the actual written size.
> +			 */
> +			if (file_end >= end_offset)
> +				continue;
> +			else if (file_end >= phdr64.p_offset && file_end < end_offset)
> +				phdr64.p_filesz = file_end - phdr64.p_offset;
> +			else if (file_end < phdr64.p_offset)
> +				memset(&phdr64, 0, sizeof(Elf64_Phdr));
> +
> +			if (!write_buffer(info->fd_dumpfile, offset, &phdr64,
> +			                  sizeof(Elf64_Phdr), info->name_dumpfile))
> +				return FALSE;
> +		} else {
> +			if (!get_elf32_phdr(info->fd_dumpfile,
> +			                    info->name_dumpfile,
> +			                    i, &phdr32)) {
> +				ERRMSG("Can't find Phdr %d.\n", i);
> +				return FALSE;
> +			}
> +
> +			offset = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * i;
> +			end_offset = phdr32.p_offset + phdr32.p_filesz;
> +
> +			if (file_end >= end_offset)
> +				continue;
> +			else if (file_end >= phdr32.p_offset && file_end < end_offset)
> +				phdr32.p_filesz = file_end - phdr32.p_offset;
> +			else if (file_end < phdr32.p_offset)
> +				memset(&phdr32, 0, sizeof(Elf32_Phdr));
> +
> +			if (!write_buffer(info->fd_dumpfile, offset, &phdr32,
> +			                  sizeof(Elf32_Phdr), info->name_dumpfile))
> +				return FALSE;
> +		}
> +	}
> +
> +	return TRUE;
> +}
> +
> +int
>   write_cache_bufsz(struct cache_data *cd)
>   {
>   	if (!cd->buf_size)
> @@ -5432,6 +5554,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.
>   	 */
> @@ -6956,11 +7085,11 @@ write_kdump_pages_and_bitmap_cyclic(struct 
> cache_data *cd_header, struct cache_d
>   		if (!exclude_unnecessary_pages_cyclic(&cycle))
>   			return FALSE;
> 
> -		if (!write_kdump_pages_cyclic(cd_header, cd_page, &pd_zero,
> -					&offset_data, &cycle))
> +		if (!write_kdump_bitmap2_cyclic(&cycle))
>   			return FALSE;
> 
> -		if (!write_kdump_bitmap2_cyclic(&cycle))
> +		if (!write_kdump_pages_cyclic(cd_header, cd_page, &pd_zero,
> +					&offset_data, &cycle))
>   			return FALSE;
>   	}
> 
> @@ -7906,10 +8035,10 @@ writeout_dumpfile(void)
>   			goto out;
>   		if (info->flag_cyclic) {
>   			if (!write_elf_pages_cyclic(&cd_header, &cd_page))
> -				goto out;
> +				goto chk_enospc;
>   		} else {
>   			if (!write_elf_pages(&cd_header, &cd_page))
> -				goto out;
> +				goto chk_enospc;
>   		}
>   		if (!write_elf_eraseinfo(&cd_header))
>   			goto out;
> @@ -7923,12 +8052,12 @@ writeout_dumpfile(void)
>   	} else {
>   		if (!write_kdump_header())
>   			goto out;
> +		if (!write_kdump_bitmap())
> +			goto out;
>   		if (!write_kdump_pages(&cd_header, &cd_page))
>   			goto out;
>   		if (!write_kdump_eraseinfo(&cd_page))
>   			goto out;
> -		if (!write_kdump_bitmap())
> -			goto out;
>   	}
>   	if (info->flag_flatten) {
>   		if (!write_end_flat_header())
> @@ -7936,6 +8065,13 @@ writeout_dumpfile(void)
>   	}
> 
>   	ret = TRUE;
> +chk_enospc:
> +	if ((ret == FALSE) && info->flag_nospace && !info->flag_flatten) {
> +		if (!write_cache_bufsz(&cd_header))
> +			goto out;
> +		if (!check_and_modify_elf_header())
> +			ERRMSG("Can't modify the elf header.\n");
> +	}
>   out:
>   	free_cache_data(&cd_header);
>   	free_cache_data(&cd_page);


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] makedumpfile: make the incomplete vmcore generated by ENOSPC error analyzable
  2014-09-17  2:41   ` Wang, Xiao/Wang Xiao
@ 2014-09-17 13:55     ` Dave Anderson
  2014-09-18  7:19       ` Wang, Xiao/Wang Xiao
  0 siblings, 1 reply; 12+ messages in thread
From: Dave Anderson @ 2014-09-17 13:55 UTC (permalink / raw)
  To: Xiao Wang/Wang Xiao; +Cc: kexec



----- Original Message -----
> Hello Dave,
> 
> Thanks for your reply.
> 
> We can use two methods to indicate that the incomplete vmcore is a "fixed" one,
> 1. Use a flag in elf/kdump dumpfile(like "e_flags" in ELF header and "status"
>     in disk_dump_header) to indicate it has been "fixed". But actually the
>     kdump-compressed file needn't to use such a flag, for we just change the
>     data write order of this format.

I don't understand.

First, let's stop using the "fixed" description.  It is definitely *not* fixed, but 
rather it is still a bogus, incomplete, dumpfile, and the user should be made aware 
of that fact.  

For compressed kdumps, the disk_dump_header.status field currently uses these
three bits:

 #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 */
 
Can you please simply add a DUMP_DH_COMPRESSED_INCOMPLETE flag?

With respect to ELF vmcores, the processor-specific e_flags field is unused by the
crash utility, and it appears that makedumpfile always sets it to zero.  But
I'm not sure what the kernel does when /proc/vmcore is created?  Could there
be e_flags bits set there that a direct-copy of /proc/vmcore might contain?
That's why I suggested a unique ELF note.  

Then, if the flag is set, the crash utility can display "[INCOMPLETE]" next
to the dumpfile file name in the initial system banner and by the "sys" command.

And in the highly-likely event where the vmcore fails to initialize -- in that
case "crash -d1" can display the header contents immediately during invocation.  
That way, instead of users complaining about the crash utility, the blame can be
placed where it belongs.

> 2. We can just let makedumpfile change the "fixed" dumpfile's filename automatically.
>     Such as add a "-truncated" flag after those dumpfiles.

You probably should do that -- in *addition* to setting a flag in the header.  
Since there's no way to prevent a user from re-naming the file, without a flag,
there would be no way of confirming that it was a bogus dumpfile to begin with.

Thanks,
  Dave
 

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] makedumpfile: make the incomplete vmcore generated by ENOSPC error analyzable
  2014-09-17 13:55     ` Dave Anderson
@ 2014-09-18  7:19       ` Wang, Xiao/Wang Xiao
  2014-09-18 13:56         ` Dave Anderson
  0 siblings, 1 reply; 12+ messages in thread
From: Wang, Xiao/Wang Xiao @ 2014-09-18  7:19 UTC (permalink / raw)
  To: Dave Anderson; +Cc: kexec

Hello Dave,

On 2014/9/17 21:55, Dave Anderson wrote:
>
>
> ----- Original Message -----
>> Hello Dave,
>>
>> Thanks for your reply.
>>
>> We can use two methods to indicate that the incomplete vmcore is a "fixed" one,
>> 1. Use a flag in elf/kdump dumpfile(like "e_flags" in ELF header and "status"
>>      in disk_dump_header) to indicate it has been "fixed". But actually the
>>      kdump-compressed file needn't to use such a flag, for we just change the
>>      data write order of this format.
>
> I don't understand.
>
> First, let's stop using the "fixed" description.  It is definitely *not* fixed, but
> rather it is still a bogus, incomplete, dumpfile, and the user should be made aware
> of that fact.
>
> For compressed kdumps, the disk_dump_header.status field currently uses these
> three bits:
>
>   #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 */
>
> Can you please simply add a DUMP_DH_COMPRESSED_INCOMPLETE flag?

OK, I'll add this flag.

>
> With respect to ELF vmcores, the processor-specific e_flags field is unused by the
> crash utility, and it appears that makedumpfile always sets it to zero.  But
> I'm not sure what the kernel does when /proc/vmcore is created?  Could there
> be e_flags bits set there that a direct-copy of /proc/vmcore might contain?
> That's why I suggested a unique ELF note.

Add a unique ELF note is OK, and I thought it must need to allocate some 
diskspace
first to store this ELF note and its data, for if the dumpfile has been 
modified,
it must write a flag in this place to indicate it's an incomplete 
dumpfile. But
this may waste a bit of diskspace when the dumpfile is generated with no 
error.

>
> Then, if the flag is set, the crash utility can display "[INCOMPLETE]" next
> to the dumpfile file name in the initial system banner and by the "sys" command.
>
> And in the highly-likely event where the vmcore fails to initialize -- in that
> case "crash -d1" can display the header contents immediately during invocation.
> That way, instead of users complaining about the crash utility, the blame can be
> placed where it belongs.
>
>> 2. We can just let makedumpfile change the "fixed" dumpfile's filename automatically.
>>      Such as add a "-truncated" flag after those dumpfiles.
>
> You probably should do that -- in *addition* to setting a flag in the header.
> Since there's no way to prevent a user from re-naming the file, without a flag,
> there would be no way of confirming that it was a bogus dumpfile to begin with.

I thought it will confuse a user when makedumpfile automatically 
modified the
dumpfile name, so I'll keep the dumpfile name unchanged and use the 
above two
flags in the dumpfile to indicate that it has been modified.

>
> Thanks,
>    Dave
>
>
> .
>

-- 
Regards
Wang Xiao

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] makedumpfile: make the incomplete vmcore generated by ENOSPC error analyzable
  2014-09-17  6:47 ` Petr Tesarik
@ 2014-09-18  7:26   ` Wang, Xiao/Wang Xiao
  2014-09-18 11:18     ` HATAYAMA, Daisuke
  0 siblings, 1 reply; 12+ messages in thread
From: Wang, Xiao/Wang Xiao @ 2014-09-18  7:26 UTC (permalink / raw)
  To: Petr Tesarik; +Cc: kexec

Hello Petr,

Thanks for your reply.

On 2014/9/17 14:47, Petr Tesarik wrote:
>> Since the incomplete vmcore generated by ENOSPC error can't be anylyzed by
>> >crash utility, but sometimes this file may contain important information
> Hello 王萧,
>
> first of all, I like your patch. It has always annoyed me that any
> incomplete dump was utterly useless. Just one small question: why is
> this limited to ENOSPC? Why not e.g. EIO? EFBIG?

At present, I just consider ENOSPC for this error maybe more common. And I'm
considering to deal with other situations in the coming future.

> I think writing the (incomplete) bitmap should always be attempted.
>
> Petr Tesarik
>

PS: Your Chinese must be very good, and my Chinese name is 王晓 :P

-- 
Regards
Wang Xiao

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] makedumpfile: make the incomplete vmcore generated by ENOSPC error analyzable
  2014-09-18  7:26   ` Wang, Xiao/Wang Xiao
@ 2014-09-18 11:18     ` HATAYAMA, Daisuke
  0 siblings, 0 replies; 12+ messages in thread
From: HATAYAMA, Daisuke @ 2014-09-18 11:18 UTC (permalink / raw)
  To: Wang, Xiao/Wang Xiao; +Cc: kexec, Petr Tesarik

Hello Wang,

(2014/09/18 16:26), Wang, Xiao/Wang Xiao wrote:
> Hello Petr,
>
> Thanks for your reply.
>
> On 2014/9/17 14:47, Petr Tesarik wrote:
>>> Since the incomplete vmcore generated by ENOSPC error can't be anylyzed by
>>> >crash utility, but sometimes this file may contain important information
>> Hello 王萧,
>>
>> first of all, I like your patch. It has always annoyed me that any
>> incomplete dump was utterly useless. Just one small question: why is
>> this limited to ENOSPC? Why not e.g. EIO? EFBIG?
>
> At present, I just consider ENOSPC for this error maybe more common. And I'm
> considering to deal with other situations in the coming future.
>

For EFBIG, it seems to me enough to do the same thing as for ENOSPC fow now.

For EIO, although I'm not perfectly clear about when EIO is returned, but
such situation would include broken disk, and then we no longer trust disk
behaviour so we should stop makedumpfile from running as soon as possible,
and we should bet we can successfully recover the incomplete dump data
from the broken disk.

-- 
Thanks.
HATAYAMA, Daisuke


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] makedumpfile: make the incomplete vmcore generated by ENOSPC error analyzable
  2014-09-16  9:48 [PATCH 2/2] makedumpfile: make the incomplete vmcore generated by ENOSPC error analyzable Wang, Xiao/Wang Xiao
  2014-09-17  6:47 ` Petr Tesarik
@ 2014-09-18 12:29 ` HATAYAMA, Daisuke
  2014-09-19  9:16   ` Wang, Xiao/Wang Xiao
  1 sibling, 1 reply; 12+ messages in thread
From: HATAYAMA, Daisuke @ 2014-09-18 12:29 UTC (permalink / raw)
  To: Wang, Xiao/Wang Xiao; +Cc: kexec

Hello Wang,

(2014/09/16 18:48), Wang, Xiao/Wang Xiao wrote:
> Since the incomplete vmcore 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 vmcore file to make it analyzable
> by crash utility. As there are two formats of the vmcore file, different
> methods are needed to deal with each of them,
>
> elf:
> Modify the value of the PT_LOAD program header to reflect the actual size
> of the incomplete vmcore file. This method can't be used to modify the
> vmcore written in flattened mode.
>
> kdump-compressed:
> Dump the bitmap before any page header and page data.
>

Rigorously, this design depends on implementation of filesystems where it's
possible to lseek and write data onto already allocated blocks even after the
filesystem is full. To show correctness of this design, you should show that
test results for a variety of filesystems such as ext3, ext4, xfs, btrfs, etc.

Of course, if this design doesn't work well on some filesystem, then we just
see the second ENOSPC and we give up addtional work. This is the same situation
as now. There's no demerit.

> Signed-of-by: Wang Xiao <wangx.fnst@cn.fujitsu.com>
> ---
>   makedumpfile.c |  150 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
>   1 files changed, 143 insertions(+), 7 deletions(-)
>
> diff --git a/makedumpfile.c b/makedumpfile.c
> index ce4a866..debc15b 100644
> --- a/makedumpfile.c
> +++ b/makedumpfile.c
> @@ -3621,6 +3621,128 @@ write_cache(struct cache_data *cd, void *buf, size_t size)
>   }
>
>   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;
> +
> +    if (start_offset >= end_offset) {
> +        ERRMSG("The start offset of diskspace to be reserved must smaller than "
> +               "the end offset.\n");
> +        return FALSE;
> +    }

I feel this check should be assert()-like. This is not a message when makedumpfile runs.
At least there's no need to print this message.

> +
> +    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;
> +}
> +
> +int
> +check_and_modify_elf_header() {

check_and_modify_elf_header*s*() is better?
It's confusing to the ELF header that always occurs at the head of ELF file.

> +    int i, phnum;
> +    off_t file_end, offset, end_offset;
> +    Elf64_Ehdr ehdr64;
> +    Elf32_Ehdr ehdr32;
> +    Elf64_Phdr phdr64;
> +    Elf32_Phdr phdr32;
> +
> +    /*
> +     * the is_elf64_memory() function still can be used.
> +     */
> +    if (is_elf64_memory()) { /* ELF64 */

ehdr64 should be declared in this scope.

> +        if (!get_elf64_ehdr(info->fd_dumpfile, info->name_dumpfile, &ehdr64)) {
> +            ERRMSG("Can't get ehdr64.\n");
> +            return FALSE;
> +        }
> +        phnum = ehdr64.e_phnum;
> +    } else { /* ELF32 */

ehdr32 should be declared in this scope.

> +        if (!get_elf32_ehdr(info->fd_dumpfile, info->name_dumpfile, &ehdr32)) {
> +            ERRMSG("Can't get ehdr32.\n");
> +            return FALSE;
> +        }
> +        phnum = ehdr32.e_phnum;
> +    }
> +
> +    file_end = lseek(info->fd_dumpfile, 0, SEEK_END);
> +    if (file_end < 0) {
> +        ERRMSG("Can't detect the size of %s. %s\n",
> +               info->name_dumpfile,
> +               strerror(errno));
> +        return FALSE;
> +    }
> +
> +    for (i = 0; i < phnum; i++) {
> +        if (is_elf64_memory()) {

phdr64.

> +            if (!get_elf64_phdr(info->fd_dumpfile,
> +                                info->name_dumpfile,
> +                                i, &phdr64)) {
> +                ERRMSG("Can't find Phdr %d.\n", i);
> +                return FALSE;
> +            }
> +
> +            offset = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * i;
> +            end_offset = phdr64.p_offset + phdr64.p_filesz;
> +
> +            /*
> +             * Check the program header and modify its value according
> +             * to the actual written size.
> +             */
> +            if (file_end >= end_offset)
> +                continue;
> +            else if (file_end >= phdr64.p_offset && file_end < end_offset)
> +                phdr64.p_filesz = file_end - phdr64.p_offset;

So, this is the first case that p_filesz becomes strictly less than p_memsz
except for filtered pages.

> +            else if (file_end < phdr64.p_offset)
> +                memset(&phdr64, 0, sizeof(Elf64_Phdr));

This should be phdr64.p_filesz = 0 and phdr64.p_offset = 0.
The phdr64 has still other information on system memory such p_memsz and p_paddr.
Please don't remove them.

> +
> +            if (!write_buffer(info->fd_dumpfile, offset, &phdr64,
> +                              sizeof(Elf64_Phdr), info->name_dumpfile))
> +                return FALSE;
> +        } else {

phdr32.

> +            if (!get_elf32_phdr(info->fd_dumpfile,
> +                                info->name_dumpfile,
> +                                i, &phdr32)) {
> +                ERRMSG("Can't find Phdr %d.\n", i);
> +                return FALSE;
> +            }
> +
> +            offset = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * i;
> +            end_offset = phdr32.p_offset + phdr32.p_filesz;
> +
> +            if (file_end >= end_offset)
> +                continue;
> +            else if (file_end >= phdr32.p_offset && file_end < end_offset)
> +                phdr32.p_filesz = file_end - phdr32.p_offset;
> +            else if (file_end < phdr32.p_offset)
> +                memset(&phdr32, 0, sizeof(Elf32_Phdr));

same as the above phdr64 case.

> +
> +            if (!write_buffer(info->fd_dumpfile, offset, &phdr32,
> +                              sizeof(Elf32_Phdr), info->name_dumpfile))
> +                return FALSE;
> +        }
> +    }
> +
> +    return TRUE;
> +}
> +
> +int
>   write_cache_bufsz(struct cache_data *cd)
>   {
>       if (!cd->buf_size)
> @@ -5432,6 +5554,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.
>        */
> @@ -6956,11 +7085,11 @@ write_kdump_pages_and_bitmap_cyclic(struct cache_data *cd_header, struct cache_d
>           if (!exclude_unnecessary_pages_cyclic(&cycle))
>               return FALSE;
>
> -        if (!write_kdump_pages_cyclic(cd_header, cd_page, &pd_zero,
> -                    &offset_data, &cycle))
> +        if (!write_kdump_bitmap2_cyclic(&cycle))
>               return FALSE;
>
> -        if (!write_kdump_bitmap2_cyclic(&cycle))
> +        if (!write_kdump_pages_cyclic(cd_header, cd_page, &pd_zero,
> +                    &offset_data, &cycle))
>               return FALSE;
>       }
>
> @@ -7906,10 +8035,10 @@ writeout_dumpfile(void)
>               goto out;
>           if (info->flag_cyclic) {
>               if (!write_elf_pages_cyclic(&cd_header, &cd_page))
> -                goto out;
> +                goto chk_enospc;
>           } else {
>               if (!write_elf_pages(&cd_header, &cd_page))
> -                goto out;
> +                goto chk_enospc;
>           }
>           if (!write_elf_eraseinfo(&cd_header))
>               goto out;
> @@ -7923,12 +8052,12 @@ writeout_dumpfile(void)
>       } else {
>           if (!write_kdump_header())
>               goto out;
> +        if (!write_kdump_bitmap())
> +            goto out;
>           if (!write_kdump_pages(&cd_header, &cd_page))
>               goto out;
>           if (!write_kdump_eraseinfo(&cd_page))
>               goto out;
> -        if (!write_kdump_bitmap())
> -            goto out;
>       }
>       if (info->flag_flatten) {
>           if (!write_end_flat_header())
> @@ -7936,6 +8065,13 @@ writeout_dumpfile(void)
>       }
>
>       ret = TRUE;
> +chk_enospc:
> +    if ((ret == FALSE) && info->flag_nospace && !info->flag_flatten) {
> +        if (!write_cache_bufsz(&cd_header))
> +            goto out;
> +        if (!check_and_modify_elf_header())
> +            ERRMSG("Can't modify the elf header.\n");
> +    }

There's a feature to repeat trying to capture dumpfile in
multiple dump levels in increasing order if no space error is
returned. So, this part should be moved upward.

This is part of man 8 makedumpfile:

      -d dump_level
           Specify the type of unnecessary page for analysis.
           Pages  of   the  specified  type  are   not  copied  to
           DUMPFILE. The  page type marked in  the following table
           is excluded. A user can  specify multiple page types by
           setting the sum  of each page type  for dump_level. The
           maximum of dump_level is 31. Note that a dump_level for
           Xen dump  filtering is 0 or  1 on a machine  other than
           x86_64 (On an x86_64 machine, it is possible to specify
           2 or bigger as a dump_level).
           If specifying  multiple dump_levels with  the delimiter
           ',', makedumpfile retries to create a DUMPFILE by other
           dump_level when "No space on device" error happens. For
           example,  if  dump_level  is "11,31"  and  makedumpfile
           fails  by dump_level  11,  makedumpfile  retries it  by
           dump_level 31.
           Example:
           # makedumpfile -d 11 -x vmlinux /proc/vmcore dumpfile
           #  makedumpfile   -d  11,31  -x   vmlinux  /proc/vmcore
           dumpfile

The process of multiple dump levels is done in create_dumpfile() below.
The above check should be done after even the last trial fails.

         if (info->flag_split) {
                 if ((status = writeout_multiple_dumpfiles()) == FALSE)
                         return FALSE;
         } else {
                 if ((status = writeout_dumpfile()) == FALSE)
                         return FALSE;
         }
         if (status == NOSPACE) {
                 /*
                  * If specifying the other dump_level, makedumpfile tries
                  * to create a dumpfile with it again.
                  */
                 num_retry++;
                 if ((info->dump_level = get_next_dump_level(num_retry)) < 0)
                         return FALSE;
                 MSG("Retry to create a dumpfile by dump_level(%d).\n",
                     info->dump_level);
                 if (!delete_dumpfile())
                         return FALSE;
                 goto retry;
         }

-- 
Thanks.
HATAYAMA, Daisuke


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] makedumpfile: make the incomplete vmcore generated by ENOSPC error analyzable
  2014-09-18  7:19       ` Wang, Xiao/Wang Xiao
@ 2014-09-18 13:56         ` Dave Anderson
  0 siblings, 0 replies; 12+ messages in thread
From: Dave Anderson @ 2014-09-18 13:56 UTC (permalink / raw)
  To: Xiao Wang/Wang Xiao; +Cc: kexec



----- Original Message -----
> >
> > For compressed kdumps, the disk_dump_header.status field currently uses these
> > three bits:
> >
> >   #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 */
> >
> > Can you please simply add a DUMP_DH_COMPRESSED_INCOMPLETE flag?
> 
> OK, I'll add this flag.
> 
> >
> > With respect to ELF vmcores, the processor-specific e_flags field is unused by the
> > crash utility, and it appears that makedumpfile always sets it to zero.  But
> > I'm not sure what the kernel does when /proc/vmcore is created?  Could there
> > be e_flags bits set there that a direct-copy of /proc/vmcore might contain?
> > That's why I suggested a unique ELF note.
> 
> Add a unique ELF note is OK, and I thought it must need to allocate some diskspace
> first to store this ELF note and its data, for if the dumpfile has been modified,
> it must write a flag in this place to indicate it's an incomplete dumpfile. But
> this may waste a bit of diskspace when the dumpfile is generated with no error.
 
Looking at "kexec/crashdump-elf.c" in the kexec-tools package, it should be safe
to use the e_flags field, because even if /proc/vmcore were copied unmodified
(without makedumpfile), the crash_create_elf32_headers()/crash_create_elf64_headers()
functions would always set it to 0:

       /* Setup ELF Header*/
        elf = (EHDR *) bufp;
        bufp += sizeof(EHDR);
        memcpy(elf->e_ident, ELFMAG, SELFMAG);
        elf->e_ident[EI_CLASS]  = elf_info->class;
        elf->e_ident[EI_DATA]   = elf_info->data;
        elf->e_ident[EI_VERSION]= EV_CURRENT;
        elf->e_ident[EI_OSABI] = ELFOSABI_NONE;
        memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
        elf->e_type     = ET_CORE;
        elf->e_machine  = crash_architecture(elf_info);
        elf->e_version  = EV_CURRENT;
        elf->e_entry    = 0;
        elf->e_phoff    = sizeof(EHDR);
        elf->e_shoff    = 0;
        elf->e_flags    = 0;
        elf->e_ehsize   = sizeof(EHDR);
        elf->e_phentsize= sizeof(PHDR);
        elf->e_phnum    = 0;
        elf->e_shentsize= 0;
        elf->e_shnum    = 0;
        elf->e_shstrndx = 0;

> I thought it will confuse a user when makedumpfile automatically modified the
> dumpfile name, so I'll keep the dumpfile name unchanged and use the above two
> flags in the dumpfile to indicate that it has been modified.

OK good -- thanks!

Dave

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] makedumpfile: make the incomplete vmcore generated by ENOSPC error analyzable
  2014-09-18 12:29 ` HATAYAMA, Daisuke
@ 2014-09-19  9:16   ` Wang, Xiao/Wang Xiao
  2014-09-19  9:22     ` [PATCH 1/3] makedumpfile: make get_elf64_phdr()/get_elf32_phdr() public Wang, Xiao/Wang Xiao
  0 siblings, 1 reply; 12+ messages in thread
From: Wang, Xiao/Wang Xiao @ 2014-09-19  9:16 UTC (permalink / raw)
  To: HATAYAMA, Daisuke; +Cc: kexec

Hello HATAYAMA,

On 2014/9/18 20:29, HATAYAMA, Daisuke wrote:
> Rigorously, this design depends on implementation of filesystems where it's
> possible to lseek and write data onto already allocated blocks even
> after the
> filesystem is full. To show correctness of this design, you should show
> that
> test results for a variety of filesystems such as ext3, ext4, xfs,
> btrfs, etc.

Actually, I've tested whether lseek and write can execute on those 
filesystems(
ext2, ext3, ext4, xfs, and btrfs) when there's no more space, and both 
of these
two system calls can work well on all of those filesystems(the snapshot 
function
of btrfs may be confused, but it just need to allocate diskspace when 
creating
snapshot and will never aquire more diskspace automically in the 
future). But
I couldn't get any test results of these testing, because there's no error
message when doing such tests.

>
> Of course, if this design doesn't work well on some filesystem, then we
> just
> see the second ENOSPC and we give up addtional work. This is the same
> situation
> as now. There's no demerit.

As you said, this design won't introduce any more errors. So the influence
of the filesystem is very limited.

PS: the modified patches(according to you and Dave's comments) will be send
later.

-- 
Regards
Wang Xiao

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/3] makedumpfile: make get_elf64_phdr()/get_elf32_phdr() public
  2014-09-19  9:16   ` Wang, Xiao/Wang Xiao
@ 2014-09-19  9:22     ` Wang, Xiao/Wang Xiao
  0 siblings, 0 replies; 12+ messages in thread
From: Wang, Xiao/Wang Xiao @ 2014-09-19  9:22 UTC (permalink / raw)
  To: kexec

Move the following two functions from internal function to external
function.

get_elf64_phdr(int fd, char *filename, int index, Elf64_Phdr *phdr)
get_elf32_phdr(int fd, char *filename, int index, Elf32_Phdr *phdr)

Signed-of-by: Wang Xiao <wangx.fnst@cn.fujitsu.com>
---
  elf_info.c |   71 
+++++++++++++++++++++++++++++------------------------------
  elf_info.h |    2 +
  2 files changed, 37 insertions(+), 36 deletions(-)

diff --git a/elf_info.c b/elf_info.c
index b277f69..1499328 100644
--- a/elf_info.c
+++ b/elf_info.c
@@ -95,42 +95,6 @@ static unsigned long		size_xen_crash_info;
   * Internal functions.
   */
  static int
-get_elf64_phdr(int fd, char *filename, int index, Elf64_Phdr *phdr)
-{
-	off_t offset;
-
-	offset = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * index;
-
-	if (lseek(fd, offset, SEEK_SET) < 0) {
-		ERRMSG("Can't seek %s. %s\n", filename, strerror(errno));
-		return FALSE;
-	}
-	if (read(fd, phdr, sizeof(Elf64_Phdr)) != sizeof(Elf64_Phdr)) {
-		ERRMSG("Can't read %s. %s\n", filename, strerror(errno));
-		return FALSE;
-	}
-	return TRUE;
-}
-
-static int
-get_elf32_phdr(int fd, char *filename, int index, Elf32_Phdr *phdr)
-{
-	off_t offset;
-
-	offset = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * index;
-
-	if (lseek(fd, offset, SEEK_SET) < 0) {
-		ERRMSG("Can't seek %s. %s\n", filename, strerror(errno));
-		return FALSE;
-	}
-	if (read(fd, phdr, sizeof(Elf32_Phdr)) != sizeof(Elf32_Phdr)) {
-		ERRMSG("Can't read %s. %s\n", filename, strerror(errno));
-		return FALSE;
-	}
-	return TRUE;
-}
-
-static int
  check_elf_format(int fd, char *filename, int *phnum, unsigned int 
*num_load)
  {
  	int i;
@@ -399,6 +363,41 @@ get_pt_note_info(void)
  /*
   * External functions.
   */
+int
+get_elf64_phdr(int fd, char *filename, int index, Elf64_Phdr *phdr)
+{
+	off_t offset;
+
+	offset = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * index;
+
+	if (lseek(fd, offset, SEEK_SET) < 0) {
+		ERRMSG("Can't seek %s. %s\n", filename, strerror(errno));
+		return FALSE;
+	}
+	if (read(fd, phdr, sizeof(Elf64_Phdr)) != sizeof(Elf64_Phdr)) {
+		ERRMSG("Can't read %s. %s\n", filename, strerror(errno));
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int
+get_elf32_phdr(int fd, char *filename, int index, Elf32_Phdr *phdr)
+{
+	off_t offset;
+
+	offset = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * index;
+
+	if (lseek(fd, offset, SEEK_SET) < 0) {
+		ERRMSG("Can't seek %s. %s\n", filename, strerror(errno));
+		return FALSE;
+	}
+	if (read(fd, phdr, sizeof(Elf32_Phdr)) != sizeof(Elf32_Phdr)) {
+		ERRMSG("Can't read %s. %s\n", filename, strerror(errno));
+		return FALSE;
+	}
+	return TRUE;
+}

  /*
   * Convert Physical Address to File Offset.
diff --git a/elf_info.h b/elf_info.h
index 801faff..925c9f5 100644
--- a/elf_info.h
+++ b/elf_info.h
@@ -27,6 +27,8 @@

  #define MAX_SIZE_NHDR	MAX(sizeof(Elf64_Nhdr), sizeof(Elf32_Nhdr))

+int get_elf64_phdr(int fd, char *filename, int index, Elf64_Phdr *phdr);
+int get_elf32_phdr(int fd, char *filename, int index, Elf32_Phdr *phdr);

  off_t paddr_to_offset(unsigned long long paddr);
  off_t paddr_to_offset2(unsigned long long paddr, off_t hint);
-- 
1.7.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2014-09-19  9:22 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-16  9:48 [PATCH 2/2] makedumpfile: make the incomplete vmcore generated by ENOSPC error analyzable Wang, Xiao/Wang Xiao
2014-09-17  6:47 ` Petr Tesarik
2014-09-18  7:26   ` Wang, Xiao/Wang Xiao
2014-09-18 11:18     ` HATAYAMA, Daisuke
2014-09-18 12:29 ` HATAYAMA, Daisuke
2014-09-19  9:16   ` Wang, Xiao/Wang Xiao
2014-09-19  9:22     ` [PATCH 1/3] makedumpfile: make get_elf64_phdr()/get_elf32_phdr() public Wang, Xiao/Wang Xiao
     [not found] <mailman.12983.1410860958.22890.kexec@lists.infradead.org>
2014-09-16 13:20 ` [PATCH 2/2] makedumpfile: make the incomplete vmcore generated by ENOSPC error analyzable Dave Anderson
2014-09-17  2:41   ` Wang, Xiao/Wang Xiao
2014-09-17 13:55     ` Dave Anderson
2014-09-18  7:19       ` Wang, Xiao/Wang Xiao
2014-09-18 13:56         ` Dave Anderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox