From 3ea0e7bb2fec955c5bfff7de938a2c25394d122e Mon Sep 17 00:00:00 2001 From: Yingxin Cheng Date: Mon, 9 May 2022 12:14:57 +0800 Subject: [PATCH] crimson/os/seastore/segment_cleaner: distinguish in-journal and type-journal segments Signed-off-by: Yingxin Cheng --- src/crimson/os/seastore/segment_cleaner.cc | 36 ++++++--- src/crimson/os/seastore/segment_cleaner.h | 87 +++++++++++++++------- 2 files changed, 88 insertions(+), 35 deletions(-) diff --git a/src/crimson/os/seastore/segment_cleaner.cc b/src/crimson/os/seastore/segment_cleaner.cc index 637d4f4c829..91d90fd0547 100644 --- a/src/crimson/os/seastore/segment_cleaner.cc +++ b/src/crimson/os/seastore/segment_cleaner.cc @@ -80,8 +80,9 @@ void segments_info_t::reset() segment_size = 0; journal_segment_id = NULL_SEG_ID; - // the number of in-journal closed segments - num_in_journal = 0; + num_in_journal_open = 0; + num_type_journal = 0; + num_type_ool = 0; num_open = 0; num_empty = 0; @@ -142,7 +143,9 @@ void segments_info_t::init_closed( if (type == segment_type_t::JOURNAL) { // init_closed won't initialize journal_segment_id ceph_assert(get_journal_head() == JOURNAL_SEQ_NULL); - ++num_in_journal; + ++num_type_journal; + } else { + ++num_type_ool; } // do not increment count_close; } @@ -168,6 +171,11 @@ void segments_info_t::mark_open( ceph_assert(last_journal_segment.seq + 1 == seq); } journal_segment_id = segment; + + ++num_in_journal_open; + ++num_type_journal; + } else { + ++num_type_ool; } ceph_assert(segment_info.written_to == 0); avail_bytes_in_open += get_segment_size(); @@ -190,8 +198,11 @@ void segments_info_t::mark_empty( --num_closed; ++num_empty; if (type == segment_type_t::JOURNAL) { - ceph_assert(num_in_journal > 0); - --num_in_journal; + ceph_assert(num_type_journal > 0); + --num_type_journal; + } else { + ceph_assert(num_type_ool > 0); + --num_type_ool; } ++count_release; } @@ -210,7 +221,8 @@ void segments_info_t::mark_closed( --num_open; ++num_closed; if (segment_info.type == segment_type_t::JOURNAL) { - ++num_in_journal; + ceph_assert(num_in_journal_open > 0); + --num_in_journal_open; } ceph_assert(get_segment_size() >= segment_info.written_to); auto seg_avail_bytes = get_segment_size() - segment_info.written_to; @@ -427,8 +439,14 @@ void SegmentCleaner::register_metrics() [this] { return segments.get_segment_size(); }, sm::description("the bytes of a segment")), sm::make_counter("segments_in_journal", - [this] { return segments.get_num_in_journal(); }, + [this] { return get_segments_in_journal(); }, sm::description("the number of segments in journal")), + sm::make_counter("segments_type_journal", + [this] { return segments.get_num_type_journal(); }, + sm::description("the number of segments typed journal")), + sm::make_counter("segments_type_ool", + [this] { return segments.get_num_type_ool(); }, + sm::description("the number of segments typed out-of-line")), sm::make_counter("segments_open", [this] { return segments.get_num_open(); }, sm::description("the number of open segments")), @@ -456,10 +474,10 @@ void SegmentCleaner::register_metrics() [this] { return segments.get_available_bytes(); }, sm::description("the size of the space is available")), sm::make_counter("unavailable_unreclaimable_bytes", - [this] { return segments.get_unavailable_unreclaimable_bytes(); }, + [this] { return get_unavailable_unreclaimable_bytes(); }, sm::description("the size of the space is unavailable and unreclaimable")), sm::make_counter("unavailable_reclaimable_bytes", - [this] { return segments.get_unavailable_reclaimable_bytes(); }, + [this] { return get_unavailable_reclaimable_bytes(); }, sm::description("the size of the space is unavailable and reclaimable")), sm::make_counter("used_bytes", stats.used_bytes, sm::description("the size of the space occupied by live extents")), diff --git a/src/crimson/os/seastore/segment_cleaner.h b/src/crimson/os/seastore/segment_cleaner.h index b3e842ed548..a95605ecf99 100644 --- a/src/crimson/os/seastore/segment_cleaner.h +++ b/src/crimson/os/seastore/segment_cleaner.h @@ -114,12 +114,14 @@ public: assert(segment_size > 0); return segment_size; } - std::size_t get_num_in_journal() const { - assert(num_in_journal <= num_closed); - return num_in_journal; + std::size_t get_num_in_journal_open() const { + return num_in_journal_open; } - std::size_t get_num_reclaimable() const { - return num_closed - get_num_in_journal(); + std::size_t get_num_type_journal() const { + return num_type_journal; + } + std::size_t get_num_type_ool() const { + return num_type_ool; } std::size_t get_num_open() const { return num_open; @@ -140,32 +142,20 @@ public: return count_close; } - /* - * Space classification - * - total = available + unavailable (unreclaimable + reclaimable) - * - available: the available space for write, including open segments - * - unreclaimable: in journal or still open, cannot be reclaimed - * - reclaimable: closed and non-empty segments, can be reclaimed - */ std::size_t get_total_bytes() const { return total_bytes; } + /// the available space that is writable, including in open segments std::size_t get_available_bytes() const { return num_empty * get_segment_size() + avail_bytes_in_open; } + /// the unavailable space that is not writable std::size_t get_unavailable_bytes() const { assert(total_bytes >= get_available_bytes()); return total_bytes - get_available_bytes(); } - std::size_t get_unavailable_unreclaimable_bytes() const { - auto ret = (num_open + get_num_in_journal()) * get_segment_size(); - assert(ret >= avail_bytes_in_open); - return ret - avail_bytes_in_open; - } - std::size_t get_unavailable_reclaimable_bytes() const { - auto ret = get_num_reclaimable() * get_segment_size(); - assert(ret + get_unavailable_unreclaimable_bytes() == get_unavailable_bytes()); - return ret; + std::size_t get_available_bytes_in_open() const { + return avail_bytes_in_open; } double get_available_ratio() const { return (double)get_available_bytes() / (double)total_bytes; @@ -214,7 +204,9 @@ private: std::size_t segment_size; segment_id_t journal_segment_id; - std::size_t num_in_journal; + std::size_t num_in_journal_open; + std::size_t num_type_journal; + std::size_t num_type_ool; std::size_t num_open; std::size_t num_empty; @@ -933,7 +925,7 @@ private: max_benefit_cost); return journal_seq_t{seq, paddr_t::make_seg_paddr(id, 0)}; } else { - ceph_assert(segments.get_num_reclaimable() == 0); + ceph_assert(get_segments_reclaimable() == 0); // see gc_should_reclaim_space() ceph_abort("impossible!"); return JOURNAL_SEQ_NULL; @@ -1104,9 +1096,52 @@ private: backref_buf_entry_t::cmp_t> &&backrefs, std::vector &extents); + /* + * Segments calculations + */ + std::size_t get_segments_in_journal() const { + if (!init_complete) { + return 0; + } + if (journal_tail_committed == JOURNAL_SEQ_NULL) { + return segments.get_num_type_journal(); + } + auto journal_head = segments.get_journal_head(); + assert(journal_head != JOURNAL_SEQ_NULL); + assert(journal_head.segment_seq >= journal_tail_committed.segment_seq); + return journal_head.segment_seq + 1 - journal_tail_committed.segment_seq; + } + std::size_t get_segments_in_journal_closed() const { + auto in_journal = get_segments_in_journal(); + auto in_journal_open = segments.get_num_in_journal_open(); + if (in_journal >= in_journal_open) { + return in_journal - in_journal_open; + } else { + return 0; + } + } + std::size_t get_segments_reclaimable() const { + assert(segments.get_num_closed() >= get_segments_in_journal_closed()); + return segments.get_num_closed() - get_segments_in_journal_closed(); + } + /* * Space calculations */ + /// the unavailable space that is not reclaimable yet + std::size_t get_unavailable_unreclaimable_bytes() const { + auto ret = (segments.get_num_open() + get_segments_in_journal_closed()) * + segments.get_segment_size(); + assert(ret >= segments.get_available_bytes_in_open()); + return ret - segments.get_available_bytes_in_open(); + } + /// the unavailable space that can be reclaimed + std::size_t get_unavailable_reclaimable_bytes() const { + auto ret = get_segments_reclaimable() * segments.get_segment_size(); + ceph_assert(ret + get_unavailable_unreclaimable_bytes() == segments.get_unavailable_bytes()); + return ret; + } + /// the unavailable space that is not alive std::size_t get_unavailable_unused_bytes() const { assert(segments.get_unavailable_bytes() > stats.used_bytes); return segments.get_unavailable_bytes() - stats.used_bytes; @@ -1138,7 +1173,7 @@ private: if (get_dirty_tail_limit() > journal_tail_target) { return true; } - if (segments.get_num_reclaimable() == 0) { + if (get_segments_reclaimable() == 0) { return false; } auto aratio = get_projected_available_ratio(); @@ -1178,7 +1213,7 @@ private: segments.get_num_empty(), segments.get_num_open(), segments.get_num_closed(), - segments.get_num_in_journal(), + get_segments_in_journal(), segments.get_total_bytes(), segments.get_available_bytes(), segments.get_unavailable_bytes(), @@ -1265,7 +1300,7 @@ private: * Encapsulates logic for whether gc should be reclaiming segment space. */ bool gc_should_reclaim_space() const { - if (segments.get_num_reclaimable() == 0) { + if (get_segments_reclaimable() == 0) { return false; } auto aratio = segments.get_available_ratio(); -- 2.39.5