[PATCH] makedumpfile: clean up readmem() by removing its recursive call

Atsushi Kumagai kumagai-atsushi at mxc.nes.nec.co.jp
Thu Feb 21 02:04:09 EST 2013


Hello HATAYAMA-san,

On Thu, 21 Feb 2013 03:27:22 +0000
"Hatayama, Daisuke" <d.hatayama at jp.fujitsu.com> wrote:

> > From: kexec-bounces at lists.infradead.org
> > Sent: Wednesday, February 20, 2013 11:25 AM
> 
> > On Tue, 19 Feb 2013 05:05:39 +0000
> > "Hatayama, Daisuke" <d.hatayama at jp.fujitsu.com> wrote:
> > 
> > > Currently, readmem() calls itself recursively and its depth grows in
> > > proportin to the number of requested pages.
> > >
> > > For example, in __exclude_unnecessary_pages(), PGMM_CACHED is defined
> > > as 512 and page structure is of 56 bytes on x86_64, so size of page
> > > cache on x86_64 is now 56 * 512 = 28KiB, and this is 7 pages. This
> > > means that on the existing implementation readmem() is called
> > > recursively 7 times when reading mem_map array, but 6 of the 7 are
> > > in fact unnecessary.
> > >
> > > This patch cleans up readmem() by removing the recursive
> > > call. Instead, readmem() proceeds to the processing for next page by
> > > jump.
> > >
> > > Also, by this change, read operation is done in increasing order. This
> > > is more natural than the existing implementation in decreasing order.
> > >
> > > Signed-off-by: HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com>
> > 
> > Thanks, I'll merge this patch into v1.5.4.
> 
> Sorry, I found I missed replacing size by size_orig at the last error path.
> 
> Could you use this new patch? There I also made some cleanup using MIN() and added performance topic a little in patch description.

Sure, I'll merge this one instead of old one.


Thanks
Atsushi Kumagai

> Thanks.
> HATAYAMA, Daisuke
> 
> From b5b603f465118f23d92f8c69e300281e6321ebe4 Mon Sep 17 00:00:00 2001
> From: HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com>
> Date: Wed, 20 Feb 2013 20:13:07 +0900
> Subject: [PATCH] makedumpfile: clean up readmem() by removing its recursive
>  call
> 
> Currently, readmem() calls itself recursively and its depth grows in
> proportin to the number of requested pages.
> 
> For example, in __exclude_unnecessary_pages(), PGMM_CACHED is defined
> as 512 and page structure is of 56 bytes on x86_64, so size of page
> descriper cache on x86_64 is now 56 * 512 = 28KiB, and this is 7
> pages. This means that on the existing implementation, readmem() is
> called recursively 7 times when reading one entry of page descripter
> cache from mem_map array, but 6 of the 7 are in fact unnecessary.
> 
> This patch cleans up readmem() by removing the recursive
> call. Instead, readmem() proceeds to the processing for next page by
> jump.
> 
> By this change, read operation is done in increasing order. This is
> more natural than the existing implementation in decreasing order.
> 
> Also, there's visible performance gain. On 32GiB memory machine,
> repeating filtering 100-times on /proc/vmcore, average time for
> filtering on mem_map array was improved from 1.69 to 1.33 second:
> about 21.3 percent.
> 
> Signed-off-by: HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com>
> ---
>  makedumpfile.c | 29 +++++++++++++----------------
>  1 file changed, 13 insertions(+), 16 deletions(-)
> 
> diff --git a/makedumpfile.c b/makedumpfile.c
> index acb1b21..14e8773 100644
> --- a/makedumpfile.c
> +++ b/makedumpfile.c
> @@ -337,13 +337,12 @@ readpage_kdump_compressed(unsigned long long paddr, void *bufptr)
>  int
>  readmem(int type_addr, unsigned long long addr, void *bufptr, size_t size)
>  {
> -	size_t read_size, next_size;
> -	unsigned long long next_addr;
> +	size_t read_size, size_orig = size;
>  	unsigned long long paddr, maddr = NOT_PADDR;
>  	unsigned long long pgaddr;
>  	void *pgbuf;
> -	char *next_ptr;
>  
> +next_page:
>  	switch (type_addr) {
>  	case VADDR:
>  		if ((paddr = vaddr_to_paddr(addr)) == NOT_PADDR) {
> @@ -386,21 +385,11 @@ readmem(int type_addr, unsigned long long addr, void *bufptr, size_t size)
>  		goto error;
>  	}
>  
> -	read_size = size;
> -
>  	/*
>  	 * Read each page, because pages are not necessarily continuous.
>  	 * Ex) pages in vmalloc area
>  	 */
> -	if (!is_in_same_page(addr, addr + size - 1)) {
> -		read_size = info->page_size - (addr % info->page_size);
> -		next_addr = roundup(addr + 1, info->page_size);
> -		next_size = size - read_size;
> -		next_ptr  = (char *)bufptr + read_size;
> -
> -		if (!readmem(type_addr, next_addr, next_ptr, next_size))
> -			goto error;
> -	}
> +	read_size = MIN(info->page_size - PAGEOFFSET(paddr), size);
>  
>  	pgaddr = PAGEBASE(paddr);
>  	pgbuf = cache_search(pgaddr);
> @@ -423,10 +412,18 @@ readmem(int type_addr, unsigned long long addr, void *bufptr, size_t size)
>  	}
>  
>  	memcpy(bufptr, pgbuf + PAGEOFFSET(paddr), read_size);
> -	return size;
> +
> +	addr += read_size;
> +	bufptr += read_size;
> +	size -= read_size;
> +
> +	if (size > 0)
> +		goto next_page;
> +
> +	return size_orig;
>  
>  error:
> -	ERRMSG("type_addr: %d, addr:%llx, size:%zd\n", type_addr, addr, size);
> +	ERRMSG("type_addr: %d, addr:%llx, size:%zd\n", type_addr, addr, size_orig);
>  	return FALSE;
>  }
>  
> -- 
> 1.8.1.2
> 



More information about the kexec mailing list