[PATCH] makedumpfile: shorten cyclic exclude-unnecessary passes

Cliff Wickman cpw at sgi.com
Wed Aug 28 18:08:07 EDT 2013


From: Cliff Wickman <cpw at sgi.com>

- get_mm_sparsemem(): reduce the number of entries in the mem_map[] by
  recording only those sections which actually exist in memory
- shorten the executions of __exclude_unnecessary_pages() by passing it only
  the pfn's of the current cyclic area

- for testing: add option -a to use cyclic mode when plenty of memory is
  available for noncyclic mode
  (assumes patch  makedumpfile: use non-cyclic when possible)

- cosmetic: in cyclic mode count the number of cycles and report the cycle
  number as the scan-and-copy cycles progress
- cosmetic: let the prints of unnecessary page scans stop at their current
  position, i.e. at the end of the current cyclic region

makes a progress history like

Begin page counting phase.
Scan cycle 1
Excluding free pages               : [100 %] 
Excluding unnecessary pages        : [ 45 %] 
Scan cycle 2
Excluding free pages               : [ 87 %] 
Excluding unnecessary pages        : [ 87 %] 
Scan cycle 3
Excluding free pages               : [100 %] 
Excluding unnecessary pages        : [ 99 %] 
Scan cycle 4

Scan-and-copy cycle 1/3
Excluding free pages               : [ 45 %] 
Excluding unnecessary pages        : [ 45 %] 
Copying data                       : [ 44 %] 
Scan-and-copy cycle 2/3
Excluding free pages               : [ 87 %] 
Excluding unnecessary pages        : [ 87 %] 
Copying data                       : [ 86 %] 
Scan-and-copy cycle 3/3
Excluding free pages               : [100 %] 
Excluding unnecessary pages        : [ 99 %] 
Copying data                       : [100 %] 
Saving core complete


Diffed against makedumpfile-1.5.4
Signed-off-by: Cliff Wickman <cpw at sgi.com>
---
 makedumpfile.c |  127 +++++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 98 insertions(+), 29 deletions(-)

Index: makedumpfile-1.5.4/makedumpfile.c
===================================================================
--- makedumpfile-1.5.4.orig/makedumpfile.c
+++ makedumpfile-1.5.4/makedumpfile.c
@@ -50,6 +50,8 @@ unsigned long long pfn_hwpoison;
 unsigned long long num_dumped;
 
 int retcd = FAILED;	/* return code */
+int aflag = 0;
+int total_cycles = 0;
 
 #define INITIALIZE_LONG_TABLE(table, value) \
 do { \
@@ -2651,7 +2653,7 @@ sparse_decode_mem_map(unsigned long code
 int
 get_mm_sparsemem(void)
 {
-	unsigned int section_nr, mem_section_size, num_section;
+	unsigned int section_nr, valid_section_nr, mem_section_size, num_section;
 	unsigned long long pfn_start, pfn_end;
 	unsigned long section, mem_map;
 	unsigned long *mem_sec = NULL;
@@ -2686,17 +2688,26 @@ get_mm_sparsemem(void)
 		    strerror(errno));
 		goto out;
 	}
+	valid_section_nr = 0;
 	for (section_nr = 0; section_nr < num_section; section_nr++) {
 		section = nr_to_section(section_nr, mem_sec);
 		mem_map = section_mem_map_addr(section);
 		mem_map = sparse_decode_mem_map(mem_map, section_nr);
-		if (!is_kvaddr(mem_map))
-			mem_map = NOT_MEMMAP_ADDR;
-		pfn_start = section_nr * PAGES_PER_SECTION();
-		pfn_end   = pfn_start + PAGES_PER_SECTION();
-		if (info->max_mapnr < pfn_end)
-			pfn_end = info->max_mapnr;
-		dump_mem_map(pfn_start, pfn_end, mem_map, section_nr);
+		if (is_kvaddr(mem_map)) {
+			pfn_start = section_nr * PAGES_PER_SECTION();
+			pfn_end   = pfn_start + PAGES_PER_SECTION();
+			if (info->max_mapnr < pfn_end)
+				pfn_end = info->max_mapnr;
+			dump_mem_map(pfn_start, pfn_end, mem_map, valid_section_nr);
+			valid_section_nr++;
+		}
+	}
+	info->num_mem_map = valid_section_nr;
+	if (valid_section_nr < num_section) {
+		if (realloc(mem_sec, mem_section_size) != mem_sec) {
+			ERRMSG("mem_sec realloc failed\n");
+			exit(1);
+		};
 	}
 	ret = TRUE;
 out:
@@ -3642,10 +3653,15 @@ reset_bitmap_of_free_pages(unsigned long
 					retcd = ANALYSIS_FAILED;
 					return FALSE;
 				}
-				for (i = 0; i < (1<<order); i++) {
-					pfn = start_pfn + i;
-					if (clear_bit_on_2nd_bitmap_for_kernel(pfn))
-						found_free_pages++;
+
+				if (!info->flag_cyclic ||
+				    ((start_pfn >= info->cyclic_start_pfn) &&
+				     (start_pfn < info->cyclic_end_pfn))) {
+					for (i = 0; i < (1<<order); i++) {
+						pfn = start_pfn + i;
+						if (clear_bit_on_2nd_bitmap_for_kernel(pfn))
+							found_free_pages++;
+					}
 				}
 
 				previous = curr;
@@ -4519,6 +4535,10 @@ int
 exclude_unnecessary_pages_cyclic(void)
 {
 	unsigned int mm;
+	unsigned long pfn_start;
+	unsigned long pfn_end;
+	unsigned long mem_map;
+	long offset;
 	struct mem_map_data *mmd;
 	struct timeval tv_start;
 
@@ -4527,9 +4547,12 @@ exclude_unnecessary_pages_cyclic(void)
 	 */
 	copy_bitmap_cyclic();
 
-	if ((info->dump_level & DL_EXCLUDE_FREE) && !info->page_is_buddy)
+	if ((info->dump_level & DL_EXCLUDE_FREE) && !info->page_is_buddy) {
 		if (!exclude_free_page())
 			return FALSE;
+		else
+			PROGRESS_MSG("\n");
+	}
 
 	/*
 	 * Exclude cache pages, cache private pages, user data pages,
@@ -4549,21 +4572,37 @@ exclude_unnecessary_pages_cyclic(void)
 
 			mmd = &info->mem_map_data[mm];
 
+			// NOT_MEMMAP_ADDR generally not used
 			if (mmd->mem_map == NOT_MEMMAP_ADDR)
 				continue;
 
 			if (mmd->pfn_end >= info->cyclic_start_pfn &&
 			    mmd->pfn_start <= info->cyclic_end_pfn) {
-				if (!__exclude_unnecessary_pages(mmd->mem_map,
-								 mmd->pfn_start, mmd->pfn_end))
+				offset = 0;
+				pfn_start = mmd->pfn_start;
+				pfn_end = mmd->pfn_end;
+				mem_map = mmd->mem_map;
+				if (info->cyclic_end_pfn < pfn_end) {
+					pfn_end = info->cyclic_end_pfn;
+				}
+				if (info->cyclic_start_pfn > pfn_start)	{
+					offset = info->cyclic_start_pfn -
+						pfn_start;
+					mem_map = mmd->mem_map +
+							(SIZE(page) * offset);
+					pfn_start = info->cyclic_start_pfn;
+				}
+
+				if (!__exclude_unnecessary_pages(mem_map,
+							pfn_start, pfn_end))
 					return FALSE;
 			}
 		}
 
 		/*
-		 * print [100 %]
+		 * let progress stop at the print ending position
 		 */
-		print_progress(PROGRESS_UNN_PAGES, info->num_mem_map, info->num_mem_map);
+		PROGRESS_MSG("\n");
 		print_execution_time(PROGRESS_UNN_PAGES, &tv_start);
 	}
 
@@ -4571,7 +4610,7 @@ exclude_unnecessary_pages_cyclic(void)
 }
 
 int
-update_cyclic_region(unsigned long long pfn)
+update_cyclic_region(unsigned long long pfn, int *didscan)
 {
 	if (is_cyclic_region(pfn))
 		return TRUE;
@@ -4588,6 +4627,8 @@ update_cyclic_region(unsigned long long 
 	if (!exclude_unnecessary_pages_cyclic())
 		return FALSE;
 
+	if (didscan)
+		(*didscan)++;
 	return TRUE;
 }
 
@@ -4651,14 +4692,17 @@ create_2nd_bitmap(void)
 			ERRMSG("Can't exclude unnecessary pages.\n");
 			return FALSE;
 		}
+		PROGRESS_MSG("\n");
 	}
 
 	/*
 	 * Exclude free pages.
 	 */
-	if ((info->dump_level & DL_EXCLUDE_FREE) && !info->page_is_buddy)
+	if ((info->dump_level & DL_EXCLUDE_FREE) && !info->page_is_buddy) {
 		if (!exclude_free_page())
 			return FALSE;
+		PROGRESS_MSG("\n");
+	}
 
 	/*
 	 * Exclude Xen user domain.
@@ -5262,15 +5306,26 @@ get_num_dumpable(void)
 unsigned long long
 get_num_dumpable_cyclic(void)
 {
+	int cycle = 0;
+	int lastcycle = 0;
+	int newcycle = 1;
 	unsigned long long pfn, num_dumpable=0;
 
+	PROGRESS_MSG("Begin page counting phase.\n");
 	for (pfn = 0; pfn < info->max_mapnr; pfn++) {
-		if (!update_cyclic_region(pfn))
+		if (newcycle)
+			PROGRESS_MSG("Scan cycle %d\n", cycle + 1);
+		newcycle = 0;
+		lastcycle = cycle;
+		if (!update_cyclic_region(pfn, &cycle))
 			return FALSE;
+		if (cycle > lastcycle)
+			newcycle++;
 
 		if (is_dumpable_cyclic(info->partial_bitmap2, pfn))
 			num_dumpable++;
 	}
+	total_cycles = cycle;
 
 	return num_dumpable;
 }
@@ -5566,7 +5621,7 @@ get_loads_dumpfile_cyclic(void)
 			 * Update target region and bitmap
 			 */
 			if (!is_cyclic_region(pfn)) {
-				if (!update_cyclic_region(pfn))
+				if (!update_cyclic_region(pfn, 0))
 					return FALSE;
 			}
 
@@ -5635,7 +5690,7 @@ write_elf_pages_cyclic(struct cache_data
 
 	info->cyclic_start_pfn = 0;
 	info->cyclic_end_pfn = 0;
-	if (!update_cyclic_region(0))
+	if (!update_cyclic_region(0, 0))
 		return FALSE;
 
 	if (!(phnum = get_phnum_memory()))
@@ -5673,7 +5728,7 @@ write_elf_pages_cyclic(struct cache_data
 			/*
 			 * Update target region and partial bitmap if necessary.
 			 */
-			if (!update_cyclic_region(pfn))
+			if (!update_cyclic_region(pfn, 0))
 				return FALSE;
 
 			if (!is_dumpable_cyclic(info->partial_bitmap2, pfn)) {
@@ -6499,6 +6554,7 @@ out:
 int
 write_kdump_pages_and_bitmap_cyclic(struct cache_data *cd_header, struct cache_data *cd_page)
 {
+	int cycle_number = 1;
 	struct page_desc pd_zero;
 	off_t offset_data=0;
 	struct disk_dump_header *dh = info->dump_header;
@@ -6544,7 +6600,10 @@ write_kdump_pages_and_bitmap_cyclic(stru
 		if (is_cyclic_region(pfn))
 			continue;
 
-		if (!update_cyclic_region(pfn))
+		PROGRESS_MSG("\nScan-and-copy cycle %d/%d\n",
+			cycle_number, total_cycles);
+		cycle_number++;
+		if (!update_cyclic_region(pfn, 0))
                         return FALSE;
 
 		if (!write_kdump_pages_cyclic(cd_header, cd_page, &pd_zero, &offset_data))
@@ -7673,12 +7732,19 @@ create_dumpfile(void)
 	print_vtop();
 
 	if (plenty_of_memory()) {
-		if (info->flag_cyclic == TRUE)
-			MSG("Plenty of memory; using non-cyclic mode.\n");
-		info->flag_cyclic = FALSE;
+		if (info->flag_cyclic == TRUE) {
+			if (aflag)
+				PROGRESS_MSG(
+			     "Plenty of memory; could use non-cyclic mode.\n");
+			else {
+				PROGRESS_MSG(
+				"Plenty of memory; using non-cyclic mode.\n");
+				info->flag_cyclic = FALSE;
+			}
+		}
 	} else {
 		if (info->flag_cyclic == TRUE)
-			MSG("Restricted memory; staying in cyclic mode.\n");
+			PROGRESS_MSG("Restricted memory; staying in cyclic mode.\n");
 	}
 
 	num_retry = 0;
@@ -8623,9 +8689,12 @@ main(int argc, char *argv[])
 	
 	info->block_order = DEFAULT_ORDER;
 	message_level = DEFAULT_MSG_LEVEL;
-	while ((opt = getopt_long(argc, argv, "b:cDd:EFfg:hi:lMpRrsvXx:", longopts,
+	while ((opt = getopt_long(argc, argv, "ab:cDd:EFfg:hi:lMpRrsvXx:", longopts,
 	    NULL)) != -1) {
 		switch (opt) {
+		case 'a':
+			aflag = 1; // force cyclic mode
+			break;
 		case 'b':
 			info->block_order = atoi(optarg);
 			break;



More information about the kexec mailing list