]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
test/crimson/seastore: add unittest cases for scattered allocation
authorXuehan Xu <xuxuehan@qianxin.com>
Mon, 6 Nov 2023 10:34:28 +0000 (18:34 +0800)
committerXuehan Xu <xuxuehan@qianxin.com>
Mon, 5 Feb 2024 08:27:50 +0000 (16:27 +0800)
Signed-off-by: Xuehan Xu <xuxuehan@qianxin.com>
src/crimson/common/errorator.h
src/crimson/os/seastore/async_cleaner.h
src/crimson/os/seastore/extent_placement_manager.h
src/crimson/os/seastore/random_block_manager.h
src/crimson/os/seastore/random_block_manager/block_rb_manager.cc
src/crimson/os/seastore/random_block_manager/block_rb_manager.h
src/test/crimson/seastore/test_transaction_manager.cc

index 656af5813560f165b9ad8f6b96e4c60b685997ba..ebc5a95bb3e6eeef1b47af2371cac86f3039c862 100644 (file)
@@ -11,6 +11,8 @@
 #include "crimson/common/utility.h"
 #include "include/ceph_assert.h"
 
+class transaction_manager_test_t;
+
 namespace crimson::interruptible {
 
 template <typename, typename>
@@ -528,6 +530,7 @@ private:
 
   protected:
     using base_t::get_exception;
+    friend class ::transaction_manager_test_t;
   public:
     using errorator_type = ::crimson::errorator<AllowedErrors...>;
     using promise_type = seastar::promise<ValueT>;
@@ -708,6 +711,9 @@ private:
     auto unsafe_get0() {
       return seastar::future<ValueT>::get0();
     }
+    void unsafe_wait() {
+      seastar::future<ValueT>::wait();
+    }
 
     template <class FuncT>
     _future finally(FuncT &&func) {
index 8f69d742d74169bab6f80484320c4d4652b49dee..1c94745d820c2196999c183678e12c8deea7d105 100644 (file)
@@ -1156,6 +1156,10 @@ public:
 
   virtual std::size_t get_reclaim_size_per_cycle() const = 0;
 
+#ifdef UNIT_TESTS_BUILT
+  virtual void prefill_fragmented_devices() {}
+#endif
+
   // test only
   virtual bool check_usage() = 0;
 
@@ -1677,6 +1681,17 @@ public:
     return 0;
   }
 
+#ifdef UNIT_TESTS_BUILT
+  void prefill_fragmented_devices() final {
+    LOG_PREFIX(RBMCleaner::prefill_fragmented_devices);
+    SUBDEBUG(seastore_cleaner, "");
+    auto rbs = rb_group->get_rb_managers();
+    for (auto p : rbs) {
+      p->prefill_fragmented_device();
+    }
+  }
+#endif
+
   RandomBlockManager* get_rbm(paddr_t paddr) {
     auto rbs = rb_group->get_rb_managers();
     for (auto p : rbs) {
index b1a4de2ef457a83ac82a503927664befe2ed2013..6a71a4ca986458981bb732a87a0f2d619b12dfaf 100644 (file)
@@ -48,6 +48,10 @@ public:
 
   virtual bool can_inplace_rewrite(Transaction& t,
     CachedExtentRef extent) = 0;
+
+#ifdef UNIT_TESTS_BUILT
+  virtual void prefill_fragmented_devices() {}
+#endif
 };
 using ExtentOolWriterRef = std::unique_ptr<ExtentOolWriter>;
 
@@ -152,6 +156,13 @@ public:
     return crimson::os::seastore::can_inplace_rewrite(extent->get_type());
   }
 
+#ifdef UNIT_TESTS_BUILT
+  void prefill_fragmented_devices() final {
+    LOG_PREFIX(RandomBlockOolWriter::prefill_fragmented_devices);
+    SUBDEBUG(seastore_epm, "");
+    return rb_cleaner->prefill_fragmented_devices();
+  }
+#endif
 private:
   alloc_write_iertr::future<> do_write(
     Transaction& t,
@@ -377,6 +388,16 @@ public:
     return allocs;
   }
 
+#ifdef UNIT_TESTS_BUILT
+  void prefill_fragmented_devices() {
+    LOG_PREFIX(ExtentPlacementManager::prefill_fragmented_devices);
+    SUBDEBUG(seastore_epm, "");
+    for (auto &writer : writer_refs) {
+      writer->prefill_fragmented_devices();
+    }
+  }
+#endif
+
   /**
    * dispatch_result_t
    *
index f0e0f018bd1034dfbba1fca87a8276792a34a7c2..fc45af3b2f5599f68dd102be1166d8fe4aa7b548 100644 (file)
@@ -149,6 +149,9 @@ public:
   virtual rbm_extent_state_t get_extent_state(paddr_t addr, size_t size) = 0;
   virtual size_t get_journal_size() const = 0;
   virtual ~RandomBlockManager() {}
+#ifdef UNIT_TESTS_BUILT
+  virtual void prefill_fragmented_device() = 0;
+#endif
 };
 using RandomBlockManagerRef = std::unique_ptr<RandomBlockManager>;
 
index cca520a9bfea36e27b992a5d63a3585864fccfec..715aafbc8a8e95263f320605c1a03745eb21b0c1 100644 (file)
@@ -182,6 +182,25 @@ BlockRBManager::write_ertr::future<> BlockRBManager::write(
     std::move(bptr));
 }
 
+#ifdef UNIT_TESTS_BUILT
+void BlockRBManager::prefill_fragmented_device()
+{
+  LOG_PREFIX(BlockRBManager::prefill_fragmented_device);
+  // the first 2 blocks must be allocated to lba root
+  // and backref root during mkfs
+  for (size_t block = get_block_size() * 2;
+      block <= get_size() - get_block_size() * 2;
+      block += get_block_size() * 2) {
+    DEBUG("marking {}~{} used",
+      get_start_rbm_addr() + block,
+      get_block_size());
+    allocator->mark_extent_used(
+      get_start_rbm_addr() + block,
+      get_block_size());
+  }
+}
+#endif
+
 std::ostream &operator<<(std::ostream &out, const rbm_metadata_header_t &header)
 {
   out << " rbm_metadata_header_t(size=" << header.size
index 14d2a28a314609a85922982fcc9b83e6b8148ce8..bc33710eee0203b1d574a62d167dff51a4af7612 100644 (file)
@@ -127,6 +127,10 @@ public:
     return device->get_journal_size();
   }
 
+#ifdef UNIT_TESTS_BUILT
+  void prefill_fragmented_device() final;
+#endif
+
 private:
   /*
    * this contains the number of bitmap blocks, free blocks and
index 378644dafa8404a39ae46fc056502e897c982a55..869eae716cd6e2a21646c7dda525d6a7a6f45346 100644 (file)
@@ -398,6 +398,40 @@ struct transaction_manager_test_t :
     return extent;
   }
 
+  std::vector<TestBlockRef> alloc_extents(
+    test_transaction_t &t,
+    laddr_t hint,
+    extent_len_t len,
+    char contents) {
+    auto extents = with_trans_intr(*(t.t), [&](auto& trans) {
+      return tm->alloc_data_extents<TestBlock>(trans, hint, len);
+    }).unsafe_get0();
+    size_t length = 0;
+    for (auto &extent : extents) {
+      extent->set_contents(contents);
+      length += extent->get_length();
+      EXPECT_FALSE(test_mappings.contains(extent->get_laddr(), t.mapping_delta));
+      test_mappings.alloced(hint, *extent, t.mapping_delta);
+    }
+    EXPECT_EQ(len, length);
+    return extents;
+  }
+
+  void alloc_extents_deemed_fail(
+    test_transaction_t &t,
+    laddr_t hint,
+    extent_len_t len,
+    char contents)
+  {
+    std::cout << __func__ << std::endl;
+    auto fut = with_trans_intr(*(t.t), [&](auto& trans) {
+      return tm->alloc_data_extents<TestBlock>(trans, hint, len);
+    });
+    fut.unsafe_wait();
+    assert(fut.failed());
+    (void)fut.get_exception();
+  }
+
   TestBlockRef alloc_extent(
     test_transaction_t &t,
     laddr_t hint,
@@ -1675,6 +1709,30 @@ struct tm_multi_tier_device_test_t :
   tm_multi_tier_device_test_t() : transaction_manager_test_t(1, 2) {}
 };
 
+struct tm_random_block_device_test_t :
+  public transaction_manager_test_t {
+
+  tm_random_block_device_test_t() : transaction_manager_test_t(1, 0) {}
+};
+
+TEST_P(tm_random_block_device_test_t, scatter_allocation)
+{
+  run_async([this] {
+    constexpr laddr_t ADDR = 0xFF * 4096;
+    epm->prefill_fragmented_devices();
+    auto t = create_transaction();
+    for (int i = 0; i < 1991; i++) {
+      auto extents = alloc_extents(t, ADDR + i * 16384, 16384, 'a');
+      std::cout << "num of extents: " << extents.size() << std::endl;
+    }
+    alloc_extents_deemed_fail(t, ADDR + 1991 * 16384, 16384, 'a');
+    check_mappings(t);
+    check();
+    submit_transaction(std::move(t));
+    check();
+  });
+}
+
 TEST_P(tm_single_device_test_t, basic)
 {
   constexpr laddr_t SIZE = 4096;
@@ -2133,3 +2191,11 @@ INSTANTIATE_TEST_SUITE_P(
     "segmented"
   )
 );
+
+INSTANTIATE_TEST_SUITE_P(
+  transaction_manager_test,
+  tm_random_block_device_test_t,
+  ::testing::Values (
+    "circularbounded"
+  )
+);