liblp: Auto-suffix group names.
This is needed for update_engine to properly clean old partitions on
retrofit devices.
Bug: 119687874
Test: liblp_test gtest
Change-Id: Ida9483ad3c127e357f45789540ebbedc9d3d3883
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index b6d6da1..9fe92df 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -623,6 +623,9 @@
LERROR << "Partition group name is too long: " << group->name();
return nullptr;
}
+ if (auto_slot_suffixing_ && group->name() != "default") {
+ out.flags |= LP_GROUP_SLOT_SUFFIXED;
+ }
strncpy(out.name, group->name().c_str(), sizeof(out.name));
out.maximum_size = group->maximum_size();
diff --git a/fs_mgr/liblp/include/liblp/metadata_format.h b/fs_mgr/liblp/include/liblp/metadata_format.h
index c2e25fb..9c5ec5c 100644
--- a/fs_mgr/liblp/include/liblp/metadata_format.h
+++ b/fs_mgr/liblp/include/liblp/metadata_format.h
@@ -38,7 +38,7 @@
#define LP_METADATA_HEADER_MAGIC 0x414C5030
/* Current metadata version. */
-#define LP_METADATA_MAJOR_VERSION 9
+#define LP_METADATA_MAJOR_VERSION 10
#define LP_METADATA_MINOR_VERSION 0
/* Attributes for the LpMetadataPartition::attributes field.
@@ -267,10 +267,19 @@
/* 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. */
+ /* 36: Flags (see LP_GROUP_*). */
+ uint32_t flags;
+
+ /* 40: Maximum size in bytes. If 0, the group has no maximum size. */
uint64_t maximum_size;
} LpMetadataPartitionGroup;
+/* This flag is only intended to be used with super_empty.img and super.img on
+ * retrofit devices. If set, the group needs a slot suffix to be interpreted
+ * correctly. The suffix is automatically applied by ReadMetadata().
+ */
+#define LP_GROUP_SLOT_SUFFIXED (1 << 0)
+
/* This struct defines an entry in the block_devices table. There must be at
* least one device, and the first device must represent the partition holding
* the super metadata.
diff --git a/fs_mgr/liblp/io_test.cpp b/fs_mgr/liblp/io_test.cpp
index 9acf23e..b539d77 100644
--- a/fs_mgr/liblp/io_test.cpp
+++ b/fs_mgr/liblp/io_test.cpp
@@ -622,6 +622,7 @@
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();
@@ -641,6 +642,11 @@
EXPECT_EQ(GetPartitionName(metadata->partitions[0]), "system_b");
ASSERT_EQ(metadata->block_devices.size(), static_cast<size_t>(1));
EXPECT_EQ(GetBlockDevicePartitionName(metadata->block_devices[0]), "super_b");
+ ASSERT_EQ(metadata->groups.size(), static_cast<size_t>(2));
+ EXPECT_EQ(GetPartitionGroupName(metadata->groups[0]), "default");
+ EXPECT_EQ(GetPartitionGroupName(metadata->groups[1]), "example_b");
+ EXPECT_EQ(metadata->groups[0].flags, 0);
+ EXPECT_EQ(metadata->groups[1].flags, 0);
metadata = ReadMetadata(opener, "super_a", 0);
ASSERT_NE(metadata, nullptr);
@@ -648,6 +654,11 @@
EXPECT_EQ(GetPartitionName(metadata->partitions[0]), "system_a");
ASSERT_EQ(metadata->block_devices.size(), static_cast<size_t>(1));
EXPECT_EQ(GetBlockDevicePartitionName(metadata->block_devices[0]), "super_a");
+ ASSERT_EQ(metadata->groups.size(), static_cast<size_t>(2));
+ EXPECT_EQ(GetPartitionGroupName(metadata->groups[0]), "default");
+ EXPECT_EQ(GetPartitionGroupName(metadata->groups[1]), "example_a");
+ EXPECT_EQ(metadata->groups[0].flags, 0);
+ EXPECT_EQ(metadata->groups[1].flags, 0);
}
TEST(liblp, UpdateRetrofit) {
diff --git a/fs_mgr/liblp/reader.cpp b/fs_mgr/liblp/reader.cpp
index b36ba0e..305e6c7 100644
--- a/fs_mgr/liblp/reader.cpp
+++ b/fs_mgr/liblp/reader.cpp
@@ -375,6 +375,18 @@
}
block_device.flags &= ~LP_BLOCK_DEVICE_SLOT_SUFFIXED;
}
+ for (auto& group : metadata->groups) {
+ if (!(group.flags & LP_GROUP_SLOT_SUFFIXED)) {
+ continue;
+ }
+ std::string group_name = GetPartitionGroupName(group) + slot_suffix;
+ if (group_name.size() > sizeof(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;
}