Loading fs_mgr/liblp/builder.cpp +38 −30 Original line number Diff line number Diff line Loading @@ -150,7 +150,7 @@ std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const std::string& block_d } BlockDeviceInfo device_info; if (fs_mgr::GetBlockDeviceInfo(block_device, &device_info)) { builder->set_block_device_info(device_info); builder->UpdateBlockDeviceInfo(device_info); } return builder; } Loading Loading @@ -217,10 +217,6 @@ bool MetadataBuilder::Init(const LpMetadata& metadata) { } } } device_info_.alignment = geometry_.alignment; device_info_.alignment_offset = geometry_.alignment_offset; device_info_.logical_block_size = geometry_.logical_block_size; return true; } Loading @@ -239,24 +235,23 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata metadata_max_size = AlignTo(metadata_max_size, LP_SECTOR_SIZE); // Check that device properties are sane. device_info_ = device_info; if (device_info_.size % LP_SECTOR_SIZE != 0) { if (device_info.size % LP_SECTOR_SIZE != 0) { LERROR << "Block device size must be a multiple of 512."; return false; } if (device_info_.logical_block_size % LP_SECTOR_SIZE != 0) { if (device_info.logical_block_size % LP_SECTOR_SIZE != 0) { LERROR << "Logical block size must be a multiple of 512."; return false; } if (device_info_.alignment_offset % LP_SECTOR_SIZE != 0) { if (device_info.alignment_offset % LP_SECTOR_SIZE != 0) { LERROR << "Alignment offset is not sector-aligned."; return false; } if (device_info_.alignment % LP_SECTOR_SIZE != 0) { if (device_info.alignment % LP_SECTOR_SIZE != 0) { LERROR << "Partition alignment is not sector-aligned."; return false; } if (device_info_.alignment_offset > device_info_.alignment) { if (device_info.alignment_offset > device_info.alignment) { LERROR << "Partition alignment offset is greater than its alignment."; return false; } Loading @@ -267,20 +262,21 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata uint64_t reserved = LP_METADATA_GEOMETRY_SIZE + (uint64_t(metadata_max_size) * metadata_slot_count); uint64_t total_reserved = reserved * 2; if (device_info_.size < total_reserved) { if (device_info.size < total_reserved) { LERROR << "Attempting to create metadata on a block device that is too small."; return false; } // Compute the first free sector, factoring in alignment. uint64_t free_area = AlignTo(reserved, device_info_.alignment, device_info_.alignment_offset); uint64_t free_area = AlignTo(total_reserved, device_info.alignment, device_info.alignment_offset); uint64_t first_sector = free_area / LP_SECTOR_SIZE; // Compute the last free sector, which is inclusive. We subtract 1 to make // sure that logical partitions won't overlap with the same sector as the // backup metadata, which could happen if the block device was not aligned // to LP_SECTOR_SIZE. uint64_t last_sector = ((device_info_.size - reserved) / LP_SECTOR_SIZE) - 1; uint64_t last_sector = (device_info.size / LP_SECTOR_SIZE) - 1; // If this check fails, it means either (1) we did not have free space to // allocate a single sector, or (2) we did, but the alignment was high Loading @@ -296,7 +292,7 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata // computation, then we abort. Note that the last sector is inclusive, // so we have to account for that. uint64_t num_free_sectors = last_sector - first_sector + 1; uint64_t sectors_per_block = device_info_.logical_block_size / LP_SECTOR_SIZE; uint64_t sectors_per_block = device_info.logical_block_size / LP_SECTOR_SIZE; if (num_free_sectors < sectors_per_block) { LERROR << "Not enough space to allocate any partition tables."; return false; Loading @@ -307,9 +303,9 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata geometry_.last_logical_sector = last_sector; geometry_.metadata_max_size = metadata_max_size; geometry_.metadata_slot_count = metadata_slot_count; geometry_.alignment = device_info_.alignment; geometry_.alignment_offset = device_info_.alignment_offset; geometry_.block_device_size = device_info_.size; geometry_.alignment = device_info.alignment; geometry_.alignment_offset = device_info.alignment_offset; geometry_.block_device_size = device_info.size; geometry_.logical_block_size = device_info.logical_block_size; if (!AddGroup("default", 0)) { Loading Loading @@ -460,7 +456,7 @@ bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size) free_regions.emplace_back(last_free_extent_start, geometry_.last_logical_sector + 1); } const uint64_t sectors_per_block = device_info_.logical_block_size / LP_SECTOR_SIZE; const uint64_t sectors_per_block = geometry_.logical_block_size / LP_SECTOR_SIZE; CHECK_NE(sectors_per_block, 0); CHECK(sectors_needed % sectors_per_block == 0); Loading Loading @@ -578,32 +574,44 @@ uint64_t MetadataBuilder::AlignSector(uint64_t sector) { // Note: when reading alignment info from the Kernel, we don't assume it // is aligned to the sector size, so we round up to the nearest sector. uint64_t lba = sector * LP_SECTOR_SIZE; uint64_t aligned = AlignTo(lba, device_info_.alignment, device_info_.alignment_offset); uint64_t aligned = AlignTo(lba, geometry_.alignment, geometry_.alignment_offset); return AlignTo(aligned, LP_SECTOR_SIZE) / LP_SECTOR_SIZE; } void MetadataBuilder::set_block_device_info(const BlockDeviceInfo& device_info) { device_info_.size = device_info.size; bool MetadataBuilder::GetBlockDeviceInfo(BlockDeviceInfo* info) const { info->size = geometry_.block_device_size; info->alignment = geometry_.alignment; info->alignment_offset = geometry_.alignment_offset; info->logical_block_size = geometry_.logical_block_size; return true; } // Note that if the logical block size changes, we're probably in trouble: // we could have already built extents that will only work on the previous // size. DCHECK(partitions_.empty() || device_info_.logical_block_size == device_info.logical_block_size); bool MetadataBuilder::UpdateBlockDeviceInfo(const BlockDeviceInfo& device_info) { if (device_info.size != geometry_.block_device_size) { LERROR << "Device size does not match (got " << device_info.size << ", expected " << geometry_.block_device_size << ")"; return false; } if (device_info.logical_block_size != geometry_.logical_block_size) { LERROR << "Device logical block size does not match (got " << device_info.logical_block_size << ", expected " << geometry_.logical_block_size << ")"; return false; } // The kernel does not guarantee these values are present, so we only // replace existing values if the new values are non-zero. if (device_info.alignment) { device_info_.alignment = device_info.alignment; geometry_.alignment = device_info.alignment; } if (device_info.alignment_offset) { device_info_.alignment_offset = device_info.alignment_offset; geometry_.alignment_offset = device_info.alignment_offset; } return true; } bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_size) { // Align the space needed up to the nearest sector. uint64_t aligned_size = AlignTo(requested_size, device_info_.logical_block_size); uint64_t aligned_size = AlignTo(requested_size, geometry_.logical_block_size); uint64_t old_size = partition->size(); if (aligned_size > old_size) { Loading fs_mgr/liblp/builder_test.cpp +42 −29 Original line number Diff line number Diff line Loading @@ -48,8 +48,8 @@ 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 (4096+1024*2)/512 = 12. EXPECT_EQ(extent->physical_sector(), 12); // The first logical sector will be (8192+1024*4)/512 = 12. EXPECT_EQ(extent->physical_sector(), 24); // Test resizing to the same size. EXPECT_EQ(builder->ResizePartition(system, 65536), true); Loading Loading @@ -78,7 +78,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(), 12); EXPECT_EQ(extent->physical_sector(), 24); // Test shrinking to 0. builder->ResizePartition(system, 0); Loading Loading @@ -127,7 +127,7 @@ TEST(liblp, InternalAlignment) { unique_ptr<LpMetadata> exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->geometry.first_logical_sector, 1536); EXPECT_EQ(exported->geometry.last_logical_sector, 2031); EXPECT_EQ(exported->geometry.last_logical_sector, 2047); // Test a large alignment offset thrown in. device_info.alignment_offset = 753664; Loading @@ -136,7 +136,7 @@ TEST(liblp, InternalAlignment) { exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->geometry.first_logical_sector, 1472); EXPECT_EQ(exported->geometry.last_logical_sector, 2031); EXPECT_EQ(exported->geometry.last_logical_sector, 2047); // Alignment offset without alignment doesn't mean anything. device_info.alignment = 0; Loading @@ -150,8 +150,8 @@ TEST(liblp, InternalAlignment) { ASSERT_NE(builder, nullptr); exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->geometry.first_logical_sector, 78); EXPECT_EQ(exported->geometry.last_logical_sector, 1973); EXPECT_EQ(exported->geometry.first_logical_sector, 150); EXPECT_EQ(exported->geometry.last_logical_sector, 2045); // Test a small alignment with no alignment offset. device_info.alignment = 11 * 1024; Loading @@ -159,8 +159,8 @@ TEST(liblp, InternalAlignment) { ASSERT_NE(builder, nullptr); exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->geometry.first_logical_sector, 72); EXPECT_EQ(exported->geometry.last_logical_sector, 1975); EXPECT_EQ(exported->geometry.first_logical_sector, 160); EXPECT_EQ(exported->geometry.last_logical_sector, 2047); } TEST(liblp, InternalPartitionAlignment) { Loading Loading @@ -247,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(), 12); EXPECT_EQ(system1->physical_sector(), 24); EXPECT_EQ(system2->num_sectors(), 32768 / LP_SECTOR_SIZE); EXPECT_EQ(system2->physical_sector(), 204); EXPECT_EQ(system2->physical_sector(), 216); EXPECT_EQ(vendor1->num_sectors(), 32768 / LP_SECTOR_SIZE); EXPECT_EQ(vendor1->physical_sector(), 140); EXPECT_EQ(vendor1->physical_sector(), 152); EXPECT_EQ(system1->physical_sector() + system1->num_sectors(), vendor1->physical_sector()); EXPECT_EQ(vendor1->physical_sector() + vendor1->num_sectors(), system2->physical_sector()); } Loading Loading @@ -297,13 +297,11 @@ 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, 12); EXPECT_EQ(geometry.last_logical_sector, 2035); EXPECT_EQ(geometry.first_logical_sector, 24); EXPECT_EQ(geometry.last_logical_sector, 2047); static const size_t kMetadataSpace = (kMetadataSize * kMetadataSlots) + LP_METADATA_GEOMETRY_SIZE; uint64_t space_at_end = kDiskSize - (geometry.last_logical_sector + 1) * LP_SECTOR_SIZE; EXPECT_GE(space_at_end, kMetadataSpace); ((kMetadataSize * kMetadataSlots) + LP_METADATA_GEOMETRY_SIZE) * 2; EXPECT_GE(geometry.first_logical_sector * LP_SECTOR_SIZE, kMetadataSpace); // Verify header. Loading Loading @@ -361,9 +359,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(), 12); EXPECT_EQ(system1->physical_sector(), 24); EXPECT_EQ(system2->num_sectors(), 32768 / LP_SECTOR_SIZE); EXPECT_EQ(system2->physical_sector(), 204); EXPECT_EQ(system2->physical_sector(), 216); EXPECT_EQ(vendor1->num_sectors(), 32768 / LP_SECTOR_SIZE); } Loading Loading @@ -437,22 +435,37 @@ TEST(liblp, UpdateBlockDeviceInfo) { unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1); ASSERT_NE(builder, nullptr); EXPECT_EQ(builder->block_device_info().size, device_info.size); EXPECT_EQ(builder->block_device_info().alignment, device_info.alignment); EXPECT_EQ(builder->block_device_info().alignment_offset, device_info.alignment_offset); EXPECT_EQ(builder->block_device_info().logical_block_size, device_info.logical_block_size); BlockDeviceInfo new_info; ASSERT_TRUE(builder->GetBlockDeviceInfo(&new_info)); EXPECT_EQ(new_info.size, device_info.size); EXPECT_EQ(new_info.alignment, device_info.alignment); EXPECT_EQ(new_info.alignment_offset, device_info.alignment_offset); EXPECT_EQ(new_info.logical_block_size, device_info.logical_block_size); device_info.alignment = 0; device_info.alignment_offset = 2048; builder->set_block_device_info(device_info); EXPECT_EQ(builder->block_device_info().alignment, 4096); EXPECT_EQ(builder->block_device_info().alignment_offset, device_info.alignment_offset); ASSERT_TRUE(builder->UpdateBlockDeviceInfo(device_info)); ASSERT_TRUE(builder->GetBlockDeviceInfo(&new_info)); EXPECT_EQ(new_info.alignment, 4096); EXPECT_EQ(new_info.alignment_offset, device_info.alignment_offset); device_info.alignment = 8192; device_info.alignment_offset = 0; builder->set_block_device_info(device_info); EXPECT_EQ(builder->block_device_info().alignment, 8192); EXPECT_EQ(builder->block_device_info().alignment_offset, 2048); ASSERT_TRUE(builder->UpdateBlockDeviceInfo(device_info)); ASSERT_TRUE(builder->GetBlockDeviceInfo(&new_info)); EXPECT_EQ(new_info.alignment, 8192); EXPECT_EQ(new_info.alignment_offset, 2048); new_info.size += 4096; ASSERT_FALSE(builder->UpdateBlockDeviceInfo(new_info)); ASSERT_TRUE(builder->GetBlockDeviceInfo(&new_info)); EXPECT_EQ(new_info.size, 1024 * 1024); new_info.logical_block_size = 512; ASSERT_FALSE(builder->UpdateBlockDeviceInfo(new_info)); ASSERT_TRUE(builder->GetBlockDeviceInfo(&new_info)); EXPECT_EQ(new_info.logical_block_size, 4096); } TEST(liblp, InvalidBlockSize) { Loading fs_mgr/liblp/images.cpp +5 −20 Original line number Diff line number Diff line Loading @@ -167,16 +167,12 @@ bool SparseBuilder::Build() { std::string metadata_blob = SerializeMetadata(metadata_); metadata_blob.resize(geometry_.metadata_max_size); std::string all_metadata; for (size_t i = 0; i < geometry_.metadata_slot_count; i++) { all_metadata += metadata_blob; // Two copies of geometry, then two copies of each metadata slot. all_metadata_ += geometry_blob + geometry_blob; for (size_t i = 0; i < geometry_.metadata_slot_count * 2; i++) { all_metadata_ += metadata_blob; } // Metadata immediately follows geometry, and we write the same metadata // to all slots. Note that we don't bother trying to write skip chunks // here since it's a small amount of data. primary_blob_ = geometry_blob + all_metadata; if (!AddData(primary_blob_, 0)) { if (!AddData(all_metadata_, 0)) { return false; } Loading @@ -195,17 +191,6 @@ bool SparseBuilder::Build() { LERROR << "Partition image was specified but no partition was found."; return false; } // The backup area contains all metadata slots, and then geometry. Similar // to before we write the metadata to every slot. int64_t backup_offset = GetBackupMetadataOffset(geometry_, 0); int64_t backups_start = static_cast<int64_t>(geometry_.block_device_size) + backup_offset; int64_t backup_sector = backups_start / LP_SECTOR_SIZE; backup_blob_ = all_metadata + geometry_blob; if (!AddData(backup_blob_, backup_sector)) { return false; } return true; } Loading fs_mgr/liblp/images.h +1 −2 Original line number Diff line number Diff line Loading @@ -56,8 +56,7 @@ class SparseBuilder { const LpMetadataGeometry& geometry_; uint32_t block_size_; std::unique_ptr<sparse_file, decltype(&sparse_file_destroy)> file_; std::string primary_blob_; std::string backup_blob_; std::string all_metadata_; std::map<std::string, std::string> images_; std::vector<android::base::unique_fd> temp_fds_; }; Loading fs_mgr/liblp/include/liblp/builder.h +2 −5 Original line number Diff line number Diff line Loading @@ -215,10 +215,8 @@ class MetadataBuilder { uint64_t AllocatableSpace() const; uint64_t UsedSpace() const; // Merge new block device information into previous values. Alignment values // are only overwritten if the new values are non-zero. void set_block_device_info(const BlockDeviceInfo& device_info); const BlockDeviceInfo& block_device_info() const { return device_info_; } bool GetBlockDeviceInfo(BlockDeviceInfo* info) const; bool UpdateBlockDeviceInfo(const BlockDeviceInfo& info); private: MetadataBuilder(); Loading @@ -238,7 +236,6 @@ class MetadataBuilder { LpMetadataHeader header_; std::vector<std::unique_ptr<Partition>> partitions_; std::vector<std::unique_ptr<PartitionGroup>> groups_; BlockDeviceInfo device_info_; }; // Read BlockDeviceInfo for a given block device. This always returns false Loading Loading
fs_mgr/liblp/builder.cpp +38 −30 Original line number Diff line number Diff line Loading @@ -150,7 +150,7 @@ std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const std::string& block_d } BlockDeviceInfo device_info; if (fs_mgr::GetBlockDeviceInfo(block_device, &device_info)) { builder->set_block_device_info(device_info); builder->UpdateBlockDeviceInfo(device_info); } return builder; } Loading Loading @@ -217,10 +217,6 @@ bool MetadataBuilder::Init(const LpMetadata& metadata) { } } } device_info_.alignment = geometry_.alignment; device_info_.alignment_offset = geometry_.alignment_offset; device_info_.logical_block_size = geometry_.logical_block_size; return true; } Loading @@ -239,24 +235,23 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata metadata_max_size = AlignTo(metadata_max_size, LP_SECTOR_SIZE); // Check that device properties are sane. device_info_ = device_info; if (device_info_.size % LP_SECTOR_SIZE != 0) { if (device_info.size % LP_SECTOR_SIZE != 0) { LERROR << "Block device size must be a multiple of 512."; return false; } if (device_info_.logical_block_size % LP_SECTOR_SIZE != 0) { if (device_info.logical_block_size % LP_SECTOR_SIZE != 0) { LERROR << "Logical block size must be a multiple of 512."; return false; } if (device_info_.alignment_offset % LP_SECTOR_SIZE != 0) { if (device_info.alignment_offset % LP_SECTOR_SIZE != 0) { LERROR << "Alignment offset is not sector-aligned."; return false; } if (device_info_.alignment % LP_SECTOR_SIZE != 0) { if (device_info.alignment % LP_SECTOR_SIZE != 0) { LERROR << "Partition alignment is not sector-aligned."; return false; } if (device_info_.alignment_offset > device_info_.alignment) { if (device_info.alignment_offset > device_info.alignment) { LERROR << "Partition alignment offset is greater than its alignment."; return false; } Loading @@ -267,20 +262,21 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata uint64_t reserved = LP_METADATA_GEOMETRY_SIZE + (uint64_t(metadata_max_size) * metadata_slot_count); uint64_t total_reserved = reserved * 2; if (device_info_.size < total_reserved) { if (device_info.size < total_reserved) { LERROR << "Attempting to create metadata on a block device that is too small."; return false; } // Compute the first free sector, factoring in alignment. uint64_t free_area = AlignTo(reserved, device_info_.alignment, device_info_.alignment_offset); uint64_t free_area = AlignTo(total_reserved, device_info.alignment, device_info.alignment_offset); uint64_t first_sector = free_area / LP_SECTOR_SIZE; // Compute the last free sector, which is inclusive. We subtract 1 to make // sure that logical partitions won't overlap with the same sector as the // backup metadata, which could happen if the block device was not aligned // to LP_SECTOR_SIZE. uint64_t last_sector = ((device_info_.size - reserved) / LP_SECTOR_SIZE) - 1; uint64_t last_sector = (device_info.size / LP_SECTOR_SIZE) - 1; // If this check fails, it means either (1) we did not have free space to // allocate a single sector, or (2) we did, but the alignment was high Loading @@ -296,7 +292,7 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata // computation, then we abort. Note that the last sector is inclusive, // so we have to account for that. uint64_t num_free_sectors = last_sector - first_sector + 1; uint64_t sectors_per_block = device_info_.logical_block_size / LP_SECTOR_SIZE; uint64_t sectors_per_block = device_info.logical_block_size / LP_SECTOR_SIZE; if (num_free_sectors < sectors_per_block) { LERROR << "Not enough space to allocate any partition tables."; return false; Loading @@ -307,9 +303,9 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata geometry_.last_logical_sector = last_sector; geometry_.metadata_max_size = metadata_max_size; geometry_.metadata_slot_count = metadata_slot_count; geometry_.alignment = device_info_.alignment; geometry_.alignment_offset = device_info_.alignment_offset; geometry_.block_device_size = device_info_.size; geometry_.alignment = device_info.alignment; geometry_.alignment_offset = device_info.alignment_offset; geometry_.block_device_size = device_info.size; geometry_.logical_block_size = device_info.logical_block_size; if (!AddGroup("default", 0)) { Loading Loading @@ -460,7 +456,7 @@ bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size) free_regions.emplace_back(last_free_extent_start, geometry_.last_logical_sector + 1); } const uint64_t sectors_per_block = device_info_.logical_block_size / LP_SECTOR_SIZE; const uint64_t sectors_per_block = geometry_.logical_block_size / LP_SECTOR_SIZE; CHECK_NE(sectors_per_block, 0); CHECK(sectors_needed % sectors_per_block == 0); Loading Loading @@ -578,32 +574,44 @@ uint64_t MetadataBuilder::AlignSector(uint64_t sector) { // Note: when reading alignment info from the Kernel, we don't assume it // is aligned to the sector size, so we round up to the nearest sector. uint64_t lba = sector * LP_SECTOR_SIZE; uint64_t aligned = AlignTo(lba, device_info_.alignment, device_info_.alignment_offset); uint64_t aligned = AlignTo(lba, geometry_.alignment, geometry_.alignment_offset); return AlignTo(aligned, LP_SECTOR_SIZE) / LP_SECTOR_SIZE; } void MetadataBuilder::set_block_device_info(const BlockDeviceInfo& device_info) { device_info_.size = device_info.size; bool MetadataBuilder::GetBlockDeviceInfo(BlockDeviceInfo* info) const { info->size = geometry_.block_device_size; info->alignment = geometry_.alignment; info->alignment_offset = geometry_.alignment_offset; info->logical_block_size = geometry_.logical_block_size; return true; } // Note that if the logical block size changes, we're probably in trouble: // we could have already built extents that will only work on the previous // size. DCHECK(partitions_.empty() || device_info_.logical_block_size == device_info.logical_block_size); bool MetadataBuilder::UpdateBlockDeviceInfo(const BlockDeviceInfo& device_info) { if (device_info.size != geometry_.block_device_size) { LERROR << "Device size does not match (got " << device_info.size << ", expected " << geometry_.block_device_size << ")"; return false; } if (device_info.logical_block_size != geometry_.logical_block_size) { LERROR << "Device logical block size does not match (got " << device_info.logical_block_size << ", expected " << geometry_.logical_block_size << ")"; return false; } // The kernel does not guarantee these values are present, so we only // replace existing values if the new values are non-zero. if (device_info.alignment) { device_info_.alignment = device_info.alignment; geometry_.alignment = device_info.alignment; } if (device_info.alignment_offset) { device_info_.alignment_offset = device_info.alignment_offset; geometry_.alignment_offset = device_info.alignment_offset; } return true; } bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_size) { // Align the space needed up to the nearest sector. uint64_t aligned_size = AlignTo(requested_size, device_info_.logical_block_size); uint64_t aligned_size = AlignTo(requested_size, geometry_.logical_block_size); uint64_t old_size = partition->size(); if (aligned_size > old_size) { Loading
fs_mgr/liblp/builder_test.cpp +42 −29 Original line number Diff line number Diff line Loading @@ -48,8 +48,8 @@ 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 (4096+1024*2)/512 = 12. EXPECT_EQ(extent->physical_sector(), 12); // The first logical sector will be (8192+1024*4)/512 = 12. EXPECT_EQ(extent->physical_sector(), 24); // Test resizing to the same size. EXPECT_EQ(builder->ResizePartition(system, 65536), true); Loading Loading @@ -78,7 +78,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(), 12); EXPECT_EQ(extent->physical_sector(), 24); // Test shrinking to 0. builder->ResizePartition(system, 0); Loading Loading @@ -127,7 +127,7 @@ TEST(liblp, InternalAlignment) { unique_ptr<LpMetadata> exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->geometry.first_logical_sector, 1536); EXPECT_EQ(exported->geometry.last_logical_sector, 2031); EXPECT_EQ(exported->geometry.last_logical_sector, 2047); // Test a large alignment offset thrown in. device_info.alignment_offset = 753664; Loading @@ -136,7 +136,7 @@ TEST(liblp, InternalAlignment) { exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->geometry.first_logical_sector, 1472); EXPECT_EQ(exported->geometry.last_logical_sector, 2031); EXPECT_EQ(exported->geometry.last_logical_sector, 2047); // Alignment offset without alignment doesn't mean anything. device_info.alignment = 0; Loading @@ -150,8 +150,8 @@ TEST(liblp, InternalAlignment) { ASSERT_NE(builder, nullptr); exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->geometry.first_logical_sector, 78); EXPECT_EQ(exported->geometry.last_logical_sector, 1973); EXPECT_EQ(exported->geometry.first_logical_sector, 150); EXPECT_EQ(exported->geometry.last_logical_sector, 2045); // Test a small alignment with no alignment offset. device_info.alignment = 11 * 1024; Loading @@ -159,8 +159,8 @@ TEST(liblp, InternalAlignment) { ASSERT_NE(builder, nullptr); exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->geometry.first_logical_sector, 72); EXPECT_EQ(exported->geometry.last_logical_sector, 1975); EXPECT_EQ(exported->geometry.first_logical_sector, 160); EXPECT_EQ(exported->geometry.last_logical_sector, 2047); } TEST(liblp, InternalPartitionAlignment) { Loading Loading @@ -247,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(), 12); EXPECT_EQ(system1->physical_sector(), 24); EXPECT_EQ(system2->num_sectors(), 32768 / LP_SECTOR_SIZE); EXPECT_EQ(system2->physical_sector(), 204); EXPECT_EQ(system2->physical_sector(), 216); EXPECT_EQ(vendor1->num_sectors(), 32768 / LP_SECTOR_SIZE); EXPECT_EQ(vendor1->physical_sector(), 140); EXPECT_EQ(vendor1->physical_sector(), 152); EXPECT_EQ(system1->physical_sector() + system1->num_sectors(), vendor1->physical_sector()); EXPECT_EQ(vendor1->physical_sector() + vendor1->num_sectors(), system2->physical_sector()); } Loading Loading @@ -297,13 +297,11 @@ 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, 12); EXPECT_EQ(geometry.last_logical_sector, 2035); EXPECT_EQ(geometry.first_logical_sector, 24); EXPECT_EQ(geometry.last_logical_sector, 2047); static const size_t kMetadataSpace = (kMetadataSize * kMetadataSlots) + LP_METADATA_GEOMETRY_SIZE; uint64_t space_at_end = kDiskSize - (geometry.last_logical_sector + 1) * LP_SECTOR_SIZE; EXPECT_GE(space_at_end, kMetadataSpace); ((kMetadataSize * kMetadataSlots) + LP_METADATA_GEOMETRY_SIZE) * 2; EXPECT_GE(geometry.first_logical_sector * LP_SECTOR_SIZE, kMetadataSpace); // Verify header. Loading Loading @@ -361,9 +359,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(), 12); EXPECT_EQ(system1->physical_sector(), 24); EXPECT_EQ(system2->num_sectors(), 32768 / LP_SECTOR_SIZE); EXPECT_EQ(system2->physical_sector(), 204); EXPECT_EQ(system2->physical_sector(), 216); EXPECT_EQ(vendor1->num_sectors(), 32768 / LP_SECTOR_SIZE); } Loading Loading @@ -437,22 +435,37 @@ TEST(liblp, UpdateBlockDeviceInfo) { unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1); ASSERT_NE(builder, nullptr); EXPECT_EQ(builder->block_device_info().size, device_info.size); EXPECT_EQ(builder->block_device_info().alignment, device_info.alignment); EXPECT_EQ(builder->block_device_info().alignment_offset, device_info.alignment_offset); EXPECT_EQ(builder->block_device_info().logical_block_size, device_info.logical_block_size); BlockDeviceInfo new_info; ASSERT_TRUE(builder->GetBlockDeviceInfo(&new_info)); EXPECT_EQ(new_info.size, device_info.size); EXPECT_EQ(new_info.alignment, device_info.alignment); EXPECT_EQ(new_info.alignment_offset, device_info.alignment_offset); EXPECT_EQ(new_info.logical_block_size, device_info.logical_block_size); device_info.alignment = 0; device_info.alignment_offset = 2048; builder->set_block_device_info(device_info); EXPECT_EQ(builder->block_device_info().alignment, 4096); EXPECT_EQ(builder->block_device_info().alignment_offset, device_info.alignment_offset); ASSERT_TRUE(builder->UpdateBlockDeviceInfo(device_info)); ASSERT_TRUE(builder->GetBlockDeviceInfo(&new_info)); EXPECT_EQ(new_info.alignment, 4096); EXPECT_EQ(new_info.alignment_offset, device_info.alignment_offset); device_info.alignment = 8192; device_info.alignment_offset = 0; builder->set_block_device_info(device_info); EXPECT_EQ(builder->block_device_info().alignment, 8192); EXPECT_EQ(builder->block_device_info().alignment_offset, 2048); ASSERT_TRUE(builder->UpdateBlockDeviceInfo(device_info)); ASSERT_TRUE(builder->GetBlockDeviceInfo(&new_info)); EXPECT_EQ(new_info.alignment, 8192); EXPECT_EQ(new_info.alignment_offset, 2048); new_info.size += 4096; ASSERT_FALSE(builder->UpdateBlockDeviceInfo(new_info)); ASSERT_TRUE(builder->GetBlockDeviceInfo(&new_info)); EXPECT_EQ(new_info.size, 1024 * 1024); new_info.logical_block_size = 512; ASSERT_FALSE(builder->UpdateBlockDeviceInfo(new_info)); ASSERT_TRUE(builder->GetBlockDeviceInfo(&new_info)); EXPECT_EQ(new_info.logical_block_size, 4096); } TEST(liblp, InvalidBlockSize) { Loading
fs_mgr/liblp/images.cpp +5 −20 Original line number Diff line number Diff line Loading @@ -167,16 +167,12 @@ bool SparseBuilder::Build() { std::string metadata_blob = SerializeMetadata(metadata_); metadata_blob.resize(geometry_.metadata_max_size); std::string all_metadata; for (size_t i = 0; i < geometry_.metadata_slot_count; i++) { all_metadata += metadata_blob; // Two copies of geometry, then two copies of each metadata slot. all_metadata_ += geometry_blob + geometry_blob; for (size_t i = 0; i < geometry_.metadata_slot_count * 2; i++) { all_metadata_ += metadata_blob; } // Metadata immediately follows geometry, and we write the same metadata // to all slots. Note that we don't bother trying to write skip chunks // here since it's a small amount of data. primary_blob_ = geometry_blob + all_metadata; if (!AddData(primary_blob_, 0)) { if (!AddData(all_metadata_, 0)) { return false; } Loading @@ -195,17 +191,6 @@ bool SparseBuilder::Build() { LERROR << "Partition image was specified but no partition was found."; return false; } // The backup area contains all metadata slots, and then geometry. Similar // to before we write the metadata to every slot. int64_t backup_offset = GetBackupMetadataOffset(geometry_, 0); int64_t backups_start = static_cast<int64_t>(geometry_.block_device_size) + backup_offset; int64_t backup_sector = backups_start / LP_SECTOR_SIZE; backup_blob_ = all_metadata + geometry_blob; if (!AddData(backup_blob_, backup_sector)) { return false; } return true; } Loading
fs_mgr/liblp/images.h +1 −2 Original line number Diff line number Diff line Loading @@ -56,8 +56,7 @@ class SparseBuilder { const LpMetadataGeometry& geometry_; uint32_t block_size_; std::unique_ptr<sparse_file, decltype(&sparse_file_destroy)> file_; std::string primary_blob_; std::string backup_blob_; std::string all_metadata_; std::map<std::string, std::string> images_; std::vector<android::base::unique_fd> temp_fds_; }; Loading
fs_mgr/liblp/include/liblp/builder.h +2 −5 Original line number Diff line number Diff line Loading @@ -215,10 +215,8 @@ class MetadataBuilder { uint64_t AllocatableSpace() const; uint64_t UsedSpace() const; // Merge new block device information into previous values. Alignment values // are only overwritten if the new values are non-zero. void set_block_device_info(const BlockDeviceInfo& device_info); const BlockDeviceInfo& block_device_info() const { return device_info_; } bool GetBlockDeviceInfo(BlockDeviceInfo* info) const; bool UpdateBlockDeviceInfo(const BlockDeviceInfo& info); private: MetadataBuilder(); Loading @@ -238,7 +236,6 @@ class MetadataBuilder { LpMetadataHeader header_; std::vector<std::unique_ptr<Partition>> partitions_; std::vector<std::unique_ptr<PartitionGroup>> groups_; BlockDeviceInfo device_info_; }; // Read BlockDeviceInfo for a given block device. This always returns false Loading