]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/os/seastore: introduce JournalTrimmer 47489/head
authorYingxin Cheng <yingxin.cheng@intel.com>
Mon, 8 Aug 2022 01:49:35 +0000 (09:49 +0800)
committerYingxin Cheng <yingxin.cheng@intel.com>
Thu, 11 Aug 2022 01:16:58 +0000 (09:16 +0800)
Signed-off-by: Myoungwon Oh <myoungwon.oh@samsung.com>
Signed-off-by: Yingxin Cheng <yingxin.cheng@intel.com>
14 files changed:
src/crimson/os/seastore/async_cleaner.h
src/crimson/os/seastore/extent_placement_manager.cc
src/crimson/os/seastore/journal.cc
src/crimson/os/seastore/journal.h
src/crimson/os/seastore/journal/circular_bounded_journal.cc
src/crimson/os/seastore/journal/circular_bounded_journal.h
src/crimson/os/seastore/journal/segment_allocator.cc
src/crimson/os/seastore/journal/segment_allocator.h
src/crimson/os/seastore/journal/segmented_journal.cc
src/crimson/os/seastore/journal/segmented_journal.h
src/crimson/os/seastore/transaction_manager.cc
src/test/crimson/seastore/test_btree_lba_manager.cc
src/test/crimson/seastore/test_cbjournal.cc
src/test/crimson/seastore/test_seastore_journal.cc

index 963efe3a805501956d2d267b400bd9f5b37cd8a4..528e569c1b258a04fded394f2c04c539e2ce48f7 100644 (file)
@@ -267,9 +267,9 @@ private:
 std::ostream &operator<<(std::ostream &, const segments_info_t &);
 
 /**
- * Callback interface for managing available segments
+ * Callback interface for journal trimming
  */
-class SegmentProvider {
+class JournalTrimmer {
 public:
   // get the committed journal head
   virtual journal_seq_t get_journal_head() const = 0;
@@ -292,6 +292,14 @@ public:
   virtual void update_journal_tails(
       journal_seq_t dirty_tail, journal_seq_t alloc_tail) = 0;
 
+  virtual ~JournalTrimmer() {}
+};
+
+/**
+ * Callback interface for managing available segments
+ */
+class SegmentProvider {
+public:
   virtual const segment_info_t& get_seg_info(segment_id_t id) const = 0;
 
   virtual segment_id_t allocate_segment(
@@ -519,7 +527,7 @@ public:
 };
 
 
-class AsyncCleaner : public SegmentProvider {
+class AsyncCleaner : public SegmentProvider, public JournalTrimmer {
 public:
   /// Config
   struct config_t {
index 78c707bb713e323796438f81535bc0109e6e0fb1..9518fdc7897460e94fc002cb15056d7736221376 100644 (file)
@@ -14,7 +14,7 @@ SegmentedOolWriter::SegmentedOolWriter(
   reclaim_gen_t gen,
   SegmentProvider& sp,
   SegmentSeqAllocator &ssa)
-  : segment_allocator(segment_type_t::OOL, category, gen, sp, ssa),
+  : segment_allocator(nullptr, category, gen, sp, ssa),
     record_submitter(crimson::common::get_conf<uint64_t>(
                        "seastore_journal_iodepth_limit"),
                      crimson::common::get_conf<uint64_t>(
index 1f219724d7685a31ce7bfad3f16eea477f7d40d7..d4714cf3f961919bc3ce55cbe3d21d02c8946207 100644 (file)
@@ -7,16 +7,19 @@
 
 namespace crimson::os::seastore::journal {
 
-JournalRef make_segmented(SegmentProvider &provider)
+JournalRef make_segmented(
+  SegmentProvider &provider,
+  JournalTrimmer &trimmer)
 {
-  return std::make_unique<SegmentedJournal>(provider);
+  return std::make_unique<SegmentedJournal>(provider, trimmer);
 }
 
 JournalRef make_circularbounded(
+  JournalTrimmer &trimmer,
   crimson::os::seastore::random_block_device::RBMDevice* device,
   std::string path)
 {
-  return std::make_unique<CircularBoundedJournal>(device, path);
+  return std::make_unique<CircularBoundedJournal>(trimmer, device, path);
 }
 
 }
index c2e537008f273475bdcd6fe0e44b5f11d2b7c143..71eac4c00338754c6fb6957314427d47709426a7 100644 (file)
@@ -17,6 +17,7 @@ class RBMDevice;
 
 class SegmentManagerGroup;
 class SegmentProvider;
+class JournalTrimmer;
 
 enum class journal_type_t {
   SEGMENT_JOURNAL = 0,
@@ -25,6 +26,7 @@ enum class journal_type_t {
 
 class Journal {
 public:
+  virtual JournalTrimmer &get_trimmer() = 0;
   /**
    * initializes journal for mkfs writes -- must run prior to calls
    * to submit_record.
@@ -108,9 +110,12 @@ using JournalRef = std::unique_ptr<Journal>;
 
 namespace journal {
 
-JournalRef make_segmented(SegmentProvider &provider);
+JournalRef make_segmented(
+  SegmentProvider &provider,
+  JournalTrimmer &trimmer);
 
 JournalRef make_circularbounded(
+  JournalTrimmer &trimmer,
   crimson::os::seastore::random_block_device::RBMDevice* device,
   std::string path);
 
index d7ff795f0076ae8e0f57f4ea563214cf8274d15f..2bc4672319bd1490488a42a7425b50c4c8745e10 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "crimson/common/errorator-loop.h"
 #include "include/intarith.h"
+#include "crimson/os/seastore/async_cleaner.h"
 #include "crimson/os/seastore/journal/circular_bounded_journal.h"
 #include "crimson/os/seastore/logging.h"
 
@@ -24,9 +25,11 @@ std::ostream &operator<<(std::ostream &out,
              << ")";
 }
 
-CircularBoundedJournal::CircularBoundedJournal(RBMDevice* device,
+CircularBoundedJournal::CircularBoundedJournal(
+    JournalTrimmer &trimmer,
+    RBMDevice* device,
     const std::string &path)
-  : device(device), path(path) {}
+  : trimmer(trimmer), device(device), path(path) {}
 
 CircularBoundedJournal::mkfs_ret
 CircularBoundedJournal::mkfs(const mkfs_config_t& config)
@@ -236,6 +239,7 @@ CircularBoundedJournal::submit_record_ret CircularBoundedJournal::submit_record(
       paddr,
       write_result
     };
+    trimmer.set_journal_head(write_result.start_seq);
     return submit_result;
   });
 }
index 4a310806a95f9baab06fd71f65f18eeec9fbc301..c41d75405f0c7dd99ed1cda2eb3fd3331c668f7a 100644 (file)
@@ -20,7 +20,6 @@
 #include "crimson/os/seastore/random_block_manager/rbm_device.h"
 #include <list>
 
-
 namespace crimson::os::seastore::journal {
 
 constexpr rbm_abs_addr CBJOURNAL_START_ADDRESS = 0;
@@ -77,9 +76,14 @@ public:
     }
   };
 
-  CircularBoundedJournal(RBMDevice* device, const std::string &path);
+  CircularBoundedJournal(
+      JournalTrimmer &trimmer, RBMDevice* device, const std::string &path);
   ~CircularBoundedJournal() {}
 
+  JournalTrimmer &get_trimmer() final {
+    return trimmer;
+  }
+
   open_for_mkfs_ret open_for_mkfs() final;
 
   open_for_mount_ret open_for_mount() final;
@@ -280,6 +284,7 @@ public:
 
 private:
   cbj_header_t header;
+  JournalTrimmer &trimmer;
   RBMDevice* device;
   std::string path;
   WritePipeline *write_pipeline = nullptr;
index b8b193ae39e6d80a5d8e98e3c4348c6a9d992c18..f97dd6a181ac994dd2198032aa12808124d2e0ad 100644 (file)
@@ -13,20 +13,22 @@ SET_SUBSYS(seastore_journal);
 namespace crimson::os::seastore::journal {
 
 SegmentAllocator::SegmentAllocator(
-  segment_type_t type,
+  JournalTrimmer *trimmer,
   data_category_t category,
   reclaim_gen_t gen,
   SegmentProvider &sp,
   SegmentSeqAllocator &ssa)
   : print_name{fmt::format("{}_G{}", category, gen)},
-    type{type},
+    type{trimmer == nullptr ?
+         segment_type_t::OOL :
+         segment_type_t::JOURNAL},
     category{category},
     gen{gen},
     segment_provider{sp},
     sm_group{*sp.get_segment_manager_group()},
-    segment_seq_allocator(ssa)
+    segment_seq_allocator(ssa),
+    trimmer{trimmer}
 {
-  ceph_assert(type != segment_type_t::NULL_SEG);
   reset();
 }
 
@@ -57,8 +59,8 @@ SegmentAllocator::do_open(bool is_mkfs)
     journal_seq_t dirty_tail;
     journal_seq_t alloc_tail;
     if (type == segment_type_t::JOURNAL) {
-      dirty_tail = segment_provider.get_dirty_tail();
-      alloc_tail = segment_provider.get_alloc_tail();
+      dirty_tail = trimmer->get_dirty_tail();
+      alloc_tail = trimmer->get_alloc_tail();
       if (is_mkfs) {
         ceph_assert(dirty_tail == JOURNAL_SEQ_NULL);
         ceph_assert(alloc_tail == JOURNAL_SEQ_NULL);
index a664b42e78f5669e04778c61df832c6d49caa3d0..3355f18418f8e417c234324b46275b2ae6e59d45 100644 (file)
@@ -16,6 +16,7 @@
 
 namespace crimson::os::seastore {
   class SegmentProvider;
+  class JournalTrimmer;
 }
 
 namespace crimson::os::seastore::journal {
@@ -30,7 +31,7 @@ class SegmentAllocator {
       crimson::ct_error::input_output_error>;
 
  public:
-  SegmentAllocator(segment_type_t type,
+  SegmentAllocator(JournalTrimmer *trimmer,
                    data_category_t category,
                    reclaim_gen_t gen,
                    SegmentProvider &sp,
@@ -128,7 +129,7 @@ class SegmentAllocator {
   seastore_off_t written_to;
   SegmentSeqAllocator &segment_seq_allocator;
   segment_nonce_t current_segment_nonce;
-  //3. journal tail written to both segment_header_t and segment_tail_t
+  JournalTrimmer *trimmer;
 };
 
 /**
index 19008138df4ba72bbf4875b0d1b507cd70eedf10..12fc3b86d9463ca0bab6bd6c77e9b0bb9d8cad52 100644 (file)
@@ -27,11 +27,11 @@ SET_SUBSYS(seastore_journal);
 namespace crimson::os::seastore::journal {
 
 SegmentedJournal::SegmentedJournal(
-  SegmentProvider &segment_provider)
-  : segment_provider(segment_provider),
-    segment_seq_allocator(
+  SegmentProvider &segment_provider,
+  JournalTrimmer &trimmer)
+  : segment_seq_allocator(
       new SegmentSeqAllocator(segment_type_t::JOURNAL)),
-    journal_segment_allocator(segment_type_t::JOURNAL,
+    journal_segment_allocator(&trimmer,
                               data_category_t::METADATA,
                               0, // generation
                               segment_provider,
@@ -45,7 +45,8 @@ SegmentedJournal::SegmentedJournal(
                      crimson::common::get_conf<double>(
                        "seastore_journal_batch_preferred_fullness"),
                      journal_segment_allocator),
-    sm_group(*segment_provider.get_segment_manager_group())
+    sm_group(*segment_provider.get_segment_manager_group()),
+    trimmer{trimmer}
 {
 }
 
@@ -105,9 +106,9 @@ SegmentedJournal::prep_replay_segments(
   return scan_last_segment(last_segment_id, last_header
   ).safe_then([this, FNAME, segments=std::move(segments)] {
     INFO("dirty_tail={}, alloc_tail={}",
-         segment_provider.get_dirty_tail(),
-         segment_provider.get_alloc_tail());
-    auto journal_tail = segment_provider.get_journal_tail();
+         trimmer.get_dirty_tail(),
+         trimmer.get_alloc_tail());
+    auto journal_tail = trimmer.get_journal_tail();
     auto journal_tail_paddr = journal_tail.offset;
     ceph_assert(journal_tail != JOURNAL_SEQ_NULL);
     ceph_assert(journal_tail_paddr != P_ADDR_NULL);
@@ -152,7 +153,7 @@ SegmentedJournal::scan_last_segment(
 {
   LOG_PREFIX(SegmentedJournal::scan_last_segment);
   assert(segment_id == segment_header.physical_segment_id);
-  segment_provider.update_journal_tails(
+  trimmer.update_journal_tails(
       segment_header.dirty_tail, segment_header.alloc_tail);
   auto seq = journal_seq_t{
     segment_header.segment_seq,
@@ -203,7 +204,7 @@ SegmentedJournal::scan_last_segment(
               DEBUG("got {}, at {}", tail_delta, start_seq);
               ceph_assert(tail_delta.dirty_tail != JOURNAL_SEQ_NULL);
               ceph_assert(tail_delta.alloc_tail != JOURNAL_SEQ_NULL);
-              segment_provider.update_journal_tails(
+              trimmer.update_journal_tails(
                   tail_delta.dirty_tail, tail_delta.alloc_tail);
             }
           }
@@ -287,8 +288,8 @@ SegmentedJournal::replay_segment(
            return handler(
              locator,
              delta,
-             segment_provider.get_dirty_tail(),
-             segment_provider.get_alloc_tail(),
+             trimmer.get_dirty_tail(),
+             trimmer.get_alloc_tail(),
               modify_time
             ).safe_then([&stats, delta_type=delta.type](bool is_applied) {
               if (is_applied) {
index cc5e489393dfcedb0ac0d9fb506b2d5e98cb30d0..ba4b0cd5fb9df053e3398a7f730498d965e5738f 100644 (file)
@@ -24,9 +24,15 @@ namespace crimson::os::seastore::journal {
  */
 class SegmentedJournal : public Journal {
 public:
-  SegmentedJournal(SegmentProvider &segment_provider);
+  SegmentedJournal(
+      SegmentProvider &segment_provider,
+      JournalTrimmer &trimmer);
   ~SegmentedJournal() {}
 
+  JournalTrimmer &get_trimmer() final {
+    return trimmer;
+  }
+
   open_for_mkfs_ret open_for_mkfs() final;
 
   open_for_mount_ret open_for_mount() final;
@@ -55,11 +61,11 @@ private:
     OrderingHandle &handle
   );
 
-  SegmentProvider& segment_provider;
   SegmentSeqAllocatorRef segment_seq_allocator;
   SegmentAllocator journal_segment_allocator;
   RecordSubmitter record_submitter;
   SegmentManagerGroup &sm_group;
+  JournalTrimmer &trimmer;
   WritePipeline* write_pipeline = nullptr;
 
   /// return ordered vector of segments to replay
index 52623def9ed368907d4009d8191e0f12a804c921..5172838673c84218240221954466f439706dfbc2 100644 (file)
@@ -49,8 +49,8 @@ TransactionManager::mkfs_ertr::future<> TransactionManager::mkfs()
   ).safe_then([this] {
     return journal->open_for_mkfs();
   }).safe_then([this](auto start_seq) {
-    async_cleaner->update_journal_tails(start_seq, start_seq);
-    async_cleaner->set_journal_head(start_seq);
+    journal->get_trimmer().update_journal_tails(start_seq, start_seq);
+    journal->get_trimmer().set_journal_head(start_seq);
     return epm->open();
   }).safe_then([this, FNAME]() {
     return with_transaction_intr(
@@ -109,7 +109,7 @@ TransactionManager::mount_ertr::future<> TransactionManager::mount()
   }).safe_then([this] {
     return journal->open_for_mount();
   }).safe_then([this](auto start_seq) {
-    async_cleaner->set_journal_head(start_seq);
+    journal->get_trimmer().set_journal_head(start_seq);
     return with_transaction_weak(
       "mount",
       [this](auto &t)
@@ -337,8 +337,8 @@ TransactionManager::submit_transaction_direct(
 
     auto record = cache->prepare_record(
       tref,
-      async_cleaner->get_journal_head(),
-      async_cleaner->get_dirty_tail());
+      journal->get_trimmer().get_journal_head(),
+      journal->get_trimmer().get_dirty_tail());
 
     tref.get_handle().maybe_release_collection_lock();
 
@@ -347,7 +347,7 @@ TransactionManager::submit_transaction_direct(
     ).safe_then([this, FNAME, &tref](auto submit_result) mutable {
       SUBDEBUGT(seastore_t, "committed with {}", tref, submit_result);
       auto start_seq = submit_result.write_result.start_seq;
-      async_cleaner->set_journal_head(start_seq);
+      journal->get_trimmer().set_journal_head(start_seq);
       cache->complete_commit(
           tref,
           submit_result.record_block_base,
@@ -389,7 +389,7 @@ TransactionManager::submit_transaction_direct(
       lba_manager->complete_transaction(tref, lba_to_clear, lba_to_link);
       backref_manager->complete_transaction(tref, backref_to_clear, backref_to_link);
 
-      async_cleaner->update_journal_tails(
+      journal->get_trimmer().update_journal_tails(
        cache->get_oldest_dirty_from().value_or(start_seq),
        cache->get_oldest_backref_dirty_from().value_or(start_seq));
       return tref.get_handle().complete();
@@ -664,10 +664,11 @@ TransactionManagerRef make_transaction_manager(
   auto p_device_type = primary_device->get_device_type();
   JournalRef journal;
   if (p_device_type == device_type_t::SEGMENTED) {
-    journal = journal::make_segmented(*async_cleaner);
+    journal = journal::make_segmented(*async_cleaner, *async_cleaner);
   } else {
     ceph_assert(p_device_type == device_type_t::RANDOM_BLOCK);
     journal = journal::make_circularbounded(
+      *async_cleaner,
       static_cast<random_block_device::RBMDevice*>(primary_device),
       "");
     async_cleaner->set_disable_trim(true);
index 92719d83aa272b9f6bb92b711e2503752305cfba..adc3ce504c638b6e591e44591123c6b85a1dba34 100644 (file)
@@ -25,7 +25,7 @@ using namespace crimson::os::seastore::lba_manager;
 using namespace crimson::os::seastore::lba_manager::btree;
 
 struct btree_test_base :
-  public seastar_test_suite_t, SegmentProvider {
+  public seastar_test_suite_t, SegmentProvider, JournalTrimmer {
 
   segment_manager::EphemeralSegmentManagerRef segment_manager;
   SegmentManagerGroupRef sms;
@@ -49,7 +49,7 @@ struct btree_test_base :
   btree_test_base() = default;
 
   /*
-   * SegmentProvider interfaces
+   * JournalTrimmer interfaces
    */
   journal_seq_t get_journal_head() const final { return dummy_tail; }
 
@@ -61,6 +61,9 @@ struct btree_test_base :
 
   void update_journal_tails(journal_seq_t, journal_seq_t) final {}
 
+  /*
+   * SegmentProvider interfaces
+   */
   const segment_info_t& get_seg_info(segment_id_t id) const final {
     tmp_info = {};
     tmp_info.seq = segment_seqs.at(id);
@@ -114,7 +117,7 @@ struct btree_test_base :
         segment_manager::get_ephemeral_device_config(0, 1));
     }).safe_then([this] {
       sms.reset(new SegmentManagerGroup());
-      journal = journal::make_segmented(*this);
+      journal = journal::make_segmented(*this, *this);
       epm.reset(new ExtentPlacementManager());
       cache.reset(new Cache(*epm));
 
index d7ed72eae32732edade3f97521930148eaa92729..309118fa37d7c5fa23c69b4fa329d6ca2924da4d 100644 (file)
@@ -6,11 +6,12 @@
 #include <random>
 
 #include "crimson/common/log.h"
-#include "crimson/os/seastore/seastore_types.h"
+#include "crimson/os/seastore/async_cleaner.h"
 #include "crimson/os/seastore/journal.h"
 #include "crimson/os/seastore/journal/circular_bounded_journal.h"
 #include "crimson/os/seastore/random_block_manager.h"
 #include "crimson/os/seastore/random_block_manager/rbm_device.h"
+#include "crimson/os/seastore/seastore_types.h"
 #include "test/crimson/seastore/transaction_manager_test_state.h"
 
 using namespace crimson;
@@ -119,7 +120,7 @@ struct entry_validator_t {
   }
 };
 
-struct cbjournal_test_t : public seastar_test_suite_t
+struct cbjournal_test_t : public seastar_test_suite_t, JournalTrimmer
 {
   std::vector<entry_validator_t> entries;
   std::unique_ptr<CircularBoundedJournal> cbj;
@@ -132,7 +133,7 @@ struct cbjournal_test_t : public seastar_test_suite_t
 
   cbjournal_test_t() {
     device = new random_block_device::TestMemory(CBTEST_DEFAULT_TEST_SIZE + CBTEST_DEFAULT_BLOCK_SIZE);
-    cbj.reset(new CircularBoundedJournal(device, std::string()));
+    cbj.reset(new CircularBoundedJournal(*this, device, std::string()));
     device_id_t d_id = 1 << (std::numeric_limits<device_id_t>::digits - 1);
     config.block_size = CBTEST_DEFAULT_BLOCK_SIZE;
     config.total_size = CBTEST_DEFAULT_TEST_SIZE;
@@ -141,6 +142,27 @@ struct cbjournal_test_t : public seastar_test_suite_t
     cbj->set_write_pipeline(&pipeline);
   }
 
+  /*
+   * JournalTrimmer interfaces
+   */
+  journal_seq_t get_journal_head() const {
+    return JOURNAL_SEQ_NULL;
+  }
+
+  journal_seq_t get_dirty_tail() const final {
+    return JOURNAL_SEQ_NULL;
+  }
+
+  journal_seq_t get_alloc_tail() const final {
+    return JOURNAL_SEQ_NULL;
+  }
+
+  void set_journal_head(journal_seq_t head) final {}
+
+  void update_journal_tails(
+    journal_seq_t dirty_tail,
+    journal_seq_t alloc_tail) final {}
+
   seastar::future<> set_up_fut() final {
     return seastar::now();
   }
index 0b6f7870c8f66a0720fb99871d8c7d3daf1fef0e..ac190c78102b161fd92c64d5d86b4738496641bf 100644 (file)
@@ -63,7 +63,7 @@ struct record_validator_t {
   }
 };
 
-struct journal_test_t : seastar_test_suite_t, SegmentProvider {
+struct journal_test_t : seastar_test_suite_t, SegmentProvider, JournalTrimmer {
   segment_manager::EphemeralSegmentManagerRef segment_manager;
   WritePipeline pipeline;
   JournalRef journal;
@@ -88,7 +88,7 @@ struct journal_test_t : seastar_test_suite_t, SegmentProvider {
   journal_test_t() = default;
 
   /*
-   * SegmentProvider interfaces
+   * JournalTrimmer interfaces
    */
   journal_seq_t get_journal_head() const final { return dummy_tail; }
 
@@ -100,6 +100,9 @@ struct journal_test_t : seastar_test_suite_t, SegmentProvider {
 
   void update_journal_tails(journal_seq_t, journal_seq_t) final {}
 
+  /*
+   * SegmentProvider interfaces
+   */
   const segment_info_t& get_seg_info(segment_id_t id) const final {
     tmp_info = {};
     tmp_info.seq = segment_seqs.at(id);
@@ -140,7 +143,7 @@ struct journal_test_t : seastar_test_suite_t, SegmentProvider {
       block_size = segment_manager->get_block_size();
       sms.reset(new SegmentManagerGroup());
       next = segment_id_t(segment_manager->get_device_id(), 0);
-      journal = journal::make_segmented(*this);
+      journal = journal::make_segmented(*this, *this);
       journal->set_write_pipeline(&pipeline);
       sms->add_segment_manager(segment_manager.get());
       return journal->open_for_mkfs();
@@ -169,7 +172,7 @@ struct journal_test_t : seastar_test_suite_t, SegmentProvider {
   auto replay(T &&f) {
     return journal->close(
     ).safe_then([this, f=std::move(f)]() mutable {
-      journal = journal::make_segmented(*this);
+      journal = journal::make_segmented(*this, *this);
       journal->set_write_pipeline(&pipeline);
       return journal->replay(std::forward<T>(std::move(f)));
     }).safe_then([this] {