]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/os/seastore/lba_manager: add the alloc_extents interface
authorXuehan Xu <xuxuehan@qianxin.com>
Wed, 21 Feb 2024 06:52:41 +0000 (14:52 +0800)
committerXuehan Xu <xuxuehan@qianxin.com>
Mon, 22 Apr 2024 03:26:45 +0000 (11:26 +0800)
This is necessary because continuous data may be splitted into multiple
extents if the size of each data extent is constrained

Signed-off-by: Xuehan Xu <xuxuehan@qianxin.com>
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

index 8794bc9405d5b66576db448a78d7cd7bd4ee23db..e46298dd44f3dfc0ded70db72a19cbbfeb8f3f41 100644 (file)
@@ -88,6 +88,14 @@ public:
     LogicalCachedExtent &nextent,
     extent_ref_count_t refcount = EXTENT_DEFAULT_REF_COUNT) = 0;
 
+  using alloc_extents_ret = alloc_extent_iertr::future<
+    std::vector<LBAMappingRef>>;
+  virtual alloc_extents_ret alloc_extents(
+    Transaction &t,
+    laddr_t hint,
+    std::vector<LogicalCachedExtentRef> extents,
+    extent_ref_count_t refcount) = 0;
+
   virtual alloc_extent_ret clone_mapping(
     Transaction &t,
     laddr_t hint,
index c2980d4a41becaee014ac6234328055d38e11494..74364d6245cb1e02d738f47b3aaf6ea64443d4f6 100644 (file)
@@ -300,16 +300,17 @@ BtreeLBAManager::_get_mapping(
     });
 }
 
-BtreeLBAManager::alloc_extent_ret
-BtreeLBAManager::_alloc_extent(
+BtreeLBAManager::alloc_extents_ret
+BtreeLBAManager::_alloc_extents(
   Transaction &t,
   laddr_t hint,
-  extent_len_t len,
-  pladdr_t addr,
-  uint32_t checksum,
-  LogicalCachedExtent* nextent,
+  std::vector<alloc_mapping_info_t> &alloc_infos,
   extent_ref_count_t refcount)
 {
+  extent_len_t total_len = 0;
+  for (auto &info : alloc_infos) {
+    total_len += info.len;
+  }
   struct state_t {
     laddr_t last_end;
 
@@ -319,77 +320,98 @@ BtreeLBAManager::_alloc_extent(
     state_t(laddr_t hint) : last_end(hint) {}
   };
 
-  LOG_PREFIX(BtreeLBAManager::_alloc_extent);
-  TRACET("{}~{}, hint={}, refcount={}", t, addr, len, hint, refcount);
+  LOG_PREFIX(BtreeLBAManager::_alloc_extents);
+  TRACET("{}~{}, hint={}, num of extents: {}, refcount={}",
+    t, alloc_infos.front().val, total_len, hint, alloc_infos.size(), refcount);
 
   auto c = get_context(t);
-  ++stats.num_alloc_extents;
+  stats.num_alloc_extents += alloc_infos.size();
   auto lookup_attempts = stats.num_alloc_extents_iter_nexts;
-  return crimson::os::seastore::with_btree_state<LBABtree, state_t>(
-    cache,
-    c,
-    hint,
-    [this, FNAME, c, hint, len, addr, lookup_attempts,
-    &t, nextent, refcount, checksum](auto &btree, auto &state) {
+  return seastar::do_with(
+    std::vector<LBAMappingRef>(),
+    [this, FNAME, &alloc_infos, hint, &t, total_len, c,
+    lookup_attempts, refcount](auto &rets) {
+    return crimson::os::seastore::with_btree_state<LBABtree, state_t>(
+      cache,
+      c,
+      hint,
+      [this, c, hint, total_len, addr=alloc_infos.front().val, &rets, refcount,
+      lookup_attempts, &t, &alloc_infos, FNAME](auto &btree, auto &state) {
       return LBABtree::iterate_repeat(
        c,
        btree.upper_bound_right(c, hint),
-       [this, &state, len, addr, &t, hint, FNAME, lookup_attempts](auto &pos) {
-         ++stats.num_alloc_extents_iter_nexts;
-         if (pos.is_end()) {
-           DEBUGT("{}~{}, hint={}, state: end, done with {} attempts, insert at {}",
-                   t, addr, len, hint,
-                   stats.num_alloc_extents_iter_nexts - lookup_attempts,
-                   state.last_end);
-           state.insert_iter = pos;
-           return typename LBABtree::iterate_repeat_ret_inner(
-             interruptible::ready_future_marker{},
-             seastar::stop_iteration::yes);
-         } else if (pos.get_key() >= (state.last_end + len)) {
-           DEBUGT("{}~{}, hint={}, state: {}~{}, done with {} attempts, insert at {} -- {}",
-                   t, addr, len, hint,
-                   pos.get_key(), pos.get_val().len,
-                   stats.num_alloc_extents_iter_nexts - lookup_attempts,
-                   state.last_end,
-                   pos.get_val());
-           state.insert_iter = pos;
-           return typename LBABtree::iterate_repeat_ret_inner(
-             interruptible::ready_future_marker{},
-             seastar::stop_iteration::yes);
-         } else {
-           state.last_end = pos.get_key() + pos.get_val().len;
-           TRACET("{}~{}, hint={}, state: {}~{}, repeat ... -- {}",
-                   t, addr, len, hint,
-                   pos.get_key(), pos.get_val().len,
-                   pos.get_val());
-           return typename LBABtree::iterate_repeat_ret_inner(
-             interruptible::ready_future_marker{},
-             seastar::stop_iteration::no);
-         }
-       }).si_then([FNAME, c, addr, len, hint, &btree,
-                   &state, nextent, refcount, checksum] {
+       [this, &state, total_len, addr, &t, hint,
+       lookup_attempts, FNAME](auto &pos) {
+       ++stats.num_alloc_extents_iter_nexts;
+       if (pos.is_end()) {
+         DEBUGT("{}~{}, hint={}, state: end, done with {} attempts, insert at {}",
+                t, addr, total_len, hint,
+                stats.num_alloc_extents_iter_nexts - lookup_attempts,
+                state.last_end);
+         state.insert_iter = pos;
+         return typename LBABtree::iterate_repeat_ret_inner(
+           interruptible::ready_future_marker{},
+           seastar::stop_iteration::yes);
+       } else if (pos.get_key() >= (state.last_end + total_len)) {
+         DEBUGT("{}~{}, hint={}, state: {}~{}, done with {} attempts, insert at {} -- {}",
+                t, addr, total_len, hint,
+                pos.get_key(), pos.get_val().len,
+                stats.num_alloc_extents_iter_nexts - lookup_attempts,
+                state.last_end,
+                pos.get_val());
+         state.insert_iter = pos;
+         return typename LBABtree::iterate_repeat_ret_inner(
+           interruptible::ready_future_marker{},
+           seastar::stop_iteration::yes);
+       } else {
+         state.last_end = pos.get_key() + pos.get_val().len;
+         TRACET("{}~{}, hint={}, state: {}~{}, repeat ... -- {}",
+                t, addr, total_len, hint,
+                pos.get_key(), pos.get_val().len,
+                pos.get_val());
+         return typename LBABtree::iterate_repeat_ret_inner(
+           interruptible::ready_future_marker{},
+           seastar::stop_iteration::no);
+       }
+      }).si_then([c, addr, hint, &btree, &state, &alloc_infos,
+                 total_len, &rets, refcount, FNAME] {
+       return trans_intr::do_for_each(
+         alloc_infos,
+         [c, addr, hint, &btree, &state, FNAME,
+         total_len, &rets, refcount](auto &alloc_info) {
          return btree.insert(
            c,
            *state.insert_iter,
            state.last_end,
-           lba_map_val_t{len, pladdr_t(addr), refcount, checksum},
-           nextent
-         ).si_then([&state, FNAME, c, addr, len, hint, nextent](auto &&p) {
+           lba_map_val_t{
+             alloc_info.len,
+             pladdr_t(alloc_info.val),
+             refcount,
+             alloc_info.checksum},
+           alloc_info.extent
+         ).si_then([&state, c, addr, total_len, hint, FNAME,
+                   &alloc_info, &rets](auto &&p) {
            auto [iter, inserted] = std::move(p);
            TRACET("{}~{}, hint={}, inserted at {}",
-                  c.trans, addr, len, hint, state.last_end);
-           if (nextent) {
-             ceph_assert(addr.is_paddr());
-             nextent->set_laddr(iter.get_key());
+                  c.trans, addr, total_len, hint, state.last_end);
+           if (alloc_info.extent) {
+             ceph_assert(alloc_info.val.is_paddr());
+             alloc_info.extent->set_laddr(iter.get_key());
            }
            ceph_assert(inserted);
-           state.ret = iter;
+           rets.emplace_back(iter.get_pin(c));
+           return iter.next(c).si_then([&state, &alloc_info](auto it) {
+             state.insert_iter = it;
+             state.last_end += alloc_info.len;
+           });
          });
        });
-    }).si_then([c](auto &&state) {
+      });
+    }).si_then([&rets](auto &&state) {
       return alloc_extent_iertr::make_ready_future<
-       LBAMappingRef>(state.ret->get_pin(c));
+       std::vector<LBAMappingRef>>(std::move(rets));
     });
+  });
 }
 
 static bool is_lba_node(const CachedExtent &e)
index 2641e940ee4d2c7b52435c516748682fca5ada51..c43d60dcb5b0b3ed9721b51d5a0018c28e9d5c9c 100644 (file)
@@ -214,19 +214,35 @@ public:
     Transaction &t,
     laddr_t offset) final;
 
+
+  struct alloc_mapping_info_t {
+    extent_len_t len = 0;
+    pladdr_t val;
+    uint32_t checksum = 0;
+    LogicalCachedExtent* extent = nullptr;
+  };
+
   alloc_extent_ret reserve_region(
     Transaction &t,
     laddr_t hint,
-    extent_len_t len)
+    extent_len_t len) final
   {
-    return _alloc_extent(
-      t,
-      hint,
-      len,
-      P_ADDR_ZERO,
-      0,
-      nullptr,
-      EXTENT_DEFAULT_REF_COUNT);
+    std::vector<alloc_mapping_info_t> alloc_infos = {
+      alloc_mapping_info_t{len, P_ADDR_ZERO, 0, nullptr}};
+    return seastar::do_with(
+      std::move(alloc_infos),
+      [&t, hint, this](auto &alloc_infos) {
+      return _alloc_extents(
+       t,
+       hint,
+       alloc_infos,
+       EXTENT_DEFAULT_REF_COUNT
+      ).si_then([](auto mappings) {
+       assert(mappings.size() == 1);
+       auto mapping = std::move(mappings.front());
+       return mapping;
+      });
+    });
   }
 
   alloc_extent_ret clone_mapping(
@@ -234,36 +250,45 @@ public:
     laddr_t hint,
     extent_len_t len,
     laddr_t intermediate_key,
-    laddr_t intermediate_base)
+    laddr_t intermediate_base) final
   {
     assert(intermediate_key != L_ADDR_NULL);
     assert(intermediate_base != L_ADDR_NULL);
-    return _alloc_extent(
-      t,
-      hint,
-      len,
-      intermediate_key,
-      0,       // crc will only be used and checked with LBA direct mappings
+    std::vector<alloc_mapping_info_t> alloc_infos = {
+      alloc_mapping_info_t{
+       len,
+       intermediate_key,
+       0,      // crc will only be used and checked with LBA direct mappings
                // also see pin_to_extent(_by_type)
-      nullptr,
-      EXTENT_DEFAULT_REF_COUNT
-    ).si_then([&t, this, intermediate_base](auto indirect_mapping) {
-      assert(indirect_mapping->is_indirect());
-      return update_refcount(t, intermediate_base, 1, false
-      ).si_then([imapping=std::move(indirect_mapping)](auto res) mutable {
-       auto mapping = std::move(res.mapping);
-       ceph_assert(mapping->is_stable());
-       mapping->make_indirect(
-         imapping->get_key(),
-         imapping->get_length(),
-         imapping->get_intermediate_key());
-       return seastar::make_ready_future<
-         LBAMappingRef>(std::move(mapping));
-      });
-    }).handle_error_interruptible(
-      crimson::ct_error::input_output_error::pass_further{},
-      crimson::ct_error::assert_all{"unexpect enoent"}
-    );
+       nullptr}};
+    return seastar::do_with(
+      std::move(alloc_infos),
+      [this, &t, intermediate_base, hint](auto &alloc_infos) {
+      return _alloc_extents(
+       t,
+       hint,
+       alloc_infos,
+       EXTENT_DEFAULT_REF_COUNT
+      ).si_then([&t, this, intermediate_base](auto mappings) {
+       assert(mappings.size() == 1);
+       auto indirect_mapping = std::move(mappings.front());
+       assert(indirect_mapping->is_indirect());
+       return update_refcount(t, intermediate_base, 1, false
+       ).si_then([imapping=std::move(indirect_mapping)](auto p) mutable {
+         auto mapping = std::move(p.mapping);
+         ceph_assert(mapping->is_stable());
+         mapping->make_indirect(
+           imapping->get_key(),
+           imapping->get_length(),
+           imapping->get_intermediate_key());
+         return seastar::make_ready_future<
+           LBAMappingRef>(std::move(mapping));
+       });
+      }).handle_error_interruptible(
+       crimson::ct_error::input_output_error::pass_further{},
+       crimson::ct_error::assert_all{"unexpect enoent"}
+      );
+    });
   }
 
   alloc_extent_ret alloc_extent(
@@ -274,14 +299,43 @@ public:
   {
     // The real checksum will be updated upon transaction commit
     assert(ext.get_last_committed_crc() == 0);
-    return _alloc_extent(
-      t,
-      hint,
-      ext.get_length(),
-      ext.get_paddr(),
-      ext.get_last_committed_crc(),
-      &ext,
-      refcount);
+    std::vector<alloc_mapping_info_t> alloc_infos = {{
+      ext.get_length(), ext.get_paddr(), ext.get_last_committed_crc(), &ext}};
+    return seastar::do_with(
+      std::move(alloc_infos),
+      [this, &t, hint, refcount](auto &alloc_infos) {
+      return _alloc_extents(
+       t,
+       hint,
+       alloc_infos,
+       refcount
+      ).si_then([](auto mappings) {
+       assert(mappings.size() == 1);
+       auto mapping = std::move(mappings.front());
+       return mapping;
+      });
+    });
+  }
+
+  alloc_extents_ret alloc_extents(
+    Transaction &t,
+    laddr_t hint,
+    std::vector<LogicalCachedExtentRef> extents,
+    extent_ref_count_t refcount) final
+  {
+    std::vector<alloc_mapping_info_t> alloc_infos;
+    for (auto &extent : extents) {
+      alloc_infos.emplace_back(alloc_mapping_info_t{
+       extent->get_length(),
+       pladdr_t(extent->get_paddr()),
+       extent->get_last_committed_crc(),
+       extent.get()});
+    }
+    return seastar::do_with(
+      std::move(alloc_infos),
+      [this, &t, hint, refcount](auto &alloc_infos) {
+      return _alloc_extents(t, hint, alloc_infos, refcount);
+    });
   }
 
   ref_ret decref_extent(
@@ -409,13 +463,10 @@ private:
     update_func_t &&f,
     LogicalCachedExtent*);
 
-  alloc_extent_ret _alloc_extent(
+  alloc_extents_ret _alloc_extents(
     Transaction &t,
     laddr_t hint,
-    extent_len_t len,
-    pladdr_t addr,
-    uint32_t checksum,
-    LogicalCachedExtent*,
+    std::vector<alloc_mapping_info_t> &alloc_infos,
     extent_ref_count_t refcount);
 
   using _get_mapping_ret = get_mapping_iertr::future<BtreeLBAMappingRef>;