Skip to content

Commit 4868f40

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. Signed-off-by: Evgeniy Akimov <[email protected]> Signed-off-by: Eugene Batalov <[email protected]>
1 parent ad58f51 commit 4868f40

File tree

3 files changed

+75
-2
lines changed

3 files changed

+75
-2
lines changed

cgroup.c

+70
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,76 @@ int dump_real_freezer_state(void)
877877
return 0;
878878
}
879879

880+
int restore_freezer_state(void)
881+
{
882+
int fd, err, sfd, cgfd, i;
883+
char state[8];
884+
CgControllerEntry *freezer_ctrl = NULL;
885+
char paux[PATH_MAX];
886+
int ctrl_off;
887+
888+
sfd = get_service_fd(IMG_FD_OFF);
889+
if (faccessat(sfd, freezer_state_file, F_OK, 0) < 0)
890+
return 0;
891+
892+
fd = openat(sfd, freezer_state_file, O_RDONLY);
893+
if (fd < 0) {
894+
pr_err("Can't open freezer state dump file\n");
895+
return -1;
896+
}
897+
err = read(fd, state, sizeof(state));
898+
close(fd);
899+
if (err < 0) {
900+
pr_err("Can't load freezer state\n");
901+
return -1;
902+
}
903+
904+
if (strncmp(state, "FROZEN", sizeof("FROZEN") - 1) != 0)
905+
return 0;
906+
907+
for (i = 0; i < n_controllers; i++) {
908+
CgControllerEntry *ctrl = controllers[i];
909+
910+
if (cgroup_contains(ctrl->cnames, ctrl->n_cnames, "freezer")) {
911+
freezer_ctrl = ctrl;
912+
break;
913+
}
914+
}
915+
916+
if (!freezer_ctrl) {
917+
pr_err("Can't restore freezer cgroup state: root freezer cgroup not found\n");
918+
return -1;
919+
}
920+
921+
/*
922+
* Here we rely on --freeze-cgroup option assumption that all tasks are in a
923+
* specified freezer group, so we need to freeze only one root freezer cgroup.
924+
*/
925+
BUG_ON(freezer_ctrl->n_dirs != 1);
926+
927+
cgfd = get_service_fd(CGROUP_YARD);
928+
ctrl_off = ctrl_dir_and_opt(freezer_ctrl, paux, sizeof(paux), NULL, 0);
929+
930+
for (i = 0; i < freezer_ctrl->n_dirs; i++) {
931+
CgroupDirEntry *entry = freezer_ctrl->dirs[i];
932+
933+
snprintf(paux + ctrl_off, sizeof(paux) - ctrl_off, "/%s/freezer.state", entry->dir_name);
934+
fd = openat(cgfd, paux, O_WRONLY);
935+
if (fd < 0) {
936+
pr_err("Can't open %s\n", paux);
937+
return -1;
938+
}
939+
err = write(fd, "FROZEN", sizeof("FROZEN"));
940+
close(fd);
941+
if (err < 0) {
942+
pr_err("Can't update %s (%d)\n", paux, err);
943+
return -1;
944+
}
945+
}
946+
947+
return 0;
948+
}
949+
880950
static const char *special_cpuset_props[] = {
881951
"cpuset.cpus",
882952
"cpuset.mems",

cr-restore.c

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

19041904
ret = prepare_cgroup_properties();
1905-
fini_cgroup();
19061905
if (ret < 0)
19071906
goto out_kill;
19081907

@@ -1945,8 +1944,11 @@ static int restore_root_task(struct pstree_item *init)
19451944
if (clear_breakpoints())
19461945
pr_err("Unable to flush breakpoints\n");
19471946

1948-
if (ret == 0)
1947+
if (ret == 0) {
19491948
finalize_restore();
1949+
ret = restore_freezer_state();
1950+
}
1951+
fini_cgroup();
19501952

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

include/cgroup.h

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ int prepare_cgroup_properties(void);
1212
void fini_cgroup(void);
1313

1414
int dump_real_freezer_state(void);
15+
int restore_freezer_state(void);
1516

1617
struct cg_controller;
1718

0 commit comments

Comments
 (0)