]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
crimson/os/seastore/btree: link fixed-kv-btree and root_block with pointers
authorXuehan Xu <xxhdx1985126@gmail.com>
Thu, 20 Oct 2022 09:41:25 +0000 (17:41 +0800)
committerMatan Breizman <mbreizma@redhat.com>
Tue, 23 May 2023 13:24:45 +0000 (13:24 +0000)
Signed-off-by: Xuehan Xu <xxhdx1985126@gmail.com>
(cherry picked from commit 4d9b60e75047fa0d7e5acce601bc15f49d253349)

12 files changed:
src/crimson/os/seastore/CMakeLists.txt
src/crimson/os/seastore/backref/btree_backref_manager.cc
src/crimson/os/seastore/btree/fixed_kv_btree.h
src/crimson/os/seastore/btree/fixed_kv_node.h
src/crimson/os/seastore/cache.h
src/crimson/os/seastore/cached_extent.cc
src/crimson/os/seastore/cached_extent.h
src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.cc
src/crimson/os/seastore/lba_manager/btree/lba_btree_node.cc
src/crimson/os/seastore/root_block.cc [new file with mode: 0644]
src/crimson/os/seastore/root_block.h
src/test/crimson/seastore/test_btree_lba_manager.cc

index 6dd19a1563a525027f24af817ea4aa889abcc161..baa2e7ca954ebdd0f0b0d37b26375518a533248f 100644 (file)
@@ -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
index 341afef36406a93f31b64636eb22f9adee53b396..7db8318cb9d78e9f853469d9f8d103768bb2ea84 100644 (file)
@@ -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<paddr_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<RootBlock&>(*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 <typename ROOT>
+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<paddr_t>(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{},
index 47eda89782c78e1ebb33f052b3991bf6a37a05a8..0e51d00ed76787ce1d0e5328db08049334dcd5fd 100644 (file)
@@ -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 <typename T>
+phy_tree_root_t& get_phy_tree_root(root_t& r);
+
 template <typename node_key_t>
 struct op_context_t {
   Cache &cache;
@@ -27,6 +31,23 @@ struct op_context_t {
   btree_pin_set_t<node_key_t> *pins = nullptr;
 };
 
+using get_phy_tree_root_node_ret =
+  std::pair<bool,
+            ::crimson::interruptible::interruptible_future<
+              typename trans_intr::condition, CachedExtentRef>>;
+
+template <typename T, typename key_t>
+const get_phy_tree_root_node_ret get_phy_tree_root_node(
+  const RootBlockRef &root_block,
+  op_context_t<key_t> c);
+
+template <typename ROOT_T>
+void link_phy_tree_root_node(RootBlockRef &root_block, ROOT_T* root_node);
+
+template <typename T>
+void unlink_phy_tree_root_node(RootBlockRef &root_block);
+
+
 template <typename T>
 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<self_type>(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<self_type>(root_block->get_root());
+  }
+
+  template <typename T>
+  void set_root_node(const TCachedExtentRef<T> &root_node) {
+    static_assert(std::is_base_of_v<typename internal_node_t::base_t, T>);
+    link_phy_tree_root_node(root_block, root_node.get());
+  }
+
+  auto get_root_node(op_context_t<node_key_t> c) const {
+    return get_phy_tree_root_node<self_type>(root_block, c);
   }
 
   /// mkfs
   using mkfs_ret = phy_tree_root_t;
-  static mkfs_ret mkfs(op_context_t<node_key_t> c) {
+  static mkfs_ret mkfs(RootBlockRef &root_block, op_context_t<node_key_t> c) {
+    assert(root_block->is_mutation_pending());
     auto root_leaf = c.cache.template alloc_new_extent<leaf_node_t>(
       c.trans,
       node_size,
@@ -328,6 +359,7 @@ public:
     root_leaf->pin.set_range(meta);
     get_tree_stats<self_type>(c.trans).depth = 1u;
     get_tree_stats<self_type>(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<RootBlock>();
+        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 <typename T>
   using node_position_t = typename iterator::template node_position_t<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<node_key_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<node_key_t>::min,
-       min_max_t<node_key_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<internal_node_t>();
+          return on_found_internal(root_node);
+        } else {
+          auto root_node = root->template cast<leaf_node_t>();
+          return on_found_leaf(root_node);
+        }
       });
     } else {
-      return get_leaf_node(
-       c,
-       root.get_location(),
-       min_max_t<node_key_t>::min,
-       min_max_t<node_key_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<node_key_t>::min,
+          min_max_t<node_key_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<node_key_t>::min,
+          min_max_t<node_key_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<LI>(lookup_internal),
       std::forward<LL>(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<node_key_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<self_type>(c.trans).depth = iter.get_depth();
       get_tree_stats<self_type>(c.trans).extents_num_delta++;
-      root_dirty = true;
+
+      root_block = c.cache.duplicate_for_write(
+        c.trans, root_block)->template cast<RootBlock>();
+      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<leaf_node_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<self_type>(c.trans).depth = iter.get_depth();
                   get_tree_stats<self_type>(c.trans).extents_num_delta--;
-                  root_dirty = true;
+
+                  root_block = c.cache.duplicate_for_write(
+                    c.trans, root_block
+                  )->template cast<RootBlock>();
+                  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 <typename T>
-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<node_key_t> c,
   F &&f) {
-  using base_ertr = crimson::errorator<
-    crimson::ct_error::input_output_error>;
-  using base_iertr = trans_iertr<base_ertr>;
   return cache.get_root(
     c.trans
-  ).si_then([c, f=std::forward<F>(f), &cache](RootBlockRef croot) mutable {
+  ).si_then([f=std::forward<F>(f)](RootBlockRef croot) mutable {
     return seastar::do_with(
-      tree_type_t(get_phy_tree_root<tree_type_t>(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<RootBlock>();
-            get_phy_tree_root<tree_type_t>(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);
       });
   });
 }
index b171db6965b5a20e452a7d084f48ab7e7b58796e..bee5b2fa512ebafec10f16245a87e6802b92b9d0 100644 (file)
@@ -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<NODE_KEY>(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<NODE_KEY>(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;
+      }
     }
   }
 
index 789b14074b882769d2ad14bfc27a8e3317d5411c..ec3c27b160674cdd3663c51b6fc80d3d6a89626a 100644 (file)
@@ -512,6 +512,34 @@ public:
     return get_absent_extent<T>(t, offset, length, [](T &){});
   }
 
+  seastar::future<CachedExtentRef> 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 <typename T>
+  seastar::future<TCachedExtentRef<T>> get_extent_viewable_by_trans(
+    Transaction &t,
+    TCachedExtentRef<T> extent)
+  {
+    return get_extent_viewable_by_trans(t, CachedExtentRef(extent.get())
+    ).then([](auto p_extent) {
+      return p_extent->template cast<T>();
+    });
+  }
+
   extent_len_t get_block_size() const {
     return epm.get_block_size();
   }
index f1ea69d633260ee5486e626cf04ef24b72750810..dfa4c6561684f063f7f2d158c95e3e8b840212db 100644 (file)
@@ -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 {
index 170a81377467bf9c64225749918eecf3857c24c1..a2544d5e996b05bdbbeedb79e15358da4121f617 100644 (file)
@@ -626,6 +626,7 @@ private:
   }
 
   CachedExtent* get_transactional_view(Transaction &t);
+  CachedExtent* get_transactional_view(transaction_id_t tid);
 
   read_set_item_t<Transaction>::trans_set_t transactions;
 
index 63130f7b476c02f323be2e1b80bdcaeaffad107a..2c159535f3874f5273a7e60ff2b9771eb93a4606 100644 (file)
@@ -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<laddr_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<RootBlock&>(*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 <typename ROOT>
+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<laddr_t>(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) {
index e3eed252ebe4303915cd06ec2c9642aa7d9527a1..c502ef338a1f943992ea0e232baa76f77c641373 100644 (file)
@@ -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 (file)
index 0000000..dc928e8
--- /dev/null
@@ -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<RootBlock&>(*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<RootBlock&>(*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
index 435860ff36bb18a23dd0542ce8704c41f33d4efc..bf3dfb54265688f8480ace5cf98952cbabebe610 100644 (file)
@@ -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;
 
index ab9ef79745987e1c4655b9e568ab4c970eb561b3..3853d53e7a4ff70622904f3e0e9f500ca3d7e971 100644 (file)
@@ -198,19 +198,11 @@ struct lba_btree_test : btree_test_base {
       auto mut_croot = cache->duplicate_for_write(
        t, croot
       )->cast<RootBlock>();
-      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<RootBlock>();
-      mut_croot->root.lba_root = btree.get_root_undirty();
-    }
-  }
-
   template <typename F>
   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>(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