set(crimson_seastore_srcs
cached_extent.cc
lba_mapping.cc
+ logical_child_node.cc
seastore_types.cc
segment_manager.cc
segment_manager/ephemeral.cc
omap_manager.cc
omap_manager/btree/btree_omap_manager.cc
omap_manager/btree/omap_btree_node_impl.cc
- btree/fixed_kv_node.cc
onode.cc
onode_manager/staged-fltree/node.cc
onode_manager/staged-fltree/node_extent_manager.cc
#include "crimson/os/seastore/btree/fixed_kv_node.h"
+namespace crimson::os::seastore {
+class LogicalChildNode;
+}
+
namespace crimson::os::seastore::backref {
using backref_node_meta_t = fixed_kv_node_meta_t<paddr_t>;
check_capacity(BACKREF_NODE_SIZE),
"INTERNAL_NODE_CAPACITY doesn't fit in BACKREF_NODE_SIZE");
public:
+ using key_type = paddr_t;
template <typename... T>
BackrefInternalNode(T&&... t) :
FixedKVInternalNode(std::forward<T>(t)...) {}
paddr_t, paddr_le_t,
backref_map_val_t, backref_map_val_le_t,
BACKREF_NODE_SIZE,
+ BackrefInternalNode,
BackrefLeafNode,
+ LogicalChildNode,
false> {
static_assert(
check_capacity(BACKREF_NODE_SIZE),
"LEAF_NODE_CAPACITY doesn't fit in BACKREF_NODE_SIZE");
public:
+ using key_type = paddr_t;
template <typename... T>
BackrefLeafNode(T&&... t) :
FixedKVLeafNode(std::forward<T>(t)...) {}
const_iterator iter,
paddr_t key,
backref_map_val_t val,
- LogicalCachedExtent*) final {
+ LogicalChildNode*) final {
journal_insert(
iter,
key,
void update(
const_iterator iter,
backref_map_val_t val,
- LogicalCachedExtent*) final {
+ LogicalChildNode*) final {
return journal_update(
iter,
val,
}
}
-template <typename ROOT>
-void link_phy_tree_root_node(RootBlockRef &root_block, ROOT* backref_root) {
- root_block->backref_root_node = backref_root;
- ceph_assert(backref_root != nullptr);
- backref_root->root_block = root_block;
-}
-
-template void link_phy_tree_root_node(
- RootBlockRef &root_block, backref::BackrefInternalNode* backref_root);
-template void link_phy_tree_root_node(
- RootBlockRef &root_block, backref::BackrefLeafNode* backref_root);
-template void link_phy_tree_root_node(
- RootBlockRef &root_block, backref::BackrefNode* backref_root);
+template <typename RootT>
+class TreeRootLinker<RootBlock, RootT> {
+public:
+ static void link_root(RootBlockRef &root_block, RootT* backref_root) {
+ root_block->backref_root_node = backref_root;
+ ceph_assert(backref_root != nullptr);
+ backref_root->parent_of_root = root_block;
+ }
+ static void unlink_root(RootBlockRef &root_block) {
+ root_block->backref_root_node = nullptr;
+ }
+};
-template <>
-void unlink_phy_tree_root_node<paddr_t>(RootBlockRef &root_block) {
- root_block->backref_root_node = nullptr;
-}
+template class TreeRootLinker<RootBlock, backref::BackrefInternalNode>;
+template class TreeRootLinker<RootBlock, backref::BackrefLeafNode>;
}
: BackrefMapping(ctx) {}
BtreeBackrefMapping(
op_context_t<paddr_t> ctx,
- CachedExtentRef parent,
+ BackrefLeafNodeRef parent,
uint16_t pos,
backref_map_val_t &val,
backref_node_meta_t &&meta)
#include "crimson/os/seastore/seastore_types.h"
#include "crimson/os/seastore/btree/btree_range_pin.h"
#include "crimson/os/seastore/root_block.h"
+#include "crimson/os/seastore/linked_tree_node.h"
namespace crimson::os::seastore::lba_manager::btree {
struct lba_map_val_t;
namespace crimson::os::seastore {
-bool is_valid_child_ptr(ChildableCachedExtent* child);
-
-bool is_reserved_ptr(ChildableCachedExtent* child);
-
-inline ChildableCachedExtent* get_reserved_ptr() {
- return (ChildableCachedExtent*)0x1;
-}
-
template <typename T>
phy_tree_root_t& get_phy_tree_root(root_t& r);
const RootBlockRef &root_block,
op_context_t<key_t> c);
-template <typename ROOT_T>
-void link_phy_tree_root_node(RootBlockRef &root_block, ROOT_T* root_node);
-
-template <typename T>
-void unlink_phy_tree_root_node(RootBlockRef &root_block);
-
template <typename T>
Transaction::tree_stats_t& get_tree_stats(Transaction &t);
template <typename T>
void set_root_node(const TCachedExtentRef<T> &root_node) {
static_assert(std::is_base_of_v<typename internal_node_t::base_t, T>);
- link_phy_tree_root_node(root_block, root_node.get());
+ TreeRootLinker<RootBlock, T>::link_root(root_block, root_node.get());
}
auto get_root_node(op_context_t<node_key_t> c) const {
root_leaf->range = meta;
get_tree_stats<self_type>(c.trans).depth = 1u;
get_tree_stats<self_type>(c.trans).extents_num_delta++;
- link_phy_tree_root_node(root_block, root_leaf.get());
+ TreeRootLinker<RootBlock, leaf_node_t>::link_root(root_block, root_leaf.get());
return phy_tree_root_t{root_leaf->get_paddr(), 1u};
}
return upper_bound(c, min_max_t<node_key_t>::max);
}
+#ifdef UNIT_TESTS_BUILT
template <typename child_node_t, typename node_t, bool lhc = leaf_has_children,
typename std::enable_if<lhc, int>::type = 0>
void check_node(
if (node->is_pending()) {
auto &n = node->get_stable_for_key(i->get_key());
assert(cnode->get_parent_node().get() == &n);
- auto pos = n.lower_bound_offset(i->get_key());
- assert(pos < n.get_node_size());
+ auto pos = n.lower_bound(i->get_key()).get_offset();
+ assert(pos < n.get_size());
assert(n.children[pos] == cnode.get());
} else {
assert(cnode->get_parent_node().get() == node.get());
if (node->is_mutation_pending()) {
auto &n = node->get_stable_for_key(i->get_key());
assert(prior.get_parent_node().get() == &n);
- auto pos = n.lower_bound_offset(i->get_key());
- assert(pos < n.get_node_size());
+ auto pos = n.lower_bound(i->get_key()).get_offset();
+ assert(pos < n.get_size());
assert(n.children[pos] == &prior);
} else {
assert(prior.get_parent_node().get() == node.get());
ceph_abort("impossible");
}
} else if (ret == Transaction::get_extent_ret::ABSENT) {
- ChildableCachedExtent* child = nullptr;
+ BaseChildNode<std::remove_reference_t<decltype(*node)>,
+ node_key_t>* child = nullptr;
if (node->is_pending()) {
auto &n = node->get_stable_for_key(i->get_key());
- auto pos = n.lower_bound_offset(i->get_key());
- assert(pos < n.get_node_size());
+ auto pos = n.lower_bound(i->get_key()).get_offset();
+ assert(pos < n.get_size());
child = n.children[pos];
} else {
child = node->children[i->get_offset()];
}
}
} else {
- auto c = (child_node_t*)child;
+ auto c = static_cast<child_node_t*>(child);
assert(c->has_parent_tracker());
assert(c->get_parent_node().get() == node.get()
|| (node->is_pending() && c->is_stable()
if (depth > 1) {
auto &node = iter.get_internal(depth).node;
assert(node->is_valid());
- check_node<typename internal_node_t::base_t>(c, node);
+ if (depth > 2 ) {
+ check_node<internal_node_t>(c, node);
+ } else {
+ check_node<leaf_node_t>(c, node);
+ }
} else {
assert(depth == 1);
auto &node = iter.leaf.node;
assert(node->is_valid());
- check_node<LogicalCachedExtent>(c, node);
+ check_node<typename leaf_node_t::base_child_node_t>(c, node);
}
return seastar::now();
};
&checker);
});
}
+#endif
using iterate_repeat_ret_inner = base_iertr::future<
seastar::stop_iteration>;
iterator iter,
node_key_t laddr,
node_val_t val,
- LogicalCachedExtent* nextent
+ leaf_node_t::base_child_node_t* nextent
) {
LOG_PREFIX(FixedKVBtree::insert);
SUBTRACET(
op_context_t<node_key_t> c,
node_key_t laddr,
node_val_t val,
- LogicalCachedExtent* nextent) {
+ leaf_node_t::base_child_node_t* nextent) {
return lower_bound(
c, laddr
).si_then([this, c, laddr, val, nextent](auto iter) {
op_context_t<node_key_t> c,
iterator iter,
node_val_t val,
- LogicalCachedExtent* nextent)
+ leaf_node_t::base_child_node_t* nextent)
{
LOG_PREFIX(FixedKVBtree::update);
SUBTRACET(
using update_internal_mapping_iertr = base_iertr;
using update_internal_mapping_ret = update_internal_mapping_iertr::future<>;
+ template <typename T>
+ requires std::is_same_v<internal_node_t, T> || std::is_same_v<leaf_node_t, T>
update_internal_mapping_ret update_internal_mapping(
op_context_t<node_key_t> c,
depth_t depth,
node_key_t laddr,
paddr_t old_addr,
paddr_t new_addr,
- typename internal_node_t::base_ref nextent)
+ TCachedExtentRef<T> nextent)
{
LOG_PREFIX(FixedKVBtree::update_internal_mapping);
SUBTRACET(
auto init_internal = [c, depth, begin, end,
parent_pos=std::move(parent_pos)]
(internal_node_t &node) {
+ using tree_root_linker_t = TreeRootLinker<RootBlock, internal_node_t>;
assert(!node.is_pending());
assert(!node.is_linked());
node.range = fixed_kv_node_meta_t<node_key_t>{begin, end, depth};
auto root_block = c.cache.get_root_fast(c.trans);
if (root_block->is_mutation_pending()) {
auto &stable_root = (RootBlockRef&)*root_block->get_prior_instance();
- link_phy_tree_root_node(stable_root, &node);
+ tree_root_linker_t::link_root(stable_root, &node);
} else {
assert(!root_block->is_pending());
- link_phy_tree_root_node(root_block, &node);
+ tree_root_linker_t::link_root(root_block, &node);
}
}
};
auto init_leaf = [c, begin, end,
parent_pos=std::move(parent_pos)]
(leaf_node_t &node) {
+ using tree_root_linker_t = TreeRootLinker<RootBlock, leaf_node_t>;
assert(!node.is_pending());
assert(!node.is_linked());
node.range = fixed_kv_node_meta_t<node_key_t>{begin, end, 1};
auto root_block = c.cache.get_root_fast(c.trans);
if (root_block->is_mutation_pending()) {
auto &stable_root = (RootBlockRef&)*root_block->get_prior_instance();
- link_phy_tree_root_node(stable_root, &node);
+ tree_root_linker_t::link_root(stable_root, &node);
} else {
assert(!root_block->is_pending());
- link_phy_tree_root_node(root_block, &node);
+ tree_root_linker_t::link_root(root_block, &node);
}
}
};
return seastar::now();
};
- auto v = parent->template get_child<internal_node_t>(c, node_iter);
+ auto v = parent->template get_child<internal_node_t>(
+ c.trans, c.cache, node_iter.get_offset(), node_iter.get_key());
// checking the lba child must be atomic with creating
// and linking the absent child
if (v.has_child()) {
begin,
end,
std::make_optional<node_position_t<internal_node_t>>(
- child_pos.template get_parent<internal_node_t>(),
+ child_pos.get_parent(),
child_pos.get_pos())
).si_then([on_found=std::move(on_found)](InternalNodeRef node) {
return on_found(node);
return seastar::now();
};
- auto v = parent->template get_child<leaf_node_t>(c, node_iter);
+ auto v = parent->template get_child<leaf_node_t>(
+ c.trans, c.cache, node_iter.get_offset(), node_iter.get_key());
// checking the lba child must be atomic with creating
// and linking the absent child
if (v.has_child()) {
begin,
end,
std::make_optional<node_position_t<internal_node_t>>(
- child_pos.template get_parent<internal_node_t>(),
+ child_pos.get_parent(),
child_pos.get_pos())
).si_then([on_found=std::move(on_found)](LeafNodeRef node) {
return on_found(node);
return seastar::now();
};
- auto v = parent_pos.node->template get_child<NodeType>(c, donor_iter);
+ auto v = parent_pos.node->template get_child<NodeType>(
+ c.trans, c.cache, donor_iter.get_offset(), donor_iter.get_key());
// checking the lba child must be atomic with creating
// and linking the absent child
if (v.has_child()) {
begin,
end,
std::make_optional<node_position_t<internal_node_t>>(
- child_pos.template get_parent<internal_node_t>(),
+ child_pos.get_parent(),
child_pos.get_pos())
).si_then([do_merge=std::move(do_merge)](typename NodeType::Ref donor) {
return do_merge(donor);
+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "crimson/os/seastore/btree/fixed_kv_node.h"
-
-namespace crimson::os::seastore {
-
-bool is_valid_child_ptr(ChildableCachedExtent* child) {
- return child != nullptr && child != get_reserved_ptr();
-}
-
-bool is_reserved_ptr(ChildableCachedExtent* child) {
- return child == get_reserved_ptr();
-}
-
-} // namespace crimson::os::seastore
* Base class enabling recursive lookup between internal and leaf nodes.
*/
template <typename node_key_t>
-struct FixedKVNode : ChildableCachedExtent {
+struct FixedKVNode : CachedExtent {
using FixedKVNodeRef = TCachedExtentRef<FixedKVNode>;
fixed_kv_node_meta_t<node_key_t> range;
- struct fixedkv_node_cmp_t {
- using is_transparent = node_key_t;
- bool operator()(const FixedKVNodeRef &l, const FixedKVNodeRef &r) const {
- assert(l->range.end <= r->range.begin
- || r->range.end <= l->range.begin
- || (l->range.begin == r->range.begin
- && l->range.end == r->range.end));
- return l->range.begin < r->range.begin;
- }
- bool operator()(const node_key_t &l, const FixedKVNodeRef &r) const {
- return l < r->range.begin;
- }
- bool operator()(const FixedKVNodeRef &l, const node_key_t &r) const {
- return l->range.begin < r;
- }
- };
-
- /*
- *
- * Nodes of fixed-kv-btree connect to their child nodes by pointers following
- * invariants below:
- *
- * 1. if nodes are stable:
- * a. parent points at the node's stable parent
- * b. prior_instance is empty
- * c. child pointers point at stable children. Child resolution is done
- * directly via this array.
- * d. copy_sources is empty
- * 2. if nodes are mutation_pending:
- * a. parent is empty and needs to be fixed upon commit
- * b. prior_instance points to its stable version
- * c. child pointers are null except for initial_pending() children of
- * this transaction. Child resolution is done by first checking this
- * array, and then recursively resolving via the parent. We copy child
- * pointers from parent on commit.
- * d. copy_sources is empty
- * 3. if nodes are initial_pending
- * a. parent points at its pending parent on this transaction (must exist)
- * b. prior_instance is empty or, if it's the result of rewrite, points to
- * its stable predecessor
- * c. child pointers are null except for initial_pending() children of
- * this transaction (live due to 3a below). Child resolution is done
- * by first checking this array, and then recursively resolving via
- * the correct copy_sources entry. We copy child pointers from copy_sources
- * on commit.
- * d. copy_sources contains the set of stable nodes at the same tree-level(only
- * its "prior_instance" if the node is the result of a rewrite), with which
- * the lba range of this node overlaps.
- * 4. EXIST_CLEAN and EXIST_MUTATION_PENDING belong to 3 above (except that they
- * cannot be rewritten) because their parents must be mutated upon remapping.
- */
- std::vector<ChildableCachedExtent*> children;
- std::set<FixedKVNodeRef, fixedkv_node_cmp_t> copy_sources;
- uint16_t capacity = 0;
- parent_tracker_t* my_tracker = nullptr;
- RootBlockRef root_block;
-
- // copy dests points from a stable node back to its pending nodes
- // having copy sources at the same tree level, it serves as a two-level index:
- // transaction-id then node-key to the pending node.
- //
- // The copy dest pointers must be symmetric to the copy source pointers.
- //
- // copy_dests_t will be automatically unregisterred upon transaction destruction,
- // see Transaction::views
- struct copy_dests_t : trans_spec_view_t {
- std::set<FixedKVNodeRef, fixedkv_node_cmp_t> dests_by_key;
- copy_dests_t(Transaction &t) : trans_spec_view_t{t.get_trans_id()} {}
- ~copy_dests_t() {
- LOG_PREFIX(~copy_dests_t);
- SUBTRACE(seastore_fixedkv_tree, "copy_dests_t destroyed");
- }
- };
-
- trans_view_set_t copy_dests_by_trans;
-
- void add_copy_dest(Transaction &t, FixedKVNodeRef dest) {
- ceph_assert(is_stable());
- ceph_assert(dest->is_pending());
- auto tid = t.get_trans_id();
- auto iter = copy_dests_by_trans.lower_bound(
- tid, trans_spec_view_t::cmp_t());
- if (iter == copy_dests_by_trans.end() ||
- iter->pending_for_transaction != tid) {
- iter = copy_dests_by_trans.insert_before(
- iter, t.add_transactional_view<copy_dests_t>(t));
- }
- auto ©_dests = static_cast<copy_dests_t&>(*iter);
- auto [it, inserted] = copy_dests.dests_by_key.insert(dest);
- assert(inserted || it->get() == dest.get());
- }
-
- void del_copy_dest(Transaction &t, FixedKVNodeRef dest) {
- auto iter = copy_dests_by_trans.find(
- t.get_trans_id(), trans_spec_view_t::cmp_t());
- ceph_assert(iter != copy_dests_by_trans.end());
- auto ©_dests = static_cast<copy_dests_t&>(*iter);
- auto it = copy_dests.dests_by_key.find(dest);
- ceph_assert(it != copy_dests.dests_by_key.end());
- copy_dests.dests_by_key.erase(dest);
- }
-
- FixedKVNodeRef find_pending_version(Transaction &t, node_key_t key) {
- assert(is_stable());
- auto mut_iter = mutation_pendings.find(
- t.get_trans_id(), trans_spec_view_t::cmp_t());
- if (mut_iter != mutation_pendings.end()) {
- assert(copy_dests_by_trans.find(t.get_trans_id()) ==
- copy_dests_by_trans.end());
- return (FixedKVNode*)(&(*mut_iter));
- }
- auto iter = copy_dests_by_trans.find(
- t.get_trans_id(), trans_spec_view_t::cmp_t());
- ceph_assert(iter != copy_dests_by_trans.end());
- auto ©_dests = static_cast<copy_dests_t&>(*iter);
- auto it = copy_dests.dests_by_key.lower_bound(key);
- if (it == copy_dests.dests_by_key.end() || (*it)->range.begin > key) {
- ceph_assert(it != copy_dests.dests_by_key.begin());
- --it;
- }
- ceph_assert((*it)->range.begin <= key && key < (*it)->range.end);
- return *it;
- }
-
- bool is_linked() {
- assert(!has_parent_tracker() || !(bool)root_block);
- return (bool)has_parent_tracker() || (bool)root_block;
+ bool is_btree_root() const {
+ return range.is_root();
}
- FixedKVNode(uint16_t capacity, ceph::bufferptr &&ptr)
- : ChildableCachedExtent(std::move(ptr)),
- children(capacity, nullptr),
- capacity(capacity) {}
- // Must be identical with FixedKVNode(capacity, ptr) after on_fully_loaded()
- explicit FixedKVNode(uint16_t capacity, extent_len_t length)
- : ChildableCachedExtent(length),
- children(capacity, nullptr),
- capacity(capacity) {}
+ FixedKVNode(ceph::bufferptr &&ptr)
+ : CachedExtent(std::move(ptr)) {}
+ // Must be identical with FixedKVNode(ptr) after on_fully_loaded()
+ explicit FixedKVNode(extent_len_t length)
+ : CachedExtent(length) {}
FixedKVNode(const FixedKVNode &rhs)
- : ChildableCachedExtent(rhs),
- range(rhs.range),
- children(rhs.capacity, nullptr),
- capacity(rhs.capacity) {}
+ : CachedExtent(rhs),
+ range(rhs.range) {}
virtual fixed_kv_node_meta_t<node_key_t> get_node_meta() const = 0;
- virtual uint16_t get_node_size() const = 0;
-
virtual ~FixedKVNode() = default;
- virtual node_key_t get_key_from_idx(uint16_t idx) const = 0;
-
- template<typename iter_t>
- void update_child_ptr(iter_t iter, ChildableCachedExtent* child) {
- children[iter.get_offset()] = child;
- set_child_ptracker(child);
- }
-
- virtual bool is_leaf_and_has_children() const = 0;
-
- template<typename iter_t>
- void insert_child_ptr(iter_t iter, ChildableCachedExtent* child) {
- auto raw_children = children.data();
- auto offset = iter.get_offset();
- std::memmove(
- &raw_children[offset + 1],
- &raw_children[offset],
- (get_node_size() - offset) * sizeof(ChildableCachedExtent*));
- if (child) {
- children[offset] = child;
- set_child_ptracker(child);
- } else {
- // this can happen when reserving lba spaces and cloning mappings
- ceph_assert(is_leaf_and_has_children());
- // this is to avoid mistakenly copying pointers from
- // copy sources when committing this lba node, because
- // we rely on pointers' "nullness" to avoid copying
- // pointers for updated values
- children[offset] = get_reserved_ptr();
- }
- }
-
- template<typename iter_t>
- void remove_child_ptr(iter_t iter) {
- LOG_PREFIX(FixedKVNode::remove_child_ptr);
- auto raw_children = children.data();
- auto offset = iter.get_offset();
- SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, total size {}, extent {}",
- this->pending_for_transaction,
- offset,
- get_node_size(),
- (void*)raw_children[offset]);
- // parent tracker of the child being removed will be
- // reset when the child is invalidated, so no need to
- // reset it here
- std::memmove(
- &raw_children[offset],
- &raw_children[offset + 1],
- (get_node_size() - offset - 1) * sizeof(ChildableCachedExtent*));
- }
-
- virtual bool have_children() const = 0;
+ virtual void do_on_rewrite(Transaction &t, CachedExtent &extent) = 0;
void on_rewrite(Transaction &t, CachedExtent &extent, extent_len_t off) final {
assert(get_type() == extent.get_type());
assert(off == 0);
- auto &foreign_extent = (FixedKVNode&)extent;
range = get_node_meta();
-
- if (have_children()) {
- if (!foreign_extent.is_pending()) {
- foreign_extent.add_copy_dest(t, this);
- copy_sources.emplace(&foreign_extent);
- } else {
- ceph_assert(foreign_extent.is_mutation_pending());
- auto copy_source =
- foreign_extent.get_prior_instance()->template cast<FixedKVNode>();
- copy_source->add_copy_dest(t, this);
- copy_sources.emplace(copy_source);
- children = std::move(foreign_extent.children);
- adjust_ptracker_for_children();
- }
- }
+ do_on_rewrite(t, extent);
/* This is a bit underhanded. Any relative addrs here must necessarily
* be record relative as we are rewriting a dirty extent. Thus, we
} // else: backend_type_t::RANDOM_BLOCK
}
- FixedKVNode& get_stable_for_key(node_key_t key) const {
- ceph_assert(is_pending());
- if (is_mutation_pending()) {
- return (FixedKVNode&)*get_prior_instance();
- } else {
- ceph_assert(!copy_sources.empty());
- auto it = copy_sources.upper_bound(key);
- it--;
- auto ©_source = *it;
- ceph_assert(copy_source->get_node_meta().is_in_range(key));
- return *copy_source;
- }
- }
-
- static void push_copy_sources(
- Transaction &t,
- FixedKVNode &dest,
- FixedKVNode &src)
- {
- ceph_assert(dest.is_initial_pending());
- if (!src.is_pending()) {
- src.add_copy_dest(t, &dest);
- dest.copy_sources.emplace(&src);
- } else if (src.is_mutation_pending()) {
- auto copy_src =
- src.get_prior_instance()->template cast<FixedKVNode>();
- copy_src->add_copy_dest(t, &dest);
- dest.copy_sources.emplace(copy_src);
- } else {
- ceph_assert(src.is_initial_pending());
- for (auto &cs : src.copy_sources) {
- cs->add_copy_dest(t, &dest);
- }
- dest.copy_sources.insert(
- src.copy_sources.begin(),
- src.copy_sources.end());
- }
- }
-
- virtual uint16_t get_node_split_pivot() = 0;
-
- static void move_child_ptrs(
- FixedKVNode &dest,
- FixedKVNode &src,
- size_t dest_start,
- size_t src_start,
- size_t src_end)
- {
- std::memmove(
- dest.children.data() + dest_start,
- src.children.data() + src_start,
- (src_end - src_start) * sizeof(ChildableCachedExtent*));
-
- ceph_assert(src_start < src_end);
- ceph_assert(src.children.size() >= src_end);
- for (auto it = src.children.begin() + src_start;
- it != src.children.begin() + src_end;
- it++)
- {
- auto child = *it;
- if (is_valid_child_ptr(child)) {
- dest.set_child_ptracker(child);
- }
- }
- }
-
- void link_child(ChildableCachedExtent* child, uint16_t pos) {
- assert(pos < get_node_size());
- assert(child);
- ceph_assert(!is_pending());
- ceph_assert(child->is_valid() && !child->is_pending());
- assert(!children[pos]);
- children[pos] = child;
- set_child_ptracker(child);
- }
-
- virtual bool is_child_stable(
- op_context_t<node_key_t>,
- uint16_t pos,
- node_key_t key) const = 0;
- virtual bool is_child_data_stable(
- op_context_t<node_key_t>,
- uint16_t pos,
- node_key_t key) const = 0;
-
- template <typename T>
- get_child_ret_t<T> get_child(
- op_context_t<node_key_t> c,
- uint16_t pos,
- node_key_t key)
- {
- assert(children.capacity());
- assert(key == get_key_from_idx(pos));
- auto child = children[pos];
- ceph_assert(!is_reserved_ptr(child));
- if (is_valid_child_ptr(child)) {
- return c.cache.template get_extent_viewable_by_trans<T>(c.trans, (T*)child);
- } else if (is_pending()) {
- auto &sparent = get_stable_for_key(key);
- auto spos = sparent.lower_bound_offset(key);
- auto child = sparent.children[spos];
- if (is_valid_child_ptr(child)) {
- return c.cache.template get_extent_viewable_by_trans<T>(c.trans, (T*)child);
- } else {
- c.cache.account_absent_access(c.trans.get_src());
- return child_pos_t(&sparent, spos);
- }
- } else {
- c.cache.account_absent_access(c.trans.get_src());
- return child_pos_t(this, pos);
- }
- }
-
- template <typename T, typename iter_t>
- get_child_ret_t<T> get_child(op_context_t<node_key_t> c, iter_t iter) {
- return get_child<T>(c, iter.get_offset(), iter.get_key());
- }
-
- void split_child_ptrs(
- Transaction &t,
- FixedKVNode &left,
- FixedKVNode &right)
- {
- assert(!left.my_tracker);
- assert(!right.my_tracker);
- if (is_initial_pending()) {
- for (auto &cs : copy_sources) {
- cs->del_copy_dest(t, this);
- }
- }
-
- push_copy_sources(t, left, *this);
- push_copy_sources(t, right, *this);
- if (is_pending()) {
- uint16_t pivot = get_node_split_pivot();
- move_child_ptrs(left, *this, 0, 0, pivot);
- move_child_ptrs(right, *this, 0, pivot, get_node_size());
- my_tracker = nullptr;
- }
- }
-
- void merge_child_ptrs(
- Transaction &t,
- FixedKVNode &left,
- FixedKVNode &right)
- {
- ceph_assert(!my_tracker);
-
- if (left.is_initial_pending()) {
- for (auto &cs : left.copy_sources) {
- cs->del_copy_dest(t, &left);
- }
- }
- if (right.is_initial_pending()) {
- for (auto &cs : right.copy_sources) {
- cs->del_copy_dest(t, &right);
- }
- }
- push_copy_sources(t, *this, left);
- push_copy_sources(t, *this, right);
-
- if (left.is_pending()) {
- move_child_ptrs(*this, left, 0, 0, left.get_node_size());
- left.my_tracker = nullptr;
- }
-
- if (right.is_pending()) {
- move_child_ptrs(*this, right, left.get_node_size(), 0, right.get_node_size());
- right.my_tracker = nullptr;
- }
- }
-
- static void balance_child_ptrs(
- Transaction &t,
- FixedKVNode &left,
- FixedKVNode &right,
- bool prefer_left,
- FixedKVNode &replacement_left,
- FixedKVNode &replacement_right)
- {
- size_t l_size = left.get_node_size();
- size_t r_size = right.get_node_size();
- size_t total = l_size + r_size;
- size_t pivot_idx = (l_size + r_size) / 2;
- if (total % 2 && prefer_left) {
- pivot_idx++;
- }
-
- if (left.is_initial_pending()) {
- for (auto &cs : left.copy_sources) {
- cs->del_copy_dest(t, &left);
- }
- }
- if (right.is_initial_pending()) {
- for (auto &cs : right.copy_sources) {
- cs->del_copy_dest(t, &right);
- }
- }
-
- assert(!replacement_left.my_tracker);
- assert(!replacement_right.my_tracker);
- if (pivot_idx < l_size) {
- // deal with left
- push_copy_sources(t, replacement_left, left);
- push_copy_sources(t, replacement_right, left);
- if (left.is_pending()) {
- move_child_ptrs(replacement_left, left, 0, 0, pivot_idx);
- move_child_ptrs(replacement_right, left, 0, pivot_idx, l_size);
- left.my_tracker = nullptr;
- }
-
- // deal with right
- push_copy_sources(t, replacement_right, right);
- if (right.is_pending()) {
- move_child_ptrs(replacement_right, right, l_size - pivot_idx, 0, r_size);
- right.my_tracker= nullptr;
- }
- } else {
- // deal with left
- push_copy_sources(t, replacement_left, left);
- if (left.is_pending()) {
- move_child_ptrs(replacement_left, left, 0, 0, l_size);
- left.my_tracker = nullptr;
- }
-
- // deal with right
- push_copy_sources(t, replacement_left, right);
- push_copy_sources(t, replacement_right, right);
- if (right.is_pending()) {
- move_child_ptrs(replacement_left, right, l_size, 0, pivot_idx - l_size);
- move_child_ptrs(replacement_right, right, 0, pivot_idx - l_size, r_size);
- right.my_tracker= nullptr;
- }
- }
- }
-
- void set_parent_tracker_from_prior_instance() {
- assert(is_mutation_pending());
- auto &prior = (FixedKVNode&)(*get_prior_instance());
- if (range.is_root()) {
- ceph_assert(prior.root_block);
- ceph_assert(pending_for_transaction);
- root_block = prior.root_block;
- link_phy_tree_root_node(root_block, this);
- return;
- }
- ceph_assert(!root_block);
- take_prior_parent_tracker();
- assert(is_parent_valid());
- auto parent = get_parent_node<FixedKVNode>();
- //TODO: can this search be avoided?
- auto off = parent->lower_bound_offset(get_node_meta().begin);
- assert(parent->get_key_from_idx(off) == get_node_meta().begin);
- parent->children[off] = this;
- }
-
- bool is_children_empty() const {
- for (auto it = children.begin();
- it != children.begin() + get_node_size();
- it++) {
- if (is_valid_child_ptr(*it)
- && (*it)->is_valid()) {
- return false;
- }
- }
- return true;
- }
-
- void set_children_from_prior_instance() {
- assert(get_prior_instance());
- auto &prior = (FixedKVNode&)(*get_prior_instance());
- assert(prior.my_tracker || prior.is_children_empty());
-
- if (prior.my_tracker) {
- prior.my_tracker->reset_parent(this);
- my_tracker = prior.my_tracker;
- // All my initial pending children is pointing to the original
- // tracker which has been dropped by the above line, so need
- // to adjust them to point to the new tracker
- adjust_ptracker_for_children();
- }
- assert(my_tracker || is_children_empty());
- }
-
- void adjust_ptracker_for_children() {
- auto begin = children.begin();
- auto end = begin + get_node_size();
- ceph_assert(end <= children.end());
- for (auto it = begin; it != end; it++) {
- auto child = *it;
- if (is_valid_child_ptr(child)) {
- set_child_ptracker(child);
- }
- }
- }
-
void on_delta_write(paddr_t record_block_offset) final {
// All in-memory relative addrs are necessarily record-relative
assert(get_prior_instance());
resolve_relative_addrs(record_block_offset);
}
- virtual uint16_t lower_bound_offset(node_key_t) const = 0;
- virtual uint16_t upper_bound_offset(node_key_t) const = 0;
-
- virtual bool validate_stable_children() = 0;
-
- template<typename iter_t>
- uint16_t copy_children_from_stable_source(
- FixedKVNode &source,
- iter_t foreign_start_it,
- iter_t foreign_end_it,
- iter_t local_start_it) {
- auto foreign_it = foreign_start_it, local_it = local_start_it;
- while (foreign_it != foreign_end_it
- && local_it.get_offset() < get_node_size())
- {
- auto &child = children[local_it.get_offset()];
- if (foreign_it.get_key() == local_it.get_key()) {
- // the foreign key is preserved
- if (!child) {
- child = source.children[foreign_it.get_offset()];
- // child can be either valid if present, nullptr if absent,
- // or reserved ptr.
- }
- foreign_it++;
- local_it++;
- } else if (foreign_it.get_key() < local_it.get_key()) {
- // the foreign key has been removed, because, if it hasn't,
- // there must have been a local key before the one pointed
- // by the current "local_it" that's equal to this foreign key
- // and has pushed the foreign_it forward.
- foreign_it++;
- } else {
- // the local key must be a newly inserted one.
- local_it++;
- }
- }
- return local_it.get_offset();
- }
-
- template<typename Func>
- void copy_children_from_stable_sources(Func &&get_iter) {
- if (!copy_sources.empty()) {
- auto it = --copy_sources.upper_bound(get_node_meta().begin);
- auto &cs = *it;
- uint16_t start_pos = cs->lower_bound_offset(
- get_node_meta().begin);
- if (start_pos == cs->get_node_size()) {
- it++;
- start_pos = 0;
- }
- uint16_t local_next_pos = 0;
- for (; it != copy_sources.end(); it++) {
- auto& copy_source = *it;
- auto end_pos = copy_source->get_node_size();
- if (copy_source->get_node_meta().is_in_range(get_node_meta().end)) {
- end_pos = copy_source->upper_bound_offset(get_node_meta().end);
- }
- auto local_start_iter = get_iter(*this, local_next_pos);
- auto foreign_start_iter = get_iter(*copy_source, start_pos);
- auto foreign_end_iter = get_iter(*copy_source, end_pos);
- local_next_pos = copy_children_from_stable_source(
- *copy_source, foreign_start_iter, foreign_end_iter, local_start_iter);
- if (end_pos != copy_source->get_node_size()) {
- break;
- }
- start_pos = 0;
- }
- }
- }
-
- void on_invalidated(Transaction &t) final {
- reset_parent_tracker();
- }
-
- void on_initial_write() final {
- // All in-memory relative addrs are necessarily block-relative
- resolve_relative_addrs(get_paddr());
- if (range.is_root()) {
- reset_parent_tracker();
- }
- assert(has_parent_tracker() ? (is_parent_valid()) : true);
- }
-
- void set_child_ptracker(ChildableCachedExtent *child) {
- if (!this->my_tracker) {
- this->my_tracker = new parent_tracker_t(this);
- }
- child->reset_parent_tracker(this->my_tracker);
- }
-
void on_clean_read() final {
// From initial write of block, relative addrs are necessarily block-relative
resolve_relative_addrs(get_paddr());
}
+ node_key_t get_begin() const {
+ return this->range.begin;
+ }
+ node_key_t get_end() const {
+ return this->range.end;
+ }
virtual void resolve_relative_addrs(paddr_t base) = 0;
+ virtual bool is_linked() const = 0;
+ virtual uint16_t get_node_split_pivot() const = 0;
};
/**
fixed_kv_node_meta_t<NODE_KEY>,
fixed_kv_node_meta_le_t<NODE_KEY_LE>,
NODE_KEY, NODE_KEY_LE,
- paddr_t, paddr_le_t> {
+ paddr_t, paddr_le_t>,
+ RootChildNode<RootBlock, node_type_t>,
+ ParentNode<node_type_t, NODE_KEY>,
+ ChildNode<node_type_t, node_type_t, NODE_KEY> {
using Ref = TCachedExtentRef<node_type_t>;
using base_t = FixedKVNode<NODE_KEY>;
using base_ref = typename FixedKVNode<NODE_KEY>::FixedKVNodeRef;
NODE_KEY_LE,
node_size,
node_type_t>;
+ using parent_node_t = ParentNode<node_type_t, NODE_KEY>;
+ using base_child_node_t = BaseChildNode<node_type_t, NODE_KEY>;
+ using child_node_t = ChildNode<node_type_t, node_type_t, NODE_KEY>;
+ using root_node_t = RootChildNode<RootBlock, node_type_t>;
+
+ bool is_linked() const final {
+ return this->has_parent_tracker() ||
+ (this->is_btree_root() && this->has_root_parent());
+ }
+
+ void do_on_rewrite(Transaction &t, CachedExtent &extent) final {
+ this->parent_node_t::on_rewrite(t, static_cast<node_type_t&>(extent));
+ }
explicit FixedKVInternalNode(ceph::bufferptr &&ptr)
- : FixedKVNode<NODE_KEY>(CAPACITY, std::move(ptr)) {
+ : FixedKVNode<NODE_KEY>(std::move(ptr)),
+ ParentNode<node_type_t, NODE_KEY>(CAPACITY) {
this->set_layout_buf(this->get_bptr().c_str());
}
// Must be identical with FixedKVInternalNode(ptr) after on_fully_loaded()
explicit FixedKVInternalNode(extent_len_t length)
- : FixedKVNode<NODE_KEY>(CAPACITY, length) {}
+ : FixedKVNode<NODE_KEY>(length),
+ ParentNode<node_type_t, NODE_KEY>(CAPACITY) {}
FixedKVInternalNode(const FixedKVInternalNode &rhs)
- : FixedKVNode<NODE_KEY>(rhs) {
+ : FixedKVNode<NODE_KEY>(rhs),
+ ParentNode<node_type_t, NODE_KEY>(rhs) {
this->set_layout_buf(this->get_bptr().c_str());
}
- bool have_children() const final {
- return true;
- }
-
- bool is_leaf_and_has_children() const final {
+ bool is_leaf_and_has_children() const {
return false;
}
- uint16_t get_node_split_pivot() final {
+ uint16_t get_node_split_pivot() const final{
return this->get_split_pivot().get_offset();
}
void prepare_commit() final {
- if (this->is_initial_pending()) {
- if (this->is_rewrite()) {
- this->set_children_from_prior_instance();
- }
- this->copy_children_from_stable_sources(
- [this](base_t &node, uint16_t pos) {
- ceph_assert(node.get_type() == this->get_type());
- auto &n = static_cast<this_type_t&>(node);
- return n.iter_idx(pos);
- }
- );
- if (this->is_rewrite()) {
- this->reset_prior_instance();
- } else {
- this->adjust_ptracker_for_children();
- }
- assert(this->validate_stable_children());
- this->copy_sources.clear();
- }
- }
-
- bool is_child_stable(
- op_context_t<NODE_KEY>,
- uint16_t pos,
- NODE_KEY key) const final {
- ceph_abort("impossible");
- return false;
- }
- bool is_child_data_stable(
- op_context_t<NODE_KEY>,
- uint16_t pos,
- NODE_KEY key) const final {
- ceph_abort("impossible");
- return false;
- }
-
- bool validate_stable_children() final {
- LOG_PREFIX(FixedKVInternalNode::validate_stable_children);
- if (this->children.empty()) {
- return false;
- }
-
- for (auto i : *this) {
- auto child = (FixedKVNode<NODE_KEY>*)this->children[i.get_offset()];
- if (child && child->range.begin != i.get_key()) {
- SUBERROR(seastore_fixedkv_tree,
- "stable child not valid: child {}, child meta{}, key {}",
- *child,
- child->get_node_meta(),
- i.get_key());
- ceph_abort();
- return false;
- }
- }
- return true;
+ parent_node_t::prepare_commit();
}
virtual ~FixedKVInternalNode() {
if (this->is_valid() && !this->is_pending()) {
- if (this->range.is_root()) {
- ceph_assert(this->root_block);
- unlink_phy_tree_root_node<NODE_KEY>(this->root_block);
+ if (this->is_btree_root()) {
+ this->root_node_t::destroy();
} else {
- ceph_assert(this->is_parent_valid());
- auto parent = this->template get_parent_node<FixedKVNode<NODE_KEY>>();
- auto off = parent->lower_bound_offset(this->get_meta().begin);
- assert(parent->get_key_from_idx(off) == this->get_meta().begin);
- assert(parent->children[off] == this);
- parent->children[off] = nullptr;
+ this->child_node_t::destroy();
}
}
}
- uint16_t lower_bound_offset(NODE_KEY key) const final {
- return this->lower_bound(key).get_offset();
- }
-
- uint16_t upper_bound_offset(NODE_KEY key) const final {
- return this->upper_bound(key).get_offset();
+ void on_initial_write() final {
+ // All in-memory relative addrs are necessarily block-relative
+ resolve_relative_addrs(this->get_paddr());
+ if (this->is_btree_root()) {
+ this->root_node_t::on_initial_write();
+ }
}
- NODE_KEY get_key_from_idx(uint16_t idx) const final {
- return this->iter_idx(idx).get_key();
+ void on_invalidated(Transaction &t) final {
+ this->child_node_t::on_invalidated();
}
fixed_kv_node_meta_t<NODE_KEY> get_node_meta() const {
return this->get_meta();
}
- uint16_t get_node_size() const final {
- return this->get_size();
- }
-
uint32_t calc_crc32c() const final {
return this->calc_phy_checksum();
}
};
void on_replace_prior() final {
- ceph_assert(!this->is_rewrite());
- this->set_children_from_prior_instance();
- auto &prior = (this_type_t&)(*this->get_prior_instance());
- auto copied = this->copy_children_from_stable_source(
- prior,
- prior.begin(),
- prior.end(),
- this->begin());
- ceph_assert(copied <= get_node_size());
- assert(this->validate_stable_children());
- this->set_parent_tracker_from_prior_instance();
+ this->parent_node_t::on_replace_prior();
+ if (this->is_btree_root()) {
+ this->root_node_t::on_replace_prior();
+ } else {
+ this->child_node_t::on_replace_prior();
+ }
}
void update(
internal_const_iterator_t iter,
paddr_t addr,
- FixedKVNode<NODE_KEY>* nextent) {
+ base_child_node_t* nextent) {
LOG_PREFIX(FixedKVInternalNode::update);
SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, {}",
this->pending_for_transaction,
iter.get_offset(),
- *nextent);
- this->update_child_ptr(iter, nextent);
+ (void*)nextent);
+ this->update_child_ptr(iter.get_offset(), nextent);
return this->journal_update(
iter,
this->maybe_generate_relative(addr),
internal_const_iterator_t iter,
NODE_KEY pivot,
paddr_t addr,
- FixedKVNode<NODE_KEY>* nextent) {
+ base_child_node_t* nextent) {
LOG_PREFIX(FixedKVInternalNode::insert);
SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, key {}, {}",
this->pending_for_transaction,
iter.get_offset(),
pivot,
- *nextent);
- this->insert_child_ptr(iter, nextent);
+ (void*)nextent);
+ this->insert_child_ptr(iter.get_offset(), nextent);
return this->journal_insert(
iter,
pivot,
this->pending_for_transaction,
iter.get_offset(),
iter.get_key());
- this->remove_child_ptr(iter);
+ this->remove_child_ptr(iter.get_offset());
return this->journal_remove(
iter,
maybe_get_delta_buffer());
internal_const_iterator_t iter,
NODE_KEY pivot,
paddr_t addr,
- FixedKVNode<NODE_KEY>* nextent) {
+ base_child_node_t* nextent) {
LOG_PREFIX(FixedKVInternalNode::replace);
SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, old key {}, key {}, {}",
this->pending_for_transaction,
iter.get_offset(),
iter.get_key(),
pivot,
- *nextent);
- this->update_child_ptr(iter, nextent);
+ (void*)nextent);
+ this->update_child_ptr(iter.get_offset(), nextent);
return this->journal_replace(
iter,
pivot,
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
auto right = c.cache.template alloc_new_non_data_extent<node_type_t>(
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
+ this->split_child_ptrs(c.trans, *left, *right);
auto pivot = this->split_into(*left, *right);
left->range = left->get_meta();
right->range = right->get_meta();
- this->split_child_ptrs(c.trans, *left, *right);
+ this->adjust_copy_src_dest_on_split(c.trans, *left, *right);
return std::make_tuple(
left,
right,
Ref &right) {
auto replacement = c.cache.template alloc_new_non_data_extent<node_type_t>(
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
+ replacement->merge_child_ptrs(
+ c.trans, static_cast<node_type_t&>(*this), *right);
replacement->merge_from(*this, *right->template cast<node_type_t>());
replacement->range = replacement->get_meta();
- replacement->merge_child_ptrs(c.trans, *this, *right);
+ replacement->adjust_copy_src_dest_on_merge(
+ c.trans, static_cast<node_type_t&>(*this), *right);
return replacement;
}
auto replacement_right = c.cache.template alloc_new_non_data_extent<node_type_t>(
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
+ this->balance_child_ptrs(
+ c.trans,
+ static_cast<node_type_t&>(*this),
+ right,
+ prefer_left,
+ *replacement_left,
+ *replacement_right);
auto pivot = this->balance_into_new_nodes(
*this,
right,
*replacement_right);
replacement_left->range = replacement_left->get_meta();
replacement_right->range = replacement_right->get_meta();
- this->balance_child_ptrs(
+ this->adjust_copy_src_dest_on_balance(
c.trans,
- *this,
+ static_cast<node_type_t&>(*this),
right,
prefer_left,
*replacement_left,
}
}
- std::ostream &_print_detail(std::ostream &out) const
+ std::ostream &print_detail(std::ostream &out) const
{
out << ", size=" << this->get_size()
<< ", meta=" << this->get_meta()
if (this->my_tracker) {
out << ", my_tracker->parent=" << (void*)this->my_tracker->get_parent().get();
}
- return out << ", root_block=" << (void*)this->root_block.get();
+ return out << ", root_block=" << (void*)this->parent_of_root.get();
}
ceph::bufferlist get_delta() {
typename VAL,
typename VAL_LE,
size_t node_size,
+ typename internal_node_type_t,
typename node_type_t,
+ typename child_t,
bool has_children>
struct FixedKVLeafNode
: FixedKVNode<NODE_KEY>,
fixed_kv_node_meta_t<NODE_KEY>,
fixed_kv_node_meta_le_t<NODE_KEY_LE>,
NODE_KEY, NODE_KEY_LE,
- VAL, VAL_LE> {
+ VAL, VAL_LE>,
+ RootChildNode<RootBlock, node_type_t>,
+ ParentNode<node_type_t, NODE_KEY>,
+ ChildNode<internal_node_type_t, node_type_t, NODE_KEY> {
using Ref = TCachedExtentRef<node_type_t>;
using node_layout_t =
common::FixedKVNodeLayout<
VAL,
VAL_LE,
node_size,
+ internal_node_type_t,
node_type_t,
+ child_t,
has_children>;
using base_t = FixedKVNode<NODE_KEY>;
+ using parent_node_t = ParentNode<node_type_t, NODE_KEY>;
+ using base_child_node_t = child_t;
+ using child_node_t = ChildNode<internal_node_type_t, node_type_t, NODE_KEY>;
+ using root_node_t = RootChildNode<RootBlock, node_type_t>;
explicit FixedKVLeafNode(ceph::bufferptr &&ptr)
- : FixedKVNode<NODE_KEY>(has_children ? CAPACITY : 0, std::move(ptr)) {
+ : FixedKVNode<NODE_KEY>(std::move(ptr)),
+ ParentNode<node_type_t, NODE_KEY>(has_children ? CAPACITY : 0){
this->set_layout_buf(this->get_bptr().c_str());
}
// Must be identical with FixedKVLeafNode(ptr) after on_fully_loaded()
explicit FixedKVLeafNode(extent_len_t length)
- : FixedKVNode<NODE_KEY>(has_children ? CAPACITY : 0, length) {}
+ : FixedKVNode<NODE_KEY>(length),
+ ParentNode<node_type_t, NODE_KEY>(has_children ? CAPACITY : 0) {}
FixedKVLeafNode(const FixedKVLeafNode &rhs)
: FixedKVNode<NODE_KEY>(rhs),
+ ParentNode<node_type_t, NODE_KEY>(rhs),
modifications(rhs.modifications) {
this->set_layout_buf(this->get_bptr().c_str());
}
+ bool is_linked() const final {
+ return this->has_parent_tracker() ||
+ (this->is_btree_root() && this->has_root_parent());
+ }
+
static constexpr bool do_has_children = has_children;
// for the stable extent, modifications is always 0;
// it will increase for each transaction-local change, so that
// modifications can be detected (see BtreeLBAMapping.parent_modifications)
uint64_t modifications = 0;
+ void on_invalidated(Transaction &t) final {
+ this->child_node_t::on_invalidated();
+ }
- bool have_children() const final {
- return do_has_children;
+ void on_initial_write() final {
+ // All in-memory relative addrs are necessarily block-relative
+ this->resolve_relative_addrs(this->get_paddr());
+ if (this->is_btree_root()) {
+ this->root_node_t::on_initial_write();
+ }
+ }
+
+ void _on_rewrite(Transaction &t, CachedExtent &extent) final {
+ if (do_has_children) {
+ this->parent_node_t::on_rewrite(t, static_cast<node_type_t&>(extent));
+ }
}
void on_modify() {
return v != modifications;
}
- bool is_leaf_and_has_children() const final {
+ bool is_leaf_and_has_children() const {
return has_children;
}
- uint16_t get_node_split_pivot() final {
+ uint16_t get_node_split_pivot() const final{
return this->get_split_pivot().get_offset();
}
- // children are considered stable if any of the following case is true:
- // 1. The child extent is absent in cache
- // 2. The child extent is stable
- //
- // For reserved mappings, the return values are undefined.
bool is_child_stable(
op_context_t<NODE_KEY> c,
uint16_t pos,
- NODE_KEY key) const final {
- return _is_child_stable(c, pos, key);
+ NODE_KEY key) const {
+ return parent_node_t::_is_child_stable(c.trans, pos, key);
}
bool is_child_data_stable(
op_context_t<NODE_KEY> c,
uint16_t pos,
- NODE_KEY key) const final {
- return _is_child_stable(c, pos, key, true);
- }
-
- bool _is_child_stable(
- op_context_t<NODE_KEY> c,
- uint16_t pos,
- NODE_KEY key,
- bool data_only = false) const {
- assert(key == get_key_from_idx(pos));
- auto child = this->children[pos];
- if (is_reserved_ptr(child)) {
- return true;
- } else if (is_valid_child_ptr(child)) {
- ceph_assert(child->is_logical());
- ceph_assert(
- child->is_pending_in_trans(c.trans.get_trans_id())
- || this->is_stable_written());
- if (data_only) {
- return c.cache.is_viewable_extent_data_stable(c.trans, child);
- } else {
- return c.cache.is_viewable_extent_stable(c.trans, child);
- }
- } else if (this->is_pending()) {
- auto key = this->iter_idx(pos).get_key();
- auto &sparent = this->get_stable_for_key(key);
- auto spos = sparent.lower_bound_offset(key);
- auto child = sparent.children[spos];
- if (is_valid_child_ptr(child)) {
- ceph_assert(child->is_logical());
- if (data_only) {
- return c.cache.is_viewable_extent_data_stable(c.trans, child);
- } else {
- return c.cache.is_viewable_extent_stable(c.trans, child);
- }
- } else {
- return true;
- }
- } else {
- return true;
- }
- }
-
- bool validate_stable_children() override {
- return true;
+ NODE_KEY key) const {
+ return parent_node_t::_is_child_stable(c.trans, pos, key, true);
}
virtual ~FixedKVLeafNode() {
if (this->is_valid() && !this->is_pending()) {
- if (this->range.is_root()) {
- ceph_assert(this->root_block);
- unlink_phy_tree_root_node<NODE_KEY>(this->root_block);
+ if (this->is_btree_root()) {
+ this->root_node_t::destroy();
} else {
- ceph_assert(this->is_parent_valid());
- auto parent = this->template get_parent_node<FixedKVNode<NODE_KEY>>();
- auto off = parent->lower_bound_offset(this->get_meta().begin);
- assert(parent->get_key_from_idx(off) == this->get_meta().begin);
- assert(parent->children[off] == this);
- parent->children[off] = nullptr;
+ this->child_node_t::destroy();
}
}
}
void prepare_commit() final {
if constexpr (has_children) {
- if (this->is_initial_pending()) {
- if (this->is_rewrite()) {
- this->set_children_from_prior_instance();
- }
- this->copy_children_from_stable_sources(
- [this](base_t &node, uint16_t pos) {
- ceph_assert(node.get_type() == this->get_type());
- auto &n = static_cast<this_type_t&>(node);
- return n.iter_idx(pos);
- }
- );
- if (this->is_rewrite()) {
- this->reset_prior_instance();
- } else {
- this->adjust_ptracker_for_children();
- }
- assert(this->validate_stable_children());
- this->copy_sources.clear();
- }
+ parent_node_t::prepare_commit();
}
modifications = 0;
- assert(this->is_initial_pending()
- ? this->copy_sources.empty():
- true);
}
void on_replace_prior() final {
ceph_assert(!this->is_rewrite());
if constexpr (has_children) {
- this->set_children_from_prior_instance();
- auto &prior = (this_type_t&)(*this->get_prior_instance());
- auto copied = this->copy_children_from_stable_source(
- prior,
- prior.begin(),
- prior.end(),
- this->begin());
- ceph_assert(copied <= get_node_size());
- assert(this->validate_stable_children());
- this->set_parent_tracker_from_prior_instance();
+ this->parent_node_t::on_replace_prior();
+ }
+ if (this->is_btree_root()) {
+ this->root_node_t::on_replace_prior();
} else {
- this->set_parent_tracker_from_prior_instance();
+ this->child_node_t::on_replace_prior();
}
modifications = 0;
}
- uint16_t lower_bound_offset(NODE_KEY key) const final {
- return this->lower_bound(key).get_offset();
- }
-
- uint16_t upper_bound_offset(NODE_KEY key) const final {
- return this->upper_bound(key).get_offset();
- }
-
- NODE_KEY get_key_from_idx(uint16_t idx) const final {
- return this->iter_idx(idx).get_key();
- }
-
fixed_kv_node_meta_t<NODE_KEY> get_node_meta() const {
return this->get_meta();
}
- uint16_t get_node_size() const final {
- return this->get_size();
- }
-
uint32_t calc_crc32c() const final {
return this->calc_phy_checksum();
}
CachedExtentRef duplicate_for_write(Transaction&) override {
assert(delta_buffer.empty());
- return CachedExtentRef(new node_type_t(*this));
+ auto extent = new node_type_t(*this);
+ extent->set_cache_proxy(this->get_cache_proxy());
+ return CachedExtentRef(extent);
};
virtual void update(
internal_const_iterator_t iter,
VAL val,
- LogicalCachedExtent* nextent) = 0;
+ base_child_node_t* nextent) = 0;
virtual internal_const_iterator_t insert(
internal_const_iterator_t iter,
NODE_KEY addr,
VAL val,
- LogicalCachedExtent* nextent) = 0;
+ base_child_node_t* nextent) = 0;
virtual void remove(internal_const_iterator_t iter) = 0;
std::tuple<Ref, Ref, NODE_KEY>
make_split_children(op_context_t<NODE_KEY> c) {
auto left = c.cache.template alloc_new_non_data_extent<node_type_t>(
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
+ left->set_cache_proxy(this->get_cache_proxy());
auto right = c.cache.template alloc_new_non_data_extent<node_type_t>(
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
+ if constexpr (has_children) {
+ this->split_child_ptrs(c.trans, *left, *right);
+ }
+ right->set_cache_proxy(this->get_cache_proxy());
auto pivot = this->split_into(*left, *right);
left->range = left->get_meta();
right->range = right->get_meta();
if constexpr (has_children) {
- this->split_child_ptrs(c.trans, *left, *right);
+ this->adjust_copy_src_dest_on_split(c.trans, *left, *right);
}
return std::make_tuple(
left,
Ref &right) {
auto replacement = c.cache.template alloc_new_non_data_extent<node_type_t>(
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
+ if constexpr (has_children) {
+ replacement->merge_child_ptrs(
+ c.trans, static_cast<node_type_t&>(*this), *right);
+ }
+ replacement->set_cache_proxy(this->get_cache_proxy());
replacement->merge_from(*this, *right->template cast<node_type_t>());
replacement->range = replacement->get_meta();
if constexpr (has_children) {
- replacement->merge_child_ptrs(c.trans, *this, *right);
+ replacement->adjust_copy_src_dest_on_merge(
+ c.trans, static_cast<node_type_t&>(*this), *right);
}
return replacement;
}
auto &right = *_right->template cast<node_type_t>();
auto replacement_left = c.cache.template alloc_new_non_data_extent<node_type_t>(
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
+ replacement_left->set_cache_proxy(this->get_cache_proxy());
auto replacement_right = c.cache.template alloc_new_non_data_extent<node_type_t>(
c.trans, node_size, placement_hint_t::HOT, INIT_GENERATION);
+ replacement_right->set_cache_proxy(this->get_cache_proxy());
+ if constexpr (has_children) {
+ this->balance_child_ptrs(
+ c.trans,
+ static_cast<node_type_t&>(*this),
+ right,
+ prefer_left,
+ *replacement_left,
+ *replacement_right);
+ }
auto pivot = this->balance_into_new_nodes(
*this,
right,
replacement_left->range = replacement_left->get_meta();
replacement_right->range = replacement_right->get_meta();
if constexpr (has_children) {
- this->balance_child_ptrs(
+ this->adjust_copy_src_dest_on_balance(
c.trans,
- *this,
+ static_cast<node_type_t&>(*this),
right,
prefer_left,
*replacement_left,
this->resolve_relative_addrs(base);
}
- std::ostream &_print_detail(std::ostream &out) const
+ std::ostream &print_detail(std::ostream &out) const
{
return out << ", size=" << this->get_size()
<< ", meta=" << this->get_meta();
#include "crimson/os/seastore/seastore_types.h"
#include "crimson/os/seastore/segment_manager.h"
#include "crimson/os/seastore/transaction.h"
+#include "crimson/os/seastore/linked_tree_node.h"
namespace crimson::os::seastore::backref {
class BtreeBackrefManager;
* - TRACE: DEBUG details
* - seastore_t logs
*/
-class Cache {
+class Cache : public ExtentTransViewRetriever {
public:
using base_ertr = crimson::errorator<
crimson::ct_error::input_output_error>;
return t.root;
}
- void account_absent_access(Transaction::src_t src) {
+ void account_absent_access(Transaction::src_t src) final {
++(get_by_src(stats.cache_absent_by_src, src));
++stats.access.cache_absent;
}
bool is_viewable_extent_stable(
Transaction &t,
- CachedExtentRef extent)
+ CachedExtentRef extent) final
{
assert(extent);
auto view = extent->get_transactional_view(t);
bool is_viewable_extent_data_stable(
Transaction &t,
- CachedExtentRef extent)
+ CachedExtentRef extent) final
{
assert(extent);
auto view = extent->get_transactional_view(t);
get_extent_iertr::future<CachedExtentRef>
get_extent_viewable_by_trans(
Transaction &t,
- CachedExtentRef extent)
+ CachedExtentRef extent) final
{
assert(extent->is_valid());
});
}
- template <typename T>
- get_extent_iertr::future<TCachedExtentRef<T>>
- get_extent_viewable_by_trans(
- Transaction &t,
- TCachedExtentRef<T> extent)
- {
- return get_extent_viewable_by_trans(t, CachedExtentRef(extent.get())
- ).si_then([](auto p_extent) {
- return p_extent->template cast<T>();
- });
- }
-
// wait extent io or do partial reads
template <typename T>
get_extent_iertr::future<TCachedExtentRef<T>>
#include "crimson/os/seastore/btree/fixed_kv_node.h"
#include "crimson/os/seastore/lba_mapping.h"
+#include "crimson/os/seastore/logical_child_node.h"
namespace {
[[maybe_unused]] seastar::logger& logger() {
}
}
-std::ostream &operator<<(std::ostream &out, const parent_tracker_t &tracker) {
- return out << "tracker_ptr=" << (void*)&tracker
- << ", parent_ptr=" << (void*)tracker.get_parent().get();
-}
-
-std::ostream &ChildableCachedExtent::print_detail(std::ostream &out) const {
- if (parent_tracker) {
- out << ", parent_tracker(" << *parent_tracker << ")";
- } else {
- out << ", parent_tracker(nullptr)";
- }
- _print_detail(out);
- return out;
-}
-
-std::ostream &LogicalCachedExtent::_print_detail(std::ostream &out) const
+std::ostream &LogicalCachedExtent::print_detail(std::ostream &out) const
{
out << ", laddr=" << laddr;
return print_detail_l(out);
}
-void child_pos_t::link_child(ChildableCachedExtent *c) {
- get_parent<FixedKVNode<laddr_t>>()->link_child(c, pos);
-}
-
void CachedExtent::set_invalid(Transaction &t) {
state = extent_state_t::INVALID;
if (trans_view_hook.is_linked()) {
on_invalidated(t);
}
-LogicalCachedExtent::~LogicalCachedExtent() {
- if (has_parent_tracker() && is_valid() && !is_pending()) {
- assert(get_parent_node());
- auto parent = get_parent_node<FixedKVNode<laddr_t>>();
- auto off = parent->lower_bound_offset(laddr);
- assert(parent->get_key_from_idx(off) == laddr);
- assert(parent->children[off] == this);
- parent->children[off] = nullptr;
- }
-}
-
-void LogicalCachedExtent::on_replace_prior() {
- assert(is_mutation_pending());
- take_prior_parent_tracker();
- assert(get_parent_node());
- auto parent = get_parent_node<FixedKVNode<laddr_t>>();
- //TODO: can this search be avoided?
- auto off = parent->lower_bound_offset(laddr);
- assert(parent->get_key_from_idx(off) == laddr);
- 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;
- if (p.my_tracker == this) {
- p.my_tracker = nullptr;
- }
-}
-
bool BufferSpace::is_range_loaded(extent_len_t offset, extent_len_t length) const
{
assert(length > 0);
class TransactionManager;
class ExtentPlacementManager;
-template <typename, typename>
-class BtreeNodeMapping;
-
// #define DEBUG_CACHED_EXTENT_REF
#ifdef DEBUG_CACHED_EXTENT_REF
friend class ::lba_btree_test;
friend class ::btree_test_base;
friend class ::cache_test_t;
+ template <typename, typename, typename>
+ friend class ParentNode;
};
std::ostream &operator<<(std::ostream &, CachedExtent::extent_state_t);
uint64_t bytes = 0;
};
-class ChildableCachedExtent;
-
-class child_pos_t {
-public:
- child_pos_t(CachedExtentRef stable_parent, uint16_t pos)
- : stable_parent(stable_parent), pos(pos) {}
-
- template <typename parent_t>
- TCachedExtentRef<parent_t> get_parent() {
- ceph_assert(stable_parent);
- return stable_parent->template cast<parent_t>();
- }
- uint16_t get_pos() {
- return pos;
- }
- void link_child(ChildableCachedExtent *c);
-private:
- CachedExtentRef stable_parent;
- uint16_t pos = std::numeric_limits<uint16_t>::max();
-};
-
-using get_child_iertr = trans_iertr<crimson::errorator<
- crimson::ct_error::input_output_error>>;
-template <typename T>
-using get_child_ifut = get_child_iertr::future<TCachedExtentRef<T>>;
-
-template <typename T>
-struct get_child_ret_t {
- std::variant<child_pos_t, get_child_ifut<T>> ret;
- get_child_ret_t(child_pos_t pos)
- : ret(std::move(pos)) {}
- get_child_ret_t(get_child_ifut<T> child)
- : ret(std::move(child)) {}
-
- bool has_child() const {
- return ret.index() == 1;
- }
-
- child_pos_t &get_child_pos() {
- ceph_assert(ret.index() == 0);
- return std::get<0>(ret);
- }
-
- get_child_ifut<T> &get_child_fut() {
- ceph_assert(ret.index() == 1);
- return std::get<1>(ret);
- }
-};
-
template <typename key_t, typename>
class PhysicalNodeMapping;
}
};
-class parent_tracker_t
- : public boost::intrusive_ref_counter<
- parent_tracker_t, boost::thread_unsafe_counter> {
-public:
- parent_tracker_t(CachedExtentRef parent)
- : parent(parent) {}
- parent_tracker_t(CachedExtent* parent)
- : parent(parent) {}
- ~parent_tracker_t();
- template <typename T = CachedExtent>
- TCachedExtentRef<T> get_parent() const {
- ceph_assert(parent);
- if constexpr (std::is_same_v<T, CachedExtent>) {
- return parent;
- } else {
- return parent->template cast<T>();
- }
- }
- void reset_parent(CachedExtentRef p) {
- parent = p;
- }
- bool is_valid() const {
- return parent && parent->is_valid();
- }
-private:
- CachedExtentRef parent;
-};
-
-std::ostream &operator<<(std::ostream &, const parent_tracker_t &);
-
-using parent_tracker_ref = boost::intrusive_ptr<parent_tracker_t>;
-
-class ChildableCachedExtent : public CachedExtent {
-public:
- template <typename... T>
- ChildableCachedExtent(T&&... t) : CachedExtent(std::forward<T>(t)...) {}
- bool has_parent_tracker() const {
- return (bool)parent_tracker;
- }
- void reset_parent_tracker(parent_tracker_t *p = nullptr) {
- parent_tracker.reset(p);
- }
- bool is_parent_valid() const {
- return parent_tracker && parent_tracker->is_valid();
- }
- template <typename T = CachedExtent>
- TCachedExtentRef<T> get_parent_node() const {
- assert(parent_tracker);
- return parent_tracker->template get_parent<T>();
- }
- void take_prior_parent_tracker() {
- auto &prior = (ChildableCachedExtent&)(*get_prior_instance());
- parent_tracker = prior.parent_tracker;
- }
- std::ostream &print_detail(std::ostream &out) const final;
-private:
- parent_tracker_ref parent_tracker;
- virtual std::ostream &_print_detail(std::ostream &out) const {
- return out;
- }
-};
-
class LBAMapping;
/**
* LogicalCachedExtent
* Users of TransactionManager should be using extents derived from
* LogicalCachedExtent.
*/
-class LogicalCachedExtent : public ChildableCachedExtent {
+class LogicalCachedExtent : public CachedExtent {
public:
template <typename... T>
- LogicalCachedExtent(T&&... t)
- : ChildableCachedExtent(std::forward<T>(t)...)
- {}
+ LogicalCachedExtent(T&&... t) : CachedExtent(std::forward<T>(t)...) {}
void on_rewrite(Transaction&, CachedExtent &extent, extent_len_t off) final {
assert(get_type() == extent.get_type());
return true;
}
- std::ostream &_print_detail(std::ostream &out) const final;
+ std::ostream &print_detail(std::ostream &out) const final;
struct modified_region_t {
extent_len_t offset;
virtual void clear_modified_region() {}
- virtual ~LogicalCachedExtent();
+ virtual ~LogicalCachedExtent() {}
protected:
- void on_replace_prior() final;
virtual void apply_delta(const ceph::bufferlist &bl) = 0;
#include "crimson/os/seastore/seastore_types.h"
#include "crimson/os/seastore/transaction_manager.h"
#include "crimson/os/seastore/collection_manager.h"
+#include "crimson/os/seastore/logical_child_node.h"
namespace crimson::os::seastore::collection_manager {
struct coll_context_t {
namespace crimson::os::seastore::collection_manager {
-struct CollectionNode
- : LogicalCachedExtent {
+struct CollectionNode : LogicalChildNode {
using CollectionNodeRef = TCachedExtentRef<CollectionNode>;
explicit CollectionNode(ceph::bufferptr &&ptr)
- : LogicalCachedExtent(std::move(ptr)) {}
+ : LogicalChildNode(std::move(ptr)) {}
explicit CollectionNode(extent_len_t length)
- : LogicalCachedExtent(length) {}
+ : LogicalChildNode(length) {}
explicit CollectionNode(const CollectionNode &other)
- : LogicalCachedExtent(other),
+ : LogicalChildNode(other),
decoded(other.decoded) {}
static constexpr extent_types_t type = extent_types_t::COLL_BLOCK;
LBAManager::update_mappings_ret
LBAManager::update_mappings(
Transaction& t,
- const std::list<LogicalCachedExtentRef>& extents)
+ const std::list<LogicalChildNodeRef>& extents)
{
return trans_intr::do_for_each(extents,
[this, &t](auto &extent) {
#include "crimson/os/seastore/cache.h"
#include "crimson/os/seastore/seastore_types.h"
#include "crimson/os/seastore/lba_mapping.h"
+#include "crimson/os/seastore/logical_child_node.h"
namespace crimson::os::seastore {
virtual alloc_extent_ret alloc_extent(
Transaction &t,
laddr_t hint,
- LogicalCachedExtent &nextent,
+ LogicalChildNode &nextent,
extent_ref_count_t refcount = EXTENT_DEFAULT_REF_COUNT) = 0;
using alloc_extents_ret = alloc_extent_iertr::future<
virtual alloc_extents_ret alloc_extents(
Transaction &t,
laddr_t hint,
- std::vector<LogicalCachedExtentRef> extents,
+ std::vector<LogicalChildNodeRef> extents,
extent_ref_count_t refcount) = 0;
virtual alloc_extent_ret clone_mapping(
Transaction &t,
LBAMappingRef orig_mapping,
std::vector<remap_entry> remaps,
- std::vector<LogicalCachedExtentRef> extents // Required if and only
+ std::vector<LogicalChildNodeRef> extents // Required if and only
// if pin isn't indirect
) = 0;
/**
* Should be called after replay on each cached extent.
* Implementation must initialize the LBAMapping on any
- * LogicalCachedExtent's and may also read in any dependent
+ * LogicalChildNode's and may also read in any dependent
* structures, etc.
*
* @return returns whether the extent is alive
Transaction &t,
CachedExtentRef e) = 0;
+#ifdef UNIT_TESTS_BUILT
using check_child_trackers_ret = base_iertr::future<>;
virtual check_child_trackers_ret check_child_trackers(Transaction &t) = 0;
+#endif
/**
* Calls f for each mapping in [begin, end)
extent_len_t len,
paddr_t paddr,
uint32_t checksum,
- LogicalCachedExtent *nextent) = 0;
+ LogicalChildNode *nextent) = 0;
/**
* update_mappings
using update_mappings_ret = update_mappings_iertr::future<>;
update_mappings_ret update_mappings(
Transaction& t,
- const std::list<LogicalCachedExtentRef>& extents);
+ const std::list<LogicalChildNodeRef>& extents);
/**
* get_physical_extent_if_live
}
}
-template <typename ROOT>
-void link_phy_tree_root_node(RootBlockRef &root_block, ROOT* lba_root) {
- root_block->lba_root_node = lba_root;
- ceph_assert(lba_root != nullptr);
- lba_root->root_block = root_block;
-}
-
-template void link_phy_tree_root_node(
- RootBlockRef &root_block, lba_manager::btree::LBAInternalNode* lba_root);
-template void link_phy_tree_root_node(
- RootBlockRef &root_block, lba_manager::btree::LBALeafNode* lba_root);
-template void link_phy_tree_root_node(
- RootBlockRef &root_block, lba_manager::btree::LBANode* lba_root);
+template <typename RootT>
+class TreeRootLinker<RootBlock, RootT> {
+public:
+ static void link_root(RootBlockRef &root_block, RootT* lba_root) {
+ root_block->lba_root_node = lba_root;
+ ceph_assert(lba_root != nullptr);
+ lba_root->parent_of_root = root_block;
+ }
+ static void unlink_root(RootBlockRef &root_block) {
+ root_block->lba_root_node = nullptr;
+ }
+};
-template <>
-void unlink_phy_tree_root_node<laddr_t>(RootBlockRef &root_block) {
- root_block->lba_root_node = nullptr;
-}
+template class TreeRootLinker<RootBlock, lba_manager::btree::LBAInternalNode>;
+template class TreeRootLinker<RootBlock, lba_manager::btree::LBALeafNode>;
}
namespace crimson::os::seastore::lba_manager::btree {
-get_child_ret_t<LogicalCachedExtent>
+get_child_ret_t<lba_manager::btree::LBALeafNode, LogicalChildNode>
BtreeLBAMapping::get_logical_extent(Transaction &t)
{
ceph_assert(is_parent_viewable());
auto k = this->is_indirect()
? this->get_intermediate_base()
: get_key();
- auto v = p.template get_child<LogicalCachedExtent>(ctx, pos, k);
+ auto v = p.template get_child<LogicalChildNode>(ctx.trans, ctx.cache, pos, k);
if (!v.has_child()) {
this->child_pos = v.get_child_pos();
}
bool BtreeLBAMapping::is_stable() const
{
- assert(!this->parent_modified());
+ assert(!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();
+ 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(!this->parent_modified());
+ assert(!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();
+ auto &p = (LBALeafNode&)*parent;
+ auto k = is_indirect() ? get_intermediate_base() : get_key();
return p.is_child_data_stable(ctx, pos, k);
}
bool &ret)
{
if (e->is_logical()) {
- auto logn = e->cast<LogicalCachedExtent>();
+ auto logn = e->cast<LogicalChildNode>();
return btree.lower_bound(
c,
logn->get_laddr()
});
}
+#ifdef UNIT_TESTS_BUILT
BtreeLBAManager::check_child_trackers_ret
BtreeLBAManager::check_child_trackers(
Transaction &t) {
return btree.check_child_trackers(c);
});
}
+#endif
BtreeLBAManager::scan_mappings_ret
BtreeLBAManager::scan_mappings(
extent_len_t len,
paddr_t addr,
uint32_t checksum,
- LogicalCachedExtent *nextent)
+ LogicalChildNode *nextent)
{
LOG_PREFIX(BtreeLBAManager::update_mapping);
TRACET("laddr={}, paddr {} => {}", t, laddr, prev_addr, addr);
Transaction &t,
laddr_t addr,
update_func_t &&f,
- LogicalCachedExtent* nextent)
+ LogicalChildNode* nextent)
{
auto c = get_context(t);
return with_btree_ret<LBABtree, update_mapping_ret_bare_t>(
namespace crimson::os::seastore::lba_manager::btree {
-struct LBALeafNode;
-
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
raw_val(val.pladdr),
map_val(val),
parent_modifications(parent->modifications)
- {}
+ {
+ if (!parent->is_pending()) {
+ this->child_pos = {parent, pos};
+ }
+ }
lba_map_val_t get_map_val() const {
return map_val;
}
bool is_stable() const final;
bool is_data_stable() const final;
- get_child_ret_t<LogicalCachedExtent> get_logical_extent(Transaction &t);
+ get_child_ret_t<lba_manager::btree::LBALeafNode, LogicalChildNode>
+ get_logical_extent(Transaction &t);
protected:
LBAMappingRef _duplicate(
extent_len_t len = 0;
pladdr_t val;
uint32_t checksum = 0;
- LogicalCachedExtent* extent = nullptr;
+ LogicalChildNode* extent = nullptr;
static alloc_mapping_info_t create_zero(extent_len_t len) {
return {L_ADDR_NULL, len, P_ADDR_ZERO, 0, nullptr};
extent_len_t len,
paddr_t paddr,
uint32_t checksum,
- LogicalCachedExtent *extent) {
+ LogicalChildNode *extent) {
return {laddr, len, paddr, checksum, extent};
}
};
alloc_extent_ret alloc_extent(
Transaction &t,
laddr_t hint,
- LogicalCachedExtent &ext,
+ LogicalChildNode &ext,
extent_ref_count_t refcount = EXTENT_DEFAULT_REF_COUNT) final
{
// The real checksum will be updated upon transaction commit
alloc_extents_ret alloc_extents(
Transaction &t,
laddr_t hint,
- std::vector<LogicalCachedExtentRef> extents,
+ std::vector<LogicalChildNodeRef> extents,
extent_ref_count_t refcount) final
{
std::vector<alloc_mapping_info_t> alloc_infos;
Transaction &t,
LBAMappingRef orig_mapping,
std::vector<remap_entry> remaps,
- std::vector<LogicalCachedExtentRef> extents) final {
+ std::vector<LogicalChildNodeRef> extents) final {
LOG_PREFIX(BtreeLBAManager::remap_mappings);
assert((orig_mapping->is_indirect())
== (remaps.size() != extents.size()));
Transaction &t,
CachedExtentRef e) final;
+#ifdef UNIT_TESTS_BUILT
check_child_trackers_ret check_child_trackers(Transaction &t) final;
+#endif
scan_mappings_ret scan_mappings(
Transaction &t,
extent_len_t len,
paddr_t paddr,
uint32_t checksum,
- LogicalCachedExtent*) final;
+ LogicalChildNode*) final;
get_physical_extent_if_live_ret get_physical_extent_if_live(
Transaction &t,
Transaction &t,
laddr_t addr,
update_func_t &&f,
- LogicalCachedExtent*);
+ LogicalChildNode*);
alloc_extents_ret _alloc_extents(
Transaction &t,
#include "crimson/os/seastore/lba_manager/btree/btree_lba_manager.h"
#include "crimson/os/seastore/logging.h"
+#include "crimson/os/seastore/logical_child_node.h"
SET_SUBSYS(seastore_lba);
<< ")";
}
-std::ostream &LBALeafNode::_print_detail(std::ostream &out) const
+std::ostream &LBALeafNode::print_detail(std::ostream &out) const
{
out << ", size=" << this->get_size()
<< ", meta=" << this->get_meta()
if (this->my_tracker) {
out << ", my_tracker->parent=" << (void*)this->my_tracker->get_parent().get();
}
- return out << ", root_block=" << (void*)this->root_block.get();
+ return out << ", root_block=" << (void*)this->parent_of_root.get();
}
void LBALeafNode::resolve_relative_addrs(paddr_t base)
lba_node_meta_t{laddr, (laddr + val.len).checked_to_laddr(), 0});
}
+void LBALeafNode::update(
+ internal_const_iterator_t iter,
+ lba_map_val_t val,
+ LogicalChildNode* nextent)
+{
+ LOG_PREFIX(LBALeafNode::update);
+ if (nextent) {
+ SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, {}",
+ this->pending_for_transaction,
+ iter.get_offset(),
+ *nextent);
+ // child-ptr may already be correct, see LBAManager::update_mappings()
+ if (!nextent->has_parent_tracker()) {
+ this->update_child_ptr(iter.get_offset(), nextent);
+ }
+ assert(nextent->has_parent_tracker()
+ && nextent->get_parent_node().get() == this);
+ }
+ this->on_modify();
+ if (val.pladdr.is_paddr()) {
+ val.pladdr = maybe_generate_relative(val.pladdr.get_paddr());
+ }
+ return this->journal_update(
+ iter,
+ val,
+ this->maybe_get_delta_buffer());
+}
+
+LBALeafNode::internal_const_iterator_t LBALeafNode::insert(
+ internal_const_iterator_t iter,
+ laddr_t addr,
+ lba_map_val_t val,
+ LogicalChildNode* nextent)
+{
+ LOG_PREFIX(LBALeafNode::insert);
+ SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, key {}, extent {}",
+ this->pending_for_transaction,
+ iter.get_offset(),
+ addr,
+ (void*)nextent);
+ this->on_modify();
+ this->insert_child_ptr(iter.get_offset(), nextent);
+ if (val.pladdr.is_paddr()) {
+ val.pladdr = maybe_generate_relative(val.pladdr.get_paddr());
+ }
+ this->journal_insert(
+ iter,
+ addr,
+ val,
+ this->maybe_get_delta_buffer());
+ return iter;
+}
+
}
#include "crimson/common/fixed_kv_node_layout.h"
#include "crimson/common/errorator.h"
-#include "crimson/os/seastore/lba_manager.h"
#include "crimson/os/seastore/seastore_types.h"
#include "crimson/os/seastore/cache.h"
#include "crimson/os/seastore/cached_extent.h"
#include "crimson/os/seastore/btree/fixed_kv_btree.h"
#include "crimson/os/seastore/btree/fixed_kv_node.h"
+namespace crimson::os::seastore {
+class LogicalChildNode;
+}
+
namespace crimson::os::seastore::lba_manager::btree {
-using base_iertr = LBAManager::base_iertr;
+using base_iertr = Cache::base_iertr;
using LBANode = FixedKVNode<laddr_t>;
class BtreeLBAMapping;
"INTERNAL_NODE_CAPACITY doesn't fit in LBA_BLOCK_SIZE");
using Ref = TCachedExtentRef<LBAInternalNode>;
using internal_iterator_t = const_iterator;
+ using key_type = laddr_t;
template <typename... T>
LBAInternalNode(T&&... t) :
FixedKVInternalNode(std::forward<T>(t)...) {}
laddr_t, laddr_le_t,
lba_map_val_t, lba_map_val_le_t,
LBA_BLOCK_SIZE,
+ LBAInternalNode,
LBALeafNode,
+ LogicalChildNode,
true> {
static_assert(
check_capacity(LBA_BLOCK_SIZE),
laddr_t, laddr_le_t,
lba_map_val_t, lba_map_val_le_t,
LBA_BLOCK_SIZE,
+ LBAInternalNode,
LBALeafNode,
+ LogicalChildNode,
true>;
using internal_const_iterator_t =
typename parent_type_t::node_layout_t::const_iterator;
using internal_iterator_t =
typename parent_type_t::node_layout_t::iterator;
+ using key_type = laddr_t;
template <typename... T>
LBALeafNode(T&&... t) :
parent_type_t(std::forward<T>(t)...) {}
static constexpr extent_types_t TYPE = extent_types_t::LADDR_LEAF;
- bool validate_stable_children() final {
- LOG_PREFIX(LBALeafNode::validate_stable_children);
- if (this->children.empty()) {
- return false;
- }
-
- for (auto i : *this) {
- auto child = (LogicalCachedExtent*)this->children[i.get_offset()];
- // Children may not be marked as stable yet,
- // the specific order is undefined in the transaction prepare record phase.
- if (is_valid_child_ptr(child) && child->get_laddr() != i.get_key()) {
- SUBERROR(seastore_fixedkv_tree,
- "stable child not valid: child {}, key {}",
- *child,
- i.get_key());
- ceph_abort();
- return false;
- }
- }
- return true;
- }
-
void update(
internal_const_iterator_t iter,
lba_map_val_t val,
- LogicalCachedExtent* nextent) final {
- LOG_PREFIX(LBALeafNode::update);
- if (nextent) {
- SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, {}",
- this->pending_for_transaction,
- iter.get_offset(),
- *nextent);
- // child-ptr may already be correct, see LBAManager::update_mappings()
- if (!nextent->has_parent_tracker()) {
- this->update_child_ptr(iter, nextent);
- }
- assert(nextent->has_parent_tracker()
- && nextent->get_parent_node<LBALeafNode>().get() == this);
- }
- this->on_modify();
- if (val.pladdr.is_paddr()) {
- val.pladdr = maybe_generate_relative(val.pladdr.get_paddr());
- }
- return this->journal_update(
- iter,
- val,
- this->maybe_get_delta_buffer());
- }
+ LogicalChildNode* nextent) final;
internal_const_iterator_t insert(
internal_const_iterator_t iter,
laddr_t addr,
lba_map_val_t val,
- LogicalCachedExtent* nextent) final {
- LOG_PREFIX(LBALeafNode::insert);
- SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, key {}, extent {}",
- this->pending_for_transaction,
- iter.get_offset(),
- addr,
- (void*)nextent);
- this->on_modify();
- this->insert_child_ptr(iter, nextent);
- if (val.pladdr.is_paddr()) {
- val.pladdr = maybe_generate_relative(val.pladdr.get_paddr());
- }
- this->journal_insert(
- iter,
- addr,
- val,
- this->maybe_get_delta_buffer());
- return iter;
- }
+ LogicalChildNode* nextent) final;
void remove(internal_const_iterator_t iter) final {
LOG_PREFIX(LBALeafNode::remove);
iter.get_key());
assert(iter != this->end());
this->on_modify();
- this->remove_child_ptr(iter);
+ this->remove_child_ptr(iter.get_offset());
return this->journal_remove(
iter,
this->maybe_get_delta_buffer());
return TYPE;
}
- std::ostream &_print_detail(std::ostream &out) const final;
+ std::ostream &print_detail(std::ostream &out) const final;
void maybe_fix_mapping_pos(BtreeLBAMapping &mapping);
std::unique_ptr<BtreeLBAMapping> get_mapping(op_context_t<laddr_t> c, laddr_t laddr);
#include "crimson/os/seastore/cached_extent.h"
#include "crimson/os/seastore/btree/btree_range_pin.h"
+#include "crimson/os/seastore/lba_manager/btree/lba_btree_node.h"
+#include "crimson/os/seastore/logical_child_node.h"
namespace crimson::os::seastore {
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;
// 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>
+ virtual get_child_ret_t<lba_manager::btree::LBALeafNode, LogicalChildNode>
get_logical_extent(Transaction &t) = 0;
- void link_child(ChildableCachedExtent *c) {
+ void link_child(LogicalChildNode *c) {
ceph_assert(child_pos);
child_pos->link_child(c);
}
virtual ~LBAMapping() {}
protected:
virtual LBAMappingRef _duplicate(op_context_t<laddr_t>) const = 0;
- std::optional<child_pos_t> child_pos = std::nullopt;
+ std::optional<child_pos_t<
+ lba_manager::btree::LBALeafNode>> child_pos = std::nullopt;
};
std::ostream &operator<<(std::ostream &out, const LBAMapping &rhs);
friend class parent_tracker_t;
template <typename>
friend class child_pos_t;
-#ifndef UNIT_TESTS_BUILT
+#ifdef UNIT_TESTS_BUILT
template <typename, typename, typename, typename, typename, size_t, bool>
friend class FixedKVBtree;
#endif
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "crimson/os/seastore/logical_child_node.h"
+#include "crimson/os/seastore/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
--- /dev/null
+// -*- 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/linked_tree_node.h"
+#include "crimson/os/seastore/btree/btree_range_pin.h"
+#include "crimson/os/seastore/lba_manager/btree/lba_btree_node.h"
+
+namespace crimson::os::seastore {
+
+class LogicalChildNode : public LogicalCachedExtent,
+ public ChildNode<lba_manager::btree::LBALeafNode,
+ LogicalChildNode,
+ laddr_t> {
+ using child_node_t = ChildNode<
+ lba_manager::btree::LBALeafNode, LogicalChildNode, laddr_t>;
+public:
+ template <typename... T>
+ LogicalChildNode(T&&... t) : LogicalCachedExtent(std::forward<T>(t)...) {}
+
+ virtual ~LogicalChildNode() {
+ if (this->has_parent_tracker() &&
+ this->is_valid() &&
+ !this->is_pending()) {
+ child_node_t::destroy();
+ }
+ }
+
+ bool is_btree_root() const {
+ return false;
+ }
+
+ laddr_t get_begin() const {
+ return get_laddr();
+ }
+
+ laddr_t get_end() const {
+ return (get_laddr() + get_length()).checked_to_laddr();
+ }
+protected:
+ void on_replace_prior() final {
+ child_node_t::on_replace_prior();
+ }
+};
+using LogicalChildNodeRef = TCachedExtentRef<LogicalChildNode>;
+} // namespace crimson::os::seastore
+
+#if FMT_VERSION >= 90000
+template <> struct fmt::formatter<crimson::os::seastore::LogicalChildNode> : fmt::ostream_formatter {};
+#endif
#include "crimson/os/seastore/onode.h"
#include "crimson/os/seastore/transaction_manager.h"
#include "crimson/os/seastore/transaction.h"
+#include "crimson/os/seastore/logical_child_node.h"
namespace crimson::os::seastore {
mutable std::optional<ceph::bufferptr> ptr = std::nullopt;
};
-struct ObjectDataBlock : crimson::os::seastore::LogicalCachedExtent {
+struct ObjectDataBlock : crimson::os::seastore::LogicalChildNode {
using Ref = TCachedExtentRef<ObjectDataBlock>;
std::vector<block_delta_t> delta = {};
overwrite_buf_t cached_overwrites;
explicit ObjectDataBlock(ceph::bufferptr &&ptr)
- : LogicalCachedExtent(std::move(ptr)) {}
+ : LogicalChildNode(std::move(ptr)) {}
explicit ObjectDataBlock(const ObjectDataBlock &other, share_buffer_t s)
- : LogicalCachedExtent(other, s), modified_region(other.modified_region) {}
+ : LogicalChildNode(other, s), modified_region(other.modified_region) {}
explicit ObjectDataBlock(extent_len_t length)
- : LogicalCachedExtent(length) {}
+ : LogicalChildNode(length) {}
CachedExtentRef duplicate_for_write(Transaction&) final {
return CachedExtentRef(new ObjectDataBlock(*this, share_buffer_t{}));
FAIL = 3
};
-struct OMapNode : LogicalCachedExtent {
+struct OMapNode : LogicalChildNode {
using base_iertr = OMapManager::base_iertr;
using OMapNodeRef = TCachedExtentRef<OMapNode>;
need_merge(n_merge) {}
};
- explicit OMapNode(ceph::bufferptr &&ptr) : LogicalCachedExtent(std::move(ptr)) {}
- explicit OMapNode(extent_len_t length) : LogicalCachedExtent(length) {}
+ explicit OMapNode(ceph::bufferptr &&ptr) : LogicalChildNode(std::move(ptr)) {}
+ explicit OMapNode(extent_len_t length) : LogicalChildNode(length) {}
OMapNode(const OMapNode &other)
- : LogicalCachedExtent(other) {}
+ : LogicalChildNode(other) {}
using get_value_iertr = base_iertr;
using get_value_ret = OMapManager::omap_get_value_ret;
namespace crimson::os::seastore::onode {
-using crimson::os::seastore::LogicalCachedExtent;
-class NodeExtent : public LogicalCachedExtent {
+class NodeExtent : public LogicalChildNode {
public:
virtual ~NodeExtent() = default;
const node_header_t& get_header() const {
protected:
template <typename... T>
- NodeExtent(T&&... t) : LogicalCachedExtent(std::forward<T>(t)...) {}
+ NodeExtent(T&&... t) : LogicalChildNode(std::forward<T>(t)...) {}
NodeExtentMutable do_get_mutable() {
return NodeExtentMutable(get_bptr().c_str(), get_length());
retire_iertr::future<> retire_extent(
Transaction& t, NodeExtentRef _extent) override {
- LogicalCachedExtentRef extent = _extent;
+ LogicalChildNodeRef extent = _extent;
auto addr = extent->get_laddr();
auto len = extent->get_length();
SUBDEBUGT(seastore_onode,
#include "crimson/os/seastore/root_block.h"
#include "crimson/os/seastore/lba_manager/btree/lba_btree_node.h"
#include "crimson/os/seastore/backref/backref_tree_node.h"
+#include "crimson/os/seastore/linked_tree_node.h"
namespace crimson::os::seastore {
auto &prior = static_cast<RootBlock&>(*get_prior_instance());
if (prior.lba_root_node) {
RootBlockRef this_ref = this;
- link_phy_tree_root_node(
- this_ref,
- static_cast<lba_manager::btree::LBANode*>(prior.lba_root_node)
- );
+ auto lba_root = static_cast<
+ lba_manager::btree::LBANode*>(prior.lba_root_node);
+ if (likely(lba_root->range.depth > 1)) {
+ TreeRootLinker<RootBlock, lba_manager::btree::LBAInternalNode>::link_root(
+ this_ref,
+ static_cast<lba_manager::btree::LBAInternalNode*>(prior.lba_root_node)
+ );
+ } else {
+ assert(lba_root->range.depth == 1);
+ TreeRootLinker<RootBlock, lba_manager::btree::LBALeafNode>::link_root(
+ this_ref,
+ static_cast<lba_manager::btree::LBALeafNode*>(prior.lba_root_node)
+ );
+ }
}
}
if (!backref_root_node) {
auto &prior = static_cast<RootBlock&>(*get_prior_instance());
if (prior.backref_root_node) {
RootBlockRef this_ref = this;
- link_phy_tree_root_node(
- this_ref,
- static_cast<backref::BackrefNode*>(prior.backref_root_node)
- );
+ auto backref_root = static_cast<
+ backref::BackrefNode*>(prior.backref_root_node);
+ if (likely(backref_root->range.depth > 1)) {
+ TreeRootLinker<RootBlock, backref::BackrefInternalNode>::link_root(
+ this_ref,
+ static_cast<backref::BackrefInternalNode*>(prior.backref_root_node)
+ );
+ } else {
+ assert(backref_root->range.depth == 1);
+ TreeRootLinker<RootBlock, backref::BackrefLeafNode>::link_root(
+ this_ref,
+ static_cast<backref::BackrefLeafNode*>(prior.backref_root_node)
+ );
+ }
}
}
}
#pragma once
-#include "crimson/os/seastore/cached_extent.h"
+#include "crimson/os/seastore/logical_child_node.h"
namespace crimson::os::seastore {
-struct RootMetaBlock : LogicalCachedExtent {
+struct RootMetaBlock : LogicalChildNode {
using meta_t = std::map<std::string, std::string>;
using Ref = TCachedExtentRef<RootMetaBlock>;
static constexpr size_t SIZE = 4096;
static constexpr int MAX_META_LENGTH = 1024;
explicit RootMetaBlock(ceph::bufferptr &&ptr)
- : LogicalCachedExtent(std::move(ptr)) {}
+ : LogicalChildNode(std::move(ptr)) {}
explicit RootMetaBlock(extent_len_t length)
- : LogicalCachedExtent(length) {}
+ : LogicalChildNode(length) {}
RootMetaBlock(const RootMetaBlock &rhs)
- : LogicalCachedExtent(rhs) {}
+ : LogicalChildNode(rhs) {}
CachedExtentRef duplicate_for_write(Transaction&) final {
return CachedExtentRef(new RootMetaBlock(*this));
#ifdef UNIT_TESTS_BUILT
TransactionManager::ref_ret TransactionManager::inc_ref(
Transaction &t,
- LogicalCachedExtentRef &ref)
+ LogicalChildNodeRef &ref)
{
LOG_PREFIX(TransactionManager::inc_ref);
TRACET("{}", t, *ref);
TransactionManager::ref_ret TransactionManager::remove(
Transaction &t,
- LogicalCachedExtentRef &ref)
+ LogicalChildNodeRef &ref)
{
LOG_PREFIX(TransactionManager::remove);
DEBUGT("{} ...", t, *ref);
LOG_PREFIX(TransactionManager::update_lba_mappings);
SUBTRACET(seastore_t, "update extent lba mappings", t);
return seastar::do_with(
- std::list<LogicalCachedExtentRef>(),
+ std::list<LogicalChildNodeRef>(),
std::list<CachedExtentRef>(),
[this, &t, &pre_allocated_extents](auto &lextents, auto &pextents) {
auto chksum_func = [&lextents, &pextents, this](auto &extent) {
assert(extent->get_last_committed_crc() == CRC_NULL);
}
#endif
- lextents.emplace_back(extent->template cast<LogicalCachedExtent>());
+ lextents.emplace_back(extent->template cast<LogicalChildNode>());
} else {
assert(is_physical_type(extent->get_type()));
pextents.emplace_back(extent);
TransactionManager::rewrite_extent_ret
TransactionManager::rewrite_logical_extent(
Transaction& t,
- LogicalCachedExtentRef extent)
+ LogicalChildNodeRef extent)
{
LOG_PREFIX(TransactionManager::rewrite_logical_extent);
if (extent->has_been_invalidated()) {
extent->get_length(),
extent->get_user_hint(),
// get target rewrite generation
- extent->get_rewrite_generation())->cast<LogicalCachedExtent>();
+ extent->get_rewrite_generation())->cast<LogicalChildNode>();
nextent->rewrite(t, *extent, 0);
DEBUGT("rewriting meta -- {} to {}", t, *extent, *nextent);
extents,
[extent, this, FNAME, &t, &off, &left, &refcount](auto &_nextent)
{
- auto nextent = _nextent->template cast<LogicalCachedExtent>();
+ auto nextent = _nextent->template cast<LogicalChildNode>();
bool first_extent = (off == 0);
ceph_assert(left >= nextent->get_length());
nextent->rewrite(t, *extent, off);
auto fut = rewrite_extent_iertr::now();
if (extent->is_logical()) {
assert(is_logical_type(extent->get_type()));
- fut = rewrite_logical_extent(t, extent->cast<LogicalCachedExtent>());
+ fut = rewrite_logical_extent(t, extent->cast<LogicalChildNode>());
} else if (is_backref_node(extent->get_type())) {
fut = backref_manager->rewrite_extent(t, extent);
} else {
}
/// Obtain mutable copy of extent
- LogicalCachedExtentRef get_mutable_extent(Transaction &t, LogicalCachedExtentRef ref) {
+ LogicalChildNodeRef get_mutable_extent(Transaction &t, LogicalChildNodeRef ref) {
LOG_PREFIX(TransactionManager::get_mutable_extent);
auto ret = cache->duplicate_for_write(
t,
- ref)->cast<LogicalCachedExtent>();
+ ref)->cast<LogicalChildNode>();
if (!ret->has_laddr()) {
SUBDEBUGT(seastore_tm, "duplicate from {}", t, *ref);
ret->set_laddr(ref->get_laddr());
/// Add refcount for ref
ref_ret inc_ref(
Transaction &t,
- LogicalCachedExtentRef &ref);
+ LogicalChildNodeRef &ref);
/// Add refcount for offset
ref_ret inc_ref(
*/
ref_ret remove(
Transaction &t,
- LogicalCachedExtentRef &ref);
+ LogicalChildNodeRef &ref);
ref_ret remove(
Transaction &t,
return lba_manager->alloc_extents(
t,
laddr_hint,
- std::vector<LogicalCachedExtentRef>(
+ std::vector<LogicalChildNodeRef>(
exts.begin(), exts.end()),
EXTENT_DEFAULT_REF_COUNT
).si_then([exts=std::move(exts), &t, FNAME](auto &&) mutable {
Transaction &t,
LBAMappingRef &&pin,
std::array<remap_entry, N> remaps) {
- static_assert(std::is_base_of_v<LogicalCachedExtent, T>);
+ static_assert(std::is_base_of_v<LogicalChildNode, T>);
#ifndef NDEBUG
std::sort(remaps.begin(), remaps.end(),
#endif
return seastar::do_with(
- std::vector<LogicalCachedExtentRef>(),
+ std::vector<LogicalChildNodeRef>(),
std::move(pin),
std::move(remaps),
[&t, this](auto &extents, auto &pin, auto &remaps) {
return v.get_child_fut(
).si_then([pin=std::move(pin)](auto extent) {
#ifndef NDEBUG
- auto lextent = extent->template cast<LogicalCachedExtent>();
+ auto lextent = extent->template cast<LogicalChildNode>();
auto pin_laddr = pin->get_key();
if (pin->is_indirect()) {
pin_laddr = pin->get_intermediate_base();
}
}
- base_iertr::future<LogicalCachedExtentRef> read_pin_by_type(
+ base_iertr::future<LogicalChildNodeRef> read_pin_by_type(
Transaction &t,
LBAMappingRef pin,
extent_types_t type)
rewrite_extent_ret rewrite_logical_extent(
Transaction& t,
- LogicalCachedExtentRef extent);
+ LogicalChildNodeRef extent);
submit_transaction_direct_ret do_submit_transaction(
Transaction &t,
* Get extent mapped at pin.
*/
using pin_to_extent_by_type_ret = pin_to_extent_iertr::future<
- LogicalCachedExtentRef>;
+ LogicalChildNodeRef>;
pin_to_extent_by_type_ret pin_to_extent_by_type(
Transaction &t,
LBAMappingRef pin,
direct_key,
direct_length,
[&pref](CachedExtent &extent) mutable {
- auto &lextent = static_cast<LogicalCachedExtent&>(extent);
+ auto &lextent = static_cast<LogicalChildNode&>(extent);
assert(!lextent.has_laddr());
assert(!lextent.has_been_invalidated());
assert(!pref.has_been_invalidated());
}
return pin_to_extent_by_type_ret(
interruptible::ready_future_marker{},
- std::move(ref->template cast<LogicalCachedExtent>()));
+ std::move(ref->template cast<LogicalChildNode>()));
});
}
#include <random>
#include "crimson/os/seastore/transaction_manager.h"
+#include "crimson/os/seastore/logical_child_node.h"
namespace crimson::os::seastore {
<< ", checksum=0x" << rhs.checksum << std::dec << ")";
}
-struct TestBlock : crimson::os::seastore::LogicalCachedExtent {
+struct TestBlock : crimson::os::seastore::LogicalChildNode {
constexpr static extent_len_t SIZE = 4<<10;
using Ref = TCachedExtentRef<TestBlock>;
interval_set<extent_len_t> modified_region;
explicit TestBlock(ceph::bufferptr &&ptr)
- : LogicalCachedExtent(std::move(ptr)) {}
+ : LogicalChildNode(std::move(ptr)) {}
explicit TestBlock(extent_len_t length)
- : LogicalCachedExtent(length) {}
+ : LogicalChildNode(length) {}
TestBlock(const TestBlock &other)
- : LogicalCachedExtent(other), modified_region(other.modified_region) {}
+ : LogicalChildNode(other), modified_region(other.modified_region) {}
CachedExtentRef duplicate_for_write(Transaction&) final {
return CachedExtentRef(new TestBlock(*this));
*t.t,
[this](auto &t) {
return seastar::do_with(
- std::list<LogicalCachedExtentRef>(),
+ std::list<LogicalChildNodeRef>(),
std::list<CachedExtentRef>(),
[this, &t](auto &lextents, auto &pextents) {
auto chksum_func = [&lextents, &pextents](auto &extent) {
extent->update_in_extent_chksum_field(crc);
}
assert(extent->calc_crc32c() == extent->get_last_committed_crc());
- lextents.emplace_back(extent->template cast<LogicalCachedExtent>());
+ lextents.emplace_back(extent->template cast<LogicalChildNode>());
} else {
pextents.push_back(extent);
}
0,
get_paddr());
return seastar::do_with(
- std::vector<LogicalCachedExtentRef>(
+ std::vector<LogicalChildNodeRef>(
extents.begin(), extents.end()),
[this, &t, hint](auto &extents) {
return lba_manager->alloc_extents(t, hint, std::move(extents), EXTENT_DEFAULT_REF_COUNT);