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:
commit
05fbdcd3eb
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {}
|
||||
|
|
Loading…
Reference in New Issue