From 295544f7a9d4a09a3c611f6f3de9c59bbc6a7bc7 Mon Sep 17 00:00:00 2001 From: Zhang Song Date: Tue, 22 Apr 2025 16:25:28 +0800 Subject: [PATCH] crimson/os/seastore: refactor LBAMapping and BackrefMapping Signed-off-by: Zhang Song (cherry picked from commit 23883c91d5f80032a54609fc95ad2a7606509f5b) --- .../seastore/backref/btree_backref_manager.h | 18 -- src/crimson/os/seastore/backref_mapping.h | 62 ++--- .../lba_manager/btree/btree_lba_manager.cc | 31 --- .../lba_manager/btree/btree_lba_manager.h | 200 ---------------- src/crimson/os/seastore/lba_mapping.cc | 52 ++++- src/crimson/os/seastore/lba_mapping.h | 213 +++++++++++------- .../os/seastore/object_data_handler.cc | 2 +- src/crimson/os/seastore/transaction_manager.h | 4 +- 8 files changed, 212 insertions(+), 370 deletions(-) diff --git a/src/crimson/os/seastore/backref/btree_backref_manager.h b/src/crimson/os/seastore/backref/btree_backref_manager.h index b7d84845c33..fec9cd821eb 100644 --- a/src/crimson/os/seastore/backref/btree_backref_manager.h +++ b/src/crimson/os/seastore/backref/btree_backref_manager.h @@ -9,24 +9,6 @@ namespace crimson::os::seastore::backref { -class BtreeBackrefMapping : public BackrefMapping { -public: - BtreeBackrefMapping( - op_context_t ctx, - BackrefLeafNodeRef parent, - uint16_t pos, - backref_map_val_t &val, - backref_node_meta_t &&meta) - : BackrefMapping( - val.type, - ctx, - parent, - pos, - val.laddr, - val.len, - std::forward(meta)) {} -}; - constexpr size_t BACKREF_BLOCK_SIZE = 4096; using BackrefBtree = FixedKVBtree< diff --git a/src/crimson/os/seastore/backref_mapping.h b/src/crimson/os/seastore/backref_mapping.h index 399983de7bc..cda6285862f 100644 --- a/src/crimson/os/seastore/backref_mapping.h +++ b/src/crimson/os/seastore/backref_mapping.h @@ -8,50 +8,52 @@ namespace crimson::os::seastore { class BackrefMapping { - op_context_t ctx; - CachedExtentRef parent; - fixed_kv_node_meta_t range; - laddr_t value; - extent_len_t len = 0; - uint16_t pos = std::numeric_limits::max(); - extent_types_t type; + BackrefCursorRef cursor; + + BackrefMapping(BackrefCursorRef cursor) + : cursor(std::move(cursor)) {} + public: - BackrefMapping( - extent_types_t type, - op_context_t ctx, - CachedExtentRef parent, - uint16_t pos, - laddr_t value, - extent_len_t len, - fixed_kv_node_meta_t meta) - : ctx(ctx), - parent(parent), - range(meta), - value(value), - len(len), - pos(pos), - type(type) - {} + static BackrefMapping create(BackrefCursorRef cursor) { + return BackrefMapping(std::move(cursor)); + } + + BackrefMapping() = default; + + BackrefMapping(const BackrefMapping &) = delete; + BackrefMapping(BackrefMapping &&) = default; + + BackrefMapping &operator=(const BackrefMapping &) = delete; + BackrefMapping &operator=(BackrefMapping &&) = default; + + ~BackrefMapping() = default; + + bool is_viewable() const { + assert(cursor); + return cursor->is_viewable(); + } extent_len_t get_length() const { - ceph_assert(range.end > range.begin); - return len; + assert(cursor); + return cursor->get_length(); } laddr_t get_val() const { - return value; + assert(cursor); + return cursor->get_laddr(); } paddr_t get_key() const { - return range.begin; + assert(cursor); + return cursor->get_paddr(); } extent_types_t get_type() const { - return type; + assert(cursor); + return cursor->get_type(); } }; -using BackrefMappingRef = std::unique_ptr; -using backref_pin_list_t = std::list; +using backref_mapping_list_t = std::list; } // 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 cb0a7f61fbd..c7a91f95cc7 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 @@ -89,37 +89,6 @@ template class TreeRootLinker; namespace crimson::os::seastore::lba_manager::btree { -get_child_ret_t -BtreeLBAMapping::get_logical_extent(Transaction &t) -{ - ceph_assert(is_parent_viewable()); - assert(pos != std::numeric_limits::max()); - ceph_assert(t.get_trans_id() == ctx.trans.get_trans_id()); - auto &p = static_cast(*parent); - auto k = this->is_indirect() - ? this->get_intermediate_base() - : get_key(); - return p.template get_child(ctx.trans, ctx.cache, pos, k); -} - -bool BtreeLBAMapping::is_stable() const -{ - assert(!parent_modified()); - assert(pos != std::numeric_limits::max()); - auto &p = (LBALeafNode&)*parent; - auto k = is_indirect() ? get_intermediate_base() : get_key(); - return p.is_child_stable(ctx, pos, k); -} - -bool BtreeLBAMapping::is_data_stable() const -{ - assert(!parent_modified()); - assert(pos != std::numeric_limits::max()); - auto &p = (LBALeafNode&)*parent; - auto k = is_indirect() ? 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 6b265326d24..83831d45cbb 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 @@ -29,206 +29,6 @@ class LogicalCachedExtent; namespace crimson::os::seastore::lba_manager::btree { -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; -// 2. indirect lba mapping: the pladdr in the value of which is an laddr pointing -// to the physical lba mapping that's pointing to the actual paddr of the -// extent being searched; -// -// Accordingly, BtreeLBAMapping may also work under two modes: indirect or direct -// 1. BtreeLBAMappings that come from quering an indirect lba mapping in the lba tree -// are indirect; -// 2. BtreeLBAMappings that come from quering a physical lba mapping in the lba tree -// are direct. -// -// For direct BtreeLBAMappings, there are two important fields: -// 1. key: the laddr of the lba mapping being queried; -// 2. paddr: the paddr recorded in the value of the lba mapping being queried. -// For indirect BtreeLBAMappings, BtreeLBAMapping has three important fields: -// 1. key: the laddr key of the lba entry being queried; -// 2. intermediate_key: the laddr within the scope of the physical lba mapping -// that the current indirect lba mapping points to; although an indirect mapping -// points to the start of the physical lba mapping, it may change to other -// laddr after remap -// 3. intermediate_base: the laddr key of the physical lba mapping, intermediate_key -// and intermediate_base should be the same when doing cloning -// 4. intermediate_offset: intermediate_key - intermediate_base -// 5. intermediate_length: the length of the actual physical lba mapping -// 6. paddr: the paddr recorded in the physical lba mapping pointed to by the -// indirect lba mapping being queried; -// -// NOTE THAT, for direct BtreeLBAMappings, their intermediate_keys are the same as -// their keys. -public: - BtreeLBAMapping(op_context_t ctx) - : LBAMapping(ctx) {} - BtreeLBAMapping( - op_context_t c, - LBALeafNodeRef parent, - uint16_t pos, - lba_map_val_t &val, - lba_node_meta_t meta) - : LBAMapping( - c, - parent, - pos, - val.pladdr.is_paddr() ? val.pladdr.get_paddr() : P_ADDR_NULL, - val.len, - meta), - key(meta.begin), - indirect(val.pladdr.is_laddr()), - intermediate_key(indirect ? val.pladdr.get_laddr() : L_ADDR_NULL), - intermediate_length(indirect ? val.len : 0), - raw_val(val.pladdr), - map_val(val), - parent_modifications(parent->modifications) - {} - - lba_map_val_t get_map_val() const { - return map_val; - } - - bool is_indirect() const final { - return indirect; - } - - void make_indirect( - laddr_t new_key, - extent_len_t length, - laddr_t interkey = L_ADDR_NULL) - { - assert(!indirect); - indirect = true; - intermediate_base = key; - intermediate_length = len; - adjust_mutable_indirect_attrs(new_key, length, interkey); - } - - laddr_t get_key() const final { - return key; - } - - pladdr_t get_raw_val() const { - return raw_val; - } - - laddr_t get_intermediate_key() const final { - assert(is_indirect()); - assert(intermediate_key != L_ADDR_NULL); - return intermediate_key; - } - - laddr_t get_intermediate_base() const final { - assert(is_indirect()); - assert(intermediate_base != L_ADDR_NULL); - return intermediate_base; - } - - extent_len_t get_intermediate_offset() const final { - assert(intermediate_key >= intermediate_base); - assert((intermediate_key == L_ADDR_NULL) - == (intermediate_base == L_ADDR_NULL)); - return intermediate_key.get_byte_distance(intermediate_base); - } - - extent_len_t get_intermediate_length() const final { - assert(is_indirect()); - assert(intermediate_length); - return intermediate_length; - } - - bool is_clone() const final { - return get_map_val().refcount > 1; - } - - uint32_t get_checksum() const final { - return get_map_val().checksum; - } - - void adjust_mutable_indirect_attrs( - laddr_t new_key, - extent_len_t length, - laddr_t interkey = L_ADDR_NULL) - { - assert(indirect); - assert(value.is_paddr()); - intermediate_key = (interkey == L_ADDR_NULL ? key : interkey); - key = new_key; - len = length; - } - - uint64_t get_parent_modifications() const { - return parent_modifications; - } - - bool parent_modified() const final { - ceph_assert(parent); - ceph_assert(is_parent_viewable()); - auto &p = static_cast(*parent); - return p.modified_since(parent_modifications); - } - - void maybe_fix_pos() final { - assert(is_parent_viewable()); - if (!parent_modified()) { - return; - } - LOG_PREFIX(BtreeLBAMapping::maybe_fix_pos); - auto &p = static_cast(*parent); - p.maybe_fix_mapping_pos(*this); - SUBDEBUGT(seastore_lba, "fixed pin {}", - ctx.trans, static_cast(*this)); - } - - LBAMappingRef refresh_with_pending_parent() final { - LOG_PREFIX(BtreeLBAMapping::refresh_with_pending_parent); - assert(is_parent_valid() && !is_parent_viewable()); - auto &p = static_cast(*parent); - auto &viewable_p = static_cast( - *p.find_pending_version(ctx.trans, get_key())); - auto new_pin = viewable_p.get_mapping(ctx, get_key()); - SUBDEBUGT(seastore_lba, "new pin {}", ctx.trans, static_cast(*new_pin)); - return new_pin; - } - bool is_stable() const final; - bool is_data_stable() const final; - get_child_ret_t - get_logical_extent(Transaction &t); - -protected: - LBAMappingRef _duplicate( - op_context_t ctx) const final { - auto pin = std::unique_ptr(new BtreeLBAMapping(ctx)); - pin->key = key; - pin->intermediate_base = intermediate_base; - pin->intermediate_key = intermediate_key; - pin->intermediate_length = intermediate_length; - pin->indirect = indirect; - pin->raw_val = raw_val; - pin->map_val = map_val; - pin->parent_modifications = parent_modifications; - return pin; - } -private: - void _new_pos(uint16_t pos) { - this->pos = pos; - } - - laddr_t key = L_ADDR_NULL; - bool indirect = false; - laddr_t intermediate_key = L_ADDR_NULL; - laddr_t intermediate_base = L_ADDR_NULL; - extent_len_t intermediate_length = 0; - pladdr_t raw_val; - lba_map_val_t map_val; - uint64_t parent_modifications = 0; - friend struct LBALeafNode; -}; - -using BtreeLBAMappingRef = std::unique_ptr; - using LBABtree = FixedKVBtree< laddr_t, lba_map_val_t, LBAInternalNode, LBALeafNode, LBACursor, LBA_BLOCK_SIZE>; diff --git a/src/crimson/os/seastore/lba_mapping.cc b/src/crimson/os/seastore/lba_mapping.cc index 90fae09ce21..d52233869bb 100644 --- a/src/crimson/os/seastore/lba_mapping.cc +++ b/src/crimson/os/seastore/lba_mapping.cc @@ -1,7 +1,7 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab -#include "lba_mapping.h" +#include "crimson/os/seastore/lba_mapping.h" namespace crimson::os::seastore { @@ -20,25 +20,55 @@ std::ostream &operator<<(std::ostream &out, const LBAMapping &rhs) return out; } -std::ostream &operator<<(std::ostream &out, const lba_pin_list_t &rhs) +std::ostream &operator<<(std::ostream &out, const lba_mapping_list_t &rhs) { bool first = true; out << '['; for (const auto &i: rhs) { - out << (first ? "" : ",") << *i; + 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; +using lba_manager::btree::LBALeafNode; + +get_child_ret_t +LBAMapping::get_logical_extent(Transaction &t) +{ + assert(is_linked_direct()); + ceph_assert(direct_cursor->is_viewable()); + ceph_assert(direct_cursor->ctx.trans.get_trans_id() + == t.get_trans_id()); + assert(!direct_cursor->is_end()); + auto &i = *direct_cursor; + assert(i.pos != BTREENODE_POS_NULL); + ceph_assert(t.get_trans_id() == i.ctx.trans.get_trans_id()); + auto p = direct_cursor->parent->cast(); + return p->template get_child( + t, i.ctx.cache, i.pos, i.key); +} + +bool LBAMapping::is_stable() const { + assert(is_linked_direct()); + ceph_assert(direct_cursor->is_viewable()); + assert(!direct_cursor->is_end()); + auto leaf = direct_cursor->parent->cast(); + return leaf->is_child_stable( + direct_cursor->ctx, + direct_cursor->pos, + direct_cursor->key); +} + +bool LBAMapping::is_data_stable() const { + assert(is_linked_direct()); + ceph_assert(direct_cursor->is_viewable()); + assert(!direct_cursor->is_end()); + auto leaf = direct_cursor->parent->cast(); + return leaf->is_child_data_stable( + direct_cursor->ctx, + direct_cursor->pos, + direct_cursor->key); } } // namespace crimson::os::seastore diff --git a/src/crimson/os/seastore/lba_mapping.h b/src/crimson/os/seastore/lba_mapping.h index c913bcb10ec..05f987e8def 100644 --- a/src/crimson/os/seastore/lba_mapping.h +++ b/src/crimson/os/seastore/lba_mapping.h @@ -10,114 +10,173 @@ namespace crimson::os::seastore { -class LBAMapping; -using LBAMappingRef = std::unique_ptr; - -class LogicalCachedExtent; +namespace lba_manager::btree { +class BtreeLBAManager; +} class LBAMapping { -public: - LBAMapping(op_context_t ctx) - : ctx(ctx) {} - LBAMapping( - op_context_t ctx, - CachedExtentRef parent, - uint16_t pos, - pladdr_t value, - extent_len_t len, - fixed_kv_node_meta_t meta) - : ctx(ctx), - parent(parent), - value(value), - len(len), - range(meta), - pos(pos) - {} - - CachedExtentRef get_parent() { - return parent; - } - - uint16_t get_pos() const { - return pos; + LBAMapping(LBACursorRef direct, LBACursorRef indirect) + : direct_cursor(std::move(direct)), + indirect_cursor(std::move(indirect)) + { + assert(is_linked_direct()); + assert(!direct_cursor->is_indirect()); + assert(!indirect_cursor || indirect_cursor->is_indirect()); } - extent_len_t get_length() const { - ceph_assert(range.end > range.begin); - return len; +public: + static LBAMapping create_indirect( + LBACursorRef direct, LBACursorRef indirect) { + return LBAMapping(std::move(direct), std::move(indirect)); } - paddr_t get_val() const { - return value.get_paddr(); + static LBAMapping create_direct(LBACursorRef direct) { + return LBAMapping(std::move(direct), nullptr); } - virtual laddr_t get_key() const { - return range.begin; - } + LBAMapping(const LBAMapping &) = delete; + LBAMapping(LBAMapping &&) = default; + LBAMapping &operator=(const LBAMapping &) = delete; + LBAMapping &operator=(LBAMapping &&) = default; + ~LBAMapping() = default; - bool has_been_invalidated() const { - return parent->has_been_invalidated(); + bool is_linked_direct() const { + return (bool)direct_cursor; } - bool is_parent_viewable() const { - ceph_assert(parent); - return parent->is_viewable_by_trans(ctx.trans).first; + bool is_indirect() const { + assert(is_linked_direct()); + return (bool)indirect_cursor; } - bool is_parent_valid() const { - ceph_assert(parent); - return parent->is_valid(); + bool is_viewable() const { + assert(is_linked_direct()); + return direct_cursor->is_viewable() + && (!indirect_cursor || indirect_cursor->is_viewable()); } - virtual void maybe_fix_pos() = 0; - virtual bool parent_modified() const = 0; - virtual uint32_t get_checksum() const = 0; - - // 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 - get_logical_extent(Transaction &t) = 0; - - 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_stable() const; + bool is_data_stable() const; + bool is_clone() const { + assert(is_linked_direct()); + return direct_cursor->get_refcount() > 1; + } bool is_zero_reserved() const { + assert(is_linked_direct()); return get_val().is_zero(); } - LBAMappingRef duplicate() const; + extent_len_t get_length() const { + assert(is_linked_direct()); + if (is_indirect()) { + return indirect_cursor->get_length(); + } + return direct_cursor->get_length(); + } - virtual ~LBAMapping() {} -protected: - virtual LBAMappingRef _duplicate(op_context_t) const = 0; + paddr_t get_val() const { + assert(is_linked_direct()); + return direct_cursor->get_paddr(); + } + + checksum_t get_checksum() const { + assert(is_linked_direct()); + return direct_cursor->get_checksum(); + } + + laddr_t get_key() const { + assert(is_linked_direct()); + if (is_indirect()) { + return indirect_cursor->get_laddr(); + } + return direct_cursor->get_laddr(); + } - op_context_t ctx; - CachedExtentRef parent; + // An lba pin may be indirect, see comments in lba_manager/btree/btree_lba_manager.h + laddr_t get_intermediate_key() const { + assert(is_indirect()); + return indirect_cursor->get_intermediate_key(); + } + laddr_t get_intermediate_base() const { + assert(is_linked_direct()); + return direct_cursor->get_laddr(); + } + extent_len_t get_intermediate_length() const { + assert(is_linked_direct()); + return direct_cursor->get_length(); + } + // The start offset of the indirect cursor related to direct cursor + extent_len_t get_intermediate_offset() const { + assert(is_indirect()); + assert(get_intermediate_base() <= get_intermediate_key()); + assert(get_intermediate_key() + get_length() <= + get_intermediate_base() + get_intermediate_length()); + return get_intermediate_base().get_byte_distance< + extent_len_t>(get_intermediate_key()); + } + + get_child_ret_t + get_logical_extent(Transaction &t); + + LBAMapping duplicate() const { + auto dup_iter = [](const LBACursorRef &iter) -> LBACursorRef { + if (iter) { + return iter->duplicate(); + } else { + return nullptr; + } + }; + return LBAMapping(dup_iter(direct_cursor), dup_iter(indirect_cursor)); + } - pladdr_t value; - extent_len_t len = 0; - fixed_kv_node_meta_t range; - uint16_t pos = std::numeric_limits::max(); +private: + friend lba_manager::btree::BtreeLBAManager; + + // To support cloning, there are two kinds of lba mappings: + // 1. direct lba mapping: the pladdr in the value of which is the paddr of + // the corresponding extent; + // 2. indirect lba mapping: the pladdr in the value of which is an laddr pointing + // to the direct lba mapping that's pointing to the actual paddr of the + // extent being searched; + // + // Accordingly, LBAMapping may also work under two modes: indirect or direct + // 1. LBAMappings that come from quering an indirect lba mapping in the lba tree + // are indirect; + // 2. LBAMappings that come from quering a direct lba mapping in the lba tree + // are direct. + // + // For direct LBAMappings, there are two important properties: + // 1. key: the laddr of the lba mapping being queried; + // 2. paddr: the paddr recorded in the value of the lba mapping being queried. + // For indirect LBAMappings, LBAMapping has three important properties: + // 1. key: the laddr key of the lba entry being queried; + // 2. intermediate_key: the laddr within the scope of the direct lba mapping + // that the current indirect lba mapping points to; although an indirect mapping + // points to the start of the direct lba mapping, it may change to other + // laddr after remap + // 3. intermediate_base: the laddr key of the direct lba mapping, intermediate_key + // and intermediate_base should be the same when doing cloning + // 4. intermediate_offset: intermediate_key - intermediate_base + // 5. intermediate_length: the length of the actual direct lba mapping + // 6. paddr: the paddr recorded in the direct lba mapping pointed to by the + // indirect lba mapping being queried; + // + // NOTE THAT, for direct LBAMappings, their intermediate_keys are the same as + // their keys. + LBACursorRef direct_cursor; + LBACursorRef indirect_cursor; }; std::ostream &operator<<(std::ostream &out, const LBAMapping &rhs); -using lba_pin_list_t = std::list; +using lba_mapping_list_t = std::list; -std::ostream &operator<<(std::ostream &out, const lba_pin_list_t &rhs); +std::ostream &operator<<(std::ostream &out, const lba_mapping_list_t &rhs); } // namespace crimson::os::seastore #if FMT_VERSION >= 90000 template <> struct fmt::formatter : fmt::ostream_formatter {}; -template <> struct fmt::formatter : fmt::ostream_formatter {}; +template <> struct fmt::formatter : fmt::ostream_formatter {}; #endif diff --git a/src/crimson/os/seastore/object_data_handler.cc b/src/crimson/os/seastore/object_data_handler.cc index 8f817a521cf..47ab0bb223a 100644 --- a/src/crimson/os/seastore/object_data_handler.cc +++ b/src/crimson/os/seastore/object_data_handler.cc @@ -721,7 +721,7 @@ public: left_operation(overwrite_operation_t::UNKNOWN), right_operation(overwrite_operation_t::UNKNOWN), block_size(block_size), - // TODO: introduce PhysicalNodeMapping::is_fresh() + // TODO: introduce LBAMapping::is_fresh() // Note: fresh write can be merged with overwrite if they overlap. is_left_fresh(!pins.front()->is_stable()), is_right_fresh(!pins.back()->is_stable()) { diff --git a/src/crimson/os/seastore/transaction_manager.h b/src/crimson/os/seastore/transaction_manager.h index 4fffcbc88f4..4c12a0109ae 100644 --- a/src/crimson/os/seastore/transaction_manager.h +++ b/src/crimson/os/seastore/transaction_manager.h @@ -670,9 +670,9 @@ public: /* * clone_mapping * - * create an indirect lba mapping pointing to the physical + * create an indirect lba mapping pointing to the direct * lba mapping whose key is intermediate_key. Resort to btree_lba_manager.h - * for the definition of "indirect lba mapping" and "physical lba mapping". + * for the definition of "indirect lba mapping" and "direct lba mapping". * Note that the cloned extent must be stable */ using clone_extent_iertr = alloc_extent_iertr; -- 2.39.5