From: Zhang Song Date: Fri, 23 Aug 2024 09:37:58 +0000 (+0800) Subject: crimson/os/seastore: make laddr_t block aligned X-Git-Tag: v20.0.0~1167^2~7 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=f2fc9e75e5692de191c2264556612ac62f16f87f;p=ceph.git crimson/os/seastore: make laddr_t block aligned Signed-off-by: Zhang Song --- diff --git a/src/crimson/os/seastore/seastore_types.cc b/src/crimson/os/seastore/seastore_types.cc index 2f480482660..66688b939c5 100644 --- a/src/crimson/os/seastore/seastore_types.cc +++ b/src/crimson/os/seastore/seastore_types.cc @@ -96,6 +96,11 @@ std::ostream &operator<<(std::ostream &out, const laddr_t &laddr) { return out << 'L' << std::hex << laddr.value << std::dec; } +std::ostream &operator<<(std::ostream &out, const laddr_offset_t &laddr_offset) { + return out << laddr_offset.get_aligned_laddr() + << "+" << std::hex << laddr_offset.get_offset() << std::dec; +} + std::ostream &operator<<(std::ostream &out, const pladdr_t &pladdr) { if (pladdr.is_laddr()) { diff --git a/src/crimson/os/seastore/seastore_types.h b/src/crimson/os/seastore/seastore_types.h index 8f3ec38537f..4f511540c2a 100644 --- a/src/crimson/os/seastore/seastore_types.h +++ b/src/crimson/os/seastore/seastore_types.h @@ -1006,6 +1006,19 @@ constexpr journal_seq_t JOURNAL_SEQ_MAX{ // JOURNAL_SEQ_NULL == JOURNAL_SEQ_MAX == journal_seq_t{} constexpr journal_seq_t JOURNAL_SEQ_NULL = JOURNAL_SEQ_MAX; +// logical offset between two laddr_t +using loffset_t = uint64_t; + +// logical offset within an extent +using extent_len_t = uint32_t; +constexpr extent_len_t EXTENT_LEN_MAX = + std::numeric_limits::max(); + +using extent_len_le_t = ceph_le32; +inline extent_len_le_t init_extent_len_le(extent_len_t len) { + return ceph_le32(len); +} + // logical addr, see LBAManager, TransactionManager class laddr_t { public: @@ -1015,24 +1028,19 @@ public: std::numeric_limits::max(); constexpr laddr_t() : laddr_t(RAW_VALUE_MAX) {} - constexpr explicit laddr_t(Unsigned value) : value(value) {} - bool is_aligned(Unsigned alignment) const { - assert(alignment != 0); - assert((alignment & (alignment - 1)) == 0); - return value == p2align(value, alignment); - } + // laddr_t is block aligned, one logical address represents one 4KiB block in disk + static constexpr unsigned UNIT_SHIFT = 12; + static constexpr unsigned UNIT_SIZE = 1 << UNIT_SHIFT; // 4096 + static constexpr unsigned UNIT_MASK = UNIT_SIZE - 1; - laddr_t get_aligned_laddr(Unsigned alignment) const { - assert(alignment != 0); - assert((alignment & (alignment - 1)) == 0); - return laddr_t(p2align(value, alignment)); + static laddr_t from_byte_offset(Unsigned value) { + assert((value & UNIT_MASK) == 0); + return laddr_t(value >> UNIT_SHIFT); } - laddr_t get_roundup_laddr(Unsigned alignment) const { - assert(alignment != 0); - assert((alignment & (alignment - 1)) == 0); - return laddr_t(p2roundup(value, alignment)); + static constexpr laddr_t from_raw_uint(Unsigned v) { + return laddr_t(v); } /// laddr_t works like primitive integer type, encode/decode it manually @@ -1047,38 +1055,178 @@ public: memcpy((char *)&value, p.get_pos_add(sizeof(Unsigned)), sizeof(Unsigned)); } - friend std::ostream &operator<<(std::ostream &, const laddr_t &); + // laddr_offset_t contains one base laddr and one block not aligned + // offset(< laddr_t::UNIT_SIZE). It is the return type of plus/minus + // overloads for laddr_t and loffset_t. + struct laddr_offset_t { + explicit laddr_offset_t(laddr_t base) + : base(base.value), offset(0) {} + laddr_offset_t(laddr_t base, extent_len_t offset) + : base(base.value), offset(offset) { + assert(offset < laddr_t::UNIT_SIZE); + } - friend auto operator<=>(const laddr_t&, const laddr_t&) = default; + laddr_t get_roundup_laddr() const { + if (offset == 0) { + return laddr_t(base); + } else { + assert(offset < laddr_t::UNIT_SIZE); + return laddr_t(base + 1); + } + } + laddr_t get_aligned_laddr() const { return laddr_t(base); } + extent_len_t get_offset() const { + assert(offset < laddr_t::UNIT_SIZE); + return offset; + } + laddr_t checked_to_laddr() const { + assert(offset == 0); + return laddr_t(base); + } + + template + U get_byte_distance(const laddr_t &l) const { + assert(offset < UNIT_SIZE); + if (base >= l.value) { + Unsigned udiff = base - l.value; + assert(udiff <= (std::numeric_limits::max() >> UNIT_SHIFT)); + return (static_cast(udiff) << UNIT_SHIFT) + offset; + } else { // base < l.value + Unsigned udiff = l.value - base; + assert(udiff <= (std::numeric_limits::max() >> UNIT_SHIFT)); + return (static_cast(udiff) << UNIT_SHIFT) - offset; + } + } + + template + U get_byte_distance(const laddr_offset_t &l) const { + assert(offset < UNIT_SIZE); + if (*this >= l) { + Unsigned udiff = base - l.base; + assert(udiff <= (std::numeric_limits::max() >> UNIT_SHIFT)); + return ((static_cast(udiff) << UNIT_SHIFT) + offset) - l.offset; + } else { // *this < l + Unsigned udiff = l.base - base; + assert(udiff <= (std::numeric_limits::max() >> UNIT_SHIFT)); + return ((static_cast(udiff) << UNIT_SHIFT) + l.offset) - offset; + } + } + + friend bool operator==(const laddr_offset_t&, const laddr_offset_t&) = default; + friend auto operator<=>(const laddr_offset_t&, const laddr_offset_t&) = default; + friend std::ostream &operator<<(std::ostream&, const laddr_offset_t&); + friend laddr_offset_t operator+(const laddr_offset_t &laddr_offset, + const loffset_t &offset) { + // laddr_offset_t could access (laddr_t + loffset_t) overload. + return laddr_offset.get_aligned_laddr() + + (laddr_offset.get_offset() + offset); + } + friend laddr_offset_t operator+(const loffset_t &offset, + const laddr_offset_t &loffset) { + return loffset + offset; + } + + friend laddr_offset_t operator-(const laddr_offset_t &laddr_offset, + const loffset_t &offset) { + if (laddr_offset.get_offset() >= offset) { + return laddr_offset_t( + laddr_offset.get_aligned_laddr(), + laddr_offset.get_offset() - offset); + } else { + // laddr_offset_t could access (laddr_t - loffset_t) overload. + return laddr_offset.get_aligned_laddr() + - (offset - laddr_offset.get_offset()); + } + } + + friend class laddr_t; + private: + // use Unsigned here to avoid incomplete type of laddr_t + Unsigned base; + extent_len_t offset; + }; - friend laddr_t operator+(const laddr_t &laddr, const Unsigned &i) { - return laddr_t{laddr.value + i}; + template + U get_byte_distance(const laddr_offset_t &l) const { + if (value <= l.base) { + Unsigned udiff = l.base - value; + assert(udiff <= (std::numeric_limits::max() >> UNIT_SHIFT)); + return (static_cast(udiff) << UNIT_SHIFT) + l.offset; + } else { // value > l.base + Unsigned udiff = value - l.base; + assert(udiff <= (std::numeric_limits::max() >> UNIT_SHIFT)); + return (static_cast(udiff) << UNIT_SHIFT) - l.offset; + } } - friend laddr_t operator+(const Unsigned &i, const laddr_t &laddr) { - return laddr_t{laddr.value + i}; + template + U get_byte_distance(const laddr_t &l) const { + Unsigned diff = value > l.value + ? value - l.value + : l.value - value; + assert(diff <= (std::numeric_limits::max() >> UNIT_SHIFT)); + return static_cast(diff) << UNIT_SHIFT; } - friend laddr_t operator-(const laddr_t &laddr, const Unsigned &i) { - return laddr_t{laddr.value - i}; + friend std::ostream &operator<<(std::ostream &, const laddr_t &); + friend bool operator==(const laddr_t&, const laddr_t&) = default; + friend bool operator==(const laddr_t &laddr, + const laddr_offset_t &laddr_offset) { + return laddr == laddr_offset.get_aligned_laddr() + && 0 == laddr_offset.get_offset(); + } + friend bool operator==(const laddr_offset_t &laddr_offset, + const laddr_t &laddr) { + return laddr_offset.get_aligned_laddr() == laddr + && laddr_offset.get_offset() == 0; + } + friend auto operator<=>(const laddr_t&, const laddr_t&) = default; + friend auto operator<=>(const laddr_t &laddr, + const laddr_offset_t &laddr_offset) { + return laddr_offset_t(laddr, 0) <=> laddr_offset; + } + friend auto operator<=>(const laddr_offset_t &laddr_offset, + const laddr_t &laddr) { + return laddr_offset <=> laddr_offset_t(laddr, 0); } - friend Unsigned operator-(const laddr_t &l, const laddr_t &r) { - return l.value - r.value; + friend laddr_offset_t operator+(const laddr_t &laddr, + const loffset_t &offset) { + auto base = laddr; + base.value += offset >> laddr_t::UNIT_SHIFT; + assert(base.value >= laddr.value); + return laddr_offset_t(base, offset & laddr_t::UNIT_MASK); + } + friend laddr_offset_t operator+(const loffset_t &offset, + const laddr_t &laddr) { + return laddr + offset; + } + + friend laddr_offset_t operator-(const laddr_t &laddr, loffset_t offset) { + auto base = laddr; + auto diff = (offset + laddr_t::UNIT_SIZE - 1) >> laddr_t::UNIT_SHIFT; + base.value -= diff; + assert(base.value <= laddr.value); + offset = (diff << laddr_t::UNIT_SHIFT) - offset; + return laddr_offset_t(base, offset); } friend struct laddr_le_t; friend struct pladdr_le_t; private: + // Prevent direct construction of laddr_t with an integer, + // always use laddr_t::from_raw_uint instead. + constexpr explicit laddr_t(Unsigned value) : value(value) {} Unsigned value; }; +using laddr_offset_t = laddr_t::laddr_offset_t; -constexpr laddr_t L_ADDR_MAX = laddr_t(laddr_t::RAW_VALUE_MAX); -constexpr laddr_t L_ADDR_MIN = laddr_t(0); +constexpr laddr_t L_ADDR_MAX = laddr_t::from_raw_uint(laddr_t::RAW_VALUE_MAX); +constexpr laddr_t L_ADDR_MIN = laddr_t::from_raw_uint(0); constexpr laddr_t L_ADDR_NULL = L_ADDR_MAX; -constexpr laddr_t L_ADDR_ROOT = laddr_t(laddr_t::RAW_VALUE_MAX - 1); -constexpr laddr_t L_ADDR_LBAT = laddr_t(laddr_t::RAW_VALUE_MAX - 2); +constexpr laddr_t L_ADDR_ROOT = laddr_t::from_raw_uint(laddr_t::RAW_VALUE_MAX - 1); +constexpr laddr_t L_ADDR_LBAT = laddr_t::from_raw_uint(laddr_t::RAW_VALUE_MAX - 2); struct __attribute__((packed)) laddr_le_t { ceph_le64 laddr; @@ -1200,16 +1348,6 @@ struct min_max_t { static constexpr paddr_t null = P_ADDR_NULL; }; -// logical offset, see LBAManager, TransactionManager -using extent_len_t = uint32_t; -constexpr extent_len_t EXTENT_LEN_MAX = - std::numeric_limits::max(); - -using extent_len_le_t = ceph_le32; -inline extent_len_le_t init_extent_len_le(extent_len_t len) { - return ceph_le32(len); -} - using extent_ref_count_t = uint32_t; constexpr extent_ref_count_t EXTENT_DEFAULT_REF_COUNT = 1; @@ -2749,6 +2887,7 @@ template <> struct fmt::formatter : fmt:: template <> struct fmt::formatter : fmt::ostream_formatter {}; template <> struct fmt::formatter : fmt::ostream_formatter {}; template <> struct fmt::formatter : fmt::ostream_formatter {}; +template <> struct fmt::formatter : fmt::ostream_formatter {}; template <> struct fmt::formatter : fmt::ostream_formatter {}; template <> struct fmt::formatter : fmt::ostream_formatter {}; template <> struct fmt::formatter : fmt::ostream_formatter {};