@@ -1006,6 +1006,19 @@ constexpr journal_seq_t JOURNAL_SEQ_MAX{
10061006// JOURNAL_SEQ_NULL == JOURNAL_SEQ_MAX == journal_seq_t{}
10071007constexpr journal_seq_t JOURNAL_SEQ_NULL = JOURNAL_SEQ_MAX;
10081008
1009+ // logical offset between two laddr_t
1010+ using loffset_t = uint64_t ;
1011+
1012+ // logical offset within an extent
1013+ using extent_len_t = uint32_t ;
1014+ constexpr extent_len_t EXTENT_LEN_MAX =
1015+ std::numeric_limits<extent_len_t >::max();
1016+
1017+ using extent_len_le_t = ceph_le32;
1018+ inline extent_len_le_t init_extent_len_le (extent_len_t len) {
1019+ return ceph_le32 (len);
1020+ }
1021+
10091022// logical addr, see LBAManager, TransactionManager
10101023class laddr_t {
10111024public:
@@ -1015,24 +1028,19 @@ class laddr_t {
10151028 std::numeric_limits<Unsigned>::max();
10161029
10171030 constexpr laddr_t () : laddr_t(RAW_VALUE_MAX) {}
1018- constexpr explicit laddr_t (Unsigned value) : value(value) {}
10191031
1020- bool is_aligned (Unsigned alignment) const {
1021- assert (alignment != 0 );
1022- assert ((alignment & (alignment - 1 )) == 0 );
1023- return value == p2align (value, alignment);
1024- }
1032+ // laddr_t is block aligned, one logical address represents one 4KiB block in disk
1033+ static constexpr unsigned UNIT_SHIFT = 12 ;
1034+ static constexpr unsigned UNIT_SIZE = 1 << UNIT_SHIFT; // 4096
1035+ static constexpr unsigned UNIT_MASK = UNIT_SIZE - 1 ;
10251036
1026- laddr_t get_aligned_laddr (Unsigned alignment) const {
1027- assert (alignment != 0 );
1028- assert ((alignment & (alignment - 1 )) == 0 );
1029- return laddr_t (p2align (value, alignment));
1037+ static laddr_t from_byte_offset (Unsigned value) {
1038+ assert ((value & UNIT_MASK) == 0 );
1039+ return laddr_t (value >> UNIT_SHIFT);
10301040 }
10311041
1032- laddr_t get_roundup_laddr (Unsigned alignment) const {
1033- assert (alignment != 0 );
1034- assert ((alignment & (alignment - 1 )) == 0 );
1035- return laddr_t (p2roundup (value, alignment));
1042+ static constexpr laddr_t from_raw_uint (Unsigned v) {
1043+ return laddr_t (v);
10361044 }
10371045
10381046 // / laddr_t works like primitive integer type, encode/decode it manually
@@ -1047,38 +1055,178 @@ class laddr_t {
10471055 memcpy ((char *)&value, p.get_pos_add (sizeof (Unsigned)), sizeof (Unsigned));
10481056 }
10491057
1050- friend std::ostream &operator <<(std::ostream &, const laddr_t &);
1058+ // laddr_offset_t contains one base laddr and one block not aligned
1059+ // offset(< laddr_t::UNIT_SIZE). It is the return type of plus/minus
1060+ // overloads for laddr_t and loffset_t.
1061+ struct laddr_offset_t {
1062+ explicit laddr_offset_t (laddr_t base)
1063+ : base(base.value), offset(0 ) {}
1064+ laddr_offset_t (laddr_t base, extent_len_t offset)
1065+ : base(base.value), offset(offset) {
1066+ assert (offset < laddr_t ::UNIT_SIZE);
1067+ }
10511068
1052- friend auto operator <=>(const laddr_t &, const laddr_t &) = default ;
1069+ laddr_t get_roundup_laddr () const {
1070+ if (offset == 0 ) {
1071+ return laddr_t (base);
1072+ } else {
1073+ assert (offset < laddr_t ::UNIT_SIZE);
1074+ return laddr_t (base + 1 );
1075+ }
1076+ }
1077+ laddr_t get_aligned_laddr () const { return laddr_t (base); }
1078+ extent_len_t get_offset () const {
1079+ assert (offset < laddr_t ::UNIT_SIZE);
1080+ return offset;
1081+ }
1082+ laddr_t checked_to_laddr () const {
1083+ assert (offset == 0 );
1084+ return laddr_t (base);
1085+ }
1086+
1087+ template <std::unsigned_integral U>
1088+ U get_byte_distance (const laddr_t &l) const {
1089+ assert (offset < UNIT_SIZE);
1090+ if (base >= l.value ) {
1091+ Unsigned udiff = base - l.value ;
1092+ assert (udiff <= (std::numeric_limits<U>::max () >> UNIT_SHIFT));
1093+ return (static_cast <U>(udiff) << UNIT_SHIFT) + offset;
1094+ } else { // base < l.value
1095+ Unsigned udiff = l.value - base;
1096+ assert (udiff <= (std::numeric_limits<U>::max () >> UNIT_SHIFT));
1097+ return (static_cast <U>(udiff) << UNIT_SHIFT) - offset;
1098+ }
1099+ }
1100+
1101+ template <std::unsigned_integral U>
1102+ U get_byte_distance (const laddr_offset_t &l) const {
1103+ assert (offset < UNIT_SIZE);
1104+ if (*this >= l) {
1105+ Unsigned udiff = base - l.base ;
1106+ assert (udiff <= (std::numeric_limits<U>::max () >> UNIT_SHIFT));
1107+ return ((static_cast <U>(udiff) << UNIT_SHIFT) + offset) - l.offset ;
1108+ } else { // *this < l
1109+ Unsigned udiff = l.base - base;
1110+ assert (udiff <= (std::numeric_limits<U>::max () >> UNIT_SHIFT));
1111+ return ((static_cast <U>(udiff) << UNIT_SHIFT) + l.offset ) - offset;
1112+ }
1113+ }
1114+
1115+ friend bool operator ==(const laddr_offset_t &, const laddr_offset_t &) = default ;
1116+ friend auto operator <=>(const laddr_offset_t &, const laddr_offset_t &) = default ;
1117+ friend std::ostream &operator <<(std::ostream&, const laddr_offset_t &);
1118+ friend laddr_offset_t operator +(const laddr_offset_t &laddr_offset,
1119+ const loffset_t &offset) {
1120+ // laddr_offset_t could access (laddr_t + loffset_t) overload.
1121+ return laddr_offset.get_aligned_laddr ()
1122+ + (laddr_offset.get_offset () + offset);
1123+ }
1124+ friend laddr_offset_t operator +(const loffset_t &offset,
1125+ const laddr_offset_t &loffset) {
1126+ return loffset + offset;
1127+ }
1128+
1129+ friend laddr_offset_t operator -(const laddr_offset_t &laddr_offset,
1130+ const loffset_t &offset) {
1131+ if (laddr_offset.get_offset () >= offset) {
1132+ return laddr_offset_t (
1133+ laddr_offset.get_aligned_laddr (),
1134+ laddr_offset.get_offset () - offset);
1135+ } else {
1136+ // laddr_offset_t could access (laddr_t - loffset_t) overload.
1137+ return laddr_offset.get_aligned_laddr ()
1138+ - (offset - laddr_offset.get_offset ());
1139+ }
1140+ }
1141+
1142+ friend class laddr_t ;
1143+ private:
1144+ // use Unsigned here to avoid incomplete type of laddr_t
1145+ Unsigned base;
1146+ extent_len_t offset;
1147+ };
10531148
1054- friend laddr_t operator +(const laddr_t &laddr, const Unsigned &i) {
1055- return laddr_t {laddr.value + i};
1149+ template <std::unsigned_integral U>
1150+ U get_byte_distance (const laddr_offset_t &l) const {
1151+ if (value <= l.base ) {
1152+ Unsigned udiff = l.base - value;
1153+ assert (udiff <= (std::numeric_limits<U>::max () >> UNIT_SHIFT));
1154+ return (static_cast <U>(udiff) << UNIT_SHIFT) + l.offset ;
1155+ } else { // value > l.base
1156+ Unsigned udiff = value - l.base ;
1157+ assert (udiff <= (std::numeric_limits<U>::max () >> UNIT_SHIFT));
1158+ return (static_cast <U>(udiff) << UNIT_SHIFT) - l.offset ;
1159+ }
10561160 }
10571161
1058- friend laddr_t operator +(const Unsigned &i, const laddr_t &laddr) {
1059- return laddr_t {laddr.value + i};
1162+ template <std::unsigned_integral U>
1163+ U get_byte_distance (const laddr_t &l) const {
1164+ Unsigned diff = value > l.value
1165+ ? value - l.value
1166+ : l.value - value;
1167+ assert (diff <= (std::numeric_limits<U>::max () >> UNIT_SHIFT));
1168+ return static_cast <U>(diff) << UNIT_SHIFT;
10601169 }
10611170
1062- friend laddr_t operator -(const laddr_t &laddr, const Unsigned &i) {
1063- return laddr_t {laddr.value - i};
1171+ friend std::ostream &operator <<(std::ostream &, const laddr_t &);
1172+ friend bool operator ==(const laddr_t &, const laddr_t &) = default ;
1173+ friend bool operator ==(const laddr_t &laddr,
1174+ const laddr_offset_t &laddr_offset) {
1175+ return laddr == laddr_offset.get_aligned_laddr ()
1176+ && 0 == laddr_offset.get_offset ();
1177+ }
1178+ friend bool operator ==(const laddr_offset_t &laddr_offset,
1179+ const laddr_t &laddr) {
1180+ return laddr_offset.get_aligned_laddr () == laddr
1181+ && laddr_offset.get_offset () == 0 ;
1182+ }
1183+ friend auto operator <=>(const laddr_t &, const laddr_t &) = default ;
1184+ friend auto operator <=>(const laddr_t &laddr,
1185+ const laddr_offset_t &laddr_offset) {
1186+ return laddr_offset_t (laddr, 0 ) <=> laddr_offset;
1187+ }
1188+ friend auto operator <=>(const laddr_offset_t &laddr_offset,
1189+ const laddr_t &laddr) {
1190+ return laddr_offset <=> laddr_offset_t (laddr, 0 );
10641191 }
10651192
1066- friend Unsigned operator -(const laddr_t &l, const laddr_t &r) {
1067- return l.value - r.value ;
1193+ friend laddr_offset_t operator +(const laddr_t &laddr,
1194+ const loffset_t &offset) {
1195+ auto base = laddr;
1196+ base.value += offset >> laddr_t ::UNIT_SHIFT;
1197+ assert (base.value >= laddr.value );
1198+ return laddr_offset_t (base, offset & laddr_t ::UNIT_MASK);
1199+ }
1200+ friend laddr_offset_t operator +(const loffset_t &offset,
1201+ const laddr_t &laddr) {
1202+ return laddr + offset;
1203+ }
1204+
1205+ friend laddr_offset_t operator -(const laddr_t &laddr, loffset_t offset) {
1206+ auto base = laddr;
1207+ auto diff = (offset + laddr_t ::UNIT_SIZE - 1 ) >> laddr_t ::UNIT_SHIFT;
1208+ base.value -= diff;
1209+ assert (base.value <= laddr.value );
1210+ offset = (diff << laddr_t ::UNIT_SHIFT) - offset;
1211+ return laddr_offset_t (base, offset);
10681212 }
10691213
10701214 friend struct laddr_le_t ;
10711215 friend struct pladdr_le_t ;
10721216
10731217private:
1218+ // Prevent direct construction of laddr_t with an integer,
1219+ // always use laddr_t::from_raw_uint instead.
1220+ constexpr explicit laddr_t (Unsigned value) : value(value) {}
10741221 Unsigned value;
10751222};
1223+ using laddr_offset_t = laddr_t ::laddr_offset_t ;
10761224
1077- constexpr laddr_t L_ADDR_MAX = laddr_t (laddr_t ::RAW_VALUE_MAX);
1078- constexpr laddr_t L_ADDR_MIN = laddr_t (0 );
1225+ constexpr laddr_t L_ADDR_MAX = laddr_t ::from_raw_uint (laddr_t ::RAW_VALUE_MAX);
1226+ constexpr laddr_t L_ADDR_MIN = laddr_t ::from_raw_uint (0 );
10791227constexpr laddr_t L_ADDR_NULL = L_ADDR_MAX;
1080- constexpr laddr_t L_ADDR_ROOT = laddr_t (laddr_t ::RAW_VALUE_MAX - 1 );
1081- constexpr laddr_t L_ADDR_LBAT = laddr_t (laddr_t ::RAW_VALUE_MAX - 2 );
1228+ constexpr laddr_t L_ADDR_ROOT = laddr_t ::from_raw_uint (laddr_t ::RAW_VALUE_MAX - 1 );
1229+ constexpr laddr_t L_ADDR_LBAT = laddr_t ::from_raw_uint (laddr_t ::RAW_VALUE_MAX - 2 );
10821230
10831231struct __attribute__ ((packed)) laddr_le_t {
10841232 ceph_le64 laddr;
@@ -1200,16 +1348,6 @@ struct min_max_t<paddr_t> {
12001348 static constexpr paddr_t null = P_ADDR_NULL;
12011349};
12021350
1203- // logical offset, see LBAManager, TransactionManager
1204- using extent_len_t = uint32_t ;
1205- constexpr extent_len_t EXTENT_LEN_MAX =
1206- std::numeric_limits<extent_len_t >::max();
1207-
1208- using extent_len_le_t = ceph_le32;
1209- inline extent_len_le_t init_extent_len_le (extent_len_t len) {
1210- return ceph_le32 (len);
1211- }
1212-
12131351using extent_ref_count_t = uint32_t ;
12141352constexpr extent_ref_count_t EXTENT_DEFAULT_REF_COUNT = 1 ;
12151353
@@ -2749,6 +2887,7 @@ template <> struct fmt::formatter<crimson::os::seastore::extent_types_t> : fmt::
27492887template <> struct fmt ::formatter<crimson::os::seastore::journal_seq_t > : fmt::ostream_formatter {};
27502888template <> struct fmt ::formatter<crimson::os::seastore::journal_tail_delta_t > : fmt::ostream_formatter {};
27512889template <> struct fmt ::formatter<crimson::os::seastore::laddr_t > : fmt::ostream_formatter {};
2890+ template <> struct fmt ::formatter<crimson::os::seastore::laddr_offset_t > : fmt::ostream_formatter {};
27522891template <> struct fmt ::formatter<crimson::os::seastore::laddr_list_t > : fmt::ostream_formatter {};
27532892template <> struct fmt ::formatter<crimson::os::seastore::omap_root_t > : fmt::ostream_formatter {};
27542893template <> struct fmt ::formatter<crimson::os::seastore::paddr_list_t > : fmt::ostream_formatter {};
0 commit comments