]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
test/bluestore_types: introduce basic UT for new ExtentMap::dup
authorIgor Fedotov <igor.fedotov@croit.io>
Wed, 19 Apr 2023 15:00:10 +0000 (18:00 +0300)
committerAdam Kupczyk <akupczyk@ibm.com>
Wed, 9 Aug 2023 07:51:58 +0000 (07:51 +0000)
Signed-off-by: Igor Fedotov <igor.fedotov@croit.io>
src/test/objectstore/test_bluestore_types.cc

index 18ccaff913d2ae421f3fd830870fee82cf56c4f0..eac7b223cdbd04afdb09fe5861092e770cceae8b 100644 (file)
@@ -1285,6 +1285,172 @@ TEST(ExtentMap, compress_extent_map)
 }
 
 
+TEST(ExtentMap, dup_extent_map)
+{
+  BlueStore store(g_ceph_context, "", 4096);
+  BlueStore::OnodeCacheShard *oc = BlueStore::OnodeCacheShard::create(
+    g_ceph_context, "lru", NULL);
+  BlueStore::BufferCacheShard *bc = BlueStore::BufferCacheShard::create(
+    g_ceph_context, "lru", NULL);
+
+  size_t csum_order = 12; //1^12 = 4096 bytes
+  auto coll = ceph::make_ref<BlueStore::Collection>(&store, oc, bc, coll_t());
+  std::unique_ptr<ceph::Formatter> formatter(Formatter::create("json"));
+
+  ///////////////////////////
+  //constructing onode1
+  BlueStore::OnodeRef onode1(new BlueStore::Onode(coll.get(), ghobject_t(), ""));
+  
+  //BlueStore::ExtentMap em1(&onode1,
+  //  g_ceph_context->_conf->bluestore_extent_map_inline_shard_prealloc_size);
+  BlueStore::ExtentMap& em1 = onode1->extent_map;
+  ///////////////////////////
+  // constructing extent/Blob: 0x0~2000 at <0x100000~2000>
+  size_t ext1_offs = 0x0;
+  size_t ext1_len = 0x2000;
+  size_t ext1_boffs = 0x0;
+  BlueStore::BlobRef b1(new BlueStore::Blob);
+  b1->shared_blob = new BlueStore::SharedBlob(coll.get());
+  auto &_b1 = b1->dirty_blob();
+  _b1.init_csum(Checksummer::CSUM_CRC32C, csum_order, ext1_len);
+  for(size_t i = 0; i < _b1.get_csum_count(); i++) {
+    *(_b1.get_csum_item_ptr(i)) = i + 1;
+  }
+  PExtentVector pextents;
+  pextents.emplace_back(0x100000, ext1_len);
+  _b1.allocated(0, ext1_len, pextents);
+
+  auto *ext1 = new BlueStore::Extent(ext1_offs, ext1_boffs, ext1_len, b1);
+  em1.extent_map.insert(*ext1);
+  b1->get_ref(coll.get(), ext1->blob_offset, ext1->length);
+  _b1.mark_used(ext1->blob_offset, ext1->length);
+
+  ///////////////////////////
+  //constructing onode2 which is a full clone from onode1
+  BlueStore::OnodeRef onode2(new BlueStore::Onode(coll.get(), ghobject_t(), ""));
+  //BlueStore::ExtentMap em2(&onode2,
+  //  g_ceph_context->_conf->bluestore_extent_map_inline_shard_prealloc_size);
+  BlueStore::ExtentMap& em2 = onode2->extent_map;
+  {
+    BlueStore::TransContext txc(store.cct, coll.get(), nullptr, nullptr);
+
+    //em1.dup(&store, &txc, coll, em2, ext1_offs, ext1_len, ext1_offs);
+    onode1->extent_map.dup(&store, &txc, coll, onode1, onode2, ext1_offs, ext1_len, ext1_offs);
+
+    em1.dump(formatter.get()); // see the log if any
+    formatter->flush(std::cout);
+    std::cout << std::endl;
+    em2.dump(formatter.get());
+    formatter->flush(std::cout);
+    std::cout << std::endl;
+
+    ASSERT_TRUE(b1->get_blob().is_shared());
+    ASSERT_EQ(b1->get_referenced_bytes(), ext1_len);
+
+    BlueStore::BlobRef b2 = em2.seek_lextent(ext1_offs)->blob;
+    ASSERT_TRUE(b2->get_blob().is_shared());
+    ASSERT_EQ(b2->get_referenced_bytes(), ext1_len);
+    ASSERT_EQ(b1->shared_blob, b2->shared_blob);
+    auto &_b2 = b2->get_blob();
+    ASSERT_EQ(_b1.get_csum_count(), _b2.get_csum_count());
+    for(size_t i = 0; i < _b2.get_csum_count(); i++) {
+      ASSERT_EQ(*(_b1.get_csum_item_ptr(i)), *(_b2.get_csum_item_ptr(i)));
+    }
+  }
+
+  ///////////////////////////
+  //constructing onode3 which is partial clone (tail part) from onode2
+  BlueStore::OnodeRef onode3(new BlueStore::Onode(coll.get(), ghobject_t(), ""));
+  //BlueStore::ExtentMap em3(&onode3,
+  //  g_ceph_context->_conf->bluestore_extent_map_inline_shard_prealloc_size);
+  BlueStore::ExtentMap& em3 = onode3->extent_map;
+  {
+    size_t clone_shift = 0x1000;
+    ceph_assert(ext1_len > clone_shift);
+    size_t clone_offs = ext1_offs + clone_shift;
+    size_t clone_len = ext1_len - clone_shift;
+    BlueStore::TransContext txc(store.cct, coll.get(), nullptr, nullptr);
+
+    onode1->extent_map.dup(&store, &txc, coll, onode1, onode3, clone_offs, clone_len, clone_offs);
+    em1.dump(formatter.get()); // see the log if any
+    formatter->flush(std::cout);
+    std::cout << std::endl;
+    em3.dump(formatter.get());
+    formatter->flush(std::cout);
+    std::cout << std::endl;
+
+    // make sure (basically) onode1&2 are unmodified
+    BlueStore::BlobRef b1 = em1.seek_lextent(ext1_offs)->blob;
+    BlueStore::BlobRef b2 = em2.seek_lextent(ext1_offs)->blob;
+    ASSERT_EQ(b1->shared_blob, b2->shared_blob);
+
+    BlueStore::Extent &ext3 = *em3.seek_lextent(clone_offs);
+    ASSERT_EQ(ext3.blob_offset, clone_shift);
+    ASSERT_EQ(ext3.length, clone_len);
+    BlueStore::BlobRef b3 = ext3.blob;
+    ASSERT_TRUE(b3->get_blob().is_shared());
+    ASSERT_EQ(b3->shared_blob, b1->shared_blob);
+    ASSERT_EQ(b3->get_referenced_bytes(), clone_len);
+    auto ll = b3->get_blob().get_logical_length();
+    ASSERT_EQ(ll, ext1_len);
+    auto &_b3 = b3->get_blob();
+    ASSERT_EQ(_b1.get_csum_count(), _b3.get_csum_count());
+    for(size_t i = 0; i < _b3.get_csum_count(); i++) {
+      ASSERT_EQ(*(_b1.get_csum_item_ptr(i)), *(_b3.get_csum_item_ptr(i)));
+    }
+  }
+
+  ///////////////////////////
+  //constructing onode4 which is partial clone (head part) from onode2
+  BlueStore::OnodeRef onode4(new BlueStore::Onode(coll.get(), ghobject_t(), ""));
+  //BlueStore::ExtentMap em4(&onode4,
+  //  g_ceph_context->_conf->bluestore_extent_map_inline_shard_prealloc_size);
+  BlueStore::ExtentMap& em4 = onode4->extent_map;
+
+  {
+    size_t clone_shift = 0;
+    size_t clone_len = 0x1000;
+    ceph_assert(ext1_len >= clone_shift + clone_len);
+    size_t clone_offs = ext1_offs + clone_shift;
+    BlueStore::TransContext txc(store.cct, coll.get(), nullptr, nullptr);
+
+    onode2->extent_map.dup(&store, &txc, coll, onode2, onode4, clone_offs, clone_len, clone_offs);
+    em2.dump(formatter.get()); // see the log if any
+    formatter->flush(std::cout);
+    std::cout << std::endl;
+    em4.dump(formatter.get());
+    formatter->flush(std::cout);
+    std::cout << std::endl;
+
+    // make sure (basically) onode1&2 are unmodified
+    BlueStore::BlobRef b1 = em1.seek_lextent(ext1_offs)->blob;
+    BlueStore::BlobRef b2 = em2.seek_lextent(ext1_offs)->blob;
+    BlueStore::BlobRef b3 = em3.seek_lextent(ext1_offs)->blob;
+    ASSERT_EQ(b1->shared_blob, b2->shared_blob);
+    ASSERT_EQ(b1->shared_blob, b3->shared_blob);
+    auto &_b2 = b2->get_blob();
+
+    BlueStore::Extent &ext4 = *em4.seek_lextent(clone_offs);
+    ASSERT_EQ(ext4.blob_offset, clone_shift);
+    ASSERT_EQ(ext4.length, clone_len);
+    BlueStore::BlobRef b4 = ext4.blob;
+    ASSERT_TRUE(b4->get_blob().is_shared());
+    ASSERT_EQ(b4->shared_blob, b2->shared_blob);
+    ASSERT_EQ(b4->get_referenced_bytes(), clone_len);
+    auto &_b4 = b4->get_blob();
+    auto ll = _b4.get_logical_length();
+    auto csum_entries = ll / (1 << csum_order);
+    ASSERT_EQ(ll, clone_len);
+    ASSERT_EQ(csum_entries, _b4.get_csum_count());
+
+    ASSERT_GT(_b2.get_csum_count(), csum_entries);
+    for(size_t i = 0; i < csum_entries; i++) {
+      ASSERT_EQ(*(_b2.get_csum_item_ptr(i)), *(_b4.get_csum_item_ptr(i)));
+    }
+  }
+}
+
+
 void clear_and_dispose(BlueStore::old_extent_map_t& old_em)
 {
   auto oep = old_em.begin();