From 01cf85bd8ed786512f546fa86f7d47a83bab09f6 Mon Sep 17 00:00:00 2001 From: LongPing Wei Date: Wed, 9 Jan 2019 20:30:18 +0800 Subject: [PATCH] Support mounting same mount points with different fstab config This commits allows multiple lines in a fstab have the same mount point for first-stage mount, where the first successful mount will be used. This allows us to specify a common/shared fstab, with different settings (e.g., ext4, squashfs) per line, to mount different types of images on the same mount point. e.g., allows the device to mount GSI (ext4) while support mounting the original squashfs system.img. Sample fstab: fstab in dt: android { fstab { odm_ext4 { dev = "/dev/block/by-name/odm"; mnt_point = "/odm"; type = ext4; mnt_flags = "ro"; fs_mgr_flags = "slotselect"; }; odm_f2fs { dev = "/dev/block/by-name/odm"; mnt_point = "/odm"; type = f2fs; mnt_flags = "ro"; fs_mgr_flags = "slotselect"; }; }; } fstab in file: /dev/block/by-name/odm /odm ext4 ro slotselect /dev/block/by-name/odm /odm f2fs ro slotselect Test: make & boot & check /proc/mounts Change-Id: I64892e3007b0cfd7d06dad1cfc664c45305197ee --- init/first_stage_mount.cpp | 61 +++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp index b5ff65867..71fe4010d 100644 --- a/init/first_stage_mount.cpp +++ b/init/first_stage_mount.cpp @@ -414,16 +414,32 @@ bool FirstStageMount::TrySwitchSystemAsRoot() { return entry.mount_point == "/system"; }); - if (system_partition != fstab_.end()) { - if (!MountPartition(&(*system_partition))) { - return false; + if (system_partition == fstab_.end()) return true; + + bool mounted = false; + bool no_fail = false; + for (auto it = system_partition; it != fstab_.end();) { + if (it->mount_point != "/system") { + break; } - - SwitchRoot((*system_partition).mount_point); - - fstab_.erase(system_partition); + no_fail |= (it->fs_mgr_flags).no_fail; + if (MountPartition(&(*it))) { + mounted = true; + SwitchRoot("/system"); + break; + } + it++; } + if (!mounted && !no_fail) { + LOG(ERROR) << "Failed to mount /system"; + return false; + } + + auto it = std::remove_if(fstab_.begin(), fstab_.end(), + [](const auto& entry) { return entry.mount_point == "/system"; }); + fstab_.erase(it, fstab_.end()); + return true; } @@ -444,14 +460,12 @@ bool FirstStageMount::TrySkipMountingPartitions() { if (skip_mount_point.empty()) { continue; } - auto removing_entry = - std::find_if(fstab_.begin(), fstab_.end(), [&skip_mount_point](const auto& entry) { - return entry.mount_point == skip_mount_point; - }); - if (removing_entry != fstab_.end()) { - fstab_.erase(removing_entry); - LOG(INFO) << "Skip mounting partition: " << skip_mount_point; - } + auto it = std::remove_if(fstab_.begin(), fstab_.end(), + [&skip_mount_point](const auto& entry) { + return entry.mount_point == skip_mount_point; + }); + fstab_.erase(it, fstab_.end()); + LOG(INFO) << "Skip mounting partition: " << skip_mount_point; } return true; @@ -462,8 +476,21 @@ bool FirstStageMount::MountPartitions() { if (!TrySkipMountingPartitions()) return false; - for (auto& fstab_entry : fstab_) { - if (!MountPartition(&fstab_entry) && !fstab_entry.fs_mgr_flags.no_fail) { + for (auto it = fstab_.begin(); it != fstab_.end();) { + bool mounted = false; + bool no_fail = false; + auto start_mount_point = it->mount_point; + do { + no_fail |= (it->fs_mgr_flags).no_fail; + if (!mounted) + mounted = MountPartition(&(*it)); + else + LOG(INFO) << "Skip already-mounted partition: " << start_mount_point; + it++; + } while (it != fstab_.end() && it->mount_point == start_mount_point); + + if (!mounted && !no_fail) { + LOG(ERROR) << start_mount_point << " mounted unsuccessfully but it is required!"; return false; } }