Merge "Run module code only after KeyMints receive module info" into main
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 858956a..34f2c45 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -335,7 +335,7 @@
ConsumeFd(std::move(output_fd), &result);
ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0+dead)");
- if (mte_supported()) {
+ if (mte_supported() && mte_enabled()) {
// Test that the default TAGGED_ADDR_CTRL value is set.
ASSERT_MATCH(result, R"(tagged_addr_ctrl: 000000000007fff3)"
R"( \(PR_TAGGED_ADDR_ENABLE, PR_MTE_TCF_SYNC, mask 0xfffe\))");
@@ -443,7 +443,7 @@
TEST_P(SizeParamCrasherTest, mte_uaf) {
#if defined(__aarch64__)
- if (!mte_supported()) {
+ if (!mte_supported() || !mte_enabled()) {
GTEST_SKIP() << "Requires MTE";
}
@@ -490,7 +490,7 @@
TEST_P(SizeParamCrasherTest, mte_oob_uaf) {
#if defined(__aarch64__)
- if (!mte_supported()) {
+ if (!mte_supported() || !mte_enabled()) {
GTEST_SKIP() << "Requires MTE";
}
@@ -522,7 +522,7 @@
TEST_P(SizeParamCrasherTest, mte_overflow) {
#if defined(__aarch64__)
- if (!mte_supported()) {
+ if (!mte_supported() || !mte_enabled()) {
GTEST_SKIP() << "Requires MTE";
}
@@ -565,7 +565,7 @@
TEST_P(SizeParamCrasherTest, mte_underflow) {
#if defined(__aarch64__)
- if (!mte_supported()) {
+ if (!mte_supported() || !mte_enabled()) {
GTEST_SKIP() << "Requires MTE";
}
@@ -614,7 +614,7 @@
// unsubtle chaos is sure to result.
// https://man7.org/linux/man-pages/man3/longjmp.3.html
#if defined(__aarch64__)
- if (!mte_supported()) {
+ if (!mte_supported() || !mte_enabled()) {
GTEST_SKIP() << "Requires MTE";
}
@@ -648,7 +648,7 @@
TEST_F(CrasherTest, mte_async) {
#if defined(__aarch64__)
- if (!mte_supported()) {
+ if (!mte_supported() || !mte_enabled()) {
GTEST_SKIP() << "Requires MTE";
}
@@ -678,7 +678,7 @@
TEST_F(CrasherTest, mte_multiple_causes) {
#if defined(__aarch64__)
- if (!mte_supported()) {
+ if (!mte_supported() || !mte_enabled()) {
GTEST_SKIP() << "Requires MTE";
}
@@ -764,7 +764,7 @@
TEST_F(CrasherTest, mte_register_tag_dump) {
#if defined(__aarch64__)
- if (!mte_supported()) {
+ if (!mte_supported() || !mte_enabled()) {
GTEST_SKIP() << "Requires MTE";
}
@@ -797,7 +797,7 @@
TEST_F(CrasherTest, mte_fault_tag_dump_front_truncated) {
#if defined(__aarch64__)
- if (!mte_supported()) {
+ if (!mte_supported() || !mte_enabled()) {
GTEST_SKIP() << "Requires MTE";
}
@@ -828,7 +828,7 @@
TEST_F(CrasherTest, mte_fault_tag_dump) {
#if defined(__aarch64__)
- if (!mte_supported()) {
+ if (!mte_supported() || !mte_enabled()) {
GTEST_SKIP() << "Requires MTE";
}
@@ -862,7 +862,7 @@
TEST_F(CrasherTest, mte_fault_tag_dump_rear_truncated) {
#if defined(__aarch64__)
- if (!mte_supported()) {
+ if (!mte_supported() || !mte_enabled()) {
GTEST_SKIP() << "Requires MTE";
}
diff --git a/debuggerd/libdebuggerd/test/tombstone_proto_to_text_test.cpp b/debuggerd/libdebuggerd/test/tombstone_proto_to_text_test.cpp
index aad209a..988ca0c 100644
--- a/debuggerd/libdebuggerd/test/tombstone_proto_to_text_test.cpp
+++ b/debuggerd/libdebuggerd/test/tombstone_proto_to_text_test.cpp
@@ -175,3 +175,8 @@
ProtoToString();
EXPECT_MATCH(text_, "\\(BuildId: 0123456789abcdef\\)\\nSYMBOLIZE 0123456789abcdef 12345\\n");
}
+
+TEST_F(TombstoneProtoToTextTest, uid) {
+ ProtoToString();
+ EXPECT_MATCH(text_, "\\nLOG uid: 0\\n");
+}
diff --git a/fs_mgr/README.overlayfs.md b/fs_mgr/README.overlayfs.md
index 94b2f8c..df5d775 100644
--- a/fs_mgr/README.overlayfs.md
+++ b/fs_mgr/README.overlayfs.md
@@ -79,16 +79,15 @@
done file by file. Be mindful of wasted space. For example, defining
**BOARD_IMAGE_PARTITION_RESERVED_SIZE** has a negative impact on the
right-sizing of images and requires more free dynamic partition space.
-- The kernel requires **CONFIG_OVERLAY_FS=y**. If the kernel version is higher
- than 4.4, it requires source to be in line with android-common kernels.
- The patch series is available on the upstream mailing list and the latest as
- of Sep 5 2019 is https://www.spinics.net/lists/linux-mtd/msg08331.html
- This patch adds an override_creds _mount_ option to OverlayFS that
- permits legacy behavior for systems that do not have overlapping
- sepolicy rules, principals of least privilege, which is how Android behaves.
- For 4.19 and higher a rework of the xattr handling to deal with recursion
- is required. https://patchwork.kernel.org/patch/11117145/ is a start of that
- adjustment.
+- The kernel requires **CONFIG_OVERLAY_FS=y**. overlayfs is used 'as is' as of
+ android 16, no modifications are required.
+- In order for overlayfs to work, overlays are mounted in the overlay_remounter
+ domain, defined here: system/sepolicy/private/overlay_remounter.te. This domain
+ must have full access to the files on the underlying volumes, add any other file
+ and directory types here
+- For devices with dynamic partitions, we use a simpler logic to decide which
+ partitions to remount, being all logical ones. In case this isn't correct,
+ we added the overlay=on and overlay=off mount flags to allow detailed control.
- _adb enable-verity_ frees up OverlayFS and reverts the device to the state
prior to content updates. The update engine performs a full OTA.
- _adb remount_ overrides are incompatible with OTA resources, so the update
diff --git a/fs_mgr/fs_mgr_overlayfs_mount.cpp b/fs_mgr/fs_mgr_overlayfs_mount.cpp
index 69d3161..762e70d 100644
--- a/fs_mgr/fs_mgr_overlayfs_mount.cpp
+++ b/fs_mgr/fs_mgr_overlayfs_mount.cpp
@@ -49,6 +49,10 @@
#include "fs_mgr_overlayfs_mount.h"
#include "fs_mgr_priv.h"
+// Flag to simplify algorithm for choosing which partitions to overlay to simply overlay
+// all dynamic partitions
+constexpr bool overlay_dynamic_partitions_only = true;
+
using namespace std::literals;
using namespace android::fs_mgr;
using namespace android::storage_literals;
@@ -669,6 +673,19 @@
Fstab candidates;
for (const auto& entry : fstab) {
+ // fstab overlay flag overrides all other behavior
+ if (entry.fs_mgr_flags.overlay_off) continue;
+ if (entry.fs_mgr_flags.overlay_on) {
+ candidates.push_back(entry);
+ continue;
+ }
+
+ // overlay_dynamic_partitions_only simplifies logic to overlay exactly dynamic partitions
+ if (overlay_dynamic_partitions_only) {
+ if (entry.fs_mgr_flags.logical) candidates.push_back(entry);
+ continue;
+ }
+
// Filter out partitions whose type doesn't match what's mounted.
// This avoids spammy behavior on devices which can mount different
// filesystems for each partition.
diff --git a/fs_mgr/libfstab/fstab.cpp b/fs_mgr/libfstab/fstab.cpp
index 010fbc8..ec23ce5 100644
--- a/fs_mgr/libfstab/fstab.cpp
+++ b/fs_mgr/libfstab/fstab.cpp
@@ -209,6 +209,8 @@
CheckFlag("metadata_csum", ext_meta_csum);
CheckFlag("fscompress", fs_compress);
CheckFlag("overlayfs_remove_missing_lowerdir", overlayfs_remove_missing_lowerdir);
+ CheckFlag("overlay=on", overlay_on);
+ CheckFlag("overlay=off", overlay_off);
#undef CheckFlag
diff --git a/fs_mgr/libfstab/include/fstab/fstab.h b/fs_mgr/libfstab/include/fstab/fstab.h
index 0ff3188..4924ae3 100644
--- a/fs_mgr/libfstab/include/fstab/fstab.h
+++ b/fs_mgr/libfstab/include/fstab/fstab.h
@@ -87,6 +87,8 @@
bool fs_compress : 1;
bool overlayfs_remove_missing_lowerdir : 1;
bool is_zoned : 1;
+ bool overlay_on : 1;
+ bool overlay_off : 1;
} fs_mgr_flags = {};
bool is_encryptable() const { return fs_mgr_flags.crypt; }
diff --git a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
index 6f31251..94d8e9f 100644
--- a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
+++ b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
@@ -17,7 +17,6 @@
option optimize_for = LITE_RUNTIME;
-// Next: 4
enum SnapshotState {
// No snapshot is found.
NONE = 0;
@@ -34,7 +33,6 @@
MERGE_COMPLETED = 3;
}
-// Next: 3
enum MergePhase {
// No merge is in progress.
NO_MERGE = 0;
@@ -46,7 +44,6 @@
SECOND_PHASE = 2;
}
-// Next: 13
message SnapshotStatus {
// Name of the snapshot. This is usually the name of the snapshotted
// logical partition; for example, "system_b".
@@ -126,14 +123,11 @@
reserved 18;
- // Blocks size to be verified at once
- uint64 verify_block_size = 19;
+ reserved 19;
- // Default value is 2, configures threads to do verification phase
- uint32 num_verify_threads = 20;
+ reserved 20;
}
-// Next: 8
enum UpdateState {
// No update or merge is in progress.
None = 0;
@@ -162,7 +156,6 @@
Cancelled = 7;
};
-// Next 14:
//
// To understand the source of each failure, read snapshot.cpp. To handle new
// sources of failure, avoid reusing an existing code; add a new code instead.
@@ -190,7 +183,6 @@
WrongMergeCountConsistencyCheck = 20;
};
-// Next: 8
message SnapshotUpdateStatus {
UpdateState state = 1;
@@ -235,9 +227,17 @@
// Number of worker threads to serve I/O from dm-user
uint32 num_worker_threads = 14;
+
+ // Block size to be verified after OTA reboot
+ uint64 verify_block_size = 15;
+
+ // Default value is 3, configures threads to do verification phase
+ uint32 num_verification_threads = 16;
+
+ // Skips verification of partitions
+ bool skip_verification = 17;
}
-// Next: 10
message SnapshotMergeReport {
// Status of the update after the merge attempts.
UpdateState state = 1;
@@ -285,12 +285,12 @@
}
message VerityHash {
- // Partition name
- string partition_name = 1;
+ // Partition name
+ string partition_name = 1;
- // Salt used for verity hashes
- string salt = 2;
+ // Salt used for verity hashes
+ string salt = 2;
- // sha256 hash values of each block in the image
- repeated bytes block_hash = 3;
+ // sha256 hash values of each block in the image
+ repeated bytes block_hash = 3;
}
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 8a8100c..4520b21 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -859,12 +859,21 @@
// Check if direct reads are enabled for the source image
bool UpdateUsesODirect(LockedFile* lock);
+ // Check if we skip the verification of the target image
+ bool UpdateUsesSkipVerification(LockedFile* lock);
+
// Get value of maximum cow op merge size
uint32_t GetUpdateCowOpMergeSize(LockedFile* lock);
// Get number of threads to perform post OTA boot verification
uint32_t GetUpdateWorkerCount(LockedFile* lock);
+ // Get the verification block size
+ uint32_t GetVerificationBlockSize(LockedFile* lock);
+
+ // Get the number of verification threads
+ uint32_t GetNumVerificationThreads(LockedFile* lock);
+
// Wrapper around libdm, with diagnostics.
bool DeleteDeviceIfExists(const std::string& name,
const std::chrono::milliseconds& timeout_ms = {});
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h
index 8a70400..79443b2 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h
@@ -64,6 +64,7 @@
public:
// Not thread safe.
static SnapshotMergeStats* GetInstance(SnapshotManager& manager);
+ SnapshotMergeStats(const std::string& path);
// ISnapshotMergeStats overrides
bool Start() override;
@@ -88,7 +89,6 @@
private:
bool ReadState();
bool DeleteState();
- SnapshotMergeStats(const std::string& path);
std::string path_;
SnapshotMergeReport report_;
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index adfb16b..fa2f569 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -1792,6 +1792,15 @@
if (worker_count != 0) {
snapuserd_argv->emplace_back("-worker_count=" + std::to_string(worker_count));
}
+ uint32_t verify_block_size = GetVerificationBlockSize(lock.get());
+ if (verify_block_size != 0) {
+ snapuserd_argv->emplace_back("-verify_block_size=" + std::to_string(verify_block_size));
+ }
+ uint32_t num_verify_threads = GetNumVerificationThreads(lock.get());
+ if (num_verify_threads != 0) {
+ snapuserd_argv->emplace_back("-num_verify_threads=" +
+ std::to_string(num_verify_threads));
+ }
}
size_t num_cows = 0;
@@ -2225,6 +2234,11 @@
return update_status.o_direct();
}
+bool SnapshotManager::UpdateUsesSkipVerification(LockedFile* lock) {
+ SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
+ return update_status.skip_verification();
+}
+
uint32_t SnapshotManager::GetUpdateCowOpMergeSize(LockedFile* lock) {
SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
return update_status.cow_op_merge_size();
@@ -2235,6 +2249,16 @@
return update_status.num_worker_threads();
}
+uint32_t SnapshotManager::GetVerificationBlockSize(LockedFile* lock) {
+ SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
+ return update_status.verify_block_size();
+}
+
+uint32_t SnapshotManager::GetNumVerificationThreads(LockedFile* lock) {
+ SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
+ return update_status.num_verification_threads();
+}
+
bool SnapshotManager::MarkSnapuserdFromSystem() {
auto path = GetSnapuserdFromSystemPath();
@@ -3225,8 +3249,11 @@
status.set_io_uring_enabled(old_status.io_uring_enabled());
status.set_legacy_snapuserd(old_status.legacy_snapuserd());
status.set_o_direct(old_status.o_direct());
+ status.set_skip_verification(old_status.skip_verification());
status.set_cow_op_merge_size(old_status.cow_op_merge_size());
status.set_num_worker_threads(old_status.num_worker_threads());
+ status.set_verify_block_size(old_status.verify_block_size());
+ status.set_num_verification_threads(old_status.num_verification_threads());
}
return WriteSnapshotUpdateStatus(lock, status);
}
@@ -3605,6 +3632,10 @@
status.set_o_direct(true);
LOG(INFO) << "o_direct for source image enabled";
}
+ if (GetSkipVerificationProperty()) {
+ status.set_skip_verification(true);
+ LOG(INFO) << "skipping verification of images";
+ }
if (is_legacy_snapuserd) {
status.set_legacy_snapuserd(true);
LOG(INFO) << "Setting legacy_snapuserd to true";
@@ -3613,7 +3644,10 @@
android::base::GetUintProperty<uint32_t>("ro.virtual_ab.cow_op_merge_size", 0));
status.set_num_worker_threads(
android::base::GetUintProperty<uint32_t>("ro.virtual_ab.num_worker_threads", 0));
-
+ status.set_verify_block_size(
+ android::base::GetUintProperty<uint32_t>("ro.virtual_ab.verify_block_size", 0));
+ status.set_num_verification_threads(
+ android::base::GetUintProperty<uint32_t>("ro.virtual_ab.num_verify_threads", 0));
} else if (legacy_compression) {
LOG(INFO) << "Virtual A/B using legacy snapuserd";
} else {
@@ -4049,8 +4083,11 @@
ss << "Using userspace snapshots: " << update_status.userspace_snapshots() << std::endl;
ss << "Using io_uring: " << update_status.io_uring_enabled() << std::endl;
ss << "Using o_direct: " << update_status.o_direct() << std::endl;
+ ss << "Using skip_verification: " << update_status.skip_verification() << std::endl;
ss << "Cow op merge size (0 for uncapped): " << update_status.cow_op_merge_size() << std::endl;
ss << "Worker thread count: " << update_status.num_worker_threads() << std::endl;
+ ss << "Num verification threads: " << update_status.num_verification_threads() << std::endl;
+ ss << "Verify block size: " << update_status.verify_block_size() << std::endl;
ss << "Using XOR compression: " << GetXorCompressionEnabledProperty() << std::endl;
ss << "Current slot: " << device_->GetSlotSuffix() << std::endl;
ss << "Boot indicator: booting from " << GetCurrentSlot() << " slot" << std::endl;
diff --git a/fs_mgr/libsnapshot/snapshot_stats.cpp b/fs_mgr/libsnapshot/snapshot_stats.cpp
index 8e9d9c5..e684d87 100644
--- a/fs_mgr/libsnapshot/snapshot_stats.cpp
+++ b/fs_mgr/libsnapshot/snapshot_stats.cpp
@@ -24,9 +24,12 @@
namespace snapshot {
SnapshotMergeStats* SnapshotMergeStats::GetInstance(SnapshotManager& parent) {
- static SnapshotMergeStats g_instance(parent.GetMergeStateFilePath());
- CHECK_EQ(g_instance.path_, parent.GetMergeStateFilePath());
- return &g_instance;
+ static std::unique_ptr<SnapshotMergeStats> g_instance;
+
+ if (!g_instance || g_instance->path_ != parent.GetMergeStateFilePath()) {
+ g_instance = std::make_unique<SnapshotMergeStats>(parent.GetMergeStateFilePath());
+ }
+ return g_instance.get();
}
SnapshotMergeStats::SnapshotMergeStats(const std::string& path) : path_(path), running_(false) {}
diff --git a/fs_mgr/libsnapshot/snapuserd/Android.bp b/fs_mgr/libsnapshot/snapuserd/Android.bp
index 639116e..9972bc7 100644
--- a/fs_mgr/libsnapshot/snapuserd/Android.bp
+++ b/fs_mgr/libsnapshot/snapuserd/Android.bp
@@ -88,6 +88,7 @@
"libprocessgroup",
"libprocessgroup_util",
"libjsoncpp",
+ "liburing_cpp",
],
export_include_dirs: ["include"],
header_libs: [
@@ -136,6 +137,7 @@
"libext4_utils",
"liburing",
"libzstd",
+ "liburing_cpp",
],
header_libs: [
@@ -222,6 +224,7 @@
"libjsoncpp",
"liburing",
"libz",
+ "liburing_cpp",
],
include_dirs: [
".",
@@ -319,6 +322,7 @@
"libjsoncpp",
"liburing",
"libz",
+ "liburing_cpp",
],
include_dirs: [
".",
diff --git a/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp b/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
index 32e16cc..d29223e 100644
--- a/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
@@ -20,8 +20,13 @@
#include <gflags/gflags.h>
#include <snapuserd/snapuserd_client.h>
+#include <storage_literals/storage_literals.h>
+#include "user-space-merge/snapuserd_core.h"
+
#include "snapuserd_daemon.h"
+using namespace android::storage_literals;
+
DEFINE_string(socket, android::snapshot::kSnapuserdSocket, "Named socket or socket path.");
DEFINE_bool(no_socket, false,
"If true, no socket is used. Each additional argument is an INIT message.");
@@ -30,8 +35,12 @@
DEFINE_bool(user_snapshot, false, "If true, user-space snapshots are used");
DEFINE_bool(io_uring, false, "If true, io_uring feature is enabled");
DEFINE_bool(o_direct, false, "If true, enable direct reads on source device");
+DEFINE_bool(skip_verification, false, "If true, skip verification of partitions");
DEFINE_int32(cow_op_merge_size, 0, "number of operations to be processed at once");
-DEFINE_int32(worker_count, 4, "number of worker threads used to serve I/O requests to dm-user");
+DEFINE_int32(worker_count, android::snapshot::kNumWorkerThreads,
+ "number of worker threads used to serve I/O requests to dm-user");
+DEFINE_int32(verify_block_size, 1_MiB, "block sized used during verification of snapshots");
+DEFINE_int32(num_verify_threads, 3, "number of threads used during verification phase");
namespace android {
namespace snapshot {
@@ -95,9 +104,6 @@
MaskAllSignalsExceptIntAndTerm();
user_server_.SetServerRunning();
- if (FLAGS_io_uring) {
- user_server_.SetIouringEnabled();
- }
if (FLAGS_socket_handoff) {
return user_server_.RunForSocketHandoff();
@@ -110,14 +116,20 @@
}
for (int i = arg_start; i < argc; i++) {
auto parts = android::base::Split(argv[i], ",");
-
if (parts.size() != 4) {
LOG(ERROR) << "Malformed message, expected at least four sub-arguments.";
return false;
}
- auto handler =
- user_server_.AddHandler(parts[0], parts[1], parts[2], parts[3], FLAGS_worker_count,
- FLAGS_o_direct, FLAGS_cow_op_merge_size);
+ HandlerOptions options = {
+ .num_worker_threads = FLAGS_worker_count,
+ .use_iouring = FLAGS_io_uring,
+ .o_direct = FLAGS_o_direct,
+ .skip_verification = FLAGS_skip_verification,
+ .cow_op_merge_size = static_cast<uint32_t>(FLAGS_cow_op_merge_size),
+ .verify_block_size = static_cast<uint32_t>(FLAGS_verify_block_size),
+ .num_verification_threads = static_cast<uint32_t>(FLAGS_num_verify_threads),
+ };
+ auto handler = user_server_.AddHandler(parts[0], parts[1], parts[2], parts[3], options);
if (!handler || !user_server_.StartHandler(parts[0])) {
return false;
}
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.cpp
index ef4ba93..c15ac6b 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.cpp
@@ -40,8 +40,9 @@
bool Extractor::Init() {
auto opener = factory_.CreateTestOpener(control_name_);
+ HandlerOptions options;
handler_ = std::make_shared<SnapshotHandler>(control_name_, cow_path_, base_path_, base_path_,
- opener, 1, false, false, false, 0);
+ opener, options);
if (!handler_->InitCowDevice()) {
return false;
}
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.h
index 65285b1..814bc85 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.h
@@ -14,8 +14,8 @@
#pragma once
+#include <future>
#include <string>
-#include <thread>
#include <android-base/unique_fd.h>
#include "merge_worker.h"
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
index cf507e3..6b6f071 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
@@ -52,11 +52,9 @@
std::shared_ptr<HandlerThread> SnapshotHandlerManager::AddHandler(
const std::string& misc_name, const std::string& cow_device_path,
const std::string& backing_device, const std::string& base_path_merge,
- std::shared_ptr<IBlockServerOpener> opener, int num_worker_threads, bool use_iouring,
- bool o_direct, uint32_t cow_op_merge_size) {
- auto snapuserd = std::make_shared<SnapshotHandler>(
- misc_name, cow_device_path, backing_device, base_path_merge, opener, num_worker_threads,
- use_iouring, perform_verification_, o_direct, cow_op_merge_size);
+ std::shared_ptr<IBlockServerOpener> opener, HandlerOptions options) {
+ auto snapuserd = std::make_shared<SnapshotHandler>(misc_name, cow_device_path, backing_device,
+ base_path_merge, opener, options);
if (!snapuserd->InitCowDevice()) {
LOG(ERROR) << "Failed to initialize Snapuserd";
return nullptr;
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h
index 89f3461..d10d8e8 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h
@@ -27,6 +27,16 @@
namespace android {
namespace snapshot {
+struct HandlerOptions {
+ int num_worker_threads{};
+ bool use_iouring{};
+ bool o_direct{};
+ bool skip_verification{};
+ uint32_t cow_op_merge_size{};
+ uint32_t verify_block_size{};
+ uint32_t num_verification_threads{};
+};
+
class SnapshotHandler;
class HandlerThread {
@@ -53,11 +63,12 @@
virtual ~ISnapshotHandlerManager() {}
// Add a new snapshot handler but do not start serving requests yet.
- virtual std::shared_ptr<HandlerThread> AddHandler(
- const std::string& misc_name, const std::string& cow_device_path,
- const std::string& backing_device, const std::string& base_path_merge,
- std::shared_ptr<IBlockServerOpener> opener, int num_worker_threads, bool use_iouring,
- bool o_direct, uint32_t cow_op_merge_size) = 0;
+ virtual std::shared_ptr<HandlerThread> AddHandler(const std::string& misc_name,
+ const std::string& cow_device_path,
+ const std::string& backing_device,
+ const std::string& base_path_merge,
+ std::shared_ptr<IBlockServerOpener> opener,
+ HandlerOptions options) = 0;
// Start serving requests on a snapshot handler.
virtual bool StartHandler(const std::string& misc_name) = 0;
@@ -102,8 +113,8 @@
const std::string& backing_device,
const std::string& base_path_merge,
std::shared_ptr<IBlockServerOpener> opener,
- int num_worker_threads, bool use_iouring,
- bool o_direct, uint32_t cow_op_merge_size) override;
+ HandlerOptions options) override;
+
bool StartHandler(const std::string& misc_name) override;
bool DeleteHandler(const std::string& misc_name) override;
bool InitiateMerge(const std::string& misc_name) override;
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
index 7c9a64e..1f3d3a0 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
@@ -22,6 +22,8 @@
#include <android-base/strings.h>
#include <snapuserd/dm_user_block_server.h>
+#include <future>
+
#include "merge_worker.h"
#include "read_worker.h"
#include "utility.h"
@@ -35,26 +37,21 @@
SnapshotHandler::SnapshotHandler(std::string misc_name, std::string cow_device,
std::string backing_device, std::string base_path_merge,
- std::shared_ptr<IBlockServerOpener> opener, int num_worker_threads,
- bool use_iouring, bool perform_verification, bool o_direct,
- uint32_t cow_op_merge_size) {
+ std::shared_ptr<IBlockServerOpener> opener,
+ HandlerOptions options) {
misc_name_ = std::move(misc_name);
cow_device_ = std::move(cow_device);
backing_store_device_ = std::move(backing_device);
block_server_opener_ = std::move(opener);
base_path_merge_ = std::move(base_path_merge);
- num_worker_threads_ = num_worker_threads;
- is_io_uring_enabled_ = use_iouring;
- perform_verification_ = perform_verification;
- o_direct_ = o_direct;
- cow_op_merge_size_ = cow_op_merge_size;
+ handler_options_ = options;
}
bool SnapshotHandler::InitializeWorkers() {
for (int i = 0; i < num_worker_threads_; i++) {
auto wt = std::make_unique<ReadWorker>(cow_device_, backing_store_device_, misc_name_,
base_path_merge_, GetSharedPtr(),
- block_server_opener_, o_direct_);
+ block_server_opener_, handler_options_.o_direct);
if (!wt->Init()) {
SNAP_LOG(ERROR) << "Thread initialization failed";
return false;
@@ -62,13 +59,16 @@
worker_threads_.push_back(std::move(wt));
}
- merge_thread_ = std::make_unique<MergeWorker>(cow_device_, misc_name_, base_path_merge_,
- GetSharedPtr(), cow_op_merge_size_);
+ merge_thread_ =
+ std::make_unique<MergeWorker>(cow_device_, misc_name_, base_path_merge_, GetSharedPtr(),
+ handler_options_.cow_op_merge_size);
- read_ahead_thread_ = std::make_unique<ReadAhead>(cow_device_, backing_store_device_, misc_name_,
- GetSharedPtr(), cow_op_merge_size_);
+ read_ahead_thread_ =
+ std::make_unique<ReadAhead>(cow_device_, backing_store_device_, misc_name_,
+ GetSharedPtr(), handler_options_.cow_op_merge_size);
- update_verify_ = std::make_unique<UpdateVerify>(misc_name_);
+ update_verify_ = std::make_unique<UpdateVerify>(misc_name_, handler_options_.verify_block_size,
+ handler_options_.num_verification_threads);
return true;
}
@@ -429,7 +429,7 @@
// During selinux init transition, libsnapshot will propagate the
// status of io_uring enablement. As properties are not initialized,
// we cannot query system property.
- if (is_io_uring_enabled_) {
+ if (handler_options_.use_iouring) {
return true;
}
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
index 924539f..9c5d58b 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
@@ -24,15 +24,11 @@
#include <condition_variable>
#include <cstring>
-#include <future>
#include <iostream>
-#include <limits>
#include <mutex>
#include <ostream>
#include <string>
-#include <thread>
#include <unordered_map>
-#include <unordered_set>
#include <vector>
#include <android-base/file.h>
@@ -48,6 +44,7 @@
#include <snapuserd/snapuserd_kernel.h>
#include <storage_literals/storage_literals.h>
#include <system/thread_defs.h>
+#include <user-space-merge/handler_manager.h>
#include "snapuserd_readahead.h"
#include "snapuserd_verify.h"
@@ -104,8 +101,7 @@
public:
SnapshotHandler(std::string misc_name, std::string cow_device, std::string backing_device,
std::string base_path_merge, std::shared_ptr<IBlockServerOpener> opener,
- int num_workers, bool use_iouring, bool perform_verification, bool o_direct,
- uint32_t cow_op_merge_size);
+ HandlerOptions options);
bool InitCowDevice();
bool Start();
@@ -248,14 +244,12 @@
bool merge_initiated_ = false;
bool merge_monitored_ = false;
bool attached_ = false;
- bool is_io_uring_enabled_ = false;
bool scratch_space_ = false;
int num_worker_threads_ = kNumWorkerThreads;
bool perform_verification_ = true;
bool resume_merge_ = false;
bool merge_complete_ = false;
- bool o_direct_ = false;
- uint32_t cow_op_merge_size_ = 0;
+ HandlerOptions handler_options_;
std::unique_ptr<UpdateVerify> update_verify_;
std::shared_ptr<IBlockServerOpener> block_server_opener_;
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
index 372b2f2..b21189c 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
@@ -35,6 +35,7 @@
#include <snapuserd/dm_user_block_server.h>
#include <snapuserd/snapuserd_client.h>
#include "snapuserd_server.h"
+#include "user-space-merge/handler_manager.h"
#include "user-space-merge/snapuserd_core.h"
namespace android {
@@ -126,7 +127,8 @@
return Sendmsg(fd, "fail");
}
- auto handler = AddHandler(out[1], out[2], out[3], out[4], std::nullopt);
+ HandlerOptions options;
+ auto handler = AddHandler(out[1], out[2], out[3], out[4], options);
if (!handler) {
return Sendmsg(fd, "fail");
}
@@ -348,11 +350,11 @@
SetTerminating();
}
-std::shared_ptr<HandlerThread> UserSnapshotServer::AddHandler(
- const std::string& misc_name, const std::string& cow_device_path,
- const std::string& backing_device, const std::string& base_path_merge,
- std::optional<uint32_t> num_worker_threads, const bool o_direct,
- uint32_t cow_op_merge_size) {
+std::shared_ptr<HandlerThread> UserSnapshotServer::AddHandler(const std::string& misc_name,
+ const std::string& cow_device_path,
+ const std::string& backing_device,
+ const std::string& base_path_merge,
+ HandlerOptions options) {
// We will need multiple worker threads only during
// device boot after OTA. For all other purposes,
// one thread is sufficient. We don't want to consume
@@ -361,23 +363,19 @@
//
// During boot up, we need multiple threads primarily for
// update-verification.
- if (!num_worker_threads.has_value()) {
- num_worker_threads = kNumWorkerThreads;
- }
if (is_socket_present_) {
- num_worker_threads = 1;
+ options.num_worker_threads = 1;
}
- if (android::base::EndsWith(misc_name, "-init") || is_socket_present_ ||
- (access(kBootSnapshotsWithoutSlotSwitch, F_OK) == 0)) {
+ if (options.skip_verification || android::base::EndsWith(misc_name, "-init") ||
+ is_socket_present_ || (access(kBootSnapshotsWithoutSlotSwitch, F_OK) == 0)) {
handlers_->DisableVerification();
}
auto opener = block_server_factory_->CreateOpener(misc_name);
return handlers_->AddHandler(misc_name, cow_device_path, backing_device, base_path_merge,
- opener, num_worker_threads.value(), io_uring_enabled_, o_direct,
- cow_op_merge_size);
+ opener, options);
}
bool UserSnapshotServer::WaitForSocket() {
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
index f002e8d..73ce7b2 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
@@ -51,7 +51,6 @@
std::vector<struct pollfd> watched_fds_;
bool is_socket_present_ = false;
bool is_server_running_ = false;
- bool io_uring_enabled_ = false;
std::unique_ptr<ISnapshotHandlerManager> handlers_;
std::unique_ptr<IBlockServerFactory> block_server_factory_;
@@ -87,17 +86,13 @@
const std::string& cow_device_path,
const std::string& backing_device,
const std::string& base_path_merge,
- std::optional<uint32_t> num_worker_threads,
- bool o_direct = false,
- uint32_t cow_op_merge_size = 0);
+ HandlerOptions options);
bool StartHandler(const std::string& misc_name);
void SetTerminating() { terminating_ = true; }
void ReceivedSocketSignal() { received_socket_signal_ = true; }
void SetServerRunning() { is_server_running_ = true; }
bool IsServerRunning() { return is_server_running_; }
- void SetIouringEnabled() { io_uring_enabled_ = true; }
- bool IsIouringEnabled() { return io_uring_enabled_; }
};
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
index 0790a19..f3795a1 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
@@ -24,9 +24,8 @@
#include <unistd.h>
#include <chrono>
-#include <iostream>
+#include <future>
#include <memory>
-#include <string_view>
#include <android-base/file.h>
#include <android-base/properties.h>
@@ -44,7 +43,6 @@
#include "snapuserd_core.h"
#include "testing/dm_user_harness.h"
#include "testing/host_harness.h"
-#include "testing/temp_device.h"
#include "utility.h"
namespace android {
@@ -68,6 +66,8 @@
int block_size;
int num_threads;
uint32_t cow_op_merge_size;
+ uint32_t verification_block_size;
+ uint32_t num_verification_threads;
};
class SnapuserdTestBase : public ::testing::TestWithParam<TestParam> {
@@ -731,9 +731,17 @@
auto opener = factory->CreateOpener(system_device_ctrl_name_);
handlers_->DisableVerification();
const TestParam params = GetParam();
- auto handler = handlers_->AddHandler(
- system_device_ctrl_name_, cow_system_->path, base_dev_->GetPath(), base_dev_->GetPath(),
- opener, 1, params.io_uring, params.o_direct, params.cow_op_merge_size);
+ HandlerOptions options = {
+ .num_worker_threads = params.num_threads,
+ .use_iouring = params.io_uring,
+ .o_direct = params.o_direct,
+ .cow_op_merge_size = params.cow_op_merge_size,
+ .verify_block_size = params.verification_block_size,
+ .num_verification_threads = params.num_verification_threads,
+ };
+ auto handler =
+ handlers_->AddHandler(system_device_ctrl_name_, cow_system_->path, base_dev_->GetPath(),
+ base_dev_->GetPath(), opener, options);
ASSERT_NE(handler, nullptr);
ASSERT_NE(handler->snapuserd(), nullptr);
#ifdef __ANDROID__
@@ -1273,9 +1281,17 @@
ASSERT_NE(opener_, nullptr);
const TestParam params = GetParam();
- handler_ = std::make_shared<SnapshotHandler>(
- system_device_ctrl_name_, cow_system_->path, base_dev_->GetPath(), base_dev_->GetPath(),
- opener_, 1, false, false, params.o_direct, params.cow_op_merge_size);
+ HandlerOptions options = {
+ .num_worker_threads = params.num_threads,
+ .use_iouring = params.io_uring,
+ .o_direct = params.o_direct,
+ .cow_op_merge_size = params.cow_op_merge_size,
+ .verify_block_size = params.verification_block_size,
+ .num_verification_threads = params.num_verification_threads,
+ };
+ handler_ = std::make_shared<SnapshotHandler>(system_device_ctrl_name_, cow_system_->path,
+ base_dev_->GetPath(), base_dev_->GetPath(),
+ opener_, options);
ASSERT_TRUE(handler_->InitCowDevice());
ASSERT_TRUE(handler_->InitializeWorkers());
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.cpp
index 957c6a8..2dfcc36 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.cpp
@@ -20,8 +20,10 @@
#include <android-base/scopeguard.h>
#include <android-base/strings.h>
-#include "android-base/properties.h"
+#include <future>
+
#include "snapuserd_core.h"
+#include "utility.h"
namespace android {
namespace snapshot {
@@ -30,8 +32,12 @@
using namespace android::dm;
using android::base::unique_fd;
-UpdateVerify::UpdateVerify(const std::string& misc_name)
- : misc_name_(misc_name), state_(UpdateVerifyState::VERIFY_UNKNOWN) {}
+UpdateVerify::UpdateVerify(const std::string& misc_name, uint32_t verify_block_size,
+ uint32_t num_verification_threads)
+ : misc_name_(misc_name),
+ state_(UpdateVerifyState::VERIFY_UNKNOWN),
+ verify_block_size_(verify_block_size),
+ num_verification_threads_(num_verification_threads) {}
bool UpdateVerify::CheckPartitionVerification() {
auto now = std::chrono::system_clock::now();
@@ -104,43 +110,107 @@
return false;
}
- loff_t file_offset = offset;
- auto verify_block_size = android::base::GetUintProperty<uint>("ro.virtual_ab.verify_block_size",
- kBlockSizeVerify);
- const uint64_t read_sz = verify_block_size;
+ int queue_depth = std::max(queue_depth_, 1);
+ int verify_block_size = verify_block_size_;
- void* addr;
- ssize_t page_size = getpagesize();
- if (posix_memalign(&addr, page_size, read_sz) < 0) {
- SNAP_PLOG(ERROR) << "posix_memalign failed "
- << " page_size: " << page_size << " read_sz: " << read_sz;
+ // Smaller partitions don't need a bigger queue-depth.
+ // This is required for low-memory devices.
+ if (dev_sz < threshold_size_) {
+ queue_depth = std::max(queue_depth / 2, 1);
+ verify_block_size >>= 2;
+ }
+
+ if (!IsBlockAligned(verify_block_size)) {
+ verify_block_size = EXT4_ALIGN(verify_block_size, BLOCK_SZ);
+ }
+
+ std::unique_ptr<io_uring_cpp::IoUringInterface> ring =
+ io_uring_cpp::IoUringInterface::CreateLinuxIoUring(queue_depth, 0);
+ if (ring.get() == nullptr) {
+ PLOG(ERROR) << "Verify: io_uring_queue_init failed for queue_depth: " << queue_depth;
return false;
}
- std::unique_ptr<void, decltype(&::free)> buffer(addr, ::free);
-
- uint64_t bytes_read = 0;
-
- while (true) {
- size_t to_read = std::min((dev_sz - file_offset), read_sz);
-
- if (!android::base::ReadFullyAtOffset(fd.get(), buffer.get(), to_read, file_offset)) {
- SNAP_PLOG(ERROR) << "Failed to read block from block device: " << dm_block_device
- << " partition-name: " << partition_name
- << " at offset: " << file_offset << " read-size: " << to_read
- << " block-size: " << dev_sz;
+ std::unique_ptr<struct iovec[]> vecs = std::make_unique<struct iovec[]>(queue_depth);
+ std::vector<std::unique_ptr<void, decltype(&::free)>> buffers;
+ for (int i = 0; i < queue_depth; i++) {
+ void* addr;
+ ssize_t page_size = getpagesize();
+ if (posix_memalign(&addr, page_size, verify_block_size) < 0) {
+ LOG(ERROR) << "posix_memalign failed";
return false;
}
- bytes_read += to_read;
- file_offset += (skip_blocks * verify_block_size);
- if (file_offset >= dev_sz) {
+ buffers.emplace_back(addr, ::free);
+ vecs[i].iov_base = addr;
+ vecs[i].iov_len = verify_block_size;
+ }
+
+ auto ret = ring->RegisterBuffers(vecs.get(), queue_depth);
+ if (!ret.IsOk()) {
+ SNAP_LOG(ERROR) << "io_uring_register_buffers failed: " << ret.ErrCode();
+ return false;
+ }
+
+ loff_t file_offset = offset;
+ const uint64_t read_sz = verify_block_size;
+ uint64_t total_read = 0;
+ int num_submitted = 0;
+
+ SNAP_LOG(DEBUG) << "VerifyBlocks: queue_depth: " << queue_depth
+ << " verify_block_size: " << verify_block_size << " dev_sz: " << dev_sz
+ << " file_offset: " << file_offset << " skip_blocks: " << skip_blocks;
+
+ while (file_offset < dev_sz) {
+ for (size_t i = 0; i < queue_depth; i++) {
+ uint64_t to_read = std::min((dev_sz - file_offset), read_sz);
+ if (to_read <= 0) break;
+
+ const auto sqe =
+ ring->PrepReadFixed(fd.get(), vecs[i].iov_base, to_read, file_offset, i);
+ if (!sqe.IsOk()) {
+ SNAP_PLOG(ERROR) << "PrepReadFixed failed";
+ return false;
+ }
+ file_offset += (skip_blocks * to_read);
+ total_read += to_read;
+ num_submitted += 1;
+ if (file_offset >= dev_sz) {
+ break;
+ }
+ }
+
+ if (num_submitted == 0) {
break;
}
+
+ const auto io_submit = ring->SubmitAndWait(num_submitted);
+ if (!io_submit.IsOk()) {
+ SNAP_LOG(ERROR) << "SubmitAndWait failed: " << io_submit.ErrMsg()
+ << " for: " << num_submitted << " entries.";
+ return false;
+ }
+
+ SNAP_LOG(DEBUG) << "io_uring_submit: " << total_read << "num_submitted: " << num_submitted
+ << "ret: " << ret;
+
+ const auto cqes = ring->PopCQE(num_submitted);
+ if (cqes.IsErr()) {
+ SNAP_LOG(ERROR) << "PopCqe failed for: " << num_submitted
+ << " error: " << cqes.GetError().ErrMsg();
+ return false;
+ }
+ for (const auto& cqe : cqes.GetResult()) {
+ if (cqe.res < 0) {
+ SNAP_LOG(ERROR) << "I/O failed: cqe->res: " << cqe.res;
+ return false;
+ }
+ num_submitted -= 1;
+ }
}
- SNAP_LOG(DEBUG) << "Verification success with bytes-read: " << bytes_read
- << " dev_sz: " << dev_sz << " partition_name: " << partition_name;
+ SNAP_LOG(DEBUG) << "Verification success with io_uring: " << " dev_sz: " << dev_sz
+ << " partition_name: " << partition_name << " total_read: " << total_read;
return true;
}
@@ -175,35 +245,29 @@
return false;
}
- /*
- * Not all partitions are of same size. Some partitions are as small as
- * 100Mb. We can just finish them in a single thread. For bigger partitions
- * such as product, 4 threads are sufficient enough.
- *
- * TODO: With io_uring SQ_POLL support, we can completely cut this
- * down to just single thread for all partitions and potentially verify all
- * the partitions with zero syscalls. Additionally, since block layer
- * supports polling, IO_POLL could be used which will further cut down
- * latency.
- */
+ if (!KernelSupportsIoUring()) {
+ SNAP_LOG(INFO) << "Kernel does not support io_uring. Skipping verification.\n";
+ // This will fallback to update_verifier to do the verification.
+ return false;
+ }
+
int num_threads = kMinThreadsToVerify;
- auto verify_threshold_size = android::base::GetUintProperty<uint>(
- "ro.virtual_ab.verify_threshold_size", kThresholdSize);
- if (dev_sz > verify_threshold_size) {
+ if (dev_sz > threshold_size_) {
num_threads = kMaxThreadsToVerify;
+ if (num_verification_threads_ != 0) {
+ num_threads = num_verification_threads_;
+ }
}
std::vector<std::future<bool>> threads;
off_t start_offset = 0;
const int skip_blocks = num_threads;
- auto verify_block_size =
- android::base::GetUintProperty("ro.virtual_ab.verify_block_size", kBlockSizeVerify);
while (num_threads) {
threads.emplace_back(std::async(std::launch::async, &UpdateVerify::VerifyBlocks, this,
partition_name, dm_block_device, start_offset, skip_blocks,
dev_sz));
- start_offset += verify_block_size;
+ start_offset += verify_block_size_;
num_threads -= 1;
if (start_offset >= dev_sz) {
break;
@@ -218,9 +282,9 @@
if (ret) {
succeeded = true;
UpdatePartitionVerificationState(UpdateVerifyState::VERIFY_SUCCESS);
- SNAP_LOG(INFO) << "Partition: " << partition_name << " Block-device: " << dm_block_device
- << " Size: " << dev_sz
- << " verification success. Duration : " << timer.duration().count() << " ms";
+ SNAP_LOG(INFO) << "Partition verification success: " << partition_name
+ << " Block-device: " << dm_block_device << " Size: " << dev_sz
+ << " Duration : " << timer.duration().count() << " ms";
return true;
}
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.h
index b300a70..f995c7f 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.h
@@ -15,6 +15,7 @@
#pragma once
+#include <liburing.h>
#include <stdint.h>
#include <sys/types.h>
@@ -22,6 +23,7 @@
#include <mutex>
#include <string>
+#include <liburing_cpp/IoUring.h>
#include <snapuserd/snapuserd_kernel.h>
#include <storage_literals/storage_literals.h>
@@ -32,7 +34,8 @@
class UpdateVerify {
public:
- UpdateVerify(const std::string& misc_name);
+ UpdateVerify(const std::string& misc_name, uint32_t verify_block_size,
+ uint32_t num_verification_threads);
void VerifyUpdatePartition();
bool CheckPartitionVerification();
@@ -48,27 +51,24 @@
std::mutex m_lock_;
std::condition_variable m_cv_;
+ int kMinThreadsToVerify = 1;
+ int kMaxThreadsToVerify = 3;
+
/*
- * Scanning of partitions is an expensive operation both in terms of memory
- * and CPU usage. The goal here is to scan the partitions fast enough without
- * significant increase in the boot time.
- *
- * Partitions such as system, product which may be huge and may need multiple
- * threads to speed up the verification process. Using multiple threads for
- * all partitions may increase CPU usage significantly. Hence, limit that to
- * 1 thread per partition.
+ * To optimize partition scanning speed without significantly impacting boot time,
+ * we employ O_DIRECT, bypassing the page-cache. However, O_DIRECT's memory
+ * allocation from CMA can be problematic on devices with restricted CMA space.
+ * To address this, io_uring_register_buffers() pre-registers I/O buffers,
+ * preventing CMA usage. See b/401952955 for more details.
*
* These numbers were derived by monitoring the memory and CPU pressure
* (/proc/pressure/{cpu,memory}; and monitoring the Inactive(file) and
* Active(file) pages from /proc/meminfo.
- *
- * Additionally, for low memory devices, it is advisable to use O_DIRECT
- * functionality for source block device.
*/
- int kMinThreadsToVerify = 1;
- int kMaxThreadsToVerify = 3;
- uint64_t kThresholdSize = 750_MiB;
- uint64_t kBlockSizeVerify = 2_MiB;
+ uint64_t verify_block_size_ = 1_MiB;
+ uint64_t threshold_size_ = 2_GiB;
+ uint32_t num_verification_threads_;
+ int queue_depth_ = 4;
bool IsBlockAligned(uint64_t read_size) { return ((read_size & (BLOCK_SZ - 1)) == 0); }
void UpdatePartitionVerificationState(UpdateVerifyState state);
diff --git a/fs_mgr/libsnapshot/utility.cpp b/fs_mgr/libsnapshot/utility.cpp
index 30510d0..04ee069 100644
--- a/fs_mgr/libsnapshot/utility.cpp
+++ b/fs_mgr/libsnapshot/utility.cpp
@@ -199,7 +199,7 @@
}
std::ostream& operator<<(std::ostream& os, const Now&) {
- struct tm now{};
+ struct tm now {};
time_t t = time(nullptr);
localtime_r(&t, &now);
return os << std::put_time(&now, "%Y%m%d-%H%M%S");
@@ -293,6 +293,11 @@
return fetcher->GetBoolProperty("ro.virtual_ab.o_direct.enabled", false);
}
+bool GetSkipVerificationProperty() {
+ auto fetcher = IPropertyFetcher::GetInstance();
+ return fetcher->GetBoolProperty("ro.virtual_ab.skip_verification", false);
+}
+
std::string GetOtherPartitionName(const std::string& name) {
auto suffix = android::fs_mgr::GetPartitionSlotSuffix(name);
CHECK(suffix == "_a" || suffix == "_b");
diff --git a/fs_mgr/libsnapshot/utility.h b/fs_mgr/libsnapshot/utility.h
index 30c75c0..eaf51c1 100644
--- a/fs_mgr/libsnapshot/utility.h
+++ b/fs_mgr/libsnapshot/utility.h
@@ -136,6 +136,7 @@
bool GetIouringEnabledProperty();
bool GetXorCompressionEnabledProperty();
bool GetODirectEnabledProperty();
+bool GetSkipVerificationProperty();
bool CanUseUserspaceSnapshots();
bool IsDmSnapshotTestingEnabled();
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index b0a14bb..64c85e2 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -342,9 +342,10 @@
return value;
}
-static int getIntField(const String8& path) {
+template <typename T = int>
+static T getIntField(const String8& path) {
std::string buf;
- int value = 0;
+ T value = 0;
if (readFromFile(path, &buf) > 0)
android::base::ParseInt(buf, &value);
@@ -416,11 +417,11 @@
if (!mHealthdConfig->batteryManufacturingDatePath.empty())
ensureBatteryHealthData(mHealthInfo.get())->batteryManufacturingDateSeconds =
- getIntField(mHealthdConfig->batteryManufacturingDatePath);
+ getIntField<int64_t>(mHealthdConfig->batteryManufacturingDatePath);
if (!mHealthdConfig->batteryFirstUsageDatePath.empty())
ensureBatteryHealthData(mHealthInfo.get())->batteryFirstUsageSeconds =
- getIntField(mHealthdConfig->batteryFirstUsageDatePath);
+ getIntField<int64_t>(mHealthdConfig->batteryFirstUsageDatePath);
mHealthInfo->batteryTemperatureTenthsCelsius =
mBatteryFixedTemperature ? mBatteryFixedTemperature
@@ -715,49 +716,54 @@
char vs[128];
const HealthInfo& props = *mHealthInfo;
+ snprintf(vs, sizeof(vs), "Cached HealthInfo:\n");
+ write(fd, vs, strlen(vs));
snprintf(vs, sizeof(vs),
- "ac: %d usb: %d wireless: %d dock: %d current_max: %d voltage_max: %d\n",
+ " ac: %d usb: %d wireless: %d dock: %d current_max: %d voltage_max: %d\n",
props.chargerAcOnline, props.chargerUsbOnline, props.chargerWirelessOnline,
props.chargerDockOnline, props.maxChargingCurrentMicroamps,
props.maxChargingVoltageMicrovolts);
write(fd, vs, strlen(vs));
- snprintf(vs, sizeof(vs), "status: %d health: %d present: %d\n",
+ snprintf(vs, sizeof(vs), " status: %d health: %d present: %d\n",
props.batteryStatus, props.batteryHealth, props.batteryPresent);
write(fd, vs, strlen(vs));
- snprintf(vs, sizeof(vs), "level: %d voltage: %d temp: %d\n", props.batteryLevel,
+ snprintf(vs, sizeof(vs), " level: %d voltage: %d temp: %d\n", props.batteryLevel,
props.batteryVoltageMillivolts, props.batteryTemperatureTenthsCelsius);
write(fd, vs, strlen(vs));
if (!mHealthdConfig->batteryCurrentNowPath.empty()) {
+ snprintf(vs, sizeof(vs), " current now: %d\n", props.batteryCurrentMicroamps);
+ write(fd, vs, strlen(vs));
+ }
+
+ if (!mHealthdConfig->batteryCycleCountPath.empty()) {
+ snprintf(vs, sizeof(vs), " cycle count: %d\n", props.batteryCycleCount);
+ write(fd, vs, strlen(vs));
+ }
+
+ if (!mHealthdConfig->batteryFullChargePath.empty()) {
+ snprintf(vs, sizeof(vs), " Full charge: %d\n", props.batteryFullChargeUah);
+ write(fd, vs, strlen(vs));
+ }
+
+ snprintf(vs, sizeof(vs), "Real-time Values:\n");
+ write(fd, vs, strlen(vs));
+
+ if (!mHealthdConfig->batteryCurrentNowPath.empty()) {
v = getIntField(mHealthdConfig->batteryCurrentNowPath);
- snprintf(vs, sizeof(vs), "current now: %d\n", v);
+ snprintf(vs, sizeof(vs), " current now: %d\n", v);
write(fd, vs, strlen(vs));
}
if (!mHealthdConfig->batteryCurrentAvgPath.empty()) {
v = getIntField(mHealthdConfig->batteryCurrentAvgPath);
- snprintf(vs, sizeof(vs), "current avg: %d\n", v);
+ snprintf(vs, sizeof(vs), " current avg: %d\n", v);
write(fd, vs, strlen(vs));
}
if (!mHealthdConfig->batteryChargeCounterPath.empty()) {
v = getIntField(mHealthdConfig->batteryChargeCounterPath);
- snprintf(vs, sizeof(vs), "charge counter: %d\n", v);
- write(fd, vs, strlen(vs));
- }
-
- if (!mHealthdConfig->batteryCurrentNowPath.empty()) {
- snprintf(vs, sizeof(vs), "current now: %d\n", props.batteryCurrentMicroamps);
- write(fd, vs, strlen(vs));
- }
-
- if (!mHealthdConfig->batteryCycleCountPath.empty()) {
- snprintf(vs, sizeof(vs), "cycle count: %d\n", props.batteryCycleCount);
- write(fd, vs, strlen(vs));
- }
-
- if (!mHealthdConfig->batteryFullChargePath.empty()) {
- snprintf(vs, sizeof(vs), "Full charge: %d\n", props.batteryFullChargeUah);
+ snprintf(vs, sizeof(vs), " charge counter: %d\n", v);
write(fd, vs, strlen(vs));
}
}
diff --git a/init/Android.bp b/init/Android.bp
index 9edbe9d..b209c47 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -292,9 +292,6 @@
"make_f2fs",
"mke2fs",
"sload_f2fs",
-
- // TODO: Revert after go/android-memcgv2-exp b/386797433
- "memcgv2_activation_depth",
],
}
@@ -694,10 +691,3 @@
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/README.md b/init/README.md
index c9742ad..6a66f14 100644
--- a/init/README.md
+++ b/init/README.md
@@ -971,26 +971,13 @@
Bootcharting
------------
-This version of init contains code to perform "bootcharting": generating log
-files that can be later processed by the tools provided by <http://www.bootchart.org/>.
+Bootchart provides CPU and I/O load breakdown of all processes for the whole system.
+Refer to the instructions at
+ <https://source.android.com/docs/core/perf/boot-times#bootchart>.
On the emulator, use the -bootchart _timeout_ option to boot with bootcharting
activated for _timeout_ seconds.
-On a device:
-
- adb shell 'touch /data/bootchart/enabled'
-
-Don't forget to delete this file when you're done collecting data!
-
-The log files are written to /data/bootchart/. A script is provided to
-retrieve them and create a bootchart.tgz file that can be used with the
-bootchart command-line utility:
-
- sudo apt-get install pybootchartgui
- # grab-bootchart.sh uses $ANDROID_SERIAL.
- $ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh
-
One thing to watch for is that the bootchart will show init as if it started
running at 0s. You'll have to look at dmesg to work out when the kernel
actually started init.
diff --git a/init/compare-bootcharts.py b/init/compare-bootcharts.py
index 009b639..b299b7d 100755
--- a/init/compare-bootcharts.py
+++ b/init/compare-bootcharts.py
@@ -47,7 +47,7 @@
def analyze_process_maps(process_map1, process_map2, jiffy_record):
# List interesting processes here
processes_of_interest = [
- '/init',
+ '/system/bin/init',
'/system/bin/surfaceflinger',
'/system/bin/bootanimation',
'zygote64',
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 6bb0ad7..e06a645 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -402,7 +402,7 @@
// /second_stage_resources is used to preserve files from first to second
// stage init
- CHECKCALL(mount("tmpfs", kSecondStageRes, "tmpfs", MS_NOSUID | MS_NODEV,
+ CHECKCALL(mount("tmpfs", kSecondStageRes, "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
"mode=0755,uid=0,gid=0"));
if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
diff --git a/init/libprefetch/prefetch/src/tracer/mem.rs b/init/libprefetch/prefetch/src/tracer/mem.rs
index f69ae80..42120da 100644
--- a/init/libprefetch/prefetch/src/tracer/mem.rs
+++ b/init/libprefetch/prefetch/src/tracer/mem.rs
@@ -320,8 +320,8 @@
// Convenience function to create regex. Used once per life of `record` but multiple times in
// case of tests.
pub fn get_trace_line_regex() -> Result<Regex, Error> {
- // TODO: Fix this Regex expression for 5.15 kernels. This expression
- // works only on 6.1+. Prior to 6.1, "<page>" was present in the output.
+ // `page=[hex]` entry exists in 5.x kernel format but not in 6.x.
+ // Conversely, `order=[digit]` entry exists in 6.x kernel format but not in 5.x.
Regex::new(concat!(
r"^\s+(?P<cmd_pid>\S+)",
r"\s+(?P<cpu>\S+)",
@@ -330,9 +330,10 @@
r"\s+mm_filemap_add_to_page_cache:",
r"\s+dev\s+(?P<major>[0-9]+):(?P<minor>[0-9]+)",
r"\s+ino\s+(?P<ino>\S+)",
- //r"\s+(?P<page>\S+)",
+ r"(?:\s+(?P<page>page=\S+))?",
r"\s+(?P<pfn>\S+)",
- r"\s+ofs=(?P<offset>[0-9]+)"
+ r"\s+ofs=(?P<offset>[0-9]+)",
+ r"(?:\s+(?P<order>\S+))?"
))
.map_err(|e| Error::Custom {
error: format!("create regex for tracing failed with: {}", e),
@@ -682,22 +683,30 @@
use super::*;
- static TRACE_BUFFER: &str = r#"
- Settingide-502 [001] .... 484.360292: mm_filemap_add_to_page_CACHE: dev 254:6 ino cf1 page=68d477 pfn=59833 ofs=32768
- Settingide-502 [001] .... 484.360311: mm_filemap_add_to_page_cache: dev 254:6 ino cf1 page=759458 pfn=59827 ofs=57344
- BOX_ENTDED-3071 [001] .... 485.276715: mm_filemap_add_to_pag_ecache: dev 254:6 ino 1 page=00cc1c pfn=81748 ofs=13574144
- BOX_ENTDED-3071 [001] .... 485.276990: mm_filemap_add_to_page_cache: dev 254:6 ino cf2 page=36540b pfn=60952 ofs=0
- .gms.peent-843 [001] .... 485.545516: mm_filemap_add_to_page_cache: dev 254:6 ino 1 page=002e8b pfn=58928 ofs=13578240
- .gms.peent-843 [001] .... 485.545820: mm_filemap_add_to_page_cache: dev 254:6 ino cf3 page=6233ce pfn=58108 ofs=0
- an.bg-459 [001] .... 494.029396: mm_filemap_add_to_page_cache: dev 254:3 ino 7cf page=c5b5c7 pfn=373933 ofs=1310720
- an.bg-459 [001] .... 494.029398: mm_filemap_add_to_page_cache: dev 254:3 ino 7cf page=b8b9ec pfn=410074 ofs=1314816
- "#;
+ static TRACE_BUFFER: &str = concat!(
+ // kernel 5.x
+ " Settingide-502 [001] .... 484.360292: mm_filemap_add_to_page_CACHE: dev 254:6 ino cf1 page=68d477 pfn=59833 ofs=32768\n",
+ " Settingide-502 [001] .... 484.360311: mm_filemap_add_to_page_cache: dev 254:6 ino cf1 page=759458 pfn=59827 ofs=57344\n",
+ " BOX_ENTDED-3071 [001] .... 485.276715: mm_filemap_add_to_pag_ecache: dev 254:6 ino 1 page=00cc1c pfn=81748 ofs=13574144\n",
+ " BOX_ENTDED-3071 [001] .... 485.276990: mm_filemap_add_to_page_cache: dev 254:6 ino cf2 page=36540b pfn=60952 ofs=0\n",
+ " .gms.peent-843 [001] .... 485.545516: mm_filemap_add_to_page_cache: dev 254:6 ino 1 page=002e8b pfn=58928 ofs=13578240\n",
+ " .gms.peent-843 [001] .... 485.545820: mm_filemap_add_to_page_cache: dev 254:6 ino cf3 page=6233ce pfn=58108 ofs=0\n",
+ " an.bg-459 [001] .... 494.029396: mm_filemap_add_to_page_cache: dev 254:3 ino 7cf page=c5b5c7 pfn=373933 ofs=1310720\n",
+ " an.bg-459 [001] .... 494.029398: mm_filemap_add_to_page_cache: dev 254:3 ino 7cf page=b8b9ec pfn=410074 ofs=1314816\n",
+
+ // kernel 6.x
+ " logcat-686 [006] ..... 148216.040320: mm_filemap_add_to_page_CACHE: dev 254:85 ino 3f15 pfn=0x213bc2 ofs=528384 order=0\n",
+ " logcat-686 [001] ..... 148217.776227: mm_filemap_add_to_page_cache: dev 254:85 ino 3f15 pfn=0x21d306 ofs=532480 order=0\n",
+ " logcat-686 [003] ..... 148219.044389: mm_filemap_add_to_pag_ecache: dev 254:85 ino 3f15 pfn=0x224b8d ofs=536576 order=0\n",
+ " logcat-686 [001] ..... 148220.780964: mm_filemap_add_to_page_cache: dev 254:85 ino 3f15 pfn=0x1bfe0a ofs=540672 order=0\n",
+ " logcat-686 [001] ..... 148223.046560: mm_filemap_add_to_page_cache: dev 254:85 ino 3f15 pfn=0x1f3d29 ofs=544768 order=0",
+ );
fn sample_mem_traces() -> (String, Vec<Option<TraceLineInfo>>) {
(
TRACE_BUFFER.to_owned(),
vec![
- None,
+ // 5.x
None,
Some(TraceLineInfo::from_fields(254, 6, 0xcf1, 57344, 484360311000)),
None,
@@ -706,7 +715,12 @@
Some(TraceLineInfo::from_fields(254, 6, 0xcf3, 0, 485545820000)),
Some(TraceLineInfo::from_fields(254, 3, 0x7cf, 1310720, 494029396000)),
Some(TraceLineInfo::from_fields(254, 3, 0x7cf, 1314816, 494029398000)),
+ // 6.x
None,
+ Some(TraceLineInfo::from_fields(254, 85, 0x3f15, 532480, 148217776227000)),
+ None,
+ Some(TraceLineInfo::from_fields(254, 85, 0x3f15, 540672, 148220780964000)),
+ Some(TraceLineInfo::from_fields(254, 85, 0x3f15, 544768, 148223046560000)),
],
)
}
diff --git a/init/memcgv2_activation_depth.sh b/init/memcgv2_activation_depth.sh
deleted file mode 100644
index 91d215d..0000000
--- a/init/memcgv2_activation_depth.sh
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/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/init/selinux.cpp b/init/selinux.cpp
index 2a27c1d..03fd2d2 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -56,6 +56,7 @@
#include <linux/audit.h>
#include <linux/netlink.h>
#include <stdlib.h>
+#include <sys/mount.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -701,8 +702,8 @@
}
#ifdef ALLOW_REMOUNT_OVERLAYS
-void SetupOverlays() {
- if (android::fs_mgr::use_override_creds) return;
+bool EarlySetupOverlays() {
+ if (android::fs_mgr::use_override_creds) return false;
bool has_overlays = false;
std::string contents;
@@ -715,8 +716,16 @@
break;
}
- if (!has_overlays) return;
+ if (!has_overlays) return false;
+ if (mount("tmpfs", kSecondStageRes, "tmpfs", MS_REMOUNT | MS_NOSUID | MS_NODEV,
+ "mode=0755,uid=0,gid=0") == -1) {
+ PLOG(FATAL) << "Failed to remount tmpfs on " << kSecondStageRes << " to remove NO_EXEC";
+ }
+ return true;
+}
+
+void SetupOverlays() {
// After adb remount, we mount all r/o volumes with overlayfs to allow writing.
// However, since overlayfs performs its file operations in the context of the
// mounting process, this will not work as is - init is in the kernel domain in
@@ -728,7 +737,6 @@
// We will call overlay_remounter which will do the unmounts/mounts.
// But for that to work, the volumes must not be busy, so we need to copy
// overlay_remounter from system to a ramdisk and run it from there.
-
const char* kOverlayRemounter = "overlay_remounter";
auto or_src = std::filesystem::path("/system/xbin/") / kOverlayRemounter;
auto or_dest = std::filesystem::path(kSecondStageRes) / kOverlayRemounter;
@@ -756,6 +764,9 @@
PLOG(FATAL) << "execv(\"" << or_dest << "\") failed";
}
#else
+bool EarlySetupOverlays() {
+ return false;
+}
void SetupOverlays() {}
#endif
@@ -771,6 +782,9 @@
SelinuxSetupKernelLogging();
+ // Test to see if we should use overlays, and if so remount tmpfs before selinux will block
+ bool use_overlays = EarlySetupOverlays();
+
// TODO(b/287206497): refactor into different headers to only include what we need.
if (IsMicrodroid()) {
LoadSelinuxPolicyMicrodroid();
@@ -801,7 +815,7 @@
// SetupOverlays does not return if overlays exist, instead it execs overlay_remounter
// which then execs second stage init
- SetupOverlays();
+ if (use_overlays) SetupOverlays();
const char* path = "/system/bin/init";
const char* args[] = {path, "second_stage", nullptr};
diff --git a/init/service_utils.cpp b/init/service_utils.cpp
index f8821a0..8d9a046 100644
--- a/init/service_utils.cpp
+++ b/init/service_utils.cpp
@@ -98,7 +98,17 @@
// Look up the filesystems that were mounted under /sys before we wiped
// it and attempt to restore them.
for (const auto& entry : mounts) {
- if (entry.mount_point.starts_with("/sys/")) {
+ // Never mount /sys/kernel/debug/tracing. This is the *one* mount
+ // that is special within Linux kernel: for backward compatibility
+ // tracefs gets auto-mounted there whenever one mounts debugfs [1].
+ //
+ // Attempting to mount the filesystem here will cause SELinux
+ // denials, because unlike *all other* filesystems in Android, it's
+ // not init who mounted it so there's no policy that would allow it.
+ //
+ // [1] https://lore.kernel.org/lkml/20150204143755.694479564@goodmis.org/
+ if (entry.mount_point.starts_with("/sys/") &&
+ entry.mount_point != "/sys/kernel/debug/tracing") {
if (mount(entry.blk_device.c_str(), entry.mount_point.c_str(),
entry.fs_type.c_str(), entry.flags, "")) {
LOG(WARNING) << "Could not mount(" << entry.mount_point
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index 00a1114..0d1b7fe 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -72,20 +72,14 @@
{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
{ 00755, AID_ROOT, AID_SYSTEM, 0, "mnt" },
{ 00751, AID_ROOT, AID_SHELL, 0, "product/bin" },
- { 00751, AID_ROOT, AID_SHELL, 0, "product/apex/*/bin" },
{ 00777, AID_ROOT, AID_ROOT, 0, "sdcard" },
{ 00751, AID_ROOT, AID_SDCARD_R, 0, "storage" },
- { 00750, AID_ROOT, AID_SYSTEM, 0, "system/apex/com.android.tethering/bin/for-system" },
{ 00751, AID_ROOT, AID_SHELL, 0, "system/bin" },
{ 00755, AID_ROOT, AID_ROOT, 0, "system/etc/ppp" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/vendor" },
{ 00750, AID_ROOT, AID_SHELL, 0, "system/xbin" },
- { 00751, AID_ROOT, AID_SHELL, 0, "system/apex/*/bin" },
- { 00750, AID_ROOT, AID_SYSTEM, 0, "system_ext/apex/com.android.tethering/bin/for-system" },
{ 00751, AID_ROOT, AID_SHELL, 0, "system_ext/bin" },
- { 00751, AID_ROOT, AID_SHELL, 0, "system_ext/apex/*/bin" },
{ 00751, AID_ROOT, AID_SHELL, 0, "vendor/bin" },
- { 00751, AID_ROOT, AID_SHELL, 0, "vendor/apex/*/bin" },
{ 00755, AID_ROOT, AID_SHELL, 0, "vendor" },
{},
// clang-format on
@@ -182,8 +176,6 @@
// the following files have enhanced capabilities and ARE included
// in user builds.
- { 06755, AID_CLAT, AID_CLAT, 0, "system/apex/com.android.tethering/bin/for-system/clatd" },
- { 06755, AID_CLAT, AID_CLAT, 0, "system_ext/apex/com.android.tethering/bin/for-system/clatd" },
{ 00700, AID_SYSTEM, AID_SHELL, CAP_MASK_LONG(CAP_BLOCK_SUSPEND),
"system/bin/inputflinger" },
{ 00750, AID_ROOT, AID_SHELL, CAP_MASK_LONG(CAP_SETUID) |
@@ -214,23 +206,19 @@
{ 00644, AID_ROOT, AID_ROOT, 0, "odm/app/*" },
{ 00644, AID_ROOT, AID_ROOT, 0, "odm/priv-app/*" },
{ 00755, AID_ROOT, AID_SHELL, 0, "product/bin/*" },
- { 00755, AID_ROOT, AID_SHELL, 0, "product/apex/*bin/*" },
{ 00644, AID_ROOT, AID_ROOT, 0, "product/framework/*" },
{ 00644, AID_ROOT, AID_ROOT, 0, "product/app/*" },
{ 00644, AID_ROOT, AID_ROOT, 0, "product/priv-app/*" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin/*" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/xbin/*" },
- { 00755, AID_ROOT, AID_SHELL, 0, "system/apex/*/bin/*" },
{ 00644, AID_ROOT, AID_ROOT, 0, "system/framework/*" },
{ 00644, AID_ROOT, AID_ROOT, 0, "system/app/*" },
{ 00644, AID_ROOT, AID_ROOT, 0, "system/priv-app/*" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system_ext/bin/*" },
- { 00755, AID_ROOT, AID_SHELL, 0, "system_ext/apex/*/bin/*" },
{ 00644, AID_ROOT, AID_ROOT, 0, "system_ext/framework/*" },
{ 00644, AID_ROOT, AID_ROOT, 0, "system_ext/app/*" },
{ 00644, AID_ROOT, AID_ROOT, 0, "system_ext/priv-app/*" },
{ 00755, AID_ROOT, AID_SHELL, 0, "vendor/bin/*" },
- { 00755, AID_ROOT, AID_SHELL, 0, "vendor/apex/*bin/*" },
{ 00755, AID_ROOT, AID_SHELL, 0, "vendor/xbin/*" },
{ 00644, AID_ROOT, AID_ROOT, 0, "vendor/framework/*" },
{ 00644, AID_ROOT, AID_ROOT, 0, "vendor/app/*" },
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index 2aaafbe..b6aded0 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -144,6 +144,7 @@
#define AID_UPROBESTATS 1093 /* uid for uprobestats */
#define AID_CROS_EC 1094 /* uid for accessing ChromeOS EC (cros_ec) */
#define AID_MMD 1095 /* uid for memory management daemon */
+#define AID_UPDATE_ENGINE_LOG 1096 /* GID for accessing update_engine logs */
// Additions to this file must be made in AOSP, *not* in internal branches.
// You will also need to update expect_ids() in bionic/tests/grp_pwd_test.cpp.
diff --git a/libprocessgroup/profiles/cgroups.json b/libprocessgroup/profiles/cgroups.json
index dbf736a..e9345a5 100644
--- a/libprocessgroup/profiles/cgroups.json
+++ b/libprocessgroup/profiles/cgroups.json
@@ -36,7 +36,7 @@
"Controller": "memory",
"Path": ".",
"NeedsActivation": true,
- "MaxActivationDepth": 0,
+ "MaxActivationDepth": 3,
"Optional": true
}
]
diff --git a/libprocessgroup/profiles/task_profiles.json b/libprocessgroup/profiles/task_profiles.json
index 720cb30..42cdb91 100644
--- a/libprocessgroup/profiles/task_profiles.json
+++ b/libprocessgroup/profiles/task_profiles.json
@@ -597,7 +597,7 @@
"Params":
{
"Name": "MemSoftLimit",
- "Value": "16MB"
+ "Value": "16M"
}
},
{
@@ -619,7 +619,7 @@
"Params":
{
"Name": "MemSoftLimit",
- "Value": "512MB"
+ "Value": "512M"
}
},
{
diff --git a/libprocessgroup/util/util.cpp b/libprocessgroup/util/util.cpp
index a15a44f..c772bc5 100644
--- a/libprocessgroup/util/util.cpp
+++ b/libprocessgroup/util/util.cpp
@@ -18,19 +18,15 @@
#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>
@@ -178,38 +174,6 @@
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
@@ -271,10 +235,7 @@
bool ActivateControllers(const std::string& path, const CgroupDescriptorMap& descriptors) {
for (const auto& [name, descriptor] : descriptors) {
const uint32_t flags = descriptor.controller()->flags();
- 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 uint32_t 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 48e94d5..471059b 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -614,9 +614,6 @@
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.
@@ -790,7 +787,8 @@
mkdir /data/misc/vold 0700 root root
mkdir /data/misc/boottrace 0771 system shell
mkdir /data/misc/update_engine 0700 root root
- mkdir /data/misc/update_engine_log 02750 root log
+ mkdir /data/misc/update_engine_log 02750 root update_engine_log
+ chown root update_engine_log /data/misc/update_engine_log
mkdir /data/misc/trace 0700 root root
# create location to store surface and window trace files
mkdir /data/misc/wmtrace 0700 system system
@@ -1236,7 +1234,7 @@
# and chown/chmod does not work for /proc/sys/ entries.
# So proxy writes through init.
on property:sys.sysctl.extra_free_kbytes=*
- exec -- /system/bin/extra_free_kbytes.sh ${sys.sysctl.extra_free_kbytes}
+ exec_background -- /system/bin/extra_free_kbytes.sh ${sys.sysctl.extra_free_kbytes}
# Allow users to drop caches
on property:perf.drop_caches=3
@@ -1323,34 +1321,14 @@
# 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 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
+ write /sys/kernel/mm/lru_gen/enabled 1
on property:persist.device_config.mglru_native.lru_gen_config=core_and_mm_walk
- 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
+ write /sys/kernel/mm/lru_gen/enabled 3
on property:persist.device_config.mglru_native.lru_gen_config=core_and_nonleaf_young
- 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
+ write /sys/kernel/mm/lru_gen/enabled 5
on property:persist.device_config.mglru_native.lru_gen_config=all
- 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
+ write /sys/kernel/mm/lru_gen/enabled 7
# Allow other processes to run `snapshotctl` through `init`. This requires
# `set_prop` permission on `snapshotctl_prop`.
diff --git a/storaged/main.cpp b/storaged/main.cpp
index bbed210..8e71180 100644
--- a/storaged/main.cpp
+++ b/storaged/main.cpp
@@ -25,13 +25,12 @@
#include <sys/types.h>
#include <vector>
-#include <android-base/macros.h>
#include <android-base/logging.h>
+#include <android-base/macros.h>
#include <android-base/stringprintf.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
-#include <cutils/android_get_control_file.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
#include <cutils/sched_policy.h>
#include <private/android_filesystem_config.h>
diff --git a/storaged/storaged.rc b/storaged/storaged.rc
index 7085743..6debb69 100644
--- a/storaged/storaged.rc
+++ b/storaged/storaged.rc
@@ -2,7 +2,6 @@
class main
capabilities DAC_READ_SEARCH
priority 10
- file /d/mmc0/mmc0:0001/ext_csd r
task_profiles ServiceCapacityLow
user root
group package_info
diff --git a/trusty/libtrusty/tipc-test/tipc_test.c b/trusty/libtrusty/tipc-test/tipc_test.c
index 9910aee..121837d 100644
--- a/trusty/libtrusty/tipc-test/tipc_test.c
+++ b/trusty/libtrusty/tipc-test/tipc_test.c
@@ -55,8 +55,6 @@
"}"
/* clang-format on */
-#define countof(arr) (sizeof(arr) / sizeof(arr[0]))
-
static const char *uuid_name = "com.android.ipc-unittest.srv.uuid";
static const char *echo_name = "com.android.ipc-unittest.srv.echo";
static const char *ta_only_name = "com.android.ipc-unittest.srv.ta_only";
@@ -906,14 +904,12 @@
static int send_fd_test(const struct tipc_test_params* params) {
int ret;
- int dma_buf[] = {-1, -1, -1};
+ int dma_buf = -1;
int fd = -1;
- volatile char* buf[countof(dma_buf)] = {MAP_FAILED, MAP_FAILED, MAP_FAILED};
+ volatile char* buf = MAP_FAILED;
BufferAllocator* allocator = NULL;
- uint i;
const size_t num_chunks = 10;
- const size_t buf_size = memref_chunk_size * num_chunks;
fd = tipc_connect(params->dev_name, receiver_name);
if (fd < 0) {
@@ -929,86 +925,56 @@
goto cleanup;
}
- for (i = 0; i < countof(dma_buf); i++) {
- ret = DmabufHeapAlloc(allocator, "system", buf_size, 0, 0 /* legacy align */);
- if (ret < 0) {
- fprintf(stderr, "Failed to create dma-buf fd of size %zu err (%d)\n", buf_size, ret);
- goto cleanup;
- }
- dma_buf[i] = ret;
+ size_t buf_size = memref_chunk_size * num_chunks;
+ dma_buf = DmabufHeapAlloc(allocator, "system", buf_size, 0, 0 /* legacy align */);
+ if (dma_buf < 0) {
+ ret = dma_buf;
+ fprintf(stderr, "Failed to create dma-buf fd of size %zu err (%d)\n", buf_size, ret);
+ goto cleanup;
}
- for (i = 0; i < countof(dma_buf); i++) {
- buf[i] = mmap(0, buf_size, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf[i], 0);
- if (buf[i] == MAP_FAILED) {
- fprintf(stderr, "Failed to map dma-buf: %s\n", strerror(errno));
- ret = -1;
- goto cleanup;
- }
-
- strcpy((char*)buf[i], "From NS");
+ buf = mmap(0, buf_size, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf, 0);
+ if (buf == MAP_FAILED) {
+ fprintf(stderr, "Failed to map dma-buf: %s\n", strerror(errno));
+ ret = -1;
+ goto cleanup;
}
- struct trusty_shm shm[] = {
- {
- .fd = dma_buf[0],
- .transfer = TRUSTY_SHARE,
- },
- {
- .fd = dma_buf[0],
- .transfer = TRUSTY_SEND_SECURE_OR_SHARE,
- },
- {
- .fd = dma_buf[1],
- .transfer = TRUSTY_LEND,
- },
- {
- .fd = dma_buf[1],
- .transfer = TRUSTY_SEND_SECURE_OR_SHARE,
- },
- {
- .fd = dma_buf[2],
- .transfer = TRUSTY_SEND_SECURE_OR_SHARE,
- },
+ strcpy((char*)buf, "From NS");
+
+ struct trusty_shm shm = {
+ .fd = dma_buf,
+ .transfer = TRUSTY_SHARE,
};
- for (i = 0; i < countof(shm); i++) {
- ssize_t rc = tipc_send(fd, NULL, 0, &shm[i], 1);
- if (rc < 0) {
- fprintf(stderr, "tipc_send failed: %zd\n", rc);
- ret = rc;
- goto cleanup;
- }
- char c;
- read(fd, &c, 1);
+ ssize_t rc = tipc_send(fd, NULL, 0, &shm, 1);
+ if (rc < 0) {
+ fprintf(stderr, "tipc_send failed: %zd\n", rc);
+ ret = rc;
+ goto cleanup;
}
+ char c;
+ read(fd, &c, 1);
+ tipc_close(fd);
ret = 0;
- for (i = 0; i < countof(buf); i++) {
- for (size_t skip = 0; skip < num_chunks; skip++) {
- int cmp = strcmp("Hello from Trusty!", (const char*)&buf[i][skip * memref_chunk_size])
- ? (-1)
- : 0;
- if (cmp) fprintf(stderr, "Failed: Unexpected content at page %zu in dmabuf\n", skip);
- ret |= cmp;
- }
+ for (size_t skip = 0; skip < num_chunks; skip++) {
+ int cmp = strcmp("Hello from Trusty!",
+ (const char*)&buf[skip * memref_chunk_size]) ? (-1) : 0;
+ if (cmp)
+ fprintf(stderr, "Failed: Unexpected content at page %zu in dmabuf\n", skip);
+ ret |= cmp;
}
cleanup:
- for (i = 0; i < countof(dma_buf); i++) {
- if (buf[i] != MAP_FAILED) {
- munmap((char*)buf[i], buf_size);
- }
- if (dma_buf[i] >= 0) {
- close(dma_buf[i]);
- }
+ if (buf != MAP_FAILED) {
+ munmap((char*)buf, buf_size);
}
+ close(dma_buf);
if (allocator) {
FreeDmabufHeapBufferAllocator(allocator);
}
- if (fd >= 0) {
- tipc_close(fd);
- }
+ tipc_close(fd);
return ret;
}