* - TRACE: DEBUG details
* - seastore_t logs
*/
-class Cache : public ExtentTransViewRetriever {
+class Cache : public ExtentTransViewRetriever,
+ public RetiredExtentPlaceholderInvalidater {
public:
using base_ertr = crimson::errorator<
crimson::ct_error::input_output_error>;
}
}
+ void invalidate_retired_placeholder(
+ Transaction &t,
+ CachedExtent &retired_placeholder,
+ CachedExtent &extent) {
+ // replace placeholder in transactions
+ while (!retired_placeholder.read_transactions.empty()) {
+ auto t = retired_placeholder.read_transactions.begin()->t;
+ t->replace_placeholder(retired_placeholder, extent);
+ }
+ retired_placeholder.set_invalid(t);
+ }
+
/*
* get_absent_extent
*
namespace crimson::os::seastore {
+struct RetiredExtentPlaceholderInvalidater {
+ virtual void invalidate_retired_placeholder(
+ Transaction &t,
+ CachedExtent &retired_placeholder,
+ CachedExtent &extent) = 0;
+};
+
template <typename ParentT>
class child_pos_t {
public:
child_pos_t(TCachedExtentRef<ParentT> stable_parent, btreenode_pos_t pos)
: stable_parent(stable_parent), pos(pos) {}
+ child_pos_t(
+ TCachedExtentRef<ParentT> stable_parent,
+ btreenode_pos_t pos,
+ CachedExtent* placeholder)
+ : stable_parent(stable_parent),
+ pos(pos),
+ retired_placeholder(placeholder) {
+ assert(retired_placeholder->is_placeholder());
+ }
TCachedExtentRef<ParentT> get_parent() {
ceph_assert(stable_parent);
void link_child(ChildT *c) {
get_parent()->link_child(c, pos);
}
+ void invalidate_retired_placeholder(
+ Transaction &t,
+ RetiredExtentPlaceholderInvalidater &repi,
+ CachedExtent &extent) {
+ if (retired_placeholder) {
+ repi.invalidate_retired_placeholder(t, *retired_placeholder, extent);
+ }
+ }
private:
TCachedExtentRef<ParentT> stable_parent;
btreenode_pos_t pos = std::numeric_limits<btreenode_pos_t>::max();
+ CachedExtentRef retired_placeholder;
};
using get_child_iertr = trans_iertr<crimson::errorator<
return parent_tracker->get_parent();
}
virtual key_t node_begin() const = 0;
+ virtual bool is_retired_placeholder() const = 0;
protected:
parent_tracker_ref<ParentT> parent_tracker;
virtual bool _is_valid() const = 0;
auto child = children[pos];
ceph_assert(!is_reserved_ptr(child));
if (is_valid_child_ptr(child)) {
- return etvr.get_extent_viewable_by_trans<ChildT>(
- t, static_cast<ChildT*>(child));
+ if (child->is_retired_placeholder()) {
+ assert(me.is_stable());
+ return child_pos_t<T>(
+ &me, pos, dynamic_cast<CachedExtent*>(child));
+ } else {
+ return etvr.get_extent_viewable_by_trans<ChildT>(
+ t, static_cast<ChildT*>(child));
+ }
} else if (me.is_pending()) {
auto &sparent = me.get_stable_for_key(key);
auto spos = sparent.lower_bound(key).get_offset();
auto child = sparent.children[spos];
if (is_valid_child_ptr(child)) {
- return etvr.get_extent_viewable_by_trans<ChildT>(
- t, static_cast<ChildT*>(child));
+ if (child->is_retired_placeholder()) {
+ return child_pos_t<T>(
+ &sparent, spos, dynamic_cast<CachedExtent*>(child));
+ } else {
+ return etvr.get_extent_viewable_by_trans<ChildT>(
+ t, static_cast<ChildT*>(child));
+ }
} else {
return child_pos_t<T>(&sparent, spos);
}
assert(child);
ceph_assert(me.is_stable());
assert(child->_is_stable());
- assert(!children[pos]);
+ if (unlikely(children[pos] != nullptr)) {
+ assert(is_valid_child_ptr(children[pos]));
+ assert(children[pos]->is_retired_placeholder());
+ }
ceph_assert(is_valid_child_ptr(child));
update_child_ptr(pos, child);
}
}
}
+ bool is_retired_placeholder() const final {
+ auto &me = down_cast();
+ return me.is_placeholder();
+ }
protected:
void on_invalidated() {
this->reset_parent_tracker();
partial_len,
[laddr=pin.get_intermediate_base(),
maybe_init=std::move(maybe_init),
- child_pos=std::move(child_pos)]
+ child_pos=std::move(child_pos),
+ &t, this]
(T &extent) mutable {
assert(extent.is_logical());
assert(!extent.has_laddr());
assert(!extent.has_been_invalidated());
child_pos.link_child(&extent);
+ child_pos.invalidate_retired_placeholder(t, *cache, extent);
extent.set_laddr(laddr);
maybe_init(extent);
extent.set_seen_by_users();
pin.get_val(),
direct_key,
direct_length,
- [direct_key, child_pos=std::move(child_pos)](CachedExtent &extent) mutable {
+ [direct_key, child_pos=std::move(child_pos),
+ &t, this](CachedExtent &extent) mutable {
assert(extent.is_logical());
auto &lextent = static_cast<LogicalChildNode&>(extent);
assert(!lextent.has_laddr());
assert(!lextent.has_been_invalidated());
child_pos.link_child(&lextent);
+ child_pos.invalidate_retired_placeholder(t, *cache, lextent);
lextent.set_laddr(direct_key);
// No change to extent::seen_by_user because this path is only
// for background cleaning.