Write blocks in increasing order if src/dst extent start at same block
This is because xor ops can have non-zero offsets, which means dst block
depends on src_block and the block right after that.
Test: th
Bug: 200076590
Bug: 177104308
Change-Id: I9f40a52ff667ebc5f1b334d9d204ac2d5ccb2c6b
diff --git a/payload_consumer/vabc_partition_writer.cc b/payload_consumer/vabc_partition_writer.cc
index 07eff92..6ca94c1 100644
--- a/payload_consumer/vabc_partition_writer.cc
+++ b/payload_consumer/vabc_partition_writer.cc
@@ -170,7 +170,7 @@
// If this is self-overlapping op and |dst_extent| comes before
// |src_extent|, we must write in ascending order for correctness.
if (ExtentRanges::ExtentsOverlap(src_extent, dst_extent) &&
- dst_extent.start_block() < src_extent.start_block()) {
+ dst_extent.start_block() <= src_extent.start_block()) {
for (size_t i = 0; i < dst_extent.num_blocks(); i++) {
blocks_merge_order.push_back(dst_extent.start_block() + i);
}
diff --git a/payload_consumer/vabc_partition_writer_unittest.cc b/payload_consumer/vabc_partition_writer_unittest.cc
index a39098a..7a3fc9b 100644
--- a/payload_consumer/vabc_partition_writer_unittest.cc
+++ b/payload_consumer/vabc_partition_writer_unittest.cc
@@ -50,10 +50,10 @@
void SetUp() override { ftruncate(source_part_.fd, FAKE_PART_SIZE); }
protected:
- void AddMergeOp(PartitionUpdate* partition,
- std::array<size_t, 2> src_extent,
- std::array<size_t, 2> dst_extent,
- CowMergeOperation_Type type) {
+ CowMergeOperation* AddMergeOp(PartitionUpdate* partition,
+ std::array<size_t, 2> src_extent,
+ std::array<size_t, 2> dst_extent,
+ CowMergeOperation_Type type) {
auto merge_op = partition->add_merge_operations();
auto src = merge_op->mutable_src_extent();
src->set_start_block(src_extent[0]);
@@ -62,6 +62,7 @@
dst->set_start_block(dst_extent[0]);
dst->set_num_blocks(dst_extent[1]);
merge_op->set_type(type);
+ return merge_op;
}
android::snapshot::CowOptions options_ = {
@@ -103,6 +104,29 @@
ASSERT_TRUE(writer_.Init(&install_plan_, true, 0));
}
+TEST_F(VABCPartitionWriterTest, MergeSequenceXorSameBlock) {
+ AddMergeOp(&partition_update_, {19, 4}, {19, 3}, CowMergeOperation::COW_XOR)
+ ->set_src_offset(1);
+ VABCPartitionWriter writer_{
+ partition_update_, install_part_, &dynamic_control_, kBlockSize};
+ EXPECT_CALL(dynamic_control_, OpenCowWriter(fake_part_name, _, false))
+ .WillOnce(Invoke(
+ [](const std::string&, const std::optional<std::string>&, bool) {
+ auto cow_writer =
+ std::make_unique<android::snapshot::MockSnapshotWriter>(
+ android::snapshot::CowOptions{});
+ auto expected_merge_sequence = {19, 20, 21};
+ EXPECT_CALL(*cow_writer, Initialize()).WillOnce(Return(true));
+ EXPECT_CALL(*cow_writer, EmitSequenceData(_, _))
+ .With(Args<1, 0>(ElementsAreArray(expected_merge_sequence)))
+ .WillOnce(Return(true));
+ ON_CALL(*cow_writer, EmitCopy(_, _)).WillByDefault(Return(true));
+ ON_CALL(*cow_writer, EmitLabel(_)).WillByDefault(Return(true));
+ return cow_writer;
+ }));
+ ASSERT_TRUE(writer_.Init(&install_plan_, true, 0));
+}
+
TEST_F(VABCPartitionWriterTest, EmitBlockTest) {
AddMergeOp(&partition_update_, {5, 1}, {10, 1}, CowMergeOperation::COW_COPY);
AddMergeOp(&partition_update_, {10, 1}, {15, 1}, CowMergeOperation::COW_COPY);