Loading fs_mgr/liblp/builder.cpp +15 −1 Original line number Diff line number Diff line Loading @@ -253,7 +253,7 @@ MetadataBuilder::MetadataBuilder() : auto_slot_suffixing_(false) { header_.magic = LP_METADATA_HEADER_MAGIC; header_.major_version = LP_METADATA_MAJOR_VERSION; header_.minor_version = LP_METADATA_MINOR_VERSION_MIN; header_.header_size = sizeof(header_); header_.header_size = sizeof(LpMetadataHeaderV1_0); header_.partitions.entry_size = sizeof(LpMetadataPartition); header_.extents.entry_size = sizeof(LpMetadataExtent); header_.groups.entry_size = sizeof(LpMetadataPartitionGroup); Loading @@ -264,6 +264,12 @@ bool MetadataBuilder::Init(const LpMetadata& metadata) { geometry_ = metadata.geometry; block_devices_ = metadata.block_devices; // Bump the version as necessary to copy any newer fields. if (metadata.header.minor_version >= LP_METADATA_VERSION_FOR_EXPANDED_HEADER) { RequireExpandedMetadataHeader(); header_.flags = metadata.header.flags; } for (const auto& group : metadata.groups) { std::string group_name = GetPartitionGroupName(group); if (!AddGroup(group_name, group.maximum_size)) { Loading Loading @@ -883,6 +889,14 @@ std::unique_ptr<LpMetadata> MetadataBuilder::Export() { return metadata; } void MetadataBuilder::RequireExpandedMetadataHeader() { if (header_.minor_version >= LP_METADATA_VERSION_FOR_EXPANDED_HEADER) { return; } header_.minor_version = LP_METADATA_VERSION_FOR_EXPANDED_HEADER; header_.header_size = sizeof(LpMetadataHeaderV1_2); } uint64_t MetadataBuilder::AllocatableSpace() const { uint64_t total_size = 0; for (const auto& block_device : block_devices_) { Loading fs_mgr/liblp/builder_test.cpp +20 −0 Original line number Diff line number Diff line Loading @@ -352,6 +352,7 @@ TEST_F(BuilderTest, BuilderExport) { 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_MIN); EXPECT_EQ(header.header_size, sizeof(LpMetadataHeaderV1_0)); ASSERT_EQ(exported->partitions.size(), 2); ASSERT_EQ(exported->extents.size(), 3); Loading Loading @@ -917,3 +918,22 @@ TEST_F(BuilderTest, Interval) { std::vector<Interval>{Interval(0, 100, 150)}) .size()); } TEST_F(BuilderTest, ExpandedHeader) { unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2); ASSERT_NE(builder, nullptr); builder->RequireExpandedMetadataHeader(); unique_ptr<LpMetadata> exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->header.header_size, sizeof(LpMetadataHeaderV1_2)); exported->header.flags = 0x5e5e5e5e; builder = MetadataBuilder::New(*exported.get()); exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->header.header_size, sizeof(LpMetadataHeaderV1_2)); EXPECT_EQ(exported->header.flags, 0x5e5e5e5e); } fs_mgr/liblp/include/liblp/builder.h +4 −0 Original line number Diff line number Diff line Loading @@ -325,6 +325,10 @@ class MetadataBuilder { bool GetBlockDeviceInfo(const std::string& partition_name, BlockDeviceInfo* info) const; bool UpdateBlockDeviceInfo(const std::string& partition_name, const BlockDeviceInfo& info); // Require the expanded metadata header. This is exposed for testing, and // is normally only called as needed by other methods. void RequireExpandedMetadataHeader(); // 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. Loading fs_mgr/liblp/include/liblp/metadata_format.h +39 −1 Original line number Diff line number Diff line Loading @@ -40,11 +40,14 @@ extern "C" { /* Current metadata version. */ #define LP_METADATA_MAJOR_VERSION 10 #define LP_METADATA_MINOR_VERSION_MIN 0 #define LP_METADATA_MINOR_VERSION_MAX 1 #define LP_METADATA_MINOR_VERSION_MAX 2 /* Metadata version needed to use the UPDATED partition attribute. */ #define LP_METADATA_VERSION_FOR_UPDATED_ATTR 1 /* Metadata version needed for the new expanded header struct. */ #define LP_METADATA_VERSION_FOR_EXPANDED_HEADER 2 /* Attributes for the LpMetadataPartition::attributes field. * * READONLY - The partition should not be considered writable. When used with Loading Loading @@ -212,6 +215,22 @@ typedef struct LpMetadataHeader { LpMetadataTableDescriptor groups; /* 116: Block device table. */ LpMetadataTableDescriptor block_devices; /* Everything past here is header version 1.2+, and is only included if * needed. When liblp supporting >= 1.2 reads a < 1.2 header, it must * zero these additional fields. */ /* 128: See LP_HEADER_FLAG_ constants for possible values. Header flags are * independent of the version number and intended to be informational only. * New flags can be added without bumping the version. * * (Note there are no flags currently defined.) */ uint32_t flags; /* 132: Reserved (zero), pad to 256 bytes. */ uint8_t reserved[124]; } __attribute__((packed)) LpMetadataHeader; /* This struct defines a logical partition entry, similar to what would be Loading Loading @@ -351,6 +370,25 @@ typedef struct LpMetadataBlockDevice { */ #define LP_BLOCK_DEVICE_SLOT_SUFFIXED (1 << 0) /* For ease of writing compatibility checks, the original metadata header is * preserved below, and typedefs are provided for the current version. */ typedef struct LpMetadataHeaderV1_0 { uint32_t magic; uint16_t major_version; uint16_t minor_version; uint32_t header_size; uint8_t header_checksum[32]; uint32_t tables_size; uint8_t tables_checksum[32]; LpMetadataTableDescriptor partitions; LpMetadataTableDescriptor extents; LpMetadataTableDescriptor groups; LpMetadataTableDescriptor block_devices; } __attribute__((packed)) LpMetadataHeaderV1_0; typedef LpMetadataHeader LpMetadataHeaderV1_2; #ifdef __cplusplus } /* extern "C" */ #endif Loading fs_mgr/liblp/io_test.cpp +26 −1 Original line number Diff line number Diff line Loading @@ -372,7 +372,7 @@ TEST_F(LiblpTest, TooManyPartitions) { // Compute the maximum number of partitions we can fit in 512 bytes of // metadata. By default there is the header, one partition group, and a // block device entry. static const size_t kMaxPartitionTableSize = kMetadataSize - sizeof(LpMetadataHeader) - static const size_t kMaxPartitionTableSize = kMetadataSize - sizeof(LpMetadataHeaderV1_0) - sizeof(LpMetadataPartitionGroup) - sizeof(LpMetadataBlockDevice); size_t max_partitions = kMaxPartitionTableSize / sizeof(LpMetadataPartition); Loading Loading @@ -742,3 +742,28 @@ TEST_F(LiblpTest, UpdateVirtualAB) { ASSERT_GE(metadata->partitions.size(), 1); ASSERT_NE(metadata->partitions[0].attributes & LP_PARTITION_ATTR_UPDATED, 0); } TEST_F(LiblpTest, ReadExpandedHeader) { unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder(); ASSERT_NE(builder, nullptr); ASSERT_TRUE(AddDefaultPartitions(builder.get())); builder->RequireExpandedMetadataHeader(); unique_fd fd = CreateFakeDisk(); ASSERT_GE(fd, 0); DefaultPartitionOpener opener(fd); // Export and flash. unique_ptr<LpMetadata> exported = builder->Export(); ASSERT_NE(exported, nullptr); exported->header.flags = 0x5e5e5e5e; ASSERT_TRUE(FlashPartitionTable(opener, "super", *exported.get())); unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0); ASSERT_NE(imported, nullptr); EXPECT_EQ(imported->header.header_size, sizeof(LpMetadataHeaderV1_2)); EXPECT_EQ(imported->header.header_size, exported->header.header_size); EXPECT_EQ(imported->header.flags, exported->header.flags); } Loading
fs_mgr/liblp/builder.cpp +15 −1 Original line number Diff line number Diff line Loading @@ -253,7 +253,7 @@ MetadataBuilder::MetadataBuilder() : auto_slot_suffixing_(false) { header_.magic = LP_METADATA_HEADER_MAGIC; header_.major_version = LP_METADATA_MAJOR_VERSION; header_.minor_version = LP_METADATA_MINOR_VERSION_MIN; header_.header_size = sizeof(header_); header_.header_size = sizeof(LpMetadataHeaderV1_0); header_.partitions.entry_size = sizeof(LpMetadataPartition); header_.extents.entry_size = sizeof(LpMetadataExtent); header_.groups.entry_size = sizeof(LpMetadataPartitionGroup); Loading @@ -264,6 +264,12 @@ bool MetadataBuilder::Init(const LpMetadata& metadata) { geometry_ = metadata.geometry; block_devices_ = metadata.block_devices; // Bump the version as necessary to copy any newer fields. if (metadata.header.minor_version >= LP_METADATA_VERSION_FOR_EXPANDED_HEADER) { RequireExpandedMetadataHeader(); header_.flags = metadata.header.flags; } for (const auto& group : metadata.groups) { std::string group_name = GetPartitionGroupName(group); if (!AddGroup(group_name, group.maximum_size)) { Loading Loading @@ -883,6 +889,14 @@ std::unique_ptr<LpMetadata> MetadataBuilder::Export() { return metadata; } void MetadataBuilder::RequireExpandedMetadataHeader() { if (header_.minor_version >= LP_METADATA_VERSION_FOR_EXPANDED_HEADER) { return; } header_.minor_version = LP_METADATA_VERSION_FOR_EXPANDED_HEADER; header_.header_size = sizeof(LpMetadataHeaderV1_2); } uint64_t MetadataBuilder::AllocatableSpace() const { uint64_t total_size = 0; for (const auto& block_device : block_devices_) { Loading
fs_mgr/liblp/builder_test.cpp +20 −0 Original line number Diff line number Diff line Loading @@ -352,6 +352,7 @@ TEST_F(BuilderTest, BuilderExport) { 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_MIN); EXPECT_EQ(header.header_size, sizeof(LpMetadataHeaderV1_0)); ASSERT_EQ(exported->partitions.size(), 2); ASSERT_EQ(exported->extents.size(), 3); Loading Loading @@ -917,3 +918,22 @@ TEST_F(BuilderTest, Interval) { std::vector<Interval>{Interval(0, 100, 150)}) .size()); } TEST_F(BuilderTest, ExpandedHeader) { unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2); ASSERT_NE(builder, nullptr); builder->RequireExpandedMetadataHeader(); unique_ptr<LpMetadata> exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->header.header_size, sizeof(LpMetadataHeaderV1_2)); exported->header.flags = 0x5e5e5e5e; builder = MetadataBuilder::New(*exported.get()); exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->header.header_size, sizeof(LpMetadataHeaderV1_2)); EXPECT_EQ(exported->header.flags, 0x5e5e5e5e); }
fs_mgr/liblp/include/liblp/builder.h +4 −0 Original line number Diff line number Diff line Loading @@ -325,6 +325,10 @@ class MetadataBuilder { bool GetBlockDeviceInfo(const std::string& partition_name, BlockDeviceInfo* info) const; bool UpdateBlockDeviceInfo(const std::string& partition_name, const BlockDeviceInfo& info); // Require the expanded metadata header. This is exposed for testing, and // is normally only called as needed by other methods. void RequireExpandedMetadataHeader(); // 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. Loading
fs_mgr/liblp/include/liblp/metadata_format.h +39 −1 Original line number Diff line number Diff line Loading @@ -40,11 +40,14 @@ extern "C" { /* Current metadata version. */ #define LP_METADATA_MAJOR_VERSION 10 #define LP_METADATA_MINOR_VERSION_MIN 0 #define LP_METADATA_MINOR_VERSION_MAX 1 #define LP_METADATA_MINOR_VERSION_MAX 2 /* Metadata version needed to use the UPDATED partition attribute. */ #define LP_METADATA_VERSION_FOR_UPDATED_ATTR 1 /* Metadata version needed for the new expanded header struct. */ #define LP_METADATA_VERSION_FOR_EXPANDED_HEADER 2 /* Attributes for the LpMetadataPartition::attributes field. * * READONLY - The partition should not be considered writable. When used with Loading Loading @@ -212,6 +215,22 @@ typedef struct LpMetadataHeader { LpMetadataTableDescriptor groups; /* 116: Block device table. */ LpMetadataTableDescriptor block_devices; /* Everything past here is header version 1.2+, and is only included if * needed. When liblp supporting >= 1.2 reads a < 1.2 header, it must * zero these additional fields. */ /* 128: See LP_HEADER_FLAG_ constants for possible values. Header flags are * independent of the version number and intended to be informational only. * New flags can be added without bumping the version. * * (Note there are no flags currently defined.) */ uint32_t flags; /* 132: Reserved (zero), pad to 256 bytes. */ uint8_t reserved[124]; } __attribute__((packed)) LpMetadataHeader; /* This struct defines a logical partition entry, similar to what would be Loading Loading @@ -351,6 +370,25 @@ typedef struct LpMetadataBlockDevice { */ #define LP_BLOCK_DEVICE_SLOT_SUFFIXED (1 << 0) /* For ease of writing compatibility checks, the original metadata header is * preserved below, and typedefs are provided for the current version. */ typedef struct LpMetadataHeaderV1_0 { uint32_t magic; uint16_t major_version; uint16_t minor_version; uint32_t header_size; uint8_t header_checksum[32]; uint32_t tables_size; uint8_t tables_checksum[32]; LpMetadataTableDescriptor partitions; LpMetadataTableDescriptor extents; LpMetadataTableDescriptor groups; LpMetadataTableDescriptor block_devices; } __attribute__((packed)) LpMetadataHeaderV1_0; typedef LpMetadataHeader LpMetadataHeaderV1_2; #ifdef __cplusplus } /* extern "C" */ #endif Loading
fs_mgr/liblp/io_test.cpp +26 −1 Original line number Diff line number Diff line Loading @@ -372,7 +372,7 @@ TEST_F(LiblpTest, TooManyPartitions) { // Compute the maximum number of partitions we can fit in 512 bytes of // metadata. By default there is the header, one partition group, and a // block device entry. static const size_t kMaxPartitionTableSize = kMetadataSize - sizeof(LpMetadataHeader) - static const size_t kMaxPartitionTableSize = kMetadataSize - sizeof(LpMetadataHeaderV1_0) - sizeof(LpMetadataPartitionGroup) - sizeof(LpMetadataBlockDevice); size_t max_partitions = kMaxPartitionTableSize / sizeof(LpMetadataPartition); Loading Loading @@ -742,3 +742,28 @@ TEST_F(LiblpTest, UpdateVirtualAB) { ASSERT_GE(metadata->partitions.size(), 1); ASSERT_NE(metadata->partitions[0].attributes & LP_PARTITION_ATTR_UPDATED, 0); } TEST_F(LiblpTest, ReadExpandedHeader) { unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder(); ASSERT_NE(builder, nullptr); ASSERT_TRUE(AddDefaultPartitions(builder.get())); builder->RequireExpandedMetadataHeader(); unique_fd fd = CreateFakeDisk(); ASSERT_GE(fd, 0); DefaultPartitionOpener opener(fd); // Export and flash. unique_ptr<LpMetadata> exported = builder->Export(); ASSERT_NE(exported, nullptr); exported->header.flags = 0x5e5e5e5e; ASSERT_TRUE(FlashPartitionTable(opener, "super", *exported.get())); unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0); ASSERT_NE(imported, nullptr); EXPECT_EQ(imported->header.header_size, sizeof(LpMetadataHeaderV1_2)); EXPECT_EQ(imported->header.header_size, exported->header.header_size); EXPECT_EQ(imported->header.flags, exported->header.flags); }