libprocessgroup: Add MaxActivationDepth
Cgroup v2 controllers can be enabled in a subtree of the shared
hierarchy. That allows users to limit the number of cgroups with a
controller enabled to less than the total number of cgroups. [1]
There are costs for each cgroup. Kernel memory is used for each cgroup,
plus additional memory for each active controller in each cgroup. Some
kernel operations scale with the number of cgroups (with a given
controller enabled), so it can be desirable to minimize the number of
cgroups with that controller enabled.
This change allows each v2 controller configuration to specify a maximum
activation depth, past which the controller will not be activated deeper
in the Android cgroup v2 hierarchy. The hierarchy root is defined as
depth 0. MaxActivationDepth is the field name for this purpose for
controllers in the Controllers array under Cgroups2 in cgroups.json.
Here are two examples:
"MaxActivationDepth": 1
This will activate the controller in every per-application cgroup, but
not in the per-process cgroups below.
/sys/fs/cgroup depth=0 active=true (controller listed in cgroup.subtree_control)
/sys/fs/cgroup/uid_0 depth=1 active=true (controller NOT listed in cgroup.subtree_control)
/sys/fs/cgroup/uid_0/pid_100 depth=2 active=false (controller NOT listed in cgroup.subtree_control)
This can also be used with
PRODUCT_CGROUP_V2_SYS_APP_ISOLATION_ENABLED := true.
"MaxActivationDepth": 1
This will activate the controller only at the app / system level, but
not in per-application cgroups below. This results in a total of only
3 cgroups with the controller enabled (root, apps, system).
/sys/fs/cgroup depth=0 active=true (controller listed in cgroup.subtree_control)
/sys/fs/cgroup/apps depth=1 active=true (controller NOT listed in cgroup.subtree_control)
/sys/fs/cgroup/apps/uid_10000 depth=2 active=false (controller NOT listed in cgroup.subtree_control)
/sys/fs/cgroup/apps/uid_10000/pid_100 depth=3 active=false (controller NOT listed in cgroup.subtree_control)
[1] https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html#enabling-and-disabling
Bug: 346584259
Test: Cuttlefish with memcg v2
Change-Id: I62109ea935261c51fc30b2054c4d28d0360f7985
diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp
index ebc0599..52b5afe 100644
--- a/libprocessgroup/cgroup_map.cpp
+++ b/libprocessgroup/cgroup_map.cpp
@@ -28,6 +28,7 @@
#include <android-base/strings.h>
#include <cgroup_map.h>
#include <processgroup/processgroup.h>
+#include <processgroup/util.h>
using android::base::StartsWith;
using android::base::StringPrintf;
@@ -216,7 +217,13 @@
for (uint32_t i = 0; i < controller_count; ++i) {
const ACgroupController* controller = ACgroupFile_getController(i);
const uint32_t flags = ACgroupController_getFlags(controller);
- if (flags & CGROUPRC_CONTROLLER_FLAG_NEEDS_ACTIVATION) {
+ uint32_t max_activation_depth = UINT32_MAX;
+ if (__builtin_available(android 36, *)) {
+ max_activation_depth = ACgroupController_getMaxActivationDepth(controller);
+ }
+ const int depth = util::GetCgroupDepth(ACgroupController_getPath(controller), path);
+
+ if (flags & CGROUPRC_CONTROLLER_FLAG_NEEDS_ACTIVATION && depth < max_activation_depth) {
std::string str("+");
str.append(ACgroupController_getName(controller));
if (!WriteStringToFile(str, path + "/cgroup.subtree_control")) {