From: Qiao Nuohan <qiaonuohan@xxxxxxxxxxxxxx> readpage_elf_parallel is used to enable reading pages from elf format parallelly. fd_memory should be initialize and offered to each threads individually to avoid conflict. Signed-off-by: Qiao Nuohan <qiaonuohan at cn.fujitsu.com> --- makedumpfile.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/makedumpfile.c b/makedumpfile.c index d1b4bc2..44c78b4 100644 --- a/makedumpfile.c +++ b/makedumpfile.c @@ -575,6 +575,27 @@ read_from_vmcore(off_t offset, void *bufptr, unsigned long size) return TRUE; } +static int +read_from_vmcore_parallel(int fd_memory, off_t offset, void *bufptr, + unsigned long size) +{ + const off_t failed = (off_t)-1; + + if (lseek(fd_memory, offset, SEEK_SET) == failed) { + ERRMSG("Can't seek the dump memory(%s). (offset: %llx) %s\n", + info->name_memory, (unsigned long long)offset, strerror(errno)); + return FALSE; + } + + if (read(fd_memory, bufptr, size) != size) { + ERRMSG("Can't read the dump memory(%s). %s\n", + info->name_memory, strerror(errno)); + return FALSE; + } + + return TRUE; +} + /* * This function is specific for reading page from ELF. * @@ -669,6 +690,83 @@ readpage_elf(unsigned long long paddr, void *bufptr) } static int +readpage_elf_parallel(int fd_memory, unsigned long long paddr, void *bufptr) +{ + off_t offset1, offset2; + size_t size1, size2; + unsigned long long phys_start, phys_end, frac_head = 0; + + offset1 = paddr_to_offset(paddr); + offset2 = paddr_to_offset(paddr + info->page_size); + phys_start = paddr; + phys_end = paddr + info->page_size; + + /* + * Check the case phys_start isn't aligned by page size like below: + * + * phys_start + * = 0x40ffda7000 + * |<-- frac_head -->|------------- PT_LOAD ------------- + * ----+-----------------------+---------------------+---- + * | pfn:N | pfn:N+1 | ... + * ----+-----------------------+---------------------+---- + * | + * pfn_to_paddr(pfn:N) # page size = 16k + * = 0x40ffda4000 + */ + if (!offset1) { + phys_start = page_head_to_phys_start(paddr); + offset1 = paddr_to_offset(phys_start); + frac_head = phys_start - paddr; + memset(bufptr, 0, frac_head); + } + + /* + * Check the case phys_end isn't aligned by page size like the + * phys_start's case. + */ + if (!offset2) { + phys_end = page_head_to_phys_end(paddr); + offset2 = paddr_to_offset(phys_end); + memset(bufptr + (phys_end - paddr), 0, info->page_size + - (phys_end - paddr)); + } + + /* + * Check the separated page on different PT_LOAD segments. + */ + if (offset1 + (phys_end - phys_start) == offset2) { + size1 = phys_end - phys_start; + } else { + for (size1 = 1; size1 < info->page_size - frac_head; size1++) { + offset2 = paddr_to_offset(phys_start + size1); + if (offset1 + size1 != offset2) + break; + } + } + + if(!read_from_vmcore_parallel(fd_memory, offset1, bufptr + frac_head, + size1)) { + ERRMSG("Can't read the dump memory(%s).\n", + info->name_memory); + return FALSE; + } + + if (size1 + frac_head != info->page_size) { + size2 = phys_end - (phys_start + size1); + + if(!read_from_vmcore_parallel(fd_memory, offset2, + bufptr + frac_head + size1, size2)) { + ERRMSG("Can't read the dump memory(%s).\n", + info->name_memory); + return FALSE; + } + } + + return TRUE; +} + +static int readpage_kdump_compressed(unsigned long long paddr, void *bufptr) { page_desc_t pd; -- 1.8.3.1