Merge pull request #18553 from Werkov/cgroup-user-instance-controllers

Make (user) instance aware of delegated cgroup controllers
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2021-03-10 09:41:40 +01:00
committed by GitHub
3 changed files with 46 additions and 62 deletions
+42 -41
View File
@@ -527,41 +527,22 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
return 0;
}
static int controller_is_accessible(const char *controller) {
int r;
static int controller_is_v1_accessible(const char *root, const char *controller) {
const char *cpath, *dn;
assert(controller);
/* Checks whether a specific controller is accessible,
* i.e. its hierarchy mounted. In the unified hierarchy all
* controllers are considered accessible, except for the named
* hierarchies */
dn = controller_to_dirname(controller);
cpath = strjoina("/sys/fs/cgroup/", dn);
if (root)
/* Also check that:
* - possible subcgroup is created at root,
* - we can modify the hierarchy.
* "Leak" cpath on stack */
cpath = strjoina(cpath, root, "/cgroup.procs");
if (!cg_controller_is_valid(controller))
return -EINVAL;
r = cg_all_unified();
if (r < 0)
return r;
if (r > 0) {
/* We don't support named hierarchies if we are using
* the unified hierarchy. */
if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
return 0;
if (startswith(controller, "name="))
return -EOPNOTSUPP;
} else {
const char *cc, *dn;
dn = controller_to_dirname(controller);
cc = strjoina("/sys/fs/cgroup/", dn);
if (laccess(cc, F_OK) < 0)
return -errno;
}
if (laccess(cpath, root ? W_OK : F_OK) < 0)
return -errno;
return 0;
}
@@ -572,10 +553,23 @@ int cg_get_path_and_check(const char *controller, const char *path, const char *
assert(controller);
assert(fs);
/* Check if the specified controller is actually accessible */
r = controller_is_accessible(controller);
if (!cg_controller_is_valid(controller))
return -EINVAL;
r = cg_all_unified();
if (r < 0)
return r;
if (r > 0) {
/* In the unified hierarchy all controllers are considered accessible,
* except for the named hierarchies */
if (startswith(controller, "name="))
return -EOPNOTSUPP;
} else {
/* Check if the specified controller is actually accessible */
r = controller_is_v1_accessible(NULL, controller);
if (r < 0)
return r;
}
return cg_get_path(controller, path, suffix, fs);
}
@@ -1892,7 +1886,7 @@ int cg_mask_from_string(const char *value, CGroupMask *ret) {
return 0;
}
int cg_mask_supported(CGroupMask *ret) {
int cg_mask_supported_subtree(const char *root, CGroupMask *ret) {
CGroupMask mask;
int r;
@@ -1904,15 +1898,11 @@ int cg_mask_supported(CGroupMask *ret) {
if (r < 0)
return r;
if (r > 0) {
_cleanup_free_ char *root = NULL, *controllers = NULL, *path = NULL;
_cleanup_free_ char *controllers = NULL, *path = NULL;
/* In the unified hierarchy we can read the supported and accessible controllers from
* the top-level cgroup attribute */
r = cg_get_root_path(&root);
if (r < 0)
return r;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, root, "cgroup.controllers", &path);
if (r < 0)
return r;
@@ -1931,7 +1921,7 @@ int cg_mask_supported(CGroupMask *ret) {
} else {
CGroupController c;
/* In the legacy hierarchy, we check which hierarchies are mounted. */
/* In the legacy hierarchy, we check which hierarchies are accessible. */
mask = 0;
for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
@@ -1942,7 +1932,7 @@ int cg_mask_supported(CGroupMask *ret) {
continue;
n = cgroup_controller_to_string(c);
if (controller_is_accessible(n) >= 0)
if (controller_is_v1_accessible(root, n) >= 0)
mask |= bit;
}
}
@@ -1951,6 +1941,17 @@ int cg_mask_supported(CGroupMask *ret) {
return 0;
}
int cg_mask_supported(CGroupMask *ret) {
_cleanup_free_ char *root = NULL;
int r;
r = cg_get_root_path(&root);
if (r < 0)
return r;
return cg_mask_supported_subtree(root, ret);
}
int cg_kernel_controllers(Set **ret) {
_cleanup_set_free_free_ Set *controllers = NULL;
_cleanup_fclose_ FILE *f = NULL;
+1
View File
@@ -260,6 +260,7 @@ int cg_slice_to_path(const char *unit, char **ret);
typedef const char* (*cg_migrate_callback_t)(CGroupMask mask, void *userdata);
int cg_mask_supported(CGroupMask *ret);
int cg_mask_supported_subtree(const char *root, CGroupMask *ret);
int cg_mask_from_string(const char *s, CGroupMask *ret);
int cg_mask_to_string(CGroupMask mask, char **ret);