]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #pragma once | |
5 | ||
6 | #include <limits> | |
7 | #include <iostream> | |
8 | ||
9 | #include "include/byteorder.h" | |
10 | #include "include/denc.h" | |
11 | #include "include/buffer.h" | |
12 | #include "include/cmp.h" | |
13 | #include "include/uuid.h" | |
14 | ||
15 | namespace crimson::os::seastore { | |
16 | ||
17 | using depth_t = int32_t; | |
18 | using depth_le_t = ceph_les32; | |
19 | ||
20 | using checksum_t = uint32_t; | |
21 | ||
22 | // Immutable metadata for seastore to set at mkfs time | |
23 | struct seastore_meta_t { | |
24 | uuid_d seastore_id; | |
25 | ||
26 | DENC(seastore_meta_t, v, p) { | |
27 | DENC_START(1, 1, p); | |
28 | denc(v.seastore_id, p); | |
29 | DENC_FINISH(p); | |
30 | } | |
31 | }; | |
32 | ||
33 | // Identifies segment location on disk, see SegmentManager, | |
34 | using segment_id_t = uint32_t; | |
35 | constexpr segment_id_t NULL_SEG_ID = | |
36 | std::numeric_limits<segment_id_t>::max() - 1; | |
37 | /* Used to denote relative paddr_t */ | |
38 | constexpr segment_id_t RECORD_REL_SEG_ID = | |
39 | std::numeric_limits<segment_id_t>::max() - 2; | |
40 | constexpr segment_id_t BLOCK_REL_SEG_ID = | |
41 | std::numeric_limits<segment_id_t>::max() - 3; | |
42 | ||
43 | // for tests which generate fake paddrs | |
44 | constexpr segment_id_t FAKE_SEG_ID = | |
45 | std::numeric_limits<segment_id_t>::max() - 4; | |
46 | ||
47 | std::ostream &segment_to_stream(std::ostream &, const segment_id_t &t); | |
48 | ||
49 | // Offset within a segment on disk, see SegmentManager | |
50 | // may be negative for relative offsets | |
51 | using segment_off_t = int32_t; | |
52 | constexpr segment_off_t NULL_SEG_OFF = | |
53 | std::numeric_limits<segment_id_t>::max(); | |
54 | ||
55 | std::ostream &offset_to_stream(std::ostream &, const segment_off_t &t); | |
56 | ||
57 | /* Monotonically increasing segment seq, uniquely identifies | |
58 | * the incarnation of a segment */ | |
59 | using segment_seq_t = uint32_t; | |
60 | static constexpr segment_seq_t NULL_SEG_SEQ = | |
61 | std::numeric_limits<segment_seq_t>::max(); | |
62 | ||
63 | // Offset of delta within a record | |
64 | using record_delta_idx_t = uint32_t; | |
65 | constexpr record_delta_idx_t NULL_DELTA_IDX = | |
66 | std::numeric_limits<record_delta_idx_t>::max(); | |
67 | ||
68 | /** | |
69 | * paddr_t | |
70 | * | |
71 | * <segment, offset> offset on disk, see SegmentManager | |
72 | * | |
73 | * May be absolute, record_relative, or block_relative. | |
74 | * | |
75 | * Blocks get read independently of the surrounding record, | |
76 | * so paddrs embedded directly within a block need to refer | |
77 | * to other blocks within the same record by a block_relative | |
78 | * addr relative to the block's own offset. By contrast, | |
79 | * deltas to existing blocks need to use record_relative | |
80 | * addrs relative to the first block of the record. | |
81 | * | |
82 | * Fresh extents during a transaction are refered to by | |
83 | * record_relative paddrs. | |
84 | */ | |
85 | struct paddr_t { | |
86 | segment_id_t segment = NULL_SEG_ID; | |
87 | segment_off_t offset = NULL_SEG_OFF; | |
88 | ||
89 | bool is_relative() const { | |
90 | return segment == RECORD_REL_SEG_ID || | |
91 | segment == BLOCK_REL_SEG_ID; | |
92 | } | |
93 | ||
94 | bool is_record_relative() const { | |
95 | return segment == RECORD_REL_SEG_ID; | |
96 | } | |
97 | ||
98 | bool is_block_relative() const { | |
99 | return segment == BLOCK_REL_SEG_ID; | |
100 | } | |
101 | ||
102 | paddr_t add_offset(segment_off_t o) const { | |
103 | return paddr_t{segment, offset + o}; | |
104 | } | |
105 | ||
106 | paddr_t add_relative(paddr_t o) const { | |
107 | assert(o.is_relative()); | |
108 | return paddr_t{segment, offset + o.offset}; | |
109 | } | |
110 | ||
111 | paddr_t add_block_relative(paddr_t o) const { | |
112 | // special version mainly for documentation purposes | |
113 | assert(o.is_block_relative()); | |
114 | return add_relative(o); | |
115 | } | |
116 | ||
117 | paddr_t add_record_relative(paddr_t o) const { | |
118 | // special version mainly for documentation purposes | |
119 | assert(o.is_record_relative()); | |
120 | return add_relative(o); | |
121 | } | |
122 | ||
123 | /** | |
124 | * paddr_t::operator- | |
125 | * | |
126 | * Only defined for record_relative paddr_ts. Yields a | |
127 | * block_relative address. | |
128 | */ | |
129 | paddr_t operator-(paddr_t rhs) const { | |
130 | assert(rhs.is_relative() && is_relative()); | |
131 | assert(rhs.segment == segment); | |
132 | return paddr_t{ | |
133 | BLOCK_REL_SEG_ID, | |
134 | offset - rhs.offset | |
135 | }; | |
136 | } | |
137 | ||
138 | /** | |
139 | * maybe_relative_to | |
140 | * | |
141 | * Helper for the case where an in-memory paddr_t may be | |
142 | * either block_relative or absolute (not record_relative). | |
143 | * | |
144 | * base must be either absolute or record_relative. | |
145 | */ | |
146 | paddr_t maybe_relative_to(paddr_t base) const { | |
147 | assert(!base.is_block_relative()); | |
148 | if (is_block_relative()) | |
149 | return base.add_block_relative(*this); | |
150 | else | |
151 | return *this; | |
152 | } | |
153 | ||
154 | DENC(paddr_t, v, p) { | |
155 | DENC_START(1, 1, p); | |
156 | denc(v.segment, p); | |
157 | denc(v.offset, p); | |
158 | DENC_FINISH(p); | |
159 | } | |
160 | }; | |
161 | WRITE_CMP_OPERATORS_2(paddr_t, segment, offset) | |
162 | WRITE_EQ_OPERATORS_2(paddr_t, segment, offset) | |
163 | constexpr paddr_t P_ADDR_NULL = paddr_t{}; | |
164 | constexpr paddr_t P_ADDR_MIN = paddr_t{0, 0}; | |
165 | constexpr paddr_t make_record_relative_paddr(segment_off_t off) { | |
166 | return paddr_t{RECORD_REL_SEG_ID, off}; | |
167 | } | |
168 | constexpr paddr_t make_block_relative_paddr(segment_off_t off) { | |
169 | return paddr_t{BLOCK_REL_SEG_ID, off}; | |
170 | } | |
171 | constexpr paddr_t make_fake_paddr(segment_off_t off) { | |
172 | return paddr_t{FAKE_SEG_ID, off}; | |
173 | } | |
174 | ||
175 | struct paddr_le_t { | |
176 | ceph_le32 segment = init_le32(NULL_SEG_ID); | |
177 | ceph_les32 offset = init_les32(NULL_SEG_OFF); | |
178 | ||
179 | paddr_le_t() = default; | |
180 | paddr_le_t(ceph_le32 segment, ceph_les32 offset) | |
181 | : segment(segment), offset(offset) {} | |
182 | paddr_le_t(segment_id_t segment, segment_off_t offset) | |
183 | : segment(init_le32(segment)), offset(init_les32(offset)) {} | |
184 | paddr_le_t(const paddr_t &addr) : paddr_le_t(addr.segment, addr.offset) {} | |
185 | ||
186 | operator paddr_t() const { | |
187 | return paddr_t{segment, offset}; | |
188 | } | |
189 | }; | |
190 | ||
191 | std::ostream &operator<<(std::ostream &out, const paddr_t &rhs); | |
192 | ||
193 | using objaddr_t = uint32_t; | |
194 | constexpr objaddr_t OBJ_ADDR_MIN = std::numeric_limits<objaddr_t>::min(); | |
195 | ||
196 | /* Monotonically increasing identifier for the location of a | |
197 | * journal_record. | |
198 | */ | |
199 | struct journal_seq_t { | |
200 | segment_seq_t segment_seq = 0; | |
201 | paddr_t offset; | |
202 | ||
203 | DENC(journal_seq_t, v, p) { | |
204 | DENC_START(1, 1, p); | |
205 | denc(v.segment_seq, p); | |
206 | denc(v.offset, p); | |
207 | DENC_FINISH(p); | |
208 | } | |
209 | }; | |
210 | WRITE_CMP_OPERATORS_2(journal_seq_t, segment_seq, offset) | |
211 | WRITE_EQ_OPERATORS_2(journal_seq_t, segment_seq, offset) | |
212 | ||
213 | std::ostream &operator<<(std::ostream &out, const journal_seq_t &seq); | |
214 | ||
215 | static constexpr journal_seq_t NO_DELTAS = journal_seq_t{ | |
216 | NULL_SEG_SEQ, | |
217 | P_ADDR_NULL | |
218 | }; | |
219 | ||
220 | // logical addr, see LBAManager, TransactionManager | |
221 | using laddr_t = uint64_t; | |
222 | constexpr laddr_t L_ADDR_MIN = std::numeric_limits<laddr_t>::min(); | |
223 | constexpr laddr_t L_ADDR_MAX = std::numeric_limits<laddr_t>::max(); | |
224 | constexpr laddr_t L_ADDR_NULL = std::numeric_limits<laddr_t>::max(); | |
225 | constexpr laddr_t L_ADDR_ROOT = std::numeric_limits<laddr_t>::max() - 1; | |
226 | constexpr laddr_t L_ADDR_LBAT = std::numeric_limits<laddr_t>::max() - 2; | |
227 | ||
228 | struct laddr_le_t { | |
229 | ceph_le64 laddr = init_le64(L_ADDR_NULL); | |
230 | ||
231 | laddr_le_t() = default; | |
232 | laddr_le_t(const laddr_le_t &) = default; | |
233 | explicit laddr_le_t(const laddr_t &addr) | |
234 | : laddr(init_le64(addr)) {} | |
235 | ||
236 | operator laddr_t() const { | |
237 | return laddr_t(laddr); | |
238 | } | |
239 | laddr_le_t& operator=(laddr_t addr) { | |
240 | ceph_le64 val; | |
241 | val = addr; | |
242 | laddr = val; | |
243 | return *this; | |
244 | } | |
245 | }; | |
246 | ||
247 | // logical offset, see LBAManager, TransactionManager | |
248 | using extent_len_t = uint32_t; | |
249 | constexpr extent_len_t EXTENT_LEN_MAX = | |
250 | std::numeric_limits<extent_len_t>::max(); | |
251 | ||
252 | using extent_len_le_t = ceph_le32; | |
253 | inline extent_len_le_t init_extent_len_le_t(extent_len_t len) { | |
254 | return init_le32(len); | |
255 | } | |
256 | ||
257 | struct laddr_list_t : std::list<std::pair<laddr_t, extent_len_t>> { | |
258 | template <typename... T> | |
259 | laddr_list_t(T&&... args) | |
260 | : std::list<std::pair<laddr_t, extent_len_t>>(std::forward<T>(args)...) {} | |
261 | }; | |
262 | struct paddr_list_t : std::list<std::pair<paddr_t, extent_len_t>> { | |
263 | template <typename... T> | |
264 | paddr_list_t(T&&... args) | |
265 | : std::list<std::pair<paddr_t, extent_len_t>>(std::forward<T>(args)...) {} | |
266 | }; | |
267 | ||
268 | std::ostream &operator<<(std::ostream &out, const laddr_list_t &rhs); | |
269 | std::ostream &operator<<(std::ostream &out, const paddr_list_t &rhs); | |
270 | ||
271 | /* identifies type of extent, used for interpretting deltas, managing | |
272 | * writeback. | |
273 | * | |
274 | * Note that any new extent type needs to be added to | |
275 | * Cache::get_extent_by_type in cache.cc | |
276 | */ | |
277 | enum class extent_types_t : uint8_t { | |
278 | ROOT = 0, | |
279 | LADDR_INTERNAL = 1, | |
280 | LADDR_LEAF = 2, | |
281 | ONODE_BLOCK = 3, | |
282 | EXTMAP_INNER = 4, | |
283 | EXTMAP_LEAF = 5, | |
284 | ONODE_BLOCK_STAGED = 6, | |
285 | ||
286 | // Test Block Types | |
287 | TEST_BLOCK = 0xF0, | |
288 | TEST_BLOCK_PHYSICAL = 0xF1, | |
289 | ||
290 | // None | |
291 | NONE = 0xFF | |
292 | }; | |
293 | ||
294 | inline bool is_logical_type(extent_types_t type) { | |
295 | switch (type) { | |
296 | case extent_types_t::ROOT: | |
297 | case extent_types_t::LADDR_INTERNAL: | |
298 | case extent_types_t::LADDR_LEAF: | |
299 | return false; | |
300 | default: | |
301 | return true; | |
302 | } | |
303 | } | |
304 | ||
305 | std::ostream &operator<<(std::ostream &out, extent_types_t t); | |
306 | ||
307 | /* description of a new physical extent */ | |
308 | struct extent_t { | |
309 | extent_types_t type; ///< type of extent | |
310 | laddr_t addr; ///< laddr of extent (L_ADDR_NULL for non-logical) | |
311 | ceph::bufferlist bl; ///< payload, bl.length() == length, aligned | |
312 | }; | |
313 | ||
314 | using extent_version_t = uint32_t; | |
315 | constexpr extent_version_t EXTENT_VERSION_NULL = 0; | |
316 | ||
317 | /* description of a mutation to a physical extent */ | |
318 | struct delta_info_t { | |
319 | extent_types_t type = extent_types_t::NONE; ///< delta type | |
320 | paddr_t paddr; ///< physical address | |
321 | laddr_t laddr = L_ADDR_NULL; ///< logical address | |
322 | uint32_t prev_crc = 0; | |
323 | uint32_t final_crc = 0; | |
324 | segment_off_t length = NULL_SEG_OFF; ///< extent length | |
325 | extent_version_t pversion; ///< prior version | |
326 | ceph::bufferlist bl; ///< payload | |
327 | ||
328 | DENC(delta_info_t, v, p) { | |
329 | DENC_START(1, 1, p); | |
330 | denc(v.type, p); | |
331 | denc(v.paddr, p); | |
332 | denc(v.laddr, p); | |
333 | denc(v.prev_crc, p); | |
334 | denc(v.final_crc, p); | |
335 | denc(v.length, p); | |
336 | denc(v.pversion, p); | |
337 | denc(v.bl, p); | |
338 | DENC_FINISH(p); | |
339 | } | |
340 | ||
341 | bool operator==(const delta_info_t &rhs) const { | |
342 | return ( | |
343 | type == rhs.type && | |
344 | paddr == rhs.paddr && | |
345 | laddr == rhs.laddr && | |
346 | prev_crc == rhs.prev_crc && | |
347 | final_crc == rhs.final_crc && | |
348 | length == rhs.length && | |
349 | pversion == rhs.pversion && | |
350 | bl == rhs.bl | |
351 | ); | |
352 | } | |
353 | ||
354 | friend std::ostream &operator<<(std::ostream &lhs, const delta_info_t &rhs); | |
355 | }; | |
356 | ||
357 | std::ostream &operator<<(std::ostream &lhs, const delta_info_t &rhs); | |
358 | ||
359 | struct record_t { | |
360 | std::vector<extent_t> extents; | |
361 | std::vector<delta_info_t> deltas; | |
362 | }; | |
363 | ||
364 | } | |
365 | ||
366 | WRITE_CLASS_DENC_BOUNDED(crimson::os::seastore::seastore_meta_t) | |
367 | WRITE_CLASS_DENC_BOUNDED(crimson::os::seastore::paddr_t) | |
368 | WRITE_CLASS_DENC_BOUNDED(crimson::os::seastore::journal_seq_t) | |
369 | WRITE_CLASS_DENC_BOUNDED(crimson::os::seastore::delta_info_t) |