Call InitPartitionMetadata when resuming an update.
BootControlAndroid::InitPartitionMetadata() should always be called when
starting / resuming an update that uses dynamic partitions. This allows
updating the metadata for the target slot, as well as setting up the
internal state for accessing the dynamic partitions in the target slot.
Bug: 122097567
Test: Run update_engine_unittests on taimen and blueline.
Test: Apply a payload that uses dynamic partitions. Reboot before it
finishes, then resume the update.
Change-Id: I1353f7460a61c0183654b6349689beaa9bf12129
diff --git a/boot_control_android.cc b/boot_control_android.cc
index af1a5f9..421c091 100644
--- a/boot_control_android.cc
+++ b/boot_control_android.cc
@@ -396,7 +396,9 @@
} // namespace
bool BootControlAndroid::InitPartitionMetadata(
- Slot target_slot, const PartitionMetadata& partition_metadata) {
+ Slot target_slot,
+ const PartitionMetadata& partition_metadata,
+ bool update_metadata) {
if (fs_mgr_overlayfs_is_setup()) {
// Non DAP devices can use overlayfs as well.
LOG(WARNING)
@@ -414,11 +416,6 @@
return false;
}
- string target_suffix;
- if (!GetSuffix(target_slot, &target_suffix)) {
- return false;
- }
-
// Although the current build supports dynamic partitions, the given payload
// doesn't use it for target partitions. This could happen when applying a
// retrofit update. Skip updating the partition metadata for the target slot.
@@ -427,6 +424,15 @@
return true;
}
+ if (!update_metadata) {
+ return true;
+ }
+
+ string target_suffix;
+ if (!GetSuffix(target_slot, &target_suffix)) {
+ return false;
+ }
+
// Unmap all the target dynamic partitions because they would become
// inconsistent with the new metadata.
if (!UnmapTargetPartitions(
@@ -434,15 +440,11 @@
return false;
}
- if (!UpdatePartitionMetadata(dynamic_control_.get(),
- source_slot,
- target_slot,
- target_suffix,
- partition_metadata)) {
- return false;
- }
-
- return true;
+ return UpdatePartitionMetadata(dynamic_control_.get(),
+ source_slot,
+ target_slot,
+ target_suffix,
+ partition_metadata);
}
} // namespace chromeos_update_engine
diff --git a/boot_control_android.h b/boot_control_android.h
index aa62e42..a6f33be 100644
--- a/boot_control_android.h
+++ b/boot_control_android.h
@@ -51,8 +51,9 @@
bool MarkSlotUnbootable(BootControlInterface::Slot slot) override;
bool SetActiveBootSlot(BootControlInterface::Slot slot) override;
bool MarkBootSuccessfulAsync(base::Callback<void(bool)> callback) override;
- bool InitPartitionMetadata(
- Slot slot, const PartitionMetadata& partition_metadata) override;
+ bool InitPartitionMetadata(Slot slot,
+ const PartitionMetadata& partition_metadata,
+ bool update_metadata) override;
void Cleanup() override;
private:
diff --git a/boot_control_android_unittest.cc b/boot_control_android_unittest.cc
index 0eb3fe0..bb9903e 100644
--- a/boot_control_android_unittest.cc
+++ b/boot_control_android_unittest.cc
@@ -379,10 +379,12 @@
.Times(0);
}
- bool InitPartitionMetadata(uint32_t slot, PartitionSizes partition_sizes) {
+ bool InitPartitionMetadata(uint32_t slot,
+ PartitionSizes partition_sizes,
+ bool update_metadata = true) {
auto m = partitionSizesToMetadata(partition_sizes);
LOG(INFO) << m;
- return bootctl_.InitPartitionMetadata(slot, m);
+ return bootctl_.InitPartitionMetadata(slot, m, update_metadata);
}
BootControlAndroid bootctl_; // BootControlAndroid under test.
@@ -537,21 +539,74 @@
// Not calling through BootControlAndroidTest::InitPartitionMetadata(), since
// we don't want any default group in the PartitionMetadata.
- EXPECT_TRUE(bootctl_.InitPartitionMetadata(target(), {}));
+ EXPECT_TRUE(bootctl_.InitPartitionMetadata(target(), {}, true));
// Should use dynamic source partitions.
EXPECT_CALL(dynamicControl(), GetState(S("system")))
.Times(1)
.WillOnce(Return(DmDeviceState::ACTIVE));
- string source_device;
- EXPECT_TRUE(bootctl_.GetPartitionDevice("system", source(), &source_device));
- EXPECT_EQ(GetDmDevice(S("system")), source_device);
+ string system_device;
+ EXPECT_TRUE(bootctl_.GetPartitionDevice("system", source(), &system_device));
+ EXPECT_EQ(GetDmDevice(S("system")), system_device);
// Should use static target partitions without querying dynamic control.
EXPECT_CALL(dynamicControl(), GetState(T("system"))).Times(0);
- string target_device;
- EXPECT_TRUE(bootctl_.GetPartitionDevice("system", target(), &target_device));
- EXPECT_EQ(GetDevice(T("system")), target_device);
+ EXPECT_TRUE(bootctl_.GetPartitionDevice("system", target(), &system_device));
+ EXPECT_EQ(GetDevice(T("system")), system_device);
+
+ // Static partition "bar".
+ EXPECT_CALL(dynamicControl(), GetState(S("bar"))).Times(0);
+ std::string bar_device;
+ EXPECT_TRUE(bootctl_.GetPartitionDevice("bar", source(), &bar_device));
+ EXPECT_EQ(GetDevice(S("bar")), bar_device);
+
+ EXPECT_CALL(dynamicControl(), GetState(T("bar"))).Times(0);
+ EXPECT_TRUE(bootctl_.GetPartitionDevice("bar", target(), &bar_device));
+ EXPECT_EQ(GetDevice(T("bar")), bar_device);
+}
+
+TEST_P(BootControlAndroidTestP, GetPartitionDeviceWhenResumingUpdate) {
+ // Both of the two slots contain valid partition metadata, since this is
+ // resuming an update.
+ SetMetadata(source(),
+ {{S("system"), 2_GiB},
+ {S("vendor"), 1_GiB},
+ {T("system"), 2_GiB},
+ {T("vendor"), 1_GiB}});
+ SetMetadata(target(),
+ {{S("system"), 2_GiB},
+ {S("vendor"), 1_GiB},
+ {T("system"), 2_GiB},
+ {T("vendor"), 1_GiB}});
+ EXPECT_CALL(dynamicControl(),
+ StoreMetadata(GetSuperDevice(target()), _, target()))
+ .Times(0);
+ EXPECT_TRUE(InitPartitionMetadata(
+ target(), {{"system", 2_GiB}, {"vendor", 1_GiB}}, false));
+
+ // Dynamic partition "system".
+ EXPECT_CALL(dynamicControl(), GetState(S("system")))
+ .Times(1)
+ .WillOnce(Return(DmDeviceState::ACTIVE));
+ string system_device;
+ EXPECT_TRUE(bootctl_.GetPartitionDevice("system", source(), &system_device));
+ EXPECT_EQ(GetDmDevice(S("system")), system_device);
+
+ EXPECT_CALL(dynamicControl(), GetState(T("system")))
+ .Times(1)
+ .WillOnce(Return(DmDeviceState::ACTIVE));
+ EXPECT_TRUE(bootctl_.GetPartitionDevice("system", target(), &system_device));
+ EXPECT_EQ(GetDmDevice(T("system")), system_device);
+
+ // Static partition "bar".
+ EXPECT_CALL(dynamicControl(), GetState(S("bar"))).Times(0);
+ std::string bar_device;
+ EXPECT_TRUE(bootctl_.GetPartitionDevice("bar", source(), &bar_device));
+ EXPECT_EQ(GetDevice(S("bar")), bar_device);
+
+ EXPECT_CALL(dynamicControl(), GetState(T("bar"))).Times(0);
+ EXPECT_TRUE(bootctl_.GetPartitionDevice("bar", target(), &bar_device));
+ EXPECT_EQ(GetDevice(T("bar")), bar_device);
}
INSTANTIATE_TEST_CASE_P(BootControlAndroidTest,
@@ -695,7 +750,8 @@
target(),
PartitionMetadata{
.groups = {SimpleGroup("android", 3_GiB, "system", 3_GiB),
- SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}}));
+ SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}},
+ true));
}
TEST_P(BootControlAndroidGroupTestP, NotEnoughSpaceForGroup) {
@@ -703,7 +759,8 @@
target(),
PartitionMetadata{
.groups = {SimpleGroup("android", 3_GiB, "system", 1_GiB),
- SimpleGroup("oem", 2_GiB, "vendor", 3_GiB)}}))
+ SimpleGroup("oem", 2_GiB, "vendor", 3_GiB)}},
+ true))
<< "Should not be able to grow over maximum size of group";
}
@@ -711,7 +768,8 @@
EXPECT_FALSE(bootctl_.InitPartitionMetadata(
target(),
PartitionMetadata{.groups = {{.name = "android", .size = 3_GiB},
- {.name = "oem", .size = 3_GiB}}}))
+ {.name = "oem", .size = 3_GiB}}},
+ true))
<< "Should not be able to grow over size of super / 2";
}
@@ -727,12 +785,13 @@
EXPECT_TRUE(bootctl_.InitPartitionMetadata(
target(),
PartitionMetadata{
- .groups = {
- {.name = "android",
- .size = 3_GiB,
- .partitions = {{.name = "system", .size = 2_GiB},
- {.name = "product_services", .size = 1_GiB}}},
- SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}}));
+ .groups = {{.name = "android",
+ .size = 3_GiB,
+ .partitions = {{.name = "system", .size = 2_GiB},
+ {.name = "product_services",
+ .size = 1_GiB}}},
+ SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}},
+ true));
}
TEST_P(BootControlAndroidGroupTestP, RemovePartitionFromGroup) {
@@ -744,7 +803,8 @@
target(),
PartitionMetadata{
.groups = {{.name = "android", .size = 3_GiB, .partitions = {}},
- SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}}));
+ SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}},
+ true));
}
TEST_P(BootControlAndroidGroupTestP, AddGroup) {
@@ -756,10 +816,10 @@
EXPECT_TRUE(bootctl_.InitPartitionMetadata(
target(),
PartitionMetadata{
- .groups = {
- SimpleGroup("android", 2_GiB, "system", 2_GiB),
- SimpleGroup("oem", 1_GiB, "vendor", 1_GiB),
- SimpleGroup("new_group", 2_GiB, "new_partition", 2_GiB)}}));
+ .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB),
+ SimpleGroup("oem", 1_GiB, "vendor", 1_GiB),
+ SimpleGroup("new_group", 2_GiB, "new_partition", 2_GiB)}},
+ true));
}
TEST_P(BootControlAndroidGroupTestP, RemoveGroup) {
@@ -768,7 +828,8 @@
EXPECT_TRUE(bootctl_.InitPartitionMetadata(
target(),
PartitionMetadata{
- .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB)}}));
+ .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB)}},
+ true));
}
TEST_P(BootControlAndroidGroupTestP, ResizeGroup) {
@@ -781,7 +842,8 @@
target(),
PartitionMetadata{
.groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB),
- SimpleGroup("oem", 3_GiB, "vendor", 3_GiB)}}));
+ SimpleGroup("oem", 3_GiB, "vendor", 3_GiB)}},
+ true));
}
INSTANTIATE_TEST_CASE_P(BootControlAndroidTest,
diff --git a/boot_control_chromeos.cc b/boot_control_chromeos.cc
index a82efc7..4fa1268 100644
--- a/boot_control_chromeos.cc
+++ b/boot_control_chromeos.cc
@@ -303,7 +303,9 @@
}
bool BootControlChromeOS::InitPartitionMetadata(
- Slot slot, const PartitionMetadata& partition_metadata) {
+ Slot slot,
+ const PartitionMetadata& partition_metadata,
+ bool update_metadata) {
return true;
}
diff --git a/boot_control_chromeos.h b/boot_control_chromeos.h
index c474d6f..f3682e9 100644
--- a/boot_control_chromeos.h
+++ b/boot_control_chromeos.h
@@ -50,8 +50,9 @@
bool MarkSlotUnbootable(BootControlInterface::Slot slot) override;
bool SetActiveBootSlot(BootControlInterface::Slot slot) override;
bool MarkBootSuccessfulAsync(base::Callback<void(bool)> callback) override;
- bool InitPartitionMetadata(
- Slot slot, const PartitionMetadata& partition_metadata) override;
+ bool InitPartitionMetadata(Slot slot,
+ const PartitionMetadata& partition_metadata,
+ bool update_metadata) override;
void Cleanup() override;
private:
diff --git a/common/boot_control_interface.h b/common/boot_control_interface.h
index 43517ce..392d785 100644
--- a/common/boot_control_interface.h
+++ b/common/boot_control_interface.h
@@ -66,7 +66,9 @@
// Determines the block device for the given partition name and slot number.
// The |slot| number must be between 0 and GetNumSlots() - 1 and the
// |partition_name| is a platform-specific name that identifies a partition on
- // every slot. On success, returns true and stores the block device in
+ // every slot. In order to access the dynamic partitions in the target slot,
+ // InitPartitionMetadata() must be called (once per payload) prior to calling
+ // this function. On success, returns true and stores the block device in
// |device|.
virtual bool GetPartitionDevice(const std::string& partition_name,
Slot slot,
@@ -92,14 +94,14 @@
// of the operation.
virtual bool MarkBootSuccessfulAsync(base::Callback<void(bool)> callback) = 0;
- // Initialize metadata of underlying partitions for a given |slot|.
- // Ensure that all updateable groups with the suffix GetSuffix(|slot|) exactly
- // matches the layout specified in |partition_metadata|. Ensure that
- // partitions at the specified |slot| has a given size and updateable group,
- // as specified by |partition_metadata|. Sizes must be aligned to the logical
- // block size of the super partition.
+ // Initializes the metadata of the underlying partitions for a given |slot|
+ // and sets up the states for accessing dynamic partitions.
+ // |partition_metadata| will be written to the specified |slot| if
+ // |update_metadata| is set.
virtual bool InitPartitionMetadata(
- Slot slot, const PartitionMetadata& partition_metadata) = 0;
+ Slot slot,
+ const PartitionMetadata& partition_metadata,
+ bool update_metadata) = 0;
// Do necessary clean-up operations after the whole update.
virtual void Cleanup() = 0;
diff --git a/common/boot_control_stub.cc b/common/boot_control_stub.cc
index ca880d4..0fe8a98 100644
--- a/common/boot_control_stub.cc
+++ b/common/boot_control_stub.cc
@@ -60,7 +60,9 @@
}
bool BootControlStub::InitPartitionMetadata(
- Slot slot, const PartitionMetadata& partition_metadata) {
+ Slot slot,
+ const PartitionMetadata& partition_metadata,
+ bool update_metadata) {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return false;
}
diff --git a/common/boot_control_stub.h b/common/boot_control_stub.h
index 0950997..8dfaffc 100644
--- a/common/boot_control_stub.h
+++ b/common/boot_control_stub.h
@@ -45,8 +45,9 @@
bool MarkSlotUnbootable(BootControlInterface::Slot slot) override;
bool SetActiveBootSlot(BootControlInterface::Slot slot) override;
bool MarkBootSuccessfulAsync(base::Callback<void(bool)> callback) override;
- bool InitPartitionMetadata(
- Slot slot, const PartitionMetadata& partition_metadata) override;
+ bool InitPartitionMetadata(Slot slot,
+ const PartitionMetadata& partition_metadata,
+ bool update_metadata) override;
void Cleanup() override;
private:
diff --git a/common/constants.cc b/common/constants.cc
index 3ae7a60..310f1b2 100644
--- a/common/constants.cc
+++ b/common/constants.cc
@@ -37,8 +37,8 @@
const char kPrefsDailyMetricsLastReportedAt[] =
"daily-metrics-last-reported-at";
const char kPrefsDeltaUpdateFailures[] = "delta-update-failures";
-const char kPrefsDynamicPartitionMetadataInitialized[] =
- "dynamic-partition-metadata-initialized";
+const char kPrefsDynamicPartitionMetadataUpdated[] =
+ "dynamic-partition-metadata-updated";
const char kPrefsFullPayloadAttemptNumber[] = "full-payload-attempt-number";
const char kPrefsInstallDateDays[] = "install-date-days";
const char kPrefsLastActivePingDay[] = "last-active-ping-day";
diff --git a/common/constants.h b/common/constants.h
index 61e5ddd..d5a8ae3 100644
--- a/common/constants.h
+++ b/common/constants.h
@@ -41,7 +41,7 @@
extern const char kPrefsCurrentUrlIndex[];
extern const char kPrefsDailyMetricsLastReportedAt[];
extern const char kPrefsDeltaUpdateFailures[];
-extern const char kPrefsDynamicPartitionMetadataInitialized[];
+extern const char kPrefsDynamicPartitionMetadataUpdated[];
extern const char kPrefsFullPayloadAttemptNumber[];
extern const char kPrefsInstallDateDays[];
extern const char kPrefsLastActivePingDay[];
diff --git a/common/fake_boot_control.h b/common/fake_boot_control.h
index 513c149..ba975a2 100644
--- a/common/fake_boot_control.h
+++ b/common/fake_boot_control.h
@@ -74,8 +74,9 @@
return true;
}
- bool InitPartitionMetadata(
- Slot slot, const PartitionMetadata& partition_metadata) override {
+ bool InitPartitionMetadata(Slot slot,
+ const PartitionMetadata& partition_metadata,
+ bool update_metadata) override {
return true;
}
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index 0711ac6..1bfdf9c 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -935,14 +935,6 @@
}
bool DeltaPerformer::InitPartitionMetadata() {
- bool metadata_initialized;
- if (prefs_->GetBoolean(kPrefsDynamicPartitionMetadataInitialized,
- &metadata_initialized) &&
- metadata_initialized) {
- LOG(INFO) << "Skipping InitPartitionMetadata.";
- return true;
- }
-
BootControlInterface::PartitionMetadata partition_metadata;
if (manifest_.has_dynamic_partition_metadata()) {
std::map<string, uint64_t> partition_sizes;
@@ -970,14 +962,16 @@
}
}
- if (!boot_control_->InitPartitionMetadata(install_plan_->target_slot,
- partition_metadata)) {
+ bool metadata_updated = false;
+ prefs_->GetBoolean(kPrefsDynamicPartitionMetadataUpdated, &metadata_updated);
+ if (!boot_control_->InitPartitionMetadata(
+ install_plan_->target_slot, partition_metadata, !metadata_updated)) {
LOG(ERROR) << "Unable to initialize partition metadata for slot "
<< BootControlInterface::SlotName(install_plan_->target_slot);
return false;
}
TEST_AND_RETURN_FALSE(
- prefs_->SetBoolean(kPrefsDynamicPartitionMetadataInitialized, true));
+ prefs_->SetBoolean(kPrefsDynamicPartitionMetadataUpdated, true));
LOG(INFO) << "InitPartitionMetadata done.";
return true;
@@ -1901,7 +1895,7 @@
prefs->SetInt64(kPrefsResumedUpdateFailures, 0);
prefs->Delete(kPrefsPostInstallSucceeded);
prefs->Delete(kPrefsVerityWritten);
- prefs->Delete(kPrefsDynamicPartitionMetadataInitialized);
+ prefs->Delete(kPrefsDynamicPartitionMetadataUpdated);
}
return true;
}
diff --git a/payload_consumer/delta_performer_integration_test.cc b/payload_consumer/delta_performer_integration_test.cc
index 9368e11..0912764 100644
--- a/payload_consumer/delta_performer_integration_test.cc
+++ b/payload_consumer/delta_performer_integration_test.cc
@@ -697,7 +697,7 @@
.WillRepeatedly(Return(true));
EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignedSHA256Context, _))
.WillRepeatedly(Return(true));
- EXPECT_CALL(prefs, SetBoolean(kPrefsDynamicPartitionMetadataInitialized, _))
+ EXPECT_CALL(prefs, SetBoolean(kPrefsDynamicPartitionMetadataUpdated, _))
.WillRepeatedly(Return(true));
if (op_hash_test == kValidOperationData && signature_test != kSignatureNone) {
EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignatureBlob, _))