diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h index 7411e5a01..8e3875fa6 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h @@ -72,6 +72,8 @@ class SnapshotStatus; static constexpr const std::string_view kCowGroupName = "cow"; +bool SourceCopyOperationIsClone(const chromeos_update_engine::InstallOperation& operation); + enum class UpdateState : unsigned int { // No update or merge is in progress. None, diff --git a/fs_mgr/libsnapshot/partition_cow_creator.cpp b/fs_mgr/libsnapshot/partition_cow_creator.cpp index 0ba2a88e7..61f5c0cab 100644 --- a/fs_mgr/libsnapshot/partition_cow_creator.cpp +++ b/fs_mgr/libsnapshot/partition_cow_creator.cpp @@ -62,6 +62,19 @@ bool PartitionCowCreator::HasExtent(Partition* p, Extent* e) { return false; } +bool SourceCopyOperationIsClone(const InstallOperation& operation) { + using ChromeOSExtent = chromeos_update_engine::Extent; + if (operation.src_extents().size() != operation.dst_extents().size()) { + return false; + } + return std::equal(operation.src_extents().begin(), operation.src_extents().end(), + operation.dst_extents().begin(), + [](const ChromeOSExtent& src, const ChromeOSExtent& dst) { + return src.start_block() == dst.start_block() && + src.num_blocks() == dst.num_blocks(); + }); +} + 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(); @@ -88,6 +101,11 @@ uint64_t PartitionCowCreator::GetCowSize() { if (operations == nullptr) return sc.cow_size_bytes(); for (const auto& iop : *operations) { + // Do not allocate space for operations that are going to be skipped + // during OTA application. + if (iop.type() == InstallOperation::SOURCE_COPY && SourceCopyOperationIsClone(iop)) + continue; + for (const auto& de : iop.dst_extents()) { WriteExtent(&sc, de, sectors_per_block); }