From 2e755e38af9e73b802c229e88a3de4e48eaff805 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 31 Jul 2018 13:34:14 -0700 Subject: [PATCH] liblp: Add a ResizePartition helper to MetadataBuilder. This change is to assist with implementing the fastbootd "resize-partition" command. The GrowPartition and ShrinkPartition functions are now private. Bug: 78793464 Test: N/A Change-Id: Ic66a3052359e2558663272ff6e014704206b197e --- fs_mgr/liblp/builder.cpp | 33 ++++++++-------- fs_mgr/liblp/builder_test.cpp | 57 ++++++++++++++-------------- fs_mgr/liblp/include/liblp/builder.h | 29 +++++--------- fs_mgr/liblp/io_test.cpp | 4 +- 4 files changed, 57 insertions(+), 66 deletions(-) diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp index 9d710f90b..d6eee6b32 100644 --- a/fs_mgr/liblp/builder.cpp +++ b/fs_mgr/liblp/builder.cpp @@ -82,11 +82,7 @@ void Partition::RemoveExtents() { extents_.clear(); } -void Partition::ShrinkTo(uint64_t requested_size) { - uint64_t aligned_size = AlignTo(requested_size, LP_SECTOR_SIZE); - if (size_ <= aligned_size) { - return; - } +void Partition::ShrinkTo(uint64_t aligned_size) { if (aligned_size == 0) { RemoveExtents(); return; @@ -106,7 +102,7 @@ void Partition::ShrinkTo(uint64_t requested_size) { sectors_to_remove -= extent->num_sectors(); extents_.pop_back(); } - DCHECK(size_ == requested_size); + DCHECK(size_ == aligned_size); } std::unique_ptr MetadataBuilder::New(const std::string& block_device, @@ -290,13 +286,7 @@ void MetadataBuilder::RemovePartition(const std::string& name) { } } -bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t requested_size) { - // Align the space needed up to the nearest sector. - uint64_t aligned_size = AlignTo(requested_size, LP_SECTOR_SIZE); - if (partition->size() >= aligned_size) { - return true; - } - +bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size) { // Figure out how much we need to allocate. uint64_t space_needed = aligned_size - partition->size(); uint64_t sectors_needed = space_needed / LP_SECTOR_SIZE; @@ -394,8 +384,8 @@ bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t requested_siz return true; } -void MetadataBuilder::ShrinkPartition(Partition* partition, uint64_t requested_size) { - partition->ShrinkTo(requested_size); +void MetadataBuilder::ShrinkPartition(Partition* partition, uint64_t aligned_size) { + partition->ShrinkTo(aligned_size); } std::unique_ptr MetadataBuilder::Export() { @@ -465,5 +455,18 @@ void MetadataBuilder::set_block_device_info(const BlockDeviceInfo& device_info) } } +bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_size) { + // Align the space needed up to the nearest sector. + uint64_t aligned_size = AlignTo(requested_size, LP_SECTOR_SIZE); + + if (aligned_size > partition->size()) { + return GrowPartition(partition, aligned_size); + } + if (aligned_size < partition->size()) { + ShrinkPartition(partition, aligned_size); + } + return true; +} + } // namespace fs_mgr } // namespace android diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp index b610fd4c4..4334d51a5 100644 --- a/fs_mgr/liblp/builder_test.cpp +++ b/fs_mgr/liblp/builder_test.cpp @@ -45,7 +45,7 @@ TEST(liblp, ResizePartition) { Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY); ASSERT_NE(system, nullptr); - EXPECT_EQ(builder->GrowPartition(system, 65536), true); + EXPECT_EQ(builder->ResizePartition(system, 65536), true); EXPECT_EQ(system->size(), 65536); ASSERT_EQ(system->extents().size(), 1); @@ -55,24 +55,23 @@ TEST(liblp, ResizePartition) { // The first logical sector will be (4096+1024*2)/512 = 12. EXPECT_EQ(extent->physical_sector(), 12); - // Test growing to the same size. - EXPECT_EQ(builder->GrowPartition(system, 65536), true); + // Test resizing to the same size. + EXPECT_EQ(builder->ResizePartition(system, 65536), true); EXPECT_EQ(system->size(), 65536); EXPECT_EQ(system->extents().size(), 1); EXPECT_EQ(system->extents()[0]->num_sectors(), 65536 / LP_SECTOR_SIZE); - // Test growing to a smaller size. - EXPECT_EQ(builder->GrowPartition(system, 0), true); - EXPECT_EQ(system->size(), 65536); + // Test resizing to a smaller size. + EXPECT_EQ(builder->ResizePartition(system, 0), true); + EXPECT_EQ(system->size(), 0); + EXPECT_EQ(system->extents().size(), 0); + // Test resizing to a greater size. + builder->ResizePartition(system, 131072); + EXPECT_EQ(system->size(), 131072); EXPECT_EQ(system->extents().size(), 1); - EXPECT_EQ(system->extents()[0]->num_sectors(), 65536 / LP_SECTOR_SIZE); - // Test shrinking to a greater size. - builder->ShrinkPartition(system, 131072); - EXPECT_EQ(system->size(), 65536); - EXPECT_EQ(system->extents().size(), 1); - EXPECT_EQ(system->extents()[0]->num_sectors(), 65536 / LP_SECTOR_SIZE); + EXPECT_EQ(system->extents()[0]->num_sectors(), 131072 / LP_SECTOR_SIZE); // Test shrinking within the same extent. - builder->ShrinkPartition(system, 32768); + builder->ResizePartition(system, 32768); EXPECT_EQ(system->size(), 32768); EXPECT_EQ(system->extents().size(), 1); extent = system->extents()[0]->AsLinearExtent(); @@ -81,7 +80,7 @@ TEST(liblp, ResizePartition) { EXPECT_EQ(extent->physical_sector(), 12); // Test shrinking to 0. - builder->ShrinkPartition(system, 0); + builder->ResizePartition(system, 0); EXPECT_EQ(system->size(), 0); EXPECT_EQ(system->extents().size(), 0); } @@ -92,11 +91,11 @@ TEST(liblp, PartitionAlignment) { // Test that we align up to one sector. Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY); ASSERT_NE(system, nullptr); - EXPECT_EQ(builder->GrowPartition(system, 10000), true); + EXPECT_EQ(builder->ResizePartition(system, 10000), true); EXPECT_EQ(system->size(), 10240); EXPECT_EQ(system->extents().size(), 1); - builder->ShrinkPartition(system, 9000); + builder->ResizePartition(system, 9000); EXPECT_EQ(system->size(), 9216); EXPECT_EQ(system->extents().size(), 1); } @@ -174,8 +173,8 @@ TEST(liblp, InternalPartitionAlignment) { // Add a bunch of small extents to each, interleaving. for (size_t i = 0; i < 10; i++) { - ASSERT_TRUE(builder->GrowPartition(a, a->size() + 4096)); - ASSERT_TRUE(builder->GrowPartition(b, b->size() + 4096)); + ASSERT_TRUE(builder->ResizePartition(a, a->size() + 4096)); + ASSERT_TRUE(builder->ResizePartition(b, b->size() + 4096)); } EXPECT_EQ(a->size(), 40960); EXPECT_EQ(b->size(), 40960); @@ -203,9 +202,9 @@ TEST(liblp, UseAllDiskSpace) { Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY); ASSERT_NE(system, nullptr); - EXPECT_EQ(builder->GrowPartition(system, 1036288), true); + EXPECT_EQ(builder->ResizePartition(system, 1036288), true); EXPECT_EQ(system->size(), 1036288); - EXPECT_EQ(builder->GrowPartition(system, 1036289), false); + EXPECT_EQ(builder->ResizePartition(system, 1036289), false); } TEST(liblp, BuildComplex) { @@ -215,9 +214,9 @@ TEST(liblp, BuildComplex) { Partition* vendor = builder->AddPartition("vendor", TEST_GUID2, LP_PARTITION_ATTR_READONLY); ASSERT_NE(system, nullptr); ASSERT_NE(vendor, nullptr); - EXPECT_EQ(builder->GrowPartition(system, 65536), true); - EXPECT_EQ(builder->GrowPartition(vendor, 32768), true); - EXPECT_EQ(builder->GrowPartition(system, 98304), true); + EXPECT_EQ(builder->ResizePartition(system, 65536), true); + EXPECT_EQ(builder->ResizePartition(vendor, 32768), true); + EXPECT_EQ(builder->ResizePartition(system, 98304), true); EXPECT_EQ(system->size(), 98304); EXPECT_EQ(vendor->size(), 32768); @@ -268,9 +267,9 @@ TEST(liblp, BuilderExport) { Partition* vendor = builder->AddPartition("vendor", TEST_GUID2, LP_PARTITION_ATTR_READONLY); ASSERT_NE(system, nullptr); ASSERT_NE(vendor, nullptr); - EXPECT_EQ(builder->GrowPartition(system, 65536), true); - EXPECT_EQ(builder->GrowPartition(vendor, 32768), true); - EXPECT_EQ(builder->GrowPartition(system, 98304), true); + EXPECT_EQ(builder->ResizePartition(system, 65536), true); + EXPECT_EQ(builder->ResizePartition(vendor, 32768), true); + EXPECT_EQ(builder->ResizePartition(system, 98304), true); unique_ptr exported = builder->Export(); EXPECT_NE(exported, nullptr); @@ -323,9 +322,9 @@ TEST(liblp, BuilderImport) { Partition* vendor = builder->AddPartition("vendor", TEST_GUID2, LP_PARTITION_ATTR_READONLY); ASSERT_NE(system, nullptr); ASSERT_NE(vendor, nullptr); - EXPECT_EQ(builder->GrowPartition(system, 65536), true); - EXPECT_EQ(builder->GrowPartition(vendor, 32768), true); - EXPECT_EQ(builder->GrowPartition(system, 98304), true); + EXPECT_EQ(builder->ResizePartition(system, 65536), true); + EXPECT_EQ(builder->ResizePartition(vendor, 32768), true); + EXPECT_EQ(builder->ResizePartition(system, 98304), true); unique_ptr exported = builder->Export(); ASSERT_NE(exported, nullptr); diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h index 8bde3132c..0f96e3a60 100644 --- a/fs_mgr/liblp/include/liblp/builder.h +++ b/fs_mgr/liblp/include/liblp/builder.h @@ -162,29 +162,17 @@ class MetadataBuilder { // Find a partition by name. If no partition is found, nullptr is returned. Partition* FindPartition(const std::string& name); - // Grow a partition to the requested size. If the partition's size is already - // greater or equal to the requested size, this will return true and the - // partition table will not be changed. Otherwise, a greedy algorithm is - // used to find free gaps in the partition table and allocate them for this - // partition. If not enough space can be allocated, false is returned, and - // the parition table will not be modified. + // Grow or shrink a partition to the requested size. This size will be + // rounded UP to the nearest block (512 bytes). // - // The size will be rounded UP to the nearest sector. + // When growing a partition, a greedy algorithm is used to find free gaps + // in the partition table and allocate them. If not enough space can be + // allocated, false is returned, and the parition table will not be + // modified. // // Note, this is an in-memory operation, and it does not alter the // underlying filesystem or contents of the partition on disk. - bool GrowPartition(Partition* partition, uint64_t requested_size); - - // Shrink a partition to the requested size. If the partition is already - // smaller than the given size, this will return and the partition table - // will not be changed. Otherwise, extents will be removed and/or shrunk - // from the end of the partition until it is the requested size. - // - // The size will be rounded UP to the nearest sector. - // - // Note, this is an in-memory operation, and it does not alter the - // underlying filesystem or contents of the partition on disk. - void ShrinkPartition(Partition* partition, uint64_t requested_size); + bool ResizePartition(Partition* partition, uint64_t requested_size); // Amount of space that can be allocated to logical partitions. uint64_t AllocatableSpace() const; @@ -198,7 +186,8 @@ class MetadataBuilder { MetadataBuilder(); bool Init(const BlockDeviceInfo& info, uint32_t metadata_max_size, uint32_t metadata_slot_count); bool Init(const LpMetadata& metadata); - + bool GrowPartition(Partition* partition, uint64_t aligned_size); + void ShrinkPartition(Partition* partition, uint64_t aligned_size); uint64_t AlignSector(uint64_t sector); LpMetadataGeometry geometry_; diff --git a/fs_mgr/liblp/io_test.cpp b/fs_mgr/liblp/io_test.cpp index bbbedc761..638f4b310 100644 --- a/fs_mgr/liblp/io_test.cpp +++ b/fs_mgr/liblp/io_test.cpp @@ -85,7 +85,7 @@ static bool AddDefaultPartitions(MetadataBuilder* builder) { if (!system) { return false; } - return builder->GrowPartition(system, 24 * 1024); + return builder->ResizePartition(system, 24 * 1024); } // Create a temporary disk and flash it with the default partition setup. @@ -345,7 +345,7 @@ TEST(liblp, TooManyPartitions) { ASSERT_NE(partition, nullptr); // Add one extent to any partition to fill up more space - we're at 508 // bytes after this, out of 512. - ASSERT_TRUE(builder->GrowPartition(partition, 1024)); + ASSERT_TRUE(builder->ResizePartition(partition, 1024)); unique_ptr exported = builder->Export(); ASSERT_NE(exported, nullptr);