]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
crimson/os/seastore: add new interfaces to alloc multiple extents for a
authorXuehan Xu <xuxuehan@qianxin.com>
Fri, 19 Jan 2024 02:51:38 +0000 (10:51 +0800)
committerXuehan Xu <xuxuehan@qianxin.com>
Mon, 5 Feb 2024 08:27:50 +0000 (16:27 +0800)
single request

Signed-off-by: Xuehan Xu <xuxuehan@qianxin.com>
15 files changed:
src/crimson/os/seastore/async_cleaner.h
src/crimson/os/seastore/btree/fixed_kv_btree.h
src/crimson/os/seastore/btree/fixed_kv_node.h
src/crimson/os/seastore/cache.cc
src/crimson/os/seastore/cache.h
src/crimson/os/seastore/collection_manager/flat_collection_manager.cc
src/crimson/os/seastore/extent_placement_manager.h
src/crimson/os/seastore/omap_manager/btree/btree_omap_manager.cc
src/crimson/os/seastore/omap_manager/btree/omap_btree_node_impl.cc
src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager/seastore.h
src/crimson/os/seastore/transaction_manager.h
src/crimson/tools/store_nbd/tm_driver.cc
src/test/crimson/seastore/test_btree_lba_manager.cc
src/test/crimson/seastore/test_seastore_cache.cc
src/test/crimson/seastore/test_transaction_manager.cc

index fb8e03bb4bcf8ae1e2c75005ebfd351b5ab7a290..8f69d742d74169bab6f80484320c4d4652b49dee 100644 (file)
@@ -1695,6 +1695,14 @@ public:
     return paddr;
   }
 
+  std::list<alloc_paddr_result> alloc_paddrs(extent_len_t length) {
+    // TODO: implement allocation strategy (dirty metadata and multiple devices)
+    auto rbs = rb_group->get_rb_managers();
+    auto ret = rbs[0]->alloc_extents(length);
+    stats.used_bytes += length;
+    return ret;
+  }
+
   size_t get_total_bytes() const {
     auto rbs = rb_group->get_rb_managers();
     size_t total = 0;
index a2a97e30a50365cb9ac17146cd6d78e38046cd9e..b91a4e2d07bf911adc7e3f0c7fb8750ec41c77d3 100644 (file)
@@ -356,7 +356,7 @@ public:
   using mkfs_ret = phy_tree_root_t;
   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>(
+    auto root_leaf = c.cache.template alloc_new_non_data_extent<leaf_node_t>(
       c.trans,
       node_size,
       placement_hint_t::HOT,
@@ -1022,7 +1022,7 @@ public:
     assert(is_lba_backref_node(e->get_type()));
     
     auto do_rewrite = [&](auto &fixed_kv_extent) {
-      auto n_fixed_kv_extent = c.cache.template alloc_new_extent<
+      auto n_fixed_kv_extent = c.cache.template alloc_new_non_data_extent<
         std::remove_reference_t<decltype(fixed_kv_extent)>
         >(
         c.trans,
@@ -1781,7 +1781,7 @@ private:
     SUBTRACET(seastore_fixedkv_tree, "split_from {}, depth {}", c.trans, split_from, iter.get_depth());
 
     if (split_from == iter.get_depth()) {
-      auto nroot = c.cache.template alloc_new_extent<internal_node_t>(
+      auto nroot = c.cache.template alloc_new_non_data_extent<internal_node_t>(
         c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
       fixed_kv_node_meta_t<node_key_t> meta{
         min_max_t<node_key_t>::min, min_max_t<node_key_t>::max, iter.get_depth() + 1};
index 4d32475ee24de133afaf2e971a902ed7676562c4..6ad55e3b9b32f98813ea7740c9d0b7be5be12be6 100644 (file)
@@ -757,9 +757,9 @@ struct FixedKVInternalNode
 
   std::tuple<Ref, Ref, NODE_KEY>
   make_split_children(op_context_t<NODE_KEY> c) {
-    auto left = c.cache.template alloc_new_extent<node_type_t>(
+    auto left = c.cache.template alloc_new_non_data_extent<node_type_t>(
       c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
-    auto right = c.cache.template alloc_new_extent<node_type_t>(
+    auto right = c.cache.template alloc_new_non_data_extent<node_type_t>(
       c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
     this->split_child_ptrs(*left, *right);
     auto pivot = this->split_into(*left, *right);
@@ -774,7 +774,7 @@ struct FixedKVInternalNode
   Ref make_full_merge(
     op_context_t<NODE_KEY> c,
     Ref &right) {
-    auto replacement = c.cache.template alloc_new_extent<node_type_t>(
+    auto replacement = c.cache.template alloc_new_non_data_extent<node_type_t>(
       c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
     replacement->merge_child_ptrs(*this, *right);
     replacement->merge_from(*this, *right->template cast<node_type_t>());
@@ -789,9 +789,9 @@ struct FixedKVInternalNode
     bool prefer_left) {
     ceph_assert(_right->get_type() == this->get_type());
     auto &right = *_right->template cast<node_type_t>();
-    auto replacement_left = c.cache.template alloc_new_extent<node_type_t>(
+    auto replacement_left = c.cache.template alloc_new_non_data_extent<node_type_t>(
       c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
-    auto replacement_right = c.cache.template alloc_new_extent<node_type_t>(
+    auto replacement_right = c.cache.template alloc_new_non_data_extent<node_type_t>(
       c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
 
     auto pivot = this->balance_into_new_nodes(
@@ -1127,9 +1127,9 @@ struct FixedKVLeafNode
 
   std::tuple<Ref, Ref, NODE_KEY>
   make_split_children(op_context_t<NODE_KEY> c) {
-    auto left = c.cache.template alloc_new_extent<node_type_t>(
+    auto left = c.cache.template alloc_new_non_data_extent<node_type_t>(
       c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
-    auto right = c.cache.template alloc_new_extent<node_type_t>(
+    auto right = c.cache.template alloc_new_non_data_extent<node_type_t>(
       c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
     if constexpr (has_children) {
       this->split_child_ptrs(*left, *right);
@@ -1146,7 +1146,7 @@ struct FixedKVLeafNode
   Ref make_full_merge(
     op_context_t<NODE_KEY> c,
     Ref &right) {
-    auto replacement = c.cache.template alloc_new_extent<node_type_t>(
+    auto replacement = c.cache.template alloc_new_non_data_extent<node_type_t>(
       c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
     if constexpr (has_children) {
       replacement->merge_child_ptrs(*this, *right);
@@ -1163,9 +1163,9 @@ struct FixedKVLeafNode
     bool prefer_left) {
     ceph_assert(_right->get_type() == this->get_type());
     auto &right = *_right->template cast<node_type_t>();
-    auto replacement_left = c.cache.template alloc_new_extent<node_type_t>(
+    auto replacement_left = c.cache.template alloc_new_non_data_extent<node_type_t>(
       c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
-    auto replacement_right = c.cache.template alloc_new_extent<node_type_t>(
+    auto replacement_right = c.cache.template alloc_new_non_data_extent<node_type_t>(
       c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
 
     auto pivot = this->balance_into_new_nodes(
index b81fe62906c7b3eda2ea5556074a26feb6476599..0e5eeb96c17e218b1e07b295a5dbd87d85892796 100644 (file)
@@ -962,32 +962,33 @@ CachedExtentRef Cache::alloc_new_extent_by_type(
   LOG_PREFIX(Cache::alloc_new_extent_by_type);
   SUBDEBUGT(seastore_cache, "allocate {} {}B, hint={}, gen={}",
             t, type, length, hint, rewrite_gen_printer_t{gen});
+  ceph_assert(get_extent_category(type) == data_category_t::METADATA);
   switch (type) {
   case extent_types_t::ROOT:
     ceph_assert(0 == "ROOT is never directly alloc'd");
     return CachedExtentRef();
   case extent_types_t::LADDR_INTERNAL:
-    return alloc_new_extent<lba_manager::btree::LBAInternalNode>(t, length, hint, gen);
+    return alloc_new_non_data_extent<lba_manager::btree::LBAInternalNode>(t, length, hint, gen);
   case extent_types_t::LADDR_LEAF:
-    return alloc_new_extent<lba_manager::btree::LBALeafNode>(
+    return alloc_new_non_data_extent<lba_manager::btree::LBALeafNode>(
       t, length, hint, gen);
   case extent_types_t::ONODE_BLOCK_STAGED:
-    return alloc_new_extent<onode::SeastoreNodeExtent>(t, length, hint, gen);
+    return alloc_new_non_data_extent<onode::SeastoreNodeExtent>(
+      t, length, hint, gen);
   case extent_types_t::OMAP_INNER:
-    return alloc_new_extent<omap_manager::OMapInnerNode>(t, length, hint, gen);
+    return alloc_new_non_data_extent<omap_manager::OMapInnerNode>(
+      t, length, hint, gen);
   case extent_types_t::OMAP_LEAF:
-    return alloc_new_extent<omap_manager::OMapLeafNode>(t, length, hint, gen);
+    return alloc_new_non_data_extent<omap_manager::OMapLeafNode>(
+      t, length, hint, gen);
   case extent_types_t::COLL_BLOCK:
-    return alloc_new_extent<collection_manager::CollectionNode>(t, length, hint, gen);
-  case extent_types_t::OBJECT_DATA_BLOCK:
-    return alloc_new_extent<ObjectDataBlock>(t, length, hint, gen);
+    return alloc_new_non_data_extent<collection_manager::CollectionNode>(
+      t, length, hint, gen);
   case extent_types_t::RETIRED_PLACEHOLDER:
     ceph_assert(0 == "impossible");
     return CachedExtentRef();
-  case extent_types_t::TEST_BLOCK:
-    return alloc_new_extent<TestBlock>(t, length, hint, gen);
   case extent_types_t::TEST_BLOCK_PHYSICAL:
-    return alloc_new_extent<TestBlockPhysical>(t, length, hint, gen);
+    return alloc_new_non_data_extent<TestBlockPhysical>(t, length, hint, gen);
   case extent_types_t::NONE: {
     ceph_assert(0 == "NONE is an invalid extent type");
     return CachedExtentRef();
@@ -998,6 +999,38 @@ CachedExtentRef Cache::alloc_new_extent_by_type(
   }
 }
 
+std::vector<CachedExtentRef> Cache::alloc_new_data_extents_by_type(
+  Transaction &t,        ///< [in, out] current transaction
+  extent_types_t type,   ///< [in] type tag
+  extent_len_t length,   ///< [in] length
+  placement_hint_t hint, ///< [in] user hint
+  rewrite_gen_t gen      ///< [in] rewrite generation
+)
+{
+  LOG_PREFIX(Cache::alloc_new_data_extents_by_type);
+  SUBDEBUGT(seastore_cache, "allocate {} {}B, hint={}, gen={}",
+            t, type, length, hint, rewrite_gen_printer_t{gen});
+  ceph_assert(get_extent_category(type) == data_category_t::DATA);
+  std::vector<CachedExtentRef> res;
+  switch (type) {
+  case extent_types_t::OBJECT_DATA_BLOCK:
+    {
+      auto extents = alloc_new_data_extents<ObjectDataBlock>(t, length, hint, gen);
+      res.insert(res.begin(), extents.begin(), extents.end());
+    }
+    return res;
+  case extent_types_t::TEST_BLOCK:
+    {
+      auto extents = alloc_new_data_extents<TestBlock>(t, length, hint, gen);
+      res.insert(res.begin(), extents.begin(), extents.end());
+    }
+    return res;
+  default:
+    ceph_assert(0 == "impossible");
+    return res;
+  }
+}
+
 CachedExtentRef Cache::duplicate_for_write(
   Transaction &t,
   CachedExtentRef i) {
index 0f32bfe87e66b547a0a00929013635ec6929bea6..a6aeb357148f443d2b4da510ca237bc6c1338fb6 100644 (file)
@@ -859,13 +859,13 @@ public:
   }
 
   /**
-   * alloc_new_extent
+   * alloc_new_non_data_extent
    *
    * Allocates a fresh extent. if delayed is true, addr will be alloc'd later.
    * Note that epaddr can only be fed by the btree lba unittest for now
    */
   template <typename T>
-  TCachedExtentRef<T> alloc_new_extent(
+  TCachedExtentRef<T> alloc_new_non_data_extent(
     Transaction &t,         ///< [in, out] current transaction
     extent_len_t length,    ///< [in] length
     placement_hint_t hint,  ///< [in] user hint
@@ -876,13 +876,13 @@ public:
     rewrite_gen_t gen
 #endif
   ) {
-    LOG_PREFIX(Cache::alloc_new_extent);
+    LOG_PREFIX(Cache::alloc_new_non_data_extent);
     SUBTRACET(seastore_cache, "allocate {} {}B, hint={}, gen={}",
               t, T::TYPE, length, hint, rewrite_gen_printer_t{gen});
 #ifdef UNIT_TESTS_BUILT
-    auto result = epm.alloc_new_extent(t, T::TYPE, length, hint, gen, epaddr);
+    auto result = epm.alloc_new_non_data_extent(t, T::TYPE, length, hint, gen, epaddr);
 #else
-    auto result = epm.alloc_new_extent(t, T::TYPE, length, hint, gen);
+    auto result = epm.alloc_new_non_data_extent(t, T::TYPE, length, hint, gen);
 #endif
     auto ret = CachedExtent::make_cached_extent_ref<T>(std::move(result.bp));
     ret->init(CachedExtent::extent_state_t::INITIAL_WRITE_PENDING,
@@ -897,6 +897,49 @@ public:
               hint, rewrite_gen_printer_t{result.gen}, *ret);
     return ret;
   }
+  /**
+   * alloc_new_data_extents
+   *
+   * Allocates a fresh extent. if delayed is true, addr will be alloc'd later.
+   * Note that epaddr can only be fed by the btree lba unittest for now
+   */
+  template <typename T>
+  std::vector<TCachedExtentRef<T>> alloc_new_data_extents(
+    Transaction &t,         ///< [in, out] current transaction
+    extent_len_t length,    ///< [in] length
+    placement_hint_t hint,  ///< [in] user hint
+#ifdef UNIT_TESTS_BUILT
+    rewrite_gen_t gen,      ///< [in] rewrite generation
+    std::optional<paddr_t> epaddr = std::nullopt ///< [in] paddr fed by callers
+#else
+    rewrite_gen_t gen
+#endif
+  ) {
+    LOG_PREFIX(Cache::alloc_new_data_extents);
+    SUBTRACET(seastore_cache, "allocate {} {}B, hint={}, gen={}",
+              t, T::TYPE, length, hint, rewrite_gen_printer_t{gen});
+#ifdef UNIT_TESTS_BUILT
+    auto results = epm.alloc_new_data_extents(t, T::TYPE, length, hint, gen, epaddr);
+#else
+    auto results = epm.alloc_new_data_extents(t, T::TYPE, length, hint, gen);
+#endif
+    std::vector<TCachedExtentRef<T>> extents;
+    for (auto &result : results) {
+      auto ret = CachedExtent::make_cached_extent_ref<T>(std::move(result.bp));
+      ret->init(CachedExtent::extent_state_t::INITIAL_WRITE_PENDING,
+                result.paddr,
+                hint,
+                result.gen,
+                t.get_trans_id());
+      t.add_fresh_extent(ret);
+      SUBDEBUGT(seastore_cache,
+                "allocated {} {}B extent at {}, hint={}, gen={} -- {}",
+                t, T::TYPE, length, result.paddr,
+                hint, rewrite_gen_printer_t{result.gen}, *ret);
+      extents.emplace_back(std::move(ret));
+    }
+    return extents;
+  }
 
   /**
    * alloc_remapped_extent
@@ -953,6 +996,19 @@ public:
     rewrite_gen_t gen      ///< [in] rewrite generation
     );
 
+  /**
+   * alloc_new_extent
+   *
+   * Allocates a fresh extent.  addr will be relative until commit.
+   */
+  std::vector<CachedExtentRef> alloc_new_data_extents_by_type(
+    Transaction &t,        ///< [in, out] current transaction
+    extent_types_t type,   ///< [in] type tag
+    extent_len_t length,   ///< [in] length
+    placement_hint_t hint, ///< [in] user hint
+    rewrite_gen_t gen      ///< [in] rewrite generation
+    );
+
   /**
    * Allocates mutable buffer from extent_set on offset~len
    *
index 3c65ed0e2c185de0f681d662b9b29f2b1a67ebd7..81353655694ee98912b338b7ff79c018a805fbdd 100644 (file)
@@ -30,7 +30,7 @@ FlatCollectionManager::mkfs(Transaction &t)
 {
 
   logger().debug("FlatCollectionManager: {}", __func__);
-  return tm.alloc_extent<CollectionNode>(
+  return tm.alloc_non_data_extent<CollectionNode>(
     t, L_ADDR_MIN, MIN_FLAT_BLOCK_SIZE
   ).si_then([](auto&& root_extent) {
     coll_root_t coll_root = coll_root_t(
@@ -74,7 +74,7 @@ FlatCollectionManager::create(coll_root_t &coll_root, Transaction &t,
        // TODO return error probably, but such a nonsensically large number of
        // collections would create a ton of other problems as well
        assert(new_size < MAX_FLAT_BLOCK_SIZE);
-        return tm.alloc_extent<CollectionNode>(
+        return tm.alloc_non_data_extent<CollectionNode>(
          t, L_ADDR_MIN, new_size
        ).si_then([=, this, &coll_root, &t] (auto &&root_extent) {
           coll_root.update(root_extent->get_laddr(), root_extent->get_length());
index 371b49e07414766b96fb706b036d8362c5eefeae..70dbc428d10bf405e7947243e1fb21da13726d5b 100644 (file)
@@ -35,6 +35,8 @@ public:
 
   virtual paddr_t alloc_paddr(extent_len_t length) = 0;
 
+  virtual std::list<alloc_paddr_result> alloc_paddrs(extent_len_t length) = 0;
+
   using alloc_write_ertr = base_ertr;
   using alloc_write_iertr = trans_iertr<alloc_write_ertr>;
   virtual alloc_write_iertr::future<> alloc_write_ool_extents(
@@ -82,6 +84,10 @@ public:
     return make_delayed_temp_paddr(0);
   }
 
+  std::list<alloc_paddr_result> alloc_paddrs(extent_len_t length) final {
+    return {alloc_paddr_result{make_delayed_temp_paddr(0), length}};
+  }
+
   bool can_inplace_rewrite(Transaction& t,
     CachedExtentRef extent) final {
     return false;
@@ -130,6 +136,11 @@ public:
     return rb_cleaner->alloc_paddr(length);
   }
 
+  std::list<alloc_paddr_result> alloc_paddrs(extent_len_t length) final {
+    assert(rb_cleaner);
+    return rb_cleaner->alloc_paddrs(length);
+  }
+
   bool can_inplace_rewrite(Transaction& t,
     CachedExtentRef extent) final {
     if (!extent->is_dirty()) {
@@ -268,7 +279,7 @@ public:
     bufferptr bp;
     rewrite_gen_t gen;
   };
-  alloc_result_t alloc_new_extent(
+  alloc_result_t alloc_new_non_data_extent(
     Transaction& t,
     extent_types_t type,
     extent_len_t length,
@@ -302,19 +313,64 @@ public:
     if (gen == INLINE_GENERATION) {
 #endif
       addr = make_record_relative_paddr(0);
-    } else if (category == data_category_t::DATA) {
-      assert(data_writers_by_gen[generation_to_writer(gen)]);
-      addr = data_writers_by_gen[
-         generation_to_writer(gen)]->alloc_paddr(length);
     } else {
       assert(category == data_category_t::METADATA);
       assert(md_writers_by_gen[generation_to_writer(gen)]);
       addr = md_writers_by_gen[
          generation_to_writer(gen)]->alloc_paddr(length);
     }
+    assert(!(category == data_category_t::DATA));
     return {addr, std::move(bp), gen};
   }
 
+  std::list<alloc_result_t> alloc_new_data_extents(
+    Transaction& t,
+    extent_types_t type,
+    extent_len_t length,
+    placement_hint_t hint,
+#ifdef UNIT_TESTS_BUILT
+    rewrite_gen_t gen,
+    std::optional<paddr_t> external_paddr = std::nullopt
+#else
+    rewrite_gen_t gen
+#endif
+  ) {
+    assert(hint < placement_hint_t::NUM_HINTS);
+    assert(is_target_rewrite_generation(gen));
+    assert(gen == INIT_GENERATION || hint == placement_hint_t::REWRITE);
+
+    data_category_t category = get_extent_category(type);
+    gen = adjust_generation(category, type, hint, gen);
+    assert(gen != INLINE_GENERATION);
+
+    // XXX: bp might be extended to point to different memory (e.g. PMem)
+    // according to the allocator.
+    std::list<alloc_result_t> allocs;
+#ifdef UNIT_TESTS_BUILT
+    if (unlikely(external_paddr.has_value())) {
+      assert(external_paddr->is_fake());
+      auto bp = ceph::bufferptr(
+        buffer::create_page_aligned(length));
+      bp.zero();
+      allocs.emplace_back(alloc_result_t{*external_paddr, std::move(bp), gen});
+    } else {
+#else
+    {
+#endif
+      assert(category == data_category_t::DATA);
+      assert(data_writers_by_gen[generation_to_writer(gen)]);
+      auto addrs = data_writers_by_gen[
+          generation_to_writer(gen)]->alloc_paddrs(length);
+      for (auto &ext : addrs) {
+        auto bp = ceph::bufferptr(
+          buffer::create_page_aligned(ext.len));
+        bp.zero();
+        allocs.emplace_back(alloc_result_t{ext.start, std::move(bp), gen});
+      }
+    }
+    return allocs;
+  }
+
   /**
    * dispatch_result_t
    *
index 77dc270a53234df6df20322f9fd7db3a1c2ed2eb..c182965764eecd10b11b8ff70bac83976ec6591d 100644 (file)
@@ -22,7 +22,7 @@ BtreeOMapManager::initialize_omap(Transaction &t, laddr_t hint)
 {
   LOG_PREFIX(BtreeOMapManager::initialize_omap);
   DEBUGT("hint: {}", t, hint);
-  return tm.alloc_extent<OMapLeafNode>(t, hint, OMAP_LEAF_BLOCK_SIZE)
+  return tm.alloc_non_data_extent<OMapLeafNode>(t, hint, OMAP_LEAF_BLOCK_SIZE)
     .si_then([hint, &t](auto&& root_extent) {
       root_extent->set_size(0);
       omap_node_meta_t meta{1};
@@ -51,7 +51,7 @@ BtreeOMapManager::handle_root_split(
 {
   LOG_PREFIX(BtreeOMapManager::handle_root_split);
   DEBUGT("{}", oc.t, omap_root);
-  return oc.tm.alloc_extent<OMapInnerNode>(oc.t, omap_root.hint,
+  return oc.tm.alloc_non_data_extent<OMapInnerNode>(oc.t, omap_root.hint,
                                            OMAP_INNER_BLOCK_SIZE)
     .si_then([&omap_root, mresult, oc](auto&& nroot) -> handle_root_split_ret {
     auto [left, right, pivot] = *(mresult.split_tuple);
index 96115f13237c2c226e6c84ac7ccf75e992148757..c932f6d590c10e5833e3134560e6e856672a2c8a 100644 (file)
@@ -346,7 +346,7 @@ OMapInnerNode::make_full_merge(omap_context_t oc, OMapNodeRef right)
 {
   LOG_PREFIX(OMapInnerNode::make_full_merge);
   DEBUGT("", oc.t);
-  return oc.tm.alloc_extent<OMapInnerNode>(oc.t, oc.hint,
+  return oc.tm.alloc_non_data_extent<OMapInnerNode>(oc.t, oc.hint,
     OMAP_INNER_BLOCK_SIZE)
     .si_then([this, right] (auto &&replacement) {
       replacement->merge_from(*this, *right->cast<OMapInnerNode>());
@@ -679,7 +679,7 @@ OMapLeafNode::make_full_merge(omap_context_t oc, OMapNodeRef right)
   ceph_assert(right->get_type() == TYPE);
   LOG_PREFIX(OMapLeafNode::make_full_merge);
   DEBUGT("this: {}", oc.t, *this);
-  return oc.tm.alloc_extent<OMapLeafNode>(oc.t, oc.hint, OMAP_LEAF_BLOCK_SIZE)
+  return oc.tm.alloc_non_data_extent<OMapLeafNode>(oc.t, oc.hint, OMAP_LEAF_BLOCK_SIZE)
     .si_then([this, right] (auto &&replacement) {
       replacement->merge_from(*this, *right->cast<OMapLeafNode>());
       return full_merge_ret(
index c12e583bd566c55d876332cef50818fc2effccf4..cff67f9cf51f8eac0c2b3bf104f08343b4682f85 100644 (file)
@@ -131,7 +131,7 @@ class SeastoreNodeExtentManager final: public TransactionManagerHandle {
         return alloc_iertr::make_ready_future<NodeExtentRef>();
       }
     }
-    return tm.alloc_extent<SeastoreNodeExtent>(t, hint, len
+    return tm.alloc_non_data_extent<SeastoreNodeExtent>(t, hint, len
     ).si_then([len, &t](auto extent) {
       SUBDEBUGT(seastore_onode,
           "allocated {}B at {:#x} -- {}",
index 2bfed6ac9f66e5897c70af33be701e34e6b4a03c..4bacd78fe60b473d0997300416967214d89f3616 100644 (file)
@@ -279,7 +279,7 @@ public:
     std::vector<laddr_t> offsets);
 
   /**
-   * alloc_extent
+   * alloc_non_data_extent
    *
    * Allocates a new block of type T with the minimum lba range of size len
    * greater than laddr_hint.
@@ -288,16 +288,16 @@ public:
   template <typename T>
   using alloc_extent_ret = alloc_extent_iertr::future<TCachedExtentRef<T>>;
   template <typename T>
-  alloc_extent_ret<T> alloc_extent(
+  alloc_extent_ret<T> alloc_non_data_extent(
     Transaction &t,
     laddr_t laddr_hint,
     extent_len_t len,
     placement_hint_t placement_hint = placement_hint_t::HOT) {
-    LOG_PREFIX(TransactionManager::alloc_extent);
+    LOG_PREFIX(TransactionManager::alloc_non_data_extent);
     SUBTRACET(seastore_tm, "{} len={}, placement_hint={}, laddr_hint={}",
               t, T::TYPE, len, placement_hint, laddr_hint);
     ceph_assert(is_aligned(laddr_hint, epm->get_block_size()));
-    auto ext = cache->alloc_new_extent<T>(
+    auto ext = cache->alloc_new_non_data_extent<T>(
       t,
       len,
       placement_hint,
@@ -309,13 +309,64 @@ public:
       ext->get_paddr(),
       *ext
     ).si_then([ext=std::move(ext), laddr_hint, &t](auto &&) mutable {
-      LOG_PREFIX(TransactionManager::alloc_extent);
+      LOG_PREFIX(TransactionManager::alloc_non_data_extent);
       SUBDEBUGT(seastore_tm, "new extent: {}, laddr_hint: {}", t, *ext, laddr_hint);
       return alloc_extent_iertr::make_ready_future<TCachedExtentRef<T>>(
        std::move(ext));
     });
   }
 
+  /**
+   * alloc_data_extents
+   *
+   * Allocates a new block of type T with the minimum lba range of size len
+   * greater than laddr_hint.
+   */
+  using alloc_extents_iertr = alloc_extent_iertr;
+  template <typename T>
+  using alloc_extents_ret = alloc_extents_iertr::future<
+    std::vector<TCachedExtentRef<T>>>;
+  template <typename T>
+  alloc_extents_ret<T> alloc_data_extents(
+    Transaction &t,
+    laddr_t laddr_hint,
+    extent_len_t len,
+    placement_hint_t placement_hint = placement_hint_t::HOT) {
+    LOG_PREFIX(TransactionManager::alloc_data_extents);
+    SUBTRACET(seastore_tm, "{} len={}, placement_hint={}, laddr_hint={}",
+              t, T::TYPE, len, placement_hint, laddr_hint);
+    ceph_assert(is_aligned(laddr_hint, epm->get_block_size()));
+    auto exts = cache->alloc_new_data_extents<T>(
+      t,
+      len,
+      placement_hint,
+      INIT_GENERATION);
+    return seastar::do_with(
+      std::move(exts),
+      laddr_hint,
+      [this, &t](auto &exts, auto &laddr_hint) {
+      return trans_intr::do_for_each(
+        exts,
+        [this, &t, &laddr_hint](auto &ext) {
+        return lba_manager->alloc_extent(
+          t,
+          laddr_hint,
+          ext->get_length(),
+          ext->get_paddr(),
+          *ext
+        ).si_then([&ext, &laddr_hint, &t](auto &&) mutable {
+          LOG_PREFIX(TransactionManager::alloc_extents);
+          SUBDEBUGT(seastore_tm, "new extent: {}, laddr_hint: {}", t, *ext, laddr_hint);
+          laddr_hint += ext->get_length();
+          return alloc_extent_iertr::now();
+        });
+      }).si_then([&exts] {
+        return alloc_extent_iertr::make_ready_future<
+          std::vector<TCachedExtentRef<T>>>(std::move(exts));
+      });
+    });
+  }
+
   template <typename T>
   read_extent_ret<T> get_mutable_extent_by_laddr(Transaction &t, laddr_t laddr, extent_len_t len) {
     return get_pin(t, laddr
@@ -540,7 +591,6 @@ public:
    *
    * allocates more than one new blocks of type T.
    */
-   using alloc_extents_iertr = alloc_extent_iertr;
    template<class T>
    alloc_extents_iertr::future<std::vector<TCachedExtentRef<T>>>
    alloc_extents(
@@ -557,7 +607,7 @@ public:
                        boost::make_counting_iterator(0),
                        boost::make_counting_iterator(num),
          [this, &t, len, hint, &extents] (auto i) {
-         return alloc_extent<T>(t, hint, len).si_then(
+         return alloc_non_data_extent<T>(t, hint, len).si_then(
            [&extents](auto &&node) {
            extents.push_back(node);
          });
index 62891aa864c8797c27d5fb946b97fbe7e10e67d7..01658c4f0637f53474c212a52ee63693be3d3c9b 100644 (file)
@@ -33,12 +33,20 @@ seastar::future<> TMDriver::write(
           crimson::ct_error::pass_further_all{}
         ).si_then([this, offset, &t, &ptr] {
           logger().debug("dec_ref complete");
-          return tm->alloc_extent<TestBlock>(t, offset, ptr.length());
-        }).si_then([this, offset, &t, &ptr](auto ext) {
-          boost::ignore_unused(offset);  // avoid clang warning;
-          assert(ext->get_laddr() == (size_t)offset);
-          assert(ext->get_bptr().length() == ptr.length());
-          ext->get_bptr().swap(ptr);
+          return tm->alloc_data_extents<TestBlock>(t, offset, ptr.length());
+        }).si_then([this, offset, &t, &ptr](auto extents) mutable {
+         boost::ignore_unused(offset);  // avoid clang warning;
+         auto off = offset;
+         auto left = ptr.length();
+         size_t written = 0;
+         for (auto &ext : extents) {
+           assert(ext->get_laddr() == (size_t)off);
+           assert(ext->get_bptr().length() <= left);
+           ptr.copy_out(written, ext->get_length(), ext->get_bptr().c_str());
+           off += ext->get_length();
+           left -= ext->get_length();
+         }
+         assert(!left);
           logger().debug("submitting transaction");
           return tm->submit_transaction(t);
         });
index f18c3ac670ad66b596bfdaf0056b1e89f6bf9467..5199f963dc95997c44a9e8919f9097c772e72b74 100644 (file)
@@ -262,12 +262,14 @@ struct lba_btree_test : btree_test_base {
     ceph_assert(check.count(addr) == 0);
     check.emplace(addr, get_map_val(len));
     lba_btree_update([=, this](auto &btree, auto &t) {
-      auto extent = cache->alloc_new_extent<TestBlock>(
+      auto extents = cache->alloc_new_data_extents<TestBlock>(
          t,
          TestBlock::SIZE,
          placement_hint_t::HOT,
          0,
          get_paddr());
+      assert(extents.size() == 1);
+      auto extent = extents.front();
       return btree.insert(
        get_op_context(t), addr, get_map_val(len), extent.get()
       ).si_then([addr, extent](auto p){
@@ -374,7 +376,7 @@ struct btree_lba_manager_test : btree_test_base {
       test_lba_mappings
     };
     if (create_fake_extent) {
-      cache->alloc_new_extent<TestBlockPhysical>(
+      cache->alloc_new_non_data_extent<TestBlockPhysical>(
           *t.t,
           TestBlockPhysical::SIZE,
           placement_hint_t::HOT,
@@ -425,12 +427,14 @@ struct btree_lba_manager_test : btree_test_base {
     auto ret = with_trans_intr(
       *t.t,
       [=, this](auto &t) {
-       auto extent = cache->alloc_new_extent<TestBlock>(
+       auto extents = cache->alloc_new_data_extents<TestBlock>(
            t,
            TestBlock::SIZE,
            placement_hint_t::HOT,
            0,
            get_paddr());
+       assert(extents.size() == 1);
+       auto extent = extents.front();
        return lba_manager->alloc_extent(
          t, hint, len, extent->get_paddr(), *extent);
       }).unsafe_get0();
index b249d27e4617de5b88d238d914665fe47b5c98e4..66c9899538c853e8099ad5b2ddb8e8c8fae3f915 100644 (file)
@@ -129,7 +129,7 @@ TEST_F(cache_test_t, test_addr_fixup)
     int csum = 0;
     {
       auto t = get_transaction();
-      auto extent = cache->alloc_new_extent<TestBlockPhysical>(
+      auto extent = cache->alloc_new_non_data_extent<TestBlockPhysical>(
        *t,
        TestBlockPhysical::SIZE,
        placement_hint_t::HOT,
@@ -160,7 +160,7 @@ TEST_F(cache_test_t, test_dirty_extent)
     {
       // write out initial test block
       auto t = get_transaction();
-      auto extent = cache->alloc_new_extent<TestBlockPhysical>(
+      auto extent = cache->alloc_new_non_data_extent<TestBlockPhysical>(
        *t,
        TestBlockPhysical::SIZE,
        placement_hint_t::HOT,
index dfe599177056e13191705d96c1b881ee9bab3e4d..c33c9ffce4bc50ca2098d8f36054b6c3afa2ca28 100644 (file)
@@ -386,9 +386,11 @@ struct transaction_manager_test_t :
     laddr_t hint,
     extent_len_t len,
     char contents) {
-    auto extent = with_trans_intr(*(t.t), [&](auto& trans) {
-      return tm->alloc_extent<TestBlock>(trans, hint, len);
+    auto extents = with_trans_intr(*(t.t), [&](auto& trans) {
+      return tm->alloc_data_extents<TestBlock>(trans, hint, len);
     }).unsafe_get0();
+    assert(extents.size() == 1);
+    auto extent = extents.front();
     extent->set_contents(contents);
     EXPECT_FALSE(test_mappings.contains(extent->get_laddr(), t.mapping_delta));
     EXPECT_EQ(len, extent->get_length());
@@ -723,9 +725,11 @@ struct transaction_manager_test_t :
                boost::make_counting_iterator(0),
                boost::make_counting_iterator(num),
                [&t, this, size](auto) {
-                 return tm->alloc_extent<TestBlock>(
+                 return tm->alloc_data_extents<TestBlock>(
                    *(t.t), L_ADDR_MIN, size
-                 ).si_then([&t, this, size](auto extent) {
+                 ).si_then([&t, this, size](auto extents) {
+                   assert(extents.size() == 1);
+                   auto extent = extents.front();
                    extent->set_contents(get_random_contents());
                    EXPECT_FALSE(
                      test_mappings.contains(extent->get_laddr(), t.mapping_delta));
@@ -1110,9 +1114,11 @@ struct transaction_manager_test_t :
             o_len - new_offset - new_len)
         }
       ).si_then([this, new_offset, new_len, o_laddr, &t, &bl](auto ret) {
-        return tm->alloc_extent<TestBlock>(t, o_laddr + new_offset, new_len
+        return tm->alloc_data_extents<TestBlock>(t, o_laddr + new_offset, new_len
         ).si_then([this, ret = std::move(ret), new_len,
-                   new_offset, o_laddr, &t, &bl](auto ext) mutable {
+                   new_offset, o_laddr, &t, &bl](auto extents) mutable {
+         assert(extents.size() == 1);
+         auto ext = extents.front();
           ceph_assert(ret.size() == 2);
           auto iter = bl.cbegin();
           iter.copy(new_len, ext->get_bptr().c_str());
@@ -1141,9 +1147,11 @@ struct transaction_manager_test_t :
             o_len - new_offset - new_len)
         }
       ).si_then([this, new_offset, new_len, o_laddr, &t, &bl](auto ret) {
-        return tm->alloc_extent<TestBlock>(t, o_laddr + new_offset, new_len
+        return tm->alloc_data_extents<TestBlock>(t, o_laddr + new_offset, new_len
         ).si_then([this, ret = std::move(ret), new_offset, new_len,
-                   o_laddr, &t, &bl](auto ext) mutable {
+                   o_laddr, &t, &bl](auto extents) mutable {
+         assert(extents.size() == 1);
+         auto ext = extents.front();
           ceph_assert(ret.size() == 1);
           auto iter = bl.cbegin();
           iter.copy(new_len, ext->get_bptr().c_str());
@@ -1167,9 +1175,11 @@ struct transaction_manager_test_t :
             new_offset)
         }
       ).si_then([this, new_offset, new_len, o_laddr, &t, &bl](auto ret) {
-        return tm->alloc_extent<TestBlock>(t, o_laddr + new_offset, new_len
+        return tm->alloc_data_extents<TestBlock>(t, o_laddr + new_offset, new_len
         ).si_then([this, ret = std::move(ret), new_len, o_laddr, &t, &bl]
-          (auto ext) mutable {
+          (auto extents) mutable {
+         assert(extents.size() == 1);
+         auto ext = extents.front();
           ceph_assert(ret.size() == 1);
           auto iter = bl.cbegin();
           iter.copy(new_len, ext->get_bptr().c_str());