622 lines
18 KiB
Diff
622 lines
18 KiB
Diff
From 33c351e18eddc2517f799c1cac20790ebabddbc8 Mon Sep 17 00:00:00 2001
|
|
From: Jingxian He <hejingxian@huawei.com>
|
|
Date: Wed, 19 May 2021 21:45:03 +0800
|
|
Subject: [PATCH 22/72] notifier: add notifier calling method for checkpoint
|
|
and restore
|
|
|
|
Add notifier calling method for checkpoint and restore during kernel module upgrading.
|
|
|
|
Signed-off-by: Xiaoguang Li <lixiaoguang2@huawei.com>
|
|
Signed-off-by: He Jingxian <hejingxian@huawei.com>
|
|
Signed-off-by: fu.lin <fu.lin10@huawei.com>
|
|
---
|
|
criu/config.c | 1 +
|
|
criu/cr-dump.c | 34 +++++++++++
|
|
criu/cr-restore.c | 18 +++++-
|
|
criu/crtools.c | 2 +
|
|
criu/include/cr_options.h | 1 +
|
|
criu/include/notifier.h | 44 +++++++++++++++
|
|
criu/include/restorer.h | 1 +
|
|
criu/include/util.h | 2 +
|
|
criu/pie/restorer.c | 116 ++++++++++++++++++++++++++++++++++----
|
|
criu/pie/util.c | 91 ++++++++++++++++++++++++++++++
|
|
10 files changed, 297 insertions(+), 13 deletions(-)
|
|
create mode 100644 criu/include/notifier.h
|
|
|
|
diff --git a/criu/config.c b/criu/config.c
|
|
index 6dfbb01..5d1cff6 100644
|
|
--- a/criu/config.c
|
|
+++ b/criu/config.c
|
|
@@ -700,6 +700,7 @@ int parse_options(int argc, char **argv, bool *usage_error, bool *has_exec_cmd,
|
|
{ "lsm-mount-context", required_argument, 0, 1099 },
|
|
{ "network-lock", required_argument, 0, 1100 },
|
|
BOOL_OPT("use-fork-pid", &opts.use_fork_pid),
|
|
+ BOOL_OPT("with-notifier", &opts.with_notifier_kup),
|
|
{},
|
|
};
|
|
|
|
diff --git a/criu/cr-dump.c b/criu/cr-dump.c
|
|
index 5fac9ce..50a2f9b 100644
|
|
--- a/criu/cr-dump.c
|
|
+++ b/criu/cr-dump.c
|
|
@@ -87,6 +87,7 @@
|
|
#include "apparmor.h"
|
|
#include "asm/dump.h"
|
|
#include "pin-mem.h"
|
|
+#include "notifier.h"
|
|
|
|
/*
|
|
* Architectures can overwrite this function to restore register sets that
|
|
@@ -1981,6 +1982,8 @@ static int cr_lazy_mem_dump(void)
|
|
return ret;
|
|
}
|
|
|
|
+static enum notifier_state notifier_state = NOTHING_COMPLETE;
|
|
+
|
|
static int cr_dump_finish(int ret)
|
|
{
|
|
int post_dump_ret = 0;
|
|
@@ -2067,6 +2070,20 @@ static int cr_dump_finish(int ret)
|
|
clear_pin_mem(0);
|
|
}
|
|
|
|
+ if (ret != 0 && opts.with_notifier_kup) {
|
|
+ pr_info("call notifier rollback\n");
|
|
+ switch (notifier_state) {
|
|
+ case PRE_FREEZE_COMPLETE:
|
|
+ notifier_kup(PRE_FREEZE, ROLLBACK, true);
|
|
+ break;
|
|
+ case FREEZE_TO_KILL_COMPLETE:
|
|
+ notifier_kup(FREEZE_TO_KILL, ROLLBACK, true);
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
if (ret) {
|
|
pr_err("Dumping FAILED.\n");
|
|
} else {
|
|
@@ -2100,6 +2117,14 @@ int cr_dump_tasks(pid_t pid)
|
|
goto err;
|
|
root_item->pid->real = pid;
|
|
|
|
+ if (notifier_kup(PRE_FREEZE, PREPARE, opts.with_notifier_kup)) {
|
|
+ /* disable rollback function because we has already rollbacked. */
|
|
+ opts.with_notifier_kup = false;
|
|
+ pr_err("call notifier: %d err\n", PRE_FREEZE);
|
|
+ goto err;
|
|
+ } else
|
|
+ notifier_state = PRE_FREEZE_COMPLETE;
|
|
+
|
|
pre_dump_ret = run_scripts(ACT_PRE_DUMP);
|
|
if (pre_dump_ret != 0) {
|
|
pr_err("Pre dump script failed with %d!\n", pre_dump_ret);
|
|
@@ -2258,6 +2283,15 @@ int cr_dump_tasks(pid_t pid)
|
|
ret = write_img_inventory(&he);
|
|
if (ret)
|
|
goto err;
|
|
+
|
|
+ ret = notifier_kup(FREEZE_TO_KILL, PREPARE, opts.with_notifier_kup);
|
|
+ if (ret) {
|
|
+ opts.with_notifier_kup = false;
|
|
+ pr_err("call notifier:%d err\n", FREEZE_TO_KILL);
|
|
+ goto err;
|
|
+ } else
|
|
+ notifier_state = FREEZE_TO_KILL_COMPLETE;
|
|
+
|
|
err:
|
|
if (parent_ie)
|
|
inventory_entry__free_unpacked(parent_ie, NULL);
|
|
diff --git a/criu/cr-restore.c b/criu/cr-restore.c
|
|
index 497dd14..03511b6 100644
|
|
--- a/criu/cr-restore.c
|
|
+++ b/criu/cr-restore.c
|
|
@@ -81,6 +81,7 @@
|
|
#include "bpfmap.h"
|
|
#include "apparmor.h"
|
|
#include "pin-mem.h"
|
|
+#include "notifier.h"
|
|
|
|
#include "parasite-syscall.h"
|
|
#include "files-reg.h"
|
|
@@ -1951,6 +1952,7 @@ static int restore_task_with_children(void *_arg)
|
|
return 0;
|
|
|
|
err:
|
|
+ do_notifier_rollback(opts.with_notifier_kup, POST_UPDATE_KERNEL_COMPLETE);
|
|
if (current->parent == NULL)
|
|
futex_abort_and_wake(&task_entries->nr_in_progress);
|
|
exit(1);
|
|
@@ -2451,8 +2453,10 @@ skip_ns_bouncing:
|
|
*/
|
|
attach_to_tasks(root_seized);
|
|
|
|
- if (restore_switch_stage(CR_STATE_RESTORE_CREDS))
|
|
+ if (restore_switch_stage(CR_STATE_RESTORE_CREDS)) {
|
|
+ pr_err("Can't switch to CR_STATE_RESTORE_CREDS stage\n");
|
|
goto out_kill_network_unlocked;
|
|
+ }
|
|
|
|
timing_stop(TIME_RESTORE);
|
|
|
|
@@ -2631,6 +2635,15 @@ int cr_restore_tasks(void)
|
|
goto clean_cgroup;
|
|
|
|
ret = restore_root_task(root_item);
|
|
+ if (ret)
|
|
+ goto err;
|
|
+
|
|
+ ret = notifier_kup(POST_RUN, PREPARE, opts.with_notifier_kup);
|
|
+ if (ret < 0) {
|
|
+ opts.with_notifier_kup = false;
|
|
+ pr_err("calling POST_RUN notifier list return err\n");
|
|
+ }
|
|
+
|
|
clean_cgroup:
|
|
fini_cgroup();
|
|
err:
|
|
@@ -3922,6 +3935,9 @@ static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
|
|
err:
|
|
free_mappings(&self_vmas);
|
|
err_nv:
|
|
+ if (current->parent == NULL && opts.with_notifier_kup)
|
|
+ do_notifier_rollback(true, POST_UPDATE_KERNEL_COMPLETE);
|
|
+
|
|
/* Just to be sure */
|
|
exit(1);
|
|
return -1;
|
|
diff --git a/criu/crtools.c b/criu/crtools.c
|
|
index 502acdf..1d08620 100644
|
|
--- a/criu/crtools.c
|
|
+++ b/criu/crtools.c
|
|
@@ -449,6 +449,8 @@ usage:
|
|
" 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"
|
|
+ " --with-notifier Allow to checkpoint/restore kup notifier chain.\n"
|
|
+ " This feature needs the kernel assistance.\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 923cc5f..039edba 100644
|
|
--- a/criu/include/cr_options.h
|
|
+++ b/criu/include/cr_options.h
|
|
@@ -192,6 +192,7 @@ struct cr_options {
|
|
int with_cpu_affinity;
|
|
int pin_memory;
|
|
int use_fork_pid;
|
|
+ int with_notifier_kup;
|
|
};
|
|
|
|
extern struct cr_options opts;
|
|
diff --git a/criu/include/notifier.h b/criu/include/notifier.h
|
|
new file mode 100644
|
|
index 0000000..e4972a7
|
|
--- /dev/null
|
|
+++ b/criu/include/notifier.h
|
|
@@ -0,0 +1,44 @@
|
|
+#ifndef __CRIU_NOTIFIER_H__
|
|
+#define __CRIU_NOTIFIER_H__
|
|
+
|
|
+#define NOTIFY_PROC_PATH "/sys/kernel/modrestore/nvwa_notifier"
|
|
+
|
|
+#if __has_include("linux/modrestore.h")
|
|
+# define CONFIG_EULEROS_MODRESTORE_NOTIFY /* useless, historical factors */
|
|
+# include <linux/modrestore.h>
|
|
+#else
|
|
+enum KUP_HOOK_POINT {
|
|
+ PRE_FREEZE,
|
|
+ FREEZE_TO_KILL,
|
|
+ PRE_UPDATE_KERNEL,
|
|
+ POST_UPDATE_KERNEL,
|
|
+ UNFREEZE_TO_RUN,
|
|
+ POST_RUN,
|
|
+
|
|
+ KUP_HOOK_MAX,
|
|
+};
|
|
+
|
|
+enum nvwa_cmd {
|
|
+ PREPARE = 0,
|
|
+ ROLLBACK,
|
|
+
|
|
+ NVWA_CMD_MAX,
|
|
+};
|
|
+#endif
|
|
+
|
|
+enum notifier_state {
|
|
+ NOTHING_COMPLETE,
|
|
+ PRE_FREEZE_COMPLETE,
|
|
+ FREEZE_TO_KILL_COMPLETE,
|
|
+ PRE_UPDATE_KERNEL_COMPLETE,
|
|
+ POST_UPDATE_KERNEL_COMPLETE,
|
|
+ UNFREEZE_TO_RUN_COMPLETE,
|
|
+ POST_RUN_COMPLETE,
|
|
+
|
|
+ NOTIFIER_ROLLBACK_DONE = 0xfc17173b, /* has done rollback */
|
|
+};
|
|
+
|
|
+int notifier_kup(enum KUP_HOOK_POINT, enum nvwa_cmd, bool);
|
|
+void do_notifier_rollback(bool, enum notifier_state);
|
|
+
|
|
+#endif /* __CRIU_NOTIFIER_H__ */
|
|
diff --git a/criu/include/restorer.h b/criu/include/restorer.h
|
|
index 93f87f4..2f7345b 100644
|
|
--- a/criu/include/restorer.h
|
|
+++ b/criu/include/restorer.h
|
|
@@ -234,6 +234,7 @@ struct task_restore_args {
|
|
bool has_clone3_set_tid;
|
|
bool pin_memory;
|
|
bool use_fork_pid;
|
|
+ bool with_notifier_kup;
|
|
} __aligned(64);
|
|
|
|
/*
|
|
diff --git a/criu/include/util.h b/criu/include/util.h
|
|
index 1c0b3c7..e0049a6 100644
|
|
--- a/criu/include/util.h
|
|
+++ b/criu/include/util.h
|
|
@@ -13,6 +13,8 @@
|
|
#include <sys/sysmacros.h>
|
|
#include <dirent.h>
|
|
#include <poll.h>
|
|
+#include <sys/stat.h>
|
|
+#include <fcntl.h>
|
|
|
|
#include "int.h"
|
|
#include "common/compiler.h"
|
|
diff --git a/criu/pie/restorer.c b/criu/pie/restorer.c
|
|
index 1317582..4a1d38d 100644
|
|
--- a/criu/pie/restorer.c
|
|
+++ b/criu/pie/restorer.c
|
|
@@ -36,6 +36,7 @@
|
|
#include "vma.h"
|
|
#include "uffd.h"
|
|
#include "sched.h"
|
|
+#include "notifier.h"
|
|
|
|
#include "common/lock.h"
|
|
#include "common/page.h"
|
|
@@ -77,6 +78,7 @@
|
|
|
|
static struct task_entries *task_entries_local;
|
|
static futex_t thread_inprogress;
|
|
+static futex_t thread_start;
|
|
static pid_t *helpers;
|
|
static int n_helpers;
|
|
static pid_t *zombies;
|
|
@@ -118,10 +120,28 @@ void parasite_cleanup(void)
|
|
|
|
extern void cr_restore_rt(void) asm("__cr_restore_rt") __attribute__((visibility("hidden")));
|
|
|
|
+static int args_with_notifier_kup;
|
|
+static enum notifier_state notifier_state = POST_UPDATE_KERNEL_COMPLETE;
|
|
+static futex_t notifier_done;
|
|
+
|
|
static void sigchld_handler(int signal, siginfo_t *siginfo, void *data)
|
|
{
|
|
char *r;
|
|
int i;
|
|
+ rt_sigaction_t act;
|
|
+
|
|
+ if (signal == SIGSEGV || signal == SIGBUS || signal == SIGILL) {
|
|
+ /* Make sure we exit with the right signal at the end. So for instance
|
|
+ * the core will be dumped if enabled. */
|
|
+ pr_info("recv signal: %d\n", signal);
|
|
+ do_notifier_rollback(args_with_notifier_kup, notifier_state);
|
|
+ ksigemptyset (&act.rt_sa_mask);
|
|
+ act.rt_sa_flags = SA_SIGINFO | SA_RESTART;
|
|
+ act.rt_sa_handler = (rt_sighandler_t)SIG_DFL;
|
|
+ sys_sigaction(signal, &act, NULL, sizeof(k_rtsigset_t));
|
|
+ sys_kill(sys_getpid(),signal);
|
|
+ return;
|
|
+ }
|
|
|
|
/* We can ignore helpers that die, we expect them to after
|
|
* CR_STATE_RESTORE is finished. */
|
|
@@ -148,10 +168,14 @@ static void sigchld_handler(int signal, siginfo_t *siginfo, void *data)
|
|
|
|
pr_info("Task %d %s %d\n", siginfo->si_pid, r, siginfo->si_status);
|
|
|
|
+ pr_info("%s: trace do_notifier_rollback\n", __func__);
|
|
+ do_notifier_rollback(args_with_notifier_kup, notifier_state);
|
|
futex_abort_and_wake(&task_entries_local->nr_in_progress);
|
|
/* sa_restorer may be unmaped, so we can't go back to userspace*/
|
|
sys_kill(sys_getpid(), SIGSTOP);
|
|
sys_exit_group(1);
|
|
+
|
|
+ /* for notifier, do nothing when receiving SIGCHLD signal */
|
|
}
|
|
|
|
static int lsm_set_label(char *label, char *type, int procfd)
|
|
@@ -616,6 +640,27 @@ static void noinline rst_sigreturn(unsigned long new_sp, struct rt_sigframe *sig
|
|
ARCH_RT_SIGRETURN(new_sp, sigframe);
|
|
}
|
|
|
|
+/* Notice: only one task, so it isn't necessary to consider concurrent. */
|
|
+static int do_notifier(bool *notify)
|
|
+{
|
|
+ int retval = 0;
|
|
+
|
|
+ if (!*notify)
|
|
+ return 0;
|
|
+
|
|
+ pr_info("unfreeze_to_run restore notifier\n");
|
|
+ retval = notifier_kup(UNFREEZE_TO_RUN, PREPARE, true);
|
|
+ if (retval) {
|
|
+ *notify = false;
|
|
+ notifier_state = NOTIFIER_ROLLBACK_DONE;
|
|
+ pr_err("call notifier: %d err\n", UNFREEZE_TO_RUN);
|
|
+ }
|
|
+
|
|
+ notifier_state = UNFREEZE_TO_RUN_COMPLETE;
|
|
+
|
|
+ return retval;
|
|
+}
|
|
+
|
|
/*
|
|
* Threads restoration via sigreturn. Note it's locked
|
|
* routine and calls for unlock at the end.
|
|
@@ -654,12 +699,18 @@ long __export_restore_thread(struct thread_restore_args *args)
|
|
|
|
pr_info("%ld: Restored\n", sys_gettid());
|
|
|
|
- restore_finish_stage(task_entries_local, CR_STATE_RESTORE);
|
|
+ if (!!(restore_finish_stage(task_entries_local, CR_STATE_RESTORE) & FUTEX_ABORT_FLAG)) {
|
|
+ pr_err("%s: abort by CR_STATE_RESTORE\n", __func__);
|
|
+ goto core_restore_end;
|
|
+ }
|
|
|
|
if (restore_signals(args->siginfo, args->siginfo_n, false))
|
|
goto core_restore_end;
|
|
|
|
- restore_finish_stage(task_entries_local, CR_STATE_RESTORE_SIGCHLD);
|
|
+ if (!!(restore_finish_stage(task_entries_local, CR_STATE_RESTORE_SIGCHLD) & FUTEX_ABORT_FLAG)) {
|
|
+ pr_err("%s: abort by CR_STATE_RESTORE_SIGCHLD\n", __func__);
|
|
+ goto core_restore_end;
|
|
+ }
|
|
|
|
/*
|
|
* Make sure it's before creds, since it's privileged
|
|
@@ -674,16 +725,29 @@ long __export_restore_thread(struct thread_restore_args *args)
|
|
if (ret)
|
|
BUG();
|
|
|
|
- restore_finish_stage(task_entries_local, CR_STATE_RESTORE_CREDS);
|
|
+ if (!!(restore_finish_stage(task_entries_local, CR_STATE_RESTORE_CREDS) & FUTEX_ABORT_FLAG)) {
|
|
+ pr_err("%s: abort by CR_STATE_RESTORE_CREDS\n", __func__);
|
|
+ goto core_restore_end;
|
|
+ }
|
|
|
|
futex_dec_and_wake(&thread_inprogress);
|
|
+ futex_wait_while(&thread_start, 0);
|
|
+ if (!!(futex_get(&thread_start) & FUTEX_ABORT_FLAG)) {
|
|
+ pr_err("%s: abort by thread_start\n", __func__);
|
|
+ goto wait_notifier;
|
|
+ }
|
|
|
|
new_sp = (long)rt_sigframe + RT_SIGFRAME_OFFSET(rt_sigframe);
|
|
rst_sigreturn(new_sp, rt_sigframe);
|
|
|
|
core_restore_end:
|
|
- pr_err("Restorer abnormal termination for %ld\n", sys_getpid());
|
|
- futex_abort_and_wake(&task_entries_local->nr_in_progress);
|
|
+ futex_abort_and_wake(&thread_start);
|
|
+ futex_abort_and_wake(&task_entries_local->start);
|
|
+
|
|
+wait_notifier:
|
|
+ pr_err("%s: Restorer abnormal termination for %ld\n", __func__, sys_getpid());
|
|
+ futex_wait_while(¬ifier_done, 0);
|
|
+
|
|
sys_exit_group(1);
|
|
return -1;
|
|
}
|
|
@@ -1465,6 +1529,10 @@ long __export_restore_task(struct task_restore_args *args)
|
|
rt_sigaction_t act;
|
|
bool has_vdso_proxy;
|
|
|
|
+ futex_set(&thread_inprogress, 1);
|
|
+ futex_set(&thread_start, 0);
|
|
+ futex_set(¬ifier_done, 0);
|
|
+
|
|
bootstrap_start = args->bootstrap_start;
|
|
bootstrap_len = args->bootstrap_len;
|
|
|
|
@@ -1481,6 +1549,7 @@ long __export_restore_task(struct task_restore_args *args)
|
|
#ifdef ARCH_HAS_LONG_PAGES
|
|
__page_size = args->page_size;
|
|
#endif
|
|
+ args_with_notifier_kup = args->with_notifier_kup;
|
|
|
|
ksigfillset(&act.rt_sa_mask);
|
|
act.rt_sa_handler = sigchld_handler;
|
|
@@ -1895,7 +1964,8 @@ long __export_restore_task(struct task_restore_args *args)
|
|
pr_err("Unable to create a thread: %ld\n", ret);
|
|
mutex_unlock(&task_entries_local->last_pid_mutex);
|
|
goto core_restore_end;
|
|
- }
|
|
+ } else
|
|
+ futex_inc(&thread_inprogress);
|
|
}
|
|
|
|
mutex_unlock(&task_entries_local->last_pid_mutex);
|
|
@@ -1919,7 +1989,14 @@ long __export_restore_task(struct task_restore_args *args)
|
|
|
|
pr_info("%ld: Restored\n", sys_getpid());
|
|
|
|
- restore_finish_stage(task_entries_local, CR_STATE_RESTORE);
|
|
+ if (!!(restore_finish_stage(task_entries_local, CR_STATE_RESTORE) & FUTEX_ABORT_FLAG)) {
|
|
+ pr_err("%s: abort by CR_STATE_RESTORE\n", __func__);
|
|
+ goto core_restore_end;
|
|
+ }
|
|
+
|
|
+ ret = do_notifier(&args->with_notifier_kup);
|
|
+ if (ret)
|
|
+ goto core_restore_end;
|
|
|
|
if (wait_helpers(args) < 0)
|
|
goto core_restore_end;
|
|
@@ -1965,7 +2042,8 @@ long __export_restore_task(struct task_restore_args *args)
|
|
if (ret)
|
|
goto core_restore_end;
|
|
|
|
- restore_finish_stage(task_entries_local, CR_STATE_RESTORE_SIGCHLD);
|
|
+ if (!!(restore_finish_stage(task_entries_local, CR_STATE_RESTORE_SIGCHLD) & FUTEX_ABORT_FLAG))
|
|
+ goto core_restore_end;
|
|
|
|
rst_tcp_socks_all(args);
|
|
|
|
@@ -1986,15 +2064,20 @@ long __export_restore_task(struct task_restore_args *args)
|
|
ret = ret || restore_pdeath_sig(args->t);
|
|
ret = ret || restore_child_subreaper(args->child_subreaper);
|
|
|
|
- futex_set_and_wake(&thread_inprogress, args->nr_threads);
|
|
-
|
|
- restore_finish_stage(task_entries_local, CR_STATE_RESTORE_CREDS);
|
|
+ if (!!(restore_finish_stage(task_entries_local, CR_STATE_RESTORE_CREDS) & FUTEX_ABORT_FLAG))
|
|
+ goto core_restore_end;
|
|
|
|
if (ret)
|
|
BUG();
|
|
|
|
/* Wait until children stop to use args->task_entries */
|
|
futex_wait_while_gt(&thread_inprogress, 1);
|
|
+ if (!!(futex_get(&thread_start) & FUTEX_ABORT_FLAG)) {
|
|
+ pr_err("%s: terminate by main thread futex_start\n", __func__);
|
|
+ goto handle_notifier;
|
|
+ }
|
|
+
|
|
+ futex_set_and_wake(&thread_start, 1);
|
|
|
|
sys_close(args->proc_fd);
|
|
std_log_set_fd(-1);
|
|
@@ -2030,8 +2113,17 @@ long __export_restore_task(struct task_restore_args *args)
|
|
rst_sigreturn(new_sp, rt_sigframe);
|
|
|
|
core_restore_end:
|
|
- futex_abort_and_wake(&task_entries_local->nr_in_progress);
|
|
+ futex_abort_and_wake(&thread_start);
|
|
+ futex_abort_and_wake(&task_entries_local->start);
|
|
+
|
|
+handle_notifier:
|
|
+ do_notifier_rollback(args->with_notifier_kup, notifier_state);
|
|
+
|
|
+ futex_abort_and_wake(&task_entries_local->nr_in_progress); /* notifier the criu main process */
|
|
pr_err("Restorer fail %ld\n", sys_getpid());
|
|
+
|
|
+ futex_set_and_wake(¬ifier_done, 1); /* wake all other threads to exit */
|
|
+
|
|
sys_exit_group(1);
|
|
return -1;
|
|
}
|
|
diff --git a/criu/pie/util.c b/criu/pie/util.c
|
|
index e7a5a9f..9871db7 100644
|
|
--- a/criu/pie/util.c
|
|
+++ b/criu/pie/util.c
|
|
@@ -11,6 +11,7 @@
|
|
#include "fcntl.h"
|
|
#include "log.h"
|
|
#include "util-pie.h"
|
|
+#include "notifier.h"
|
|
|
|
#ifdef CR_NOGLIBC
|
|
#include <compel/plugins/std/syscall.h>
|
|
@@ -52,3 +53,93 @@ err_close:
|
|
__sys(close)(fd);
|
|
return -1;
|
|
}
|
|
+
|
|
+#define KUP_BUF_SIZE 256
|
|
+
|
|
+static int int_to_string(unsigned number, char *buf, size_t total) {
|
|
+ unsigned remainder, quotient, i, len;
|
|
+
|
|
+ quotient = number;
|
|
+ len = 0;
|
|
+ do {
|
|
+ quotient /= 10;
|
|
+ len += 1;
|
|
+ } while (quotient > 0);
|
|
+
|
|
+ if (len > total - 1)
|
|
+ return -1;
|
|
+
|
|
+ quotient = number;
|
|
+ i = 1;
|
|
+ do {
|
|
+ remainder = quotient % 10;
|
|
+ quotient = quotient / 10;
|
|
+ buf[len-i] = '0' + remainder;
|
|
+ i++;
|
|
+ } while (quotient > 0);
|
|
+ buf[len] = '\0';
|
|
+
|
|
+ return len == 0 ? -1 : len;
|
|
+}
|
|
+
|
|
+int notifier_kup(enum KUP_HOOK_POINT action, enum nvwa_cmd cmd, bool enable)
|
|
+{
|
|
+ int fd, count = 0, retval = 0;
|
|
+ char buf[KUP_BUF_SIZE] = {0};
|
|
+
|
|
+ if (!enable)
|
|
+ return 0;
|
|
+
|
|
+ fd = __sys(open)(NOTIFY_PROC_PATH, O_WRONLY, 0);
|
|
+ if (fd == -EACCES) {
|
|
+ /* there is no priviledge to open file, ignore this condition. */
|
|
+ pr_info("%s: open %s failed, retval: %d (-EACCES)\n",
|
|
+ __func__, NOTIFY_PROC_PATH, -EACCES);
|
|
+ return 0;
|
|
+ } else if (fd < 0) {
|
|
+ __pr_perror("%s: Can't open %s: %d\n", __func__, NOTIFY_PROC_PATH, fd);
|
|
+ return fd;
|
|
+ }
|
|
+
|
|
+ retval = int_to_string(action, buf, sizeof(buf)-count);
|
|
+ if (retval <= 0) {
|
|
+ __pr_perror("%s: int_to_string error\n", __func__);
|
|
+ goto err_close;
|
|
+ }
|
|
+
|
|
+ buf[retval] = ':';
|
|
+ count = retval + 1;
|
|
+
|
|
+ retval = int_to_string(cmd, buf+count, sizeof(buf)-count);
|
|
+ if (retval <= 0) {
|
|
+ __pr_perror("%s: int_to_string error\n", __func__);
|
|
+ goto err_close;
|
|
+ }
|
|
+
|
|
+ count += retval;
|
|
+ retval = __sys(write)(fd, buf, count);
|
|
+ if (retval < 0)
|
|
+ __pr_perror("%s: Can't write to %s\n", __func__, NOTIFY_PROC_PATH);
|
|
+
|
|
+err_close:
|
|
+ __sys(close)(fd);
|
|
+
|
|
+ return retval < 0 ? -1 : 0;
|
|
+}
|
|
+
|
|
+void do_notifier_rollback(bool rollback, enum notifier_state status)
|
|
+{
|
|
+ if (!rollback)
|
|
+ return;
|
|
+
|
|
+ switch (status) {
|
|
+ case POST_UPDATE_KERNEL_COMPLETE:
|
|
+ notifier_kup(POST_UPDATE_KERNEL, ROLLBACK, true);
|
|
+ break;
|
|
+ case UNFREEZE_TO_RUN_COMPLETE:
|
|
+ notifier_kup(UNFREEZE_TO_RUN, ROLLBACK, true);
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+}
|
|
--
|
|
2.34.1
|
|
|