From 9f1f352eb5aff43bb7ac6d1a085b25a8351cbd91 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Wed, 27 Dec 2023 18:07:05 +0100 Subject: [PATCH] librbd/object_map: add support for ranged diff-iterate Currently diff-iterate in fast-diff mode is performed on the entire image no matter what image extent is passed to the API. Then, unused diff just gets discarded as DiffIterate ends up querying only objects that the passed image extent maps to. This hasn't been an issue for internal consumers ("rbd du", "rbd diff", etc) because they work on the entire image, but turns out to lead to quadratic slowdown in some QEMU use cases. 0..UINT64_MAX range is carved out for deep-copy which is unranged by definition. To get effectively unranged diff-iterate, 0..UINT64_MAX-1 range can be used. Fixes: https://tracker.ceph.com/issues/63341 Signed-off-by: Ilya Dryomov (cherry picked from commit 0b5ba5fedf704ada74a65108af129eae6baea5c5) --- src/librbd/api/DiffIterate.cc | 34 +++- src/librbd/api/DiffIterate.h | 3 + src/librbd/deep_copy/ImageCopyRequest.cc | 2 +- src/librbd/object_map/DiffRequest.cc | 82 +++++++-- src/librbd/object_map/DiffRequest.h | 24 +-- .../deep_copy/test_mock_ImageCopyRequest.cc | 2 +- .../object_map/test_mock_DiffRequest.cc | 169 ++++++++++++++---- 7 files changed, 243 insertions(+), 73 deletions(-) diff --git a/src/librbd/api/DiffIterate.cc b/src/librbd/api/DiffIterate.cc index 4bbc8ebdc98ae..a464b942ae091 100644 --- a/src/librbd/api/DiffIterate.cc +++ b/src/librbd/api/DiffIterate.cc @@ -211,6 +211,29 @@ int DiffIterate::diff_iterate(I *ictx, return r; } +template +std::pair DiffIterate::calc_object_diff_range() { + uint64_t period = m_image_ctx.get_stripe_period(); + uint64_t first_period_off = round_down_to(m_offset, period); + uint64_t last_period_off = round_down_to(m_offset + m_length - 1, period); + + striper::LightweightObjectExtents object_extents; + if (first_period_off != last_period_off) { + // map only the tail of the first period and the front of the last + // period instead of the entire range for efficiency + Striper::file_to_extents(m_image_ctx.cct, &m_image_ctx.layout, + m_offset, first_period_off + period - m_offset, + 0, 0, &object_extents); + Striper::file_to_extents(m_image_ctx.cct, &m_image_ctx.layout, + last_period_off, m_offset + m_length - last_period_off, + 0, 0, &object_extents); + } else { + Striper::file_to_extents(m_image_ctx.cct, &m_image_ctx.layout, m_offset, + m_length, 0, 0, &object_extents); + } + return {object_extents.front().object_no, object_extents.back().object_no + 1}; +} + template int DiffIterate::execute() { CephContext* cct = m_image_ctx.cct; @@ -245,20 +268,24 @@ int DiffIterate::execute() { int r; bool fast_diff_enabled = false; + uint64_t start_object_no, end_object_no; BitVector<2> object_diff_state; interval_set parent_diff; if (m_whole_object) { + std::tie(start_object_no, end_object_no) = calc_object_diff_range(); + C_SaferCond ctx; auto req = object_map::DiffRequest::create(&m_image_ctx, from_snap_id, - end_snap_id, true, + end_snap_id, start_object_no, + end_object_no, &object_diff_state, &ctx); req->send(); - r = ctx.wait(); if (r < 0) { ldout(cct, 5) << "fast diff disabled" << dendl; } else { ldout(cct, 5) << "fast diff enabled" << dendl; + ceph_assert(object_diff_state.size() == end_object_no - start_object_no); fast_diff_enabled = true; // check parent overlap only if we are comparing to the beginning of time @@ -308,7 +335,8 @@ int DiffIterate::execute() { io::SparseExtents aggregate_sparse_extents; for (auto& [object, extents] : object_extents) { const uint64_t object_no = extents.front().objectno; - uint8_t diff_state = object_diff_state[object_no]; + ceph_assert(object_no >= start_object_no && object_no < end_object_no); + uint8_t diff_state = object_diff_state[object_no - start_object_no]; ldout(cct, 20) << "object " << object << ": diff_state=" << (int)diff_state << dendl; diff --git a/src/librbd/api/DiffIterate.h b/src/librbd/api/DiffIterate.h index e6074d9cb3d66..8ce7f6afd7c30 100644 --- a/src/librbd/api/DiffIterate.h +++ b/src/librbd/api/DiffIterate.h @@ -7,6 +7,7 @@ #include "include/int_types.h" #include "common/bit_vector.hpp" #include "cls/rbd/cls_rbd_types.h" +#include namespace librbd { @@ -51,6 +52,8 @@ private: { } + std::pair calc_object_diff_range(); + int execute(); int diff_object_map(uint64_t from_snap_id, uint64_t to_snap_id, diff --git a/src/librbd/deep_copy/ImageCopyRequest.cc b/src/librbd/deep_copy/ImageCopyRequest.cc index abd8891c02632..6688083402cb6 100644 --- a/src/librbd/deep_copy/ImageCopyRequest.cc +++ b/src/librbd/deep_copy/ImageCopyRequest.cc @@ -103,7 +103,7 @@ void ImageCopyRequest::compute_diff() { ImageCopyRequest, &ImageCopyRequest::handle_compute_diff>(this); auto req = object_map::DiffRequest::create(m_src_image_ctx, m_src_snap_id_start, - m_src_snap_id_end, false, + m_src_snap_id_end, 0, UINT64_MAX, &m_object_diff_state, ctx); req->send(); } diff --git a/src/librbd/object_map/DiffRequest.cc b/src/librbd/object_map/DiffRequest.cc index 4d23bcbad4da1..b8666fb9809ad 100644 --- a/src/librbd/object_map/DiffRequest.cc +++ b/src/librbd/object_map/DiffRequest.cc @@ -20,6 +20,29 @@ namespace object_map { using util::create_rados_callback; +template +DiffRequest::DiffRequest(I* image_ctx, + uint64_t snap_id_start, uint64_t snap_id_end, + uint64_t start_object_no, uint64_t end_object_no, + BitVector<2>* object_diff_state, + Context* on_finish) + : m_image_ctx(image_ctx), m_snap_id_start(snap_id_start), + m_snap_id_end(snap_id_end), m_start_object_no(start_object_no), + m_end_object_no(end_object_no), m_object_diff_state(object_diff_state), + m_on_finish(on_finish) { + auto cct = m_image_ctx->cct; + ldout(cct, 10) << "snap_id_start=" << m_snap_id_start + << ", snap_id_end=" << m_snap_id_end + << ", start_object_no=" << m_start_object_no + << ", end_object_no=" << m_end_object_no + << dendl; +} + +template +bool DiffRequest::is_diff_iterate() const { + return m_start_object_no != 0 || m_end_object_no != UINT64_MAX; +} + template void DiffRequest::send() { auto cct = m_image_ctx->cct; @@ -30,19 +53,34 @@ void DiffRequest::send() { << "snap_id_end=" << m_snap_id_end << dendl; finish(-EINVAL); return; - } else if (m_snap_id_start == m_snap_id_end) { - // no delta between the same snapshot - finish(0); + } + if (m_start_object_no == UINT64_MAX || m_start_object_no > m_end_object_no || + (m_start_object_no != 0 && m_end_object_no == UINT64_MAX)) { + lderr(cct) << "invalid start/end object numbers: " + << "start_object_no=" << m_start_object_no << ", " + << "end_object_no=" << m_end_object_no << dendl; + finish(-EINVAL); return; } m_object_diff_state->clear(); + if (m_snap_id_start == m_snap_id_end) { + // no delta between the same snapshot + finish(0); + return; + } + if (m_start_object_no == m_end_object_no) { + // no objects in the provided range (half-open) + finish(0); + return; + } + // collect all the snap ids in the provided range (inclusive) unless // this is diff-iterate against the beginning of time, in which case // only the end version matters std::shared_lock image_locker{m_image_ctx->image_lock}; - if (!m_diff_iterate_range || m_snap_id_start != 0) { + if (!is_diff_iterate() || m_snap_id_start != 0) { if (m_snap_id_start != 0) { m_snap_ids.insert(m_snap_id_start); } @@ -178,10 +216,14 @@ void DiffRequest::handle_load_object_map(int r) { m_object_map.resize(num_objs); } + uint64_t start_object_no, end_object_no; uint64_t prev_object_diff_state_size = m_object_diff_state->size(); - if (m_diff_iterate_range) { - if (m_object_diff_state->size() != m_object_map.size()) { - m_object_diff_state->resize(m_object_map.size()); + if (is_diff_iterate()) { + start_object_no = std::min(m_start_object_no, m_object_map.size()); + end_object_no = std::min(m_end_object_no, m_object_map.size()); + uint64_t num_objs_in_range = end_object_no - start_object_no; + if (m_object_diff_state->size() != num_objs_in_range) { + m_object_diff_state->resize(num_objs_in_range); } } else { // for deep-copy, the object diff state should be the largest of @@ -194,21 +236,23 @@ void DiffRequest::handle_load_object_map(int r) { // diff state m_object_map.resize(m_object_diff_state->size()); } + start_object_no = 0; + end_object_no = m_object_diff_state->size(); } - uint64_t overlap = std::min(m_object_map.size(), prev_object_diff_state_size); - auto it = m_object_map.begin(); - auto overlap_end_it = it + overlap; + uint64_t overlap = std::min(m_object_diff_state->size(), + prev_object_diff_state_size); + auto it = m_object_map.begin() + start_object_no; auto diff_it = m_object_diff_state->begin(); - uint64_t i = 0; - for (; it != overlap_end_it; ++it, ++diff_it, ++i) { + uint64_t ono = start_object_no; + for (; ono < start_object_no + overlap; ++it, ++diff_it, ++ono) { uint8_t object_map_state = *it; uint8_t prev_object_diff_state = *diff_it; switch (prev_object_diff_state) { case DIFF_STATE_HOLE: if (object_map_state != OBJECT_NONEXISTENT) { // stay in HOLE on intermediate snapshots for diff-iterate - if (!m_diff_iterate_range || m_current_snap_id == m_snap_id_end) { + if (!is_diff_iterate() || m_current_snap_id == m_snap_id_end) { *diff_it = DIFF_STATE_DATA_UPDATED; } } @@ -234,7 +278,7 @@ void DiffRequest::handle_load_object_map(int r) { ceph_abort(); } - ldout(cct, 20) << "object state: " << i << " " + ldout(cct, 20) << "object state: " << ono << " " << static_cast(prev_object_diff_state) << "->" << static_cast(*diff_it) << " (" << static_cast(object_map_state) << ")" @@ -242,8 +286,9 @@ void DiffRequest::handle_load_object_map(int r) { } ldout(cct, 20) << "computed overlap diffs" << dendl; - auto end_it = m_object_map.end(); - for (; it != end_it; ++it, ++diff_it, ++i) { + ceph_assert(diff_it == m_object_diff_state->end() || + end_object_no <= m_object_map.size()); + for (; ono < end_object_no; ++it, ++diff_it, ++ono) { uint8_t object_map_state = *it; if (object_map_state == OBJECT_NONEXISTENT) { *diff_it = DIFF_STATE_HOLE; @@ -251,7 +296,7 @@ void DiffRequest::handle_load_object_map(int r) { // diffing against the beginning of time or image was grown // (implicit) starting state is HOLE, this is the first object // map after - if (m_diff_iterate_range) { + if (is_diff_iterate()) { // for diff-iterate, if the object is discarded prior to or // in the end version, result should be HOLE // since DATA_UPDATED can transition only to HOLE_UPDATED, @@ -278,12 +323,13 @@ void DiffRequest::handle_load_object_map(int r) { } } - ldout(cct, 20) << "object state: " << i << " " + ldout(cct, 20) << "object state: " << ono << " " << "->" << static_cast(*diff_it) << " (" << static_cast(*it) << ")" << dendl; } ldout(cct, 20) << "computed resize diffs" << dendl; + ceph_assert(diff_it == m_object_diff_state->end()); std::shared_lock image_locker{m_image_ctx->image_lock}; load_object_map(&image_locker); } diff --git a/src/librbd/object_map/DiffRequest.h b/src/librbd/object_map/DiffRequest.h index f2fb9975f7510..6a8ecb9dc9306 100644 --- a/src/librbd/object_map/DiffRequest.h +++ b/src/librbd/object_map/DiffRequest.h @@ -21,21 +21,20 @@ namespace object_map { template class DiffRequest { public: - static DiffRequest* create(ImageCtxT* image_ctx, uint64_t snap_id_start, - uint64_t snap_id_end, bool diff_iterate_range, + static DiffRequest* create(ImageCtxT* image_ctx, + uint64_t snap_id_start, uint64_t snap_id_end, + uint64_t start_object_no, uint64_t end_object_no, BitVector<2>* object_diff_state, Context* on_finish) { return new DiffRequest(image_ctx, snap_id_start, snap_id_end, - diff_iterate_range, object_diff_state, on_finish); + start_object_no, end_object_no, object_diff_state, + on_finish); } - DiffRequest(ImageCtxT* image_ctx, uint64_t snap_id_start, - uint64_t snap_id_end, bool diff_iterate_range, - BitVector<2>* object_diff_state, Context* on_finish) - : m_image_ctx(image_ctx), m_snap_id_start(snap_id_start), - m_snap_id_end(snap_id_end), m_diff_iterate_range(diff_iterate_range), - m_object_diff_state(object_diff_state), m_on_finish(on_finish) { - } + DiffRequest(ImageCtxT* image_ctx, + uint64_t snap_id_start, uint64_t snap_id_end, + uint64_t start_object_no, uint64_t end_object_no, + BitVector<2>* object_diff_state, Context* on_finish); void send(); @@ -58,7 +57,8 @@ private: ImageCtxT* m_image_ctx; uint64_t m_snap_id_start; uint64_t m_snap_id_end; - bool m_diff_iterate_range; + uint64_t m_start_object_no; + uint64_t m_end_object_no; BitVector<2>* m_object_diff_state; Context* m_on_finish; @@ -72,6 +72,8 @@ private: bufferlist m_out_bl; + bool is_diff_iterate() const; + void load_object_map(std::shared_lock* image_locker); void handle_load_object_map(int r); diff --git a/src/test/librbd/deep_copy/test_mock_ImageCopyRequest.cc b/src/test/librbd/deep_copy/test_mock_ImageCopyRequest.cc index 634cabfa79e3e..2c42d5075ccfc 100644 --- a/src/test/librbd/deep_copy/test_mock_ImageCopyRequest.cc +++ b/src/test/librbd/deep_copy/test_mock_ImageCopyRequest.cc @@ -92,7 +92,7 @@ struct DiffRequest { static DiffRequest* s_instance; static DiffRequest* create(MockTestImageCtx *image_ctx, uint64_t snap_id_start, uint64_t snap_id_end, - bool diff_iterate_range, + uint64_t start_object_no, uint64_t end_object_no, BitVector<2>* object_diff_state, Context* on_finish) { ceph_assert(s_instance != nullptr); diff --git a/src/test/librbd/object_map/test_mock_DiffRequest.cc b/src/test/librbd/object_map/test_mock_DiffRequest.cc index 9be4995e00a77..c7afbe939c296 100644 --- a/src/test/librbd/object_map/test_mock_DiffRequest.cc +++ b/src/test/librbd/object_map/test_mock_DiffRequest.cc @@ -209,7 +209,7 @@ public: template int do_diff(F&& f, uint64_t start_snap_id, uint64_t end_snap_id, - bool diff_iterate_range) { + uint64_t start_object_no, uint64_t end_object_no) { InSequence seq; MockTestImageCtx mock_image_ctx(*m_image_ctx); @@ -217,7 +217,7 @@ public: C_SaferCond ctx; auto req = new MockDiffRequest(&mock_image_ctx, start_snap_id, - end_snap_id, diff_iterate_range, + end_snap_id, start_object_no, end_object_no, &m_diff_state, &ctx); req->send(); return ctx.wait(); @@ -226,14 +226,29 @@ public: template void test_diff_iterate(F&& f, uint64_t start_snap_id, uint64_t end_snap_id, const BitVector<2>& expected_diff_state) { - ASSERT_EQ(0, do_diff(std::forward(f), start_snap_id, end_snap_id, true)); + // ranged -- run through all ranges (substrings) in expected_diff_state + for (uint64_t i = 0; i < expected_diff_state.size(); i++) { + for (uint64_t j = i + 1; j <= expected_diff_state.size(); j++) { + ASSERT_EQ(0, do_diff(std::forward(f), start_snap_id, end_snap_id, + i, j)); + ASSERT_EQ(j - i, m_diff_state.size()); + for (uint64_t k = 0; k < m_diff_state.size(); k++) { + ASSERT_EQ(expected_diff_state[i + k], m_diff_state[k]); + } + } + } + + // unranged -- equivalent to i=0, j=expected_diff_state.size() range + ASSERT_EQ(0, do_diff(std::forward(f), start_snap_id, end_snap_id, + 0, UINT64_MAX - 1)); ASSERT_EQ(expected_diff_state, m_diff_state); } template void test_deep_copy(F&& f, uint64_t start_snap_id, uint64_t end_snap_id, const BitVector<2>& expected_diff_state) { - ASSERT_EQ(0, do_diff(std::forward(f), start_snap_id, end_snap_id, false)); + ASSERT_EQ(0, do_diff(std::forward(f), start_snap_id, end_snap_id, + 0, UINT64_MAX)); ASSERT_EQ(expected_diff_state, m_diff_state); } @@ -243,9 +258,17 @@ public: TEST_P(TestMockObjectMapDiffRequest, InvalidStartSnap) { if (is_diff_iterate()) { - ASSERT_EQ(-EINVAL, do_diff(noop, CEPH_NOSNAP, CEPH_NOSNAP, true)); + ASSERT_EQ(-EINVAL, do_diff(noop, CEPH_NOSNAP, CEPH_NOSNAP, 123, 456)); + } else { + ASSERT_EQ(-EINVAL, do_diff(noop, CEPH_NOSNAP, CEPH_NOSNAP, 0, UINT64_MAX)); + } +} + +TEST_P(TestMockObjectMapDiffRequest, InvalidEndSnap) { + if (is_diff_iterate()) { + ASSERT_EQ(-EINVAL, do_diff(noop, 2, 1, 123, 456)); } else { - ASSERT_EQ(-EINVAL, do_diff(noop, CEPH_NOSNAP, CEPH_NOSNAP, false)); + ASSERT_EQ(-EINVAL, do_diff(noop, 2, 1, 0, UINT64_MAX)); } } @@ -253,21 +276,48 @@ TEST_P(TestMockObjectMapDiffRequest, StartEndSnapEqual) { BitVector<2> expected_diff_state; if (is_diff_iterate()) { - ASSERT_EQ(0, do_diff(noop, 1, 1, true)); + ASSERT_EQ(0, do_diff(noop, 1, 1, 123, 456)); } else { - ASSERT_EQ(0, do_diff(noop, 1, 1, false)); + ASSERT_EQ(0, do_diff(noop, 1, 1, 0, UINT64_MAX)); } ASSERT_EQ(expected_diff_state, m_diff_state); } +TEST_P(TestMockObjectMapDiffRequest, InvalidStartObject) { + if (is_diff_iterate()) { + ASSERT_EQ(-EINVAL, do_diff(noop, 0, 1, UINT64_MAX, UINT64_MAX)); + } else { + ASSERT_EQ(-EINVAL, do_diff(noop, 0, 1, 123, UINT64_MAX)); + } +} + +TEST_P(TestMockObjectMapDiffRequest, InvalidEndObject) { + if (is_diff_iterate()) { + ASSERT_EQ(-EINVAL, do_diff(noop, 0, 1, 456, 123)); + } else { + SUCCEED(); + } +} + +TEST_P(TestMockObjectMapDiffRequest, StartEndObjectEqual) { + BitVector<2> expected_diff_state; + + if (is_diff_iterate()) { + ASSERT_EQ(0, do_diff(noop, 0, 1, 123, 123)); + ASSERT_EQ(expected_diff_state, m_diff_state); + } else { + SUCCEED(); + } +} + TEST_P(TestMockObjectMapDiffRequest, FastDiffDisabled) { // negative test -- object-map implicitly enables fast-diff REQUIRE(!is_feature_enabled(RBD_FEATURE_OBJECT_MAP)); if (is_diff_iterate()) { - ASSERT_EQ(-EINVAL, do_diff(noop, 0, CEPH_NOSNAP, true)); + ASSERT_EQ(-EINVAL, do_diff(noop, 0, CEPH_NOSNAP, 123, 456)); } else { - ASSERT_EQ(-EINVAL, do_diff(noop, 0, CEPH_NOSNAP, false)); + ASSERT_EQ(-EINVAL, do_diff(noop, 0, CEPH_NOSNAP, 0, UINT64_MAX)); } } @@ -301,6 +351,28 @@ TEST_P(TestMockObjectMapDiffRequest, FromBeginningToSnap) { } } +TEST_P(TestMockObjectMapDiffRequest, FromBeginningToSnapEmpty) { + REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF); + + m_image_ctx->size = 0; + m_image_ctx->snap_info = { + {1U, {"snap1", {cls::rbd::UserSnapshotNamespace{}}, {}, {}, {}, {}, {}}} + }; + + BitVector<2> object_map_1; + BitVector<2> expected_diff_state; + + auto load = [&](MockTestImageCtx& mock_image_ctx) { + expect_get_flags(mock_image_ctx, 1, 0, 0); + expect_load_map(mock_image_ctx, 1, object_map_1, 0); + }; + if (is_diff_iterate()) { + test_diff_iterate(load, 0, 1, expected_diff_state); + } else { + test_deep_copy(load, 0, 1, expected_diff_state); + } +} + TEST_P(TestMockObjectMapDiffRequest, FromBeginningToSnapIntermediateSnap) { REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF); @@ -558,6 +630,25 @@ TEST_P(TestMockObjectMapDiffRequest, FromBeginningToHead) { } } +TEST_P(TestMockObjectMapDiffRequest, FromBeginningToHeadEmpty) { + REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF); + + m_image_ctx->size = 0; + + BitVector<2> object_map_head; + BitVector<2> expected_diff_state; + + auto load = [&](MockTestImageCtx& mock_image_ctx) { + expect_get_flags(mock_image_ctx, CEPH_NOSNAP, 0, 0); + expect_load_map(mock_image_ctx, CEPH_NOSNAP, object_map_head, 0); + }; + if (is_diff_iterate()) { + test_diff_iterate(load, 0, CEPH_NOSNAP, expected_diff_state); + } else { + test_deep_copy(load, 0, CEPH_NOSNAP, expected_diff_state); + } +} + TEST_P(TestMockObjectMapDiffRequest, FromBeginningToHeadIntermediateSnap) { REQUIRE_FEATURE(RBD_FEATURE_FAST_DIFF); @@ -1274,9 +1365,9 @@ TEST_P(TestMockObjectMapDiffRequest, StartSnapDNE) { }; if (is_diff_iterate()) { - ASSERT_EQ(-ENOENT, do_diff(noop, 1, 2, true)); + ASSERT_EQ(-ENOENT, do_diff(noop, 1, 2, 0, object_count)); } else { - ASSERT_EQ(-ENOENT, do_diff(noop, 1, 2, false)); + ASSERT_EQ(-ENOENT, do_diff(noop, 1, 2, 0, UINT64_MAX)); } } @@ -1294,13 +1385,13 @@ TEST_P(TestMockObjectMapDiffRequest, EndSnapDNE) { object_map_1.resize(object_count); if (is_diff_iterate()) { - ASSERT_EQ(-ENOENT, do_diff(noop, 0, 2, true)); + ASSERT_EQ(-ENOENT, do_diff(noop, 0, 2, 0, object_count)); } else { auto load = [&](MockTestImageCtx& mock_image_ctx) { expect_get_flags(mock_image_ctx, 1, 0, 0); expect_load_map(mock_image_ctx, 1, object_map_1, 0); }; - ASSERT_EQ(-ENOENT, do_diff(load, 0, 2, false)); + ASSERT_EQ(-ENOENT, do_diff(load, 0, 2, 0, UINT64_MAX)); } } @@ -1397,9 +1488,9 @@ TEST_P(TestMockObjectMapDiffRequest, StartObjectMapDNE) { expect_load_map(mock_image_ctx, 1, object_map_1, -ENOENT); }; if (is_diff_iterate()) { - ASSERT_EQ(-ENOENT, do_diff(load, 1, 2, true)); + ASSERT_EQ(-ENOENT, do_diff(load, 1, 2, 0, object_count)); } else { - ASSERT_EQ(-ENOENT, do_diff(load, 1, 2, false)); + ASSERT_EQ(-ENOENT, do_diff(load, 1, 2, 0, UINT64_MAX)); } } @@ -1429,7 +1520,7 @@ TEST_P(TestMockObjectMapDiffRequest, EndObjectMapDNE) { expect_get_flags(mock_image_ctx, 2, 0, 0); expect_load_map(mock_image_ctx, 2, object_map_2, -ENOENT); }; - ASSERT_EQ(-ENOENT, do_diff(load, 0, 2, true)); + ASSERT_EQ(-ENOENT, do_diff(load, 0, 2, 0, object_count)); } else { auto load = [&](MockTestImageCtx& mock_image_ctx) { expect_get_flags(mock_image_ctx, 1, 0, 0); @@ -1437,7 +1528,7 @@ TEST_P(TestMockObjectMapDiffRequest, EndObjectMapDNE) { expect_get_flags(mock_image_ctx, 2, 0, 0); expect_load_map(mock_image_ctx, 2, object_map_2, -ENOENT); }; - ASSERT_EQ(-ENOENT, do_diff(load, 0, 2, false)); + ASSERT_EQ(-ENOENT, do_diff(load, 0, 2, 0, UINT64_MAX)); } } @@ -1529,9 +1620,9 @@ TEST_P(TestMockObjectMapDiffRequest, StartFastDiffInvalid) { expect_get_flags(mock_image_ctx, 1, RBD_FLAG_FAST_DIFF_INVALID, 0); }; if (is_diff_iterate()) { - ASSERT_EQ(-EINVAL, do_diff(get_flags, 1, 2, true)); + ASSERT_EQ(-EINVAL, do_diff(get_flags, 1, 2, 0, object_count)); } else { - ASSERT_EQ(-EINVAL, do_diff(get_flags, 1, 2, false)); + ASSERT_EQ(-EINVAL, do_diff(get_flags, 1, 2, 0, UINT64_MAX)); } } @@ -1554,14 +1645,14 @@ TEST_P(TestMockObjectMapDiffRequest, EndFastDiffInvalid) { auto get_flags = [&](MockTestImageCtx& mock_image_ctx) { expect_get_flags(mock_image_ctx, 2, RBD_FLAG_FAST_DIFF_INVALID, 0); }; - ASSERT_EQ(-EINVAL, do_diff(get_flags, 0, 2, true)); + ASSERT_EQ(-EINVAL, do_diff(get_flags, 0, 2, 0, object_count)); } else { auto get_flags = [&](MockTestImageCtx& mock_image_ctx) { expect_get_flags(mock_image_ctx, 1, 0, 0); expect_load_map(mock_image_ctx, 1, object_map_1, 0); expect_get_flags(mock_image_ctx, 2, RBD_FLAG_FAST_DIFF_INVALID, 0); }; - ASSERT_EQ(-EINVAL, do_diff(get_flags, 0, 2, false)); + ASSERT_EQ(-EINVAL, do_diff(get_flags, 0, 2, 0, UINT64_MAX)); } } @@ -1592,7 +1683,7 @@ TEST_P(TestMockObjectMapDiffRequest, IntermediateFastDiffInvalidFromBeginning) { auto get_flags = [&](MockTestImageCtx& mock_image_ctx) { expect_get_flags(mock_image_ctx, 1, RBD_FLAG_FAST_DIFF_INVALID, 0); }; - ASSERT_EQ(-EINVAL, do_diff(get_flags, 0, CEPH_NOSNAP, false)); + ASSERT_EQ(-EINVAL, do_diff(get_flags, 0, CEPH_NOSNAP, 0, UINT64_MAX)); } } @@ -1617,9 +1708,9 @@ TEST_P(TestMockObjectMapDiffRequest, IntermediateFastDiffInvalidFromSnap) { expect_get_flags(mock_image_ctx, 2, RBD_FLAG_FAST_DIFF_INVALID, 0); }; if (is_diff_iterate()) { - ASSERT_EQ(-EINVAL, do_diff(get_flags, 1, CEPH_NOSNAP, true)); + ASSERT_EQ(-EINVAL, do_diff(get_flags, 1, CEPH_NOSNAP, 0, object_count)); } else { - ASSERT_EQ(-EINVAL, do_diff(get_flags, 1, CEPH_NOSNAP, false)); + ASSERT_EQ(-EINVAL, do_diff(get_flags, 1, CEPH_NOSNAP, 0, UINT64_MAX)); } } @@ -1642,9 +1733,9 @@ TEST_P(TestMockObjectMapDiffRequest, StartObjectMapLoadError) { expect_load_map(mock_image_ctx, 1, object_map_1, -EPERM); }; if (is_diff_iterate()) { - ASSERT_EQ(-EPERM, do_diff(load, 1, 2, true)); + ASSERT_EQ(-EPERM, do_diff(load, 1, 2, 0, object_count)); } else { - ASSERT_EQ(-EPERM, do_diff(load, 1, 2, false)); + ASSERT_EQ(-EPERM, do_diff(load, 1, 2, 0, UINT64_MAX)); } } @@ -1674,7 +1765,7 @@ TEST_P(TestMockObjectMapDiffRequest, EndObjectMapLoadError) { expect_get_flags(mock_image_ctx, 2, 0, 0); expect_load_map(mock_image_ctx, 2, object_map_2, -EPERM); }; - ASSERT_EQ(-EPERM, do_diff(load, 0, 2, true)); + ASSERT_EQ(-EPERM, do_diff(load, 0, 2, 0, object_count)); } else { auto load = [&](MockTestImageCtx& mock_image_ctx) { expect_get_flags(mock_image_ctx, 1, 0, 0); @@ -1682,7 +1773,7 @@ TEST_P(TestMockObjectMapDiffRequest, EndObjectMapLoadError) { expect_get_flags(mock_image_ctx, 2, 0, 0); expect_load_map(mock_image_ctx, 2, object_map_2, -EPERM); }; - ASSERT_EQ(-EPERM, do_diff(load, 0, 2, false)); + ASSERT_EQ(-EPERM, do_diff(load, 0, 2, 0, UINT64_MAX)); } } @@ -1715,7 +1806,7 @@ TEST_P(TestMockObjectMapDiffRequest, IntermediateObjectMapLoadErrorFromBeginning expect_get_flags(mock_image_ctx, 1, 0, 0); expect_load_map(mock_image_ctx, 1, object_map_1, -EPERM); }; - ASSERT_EQ(-EPERM, do_diff(load, 0, CEPH_NOSNAP, false)); + ASSERT_EQ(-EPERM, do_diff(load, 0, CEPH_NOSNAP, 0, UINT64_MAX)); } } @@ -1742,9 +1833,9 @@ TEST_P(TestMockObjectMapDiffRequest, IntermediateObjectMapLoadErrorFromSnap) { expect_load_map(mock_image_ctx, 2, object_map_2, -EPERM); }; if (is_diff_iterate()) { - ASSERT_EQ(-EPERM, do_diff(load, 1, CEPH_NOSNAP, true)); + ASSERT_EQ(-EPERM, do_diff(load, 1, CEPH_NOSNAP, 0, object_count)); } else { - ASSERT_EQ(-EPERM, do_diff(load, 1, CEPH_NOSNAP, false)); + ASSERT_EQ(-EPERM, do_diff(load, 1, CEPH_NOSNAP, 0, UINT64_MAX)); } } @@ -1768,9 +1859,9 @@ TEST_P(TestMockObjectMapDiffRequest, StartObjectMapTooSmall) { expect_load_map(mock_image_ctx, 1, object_map_1, 0); }; if (is_diff_iterate()) { - ASSERT_EQ(-EINVAL, do_diff(load, 1, 2, true)); + ASSERT_EQ(-EINVAL, do_diff(load, 1, 2, 0, object_count)); } else { - ASSERT_EQ(-EINVAL, do_diff(load, 1, 2, false)); + ASSERT_EQ(-EINVAL, do_diff(load, 1, 2, 0, UINT64_MAX)); } } @@ -1796,7 +1887,7 @@ TEST_P(TestMockObjectMapDiffRequest, EndObjectMapTooSmall) { expect_get_flags(mock_image_ctx, 2, 0, 0); expect_load_map(mock_image_ctx, 2, object_map_2, 0); }; - ASSERT_EQ(-EINVAL, do_diff(load, 0, 2, true)); + ASSERT_EQ(-EINVAL, do_diff(load, 0, 2, 0, object_count)); } else { auto load = [&](MockTestImageCtx& mock_image_ctx) { expect_get_flags(mock_image_ctx, 1, 0, 0); @@ -1804,7 +1895,7 @@ TEST_P(TestMockObjectMapDiffRequest, EndObjectMapTooSmall) { expect_get_flags(mock_image_ctx, 2, 0, 0); expect_load_map(mock_image_ctx, 2, object_map_2, 0); }; - ASSERT_EQ(-EINVAL, do_diff(load, 0, 2, false)); + ASSERT_EQ(-EINVAL, do_diff(load, 0, 2, 0, UINT64_MAX)); } } @@ -1838,7 +1929,7 @@ TEST_P(TestMockObjectMapDiffRequest, IntermediateObjectMapTooSmallFromBeginning) expect_get_flags(mock_image_ctx, 1, 0, 0); expect_load_map(mock_image_ctx, 1, object_map_1, 0); }; - ASSERT_EQ(-EINVAL, do_diff(load, 0, CEPH_NOSNAP, false)); + ASSERT_EQ(-EINVAL, do_diff(load, 0, CEPH_NOSNAP, 0, UINT64_MAX)); } } @@ -1866,9 +1957,9 @@ TEST_P(TestMockObjectMapDiffRequest, IntermediateObjectMapTooSmallFromSnap) { expect_load_map(mock_image_ctx, 2, object_map_2, 0); }; if (is_diff_iterate()) { - ASSERT_EQ(-EINVAL, do_diff(load, 1, CEPH_NOSNAP, true)); + ASSERT_EQ(-EINVAL, do_diff(load, 1, CEPH_NOSNAP, 0, object_count)); } else { - ASSERT_EQ(-EINVAL, do_diff(load, 1, CEPH_NOSNAP, false)); + ASSERT_EQ(-EINVAL, do_diff(load, 1, CEPH_NOSNAP, 0, UINT64_MAX)); } } -- 2.39.5