]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
crimson/os/seastore: add test workload to promote/evict aggressively
authorZhang Song <zhangsong02@qianxin.com>
Wed, 3 Sep 2025 08:10:54 +0000 (16:10 +0800)
committerXuehan Xu <xuxuehan@qianxin.com>
Sat, 23 May 2026 09:12:01 +0000 (17:12 +0800)
Signed-off-by: Zhang Song <zhangsong02@qianxin.com>
Signed-off-by: Xuehan Xu <xuxuehan@qianxin.com>
18 files changed:
ceph.spec.in
src/common/options/crimson.yaml.in
src/crimson/os/seastore/CMakeLists.txt
src/crimson/os/seastore/async_cleaner.cc
src/crimson/os/seastore/async_cleaner.h
src/crimson/os/seastore/backref/btree_backref_manager.cc
src/crimson/os/seastore/backref/btree_backref_manager.h
src/crimson/os/seastore/backref_manager.h
src/crimson/os/seastore/cache.cc
src/crimson/os/seastore/cache.h
src/crimson/os/seastore/cached_extent.cc
src/crimson/os/seastore/extent_pinboard.cc
src/crimson/os/seastore/extent_placement_manager.cc
src/crimson/os/seastore/extent_placement_manager.h
src/crimson/os/seastore/seastore.cc
src/crimson/os/seastore/transaction_manager.cc
src/crimson/os/seastore/transaction_manager.h
src/test/crimson/seastore/test_transaction_manager.cc

index 780889d5e738d876dfecc728dba58b50c4fc119e..91b37da09cf81abe7f570af3d06169ff274f4d63 100644 (file)
@@ -92,6 +92,7 @@
 %endif
 %endif
 %bcond_without crimson
+%bcond_with crimson_test_workload
 %if 0%{?suse_version} || 0%{?openEuler}
 %bcond_with jaeger
 %else
@@ -1536,6 +1537,9 @@ cmake .. \
 %if 0%{with crimson}
     -DWITH_CRIMSON:BOOL=ON \
     -DWITH_JAEGER:BOOL=OFF \
+%endif
+%if 0%{with crimson_test_workload}
+    -DENABLE_CRIMSON_TEST_WORKLOAD:BOOL=ON \
 %endif
     -DWITH_GRAFANA:BOOL=ON \
 %if %{with sccache}
index 5c31100954c0820885c66809b52230c87e710909..3dba1a6b998ff29692debbf7e169f2dc0ad8b71a 100644 (file)
@@ -143,6 +143,11 @@ options:
   desc: CPU cores on which POSIX threads alienized to seastar will run in cpuset(7) format
   flags:
   - startup
+- name: crimson_test_workload
+  type: bool
+  level: dev
+  desc: enable test workload
+  default: false
 
 # Seastore options
 
@@ -348,3 +353,18 @@ options:
   level: dev
   desc: select write through policy when data length is greater than this value.
   default: 512_K
+- name: seastore_test_workload_write_through_probability
+  type: float
+  level: dev
+  desc: the probability of write the incoming data to slow devices
+  default: 0.5
+- name: seastore_test_workload_2Q_promote_probability
+  type: float
+  level: dev
+  desc: the probability of promote the extents to the faster devices
+  default: 0.5
+- name: seastore_test_workload_force_prcess_background_tasks_period
+  type: uint
+  level: dev
+  desc: the seconds of period for force process background tasks
+  default: 5
index 1a707cfea5b063db59a895188afb46a9906d4eb9..5d9d6e5a4e7ae387fd9c0af85d7ab54940818688 100644 (file)
@@ -81,3 +81,11 @@ endif()
 
 set_target_properties(crimson-seastore PROPERTIES
   JOB_POOL_COMPILE heavy_compile_job_pool)
+
+option(ENABLE_CRIMSON_TEST_WORKLOAD "enable crimson test workload" OFF)
+if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
+  set(ENABLE_CRIMSON_TEST_WORKLOAD ON CACHE BOOL "enable crimson test workload" FORCE)
+endif()
+if(ENABLE_CRIMSON_TEST_WORKLOAD)
+  target_compile_definitions(crimson-seastore PUBLIC CRIMSON_TEST_WORKLOAD)
+endif()
index 593b6ddb46ceafa313269c9282b0f618692adecf..6f35c98d30e9c8a19897065dc170476b976190ef 100644 (file)
@@ -601,10 +601,10 @@ std::size_t JournalTrimmerImpl::get_alloc_journal_size() const
   return static_cast<std::size_t>(ret);
 }
 
-seastar::future<> JournalTrimmerImpl::trim() {
+seastar::future<> JournalTrimmerImpl::trim(bool force) {
   return seastar::when_all(
-    [this] {
-      if (should_trim_alloc()) {
+    [this, force] {
+      if (force || should_trim_alloc()) {
         return trim_alloc(
         ).handle_error(
           crimson::ct_error::assert_all{
@@ -615,8 +615,8 @@ seastar::future<> JournalTrimmerImpl::trim() {
         return seastar::now();
       }
     },
-    [this] {
-      if (should_start_trim_dirty()) {
+    [this, force] {
+      if (force || should_start_trim_dirty()) {
         return trim_dirty(
         ).handle_error(
           crimson::ct_error::assert_all{
index 0ecf9ad707909332a767a1570b268ad6ea7db823..005e4bcdfb6d353af3ddddd5dcf36d6b84b7fed3 100644 (file)
@@ -375,6 +375,12 @@ public:
     Transaction &t,
     CachedExtentRef extent) = 0;
 
+#ifdef CRIMSON_TEST_WORKLOAD
+  virtual promote_extent_ret promote_extents_from_disk(
+    Transaction &t,
+    paddr_t paddr) = 0;
+#endif
+
   /**
    * demote_region
    *
@@ -666,7 +672,7 @@ public:
     reserved_usage -= usage;
   }
 
-  seastar::future<> trim();
+  seastar::future<> trim(bool force);
 
   static JournalTrimmerImplRef create(
       store_index_t store_index,
index 93df968644eaeddf945f7e57cca33e1bb512eebb..e394758a76bc68ed719165883b069cf1ab95f9ff 100644 (file)
@@ -1,6 +1,7 @@
 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*-
 // vim: ts=8 sw=2 sts=2 expandtab
 
+#include "crimson/common/coroutine.h"
 #include "crimson/os/seastore/backref/btree_backref_manager.h"
 
 SET_SUBSYS(seastore_backref);
@@ -456,6 +457,51 @@ BtreeBackrefManager::scan_mapped_space(
   });
 }
 
+#ifdef CRIMSON_TEST_WORKLOAD
+BtreeBackrefManager::scan_device_ret
+BtreeBackrefManager::scan_device(
+  Transaction &t,
+  paddr_t paddr,
+  scan_device_func_t &f)
+{
+  LOG_PREFIX(BtreeBackrefManager::scan_device);
+  auto c = get_context(t);
+  auto croot = co_await cache.get_root(t);
+  auto btree = BackrefBtree(croot);
+  auto iter = co_await btree.lower_bound(c, paddr);
+  while (!iter.is_end()) {
+    auto key = iter.get_key();
+    auto bentry = cache.get_cached_backref_entry(key);
+    if (bentry) {
+      assert(bentry->paddr == key);
+    }
+    if (bentry && bentry->laddr == L_ADDR_NULL) {
+      INFOT("{} is removed", t, bentry->paddr);
+      iter = co_await iter.next(c);
+      continue;
+    }
+    if (key.get_device_id() == paddr.get_device_id()) {
+      auto val = iter.get_val();
+      if (bentry && bentry->laddr != val.laddr) {
+        INFOT("{} changed from {} to {}",
+          t, bentry->paddr, val.laddr, bentry->laddr);
+        iter = co_await iter.next(c);
+        continue;
+      }
+      INFOT("scanned {}, {}", t, key, val.laddr);
+      auto ret = co_await f(key, val.len, val.type, val.laddr);
+      if (ret == seastar::stop_iteration::yes) {
+       break;
+      }
+    } else if (key.get_device_id() > paddr.get_device_id()) {
+      break;
+    }
+    iter = co_await iter.next(c);
+  }
+  co_return;
+}
+#endif
+
 base_iertr::future<> _init_cached_extent(
   op_context_t c,
   const CachedExtentRef &e,
index b8b69af77d96d52a04c82a70aa2f75aa6121c4f0..93765ac7bba16d4e3c2fe9f85db3e5e58c8ae55b 100644 (file)
@@ -55,6 +55,13 @@ public:
     Transaction &t,
     scan_mapped_space_func_t &&f) final;
 
+#ifdef CRIMSON_TEST_WORKLOAD
+  scan_device_ret scan_device(
+    Transaction &t,
+    paddr_t paddr,
+    scan_device_func_t &f) final;
+#endif
+
   init_cached_extent_ret init_cached_extent(
     Transaction &t,
     CachedExtentRef e) final;
index 6b6f1676189629ee8207b8ebaee15d0dda764f55..932d86a07e73dac077176b4557670a069f8ac650 100644 (file)
@@ -139,6 +139,17 @@ public:
     Transaction &t,
     scan_mapped_space_func_t &&f) = 0;
 
+#ifdef CRIMSON_TEST_WORKLOAD
+  using scan_device_ret = base_iertr::future<>;
+  using scan_device_func_t = std::function<
+    base_iertr::future<seastar::stop_iteration>(
+      paddr_t, extent_len_t, extent_types_t, laddr_t)>;
+  virtual scan_device_ret scan_device(
+    Transaction &t,
+    paddr_t start,
+    scan_device_func_t &f) = 0;
+#endif
+
   virtual ~BackrefManager() {}
 };
 
index c42111ced13056cec18da2a1dec5fe561aff1de3..93c83f3eec79770fa417e38053e4160758a76eec 100644 (file)
@@ -33,6 +33,9 @@ Cache::Cache(
   ExtentPlacementManager &epm,
   store_index_t store_index)
   : epm(epm),
+#ifdef CRIMSON_TEST_WORKLOAD
+    force_backref(crimson::common::get_conf<bool>("crimson_test_workload")),
+#endif
     pinboard(create_extent_pinboard(
       crimson::common::get_conf<Option::size_t>(
        "seastore_cachepin_size_pershard"),
index 1b41f50f886411cd948cbba601ce35d02d826188..cfb4ccaa0e023bee5fb6eb4e584c7ea06343cdeb 100644 (file)
@@ -747,7 +747,11 @@ public:
   }
 
   bool can_drop_backref() const {
+#ifdef CRIMSON_TEST_WORKLOAD
+    return epm.is_pure_rbm() && !force_backref;
+#else
     return epm.is_pure_rbm();
+#endif
   }
 
   void update_read_ratio(Transaction &t) {
@@ -1023,6 +1027,23 @@ private:
     return res;
   }
 
+  std::optional<backref_entry_t> get_cached_backref_entry(paddr_t addr) {
+    auto it = backref_entry_mset.lower_bound(
+      addr,
+      backref_entry_t::cmp_t());
+    if (it == backref_entry_mset.end()) {
+      return std::nullopt;
+    }
+    while (it->paddr == addr) {
+      auto &backref_entry = *it;
+      ++it;
+      if (it->paddr != addr || it == backref_entry_mset.end()) {
+        return backref_entry;
+      }
+    }
+    return std::nullopt;
+  }
+
   const backref_entry_mset_t& get_backref_entry_mset() {
     return backref_entry_mset;
   }
@@ -1688,6 +1709,10 @@ private:
 
   transaction_id_t next_id = 0;
 
+#ifdef CRIMSON_TEST_WORKLOAD
+  const bool force_backref = false;
+#endif
+
   /**
    * dirty
    *
index 4fd253e27e54e6c2528d428b7e486233c3249b63..7ee7c8980f63b293ca05604685935d23fec5139a 100644 (file)
@@ -415,8 +415,12 @@ void ExtentCommitter::commit_state() {
   prior.last_committed_crc = extent.last_committed_crc;
   prior.dirty_from = extent.dirty_from;
   prior.length = extent.length;
-  prior.loaded_length = extent.loaded_length;
-  prior.buffer_space = std::move(extent.buffer_space);
+  // XXX: at present, zero loaded_length extents here
+  // must have been created by promoting/demoting them.
+  if (likely(extent.loaded_length != 0)) {
+    assert(prior.loaded_length == extent.loaded_length);
+    prior.buffer_space = std::move(extent.buffer_space);
+  }
   // XXX: We can go ahead and change the prior's version because
   // transactions don't hold a local view of the version field,
   // unlike FixedKVLeafNode::modifications
index d45bb0efcfc021943ade272ed1644515467da9b6..56d5dc6fcb070db8e5e3b7bdb11a2cbef88a3772 100644 (file)
@@ -285,7 +285,13 @@ public:
   }
 
   size_t get_promotion_size() const {
+#ifdef CRIMSON_TEST_WORKLOAD
+    return current_contents >= promotion_size
+      ? current_contents
+      : promotion_size;
+#else
     return current_contents;
+#endif
   }
 
   void set_background_callback(BackgroundListener *l) {
@@ -297,7 +303,13 @@ public:
   }
 
   bool should_run_promote() const {
-    return enabled() && current_contents >= promotion_size;
+    return enabled() &&
+       (current_contents >= promotion_size
+#ifdef CRIMSON_TEST_WORKLOAD
+        || (crimson::common::get_conf<bool>("crimson_test_workload")
+            && current_contents != 0)
+#endif
+        );
   }
 
   std::size_t get_promoted_size() const {
@@ -346,6 +358,19 @@ public:
     std::size_t promote_size = 0;
     std::list<CachedExtentRef> extents;
     DEBUGT("start promote", t);
+#ifdef CRIMSON_TEST_WORKLOAD
+    if (current_contents < promotion_size
+       && crimson::common::get_conf<bool>("crimson_test_workload")) {
+      auto id = epm.get_cold_device_id();
+      paddr_t start = P_ADDR_NULL;
+      if (device_id_to_paddr_type(id) == paddr_types_t::SEGMENT) {
+       start = paddr_t::make_seg_paddr(id, 0, 0);
+      } else {
+       start = paddr_t::make_blk_paddr(id, 0);
+      }
+      co_await ecb->promote_extents_from_disk(t, start);
+    } else {
+#endif
     for (auto &extent : list) {
       DEBUGT("promote {} to the hot tier", t, extent);
       ceph_assert(extent.is_stable_clean());
@@ -361,6 +386,9 @@ public:
       co_await trans_intr::make_interruptible(extent->wait_io());
       co_await ecb->promote_extent(t, extent);
     }
+#ifdef CRIMSON_TEST_WORKLOAD
+    }
+#endif
     // existing extents in lru will be retired after transaction submitted
     co_await ecb->submit_transaction_direct(t);
     promoted_count += extents.size();
@@ -871,6 +899,15 @@ private:
         // to the warm out queue.
         continue;
       }
+#ifdef CRIMSON_TEST_WORKLOAD
+      if (promoter.should_promote_extent(*extent)
+         && crimson::common::get_conf<bool>("crimson_test_workload")
+         && (double(std::rand() % 100) / 100.0) <= crimson::common::get_conf<double>(
+           "seastore_test_workload_2Q_promote_probability")) {
+       promoter.add_extent(*extent);
+       continue;
+      }
+#endif
       auto lext = extent->cast<LogicalCachedExtent>();
       auto laddr = lext->get_laddr();
       auto end = extent->get_last_touch_end();
index 9a9aeb8a832e1bcee93b6b7af2c99a70fb32c553..9f50d5396f041e4158d6019323a3cad4eb4ff7f5 100644 (file)
@@ -863,9 +863,20 @@ ExtentPlacementManager::BackgroundProcess::run()
 {
   assert(is_running());
   while (is_running()) {
-    if (background_should_run()) {
+    if (background_should_run()
+#ifdef CRIMSON_TEST_WORKLOAD
+        || force_run_background()
+#endif
+      ) {
       log_state("run(background)");
       co_await do_background_cycle();
+#ifdef CRIMSON_TEST_WORKLOAD
+      if (test_workload && force_process_state != ForceProcessState::STOP) {
+        last_process_state = force_process_state;
+        force_process_state = ForceProcessState::STOP;
+        set_next_arm_timepoint();
+      }
+#endif
     } else {
       log_state("run(block)");
       assert(!blocking_background);
@@ -1004,12 +1015,26 @@ ExtentPlacementManager::BackgroundProcess::do_background_cycle()
     }
   }
 
+  bool force_trim = false;
+  bool should_abort_cleaner_usage = true;
+#ifdef CRIMSON_TEST_WORKLOAD
+  if (test_workload && force_process_state == ForceProcessState::TRIM) {
+    if (!proceed_trim) {
+      should_abort_cleaner_usage = false;
+    }
+    proceed_trim = true;
+    force_trim = true;
+  }
+#endif
+
   if (proceed_trim) {
     DEBUG("started trimming...");
-    return trimmer->trim(
-    ).finally([this, trim_usage, FNAME] {
+    return trimmer->trim(force_trim
+    ).finally([this, trim_usage, should_abort_cleaner_usage, FNAME] {
       DEBUG("finished trimming");
-      abort_cleaner_usage(trim_usage, {true, true});
+      if (should_abort_cleaner_usage) {
+        abort_cleaner_usage(trim_usage, {true, true});
+      }
     });
   } else {
     assert(!proceed_trim);
@@ -1047,11 +1072,27 @@ ExtentPlacementManager::BackgroundProcess::do_background_cycle()
       proceed_demote = true;
     }
 
+    bool abort_cold_cleaner_usage = true;
+#ifdef CRIMSON_TEST_WORKLOAD
+    if (test_workload && force_process_state == ForceProcessState::CLEAN) {
+      if (!proceed_clean_main) {
+        abort_cold_cleaner_usage = false;
+      }
+      proceed_clean_main = main_cleaner->can_clean_space();
+      if (has_cold_tier()) {
+        proceed_clean_cold = cold_cleaner->can_clean_space();
+      }
+      if (logical_bucket) {
+        proceed_demote = logical_bucket->could_demote();
+      }
+    }
+#endif
+
     if (!proceed_clean_main && !proceed_clean_cold && !proceed_demote) {
       ceph_abort_msg("no background process will start");
     }
     return seastar::when_all(
-      [this, FNAME, proceed_clean_main,
+      [this, FNAME, proceed_clean_main, abort_cold_cleaner_usage,
        should_clean_main_for_trim, main_cold_usage] {
         if (!proceed_clean_main) {
           return seastar::now();
@@ -1066,9 +1107,11 @@ ExtentPlacementManager::BackgroundProcess::do_background_cycle()
           crimson::ct_error::assert_all{
             "do_background_cycle encountered invalid error in main clean_space"
           }
-        ).finally([this, main_cold_usage, FNAME] {
+        ).finally([this, main_cold_usage, abort_cold_cleaner_usage, FNAME] {
           DEBUG("finished clean main");
-          abort_cold_usage(main_cold_usage, true);
+          if (abort_cold_cleaner_usage) {
+            abort_cold_usage(main_cold_usage, true);
+          }
         });
       },
       [this, FNAME, proceed_clean_cold,
index 1672794e5c25bea6293b42c2c2f1f920645ac17d..e93c7d4d5cce95c430d74de5373a7a90a98a8332 100644 (file)
@@ -538,8 +538,16 @@ public:
   }
 
   write_policy_t get_write_policy(extent_types_t type, extent_len_t length) const {
-    if (has_cold_tier() && length >= write_through_size && is_data_type(type)) {
-      return write_policy_t::WRITE_THROUGH;
+    if (has_cold_tier() &&  is_data_type(type)) {
+      if (length >= write_through_size
+#ifdef CRIMSON_TEST_WORKLOAD
+          || (crimson::common::get_conf<bool>("crimson_test_workload")
+              && (double(std::rand() % 100) / 100.0) <= crimson::common::get_conf<double>(
+                "seastore_test_workload_write_through_probability"))
+#endif
+          ) {
+        return write_policy_t::WRITE_THROUGH;
+      }
     }
     return write_policy_t::WRITE_BACK;
   }
@@ -707,6 +715,12 @@ public:
     return hot_tier_generations - 1;
   }
 
+#ifdef CRIMSON_TEST_WORKLOAD
+  device_id_t get_cold_device_id() const {
+    return background_process.get_cold_device_id();
+  }
+#endif
+
 private:
   rewrite_gen_t adjust_generation(
       data_category_t category,
@@ -880,6 +894,17 @@ private:
           get_conf<Option::size_t>("seastore_logical_bucket_capacity"),
           get_conf<Option::size_t>("seastore_logical_bucket_proceed_size_per_cycle"));
       }
+#ifdef CRIMSON_TEST_WORKLOAD
+      LOG_PREFIX(BackgroundProcess::init);
+      test_workload = crimson::common::get_conf<bool>("crimson_test_workload");
+      force_process_half_life = crimson::common::get_conf<uint64_t>(
+        "seastore_test_workload_force_prcess_background_tasks_period");
+      force_background_timer.set_callback([this] { wake_half_life(); });
+      SUBINFO(seastore_epm, "crimson test workload supported, enabled: {}", test_workload);
+      if (test_workload) {
+        set_next_arm_timepoint();
+      }
+#endif
     }
 
     LogicalBucket *get_logical_bucket() {
@@ -996,6 +1021,14 @@ private:
       }
     }
 
+
+#ifdef CRIMSON_TEST_WORKLOAD
+    device_id_t get_cold_device_id() const {
+      assert(has_cold_tier());
+      return *cold_cleaner->get_device_ids().begin();
+    }
+#endif
+
     seastar::future<> reserve_projected_usage(io_usage_t usage);
 
     void release_projected_usage(const io_usage_t &usage) {
@@ -1098,7 +1131,15 @@ private:
     // to make sure the condition is consistent.
     bool background_should_run() {
       assert(is_ready());
+#ifdef CRIMSON_TEST_WORKLOAD
+      if (test_workload) {
+        force_fast_evict();
+      } else {
+        maybe_update_eviction_mode();
+      }
+#else
       maybe_update_eviction_mode();
+#endif
       return main_cleaner_should_run()
         || cold_cleaner_should_run()
         || trimmer->should_trim();
@@ -1138,6 +1179,14 @@ private:
       }
     }
 
+#ifdef CRIMSON_TEST_WORKLOAD
+    void force_fast_evict() {
+      if (has_cold_tier()) {
+        eviction_state.force_fast_evict();
+      }
+    }
+#endif
+
     struct eviction_state_t {
       enum class eviction_mode_t {
         STOP,     // generation greater than or equal to MIN_COLD_GENERATION
@@ -1249,6 +1298,12 @@ private:
           eviction_mode = eviction_mode_t::FAST;
         }
       }
+
+#ifdef CRIMSON_TEST_WORKLOAD
+      void force_fast_evict() {
+        eviction_mode = eviction_mode_t::FAST;
+      }
+#endif
     };
 
     seastar::future<> do_background_cycle();
@@ -1289,6 +1344,39 @@ private:
     state_t state = state_t::STOP;
     eviction_state_t eviction_state;
 
+#ifdef CRIMSON_TEST_WORKLOAD
+    enum class ForceProcessState {
+      STOP,
+      TRIM,
+      CLEAN,
+    };
+    bool test_workload = false;
+    ForceProcessState force_process_state = ForceProcessState::STOP;
+    ForceProcessState last_process_state = ForceProcessState::STOP;
+    seastar::timer<seastar::steady_clock_type> force_background_timer;
+    int force_process_half_life;
+
+    void set_next_arm_timepoint() {
+      assert(test_workload);
+      force_background_timer.arm(std::chrono::seconds(force_process_half_life));
+    }
+
+    void wake_half_life() {
+      assert(test_workload);
+      if (last_process_state == ForceProcessState::TRIM) {
+        force_process_state = ForceProcessState::CLEAN;
+      } else {
+        force_process_state = ForceProcessState::TRIM;
+      }
+
+      do_wake_background();
+    }
+
+    bool force_run_background() const {
+      return test_workload && force_process_state != ForceProcessState::STOP
+        && (logical_bucket && logical_bucket->could_demote());
+    }
+#endif
     friend class ::transaction_manager_test_t;
   };
 
index 6666005dda5645bb1badfcf9c27e24b8b779c43d..b362d3e9098eb1c55dafc59f98183ce763dda7dd 100644 (file)
@@ -615,6 +615,24 @@ Device::access_ertr::future<> SeaStore::_mkfs(uuid_d new_osd_fsid)
     co_await rdir.close();
   }
 
+#ifdef CRIMSON_TEST_WORKLOAD
+  if (sds.empty() && crimson::common::get_conf<bool>("crimson_test_workload")) {
+    // lbc test workload enabled while no secondary devices indicated, create one
+    std::string path = fmt::format("{}/block.1", root);
+    co_await seastar::make_directory(path);
+    DeviceRef sec_dev = co_await Device::make_device(path, dtype, btype);
+    auto p_sec_dev = sec_dev.get();
+    secondaries.emplace_back(std::move(sec_dev));
+    co_await p_sec_dev->start(store_shard_nums);
+    magic_t magic = (magic_t)std::rand();
+    device_id_t id = 0x1;
+    sds.emplace(id, device_spec_t{magic, dtype, btype, id});
+    co_await p_sec_dev->mkfs(
+      device_config_t::create_secondary(new_osd_fsid, id, dtype, btype, magic)
+    ).handle_error(crimson::ct_error::assert_all{"not possible"});
+    co_await set_secondaries();
+  }
+#endif
   device_id_t id = 0;
   device_type_t d_type = device->get_device_type();
   backend_type_t b_type = device->get_backend_type();
index 73f52fb1189c206d407aebd9ff2c523f1ec975fc..c282a98b901f68da8dd7cf9663c0f293c463a459 100644 (file)
@@ -1213,6 +1213,49 @@ TransactionManager::promote_extent(
     t, mapping, std::move(promoted_extents));
 }
 
+#ifdef CRIMSON_TEST_WORKLOAD
+TransactionManager::promote_extent_ret
+TransactionManager::promote_extents_from_disk(
+  Transaction &t,
+  paddr_t paddr)
+{
+  using scan_device_func_t = BackrefManager::scan_device_func_t;
+  std::size_t size = 0;
+  scan_device_func_t func = [this, &t, &size](
+    paddr_t paddr, extent_len_t length, extent_types_t type, laddr_t laddr)
+      -> base_iertr::future<seastar::stop_iteration> {
+    if (type != extent_types_t::OBJECT_DATA_BLOCK) {
+      co_return seastar::stop_iteration::no;
+    }
+    auto cursor = co_await lba_manager->get_cursor(t, laddr
+      ).handle_error_interruptible(
+        crimson::ct_error::enoent::assert_failure(),
+        crimson::ct_error::pass_further_all{}
+      );
+    assert(cursor->is_direct());
+    if (cursor->has_shadow_paddr()) {
+      // the extent is already promoted to the hot tier
+      co_return seastar::stop_iteration::no;
+    }
+    auto extent = co_await read_cursor_by_type(t, std::move(cursor), type);
+    if (extent->is_stable_dirty()) {
+      // dirty extents shouldn't be promoted as is in
+      // the real world
+      co_return seastar::stop_iteration::no;
+    }
+    co_await promote_extent(t, extent.get());
+    size += length;
+    if (size >= crimson::common::get_conf<
+        Option::size_t>("seastore_cache_promotion_size")) {
+      co_return seastar::stop_iteration::yes;
+    } else {
+      co_return seastar::stop_iteration::no;
+    }
+  };
+  co_await backref_manager->scan_device(t, paddr, func);
+}
+#endif
+
 TransactionManager::rewrite_extents_ret TransactionManager::rewrite_extents(
   Transaction &t,
   std::vector<CachedExtentRef> &extents,
@@ -1530,7 +1573,11 @@ TransactionManagerRef make_transaction_manager(
       store_index,
       *backref_manager, trimmer_config,
       backend_type, roll_start, roll_size,
-      !pure_rbm_backend);
+      !pure_rbm_backend
+#ifdef CRIMSON_TEST_WORKLOAD
+        || crimson::common::get_conf<bool>("crimson_test_workload")
+#endif
+    );
 
   AsyncCleanerRef cleaner;
   JournalRef journal;
index 4327c572f1a814340c4097a4c53b2a515d79a3b4..da1a3641fdbd8ae5754f3eeb817b6ffea810609b 100644 (file)
@@ -958,7 +958,13 @@ public:
   using ExtentCallbackInterface::promote_extent_ret;
   promote_extent_ret promote_extent(
     Transaction &t,
-    CachedExtentRef extent);
+    CachedExtentRef extent) final;
+
+#ifdef CRIMSON_TEST_WORKLOAD
+  promote_extent_ret promote_extents_from_disk(
+    Transaction &t,
+    paddr_t paddr) final;
+#endif
 
   using ExtentCallbackInterface::demote_region_res_t;
   using ExtentCallbackInterface::demote_region_ret;
index 85d4ff2bee3cc46631ff1d0b43b82e51a1f44c8a..74b8fdd12797b91200c72feafb9b2913d7b282d7 100644 (file)
@@ -913,7 +913,7 @@ struct transaction_manager_test_t :
       if (run_clean) {
         return epm->run_background_work_until_halt();
       } else {
-        return epm->background_process.trimmer->trim();
+        return epm->background_process.trimmer->trim(false);
       }
     }).handle_error(
       crimson::ct_error::assert_all{