From: Zhang Song Date: Wed, 3 Sep 2025 08:02:29 +0000 (+0800) Subject: crimson/os/seastore: implement demote region X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c5d0570e679931fa445d28cc25e54e8266b7d46f;p=ceph-ci.git crimson/os/seastore: implement demote region Signed-off-by: Zhang Song Signed-off-by: Xuehan Xu --- diff --git a/src/crimson/os/seastore/extent_placement_manager.h b/src/crimson/os/seastore/extent_placement_manager.h index aba38a43e1a..2a48510a17f 100644 --- a/src/crimson/os/seastore/extent_placement_manager.h +++ b/src/crimson/os/seastore/extent_placement_manager.h @@ -179,7 +179,9 @@ public: if (!extent->is_stable_dirty()) { return false; } - assert(t.get_src() == transaction_type_t::TRIM_DIRTY); + assert((t.get_src() == transaction_type_t::TRIM_DIRTY) || + (t.get_src() == transaction_type_t::DEMOTE) || + (t.get_src() == transaction_type_t::PROMOTE)); ceph_assert_always(is_root_type(extent->get_type()) || extent->get_paddr().is_absolute()); return crimson::os::seastore::can_inplace_rewrite(extent->get_type()); @@ -616,6 +618,10 @@ public: return !devices_by_id[addr.get_device_id()]->is_end_to_end_data_protection(); } + rewrite_gen_t get_max_hot_gen() const { + return hot_tier_generations - 1; + } + private: rewrite_gen_t adjust_generation( data_category_t category, diff --git a/src/crimson/os/seastore/lba/btree_lba_manager.cc b/src/crimson/os/seastore/lba/btree_lba_manager.cc index 31aaa659736..bf85eaf0862 100644 --- a/src/crimson/os/seastore/lba/btree_lba_manager.cc +++ b/src/crimson/os/seastore/lba/btree_lba_manager.cc @@ -269,6 +269,22 @@ BtreeLBAManager::lower_bound( co_return iter.get_cursor(c); } +BtreeLBAManager::upper_bound_right_ret +BtreeLBAManager::upper_bound_right( + Transaction &t, + laddr_t laddr) +{ + auto c = get_context(t); + auto btree = co_await get_btree(c); + auto iter = co_await btree.upper_bound_right(c, laddr); + if (iter.is_end()) { + co_await upper_bound_right_iertr::future( + crimson::ct_error::enoent::make()); + } + assert(iter.get_key() >= laddr); + co_return iter.get_cursor(c); +} + BtreeLBAManager::promote_extent_ret BtreeLBAManager::promote_extent( Transaction &t, @@ -320,6 +336,34 @@ BtreeLBAManager::promote_extent( } co_return; } +BtreeLBAManager::demote_extent_ret +BtreeLBAManager::demote_extent( + Transaction &t, + LBACursor &cursor, + LogicalChildNode &extent) +{ + assert(cursor.is_viewable()); + assert(!cursor.is_end()); + assert(!cursor.is_indirect()); + assert(cursor.has_shadow_paddr()); + auto c = get_context(t); + auto btree = co_await get_btree(c); + auto ret = co_await _update_mapping( + t, + cursor, + [&extent](lba_map_val_t val) { + assert(val.pladdr.is_paddr()); + assert(val.shadow_paddr == extent.get_paddr()); + val.pladdr = pladdr_t(val.shadow_paddr); + val.shadow_paddr = P_ADDR_NULL; + return val; + }, + &extent + ).handle_error_interruptible( + demote_extent_iertr::pass_further{}, + crimson::ct_error::assert_all("unexpected enoent")); + co_return ret; +} BtreeLBAManager::alloc_extent_ret BtreeLBAManager::reserve_region( diff --git a/src/crimson/os/seastore/lba/btree_lba_manager.h b/src/crimson/os/seastore/lba/btree_lba_manager.h index cee8f46bf97..f8c6d25f59f 100644 --- a/src/crimson/os/seastore/lba/btree_lba_manager.h +++ b/src/crimson/os/seastore/lba/btree_lba_manager.h @@ -79,11 +79,20 @@ public: Transaction &t, laddr_t laddr) final; + upper_bound_right_ret upper_bound_right( + Transaction &t, + laddr_t laddr) final; + promote_extent_ret promote_extent( Transaction &t, LBACursor &cursor, std::vector extents) final; + demote_extent_ret demote_extent( + Transaction &t, + LBACursor &cursor, + LogicalChildNode &extent) final; + alloc_extent_ret reserve_region( Transaction &t, LBACursorRef pos, diff --git a/src/crimson/os/seastore/lba_manager.h b/src/crimson/os/seastore/lba_manager.h index 59f6f251176..39ddbed6c0d 100644 --- a/src/crimson/os/seastore/lba_manager.h +++ b/src/crimson/os/seastore/lba_manager.h @@ -60,6 +60,13 @@ public: Transaction &t, laddr_t laddr) = 0; + using upper_bound_right_iertr = base_iertr::extend< + crimson::ct_error::enoent>; + using upper_bound_right_ret = upper_bound_right_iertr::future; + virtual upper_bound_right_ret upper_bound_right( + Transaction &t, + laddr_t laddr) = 0; + #ifdef UNIT_TESTS_BUILT using get_end_mapping_iertr = base_iertr; using get_end_mapping_ret = get_end_mapping_iertr::future; @@ -174,6 +181,13 @@ public: LBACursor &cursor, std::vector extents) = 0; + using demote_extent_iertr = base_iertr; + using demote_extent_ret = demote_extent_iertr::future; + virtual demote_extent_ret demote_extent( + Transaction &t, + LBACursor &cursor, + LogicalChildNode &extent) = 0; + virtual alloc_extent_ret reserve_region( Transaction &t, laddr_hint_t hint, diff --git a/src/crimson/os/seastore/transaction_manager.cc b/src/crimson/os/seastore/transaction_manager.cc index fc79c523d69..6a853f6c14f 100644 --- a/src/crimson/os/seastore/transaction_manager.cc +++ b/src/crimson/os/seastore/transaction_manager.cc @@ -502,6 +502,57 @@ TransactionManager::relocate_logical_extent( } } +base_iertr::future +TransactionManager::relocate_shadow_extent( + Transaction &t, LBAMapping mapping) +{ + LOG_PREFIX(TransactionManager::relocate_shadow_extent); + SUBDEBUGT(seastore_tm, "relocate {}", t, mapping); + assert(mapping.has_shadow_val()); + assert(!mapping.is_zero_reserved()); + assert(mapping.is_viewable()); + assert(!mapping.is_indirect()); + auto v = get_extent_if_linked(t, *mapping.direct_cursor); + CachedExtentRef extent; + auto laddr = mapping.get_intermediate_base(); + if (!v.has_child()) { + auto &child_pos = v.get_child_pos(); + extent = cache->retire_absent_extent_addr_by_type( + t, + laddr, + mapping.get_val(), + mapping.get_length(), + mapping.get_extent_type(), + [laddr, &child_pos](auto &extent) { + auto lextent = extent.template cast(); + assert(extent.is_logical()); + assert(!lextent->has_laddr()); + assert(!extent.has_been_invalidated()); + child_pos.link_child(lextent.get()); + lextent->set_laddr(laddr); + } + ); + } else { + auto 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( + t, mapping.get_extent_type(), laddr, + mapping.get_shadow_val(), 0, mapping.get_length(), std::nullopt + )->cast(); +} + TransactionManager::submit_transaction_iertr::future<> TransactionManager::submit_transaction( Transaction &t) @@ -1182,9 +1233,49 @@ TransactionManager::demote_region( laddr_t start, loffset_t max_proceed_size) { - // TODO - return demote_region_iertr::make_ready_future( - demote_region_res_t{0, false}); + LOG_PREFIX(TransactionManager::demote_region); + auto prefix = start.get_object_prefix(); + DEBUGT("start demote {}", t, prefix); + auto cursor = co_await lba_manager->upper_bound_right( + t, start + ).handle_error_interruptible( + demote_region_iertr::pass_further{}, + crimson::ct_error::assert_all("unexpected enoent")); + auto it = co_await resolve_cursor_to_mapping(t, std::move(cursor)); + demote_region_res_t ret{0, 0, false}; + while ((ret.demoted_size + ret.evicted_size) < max_proceed_size) { + if (it.is_end() || it.get_key().get_object_prefix() != prefix) { + ret.complete = true; + break; + } + if (it.is_indirect()) { + it = co_await it.next(); + continue; + } + if (it.has_shadow_val()) { + DEBUGT("demote shadow {}", t, it); + auto extent = co_await relocate_shadow_extent(t, it); + ret.demoted_size += extent->get_length(); + auto cursor = co_await lba_manager->demote_extent( + t, *it.direct_cursor, *extent); + auto nit = co_await resolve_cursor_to_mapping(t, std::move(cursor)); + it = co_await nit.next(); + } else if (!it.is_indirect() && !it.is_zero_reserved() && + !epm->is_cold_device(it.get_val().get_device_id())) { + DEBUGT("demote hot {}", t, it); + auto extent = co_await read_cursor_by_type( + t, it.direct_cursor, it.get_extent_type()); + ret.evicted_size += extent->get_length(); + extent->set_target_rewrite_generation(epm->get_max_hot_gen() + 1); + co_await rewrite_logical_extent(t, extent); + it = co_await it.next(); + } else { + DEBUGT("skip {}", t, it); + it = co_await it.next(); + } + } + + co_return ret; } TransactionManager::get_extents_if_live_ret diff --git a/src/crimson/os/seastore/transaction_manager.h b/src/crimson/os/seastore/transaction_manager.h index 17c5029ea7e..c21bebd23d1 100644 --- a/src/crimson/os/seastore/transaction_manager.h +++ b/src/crimson/os/seastore/transaction_manager.h @@ -114,6 +114,10 @@ public: Transaction &t, LBAMapping mapping); + base_iertr::future relocate_shadow_extent( + Transaction &t, + LBAMapping mapping); + /** * get_pin *