mirror of
https://github.com/ceph/ceph
synced 2025-03-11 02:39:05 +00:00
crimson/os/seastore/.../lba_btree: fix min_capacity condition
Reducing the size of split_merge_multi has an interesting side effect of causing removes to happen on some leaf nodes immediately after split. After split, child nodes would have size 72 or 73. At size 72, the node would be at_min_size() and a remove would put it below causing the at_min_size() condition to fail and hande_merge to misbehave. Replace at_min_capacity() with below_min_capacity(). below_min_capacity() will not be true for any child of a split, and asserts that the child is below capacity by no more than 1. Signed-off-by: Samuel Just <sjust@redhat.com>
This commit is contained in:
parent
542d237ffe
commit
617b87228f
@ -666,7 +666,7 @@ LBABtree::handle_merge_ret merge_level(
|
||||
auto [liter, riter] = donor_is_left ?
|
||||
std::make_pair(donor_iter, iter) : std::make_pair(iter, donor_iter);
|
||||
|
||||
if (donor->at_min_capacity()) {
|
||||
if (donor->below_min_capacity()) {
|
||||
auto replacement = l->make_full_merge(c, r);
|
||||
|
||||
parent_pos.node->update(
|
||||
@ -727,8 +727,8 @@ LBABtree::handle_merge_ret LBABtree::handle_merge(
|
||||
iterator &iter)
|
||||
{
|
||||
LOG_PREFIX(LBATree::handle_merge);
|
||||
if (!iter.leaf.node->at_min_capacity() ||
|
||||
iter.get_depth() == 1) {
|
||||
if (iter.get_depth() == 1 ||
|
||||
!iter.leaf.node->below_min_capacity()) {
|
||||
DEBUGT(
|
||||
"no need to merge leaf, leaf size {}, depth {}",
|
||||
c.trans,
|
||||
@ -775,7 +775,7 @@ LBABtree::handle_merge_ret LBABtree::handle_merge(
|
||||
DEBUGT("no need to collapse root", c.trans);
|
||||
}
|
||||
return seastar::stop_iteration::yes;
|
||||
} else if (pos.node->at_min_capacity()) {
|
||||
} else if (pos.node->below_min_capacity()) {
|
||||
DEBUGT(
|
||||
"continuing, next node {} depth {} at min",
|
||||
c.trans,
|
||||
|
@ -157,11 +157,11 @@ public:
|
||||
}
|
||||
|
||||
depth_t check_merge() const {
|
||||
if (!leaf.node->at_min_capacity()) {
|
||||
if (!leaf.node->below_min_capacity()) {
|
||||
return 0;
|
||||
}
|
||||
for (depth_t merge_from = 1; merge_from < get_depth(); ++merge_from) {
|
||||
if (!get_internal(merge_from + 1).node->at_min_capacity())
|
||||
if (!get_internal(merge_from + 1).node->below_min_capacity())
|
||||
return merge_from;
|
||||
}
|
||||
return get_depth();
|
||||
|
@ -313,12 +313,18 @@ struct LBAInternalNode
|
||||
resolve_relative_addrs(base);
|
||||
}
|
||||
|
||||
constexpr static size_t get_min_capacity() {
|
||||
return (get_capacity() - 1) / 2;
|
||||
}
|
||||
|
||||
bool at_max_capacity() const {
|
||||
assert(get_size() <= get_capacity());
|
||||
return get_size() == get_capacity();
|
||||
}
|
||||
|
||||
bool at_min_capacity() const {
|
||||
return get_size() == (get_capacity() / 2);
|
||||
bool below_min_capacity() const {
|
||||
assert(get_size() >= (get_min_capacity() - 1));
|
||||
return get_size() < get_min_capacity();
|
||||
}
|
||||
};
|
||||
using LBAInternalNodeRef = LBAInternalNode::Ref;
|
||||
@ -530,12 +536,18 @@ struct LBALeafNode
|
||||
|
||||
std::ostream &print_detail(std::ostream &out) const final;
|
||||
|
||||
constexpr static size_t get_min_capacity() {
|
||||
return (get_capacity() - 1) / 2;
|
||||
}
|
||||
|
||||
bool at_max_capacity() const {
|
||||
assert(get_size() <= get_capacity());
|
||||
return get_size() == get_capacity();
|
||||
}
|
||||
|
||||
bool at_min_capacity() const {
|
||||
return get_size() == (get_capacity() / 2);
|
||||
bool below_min_capacity() const {
|
||||
assert(get_size() >= (get_min_capacity() - 1));
|
||||
return get_size() < get_min_capacity();
|
||||
}
|
||||
};
|
||||
using LBALeafNodeRef = TCachedExtentRef<LBALeafNode>;
|
||||
|
Loading…
Reference in New Issue
Block a user