From 55ffa83064c77bf54ff2695ddb908656826cf6f3 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Mon, 10 Jul 2017 21:24:17 +0300 Subject: [PATCH] util: Add fd parameter to vaddr_to_pfn() Expand vaddr_to_pfn() so it can read and translate to PFN from already opened fd. This can be used as optimization if one need to translate a couple of addresses and also to read other task's PFN. I'll use it in the next patch for reading other tasks's vdso's PFN. Signed-off-by: Dmitry Safonov Signed-off-by: Andrei Vagin --- criu/include/util.h | 2 +- criu/kerndat.c | 2 +- criu/util.c | 23 +++++++++++++++++------ criu/vdso.c | 2 +- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/criu/include/util.h b/criu/include/util.h index bf466f5d6..5d471cb67 100644 --- a/criu/include/util.h +++ b/criu/include/util.h @@ -193,7 +193,7 @@ extern int read_fd_link(int lfd, char *buf, size_t size); #define USEC_PER_SEC 1000000L #define NSEC_PER_SEC 1000000000L -int vaddr_to_pfn(unsigned long vaddr, u64 *pfn); +int vaddr_to_pfn(int fd, unsigned long vaddr, u64 *pfn); /* * Check whether @str starts with @sub and report the diff --git a/criu/kerndat.c b/criu/kerndat.c index 055cc4e67..b9195176b 100644 --- a/criu/kerndat.c +++ b/criu/kerndat.c @@ -354,7 +354,7 @@ static int init_zero_page_pfn() return -1; } - ret = vaddr_to_pfn((unsigned long)addr, &kdat.zero_page_pfn); + ret = vaddr_to_pfn(-1, (unsigned long)addr, &kdat.zero_page_pfn); munmap(addr, PAGE_SIZE); if (kdat.zero_page_pfn == 0) diff --git a/criu/util.c b/criu/util.c index b681daf9b..dc11e5f9d 100644 --- a/criu/util.c +++ b/criu/util.c @@ -784,14 +784,23 @@ out: return ret; } -int vaddr_to_pfn(unsigned long vaddr, u64 *pfn) +/* + * Get PFN from pagemap file for virtual address vaddr. + * Optionally if fd >= 0, it's used as pagemap file descriptor + * (may be other task's pagemap) + */ +int vaddr_to_pfn(int fd, unsigned long vaddr, u64 *pfn) { - int fd, ret = -1; + int ret = -1; off_t off; + bool close_fd = false; - fd = open_proc(PROC_SELF, "pagemap"); - if (fd < 0) - return -1; + if (fd < 0) { + fd = open_proc(PROC_SELF, "pagemap"); + if (fd < 0) + return -1; + close_fd = true; + } off = (vaddr / page_size()) * sizeof(u64); ret = pread(fd, pfn, sizeof(*pfn), off); @@ -803,7 +812,9 @@ int vaddr_to_pfn(unsigned long vaddr, u64 *pfn) ret = 0; } - close(fd); + if (close_fd) + close(fd); + return ret; } diff --git a/criu/vdso.c b/criu/vdso.c index a0b8a4e0b..b4e6b1860 100644 --- a/criu/vdso.c +++ b/criu/vdso.c @@ -493,7 +493,7 @@ int vdso_init_dump(void) if (kdat.pmap != PM_FULL) pr_info("VDSO detection turned off\n"); - else if (vaddr_to_pfn(vdso_maps.vdso_start, &vdso_pfn)) + else if (vaddr_to_pfn(-1, vdso_maps.vdso_start, &vdso_pfn)) return -1; return 0;