PartitionCowCreator accounts for extra extents
dm-verity and error correction use part of the partitions using these features to store their data. Their data may be modified during an update, so the COW device for the dm-snapshot must reserve some extra space for them. This patch extends the PartitionCowCreator data structure with the extra_extents field that will store the (optional) additional extents, e.g., the hash table extent for dm-verity or the error correction extent. Test: incremental OTA apply Test: libsnapshot_test Bug: 145180464 Change-Id: I387a6cc8438507ad41a85cc3400241ecaf627b8f Signed-off-by: Alessio Balsini <balsini@google.com>
This commit is contained in:
parent
4ac630b562
commit
33836a6061
3 changed files with 50 additions and 19 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <liblp/builder.h>
|
||||
#include <update_engine/update_metadata.pb.h>
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
|
|
@ -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>;
|
||||
|
@ -1886,12 +1887,15 @@ bool SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manifest
|
|||
// these devices.
|
||||
AutoDeviceList created_devices;
|
||||
|
||||
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};
|
||||
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,
|
||||
.extra_extents = {},
|
||||
};
|
||||
|
||||
if (!CreateUpdateSnapshotsInternal(lock.get(), manifest, &cow_creator, &created_devices,
|
||||
&all_snapshot_status)) {
|
||||
|
@ -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)) {
|
||||
|
@ -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…
Reference in a new issue