diff options
author | Atsushi Kumagai <kumagai-atsushi@mxc.nes.nec.co.jp> | 2014-02-10 15:34:55 +0900 |
---|---|---|
committer | Atsushi Kumagai <kumagai-atsushi@mxc.nes.nec.co.jp> | 2014-02-10 15:34:55 +0900 |
commit | 2091af13acb46f36641ba2a5567c0e4ae09780cc (patch) | |
tree | c59511419fad75c21ba60a58d3f847fa213c690e /elf_info.c | |
parent | 7a3d4a1f24ff297caf4aecfa4f1249099a8694a2 (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.c | 65 |
1 files changed, 65 insertions, 0 deletions
@@ -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) { |