[CRIU] [PATCH 09/11] vdso: Don't parse self-maps if kdat.can_map_vdso

Dmitry Safonov dsafonov at virtuozzo.com
Mon Jul 17 15:40:00 MSK 2017


Just map vdso at restorer's parking zone, no need for
searching it in CRIU and remap it to park zone.
That will save some open()/read()/close() syscalls
for parsing maps file.

Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
 criu/arch/aarch64/include/asm/restorer.h |  1 +
 criu/arch/arm/include/asm/restorer.h     |  1 +
 criu/arch/ppc64/include/asm/restorer.h   |  1 +
 criu/arch/x86/include/asm/restorer.h     |  5 +++++
 criu/arch/x86/restorer.c                 | 10 ++++++++++
 criu/cr-restore.c                        |  1 +
 criu/include/restorer.h                  |  1 +
 criu/pie/parasite-vdso.c                 | 19 +------------------
 criu/pie/restorer.c                      | 11 ++++++++---
 criu/vdso.c                              | 22 +++++++++++++++-------
 10 files changed, 44 insertions(+), 28 deletions(-)

diff --git a/criu/arch/aarch64/include/asm/restorer.h b/criu/arch/aarch64/include/asm/restorer.h
index 000d3f8bab61..bef85f3a3210 100644
--- a/criu/arch/aarch64/include/asm/restorer.h
+++ b/criu/arch/aarch64/include/asm/restorer.h
@@ -54,6 +54,7 @@
 
 #define kdat_compatible_cr()			0
 #define kdat_can_map_vdso()			0
+#define arch_map_vdso(map, compat)		-1
 
 int restore_gpregs(struct rt_sigframe *f, UserAarch64RegsEntry *r);
 int restore_nonsigframe_gpregs(UserAarch64RegsEntry *r);
diff --git a/criu/arch/arm/include/asm/restorer.h b/criu/arch/arm/include/asm/restorer.h
index 3da166a44d54..d9208185f731 100644
--- a/criu/arch/arm/include/asm/restorer.h
+++ b/criu/arch/arm/include/asm/restorer.h
@@ -55,6 +55,7 @@
 
 #define kdat_compatible_cr()			0
 #define kdat_can_map_vdso()			0
+#define arch_map_vdso(map, compat)		-1
 
 int restore_gpregs(struct rt_sigframe *f, UserArmRegsEntry *r);
 int restore_nonsigframe_gpregs(UserArmRegsEntry *r);
diff --git a/criu/arch/ppc64/include/asm/restorer.h b/criu/arch/ppc64/include/asm/restorer.h
index ad9c39a7886b..3fffa833c157 100644
--- a/criu/arch/ppc64/include/asm/restorer.h
+++ b/criu/arch/ppc64/include/asm/restorer.h
@@ -50,6 +50,7 @@
 
 #define kdat_compatible_cr()			0
 #define kdat_can_map_vdso()			0
+#define arch_map_vdso(map, compat)		-1
 
 int restore_gpregs(struct rt_sigframe *f, UserPpc64RegsEntry *r);
 int restore_nonsigframe_gpregs(UserPpc64RegsEntry *r);
diff --git a/criu/arch/x86/include/asm/restorer.h b/criu/arch/x86/include/asm/restorer.h
index 04509ff2fefe..e39675d957d1 100644
--- a/criu/arch/x86/include/asm/restorer.h
+++ b/criu/arch/x86/include/asm/restorer.h
@@ -76,6 +76,10 @@ static inline int set_compat_robust_list(uint32_t head_ptr, uint32_t len)
 # define ARCH_MAP_VDSO_32		0x2002
 #endif
 
+#ifndef ARCH_MAP_VDSO_64
+# define ARCH_MAP_VDSO_64		0x2003
+#endif
+
 extern int kdat_compatible_cr(void);
 extern int kdat_can_map_vdso(void);
 
@@ -114,5 +118,6 @@ int restore_nonsigframe_gpregs(UserX86RegsEntry *r);
 int ptrace_set_breakpoint(pid_t pid, void *addr);
 int ptrace_flush_breakpoints(pid_t pid);
 
+extern int arch_map_vdso(unsigned long map_at, bool compatible);
 
 #endif
diff --git a/criu/arch/x86/restorer.c b/criu/arch/x86/restorer.c
index d6da030b24c6..2d335d5e1d29 100644
--- a/criu/arch/x86/restorer.c
+++ b/criu/arch/x86/restorer.c
@@ -13,6 +13,16 @@
 #include "log.h"
 #include "cpu.h"
 
+int arch_map_vdso(unsigned long map_at, bool compatible)
+{
+	int vdso_type = compatible ? ARCH_MAP_VDSO_32 : ARCH_MAP_VDSO_64;
+
+	pr_debug("Mapping %s vDSO at %lx\n",
+		compatible ? "compatible" : "native", map_at);
+
+	return sys_arch_prctl(vdso_type, map_at);
+}
+
 int restore_nonsigframe_gpregs(UserX86RegsEntry *r)
 {
 	long ret;
diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index e14fa0694a98..e81f7cb91494 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -3624,6 +3624,7 @@ static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
 	task_args->vdso_rt_parked_at = (unsigned long)mem;
 	task_args->vdso_maps_rt = vdso_maps_rt;
 	task_args->vdso_rt_size = vdso_rt_size;
+	task_args->can_map_vdso = kdat.can_map_vdso;
 #endif
 
 	new_sp = restorer_stack(task_args->t->mz);
diff --git a/criu/include/restorer.h b/criu/include/restorer.h
index ac0b4e1f4d18..4d3b3cf9147a 100644
--- a/criu/include/restorer.h
+++ b/criu/include/restorer.h
@@ -198,6 +198,7 @@ struct task_restore_args {
 
 	bool				check_only;
 
+	bool				can_map_vdso;
 #ifdef CONFIG_VDSO
 	unsigned long			vdso_rt_size;
 	struct vdso_maps		vdso_maps_rt;		/* runtime vdso symbols */
diff --git a/criu/pie/parasite-vdso.c b/criu/pie/parasite-vdso.c
index a31363352385..8072c11f7c78 100644
--- a/criu/pie/parasite-vdso.c
+++ b/criu/pie/parasite-vdso.c
@@ -74,19 +74,8 @@ int vdso_do_park(struct vdso_maps *rt, unsigned long park_at,
 	return ret;
 }
 
+/* XXX: move in arch/ */
 #if defined(CONFIG_X86_64) && defined(CONFIG_COMPAT)
-int vdso_map_compat(unsigned long map_at)
-{
-	int ret;
-
-	pr_debug("Mapping compatible vDSO at %lx\n", map_at);
-
-	ret = sys_arch_prctl(ARCH_MAP_VDSO_32, map_at);
-	if (ret < 0)
-		return ret;
-	return 0;
-}
-
 int __vdso_fill_symtable(uintptr_t mem, size_t size,
 		struct vdso_symtable *t, bool compat_vdso)
 {
@@ -96,12 +85,6 @@ int __vdso_fill_symtable(uintptr_t mem, size_t size,
 		return vdso_fill_symtable(mem, size, t);
 }
 #else
-int vdso_map_compat(unsigned long __always_unused map_at)
-{
-	/* shouldn't be called on !CONFIG_COMPAT */
-	BUG();
-	return 0;
-}
 int __vdso_fill_symtable(uintptr_t mem, size_t size,
 		struct vdso_symtable *t, bool __always_unused compat_vdso)
 {
diff --git a/criu/pie/restorer.c b/criu/pie/restorer.c
index b30e8ad5a2a7..cadfda07731b 100644
--- a/criu/pie/restorer.c
+++ b/criu/pie/restorer.c
@@ -1187,6 +1187,9 @@ static bool vdso_needs_parking(struct task_restore_args *args)
 	if (args->compatible_mode)
 		return false;
 
+	if (args->can_map_vdso)
+		return false;
+
 	return !vdso_unmapped(args);
 }
 
@@ -1257,10 +1260,12 @@ long __export_restore_task(struct task_restore_args *args)
 				bootstrap_start, bootstrap_len, args->task_size))
 		goto core_restore_end;
 
-	/* Map compatible vdso */
-	if (!vdso_unmapped(args) && args->compatible_mode) {
-		if (vdso_map_compat(args->vdso_rt_parked_at))
+	/* Map vdso that wasn't parked */
+	if (!vdso_unmapped(args) && args->can_map_vdso) {
+		if (arch_map_vdso(args->vdso_rt_parked_at,
+				args->compatible_mode) < 0) {
 			goto core_restore_end;
+		}
 	}
 
 	/* Shift private vma-s to the left */
diff --git a/criu/vdso.c b/criu/vdso.c
index ce62996fb994..64046bc169d9 100644
--- a/criu/vdso.c
+++ b/criu/vdso.c
@@ -572,14 +572,22 @@ int vdso_init_restore(void)
 	if (vdso_maps.vdso_start != VDSO_BAD_ADDR)
 		return 0;
 
-	if (vdso_parse_maps(PROC_SELF, &vdso_maps)) {
-		pr_err("Failed reading self/maps for filling vdso/vvar bounds\n");
-		return -1;
-	}
+	/*
+	 * Parsing self-maps here only to find vvar/vdso vmas in
+	 * criu's address space, for further remapping to restorer's
+	 * parking zone. Don't need to do this if map-vdso API
+	 * is present.
+	 */
+	if (!kdat.can_map_vdso) {
+		if (vdso_parse_maps(PROC_SELF, &vdso_maps)) {
+			pr_err("Failed reading self/maps for filling vdso/vvar bounds\n");
+			return -1;
+		}
 
-	if (!is_kdat_vdso_sym_valid()) {
-		pr_err("Kdat sizes of vdso/vvar differ to maps file \n");
-		return -1;
+		if (!is_kdat_vdso_sym_valid()) {
+			pr_err("Kdat sizes of vdso/vvar differ to maps file \n");
+			return -1;
+		}
 	}
 
 	vdso_maps.sym = kdat.vdso_sym;
-- 
2.13.1



More information about the CRIU mailing list