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

Commit 3fff9fbe authored by Yifan Hong's avatar Yifan Hong Committed by Gerrit Code Review
Browse files

Merge changes from topic "vintf_object_recovery_mount"

* changes:
  Move parts of roots.cpp from librecovery
  fs_mgr_do_mount_one: allow overriding mount_point
parents 38ff8081 bf80e7dd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ cc_library {
        "fs_mgr_verity.cpp",
        "fs_mgr_dm_linear.cpp",
        "fs_mgr_overlayfs.cpp",
        "fs_mgr_roots.cpp",
        "fs_mgr_vendor_overlay.cpp",
    ],
    shared_libs: [
+3 −2
Original line number Diff line number Diff line
@@ -1179,11 +1179,12 @@ int fs_mgr_mount_all(Fstab* fstab, int mount_mode) {

// wrapper to __mount() and expects a fully prepared fstab_rec,
// unlike fs_mgr_do_mount which does more things with avb / verity etc.
int fs_mgr_do_mount_one(const FstabEntry& entry) {
int fs_mgr_do_mount_one(const FstabEntry& entry, const std::string& mount_point) {
    // Run fsck if needed
    prepare_fs_for_mount(entry.blk_device, entry);

    int ret = __mount(entry.blk_device, entry.mount_point, entry);
    int ret =
            __mount(entry.blk_device, mount_point.empty() ? entry.mount_point : mount_point, entry);
    if (ret) {
      ret = (errno == EBUSY) ? FS_MGR_DOMNT_BUSY : FS_MGR_DOMNT_FAILED;
    }
+195 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "fs_mgr/roots.h"

#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <string>

#include "fs_mgr.h"
#include "fs_mgr_dm_linear.h"
#include "fs_mgr_priv.h"

namespace android {
namespace fs_mgr {

static constexpr const char* kSystemRoot = "/system";

static bool gDidMapLogicalPartitions = false;

FstabEntry* GetEntryForPath(Fstab* fstab, const std::string& path) {
    if (path.empty()) return nullptr;
    std::string str(path);
    while (true) {
        auto it = std::find_if(fstab->begin(), fstab->end(),
                               [&str](const auto& entry) { return entry.mount_point == str; });
        if (it != fstab->end()) return &*it;
        if (str == "/") break;
        auto slash = str.find_last_of('/');
        if (slash == std::string::npos) break;
        if (slash == 0) {
            str = "/";
        } else {
            str = str.substr(0, slash);
        }
    }
    return nullptr;
}

enum class MountState {
    ERROR = -1,
    NOT_MOUNTED = 0,
    MOUNTED = 1,
};

static MountState GetMountState(const std::string& mount_point) {
    Fstab mounted_fstab;
    if (!ReadFstabFromFile("/proc/mounts", &mounted_fstab)) {
        LERROR << "Failed to scan mounted volumes";
        return MountState::ERROR;
    }

    auto mv = std::find_if(
            mounted_fstab.begin(), mounted_fstab.end(),
            [&mount_point](const auto& entry) { return entry.mount_point == mount_point; });
    if (mv != mounted_fstab.end()) {
        return MountState::MOUNTED;
    }
    return MountState::NOT_MOUNTED;
}

bool EnsurePathMounted(Fstab* fstab, const std::string& path, const std::string& mount_pt) {
    auto rec = GetEntryForPath(fstab, path);
    if (rec == nullptr) {
        LERROR << "unknown volume for path [" << path << "]";
        return false;
    }
    if (rec->fs_type == "ramdisk") {
        // The ramdisk is always mounted.
        return true;
    }

    // If we can't acquire the block device for a logical partition, it likely
    // was never created. In that case we try to create it.
    if (rec->fs_mgr_flags.logical && !fs_mgr_update_logical_partition(rec)) {
        if (gDidMapLogicalPartitions) {
            LERROR << "Failed to find block device for partition";
            return false;
        }
        std::string super_name = fs_mgr_get_super_partition_name();
        if (!android::fs_mgr::CreateLogicalPartitions("/dev/block/by-name/" + super_name)) {
            LERROR << "Failed to create logical partitions";
            return false;
        }
        gDidMapLogicalPartitions = true;
        if (!fs_mgr_update_logical_partition(rec)) {
            LERROR << "Failed to find block device for partition";
            return false;
        }
    }

    auto mounted = GetMountState(rec->mount_point);
    if (mounted == MountState::ERROR) {
        return false;
    }
    if (mounted == MountState::MOUNTED) {
        return true;
    }

    const std::string mount_point = mount_pt.empty() ? rec->mount_point : mount_pt;

    static const std::vector<std::string> supported_fs{"ext4", "squashfs", "vfat", "f2fs"};
    if (std::find(supported_fs.begin(), supported_fs.end(), rec->fs_type) == supported_fs.end()) {
        LERROR << "unknown fs_type \"" << rec->fs_type << "\" for " << mount_point;
        return false;
    }

    int result = fs_mgr_do_mount_one(*rec, mount_point);
    if (result == -1 && rec->fs_mgr_flags.formattable) {
        PERROR << "Failed to mount " << mount_point << "; formatting";
        bool crypt_footer = rec->is_encryptable() && rec->key_loc == "footer";
        if (fs_mgr_do_format(*rec, crypt_footer) != 0) {
            PERROR << "Failed to format " << mount_point;
            return false;
        }
        result = fs_mgr_do_mount_one(*rec, mount_point);
    }

    if (result == -1) {
        PERROR << "Failed to mount " << mount_point;
        return false;
    }
    return true;
}

bool EnsurePathUnmounted(Fstab* fstab, const std::string& path) {
    auto rec = GetEntryForPath(fstab, path);
    if (rec == nullptr) {
        LERROR << "unknown volume for path [" << path << "]";
        return false;
    }
    if (rec->fs_type == "ramdisk") {
        // The ramdisk is always mounted; you can't unmount it.
        return false;
    }

    Fstab mounted_fstab;
    if (!ReadFstabFromFile("/proc/mounts", &mounted_fstab)) {
        LERROR << "Failed to scan mounted volumes";
        return false;
    }

    auto mounted = GetMountState(rec->mount_point);
    if (mounted == MountState::ERROR) {
        return false;
    }
    if (mounted == MountState::NOT_MOUNTED) {
        return true;
    }

    int result = umount(rec->mount_point.c_str());
    if (result == -1) {
        PWARNING << "Failed to umount " << rec->mount_point;
        return false;
    }
    return true;
}

std::string GetSystemRoot() {
    Fstab fstab;
    if (!ReadDefaultFstab(&fstab)) {
        LERROR << "Failed to read default fstab";
        return "";
    }

    auto it = std::find_if(fstab.begin(), fstab.end(),
                           [](const auto& entry) { return entry.mount_point == kSystemRoot; });
    if (it == fstab.end()) {
        return "/";
    }

    return kSystemRoot;
}

bool LogicalPartitionsMapped() {
    return gDidMapLogicalPartitions;
}

}  // namespace fs_mgr
}  // namespace android
+1 −1
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@ int fs_mgr_mount_all(Fstab* fstab, int mount_mode);
int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point);
int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
                    bool need_cp);
int fs_mgr_do_mount_one(const FstabEntry& entry);
int fs_mgr_do_mount_one(const FstabEntry& entry, const std::string& mount_point = "");
int fs_mgr_do_mount_one(fstab_rec* rec);
int fs_mgr_do_tmpfs_mount(const char *n_name);
fstab_rec const* fs_mgr_get_crypt_entry(fstab const* fstab);
+52 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <string>

#include <fs_mgr.h>

namespace android {
namespace fs_mgr {

// Finds the volume specified by the given path. fs_mgr_get_entry_for_mount_point() does exact match
// only, so it attempts the prefixes recursively (e.g. "/cache/recovery/last_log",
// "/cache/recovery", "/cache", "/" for a given path of "/cache/recovery/last_log") and returns the
// first match or nullptr.
FstabEntry* GetEntryForPath(Fstab* fstab, const std::string& path);

// Make sure that the volume 'path' is on is mounted.
// * If 'mount_point' is nullptr, use mount point in fstab. Caller can call
//   fs_mgr_ensure_path_unmounted() with the same 'path' argument to unmount.
// * If 'mount_point' is not nullptr, the mount point is overridden. Caller can
//   call umount(mount_point) to unmount.
// Returns true on success (volume is mounted).
bool EnsurePathMounted(Fstab* fstab, const std::string& path, const std::string& mount_point = "");

// Make sure that the volume 'path' is on is unmounted.  Returns true on
// success (volume is unmounted).
bool EnsurePathUnmounted(Fstab* fstab, const std::string& path);

// Return "/system" if it is in default fstab, otherwise "/".
std::string GetSystemRoot();

// Return true iff logical partitions are mapped when partitions are mounted via ensure_path_mounted
// functions.
bool LogicalPartitionsMapped();

}  // namespace fs_mgr
}  // namespace android