Write CowReplace blocks in batch
snapuserd is optimizing merge performance, sending blocks in batch will
help.
Test: th
Change-Id: Ie358137768b1f0d7e03530e5f1ddb57e40e183ed
diff --git a/common/cow_operation_convert_unittest.cc b/common/cow_operation_convert_unittest.cc
index 93173fe..d5b522a 100644
--- a/common/cow_operation_convert_unittest.cc
+++ b/common/cow_operation_convert_unittest.cc
@@ -46,7 +46,8 @@
}
std::ostream& operator<<(std::ostream& out, const CowOperation& c) {
- out << "{" << c.op << ", " << c.src_block << ", " << c.dst_block << "}";
+ out << "{" << c.op << ", " << c.src_block << ", " << c.dst_block << ", "
+ << c.block_count << "}";
return out;
}
@@ -63,18 +64,24 @@
ExtentRanges modified_extents;
for (auto&& cow_op : cow_ops) {
if (cow_op.op == CowOperation::CowCopy) {
- EXPECT_TRUE(src_extent_set.ContainsBlock(cow_op.src_block));
- // converted operations should be conflict free.
- EXPECT_FALSE(modified_extents.ContainsBlock(cow_op.src_block))
- << "SOURCE_COPY operation " << cow_op
- << " read from a modified block";
+ for (size_t i = 0; i < cow_op.block_count; i++) {
+ ASSERT_TRUE(src_extent_set.ContainsBlock(cow_op.src_block + i));
+ // converted operations should be conflict free.
+ ASSERT_FALSE(modified_extents.ContainsBlock(cow_op.src_block + i))
+ << "SOURCE_COPY operation " << cow_op
+ << " read from a modified block";
+ }
}
- EXPECT_TRUE(dst_extent_set.ContainsBlock(cow_op.dst_block));
- dst_extent_set.SubtractExtent(ExtentForRange(cow_op.dst_block, 1));
- modified_extents.AddBlock(cow_op.dst_block);
+ for (size_t i = 0; i < cow_op.block_count; i++) {
+ ASSERT_TRUE(dst_extent_set.ContainsBlock(cow_op.dst_block + i));
+ }
+ dst_extent_set.SubtractExtent(
+ ExtentForRange(cow_op.dst_block, cow_op.block_count));
+ modified_extents.AddExtent(
+ ExtentForRange(cow_op.dst_block, cow_op.block_count));
}
// The generated CowOps should cover all extents in InstallOps.
- EXPECT_EQ(dst_extent_set.blocks(), 0UL);
+ ASSERT_EQ(dst_extent_set.blocks(), 0UL);
// It's possible that src_extent_set is non-empty, because some operations
// will be converted to CowReplace, and we don't count the source extent for
// those.
@@ -233,4 +240,61 @@
VerifyCowMergeOp(cow_ops);
}
+TEST_F(CowOperationConvertTest, CowReplaceCoalesce) {
+ AddOperation(
+ &operations_, InstallOperation::SOURCE_COPY, {{30, 10}}, {{0, 10}});
+
+ AddMergeOperation(
+ &merge_operations_, CowMergeOperation::COW_COPY, {30, 1}, {0, 1});
+ AddMergeOperation(
+ &merge_operations_, CowMergeOperation::COW_COPY, {31, 1}, {1, 1});
+ AddMergeOperation(
+ &merge_operations_, CowMergeOperation::COW_COPY, {32, 1}, {2, 1});
+
+ auto cow_ops = ConvertToCowOperations(operations_, merge_operations_);
+ for (const auto& op : cow_ops) {
+ LOG(INFO) << op;
+ }
+ ASSERT_EQ(cow_ops.size(), 4UL);
+ // Expect 3 COW_COPY and 1 COW_REPLACE
+ ASSERT_EQ(std::count_if(cow_ops.begin(),
+ cow_ops.end(),
+ [](auto&& cow_op) {
+ return cow_op.op == CowOperation::CowCopy;
+ }),
+ 3);
+ ASSERT_EQ(std::count_if(cow_ops.begin(),
+ cow_ops.end(),
+ [](auto&& cow_op) {
+ return cow_op.op == CowOperation::CowReplace;
+ }),
+ 1);
+ VerifyCowMergeOp(cow_ops);
+}
+
+TEST_F(CowOperationConvertTest, CowReplaceDifferenceSrc) {
+ AddOperation(
+ &operations_, InstallOperation::SOURCE_COPY, {{30, 10}}, {{0, 10}});
+ AddOperation(
+ &operations_, InstallOperation::SOURCE_COPY, {{100, 10}}, {{10, 10}});
+
+ auto cow_ops = ConvertToCowOperations(operations_, merge_operations_);
+ for (const auto& op : cow_ops) {
+ LOG(INFO) << op;
+ }
+ ASSERT_EQ(cow_ops.size(), 2UL);
+ // |src_block| matters. Even for ReplaceOperation.
+ // As update_engine still need to know where the data come from.
+ ASSERT_EQ(cow_ops[0].op, CowOperation::CowReplace);
+ ASSERT_EQ(cow_ops[0].src_block, 30UL);
+ ASSERT_EQ(cow_ops[0].dst_block, 0UL);
+ ASSERT_EQ(cow_ops[0].block_count, 10UL);
+
+ ASSERT_EQ(cow_ops[1].op, CowOperation::CowReplace);
+ ASSERT_EQ(cow_ops[1].src_block, 100UL);
+ ASSERT_EQ(cow_ops[1].dst_block, 10UL);
+ ASSERT_EQ(cow_ops[1].block_count, 10UL);
+ VerifyCowMergeOp(cow_ops);
+}
+
} // namespace chromeos_update_engine