Loading fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +8 −6 Original line number Diff line number Diff line Loading @@ -169,7 +169,8 @@ class SnapshotManager final { // // The optional callback allows the caller to periodically check the // progress with GetUpdateState(). UpdateState ProcessUpdateState(const std::function<void()>& callback = {}); UpdateState ProcessUpdateState(const std::function<void()>& callback = {}, const std::function<bool()>& before_cancel = {}); public: // Initiate the merge if necessary, then wait for the merge to finish. Loading @@ -179,7 +180,8 @@ class SnapshotManager final { // - Unverified if called on the source slot // - MergeCompleted if merge is completed // - other states indicating an error has occurred UpdateState InitiateMergeAndWait(SnapshotMergeReport* report = nullptr); UpdateState InitiateMergeAndWait(SnapshotMergeReport* report = nullptr, const std::function<bool()>& before_cancel = {}); // Wait for the merge if rebooted into the new slot. Does NOT initiate a // merge. If the merge has not been initiated (but should be), wait. Loading Loading @@ -375,14 +377,14 @@ class SnapshotManager final { // Check for a cancelled or rolled back merge, returning true if such a // condition was detected and handled. bool HandleCancelledUpdate(LockedFile* lock); bool HandleCancelledUpdate(LockedFile* lock, const std::function<bool()>& before_cancel); // Helper for HandleCancelledUpdate. Assumes booting from new slot. bool AreAllSnapshotsCancelled(LockedFile* lock); // Remove artifacts created by the update process, such as snapshots, and // set the update state to None. bool RemoveAllUpdateState(LockedFile* lock); bool RemoveAllUpdateState(LockedFile* lock, const std::function<bool()>& prolog = {}); // Interact with /metadata/ota. std::unique_ptr<LockedFile> OpenLock(int lock_flags); Loading Loading @@ -437,8 +439,8 @@ class SnapshotManager final { // UpdateState::MergeCompleted // UpdateState::MergeFailed // UpdateState::MergeNeedsReboot UpdateState CheckMergeState(); UpdateState CheckMergeState(LockedFile* lock); UpdateState CheckMergeState(const std::function<bool()>& before_cancel); UpdateState CheckMergeState(LockedFile* lock, const std::function<bool()>& before_cancel); UpdateState CheckTargetMergeState(LockedFile* lock, const std::string& name); // Interact with status files under /metadata/ota/snapshots. Loading fs_mgr/libsnapshot/snapshot.cpp +22 −13 Original line number Diff line number Diff line Loading @@ -219,7 +219,12 @@ static bool RemoveFileIfExists(const std::string& path) { return true; } bool SnapshotManager::RemoveAllUpdateState(LockedFile* lock) { bool SnapshotManager::RemoveAllUpdateState(LockedFile* lock, const std::function<bool()>& prolog) { if (prolog && !prolog()) { LOG(WARNING) << "Can't RemoveAllUpdateState: prolog failed."; return false; } LOG(INFO) << "Removing all update state."; #ifdef LIBSNAPSHOT_USE_CALLSTACK Loading Loading @@ -789,9 +794,10 @@ bool SnapshotManager::QuerySnapshotStatus(const std::string& dm_name, std::strin // Note that when a merge fails, we will *always* try again to complete the // merge each time the device boots. There is no harm in doing so, and if // the problem was transient, we might manage to get a new outcome. UpdateState SnapshotManager::ProcessUpdateState(const std::function<void()>& callback) { UpdateState SnapshotManager::ProcessUpdateState(const std::function<void()>& callback, const std::function<bool()>& before_cancel) { while (true) { UpdateState state = CheckMergeState(); UpdateState state = CheckMergeState(before_cancel); if (state == UpdateState::MergeFailed) { AcknowledgeMergeFailure(); } Loading @@ -811,24 +817,25 @@ UpdateState SnapshotManager::ProcessUpdateState(const std::function<void()>& cal } } UpdateState SnapshotManager::CheckMergeState() { UpdateState SnapshotManager::CheckMergeState(const std::function<bool()>& before_cancel) { auto lock = LockExclusive(); if (!lock) { return UpdateState::MergeFailed; } UpdateState state = CheckMergeState(lock.get()); UpdateState state = CheckMergeState(lock.get(), before_cancel); if (state == UpdateState::MergeCompleted) { // Do this inside the same lock. Failures get acknowledged without the // lock, because flock() might have failed. AcknowledgeMergeSuccess(lock.get()); } else if (state == UpdateState::Cancelled) { RemoveAllUpdateState(lock.get()); RemoveAllUpdateState(lock.get(), before_cancel); } return state; } UpdateState SnapshotManager::CheckMergeState(LockedFile* lock) { UpdateState SnapshotManager::CheckMergeState(LockedFile* lock, const std::function<bool()>& before_cancel) { UpdateState state = ReadUpdateState(lock); switch (state) { case UpdateState::None: Loading @@ -849,7 +856,7 @@ UpdateState SnapshotManager::CheckMergeState(LockedFile* lock) { // This is an edge case. Normally cancelled updates are detected // via the merge poll below, but if we never started a merge, we // need to also check here. if (HandleCancelledUpdate(lock)) { if (HandleCancelledUpdate(lock, before_cancel)) { return UpdateState::Cancelled; } return state; Loading Loading @@ -1169,7 +1176,8 @@ bool SnapshotManager::CollapseSnapshotDevice(const std::string& name, return true; } bool SnapshotManager::HandleCancelledUpdate(LockedFile* lock) { bool SnapshotManager::HandleCancelledUpdate(LockedFile* lock, const std::function<bool()>& before_cancel) { auto slot = GetCurrentSlot(); if (slot == Slot::Unknown) { return false; Loading @@ -1177,7 +1185,7 @@ bool SnapshotManager::HandleCancelledUpdate(LockedFile* lock) { // If all snapshots were reflashed, then cancel the entire update. if (AreAllSnapshotsCancelled(lock)) { RemoveAllUpdateState(lock); RemoveAllUpdateState(lock, before_cancel); return true; } Loading Loading @@ -2388,7 +2396,8 @@ std::unique_ptr<AutoDevice> SnapshotManager::EnsureMetadataMounted() { return AutoUnmountDevice::New(device_->GetMetadataDir()); } UpdateState SnapshotManager::InitiateMergeAndWait(SnapshotMergeReport* stats_report) { UpdateState SnapshotManager::InitiateMergeAndWait(SnapshotMergeReport* stats_report, const std::function<bool()>& before_cancel) { { auto lock = LockExclusive(); // Sync update state from file with bootloader. Loading @@ -2413,7 +2422,7 @@ UpdateState SnapshotManager::InitiateMergeAndWait(SnapshotMergeReport* stats_rep LOG(INFO) << "Waiting for any previous merge request to complete. " << "This can take up to several minutes."; merge_stats.Resume(); auto state = ProcessUpdateState(callback); auto state = ProcessUpdateState(callback, before_cancel); merge_stats.set_state(state); if (state == UpdateState::None) { LOG(INFO) << "Can't find any snapshot to merge."; Loading @@ -2436,7 +2445,7 @@ UpdateState SnapshotManager::InitiateMergeAndWait(SnapshotMergeReport* stats_rep // All other states can be handled by ProcessUpdateState. LOG(INFO) << "Waiting for merge to complete. This can take up to several minutes."; last_progress = 0; state = ProcessUpdateState(callback); state = ProcessUpdateState(callback, before_cancel); merge_stats.set_state(state); } Loading Loading
fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +8 −6 Original line number Diff line number Diff line Loading @@ -169,7 +169,8 @@ class SnapshotManager final { // // The optional callback allows the caller to periodically check the // progress with GetUpdateState(). UpdateState ProcessUpdateState(const std::function<void()>& callback = {}); UpdateState ProcessUpdateState(const std::function<void()>& callback = {}, const std::function<bool()>& before_cancel = {}); public: // Initiate the merge if necessary, then wait for the merge to finish. Loading @@ -179,7 +180,8 @@ class SnapshotManager final { // - Unverified if called on the source slot // - MergeCompleted if merge is completed // - other states indicating an error has occurred UpdateState InitiateMergeAndWait(SnapshotMergeReport* report = nullptr); UpdateState InitiateMergeAndWait(SnapshotMergeReport* report = nullptr, const std::function<bool()>& before_cancel = {}); // Wait for the merge if rebooted into the new slot. Does NOT initiate a // merge. If the merge has not been initiated (but should be), wait. Loading Loading @@ -375,14 +377,14 @@ class SnapshotManager final { // Check for a cancelled or rolled back merge, returning true if such a // condition was detected and handled. bool HandleCancelledUpdate(LockedFile* lock); bool HandleCancelledUpdate(LockedFile* lock, const std::function<bool()>& before_cancel); // Helper for HandleCancelledUpdate. Assumes booting from new slot. bool AreAllSnapshotsCancelled(LockedFile* lock); // Remove artifacts created by the update process, such as snapshots, and // set the update state to None. bool RemoveAllUpdateState(LockedFile* lock); bool RemoveAllUpdateState(LockedFile* lock, const std::function<bool()>& prolog = {}); // Interact with /metadata/ota. std::unique_ptr<LockedFile> OpenLock(int lock_flags); Loading Loading @@ -437,8 +439,8 @@ class SnapshotManager final { // UpdateState::MergeCompleted // UpdateState::MergeFailed // UpdateState::MergeNeedsReboot UpdateState CheckMergeState(); UpdateState CheckMergeState(LockedFile* lock); UpdateState CheckMergeState(const std::function<bool()>& before_cancel); UpdateState CheckMergeState(LockedFile* lock, const std::function<bool()>& before_cancel); UpdateState CheckTargetMergeState(LockedFile* lock, const std::string& name); // Interact with status files under /metadata/ota/snapshots. Loading
fs_mgr/libsnapshot/snapshot.cpp +22 −13 Original line number Diff line number Diff line Loading @@ -219,7 +219,12 @@ static bool RemoveFileIfExists(const std::string& path) { return true; } bool SnapshotManager::RemoveAllUpdateState(LockedFile* lock) { bool SnapshotManager::RemoveAllUpdateState(LockedFile* lock, const std::function<bool()>& prolog) { if (prolog && !prolog()) { LOG(WARNING) << "Can't RemoveAllUpdateState: prolog failed."; return false; } LOG(INFO) << "Removing all update state."; #ifdef LIBSNAPSHOT_USE_CALLSTACK Loading Loading @@ -789,9 +794,10 @@ bool SnapshotManager::QuerySnapshotStatus(const std::string& dm_name, std::strin // Note that when a merge fails, we will *always* try again to complete the // merge each time the device boots. There is no harm in doing so, and if // the problem was transient, we might manage to get a new outcome. UpdateState SnapshotManager::ProcessUpdateState(const std::function<void()>& callback) { UpdateState SnapshotManager::ProcessUpdateState(const std::function<void()>& callback, const std::function<bool()>& before_cancel) { while (true) { UpdateState state = CheckMergeState(); UpdateState state = CheckMergeState(before_cancel); if (state == UpdateState::MergeFailed) { AcknowledgeMergeFailure(); } Loading @@ -811,24 +817,25 @@ UpdateState SnapshotManager::ProcessUpdateState(const std::function<void()>& cal } } UpdateState SnapshotManager::CheckMergeState() { UpdateState SnapshotManager::CheckMergeState(const std::function<bool()>& before_cancel) { auto lock = LockExclusive(); if (!lock) { return UpdateState::MergeFailed; } UpdateState state = CheckMergeState(lock.get()); UpdateState state = CheckMergeState(lock.get(), before_cancel); if (state == UpdateState::MergeCompleted) { // Do this inside the same lock. Failures get acknowledged without the // lock, because flock() might have failed. AcknowledgeMergeSuccess(lock.get()); } else if (state == UpdateState::Cancelled) { RemoveAllUpdateState(lock.get()); RemoveAllUpdateState(lock.get(), before_cancel); } return state; } UpdateState SnapshotManager::CheckMergeState(LockedFile* lock) { UpdateState SnapshotManager::CheckMergeState(LockedFile* lock, const std::function<bool()>& before_cancel) { UpdateState state = ReadUpdateState(lock); switch (state) { case UpdateState::None: Loading @@ -849,7 +856,7 @@ UpdateState SnapshotManager::CheckMergeState(LockedFile* lock) { // This is an edge case. Normally cancelled updates are detected // via the merge poll below, but if we never started a merge, we // need to also check here. if (HandleCancelledUpdate(lock)) { if (HandleCancelledUpdate(lock, before_cancel)) { return UpdateState::Cancelled; } return state; Loading Loading @@ -1169,7 +1176,8 @@ bool SnapshotManager::CollapseSnapshotDevice(const std::string& name, return true; } bool SnapshotManager::HandleCancelledUpdate(LockedFile* lock) { bool SnapshotManager::HandleCancelledUpdate(LockedFile* lock, const std::function<bool()>& before_cancel) { auto slot = GetCurrentSlot(); if (slot == Slot::Unknown) { return false; Loading @@ -1177,7 +1185,7 @@ bool SnapshotManager::HandleCancelledUpdate(LockedFile* lock) { // If all snapshots were reflashed, then cancel the entire update. if (AreAllSnapshotsCancelled(lock)) { RemoveAllUpdateState(lock); RemoveAllUpdateState(lock, before_cancel); return true; } Loading Loading @@ -2388,7 +2396,8 @@ std::unique_ptr<AutoDevice> SnapshotManager::EnsureMetadataMounted() { return AutoUnmountDevice::New(device_->GetMetadataDir()); } UpdateState SnapshotManager::InitiateMergeAndWait(SnapshotMergeReport* stats_report) { UpdateState SnapshotManager::InitiateMergeAndWait(SnapshotMergeReport* stats_report, const std::function<bool()>& before_cancel) { { auto lock = LockExclusive(); // Sync update state from file with bootloader. Loading @@ -2413,7 +2422,7 @@ UpdateState SnapshotManager::InitiateMergeAndWait(SnapshotMergeReport* stats_rep LOG(INFO) << "Waiting for any previous merge request to complete. " << "This can take up to several minutes."; merge_stats.Resume(); auto state = ProcessUpdateState(callback); auto state = ProcessUpdateState(callback, before_cancel); merge_stats.set_state(state); if (state == UpdateState::None) { LOG(INFO) << "Can't find any snapshot to merge."; Loading @@ -2436,7 +2445,7 @@ UpdateState SnapshotManager::InitiateMergeAndWait(SnapshotMergeReport* stats_rep // All other states can be handled by ProcessUpdateState. LOG(INFO) << "Waiting for merge to complete. This can take up to several minutes."; last_progress = 0; state = ProcessUpdateState(callback); state = ProcessUpdateState(callback, before_cancel); merge_stats.set_state(state); } Loading