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

Commit 80281894 authored by Bowgo Tsai's avatar Bowgo Tsai
Browse files

first stage mount: support mount points like /vendor/abc

Current syntax of the fstab in device tree (fstab_dt) assumes the
node name is the mount point, which doesn't allow subdir:

    vendor {   <== using "vendor/abc" leads to syntax error in device tree
        compatible = "android,vendor";
        dev = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor";
        type = "ext4";
        mnt_flags = "ro,barrier=1,inode_readahead_blks=8";
        fsmgr_flags = "wait";
    };

This CL adds a new field "mnt_point" in the fstab_dt configuration:

    vendor_abc {
        compatible = "android,vendor_abc";
        dev = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/abc";
        type = "ext4";
        mnt_flags = "ro,barrier=1,inode_readahead_blks=8";
        mnt_point = "/vendor/abc";                          <== new field
        fsmgr_flags = "wait";
    };

The new field is optional and will fallback to using node name as mount
point if it is absent.

Note that this CL also sorts fstab_dt by mount point, because
/vendor needs to be mounted first, which contains a directory
/vendor/abc, before /vendor/abc can be mounted.

Bug: 69955336
Test: first stage mount /vendor/abc on a device
Change-Id: Ie2e519f9801f211a7a221622f32c82bedd00353f
parent a7e2a12d
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -25,6 +25,9 @@ cc_defaults {
        "-Werror",
        "-Wno-unused-variable",
    ],
    cppflags: [
        "-std=gnu++1z",
    ],
}

cc_library_static {
+34 −16
Original line number Diff line number Diff line
@@ -23,6 +23,10 @@
#include <sys/mount.h>
#include <unistd.h>

#include <algorithm>
#include <utility>
#include <vector>

#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -397,16 +401,17 @@ static bool is_dt_fstab_compatible() {
}

static std::string read_fstab_from_dt() {
    std::string fstab;
    if (!is_dt_compatible() || !is_dt_fstab_compatible()) {
        return fstab;
        return {};
    }

    std::string fstabdir_name = get_android_dt_dir() + "/fstab";
    std::unique_ptr<DIR, int (*)(DIR*)> fstabdir(opendir(fstabdir_name.c_str()), closedir);
    if (!fstabdir) return fstab;
    if (!fstabdir) return {};

    dirent* dp;
    // Each element in fstab_dt_entries is <mount point, the line format in fstab file>.
    std::vector<std::pair<std::string, std::string>> fstab_dt_entries;
    while ((dp = readdir(fstabdir.get())) != NULL) {
        // skip over name, compatible and .
        if (dp->d_type != DT_DIR || dp->d_name[0] == '.') continue;
@@ -427,41 +432,54 @@ static std::string read_fstab_from_dt() {
        file_name = android::base::StringPrintf("%s/%s/dev", fstabdir_name.c_str(), dp->d_name);
        if (!read_dt_file(file_name, &value)) {
            LERROR << "dt_fstab: Failed to find device for partition " << dp->d_name;
            fstab.clear();
            break;
            return {};
        }
        fstab_entry.push_back(value);
        fstab_entry.push_back(android::base::StringPrintf("/%s", dp->d_name));

        std::string mount_point;
        file_name =
            android::base::StringPrintf("%s/%s/mnt_point", fstabdir_name.c_str(), dp->d_name);
        if (read_dt_file(file_name, &value)) {
            LINFO << "dt_fstab: Using a specified mount point " << value << " for " << dp->d_name;
            mount_point = value;
        } else {
            mount_point = android::base::StringPrintf("/%s", dp->d_name);
        }
        fstab_entry.push_back(mount_point);

        file_name = android::base::StringPrintf("%s/%s/type", fstabdir_name.c_str(), dp->d_name);
        if (!read_dt_file(file_name, &value)) {
            LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
            fstab.clear();
            break;
            return {};
        }
        fstab_entry.push_back(value);

        file_name = android::base::StringPrintf("%s/%s/mnt_flags", fstabdir_name.c_str(), dp->d_name);
        if (!read_dt_file(file_name, &value)) {
            LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
            fstab.clear();
            break;
            return {};
        }
        fstab_entry.push_back(value);

        file_name = android::base::StringPrintf("%s/%s/fsmgr_flags", fstabdir_name.c_str(), dp->d_name);
        if (!read_dt_file(file_name, &value)) {
            LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
            fstab.clear();
            break;
            return {};
        }
        fstab_entry.push_back(value);

        fstab += android::base::Join(fstab_entry, " ");
        fstab += '\n';
        // Adds a fstab_entry to fstab_dt_entries, to be sorted by mount_point later.
        fstab_dt_entries.emplace_back(mount_point, android::base::Join(fstab_entry, " "));
    }

    return fstab;
    // Sort fstab_dt entries, to ensure /vendor is mounted before /vendor/abc is attempted.
    std::sort(fstab_dt_entries.begin(), fstab_dt_entries.end(),
              [](const auto& a, const auto& b) { return a.first < b.first; });

    std::string fstab_result;
    for (const auto& [_, dt_entry] : fstab_dt_entries) {
        fstab_result += dt_entry + "\n";
    }
    return fstab_result;
}

bool is_dt_compatible() {