Fix double-accounting bug in liblp.
When flashing in fastbootd, we create a new MetadataBuilder using the given super_empty.img and attempt to import the existing partition table. This will fail if there is some incompatibility in the partition layout or partition quotas. This import code was accidentally double-accounting partitions when determining if they could fit within the group quota, preventing "fastboot flashall" once partitions reached a certain size. Bug: 126930319 Test: liblp_test gtest Change-Id: I89a69cba110b62719197c9a4885cfc5bcf8f009f
This commit is contained in:
parent
33f344cb36
commit
88e36c1514
|
@ -550,11 +550,11 @@ auto MetadataBuilder::GetFreeRegions() const -> std::vector<Interval> {
|
|||
}
|
||||
|
||||
bool MetadataBuilder::ValidatePartitionSizeChange(Partition* partition, uint64_t old_size,
|
||||
uint64_t new_size) {
|
||||
uint64_t new_size, bool force_check) {
|
||||
PartitionGroup* group = FindGroup(partition->group_name());
|
||||
CHECK(group);
|
||||
|
||||
if (new_size <= old_size) {
|
||||
if (!force_check && new_size <= old_size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -861,7 +861,7 @@ bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_s
|
|||
uint64_t aligned_size = AlignTo(requested_size, geometry_.logical_block_size);
|
||||
uint64_t old_size = partition->size();
|
||||
|
||||
if (!ValidatePartitionSizeChange(partition, old_size, aligned_size)) {
|
||||
if (!ValidatePartitionSizeChange(partition, old_size, aligned_size, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -973,7 +973,12 @@ bool MetadataBuilder::ImportPartition(const LpMetadata& metadata,
|
|||
|
||||
ImportExtents(partition, metadata, source);
|
||||
|
||||
if (!ValidatePartitionSizeChange(partition, 0, partition->size())) {
|
||||
// Note: we've already increased the partition size by calling
|
||||
// ImportExtents(). In order to figure out the size before that,
|
||||
// we would have to iterate the extents and add up the linear
|
||||
// segments. Instead, we just force ValidatePartitionSizeChange
|
||||
// to check if the current configuration is acceptable.
|
||||
if (!ValidatePartitionSizeChange(partition, partition->size(), partition->size(), true)) {
|
||||
partition->RemoveExtents();
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -835,3 +835,73 @@ TEST_F(BuilderTest, PartialExtents) {
|
|||
EXPECT_EQ(exported->extents[1].target_data, 4608);
|
||||
EXPECT_EQ(exported->extents[1].num_sectors, 1536);
|
||||
}
|
||||
|
||||
TEST_F(BuilderTest, UpdateSuper) {
|
||||
// Build the on-disk metadata that we saw before flashing.
|
||||
auto builder = MetadataBuilder::New(8145338368ULL, 65536, 3);
|
||||
ASSERT_NE(builder, nullptr);
|
||||
|
||||
ASSERT_TRUE(builder->AddGroup("google_dynamic_partitions_a", 4068474880ULL));
|
||||
ASSERT_TRUE(builder->AddGroup("google_dynamic_partitions_b", 4068474880ULL));
|
||||
|
||||
Partition* partition = builder->AddPartition("system_a", "google_dynamic_partitions_a",
|
||||
LP_PARTITION_ATTR_READONLY);
|
||||
ASSERT_NE(partition, nullptr);
|
||||
ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 1901568, 3608576));
|
||||
|
||||
partition = builder->AddPartition("vendor_a", "google_dynamic_partitions_a",
|
||||
LP_PARTITION_ATTR_READONLY);
|
||||
ASSERT_NE(partition, nullptr);
|
||||
ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 1521664, 5510144));
|
||||
|
||||
partition = builder->AddPartition("product_a", "google_dynamic_partitions_a",
|
||||
LP_PARTITION_ATTR_READONLY);
|
||||
ASSERT_NE(partition, nullptr);
|
||||
ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 3606528, 2048));
|
||||
|
||||
partition = builder->AddPartition("system_b", "google_dynamic_partitions_b",
|
||||
LP_PARTITION_ATTR_READONLY);
|
||||
ASSERT_NE(partition, nullptr);
|
||||
ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 1901568, 7955456));
|
||||
|
||||
partition = builder->AddPartition("vendor_b", "google_dynamic_partitions_b",
|
||||
LP_PARTITION_ATTR_READONLY);
|
||||
ASSERT_NE(partition, nullptr);
|
||||
ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 1521664, 9857024));
|
||||
|
||||
partition = builder->AddPartition("product_b", "google_dynamic_partitions_b",
|
||||
LP_PARTITION_ATTR_READONLY);
|
||||
ASSERT_NE(partition, nullptr);
|
||||
ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 3606528, 11378688));
|
||||
|
||||
auto on_disk = builder->Export();
|
||||
ASSERT_NE(on_disk, nullptr);
|
||||
|
||||
// Build the super_empty from the new build.
|
||||
builder = MetadataBuilder::New(8145338368ULL, 65536, 3);
|
||||
ASSERT_NE(builder, nullptr);
|
||||
|
||||
ASSERT_TRUE(builder->AddGroup("google_dynamic_partitions_a", 4068474880ULL));
|
||||
ASSERT_TRUE(builder->AddGroup("google_dynamic_partitions_b", 4068474880ULL));
|
||||
ASSERT_NE(builder->AddPartition("system_a", "google_dynamic_partitions_a",
|
||||
LP_PARTITION_ATTR_READONLY),
|
||||
nullptr);
|
||||
ASSERT_NE(builder->AddPartition("system_b", "google_dynamic_partitions_b",
|
||||
LP_PARTITION_ATTR_READONLY),
|
||||
nullptr);
|
||||
ASSERT_NE(builder->AddPartition("vendor_a", "google_dynamic_partitions_a",
|
||||
LP_PARTITION_ATTR_READONLY),
|
||||
nullptr);
|
||||
ASSERT_NE(builder->AddPartition("vendor_b", "google_dynamic_partitions_b",
|
||||
LP_PARTITION_ATTR_READONLY),
|
||||
nullptr);
|
||||
ASSERT_NE(builder->AddPartition("product_a", "google_dynamic_partitions_a",
|
||||
LP_PARTITION_ATTR_READONLY),
|
||||
nullptr);
|
||||
ASSERT_NE(builder->AddPartition("product_b", "google_dynamic_partitions_b",
|
||||
LP_PARTITION_ATTR_READONLY),
|
||||
nullptr);
|
||||
|
||||
std::set<std::string> partitions_to_keep{"system_a", "vendor_a", "product_a"};
|
||||
ASSERT_TRUE(builder->ImportPartitions(*on_disk.get(), partitions_to_keep));
|
||||
}
|
||||
|
|
|
@ -297,7 +297,8 @@ class MetadataBuilder {
|
|||
uint64_t TotalSizeOfGroup(PartitionGroup* group) const;
|
||||
bool UpdateBlockDeviceInfo(size_t index, const BlockDeviceInfo& info);
|
||||
bool FindBlockDeviceByName(const std::string& partition_name, uint32_t* index) const;
|
||||
bool ValidatePartitionSizeChange(Partition* partition, uint64_t old_size, uint64_t new_size);
|
||||
bool ValidatePartitionSizeChange(Partition* partition, uint64_t old_size, uint64_t new_size,
|
||||
bool force_check);
|
||||
void ImportExtents(Partition* dest, const LpMetadata& metadata,
|
||||
const LpMetadataPartition& source);
|
||||
bool ImportPartition(const LpMetadata& metadata, const LpMetadataPartition& source);
|
||||
|
|
Loading…
Reference in New Issue