system/core
Révision | fd285d2b70537fd3ef239ae3843c30ccf07ac161 (tree) |
---|---|
l'heure | 2019-05-18 08:18:29 |
Auteur | Suren Baghdasaryan <surenb@goog...> |
Commiter | Suren Baghdasaryan |
libprocessgroup: add flags to indicate when a controller failed to mount
Controllers listed in cgroups.json file might fail to mount if kernel is
not configured to support them. We need a way to indicate whether a
controller was successfully mounted and is usable to avoid logging errors
and warnings when a controller that failed to mount is being used. Add
flags bitmask to cgrouprc controller descriptor and use a bit to indicate
that controller is successfully mounted. Modify cpusets_enabled() and
schedboost_enabled() functions to use this bit and report the actual
availability of the controller.
Bug: 124080437
Test: libcutils_test with cpuset and schedtune controllers disabled
Change-Id: I770cc39fe50465146e3205aacf77dc3c56923c5d
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
@@ -67,6 +67,13 @@ bool CgroupController::HasValue() const { | ||
67 | 67 | return controller_ != nullptr; |
68 | 68 | } |
69 | 69 | |
70 | +bool CgroupController::IsUsable() const { | |
71 | + if (!HasValue()) return false; | |
72 | + | |
73 | + uint32_t flags = ACgroupController_getFlags(controller_); | |
74 | + return (flags & CGROUPRC_CONTROLLER_FLAG_MOUNTED) != 0; | |
75 | +} | |
76 | + | |
70 | 77 | std::string CgroupController::GetTasksFilePath(const std::string& rel_path) const { |
71 | 78 | std::string tasks_path = path(); |
72 | 79 |
@@ -153,6 +160,7 @@ void CgroupMap::Print() const { | ||
153 | 160 | const ACgroupController* controller = ACgroupFile_getController(i); |
154 | 161 | LOG(INFO) << "\t" << ACgroupController_getName(controller) << " ver " |
155 | 162 | << ACgroupController_getVersion(controller) << " path " |
163 | + << ACgroupController_getFlags(controller) << " flags " | |
156 | 164 | << ACgroupController_getPath(controller); |
157 | 165 | } |
158 | 166 | } |
@@ -38,6 +38,7 @@ class CgroupController { | ||
38 | 38 | const char* path() const; |
39 | 39 | |
40 | 40 | bool HasValue() const; |
41 | + bool IsUsable() const; | |
41 | 42 | |
42 | 43 | std::string GetTasksFilePath(const std::string& path) const; |
43 | 44 | std::string GetProcsFilePath(const std::string& path, uid_t uid, pid_t pid) const; |
@@ -42,19 +42,19 @@ cc_library { | ||
42 | 42 | "libcgrouprc_format", |
43 | 43 | ], |
44 | 44 | stubs: { |
45 | - symbol_file: "libcgrouprc.map.txt", | |
45 | + symbol_file: "libcgrouprc.llndk.txt", | |
46 | 46 | versions: ["29"], |
47 | 47 | }, |
48 | 48 | target: { |
49 | 49 | linux: { |
50 | - version_script: "libcgrouprc.map.txt", | |
50 | + version_script: "libcgrouprc.llndk.txt", | |
51 | 51 | }, |
52 | 52 | }, |
53 | 53 | } |
54 | 54 | |
55 | 55 | llndk_library { |
56 | 56 | name: "libcgrouprc", |
57 | - symbol_file: "libcgrouprc.map.txt", | |
57 | + symbol_file: "libcgrouprc.llndk.txt", | |
58 | 58 | export_include_dirs: [ |
59 | 59 | "include", |
60 | 60 | ], |
@@ -27,6 +27,11 @@ uint32_t ACgroupController_getVersion(const ACgroupController* controller) { | ||
27 | 27 | return controller->version(); |
28 | 28 | } |
29 | 29 | |
30 | +uint32_t ACgroupController_getFlags(const ACgroupController* controller) { | |
31 | + CHECK(controller != nullptr); | |
32 | + return controller->flags(); | |
33 | +} | |
34 | + | |
30 | 35 | const char* ACgroupController_getName(const ACgroupController* controller) { |
31 | 36 | CHECK(controller != nullptr); |
32 | 37 | return controller->name(); |
@@ -66,6 +66,18 @@ __attribute__((warn_unused_result)) uint32_t ACgroupController_getVersion(const | ||
66 | 66 | __INTRODUCED_IN(29); |
67 | 67 | |
68 | 68 | /** |
69 | + * Flag bitmask used in ACgroupController_getFlags | |
70 | + */ | |
71 | +#define CGROUPRC_CONTROLLER_FLAG_MOUNTED 0x1 | |
72 | + | |
73 | +/** | |
74 | + * Returns the flags bitmask of the given controller. | |
75 | + * If the given controller is null, return 0. | |
76 | + */ | |
77 | +__attribute__((warn_unused_result)) uint32_t ACgroupController_getFlags(const ACgroupController*) | |
78 | + __INTRODUCED_IN(29); | |
79 | + | |
80 | +/** | |
69 | 81 | * Returns the name of the given controller. |
70 | 82 | * If the given controller is null, return nullptr. |
71 | 83 | */ |
@@ -4,6 +4,7 @@ LIBCGROUPRC { # introduced=29 | ||
4 | 4 | ACgroupFile_getControllerCount; |
5 | 5 | ACgroupFile_getController; |
6 | 6 | ACgroupController_getVersion; |
7 | + ACgroupController_getFlags; | |
7 | 8 | ACgroupController_getName; |
8 | 9 | ACgroupController_getPath; |
9 | 10 | local: |
@@ -20,12 +20,19 @@ namespace android { | ||
20 | 20 | namespace cgrouprc { |
21 | 21 | namespace format { |
22 | 22 | |
23 | -CgroupController::CgroupController(uint32_t version, const std::string& name, | |
24 | - const std::string& path) { | |
23 | +CgroupController::CgroupController() : version_(0), flags_(0) { | |
24 | + memset(name_, 0, sizeof(name_)); | |
25 | + memset(path_, 0, sizeof(path_)); | |
26 | +} | |
27 | + | |
28 | +CgroupController::CgroupController(uint32_t version, uint32_t flags, const std::string& name, | |
29 | + const std::string& path) | |
30 | + : CgroupController() { | |
25 | 31 | // strlcpy isn't available on host. Although there is an implementation |
26 | 32 | // in licutils, libcutils itself depends on libcgrouprc_format, causing |
27 | 33 | // a circular dependency. |
28 | 34 | version_ = version; |
35 | + flags_ = flags; | |
29 | 36 | strncpy(name_, name.c_str(), sizeof(name_) - 1); |
30 | 37 | name_[sizeof(name_) - 1] = '\0'; |
31 | 38 | strncpy(path_, path.c_str(), sizeof(path_) - 1); |
@@ -36,6 +43,10 @@ uint32_t CgroupController::version() const { | ||
36 | 43 | return version_; |
37 | 44 | } |
38 | 45 | |
46 | +uint32_t CgroupController::flags() const { | |
47 | + return flags_; | |
48 | +} | |
49 | + | |
39 | 50 | const char* CgroupController::name() const { |
40 | 51 | return name_; |
41 | 52 | } |
@@ -44,6 +55,10 @@ const char* CgroupController::path() const { | ||
44 | 55 | return path_; |
45 | 56 | } |
46 | 57 | |
58 | +void CgroupController::set_flags(uint32_t flags) { | |
59 | + flags_ = flags; | |
60 | +} | |
61 | + | |
47 | 62 | } // namespace format |
48 | 63 | } // namespace cgrouprc |
49 | 64 | } // namespace android |
@@ -26,18 +26,23 @@ namespace format { | ||
26 | 26 | // Minimal controller description to be mmapped into process address space |
27 | 27 | struct CgroupController { |
28 | 28 | public: |
29 | - CgroupController() {} | |
30 | - CgroupController(uint32_t version, const std::string& name, const std::string& path); | |
29 | + CgroupController(); | |
30 | + CgroupController(uint32_t version, uint32_t flags, const std::string& name, | |
31 | + const std::string& path); | |
31 | 32 | |
32 | 33 | uint32_t version() const; |
34 | + uint32_t flags() const; | |
33 | 35 | const char* name() const; |
34 | 36 | const char* path() const; |
35 | 37 | |
38 | + void set_flags(uint32_t flags); | |
39 | + | |
36 | 40 | private: |
37 | 41 | static constexpr size_t CGROUP_NAME_BUF_SZ = 16; |
38 | 42 | static constexpr size_t CGROUP_PATH_BUF_SZ = 32; |
39 | 43 | |
40 | 44 | uint32_t version_; |
45 | + uint32_t flags_; | |
41 | 46 | char name_[CGROUP_NAME_BUF_SZ]; |
42 | 47 | char path_[CGROUP_PATH_BUF_SZ]; |
43 | 48 | }; |
@@ -106,8 +106,7 @@ bool UsePerAppMemcg() { | ||
106 | 106 | } |
107 | 107 | |
108 | 108 | static bool isMemoryCgroupSupported() { |
109 | - std::string cgroup_name; | |
110 | - static bool memcg_supported = CgroupMap::GetInstance().FindController("memory").HasValue(); | |
109 | + static bool memcg_supported = CgroupMap::GetInstance().FindController("memory").IsUsable(); | |
111 | 110 | |
112 | 111 | return memcg_supported; |
113 | 112 | } |
@@ -151,19 +151,19 @@ int set_sched_policy(int tid, SchedPolicy policy) { | ||
151 | 151 | } |
152 | 152 | |
153 | 153 | bool cpusets_enabled() { |
154 | - static bool enabled = (CgroupMap::GetInstance().FindController("cpuset").HasValue()); | |
154 | + static bool enabled = (CgroupMap::GetInstance().FindController("cpuset").IsUsable()); | |
155 | 155 | return enabled; |
156 | 156 | } |
157 | 157 | |
158 | 158 | bool schedboost_enabled() { |
159 | - static bool enabled = (CgroupMap::GetInstance().FindController("schedtune").HasValue()); | |
159 | + static bool enabled = (CgroupMap::GetInstance().FindController("schedtune").IsUsable()); | |
160 | 160 | return enabled; |
161 | 161 | } |
162 | 162 | |
163 | 163 | static int getCGroupSubsys(int tid, const char* subsys, std::string& subgroup) { |
164 | 164 | auto controller = CgroupMap::GetInstance().FindController(subsys); |
165 | 165 | |
166 | - if (!controller.HasValue()) return -1; | |
166 | + if (!controller.IsUsable()) return -1; | |
167 | 167 | |
168 | 168 | if (!controller.GetTaskGroup(tid, &subgroup)) { |
169 | 169 | LOG(ERROR) << "Failed to find cgroup for tid " << tid; |
@@ -32,6 +32,8 @@ class CgroupDescriptor { | ||
32 | 32 | std::string uid() const { return uid_; } |
33 | 33 | std::string gid() const { return gid_; } |
34 | 34 | |
35 | + void set_mounted(bool mounted); | |
36 | + | |
35 | 37 | private: |
36 | 38 | format::CgroupController controller_; |
37 | 39 | mode_t mode_ = 0; |
@@ -35,6 +35,7 @@ | ||
35 | 35 | #include <android-base/properties.h> |
36 | 36 | #include <android-base/stringprintf.h> |
37 | 37 | #include <android-base/unique_fd.h> |
38 | +#include <android/cgrouprc.h> | |
38 | 39 | #include <json/reader.h> |
39 | 40 | #include <json/value.h> |
40 | 41 | #include <processgroup/format/cgroup_file.h> |
@@ -267,7 +268,17 @@ static bool WriteRcFile(const std::map<std::string, CgroupDescriptor>& descripto | ||
267 | 268 | CgroupDescriptor::CgroupDescriptor(uint32_t version, const std::string& name, |
268 | 269 | const std::string& path, mode_t mode, const std::string& uid, |
269 | 270 | const std::string& gid) |
270 | - : controller_(version, name, path), mode_(mode), uid_(uid), gid_(gid) {} | |
271 | + : controller_(version, 0, name, path), mode_(mode), uid_(uid), gid_(gid) {} | |
272 | + | |
273 | +void CgroupDescriptor::set_mounted(bool mounted) { | |
274 | + uint32_t flags = controller_.flags(); | |
275 | + if (mounted) { | |
276 | + flags |= CGROUPRC_CONTROLLER_FLAG_MOUNTED; | |
277 | + } else { | |
278 | + flags &= ~CGROUPRC_CONTROLLER_FLAG_MOUNTED; | |
279 | + } | |
280 | + controller_.set_flags(flags); | |
281 | +} | |
271 | 282 | |
272 | 283 | } // namespace cgrouprc |
273 | 284 | } // namespace android |
@@ -296,10 +307,11 @@ bool CgroupSetup() { | ||
296 | 307 | } |
297 | 308 | |
298 | 309 | // setup cgroups |
299 | - for (const auto& [name, descriptor] : descriptors) { | |
300 | - if (!SetupCgroup(descriptor)) { | |
310 | + for (auto& [name, descriptor] : descriptors) { | |
311 | + if (SetupCgroup(descriptor)) { | |
312 | + descriptor.set_mounted(true); | |
313 | + } else { | |
301 | 314 | // issue a warning and proceed with the next cgroup |
302 | - // TODO: mark the descriptor as invalid and skip it in WriteRcFile() | |
303 | 315 | LOG(WARNING) << "Failed to setup " << name << " cgroup"; |
304 | 316 | } |
305 | 317 | } |