Loading fs_mgr/liblp/images.cpp +58 −36 Original line number Diff line number Diff line Loading @@ -57,10 +57,9 @@ std::unique_ptr<LpMetadata> ReadFromImageFile(const char* file) { bool WriteToImageFile(int fd, const LpMetadata& input) { std::string geometry = SerializeGeometry(input.geometry); std::string padding(LP_METADATA_GEOMETRY_SIZE - geometry.size(), '\0'); std::string metadata = SerializeMetadata(input); std::string everything = geometry + padding + metadata; std::string everything = geometry + metadata; if (!android::base::WriteFully(fd, everything.data(), everything.size())) { PERROR << __PRETTY_FUNCTION__ << "write " << everything.size() << " bytes failed"; Loading @@ -83,26 +82,29 @@ bool WriteToImageFile(const char* file, const LpMetadata& input) { // to do this when the data pointers are all in one place. class SparseBuilder { public: explicit SparseBuilder(const LpMetadata& metadata); SparseBuilder(const LpMetadata& metadata, uint32_t block_size); bool Build(); bool Export(const char* file); bool IsValid() const { return file_ != nullptr; } private: bool AddData(const std::string& blob, uint32_t block); bool AddData(const std::string& blob, uint64_t sector); bool SectorToBlock(uint64_t sector, uint32_t* block); const LpMetadata& metadata_; const LpMetadataGeometry& geometry_; uint32_t block_size_; std::unique_ptr<sparse_file, decltype(&sparse_file_destroy)> file_; std::string geometry_blob_; std::string metadata_blob_; std::string primary_blob_; std::string backup_blob_; }; SparseBuilder::SparseBuilder(const LpMetadata& metadata) SparseBuilder::SparseBuilder(const LpMetadata& metadata, uint32_t block_size) : metadata_(metadata), geometry_(metadata.geometry), file_(sparse_file_new(LP_SECTOR_SIZE, geometry_.block_device_size), sparse_file_destroy) {} block_size_(block_size), file_(sparse_file_new(block_size_, geometry_.block_device_size), sparse_file_destroy) {} bool SparseBuilder::Export(const char* file) { android::base::unique_fd fd(open(file, O_CREAT | O_RDWR | O_TRUNC, 0644)); Loading @@ -119,7 +121,11 @@ bool SparseBuilder::Export(const char* file) { return true; } bool SparseBuilder::AddData(const std::string& blob, uint32_t block) { bool SparseBuilder::AddData(const std::string& blob, uint64_t sector) { uint32_t block; if (!SectorToBlock(sector, &block)) { return false; } void* data = const_cast<char*>(blob.data()); int ret = sparse_file_add_data(file_.get(), data, blob.size(), block); if (ret != 0) { Loading @@ -129,22 +135,37 @@ bool SparseBuilder::AddData(const std::string& blob, uint32_t block) { return true; } bool SparseBuilder::Build() { geometry_blob_ = SerializeGeometry(geometry_); geometry_blob_.resize(LP_METADATA_GEOMETRY_SIZE); if (!AddData(geometry_blob_, 0)) { bool SparseBuilder::SectorToBlock(uint64_t sector, uint32_t* block) { // The caller must ensure that the metadata has an alignment that is a // multiple of the block size. liblp will take care of the rest, ensuring // that all partitions are on an aligned boundary. Therefore all writes // should be block-aligned, and if they are not, the table was misconfigured. // Note that the default alignment is 1MiB, which is a multiple of the // default block size (4096). if ((sector * LP_SECTOR_SIZE) % block_size_ != 0) { LERROR << "sector " << sector << " is not aligned to block size " << block_size_; return false; } *block = (sector * LP_SECTOR_SIZE) / block_size_; return true; } // Metadata immediately follows geometry, and we write the same metadata // to all slots. uint32_t metadata_block = LP_METADATA_GEOMETRY_SIZE / LP_SECTOR_SIZE; metadata_blob_ = SerializeMetadata(metadata_); bool SparseBuilder::Build() { std::string geometry_blob = SerializeGeometry(geometry_); 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++) { if (!AddData(metadata_blob_, metadata_block)) { return false; all_metadata += metadata_blob; } metadata_block += geometry_.metadata_max_size / LP_SECTOR_SIZE; // 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)) { return false; } // The backup area contains all metadata slots, and then geometry. Similar Loading @@ -152,31 +173,32 @@ bool SparseBuilder::Build() { int64_t backup_offset = GetBackupMetadataOffset(geometry_, 0); uint64_t backups_start = geometry_.block_device_size + backup_offset; uint64_t backup_sector = backups_start / LP_SECTOR_SIZE; for (size_t i = 0; i < geometry_.metadata_slot_count; i++) { if (!AddData(metadata_blob_, backup_sector)) { backup_blob_ = all_metadata + geometry_blob; if (!AddData(backup_blob_, backup_sector)) { return false; } backup_sector += geometry_.metadata_max_size / LP_SECTOR_SIZE; return true; } if (!AddData(geometry_blob_, backup_sector)) { bool WriteToSparseFile(const char* file, const LpMetadata& metadata, uint32_t block_size) { if (block_size % LP_SECTOR_SIZE != 0) { LERROR << "Block size must be a multiple of the sector size, " << LP_SECTOR_SIZE; return false; } return true; if (metadata.geometry.block_device_size % block_size != 0) { LERROR << "Device size must be a multiple of the block size, " << block_size; return false; } bool WriteToSparseFile(const char* file, const LpMetadata& metadata) { uint64_t num_blocks = AlignTo(metadata.geometry.block_device_size, LP_SECTOR_SIZE) / LP_SECTOR_SIZE; uint64_t num_blocks = metadata.geometry.block_device_size % block_size; if (num_blocks >= UINT_MAX) { // libsparse counts blocks in unsigned 32-bit integers, but our block // size is rather low (512 bytes), since we operate in sectors. // Therefore the maximum block device size we can represent with a // sparse file is 2TB for now. // libsparse counts blocks in unsigned 32-bit integers, so we check to // make sure we're not going to overflow. LERROR << "Block device is too large to encode with libsparse."; return false; } SparseBuilder builder(metadata); SparseBuilder builder(metadata, block_size); if (!builder.IsValid()) { LERROR << "Could not allocate sparse file of size " << metadata.geometry.block_device_size; return false; Loading fs_mgr/liblp/include/liblp/liblp.h +1 −1 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ std::unique_ptr<LpMetadata> ReadMetadata(const char* block_device, uint32_t slot // Read/Write logical partition metadata to an image file, for diagnostics or // flashing. bool WriteToSparseFile(const char* file, const LpMetadata& metadata); bool WriteToSparseFile(const char* file, const LpMetadata& metadata, uint32_t block_size); bool WriteToImageFile(const char* file, const LpMetadata& metadata); std::unique_ptr<LpMetadata> ReadFromImageFile(const char* file); Loading fs_mgr/liblp/writer.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,10 @@ std::string SerializeGeometry(const LpMetadataGeometry& input) { LpMetadataGeometry geometry = input; memset(geometry.checksum, 0, sizeof(geometry.checksum)); SHA256(&geometry, sizeof(geometry), geometry.checksum); return std::string(reinterpret_cast<const char*>(&geometry), sizeof(geometry)); std::string blob(reinterpret_cast<const char*>(&geometry), sizeof(geometry)); blob.resize(LP_METADATA_GEOMETRY_SIZE); return blob; } static bool CompareGeometry(const LpMetadataGeometry& g1, const LpMetadataGeometry& g2) { Loading Loading
fs_mgr/liblp/images.cpp +58 −36 Original line number Diff line number Diff line Loading @@ -57,10 +57,9 @@ std::unique_ptr<LpMetadata> ReadFromImageFile(const char* file) { bool WriteToImageFile(int fd, const LpMetadata& input) { std::string geometry = SerializeGeometry(input.geometry); std::string padding(LP_METADATA_GEOMETRY_SIZE - geometry.size(), '\0'); std::string metadata = SerializeMetadata(input); std::string everything = geometry + padding + metadata; std::string everything = geometry + metadata; if (!android::base::WriteFully(fd, everything.data(), everything.size())) { PERROR << __PRETTY_FUNCTION__ << "write " << everything.size() << " bytes failed"; Loading @@ -83,26 +82,29 @@ bool WriteToImageFile(const char* file, const LpMetadata& input) { // to do this when the data pointers are all in one place. class SparseBuilder { public: explicit SparseBuilder(const LpMetadata& metadata); SparseBuilder(const LpMetadata& metadata, uint32_t block_size); bool Build(); bool Export(const char* file); bool IsValid() const { return file_ != nullptr; } private: bool AddData(const std::string& blob, uint32_t block); bool AddData(const std::string& blob, uint64_t sector); bool SectorToBlock(uint64_t sector, uint32_t* block); const LpMetadata& metadata_; const LpMetadataGeometry& geometry_; uint32_t block_size_; std::unique_ptr<sparse_file, decltype(&sparse_file_destroy)> file_; std::string geometry_blob_; std::string metadata_blob_; std::string primary_blob_; std::string backup_blob_; }; SparseBuilder::SparseBuilder(const LpMetadata& metadata) SparseBuilder::SparseBuilder(const LpMetadata& metadata, uint32_t block_size) : metadata_(metadata), geometry_(metadata.geometry), file_(sparse_file_new(LP_SECTOR_SIZE, geometry_.block_device_size), sparse_file_destroy) {} block_size_(block_size), file_(sparse_file_new(block_size_, geometry_.block_device_size), sparse_file_destroy) {} bool SparseBuilder::Export(const char* file) { android::base::unique_fd fd(open(file, O_CREAT | O_RDWR | O_TRUNC, 0644)); Loading @@ -119,7 +121,11 @@ bool SparseBuilder::Export(const char* file) { return true; } bool SparseBuilder::AddData(const std::string& blob, uint32_t block) { bool SparseBuilder::AddData(const std::string& blob, uint64_t sector) { uint32_t block; if (!SectorToBlock(sector, &block)) { return false; } void* data = const_cast<char*>(blob.data()); int ret = sparse_file_add_data(file_.get(), data, blob.size(), block); if (ret != 0) { Loading @@ -129,22 +135,37 @@ bool SparseBuilder::AddData(const std::string& blob, uint32_t block) { return true; } bool SparseBuilder::Build() { geometry_blob_ = SerializeGeometry(geometry_); geometry_blob_.resize(LP_METADATA_GEOMETRY_SIZE); if (!AddData(geometry_blob_, 0)) { bool SparseBuilder::SectorToBlock(uint64_t sector, uint32_t* block) { // The caller must ensure that the metadata has an alignment that is a // multiple of the block size. liblp will take care of the rest, ensuring // that all partitions are on an aligned boundary. Therefore all writes // should be block-aligned, and if they are not, the table was misconfigured. // Note that the default alignment is 1MiB, which is a multiple of the // default block size (4096). if ((sector * LP_SECTOR_SIZE) % block_size_ != 0) { LERROR << "sector " << sector << " is not aligned to block size " << block_size_; return false; } *block = (sector * LP_SECTOR_SIZE) / block_size_; return true; } // Metadata immediately follows geometry, and we write the same metadata // to all slots. uint32_t metadata_block = LP_METADATA_GEOMETRY_SIZE / LP_SECTOR_SIZE; metadata_blob_ = SerializeMetadata(metadata_); bool SparseBuilder::Build() { std::string geometry_blob = SerializeGeometry(geometry_); 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++) { if (!AddData(metadata_blob_, metadata_block)) { return false; all_metadata += metadata_blob; } metadata_block += geometry_.metadata_max_size / LP_SECTOR_SIZE; // 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)) { return false; } // The backup area contains all metadata slots, and then geometry. Similar Loading @@ -152,31 +173,32 @@ bool SparseBuilder::Build() { int64_t backup_offset = GetBackupMetadataOffset(geometry_, 0); uint64_t backups_start = geometry_.block_device_size + backup_offset; uint64_t backup_sector = backups_start / LP_SECTOR_SIZE; for (size_t i = 0; i < geometry_.metadata_slot_count; i++) { if (!AddData(metadata_blob_, backup_sector)) { backup_blob_ = all_metadata + geometry_blob; if (!AddData(backup_blob_, backup_sector)) { return false; } backup_sector += geometry_.metadata_max_size / LP_SECTOR_SIZE; return true; } if (!AddData(geometry_blob_, backup_sector)) { bool WriteToSparseFile(const char* file, const LpMetadata& metadata, uint32_t block_size) { if (block_size % LP_SECTOR_SIZE != 0) { LERROR << "Block size must be a multiple of the sector size, " << LP_SECTOR_SIZE; return false; } return true; if (metadata.geometry.block_device_size % block_size != 0) { LERROR << "Device size must be a multiple of the block size, " << block_size; return false; } bool WriteToSparseFile(const char* file, const LpMetadata& metadata) { uint64_t num_blocks = AlignTo(metadata.geometry.block_device_size, LP_SECTOR_SIZE) / LP_SECTOR_SIZE; uint64_t num_blocks = metadata.geometry.block_device_size % block_size; if (num_blocks >= UINT_MAX) { // libsparse counts blocks in unsigned 32-bit integers, but our block // size is rather low (512 bytes), since we operate in sectors. // Therefore the maximum block device size we can represent with a // sparse file is 2TB for now. // libsparse counts blocks in unsigned 32-bit integers, so we check to // make sure we're not going to overflow. LERROR << "Block device is too large to encode with libsparse."; return false; } SparseBuilder builder(metadata); SparseBuilder builder(metadata, block_size); if (!builder.IsValid()) { LERROR << "Could not allocate sparse file of size " << metadata.geometry.block_device_size; return false; Loading
fs_mgr/liblp/include/liblp/liblp.h +1 −1 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ std::unique_ptr<LpMetadata> ReadMetadata(const char* block_device, uint32_t slot // Read/Write logical partition metadata to an image file, for diagnostics or // flashing. bool WriteToSparseFile(const char* file, const LpMetadata& metadata); bool WriteToSparseFile(const char* file, const LpMetadata& metadata, uint32_t block_size); bool WriteToImageFile(const char* file, const LpMetadata& metadata); std::unique_ptr<LpMetadata> ReadFromImageFile(const char* file); Loading
fs_mgr/liblp/writer.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,10 @@ std::string SerializeGeometry(const LpMetadataGeometry& input) { LpMetadataGeometry geometry = input; memset(geometry.checksum, 0, sizeof(geometry.checksum)); SHA256(&geometry, sizeof(geometry), geometry.checksum); return std::string(reinterpret_cast<const char*>(&geometry), sizeof(geometry)); std::string blob(reinterpret_cast<const char*>(&geometry), sizeof(geometry)); blob.resize(LP_METADATA_GEOMETRY_SIZE); return blob; } static bool CompareGeometry(const LpMetadataGeometry& g1, const LpMetadataGeometry& g2) { Loading