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
diff --git a/init/Android.bp b/init/Android.bp
index 38d495f..6772e58 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -70,6 +70,7 @@
"libprotobuf-cpp-lite",
"libpropertyinfoserializer",
"libpropertyinfoparser",
+ "libsnapshot_nobinder",
],
shared_libs: [
"libbacktrace",
diff --git a/init/Android.mk b/init/Android.mk
index 006e1bf..d7258a7 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -114,6 +114,7 @@
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 dffd6af..6b4216f 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -36,6 +36,7 @@
#include <fs_mgr_overlayfs.h>
#include <libgsi/libgsi.h>
#include <liblp/liblp.h>
+#include <libsnapshot/snapshot.h>
#include "devices.h"
#include "switch_root.h"
@@ -55,6 +56,7 @@
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 @@
if (!InitDevices()) return false;
- if (!CreateLogicalPartitions()) return false;
-
if (!MountPartitions()) return false;
return true;
@@ -366,6 +366,16 @@
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 @@
// 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::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;