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

Hatayama, Daisuke d.hatayama at jp.fujitsu.com
Tue Feb 19 00:05:39 EST 2013


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>
---
 makedumpfile.c |   28 ++++++++++++++--------------
 1 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/makedumpfile.c b/makedumpfile.c
index acb1b21..0bc8e1c 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,14 @@ 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;
+	read_size = info->page_size - PAGEOFFSET(paddr);
 
-		if (!readmem(type_addr, next_addr, next_ptr, next_size))
-			goto error;
-	}
+	if (read_size > size)
+		read_size = size;
 
 	pgaddr = PAGEBASE(paddr);
 	pgbuf = cache_search(pgaddr);
@@ -423,7 +415,15 @@ 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);
-- 
1.7.7.6




More information about the kexec mailing list