return p.is_child_stable(ctx, pos);
}
+template <typename key_t, typename val_t>
+bool BtreeNodeMapping<key_t, val_t>::is_data_stable() const
+{
+ assert(parent);
+ assert(parent->is_valid());
+ assert(pos != std::numeric_limits<uint16_t>::max());
+ auto &p = (FixedKVNode<key_t>&)*parent;
+ return p.is_child_data_stable(ctx, pos);
+}
+
template class BtreeNodeMapping<laddr_t, paddr_t>;
template class BtreeNodeMapping<paddr_t, laddr_t>;
} // namespace crimson::os::seastore
get_child_ret_t<LogicalCachedExtent> get_logical_extent(Transaction&) final;
bool is_stable() const final;
+ bool is_data_stable() const final;
};
}
}
virtual bool is_child_stable(op_context_t<node_key_t>, uint16_t pos) const = 0;
+ virtual bool is_child_data_stable(op_context_t<node_key_t>, uint16_t pos) const = 0;
template <typename T>
get_child_ret_t<T> get_child(
ceph_abort("impossible");
return false;
}
+ bool is_child_data_stable(op_context_t<NODE_KEY>, uint16_t pos) const final {
+ ceph_abort("impossible");
+ return false;
+ }
bool validate_stable_children() final {
LOG_PREFIX(FixedKVInternalNode::validate_stable_children);
//
// For reserved mappings, the return values are undefined.
bool is_child_stable(op_context_t<NODE_KEY> c, uint16_t pos) const final {
+ return _is_child_stable(c, pos);
+ }
+ bool is_child_data_stable(op_context_t<NODE_KEY> c, uint16_t pos) const final {
+ return _is_child_stable(c, pos, true);
+ }
+
+ bool _is_child_stable(op_context_t<NODE_KEY> c, uint16_t pos, bool data_only = false) const {
auto child = this->children[pos];
if (is_reserved_ptr(child)) {
return true;
ceph_assert(
child->is_pending_in_trans(c.trans.get_trans_id())
|| this->is_stable_written());
- return c.cache.is_viewable_extent_stable(c.trans, child);
+ 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 child = sparent.children[spos];
if (is_valid_child_ptr(child)) {
ceph_assert(child->is_logical());
- return c.cache.is_viewable_extent_stable(c.trans, child);
+ 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;
}
return view->is_stable();
}
+ bool is_viewable_extent_data_stable(
+ Transaction &t,
+ CachedExtentRef extent)
+ {
+ assert(extent);
+ auto view = extent->get_transactional_view(t);
+ return view->is_data_stable();
+ }
+
using get_extent_ertr = base_ertr;
get_extent_ertr::future<CachedExtentRef>
get_extent_viewable_by_trans(
is_pending_io());
}
+ bool is_data_stable() const {
+ return is_stable() || is_exist_clean();
+ }
+
/// Returns true if extent has a pending delta
bool is_mutation_pending() const {
return state == extent_state_t::MUTATION_PENDING;
// For reserved mappings, the return values are
// undefined although it won't crash
virtual bool is_stable() const = 0;
+ virtual bool is_data_stable() const = 0;
virtual bool is_clone() const = 0;
bool is_zero_reserved() const {
return !get_val().is_real();
interval_set<uint64_t> pre_alloc_addr_removed, pre_alloc_addr_remapped;
if (delta_based_overwrite_max_extent_size) {
for (auto &r : ops.to_remove) {
- // TODO: Introduce LBAMapping::is_data_stable() to include EXIST_CLEAN extents
- if (r->is_stable() && !r->is_zero_reserved()) {
+ if (r->is_data_stable() && !r->is_zero_reserved()) {
pre_alloc_addr_removed.insert(r->get_key(), r->get_length());
}
}
for (auto &r : ops.to_remap) {
- if (r.pin && r.pin->is_stable() && !r.pin->is_zero_reserved()) {
+ if (r.pin && r.pin->is_data_stable() && !r.pin->is_zero_reserved()) {
pre_alloc_addr_remapped.insert(r.pin->get_key(), r.pin->get_length());
}
}
read_extent_ret<T> get_mutable_extent_by_laddr(Transaction &t, laddr_t laddr, extent_len_t len) {
return get_pin(t, laddr
).si_then([this, &t, len](auto pin) {
- ceph_assert(pin->is_stable() && !pin->is_zero_reserved());
+ ceph_assert(pin->is_data_stable() && !pin->is_zero_reserved());
ceph_assert(!pin->is_clone());
ceph_assert(pin->get_length() == len);
return this->read_pin<T>(t, std::move(pin));
auto pin1 = remap_pin(*t, std::move(pins.front()), 4096, 8192);
auto ext = get_extent(*t, base + 4096, 4096 * 2);
ASSERT_TRUE(ext->is_exist_clean());
- ext = tm->get_mutable_extent(*t, ext)->cast<ObjectDataBlock>();
-
- auto l = 4096;
- memset(
- known_contents.c_str() + base + 4096,
- 'z',
- l);
- bufferlist bl;
- bl.append(
- bufferptr(
- known_contents,
- base + 4096,
- l));
-
- ext->overwrite(0, bl);
+ write(*t, base + 4096, 4096, 'y');
ASSERT_TRUE(ext->is_exist_mutation_pending());
+ write(*t, base + 8092, 4096, 'z');
}
submit_transaction(std::move(t));
read(base + 4096, 4096);