1 // Copyright (C) 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <libsnapshot/cow_format.h>
16 #include <libsnapshot/snapshot.h>
17
18 #include <fcntl.h>
19 #include <signal.h>
20 #include <sys/file.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23
24 #include <chrono>
25 #include <deque>
26 #include <future>
27 #include <iostream>
28
29 #include <android-base/file.h>
30 #include <android-base/logging.h>
31 #include <android-base/properties.h>
32 #include <android-base/strings.h>
33 #include <android-base/unique_fd.h>
34 #include <fs_mgr/file_wait.h>
35 #include <fs_mgr/roots.h>
36 #include <fs_mgr_dm_linear.h>
37 #include <gflags/gflags.h>
38 #include <gtest/gtest.h>
39 #include <libdm/dm.h>
40 #include <libfiemap/image_manager.h>
41 #include <liblp/builder.h>
42 #include <storage_literals/storage_literals.h>
43
44 #include <android/snapshot/snapshot.pb.h>
45 #include <libsnapshot/test_helpers.h>
46 #include "partition_cow_creator.h"
47 #include "utility.h"
48
49 // Mock classes are not used. Header included to ensure mocked class definition aligns with the
50 // class itself.
51 #include <libsnapshot/mock_device_info.h>
52 #include <libsnapshot/mock_snapshot.h>
53
54 DEFINE_string(force_config, "", "Force testing mode (dmsnap, vab, vabc) ignoring device config.");
55 DEFINE_string(force_iouring_disable, "",
56 "Force testing mode (iouring_disabled) - disable io_uring");
57
58 namespace android {
59 namespace snapshot {
60
61 using android::base::unique_fd;
62 using android::dm::DeviceMapper;
63 using android::dm::DmDeviceState;
64 using android::dm::IDeviceMapper;
65 using android::fiemap::FiemapStatus;
66 using android::fiemap::IImageManager;
67 using android::fs_mgr::BlockDeviceInfo;
68 using android::fs_mgr::CreateLogicalPartitionParams;
69 using android::fs_mgr::DestroyLogicalPartition;
70 using android::fs_mgr::EnsurePathMounted;
71 using android::fs_mgr::EnsurePathUnmounted;
72 using android::fs_mgr::Extent;
73 using android::fs_mgr::Fstab;
74 using android::fs_mgr::GetPartitionGroupName;
75 using android::fs_mgr::GetPartitionName;
76 using android::fs_mgr::Interval;
77 using android::fs_mgr::MetadataBuilder;
78 using android::fs_mgr::SlotSuffixForSlotNumber;
79 using chromeos_update_engine::DeltaArchiveManifest;
80 using chromeos_update_engine::DynamicPartitionGroup;
81 using chromeos_update_engine::PartitionUpdate;
82 using namespace ::testing;
83 using namespace android::storage_literals;
84 using namespace std::chrono_literals;
85 using namespace std::string_literals;
86
87 // Global states. See test_helpers.h.
88 std::unique_ptr<SnapshotManager> sm;
89 TestDeviceInfo* test_device = nullptr;
90 std::string fake_super;
91
92 void MountMetadata();
93 bool ShouldUseCompression();
94 bool IsDaemonRequired();
95
96 class SnapshotTest : public ::testing::Test {
97 public:
SnapshotTest()98 SnapshotTest() : dm_(DeviceMapper::Instance()) {}
99
100 // This is exposed for main.
Cleanup()101 void Cleanup() {
102 InitializeState();
103 CleanupTestArtifacts();
104 }
105
106 protected:
SetUp()107 void SetUp() override {
108 SKIP_IF_NON_VIRTUAL_AB();
109
110 SnapshotTestPropertyFetcher::SetUp();
111 InitializeState();
112 CleanupTestArtifacts();
113 FormatFakeSuper();
114 MountMetadata();
115 ASSERT_TRUE(sm->BeginUpdate());
116 }
117
TearDown()118 void TearDown() override {
119 RETURN_IF_NON_VIRTUAL_AB();
120
121 lock_ = nullptr;
122
123 CleanupTestArtifacts();
124 SnapshotTestPropertyFetcher::TearDown();
125 }
126
InitializeState()127 void InitializeState() {
128 ASSERT_TRUE(sm->EnsureImageManager());
129 image_manager_ = sm->image_manager();
130
131 test_device->set_slot_suffix("_a");
132
133 sm->set_use_first_stage_snapuserd(false);
134 }
135
CleanupTestArtifacts()136 void CleanupTestArtifacts() {
137 // Normally cancelling inside a merge is not allowed. Since these
138 // are tests, we don't care, destroy everything that might exist.
139 // Note we hardcode this list because of an annoying quirk: when
140 // completing a merge, the snapshot stops existing, so we can't
141 // get an accurate list to remove.
142 lock_ = nullptr;
143
144 std::vector<std::string> snapshots = {"test-snapshot", "test_partition_a",
145 "test_partition_b"};
146 for (const auto& snapshot : snapshots) {
147 CleanupSnapshotArtifacts(snapshot);
148 }
149
150 // Remove stale partitions in fake super.
151 std::vector<std::string> partitions = {
152 "base-device",
153 "test_partition_b",
154 "test_partition_b-base",
155 "test_partition_b-cow",
156 };
157 for (const auto& partition : partitions) {
158 DeleteDevice(partition);
159 }
160
161 if (sm->GetUpdateState() != UpdateState::None) {
162 auto state_file = sm->GetStateFilePath();
163 unlink(state_file.c_str());
164 }
165 }
166
CleanupSnapshotArtifacts(const std::string & snapshot)167 void CleanupSnapshotArtifacts(const std::string& snapshot) {
168 // The device-mapper stack may have been collapsed to dm-linear, so it's
169 // necessary to check what state it's in before attempting a cleanup.
170 // SnapshotManager has no path like this because we'd never remove a
171 // merged snapshot (a live partition).
172 bool is_dm_user = false;
173 DeviceMapper::TargetInfo target;
174 if (sm->IsSnapshotDevice(snapshot, &target)) {
175 is_dm_user = (DeviceMapper::GetTargetType(target.spec) == "user");
176 }
177
178 if (is_dm_user) {
179 ASSERT_TRUE(sm->EnsureSnapuserdConnected());
180 ASSERT_TRUE(AcquireLock());
181
182 auto local_lock = std::move(lock_);
183 ASSERT_TRUE(sm->UnmapUserspaceSnapshotDevice(local_lock.get(), snapshot));
184 }
185
186 ASSERT_TRUE(DeleteSnapshotDevice(snapshot));
187 DeleteBackingImage(image_manager_, snapshot + "-cow-img");
188
189 auto status_file = sm->GetSnapshotStatusFilePath(snapshot);
190 android::base::RemoveFileIfExists(status_file);
191 }
192
AcquireLock()193 bool AcquireLock() {
194 lock_ = sm->LockExclusive();
195 return !!lock_;
196 }
197
198 // This is so main() can instantiate this to invoke Cleanup.
TestBody()199 virtual void TestBody() override {}
200
FormatFakeSuper()201 void FormatFakeSuper() {
202 BlockDeviceInfo super_device("super", kSuperSize, 0, 0, 4096);
203 std::vector<BlockDeviceInfo> devices = {super_device};
204
205 auto builder = MetadataBuilder::New(devices, "super", 65536, 2);
206 ASSERT_NE(builder, nullptr);
207
208 auto metadata = builder->Export();
209 ASSERT_NE(metadata, nullptr);
210
211 TestPartitionOpener opener(fake_super);
212 ASSERT_TRUE(FlashPartitionTable(opener, fake_super, *metadata.get()));
213 }
214
215 // If |path| is non-null, the partition will be mapped after creation.
CreatePartition(const std::string & name,uint64_t size,std::string * path=nullptr,const std::optional<std::string> group={})216 bool CreatePartition(const std::string& name, uint64_t size, std::string* path = nullptr,
217 const std::optional<std::string> group = {}) {
218 TestPartitionOpener opener(fake_super);
219 auto builder = MetadataBuilder::New(opener, "super", 0);
220 if (!builder) return false;
221
222 std::string partition_group = std::string(android::fs_mgr::kDefaultGroup);
223 if (group) {
224 partition_group = *group;
225 }
226 return CreatePartition(builder.get(), name, size, path, partition_group);
227 }
228
CreatePartition(MetadataBuilder * builder,const std::string & name,uint64_t size,std::string * path,const std::string & group)229 bool CreatePartition(MetadataBuilder* builder, const std::string& name, uint64_t size,
230 std::string* path, const std::string& group) {
231 auto partition = builder->AddPartition(name, group, 0);
232 if (!partition) return false;
233 if (!builder->ResizePartition(partition, size)) {
234 return false;
235 }
236
237 // Update the source slot.
238 auto metadata = builder->Export();
239 if (!metadata) return false;
240
241 TestPartitionOpener opener(fake_super);
242 if (!UpdatePartitionTable(opener, "super", *metadata.get(), 0)) {
243 return false;
244 }
245
246 if (!path) return true;
247
248 CreateLogicalPartitionParams params = {
249 .block_device = fake_super,
250 .metadata = metadata.get(),
251 .partition_name = name,
252 .force_writable = true,
253 .timeout_ms = 10s,
254 };
255 return CreateLogicalPartition(params, path);
256 }
257
MapUpdateSnapshot(const std::string & name,std::unique_ptr<ISnapshotWriter> * writer)258 AssertionResult MapUpdateSnapshot(const std::string& name,
259 std::unique_ptr<ISnapshotWriter>* writer) {
260 TestPartitionOpener opener(fake_super);
261 CreateLogicalPartitionParams params{
262 .block_device = fake_super,
263 .metadata_slot = 1,
264 .partition_name = name,
265 .timeout_ms = 10s,
266 .partition_opener = &opener,
267 };
268
269 auto old_partition = "/dev/block/mapper/" + GetOtherPartitionName(name);
270 auto result = sm->OpenSnapshotWriter(params, {old_partition});
271 if (!result) {
272 return AssertionFailure() << "Cannot open snapshot for writing: " << name;
273 }
274 if (!result->Initialize()) {
275 return AssertionFailure() << "Cannot initialize snapshot for writing: " << name;
276 }
277
278 if (writer) {
279 *writer = std::move(result);
280 }
281 return AssertionSuccess();
282 }
283
MapUpdateSnapshot(const std::string & name,std::string * path)284 AssertionResult MapUpdateSnapshot(const std::string& name, std::string* path) {
285 TestPartitionOpener opener(fake_super);
286 CreateLogicalPartitionParams params{
287 .block_device = fake_super,
288 .metadata_slot = 1,
289 .partition_name = name,
290 .timeout_ms = 10s,
291 .partition_opener = &opener,
292 };
293
294 auto result = sm->MapUpdateSnapshot(params, path);
295 if (!result) {
296 return AssertionFailure() << "Cannot open snapshot for writing: " << name;
297 }
298 return AssertionSuccess();
299 }
300
DeleteSnapshotDevice(const std::string & snapshot)301 AssertionResult DeleteSnapshotDevice(const std::string& snapshot) {
302 AssertionResult res = AssertionSuccess();
303 if (!(res = DeleteDevice(snapshot))) return res;
304 if (!sm->UnmapDmUserDevice(snapshot + "-user-cow")) {
305 return AssertionFailure() << "Cannot delete dm-user device for " << snapshot;
306 }
307 if (!(res = DeleteDevice(snapshot + "-inner"))) return res;
308 if (!(res = DeleteDevice(snapshot + "-cow"))) return res;
309 if (!image_manager_->UnmapImageIfExists(snapshot + "-cow-img")) {
310 return AssertionFailure() << "Cannot unmap image " << snapshot << "-cow-img";
311 }
312 if (!(res = DeleteDevice(snapshot + "-base"))) return res;
313 if (!(res = DeleteDevice(snapshot + "-src"))) return res;
314 return AssertionSuccess();
315 }
316
DeleteDevice(const std::string & device)317 AssertionResult DeleteDevice(const std::string& device) {
318 if (!dm_.DeleteDeviceIfExists(device)) {
319 return AssertionFailure() << "Can't delete " << device;
320 }
321 return AssertionSuccess();
322 }
323
CreateCowImage(const std::string & name)324 AssertionResult CreateCowImage(const std::string& name) {
325 if (!sm->CreateCowImage(lock_.get(), name)) {
326 return AssertionFailure() << "Cannot create COW image " << name;
327 }
328 std::string cow_device;
329 auto map_res = MapCowImage(name, 10s, &cow_device);
330 if (!map_res) {
331 return map_res;
332 }
333 if (!InitializeKernelCow(cow_device)) {
334 return AssertionFailure() << "Cannot zero fill " << cow_device;
335 }
336 if (!sm->UnmapCowImage(name)) {
337 return AssertionFailure() << "Cannot unmap " << name << " after zero filling it";
338 }
339 return AssertionSuccess();
340 }
341
MapCowImage(const std::string & name,const std::chrono::milliseconds & timeout_ms,std::string * path)342 AssertionResult MapCowImage(const std::string& name,
343 const std::chrono::milliseconds& timeout_ms, std::string* path) {
344 auto cow_image_path = sm->MapCowImage(name, timeout_ms);
345 if (!cow_image_path.has_value()) {
346 return AssertionFailure() << "Cannot map cow image " << name;
347 }
348 *path = *cow_image_path;
349 return AssertionSuccess();
350 }
351
352 // Prepare A/B slot for a partition named "test_partition".
PrepareOneSnapshot(uint64_t device_size,std::unique_ptr<ISnapshotWriter> * writer=nullptr)353 AssertionResult PrepareOneSnapshot(uint64_t device_size,
354 std::unique_ptr<ISnapshotWriter>* writer = nullptr) {
355 lock_ = nullptr;
356
357 DeltaArchiveManifest manifest;
358
359 auto dynamic_partition_metadata = manifest.mutable_dynamic_partition_metadata();
360 dynamic_partition_metadata->set_vabc_enabled(IsCompressionEnabled());
361 dynamic_partition_metadata->set_cow_version(android::snapshot::kCowVersionMajor);
362
363 auto group = dynamic_partition_metadata->add_groups();
364 group->set_name("group");
365 group->set_size(device_size * 2);
366 group->add_partition_names("test_partition");
367
368 auto pu = manifest.add_partitions();
369 pu->set_partition_name("test_partition");
370 pu->set_estimate_cow_size(device_size);
371 SetSize(pu, device_size);
372
373 auto extent = pu->add_operations()->add_dst_extents();
374 extent->set_start_block(0);
375 if (device_size) {
376 extent->set_num_blocks(device_size / manifest.block_size());
377 }
378
379 TestPartitionOpener opener(fake_super);
380 auto builder = MetadataBuilder::New(opener, "super", 0);
381 if (!builder) {
382 return AssertionFailure() << "Failed to open MetadataBuilder";
383 }
384 builder->AddGroup("group_a", 16_GiB);
385 builder->AddGroup("group_b", 16_GiB);
386 if (!CreatePartition(builder.get(), "test_partition_a", device_size, nullptr, "group_a")) {
387 return AssertionFailure() << "Failed create test_partition_a";
388 }
389
390 if (!sm->CreateUpdateSnapshots(manifest)) {
391 return AssertionFailure() << "Failed to create update snapshots";
392 }
393
394 if (writer) {
395 auto res = MapUpdateSnapshot("test_partition_b", writer);
396 if (!res) {
397 return res;
398 }
399 } else if (!IsCompressionEnabled()) {
400 std::string ignore;
401 if (!MapUpdateSnapshot("test_partition_b", &ignore)) {
402 return AssertionFailure() << "Failed to map test_partition_b";
403 }
404 }
405 if (!AcquireLock()) {
406 return AssertionFailure() << "Failed to acquire lock";
407 }
408 return AssertionSuccess();
409 }
410
411 // Simulate a reboot into the new slot.
SimulateReboot()412 AssertionResult SimulateReboot() {
413 lock_ = nullptr;
414 if (!sm->FinishedSnapshotWrites(false)) {
415 return AssertionFailure() << "Failed to finish snapshot writes";
416 }
417 if (!sm->UnmapUpdateSnapshot("test_partition_b")) {
418 return AssertionFailure() << "Failed to unmap COW for test_partition_b";
419 }
420 if (!dm_.DeleteDeviceIfExists("test_partition_b")) {
421 return AssertionFailure() << "Failed to delete test_partition_b";
422 }
423 if (!dm_.DeleteDeviceIfExists("test_partition_b-base")) {
424 return AssertionFailure() << "Failed to destroy test_partition_b-base";
425 }
426 return AssertionSuccess();
427 }
428
NewManagerForFirstStageMount(const std::string & slot_suffix="_a")429 std::unique_ptr<SnapshotManager> NewManagerForFirstStageMount(
430 const std::string& slot_suffix = "_a") {
431 auto info = new TestDeviceInfo(fake_super, slot_suffix);
432 return NewManagerForFirstStageMount(info);
433 }
434
NewManagerForFirstStageMount(TestDeviceInfo * info)435 std::unique_ptr<SnapshotManager> NewManagerForFirstStageMount(TestDeviceInfo* info) {
436 info->set_first_stage_init(true);
437 auto init = SnapshotManager::NewForFirstStageMount(info);
438 if (!init) {
439 return nullptr;
440 }
441 init->SetUeventRegenCallback([](const std::string& device) -> bool {
442 return android::fs_mgr::WaitForFile(device, snapshot_timeout_);
443 });
444 return init;
445 }
446
447 static constexpr std::chrono::milliseconds snapshot_timeout_ = 5s;
448 DeviceMapper& dm_;
449 std::unique_ptr<SnapshotManager::LockedFile> lock_;
450 android::fiemap::IImageManager* image_manager_ = nullptr;
451 std::string fake_super_;
452 };
453
TEST_F(SnapshotTest,CreateSnapshot)454 TEST_F(SnapshotTest, CreateSnapshot) {
455 ASSERT_TRUE(AcquireLock());
456
457 PartitionCowCreator cow_creator;
458 cow_creator.compression_enabled = ShouldUseCompression();
459 if (cow_creator.compression_enabled) {
460 cow_creator.compression_algorithm = "gz";
461 } else {
462 cow_creator.compression_algorithm = "none";
463 }
464
465 static const uint64_t kDeviceSize = 1024 * 1024;
466 SnapshotStatus status;
467 status.set_name("test-snapshot");
468 status.set_device_size(kDeviceSize);
469 status.set_snapshot_size(kDeviceSize);
470 status.set_cow_file_size(kDeviceSize);
471 ASSERT_TRUE(sm->CreateSnapshot(lock_.get(), &cow_creator, &status));
472 ASSERT_TRUE(CreateCowImage("test-snapshot"));
473
474 std::vector<std::string> snapshots;
475 ASSERT_TRUE(sm->ListSnapshots(lock_.get(), &snapshots));
476 ASSERT_EQ(snapshots.size(), 1);
477 ASSERT_EQ(snapshots[0], "test-snapshot");
478
479 // Scope so delete can re-acquire the snapshot file lock.
480 {
481 SnapshotStatus status;
482 ASSERT_TRUE(sm->ReadSnapshotStatus(lock_.get(), "test-snapshot", &status));
483 ASSERT_EQ(status.state(), SnapshotState::CREATED);
484 ASSERT_EQ(status.device_size(), kDeviceSize);
485 ASSERT_EQ(status.snapshot_size(), kDeviceSize);
486 ASSERT_EQ(status.compression_enabled(), cow_creator.compression_enabled);
487 ASSERT_EQ(status.compression_algorithm(), cow_creator.compression_algorithm);
488 }
489
490 ASSERT_TRUE(sm->UnmapSnapshot(lock_.get(), "test-snapshot"));
491 ASSERT_TRUE(sm->UnmapCowImage("test-snapshot"));
492 ASSERT_TRUE(sm->DeleteSnapshot(lock_.get(), "test-snapshot"));
493 }
494
TEST_F(SnapshotTest,MapSnapshot)495 TEST_F(SnapshotTest, MapSnapshot) {
496 ASSERT_TRUE(AcquireLock());
497
498 PartitionCowCreator cow_creator;
499 cow_creator.compression_enabled = ShouldUseCompression();
500
501 static const uint64_t kDeviceSize = 1024 * 1024;
502 SnapshotStatus status;
503 status.set_name("test-snapshot");
504 status.set_device_size(kDeviceSize);
505 status.set_snapshot_size(kDeviceSize);
506 status.set_cow_file_size(kDeviceSize);
507 ASSERT_TRUE(sm->CreateSnapshot(lock_.get(), &cow_creator, &status));
508 ASSERT_TRUE(CreateCowImage("test-snapshot"));
509
510 std::string base_device;
511 ASSERT_TRUE(CreatePartition("base-device", kDeviceSize, &base_device));
512
513 std::string cow_device;
514 ASSERT_TRUE(MapCowImage("test-snapshot", 10s, &cow_device));
515
516 std::string snap_device;
517 ASSERT_TRUE(sm->MapSnapshot(lock_.get(), "test-snapshot", base_device, cow_device, 10s,
518 &snap_device));
519 ASSERT_TRUE(android::base::StartsWith(snap_device, "/dev/block/dm-"));
520 }
521
TEST_F(SnapshotTest,NoMergeBeforeReboot)522 TEST_F(SnapshotTest, NoMergeBeforeReboot) {
523 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
524
525 // Merge should fail, since the slot hasn't changed.
526 ASSERT_FALSE(sm->InitiateMerge());
527 }
528
TEST_F(SnapshotTest,CleanFirstStageMount)529 TEST_F(SnapshotTest, CleanFirstStageMount) {
530 // If there's no update in progress, there should be no first-stage mount
531 // needed.
532 auto sm = NewManagerForFirstStageMount();
533 ASSERT_NE(sm, nullptr);
534 ASSERT_FALSE(sm->NeedSnapshotsInFirstStageMount());
535 }
536
TEST_F(SnapshotTest,FirstStageMountAfterRollback)537 TEST_F(SnapshotTest, FirstStageMountAfterRollback) {
538 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
539
540 // We didn't change the slot, so we shouldn't need snapshots.
541 auto sm = NewManagerForFirstStageMount();
542 ASSERT_NE(sm, nullptr);
543 ASSERT_FALSE(sm->NeedSnapshotsInFirstStageMount());
544
545 auto indicator = sm->GetRollbackIndicatorPath();
546 ASSERT_EQ(access(indicator.c_str(), R_OK), 0);
547 }
548
TEST_F(SnapshotTest,Merge)549 TEST_F(SnapshotTest, Merge) {
550 ASSERT_TRUE(AcquireLock());
551
552 static const uint64_t kDeviceSize = 1024 * 1024;
553
554 std::unique_ptr<ISnapshotWriter> writer;
555 ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize, &writer));
556
557 bool userspace_snapshots = sm->UpdateUsesUserSnapshots(lock_.get());
558
559 // Release the lock.
560 lock_ = nullptr;
561
562 std::string test_string = "This is a test string.";
563 test_string.resize(writer->options().block_size);
564 ASSERT_TRUE(writer->AddRawBlocks(0, test_string.data(), test_string.size()));
565 ASSERT_TRUE(writer->Finalize());
566 writer = nullptr;
567
568 // Done updating.
569 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
570
571 ASSERT_TRUE(sm->UnmapUpdateSnapshot("test_partition_b"));
572
573 test_device->set_slot_suffix("_b");
574 ASSERT_TRUE(sm->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
575 ASSERT_TRUE(sm->InitiateMerge());
576
577 // The device should have been switched to a snapshot-merge target.
578 DeviceMapper::TargetInfo target;
579 ASSERT_TRUE(sm->IsSnapshotDevice("test_partition_b", &target));
580 if (userspace_snapshots) {
581 ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
582 } else {
583 ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot-merge");
584 }
585
586 // We should not be able to cancel an update now.
587 ASSERT_FALSE(sm->CancelUpdate());
588
589 ASSERT_EQ(sm->ProcessUpdateState(), UpdateState::MergeCompleted);
590 ASSERT_EQ(sm->GetUpdateState(), UpdateState::None);
591
592 // The device should no longer be a snapshot or snapshot-merge.
593 ASSERT_FALSE(sm->IsSnapshotDevice("test_partition_b"));
594
595 // Test that we can read back the string we wrote to the snapshot. Note
596 // that the base device is gone now. |snap_device| contains the correct
597 // partition.
598 unique_fd fd(open("/dev/block/mapper/test_partition_b", O_RDONLY | O_CLOEXEC));
599 ASSERT_GE(fd, 0);
600
601 std::string buffer(test_string.size(), '\0');
602 ASSERT_TRUE(android::base::ReadFully(fd, buffer.data(), buffer.size()));
603 ASSERT_EQ(test_string, buffer);
604 }
605
TEST_F(SnapshotTest,FirstStageMountAndMerge)606 TEST_F(SnapshotTest, FirstStageMountAndMerge) {
607 ASSERT_TRUE(AcquireLock());
608
609 static const uint64_t kDeviceSize = 1024 * 1024;
610 ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize));
611 ASSERT_TRUE(SimulateReboot());
612
613 auto init = NewManagerForFirstStageMount("_b");
614 ASSERT_NE(init, nullptr);
615 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
616 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
617
618 ASSERT_TRUE(AcquireLock());
619
620 bool userspace_snapshots = init->UpdateUsesUserSnapshots(lock_.get());
621
622 // Validate that we have a snapshot device.
623 SnapshotStatus status;
624 ASSERT_TRUE(init->ReadSnapshotStatus(lock_.get(), "test_partition_b", &status));
625 ASSERT_EQ(status.state(), SnapshotState::CREATED);
626 if (ShouldUseCompression()) {
627 ASSERT_EQ(status.compression_algorithm(), "gz");
628 } else {
629 ASSERT_EQ(status.compression_algorithm(), "none");
630 }
631
632 DeviceMapper::TargetInfo target;
633 ASSERT_TRUE(init->IsSnapshotDevice("test_partition_b", &target));
634 if (userspace_snapshots) {
635 ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
636 } else {
637 ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot");
638 }
639 }
640
TEST_F(SnapshotTest,FlashSuperDuringUpdate)641 TEST_F(SnapshotTest, FlashSuperDuringUpdate) {
642 ASSERT_TRUE(AcquireLock());
643
644 static const uint64_t kDeviceSize = 1024 * 1024;
645 ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize));
646 ASSERT_TRUE(SimulateReboot());
647
648 // Reflash the super partition.
649 FormatFakeSuper();
650 ASSERT_TRUE(CreatePartition("test_partition_b", kDeviceSize));
651
652 auto init = NewManagerForFirstStageMount("_b");
653 ASSERT_NE(init, nullptr);
654 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
655 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
656
657 ASSERT_TRUE(AcquireLock());
658
659 SnapshotStatus status;
660 ASSERT_TRUE(init->ReadSnapshotStatus(lock_.get(), "test_partition_b", &status));
661
662 // We should not get a snapshot device now.
663 DeviceMapper::TargetInfo target;
664 ASSERT_FALSE(init->IsSnapshotDevice("test_partition_b", &target));
665
666 // We should see a cancelled update as well.
667 lock_ = nullptr;
668 ASSERT_EQ(sm->ProcessUpdateState(), UpdateState::Cancelled);
669 }
670
TEST_F(SnapshotTest,FlashSuperDuringMerge)671 TEST_F(SnapshotTest, FlashSuperDuringMerge) {
672 ASSERT_TRUE(AcquireLock());
673
674 static const uint64_t kDeviceSize = 1024 * 1024;
675 ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize));
676 ASSERT_TRUE(SimulateReboot());
677
678 auto init = NewManagerForFirstStageMount("_b");
679 ASSERT_NE(init, nullptr);
680 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
681 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
682 ASSERT_TRUE(init->InitiateMerge());
683
684 // Now, reflash super. Note that we haven't called ProcessUpdateState, so the
685 // status is still Merging.
686 ASSERT_TRUE(DeleteSnapshotDevice("test_partition_b"));
687 ASSERT_TRUE(init->image_manager()->UnmapImageIfExists("test_partition_b-cow-img"));
688 FormatFakeSuper();
689 ASSERT_TRUE(CreatePartition("test_partition_b", kDeviceSize));
690 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
691 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
692
693 // Because the status is Merging, we must call ProcessUpdateState, which should
694 // detect a cancelled update.
695 ASSERT_EQ(init->ProcessUpdateState(), UpdateState::Cancelled);
696 ASSERT_EQ(init->GetUpdateState(), UpdateState::None);
697 }
698
TEST_F(SnapshotTest,UpdateBootControlHal)699 TEST_F(SnapshotTest, UpdateBootControlHal) {
700 ASSERT_TRUE(AcquireLock());
701
702 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::None));
703 ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
704
705 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Initiated));
706 ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
707
708 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Unverified));
709 ASSERT_EQ(test_device->merge_status(), MergeStatus::SNAPSHOTTED);
710
711 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Merging));
712 ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
713
714 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeNeedsReboot));
715 ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
716
717 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeCompleted));
718 ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
719
720 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeFailed));
721 ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
722 }
723
TEST_F(SnapshotTest,MergeFailureCode)724 TEST_F(SnapshotTest, MergeFailureCode) {
725 ASSERT_TRUE(AcquireLock());
726
727 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeFailed,
728 MergeFailureCode::ListSnapshots));
729 ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
730
731 SnapshotUpdateStatus status = sm->ReadSnapshotUpdateStatus(lock_.get());
732 ASSERT_EQ(status.state(), UpdateState::MergeFailed);
733 ASSERT_EQ(status.merge_failure_code(), MergeFailureCode::ListSnapshots);
734 }
735
736 enum class Request { UNKNOWN, LOCK_SHARED, LOCK_EXCLUSIVE, UNLOCK, EXIT };
operator <<(std::ostream & os,Request request)737 std::ostream& operator<<(std::ostream& os, Request request) {
738 switch (request) {
739 case Request::LOCK_SHARED:
740 return os << "Shared";
741 case Request::LOCK_EXCLUSIVE:
742 return os << "Exclusive";
743 case Request::UNLOCK:
744 return os << "Unlock";
745 case Request::EXIT:
746 return os << "Exit";
747 case Request::UNKNOWN:
748 [[fallthrough]];
749 default:
750 return os << "Unknown";
751 }
752 }
753
754 class LockTestConsumer {
755 public:
MakeRequest(Request new_request)756 AssertionResult MakeRequest(Request new_request) {
757 {
758 std::unique_lock<std::mutex> ulock(mutex_);
759 requests_.push_back(new_request);
760 }
761 cv_.notify_all();
762 return AssertionSuccess() << "Request " << new_request << " successful";
763 }
764
765 template <typename R, typename P>
WaitFulfill(std::chrono::duration<R,P> timeout)766 AssertionResult WaitFulfill(std::chrono::duration<R, P> timeout) {
767 std::unique_lock<std::mutex> ulock(mutex_);
768 if (cv_.wait_for(ulock, timeout, [this] { return requests_.empty(); })) {
769 return AssertionSuccess() << "All requests_ fulfilled.";
770 }
771 return AssertionFailure() << "Timeout waiting for fulfilling " << requests_.size()
772 << " request(s), first one is "
773 << (requests_.empty() ? Request::UNKNOWN : requests_.front());
774 }
775
StartHandleRequestsInBackground()776 void StartHandleRequestsInBackground() {
777 future_ = std::async(std::launch::async, &LockTestConsumer::HandleRequests, this);
778 }
779
780 private:
HandleRequests()781 void HandleRequests() {
782 static constexpr auto consumer_timeout = 3s;
783
784 auto next_request = Request::UNKNOWN;
785 do {
786 // Peek next request.
787 {
788 std::unique_lock<std::mutex> ulock(mutex_);
789 if (cv_.wait_for(ulock, consumer_timeout, [this] { return !requests_.empty(); })) {
790 next_request = requests_.front();
791 } else {
792 next_request = Request::EXIT;
793 }
794 }
795
796 // Handle next request.
797 switch (next_request) {
798 case Request::LOCK_SHARED: {
799 lock_ = sm->LockShared();
800 } break;
801 case Request::LOCK_EXCLUSIVE: {
802 lock_ = sm->LockExclusive();
803 } break;
804 case Request::EXIT:
805 [[fallthrough]];
806 case Request::UNLOCK: {
807 lock_.reset();
808 } break;
809 case Request::UNKNOWN:
810 [[fallthrough]];
811 default:
812 break;
813 }
814
815 // Pop next request. This thread is the only thread that
816 // pops from the front of the requests_ deque.
817 {
818 std::unique_lock<std::mutex> ulock(mutex_);
819 if (next_request == Request::EXIT) {
820 requests_.clear();
821 } else {
822 requests_.pop_front();
823 }
824 }
825 cv_.notify_all();
826 } while (next_request != Request::EXIT);
827 }
828
829 std::mutex mutex_;
830 std::condition_variable cv_;
831 std::deque<Request> requests_;
832 std::unique_ptr<SnapshotManager::LockedFile> lock_;
833 std::future<void> future_;
834 };
835
836 class LockTest : public ::testing::Test {
837 public:
SetUp()838 void SetUp() {
839 SKIP_IF_NON_VIRTUAL_AB();
840 first_consumer.StartHandleRequestsInBackground();
841 second_consumer.StartHandleRequestsInBackground();
842 }
843
TearDown()844 void TearDown() {
845 RETURN_IF_NON_VIRTUAL_AB();
846 EXPECT_TRUE(first_consumer.MakeRequest(Request::EXIT));
847 EXPECT_TRUE(second_consumer.MakeRequest(Request::EXIT));
848 }
849
850 static constexpr auto request_timeout = 500ms;
851 LockTestConsumer first_consumer;
852 LockTestConsumer second_consumer;
853 };
854
TEST_F(LockTest,SharedShared)855 TEST_F(LockTest, SharedShared) {
856 ASSERT_TRUE(first_consumer.MakeRequest(Request::LOCK_SHARED));
857 ASSERT_TRUE(first_consumer.WaitFulfill(request_timeout));
858 ASSERT_TRUE(second_consumer.MakeRequest(Request::LOCK_SHARED));
859 ASSERT_TRUE(second_consumer.WaitFulfill(request_timeout));
860 }
861
862 using LockTestParam = std::pair<Request, Request>;
863 class LockTestP : public LockTest, public ::testing::WithParamInterface<LockTestParam> {};
TEST_P(LockTestP,Test)864 TEST_P(LockTestP, Test) {
865 ASSERT_TRUE(first_consumer.MakeRequest(GetParam().first));
866 ASSERT_TRUE(first_consumer.WaitFulfill(request_timeout));
867 ASSERT_TRUE(second_consumer.MakeRequest(GetParam().second));
868 ASSERT_FALSE(second_consumer.WaitFulfill(request_timeout))
869 << "Should not be able to " << GetParam().second << " while separate thread "
870 << GetParam().first;
871 ASSERT_TRUE(first_consumer.MakeRequest(Request::UNLOCK));
872 ASSERT_TRUE(second_consumer.WaitFulfill(request_timeout))
873 << "Should be able to hold lock that is released by separate thread";
874 }
875 INSTANTIATE_TEST_SUITE_P(
876 LockTest, LockTestP,
877 testing::Values(LockTestParam{Request::LOCK_EXCLUSIVE, Request::LOCK_EXCLUSIVE},
878 LockTestParam{Request::LOCK_EXCLUSIVE, Request::LOCK_SHARED},
879 LockTestParam{Request::LOCK_SHARED, Request::LOCK_EXCLUSIVE}),
__anon581dab5a0402(const testing::TestParamInfo<LockTestP::ParamType>& info) 880 [](const testing::TestParamInfo<LockTestP::ParamType>& info) {
881 std::stringstream ss;
882 ss << info.param.first << info.param.second;
883 return ss.str();
884 });
885
886 class SnapshotUpdateTest : public SnapshotTest {
887 public:
SetUp()888 void SetUp() override {
889 SKIP_IF_NON_VIRTUAL_AB();
890
891 SnapshotTest::SetUp();
892 Cleanup();
893
894 // Cleanup() changes slot suffix, so initialize it again.
895 test_device->set_slot_suffix("_a");
896
897 opener_ = std::make_unique<TestPartitionOpener>(fake_super);
898
899 auto dynamic_partition_metadata = manifest_.mutable_dynamic_partition_metadata();
900 dynamic_partition_metadata->set_vabc_enabled(ShouldUseCompression());
901 dynamic_partition_metadata->set_cow_version(android::snapshot::kCowVersionMajor);
902
903 // Create a fake update package metadata.
904 // Not using full name "system", "vendor", "product" because these names collide with the
905 // mapped partitions on the running device.
906 // Each test modifies manifest_ slightly to indicate changes to the partition layout.
907 group_ = dynamic_partition_metadata->add_groups();
908 group_->set_name("group");
909 group_->set_size(kGroupSize);
910 group_->add_partition_names("sys");
911 group_->add_partition_names("vnd");
912 group_->add_partition_names("prd");
913 sys_ = manifest_.add_partitions();
914 sys_->set_partition_name("sys");
915 sys_->set_estimate_cow_size(2_MiB);
916 SetSize(sys_, 3_MiB);
917 vnd_ = manifest_.add_partitions();
918 vnd_->set_partition_name("vnd");
919 vnd_->set_estimate_cow_size(2_MiB);
920 SetSize(vnd_, 3_MiB);
921 prd_ = manifest_.add_partitions();
922 prd_->set_partition_name("prd");
923 prd_->set_estimate_cow_size(2_MiB);
924 SetSize(prd_, 3_MiB);
925
926 // Initialize source partition metadata using |manifest_|.
927 src_ = MetadataBuilder::New(*opener_, "super", 0);
928 ASSERT_NE(src_, nullptr);
929 ASSERT_TRUE(FillFakeMetadata(src_.get(), manifest_, "_a"));
930 // Add sys_b which is like system_other.
931 ASSERT_TRUE(src_->AddGroup("group_b", kGroupSize));
932 auto partition = src_->AddPartition("sys_b", "group_b", 0);
933 ASSERT_NE(nullptr, partition);
934 ASSERT_TRUE(src_->ResizePartition(partition, 1_MiB));
935 auto metadata = src_->Export();
936 ASSERT_NE(nullptr, metadata);
937 ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *metadata.get(), 0));
938
939 // Map source partitions.
940 std::string path;
941 for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
942 ASSERT_TRUE(CreateLogicalPartition(
943 CreateLogicalPartitionParams{
944 .block_device = fake_super,
945 .metadata_slot = 0,
946 .partition_name = name,
947 .timeout_ms = 1s,
948 .partition_opener = opener_.get(),
949 },
950 &path));
951 ASSERT_TRUE(WriteRandomData(path));
952 auto hash = GetHash(path);
953 ASSERT_TRUE(hash.has_value());
954 hashes_[name] = *hash;
955 }
956
957 // OTA client blindly unmaps all partitions that are possibly mapped.
958 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
959 ASSERT_TRUE(sm->UnmapUpdateSnapshot(name));
960 }
961 }
TearDown()962 void TearDown() override {
963 RETURN_IF_NON_VIRTUAL_AB();
964
965 Cleanup();
966 SnapshotTest::TearDown();
967 }
Cleanup()968 void Cleanup() {
969 if (!image_manager_) {
970 InitializeState();
971 }
972 MountMetadata();
973 for (const auto& suffix : {"_a", "_b"}) {
974 test_device->set_slot_suffix(suffix);
975
976 // Cheat our way out of merge failed states.
977 if (sm->ProcessUpdateState() == UpdateState::MergeFailed) {
978 ASSERT_TRUE(AcquireLock());
979 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::None));
980 lock_ = {};
981 }
982
983 EXPECT_TRUE(sm->CancelUpdate()) << suffix;
984 }
985 EXPECT_TRUE(UnmapAll());
986 }
987
IsPartitionUnchanged(const std::string & name)988 AssertionResult IsPartitionUnchanged(const std::string& name) {
989 std::string path;
990 if (!dm_.GetDmDevicePathByName(name, &path)) {
991 return AssertionFailure() << "Path of " << name << " cannot be determined";
992 }
993 auto hash = GetHash(path);
994 if (!hash.has_value()) {
995 return AssertionFailure() << "Cannot read partition " << name << ": " << path;
996 }
997 auto it = hashes_.find(name);
998 if (it == hashes_.end()) {
999 return AssertionFailure() << "No existing hash for " << name << ". Bad test code?";
1000 }
1001 if (it->second != *hash) {
1002 return AssertionFailure() << "Content of " << name << " has changed";
1003 }
1004 return AssertionSuccess();
1005 }
1006
GetSnapshotSize(const std::string & name)1007 std::optional<uint64_t> GetSnapshotSize(const std::string& name) {
1008 if (!AcquireLock()) {
1009 return std::nullopt;
1010 }
1011 auto local_lock = std::move(lock_);
1012
1013 SnapshotStatus status;
1014 if (!sm->ReadSnapshotStatus(local_lock.get(), name, &status)) {
1015 return std::nullopt;
1016 }
1017 return status.snapshot_size();
1018 }
1019
UnmapAll()1020 AssertionResult UnmapAll() {
1021 for (const auto& name : {"sys", "vnd", "prd", "dlkm"}) {
1022 if (!dm_.DeleteDeviceIfExists(name + "_a"s)) {
1023 return AssertionFailure() << "Cannot unmap " << name << "_a";
1024 }
1025 if (!DeleteSnapshotDevice(name + "_b"s)) {
1026 return AssertionFailure() << "Cannot delete snapshot " << name << "_b";
1027 }
1028 }
1029 return AssertionSuccess();
1030 }
1031
MapOneUpdateSnapshot(const std::string & name)1032 AssertionResult MapOneUpdateSnapshot(const std::string& name) {
1033 if (ShouldUseCompression()) {
1034 std::unique_ptr<ISnapshotWriter> writer;
1035 return MapUpdateSnapshot(name, &writer);
1036 } else {
1037 std::string path;
1038 return MapUpdateSnapshot(name, &path);
1039 }
1040 }
1041
WriteSnapshotAndHash(const std::string & name)1042 AssertionResult WriteSnapshotAndHash(const std::string& name) {
1043 if (ShouldUseCompression()) {
1044 std::unique_ptr<ISnapshotWriter> writer;
1045 auto res = MapUpdateSnapshot(name, &writer);
1046 if (!res) {
1047 return res;
1048 }
1049 if (!WriteRandomData(writer.get(), &hashes_[name])) {
1050 return AssertionFailure() << "Unable to write random data to snapshot " << name;
1051 }
1052 if (!writer->Finalize()) {
1053 return AssertionFailure() << "Unable to finalize COW for " << name;
1054 }
1055 } else {
1056 std::string path;
1057 auto res = MapUpdateSnapshot(name, &path);
1058 if (!res) {
1059 return res;
1060 }
1061 if (!WriteRandomData(path, std::nullopt, &hashes_[name])) {
1062 return AssertionFailure() << "Unable to write random data to snapshot " << name;
1063 }
1064 }
1065
1066 // Make sure updates to one device are seen by all devices.
1067 sync();
1068
1069 return AssertionSuccess() << "Written random data to snapshot " << name
1070 << ", hash: " << hashes_[name];
1071 }
1072
1073 // Generate a snapshot that moves all the upper blocks down to the start.
1074 // It doesn't really matter the order, we just want copies that reference
1075 // blocks that won't exist if the partition shrinks.
ShiftAllSnapshotBlocks(const std::string & name,uint64_t old_size)1076 AssertionResult ShiftAllSnapshotBlocks(const std::string& name, uint64_t old_size) {
1077 std::unique_ptr<ISnapshotWriter> writer;
1078 if (auto res = MapUpdateSnapshot(name, &writer); !res) {
1079 return res;
1080 }
1081 if (!writer->options().max_blocks || !*writer->options().max_blocks) {
1082 return AssertionFailure() << "No max blocks set for " << name << " writer";
1083 }
1084
1085 uint64_t src_block = (old_size / writer->options().block_size) - 1;
1086 uint64_t dst_block = 0;
1087 uint64_t max_blocks = *writer->options().max_blocks;
1088 while (dst_block < max_blocks && dst_block < src_block) {
1089 if (!writer->AddCopy(dst_block, src_block)) {
1090 return AssertionFailure() << "Unable to add copy for " << name << " for blocks "
1091 << src_block << ", " << dst_block;
1092 }
1093 dst_block++;
1094 src_block--;
1095 }
1096 if (!writer->Finalize()) {
1097 return AssertionFailure() << "Unable to finalize writer for " << name;
1098 }
1099
1100 auto hash = HashSnapshot(writer.get());
1101 if (hash.empty()) {
1102 return AssertionFailure() << "Unable to hash snapshot writer for " << name;
1103 }
1104 hashes_[name] = hash;
1105
1106 return AssertionSuccess();
1107 }
1108
MapUpdateSnapshots(const std::vector<std::string> & names={"sys_b", "vnd_b", "prd_b"})1109 AssertionResult MapUpdateSnapshots(const std::vector<std::string>& names = {"sys_b", "vnd_b",
1110 "prd_b"}) {
1111 for (const auto& name : names) {
1112 auto res = MapOneUpdateSnapshot(name);
1113 if (!res) {
1114 return res;
1115 }
1116 }
1117 return AssertionSuccess();
1118 }
1119
1120 // Create fake install operations to grow the COW device size.
AddOperation(PartitionUpdate * partition_update,uint64_t size_bytes=0)1121 void AddOperation(PartitionUpdate* partition_update, uint64_t size_bytes = 0) {
1122 auto e = partition_update->add_operations()->add_dst_extents();
1123 e->set_start_block(0);
1124 if (size_bytes == 0) {
1125 size_bytes = GetSize(partition_update);
1126 }
1127 e->set_num_blocks(size_bytes / manifest_.block_size());
1128 }
1129
AddOperationForPartitions(std::vector<PartitionUpdate * > partitions={})1130 void AddOperationForPartitions(std::vector<PartitionUpdate*> partitions = {}) {
1131 if (partitions.empty()) {
1132 partitions = {sys_, vnd_, prd_};
1133 }
1134 for (auto* partition : partitions) {
1135 AddOperation(partition);
1136 }
1137 }
1138
1139 std::unique_ptr<TestPartitionOpener> opener_;
1140 DeltaArchiveManifest manifest_;
1141 std::unique_ptr<MetadataBuilder> src_;
1142 std::map<std::string, std::string> hashes_;
1143
1144 PartitionUpdate* sys_ = nullptr;
1145 PartitionUpdate* vnd_ = nullptr;
1146 PartitionUpdate* prd_ = nullptr;
1147 DynamicPartitionGroup* group_ = nullptr;
1148 };
1149
1150 // Test full update flow executed by update_engine. Some partitions uses super empty space,
1151 // some uses images, and some uses both.
1152 // Also test UnmapUpdateSnapshot unmaps everything.
1153 // Also test first stage mount and merge after this.
TEST_F(SnapshotUpdateTest,FullUpdateFlow)1154 TEST_F(SnapshotUpdateTest, FullUpdateFlow) {
1155 // Grow all partitions. Set |prd| large enough that |sys| and |vnd|'s COWs
1156 // fit in super, but not |prd|.
1157 constexpr uint64_t partition_size = 3788_KiB;
1158 SetSize(sys_, partition_size);
1159 SetSize(vnd_, partition_size);
1160 SetSize(prd_, 18_MiB);
1161
1162 // Make sure |prd| does not fit in super at all. On VABC, this means we
1163 // fake an extra large COW for |vnd| to fill up super.
1164 vnd_->set_estimate_cow_size(30_MiB);
1165 prd_->set_estimate_cow_size(30_MiB);
1166
1167 AddOperationForPartitions();
1168
1169 // Execute the update.
1170 ASSERT_TRUE(sm->BeginUpdate());
1171 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1172
1173 // Test that partitions prioritize using space in super.
1174 auto tgt = MetadataBuilder::New(*opener_, "super", 1);
1175 ASSERT_NE(tgt, nullptr);
1176 ASSERT_NE(nullptr, tgt->FindPartition("sys_b-cow"));
1177 ASSERT_NE(nullptr, tgt->FindPartition("vnd_b-cow"));
1178 ASSERT_EQ(nullptr, tgt->FindPartition("prd_b-cow"));
1179
1180 // Write some data to target partitions.
1181 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1182 ASSERT_TRUE(WriteSnapshotAndHash(name));
1183 }
1184
1185 // Assert that source partitions aren't affected.
1186 for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1187 ASSERT_TRUE(IsPartitionUnchanged(name));
1188 }
1189
1190 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1191
1192 // Simulate shutting down the device.
1193 ASSERT_TRUE(UnmapAll());
1194
1195 // After reboot, init does first stage mount.
1196 auto init = NewManagerForFirstStageMount("_b");
1197 ASSERT_NE(init, nullptr);
1198 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1199 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1200
1201 auto indicator = sm->GetRollbackIndicatorPath();
1202 ASSERT_NE(access(indicator.c_str(), R_OK), 0);
1203
1204 // Check that the target partitions have the same content.
1205 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1206 ASSERT_TRUE(IsPartitionUnchanged(name));
1207 }
1208
1209 // Initiate the merge and wait for it to be completed.
1210 ASSERT_TRUE(init->InitiateMerge());
1211 ASSERT_EQ(init->IsSnapuserdRequired(), IsDaemonRequired());
1212 {
1213 // We should have started in SECOND_PHASE since nothing shrinks.
1214 ASSERT_TRUE(AcquireLock());
1215 auto local_lock = std::move(lock_);
1216 auto status = init->ReadSnapshotUpdateStatus(local_lock.get());
1217 ASSERT_EQ(status.merge_phase(), MergePhase::SECOND_PHASE);
1218 }
1219 ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
1220
1221 // Make sure the second phase ran and deleted snapshots.
1222 {
1223 ASSERT_TRUE(AcquireLock());
1224 auto local_lock = std::move(lock_);
1225 std::vector<std::string> snapshots;
1226 ASSERT_TRUE(init->ListSnapshots(local_lock.get(), &snapshots));
1227 ASSERT_TRUE(snapshots.empty());
1228 }
1229
1230 // Check that the target partitions have the same content after the merge.
1231 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1232 ASSERT_TRUE(IsPartitionUnchanged(name))
1233 << "Content of " << name << " changes after the merge";
1234 }
1235 }
1236
TEST_F(SnapshotUpdateTest,DuplicateOps)1237 TEST_F(SnapshotUpdateTest, DuplicateOps) {
1238 if (!ShouldUseCompression()) {
1239 GTEST_SKIP() << "Compression-only test";
1240 }
1241
1242 // Execute the update.
1243 ASSERT_TRUE(sm->BeginUpdate());
1244 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1245
1246 // Write some data to target partitions.
1247 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1248 ASSERT_TRUE(WriteSnapshotAndHash(name));
1249 }
1250
1251 std::vector<PartitionUpdate*> partitions = {sys_, vnd_, prd_};
1252 for (auto* partition : partitions) {
1253 AddOperation(partition);
1254
1255 std::unique_ptr<ISnapshotWriter> writer;
1256 auto res = MapUpdateSnapshot(partition->partition_name() + "_b", &writer);
1257 ASSERT_TRUE(res);
1258 ASSERT_TRUE(writer->AddZeroBlocks(0, 1));
1259 ASSERT_TRUE(writer->AddZeroBlocks(0, 1));
1260 ASSERT_TRUE(writer->Finalize());
1261 }
1262
1263 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1264
1265 // Simulate shutting down the device.
1266 ASSERT_TRUE(UnmapAll());
1267
1268 // After reboot, init does first stage mount.
1269 auto init = NewManagerForFirstStageMount("_b");
1270 ASSERT_NE(init, nullptr);
1271 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1272 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1273
1274 // Initiate the merge and wait for it to be completed.
1275 ASSERT_TRUE(init->InitiateMerge());
1276 ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
1277 }
1278
1279 // Test that shrinking and growing partitions at the same time is handled
1280 // correctly in VABC.
TEST_F(SnapshotUpdateTest,SpaceSwapUpdate)1281 TEST_F(SnapshotUpdateTest, SpaceSwapUpdate) {
1282 if (!ShouldUseCompression()) {
1283 // b/179111359
1284 GTEST_SKIP() << "Skipping Virtual A/B Compression test";
1285 }
1286
1287 auto old_sys_size = GetSize(sys_);
1288 auto old_prd_size = GetSize(prd_);
1289
1290 // Grow |sys| but shrink |prd|.
1291 SetSize(sys_, old_sys_size * 2);
1292 sys_->set_estimate_cow_size(8_MiB);
1293 SetSize(prd_, old_prd_size / 2);
1294 prd_->set_estimate_cow_size(1_MiB);
1295
1296 AddOperationForPartitions();
1297
1298 ASSERT_TRUE(sm->BeginUpdate());
1299 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1300
1301 // Check that the old partition sizes were saved correctly.
1302 {
1303 ASSERT_TRUE(AcquireLock());
1304 auto local_lock = std::move(lock_);
1305
1306 SnapshotStatus status;
1307 ASSERT_TRUE(sm->ReadSnapshotStatus(local_lock.get(), "prd_b", &status));
1308 ASSERT_EQ(status.old_partition_size(), 3145728);
1309 ASSERT_TRUE(sm->ReadSnapshotStatus(local_lock.get(), "sys_b", &status));
1310 ASSERT_EQ(status.old_partition_size(), 3145728);
1311 }
1312
1313 ASSERT_TRUE(WriteSnapshotAndHash("sys_b"));
1314 ASSERT_TRUE(WriteSnapshotAndHash("vnd_b"));
1315 ASSERT_TRUE(ShiftAllSnapshotBlocks("prd_b", old_prd_size));
1316
1317 sync();
1318
1319 // Assert that source partitions aren't affected.
1320 for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1321 ASSERT_TRUE(IsPartitionUnchanged(name));
1322 }
1323
1324 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1325
1326 // Simulate shutting down the device.
1327 ASSERT_TRUE(UnmapAll());
1328
1329 // After reboot, init does first stage mount.
1330 auto init = NewManagerForFirstStageMount("_b");
1331 ASSERT_NE(init, nullptr);
1332 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1333 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1334
1335 auto indicator = sm->GetRollbackIndicatorPath();
1336 ASSERT_NE(access(indicator.c_str(), R_OK), 0);
1337
1338 // Check that the target partitions have the same content.
1339 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1340 ASSERT_TRUE(IsPartitionUnchanged(name));
1341 }
1342
1343 // Initiate the merge and wait for it to be completed.
1344 ASSERT_TRUE(init->InitiateMerge());
1345 ASSERT_EQ(init->IsSnapuserdRequired(), IsDaemonRequired());
1346 {
1347 // Check that the merge phase is FIRST_PHASE until at least one call
1348 // to ProcessUpdateState() occurs.
1349 ASSERT_TRUE(AcquireLock());
1350 auto local_lock = std::move(lock_);
1351 auto status = init->ReadSnapshotUpdateStatus(local_lock.get());
1352 ASSERT_EQ(status.merge_phase(), MergePhase::FIRST_PHASE);
1353 }
1354
1355 // Simulate shutting down the device and creating partitions again.
1356 ASSERT_TRUE(UnmapAll());
1357 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1358
1359 // Check that we used the correct types after rebooting mid-merge.
1360 DeviceMapper::TargetInfo target;
1361 ASSERT_TRUE(init->IsSnapshotDevice("prd_b", &target));
1362
1363 bool userspace_snapshots = init->UpdateUsesUserSnapshots();
1364 if (userspace_snapshots) {
1365 ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
1366 ASSERT_TRUE(init->IsSnapshotDevice("sys_b", &target));
1367 ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
1368 ASSERT_TRUE(init->IsSnapshotDevice("vnd_b", &target));
1369 ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
1370 } else {
1371 ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot-merge");
1372 ASSERT_TRUE(init->IsSnapshotDevice("sys_b", &target));
1373 ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot");
1374 ASSERT_TRUE(init->IsSnapshotDevice("vnd_b", &target));
1375 ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot");
1376 }
1377
1378 // Complete the merge.
1379 ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
1380
1381 // Make sure the second phase ran and deleted snapshots.
1382 {
1383 ASSERT_TRUE(AcquireLock());
1384 auto local_lock = std::move(lock_);
1385 std::vector<std::string> snapshots;
1386 ASSERT_TRUE(init->ListSnapshots(local_lock.get(), &snapshots));
1387 ASSERT_TRUE(snapshots.empty());
1388 }
1389
1390 // Check that the target partitions have the same content after the merge.
1391 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1392 ASSERT_TRUE(IsPartitionUnchanged(name))
1393 << "Content of " << name << " changes after the merge";
1394 }
1395 }
1396
1397 // Test that a transient merge consistency check failure can resume properly.
TEST_F(SnapshotUpdateTest,ConsistencyCheckResume)1398 TEST_F(SnapshotUpdateTest, ConsistencyCheckResume) {
1399 if (!ShouldUseCompression()) {
1400 // b/179111359
1401 GTEST_SKIP() << "Skipping Virtual A/B Compression test";
1402 }
1403
1404 auto old_sys_size = GetSize(sys_);
1405 auto old_prd_size = GetSize(prd_);
1406
1407 // Grow |sys| but shrink |prd|.
1408 SetSize(sys_, old_sys_size * 2);
1409 sys_->set_estimate_cow_size(8_MiB);
1410 SetSize(prd_, old_prd_size / 2);
1411 prd_->set_estimate_cow_size(1_MiB);
1412
1413 AddOperationForPartitions();
1414
1415 ASSERT_TRUE(sm->BeginUpdate());
1416 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1417 ASSERT_TRUE(WriteSnapshotAndHash("sys_b"));
1418 ASSERT_TRUE(WriteSnapshotAndHash("vnd_b"));
1419 ASSERT_TRUE(ShiftAllSnapshotBlocks("prd_b", old_prd_size));
1420
1421 sync();
1422
1423 // Assert that source partitions aren't affected.
1424 for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1425 ASSERT_TRUE(IsPartitionUnchanged(name));
1426 }
1427
1428 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1429
1430 // Simulate shutting down the device.
1431 ASSERT_TRUE(UnmapAll());
1432
1433 // After reboot, init does first stage mount.
1434 auto init = NewManagerForFirstStageMount("_b");
1435 ASSERT_NE(init, nullptr);
1436 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1437 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1438
1439 // Check that the target partitions have the same content.
1440 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1441 ASSERT_TRUE(IsPartitionUnchanged(name));
1442 }
1443
1444 auto old_checker = init->merge_consistency_checker();
1445
1446 init->set_merge_consistency_checker(
1447 [](const std::string&, const SnapshotStatus&) -> MergeFailureCode {
1448 return MergeFailureCode::WrongMergeCountConsistencyCheck;
1449 });
1450
1451 // Initiate the merge and wait for it to be completed.
1452 ASSERT_TRUE(init->InitiateMerge());
1453 ASSERT_EQ(init->IsSnapuserdRequired(), IsDaemonRequired());
1454 {
1455 // Check that the merge phase is FIRST_PHASE until at least one call
1456 // to ProcessUpdateState() occurs.
1457 ASSERT_TRUE(AcquireLock());
1458 auto local_lock = std::move(lock_);
1459 auto status = init->ReadSnapshotUpdateStatus(local_lock.get());
1460 ASSERT_EQ(status.merge_phase(), MergePhase::FIRST_PHASE);
1461 }
1462
1463 // Merge should have failed.
1464 ASSERT_EQ(UpdateState::MergeFailed, init->ProcessUpdateState());
1465
1466 // Simulate shutting down the device and creating partitions again.
1467 ASSERT_TRUE(UnmapAll());
1468
1469 // Restore the checker.
1470 init->set_merge_consistency_checker(std::move(old_checker));
1471
1472 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1473
1474 // Complete the merge.
1475 ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
1476
1477 // Check that the target partitions have the same content after the merge.
1478 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1479 ASSERT_TRUE(IsPartitionUnchanged(name))
1480 << "Content of " << name << " changes after the merge";
1481 }
1482 }
1483
1484 // Test that if new system partitions uses empty space in super, that region is not snapshotted.
TEST_F(SnapshotUpdateTest,DirectWriteEmptySpace)1485 TEST_F(SnapshotUpdateTest, DirectWriteEmptySpace) {
1486 GTEST_SKIP() << "b/141889746";
1487 SetSize(sys_, 4_MiB);
1488 // vnd_b and prd_b are unchanged.
1489 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1490 ASSERT_EQ(3_MiB, GetSnapshotSize("sys_b").value_or(0));
1491 }
1492
1493 // Test that if new system partitions uses space of old vendor partition, that region is
1494 // snapshotted.
TEST_F(SnapshotUpdateTest,SnapshotOldPartitions)1495 TEST_F(SnapshotUpdateTest, SnapshotOldPartitions) {
1496 SetSize(sys_, 4_MiB); // grows
1497 SetSize(vnd_, 2_MiB); // shrinks
1498 // prd_b is unchanged
1499 ASSERT_TRUE(sm->BeginUpdate());
1500 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1501 ASSERT_EQ(4_MiB, GetSnapshotSize("sys_b").value_or(0));
1502 }
1503
1504 // Test that even if there seem to be empty space in target metadata, COW partition won't take
1505 // it because they are used by old partitions.
TEST_F(SnapshotUpdateTest,CowPartitionDoNotTakeOldPartitions)1506 TEST_F(SnapshotUpdateTest, CowPartitionDoNotTakeOldPartitions) {
1507 SetSize(sys_, 2_MiB); // shrinks
1508 // vnd_b and prd_b are unchanged.
1509 ASSERT_TRUE(sm->BeginUpdate());
1510 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1511
1512 auto tgt = MetadataBuilder::New(*opener_, "super", 1);
1513 ASSERT_NE(nullptr, tgt);
1514 auto metadata = tgt->Export();
1515 ASSERT_NE(nullptr, metadata);
1516 std::vector<std::string> written;
1517 // Write random data to all COW partitions in super
1518 for (auto p : metadata->partitions) {
1519 if (GetPartitionGroupName(metadata->groups[p.group_index]) != kCowGroupName) {
1520 continue;
1521 }
1522 std::string path;
1523 ASSERT_TRUE(CreateLogicalPartition(
1524 CreateLogicalPartitionParams{
1525 .block_device = fake_super,
1526 .metadata = metadata.get(),
1527 .partition = &p,
1528 .timeout_ms = 1s,
1529 .partition_opener = opener_.get(),
1530 },
1531 &path));
1532 ASSERT_TRUE(WriteRandomData(path));
1533 written.push_back(GetPartitionName(p));
1534 }
1535 ASSERT_FALSE(written.empty())
1536 << "No COW partitions are created even if there are empty space in super partition";
1537
1538 // Make sure source partitions aren't affected.
1539 for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1540 ASSERT_TRUE(IsPartitionUnchanged(name));
1541 }
1542 }
1543
1544 // Test that it crashes after creating snapshot status file but before creating COW image, then
1545 // calling CreateUpdateSnapshots again works.
TEST_F(SnapshotUpdateTest,SnapshotStatusFileWithoutCow)1546 TEST_F(SnapshotUpdateTest, SnapshotStatusFileWithoutCow) {
1547 // Write some trash snapshot files to simulate leftovers from previous runs.
1548 {
1549 ASSERT_TRUE(AcquireLock());
1550 auto local_lock = std::move(lock_);
1551 SnapshotStatus status;
1552 status.set_name("sys_b");
1553 ASSERT_TRUE(sm->WriteSnapshotStatus(local_lock.get(), status));
1554 ASSERT_TRUE(image_manager_->CreateBackingImage("sys_b-cow-img", 1_MiB,
1555 IImageManager::CREATE_IMAGE_DEFAULT));
1556 }
1557
1558 // Redo the update.
1559 ASSERT_TRUE(sm->BeginUpdate());
1560 ASSERT_TRUE(sm->UnmapUpdateSnapshot("sys_b"));
1561
1562 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1563
1564 // Check that target partitions can be mapped.
1565 EXPECT_TRUE(MapUpdateSnapshots());
1566 }
1567
1568 // Test that the old partitions are not modified.
TEST_F(SnapshotUpdateTest,TestRollback)1569 TEST_F(SnapshotUpdateTest, TestRollback) {
1570 // Execute the update.
1571 ASSERT_TRUE(sm->BeginUpdate());
1572 ASSERT_TRUE(sm->UnmapUpdateSnapshot("sys_b"));
1573
1574 AddOperationForPartitions();
1575
1576 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1577
1578 // Write some data to target partitions.
1579 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1580 ASSERT_TRUE(WriteSnapshotAndHash(name));
1581 }
1582
1583 // Assert that source partitions aren't affected.
1584 for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1585 ASSERT_TRUE(IsPartitionUnchanged(name));
1586 }
1587
1588 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1589
1590 // Simulate shutting down the device.
1591 ASSERT_TRUE(UnmapAll());
1592
1593 // After reboot, init does first stage mount.
1594 auto init = NewManagerForFirstStageMount("_b");
1595 ASSERT_NE(init, nullptr);
1596 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1597 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1598
1599 // Check that the target partitions have the same content.
1600 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1601 ASSERT_TRUE(IsPartitionUnchanged(name));
1602 }
1603
1604 // Simulate shutting down the device again.
1605 ASSERT_TRUE(UnmapAll());
1606 init = NewManagerForFirstStageMount("_a");
1607 ASSERT_NE(init, nullptr);
1608 ASSERT_FALSE(init->NeedSnapshotsInFirstStageMount());
1609 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1610
1611 // Assert that the source partitions aren't affected.
1612 for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1613 ASSERT_TRUE(IsPartitionUnchanged(name));
1614 }
1615 }
1616
1617 // Test that if an update is applied but not booted into, it can be canceled.
TEST_F(SnapshotUpdateTest,CancelAfterApply)1618 TEST_F(SnapshotUpdateTest, CancelAfterApply) {
1619 ASSERT_TRUE(sm->BeginUpdate());
1620 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1621 ASSERT_TRUE(sm->CancelUpdate());
1622 }
1623
ToIntervals(const std::vector<std::unique_ptr<Extent>> & extents)1624 static std::vector<Interval> ToIntervals(const std::vector<std::unique_ptr<Extent>>& extents) {
1625 std::vector<Interval> ret;
1626 std::transform(extents.begin(), extents.end(), std::back_inserter(ret),
1627 [](const auto& extent) { return extent->AsLinearExtent()->AsInterval(); });
1628 return ret;
1629 }
1630
1631 // Test that at the second update, old COW partition spaces are reclaimed.
TEST_F(SnapshotUpdateTest,ReclaimCow)1632 TEST_F(SnapshotUpdateTest, ReclaimCow) {
1633 // Make sure VABC cows are small enough that they fit in fake_super.
1634 sys_->set_estimate_cow_size(64_KiB);
1635 vnd_->set_estimate_cow_size(64_KiB);
1636 prd_->set_estimate_cow_size(64_KiB);
1637
1638 // Execute the first update.
1639 ASSERT_TRUE(sm->BeginUpdate());
1640 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1641 ASSERT_TRUE(MapUpdateSnapshots());
1642 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1643
1644 // Simulate shutting down the device.
1645 ASSERT_TRUE(UnmapAll());
1646
1647 // After reboot, init does first stage mount.
1648 auto init = NewManagerForFirstStageMount("_b");
1649 ASSERT_NE(init, nullptr);
1650 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1651 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1652 init = nullptr;
1653
1654 // Initiate the merge and wait for it to be completed.
1655 auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
1656 ASSERT_TRUE(new_sm->InitiateMerge());
1657 ASSERT_EQ(UpdateState::MergeCompleted, new_sm->ProcessUpdateState());
1658
1659 // Execute the second update.
1660 ASSERT_TRUE(new_sm->BeginUpdate());
1661 ASSERT_TRUE(new_sm->CreateUpdateSnapshots(manifest_));
1662
1663 // Check that the old COW space is reclaimed and does not occupy space of mapped partitions.
1664 auto src = MetadataBuilder::New(*opener_, "super", 1);
1665 ASSERT_NE(src, nullptr);
1666 auto tgt = MetadataBuilder::New(*opener_, "super", 0);
1667 ASSERT_NE(tgt, nullptr);
1668 for (const auto& cow_part_name : {"sys_a-cow", "vnd_a-cow", "prd_a-cow"}) {
1669 auto* cow_part = tgt->FindPartition(cow_part_name);
1670 ASSERT_NE(nullptr, cow_part) << cow_part_name << " does not exist in target metadata";
1671 auto cow_intervals = ToIntervals(cow_part->extents());
1672 for (const auto& old_part_name : {"sys_b", "vnd_b", "prd_b"}) {
1673 auto* old_part = src->FindPartition(old_part_name);
1674 ASSERT_NE(nullptr, old_part) << old_part_name << " does not exist in source metadata";
1675 auto old_intervals = ToIntervals(old_part->extents());
1676
1677 auto intersect = Interval::Intersect(cow_intervals, old_intervals);
1678 ASSERT_TRUE(intersect.empty()) << "COW uses space of source partitions";
1679 }
1680 }
1681 }
1682
TEST_F(SnapshotUpdateTest,RetrofitAfterRegularAb)1683 TEST_F(SnapshotUpdateTest, RetrofitAfterRegularAb) {
1684 constexpr auto kRetrofitGroupSize = kGroupSize / 2;
1685
1686 // Initialize device-mapper / disk
1687 ASSERT_TRUE(UnmapAll());
1688 FormatFakeSuper();
1689
1690 // Setup source partition metadata to have both _a and _b partitions.
1691 src_ = MetadataBuilder::New(*opener_, "super", 0);
1692 ASSERT_NE(nullptr, src_);
1693 for (const auto& suffix : {"_a"s, "_b"s}) {
1694 ASSERT_TRUE(src_->AddGroup(group_->name() + suffix, kRetrofitGroupSize));
1695 for (const auto& name : {"sys"s, "vnd"s, "prd"s}) {
1696 auto partition = src_->AddPartition(name + suffix, group_->name() + suffix, 0);
1697 ASSERT_NE(nullptr, partition);
1698 ASSERT_TRUE(src_->ResizePartition(partition, 2_MiB));
1699 }
1700 }
1701 auto metadata = src_->Export();
1702 ASSERT_NE(nullptr, metadata);
1703 ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *metadata.get(), 0));
1704
1705 // Flash source partitions
1706 std::string path;
1707 for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1708 ASSERT_TRUE(CreateLogicalPartition(
1709 CreateLogicalPartitionParams{
1710 .block_device = fake_super,
1711 .metadata_slot = 0,
1712 .partition_name = name,
1713 .timeout_ms = 1s,
1714 .partition_opener = opener_.get(),
1715 },
1716 &path));
1717 ASSERT_TRUE(WriteRandomData(path));
1718 auto hash = GetHash(path);
1719 ASSERT_TRUE(hash.has_value());
1720 hashes_[name] = *hash;
1721 }
1722
1723 // Setup manifest.
1724 group_->set_size(kRetrofitGroupSize);
1725 for (auto* partition : {sys_, vnd_, prd_}) {
1726 SetSize(partition, 2_MiB);
1727 }
1728 AddOperationForPartitions();
1729
1730 ASSERT_TRUE(sm->BeginUpdate());
1731 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1732
1733 // Test that COW image should not be created for retrofit devices; super
1734 // should be big enough.
1735 ASSERT_FALSE(image_manager_->BackingImageExists("sys_b-cow-img"));
1736 ASSERT_FALSE(image_manager_->BackingImageExists("vnd_b-cow-img"));
1737 ASSERT_FALSE(image_manager_->BackingImageExists("prd_b-cow-img"));
1738
1739 // Write some data to target partitions.
1740 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1741 ASSERT_TRUE(WriteSnapshotAndHash(name));
1742 }
1743
1744 // Assert that source partitions aren't affected.
1745 for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1746 ASSERT_TRUE(IsPartitionUnchanged(name));
1747 }
1748
1749 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1750 }
1751
TEST_F(SnapshotUpdateTest,MergeCannotRemoveCow)1752 TEST_F(SnapshotUpdateTest, MergeCannotRemoveCow) {
1753 // Make source partitions as big as possible to force COW image to be created.
1754 SetSize(sys_, 10_MiB);
1755 SetSize(vnd_, 10_MiB);
1756 SetSize(prd_, 10_MiB);
1757 sys_->set_estimate_cow_size(12_MiB);
1758 vnd_->set_estimate_cow_size(12_MiB);
1759 prd_->set_estimate_cow_size(12_MiB);
1760
1761 src_ = MetadataBuilder::New(*opener_, "super", 0);
1762 ASSERT_NE(src_, nullptr);
1763 src_->RemoveGroupAndPartitions(group_->name() + "_a");
1764 src_->RemoveGroupAndPartitions(group_->name() + "_b");
1765 ASSERT_TRUE(FillFakeMetadata(src_.get(), manifest_, "_a"));
1766 auto metadata = src_->Export();
1767 ASSERT_NE(nullptr, metadata);
1768 ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *metadata.get(), 0));
1769
1770 // Add operations for sys. The whole device is written.
1771 AddOperation(sys_);
1772
1773 // Execute the update.
1774 ASSERT_TRUE(sm->BeginUpdate());
1775 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1776 ASSERT_TRUE(MapUpdateSnapshots());
1777 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1778
1779 // Simulate shutting down the device.
1780 ASSERT_TRUE(UnmapAll());
1781
1782 // After reboot, init does first stage mount.
1783 // Normally we should use NewManagerForFirstStageMount, but if so,
1784 // "gsid.mapped_image.sys_b-cow-img" won't be set.
1785 auto init = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
1786 ASSERT_NE(init, nullptr);
1787 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1788
1789 // Keep an open handle to the cow device. This should cause the merge to
1790 // be incomplete.
1791 auto cow_path = android::base::GetProperty("gsid.mapped_image.sys_b-cow-img", "");
1792 unique_fd fd(open(cow_path.c_str(), O_RDONLY | O_CLOEXEC));
1793 ASSERT_GE(fd, 0);
1794
1795 // COW cannot be removed due to open fd, so expect a soft failure.
1796 ASSERT_TRUE(init->InitiateMerge());
1797 ASSERT_EQ(UpdateState::MergeNeedsReboot, init->ProcessUpdateState());
1798
1799 // Simulate shutting down the device.
1800 fd.reset();
1801 ASSERT_TRUE(UnmapAll());
1802
1803 // init does first stage mount again.
1804 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1805
1806 // sys_b should be mapped as a dm-linear device directly.
1807 ASSERT_FALSE(sm->IsSnapshotDevice("sys_b", nullptr));
1808
1809 // Merge should be able to complete now.
1810 ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
1811 }
1812
1813 class MetadataMountedTest : public ::testing::Test {
1814 public:
1815 // This is so main() can instantiate this to invoke Cleanup.
TestBody()1816 virtual void TestBody() override {}
SetUp()1817 void SetUp() override {
1818 SKIP_IF_NON_VIRTUAL_AB();
1819 metadata_dir_ = test_device->GetMetadataDir();
1820 ASSERT_TRUE(ReadDefaultFstab(&fstab_));
1821 }
TearDown()1822 void TearDown() override {
1823 RETURN_IF_NON_VIRTUAL_AB();
1824 SetUp();
1825 // Remount /metadata
1826 test_device->set_recovery(false);
1827 EXPECT_TRUE(android::fs_mgr::EnsurePathMounted(&fstab_, metadata_dir_));
1828 }
IsMetadataMounted()1829 AssertionResult IsMetadataMounted() {
1830 Fstab mounted_fstab;
1831 if (!ReadFstabFromFile("/proc/mounts", &mounted_fstab)) {
1832 ADD_FAILURE() << "Failed to scan mounted volumes";
1833 return AssertionFailure() << "Failed to scan mounted volumes";
1834 }
1835
1836 auto entry = GetEntryForPath(&fstab_, metadata_dir_);
1837 if (entry == nullptr) {
1838 return AssertionFailure() << "No mount point found in fstab for path " << metadata_dir_;
1839 }
1840
1841 auto mv = GetEntryForMountPoint(&mounted_fstab, entry->mount_point);
1842 if (mv == nullptr) {
1843 return AssertionFailure() << metadata_dir_ << " is not mounted";
1844 }
1845 return AssertionSuccess() << metadata_dir_ << " is mounted";
1846 }
1847 std::string metadata_dir_;
1848 Fstab fstab_;
1849 };
1850
MountMetadata()1851 void MountMetadata() {
1852 MetadataMountedTest().TearDown();
1853 }
1854
TEST_F(MetadataMountedTest,Android)1855 TEST_F(MetadataMountedTest, Android) {
1856 auto device = sm->EnsureMetadataMounted();
1857 EXPECT_NE(nullptr, device);
1858 device.reset();
1859
1860 EXPECT_TRUE(IsMetadataMounted());
1861 EXPECT_TRUE(sm->CancelUpdate()) << "Metadata dir should never be unmounted in Android mode";
1862 }
1863
TEST_F(MetadataMountedTest,Recovery)1864 TEST_F(MetadataMountedTest, Recovery) {
1865 test_device->set_recovery(true);
1866 metadata_dir_ = test_device->GetMetadataDir();
1867
1868 EXPECT_TRUE(android::fs_mgr::EnsurePathUnmounted(&fstab_, metadata_dir_));
1869 EXPECT_FALSE(IsMetadataMounted());
1870
1871 auto device = sm->EnsureMetadataMounted();
1872 EXPECT_NE(nullptr, device);
1873 EXPECT_TRUE(IsMetadataMounted());
1874
1875 device.reset();
1876 EXPECT_FALSE(IsMetadataMounted());
1877 }
1878
1879 // Test that during a merge, we can wipe data in recovery.
TEST_F(SnapshotUpdateTest,MergeInRecovery)1880 TEST_F(SnapshotUpdateTest, MergeInRecovery) {
1881 // Execute the first update.
1882 ASSERT_TRUE(sm->BeginUpdate());
1883 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1884 ASSERT_TRUE(MapUpdateSnapshots());
1885 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1886
1887 // Simulate shutting down the device.
1888 ASSERT_TRUE(UnmapAll());
1889
1890 // After reboot, init does first stage mount.
1891 auto init = NewManagerForFirstStageMount("_b");
1892 ASSERT_NE(init, nullptr);
1893 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1894 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1895 init = nullptr;
1896
1897 // Initiate the merge and then immediately stop it to simulate a reboot.
1898 auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
1899 ASSERT_TRUE(new_sm->InitiateMerge());
1900 ASSERT_TRUE(UnmapAll());
1901
1902 // Simulate a reboot into recovery.
1903 auto test_device = std::make_unique<TestDeviceInfo>(fake_super, "_b");
1904 test_device->set_recovery(true);
1905 new_sm = NewManagerForFirstStageMount(test_device.release());
1906
1907 ASSERT_TRUE(new_sm->HandleImminentDataWipe());
1908 ASSERT_EQ(new_sm->GetUpdateState(), UpdateState::None);
1909 }
1910
1911 // Test that a merge does not clear the snapshot state in fastboot.
TEST_F(SnapshotUpdateTest,MergeInFastboot)1912 TEST_F(SnapshotUpdateTest, MergeInFastboot) {
1913 // Execute the first update.
1914 ASSERT_TRUE(sm->BeginUpdate());
1915 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1916 ASSERT_TRUE(MapUpdateSnapshots());
1917 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1918
1919 // Simulate shutting down the device.
1920 ASSERT_TRUE(UnmapAll());
1921
1922 // After reboot, init does first stage mount.
1923 auto init = NewManagerForFirstStageMount("_b");
1924 ASSERT_NE(init, nullptr);
1925 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1926 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1927 init = nullptr;
1928
1929 // Initiate the merge and then immediately stop it to simulate a reboot.
1930 auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
1931 ASSERT_TRUE(new_sm->InitiateMerge());
1932 ASSERT_TRUE(UnmapAll());
1933
1934 // Simulate a reboot into recovery.
1935 auto test_device = std::make_unique<TestDeviceInfo>(fake_super, "_b");
1936 test_device->set_recovery(true);
1937 new_sm = NewManagerForFirstStageMount(test_device.release());
1938
1939 ASSERT_TRUE(new_sm->FinishMergeInRecovery());
1940
1941 ASSERT_TRUE(UnmapAll());
1942
1943 auto mount = new_sm->EnsureMetadataMounted();
1944 ASSERT_TRUE(mount && mount->HasDevice());
1945 ASSERT_EQ(new_sm->ProcessUpdateState(), UpdateState::MergeCompleted);
1946
1947 // Finish the merge in a normal boot.
1948 test_device = std::make_unique<TestDeviceInfo>(fake_super, "_b");
1949 init = NewManagerForFirstStageMount(test_device.release());
1950 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1951 init = nullptr;
1952
1953 test_device = std::make_unique<TestDeviceInfo>(fake_super, "_b");
1954 new_sm = NewManagerForFirstStageMount(test_device.release());
1955 ASSERT_EQ(new_sm->ProcessUpdateState(), UpdateState::MergeCompleted);
1956 ASSERT_EQ(new_sm->ProcessUpdateState(), UpdateState::None);
1957 }
1958
1959 // Test that after an OTA, before a merge, we can wipe data in recovery.
TEST_F(SnapshotUpdateTest,DataWipeRollbackInRecovery)1960 TEST_F(SnapshotUpdateTest, DataWipeRollbackInRecovery) {
1961 // Execute the first update.
1962 ASSERT_TRUE(sm->BeginUpdate());
1963 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1964 ASSERT_TRUE(MapUpdateSnapshots());
1965 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1966
1967 // Simulate shutting down the device.
1968 ASSERT_TRUE(UnmapAll());
1969
1970 // Simulate a reboot into recovery.
1971 auto test_device = new TestDeviceInfo(fake_super, "_b");
1972 test_device->set_recovery(true);
1973 auto new_sm = NewManagerForFirstStageMount(test_device);
1974
1975 ASSERT_TRUE(new_sm->HandleImminentDataWipe());
1976 // Manually mount metadata so that we can call GetUpdateState() below.
1977 MountMetadata();
1978 EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::None);
1979 EXPECT_TRUE(test_device->IsSlotUnbootable(1));
1980 EXPECT_FALSE(test_device->IsSlotUnbootable(0));
1981 }
1982
1983 // Test that after an OTA and a bootloader rollback with no merge, we can wipe
1984 // data in recovery.
TEST_F(SnapshotUpdateTest,DataWipeAfterRollback)1985 TEST_F(SnapshotUpdateTest, DataWipeAfterRollback) {
1986 // Execute the first update.
1987 ASSERT_TRUE(sm->BeginUpdate());
1988 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1989 ASSERT_TRUE(MapUpdateSnapshots());
1990 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1991
1992 // Simulate shutting down the device.
1993 ASSERT_TRUE(UnmapAll());
1994
1995 // Simulate a rollback, with reboot into recovery.
1996 auto test_device = new TestDeviceInfo(fake_super, "_a");
1997 test_device->set_recovery(true);
1998 auto new_sm = NewManagerForFirstStageMount(test_device);
1999
2000 ASSERT_TRUE(new_sm->HandleImminentDataWipe());
2001 EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::None);
2002 EXPECT_FALSE(test_device->IsSlotUnbootable(0));
2003 EXPECT_FALSE(test_device->IsSlotUnbootable(1));
2004 }
2005
2006 // Test update package that requests data wipe.
TEST_F(SnapshotUpdateTest,DataWipeRequiredInPackage)2007 TEST_F(SnapshotUpdateTest, DataWipeRequiredInPackage) {
2008 AddOperationForPartitions();
2009 // Execute the update.
2010 ASSERT_TRUE(sm->BeginUpdate());
2011 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2012
2013 // Write some data to target partitions.
2014 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
2015 ASSERT_TRUE(WriteSnapshotAndHash(name)) << name;
2016 }
2017
2018 ASSERT_TRUE(sm->FinishedSnapshotWrites(true /* wipe */));
2019
2020 // Simulate shutting down the device.
2021 ASSERT_TRUE(UnmapAll());
2022
2023 // Simulate a reboot into recovery.
2024 auto test_device = new TestDeviceInfo(fake_super, "_b");
2025 test_device->set_recovery(true);
2026 auto new_sm = NewManagerForFirstStageMount(test_device);
2027
2028 ASSERT_TRUE(new_sm->HandleImminentDataWipe());
2029 // Manually mount metadata so that we can call GetUpdateState() below.
2030 MountMetadata();
2031 EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::None);
2032 ASSERT_FALSE(test_device->IsSlotUnbootable(1));
2033 ASSERT_FALSE(test_device->IsSlotUnbootable(0));
2034
2035 ASSERT_TRUE(UnmapAll());
2036
2037 // Now reboot into new slot.
2038 test_device = new TestDeviceInfo(fake_super, "_b");
2039 auto init = NewManagerForFirstStageMount(test_device);
2040 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2041 // Verify that we are on the downgraded build.
2042 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
2043 ASSERT_TRUE(IsPartitionUnchanged(name)) << name;
2044 }
2045 }
2046
2047 // Test update package that requests data wipe.
TEST_F(SnapshotUpdateTest,DataWipeWithStaleSnapshots)2048 TEST_F(SnapshotUpdateTest, DataWipeWithStaleSnapshots) {
2049 AddOperationForPartitions();
2050
2051 // Execute the update.
2052 ASSERT_TRUE(sm->BeginUpdate());
2053 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2054
2055 // Write some data to target partitions.
2056 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
2057 ASSERT_TRUE(WriteSnapshotAndHash(name)) << name;
2058 }
2059
2060 // Create a stale snapshot that should not exist.
2061 {
2062 ASSERT_TRUE(AcquireLock());
2063
2064 PartitionCowCreator cow_creator = {
2065 .compression_enabled = ShouldUseCompression(),
2066 .compression_algorithm = ShouldUseCompression() ? "gz" : "none",
2067 };
2068 SnapshotStatus status;
2069 status.set_name("sys_a");
2070 status.set_device_size(1_MiB);
2071 status.set_snapshot_size(2_MiB);
2072 status.set_cow_partition_size(2_MiB);
2073
2074 ASSERT_TRUE(sm->CreateSnapshot(lock_.get(), &cow_creator, &status));
2075 lock_ = nullptr;
2076
2077 ASSERT_TRUE(sm->EnsureImageManager());
2078 ASSERT_TRUE(sm->image_manager()->CreateBackingImage("sys_a", 1_MiB, 0));
2079 }
2080
2081 ASSERT_TRUE(sm->FinishedSnapshotWrites(true /* wipe */));
2082
2083 // Simulate shutting down the device.
2084 ASSERT_TRUE(UnmapAll());
2085
2086 // Simulate a reboot into recovery.
2087 auto test_device = new TestDeviceInfo(fake_super, "_b");
2088 test_device->set_recovery(true);
2089 auto new_sm = NewManagerForFirstStageMount(test_device);
2090
2091 ASSERT_TRUE(new_sm->HandleImminentDataWipe());
2092 // Manually mount metadata so that we can call GetUpdateState() below.
2093 MountMetadata();
2094 EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::None);
2095 ASSERT_FALSE(test_device->IsSlotUnbootable(1));
2096 ASSERT_FALSE(test_device->IsSlotUnbootable(0));
2097
2098 ASSERT_TRUE(UnmapAll());
2099
2100 // Now reboot into new slot.
2101 test_device = new TestDeviceInfo(fake_super, "_b");
2102 auto init = NewManagerForFirstStageMount(test_device);
2103 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2104 // Verify that we are on the downgraded build.
2105 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
2106 ASSERT_TRUE(IsPartitionUnchanged(name)) << name;
2107 }
2108 }
2109
TEST_F(SnapshotUpdateTest,Hashtree)2110 TEST_F(SnapshotUpdateTest, Hashtree) {
2111 constexpr auto partition_size = 4_MiB;
2112 constexpr auto data_size = 3_MiB;
2113 constexpr auto hashtree_size = 512_KiB;
2114 constexpr auto fec_size = partition_size - data_size - hashtree_size;
2115
2116 const auto block_size = manifest_.block_size();
2117 SetSize(sys_, partition_size);
2118 AddOperation(sys_, data_size);
2119
2120 sys_->set_estimate_cow_size(partition_size + data_size);
2121
2122 // Set hastree extents.
2123 sys_->mutable_hash_tree_data_extent()->set_start_block(0);
2124 sys_->mutable_hash_tree_data_extent()->set_num_blocks(data_size / block_size);
2125
2126 sys_->mutable_hash_tree_extent()->set_start_block(data_size / block_size);
2127 sys_->mutable_hash_tree_extent()->set_num_blocks(hashtree_size / block_size);
2128
2129 // Set FEC extents.
2130 sys_->mutable_fec_data_extent()->set_start_block(0);
2131 sys_->mutable_fec_data_extent()->set_num_blocks((data_size + hashtree_size) / block_size);
2132
2133 sys_->mutable_fec_extent()->set_start_block((data_size + hashtree_size) / block_size);
2134 sys_->mutable_fec_extent()->set_num_blocks(fec_size / block_size);
2135
2136 ASSERT_TRUE(sm->BeginUpdate());
2137 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2138
2139 // Map and write some data to target partition.
2140 ASSERT_TRUE(MapUpdateSnapshots({"vnd_b", "prd_b"}));
2141 ASSERT_TRUE(WriteSnapshotAndHash("sys_b"));
2142
2143 // Finish update.
2144 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2145
2146 // Simulate shutting down the device.
2147 ASSERT_TRUE(UnmapAll());
2148
2149 // After reboot, init does first stage mount.
2150 auto init = NewManagerForFirstStageMount("_b");
2151 ASSERT_NE(init, nullptr);
2152 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
2153 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2154
2155 // Check that the target partition have the same content. Hashtree and FEC extents
2156 // should be accounted for.
2157 ASSERT_TRUE(IsPartitionUnchanged("sys_b"));
2158 }
2159
2160 // Test for overflow bit after update
TEST_F(SnapshotUpdateTest,Overflow)2161 TEST_F(SnapshotUpdateTest, Overflow) {
2162 if (ShouldUseCompression()) {
2163 GTEST_SKIP() << "No overflow bit set for userspace COWs";
2164 }
2165
2166 const auto actual_write_size = GetSize(sys_);
2167 const auto declared_write_size = actual_write_size - 1_MiB;
2168
2169 AddOperation(sys_, declared_write_size);
2170
2171 // Execute the update.
2172 ASSERT_TRUE(sm->BeginUpdate());
2173 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2174
2175 // Map and write some data to target partitions.
2176 ASSERT_TRUE(MapUpdateSnapshots({"vnd_b", "prd_b"}));
2177 ASSERT_TRUE(WriteSnapshotAndHash("sys_b"));
2178
2179 std::vector<android::dm::DeviceMapper::TargetInfo> table;
2180 ASSERT_TRUE(DeviceMapper::Instance().GetTableStatus("sys_b", &table));
2181 ASSERT_EQ(1u, table.size());
2182 EXPECT_TRUE(table[0].IsOverflowSnapshot());
2183
2184 ASSERT_FALSE(sm->FinishedSnapshotWrites(false))
2185 << "FinishedSnapshotWrites should detect overflow of CoW device.";
2186 }
2187
TEST_F(SnapshotUpdateTest,LowSpace)2188 TEST_F(SnapshotUpdateTest, LowSpace) {
2189 static constexpr auto kMaxFree = 10_MiB;
2190 auto userdata = std::make_unique<LowSpaceUserdata>();
2191 ASSERT_TRUE(userdata->Init(kMaxFree));
2192
2193 // Grow all partitions to 10_MiB, total 30_MiB. This requires 30 MiB of CoW space. After
2194 // using the empty space in super (< 1 MiB), it uses 30 MiB of /userdata space.
2195 constexpr uint64_t partition_size = 10_MiB;
2196 SetSize(sys_, partition_size);
2197 SetSize(vnd_, partition_size);
2198 SetSize(prd_, partition_size);
2199 sys_->set_estimate_cow_size(partition_size);
2200 vnd_->set_estimate_cow_size(partition_size);
2201 prd_->set_estimate_cow_size(partition_size);
2202
2203 AddOperationForPartitions();
2204
2205 // Execute the update.
2206 ASSERT_TRUE(sm->BeginUpdate());
2207 auto res = sm->CreateUpdateSnapshots(manifest_);
2208 ASSERT_FALSE(res);
2209 ASSERT_EQ(Return::ErrorCode::NO_SPACE, res.error_code());
2210 ASSERT_GE(res.required_size(), 14_MiB);
2211 ASSERT_LT(res.required_size(), 40_MiB);
2212 }
2213
TEST_F(SnapshotUpdateTest,AddPartition)2214 TEST_F(SnapshotUpdateTest, AddPartition) {
2215 group_->add_partition_names("dlkm");
2216
2217 auto dlkm = manifest_.add_partitions();
2218 dlkm->set_partition_name("dlkm");
2219 dlkm->set_estimate_cow_size(2_MiB);
2220 SetSize(dlkm, 3_MiB);
2221
2222 // Grow all partitions. Set |prd| large enough that |sys| and |vnd|'s COWs
2223 // fit in super, but not |prd|.
2224 constexpr uint64_t partition_size = 3788_KiB;
2225 SetSize(sys_, partition_size);
2226 SetSize(vnd_, partition_size);
2227 SetSize(prd_, partition_size);
2228 SetSize(dlkm, partition_size);
2229
2230 AddOperationForPartitions({sys_, vnd_, prd_, dlkm});
2231
2232 // Execute the update.
2233 ASSERT_TRUE(sm->BeginUpdate());
2234 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2235
2236 // Write some data to target partitions.
2237 for (const auto& name : {"sys_b", "vnd_b", "prd_b", "dlkm_b"}) {
2238 ASSERT_TRUE(WriteSnapshotAndHash(name));
2239 }
2240
2241 // Assert that source partitions aren't affected.
2242 for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
2243 ASSERT_TRUE(IsPartitionUnchanged(name));
2244 }
2245
2246 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2247
2248 // Simulate shutting down the device.
2249 ASSERT_TRUE(UnmapAll());
2250
2251 // After reboot, init does first stage mount.
2252 auto init = NewManagerForFirstStageMount("_b");
2253 ASSERT_NE(init, nullptr);
2254
2255 ASSERT_TRUE(init->EnsureSnapuserdConnected());
2256 init->set_use_first_stage_snapuserd(true);
2257
2258 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
2259 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2260
2261 // Check that the target partitions have the same content.
2262 std::vector<std::string> partitions = {"sys_b", "vnd_b", "prd_b", "dlkm_b"};
2263 for (const auto& name : partitions) {
2264 ASSERT_TRUE(IsPartitionUnchanged(name));
2265 }
2266
2267 ASSERT_TRUE(init->PerformInitTransition(SnapshotManager::InitTransition::SECOND_STAGE));
2268 for (const auto& name : partitions) {
2269 ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete(name + "-user-cow-init"));
2270 }
2271
2272 // Initiate the merge and wait for it to be completed.
2273 ASSERT_TRUE(init->InitiateMerge());
2274 ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
2275
2276 // Check that the target partitions have the same content after the merge.
2277 for (const auto& name : {"sys_b", "vnd_b", "prd_b", "dlkm_b"}) {
2278 ASSERT_TRUE(IsPartitionUnchanged(name))
2279 << "Content of " << name << " changes after the merge";
2280 }
2281 }
2282
2283 class AutoKill final {
2284 public:
AutoKill(pid_t pid)2285 explicit AutoKill(pid_t pid) : pid_(pid) {}
~AutoKill()2286 ~AutoKill() {
2287 if (pid_ > 0) kill(pid_, SIGKILL);
2288 }
2289
valid() const2290 bool valid() const { return pid_ > 0; }
2291
2292 private:
2293 pid_t pid_;
2294 };
2295
TEST_F(SnapshotUpdateTest,DaemonTransition)2296 TEST_F(SnapshotUpdateTest, DaemonTransition) {
2297 if (!ShouldUseCompression()) {
2298 GTEST_SKIP() << "Skipping Virtual A/B Compression test";
2299 }
2300
2301 // Ensure a connection to the second-stage daemon, but use the first-stage
2302 // code paths thereafter.
2303 ASSERT_TRUE(sm->EnsureSnapuserdConnected());
2304 sm->set_use_first_stage_snapuserd(true);
2305
2306 AddOperationForPartitions();
2307 // Execute the update.
2308 ASSERT_TRUE(sm->BeginUpdate());
2309 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2310 ASSERT_TRUE(MapUpdateSnapshots());
2311 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2312 ASSERT_TRUE(UnmapAll());
2313
2314 auto init = NewManagerForFirstStageMount("_b");
2315 ASSERT_NE(init, nullptr);
2316
2317 ASSERT_TRUE(init->EnsureSnapuserdConnected());
2318 init->set_use_first_stage_snapuserd(true);
2319
2320 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
2321 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2322
2323 bool userspace_snapshots = init->UpdateUsesUserSnapshots();
2324
2325 if (userspace_snapshots) {
2326 ASSERT_EQ(access("/dev/dm-user/sys_b-init", F_OK), 0);
2327 ASSERT_EQ(access("/dev/dm-user/sys_b", F_OK), -1);
2328 } else {
2329 ASSERT_EQ(access("/dev/dm-user/sys_b-user-cow-init", F_OK), 0);
2330 ASSERT_EQ(access("/dev/dm-user/sys_b-user-cow", F_OK), -1);
2331 }
2332
2333 ASSERT_TRUE(init->PerformInitTransition(SnapshotManager::InitTransition::SECOND_STAGE));
2334
2335 // :TODO: this is a workaround to ensure the handler list stays empty. We
2336 // should make this test more like actual init, and spawn two copies of
2337 // snapuserd, given how many other tests we now have for normal snapuserd.
2338 if (userspace_snapshots) {
2339 ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("sys_b-init"));
2340 ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("vnd_b-init"));
2341 ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("prd_b-init"));
2342
2343 // The control device should have been renamed.
2344 ASSERT_TRUE(android::fs_mgr::WaitForFileDeleted("/dev/dm-user/sys_b-init", 10s));
2345 ASSERT_EQ(access("/dev/dm-user/sys_b", F_OK), 0);
2346 } else {
2347 ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("sys_b-user-cow-init"));
2348 ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("vnd_b-user-cow-init"));
2349 ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("prd_b-user-cow-init"));
2350
2351 // The control device should have been renamed.
2352 ASSERT_TRUE(android::fs_mgr::WaitForFileDeleted("/dev/dm-user/sys_b-user-cow-init", 10s));
2353 ASSERT_EQ(access("/dev/dm-user/sys_b-user-cow", F_OK), 0);
2354 }
2355 }
2356
TEST_F(SnapshotUpdateTest,MapAllSnapshots)2357 TEST_F(SnapshotUpdateTest, MapAllSnapshots) {
2358 AddOperationForPartitions();
2359 // Execute the update.
2360 ASSERT_TRUE(sm->BeginUpdate());
2361 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2362 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
2363 ASSERT_TRUE(WriteSnapshotAndHash(name));
2364 }
2365 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2366 ASSERT_TRUE(sm->MapAllSnapshots(10s));
2367
2368 // Read bytes back and verify they match the cache.
2369 ASSERT_TRUE(IsPartitionUnchanged("sys_b"));
2370
2371 ASSERT_TRUE(sm->UnmapAllSnapshots());
2372 }
2373
TEST_F(SnapshotUpdateTest,CancelOnTargetSlot)2374 TEST_F(SnapshotUpdateTest, CancelOnTargetSlot) {
2375 AddOperationForPartitions();
2376
2377 ASSERT_TRUE(UnmapAll());
2378
2379 // Execute the update from B->A.
2380 test_device->set_slot_suffix("_b");
2381 ASSERT_TRUE(sm->BeginUpdate());
2382 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2383
2384 std::string path;
2385 ASSERT_TRUE(CreateLogicalPartition(
2386 CreateLogicalPartitionParams{
2387 .block_device = fake_super,
2388 .metadata_slot = 0,
2389 .partition_name = "sys_a",
2390 .timeout_ms = 1s,
2391 .partition_opener = opener_.get(),
2392 },
2393 &path));
2394
2395 bool userspace_snapshots = sm->UpdateUsesUserSnapshots();
2396
2397 unique_fd fd;
2398 if (!userspace_snapshots) {
2399 // Hold sys_a open so it can't be unmapped.
2400 fd.reset(open(path.c_str(), O_RDONLY));
2401 }
2402
2403 // Switch back to "A", make sure we can cancel. Instead of unmapping sys_a
2404 // we should simply delete the old snapshots.
2405 test_device->set_slot_suffix("_a");
2406 ASSERT_TRUE(sm->BeginUpdate());
2407 }
2408
TEST_F(SnapshotUpdateTest,QueryStatusError)2409 TEST_F(SnapshotUpdateTest, QueryStatusError) {
2410 // Grow all partitions. Set |prd| large enough that |sys| and |vnd|'s COWs
2411 // fit in super, but not |prd|.
2412 constexpr uint64_t partition_size = 3788_KiB;
2413 SetSize(sys_, partition_size);
2414 SetSize(vnd_, partition_size);
2415 SetSize(prd_, 18_MiB);
2416
2417 // Make sure |prd| does not fit in super at all. On VABC, this means we
2418 // fake an extra large COW for |vnd| to fill up super.
2419 vnd_->set_estimate_cow_size(30_MiB);
2420 prd_->set_estimate_cow_size(30_MiB);
2421
2422 AddOperationForPartitions();
2423
2424 // Execute the update.
2425 ASSERT_TRUE(sm->BeginUpdate());
2426 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2427
2428 if (sm->UpdateUsesUserSnapshots()) {
2429 GTEST_SKIP() << "Test does not apply to userspace snapshots";
2430 }
2431
2432 // Test that partitions prioritize using space in super.
2433 auto tgt = MetadataBuilder::New(*opener_, "super", 1);
2434 ASSERT_NE(tgt, nullptr);
2435 ASSERT_NE(nullptr, tgt->FindPartition("sys_b-cow"));
2436 ASSERT_NE(nullptr, tgt->FindPartition("vnd_b-cow"));
2437 ASSERT_EQ(nullptr, tgt->FindPartition("prd_b-cow"));
2438
2439 // Write some data to target partitions.
2440 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
2441 ASSERT_TRUE(WriteSnapshotAndHash(name));
2442 }
2443
2444 // Assert that source partitions aren't affected.
2445 for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
2446 ASSERT_TRUE(IsPartitionUnchanged(name));
2447 }
2448
2449 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2450
2451 ASSERT_TRUE(UnmapAll());
2452
2453 class DmStatusFailure final : public DeviceMapperWrapper {
2454 public:
2455 bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* table) override {
2456 if (!DeviceMapperWrapper::GetTableStatus(name, table)) {
2457 return false;
2458 }
2459 if (name == "sys_b" && !table->empty()) {
2460 auto& info = table->at(0);
2461 if (DeviceMapper::GetTargetType(info.spec) == "snapshot-merge") {
2462 info.data = "Merge failed";
2463 }
2464 }
2465 return true;
2466 }
2467 };
2468 DmStatusFailure wrapper;
2469
2470 // After reboot, init does first stage mount.
2471 auto info = new TestDeviceInfo(fake_super, "_b");
2472 info->set_dm(&wrapper);
2473
2474 auto init = NewManagerForFirstStageMount(info);
2475 ASSERT_NE(init, nullptr);
2476
2477 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
2478 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2479
2480 // Initiate the merge and wait for it to be completed.
2481 ASSERT_TRUE(init->InitiateMerge());
2482 ASSERT_EQ(UpdateState::MergeFailed, init->ProcessUpdateState());
2483
2484 // Simulate a reboot that tries the merge again, with the non-failing dm.
2485 ASSERT_TRUE(UnmapAll());
2486 init = NewManagerForFirstStageMount("_b");
2487 ASSERT_NE(init, nullptr);
2488 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2489 ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
2490 }
2491
2492 class FlashAfterUpdateTest : public SnapshotUpdateTest,
2493 public WithParamInterface<std::tuple<uint32_t, bool>> {
2494 public:
InitiateMerge(const std::string & slot_suffix)2495 AssertionResult InitiateMerge(const std::string& slot_suffix) {
2496 auto sm = SnapshotManager::New(new TestDeviceInfo(fake_super, slot_suffix));
2497 if (!sm->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_)) {
2498 return AssertionFailure() << "Cannot CreateLogicalAndSnapshotPartitions";
2499 }
2500 if (!sm->InitiateMerge()) {
2501 return AssertionFailure() << "Cannot initiate merge";
2502 }
2503 return AssertionSuccess();
2504 }
2505 };
2506
TEST_P(FlashAfterUpdateTest,FlashSlotAfterUpdate)2507 TEST_P(FlashAfterUpdateTest, FlashSlotAfterUpdate) {
2508 // Execute the update.
2509 ASSERT_TRUE(sm->BeginUpdate());
2510 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2511 ASSERT_TRUE(MapUpdateSnapshots());
2512 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2513
2514 // Simulate shutting down the device.
2515 ASSERT_TRUE(UnmapAll());
2516
2517 bool after_merge = std::get<1>(GetParam());
2518 if (after_merge) {
2519 ASSERT_TRUE(InitiateMerge("_b"));
2520 // Simulate shutting down the device after merge has initiated.
2521 ASSERT_TRUE(UnmapAll());
2522 }
2523
2524 auto flashed_slot = std::get<0>(GetParam());
2525 auto flashed_slot_suffix = SlotSuffixForSlotNumber(flashed_slot);
2526
2527 // Simulate flashing |flashed_slot|. This clears the UPDATED flag.
2528 auto flashed_builder = MetadataBuilder::New(*opener_, "super", flashed_slot);
2529 ASSERT_NE(flashed_builder, nullptr);
2530 flashed_builder->RemoveGroupAndPartitions(group_->name() + flashed_slot_suffix);
2531 flashed_builder->RemoveGroupAndPartitions(kCowGroupName);
2532 ASSERT_TRUE(FillFakeMetadata(flashed_builder.get(), manifest_, flashed_slot_suffix));
2533
2534 // Deliberately remove a partition from this build so that
2535 // InitiateMerge do not switch state to "merging". This is possible in
2536 // practice because the list of dynamic partitions may change.
2537 ASSERT_NE(nullptr, flashed_builder->FindPartition("prd" + flashed_slot_suffix));
2538 flashed_builder->RemovePartition("prd" + flashed_slot_suffix);
2539
2540 // Note that fastbootd always updates the partition table of both slots.
2541 auto flashed_metadata = flashed_builder->Export();
2542 ASSERT_NE(nullptr, flashed_metadata);
2543 ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *flashed_metadata, 0));
2544 ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *flashed_metadata, 1));
2545
2546 std::string path;
2547 for (const auto& name : {"sys", "vnd"}) {
2548 ASSERT_TRUE(CreateLogicalPartition(
2549 CreateLogicalPartitionParams{
2550 .block_device = fake_super,
2551 .metadata_slot = flashed_slot,
2552 .partition_name = name + flashed_slot_suffix,
2553 .timeout_ms = 1s,
2554 .partition_opener = opener_.get(),
2555 },
2556 &path));
2557 ASSERT_TRUE(WriteRandomData(path));
2558 auto hash = GetHash(path);
2559 ASSERT_TRUE(hash.has_value());
2560 hashes_[name + flashed_slot_suffix] = *hash;
2561 }
2562
2563 // Simulate shutting down the device after flash.
2564 ASSERT_TRUE(UnmapAll());
2565
2566 // Simulate reboot. After reboot, init does first stage mount.
2567 auto init = NewManagerForFirstStageMount(flashed_slot_suffix);
2568 ASSERT_NE(init, nullptr);
2569
2570 if (flashed_slot && after_merge) {
2571 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
2572 }
2573 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2574
2575 // Check that the target partitions have the same content.
2576 for (const auto& name : {"sys", "vnd"}) {
2577 ASSERT_TRUE(IsPartitionUnchanged(name + flashed_slot_suffix));
2578 }
2579
2580 // There should be no snapshot to merge.
2581 auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, flashed_slot_suffix));
2582 if (flashed_slot == 0 && after_merge) {
2583 ASSERT_EQ(UpdateState::MergeCompleted, new_sm->ProcessUpdateState());
2584 } else {
2585 // update_engine calls ProcessUpdateState first -- should see Cancelled.
2586 ASSERT_EQ(UpdateState::Cancelled, new_sm->ProcessUpdateState());
2587 }
2588
2589 // Next OTA calls CancelUpdate no matter what.
2590 ASSERT_TRUE(new_sm->CancelUpdate());
2591 }
2592
2593 INSTANTIATE_TEST_SUITE_P(Snapshot, FlashAfterUpdateTest, Combine(Values(0, 1), Bool()),
__anon581dab5a0702(const TestParamInfo<FlashAfterUpdateTest::ParamType>& info) 2594 [](const TestParamInfo<FlashAfterUpdateTest::ParamType>& info) {
2595 return "Flash"s + (std::get<0>(info.param) ? "New"s : "Old"s) +
2596 "Slot"s + (std::get<1>(info.param) ? "After"s : "Before"s) +
2597 "Merge"s;
2598 });
2599
2600 // Test behavior of ImageManager::Create on low space scenario. These tests assumes image manager
2601 // uses /data as backup device.
2602 class ImageManagerTest : public SnapshotTest, public WithParamInterface<uint64_t> {
2603 protected:
SetUp()2604 void SetUp() override {
2605 SKIP_IF_NON_VIRTUAL_AB();
2606 SnapshotTest::SetUp();
2607 userdata_ = std::make_unique<LowSpaceUserdata>();
2608 ASSERT_TRUE(userdata_->Init(GetParam()));
2609 }
TearDown()2610 void TearDown() override {
2611 RETURN_IF_NON_VIRTUAL_AB();
2612
2613 EXPECT_TRUE(!image_manager_->BackingImageExists(kImageName) ||
2614 image_manager_->DeleteBackingImage(kImageName));
2615 }
2616 static constexpr const char* kImageName = "my_image";
2617 std::unique_ptr<LowSpaceUserdata> userdata_;
2618 };
2619
TEST_P(ImageManagerTest,CreateImageNoSpace)2620 TEST_P(ImageManagerTest, CreateImageNoSpace) {
2621 uint64_t to_allocate = userdata_->free_space() + userdata_->bsize();
2622 auto res = image_manager_->CreateBackingImage(kImageName, to_allocate,
2623 IImageManager::CREATE_IMAGE_DEFAULT);
2624 ASSERT_FALSE(res) << "Should not be able to create image with size = " << to_allocate
2625 << " bytes because only " << userdata_->free_space() << " bytes are free";
2626 ASSERT_EQ(FiemapStatus::ErrorCode::NO_SPACE, res.error_code()) << res.string();
2627 }
2628
ImageManagerTestParams()2629 std::vector<uint64_t> ImageManagerTestParams() {
2630 std::vector<uint64_t> ret;
2631 for (uint64_t size = 1_MiB; size <= 512_MiB; size *= 2) {
2632 ret.push_back(size);
2633 }
2634 return ret;
2635 }
2636
2637 INSTANTIATE_TEST_SUITE_P(ImageManagerTest, ImageManagerTest, ValuesIn(ImageManagerTestParams()));
2638
Mkdir(const std::string & path)2639 bool Mkdir(const std::string& path) {
2640 if (mkdir(path.c_str(), 0700) && errno != EEXIST) {
2641 std::cerr << "Could not mkdir " << path << ": " << strerror(errno) << std::endl;
2642 return false;
2643 }
2644 return true;
2645 }
2646
2647 class SnapshotTestEnvironment : public ::testing::Environment {
2648 public:
~SnapshotTestEnvironment()2649 ~SnapshotTestEnvironment() override {}
2650 void SetUp() override;
2651 void TearDown() override;
2652
2653 private:
2654 bool CreateFakeSuper();
2655
2656 std::unique_ptr<IImageManager> super_images_;
2657 };
2658
CreateFakeSuper()2659 bool SnapshotTestEnvironment::CreateFakeSuper() {
2660 // Create and map the fake super partition.
2661 static constexpr int kImageFlags =
2662 IImageManager::CREATE_IMAGE_DEFAULT | IImageManager::CREATE_IMAGE_ZERO_FILL;
2663 if (!super_images_->CreateBackingImage("fake-super", kSuperSize, kImageFlags)) {
2664 LOG(ERROR) << "Could not create fake super partition";
2665 return false;
2666 }
2667 if (!super_images_->MapImageDevice("fake-super", 10s, &fake_super)) {
2668 LOG(ERROR) << "Could not map fake super partition";
2669 return false;
2670 }
2671 test_device->set_fake_super(fake_super);
2672 return true;
2673 }
2674
SetUp()2675 void SnapshotTestEnvironment::SetUp() {
2676 // b/163082876: GTEST_SKIP in Environment will make atest report incorrect results. Until
2677 // that is fixed, don't call GTEST_SKIP here, but instead call GTEST_SKIP in individual test
2678 // suites.
2679 RETURN_IF_NON_VIRTUAL_AB_MSG("Virtual A/B is not enabled, skipping global setup.\n");
2680
2681 std::vector<std::string> paths = {
2682 // clang-format off
2683 "/data/gsi/ota/test",
2684 "/data/gsi/ota/test/super",
2685 "/metadata/gsi/ota/test",
2686 "/metadata/gsi/ota/test/super",
2687 "/metadata/ota/test",
2688 "/metadata/ota/test/snapshots",
2689 // clang-format on
2690 };
2691 for (const auto& path : paths) {
2692 ASSERT_TRUE(Mkdir(path));
2693 }
2694
2695 // Create this once, otherwise, gsid will start/stop between each test.
2696 test_device = new TestDeviceInfo();
2697 sm = SnapshotManager::New(test_device);
2698 ASSERT_NE(nullptr, sm) << "Could not create snapshot manager";
2699
2700 // Use a separate image manager for our fake super partition.
2701 super_images_ = IImageManager::Open("ota/test/super", 10s);
2702 ASSERT_NE(nullptr, super_images_) << "Could not create image manager";
2703
2704 // Map the old image if one exists so we can safely unmap everything that
2705 // depends on it.
2706 bool recreate_fake_super;
2707 if (super_images_->BackingImageExists("fake-super")) {
2708 if (super_images_->IsImageMapped("fake-super")) {
2709 ASSERT_TRUE(super_images_->GetMappedImageDevice("fake-super", &fake_super));
2710 } else {
2711 ASSERT_TRUE(super_images_->MapImageDevice("fake-super", 10s, &fake_super));
2712 }
2713 test_device->set_fake_super(fake_super);
2714 recreate_fake_super = true;
2715 } else {
2716 ASSERT_TRUE(CreateFakeSuper());
2717 recreate_fake_super = false;
2718 }
2719
2720 // Clean up previous run.
2721 MetadataMountedTest().TearDown();
2722 SnapshotUpdateTest().Cleanup();
2723 SnapshotTest().Cleanup();
2724
2725 if (recreate_fake_super) {
2726 // Clean up any old copy.
2727 DeleteBackingImage(super_images_.get(), "fake-super");
2728 ASSERT_TRUE(CreateFakeSuper());
2729 }
2730 }
2731
TearDown()2732 void SnapshotTestEnvironment::TearDown() {
2733 RETURN_IF_NON_VIRTUAL_AB();
2734 if (super_images_ != nullptr) {
2735 DeleteBackingImage(super_images_.get(), "fake-super");
2736 }
2737 }
2738
IsDaemonRequired()2739 bool IsDaemonRequired() {
2740 if (FLAGS_force_config == "dmsnap") {
2741 return false;
2742 }
2743
2744 if (!IsCompressionEnabled()) {
2745 return false;
2746 }
2747
2748 const std::string UNKNOWN = "unknown";
2749 const std::string vendor_release =
2750 android::base::GetProperty("ro.vendor.build.version.release_or_codename", UNKNOWN);
2751
2752 // No userspace snapshots if vendor partition is on Android 12
2753 // However, for GRF devices, snapuserd daemon will be on
2754 // vendor ramdisk in Android 12.
2755 if (vendor_release.find("12") != std::string::npos) {
2756 return true;
2757 }
2758
2759 if (!FLAGS_force_config.empty()) {
2760 return true;
2761 }
2762
2763 return IsUserspaceSnapshotsEnabled();
2764 }
2765
ShouldUseCompression()2766 bool ShouldUseCompression() {
2767 if (FLAGS_force_config == "vab" || FLAGS_force_config == "dmsnap") {
2768 return false;
2769 }
2770 if (FLAGS_force_config == "vabc") {
2771 return true;
2772 }
2773 return IsCompressionEnabled();
2774 }
2775
2776 } // namespace snapshot
2777 } // namespace android
2778
main(int argc,char ** argv)2779 int main(int argc, char** argv) {
2780 ::testing::InitGoogleTest(&argc, argv);
2781 ::testing::AddGlobalTestEnvironment(new ::android::snapshot::SnapshotTestEnvironment());
2782 gflags::ParseCommandLineFlags(&argc, &argv, false);
2783
2784 android::base::SetProperty("ctl.stop", "snapuserd");
2785
2786 std::unordered_set<std::string> configs = {"", "dmsnap", "vab", "vabc"};
2787 if (configs.count(FLAGS_force_config) == 0) {
2788 std::cerr << "Unexpected force_config argument\n";
2789 return 1;
2790 }
2791
2792 if (FLAGS_force_config == "dmsnap") {
2793 if (!android::base::SetProperty("snapuserd.test.dm.snapshots", "1")) {
2794 return testing::AssertionFailure()
2795 << "Failed to disable property: virtual_ab.userspace.snapshots.enabled";
2796 }
2797 }
2798
2799 if (FLAGS_force_iouring_disable == "iouring_disabled") {
2800 if (!android::base::SetProperty("snapuserd.test.io_uring.force_disable", "1")) {
2801 return testing::AssertionFailure()
2802 << "Failed to disable property: snapuserd.test.io_uring.disabled";
2803 }
2804 }
2805
2806 int ret = RUN_ALL_TESTS();
2807
2808 if (FLAGS_force_config == "dmsnap") {
2809 android::base::SetProperty("snapuserd.test.dm.snapshots", "0");
2810 }
2811
2812 if (FLAGS_force_iouring_disable == "iouring_disabled") {
2813 android::base::SetProperty("snapuserd.test.io_uring.force_disable", "0");
2814 }
2815
2816 return ret;
2817 }
2818