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
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index 317ee1f..5a2dfc6 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -94,8 +94,37 @@
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<struct dm_ioctl*>(&ioctl_buffer[0]);
+ InitIo(io, name);
+ io->data_size = ioctl_buffer.size();
+ io->data_start = sizeof(struct dm_ioctl);
+ io->target_count = static_cast<uint32_t>(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 48cd332..868286e 100644
--- a/fs_mgr/libdm/dm_table.cpp
+++ b/fs_mgr/libdm/dm_table.cpp
@@ -34,8 +34,8 @@
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 c0b7fe9..8407774 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -69,14 +69,6 @@
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 @@
// 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 @@
}
}
+ // 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 0b1685d..8a5c624 100644
--- a/fs_mgr/libdm/include/libdm/dm_table.h
+++ b/fs_mgr/libdm/include/libdm/dm_table.h
@@ -30,7 +30,7 @@
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 @@
// 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 @@
// 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 8b2ca3f..d637dc6 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -34,6 +34,7 @@
#include <vector>
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 @@
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;
}