[RFC PATCH v2 8/10] Implement the main routine of cyclic processing for ELF format.

Atsushi Kumagai kumagai-atsushi at mxc.nes.nec.co.jp
Thu Jun 28 22:23:45 EDT 2012


Implement the function which write out ELF dumpfile cyclically.
The basic idea is same as the routine for kdump-compressed format.

Signed-off-by: Atsushi Kumagai <kumagai-atsushi at mxc.nes.nec.co.jp>
---
 makedumpfile.c |  243 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 238 insertions(+), 5 deletions(-)

diff --git a/makedumpfile.c b/makedumpfile.c
index 420f103..5670bcf 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -4290,9 +4290,16 @@ write_elf_header(struct cache_data *cd_header)
 	/*
 	 * Get the PT_LOAD number of the dumpfile.
 	 */
-	if (!(num_loads_dumpfile = get_loads_dumpfile())) {
-		ERRMSG("Can't get a number of PT_LOAD.\n");
-		goto out;
+	if (info->flag_cyclic) {
+		if (!(num_loads_dumpfile = get_loads_dumpfile_cyclic())) {
+			ERRMSG("Can't get a number of PT_LOAD.\n");
+			goto out;
+		}
+	} else {
+		if (!(num_loads_dumpfile = get_loads_dumpfile())) {
+			ERRMSG("Can't get a number of PT_LOAD.\n");
+			goto out;
+		}
 	}
 
 	if (is_elf64_memory()) { /* ELF64 */
@@ -4959,6 +4966,227 @@ get_loads_dumpfile_cyclic(void)
 }
 
 int
+write_elf_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_page)
+{
+	int i, phnum;
+	long page_size = info->page_size;
+	unsigned char buf[info->page_size];
+	unsigned long long pfn, pfn_start, pfn_end, paddr, num_excluded;
+	unsigned long long num_dumpable, per, num_dumped=0;
+	unsigned long long memsz, filesz;
+	unsigned long frac_head, frac_tail;
+	off_t off_seg_load, off_memory;
+	Elf64_Phdr load;
+	struct timeval tv_start;
+
+	if (!info->flag_elf_dumpfile)
+		return FALSE;
+
+	num_dumpable = info->num_dumpable;
+	per = num_dumpable / 100;
+
+	off_seg_load   = info->offset_load_dumpfile;
+	cd_page->offset = info->offset_load_dumpfile;
+
+	/*
+	 * Reset counter for debug message.
+	 */
+	pfn_zero =  pfn_cache = pfn_cache_private = pfn_user = pfn_free = 0;
+	pfn_memhole = info->max_mapnr;
+
+	info->cyclic_start_pfn = 0;
+	info->cyclic_end_pfn = 0;
+	if (!update_cyclic_region(0))
+		return FALSE;
+
+	if (!(phnum = get_phnum_memory()))
+		return FALSE;
+
+	gettimeofday(&tv_start, NULL);
+
+	for (i = 0; i < phnum; i++) {
+		if (!get_phdr_memory(i, &load))
+			return FALSE;
+
+		if (load.p_type != PT_LOAD)
+			continue;
+
+		off_memory= load.p_offset;
+		paddr = load.p_paddr;
+		pfn_start = paddr_to_pfn(load.p_paddr);
+		pfn_end = paddr_to_pfn(load.p_paddr + load.p_memsz);
+		frac_head = page_size - (load.p_paddr % page_size);
+		frac_tail = (load.p_paddr + load.p_memsz)%page_size;
+
+		num_excluded = 0;
+		memsz  = 0;
+		filesz = 0;
+		if (frac_head && (frac_head != page_size)) {
+			memsz  = frac_head;
+			filesz = frac_head;
+			pfn_start++;
+		}
+
+		if (frac_tail)
+			pfn_end++;
+
+		for (pfn = pfn_start; pfn < pfn_end; pfn++) {
+			/*
+			 * Update target region and partial bitmap if necessary.
+			 */
+			if (!update_cyclic_region(pfn))
+				return FALSE;
+
+			if (!is_dumpable_cyclic(info->partial_bitmap2, pfn)) {
+				num_excluded++;
+				if ((pfn == pfn_end - 1) && frac_tail)
+					memsz += frac_tail;
+				else
+					memsz += page_size;
+				continue;
+			}
+
+			/*
+			 * Exclude zero pages.
+			 */
+			if (info->dump_level & DL_EXCLUDE_ZERO) {
+				if (!read_pfn(pfn, buf))
+					return FALSE;
+				if (is_zero_page(buf, page_size)) {
+					pfn_zero++;
+					num_excluded++;
+					if ((pfn == pfn_end - 1) && frac_tail)
+						memsz += frac_tail;
+					else
+						memsz += page_size;
+					continue;
+				}
+			}
+
+			if ((num_dumped % per) == 0)
+				print_progress(PROGRESS_COPY, num_dumped, num_dumpable);
+
+			num_dumped++;
+
+			/*
+			 * The dumpable pages are continuous.
+			 */
+			if (!num_excluded) {
+				if ((pfn == pfn_end - 1) && frac_tail) {
+					memsz  += frac_tail;
+					filesz += frac_tail;
+				} else {
+					memsz  += page_size;
+					filesz += page_size;
+				}
+				continue;
+				/*
+				 * If the number of the contiguous pages to be excluded
+				 * is 255 or less, those pages are not excluded.
+				 */
+			} else if (num_excluded < PFN_EXCLUDED) {
+				if ((pfn == pfn_end - 1) && frac_tail) {
+					memsz  += frac_tail;
+					filesz += (page_size*num_excluded
+						   + frac_tail);
+				}else {
+					memsz  += page_size;
+					filesz += (page_size*num_excluded
+						   + page_size);
+				}
+				num_excluded = 0;
+				continue;
+			}
+
+			/*
+			 * If the number of the contiguous pages to be excluded
+			 * is 256 or more, those pages are excluded really.
+			 * And a new PT_LOAD segment is created.
+			 */
+			load.p_memsz = memsz;
+			load.p_filesz = filesz;
+			if (load.p_filesz)
+				load.p_offset = off_seg_load;
+			else
+				/*
+				 * If PT_LOAD segment does not have real data
+				 * due to the all excluded pages, the file
+				 * offset is not effective and it should be 0.
+				 */
+				load.p_offset = 0;
+
+			/*
+			 * Write a PT_LOAD header.
+			 */
+			if (!write_elf_phdr(cd_header, &load))
+				return FALSE;
+
+			/*
+			 * Write a PT_LOAD segment.
+			 */
+			if (load.p_filesz)
+				if (!write_elf_load_segment(cd_page, paddr,
+							    off_memory, load.p_filesz))
+					return FALSE;
+
+			load.p_paddr += load.p_memsz;
+#ifdef __x86__
+			/*
+			 * FIXME:
+			 *  (x86) Fill PT_LOAD headers with appropriate
+			 * virtual addresses.
+			 */
+			if (load.p_paddr < MAXMEM)
+				load.p_vaddr += load.p_memsz;
+#else
+			load.p_vaddr += load.p_memsz;
+#endif /* x86 */
+			paddr  = load.p_paddr;
+			off_seg_load += load.p_filesz;
+
+			num_excluded = 0;
+			memsz  = page_size;
+			filesz = page_size;
+		}
+		/*
+		 * Write the last PT_LOAD.
+		 */
+		load.p_memsz = memsz;
+		load.p_filesz = filesz;
+		load.p_offset = off_seg_load;
+
+		/*
+		 * Write a PT_LOAD header.
+		 */
+		if (!write_elf_phdr(cd_header, &load))
+			return FALSE;
+
+		/*
+		 * Write a PT_LOAD segment.
+		 */
+		if (load.p_filesz)
+			if (!write_elf_load_segment(cd_page, paddr,
+						    off_memory, load.p_filesz))
+				return FALSE;
+
+		off_seg_load += load.p_filesz;
+	}
+	if (!write_cache_bufsz(cd_header))
+		return FALSE;
+	if (!write_cache_bufsz(cd_page))
+		return FALSE;
+
+	/*
+	 * print [100 %]
+	 */
+	print_progress(PROGRESS_COPY, num_dumpable, num_dumpable);
+	print_execution_time(PROGRESS_COPY, &tv_start);
+	PROGRESS_MSG("\n");
+
+	return TRUE;
+}
+
+int
 write_kdump_pages(struct cache_data *cd_header, struct cache_data *cd_page)
 {
  	unsigned long long pfn, per, num_dumpable, num_dumped = 0;
@@ -6430,8 +6658,13 @@ writeout_dumpfile(void)
 	if (info->flag_elf_dumpfile) {
 		if (!write_elf_header(&cd_header))
 			goto out;
-		if (!write_elf_pages(&cd_header, &cd_page))
-			goto out;
+		if (info->flag_cyclic) {
+			if (!write_elf_pages_cyclic(&cd_header, &cd_page))
+				goto out;
+		} else {
+			if (!write_elf_pages(&cd_header, &cd_page))
+				goto out;
+		}
 		if (!write_elf_eraseinfo(&cd_header))
 			goto out;
 	} else if (info->flag_cyclic) {
-- 
1.7.9.2



More information about the kexec mailing list