Merge "liblp: Add an attribute to indicate that a partition has been updated."
am: 74a6f4cf57
Change-Id: I0f3038c4537e38ce4d09c030bec1079dd941d973
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index 77c9c28..8a74745 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -232,7 +232,7 @@
memset(&header_, 0, sizeof(header_));
header_.magic = LP_METADATA_HEADER_MAGIC;
header_.major_version = LP_METADATA_MAJOR_VERSION;
- header_.minor_version = LP_METADATA_MINOR_VERSION;
+ header_.minor_version = LP_METADATA_MINOR_VERSION_MIN;
header_.header_size = sizeof(header_);
header_.partitions.entry_size = sizeof(LpMetadataPartition);
header_.extents.entry_size = sizeof(LpMetadataExtent);
@@ -796,6 +796,11 @@
return nullptr;
}
+ if (partition->attributes() & LP_PARTITION_ATTR_UPDATED) {
+ static const uint16_t kMinVersion = LP_METADATA_VERSION_FOR_UPDATED_ATTR;
+ metadata->header.minor_version = std::max(metadata->header.minor_version, kMinVersion);
+ }
+
strncpy(part.name, partition->name().c_str(), sizeof(part.name));
part.first_extent_index = static_cast<uint32_t>(metadata->extents.size());
part.num_extents = static_cast<uint32_t>(partition->extents().size());
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index dde6d07..c5b4047 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -349,7 +349,7 @@
const LpMetadataHeader& header = exported->header;
EXPECT_EQ(header.magic, LP_METADATA_HEADER_MAGIC);
EXPECT_EQ(header.major_version, LP_METADATA_MAJOR_VERSION);
- EXPECT_EQ(header.minor_version, LP_METADATA_MINOR_VERSION);
+ EXPECT_EQ(header.minor_version, LP_METADATA_MINOR_VERSION_MIN);
ASSERT_EQ(exported->partitions.size(), 2);
ASSERT_EQ(exported->extents.size(), 3);
diff --git a/fs_mgr/liblp/include/liblp/metadata_format.h b/fs_mgr/liblp/include/liblp/metadata_format.h
index 8934aaf..6e928b4 100644
--- a/fs_mgr/liblp/include/liblp/metadata_format.h
+++ b/fs_mgr/liblp/include/liblp/metadata_format.h
@@ -39,7 +39,11 @@
/* Current metadata version. */
#define LP_METADATA_MAJOR_VERSION 10
-#define LP_METADATA_MINOR_VERSION 0
+#define LP_METADATA_MINOR_VERSION_MIN 0
+#define LP_METADATA_MINOR_VERSION_MAX 1
+
+/* Metadata version needed to use the UPDATED partition attribute. */
+#define LP_METADATA_VERSION_FOR_UPDATED_ATTR 1
/* Attributes for the LpMetadataPartition::attributes field.
*
@@ -58,8 +62,20 @@
*/
#define LP_PARTITION_ATTR_SLOT_SUFFIXED (1 << 1)
-/* Mask that defines all valid attributes. */
-#define LP_PARTITION_ATTRIBUTE_MASK (LP_PARTITION_ATTR_READONLY | LP_PARTITION_ATTR_SLOT_SUFFIXED)
+/* This flag is applied automatically when using MetadataBuilder::NewForUpdate.
+ * It signals that the partition was created (or modified) for a snapshot-based
+ * update. If this flag is not present, the partition was likely flashed via
+ * fastboot.
+ */
+#define LP_PARTITION_ATTR_UPDATED (1 << 2)
+
+/* Mask that defines all valid attributes. When changing this, make sure to
+ * update ParseMetadata().
+ */
+#define LP_PARTITION_ATTRIBUTE_MASK_V0 \
+ (LP_PARTITION_ATTR_READONLY | LP_PARTITION_ATTR_SLOT_SUFFIXED)
+#define LP_PARTITION_ATTRIBUTE_MASK_V1 (LP_PARTITION_ATTRIBUTE_MASK_V0 | LP_PARTITION_ATTR_UPDATED)
+#define LP_PARTITION_ATTRIBUTE_MASK LP_PARTITION_ATTRIBUTE_MASK_V1
/* Default name of the physical partition that holds logical partition entries.
* The layout of this partition will look like:
diff --git a/fs_mgr/liblp/io_test.cpp b/fs_mgr/liblp/io_test.cpp
index df89e9c..22f6746 100644
--- a/fs_mgr/liblp/io_test.cpp
+++ b/fs_mgr/liblp/io_test.cpp
@@ -713,3 +713,32 @@
ASSERT_EQ(updated->block_devices.size(), static_cast<size_t>(1));
EXPECT_EQ(GetBlockDevicePartitionName(updated->block_devices[0]), "super");
}
+
+TEST_F(LiblpTest, UpdateVirtualAB) {
+ ON_CALL(*GetMockedPropertyFetcher(), GetBoolProperty("ro.virtual_ab.enabled", _))
+ .WillByDefault(Return(true));
+
+ unique_fd fd = CreateFlashedDisk();
+ ASSERT_GE(fd, 0);
+
+ DefaultPartitionOpener opener(fd);
+ auto builder = MetadataBuilder::NewForUpdate(opener, "super", 0, 1);
+ ASSERT_NE(builder, nullptr);
+ auto updated = builder->Export();
+ ASSERT_NE(updated, nullptr);
+ ASSERT_TRUE(UpdatePartitionTable(opener, "super", *updated.get(), 1));
+
+ // Validate old slot.
+ auto metadata = ReadMetadata(opener, "super", 0);
+ ASSERT_NE(metadata, nullptr);
+ ASSERT_EQ(metadata->header.minor_version, 0);
+ ASSERT_GE(metadata->partitions.size(), 1);
+ ASSERT_EQ(metadata->partitions[0].attributes & LP_PARTITION_ATTR_UPDATED, 0);
+
+ // Validate new slot.
+ metadata = ReadMetadata(opener, "super", 1);
+ ASSERT_NE(metadata, nullptr);
+ ASSERT_EQ(metadata->header.minor_version, 1);
+ ASSERT_GE(metadata->partitions.size(), 1);
+ ASSERT_NE(metadata->partitions[0].attributes & LP_PARTITION_ATTR_UPDATED, 0);
+}
diff --git a/fs_mgr/liblp/reader.cpp b/fs_mgr/liblp/reader.cpp
index 8dbe955..aecf685 100644
--- a/fs_mgr/liblp/reader.cpp
+++ b/fs_mgr/liblp/reader.cpp
@@ -181,7 +181,7 @@
}
// Check that the version is compatible.
if (header.major_version != LP_METADATA_MAJOR_VERSION ||
- header.minor_version > LP_METADATA_MINOR_VERSION) {
+ header.minor_version > LP_METADATA_MINOR_VERSION_MAX) {
LERROR << "Logical partition metadata has incompatible version.";
return false;
}
@@ -245,6 +245,13 @@
return nullptr;
}
+ uint32_t valid_attributes = 0;
+ if (metadata->header.minor_version >= LP_METADATA_VERSION_FOR_UPDATED_ATTR) {
+ valid_attributes = LP_PARTITION_ATTRIBUTE_MASK_V1;
+ } else {
+ valid_attributes = LP_PARTITION_ATTRIBUTE_MASK_V0;
+ }
+
// ValidateTableSize ensured that |cursor| is valid for the number of
// entries in the table.
uint8_t* cursor = buffer.get() + header.partitions.offset;
@@ -253,7 +260,7 @@
memcpy(&partition, cursor, sizeof(partition));
cursor += header.partitions.entry_size;
- if (partition.attributes & ~LP_PARTITION_ATTRIBUTE_MASK) {
+ if (partition.attributes & ~valid_attributes) {
LERROR << "Logical partition has invalid attribute set.";
return nullptr;
}
diff --git a/fs_mgr/liblp/utility.cpp b/fs_mgr/liblp/utility.cpp
index 17f05aa..afcce8f 100644
--- a/fs_mgr/liblp/utility.cpp
+++ b/fs_mgr/liblp/utility.cpp
@@ -269,6 +269,7 @@
<< "; this partition should not belong to this group!";
continue; // not adding to new_partition_ptrs
}
+ partition.attributes |= LP_PARTITION_ATTR_UPDATED;
partition.group_index = std::distance(new_group_ptrs.begin(), it);
new_partition_ptrs.push_back(&partition);
}