From e1c0744c2647fd48d1c57d9628a145d3f3284107 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 19 Jun 2018 18:13:07 -0700 Subject: [PATCH] libdm: Implement LoadTableAndActivate. This change implements DeviceMapper::LoadTableAndActivate by serializing the given DmTable and issuing DM_TABLE_LOAD and DM_DEV_SUSPEND ioctls. In addition, this makes the CreateDevice() method private, and introduces a separate method for creating a device and loading a table as a single operation. This will obviate the need for separate inactive device cleanup logic later. Note that this change does not yet implement DmTable::Serialize(). Bug: 110035986 Test: N/A Change-Id: Ic8affe591db4930ce672b00db989978b57ca8cbf --- fs_mgr/libdm/dm.cpp | 33 +++++++++++++++++++++++++-- fs_mgr/libdm/dm_table.cpp | 4 ++-- fs_mgr/libdm/include/libdm/dm.h | 25 +++++++++++--------- fs_mgr/libdm/include/libdm/dm_table.h | 9 +++++--- fs_mgr/tools/dmctl.cpp | 5 +++- 5 files changed, 57 insertions(+), 19 deletions(-) diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp index 317ee1f61..5a2dfc67a 100644 --- a/fs_mgr/libdm/dm.cpp +++ b/fs_mgr/libdm/dm.cpp @@ -94,8 +94,37 @@ DmDeviceState DeviceMapper::state(const std::string& /* name */) const { return DmDeviceState::INVALID; } -bool DeviceMapper::LoadTableAndActivate(const std::string& /* name */, const DmTable& /* table */) { - return false; +bool DeviceMapper::CreateDevice(const std::string& name, const DmTable& table) { + if (!CreateDevice(name)) { + return false; + } + if (!LoadTableAndActivate(name, table)) { + DeleteDevice(name); + return false; + } + return true; +} + +bool DeviceMapper::LoadTableAndActivate(const std::string& name, const DmTable& table) { + std::string ioctl_buffer(sizeof(struct dm_ioctl), 0); + ioctl_buffer += table.Serialize(); + + struct dm_ioctl* io = reinterpret_cast(&ioctl_buffer[0]); + InitIo(io, name); + io->data_size = ioctl_buffer.size(); + io->data_start = sizeof(struct dm_ioctl); + io->target_count = static_cast(table.num_targets()); + if (ioctl(fd_, DM_TABLE_LOAD, io)) { + PLOG(ERROR) << "DM_TABLE_LOAD failed"; + return false; + } + + InitIo(io, name); + if (ioctl(fd_, DM_DEV_SUSPEND, io)) { + PLOG(ERROR) << "DM_TABLE_SUSPEND resume failed"; + return false; + } + return true; } // Reads all the available device mapper targets and their corresponding diff --git a/fs_mgr/libdm/dm_table.cpp b/fs_mgr/libdm/dm_table.cpp index 48cd332b1..868286e22 100644 --- a/fs_mgr/libdm/dm_table.cpp +++ b/fs_mgr/libdm/dm_table.cpp @@ -34,8 +34,8 @@ bool DmTable::valid() const { return true; } -uint64_t DmTable::size() const { - return valid() ? size_ : 0; +uint64_t DmTable::num_sectors() const { + return valid() ? num_sectors_ : 0; } // Returns a string represnetation of the table that is ready to be passed diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h index c0b7fe9de..840777499 100644 --- a/fs_mgr/libdm/include/libdm/dm.h +++ b/fs_mgr/libdm/include/libdm/dm.h @@ -69,14 +69,6 @@ class DeviceMapper final { uint64_t dev_; }; - // Creates a device mapper device with given name. - // Return 'true' on success and 'false' on failure to - // create OR if a device mapper device with the same name already - // exists. - // TODO(b/110035986): Make this method private and to be only - // called through LoadTableAndActivate() below. - bool CreateDevice(const std::string& name); - // Removes a device mapper device with the given name. // Returns 'true' on success, false otherwise. bool DeleteDevice(const std::string& name); @@ -90,9 +82,14 @@ class DeviceMapper final { // One of INVALID, SUSPENDED or ACTIVE. DmDeviceState state(const std::string& name) const; - // Loads the device mapper table from parameter into the underlying - // device mapper device with given name and activate / resumes the device in the process. - // If a device mapper device with the 'name', doesn't exist, it will be created. + // Creates a device, loads the given table, and activates it. If the device + // is not able to be activated, it is destroyed, and false is returned. + bool CreateDevice(const std::string& name, const DmTable& table); + + // Loads the device mapper table from parameter into the underlying device + // mapper device with given name and activate / resumes the device in the + // process. A device with the given name must already exist. + // // Returns 'true' on success, false otherwise. bool LoadTableAndActivate(const std::string& name, const DmTable& table); @@ -140,6 +137,12 @@ class DeviceMapper final { } } + // Creates a device mapper device with given name. + // Return 'true' on success and 'false' on failure to + // create OR if a device mapper device with the same name already + // exists. + bool CreateDevice(const std::string& name); + int fd_; // Non-copyable & Non-movable DeviceMapper(const DeviceMapper&) = delete; diff --git a/fs_mgr/libdm/include/libdm/dm_table.h b/fs_mgr/libdm/include/libdm/dm_table.h index 0b1685db0..8a5c62400 100644 --- a/fs_mgr/libdm/include/libdm/dm_table.h +++ b/fs_mgr/libdm/include/libdm/dm_table.h @@ -30,7 +30,7 @@ namespace dm { class DmTable { public: - DmTable() : size_(0){}; + DmTable() : num_sectors_(0){}; // Adds a target to the device mapper table for a range specified in the target object. // The function will return 'true' if the target was successfully added and doesn't overlap with @@ -48,9 +48,12 @@ class DmTable { // table is malformed. bool valid() const; + // Returns the toatl number of targets. + size_t num_targets() const { return targets_.size(); } + // Returns the total size represented by the table in terms of number of 512-byte sectors. // NOTE: This function will overlook if there are any gaps in the targets added in the table. - uint64_t size() const; + uint64_t num_sectors() const; // Returns the string represntation of the table that is ready to be passed into the kernel // as part of the DM_TABLE_LOAD ioctl. @@ -66,7 +69,7 @@ class DmTable { // Total size in terms of # of sectors, as calculated by looking at the last and the first // target in 'target_'. - uint64_t size_; + uint64_t num_sectors_; }; } // namespace dm diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp index 8b2ca3fa0..d637dc67c 100644 --- a/fs_mgr/tools/dmctl.cpp +++ b/fs_mgr/tools/dmctl.cpp @@ -34,6 +34,7 @@ #include using DeviceMapper = ::android::dm::DeviceMapper; +using DmTable = ::android::dm::DmTable; using DmTarget = ::android::dm::DmTarget; using DmBlockDevice = ::android::dm::DeviceMapper::DmBlockDevice; @@ -53,9 +54,11 @@ static int DmCreateCmdHandler(int argc, char** argv) { return -EINVAL; } + DmTable table; + std::string name = argv[0]; DeviceMapper& dm = DeviceMapper::Instance(); - if (!dm.CreateDevice(name)) { + if (!dm.CreateDevice(name, table)) { std::cerr << "Failed to create device-mapper device with name: " << name << std::endl; return -EIO; }