1 // Copyright (C) 2019 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/snapshot.h>
16
17 #include <dirent.h>
18 #include <fcntl.h>
19 #include <math.h>
20 #include <sys/file.h>
21 #include <sys/types.h>
22 #include <sys/unistd.h>
23 #include <sys/xattr.h>
24
25 #include <chrono>
26 #include <filesystem>
27 #include <optional>
28 #include <thread>
29
30 #include <android-base/file.h>
31 #include <android-base/logging.h>
32 #include <android-base/parseint.h>
33 #include <android-base/properties.h>
34 #include <android-base/stringprintf.h>
35 #include <android-base/strings.h>
36 #include <android-base/unique_fd.h>
37 #include <cutils/sockets.h>
38 #include <ext4_utils/ext4_utils.h>
39 #include <fs_mgr.h>
40 #include <fs_mgr/file_wait.h>
41 #include <fs_mgr_dm_linear.h>
42 #include <fstab/fstab.h>
43 #include <libdm/dm.h>
44 #include <libfiemap/image_manager.h>
45 #include <liblp/liblp.h>
46
47 #include <android/snapshot/snapshot.pb.h>
48 #include <libsnapshot/snapshot_stats.h>
49 #include "device_info.h"
50 #include "partition_cow_creator.h"
51 #include "scratch_super.h"
52 #include "snapshot_metadata_updater.h"
53 #include "utility.h"
54
55 namespace android {
56 namespace snapshot {
57
58 using aidl::android::hardware::boot::MergeStatus;
59 using android::base::unique_fd;
60 using android::dm::DeviceMapper;
61 using android::dm::DmDeviceState;
62 using android::dm::DmTable;
63 using android::dm::DmTargetLinear;
64 using android::dm::DmTargetSnapshot;
65 using android::dm::DmTargetUser;
66 using android::dm::kSectorSize;
67 using android::dm::SnapshotStorageMode;
68 using android::fiemap::FiemapStatus;
69 using android::fiemap::IImageManager;
70 using android::fs_mgr::CreateDmTable;
71 using android::fs_mgr::CreateLogicalPartition;
72 using android::fs_mgr::CreateLogicalPartitionParams;
73 using android::fs_mgr::GetPartitionGroupName;
74 using android::fs_mgr::GetPartitionName;
75 using android::fs_mgr::LpMetadata;
76 using android::fs_mgr::MetadataBuilder;
77 using android::fs_mgr::SlotNumberForSlotSuffix;
78 using chromeos_update_engine::DeltaArchiveManifest;
79 using chromeos_update_engine::Extent;
80 using chromeos_update_engine::FileDescriptor;
81 using chromeos_update_engine::PartitionUpdate;
82 template <typename T>
83 using RepeatedPtrField = google::protobuf::RepeatedPtrField<T>;
84 using std::chrono::duration_cast;
85 using namespace std::chrono_literals;
86 using namespace std::string_literals;
87 using android::base::Realpath;
88 using android::base::StringPrintf;
89
90 static constexpr char kBootSnapshotsWithoutSlotSwitch[] =
91 "/metadata/ota/snapshot-boot-without-slot-switch";
92 static constexpr char kBootIndicatorPath[] = "/metadata/ota/snapshot-boot";
93 static constexpr char kRollbackIndicatorPath[] = "/metadata/ota/rollback-indicator";
94 static constexpr char kSnapuserdFromSystem[] = "/metadata/ota/snapuserd-from-system";
95 static constexpr auto kUpdateStateCheckInterval = 2s;
96 static constexpr char kOtaFileContext[] = "u:object_r:ota_metadata_file:s0";
97
98 /*
99 * The readahead size is set to 32kb so that
100 * there is no significant memory pressure (/proc/pressure/memory) during boot.
101 * After OTA, during boot, partitions are scanned before marking slot as successful.
102 * This scan will trigger readahead both on source and COW block device thereby
103 * leading to Inactive(file) pages to be very high.
104 *
105 * A lower value may help reduce memory pressure further, however, that will
106 * increase the boot time. Thus, for device which don't care about OTA boot
107 * time, they could use O_DIRECT functionality wherein the I/O to the source
108 * block device will be O_DIRECT.
109 */
110 static constexpr auto kReadAheadSizeKb = 32;
111
112 // Note: IImageManager is an incomplete type in the header, so the default
113 // destructor doesn't work.
~SnapshotManager()114 SnapshotManager::~SnapshotManager() {}
115
New(IDeviceInfo * info)116 std::unique_ptr<SnapshotManager> SnapshotManager::New(IDeviceInfo* info) {
117 if (!info) {
118 info = new DeviceInfo();
119 }
120
121 auto sm = std::unique_ptr<SnapshotManager>(new SnapshotManager(info));
122 if (info->IsTempMetadata()) {
123 LOG(INFO) << "Using temp metadata from super";
124 }
125 return sm;
126 }
127
NewForFirstStageMount(IDeviceInfo * info)128 std::unique_ptr<SnapshotManager> SnapshotManager::NewForFirstStageMount(IDeviceInfo* info) {
129 if (!info) {
130 DeviceInfo* impl = new DeviceInfo();
131 impl->set_first_stage_init(true);
132 info = impl;
133 }
134 auto sm = New(info);
135
136 // The first-stage version of snapuserd is explicitly started by init. Do
137 // not attempt to using it during tests (which run in normal AOSP).
138 if (!sm->device()->IsTestDevice()) {
139 sm->use_first_stage_snapuserd_ = true;
140 }
141 return sm;
142 }
143
SnapshotManager(IDeviceInfo * device)144 SnapshotManager::SnapshotManager(IDeviceInfo* device)
145 : dm_(device->GetDeviceMapper()), device_(device), metadata_dir_(device_->GetMetadataDir()) {}
146
GetCowName(const std::string & snapshot_name)147 static std::string GetCowName(const std::string& snapshot_name) {
148 return snapshot_name + "-cow";
149 }
150
GetSnapshotDriver(LockedFile * lock)151 SnapshotManager::SnapshotDriver SnapshotManager::GetSnapshotDriver(LockedFile* lock) {
152 if (UpdateUsesUserSnapshots(lock)) {
153 return SnapshotManager::SnapshotDriver::DM_USER;
154 } else {
155 return SnapshotManager::SnapshotDriver::DM_SNAPSHOT;
156 }
157 }
158
GetDmUserCowName(const std::string & snapshot_name,SnapshotManager::SnapshotDriver driver)159 static std::string GetDmUserCowName(const std::string& snapshot_name,
160 SnapshotManager::SnapshotDriver driver) {
161 // dm-user block device will act as a snapshot device. We identify it with
162 // the same partition name so that when partitions can be mounted off
163 // dm-user.
164
165 switch (driver) {
166 case SnapshotManager::SnapshotDriver::DM_USER: {
167 return snapshot_name;
168 }
169
170 case SnapshotManager::SnapshotDriver::DM_SNAPSHOT: {
171 return snapshot_name + "-user-cow";
172 }
173
174 default: {
175 LOG(ERROR) << "Invalid snapshot driver";
176 return "";
177 }
178 }
179 }
180
GetCowImageDeviceName(const std::string & snapshot_name)181 static std::string GetCowImageDeviceName(const std::string& snapshot_name) {
182 return snapshot_name + "-cow-img";
183 }
184
GetBaseDeviceName(const std::string & partition_name)185 static std::string GetBaseDeviceName(const std::string& partition_name) {
186 return partition_name + "-base";
187 }
188
GetSourceDeviceName(const std::string & partition_name)189 static std::string GetSourceDeviceName(const std::string& partition_name) {
190 return partition_name + "-src";
191 }
192
BeginUpdate()193 bool SnapshotManager::BeginUpdate() {
194 switch (TryCancelUpdate()) {
195 case CancelResult::OK:
196 break;
197 case CancelResult::NEEDS_MERGE: {
198 LOG(INFO) << "Wait for merge (if any) before beginning a new update.";
199 auto state = ProcessUpdateState();
200 LOG(INFO) << "Merged with end state: " << state;
201 break;
202 }
203 default:
204 LOG(ERROR) << "Cannot begin update, existing update cannot be cancelled.";
205 return false;
206 }
207
208 auto file = LockExclusive();
209 if (!file) return false;
210
211 // Purge the ImageManager just in case there is a corrupt lp_metadata file
212 // lying around. (NB: no need to return false on an error, we can let the
213 // update try to progress.)
214 if (EnsureImageManager()) {
215 images_->RemoveAllImages();
216 }
217
218 // Clear any cached metadata (this allows re-using one manager across tests).
219 old_partition_metadata_ = nullptr;
220
221 auto state = ReadUpdateState(file.get());
222 if (state != UpdateState::None) {
223 LOG(ERROR) << "An update is already in progress, cannot begin a new update";
224 return false;
225 }
226 return WriteUpdateState(file.get(), UpdateState::Initiated);
227 }
228
CancelUpdate()229 bool SnapshotManager::CancelUpdate() {
230 return TryCancelUpdate() == CancelResult::OK;
231 }
232
TryCancelUpdate()233 CancelResult SnapshotManager::TryCancelUpdate() {
234 auto lock = LockExclusive();
235 if (!lock) return CancelResult::ERROR;
236
237 UpdateState state = ReadUpdateState(lock.get());
238 CancelResult result = IsCancelUpdateSafe(state);
239
240 if (result != CancelResult::OK && device_->IsRecovery()) {
241 LOG(ERROR) << "Cancel result " << result << " will be overridden in recovery.";
242 result = CancelResult::OK;
243 }
244
245 switch (result) {
246 case CancelResult::OK:
247 LOG(INFO) << "Cancelling update from state: " << state;
248 RemoveAllUpdateState(lock.get());
249 RemoveInvalidSnapshots(lock.get());
250 break;
251 case CancelResult::NEEDS_MERGE:
252 LOG(ERROR) << "Cannot cancel an update while a merge is in progress.";
253 break;
254 case CancelResult::LIVE_SNAPSHOTS:
255 LOG(ERROR) << "Cannot cancel an update while snapshots are live.";
256 break;
257 case CancelResult::ERROR:
258 // Error was already reported.
259 break;
260 }
261 return result;
262 }
263
IsCancelUpdateSafe()264 bool SnapshotManager::IsCancelUpdateSafe() {
265 // This may be called in recovery, so ensure we have /metadata.
266 auto mount = EnsureMetadataMounted();
267 if (!mount || !mount->HasDevice()) {
268 return true;
269 }
270
271 auto lock = LockExclusive();
272 if (!lock) {
273 return false;
274 }
275
276 UpdateState state = ReadUpdateState(lock.get());
277 return IsCancelUpdateSafe(state) == CancelResult::OK;
278 }
279
IsCancelUpdateSafe(UpdateState state)280 CancelResult SnapshotManager::IsCancelUpdateSafe(UpdateState state) {
281 if (IsSnapshotWithoutSlotSwitch()) {
282 return CancelResult::LIVE_SNAPSHOTS;
283 }
284
285 switch (state) {
286 case UpdateState::Merging:
287 case UpdateState::MergeNeedsReboot:
288 case UpdateState::MergeFailed:
289 return CancelResult::NEEDS_MERGE;
290 case UpdateState::Unverified: {
291 // We completed an update, but it can still be canceled if we haven't booted into it.
292 auto slot = GetCurrentSlot();
293 if (slot == Slot::Target) {
294 return CancelResult::LIVE_SNAPSHOTS;
295 }
296 return CancelResult::OK;
297 }
298 case UpdateState::None:
299 case UpdateState::Initiated:
300 case UpdateState::Cancelled:
301 return CancelResult::OK;
302 default:
303 LOG(ERROR) << "Unknown state: " << state;
304 return CancelResult::ERROR;
305 }
306 }
307
ReadUpdateSourceSlotSuffix()308 std::string SnapshotManager::ReadUpdateSourceSlotSuffix() {
309 auto boot_file = GetSnapshotBootIndicatorPath();
310 std::string contents;
311 if (!android::base::ReadFileToString(boot_file, &contents)) {
312 return {};
313 }
314 return contents;
315 }
316
GetCurrentSlot()317 SnapshotManager::Slot SnapshotManager::GetCurrentSlot() {
318 auto contents = ReadUpdateSourceSlotSuffix();
319 if (contents.empty()) {
320 return Slot::Unknown;
321 }
322 if (device_->GetSlotSuffix() == contents) {
323 return Slot::Source;
324 }
325 return Slot::Target;
326 }
327
GetSnapshotSlotSuffix()328 std::string SnapshotManager::GetSnapshotSlotSuffix() {
329 switch (GetCurrentSlot()) {
330 case Slot::Target:
331 return device_->GetSlotSuffix();
332 default:
333 return device_->GetOtherSlotSuffix();
334 }
335 }
336
RemoveFileIfExists(const std::string & path)337 static bool RemoveFileIfExists(const std::string& path) {
338 std::string message;
339 if (!android::base::RemoveFileIfExists(path, &message)) {
340 LOG(ERROR) << "Remove failed: " << path << ": " << message;
341 return false;
342 }
343 return true;
344 }
345
RemoveAllUpdateState(LockedFile * lock,const std::function<bool ()> & prolog)346 bool SnapshotManager::RemoveAllUpdateState(LockedFile* lock, const std::function<bool()>& prolog) {
347 if (prolog && !prolog()) {
348 LOG(WARNING) << "Can't RemoveAllUpdateState: prolog failed.";
349 return false;
350 }
351
352 LOG(INFO) << "Removing all update state.";
353
354 if (ReadUpdateState(lock) != UpdateState::None) {
355 // Only call this if we're actually cancelling an update. It's not
356 // expected to yield anything otherwise, and firing up gsid on normal
357 // boot is expensive.
358 if (!RemoveAllSnapshots(lock)) {
359 LOG(ERROR) << "Could not remove all snapshots";
360 return false;
361 }
362 }
363
364 // It's okay if these fail:
365 // - For SnapshotBoot and Rollback, first-stage init performs a deeper check after
366 // reading the indicator file, so it's not a problem if it still exists
367 // after the update completes.
368 // - For ForwardMerge, FinishedSnapshotWrites asserts that the existence of the indicator
369 // matches the incoming update.
370 std::vector<std::string> files = {
371 GetSnapshotBootIndicatorPath(), GetRollbackIndicatorPath(),
372 GetForwardMergeIndicatorPath(), GetOldPartitionMetadataPath(),
373 GetBootSnapshotsWithoutSlotSwitchPath(), GetSnapuserdFromSystemPath(),
374 };
375 for (const auto& file : files) {
376 RemoveFileIfExists(file);
377 }
378
379 // If this fails, we'll keep trying to remove the update state (as the
380 // device reboots or starts a new update) until it finally succeeds.
381 return WriteUpdateState(lock, UpdateState::None);
382 }
383
FinishedSnapshotWrites(bool wipe)384 bool SnapshotManager::FinishedSnapshotWrites(bool wipe) {
385 auto lock = LockExclusive();
386 if (!lock) return false;
387
388 auto update_state = ReadUpdateState(lock.get());
389 if (update_state == UpdateState::Unverified) {
390 LOG(INFO) << "FinishedSnapshotWrites already called before. Ignored.";
391 return true;
392 }
393
394 if (update_state != UpdateState::Initiated) {
395 LOG(ERROR) << "Can only transition to the Unverified state from the Initiated state.";
396 return false;
397 }
398
399 if (!EnsureNoOverflowSnapshot(lock.get())) {
400 LOG(ERROR) << "Cannot ensure there are no overflow snapshots.";
401 return false;
402 }
403
404 if (!UpdateForwardMergeIndicator(wipe)) {
405 return false;
406 }
407
408 // This file is written on boot to detect whether a rollback occurred. It
409 // MUST NOT exist before rebooting, otherwise, we're at risk of deleting
410 // snapshots too early.
411 if (!RemoveFileIfExists(GetRollbackIndicatorPath())) {
412 return false;
413 }
414
415 // This file acts as both a quick indicator for init (it can use access(2)
416 // to decide how to do first-stage mounts), and it stores the old slot, so
417 // we can tell whether or not we performed a rollback.
418 auto contents = device_->GetSlotSuffix();
419 auto boot_file = GetSnapshotBootIndicatorPath();
420 if (!WriteStringToFileAtomic(contents, boot_file)) {
421 PLOG(ERROR) << "write failed: " << boot_file;
422 return false;
423 }
424 return WriteUpdateState(lock.get(), UpdateState::Unverified);
425 }
426
CreateSnapshot(LockedFile * lock,PartitionCowCreator * cow_creator,SnapshotStatus * status)427 bool SnapshotManager::CreateSnapshot(LockedFile* lock, PartitionCowCreator* cow_creator,
428 SnapshotStatus* status) {
429 CHECK(lock);
430 CHECK(lock->lock_mode() == LOCK_EX);
431 CHECK(status);
432
433 if (status->name().empty()) {
434 LOG(ERROR) << "SnapshotStatus has no name.";
435 return false;
436 }
437 // Check these sizes. Like liblp, we guarantee the partition size is
438 // respected, which means it has to be sector-aligned. (This guarantee is
439 // useful for locating avb footers correctly). The COW file size, however,
440 // can be arbitrarily larger than specified, so we can safely round it up.
441 if (status->device_size() % kSectorSize != 0) {
442 LOG(ERROR) << "Snapshot " << status->name()
443 << " device size is not a multiple of the sector size: "
444 << status->device_size();
445 return false;
446 }
447 if (status->snapshot_size() % kSectorSize != 0) {
448 LOG(ERROR) << "Snapshot " << status->name()
449 << " snapshot size is not a multiple of the sector size: "
450 << status->snapshot_size();
451 return false;
452 }
453 if (status->cow_partition_size() % kSectorSize != 0) {
454 LOG(ERROR) << "Snapshot " << status->name()
455 << " cow partition size is not a multiple of the sector size: "
456 << status->cow_partition_size();
457 return false;
458 }
459 if (status->cow_file_size() % kSectorSize != 0) {
460 LOG(ERROR) << "Snapshot " << status->name()
461 << " cow file size is not a multiple of the sector size: "
462 << status->cow_file_size();
463 return false;
464 }
465
466 status->set_state(SnapshotState::CREATED);
467 status->set_sectors_allocated(0);
468 status->set_metadata_sectors(0);
469 status->set_using_snapuserd(cow_creator->using_snapuserd);
470 status->set_compression_algorithm(cow_creator->compression_algorithm);
471 status->set_compression_factor(cow_creator->compression_factor);
472 status->set_read_ahead_size(cow_creator->read_ahead_size);
473 if (cow_creator->enable_threading) {
474 status->set_enable_threading(cow_creator->enable_threading);
475 }
476 if (cow_creator->batched_writes) {
477 status->set_batched_writes(cow_creator->batched_writes);
478 }
479
480 if (!WriteSnapshotStatus(lock, *status)) {
481 PLOG(ERROR) << "Could not write snapshot status: " << status->name();
482 return false;
483 }
484 return true;
485 }
486
CreateCowImage(LockedFile * lock,const std::string & name)487 Return SnapshotManager::CreateCowImage(LockedFile* lock, const std::string& name) {
488 CHECK(lock);
489 CHECK(lock->lock_mode() == LOCK_EX);
490 if (!EnsureImageManager()) return Return::Error();
491
492 SnapshotStatus status;
493 if (!ReadSnapshotStatus(lock, name, &status)) {
494 return Return::Error();
495 }
496
497 // The COW file size should have been rounded up to the nearest sector in CreateSnapshot.
498 if (status.cow_file_size() % kSectorSize != 0) {
499 LOG(ERROR) << "Snapshot " << name << " COW file size is not a multiple of the sector size: "
500 << status.cow_file_size();
501 return Return::Error();
502 }
503
504 std::string cow_image_name = GetCowImageDeviceName(name);
505 int cow_flags = IImageManager::CREATE_IMAGE_DEFAULT;
506 return Return(images_->CreateBackingImage(cow_image_name, status.cow_file_size(), cow_flags));
507 }
508
MapDmUserCow(LockedFile * lock,const std::string & name,const std::string & cow_file,const std::string & base_device,const std::string & base_path_merge,const std::chrono::milliseconds & timeout_ms,std::string * path)509 bool SnapshotManager::MapDmUserCow(LockedFile* lock, const std::string& name,
510 const std::string& cow_file, const std::string& base_device,
511 const std::string& base_path_merge,
512 const std::chrono::milliseconds& timeout_ms, std::string* path) {
513 CHECK(lock);
514
515 if (UpdateUsesUserSnapshots(lock)) {
516 SnapshotStatus status;
517 if (!ReadSnapshotStatus(lock, name, &status)) {
518 LOG(ERROR) << "MapDmUserCow: ReadSnapshotStatus failed...";
519 return false;
520 }
521
522 if (status.state() == SnapshotState::NONE ||
523 status.state() == SnapshotState::MERGE_COMPLETED) {
524 LOG(ERROR) << "Should not create a snapshot device for " << name
525 << " after merging has completed.";
526 return false;
527 }
528
529 SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
530 if (update_status.state() == UpdateState::MergeCompleted ||
531 update_status.state() == UpdateState::MergeNeedsReboot) {
532 LOG(ERROR) << "Should not create a snapshot device for " << name
533 << " after global merging has completed.";
534 return false;
535 }
536 }
537
538 // Use an extra decoration for first-stage init, so we can transition
539 // to a new table entry in second-stage.
540 std::string misc_name = name;
541 if (use_first_stage_snapuserd_) {
542 misc_name += "-init";
543 }
544
545 if (!EnsureSnapuserdConnected()) {
546 return false;
547 }
548
549 uint64_t base_sectors = 0;
550 if (!UpdateUsesUserSnapshots(lock)) {
551 base_sectors = snapuserd_client_->InitDmUserCow(misc_name, cow_file, base_device);
552 if (base_sectors == 0) {
553 LOG(ERROR) << "Failed to retrieve base_sectors from Snapuserd";
554 return false;
555 }
556 } else if (IsSnapshotWithoutSlotSwitch()) {
557 // When snapshots are on current slot, we determine the size
558 // of block device based on the number of COW operations. We cannot
559 // use base device as it will be from older image.
560 unique_fd fd(open(cow_file.c_str(), O_RDONLY | O_CLOEXEC));
561 if (fd < 0) {
562 PLOG(ERROR) << "Failed to open " << cow_file;
563 return false;
564 }
565
566 CowReader reader;
567 if (!reader.Parse(std::move(fd))) {
568 LOG(ERROR) << "Failed to parse cow " << cow_file;
569 return false;
570 }
571
572 uint64_t dev_sz = 0;
573 const auto& header = reader.GetHeader();
574 if (header.prefix.major_version == 2) {
575 const size_t num_ops = reader.get_num_total_data_ops();
576 dev_sz = (num_ops * header.block_size);
577 } else {
578 // create_snapshot will skip in-place copy ops. Hence, fetch this
579 // information directly from v3 header.
580 const auto& v3_header = reader.header_v3();
581 dev_sz = v3_header.op_count_max * v3_header.block_size;
582 }
583
584 base_sectors = dev_sz >> 9;
585 } else {
586 // For userspace snapshots, the size of the base device is taken as the
587 // size of the dm-user block device. Since there is no pseudo mapping
588 // created in the daemon, we no longer need to rely on the daemon for
589 // sizing the dm-user block device.
590 unique_fd fd(TEMP_FAILURE_RETRY(open(base_path_merge.c_str(), O_RDONLY | O_CLOEXEC)));
591 if (fd < 0) {
592 LOG(ERROR) << "Cannot open block device: " << base_path_merge;
593 return false;
594 }
595
596 uint64_t dev_sz = get_block_device_size(fd.get());
597 if (!dev_sz) {
598 LOG(ERROR) << "Failed to find block device size: " << base_path_merge;
599 return false;
600 }
601
602 base_sectors = dev_sz >> 9;
603 }
604
605 DmTable table;
606 table.Emplace<DmTargetUser>(0, base_sectors, misc_name);
607 if (!dm_.CreateDevice(name, table, path, timeout_ms)) {
608 LOG(ERROR) << " dm-user: CreateDevice failed... ";
609 return false;
610 }
611 if (!WaitForDevice(*path, timeout_ms)) {
612 LOG(ERROR) << " dm-user: timeout: Failed to create block device for: " << name;
613 return false;
614 }
615
616 auto control_device = "/dev/dm-user/" + misc_name;
617 if (!WaitForDevice(control_device, timeout_ms)) {
618 return false;
619 }
620
621 if (UpdateUsesUserSnapshots(lock)) {
622 // Now that the dm-user device is created, initialize the daemon and
623 // spin up the worker threads.
624 if (!snapuserd_client_->InitDmUserCow(misc_name, cow_file, base_device, base_path_merge)) {
625 LOG(ERROR) << "InitDmUserCow failed";
626 return false;
627 }
628 }
629
630 return snapuserd_client_->AttachDmUser(misc_name);
631 }
632
MapSnapshot(LockedFile * lock,const std::string & name,const std::string & base_device,const std::string & cow_device,const std::chrono::milliseconds & timeout_ms,std::string * dev_path)633 bool SnapshotManager::MapSnapshot(LockedFile* lock, const std::string& name,
634 const std::string& base_device, const std::string& cow_device,
635 const std::chrono::milliseconds& timeout_ms,
636 std::string* dev_path) {
637 CHECK(lock);
638
639 SnapshotStatus status;
640 if (!ReadSnapshotStatus(lock, name, &status)) {
641 return false;
642 }
643 if (status.state() == SnapshotState::NONE || status.state() == SnapshotState::MERGE_COMPLETED) {
644 LOG(ERROR) << "Should not create a snapshot device for " << name
645 << " after merging has completed.";
646 return false;
647 }
648
649 // Validate the block device size, as well as the requested snapshot size.
650 // Note that during first-stage init, we don't have the device paths.
651 if (android::base::StartsWith(base_device, "/")) {
652 unique_fd fd(open(base_device.c_str(), O_RDONLY | O_CLOEXEC));
653 if (fd < 0) {
654 PLOG(ERROR) << "open failed: " << base_device;
655 return false;
656 }
657 auto dev_size = get_block_device_size(fd);
658 if (!dev_size) {
659 PLOG(ERROR) << "Could not determine block device size: " << base_device;
660 return false;
661 }
662 if (status.device_size() != dev_size) {
663 LOG(ERROR) << "Block device size for " << base_device << " does not match"
664 << "(expected " << status.device_size() << ", got " << dev_size << ")";
665 return false;
666 }
667 }
668 if (status.device_size() % kSectorSize != 0) {
669 LOG(ERROR) << "invalid blockdev size for " << base_device << ": " << status.device_size();
670 return false;
671 }
672 if (status.snapshot_size() % kSectorSize != 0 ||
673 status.snapshot_size() > status.device_size()) {
674 LOG(ERROR) << "Invalid snapshot size for " << base_device << ": " << status.snapshot_size();
675 return false;
676 }
677 if (status.device_size() != status.snapshot_size()) {
678 LOG(ERROR) << "Device size and snapshot size must be the same (device size = "
679 << status.device_size() << ", snapshot size = " << status.snapshot_size();
680 return false;
681 }
682
683 uint64_t snapshot_sectors = status.snapshot_size() / kSectorSize;
684
685 // Note that merging is a global state. We do track whether individual devices
686 // have completed merging, but the start of the merge process is considered
687 // atomic.
688 SnapshotStorageMode mode;
689 SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
690 switch (update_status.state()) {
691 case UpdateState::MergeCompleted:
692 case UpdateState::MergeNeedsReboot:
693 LOG(ERROR) << "Should not create a snapshot device for " << name
694 << " after global merging has completed.";
695 return false;
696 case UpdateState::Merging:
697 case UpdateState::MergeFailed:
698 // Note: MergeFailed indicates that a merge is in progress, but
699 // is possibly stalled. We still have to honor the merge.
700 if (DecideMergePhase(status) == update_status.merge_phase()) {
701 mode = SnapshotStorageMode::Merge;
702 } else {
703 mode = SnapshotStorageMode::Persistent;
704 }
705 break;
706 default:
707 mode = SnapshotStorageMode::Persistent;
708 break;
709 }
710
711 if (mode == SnapshotStorageMode::Persistent && status.state() == SnapshotState::MERGING) {
712 LOG(ERROR) << "Snapshot: " << name
713 << " has snapshot status Merging but mode set to Persistent."
714 << " Changing mode to Snapshot-Merge.";
715 mode = SnapshotStorageMode::Merge;
716 }
717
718 DmTable table;
719 table.Emplace<DmTargetSnapshot>(0, snapshot_sectors, base_device, cow_device, mode,
720 kSnapshotChunkSize);
721 if (!dm_.CreateDevice(name, table, dev_path, timeout_ms)) {
722 LOG(ERROR) << "Could not create snapshot device: " << name;
723 return false;
724 }
725 return true;
726 }
727
MapCowImage(const std::string & name,const std::chrono::milliseconds & timeout_ms)728 std::optional<std::string> SnapshotManager::MapCowImage(
729 const std::string& name, const std::chrono::milliseconds& timeout_ms) {
730 if (!EnsureImageManager()) return std::nullopt;
731 auto cow_image_name = GetCowImageDeviceName(name);
732
733 bool ok;
734 std::string cow_dev;
735 if (device_->IsRecovery() || device_->IsFirstStageInit()) {
736 const auto& opener = device_->GetPartitionOpener();
737 ok = images_->MapImageWithDeviceMapper(opener, cow_image_name, &cow_dev);
738 } else {
739 ok = images_->MapImageDevice(cow_image_name, timeout_ms, &cow_dev);
740 }
741
742 if (ok) {
743 LOG(INFO) << "Mapped " << cow_image_name << " to " << cow_dev;
744 return cow_dev;
745 }
746 LOG(ERROR) << "Could not map image device: " << cow_image_name;
747 return std::nullopt;
748 }
749
MapSourceDevice(LockedFile * lock,const std::string & name,const std::chrono::milliseconds & timeout_ms,std::string * path)750 bool SnapshotManager::MapSourceDevice(LockedFile* lock, const std::string& name,
751 const std::chrono::milliseconds& timeout_ms,
752 std::string* path) {
753 CHECK(lock);
754
755 auto metadata = ReadOldPartitionMetadata(lock);
756 if (!metadata) {
757 LOG(ERROR) << "Could not map source device due to missing or corrupt metadata";
758 return false;
759 }
760
761 auto old_name = GetOtherPartitionName(name);
762 auto slot_suffix = device_->GetSlotSuffix();
763 auto slot = SlotNumberForSlotSuffix(slot_suffix);
764
765 CreateLogicalPartitionParams params = {
766 .block_device = device_->GetSuperDevice(slot),
767 .metadata = metadata,
768 .partition_name = old_name,
769 .timeout_ms = timeout_ms,
770 .device_name = GetSourceDeviceName(name),
771 .partition_opener = &device_->GetPartitionOpener(),
772 };
773 if (!CreateLogicalPartition(std::move(params), path)) {
774 LOG(ERROR) << "Could not create source device for snapshot " << name;
775 return false;
776 }
777 return true;
778 }
779
UnmapSnapshot(LockedFile * lock,const std::string & name)780 bool SnapshotManager::UnmapSnapshot(LockedFile* lock, const std::string& name) {
781 CHECK(lock);
782
783 if (UpdateUsesUserSnapshots(lock)) {
784 if (!UnmapUserspaceSnapshotDevice(lock, name)) {
785 return false;
786 }
787 } else {
788 if (!DeleteDeviceIfExists(name)) {
789 LOG(ERROR) << "Could not delete snapshot device: " << name;
790 return false;
791 }
792 }
793 return true;
794 }
795
UnmapCowImage(const std::string & name)796 bool SnapshotManager::UnmapCowImage(const std::string& name) {
797 if (!EnsureImageManager()) return false;
798 return images_->UnmapImageIfExists(GetCowImageDeviceName(name));
799 }
800
DeleteSnapshot(LockedFile * lock,const std::string & name)801 bool SnapshotManager::DeleteSnapshot(LockedFile* lock, const std::string& name) {
802 CHECK(lock);
803 CHECK(lock->lock_mode() == LOCK_EX);
804 if (!EnsureImageManager()) return false;
805
806 if (!UnmapCowDevices(lock, name)) {
807 return false;
808 }
809
810 // We can't delete snapshots in recovery. The only way we'd try is it we're
811 // completing or canceling a merge in preparation for a data wipe, in which
812 // case, we don't care if the file sticks around.
813 if (device_->IsRecovery()) {
814 LOG(INFO) << "Skipping delete of snapshot " << name << " in recovery.";
815 return true;
816 }
817
818 auto cow_image_name = GetCowImageDeviceName(name);
819 if (images_->BackingImageExists(cow_image_name)) {
820 if (!images_->DeleteBackingImage(cow_image_name)) {
821 return false;
822 }
823 }
824
825 std::string error;
826 auto file_path = GetSnapshotStatusFilePath(name);
827 if (!android::base::RemoveFileIfExists(file_path, &error)) {
828 LOG(ERROR) << "Failed to remove status file " << file_path << ": " << error;
829 return false;
830 }
831
832 // This path may never exist. If it is present, then it's a stale
833 // snapshot status file. Just remove the file and log the message.
834 const std::string tmp_path = file_path + ".tmp";
835 if (!android::base::RemoveFileIfExists(tmp_path, &error)) {
836 LOG(ERROR) << "Failed to remove stale snapshot file " << tmp_path;
837 }
838
839 return true;
840 }
841
InitiateMerge()842 bool SnapshotManager::InitiateMerge() {
843 auto lock = LockExclusive();
844 if (!lock) return false;
845
846 UpdateState state = ReadUpdateState(lock.get());
847 if (state != UpdateState::Unverified) {
848 LOG(ERROR) << "Cannot begin a merge if an update has not been verified";
849 return false;
850 }
851
852 auto slot = GetCurrentSlot();
853 if (slot != Slot::Target) {
854 LOG(ERROR) << "Device cannot merge while not booting from new slot";
855 return false;
856 }
857
858 std::vector<std::string> snapshots;
859 if (!ListSnapshots(lock.get(), &snapshots)) {
860 LOG(ERROR) << "Could not list snapshots";
861 return false;
862 }
863
864 auto current_slot_suffix = device_->GetSlotSuffix();
865
866 for (const auto& snapshot : snapshots) {
867 if (!android::base::EndsWith(snapshot, current_slot_suffix)) {
868 // Allow the merge to continue, but log this unexpected case.
869 LOG(ERROR) << "Unexpected snapshot found during merge: " << snapshot;
870 continue;
871 }
872
873 // The device has to be mapped, since everything should be merged at
874 // the same time. This is a fairly serious error. We could forcefully
875 // map everything here, but it should have been mapped during first-
876 // stage init.
877 if (dm_.GetState(snapshot) == DmDeviceState::INVALID) {
878 LOG(ERROR) << "Cannot begin merge; device " << snapshot << " is not mapped.";
879 return false;
880 }
881 }
882
883 auto metadata = ReadCurrentMetadata();
884 for (auto it = snapshots.begin(); it != snapshots.end();) {
885 switch (GetMetadataPartitionState(*metadata, *it)) {
886 case MetadataPartitionState::Flashed:
887 LOG(WARNING) << "Detected re-flashing for partition " << *it
888 << ". Skip merging it.";
889 [[fallthrough]];
890 case MetadataPartitionState::None: {
891 LOG(WARNING) << "Deleting snapshot for partition " << *it;
892 if (!DeleteSnapshot(lock.get(), *it)) {
893 LOG(WARNING) << "Cannot delete snapshot for partition " << *it
894 << ". Skip merging it anyways.";
895 }
896 it = snapshots.erase(it);
897 } break;
898 case MetadataPartitionState::Updated: {
899 ++it;
900 } break;
901 }
902 }
903
904 bool using_snapuserd = false;
905
906 std::vector<std::string> first_merge_group;
907
908 DmTargetSnapshot::Status initial_target_values = {};
909 for (const auto& snapshot : snapshots) {
910 if (!UpdateUsesUserSnapshots(lock.get())) {
911 DmTargetSnapshot::Status current_status;
912 if (!QuerySnapshotStatus(snapshot, nullptr, ¤t_status)) {
913 return false;
914 }
915 initial_target_values.sectors_allocated += current_status.sectors_allocated;
916 initial_target_values.total_sectors += current_status.total_sectors;
917 initial_target_values.metadata_sectors += current_status.metadata_sectors;
918 }
919
920 SnapshotStatus snapshot_status;
921 if (!ReadSnapshotStatus(lock.get(), snapshot, &snapshot_status)) {
922 return false;
923 }
924
925 using_snapuserd |= snapshot_status.using_snapuserd();
926 if (DecideMergePhase(snapshot_status) == MergePhase::FIRST_PHASE) {
927 first_merge_group.emplace_back(snapshot);
928 }
929 }
930
931 SnapshotUpdateStatus initial_status = ReadSnapshotUpdateStatus(lock.get());
932 initial_status.set_state(UpdateState::Merging);
933 initial_status.set_using_snapuserd(using_snapuserd);
934
935 if (!UpdateUsesUserSnapshots(lock.get())) {
936 initial_status.set_sectors_allocated(initial_target_values.sectors_allocated);
937 initial_status.set_total_sectors(initial_target_values.total_sectors);
938 initial_status.set_metadata_sectors(initial_target_values.metadata_sectors);
939 }
940
941 // If any partitions shrunk, we need to merge them before we merge any other
942 // partitions (see b/177935716). Otherwise, a merge from another partition
943 // may overwrite the source block of a copy operation.
944 const std::vector<std::string>* merge_group;
945 if (first_merge_group.empty()) {
946 merge_group = &snapshots;
947 initial_status.set_merge_phase(MergePhase::SECOND_PHASE);
948 } else {
949 merge_group = &first_merge_group;
950 initial_status.set_merge_phase(MergePhase::FIRST_PHASE);
951 }
952
953 // Point of no return - mark that we're starting a merge. From now on every
954 // eligible snapshot must be a merge target.
955 if (!WriteSnapshotUpdateStatus(lock.get(), initial_status)) {
956 return false;
957 }
958
959 auto reported_code = MergeFailureCode::Ok;
960 for (const auto& snapshot : *merge_group) {
961 // If this fails, we have no choice but to continue. Everything must
962 // be merged. This is not an ideal state to be in, but it is safe,
963 // because we the next boot will try again.
964 auto code = SwitchSnapshotToMerge(lock.get(), snapshot);
965 if (code != MergeFailureCode::Ok) {
966 LOG(ERROR) << "Failed to switch snapshot to a merge target: " << snapshot;
967 if (reported_code == MergeFailureCode::Ok) {
968 reported_code = code;
969 }
970 }
971 }
972
973 // If we couldn't switch everything to a merge target, pre-emptively mark
974 // this merge as failed. It will get acknowledged when WaitForMerge() is
975 // called.
976 if (reported_code != MergeFailureCode::Ok) {
977 WriteUpdateState(lock.get(), UpdateState::MergeFailed, reported_code);
978 }
979
980 // Return true no matter what, because a merge was initiated.
981 return true;
982 }
983
SwitchSnapshotToMerge(LockedFile * lock,const std::string & name)984 MergeFailureCode SnapshotManager::SwitchSnapshotToMerge(LockedFile* lock, const std::string& name) {
985 SnapshotStatus status;
986 if (!ReadSnapshotStatus(lock, name, &status)) {
987 return MergeFailureCode::ReadStatus;
988 }
989 if (status.state() != SnapshotState::CREATED) {
990 LOG(WARNING) << "Snapshot " << name
991 << " has unexpected state: " << SnapshotState_Name(status.state());
992 }
993
994 if (UpdateUsesUserSnapshots(lock)) {
995 if (EnsureSnapuserdConnected()) {
996 // This is the point where we inform the daemon to initiate/resume
997 // the merge
998 if (!snapuserd_client_->InitiateMerge(name)) {
999 return MergeFailureCode::UnknownTable;
1000 }
1001 } else {
1002 LOG(ERROR) << "Failed to connect to snapuserd daemon to initiate merge";
1003 return MergeFailureCode::UnknownTable;
1004 }
1005 } else {
1006 // After this, we return true because we technically did switch to a merge
1007 // target. Everything else we do here is just informational.
1008 if (auto code = RewriteSnapshotDeviceTable(name); code != MergeFailureCode::Ok) {
1009 return code;
1010 }
1011 }
1012
1013 status.set_state(SnapshotState::MERGING);
1014
1015 if (!UpdateUsesUserSnapshots(lock)) {
1016 DmTargetSnapshot::Status dm_status;
1017 if (!QuerySnapshotStatus(name, nullptr, &dm_status)) {
1018 LOG(ERROR) << "Could not query merge status for snapshot: " << name;
1019 }
1020 status.set_sectors_allocated(dm_status.sectors_allocated);
1021 status.set_metadata_sectors(dm_status.metadata_sectors);
1022 }
1023
1024 if (!WriteSnapshotStatus(lock, status)) {
1025 LOG(ERROR) << "Could not update status file for snapshot: " << name;
1026 }
1027 return MergeFailureCode::Ok;
1028 }
1029
RewriteSnapshotDeviceTable(const std::string & name)1030 MergeFailureCode SnapshotManager::RewriteSnapshotDeviceTable(const std::string& name) {
1031 std::vector<DeviceMapper::TargetInfo> old_targets;
1032 if (!dm_.GetTableInfo(name, &old_targets)) {
1033 LOG(ERROR) << "Could not read snapshot device table: " << name;
1034 return MergeFailureCode::GetTableInfo;
1035 }
1036 if (old_targets.size() != 1 || DeviceMapper::GetTargetType(old_targets[0].spec) != "snapshot") {
1037 LOG(ERROR) << "Unexpected device-mapper table for snapshot: " << name;
1038 return MergeFailureCode::UnknownTable;
1039 }
1040
1041 std::string base_device, cow_device;
1042 if (!DmTargetSnapshot::GetDevicesFromParams(old_targets[0].data, &base_device, &cow_device)) {
1043 LOG(ERROR) << "Could not derive underlying devices for snapshot: " << name;
1044 return MergeFailureCode::GetTableParams;
1045 }
1046
1047 DmTable table;
1048 table.Emplace<DmTargetSnapshot>(0, old_targets[0].spec.length, base_device, cow_device,
1049 SnapshotStorageMode::Merge, kSnapshotChunkSize);
1050 if (!dm_.LoadTableAndActivate(name, table)) {
1051 LOG(ERROR) << "Could not swap device-mapper tables on snapshot device " << name;
1052 return MergeFailureCode::ActivateNewTable;
1053 }
1054 LOG(INFO) << "Successfully switched snapshot device to a merge target: " << name;
1055 return MergeFailureCode::Ok;
1056 }
1057
GetSingleTarget(const std::string & dm_name,TableQuery query,DeviceMapper::TargetInfo * target)1058 bool SnapshotManager::GetSingleTarget(const std::string& dm_name, TableQuery query,
1059 DeviceMapper::TargetInfo* target) {
1060 if (dm_.GetState(dm_name) == DmDeviceState::INVALID) {
1061 return false;
1062 }
1063
1064 std::vector<DeviceMapper::TargetInfo> targets;
1065 bool result;
1066 if (query == TableQuery::Status) {
1067 result = dm_.GetTableStatus(dm_name, &targets);
1068 } else {
1069 result = dm_.GetTableInfo(dm_name, &targets);
1070 }
1071 if (!result) {
1072 LOG(ERROR) << "Could not query device: " << dm_name;
1073 return false;
1074 }
1075 if (targets.size() != 1) {
1076 return false;
1077 }
1078
1079 *target = std::move(targets[0]);
1080 return true;
1081 }
1082
IsSnapshotDevice(const std::string & dm_name,TargetInfo * target)1083 bool SnapshotManager::IsSnapshotDevice(const std::string& dm_name, TargetInfo* target) {
1084 DeviceMapper::TargetInfo snap_target;
1085 if (!GetSingleTarget(dm_name, TableQuery::Status, &snap_target)) {
1086 return false;
1087 }
1088 auto type = DeviceMapper::GetTargetType(snap_target.spec);
1089
1090 // If this is not a user-snapshot device then it should either
1091 // be a dm-snapshot or dm-snapshot-merge target
1092 if (type != "user") {
1093 if (type != "snapshot" && type != "snapshot-merge") {
1094 return false;
1095 }
1096 }
1097
1098 if (target) {
1099 *target = std::move(snap_target);
1100 }
1101 return true;
1102 }
1103
UpdateStateToStr(const enum UpdateState state)1104 auto SnapshotManager::UpdateStateToStr(const enum UpdateState state) {
1105 switch (state) {
1106 case None:
1107 return "None";
1108 case Initiated:
1109 return "Initiated";
1110 case Unverified:
1111 return "Unverified";
1112 case Merging:
1113 return "Merging";
1114 case MergeNeedsReboot:
1115 return "MergeNeedsReboot";
1116 case MergeCompleted:
1117 return "MergeCompleted";
1118 case MergeFailed:
1119 return "MergeFailed";
1120 case Cancelled:
1121 return "Cancelled";
1122 default:
1123 return "Unknown";
1124 }
1125 }
1126
QuerySnapshotStatus(const std::string & dm_name,std::string * target_type,DmTargetSnapshot::Status * status)1127 bool SnapshotManager::QuerySnapshotStatus(const std::string& dm_name, std::string* target_type,
1128 DmTargetSnapshot::Status* status) {
1129 DeviceMapper::TargetInfo target;
1130 if (!IsSnapshotDevice(dm_name, &target)) {
1131 LOG(ERROR) << "Device " << dm_name << " is not a snapshot or snapshot-merge device";
1132 return false;
1133 }
1134 if (!DmTargetSnapshot::ParseStatusText(target.data, status)) {
1135 LOG(ERROR) << "Could not parse snapshot status text: " << dm_name;
1136 return false;
1137 }
1138 if (target_type) {
1139 *target_type = DeviceMapper::GetTargetType(target.spec);
1140 }
1141 if (!status->error.empty()) {
1142 LOG(ERROR) << "Snapshot: " << dm_name << " returned error code: " << status->error;
1143 return false;
1144 }
1145 return true;
1146 }
1147
1148 // Note that when a merge fails, we will *always* try again to complete the
1149 // merge each time the device boots. There is no harm in doing so, and if
1150 // the problem was transient, we might manage to get a new outcome.
ProcessUpdateState(const std::function<bool ()> & callback,const std::function<bool ()> & before_cancel)1151 UpdateState SnapshotManager::ProcessUpdateState(const std::function<bool()>& callback,
1152 const std::function<bool()>& before_cancel) {
1153 while (true) {
1154 auto result = CheckMergeState(before_cancel);
1155 LOG(INFO) << "ProcessUpdateState handling state: " << UpdateStateToStr(result.state);
1156
1157 if (result.state == UpdateState::MergeFailed) {
1158 AcknowledgeMergeFailure(result.failure_code);
1159 }
1160
1161 if (result.state == UpdateState::MergeCompleted) {
1162 if (device_->IsTempMetadata()) {
1163 CleanupScratchOtaMetadataIfPresent();
1164 }
1165 }
1166
1167 if (result.state != UpdateState::Merging) {
1168 // Either there is no merge, or the merge was finished, so no need
1169 // to keep waiting.
1170 return result.state;
1171 }
1172
1173 if (callback && !callback()) {
1174 return result.state;
1175 }
1176
1177 // This wait is not super time sensitive, so we have a relatively
1178 // low polling frequency.
1179 std::this_thread::sleep_for(kUpdateStateCheckInterval);
1180 }
1181 }
1182
CheckMergeState(const std::function<bool ()> & before_cancel)1183 auto SnapshotManager::CheckMergeState(const std::function<bool()>& before_cancel) -> MergeResult {
1184 auto lock = LockExclusive();
1185 if (!lock) {
1186 return MergeResult(UpdateState::MergeFailed, MergeFailureCode::AcquireLock);
1187 }
1188
1189 auto result = CheckMergeState(lock.get(), before_cancel);
1190 LOG(INFO) << "CheckMergeState for snapshots returned: " << UpdateStateToStr(result.state);
1191
1192 if (result.state == UpdateState::MergeCompleted) {
1193 // Do this inside the same lock. Failures get acknowledged without the
1194 // lock, because flock() might have failed.
1195 AcknowledgeMergeSuccess(lock.get());
1196 } else if (result.state == UpdateState::Cancelled) {
1197 if (!device_->IsRecovery() && !RemoveAllUpdateState(lock.get(), before_cancel)) {
1198 LOG(ERROR) << "Failed to remove all update state after acknowleding cancelled update.";
1199 }
1200 }
1201 return result;
1202 }
1203
CheckMergeState(LockedFile * lock,const std::function<bool ()> & before_cancel)1204 auto SnapshotManager::CheckMergeState(LockedFile* lock,
1205 const std::function<bool()>& before_cancel) -> MergeResult {
1206 SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
1207 switch (update_status.state()) {
1208 case UpdateState::None:
1209 case UpdateState::MergeCompleted:
1210 // Harmless races are allowed between two callers of WaitForMerge,
1211 // so in both of these cases we just propagate the state.
1212 return MergeResult(update_status.state());
1213
1214 case UpdateState::Merging:
1215 case UpdateState::MergeNeedsReboot:
1216 case UpdateState::MergeFailed:
1217 // We'll poll each snapshot below. Note that for the NeedsReboot
1218 // case, we always poll once to give cleanup another opportunity to
1219 // run.
1220 break;
1221
1222 case UpdateState::Unverified:
1223 // This is an edge case. Normally cancelled updates are detected
1224 // via the merge poll below, but if we never started a merge, we
1225 // need to also check here.
1226 if (HandleCancelledUpdate(lock, before_cancel)) {
1227 return MergeResult(UpdateState::Cancelled);
1228 }
1229 return MergeResult(update_status.state());
1230
1231 default:
1232 return MergeResult(update_status.state());
1233 }
1234
1235 std::vector<std::string> snapshots;
1236 if (!ListSnapshots(lock, &snapshots)) {
1237 return MergeResult(UpdateState::MergeFailed, MergeFailureCode::ListSnapshots);
1238 }
1239
1240 auto current_slot_suffix = device_->GetSlotSuffix();
1241
1242 bool cancelled = false;
1243 bool merging = false;
1244 bool needs_reboot = false;
1245 bool wrong_phase = false;
1246 MergeFailureCode failure_code = MergeFailureCode::Ok;
1247 for (const auto& snapshot : snapshots) {
1248 if (!android::base::EndsWith(snapshot, current_slot_suffix)) {
1249 // This will have triggered an error message in InitiateMerge already.
1250 LOG(ERROR) << "Skipping merge validation of unexpected snapshot: " << snapshot;
1251 continue;
1252 }
1253
1254 auto result = CheckTargetMergeState(lock, snapshot, update_status);
1255 LOG(INFO) << "CheckTargetMergeState for " << snapshot
1256 << " returned: " << UpdateStateToStr(result.state);
1257
1258 switch (result.state) {
1259 case UpdateState::MergeFailed:
1260 // Take the first failure code in case other failures compound.
1261 if (failure_code == MergeFailureCode::Ok) {
1262 failure_code = result.failure_code;
1263 }
1264 break;
1265 case UpdateState::Merging:
1266 merging = true;
1267 break;
1268 case UpdateState::MergeNeedsReboot:
1269 needs_reboot = true;
1270 break;
1271 case UpdateState::MergeCompleted:
1272 break;
1273 case UpdateState::Cancelled:
1274 cancelled = true;
1275 break;
1276 case UpdateState::None:
1277 wrong_phase = true;
1278 break;
1279 default:
1280 LOG(ERROR) << "Unknown merge status for \"" << snapshot << "\": " << "\""
1281 << result.state << "\"";
1282 if (failure_code == MergeFailureCode::Ok) {
1283 failure_code = MergeFailureCode::UnexpectedMergeState;
1284 }
1285 break;
1286 }
1287 }
1288
1289 if (merging) {
1290 // Note that we handle "Merging" before we handle anything else. We
1291 // want to poll until *nothing* is merging if we can, so everything has
1292 // a chance to get marked as completed or failed.
1293 return MergeResult(UpdateState::Merging);
1294 }
1295 if (failure_code != MergeFailureCode::Ok) {
1296 // Note: since there are many drop-out cases for failure, we acknowledge
1297 // it in WaitForMerge rather than here and elsewhere.
1298 return MergeResult(UpdateState::MergeFailed, failure_code);
1299 }
1300 if (wrong_phase) {
1301 // If we got here, no other partitions are being merged, and nothing
1302 // failed to merge. It's safe to move to the next merge phase.
1303 auto code = MergeSecondPhaseSnapshots(lock);
1304 if (code != MergeFailureCode::Ok) {
1305 return MergeResult(UpdateState::MergeFailed, code);
1306 }
1307 return MergeResult(UpdateState::Merging);
1308 }
1309 if (needs_reboot) {
1310 WriteUpdateState(lock, UpdateState::MergeNeedsReboot);
1311 return MergeResult(UpdateState::MergeNeedsReboot);
1312 }
1313 if (cancelled) {
1314 // This is an edge case, that we handle as correctly as we sensibly can.
1315 // The underlying partition has changed behind update_engine, and we've
1316 // removed the snapshot as a result. The exact state of the update is
1317 // undefined now, but this can only happen on an unlocked device where
1318 // partitions can be flashed without wiping userdata.
1319 return MergeResult(UpdateState::Cancelled);
1320 }
1321 return MergeResult(UpdateState::MergeCompleted);
1322 }
1323
CheckTargetMergeState(LockedFile * lock,const std::string & name,const SnapshotUpdateStatus & update_status)1324 auto SnapshotManager::CheckTargetMergeState(LockedFile* lock, const std::string& name,
1325 const SnapshotUpdateStatus& update_status)
1326 -> MergeResult {
1327 SnapshotStatus snapshot_status;
1328 if (!ReadSnapshotStatus(lock, name, &snapshot_status)) {
1329 return MergeResult(UpdateState::MergeFailed, MergeFailureCode::ReadStatus);
1330 }
1331
1332 std::unique_ptr<LpMetadata> current_metadata;
1333
1334 if (!IsSnapshotDevice(name)) {
1335 if (!current_metadata) {
1336 current_metadata = ReadCurrentMetadata();
1337 }
1338
1339 if (!current_metadata ||
1340 GetMetadataPartitionState(*current_metadata, name) != MetadataPartitionState::Updated) {
1341 DeleteSnapshot(lock, name);
1342 return MergeResult(UpdateState::Cancelled);
1343 }
1344
1345 // During a check, we decided the merge was complete, but we were unable to
1346 // collapse the device-mapper stack and perform COW cleanup. If we haven't
1347 // rebooted after this check, the device will still be a snapshot-merge
1348 // target. If we have rebooted, the device will now be a linear target,
1349 // and we can try cleanup again.
1350 if (snapshot_status.state() == SnapshotState::MERGE_COMPLETED) {
1351 // NB: It's okay if this fails now, we gave cleanup our best effort.
1352 OnSnapshotMergeComplete(lock, name, snapshot_status);
1353 return MergeResult(UpdateState::MergeCompleted);
1354 }
1355
1356 LOG(ERROR) << "Expected snapshot or snapshot-merge for device: " << name;
1357 return MergeResult(UpdateState::MergeFailed, MergeFailureCode::UnknownTargetType);
1358 }
1359
1360 // This check is expensive so it is only enabled for debugging.
1361 DCHECK((current_metadata = ReadCurrentMetadata()) &&
1362 GetMetadataPartitionState(*current_metadata, name) == MetadataPartitionState::Updated);
1363
1364 if (UpdateUsesUserSnapshots(lock)) {
1365 if (!EnsureSnapuserdConnected()) {
1366 return MergeResult(UpdateState::MergeFailed, MergeFailureCode::QuerySnapshotStatus);
1367 }
1368
1369 // Query the snapshot status from the daemon
1370 const auto merge_status = snapuserd_client_->QuerySnapshotStatus(name);
1371 if (merge_status == "snapshot-merge-failed") {
1372 return MergeResult(UpdateState::MergeFailed, MergeFailureCode::UnknownTargetType);
1373 }
1374
1375 // This is the case when device reboots during merge. Once the device boots,
1376 // snapuserd daemon will not resume merge immediately in first stage init.
1377 // This is slightly different as compared to dm-snapshot-merge; In this
1378 // case, metadata file will have "MERGING" state whereas the daemon will be
1379 // waiting to resume the merge. Thus, we resume the merge at this point.
1380 if (merge_status == "snapshot" && snapshot_status.state() == SnapshotState::MERGING) {
1381 if (!snapuserd_client_->InitiateMerge(name)) {
1382 return MergeResult(UpdateState::MergeFailed, MergeFailureCode::UnknownTargetType);
1383 }
1384 return MergeResult(UpdateState::Merging);
1385 }
1386
1387 if (merge_status == "snapshot" &&
1388 DecideMergePhase(snapshot_status) == MergePhase::SECOND_PHASE) {
1389 if (update_status.merge_phase() == MergePhase::FIRST_PHASE) {
1390 // The snapshot is not being merged because it's in the wrong phase.
1391 return MergeResult(UpdateState::None);
1392 } else {
1393 // update_status is already in second phase but the
1394 // snapshot_status is still not set to SnapshotState::MERGING.
1395 //
1396 // Resume the merge at this point. see b/374225913
1397 LOG(INFO) << "SwitchSnapshotToMerge: " << name << " after resuming merge";
1398 auto code = SwitchSnapshotToMerge(lock, name);
1399 if (code != MergeFailureCode::Ok) {
1400 LOG(ERROR) << "Failed to switch snapshot: " << name
1401 << " to merge during second phase";
1402 return MergeResult(UpdateState::MergeFailed,
1403 MergeFailureCode::UnknownTargetType);
1404 }
1405 return MergeResult(UpdateState::Merging);
1406 }
1407 }
1408
1409 if (merge_status == "snapshot-merge") {
1410 if (snapshot_status.state() == SnapshotState::MERGE_COMPLETED) {
1411 LOG(ERROR) << "Snapshot " << name
1412 << " is merging after being marked merge-complete.";
1413 return MergeResult(UpdateState::MergeFailed,
1414 MergeFailureCode::UnmergedSectorsAfterCompletion);
1415 }
1416 return MergeResult(UpdateState::Merging);
1417 }
1418
1419 if (merge_status != "snapshot-merge-complete") {
1420 LOG(ERROR) << "Snapshot " << name << " has incorrect status: " << merge_status;
1421 return MergeResult(UpdateState::MergeFailed, MergeFailureCode::ExpectedMergeTarget);
1422 }
1423 } else {
1424 // dm-snapshot in the kernel
1425 std::string target_type;
1426 DmTargetSnapshot::Status status;
1427 if (!QuerySnapshotStatus(name, &target_type, &status)) {
1428 return MergeResult(UpdateState::MergeFailed, MergeFailureCode::QuerySnapshotStatus);
1429 }
1430 if (target_type == "snapshot" &&
1431 DecideMergePhase(snapshot_status) == MergePhase::SECOND_PHASE &&
1432 update_status.merge_phase() == MergePhase::FIRST_PHASE) {
1433 // The snapshot is not being merged because it's in the wrong phase.
1434 return MergeResult(UpdateState::None);
1435 }
1436 if (target_type != "snapshot-merge") {
1437 // We can get here if we failed to rewrite the target type in
1438 // InitiateMerge(). If we failed to create the target in first-stage
1439 // init, boot would not succeed.
1440 LOG(ERROR) << "Snapshot " << name << " has incorrect target type: " << target_type;
1441 return MergeResult(UpdateState::MergeFailed, MergeFailureCode::ExpectedMergeTarget);
1442 }
1443
1444 // These two values are equal when merging is complete.
1445 if (status.sectors_allocated != status.metadata_sectors) {
1446 if (snapshot_status.state() == SnapshotState::MERGE_COMPLETED) {
1447 LOG(ERROR) << "Snapshot " << name
1448 << " is merging after being marked merge-complete.";
1449 return MergeResult(UpdateState::MergeFailed,
1450 MergeFailureCode::UnmergedSectorsAfterCompletion);
1451 }
1452 return MergeResult(UpdateState::Merging);
1453 }
1454 }
1455
1456 // Merging is done. First, update the status file to indicate the merge
1457 // is complete. We do this before calling OnSnapshotMergeComplete, even
1458 // though this means the write is potentially wasted work (since in the
1459 // ideal case we'll immediately delete the file).
1460 //
1461 // This makes it simpler to reason about the next reboot: no matter what
1462 // part of cleanup failed, first-stage init won't try to create another
1463 // snapshot device for this partition.
1464 snapshot_status.set_state(SnapshotState::MERGE_COMPLETED);
1465 if (!WriteSnapshotStatus(lock, snapshot_status)) {
1466 return MergeResult(UpdateState::MergeFailed, MergeFailureCode::WriteStatus);
1467 }
1468 if (!OnSnapshotMergeComplete(lock, name, snapshot_status)) {
1469 return MergeResult(UpdateState::MergeNeedsReboot);
1470 }
1471 return MergeResult(UpdateState::MergeCompleted, MergeFailureCode::Ok);
1472 }
1473
1474 // This returns the backing device, not the dm-user layer.
GetMappedCowDeviceName(const std::string & snapshot,const SnapshotStatus & status)1475 static std::string GetMappedCowDeviceName(const std::string& snapshot,
1476 const SnapshotStatus& status) {
1477 // If no partition was created (the COW exists entirely on /data), the
1478 // device-mapper layering is different than if we had a partition.
1479 if (status.cow_partition_size() == 0) {
1480 return GetCowImageDeviceName(snapshot);
1481 }
1482 return GetCowName(snapshot);
1483 }
1484
MergeSecondPhaseSnapshots(LockedFile * lock)1485 MergeFailureCode SnapshotManager::MergeSecondPhaseSnapshots(LockedFile* lock) {
1486 std::vector<std::string> snapshots;
1487 if (!ListSnapshots(lock, &snapshots)) {
1488 return MergeFailureCode::ListSnapshots;
1489 }
1490
1491 SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
1492 CHECK(update_status.state() == UpdateState::Merging ||
1493 update_status.state() == UpdateState::MergeFailed);
1494 CHECK(update_status.merge_phase() == MergePhase::FIRST_PHASE);
1495
1496 update_status.set_state(UpdateState::Merging);
1497 update_status.set_merge_phase(MergePhase::SECOND_PHASE);
1498 if (!WriteSnapshotUpdateStatus(lock, update_status)) {
1499 return MergeFailureCode::WriteStatus;
1500 }
1501
1502 auto current_slot_suffix = device_->GetSlotSuffix();
1503 MergeFailureCode result = MergeFailureCode::Ok;
1504 for (const auto& snapshot : snapshots) {
1505 if (!android::base::EndsWith(snapshot, current_slot_suffix)) {
1506 LOG(ERROR) << "Skipping invalid snapshot: " << snapshot
1507 << " during MergeSecondPhaseSnapshots";
1508 continue;
1509 }
1510 SnapshotStatus snapshot_status;
1511 if (!ReadSnapshotStatus(lock, snapshot, &snapshot_status)) {
1512 return MergeFailureCode::ReadStatus;
1513 }
1514 if (DecideMergePhase(snapshot_status) != MergePhase::SECOND_PHASE) {
1515 continue;
1516 }
1517 auto code = SwitchSnapshotToMerge(lock, snapshot);
1518 if (code != MergeFailureCode::Ok) {
1519 LOG(ERROR) << "Failed to switch snapshot to a second-phase merge target: " << snapshot;
1520 if (result == MergeFailureCode::Ok) {
1521 result = code;
1522 }
1523 }
1524 }
1525 return result;
1526 }
1527
GetBootSnapshotsWithoutSlotSwitchPath()1528 std::string SnapshotManager::GetBootSnapshotsWithoutSlotSwitchPath() {
1529 return metadata_dir_ + "/" + android::base::Basename(kBootSnapshotsWithoutSlotSwitch);
1530 }
1531
GetSnapshotBootIndicatorPath()1532 std::string SnapshotManager::GetSnapshotBootIndicatorPath() {
1533 return metadata_dir_ + "/" + android::base::Basename(kBootIndicatorPath);
1534 }
1535
GetRollbackIndicatorPath()1536 std::string SnapshotManager::GetRollbackIndicatorPath() {
1537 return metadata_dir_ + "/" + android::base::Basename(kRollbackIndicatorPath);
1538 }
1539
GetSnapuserdFromSystemPath()1540 std::string SnapshotManager::GetSnapuserdFromSystemPath() {
1541 return metadata_dir_ + "/" + android::base::Basename(kSnapuserdFromSystem);
1542 }
1543
GetForwardMergeIndicatorPath()1544 std::string SnapshotManager::GetForwardMergeIndicatorPath() {
1545 return metadata_dir_ + "/allow-forward-merge";
1546 }
1547
GetOldPartitionMetadataPath()1548 std::string SnapshotManager::GetOldPartitionMetadataPath() {
1549 return metadata_dir_ + "/old-partition-metadata";
1550 }
1551
AcknowledgeMergeSuccess(LockedFile * lock)1552 void SnapshotManager::AcknowledgeMergeSuccess(LockedFile* lock) {
1553 // It's not possible to remove update state in recovery, so write an
1554 // indicator that cleanup is needed on reboot. If a factory data reset
1555 // was requested, it doesn't matter, everything will get wiped anyway.
1556 // To make testing easier we consider a /data wipe as cleaned up.
1557 if (device_->IsRecovery()) {
1558 WriteUpdateState(lock, UpdateState::MergeCompleted);
1559 return;
1560 }
1561
1562 RemoveAllUpdateState(lock);
1563
1564 if (UpdateUsesUserSnapshots(lock) && !device()->IsTestDevice()) {
1565 if (snapuserd_client_) {
1566 snapuserd_client_->DetachSnapuserd();
1567 snapuserd_client_->RemoveTransitionedDaemonIndicator();
1568 snapuserd_client_ = nullptr;
1569 }
1570 }
1571 }
1572
AcknowledgeMergeFailure(MergeFailureCode failure_code)1573 void SnapshotManager::AcknowledgeMergeFailure(MergeFailureCode failure_code) {
1574 // Log first, so worst case, we always have a record of why the calls below
1575 // were being made.
1576 LOG(ERROR) << "Merge could not be completed and will be marked as failed.";
1577
1578 auto lock = LockExclusive();
1579 if (!lock) return;
1580
1581 // Since we released the lock in between WaitForMerge and here, it's
1582 // possible (1) the merge successfully completed or (2) was already
1583 // marked as a failure. So make sure to check the state again, and
1584 // only mark as a failure if appropriate.
1585 UpdateState state = ReadUpdateState(lock.get());
1586 if (state != UpdateState::Merging && state != UpdateState::MergeNeedsReboot) {
1587 return;
1588 }
1589
1590 WriteUpdateState(lock.get(), UpdateState::MergeFailed, failure_code);
1591 }
1592
OnSnapshotMergeComplete(LockedFile * lock,const std::string & name,const SnapshotStatus & status)1593 bool SnapshotManager::OnSnapshotMergeComplete(LockedFile* lock, const std::string& name,
1594 const SnapshotStatus& status) {
1595 if (!UpdateUsesUserSnapshots(lock)) {
1596 if (IsSnapshotDevice(name)) {
1597 // We are extra-cautious here, to avoid deleting the wrong table.
1598 std::string target_type;
1599 DmTargetSnapshot::Status dm_status;
1600 if (!QuerySnapshotStatus(name, &target_type, &dm_status)) {
1601 return false;
1602 }
1603 if (target_type != "snapshot-merge") {
1604 LOG(ERROR) << "Unexpected target type " << target_type
1605 << " for snapshot device: " << name;
1606 return false;
1607 }
1608 if (dm_status.sectors_allocated != dm_status.metadata_sectors) {
1609 LOG(ERROR) << "Merge is unexpectedly incomplete for device " << name;
1610 return false;
1611 }
1612 if (!CollapseSnapshotDevice(lock, name, status)) {
1613 LOG(ERROR) << "Unable to collapse snapshot: " << name;
1614 return false;
1615 }
1616 }
1617 } else {
1618 // Just collapse the device - no need to query again as we just did
1619 // prior to calling this function
1620 if (!CollapseSnapshotDevice(lock, name, status)) {
1621 LOG(ERROR) << "Unable to collapse snapshot: " << name;
1622 return false;
1623 }
1624 }
1625
1626 // Note that collapsing is implicitly an Unmap, so we don't need to
1627 // unmap the snapshot.
1628
1629 if (!DeleteSnapshot(lock, name)) {
1630 LOG(ERROR) << "Could not delete snapshot: " << name;
1631 return false;
1632 }
1633 return true;
1634 }
1635
CollapseSnapshotDevice(LockedFile * lock,const std::string & name,const SnapshotStatus & status)1636 bool SnapshotManager::CollapseSnapshotDevice(LockedFile* lock, const std::string& name,
1637 const SnapshotStatus& status) {
1638 if (!UpdateUsesUserSnapshots(lock)) {
1639 // Verify we have a snapshot-merge device.
1640 DeviceMapper::TargetInfo target;
1641 if (!GetSingleTarget(name, TableQuery::Table, &target)) {
1642 return false;
1643 }
1644 if (DeviceMapper::GetTargetType(target.spec) != "snapshot-merge") {
1645 // This should be impossible, it was checked earlier.
1646 LOG(ERROR) << "Snapshot device has invalid target type: " << name;
1647 return false;
1648 }
1649
1650 std::string base_device, cow_device;
1651 if (!DmTargetSnapshot::GetDevicesFromParams(target.data, &base_device, &cow_device)) {
1652 LOG(ERROR) << "Could not parse snapshot device " << name
1653 << " parameters: " << target.data;
1654 return false;
1655 }
1656 }
1657
1658 uint64_t snapshot_sectors = status.snapshot_size() / kSectorSize;
1659 if (snapshot_sectors * kSectorSize != status.snapshot_size()) {
1660 LOG(ERROR) << "Snapshot " << name
1661 << " size is not sector aligned: " << status.snapshot_size();
1662 return false;
1663 }
1664
1665 uint32_t slot = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
1666 // Create a DmTable that is identical to the base device.
1667 CreateLogicalPartitionParams base_device_params{
1668 .block_device = device_->GetSuperDevice(slot),
1669 .metadata_slot = slot,
1670 .partition_name = name,
1671 .partition_opener = &device_->GetPartitionOpener(),
1672 };
1673 DmTable table;
1674 if (!CreateDmTable(base_device_params, &table)) {
1675 LOG(ERROR) << "Could not create a DmTable for partition: " << name;
1676 return false;
1677 }
1678
1679 if (!dm_.LoadTableAndActivate(name, table)) {
1680 return false;
1681 }
1682
1683 if (!UpdateUsesUserSnapshots(lock)) {
1684 // Attempt to delete the snapshot device if one still exists. Nothing
1685 // should be depending on the device, and device-mapper should have
1686 // flushed remaining I/O. We could in theory replace with dm-zero (or
1687 // re-use the table above), but for now it's better to know why this
1688 // would fail.
1689 //
1690 // Furthermore, we should not be trying to unmap for userspace snapshot
1691 // as unmap will fail since dm-user itself was a snapshot device prior
1692 // to switching of tables. Unmap will fail as the device will be mounted
1693 // by system partitions
1694 if (status.using_snapuserd()) {
1695 auto dm_user_name = GetDmUserCowName(name, GetSnapshotDriver(lock));
1696 UnmapDmUserDevice(dm_user_name);
1697 }
1698 }
1699
1700 // We can't delete base device immediately as daemon holds a reference.
1701 // Make sure we wait for all the worker threads to terminate and release
1702 // the reference
1703 if (UpdateUsesUserSnapshots(lock) && EnsureSnapuserdConnected()) {
1704 if (!snapuserd_client_->WaitForDeviceDelete(name)) {
1705 LOG(ERROR) << "Failed to wait for " << name << " control device to delete";
1706 }
1707 }
1708
1709 auto base_name = GetBaseDeviceName(name);
1710 if (!DeleteDeviceIfExists(base_name)) {
1711 LOG(ERROR) << "Unable to delete base device for snapshot: " << base_name;
1712 }
1713
1714 if (!DeleteDeviceIfExists(GetSourceDeviceName(name), 4000ms)) {
1715 LOG(ERROR) << "Unable to delete source device for snapshot: " << GetSourceDeviceName(name);
1716 }
1717
1718 return true;
1719 }
1720
HandleCancelledUpdate(LockedFile * lock,const std::function<bool ()> & before_cancel)1721 bool SnapshotManager::HandleCancelledUpdate(LockedFile* lock,
1722 const std::function<bool()>& before_cancel) {
1723 auto slot = GetCurrentSlot();
1724 if (slot == Slot::Unknown) {
1725 return false;
1726 }
1727
1728 // If all snapshots were reflashed, then cancel the entire update.
1729 if (AreAllSnapshotsCancelled(lock)) {
1730 LOG(WARNING) << "Detected re-flashing, cancelling unverified update.";
1731 return RemoveAllUpdateState(lock, before_cancel);
1732 }
1733
1734 // If update has been rolled back, then cancel the entire update.
1735 // Client (update_engine) is responsible for doing additional cleanup work on its own states
1736 // when ProcessUpdateState() returns UpdateState::Cancelled.
1737 auto current_slot = GetCurrentSlot();
1738 if (current_slot != Slot::Source) {
1739 LOG(INFO) << "Update state is being processed while booting at " << current_slot
1740 << " slot, taking no action.";
1741 return false;
1742 }
1743
1744 // current_slot == Source. Attempt to detect rollbacks.
1745 if (access(GetRollbackIndicatorPath().c_str(), F_OK) != 0) {
1746 // This unverified update is not attempted. Take no action.
1747 PLOG(INFO) << "Rollback indicator not detected. "
1748 << "Update state is being processed before reboot, taking no action.";
1749 return false;
1750 }
1751
1752 LOG(WARNING) << "Detected rollback, cancelling unverified update.";
1753 return RemoveAllUpdateState(lock, before_cancel);
1754 }
1755
PerformInitTransition(InitTransition transition,std::vector<std::string> * snapuserd_argv)1756 bool SnapshotManager::PerformInitTransition(InitTransition transition,
1757 std::vector<std::string>* snapuserd_argv) {
1758 LOG(INFO) << "Performing transition for snapuserd.";
1759
1760 // Don't use EnsureSnapuserdConnected() because this is called from init,
1761 // and attempting to do so will deadlock.
1762 if (!snapuserd_client_ && transition != InitTransition::SELINUX_DETACH) {
1763 snapuserd_client_ = SnapuserdClient::Connect(kSnapuserdSocket, 10s);
1764 if (!snapuserd_client_) {
1765 LOG(ERROR) << "Unable to connect to snapuserd";
1766 return false;
1767 }
1768 }
1769
1770 auto lock = LockExclusive();
1771 if (!lock) return false;
1772
1773 std::vector<std::string> snapshots;
1774 if (!ListSnapshots(lock.get(), &snapshots)) {
1775 LOG(ERROR) << "Failed to list snapshots.";
1776 return false;
1777 }
1778
1779 if (UpdateUsesUserSnapshots(lock.get()) && transition == InitTransition::SELINUX_DETACH) {
1780 snapuserd_argv->emplace_back("-user_snapshot");
1781 if (UpdateUsesIouring(lock.get())) {
1782 snapuserd_argv->emplace_back("-io_uring");
1783 }
1784 if (UpdateUsesODirect(lock.get())) {
1785 snapuserd_argv->emplace_back("-o_direct");
1786 }
1787 uint cow_op_merge_size = GetUpdateCowOpMergeSize(lock.get());
1788 if (cow_op_merge_size != 0) {
1789 snapuserd_argv->emplace_back("-cow_op_merge_size=" + std::to_string(cow_op_merge_size));
1790 }
1791 uint32_t worker_count = GetUpdateWorkerCount(lock.get());
1792 if (worker_count != 0) {
1793 snapuserd_argv->emplace_back("-worker_count=" + std::to_string(worker_count));
1794 }
1795 uint32_t verify_block_size = GetVerificationBlockSize(lock.get());
1796 if (verify_block_size != 0) {
1797 snapuserd_argv->emplace_back("-verify_block_size=" + std::to_string(verify_block_size));
1798 }
1799 uint32_t num_verify_threads = GetNumVerificationThreads(lock.get());
1800 if (num_verify_threads != 0) {
1801 snapuserd_argv->emplace_back("-num_verify_threads=" +
1802 std::to_string(num_verify_threads));
1803 }
1804 }
1805
1806 size_t num_cows = 0;
1807 size_t ok_cows = 0;
1808 for (const auto& snapshot : snapshots) {
1809 std::string user_cow_name = GetDmUserCowName(snapshot, GetSnapshotDriver(lock.get()));
1810
1811 if (dm_.GetState(user_cow_name) == DmDeviceState::INVALID) {
1812 continue;
1813 }
1814
1815 DeviceMapper::TargetInfo target;
1816 if (!GetSingleTarget(user_cow_name, TableQuery::Table, &target)) {
1817 continue;
1818 }
1819
1820 auto target_type = DeviceMapper::GetTargetType(target.spec);
1821 if (target_type != "user") {
1822 LOG(ERROR) << "Unexpected target type for " << user_cow_name << ": " << target_type;
1823 continue;
1824 }
1825
1826 num_cows++;
1827
1828 SnapshotStatus snapshot_status;
1829 if (!ReadSnapshotStatus(lock.get(), snapshot, &snapshot_status)) {
1830 LOG(ERROR) << "Unable to read snapshot status: " << snapshot;
1831 continue;
1832 }
1833
1834 auto misc_name = user_cow_name;
1835
1836 std::string source_device_name;
1837 if (snapshot_status.old_partition_size() > 0) {
1838 source_device_name = GetSourceDeviceName(snapshot);
1839 } else {
1840 source_device_name = GetBaseDeviceName(snapshot);
1841 }
1842
1843 std::string source_device;
1844 if (!dm_.GetDmDevicePathByName(source_device_name, &source_device)) {
1845 LOG(ERROR) << "Could not get device path for " << GetSourceDeviceName(snapshot);
1846 continue;
1847 }
1848
1849 std::string base_path_merge;
1850 if (!dm_.GetDmDevicePathByName(GetBaseDeviceName(snapshot), &base_path_merge)) {
1851 LOG(ERROR) << "Could not get device path for " << GetSourceDeviceName(snapshot);
1852 continue;
1853 }
1854
1855 std::string cow_image_name = GetMappedCowDeviceName(snapshot, snapshot_status);
1856
1857 std::string cow_image_device;
1858 if (!dm_.GetDmDevicePathByName(cow_image_name, &cow_image_device)) {
1859 LOG(ERROR) << "Could not get device path for " << cow_image_name;
1860 continue;
1861 }
1862
1863 if (transition == InitTransition::SELINUX_DETACH) {
1864 if (!UpdateUsesUserSnapshots(lock.get())) {
1865 auto message = misc_name + "," + cow_image_device + "," + source_device;
1866 snapuserd_argv->emplace_back(std::move(message));
1867 } else {
1868 auto message = misc_name + "," + cow_image_device + "," + source_device + "," +
1869 base_path_merge;
1870 snapuserd_argv->emplace_back(std::move(message));
1871 }
1872 SetReadAheadSize(cow_image_device, snapshot_status.read_ahead_size());
1873 SetReadAheadSize(source_device, snapshot_status.read_ahead_size());
1874
1875 // Do not attempt to connect to the new snapuserd yet, it hasn't
1876 // been started. We do however want to wait for the misc device
1877 // to have been created.
1878 ok_cows++;
1879 continue;
1880 }
1881
1882 DmTable table;
1883 table.Emplace<DmTargetUser>(0, target.spec.length, misc_name);
1884 if (!dm_.LoadTableAndActivate(user_cow_name, table)) {
1885 LOG(ERROR) << "Unable to swap tables for " << misc_name;
1886 continue;
1887 }
1888
1889 // Wait for ueventd to acknowledge and create the control device node.
1890 std::string control_device = "/dev/dm-user/" + misc_name;
1891 if (!WaitForDevice(control_device, 10s)) {
1892 LOG(ERROR) << "dm-user control device no found: " << misc_name;
1893 continue;
1894 }
1895
1896 uint64_t base_sectors;
1897 if (!UpdateUsesUserSnapshots(lock.get())) {
1898 base_sectors =
1899 snapuserd_client_->InitDmUserCow(misc_name, cow_image_device, source_device);
1900 } else {
1901 base_sectors = snapuserd_client_->InitDmUserCow(misc_name, cow_image_device,
1902 source_device, base_path_merge);
1903 }
1904
1905 if (base_sectors == 0) {
1906 // Unrecoverable as metadata reads from cow device failed
1907 LOG(FATAL) << "Failed to retrieve base_sectors from Snapuserd";
1908 return false;
1909 }
1910
1911 CHECK(base_sectors <= target.spec.length);
1912
1913 if (!snapuserd_client_->AttachDmUser(misc_name)) {
1914 // This error is unrecoverable. We cannot proceed because reads to
1915 // the underlying device will fail.
1916 LOG(FATAL) << "Could not initialize snapuserd for " << user_cow_name;
1917 return false;
1918 }
1919
1920 ok_cows++;
1921 }
1922
1923 if (ok_cows != num_cows) {
1924 LOG(ERROR) << "Could not transition all snapuserd consumers.";
1925 return false;
1926 }
1927 return true;
1928 }
1929
ReadCurrentMetadata()1930 std::unique_ptr<LpMetadata> SnapshotManager::ReadCurrentMetadata() {
1931 const auto& opener = device_->GetPartitionOpener();
1932 uint32_t slot = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
1933 auto super_device = device_->GetSuperDevice(slot);
1934 auto metadata = android::fs_mgr::ReadMetadata(opener, super_device, slot);
1935 if (!metadata) {
1936 LOG(ERROR) << "Could not read dynamic partition metadata for device: " << super_device;
1937 return nullptr;
1938 }
1939 return metadata;
1940 }
1941
GetMetadataPartitionState(const LpMetadata & metadata,const std::string & name)1942 SnapshotManager::MetadataPartitionState SnapshotManager::GetMetadataPartitionState(
1943 const LpMetadata& metadata, const std::string& name) {
1944 auto partition = android::fs_mgr::FindPartition(metadata, name);
1945 if (!partition) return MetadataPartitionState::None;
1946 if (partition->attributes & LP_PARTITION_ATTR_UPDATED) {
1947 return MetadataPartitionState::Updated;
1948 }
1949 return MetadataPartitionState::Flashed;
1950 }
1951
AreAllSnapshotsCancelled(LockedFile * lock)1952 bool SnapshotManager::AreAllSnapshotsCancelled(LockedFile* lock) {
1953 std::vector<std::string> snapshots;
1954 if (!ListSnapshots(lock, &snapshots)) {
1955 LOG(WARNING) << "Failed to list snapshots to determine whether device has been flashed "
1956 << "after applying an update. Assuming no snapshots.";
1957 // Let HandleCancelledUpdate resets UpdateState.
1958 return true;
1959 }
1960
1961 std::map<std::string, bool> flashing_status;
1962
1963 if (!GetSnapshotFlashingStatus(lock, snapshots, &flashing_status)) {
1964 LOG(WARNING) << "Failed to determine whether partitions have been flashed. Not"
1965 << "removing update states.";
1966 return false;
1967 }
1968
1969 bool all_snapshots_cancelled = std::all_of(flashing_status.begin(), flashing_status.end(),
1970 [](const auto& pair) { return pair.second; });
1971
1972 if (all_snapshots_cancelled) {
1973 LOG(WARNING) << "All partitions are re-flashed after update, removing all update states.";
1974 }
1975 return all_snapshots_cancelled;
1976 }
1977
GetSnapshotFlashingStatus(LockedFile * lock,const std::vector<std::string> & snapshots,std::map<std::string,bool> * out)1978 bool SnapshotManager::GetSnapshotFlashingStatus(LockedFile* lock,
1979 const std::vector<std::string>& snapshots,
1980 std::map<std::string, bool>* out) {
1981 CHECK(lock);
1982
1983 auto source_slot_suffix = ReadUpdateSourceSlotSuffix();
1984 if (source_slot_suffix.empty()) {
1985 return false;
1986 }
1987 uint32_t source_slot = SlotNumberForSlotSuffix(source_slot_suffix);
1988 uint32_t target_slot = (source_slot == 0) ? 1 : 0;
1989
1990 // Attempt to detect re-flashing on each partition.
1991 // - If all partitions are re-flashed, we can proceed to cancel the whole update.
1992 // - If only some of the partitions are re-flashed, snapshots for re-flashed partitions are
1993 // deleted. Caller is responsible for merging the rest of the snapshots.
1994 // - If none of the partitions are re-flashed, caller is responsible for merging the snapshots.
1995 //
1996 // Note that we use target slot metadata, since if an OTA has been applied
1997 // to the target slot, we can detect the UPDATED flag. Any kind of flash
1998 // operation against dynamic partitions ensures that all copies of the
1999 // metadata are in sync, so flashing all partitions on the source slot will
2000 // remove the UPDATED flag on the target slot as well.
2001 const auto& opener = device_->GetPartitionOpener();
2002 auto super_device = device_->GetSuperDevice(target_slot);
2003 auto metadata = android::fs_mgr::ReadMetadata(opener, super_device, target_slot);
2004 if (!metadata) {
2005 return false;
2006 }
2007
2008 for (const auto& snapshot_name : snapshots) {
2009 if (GetMetadataPartitionState(*metadata, snapshot_name) ==
2010 MetadataPartitionState::Updated) {
2011 out->emplace(snapshot_name, false);
2012 } else {
2013 // Delete snapshots for partitions that are re-flashed after the update.
2014 LOG(WARNING) << "Detected re-flashing of partition " << snapshot_name << ".";
2015 out->emplace(snapshot_name, true);
2016 }
2017 }
2018 return true;
2019 }
2020
RemoveInvalidSnapshots(LockedFile * lock)2021 void SnapshotManager::RemoveInvalidSnapshots(LockedFile* lock) {
2022 std::vector<std::string> snapshots;
2023
2024 // Remove the stale snapshot metadata
2025 //
2026 // We make sure that all the three cases
2027 // are valid before removing the snapshot metadata:
2028 //
2029 // 1: dm state is active
2030 // 2: Root fs is not mounted off as a snapshot device
2031 // 3: Snapshot slot suffix should match current device slot
2032 if (!ListSnapshots(lock, &snapshots, device_->GetSlotSuffix()) || snapshots.empty()) {
2033 return;
2034 }
2035
2036 // We indeed have some invalid snapshots
2037 for (const auto& name : snapshots) {
2038 if (dm_.GetState(name) == DmDeviceState::ACTIVE && !IsSnapshotDevice(name)) {
2039 if (!DeleteSnapshot(lock, name)) {
2040 LOG(ERROR) << "Failed to delete invalid snapshot: " << name;
2041 } else {
2042 LOG(INFO) << "Invalid snapshot: " << name << " deleted";
2043 }
2044 }
2045 }
2046 }
2047
RemoveAllSnapshots(LockedFile * lock)2048 bool SnapshotManager::RemoveAllSnapshots(LockedFile* lock) {
2049 std::vector<std::string> snapshots;
2050 if (!ListSnapshots(lock, &snapshots)) {
2051 LOG(ERROR) << "Could not list snapshots";
2052 return false;
2053 }
2054
2055 std::map<std::string, bool> flashing_status;
2056 if (!GetSnapshotFlashingStatus(lock, snapshots, &flashing_status)) {
2057 LOG(WARNING) << "Failed to get flashing status";
2058 }
2059
2060 auto current_slot = GetCurrentSlot();
2061 bool ok = true;
2062 bool has_mapped_cow_images = false;
2063 for (const auto& name : snapshots) {
2064 // If booting off source slot, it is okay to unmap and delete all the snapshots.
2065 // If boot indicator is missing, update state is None or Initiated, so
2066 // it is also okay to unmap and delete all the snapshots.
2067 // If booting off target slot,
2068 // - should not unmap because:
2069 // - In Android mode, snapshots are not mapped, but
2070 // filesystems are mounting off dm-linear targets directly.
2071 // - In recovery mode, assume nothing is mapped, so it is optional to unmap.
2072 // - If partition is flashed or unknown, it is okay to delete snapshots.
2073 // Otherwise (UPDATED flag), only delete snapshots if they are not mapped
2074 // as dm-snapshot (for example, after merge completes).
2075 bool should_unmap = current_slot != Slot::Target;
2076 bool should_delete = ShouldDeleteSnapshot(flashing_status, current_slot, name);
2077 if (should_unmap && android::base::EndsWith(name, device_->GetSlotSuffix())) {
2078 // Something very unexpected has happened - we want to unmap this
2079 // snapshot, but it's on the wrong slot. We can't unmap an active
2080 // partition. If this is not really a snapshot, skip the unmap
2081 // step.
2082 if (dm_.GetState(name) == DmDeviceState::INVALID || !IsSnapshotDevice(name)) {
2083 LOG(ERROR) << "Detected snapshot " << name << " on " << current_slot << " slot"
2084 << " for source partition; removing without unmap.";
2085 should_unmap = false;
2086 }
2087 }
2088
2089 bool partition_ok = true;
2090 if (should_unmap && !UnmapPartitionWithSnapshot(lock, name)) {
2091 partition_ok = false;
2092 }
2093 if (partition_ok && should_delete && !DeleteSnapshot(lock, name)) {
2094 partition_ok = false;
2095 }
2096
2097 if (!partition_ok) {
2098 // Remember whether or not we were able to unmap the cow image.
2099 auto cow_image_device = GetCowImageDeviceName(name);
2100 has_mapped_cow_images |=
2101 (EnsureImageManager() && images_->IsImageMapped(cow_image_device));
2102
2103 ok = false;
2104 }
2105 }
2106
2107 if (ok || !has_mapped_cow_images) {
2108 if (!EnsureImageManager()) {
2109 return false;
2110 }
2111
2112 if (device_->IsRecovery()) {
2113 // If a device is in recovery, we need to mark the snapshots for cleanup
2114 // upon next reboot, since we cannot delete them here.
2115 if (!images_->DisableAllImages()) {
2116 LOG(ERROR) << "Could not remove all snapshot artifacts in recovery";
2117 return false;
2118 }
2119 } else if (!images_->RemoveAllImages()) {
2120 // Delete any image artifacts as a precaution, in case an update is
2121 // being cancelled due to some corrupted state in an lp_metadata file.
2122 // Note that we do not do this if some cow images are still mapped,
2123 // since we must not remove backing storage if it's in use.
2124 LOG(ERROR) << "Could not remove all snapshot artifacts";
2125 return false;
2126 }
2127 }
2128 return ok;
2129 }
2130
2131 // See comments in RemoveAllSnapshots().
ShouldDeleteSnapshot(const std::map<std::string,bool> & flashing_status,Slot current_slot,const std::string & name)2132 bool SnapshotManager::ShouldDeleteSnapshot(const std::map<std::string, bool>& flashing_status,
2133 Slot current_slot, const std::string& name) {
2134 if (current_slot != Slot::Target) {
2135 return true;
2136 }
2137 auto it = flashing_status.find(name);
2138 if (it == flashing_status.end()) {
2139 LOG(WARNING) << "Can't determine flashing status for " << name;
2140 return true;
2141 }
2142 if (it->second) {
2143 // partition flashed, okay to delete obsolete snapshots
2144 return true;
2145 }
2146 return !IsSnapshotDevice(name);
2147 }
2148
GetUpdateState(double * progress)2149 UpdateState SnapshotManager::GetUpdateState(double* progress) {
2150 // If we've never started an update, the state file won't exist.
2151 auto state_file = GetStateFilePath();
2152 if (access(state_file.c_str(), F_OK) != 0 && errno == ENOENT) {
2153 return UpdateState::None;
2154 }
2155
2156 auto lock = LockShared();
2157 if (!lock) {
2158 return UpdateState::None;
2159 }
2160
2161 SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock.get());
2162 auto state = update_status.state();
2163 if (progress == nullptr) {
2164 return state;
2165 }
2166
2167 if (state == UpdateState::MergeCompleted) {
2168 *progress = 100.0;
2169 return state;
2170 }
2171
2172 *progress = 0.0;
2173 if (state != UpdateState::Merging) {
2174 return state;
2175 }
2176
2177 if (!UpdateUsesUserSnapshots(lock.get())) {
2178 // Sum all the snapshot states as if the system consists of a single huge
2179 // snapshots device, then compute the merge completion percentage of that
2180 // device.
2181 std::vector<std::string> snapshots;
2182 if (!ListSnapshots(lock.get(), &snapshots)) {
2183 LOG(ERROR) << "Could not list snapshots";
2184 return state;
2185 }
2186
2187 DmTargetSnapshot::Status fake_snapshots_status = {};
2188 for (const auto& snapshot : snapshots) {
2189 DmTargetSnapshot::Status current_status;
2190
2191 if (!IsSnapshotDevice(snapshot)) continue;
2192 if (!QuerySnapshotStatus(snapshot, nullptr, ¤t_status)) continue;
2193
2194 fake_snapshots_status.sectors_allocated += current_status.sectors_allocated;
2195 fake_snapshots_status.total_sectors += current_status.total_sectors;
2196 fake_snapshots_status.metadata_sectors += current_status.metadata_sectors;
2197 }
2198
2199 *progress = DmTargetSnapshot::MergePercent(fake_snapshots_status,
2200 update_status.sectors_allocated());
2201 } else {
2202 if (EnsureSnapuserdConnected()) {
2203 *progress = snapuserd_client_->GetMergePercent();
2204 }
2205 }
2206
2207 return state;
2208 }
2209
IsSnapshotWithoutSlotSwitch()2210 bool SnapshotManager::IsSnapshotWithoutSlotSwitch() {
2211 return (access(GetBootSnapshotsWithoutSlotSwitchPath().c_str(), F_OK) == 0);
2212 }
2213
UpdateUsesCompression()2214 bool SnapshotManager::UpdateUsesCompression() {
2215 auto lock = LockShared();
2216 if (!lock) return false;
2217 return UpdateUsesCompression(lock.get());
2218 }
2219
UpdateUsesCompression(LockedFile * lock)2220 bool SnapshotManager::UpdateUsesCompression(LockedFile* lock) {
2221 // This returns true even if compression is "none", since update_engine is
2222 // really just trying to see if snapuserd is in use.
2223 SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2224 return update_status.using_snapuserd();
2225 }
2226
UpdateUsesIouring(LockedFile * lock)2227 bool SnapshotManager::UpdateUsesIouring(LockedFile* lock) {
2228 SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2229 return update_status.io_uring_enabled();
2230 }
2231
UpdateUsesODirect(LockedFile * lock)2232 bool SnapshotManager::UpdateUsesODirect(LockedFile* lock) {
2233 SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2234 return update_status.o_direct();
2235 }
2236
UpdateUsesSkipVerification(LockedFile * lock)2237 bool SnapshotManager::UpdateUsesSkipVerification(LockedFile* lock) {
2238 SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2239 return update_status.skip_verification();
2240 }
2241
GetUpdateCowOpMergeSize(LockedFile * lock)2242 uint32_t SnapshotManager::GetUpdateCowOpMergeSize(LockedFile* lock) {
2243 SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2244 return update_status.cow_op_merge_size();
2245 }
2246
GetUpdateWorkerCount(LockedFile * lock)2247 uint32_t SnapshotManager::GetUpdateWorkerCount(LockedFile* lock) {
2248 SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2249 return update_status.num_worker_threads();
2250 }
2251
GetVerificationBlockSize(LockedFile * lock)2252 uint32_t SnapshotManager::GetVerificationBlockSize(LockedFile* lock) {
2253 SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2254 return update_status.verify_block_size();
2255 }
2256
GetNumVerificationThreads(LockedFile * lock)2257 uint32_t SnapshotManager::GetNumVerificationThreads(LockedFile* lock) {
2258 SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2259 return update_status.num_verification_threads();
2260 }
2261
MarkSnapuserdFromSystem()2262 bool SnapshotManager::MarkSnapuserdFromSystem() {
2263 auto path = GetSnapuserdFromSystemPath();
2264
2265 if (!android::base::WriteStringToFile("1", path)) {
2266 PLOG(ERROR) << "Unable to write to vendor update path: " << path;
2267 return false;
2268 }
2269
2270 unique_fd fd(open(path.c_str(), O_PATH));
2271 if (fd < 0) {
2272 PLOG(ERROR) << "Failed to open file: " << path;
2273 return false;
2274 }
2275
2276 /*
2277 * This function is invoked by first stage init and hence we need to
2278 * explicitly set the correct selinux label for this file as update_engine
2279 * will try to remove this file later on once the snapshot merge is
2280 * complete.
2281 */
2282 if (fsetxattr(fd.get(), XATTR_NAME_SELINUX, kOtaFileContext, strlen(kOtaFileContext) + 1, 0) <
2283 0) {
2284 PLOG(ERROR) << "fsetxattr for the path: " << path << " failed";
2285 }
2286
2287 return true;
2288 }
2289
2290 /*
2291 * Please see b/304829384 for more details.
2292 *
2293 * In Android S, we use dm-snapshot for mounting snapshots and snapshot-merge
2294 * process. If the vendor partition continues to be on Android S, then
2295 * "snapuserd" binary in first stage ramdisk will be from vendor partition.
2296 * Thus, we need to maintain backward compatibility.
2297 *
2298 * Now, We take a two step approach to maintain the backward compatibility:
2299 *
2300 * 1: During OTA installation, we will continue to use "user-space" snapshots
2301 * for OTA installation as both update-engine and snapuserd binary will be from system partition.
2302 * However, during installation, we mark "legacy_snapuserd" in
2303 * SnapshotUpdateStatus file to mark that this is a path to support backward compatibility.
2304 * Thus, this function will return "false" during OTA installation.
2305 *
2306 * 2: Post OTA reboot, there are two key steps:
2307 * a: During first stage init, "init" and "snapuserd" could be from vendor
2308 * partition. This could be from Android S. Thus, the snapshot mount path
2309 * will be based off dm-snapshot.
2310 *
2311 * b: Post selinux transition, "init" and "update-engine" will be "system"
2312 * partition. Now, since the snapshots are mounted off dm-snapshot,
2313 * update-engine interaction with "snapuserd" should work based off
2314 * dm-snapshots.
2315 *
2316 * TL;DR: update-engine will use the "system" snapuserd for installing new
2317 * updates (this is safe as there is no "vendor" snapuserd running during
2318 * installation). Post reboot, update-engine will use the legacy path when
2319 * communicating with "vendor" snapuserd that was started in first-stage
2320 * init. Hence, this function checks:
2321 * i: Are we in post OTA reboot
2322 * ii: Is the Vendor from Android 12
2323 * iii: If both (i) and (ii) are true, then use the dm-snapshot based
2324 * approach.
2325 *
2326 * 3: Post OTA reboot, if the vendor partition was updated from Android 12 to
2327 * any other release post Android 12, then snapuserd binary will be "system"
2328 * partition as post Android 12, init_boot will contain a copy of snapuserd
2329 * binary. Thus, during first stage init, if init is able to communicate to
2330 * daemon, that gives us a signal that the binary is from "system" copy. Hence,
2331 * there is no need to fallback to legacy dm-snapshot. Thus, init will use a
2332 * marker in /metadata to signal that the snapuserd binary from first stage init
2333 * can handle userspace snapshots.
2334 *
2335 */
IsLegacySnapuserdPostReboot()2336 bool SnapshotManager::IsLegacySnapuserdPostReboot() {
2337 auto slot = GetCurrentSlot();
2338 if (slot == Slot::Target) {
2339 /*
2340 If this marker is present, the daemon can handle userspace snapshots.
2341 During post-OTA reboot, this implies that the vendor partition is
2342 Android 13 or higher. If the snapshots were created on an
2343 Android 12 vendor, this means the vendor partition has been updated.
2344 */
2345 if (access(GetSnapuserdFromSystemPath().c_str(), F_OK) == 0) {
2346 is_snapshot_userspace_ = true;
2347 return false;
2348 }
2349 // If the marker isn't present and if the vendor is still in Android 12
2350 if (is_legacy_snapuserd_.has_value() && is_legacy_snapuserd_.value() == true) {
2351 return true;
2352 }
2353 }
2354
2355 return false;
2356 }
2357
UpdateUsesUserSnapshots()2358 bool SnapshotManager::UpdateUsesUserSnapshots() {
2359 // This and the following function is constantly
2360 // invoked during snapshot merge. We want to avoid
2361 // constantly reading from disk. Hence, store this
2362 // value in memory.
2363 //
2364 // Furthermore, this value in the disk is set
2365 // only when OTA is applied and doesn't change
2366 // during merge phase. Hence, once we know that
2367 // the value is read from disk the very first time,
2368 // it is safe to read successive checks from memory.
2369
2370 if (is_snapshot_userspace_.has_value()) {
2371 // Check if legacy snapuserd is running post OTA reboot
2372 if (IsLegacySnapuserdPostReboot()) {
2373 return false;
2374 }
2375 return is_snapshot_userspace_.value();
2376 }
2377
2378 auto lock = LockShared();
2379 if (!lock) return false;
2380
2381 return UpdateUsesUserSnapshots(lock.get());
2382 }
2383
UpdateUsesUserSnapshots(LockedFile * lock)2384 bool SnapshotManager::UpdateUsesUserSnapshots(LockedFile* lock) {
2385 if (!is_snapshot_userspace_.has_value()) {
2386 SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2387 is_snapshot_userspace_ = update_status.userspace_snapshots();
2388 is_legacy_snapuserd_ = update_status.legacy_snapuserd();
2389 }
2390
2391 if (IsLegacySnapuserdPostReboot()) {
2392 return false;
2393 }
2394
2395 return is_snapshot_userspace_.value();
2396 }
2397
ListSnapshots(LockedFile * lock,std::vector<std::string> * snapshots,const std::string & suffix)2398 bool SnapshotManager::ListSnapshots(LockedFile* lock, std::vector<std::string>* snapshots,
2399 const std::string& suffix) {
2400 CHECK(lock);
2401
2402 auto dir_path = metadata_dir_ + "/snapshots"s;
2403 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(dir_path.c_str()), closedir);
2404 if (!dir) {
2405 PLOG(ERROR) << "opendir failed: " << dir_path;
2406 return false;
2407 }
2408
2409 struct dirent* dp;
2410 while ((dp = readdir(dir.get())) != nullptr) {
2411 if (dp->d_type != DT_REG) continue;
2412
2413 std::string name(dp->d_name);
2414 if (!suffix.empty() && !android::base::EndsWith(name, suffix)) {
2415 continue;
2416 }
2417
2418 // Insert system and product partition at the beginning so that
2419 // during snapshot-merge, these partitions are merged first.
2420 if (name == "system_a" || name == "system_b" || name == "product_a" ||
2421 name == "product_b") {
2422 snapshots->insert(snapshots->begin(), std::move(name));
2423 } else {
2424 snapshots->emplace_back(std::move(name));
2425 }
2426 }
2427
2428 return true;
2429 }
2430
IsSnapshotManagerNeeded()2431 bool SnapshotManager::IsSnapshotManagerNeeded() {
2432 if (access(kBootIndicatorPath, F_OK) == 0) {
2433 return true;
2434 }
2435
2436 if (IsScratchOtaMetadataOnSuper()) {
2437 return true;
2438 }
2439
2440 return false;
2441 }
2442
MapTempOtaMetadataPartitionIfNeeded(const std::function<bool (const std::string &)> & init)2443 bool SnapshotManager::MapTempOtaMetadataPartitionIfNeeded(
2444 const std::function<bool(const std::string&)>& init) {
2445 auto device = android::snapshot::GetScratchOtaMetadataPartition();
2446 if (!device.empty()) {
2447 init(device);
2448 if (android::snapshot::MapScratchOtaMetadataPartition(device).empty()) {
2449 return false;
2450 }
2451 }
2452 return true;
2453 }
2454
GetGlobalRollbackIndicatorPath()2455 std::string SnapshotManager::GetGlobalRollbackIndicatorPath() {
2456 return kRollbackIndicatorPath;
2457 }
2458
NeedSnapshotsInFirstStageMount()2459 bool SnapshotManager::NeedSnapshotsInFirstStageMount() {
2460 if (IsSnapshotWithoutSlotSwitch()) {
2461 if (GetCurrentSlot() != Slot::Source) {
2462 LOG(ERROR) << "Snapshots marked to boot without slot switch; but slot is wrong";
2463 return false;
2464 }
2465 return true;
2466 }
2467 // If we fail to read, we'll wind up using CreateLogicalPartitions, which
2468 // will create devices that look like the old slot, except with extra
2469 // content at the end of each device. This will confuse dm-verity, and
2470 // ultimately we'll fail to boot. Why not make it a fatal error and have
2471 // the reason be clearer? Because the indicator file still exists, and
2472 // if this was FATAL, reverting to the old slot would be broken.
2473 auto slot = GetCurrentSlot();
2474
2475 if (slot != Slot::Target) {
2476 if (slot == Slot::Source) {
2477 // Device is rebooting into the original slot, so mark this as a
2478 // rollback.
2479 auto path = GetRollbackIndicatorPath();
2480 if (!android::base::WriteStringToFile("1", path)) {
2481 PLOG(ERROR) << "Unable to write rollback indicator: " << path;
2482 } else {
2483 LOG(INFO) << "Rollback detected, writing rollback indicator to " << path;
2484 if (device_->IsTempMetadata()) {
2485 CleanupScratchOtaMetadataIfPresent();
2486 }
2487 }
2488 }
2489 LOG(INFO) << "Not booting from new slot. Will not mount snapshots.";
2490 return false;
2491 }
2492
2493 // If we can't read the update state, it's unlikely anything else will
2494 // succeed, so this is a fatal error. We'll eventually exhaust boot
2495 // attempts and revert to the old slot.
2496 auto lock = LockShared();
2497 if (!lock) {
2498 LOG(FATAL) << "Could not read update state to determine snapshot status";
2499 return false;
2500 }
2501 switch (ReadUpdateState(lock.get())) {
2502 case UpdateState::Unverified:
2503 case UpdateState::Merging:
2504 case UpdateState::MergeFailed:
2505 return true;
2506 default:
2507 return false;
2508 }
2509 }
2510
CreateLogicalAndSnapshotPartitions(const std::string & super_device,const std::chrono::milliseconds & timeout_ms)2511 bool SnapshotManager::CreateLogicalAndSnapshotPartitions(
2512 const std::string& super_device, const std::chrono::milliseconds& timeout_ms) {
2513 LOG(INFO) << "Creating logical partitions with snapshots as needed";
2514
2515 auto lock = LockExclusive();
2516 if (!lock) return false;
2517
2518 uint32_t slot = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
2519 return MapAllPartitions(lock.get(), super_device, slot, timeout_ms);
2520 }
2521
MapAllPartitions(LockedFile * lock,const std::string & super_device,uint32_t slot,const std::chrono::milliseconds & timeout_ms)2522 bool SnapshotManager::MapAllPartitions(LockedFile* lock, const std::string& super_device,
2523 uint32_t slot, const std::chrono::milliseconds& timeout_ms) {
2524 const auto& opener = device_->GetPartitionOpener();
2525 auto metadata = android::fs_mgr::ReadMetadata(opener, super_device, slot);
2526 if (!metadata) {
2527 LOG(ERROR) << "Could not read dynamic partition metadata for device: " << super_device;
2528 return false;
2529 }
2530
2531 if (!EnsureImageManager()) {
2532 return false;
2533 }
2534
2535 for (const auto& partition : metadata->partitions) {
2536 if (GetPartitionGroupName(metadata->groups[partition.group_index]) == kCowGroupName) {
2537 LOG(INFO) << "Skip mapping partition " << GetPartitionName(partition) << " in group "
2538 << kCowGroupName;
2539 continue;
2540 }
2541
2542 if (GetPartitionName(partition) ==
2543 android::base::Basename(android::snapshot::kOtaMetadataMount)) {
2544 LOG(INFO) << "Partition: " << GetPartitionName(partition) << " skipping";
2545 continue;
2546 }
2547
2548 CreateLogicalPartitionParams params = {
2549 .block_device = super_device,
2550 .metadata = metadata.get(),
2551 .partition = &partition,
2552 .timeout_ms = timeout_ms,
2553 .partition_opener = &opener,
2554 };
2555 if (!MapPartitionWithSnapshot(lock, std::move(params), SnapshotContext::Mount, nullptr)) {
2556 return false;
2557 }
2558 }
2559
2560 LOG(INFO) << "Created logical partitions with snapshot.";
2561 return true;
2562 }
2563
GetRemainingTime(const std::chrono::milliseconds & timeout,const std::chrono::time_point<std::chrono::steady_clock> & begin)2564 static std::chrono::milliseconds GetRemainingTime(
2565 const std::chrono::milliseconds& timeout,
2566 const std::chrono::time_point<std::chrono::steady_clock>& begin) {
2567 // If no timeout is specified, execute all commands without specifying any timeout.
2568 if (timeout.count() == 0) return std::chrono::milliseconds(0);
2569 auto passed_time = std::chrono::steady_clock::now() - begin;
2570 auto remaining_time = timeout - duration_cast<std::chrono::milliseconds>(passed_time);
2571 if (remaining_time.count() <= 0) {
2572 LOG(ERROR) << "MapPartitionWithSnapshot has reached timeout " << timeout.count() << "ms ("
2573 << remaining_time.count() << "ms remaining)";
2574 // Return min() instead of remaining_time here because 0 is treated as a special value for
2575 // no timeout, where the rest of the commands will still be executed.
2576 return std::chrono::milliseconds::min();
2577 }
2578 return remaining_time;
2579 }
2580
MapPartitionWithSnapshot(LockedFile * lock,CreateLogicalPartitionParams params,SnapshotContext context,SnapshotPaths * paths)2581 bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock,
2582 CreateLogicalPartitionParams params,
2583 SnapshotContext context, SnapshotPaths* paths) {
2584 auto begin = std::chrono::steady_clock::now();
2585
2586 CHECK(lock);
2587
2588 if (params.GetPartitionName() != params.GetDeviceName()) {
2589 LOG(ERROR) << "Mapping snapshot with a different name is unsupported: partition_name = "
2590 << params.GetPartitionName() << ", device_name = " << params.GetDeviceName();
2591 return false;
2592 }
2593
2594 // Fill out fields in CreateLogicalPartitionParams so that we have more information (e.g. by
2595 // reading super partition metadata).
2596 CreateLogicalPartitionParams::OwnedData params_owned_data;
2597 if (!params.InitDefaults(¶ms_owned_data)) {
2598 return false;
2599 }
2600
2601 if (!params.partition->num_extents) {
2602 LOG(INFO) << "Skipping zero-length logical partition: " << params.GetPartitionName();
2603 return true; // leave path empty to indicate that nothing is mapped.
2604 }
2605
2606 // Determine if there is a live snapshot for the SnapshotStatus of the partition; i.e. if the
2607 // partition still has a snapshot that needs to be mapped. If no live snapshot or merge
2608 // completed, live_snapshot_status is set to nullopt.
2609 std::optional<SnapshotStatus> live_snapshot_status;
2610 do {
2611 if (!IsSnapshotWithoutSlotSwitch() &&
2612 !(params.partition->attributes & LP_PARTITION_ATTR_UPDATED)) {
2613 LOG(INFO) << "Detected re-flashing of partition, will skip snapshot: "
2614 << params.GetPartitionName();
2615 break;
2616 }
2617 auto file_path = GetSnapshotStatusFilePath(params.GetPartitionName());
2618 if (access(file_path.c_str(), F_OK) != 0) {
2619 if (errno != ENOENT) {
2620 PLOG(INFO) << "Can't map snapshot for " << params.GetPartitionName()
2621 << ": Can't access " << file_path;
2622 return false;
2623 }
2624 break;
2625 }
2626 live_snapshot_status = std::make_optional<SnapshotStatus>();
2627 if (!ReadSnapshotStatus(lock, params.GetPartitionName(), &*live_snapshot_status)) {
2628 return false;
2629 }
2630 // No live snapshot if merge is completed.
2631 if (live_snapshot_status->state() == SnapshotState::MERGE_COMPLETED) {
2632 live_snapshot_status.reset();
2633 }
2634
2635 if (live_snapshot_status->state() == SnapshotState::NONE ||
2636 live_snapshot_status->cow_partition_size() + live_snapshot_status->cow_file_size() ==
2637 0) {
2638 LOG(WARNING) << "Snapshot status for " << params.GetPartitionName()
2639 << " is invalid, ignoring: state = "
2640 << SnapshotState_Name(live_snapshot_status->state())
2641 << ", cow_partition_size = " << live_snapshot_status->cow_partition_size()
2642 << ", cow_file_size = " << live_snapshot_status->cow_file_size();
2643 live_snapshot_status.reset();
2644 }
2645 } while (0);
2646
2647 if (live_snapshot_status.has_value()) {
2648 // dm-snapshot requires the base device to be writable.
2649 params.force_writable = true;
2650 // Map the base device with a different name to avoid collision.
2651 params.device_name = GetBaseDeviceName(params.GetPartitionName());
2652 }
2653
2654 AutoDeviceList created_devices;
2655
2656 // Create the base device for the snapshot, or if there is no snapshot, the
2657 // device itself. This device consists of the real blocks in the super
2658 // partition that this logical partition occupies.
2659 std::string base_path;
2660 if (!CreateLogicalPartition(params, &base_path)) {
2661 LOG(ERROR) << "Could not create logical partition " << params.GetPartitionName()
2662 << " as device " << params.GetDeviceName();
2663 return false;
2664 }
2665 created_devices.EmplaceBack<AutoUnmapDevice>(&dm_, params.GetDeviceName());
2666
2667 if (paths) {
2668 paths->target_device = base_path;
2669 }
2670
2671 auto remaining_time = GetRemainingTime(params.timeout_ms, begin);
2672 if (remaining_time.count() < 0) {
2673 return false;
2674 }
2675
2676 // Wait for the base device to appear
2677 if (!WaitForDevice(base_path, remaining_time)) {
2678 return false;
2679 }
2680
2681 if (!live_snapshot_status.has_value()) {
2682 created_devices.Release();
2683 return true;
2684 }
2685
2686 // We don't have ueventd in first-stage init, so use device major:minor
2687 // strings instead.
2688 std::string base_device;
2689 if (!dm_.GetDeviceString(params.GetDeviceName(), &base_device)) {
2690 LOG(ERROR) << "Could not determine major/minor for: " << params.GetDeviceName();
2691 return false;
2692 }
2693
2694 remaining_time = GetRemainingTime(params.timeout_ms, begin);
2695 if (remaining_time.count() < 0) return false;
2696
2697 std::string cow_name;
2698 CreateLogicalPartitionParams cow_params = params;
2699 cow_params.timeout_ms = remaining_time;
2700 if (!MapCowDevices(lock, cow_params, *live_snapshot_status, &created_devices, &cow_name)) {
2701 return false;
2702 }
2703 std::string cow_device;
2704 if (!GetMappedImageDeviceStringOrPath(cow_name, &cow_device)) {
2705 LOG(ERROR) << "Could not determine major/minor for: " << cow_name;
2706 return false;
2707 }
2708 if (paths) {
2709 paths->cow_device_name = cow_name;
2710 }
2711
2712 remaining_time = GetRemainingTime(params.timeout_ms, begin);
2713 if (remaining_time.count() < 0) return false;
2714
2715 if (context == SnapshotContext::Update && live_snapshot_status->using_snapuserd()) {
2716 // Stop here, we can't run dm-user yet, the COW isn't built.
2717 created_devices.Release();
2718 return true;
2719 }
2720
2721 if (live_snapshot_status->using_snapuserd()) {
2722 // Get the source device (eg the view of the partition from before it was resized).
2723 std::string source_device_path;
2724 if (live_snapshot_status->old_partition_size() > 0) {
2725 if (!MapSourceDevice(lock, params.GetPartitionName(), remaining_time,
2726 &source_device_path)) {
2727 LOG(ERROR) << "Could not map source device for: " << cow_name;
2728 return false;
2729 }
2730
2731 auto source_device = GetSourceDeviceName(params.GetPartitionName());
2732 created_devices.EmplaceBack<AutoUnmapDevice>(&dm_, source_device);
2733 } else {
2734 source_device_path = base_path;
2735 }
2736
2737 if (!WaitForDevice(source_device_path, remaining_time)) {
2738 return false;
2739 }
2740
2741 std::string cow_path;
2742 if (!GetMappedImageDevicePath(cow_name, &cow_path)) {
2743 LOG(ERROR) << "Could not determine path for: " << cow_name;
2744 return false;
2745 }
2746 if (!WaitForDevice(cow_path, remaining_time)) {
2747 return false;
2748 }
2749
2750 auto name = GetDmUserCowName(params.GetPartitionName(), GetSnapshotDriver(lock));
2751
2752 std::string new_cow_device;
2753 if (!MapDmUserCow(lock, name, cow_path, source_device_path, base_path, remaining_time,
2754 &new_cow_device)) {
2755 LOG(ERROR) << "Could not map dm-user device for partition "
2756 << params.GetPartitionName();
2757 return false;
2758 }
2759 created_devices.EmplaceBack<AutoUnmapDevice>(&dm_, name);
2760
2761 cow_device = new_cow_device;
2762 }
2763
2764 // For userspace snapshots, dm-user block device itself will act as a
2765 // snapshot device. There is one subtle difference - MapSnapshot will create
2766 // either snapshot target or snapshot-merge target based on the underlying
2767 // state of the snapshot device. If snapshot-merge target is created, merge
2768 // will immediately start in the kernel.
2769 //
2770 // This is no longer true with respect to userspace snapshots. When dm-user
2771 // block device is created, we just have the snapshots ready but daemon in
2772 // the user-space will not start the merge. We have to explicitly inform the
2773 // daemon to resume the merge. Check ProcessUpdateState() call stack.
2774 if (!UpdateUsesUserSnapshots(lock)) {
2775 remaining_time = GetRemainingTime(params.timeout_ms, begin);
2776 if (remaining_time.count() < 0) return false;
2777
2778 std::string path;
2779 if (!MapSnapshot(lock, params.GetPartitionName(), base_device, cow_device, remaining_time,
2780 &path)) {
2781 LOG(ERROR) << "Could not map snapshot for partition: " << params.GetPartitionName();
2782 return false;
2783 }
2784 // No need to add params.GetPartitionName() to created_devices since it is immediately
2785 // released.
2786
2787 if (paths) {
2788 paths->snapshot_device = path;
2789 }
2790 LOG(INFO) << "Mapped " << params.GetPartitionName() << " as snapshot device at " << path;
2791 } else {
2792 LOG(INFO) << "Mapped " << params.GetPartitionName() << " as snapshot device at "
2793 << cow_device;
2794 }
2795
2796 created_devices.Release();
2797
2798 return true;
2799 }
2800
UnmapPartitionWithSnapshot(LockedFile * lock,const std::string & target_partition_name)2801 bool SnapshotManager::UnmapPartitionWithSnapshot(LockedFile* lock,
2802 const std::string& target_partition_name) {
2803 CHECK(lock);
2804
2805 if (!UnmapSnapshot(lock, target_partition_name)) {
2806 return false;
2807 }
2808
2809 if (!UnmapCowDevices(lock, target_partition_name)) {
2810 return false;
2811 }
2812
2813 auto base_name = GetBaseDeviceName(target_partition_name);
2814 if (!DeleteDeviceIfExists(base_name)) {
2815 LOG(ERROR) << "Cannot delete base device: " << base_name;
2816 return false;
2817 }
2818
2819 auto source_name = GetSourceDeviceName(target_partition_name);
2820 if (!DeleteDeviceIfExists(source_name)) {
2821 LOG(ERROR) << "Cannot delete source device: " << source_name;
2822 return false;
2823 }
2824
2825 LOG(INFO) << "Successfully unmapped snapshot " << target_partition_name;
2826
2827 return true;
2828 }
2829
MapCowDevices(LockedFile * lock,const CreateLogicalPartitionParams & params,const SnapshotStatus & snapshot_status,AutoDeviceList * created_devices,std::string * cow_name)2830 bool SnapshotManager::MapCowDevices(LockedFile* lock, const CreateLogicalPartitionParams& params,
2831 const SnapshotStatus& snapshot_status,
2832 AutoDeviceList* created_devices, std::string* cow_name) {
2833 CHECK(lock);
2834 CHECK(snapshot_status.cow_partition_size() + snapshot_status.cow_file_size() > 0);
2835 auto begin = std::chrono::steady_clock::now();
2836
2837 std::string partition_name = params.GetPartitionName();
2838 std::string cow_image_name = GetCowImageDeviceName(partition_name);
2839 *cow_name = GetCowName(partition_name);
2840
2841 // Map COW image if necessary.
2842 if (snapshot_status.cow_file_size() > 0) {
2843 if (!EnsureImageManager()) return false;
2844 auto remaining_time = GetRemainingTime(params.timeout_ms, begin);
2845 if (remaining_time.count() < 0) return false;
2846
2847 if (!MapCowImage(partition_name, remaining_time).has_value()) {
2848 LOG(ERROR) << "Could not map cow image for partition: " << partition_name;
2849 return false;
2850 }
2851 created_devices->EmplaceBack<AutoUnmapImage>(images_.get(), cow_image_name);
2852
2853 // If no COW partition exists, just return the image alone.
2854 if (snapshot_status.cow_partition_size() == 0) {
2855 *cow_name = std::move(cow_image_name);
2856 LOG(INFO) << "Mapped COW image for " << partition_name << " at " << *cow_name;
2857 return true;
2858 }
2859 }
2860
2861 auto remaining_time = GetRemainingTime(params.timeout_ms, begin);
2862 if (remaining_time.count() < 0) return false;
2863
2864 CHECK(snapshot_status.cow_partition_size() > 0);
2865
2866 // Create the DmTable for the COW device. It is the DmTable of the COW partition plus
2867 // COW image device as the last extent.
2868 CreateLogicalPartitionParams cow_partition_params = params;
2869 cow_partition_params.partition = nullptr;
2870 cow_partition_params.partition_name = *cow_name;
2871 cow_partition_params.device_name.clear();
2872 DmTable table;
2873 if (!CreateDmTable(cow_partition_params, &table)) {
2874 return false;
2875 }
2876 // If the COW image exists, append it as the last extent.
2877 if (snapshot_status.cow_file_size() > 0) {
2878 std::string cow_image_device;
2879 if (!GetMappedImageDeviceStringOrPath(cow_image_name, &cow_image_device)) {
2880 LOG(ERROR) << "Cannot determine major/minor for: " << cow_image_name;
2881 return false;
2882 }
2883 auto cow_partition_sectors = snapshot_status.cow_partition_size() / kSectorSize;
2884 auto cow_image_sectors = snapshot_status.cow_file_size() / kSectorSize;
2885 table.Emplace<DmTargetLinear>(cow_partition_sectors, cow_image_sectors, cow_image_device,
2886 0);
2887 }
2888
2889 // We have created the DmTable now. Map it.
2890 std::string cow_path;
2891 if (!dm_.CreateDevice(*cow_name, table, &cow_path, remaining_time)) {
2892 LOG(ERROR) << "Could not create COW device: " << *cow_name;
2893 return false;
2894 }
2895 created_devices->EmplaceBack<AutoUnmapDevice>(&dm_, *cow_name);
2896 LOG(INFO) << "Mapped COW device for " << params.GetPartitionName() << " at " << cow_path;
2897 return true;
2898 }
2899
UnmapCowDevices(LockedFile * lock,const std::string & name)2900 bool SnapshotManager::UnmapCowDevices(LockedFile* lock, const std::string& name) {
2901 CHECK(lock);
2902 if (!EnsureImageManager()) return false;
2903
2904 if (UpdateUsesCompression(lock) && !UpdateUsesUserSnapshots(lock)) {
2905 auto dm_user_name = GetDmUserCowName(name, GetSnapshotDriver(lock));
2906 if (!UnmapDmUserDevice(dm_user_name)) {
2907 return false;
2908 }
2909 }
2910
2911 if (!DeleteDeviceIfExists(GetCowName(name), 4000ms)) {
2912 LOG(ERROR) << "Cannot unmap: " << GetCowName(name);
2913 return false;
2914 }
2915
2916 std::string cow_image_name = GetCowImageDeviceName(name);
2917 if (!images_->UnmapImageIfExists(cow_image_name)) {
2918 LOG(ERROR) << "Cannot unmap image " << cow_image_name;
2919 return false;
2920 }
2921 return true;
2922 }
2923
UnmapDmUserDevice(const std::string & dm_user_name)2924 bool SnapshotManager::UnmapDmUserDevice(const std::string& dm_user_name) {
2925 if (dm_.GetState(dm_user_name) == DmDeviceState::INVALID) {
2926 return true;
2927 }
2928
2929 if (!DeleteDeviceIfExists(dm_user_name)) {
2930 LOG(ERROR) << "Cannot unmap " << dm_user_name;
2931 return false;
2932 }
2933
2934 if (EnsureSnapuserdConnected()) {
2935 if (!snapuserd_client_->WaitForDeviceDelete(dm_user_name)) {
2936 LOG(ERROR) << "Failed to wait for " << dm_user_name << " control device to delete";
2937 return false;
2938 }
2939 }
2940
2941 // Ensure the control device is gone so we don't run into ABA problems.
2942 auto control_device = "/dev/dm-user/" + dm_user_name;
2943 if (!android::fs_mgr::WaitForFileDeleted(control_device, 10s)) {
2944 LOG(ERROR) << "Timed out waiting for " << control_device << " to unlink";
2945 return false;
2946 }
2947 return true;
2948 }
2949
UnmapUserspaceSnapshotDevice(LockedFile * lock,const std::string & snapshot_name)2950 bool SnapshotManager::UnmapUserspaceSnapshotDevice(LockedFile* lock,
2951 const std::string& snapshot_name) {
2952 auto dm_user_name = GetDmUserCowName(snapshot_name, GetSnapshotDriver(lock));
2953 if (dm_.GetState(dm_user_name) == DmDeviceState::INVALID) {
2954 return true;
2955 }
2956
2957 CHECK(lock);
2958
2959 SnapshotStatus snapshot_status;
2960
2961 if (!ReadSnapshotStatus(lock, snapshot_name, &snapshot_status)) {
2962 return false;
2963 }
2964 // If the merge is complete, then we switch dm tables which is equivalent
2965 // to unmap; hence, we can't be deleting the device
2966 // as the table would be mounted off partitions and will fail.
2967 if (snapshot_status.state() != SnapshotState::MERGE_COMPLETED) {
2968 if (!DeleteDeviceIfExists(dm_user_name, 4000ms)) {
2969 LOG(ERROR) << "Cannot unmap " << dm_user_name;
2970 return false;
2971 }
2972 }
2973
2974 if (EnsureSnapuserdConnected()) {
2975 if (!snapuserd_client_->WaitForDeviceDelete(dm_user_name)) {
2976 LOG(ERROR) << "Failed to wait for " << dm_user_name << " control device to delete";
2977 return false;
2978 }
2979 }
2980
2981 // Ensure the control device is gone so we don't run into ABA problems.
2982 auto control_device = "/dev/dm-user/" + dm_user_name;
2983 if (!android::fs_mgr::WaitForFileDeleted(control_device, 10s)) {
2984 LOG(ERROR) << "Timed out waiting for " << control_device << " to unlink";
2985 return false;
2986 }
2987 return true;
2988 }
2989
MapAllSnapshots(const std::chrono::milliseconds & timeout_ms)2990 bool SnapshotManager::MapAllSnapshots(const std::chrono::milliseconds& timeout_ms) {
2991 auto lock = LockExclusive();
2992 if (!lock) return false;
2993
2994 auto state = ReadUpdateState(lock.get());
2995 if (state == UpdateState::Unverified) {
2996 if (GetCurrentSlot() == Slot::Target) {
2997 LOG(ERROR) << "Cannot call MapAllSnapshots when booting from the target slot.";
2998 return false;
2999 }
3000 } else if (state != UpdateState::Initiated) {
3001 LOG(ERROR) << "Cannot call MapAllSnapshots from update state: " << state;
3002 return false;
3003 }
3004
3005 std::vector<std::string> snapshots;
3006 if (!ListSnapshots(lock.get(), &snapshots)) {
3007 return false;
3008 }
3009
3010 const auto& opener = device_->GetPartitionOpener();
3011 auto slot_suffix = device_->GetOtherSlotSuffix();
3012 auto slot_number = SlotNumberForSlotSuffix(slot_suffix);
3013 auto super_device = device_->GetSuperDevice(slot_number);
3014 auto metadata = android::fs_mgr::ReadMetadata(opener, super_device, slot_number);
3015 if (!metadata) {
3016 LOG(ERROR) << "MapAllSnapshots could not read dynamic partition metadata for device: "
3017 << super_device;
3018 return false;
3019 }
3020
3021 for (const auto& snapshot : snapshots) {
3022 if (!UnmapPartitionWithSnapshot(lock.get(), snapshot)) {
3023 LOG(ERROR) << "MapAllSnapshots could not unmap snapshot: " << snapshot;
3024 return false;
3025 }
3026
3027 CreateLogicalPartitionParams params = {
3028 .block_device = super_device,
3029 .metadata = metadata.get(),
3030 .partition_name = snapshot,
3031 .timeout_ms = timeout_ms,
3032 .partition_opener = &opener,
3033 };
3034 if (!MapPartitionWithSnapshot(lock.get(), std::move(params), SnapshotContext::Mount,
3035 nullptr)) {
3036 LOG(ERROR) << "MapAllSnapshots failed to map: " << snapshot;
3037 return false;
3038 }
3039 }
3040
3041 LOG(INFO) << "MapAllSnapshots succeeded.";
3042 return true;
3043 }
3044
UnmapAllSnapshots()3045 bool SnapshotManager::UnmapAllSnapshots() {
3046 auto lock = LockExclusive();
3047 if (!lock) return false;
3048
3049 return UnmapAllSnapshots(lock.get());
3050 }
3051
UnmapAllSnapshots(LockedFile * lock)3052 bool SnapshotManager::UnmapAllSnapshots(LockedFile* lock) {
3053 LOG(INFO) << "Lock acquired for " << __FUNCTION__;
3054 std::vector<std::string> snapshots;
3055 if (!ListSnapshots(lock, &snapshots)) {
3056 return false;
3057 }
3058 LOG(INFO) << "Found " << snapshots.size() << " partitions with snapshots";
3059
3060 for (const auto& snapshot : snapshots) {
3061 if (!UnmapPartitionWithSnapshot(lock, snapshot)) {
3062 LOG(ERROR) << "Failed to unmap snapshot: " << snapshot;
3063 return false;
3064 }
3065 }
3066 LOG(INFO) << "Unmapped " << snapshots.size() << " partitions with snapshots";
3067
3068 // Terminate the daemon and release the snapuserd_client_ object.
3069 // If we need to re-connect with the daemon, EnsureSnapuserdConnected()
3070 // will re-create the object and establish the socket connection.
3071 if (snapuserd_client_) {
3072 LOG(INFO) << "Shutdown snapuserd daemon";
3073 snapuserd_client_->DetachSnapuserd();
3074 snapuserd_client_ = nullptr;
3075 }
3076
3077 return true;
3078 }
3079
OpenFile(const std::string & file,int lock_flags)3080 auto SnapshotManager::OpenFile(const std::string& file,
3081 int lock_flags) -> std::unique_ptr<LockedFile> {
3082 const auto start = std::chrono::system_clock::now();
3083 unique_fd fd(open(file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
3084 if (fd < 0) {
3085 PLOG(ERROR) << "Open failed: " << file;
3086 return nullptr;
3087 }
3088 if (lock_flags != 0 && TEMP_FAILURE_RETRY(flock(fd, lock_flags)) < 0) {
3089 PLOG(ERROR) << "Acquire flock failed: " << file;
3090 return nullptr;
3091 }
3092 // For simplicity, we want to CHECK that lock_mode == LOCK_EX, in some
3093 // calls, so strip extra flags.
3094 int lock_mode = lock_flags & (LOCK_EX | LOCK_SH);
3095 const auto end = std::chrono::system_clock::now();
3096 const auto duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
3097 if (duration_ms >= 1000ms) {
3098 LOG(INFO) << "Taking lock on " << file << " took " << duration_ms.count() << "ms";
3099 }
3100 return std::make_unique<LockedFile>(file, std::move(fd), lock_mode);
3101 }
3102
~LockedFile()3103 SnapshotManager::LockedFile::~LockedFile() {
3104 if (TEMP_FAILURE_RETRY(flock(fd_, LOCK_UN)) < 0) {
3105 PLOG(ERROR) << "Failed to unlock file: " << path_;
3106 }
3107 }
3108
GetStateFilePath() const3109 std::string SnapshotManager::GetStateFilePath() const {
3110 return metadata_dir_ + "/state"s;
3111 }
3112
GetMergeStateFilePath() const3113 std::string SnapshotManager::GetMergeStateFilePath() const {
3114 return metadata_dir_ + "/merge_state"s;
3115 }
3116
GetLockPath() const3117 std::string SnapshotManager::GetLockPath() const {
3118 return metadata_dir_;
3119 }
3120
OpenLock(int lock_flags)3121 std::unique_ptr<SnapshotManager::LockedFile> SnapshotManager::OpenLock(int lock_flags) {
3122 auto lock_file = GetLockPath();
3123 return OpenFile(lock_file, lock_flags);
3124 }
3125
LockShared()3126 std::unique_ptr<SnapshotManager::LockedFile> SnapshotManager::LockShared() {
3127 return OpenLock(LOCK_SH);
3128 }
3129
LockExclusive()3130 std::unique_ptr<SnapshotManager::LockedFile> SnapshotManager::LockExclusive() {
3131 return OpenLock(LOCK_EX);
3132 }
3133
UpdateStateFromString(const std::string & contents)3134 static UpdateState UpdateStateFromString(const std::string& contents) {
3135 if (contents.empty() || contents == "none") {
3136 return UpdateState::None;
3137 } else if (contents == "initiated") {
3138 return UpdateState::Initiated;
3139 } else if (contents == "unverified") {
3140 return UpdateState::Unverified;
3141 } else if (contents == "merging") {
3142 return UpdateState::Merging;
3143 } else if (contents == "merge-completed") {
3144 return UpdateState::MergeCompleted;
3145 } else if (contents == "merge-needs-reboot") {
3146 return UpdateState::MergeNeedsReboot;
3147 } else if (contents == "merge-failed") {
3148 return UpdateState::MergeFailed;
3149 } else if (contents == "cancelled") {
3150 return UpdateState::Cancelled;
3151 } else {
3152 LOG(ERROR) << "Unknown merge state in update state file: \"" << contents << "\"";
3153 return UpdateState::None;
3154 }
3155 }
3156
operator <<(std::ostream & os,UpdateState state)3157 std::ostream& operator<<(std::ostream& os, UpdateState state) {
3158 switch (state) {
3159 case UpdateState::None:
3160 return os << "none";
3161 case UpdateState::Initiated:
3162 return os << "initiated";
3163 case UpdateState::Unverified:
3164 return os << "unverified";
3165 case UpdateState::Merging:
3166 return os << "merging";
3167 case UpdateState::MergeCompleted:
3168 return os << "merge-completed";
3169 case UpdateState::MergeNeedsReboot:
3170 return os << "merge-needs-reboot";
3171 case UpdateState::MergeFailed:
3172 return os << "merge-failed";
3173 case UpdateState::Cancelled:
3174 return os << "cancelled";
3175 default:
3176 LOG(ERROR) << "Unknown update state: " << static_cast<uint32_t>(state);
3177 return os;
3178 }
3179 }
3180
operator <<(std::ostream & os,MergePhase phase)3181 std::ostream& operator<<(std::ostream& os, MergePhase phase) {
3182 switch (phase) {
3183 case MergePhase::NO_MERGE:
3184 return os << "none";
3185 case MergePhase::FIRST_PHASE:
3186 return os << "first";
3187 case MergePhase::SECOND_PHASE:
3188 return os << "second";
3189 default:
3190 LOG(ERROR) << "Unknown merge phase: " << static_cast<uint32_t>(phase);
3191 return os << "unknown(" << static_cast<uint32_t>(phase) << ")";
3192 }
3193 }
3194
ReadUpdateState(LockedFile * lock)3195 UpdateState SnapshotManager::ReadUpdateState(LockedFile* lock) {
3196 SnapshotUpdateStatus status = ReadSnapshotUpdateStatus(lock);
3197 return status.state();
3198 }
3199
ReadSnapshotUpdateStatus(LockedFile * lock)3200 SnapshotUpdateStatus SnapshotManager::ReadSnapshotUpdateStatus(LockedFile* lock) {
3201 CHECK(lock);
3202
3203 SnapshotUpdateStatus status = {};
3204 std::string contents;
3205 if (!android::base::ReadFileToString(GetStateFilePath(), &contents)) {
3206 PLOG(ERROR) << "Read state file failed";
3207 status.set_state(UpdateState::None);
3208 return status;
3209 }
3210
3211 if (!status.ParseFromString(contents)) {
3212 LOG(WARNING) << "Unable to parse state file as SnapshotUpdateStatus, using the old format";
3213
3214 // Try to rollback to legacy file to support devices that are
3215 // currently using the old file format.
3216 // TODO(b/147409432)
3217 status.set_state(UpdateStateFromString(contents));
3218 }
3219
3220 return status;
3221 }
3222
WriteUpdateState(LockedFile * lock,UpdateState state,MergeFailureCode failure_code)3223 bool SnapshotManager::WriteUpdateState(LockedFile* lock, UpdateState state,
3224 MergeFailureCode failure_code) {
3225 SnapshotUpdateStatus status;
3226 status.set_state(state);
3227
3228 switch (state) {
3229 case UpdateState::MergeFailed:
3230 status.set_merge_failure_code(failure_code);
3231 break;
3232 case UpdateState::Initiated:
3233 status.set_source_build_fingerprint(
3234 android::base::GetProperty("ro.build.fingerprint", ""));
3235 break;
3236 default:
3237 break;
3238 }
3239
3240 // If we're transitioning between two valid states (eg, we're not beginning
3241 // or ending an OTA), then make sure to propagate the compression bit and
3242 // build fingerprint.
3243 if (!(state == UpdateState::Initiated || state == UpdateState::None)) {
3244 SnapshotUpdateStatus old_status = ReadSnapshotUpdateStatus(lock);
3245 status.set_using_snapuserd(old_status.using_snapuserd());
3246 status.set_source_build_fingerprint(old_status.source_build_fingerprint());
3247 status.set_merge_phase(old_status.merge_phase());
3248 status.set_userspace_snapshots(old_status.userspace_snapshots());
3249 status.set_io_uring_enabled(old_status.io_uring_enabled());
3250 status.set_legacy_snapuserd(old_status.legacy_snapuserd());
3251 status.set_o_direct(old_status.o_direct());
3252 status.set_skip_verification(old_status.skip_verification());
3253 status.set_cow_op_merge_size(old_status.cow_op_merge_size());
3254 status.set_num_worker_threads(old_status.num_worker_threads());
3255 status.set_verify_block_size(old_status.verify_block_size());
3256 status.set_num_verification_threads(old_status.num_verification_threads());
3257 }
3258 return WriteSnapshotUpdateStatus(lock, status);
3259 }
3260
WriteSnapshotUpdateStatus(LockedFile * lock,const SnapshotUpdateStatus & status)3261 bool SnapshotManager::WriteSnapshotUpdateStatus(LockedFile* lock,
3262 const SnapshotUpdateStatus& status) {
3263 CHECK(lock);
3264 CHECK(lock->lock_mode() == LOCK_EX);
3265
3266 std::string contents;
3267 if (!status.SerializeToString(&contents)) {
3268 LOG(ERROR) << "Unable to serialize SnapshotUpdateStatus.";
3269 return false;
3270 }
3271
3272 #ifdef LIBSNAPSHOT_USE_HAL
3273 auto merge_status = MergeStatus::UNKNOWN;
3274 switch (status.state()) {
3275 // The needs-reboot and completed cases imply that /data and /metadata
3276 // can be safely wiped, so we don't report a merge status.
3277 case UpdateState::None:
3278 case UpdateState::MergeNeedsReboot:
3279 case UpdateState::MergeCompleted:
3280 case UpdateState::Initiated:
3281 merge_status = MergeStatus::NONE;
3282 break;
3283 case UpdateState::Unverified:
3284 merge_status = MergeStatus::SNAPSHOTTED;
3285 break;
3286 case UpdateState::Merging:
3287 case UpdateState::MergeFailed:
3288 merge_status = MergeStatus::MERGING;
3289 break;
3290 default:
3291 // Note that Cancelled flows to here - it is never written, since
3292 // it only communicates a transient state to the caller.
3293 LOG(ERROR) << "Unexpected update status: " << status.state();
3294 break;
3295 }
3296
3297 bool set_before_write =
3298 merge_status == MergeStatus::SNAPSHOTTED || merge_status == MergeStatus::MERGING;
3299 if (set_before_write && !device_->SetBootControlMergeStatus(merge_status)) {
3300 return false;
3301 }
3302 #endif
3303
3304 if (!WriteStringToFileAtomic(contents, GetStateFilePath())) {
3305 PLOG(ERROR) << "Could not write to state file";
3306 return false;
3307 }
3308
3309 #ifdef LIBSNAPSHOT_USE_HAL
3310 if (!set_before_write && !device_->SetBootControlMergeStatus(merge_status)) {
3311 return false;
3312 }
3313 #endif
3314 return true;
3315 }
3316
GetSnapshotStatusFilePath(const std::string & name)3317 std::string SnapshotManager::GetSnapshotStatusFilePath(const std::string& name) {
3318 auto file = metadata_dir_ + "/snapshots/"s + name;
3319 return file;
3320 }
3321
ReadSnapshotStatus(LockedFile * lock,const std::string & name,SnapshotStatus * status)3322 bool SnapshotManager::ReadSnapshotStatus(LockedFile* lock, const std::string& name,
3323 SnapshotStatus* status) {
3324 CHECK(lock);
3325 auto path = GetSnapshotStatusFilePath(name);
3326
3327 unique_fd fd(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
3328 if (fd < 0) {
3329 PLOG(ERROR) << "Open failed: " << path;
3330 return false;
3331 }
3332
3333 if (!status->ParseFromFileDescriptor(fd.get())) {
3334 PLOG(ERROR) << "Unable to parse " << path << " as SnapshotStatus";
3335 return false;
3336 }
3337
3338 if (status->name() != name) {
3339 LOG(WARNING) << "Found snapshot status named " << status->name() << " in " << path;
3340 status->set_name(name);
3341 }
3342
3343 return true;
3344 }
3345
WriteSnapshotStatus(LockedFile * lock,const SnapshotStatus & status)3346 bool SnapshotManager::WriteSnapshotStatus(LockedFile* lock, const SnapshotStatus& status) {
3347 // The caller must take an exclusive lock to modify snapshots.
3348 CHECK(lock);
3349 CHECK(lock->lock_mode() == LOCK_EX);
3350 CHECK(!status.name().empty());
3351
3352 auto path = GetSnapshotStatusFilePath(status.name());
3353
3354 std::string content;
3355 if (!status.SerializeToString(&content)) {
3356 LOG(ERROR) << "Unable to serialize SnapshotStatus for " << status.name();
3357 return false;
3358 }
3359
3360 if (!WriteStringToFileAtomic(content, path)) {
3361 PLOG(ERROR) << "Unable to write SnapshotStatus to " << path;
3362 return false;
3363 }
3364
3365 return true;
3366 }
3367
EnsureImageManager()3368 bool SnapshotManager::EnsureImageManager() {
3369 if (images_) return true;
3370
3371 images_ = device_->OpenImageManager();
3372 if (!images_) {
3373 LOG(ERROR) << "Could not open ImageManager";
3374 return false;
3375 }
3376 return true;
3377 }
3378
EnsureSnapuserdConnected(std::chrono::milliseconds timeout_ms)3379 bool SnapshotManager::EnsureSnapuserdConnected(std::chrono::milliseconds timeout_ms) {
3380 if (snapuserd_client_) {
3381 return true;
3382 }
3383
3384 if (!use_first_stage_snapuserd_ && !EnsureSnapuserdStarted()) {
3385 return false;
3386 }
3387
3388 snapuserd_client_ = SnapuserdClient::Connect(kSnapuserdSocket, timeout_ms);
3389 if (!snapuserd_client_) {
3390 LOG(ERROR) << "Unable to connect to snapuserd";
3391 return false;
3392 }
3393 return true;
3394 }
3395
UnmapAndDeleteCowPartition(MetadataBuilder * current_metadata)3396 void SnapshotManager::UnmapAndDeleteCowPartition(MetadataBuilder* current_metadata) {
3397 std::vector<std::string> to_delete;
3398 for (auto* existing_cow_partition : current_metadata->ListPartitionsInGroup(kCowGroupName)) {
3399 if (!DeleteDeviceIfExists(existing_cow_partition->name())) {
3400 LOG(WARNING) << existing_cow_partition->name()
3401 << " cannot be unmapped and its space cannot be reclaimed";
3402 continue;
3403 }
3404 to_delete.push_back(existing_cow_partition->name());
3405 }
3406 for (const auto& name : to_delete) {
3407 current_metadata->RemovePartition(name);
3408 }
3409 }
3410
AddRequiredSpace(Return orig,const std::map<std::string,SnapshotStatus> & all_snapshot_status)3411 static Return AddRequiredSpace(Return orig,
3412 const std::map<std::string, SnapshotStatus>& all_snapshot_status) {
3413 if (orig.error_code() != Return::ErrorCode::NO_SPACE) {
3414 return orig;
3415 }
3416 uint64_t sum = 0;
3417 for (auto&& [name, status] : all_snapshot_status) {
3418 sum += status.cow_file_size();
3419 }
3420 LOG(INFO) << "Calculated needed COW space: " << sum << " bytes";
3421 return Return::NoSpace(sum);
3422 }
3423
CreateUpdateSnapshots(const DeltaArchiveManifest & manifest)3424 Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manifest) {
3425 auto lock = LockExclusive();
3426 if (!lock) return Return::Error();
3427
3428 auto update_state = ReadUpdateState(lock.get());
3429 if (update_state != UpdateState::Initiated) {
3430 LOG(ERROR) << "Cannot create update snapshots in state " << update_state;
3431 return Return::Error();
3432 }
3433
3434 // TODO(b/134949511): remove this check. Right now, with overlayfs mounted, the scratch
3435 // partition takes up a big chunk of space in super, causing COW images to be created on
3436 // retrofit Virtual A/B devices.
3437 if (device_->IsOverlayfsSetup()) {
3438 LOG(ERROR) << "Cannot create update snapshots with overlayfs setup. Run `adb enable-verity`"
3439 << ", reboot, then try again.";
3440 return Return::Error();
3441 }
3442
3443 const auto& opener = device_->GetPartitionOpener();
3444 auto current_suffix = device_->GetSlotSuffix();
3445 uint32_t current_slot = SlotNumberForSlotSuffix(current_suffix);
3446 auto target_suffix = device_->GetOtherSlotSuffix();
3447 uint32_t target_slot = SlotNumberForSlotSuffix(target_suffix);
3448 auto current_super = device_->GetSuperDevice(current_slot);
3449
3450 auto current_metadata = MetadataBuilder::New(opener, current_super, current_slot);
3451 if (current_metadata == nullptr) {
3452 LOG(ERROR) << "Cannot create metadata builder.";
3453 return Return::Error();
3454 }
3455
3456 auto target_metadata =
3457 MetadataBuilder::NewForUpdate(opener, current_super, current_slot, target_slot);
3458 if (target_metadata == nullptr) {
3459 LOG(ERROR) << "Cannot create target metadata builder.";
3460 return Return::Error();
3461 }
3462
3463 // Delete partitions with target suffix in |current_metadata|. Otherwise,
3464 // partition_cow_creator recognizes these left-over partitions as used space.
3465 for (const auto& group_name : current_metadata->ListGroups()) {
3466 if (android::base::EndsWith(group_name, target_suffix)) {
3467 current_metadata->RemoveGroupAndPartitions(group_name);
3468 }
3469 }
3470
3471 SnapshotMetadataUpdater metadata_updater(target_metadata.get(), target_slot, manifest);
3472 if (!metadata_updater.Update()) {
3473 LOG(ERROR) << "Cannot calculate new metadata.";
3474 return Return::Error();
3475 }
3476
3477 // Delete previous COW partitions in current_metadata so that PartitionCowCreator marks those as
3478 // free regions.
3479 UnmapAndDeleteCowPartition(current_metadata.get());
3480
3481 // Check that all these metadata is not retrofit dynamic partitions. Snapshots on
3482 // devices with retrofit dynamic partitions does not make sense.
3483 // This ensures that current_metadata->GetFreeRegions() uses the same device
3484 // indices as target_metadata (i.e. 0 -> "super").
3485 // This is also assumed in MapCowDevices() call below.
3486 CHECK(current_metadata->GetBlockDevicePartitionName(0) == LP_METADATA_DEFAULT_PARTITION_NAME &&
3487 target_metadata->GetBlockDevicePartitionName(0) == LP_METADATA_DEFAULT_PARTITION_NAME);
3488
3489 const auto& dap_metadata = manifest.dynamic_partition_metadata();
3490
3491 std::string vabc_disable_reason;
3492 if (!dap_metadata.vabc_enabled()) {
3493 vabc_disable_reason = "not enabled metadata";
3494 } else if (device_->IsRecovery()) {
3495 vabc_disable_reason = "recovery";
3496 } else if (!KernelSupportsCompressedSnapshots()) {
3497 vabc_disable_reason = "kernel missing userspace block device support";
3498 }
3499
3500 // Deduce supported features.
3501 bool userspace_snapshots = CanUseUserspaceSnapshots();
3502 bool legacy_compression = GetLegacyCompressionEnabledProperty();
3503 bool is_legacy_snapuserd = IsVendorFromAndroid12();
3504
3505 if (!vabc_disable_reason.empty()) {
3506 if (userspace_snapshots) {
3507 LOG(INFO) << "Userspace snapshots disabled: " << vabc_disable_reason;
3508 }
3509 if (legacy_compression) {
3510 LOG(INFO) << "Compression disabled: " << vabc_disable_reason;
3511 }
3512 userspace_snapshots = false;
3513 legacy_compression = false;
3514 is_legacy_snapuserd = false;
3515 }
3516
3517 if (legacy_compression || userspace_snapshots) {
3518 if (dap_metadata.cow_version() < kMinCowVersion ||
3519 dap_metadata.cow_version() > kMaxCowVersion) {
3520 LOG(ERROR) << "Manifest cow version is out of bounds (got: "
3521 << dap_metadata.cow_version() << ", min: " << kMinCowVersion
3522 << ", max: " << kMaxCowVersion << ")";
3523 return Return::Error();
3524 }
3525 }
3526
3527 if (!userspace_snapshots && is_legacy_snapuserd && legacy_compression) {
3528 userspace_snapshots = true;
3529 LOG(INFO) << "Vendor from Android 12. Enabling userspace snapshot for OTA install";
3530 }
3531
3532 const bool using_snapuserd = userspace_snapshots || legacy_compression;
3533 if (!using_snapuserd) {
3534 LOG(INFO) << "Using legacy Virtual A/B (dm-snapshot)";
3535 }
3536
3537 std::string compression_algorithm;
3538 uint64_t compression_factor{};
3539 if (using_snapuserd) {
3540 compression_algorithm = dap_metadata.vabc_compression_param();
3541 compression_factor = dap_metadata.compression_factor();
3542 if (compression_algorithm.empty()) {
3543 // Older OTAs don't set an explicit compression type, so default to gz.
3544 compression_algorithm = "gz";
3545 }
3546 LOG(INFO) << "using compression algorithm: " << compression_algorithm
3547 << ", max compressible block size: " << compression_factor;
3548 }
3549 auto read_ahead_size =
3550 android::base::GetUintProperty<uint>("ro.virtual_ab.read_ahead_size", kReadAheadSizeKb);
3551 PartitionCowCreator cow_creator{
3552 .target_metadata = target_metadata.get(),
3553 .target_suffix = target_suffix,
3554 .target_partition = nullptr,
3555 .current_metadata = current_metadata.get(),
3556 .current_suffix = current_suffix,
3557 .update = nullptr,
3558 .extra_extents = {},
3559 .using_snapuserd = using_snapuserd,
3560 .compression_algorithm = compression_algorithm,
3561 .compression_factor = compression_factor,
3562 .read_ahead_size = read_ahead_size,
3563 };
3564
3565 if (dap_metadata.vabc_feature_set().has_threaded()) {
3566 cow_creator.enable_threading = dap_metadata.vabc_feature_set().threaded();
3567 }
3568 if (dap_metadata.vabc_feature_set().has_batch_writes()) {
3569 cow_creator.batched_writes = dap_metadata.vabc_feature_set().batch_writes();
3570 }
3571
3572 // In case of error, automatically delete devices that are created along the way.
3573 // Note that "lock" is destroyed after "created_devices", so it is safe to use |lock| for
3574 // these devices.
3575 AutoDeviceList created_devices;
3576 std::map<std::string, SnapshotStatus> all_snapshot_status;
3577 auto ret = CreateUpdateSnapshotsInternal(lock.get(), manifest, &cow_creator, &created_devices,
3578 &all_snapshot_status);
3579 if (!ret.is_ok()) {
3580 LOG(ERROR) << "CreateUpdateSnapshotsInternal failed: " << ret.string();
3581 return ret;
3582 }
3583
3584 auto exported_target_metadata = target_metadata->Export();
3585 if (exported_target_metadata == nullptr) {
3586 LOG(ERROR) << "Cannot export target metadata";
3587 return Return::Error();
3588 }
3589
3590 ret = InitializeUpdateSnapshots(lock.get(), dap_metadata.cow_version(), target_metadata.get(),
3591 exported_target_metadata.get(), target_suffix,
3592 all_snapshot_status);
3593 if (!ret.is_ok()) return ret;
3594
3595 if (!UpdatePartitionTable(opener, device_->GetSuperDevice(target_slot),
3596 *exported_target_metadata, target_slot)) {
3597 LOG(ERROR) << "Cannot write target metadata";
3598 return Return::Error();
3599 }
3600
3601 // If snapuserd is enabled, we need to retain a copy of the old metadata
3602 // so we can access original blocks in case they are moved around. We do
3603 // not want to rely on the old super metadata slot because we don't
3604 // guarantee its validity after the slot switch is successful.
3605 if (using_snapuserd) {
3606 auto metadata = current_metadata->Export();
3607 if (!metadata) {
3608 LOG(ERROR) << "Could not export current metadata";
3609 return Return::Error();
3610 }
3611
3612 auto path = GetOldPartitionMetadataPath();
3613 if (!android::fs_mgr::WriteToImageFile(path, *metadata.get())) {
3614 LOG(ERROR) << "Cannot write old metadata to " << path;
3615 return Return::Error();
3616 }
3617 }
3618
3619 SnapshotUpdateStatus status = ReadSnapshotUpdateStatus(lock.get());
3620 status.set_state(update_state);
3621 status.set_using_snapuserd(using_snapuserd);
3622
3623 if (userspace_snapshots) {
3624 status.set_userspace_snapshots(true);
3625 LOG(INFO) << "Virtual A/B using userspace snapshots";
3626
3627 if (GetIouringEnabledProperty()) {
3628 status.set_io_uring_enabled(true);
3629 LOG(INFO) << "io_uring for snapshots enabled";
3630 }
3631 if (GetODirectEnabledProperty()) {
3632 status.set_o_direct(true);
3633 LOG(INFO) << "o_direct for source image enabled";
3634 }
3635 if (GetSkipVerificationProperty()) {
3636 status.set_skip_verification(true);
3637 LOG(INFO) << "skipping verification of images";
3638 }
3639 if (is_legacy_snapuserd) {
3640 status.set_legacy_snapuserd(true);
3641 LOG(INFO) << "Setting legacy_snapuserd to true";
3642 }
3643 status.set_cow_op_merge_size(
3644 android::base::GetUintProperty<uint32_t>("ro.virtual_ab.cow_op_merge_size", 0));
3645 status.set_num_worker_threads(
3646 android::base::GetUintProperty<uint32_t>("ro.virtual_ab.num_worker_threads", 0));
3647 status.set_verify_block_size(
3648 android::base::GetUintProperty<uint32_t>("ro.virtual_ab.verify_block_size", 0));
3649 status.set_num_verification_threads(
3650 android::base::GetUintProperty<uint32_t>("ro.virtual_ab.num_verify_threads", 0));
3651 } else if (legacy_compression) {
3652 LOG(INFO) << "Virtual A/B using legacy snapuserd";
3653 } else {
3654 LOG(INFO) << "Virtual A/B using dm-snapshot";
3655 }
3656
3657 is_snapshot_userspace_.emplace(userspace_snapshots);
3658 is_legacy_snapuserd_.emplace(is_legacy_snapuserd);
3659
3660 if (!device()->IsTestDevice() && using_snapuserd) {
3661 // Terminate stale daemon if any
3662 std::unique_ptr<SnapuserdClient> snapuserd_client = std::move(snapuserd_client_);
3663 if (!snapuserd_client) {
3664 snapuserd_client = SnapuserdClient::TryConnect(kSnapuserdSocket, 5s);
3665 }
3666 if (snapuserd_client) {
3667 snapuserd_client->DetachSnapuserd();
3668 snapuserd_client = nullptr;
3669 }
3670 }
3671
3672 if (!WriteSnapshotUpdateStatus(lock.get(), status)) {
3673 LOG(ERROR) << "Unable to write new update state";
3674 return Return::Error();
3675 }
3676
3677 created_devices.Release();
3678 LOG(INFO) << "Successfully created all snapshots for target slot " << target_suffix;
3679
3680 return Return::Ok();
3681 }
3682
CreateUpdateSnapshotsInternal(LockedFile * lock,const DeltaArchiveManifest & manifest,PartitionCowCreator * cow_creator,AutoDeviceList * created_devices,std::map<std::string,SnapshotStatus> * all_snapshot_status)3683 Return SnapshotManager::CreateUpdateSnapshotsInternal(
3684 LockedFile* lock, const DeltaArchiveManifest& manifest, PartitionCowCreator* cow_creator,
3685 AutoDeviceList* created_devices,
3686 std::map<std::string, SnapshotStatus>* all_snapshot_status) {
3687 CHECK(lock);
3688
3689 auto* target_metadata = cow_creator->target_metadata;
3690 const auto& target_suffix = cow_creator->target_suffix;
3691
3692 if (!target_metadata->AddGroup(kCowGroupName, 0)) {
3693 LOG(ERROR) << "Cannot add group " << kCowGroupName;
3694 return Return::Error();
3695 }
3696
3697 std::map<std::string, const PartitionUpdate*> partition_map;
3698 std::map<std::string, std::vector<Extent>> extra_extents_map;
3699 for (const auto& partition_update : manifest.partitions()) {
3700 auto suffixed_name = partition_update.partition_name() + target_suffix;
3701 auto&& [it, inserted] = partition_map.emplace(suffixed_name, &partition_update);
3702 if (!inserted) {
3703 LOG(ERROR) << "Duplicated partition " << partition_update.partition_name()
3704 << " in update manifest.";
3705 return Return::Error();
3706 }
3707
3708 auto& extra_extents = extra_extents_map[suffixed_name];
3709 if (partition_update.has_hash_tree_extent()) {
3710 extra_extents.push_back(partition_update.hash_tree_extent());
3711 }
3712 if (partition_update.has_fec_extent()) {
3713 extra_extents.push_back(partition_update.fec_extent());
3714 }
3715 }
3716
3717 for (auto* target_partition : ListPartitionsWithSuffix(target_metadata, target_suffix)) {
3718 cow_creator->target_partition = target_partition;
3719 cow_creator->update = nullptr;
3720 auto iter = partition_map.find(target_partition->name());
3721 if (iter != partition_map.end()) {
3722 cow_creator->update = iter->second;
3723 } else {
3724 LOG(INFO) << target_partition->name()
3725 << " isn't included in the payload, skipping the cow creation.";
3726 continue;
3727 }
3728
3729 cow_creator->extra_extents.clear();
3730 auto extra_extents_it = extra_extents_map.find(target_partition->name());
3731 if (extra_extents_it != extra_extents_map.end()) {
3732 cow_creator->extra_extents = std::move(extra_extents_it->second);
3733 }
3734
3735 // Compute the device sizes for the partition.
3736 auto cow_creator_ret = cow_creator->Run();
3737 if (!cow_creator_ret.has_value()) {
3738 LOG(ERROR) << "PartitionCowCreator returned no value for " << target_partition->name();
3739 return Return::Error();
3740 }
3741
3742 LOG(INFO) << "For partition " << target_partition->name()
3743 << ", device size = " << cow_creator_ret->snapshot_status.device_size()
3744 << ", snapshot size = " << cow_creator_ret->snapshot_status.snapshot_size()
3745 << ", cow partition size = "
3746 << cow_creator_ret->snapshot_status.cow_partition_size()
3747 << ", cow file size = " << cow_creator_ret->snapshot_status.cow_file_size();
3748
3749 // Delete any existing snapshot before re-creating one.
3750 if (!DeleteSnapshot(lock, target_partition->name())) {
3751 LOG(ERROR) << "Cannot delete existing snapshot before creating a new one for partition "
3752 << target_partition->name();
3753 return Return::Error();
3754 }
3755
3756 // It is possible that the whole partition uses free space in super, and snapshot / COW
3757 // would not be needed. In this case, skip the partition.
3758 bool needs_snapshot = cow_creator_ret->snapshot_status.snapshot_size() > 0;
3759 bool needs_cow = (cow_creator_ret->snapshot_status.cow_partition_size() +
3760 cow_creator_ret->snapshot_status.cow_file_size()) > 0;
3761 CHECK(needs_snapshot == needs_cow);
3762
3763 if (!needs_snapshot) {
3764 LOG(INFO) << "Skip creating snapshot for partition " << target_partition->name()
3765 << "because nothing needs to be snapshotted.";
3766 continue;
3767 }
3768
3769 // Find the original partition size.
3770 auto name = target_partition->name();
3771 auto old_partition_name =
3772 name.substr(0, name.size() - target_suffix.size()) + cow_creator->current_suffix;
3773 auto old_partition = cow_creator->current_metadata->FindPartition(old_partition_name);
3774 if (old_partition) {
3775 cow_creator_ret->snapshot_status.set_old_partition_size(old_partition->size());
3776 }
3777
3778 // Store these device sizes to snapshot status file.
3779 if (!CreateSnapshot(lock, cow_creator, &cow_creator_ret->snapshot_status)) {
3780 return Return::Error();
3781 }
3782 created_devices->EmplaceBack<AutoDeleteSnapshot>(this, lock, target_partition->name());
3783
3784 // Create the COW partition. That is, use any remaining free space in super partition before
3785 // creating the COW images.
3786 if (cow_creator_ret->snapshot_status.cow_partition_size() > 0) {
3787 CHECK(cow_creator_ret->snapshot_status.cow_partition_size() % kSectorSize == 0)
3788 << "cow_partition_size == "
3789 << cow_creator_ret->snapshot_status.cow_partition_size()
3790 << " is not a multiple of sector size " << kSectorSize;
3791 auto cow_partition = target_metadata->AddPartition(GetCowName(target_partition->name()),
3792 kCowGroupName, 0 /* flags */);
3793 if (cow_partition == nullptr) {
3794 return Return::Error();
3795 }
3796
3797 if (!target_metadata->ResizePartition(
3798 cow_partition, cow_creator_ret->snapshot_status.cow_partition_size(),
3799 cow_creator_ret->cow_partition_usable_regions)) {
3800 LOG(ERROR) << "Cannot create COW partition on metadata with size "
3801 << cow_creator_ret->snapshot_status.cow_partition_size();
3802 return Return::Error();
3803 }
3804 // Only the in-memory target_metadata is modified; nothing to clean up if there is an
3805 // error in the future.
3806 }
3807
3808 all_snapshot_status->emplace(target_partition->name(),
3809 std::move(cow_creator_ret->snapshot_status));
3810
3811 LOG(INFO) << "Successfully created snapshot partition for " << target_partition->name();
3812 }
3813
3814 LOG(INFO) << "Allocating CoW images.";
3815
3816 for (auto&& [name, snapshot_status] : *all_snapshot_status) {
3817 // Create the backing COW image if necessary.
3818 if (snapshot_status.cow_file_size() > 0) {
3819 auto ret = CreateCowImage(lock, name);
3820 if (!ret.is_ok()) {
3821 LOG(ERROR) << "CreateCowImage failed: " << ret.string();
3822 return AddRequiredSpace(ret, *all_snapshot_status);
3823 }
3824 }
3825
3826 LOG(INFO) << "Successfully created snapshot for " << name;
3827 }
3828
3829 return Return::Ok();
3830 }
3831
InitializeUpdateSnapshots(LockedFile * lock,uint32_t cow_version,MetadataBuilder * target_metadata,const LpMetadata * exported_target_metadata,const std::string & target_suffix,const std::map<std::string,SnapshotStatus> & all_snapshot_status)3832 Return SnapshotManager::InitializeUpdateSnapshots(
3833 LockedFile* lock, uint32_t cow_version, MetadataBuilder* target_metadata,
3834 const LpMetadata* exported_target_metadata, const std::string& target_suffix,
3835 const std::map<std::string, SnapshotStatus>& all_snapshot_status) {
3836 CHECK(lock);
3837
3838 CreateLogicalPartitionParams cow_params{
3839 .block_device = LP_METADATA_DEFAULT_PARTITION_NAME,
3840 .metadata = exported_target_metadata,
3841 .timeout_ms = std::chrono::milliseconds::max(),
3842 .partition_opener = &device_->GetPartitionOpener(),
3843 };
3844 for (auto* target_partition : ListPartitionsWithSuffix(target_metadata, target_suffix)) {
3845 AutoDeviceList created_devices_for_cow;
3846
3847 if (!UnmapPartitionWithSnapshot(lock, target_partition->name())) {
3848 LOG(ERROR) << "Cannot unmap existing COW devices before re-mapping them for zero-fill: "
3849 << target_partition->name();
3850 return Return::Error();
3851 }
3852
3853 auto it = all_snapshot_status.find(target_partition->name());
3854 if (it == all_snapshot_status.end()) continue;
3855 cow_params.partition_name = target_partition->name();
3856 std::string cow_name;
3857 if (!MapCowDevices(lock, cow_params, it->second, &created_devices_for_cow, &cow_name)) {
3858 return Return::Error();
3859 }
3860
3861 std::string cow_path;
3862 if (!images_->GetMappedImageDevice(cow_name, &cow_path)) {
3863 LOG(ERROR) << "Cannot determine path for " << cow_name;
3864 return Return::Error();
3865 }
3866
3867 if (!android::fs_mgr::WaitForFile(cow_path, 6s)) {
3868 LOG(ERROR) << "Timed out waiting for device to appear: " << cow_path;
3869 return Return::Error();
3870 }
3871
3872 if (it->second.using_snapuserd()) {
3873 unique_fd fd(open(cow_path.c_str(), O_RDWR | O_CLOEXEC));
3874 if (fd < 0) {
3875 PLOG(ERROR) << "open " << cow_path << " failed for snapshot "
3876 << cow_params.partition_name;
3877 return Return::Error();
3878 }
3879
3880 CowOptions options;
3881 if (device()->IsTestDevice()) {
3882 options.scratch_space = false;
3883 }
3884 options.compression = it->second.compression_algorithm();
3885 if (cow_version >= 3) {
3886 options.op_count_max = it->second.estimated_ops_buffer_size();
3887 options.max_blocks = {it->second.device_size() / options.block_size};
3888 }
3889
3890 auto writer = CreateCowWriter(cow_version, options, std::move(fd));
3891 if (!writer->Finalize()) {
3892 LOG(ERROR) << "Could not initialize COW device for " << target_partition->name();
3893 return Return::Error();
3894 }
3895 } else {
3896 auto ret = InitializeKernelCow(cow_path);
3897 if (!ret.is_ok()) {
3898 LOG(ERROR) << "Can't zero-fill COW device for " << target_partition->name() << ": "
3899 << cow_path;
3900 return AddRequiredSpace(ret, all_snapshot_status);
3901 }
3902 }
3903 // Let destructor of created_devices_for_cow to unmap the COW devices.
3904 };
3905 return Return::Ok();
3906 }
3907
MapUpdateSnapshot(const CreateLogicalPartitionParams & params,std::string * snapshot_path)3908 bool SnapshotManager::MapUpdateSnapshot(const CreateLogicalPartitionParams& params,
3909 std::string* snapshot_path) {
3910 auto lock = LockShared();
3911 if (!lock) return false;
3912 if (!UnmapPartitionWithSnapshot(lock.get(), params.GetPartitionName())) {
3913 LOG(ERROR) << "Cannot unmap existing snapshot before re-mapping it: "
3914 << params.GetPartitionName();
3915 return false;
3916 }
3917
3918 SnapshotStatus status;
3919 if (!ReadSnapshotStatus(lock.get(), params.GetPartitionName(), &status)) {
3920 return false;
3921 }
3922 if (status.using_snapuserd()) {
3923 LOG(ERROR) << "Cannot use MapUpdateSnapshot with snapuserd";
3924 return false;
3925 }
3926
3927 SnapshotPaths paths;
3928 if (!MapPartitionWithSnapshot(lock.get(), params, SnapshotContext::Update, &paths)) {
3929 return false;
3930 }
3931
3932 if (!paths.snapshot_device.empty()) {
3933 *snapshot_path = paths.snapshot_device;
3934 } else {
3935 *snapshot_path = paths.target_device;
3936 }
3937 DCHECK(!snapshot_path->empty());
3938 return true;
3939 }
3940
OpenSnapshotWriter(const android::fs_mgr::CreateLogicalPartitionParams & params,std::optional<uint64_t> label)3941 std::unique_ptr<ICowWriter> SnapshotManager::OpenSnapshotWriter(
3942 const android::fs_mgr::CreateLogicalPartitionParams& params,
3943 std::optional<uint64_t> label) {
3944 #if defined(LIBSNAPSHOT_NO_COW_WRITE)
3945 (void)params;
3946 (void)label;
3947
3948 LOG(ERROR) << "Snapshots cannot be written in first-stage init or recovery";
3949 return nullptr;
3950 #else
3951 // First unmap any existing mapping.
3952 auto lock = LockShared();
3953 if (!lock) return nullptr;
3954 if (!UnmapPartitionWithSnapshot(lock.get(), params.GetPartitionName())) {
3955 LOG(ERROR) << "Cannot unmap existing snapshot before re-mapping it: "
3956 << params.GetPartitionName();
3957 return nullptr;
3958 }
3959
3960 SnapshotPaths paths;
3961 if (!MapPartitionWithSnapshot(lock.get(), params, SnapshotContext::Update, &paths)) {
3962 return nullptr;
3963 }
3964
3965 SnapshotStatus status;
3966 if (!paths.cow_device_name.empty()) {
3967 if (!ReadSnapshotStatus(lock.get(), params.GetPartitionName(), &status)) {
3968 return nullptr;
3969 }
3970 } else {
3971 // Currently, partition_cow_creator always creates snapshots. The
3972 // reason is that if partition X shrinks while partition Y grows, we
3973 // cannot bindly write to the newly freed extents in X. This would
3974 // make the old slot unusable. So, the entire size of the target
3975 // partition is currently considered snapshottable.
3976 LOG(ERROR) << "No snapshot available for partition " << params.GetPartitionName();
3977 return nullptr;
3978 }
3979
3980 if (!status.using_snapuserd()) {
3981 LOG(ERROR) << "Can only create snapshot writers with userspace or compressed snapshots";
3982 return nullptr;
3983 }
3984
3985 return OpenCompressedSnapshotWriter(lock.get(), status, paths, label);
3986 #endif
3987 }
3988
3989 #if !defined(LIBSNAPSHOT_NO_COW_WRITE)
OpenCompressedSnapshotWriter(LockedFile * lock,const SnapshotStatus & status,const SnapshotPaths & paths,std::optional<uint64_t> label)3990 std::unique_ptr<ICowWriter> SnapshotManager::OpenCompressedSnapshotWriter(
3991 LockedFile* lock, const SnapshotStatus& status, const SnapshotPaths& paths,
3992 std::optional<uint64_t> label) {
3993 CHECK(lock);
3994
3995 CowOptions cow_options;
3996 cow_options.compression = status.compression_algorithm();
3997 cow_options.max_blocks = {status.device_size() / cow_options.block_size};
3998 cow_options.batch_write = status.batched_writes();
3999 cow_options.num_compress_threads = status.enable_threading() ? 2 : 1;
4000 cow_options.op_count_max = status.estimated_ops_buffer_size();
4001 cow_options.compression_factor = status.compression_factor();
4002 // Disable scratch space for vts tests
4003 if (device()->IsTestDevice()) {
4004 cow_options.scratch_space = false;
4005 }
4006
4007 // Currently we don't support partial snapshots, since partition_cow_creator
4008 // never creates this scenario.
4009 CHECK(status.snapshot_size() == status.device_size());
4010
4011 std::string cow_path;
4012 if (!GetMappedImageDevicePath(paths.cow_device_name, &cow_path)) {
4013 LOG(ERROR) << "Could not determine path for " << paths.cow_device_name;
4014 return nullptr;
4015 }
4016
4017 unique_fd cow_fd(open(cow_path.c_str(), O_RDWR | O_CLOEXEC));
4018 if (cow_fd < 0) {
4019 PLOG(ERROR) << "OpenCompressedSnapshotWriter: open " << cow_path;
4020 return nullptr;
4021 }
4022
4023 CowHeaderV3 header;
4024 if (!ReadCowHeader(cow_fd, &header)) {
4025 LOG(ERROR) << "OpenCompressedSnapshotWriter: read header failed";
4026 return nullptr;
4027 }
4028
4029 return CreateCowWriter(header.prefix.major_version, cow_options, std::move(cow_fd), label);
4030 }
4031 #endif // !defined(LIBSNAPSHOT_NO_COW_WRITE)
4032
UnmapUpdateSnapshot(const std::string & target_partition_name)4033 bool SnapshotManager::UnmapUpdateSnapshot(const std::string& target_partition_name) {
4034 auto lock = LockShared();
4035 if (!lock) return false;
4036 return UnmapPartitionWithSnapshot(lock.get(), target_partition_name);
4037 }
4038
UnmapAllPartitionsInRecovery()4039 bool SnapshotManager::UnmapAllPartitionsInRecovery() {
4040 auto lock = LockExclusive();
4041 if (!lock) return false;
4042
4043 const auto& opener = device_->GetPartitionOpener();
4044 uint32_t slot = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
4045 auto super_device = device_->GetSuperDevice(slot);
4046 auto metadata = android::fs_mgr::ReadMetadata(opener, super_device, slot);
4047 if (!metadata) {
4048 LOG(ERROR) << "Could not read dynamic partition metadata for device: " << super_device;
4049 return false;
4050 }
4051
4052 bool ok = true;
4053 for (const auto& partition : metadata->partitions) {
4054 auto partition_name = GetPartitionName(partition);
4055 ok &= UnmapPartitionWithSnapshot(lock.get(), partition_name);
4056 }
4057 return ok;
4058 }
4059
operator <<(std::ostream & os,SnapshotManager::Slot slot)4060 std::ostream& operator<<(std::ostream& os, SnapshotManager::Slot slot) {
4061 switch (slot) {
4062 case SnapshotManager::Slot::Unknown:
4063 return os << "unknown";
4064 case SnapshotManager::Slot::Source:
4065 return os << "source";
4066 case SnapshotManager::Slot::Target:
4067 return os << "target";
4068 }
4069 }
4070
Dump(std::ostream & os)4071 bool SnapshotManager::Dump(std::ostream& os) {
4072 // Don't actually lock. Dump() is for debugging purposes only, so it is okay
4073 // if it is racy.
4074 auto file = OpenLock(0 /* lock flag */);
4075 if (!file) return false;
4076
4077 std::stringstream ss;
4078
4079 auto update_status = ReadSnapshotUpdateStatus(file.get());
4080
4081 ss << "Update state: " << update_status.state() << std::endl;
4082 ss << "Using snapuserd: " << update_status.using_snapuserd() << std::endl;
4083 ss << "Using userspace snapshots: " << update_status.userspace_snapshots() << std::endl;
4084 ss << "Using io_uring: " << update_status.io_uring_enabled() << std::endl;
4085 ss << "Using o_direct: " << update_status.o_direct() << std::endl;
4086 ss << "Using skip_verification: " << update_status.skip_verification() << std::endl;
4087 ss << "Cow op merge size (0 for uncapped): " << update_status.cow_op_merge_size() << std::endl;
4088 ss << "Worker thread count: " << update_status.num_worker_threads() << std::endl;
4089 ss << "Num verification threads: " << update_status.num_verification_threads() << std::endl;
4090 ss << "Verify block size: " << update_status.verify_block_size() << std::endl;
4091 ss << "Using XOR compression: " << GetXorCompressionEnabledProperty() << std::endl;
4092 ss << "Current slot: " << device_->GetSlotSuffix() << std::endl;
4093 ss << "Boot indicator: booting from " << GetCurrentSlot() << " slot" << std::endl;
4094 ss << "Rollback indicator: "
4095 << (access(GetRollbackIndicatorPath().c_str(), F_OK) == 0 ? "exists" : strerror(errno))
4096 << std::endl;
4097 ss << "Forward merge indicator: "
4098 << (access(GetForwardMergeIndicatorPath().c_str(), F_OK) == 0 ? "exists" : strerror(errno))
4099 << std::endl;
4100 ss << "Source build fingerprint: " << update_status.source_build_fingerprint() << std::endl;
4101
4102 if (update_status.state() == UpdateState::Merging) {
4103 ss << "Merge completion: ";
4104 if (!EnsureSnapuserdConnected()) {
4105 ss << "N/A";
4106 } else {
4107 ss << snapuserd_client_->GetMergePercent() << "%";
4108 }
4109 ss << std::endl;
4110 ss << "Merge phase: " << update_status.merge_phase() << std::endl;
4111 }
4112
4113 bool ok = true;
4114 std::vector<std::string> snapshots;
4115 if (!ListSnapshots(file.get(), &snapshots)) {
4116 LOG(ERROR) << "Could not list snapshots";
4117 snapshots.clear();
4118 ok = false;
4119 }
4120 for (const auto& name : snapshots) {
4121 ss << "Snapshot: " << name << std::endl;
4122 SnapshotStatus status;
4123 if (!ReadSnapshotStatus(file.get(), name, &status)) {
4124 ok = false;
4125 continue;
4126 }
4127 ss << " state: " << SnapshotState_Name(status.state()) << std::endl;
4128 ss << " device size (bytes): " << status.device_size() << std::endl;
4129 ss << " snapshot size (bytes): " << status.snapshot_size() << std::endl;
4130 ss << " cow partition size (bytes): " << status.cow_partition_size() << std::endl;
4131 ss << " cow file size (bytes): " << status.cow_file_size() << std::endl;
4132 ss << " allocated sectors: " << status.sectors_allocated() << std::endl;
4133 ss << " metadata sectors: " << status.metadata_sectors() << std::endl;
4134 ss << " compression: " << status.compression_algorithm() << std::endl;
4135 ss << " compression factor: " << status.compression_factor() << std::endl;
4136 ss << " merge phase: " << DecideMergePhase(status) << std::endl;
4137 }
4138 os << ss.rdbuf();
4139 return ok;
4140 }
4141
EnsureMetadataMounted()4142 std::unique_ptr<AutoDevice> SnapshotManager::EnsureMetadataMounted() {
4143 if (!device_->IsRecovery()) {
4144 // No need to mount anything in recovery.
4145 LOG(INFO) << "EnsureMetadataMounted does nothing in Android mode.";
4146 return std::unique_ptr<AutoUnmountDevice>(new AutoUnmountDevice());
4147 }
4148 auto ret = AutoUnmountDevice::New(device_->GetMetadataDir());
4149 if (ret == nullptr) return nullptr;
4150
4151 // In rescue mode, it is possible to erase and format metadata, but /metadata/ota is not
4152 // created to execute snapshot updates. Hence, subsequent calls is likely to fail because
4153 // Lock*() fails. By failing early and returning nullptr here, update_engine_sideload can
4154 // treat this case as if /metadata is not mounted.
4155 if (!LockShared()) {
4156 LOG(WARNING) << "/metadata is mounted, but errors occur when acquiring a shared lock. "
4157 "Subsequent calls to SnapshotManager will fail. Unmounting /metadata now.";
4158 return nullptr;
4159 }
4160 return ret;
4161 }
4162
HandleImminentDataWipe(const std::function<void ()> & callback)4163 bool SnapshotManager::HandleImminentDataWipe(const std::function<void()>& callback) {
4164 if (!device_->IsRecovery()) {
4165 LOG(ERROR) << "Data wipes are only allowed in recovery.";
4166 return false;
4167 }
4168
4169 auto mount = EnsureMetadataMounted();
4170 if (!mount || !mount->HasDevice()) {
4171 // We allow the wipe to continue, because if we can't mount /metadata,
4172 // it is unlikely the device would have booted anyway. If there is no
4173 // metadata partition, then the device predates Virtual A/B.
4174 LOG(INFO) << "/metadata not found; allowing wipe.";
4175 return true;
4176 }
4177
4178 // This could happen if /metadata mounted but there is no filesystem
4179 // structure. Weird, but we have to assume there's no OTA pending, and
4180 // thus we let the wipe proceed.
4181 UpdateState state;
4182 {
4183 auto lock = LockExclusive();
4184 if (!lock) {
4185 LOG(ERROR) << "Unable to determine update state; allowing wipe.";
4186 return true;
4187 }
4188
4189 state = ReadUpdateState(lock.get());
4190 LOG(INFO) << "Update state before wipe: " << state << "; slot: " << GetCurrentSlot()
4191 << "; suffix: " << device_->GetSlotSuffix();
4192 }
4193
4194 bool try_merge = false;
4195 switch (state) {
4196 case UpdateState::None:
4197 case UpdateState::Initiated:
4198 LOG(INFO) << "Wipe is not impacted by update state; allowing wipe.";
4199 break;
4200 case UpdateState::Unverified:
4201 if (GetCurrentSlot() != Slot::Target) {
4202 LOG(INFO) << "Wipe is not impacted by rolled back update; allowing wipe";
4203 break;
4204 }
4205 if (!HasForwardMergeIndicator()) {
4206 auto slot_number = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
4207 auto other_slot_number = SlotNumberForSlotSuffix(device_->GetOtherSlotSuffix());
4208
4209 // We're not allowed to forward merge, so forcefully rollback the
4210 // slot switch.
4211 LOG(INFO) << "Allowing wipe due to lack of forward merge indicator; reverting to "
4212 "old slot since update will be deleted.";
4213 device_->SetSlotAsUnbootable(slot_number);
4214 device_->SetActiveBootSlot(other_slot_number);
4215 break;
4216 }
4217
4218 // Forward merge indicator means we have to mount snapshots and try to merge.
4219 LOG(INFO) << "Forward merge indicator is present.";
4220 try_merge = true;
4221 break;
4222 case UpdateState::Merging:
4223 case UpdateState::MergeFailed:
4224 try_merge = true;
4225 break;
4226 case UpdateState::MergeNeedsReboot:
4227 case UpdateState::Cancelled:
4228 LOG(INFO) << "Unexpected update state in recovery; allowing wipe.";
4229 break;
4230 default:
4231 break;
4232 }
4233
4234 if (try_merge) {
4235 auto slot_number = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
4236 auto super_path = device_->GetSuperDevice(slot_number);
4237 if (!CreateLogicalAndSnapshotPartitions(super_path, 20s)) {
4238 LOG(ERROR) << "Unable to map partitions to complete merge.";
4239 return false;
4240 }
4241
4242 auto process_callback = [&]() -> bool {
4243 if (callback) {
4244 callback();
4245 }
4246 return true;
4247 };
4248
4249 state = ProcessUpdateStateOnDataWipe(process_callback);
4250 if (state == UpdateState::MergeFailed) {
4251 return false;
4252 }
4253
4254 // Nothing should be depending on partitions now, so unmap them all.
4255 if (!UnmapAllPartitionsInRecovery()) {
4256 LOG(ERROR) << "Unable to unmap all partitions; fastboot may fail to flash.";
4257 }
4258 }
4259
4260 if (state != UpdateState::None) {
4261 auto lock = LockExclusive();
4262 if (!lock) return false;
4263
4264 // Zap the update state so the bootloader doesn't think we're still
4265 // merging. It's okay if this fails, it's informative only at this
4266 // point.
4267 WriteUpdateState(lock.get(), UpdateState::None);
4268 }
4269 return true;
4270 }
4271
FinishMergeInRecovery()4272 bool SnapshotManager::FinishMergeInRecovery() {
4273 if (!device_->IsRecovery()) {
4274 LOG(ERROR) << "Data wipes are only allowed in recovery.";
4275 return false;
4276 }
4277
4278 auto mount = EnsureMetadataMounted();
4279 if (!mount || !mount->HasDevice()) {
4280 return false;
4281 }
4282
4283 auto slot_number = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
4284 auto super_path = device_->GetSuperDevice(slot_number);
4285 if (!CreateLogicalAndSnapshotPartitions(super_path, 20s)) {
4286 LOG(ERROR) << "Unable to map partitions to complete merge.";
4287 return false;
4288 }
4289
4290 UpdateState state = ProcessUpdateState();
4291 if (state != UpdateState::MergeCompleted) {
4292 LOG(ERROR) << "Merge returned unexpected status: " << state;
4293 return false;
4294 }
4295
4296 // Nothing should be depending on partitions now, so unmap them all.
4297 if (!UnmapAllPartitionsInRecovery()) {
4298 LOG(ERROR) << "Unable to unmap all partitions; fastboot may fail to flash.";
4299 }
4300 return true;
4301 }
4302
ProcessUpdateStateOnDataWipe(const std::function<bool ()> & callback)4303 UpdateState SnapshotManager::ProcessUpdateStateOnDataWipe(const std::function<bool()>& callback) {
4304 while (true) {
4305 UpdateState state = ProcessUpdateState(callback);
4306 LOG(INFO) << "Processed updated state in recovery: " << state;
4307 switch (state) {
4308 case UpdateState::MergeFailed:
4309 LOG(ERROR) << "Unrecoverable merge failure detected.";
4310 return state;
4311 case UpdateState::Unverified: {
4312 // Unverified was already handled earlier, in HandleImminentDataWipe,
4313 // but it will fall through here if a forward merge is required.
4314 //
4315 // If InitiateMerge fails, we early return. If it succeeds, then we
4316 // are guaranteed that the next call to ProcessUpdateState will not
4317 // return Unverified.
4318 if (!InitiateMerge()) {
4319 LOG(ERROR) << "Failed to initiate merge on data wipe.";
4320 return UpdateState::MergeFailed;
4321 }
4322 continue;
4323 }
4324 case UpdateState::MergeNeedsReboot:
4325 // We shouldn't get here, because nothing is depending on
4326 // logical partitions.
4327 LOG(ERROR) << "Unexpected merge-needs-reboot state in recovery.";
4328 return state;
4329 default:
4330 return state;
4331 }
4332 }
4333 }
4334
HasForwardMergeIndicator()4335 bool SnapshotManager::HasForwardMergeIndicator() {
4336 return access(GetForwardMergeIndicatorPath().c_str(), F_OK) == 0;
4337 }
4338
EnsureNoOverflowSnapshot(LockedFile * lock)4339 bool SnapshotManager::EnsureNoOverflowSnapshot(LockedFile* lock) {
4340 CHECK(lock);
4341
4342 std::vector<std::string> snapshots;
4343 if (!ListSnapshots(lock, &snapshots)) {
4344 LOG(ERROR) << "Could not list snapshots.";
4345 return false;
4346 }
4347
4348 for (const auto& snapshot : snapshots) {
4349 SnapshotStatus status;
4350 if (!ReadSnapshotStatus(lock, snapshot, &status)) {
4351 return false;
4352 }
4353 if (status.using_snapuserd()) {
4354 continue;
4355 }
4356
4357 std::vector<DeviceMapper::TargetInfo> targets;
4358 if (!dm_.GetTableStatus(snapshot, &targets)) {
4359 LOG(ERROR) << "Could not read snapshot device table: " << snapshot;
4360 return false;
4361 }
4362 if (targets.size() != 1) {
4363 LOG(ERROR) << "Unexpected device-mapper table for snapshot: " << snapshot
4364 << ", size = " << targets.size();
4365 return false;
4366 }
4367 if (targets[0].IsOverflowSnapshot()) {
4368 LOG(ERROR) << "Detected overflow in snapshot " << snapshot
4369 << ", CoW device size computation is wrong!";
4370 return false;
4371 }
4372 }
4373
4374 return true;
4375 }
4376
RecoveryCreateSnapshotDevices()4377 CreateResult SnapshotManager::RecoveryCreateSnapshotDevices() {
4378 if (!device_->IsRecovery()) {
4379 LOG(ERROR) << __func__ << " is only allowed in recovery.";
4380 return CreateResult::NOT_CREATED;
4381 }
4382
4383 auto mount = EnsureMetadataMounted();
4384 if (!mount || !mount->HasDevice()) {
4385 LOG(ERROR) << "Couldn't mount Metadata.";
4386 return CreateResult::NOT_CREATED;
4387 }
4388 return RecoveryCreateSnapshotDevices(mount);
4389 }
4390
RecoveryCreateSnapshotDevices(const std::unique_ptr<AutoDevice> & metadata_device)4391 CreateResult SnapshotManager::RecoveryCreateSnapshotDevices(
4392 const std::unique_ptr<AutoDevice>& metadata_device) {
4393 if (!device_->IsRecovery()) {
4394 LOG(ERROR) << __func__ << " is only allowed in recovery.";
4395 return CreateResult::NOT_CREATED;
4396 }
4397
4398 if (metadata_device == nullptr || !metadata_device->HasDevice()) {
4399 LOG(ERROR) << "Metadata not mounted.";
4400 return CreateResult::NOT_CREATED;
4401 }
4402
4403 auto state_file = GetStateFilePath();
4404 if (access(state_file.c_str(), F_OK) != 0 && errno == ENOENT) {
4405 LOG(ERROR) << "Couldn't access state file.";
4406 return CreateResult::NOT_CREATED;
4407 }
4408
4409 if (!NeedSnapshotsInFirstStageMount()) {
4410 return CreateResult::NOT_CREATED;
4411 }
4412
4413 auto slot_suffix = device_->GetOtherSlotSuffix();
4414 auto slot_number = SlotNumberForSlotSuffix(slot_suffix);
4415 auto super_path = device_->GetSuperDevice(slot_number);
4416 if (!CreateLogicalAndSnapshotPartitions(super_path, 20s)) {
4417 LOG(ERROR) << "Unable to map partitions.";
4418 return CreateResult::ERROR;
4419 }
4420 return CreateResult::CREATED;
4421 }
4422
UpdateForwardMergeIndicator(bool wipe)4423 bool SnapshotManager::UpdateForwardMergeIndicator(bool wipe) {
4424 auto path = GetForwardMergeIndicatorPath();
4425
4426 if (!wipe) {
4427 LOG(INFO) << "Wipe is not scheduled. Deleting forward merge indicator.";
4428 return RemoveFileIfExists(path);
4429 }
4430
4431 // TODO(b/152094219): Don't forward merge if no CoW file is allocated.
4432
4433 LOG(INFO) << "Wipe will be scheduled. Allowing forward merge of snapshots.";
4434 if (!android::base::WriteStringToFile("1", path)) {
4435 PLOG(ERROR) << "Unable to write forward merge indicator: " << path;
4436 return false;
4437 }
4438
4439 return true;
4440 }
4441
GetSnapshotMergeStatsInstance()4442 ISnapshotMergeStats* SnapshotManager::GetSnapshotMergeStatsInstance() {
4443 return SnapshotMergeStats::GetInstance(*this);
4444 }
4445
4446 // This is only to be used in recovery or normal Android (not first-stage init).
4447 // We don't guarantee dm paths are available in first-stage init, because ueventd
4448 // isn't running yet.
GetMappedImageDevicePath(const std::string & device_name,std::string * device_path)4449 bool SnapshotManager::GetMappedImageDevicePath(const std::string& device_name,
4450 std::string* device_path) {
4451 // Try getting the device string if it is a device mapper device.
4452 if (dm_.GetState(device_name) != DmDeviceState::INVALID) {
4453 return dm_.GetDmDevicePathByName(device_name, device_path);
4454 }
4455
4456 // Otherwise, get path from IImageManager.
4457 return images_->GetMappedImageDevice(device_name, device_path);
4458 }
4459
GetMappedImageDeviceStringOrPath(const std::string & device_name,std::string * device_string_or_mapped_path)4460 bool SnapshotManager::GetMappedImageDeviceStringOrPath(const std::string& device_name,
4461 std::string* device_string_or_mapped_path) {
4462 // Try getting the device string if it is a device mapper device.
4463 if (dm_.GetState(device_name) != DmDeviceState::INVALID) {
4464 return dm_.GetDeviceString(device_name, device_string_or_mapped_path);
4465 }
4466
4467 // Otherwise, get path from IImageManager.
4468 if (!images_->GetMappedImageDevice(device_name, device_string_or_mapped_path)) {
4469 return false;
4470 }
4471
4472 LOG(WARNING) << "Calling GetMappedImageDevice with local image manager; device "
4473 << (device_string_or_mapped_path ? *device_string_or_mapped_path : "(nullptr)")
4474 << "may not be available in first stage init! ";
4475 return true;
4476 }
4477
WaitForDevice(const std::string & device,std::chrono::milliseconds timeout_ms)4478 bool SnapshotManager::WaitForDevice(const std::string& device,
4479 std::chrono::milliseconds timeout_ms) {
4480 if (!android::base::StartsWith(device, "/")) {
4481 return true;
4482 }
4483
4484 // In first-stage init, we rely on init setting a callback which can
4485 // regenerate uevents and populate /dev for us.
4486 if (uevent_regen_callback_) {
4487 if (!uevent_regen_callback_(device)) {
4488 LOG(ERROR) << "Failed to find device after regenerating uevents: " << device;
4489 return false;
4490 }
4491 return true;
4492 }
4493
4494 // Otherwise, the only kind of device we need to wait for is a dm-user
4495 // misc device. Normal calls to DeviceMapper::CreateDevice() guarantee
4496 // the path has been created.
4497 if (!android::base::StartsWith(device, "/dev/dm-user/")) {
4498 return true;
4499 }
4500
4501 if (timeout_ms.count() == 0) {
4502 LOG(ERROR) << "No timeout was specified to wait for device: " << device;
4503 return false;
4504 }
4505 if (!android::fs_mgr::WaitForFile(device, timeout_ms)) {
4506 LOG(ERROR) << "Timed out waiting for device to appear: " << device;
4507 return false;
4508 }
4509 return true;
4510 }
4511
IsSnapuserdRequired()4512 bool SnapshotManager::IsSnapuserdRequired() {
4513 auto lock = LockExclusive();
4514 if (!lock) return false;
4515
4516 auto status = ReadSnapshotUpdateStatus(lock.get());
4517 return status.state() != UpdateState::None && status.using_snapuserd();
4518 }
4519
PrepareSnapuserdArgsForSelinux(std::vector<std::string> * snapuserd_argv)4520 bool SnapshotManager::PrepareSnapuserdArgsForSelinux(std::vector<std::string>* snapuserd_argv) {
4521 return PerformInitTransition(InitTransition::SELINUX_DETACH, snapuserd_argv);
4522 }
4523
DetachFirstStageSnapuserdForSelinux()4524 bool SnapshotManager::DetachFirstStageSnapuserdForSelinux() {
4525 LOG(INFO) << "Detaching first stage snapuserd";
4526
4527 auto lock = LockExclusive();
4528 if (!lock) return false;
4529
4530 std::vector<std::string> snapshots;
4531 if (!ListSnapshots(lock.get(), &snapshots)) {
4532 LOG(ERROR) << "Failed to list snapshots.";
4533 return false;
4534 }
4535
4536 size_t num_cows = 0;
4537 size_t ok_cows = 0;
4538 for (const auto& snapshot : snapshots) {
4539 std::string user_cow_name = GetDmUserCowName(snapshot, GetSnapshotDriver(lock.get()));
4540
4541 if (dm_.GetState(user_cow_name) == DmDeviceState::INVALID) {
4542 continue;
4543 }
4544
4545 DeviceMapper::TargetInfo target;
4546 if (!GetSingleTarget(user_cow_name, TableQuery::Table, &target)) {
4547 continue;
4548 }
4549
4550 auto target_type = DeviceMapper::GetTargetType(target.spec);
4551 if (target_type != "user") {
4552 LOG(ERROR) << "Unexpected target type for " << user_cow_name << ": " << target_type;
4553 continue;
4554 }
4555
4556 num_cows++;
4557 auto misc_name = user_cow_name;
4558
4559 DmTable table;
4560 table.Emplace<DmTargetUser>(0, target.spec.length, misc_name);
4561 if (!dm_.LoadTableAndActivate(user_cow_name, table)) {
4562 LOG(ERROR) << "Unable to swap tables for " << misc_name;
4563 continue;
4564 }
4565
4566 // Wait for ueventd to acknowledge and create the control device node.
4567 std::string control_device = "/dev/dm-user/" + misc_name;
4568 if (!WaitForDevice(control_device, 10s)) {
4569 LOG(ERROR) << "dm-user control device no found: " << misc_name;
4570 continue;
4571 }
4572
4573 ok_cows++;
4574 LOG(INFO) << "control device is ready: " << control_device;
4575 }
4576
4577 if (ok_cows != num_cows) {
4578 LOG(ERROR) << "Could not transition all snapuserd consumers.";
4579 return false;
4580 }
4581
4582 return true;
4583 }
4584
PerformSecondStageInitTransition()4585 bool SnapshotManager::PerformSecondStageInitTransition() {
4586 return PerformInitTransition(InitTransition::SECOND_STAGE);
4587 }
4588
ReadOldPartitionMetadata(LockedFile * lock)4589 const LpMetadata* SnapshotManager::ReadOldPartitionMetadata(LockedFile* lock) {
4590 CHECK(lock);
4591
4592 if (!old_partition_metadata_) {
4593 auto path = GetOldPartitionMetadataPath();
4594 old_partition_metadata_ = android::fs_mgr::ReadFromImageFile(path);
4595 if (!old_partition_metadata_) {
4596 LOG(ERROR) << "Could not read old partition metadata from " << path;
4597 return nullptr;
4598 }
4599 }
4600 return old_partition_metadata_.get();
4601 }
4602
DecideMergePhase(const SnapshotStatus & status)4603 MergePhase SnapshotManager::DecideMergePhase(const SnapshotStatus& status) {
4604 if (status.using_snapuserd() && status.device_size() < status.old_partition_size()) {
4605 return MergePhase::FIRST_PHASE;
4606 }
4607 return MergePhase::SECOND_PHASE;
4608 }
4609
UpdateCowStats(ISnapshotMergeStats * stats)4610 void SnapshotManager::UpdateCowStats(ISnapshotMergeStats* stats) {
4611 auto lock = LockExclusive();
4612 if (!lock) return;
4613
4614 std::vector<std::string> snapshots;
4615 if (!ListSnapshots(lock.get(), &snapshots, GetSnapshotSlotSuffix())) {
4616 LOG(ERROR) << "Could not list snapshots";
4617 return;
4618 }
4619
4620 uint64_t cow_file_size = 0;
4621 uint64_t total_cow_size = 0;
4622 uint64_t estimated_cow_size = 0;
4623 for (const auto& snapshot : snapshots) {
4624 SnapshotStatus status;
4625 if (!ReadSnapshotStatus(lock.get(), snapshot, &status)) {
4626 return;
4627 }
4628
4629 cow_file_size += status.cow_file_size();
4630 total_cow_size += status.cow_file_size() + status.cow_partition_size();
4631 estimated_cow_size += status.estimated_cow_size();
4632 }
4633
4634 stats->report()->set_cow_file_size(cow_file_size);
4635 stats->report()->set_total_cow_size_bytes(total_cow_size);
4636 stats->report()->set_estimated_cow_size_bytes(estimated_cow_size);
4637 }
4638
SetMergeStatsFeatures(ISnapshotMergeStats * stats)4639 void SnapshotManager::SetMergeStatsFeatures(ISnapshotMergeStats* stats) {
4640 auto lock = LockExclusive();
4641 if (!lock) return;
4642
4643 SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock.get());
4644 stats->report()->set_iouring_used(update_status.io_uring_enabled());
4645 stats->report()->set_userspace_snapshots_used(update_status.userspace_snapshots());
4646 stats->report()->set_xor_compression_used(GetXorCompressionEnabledProperty());
4647 }
4648
DeleteDeviceIfExists(const std::string & name,const std::chrono::milliseconds & timeout_ms)4649 bool SnapshotManager::DeleteDeviceIfExists(const std::string& name,
4650 const std::chrono::milliseconds& timeout_ms) {
4651 auto start = std::chrono::steady_clock::now();
4652 while (true) {
4653 if (dm_.DeleteDeviceIfExists(name)) {
4654 return true;
4655 }
4656 auto now = std::chrono::steady_clock::now();
4657 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start);
4658 if (elapsed >= timeout_ms) {
4659 break;
4660 }
4661 std::this_thread::sleep_for(400ms);
4662 }
4663
4664 // Try to diagnose why this failed. First get the actual device path.
4665 std::string full_path;
4666 if (!dm_.GetDmDevicePathByName(name, &full_path)) {
4667 LOG(ERROR) << "Unable to diagnose DM_DEV_REMOVE failure.";
4668 return false;
4669 }
4670
4671 // Check for child dm-devices.
4672 std::string block_name = android::base::Basename(full_path);
4673 std::string sysfs_holders = "/sys/class/block/" + block_name + "/holders";
4674
4675 std::error_code ec;
4676 std::filesystem::directory_iterator dir_iter(sysfs_holders, ec);
4677 if (auto begin = std::filesystem::begin(dir_iter); begin != std::filesystem::end(dir_iter)) {
4678 LOG(ERROR) << "Child device-mapper device still mapped: " << begin->path();
4679 return false;
4680 }
4681
4682 // Check for mounted partitions.
4683 android::fs_mgr::Fstab fstab;
4684 android::fs_mgr::ReadFstabFromFile("/proc/mounts", &fstab);
4685 for (const auto& entry : fstab) {
4686 if (android::base::Basename(entry.blk_device) == block_name) {
4687 LOG(ERROR) << "Partition still mounted: " << entry.mount_point;
4688 return false;
4689 }
4690 }
4691
4692 // Check for detached mounted partitions.
4693 for (const auto& fs : std::filesystem::directory_iterator("/sys/fs", ec)) {
4694 std::string fs_type = android::base::Basename(fs.path().c_str());
4695 if (!(fs_type == "ext4" || fs_type == "f2fs")) {
4696 continue;
4697 }
4698
4699 std::string path = fs.path().c_str() + "/"s + block_name;
4700 if (access(path.c_str(), F_OK) == 0) {
4701 LOG(ERROR) << "Block device was lazily unmounted and is still in-use: " << full_path
4702 << "; possibly open file descriptor or attached loop device.";
4703 return false;
4704 }
4705 }
4706
4707 LOG(ERROR) << "Device-mapper device " << name << "(" << full_path << ")" << " still in use."
4708 << " Probably a file descriptor was leaked or held open, or a loop device is"
4709 << " attached.";
4710 return false;
4711 }
4712
ReadMergeFailureCode()4713 MergeFailureCode SnapshotManager::ReadMergeFailureCode() {
4714 auto lock = LockExclusive();
4715 if (!lock) return MergeFailureCode::AcquireLock;
4716
4717 SnapshotUpdateStatus status = ReadSnapshotUpdateStatus(lock.get());
4718 if (status.state() != UpdateState::MergeFailed) {
4719 return MergeFailureCode::Ok;
4720 }
4721 return status.merge_failure_code();
4722 }
4723
ReadSourceBuildFingerprint()4724 std::string SnapshotManager::ReadSourceBuildFingerprint() {
4725 auto lock = LockExclusive();
4726 if (!lock) return {};
4727
4728 SnapshotUpdateStatus status = ReadSnapshotUpdateStatus(lock.get());
4729 return status.source_build_fingerprint();
4730 }
4731
PauseSnapshotMerge()4732 bool SnapshotManager::PauseSnapshotMerge() {
4733 auto snapuserd_client = SnapuserdClient::TryConnect(kSnapuserdSocket, 5s);
4734 if (snapuserd_client) {
4735 // Pause the snapshot-merge
4736 return snapuserd_client->PauseMerge();
4737 }
4738 return false;
4739 }
4740
ResumeSnapshotMerge()4741 bool SnapshotManager::ResumeSnapshotMerge() {
4742 auto snapuserd_client = SnapuserdClient::TryConnect(kSnapuserdSocket, 5s);
4743 if (snapuserd_client) {
4744 // Resume the snapshot-merge
4745 return snapuserd_client->ResumeMerge();
4746 }
4747 return false;
4748 }
4749
IsUserspaceSnapshotUpdateInProgress(std::vector<std::string> & dynamic_partitions)4750 bool SnapshotManager::IsUserspaceSnapshotUpdateInProgress(
4751 std::vector<std::string>& dynamic_partitions) {
4752 // We cannot grab /metadata/ota lock here as this
4753 // is in reboot path. See b/308900853
4754 //
4755 // Check if any of the partitions are mounted
4756 // off dm-user block device. If so, then we are certain
4757 // that OTA update in progress.
4758 auto current_suffix = device_->GetSlotSuffix();
4759 auto& dm = DeviceMapper::Instance();
4760 auto dm_block_devices = dm.FindDmPartitions();
4761 if (dm_block_devices.empty()) {
4762 LOG(ERROR) << "No dm-enabled block device is found.";
4763 return false;
4764 }
4765
4766 bool is_ota_in_progress = false;
4767 for (auto& partition : dm_block_devices) {
4768 std::string partition_name = partition.first + current_suffix;
4769 DeviceMapper::TargetInfo snap_target;
4770 if (!GetSingleTarget(partition_name, TableQuery::Status, &snap_target)) {
4771 continue;
4772 }
4773 auto type = DeviceMapper::GetTargetType(snap_target.spec);
4774 // Partition is mounted off snapshots
4775 if (type == "user") {
4776 dynamic_partitions.emplace_back("/" + partition.first);
4777 is_ota_in_progress = true;
4778 }
4779 }
4780 return is_ota_in_progress;
4781 }
4782
BootFromSnapshotsWithoutSlotSwitch()4783 bool SnapshotManager::BootFromSnapshotsWithoutSlotSwitch() {
4784 auto lock = LockExclusive();
4785 if (!lock) return false;
4786
4787 auto contents = device_->GetSlotSuffix();
4788 // This is the indicator which tells first-stage init
4789 // to boot from snapshots even though there was no slot-switch
4790 auto boot_file = GetBootSnapshotsWithoutSlotSwitchPath();
4791 if (!WriteStringToFileAtomic(contents, boot_file)) {
4792 PLOG(ERROR) << "write failed: " << boot_file;
4793 return false;
4794 }
4795
4796 SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock.get());
4797 update_status.set_state(UpdateState::Initiated);
4798 update_status.set_userspace_snapshots(true);
4799 update_status.set_using_snapuserd(true);
4800 if (!WriteSnapshotUpdateStatus(lock.get(), update_status)) {
4801 return false;
4802 }
4803 return true;
4804 }
4805
PrepareDeviceToBootWithoutSnapshot()4806 bool SnapshotManager::PrepareDeviceToBootWithoutSnapshot() {
4807 auto lock = LockExclusive();
4808 if (!lock) return false;
4809
4810 android::base::RemoveFileIfExists(GetSnapshotBootIndicatorPath());
4811 android::base::RemoveFileIfExists(GetBootSnapshotsWithoutSlotSwitchPath());
4812
4813 SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock.get());
4814 update_status.set_state(UpdateState::Cancelled);
4815 if (!WriteSnapshotUpdateStatus(lock.get(), update_status)) {
4816 return false;
4817 }
4818 return true;
4819 }
4820
SetReadAheadSize(const std::string & entry_block_device,off64_t size_kb)4821 void SnapshotManager::SetReadAheadSize(const std::string& entry_block_device, off64_t size_kb) {
4822 std::string block_device;
4823 if (!Realpath(entry_block_device, &block_device)) {
4824 PLOG(ERROR) << "Failed to realpath " << entry_block_device;
4825 return;
4826 }
4827
4828 static constexpr std::string_view kDevBlockPrefix("/dev/block/");
4829 if (!android::base::StartsWith(block_device, kDevBlockPrefix)) {
4830 LOG(ERROR) << block_device << " is not a block device";
4831 return;
4832 }
4833
4834 std::string block_name = block_device.substr(kDevBlockPrefix.length());
4835 std::string sys_partition =
4836 android::base::StringPrintf("/sys/class/block/%s/partition", block_name.c_str());
4837 struct stat info;
4838 if (lstat(sys_partition.c_str(), &info) == 0) {
4839 block_name += "/..";
4840 }
4841 std::string sys_ra = android::base::StringPrintf("/sys/class/block/%s/queue/read_ahead_kb",
4842 block_name.c_str());
4843 std::string size = std::to_string(size_kb);
4844 android::base::WriteStringToFile(size, sys_ra.c_str());
4845 }
4846
4847 } // namespace snapshot
4848 } // namespace android
4849