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<backref_node_meta_t>(meta)) {}
-};
-
constexpr size_t BACKREF_BLOCK_SIZE = 4096;
using BackrefBtree = FixedKVBtree<
namespace crimson::os::seastore {
class BackrefMapping {
- op_context_t ctx;
- CachedExtentRef parent;
- fixed_kv_node_meta_t<paddr_t> range;
- laddr_t value;
- extent_len_t len = 0;
- uint16_t pos = std::numeric_limits<uint16_t>::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<paddr_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<BackrefMapping>;
-using backref_pin_list_t = std::list<BackrefMappingRef>;
+using backref_mapping_list_t = std::list<BackrefMapping>;
} // namespace crimson::os::seastore
namespace crimson::os::seastore::lba_manager::btree {
-get_child_ret_t<lba_manager::btree::LBALeafNode, LogicalChildNode>
-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();
- return p.template get_child<LogicalChildNode>(ctx.trans, ctx.cache, pos, k);
-}
-
-bool BtreeLBAMapping::is_stable() const
-{
- assert(!parent_modified());
- assert(pos != std::numeric_limits<uint16_t>::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<uint16_t>::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)
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<extent_len_t>(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<LBALeafNode&>(*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<LBALeafNode&>(*parent);
- p.maybe_fix_mapping_pos(*this);
- SUBDEBUGT(seastore_lba, "fixed pin {}",
- ctx.trans, static_cast<LBAMapping&>(*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<LBALeafNode&>(*parent);
- auto &viewable_p = static_cast<LBALeafNode&>(
- *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<LBAMapping&>(*new_pin));
- return new_pin;
- }
- bool is_stable() const final;
- bool is_data_stable() const final;
- get_child_ret_t<lba_manager::btree::LBALeafNode, LogicalChildNode>
- get_logical_extent(Transaction &t);
-
-protected:
- LBAMappingRef _duplicate(
- op_context_t ctx) const final {
- auto pin = std::unique_ptr<BtreeLBAMapping>(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<BtreeLBAMapping>;
-
using LBABtree = FixedKVBtree<
laddr_t, lba_map_val_t, LBAInternalNode,
LBALeafNode, LBACursor, LBA_BLOCK_SIZE>;
// -*- 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 {
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<LBALeafNode, LogicalChildNode>
+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<LBALeafNode>();
+ return p->template get_child<LogicalChildNode>(
+ 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<LBALeafNode>();
+ 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<LBALeafNode>();
+ return leaf->is_child_data_stable(
+ direct_cursor->ctx,
+ direct_cursor->pos,
+ direct_cursor->key);
}
} // namespace crimson::os::seastore
namespace crimson::os::seastore {
-class LBAMapping;
-using LBAMappingRef = std::unique_ptr<LBAMapping>;
-
-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<laddr_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<lba_manager::btree::LBALeafNode, LogicalChildNode>
- 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<lba_manager::btree::LBALeafNode, LogicalChildNode>
+ 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<laddr_t> range;
- uint16_t pos = std::numeric_limits<uint16_t>::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<LBAMappingRef>;
+using lba_mapping_list_t = std::list<LBAMapping>;
-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<crimson::os::seastore::LBAMapping> : fmt::ostream_formatter {};
-template <> struct fmt::formatter<crimson::os::seastore::lba_pin_list_t> : fmt::ostream_formatter {};
+template <> struct fmt::formatter<crimson::os::seastore::lba_mapping_list_t> : fmt::ostream_formatter {};
#endif
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()) {
/*
* 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;