]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
test/librbd: add TestInternal.FlattenInconsistentObjectMap 61168/head
authorIlya Dryomov <idryomov@gmail.com>
Tue, 17 Dec 2024 08:57:44 +0000 (09:57 +0100)
committerIlya Dryomov <idryomov@gmail.com>
Sun, 22 Dec 2024 15:28:09 +0000 (16:28 +0100)
Inject an object map with all possible inconsistencies before
flattening to ensure that something similar to commit 40af4f87b64f
("librbd: flatten operation should use object map") doesn't reappear
in a different form.

Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
(cherry picked from commit ffcd90313b9dd6e5aab8df0f9a5335a69785133c)

src/test/librbd/test_internal.cc

index 75a1985c0d959d9042029cd34ccf183b8c4e4c89..d696e7c5087e163149ef2234f943a714a5a94963 100644 (file)
@@ -1571,6 +1571,83 @@ TEST_F(TestInternal, FlattenNoEmptyObjects)
   rados_ioctx_destroy(d_ioctx);
 }
 
+TEST_F(TestInternal, FlattenInconsistentObjectMap)
+{
+  REQUIRE_FEATURE(RBD_FEATURE_LAYERING | RBD_FEATURE_OBJECT_MAP);
+  REQUIRE(!is_feature_enabled(RBD_FEATURE_STRIPINGV2));
+
+  librbd::ImageCtx* ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  librbd::NoOpProgressContext no_op;
+  ASSERT_EQ(0, ictx->operations->resize((1 << ictx->order) * 5, true, no_op));
+
+  bufferlist bl;
+  bl.append(std::string(256, '1'));
+  for (int i = 1; i < 5; i++) {
+    ASSERT_EQ(256, api::Io<>::write(*ictx, (1 << ictx->order) * i, 256,
+                                    bufferlist{bl}, 0));
+  }
+
+  ASSERT_EQ(0, snap_create(*ictx, "snap"));
+  ASSERT_EQ(0, snap_protect(*ictx, "snap"));
+
+  uint64_t features;
+  ASSERT_EQ(0, librbd::get_features(ictx, &features));
+
+  std::string clone_name = get_temp_image_name();
+  int order = ictx->order;
+  ASSERT_EQ(0, librbd::clone(m_ioctx, m_image_name.c_str(), "snap", m_ioctx,
+                             clone_name.c_str(), features, &order, 0, 0));
+
+  close_image(ictx);
+  ASSERT_EQ(0, open_image(clone_name, &ictx));
+
+  C_SaferCond lock_ctx;
+  {
+    std::shared_lock owner_locker{ictx->owner_lock};
+    ictx->exclusive_lock->try_acquire_lock(&lock_ctx);
+  }
+  ASSERT_EQ(0, lock_ctx.wait());
+  ASSERT_TRUE(ictx->exclusive_lock->is_lock_owner());
+
+  ceph::BitVector<2> inconsistent_object_map;
+  inconsistent_object_map.resize(5);
+  inconsistent_object_map[0] = OBJECT_NONEXISTENT;
+  inconsistent_object_map[1] = OBJECT_NONEXISTENT;
+  inconsistent_object_map[2] = OBJECT_EXISTS;
+  inconsistent_object_map[3] = OBJECT_EXISTS_CLEAN;
+  // OBJECT_PENDING shouldn't happen within parent overlap, but test
+  // anyway
+  inconsistent_object_map[4] = OBJECT_PENDING;
+
+  auto object_map = new librbd::ObjectMap<>(*ictx, CEPH_NOSNAP);
+  C_SaferCond save_ctx;
+  {
+    std::shared_lock owner_locker{ictx->owner_lock};
+    std::unique_lock image_locker{ictx->image_lock};
+    object_map->set_object_map(inconsistent_object_map);
+    object_map->aio_save(&save_ctx);
+  }
+  ASSERT_EQ(0, save_ctx.wait());
+  object_map->put();
+
+  close_image(ictx);
+  ASSERT_EQ(0, open_image(clone_name, &ictx));
+  ASSERT_EQ(0, ictx->operations->flatten(no_op));
+
+  bufferptr read_ptr(256);
+  bufferlist read_bl;
+  read_bl.push_back(read_ptr);
+
+  librbd::io::ReadResult read_result{&read_bl};
+  for (int i = 1; i < 5; i++) {
+    ASSERT_EQ(256, api::Io<>::read(*ictx, (1 << ictx->order) * i, 256,
+                                   librbd::io::ReadResult{read_result}, 0));
+    EXPECT_TRUE(bl.contents_equal(read_bl));
+  }
+}
+
 TEST_F(TestInternal, PoolMetadataConfApply) {
   REQUIRE_FORMAT_V2();