Loading fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +7 −1 Original line number Diff line number Diff line Loading @@ -142,7 +142,9 @@ class SnapshotManager final { // be created, and the device must either cancel the OTA (either before // rebooting or after rolling back), or merge the OTA. // Before calling this function, all snapshots must be mapped. bool FinishedSnapshotWrites(); // If |wipe| is set to true, wipe is scheduled after reboot, and snapshots // may need to be merged before wiping. bool FinishedSnapshotWrites(bool wipe); // Initiate a merge on all snapshot devices. This should only be used after an // update has been marked successful after booting. Loading Loading @@ -523,6 +525,10 @@ class SnapshotManager final { bool ShouldDeleteSnapshot(LockedFile* lock, const std::map<std::string, bool>& flashing_status, Slot current_slot, const std::string& name); // Create or delete forward merge indicator given |wipe|. Iff wipe is scheduled, // allow forward merge on FDR. bool UpdateForwardMergeIndicator(bool wipe); std::string gsid_dir_; std::string metadata_dir_; std::unique_ptr<IDeviceInfo> device_; Loading fs_mgr/libsnapshot/snapshot.cpp +19 −1 Original line number Diff line number Diff line Loading @@ -248,7 +248,7 @@ bool SnapshotManager::RemoveAllUpdateState(LockedFile* lock, const std::function return WriteUpdateState(lock, UpdateState::None); } bool SnapshotManager::FinishedSnapshotWrites() { bool SnapshotManager::FinishedSnapshotWrites(bool wipe) { auto lock = LockExclusive(); if (!lock) return false; Loading @@ -268,6 +268,10 @@ bool SnapshotManager::FinishedSnapshotWrites() { return false; } if (!UpdateForwardMergeIndicator(wipe)) { return false; } // This file is written on boot to detect whether a rollback occurred. It // MUST NOT exist before rebooting, otherwise, we're at risk of deleting // snapshots too early. Loading Loading @@ -2638,5 +2642,19 @@ CreateResult SnapshotManager::RecoveryCreateSnapshotDevices( return CreateResult::CREATED; } bool SnapshotManager::UpdateForwardMergeIndicator(bool wipe) { if (!wipe) { return RemoveFileIfExists(path); } LOG(INFO) << "Wipe will be scheduled. Allowing forward merge of snapshots."; if (!android::base::WriteStringToFile("1", path)) { PLOG(ERROR) << "Unable to write forward merge indicator: " << path; return false; } return true; } } // namespace snapshot } // namespace android fs_mgr/libsnapshot/snapshot_test.cpp +16 −16 Original line number Diff line number Diff line Loading @@ -320,7 +320,7 @@ class SnapshotTest : public ::testing::Test { // Simulate a reboot into the new slot. AssertionResult SimulateReboot() { lock_ = nullptr; if (!sm->FinishedSnapshotWrites()) { if (!sm->FinishedSnapshotWrites(false)) { return AssertionFailure(); } if (!dm_.DeleteDevice("test_partition_b")) { Loading Loading @@ -424,7 +424,7 @@ TEST_F(SnapshotTest, MapPartialSnapshot) { } TEST_F(SnapshotTest, NoMergeBeforeReboot) { ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Merge should fail, since the slot hasn't changed. ASSERT_FALSE(sm->InitiateMerge()); Loading @@ -440,7 +440,7 @@ TEST_F(SnapshotTest, CleanFirstStageMount) { } TEST_F(SnapshotTest, FirstStageMountAfterRollback) { ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // We didn't change the slot, so we shouldn't need snapshots. TestDeviceInfo* info = new TestDeviceInfo(fake_super); Loading Loading @@ -476,7 +476,7 @@ TEST_F(SnapshotTest, Merge) { lock_ = nullptr; // Done updating. ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); test_device->set_slot_suffix("_b"); ASSERT_TRUE(sm->InitiateMerge()); Loading Loading @@ -1007,7 +1007,7 @@ TEST_F(SnapshotUpdateTest, FullUpdateFlow) { ASSERT_TRUE(IsPartitionUnchanged(name)); } ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading Loading @@ -1139,7 +1139,7 @@ TEST_F(SnapshotUpdateTest, TestRollback) { ASSERT_TRUE(IsPartitionUnchanged(name)); } ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading Loading @@ -1171,7 +1171,7 @@ TEST_F(SnapshotUpdateTest, TestRollback) { // Test that if an update is applied but not booted into, it can be canceled. TEST_F(SnapshotUpdateTest, CancelAfterApply) { ASSERT_TRUE(sm->BeginUpdate()); ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); ASSERT_TRUE(sm->CancelUpdate()); } Loading @@ -1188,7 +1188,7 @@ TEST_F(SnapshotUpdateTest, ReclaimCow) { ASSERT_TRUE(sm->BeginUpdate()); ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_)); ASSERT_TRUE(MapUpdateSnapshots()); ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading Loading @@ -1295,7 +1295,7 @@ TEST_F(SnapshotUpdateTest, RetrofitAfterRegularAb) { ASSERT_TRUE(IsPartitionUnchanged(name)); } ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); } TEST_F(SnapshotUpdateTest, MergeCannotRemoveCow) { Loading Loading @@ -1324,7 +1324,7 @@ TEST_F(SnapshotUpdateTest, MergeCannotRemoveCow) { ASSERT_TRUE(sm->BeginUpdate()); ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_)); ASSERT_TRUE(MapUpdateSnapshots()); ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading Loading @@ -1428,7 +1428,7 @@ TEST_F(SnapshotUpdateTest, MergeInRecovery) { ASSERT_TRUE(sm->BeginUpdate()); ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_)); ASSERT_TRUE(MapUpdateSnapshots()); ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading Loading @@ -1460,7 +1460,7 @@ TEST_F(SnapshotUpdateTest, DataWipeRollbackInRecovery) { ASSERT_TRUE(sm->BeginUpdate()); ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_)); ASSERT_TRUE(MapUpdateSnapshots()); ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading @@ -1485,7 +1485,7 @@ TEST_F(SnapshotUpdateTest, DataWipeAfterRollback) { ASSERT_TRUE(sm->BeginUpdate()); ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_)); ASSERT_TRUE(MapUpdateSnapshots()); ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading Loading @@ -1533,7 +1533,7 @@ TEST_F(SnapshotUpdateTest, Hashtree) { ASSERT_TRUE(WriteSnapshotAndHash("sys_b", partition_size)); // Finish update. ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading Loading @@ -1569,7 +1569,7 @@ TEST_F(SnapshotUpdateTest, Overflow) { ASSERT_EQ(1u, table.size()); EXPECT_TRUE(table[0].IsOverflowSnapshot()); ASSERT_FALSE(sm->FinishedSnapshotWrites()) ASSERT_FALSE(sm->FinishedSnapshotWrites(false)) << "FinishedSnapshotWrites should detect overflow of CoW device."; } Loading Loading @@ -1623,7 +1623,7 @@ TEST_P(FlashAfterUpdateTest, FlashSlotAfterUpdate) { ASSERT_TRUE(sm->BeginUpdate()); ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_)); ASSERT_TRUE(MapUpdateSnapshots()); ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading Loading
fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +7 −1 Original line number Diff line number Diff line Loading @@ -142,7 +142,9 @@ class SnapshotManager final { // be created, and the device must either cancel the OTA (either before // rebooting or after rolling back), or merge the OTA. // Before calling this function, all snapshots must be mapped. bool FinishedSnapshotWrites(); // If |wipe| is set to true, wipe is scheduled after reboot, and snapshots // may need to be merged before wiping. bool FinishedSnapshotWrites(bool wipe); // Initiate a merge on all snapshot devices. This should only be used after an // update has been marked successful after booting. Loading Loading @@ -523,6 +525,10 @@ class SnapshotManager final { bool ShouldDeleteSnapshot(LockedFile* lock, const std::map<std::string, bool>& flashing_status, Slot current_slot, const std::string& name); // Create or delete forward merge indicator given |wipe|. Iff wipe is scheduled, // allow forward merge on FDR. bool UpdateForwardMergeIndicator(bool wipe); std::string gsid_dir_; std::string metadata_dir_; std::unique_ptr<IDeviceInfo> device_; Loading
fs_mgr/libsnapshot/snapshot.cpp +19 −1 Original line number Diff line number Diff line Loading @@ -248,7 +248,7 @@ bool SnapshotManager::RemoveAllUpdateState(LockedFile* lock, const std::function return WriteUpdateState(lock, UpdateState::None); } bool SnapshotManager::FinishedSnapshotWrites() { bool SnapshotManager::FinishedSnapshotWrites(bool wipe) { auto lock = LockExclusive(); if (!lock) return false; Loading @@ -268,6 +268,10 @@ bool SnapshotManager::FinishedSnapshotWrites() { return false; } if (!UpdateForwardMergeIndicator(wipe)) { return false; } // This file is written on boot to detect whether a rollback occurred. It // MUST NOT exist before rebooting, otherwise, we're at risk of deleting // snapshots too early. Loading Loading @@ -2638,5 +2642,19 @@ CreateResult SnapshotManager::RecoveryCreateSnapshotDevices( return CreateResult::CREATED; } bool SnapshotManager::UpdateForwardMergeIndicator(bool wipe) { if (!wipe) { return RemoveFileIfExists(path); } LOG(INFO) << "Wipe will be scheduled. Allowing forward merge of snapshots."; if (!android::base::WriteStringToFile("1", path)) { PLOG(ERROR) << "Unable to write forward merge indicator: " << path; return false; } return true; } } // namespace snapshot } // namespace android
fs_mgr/libsnapshot/snapshot_test.cpp +16 −16 Original line number Diff line number Diff line Loading @@ -320,7 +320,7 @@ class SnapshotTest : public ::testing::Test { // Simulate a reboot into the new slot. AssertionResult SimulateReboot() { lock_ = nullptr; if (!sm->FinishedSnapshotWrites()) { if (!sm->FinishedSnapshotWrites(false)) { return AssertionFailure(); } if (!dm_.DeleteDevice("test_partition_b")) { Loading Loading @@ -424,7 +424,7 @@ TEST_F(SnapshotTest, MapPartialSnapshot) { } TEST_F(SnapshotTest, NoMergeBeforeReboot) { ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Merge should fail, since the slot hasn't changed. ASSERT_FALSE(sm->InitiateMerge()); Loading @@ -440,7 +440,7 @@ TEST_F(SnapshotTest, CleanFirstStageMount) { } TEST_F(SnapshotTest, FirstStageMountAfterRollback) { ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // We didn't change the slot, so we shouldn't need snapshots. TestDeviceInfo* info = new TestDeviceInfo(fake_super); Loading Loading @@ -476,7 +476,7 @@ TEST_F(SnapshotTest, Merge) { lock_ = nullptr; // Done updating. ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); test_device->set_slot_suffix("_b"); ASSERT_TRUE(sm->InitiateMerge()); Loading Loading @@ -1007,7 +1007,7 @@ TEST_F(SnapshotUpdateTest, FullUpdateFlow) { ASSERT_TRUE(IsPartitionUnchanged(name)); } ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading Loading @@ -1139,7 +1139,7 @@ TEST_F(SnapshotUpdateTest, TestRollback) { ASSERT_TRUE(IsPartitionUnchanged(name)); } ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading Loading @@ -1171,7 +1171,7 @@ TEST_F(SnapshotUpdateTest, TestRollback) { // Test that if an update is applied but not booted into, it can be canceled. TEST_F(SnapshotUpdateTest, CancelAfterApply) { ASSERT_TRUE(sm->BeginUpdate()); ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); ASSERT_TRUE(sm->CancelUpdate()); } Loading @@ -1188,7 +1188,7 @@ TEST_F(SnapshotUpdateTest, ReclaimCow) { ASSERT_TRUE(sm->BeginUpdate()); ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_)); ASSERT_TRUE(MapUpdateSnapshots()); ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading Loading @@ -1295,7 +1295,7 @@ TEST_F(SnapshotUpdateTest, RetrofitAfterRegularAb) { ASSERT_TRUE(IsPartitionUnchanged(name)); } ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); } TEST_F(SnapshotUpdateTest, MergeCannotRemoveCow) { Loading Loading @@ -1324,7 +1324,7 @@ TEST_F(SnapshotUpdateTest, MergeCannotRemoveCow) { ASSERT_TRUE(sm->BeginUpdate()); ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_)); ASSERT_TRUE(MapUpdateSnapshots()); ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading Loading @@ -1428,7 +1428,7 @@ TEST_F(SnapshotUpdateTest, MergeInRecovery) { ASSERT_TRUE(sm->BeginUpdate()); ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_)); ASSERT_TRUE(MapUpdateSnapshots()); ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading Loading @@ -1460,7 +1460,7 @@ TEST_F(SnapshotUpdateTest, DataWipeRollbackInRecovery) { ASSERT_TRUE(sm->BeginUpdate()); ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_)); ASSERT_TRUE(MapUpdateSnapshots()); ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading @@ -1485,7 +1485,7 @@ TEST_F(SnapshotUpdateTest, DataWipeAfterRollback) { ASSERT_TRUE(sm->BeginUpdate()); ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_)); ASSERT_TRUE(MapUpdateSnapshots()); ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading Loading @@ -1533,7 +1533,7 @@ TEST_F(SnapshotUpdateTest, Hashtree) { ASSERT_TRUE(WriteSnapshotAndHash("sys_b", partition_size)); // Finish update. ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading Loading @@ -1569,7 +1569,7 @@ TEST_F(SnapshotUpdateTest, Overflow) { ASSERT_EQ(1u, table.size()); EXPECT_TRUE(table[0].IsOverflowSnapshot()); ASSERT_FALSE(sm->FinishedSnapshotWrites()) ASSERT_FALSE(sm->FinishedSnapshotWrites(false)) << "FinishedSnapshotWrites should detect overflow of CoW device."; } Loading Loading @@ -1623,7 +1623,7 @@ TEST_P(FlashAfterUpdateTest, FlashSlotAfterUpdate) { ASSERT_TRUE(sm->BeginUpdate()); ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_)); ASSERT_TRUE(MapUpdateSnapshots()); ASSERT_TRUE(sm->FinishedSnapshotWrites()); ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); Loading