diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-03-04 22:24:52 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2024-03-04 22:24:52 +0000 |
commit | d9f311f4c1e0e7aca005c1020532c8978f27ab98 (patch) | |
tree | 244c4698bb8f6ea62355bfb8c9c88e39ee7c1eb5 | |
parent | 15fd24f0fe49af8ee3137ee78488627319d91ade (diff) | |
parent | f4cd75095c0f16b3cb4478a69be3d9c968c35eb5 (diff) | |
download | core-simpleperf-release.tar.gz |
Merge "Snap for 11526323 from eed1c420872f3c31e7fed5e2383e042c8762aebf to simpleperf-release" into simpleperf-releasesimpleperf-release
-rw-r--r-- | debuggerd/debuggerd_test.cpp | 6 | ||||
-rw-r--r-- | fs_mgr/libdm/dm_target.cpp | 4 | ||||
-rw-r--r-- | fs_mgr/libdm/dm_test.cpp | 7 | ||||
-rw-r--r-- | fs_mgr/libdm/include/libdm/dm_target.h | 18 | ||||
-rw-r--r-- | fs_mgr/libsnapshot/partition_cow_creator_test.cpp | 1 | ||||
-rw-r--r-- | fs_mgr/libsnapshot/snapshot_test.cpp | 1 | ||||
-rw-r--r-- | fs_mgr/libsnapshot/snapshotctl.cpp | 223 | ||||
-rwxr-xr-x | fs_mgr/libsnapshot/vts_ota_config_test.cpp | 1 | ||||
-rwxr-xr-x | fs_mgr/tests/adb-remount-test.sh | 8 | ||||
-rw-r--r-- | fs_mgr/tools/dmctl.cpp | 15 | ||||
-rw-r--r-- | rootdir/init.rc | 6 |
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. |