]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/os/seastore: make laddr_t block aligned
authorZhang Song <zhangsong02@qianxin.com>
Fri, 23 Aug 2024 09:37:58 +0000 (17:37 +0800)
committerZhang Song <zhangsong02@qianxin.com>
Fri, 23 Aug 2024 11:19:38 +0000 (19:19 +0800)
Signed-off-by: Zhang Song <zhangsong02@qianxin.com>
src/crimson/os/seastore/seastore_types.cc
src/crimson/os/seastore/seastore_types.h

index 2f480482660a14a51a2fb2a986aec24454a8ee23..66688b939c5c9e1ff4a37e998e290899ecc385fd 100644 (file)
@@ -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()) {
index 8f3ec38537f2475af8423968bd3af3ec057106b6..4f511540c2af3a2eb43ad0c5368ef3d430a2d703 100644 (file)
@@ -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<extent_len_t>::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<Unsigned>::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<std::unsigned_integral U>
+    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<U>::max() >> UNIT_SHIFT));
+       return (static_cast<U>(udiff) << UNIT_SHIFT) + offset;
+      } else { // base < l.value
+       Unsigned udiff = l.value - base;
+       assert(udiff <= (std::numeric_limits<U>::max() >> UNIT_SHIFT));
+       return (static_cast<U>(udiff) << UNIT_SHIFT) - offset;
+      }
+    }
+
+    template<std::unsigned_integral U>
+    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<U>::max() >> UNIT_SHIFT));
+       return ((static_cast<U>(udiff) << UNIT_SHIFT) + offset) - l.offset;
+      } else { // *this < l
+       Unsigned udiff = l.base - base;
+       assert(udiff <= (std::numeric_limits<U>::max() >> UNIT_SHIFT));
+       return ((static_cast<U>(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<std::unsigned_integral U>
+  U get_byte_distance(const laddr_offset_t &l) const {
+    if (value <= l.base) {
+      Unsigned udiff = l.base - value;
+      assert(udiff <= (std::numeric_limits<U>::max() >> UNIT_SHIFT));
+      return (static_cast<U>(udiff) << UNIT_SHIFT) + l.offset;
+    } else { // value > l.base
+      Unsigned udiff = value - l.base;
+      assert(udiff <= (std::numeric_limits<U>::max() >> UNIT_SHIFT));
+      return (static_cast<U>(udiff) << UNIT_SHIFT) - l.offset;
+    }
   }
 
-  friend laddr_t operator+(const Unsigned &i, const laddr_t &laddr) {
-    return laddr_t{laddr.value + i};
+  template<std::unsigned_integral U>
+  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<U>::max() >> UNIT_SHIFT));
+    return static_cast<U>(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<paddr_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<extent_len_t>::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<crimson::os::seastore::extent_types_t> : fmt::
 template <> struct fmt::formatter<crimson::os::seastore::journal_seq_t> : fmt::ostream_formatter {};
 template <> struct fmt::formatter<crimson::os::seastore::journal_tail_delta_t> : fmt::ostream_formatter {};
 template <> struct fmt::formatter<crimson::os::seastore::laddr_t> : fmt::ostream_formatter {};
+template <> struct fmt::formatter<crimson::os::seastore::laddr_offset_t> : fmt::ostream_formatter {};
 template <> struct fmt::formatter<crimson::os::seastore::laddr_list_t> : fmt::ostream_formatter {};
 template <> struct fmt::formatter<crimson::os::seastore::omap_root_t> : fmt::ostream_formatter {};
 template <> struct fmt::formatter<crimson::os::seastore::paddr_list_t> : fmt::ostream_formatter {};