Loading fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +1 −0 Original line number Diff line number Diff line Loading @@ -399,6 +399,7 @@ class SnapshotManager final : public ISnapshotManager { FRIEND_TEST(SnapshotTest, MergeFailureCode); FRIEND_TEST(SnapshotTest, NoMergeBeforeReboot); FRIEND_TEST(SnapshotTest, UpdateBootControlHal); FRIEND_TEST(SnapshotUpdateTest, AddPartition); FRIEND_TEST(SnapshotUpdateTest, DaemonTransition); FRIEND_TEST(SnapshotUpdateTest, DataWipeAfterRollback); FRIEND_TEST(SnapshotUpdateTest, DataWipeRollbackInRecovery); Loading fs_mgr/libsnapshot/snapshot.cpp +11 −7 Original line number Diff line number Diff line Loading @@ -2087,6 +2087,7 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock, if (live_snapshot_status->compression_enabled()) { // Get the source device (eg the view of the partition from before it was resized). std::string source_device_path; if (live_snapshot_status->old_partition_size() > 0) { if (!MapSourceDevice(lock, params.GetPartitionName(), remaining_time, &source_device_path)) { LOG(ERROR) << "Could not map source device for: " << cow_name; Loading @@ -2095,6 +2096,9 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock, auto source_device = GetSourceDeviceName(params.GetPartitionName()); created_devices.EmplaceBack<AutoUnmapDevice>(&dm, source_device); } else { source_device_path = base_path; } if (!WaitForDevice(source_device_path, remaining_time)) { return false; Loading fs_mgr/libsnapshot/snapshot_test.cpp +65 −1 Original line number Diff line number Diff line Loading @@ -963,7 +963,7 @@ class SnapshotUpdateTest : public SnapshotTest { } AssertionResult UnmapAll() { for (const auto& name : {"sys", "vnd", "prd"}) { for (const auto& name : {"sys", "vnd", "prd", "dlkm"}) { if (!dm_.DeleteDeviceIfExists(name + "_a"s)) { return AssertionFailure() << "Cannot unmap " << name << "_a"; } Loading Loading @@ -2073,6 +2073,70 @@ TEST_F(SnapshotUpdateTest, LowSpace) { ASSERT_LT(res.required_size(), 40_MiB); } TEST_F(SnapshotUpdateTest, AddPartition) { // OTA client blindly unmaps all partitions that are possibly mapped. for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) { ASSERT_TRUE(sm->UnmapUpdateSnapshot(name)); } group_->add_partition_names("dlkm"); auto dlkm = manifest_.add_partitions(); dlkm->set_partition_name("dlkm"); dlkm->set_estimate_cow_size(2_MiB); SetSize(dlkm, 3_MiB); // Grow all partitions. Set |prd| large enough that |sys| and |vnd|'s COWs // fit in super, but not |prd|. constexpr uint64_t partition_size = 3788_KiB; SetSize(sys_, partition_size); SetSize(vnd_, partition_size); SetSize(prd_, partition_size); SetSize(dlkm, partition_size); AddOperationForPartitions({sys_, vnd_, prd_, dlkm}); // Execute the update. ASSERT_TRUE(sm->BeginUpdate()); ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_)); // Write some data to target partitions. for (const auto& name : {"sys_b", "vnd_b", "prd_b", "dlkm_b"}) { ASSERT_TRUE(WriteSnapshotAndHash(name)); } // Assert that source partitions aren't affected. for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) { ASSERT_TRUE(IsPartitionUnchanged(name)); } ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); // After reboot, init does first stage mount. auto init = NewManagerForFirstStageMount("_b"); ASSERT_NE(init, nullptr); ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount()); ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_)); // Check that the target partitions have the same content. for (const auto& name : {"sys_b", "vnd_b", "prd_b", "dlkm_b"}) { ASSERT_TRUE(IsPartitionUnchanged(name)); } // Initiate the merge and wait for it to be completed. ASSERT_TRUE(init->InitiateMerge()); ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState()); // Check that the target partitions have the same content after the merge. for (const auto& name : {"sys_b", "vnd_b", "prd_b", "dlkm_b"}) { ASSERT_TRUE(IsPartitionUnchanged(name)) << "Content of " << name << " changes after the merge"; } } class AutoKill final { public: explicit AutoKill(pid_t pid) : pid_(pid) {} Loading Loading
fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +1 −0 Original line number Diff line number Diff line Loading @@ -399,6 +399,7 @@ class SnapshotManager final : public ISnapshotManager { FRIEND_TEST(SnapshotTest, MergeFailureCode); FRIEND_TEST(SnapshotTest, NoMergeBeforeReboot); FRIEND_TEST(SnapshotTest, UpdateBootControlHal); FRIEND_TEST(SnapshotUpdateTest, AddPartition); FRIEND_TEST(SnapshotUpdateTest, DaemonTransition); FRIEND_TEST(SnapshotUpdateTest, DataWipeAfterRollback); FRIEND_TEST(SnapshotUpdateTest, DataWipeRollbackInRecovery); Loading
fs_mgr/libsnapshot/snapshot.cpp +11 −7 Original line number Diff line number Diff line Loading @@ -2087,6 +2087,7 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock, if (live_snapshot_status->compression_enabled()) { // Get the source device (eg the view of the partition from before it was resized). std::string source_device_path; if (live_snapshot_status->old_partition_size() > 0) { if (!MapSourceDevice(lock, params.GetPartitionName(), remaining_time, &source_device_path)) { LOG(ERROR) << "Could not map source device for: " << cow_name; Loading @@ -2095,6 +2096,9 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock, auto source_device = GetSourceDeviceName(params.GetPartitionName()); created_devices.EmplaceBack<AutoUnmapDevice>(&dm, source_device); } else { source_device_path = base_path; } if (!WaitForDevice(source_device_path, remaining_time)) { return false; Loading
fs_mgr/libsnapshot/snapshot_test.cpp +65 −1 Original line number Diff line number Diff line Loading @@ -963,7 +963,7 @@ class SnapshotUpdateTest : public SnapshotTest { } AssertionResult UnmapAll() { for (const auto& name : {"sys", "vnd", "prd"}) { for (const auto& name : {"sys", "vnd", "prd", "dlkm"}) { if (!dm_.DeleteDeviceIfExists(name + "_a"s)) { return AssertionFailure() << "Cannot unmap " << name << "_a"; } Loading Loading @@ -2073,6 +2073,70 @@ TEST_F(SnapshotUpdateTest, LowSpace) { ASSERT_LT(res.required_size(), 40_MiB); } TEST_F(SnapshotUpdateTest, AddPartition) { // OTA client blindly unmaps all partitions that are possibly mapped. for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) { ASSERT_TRUE(sm->UnmapUpdateSnapshot(name)); } group_->add_partition_names("dlkm"); auto dlkm = manifest_.add_partitions(); dlkm->set_partition_name("dlkm"); dlkm->set_estimate_cow_size(2_MiB); SetSize(dlkm, 3_MiB); // Grow all partitions. Set |prd| large enough that |sys| and |vnd|'s COWs // fit in super, but not |prd|. constexpr uint64_t partition_size = 3788_KiB; SetSize(sys_, partition_size); SetSize(vnd_, partition_size); SetSize(prd_, partition_size); SetSize(dlkm, partition_size); AddOperationForPartitions({sys_, vnd_, prd_, dlkm}); // Execute the update. ASSERT_TRUE(sm->BeginUpdate()); ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_)); // Write some data to target partitions. for (const auto& name : {"sys_b", "vnd_b", "prd_b", "dlkm_b"}) { ASSERT_TRUE(WriteSnapshotAndHash(name)); } // Assert that source partitions aren't affected. for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) { ASSERT_TRUE(IsPartitionUnchanged(name)); } ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); // Simulate shutting down the device. ASSERT_TRUE(UnmapAll()); // After reboot, init does first stage mount. auto init = NewManagerForFirstStageMount("_b"); ASSERT_NE(init, nullptr); ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount()); ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_)); // Check that the target partitions have the same content. for (const auto& name : {"sys_b", "vnd_b", "prd_b", "dlkm_b"}) { ASSERT_TRUE(IsPartitionUnchanged(name)); } // Initiate the merge and wait for it to be completed. ASSERT_TRUE(init->InitiateMerge()); ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState()); // Check that the target partitions have the same content after the merge. for (const auto& name : {"sys_b", "vnd_b", "prd_b", "dlkm_b"}) { ASSERT_TRUE(IsPartitionUnchanged(name)) << "Content of " << name << " changes after the merge"; } } class AutoKill final { public: explicit AutoKill(pid_t pid) : pid_(pid) {} Loading