[CRIU] [PATCHv2 3/3] restore: restore freezer cgroup state

Eugene Batalov eabatalov89 at gmail.com
Tue Dec 15 02:51:28 PST 2015


From: Evgeniy Akimov <geka666 at gmail.com>

Patch restores freezer cgroup state between finalize_restore stages.
It should be done after first stage because we cannot unmap restorer blob
from frozen process, and before second stage because we must freeze processes
before they continue run.
We also need to move fini_cgroup between these stages to provide freezer
cgroup state restorer access to cgroup mount directories.
Error handlers contains fini_cgroup, so we are sure that fini_cgroup call
won't be missed.

Patch restores state only for one freezer cgroup from --freeze-cgroup option,
not all states from whole hierarchy, because CRIU supports checkpoint from
freezer cgroup hierarchy only with THAWED state, except root cgroup from
--freeze-cgroup option.

Signed-off-by: Evgeniy Akimov <geka666 at gmail.com>
Signed-off-by: Eugene Batalov <eabatalov89 at gmail.com>
---
 cgroup.c         | 29 +++++++++++++++++++++++++++++
 cr-restore.c     |  6 +++++-
 include/cgroup.h |  1 +
 3 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/cgroup.c b/cgroup.c
index ffc1c96..4d603b7 100644
--- a/cgroup.c
+++ b/cgroup.c
@@ -1036,6 +1036,31 @@ static int restore_cgroup_prop(const CgroupPropEntry * cg_prop_entry_p,
 	return 0;
 }
 
+static CgroupPropEntry *freezer_state_entry;
+static char freezer_path[PATH_MAX];
+
+int restore_freezer_state(void)
+{
+	size_t freezer_path_len;
+
+	if (!freezer_state_entry)
+		return 0;
+
+	freezer_path_len = strlen(freezer_path);
+	return restore_cgroup_prop(freezer_state_entry, freezer_path, freezer_path_len);
+}
+
+static void add_freezer_state_for_restore(CgroupPropEntry *entry, char *path, size_t path_len)
+{
+	BUG_ON(freezer_state_entry);
+	BUG_ON(path_len >= sizeof(freezer_path));
+
+	freezer_state_entry = entry;
+	/* Path is not null terminated at path_len */
+	strncpy(freezer_path, path, path_len);
+	freezer_path[path_len] = 0;
+}
+
 static int prepare_cgroup_dir_properties(char *path, int off, CgroupDirEntry **ents,
 					 unsigned int n_ents)
 {
@@ -1051,6 +1076,10 @@ static int prepare_cgroup_dir_properties(char *path, int off, CgroupDirEntry **e
 		off2 += sprintf(path + off, "/%s", e->dir_name);
 		if (e->n_properties > 0) {
 			for (j = 0; j < e->n_properties; ++j) {
+				if (!strcmp(e->properties[j]->name, "freezer.state")) {
+					add_freezer_state_for_restore(e->properties[j], path, off2);
+					continue; /* skip restore now */
+				}
 				if (restore_cgroup_prop(e->properties[j], path, off2) < 0)
 					return -1;
 			}
diff --git a/cr-restore.c b/cr-restore.c
index 2362b63..22d7de2 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -1915,7 +1915,6 @@ static int restore_root_task(struct pstree_item *init)
 		goto out_kill;
 
 	ret = prepare_cgroup_properties();
-	fini_cgroup();
 	if (ret < 0)
 		goto out_kill;
 
@@ -1961,6 +1960,11 @@ static int restore_root_task(struct pstree_item *init)
 	if (ret == 0)
 		finalize_restore();
 
+	if (restore_freezer_state())
+		pr_err("Unable to restore freezer state\n");
+
+	fini_cgroup();
+
 	/* Detaches from processes and they continue run through sigreturn. */
 	finalize_restore_detach(ret);
 
diff --git a/include/cgroup.h b/include/cgroup.h
index 37ba3cb..58bbd63 100644
--- a/include/cgroup.h
+++ b/include/cgroup.h
@@ -9,6 +9,7 @@ int prepare_task_cgroup(struct pstree_item *);
 int prepare_cgroup(void);
 /* Restore things like cpu_limit in known cgroups. */
 int prepare_cgroup_properties(void);
+int restore_freezer_state(void);
 void fini_cgroup(void);
 
 struct cg_controller;
-- 
1.9.1



More information about the CRIU mailing list