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

Commit 96e5f9b5 authored by Tom Cherry's avatar Tom Cherry
Browse files

Allow mapping of raw block devices to partition names

Allow mapping of raw block devices (those without a partition table)
to partition names for first stage mount and ueventd.  For example, a
block device `vdb` that contains only an ext4 metadata partition could
be mapped to `metadata` such that /dev/block/by-name/metadata is
created.

The mapping is provided by the `androidboot.partition_map` bootconfig
or kernel command line parameter.

Bug: 159943320
Test: boot with raw vdb,metadata;vdc,userdata partitions
Change-Id: Ib6a939d6fb88b85c46c81d613425a127627a734b
parent 56a05e1f
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -86,9 +86,15 @@ ListenerAction BlockDevInitializer::HandleUevent(const Uevent& uevent,
    }

    auto iter = devices->find(name);
    if (iter == devices->end()) {
        auto partition_name = DeviceHandler::GetPartitionNameForDevice(uevent.device_name);
        if (!partition_name.empty()) {
            iter = devices->find(partition_name);
        }
        if (iter == devices->end()) {
            return ListenerAction::kContinue;
        }
    }

    LOG(VERBOSE) << __PRETTY_FUNCTION__ << ": found partition: " << name;

+35 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ using android::base::Dirname;
using android::base::ReadFileToString;
using android::base::Readlink;
using android::base::Realpath;
using android::base::Split;
using android::base::StartsWith;
using android::base::StringPrintf;
using android::base::Trim;
@@ -187,6 +188,36 @@ void SysfsPermissions::SetPermissions(const std::string& path) const {
    }
}

std::string DeviceHandler::GetPartitionNameForDevice(const std::string& query_device) {
    static const auto partition_map = [] {
        std::vector<std::pair<std::string, std::string>> partition_map;
        auto parser = [&partition_map](const std::string& key, const std::string& value) {
            if (key != "androidboot.partition_map") {
                return;
            }
            for (const auto& map : Split(value, ";")) {
                auto map_pieces = Split(map, ",");
                if (map_pieces.size() != 2) {
                    LOG(ERROR) << "Expected a comma separated device,partition mapping, but found '"
                               << map << "'";
                    continue;
                }
                partition_map.emplace_back(map_pieces[0], map_pieces[1]);
            }
        };
        ImportKernelCmdline(parser);
        ImportBootconfig(parser);
        return partition_map;
    }();

    for (const auto& [device, partition] : partition_map) {
        if (query_device == device) {
            return partition;
        }
    }
    return {};
}

// Given a path that may start with a platform device, find the parent platform device by finding a
// parent directory with a 'subsystem' symlink that points to the platform bus.
// If it doesn't start with a platform device, return false
@@ -376,6 +407,10 @@ std::vector<std::string> DeviceHandler::GetBlockDeviceSymlinks(const Uevent& uev
        // If we don't have a partition name but we are a partition on a boot device, create a
        // symlink of /dev/block/by-name/<device_name> for symmetry.
        links.emplace_back("/dev/block/by-name/" + uevent.device_name);
        auto partition_name = GetPartitionNameForDevice(uevent.device_name);
        if (!partition_name.empty()) {
            links.emplace_back("/dev/block/by-name/" + partition_name);
        }
    }

    auto last_slash = uevent.path.rfind('/');
+6 −0
Original line number Diff line number Diff line
@@ -122,6 +122,12 @@ class DeviceHandler : public UeventHandler {

    std::vector<std::string> GetBlockDeviceSymlinks(const Uevent& uevent) const;

    // `androidboot.partition_map` allows associating a partition name for a raw block device
    // through a comma separated and semicolon deliminated list. For example,
    // `androidboot.partition_map=vdb,metadata;vdc,userdata` maps `vdb` to `metadata` and `vdc` to
    // `userdata`.
    static std::string GetPartitionNameForDevice(const std::string& device);

  private:
    bool FindPlatformDevice(std::string path, std::string* platform_device_path) const;
    std::tuple<mode_t, uid_t, gid_t> GetDevicePermissions(