From: Xuehan Xu Date: Wed, 28 Feb 2024 09:59:41 +0000 (+0800) Subject: crimson/os/seastore/btree: add CachedExtent::on_rewrite() and X-Git-Tag: v20.0.0~1896^2~7 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=1b8a781f665df06b056511debec46deac604a79c;p=ceph.git crimson/os/seastore/btree: add CachedExtent::on_rewrite() and CachedExtent::is_rewrite() Signed-off-by: Xuehan Xu --- diff --git a/src/crimson/os/seastore/btree/fixed_kv_btree.h b/src/crimson/os/seastore/btree/fixed_kv_btree.h index 504eca9e6fbf2..6518648053409 100644 --- a/src/crimson/os/seastore/btree/fixed_kv_btree.h +++ b/src/crimson/os/seastore/btree/fixed_kv_btree.h @@ -1034,46 +1034,7 @@ public: fixed_kv_extent.get_user_hint(), // get target rewrite generation fixed_kv_extent.get_rewrite_generation()); - fixed_kv_extent.get_bptr().copy_out( - 0, - fixed_kv_extent.get_length(), - n_fixed_kv_extent->get_bptr().c_str()); - n_fixed_kv_extent->set_modify_time(fixed_kv_extent.get_modify_time()); - n_fixed_kv_extent->range = n_fixed_kv_extent->get_node_meta(); - n_fixed_kv_extent->set_last_committed_crc(fixed_kv_extent.get_last_committed_crc()); - - if (fixed_kv_extent.get_type() == internal_node_t::TYPE || - leaf_node_t::do_has_children) { - if (!fixed_kv_extent.is_pending()) { - n_fixed_kv_extent->copy_sources.emplace(&fixed_kv_extent); - n_fixed_kv_extent->prior_instance = &fixed_kv_extent; - } else { - ceph_assert(fixed_kv_extent.is_mutation_pending()); - n_fixed_kv_extent->copy_sources.emplace( - (typename internal_node_t::base_t* - )fixed_kv_extent.get_prior_instance().get()); - n_fixed_kv_extent->children = std::move(fixed_kv_extent.children); - n_fixed_kv_extent->prior_instance = fixed_kv_extent.get_prior_instance(); - n_fixed_kv_extent->adjust_ptracker_for_children(); - } - } - - /* This is a bit underhanded. Any relative addrs here must necessarily - * be record relative as we are rewriting a dirty extent. Thus, we - * are using resolve_relative_addrs with a (likely negative) block - * relative offset to correct them to block-relative offsets adjusted - * for our new transaction location. - * - * Upon commit, these now block relative addresses will be interpretted - * against the real final address. - */ - if (!n_fixed_kv_extent->get_paddr().is_absolute()) { - // backend_type_t::SEGMENTED - assert(n_fixed_kv_extent->get_paddr().is_record_relative()); - n_fixed_kv_extent->resolve_relative_addrs( - make_record_relative_paddr(0).block_relative_to( - n_fixed_kv_extent->get_paddr())); - } // else: backend_type_t::RANDOM_BLOCK + n_fixed_kv_extent->rewrite(fixed_kv_extent, 0); SUBTRACET( seastore_fixedkv_tree, diff --git a/src/crimson/os/seastore/btree/fixed_kv_node.h b/src/crimson/os/seastore/btree/fixed_kv_node.h index 14a1703abbc81..31b9067a74439 100644 --- a/src/crimson/os/seastore/btree/fixed_kv_node.h +++ b/src/crimson/os/seastore/btree/fixed_kv_node.h @@ -157,6 +157,43 @@ struct FixedKVNode : ChildableCachedExtent { (get_node_size() - offset - 1) * sizeof(ChildableCachedExtent*)); } + virtual bool have_children() const = 0; + + void on_rewrite(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()) { + copy_sources.emplace(&foreign_extent); + } else { + ceph_assert(foreign_extent.is_mutation_pending()); + copy_sources.emplace( + foreign_extent.get_prior_instance()->template cast()); + children = std::move(foreign_extent.children); + adjust_ptracker_for_children(); + } + } + + /* This is a bit underhanded. Any relative addrs here must necessarily + * be record relative as we are rewriting a dirty extent. Thus, we + * are using resolve_relative_addrs with a (likely negative) block + * relative offset to correct them to block-relative offsets adjusted + * for our new transaction location. + * + * Upon commit, these now block relative addresses will be interpretted + * against the real final address. + */ + if (!get_paddr().is_absolute()) { + // backend_type_t::SEGMENTED + assert(get_paddr().is_record_relative()); + resolve_relative_addrs( + make_record_relative_paddr(0).block_relative_to(get_paddr())); + } // else: backend_type_t::RANDOM_BLOCK + } + FixedKVNode& get_stable_for_key(node_key_t key) const { ceph_assert(is_pending()); if (is_mutation_pending()) { @@ -488,10 +525,6 @@ struct FixedKVNode : ChildableCachedExtent { reset_parent_tracker(); } - bool is_rewrite() { - return is_initial_pending() && get_prior_instance(); - } - void on_initial_write() final { // All in-memory relative addrs are necessarily block-relative resolve_relative_addrs(get_paddr()); @@ -564,6 +597,10 @@ struct FixedKVInternalNode : FixedKVNode(rhs), node_layout_t(this->get_bptr().c_str()) {} + bool have_children() const final { + return true; + } + bool is_leaf_and_has_children() const final { return false; } @@ -977,6 +1014,10 @@ struct FixedKVLeafNode static constexpr bool do_has_children = has_children; + bool have_children() const final { + return do_has_children; + } + bool is_leaf_and_has_children() const final { return has_children; } diff --git a/src/crimson/os/seastore/cache.cc b/src/crimson/os/seastore/cache.cc index 801ba356fbe4f..56258df03d931 100644 --- a/src/crimson/os/seastore/cache.cc +++ b/src/crimson/os/seastore/cache.cc @@ -1538,6 +1538,7 @@ void Cache::complete_commit( i->on_initial_write(); i->state = CachedExtent::extent_state_t::CLEAN; + i->prior_instance.reset(); DEBUGT("add extent as fresh, inline={} -- {}", t, is_inline, *i); const auto t_src = t.get_src(); diff --git a/src/crimson/os/seastore/cached_extent.h b/src/crimson/os/seastore/cached_extent.h index 942be72323161..9643cbe6cc7db 100644 --- a/src/crimson/os/seastore/cached_extent.h +++ b/src/crimson/os/seastore/cached_extent.h @@ -325,6 +325,31 @@ public: return true; } + void rewrite(CachedExtent &e, extent_len_t o) { + assert(is_initial_pending()); + if (!e.is_pending()) { + prior_instance = &e; + } else { + assert(e.is_mutation_pending()); + prior_instance = e.get_prior_instance(); + } + e.get_bptr().copy_out( + o, + get_length(), + get_bptr().c_str()); + set_modify_time(e.get_modify_time()); + set_last_committed_crc(e.get_last_committed_crc()); + on_rewrite(e, o); + } + + /** + * on_rewrite + * + * Called when this extent is rewriting another one. + * + */ + virtual void on_rewrite(CachedExtent &, extent_len_t) = 0; + friend std::ostream &operator<<(std::ostream &, extent_state_t); virtual std::ostream &print_detail(std::ostream &out) const { return out; } std::ostream &print(std::ostream &out) const { @@ -419,6 +444,10 @@ public: return is_mutable() || state == extent_state_t::EXIST_CLEAN; } + bool is_rewrite() { + return is_initial_pending() && get_prior_instance(); + } + /// Returns true if extent is stable, written and shared among transactions bool is_stable_written() const { return state == extent_state_t::CLEAN_PENDING || @@ -797,6 +826,10 @@ protected: */ virtual void update_in_extent_chksum_field(uint32_t) {} + void set_prior_instance(CachedExtentRef p) { + prior_instance = p; + } + /// Sets last_committed_crc void set_last_committed_crc(uint32_t crc) { last_committed_crc = crc; @@ -1157,6 +1190,8 @@ public: return false; } + void on_rewrite(CachedExtent&, extent_len_t) final {} + std::ostream &print_detail(std::ostream &out) const final { return out << ", RetiredExtentPlaceholder"; } @@ -1242,6 +1277,12 @@ public: : ChildableCachedExtent(std::forward(t)...) {} + void on_rewrite(CachedExtent &extent, extent_len_t off) final { + assert(get_type() == extent.get_type()); + auto &lextent = (LogicalCachedExtent&)extent; + set_laddr(lextent.get_laddr() + off); + } + bool has_laddr() const { return laddr != L_ADDR_NULL; } diff --git a/src/crimson/os/seastore/root_block.h b/src/crimson/os/seastore/root_block.h index 0e45519ce4516..6d4da5756b8a1 100644 --- a/src/crimson/os/seastore/root_block.h +++ b/src/crimson/os/seastore/root_block.h @@ -50,6 +50,8 @@ struct RootBlock : CachedExtent { backref_root_node(nullptr) {} + void on_rewrite(CachedExtent&, extent_len_t) final {} + CachedExtentRef duplicate_for_write(Transaction&) final { return CachedExtentRef(new RootBlock(*this)); }; diff --git a/src/crimson/os/seastore/transaction_manager.cc b/src/crimson/os/seastore/transaction_manager.cc index ef8965a31afd6..087d0a5717e8e 100644 --- a/src/crimson/os/seastore/transaction_manager.cc +++ b/src/crimson/os/seastore/transaction_manager.cc @@ -495,12 +495,7 @@ TransactionManager::rewrite_logical_extent( lextent->get_user_hint(), // get target rewrite generation lextent->get_rewrite_generation())->cast(); - lextent->get_bptr().copy_out( - 0, - lextent->get_length(), - nlextent->get_bptr().c_str()); - nlextent->set_laddr(lextent->get_laddr()); - nlextent->set_modify_time(lextent->get_modify_time()); + nlextent->rewrite(*lextent, 0); DEBUGT("rewriting logical extent -- {} to {}", t, *lextent, *nlextent); @@ -541,13 +536,7 @@ TransactionManager::rewrite_logical_extent( bool first_extent = (off == 0); ceph_assert(left >= nextent->get_length()); auto nlextent = nextent->template cast(); - lextent->get_bptr().copy_out( - off, - nlextent->get_length(), - nlextent->get_bptr().c_str()); - nlextent->set_laddr(lextent->get_laddr() + off); - nlextent->set_modify_time(lextent->get_modify_time()); - nlextent->set_last_committed_crc(lextent->get_last_committed_crc()); + nlextent->rewrite(*lextent, off); DEBUGT("rewriting logical extent -- {} to {}", t, *lextent, *nlextent); /* This update_mapping is, strictly speaking, unnecessary for delayed_alloc diff --git a/src/test/crimson/seastore/test_block.h b/src/test/crimson/seastore/test_block.h index 7073b8a190463..76891076f3360 100644 --- a/src/test/crimson/seastore/test_block.h +++ b/src/test/crimson/seastore/test_block.h @@ -111,6 +111,8 @@ struct TestBlockPhysical : crimson::os::seastore::CachedExtent{ std::vector delta = {}; + void on_rewrite(CachedExtent&, extent_len_t) final {} + TestBlockPhysical(ceph::bufferptr &&ptr) : CachedExtent(std::move(ptr)) {} TestBlockPhysical(const TestBlockPhysical &other)