update_engine resize dynamic partitions during OTA.
update_engine uses device mapper to resize dynamic partitions
before opening the devices to apply the update.
* DeltaPerformer calls BootControlInterface::InitPartitionMetadata
when parsing the update manifest. The implementation for
BootControlAndroid::InitPartitionMetadata does the following
if sizes for dynamic partitions are incorrect (assuming updating
from slot A to B):
* Load metadata from metadata slot A
* Delete all extents of partitions at slot B (with _b suffix)
* Add extents for partitions at slot B
* Write metadata to metadata slot B
* Re-map all partitions at slot B using metadata slot B with
force_writable = true
* BootControlAndroid::GetPartitionDevice() checks device-mapper
before returning static partitions.
* PostinstallRunnerAction::Cleanup calls BootControlInterface::Cleanup
which unmaps all partitions at slot B.
A partition "foo" is considered dynamic if foo_a exists as a dynamic
partition OR foo_b does NOT exist as a static partition.
Bug: 110717529
Test: manual ota
Test: update_engine_unittests --gtest_filter=*BootControlAndroid*
Change-Id: I50f410b486a874242663624801c3694151bdda18
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index e700255..30fe763 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -21,6 +21,7 @@
#include <algorithm>
#include <cstring>
+#include <map>
#include <memory>
#include <string>
#include <utility>
@@ -639,9 +640,11 @@
return false;
}
- if (!OpenCurrentPartition()) {
- *error = ErrorCode::kInstallDeviceOpenError;
- return false;
+ if (next_operation_num_ < acc_num_operations_[current_partition_]) {
+ if (!OpenCurrentPartition()) {
+ *error = ErrorCode::kInstallDeviceOpenError;
+ return false;
+ }
}
if (next_operation_num_ > 0)
@@ -658,9 +661,12 @@
// We know there are more operations to perform because we didn't reach the
// |num_total_operations_| limit yet.
- while (next_operation_num_ >= acc_num_operations_[current_partition_]) {
+ if (next_operation_num_ >= acc_num_operations_[current_partition_]) {
CloseCurrentPartition();
- current_partition_++;
+ // Skip until there are operations for current_partition_.
+ while (next_operation_num_ >= acc_num_operations_[current_partition_]) {
+ current_partition_++;
+ }
if (!OpenCurrentPartition()) {
*error = ErrorCode::kInstallDeviceOpenError;
return false;
@@ -912,6 +918,20 @@
install_plan_->partitions.push_back(install_part);
}
+ if (install_plan_->target_slot != BootControlInterface::kInvalidSlot) {
+ BootControlInterface::PartitionSizes partition_sizes;
+ for (const InstallPlan::Partition& partition : install_plan_->partitions) {
+ partition_sizes.emplace(partition.name, partition.target_size);
+ }
+ if (!boot_control_->InitPartitionMetadata(install_plan_->target_slot,
+ partition_sizes)) {
+ LOG(ERROR) << "Unable to initialize partition metadata for slot "
+ << BootControlInterface::SlotName(install_plan_->target_slot);
+ *error = ErrorCode::kInstallDeviceOpenError;
+ return false;
+ }
+ }
+
if (!install_plan_->LoadPartitionsFromSlots(boot_control_)) {
LOG(ERROR) << "Unable to determine all the partition devices.";
*error = ErrorCode::kInstallDeviceOpenError;
diff --git a/payload_consumer/filesystem_verifier_action.cc b/payload_consumer/filesystem_verifier_action.cc
index a5e1e61..d74d81d 100644
--- a/payload_consumer/filesystem_verifier_action.cc
+++ b/payload_consumer/filesystem_verifier_action.cc
@@ -98,13 +98,25 @@
partition_size_ = partition.target_size;
break;
}
- LOG(INFO) << "Hashing partition " << partition_index_ << " ("
- << partition.name << ") on device " << part_path;
+
if (part_path.empty()) {
+ if (partition_size_ == 0) {
+ LOG(INFO) << "Skip hashing partition " << partition_index_ << " ("
+ << partition.name << ") because size is 0.";
+ partition_index_++;
+ StartPartitionHashing();
+ return;
+ }
+ LOG(ERROR) << "Cannot hash partition " << partition_index_ << " ("
+ << partition.name
+ << ") because its device path cannot be determined.";
Cleanup(ErrorCode::kFilesystemVerifierError);
return;
}
+ LOG(INFO) << "Hashing partition " << partition_index_ << " ("
+ << partition.name << ") on device " << part_path;
+
brillo::ErrorPtr error;
src_stream_ = brillo::FileStream::Open(
base::FilePath(part_path),
diff --git a/payload_consumer/install_plan.cc b/payload_consumer/install_plan.cc
index 45112d6..561e294 100644
--- a/payload_consumer/install_plan.cc
+++ b/payload_consumer/install_plan.cc
@@ -103,7 +103,8 @@
partition.source_path.clear();
}
- if (target_slot != BootControlInterface::kInvalidSlot) {
+ if (target_slot != BootControlInterface::kInvalidSlot &&
+ partition.target_size > 0) {
result = boot_control->GetPartitionDevice(
partition.name, target_slot, &partition.target_path) && result;
} else {