1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #ifndef _BCACHEFS_EXTENTS_H |
3 | #define _BCACHEFS_EXTENTS_H |
4 | |
5 | #include "bcachefs.h" |
6 | #include "bkey.h" |
7 | #include "extents_types.h" |
8 | |
9 | struct bch_fs; |
10 | struct btree_trans; |
11 | enum bkey_invalid_flags; |
12 | |
13 | /* extent entries: */ |
14 | |
15 | #define extent_entry_last(_e) \ |
16 | ((typeof(&(_e).v->start[0])) bkey_val_end(_e)) |
17 | |
18 | #define entry_to_ptr(_entry) \ |
19 | ({ \ |
20 | EBUG_ON((_entry) && !extent_entry_is_ptr(_entry)); \ |
21 | \ |
22 | __builtin_choose_expr( \ |
23 | type_is_exact(_entry, const union bch_extent_entry *), \ |
24 | (const struct bch_extent_ptr *) (_entry), \ |
25 | (struct bch_extent_ptr *) (_entry)); \ |
26 | }) |
27 | |
28 | /* downcast, preserves const */ |
29 | #define to_entry(_entry) \ |
30 | ({ \ |
31 | BUILD_BUG_ON(!type_is(_entry, union bch_extent_crc *) && \ |
32 | !type_is(_entry, struct bch_extent_ptr *) && \ |
33 | !type_is(_entry, struct bch_extent_stripe_ptr *)); \ |
34 | \ |
35 | __builtin_choose_expr( \ |
36 | (type_is_exact(_entry, const union bch_extent_crc *) || \ |
37 | type_is_exact(_entry, const struct bch_extent_ptr *) ||\ |
38 | type_is_exact(_entry, const struct bch_extent_stripe_ptr *)),\ |
39 | (const union bch_extent_entry *) (_entry), \ |
40 | (union bch_extent_entry *) (_entry)); \ |
41 | }) |
42 | |
43 | #define extent_entry_next(_entry) \ |
44 | ((typeof(_entry)) ((void *) (_entry) + extent_entry_bytes(_entry))) |
45 | |
46 | #define extent_entry_next_safe(_entry, _end) \ |
47 | (likely(__extent_entry_type(_entry) < BCH_EXTENT_ENTRY_MAX) \ |
48 | ? extent_entry_next(_entry) \ |
49 | : _end) |
50 | |
51 | static inline unsigned |
52 | __extent_entry_type(const union bch_extent_entry *e) |
53 | { |
54 | return e->type ? __ffs(e->type) : BCH_EXTENT_ENTRY_MAX; |
55 | } |
56 | |
57 | static inline enum bch_extent_entry_type |
58 | extent_entry_type(const union bch_extent_entry *e) |
59 | { |
60 | int ret = __ffs(e->type); |
61 | |
62 | EBUG_ON(ret < 0 || ret >= BCH_EXTENT_ENTRY_MAX); |
63 | |
64 | return ret; |
65 | } |
66 | |
67 | static inline size_t extent_entry_bytes(const union bch_extent_entry *entry) |
68 | { |
69 | switch (extent_entry_type(e: entry)) { |
70 | #define x(f, n) \ |
71 | case BCH_EXTENT_ENTRY_##f: \ |
72 | return sizeof(struct bch_extent_##f); |
73 | BCH_EXTENT_ENTRY_TYPES() |
74 | #undef x |
75 | default: |
76 | BUG(); |
77 | } |
78 | } |
79 | |
80 | static inline size_t extent_entry_u64s(const union bch_extent_entry *entry) |
81 | { |
82 | return extent_entry_bytes(entry) / sizeof(u64); |
83 | } |
84 | |
85 | static inline void __extent_entry_insert(struct bkey_i *k, |
86 | union bch_extent_entry *dst, |
87 | union bch_extent_entry *new) |
88 | { |
89 | union bch_extent_entry *end = bkey_val_end(bkey_i_to_s(k)); |
90 | |
91 | memmove_u64s_up_small(dst: (u64 *) dst + extent_entry_u64s(entry: new), |
92 | src: dst, u64s: (u64 *) end - (u64 *) dst); |
93 | k->k.u64s += extent_entry_u64s(entry: new); |
94 | memcpy_u64s_small(dst, src: new, u64s: extent_entry_u64s(entry: new)); |
95 | } |
96 | |
97 | static inline void extent_entry_drop(struct bkey_s k, union bch_extent_entry *entry) |
98 | { |
99 | union bch_extent_entry *next = extent_entry_next(entry); |
100 | |
101 | /* stripes have ptrs, but their layout doesn't work with this code */ |
102 | BUG_ON(k.k->type == KEY_TYPE_stripe); |
103 | |
104 | memmove_u64s_down(dst: entry, src: next, |
105 | u64s: (u64 *) bkey_val_end(k) - (u64 *) next); |
106 | k.k->u64s -= (u64 *) next - (u64 *) entry; |
107 | } |
108 | |
109 | static inline bool extent_entry_is_ptr(const union bch_extent_entry *e) |
110 | { |
111 | return __extent_entry_type(e) == BCH_EXTENT_ENTRY_ptr; |
112 | } |
113 | |
114 | static inline bool extent_entry_is_stripe_ptr(const union bch_extent_entry *e) |
115 | { |
116 | return __extent_entry_type(e) == BCH_EXTENT_ENTRY_stripe_ptr; |
117 | } |
118 | |
119 | static inline bool extent_entry_is_crc(const union bch_extent_entry *e) |
120 | { |
121 | switch (__extent_entry_type(e)) { |
122 | case BCH_EXTENT_ENTRY_crc32: |
123 | case BCH_EXTENT_ENTRY_crc64: |
124 | case BCH_EXTENT_ENTRY_crc128: |
125 | return true; |
126 | default: |
127 | return false; |
128 | } |
129 | } |
130 | |
131 | union bch_extent_crc { |
132 | u8 type; |
133 | struct bch_extent_crc32 crc32; |
134 | struct bch_extent_crc64 crc64; |
135 | struct bch_extent_crc128 crc128; |
136 | }; |
137 | |
138 | #define __entry_to_crc(_entry) \ |
139 | __builtin_choose_expr( \ |
140 | type_is_exact(_entry, const union bch_extent_entry *), \ |
141 | (const union bch_extent_crc *) (_entry), \ |
142 | (union bch_extent_crc *) (_entry)) |
143 | |
144 | #define entry_to_crc(_entry) \ |
145 | ({ \ |
146 | EBUG_ON((_entry) && !extent_entry_is_crc(_entry)); \ |
147 | \ |
148 | __entry_to_crc(_entry); \ |
149 | }) |
150 | |
151 | static inline struct bch_extent_crc_unpacked |
152 | bch2_extent_crc_unpack(const struct bkey *k, const union bch_extent_crc *crc) |
153 | { |
154 | #define common_fields(_crc) \ |
155 | .csum_type = _crc.csum_type, \ |
156 | .compression_type = _crc.compression_type, \ |
157 | .compressed_size = _crc._compressed_size + 1, \ |
158 | .uncompressed_size = _crc._uncompressed_size + 1, \ |
159 | .offset = _crc.offset, \ |
160 | .live_size = k->size |
161 | |
162 | if (!crc) |
163 | return (struct bch_extent_crc_unpacked) { |
164 | .compressed_size = k->size, |
165 | .uncompressed_size = k->size, |
166 | .live_size = k->size, |
167 | }; |
168 | |
169 | switch (extent_entry_type(to_entry(crc))) { |
170 | case BCH_EXTENT_ENTRY_crc32: { |
171 | struct bch_extent_crc_unpacked ret = (struct bch_extent_crc_unpacked) { |
172 | common_fields(crc->crc32), |
173 | }; |
174 | |
175 | *((__le32 *) &ret.csum.lo) = (__le32 __force) crc->crc32.csum; |
176 | return ret; |
177 | } |
178 | case BCH_EXTENT_ENTRY_crc64: { |
179 | struct bch_extent_crc_unpacked ret = (struct bch_extent_crc_unpacked) { |
180 | common_fields(crc->crc64), |
181 | .nonce = crc->crc64.nonce, |
182 | .csum.lo = (__force __le64) crc->crc64.csum_lo, |
183 | }; |
184 | |
185 | *((__le16 *) &ret.csum.hi) = (__le16 __force) crc->crc64.csum_hi; |
186 | |
187 | return ret; |
188 | } |
189 | case BCH_EXTENT_ENTRY_crc128: { |
190 | struct bch_extent_crc_unpacked ret = (struct bch_extent_crc_unpacked) { |
191 | common_fields(crc->crc128), |
192 | .nonce = crc->crc128.nonce, |
193 | .csum = crc->crc128.csum, |
194 | }; |
195 | |
196 | return ret; |
197 | } |
198 | default: |
199 | BUG(); |
200 | } |
201 | #undef common_fields |
202 | } |
203 | |
204 | static inline bool crc_is_compressed(struct bch_extent_crc_unpacked crc) |
205 | { |
206 | return (crc.compression_type != BCH_COMPRESSION_TYPE_none && |
207 | crc.compression_type != BCH_COMPRESSION_TYPE_incompressible); |
208 | } |
209 | |
210 | static inline bool crc_is_encoded(struct bch_extent_crc_unpacked crc) |
211 | { |
212 | return crc.csum_type != BCH_CSUM_none || crc_is_compressed(crc); |
213 | } |
214 | |
215 | /* bkey_ptrs: generically over any key type that has ptrs */ |
216 | |
217 | struct bkey_ptrs_c { |
218 | const union bch_extent_entry *start; |
219 | const union bch_extent_entry *end; |
220 | }; |
221 | |
222 | struct bkey_ptrs { |
223 | union bch_extent_entry *start; |
224 | union bch_extent_entry *end; |
225 | }; |
226 | |
227 | static inline struct bkey_ptrs_c bch2_bkey_ptrs_c(struct bkey_s_c k) |
228 | { |
229 | switch (k.k->type) { |
230 | case KEY_TYPE_btree_ptr: { |
231 | struct bkey_s_c_btree_ptr e = bkey_s_c_to_btree_ptr(k); |
232 | |
233 | return (struct bkey_ptrs_c) { |
234 | to_entry(&e.v->start[0]), |
235 | to_entry(extent_entry_last(e)) |
236 | }; |
237 | } |
238 | case KEY_TYPE_extent: { |
239 | struct bkey_s_c_extent e = bkey_s_c_to_extent(k); |
240 | |
241 | return (struct bkey_ptrs_c) { |
242 | e.v->start, |
243 | extent_entry_last(e) |
244 | }; |
245 | } |
246 | case KEY_TYPE_stripe: { |
247 | struct bkey_s_c_stripe s = bkey_s_c_to_stripe(k); |
248 | |
249 | return (struct bkey_ptrs_c) { |
250 | to_entry(&s.v->ptrs[0]), |
251 | to_entry(&s.v->ptrs[s.v->nr_blocks]), |
252 | }; |
253 | } |
254 | case KEY_TYPE_reflink_v: { |
255 | struct bkey_s_c_reflink_v r = bkey_s_c_to_reflink_v(k); |
256 | |
257 | return (struct bkey_ptrs_c) { |
258 | r.v->start, |
259 | bkey_val_end(r), |
260 | }; |
261 | } |
262 | case KEY_TYPE_btree_ptr_v2: { |
263 | struct bkey_s_c_btree_ptr_v2 e = bkey_s_c_to_btree_ptr_v2(k); |
264 | |
265 | return (struct bkey_ptrs_c) { |
266 | to_entry(&e.v->start[0]), |
267 | to_entry(extent_entry_last(e)) |
268 | }; |
269 | } |
270 | default: |
271 | return (struct bkey_ptrs_c) { NULL, NULL }; |
272 | } |
273 | } |
274 | |
275 | static inline struct bkey_ptrs bch2_bkey_ptrs(struct bkey_s k) |
276 | { |
277 | struct bkey_ptrs_c p = bch2_bkey_ptrs_c(k: k.s_c); |
278 | |
279 | return (struct bkey_ptrs) { |
280 | (void *) p.start, |
281 | (void *) p.end |
282 | }; |
283 | } |
284 | |
285 | #define __bkey_extent_entry_for_each_from(_start, _end, _entry) \ |
286 | for ((_entry) = (_start); \ |
287 | (_entry) < (_end); \ |
288 | (_entry) = extent_entry_next_safe(_entry, _end)) |
289 | |
290 | #define __bkey_ptr_next(_ptr, _end) \ |
291 | ({ \ |
292 | typeof(_end) _entry; \ |
293 | \ |
294 | __bkey_extent_entry_for_each_from(to_entry(_ptr), _end, _entry) \ |
295 | if (extent_entry_is_ptr(_entry)) \ |
296 | break; \ |
297 | \ |
298 | _entry < (_end) ? entry_to_ptr(_entry) : NULL; \ |
299 | }) |
300 | |
301 | #define bkey_extent_entry_for_each_from(_p, _entry, _start) \ |
302 | __bkey_extent_entry_for_each_from(_start, (_p).end, _entry) |
303 | |
304 | #define bkey_extent_entry_for_each(_p, _entry) \ |
305 | bkey_extent_entry_for_each_from(_p, _entry, _p.start) |
306 | |
307 | #define __bkey_for_each_ptr(_start, _end, _ptr) \ |
308 | for (typeof(_start) (_ptr) = (_start); \ |
309 | ((_ptr) = __bkey_ptr_next(_ptr, _end)); \ |
310 | (_ptr)++) |
311 | |
312 | #define bkey_ptr_next(_p, _ptr) \ |
313 | __bkey_ptr_next(_ptr, (_p).end) |
314 | |
315 | #define bkey_for_each_ptr(_p, _ptr) \ |
316 | __bkey_for_each_ptr(&(_p).start->ptr, (_p).end, _ptr) |
317 | |
318 | #define __bkey_ptr_next_decode(_k, _end, _ptr, _entry) \ |
319 | ({ \ |
320 | __label__ out; \ |
321 | \ |
322 | (_ptr).idx = 0; \ |
323 | (_ptr).has_ec = false; \ |
324 | \ |
325 | __bkey_extent_entry_for_each_from(_entry, _end, _entry) \ |
326 | switch (__extent_entry_type(_entry)) { \ |
327 | case BCH_EXTENT_ENTRY_ptr: \ |
328 | (_ptr).ptr = _entry->ptr; \ |
329 | goto out; \ |
330 | case BCH_EXTENT_ENTRY_crc32: \ |
331 | case BCH_EXTENT_ENTRY_crc64: \ |
332 | case BCH_EXTENT_ENTRY_crc128: \ |
333 | (_ptr).crc = bch2_extent_crc_unpack(_k, \ |
334 | entry_to_crc(_entry)); \ |
335 | break; \ |
336 | case BCH_EXTENT_ENTRY_stripe_ptr: \ |
337 | (_ptr).ec = _entry->stripe_ptr; \ |
338 | (_ptr).has_ec = true; \ |
339 | break; \ |
340 | default: \ |
341 | /* nothing */ \ |
342 | break; \ |
343 | } \ |
344 | out: \ |
345 | _entry < (_end); \ |
346 | }) |
347 | |
348 | #define __bkey_for_each_ptr_decode(_k, _start, _end, _ptr, _entry) \ |
349 | for ((_ptr).crc = bch2_extent_crc_unpack(_k, NULL), \ |
350 | (_entry) = _start; \ |
351 | __bkey_ptr_next_decode(_k, _end, _ptr, _entry); \ |
352 | (_entry) = extent_entry_next_safe(_entry, _end)) |
353 | |
354 | #define bkey_for_each_ptr_decode(_k, _p, _ptr, _entry) \ |
355 | __bkey_for_each_ptr_decode(_k, (_p).start, (_p).end, \ |
356 | _ptr, _entry) |
357 | |
358 | #define bkey_crc_next(_k, _start, _end, _crc, _iter) \ |
359 | ({ \ |
360 | __bkey_extent_entry_for_each_from(_iter, _end, _iter) \ |
361 | if (extent_entry_is_crc(_iter)) { \ |
362 | (_crc) = bch2_extent_crc_unpack(_k, \ |
363 | entry_to_crc(_iter)); \ |
364 | break; \ |
365 | } \ |
366 | \ |
367 | (_iter) < (_end); \ |
368 | }) |
369 | |
370 | #define __bkey_for_each_crc(_k, _start, _end, _crc, _iter) \ |
371 | for ((_crc) = bch2_extent_crc_unpack(_k, NULL), \ |
372 | (_iter) = (_start); \ |
373 | bkey_crc_next(_k, _start, _end, _crc, _iter); \ |
374 | (_iter) = extent_entry_next(_iter)) |
375 | |
376 | #define bkey_for_each_crc(_k, _p, _crc, _iter) \ |
377 | __bkey_for_each_crc(_k, (_p).start, (_p).end, _crc, _iter) |
378 | |
379 | /* Iterate over pointers in KEY_TYPE_extent: */ |
380 | |
381 | #define extent_for_each_entry_from(_e, _entry, _start) \ |
382 | __bkey_extent_entry_for_each_from(_start, \ |
383 | extent_entry_last(_e), _entry) |
384 | |
385 | #define extent_for_each_entry(_e, _entry) \ |
386 | extent_for_each_entry_from(_e, _entry, (_e).v->start) |
387 | |
388 | #define extent_ptr_next(_e, _ptr) \ |
389 | __bkey_ptr_next(_ptr, extent_entry_last(_e)) |
390 | |
391 | #define extent_for_each_ptr(_e, _ptr) \ |
392 | __bkey_for_each_ptr(&(_e).v->start->ptr, extent_entry_last(_e), _ptr) |
393 | |
394 | #define extent_for_each_ptr_decode(_e, _ptr, _entry) \ |
395 | __bkey_for_each_ptr_decode((_e).k, (_e).v->start, \ |
396 | extent_entry_last(_e), _ptr, _entry) |
397 | |
398 | /* utility code common to all keys with pointers: */ |
399 | |
400 | void bch2_mark_io_failure(struct bch_io_failures *, |
401 | struct extent_ptr_decoded *); |
402 | int bch2_bkey_pick_read_device(struct bch_fs *, struct bkey_s_c, |
403 | struct bch_io_failures *, |
404 | struct extent_ptr_decoded *); |
405 | |
406 | /* KEY_TYPE_btree_ptr: */ |
407 | |
408 | int bch2_btree_ptr_invalid(struct bch_fs *, struct bkey_s_c, |
409 | enum bkey_invalid_flags, struct printbuf *); |
410 | void bch2_btree_ptr_to_text(struct printbuf *, struct bch_fs *, |
411 | struct bkey_s_c); |
412 | |
413 | int bch2_btree_ptr_v2_invalid(struct bch_fs *, struct bkey_s_c, |
414 | enum bkey_invalid_flags, struct printbuf *); |
415 | void bch2_btree_ptr_v2_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); |
416 | void bch2_btree_ptr_v2_compat(enum btree_id, unsigned, unsigned, |
417 | int, struct bkey_s); |
418 | |
419 | #define bch2_bkey_ops_btree_ptr ((struct bkey_ops) { \ |
420 | .key_invalid = bch2_btree_ptr_invalid, \ |
421 | .val_to_text = bch2_btree_ptr_to_text, \ |
422 | .swab = bch2_ptr_swab, \ |
423 | .trigger = bch2_trigger_extent, \ |
424 | }) |
425 | |
426 | #define bch2_bkey_ops_btree_ptr_v2 ((struct bkey_ops) { \ |
427 | .key_invalid = bch2_btree_ptr_v2_invalid, \ |
428 | .val_to_text = bch2_btree_ptr_v2_to_text, \ |
429 | .swab = bch2_ptr_swab, \ |
430 | .compat = bch2_btree_ptr_v2_compat, \ |
431 | .trigger = bch2_trigger_extent, \ |
432 | .min_val_size = 40, \ |
433 | }) |
434 | |
435 | /* KEY_TYPE_extent: */ |
436 | |
437 | bool bch2_extent_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c); |
438 | |
439 | #define bch2_bkey_ops_extent ((struct bkey_ops) { \ |
440 | .key_invalid = bch2_bkey_ptrs_invalid, \ |
441 | .val_to_text = bch2_bkey_ptrs_to_text, \ |
442 | .swab = bch2_ptr_swab, \ |
443 | .key_normalize = bch2_extent_normalize, \ |
444 | .key_merge = bch2_extent_merge, \ |
445 | .trigger = bch2_trigger_extent, \ |
446 | }) |
447 | |
448 | /* KEY_TYPE_reservation: */ |
449 | |
450 | int bch2_reservation_invalid(struct bch_fs *, struct bkey_s_c, |
451 | enum bkey_invalid_flags, struct printbuf *); |
452 | void bch2_reservation_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); |
453 | bool bch2_reservation_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c); |
454 | |
455 | #define bch2_bkey_ops_reservation ((struct bkey_ops) { \ |
456 | .key_invalid = bch2_reservation_invalid, \ |
457 | .val_to_text = bch2_reservation_to_text, \ |
458 | .key_merge = bch2_reservation_merge, \ |
459 | .trigger = bch2_trigger_reservation, \ |
460 | .min_val_size = 8, \ |
461 | }) |
462 | |
463 | /* Extent checksum entries: */ |
464 | |
465 | bool bch2_can_narrow_extent_crcs(struct bkey_s_c, |
466 | struct bch_extent_crc_unpacked); |
467 | bool bch2_bkey_narrow_crcs(struct bkey_i *, struct bch_extent_crc_unpacked); |
468 | void bch2_extent_crc_append(struct bkey_i *, |
469 | struct bch_extent_crc_unpacked); |
470 | |
471 | /* Generic code for keys with pointers: */ |
472 | |
473 | static inline bool bkey_is_btree_ptr(const struct bkey *k) |
474 | { |
475 | switch (k->type) { |
476 | case KEY_TYPE_btree_ptr: |
477 | case KEY_TYPE_btree_ptr_v2: |
478 | return true; |
479 | default: |
480 | return false; |
481 | } |
482 | } |
483 | |
484 | static inline bool bkey_extent_is_direct_data(const struct bkey *k) |
485 | { |
486 | switch (k->type) { |
487 | case KEY_TYPE_btree_ptr: |
488 | case KEY_TYPE_btree_ptr_v2: |
489 | case KEY_TYPE_extent: |
490 | case KEY_TYPE_reflink_v: |
491 | return true; |
492 | default: |
493 | return false; |
494 | } |
495 | } |
496 | |
497 | static inline bool bkey_extent_is_inline_data(const struct bkey *k) |
498 | { |
499 | return k->type == KEY_TYPE_inline_data || |
500 | k->type == KEY_TYPE_indirect_inline_data; |
501 | } |
502 | |
503 | static inline unsigned bkey_inline_data_offset(const struct bkey *k) |
504 | { |
505 | switch (k->type) { |
506 | case KEY_TYPE_inline_data: |
507 | return sizeof(struct bch_inline_data); |
508 | case KEY_TYPE_indirect_inline_data: |
509 | return sizeof(struct bch_indirect_inline_data); |
510 | default: |
511 | BUG(); |
512 | } |
513 | } |
514 | |
515 | static inline unsigned bkey_inline_data_bytes(const struct bkey *k) |
516 | { |
517 | return bkey_val_bytes(k) - bkey_inline_data_offset(k); |
518 | } |
519 | |
520 | #define bkey_inline_data_p(_k) (((void *) (_k).v) + bkey_inline_data_offset((_k).k)) |
521 | |
522 | static inline bool bkey_extent_is_data(const struct bkey *k) |
523 | { |
524 | return bkey_extent_is_direct_data(k) || |
525 | bkey_extent_is_inline_data(k) || |
526 | k->type == KEY_TYPE_reflink_p; |
527 | } |
528 | |
529 | /* |
530 | * Should extent be counted under inode->i_sectors? |
531 | */ |
532 | static inline bool bkey_extent_is_allocation(const struct bkey *k) |
533 | { |
534 | switch (k->type) { |
535 | case KEY_TYPE_extent: |
536 | case KEY_TYPE_reservation: |
537 | case KEY_TYPE_reflink_p: |
538 | case KEY_TYPE_reflink_v: |
539 | case KEY_TYPE_inline_data: |
540 | case KEY_TYPE_indirect_inline_data: |
541 | case KEY_TYPE_error: |
542 | return true; |
543 | default: |
544 | return false; |
545 | } |
546 | } |
547 | |
548 | static inline bool bkey_extent_is_unwritten(struct bkey_s_c k) |
549 | { |
550 | struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); |
551 | |
552 | bkey_for_each_ptr(ptrs, ptr) |
553 | if (ptr->unwritten) |
554 | return true; |
555 | return false; |
556 | } |
557 | |
558 | static inline bool bkey_extent_is_reservation(struct bkey_s_c k) |
559 | { |
560 | return k.k->type == KEY_TYPE_reservation || |
561 | bkey_extent_is_unwritten(k); |
562 | } |
563 | |
564 | static inline struct bch_devs_list bch2_bkey_devs(struct bkey_s_c k) |
565 | { |
566 | struct bch_devs_list ret = (struct bch_devs_list) { 0 }; |
567 | struct bkey_ptrs_c p = bch2_bkey_ptrs_c(k); |
568 | |
569 | bkey_for_each_ptr(p, ptr) |
570 | ret.data[ret.nr++] = ptr->dev; |
571 | |
572 | return ret; |
573 | } |
574 | |
575 | static inline struct bch_devs_list bch2_bkey_dirty_devs(struct bkey_s_c k) |
576 | { |
577 | struct bch_devs_list ret = (struct bch_devs_list) { 0 }; |
578 | struct bkey_ptrs_c p = bch2_bkey_ptrs_c(k); |
579 | |
580 | bkey_for_each_ptr(p, ptr) |
581 | if (!ptr->cached) |
582 | ret.data[ret.nr++] = ptr->dev; |
583 | |
584 | return ret; |
585 | } |
586 | |
587 | static inline struct bch_devs_list bch2_bkey_cached_devs(struct bkey_s_c k) |
588 | { |
589 | struct bch_devs_list ret = (struct bch_devs_list) { 0 }; |
590 | struct bkey_ptrs_c p = bch2_bkey_ptrs_c(k); |
591 | |
592 | bkey_for_each_ptr(p, ptr) |
593 | if (ptr->cached) |
594 | ret.data[ret.nr++] = ptr->dev; |
595 | |
596 | return ret; |
597 | } |
598 | |
599 | unsigned bch2_bkey_nr_ptrs(struct bkey_s_c); |
600 | unsigned bch2_bkey_nr_ptrs_allocated(struct bkey_s_c); |
601 | unsigned bch2_bkey_nr_ptrs_fully_allocated(struct bkey_s_c); |
602 | bool bch2_bkey_is_incompressible(struct bkey_s_c); |
603 | unsigned bch2_bkey_sectors_compressed(struct bkey_s_c); |
604 | |
605 | unsigned bch2_bkey_replicas(struct bch_fs *, struct bkey_s_c); |
606 | unsigned bch2_extent_ptr_desired_durability(struct bch_fs *, struct extent_ptr_decoded *); |
607 | unsigned bch2_extent_ptr_durability(struct bch_fs *, struct extent_ptr_decoded *); |
608 | unsigned bch2_bkey_durability(struct bch_fs *, struct bkey_s_c); |
609 | |
610 | void bch2_bkey_drop_device(struct bkey_s, unsigned); |
611 | void bch2_bkey_drop_device_noerror(struct bkey_s, unsigned); |
612 | |
613 | const struct bch_extent_ptr *bch2_bkey_has_device_c(struct bkey_s_c, unsigned); |
614 | |
615 | static inline struct bch_extent_ptr *bch2_bkey_has_device(struct bkey_s k, unsigned dev) |
616 | { |
617 | return (void *) bch2_bkey_has_device_c(k.s_c, dev); |
618 | } |
619 | |
620 | bool bch2_bkey_has_target(struct bch_fs *, struct bkey_s_c, unsigned); |
621 | |
622 | void bch2_bkey_extent_entry_drop(struct bkey_i *, union bch_extent_entry *); |
623 | |
624 | static inline void bch2_bkey_append_ptr(struct bkey_i *k, struct bch_extent_ptr ptr) |
625 | { |
626 | struct bch_extent_ptr *dest; |
627 | |
628 | EBUG_ON(bch2_bkey_has_device(bkey_i_to_s(k), ptr.dev)); |
629 | |
630 | switch (k->k.type) { |
631 | case KEY_TYPE_btree_ptr: |
632 | case KEY_TYPE_btree_ptr_v2: |
633 | case KEY_TYPE_extent: |
634 | EBUG_ON(bkey_val_u64s(&k->k) >= BKEY_EXTENT_VAL_U64s_MAX); |
635 | |
636 | ptr.type = 1 << BCH_EXTENT_ENTRY_ptr; |
637 | dest = (struct bch_extent_ptr *)((void *) &k->v + bkey_val_bytes(k: &k->k)); |
638 | *dest = ptr; |
639 | k->k.u64s++; |
640 | break; |
641 | default: |
642 | BUG(); |
643 | } |
644 | } |
645 | |
646 | void bch2_extent_ptr_decoded_append(struct bkey_i *, |
647 | struct extent_ptr_decoded *); |
648 | union bch_extent_entry *bch2_bkey_drop_ptr_noerror(struct bkey_s, |
649 | struct bch_extent_ptr *); |
650 | union bch_extent_entry *bch2_bkey_drop_ptr(struct bkey_s, |
651 | struct bch_extent_ptr *); |
652 | |
653 | #define bch2_bkey_drop_ptrs(_k, _ptr, _cond) \ |
654 | do { \ |
655 | struct bkey_ptrs _ptrs = bch2_bkey_ptrs(_k); \ |
656 | \ |
657 | _ptr = &_ptrs.start->ptr; \ |
658 | \ |
659 | while ((_ptr = bkey_ptr_next(_ptrs, _ptr))) { \ |
660 | if (_cond) { \ |
661 | _ptr = (void *) bch2_bkey_drop_ptr(_k, _ptr); \ |
662 | _ptrs = bch2_bkey_ptrs(_k); \ |
663 | continue; \ |
664 | } \ |
665 | \ |
666 | (_ptr)++; \ |
667 | } \ |
668 | } while (0) |
669 | |
670 | bool bch2_bkey_matches_ptr(struct bch_fs *, struct bkey_s_c, |
671 | struct bch_extent_ptr, u64); |
672 | bool bch2_extents_match(struct bkey_s_c, struct bkey_s_c); |
673 | struct bch_extent_ptr * |
674 | bch2_extent_has_ptr(struct bkey_s_c, struct extent_ptr_decoded, struct bkey_s); |
675 | |
676 | void bch2_extent_ptr_set_cached(struct bkey_s, struct bch_extent_ptr *); |
677 | |
678 | bool bch2_extent_normalize(struct bch_fs *, struct bkey_s); |
679 | void bch2_extent_ptr_to_text(struct printbuf *out, struct bch_fs *, const struct bch_extent_ptr *); |
680 | void bch2_bkey_ptrs_to_text(struct printbuf *, struct bch_fs *, |
681 | struct bkey_s_c); |
682 | int bch2_bkey_ptrs_invalid(struct bch_fs *, struct bkey_s_c, |
683 | enum bkey_invalid_flags, struct printbuf *); |
684 | |
685 | void bch2_ptr_swab(struct bkey_s); |
686 | |
687 | const struct bch_extent_rebalance *bch2_bkey_rebalance_opts(struct bkey_s_c); |
688 | unsigned bch2_bkey_ptrs_need_rebalance(struct bch_fs *, struct bkey_s_c, |
689 | unsigned, unsigned); |
690 | bool bch2_bkey_needs_rebalance(struct bch_fs *, struct bkey_s_c); |
691 | |
692 | int bch2_bkey_set_needs_rebalance(struct bch_fs *, struct bkey_i *, |
693 | struct bch_io_opts *); |
694 | |
695 | /* Generic extent code: */ |
696 | |
697 | enum bch_extent_overlap { |
698 | BCH_EXTENT_OVERLAP_ALL = 0, |
699 | BCH_EXTENT_OVERLAP_BACK = 1, |
700 | BCH_EXTENT_OVERLAP_FRONT = 2, |
701 | BCH_EXTENT_OVERLAP_MIDDLE = 3, |
702 | }; |
703 | |
704 | /* Returns how k overlaps with m */ |
705 | static inline enum bch_extent_overlap bch2_extent_overlap(const struct bkey *k, |
706 | const struct bkey *m) |
707 | { |
708 | int cmp1 = bkey_lt(l: k->p, r: m->p); |
709 | int cmp2 = bkey_gt(l: bkey_start_pos(k), r: bkey_start_pos(k: m)); |
710 | |
711 | return (cmp1 << 1) + cmp2; |
712 | } |
713 | |
714 | int bch2_cut_front_s(struct bpos, struct bkey_s); |
715 | int bch2_cut_back_s(struct bpos, struct bkey_s); |
716 | |
717 | static inline void bch2_cut_front(struct bpos where, struct bkey_i *k) |
718 | { |
719 | bch2_cut_front_s(where, bkey_i_to_s(k)); |
720 | } |
721 | |
722 | static inline void bch2_cut_back(struct bpos where, struct bkey_i *k) |
723 | { |
724 | bch2_cut_back_s(where, bkey_i_to_s(k)); |
725 | } |
726 | |
727 | /** |
728 | * bch_key_resize - adjust size of @k |
729 | * |
730 | * bkey_start_offset(k) will be preserved, modifies where the extent ends |
731 | */ |
732 | static inline void bch2_key_resize(struct bkey *k, unsigned new_size) |
733 | { |
734 | k->p.offset -= k->size; |
735 | k->p.offset += new_size; |
736 | k->size = new_size; |
737 | } |
738 | |
739 | #endif /* _BCACHEFS_EXTENTS_H */ |
740 | |