From 7f19b1e6de17dd124328f7538e23d6bed56b55fc Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Wed, 10 Mar 2021 10:31:35 -0800 Subject: [PATCH] libprocessgroup: introduce optional attribute for cgroup controllers Memory cgroup controller is not used by high-end Android devices and is disabled in Android kernels 5.10+, however Android Go devices still require this controller. Similarly schedtune controller is being replaced with cpu controller's utilclamp feature, however some devices are using older kernels which only support schedtune. To prevent spamming logcat with errors we need a way to mark a controller optional in such cases without removing it from cgroups.json file. Introduce "Optional" attribute to cgroup controller's cgroups.json description to accomodate these cases. When an optional controller fails to mount due to lack of support in the kernel it will log an informational message without generating further errors. Bug: 181866655 Test: boot and observe libprocessgroup messages in logcat Signed-off-by: Suren Baghdasaryan Change-Id: Ib5bcfdd8d338704f3f9d8b326d8ddd88b67915a1 --- .../cgrouprc/include/android/cgrouprc.h | 1 + libprocessgroup/profiles/cgroups.json | 3 ++- libprocessgroup/profiles/cgroups.proto | 3 ++- libprocessgroup/profiles/cgroups_30.json | 3 ++- libprocessgroup/setup/cgroup_map_write.cpp | 15 +++++++++++++-- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/libprocessgroup/cgrouprc/include/android/cgrouprc.h b/libprocessgroup/cgrouprc/include/android/cgrouprc.h index 9a799547d..100d60ea9 100644 --- a/libprocessgroup/cgrouprc/include/android/cgrouprc.h +++ b/libprocessgroup/cgrouprc/include/android/cgrouprc.h @@ -68,6 +68,7 @@ __attribute__((warn_unused_result)) uint32_t ACgroupController_getVersion(const */ #define CGROUPRC_CONTROLLER_FLAG_MOUNTED 0x1 #define CGROUPRC_CONTROLLER_FLAG_NEEDS_ACTIVATION 0x2 +#define CGROUPRC_CONTROLLER_FLAG_OPTIONAL 0x4 /** * Returns the flags bitmask of the given controller. diff --git a/libprocessgroup/profiles/cgroups.json b/libprocessgroup/profiles/cgroups.json index 962d2baa8..063422091 100644 --- a/libprocessgroup/profiles/cgroups.json +++ b/libprocessgroup/profiles/cgroups.json @@ -26,7 +26,8 @@ "Path": "/dev/memcg", "Mode": "0700", "UID": "root", - "GID": "system" + "GID": "system", + "Optional": true } ], "Cgroups2": { diff --git a/libprocessgroup/profiles/cgroups.proto b/libprocessgroup/profiles/cgroups.proto index 13adcae07..f2de3452a 100644 --- a/libprocessgroup/profiles/cgroups.proto +++ b/libprocessgroup/profiles/cgroups.proto @@ -24,7 +24,7 @@ message Cgroups { Cgroups2 cgroups2 = 2 [json_name = "Cgroups2"]; } -// Next: 7 +// Next: 8 message Cgroup { string controller = 1 [json_name = "Controller"]; string path = 2 [json_name = "Path"]; @@ -35,6 +35,7 @@ message Cgroup { // when a boolean is specified as false, so leave unspecified in that case // https://developers.google.com/protocol-buffers/docs/proto3#default bool needs_activation = 6 [json_name = "NeedsActivation"]; + bool is_optional = 7 [json_name = "Optional"]; } // Next: 6 diff --git a/libprocessgroup/profiles/cgroups_30.json b/libprocessgroup/profiles/cgroups_30.json index 17d492949..80a074bf1 100644 --- a/libprocessgroup/profiles/cgroups_30.json +++ b/libprocessgroup/profiles/cgroups_30.json @@ -5,7 +5,8 @@ "Path": "/dev/stune", "Mode": "0755", "UID": "system", - "GID": "system" + "GID": "system", + "Optional": true } ] } diff --git a/libprocessgroup/setup/cgroup_map_write.cpp b/libprocessgroup/setup/cgroup_map_write.cpp index b0b91f81f..3121d244b 100644 --- a/libprocessgroup/setup/cgroup_map_write.cpp +++ b/libprocessgroup/setup/cgroup_map_write.cpp @@ -161,6 +161,10 @@ static void MergeCgroupToDescriptors(std::map* de controller_flags |= CGROUPRC_CONTROLLER_FLAG_NEEDS_ACTIVATION; } + if (cgroup["Optional"].isBool() && cgroup["Optional"].asBool()) { + controller_flags |= CGROUPRC_CONTROLLER_FLAG_OPTIONAL; + } + CgroupDescriptor descriptor( cgroups_version, name, path, std::strtoul(cgroup["Mode"].asString().c_str(), 0, 8), cgroup["UID"].asString(), cgroup["GID"].asString(), controller_flags); @@ -308,8 +312,15 @@ static bool SetupCgroup(const CgroupDescriptor& descriptor) { } if (result < 0) { - PLOG(ERROR) << "Failed to mount " << controller->name() << " cgroup"; - return false; + bool optional = controller->flags() & CGROUPRC_CONTROLLER_FLAG_OPTIONAL; + + if (optional && errno == EINVAL) { + // Optional controllers are allowed to fail to mount if kernel does not support them + LOG(INFO) << "Optional " << controller->name() << " cgroup controller is not mounted"; + } else { + PLOG(ERROR) << "Failed to mount " << controller->name() << " cgroup"; + return false; + } } return true;