From: Igor Fedotov Date: Tue, 22 Nov 2016 21:26:56 +0000 (+0000) Subject: os/bluestore: add test case for GC X-Git-Tag: v12.0.1~379^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=b108eb6ca90e228688c90abca7d29a33cf563ae8;p=ceph.git os/bluestore: add test case for GC Signed-off-by: Igor Fedotov --- diff --git a/src/test/objectstore/test_bluestore_types.cc b/src/test/objectstore/test_bluestore_types.cc index 43ac455cacda..6c0284c6e9a3 100644 --- a/src/test/objectstore/test_bluestore_types.cc +++ b/src/test/objectstore/test_bluestore_types.cc @@ -1214,6 +1214,290 @@ TEST(ExtentMap, compress_extent_map) ASSERT_EQ(6u, em.extent_map.size()); } +TEST(GarbageCollector, BasicTest) +{ + BlueStore::LRUCache cache(g_ceph_context); + BlueStore store(g_ceph_context, "", 4096); + BlueStore::Collection coll(&store, &cache, coll_t()); + BlueStore::Onode onode(&coll, ghobject_t(), ""); + BlueStore::ExtentMap em(&onode); + + BlueStore::extent_map_t old_extents; + + + /* + min_alloc_size = 4096 + original disposition + extent1 + -> blob1 + extent2 + -> blob2 + extent3 + -> blob1 + extent4 + -> blob3 + on write(300~100) resulted in + extent1 + -> blob1 + extent2 + -> blob2 + extent3 + -> blob4 + extent4 + -> blob3 + */ + { + BlueStore::GarbageCollector gc(g_ceph_context); + int64_t saving; + BlueStore::BlobRef b1(new BlueStore::Blob); + BlueStore::BlobRef b2(new BlueStore::Blob); + BlueStore::BlobRef b3(new BlueStore::Blob); + BlueStore::BlobRef b4(new BlueStore::Blob); + b1->shared_blob = new BlueStore::SharedBlob(&coll); + b2->shared_blob = new BlueStore::SharedBlob(&coll); + b3->shared_blob = new BlueStore::SharedBlob(&coll); + b4->shared_blob = new BlueStore::SharedBlob(&coll); + b1->dirty_blob().set_flag(bluestore_blob_t::FLAG_COMPRESSED); + b1->dirty_blob().compressed_length_orig = 0x2000; + b1->dirty_blob().compressed_length = 0x1000; + b1->dirty_blob().extents.emplace_back(0, 0x1000); + b2->dirty_blob().extents.emplace_back(1, 0x1000); + b3->dirty_blob().extents.emplace_back(2, 0x1000); + b4->dirty_blob().extents.emplace_back(3, 0x1000); + em.extent_map.insert(*new BlueStore::Extent(100, 100, 10, b1)); + b1->get_ref(&coll, 100, 10); + em.extent_map.insert(*new BlueStore::Extent(200, 200, 10, b2)); + b2->get_ref(&coll, 200, 10); + em.extent_map.insert(*new BlueStore::Extent(300, 300, 100, b4)); + b4->get_ref(&coll, 300, 100); + em.extent_map.insert(*new BlueStore::Extent(4096, 0, 10, b3)); + b3->get_ref(&coll, 0, 10); + + old_extents.push_back(*new BlueStore::Extent(300, 300, 10, b1)); + b1->get_ref(&coll, 300, 10); + + saving = gc.estimate(300, 100, em, old_extents, 4096); + ASSERT_EQ(saving, 1); + auto& to_collect = gc.get_extents_to_collect(); + ASSERT_EQ(to_collect.size(), 1u); + ASSERT_EQ(to_collect[0], AllocExtent(100,10) ); + + em.clear(); + old_extents.clear(); + } + /* + original disposition + min_alloc_size = 0x10000 + extent1 + -> blob1 + Write 0x8000~37000 resulted in the following extent map prior to GC + for the last write_small(0x30000~0xf000): + + extent1 + -> blob1 + extent2 + -> blob2 + extent3 + -> blob3 + extent4 + -> blob4 + extent5 + -> blob1 + */ + { + BlueStore store(g_ceph_context, "", 0x10000); + BlueStore::Collection coll(&store, &cache, coll_t()); + BlueStore::Onode onode(&coll, ghobject_t(), ""); + BlueStore::ExtentMap em(&onode); + + BlueStore::extent_map_t old_extents; + BlueStore::GarbageCollector gc(g_ceph_context); + int64_t saving; + BlueStore::BlobRef b1(new BlueStore::Blob); + BlueStore::BlobRef b2(new BlueStore::Blob); + BlueStore::BlobRef b3(new BlueStore::Blob); + BlueStore::BlobRef b4(new BlueStore::Blob); + b1->shared_blob = new BlueStore::SharedBlob(&coll); + b2->shared_blob = new BlueStore::SharedBlob(&coll); + b3->shared_blob = new BlueStore::SharedBlob(&coll); + b4->shared_blob = new BlueStore::SharedBlob(&coll); + b1->dirty_blob().set_flag(bluestore_blob_t::FLAG_COMPRESSED); + b1->dirty_blob().extents.emplace_back(0, 0x20000); + b1->dirty_blob().compressed_length = 0x20000; + b1->dirty_blob().compressed_length_orig = 0x40000; + b2->dirty_blob().extents.emplace_back(1, 0x10000); + b3->dirty_blob().extents.emplace_back(2, 0x20000); + b4->dirty_blob().extents.emplace_back(3, 0x10000); + + em.extent_map.insert(*new BlueStore::Extent(0, 0, 0x8000, b1)); + b1->get_ref(&coll, 0, 0x8000); + em.extent_map.insert( + *new BlueStore::Extent(0x8000, 0x8000, 0x8000, b2)); // new extent + b2->get_ref(&coll, 0x8000, 0x8000); + em.extent_map.insert( + *new BlueStore::Extent(0x10000, 0, 0x20000, b3)); // new extent + b3->get_ref(&coll, 0, 0x20000); + em.extent_map.insert( + *new BlueStore::Extent(0x30000, 0, 0xf000, b4)); // new extent + b4->get_ref(&coll, 0, 0xf000); + em.extent_map.insert(*new BlueStore::Extent(0x3f000, 0x3f000, 0x1000, b1)); + b1->get_ref(&coll, 0x3f000, 0x1000); + + old_extents.push_back(*new BlueStore::Extent(0x8000, 0x8000, 0x8000, b1)); + b1->get_ref(&coll, 0x8000, 0x8000); + old_extents.push_back( + *new BlueStore::Extent(0x10000, 0x10000, 0x20000, b1)); + b1->get_ref(&coll, 0x10000, 0x20000); + old_extents.push_back(*new BlueStore::Extent(0x30000, 0x30000, 0xf000, b1)); + b1->get_ref(&coll, 0x30000, 0xf000); + + saving = gc.estimate(0x30000, 0xf000, em, old_extents, 0x10000); + ASSERT_EQ(saving, 2); + auto& to_collect = gc.get_extents_to_collect(); + ASSERT_EQ(to_collect.size(), 2u); + ASSERT_TRUE(to_collect[0] == AllocExtent(0x0,0x8000) || + to_collect[1] == AllocExtent(0x0,0x8000)); + ASSERT_TRUE(to_collect[0] == AllocExtent(0x3f000,0x1000) || + to_collect[1] == AllocExtent(0x3f000,0x1000)); + + em.clear(); + old_extents.clear(); + } + /* + original disposition + min_alloc_size = 0x1000 + extent1 + -> blob1 + write 0x3000~4000 resulted in the following extent map + (future feature - suppose we can compress incoming write prior to + GC invocation) + + extent1 + -> blob1 + extent2 + -> blob2 + */ + { + BlueStore::GarbageCollector gc(g_ceph_context); + int64_t saving; + BlueStore::BlobRef b1(new BlueStore::Blob); + BlueStore::BlobRef b2(new BlueStore::Blob); + b1->shared_blob = new BlueStore::SharedBlob(&coll); + b2->shared_blob = new BlueStore::SharedBlob(&coll); + b1->dirty_blob().set_flag(bluestore_blob_t::FLAG_COMPRESSED); + b1->dirty_blob().extents.emplace_back(0, 0x2000); + b1->dirty_blob().compressed_length_orig = 0x4000; + b1->dirty_blob().compressed_length = 0x2000; + b2->dirty_blob().set_flag(bluestore_blob_t::FLAG_COMPRESSED); + b2->dirty_blob().extents.emplace_back(0, 0x2000); + b2->dirty_blob().compressed_length_orig = 0x4000; + b2->dirty_blob().compressed_length = 0x2000; + + em.extent_map.insert(*new BlueStore::Extent(0, 0, 0x3000, b1)); + b1->get_ref(&coll, 0, 0x3000); + em.extent_map.insert( + *new BlueStore::Extent(0x3000, 0, 0x4000, b2)); // new extent + b2->get_ref(&coll, 0, 0x4000); + + old_extents.push_back(*new BlueStore::Extent(0x3000, 0x3000, 0x1000, b1)); + b1->get_ref(&coll, 0x3000, 0x1000); + + saving = gc.estimate(0x3000, 0x4000, em, old_extents, 0x1000); + ASSERT_EQ(saving, 0); + auto& to_collect = gc.get_extents_to_collect(); + ASSERT_EQ(to_collect.size(), 0u); + em.clear(); + old_extents.clear(); + } + /* + original disposition + min_alloc_size = 0x10000 + extent0 + -> blob0 + extent1 + -> blob1 + write 0x8000~37000 resulted in the following extent map prior + to GC for the last write_small(0x30000~0xf000) + + extent0 + -> blob0 + extent2 + -> blob2 + extent3 + -> blob3 + extent4 + -> blob4 + extent5 + -> blob1 + */ + { + BlueStore store(g_ceph_context, "", 0x10000); + BlueStore::Collection coll(&store, &cache, coll_t()); + BlueStore::Onode onode(&coll, ghobject_t(), ""); + BlueStore::ExtentMap em(&onode); + + BlueStore::extent_map_t old_extents; + BlueStore::GarbageCollector gc(g_ceph_context); + int64_t saving; + BlueStore::BlobRef b0(new BlueStore::Blob); + BlueStore::BlobRef b1(new BlueStore::Blob); + BlueStore::BlobRef b2(new BlueStore::Blob); + BlueStore::BlobRef b3(new BlueStore::Blob); + BlueStore::BlobRef b4(new BlueStore::Blob); + b0->shared_blob = new BlueStore::SharedBlob(&coll); + b1->shared_blob = new BlueStore::SharedBlob(&coll); + b2->shared_blob = new BlueStore::SharedBlob(&coll); + b3->shared_blob = new BlueStore::SharedBlob(&coll); + b4->shared_blob = new BlueStore::SharedBlob(&coll); + b0->dirty_blob().set_flag(bluestore_blob_t::FLAG_COMPRESSED); + b0->dirty_blob().extents.emplace_back(0, 0x10000); + b0->dirty_blob().compressed_length_orig = 0x20000; + b0->dirty_blob().compressed_length = 0x10000; + b1->dirty_blob().set_flag(bluestore_blob_t::FLAG_COMPRESSED); + b1->dirty_blob().extents.emplace_back(0, 0x10000); + b1->dirty_blob().compressed_length_orig = 0x20000; + b1->dirty_blob().compressed_length = 0x10000; + b2->dirty_blob().extents.emplace_back(1, 0x10000); + b3->dirty_blob().extents.emplace_back(2, 0x20000); + b4->dirty_blob().extents.emplace_back(3, 0x1000); + + em.extent_map.insert(*new BlueStore::Extent(0, 0, 0x8000, b0)); + b0->get_ref(&coll, 0, 0x8000); + em.extent_map.insert( + *new BlueStore::Extent(0x8000, 0x8000, 0x8000, b2)); // new extent + b2->get_ref(&coll, 0x8000, 0x8000); + em.extent_map.insert( + *new BlueStore::Extent(0x10000, 0, 0x20000, b3)); // new extent + b3->get_ref(&coll, 0, 0x20000); + em.extent_map.insert( + *new BlueStore::Extent(0x30000, 0, 0xf000, b4)); // new extent + b4->get_ref(&coll, 0, 0xf000); + em.extent_map.insert(*new BlueStore::Extent(0x3f000, 0x1f000, 0x1000, b1)); + b1->get_ref(&coll, 0x1f000, 0x1000); + + old_extents.push_back(*new BlueStore::Extent(0x8000, 0x8000, 0x8000, b0)); + b0->get_ref(&coll, 0x8000, 0x8000); + old_extents.push_back( + *new BlueStore::Extent(0x10000, 0x10000, 0x10000, b0)); + b0->get_ref(&coll, 0x10000, 0x10000); + old_extents.push_back( + *new BlueStore::Extent(0x20000, 0x00000, 0x1f000, b1)); + b1->get_ref(&coll, 0x0, 0x1f000); + + saving = gc.estimate(0x30000, 0xf000, em, old_extents, 0x10000); + ASSERT_EQ(saving, 2); + auto& to_collect = gc.get_extents_to_collect(); + ASSERT_EQ(to_collect.size(), 2u); + ASSERT_TRUE(to_collect[0] == AllocExtent(0x0,0x8000) || + to_collect[1] == AllocExtent(0x0,0x8000)); + ASSERT_TRUE(to_collect[0] == AllocExtent(0x3f000,0x1000) || + to_collect[1] == AllocExtent(0x3f000,0x1000)); + + em.clear(); + old_extents.clear(); + } + } + int main(int argc, char **argv) { vector args; argv_to_vec(argc, (const char **)argv, args);