Loading fastboot/device/flashing.cpp +28 −1 Original line number Diff line number Diff line Loading @@ -148,13 +148,40 @@ bool UpdateSuper(FastbootDevice* device, const std::string& super_name, bool wip // image. std::string slot_suffix = device->GetCurrentSlot(); uint32_t slot_number = SlotNumberForSlotSuffix(slot_suffix); if (wipe || !ReadMetadata(super_name, slot_number)) { std::unique_ptr<LpMetadata> old_metadata = ReadMetadata(super_name, slot_number); if (wipe || !old_metadata) { if (!FlashPartitionTable(super_name, *new_metadata.get())) { return device->WriteFail("Unable to flash new partition table"); } return device->WriteOkay("Successfully flashed partition table"); } std::set<std::string> partitions_to_keep; for (const auto& partition : old_metadata->partitions) { // Preserve partitions in the other slot, but not the current slot. std::string partition_name = GetPartitionName(partition); if (!slot_suffix.empty() && GetPartitionSlotSuffix(partition_name) == slot_suffix) { continue; } partitions_to_keep.emplace(partition_name); } // Do not preserve the scratch partition. partitions_to_keep.erase("scratch"); if (!partitions_to_keep.empty()) { std::unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(*new_metadata.get()); if (!builder->ImportPartitions(*old_metadata.get(), partitions_to_keep)) { return device->WriteFail( "Old partitions are not compatible with the new super layout; wipe needed"); } new_metadata = builder->Export(); if (!new_metadata) { return device->WriteFail("Unable to build new partition table; wipe needed"); } } // Write the new table to every metadata slot. bool ok = true; for (size_t i = 0; i < new_metadata->geometry.metadata_slot_count; i++) { Loading fastboot/fastboot.cpp +10 −7 Original line number Diff line number Diff line Loading @@ -1200,6 +1200,15 @@ FlashAllTool::FlashAllTool(const ImageSource& source, const std::string& slot_ov void FlashAllTool::Flash() { DumpInfo(); CheckRequirements(); // Change the slot first, so we boot into the correct recovery image when // using fastbootd. if (slot_override_ == "all") { set_active("a"); } else { set_active(slot_override_); } DetermineSecondarySlot(); CollectImages(); Loading @@ -1223,12 +1232,6 @@ void FlashAllTool::Flash() { // Flash OS images, resizing logical partitions as needed. FlashImages(os_images_); if (slot_override_ == "all") { set_active("a"); } else { set_active(slot_override_); } } void FlashAllTool::CheckRequirements() { Loading @@ -1243,7 +1246,7 @@ void FlashAllTool::DetermineSecondarySlot() { if (skip_secondary_) { return; } if (slot_override_ != "") { if (slot_override_ != "" && slot_override_ != "all") { secondary_slot_ = get_other_slot(slot_override_); } else { secondary_slot_ = get_other_slot(); Loading fs_mgr/liblp/builder.cpp +99 −13 Original line number Diff line number Diff line Loading @@ -184,21 +184,25 @@ bool MetadataBuilder::Init(const LpMetadata& metadata) { if (!builder) { return false; } ImportExtents(builder, metadata, partition); } return true; } for (size_t i = 0; i < partition.num_extents; i++) { const LpMetadataExtent& extent = metadata.extents[partition.first_extent_index + i]; void MetadataBuilder::ImportExtents(Partition* dest, const LpMetadata& metadata, const LpMetadataPartition& source) { for (size_t i = 0; i < source.num_extents; i++) { const LpMetadataExtent& extent = metadata.extents[source.first_extent_index + i]; if (extent.target_type == LP_TARGET_TYPE_LINEAR) { auto copy = std::make_unique<LinearExtent>(extent.num_sectors, extent.target_source, extent.target_data); builder->AddExtent(std::move(copy)); dest->AddExtent(std::move(copy)); } else if (extent.target_type == LP_TARGET_TYPE_ZERO) { auto copy = std::make_unique<ZeroExtent>(extent.num_sectors); builder->AddExtent(std::move(copy)); dest->AddExtent(std::move(copy)); } } } return true; } static bool VerifyDeviceProperties(const BlockDeviceInfo& device_info) { if (device_info.logical_block_size % LP_SECTOR_SIZE != 0) { Loading Loading @@ -471,13 +475,18 @@ auto MetadataBuilder::GetFreeRegions() const -> std::vector<Interval> { return free_regions; } bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size) { bool MetadataBuilder::ValidatePartitionSizeChange(Partition* partition, uint64_t old_size, uint64_t new_size) { PartitionGroup* group = FindGroup(partition->group_name()); CHECK(group); if (new_size <= old_size) { return true; } // Figure out how much we need to allocate, and whether our group has // enough space remaining. uint64_t space_needed = aligned_size - partition->size(); uint64_t space_needed = new_size - old_size; if (group->maximum_size() > 0) { uint64_t group_size = TotalSizeOfGroup(group); if (group_size >= group->maximum_size() || Loading @@ -488,7 +497,11 @@ bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size) return false; } } return true; } bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size) { uint64_t space_needed = aligned_size - partition->size(); uint64_t sectors_needed = space_needed / LP_SECTOR_SIZE; DCHECK(sectors_needed * LP_SECTOR_SIZE == space_needed); Loading Loading @@ -704,6 +717,10 @@ 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)) { return false; } if (aligned_size > old_size) { if (!GrowPartition(partition, aligned_size)) { return false; Loading Loading @@ -750,5 +767,74 @@ void MetadataBuilder::RemoveGroupAndPartitions(const std::string& group_name) { } } static bool CompareBlockDevices(const LpMetadataBlockDevice& first, const LpMetadataBlockDevice& second) { // Note: we don't compare alignment, since it's a performance thing and // won't affect whether old extents continue to work. return first.first_logical_sector == second.first_logical_sector && first.size == second.size && GetBlockDevicePartitionName(first) == GetBlockDevicePartitionName(second); } bool MetadataBuilder::ImportPartitions(const LpMetadata& metadata, const std::set<std::string>& partition_names) { // The block device list must be identical. We do not try to be clever and // allow ordering changes or changes that don't affect partitions. This // process is designed to allow the most common flashing scenarios and more // complex ones should require a wipe. if (metadata.block_devices.size() != block_devices_.size()) { LINFO << "Block device tables does not match."; return false; } for (size_t i = 0; i < metadata.block_devices.size(); i++) { const LpMetadataBlockDevice& old_device = metadata.block_devices[i]; const LpMetadataBlockDevice& new_device = block_devices_[i]; if (!CompareBlockDevices(old_device, new_device)) { LINFO << "Block device tables do not match"; return false; } } // Import named partitions. Note that we do not attempt to merge group // information here. If the device changed its group names, the old // partitions will fail to merge. The same could happen if the group // allocation sizes change. for (const auto& partition : metadata.partitions) { std::string partition_name = GetPartitionName(partition); if (partition_names.find(partition_name) == partition_names.end()) { continue; } if (!ImportPartition(metadata, partition)) { return false; } } return true; } bool MetadataBuilder::ImportPartition(const LpMetadata& metadata, const LpMetadataPartition& source) { std::string partition_name = GetPartitionName(source); Partition* partition = FindPartition(partition_name); if (!partition) { std::string group_name = GetPartitionGroupName(metadata.groups[source.group_index]); partition = AddPartition(partition_name, group_name, source.attributes); if (!partition) { return false; } } if (partition->size() > 0) { LINFO << "Importing partition table would overwrite non-empty partition: " << partition_name; return false; } ImportExtents(partition, metadata, source); if (!ValidatePartitionSizeChange(partition, 0, partition->size())) { partition->RemoveExtents(); return false; } return true; } } // namespace fs_mgr } // namespace android fs_mgr/liblp/builder_test.cpp +61 −0 Original line number Diff line number Diff line Loading @@ -632,3 +632,64 @@ TEST(liblp, MultipleBlockDevices) { EXPECT_EQ(metadata->extents[2].target_data, 1472); EXPECT_EQ(metadata->extents[2].target_source, 2); } TEST(liblp, ImportPartitionsOk) { unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2); ASSERT_NE(builder, nullptr); Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY); Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY); ASSERT_NE(system, nullptr); ASSERT_NE(vendor, nullptr); EXPECT_EQ(builder->ResizePartition(system, 65536), true); EXPECT_EQ(builder->ResizePartition(vendor, 32768), true); EXPECT_EQ(builder->ResizePartition(system, 98304), true); unique_ptr<LpMetadata> exported = builder->Export(); ASSERT_NE(exported, nullptr); builder = MetadataBuilder::New(1024 * 1024, 1024, 2); ASSERT_NE(builder, nullptr); ASSERT_TRUE(builder->ImportPartitions(*exported.get(), {"vendor"})); EXPECT_NE(builder->FindPartition("vendor"), nullptr); EXPECT_EQ(builder->FindPartition("system"), nullptr); unique_ptr<LpMetadata> new_metadata = builder->Export(); ASSERT_NE(new_metadata, nullptr); ASSERT_EQ(exported->partitions.size(), static_cast<size_t>(2)); ASSERT_EQ(GetPartitionName(exported->partitions[1]), "vendor"); ASSERT_EQ(new_metadata->partitions.size(), static_cast<size_t>(1)); ASSERT_EQ(GetPartitionName(new_metadata->partitions[0]), "vendor"); const LpMetadataExtent& extent_a = exported->extents[exported->partitions[1].first_extent_index]; const LpMetadataExtent& extent_b = new_metadata->extents[new_metadata->partitions[0].first_extent_index]; EXPECT_EQ(extent_a.num_sectors, extent_b.num_sectors); EXPECT_EQ(extent_a.target_type, extent_b.target_type); EXPECT_EQ(extent_a.target_data, extent_b.target_data); EXPECT_EQ(extent_a.target_source, extent_b.target_source); } TEST(liblp, ImportPartitionsFail) { unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2); ASSERT_NE(builder, nullptr); Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY); Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY); ASSERT_NE(system, nullptr); ASSERT_NE(vendor, nullptr); EXPECT_EQ(builder->ResizePartition(system, 65536), true); EXPECT_EQ(builder->ResizePartition(vendor, 32768), true); EXPECT_EQ(builder->ResizePartition(system, 98304), true); unique_ptr<LpMetadata> exported = builder->Export(); ASSERT_NE(exported, nullptr); // Different device size. builder = MetadataBuilder::New(1024 * 2048, 1024, 2); ASSERT_NE(builder, nullptr); EXPECT_FALSE(builder->ImportPartitions(*exported.get(), {"system"})); } fs_mgr/liblp/include/liblp/builder.h +10 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <map> #include <memory> #include <set> #include "liblp.h" #include "partition_opener.h" Loading Loading @@ -225,6 +226,11 @@ class MetadataBuilder { bool GetBlockDeviceInfo(const std::string& partition_name, BlockDeviceInfo* info) const; bool UpdateBlockDeviceInfo(const std::string& partition_name, const BlockDeviceInfo& info); // Attempt to preserve the named partitions from an older metadata. If this // is not possible (for example, the block device list has changed) then // false is returned. bool ImportPartitions(const LpMetadata& metadata, const std::set<std::string>& partition_names); private: MetadataBuilder(); MetadataBuilder(const MetadataBuilder&) = delete; Loading @@ -240,6 +246,10 @@ 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); void ImportExtents(Partition* dest, const LpMetadata& metadata, const LpMetadataPartition& source); bool ImportPartition(const LpMetadata& metadata, const LpMetadataPartition& source); struct Interval { uint32_t device_index; Loading Loading
fastboot/device/flashing.cpp +28 −1 Original line number Diff line number Diff line Loading @@ -148,13 +148,40 @@ bool UpdateSuper(FastbootDevice* device, const std::string& super_name, bool wip // image. std::string slot_suffix = device->GetCurrentSlot(); uint32_t slot_number = SlotNumberForSlotSuffix(slot_suffix); if (wipe || !ReadMetadata(super_name, slot_number)) { std::unique_ptr<LpMetadata> old_metadata = ReadMetadata(super_name, slot_number); if (wipe || !old_metadata) { if (!FlashPartitionTable(super_name, *new_metadata.get())) { return device->WriteFail("Unable to flash new partition table"); } return device->WriteOkay("Successfully flashed partition table"); } std::set<std::string> partitions_to_keep; for (const auto& partition : old_metadata->partitions) { // Preserve partitions in the other slot, but not the current slot. std::string partition_name = GetPartitionName(partition); if (!slot_suffix.empty() && GetPartitionSlotSuffix(partition_name) == slot_suffix) { continue; } partitions_to_keep.emplace(partition_name); } // Do not preserve the scratch partition. partitions_to_keep.erase("scratch"); if (!partitions_to_keep.empty()) { std::unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(*new_metadata.get()); if (!builder->ImportPartitions(*old_metadata.get(), partitions_to_keep)) { return device->WriteFail( "Old partitions are not compatible with the new super layout; wipe needed"); } new_metadata = builder->Export(); if (!new_metadata) { return device->WriteFail("Unable to build new partition table; wipe needed"); } } // Write the new table to every metadata slot. bool ok = true; for (size_t i = 0; i < new_metadata->geometry.metadata_slot_count; i++) { Loading
fastboot/fastboot.cpp +10 −7 Original line number Diff line number Diff line Loading @@ -1200,6 +1200,15 @@ FlashAllTool::FlashAllTool(const ImageSource& source, const std::string& slot_ov void FlashAllTool::Flash() { DumpInfo(); CheckRequirements(); // Change the slot first, so we boot into the correct recovery image when // using fastbootd. if (slot_override_ == "all") { set_active("a"); } else { set_active(slot_override_); } DetermineSecondarySlot(); CollectImages(); Loading @@ -1223,12 +1232,6 @@ void FlashAllTool::Flash() { // Flash OS images, resizing logical partitions as needed. FlashImages(os_images_); if (slot_override_ == "all") { set_active("a"); } else { set_active(slot_override_); } } void FlashAllTool::CheckRequirements() { Loading @@ -1243,7 +1246,7 @@ void FlashAllTool::DetermineSecondarySlot() { if (skip_secondary_) { return; } if (slot_override_ != "") { if (slot_override_ != "" && slot_override_ != "all") { secondary_slot_ = get_other_slot(slot_override_); } else { secondary_slot_ = get_other_slot(); Loading
fs_mgr/liblp/builder.cpp +99 −13 Original line number Diff line number Diff line Loading @@ -184,21 +184,25 @@ bool MetadataBuilder::Init(const LpMetadata& metadata) { if (!builder) { return false; } ImportExtents(builder, metadata, partition); } return true; } for (size_t i = 0; i < partition.num_extents; i++) { const LpMetadataExtent& extent = metadata.extents[partition.first_extent_index + i]; void MetadataBuilder::ImportExtents(Partition* dest, const LpMetadata& metadata, const LpMetadataPartition& source) { for (size_t i = 0; i < source.num_extents; i++) { const LpMetadataExtent& extent = metadata.extents[source.first_extent_index + i]; if (extent.target_type == LP_TARGET_TYPE_LINEAR) { auto copy = std::make_unique<LinearExtent>(extent.num_sectors, extent.target_source, extent.target_data); builder->AddExtent(std::move(copy)); dest->AddExtent(std::move(copy)); } else if (extent.target_type == LP_TARGET_TYPE_ZERO) { auto copy = std::make_unique<ZeroExtent>(extent.num_sectors); builder->AddExtent(std::move(copy)); dest->AddExtent(std::move(copy)); } } } return true; } static bool VerifyDeviceProperties(const BlockDeviceInfo& device_info) { if (device_info.logical_block_size % LP_SECTOR_SIZE != 0) { Loading Loading @@ -471,13 +475,18 @@ auto MetadataBuilder::GetFreeRegions() const -> std::vector<Interval> { return free_regions; } bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size) { bool MetadataBuilder::ValidatePartitionSizeChange(Partition* partition, uint64_t old_size, uint64_t new_size) { PartitionGroup* group = FindGroup(partition->group_name()); CHECK(group); if (new_size <= old_size) { return true; } // Figure out how much we need to allocate, and whether our group has // enough space remaining. uint64_t space_needed = aligned_size - partition->size(); uint64_t space_needed = new_size - old_size; if (group->maximum_size() > 0) { uint64_t group_size = TotalSizeOfGroup(group); if (group_size >= group->maximum_size() || Loading @@ -488,7 +497,11 @@ bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size) return false; } } return true; } bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size) { uint64_t space_needed = aligned_size - partition->size(); uint64_t sectors_needed = space_needed / LP_SECTOR_SIZE; DCHECK(sectors_needed * LP_SECTOR_SIZE == space_needed); Loading Loading @@ -704,6 +717,10 @@ 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)) { return false; } if (aligned_size > old_size) { if (!GrowPartition(partition, aligned_size)) { return false; Loading Loading @@ -750,5 +767,74 @@ void MetadataBuilder::RemoveGroupAndPartitions(const std::string& group_name) { } } static bool CompareBlockDevices(const LpMetadataBlockDevice& first, const LpMetadataBlockDevice& second) { // Note: we don't compare alignment, since it's a performance thing and // won't affect whether old extents continue to work. return first.first_logical_sector == second.first_logical_sector && first.size == second.size && GetBlockDevicePartitionName(first) == GetBlockDevicePartitionName(second); } bool MetadataBuilder::ImportPartitions(const LpMetadata& metadata, const std::set<std::string>& partition_names) { // The block device list must be identical. We do not try to be clever and // allow ordering changes or changes that don't affect partitions. This // process is designed to allow the most common flashing scenarios and more // complex ones should require a wipe. if (metadata.block_devices.size() != block_devices_.size()) { LINFO << "Block device tables does not match."; return false; } for (size_t i = 0; i < metadata.block_devices.size(); i++) { const LpMetadataBlockDevice& old_device = metadata.block_devices[i]; const LpMetadataBlockDevice& new_device = block_devices_[i]; if (!CompareBlockDevices(old_device, new_device)) { LINFO << "Block device tables do not match"; return false; } } // Import named partitions. Note that we do not attempt to merge group // information here. If the device changed its group names, the old // partitions will fail to merge. The same could happen if the group // allocation sizes change. for (const auto& partition : metadata.partitions) { std::string partition_name = GetPartitionName(partition); if (partition_names.find(partition_name) == partition_names.end()) { continue; } if (!ImportPartition(metadata, partition)) { return false; } } return true; } bool MetadataBuilder::ImportPartition(const LpMetadata& metadata, const LpMetadataPartition& source) { std::string partition_name = GetPartitionName(source); Partition* partition = FindPartition(partition_name); if (!partition) { std::string group_name = GetPartitionGroupName(metadata.groups[source.group_index]); partition = AddPartition(partition_name, group_name, source.attributes); if (!partition) { return false; } } if (partition->size() > 0) { LINFO << "Importing partition table would overwrite non-empty partition: " << partition_name; return false; } ImportExtents(partition, metadata, source); if (!ValidatePartitionSizeChange(partition, 0, partition->size())) { partition->RemoveExtents(); return false; } return true; } } // namespace fs_mgr } // namespace android
fs_mgr/liblp/builder_test.cpp +61 −0 Original line number Diff line number Diff line Loading @@ -632,3 +632,64 @@ TEST(liblp, MultipleBlockDevices) { EXPECT_EQ(metadata->extents[2].target_data, 1472); EXPECT_EQ(metadata->extents[2].target_source, 2); } TEST(liblp, ImportPartitionsOk) { unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2); ASSERT_NE(builder, nullptr); Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY); Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY); ASSERT_NE(system, nullptr); ASSERT_NE(vendor, nullptr); EXPECT_EQ(builder->ResizePartition(system, 65536), true); EXPECT_EQ(builder->ResizePartition(vendor, 32768), true); EXPECT_EQ(builder->ResizePartition(system, 98304), true); unique_ptr<LpMetadata> exported = builder->Export(); ASSERT_NE(exported, nullptr); builder = MetadataBuilder::New(1024 * 1024, 1024, 2); ASSERT_NE(builder, nullptr); ASSERT_TRUE(builder->ImportPartitions(*exported.get(), {"vendor"})); EXPECT_NE(builder->FindPartition("vendor"), nullptr); EXPECT_EQ(builder->FindPartition("system"), nullptr); unique_ptr<LpMetadata> new_metadata = builder->Export(); ASSERT_NE(new_metadata, nullptr); ASSERT_EQ(exported->partitions.size(), static_cast<size_t>(2)); ASSERT_EQ(GetPartitionName(exported->partitions[1]), "vendor"); ASSERT_EQ(new_metadata->partitions.size(), static_cast<size_t>(1)); ASSERT_EQ(GetPartitionName(new_metadata->partitions[0]), "vendor"); const LpMetadataExtent& extent_a = exported->extents[exported->partitions[1].first_extent_index]; const LpMetadataExtent& extent_b = new_metadata->extents[new_metadata->partitions[0].first_extent_index]; EXPECT_EQ(extent_a.num_sectors, extent_b.num_sectors); EXPECT_EQ(extent_a.target_type, extent_b.target_type); EXPECT_EQ(extent_a.target_data, extent_b.target_data); EXPECT_EQ(extent_a.target_source, extent_b.target_source); } TEST(liblp, ImportPartitionsFail) { unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2); ASSERT_NE(builder, nullptr); Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY); Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY); ASSERT_NE(system, nullptr); ASSERT_NE(vendor, nullptr); EXPECT_EQ(builder->ResizePartition(system, 65536), true); EXPECT_EQ(builder->ResizePartition(vendor, 32768), true); EXPECT_EQ(builder->ResizePartition(system, 98304), true); unique_ptr<LpMetadata> exported = builder->Export(); ASSERT_NE(exported, nullptr); // Different device size. builder = MetadataBuilder::New(1024 * 2048, 1024, 2); ASSERT_NE(builder, nullptr); EXPECT_FALSE(builder->ImportPartitions(*exported.get(), {"system"})); }
fs_mgr/liblp/include/liblp/builder.h +10 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <map> #include <memory> #include <set> #include "liblp.h" #include "partition_opener.h" Loading Loading @@ -225,6 +226,11 @@ class MetadataBuilder { bool GetBlockDeviceInfo(const std::string& partition_name, BlockDeviceInfo* info) const; bool UpdateBlockDeviceInfo(const std::string& partition_name, const BlockDeviceInfo& info); // Attempt to preserve the named partitions from an older metadata. If this // is not possible (for example, the block device list has changed) then // false is returned. bool ImportPartitions(const LpMetadata& metadata, const std::set<std::string>& partition_names); private: MetadataBuilder(); MetadataBuilder(const MetadataBuilder&) = delete; Loading @@ -240,6 +246,10 @@ 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); void ImportExtents(Partition* dest, const LpMetadata& metadata, const LpMetadataPartition& source); bool ImportPartition(const LpMetadata& metadata, const LpMetadataPartition& source); struct Interval { uint32_t device_index; Loading