Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e1c0744c authored by David Anderson's avatar David Anderson
Browse files

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
parent b1a834ec
Loading
Loading
Loading
Loading
+31 −2
Original line number Original line Diff line number Diff line
@@ -94,9 +94,38 @@ DmDeviceState DeviceMapper::state(const std::string& /* name */) const {
    return DmDeviceState::INVALID;
    return DmDeviceState::INVALID;
}
}


bool DeviceMapper::LoadTableAndActivate(const std::string& /* name */, const DmTable& /* table */) {
bool DeviceMapper::CreateDevice(const std::string& name, const DmTable& table) {
    if (!CreateDevice(name)) {
        return false;
        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
// Reads all the available device mapper targets and their corresponding
// versions from the kernel and returns in a vector
// versions from the kernel and returns in a vector
+2 −2
Original line number Original line Diff line number Diff line
@@ -34,8 +34,8 @@ bool DmTable::valid() const {
    return true;
    return true;
}
}


uint64_t DmTable::size() const {
uint64_t DmTable::num_sectors() const {
    return valid() ? size_ : 0;
    return valid() ? num_sectors_ : 0;
}
}


// Returns a string represnetation of the table that is ready to be passed
// Returns a string represnetation of the table that is ready to be passed
+14 −11
Original line number Original line Diff line number Diff line
@@ -69,14 +69,6 @@ class DeviceMapper final {
        uint64_t dev_;
        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.
    // Removes a device mapper device with the given name.
    // Returns 'true' on success, false otherwise.
    // Returns 'true' on success, false otherwise.
    bool DeleteDevice(const std::string& name);
    bool DeleteDevice(const std::string& name);
@@ -90,9 +82,14 @@ class DeviceMapper final {
    // One of INVALID, SUSPENDED or ACTIVE.
    // One of INVALID, SUSPENDED or ACTIVE.
    DmDeviceState state(const std::string& name) const;
    DmDeviceState state(const std::string& name) const;


    // Loads the device mapper table from parameter into the underlying
    // Creates a device, loads the given table, and activates it. If the device
    // device mapper device with given name and activate / resumes the device in the process.
    // is not able to be activated, it is destroyed, and false is returned.
    // If a device mapper device with the 'name', doesn't exist, it will be created.
    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.
    // Returns 'true' on success, false otherwise.
    bool LoadTableAndActivate(const std::string& name, const DmTable& table);
    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_;
    int fd_;
    // Non-copyable & Non-movable
    // Non-copyable & Non-movable
    DeviceMapper(const DeviceMapper&) = delete;
    DeviceMapper(const DeviceMapper&) = delete;
+6 −3
Original line number Original line Diff line number Diff line
@@ -30,7 +30,7 @@ namespace dm {


class DmTable {
class DmTable {
  public:
  public:
    DmTable() : size_(0){};
    DmTable() : num_sectors_(0){};


    // Adds a target to the device mapper table for a range specified in the target object.
    // 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
    // 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.
    // table is malformed.
    bool valid() const;
    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.
    // 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.
    // 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
    // Returns the string represntation of the table that is ready to be passed into the kernel
    // as part of the DM_TABLE_LOAD ioctl.
    // 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
    // Total size in terms of # of sectors, as calculated by looking at the last and the first
    // target in 'target_'.
    // target in 'target_'.
    uint64_t size_;
    uint64_t num_sectors_;
};
};


}  // namespace dm
}  // namespace dm
+4 −1
Original line number Original line Diff line number Diff line
@@ -34,6 +34,7 @@
#include <vector>
#include <vector>


using DeviceMapper = ::android::dm::DeviceMapper;
using DeviceMapper = ::android::dm::DeviceMapper;
using DmTable = ::android::dm::DmTable;
using DmTarget = ::android::dm::DmTarget;
using DmTarget = ::android::dm::DmTarget;
using DmBlockDevice = ::android::dm::DeviceMapper::DmBlockDevice;
using DmBlockDevice = ::android::dm::DeviceMapper::DmBlockDevice;


@@ -53,9 +54,11 @@ static int DmCreateCmdHandler(int argc, char** argv) {
        return -EINVAL;
        return -EINVAL;
    }
    }


    DmTable table;

    std::string name = argv[0];
    std::string name = argv[0];
    DeviceMapper& dm = DeviceMapper::Instance();
    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;
        std::cerr << "Failed to create device-mapper device with name: " << name << std::endl;
        return -EIO;
        return -EIO;
    }
    }