Only skip operation on snapshot partitions
On Virtual A/B devices, don't skip SOURCE_COPY on
static partitions.
Test: update_engine_unittest
Test: incremental update to self
Change-Id: I5c93b501e09f50f559151eb77d83052373c90d0d
diff --git a/common/dynamic_partition_control_interface.h b/common/dynamic_partition_control_interface.h
index 39daf75..c17bafb 100644
--- a/common/dynamic_partition_control_interface.h
+++ b/common/dynamic_partition_control_interface.h
@@ -50,8 +50,12 @@
// Return the feature flags of Virtual A/B on this device.
virtual FeatureFlag GetVirtualAbFeatureFlag() = 0;
- // Checks if the provided InstallOperation can be skipped on this device.
- virtual bool ShouldSkipOperation(const InstallOperation& operation) = 0;
+ // Checks if |operation| can be skipped on the given partition.
+ // |partition_name| should not have the slot suffix; implementation of
+ // DynamicPartitionControlInterface checks partition at the target slot
+ // previously set with PreparePartitionsForUpdate().
+ virtual bool ShouldSkipOperation(const std::string& partition_name,
+ const InstallOperation& operation) = 0;
// Do necessary cleanups before destroying the object.
virtual void Cleanup() = 0;
diff --git a/common/dynamic_partition_control_stub.cc b/common/dynamic_partition_control_stub.cc
index 06f6b3c..bc792c8 100644
--- a/common/dynamic_partition_control_stub.cc
+++ b/common/dynamic_partition_control_stub.cc
@@ -33,7 +33,7 @@
}
bool DynamicPartitionControlStub::ShouldSkipOperation(
- const InstallOperation& operation) {
+ const std::string& partition_name, const InstallOperation& operation) {
return false;
}
diff --git a/common/dynamic_partition_control_stub.h b/common/dynamic_partition_control_stub.h
index c62758b..1704f05 100644
--- a/common/dynamic_partition_control_stub.h
+++ b/common/dynamic_partition_control_stub.h
@@ -29,7 +29,8 @@
public:
FeatureFlag GetDynamicPartitionsFeatureFlag() override;
FeatureFlag GetVirtualAbFeatureFlag() override;
- bool ShouldSkipOperation(const InstallOperation& operation) override;
+ bool ShouldSkipOperation(const std::string& partition_name,
+ const InstallOperation& operation) override;
void Cleanup() override;
bool PreparePartitionsForUpdate(uint32_t source_slot,
uint32_t target_slot,
diff --git a/dynamic_partition_control_android.cc b/dynamic_partition_control_android.cc
index 4414e4b..4ad02c7 100644
--- a/dynamic_partition_control_android.cc
+++ b/dynamic_partition_control_android.cc
@@ -106,11 +106,13 @@
}
bool DynamicPartitionControlAndroid::ShouldSkipOperation(
- const InstallOperation& operation) {
+ const std::string& partition_name, const InstallOperation& operation) {
switch (operation.type()) {
case InstallOperation::SOURCE_COPY:
return target_supports_snapshot_ &&
GetVirtualAbFeatureFlag().IsEnabled() &&
+ mapped_devices_.count(partition_name +
+ SlotSuffixForSlotNumber(target_slot_)) > 0 &&
SourceCopyOperationIsClone(operation);
break;
default:
@@ -371,6 +373,9 @@
uint32_t target_slot,
const DeltaArchiveManifest& manifest,
bool update) {
+ source_slot_ = source_slot;
+ target_slot_ = target_slot;
+
if (fs_mgr_overlayfs_is_setup()) {
// Non DAP devices can use overlayfs as well.
LOG(WARNING)
@@ -675,4 +680,9 @@
return DynamicPartitionDeviceStatus::ERROR;
}
+void DynamicPartitionControlAndroid::set_fake_mapped_devices(
+ const std::set<std::string>& fake) {
+ mapped_devices_ = fake;
+}
+
} // namespace chromeos_update_engine
diff --git a/dynamic_partition_control_android.h b/dynamic_partition_control_android.h
index 2bfbcb1..13fbb1a 100644
--- a/dynamic_partition_control_android.h
+++ b/dynamic_partition_control_android.h
@@ -35,7 +35,8 @@
~DynamicPartitionControlAndroid();
FeatureFlag GetDynamicPartitionsFeatureFlag() override;
FeatureFlag GetVirtualAbFeatureFlag() override;
- bool ShouldSkipOperation(const InstallOperation& operation) override;
+ bool ShouldSkipOperation(const std::string& partition_name,
+ const InstallOperation& operation) override;
void Cleanup() override;
bool PreparePartitionsForUpdate(uint32_t source_slot,
@@ -122,6 +123,8 @@
// metadata) for a given slot.
virtual std::string GetSuperPartitionName(uint32_t slot);
+ virtual void set_fake_mapped_devices(const std::set<std::string>& fake);
+
private:
friend class DynamicPartitionControlAndroidTest;
@@ -182,6 +185,8 @@
// Whether the target partitions should be loaded as dynamic partitions. Set
// by PreparePartitionsForUpdate() per each update.
bool is_target_dynamic_ = false;
+ uint32_t source_slot_ = UINT32_MAX;
+ uint32_t target_slot_ = UINT32_MAX;
DISALLOW_COPY_AND_ASSIGN(DynamicPartitionControlAndroid);
};
diff --git a/dynamic_partition_control_android_unittest.cc b/dynamic_partition_control_android_unittest.cc
index fc3d38c..207a97e 100644
--- a/dynamic_partition_control_android_unittest.cc
+++ b/dynamic_partition_control_android_unittest.cc
@@ -620,18 +620,22 @@
<< "Should not be able to apply to current slot.";
}
-TEST_F(DynamicPartitionControlAndroidTest, ShouldSkipOperationTest) {
+TEST_P(DynamicPartitionControlAndroidTestP, ShouldSkipOperationTest) {
+ ASSERT_TRUE(dynamicControl().PreparePartitionsForUpdate(
+ source(), target(), PartitionSizesToManifest({{"foo", 4_MiB}}), false));
+ dynamicControl().set_fake_mapped_devices({T("foo")});
+
InstallOperation iop;
Extent *se, *de;
// Not a SOURCE_COPY operation, cannot skip.
iop.set_type(InstallOperation::REPLACE);
- EXPECT_FALSE(dynamicControl().ShouldSkipOperation(iop));
+ EXPECT_FALSE(dynamicControl().ShouldSkipOperation("foo", iop));
iop.set_type(InstallOperation::SOURCE_COPY);
// By default GetVirtualAbFeatureFlag is disabled. Cannot skip operation.
- EXPECT_FALSE(dynamicControl().ShouldSkipOperation(iop));
+ EXPECT_FALSE(dynamicControl().ShouldSkipOperation("foo", iop));
// Enable GetVirtualAbFeatureFlag in the mock interface.
ON_CALL(dynamicControl(), GetVirtualAbFeatureFlag())
@@ -639,19 +643,19 @@
// By default target_supports_snapshot_ is set to false. Cannot skip
// operation.
- EXPECT_FALSE(dynamicControl().ShouldSkipOperation(iop));
+ EXPECT_FALSE(dynamicControl().ShouldSkipOperation("foo", iop));
SetSnapshotEnabled(true);
// Empty source and destination. Skip.
- EXPECT_TRUE(dynamicControl().ShouldSkipOperation(iop));
+ EXPECT_TRUE(dynamicControl().ShouldSkipOperation("foo", iop));
se = iop.add_src_extents();
se->set_start_block(0);
se->set_num_blocks(1);
// There is something in sources, but destinations are empty. Cannot skip.
- EXPECT_FALSE(dynamicControl().ShouldSkipOperation(iop));
+ EXPECT_FALSE(dynamicControl().ShouldSkipOperation("foo", iop));
InstallOperation iop2;
@@ -660,42 +664,45 @@
de->set_num_blocks(1);
// There is something in destinations, but sources are empty. Cannot skip.
- EXPECT_FALSE(dynamicControl().ShouldSkipOperation(iop2));
+ EXPECT_FALSE(dynamicControl().ShouldSkipOperation("foo", iop2));
de = iop.add_dst_extents();
de->set_start_block(0);
de->set_num_blocks(1);
// Sources and destinations are identical. Skip.
- EXPECT_TRUE(dynamicControl().ShouldSkipOperation(iop));
+ EXPECT_TRUE(dynamicControl().ShouldSkipOperation("foo", iop));
se = iop.add_src_extents();
se->set_start_block(1);
se->set_num_blocks(5);
// There is something in source, but not in destination. Cannot skip.
- EXPECT_FALSE(dynamicControl().ShouldSkipOperation(iop));
+ EXPECT_FALSE(dynamicControl().ShouldSkipOperation("foo", iop));
de = iop.add_dst_extents();
de->set_start_block(1);
de->set_num_blocks(5);
// There is source and destination are equal. Skip.
- EXPECT_TRUE(dynamicControl().ShouldSkipOperation(iop));
+ EXPECT_TRUE(dynamicControl().ShouldSkipOperation("foo", iop));
de = iop.add_dst_extents();
de->set_start_block(6);
de->set_num_blocks(5);
// There is something extra in dest. Cannot skip.
- EXPECT_FALSE(dynamicControl().ShouldSkipOperation(iop));
+ EXPECT_FALSE(dynamicControl().ShouldSkipOperation("foo", iop));
se = iop.add_src_extents();
se->set_start_block(6);
se->set_num_blocks(5);
// Source and dest are identical again. Skip.
- EXPECT_TRUE(dynamicControl().ShouldSkipOperation(iop));
+ EXPECT_TRUE(dynamicControl().ShouldSkipOperation("foo", iop));
+
+ // Don't skip for static partitions.
+ EXPECT_FALSE(dynamicControl().ShouldSkipOperation("bar", iop));
}
} // namespace chromeos_update_engine
diff --git a/mock_dynamic_partition_control.h b/mock_dynamic_partition_control.h
index db8e834..09b825d 100644
--- a/mock_dynamic_partition_control.h
+++ b/mock_dynamic_partition_control.h
@@ -17,6 +17,7 @@
#include <stdint.h>
#include <memory>
+#include <set>
#include <string>
#include <gmock/gmock.h>
@@ -69,6 +70,10 @@
MOCK_METHOD1(GetSuperPartitionName, std::string(uint32_t));
MOCK_METHOD0(GetVirtualAbFeatureFlag, FeatureFlag());
MOCK_METHOD0(FinishUpdate, bool());
+
+ void set_fake_mapped_devices(const std::set<std::string>& fake) override {
+ DynamicPartitionControlAndroid::set_fake_mapped_devices(fake);
+ }
};
} // namespace chromeos_update_engine
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index 3d38c5b..c49474c 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -1157,8 +1157,10 @@
// The device may optimize the SOURCE_COPY operation.
// Being this a device-specific optimization let DynamicPartitionController
// decide it the operation should be skipped.
+ const PartitionUpdate& partition = partitions_[current_partition_];
const auto& partition_control = boot_control_->GetDynamicPartitionControl();
- bool should_skip = partition_control->ShouldSkipOperation(operation);
+ bool should_skip = partition_control->ShouldSkipOperation(
+ partition.partition_name(), operation);
if (operation.has_src_sha256_hash()) {
bool read_ok;