Commit 248fc315 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

restore: use breakpoints instead of tracing syscalls

Currently CRIU traces syscalls to catch a moment, when sigreturn() is
called. Now we trace recv(cmd), close(logfd), close(cmdfd), sigreturn().

We can reduce a number of steps by using hw breakpoints. A breakpoint is
set before sigreturn, so we will need to trace only it.
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 0b1b8151
...@@ -1546,7 +1546,7 @@ static int attach_to_tasks(bool root_seized) ...@@ -1546,7 +1546,7 @@ static int attach_to_tasks(bool root_seized)
for_each_pstree_item(item) { for_each_pstree_item(item) {
pid_t pid = item->pid.real; pid_t pid = item->pid.real;
int status, i; int status, i, ret;
if (!task_alive(item)) if (!task_alive(item))
continue; continue;
...@@ -1579,7 +1579,12 @@ static int attach_to_tasks(bool root_seized) ...@@ -1579,7 +1579,12 @@ static int attach_to_tasks(bool root_seized)
return -1; return -1;
} }
if (ptrace(PTRACE_SYSCALL, pid, NULL, NULL)) { ret = ptrace_set_breakpoint(pid, item->rst->breakpoint);
if (ret < 0)
return -1;
/* A breakpoint was not set */
if (ret == 0 && ptrace(PTRACE_SYSCALL, pid, NULL, NULL)) {
pr_perror("Unable to start %d", pid); pr_perror("Unable to start %d", pid);
return -1; return -1;
} }
...@@ -2691,6 +2696,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core) ...@@ -2691,6 +2696,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
if (rst_mem_remap(mem)) if (rst_mem_remap(mem))
goto err; goto err;
task_args->breakpoint = &current->rst->breakpoint;
task_args->task_entries = rst_mem_remap_ptr(task_entries_pos, RM_SHREMAP); task_args->task_entries = rst_mem_remap_ptr(task_entries_pos, RM_SHREMAP);
task_args->rst_mem = mem; task_args->rst_mem = mem;
......
...@@ -158,6 +158,7 @@ struct task_restore_args { ...@@ -158,6 +158,7 @@ struct task_restore_args {
struct vdso_symtable vdso_sym_rt; /* runtime vdso symbols */ struct vdso_symtable vdso_sym_rt; /* runtime vdso symbols */
unsigned long vdso_rt_parked_at; /* safe place to keep vdso */ unsigned long vdso_rt_parked_at; /* safe place to keep vdso */
#endif #endif
void **breakpoint;
} __aligned(64); } __aligned(64);
#define RESTORE_ALIGN_STACK(start, size) \ #define RESTORE_ALIGN_STACK(start, size) \
......
...@@ -54,6 +54,8 @@ struct rst_info { ...@@ -54,6 +54,8 @@ struct rst_info {
struct file_desc *root; struct file_desc *root;
bool has_umask; bool has_umask;
u32 umask; u32 umask;
void *breakpoint;
}; };
#endif /* __CR_RST_INFO_H__ */ #endif /* __CR_RST_INFO_H__ */
...@@ -330,6 +330,11 @@ static int restore_thread_common(struct rt_sigframe *sigframe, ...@@ -330,6 +330,11 @@ static int restore_thread_common(struct rt_sigframe *sigframe,
return 0; return 0;
} }
static void noinline rst_sigreturn(unsigned long new_sp)
{
ARCH_RT_SIGRETURN(new_sp);
}
/* /*
* Threads restoration via sigreturn. Note it's locked * Threads restoration via sigreturn. Note it's locked
* routine and calls for unlock at the end. * routine and calls for unlock at the end.
...@@ -381,7 +386,7 @@ long __export_restore_thread(struct thread_restore_args *args) ...@@ -381,7 +386,7 @@ long __export_restore_thread(struct thread_restore_args *args)
futex_dec_and_wake(&thread_inprogress); futex_dec_and_wake(&thread_inprogress);
new_sp = (long)rt_sigframe + SIGFRAME_OFFSET; new_sp = (long)rt_sigframe + SIGFRAME_OFFSET;
ARCH_RT_SIGRETURN(new_sp); rst_sigreturn(new_sp);
core_restore_end: core_restore_end:
pr_err("Restorer abnormal termination for %ld\n", sys_getpid()); pr_err("Restorer abnormal termination for %ld\n", sys_getpid());
...@@ -764,6 +769,7 @@ long __export_restore_task(struct task_restore_args *args) ...@@ -764,6 +769,7 @@ long __export_restore_task(struct task_restore_args *args)
task_entries = args->task_entries; task_entries = args->task_entries;
helpers = args->helpers; helpers = args->helpers;
n_helpers = args->n_helpers; n_helpers = args->n_helpers;
*args->breakpoint = rst_sigreturn;
ksigfillset(&act.rt_sa_mask); ksigfillset(&act.rt_sa_mask);
act.rt_sa_handler = sigchld_handler; act.rt_sa_handler = sigchld_handler;
...@@ -1130,7 +1136,7 @@ long __export_restore_task(struct task_restore_args *args) ...@@ -1130,7 +1136,7 @@ long __export_restore_task(struct task_restore_args *args)
* pure assembly since we don't need any additional * pure assembly since we don't need any additional
* code insns from gcc. * code insns from gcc.
*/ */
ARCH_RT_SIGRETURN(new_sp); rst_sigreturn(new_sp);
core_restore_end: core_restore_end:
futex_abort_and_wake(&task_entries->nr_in_progress); futex_abort_and_wake(&task_entries->nr_in_progress);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment