Merge "Explicitly mention a confusing proto3 infelicity." into main am: 3a0c095253 am: b76d6fd9b1
Original change: https://android-review.googlesource.com/c/platform/system/core/+/3531073
Change-Id: Ib9297819fe815c06142e6dd4a9fc61a5b71e353d
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index f47c317..ab6430f 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -8,4 +8,3 @@
rustfmt = --config-path=rustfmt.toml
[Hook Scripts]
-aosp_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "."
diff --git a/init/Android.bp b/init/Android.bp
index b209c47..9edbe9d 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -292,6 +292,9 @@
"make_f2fs",
"mke2fs",
"sload_f2fs",
+
+ // TODO: Revert after go/android-memcgv2-exp b/386797433
+ "memcgv2_activation_depth",
],
}
@@ -691,3 +694,10 @@
default: ["init_first_stage"],
}),
}
+
+// TODO: Revert after go/android-memcgv2-exp b/386797433
+sh_binary {
+ name: "memcgv2_activation_depth",
+ src: "memcgv2_activation_depth.sh",
+ filename_from_src: true,
+}
diff --git a/init/memcgv2_activation_depth.sh b/init/memcgv2_activation_depth.sh
new file mode 100644
index 0000000..91d215d
--- /dev/null
+++ b/init/memcgv2_activation_depth.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+
+# This script adjusts overrides of the memcg v2 MaxActivationDepth value at runtime.
+# The override value needs to be accessible starting very early in the Android boot, where aconfig
+# flags and system properties do not work. A file on /metadata is used instead.
+
+# The kernel allows this to be as high as 65535, but our Android hierarchy is never that deep.
+MAX_ALLOWED_DEPTH=5
+
+# Store overridden MaxActivationDepths here for libprocessgroup to find them
+OVERRIDE_FILE_PATH="/metadata/libprocessgroup/memcg_v2_max_activation_depth"
+
+if [ "$#" -ne 1 ]
+then
+ echo "Usage: $0 <memcg v2 MaxActivationDepth value>"
+ exit 99
+fi
+
+max_activation_depth=$1
+
+if [[ $max_activation_depth != +([0-9]) ]]
+then
+ echo "MaxActivationDepth value must be a positive integer: $max_activation_depth"
+ exit 98
+fi
+
+if [ $max_activation_depth -lt 0 ]
+then
+ echo "Negative MaxActivationDepth is invalid: $max_activation_depth"
+ exit 97
+fi
+
+if [ $max_activation_depth -gt $MAX_ALLOWED_DEPTH ]
+then
+ echo "MaxActivationDepth is too large: $max_activation_depth"
+ exit 96
+fi
+
+grep memory /sys/fs/cgroup/cgroup.controllers
+if [ $? -ne 0 ]
+then
+ echo "memcg v2 is not available on this device!"
+ exit 95
+fi
+
+current_activation_depth=$(cat $OVERRIDE_FILE_PATH)
+if [ $? -ne 0 ]
+then
+ # Find the default activation depth in the absence of any properties / overrides.
+ #
+ # To do this 100% correctly requires JSON parsing which we don't really want to do here.
+ # We know that this will be called only for Pixel (for a limited-duration experiment), and that
+ # Pixel does not override cgroups.json, therefore we can assume that the system cgroups.json has
+ # only a single MaxActivationDepth entry which corresponds to the v2 memory controller. So we
+ # can just grep for the default value.
+ default_activation_depth=$(grep MaxActivationDepth /system/etc/cgroups.json | tr -dc '0-9')
+ if [ $? -ne 0 -o $default_activation_depth -gt $MAX_ALLOWED_DEPTH ]
+ then
+ # If MaxActivationDepth is not present, libprocessgroup does not limit how deep it will activate
+ default_activation_depth=$MAX_ALLOWED_DEPTH
+ fi
+ current_activation_depth=$default_activation_depth
+fi
+
+# libprocessgroup will pick this up for all future cgroup creations, including on the next boot
+echo $max_activation_depth > $OVERRIDE_FILE_PATH
+chmod ugo+r $OVERRIDE_FILE_PATH
+
+if [ $max_activation_depth -lt $current_activation_depth ]
+then
+ # We can deactivate memcgs which are deeper than the new depth value, however that would leave
+ # behind zombie memcgs which would ruin the metrics produced from this device. The only way to
+ # eliminate those zombies is to remove the entire cgroup, which we cannot do without killing
+ # all the contained processes. So the only real option we have is to reboot here, but that would
+ # look like a random reboot to users. So don't do anything now. Wait until the next reboot for
+ # the new setting to be applied.
+ :
+elif [ $max_activation_depth -gt $current_activation_depth ]
+then
+ for d in $(seq $max_activation_depth)
+ do
+ for f in $(find /sys/fs/cgroup/ -mindepth $d -maxdepth $d -name cgroup.subtree_control)
+ do
+ echo "+memory" > $f
+ done
+ done
+fi
diff --git a/libprocessgroup/util/util.cpp b/libprocessgroup/util/util.cpp
index c772bc5..a15a44f 100644
--- a/libprocessgroup/util/util.cpp
+++ b/libprocessgroup/util/util.cpp
@@ -18,15 +18,19 @@
#include <algorithm>
#include <iterator>
+#include <mutex>
#include <optional>
#include <string_view>
#include <mntent.h>
+#include <unistd.h>
#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <json/reader.h>
#include <json/value.h>
@@ -174,6 +178,38 @@
return mounts;
}
+// Keep the override file open to reduce open syscalls, but read it every time.
+// Note that memcgv2_activation_depth.sh can race with us here.
+std::optional<unsigned int> ReadMaxActivationDepthMetadataOverride() {
+ static const char* OVERRIDE_FILE_PATH =
+ "/metadata/libprocessgroup/memcg_v2_max_activation_depth";
+ static int override_fd = open(OVERRIDE_FILE_PATH, O_RDONLY | O_CLOEXEC);
+ static std::mutex mtx;
+
+ std::unique_lock lock(mtx);
+ if (override_fd < 0) {
+ override_fd = open(OVERRIDE_FILE_PATH, O_RDONLY | O_CLOEXEC);
+ if (override_fd < 0) return std::nullopt;
+ }
+
+ std::string depth_str;
+ const bool ret = android::base::ReadFdToString(override_fd, &depth_str);
+ lseek(override_fd, 0, SEEK_SET);
+ lock.unlock();
+
+ if (!ret) {
+ PLOG(ERROR) << "Failed to read max activation depth override";
+ return std::nullopt;
+ }
+
+ unsigned int depth;
+ if (!android::base::ParseUint(android::base::Trim(depth_str), &depth)) {
+ PLOG(ERROR) << "Failed to convert max activation depth override (" << depth_str << ')';
+ return std::nullopt;
+ }
+ return depth;
+}
+
} // anonymous namespace
@@ -235,7 +271,10 @@
bool ActivateControllers(const std::string& path, const CgroupDescriptorMap& descriptors) {
for (const auto& [name, descriptor] : descriptors) {
const uint32_t flags = descriptor.controller()->flags();
- const uint32_t max_activation_depth = descriptor.controller()->max_activation_depth();
+ uint32_t max_activation_depth;
+ std::optional<unsigned int> metadataMaxDepth = ReadMaxActivationDepthMetadataOverride();
+ if (metadataMaxDepth) max_activation_depth = *metadataMaxDepth;
+ else max_activation_depth = descriptor.controller()->max_activation_depth();
const unsigned int depth = GetCgroupDepth(descriptor.controller()->path(), path);
if (flags & CGROUPRC_CONTROLLER_FLAG_NEEDS_ACTIVATION && depth < max_activation_depth) {
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 7d74d12..255ef88 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -614,6 +614,9 @@
mkdir /metadata/staged-install 0770 root system
+ # TODO: Revert after go/android-memcgv2-exp b/386797433
+ mkdir /metadata/libprocessgroup 0775 root system
+
on late-fs
# Ensure that tracefs has the correct permissions.
# This does not work correctly if it is called in post-fs.
@@ -1320,14 +1323,34 @@
# Multi-Gen LRU Experiment
on property:persist.device_config.mglru_native.lru_gen_config=none
write /sys/kernel/mm/lru_gen/enabled 0
+ # Memcg v2 Experiment
+ # TODO: Revert after go/android-memcgv2-exp b/386797433
+ exec - system system -- /system/bin/memcgv2_activation_depth.sh 0
+ setprop persist.device_config.lmkd_native.psi_partial_stall_ms 70
on property:persist.device_config.mglru_native.lru_gen_config=core
- write /sys/kernel/mm/lru_gen/enabled 1
+ write /sys/kernel/mm/lru_gen/enabled y
+ # Memcg v2 Experiment
+ # TODO: Revert after go/android-memcgv2-exp b/386797433
+ exec - system system -- /system/bin/memcgv2_activation_depth.sh 1
+ setprop persist.device_config.lmkd_native.psi_partial_stall_ms 56
on property:persist.device_config.mglru_native.lru_gen_config=core_and_mm_walk
- write /sys/kernel/mm/lru_gen/enabled 3
+ write /sys/kernel/mm/lru_gen/enabled y
+ # Memcg v2 Experiment
+ # TODO: Revert after go/android-memcgv2-exp b/386797433
+ exec - system system -- /system/bin/memcgv2_activation_depth.sh 1
+ setprop persist.device_config.lmkd_native.psi_partial_stall_ms 70
on property:persist.device_config.mglru_native.lru_gen_config=core_and_nonleaf_young
- write /sys/kernel/mm/lru_gen/enabled 5
+ write /sys/kernel/mm/lru_gen/enabled y
+ # Memcg v2 Experiment
+ # TODO: Revert after go/android-memcgv2-exp b/386797433
+ exec - system system -- /system/bin/memcgv2_activation_depth.sh 2
+ setprop persist.device_config.lmkd_native.psi_partial_stall_ms 70
on property:persist.device_config.mglru_native.lru_gen_config=all
- write /sys/kernel/mm/lru_gen/enabled 7
+ write /sys/kernel/mm/lru_gen/enabled y
+ # Memcg v2 Experiment
+ # TODO: Revert after go/android-memcgv2-exp b/386797433
+ exec - system system -- /system/bin/memcgv2_activation_depth.sh 3
+ setprop persist.device_config.lmkd_native.psi_partial_stall_ms 70
# Allow other processes to run `snapshotctl` through `init`. This requires
# `set_prop` permission on `snapshotctl_prop`.
diff --git a/storaged/uid_info.cpp b/storaged/uid_info.cpp
index 0f718de..6f25898 100644
--- a/storaged/uid_info.cpp
+++ b/storaged/uid_info.cpp
@@ -23,13 +23,13 @@
status_t UidInfo::writeToParcel(Parcel* parcel) const {
parcel->writeInt32(uid);
- parcel->writeCString(name.c_str());
+ parcel->writeString8(String8(name.c_str()));
parcel->write(&io, sizeof(io));
parcel->writeInt32(tasks.size());
for (const auto& task_it : tasks) {
parcel->writeInt32(task_it.first);
- parcel->writeCString(task_it.second.comm.c_str());
+ parcel->writeString8(String8(task_it.second.comm.c_str()));
parcel->write(&task_it.second.io, sizeof(task_it.second.io));
}
return OK;
@@ -37,14 +37,14 @@
status_t UidInfo::readFromParcel(const Parcel* parcel) {
uid = parcel->readInt32();
- name = parcel->readCString();
+ name = parcel->readString8().c_str();
parcel->read(&io, sizeof(io));
uint32_t tasks_size = parcel->readInt32();
for (uint32_t i = 0; i < tasks_size; i++) {
task_info task;
task.pid = parcel->readInt32();
- task.comm = parcel->readCString();
+ task.comm = parcel->readString8().c_str();
parcel->read(&task.io, sizeof(task.io));
tasks[task.pid] = task;
}