]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
crimson/os/seastore: implement promote extent
authorZhang Song <zhangsong02@qianxin.com>
Wed, 3 Sep 2025 08:02:01 +0000 (16:02 +0800)
committerXuehan Xu <xuxuehan@qianxin.com>
Tue, 7 Jul 2026 08:15:30 +0000 (16:15 +0800)
Signed-off-by: Zhang Song <zhangsong02@qianxin.com>
Signed-off-by: Xuehan Xu <xuxuehan@qianxin.com>
src/crimson/os/seastore/lba/btree_lba_manager.cc
src/crimson/os/seastore/lba/btree_lba_manager.h
src/crimson/os/seastore/lba_manager.h
src/crimson/os/seastore/transaction_manager.cc

index 348ec1a6e09b9f972de874fb36176fe8d47a86fc..31aaa659736cbc66dbeed4d0fb812650e309006d 100644 (file)
@@ -7,6 +7,7 @@
 #include <seastar/core/metrics.hh>
 
 #include "include/buffer.h"
+#include "crimson/common/coroutine.h"
 #include "crimson/os/seastore/lba/btree_lba_manager.h"
 #include "crimson/os/seastore/lba/lba_btree_node.h"
 #include "crimson/os/seastore/logging.h"
@@ -268,6 +269,58 @@ BtreeLBAManager::lower_bound(
   co_return iter.get_cursor(c);
 }
 
+BtreeLBAManager::promote_extent_ret
+BtreeLBAManager::promote_extent(
+  Transaction &t,
+  LBACursor &cursor,
+  std::vector<LogicalChildNodeRef> extents)
+{
+  LOG_PREFIX(BtreeLBAManager::promote_extent);
+  auto laddr = cursor.get_laddr();
+  ceph_assert(!extents.empty());
+  ceph_assert(!cursor.is_indirect());
+  ceph_assert(laddr == extents.front()->get_laddr());
+  DEBUGT("promote cursor {} with {} extents",
+        t, cursor, extents.size());
+  auto c = get_context(t);
+  auto btree = co_await get_btree<LBABtree>(c);
+  auto iter = btree.make_partial_iter(c, cursor);
+  auto orig_val = iter.get_val();
+  if (extents.size() == 1) {
+    auto new_val = orig_val;
+    ceph_assert(new_val.pladdr.is_paddr());
+    new_val.shadow_paddr = new_val.pladdr.get_paddr();
+    auto extent = extents.front().get();
+    auto paddr = extent->get_paddr();
+    new_val.pladdr = pladdr_t(paddr);
+    TRACET("promote {} from {} to {}",
+          t, iter.get_key(), new_val.shadow_paddr, paddr);
+    assert(extent->is_pending());
+    assert(!extent->has_parent_tracker());
+    iter = btree.update(c, iter, new_val, extent);
+    assert(extent->has_parent_tracker());
+  } else {
+    auto insert_iter = co_await btree.remove(c, std::move(iter));
+    for (auto &extent : extents) {
+      auto offset = extent->get_laddr().get_byte_distance<extent_len_t>(laddr);
+      auto new_val = orig_val;
+      new_val.shadow_paddr = orig_val.pladdr.get_paddr().add_offset(offset);
+      new_val.pladdr = pladdr_t(extent->get_paddr());
+      new_val.len = extent->get_length();
+      new_val.checksum = extent->get_last_committed_crc();
+      TRACET("insert promoted cursor {} {}",
+            c.trans, extent->get_laddr(), new_val);
+      assert(!extent->has_parent_tracker());
+      auto [iter, inserted] = co_await btree.insert(
+       c, std::move(insert_iter), extent->get_laddr(), new_val, extent.get());
+      ceph_assert(inserted);
+      assert(extent->has_parent_tracker());
+      insert_iter = co_await iter.next(c);
+    }
+  }
+  co_return;
+}
+
 BtreeLBAManager::alloc_extent_ret
 BtreeLBAManager::reserve_region(
   Transaction &t,
index e47d6c29cf7b60629ff8f03a62febde33574d5f8..cee8f46bf9723e4c3dd6842d7333f43f3b274961 100644 (file)
@@ -79,6 +79,11 @@ public:
     Transaction &t,
     laddr_t laddr) final;
 
+  promote_extent_ret promote_extent(
+    Transaction &t,
+    LBACursor &cursor,
+    std::vector<LogicalChildNodeRef> extents) final;
+
   alloc_extent_ret reserve_region(
     Transaction &t,
     LBACursorRef pos,
index a537a35141850b9cb9a6b28fa263d3ff4e85c0cf..59f6f251176c0557dd2033e236c743ea432b311d 100644 (file)
@@ -167,6 +167,13 @@ public:
     LBACursorRef dest,
     LogicalChildNode &extent) = 0;
 
+  using promote_extent_iertr = base_iertr;
+  using promote_extent_ret = promote_extent_iertr::future<>;
+  virtual promote_extent_ret promote_extent(
+    Transaction &t,
+    LBACursor &cursor,
+    std::vector<LogicalChildNodeRef> extents) = 0;
+
   virtual alloc_extent_ret reserve_region(
     Transaction &t,
     laddr_hint_t hint,
index a75d2ef9d6d8be6e2b46c758496383d88fc12d58..fc79c523d6967b6bc8c018a45ee6f23626d68abe 100644 (file)
@@ -1074,8 +1074,106 @@ TransactionManager::promote_extent(
   Transaction &t,
   CachedExtentRef extent)
 {
-  // TODO
-  return rewrite_extent_iertr::make_ready_future();
+  LOG_PREFIX(TransactionManager::promote_extent);
+  assert(epm->is_cold_device(extent->get_paddr().get_device_id()));
+  DEBUGT("promote extent: {}", t, *extent);
+  ceph_assert(extent->is_logical());
+
+  std::vector<LogicalChildNodeRef> promoted_extents;
+  auto orig_ext = extent->cast<LogicalChildNode>();
+  // fill extent if it's not fully loaded
+  if (!extent->is_fully_loaded()) {
+    ceph_assert(extent->get_type() == extent_types_t::OBJECT_DATA_BLOCK);
+    extent = co_await cache->read_extent_maybe_partial(
+      t, extent->cast<ObjectDataBlock>(), 0, extent->get_length());
+  }
+
+  cache->retire_extent(t, extent);
+
+  if (get_extent_category(extent->get_type()) == data_category_t::DATA) {
+    auto promoted_raw_extents = cache->alloc_new_data_extents_by_type(
+      t,
+      orig_ext->get_type(),
+      orig_ext->get_length(),
+      placement_hint_t::HOT,
+      INIT_GENERATION);
+
+    promoted_extents.reserve(promoted_raw_extents.size());
+
+    extent_len_t offset = 0;
+    auto orig_laddr = orig_ext->get_laddr();
+    auto orig_paddr = orig_ext->get_paddr();
+    auto orig_length = orig_ext->get_length();
+    t.force_rewrite_conflict = (promoted_raw_extents.size() > 1);
+    for (auto &extent : promoted_raw_extents) {
+      auto slice_laddr = (orig_laddr + offset).checked_to_laddr();
+      auto slice_length = extent->get_length();
+      extent->rewrite(t, *orig_ext, offset);
+      assert(!extent->get_paddr().is_absolute() ||
+             !cache->is_on_cold_tier(extent->get_paddr()));
+
+      auto lext = extent->cast<LogicalChildNode>();
+      lext->set_laddr(slice_laddr);
+      //TODO: this memory copy should be saved
+      orig_ext->get_bptr().copy_out(
+        offset, slice_length, lext->get_bptr().c_str());
+      lext->set_last_committed_crc(lext->calc_crc32c());
+
+      promoted_extents.push_back(lext);
+
+      auto remapped_cold_extent = cache->alloc_remapped_extent_by_type(
+        t,
+        orig_ext->get_type(),
+        slice_laddr,
+        orig_paddr.add_offset(offset),
+        offset,
+        slice_length,
+        std::nullopt);
+      remapped_cold_extent->set_shadow_extent(true);
+
+      offset += slice_length;
+    }
+    ceph_assert(offset == orig_length);
+  } else {
+    auto promoted_extent = cache->alloc_new_non_data_extent_by_type(
+      t,
+      orig_ext->get_type(),
+      orig_ext->get_length(),
+      placement_hint_t::HOT,
+      INIT_GENERATION);
+    auto lext = promoted_extent->cast<LogicalChildNode>();
+    lext->set_laddr(orig_ext->get_laddr());
+    lext->rewrite(t, *orig_ext, 0);
+    assert(!extent->get_paddr().is_absolute() ||
+           !cache->is_on_cold_tier(lext->get_paddr()));
+    //TODO: this memory copy should be saved
+    orig_ext->get_bptr().copy_out(
+      0,
+      orig_ext->get_length(),
+      lext->get_bptr().c_str());
+    promoted_extents.push_back(lext);
+    auto remapped_cold_extent = cache->alloc_remapped_extent_by_type(
+      t,
+      orig_ext->get_type(),
+      orig_ext->get_laddr(),
+      orig_ext->get_paddr(),
+      0,
+      orig_ext->get_length(),
+      std::nullopt);
+    boost::ignore_unused(remapped_cold_extent);
+
+    remapped_cold_extent->set_shadow_extent(true);
+  }
+
+  auto cursor = co_await lba_manager->get_cursor(
+    t, *orig_ext
+  ).handle_error_interruptible(
+    promote_extent_iertr::pass_further(),
+    crimson::ct_error::assert_all("invalid error"));
+  auto mapping = co_await resolve_cursor_to_mapping(t, std::move(cursor));
+  assert(!mapping.is_indirect());
+  co_return co_await lba_manager->promote_extent(
+    t, *mapping.direct_cursor, std::move(promoted_extents));
 }
 
 TransactionManager::demote_region_ret