From c8edf84d45ca45df6bece19c3aa7eef5338f07c7 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 20 Aug 2019 17:24:18 -0700 Subject: [PATCH] init: Add first-stage init support for snapshot-based partitions. Note that /metadata must now be mounted before CreateLogicalPartitions() is called. This is because SnapshotManager overrides the default partitioning scheme, and the only way to tell if a SnapshotManager is needed is via the metadata partition. Bug: 139204329 Test: manual test Change-Id: I812df6c4c0d4d8753b1516f63dc70c5bc3e1c09c --- init/Android.bp | 1 + init/Android.mk | 1 + init/first_stage_mount.cpp | 34 ++++++++++++++++++++++++---------- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/init/Android.bp b/init/Android.bp index 38d495f4b..6772e58bc 100644 --- a/init/Android.bp +++ b/init/Android.bp @@ -70,6 +70,7 @@ cc_defaults { "libprotobuf-cpp-lite", "libpropertyinfoserializer", "libpropertyinfoparser", + "libsnapshot_nobinder", ], shared_libs: [ "libbacktrace", diff --git a/init/Android.mk b/init/Android.mk index 006e1bfaa..d7258a794 100644 --- a/init/Android.mk +++ b/init/Android.mk @@ -114,6 +114,7 @@ LOCAL_STATIC_LIBRARIES := \ libbacktrace \ libmodprobe \ libext2_uuid \ + libsnapshot_nobinder \ LOCAL_SANITIZE := signed-integer-overflow # First stage init is weird: it may start without stdout/stderr, and no /proc. diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp index dffd6af00..6b4216fe4 100644 --- a/init/first_stage_mount.cpp +++ b/init/first_stage_mount.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include "devices.h" #include "switch_root.h" @@ -55,6 +56,7 @@ using android::fs_mgr::FstabEntry; using android::fs_mgr::ReadDefaultFstab; using android::fs_mgr::ReadFstabFromDt; using android::fs_mgr::SkipMountingPartitions; +using android::snapshot::SnapshotManager; using namespace std::literals; @@ -244,8 +246,6 @@ bool FirstStageMount::DoFirstStageMount() { if (!InitDevices()) return false; - if (!CreateLogicalPartitions()) return false; - if (!MountPartitions()) return false; return true; @@ -366,6 +366,16 @@ bool FirstStageMount::CreateLogicalPartitions() { return false; } + if (SnapshotManager::IsSnapshotManagerNeeded()) { + auto sm = SnapshotManager::NewForFirstStageMount(); + if (!sm) { + return false; + } + if (sm->NeedSnapshotsInFirstStageMount()) { + return sm->CreateLogicalAndSnapshotPartitions(lp_metadata_partition_); + } + } + auto metadata = android::fs_mgr::ReadCurrentMetadata(lp_metadata_partition_); if (!metadata) { LOG(ERROR) << "Could not read logical partition metadata from " << lp_metadata_partition_; @@ -493,14 +503,7 @@ bool FirstStageMount::MountPartition(const Fstab::iterator& begin, bool erase_sa // this case, we mount system first then pivot to it. From that point on, // we are effectively identical to a system-as-root device. bool FirstStageMount::TrySwitchSystemAsRoot() { - auto metadata_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) { - return entry.mount_point == "/metadata"; - }); - if (metadata_partition != fstab_.end()) { - if (MountPartition(metadata_partition, true /* erase_same_mounts */)) { - UseGsiIfPresent(); - } - } + UseGsiIfPresent(); auto system_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) { return entry.mount_point == "/system"; @@ -523,6 +526,17 @@ bool FirstStageMount::TrySwitchSystemAsRoot() { } bool FirstStageMount::MountPartitions() { + // Mount /metadata before creating logical partitions, since we need to + // know whether a snapshot merge is in progress. + auto metadata_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) { + return entry.mount_point == "/metadata"; + }); + if (metadata_partition != fstab_.end()) { + MountPartition(metadata_partition, true /* erase_same_mounts */); + } + + if (!CreateLogicalPartitions()) return false; + if (!TrySwitchSystemAsRoot()) return false; if (!SkipMountingPartitions(&fstab_)) return false;