Loading fs_mgr/fs_mgr_dm_linear.cpp +37 −11 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include <sstream> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> Loading @@ -50,8 +51,21 @@ using DmTarget = android::dm::DmTarget; using DmTargetZero = android::dm::DmTargetZero; using DmTargetLinear = android::dm::DmTargetLinear; static bool CreateDmTable(const std::string& block_device, const LpMetadata& metadata, const LpMetadataPartition& partition, DmTable* table) { bool GetPhysicalPartitionDevicePath(const LpMetadataBlockDevice& block_device, std::string* result) { // Note: device-mapper will not accept symlinks, so we must use realpath // here. std::string name = GetBlockDevicePartitionName(block_device); std::string path = "/dev/block/by-name/" + name; if (!android::base::Realpath(path, result)) { PERROR << "realpath: " << path; return false; } return true; } static bool CreateDmTable(const LpMetadata& metadata, const LpMetadataPartition& partition, DmTable* table) { uint64_t sector = 0; for (size_t i = 0; i < partition.num_extents; i++) { const auto& extent = metadata.extents[partition.first_extent_index + i]; Loading @@ -60,10 +74,22 @@ static bool CreateDmTable(const std::string& block_device, const LpMetadata& met case LP_TARGET_TYPE_ZERO: target = std::make_unique<DmTargetZero>(sector, extent.num_sectors); break; case LP_TARGET_TYPE_LINEAR: target = std::make_unique<DmTargetLinear>(sector, extent.num_sectors, block_device, case LP_TARGET_TYPE_LINEAR: { auto block_device = GetMetadataSuperBlockDevice(metadata); if (!block_device) { LOG(ERROR) << "Could not identify the super block device"; return false; } std::string path; if (!GetPhysicalPartitionDevicePath(*block_device, &path)) { LOG(ERROR) << "Unable to complete device-mapper table, unknown block device"; return false; } target = std::make_unique<DmTargetLinear>(sector, extent.num_sectors, path, extent.target_data); break; } default: LOG(ERROR) << "Unknown target type in metadata: " << extent.target_type; return false; Loading @@ -79,13 +105,13 @@ static bool CreateDmTable(const std::string& block_device, const LpMetadata& met return true; } static bool CreateLogicalPartition(const std::string& block_device, const LpMetadata& metadata, const LpMetadataPartition& partition, bool force_writable, const std::chrono::milliseconds& timeout_ms, std::string* path) { static bool CreateLogicalPartition(const LpMetadata& metadata, const LpMetadataPartition& partition, bool force_writable, const std::chrono::milliseconds& timeout_ms, std::string* path) { DeviceMapper& dm = DeviceMapper::Instance(); DmTable table; if (!CreateDmTable(block_device, metadata, partition, &table)) { if (!CreateDmTable(metadata, partition, &table)) { return false; } if (force_writable) { Loading Loading @@ -122,7 +148,7 @@ bool CreateLogicalPartitions(const std::string& block_device) { continue; } std::string path; if (!CreateLogicalPartition(block_device, *metadata.get(), partition, false, {}, &path)) { if (!CreateLogicalPartition(*metadata.get(), partition, false, {}, &path)) { LERROR << "Could not create logical partition: " << GetPartitionName(partition); return false; } Loading @@ -140,8 +166,8 @@ bool CreateLogicalPartition(const std::string& block_device, uint32_t metadata_s } for (const auto& partition : metadata->partitions) { if (GetPartitionName(partition) == partition_name) { return CreateLogicalPartition(block_device, *metadata.get(), partition, force_writable, timeout_ms, path); return CreateLogicalPartition(*metadata.get(), partition, force_writable, timeout_ms, path); } } LERROR << "Could not find any partition with name: " << partition_name; Loading fs_mgr/liblp/builder.cpp +31 −19 Original line number Diff line number Diff line Loading @@ -186,6 +186,7 @@ MetadataBuilder::MetadataBuilder() { header_.partitions.entry_size = sizeof(LpMetadataPartition); header_.extents.entry_size = sizeof(LpMetadataExtent); header_.groups.entry_size = sizeof(LpMetadataPartitionGroup); header_.block_devices.entry_size = sizeof(LpMetadataBlockDevice); } bool MetadataBuilder::Init(const LpMetadata& metadata) { Loading @@ -198,6 +199,10 @@ bool MetadataBuilder::Init(const LpMetadata& metadata) { } } for (const auto& block_device : metadata.block_devices) { block_devices_.push_back(block_device); } for (const auto& partition : metadata.partitions) { std::string group_name = GetPartitionGroupName(metadata.groups[partition.group_index]); Partition* builder = Loading Loading @@ -259,9 +264,7 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata // We reserve a geometry block (4KB) plus space for each copy of the // maximum size of a metadata blob. Then, we double that space since // 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 = LP_PARTITION_RESERVED_BYTES + reserved * 2; uint64_t total_reserved = GetTotalMetadataSize(metadata_max_size, metadata_slot_count); if (device_info.size < total_reserved) { LERROR << "Attempting to create metadata on a block device that is too small."; return false; Loading @@ -285,12 +288,16 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata return false; } geometry_.first_logical_sector = first_sector; block_devices_.push_back(LpMetadataBlockDevice{ first_sector, device_info.alignment, device_info.alignment_offset, device_info.size, "super", }); 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_.logical_block_size = device_info.logical_block_size; if (!AddGroup("default", 0)) { Loading Loading @@ -408,9 +415,10 @@ auto MetadataBuilder::GetFreeRegions() const -> std::vector<Interval> { } // Add 0-length intervals for the first and last sectors. This will cause // ExtentsToFreeList() to treat the space in between as available. uint64_t last_sector = geometry_.block_device_size / LP_SECTOR_SIZE; extents.emplace_back(geometry_.first_logical_sector, geometry_.first_logical_sector); // ExtentToFreeList() to treat the space in between as available. uint64_t first_sector = super_device().first_logical_sector; uint64_t last_sector = super_device().size / LP_SECTOR_SIZE; extents.emplace_back(first_sector, first_sector); extents.emplace_back(last_sector, last_sector); std::sort(extents.begin(), extents.end()); Loading Loading @@ -547,14 +555,18 @@ std::unique_ptr<LpMetadata> MetadataBuilder::Export() { metadata->partitions.push_back(part); } metadata->block_devices = block_devices_; metadata->header.partitions.num_entries = static_cast<uint32_t>(metadata->partitions.size()); metadata->header.extents.num_entries = static_cast<uint32_t>(metadata->extents.size()); metadata->header.groups.num_entries = static_cast<uint32_t>(metadata->groups.size()); metadata->header.block_devices.num_entries = static_cast<uint32_t>(metadata->block_devices.size()); return metadata; } uint64_t MetadataBuilder::AllocatableSpace() const { return geometry_.block_device_size - (geometry_.first_logical_sector * LP_SECTOR_SIZE); return super_device().size - (super_device().first_logical_sector * LP_SECTOR_SIZE); } uint64_t MetadataBuilder::UsedSpace() const { Loading @@ -569,22 +581,22 @@ uint64_t MetadataBuilder::AlignSector(uint64_t sector) const { // 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, geometry_.alignment, geometry_.alignment_offset); uint64_t aligned = AlignTo(lba, super_device().alignment, super_device().alignment_offset); return AlignTo(aligned, LP_SECTOR_SIZE) / LP_SECTOR_SIZE; } bool MetadataBuilder::GetBlockDeviceInfo(BlockDeviceInfo* info) const { info->size = geometry_.block_device_size; info->alignment = geometry_.alignment; info->alignment_offset = geometry_.alignment_offset; info->size = super_device().size; info->alignment = super_device().alignment; info->alignment_offset = super_device().alignment_offset; info->logical_block_size = geometry_.logical_block_size; return true; } bool MetadataBuilder::UpdateBlockDeviceInfo(const BlockDeviceInfo& device_info) { if (device_info.size != geometry_.block_device_size) { if (device_info.size != super_device().size) { LERROR << "Device size does not match (got " << device_info.size << ", expected " << geometry_.block_device_size << ")"; << super_device().size << ")"; return false; } if (device_info.logical_block_size != geometry_.logical_block_size) { Loading @@ -596,10 +608,10 @@ bool MetadataBuilder::UpdateBlockDeviceInfo(const BlockDeviceInfo& device_info) // 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) { geometry_.alignment = device_info.alignment; super_device().alignment = device_info.alignment; } if (device_info.alignment_offset) { geometry_.alignment_offset = device_info.alignment_offset; super_device().alignment_offset = device_info.alignment_offset; } return true; } Loading fs_mgr/liblp/builder_test.cpp +17 −6 Original line number Diff line number Diff line Loading @@ -132,7 +132,9 @@ TEST(liblp, InternalAlignment) { ASSERT_NE(builder, nullptr); unique_ptr<LpMetadata> exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->geometry.first_logical_sector, 1536); auto super_device = GetMetadataSuperBlockDevice(*exported.get()); ASSERT_NE(super_device, nullptr); EXPECT_EQ(super_device->first_logical_sector, 1536); // Test a large alignment offset thrown in. device_info.alignment_offset = 753664; Loading @@ -140,7 +142,9 @@ TEST(liblp, InternalAlignment) { ASSERT_NE(builder, nullptr); exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->geometry.first_logical_sector, 1472); super_device = GetMetadataSuperBlockDevice(*exported.get()); ASSERT_NE(super_device, nullptr); EXPECT_EQ(super_device->first_logical_sector, 1472); // Alignment offset without alignment doesn't mean anything. device_info.alignment = 0; Loading @@ -154,7 +158,9 @@ TEST(liblp, InternalAlignment) { ASSERT_NE(builder, nullptr); exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->geometry.first_logical_sector, 174); super_device = GetMetadataSuperBlockDevice(*exported.get()); ASSERT_NE(super_device, nullptr); EXPECT_EQ(super_device->first_logical_sector, 174); // Test a small alignment with no alignment offset. device_info.alignment = 11 * 1024; Loading @@ -162,7 +168,9 @@ TEST(liblp, InternalAlignment) { ASSERT_NE(builder, nullptr); exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->geometry.first_logical_sector, 160); super_device = GetMetadataSuperBlockDevice(*exported.get()); ASSERT_NE(super_device, nullptr); EXPECT_EQ(super_device->first_logical_sector, 160); } TEST(liblp, InternalPartitionAlignment) { Loading Loading @@ -292,6 +300,9 @@ TEST(liblp, BuilderExport) { unique_ptr<LpMetadata> exported = builder->Export(); EXPECT_NE(exported, nullptr); auto super_device = GetMetadataSuperBlockDevice(*exported.get()); ASSERT_NE(super_device, nullptr); // Verify geometry. Some details of this may change if we change the // metadata structures. So in addition to checking the exact values, we // also check that they are internally consistent after. Loading @@ -300,11 +311,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, 32); EXPECT_EQ(super_device->first_logical_sector, 32); static const size_t kMetadataSpace = ((kMetadataSize * kMetadataSlots) + LP_METADATA_GEOMETRY_SIZE) * 2; EXPECT_GE(geometry.first_logical_sector * LP_SECTOR_SIZE, kMetadataSpace); EXPECT_GE(super_device->first_logical_sector * LP_SECTOR_SIZE, kMetadataSpace); // Verify header. const LpMetadataHeader& header = exported->header; Loading fs_mgr/liblp/images.cpp +8 −11 Original line number Diff line number Diff line Loading @@ -99,11 +99,12 @@ SparseBuilder::SparseBuilder(const LpMetadata& metadata, uint32_t block_size, block_size_(block_size), file_(nullptr, sparse_file_destroy), images_(images) { uint64_t total_size = GetTotalSuperPartitionSize(metadata); if (block_size % LP_SECTOR_SIZE != 0) { LERROR << "Block size must be a multiple of the sector size, " << LP_SECTOR_SIZE; return; } if (metadata.geometry.block_device_size % block_size != 0) { if (total_size % block_size != 0) { LERROR << "Device size must be a multiple of the block size, " << block_size; return; } Loading @@ -120,7 +121,7 @@ SparseBuilder::SparseBuilder(const LpMetadata& metadata, uint32_t block_size, return; } uint64_t num_blocks = metadata.geometry.block_device_size % block_size; uint64_t num_blocks = total_size % block_size; if (num_blocks >= UINT_MAX) { // libsparse counts blocks in unsigned 32-bit integers, so we check to // make sure we're not going to overflow. Loading @@ -128,7 +129,10 @@ SparseBuilder::SparseBuilder(const LpMetadata& metadata, uint32_t block_size, return; } file_.reset(sparse_file_new(block_size_, geometry_.block_device_size)); file_.reset(sparse_file_new(block_size_, total_size)); if (!file_) { LERROR << "Could not allocate sparse file of size " << total_size; } } bool SparseBuilder::Export(const char* file) { Loading Loading @@ -333,14 +337,7 @@ int SparseBuilder::OpenImageFile(const std::string& file) { bool WriteToSparseFile(const char* file, const LpMetadata& metadata, uint32_t block_size, const std::map<std::string, std::string>& images) { SparseBuilder builder(metadata, block_size, images); if (!builder.IsValid()) { LERROR << "Could not allocate sparse file of size " << metadata.geometry.block_device_size; return false; } if (!builder.Build()) { return false; } return builder.Export(file); return builder.IsValid() && builder.Build() && builder.Export(file); } } // namespace fs_mgr Loading fs_mgr/liblp/include/liblp/builder.h +4 −0 Original line number Diff line number Diff line Loading @@ -254,10 +254,14 @@ class MetadataBuilder { void ExtentsToFreeList(const std::vector<Interval>& extents, std::vector<Interval>* free_regions) const; const LpMetadataBlockDevice& super_device() const { return block_devices_[0]; } LpMetadataBlockDevice& super_device() { return block_devices_[0]; } LpMetadataGeometry geometry_; LpMetadataHeader header_; std::vector<std::unique_ptr<Partition>> partitions_; std::vector<std::unique_ptr<PartitionGroup>> groups_; std::vector<LpMetadataBlockDevice> block_devices_; }; // Read BlockDeviceInfo for a given block device. This always returns false Loading Loading
fs_mgr/fs_mgr_dm_linear.cpp +37 −11 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include <sstream> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> Loading @@ -50,8 +51,21 @@ using DmTarget = android::dm::DmTarget; using DmTargetZero = android::dm::DmTargetZero; using DmTargetLinear = android::dm::DmTargetLinear; static bool CreateDmTable(const std::string& block_device, const LpMetadata& metadata, const LpMetadataPartition& partition, DmTable* table) { bool GetPhysicalPartitionDevicePath(const LpMetadataBlockDevice& block_device, std::string* result) { // Note: device-mapper will not accept symlinks, so we must use realpath // here. std::string name = GetBlockDevicePartitionName(block_device); std::string path = "/dev/block/by-name/" + name; if (!android::base::Realpath(path, result)) { PERROR << "realpath: " << path; return false; } return true; } static bool CreateDmTable(const LpMetadata& metadata, const LpMetadataPartition& partition, DmTable* table) { uint64_t sector = 0; for (size_t i = 0; i < partition.num_extents; i++) { const auto& extent = metadata.extents[partition.first_extent_index + i]; Loading @@ -60,10 +74,22 @@ static bool CreateDmTable(const std::string& block_device, const LpMetadata& met case LP_TARGET_TYPE_ZERO: target = std::make_unique<DmTargetZero>(sector, extent.num_sectors); break; case LP_TARGET_TYPE_LINEAR: target = std::make_unique<DmTargetLinear>(sector, extent.num_sectors, block_device, case LP_TARGET_TYPE_LINEAR: { auto block_device = GetMetadataSuperBlockDevice(metadata); if (!block_device) { LOG(ERROR) << "Could not identify the super block device"; return false; } std::string path; if (!GetPhysicalPartitionDevicePath(*block_device, &path)) { LOG(ERROR) << "Unable to complete device-mapper table, unknown block device"; return false; } target = std::make_unique<DmTargetLinear>(sector, extent.num_sectors, path, extent.target_data); break; } default: LOG(ERROR) << "Unknown target type in metadata: " << extent.target_type; return false; Loading @@ -79,13 +105,13 @@ static bool CreateDmTable(const std::string& block_device, const LpMetadata& met return true; } static bool CreateLogicalPartition(const std::string& block_device, const LpMetadata& metadata, const LpMetadataPartition& partition, bool force_writable, const std::chrono::milliseconds& timeout_ms, std::string* path) { static bool CreateLogicalPartition(const LpMetadata& metadata, const LpMetadataPartition& partition, bool force_writable, const std::chrono::milliseconds& timeout_ms, std::string* path) { DeviceMapper& dm = DeviceMapper::Instance(); DmTable table; if (!CreateDmTable(block_device, metadata, partition, &table)) { if (!CreateDmTable(metadata, partition, &table)) { return false; } if (force_writable) { Loading Loading @@ -122,7 +148,7 @@ bool CreateLogicalPartitions(const std::string& block_device) { continue; } std::string path; if (!CreateLogicalPartition(block_device, *metadata.get(), partition, false, {}, &path)) { if (!CreateLogicalPartition(*metadata.get(), partition, false, {}, &path)) { LERROR << "Could not create logical partition: " << GetPartitionName(partition); return false; } Loading @@ -140,8 +166,8 @@ bool CreateLogicalPartition(const std::string& block_device, uint32_t metadata_s } for (const auto& partition : metadata->partitions) { if (GetPartitionName(partition) == partition_name) { return CreateLogicalPartition(block_device, *metadata.get(), partition, force_writable, timeout_ms, path); return CreateLogicalPartition(*metadata.get(), partition, force_writable, timeout_ms, path); } } LERROR << "Could not find any partition with name: " << partition_name; Loading
fs_mgr/liblp/builder.cpp +31 −19 Original line number Diff line number Diff line Loading @@ -186,6 +186,7 @@ MetadataBuilder::MetadataBuilder() { header_.partitions.entry_size = sizeof(LpMetadataPartition); header_.extents.entry_size = sizeof(LpMetadataExtent); header_.groups.entry_size = sizeof(LpMetadataPartitionGroup); header_.block_devices.entry_size = sizeof(LpMetadataBlockDevice); } bool MetadataBuilder::Init(const LpMetadata& metadata) { Loading @@ -198,6 +199,10 @@ bool MetadataBuilder::Init(const LpMetadata& metadata) { } } for (const auto& block_device : metadata.block_devices) { block_devices_.push_back(block_device); } for (const auto& partition : metadata.partitions) { std::string group_name = GetPartitionGroupName(metadata.groups[partition.group_index]); Partition* builder = Loading Loading @@ -259,9 +264,7 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata // We reserve a geometry block (4KB) plus space for each copy of the // maximum size of a metadata blob. Then, we double that space since // 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 = LP_PARTITION_RESERVED_BYTES + reserved * 2; uint64_t total_reserved = GetTotalMetadataSize(metadata_max_size, metadata_slot_count); if (device_info.size < total_reserved) { LERROR << "Attempting to create metadata on a block device that is too small."; return false; Loading @@ -285,12 +288,16 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata return false; } geometry_.first_logical_sector = first_sector; block_devices_.push_back(LpMetadataBlockDevice{ first_sector, device_info.alignment, device_info.alignment_offset, device_info.size, "super", }); 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_.logical_block_size = device_info.logical_block_size; if (!AddGroup("default", 0)) { Loading Loading @@ -408,9 +415,10 @@ auto MetadataBuilder::GetFreeRegions() const -> std::vector<Interval> { } // Add 0-length intervals for the first and last sectors. This will cause // ExtentsToFreeList() to treat the space in between as available. uint64_t last_sector = geometry_.block_device_size / LP_SECTOR_SIZE; extents.emplace_back(geometry_.first_logical_sector, geometry_.first_logical_sector); // ExtentToFreeList() to treat the space in between as available. uint64_t first_sector = super_device().first_logical_sector; uint64_t last_sector = super_device().size / LP_SECTOR_SIZE; extents.emplace_back(first_sector, first_sector); extents.emplace_back(last_sector, last_sector); std::sort(extents.begin(), extents.end()); Loading Loading @@ -547,14 +555,18 @@ std::unique_ptr<LpMetadata> MetadataBuilder::Export() { metadata->partitions.push_back(part); } metadata->block_devices = block_devices_; metadata->header.partitions.num_entries = static_cast<uint32_t>(metadata->partitions.size()); metadata->header.extents.num_entries = static_cast<uint32_t>(metadata->extents.size()); metadata->header.groups.num_entries = static_cast<uint32_t>(metadata->groups.size()); metadata->header.block_devices.num_entries = static_cast<uint32_t>(metadata->block_devices.size()); return metadata; } uint64_t MetadataBuilder::AllocatableSpace() const { return geometry_.block_device_size - (geometry_.first_logical_sector * LP_SECTOR_SIZE); return super_device().size - (super_device().first_logical_sector * LP_SECTOR_SIZE); } uint64_t MetadataBuilder::UsedSpace() const { Loading @@ -569,22 +581,22 @@ uint64_t MetadataBuilder::AlignSector(uint64_t sector) const { // 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, geometry_.alignment, geometry_.alignment_offset); uint64_t aligned = AlignTo(lba, super_device().alignment, super_device().alignment_offset); return AlignTo(aligned, LP_SECTOR_SIZE) / LP_SECTOR_SIZE; } bool MetadataBuilder::GetBlockDeviceInfo(BlockDeviceInfo* info) const { info->size = geometry_.block_device_size; info->alignment = geometry_.alignment; info->alignment_offset = geometry_.alignment_offset; info->size = super_device().size; info->alignment = super_device().alignment; info->alignment_offset = super_device().alignment_offset; info->logical_block_size = geometry_.logical_block_size; return true; } bool MetadataBuilder::UpdateBlockDeviceInfo(const BlockDeviceInfo& device_info) { if (device_info.size != geometry_.block_device_size) { if (device_info.size != super_device().size) { LERROR << "Device size does not match (got " << device_info.size << ", expected " << geometry_.block_device_size << ")"; << super_device().size << ")"; return false; } if (device_info.logical_block_size != geometry_.logical_block_size) { Loading @@ -596,10 +608,10 @@ bool MetadataBuilder::UpdateBlockDeviceInfo(const BlockDeviceInfo& device_info) // 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) { geometry_.alignment = device_info.alignment; super_device().alignment = device_info.alignment; } if (device_info.alignment_offset) { geometry_.alignment_offset = device_info.alignment_offset; super_device().alignment_offset = device_info.alignment_offset; } return true; } Loading
fs_mgr/liblp/builder_test.cpp +17 −6 Original line number Diff line number Diff line Loading @@ -132,7 +132,9 @@ TEST(liblp, InternalAlignment) { ASSERT_NE(builder, nullptr); unique_ptr<LpMetadata> exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->geometry.first_logical_sector, 1536); auto super_device = GetMetadataSuperBlockDevice(*exported.get()); ASSERT_NE(super_device, nullptr); EXPECT_EQ(super_device->first_logical_sector, 1536); // Test a large alignment offset thrown in. device_info.alignment_offset = 753664; Loading @@ -140,7 +142,9 @@ TEST(liblp, InternalAlignment) { ASSERT_NE(builder, nullptr); exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->geometry.first_logical_sector, 1472); super_device = GetMetadataSuperBlockDevice(*exported.get()); ASSERT_NE(super_device, nullptr); EXPECT_EQ(super_device->first_logical_sector, 1472); // Alignment offset without alignment doesn't mean anything. device_info.alignment = 0; Loading @@ -154,7 +158,9 @@ TEST(liblp, InternalAlignment) { ASSERT_NE(builder, nullptr); exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->geometry.first_logical_sector, 174); super_device = GetMetadataSuperBlockDevice(*exported.get()); ASSERT_NE(super_device, nullptr); EXPECT_EQ(super_device->first_logical_sector, 174); // Test a small alignment with no alignment offset. device_info.alignment = 11 * 1024; Loading @@ -162,7 +168,9 @@ TEST(liblp, InternalAlignment) { ASSERT_NE(builder, nullptr); exported = builder->Export(); ASSERT_NE(exported, nullptr); EXPECT_EQ(exported->geometry.first_logical_sector, 160); super_device = GetMetadataSuperBlockDevice(*exported.get()); ASSERT_NE(super_device, nullptr); EXPECT_EQ(super_device->first_logical_sector, 160); } TEST(liblp, InternalPartitionAlignment) { Loading Loading @@ -292,6 +300,9 @@ TEST(liblp, BuilderExport) { unique_ptr<LpMetadata> exported = builder->Export(); EXPECT_NE(exported, nullptr); auto super_device = GetMetadataSuperBlockDevice(*exported.get()); ASSERT_NE(super_device, nullptr); // Verify geometry. Some details of this may change if we change the // metadata structures. So in addition to checking the exact values, we // also check that they are internally consistent after. Loading @@ -300,11 +311,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, 32); EXPECT_EQ(super_device->first_logical_sector, 32); static const size_t kMetadataSpace = ((kMetadataSize * kMetadataSlots) + LP_METADATA_GEOMETRY_SIZE) * 2; EXPECT_GE(geometry.first_logical_sector * LP_SECTOR_SIZE, kMetadataSpace); EXPECT_GE(super_device->first_logical_sector * LP_SECTOR_SIZE, kMetadataSpace); // Verify header. const LpMetadataHeader& header = exported->header; Loading
fs_mgr/liblp/images.cpp +8 −11 Original line number Diff line number Diff line Loading @@ -99,11 +99,12 @@ SparseBuilder::SparseBuilder(const LpMetadata& metadata, uint32_t block_size, block_size_(block_size), file_(nullptr, sparse_file_destroy), images_(images) { uint64_t total_size = GetTotalSuperPartitionSize(metadata); if (block_size % LP_SECTOR_SIZE != 0) { LERROR << "Block size must be a multiple of the sector size, " << LP_SECTOR_SIZE; return; } if (metadata.geometry.block_device_size % block_size != 0) { if (total_size % block_size != 0) { LERROR << "Device size must be a multiple of the block size, " << block_size; return; } Loading @@ -120,7 +121,7 @@ SparseBuilder::SparseBuilder(const LpMetadata& metadata, uint32_t block_size, return; } uint64_t num_blocks = metadata.geometry.block_device_size % block_size; uint64_t num_blocks = total_size % block_size; if (num_blocks >= UINT_MAX) { // libsparse counts blocks in unsigned 32-bit integers, so we check to // make sure we're not going to overflow. Loading @@ -128,7 +129,10 @@ SparseBuilder::SparseBuilder(const LpMetadata& metadata, uint32_t block_size, return; } file_.reset(sparse_file_new(block_size_, geometry_.block_device_size)); file_.reset(sparse_file_new(block_size_, total_size)); if (!file_) { LERROR << "Could not allocate sparse file of size " << total_size; } } bool SparseBuilder::Export(const char* file) { Loading Loading @@ -333,14 +337,7 @@ int SparseBuilder::OpenImageFile(const std::string& file) { bool WriteToSparseFile(const char* file, const LpMetadata& metadata, uint32_t block_size, const std::map<std::string, std::string>& images) { SparseBuilder builder(metadata, block_size, images); if (!builder.IsValid()) { LERROR << "Could not allocate sparse file of size " << metadata.geometry.block_device_size; return false; } if (!builder.Build()) { return false; } return builder.Export(file); return builder.IsValid() && builder.Build() && builder.Export(file); } } // namespace fs_mgr Loading
fs_mgr/liblp/include/liblp/builder.h +4 −0 Original line number Diff line number Diff line Loading @@ -254,10 +254,14 @@ class MetadataBuilder { void ExtentsToFreeList(const std::vector<Interval>& extents, std::vector<Interval>* free_regions) const; const LpMetadataBlockDevice& super_device() const { return block_devices_[0]; } LpMetadataBlockDevice& super_device() { return block_devices_[0]; } LpMetadataGeometry geometry_; LpMetadataHeader header_; std::vector<std::unique_ptr<Partition>> partitions_; std::vector<std::unique_ptr<PartitionGroup>> groups_; std::vector<LpMetadataBlockDevice> block_devices_; }; // Read BlockDeviceInfo for a given block device. This always returns false Loading