Skip to content

Commit ef5e28a

Browse files
committed
restore: restore freezer cgroup state
Issue checkpoint-restore#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 <[email protected]> Signed-off-by: Eugene Batalov <[email protected]>
1 parent 3e03316 commit ef5e28a

File tree

3 files changed

+58
-2
lines changed

3 files changed

+58
-2
lines changed

cgroup.c

+53
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ static unsigned int n_sets;
100100
static CgSetEntry **rst_sets;
101101
static unsigned int n_controllers;
102102
static CgControllerEntry **controllers;
103+
static char *freezer_state;
103104
static char *cg_yard;
104105
static struct cg_set *root_cgset; /* Set root item lives in */
105106
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,
862863
return doff;
863864
}
864865

866+
int restore_freezer_state(void)
867+
{
868+
int fd, cgfd, i, err;
869+
char paux[PATH_MAX];
870+
int ctrl_off;
871+
CgroupDirEntry *entry;
872+
CgControllerEntry *freezer_ctrl = NULL;
873+
874+
if (!freezer_state || strcmp(freezer_state, "FROZEN") != 0)
875+
return 0;
876+
877+
for (i = 0; i < n_controllers; i++) {
878+
CgControllerEntry *ctrl = controllers[i];
879+
880+
if (cgroup_contains(ctrl->cnames, ctrl->n_cnames, "freezer")) {
881+
freezer_ctrl = ctrl;
882+
break;
883+
}
884+
}
885+
886+
if (!freezer_ctrl) {
887+
pr_err("Can't restore freezer cgroup state: root freezer cgroup not found\n");
888+
return -1;
889+
}
890+
891+
/*
892+
* Here we rely on --freeze-cgroup option assumption that all tasks are in a
893+
* specified freezer cgroup hierarchy, so we need to freeze only one root freezer cgroup.
894+
*/
895+
BUG_ON(freezer_ctrl->n_dirs != 1);
896+
entry = freezer_ctrl->dirs[0];
897+
898+
cgfd = get_service_fd(CGROUP_YARD);
899+
ctrl_off = ctrl_dir_and_opt(freezer_ctrl, paux, sizeof(paux), NULL, 0);
900+
snprintf(paux + ctrl_off, sizeof(paux) - ctrl_off, "/%s/freezer.state", entry->dir_name);
901+
902+
fd = openat(cgfd, paux, O_WRONLY);
903+
if (fd < 0) {
904+
pr_err("Can't open %s\n", paux);
905+
return -1;
906+
}
907+
err = write(fd, "FROZEN", sizeof("FROZEN"));
908+
close(fd);
909+
if (err < 0) {
910+
pr_err("Can't update %s (%d)\n", paux, err);
911+
return -1;
912+
}
913+
914+
return 0;
915+
}
916+
865917
static const char *special_cpuset_props[] = {
866918
"cpuset.cpus",
867919
"cpuset.mems",
@@ -1340,6 +1392,7 @@ int prepare_cgroup(void)
13401392
rst_sets = ce->sets;
13411393
n_controllers = ce->n_controllers;
13421394
controllers = ce->controllers;
1395+
freezer_state = ce->freezer_state;
13431396

13441397
if (n_sets)
13451398
/*

cr-restore.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -1911,7 +1911,6 @@ static int restore_root_task(struct pstree_item *init)
19111911
goto out_kill;
19121912

19131913
ret = prepare_cgroup_properties();
1914-
fini_cgroup();
19151914
if (ret < 0)
19161915
goto out_kill;
19171916

@@ -1954,8 +1953,11 @@ static int restore_root_task(struct pstree_item *init)
19541953
if (clear_breakpoints())
19551954
pr_err("Unable to flush breakpoints\n");
19561955

1957-
if (ret == 0)
1956+
if (ret == 0) {
19581957
finalize_restore();
1958+
ret = restore_freezer_state();
1959+
}
1960+
fini_cgroup();
19591961

19601962
/* Detaches from processes and they continue run through sigreturn. */
19611963
finalize_restore_detach(ret);

include/cgroup.h

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ int prepare_task_cgroup(struct pstree_item *);
99
int prepare_cgroup(void);
1010
/* Restore things like cpu_limit in known cgroups. */
1111
int prepare_cgroup_properties(void);
12+
int restore_freezer_state(void);
1213
void fini_cgroup(void);
1314

1415
struct cg_controller;

0 commit comments

Comments
 (0)