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

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

Merge "fs_mgr: Use libdm for dm-linear devices."

parents 9d254f0d 4b524408
Loading
Loading
Loading
Loading
+52 −84
Original line number Diff line number Diff line
@@ -40,102 +40,70 @@
#include <liblp/reader.h>

#include "fs_mgr_priv.h"
#include "fs_mgr_priv_dm_ioctl.h"

namespace android {
namespace fs_mgr {

std::string LogicalPartitionExtent::Serialize() const {
    // Note: we need to include an explicit null-terminator.
    std::string argv =
        android::base::StringPrintf("%s %" PRIu64, block_device_.c_str(), first_sector_);
    argv.push_back(0);
using DeviceMapper = android::dm::DeviceMapper;
using DmTable = android::dm::DmTable;
using DmTarget = android::dm::DmTarget;
using DmTargetZero = android::dm::DmTargetZero;
using DmTargetLinear = android::dm::DmTargetLinear;

    // The kernel expects each target to be aligned.
    size_t spec_bytes = sizeof(struct dm_target_spec) + argv.size();
    size_t padding = ((spec_bytes + 7) & ~7) - spec_bytes;
    for (size_t i = 0; i < padding; i++) {
        argv.push_back(0);
    }

    struct dm_target_spec spec;
    spec.sector_start = logical_sector_;
    spec.length = num_sectors_;
    spec.status = 0;
    strcpy(spec.target_type, "linear");
    spec.next = sizeof(struct dm_target_spec) + argv.size();

    return std::string((char*)&spec, sizeof(spec)) + argv;
}

static bool LoadDmTable(int dm_fd, const LogicalPartition& partition) {
    // Combine all dm_target_spec buffers together.
    std::string target_string;
static bool CreateDmDeviceForPartition(DeviceMapper& dm, const LogicalPartition& partition) {
    DmTable table;
    for (const auto& extent : partition.extents) {
        target_string += extent.Serialize();
        table.AddTarget(std::make_unique<DmTargetLinear>(extent));
    }

    // Allocate the ioctl buffer.
    size_t buffer_size = sizeof(struct dm_ioctl) + target_string.size();
    std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(buffer_size);

    // Initialize the ioctl buffer header, then copy our target specs in.
    struct dm_ioctl* io = reinterpret_cast<struct dm_ioctl*>(buffer.get());
    fs_mgr_dm_ioctl_init(io, buffer_size, partition.name);
    io->target_count = partition.extents.size();
    if (partition.attributes & kPartitionReadonly) {
        io->flags |= DM_READONLY_FLAG;
    }
    memcpy(io + 1, target_string.c_str(), target_string.size());

    if (ioctl(dm_fd, DM_TABLE_LOAD, io)) {
        PERROR << "Failed ioctl() on DM_TABLE_LOAD, partition " << partition.name;
    if (!dm.CreateDevice(partition.name, table)) {
        return false;
    }
    LINFO << "Created device-mapper device: " << partition.name;
    return true;
}

static bool LoadTablesAndActivate(int dm_fd, const LogicalPartition& partition) {
    if (!LoadDmTable(dm_fd, partition)) {
bool CreateLogicalPartitions(const LogicalPartitionTable& table) {
    DeviceMapper& dm = DeviceMapper::Instance();
    for (const auto& partition : table.partitions) {
        if (!CreateDmDeviceForPartition(dm, partition)) {
            LOG(ERROR) << "could not create dm-linear device for partition: " << partition.name;
            return false;
        }

    struct dm_ioctl io;
    return fs_mgr_dm_resume_table(&io, partition.name, dm_fd);
    }

static bool CreateDmDeviceForPartition(int dm_fd, const LogicalPartition& partition) {
    struct dm_ioctl io;
    if (!fs_mgr_dm_create_device(&io, partition.name, dm_fd)) {
        return false;
    }
    if (!LoadTablesAndActivate(dm_fd, partition)) {
        // Remove the device rather than leave it in an inactive state.
        fs_mgr_dm_destroy_device(&io, partition.name, dm_fd);
        return false;
    return true;
}

    LINFO << "Created device-mapper device: " << partition.name;
    return true;
std::unique_ptr<LogicalPartitionTable> LoadPartitionsFromDeviceTree() {
    return nullptr;
}

bool CreateLogicalPartitions(const LogicalPartitionTable& table) {
    android::base::unique_fd dm_fd(open("/dev/device-mapper", O_RDWR));
    if (dm_fd < 0) {
        PLOG(ERROR) << "failed to open /dev/device-mapper";
static bool CreateDmTable(const std::string& block_device, const LpMetadata& metadata,
                          const LpMetadataPartition& partition, DmTable* table) {
    uint64_t sector = 0;
    for (size_t i = 0; i < partition.num_extents; i++) {
        const auto& extent = metadata.extents[partition.first_extent_index + i];
        std::unique_ptr<DmTarget> target;
        switch (extent.target_type) {
            case LP_TARGET_TYPE_ZERO:
                target = std::make_unique<DmTargetZero>(sector, extent.num_sectors);
                break;
            case LP_TARGET_TYPE_LINEAR:
                target = std::make_unique<DmTargetLinear>(sector, extent.num_sectors, block_device,
                                                          extent.target_data);
                break;
            default:
                LOG(ERROR) << "Unknown target type in metadata: " << extent.target_type;
                return false;
        }
    for (const auto& partition : table.partitions) {
        if (!CreateDmDeviceForPartition(dm_fd, partition)) {
            LOG(ERROR) << "could not create dm-linear device for partition: " << partition.name;
        if (!table->AddTarget(std::move(target))) {
            return false;
        }
        sector += extent.num_sectors;
    }
    return true;
    if (partition.attributes & LP_PARTITION_ATTR_READONLY) {
        table->set_readonly(true);
    }

std::unique_ptr<LogicalPartitionTable> LoadPartitionsFromDeviceTree() {
    return nullptr;
    return true;
}

bool CreateLogicalPartitions(const std::string& block_device) {
@@ -146,21 +114,21 @@ bool CreateLogicalPartitions(const std::string& block_device) {
        return true;
    }

    LogicalPartitionTable table;
    DeviceMapper& dm = DeviceMapper::Instance();
    for (const auto& partition : metadata->partitions) {
        LogicalPartition new_partition;
        new_partition.name = GetPartitionName(partition);
        new_partition.attributes = partition.attributes;
        for (size_t i = 0; i < partition.num_extents; i++) {
            const auto& extent = metadata->extents[partition.first_extent_index + i];
            new_partition.extents.emplace_back(new_partition.num_sectors, extent.target_data,
                                               extent.num_sectors, block_device.c_str());
            new_partition.num_sectors += extent.num_sectors;
        DmTable table;
        if (!CreateDmTable(block_device, *metadata.get(), partition, &table)) {
            return false;
        }
        table.partitions.push_back(new_partition);
        std::string name = GetPartitionName(partition);
        if (!dm.CreateDevice(name, table)) {
            return false;
        }

    return CreateLogicalPartitions(table);
        std::string path;
        dm.GetDmDevicePathByName(partition.name, &path);
        LINFO << "Created logical partition " << name << " on device " << path;
    }
    return true;
}

}  // namespace fs_mgr
+5 −38
Original line number Diff line number Diff line
@@ -26,53 +26,20 @@
#define __CORE_FS_MGR_DM_LINEAR_H

#include <stdint.h>

#include <memory>
#include <string>
#include <vector>

#include <libdm/dm.h>
#include <liblp/metadata_format.h>

namespace android {
namespace fs_mgr {

static const uint32_t kPartitionReadonly = 0x1;

class LogicalPartitionExtent {
  public:
    LogicalPartitionExtent() : logical_sector_(0), first_sector_(0), num_sectors_(0) {}
    LogicalPartitionExtent(uint64_t logical_sector, uint64_t first_sector, uint64_t num_sectors,
                           const std::string& block_device)
        : logical_sector_(logical_sector),
          first_sector_(first_sector),
          num_sectors_(num_sectors),
          block_device_(block_device) {}

    // Return a string containing the dm_target_spec buffer needed to use this
    // extent in a device-mapper table.
    std::string Serialize() const;

    const std::string& block_device() const { return block_device_; }

  private:
    // Logical sector this extent represents in the presented block device.
    // This is equal to the previous extent's logical sector plus the number
    // of sectors in that extent. The first extent always starts at 0.
    uint64_t logical_sector_;
    // First 512-byte sector of this extent, on the source block device.
    uint64_t first_sector_;
    // Number of 512-byte sectors.
    uint64_t num_sectors_;
    // Target block device.
    std::string block_device_;
};

struct LogicalPartition {
    LogicalPartition() : attributes(0), num_sectors(0) {}

    std::string name;
    uint32_t attributes;
    // Number of 512-byte sectors total.
    uint64_t num_sectors;
    // List of extents.
    std::vector<LogicalPartitionExtent> extents;
    std::vector<android::dm::DmTargetLinear> extents;
};

struct LogicalPartitionTable {
+1 −0
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ class DmTargetLinear final : public DmTarget {

    std::string name() const override { return "linear"; }
    std::string GetParameterString() const override;
    const std::string& block_device() const { return block_device_; }

  private:
    std::string block_device_;