Commit b428a3a2 authored by Tycho Andersen's avatar Tycho Andersen Committed by Pavel Emelyanov

cgroup: don't fail on multi-headed freezer cgroup

Consider the case where --freeze-cgroup=/lxc/foo, but (e.g. with systemd in
lxc), all of the tasks actually live in a set of sub cgroups, e.g.
/lxc/foo/init.scope and others. In this case, we will have a multi-headed
controller, since there is nothing in the common parent. We should just
save the freezer value in all of these heads instead of failing.

Note that this doesn't address the larger problem that only the top level
freezer.state file is c/r'd, or waht happens when the container itself has
frozen tasks but not at the top level. After some discussion, there is no
nice way to atomically test-and-set the cgroup freezer, so we'll need some
other kernel help. But I'll ignore this for now :)
Signed-off-by: 's avatarTycho Andersen <tycho.andersen@canonical.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent f91d3f01
......@@ -556,31 +556,34 @@ out:
static int add_freezer_state(struct cg_controller *controller)
{
struct cgroup_dir *root_dir;
struct cgroup_prop *prop;
/*
* Here we rely on --freeze-cgroup option assumption that all tasks are in a
* specified freezer cgroup hierarchy, so we need to dump only one root freezer cgroup.
*/
if (!list_is_singular(&controller->heads)) {
pr_err("Should be only one root freezer cgroup");
return -1;
}
root_dir = list_first_entry(&controller->heads, struct cgroup_dir, siblings);
struct cgroup_dir *it;
/* There is one more case, that cgroup namespaces might
* generate "multiple" heads if nothing is actually in the
* root freezer cgroup, e.g. --freeze-cgroup=/lxc/foo and all
* tasks in either /lxc/foo/a or /lxc/foo/b.
*
* In this case
*/
list_for_each_entry(it, &controller->heads, siblings) {
struct cgroup_dir *cg_head;
struct cgroup_prop *prop;
cg_head = list_first_entry(&controller->heads, struct cgroup_dir, siblings);
prop = create_cgroup_prop("freezer.state");
if (!prop)
return -1;
prop->value = xstrdup(get_real_freezer_state());
if (!prop->value) {
free_cgroup_prop(prop);
return -1;
}
prop = create_cgroup_prop("freezer.state");
if (!prop)
return -1;
prop->value = xstrdup(get_real_freezer_state());
if (!prop->value) {
free_cgroup_prop(prop);
return -1;
list_add_tail(&prop->list, &cg_head->properties);
cg_head->n_properties++;
}
list_add_tail(&prop->list, &root_dir->properties);
root_dir->n_properties++;
return 0;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment