Helper function to mount snapshot devices in recovery
In recovery the user has the option to mount /system, but when a device
is updating with Virtual A/B, the _b partition may be a snapshot.
This patch introduces a helper function that satisfies the dependency of
setting up the snapshot devices required to mount /system.
Bug: 139157327
Test: manual /system partition mount on VAB device during OTA
Change-Id: I7337bdd38d7016d12d3ee42be1c7893b10e9116d
Signed-off-by: Alessio Balsini <balsini@google.com>
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 5738b96..42db91e 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -74,6 +74,12 @@
bool SourceCopyOperationIsClone(const chromeos_update_engine::InstallOperation& operation);
+enum class CreateResult : unsigned int {
+ ERROR,
+ CREATED,
+ NOT_CREATED,
+};
+
enum class UpdateState : unsigned int {
// No update or merge is in progress.
None,
@@ -239,6 +245,17 @@
// optional callback fires periodically to query progress via GetUpdateState.
bool HandleImminentDataWipe(const std::function<void()>& callback = {});
+ // This method is only allowed in recovery and is used as a helper to
+ // initialize the snapshot devices as a requirement to mount a snapshotted
+ // /system in recovery.
+ // This function returns:
+ // - CreateResult::CREATED if snapshot devices were successfully created;
+ // - CreateResult::NOT_CREATED if it was not necessary to create snapshot
+ // devices;
+ // - CreateResult::ERROR if a fatal error occurred, mounting /system should
+ // be aborted.
+ CreateResult RecoveryCreateSnapshotDevices();
+
// Dump debug information.
bool Dump(std::ostream& os);
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index f38db43..862366b 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -2339,5 +2339,37 @@
return true;
}
+CreateResult SnapshotManager::RecoveryCreateSnapshotDevices() {
+ if (!device_->IsRecovery()) {
+ LOG(ERROR) << __func__ << " is only allowed in recovery.";
+ return CreateResult::NOT_CREATED;
+ }
+
+ auto mount = EnsureMetadataMounted();
+ if (!mount || !mount->HasDevice()) {
+ LOG(ERROR) << "Couldn't mount Metadata.";
+ return CreateResult::NOT_CREATED;
+ }
+
+ auto state_file = GetStateFilePath();
+ if (access(state_file.c_str(), F_OK) != 0 && errno == ENOENT) {
+ LOG(ERROR) << "Couldn't access state file.";
+ return CreateResult::NOT_CREATED;
+ }
+
+ if (!NeedSnapshotsInFirstStageMount()) {
+ return CreateResult::NOT_CREATED;
+ }
+
+ auto slot_suffix = device_->GetOtherSlotSuffix();
+ auto slot_number = SlotNumberForSlotSuffix(slot_suffix);
+ auto super_path = device_->GetSuperDevice(slot_number);
+ if (!CreateLogicalAndSnapshotPartitions(super_path)) {
+ LOG(ERROR) << "Unable to map partitions.";
+ return CreateResult::ERROR;
+ }
+ return CreateResult::CREATED;
+}
+
} // namespace snapshot
} // namespace android