summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-03-04 22:24:52 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2024-03-04 22:24:52 +0000
commitd9f311f4c1e0e7aca005c1020532c8978f27ab98 (patch)
tree244c4698bb8f6ea62355bfb8c9c88e39ee7c1eb5
parent15fd24f0fe49af8ee3137ee78488627319d91ade (diff)
parentf4cd75095c0f16b3cb4478a69be3d9c968c35eb5 (diff)
downloadcore-simpleperf-release.tar.gz
Merge "Snap for 11526323 from eed1c420872f3c31e7fed5e2383e042c8762aebf to simpleperf-release" into simpleperf-releasesimpleperf-release
-rw-r--r--debuggerd/debuggerd_test.cpp6
-rw-r--r--fs_mgr/libdm/dm_target.cpp4
-rw-r--r--fs_mgr/libdm/dm_test.cpp7
-rw-r--r--fs_mgr/libdm/include/libdm/dm_target.h18
-rw-r--r--fs_mgr/libsnapshot/partition_cow_creator_test.cpp1
-rw-r--r--fs_mgr/libsnapshot/snapshot_test.cpp1
-rw-r--r--fs_mgr/libsnapshot/snapshotctl.cpp223
-rwxr-xr-xfs_mgr/libsnapshot/vts_ota_config_test.cpp1
-rwxr-xr-xfs_mgr/tests/adb-remount-test.sh8
-rw-r--r--fs_mgr/tools/dmctl.cpp15
-rw-r--r--rootdir/init.rc6
11 files changed, 274 insertions, 16 deletions
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index f396b1de8..5cc2b3aef 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -2647,7 +2647,7 @@ TEST_F(CrasherTest, fault_address_after_last_map) {
match_str += format_full_pointer(crash_uptr);
ASSERT_MATCH(result, match_str);
- ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)");
+ ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
// Verifies that the fault address error message is at the end of the
// maps section. To do this, the check below looks for the start of the
@@ -2699,7 +2699,7 @@ TEST_F(CrasherTest, fault_address_between_maps) {
match_str += format_full_pointer(reinterpret_cast<uintptr_t>(middle_ptr));
ASSERT_MATCH(result, match_str);
- ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)");
+ ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
match_str = android::base::StringPrintf(
R"( %s.*\n--->Fault address falls at %s between mapped regions\n %s)",
@@ -2737,7 +2737,7 @@ TEST_F(CrasherTest, fault_address_in_map) {
match_str += format_full_pointer(reinterpret_cast<uintptr_t>(ptr));
ASSERT_MATCH(result, match_str);
- ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)");
+ ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
match_str = android::base::StringPrintf(R"(\n--->%s.*\n)", format_pointer(ptr).c_str());
ASSERT_MATCH(result, match_str);
diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp
index 90d91a00c..1f6bd1a21 100644
--- a/fs_mgr/libdm/dm_target.cpp
+++ b/fs_mgr/libdm/dm_target.cpp
@@ -61,6 +61,10 @@ std::string DmTargetLinear::GetParameterString() const {
return block_device_ + " " + std::to_string(physical_sector_);
}
+std::string DmTargetStripe::GetParameterString() const {
+ return "2 " + std::to_string(chunksize) + " " + block_device0_ + " 0 " + block_device1_ + " 0";
+}
+
DmTargetVerity::DmTargetVerity(uint64_t start, uint64_t length, uint32_t version,
const std::string& block_device, const std::string& hash_device,
uint32_t data_block_size, uint32_t hash_block_size,
diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp
index a0129c234..d043be63b 100644
--- a/fs_mgr/libdm/dm_test.cpp
+++ b/fs_mgr/libdm/dm_test.cpp
@@ -181,6 +181,13 @@ TEST_F(DmTest, DmSuspendResume) {
ASSERT_EQ(dm.GetState(dev.name()), DmDeviceState::ACTIVE);
}
+TEST_F(DmTest, StripeArgs) {
+ DmTargetStripe target(0, 4096, 1024, "/dev/loop0", "/dev/loop1");
+ ASSERT_EQ(target.name(), "striped");
+ ASSERT_TRUE(target.Valid());
+ ASSERT_EQ(target.GetParameterString(), "2 1024 /dev/loop0 0 /dev/loop1 0");
+}
+
TEST_F(DmTest, DmVerityArgsAvb2) {
std::string device = "/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a";
std::string algorithm = "sha1";
diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h
index 09fe20012..97f3c134e 100644
--- a/fs_mgr/libdm/include/libdm/dm_target.h
+++ b/fs_mgr/libdm/include/libdm/dm_target.h
@@ -116,6 +116,24 @@ class DmTargetLinear final : public DmTarget {
uint64_t physical_sector_;
};
+class DmTargetStripe final : public DmTarget {
+ public:
+ DmTargetStripe(uint64_t start, uint64_t length, uint64_t chunksize,
+ const std::string& block_device0, const std::string& block_device1)
+ : DmTarget(start, length),
+ chunksize(chunksize),
+ block_device0_(block_device0),
+ block_device1_(block_device1) {}
+
+ std::string name() const override { return "striped"; }
+ std::string GetParameterString() const override;
+
+ private:
+ uint64_t chunksize;
+ std::string block_device0_;
+ std::string block_device1_;
+};
+
class DmTargetVerity final : public DmTarget {
public:
DmTargetVerity(uint64_t start, uint64_t length, uint32_t version,
diff --git a/fs_mgr/libsnapshot/partition_cow_creator_test.cpp b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
index cf26a1636..a4a2c1a68 100644
--- a/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
+++ b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
@@ -39,6 +39,7 @@ using ::testing::Truly;
namespace android {
namespace snapshot {
+// @VsrTest = 3.7.6
class PartitionCowCreatorTest : public ::testing::Test {
public:
void SetUp() override {
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index e538d503d..47e6ce963 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -104,6 +104,7 @@ std::string fake_super;
void MountMetadata();
+// @VsrTest = 3.7.6
class SnapshotTest : public ::testing::Test {
public:
SnapshotTest() : dm_(DeviceMapper::Instance()) {}
diff --git a/fs_mgr/libsnapshot/snapshotctl.cpp b/fs_mgr/libsnapshot/snapshotctl.cpp
index 0396a55d6..50e9f4823 100644
--- a/fs_mgr/libsnapshot/snapshotctl.cpp
+++ b/fs_mgr/libsnapshot/snapshotctl.cpp
@@ -15,6 +15,7 @@
//
#include <sysexits.h>
+#include <unistd.h>
#include <chrono>
#include <filesystem>
@@ -46,9 +47,7 @@
#include "partition_cow_creator.h"
-#ifdef SNAPSHOTCTL_USERDEBUG_OR_ENG
#include <BootControlClient.h>
-#endif
using namespace std::chrono_literals;
using namespace std::string_literals;
@@ -79,7 +78,11 @@ int Usage() {
" revert-snapshots\n"
" Prepares devices to boot without snapshots on next boot.\n"
" This does not delete the snapshot. It only removes the indicators\n"
- " so that first stage init will not mount from snapshots.\n";
+ " so that first stage init will not mount from snapshots.\n"
+ " apply-update\n"
+ " Apply the incremental OTA update wherein the snapshots are\n"
+ " directly written to COW block device. This will bypass update-engine\n"
+ " and the device will be ready to boot from the target build.\n";
return EX_USAGE;
}
@@ -96,14 +99,22 @@ class MapSnapshots {
bool DeleteSnapshots();
bool CleanupSnapshot() { return sm_->PrepareDeviceToBootWithoutSnapshot(); }
bool BeginUpdate();
+ bool ApplyUpdate();
private:
std::optional<std::string> GetCowImagePath(std::string& name);
+ bool PrepareUpdate();
bool WriteSnapshotPatch(std::string cow_device, std::string patch);
+ std::string GetGroupName(const android::fs_mgr::LpMetadata& pt,
+ const std::string& partiton_name);
std::unique_ptr<SnapshotManager::LockedFile> lock_;
std::unique_ptr<SnapshotManager> sm_;
std::vector<std::future<bool>> threads_;
std::string snapshot_dir_path_;
+ std::unordered_map<std::string, chromeos_update_engine::DynamicPartitionGroup*> group_map_;
+
+ std::vector<std::string> patchfiles_;
+ chromeos_update_engine::DeltaArchiveManifest manifest_;
};
MapSnapshots::MapSnapshots(std::string path) {
@@ -115,6 +126,178 @@ MapSnapshots::MapSnapshots(std::string path) {
snapshot_dir_path_ = path + "/";
}
+std::string MapSnapshots::GetGroupName(const android::fs_mgr::LpMetadata& pt,
+ const std::string& partition_name) {
+ std::string group_name;
+ for (const auto& partition : pt.partitions) {
+ std::string name = android::fs_mgr::GetPartitionName(partition);
+ auto suffix = android::fs_mgr::GetPartitionSlotSuffix(name);
+ std::string pname = name.substr(0, name.size() - suffix.size());
+ if (pname == partition_name) {
+ std::string group_name =
+ android::fs_mgr::GetPartitionGroupName(pt.groups[partition.group_index]);
+ return group_name.substr(0, group_name.size() - suffix.size());
+ }
+ }
+ return "";
+}
+
+bool MapSnapshots::PrepareUpdate() {
+ auto source_slot = fs_mgr_get_slot_suffix();
+ auto source_slot_number = SlotNumberForSlotSuffix(source_slot);
+ auto super_source = fs_mgr_get_super_partition_name(source_slot_number);
+
+ // Get current partition information.
+ PartitionOpener opener;
+ auto source_metadata = ReadMetadata(opener, super_source, source_slot_number);
+ if (!source_metadata) {
+ LOG(ERROR) << "Could not read source partition metadata.\n";
+ return false;
+ }
+
+ auto dap = manifest_.mutable_dynamic_partition_metadata();
+ dap->set_snapshot_enabled(true);
+ dap->set_vabc_enabled(true);
+ dap->set_vabc_compression_param("lz4");
+ dap->set_cow_version(3);
+
+ for (const auto& entry : std::filesystem::directory_iterator(snapshot_dir_path_)) {
+ if (android::base::EndsWith(entry.path().generic_string(), ".patch")) {
+ patchfiles_.push_back(android::base::Basename(entry.path().generic_string()));
+ }
+ }
+
+ for (auto& patchfile : patchfiles_) {
+ std::string parsing_file = snapshot_dir_path_ + patchfile;
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(parsing_file.c_str(), O_RDONLY)));
+ if (fd < 0) {
+ LOG(ERROR) << "Failed to open file: " << parsing_file;
+ return false;
+ }
+ uint64_t dev_sz = lseek(fd.get(), 0, SEEK_END);
+ if (!dev_sz) {
+ LOG(ERROR) << "Could not determine block device size: " << parsing_file;
+ return false;
+ }
+
+ const int block_sz = 4_KiB;
+ dev_sz += block_sz - 1;
+ dev_sz &= ~(block_sz - 1);
+
+ auto npos = patchfile.rfind(".patch");
+ auto partition_name = patchfile.substr(0, npos);
+
+ chromeos_update_engine::DynamicPartitionGroup* group = nullptr;
+ std::string group_name = GetGroupName(*source_metadata.get(), partition_name);
+ if (group_map_.find(group_name) != group_map_.end()) {
+ group = group_map_[group_name];
+ } else {
+ group = dap->add_groups();
+ group->set_name(group_name);
+ group_map_[group_name] = group;
+ }
+ group->add_partition_names(partition_name);
+
+ auto pu = manifest_.mutable_partitions()->Add();
+ pu->set_partition_name(partition_name);
+ pu->set_estimate_cow_size(dev_sz);
+
+ CowReader reader;
+ if (!reader.Parse(fd)) {
+ LOG(ERROR) << "COW reader parse failed";
+ return false;
+ }
+
+ uint64_t new_device_size = 0;
+ const auto& header = reader.GetHeader();
+ if (header.prefix.major_version == 2) {
+ size_t num_ops = reader.get_num_total_data_ops();
+ new_device_size = (num_ops * header.block_size);
+ } else {
+ const auto& v3_header = reader.header_v3();
+ new_device_size = v3_header.op_count_max * v3_header.block_size;
+ }
+
+ LOG(INFO) << "Partition: " << partition_name << " Group_name: " << group_name
+ << " size: " << new_device_size << " COW-size: " << dev_sz;
+ pu->mutable_new_partition_info()->set_size(new_device_size);
+ }
+ return true;
+}
+
+bool MapSnapshots::ApplyUpdate() {
+ if (!PrepareUpdate()) {
+ LOG(ERROR) << "PrepareUpdate failed";
+ return false;
+ }
+ if (!sm_->BeginUpdate()) {
+ LOG(ERROR) << "BeginUpdate failed";
+ return false;
+ }
+ if (!sm_->CreateUpdateSnapshots(manifest_)) {
+ LOG(ERROR) << "Could not apply snapshots";
+ return false;
+ }
+
+ LOG(INFO) << "CreateUpdateSnapshots success";
+ if (!sm_->MapAllSnapshots(10s)) {
+ LOG(ERROR) << "MapAllSnapshots failed";
+ return false;
+ }
+
+ LOG(INFO) << "MapAllSnapshots success";
+
+ auto& dm = android::dm::DeviceMapper::Instance();
+ auto target_slot = fs_mgr_get_other_slot_suffix();
+ for (auto& patchfile : patchfiles_) {
+ auto npos = patchfile.rfind(".patch");
+ auto partition_name = patchfile.substr(0, npos) + target_slot;
+ auto cow_device = partition_name + "-cow";
+ std::string cow_path;
+ if (!dm.GetDmDevicePathByName(cow_device, &cow_path)) {
+ LOG(ERROR) << "Failed to cow path";
+ return false;
+ }
+ threads_.emplace_back(std::async(std::launch::async, &MapSnapshots::WriteSnapshotPatch,
+ this, cow_path, patchfile));
+ }
+
+ bool ret = true;
+ for (auto& t : threads_) {
+ ret = t.get() && ret;
+ }
+ if (!ret) {
+ LOG(ERROR) << "Snapshot writes failed";
+ return false;
+ }
+ if (!sm_->UnmapAllSnapshots()) {
+ LOG(ERROR) << "UnmapAllSnapshots failed";
+ return false;
+ }
+
+ LOG(INFO) << "Pre-created snapshots successfully copied";
+ // All snapshots have been written.
+ if (!sm_->FinishedSnapshotWrites(false /* wipe */)) {
+ LOG(ERROR) << "Could not finalize snapshot writes.\n";
+ return false;
+ }
+
+ auto hal = hal::BootControlClient::WaitForService();
+ if (!hal) {
+ LOG(ERROR) << "Could not find IBootControl HAL.\n";
+ return false;
+ }
+ auto target_slot_number = SlotNumberForSlotSuffix(target_slot);
+ auto cr = hal->SetActiveBootSlot(target_slot_number);
+ if (!cr.IsOk()) {
+ LOG(ERROR) << "Could not set active boot slot: " << cr.errMsg;
+ return false;
+ }
+
+ LOG(INFO) << "ApplyUpdate success";
+ return true;
+}
+
bool MapSnapshots::BeginUpdate() {
lock_ = sm_->LockExclusive();
std::vector<std::string> snapshots;
@@ -227,11 +410,10 @@ bool MapSnapshots::WriteSnapshotPatch(std::string cow_device, std::string patch)
if (file_offset >= dev_sz) {
break;
}
-
- if (fsync(cfd.get()) < 0) {
- PLOG(ERROR) << "Fsync failed at offset: " << file_offset << " size: " << to_read;
- return false;
- }
+ }
+ if (fsync(cfd.get()) < 0) {
+ PLOG(ERROR) << "Fsync failed";
+ return false;
}
return true;
}
@@ -367,6 +549,30 @@ bool DeletePrecreatedSnapshots(int, char** argv) {
return snapshot.DeleteSnapshots();
}
+bool ApplyUpdate(int argc, char** argv) {
+ android::base::InitLogging(argv, &android::base::KernelLogger);
+
+ // Make sure we are root.
+ if (::getuid() != 0) {
+ LOG(ERROR) << "Not running as root. Try \"adb root\" first.";
+ return EXIT_FAILURE;
+ }
+
+ if (argc < 3) {
+ std::cerr << " apply-update <directory location where snapshot patches are present>"
+ " Apply the snapshots to the COW block device\n";
+ return false;
+ }
+
+ std::string path = std::string(argv[2]);
+ MapSnapshots cow(path);
+ if (!cow.ApplyUpdate()) {
+ return false;
+ }
+ LOG(INFO) << "Apply update success. Please reboot the device";
+ return true;
+}
+
bool MapPrecreatedSnapshots(int argc, char** argv) {
android::base::InitLogging(argv, &android::base::KernelLogger);
@@ -554,6 +760,7 @@ static std::map<std::string, std::function<bool(int, char**)>> kCmdMap = {
{"test-blank-ota", TestOtaHandler},
#endif
{"unmap", UnmapCmdHandler},
+ {"apply-update", ApplyUpdate},
{"map-snapshots", MapPrecreatedSnapshots},
{"unmap-snapshots", UnMapPrecreatedSnapshots},
{"delete-snapshots", DeletePrecreatedSnapshots},
diff --git a/fs_mgr/libsnapshot/vts_ota_config_test.cpp b/fs_mgr/libsnapshot/vts_ota_config_test.cpp
index d387eb32d..b5618c478 100755
--- a/fs_mgr/libsnapshot/vts_ota_config_test.cpp
+++ b/fs_mgr/libsnapshot/vts_ota_config_test.cpp
@@ -21,6 +21,7 @@ static int GetVsrLevel() {
return android::base::GetIntProperty("ro.vendor.api_level", -1);
}
+// @VsrTest = 3.7.6
TEST(VAB, Enabled) {
if (!android::base::GetBoolProperty("ro.build.ab_update", false) && (GetVsrLevel() < __ANDROID_API_T__)) {
GTEST_SKIP();
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index 7ac7a1642..526c761d3 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -1081,7 +1081,9 @@ LOG OK "no overlay present before setup"
LOG RUN "Testing adb disable-verity -R"
T=$(adb_date)
-adb_su disable-verity -R >&2 ||
+adb_su disable-verity -R >&2
+err=${?}
+[[ ${err} -eq 0 || ${err} -eq 255 ]] ||
die -t "${T}" "disable-verity -R failed"
sleep 2
adb_wait "${ADB_WAIT}" ||
@@ -1192,7 +1194,9 @@ LOG OK "adb remount from scratch"
LOG RUN "Testing adb remount -R"
T=$(adb_date)
-adb_su remount -R </dev/null >&2 ||
+adb_su remount -R </dev/null >&2
+err=${?}
+[[ ${err} -eq 0 || ${err} -eq 255 ]] ||
die -t "${T}" "adb remount -R failed"
sleep 2
adb_wait "${ADB_WAIT}" ||
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index 7273087b3..9dc8c2426 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -115,6 +115,21 @@ class TargetParser final {
std::string block_device = NextArg();
return std::make_unique<DmTargetAndroidVerity>(start_sector, num_sectors, keyid,
block_device);
+ } else if (target_type == "striped") {
+ if (!HasArgs(3)) {
+ std::cerr << "Expected \"striped\" <block_device0> <block_device1> <chunksize>"
+ << std::endl;
+ return nullptr;
+ }
+ std::string block_device0 = NextArg();
+ std::string block_device1 = NextArg();
+ uint64_t chunk_size;
+ if (!android::base::ParseUint(NextArg(), &chunk_size)) {
+ std::cerr << "Expected start sector, got: " << PreviousArg() << std::endl;
+ return nullptr;
+ }
+ return std::make_unique<DmTargetStripe>(start_sector, num_sectors, chunk_size,
+ block_device0, block_device1);
} else if (target_type == "bow") {
if (!HasArgs(1)) {
std::cerr << "Expected \"bow\" <block_device>" << std::endl;
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 3c367f969..8a2ed9fac 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -641,9 +641,9 @@ on post-fs
mkdir /metadata/staged-install 0770 root system
- mkdir /metadata/aconfig 0750 root system
- mkdir /metadata/aconfig/flags 0750 root system
- mkdir /metadata/aconfig/boot 0754 root system
+ mkdir /metadata/aconfig 0775 root system
+ mkdir /metadata/aconfig/flags 0770 root system
+ mkdir /metadata/aconfig/boot 0775 root system
on late-fs
# Ensure that tracefs has the correct permissions.