[CRIU] [PATCH] pagemap: Factor out pfn retrieving for vdso and zero page

Pavel Emelyanov xemul at parallels.com
Thu Jan 30 02:44:14 PST 2014


Signed-off-by: Pavel Emelyanov <xemul at parallels.com>

---

diff --git a/arch/x86/vdso.c b/arch/x86/vdso.c
index 1beac24..f24de54 100644
--- a/arch/x86/vdso.c
+++ b/arch/x86/vdso.c
@@ -70,33 +70,10 @@ static int vdso_fill_self_symtable(struct vdso_symtable *s)
 
 int vdso_init(void)
 {
-	int ret = -1, fd;
-	off_t off;
-
 	if (vdso_fill_self_symtable(&vdso_sym_rt))
 		return -1;
 
-	fd = open_proc(getpid(), "pagemap");
-	if (fd < 0)
-		return -1;
-
-	off = (vdso_sym_rt.vma_start / PAGE_SIZE) * sizeof(u64);
-	if (lseek(fd, off, SEEK_SET) != off) {
-		pr_perror("Failed to seek address %lx\n", vdso_sym_rt.vma_start);
-		goto out;
-	}
-
-	ret = read(fd, &vdso_pfn, sizeof(vdso_pfn));
-	if (ret < 0 || ret != sizeof(vdso_pfn)) {
-		pr_perror("Can't read pme for pid %d", getpid());
-		ret = -1;
-	} else {
-		vdso_pfn = PME_PFRAME(vdso_pfn);
-		ret = 0;
-	}
-out:
-	close(fd);
-	return ret;
+	return vaddr_to_pfn(vdso_sym_rt.vma_start, &vdso_pfn);
 }
 
 /*
diff --git a/include/util.h b/include/util.h
index 6d7f5ed..890265a 100644
--- a/include/util.h
+++ b/include/util.h
@@ -289,4 +289,6 @@ 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);
+
 #endif /* __CR_UTIL_H__ */
diff --git a/kerndat.c b/kerndat.c
index 27acf0c..204f6fa 100644
--- a/kerndat.c
+++ b/kerndat.c
@@ -159,9 +159,7 @@ unsigned long zero_page_pfn;
 static int init_zero_page_pfn()
 {
 	void *addr;
-	loff_t off;
-	u64 pfn;
-	int fd = -1;
+	int ret;
 
 	addr = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 	if (addr == MAP_FAILED) {
@@ -171,37 +169,16 @@ static int init_zero_page_pfn()
 
 	if (*((int *) addr) != 0) {
 		BUG();
-		goto err;
-	}
-
-	fd = open("/proc/self/pagemap", O_RDONLY);
-	if (fd < 0) {
-		pr_perror("Unable to open /proc/self/pagemap");
-		goto err;
-	}
-
-	off = (unsigned long) addr / PAGE_SIZE * 8;
-	if (lseek(fd, off, SEEK_SET) != off) {
-		pr_perror("Can't open pagemap file");
-		goto err;
-	}
-	if (read(fd, &pfn, sizeof(pfn)) != sizeof(pfn)) {
-		pr_perror("Can't read pagemap file");
-		goto err;
+		return -1;
 	}
 
-	if (!(pfn & PME_PRESENT)) {
-		pr_err("The zero page isn't present");
-		goto err;
-	}
+	ret = vaddr_to_pfn((unsigned long)addr, &zero_page_pfn);
+	munmap(addr, PAGE_SIZE);
 
-	pfn &= PME_PFRAME_MASK;
+	if (zero_page_pfn == 0)
+		ret = -1;
 
-	zero_page_pfn = pfn;
-err:
-	munmap(addr, PAGE_SIZE);
-	close_safe(&fd);
-	return zero_page_pfn ? 0 : -1;
+	return ret;
 }
 
 int kerndat_init(void)
diff --git a/util.c b/util.c
index 7057c73..6d1e71d 100644
--- a/util.c
+++ b/util.c
@@ -581,3 +581,29 @@ int is_root_user()
 
 	return 1;
 }
+
+int vaddr_to_pfn(unsigned long vaddr, u64 *pfn)
+{
+	int fd, ret = -1;
+	off_t off;
+
+	fd = open_proc(getpid(), "pagemap");
+	if (fd < 0)
+		return -1;
+
+	off = (vaddr / PAGE_SIZE) * sizeof(u64);
+	if (lseek(fd, off, SEEK_SET) != off) {
+		pr_perror("Failed to seek address %lx\n", vaddr);
+		goto out;
+	}
+
+	ret = read(fd, pfn, sizeof(*pfn));
+	if (ret != sizeof(*pfn)) {
+		pr_perror("Can't read pme for pid %d", getpid());
+		ret = -1;
+	} else
+		ret = 0;
+out:
+	close(fd);
+	return ret;
+}


More information about the CRIU mailing list