diff options
Diffstat (limited to 'fs_mgr/liblp')
-rw-r--r-- | fs_mgr/liblp/builder.cpp | 39 | ||||
-rw-r--r-- | fs_mgr/liblp/io_test.cpp | 9 | ||||
-rw-r--r-- | fs_mgr/liblp/reader.cpp | 3 | ||||
-rw-r--r-- | fs_mgr/liblp/utility.cpp | 8 | ||||
-rw-r--r-- | fs_mgr/liblp/utility.h | 1 |
5 files changed, 40 insertions, 20 deletions
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp index b51afc17b..7035f42e5 100644 --- a/fs_mgr/liblp/builder.cpp +++ b/fs_mgr/liblp/builder.cpp @@ -158,39 +158,48 @@ std::unique_ptr<MetadataBuilder> MetadataBuilder::NewForUpdate(const IPartitionO return nullptr; } - // Get the list of devices we already have. - std::set<std::string> block_devices; - for (const auto& block_device : metadata->block_devices) { - block_devices.emplace(GetBlockDevicePartitionName(block_device)); + // On non-retrofit devices there is only one location for metadata: the + // super partition. update_engine will remove and resize partitions as + // needed. On the other hand, for retrofit devices, we'll need to + // translate block device and group names to update their slot suffixes. + auto super_device = GetMetadataSuperBlockDevice(*metadata.get()); + if (GetBlockDevicePartitionName(*super_device) == "super") { + return New(*metadata.get(), &opener); } - auto new_block_devices = metadata->block_devices; + // Clear partitions and extents, since they have no meaning on the target + // slot. We also clear groups since they are re-added during OTA. + metadata->partitions.clear(); + metadata->extents.clear(); + metadata->groups.clear(); - // Add missing block devices. std::string source_slot_suffix = SlotSuffixForSlotNumber(source_slot_number); std::string target_slot_suffix = SlotSuffixForSlotNumber(target_slot_number); - for (const auto& block_device : metadata->block_devices) { - std::string partition_name = GetBlockDevicePartitionName(block_device); + + // Translate block devices. + auto source_block_devices = std::move(metadata->block_devices); + for (const auto& source_block_device : source_block_devices) { + std::string partition_name = GetBlockDevicePartitionName(source_block_device); std::string slot_suffix = GetPartitionSlotSuffix(partition_name); if (slot_suffix.empty() || slot_suffix != source_slot_suffix) { - continue; + // This should never happen. It means that the source metadata + // refers to a target or unknown block device. + LERROR << "Invalid block device for slot " << source_slot_suffix << ": " + << partition_name; + return nullptr; } std::string new_name = partition_name.substr(0, partition_name.size() - slot_suffix.size()) + target_slot_suffix; - if (block_devices.find(new_name) != block_devices.end()) { - continue; - } - auto new_device = block_device; + auto new_device = source_block_device; if (!UpdateBlockDevicePartitionName(&new_device, new_name)) { LERROR << "Partition name too long: " << new_name; return nullptr; } - new_block_devices.emplace_back(new_device); + metadata->block_devices.emplace_back(new_device); } - metadata->block_devices = new_block_devices; return New(*metadata.get(), &opener); } diff --git a/fs_mgr/liblp/io_test.cpp b/fs_mgr/liblp/io_test.cpp index b539d776a..9f3314d34 100644 --- a/fs_mgr/liblp/io_test.cpp +++ b/fs_mgr/liblp/io_test.cpp @@ -665,6 +665,7 @@ TEST(liblp, UpdateRetrofit) { unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder(); ASSERT_NE(builder, nullptr); ASSERT_TRUE(AddDefaultPartitions(builder.get())); + ASSERT_TRUE(builder->AddGroup("example", 0)); builder->SetAutoSlotSuffixing(); auto fd = CreateFakeDisk(); @@ -682,9 +683,11 @@ TEST(liblp, UpdateRetrofit) { ASSERT_NE(builder, nullptr); auto updated = builder->Export(); ASSERT_NE(updated, nullptr); - ASSERT_EQ(updated->block_devices.size(), static_cast<size_t>(2)); - EXPECT_EQ(GetBlockDevicePartitionName(updated->block_devices[0]), "super_a"); - EXPECT_EQ(GetBlockDevicePartitionName(updated->block_devices[1]), "super_b"); + ASSERT_EQ(updated->block_devices.size(), static_cast<size_t>(1)); + EXPECT_EQ(GetBlockDevicePartitionName(updated->block_devices[0]), "super_b"); + ASSERT_TRUE(updated->groups.empty()); + ASSERT_TRUE(updated->partitions.empty()); + ASSERT_TRUE(updated->extents.empty()); } TEST(liblp, UpdateNonRetrofit) { diff --git a/fs_mgr/liblp/reader.cpp b/fs_mgr/liblp/reader.cpp index 305e6c79d..24c6b2c31 100644 --- a/fs_mgr/liblp/reader.cpp +++ b/fs_mgr/liblp/reader.cpp @@ -380,11 +380,10 @@ bool AdjustMetadataForSlot(LpMetadata* metadata, uint32_t slot_number) { continue; } std::string group_name = GetPartitionGroupName(group) + slot_suffix; - if (group_name.size() > sizeof(group.name)) { + if (!UpdatePartitionGroupName(&group, group_name)) { LERROR << __PRETTY_FUNCTION__ << " group name too long: " << group_name; return false; } - strncpy(group.name, group_name.c_str(), sizeof(group.name)); group.flags &= ~LP_GROUP_SLOT_SUFFIXED; } return true; diff --git a/fs_mgr/liblp/utility.cpp b/fs_mgr/liblp/utility.cpp index 4f20b6bf8..60ddbdd12 100644 --- a/fs_mgr/liblp/utility.cpp +++ b/fs_mgr/liblp/utility.cpp @@ -145,5 +145,13 @@ bool UpdateBlockDevicePartitionName(LpMetadataBlockDevice* device, const std::st return true; } +bool UpdatePartitionGroupName(LpMetadataPartitionGroup* group, const std::string& name) { + if (name.size() > sizeof(group->name)) { + return false; + } + strncpy(group->name, name.c_str(), sizeof(group->name)); + return true; +} + } // namespace fs_mgr } // namespace android diff --git a/fs_mgr/liblp/utility.h b/fs_mgr/liblp/utility.h index 55ecb5a59..8b70919d6 100644 --- a/fs_mgr/liblp/utility.h +++ b/fs_mgr/liblp/utility.h @@ -86,6 +86,7 @@ constexpr uint64_t AlignTo(uint64_t base, uint32_t alignment, uint32_t alignment // Update names from C++ strings. bool UpdateBlockDevicePartitionName(LpMetadataBlockDevice* device, const std::string& name); +bool UpdatePartitionGroupName(LpMetadataPartitionGroup* group, const std::string& name); } // namespace fs_mgr } // namespace android |