cgroup: move PID 1 out of the init/ group

A cgroup holding processes cannot enable controllers for its children,
so init/ had to stay a leaf.  The hotplug helpers 10-hotplug.conf.in
places there ended up in groups where cpu.weight and friends could
never be set.

Keeping PID 1 in the root cgroup makes init/ a domain like the others.
It also unbreaks lxc-based runtimes: liblxc bases the container tree on
PID 1's cgroup and only special-cases systemd's init.scope/, so under
Finit it landed containers in init/, with no controllers available.

Issue #497

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2026-08-12 07:18:40 +02:00
parent a35ed8f72e
commit 1843c24cda
2 changed files with 8 additions and 19 deletions
+3 -1
View File
@@ -42,7 +42,9 @@ the above three. We leave `init/` and `user/` as-is reducing weight of
cgroup maint { cpu.weight = 100 }
By default, the `system/` cgroup is selected for almost everything. The
`init/` cgroup is reserved for PID 1 itself and its closest relatives.
`init/` cgroup is reserved for the early boot helpers Finit drives
itself, like udev and mdev. PID 1 runs in the root cgroup, since a
cgroup holding processes cannot delegate controllers to its children.
The `user/` cgroup is for local TTY logins spawned by getty.
Joining a Cgroup
+5 -18
View File
@@ -414,9 +414,6 @@ int cgroup_service(const char *name, int pid, struct cgroup *cg, char *username,
if (!strcmp(cg->name, "root"))
return fnwrite(str("%d", pid), FINIT_CGPATH "/cgroup.procs");
if (!strcmp(cg->name, "init"))
return fnwrite(str("%d", pid), FINIT_CGPATH "/init/cgroup.procs");
snprintf(path, sizeof(path), "/sys/fs/cgroup/%s", cg->name);
if (fisdir(path))
group = cg->name;
@@ -818,7 +815,6 @@ int cgroup_del_svc(svc_t *svc, const char *name)
return cgroup_del(path);
}
/* the top-level init cgroup is a leaf, that's ensured in cgroup_init() */
void cgroup_config(void)
{
struct cg *cg;
@@ -828,15 +824,12 @@ void cgroup_config(void)
TAILQ_FOREACH(cg, &cgroups, link) {
char path[256];
int leaf = 0;
if (!cg->active)
continue;
if (!strcmp(cg->name, "init"))
leaf = 1; /* reserved */
snprintf(path, sizeof(path), "%s/%s", FINIT_CGPATH, cg->name);
group_init(path, leaf, cg->cfg);
group_init(path, 0, cg->cfg);
strlcat(path, "/cgroup.events", sizeof(path));
iwatch_add(&iw_cgroup, path, 0);
@@ -940,20 +933,14 @@ void cgroup_init(uev_ctx_t *ctx)
goto abort;
}
/* Default (protected) groups, PID 1, services, and user/login processes */
/*
* Protected groups. PID 1 stays in the root cgroup, a group with
* processes in it cannot delegate controllers to its children.
*/
cgroup_add("init", "cpu.weight:100", 1);
cgroup_add("system", "cpu.weight:9800", 1);
cgroup_add("user", "cpu.weight:100", 1);
cgroup_config();
/* Move ourselves to init (best effort, otherwise run in 'root' group */
if (fnwrite("1", FINIT_CGPATH "/init/cgroup.procs")) {
err(1, "Failed moving PID 1 to cgroup %s", FINIT_CGPATH "/init");
uev_io_stop(&cgw);
iwatch_exit(&iw_cgroup);
close(fd);
goto abort;
}
}
/**