Merge "Refactor update status management as protobuf"
This commit is contained in:
commit
5c63dc9322
4 changed files with 111 additions and 45 deletions
|
@ -127,6 +127,7 @@ cc_library_static {
|
|||
"include_test",
|
||||
],
|
||||
srcs: [
|
||||
"android/snapshot/snapshot.proto",
|
||||
"test_helpers.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
|
|
|
@ -85,3 +85,49 @@ message SnapshotStatus {
|
|||
// This is non-zero when |state| == MERGING or MERGE_COMPLETED.
|
||||
uint64 metadata_sectors = 8;
|
||||
}
|
||||
|
||||
// Next: 8
|
||||
enum UpdateState {
|
||||
// No update or merge is in progress.
|
||||
None = 0;
|
||||
|
||||
// An update is applying; snapshots may already exist.
|
||||
Initiated = 1;
|
||||
|
||||
// An update is pending, but has not been successfully booted yet.
|
||||
Unverified = 2;
|
||||
|
||||
// The kernel is merging in the background.
|
||||
Merging = 3;
|
||||
|
||||
// Post-merge cleanup steps could not be completed due to a transient
|
||||
// error, but the next reboot will finish any pending operations.
|
||||
MergeNeedsReboot = 4;
|
||||
|
||||
// Merging is complete, and needs to be acknowledged.
|
||||
MergeCompleted = 5;
|
||||
|
||||
// Merging failed due to an unrecoverable error.
|
||||
MergeFailed = 6;
|
||||
|
||||
// The update was implicitly cancelled, either by a rollback or a flash
|
||||
// operation via fastboot. This state can only be returned by WaitForMerge.
|
||||
Cancelled = 7;
|
||||
};
|
||||
|
||||
// Next: 5
|
||||
message SnapshotUpdateStatus {
|
||||
UpdateState state = 1;
|
||||
|
||||
// Total number of sectors allocated in the COW files before performing the
|
||||
// merge operation. This field is used to keep track of the total number
|
||||
// of sectors modified to monitor and show the progress of the merge during
|
||||
// an update.
|
||||
uint64 sectors_allocated = 2;
|
||||
|
||||
// Total number of sectors of all the snapshot devices.
|
||||
uint64 total_sectors = 3;
|
||||
|
||||
// Sectors allocated for metadata in all the snapshot devices.
|
||||
uint64 metadata_sectors = 4;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <android/snapshot/snapshot.pb.h>
|
||||
#include <fs_mgr_dm_linear.h>
|
||||
#include <libdm/dm.h>
|
||||
#include <libfiemap/image_manager.h>
|
||||
|
@ -80,35 +81,6 @@ enum class CreateResult : unsigned int {
|
|||
NOT_CREATED,
|
||||
};
|
||||
|
||||
enum class UpdateState : unsigned int {
|
||||
// No update or merge is in progress.
|
||||
None,
|
||||
|
||||
// An update is applying; snapshots may already exist.
|
||||
Initiated,
|
||||
|
||||
// An update is pending, but has not been successfully booted yet.
|
||||
Unverified,
|
||||
|
||||
// The kernel is merging in the background.
|
||||
Merging,
|
||||
|
||||
// Post-merge cleanup steps could not be completed due to a transient
|
||||
// error, but the next reboot will finish any pending operations.
|
||||
MergeNeedsReboot,
|
||||
|
||||
// Merging is complete, and needs to be acknowledged.
|
||||
MergeCompleted,
|
||||
|
||||
// Merging failed due to an unrecoverable error.
|
||||
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
|
||||
};
|
||||
std::ostream& operator<<(std::ostream& os, UpdateState state);
|
||||
|
||||
class SnapshotManager final {
|
||||
using CreateLogicalPartitionParams = android::fs_mgr::CreateLogicalPartitionParams;
|
||||
using IPartitionOpener = android::fs_mgr::IPartitionOpener;
|
||||
|
@ -433,7 +405,9 @@ class SnapshotManager final {
|
|||
|
||||
// Interact with /metadata/ota/state.
|
||||
UpdateState ReadUpdateState(LockedFile* file);
|
||||
SnapshotUpdateStatus ReadSnapshotUpdateStatus(LockedFile* file);
|
||||
bool WriteUpdateState(LockedFile* file, UpdateState state);
|
||||
bool WriteSnapshotUpdateStatus(LockedFile* file, const SnapshotUpdateStatus& status);
|
||||
std::string GetStateFilePath() const;
|
||||
|
||||
// Helpers for merging.
|
||||
|
|
|
@ -560,9 +560,26 @@ bool SnapshotManager::InitiateMerge() {
|
|||
}
|
||||
}
|
||||
|
||||
DmTargetSnapshot::Status initial_target_values = {};
|
||||
for (const auto& snapshot : snapshots) {
|
||||
DmTargetSnapshot::Status current_status;
|
||||
if (!QuerySnapshotStatus(snapshot, nullptr, ¤t_status)) {
|
||||
return false;
|
||||
}
|
||||
initial_target_values.sectors_allocated += current_status.sectors_allocated;
|
||||
initial_target_values.total_sectors += current_status.total_sectors;
|
||||
initial_target_values.metadata_sectors += current_status.metadata_sectors;
|
||||
}
|
||||
|
||||
SnapshotUpdateStatus initial_status;
|
||||
initial_status.set_state(UpdateState::Merging);
|
||||
initial_status.set_sectors_allocated(initial_target_values.sectors_allocated);
|
||||
initial_status.set_total_sectors(initial_target_values.total_sectors);
|
||||
initial_status.set_metadata_sectors(initial_target_values.metadata_sectors);
|
||||
|
||||
// Point of no return - mark that we're starting a merge. From now on every
|
||||
// snapshot must be a merge target.
|
||||
if (!WriteUpdateState(lock.get(), UpdateState::Merging)) {
|
||||
if (!WriteSnapshotUpdateStatus(lock.get(), initial_status)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1643,15 +1660,7 @@ std::unique_ptr<SnapshotManager::LockedFile> SnapshotManager::LockExclusive() {
|
|||
return OpenLock(LOCK_EX);
|
||||
}
|
||||
|
||||
UpdateState SnapshotManager::ReadUpdateState(LockedFile* lock) {
|
||||
CHECK(lock);
|
||||
|
||||
std::string contents;
|
||||
if (!android::base::ReadFileToString(GetStateFilePath(), &contents)) {
|
||||
PLOG(ERROR) << "Read state file failed";
|
||||
return UpdateState::None;
|
||||
}
|
||||
|
||||
static UpdateState UpdateStateFromString(const std::string& contents) {
|
||||
if (contents.empty() || contents == "none") {
|
||||
return UpdateState::None;
|
||||
} else if (contents == "initiated") {
|
||||
|
@ -1694,18 +1703,54 @@ std::ostream& operator<<(std::ostream& os, UpdateState state) {
|
|||
}
|
||||
}
|
||||
|
||||
UpdateState SnapshotManager::ReadUpdateState(LockedFile* lock) {
|
||||
SnapshotUpdateStatus status = ReadSnapshotUpdateStatus(lock);
|
||||
return status.state();
|
||||
}
|
||||
|
||||
SnapshotUpdateStatus SnapshotManager::ReadSnapshotUpdateStatus(LockedFile* lock) {
|
||||
CHECK(lock);
|
||||
|
||||
SnapshotUpdateStatus status = {};
|
||||
std::string contents;
|
||||
if (!android::base::ReadFileToString(GetStateFilePath(), &contents)) {
|
||||
PLOG(ERROR) << "Read state file failed";
|
||||
status.set_state(UpdateState::None);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!status.ParseFromString(contents)) {
|
||||
LOG(WARNING) << "Unable to parse state file as SnapshotUpdateStatus, using the old format";
|
||||
|
||||
// Try to rollback to legacy file to support devices that are
|
||||
// currently using the old file format.
|
||||
// TODO(b/147409432)
|
||||
status.set_state(UpdateStateFromString(contents));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool SnapshotManager::WriteUpdateState(LockedFile* lock, UpdateState state) {
|
||||
SnapshotUpdateStatus status = {};
|
||||
status.set_state(state);
|
||||
return WriteSnapshotUpdateStatus(lock, status);
|
||||
}
|
||||
|
||||
bool SnapshotManager::WriteSnapshotUpdateStatus(LockedFile* lock,
|
||||
const SnapshotUpdateStatus& status) {
|
||||
CHECK(lock);
|
||||
CHECK(lock->lock_mode() == LOCK_EX);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << state;
|
||||
std::string contents = ss.str();
|
||||
if (contents.empty()) return false;
|
||||
std::string contents;
|
||||
if (!status.SerializeToString(&contents)) {
|
||||
LOG(ERROR) << "Unable to serialize SnapshotUpdateStatus.";
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef LIBSNAPSHOT_USE_HAL
|
||||
auto merge_status = MergeStatus::UNKNOWN;
|
||||
switch (state) {
|
||||
switch (status.state()) {
|
||||
// The needs-reboot and completed cases imply that /data and /metadata
|
||||
// can be safely wiped, so we don't report a merge status.
|
||||
case UpdateState::None:
|
||||
|
@ -1724,7 +1769,7 @@ bool SnapshotManager::WriteUpdateState(LockedFile* lock, UpdateState state) {
|
|||
default:
|
||||
// Note that Cancelled flows to here - it is never written, since
|
||||
// it only communicates a transient state to the caller.
|
||||
LOG(ERROR) << "Unexpected update status: " << state;
|
||||
LOG(ERROR) << "Unexpected update status: " << status.state();
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue