libsnapshot: Use the compression algorithm specified in the DeltaArchiveManifest.

update_engine and libsnapshot must agree on CowOptions parameters,
otherwise the COW size estimation may be incorrect.

Bug: N/A
Test: vts_libsnapshot_test
      apply OTA, snapshotctl dump
Change-Id: I219ae458dfa19e4b3c96360d3b847edb2a01ebc8
This commit is contained in:
David Anderson 2021-02-24 22:05:35 -08:00
parent e886702132
commit cbc204b39b
5 changed files with 36 additions and 6 deletions

View File

@ -46,7 +46,7 @@ enum MergePhase {
SECOND_PHASE = 2; SECOND_PHASE = 2;
} }
// Next: 11 // Next: 12
message SnapshotStatus { message SnapshotStatus {
// Name of the snapshot. This is usually the name of the snapshotted // Name of the snapshot. This is usually the name of the snapshotted
// logical partition; for example, "system_b". // logical partition; for example, "system_b".
@ -102,6 +102,9 @@ message SnapshotStatus {
// The old partition size (if none existed, this will be zero). // The old partition size (if none existed, this will be zero).
uint64 old_partition_size = 10; uint64 old_partition_size = 10;
// Compression algorithm (none, gz, or brotli).
string compression_algorithm = 11;
} }
// Next: 8 // Next: 8

View File

@ -58,6 +58,7 @@ struct PartitionCowCreator {
std::vector<ChromeOSExtent> extra_extents = {}; std::vector<ChromeOSExtent> extra_extents = {};
// True if compression is enabled. // True if compression is enabled.
bool compression_enabled = false; bool compression_enabled = false;
std::string compression_algorithm;
struct Return { struct Return {
SnapshotStatus snapshot_status; SnapshotStatus snapshot_status;

View File

@ -359,6 +359,7 @@ bool SnapshotManager::CreateSnapshot(LockedFile* lock, PartitionCowCreator* cow_
status->set_sectors_allocated(0); status->set_sectors_allocated(0);
status->set_metadata_sectors(0); status->set_metadata_sectors(0);
status->set_compression_enabled(cow_creator->compression_enabled); status->set_compression_enabled(cow_creator->compression_enabled);
status->set_compression_algorithm(cow_creator->compression_algorithm);
if (!WriteSnapshotStatus(lock, *status)) { if (!WriteSnapshotStatus(lock, *status)) {
PLOG(ERROR) << "Could not write snapshot status: " << status->name(); PLOG(ERROR) << "Could not write snapshot status: " << status->name();
@ -2660,9 +2661,20 @@ Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manife
// these devices. // these devices.
AutoDeviceList created_devices; AutoDeviceList created_devices;
bool use_compression = IsCompressionEnabled() && const auto& dap_metadata = manifest.dynamic_partition_metadata();
manifest.dynamic_partition_metadata().vabc_enabled() && bool use_compression =
!device_->IsRecovery(); IsCompressionEnabled() && dap_metadata.vabc_enabled() && !device_->IsRecovery();
std::string compression_algorithm;
if (use_compression) {
compression_algorithm = dap_metadata.vabc_compression_param();
if (compression_algorithm.empty()) {
// Older OTAs don't set an explicit compression type, so default to gz.
compression_algorithm = "gz";
}
} else {
compression_algorithm = "none";
}
PartitionCowCreator cow_creator{ PartitionCowCreator cow_creator{
.target_metadata = target_metadata.get(), .target_metadata = target_metadata.get(),
@ -2673,6 +2685,7 @@ Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manife
.update = nullptr, .update = nullptr,
.extra_extents = {}, .extra_extents = {},
.compression_enabled = use_compression, .compression_enabled = use_compression,
.compression_algorithm = compression_algorithm,
}; };
auto ret = CreateUpdateSnapshotsInternal(lock.get(), manifest, &cow_creator, &created_devices, auto ret = CreateUpdateSnapshotsInternal(lock.get(), manifest, &cow_creator, &created_devices,
@ -2917,7 +2930,7 @@ Return SnapshotManager::InitializeUpdateSnapshots(
return Return::Error(); return Return::Error();
} }
CowWriter writer(CowOptions{}); CowWriter writer(CowOptions{.compression = it->second.compression_algorithm()});
if (!writer.Initialize(fd) || !writer.Finalize()) { if (!writer.Initialize(fd) || !writer.Finalize()) {
LOG(ERROR) << "Could not initialize COW device for " << target_partition->name(); LOG(ERROR) << "Could not initialize COW device for " << target_partition->name();
return Return::Error(); return Return::Error();
@ -3024,7 +3037,7 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenCompressedSnapshotWriter(
CHECK(lock); CHECK(lock);
CowOptions cow_options; CowOptions cow_options;
cow_options.compression = "gz"; cow_options.compression = status.compression_algorithm();
cow_options.max_blocks = {status.device_size() / cow_options.block_size}; cow_options.max_blocks = {status.device_size() / cow_options.block_size};
// Currently we don't support partial snapshots, since partition_cow_creator // Currently we don't support partial snapshots, since partition_cow_creator
@ -3163,6 +3176,7 @@ bool SnapshotManager::Dump(std::ostream& os) {
ss << " cow file size (bytes): " << status.cow_file_size() << std::endl; ss << " cow file size (bytes): " << status.cow_file_size() << std::endl;
ss << " allocated sectors: " << status.sectors_allocated() << std::endl; ss << " allocated sectors: " << status.sectors_allocated() << std::endl;
ss << " metadata sectors: " << status.metadata_sectors() << std::endl; ss << " metadata sectors: " << status.metadata_sectors() << std::endl;
ss << " compression: " << status.compression_algorithm() << std::endl;
} }
os << ss.rdbuf(); os << ss.rdbuf();
return ok; return ok;

View File

@ -423,6 +423,11 @@ TEST_F(SnapshotTest, CreateSnapshot) {
PartitionCowCreator cow_creator; PartitionCowCreator cow_creator;
cow_creator.compression_enabled = IsCompressionEnabled(); cow_creator.compression_enabled = IsCompressionEnabled();
if (cow_creator.compression_enabled) {
cow_creator.compression_algorithm = "gz";
} else {
cow_creator.compression_algorithm = "none";
}
static const uint64_t kDeviceSize = 1024 * 1024; static const uint64_t kDeviceSize = 1024 * 1024;
SnapshotStatus status; SnapshotStatus status;
@ -446,6 +451,7 @@ TEST_F(SnapshotTest, CreateSnapshot) {
ASSERT_EQ(status.device_size(), kDeviceSize); ASSERT_EQ(status.device_size(), kDeviceSize);
ASSERT_EQ(status.snapshot_size(), kDeviceSize); ASSERT_EQ(status.snapshot_size(), kDeviceSize);
ASSERT_EQ(status.compression_enabled(), cow_creator.compression_enabled); ASSERT_EQ(status.compression_enabled(), cow_creator.compression_enabled);
ASSERT_EQ(status.compression_algorithm(), cow_creator.compression_algorithm);
} }
ASSERT_TRUE(sm->UnmapSnapshot(lock_.get(), "test-snapshot")); ASSERT_TRUE(sm->UnmapSnapshot(lock_.get(), "test-snapshot"));
@ -576,6 +582,11 @@ TEST_F(SnapshotTest, FirstStageMountAndMerge) {
SnapshotStatus status; SnapshotStatus status;
ASSERT_TRUE(init->ReadSnapshotStatus(lock_.get(), "test_partition_b", &status)); ASSERT_TRUE(init->ReadSnapshotStatus(lock_.get(), "test_partition_b", &status));
ASSERT_EQ(status.state(), SnapshotState::CREATED); ASSERT_EQ(status.state(), SnapshotState::CREATED);
if (IsCompressionEnabled()) {
ASSERT_EQ(status.compression_algorithm(), "gz");
} else {
ASSERT_EQ(status.compression_algorithm(), "none");
}
DeviceMapper::TargetInfo target; DeviceMapper::TargetInfo target;
ASSERT_TRUE(init->IsSnapshotDevice("test_partition_b", &target)); ASSERT_TRUE(init->IsSnapshotDevice("test_partition_b", &target));

View File

@ -74,6 +74,7 @@ message DynamicPartitionGroup {
message DynamicPartitionMetadata { message DynamicPartitionMetadata {
repeated DynamicPartitionGroup groups = 1; repeated DynamicPartitionGroup groups = 1;
optional bool vabc_enabled = 3; optional bool vabc_enabled = 3;
optional string vabc_compression_param = 4;
} }
message DeltaArchiveManifest { message DeltaArchiveManifest {