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

Eugene Batalov eabatalov89 at gmail.com
Tue Nov 24 05:34:14 PST 2015


From: Evgeniy Akimov <geka666 at gmail.com>

Issue #20. (Support C/R of frozen cgroup)

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         | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 cr-restore.c     |  6 ++++--
 include/cgroup.h |  1 +
 3 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/cgroup.c b/cgroup.c
index c6718f9..9ec0975 100644
--- a/cgroup.c
+++ b/cgroup.c
@@ -100,6 +100,7 @@ static unsigned int n_sets;
 static CgSetEntry **rst_sets;
 static unsigned int n_controllers;
 static CgControllerEntry **controllers;
+static char *freezer_state;
 static char *cg_yard;
 static struct cg_set *root_cgset; /* Set root item lives in */
 static struct cg_set *criu_cgset; /* Set criu process lives in */
@@ -862,6 +863,57 @@ static int ctrl_dir_and_opt(CgControllerEntry *ctl, char *dir, int ds,
 	return doff;
 }
 
+int restore_freezer_state(void)
+{
+	int fd, cgfd, i, err;
+	char paux[PATH_MAX];
+	int ctrl_off;
+	CgroupDirEntry *entry;
+	CgControllerEntry *freezer_ctrl = NULL;
+
+	if (!freezer_state || strcmp(freezer_state, "FROZEN") != 0)
+		return 0;
+
+	for (i = 0; i < n_controllers; i++) {
+		CgControllerEntry *ctrl = controllers[i];
+
+		if (cgroup_contains(ctrl->cnames, ctrl->n_cnames, "freezer")) {
+			freezer_ctrl = ctrl;
+			break;
+		}
+	}
+
+	if (!freezer_ctrl) {
+		pr_err("Can't restore freezer cgroup state: root freezer cgroup not found\n");
+		return -1;
+	}
+
+	/*
+	 * Here we rely on --freeze-cgroup option assumption that all tasks are in a
+	 * specified freezer cgroup hierarchy, so we need to freeze only one root freezer cgroup.
+	 */
+	BUG_ON(freezer_ctrl->n_dirs != 1);
+	entry = freezer_ctrl->dirs[0];
+
+	cgfd = get_service_fd(CGROUP_YARD);
+	ctrl_off = ctrl_dir_and_opt(freezer_ctrl, paux, sizeof(paux), NULL, 0);
+	snprintf(paux + ctrl_off, sizeof(paux) - ctrl_off, "/%s/freezer.state", entry->dir_name);
+
+	fd = openat(cgfd, paux, O_WRONLY);
+	if (fd < 0) {
+		pr_err("Can't open %s\n", paux);
+		return -1;
+	}
+	err = write(fd, "FROZEN", sizeof("FROZEN"));
+	close(fd);
+	if (err < 0) {
+		pr_err("Can't update %s (%d)\n", paux, err);
+		return -1;
+	}
+
+	return 0;
+}
+
 static const char *special_cpuset_props[] = {
 	"cpuset.cpus",
 	"cpuset.mems",
@@ -1340,6 +1392,7 @@ int prepare_cgroup(void)
 	rst_sets = ce->sets;
 	n_controllers = ce->n_controllers;
 	controllers = ce->controllers;
+	freezer_state = ce->freezer_state;
 
 	if (n_sets)
 		/*
diff --git a/cr-restore.c b/cr-restore.c
index dddf4fd..af7954d 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -1911,7 +1911,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;
 
@@ -1954,8 +1953,11 @@ static int restore_root_task(struct pstree_item *init)
 	if (clear_breakpoints())
 		pr_err("Unable to flush breakpoints\n");
 
-	if (ret == 0)
+	if (ret == 0) {
 		finalize_restore();
+		ret = restore_freezer_state();
+	}
+	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