From a6cf5bba4a4c17ef55748c6c888978dce3831d96 Mon Sep 17 00:00:00 2001 From: Xuehan Xu Date: Mon, 1 Jul 2024 13:58:18 +0800 Subject: [PATCH] crimson/os/seastore/cached_extent: add the "refresh" ability to lba mappings So that we don't have to re-iterate through the whole lba tree to get a "parent-viewable" mapping in most cases. Signed-off-by: Xuehan Xu --- .../os/seastore/btree/btree_range_pin.h | 4 ++ src/crimson/os/seastore/btree/fixed_kv_node.h | 22 +++++++++++ src/crimson/os/seastore/cached_extent.h | 5 +++ .../lba_manager/btree/btree_lba_manager.h | 8 ++++ .../lba_manager/btree/lba_btree_node.cc | 14 +++++++ .../lba_manager/btree/lba_btree_node.h | 1 + src/crimson/os/seastore/transaction_manager.h | 37 ++++++++++++------- 7 files changed, 77 insertions(+), 14 deletions(-) diff --git a/src/crimson/os/seastore/btree/btree_range_pin.h b/src/crimson/os/seastore/btree/btree_range_pin.h index 56bdf5729be33..e0deb6b3da15a 100644 --- a/src/crimson/os/seastore/btree/btree_range_pin.h +++ b/src/crimson/os/seastore/btree/btree_range_pin.h @@ -225,6 +225,10 @@ public: } return !is_unviewable_by_trans(*parent, ctx.trans); } + bool is_parent_valid() const final { + ceph_assert(parent); + return parent->is_valid(); + } }; } diff --git a/src/crimson/os/seastore/btree/fixed_kv_node.h b/src/crimson/os/seastore/btree/fixed_kv_node.h index 536c11c479e60..0bde60ef18ede 100644 --- a/src/crimson/os/seastore/btree/fixed_kv_node.h +++ b/src/crimson/os/seastore/btree/fixed_kv_node.h @@ -134,6 +134,28 @@ struct FixedKVNode : ChildableCachedExtent { copy_dests.dests_by_key.erase(dest); } + FixedKVNodeRef find_pending_version(Transaction &t, node_key_t key) { + assert(is_stable()); + auto mut_iter = mutation_pendings.find( + t.get_trans_id(), trans_spec_view_t::cmp_t()); + if (mut_iter != mutation_pendings.end()) { + assert(copy_dests_by_trans.find(t.get_trans_id()) == + copy_dests_by_trans.end()); + return (FixedKVNode*)(&(*mut_iter)); + } + auto iter = copy_dests_by_trans.find( + t.get_trans_id(), trans_spec_view_t::cmp_t()); + ceph_assert(iter != copy_dests_by_trans.end()); + auto ©_dests = static_cast(*iter); + auto it = copy_dests.dests_by_key.lower_bound(key); + if ((*it)->range.begin > key) { + ceph_assert(it != copy_dests.dests_by_key.begin()); + --it; + } + ceph_assert((*it)->range.begin <= key && key < (*it)->range.end); + return *it; + } + bool is_linked() { assert(!has_parent_tracker() || !(bool)root_block); return (bool)has_parent_tracker() || (bool)root_block; diff --git a/src/crimson/os/seastore/cached_extent.h b/src/crimson/os/seastore/cached_extent.h index 2f8308d5eef8d..1d6ffc740cb81 100644 --- a/src/crimson/os/seastore/cached_extent.h +++ b/src/crimson/os/seastore/cached_extent.h @@ -1121,6 +1121,10 @@ public: virtual val_t get_val() const = 0; virtual key_t get_key() const = 0; virtual PhysicalNodeMappingRef duplicate() const = 0; + virtual PhysicalNodeMappingRef refresh_with_pending_parent() { + ceph_abort("impossible"); + return {}; + } virtual bool has_been_invalidated() const = 0; virtual CachedExtentRef get_parent() const = 0; virtual uint16_t get_pos() const = 0; @@ -1155,6 +1159,7 @@ public: return !get_val().is_real(); } virtual bool is_parent_viewable() const = 0; + virtual bool is_parent_valid() const = 0; virtual bool parent_modified() const { ceph_abort("impossible"); return false; diff --git a/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.h b/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.h index a5b9bb70c18df..aa6f0fecb313e 100644 --- a/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.h +++ b/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.h @@ -176,6 +176,14 @@ public: auto &p = static_cast(*parent); p.maybe_fix_mapping_pos(*this); } + + LBAMappingRef refresh_with_pending_parent() final { + assert(is_parent_valid() && !is_parent_viewable()); + auto &p = static_cast(*parent); + auto &viewable_p = static_cast( + *p.find_pending_version(ctx.trans, get_key())); + return viewable_p.get_mapping(ctx, get_key()); + } protected: std::unique_ptr> _duplicate( op_context_t ctx) const final { diff --git a/src/crimson/os/seastore/lba_manager/btree/lba_btree_node.cc b/src/crimson/os/seastore/lba_manager/btree/lba_btree_node.cc index 504c346ea946d..f3e37ff9bef37 100644 --- a/src/crimson/os/seastore/lba_manager/btree/lba_btree_node.cc +++ b/src/crimson/os/seastore/lba_manager/btree/lba_btree_node.cc @@ -72,4 +72,18 @@ void LBALeafNode::maybe_fix_mapping_pos(BtreeLBAMapping &mapping) } } +BtreeLBAMappingRef LBALeafNode::get_mapping( + op_context_t c, laddr_t laddr) +{ + auto iter = lower_bound(laddr); + ceph_assert(iter != end() && iter->get_key() == laddr); + auto val = iter.get_val(); + return std::make_unique( + c, + this, + iter.get_offset(), + val, + lba_node_meta_t{laddr, val.len, 0}); +} + } diff --git a/src/crimson/os/seastore/lba_manager/btree/lba_btree_node.h b/src/crimson/os/seastore/lba_manager/btree/lba_btree_node.h index add464e45e6f9..2cd6e7bec4aa6 100644 --- a/src/crimson/os/seastore/lba_manager/btree/lba_btree_node.h +++ b/src/crimson/os/seastore/lba_manager/btree/lba_btree_node.h @@ -294,6 +294,7 @@ struct LBALeafNode std::ostream &_print_detail(std::ostream &out) const final; void maybe_fix_mapping_pos(BtreeLBAMapping &mapping); + std::unique_ptr get_mapping(op_context_t c, laddr_t laddr); }; using LBALeafNodeRef = TCachedExtentRef; diff --git a/src/crimson/os/seastore/transaction_manager.h b/src/crimson/os/seastore/transaction_manager.h index 1417fd1de0048..2f4394720aaf9 100644 --- a/src/crimson/os/seastore/transaction_manager.h +++ b/src/crimson/os/seastore/transaction_manager.h @@ -184,11 +184,16 @@ public: { auto fut = base_iertr::make_ready_future(); if (!pin->is_parent_viewable()) { - fut = get_pin(t, pin->get_key() - ).handle_error_interruptible( - crimson::ct_error::enoent::assert_failure{"unexpected enoent"}, - crimson::ct_error::input_output_error::pass_further{} - ); + if (pin->is_parent_valid()) { + pin = pin->refresh_with_pending_parent(); + fut = base_iertr::make_ready_future(std::move(pin)); + } else { + fut = get_pin(t, pin->get_key() + ).handle_error_interruptible( + crimson::ct_error::enoent::assert_failure{"unexpected enoent"}, + crimson::ct_error::input_output_error::pass_further{} + ); + } } else { pin->maybe_fix_pos(); fut = base_iertr::make_ready_future(std::move(pin)); @@ -476,15 +481,19 @@ public: auto fut = base_iertr::now(); if (!pin->is_indirect()) { if (!pin->is_parent_viewable()) { - fut = get_pin(t, pin->get_key() - ).si_then([&pin](auto npin) { - assert(npin); - pin = std::move(npin); - return seastar::now(); - }).handle_error_interruptible( - crimson::ct_error::enoent::assert_failure{"unexpected enoent"}, - crimson::ct_error::input_output_error::pass_further{} - ); + if (pin->is_parent_valid()) { + pin = pin->refresh_with_pending_parent(); + } else { + fut = get_pin(t, pin->get_key() + ).si_then([&pin](auto npin) { + assert(npin); + pin = std::move(npin); + return seastar::now(); + }).handle_error_interruptible( + crimson::ct_error::enoent::assert_failure{"unexpected enoent"}, + crimson::ct_error::input_output_error::pass_further{} + ); + } } else { pin->maybe_fix_pos(); } -- 2.39.5