Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6aa77dd2 authored by Yifan Hong's avatar Yifan Hong
Browse files

libsnapshot: Cancel/merge existing update before begin

Attempt to cancel or merge an existing update before starting
a new one.

Test: libsnapshot_test

Change-Id: Ic534db846f1fe97bd7ca1f176a9494fbc6a0f8d5
parent 0b32b199
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -127,8 +127,9 @@ class SnapshotManager final {
    // will fail if GetUpdateState() != None.
    bool BeginUpdate();

    // Cancel an update; any snapshots will be deleted. This will fail if the
    // state != Initiated or None.
    // Cancel an update; any snapshots will be deleted. This is allowed if the
    // state == Initiated, None, or Unverified (before rebooting to the new
    // slot).
    bool CancelUpdate();

    // Mark snapshot writes as having completed. After this, new snapshots cannot
@@ -395,6 +396,13 @@ class SnapshotManager final {
    // The reverse of MapPartitionWithSnapshot.
    bool UnmapPartitionWithSnapshot(LockedFile* lock, const std::string& target_partition_name);

    // If there isn't a previous update, return true. |needs_merge| is set to false.
    // If there is a previous update but the device has not boot into it, tries to cancel the
    //   update and delete any snapshots. Return true if successful. |needs_merge| is set to false.
    // If there is a previous update and the device has boot into it, do nothing and return true.
    //   |needs_merge| is set to true.
    bool TryCancelUpdate(bool* needs_merge);

    std::string gsid_dir_;
    std::string metadata_dir_;
    std::unique_ptr<IDeviceInfo> device_;
+25 −2
Original line number Diff line number Diff line
@@ -131,6 +131,16 @@ static std::string GetSnapshotExtraDeviceName(const std::string& snapshot_name)
}

bool SnapshotManager::BeginUpdate() {
    bool needs_merge = false;
    if (!TryCancelUpdate(&needs_merge)) {
        return false;
    }
    if (needs_merge) {
        LOG(INFO) << "Wait for merge (if any) before beginning a new update.";
        auto state = ProcessUpdateState();
        LOG(INFO) << "Merged with state = " << state;
    }

    auto file = LockExclusive();
    if (!file) return false;

@@ -143,6 +153,19 @@ bool SnapshotManager::BeginUpdate() {
}

bool SnapshotManager::CancelUpdate() {
    bool needs_merge = false;
    if (!TryCancelUpdate(&needs_merge)) {
        return false;
    }
    if (needs_merge) {
        LOG(ERROR) << "Cannot cancel update after it has completed or started merging";
    }
    return !needs_merge;
}

bool SnapshotManager::TryCancelUpdate(bool* needs_merge) {
    *needs_merge = false;

    auto file = LockExclusive();
    if (!file) return false;

@@ -167,8 +190,8 @@ bool SnapshotManager::CancelUpdate() {
            return RemoveAllUpdateState(file.get());
        }
    }
    LOG(ERROR) << "Cannot cancel update after it has completed or started merging";
    return false;
    *needs_merge = true;
    return true;
}

bool SnapshotManager::RemoveAllUpdateState(LockedFile* lock) {
+1 −2
Original line number Diff line number Diff line
@@ -761,8 +761,7 @@ class SnapshotUpdateTest : public SnapshotTest {
// Also test UnmapUpdateSnapshot unmaps everything.
// Also test first stage mount and merge after this.
TEST_F(SnapshotUpdateTest, FullUpdateFlow) {
    // OTA client calls CancelUpdate then BeginUpdate before doing anything.
    ASSERT_TRUE(sm->CancelUpdate());
    // OTA client calls BeginUpdate before doing anything.
    ASSERT_TRUE(sm->BeginUpdate());

    // OTA client blindly unmaps all partitions that are possibly mapped.