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