[PATCH v4 02/10] Add mappage_elf_parallel
Zhou Wenjian
zhouwj-fnst at cn.fujitsu.com
Wed Aug 5 23:08:03 PDT 2015
From: Qiao Nuohan <qiaonuohan at cn.fujitsu.com>
mappage_elf_parallel is used to enable mmaping elf format to memory
parallelly. later patch will will use the mmapped memory to get data
of each page. fd_memory and mmap_cache should be initialized and offered
to each threads individually to avoid conflict.
Signed-off-by: Qiao Nuohan <qiaonuohan at cn.fujitsu.com>
---
makedumpfile.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
makedumpfile.h | 14 +++++++++
2 files changed, 111 insertions(+)
diff --git a/makedumpfile.c b/makedumpfile.c
index 3657d4f..d1b4bc2 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -394,6 +394,46 @@ update_mmap_range(off_t offset, int initial) {
}
static int
+update_mmap_range_parallel(int fd_memory, off_t offset,
+ struct mmap_cache *mmap_cache)
+{
+ off_t start_offset, end_offset;
+ off_t map_size;
+ off_t max_offset = get_max_file_offset();
+ off_t pt_load_end = offset_to_pt_load_end(offset);
+
+ /*
+ * mmap_buf must be cleaned
+ */
+ if (mmap_cache->mmap_buf != MAP_FAILED)
+ munmap(mmap_cache->mmap_buf, mmap_cache->mmap_end_offset
+ - mmap_cache->mmap_start_offset);
+
+ /*
+ * offset for mmap() must be page aligned.
+ */
+ start_offset = roundup(offset, info->page_size);
+ end_offset = MIN(max_offset, round(pt_load_end, info->page_size));
+
+ if (!pt_load_end || (end_offset - start_offset) <= 0)
+ return FALSE;
+
+ map_size = MIN(end_offset - start_offset, info->mmap_region_size);
+
+ mmap_cache->mmap_buf = mmap(NULL, map_size, PROT_READ, MAP_PRIVATE,
+ fd_memory, start_offset);
+
+ if (mmap_cache->mmap_buf == MAP_FAILED) {
+ return FALSE;
+ }
+
+ mmap_cache->mmap_start_offset = start_offset;
+ mmap_cache->mmap_end_offset = start_offset + map_size;
+
+ return TRUE;
+}
+
+static int
is_mapped_with_mmap(off_t offset) {
if (info->flag_usemmap == MMAP_ENABLE
@@ -404,6 +444,15 @@ is_mapped_with_mmap(off_t offset) {
return FALSE;
}
+static int
+is_mapped_with_mmap_parallel(off_t offset, struct mmap_cache *mmap_cache) {
+ if (offset >= mmap_cache->mmap_start_offset
+ && offset < mmap_cache->mmap_end_offset)
+ return TRUE;
+ else
+ return FALSE;
+}
+
int
initialize_mmap(void) {
unsigned long long phys_start;
@@ -458,6 +507,54 @@ mappage_elf(unsigned long long paddr)
return info->mmap_buf + (offset - info->mmap_start_offset);
}
+static char *
+mappage_elf_parallel(int fd_memory, unsigned long long paddr,
+ struct mmap_cache *mmap_cache)
+{
+ off_t offset, offset2;
+ int flag_usemmap;
+
+ pthread_rwlock_rdlock(&info->usemmap_rwlock);
+ flag_usemmap = info->flag_usemmap;
+ pthread_rwlock_unlock(&info->usemmap_rwlock);
+ if (flag_usemmap != MMAP_ENABLE)
+ return NULL;
+
+ offset = paddr_to_offset(paddr);
+ if (!offset || page_is_fractional(offset))
+ return NULL;
+
+ offset2 = paddr_to_offset(paddr + info->page_size - 1);
+ if (!offset2)
+ return NULL;
+
+ if (offset2 - offset != info->page_size - 1)
+ return NULL;
+
+ if (!is_mapped_with_mmap_parallel(offset, mmap_cache) &&
+ !update_mmap_range_parallel(fd_memory, offset, mmap_cache)) {
+ ERRMSG("Can't read the dump memory(%s) with mmap().\n",
+ info->name_memory);
+
+ ERRMSG("This kernel might have some problems about mmap().\n");
+ ERRMSG("read() will be used instead of mmap() from now.\n");
+
+ /*
+ * Fall back to read().
+ */
+ pthread_rwlock_wrlock(&info->usemmap_rwlock);
+ info->flag_usemmap = MMAP_DISABLE;
+ pthread_rwlock_unlock(&info->usemmap_rwlock);
+ return NULL;
+ }
+
+ if (offset < mmap_cache->mmap_start_offset ||
+ offset + info->page_size > mmap_cache->mmap_end_offset)
+ return NULL;
+
+ return mmap_cache->mmap_buf + (offset - mmap_cache->mmap_start_offset);
+}
+
static int
read_from_vmcore(off_t offset, void *bufptr, unsigned long size)
{
diff --git a/makedumpfile.h b/makedumpfile.h
index 3d6661f..bff134e 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -42,6 +42,7 @@
#include "dwarf_info.h"
#include "diskdump_mod.h"
#include "sadump_mod.h"
+#include <pthread.h>
/*
* Result of command
@@ -956,6 +957,15 @@ typedef unsigned long int ulong;
typedef unsigned long long int ulonglong;
/*
+ * for parallel process
+ */
+struct mmap_cache {
+ char *mmap_buf;
+ off_t mmap_start_offset;
+ off_t mmap_end_offset;
+};
+
+/*
* makedumpfile header
* For re-arranging the dump data on different architecture, all the
* variables are defined by 64bits. The size of signature is aligned
@@ -1219,6 +1229,10 @@ struct DumpInfo {
* for cyclic_splitting mode, setup splitblock_size
*/
long long splitblock_size;
+ /*
+ * for parallel process
+ */
+ pthread_rwlock_t usemmap_rwlock;
};
extern struct DumpInfo *info;
--
1.8.3.1
More information about the kexec
mailing list