From 6b45a2d920aad2edf17544807f7032e2b11efef3 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Thu, 30 Nov 2023 17:30:33 +0100 Subject: [PATCH] test/librbd: expand DiffIterateTest.DiffIterateDiscard Similar to DiffIterateTest.DiffIterateDeterministic, systematically cover the most common cases involving full-object discards. With this in place, issue [1] can be reproduced by any of: (preparatory) before snap3 is taken (1) beginning of time -> HEAD (2) snap1 -> HEAD (5) beginning of time -> snap3 (6) snap1 -> snap3 Sub-object discards aren't covered here because of further issues [2][3]. [1] https://tracker.ceph.com/issues/53897 [2] https://tracker.ceph.com/issues/63770 [3] https://tracker.ceph.com/issues/63771 Signed-off-by: Ilya Dryomov --- src/test/librbd/test_librbd.cc | 120 ++++++++++++++++++++++++++------- 1 file changed, 94 insertions(+), 26 deletions(-) diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc index e90569d68c6..77808b9721a 100644 --- a/src/test/librbd/test_librbd.cc +++ b/src/test/librbd/test_librbd.cc @@ -7715,12 +7715,14 @@ TYPED_TEST(DiffIterateTest, DiffIterateDeterministicPP) TYPED_TEST(DiffIterateTest, DiffIterateDiscard) { + REQUIRE(!is_feature_enabled(RBD_FEATURE_STRIPINGV2)); + librados::IoCtx ioctx; ASSERT_EQ(0, this->_rados.ioctx_create(this->m_pool_name.c_str(), ioctx)); librbd::RBD rbd; librbd::Image image; - int order = 0; + int order = 22; std::string name = this->get_temp_image_name(); uint64_t size = 20 << 20; @@ -7731,61 +7733,127 @@ TYPED_TEST(DiffIterateTest, DiffIterateDiscard) if (this->whole_object) { object_size = 1 << order; } - vector extents; - ceph::bufferlist bl; + std::vector extents; ASSERT_EQ(0, image.diff_iterate2(NULL, 0, size, true, this->whole_object, - vector_iterate_cb, (void *) &extents)); + vector_iterate_cb, &extents)); ASSERT_EQ(0u, extents.size()); - char data[256]; - memset(data, 1, sizeof(data)); - bl.append(data, 256); + ceph::bufferlist bl; + bl.append(std::string(256, '1')); ASSERT_EQ(256, image.write(0, 256, bl)); + ASSERT_EQ(256, image.write(1 << order, 256, bl)); ASSERT_EQ(0, image.diff_iterate2(NULL, 0, size, true, this->whole_object, - vector_iterate_cb, (void *) &extents)); - ASSERT_EQ(1u, extents.size()); + vector_iterate_cb, &extents)); + ASSERT_EQ(2u, extents.size()); ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]); - - int obj_ofs = 256; - ASSERT_EQ(1 << order, image.discard(0, 1 << order)); - + ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[1]); extents.clear(); + + ASSERT_EQ(size, image.discard(0, size)); ASSERT_EQ(0, image.diff_iterate2(NULL, 0, size, true, this->whole_object, - vector_iterate_cb, (void *) &extents)); + vector_iterate_cb, &extents)); ASSERT_EQ(0u, extents.size()); ASSERT_EQ(0, image.snap_create("snap1")); + ASSERT_EQ(256, image.write(0, 256, bl)); + ASSERT_EQ(256, image.write(1 << order, 256, bl)); ASSERT_EQ(0, image.diff_iterate2(NULL, 0, size, true, this->whole_object, - vector_iterate_cb, (void *) &extents)); - ASSERT_EQ(1u, extents.size()); + vector_iterate_cb, &extents)); + ASSERT_EQ(2u, extents.size()); ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]); + ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[1]); + extents.clear(); + ASSERT_EQ(0, image.snap_create("snap2")); - ASSERT_EQ(obj_ofs, image.discard(0, obj_ofs)); + ASSERT_EQ(1 << order, image.discard(0, 1 << order)); + ASSERT_EQ(0, image.diff_iterate2(NULL, 0, size, true, this->whole_object, + vector_iterate_cb, &extents)); + ASSERT_EQ(1u, extents.size()); + ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[0]); + extents.clear(); + + ASSERT_EQ(0, image.snap_create("snap3")); + // 1. beginning of time -> HEAD + ASSERT_EQ(0, image.diff_iterate2(NULL, 0, size, true, this->whole_object, + vector_iterate_cb, &extents)); + ASSERT_EQ(1u, extents.size()); + ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[0]); extents.clear(); - ASSERT_EQ(0, image.snap_set("snap2")); + + // 2. snap1 -> HEAD ASSERT_EQ(0, image.diff_iterate2("snap1", 0, size, true, this->whole_object, - vector_iterate_cb, (void *) &extents)); + vector_iterate_cb, &extents)); ASSERT_EQ(1u, extents.size()); - ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]); + ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[0]); + extents.clear(); - ASSERT_EQ(0, image.snap_set(NULL)); - ASSERT_EQ(1 << order, image.discard(0, 1 << order)); - ASSERT_EQ(0, image.snap_create("snap3")); + // 3. snap2 -> HEAD + ASSERT_EQ(0, image.diff_iterate2("snap2", 0, size, true, this->whole_object, + vector_iterate_cb, &extents)); + ASSERT_EQ(1u, extents.size()); + ASSERT_EQ(diff_extent(0, 256, false, object_size), extents[0]); + extents.clear(); + + // 4. snap3 -> HEAD + ASSERT_EQ(0, image.diff_iterate2("snap3", 0, size, true, this->whole_object, + vector_iterate_cb, &extents)); + ASSERT_EQ(0u, extents.size()); + + ASSERT_PASSED(this->validate_object_map, image); ASSERT_EQ(0, image.snap_set("snap3")); + // 5. beginning of time -> snap3 + ASSERT_EQ(0, image.diff_iterate2(NULL, 0, size, true, this->whole_object, + vector_iterate_cb, &extents)); + ASSERT_EQ(1u, extents.size()); + ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[0]); extents.clear(); + + // 6. snap1 -> snap3 ASSERT_EQ(0, image.diff_iterate2("snap1", 0, size, true, this->whole_object, - vector_iterate_cb, (void *) &extents)); - ASSERT_EQ(0u, extents.size()); + vector_iterate_cb, &extents)); + ASSERT_EQ(1u, extents.size()); + ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[0]); + extents.clear(); + // 7. snap2 -> snap3 ASSERT_EQ(0, image.diff_iterate2("snap2", 0, size, true, this->whole_object, - vector_iterate_cb, (void *) &extents)); + vector_iterate_cb, &extents)); ASSERT_EQ(1u, extents.size()); ASSERT_EQ(diff_extent(0, 256, false, object_size), extents[0]); + extents.clear(); + + ASSERT_PASSED(this->validate_object_map, image); + ASSERT_EQ(0, image.snap_set("snap2")); + + // 8. beginning of time -> snap2 + ASSERT_EQ(0, image.diff_iterate2(NULL, 0, size, true, this->whole_object, + vector_iterate_cb, &extents)); + ASSERT_EQ(2u, extents.size()); + ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]); + ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[1]); + extents.clear(); + + // 9. snap1 -> snap2 + ASSERT_EQ(0, image.diff_iterate2("snap1", 0, size, true, this->whole_object, + vector_iterate_cb, &extents)); + ASSERT_EQ(2u, extents.size()); + ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]); + ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[1]); + extents.clear(); + + ASSERT_PASSED(this->validate_object_map, image); + ASSERT_EQ(0, image.snap_set("snap1")); + + // 10. beginning of time -> snap1 + ASSERT_EQ(0, image.diff_iterate2(NULL, 0, size, true, this->whole_object, + vector_iterate_cb, &extents)); + ASSERT_EQ(0u, extents.size()); + ASSERT_PASSED(this->validate_object_map, image); } -- 2.39.5