Loading fs_mgr/liblp/builder.cpp +103 −8 Original line number Diff line number Diff line Loading @@ -79,8 +79,9 @@ void ZeroExtent::AddTo(LpMetadata* out) const { out->extents.push_back(LpMetadataExtent{num_sectors_, LP_TARGET_TYPE_ZERO, 0}); } Partition::Partition(const std::string& name, const std::string& guid, uint32_t attributes) : name_(name), guid_(guid), attributes_(attributes), size_(0) {} Partition::Partition(const std::string& name, const std::string& group_name, const std::string& guid, uint32_t attributes) : name_(name), group_name_(group_name), guid_(guid), attributes_(attributes), size_(0) {} void Partition::AddExtent(std::unique_ptr<Extent>&& extent) { size_ += extent->num_sectors() * LP_SECTOR_SIZE; Loading Loading @@ -128,6 +129,17 @@ void Partition::ShrinkTo(uint64_t aligned_size) { DCHECK(size_ == aligned_size); } uint64_t Partition::BytesOnDisk() const { uint64_t sectors = 0; for (const auto& extent : extents_) { if (!extent->AsLinearExtent()) { continue; } sectors += extent->num_sectors(); } return sectors * LP_SECTOR_SIZE; } std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const std::string& block_device, uint32_t slot_number) { std::unique_ptr<LpMetadata> metadata = ReadMetadata(block_device.c_str(), slot_number); Loading Loading @@ -175,14 +187,23 @@ MetadataBuilder::MetadataBuilder() { header_.header_size = sizeof(header_); header_.partitions.entry_size = sizeof(LpMetadataPartition); header_.extents.entry_size = sizeof(LpMetadataExtent); header_.groups.entry_size = sizeof(LpMetadataPartitionGroup); } bool MetadataBuilder::Init(const LpMetadata& metadata) { geometry_ = metadata.geometry; for (const auto& group : metadata.groups) { std::string group_name = GetPartitionGroupName(group); if (!AddGroup(group_name, group.maximum_size)) { return false; } } for (const auto& partition : metadata.partitions) { Partition* builder = AddPartition(GetPartitionName(partition), GetPartitionGuid(partition), partition.attributes); std::string group_name = GetPartitionGroupName(metadata.groups[partition.group_index]); Partition* builder = AddPartition(GetPartitionName(partition), group_name, GetPartitionGuid(partition), partition.attributes); if (!builder) { return false; } Loading Loading @@ -292,11 +313,29 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata geometry_.alignment_offset = device_info_.alignment_offset; geometry_.block_device_size = device_info_.size; geometry_.logical_block_size = device_info.logical_block_size; if (!AddGroup("default", 0)) { return false; } return true; } bool MetadataBuilder::AddGroup(const std::string& group_name, uint64_t maximum_size) { if (FindGroup(group_name)) { LERROR << "Group already exists: " << group_name; return false; } groups_.push_back(std::make_unique<PartitionGroup>(group_name, maximum_size)); return true; } Partition* MetadataBuilder::AddPartition(const std::string& name, const std::string& guid, uint32_t attributes) { return AddPartition(name, "default", guid, attributes); } Partition* MetadataBuilder::AddPartition(const std::string& name, const std::string& group_name, const std::string& guid, uint32_t attributes) { if (name.empty()) { LERROR << "Partition must have a non-empty name."; return nullptr; Loading @@ -305,7 +344,11 @@ Partition* MetadataBuilder::AddPartition(const std::string& name, const std::str LERROR << "Attempting to create duplication partition with name: " << name; return nullptr; } partitions_.push_back(std::make_unique<Partition>(name, guid, attributes)); if (!FindGroup(group_name)) { LERROR << "Could not find partition group: " << group_name; return nullptr; } partitions_.push_back(std::make_unique<Partition>(name, group_name, guid, attributes)); return partitions_.back().get(); } Loading @@ -318,6 +361,26 @@ Partition* MetadataBuilder::FindPartition(const std::string& name) { return nullptr; } PartitionGroup* MetadataBuilder::FindGroup(const std::string& group_name) const { for (const auto& group : groups_) { if (group->name() == group_name) { return group.get(); } } return nullptr; } uint64_t MetadataBuilder::TotalSizeOfGroup(PartitionGroup* group) const { uint64_t total = 0; for (const auto& partition : partitions_) { if (partition->group_name() != group->name()) { continue; } total += partition->BytesOnDisk(); } return total; } void MetadataBuilder::RemovePartition(const std::string& name) { for (auto iter = partitions_.begin(); iter != partitions_.end(); iter++) { if ((*iter)->name() == name) { Loading @@ -328,8 +391,23 @@ void MetadataBuilder::RemovePartition(const std::string& name) { } bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size) { // Figure out how much we need to allocate. PartitionGroup* group = FindGroup(partition->group_name()); CHECK(group); // Figure out how much we need to allocate, and whether our group has // enough space remaining. uint64_t space_needed = aligned_size - partition->size(); if (group->maximum_size() > 0) { uint64_t group_size = TotalSizeOfGroup(group); if (group_size >= group->maximum_size() || group->maximum_size() - group_size < space_needed) { LERROR << "Partition " << partition->name() << " is part of group " << group->name() << " which does not have enough space free (" << space_needed << "requested, " << group_size << " used out of " << group->maximum_size(); return false; } } uint64_t sectors_needed = space_needed / LP_SECTOR_SIZE; DCHECK(sectors_needed * LP_SECTOR_SIZE == space_needed); Loading Loading @@ -441,6 +519,20 @@ std::unique_ptr<LpMetadata> MetadataBuilder::Export() { metadata->header = header_; metadata->geometry = geometry_; std::map<std::string, size_t> group_indices; for (const auto& group : groups_) { LpMetadataPartitionGroup out = {}; if (group->name().size() > sizeof(out.name)) { LERROR << "Partition group name is too long: " << group->name(); return nullptr; } strncpy(out.name, group->name().c_str(), sizeof(out.name)); out.maximum_size = group->maximum_size(); metadata->groups.push_back(out); } // Flatten the partition and extent structures into an LpMetadata, which // makes it very easy to validate, serialize, or pass on to device-mapper. for (const auto& partition : partitions_) { Loading Loading @@ -475,6 +567,7 @@ std::unique_ptr<LpMetadata> MetadataBuilder::Export() { metadata->header.partitions.num_entries = static_cast<uint32_t>(metadata->partitions.size()); metadata->header.extents.num_entries = static_cast<uint32_t>(metadata->extents.size()); metadata->header.groups.num_entries = static_cast<uint32_t>(metadata->groups.size()); return metadata; } Loading Loading @@ -530,8 +623,10 @@ bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_s ShrinkPartition(partition, aligned_size); } LINFO << "Partition " << partition->name() << " will resize from " << old_size << " bytes to " << aligned_size << " bytes"; if (partition->size() != old_size) { LINFO << "Partition " << partition->name() << " will resize from " << old_size << " bytes to " << aligned_size << " bytes"; } return true; } Loading fs_mgr/liblp/builder_test.cpp +25 −0 Original line number Diff line number Diff line Loading @@ -495,3 +495,28 @@ TEST(liblp, AlignedFreeSpace) { unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 512, 1); ASSERT_EQ(builder, nullptr); } TEST(liblp, HasDefaultGroup) { BlockDeviceInfo device_info(1024 * 1024, 0, 0, 4096); unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1); ASSERT_NE(builder, nullptr); EXPECT_FALSE(builder->AddGroup("default", 0)); } TEST(liblp, GroupSizeLimits) { 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("google", 16384)); Partition* partition = builder->AddPartition("system", "google", TEST_GUID, 0); ASSERT_NE(partition, nullptr); EXPECT_TRUE(builder->ResizePartition(partition, 8192)); EXPECT_EQ(partition->size(), 8192); EXPECT_TRUE(builder->ResizePartition(partition, 16384)); EXPECT_EQ(partition->size(), 16384); EXPECT_FALSE(builder->ResizePartition(partition, 32768)); EXPECT_EQ(partition->size(), 16384); } fs_mgr/liblp/include/liblp/builder.h +36 −1 Original line number Diff line number Diff line Loading @@ -95,11 +95,25 @@ class ZeroExtent final : public Extent { void AddTo(LpMetadata* out) const override; }; class PartitionGroup final { public: explicit PartitionGroup(const std::string& name, uint64_t maximum_size) : name_(name), maximum_size_(maximum_size) {} const std::string& name() const { return name_; } uint64_t maximum_size() const { return maximum_size_; } private: std::string name_; uint64_t maximum_size_; }; class Partition final { friend class MetadataBuilder; public: Partition(const std::string& name, const std::string& guid, uint32_t attributes); Partition(const std::string& name, const std::string& group_name, const std::string& guid, uint32_t attributes); // Add a raw extent. void AddExtent(std::unique_ptr<Extent>&& extent); Loading @@ -107,7 +121,12 @@ class Partition final { // Remove all extents from this partition. void RemoveExtents(); // Compute the size used by linear extents. This is the same as size(), // but does not factor in extents which do not take up space. uint64_t BytesOnDisk() const; const std::string& name() const { return name_; } const std::string& group_name() const { return group_name_; } uint32_t attributes() const { return attributes_; } const std::string& guid() const { return guid_; } const std::vector<std::unique_ptr<Extent>>& extents() const { return extents_; } Loading @@ -117,6 +136,7 @@ class Partition final { void ShrinkTo(uint64_t aligned_size); std::string name_; std::string group_name_; std::string guid_; std::vector<std::unique_ptr<Extent>> extents_; uint32_t attributes_; Loading Loading @@ -156,12 +176,24 @@ class MetadataBuilder { return New(device_info, metadata_max_size, metadata_slot_count); } // Define a new partition group. By default there is one group called // "default", with an unrestricted size. A non-zero size will restrict the // total space used by all partitions in the group. // // This can fail and return false if the group already exists. bool AddGroup(const std::string& group_name, uint64_t maximum_size); // Export metadata so it can be serialized to an image, to disk, or mounted // via device-mapper. std::unique_ptr<LpMetadata> Export(); // Add a partition, returning a handle so it can be sized as needed. If a // partition with the given name already exists, nullptr is returned. Partition* AddPartition(const std::string& name, const std::string& group_name, const std::string& guid, uint32_t attributes); // Same as AddPartition above, but uses the default partition group which // has no size restrictions. Partition* AddPartition(const std::string& name, const std::string& guid, uint32_t attributes); // Delete a partition by name if it exists. Loading Loading @@ -202,10 +234,13 @@ class MetadataBuilder { bool GrowPartition(Partition* partition, uint64_t aligned_size); void ShrinkPartition(Partition* partition, uint64_t aligned_size); uint64_t AlignSector(uint64_t sector); PartitionGroup* FindGroup(const std::string& group_name) const; uint64_t TotalSizeOfGroup(PartitionGroup* group) const; LpMetadataGeometry geometry_; LpMetadataHeader header_; std::vector<std::unique_ptr<Partition>> partitions_; std::vector<std::unique_ptr<PartitionGroup>> groups_; BlockDeviceInfo device_info_; }; Loading fs_mgr/liblp/include/liblp/liblp.h +2 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ struct LpMetadata { LpMetadataHeader header; std::vector<LpMetadataPartition> partitions; std::vector<LpMetadataExtent> extents; std::vector<LpMetadataPartitionGroup> groups; }; // Place an initial partition table on the device. This will overwrite the Loading Loading @@ -68,6 +69,7 @@ std::unique_ptr<LpMetadata> ReadFromImageBlob(const void* data, size_t bytes); // Helper to extract safe C++ strings from partition info. std::string GetPartitionName(const LpMetadataPartition& partition); std::string GetPartitionGuid(const LpMetadataPartition& partition); std::string GetPartitionGroupName(const LpMetadataPartitionGroup& group); // Helper to return a slot number for a slot suffix. uint32_t SlotNumberForSlotSuffix(const std::string& suffix); Loading fs_mgr/liblp/include/liblp/metadata_format.h +19 −1 Original line number Diff line number Diff line Loading @@ -38,7 +38,7 @@ extern "C" { #define LP_METADATA_HEADER_MAGIC 0x414C5030 /* Current metadata version. */ #define LP_METADATA_MAJOR_VERSION 1 #define LP_METADATA_MAJOR_VERSION 2 #define LP_METADATA_MINOR_VERSION 0 /* Attributes for the LpMetadataPartition::attributes field. Loading Loading @@ -216,6 +216,8 @@ typedef struct LpMetadataHeader { LpMetadataTableDescriptor partitions; /* 92: Extent table descriptor. */ LpMetadataTableDescriptor extents; /* 104: Updateable group descriptor. */ LpMetadataTableDescriptor groups; } __attribute__((packed)) LpMetadataHeader; /* This struct defines a logical partition entry, similar to what would be Loading Loading @@ -245,6 +247,9 @@ typedef struct LpMetadataPartition { * least one extent. */ uint32_t num_extents; /* 64: Group this partition belongs to. */ uint32_t group_index; } __attribute__((packed)) LpMetadataPartition; /* This extent is a dm-linear target, and the index is an index into the Loading @@ -271,6 +276,19 @@ typedef struct LpMetadataExtent { uint64_t target_data; } __attribute__((packed)) LpMetadataExtent; /* This struct defines an entry in the groups table. Each group has a maximum * size, and partitions in a group must not exceed that size. There is always * a "default" group of unlimited size, which is used when not using update * groups or when using overlayfs or fastbootd. */ typedef struct LpMetadataPartitionGroup { /* 0: Name of this group. Any unused characters must be 0. */ char name[36]; /* 36: Maximum size in bytes. If 0, the group has no maximum size. */ uint64_t maximum_size; } LpMetadataPartitionGroup; #ifdef __cplusplus } /* extern "C" */ #endif Loading Loading
fs_mgr/liblp/builder.cpp +103 −8 Original line number Diff line number Diff line Loading @@ -79,8 +79,9 @@ void ZeroExtent::AddTo(LpMetadata* out) const { out->extents.push_back(LpMetadataExtent{num_sectors_, LP_TARGET_TYPE_ZERO, 0}); } Partition::Partition(const std::string& name, const std::string& guid, uint32_t attributes) : name_(name), guid_(guid), attributes_(attributes), size_(0) {} Partition::Partition(const std::string& name, const std::string& group_name, const std::string& guid, uint32_t attributes) : name_(name), group_name_(group_name), guid_(guid), attributes_(attributes), size_(0) {} void Partition::AddExtent(std::unique_ptr<Extent>&& extent) { size_ += extent->num_sectors() * LP_SECTOR_SIZE; Loading Loading @@ -128,6 +129,17 @@ void Partition::ShrinkTo(uint64_t aligned_size) { DCHECK(size_ == aligned_size); } uint64_t Partition::BytesOnDisk() const { uint64_t sectors = 0; for (const auto& extent : extents_) { if (!extent->AsLinearExtent()) { continue; } sectors += extent->num_sectors(); } return sectors * LP_SECTOR_SIZE; } std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const std::string& block_device, uint32_t slot_number) { std::unique_ptr<LpMetadata> metadata = ReadMetadata(block_device.c_str(), slot_number); Loading Loading @@ -175,14 +187,23 @@ MetadataBuilder::MetadataBuilder() { header_.header_size = sizeof(header_); header_.partitions.entry_size = sizeof(LpMetadataPartition); header_.extents.entry_size = sizeof(LpMetadataExtent); header_.groups.entry_size = sizeof(LpMetadataPartitionGroup); } bool MetadataBuilder::Init(const LpMetadata& metadata) { geometry_ = metadata.geometry; for (const auto& group : metadata.groups) { std::string group_name = GetPartitionGroupName(group); if (!AddGroup(group_name, group.maximum_size)) { return false; } } for (const auto& partition : metadata.partitions) { Partition* builder = AddPartition(GetPartitionName(partition), GetPartitionGuid(partition), partition.attributes); std::string group_name = GetPartitionGroupName(metadata.groups[partition.group_index]); Partition* builder = AddPartition(GetPartitionName(partition), group_name, GetPartitionGuid(partition), partition.attributes); if (!builder) { return false; } Loading Loading @@ -292,11 +313,29 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata geometry_.alignment_offset = device_info_.alignment_offset; geometry_.block_device_size = device_info_.size; geometry_.logical_block_size = device_info.logical_block_size; if (!AddGroup("default", 0)) { return false; } return true; } bool MetadataBuilder::AddGroup(const std::string& group_name, uint64_t maximum_size) { if (FindGroup(group_name)) { LERROR << "Group already exists: " << group_name; return false; } groups_.push_back(std::make_unique<PartitionGroup>(group_name, maximum_size)); return true; } Partition* MetadataBuilder::AddPartition(const std::string& name, const std::string& guid, uint32_t attributes) { return AddPartition(name, "default", guid, attributes); } Partition* MetadataBuilder::AddPartition(const std::string& name, const std::string& group_name, const std::string& guid, uint32_t attributes) { if (name.empty()) { LERROR << "Partition must have a non-empty name."; return nullptr; Loading @@ -305,7 +344,11 @@ Partition* MetadataBuilder::AddPartition(const std::string& name, const std::str LERROR << "Attempting to create duplication partition with name: " << name; return nullptr; } partitions_.push_back(std::make_unique<Partition>(name, guid, attributes)); if (!FindGroup(group_name)) { LERROR << "Could not find partition group: " << group_name; return nullptr; } partitions_.push_back(std::make_unique<Partition>(name, group_name, guid, attributes)); return partitions_.back().get(); } Loading @@ -318,6 +361,26 @@ Partition* MetadataBuilder::FindPartition(const std::string& name) { return nullptr; } PartitionGroup* MetadataBuilder::FindGroup(const std::string& group_name) const { for (const auto& group : groups_) { if (group->name() == group_name) { return group.get(); } } return nullptr; } uint64_t MetadataBuilder::TotalSizeOfGroup(PartitionGroup* group) const { uint64_t total = 0; for (const auto& partition : partitions_) { if (partition->group_name() != group->name()) { continue; } total += partition->BytesOnDisk(); } return total; } void MetadataBuilder::RemovePartition(const std::string& name) { for (auto iter = partitions_.begin(); iter != partitions_.end(); iter++) { if ((*iter)->name() == name) { Loading @@ -328,8 +391,23 @@ void MetadataBuilder::RemovePartition(const std::string& name) { } bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size) { // Figure out how much we need to allocate. PartitionGroup* group = FindGroup(partition->group_name()); CHECK(group); // Figure out how much we need to allocate, and whether our group has // enough space remaining. uint64_t space_needed = aligned_size - partition->size(); if (group->maximum_size() > 0) { uint64_t group_size = TotalSizeOfGroup(group); if (group_size >= group->maximum_size() || group->maximum_size() - group_size < space_needed) { LERROR << "Partition " << partition->name() << " is part of group " << group->name() << " which does not have enough space free (" << space_needed << "requested, " << group_size << " used out of " << group->maximum_size(); return false; } } uint64_t sectors_needed = space_needed / LP_SECTOR_SIZE; DCHECK(sectors_needed * LP_SECTOR_SIZE == space_needed); Loading Loading @@ -441,6 +519,20 @@ std::unique_ptr<LpMetadata> MetadataBuilder::Export() { metadata->header = header_; metadata->geometry = geometry_; std::map<std::string, size_t> group_indices; for (const auto& group : groups_) { LpMetadataPartitionGroup out = {}; if (group->name().size() > sizeof(out.name)) { LERROR << "Partition group name is too long: " << group->name(); return nullptr; } strncpy(out.name, group->name().c_str(), sizeof(out.name)); out.maximum_size = group->maximum_size(); metadata->groups.push_back(out); } // Flatten the partition and extent structures into an LpMetadata, which // makes it very easy to validate, serialize, or pass on to device-mapper. for (const auto& partition : partitions_) { Loading Loading @@ -475,6 +567,7 @@ std::unique_ptr<LpMetadata> MetadataBuilder::Export() { metadata->header.partitions.num_entries = static_cast<uint32_t>(metadata->partitions.size()); metadata->header.extents.num_entries = static_cast<uint32_t>(metadata->extents.size()); metadata->header.groups.num_entries = static_cast<uint32_t>(metadata->groups.size()); return metadata; } Loading Loading @@ -530,8 +623,10 @@ bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_s ShrinkPartition(partition, aligned_size); } LINFO << "Partition " << partition->name() << " will resize from " << old_size << " bytes to " << aligned_size << " bytes"; if (partition->size() != old_size) { LINFO << "Partition " << partition->name() << " will resize from " << old_size << " bytes to " << aligned_size << " bytes"; } return true; } Loading
fs_mgr/liblp/builder_test.cpp +25 −0 Original line number Diff line number Diff line Loading @@ -495,3 +495,28 @@ TEST(liblp, AlignedFreeSpace) { unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 512, 1); ASSERT_EQ(builder, nullptr); } TEST(liblp, HasDefaultGroup) { BlockDeviceInfo device_info(1024 * 1024, 0, 0, 4096); unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1); ASSERT_NE(builder, nullptr); EXPECT_FALSE(builder->AddGroup("default", 0)); } TEST(liblp, GroupSizeLimits) { 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("google", 16384)); Partition* partition = builder->AddPartition("system", "google", TEST_GUID, 0); ASSERT_NE(partition, nullptr); EXPECT_TRUE(builder->ResizePartition(partition, 8192)); EXPECT_EQ(partition->size(), 8192); EXPECT_TRUE(builder->ResizePartition(partition, 16384)); EXPECT_EQ(partition->size(), 16384); EXPECT_FALSE(builder->ResizePartition(partition, 32768)); EXPECT_EQ(partition->size(), 16384); }
fs_mgr/liblp/include/liblp/builder.h +36 −1 Original line number Diff line number Diff line Loading @@ -95,11 +95,25 @@ class ZeroExtent final : public Extent { void AddTo(LpMetadata* out) const override; }; class PartitionGroup final { public: explicit PartitionGroup(const std::string& name, uint64_t maximum_size) : name_(name), maximum_size_(maximum_size) {} const std::string& name() const { return name_; } uint64_t maximum_size() const { return maximum_size_; } private: std::string name_; uint64_t maximum_size_; }; class Partition final { friend class MetadataBuilder; public: Partition(const std::string& name, const std::string& guid, uint32_t attributes); Partition(const std::string& name, const std::string& group_name, const std::string& guid, uint32_t attributes); // Add a raw extent. void AddExtent(std::unique_ptr<Extent>&& extent); Loading @@ -107,7 +121,12 @@ class Partition final { // Remove all extents from this partition. void RemoveExtents(); // Compute the size used by linear extents. This is the same as size(), // but does not factor in extents which do not take up space. uint64_t BytesOnDisk() const; const std::string& name() const { return name_; } const std::string& group_name() const { return group_name_; } uint32_t attributes() const { return attributes_; } const std::string& guid() const { return guid_; } const std::vector<std::unique_ptr<Extent>>& extents() const { return extents_; } Loading @@ -117,6 +136,7 @@ class Partition final { void ShrinkTo(uint64_t aligned_size); std::string name_; std::string group_name_; std::string guid_; std::vector<std::unique_ptr<Extent>> extents_; uint32_t attributes_; Loading Loading @@ -156,12 +176,24 @@ class MetadataBuilder { return New(device_info, metadata_max_size, metadata_slot_count); } // Define a new partition group. By default there is one group called // "default", with an unrestricted size. A non-zero size will restrict the // total space used by all partitions in the group. // // This can fail and return false if the group already exists. bool AddGroup(const std::string& group_name, uint64_t maximum_size); // Export metadata so it can be serialized to an image, to disk, or mounted // via device-mapper. std::unique_ptr<LpMetadata> Export(); // Add a partition, returning a handle so it can be sized as needed. If a // partition with the given name already exists, nullptr is returned. Partition* AddPartition(const std::string& name, const std::string& group_name, const std::string& guid, uint32_t attributes); // Same as AddPartition above, but uses the default partition group which // has no size restrictions. Partition* AddPartition(const std::string& name, const std::string& guid, uint32_t attributes); // Delete a partition by name if it exists. Loading Loading @@ -202,10 +234,13 @@ class MetadataBuilder { bool GrowPartition(Partition* partition, uint64_t aligned_size); void ShrinkPartition(Partition* partition, uint64_t aligned_size); uint64_t AlignSector(uint64_t sector); PartitionGroup* FindGroup(const std::string& group_name) const; uint64_t TotalSizeOfGroup(PartitionGroup* group) const; LpMetadataGeometry geometry_; LpMetadataHeader header_; std::vector<std::unique_ptr<Partition>> partitions_; std::vector<std::unique_ptr<PartitionGroup>> groups_; BlockDeviceInfo device_info_; }; Loading
fs_mgr/liblp/include/liblp/liblp.h +2 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ struct LpMetadata { LpMetadataHeader header; std::vector<LpMetadataPartition> partitions; std::vector<LpMetadataExtent> extents; std::vector<LpMetadataPartitionGroup> groups; }; // Place an initial partition table on the device. This will overwrite the Loading Loading @@ -68,6 +69,7 @@ std::unique_ptr<LpMetadata> ReadFromImageBlob(const void* data, size_t bytes); // Helper to extract safe C++ strings from partition info. std::string GetPartitionName(const LpMetadataPartition& partition); std::string GetPartitionGuid(const LpMetadataPartition& partition); std::string GetPartitionGroupName(const LpMetadataPartitionGroup& group); // Helper to return a slot number for a slot suffix. uint32_t SlotNumberForSlotSuffix(const std::string& suffix); Loading
fs_mgr/liblp/include/liblp/metadata_format.h +19 −1 Original line number Diff line number Diff line Loading @@ -38,7 +38,7 @@ extern "C" { #define LP_METADATA_HEADER_MAGIC 0x414C5030 /* Current metadata version. */ #define LP_METADATA_MAJOR_VERSION 1 #define LP_METADATA_MAJOR_VERSION 2 #define LP_METADATA_MINOR_VERSION 0 /* Attributes for the LpMetadataPartition::attributes field. Loading Loading @@ -216,6 +216,8 @@ typedef struct LpMetadataHeader { LpMetadataTableDescriptor partitions; /* 92: Extent table descriptor. */ LpMetadataTableDescriptor extents; /* 104: Updateable group descriptor. */ LpMetadataTableDescriptor groups; } __attribute__((packed)) LpMetadataHeader; /* This struct defines a logical partition entry, similar to what would be Loading Loading @@ -245,6 +247,9 @@ typedef struct LpMetadataPartition { * least one extent. */ uint32_t num_extents; /* 64: Group this partition belongs to. */ uint32_t group_index; } __attribute__((packed)) LpMetadataPartition; /* This extent is a dm-linear target, and the index is an index into the Loading @@ -271,6 +276,19 @@ typedef struct LpMetadataExtent { uint64_t target_data; } __attribute__((packed)) LpMetadataExtent; /* This struct defines an entry in the groups table. Each group has a maximum * size, and partitions in a group must not exceed that size. There is always * a "default" group of unlimited size, which is used when not using update * groups or when using overlayfs or fastbootd. */ typedef struct LpMetadataPartitionGroup { /* 0: Name of this group. Any unused characters must be 0. */ char name[36]; /* 36: Maximum size in bytes. If 0, the group has no maximum size. */ uint64_t maximum_size; } LpMetadataPartitionGroup; #ifdef __cplusplus } /* extern "C" */ #endif Loading