From: Zhang Song Date: Wed, 18 Jun 2025 07:18:56 +0000 (+0800) Subject: crimson/os/seastore: move Cache::LRU out of Cache X-Git-Tag: v21.0.0~256^2~101^2~10 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=820e2f7b27c48e155927b37bf18f79b43c46ae53;p=ceph.git crimson/os/seastore: move Cache::LRU out of Cache Signed-off-by: Zhang Song --- diff --git a/src/common/options/crimson.yaml.in b/src/common/options/crimson.yaml.in index 5999758e2293..94676490635e 100644 --- a/src/common/options/crimson.yaml.in +++ b/src/common/options/crimson.yaml.in @@ -147,7 +147,7 @@ options: level: advanced desc: Max size in bytes that an extent can be, 0 to disable default: 0 -- name: seastore_cache_lru_size +- name: seastore_cachepin_size_pershard type: size level: advanced desc: Size in bytes of extents to keep in cache (per reactor). diff --git a/src/crimson/os/seastore/CMakeLists.txt b/src/crimson/os/seastore/CMakeLists.txt index d5ca12d8f067..97eae1d575cd 100644 --- a/src/crimson/os/seastore/CMakeLists.txt +++ b/src/crimson/os/seastore/CMakeLists.txt @@ -9,6 +9,7 @@ set(crimson_seastore_srcs transaction_manager.cc transaction.cc cache.cc + extent_pinboard.cc root_block.cc lba_manager.cc async_cleaner.cc diff --git a/src/crimson/os/seastore/cache.cc b/src/crimson/os/seastore/cache.cc index a639d83a78bd..1e1abdc41fb3 100644 --- a/src/crimson/os/seastore/cache.cc +++ b/src/crimson/os/seastore/cache.cc @@ -31,11 +31,10 @@ namespace crimson::os::seastore { Cache::Cache( ExtentPlacementManager &epm) : epm(epm), - lru(crimson::common::get_conf( - "seastore_cache_lru_size")) + pinboard(create_extent_pinboard( + crimson::common::get_conf( + "seastore_cachepin_size_pershard"))) { - LOG_PREFIX(Cache::Cache); - INFO("created, lru_capacity=0x{:x}B", lru.get_capacity_bytes()); register_metrics(); segment_providers_by_device_id.resize(DEVICE_ID_MAX, nullptr); } @@ -503,23 +502,11 @@ void Cache::register_metrics() stats.dirty_bytes, sm::description("total bytes of dirty extents") ), - sm::make_counter( - "cache_lru_size_bytes", - [this] { - return lru.get_current_size_bytes(); - }, - sm::description("total bytes pinned by the lru") - ), - sm::make_counter( - "cache_lru_num_extents", - [this] { - return lru.get_current_num_extents(); - }, - sm::description("total extents pinned by the lru") - ), } ); + pinboard->register_metrics(); + /** * tree stats */ @@ -744,7 +731,7 @@ void Cache::mark_dirty(CachedExtentRef ref) return; } - lru.remove_from_lru(*ref); + pinboard->remove(*ref); ref->state = CachedExtent::extent_state_t::DIRTY; add_to_dirty(ref, nullptr); } @@ -873,7 +860,7 @@ void Cache::remove_extent( remove_from_dirty(ref, p_src); } else if (!ref->is_placeholder()) { assert(ref->get_paddr().is_absolute()); - lru.remove_from_lru(*ref); + pinboard->remove(*ref); } extents_index.erase(*ref); } @@ -909,7 +896,7 @@ void Cache::commit_replace_extent( } else if (prev->is_stable_dirty()) { replace_dirty(next, prev, t_src); } else { - lru.remove_from_lru(*prev); + pinboard->remove(*prev); add_to_dirty(next, &t_src); } @@ -1949,20 +1936,20 @@ Cache::close_ertr::future<> Cache::close() { LOG_PREFIX(Cache::close); INFO("close with {}({}B) dirty, dirty_from={}, alloc_from={}, " - "{}({}B) lru, totally {}({}B) indexed extents", + "{}({}B) pinned extents, totally {}({}B) indexed extents", dirty.size(), stats.dirty_bytes, get_oldest_dirty_from().value_or(JOURNAL_SEQ_NULL), get_oldest_backref_dirty_from().value_or(JOURNAL_SEQ_NULL), - lru.get_current_num_extents(), - lru.get_current_size_bytes(), + pinboard->get_current_num_extents(), + pinboard->get_current_size_bytes(), extents_index.size(), extents_index.get_bytes()); root.reset(); clear_dirty(); backref_extents.clear(); backref_entryrefs_by_seq.clear(); - lru.clear(); + pinboard->clear(); return close_ertr::now(); } @@ -2362,7 +2349,7 @@ cache_stats_t Cache::get_stats( LOG_PREFIX(Cache::get_stats); cache_stats_t ret; - lru.get_stats(ret, report_detail, seconds); + pinboard->get_stats(ret, report_detail, seconds); /* * dirty stats @@ -2534,100 +2521,4 @@ cache_stats_t Cache::get_stats( return ret; } -void Cache::LRU::get_stats( - cache_stats_t &stats, - bool report_detail, - double seconds) const -{ - LOG_PREFIX(Cache::LRU::get_stats); - - stats.lru_sizes = cache_size_stats_t{current_size, lru.size()}; - stats.lru_io = overall_io; - stats.lru_io.minus(last_overall_io); - - if (report_detail && seconds != 0) { - counter_by_src_t > - _trans_io_by_src_ext = trans_io_by_src_ext; - counter_by_src_t trans_io_by_src; - cache_io_stats_t trans_io; - for (uint8_t _src=0; _src(_src); - auto& io_by_ext = get_by_src(_trans_io_by_src_ext, src); - const auto& last_io_by_ext = get_by_src(last_trans_io_by_src_ext, src); - auto& trans_io_per_src = get_by_src(trans_io_by_src, src); - for (uint8_t _ext=0; _ext(_ext); - auto& extent_io = get_by_ext(io_by_ext, ext); - const auto& last_extent_io = get_by_ext(last_io_by_ext, ext); - extent_io.minus(last_extent_io); - trans_io_per_src.add(extent_io); - } - trans_io.add(trans_io_per_src); - } - cache_io_stats_t other_io = stats.lru_io; - other_io.minus(trans_io); - - std::ostringstream oss; - oss << "\nlru total" << stats.lru_sizes; - cache_size_stats_t data_sizes; - cache_size_stats_t mdat_sizes; - cache_size_stats_t phys_sizes; - for (uint8_t _ext=0; _ext(_ext); - const auto& extent_sizes = get_by_ext(sizes_by_ext, ext); - if (is_data_type(ext)) { - data_sizes.add(extent_sizes); - } else if (is_logical_metadata_type(ext)) { - mdat_sizes.add(extent_sizes); - } else if (is_physical_type(ext)) { - phys_sizes.add(extent_sizes); - } - } - oss << "\n data" << data_sizes - << "\n mdat" << mdat_sizes - << "\n phys" << phys_sizes; - - oss << "\nlru io: trans-" - << cache_io_stats_printer_t{seconds, trans_io} - << "; other-" - << cache_io_stats_printer_t{seconds, other_io}; - for (uint8_t _src=0; _src(_src); - const auto& trans_io_per_src = get_by_src(trans_io_by_src, src); - if (trans_io_per_src.is_empty()) { - continue; - } - cache_io_stats_t data_io; - cache_io_stats_t mdat_io; - cache_io_stats_t phys_io; - const auto& io_by_ext = get_by_src(_trans_io_by_src_ext, src); - for (uint8_t _ext=0; _ext(_ext); - const auto extent_io = get_by_ext(io_by_ext, ext); - if (is_data_type(ext)) { - data_io.add(extent_io); - } else if (is_logical_metadata_type(ext)) { - mdat_io.add(extent_io); - } else if (is_physical_type(ext)) { - phys_io.add(extent_io); - } - } - oss << "\n " << src << ": " - << cache_io_stats_printer_t{seconds, trans_io_per_src} - << "\n data: " - << cache_io_stats_printer_t{seconds, data_io} - << "\n mdat: " - << cache_io_stats_printer_t{seconds, mdat_io} - << "\n phys: " - << cache_io_stats_printer_t{seconds, phys_io}; - } - - INFO("{}", oss.str()); - - last_trans_io_by_src_ext = trans_io_by_src_ext; - } - - last_overall_io = overall_io; -} - } diff --git a/src/crimson/os/seastore/cache.h b/src/crimson/os/seastore/cache.h index dc7e25bcf6d7..d14f76d6f462 100644 --- a/src/crimson/os/seastore/cache.h +++ b/src/crimson/os/seastore/cache.h @@ -19,6 +19,7 @@ #include "crimson/os/seastore/segment_manager.h" #include "crimson/os/seastore/transaction.h" #include "crimson/os/seastore/linked_tree_node.h" +#include "crimson/os/seastore/extent_pinboard.h" namespace crimson::os::seastore::backref { class BtreeBackrefManager; @@ -1573,7 +1574,7 @@ public: } private: - /// Update lru for access to ref + /// Update extent pinboard for access to ref void touch_extent( CachedExtent &ext, const Transaction::src_t* p_src, @@ -1584,7 +1585,7 @@ private: return; } if (ext.is_stable_clean() && !ext.is_placeholder()) { - lru.move_to_top(ext, p_src); + pinboard->move_to_top(ext, p_src); } } @@ -1641,159 +1642,7 @@ private: friend class crimson::os::seastore::backref::BtreeBackrefManager; friend class crimson::os::seastore::BackrefManager; - /** - * lru - * - * holds references to recently used extents - */ - class LRU { - // max size (bytes) - const size_t capacity = 0; - - // current size (bytes) - size_t current_size = 0; - - counter_by_extent_t sizes_by_ext; - cache_io_stats_t overall_io; - counter_by_src_t > - trans_io_by_src_ext; - - mutable cache_io_stats_t last_overall_io; - mutable cache_io_stats_t last_trans_io; - mutable counter_by_src_t > - last_trans_io_by_src_ext; - - CachedExtent::primary_ref_list lru; - - void do_remove_from_lru( - CachedExtent &extent, - const Transaction::src_t* p_src) { - assert(extent.is_stable_clean() && !extent.is_placeholder()); - assert(extent.primary_ref_list_hook.is_linked()); - assert(lru.size() > 0); - auto extent_loaded_length = extent.get_loaded_length(); - assert(current_size >= extent_loaded_length); - - lru.erase(lru.s_iterator_to(extent)); - current_size -= extent_loaded_length; - get_by_ext(sizes_by_ext, extent.get_type()).account_out(extent_loaded_length); - overall_io.out_sizes.account_in(extent_loaded_length); - if (p_src) { - get_by_ext( - get_by_src(trans_io_by_src_ext, *p_src), - extent.get_type() - ).out_sizes.account_in(extent_loaded_length); - } - intrusive_ptr_release(&extent); - } - - void trim_to_capacity( - const Transaction::src_t* p_src) { - while (current_size > capacity) { - do_remove_from_lru(lru.front(), p_src); - } - } - - public: - LRU(size_t capacity) : capacity(capacity) {} - - size_t get_capacity_bytes() const { - return capacity; - } - - size_t get_current_size_bytes() const { - return current_size; - } - - size_t get_current_num_extents() const { - return lru.size(); - } - - void get_stats( - cache_stats_t &stats, - bool report_detail, - double seconds) const; - - void remove_from_lru(CachedExtent &extent) { - assert(extent.is_stable_clean()); - assert(!extent.is_placeholder()); - - if (extent.primary_ref_list_hook.is_linked()) { - do_remove_from_lru(extent, nullptr); - } - } - - void move_to_top( - CachedExtent &extent, - const Transaction::src_t* p_src) { - assert(extent.is_stable_clean()); - assert(!extent.is_placeholder()); - - auto extent_loaded_length = extent.get_loaded_length(); - if (extent.primary_ref_list_hook.is_linked()) { - // present, move to top (back) - assert(lru.size() > 0); - assert(current_size >= extent_loaded_length); - lru.erase(lru.s_iterator_to(extent)); - lru.push_back(extent); - } else { - // absent, add to top (back) - if (extent_loaded_length > 0) { - current_size += extent_loaded_length; - overall_io.in_sizes.account_in(extent_loaded_length); - if (p_src) { - get_by_ext( - get_by_src(trans_io_by_src_ext, *p_src), - extent.get_type() - ).in_sizes.account_in(extent_loaded_length); - } - } // else: the extent isn't loaded upon touch_extent()/on_cache(), - // account the io later in increase_cached_size() upon read_extent() - get_by_ext(sizes_by_ext, extent.get_type()).account_in(extent_loaded_length); - intrusive_ptr_add_ref(&extent); - lru.push_back(extent); - - trim_to_capacity(p_src); - } - } - - void increase_cached_size( - CachedExtent &extent, - extent_len_t increased_length, - const Transaction::src_t* p_src) { - assert(extent.is_data_stable()); - - if (extent.primary_ref_list_hook.is_linked()) { - assert(extent.is_stable_clean()); - assert(!extent.is_placeholder()); - // present, increase size - assert(lru.size() > 0); - current_size += increased_length; - get_by_ext(sizes_by_ext, extent.get_type()).account_parital_in(increased_length); - overall_io.in_sizes.account_in(increased_length); - if (p_src) { - get_by_ext( - get_by_src(trans_io_by_src_ext, *p_src), - extent.get_type() - ).in_sizes.account_in(increased_length); - } - - trim_to_capacity(nullptr); - } - } - - void clear() { - LOG_PREFIX(Cache::LRU::clear); - for (auto iter = lru.begin(); iter != lru.end();) { - SUBDEBUG(seastore_cache, "clearing {}", *iter); - do_remove_from_lru(*(iter++), nullptr); - } - } - - ~LRU() { - clear(); - } - } lru; + ExtentPinboardRef pinboard; struct query_counters_t { uint64_t access = 0; @@ -2023,7 +1872,7 @@ private: load_ranges_t to_read = extent->load_ranges(offset, length); auto new_length = extent->get_loaded_length(); assert(new_length > old_length); - lru.increase_cached_size(*extent, new_length - old_length, p_src); + pinboard->increase_cached_size(*extent, new_length - old_length, p_src); return seastar::do_with(to_read.ranges, [extent, this, FNAME](auto &read_ranges) { return ExtentPlacementManager::read_ertr::parallel_for_each( read_ranges, [extent, this, FNAME](auto &read_range) { diff --git a/src/crimson/os/seastore/cached_extent.h b/src/crimson/os/seastore/cached_extent.h index 10c4aa704c81..b3defca30730 100644 --- a/src/crimson/os/seastore/cached_extent.h +++ b/src/crimson/os/seastore/cached_extent.h @@ -1011,6 +1011,7 @@ protected: } friend class Cache; + friend class ExtentPinboardLRU; template static TCachedExtentRef make_cached_extent_ref( Args&&... args) { diff --git a/src/crimson/os/seastore/extent_pinboard.cc b/src/crimson/os/seastore/extent_pinboard.cc new file mode 100644 index 000000000000..2f842d3d1af7 --- /dev/null +++ b/src/crimson/os/seastore/extent_pinboard.cc @@ -0,0 +1,289 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "crimson/os/seastore/extent_pinboard.h" +#include "crimson/os/seastore/transaction.h" + +SET_SUBSYS(seastore_cache); + +namespace crimson::os::seastore { + +class ExtentPinboardLRU : public ExtentPinboard { + // max size (bytes) + const std::size_t capacity = 0; + + // current size (bytes) + std::size_t current_size = 0; + + counter_by_extent_t sizes_by_ext; + cache_io_stats_t overall_io; + counter_by_src_t > + trans_io_by_src_ext; + + mutable cache_io_stats_t last_overall_io; + mutable cache_io_stats_t last_trans_io; + mutable counter_by_src_t > + last_trans_io_by_src_ext; + + CachedExtent::primary_ref_list lru; + + seastar::metrics::metric_group metrics; + + void do_remove_from_lru( + CachedExtent &extent, + const Transaction::src_t* p_src) { + assert(extent.is_stable_clean()); + assert(!extent.is_placeholder()); + assert(extent.primary_ref_list_hook.is_linked()); + assert(lru.size() > 0); + auto extent_loaded_length = extent.get_loaded_length(); + assert(current_size >= extent_loaded_length); + + lru.erase(lru.s_iterator_to(extent)); + current_size -= extent_loaded_length; + get_by_ext(sizes_by_ext, extent.get_type()).account_out(extent_loaded_length); + overall_io.out_sizes.account_in(extent_loaded_length); + if (p_src) { + get_by_ext( + get_by_src(trans_io_by_src_ext, *p_src), + extent.get_type() + ).out_sizes.account_in(extent_loaded_length); + } + intrusive_ptr_release(&extent); + } + + void trim_to_capacity( + const Transaction::src_t* p_src) { + while (current_size > capacity) { + do_remove_from_lru(lru.front(), p_src); + } + } + +public: + ExtentPinboardLRU(std::size_t capacity) : capacity(capacity) { + LOG_PREFIX(ExtentPinboardLRU::ExtentPinboardLRU); + INFO("created, lru_capacity=0x{:x}B", capacity); + } + + std::size_t get_capacity_bytes() const { + return capacity; + } + + std::size_t get_current_size_bytes() const final { + return current_size; + } + + std::size_t get_current_num_extents() const final { + return lru.size(); + } + + void register_metrics() final { + namespace sm = seastar::metrics; + metrics.add_group( + "cache", + { + sm::make_counter( + "lru_size_bytes", + [this] { + return get_current_size_bytes(); + }, + sm::description("total bytes pinned by the lru") + ), + sm::make_counter( + "lru_num_extents", + [this] { + return get_current_num_extents(); + }, + sm::description("total extents pinned by the lru") + ), + } + ); + } + + void get_stats( + cache_stats_t &stats, + bool report_detail, + double seconds) const final; + + void remove(CachedExtent &extent) { + assert(extent.is_stable_clean()); + assert(!extent.is_placeholder()); + + if (extent.primary_ref_list_hook.is_linked()) { + do_remove_from_lru(extent, nullptr); + } + } + + void move_to_top( + CachedExtent &extent, + const Transaction::src_t* p_src) { + assert(extent.is_stable_clean()); + assert(!extent.is_placeholder()); + + auto extent_loaded_length = extent.get_loaded_length(); + if (extent.primary_ref_list_hook.is_linked()) { + // present, move to top (back) + assert(lru.size() > 0); + assert(current_size >= extent_loaded_length); + lru.erase(lru.s_iterator_to(extent)); + lru.push_back(extent); + } else { + // absent, add to top (back) + if (extent_loaded_length > 0) { + current_size += extent_loaded_length; + overall_io.in_sizes.account_in(extent_loaded_length); + if (p_src) { + get_by_ext( + get_by_src(trans_io_by_src_ext, *p_src), + extent.get_type() + ).in_sizes.account_in(extent_loaded_length); + } + } // else: the extent isn't loaded upon touch_extent()/on_cache(), + // account the io later in increase_cached_size() upon read_extent() + get_by_ext(sizes_by_ext, extent.get_type()).account_in(extent_loaded_length); + intrusive_ptr_add_ref(&extent); + lru.push_back(extent); + + trim_to_capacity(p_src); + } + } + + void increase_cached_size( + CachedExtent &extent, + extent_len_t increased_length, + const Transaction::src_t* p_src) final { + assert(extent.is_data_stable()); + + if (extent.primary_ref_list_hook.is_linked()) { + assert(extent.is_stable_clean()); + assert(!extent.is_placeholder()); + // present, increase size + assert(lru.size() > 0); + current_size += increased_length; + get_by_ext(sizes_by_ext, extent.get_type()).account_parital_in(increased_length); + overall_io.in_sizes.account_in(increased_length); + if (p_src) { + get_by_ext( + get_by_src(trans_io_by_src_ext, *p_src), + extent.get_type() + ).in_sizes.account_in(increased_length); + } + + trim_to_capacity(nullptr); + } + } + + void clear() final { + LOG_PREFIX(ExtentPinboardLRU::clear); + for (auto iter = lru.begin(); iter != lru.end();) { + SUBDEBUG(seastore_cache, "clearing {}", *iter); + do_remove_from_lru(*(iter++), nullptr); + } + } + + ~ExtentPinboardLRU() { + clear(); + } +}; + +ExtentPinboardRef create_extent_pinboard(std::size_t capacity) { + return std::make_unique(capacity); +} + +void ExtentPinboardLRU::get_stats( + cache_stats_t &stats, + bool report_detail, + double seconds) const +{ + LOG_PREFIX(Cache::LRU::get_stats); + + stats.lru_sizes = cache_size_stats_t{current_size, lru.size()}; + stats.lru_io = overall_io; + stats.lru_io.minus(last_overall_io); + + if (report_detail && seconds != 0) { + counter_by_src_t > + _trans_io_by_src_ext = trans_io_by_src_ext; + counter_by_src_t trans_io_by_src; + cache_io_stats_t trans_io; + for (uint8_t _src=0; _src(_src); + auto& io_by_ext = get_by_src(_trans_io_by_src_ext, src); + const auto& last_io_by_ext = get_by_src(last_trans_io_by_src_ext, src); + auto& trans_io_per_src = get_by_src(trans_io_by_src, src); + for (uint8_t _ext=0; _ext(_ext); + auto& extent_io = get_by_ext(io_by_ext, ext); + const auto& last_extent_io = get_by_ext(last_io_by_ext, ext); + extent_io.minus(last_extent_io); + trans_io_per_src.add(extent_io); + } + trans_io.add(trans_io_per_src); + } + cache_io_stats_t other_io = stats.lru_io; + other_io.minus(trans_io); + + std::ostringstream oss; + oss << "\nlru total" << stats.lru_sizes; + cache_size_stats_t data_sizes; + cache_size_stats_t mdat_sizes; + cache_size_stats_t phys_sizes; + for (uint8_t _ext=0; _ext(_ext); + const auto& extent_sizes = get_by_ext(sizes_by_ext, ext); + if (is_data_type(ext)) { + data_sizes.add(extent_sizes); + } else if (is_logical_metadata_type(ext)) { + mdat_sizes.add(extent_sizes); + } else if (is_physical_type(ext)) { + phys_sizes.add(extent_sizes); + } + } + oss << "\n data" << data_sizes + << "\n mdat" << mdat_sizes + << "\n phys" << phys_sizes; + + oss << "\nlru io: trans-" + << cache_io_stats_printer_t{seconds, trans_io} + << "; other-" + << cache_io_stats_printer_t{seconds, other_io}; + for (uint8_t _src=0; _src(_src); + const auto& trans_io_per_src = get_by_src(trans_io_by_src, src); + if (trans_io_per_src.is_empty()) { + continue; + } + cache_io_stats_t data_io; + cache_io_stats_t mdat_io; + cache_io_stats_t phys_io; + const auto& io_by_ext = get_by_src(_trans_io_by_src_ext, src); + for (uint8_t _ext=0; _ext(_ext); + const auto extent_io = get_by_ext(io_by_ext, ext); + if (is_data_type(ext)) { + data_io.add(extent_io); + } else if (is_logical_metadata_type(ext)) { + mdat_io.add(extent_io); + } else if (is_physical_type(ext)) { + phys_io.add(extent_io); + } + } + oss << "\n " << src << ": " + << cache_io_stats_printer_t{seconds, trans_io_per_src} + << "\n data: " + << cache_io_stats_printer_t{seconds, data_io} + << "\n mdat: " + << cache_io_stats_printer_t{seconds, mdat_io} + << "\n phys: " + << cache_io_stats_printer_t{seconds, phys_io}; + } + + INFO("{}", oss.str()); + + last_trans_io_by_src_ext = trans_io_by_src_ext; + } + + last_overall_io = overall_io; +} + +} // namespace crimson::os::seastore diff --git a/src/crimson/os/seastore/extent_pinboard.h b/src/crimson/os/seastore/extent_pinboard.h new file mode 100644 index 000000000000..6e6d2f3dd4cd --- /dev/null +++ b/src/crimson/os/seastore/extent_pinboard.h @@ -0,0 +1,33 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "crimson/os/seastore/cached_extent.h" +#include "crimson/os/seastore/transaction.h" + +namespace crimson::os::seastore { + +struct ExtentPinboard { + virtual ~ExtentPinboard() = default; + virtual void register_metrics() = 0; + virtual void move_to_top( + CachedExtent &extent, + const Transaction::src_t *p_src) = 0; + virtual void remove(CachedExtent &extent) = 0; + virtual void get_stats( + cache_stats_t &stats, + bool report_detail, + double seconds) const = 0; + virtual std::size_t get_current_size_bytes() const = 0; + virtual std::size_t get_current_num_extents() const = 0; + virtual void increase_cached_size( + CachedExtent &extent, + extent_len_t increased_length, + const Transaction::src_t *p_src) = 0; + virtual void clear() = 0; +}; +using ExtentPinboardRef = std::unique_ptr; +ExtentPinboardRef create_extent_pinboard(std::size_t capacity); + +} // namespace crimson::os::seastore