Loading fastboot/device/commands.cpp +41 −17 Original line number Diff line number Diff line Loading @@ -194,23 +194,6 @@ bool DownloadHandler(FastbootDevice* device, const std::vector<std::string>& arg 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) { if (args.size() < 2) { return device->WriteStatus(FastbootResult::FAIL, "Missing slot argument"); Loading Loading @@ -440,6 +423,11 @@ bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::strin if (!partition) { 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)) { return device->WriteFail("Not enough space to resize partition"); } Loading @@ -449,6 +437,42 @@ bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::strin 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) { if (args.size() < 2) { return device->WriteFail("Invalid arguments"); Loading fs_mgr/fs_mgr_dm_linear.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -79,7 +79,7 @@ static bool GetPhysicalPartitionDevicePath(const IPartitionOpener& opener, 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, DmTable* table) { uint64_t sector = 0; Loading fs_mgr/include/fs_mgr_dm_linear.h +5 −0 Original line number Diff line number Diff line Loading @@ -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. 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 android Loading fs_mgr/liblp/include/liblp/builder.h +1 −0 Original line number Diff line number Diff line Loading @@ -123,6 +123,7 @@ class Partition final { const std::string& name() const { return name_; } const std::string& group_name() const { return group_name_; } 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_; } uint64_t size() const { return size_; } Loading fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +25 −7 Original line number Diff line number Diff line Loading @@ -66,7 +66,11 @@ enum class UpdateState : unsigned int { MergeCompleted, // 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 { Loading @@ -82,6 +86,7 @@ class SnapshotManager final { virtual std::string GetGsidDir() const = 0; virtual std::string GetMetadataDir() const = 0; virtual std::string GetSlotSuffix() const = 0; virtual std::string GetSuperDevice(uint32_t slot) const = 0; virtual const IPartitionOpener& GetPartitionOpener() const = 0; }; Loading Loading @@ -117,12 +122,15 @@ class SnapshotManager final { // update has been marked successful after booting. bool InitiateMerge(); // Wait for the current merge to finish, then perform cleanup when it // completes. It is necessary to call this after InitiateMerge(), or when // a merge state is detected during boot. // Perform any necessary post-boot actions. This should be run soon after // /data is mounted. // // 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 // that a merge is in progress: // Note that after calling this, GetUpdateState() may still return that a // merge is in progress: // MergeFailed indicates that a fatal error occurred. WaitForMerge() may // 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. Loading @@ -135,7 +143,7 @@ class SnapshotManager final { // // MergeCompleted indicates that the update has fully completed. // GetUpdateState will return None, and a new update can begin. UpdateState WaitForMerge(); UpdateState ProcessUpdateState(); // Find the status of the current update, if any. // Loading @@ -158,6 +166,7 @@ class SnapshotManager final { FRIEND_TEST(SnapshotTest, CreateSnapshot); FRIEND_TEST(SnapshotTest, FirstStageMountAfterRollback); FRIEND_TEST(SnapshotTest, FirstStageMountAndMerge); FRIEND_TEST(SnapshotTest, FlashSuperDuringMerge); FRIEND_TEST(SnapshotTest, FlashSuperDuringUpdate); FRIEND_TEST(SnapshotTest, MapPartialSnapshot); FRIEND_TEST(SnapshotTest, MapSnapshot); Loading Loading @@ -245,6 +254,14 @@ class SnapshotManager final { // List the known snapshot names. 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. std::unique_ptr<LockedFile> OpenStateFile(int open_flags, int lock_flags); std::unique_ptr<LockedFile> LockShared(); Loading Loading @@ -272,6 +289,7 @@ class SnapshotManager final { bool MarkSnapshotMergeCompleted(LockedFile* snapshot_lock, const std::string& snapshot_name); void AcknowledgeMergeSuccess(LockedFile* lock); void AcknowledgeMergeFailure(); bool IsCancelledSnapshot(const std::string& snapshot_name); // Note that these require the name of the device containing the snapshot, // which may be the "inner" device. Use GetsnapshotDeviecName(). Loading Loading
fastboot/device/commands.cpp +41 −17 Original line number Diff line number Diff line Loading @@ -194,23 +194,6 @@ bool DownloadHandler(FastbootDevice* device, const std::vector<std::string>& arg 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) { if (args.size() < 2) { return device->WriteStatus(FastbootResult::FAIL, "Missing slot argument"); Loading Loading @@ -440,6 +423,11 @@ bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::strin if (!partition) { 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)) { return device->WriteFail("Not enough space to resize partition"); } Loading @@ -449,6 +437,42 @@ bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::strin 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) { if (args.size() < 2) { return device->WriteFail("Invalid arguments"); Loading
fs_mgr/fs_mgr_dm_linear.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -79,7 +79,7 @@ static bool GetPhysicalPartitionDevicePath(const IPartitionOpener& opener, 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, DmTable* table) { uint64_t sector = 0; Loading
fs_mgr/include/fs_mgr_dm_linear.h +5 −0 Original line number Diff line number Diff line Loading @@ -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. 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 android Loading
fs_mgr/liblp/include/liblp/builder.h +1 −0 Original line number Diff line number Diff line Loading @@ -123,6 +123,7 @@ class Partition final { const std::string& name() const { return name_; } const std::string& group_name() const { return group_name_; } 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_; } uint64_t size() const { return size_; } Loading
fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +25 −7 Original line number Diff line number Diff line Loading @@ -66,7 +66,11 @@ enum class UpdateState : unsigned int { MergeCompleted, // 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 { Loading @@ -82,6 +86,7 @@ class SnapshotManager final { virtual std::string GetGsidDir() const = 0; virtual std::string GetMetadataDir() const = 0; virtual std::string GetSlotSuffix() const = 0; virtual std::string GetSuperDevice(uint32_t slot) const = 0; virtual const IPartitionOpener& GetPartitionOpener() const = 0; }; Loading Loading @@ -117,12 +122,15 @@ class SnapshotManager final { // update has been marked successful after booting. bool InitiateMerge(); // Wait for the current merge to finish, then perform cleanup when it // completes. It is necessary to call this after InitiateMerge(), or when // a merge state is detected during boot. // Perform any necessary post-boot actions. This should be run soon after // /data is mounted. // // 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 // that a merge is in progress: // Note that after calling this, GetUpdateState() may still return that a // merge is in progress: // MergeFailed indicates that a fatal error occurred. WaitForMerge() may // 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. Loading @@ -135,7 +143,7 @@ class SnapshotManager final { // // MergeCompleted indicates that the update has fully completed. // GetUpdateState will return None, and a new update can begin. UpdateState WaitForMerge(); UpdateState ProcessUpdateState(); // Find the status of the current update, if any. // Loading @@ -158,6 +166,7 @@ class SnapshotManager final { FRIEND_TEST(SnapshotTest, CreateSnapshot); FRIEND_TEST(SnapshotTest, FirstStageMountAfterRollback); FRIEND_TEST(SnapshotTest, FirstStageMountAndMerge); FRIEND_TEST(SnapshotTest, FlashSuperDuringMerge); FRIEND_TEST(SnapshotTest, FlashSuperDuringUpdate); FRIEND_TEST(SnapshotTest, MapPartialSnapshot); FRIEND_TEST(SnapshotTest, MapSnapshot); Loading Loading @@ -245,6 +254,14 @@ class SnapshotManager final { // List the known snapshot names. 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. std::unique_ptr<LockedFile> OpenStateFile(int open_flags, int lock_flags); std::unique_ptr<LockedFile> LockShared(); Loading Loading @@ -272,6 +289,7 @@ class SnapshotManager final { bool MarkSnapshotMergeCompleted(LockedFile* snapshot_lock, const std::string& snapshot_name); void AcknowledgeMergeSuccess(LockedFile* lock); void AcknowledgeMergeFailure(); bool IsCancelledSnapshot(const std::string& snapshot_name); // Note that these require the name of the device containing the snapshot, // which may be the "inner" device. Use GetsnapshotDeviecName(). Loading