From 6163d9bfafc01293edc8065dc3feb717a237bc21 Mon Sep 17 00:00:00 2001 From: Xuehan Xu Date: Thu, 20 Oct 2022 17:41:25 +0800 Subject: [PATCH] crimson/os/seastore/btree: link fixed-kv-btree and root_block with pointers Signed-off-by: Xuehan Xu (cherry picked from commit 4d9b60e75047fa0d7e5acce601bc15f49d253349) --- src/crimson/os/seastore/CMakeLists.txt | 1 + .../seastore/backref/btree_backref_manager.cc | 54 +++- .../os/seastore/btree/fixed_kv_btree.h | 249 ++++++++++++------ src/crimson/os/seastore/btree/fixed_kv_node.h | 59 +++-- src/crimson/os/seastore/cache.h | 28 ++ src/crimson/os/seastore/cached_extent.cc | 9 +- src/crimson/os/seastore/cached_extent.h | 1 + .../lba_manager/btree/btree_lba_manager.cc | 57 +++- .../lba_manager/btree/lba_btree_node.cc | 2 +- src/crimson/os/seastore/root_block.cc | 27 ++ src/crimson/os/seastore/root_block.h | 17 +- .../seastore/test_btree_lba_manager.cc | 25 +- 12 files changed, 399 insertions(+), 130 deletions(-) create mode 100644 src/crimson/os/seastore/root_block.cc diff --git a/src/crimson/os/seastore/CMakeLists.txt b/src/crimson/os/seastore/CMakeLists.txt index 6dd19a1563a..baa2e7ca954 100644 --- a/src/crimson/os/seastore/CMakeLists.txt +++ b/src/crimson/os/seastore/CMakeLists.txt @@ -7,6 +7,7 @@ set(crimson_seastore_srcs transaction_manager.cc transaction.cc cache.cc + root_block.cc lba_manager.cc async_cleaner.cc backref_manager.cc diff --git a/src/crimson/os/seastore/backref/btree_backref_manager.cc b/src/crimson/os/seastore/backref/btree_backref_manager.cc index 341afef3640..7db8318cb9d 100644 --- a/src/crimson/os/seastore/backref/btree_backref_manager.cc +++ b/src/crimson/os/seastore/backref/btree_backref_manager.cc @@ -19,6 +19,57 @@ phy_tree_root_t& get_phy_tree_root< return r.backref_root; } +template<> +const get_phy_tree_root_node_ret get_phy_tree_root_node< + crimson::os::seastore::backref::BackrefBtree>( + const RootBlockRef &root_block, op_context_t c) { + auto backref_root = root_block->backref_root_node; + if (backref_root) { + ceph_assert(backref_root->is_initial_pending() + == root_block->is_pending()); + return {true, + trans_intr::make_interruptible( + c.cache.get_extent_viewable_by_trans(c.trans, backref_root))}; + } else if (root_block->is_pending()) { + auto &prior = static_cast(*root_block->get_prior_instance()); + backref_root = prior.backref_root_node; + if (backref_root) { + return {true, + trans_intr::make_interruptible( + c.cache.get_extent_viewable_by_trans(c.trans, backref_root))}; + } else { + return {false, + trans_intr::make_interruptible( + seastar::make_ready_future< + CachedExtentRef>(CachedExtentRef()))}; + } + } else { + return {false, + trans_intr::make_interruptible( + seastar::make_ready_future< + CachedExtentRef>(CachedExtentRef()))}; + } +} + +template +void link_phy_tree_root_node(RootBlockRef &root_block, ROOT* backref_root) { + root_block->backref_root_node = backref_root; + ceph_assert(backref_root != nullptr); + backref_root->root_block = root_block; +} + +template void link_phy_tree_root_node( + RootBlockRef &root_block, backref::BackrefInternalNode* backref_root); +template void link_phy_tree_root_node( + RootBlockRef &root_block, backref::BackrefLeafNode* backref_root); +template void link_phy_tree_root_node( + RootBlockRef &root_block, backref::BackrefNode* backref_root); + +template <> +void unlink_phy_tree_root_node(RootBlockRef &root_block) { + root_block->backref_root_node = nullptr; +} + } namespace crimson::os::seastore::backref { @@ -36,7 +87,8 @@ BtreeBackrefManager::mkfs( LOG_PREFIX(BtreeBackrefManager::mkfs); INFOT("start", t); return cache.get_root(t).si_then([this, &t](auto croot) { - croot->get_root().backref_root = BackrefBtree::mkfs(get_context(t)); + assert(croot->is_mutation_pending()); + croot->get_root().backref_root = BackrefBtree::mkfs(croot, get_context(t)); return mkfs_iertr::now(); }).handle_error_interruptible( mkfs_iertr::pass_further{}, diff --git a/src/crimson/os/seastore/btree/fixed_kv_btree.h b/src/crimson/os/seastore/btree/fixed_kv_btree.h index 47eda89782c..0e51d00ed76 100644 --- a/src/crimson/os/seastore/btree/fixed_kv_btree.h +++ b/src/crimson/os/seastore/btree/fixed_kv_btree.h @@ -13,6 +13,7 @@ #include "crimson/os/seastore/cache.h" #include "crimson/os/seastore/seastore_types.h" #include "crimson/os/seastore/btree/btree_range_pin.h" +#include "crimson/os/seastore/root_block.h" namespace crimson::os::seastore::lba_manager::btree { struct lba_map_val_t; @@ -20,6 +21,9 @@ struct lba_map_val_t; namespace crimson::os::seastore { +template +phy_tree_root_t& get_phy_tree_root(root_t& r); + template struct op_context_t { Cache &cache; @@ -27,6 +31,23 @@ struct op_context_t { btree_pin_set_t *pins = nullptr; }; +using get_phy_tree_root_node_ret = + std::pair>; + +template +const get_phy_tree_root_node_ret get_phy_tree_root_node( + const RootBlockRef &root_block, + op_context_t c); + +template +void link_phy_tree_root_node(RootBlockRef &root_block, ROOT_T* root_node); + +template +void unlink_phy_tree_root_node(RootBlockRef &root_block); + + template Transaction::tree_stats_t& get_tree_stats(Transaction &t); @@ -303,20 +324,30 @@ public: } }; - FixedKVBtree(phy_tree_root_t root) : root(root) {} + FixedKVBtree(RootBlockRef &root_block) : root_block(root_block) {} - bool is_root_dirty() const { - return root_dirty; + auto& get_root() { + return get_phy_tree_root(root_block->get_root()); } - phy_tree_root_t get_root_undirty() { - ceph_assert(root_dirty); - root_dirty = false; - return root; + + auto& get_root() const { + return get_phy_tree_root(root_block->get_root()); + } + + template + void set_root_node(const TCachedExtentRef &root_node) { + static_assert(std::is_base_of_v); + link_phy_tree_root_node(root_block, root_node.get()); + } + + auto get_root_node(op_context_t c) const { + return get_phy_tree_root_node(root_block, c); } /// mkfs using mkfs_ret = phy_tree_root_t; - static mkfs_ret mkfs(op_context_t c) { + static mkfs_ret mkfs(RootBlockRef &root_block, op_context_t c) { + assert(root_block->is_mutation_pending()); auto root_leaf = c.cache.template alloc_new_extent( c.trans, node_size, @@ -328,6 +359,7 @@ public: root_leaf->pin.set_range(meta); get_tree_stats(c.trans).depth = 1u; get_tree_stats(c.trans).extents_num_delta++; + link_phy_tree_root_node(root_block, root_leaf.get()); return phy_tree_root_t{root_leaf->get_paddr(), 1u}; } @@ -934,11 +966,11 @@ public: depth, old_addr, new_addr, - root.get_location()); + get_root().get_location()); ceph_assert(0 == "impossible"); } - if (root.get_location() != old_addr) { + if (get_root().get_location() != old_addr) { SUBERRORT( seastore_fixedkv_tree, "updating root laddr {} at depth {} from {} to {}," @@ -948,12 +980,14 @@ public: depth, old_addr, new_addr, - root.get_location()); + get_root().get_location()); ceph_assert(0 == "impossible"); } - root.set_location(new_addr); - root_dirty = true; + root_block = c.cache.duplicate_for_write( + c.trans, root_block)->template cast(); + get_root().set_location(new_addr); + set_root_node(nextent); } else { auto &parent = iter.get_internal(depth + 1); assert(parent.node); @@ -1012,8 +1046,7 @@ public: private: - phy_tree_root_t root; - bool root_dirty = false; + RootBlockRef root_block; template using node_position_t = typename iterator::template node_position_t; @@ -1047,6 +1080,16 @@ private: if (parent_pos) { auto &parent = parent_pos->node; parent->link_child(&node, parent_pos->pos); + } else { + assert(node.range.is_root()); + auto root_block = c.cache.get_root_fast(c.trans); + if (root_block->is_mutation_pending()) { + auto &stable_root = (RootBlockRef&)*root_block->get_prior_instance(); + link_phy_tree_root_node(stable_root, &node); + } else { + assert(!root_block->is_pending()); + link_phy_tree_root_node(root_block, &node); + } } if (c.pins) { c.pins->add_pin(node.pin); @@ -1114,6 +1157,16 @@ private: if (parent_pos) { auto &parent = parent_pos->node; parent->link_child(&node, parent_pos->pos); + } else { + assert(node.range.is_root()); + auto root_block = c.cache.get_root_fast(c.trans); + if (root_block->is_mutation_pending()) { + auto &stable_root = (RootBlockRef&)*root_block->get_prior_instance(); + link_phy_tree_root_node(stable_root, &node); + } else { + assert(!root_block->is_pending()); + link_phy_tree_root_node(root_block, &node); + } } if (c.pins) { c.pins->add_pin(node.pin); @@ -1160,41 +1213,79 @@ private: op_context_t c, iterator &iter, mapped_space_visitor_t *visitor) const { - if (root.get_depth() > 1) { - return get_internal_node( - c, - root.get_depth(), - root.get_location(), - min_max_t::min, - min_max_t::max, - std::nullopt - ).si_then([this, visitor, &iter](InternalNodeRef root_node) { - iter.get_internal(root.get_depth()).node = root_node; - if (visitor) (*visitor)( - root_node->get_paddr(), - root_node->get_node_meta().begin, - root_node->get_length(), - root.get_depth(), - internal_node_t::TYPE); - return lookup_root_iertr::now(); + LOG_PREFIX(FixedKVBtree::lookup_root); + SUBTRACET(seastore_fixedkv_tree, + "looking up root on {}", + c.trans, + *root_block); + auto [found, fut] = get_root_node(c); + + auto on_found_internal = + [this, visitor, &iter](InternalNodeRef &root_node) { + iter.get_internal(get_root().get_depth()).node = root_node; + if (visitor) (*visitor)( + root_node->get_paddr(), + root_node->get_node_meta().begin, + root_node->get_length(), + get_root().get_depth(), + internal_node_t::TYPE); + return lookup_root_iertr::now(); + }; + auto on_found_leaf = + [visitor, &iter, this](LeafNodeRef root_node) { + iter.leaf.node = root_node; + if (visitor) (*visitor)( + root_node->get_paddr(), + root_node->get_node_meta().begin, + root_node->get_length(), + get_root().get_depth(), + leaf_node_t::TYPE); + return lookup_root_iertr::now(); + }; + + if (found) { + return fut.then_interruptible( + [this, c, on_found_internal=std::move(on_found_internal), + on_found_leaf=std::move(on_found_leaf)](auto root) { + LOG_PREFIX(FixedKVBtree::lookup_root); + ceph_assert(root); + SUBTRACET(seastore_fixedkv_tree, + "got root node on {}, res: {}", + c.trans, + *root_block, + *root); + + if (get_root().get_depth() > 1) { + auto root_node = root->template cast(); + return on_found_internal(root_node); + } else { + auto root_node = root->template cast(); + return on_found_leaf(root_node); + } }); } else { - return get_leaf_node( - c, - root.get_location(), - min_max_t::min, - min_max_t::max, - std::nullopt - ).si_then([visitor, &iter, this](LeafNodeRef root_node) { - iter.leaf.node = root_node; - if (visitor) (*visitor)( - root_node->get_paddr(), - root_node->get_node_meta().begin, - root_node->get_length(), - root.get_depth(), - leaf_node_t::TYPE); - return lookup_root_iertr::now(); - }); + if (get_root().get_depth() > 1) { + return get_internal_node( + c, + get_root().get_depth(), + get_root().get_location(), + min_max_t::min, + min_max_t::max, + std::nullopt + ).si_then([on_found=std::move(on_found_internal)](InternalNodeRef root_node) { + return on_found(root_node); + }); + } else { + return get_leaf_node( + c, + get_root().get_location(), + min_max_t::min, + min_max_t::max, + std::nullopt + ).si_then([on_found=std::move(on_found_leaf)](LeafNodeRef root_node) { + return on_found(root_node); + }); + } } } @@ -1421,7 +1512,7 @@ private: LOG_PREFIX(FixedKVBtree::lookup); assert(min_depth > 0); return seastar::do_with( - iterator{root.get_depth()}, + iterator{get_root().get_depth()}, std::forward
  • (lookup_internal), std::forward(lookup_leaf), [FNAME, this, visitor, c, min_depth](auto &iter, auto &li, auto &ll) { @@ -1436,11 +1527,12 @@ private: auto riter = ll(*(root_entry.node)); root_entry.pos = riter->get_offset(); } - SUBTRACET(seastore_fixedkv_tree, "got root, depth {}", c.trans, root.get_depth()); + SUBTRACET(seastore_fixedkv_tree, "got root, depth {}", + c.trans, get_root().get_depth()); return lookup_depth_range( c, iter, - root.get_depth() - 1, + get_root().get_depth() - 1, min_depth - 1, li, ll, @@ -1542,16 +1634,19 @@ private: nroot->journal_insert( nroot->begin(), min_max_t::min, - root.get_location(), + get_root().get_location(), nullptr); iter.internal.push_back({nroot, 0}); - root.set_location(nroot->get_paddr()); - root.set_depth(iter.get_depth()); - ceph_assert(root.get_depth() <= MAX_FIXEDKVBTREE_DEPTH); get_tree_stats(c.trans).depth = iter.get_depth(); get_tree_stats(c.trans).extents_num_delta++; - root_dirty = true; + + root_block = c.cache.duplicate_for_write( + c.trans, root_block)->template cast(); + get_root().set_location(nroot->get_paddr()); + get_root().set_depth(iter.get_depth()); + ceph_assert(get_root().get_depth() <= MAX_FIXEDKVBTREE_DEPTH); + set_root_node(nroot); } /* pos may be either node_position_t or @@ -1693,13 +1788,22 @@ private: c.cache.retire_extent(c.trans, pos.node); assert(pos.pos == 0); auto node_iter = pos.get_iter(); - root.set_location( - node_iter->get_val().maybe_relative_to(pos.node->get_paddr())); iter.internal.pop_back(); - root.set_depth(iter.get_depth()); get_tree_stats(c.trans).depth = iter.get_depth(); get_tree_stats(c.trans).extents_num_delta--; - root_dirty = true; + + root_block = c.cache.duplicate_for_write( + c.trans, root_block + )->template cast(); + get_root().set_location( + node_iter->get_val().maybe_relative_to(pos.node->get_paddr())); + get_root().set_depth(iter.get_depth()); + if (iter.get_depth() > 1) { + auto root_node = iter.get_internal(iter.get_depth()).node; + set_root_node(root_node); + } else { + set_root_node(iter.leaf.node); + } } else { SUBTRACET(seastore_fixedkv_tree, "no need to collapse root", c.trans); } @@ -1914,9 +2018,6 @@ struct is_fixed_kv_tree< pin_t, node_size>> : std::true_type {}; -template -phy_tree_root_t& get_phy_tree_root(root_t& r); - template < typename tree_type_t, typename node_key_t, @@ -1926,27 +2027,13 @@ auto with_btree( Cache &cache, op_context_t c, F &&f) { - using base_ertr = crimson::errorator< - crimson::ct_error::input_output_error>; - using base_iertr = trans_iertr; return cache.get_root( c.trans - ).si_then([c, f=std::forward(f), &cache](RootBlockRef croot) mutable { + ).si_then([f=std::forward(f)](RootBlockRef croot) mutable { return seastar::do_with( - tree_type_t(get_phy_tree_root(croot->get_root())), - [c, croot, f=std::move(f), &cache](auto &btree) mutable { - return f( - btree - ).si_then([c, croot, &btree, &cache] { - if (btree.is_root_dirty()) { - auto mut_croot = cache.duplicate_for_write( - c.trans, croot - )->template cast(); - get_phy_tree_root(mut_croot->get_root()) = - btree.get_root_undirty(); - } - return base_iertr::now(); - }); + tree_type_t(croot), + [f=std::move(f)](auto &btree) mutable { + return f(btree); }); }); } diff --git a/src/crimson/os/seastore/btree/fixed_kv_node.h b/src/crimson/os/seastore/btree/fixed_kv_node.h index b171db6965b..bee5b2fa512 100644 --- a/src/crimson/os/seastore/btree/fixed_kv_node.h +++ b/src/crimson/os/seastore/btree/fixed_kv_node.h @@ -18,6 +18,7 @@ #include "crimson/os/seastore/btree/btree_range_pin.h" #include "crimson/os/seastore/btree/fixed_kv_btree.h" +#include "crimson/os/seastore/root_block.h" namespace crimson::os::seastore { @@ -102,6 +103,7 @@ struct FixedKVNode : CachedExtent { uint16_t capacity = 0; parent_tracker_t* my_tracker = nullptr; parent_tracker_ref parent_tracker; + RootBlockRef root_block; FixedKVNode(uint16_t capacity, ceph::bufferptr &&ptr) : CachedExtent(std::move(ptr)), @@ -345,11 +347,16 @@ struct FixedKVNode : CachedExtent { } void set_parent_tracker_from_prior_instance() { + assert(is_mutation_pending()); + auto &prior = (FixedKVNode&)(*get_prior_instance()); if (pin.is_root()) { + ceph_assert(prior.root_block); + ceph_assert(pending_for_transaction); + root_block = prior.root_block; + link_phy_tree_root_node(root_block, this); return; } - assert(is_mutation_pending()); - auto &prior = (FixedKVNode&)(*get_prior_instance()); + ceph_assert(!root_block); parent_tracker = prior.parent_tracker; auto &parent = parent_tracker->parent; assert(parent); @@ -605,16 +612,19 @@ struct FixedKVInternalNode } virtual ~FixedKVInternalNode() { - if (!this->pin.is_root() - && this->is_valid() - && !this->is_pending()) { - ceph_assert(this->parent_tracker); - auto &parent = this->parent_tracker->parent; - ceph_assert(parent); - auto off = parent->lower_bound_offset(this->get_meta().begin); - assert(parent->get_key_from_idx(off) == get_node_meta().begin); - assert(parent->children[off] == this); - parent->children[off] = nullptr; + if (this->is_valid() && !this->is_pending()) { + if (this->pin.is_root()) { + ceph_assert(this->root_block); + unlink_phy_tree_root_node(this->root_block); + } else { + ceph_assert(this->parent_tracker); + auto &parent = this->parent_tracker->parent; + ceph_assert(parent); + auto off = parent->lower_bound_offset(this->get_meta().begin); + assert(parent->get_key_from_idx(off) == this->get_meta().begin); + assert(parent->children[off] == this); + parent->children[off] = nullptr; + } } } @@ -855,7 +865,7 @@ struct FixedKVInternalNode if (this->my_tracker) { out << ", my_tracker->parent=" << (void*)this->my_tracker->parent.get(); } - return out; + return out << ", root_block=" << (void*)this->root_block.get(); } ceph::bufferlist get_delta() { @@ -941,16 +951,19 @@ struct FixedKVLeafNode } virtual ~FixedKVLeafNode() { - if (!this->pin.is_root() - && this->is_valid() - && !this->is_pending()) { - ceph_assert(this->parent_tracker); - auto &parent = this->parent_tracker->parent; - ceph_assert(parent); - auto off = parent->lower_bound_offset(this->get_meta().begin); - assert(parent->get_key_from_idx(off) == get_node_meta().begin); - assert(parent->children[off] == this); - parent->children[off] = nullptr; + if (this->is_valid() && !this->is_pending()) { + if (this->pin.is_root()) { + ceph_assert(this->root_block); + unlink_phy_tree_root_node(this->root_block); + } else { + ceph_assert(this->parent_tracker); + auto &parent = this->parent_tracker->parent; + ceph_assert(parent); + auto off = parent->lower_bound_offset(this->get_meta().begin); + assert(parent->get_key_from_idx(off) == this->get_meta().begin); + assert(parent->children[off] == this); + parent->children[off] = nullptr; + } } } diff --git a/src/crimson/os/seastore/cache.h b/src/crimson/os/seastore/cache.h index 789b14074b8..ec3c27b1606 100644 --- a/src/crimson/os/seastore/cache.h +++ b/src/crimson/os/seastore/cache.h @@ -512,6 +512,34 @@ public: return get_absent_extent(t, offset, length, [](T &){}); } + seastar::future get_extent_viewable_by_trans( + Transaction &t, + CachedExtentRef extent) + { + auto p_extent = extent->get_transactional_view(t); + if (!p_extent->is_pending_in_trans(t.get_trans_id())) { + t.add_to_read_set(p_extent); + if (!p_extent->is_mutation_pending()) { + touch_extent(*p_extent); + } + } + return p_extent->wait_io( + ).then([p_extent] { + return CachedExtentRef(p_extent); + }); + } + + template + seastar::future> get_extent_viewable_by_trans( + Transaction &t, + TCachedExtentRef extent) + { + return get_extent_viewable_by_trans(t, CachedExtentRef(extent.get()) + ).then([](auto p_extent) { + return p_extent->template cast(); + }); + } + extent_len_t get_block_size() const { return epm.get_block_size(); } diff --git a/src/crimson/os/seastore/cached_extent.cc b/src/crimson/os/seastore/cached_extent.cc index f1ea69d6332..dfa4c656168 100644 --- a/src/crimson/os/seastore/cached_extent.cc +++ b/src/crimson/os/seastore/cached_extent.cc @@ -78,11 +78,12 @@ CachedExtent::~CachedExtent() parent_index->erase(*this); } } - CachedExtent* CachedExtent::get_transactional_view(Transaction &t) { - auto it = mutation_pendings.find( - t.get_trans_id(), - trans_spec_view_t::cmp_t()); + return get_transactional_view(t.get_trans_id()); +} + +CachedExtent* CachedExtent::get_transactional_view(transaction_id_t tid) { + auto it = mutation_pendings.find(tid, trans_spec_view_t::cmp_t()); if (it != mutation_pendings.end()) { return (CachedExtent*)&(*it); } else { diff --git a/src/crimson/os/seastore/cached_extent.h b/src/crimson/os/seastore/cached_extent.h index 170a8137746..a2544d5e996 100644 --- a/src/crimson/os/seastore/cached_extent.h +++ b/src/crimson/os/seastore/cached_extent.h @@ -626,6 +626,7 @@ private: } CachedExtent* get_transactional_view(Transaction &t); + CachedExtent* get_transactional_view(transaction_id_t tid); read_set_item_t::trans_set_t transactions; diff --git a/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.cc b/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.cc index 63130f7b476..2c159535f38 100644 --- a/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.cc +++ b/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.cc @@ -33,6 +33,58 @@ phy_tree_root_t& get_phy_tree_root< return r.lba_root; } +template <> +const get_phy_tree_root_node_ret get_phy_tree_root_node< + crimson::os::seastore::lba_manager::btree::LBABtree>( + const RootBlockRef &root_block, op_context_t c) +{ + auto lba_root = root_block->lba_root_node; + if (lba_root) { + ceph_assert(lba_root->is_initial_pending() + == root_block->is_pending()); + return {true, + trans_intr::make_interruptible( + c.cache.get_extent_viewable_by_trans(c.trans, lba_root))}; + } else if (root_block->is_pending()) { + auto &prior = static_cast(*root_block->get_prior_instance()); + lba_root = prior.lba_root_node; + if (lba_root) { + return {true, + trans_intr::make_interruptible( + c.cache.get_extent_viewable_by_trans(c.trans, lba_root))}; + } else { + return {false, + trans_intr::make_interruptible( + seastar::make_ready_future< + CachedExtentRef>(CachedExtentRef()))}; + } + } else { + return {false, + trans_intr::make_interruptible( + seastar::make_ready_future< + CachedExtentRef>(CachedExtentRef()))}; + } +} + +template +void link_phy_tree_root_node(RootBlockRef &root_block, ROOT* lba_root) { + root_block->lba_root_node = lba_root; + ceph_assert(lba_root != nullptr); + lba_root->root_block = root_block; +} + +template void link_phy_tree_root_node( + RootBlockRef &root_block, lba_manager::btree::LBAInternalNode* lba_root); +template void link_phy_tree_root_node( + RootBlockRef &root_block, lba_manager::btree::LBALeafNode* lba_root); +template void link_phy_tree_root_node( + RootBlockRef &root_block, lba_manager::btree::LBANode* lba_root); + +template <> +void unlink_phy_tree_root_node(RootBlockRef &root_block) { + root_block->lba_root_node = nullptr; +} + } namespace crimson::os::seastore::lba_manager::btree { @@ -43,7 +95,8 @@ BtreeLBAManager::mkfs_ret BtreeLBAManager::mkfs( LOG_PREFIX(BtreeLBAManager::mkfs); INFOT("start", t); return cache.get_root(t).si_then([this, &t](auto croot) { - croot->get_root().lba_root = LBABtree::mkfs(get_context(t)); + assert(croot->is_mutation_pending()); + croot->get_root().lba_root = LBABtree::mkfs(croot, get_context(t)); return mkfs_iertr::now(); }).handle_error_interruptible( mkfs_iertr::pass_further{}, @@ -301,6 +354,8 @@ BtreeLBAManager::base_iertr::future<> _init_cached_extent( if (!iter.is_end() && iter.get_key() == logn->get_laddr() && iter.get_val().paddr == logn->get_paddr()) { + assert(!iter.get_leaf_node()->is_pending()); + iter.get_leaf_node()->link_child(logn.get(), iter.get_leaf_pos()); logn->set_pin(iter.get_pin()); ceph_assert(iter.get_val().len == e->get_length()); if (c.pins) { 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 e3eed252ebe..c502ef338a1 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 @@ -35,7 +35,7 @@ std::ostream &LBALeafNode::print_detail(std::ostream &out) const if (parent_tracker) { return out << ", parent=" << (void*)parent_tracker->parent.get(); } - return out; + return out << ", root_block=" << (void*)root_block.get(); } void LBALeafNode::resolve_relative_addrs(paddr_t base) diff --git a/src/crimson/os/seastore/root_block.cc b/src/crimson/os/seastore/root_block.cc new file mode 100644 index 00000000000..dc928e81b0f --- /dev/null +++ b/src/crimson/os/seastore/root_block.cc @@ -0,0 +1,27 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "crimson/os/seastore/root_block.h" +#include "crimson/os/seastore/lba_manager/btree/lba_btree_node.h" +#include "crimson/os/seastore/backref/backref_tree_node.h" + +namespace crimson::os::seastore { + +void RootBlock::on_replace_prior(Transaction &t) { + if (!lba_root_node) { + auto &prior = static_cast(*get_prior_instance()); + lba_root_node = prior.lba_root_node; + if (lba_root_node) { + ((lba_manager::btree::LBANode*)lba_root_node)->root_block = this; + } + } + if (!backref_root_node) { + auto &prior = static_cast(*get_prior_instance()); + backref_root_node = prior.backref_root_node; + if (backref_root_node) { + ((backref::BackrefNode*)backref_root_node)->root_block = this; + } + } +} + +} // namespace crimson::os::seastore diff --git a/src/crimson/os/seastore/root_block.h b/src/crimson/os/seastore/root_block.h index 435860ff36b..bf3dfb54265 100644 --- a/src/crimson/os/seastore/root_block.h +++ b/src/crimson/os/seastore/root_block.h @@ -38,9 +38,17 @@ struct RootBlock : CachedExtent { root_t root; + CachedExtent* lba_root_node = nullptr; + CachedExtent* backref_root_node = nullptr; + RootBlock() : CachedExtent(0) {} - RootBlock(const RootBlock &rhs) = default; + RootBlock(const RootBlock &rhs) + : CachedExtent(rhs), + root(rhs.root), + lba_root_node(nullptr), + backref_root_node(nullptr) + {} CachedExtentRef duplicate_for_write(Transaction&) final { return CachedExtentRef(new RootBlock(*this)); @@ -51,6 +59,8 @@ struct RootBlock : CachedExtent { return extent_types_t::ROOT; } + void on_replace_prior(Transaction &t) final; + /// dumps root as delta ceph::bufferlist get_delta() final { ceph::bufferlist bl; @@ -84,6 +94,11 @@ struct RootBlock : CachedExtent { root_t &get_root() { return root; } + std::ostream &print_detail(std::ostream &out) const final { + return out << ", root_block(lba_root_node=" << (void*)lba_root_node + << ", backref_root_node=" << (void*)backref_root_node + << ")"; + } }; using RootBlockRef = RootBlock::Ref; diff --git a/src/test/crimson/seastore/test_btree_lba_manager.cc b/src/test/crimson/seastore/test_btree_lba_manager.cc index ab9ef797459..3853d53e7a4 100644 --- a/src/test/crimson/seastore/test_btree_lba_manager.cc +++ b/src/test/crimson/seastore/test_btree_lba_manager.cc @@ -198,19 +198,11 @@ struct lba_btree_test : btree_test_base { auto mut_croot = cache->duplicate_for_write( t, croot )->cast(); - mut_croot->root.lba_root = LBABtree::mkfs(get_op_context(t)); + mut_croot->root.lba_root = + LBABtree::mkfs(mut_croot, get_op_context(t)); }); } - void update_if_dirty(Transaction &t, LBABtree &btree, RootBlockRef croot) { - if (btree.is_root_dirty()) { - auto mut_croot = cache->duplicate_for_write( - t, croot - )->cast(); - mut_croot->root.lba_root = btree.get_root_undirty(); - } - } - template auto lba_btree_update(F &&f) { auto tref = cache->create_transaction( @@ -221,16 +213,13 @@ struct lba_btree_test : btree_test_base { [this, tref=std::move(tref), f=std::forward(f)](auto &t) mutable { return cache->get_root( t - ).si_then([this, f=std::move(f), &t](RootBlockRef croot) { + ).si_then([f=std::move(f), &t](RootBlockRef croot) { return seastar::do_with( - LBABtree(croot->root.lba_root), - [this, croot, f=std::move(f), &t](auto &btree) mutable { + LBABtree(croot), + [f=std::move(f), &t](auto &btree) mutable { return std::invoke( std::move(f), btree, t - ).si_then([this, croot, &t, &btree] { - update_if_dirty(t, btree, croot); - return seastar::now(); - }); + ); }); }).si_then([this, tref=std::move(tref)]() mutable { return submit_transaction(std::move(tref)); @@ -249,7 +238,7 @@ struct lba_btree_test : btree_test_base { t ).si_then([f=std::move(f), &t](RootBlockRef croot) mutable { return seastar::do_with( - LBABtree(croot->root.lba_root), + LBABtree(croot), [f=std::move(f), &t](auto &btree) mutable { return std::invoke( std::move(f), btree, t -- 2.39.5