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

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

Merge "Improved libdm and dmctl to handle very large numbers of extents"

parents c1c624a1 605fef0e
Loading
Loading
Loading
Loading
+18 −17
Original line number Diff line number Diff line
@@ -299,24 +299,25 @@ bool DeviceMapper::GetTableInfo(const std::string& name, std::vector<TargetInfo>
// private methods of DeviceMapper
bool DeviceMapper::GetTable(const std::string& name, uint32_t flags,
                            std::vector<TargetInfo>* table) {
    char buffer[4096];
    struct dm_ioctl* io = reinterpret_cast<struct dm_ioctl*>(buffer);
    std::vector<char> buffer;
    struct dm_ioctl* io = nullptr;

    for (buffer.resize(4096);; buffer.resize(buffer.size() * 2)) {
        io = reinterpret_cast<struct dm_ioctl*>(&buffer[0]);

        InitIo(io, name);
    io->data_size = sizeof(buffer);
        io->data_size = buffer.size();
        io->data_start = sizeof(*io);
        io->flags = flags;
        if (ioctl(fd_, DM_TABLE_STATUS, io) < 0) {
            PLOG(ERROR) << "DM_TABLE_STATUS failed for " << name;
            return false;
        }
    if (io->flags & DM_BUFFER_FULL_FLAG) {
        PLOG(ERROR) << "DM_TABLE_STATUS result for " << name << " was too large";
        return false;
        if (!(io->flags & DM_BUFFER_FULL_FLAG)) break;
    }

    uint32_t cursor = io->data_start;
    uint32_t data_end = std::min(io->data_size, uint32_t(sizeof(buffer)));
    uint32_t data_end = std::min(io->data_size, uint32_t(buffer.size()));
    for (uint32_t i = 0; i < io->target_count; i++) {
        if (cursor + sizeof(struct dm_target_spec) > data_end) {
            break;
@@ -324,14 +325,14 @@ bool DeviceMapper::GetTable(const std::string& name, uint32_t flags,
        // After each dm_target_spec is a status string. spec->next is an
        // offset from |io->data_start|, and we clamp it to the size of our
        // buffer.
        struct dm_target_spec* spec = reinterpret_cast<struct dm_target_spec*>(buffer + cursor);
        struct dm_target_spec* spec = reinterpret_cast<struct dm_target_spec*>(&buffer[cursor]);
        uint32_t data_offset = cursor + sizeof(dm_target_spec);
        uint32_t next_cursor = std::min(io->data_start + spec->next, data_end);

        std::string data;
        if (next_cursor > data_offset) {
            // Note: we use c_str() to eliminate any extra trailing 0s.
            data = std::string(buffer + data_offset, next_cursor - data_offset).c_str();
            data = std::string(&buffer[data_offset], next_cursor - data_offset).c_str();
        }
        table->emplace_back(*spec, data);
        cursor = next_cursor;
+32 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <android-base/unique_fd.h>
#include <libdm/dm.h>

#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
@@ -50,6 +51,7 @@ using DmBlockDevice = ::android::dm::DeviceMapper::DmBlockDevice;

static int Usage(void) {
    std::cerr << "usage: dmctl <command> [command options]" << std::endl;
    std::cerr << "       dmctl -f file" << std::endl;
    std::cerr << "commands:" << std::endl;
    std::cerr << "  create <dm-name> [-ro] <targets...>" << std::endl;
    std::cerr << "  delete <dm-name>" << std::endl;
@@ -58,6 +60,8 @@ static int Usage(void) {
    std::cerr << "  table <dm-name>" << std::endl;
    std::cerr << "  help" << std::endl;
    std::cerr << std::endl;
    std::cerr << "-f file reads command and all parameters from named file" << std::endl;
    std::cerr << std::endl;
    std::cerr << "Target syntax:" << std::endl;
    std::cerr << "  <target_type> <start_sector> <num_sectors> [target_data]" << std::endl;
    return -EINVAL;
@@ -340,12 +344,40 @@ static std::map<std::string, std::function<int(int, char**)>> cmdmap = {
        // clang-format on
};

static bool ReadFile(const char* filename, std::vector<std::string>* args,
                     std::vector<char*>* arg_ptrs) {
    std::ifstream file(filename);
    if (!file) return false;

    std::string arg;
    while (file >> arg) args->push_back(arg);

    for (auto const& i : *args) arg_ptrs->push_back(const_cast<char*>(i.c_str()));
    return true;
}

int main(int argc, char** argv) {
    android::base::InitLogging(argv, &android::base::StderrLogger);
    if (argc < 2) {
        return Usage();
    }

    std::vector<std::string> args;
    std::vector<char*> arg_ptrs;
    if (std::string("-f") == argv[1]) {
        if (argc != 3) {
            return Usage();
        }

        args.push_back(argv[0]);
        if (!ReadFile(argv[2], &args, &arg_ptrs)) {
            return Usage();
        }

        argc = arg_ptrs.size();
        argv = &arg_ptrs[0];
    }

    for (const auto& cmd : cmdmap) {
        if (cmd.first == argv[1]) {
            return cmd.second(argc - 2, argv + 2);