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

Commit ccb0608a authored by Nikita Ioffe's avatar Nikita Ioffe Committed by Android (Google) Code Review
Browse files

Merge "fs_mgr_get_mounted_entry_for_userdata: handle logical partitions" into rvc-dev

parents 846d1479 f495fe79
Loading
Loading
Loading
Loading
+30 −48
Original line number Diff line number Diff line
@@ -1589,76 +1589,58 @@ static bool fs_mgr_unmount_all_data_mounts(const std::string& block_device) {
    }
}

static std::string ResolveBlockDevice(const std::string& block_device) {
static bool UnwindDmDeviceStack(const std::string& block_device,
                                std::vector<std::string>* dm_stack) {
    if (!StartsWith(block_device, "/dev/block/")) {
        LWARNING << block_device << " is not a block device";
        return block_device;
    }
    std::string name = block_device.substr(5);
    if (!StartsWith(name, "block/dm-")) {
        // Not a dm-device, but might be a symlink. Optimistically try to readlink.
        std::string result;
        if (Readlink(block_device, &result)) {
            return result;
        } else if (errno == EINVAL) {
            // After all, it wasn't a symlink.
            return block_device;
        } else {
            LERROR << "Failed to readlink " << block_device;
            return "";
        }
        return false;
    }
    // It's a dm-device, let's find what's inside!
    std::string sys_dir = "/sys/" + name;
    std::string current = block_device;
    DeviceMapper& dm = DeviceMapper::Instance();
    while (true) {
        std::string slaves_dir = sys_dir + "/slaves";
        std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(slaves_dir.c_str()), closedir);
        if (!dir) {
            LERROR << "Failed to open " << slaves_dir;
            return "";
        }
        std::string sub_device_name = "";
        for (auto entry = readdir(dir.get()); entry; entry = readdir(dir.get())) {
            if (entry->d_type != DT_LNK) continue;
            if (!sub_device_name.empty()) {
                LERROR << "Too many slaves in " << slaves_dir;
                return "";
            }
            sub_device_name = entry->d_name;
        }
        if (sub_device_name.empty()) {
            LERROR << "No slaves in " << slaves_dir;
            return "";
        dm_stack->push_back(current);
        if (!dm.IsDmBlockDevice(current)) {
            break;
        }
        if (!StartsWith(sub_device_name, "dm-")) {
            // Not a dm-device! We can stop now.
            return "/dev/block/" + sub_device_name;
        auto parent = dm.GetParentBlockDeviceByPath(current);
        if (!parent) {
            return false;
        }
        // Still a dm-device, keep digging.
        sys_dir = "/sys/block/" + sub_device_name;
        current = *parent;
    }
    return true;
}

FstabEntry* fs_mgr_get_mounted_entry_for_userdata(Fstab* fstab, const FstabEntry& mounted_entry) {
    std::string resolved_block_device = ResolveBlockDevice(mounted_entry.blk_device);
    if (resolved_block_device.empty()) {
    if (mounted_entry.mount_point != "/data") {
        LERROR << mounted_entry.mount_point << " is not /data";
        return nullptr;
    }
    std::vector<std::string> dm_stack;
    if (!UnwindDmDeviceStack(mounted_entry.blk_device, &dm_stack)) {
        LERROR << "Failed to unwind dm-device stack for " << mounted_entry.blk_device;
        return nullptr;
    }
    LINFO << "/data is mounted on " << resolved_block_device;
    for (auto& entry : *fstab) {
        if (entry.mount_point != "/data") {
            continue;
        }
        std::string block_device;
        if (!Readlink(entry.blk_device, &block_device)) {
            LWARNING << "Failed to readlink " << entry.blk_device;
        if (entry.fs_mgr_flags.logical) {
            if (!fs_mgr_update_logical_partition(&entry)) {
                LERROR << "Failed to update logic partition " << entry.blk_device;
                continue;
            }
            block_device = entry.blk_device;
        } else if (!Readlink(entry.blk_device, &block_device)) {
            PWARNING << "Failed to read link " << entry.blk_device;
            block_device = entry.blk_device;
        }
        if (block_device == resolved_block_device) {
        if (std::find(dm_stack.begin(), dm_stack.end(), block_device) != dm_stack.end()) {
            return &entry;
        }
    }
    LERROR << "Didn't find entry that was used to mount /data";
    LERROR << "Didn't find entry that was used to mount /data onto " << mounted_entry.blk_device;
    return nullptr;
}