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

Commit a35d50c2 authored by Nikita Ioffe's avatar Nikita Ioffe Committed by Android (Google) Code Review
Browse files

Merge "libdm: Add DeleteDeviceDeferred API" into sc-dev

parents b9637b0a 8c427b9f
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -35,6 +35,10 @@

#include "utility.h"

#ifndef DM_DEFERRED_REMOVE
#define DM_DEFERRED_REMOVE (1 << 17)
#endif

namespace android {
namespace dm {

@@ -133,6 +137,25 @@ bool DeviceMapper::DeleteDevice(const std::string& name) {
    return DeleteDevice(name, 0ms);
}

bool DeviceMapper::DeleteDeviceDeferred(const std::string& name) {
    struct dm_ioctl io;
    InitIo(&io, name);

    io.flags |= DM_DEFERRED_REMOVE;
    if (ioctl(fd_, DM_DEV_REMOVE, &io)) {
        PLOG(ERROR) << "DM_DEV_REMOVE with DM_DEFERRED_REMOVE failed for [" << name << "]";
        return false;
    }
    return true;
}

bool DeviceMapper::DeleteDeviceIfExistsDeferred(const std::string& name) {
    if (GetState(name) == DmDeviceState::INVALID) {
        return true;
    }
    return DeleteDeviceDeferred(name);
}

static std::string GenerateUuid() {
    uuid_t uuid_bytes;
    uuid_generate(uuid_bytes);
+62 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include <libdm/dm.h>
#include <libdm/loop_control.h>
#include "test_util.h"
#include "utility.h"

using namespace std;
using namespace std::chrono_literals;
@@ -617,3 +618,64 @@ TEST(libdm, GetParentBlockDeviceByPath) {
    auto sub_block_device = dm.GetParentBlockDeviceByPath(dev.path());
    ASSERT_EQ(loop.device(), *sub_block_device);
}

TEST(libdm, DeleteDeviceDeferredNoReferences) {
    unique_fd tmp(CreateTempFile("file_1", 4096));
    ASSERT_GE(tmp, 0);
    LoopDevice loop(tmp, 10s);
    ASSERT_TRUE(loop.valid());

    DmTable table;
    ASSERT_TRUE(table.Emplace<DmTargetLinear>(0, 1, loop.device(), 0));
    ASSERT_TRUE(table.valid());
    TempDevice dev("libdm-test-dm-linear", table);
    ASSERT_TRUE(dev.valid());

    DeviceMapper& dm = DeviceMapper::Instance();

    std::string path;
    ASSERT_TRUE(dm.GetDmDevicePathByName("libdm-test-dm-linear", &path));
    ASSERT_EQ(0, access(path.c_str(), F_OK));

    ASSERT_TRUE(dm.DeleteDeviceDeferred("libdm-test-dm-linear"));

    ASSERT_TRUE(WaitForFileDeleted(path, 5s));
    ASSERT_EQ(DmDeviceState::INVALID, dm.GetState("libdm-test-dm-linear"));
    ASSERT_NE(0, access(path.c_str(), F_OK));
    ASSERT_EQ(ENOENT, errno);
}

TEST(libdm, DeleteDeviceDeferredWaitsForLastReference) {
    unique_fd tmp(CreateTempFile("file_1", 4096));
    ASSERT_GE(tmp, 0);
    LoopDevice loop(tmp, 10s);
    ASSERT_TRUE(loop.valid());

    DmTable table;
    ASSERT_TRUE(table.Emplace<DmTargetLinear>(0, 1, loop.device(), 0));
    ASSERT_TRUE(table.valid());
    TempDevice dev("libdm-test-dm-linear", table);
    ASSERT_TRUE(dev.valid());

    DeviceMapper& dm = DeviceMapper::Instance();

    std::string path;
    ASSERT_TRUE(dm.GetDmDevicePathByName("libdm-test-dm-linear", &path));
    ASSERT_EQ(0, access(path.c_str(), F_OK));

    {
        // Open a reference to block device.
        unique_fd fd(TEMP_FAILURE_RETRY(open(dev.path().c_str(), O_RDONLY | O_CLOEXEC)));
        ASSERT_GE(fd.get(), 0);

        ASSERT_TRUE(dm.DeleteDeviceDeferred("libdm-test-dm-linear"));

        ASSERT_EQ(0, access(path.c_str(), F_OK));
    }

    // After release device will be removed.
    ASSERT_TRUE(WaitForFileDeleted(path, 5s));
    ASSERT_EQ(DmDeviceState::INVALID, dm.GetState("libdm-test-dm-linear"));
    ASSERT_NE(0, access(path.c_str(), F_OK));
    ASSERT_EQ(ENOENT, errno);
}
+6 −0
Original line number Diff line number Diff line
@@ -95,6 +95,12 @@ class DeviceMapper final {
    bool DeleteDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms);
    bool DeleteDeviceIfExists(const std::string& name, const std::chrono::milliseconds& timeout_ms);

    // Enqueues a deletion of device mapper device with the given name once last reference is
    // closed.
    // Returns 'true' on success, false otherwise.
    bool DeleteDeviceDeferred(const std::string& name);
    bool DeleteDeviceIfExistsDeferred(const std::string& name);

    // Fetches and returns the complete state of the underlying device mapper
    // device with given name.
    std::optional<Info> GetDetailedInfo(const std::string& name) const;