]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
crimson/os/seastore: initialize dirty extents after replay
authorSamuel Just <sjust@redhat.com>
Wed, 15 Jul 2020 23:43:32 +0000 (16:43 -0700)
committerSamuel Just <sjust@redhat.com>
Wed, 5 Aug 2020 06:17:55 +0000 (23:17 -0700)
lba_manager needs to preload BtreeLBAPin and parent nodes.

Signed-off-by: Samuel Just <sjust@redhat.com>
src/crimson/os/seastore/cache.h
src/crimson/os/seastore/lba_manager.h
src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.cc
src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.h
src/crimson/os/seastore/lba_manager/btree/lba_btree_node.h
src/crimson/os/seastore/lba_manager/btree/lba_btree_node_impl.cc
src/crimson/os/seastore/lba_manager/btree/lba_btree_node_impl.h
src/crimson/os/seastore/transaction_manager.cc

index 50aeff0fa7d661fae838b9b8327d23d49e56f767..d8859b3e7fb7ffd084f9945d001017ec058f5405 100644 (file)
@@ -297,6 +297,35 @@ public:
   using replay_delta_ret = replay_delta_ertr::future<>;
   replay_delta_ret replay_delta(paddr_t record_base, const delta_info_t &delta);
 
+  /**
+   * init_cached_extents
+   *
+   * Calls passed lambda for each dirty cached block.  Intended for use
+   * after replay to allow lba_manager (or w/e) to read in any ancestor
+   * blocks.
+   */
+  using init_cached_extents_ertr = crimson::errorator<
+    crimson::ct_error::input_output_error>;
+  using init_cached_extents_ret = replay_delta_ertr::future<>;
+  template <typename F>
+  init_cached_extents_ret init_cached_extents(
+    Transaction &t,
+    F &&f)
+  {
+    std::vector<CachedExtentRef> dirty;
+    for (auto &e : extents) {
+      dirty.push_back(CachedExtentRef(&e));
+    }
+    return seastar::do_with(
+      std::forward<F>(f),
+      std::move(dirty),
+      [&t](auto &f, auto &refs) mutable {
+       return crimson::do_for_each(
+         refs,
+         [&t, &f](auto &e) { return f(t, e); });
+      });
+  }
+
   /**
    * print
    *
index e329eb551722ef27c7d1863173f55ab43f4a8730..1604aef86e7bf7f61af48055687bde1740ed8056 100644 (file)
@@ -117,6 +117,19 @@ public:
   virtual complete_transaction_ret complete_transaction(
     Transaction &t) = 0;
 
+  /**
+   * Should be called after replay on each cached extent.
+   * Implementation must initialize the LBAPin on any
+   * LogicalCachedExtent's and may also read in any dependent
+   * structures, etc.
+   */
+  using init_cached_extent_ertr = crimson::errorator<
+    crimson::ct_error::input_output_error>;
+  using init_cached_extent_ret = init_cached_extent_ertr::future<>;
+  virtual init_cached_extent_ret init_cached_extent(
+    Transaction &t,
+    CachedExtentRef e) = 0;
+
   virtual ~LBAManager() {}
 };
 using LBAManagerRef = std::unique_ptr<LBAManager>;
index e5ba69a0bc7b521784063610357588be271b6948..998ab256097f7ddacee79d0d148ef5534e104d3c 100644 (file)
@@ -239,6 +239,63 @@ BtreeLBAManager::complete_transaction(
   return complete_transaction_ertr::now();
 }
 
+BtreeLBAManager::init_cached_extent_ret BtreeLBAManager::init_cached_extent(
+  Transaction &t,
+  CachedExtentRef e)
+{
+  logger().debug("{}: {}", __func__, *e);
+  return get_root(t).safe_then(
+    [this, &t, e=std::move(e)](LBANodeRef root) mutable {
+      if (is_lba_node(*e)) {
+       auto lban = e->cast<LBANode>();
+       logger().debug("init_cached_extent: lba node, getting root");
+       return root->lookup(
+         op_context_t{cache, pin_set, t},
+         lban->get_node_meta().begin,
+         lban->get_node_meta().depth
+       ).safe_then([this, &t, e=std::move(e)](LBANodeRef c) {
+         if (c->get_paddr() == e->get_paddr()) {
+           assert(&*c == &*e);
+           logger().debug("init_cached_extent: {} initialized", *e);
+         } else {
+           // e is obsolete
+           logger().debug("init_cached_extent: {} obsolete", *e);
+           cache.retire_extent(t, e);
+         }
+         return init_cached_extent_ertr::now();
+       });
+      } else if (e->is_logical()) {
+       auto logn = e->cast<LogicalCachedExtent>();
+       return root->lookup_range(
+         op_context_t{cache, pin_set, t},
+         logn->get_laddr(),
+         logn->get_length()).safe_then(
+           [this, &t, logn=std::move(logn)](auto pins) {
+             if (pins.size() == 1) {
+               auto pin = std::move(pins.front());
+               pins.pop_front();
+               if (pin->get_paddr() == logn->get_paddr()) {
+                 logn->set_pin(std::move(pin));
+                 logger().debug("init_cached_extent: {} initialized", *logn);
+               } else {
+                 // paddr doesn't match, remapped, obsolete
+                 logger().debug("init_cached_extent: {} obsolete", *logn);
+                 cache.retire_extent(t, logn);
+               }
+             } else {
+               // set of extents changed, obsolete
+               logger().debug("init_cached_extent: {} obsolete", *logn);
+               cache.retire_extent(t, logn);
+             }
+             return init_cached_extent_ertr::now();
+           });
+      } else {
+       logger().debug("init_cached_extent: {} skipped", *e);
+       return init_cached_extent_ertr::now();
+      }
+    });
+}
+
 BtreeLBAManager::BtreeLBAManager(
   SegmentManager &segment_manager,
   Cache &cache)
index c32af3aab6a072be371d3907201a0ccabf6d294f..6463c91b014ea03aab0409e87618517c2ed45029 100644 (file)
@@ -83,6 +83,10 @@ public:
   complete_transaction_ret complete_transaction(
     Transaction &t) final;
 
+  init_cached_extent_ret init_cached_extent(
+    Transaction &t,
+    CachedExtentRef e) final;
+
 private:
   SegmentManager &segment_manager;
   Cache &cache;
index e1ebb25c74891cdbfdff054af9c44371bc81a719..68c7d23a672440506bfdcf65cf11bb1b6706081a 100644 (file)
@@ -58,6 +58,20 @@ struct LBANode : CachedExtent {
 
   virtual lba_node_meta_t get_node_meta() const = 0;
 
+  /**
+   * lookup
+   *
+   * Returns the node at the specified depth responsible
+   * for laddr
+   */
+  using lookup_ertr = crimson::errorator<
+    crimson::ct_error::input_output_error>;
+  using lookup_ret = lookup_ertr::future<LBANodeRef>;
+  virtual lookup_ret lookup(
+    op_context_t c,
+    laddr_t addr,
+    depth_t depth) = 0;
+
   /**
    * lookup_range
    *
index 2b01fd129d8a39348625fa80475a01d0e3e6aa1a..9f138b0c1ce074bdfbf661ae621cbfddcfdcc5f8 100644 (file)
@@ -26,6 +26,30 @@ std::ostream &LBAInternalNode::print_detail(std::ostream &out) const
             << ", meta=" << get_meta();
 }
 
+LBAInternalNode::lookup_ret LBAInternalNode::lookup(
+  op_context_t c,
+  laddr_t addr,
+  depth_t depth)
+{
+  auto meta = get_meta();
+  if (depth == get_meta().depth) {
+    return lookup_ret(
+      lookup_ertr::ready_future_marker{},
+      this);
+  }
+  assert(meta.begin <= addr);
+  assert(meta.end > addr);
+  auto [begin, end] = bound(addr, 0);
+  assert(begin == end + 1);
+  return get_lba_btree_extent(
+    c,
+    meta.depth,
+    begin->get_val(),
+    get_paddr()).safe_then([c, addr, depth](auto child) {
+      return child->lookup(c, addr, depth);
+    });
+}
+
 LBAInternalNode::lookup_range_ret LBAInternalNode::lookup_range(
   op_context_t c,
   laddr_t addr,
index 431a894ec8e9cebec0be4463877ce65bb999e2aa..02c5312c721c7baf7ae5e6533fb2c58c2996870e 100644 (file)
@@ -92,6 +92,8 @@ struct LBAInternalNode
     return is_mutation_pending() ? &delta_buffer : nullptr;
   }
 
+  lookup_ret lookup(op_context_t c, laddr_t addr, depth_t depth) final;
+
   lookup_range_ret lookup_range(
     op_context_t c,
     laddr_t addr,
@@ -339,6 +341,13 @@ struct LBALeafNode
     return is_mutation_pending() ? &delta_buffer : nullptr;
   }
 
+  lookup_ret lookup(op_context_t c, laddr_t addr, depth_t depth) final
+  {
+    return lookup_ret(
+      lookup_ertr::ready_future_marker{},
+      this);
+  }
+
   lookup_range_ret lookup_range(
     op_context_t c,
     laddr_t addr,
index c41dec000cf6a7b27b2d44c75586a64175335ce2..65f9377088ce74c28bb431d5f634574764c477ad 100644 (file)
@@ -66,6 +66,16 @@ TransactionManager::mount_ertr::future<> TransactionManager::mount()
     return cache.replay_delta(paddr, e);
   }).safe_then([this] {
     return journal.open_for_write();
+  }).safe_then([this] {
+    return seastar::do_with(
+      create_transaction(),
+      [this](auto &t) {
+       return cache.init_cached_extents(*t, [this](auto &t, auto &e) {
+         return lba_manager.init_cached_extent(t, e);
+       }).safe_then([this, &t]() mutable {
+         return submit_transaction(std::move(t));
+       });
+      });
   }).handle_error(
     mount_ertr::pass_further{},
     crimson::ct_error::all_same_way([] {