From 44365c4b93ed0ccc02d7674e52bd92cb2d5f571d Mon Sep 17 00:00:00 2001 From: Xinyu Huang Date: Tue, 21 Feb 2023 06:18:29 +0000 Subject: [PATCH] crimson/os/seastore: let CachedExtent::ptr optional separate buffer length and data length, since no buffer extent is allowed Signed-off-by: Xinyu Huang (cherry picked from commit 7cb44d350b68002123c3c2f97a888cc42260f522) --- src/crimson/os/seastore/cached_extent.h | 91 +++++++++++++++++++------ src/crimson/os/seastore/root_block.h | 2 +- 2 files changed, 71 insertions(+), 22 deletions(-) diff --git a/src/crimson/os/seastore/cached_extent.h b/src/crimson/os/seastore/cached_extent.h index 464f34d79fdc7..3590a31128b89 100644 --- a/src/crimson/os/seastore/cached_extent.h +++ b/src/crimson/os/seastore/cached_extent.h @@ -473,6 +473,12 @@ public: return dirty_from_or_retired_at; } + /// Return true if extent is fully loaded or is about to be fully loaded (call + /// wait_io() in this case) + bool is_fully_loaded() const { + return ptr.has_value(); + } + /** * get_paddr * @@ -481,8 +487,18 @@ public: */ paddr_t get_paddr() const { return poffset; } - /// Returns length of extent - virtual extent_len_t get_length() const { return ptr.length(); } + /// Returns length of extent data in disk + extent_len_t get_length() const { + return length; + } + + extent_len_t get_loaded_length() const { + if (ptr.has_value()) { + return ptr->length(); + } else { + return 0; + } + } /// Returns version, get_version() == 0 iff is_clean() extent_version_t get_version() const { @@ -498,8 +514,14 @@ public: } /// Get ref to raw buffer - bufferptr &get_bptr() { return ptr; } - const bufferptr &get_bptr() const { return ptr; } + bufferptr &get_bptr() { + assert(ptr.has_value()); + return *ptr; + } + const bufferptr &get_bptr() const { + assert(ptr.has_value()); + return *ptr; + } /// Compare by paddr friend bool operator< (const CachedExtent &a, const CachedExtent &b) { @@ -602,8 +624,11 @@ private: */ journal_seq_t dirty_from_or_retired_at; - /// Actual data contents - ceph::bufferptr ptr; + /// cache data contents, std::nullopt if no data in cache + std::optional ptr; + + /// disk data length + extent_len_t length; /// number of deltas since initial write extent_version_t version = 0; @@ -649,24 +674,52 @@ protected: trans_view_set_t mutation_pendings; CachedExtent(CachedExtent &&other) = delete; - CachedExtent(ceph::bufferptr &&ptr) : ptr(std::move(ptr)) {} + CachedExtent(ceph::bufferptr &&_ptr) : ptr(std::move(_ptr)) { + length = ptr->length(); + assert(length > 0); + } + + /// construct new CachedExtent, will deep copy the buffer CachedExtent(const CachedExtent &other) : state(other.state), dirty_from_or_retired_at(other.dirty_from_or_retired_at), - ptr(other.ptr.c_str(), other.ptr.length()), + length(other.get_length()), version(other.version), - poffset(other.poffset) {} + poffset(other.poffset) { + if (other.is_fully_loaded()) { + ptr = std::make_optional + (other.ptr->c_str(), other.ptr->length()); + } else { + // the extent must be fully loaded before CoW + assert(length == 0); // in case of root + } + } struct share_buffer_t {}; - CachedExtent(const CachedExtent &other, share_buffer_t) : - state(other.state), - dirty_from_or_retired_at(other.dirty_from_or_retired_at), - ptr(other.ptr), - version(other.version), - poffset(other.poffset) {} + /// construct new CachedExtent, will shallow copy the buffer + CachedExtent(const CachedExtent &other, share_buffer_t) + : state(other.state), + dirty_from_or_retired_at(other.dirty_from_or_retired_at), + ptr(other.ptr), + length(other.get_length()), + version(other.version), + poffset(other.poffset) {} + + // 0 length is only possible for the RootBlock + struct zero_length_t {}; + CachedExtent(zero_length_t) : ptr(ceph::bufferptr(0)), length(0) {}; struct retired_placeholder_t{}; - CachedExtent(retired_placeholder_t) : state(extent_state_t::INVALID) {} + CachedExtent(retired_placeholder_t, extent_len_t _length) + : state(extent_state_t::INVALID), + length(_length) { + assert(length > 0); + } + + /// no buffer extent, for lazy read + CachedExtent(extent_len_t _length) : length(_length) { + assert(length > 0); + } friend class Cache; template @@ -978,14 +1031,10 @@ using backref_pin_list_t = std::list; * the Cache interface boundary. */ class RetiredExtentPlaceholder : public CachedExtent { - extent_len_t length; public: RetiredExtentPlaceholder(extent_len_t length) - : CachedExtent(CachedExtent::retired_placeholder_t{}), - length(length) {} - - extent_len_t get_length() const final { return length; } + : CachedExtent(CachedExtent::retired_placeholder_t{}, length) {} CachedExtentRef duplicate_for_write(Transaction&) final { ceph_assert(0 == "Should never happen for a placeholder"); diff --git a/src/crimson/os/seastore/root_block.h b/src/crimson/os/seastore/root_block.h index bf3dfb5426568..0e45519ce4516 100644 --- a/src/crimson/os/seastore/root_block.h +++ b/src/crimson/os/seastore/root_block.h @@ -41,7 +41,7 @@ struct RootBlock : CachedExtent { CachedExtent* lba_root_node = nullptr; CachedExtent* backref_root_node = nullptr; - RootBlock() : CachedExtent(0) {} + RootBlock() : CachedExtent(zero_length_t()) {}; RootBlock(const RootBlock &rhs) : CachedExtent(rhs), -- 2.39.5