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

Commit 912b9d06 authored by Jooyung Han's avatar Jooyung Han
Browse files

libdm: LoopControl::Add/Remove(id)

This new methods wraps ioctl(LOOP_CTL_ADD/LOOP_CTL_REMOVE) with a given
ID.

Bug: 413174275
Flag: com.android.apex.flags.mount_before_data
Test: libdm_test
Change-Id: Id8b95180771590ac10e207212a80bd08f30d95d8
parent 39b0bac0
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -43,6 +43,12 @@ class LoopControl final {
    // Detach the loop device given by 'loopdev' from the attached backing file.
    bool Detach(const std::string& loopdev) const;

    // Add a new loop device with given 'id'.
    bool Add(int id) const;

    // Remove the device with given 'id'.
    bool Remove(int id) const;

    // Enable Direct I/O on a loop device. This requires kernel 4.9+.
    static bool EnableDirectIo(int fd);

@@ -60,6 +66,8 @@ class LoopControl final {
    static constexpr const char* kLoopControlDevice = "/dev/loop-control";

    android::base::unique_fd control_fd_;

    friend struct LoopControlTest;
};

// Create a temporary loop device around a file descriptor or path.
+21 −0
Original line number Diff line number Diff line
@@ -98,6 +98,27 @@ bool LoopControl::Detach(const std::string& loopdev) const {
    return true;
}

bool LoopControl::Add(int id) const {
    int rc = ioctl(control_fd_, LOOP_CTL_ADD, id);
    if (rc < 0) {
        // To avoid logspam
        if (errno != EEXIST) {
            PLOG(ERROR) << "Failed LOOP_CTL_ADD to add a loop device " << id;
        }
        return false;
    }
    return true;
}

bool LoopControl::Remove(int id) const {
    int rc = ioctl(control_fd_, LOOP_CTL_REMOVE, id);
    if (rc < 0) {
        PLOG(ERROR) << "Failed LOOP_CTL_REMOVE to remove a loop device " << id;
        return false;
    }
    return true;
}

bool LoopControl::FindFreeLoopDevice(std::string* loopdev) const {
    int rc = ioctl(control_fd_, LOOP_CTL_GET_FREE);
    if (rc < 0) {
+27 −2
Original line number Diff line number Diff line
@@ -29,8 +29,10 @@
#include "test_util.h"

using namespace std;
using namespace android::dm;
using unique_fd = android::base::unique_fd;
using android::base::Basename;
using android::base::unique_fd;

namespace android::dm {

static unique_fd TempFile() {
    // A loop device needs to be at least one sector to actually work, so fill
@@ -62,3 +64,26 @@ TEST(libdm, LoopControl) {
    ASSERT_TRUE(android::base::ReadFully(loop_fd, buffer, sizeof(buffer)));
    ASSERT_EQ(memcmp(buffer, "Hello", 6), 0);
}

struct LoopControlTest : ::testing::Test {
    LoopControl control;
    // indirection to access private LoopControl::FindFreeLoopDevice() method
    bool FindFreeLoopDevice(std::string* loopdev) const {
        return control.FindFreeLoopDevice(loopdev);
    }
};

TEST_F(LoopControlTest, AddRemove) {
    // Get an id for a free loop device first
    std::string path;
    ASSERT_TRUE(FindFreeLoopDevice(&path));
    std::string name = Basename(path);
    ASSERT_EQ(name.substr(0, 4), "loop");
    int id = atoi(name.substr(4).c_str());

    ASSERT_FALSE(control.Add(id));
    ASSERT_TRUE(control.Remove(id));
    ASSERT_TRUE(control.Add(id));
}

}  // namespace android::dm