From: Xuehan Xu Date: Mon, 18 May 2026 09:55:35 +0000 (+0800) Subject: crimson/os/seastore: demote/promote background processes are also X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=18ce9e3373646bfa01ac30baa182e847c318586e;p=ceph-ci.git crimson/os/seastore: demote/promote background processes are also rewrite transactions Signed-off-by: Xuehan Xu --- diff --git a/src/crimson/os/seastore/cache.cc b/src/crimson/os/seastore/cache.cc index 1146c994362..033fc4b4a02 100644 --- a/src/crimson/os/seastore/cache.cc +++ b/src/crimson/os/seastore/cache.cc @@ -1810,7 +1810,7 @@ record_t Cache::prepare_record( if (i->is_exist_clean()) { assert(i->version == 0); - assert(!i->prior_instance); + assert(!i->prior_instance || t.get_src() == transaction_type_t::DEMOTE); // no set_io_wait(), skip complete_commit() assert(!i->is_pending_io()); i->pending_for_transaction = TRANS_ID_NULL; @@ -1821,13 +1821,24 @@ record_t Cache::prepare_record( should_use_no_conflict_publish(t, i->get_type())); } - // exist mutation pending extents must be in t.mutated_block_list - add_extent(i); - const auto t_src = t.get_src(); - if (i->is_stable_dirty()) { - add_to_dirty(i, &t_src); + assert(i->is_logical()); + if (t.get_src() == transaction_type_t::DEMOTE) { + assert(!i->committer); + assert(!i->get_prior_instance()->committer); + i->new_committer(t); + assert(i->committer); + i->get_prior_instance()->committer = i->committer; + auto &committer = *i->committer; + committer.block_trans(t); } else { - touch_extent_fully(*i, &t_src, t.get_cache_hint()); + // exist mutation pending extents must be in t.mutated_block_list + add_extent(i); + const auto t_src = t.get_src(); + if (i->is_stable_dirty()) { + add_to_dirty(i, &t_src); + } else { + touch_extent_fully(*i, &t_src, t.get_cache_hint()); + } } alloc_delta.alloc_blk_ranges.emplace_back( @@ -2103,6 +2114,9 @@ void Cache::complete_commit( } if (i->is_logical()) { committer.maybe_sync_copied_lba_key(); + if (t.get_src() == transaction_type_t::PROMOTE) { + committer.commit_shadow_promote(t); + } } touch_extent_fully(prior, &t_src, t.get_cache_hint()); committer.sync_version(); @@ -2213,6 +2227,31 @@ void Cache::complete_commit( continue; } epm.mark_space_used(i->get_paddr(), i->get_length()); + assert(i->is_logical()); + auto t_src = t.get_src(); + if (t.get_src() == transaction_type_t::DEMOTE) { + assert(i->committer); + auto &committer = *i->committer; + auto &prior = static_cast( + *i->get_prior_instance()); + ceph_assert(prior.is_valid()); + TRACET("committing rewritten extent into " + "existing -- {}, prior={}", + t, *i, prior); + prior.pending_for_transaction = TRANS_ID_NULL; + if (auto shadow = prior.get_shadow(); shadow) { + committer.commit_shadow_demote(t); + prior.reset_shadow(); + } + committer.commit_state(); + committer.sync_checksum(); + committer.commit_and_share_paddr(); + touch_extent_fully(prior, &t_src, t.get_cache_hint()); + committer.sync_version(); + committer.unblock_trans(t); + i->committer.reset(); + prior.committer.reset(); + } } for (auto &i: t.pre_alloc_list) { if (!i->is_valid()) { diff --git a/src/crimson/os/seastore/cache.h b/src/crimson/os/seastore/cache.h index 327f206f6c7..119f71bfc2e 100644 --- a/src/crimson/os/seastore/cache.h +++ b/src/crimson/os/seastore/cache.h @@ -1731,6 +1731,9 @@ public: read_extent_futs, [](auto &fut) { return std::move(fut); }); } + bool is_on_cold_tier(paddr_t paddr) const { + return epm.is_cold_device(paddr.get_device_id()); + } private: void touch_extent_fully( CachedExtent &ext, diff --git a/src/crimson/os/seastore/cached_extent.cc b/src/crimson/os/seastore/cached_extent.cc index d6a230ca775..622a331f2e0 100644 --- a/src/crimson/os/seastore/cached_extent.cc +++ b/src/crimson/os/seastore/cached_extent.cc @@ -557,4 +557,48 @@ void ExtentCommitter::unblock_trans(Transaction &t) { } } +void ExtentCommitter::commit_shadow_demote(Transaction &t) { + LOG_PREFIX(ExtentCommitter::commit_shadow_demote); + assert(t.get_src() == transaction_type_t::DEMOTE); + auto &prior = *extent.prior_instance->template cast(); + auto shadow = prior.get_shadow(); + assert(shadow); + for (auto &trans_view : prior.retired_transactions) { + assert(trans_view.t != nullptr); + auto view_tid = trans_view.t->get_trans_id(); + if (view_tid == t.get_trans_id()) { + continue; + } + TRACET("removing shadow {} from retired_set of t.{}", t, *shadow, view_tid); + [[maybe_unused]] bool removed = + trans_view.t->remove_from_retired_set(*shadow); + assert(removed); + trans_view.t->remove_shadow_from_write_set( + shadow->get_paddr(), shadow->get_length()); + } +} + +void ExtentCommitter::commit_shadow_promote(Transaction &t) { + LOG_PREFIX(ExtentCommitter::commit_shadow_promote); + assert(t.get_src() == transaction_type_t::PROMOTE); + assert(extent.is_logical()); + auto &lprior = static_cast(*extent.prior_instance); + ceph_assert(lprior.get_pin_state() == extent_pin_state_t::Promoting); + auto &lext = static_cast(extent); + auto shadow = lext.get_shadow(); + assert(shadow); + assert(shadow->is_shadow_extent()); + lprior.set_shadow(shadow); + for (auto &trans_view : lprior.retired_transactions) { + assert(trans_view.t != nullptr); + auto view_tid = trans_view.t->get_trans_id(); + if (view_tid == t.get_trans_id()) { + continue; + } + TRACET("adding shadow {} from t.{}", t, *shadow, view_tid); + trans_view.t->add_absent_to_retired_set(shadow); + } + lprior.set_pin_state(extent_pin_state_t::Fresh); +} + } diff --git a/src/crimson/os/seastore/cached_extent.h b/src/crimson/os/seastore/cached_extent.h index 96496f44d44..7115494d167 100644 --- a/src/crimson/os/seastore/cached_extent.h +++ b/src/crimson/os/seastore/cached_extent.h @@ -301,6 +301,8 @@ public: void commit_and_share_paddr(); void maybe_sync_copied_lba_key(); + void commit_shadow_demote(Transaction&); + void commit_shadow_promote(Transaction&); private: // the rewritten extent CachedExtent &extent; diff --git a/src/crimson/os/seastore/lba/btree_lba_manager.cc b/src/crimson/os/seastore/lba/btree_lba_manager.cc index 03cceabbd6d..37a6e91f249 100644 --- a/src/crimson/os/seastore/lba/btree_lba_manager.cc +++ b/src/crimson/os/seastore/lba/btree_lba_manager.cc @@ -966,13 +966,22 @@ BtreeLBAManager::update_mappings( return this->_update_mapping( c.trans, *cursor, - [prev_addr, addr, len, checksum]( + [prev_addr, addr, len, checksum, extent, c]( const lba_map_val_t &in) { lba_map_val_t ret = in; ceph_assert(in.pladdr.is_paddr()); - ceph_assert(in.pladdr.get_paddr() == prev_addr); ceph_assert(in.len == len); - ret.pladdr = addr; + if (likely(in.pladdr.get_paddr() == prev_addr)) { + ret.pladdr = addr; + } else { + // this can only happen when the extent is EXIST_CLEAN + // and is demoted onto the cold tier by a DEMOTE trans. + assert(in.shadow_paddr == P_ADDR_NULL); + assert(extent->is_exist_clean()); + assert(extent->get_paddr() == in.pladdr.get_paddr()); + assert(c.cache.is_on_cold_tier(extent->get_paddr())); + assert(!c.cache.is_on_cold_tier(prev_addr)); + } ret.checksum = checksum; return ret; }, diff --git a/src/crimson/os/seastore/lba/lba_btree_node.h b/src/crimson/os/seastore/lba/lba_btree_node.h index a79950b64c4..49df7813c01 100644 --- a/src/crimson/os/seastore/lba/lba_btree_node.h +++ b/src/crimson/os/seastore/lba/lba_btree_node.h @@ -324,6 +324,7 @@ struct LBALeafNode iterator &iter) { LOG_PREFIX(LBALeafNode::merge_content_to); + SUBTRACET(seastore_lba, "merging with {}", t, pending_version); std::map modified; auto it = pending_version.begin(); while (it != pending_version.end() && iter != this->end()) { @@ -345,14 +346,20 @@ struct LBALeafNode ceph_abort(); } if (is_valid_child_ptr(child)) { - if ((child->_is_mutable() || child->_is_pending_io())) { - // skip the ones that the pending version is also modifying + if (// skip the ones that the pending version is also modifying + (child->_is_mutable() || child->_is_pending_io()) || + // EXIST_CLEAN extents created by DEMOTE transactions also + // updates their paddrs, so they should also be skpped. + (pending_version.t->get_src() == transaction_type_t::DEMOTE)) { + SUBTRACET(seastore_lba, "skipping {}~{}", t, it->get_key(), it->get_val()); it++; continue; } else { assert(child->_is_exist_clean() || child->_is_exist_mutation_pending()); } } + SUBTRACET(seastore_lba, "examing v2: {}~{}, v1: {}~{}", + t, it->get_key(), it->get_val(), iter->get_key(), iter->get_val()); auto pending_key = it->get_key(); auto stable_key = iter->get_key(); auto stable_end = stable_key + v1.len; @@ -362,13 +369,21 @@ struct LBALeafNode if (pending_key != stable_key) { assert(v2.pladdr != v1.pladdr); assert(is_valid_child_ptr(child)); + assert(child->_is_exist_clean()); } if (v2.pladdr != v1.pladdr) { auto m_v2 = v2; auto off = pending_key.get_byte_distance(stable_key); auto paddr = v1.pladdr.get_paddr(); paddr = paddr + off; + SUBTRACET(seastore_lba, "merging to {}, paddr: {} -> {}", + t, pending_version, m_v2.pladdr, paddr); m_v2.pladdr = paddr; + if (v1.shadow_paddr == P_ADDR_NULL) { + m_v2.shadow_paddr = P_ADDR_NULL; + } else { + m_v2.shadow_paddr = (v1.shadow_paddr + off); + } SUBTRACET(seastore_lba, "merging to {}, paddr: {} -> {}", t, pending_version, m_v2.pladdr, paddr); if (!is_valid_child_ptr(child)) { diff --git a/src/crimson/os/seastore/logical_child_node.h b/src/crimson/os/seastore/logical_child_node.h index ea4bb9c6a76..977b96aaf21 100644 --- a/src/crimson/os/seastore/logical_child_node.h +++ b/src/crimson/os/seastore/logical_child_node.h @@ -44,6 +44,20 @@ public: laddr_t get_end() const { return (get_laddr() + get_length()).checked_to_laddr(); } + + TCachedExtentRef get_shadow() const { + return shadow; + } + + void set_shadow(TCachedExtentRef &s) { + assert(!shadow); + shadow = s; + } + + void reset_shadow() { + shadow.reset(); + } + protected: void on_replace_prior(Transaction &t) final { assert(is_seen_by_users()); @@ -56,6 +70,8 @@ protected: void on_data_commit() final { ceph_abort("impossible"); } +private: + TCachedExtentRef shadow; }; using LogicalChildNodeRef = TCachedExtentRef; } // namespace crimson::os::seastore diff --git a/src/crimson/os/seastore/seastore_types.h b/src/crimson/os/seastore/seastore_types.h index f4e11936af1..f27cfb123b2 100644 --- a/src/crimson/os/seastore/seastore_types.h +++ b/src/crimson/os/seastore/seastore_types.h @@ -2757,7 +2757,9 @@ constexpr bool is_background_transaction(transaction_type_t type) { constexpr bool is_rewrite_transaction(transaction_type_t type) { return type == transaction_type_t::TRIM_DIRTY || type == transaction_type_t::CLEANER_MAIN || - type == transaction_type_t::CLEANER_COLD; + type == transaction_type_t::CLEANER_COLD || + type == transaction_type_t::DEMOTE || + type == transaction_type_t::PROMOTE; } constexpr bool is_trim_transaction(transaction_type_t type) { diff --git a/src/crimson/os/seastore/transaction.h b/src/crimson/os/seastore/transaction.h index 3f5ff0fa75a..ed1af43bd94 100644 --- a/src/crimson/os/seastore/transaction.h +++ b/src/crimson/os/seastore/transaction.h @@ -364,6 +364,21 @@ public: } } + bool remove_from_retired_set(CachedExtent &ext) { + auto it = retired_set.find(ext.get_paddr()); + if (it == retired_set.end()) { + return false; + } + auto &extent = it->extent; + if (extent->get_paddr() != ext.get_paddr()) { + return false; + } else { + assert(ext.get_length() == extent->get_length()); + retired_set.erase(it); + return true; + } + } + std::pair pre_stable_extent_paddr_mod( read_set_item_t &item) { @@ -432,6 +447,24 @@ public: write_set.insert(mextent); } } + void remove_shadow_from_write_set( + const paddr_t &shadow_paddr, extent_len_t len) { + std::vector exts; + for (auto [bottom, top] = write_set.get_overlap(shadow_paddr, len); + bottom != top; + bottom++) { + auto &mextent = *bottom; + if (mextent.is_initial_pending()) { + assert(!mextent.is_shadow_extent()); + continue; + } + assert(mextent.is_shadow_extent() && mextent.is_exist_clean()); + exts.emplace_back(&mextent); + } + for (auto i :exts) { + write_set.erase(*i); + } + } template auto for_each_finalized_fresh_block(F &&f) const { diff --git a/src/crimson/os/seastore/transaction_manager.cc b/src/crimson/os/seastore/transaction_manager.cc index 851b9883461..d32d753ee38 100644 --- a/src/crimson/os/seastore/transaction_manager.cc +++ b/src/crimson/os/seastore/transaction_manager.cc @@ -259,13 +259,14 @@ TransactionManager::ref_ret TransactionManager::remove( auto laddr = ref->get_laddr(); cache->retire_absent_extent_addr_by_type( t, laddr, shadow_addr, length, ref->get_type(), - [laddr](auto &extent) { + [ref, laddr](auto &extent) { auto lextent = extent.template cast(); assert(extent.is_logical()); assert(!lextent->has_laddr()); assert(!extent.has_been_invalidated()); lextent->set_laddr(laddr); extent.set_shadow_extent(true); + ref->set_shadow(lextent); }); } } @@ -332,11 +333,32 @@ TransactionManager::_remove( LogicalChildNode >(); ceph_assert(extent); - cache->retire_extent(t, std::move(extent)); + cache->retire_extent(t, extent); + if (mapping.has_shadow_val()) { + if (auto shadow = extent->get_shadow(); shadow) { + cache->retire_extent(t, shadow); + } else { + auto laddr = mapping.get_intermediate_base(); + std::ignore = cache->retire_absent_extent_addr_by_type( + t, laddr, + mapping.get_shadow_val(), + mapping.get_intermediate_length(), + mapping.get_extent_type(), + [extent, laddr](auto &ext) { + auto lextent = ext.template cast(); + assert(ext.is_logical()); + assert(!lextent->has_laddr()); + assert(!ext.has_been_invalidated()); + lextent->set_laddr(laddr); + ext.set_shadow_extent(true); + extent->set_shadow(lextent); + }); + } + } } else { auto &child_pos = maybe_mapped_extent.get_child_pos(); auto laddr = mapping.get_intermediate_base(); - std::ignore = cache->retire_absent_extent_addr_by_type( + auto ext = cache->retire_absent_extent_addr_by_type( t, laddr, mapping.get_val(), mapping.get_intermediate_length(), @@ -349,13 +371,23 @@ TransactionManager::_remove( child_pos.link_child(lextent.get()); lextent->set_laddr(laddr); } - ); - } - if (mapping.has_shadow_val()) { - cache->retire_absent_extent_addr( - t, mapping.get_intermediate_base(), - mapping.get_shadow_val(), - mapping.get_intermediate_length()); + )->template cast(); + if (mapping.has_shadow_val()) { + std::ignore = cache->retire_absent_extent_addr_by_type( + t, mapping.get_intermediate_base(), + mapping.get_shadow_val(), + mapping.get_intermediate_length(), + mapping.get_extent_type(), + [laddr, ext](auto &extent) { + auto lextent = extent.template cast(); + assert(extent.is_logical()); + assert(!lextent->has_laddr()); + assert(!extent.has_been_invalidated()); + lextent->set_laddr(laddr); + extent.set_shadow_extent(true); + ext->set_shadow(lextent); + }); + } } } @@ -465,7 +497,7 @@ TransactionManager::refs_ret TransactionManager::remove( base_iertr::future TransactionManager::relocate_logical_extent( - Transaction &t, LBAMapping mapping) + Transaction &t, LBAMapping mapping, laddr_t new_laddr) { LOG_PREFIX(TransactionManager::relocate_logical_extent); SUBDEBUGT(seastore_tm, "relocate {}", t, mapping); @@ -476,7 +508,7 @@ TransactionManager::relocate_logical_extent( if (!v.has_child()) { auto &child_pos = v.get_child_pos(); auto laddr = mapping.get_key(); - std::ignore = cache->retire_absent_extent_addr_by_type( + auto extent = cache->retire_absent_extent_addr_by_type( t, laddr, mapping.get_val(), @@ -490,29 +522,53 @@ TransactionManager::relocate_logical_extent( child_pos.link_child(lextent.get()); lextent->set_laddr(laddr); } - ); - co_return cache->alloc_remapped_extent_by_type( - t, mapping.get_extent_type(), mapping.get_key(), - mapping.get_val(), 0, mapping.get_length(), std::nullopt )->cast(); - } - - auto extent = co_await v.get_child_fut().si_then([](auto ext) { - return ext; - }); + if (mapping.has_shadow_val()) { + std::ignore = cache->retire_absent_extent_addr_by_type( + t, laddr, + mapping.get_shadow_val(), + mapping.get_intermediate_length(), + mapping.get_extent_type(), + [extent, laddr](auto &ext) { + auto lextent = ext.template cast(); + assert(ext.is_logical()); + assert(!lextent->has_laddr()); + assert(!ext.has_been_invalidated()); + lextent->set_laddr(laddr); + ext.set_shadow_extent(true); + extent->set_shadow(lextent); + }); + } + } else { + auto extent = co_await v.get_child_fut_as(); - if (extent->is_stable()) { - cache->retire_extent(t, extent); - co_return cache->alloc_remapped_extent_by_type( - t, mapping.get_extent_type(), mapping.get_key(), - mapping.get_val(), 0, mapping.get_length(), std::nullopt + if (extent->is_stable()) { + cache->retire_extent(t, extent); + } else { + //TODO: relocating logical extents doesn't support + // mutation pending extents yet. + assert(extent->is_initial_pending() || extent->is_exist_clean()); + extent->set_laddr(new_laddr); + if (mapping.has_shadow_val()) { + assert(extent->get_shadow()); + extent->get_shadow()->set_laddr(new_laddr); + } + co_return extent; + } + } + auto remapped_extent = cache->alloc_remapped_extent_by_type( + t, mapping.get_extent_type(), new_laddr, + mapping.get_val(), 0, mapping.get_length(), std::nullopt + )->cast(); + if (mapping.has_shadow_val()) { + auto remapped_shadow = cache->alloc_remapped_extent_by_type( + t, mapping.get_extent_type(), new_laddr, + mapping.get_shadow_val(), 0, mapping.get_length(), std::nullopt )->cast(); - } else { - //TODO: relocating logical extents doesn't support - // mutation pending extents yet. - assert(extent->is_initial_pending() || extent->is_exist_clean()); - co_return extent; + remapped_shadow->set_shadow_extent(true); + remapped_extent->set_shadow(remapped_shadow); } + co_return remapped_extent; } base_iertr::future @@ -525,8 +581,9 @@ TransactionManager::relocate_shadow_extent( assert(!mapping.is_zero_reserved()); assert(mapping.is_viewable()); assert(!mapping.is_indirect()); + assert(t.get_src() == transaction_type_t::DEMOTE); auto v = get_extent_if_linked(t, *mapping.direct_cursor); - CachedExtentRef extent; + LogicalChildNodeRef extent; auto laddr = mapping.get_intermediate_base(); if (!v.has_child()) { auto &child_pos = v.get_child_pos(); @@ -544,26 +601,35 @@ TransactionManager::relocate_shadow_extent( child_pos.link_child(lextent.get()); lextent->set_laddr(laddr); } - ); + )->template cast(); } else { - auto extent = co_await std::move(v.get_child_fut()); + extent = co_await std::move(v.get_child_fut()); cache->retire_extent(t, extent); } - auto shadow_paddr = mapping.get_shadow_val(); - std::ignore = cache->retire_absent_extent_addr_by_type( - t, laddr, shadow_paddr, mapping.get_length(), mapping.get_extent_type(), - [laddr](auto &ext) { - auto lextent = ext.template cast(); - assert(ext.is_logical()); - assert(!lextent->has_laddr()); - assert(!ext.has_been_invalidated()); - lextent->set_laddr(laddr); - } - ); - co_return cache->alloc_remapped_extent_by_type( + if (auto shadow = extent->get_shadow(); shadow) { + cache->retire_extent(t, shadow); + } else { + auto shadow_paddr = mapping.get_shadow_val(); + std::ignore = cache->retire_absent_extent_addr_by_type( + t, laddr, shadow_paddr, mapping.get_length(), mapping.get_extent_type(), + [laddr, extent](auto &ext) { + auto lextent = ext.template cast(); + assert(ext.is_logical()); + assert(!lextent->has_laddr()); + assert(!ext.has_been_invalidated()); + lextent->set_laddr(laddr); + ext.set_shadow_extent(true); + extent->set_shadow(lextent); + } + ); + } + auto nextent = cache->alloc_remapped_extent_by_type( t, mapping.get_extent_type(), laddr, mapping.get_shadow_val(), 0, mapping.get_length(), std::nullopt )->cast(); + nextent->set_prior_instance(extent); + nextent->set_last_committed_crc(extent->get_last_committed_crc()); + co_return nextent; } TransactionManager::submit_transaction_iertr::future<> @@ -1141,9 +1207,9 @@ TransactionManager::move_region( dst = co_await dst.refresh(); } } else if (!src.is_zero_reserved()) { - auto extent = co_await relocate_logical_extent(t, src); auto laddr = calc_dst_key(); - extent->set_laddr(laddr); + auto extent = co_await relocate_logical_extent(t, src, laddr); + assert(extent->get_laddr() == laddr); auto ret = co_await lba_manager->move_direct_mapping( t, src.get_effective_cursor_ref(), laddr, dst.get_effective_cursor_ref(), *extent); @@ -1247,6 +1313,8 @@ TransactionManager::promote_extent( slice_length, std::nullopt); remapped_cold_extent->set_shadow_extent(true); + auto lremapped = remapped_cold_extent->template cast(); + lext->set_shadow(lremapped); offset += slice_length; } @@ -1290,8 +1358,8 @@ TransactionManager::promote_extent( orig_ext->get_length(), std::nullopt); remapped_cold_extent->set_shadow_extent(true); - - remapped_cold_extent->set_shadow_extent(true); + auto lremapped = remapped_cold_extent->template cast(); + lext->set_shadow(lremapped); } auto cursor = co_await lba_manager->get_cursor( diff --git a/src/crimson/os/seastore/transaction_manager.h b/src/crimson/os/seastore/transaction_manager.h index 0d99e31dd0a..5edc797840d 100644 --- a/src/crimson/os/seastore/transaction_manager.h +++ b/src/crimson/os/seastore/transaction_manager.h @@ -113,7 +113,8 @@ public: */ base_iertr::future relocate_logical_extent( Transaction &t, - LBAMapping mapping); + LBAMapping mapping, + laddr_t new_laddr); base_iertr::future relocate_shadow_extent( Transaction &t, @@ -1546,7 +1547,7 @@ private: SUBTRACET(seastore_tm, "retire extent place holder...", t); auto &child_pos = ret.get_child_pos(); auto laddr = pin.get_key(); - std::ignore = cache->retire_absent_extent_addr_by_type( + auto ext = cache->retire_absent_extent_addr_by_type( t, laddr, pin.get_val(), original_len, pin.get_extent_type(), [&child_pos, laddr](auto &extent) mutable { auto lextent = extent.template cast(); @@ -1556,17 +1557,19 @@ private: child_pos.link_child(lextent.get()); lextent->set_laddr(laddr); } - ); + )->template cast(); if (pin.has_shadow_val()) { cache->retire_absent_extent_addr_by_type( t, pin.get_key(), pin.get_shadow_val(), original_len, pin.get_extent_type(), - [laddr](auto &extent) { + [laddr, ext](auto &extent) { auto lextent = extent.template cast(); assert(extent.is_logical()); assert(!lextent->has_laddr()); assert(!extent.has_been_invalidated()); lextent->set_laddr(laddr); + extent.set_shadow_extent(true); + ext->set_shadow(lextent); } ); } @@ -1594,6 +1597,26 @@ private: SUBTRACET(seastore_tm, "retire extent...", t); assert(extent->is_seen_by_users()); cache->retire_extent(t, extent); + if (pin.has_shadow_val()) { + if (auto shadow = extent->get_shadow()) { + cache->retire_extent(t, shadow); + } else { + auto laddr = pin.get_key(); + cache->retire_absent_extent_addr_by_type( + t, laddr, pin.get_shadow_val(), + original_len, pin.get_extent_type(), + [laddr, extent](auto &ext) { + auto lextent = ext.template cast(); + assert(ext.is_logical()); + assert(!lextent->has_laddr()); + assert(!ext.has_been_invalidated()); + lextent->set_laddr(laddr); + ext.set_shadow_extent(true); + extent->set_shadow(lextent); + } + ); + } + } } for (auto &remap : remaps) { auto remap_offset = remap.offset; @@ -1629,6 +1652,10 @@ private: remap_len, std::nullopt); cold_ext->set_shadow_extent(true); + auto &lremapped = static_cast< + LogicalChildNode&>(*remapped_extent); + auto lcold_ext = cold_ext->template cast(); + lremapped.set_shadow(lcold_ext); } // user must initialize the logical extent themselves. remapped_extent->set_seen_by_users();