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

Commit a45e5133 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Add dm-thin support" into main

parents 62963d97 2f814176
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -71,6 +71,9 @@ cc_defaults {
        "libbase",
        "liblog",
    ],
    header_libs: [
        "libstorage_literals_headers",
    ],
    srcs: [":libdm_test_srcs"],
    auto_gen_config: true,
    require_root: true,
+20 −0
Original line number Diff line number Diff line
@@ -769,5 +769,25 @@ bool DeviceMapper::CreatePlaceholderDevice(const std::string& name) {
    return true;
}

bool DeviceMapper::SendMessage(const std::string& name, uint64_t sector,
                               const std::string& message) {
    std::string ioctl_buffer(sizeof(struct dm_ioctl) + sizeof(struct dm_target_msg), 0);
    ioctl_buffer += message;
    ioctl_buffer.push_back('\0');

    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);
    struct dm_target_msg* msg =
            reinterpret_cast<struct dm_target_msg*>(&ioctl_buffer[sizeof(struct dm_ioctl)]);
    msg->sector = sector;
    if (ioctl(fd_, DM_TARGET_MSG, io)) {
        PLOG(ERROR) << "DM_TARGET_MSG failed";
        return false;
    }
    return true;
}

}  // namespace dm
}  // namespace android
+38 −0
Original line number Diff line number Diff line
@@ -298,5 +298,43 @@ std::string DmTargetUser::GetParameterString() const {
    return android::base::Join(argv, " ");
}

DmTargetThinPool::DmTargetThinPool(uint64_t start, uint64_t length, const std::string& metadata_dev,
                                   const std::string& data_dev, uint64_t data_block_size,
                                   uint64_t low_water_mark)
    : DmTarget(start, length),
      metadata_dev_(metadata_dev),
      data_dev_(data_dev),
      data_block_size_(data_block_size),
      low_water_mark_(low_water_mark) {}

std::string DmTargetThinPool::GetParameterString() const {
    std::vector<std::string> args{
            metadata_dev_,
            data_dev_,
            std::to_string(data_block_size_),
            std::to_string(low_water_mark_),
    };
    return android::base::Join(args, " ");
}

bool DmTargetThinPool::Valid() const {
    // data_block_size: must be between 128 (64KB) and 2097152 (1GB) and a multiple of 128 (64KB)
    if (data_block_size_ < 128 || data_block_size_ > 2097152) return false;
    if (data_block_size_ % 128) return false;
    return true;
}

DmTargetThin::DmTargetThin(uint64_t start, uint64_t length, const std::string& pool_dev,
                           uint64_t dev_id)
    : DmTarget(start, length), pool_dev_(pool_dev), dev_id_(dev_id) {}

std::string DmTargetThin::GetParameterString() const {
    std::vector<std::string> args{
            pool_dev_,
            std::to_string(dev_id_),
    };
    return android::base::Join(args, " ");
}

}  // namespace dm
}  // namespace android
+41 −0
Original line number Diff line number Diff line
@@ -37,12 +37,14 @@
#include <gtest/gtest.h>
#include <libdm/dm.h>
#include <libdm/loop_control.h>
#include <storage_literals/storage_literals.h>
#include "test_util.h"
#include "utility.h"

using namespace std;
using namespace std::chrono_literals;
using namespace android::dm;
using namespace android::storage_literals;
using android::base::make_scope_guard;
using android::base::unique_fd;

@@ -773,3 +775,42 @@ TEST_F(DmTest, GetNameAndUuid) {
    ASSERT_EQ(name, test_name_);
    ASSERT_FALSE(uuid.empty());
}

TEST_F(DmTest, ThinProvisioning) {
    if (!DeviceMapper::Instance().GetTargetByName("thin-pool", nullptr)) GTEST_SKIP();

    constexpr uint64_t MetaSize = 2_MiB;
    constexpr uint64_t DataSize = 64_MiB;
    constexpr uint64_t ThinSize = 1_TiB;

    // Prepare two loop devices for meta and data devices.
    TemporaryFile meta;
    ASSERT_GE(meta.fd, 0);
    ASSERT_EQ(0, ftruncate64(meta.fd, MetaSize));
    TemporaryFile data;
    ASSERT_GE(data.fd, 0);
    ASSERT_EQ(0, ftruncate64(data.fd, DataSize));

    LoopDevice loop_meta(meta.fd, 10s);
    ASSERT_TRUE(loop_meta.valid());
    LoopDevice loop_data(data.fd, 10s);
    ASSERT_TRUE(loop_data.valid());

    // Create a thin-pool
    DmTable poolTable;
    poolTable.Emplace<DmTargetThinPool>(0, DataSize / kSectorSize, loop_meta.device(),
                                        loop_data.device(), 128, 0);
    TempDevice pool("pool", poolTable);
    ASSERT_TRUE(pool.valid());

    // Create a thin volume
    uint64_t thin_volume_id = 0;
    ASSERT_TRUE(DeviceMapper::Instance().SendMessage(
            "pool", 0, "create_thin " + std::to_string(thin_volume_id)));

    // Use a thin volume to create a 1T device
    DmTable thinTable;
    thinTable.Emplace<DmTargetThin>(0, ThinSize / kSectorSize, pool.path(), thin_volume_id);
    TempDevice thin("thin", thinTable);
    ASSERT_TRUE(thin.valid());
}
+3 −0
Original line number Diff line number Diff line
@@ -307,6 +307,9 @@ class DeviceMapper final : public IDeviceMapper {

    bool GetDeviceNameAndUuid(dev_t dev, std::string* name, std::string* uuid);

    // Send |message| to target, pointed by |name| and |sector|. Use 0 if |sector| is not needed.
    bool SendMessage(const std::string& name, uint64_t sector, const std::string& message);

  private:
    // Maximum possible device mapper targets registered in the kernel.
    // This is only used to read the list of targets from kernel so we allocate
Loading