liblp: Add MetadataBuilder helpers for pruning unused groups.

These will help update_engine clear the target slot before applying an OTA.

Bug: 117182932
Test: liblp_test gtest
Change-Id: I6ad370e617f22f2098245a0028a93488f9ac8674
This commit is contained in:
David Anderson 2018-10-18 15:29:01 -07:00
parent 11440493a7
commit 5cb50a24bc
4 changed files with 75 additions and 3 deletions

View File

@ -47,6 +47,9 @@ cc_test {
cppflags: [
"-Wno-unused-parameter",
],
static_libs: [
"libgmock",
],
shared_libs: [
"liblp",
"libbase",

View File

@ -339,7 +339,7 @@ Partition* MetadataBuilder::FindPartition(const std::string& name) {
return nullptr;
}
PartitionGroup* MetadataBuilder::FindGroup(const std::string& group_name) const {
PartitionGroup* MetadataBuilder::FindGroup(const std::string& group_name) {
for (const auto& group : groups_) {
if (group->name() == group_name) {
return group.get();
@ -624,5 +624,36 @@ bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_s
return true;
}
std::vector<std::string> MetadataBuilder::ListGroups() const {
std::vector<std::string> names;
for (const auto& group : groups_) {
names.emplace_back(group->name());
}
return names;
}
void MetadataBuilder::RemoveGroupAndPartitions(const std::string& group_name) {
if (group_name == "default") {
// Cannot remove the default group.
return;
}
std::vector<std::string> partition_names;
for (const auto& partition : partitions_) {
if (partition->group_name() == group_name) {
partition_names.emplace_back(partition->name());
}
}
for (const auto& partition_name : partition_names) {
RemovePartition(partition_name);
}
for (auto iter = groups_.begin(); iter != groups_.end(); iter++) {
if ((*iter)->name() == group_name) {
groups_.erase(iter);
break;
}
}
}
} // namespace fs_mgr
} // namespace android

View File

@ -14,13 +14,16 @@
* limitations under the License.
*/
#include <fs_mgr.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <liblp/builder.h>
#include "fs_mgr.h"
#include "utility.h"
using namespace std;
using namespace android::fs_mgr;
using ::testing::ElementsAre;
TEST(liblp, BuildBasic) {
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
@ -542,3 +545,30 @@ TEST(liblp, RemoveAndAddFirstPartition) {
p = builder->AddPartition("vendor_a", "foo_a", 0);
ASSERT_TRUE(p && builder->ResizePartition(p, 1_GiB));
}
TEST(liblp, ListGroups) {
BlockDeviceInfo device_info(1024 * 1024, 0, 0, 4096);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
ASSERT_NE(builder, nullptr);
ASSERT_TRUE(builder->AddGroup("example", 0));
std::vector<std::string> groups = builder->ListGroups();
ASSERT_THAT(groups, ElementsAre("default", "example"));
}
TEST(liblp, RemoveGroupAndPartitions) {
BlockDeviceInfo device_info(1024 * 1024, 0, 0, 4096);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
ASSERT_NE(builder, nullptr);
ASSERT_TRUE(builder->AddGroup("example", 0));
ASSERT_NE(builder->AddPartition("system", "default", 0), nullptr);
ASSERT_NE(builder->AddPartition("vendor", "example", 0), nullptr);
builder->RemoveGroupAndPartitions("example");
ASSERT_NE(builder->FindPartition("system"), nullptr);
ASSERT_EQ(builder->FindPartition("vendor"), nullptr);
ASSERT_THAT(builder->ListGroups(), ElementsAre("default"));
builder->RemoveGroupAndPartitions("default");
ASSERT_NE(builder->FindPartition("system"), nullptr);
}

View File

@ -199,6 +199,9 @@ class MetadataBuilder {
// Find a partition by name. If no partition is found, nullptr is returned.
Partition* FindPartition(const std::string& name);
// Find a group by name. If no group is found, nullptr is returned.
PartitionGroup* FindGroup(const std::string& name);
// Grow or shrink a partition to the requested size. This size will be
// rounded UP to the nearest block (512 bytes).
//
@ -215,6 +218,12 @@ class MetadataBuilder {
uint64_t AllocatableSpace() const;
uint64_t UsedSpace() const;
// Return a list of all group names.
std::vector<std::string> ListGroups() const;
// Remove all partitions belonging to a group, then remove the group.
void RemoveGroupAndPartitions(const std::string& group_name);
bool GetBlockDeviceInfo(BlockDeviceInfo* info) const;
bool UpdateBlockDeviceInfo(const BlockDeviceInfo& info);
@ -229,7 +238,6 @@ class MetadataBuilder {
bool GrowPartition(Partition* partition, uint64_t aligned_size);
void ShrinkPartition(Partition* partition, uint64_t aligned_size);
uint64_t AlignSector(uint64_t sector) const;
PartitionGroup* FindGroup(const std::string& group_name) const;
uint64_t TotalSizeOfGroup(PartitionGroup* group) const;
struct Interval {