summaryrefslogtreecommitdiff
path: root/elf_info.c
diff options
context:
space:
mode:
authorAtsushi Kumagai <kumagai-atsushi@mxc.nes.nec.co.jp>2014-02-10 15:34:55 +0900
committerAtsushi Kumagai <kumagai-atsushi@mxc.nes.nec.co.jp>2014-02-10 15:34:55 +0900
commit2091af13acb46f36641ba2a5567c0e4ae09780cc (patch)
treec59511419fad75c21ba60a58d3f847fa213c690e /elf_info.c
parent7a3d4a1f24ff297caf4aecfa4f1249099a8694a2 (diff)
[PATCH] Restrict the mmap range to avoid mmap() failure.
Now, we know that mmap() on /proc/vmcore for fractional pages will fail due to a sanity check in remap_pfn_range(). In that case, current makedumpfile can fall back to read() mode, but it's still desirable to use mmap() as much as possible for performance. This patch restricts the range of mmap() to avoid the fall back. The original kernel issue was reported in: https://lkml.org/lkml/2013/11/13/439 and it will be fixed in kernel 3.14. Signed-off-by: Atsushi Kumagai <kumagai-atsushi@mxc.nes.nec.co.jp>
Diffstat (limited to 'elf_info.c')
-rw-r--r--elf_info.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/elf_info.c b/elf_info.c
index e350b99..b277f69 100644
--- a/elf_info.c
+++ b/elf_info.c
@@ -488,6 +488,71 @@ page_head_to_phys_end(unsigned long long head_paddr)
return 0;
}
+/*
+ * Calculate a start File Offset of PT_LOAD from a File Offset
+ * of a page. If this function returns 0x0, the input page is
+ * not in the memory image.
+ */
+off_t
+offset_to_pt_load_start(off_t offset)
+{
+ int i;
+ off_t pt_load_start;
+ struct pt_load_segment *pls;
+
+ for (i = pt_load_start = 0; i < num_pt_loads; i++) {
+ pls = &pt_loads[i];
+ if ((offset >= pls->file_offset)
+ && (offset < pls->file_offset +
+ (pls->phys_end - pls->phys_start))) {
+ pt_load_start = pls->file_offset;
+ break;
+ }
+ }
+ return pt_load_start;
+}
+
+/*
+ * Calculate a end File Offset of PT_LOAD from a File Offset
+ * of a page. If this function returns 0x0, the input page is
+ * not in the memory image.
+ */
+off_t
+offset_to_pt_load_end(off_t offset)
+{
+ int i;
+ off_t pt_load_end;
+ struct pt_load_segment *pls;
+
+ for (i = pt_load_end = 0; i < num_pt_loads; i++) {
+ pls = &pt_loads[i];
+ if ((offset >= pls->file_offset)
+ && (offset < pls->file_offset +
+ (pls->phys_end - pls->phys_start))) {
+ pt_load_end = (off_t)(pls->file_offset +
+ (pls->phys_end - pls->phys_start));
+ break;
+ }
+ }
+ return pt_load_end;
+}
+
+/*
+ * Judge whether the page is fractional or not.
+ */
+int
+page_is_fractional(off_t page_offset)
+{
+ if (page_offset % info->page_size != 0)
+ return TRUE;
+
+ if (offset_to_pt_load_end(page_offset) - page_offset
+ < info->page_size)
+ return TRUE;
+
+ return FALSE;
+}
+
unsigned long long
vaddr_to_paddr_general(unsigned long long vaddr)
{