[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