From: Xuehan Xu Date: Tue, 26 Aug 2025 06:28:55 +0000 (+0800) Subject: crimson/os/seastore: add "move_mapping" to TransactionManager and LBAManager X-Git-Tag: v21.0.1~152^2~12 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=e604b4f189569db04d63614a51b981fbf34f1675;p=ceph.git crimson/os/seastore: add "move_mapping" to TransactionManager and LBAManager Signed-off-by: Xuehan Xu --- diff --git a/src/crimson/os/seastore/cache.h b/src/crimson/os/seastore/cache.h index 9d289c1672c..bcf15a3fda7 100644 --- a/src/crimson/os/seastore/cache.h +++ b/src/crimson/os/seastore/cache.h @@ -1216,20 +1216,15 @@ public: Transaction &t, laddr_t remap_laddr, paddr_t remap_paddr, + extent_len_t remap_offset, extent_len_t remap_length, - laddr_t original_laddr, - std::optional &original_bptr) { + const std::optional &original_bptr) { LOG_PREFIX(Cache::alloc_remapped_extent); - assert(remap_laddr >= original_laddr); TCachedExtentRef ext; if (original_bptr.has_value()) { // shallow copy the buffer from original extent - auto remap_offset = remap_laddr.get_byte_distance< - extent_len_t>(original_laddr); - auto nbp = ceph::bufferptr(buffer::create_page_aligned(remap_length)); original_bptr->copy_out(remap_offset, remap_length, nbp.c_str()); - // ExtentPlacementManager::alloc_new_extent will make a new // (relative/temp) paddr, so make extent directly ext = CachedExtent::make_cached_extent_ref(std::move(nbp)); diff --git a/src/crimson/os/seastore/lba/btree_lba_manager.cc b/src/crimson/os/seastore/lba/btree_lba_manager.cc index d2c35cfeb40..019684a350f 100644 --- a/src/crimson/os/seastore/lba/btree_lba_manager.cc +++ b/src/crimson/os/seastore/lba/btree_lba_manager.cc @@ -1097,4 +1097,132 @@ BtreeLBAManager::remap_mappings( co_return ret; } +BtreeLBAManager::move_mapping_ret +BtreeLBAManager::_copy_mapping( + op_context_t c, + LBABtree &btree, + LBACursorRef src, + laddr_t dest_laddr, + LBACursorRef dest, + LogicalChildNode *extent) +{ + LOG_PREFIX(BtreeLBAManager::_copy_mapping); + assert(src && dest); + assert(dest->is_viewable()); + assert(src->is_viewable()); + assert(!src->is_end()); + assert(src->get_refcount() == EXTENT_DEFAULT_REF_COUNT); + assert(!src->is_indirect() == (bool)extent); + DEBUGT("src={} dest={}", c.trans, *src, *dest); + move_mapping_ret_t ret{std::move(src), std::move(dest)}; + auto &cursor = *ret.dest; + auto iter = btree.make_partial_iter(c, cursor); + if (!iter.is_end()) { + assert(iter.get_key() >= dest_laddr + ret.src->get_length()); + } + // insert the src mapping to dest + // attach extent to the new mapping if it exists + pladdr_t addr; + if (ret.src->is_indirect()) { + addr = ret.src->get_intermediate_key().get_local_clone_id(); + } else { + addr = ret.src->get_paddr(); + } + auto [niter, inserted] = co_await btree.insert( + c, + std::move(iter), + dest_laddr, + lba_map_val_t{ + ret.src->get_length(), + std::move(addr), + EXTENT_DEFAULT_REF_COUNT, + ret.src->is_indirect() ? 0 : ret.src->get_checksum(), + ret.src->get_extent_type()}, + extent ? extent : get_reserved_ptr()); + ceph_assert(inserted); + ret.dest = niter.get_cursor(c); + co_await ret.src->refresh(); + co_return ret; +} + +BtreeLBAManager::move_mapping_ret +BtreeLBAManager::_move_mapping( + Transaction &t, + LBACursorRef src, + laddr_t dest_laddr, + LBACursorRef dest, + LogicalChildNode *extent) { + LOG_PREFIX(BtreeLBAManager::_move_mapping); + assert(src && dest); + assert(dest->is_viewable()); + assert(src->is_viewable()); + assert(!src->is_end()); + assert(src->get_refcount() == EXTENT_DEFAULT_REF_COUNT); + DEBUGT("src={} dest={}", t, *src, *dest); + auto c = get_context(t); + auto btree = co_await get_btree(cache, c); + auto ret = co_await _copy_mapping( + c, btree, std::move(src), dest_laddr, std::move(dest), extent); + + ret.src = co_await update_mapping_refcount( + c.trans, ret.src, -1 + ).handle_error_interruptible( + move_mapping_iertr::pass_further{}, + crimson::ct_error::assert_all{"unexpected error"}); + + co_await ret.dest->refresh(); + auto iter = btree.make_partial_iter(c, *ret.dest); + iter = co_await iter.next(c); + ret.dest = iter.get_cursor(c); + + co_return ret; +} + +BtreeLBAManager::move_mapping_ret +BtreeLBAManager::move_and_clone_direct_mapping( + Transaction &t, + LBACursorRef src, + laddr_t dest_laddr, + LBACursorRef dest, + LogicalChildNode &extent) +{ + LOG_PREFIX(BtreeLBAManager::move_and_clone_direct_mapping); + assert(src && dest); + assert(dest->is_viewable()); + assert(src->is_viewable()); + assert(!src->is_indirect()); + assert(!src->is_end()); + assert(src->get_refcount() == EXTENT_DEFAULT_REF_COUNT); + DEBUGT("src={} dest={}", t, *src, *dest); + auto c = get_context(t); + auto btree = co_await get_btree(cache, c); + auto ret = co_await _copy_mapping( + c, btree, std::move(src), dest_laddr, std::move(dest), &extent); + + // turn the src mapping into an indirect one pointing to + // the previously inserted mapping + auto cursor = co_await _update_mapping( + c.trans, + *ret.src, + [&ret](const auto &in) { + lba_map_val_t val = in; + val.pladdr = ret.dest->get_key().get_local_clone_id(); + val.checksum = 0; + return val; + }, + nullptr + ).handle_error_interruptible( + move_mapping_iertr::pass_further{}, + crimson::ct_error::assert_all{"unexpected error"}); + + assert(cursor->is_indirect()); + auto iter = btree.make_partial_iter(c, *cursor); + DEBUGT("resetting child ptr, leaf: {}, pos: {}", + t, *iter.get_leaf_node(), iter.get_leaf_pos()); + iter.get_leaf_node()->reset_child_ptr(iter.get_leaf_pos()); + ret.src = std::move(cursor); + co_await ret.dest->refresh(); + co_return ret; +} + } diff --git a/src/crimson/os/seastore/lba/btree_lba_manager.h b/src/crimson/os/seastore/lba/btree_lba_manager.h index 04628f7ee26..04944968ea5 100644 --- a/src/crimson/os/seastore/lba/btree_lba_manager.h +++ b/src/crimson/os/seastore/lba/btree_lba_manager.h @@ -105,6 +105,34 @@ public: extent_len_t len, bool updateref) final; + move_mapping_ret move_indirect_mapping( + Transaction &t, + LBACursorRef src, + laddr_t dest_laddr, + LBACursorRef dest) final { + assert(src->is_indirect()); + return _move_mapping( + t, std::move(src), dest_laddr, std::move(dest), nullptr); + } + + move_mapping_ret move_direct_mapping( + Transaction &t, + LBACursorRef src, + laddr_t dest_laddr, + LBACursorRef dest, + LogicalChildNode &extent) final { + assert(!src->is_indirect()); + return _move_mapping( + t, std::move(src), dest_laddr, std::move(dest), &extent); + } + + move_mapping_ret move_and_clone_direct_mapping( + Transaction &t, + LBACursorRef src, + laddr_t dest_laddr, + LBACursorRef dest, + LogicalChildNode &extent) final; + #ifdef UNIT_TESTS_BUILT get_end_mapping_ret get_end_mapping(Transaction &t) final; #endif @@ -324,6 +352,37 @@ private: seastar::metrics::metric_group metrics; void register_metrics(store_index_t store_index); + /* + * _move_mapping + * + * copy the mapping "src" to "dest" and remove the "src" mapping. + * + * Return: the mappings next to "src" and the "dest" mapping + */ + move_mapping_ret _move_mapping( + Transaction &t, + LBACursorRef src, + laddr_t dest_laddr, + LBACursorRef dest, + LogicalChildNode *extent); + + /* + * _copy_mapping + * + * copy the mapping "src" to "dest", the extent attached to + * "src" will also be attached to the dest. This is the building + * block for _move_mapping and move_and_clone_direct_mapping + * + * Return: the "src" and the new "dest" + */ + move_mapping_ret _copy_mapping( + op_context_t c, + LBABtree &btree, + LBACursorRef src, + laddr_t dest_laddr, + LBACursorRef dest, + LogicalChildNode *extent); + /** * _update_mapping * diff --git a/src/crimson/os/seastore/lba_manager.h b/src/crimson/os/seastore/lba_manager.h index a0e4dcec518..3e3d1d9f852 100644 --- a/src/crimson/os/seastore/lba_manager.h +++ b/src/crimson/os/seastore/lba_manager.h @@ -114,6 +114,54 @@ public: // direct mapping ) = 0; + struct move_mapping_ret_t { + LBACursorRef src; + LBACursorRef dest; + }; + /* + * move_and_clone_direct_mapping + * + * move the direct mapping "src" to "dest" and clone it at the + * position of "src". + * + * Return: the new indirect mapping and the moved direct mapping + */ + using move_mapping_iertr = alloc_extent_iertr; + using move_mapping_ret = move_mapping_iertr::future; + virtual move_mapping_ret move_and_clone_direct_mapping( + Transaction &t, + LBACursorRef src, + laddr_t dest_laddr, + LBACursorRef dest, + LogicalChildNode &extent) = 0; + + /* + * move_indirect_mapping + * + * move the indirect mapping "src" to dest, and remove "src". + * + * Return: the mapping next to "src" and the original "dest" + */ + virtual move_mapping_ret move_indirect_mapping( + Transaction &t, + LBACursorRef src, + laddr_t dest_laddr, + LBACursorRef dest) = 0; + + /* + * move_direct_mapping + * + * move the indirect mapping "src" to dest, and remove "src". + * + * Return: the mapping next to "src" and the original "dest" + */ + virtual move_mapping_ret move_direct_mapping( + Transaction &t, + LBACursorRef src, + laddr_t dest_laddr, + LBACursorRef dest, + LogicalChildNode &extent) = 0; + virtual alloc_extent_ret reserve_region( Transaction &t, laddr_hint_t hint, diff --git a/src/crimson/os/seastore/linked_tree_node.h b/src/crimson/os/seastore/linked_tree_node.h index bd077130f6c..737985e863f 100644 --- a/src/crimson/os/seastore/linked_tree_node.h +++ b/src/crimson/os/seastore/linked_tree_node.h @@ -425,6 +425,10 @@ public: } } + void reset_child_ptr(btreenode_pos_t pos) { + children[pos] = get_reserved_ptr(); + } + protected: ParentNode(btreenode_pos_t capacity) : children(capacity, nullptr) {} diff --git a/src/crimson/os/seastore/transaction_manager.h b/src/crimson/os/seastore/transaction_manager.h index 945f9063e1f..6e18d4c8625 100644 --- a/src/crimson/os/seastore/transaction_manager.h +++ b/src/crimson/os/seastore/transaction_manager.h @@ -1471,8 +1471,8 @@ private: t, remap_laddr, remap_paddr, + remap_offset, remap_len, - original_laddr, original_bptr); // user must initialize the logical extent themselves. remapped_extent->set_seen_by_users();