From 75201477eb53f9eda6d03e2800a22d8a23cdfef2 Mon Sep 17 00:00:00 2001 From: Xuehan Xu Date: Wed, 3 Jun 2026 17:36:42 +0800 Subject: [PATCH] crimson/os/seastore/lba,TM: remove shadows when trimming dirty non-data extents Signed-off-by: Xuehan Xu --- src/crimson/os/seastore/async_cleaner.cc | 5 ++- src/crimson/os/seastore/async_cleaner.h | 12 +++++++ .../os/seastore/lba/btree_lba_manager.cc | 5 +++ src/crimson/os/seastore/transaction_manager.h | 36 +++++++++++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/crimson/os/seastore/async_cleaner.cc b/src/crimson/os/seastore/async_cleaner.cc index 9d515e13cd9..7ccf710d9e2 100644 --- a/src/crimson/os/seastore/async_cleaner.cc +++ b/src/crimson/os/seastore/async_cleaner.cc @@ -717,8 +717,11 @@ JournalTrimmerImpl::trim_dirty() return trans_intr::do_for_each( dirty_list, [this, &t](auto &e) { - return extent_callback->rewrite_extent( + return extent_callback->maybe_remove_shadow(t, *e + ).si_then([this, &t, e] { + return extent_callback->rewrite_extent( t, e, INIT_GENERATION, NULL_TIME); + }); }); }); }).si_then([this, &t] { diff --git a/src/crimson/os/seastore/async_cleaner.h b/src/crimson/os/seastore/async_cleaner.h index 647e0b233b3..9751dc15eea 100644 --- a/src/crimson/os/seastore/async_cleaner.h +++ b/src/crimson/os/seastore/async_cleaner.h @@ -398,6 +398,18 @@ public: laddr_t prefix, std::size_t max_proceed_size) = 0; + /** + * maybe_remove_shadow + * + * Remove the shadow of the extent if it exists + */ + using maybe_remove_shadow_iertr = base_iertr; + using maybe_remove_shadow_ret = + maybe_remove_shadow_iertr::future<>; + virtual maybe_remove_shadow_ret maybe_remove_shadow( + Transaction &t, + CachedExtent &e) = 0; + /** * get_extents_if_live * diff --git a/src/crimson/os/seastore/lba/btree_lba_manager.cc b/src/crimson/os/seastore/lba/btree_lba_manager.cc index 37a6e91f249..758e32fff45 100644 --- a/src/crimson/os/seastore/lba/btree_lba_manager.cc +++ b/src/crimson/os/seastore/lba/btree_lba_manager.cc @@ -973,6 +973,11 @@ BtreeLBAManager::update_mappings( ceph_assert(in.len == len); if (likely(in.pladdr.get_paddr() == prev_addr)) { ret.pladdr = addr; + if (c.trans.get_src() == transaction_type_t::TRIM_DIRTY) { + // This is a dirty onode/omap extent that are rewritten, + // the shadow extent should be removed. + ret.shadow_paddr = P_ADDR_NULL; + } } else { // this can only happen when the extent is EXIST_CLEAN // and is demoted onto the cold tier by a DEMOTE trans. diff --git a/src/crimson/os/seastore/transaction_manager.h b/src/crimson/os/seastore/transaction_manager.h index 5edc797840d..702e1ae253f 100644 --- a/src/crimson/os/seastore/transaction_manager.h +++ b/src/crimson/os/seastore/transaction_manager.h @@ -993,6 +993,42 @@ public: laddr_t start, std::size_t max_proceed_size) final; + maybe_remove_shadow_ret maybe_remove_shadow( + Transaction &t, + CachedExtent &e) { + if (!e.is_logical()) { + co_return; + } + auto &extent = static_cast(e); + auto cursor = co_await lba_manager->get_cursor(t, extent + ).handle_error_interruptible( + crimson::ct_error::input_output_error::pass_further{}, + crimson::ct_error::enoent::assert_failure{} + ); + if (cursor->has_shadow_paddr()) { + if (auto shadow = extent.get_shadow(); shadow) { + cache->retire_extent(t, shadow); + } else { + auto laddr = cursor->get_laddr(); + std::ignore = cache->retire_absent_extent_addr_by_type( + t, laddr, + cursor->get_shadow_paddr(), + cursor->get_length(), + cursor->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); + } + ); + } + } + } + using ExtentCallbackInterface::get_extents_if_live_ret; get_extents_if_live_ret get_extents_if_live( Transaction &t, -- 2.47.3