AU: Don't use sparse holes as scratch space in the delta generator.
This patch fixes a number of bugs related to handling of sparse holes
in the context of scratch space in the delta diff generator and adds
appropriate unit tests. Most notably:
- Ignore sparse holes for the purposes of ExtentRanges. This prevents
the generator from using sparse holes as scratch.
- Adds two unit tests to catch using sparse holes as scratch in a more
deterministric way.
- Handle correctly sparse holes in
GraphUtils::AppendBlockToExtents. For example, previously, if one
adds block 0 to a single-block kSparseHole extent, the extent would
have been simply extended.
BUG=chromium:238440
TEST=unit tests, trybots
Change-Id: I3fedcc93af319ee741821ad9d1a2a57b7a7d5de2
Reviewed-on: https://gerrit.chromium.org/gerrit/50448
Commit-Queue: Darin Petkov <petkov@chromium.org>
Reviewed-by: Darin Petkov <petkov@chromium.org>
Tested-by: Darin Petkov <petkov@chromium.org>
diff --git a/extent_ranges.cc b/extent_ranges.cc
index a8836c9..5193d3d 100644
--- a/extent_ranges.cc
+++ b/extent_ranges.cc
@@ -20,6 +20,8 @@
bool ExtentRanges::ExtentsOverlapOrTouch(const Extent& a, const Extent& b) {
if (a.start_block() == b.start_block())
return true;
+ if (a.start_block() == kSparseHole || b.start_block() == kSparseHole)
+ return false;
if (a.start_block() < b.start_block()) {
return a.start_block() + a.num_blocks() >= b.start_block();
} else {
@@ -30,6 +32,8 @@
bool ExtentRanges::ExtentsOverlap(const Extent& a, const Extent& b) {
if (a.start_block() == b.start_block())
return true;
+ if (a.start_block() == kSparseHole || b.start_block() == kSparseHole)
+ return false;
if (a.start_block() < b.start_block()) {
return a.start_block() + a.num_blocks() > b.start_block();
} else {
@@ -48,16 +52,18 @@
namespace {
Extent UnionOverlappingExtents(const Extent& first, const Extent& second) {
+ CHECK_NE(kSparseHole, first.start_block());
+ CHECK_NE(kSparseHole, second.start_block());
uint64_t start = min(first.start_block(), second.start_block());
uint64_t end = max(first.start_block() + first.num_blocks(),
second.start_block() + second.num_blocks());
return ExtentForRange(start, end - start);
}
-
+
} // namespace {}
void ExtentRanges::AddExtent(Extent extent) {
- if (extent.num_blocks() == 0)
+ if (extent.start_block() == kSparseHole || extent.num_blocks() == 0)
return;
ExtentSet::iterator begin_del = extent_set_.end();
@@ -100,7 +106,7 @@
} // namespace {}
void ExtentRanges::SubtractExtent(const Extent& extent) {
- if (extent.num_blocks() == 0)
+ if (extent.start_block() == kSparseHole || extent.num_blocks() == 0)
return;
ExtentSet::iterator begin_del = extent_set_.end();
@@ -111,12 +117,12 @@
it != e; ++it) {
if (!ExtentsOverlap(*it, extent))
continue;
-
+
if (begin_del == extent_set_.end())
begin_del = it;
end_del = it;
++end_del;
-
+
del_blocks += it->num_blocks();
ExtentSet subtraction = SubtractOverlappingExtents(*it, extent);