From: Jingxian He hejingxian@huawei.com
The default pid recover method cannot recover the task pid at every time. We add a new pid recover method by setting the fork_pid of the parent task struct, add the kernel will alloc pid by the fork_pid. The new pid recover method can also avoid other tasks using the dumping task pids.
Conflict:NA Reference:https://gitee.com/src-openeuler/criu/pulls/21 Signed-off-by: Jingxian He hejingxian@huawei.com --- criu/config.c | 1 + criu/cr-restore.c | 25 ++++++++++++++++++++++++- criu/crtools.c | 1 + criu/include/cr_options.h | 1 + criu/include/restorer.h | 3 +++ criu/pie/restorer.c | 25 ++++++++++++++++++++++++- 6 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/criu/config.c b/criu/config.c index 61b81fa..a5bcf10 100644 --- a/criu/config.c +++ b/criu/config.c @@ -543,6 +543,7 @@ int parse_options(int argc, char **argv, bool *usage_error, { "file-validation", required_argument, 0, 1098 }, BOOL_OPT("with-cpu-affinity", &opts.with_cpu_affinity), BOOL_OPT("pin-memory", &opts.pin_memory), + BOOL_OPT("use-fork-pid", &opts.use_fork_pid), { }, };
diff --git a/criu/cr-restore.c b/criu/cr-restore.c index 27f3c54..e050b88 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -1365,6 +1365,23 @@ static int set_next_pid(void *arg) return 0; }
+static int write_fork_pid(int pid) +{ + int fd, ret; + + fd = open(PIN_MEM_FILE, O_RDWR); + if (fd < 0) { + pr_warn("error open file: %s\n", PIN_MEM_FILE); + return -1; + } + ret = ioctl(fd, SET_FORK_PID, &pid); + if (ret < 0) { + pr_warn("write fork pid fail, errno: %s\n", strerror(errno)); + } + close(fd); + return ret; +} + static inline int fork_with_pid(struct pstree_item *item) { unsigned long clone_flags; @@ -1462,7 +1479,7 @@ static inline int fork_with_pid(struct pstree_item *item) if (!(clone_flags & CLONE_NEWPID)) { lock_last_pid();
- if (!kdat.has_clone3_set_tid) { + if (!kdat.has_clone3_set_tid && !opts.use_fork_pid) { if (pid_ns && pid_ns->ext_key) { /* * Restoring into another namespace requires a helper @@ -1495,6 +1512,11 @@ static inline int fork_with_pid(struct pstree_item *item) ~(CLONE_NEWNET | CLONE_NEWCGROUP | CLONE_NEWTIME)), SIGCHLD, pid); } else { + if (opts.use_fork_pid) { + ret = write_fork_pid(pid); + if (ret < 0) + goto err_unlock; + } /* * Some kernel modules, such as network packet generator * run kernel thread upon net-namespace creation taking @@ -3873,6 +3895,7 @@ static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns task_args->pin_memory = true; else task_args->pin_memory = false; + task_args->use_fork_pid = opts.use_fork_pid ? true : false;
/* * An indirect call to task_restore, note it never returns diff --git a/criu/crtools.c b/criu/crtools.c index 7bda86d..9b3ef33 100644 --- a/criu/crtools.c +++ b/criu/crtools.c @@ -444,6 +444,7 @@ usage: " --with-cpu-affinity Allow to restore cpu affinity. Only for hosts with\n" " same cpu quantity.\n" " --pin-memory Use pin memory method for checkpoint and restore.\n" +" --use-fork-pid Allow to restore task pid by setting fork pid of task struct.\n" "\n" "Check options:\n" " Without options, "criu check" checks availability of absolutely required\n" diff --git a/criu/include/cr_options.h b/criu/include/cr_options.h index a4dc5b8..7fad678 100644 --- a/criu/include/cr_options.h +++ b/criu/include/cr_options.h @@ -177,6 +177,7 @@ struct cr_options { /* restore cpu affinity */ int with_cpu_affinity; int pin_memory; + int use_fork_pid; };
extern struct cr_options opts; diff --git a/criu/include/restorer.h b/criu/include/restorer.h index 9614720..8fd47e2 100644 --- a/criu/include/restorer.h +++ b/criu/include/restorer.h @@ -226,6 +226,7 @@ struct task_restore_args { int child_subreaper; bool has_clone3_set_tid; bool pin_memory; + bool use_fork_pid; } __aligned(64);
/* @@ -325,11 +326,13 @@ enum { #define _REMAP_PIN_MEM_AREA 3 #define _DUMP_SEPCIAL_PAGES 6 #define _RETORE_SEPCIAL_PAGES 7 +#define _SET_FORK_PID 8 #define SET_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _SET_PIN_MEM_AREA, struct pin_mem_area_set) #define CLEAR_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _CLEAR_PIN_MEM_AREA, int) #define REMAP_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _REMAP_PIN_MEM_AREA, int) #define DUMP_SEPCIAL_PAGES _IOW(PIN_MEM_MAGIC, _DUMP_SEPCIAL_PAGES, int) #define RETORE_SEPCIAL_PAGES _IOW(PIN_MEM_MAGIC, _RETORE_SEPCIAL_PAGES, int) +#define SET_FORK_PID _IOW(PIN_MEM_MAGIC, _SET_FORK_PID, int)
#define ONCE_PIN_MEM_SIZE_LIMIT 32 * 1024 * 1024 #define MAX_PIN_MEM_AREA_NUM 16 diff --git a/criu/pie/restorer.c b/criu/pie/restorer.c index 1565e3c..4ab8a45 100644 --- a/criu/pie/restorer.c +++ b/criu/pie/restorer.c @@ -1431,6 +1431,22 @@ int remap_vmas(int pid) return ret; }
+int write_fork_pid(int pid) +{ + int fd, ret; + + fd = sys_open(PIN_MEM_FILE, O_RDWR, 0); + if (fd < 0) { + pr_warn("error open file: %s\n", PIN_MEM_FILE); + return -1; + } + ret = sys_ioctl(fd, SET_FORK_PID, (unsigned long) &pid); + if (ret < 0) { + pr_warn("write fork pid fail fail: %d\n", pid); + } + sys_close(fd); + return ret; +}
/* * The main routine to restore task via sigreturn. @@ -1834,7 +1850,7 @@ long __export_restore_task(struct task_restore_args *args) long parent_tid; int i, fd = -1;
- if (!args->has_clone3_set_tid) { + if (!args->has_clone3_set_tid && !args->use_fork_pid) { /* One level pid ns hierarhy */ fd = sys_openat(args->proc_fd, LAST_PID_PATH, O_RDWR, 0); if (fd < 0) { @@ -1866,6 +1882,13 @@ long __export_restore_task(struct task_restore_args *args) c_args.parent_tid = ptr_to_u64(&parent_tid); pr_debug("Using clone3 to restore the process\n"); RUN_CLONE3_RESTORE_FN(ret, c_args, sizeof(c_args), &thread_args[i], args->clone_restore_fn); + } else if (args->use_fork_pid) { + if (write_fork_pid(thread_args[i].pid) < 0) { + pr_err("Clone fail with fork pid\n"); + mutex_unlock(&task_entries_local->last_pid_mutex); + goto core_restore_end; + } + RUN_CLONE_RESTORE_FN(ret, clone_flags, new_sp, parent_tid, thread_args, args->clone_restore_fn); } else { last_pid_len = std_vprint_num(last_pid_buf, sizeof(last_pid_buf), thread_args[i].pid - 1, &s); sys_lseek(fd, 0, SEEK_SET);