summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXuehan Xu <xuxuehan@qianxin.com>2025-01-08 09:07:21 +0100
committerXuehan Xu <xuxuehan@qianxin.com>2025-01-10 08:15:56 +0100
commitcadb2027ebbb61821af8562c8d76a7d942743579 (patch)
tree2ba077f2139932c2b9c5344ccb320f65ce2cae7e
parentMerge pull request #61213 from Matan-B/wip-matanb-crimson-shared-lru-dtor (diff)
downloadceph-cadb2027ebbb61821af8562c8d76a7d942743579.tar.xz
ceph-cadb2027ebbb61821af8562c8d76a7d942743579.zip
crimson/os/seastore: refactor LBAMapping
So that PhyscalNodeMapping doesn't contain LBAMapping specific interfaces Signed-off-by: Xuehan Xu <xuxuehan@qianxin.com>
-rw-r--r--src/crimson/os/seastore/CMakeLists.txt2
-rw-r--r--src/crimson/os/seastore/async_cleaner.h1
-rw-r--r--src/crimson/os/seastore/backref/btree_backref_manager.h30
-rw-r--r--src/crimson/os/seastore/backref_manager.h1
-rw-r--r--src/crimson/os/seastore/backref_mapping.h27
-rw-r--r--src/crimson/os/seastore/btree/btree_range_pin.cc54
-rw-r--r--src/crimson/os/seastore/btree/btree_range_pin.h29
-rw-r--r--src/crimson/os/seastore/cached_extent.cc33
-rw-r--r--src/crimson/os/seastore/cached_extent.h61
-rw-r--r--src/crimson/os/seastore/lba_manager.h1
-rw-r--r--src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.cc39
-rw-r--r--src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.h16
-rw-r--r--src/crimson/os/seastore/lba_mapping.cc44
-rw-r--r--src/crimson/os/seastore/lba_mapping.h73
14 files changed, 221 insertions, 190 deletions
diff --git a/src/crimson/os/seastore/CMakeLists.txt b/src/crimson/os/seastore/CMakeLists.txt
index e5b8960c38c..3da5e65ceec 100644
--- a/src/crimson/os/seastore/CMakeLists.txt
+++ b/src/crimson/os/seastore/CMakeLists.txt
@@ -1,5 +1,6 @@
set(crimson_seastore_srcs
cached_extent.cc
+ lba_mapping.cc
seastore_types.cc
segment_manager.cc
segment_manager/ephemeral.cc
@@ -19,7 +20,6 @@ set(crimson_seastore_srcs
omap_manager.cc
omap_manager/btree/btree_omap_manager.cc
omap_manager/btree/omap_btree_node_impl.cc
- btree/btree_range_pin.cc
btree/fixed_kv_node.cc
onode.cc
onode_manager/staged-fltree/node.cc
diff --git a/src/crimson/os/seastore/async_cleaner.h b/src/crimson/os/seastore/async_cleaner.h
index 424247c5bdc..b907b1ffcea 100644
--- a/src/crimson/os/seastore/async_cleaner.h
+++ b/src/crimson/os/seastore/async_cleaner.h
@@ -17,6 +17,7 @@
#include "crimson/os/seastore/randomblock_manager_group.h"
#include "crimson/os/seastore/transaction.h"
#include "crimson/os/seastore/segment_seq_allocator.h"
+#include "crimson/os/seastore/backref_mapping.h"
namespace crimson::os::seastore {
diff --git a/src/crimson/os/seastore/backref/btree_backref_manager.h b/src/crimson/os/seastore/backref/btree_backref_manager.h
index 38084bb00e6..24897dd55da 100644
--- a/src/crimson/os/seastore/backref/btree_backref_manager.h
+++ b/src/crimson/os/seastore/backref/btree_backref_manager.h
@@ -9,44 +9,28 @@
namespace crimson::os::seastore::backref {
-constexpr size_t BACKREF_BLOCK_SIZE = 4096;
-
-class BtreeBackrefMapping : public BtreeNodeMapping<paddr_t, laddr_t> {
- extent_types_t type;
+class BtreeBackrefMapping : public BackrefMapping {
public:
BtreeBackrefMapping(op_context_t<paddr_t> ctx)
- : BtreeNodeMapping(ctx) {}
+ : BackrefMapping(ctx) {}
BtreeBackrefMapping(
op_context_t<paddr_t> ctx,
CachedExtentRef parent,
uint16_t pos,
backref_map_val_t &val,
backref_node_meta_t &&meta)
- : BtreeNodeMapping(
+ : BackrefMapping(
+ val.type,
ctx,
parent,
pos,
val.laddr,
val.len,
- std::forward<backref_node_meta_t>(meta)),
- type(val.type)
- {}
- extent_types_t get_type() const final {
- return type;
- }
-
- bool is_clone() const final {
- return false;
- }
-
-protected:
- std::unique_ptr<BtreeNodeMapping<paddr_t, laddr_t>> _duplicate(
- op_context_t<paddr_t> ctx) const final {
- return std::unique_ptr<BtreeNodeMapping<paddr_t, laddr_t>>(
- new BtreeBackrefMapping(ctx));
- }
+ std::forward<backref_node_meta_t>(meta)) {}
};
+constexpr size_t BACKREF_BLOCK_SIZE = 4096;
+
using BackrefBtree = FixedKVBtree<
paddr_t, backref_map_val_t, BackrefInternalNode,
BackrefLeafNode, BtreeBackrefMapping, BACKREF_BLOCK_SIZE, false>;
diff --git a/src/crimson/os/seastore/backref_manager.h b/src/crimson/os/seastore/backref_manager.h
index 3feedb997b4..8c746b571b2 100644
--- a/src/crimson/os/seastore/backref_manager.h
+++ b/src/crimson/os/seastore/backref_manager.h
@@ -6,6 +6,7 @@
#include "crimson/os/seastore/cache.h"
#include "crimson/os/seastore/cached_extent.h"
#include "crimson/os/seastore/transaction.h"
+#include "crimson/os/seastore/backref_mapping.h"
namespace crimson::os::seastore {
diff --git a/src/crimson/os/seastore/backref_mapping.h b/src/crimson/os/seastore/backref_mapping.h
new file mode 100644
index 00000000000..d0a6a0ea6ff
--- /dev/null
+++ b/src/crimson/os/seastore/backref_mapping.h
@@ -0,0 +1,27 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#pragma once
+
+#include "crimson/os/seastore/btree/btree_range_pin.h"
+
+namespace crimson::os::seastore {
+
+class BackrefMapping : public BtreeNodeMapping<paddr_t, laddr_t> {
+ extent_types_t type;
+public:
+ BackrefMapping(op_context_t<paddr_t> ctx)
+ : BtreeNodeMapping(ctx) {}
+ template <typename... T>
+ BackrefMapping(extent_types_t type, T&&... t)
+ : BtreeNodeMapping(std::forward<T>(t)...),
+ type(type) {}
+ extent_types_t get_type() const {
+ return type;
+ }
+};
+
+using BackrefMappingRef = std::unique_ptr<BackrefMapping>;
+using backref_pin_list_t = std::list<BackrefMappingRef>;
+
+} // namespace crimson::os::seastore
diff --git a/src/crimson/os/seastore/btree/btree_range_pin.cc b/src/crimson/os/seastore/btree/btree_range_pin.cc
deleted file mode 100644
index f0d507a24c4..00000000000
--- a/src/crimson/os/seastore/btree/btree_range_pin.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "crimson/os/seastore/btree/btree_range_pin.h"
-#include "crimson/os/seastore/btree/fixed_kv_node.h"
-
-namespace crimson::os::seastore {
-
-template <typename key_t, typename val_t>
-get_child_ret_t<LogicalCachedExtent>
-BtreeNodeMapping<key_t, val_t>::get_logical_extent(
- Transaction &t)
-{
- ceph_assert(is_parent_viewable());
- assert(pos != std::numeric_limits<uint16_t>::max());
- ceph_assert(t.get_trans_id() == ctx.trans.get_trans_id());
- auto &p = (FixedKVNode<key_t>&)*parent;
- auto k = this->is_indirect()
- ? this->get_intermediate_base()
- : get_key();
- auto v = p.template get_child<LogicalCachedExtent>(ctx, pos, k);
- if (!v.has_child()) {
- this->child_pos = v.get_child_pos();
- }
- return v;
-}
-
-template <typename key_t, typename val_t>
-bool BtreeNodeMapping<key_t, val_t>::is_stable() const
-{
- assert(!this->parent_modified());
- assert(pos != std::numeric_limits<uint16_t>::max());
- auto &p = (FixedKVNode<key_t>&)*parent;
- auto k = this->is_indirect()
- ? this->get_intermediate_base()
- : get_key();
- return p.is_child_stable(ctx, pos, k);
-}
-
-template <typename key_t, typename val_t>
-bool BtreeNodeMapping<key_t, val_t>::is_data_stable() const
-{
- assert(!this->parent_modified());
- assert(pos != std::numeric_limits<uint16_t>::max());
- auto &p = (FixedKVNode<key_t>&)*parent;
- auto k = this->is_indirect()
- ? this->get_intermediate_base()
- : get_key();
- return p.is_child_data_stable(ctx, pos, k);
-}
-
-template class BtreeNodeMapping<laddr_t, paddr_t>;
-template class BtreeNodeMapping<paddr_t, laddr_t>;
-} // namespace crimson::os::seastore
diff --git a/src/crimson/os/seastore/btree/btree_range_pin.h b/src/crimson/os/seastore/btree/btree_range_pin.h
index 91751801e5d..bfd350a8bed 100644
--- a/src/crimson/os/seastore/btree/btree_range_pin.h
+++ b/src/crimson/os/seastore/btree/btree_range_pin.h
@@ -7,11 +7,12 @@
#include "crimson/common/log.h"
-#include "crimson/os/seastore/cache.h"
#include "crimson/os/seastore/cached_extent.h"
#include "crimson/os/seastore/seastore_types.h"
+#include "crimson/os/seastore/transaction.h"
namespace crimson::os::seastore {
+class Cache;
template <typename node_key_t>
struct op_context_t {
@@ -116,8 +117,6 @@ protected:
extent_len_t len = 0;
fixed_kv_node_meta_t<key_t> range;
uint16_t pos = std::numeric_limits<uint16_t>::max();
-
- virtual std::unique_ptr<BtreeNodeMapping> _duplicate(op_context_t<key_t>) const = 0;
fixed_kv_node_meta_t<key_t> _get_pin_range() const {
return range;
}
@@ -139,11 +138,7 @@ public:
len(len),
range(meta),
pos(pos)
- {
- if (!parent->is_pending()) {
- this->child_pos = {parent, pos};
- }
- }
+ {}
CachedExtentRef get_parent() const final {
return parent;
@@ -162,11 +157,6 @@ public:
return len;
}
- extent_types_t get_type() const override {
- ceph_abort("should never happen");
- return extent_types_t::ROOT;
- }
-
val_t get_val() const final {
if constexpr (std::is_same_v<val_t, paddr_t>) {
return value.get_paddr();
@@ -180,16 +170,6 @@ public:
return range.begin;
}
- PhysicalNodeMappingRef<key_t, val_t> duplicate() const final {
- auto ret = _duplicate(ctx);
- ret->range = range;
- ret->value = value;
- ret->parent = parent;
- ret->len = len;
- ret->pos = pos;
- return ret;
- }
-
bool has_been_invalidated() const final {
return parent->has_been_invalidated();
}
@@ -215,9 +195,6 @@ public:
return unviewable;
}
- get_child_ret_t<LogicalCachedExtent> get_logical_extent(Transaction&) final;
- bool is_stable() const final;
- bool is_data_stable() const final;
bool is_parent_viewable() const final {
ceph_assert(parent);
if (!parent->is_valid()) {
diff --git a/src/crimson/os/seastore/cached_extent.cc b/src/crimson/os/seastore/cached_extent.cc
index ab2492f5bb6..49fede1d9a8 100644
--- a/src/crimson/os/seastore/cached_extent.cc
+++ b/src/crimson/os/seastore/cached_extent.cc
@@ -7,6 +7,7 @@
#include "crimson/common/log.h"
#include "crimson/os/seastore/btree/fixed_kv_node.h"
+#include "crimson/os/seastore/lba_mapping.h"
namespace {
[[maybe_unused]] seastar::logger& logger() {
@@ -142,6 +143,12 @@ void LogicalCachedExtent::on_replace_prior() {
parent->children[off] = this;
}
+void LogicalCachedExtent::maybe_set_intermediate_laddr(LBAMapping &mapping) {
+ laddr = mapping.is_indirect()
+ ? mapping.get_intermediate_base()
+ : mapping.get_key();
+}
+
parent_tracker_t::~parent_tracker_t() {
// this is parent's tracker, reset it
auto &p = (FixedKVNode<laddr_t>&)*parent;
@@ -150,32 +157,6 @@ parent_tracker_t::~parent_tracker_t() {
}
}
-std::ostream &operator<<(std::ostream &out, const LBAMapping &rhs)
-{
- out << "LBAMapping(" << rhs.get_key()
- << "~0x" << std::hex << rhs.get_length() << std::dec
- << "->" << rhs.get_val();
- if (rhs.is_indirect()) {
- out << ",indirect(" << rhs.get_intermediate_base()
- << "~0x" << std::hex << rhs.get_intermediate_length()
- << "@0x" << rhs.get_intermediate_offset() << std::dec
- << ")";
- }
- out << ")";
- return out;
-}
-
-std::ostream &operator<<(std::ostream &out, const lba_pin_list_t &rhs)
-{
- bool first = true;
- out << '[';
- for (const auto &i: rhs) {
- out << (first ? "" : ",") << *i;
- first = false;
- }
- return out << ']';
-}
-
bool BufferSpace::is_range_loaded(extent_len_t offset, extent_len_t length) const
{
assert(length > 0);
diff --git a/src/crimson/os/seastore/cached_extent.h b/src/crimson/os/seastore/cached_extent.h
index f9356f40b83..9dc60d719eb 100644
--- a/src/crimson/os/seastore/cached_extent.h
+++ b/src/crimson/os/seastore/cached_extent.h
@@ -1279,7 +1279,6 @@ private:
};
class ChildableCachedExtent;
-class LogicalCachedExtent;
class child_pos_t {
public:
@@ -1337,48 +1336,18 @@ using PhysicalNodeMappingRef = std::unique_ptr<PhysicalNodeMapping<key_t, val_t>
template <typename key_t, typename val_t>
class PhysicalNodeMapping {
public:
+ PhysicalNodeMapping() = default;
+ PhysicalNodeMapping(const PhysicalNodeMapping&) = delete;
virtual extent_len_t get_length() const = 0;
- virtual extent_types_t get_type() const = 0;
virtual val_t get_val() const = 0;
virtual key_t get_key() const = 0;
- virtual PhysicalNodeMappingRef<key_t, val_t> duplicate() const = 0;
- virtual PhysicalNodeMappingRef<key_t, val_t> refresh_with_pending_parent() {
- ceph_abort("impossible");
- return {};
- }
virtual bool has_been_invalidated() const = 0;
virtual CachedExtentRef get_parent() const = 0;
virtual uint16_t get_pos() const = 0;
- // An lba pin may be indirect, see comments in lba_manager/btree/btree_lba_manager.h
- virtual bool is_indirect() const { return false; }
- virtual key_t get_intermediate_key() const { return min_max_t<key_t>::null; }
- virtual key_t get_intermediate_base() const { return min_max_t<key_t>::null; }
- virtual extent_len_t get_intermediate_length() const { return 0; }
virtual uint32_t get_checksum() const {
ceph_abort("impossible");
return 0;
}
- // The start offset of the pin, must be 0 if the pin is not indirect
- virtual extent_len_t get_intermediate_offset() const {
- return std::numeric_limits<extent_len_t>::max();
- }
-
- virtual get_child_ret_t<LogicalCachedExtent>
- get_logical_extent(Transaction &t) = 0;
-
- void link_child(ChildableCachedExtent *c) {
- ceph_assert(child_pos);
- child_pos->link_child(c);
- }
-
- // For reserved mappings, the return values are
- // undefined although it won't crash
- virtual bool is_stable() const = 0;
- virtual bool is_data_stable() const = 0;
- virtual bool is_clone() const = 0;
- bool is_zero_reserved() const {
- return !get_val().is_real();
- }
virtual bool is_parent_viewable() const = 0;
virtual bool is_parent_valid() const = 0;
virtual bool parent_modified() const {
@@ -1391,24 +1360,8 @@ public:
}
virtual ~PhysicalNodeMapping() {}
-protected:
- std::optional<child_pos_t> child_pos = std::nullopt;
};
-using LBAMapping = PhysicalNodeMapping<laddr_t, paddr_t>;
-using LBAMappingRef = PhysicalNodeMappingRef<laddr_t, paddr_t>;
-
-std::ostream &operator<<(std::ostream &out, const LBAMapping &rhs);
-
-using lba_pin_list_t = std::list<LBAMappingRef>;
-
-std::ostream &operator<<(std::ostream &out, const lba_pin_list_t &rhs);
-
-using BackrefMapping = PhysicalNodeMapping<paddr_t, laddr_t>;
-using BackrefMappingRef = PhysicalNodeMappingRef<paddr_t, laddr_t>;
-
-using backref_pin_list_t = std::list<BackrefMappingRef>;
-
/**
* RetiredExtentPlaceholder
*
@@ -1522,6 +1475,8 @@ private:
return out;
}
};
+
+class LBAMapping;
/**
* LogicalCachedExtent
*
@@ -1556,11 +1511,7 @@ public:
laddr = nladdr;
}
- void maybe_set_intermediate_laddr(LBAMapping &mapping) {
- laddr = mapping.is_indirect()
- ? mapping.get_intermediate_base()
- : mapping.get_key();
- }
+ void maybe_set_intermediate_laddr(LBAMapping &mapping);
void apply_delta_and_adjust_crc(
paddr_t base, const ceph::bufferlist &bl) final {
@@ -1660,8 +1611,6 @@ using lextent_list_t = addr_extent_list_base_t<
}
#if FMT_VERSION >= 90000
-template <> struct fmt::formatter<crimson::os::seastore::lba_pin_list_t> : fmt::ostream_formatter {};
template <> struct fmt::formatter<crimson::os::seastore::CachedExtent> : fmt::ostream_formatter {};
template <> struct fmt::formatter<crimson::os::seastore::LogicalCachedExtent> : fmt::ostream_formatter {};
-template <> struct fmt::formatter<crimson::os::seastore::LBAMapping> : fmt::ostream_formatter {};
#endif
diff --git a/src/crimson/os/seastore/lba_manager.h b/src/crimson/os/seastore/lba_manager.h
index a050b2cdf47..9a34bf56157 100644
--- a/src/crimson/os/seastore/lba_manager.h
+++ b/src/crimson/os/seastore/lba_manager.h
@@ -19,6 +19,7 @@
#include "crimson/os/seastore/cache.h"
#include "crimson/os/seastore/seastore_types.h"
+#include "crimson/os/seastore/lba_mapping.h"
namespace crimson::os::seastore {
diff --git a/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.cc b/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.cc
index 007737ff450..888d3c359ac 100644
--- a/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.cc
+++ b/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.cc
@@ -94,6 +94,45 @@ void unlink_phy_tree_root_node<laddr_t>(RootBlockRef &root_block) {
namespace crimson::os::seastore::lba_manager::btree {
+get_child_ret_t<LogicalCachedExtent>
+BtreeLBAMapping::get_logical_extent(Transaction &t)
+{
+ ceph_assert(is_parent_viewable());
+ assert(pos != std::numeric_limits<uint16_t>::max());
+ ceph_assert(t.get_trans_id() == ctx.trans.get_trans_id());
+ auto &p = static_cast<LBALeafNode&>(*parent);
+ auto k = this->is_indirect()
+ ? this->get_intermediate_base()
+ : get_key();
+ auto v = p.template get_child<LogicalCachedExtent>(ctx, pos, k);
+ if (!v.has_child()) {
+ this->child_pos = v.get_child_pos();
+ }
+ return v;
+}
+
+bool BtreeLBAMapping::is_stable() const
+{
+ assert(!this->parent_modified());
+ assert(pos != std::numeric_limits<uint16_t>::max());
+ auto &p = static_cast<LBALeafNode&>(*parent);
+ auto k = this->is_indirect()
+ ? this->get_intermediate_base()
+ : get_key();
+ return p.is_child_stable(ctx, pos, k);
+}
+
+bool BtreeLBAMapping::is_data_stable() const
+{
+ assert(!this->parent_modified());
+ assert(pos != std::numeric_limits<uint16_t>::max());
+ auto &p = static_cast<LBALeafNode&>(*parent);
+ auto k = this->is_indirect()
+ ? this->get_intermediate_base()
+ : get_key();
+ return p.is_child_data_stable(ctx, pos, k);
+}
+
BtreeLBAManager::mkfs_ret
BtreeLBAManager::mkfs(
Transaction &t)
diff --git a/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.h b/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.h
index ef10ff9623b..e0902053d0e 100644
--- a/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.h
+++ b/src/crimson/os/seastore/lba_manager/btree/btree_lba_manager.h
@@ -23,11 +23,15 @@
#include "crimson/os/seastore/lba_manager/btree/lba_btree_node.h"
#include "crimson/os/seastore/btree/btree_range_pin.h"
+namespace crimson::os::seastore {
+class LogicalCachedExtent;
+}
+
namespace crimson::os::seastore::lba_manager::btree {
struct LBALeafNode;
-class BtreeLBAMapping : public BtreeNodeMapping<laddr_t, paddr_t> {
+class BtreeLBAMapping : public LBAMapping {
// To support cloning, there are two kinds of lba mappings:
// 1. physical lba mapping: the pladdr in the value of which is the paddr of
// the corresponding extent;
@@ -61,14 +65,14 @@ class BtreeLBAMapping : public BtreeNodeMapping<laddr_t, paddr_t> {
// their keys.
public:
BtreeLBAMapping(op_context_t<laddr_t> ctx)
- : BtreeNodeMapping(ctx) {}
+ : LBAMapping(ctx) {}
BtreeLBAMapping(
op_context_t<laddr_t> c,
LBALeafNodeRef parent,
uint16_t pos,
lba_map_val_t &val,
lba_node_meta_t meta)
- : BtreeNodeMapping(
+ : LBAMapping(
c,
parent,
pos,
@@ -190,8 +194,12 @@ public:
SUBDEBUGT(seastore_lba, "new pin {}", ctx.trans, static_cast<LBAMapping&>(*new_pin));
return new_pin;
}
+ bool is_stable() const final;
+ bool is_data_stable() const final;
+ get_child_ret_t<LogicalCachedExtent> get_logical_extent(Transaction &t);
+
protected:
- std::unique_ptr<BtreeNodeMapping<laddr_t, paddr_t>> _duplicate(
+ LBAMappingRef _duplicate(
op_context_t<laddr_t> ctx) const final {
auto pin = std::unique_ptr<BtreeLBAMapping>(new BtreeLBAMapping(ctx));
pin->key = key;
diff --git a/src/crimson/os/seastore/lba_mapping.cc b/src/crimson/os/seastore/lba_mapping.cc
new file mode 100644
index 00000000000..90fae09ce21
--- /dev/null
+++ b/src/crimson/os/seastore/lba_mapping.cc
@@ -0,0 +1,44 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "lba_mapping.h"
+
+namespace crimson::os::seastore {
+
+std::ostream &operator<<(std::ostream &out, const LBAMapping &rhs)
+{
+ out << "LBAMapping(" << rhs.get_key()
+ << "~0x" << std::hex << rhs.get_length() << std::dec
+ << "->" << rhs.get_val();
+ if (rhs.is_indirect()) {
+ out << ",indirect(" << rhs.get_intermediate_base()
+ << "~0x" << std::hex << rhs.get_intermediate_length()
+ << "@0x" << rhs.get_intermediate_offset() << std::dec
+ << ")";
+ }
+ out << ")";
+ return out;
+}
+
+std::ostream &operator<<(std::ostream &out, const lba_pin_list_t &rhs)
+{
+ bool first = true;
+ out << '[';
+ for (const auto &i: rhs) {
+ out << (first ? "" : ",") << *i;
+ first = false;
+ }
+ return out << ']';
+}
+
+LBAMappingRef LBAMapping::duplicate() const {
+ auto ret = _duplicate(ctx);
+ ret->range = range;
+ ret->value = value;
+ ret->parent = parent;
+ ret->len = len;
+ ret->pos = pos;
+ return ret;
+}
+
+} // namespace crimson::os::seastore
diff --git a/src/crimson/os/seastore/lba_mapping.h b/src/crimson/os/seastore/lba_mapping.h
new file mode 100644
index 00000000000..338d4d53f55
--- /dev/null
+++ b/src/crimson/os/seastore/lba_mapping.h
@@ -0,0 +1,73 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#pragma once
+
+#include "crimson/os/seastore/cached_extent.h"
+#include "crimson/os/seastore/btree/btree_range_pin.h"
+
+namespace crimson::os::seastore {
+
+class LBAMapping;
+using LBAMappingRef = std::unique_ptr<LBAMapping>;
+
+class LogicalCachedExtent;
+
+class LBAMapping : public BtreeNodeMapping<laddr_t, paddr_t> {
+public:
+ LBAMapping(op_context_t<laddr_t> ctx)
+ : BtreeNodeMapping<laddr_t, paddr_t>(ctx) {}
+ template <typename... T>
+ LBAMapping(T&&... t)
+ : BtreeNodeMapping<laddr_t, paddr_t>(std::forward<T>(t)...)
+ {
+ if (!parent->is_pending()) {
+ this->child_pos = {parent, pos};
+ }
+ }
+
+ // An lba pin may be indirect, see comments in lba_manager/btree/btree_lba_manager.h
+ virtual bool is_indirect() const = 0;
+ virtual laddr_t get_intermediate_key() const = 0;
+ virtual laddr_t get_intermediate_base() const = 0;
+ virtual extent_len_t get_intermediate_length() const = 0;
+ // The start offset of the pin, must be 0 if the pin is not indirect
+ virtual extent_len_t get_intermediate_offset() const = 0;
+
+ virtual get_child_ret_t<LogicalCachedExtent>
+ get_logical_extent(Transaction &t) = 0;
+
+ void link_child(ChildableCachedExtent *c) {
+ ceph_assert(child_pos);
+ child_pos->link_child(c);
+ }
+ virtual LBAMappingRef refresh_with_pending_parent() = 0;
+
+ // For reserved mappings, the return values are
+ // undefined although it won't crash
+ virtual bool is_stable() const = 0;
+ virtual bool is_data_stable() const = 0;
+ virtual bool is_clone() const = 0;
+ bool is_zero_reserved() const {
+ return !get_val().is_real();
+ }
+
+ LBAMappingRef duplicate() const;
+
+ virtual ~LBAMapping() {}
+protected:
+ virtual LBAMappingRef _duplicate(op_context_t<laddr_t>) const = 0;
+ std::optional<child_pos_t> child_pos = std::nullopt;
+};
+
+std::ostream &operator<<(std::ostream &out, const LBAMapping &rhs);
+using lba_pin_list_t = std::list<LBAMappingRef>;
+
+std::ostream &operator<<(std::ostream &out, const lba_pin_list_t &rhs);
+
+} // namespace crimson::os::seastore
+
+#if FMT_VERSION >= 90000
+template <> struct fmt::formatter<crimson::os::seastore::LBAMapping> : fmt::ostream_formatter {};
+template <> struct fmt::formatter<crimson::os::seastore::lba_pin_list_t> : fmt::ostream_formatter {};
+#endif