Loading fs_mgr/libsnapshot/partition_cow_creator.cpp +18 −11 Original line number Diff line number Diff line Loading @@ -62,27 +62,34 @@ bool PartitionCowCreator::HasExtent(Partition* p, Extent* e) { return false; } void WriteExtent(DmSnapCowSizeCalculator* sc, const chromeos_update_engine::Extent& de, unsigned int sectors_per_block) { const auto block_boundary = de.start_block() + de.num_blocks(); for (auto b = de.start_block(); b < block_boundary; ++b) { for (unsigned int s = 0; s < sectors_per_block; ++s) { const auto sector_id = b * sectors_per_block + s; sc->WriteSector(sector_id); } } } uint64_t PartitionCowCreator::GetCowSize() { // WARNING: The origin partition should be READ-ONLY const uint64_t logical_block_size = current_metadata->logical_block_size(); const unsigned int sectors_per_block = logical_block_size / kSectorSize; DmSnapCowSizeCalculator sc(kSectorSize, kSnapshotChunkSize); // Allocate space for extra extents (if any). These extents are those that can be // used for error corrections or to store verity hash trees. for (const auto& de : extra_extents) { WriteExtent(&sc, de, sectors_per_block); } if (operations == nullptr) return sc.cow_size_bytes(); for (const auto& iop : *operations) { for (const auto& de : iop.dst_extents()) { // Skip if no blocks are written if (de.num_blocks() == 0) continue; // Flag all the blocks that were written const auto block_boundary = de.start_block() + de.num_blocks(); for (auto b = de.start_block(); b < block_boundary; ++b) { for (unsigned int s = 0; s < sectors_per_block; ++s) { const auto sector_id = b * sectors_per_block + s; sc.WriteSector(sector_id); } } WriteExtent(&sc, de, sectors_per_block); } } Loading fs_mgr/libsnapshot/partition_cow_creator.h +5 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <optional> #include <string> #include <vector> #include <liblp/builder.h> #include <update_engine/update_metadata.pb.h> Loading @@ -30,6 +31,7 @@ namespace snapshot { // Helper class that creates COW for a partition. struct PartitionCowCreator { using Extent = android::fs_mgr::Extent; using ChromeOSExtent = chromeos_update_engine::Extent; using Interval = android::fs_mgr::Interval; using MetadataBuilder = android::fs_mgr::MetadataBuilder; using Partition = android::fs_mgr::Partition; Loading @@ -50,6 +52,9 @@ struct PartitionCowCreator { std::string current_suffix; // List of operations to be applied on the partition. const RepeatedPtrField<InstallOperation>* operations = nullptr; // Extra extents that are going to be invalidated during the update // process. std::vector<ChromeOSExtent> extra_extents = {}; struct Return { SnapshotStatus snapshot_status; Loading fs_mgr/libsnapshot/snapshot.cpp +27 −8 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ using android::fs_mgr::MetadataBuilder; using android::fs_mgr::SlotNumberForSlotSuffix; using android::hardware::boot::V1_1::MergeStatus; using chromeos_update_engine::DeltaArchiveManifest; using chromeos_update_engine::Extent; using chromeos_update_engine::InstallOperation; template <typename T> using RepeatedPtrField = google::protobuf::RepeatedPtrField<T>; Loading Loading @@ -1886,12 +1887,15 @@ bool SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manifest // these devices. AutoDeviceList created_devices; PartitionCowCreator cow_creator{.target_metadata = target_metadata.get(), PartitionCowCreator cow_creator{ .target_metadata = target_metadata.get(), .target_suffix = target_suffix, .target_partition = nullptr, .current_metadata = current_metadata.get(), .current_suffix = current_suffix, .operations = nullptr}; .operations = nullptr, .extra_extents = {}, }; if (!CreateUpdateSnapshotsInternal(lock.get(), manifest, &cow_creator, &created_devices, &all_snapshot_status)) { Loading Loading @@ -1937,15 +1941,24 @@ bool SnapshotManager::CreateUpdateSnapshotsInternal( } std::map<std::string, const RepeatedPtrField<InstallOperation>*> install_operation_map; std::map<std::string, std::vector<Extent>> extra_extents_map; for (const auto& partition_update : manifest.partitions()) { auto suffixed_name = partition_update.partition_name() + target_suffix; auto&& [it, inserted] = install_operation_map.emplace(std::move(suffixed_name), &partition_update.operations()); auto&& [it, inserted] = install_operation_map.emplace(suffixed_name, &partition_update.operations()); if (!inserted) { LOG(ERROR) << "Duplicated partition " << partition_update.partition_name() << " in update manifest."; return false; } auto& extra_extents = extra_extents_map[suffixed_name]; if (partition_update.has_hash_tree_extent()) { extra_extents.push_back(partition_update.hash_tree_extent()); } if (partition_update.has_fec_extent()) { extra_extents.push_back(partition_update.fec_extent()); } } for (auto* target_partition : ListPartitionsWithSuffix(target_metadata, target_suffix)) { Loading @@ -1956,6 +1969,12 @@ bool SnapshotManager::CreateUpdateSnapshotsInternal( cow_creator->operations = operations_it->second; } cow_creator->extra_extents.clear(); auto extra_extents_it = extra_extents_map.find(target_partition->name()); if (extra_extents_it != extra_extents_map.end()) { cow_creator->extra_extents = std::move(extra_extents_it->second); } // Compute the device sizes for the partition. auto cow_creator_ret = cow_creator->Run(); if (!cow_creator_ret.has_value()) { Loading Loading
fs_mgr/libsnapshot/partition_cow_creator.cpp +18 −11 Original line number Diff line number Diff line Loading @@ -62,27 +62,34 @@ bool PartitionCowCreator::HasExtent(Partition* p, Extent* e) { return false; } void WriteExtent(DmSnapCowSizeCalculator* sc, const chromeos_update_engine::Extent& de, unsigned int sectors_per_block) { const auto block_boundary = de.start_block() + de.num_blocks(); for (auto b = de.start_block(); b < block_boundary; ++b) { for (unsigned int s = 0; s < sectors_per_block; ++s) { const auto sector_id = b * sectors_per_block + s; sc->WriteSector(sector_id); } } } uint64_t PartitionCowCreator::GetCowSize() { // WARNING: The origin partition should be READ-ONLY const uint64_t logical_block_size = current_metadata->logical_block_size(); const unsigned int sectors_per_block = logical_block_size / kSectorSize; DmSnapCowSizeCalculator sc(kSectorSize, kSnapshotChunkSize); // Allocate space for extra extents (if any). These extents are those that can be // used for error corrections or to store verity hash trees. for (const auto& de : extra_extents) { WriteExtent(&sc, de, sectors_per_block); } if (operations == nullptr) return sc.cow_size_bytes(); for (const auto& iop : *operations) { for (const auto& de : iop.dst_extents()) { // Skip if no blocks are written if (de.num_blocks() == 0) continue; // Flag all the blocks that were written const auto block_boundary = de.start_block() + de.num_blocks(); for (auto b = de.start_block(); b < block_boundary; ++b) { for (unsigned int s = 0; s < sectors_per_block; ++s) { const auto sector_id = b * sectors_per_block + s; sc.WriteSector(sector_id); } } WriteExtent(&sc, de, sectors_per_block); } } Loading
fs_mgr/libsnapshot/partition_cow_creator.h +5 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <optional> #include <string> #include <vector> #include <liblp/builder.h> #include <update_engine/update_metadata.pb.h> Loading @@ -30,6 +31,7 @@ namespace snapshot { // Helper class that creates COW for a partition. struct PartitionCowCreator { using Extent = android::fs_mgr::Extent; using ChromeOSExtent = chromeos_update_engine::Extent; using Interval = android::fs_mgr::Interval; using MetadataBuilder = android::fs_mgr::MetadataBuilder; using Partition = android::fs_mgr::Partition; Loading @@ -50,6 +52,9 @@ struct PartitionCowCreator { std::string current_suffix; // List of operations to be applied on the partition. const RepeatedPtrField<InstallOperation>* operations = nullptr; // Extra extents that are going to be invalidated during the update // process. std::vector<ChromeOSExtent> extra_extents = {}; struct Return { SnapshotStatus snapshot_status; Loading
fs_mgr/libsnapshot/snapshot.cpp +27 −8 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ using android::fs_mgr::MetadataBuilder; using android::fs_mgr::SlotNumberForSlotSuffix; using android::hardware::boot::V1_1::MergeStatus; using chromeos_update_engine::DeltaArchiveManifest; using chromeos_update_engine::Extent; using chromeos_update_engine::InstallOperation; template <typename T> using RepeatedPtrField = google::protobuf::RepeatedPtrField<T>; Loading Loading @@ -1886,12 +1887,15 @@ bool SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manifest // these devices. AutoDeviceList created_devices; PartitionCowCreator cow_creator{.target_metadata = target_metadata.get(), PartitionCowCreator cow_creator{ .target_metadata = target_metadata.get(), .target_suffix = target_suffix, .target_partition = nullptr, .current_metadata = current_metadata.get(), .current_suffix = current_suffix, .operations = nullptr}; .operations = nullptr, .extra_extents = {}, }; if (!CreateUpdateSnapshotsInternal(lock.get(), manifest, &cow_creator, &created_devices, &all_snapshot_status)) { Loading Loading @@ -1937,15 +1941,24 @@ bool SnapshotManager::CreateUpdateSnapshotsInternal( } std::map<std::string, const RepeatedPtrField<InstallOperation>*> install_operation_map; std::map<std::string, std::vector<Extent>> extra_extents_map; for (const auto& partition_update : manifest.partitions()) { auto suffixed_name = partition_update.partition_name() + target_suffix; auto&& [it, inserted] = install_operation_map.emplace(std::move(suffixed_name), &partition_update.operations()); auto&& [it, inserted] = install_operation_map.emplace(suffixed_name, &partition_update.operations()); if (!inserted) { LOG(ERROR) << "Duplicated partition " << partition_update.partition_name() << " in update manifest."; return false; } auto& extra_extents = extra_extents_map[suffixed_name]; if (partition_update.has_hash_tree_extent()) { extra_extents.push_back(partition_update.hash_tree_extent()); } if (partition_update.has_fec_extent()) { extra_extents.push_back(partition_update.fec_extent()); } } for (auto* target_partition : ListPartitionsWithSuffix(target_metadata, target_suffix)) { Loading @@ -1956,6 +1969,12 @@ bool SnapshotManager::CreateUpdateSnapshotsInternal( cow_creator->operations = operations_it->second; } cow_creator->extra_extents.clear(); auto extra_extents_it = extra_extents_map.find(target_partition->name()); if (extra_extents_it != extra_extents_map.end()) { cow_creator->extra_extents = std::move(extra_extents_it->second); } // Compute the device sizes for the partition. auto cow_creator_ret = cow_creator->Run(); if (!cow_creator_ret.has_value()) { Loading