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

Commit 1d6d4507 authored by Yifan Hong's avatar Yifan Hong Committed by Gerrit Code Review
Browse files

Merge "liblp: CreateLogicalPartition with a given mapped name"

parents c1c6008b 15aa9540
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -56,8 +56,16 @@ bool OpenLogicalPartition(FastbootDevice* device, const std::string& partition_n
    if (!path) {
        return false;
    }

    CreateLogicalPartitionParams params = {
            .block_device = *path,
            .metadata_slot = slot_number,
            .partition_name = partition_name,
            .force_writable = true,
            .timeout_ms = 5s,
    };
    std::string dm_path;
    if (!CreateLogicalPartition(path->c_str(), slot_number, partition_name, true, 5s, &dm_path)) {
    if (!CreateLogicalPartition(params, &dm_path)) {
        LOG(ERROR) << "Could not map partition: " << partition_name;
        return false;
    }
+57 −41
Original line number Diff line number Diff line
@@ -109,26 +109,6 @@ static bool CreateDmTable(const LpMetadata& metadata, const LpMetadataPartition&
    return true;
}

static bool CreateLogicalPartition(const LpMetadata& metadata, const LpMetadataPartition& partition,
                                   bool force_writable, const std::chrono::milliseconds& timeout_ms,
                                   const std::string& super_device, std::string* path) {
    DeviceMapper& dm = DeviceMapper::Instance();

    DmTable table;
    if (!CreateDmTable(metadata, partition, super_device, &table)) {
        return false;
    }
    if (force_writable) {
        table.set_readonly(false);
    }
    std::string name = GetPartitionName(partition);
    if (!dm.CreateDevice(name, table, path, timeout_ms)) {
        return false;
    }
    LINFO << "Created logical partition " << name << " on device " << *path;
    return true;
}

bool CreateLogicalPartitions(const std::string& block_device) {
    uint32_t slot = SlotNumberForSlotSuffix(fs_mgr_get_slot_suffix());
    auto metadata = ReadMetadata(block_device.c_str(), slot);
@@ -145,13 +125,20 @@ std::unique_ptr<LpMetadata> ReadCurrentMetadata(const std::string& block_device)
}

bool CreateLogicalPartitions(const LpMetadata& metadata, const std::string& super_device) {
    CreateLogicalPartitionParams params = {
            .block_device = super_device,
            .metadata = &metadata,
    };
    for (const auto& partition : metadata.partitions) {
        if (!partition.num_extents) {
            LINFO << "Skipping zero-length logical partition: " << GetPartitionName(partition);
            continue;
        }
        std::string path;
        if (!CreateLogicalPartition(metadata, partition, false, {}, super_device, &path)) {

        params.partition = &partition;

        std::string ignore_path;
        if (!CreateLogicalPartition(params, &ignore_path)) {
            LERROR << "Could not create logical partition: " << GetPartitionName(partition);
            return false;
        }
@@ -159,29 +146,58 @@ bool CreateLogicalPartitions(const LpMetadata& metadata, const std::string& supe
    return true;
}

bool CreateLogicalPartition(const std::string& block_device, const LpMetadata& metadata,
                            const std::string& partition_name, bool force_writable,
                            const std::chrono::milliseconds& timeout_ms, std::string* path) {
    for (const auto& partition : metadata.partitions) {
        if (GetPartitionName(partition) == partition_name) {
            return CreateLogicalPartition(metadata, partition, force_writable, timeout_ms,
                                          block_device, path);
bool CreateLogicalPartition(const CreateLogicalPartitionParams& params, std::string* path) {
    const LpMetadata* metadata = params.metadata;

    // Read metadata if needed.
    std::unique_ptr<LpMetadata> local_metadata;
    if (!metadata) {
        if (!params.metadata_slot) {
            LOG(ERROR) << "Either metadata or a metadata slot must be specified.";
            return false;
        }
        auto slot = *params.metadata_slot;
        if (local_metadata = ReadMetadata(params.block_device, slot); !local_metadata) {
            LOG(ERROR) << "Could not read partition table for: " << params.block_device;
            return false;
        }
        metadata = local_metadata.get();
    }

    // Find the partition by name if needed.
    const LpMetadataPartition* partition = params.partition;
    if (!partition) {
        for (const auto& iter : metadata->partitions) {
            if (GetPartitionName(iter) == params.partition_name) {
                partition = &iter;
                break;
            }
        }
    LERROR << "Could not find any partition with name: " << partition_name;
        if (!partition) {
            LERROR << "Could not find any partition with name: " << params.partition_name;
            return false;
        }
    }

bool CreateLogicalPartition(const std::string& block_device, uint32_t metadata_slot,
                            const std::string& partition_name, bool force_writable,
                            const std::chrono::milliseconds& timeout_ms, std::string* path) {
    auto metadata = ReadMetadata(block_device.c_str(), metadata_slot);
    if (!metadata) {
        LOG(ERROR) << "Could not read partition table.";
        return true;
    DmTable table;
    if (!CreateDmTable(*metadata, *partition, params.block_device, &table)) {
        return false;
    }
    if (params.force_writable) {
        table.set_readonly(false);
    }

    std::string device_name = params.device_name;
    if (device_name.empty()) {
        device_name = GetPartitionName(*partition);
    }
    return CreateLogicalPartition(block_device, *metadata.get(), partition_name, force_writable,
                                  timeout_ms, path);

    DeviceMapper& dm = DeviceMapper::Instance();
    if (!dm.CreateDevice(device_name, table, path, params.timeout_ms)) {
        return false;
    }
    LINFO << "Created logical partition " << device_name << " on device " << *path;
    return true;
}

bool UnmapDevice(const std::string& name) {
+18 −7
Original line number Diff line number Diff line
@@ -959,9 +959,16 @@ bool fs_mgr_overlayfs_create_scratch(const Fstab& fstab, std::string* scratch_de
    }

    if (changed || partition_create) {
        if (!CreateLogicalPartition(super_device, slot_number, partition_name, true, 10s,
                                    scratch_device))
        CreateLogicalPartitionParams params = {
                .block_device = super_device,
                .metadata_slot = slot_number,
                .partition_name = partition_name,
                .force_writable = true,
                .timeout_ms = 10s,
        };
        if (!CreateLogicalPartition(params, scratch_device)) {
            return false;
        }

        if (change) *change = true;
    }
@@ -1182,11 +1189,15 @@ bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) {
    if ((mount_point != nullptr) && !fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) {
        auto scratch_device = fs_mgr_overlayfs_scratch_device();
        if (scratch_device.empty()) {
            auto slot_number = fs_mgr_overlayfs_slot_number();
            auto super_device = fs_mgr_overlayfs_super_device(slot_number);
            const auto partition_name = android::base::Basename(kScratchMountPoint);
            CreateLogicalPartition(super_device, slot_number, partition_name, true, 10s,
                                   &scratch_device);
            auto metadata_slot = fs_mgr_overlayfs_slot_number();
            CreateLogicalPartitionParams params = {
                    .block_device = fs_mgr_overlayfs_super_device(metadata_slot),
                    .metadata_slot = metadata_slot,
                    .partition_name = android::base::Basename(kScratchMountPoint),
                    .force_writable = true,
                    .timeout_ms = 10s,
            };
            CreateLogicalPartition(params, &scratch_device);
        }
        mount_scratch = fs_mgr_overlayfs_mount_scratch(scratch_device,
                                                       fs_mgr_overlayfs_scratch_mount_type());
+27 −16
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@

#include <chrono>
#include <memory>
#include <optional>
#include <string>
#include <vector>

@@ -49,22 +50,32 @@ bool CreateLogicalPartitions(const LpMetadata& metadata, const std::string& bloc
// method for ReadMetadata and CreateLogicalPartitions.
bool CreateLogicalPartitions(const std::string& block_device);

// Create a block device for a single logical partition, given metadata and
// the partition name. On success, a path to the partition's block device is
// returned. If |force_writable| is true, the "readonly" flag will be ignored
// so the partition can be flashed.
//
// If |timeout_ms| is non-zero, then CreateLogicalPartition will block for the
// given amount of time until the path returned in |path| is available.
bool CreateLogicalPartition(const std::string& block_device, uint32_t metadata_slot,
                            const std::string& partition_name, bool force_writable,
                            const std::chrono::milliseconds& timeout_ms, std::string* path);

// Same as above, but with a given metadata object. Care should be taken that
// the metadata represents a valid partition layout.
bool CreateLogicalPartition(const std::string& block_device, const LpMetadata& metadata,
                            const std::string& partition_name, bool force_writable,
                            const std::chrono::milliseconds& timeout_ms, std::string* path);
struct CreateLogicalPartitionParams {
    // Block device of the super partition.
    std::string block_device;

    // If |metadata| is null, the slot will be read using |metadata_slot|.
    const LpMetadata* metadata = nullptr;
    std::optional<uint32_t> metadata_slot;

    // If |partition| is not set, it will be found via |partition_name|.
    const LpMetadataPartition* partition = nullptr;
    std::string partition_name;

    // Force the device to be read-write even if it was specified as readonly
    // in the metadata.
    bool force_writable = false;

    // If |timeout_ms| is non-zero, then CreateLogicalPartition will block for
    // the given amount of time until the path returned in |path| is available.
    std::chrono::milliseconds timeout_ms = {};

    // If this is non-empty, it will override the device mapper name (by
    // default the partition name will be used).
    std::string device_name;
};

bool CreateLogicalPartition(const CreateLogicalPartitionParams& params, std::string* path);

// Destroy the block device for a logical partition, by name. If |timeout_ms|
// is non-zero, then this will block until the device path has been unlinked.