Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 18bb214b authored by David Anderson's avatar David Anderson Committed by Gerrit Code Review
Browse files

Merge "liblp: Expand the metadata header for future use."

parents 413440c5 9f75098c
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -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);
@@ -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)) {
@@ -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_) {
+20 −0
Original line number Diff line number Diff line
@@ -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);
@@ -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);
}
+4 −0
Original line number Diff line number Diff line
@@ -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.
+39 −1
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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
+26 −1
Original line number Diff line number Diff line
@@ -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);
@@ -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