libsnapshot: Fix missing source partitions when adding a new partition. am: 0a6f250242

Original change: https://googleplex-android-review.googlesource.com/c/platform/system/core/+/15670247

Change-Id: Ieda77c5fc8cf867cb62054e0a38321fdf528e311
This commit is contained in:
David Anderson 2021-08-27 19:36:47 +00:00 committed by Automerger Merge Worker
commit 05fbdcd3eb
3 changed files with 77 additions and 8 deletions

View File

@ -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);

View File

@ -2091,14 +2091,18 @@ 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 (!MapSourceDevice(lock, params.GetPartitionName(), remaining_time,
&source_device_path)) {
LOG(ERROR) << "Could not map source device for: " << cow_name;
return false;
}
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;
return false;
}
auto source_device = GetSourceDeviceName(params.GetPartitionName());
created_devices.EmplaceBack<AutoUnmapDevice>(&dm, source_device);
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;

View File

@ -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";
}
@ -2026,6 +2026,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) {}