]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/os/seastore/segment_cleaner: add dedicated backref trimming process 46356/head
authorXuehan Xu <xxhdx1985126@gmail.com>
Fri, 20 May 2022 09:23:03 +0000 (17:23 +0800)
committerXuehan Xu <xxhdx1985126@gmail.com>
Thu, 26 May 2022 09:16:55 +0000 (17:16 +0800)
Space reclamation needs to merge backrefs up to the point where the latest
release of extents within the scope of the reclamation process happened.
When the journal size is large, that merge may generate a transaction
record with size exceeds the max record size threshold. So we need have a
backref trimming process that merge most of the backrefs before the space
reclamation happens.

This commit also fixes issue: https://tracker.ceph.com/issues/55692, by
repeating the inflight backrefs trimming transaction when it's
invalidated by other trans on the ROOT block

Fixes: https://tracker.ceph.com/issues/55692
Signed-off-by: Xuehan Xu <xxhdx1985126@gmail.com>
src/crimson/os/seastore/segment_cleaner.cc
src/crimson/os/seastore/segment_cleaner.h

index c0edd31fc69b4190bf4dc11de2e65c08fe8902f6..05b42318859ef1bb638d3c4ed517dc298359899c 100644 (file)
@@ -710,6 +710,15 @@ SegmentCleaner::gc_cycle_ret SegmentCleaner::do_gc_cycle()
        "GCProcess::run encountered invalid error in gc_trim_journal"
       }
     );
+  } else if (gc_should_trim_backref()) {
+    return gc_trim_backref(get_backref_tail()
+    ).safe_then([](auto) {
+      return seastar::now();
+    }).handle_error(
+      crimson::ct_error::assert_all{
+       "GCProcess::run encountered invalid error in gc_trim_backref"
+      }
+    );
   } else if (gc_should_reclaim_space()) {
     return gc_reclaim_space(
     ).handle_error(
@@ -722,35 +731,45 @@ SegmentCleaner::gc_cycle_ret SegmentCleaner::do_gc_cycle()
   }
 }
 
-SegmentCleaner::gc_trim_journal_ret SegmentCleaner::gc_trim_journal()
-{
-  return ecb->with_transaction_intr(
-    Transaction::src_t::TRIM_BACKREF,
-    "trim_backref",
-    [this](auto &t) {
-    return seastar::do_with(
-      get_dirty_tail(),
-      [this, &t](auto &limit) {
-      return trim_backrefs(t, limit).si_then(
-       [this, &t, &limit](auto trim_backrefs_to)
-       -> ExtentCallbackInterface::submit_transaction_direct_iertr::future<
-            journal_seq_t> {
-       if (trim_backrefs_to != JOURNAL_SEQ_NULL) {
-         return ecb->submit_transaction_direct(
-           t, std::make_optional<journal_seq_t>(trim_backrefs_to)
-         ).si_then([trim_backrefs_to=std::move(trim_backrefs_to)]() mutable {
-           return seastar::make_ready_future<
-             journal_seq_t>(std::move(trim_backrefs_to));
-         });
-       }
-       return seastar::make_ready_future<journal_seq_t>(std::move(limit));
+SegmentCleaner::gc_trim_backref_ret
+SegmentCleaner::gc_trim_backref(journal_seq_t limit) {
+  return seastar::do_with(
+    journal_seq_t(),
+    [this, limit=std::move(limit)](auto &seq) mutable {
+    return repeat_eagain([this, limit=std::move(limit), &seq] {
+      return ecb->with_transaction_intr(
+       Transaction::src_t::TRIM_BACKREF,
+       "trim_backref",
+       [this, limit](auto &t) {
+       return trim_backrefs(
+         t,
+         limit
+       ).si_then([this, &t, limit](auto trim_backrefs_to)
+         -> ExtentCallbackInterface::submit_transaction_direct_iertr::future<
+           journal_seq_t> {
+         if (trim_backrefs_to != JOURNAL_SEQ_NULL) {
+           return ecb->submit_transaction_direct(
+             t, std::make_optional<journal_seq_t>(trim_backrefs_to)
+           ).si_then([trim_backrefs_to=std::move(trim_backrefs_to)]() mutable {
+             return seastar::make_ready_future<
+               journal_seq_t>(std::move(trim_backrefs_to));
+           });
+         }
+         return seastar::make_ready_future<journal_seq_t>(std::move(limit));
+       });
+      }).safe_then([&seq](auto trim_backrefs_to) {
+       seq = std::move(trim_backrefs_to);
       });
+    }).safe_then([&seq] {
+      return gc_trim_backref_ertr::make_ready_future<
+       journal_seq_t>(std::move(seq));
     });
-  }).handle_error(
-    crimson::ct_error::eagain::handle([](auto) {
-      ceph_abort("unexpected eagain");
-    }),
-    crimson::ct_error::pass_further_all()
+  });
+}
+
+SegmentCleaner::gc_trim_journal_ret SegmentCleaner::gc_trim_journal()
+{
+  return gc_trim_backref(get_dirty_tail()
   ).safe_then([this](auto seq) {
     return repeat_eagain([this, seq=std::move(seq)]() mutable {
       return ecb->with_transaction_intr(
index 786d6670988452b540fbc4a1359b72aef85ae782..f244f2689db95d599bd011cbc3255f0945ebd1f9 100644 (file)
@@ -479,6 +479,10 @@ public:
     /// Number of maximum journal segments to block user transactions.
     size_t max_journal_segments = 0;
 
+    /// Number of journal segments the transactions in which can
+    /// have their corresponding backrefs unmerged
+    size_t target_backref_inflight_segments = 0;
+
     /// Ratio of maximum available space to disable reclaiming.
     double available_ratio_gc_max = 0;
     /// Ratio of minimum available space to force reclaiming.
@@ -511,6 +515,7 @@ public:
       return config_t{
          12,   // target_journal_segments
          16,   // max_journal_segments
+         2,    // target_backref_inflight_segments
          .9,   // available_ratio_gc_max
          .2,   // available_ratio_hard_limit
          .8,   // reclaim_ratio_hard_limit
@@ -525,6 +530,7 @@ public:
       return config_t{
          2,    // target_journal_segments
          4,    // max_journal_segments
+         2,    // target_backref_inflight_segments
          .9,   // available_ratio_gc_max
          .2,   // available_ratio_hard_limit
          .8,   // reclaim_ratio_hard_limit
@@ -922,6 +928,17 @@ private:
     return ret;
   }
 
+  journal_seq_t get_backref_tail() const {
+    auto ret = segments.get_journal_head();
+    ceph_assert(ret != JOURNAL_SEQ_NULL);
+    if (ret.segment_seq >= config.target_backref_inflight_segments) {
+      ret.segment_seq -= config.target_backref_inflight_segments;
+    } else {
+      ret.segment_seq = 0;
+      ret.offset = P_ADDR_MIN;
+    }
+    return ret;
+  }
   // GC status helpers
   std::optional<paddr_t> next_reclaim_pos;
 
@@ -1021,6 +1038,10 @@ private:
   using gc_trim_journal_ret = gc_trim_journal_ertr::future<>;
   gc_trim_journal_ret gc_trim_journal();
 
+  using gc_trim_backref_ertr = gc_ertr;
+  using gc_trim_backref_ret = gc_trim_backref_ertr::future<journal_seq_t>;
+  gc_trim_backref_ret gc_trim_backref(journal_seq_t limit);
+
   using gc_reclaim_space_ertr = gc_ertr;
   using gc_reclaim_space_ret = gc_reclaim_space_ertr::future<>;
   gc_reclaim_space_ret gc_reclaim_space();
@@ -1223,6 +1244,9 @@ private:
     return get_dirty_tail() > journal_tail_target;
   }
 
+  bool gc_should_trim_backref() const {
+    return get_backref_tail() > alloc_info_replay_from;
+  }
   /**
    * gc_should_run
    *
@@ -1231,7 +1255,9 @@ private:
   bool gc_should_run() const {
     if (disable_trim) return false;
     ceph_assert(init_complete);
-    return gc_should_reclaim_space() || gc_should_trim_journal();
+    return gc_should_reclaim_space()
+      || gc_should_trim_journal()
+      || gc_should_trim_backref();
   }
 
   void init_mark_segment_closed(