Loading fs_mgr/liblp/builder.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading fs_mgr/liblp/builder_test.cpp +16 −12 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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()); } Loading Loading @@ -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; Loading Loading @@ -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); } Loading @@ -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); Loading fs_mgr/liblp/images.cpp +25 −7 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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) { Loading Loading @@ -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); Loading fs_mgr/liblp/include/liblp/metadata_format.h +6 −1 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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. Loading fs_mgr/liblp/io_test.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
fs_mgr/liblp/builder.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading
fs_mgr/liblp/builder_test.cpp +16 −12 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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()); } Loading Loading @@ -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; Loading Loading @@ -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); } Loading @@ -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); Loading
fs_mgr/liblp/images.cpp +25 −7 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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) { Loading Loading @@ -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); Loading
fs_mgr/liblp/include/liblp/metadata_format.h +6 −1 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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. Loading
fs_mgr/liblp/io_test.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -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