Fix a bug where merge sequence is incorrect
Bug: 200076590
Bug: 177104308
Test: th
Change-Id: Ie6373f01bdbc3705b77c55ba32dacdddf7111b9f
diff --git a/payload_consumer/vabc_partition_writer.cc b/payload_consumer/vabc_partition_writer.cc
index a5d03d9..07eff92 100644
--- a/payload_consumer/vabc_partition_writer.cc
+++ b/payload_consumer/vabc_partition_writer.cc
@@ -97,7 +97,8 @@
size_t next_op_index) {
xor_map_ = ComputeXorMap(partition_update_.merge_operations());
TEST_AND_RETURN_FALSE(install_plan != nullptr);
- if (source_may_exist) {
+ if (source_may_exist && install_part_.source_size > 0) {
+ TEST_AND_RETURN_FALSE(!install_part_.source_path.empty());
TEST_AND_RETURN_FALSE(verified_source_fd_.Open());
}
std::optional<std::string> source_path;
@@ -155,15 +156,28 @@
std::vector<uint32_t> blocks_merge_order;
for (const auto& merge_op : merge_sequence) {
const auto& dst_extent = merge_op.dst_extent();
+ const auto& src_extent = merge_op.src_extent();
// In place copy are basically noops, they do not need to be "merged" at
// all, don't include them in merge sequence.
if (merge_op.type() == CowMergeOperation::COW_COPY &&
merge_op.src_extent() == merge_op.dst_extent()) {
continue;
}
- // libsnapshot prefers blocks in reverse order
- for (int i = dst_extent.num_blocks() - 1; i >= 0; i--) {
- blocks_merge_order.push_back(dst_extent.start_block() + i);
+ // libsnapshot prefers blocks in reverse order, so if this isn't a self
+ // overlapping OP, writing block in reverser order
+ // If this is a self-overlapping op and |dst_extent| comes after
+ // |src_extent|, we must write in reverse order for correctness.
+ // 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()) {
+ for (size_t i = 0; i < dst_extent.num_blocks(); i++) {
+ blocks_merge_order.push_back(dst_extent.start_block() + i);
+ }
+ } else {
+ for (int i = dst_extent.num_blocks() - 1; i >= 0; i--) {
+ blocks_merge_order.push_back(dst_extent.start_block() + i);
+ }
}
}
return cow_writer->AddSequenceData(blocks_merge_order.size(),