]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
crimson/os/seastore/transaction_manager: link RetiredExtentPlaceholder
authorXuehan Xu <xuxuehan@qianxin.com>
Mon, 21 Jul 2025 09:28:59 +0000 (17:28 +0800)
committerXuehan Xu <xxhdx1985126@gmail.com>
Tue, 12 Aug 2025 05:43:25 +0000 (13:43 +0800)
onto lba leaf nodes

Signed-off-by: Xuehan Xu <xuxuehan@qianxin.com>
src/crimson/os/seastore/cache.cc
src/crimson/os/seastore/cache.h
src/crimson/os/seastore/cached_extent.h
src/crimson/os/seastore/logical_child_node.h
src/crimson/os/seastore/retired_extent_placeholder.h [new file with mode: 0644]
src/crimson/os/seastore/transaction_manager.cc
src/crimson/os/seastore/transaction_manager.h

index 33660d34082381a3524e1a8dad56db25c5be81ac..640be6771308fc247666bcbe673599895b310761 100644 (file)
@@ -93,8 +93,8 @@ Cache::retire_extent_ret Cache::retire_extent_addr(
   return retire_extent_iertr::now();
 }
 
-void Cache::retire_absent_extent_addr(
-  Transaction &t, paddr_t paddr, extent_len_t length)
+CachedExtentRef Cache::retire_absent_extent_addr(
+  Transaction &t, laddr_t laddr, paddr_t paddr, extent_len_t length)
 {
   assert(paddr.is_absolute());
 
@@ -112,10 +112,12 @@ void Cache::retire_absent_extent_addr(
   ext->init(
     CachedExtent::extent_state_t::CLEAN, paddr,
     PLACEMENT_HINT_NULL, NULL_GENERATION, TRANS_ID_NULL);
+  static_cast<RetiredExtentPlaceholder&>(*ext).set_laddr(laddr);
   DEBUGT("retire {}~0x{:x} as placeholder, add extent -- {}",
         t, paddr, length, *ext);
   add_extent(ext);
   t.add_absent_to_retired_set(ext);
+  return ext;
 }
 
 void Cache::dump_contents()
index 332a5ebecbab257ed96fd35a4b37c340b2e25e49..97cc7b6568a93c6b07985e30007cf6d461228b08 100644 (file)
@@ -163,8 +163,8 @@ public:
   retire_extent_ret retire_extent_addr(
     Transaction &t, paddr_t addr, extent_len_t length);
 
-  void retire_absent_extent_addr(
-    Transaction &t, paddr_t addr, extent_len_t length);
+  CachedExtentRef retire_absent_extent_addr(
+    Transaction &t, laddr_t laddr, paddr_t addr, extent_len_t length);
 
   /**
    * get_root
index 2ac55b3405c805fc4075fca3252753460764514b..5cf591c35b3e2a68e96f0cc2211d019100975ecb 100644 (file)
@@ -1366,54 +1366,6 @@ private:
   uint64_t bytes = 0;
 };
 
-/**
- * RetiredExtentPlaceholder
- *
- * Cache::retire_extent_addr(Transaction&, paddr_t, extent_len_t) can retire an
- * extent not currently in cache. In that case, in order to detect transaction
- * invalidation, we need to add a placeholder to the cache to create the
- * mapping back to the transaction. And whenever there is a transaction tries
- * to read the placeholder extent out, Cache is responsible to replace the
- * placeholder by the real one. Anyway, No placeholder extents should escape
- * the Cache interface boundary.
- */
-class RetiredExtentPlaceholder : public CachedExtent {
-
-public:
-  RetiredExtentPlaceholder(extent_len_t length)
-    : CachedExtent(CachedExtent::retired_placeholder_construct_t{}, length) {}
-
-  CachedExtentRef duplicate_for_write(Transaction&) final {
-    ceph_abort_msg("Should never happen for a placeholder");
-    return CachedExtentRef();
-  }
-
-  ceph::bufferlist get_delta() final {
-    ceph_abort_msg("Should never happen for a placeholder");
-    return ceph::bufferlist();
-  }
-
-  static constexpr extent_types_t TYPE = extent_types_t::RETIRED_PLACEHOLDER;
-  extent_types_t get_type() const final {
-    return TYPE;
-  }
-
-  void apply_delta_and_adjust_crc(
-    paddr_t base, const ceph::bufferlist &bl) final {
-    ceph_abort_msg("Should never happen for a placeholder");
-  }
-
-  void on_rewrite(Transaction &, CachedExtent&, extent_len_t) final {}
-
-  std::ostream &print_detail(std::ostream &out) const final {
-    return out << ", RetiredExtentPlaceholder";
-  }
-
-  void on_delta_write(paddr_t record_block_offset) final {
-    ceph_abort_msg("Should never happen for a placeholder");
-  }
-};
-
 class LBAMapping;
 /**
  * LogicalCachedExtent
index 3b2786f1eb223a72a551ca7f34ec97aed7ad4069..71e6ee0ed136bfa9bae3015c82252e59d2d707b2 100644 (file)
 
 namespace crimson::os::seastore {
 
+/**
+ * RetiredExtentPlaceholder
+ *
+ * Cache::retire_extent_addr(Transaction&, paddr_t, extent_len_t) can retire an
+ * extent not currently in cache. In that case, in order to detect transaction
+ * invalidation, we need to add a placeholder to the cache to create the
+ * mapping back to the transaction. And whenever there is a transaction tries
+ * to read the placeholder extent out, Cache is responsible to replace the
+ * placeholder by the real one. Anyway, No placeholder extents should escape
+ * the Cache interface boundary.
+ */
+class RetiredExtentPlaceholder
+  : public CachedExtent,
+    public ChildNode<lba::LBALeafNode, RetiredExtentPlaceholder, laddr_t> {
+
+public:
+  RetiredExtentPlaceholder(extent_len_t length)
+    : CachedExtent(CachedExtent::retired_placeholder_construct_t{}, length) {}
+
+  ~RetiredExtentPlaceholder() {
+    if (this->is_stable()) {
+      lba_child_node_t::destroy();
+    }
+  }
+
+  CachedExtentRef duplicate_for_write(Transaction&) final {
+    ceph_abort_msg("Should never happen for a placeholder");
+    return CachedExtentRef();
+  }
+
+  ceph::bufferlist get_delta() final {
+    ceph_abort_msg("Should never happen for a placeholder");
+    return ceph::bufferlist();
+  }
+
+  static constexpr extent_types_t TYPE = extent_types_t::RETIRED_PLACEHOLDER;
+  extent_types_t get_type() const final {
+    return TYPE;
+  }
+
+  void apply_delta_and_adjust_crc(
+    paddr_t base, const ceph::bufferlist &bl) final {
+    ceph_abort_msg("Should never happen for a placeholder");
+  }
+
+  void on_rewrite(Transaction &, CachedExtent&, extent_len_t) final {}
+
+  std::ostream &print_detail(std::ostream &out) const final {
+    return out << ", RetiredExtentPlaceholder";
+  }
+
+  void on_delta_write(paddr_t record_block_offset) final {
+    ceph_abort_msg("Should never happen for a placeholder");
+  }
+
+  void set_laddr(laddr_t laddr) {
+    this->laddr = laddr;
+  }
+
+  bool is_btree_root() const {
+    return false;
+  }
+
+  laddr_t get_begin() const {
+    assert(laddr != L_ADDR_NULL);
+    return laddr;
+  }
+
+  laddr_t get_end() const {
+    assert(laddr != L_ADDR_NULL);
+    return (laddr + get_length()).checked_to_laddr();
+  }
+
+private:
+  laddr_t laddr = L_ADDR_NULL;
+};
+
 class LogicalChildNode : public LogicalCachedExtent,
                         public ChildNode<lba::LBALeafNode,
                                          LogicalChildNode,
diff --git a/src/crimson/os/seastore/retired_extent_placeholder.h b/src/crimson/os/seastore/retired_extent_placeholder.h
new file mode 100644 (file)
index 0000000..e69de29
index 25296f09580aefb04484ced99badf3029c4563e0..075d38287cf98ca4ba35aa5ef16d408a47999b04 100644 (file)
@@ -228,118 +228,182 @@ TransactionManager::ref_ret TransactionManager::remove(
   LOG_PREFIX(TransactionManager::remove);
   DEBUGT("{} ...", t, offset);
   return lba_manager->get_mapping(t, offset
-  ).si_then([&t, this, FNAME, offset](auto mapping) {
-    return seastar::do_with(
-      std::move(mapping),
-      [&t, this, FNAME, offset](auto &mapping) {
-      auto fut = base_iertr::make_ready_future<LogicalChildNodeRef>();
-      if (mapping.is_indirect()) {
-        fut = lba_manager->complete_indirect_lba_mapping(t, std::move(mapping)
-        ).si_then([&mapping, &t, this](auto m) {
-          mapping = std::move(m);
-          auto ret = get_extent_if_linked<LogicalChildNode>(t, mapping);
-          if (ret.index() == 1) {
-            return std::move(std::get<1>(ret));
-          }
-          return get_child_iertr::make_ready_future<LogicalChildNodeRef>();
+  ).si_then([&t, this](auto mapping) {
+    return _remove(t, std::move(mapping));
+  }).si_then([](auto result) {
+    return result.result.refcount;
+  });
+}
+
+TransactionManager::ref_iertr::future<LBAMapping>
+TransactionManager::remove(
+  Transaction &t,
+  LBAMapping mapping)
+{
+  return mapping.refresh().si_then([&t, this](auto mapping) {
+    return _remove(t, std::move(mapping));
+  }).si_then([](auto res) {
+    return std::move(res.result.mapping);
+  });
+}
+
+TransactionManager::ref_iertr::future<
+  TransactionManager::_remove_mapping_result_t>
+TransactionManager::_remove_indirect_mapping(
+  Transaction &t,
+  LBAMapping mapping)
+{
+  LOG_PREFIX(TransactionManager::_remove_indirect_mapping);
+  return seastar::do_with(
+    std::move(mapping),
+    [&t, this, FNAME](auto &mapping) {
+    return lba_manager->complete_indirect_lba_mapping(t, std::move(mapping)
+    ).si_then([FNAME, &mapping, &t, this](auto m) {
+      mapping = std::move(m);
+      auto ret = get_extent_if_linked<LogicalChildNode>(t, mapping);
+      if (ret.index() == 1) {
+        return std::move(std::get<1>(ret)
+        ).si_then([&t, mapping, this, FNAME](auto extent) {
+          return lba_manager->remove_mapping(t, std::move(mapping)
+          ).si_then([this, FNAME, &t, extent](auto result) {
+            ceph_assert(result.direct_result);
+            auto &primary_result = result.result;
+            ceph_assert(primary_result.refcount == 0);
+            auto &direct_result = *result.direct_result;
+            ceph_assert(direct_result.addr.is_paddr());
+            ceph_assert(!direct_result.addr.get_paddr().is_zero());
+            ceph_assert(extent);
+            if (direct_result.refcount == 0) {
+              cache->retire_extent(t, extent);
+            }
+            DEBUGT("removed indirect mapping {}~0x{:x} refcount={} offset={} "
+                   "with direct mapping {}~0x{:x} refcount={} offset={}",
+                   t, primary_result.addr,
+                   primary_result.length,
+                   primary_result.refcount,
+                   primary_result.key,
+                   direct_result.addr,
+                   direct_result.length,
+                   direct_result.refcount,
+                   direct_result.key);
+            return ref_iertr::make_ready_future<
+              _remove_mapping_result_t>(std::move(result));
+          });
         });
-      } else if (mapping.get_val().is_real_location()) {
-        auto ret = get_extent_if_linked<LogicalChildNode>(t, mapping);
-        if (ret.index() == 1) {
-          fut = std::move(std::get<1>(ret));
-        }
-      }
-      return fut.si_then([&t, &mapping, this, FNAME, offset](auto extent) {
+      } else {
+        auto unlinked_child = std::move(std::get<0>(ret));
         return lba_manager->remove_mapping(t, std::move(mapping)
-        ).si_then([this, FNAME, offset, &t, extent](auto result) -> ref_ret {
-          auto fut = ref_iertr::now();
+        ).si_then([child_pos=unlinked_child.child_pos, &t,
+                  FNAME, this](auto result) mutable {
+          ceph_assert(result.direct_result);
           auto &primary_result = result.result;
-          assert(primary_result.refcount == 0);
-          if (primary_result.need_to_remove_extent()) {
-            ceph_assert(!result.direct_result);
-            assert(extent->get_laddr() == primary_result.direct_key);
-            if (extent) {
-              cache->retire_extent(t, extent);
-            } else {
-              fut = cache->retire_extent_addr(
-                t, primary_result.addr.get_paddr(), primary_result.length);
-            }
-          } else if (auto &direct_result = result.direct_result;
-                     direct_result.has_value() &&
-                     direct_result->need_to_remove_extent()) {
-            assert(extent->get_laddr() == direct_result->direct_key);
-            if (extent) {
-              cache->retire_extent(t, extent);
-            } else {
-              fut = cache->retire_extent_addr(
-                t, direct_result->addr.get_paddr(), direct_result->length);
-            }
+          ceph_assert(primary_result.refcount == 0);
+          auto &direct_result = *result.direct_result;
+          ceph_assert(direct_result.addr.is_paddr());
+          ceph_assert(!direct_result.addr.get_paddr().is_zero());
+          if (direct_result.refcount == 0) {
+            auto retired_placeholder = cache->retire_absent_extent_addr(
+              t, direct_result.key,
+              direct_result.addr.get_paddr(),
+              direct_result.length
+            )->template cast<RetiredExtentPlaceholder>();
+            child_pos.link_child(retired_placeholder.get());
           }
-          return fut.si_then([result=std::move(result), offset, &t, FNAME] {
-            DEBUGT("removed {}~0x{:x} refcount={} -- offset={}",
-                   t, result.result.addr, result.result.length,
-                   result.result.refcount, offset);
-            return result.result.refcount;
-          });
+            DEBUGT("removed indirect mapping {}~0x{:x} refcount={} offset={} "
+                   "with direct mapping {}~0x{:x} refcount={} offset={}",
+                   t, primary_result.addr,
+                   primary_result.length,
+                   primary_result.refcount,
+                   primary_result.key,
+                   direct_result.addr,
+                   direct_result.length,
+                   direct_result.refcount,
+                   direct_result.key);
+          return ref_iertr::make_ready_future<
+            _remove_mapping_result_t>(std::move(result));
         });
-      });
+      }
     });
   });
 }
 
-TransactionManager::ref_iertr::future<LBAMapping> TransactionManager::remove(
+TransactionManager::ref_iertr::future<
+  TransactionManager::_remove_mapping_result_t>
+TransactionManager::_remove_direct_mapping(
   Transaction &t,
   LBAMapping mapping)
 {
-  LOG_PREFIX(TransactionManager::remove);
-  return mapping.refresh().si_then([&t, this](auto mapping) {
-    if (mapping.is_indirect()) {
-      return lba_manager->complete_indirect_lba_mapping(t, std::move(mapping));
-    }
-    return LBAManager::complete_lba_mapping_iertr::make_ready_future<
-      LBAMapping>(std::move(mapping));
-  }).si_then([&t, this, FNAME](auto mapping) {
-    auto fut = base_iertr::make_ready_future<LogicalChildNodeRef>();
-    if (!mapping.is_indirect() && mapping.get_val().is_real_location()) {
-      auto ret = get_extent_if_linked<LogicalChildNode>(t, mapping);
-      if (ret.index() == 1) {
-        fut = std::move(std::get<1>(ret));
-      }
-    }
-    return fut.si_then([mapping=std::move(mapping),
-                        FNAME, this, &t](auto extent) mutable {
-      auto offset = mapping.get_key();
+  LOG_PREFIX(TransactionManager::_remove_direct_mapping);
+  auto ret = get_extent_if_linked<LogicalChildNode>(t, mapping);
+  if (ret.index() == 1) {
+    return std::move(std::get<1>(ret)
+    ).si_then([&t, mapping, this, FNAME](auto extent) {
       return lba_manager->remove_mapping(t, std::move(mapping)
-      ).si_then([FNAME, this, extent, &t, offset](auto result) {
-        auto fut = ref_iertr::now();
+      ).si_then([this, FNAME, &t, extent](auto result) {
         auto &primary_result = result.result;
-        assert(primary_result.refcount == 0);
-        if (primary_result.need_to_remove_extent()) {
-          ceph_assert(!result.direct_result);
-          if (extent) {
-            cache->retire_extent(t, extent);
-          } else {
-            fut = cache->retire_extent_addr(
-              t, primary_result.addr.get_paddr(), primary_result.length);
-          }
-        } else if (auto &direct_result = result.direct_result;
-                   direct_result.has_value() &&
-                   direct_result->need_to_remove_extent()) {
-          ceph_assert(!extent);
-          fut = cache->retire_extent_addr(
-            t, direct_result->addr.get_paddr(), direct_result->length);
-        } else {
-          ceph_assert(!extent);
-        }
-        return fut.si_then([result=std::move(result), &t, FNAME, offset]() mutable {
-          DEBUGT("removed {}~0x{:x} refcount={} -- offset={}",
-                 t, result.result.addr, result.result.length,
-                 result.result.refcount, offset);
-          return std::move(result.result.mapping);
-        });
+        ceph_assert(primary_result.refcount == 0);
+        ceph_assert(primary_result.addr.is_paddr());
+        ceph_assert(!primary_result.addr.get_paddr().is_zero());
+        ceph_assert(extent);
+        cache->retire_extent(t, extent);
+        DEBUGT("removed {}~0x{:x} refcount={} -- offset={}",
+               t, primary_result.addr, primary_result.length,
+               primary_result.refcount, primary_result.key);
+        return ref_iertr::make_ready_future<
+          _remove_mapping_result_t>(std::move(result));
       });
     });
-  });
+  } else {
+    auto unlinked_child = std::move(std::get<0>(ret));
+    return lba_manager->remove_mapping(t, std::move(mapping)
+    ).si_then([child_pos=unlinked_child.child_pos, &t,
+              FNAME, this](auto result) mutable {
+      auto &primary_result = result.result;
+      ceph_assert(primary_result.refcount == 0);
+      ceph_assert(primary_result.addr.is_paddr());
+      ceph_assert(!primary_result.addr.get_paddr().is_zero());
+      auto retired_placeholder = cache->retire_absent_extent_addr(
+        t, primary_result.key,
+        primary_result.addr.get_paddr(),
+        primary_result.length
+      )->template cast<RetiredExtentPlaceholder>();
+      child_pos.link_child(retired_placeholder.get());
+      DEBUGT("removed {}~0x{:x} refcount={} -- offset={}",
+             t, primary_result.addr, primary_result.length,
+             primary_result.refcount, primary_result.key);
+      return ref_iertr::make_ready_future<
+        _remove_mapping_result_t>(std::move(result));
+    });
+  }
+}
+
+TransactionManager::ref_iertr::future<
+  TransactionManager::_remove_mapping_result_t>
+TransactionManager::_remove(
+  Transaction &t,
+  LBAMapping mapping)
+{
+  LOG_PREFIX(TransactionManager::_remove);
+  if (mapping.is_indirect()) {
+    return _remove_indirect_mapping(t, std::move(mapping));
+  } else if (mapping.get_val().is_real_location()) {
+    return _remove_direct_mapping(t, std::move(mapping));
+  } else {
+    return lba_manager->remove_mapping(t, std::move(mapping)
+    ).si_then([&t, FNAME](auto result) {
+      auto &primary_result = result.result;
+      ceph_assert(primary_result.refcount == 0);
+      ceph_assert(primary_result.addr.is_paddr());
+      ceph_assert(primary_result.addr.get_paddr().is_zero());
+      DEBUGT("removed {}~0x{:x} refcount={} -- offset={}",
+             t, primary_result.addr,
+             primary_result.length,
+             primary_result.refcount,
+             primary_result.key);
+      return ref_iertr::make_ready_future<
+        _remove_mapping_result_t>(std::move(result));
+    });
+  }
 }
 
 TransactionManager::refs_ret TransactionManager::remove(
index 32500343c806ddbcaf15aaeb2dc3f53b8fc4dd44..98f0d0188183014672298bb6e04375dbec667c19 100644 (file)
@@ -1310,7 +1310,11 @@ private:
              });
            } else {
              // absent
-             cache->retire_absent_extent_addr(t, original_paddr, original_len);
+             auto unlinked_child = std::move(std::get<0>(ret));
+             auto retired_placeholder = cache->retire_absent_extent_addr(
+               t, pin.get_key(), original_paddr, original_len
+             )->template cast<RetiredExtentPlaceholder>();
+             unlinked_child.child_pos.link_child(retired_placeholder.get());
              return base_iertr::make_ready_future<TCachedExtentRef<T>>();
            }
          }
@@ -1375,6 +1379,19 @@ private:
     });
   }
 
+  using _remove_mapping_result_t = LBAManager::ref_update_result_t;
+  ref_iertr::future<_remove_mapping_result_t> _remove(
+    Transaction &t,
+    LBAMapping mapping);
+  ref_iertr::future<_remove_mapping_result_t>
+  _remove_indirect_mapping(
+    Transaction &t,
+    LBAMapping mapping);
+  ref_iertr::future<_remove_mapping_result_t>
+  _remove_direct_mapping(
+    Transaction &t,
+    LBAMapping mapping);
+
   rewrite_extent_ret rewrite_logical_extent(
     Transaction& t,
     LogicalChildNodeRef extent);