[PATCH 2/2] Write out a whole part of the 1st bitmap before entering cyclic process

HATAYAMA Daisuke d.hatayama at jp.fujitsu.com
Thu Oct 24 02:52:05 EDT 2013


Currently, 1st bitmap is created during cyclic process, but the
information represented by the 1st bitmap, originally present memory,
is still available from ELF program header table, so we don't need to
keep the 1st bitmap even in cyclic process.

Supported is a conversion from ELF to kdump-compressed format only,
not from ELF to ELF.

Signed-off-by: HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com>
---
 makedumpfile.c |  224 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 202 insertions(+), 22 deletions(-)

diff --git a/makedumpfile.c b/makedumpfile.c
index 4b6c0ed..7440c97 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -3055,7 +3055,8 @@ out:
 				 * bufsize_cyclic is used to allocate 1st and 2nd bitmap, 
 				 * so it should be truncated to the half of free_memory.
 				 */
-				info->bufsize_cyclic = free_memory / 2;
+				if (info->flag_elf_dumpfile)
+					info->bufsize_cyclic = free_memory / 2;
 			}
 		}
 
@@ -3328,6 +3329,33 @@ clear_bit_on_2nd_bitmap_for_kernel(unsigned long long pfn)
 	return clear_bit_on_2nd_bitmap(pfn);
 }
 
+int
+set_bit_on_2nd_bitmap(unsigned long long pfn)
+{
+	if (info->flag_cyclic) {
+		return set_bitmap_cyclic(info->partial_bitmap2, pfn, 1);
+	} else {
+		return set_bitmap(info->bitmap2, pfn, 1);
+	}
+}
+
+int
+set_bit_on_2nd_bitmap_for_kernel(unsigned long long pfn)
+{
+	unsigned long long maddr;
+
+	if (is_xen_memory()) {
+		maddr = ptom_xen(pfn_to_paddr(pfn));
+		if (maddr == NOT_PADDR) {
+			ERRMSG("Can't convert a physical address(%llx) to machine address.\n",
+			    pfn_to_paddr(pfn));
+			return FALSE;
+		}
+		pfn = paddr_to_pfn(maddr);
+	}
+	return set_bit_on_2nd_bitmap(pfn);
+}
+
 static inline int
 is_in_segs(unsigned long long paddr)
 {
@@ -4418,6 +4446,53 @@ exclude_zero_pages(void)
 	return TRUE;
 }
 
+static int
+initialize_2nd_bitmap_cyclic(void)
+{
+	int i;
+	unsigned long long pfn;
+	unsigned long long phys_start, phys_end;
+	unsigned long long pfn_start, pfn_end;
+	unsigned long long pfn_start_roundup, pfn_end_round;
+	unsigned long pfn_start_byte, pfn_end_byte;
+
+	/*
+	 * At first, clear all the bits on the 2nd-bitmap.
+	 */
+	initialize_bitmap_cyclic(info->partial_bitmap2);
+
+	/*
+	 * If page is on memory hole, set bit on the 2nd-bitmap.
+	 */
+	for (i = 0; get_pt_load(i, &phys_start, &phys_end, NULL, NULL); i++) {
+		pfn_start = MAX(paddr_to_pfn(phys_start), info->cyclic_start_pfn);
+		pfn_end = MIN(paddr_to_pfn(phys_end), info->cyclic_end_pfn);
+
+		if (pfn_start >= pfn_end)
+			continue;
+
+		pfn_start_roundup = roundup(pfn_start, BITPERBYTE);
+		pfn_end_round = round(pfn_end, BITPERBYTE);
+
+		for (pfn = pfn_start; pfn < pfn_start_roundup; ++pfn)
+			if (!set_bit_on_2nd_bitmap_for_kernel(pfn))
+				return FALSE;
+
+		pfn_start_byte = (pfn_start_roundup - info->cyclic_start_pfn) >> 3;
+		pfn_end_byte = (pfn_end_round - info->cyclic_start_pfn) >> 3;
+
+		memset(info->partial_bitmap2 + pfn_start_byte,
+		       0xff,
+		       pfn_end_byte - pfn_start_byte);
+
+		for (pfn = pfn_end_round; pfn < pfn_end; ++pfn)
+			if (!set_bit_on_2nd_bitmap_for_kernel(pfn))
+				return FALSE;
+	}
+
+	return TRUE;
+}
+
 int
 __exclude_unnecessary_pages(unsigned long mem_map,
     unsigned long long pfn_start, unsigned long long pfn_end)
@@ -4584,12 +4659,6 @@ exclude_unnecessary_pages(void)
 	return TRUE;
 }
 
-void
-copy_bitmap_cyclic(void)
-{
-	memcpy(info->partial_bitmap2, info->partial_bitmap1, info->bufsize_cyclic);
-}
-
 int
 exclude_unnecessary_pages_cyclic(void)
 {
@@ -4597,10 +4666,8 @@ exclude_unnecessary_pages_cyclic(void)
 	struct mem_map_data *mmd;
 	struct timeval tv_start;
 
-	/*
-	 * Copy 1st-bitmap to 2nd-bitmap.
-	 */
-	copy_bitmap_cyclic();
+	if (!initialize_2nd_bitmap_cyclic())
+		return FALSE;
 
 	if ((info->dump_level & DL_EXCLUDE_FREE) && !info->page_is_buddy)
 		if (!exclude_free_page())
@@ -4657,7 +4724,7 @@ update_cyclic_region(unsigned long long pfn)
 	if (info->cyclic_end_pfn > info->max_mapnr)
 		info->cyclic_end_pfn = info->max_mapnr;
 
-	if (!create_1st_bitmap_cyclic())
+	if (info->flag_elf_dumpfile && !create_1st_bitmap_cyclic())
 		return FALSE;
 
 	if (!exclude_unnecessary_pages_cyclic())
@@ -4841,19 +4908,71 @@ prepare_bitmap_buffer_cyclic(void)
 	return TRUE;
 }
 
+int
+prepare_bitmap1_buffer_cyclic(void)
+{
+	/*
+	 * Prepare partial bitmap buffers for cyclic processing.
+	 */
+	if ((info->partial_bitmap1 = (char *)malloc(info->bufsize_cyclic)) == NULL) {
+		ERRMSG("Can't allocate memory for the 1st bitmaps. %s\n",
+		       strerror(errno));
+		return FALSE;
+	}
+	initialize_bitmap_cyclic(info->partial_bitmap1);
+
+	return TRUE;
+}
+
+int
+prepare_bitmap2_buffer_cyclic(void)
+{
+	unsigned long tmp;
+
+	/*
+	 * Create 2 bitmaps (1st-bitmap & 2nd-bitmap) on block_size
+	 * boundary. The crash utility requires both of them to be
+	 * aligned to block_size boundary.
+	 */
+	tmp = divideup(divideup(info->max_mapnr, BITPERBYTE), info->page_size);
+	info->len_bitmap = tmp * info->page_size * 2;
+
+	/*
+	 * Prepare partial bitmap buffers for cyclic processing.
+	 */
+	if ((info->partial_bitmap2 = (char *)malloc(info->bufsize_cyclic)) == NULL) {
+		ERRMSG("Can't allocate memory for the 2nd bitmaps. %s\n",
+		       strerror(errno));
+		return FALSE;
+	}
+	initialize_bitmap_cyclic(info->partial_bitmap2);
+
+	return TRUE;
+}
+
 void
-free_bitmap_buffer(void)
+free_bitmap1_buffer(void)
 {
 	if (info->bitmap1) {
 		free(info->bitmap1);
 		info->bitmap1 = NULL;
 	}
+}
+
+void
+free_bitmap2_buffer(void)
+{
 	if (info->bitmap2) {
 		free(info->bitmap2);
 		info->bitmap2 = NULL;
 	}
+}
 
-	return;
+void
+free_bitmap_buffer(void)
+{
+	free_bitmap1_buffer();
+	free_bitmap2_buffer();
 }
 
 int
@@ -4862,10 +4981,21 @@ create_dump_bitmap(void)
 	int ret = FALSE;
 
 	if (info->flag_cyclic) {
-		if (!prepare_bitmap_buffer_cyclic())
-			goto out;
 
-		info->num_dumpable = get_num_dumpable_cyclic();
+		if (info->flag_elf_dumpfile) {
+			if (!prepare_bitmap_buffer_cyclic())
+				goto out;
+
+			info->num_dumpable = get_num_dumpable_cyclic();
+		} else {
+			if (!prepare_bitmap2_buffer_cyclic())
+				goto out;
+
+			info->num_dumpable = get_num_dumpable_cyclic();
+
+			free_bitmap2_buffer();
+		}
+
 	} else {
 		if (!prepare_bitmap_buffer())
 			goto out;
@@ -6564,7 +6694,7 @@ out:
 }
 
 int
-write_kdump_bitmap_cyclic(void)
+write_kdump_bitmap1_cyclic(void)
 {
 	off_t offset;
         int increment;
@@ -6576,10 +6706,30 @@ write_kdump_bitmap_cyclic(void)
 		return FALSE;
 
 	offset = info->offset_bitmap1;
-	if (!write_buffer(info->fd_dumpfile, offset,
+	if (!write_buffer(info->fd_dumpfile, offset + info->bufsize_cyclic *
+			  (info->cyclic_start_pfn / info->pfn_cyclic),
 			  info->partial_bitmap1, increment, info->name_dumpfile))
 		goto out;
 
+	ret = TRUE;
+out:
+	return ret;
+}
+
+int
+write_kdump_bitmap2_cyclic(void)
+{
+	off_t offset;
+	int increment;
+	int ret = FALSE;
+
+	increment = divideup(info->cyclic_end_pfn - info->cyclic_start_pfn,
+			     BITPERBYTE);
+
+	if (info->flag_elf_dumpfile)
+		return FALSE;
+
+	offset = info->offset_bitmap1;
 	offset += info->len_bitmap / 2;
 	if (!write_buffer(info->fd_dumpfile, offset,
 			  info->partial_bitmap2, increment, info->name_dumpfile))
@@ -6633,6 +6783,30 @@ write_kdump_pages_and_bitmap_cyclic(struct cache_data *cd_header, struct cache_d
 	}
 
 	/*
+	 * Write the 1st bitmap
+	 */
+	if (!prepare_bitmap1_buffer_cyclic())
+		return FALSE;
+
+	info->cyclic_start_pfn = 0;
+	info->cyclic_end_pfn = 0;
+	for (pfn = 0; pfn < info->max_mapnr; pfn++) {
+		if (is_cyclic_region(pfn))
+			continue;
+		if (!update_cyclic_region(pfn))
+			return FALSE;
+		if (!create_1st_bitmap_cyclic())
+			return FALSE;
+		if (!write_kdump_bitmap1_cyclic())
+			return FALSE;
+	}
+
+	free_bitmap1_buffer();
+
+	if (!prepare_bitmap2_buffer_cyclic())
+		return FALSE;
+
+	/*
 	 * Write pages and bitmap cyclically.
 	 */
 	info->cyclic_start_pfn = 0;
@@ -6647,7 +6821,7 @@ write_kdump_pages_and_bitmap_cyclic(struct cache_data *cd_header, struct cache_d
 		if (!write_kdump_pages_cyclic(cd_header, cd_page, &pd_zero, &offset_data))
 			return FALSE;
 
-		if (!write_kdump_bitmap_cyclic())
+		if (!write_kdump_bitmap2_cyclic())
 			return FALSE;
         }
 
@@ -8681,8 +8855,14 @@ calculate_cyclic_buffer_size(void) {
 	 * should be 40% of free memory to keep the size of cyclic buffer
 	 * within 80% of free memory.
 	 */
-	free_size = get_free_memory_size() * 0.4;
-	needed_size = (info->max_mapnr * 2) / BITPERBYTE;
+	if (info->flag_elf_dumpfile) {
+		free_size = get_free_memory_size() * 0.4;
+		needed_size = (info->max_mapnr * 2) / BITPERBYTE;
+	} else {
+		free_size = get_free_memory_size() * 0.8;
+		needed_size = info->max_mapnr / BITPERBYTE;
+	}
+
 	/* if --split was specified cyclic buffer allocated per dump file */
 	if (info->num_dumpfile > 1)
 		needed_size /= info->num_dumpfile;




More information about the kexec mailing list