From: Xuehan Xu Date: Mon, 18 Aug 2025 09:20:24 +0000 (+0800) Subject: crimson/os/seastore/transaction_manager: add read_pins X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=5c440f6c0c22b99c03249471d3c30b316cd5fc38;p=ceph-ci.git crimson/os/seastore/transaction_manager: add read_pins Signed-off-by: Xuehan Xu --- diff --git a/src/crimson/os/seastore/cache.h b/src/crimson/os/seastore/cache.h index 386050c2044..b1f53a59533 100644 --- a/src/crimson/os/seastore/cache.h +++ b/src/crimson/os/seastore/cache.h @@ -379,21 +379,20 @@ public: } /* - * get_absent_extent + * prepare_absent_extent * - * The extent in query is supposed to be absent in Cache. - * partially load buffer from partial_off~partial_len if not present. + * Prepare the extent that's absent in Cache, this is for later + * batch reads. */ template - get_extent_iertr::future> get_absent_extent( + TCachedExtentRef prepare_absent_extent( Transaction &t, paddr_t offset, extent_len_t length, extent_len_t partial_off, extent_len_t partial_len, - Func &&extent_init_func, - uint32_t pin_crc = CRC_NULL) { - LOG_PREFIX(Cache::get_absent_extent); + Func &&extent_init_func) { + LOG_PREFIX(Cached::prepare_absent_extent); #ifndef NDEBUG { @@ -406,8 +405,7 @@ public: } #endif - SUBTRACET(seastore_cache, "{} {}~0x{:x} is absent on t, query cache ...", - t, T::TYPE, offset, length); + SUBTRACET(seastore_cache, "{} {}~0x{:x}", t, T::TYPE, offset, length); ceph_assert(!booting); const auto t_src = t.get_src(); @@ -432,6 +430,30 @@ public: touch_extent_by_range( *ret, &t_src, t.get_cache_hint(), partial_off, partial_len); + return ret; + } + + /* + * get_absent_extent + * + * The extent in query is supposed to be absent in Cache. + * partially load buffer from partial_off~partial_len if not present. + */ + template + get_extent_iertr::future> get_absent_extent( + Transaction &t, + paddr_t offset, + extent_len_t length, + extent_len_t partial_off, + extent_len_t partial_len, + Func &&extent_init_func, + uint32_t pin_crc = CRC_NULL) { + LOG_PREFIX(Cache::get_absent_extent); + SUBTRACET(seastore_cache, "{} {}~0x{:x}", t, T::TYPE, offset, length); + + auto ret = prepare_absent_extent( + t, offset, length, partial_off, partial_len, std::move(extent_init_func)); + const auto t_src = t.get_src(); return trans_intr::make_interruptible( read_extent(std::move(ret), partial_off, partial_len, &t_src, pin_crc)); } diff --git a/src/crimson/os/seastore/transaction_manager.h b/src/crimson/os/seastore/transaction_manager.h index 048cd501b86..73cb3694485 100644 --- a/src/crimson/os/seastore/transaction_manager.h +++ b/src/crimson/os/seastore/transaction_manager.h @@ -284,6 +284,134 @@ public: }); } + template + struct read_pin_t { + LBAMapping mapping; + const extent_len_t partial_off = 0; + const extent_len_t partial_len = 0; + read_pin_t( + LBAMapping mapping, + extent_len_t partial_off, + extent_len_t partial_len) + : mapping(std::move(mapping)), + partial_off(partial_off), + partial_len(partial_len) {} + maybe_indirect_extent_t get_result() const { + bool is_clone = mapping.is_clone(); + std::optional maybe_indirect_info; + if (mapping.is_indirect()) { + auto intermediate_offset = mapping.get_intermediate_offset(); + maybe_indirect_info = indirect_info_t{ + intermediate_offset, mapping.get_length()}; + } + return maybe_indirect_extent_t{ + extent, std::move(maybe_indirect_info), is_clone}; + } + private: + TCachedExtentRef extent; + std::function on_read; + + inline extent_len_t maybe_get_direct_partial_off() const { + extent_len_t direct_partial_off = partial_off; + if (mapping.is_indirect()) { + auto intermediate_offset = mapping.get_intermediate_offset(); + direct_partial_off = intermediate_offset + partial_off; + } + return direct_partial_off; + } + Cache::read_extent_t get_read_extent_param(bool full_extent) const { + return Cache::read_extent_t{ + extent, + full_extent ? 0 : maybe_get_direct_partial_off(), + full_extent ? extent->get_length() : partial_len}; + } + void read_succeeded() { + if (on_read) { + on_read(*extent); + } + } + friend class TransactionManager; + }; + template + requires std::is_base_of_v, U> + base_iertr::future<> read_pins( + Transaction &t, + std::vector &pins, + lextent_init_func_t maybe_init = [](T&) {}) + { + LOG_PREFIX(TransactionManager::read_pins); + static_assert(is_logical_type(T::TYPE)); + co_await trans_intr::parallel_for_each( + pins, + seastar::coroutine::lambda( + [this, &t, FNAME, maybe_init=std::move(maybe_init)](auto &pin) + -> get_child_iertr::future<> { + assert(is_aligned(pin.partial_off, get_block_size())); + assert(is_aligned(pin.partial_len, get_block_size())); + // must be user-oriented required by maybe_init + assert(is_user_transaction(t.get_src())); + if (pin.mapping.is_zero_reserved()) { + co_return; + } + + pin.mapping = co_await pin.mapping.refresh(); + if (pin.mapping.is_indirect()) { + pin.mapping = co_await lba_manager->complete_indirect_lba_mapping( + t, std::move(pin.mapping)); + } + SUBTRACET(seastore_tm, "{} {}~{}", + t, pin.mapping, pin.partial_off, pin.partial_len); + auto ret = get_extent_if_linked(t, pin.mapping); + if (ret.index() == 1) { + auto extent = co_await std::move(std::get<1>(ret)); + pin.extent = std::move(extent); + pin.on_read = [maybe_init=std::move(maybe_init)](auto &extent) { + if (!extent.is_seen_by_users()) { + maybe_init(extent); + extent.set_seen_by_users(); + } + }; + co_return; + } else { + auto &r = std::get<0>(ret); + pin.extent = cache->prepare_absent_extent( + t, + pin.mapping.get_val(), + pin.mapping.get_intermediate_length(), + pin.maybe_get_direct_partial_off(), + pin.partial_len, + [laddr=pin.mapping.get_intermediate_base(), + maybe_init=std::move(maybe_init), + child_pos=std::move(r.child_pos), + &t, this] + (T &extent) mutable { + assert(extent.is_logical()); + assert(!extent.has_laddr()); + assert(!extent.has_been_invalidated()); + child_pos.link_child(&extent); + child_pos.invalidate_retired_placeholder(t, *cache, extent); + extent.set_laddr(laddr); + maybe_init(extent); + extent.set_seen_by_users(); + }); + co_return; + } + }) + ); + std::vector> extents; + for (auto &pin : pins) { + if (pin.mapping.is_zero_reserved()) { + continue; + } + extents.emplace_back(pin.get_read_extent_param( + full_extent_integrity_check)); + } + co_await cache->read_extents_maybe_partial(t, std::move(extents)); + for (auto &pin : pins) { + pin.read_succeeded(); + } + } + template base_iertr::future> read_pin( Transaction &t,