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

Commit 6f4722e9 authored by David Anderson's avatar David Anderson Committed by Gerrit Code Review
Browse files

Merge "liblp: Reserve the first logical block of the super partition."

parents 30fa1b78 69204925
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -261,7 +261,7 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata
    // we store a backup copy of everything.
    uint64_t reserved =
            LP_METADATA_GEOMETRY_SIZE + (uint64_t(metadata_max_size) * metadata_slot_count);
    uint64_t total_reserved = reserved * 2;
    uint64_t total_reserved = LP_PARTITION_RESERVED_BYTES + reserved * 2;
    if (device_info.size < total_reserved) {
        LERROR << "Attempting to create metadata on a block device that is too small.";
        return false;
+16 −12
Original line number Diff line number Diff line
@@ -48,8 +48,11 @@ TEST(liblp, ResizePartition) {
    LinearExtent* extent = system->extents()[0]->AsLinearExtent();
    ASSERT_NE(extent, nullptr);
    EXPECT_EQ(extent->num_sectors(), 65536 / LP_SECTOR_SIZE);
    // The first logical sector will be (8192+1024*4)/512 = 12.
    EXPECT_EQ(extent->physical_sector(), 24);
    // The first logical sector will be:
    //      (LP_PARTITION_RESERVED_BYTES + 4096*2 + 1024*4) / 512
    // Or, in terms of sectors (reserved + geometry + metadata):
    //      (8 + 16 + 8) = 32
    EXPECT_EQ(extent->physical_sector(), 32);

    // Test resizing to the same size.
    EXPECT_EQ(builder->ResizePartition(system, 65536), true);
@@ -78,7 +81,7 @@ TEST(liblp, ResizePartition) {
    extent = system->extents()[0]->AsLinearExtent();
    ASSERT_NE(extent, nullptr);
    EXPECT_EQ(extent->num_sectors(), 32768 / LP_SECTOR_SIZE);
    EXPECT_EQ(extent->physical_sector(), 24);
    EXPECT_EQ(extent->physical_sector(), 32);

    // Test shrinking to 0.
    builder->ResizePartition(system, 0);
@@ -148,7 +151,7 @@ TEST(liblp, InternalAlignment) {
    ASSERT_NE(builder, nullptr);
    exported = builder->Export();
    ASSERT_NE(exported, nullptr);
    EXPECT_EQ(exported->geometry.first_logical_sector, 150);
    EXPECT_EQ(exported->geometry.first_logical_sector, 174);

    // Test a small alignment with no alignment offset.
    device_info.alignment = 11 * 1024;
@@ -202,7 +205,8 @@ TEST(liblp, UseAllDiskSpace) {
    // maximum size of a metadata blob. Then, we double that space since
    // we store a backup copy of everything.
    static constexpr uint64_t geometry = 4 * 1024;
    static constexpr uint64_t allocatable = total - (metadata * slots + geometry) * 2;
    static constexpr uint64_t allocatable =
            total - (metadata * slots + geometry) * 2 - LP_PARTITION_RESERVED_BYTES;
    EXPECT_EQ(builder->AllocatableSpace(), allocatable);
    EXPECT_EQ(builder->UsedSpace(), 0);

@@ -243,11 +247,11 @@ TEST(liblp, BuildComplex) {
    ASSERT_NE(system2, nullptr);
    ASSERT_NE(vendor1, nullptr);
    EXPECT_EQ(system1->num_sectors(), 65536 / LP_SECTOR_SIZE);
    EXPECT_EQ(system1->physical_sector(), 24);
    EXPECT_EQ(system1->physical_sector(), 32);
    EXPECT_EQ(system2->num_sectors(), 32768 / LP_SECTOR_SIZE);
    EXPECT_EQ(system2->physical_sector(), 216);
    EXPECT_EQ(system2->physical_sector(), 224);
    EXPECT_EQ(vendor1->num_sectors(), 32768 / LP_SECTOR_SIZE);
    EXPECT_EQ(vendor1->physical_sector(), 152);
    EXPECT_EQ(vendor1->physical_sector(), 160);
    EXPECT_EQ(system1->physical_sector() + system1->num_sectors(), vendor1->physical_sector());
    EXPECT_EQ(vendor1->physical_sector() + vendor1->num_sectors(), system2->physical_sector());
}
@@ -293,7 +297,7 @@ TEST(liblp, BuilderExport) {
    EXPECT_EQ(geometry.struct_size, sizeof(geometry));
    EXPECT_EQ(geometry.metadata_max_size, 1024);
    EXPECT_EQ(geometry.metadata_slot_count, 2);
    EXPECT_EQ(geometry.first_logical_sector, 24);
    EXPECT_EQ(geometry.first_logical_sector, 32);

    static const size_t kMetadataSpace =
            ((kMetadataSize * kMetadataSlots) + LP_METADATA_GEOMETRY_SIZE) * 2;
@@ -354,9 +358,9 @@ TEST(liblp, BuilderImport) {
    LinearExtent* system2 = system->extents()[1]->AsLinearExtent();
    LinearExtent* vendor1 = vendor->extents()[0]->AsLinearExtent();
    EXPECT_EQ(system1->num_sectors(), 65536 / LP_SECTOR_SIZE);
    EXPECT_EQ(system1->physical_sector(), 24);
    EXPECT_EQ(system1->physical_sector(), 32);
    EXPECT_EQ(system2->num_sectors(), 32768 / LP_SECTOR_SIZE);
    EXPECT_EQ(system2->physical_sector(), 216);
    EXPECT_EQ(system2->physical_sector(), 224);
    EXPECT_EQ(vendor1->num_sectors(), 32768 / LP_SECTOR_SIZE);
}

@@ -381,7 +385,7 @@ TEST(liblp, MetadataTooLarge) {
    EXPECT_EQ(builder, nullptr);

    // No space to store metadata + geometry + one free sector.
    device_info.size += LP_METADATA_GEOMETRY_SIZE * 2;
    device_info.size += LP_PARTITION_RESERVED_BYTES + (LP_METADATA_GEOMETRY_SIZE * 2);
    builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
    EXPECT_EQ(builder, nullptr);

+25 −7
Original line number Diff line number Diff line
@@ -28,12 +28,17 @@ namespace android {
namespace fs_mgr {

std::unique_ptr<LpMetadata> ReadFromImageFile(int fd) {
    LpMetadataGeometry geometry;
    if (!ReadLogicalPartitionGeometry(fd, &geometry)) {
    std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(LP_METADATA_GEOMETRY_SIZE);
    if (SeekFile64(fd, 0, SEEK_SET) < 0) {
        PERROR << __PRETTY_FUNCTION__ << " lseek failed";
        return nullptr;
    }
    if (!android::base::ReadFully(fd, buffer.get(), LP_METADATA_GEOMETRY_SIZE)) {
        PERROR << __PRETTY_FUNCTION__ << " read failed";
        return nullptr;
    }
    if (SeekFile64(fd, LP_METADATA_GEOMETRY_SIZE, SEEK_SET) < 0) {
        PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << LP_METADATA_GEOMETRY_SIZE;
    LpMetadataGeometry geometry;
    if (!ParseGeometry(buffer.get(), &geometry)) {
        return nullptr;
    }
    return ParseMetadata(geometry, fd);
@@ -106,6 +111,14 @@ SparseBuilder::SparseBuilder(const LpMetadata& metadata, uint32_t block_size,
        LERROR << "Metadata max size must be a multiple of the block size, " << block_size;
        return;
    }
    if (LP_METADATA_GEOMETRY_SIZE % block_size != 0) {
        LERROR << "Geometry size is not a multiple of the block size, " << block_size;
        return;
    }
    if (LP_PARTITION_RESERVED_BYTES % block_size != 0) {
        LERROR << "Reserved size is not a multiple of the block size, " << block_size;
        return;
    }

    uint64_t num_blocks = metadata.geometry.block_device_size % block_size;
    if (num_blocks >= UINT_MAX) {
@@ -163,6 +176,11 @@ bool SparseBuilder::SectorToBlock(uint64_t sector, uint32_t* block) {
}

bool SparseBuilder::Build() {
    if (sparse_file_add_fill(file_.get(), 0, LP_PARTITION_RESERVED_BYTES, 0) < 0) {
        LERROR << "Could not add initial sparse block for reserved zeroes";
        return false;
    }

    std::string geometry_blob = SerializeGeometry(geometry_);
    std::string metadata_blob = SerializeMetadata(metadata_);
    metadata_blob.resize(geometry_.metadata_max_size);
+6 −1
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ extern "C" {
#define LP_METADATA_HEADER_MAGIC 0x414C5030

/* Current metadata version. */
#define LP_METADATA_MAJOR_VERSION 5
#define LP_METADATA_MAJOR_VERSION 6
#define LP_METADATA_MINOR_VERSION 0

/* Attributes for the LpMetadataPartition::attributes field.
@@ -72,6 +72,11 @@ extern "C" {
/* Size of a sector is always 512 bytes for compatibility with the Linux kernel. */
#define LP_SECTOR_SIZE 512

/* Amount of space reserved at the start of every super partition to avoid
 * creating an accidental boot sector.
 */
#define LP_PARTITION_RESERVED_BYTES 4096

/* This structure is stored at block 0 in the first 4096 bytes of the
 * partition, and again in the following block. It is never modified and
 * describes how logical partition information can be located.
+1 −0
Original line number Diff line number Diff line
@@ -376,6 +376,7 @@ TEST(liblp, ImageFiles) {
    ASSERT_NE(builder, nullptr);
    ASSERT_TRUE(AddDefaultPartitions(builder.get()));
    unique_ptr<LpMetadata> exported = builder->Export();
    ASSERT_NE(exported, nullptr);

    unique_fd fd(syscall(__NR_memfd_create, "image_file", 0));
    ASSERT_GE(fd, 0);
Loading