Loading fs_mgr/fs_mgr_dm_linear.cpp +52 −84 Original line number Diff line number Diff line Loading @@ -40,102 +40,70 @@ #include <liblp/reader.h> #include "fs_mgr_priv.h" #include "fs_mgr_priv_dm_ioctl.h" namespace android { namespace fs_mgr { std::string LogicalPartitionExtent::Serialize() const { // Note: we need to include an explicit null-terminator. std::string argv = android::base::StringPrintf("%s %" PRIu64, block_device_.c_str(), first_sector_); argv.push_back(0); using DeviceMapper = android::dm::DeviceMapper; using DmTable = android::dm::DmTable; using DmTarget = android::dm::DmTarget; using DmTargetZero = android::dm::DmTargetZero; using DmTargetLinear = android::dm::DmTargetLinear; // The kernel expects each target to be aligned. size_t spec_bytes = sizeof(struct dm_target_spec) + argv.size(); size_t padding = ((spec_bytes + 7) & ~7) - spec_bytes; for (size_t i = 0; i < padding; i++) { argv.push_back(0); } struct dm_target_spec spec; spec.sector_start = logical_sector_; spec.length = num_sectors_; spec.status = 0; strcpy(spec.target_type, "linear"); spec.next = sizeof(struct dm_target_spec) + argv.size(); return std::string((char*)&spec, sizeof(spec)) + argv; } static bool LoadDmTable(int dm_fd, const LogicalPartition& partition) { // Combine all dm_target_spec buffers together. std::string target_string; static bool CreateDmDeviceForPartition(DeviceMapper& dm, const LogicalPartition& partition) { DmTable table; for (const auto& extent : partition.extents) { target_string += extent.Serialize(); table.AddTarget(std::make_unique<DmTargetLinear>(extent)); } // Allocate the ioctl buffer. size_t buffer_size = sizeof(struct dm_ioctl) + target_string.size(); std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(buffer_size); // Initialize the ioctl buffer header, then copy our target specs in. struct dm_ioctl* io = reinterpret_cast<struct dm_ioctl*>(buffer.get()); fs_mgr_dm_ioctl_init(io, buffer_size, partition.name); io->target_count = partition.extents.size(); if (partition.attributes & kPartitionReadonly) { io->flags |= DM_READONLY_FLAG; } memcpy(io + 1, target_string.c_str(), target_string.size()); if (ioctl(dm_fd, DM_TABLE_LOAD, io)) { PERROR << "Failed ioctl() on DM_TABLE_LOAD, partition " << partition.name; if (!dm.CreateDevice(partition.name, table)) { return false; } LINFO << "Created device-mapper device: " << partition.name; return true; } static bool LoadTablesAndActivate(int dm_fd, const LogicalPartition& partition) { if (!LoadDmTable(dm_fd, partition)) { bool CreateLogicalPartitions(const LogicalPartitionTable& table) { DeviceMapper& dm = DeviceMapper::Instance(); for (const auto& partition : table.partitions) { if (!CreateDmDeviceForPartition(dm, partition)) { LOG(ERROR) << "could not create dm-linear device for partition: " << partition.name; return false; } struct dm_ioctl io; return fs_mgr_dm_resume_table(&io, partition.name, dm_fd); } static bool CreateDmDeviceForPartition(int dm_fd, const LogicalPartition& partition) { struct dm_ioctl io; if (!fs_mgr_dm_create_device(&io, partition.name, dm_fd)) { return false; } if (!LoadTablesAndActivate(dm_fd, partition)) { // Remove the device rather than leave it in an inactive state. fs_mgr_dm_destroy_device(&io, partition.name, dm_fd); return false; return true; } LINFO << "Created device-mapper device: " << partition.name; return true; std::unique_ptr<LogicalPartitionTable> LoadPartitionsFromDeviceTree() { return nullptr; } bool CreateLogicalPartitions(const LogicalPartitionTable& table) { android::base::unique_fd dm_fd(open("/dev/device-mapper", O_RDWR)); if (dm_fd < 0) { PLOG(ERROR) << "failed to open /dev/device-mapper"; static bool CreateDmTable(const std::string& block_device, 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]; std::unique_ptr<DmTarget> target; switch (extent.target_type) { 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, extent.target_data); break; default: LOG(ERROR) << "Unknown target type in metadata: " << extent.target_type; return false; } for (const auto& partition : table.partitions) { if (!CreateDmDeviceForPartition(dm_fd, partition)) { LOG(ERROR) << "could not create dm-linear device for partition: " << partition.name; if (!table->AddTarget(std::move(target))) { return false; } sector += extent.num_sectors; } return true; if (partition.attributes & LP_PARTITION_ATTR_READONLY) { table->set_readonly(true); } std::unique_ptr<LogicalPartitionTable> LoadPartitionsFromDeviceTree() { return nullptr; return true; } bool CreateLogicalPartitions(const std::string& block_device) { Loading @@ -146,21 +114,21 @@ bool CreateLogicalPartitions(const std::string& block_device) { return true; } LogicalPartitionTable table; DeviceMapper& dm = DeviceMapper::Instance(); for (const auto& partition : metadata->partitions) { LogicalPartition new_partition; new_partition.name = GetPartitionName(partition); new_partition.attributes = partition.attributes; for (size_t i = 0; i < partition.num_extents; i++) { const auto& extent = metadata->extents[partition.first_extent_index + i]; new_partition.extents.emplace_back(new_partition.num_sectors, extent.target_data, extent.num_sectors, block_device.c_str()); new_partition.num_sectors += extent.num_sectors; DmTable table; if (!CreateDmTable(block_device, *metadata.get(), partition, &table)) { return false; } table.partitions.push_back(new_partition); std::string name = GetPartitionName(partition); if (!dm.CreateDevice(name, table)) { return false; } return CreateLogicalPartitions(table); std::string path; dm.GetDmDevicePathByName(partition.name, &path); LINFO << "Created logical partition " << name << " on device " << path; } return true; } } // namespace fs_mgr Loading fs_mgr/include/fs_mgr_dm_linear.h +5 −38 Original line number Diff line number Diff line Loading @@ -26,53 +26,20 @@ #define __CORE_FS_MGR_DM_LINEAR_H #include <stdint.h> #include <memory> #include <string> #include <vector> #include <libdm/dm.h> #include <liblp/metadata_format.h> namespace android { namespace fs_mgr { static const uint32_t kPartitionReadonly = 0x1; class LogicalPartitionExtent { public: LogicalPartitionExtent() : logical_sector_(0), first_sector_(0), num_sectors_(0) {} LogicalPartitionExtent(uint64_t logical_sector, uint64_t first_sector, uint64_t num_sectors, const std::string& block_device) : logical_sector_(logical_sector), first_sector_(first_sector), num_sectors_(num_sectors), block_device_(block_device) {} // Return a string containing the dm_target_spec buffer needed to use this // extent in a device-mapper table. std::string Serialize() const; const std::string& block_device() const { return block_device_; } private: // Logical sector this extent represents in the presented block device. // This is equal to the previous extent's logical sector plus the number // of sectors in that extent. The first extent always starts at 0. uint64_t logical_sector_; // First 512-byte sector of this extent, on the source block device. uint64_t first_sector_; // Number of 512-byte sectors. uint64_t num_sectors_; // Target block device. std::string block_device_; }; struct LogicalPartition { LogicalPartition() : attributes(0), num_sectors(0) {} std::string name; uint32_t attributes; // Number of 512-byte sectors total. uint64_t num_sectors; // List of extents. std::vector<LogicalPartitionExtent> extents; std::vector<android::dm::DmTargetLinear> extents; }; struct LogicalPartitionTable { Loading fs_mgr/libdm/include/libdm/dm_target.h +1 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ class DmTargetLinear final : public DmTarget { std::string name() const override { return "linear"; } std::string GetParameterString() const override; const std::string& block_device() const { return block_device_; } private: std::string block_device_; Loading Loading
fs_mgr/fs_mgr_dm_linear.cpp +52 −84 Original line number Diff line number Diff line Loading @@ -40,102 +40,70 @@ #include <liblp/reader.h> #include "fs_mgr_priv.h" #include "fs_mgr_priv_dm_ioctl.h" namespace android { namespace fs_mgr { std::string LogicalPartitionExtent::Serialize() const { // Note: we need to include an explicit null-terminator. std::string argv = android::base::StringPrintf("%s %" PRIu64, block_device_.c_str(), first_sector_); argv.push_back(0); using DeviceMapper = android::dm::DeviceMapper; using DmTable = android::dm::DmTable; using DmTarget = android::dm::DmTarget; using DmTargetZero = android::dm::DmTargetZero; using DmTargetLinear = android::dm::DmTargetLinear; // The kernel expects each target to be aligned. size_t spec_bytes = sizeof(struct dm_target_spec) + argv.size(); size_t padding = ((spec_bytes + 7) & ~7) - spec_bytes; for (size_t i = 0; i < padding; i++) { argv.push_back(0); } struct dm_target_spec spec; spec.sector_start = logical_sector_; spec.length = num_sectors_; spec.status = 0; strcpy(spec.target_type, "linear"); spec.next = sizeof(struct dm_target_spec) + argv.size(); return std::string((char*)&spec, sizeof(spec)) + argv; } static bool LoadDmTable(int dm_fd, const LogicalPartition& partition) { // Combine all dm_target_spec buffers together. std::string target_string; static bool CreateDmDeviceForPartition(DeviceMapper& dm, const LogicalPartition& partition) { DmTable table; for (const auto& extent : partition.extents) { target_string += extent.Serialize(); table.AddTarget(std::make_unique<DmTargetLinear>(extent)); } // Allocate the ioctl buffer. size_t buffer_size = sizeof(struct dm_ioctl) + target_string.size(); std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(buffer_size); // Initialize the ioctl buffer header, then copy our target specs in. struct dm_ioctl* io = reinterpret_cast<struct dm_ioctl*>(buffer.get()); fs_mgr_dm_ioctl_init(io, buffer_size, partition.name); io->target_count = partition.extents.size(); if (partition.attributes & kPartitionReadonly) { io->flags |= DM_READONLY_FLAG; } memcpy(io + 1, target_string.c_str(), target_string.size()); if (ioctl(dm_fd, DM_TABLE_LOAD, io)) { PERROR << "Failed ioctl() on DM_TABLE_LOAD, partition " << partition.name; if (!dm.CreateDevice(partition.name, table)) { return false; } LINFO << "Created device-mapper device: " << partition.name; return true; } static bool LoadTablesAndActivate(int dm_fd, const LogicalPartition& partition) { if (!LoadDmTable(dm_fd, partition)) { bool CreateLogicalPartitions(const LogicalPartitionTable& table) { DeviceMapper& dm = DeviceMapper::Instance(); for (const auto& partition : table.partitions) { if (!CreateDmDeviceForPartition(dm, partition)) { LOG(ERROR) << "could not create dm-linear device for partition: " << partition.name; return false; } struct dm_ioctl io; return fs_mgr_dm_resume_table(&io, partition.name, dm_fd); } static bool CreateDmDeviceForPartition(int dm_fd, const LogicalPartition& partition) { struct dm_ioctl io; if (!fs_mgr_dm_create_device(&io, partition.name, dm_fd)) { return false; } if (!LoadTablesAndActivate(dm_fd, partition)) { // Remove the device rather than leave it in an inactive state. fs_mgr_dm_destroy_device(&io, partition.name, dm_fd); return false; return true; } LINFO << "Created device-mapper device: " << partition.name; return true; std::unique_ptr<LogicalPartitionTable> LoadPartitionsFromDeviceTree() { return nullptr; } bool CreateLogicalPartitions(const LogicalPartitionTable& table) { android::base::unique_fd dm_fd(open("/dev/device-mapper", O_RDWR)); if (dm_fd < 0) { PLOG(ERROR) << "failed to open /dev/device-mapper"; static bool CreateDmTable(const std::string& block_device, 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]; std::unique_ptr<DmTarget> target; switch (extent.target_type) { 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, extent.target_data); break; default: LOG(ERROR) << "Unknown target type in metadata: " << extent.target_type; return false; } for (const auto& partition : table.partitions) { if (!CreateDmDeviceForPartition(dm_fd, partition)) { LOG(ERROR) << "could not create dm-linear device for partition: " << partition.name; if (!table->AddTarget(std::move(target))) { return false; } sector += extent.num_sectors; } return true; if (partition.attributes & LP_PARTITION_ATTR_READONLY) { table->set_readonly(true); } std::unique_ptr<LogicalPartitionTable> LoadPartitionsFromDeviceTree() { return nullptr; return true; } bool CreateLogicalPartitions(const std::string& block_device) { Loading @@ -146,21 +114,21 @@ bool CreateLogicalPartitions(const std::string& block_device) { return true; } LogicalPartitionTable table; DeviceMapper& dm = DeviceMapper::Instance(); for (const auto& partition : metadata->partitions) { LogicalPartition new_partition; new_partition.name = GetPartitionName(partition); new_partition.attributes = partition.attributes; for (size_t i = 0; i < partition.num_extents; i++) { const auto& extent = metadata->extents[partition.first_extent_index + i]; new_partition.extents.emplace_back(new_partition.num_sectors, extent.target_data, extent.num_sectors, block_device.c_str()); new_partition.num_sectors += extent.num_sectors; DmTable table; if (!CreateDmTable(block_device, *metadata.get(), partition, &table)) { return false; } table.partitions.push_back(new_partition); std::string name = GetPartitionName(partition); if (!dm.CreateDevice(name, table)) { return false; } return CreateLogicalPartitions(table); std::string path; dm.GetDmDevicePathByName(partition.name, &path); LINFO << "Created logical partition " << name << " on device " << path; } return true; } } // namespace fs_mgr Loading
fs_mgr/include/fs_mgr_dm_linear.h +5 −38 Original line number Diff line number Diff line Loading @@ -26,53 +26,20 @@ #define __CORE_FS_MGR_DM_LINEAR_H #include <stdint.h> #include <memory> #include <string> #include <vector> #include <libdm/dm.h> #include <liblp/metadata_format.h> namespace android { namespace fs_mgr { static const uint32_t kPartitionReadonly = 0x1; class LogicalPartitionExtent { public: LogicalPartitionExtent() : logical_sector_(0), first_sector_(0), num_sectors_(0) {} LogicalPartitionExtent(uint64_t logical_sector, uint64_t first_sector, uint64_t num_sectors, const std::string& block_device) : logical_sector_(logical_sector), first_sector_(first_sector), num_sectors_(num_sectors), block_device_(block_device) {} // Return a string containing the dm_target_spec buffer needed to use this // extent in a device-mapper table. std::string Serialize() const; const std::string& block_device() const { return block_device_; } private: // Logical sector this extent represents in the presented block device. // This is equal to the previous extent's logical sector plus the number // of sectors in that extent. The first extent always starts at 0. uint64_t logical_sector_; // First 512-byte sector of this extent, on the source block device. uint64_t first_sector_; // Number of 512-byte sectors. uint64_t num_sectors_; // Target block device. std::string block_device_; }; struct LogicalPartition { LogicalPartition() : attributes(0), num_sectors(0) {} std::string name; uint32_t attributes; // Number of 512-byte sectors total. uint64_t num_sectors; // List of extents. std::vector<LogicalPartitionExtent> extents; std::vector<android::dm::DmTargetLinear> extents; }; struct LogicalPartitionTable { Loading
fs_mgr/libdm/include/libdm/dm_target.h +1 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ class DmTargetLinear final : public DmTarget { std::string name() const override { return "linear"; } std::string GetParameterString() const override; const std::string& block_device() const { return block_device_; } private: std::string block_device_; Loading