lmkd: Add support for cgroups v2 memcg hierarchy
Use the /sys/fs/cgroup/uid_%u/pid_%u path instead of
/dev/memcg/apps/uid_%u/pid_%u" if the memcg controller is mounted in the
v2 cgroup hierarchy. Skip the code that refers to memcg attributes that
only exist in the cgroup v1 hierarchy when using the v2 memcg. Complain
if it is attempted to use the old kill strategy in combination with
memcg v2 since only the new strategy is compatible with the v2 cgroup
hiearchy.
Bug: 213617178
Test: Tested lmkd inside the Cuttlefish emulator. Triggered an
Test: out-of-memory condition as follows:
Test: i=0; while [ $i -lt 16 ]; do dd if=/dev/zero of=/dev/null bs=1G count=1 & ((i++)) done
Test: That caused the following output to appear in logcat:
Test: 02-03 18:13:02.772 241 241 I lowmemorykiller: Kill 'com.android.packageinstaller' (3031), uid 10022, oom_score_adj 975 to free 29348kB rss, 21232kB swap; reason: min watermark is breached and swap is low (135016kB < 150384kB)
Test: 02-03 18:13:02.772 241 241 I killinfo: [3031,10022,975,0,29348,3,73644,98460,8,1000,33448,40220,1503848,135016,81720,1387040,27268,29520,50348,103164,20176,57664,0,0,0,519,103,5,0,21232,30016,0,2]
Test: From the kernel log:
Test: [ 302.834958] Out of memory: Killed process 3017 (ADB-JDWP Connec) total-vm:13522856kB, anon-rss:0kB, file-rss:0kB, shmem-rss:560kB, UID:10052 pgtables:1008kB oom_score_adj:975
Test: [ 303.223702] Out of memory: Killed process 2859 (HeapTaskDaemon) total-vm:13534452kB, anon-rss:0kB, file-rss:0kB, shmem-rss:560kB, UID:10051 pgtables:1060kB oom_score_adj:965
Test: [ 303.478833] Out of memory: Killed process 2816 (Signal Catcher) total-vm:13524108kB, anon-rss:0kB, file-rss:0kB, shmem-rss:564kB, UID:10073 pgtables:1016kB oom_score_adj:965
Test: [ 304.823796] Out of memory: Killed process 2438 (ReferenceQueueD) total-vm:13529180kB, anon-rss:0kB, file-rss:0kB, shmem-rss:568kB, UID:10015 pgtables:1056kB oom_score_adj:955
Test: [ 305.226728] Out of memory: Killed process 3126 (DefaultDispatch) total-vm:13532596kB, anon-rss:0kB, file-rss:0kB, shmem-rss:528kB, UID:10019 pgtables:1064kB oom_score_adj:945
Test: [ 305.935615] Out of memory: Killed process 2637 (Jit thread pool) total-vm:13523084kB, anon-rss:0kB, file-rss:0kB, shmem-rss:0kB, UID:10024 pgtables:1036kB oom_score_adj:935
Test: [ 307.055895] Out of memory: Killed process 2063 (HeapTaskDaemon) total-vm:13755876kB, anon-rss:0kB, file-rss:0kB, shmem-rss:11600kB, UID:10074 pgtables:1552kB oom_score_adj:0
Test: [ 307.398512] Out of memory: Killed process 2298 (rs.media.module) total-vm:13560404kB, anon-rss:12924kB, file-rss:0kB, shmem-rss:720kB, UID:10076 pgtables:1156kB oom_score_adj:-700
Test: [ 309.888679] Out of memory: Killed process 1745 (droid.bluetooth) total-vm:13720424kB, anon-rss:11084kB, file-rss:0kB, shmem-rss:208kB, UID:1002 pgtables:1220kB oom_score_adj:-700
Test: [ 311.050133] Out of memory: Killed process 1759 (ndroid.systemui) total-vm:13852268kB, anon-rss:26468kB, file-rss:0kB, shmem-rss:6988kB, UID:10075 pgtables:1628kB oom_score_adj:-800
Test: [ 313.520057] Out of memory: Killed process 2000 (m.android.phone) total-vm:13593404kB, anon-rss:14600kB, file-rss:236kB, shmem-rss:340kB, UID:1001 pgtables:1312kB oom_score_adj:-800
Test: [ 314.337744] Out of memory: Killed process 1911 (rkstack.process) total-vm:13540420kB, anon-rss:8232kB, file-rss:0kB, shmem-rss:180kB, UID:1073 pgtables:1128kB oom_score_adj:-800
Test: [ 314.745542] Out of memory: Killed process 1984 (com.android.se) total-vm:13525236kB, anon-rss:6944kB, file-rss:0kB, shmem-rss:188kB, UID:1068 pgtables:1012kB oom_score_adj:-800
Test: [ 315.007212] Out of memory: Killed process 677 (system_server) total-vm:15049836kB, anon-rss:1856kB, file-rss:0kB, shmem-rss:240kB, UID:1000 pgtables:2084kB oom_score_adj:-900
Change-Id: I78821bcd332af7b3f642f037faa2df15a937dc26
Signed-off-by: Bart Van Assche <bvanassche@google.com>
diff --git a/lmkd.cpp b/lmkd.cpp
index 6133938..741e891 100644
--- a/lmkd.cpp
+++ b/lmkd.cpp
@@ -3154,14 +3154,44 @@
mpevfd[level] = -1;
}
+enum class MemcgVersion {
+ kNotFound,
+ kV1,
+ kV2,
+};
+
+static MemcgVersion __memcg_version() {
+ std::string cgroupv2_path, memcg_path;
+
+ if (!CgroupGetControllerPath("memory", &memcg_path)) {
+ return MemcgVersion::kNotFound;
+ }
+ return CgroupGetControllerPath(CGROUPV2_CONTROLLER_NAME, &cgroupv2_path) &&
+ cgroupv2_path == memcg_path
+ ? MemcgVersion::kV2
+ : MemcgVersion::kV1;
+}
+
+static MemcgVersion memcg_version() {
+ static MemcgVersion version = __memcg_version();
+
+ return version;
+}
+
static bool init_psi_monitors() {
/*
* When PSI is used on low-ram devices or on high-end devices without memfree levels
- * use new kill strategy based on zone watermarks, free swap and thrashing stats
+ * use new kill strategy based on zone watermarks, free swap and thrashing stats.
+ * Also use the new strategy if memcg has not been mounted in the v1 cgroups hiearchy since
+ * the old strategy relies on memcg attributes that are available only in the v1 cgroups
+ * hiearchy.
*/
bool use_new_strategy =
GET_LMK_PROPERTY(bool, "use_new_strategy", low_ram_device || !use_minfree_levels);
-
+ if (!use_new_strategy && memcg_version() != MemcgVersion::kV1) {
+ ALOGE("Old kill strategy can only be used with v1 cgroup hierarchy");
+ return false;
+ }
/* In default PSI mode override stall amounts using system properties */
if (use_new_strategy) {
/* Do not use low pressure level */
@@ -3186,6 +3216,13 @@
}
static bool init_mp_common(enum vmpressure_level level) {
+ // The implementation of this function relies on memcg statistics that are only available in the
+ // v1 cgroup hierarchy.
+ if (memcg_version() != MemcgVersion::kV1) {
+ ALOGE("%s: global monitoring is only available for the v1 cgroup hierarchy", __func__);
+ return false;
+ }
+
int mpfd;
int evfd;
int evctlfd;