From 17d6a993fc17d533460c5f40f3908c708e057c18 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 23 May 2024 18:45:17 +0200 Subject: Merging upstream version 18.2.3. Signed-off-by: Daniel Baumann --- src/librados/snap_set_diff.cc | 67 ++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 26 deletions(-) (limited to 'src/librados/snap_set_diff.cc') diff --git a/src/librados/snap_set_diff.cc b/src/librados/snap_set_diff.cc index 06f76b023..42d78eb03 100644 --- a/src/librados/snap_set_diff.cc +++ b/src/librados/snap_set_diff.cc @@ -31,9 +31,8 @@ void calc_snap_set_diff(CephContext *cct, const librados::snap_set_t& snap_set, *clone_end_snap_id = 0; *whole_object = false; - for (vector::const_iterator r = snap_set.clones.begin(); - r != snap_set.clones.end(); - ) { + auto r = snap_set.clones.begin(); + while (r != snap_set.clones.end()) { // make an interval, and hide the fact that the HEAD doesn't // include itself in the snaps list librados::snap_t a, b; @@ -76,42 +75,58 @@ void calc_snap_set_diff(CephContext *cct, const librados::snap_set_t& snap_set, saw_start = true; } - *end_size = r->size; if (end < a) { - ldout(cct, 20) << " past end " << end << ", end object does not exist" << dendl; - *end_exists = false; - diff->clear(); - if (start_size) { - diff->insert(0, start_size); - } break; } if (end <= b) { ldout(cct, 20) << " end" << dendl; + *end_size = r->size; *end_exists = true; *clone_end_snap_id = b; - break; + return; } - // start with the max(this size, next size), and subtract off any - // overlap + // start with the largest possible diff to next, and subtract off + // any overlap const vector > *overlap = &r->overlap; interval_set diff_to_next; - uint64_t max_size = r->size; + uint64_t diff_boundary; + uint64_t prev_size = r->size; ++r; if (r != snap_set.clones.end()) { - if (r->size > max_size) - max_size = r->size; - } - if (max_size) - diff_to_next.insert(0, max_size); - for (vector >::const_iterator p = overlap->begin(); - p != overlap->end(); - ++p) { - diff_to_next.erase(p->first, p->second); + if (r->size >= prev_size) { + diff_boundary = r->size; + } else if (prev_size <= start_size) { + // truncated range below size at start + diff_boundary = prev_size; + } else { + // truncated range (partially) above size at start -- drop that + // part from the running diff + diff_boundary = std::max(r->size, start_size); + ldout(cct, 20) << " no more diff beyond " << diff_boundary << dendl; + diff->erase(diff_boundary, prev_size - diff_boundary); + } + if (diff_boundary) { + diff_to_next.insert(0, diff_boundary); + } + for (auto p = overlap->begin(); p != overlap->end(); ++p) { + diff_to_next.erase(p->first, p->second); + } + ldout(cct, 20) << " diff_to_next " << diff_to_next << dendl; + diff->union_of(diff_to_next); + ldout(cct, 20) << " diff now " << *diff << dendl; } - ldout(cct, 20) << " diff_to_next " << diff_to_next << dendl; - diff->union_of(diff_to_next); - ldout(cct, 20) << " diff now " << *diff << dendl; + } + + if (r != snap_set.clones.end()) { + ldout(cct, 20) << " past end " << end + << ", end object does not exist" << dendl; + } else { + ldout(cct, 20) << " ran out of clones before reaching end " << end + << ", end object does not exist" << dendl; + } + diff->clear(); + if (start_size) { + diff->insert(0, start_size); } } -- cgit v1.2.3