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

Commit 956c204f authored by David Anderson's avatar David Anderson Committed by Gerrit Code Review
Browse files

Merge changes I3872dc51,I3b185f68,I37a25ca7

* changes:
  libsnapshot: Improve how devices are collapsed after merging.
  fastbootd: Cancel snapshots when modifying partitions.
  Clean up update state when snapshots are interrupted or cancelled.
parents 4adbd290 1145c01e
Loading
Loading
Loading
Loading
+41 −17
Original line number Original line Diff line number Diff line
@@ -194,23 +194,6 @@ bool DownloadHandler(FastbootDevice* device, const std::vector<std::string>& arg
    return device->WriteStatus(FastbootResult::FAIL, "Couldn't download data");
    return device->WriteStatus(FastbootResult::FAIL, "Couldn't download data");
}
}


bool FlashHandler(FastbootDevice* device, const std::vector<std::string>& args) {
    if (args.size() < 2) {
        return device->WriteStatus(FastbootResult::FAIL, "Invalid arguments");
    }

    if (GetDeviceLockStatus()) {
        return device->WriteStatus(FastbootResult::FAIL,
                                   "Flashing is not allowed on locked devices");
    }

    int ret = Flash(device, args[1]);
    if (ret < 0) {
        return device->WriteStatus(FastbootResult::FAIL, strerror(-ret));
    }
    return device->WriteStatus(FastbootResult::OKAY, "Flashing succeeded");
}

bool SetActiveHandler(FastbootDevice* device, const std::vector<std::string>& args) {
bool SetActiveHandler(FastbootDevice* device, const std::vector<std::string>& args) {
    if (args.size() < 2) {
    if (args.size() < 2) {
        return device->WriteStatus(FastbootResult::FAIL, "Missing slot argument");
        return device->WriteStatus(FastbootResult::FAIL, "Missing slot argument");
@@ -440,6 +423,11 @@ bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::strin
    if (!partition) {
    if (!partition) {
        return device->WriteFail("Partition does not exist");
        return device->WriteFail("Partition does not exist");
    }
    }

    // Remove the updated flag to cancel any snapshots.
    uint32_t attrs = partition->attributes();
    partition->set_attributes(attrs & ~LP_PARTITION_ATTR_UPDATED);

    if (!builder->ResizePartition(partition, partition_size)) {
    if (!builder->ResizePartition(partition, partition_size)) {
        return device->WriteFail("Not enough space to resize partition");
        return device->WriteFail("Not enough space to resize partition");
    }
    }
@@ -449,6 +437,42 @@ bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::strin
    return device->WriteOkay("Partition resized");
    return device->WriteOkay("Partition resized");
}
}


void CancelPartitionSnapshot(FastbootDevice* device, const std::string& partition_name) {
    PartitionBuilder builder(device, partition_name);
    if (!builder.Valid()) return;

    auto partition = builder->FindPartition(partition_name);
    if (!partition) return;

    // Remove the updated flag to cancel any snapshots.
    uint32_t attrs = partition->attributes();
    partition->set_attributes(attrs & ~LP_PARTITION_ATTR_UPDATED);

    builder.Write();
}

bool FlashHandler(FastbootDevice* device, const std::vector<std::string>& args) {
    if (args.size() < 2) {
        return device->WriteStatus(FastbootResult::FAIL, "Invalid arguments");
    }

    if (GetDeviceLockStatus()) {
        return device->WriteStatus(FastbootResult::FAIL,
                                   "Flashing is not allowed on locked devices");
    }

    const auto& partition_name = args[1];
    if (LogicalPartitionExists(device, partition_name)) {
        CancelPartitionSnapshot(device, partition_name);
    }

    int ret = Flash(device, partition_name);
    if (ret < 0) {
        return device->WriteStatus(FastbootResult::FAIL, strerror(-ret));
    }
    return device->WriteStatus(FastbootResult::OKAY, "Flashing succeeded");
}

bool UpdateSuperHandler(FastbootDevice* device, const std::vector<std::string>& args) {
bool UpdateSuperHandler(FastbootDevice* device, const std::vector<std::string>& args) {
    if (args.size() < 2) {
    if (args.size() < 2) {
        return device->WriteFail("Invalid arguments");
        return device->WriteFail("Invalid arguments");
+3 −3
Original line number Original line Diff line number Diff line
@@ -79,7 +79,7 @@ static bool GetPhysicalPartitionDevicePath(const IPartitionOpener& opener,
    return true;
    return true;
}
}


static bool CreateDmTable(const IPartitionOpener& opener, const LpMetadata& metadata,
bool CreateDmTable(const IPartitionOpener& opener, const LpMetadata& metadata,
                   const LpMetadataPartition& partition, const std::string& super_device,
                   const LpMetadataPartition& partition, const std::string& super_device,
                   DmTable* table) {
                   DmTable* table) {
    uint64_t sector = 0;
    uint64_t sector = 0;
+5 −0
Original line number Original line Diff line number Diff line
@@ -89,6 +89,11 @@ bool CreateLogicalPartition(const CreateLogicalPartitionParams& params, std::str
// is non-zero, then this will block until the device path has been unlinked.
// is non-zero, then this will block until the device path has been unlinked.
bool DestroyLogicalPartition(const std::string& name);
bool DestroyLogicalPartition(const std::string& name);


// Helper for populating a DmTable for a logical partition.
bool CreateDmTable(const IPartitionOpener& opener, const LpMetadata& metadata,
                   const LpMetadataPartition& partition, const std::string& super_device,
                   android::dm::DmTable* table);

}  // namespace fs_mgr
}  // namespace fs_mgr
}  // namespace android
}  // namespace android


+1 −0
Original line number Original line Diff line number Diff line
@@ -123,6 +123,7 @@ class Partition final {
    const std::string& name() const { return name_; }
    const std::string& name() const { return name_; }
    const std::string& group_name() const { return group_name_; }
    const std::string& group_name() const { return group_name_; }
    uint32_t attributes() const { return attributes_; }
    uint32_t attributes() const { return attributes_; }
    void set_attributes(uint32_t attributes) { attributes_ = attributes; }
    const std::vector<std::unique_ptr<Extent>>& extents() const { return extents_; }
    const std::vector<std::unique_ptr<Extent>>& extents() const { return extents_; }
    uint64_t size() const { return size_; }
    uint64_t size() const { return size_; }


+25 −7
Original line number Original line Diff line number Diff line
@@ -66,7 +66,11 @@ enum class UpdateState : unsigned int {
    MergeCompleted,
    MergeCompleted,


    // Merging failed due to an unrecoverable error.
    // Merging failed due to an unrecoverable error.
    MergeFailed
    MergeFailed,

    // The update was implicitly cancelled, either by a rollback or a flash
    // operation via fastboot. This state can only be returned by WaitForMerge.
    Cancelled
};
};


class SnapshotManager final {
class SnapshotManager final {
@@ -82,6 +86,7 @@ class SnapshotManager final {
        virtual std::string GetGsidDir() const = 0;
        virtual std::string GetGsidDir() const = 0;
        virtual std::string GetMetadataDir() const = 0;
        virtual std::string GetMetadataDir() const = 0;
        virtual std::string GetSlotSuffix() const = 0;
        virtual std::string GetSlotSuffix() const = 0;
        virtual std::string GetSuperDevice(uint32_t slot) const = 0;
        virtual const IPartitionOpener& GetPartitionOpener() const = 0;
        virtual const IPartitionOpener& GetPartitionOpener() const = 0;
    };
    };


@@ -117,12 +122,15 @@ class SnapshotManager final {
    // update has been marked successful after booting.
    // update has been marked successful after booting.
    bool InitiateMerge();
    bool InitiateMerge();


    // Wait for the current merge to finish, then perform cleanup when it
    // Perform any necessary post-boot actions. This should be run soon after
    // completes. It is necessary to call this after InitiateMerge(), or when
    // /data is mounted.
    // a merge state is detected during boot.
    //
    // If a merge is in progress, this function will block until the merge is
    // completed. If a merge or update was cancelled, this will clean up any
    // update artifacts and return.
    //
    //
    // Note that after calling WaitForMerge(), GetUpdateState() may still return
    // Note that after calling this, GetUpdateState() may still return that a
    // that a merge is in progress:
    // merge is in progress:
    //   MergeFailed indicates that a fatal error occurred. WaitForMerge() may
    //   MergeFailed indicates that a fatal error occurred. WaitForMerge() may
    //   called any number of times again to attempt to make more progress, but
    //   called any number of times again to attempt to make more progress, but
    //   we do not expect it to succeed if a catastrophic error occurred.
    //   we do not expect it to succeed if a catastrophic error occurred.
@@ -135,7 +143,7 @@ class SnapshotManager final {
    //
    //
    //   MergeCompleted indicates that the update has fully completed.
    //   MergeCompleted indicates that the update has fully completed.
    //   GetUpdateState will return None, and a new update can begin.
    //   GetUpdateState will return None, and a new update can begin.
    UpdateState WaitForMerge();
    UpdateState ProcessUpdateState();


    // Find the status of the current update, if any.
    // Find the status of the current update, if any.
    //
    //
@@ -158,6 +166,7 @@ class SnapshotManager final {
    FRIEND_TEST(SnapshotTest, CreateSnapshot);
    FRIEND_TEST(SnapshotTest, CreateSnapshot);
    FRIEND_TEST(SnapshotTest, FirstStageMountAfterRollback);
    FRIEND_TEST(SnapshotTest, FirstStageMountAfterRollback);
    FRIEND_TEST(SnapshotTest, FirstStageMountAndMerge);
    FRIEND_TEST(SnapshotTest, FirstStageMountAndMerge);
    FRIEND_TEST(SnapshotTest, FlashSuperDuringMerge);
    FRIEND_TEST(SnapshotTest, FlashSuperDuringUpdate);
    FRIEND_TEST(SnapshotTest, FlashSuperDuringUpdate);
    FRIEND_TEST(SnapshotTest, MapPartialSnapshot);
    FRIEND_TEST(SnapshotTest, MapPartialSnapshot);
    FRIEND_TEST(SnapshotTest, MapSnapshot);
    FRIEND_TEST(SnapshotTest, MapSnapshot);
@@ -245,6 +254,14 @@ class SnapshotManager final {
    // List the known snapshot names.
    // List the known snapshot names.
    bool ListSnapshots(LockedFile* lock, std::vector<std::string>* snapshots);
    bool ListSnapshots(LockedFile* lock, std::vector<std::string>* snapshots);


    // Check for a cancelled or rolled back merge, returning true if such a
    // condition was detected and handled.
    bool HandleCancelledUpdate(LockedFile* lock);

    // Remove artifacts created by the update process, such as snapshots, and
    // set the update state to None.
    bool RemoveAllUpdateState(LockedFile* lock);

    // Interact with /metadata/ota/state.
    // Interact with /metadata/ota/state.
    std::unique_ptr<LockedFile> OpenStateFile(int open_flags, int lock_flags);
    std::unique_ptr<LockedFile> OpenStateFile(int open_flags, int lock_flags);
    std::unique_ptr<LockedFile> LockShared();
    std::unique_ptr<LockedFile> LockShared();
@@ -272,6 +289,7 @@ class SnapshotManager final {
    bool MarkSnapshotMergeCompleted(LockedFile* snapshot_lock, const std::string& snapshot_name);
    bool MarkSnapshotMergeCompleted(LockedFile* snapshot_lock, const std::string& snapshot_name);
    void AcknowledgeMergeSuccess(LockedFile* lock);
    void AcknowledgeMergeSuccess(LockedFile* lock);
    void AcknowledgeMergeFailure();
    void AcknowledgeMergeFailure();
    bool IsCancelledSnapshot(const std::string& snapshot_name);


    // Note that these require the name of the device containing the snapshot,
    // Note that these require the name of the device containing the snapshot,
    // which may be the "inner" device. Use GetsnapshotDeviecName().
    // which may be the "inner" device. Use GetsnapshotDeviecName().
Loading