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

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

Support sysfs changes in the Linux 5.15 kernel.

DM_DEV_CREATE no longer creates sysfs nodes. Note this in ueventd and
add some helper APIs to libdm, so devices can be created with a
placeholder table.

This also fixes a bug in dmctl where the detailed info on suspended
devices was wrong.

Bug: 259328366
Test: dmctl with "uevents" tool
Change-Id: I822f8010e48d32841aa0ee508822f76d03a3dd85
parent 48cd4132
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -289,7 +289,7 @@ bool DeviceMapper::CreateDevice(const std::string& name, const DmTable& table) {
    return true;
}

bool DeviceMapper::LoadTableAndActivate(const std::string& name, const DmTable& table) {
bool DeviceMapper::LoadTable(const std::string& name, const DmTable& table) {
    std::string ioctl_buffer(sizeof(struct dm_ioctl), 0);
    ioctl_buffer += table.Serialize();

@@ -305,9 +305,17 @@ bool DeviceMapper::LoadTableAndActivate(const std::string& name, const DmTable&
        PLOG(ERROR) << "DM_TABLE_LOAD failed";
        return false;
    }
    return true;
}

    InitIo(io, name);
    if (ioctl(fd_, DM_DEV_SUSPEND, io)) {
bool DeviceMapper::LoadTableAndActivate(const std::string& name, const DmTable& table) {
    if (!LoadTable(name, table)) {
        return false;
    }

    struct dm_ioctl io;
    InitIo(&io, name);
    if (ioctl(fd_, DM_DEV_SUSPEND, &io)) {
        PLOG(ERROR) << "DM_TABLE_SUSPEND resume failed";
        return false;
    }
+20 −0
Original line number Diff line number Diff line
@@ -690,3 +690,23 @@ TEST(libdm, CreateEmptyDevice) {
    // Empty device should be in suspended state.
    ASSERT_EQ(DmDeviceState::SUSPENDED, dm.GetState("empty-device"));
}

TEST(libdm, UeventAfterLoadTable) {
    static const char* kDeviceName = "libmd-test-uevent-load-table";

    DeviceMapper& dm = DeviceMapper::Instance();
    ASSERT_TRUE(dm.CreateEmptyDevice(kDeviceName));

    DmTable table;
    table.Emplace<DmTargetError>(0, 1);
    ASSERT_TRUE(dm.LoadTable(kDeviceName, table));

    std::string ignore_path;
    ASSERT_TRUE(dm.WaitForDevice(kDeviceName, 5s, &ignore_path));

    auto info = dm.GetDetailedInfo(kDeviceName);
    ASSERT_TRUE(info.has_value());
    ASSERT_TRUE(info->IsSuspended());

    ASSERT_TRUE(dm.DeleteDevice(kDeviceName));
}
+8 −1
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ class IDeviceMapper {
                              const std::chrono::milliseconds& timeout_ms) = 0;
    virtual DmDeviceState GetState(const std::string& name) const = 0;
    virtual bool LoadTableAndActivate(const std::string& name, const DmTable& table) = 0;
    virtual bool LoadTable(const std::string& name, const DmTable& table) = 0;
    virtual bool GetTableInfo(const std::string& name, std::vector<TargetInfo>* table) = 0;
    virtual bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* table) = 0;
    virtual bool GetDmDevicePathByName(const std::string& name, std::string* path) = 0;
@@ -116,7 +117,7 @@ class DeviceMapper final : public IDeviceMapper {
        bool IsBufferFull() const { return flags_ & DM_BUFFER_FULL_FLAG; }
        bool IsInactiveTablePresent() const { return flags_ & DM_INACTIVE_PRESENT_FLAG; }
        bool IsReadOnly() const { return flags_ & DM_READONLY_FLAG; }
        bool IsSuspended() const { return flags_ & DM_SUSPEND_FLAG; }
        bool IsSuspended() const { return !IsActiveTablePresent() || (flags_ & DM_SUSPEND_FLAG); }
    };

    // Removes a device mapper device with the given name.
@@ -199,6 +200,12 @@ class DeviceMapper final : public IDeviceMapper {
    // Returns 'true' on success, false otherwise.
    bool LoadTableAndActivate(const std::string& name, const DmTable& table) override;

    // Same as LoadTableAndActivate, but there is no resume step. This puts the
    // new table in the inactive slot.
    //
    // Returns 'true' on success, false otherwise.
    bool LoadTable(const std::string& name, const DmTable& table) override;

    // Returns true if a list of available device mapper targets registered in the kernel was
    // successfully read and stored in 'targets'. Returns 'false' otherwise.
    bool GetAvailableTargets(std::vector<DmTargetTypeInfo>* targets);
+3 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ namespace dm {
class DmTable {
  public:
    DmTable() : num_sectors_(0), readonly_(false) {}
    DmTable(DmTable&& other) = default;

    // 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
@@ -70,6 +71,8 @@ class DmTable {
    void set_readonly(bool readonly) { readonly_ = readonly; }
    bool readonly() const { return readonly_; }

    DmTable& operator=(DmTable&& other) = default;

    ~DmTable() = default;

  private:
+8 −0
Original line number Diff line number Diff line
@@ -323,6 +323,14 @@ class DmTargetUser final : public DmTarget {
    std::string control_device_;
};

class DmTargetError final : public DmTarget {
  public:
    DmTargetError(uint64_t start, uint64_t length) : DmTarget(start, length) {}

    std::string name() const override { return "error"; }
    std::string GetParameterString() const override { return ""; }
};

}  // namespace dm
}  // namespace android

Loading