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

Commit 3e946da5 authored by David Anderson's avatar David Anderson Committed by Gerrit Code Review
Browse files

Merge "init/fs_mgr: prototype first-stage dm-linear support"

parents 0f837fe8 62e5b20b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ cc_library_static {
        "fs_mgr_verity.cpp",
        "fs_mgr_avb.cpp",
        "fs_mgr_avb_ops.cpp",
        "fs_mgr_dm_linear.cpp",
    ],
    static_libs: [
        "libfec",
+37 −0
Original line number Diff line number Diff line
@@ -794,6 +794,29 @@ static bool call_vdc(const std::vector<std::string>& args) {
    return true;
}

bool fs_mgr_update_logical_partition(struct fstab_rec* rec) {
    // Logical partitions are specified with a named partition rather than a
    // block device, so if the block device is a path, then it has already
    // been updated.
    if (rec->blk_device[0] == '/') {
        return true;
    }

    android::base::unique_fd dm_fd(open("/dev/device-mapper", O_RDONLY));
    if (dm_fd < 0) {
        PLOG(ERROR) << "open /dev/device-mapper failed";
        return false;
    }
    struct dm_ioctl io;
    std::string device_name;
    if (!fs_mgr_dm_get_device_name(&io, rec->blk_device, dm_fd, &device_name)) {
        return false;
    }
    free(rec->blk_device);
    rec->blk_device = strdup(device_name.c_str());
    return true;
}

/* When multiple fstab records share the same mount_point, it will
 * try to mount each one in turn, and ignore any duplicates after a
 * first successful mount.
@@ -845,6 +868,13 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode)
            }
        }

        if ((fstab->recs[i].fs_mgr_flags & MF_LOGICAL)) {
            if (!fs_mgr_update_logical_partition(&fstab->recs[i])) {
                LERROR << "Could not set up logical partition, skipping!";
                continue;
            }
        }

        if (fstab->recs[i].fs_mgr_flags & MF_WAIT &&
            !fs_mgr_wait_for_file(fstab->recs[i].blk_device, 20s)) {
            LERROR << "Skipping '" << fstab->recs[i].blk_device << "' during mount_all";
@@ -1065,6 +1095,13 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
            return FS_MGR_DOMNT_FAILED;
        }

        if ((fstab->recs[i].fs_mgr_flags & MF_LOGICAL)) {
            if (!fs_mgr_update_logical_partition(&fstab->recs[i])) {
                LERROR << "Could not set up logical partition, skipping!";
                continue;
            }
        }

        /* First check the filesystem if requested */
        if (fstab->recs[i].fs_mgr_flags & MF_WAIT && !fs_mgr_wait_for_file(n_blk_device, 20s)) {
            LERROR << "Skipping mounting '" << n_blk_device << "'";
+7 −1
Original line number Diff line number Diff line
@@ -585,7 +585,13 @@ SetUpAvbHashtreeResult FsManagerAvbHandle::SetUpAvbHashtree(struct fstab_rec* fs

    // Derives partition_name from blk_device to query the corresponding AVB HASHTREE descriptor
    // to setup dm-verity. The partition_names in AVB descriptors are without A/B suffix.
    std::string partition_name(basename(fstab_entry->blk_device));
    std::string partition_name;
    if (fstab_entry->fs_mgr_flags & MF_LOGICAL) {
        partition_name = fstab_entry->logical_partition_name;
    } else {
        partition_name = basename(fstab_entry->blk_device);
    }

    if (fstab_entry->fs_mgr_flags & MF_SLOTSELECT) {
        auto ab_suffix = partition_name.rfind(fs_mgr_get_slot_suffix());
        if (ab_suffix != std::string::npos) {
+141 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "fs_mgr_dm_linear.h"

#include <inttypes.h>
#include <linux/dm-ioctl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>

#include <sstream>

#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.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);

    // 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;
    for (const auto& extent : partition.extents) {
        target_string += extent.Serialize();
    }

    // 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;
        return false;
    }
    return true;
}

static bool LoadTablesAndActivate(int dm_fd, const LogicalPartition& partition) {
    if (!LoadDmTable(dm_fd, partition)) {
        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;
    }

    LINFO << "Created device-mapper device: " << partition.name;
    return true;
}

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";
        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;
            return false;
        }
    }
    return true;
}

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

}  // namespace fs_mgr
}  // namespace android
+10 −4
Original line number Diff line number Diff line
@@ -109,6 +109,7 @@ static struct flag_list fs_mgr_flags[] = {
    {"logicalblk=", MF_LOGICALBLKSIZE},
    {"sysfs_path=", MF_SYSFS},
    {"defaults", 0},
    {"logical", MF_LOGICAL},
    {0, 0},
};

@@ -445,10 +446,6 @@ static std::string read_fstab_from_dt() {
            LERROR << "dt_fstab: Failed to find device for partition " << dp->d_name;
            return {};
        }
        if (!StartsWith(value, "/dev")) {
            LERROR << "dt_fstab: Invalid device node for partition " << dp->d_name;
            return {};
        }
        fstab_entry.push_back(value);

        std::string mount_point;
@@ -631,6 +628,10 @@ static struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
        fstab->recs[cnt].erase_blk_size = flag_vals.erase_blk_size;
        fstab->recs[cnt].logical_blk_size = flag_vals.logical_blk_size;
        fstab->recs[cnt].sysfs_path = flag_vals.sysfs_path;
        if (fstab->recs[cnt].fs_mgr_flags & MF_LOGICAL) {
            fstab->recs[cnt].logical_partition_name = strdup(fstab->recs[cnt].blk_device);
        }

        cnt++;
    }
    /* If an A/B partition, modify block device to be the real block device */
@@ -797,6 +798,7 @@ void fs_mgr_free_fstab(struct fstab *fstab)
    for (i = 0; i < fstab->num_entries; i++) {
        /* Free the pointers return by strdup(3) */
        free(fstab->recs[i].blk_device);
        free(fstab->recs[i].logical_partition_name);
        free(fstab->recs[i].mount_point);
        free(fstab->recs[i].fs_type);
        free(fstab->recs[i].fs_options);
@@ -944,3 +946,7 @@ int fs_mgr_has_sysfs_path(const struct fstab_rec *fstab)
{
    return fstab->fs_mgr_flags & MF_SYSFS;
}

int fs_mgr_is_logical(const struct fstab_rec* fstab) {
    return fstab->fs_mgr_flags & MF_LOGICAL;
}
Loading