Conflict:NA Reference:https://gitee.com/src-openeuler/criu/pulls/26
Signed-off-by: fu.lin fulin10@huawei.com --- criu/cr-restore.c | 68 +++++++++++++++++++++++++++++++++++++++++++ criu/include/pstree.h | 1 + criu/pstree.c | 8 +++++ 3 files changed, 77 insertions(+)
diff --git a/criu/cr-restore.c b/criu/cr-restore.c index ccb2690..1c92372 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -1580,6 +1580,8 @@ static inline int fork_with_pid(struct pstree_item *item) goto err_unlock; }
+ /* disable criu rollback capability. */ + criu_roll = false;
if (item == root_item) { item->pid->real = ret; @@ -2732,6 +2734,71 @@ int prepare_dummy_task_state(struct pstree_item *pi) return 0; }
+static int criu_rollback_internal(void *_arg) +{ + bool unmask = *(int *)_arg; + pid_t pid = getpid(); + + if (unmask && mask_task_exit_notify(pid, false) != 0) + pr_err("unmask exit notify failed for %d\n", pid); + + do_notifier_rollback(true, POST_UPDATE_KERNEL_COMPLETE); + return 0; +} + +static void criu_rollback(void) +{ + pid_t pid; + unsigned long clone_flags; + int retval = 0; + + if (!criu_roll || !opts.with_notifier_kup) + return; + + pid = vpid(root_item); + clone_flags = rsti(root_item)->clone_flags; + + pr_info("do criu rollback\n"); + + /* Some rollback notifier must be call in the specific task context. */ + if (opts.use_fork_pid) + retval = write_fork_pid(vpid(root_item)); + else if (!kdat.has_clone3_set_tid) + retval = set_next_pid((void *)&pid); + + if (retval < 0) { + pr_err("set next pid %d failed, can't do rollback.", pid); + return; + } + + if (!kdat.has_clone3_set_tid) { + retval = clone_noasan(criu_rollback_internal, + clone_flags | SIGCHLD, + &opts.mask_exit_notify); + } else { + retval = clone3_with_pid_noasan(criu_rollback_internal, + &opts.mask_exit_notify, + clone_flags, + SIGCHLD, pid); + } + + if (retval < 0) { + pr_err("Can't fork for %d to do rollback: %s.\n", + pid, strerror(errno)); + } else { + int status; + + if (retval != pid) + pr_err("clone pid %d isn't equal with %d\n", + retval, pid); + + if (waitpid(pid, &status, 0) < 0) { + pr_warn("Unable to wait %d: %s\n", + pid, strerror(errno)); + } + } +} + int cr_restore_tasks(void) { int ret = -1; @@ -2801,6 +2868,7 @@ int cr_restore_tasks(void) err: cr_plugin_fini(CR_PLUGIN_STAGE__RESTORE, ret); if (ret < 0) { + criu_rollback(); if ((network_status & NETWORK_COLLECTED) == 0) { if (!files_collected() && collect_image(&inet_sk_cinfo)) pr_err("collect inet sk cinfo fail"); diff --git a/criu/include/pstree.h b/criu/include/pstree.h index be0942a..d59562c 100644 --- a/criu/include/pstree.h +++ b/criu/include/pstree.h @@ -45,6 +45,7 @@ enum { }; #define FDS_EVENT (1 << FDS_EVENT_BIT)
+extern bool criu_roll; extern struct pstree_item *current;
struct rst_info; diff --git a/criu/pstree.c b/criu/pstree.c index f0d7622..3d17056 100644 --- a/criu/pstree.c +++ b/criu/pstree.c @@ -20,6 +20,11 @@ #include "images/pstree.pb-c.h" #include "crtools.h"
+/* + * Sometimes, img may be broken, set flag here to enable roll capibility + * before forking restorer. + */ +bool criu_roll; struct pstree_item *root_item; static struct rb_root pid_root_rb;
@@ -619,6 +624,9 @@ static int read_pstree_image(pid_t *pid_max) if (!img) return -1;
+ /* enable rollback capibility when opening img successfully. */ + criu_roll = true; + do { ret = read_one_pstree_item(img, pid_max); } while (ret > 0);