1 // SPDX-License-Identifier: GPL-2.0
3 #include "bkey_on_stack.h"
8 typedef int (*sort_cmp_fn)(struct btree *,
10 struct bkey_packed *);
12 static inline bool sort_iter_end(struct sort_iter *iter)
17 static inline void __sort_iter_sift(struct sort_iter *iter,
25 cmp(iter->b, iter->data[i].k, iter->data[i + 1].k) > 0;
27 swap(iter->data[i], iter->data[i + 1]);
30 static inline void sort_iter_sift(struct sort_iter *iter, sort_cmp_fn cmp)
33 __sort_iter_sift(iter, 0, cmp);
36 static inline void sort_iter_sort(struct sort_iter *iter, sort_cmp_fn cmp)
38 unsigned i = iter->used;
41 __sort_iter_sift(iter, i, cmp);
44 static inline struct bkey_packed *sort_iter_peek(struct sort_iter *iter)
46 return !sort_iter_end(iter) ? iter->data->k : NULL;
49 static inline void __sort_iter_advance(struct sort_iter *iter,
50 unsigned idx, sort_cmp_fn cmp)
52 struct sort_iter_set *i = iter->data + idx;
54 BUG_ON(idx >= iter->used);
56 i->k = bkey_next_skip_noops(i->k, i->end);
58 BUG_ON(i->k > i->end);
61 array_remove_item(iter->data, iter->used, idx);
63 __sort_iter_sift(iter, idx, cmp);
66 static inline void sort_iter_advance(struct sort_iter *iter, sort_cmp_fn cmp)
68 __sort_iter_advance(iter, 0, cmp);
71 static inline struct bkey_packed *sort_iter_next(struct sort_iter *iter,
74 struct bkey_packed *ret = sort_iter_peek(iter);
77 sort_iter_advance(iter, cmp);
83 * If keys compare equal, compare by pointer order:
85 static inline int key_sort_fix_overlapping_cmp(struct btree *b,
86 struct bkey_packed *l,
87 struct bkey_packed *r)
89 return bkey_cmp_packed(b, l, r) ?:
90 cmp_int((unsigned long) l, (unsigned long) r);
93 static inline bool should_drop_next_key(struct sort_iter *iter)
96 * key_sort_cmp() ensures that when keys compare equal the older key
97 * comes first; so if l->k compares equal to r->k then l->k is older
98 * and should be dropped.
100 return iter->used >= 2 &&
101 !bkey_cmp_packed(iter->b,
107 bch2_key_sort_fix_overlapping(struct bch_fs *c, struct bset *dst,
108 struct sort_iter *iter)
110 struct bkey_packed *out = dst->start;
111 struct bkey_packed *k;
112 struct btree_nr_keys nr;
114 memset(&nr, 0, sizeof(nr));
116 sort_iter_sort(iter, key_sort_fix_overlapping_cmp);
118 while ((k = sort_iter_peek(iter))) {
119 if (!bkey_whiteout(k) &&
120 !should_drop_next_key(iter)) {
122 btree_keys_account_key_add(&nr, 0, out);
123 out = bkey_next(out);
126 sort_iter_advance(iter, key_sort_fix_overlapping_cmp);
129 dst->u64s = cpu_to_le16((u64 *) out - dst->_data);
134 * If keys compare equal, compare by pointer order:
136 * Necessary for sort_fix_overlapping() - if there are multiple keys that
137 * compare equal in different sets, we have to process them newest to oldest.
139 static inline int extent_sort_fix_overlapping_cmp(struct btree *b,
140 struct bkey_packed *l,
141 struct bkey_packed *r)
143 struct bkey ul = bkey_unpack_key(b, l);
144 struct bkey ur = bkey_unpack_key(b, r);
146 return bkey_cmp(bkey_start_pos(&ul),
147 bkey_start_pos(&ur)) ?:
148 cmp_int((unsigned long) r, (unsigned long) l);
151 static void extent_sort_advance_prev(struct bkey_format *f,
152 struct btree_nr_keys *nr,
153 struct bkey_packed *start,
154 struct bkey_packed **prev)
157 bch2_bkey_pack(*prev, (void *) *prev, f);
159 btree_keys_account_key_add(nr, 0, *prev);
160 *prev = bkey_next(*prev);
166 static void extent_sort_append(struct bch_fs *c,
167 struct bkey_format *f,
168 struct btree_nr_keys *nr,
169 struct bkey_packed *start,
170 struct bkey_packed **prev,
173 if (bkey_whiteout(k.k))
177 * prev is always unpacked, for key merging - until right before we
182 bch2_bkey_merge(c, bkey_i_to_s((void *) *prev), k) ==
186 extent_sort_advance_prev(f, nr, start, prev);
188 bkey_reassemble((void *) *prev, k.s_c);
192 bch2_extent_sort_fix_overlapping(struct bch_fs *c, struct bset *dst,
193 struct sort_iter *iter)
195 struct btree *b = iter->b;
196 struct bkey_format *f = &b->format;
197 struct sort_iter_set *_l = iter->data, *_r = iter->data + 1;
198 struct bkey_packed *prev = NULL;
199 struct bkey l_unpacked, r_unpacked;
201 struct btree_nr_keys nr;
202 struct bkey_on_stack split;
204 memset(&nr, 0, sizeof(nr));
205 bkey_on_stack_init(&split);
207 sort_iter_sort(iter, extent_sort_fix_overlapping_cmp);
209 while (!sort_iter_end(iter)) {
210 l = __bkey_disassemble(b, _l->k, &l_unpacked);
212 if (iter->used == 1) {
213 extent_sort_append(c, f, &nr, dst->start, &prev, l);
214 sort_iter_advance(iter,
215 extent_sort_fix_overlapping_cmp);
219 r = __bkey_disassemble(b, _r->k, &r_unpacked);
221 /* If current key and next key don't overlap, just append */
222 if (bkey_cmp(l.k->p, bkey_start_pos(r.k)) <= 0) {
223 extent_sort_append(c, f, &nr, dst->start, &prev, l);
224 sort_iter_advance(iter,
225 extent_sort_fix_overlapping_cmp);
229 /* Skip 0 size keys */
231 __sort_iter_advance(iter, 1,
232 extent_sort_fix_overlapping_cmp);
237 * overlap: keep the newer key and trim the older key so they
238 * don't overlap. comparing pointers tells us which one is
239 * newer, since the bsets are appended one after the other.
242 /* can't happen because of comparison func */
243 BUG_ON(_l->k < _r->k &&
244 !bkey_cmp(bkey_start_pos(l.k), bkey_start_pos(r.k)));
248 if (bkey_cmp(l.k->p, r.k->p) >= 0) {
249 __sort_iter_advance(iter, 1,
250 extent_sort_fix_overlapping_cmp);
252 bch2_cut_front_s(l.k->p, r);
253 extent_save(b, _r->k, r.k);
254 __sort_iter_sift(iter, 1,
255 extent_sort_fix_overlapping_cmp);
257 } else if (bkey_cmp(l.k->p, r.k->p) > 0) {
260 * r wins, but it overlaps in the middle of l - split l:
262 bkey_on_stack_reassemble(&split, c, l.s_c);
263 bch2_cut_back(bkey_start_pos(r.k), split.k);
265 bch2_cut_front_s(r.k->p, l);
266 extent_save(b, _l->k, l.k);
268 __sort_iter_sift(iter, 0,
269 extent_sort_fix_overlapping_cmp);
271 extent_sort_append(c, f, &nr, dst->start,
272 &prev, bkey_i_to_s(split.k));
274 bch2_cut_back_s(bkey_start_pos(r.k), l);
275 extent_save(b, _l->k, l.k);
279 extent_sort_advance_prev(f, &nr, dst->start, &prev);
281 dst->u64s = cpu_to_le16((u64 *) prev - dst->_data);
283 bkey_on_stack_exit(&split, c);
287 /* Sort + repack in a new format: */
289 bch2_sort_repack(struct bset *dst, struct btree *src,
290 struct btree_node_iter *src_iter,
291 struct bkey_format *out_f,
292 bool filter_whiteouts)
294 struct bkey_format *in_f = &src->format;
295 struct bkey_packed *in, *out = vstruct_last(dst);
296 struct btree_nr_keys nr;
298 memset(&nr, 0, sizeof(nr));
300 while ((in = bch2_btree_node_iter_next_all(src_iter, src))) {
301 if (filter_whiteouts && bkey_whiteout(in))
304 if (bch2_bkey_transform(out_f, out, bkey_packed(in)
305 ? in_f : &bch2_bkey_format_current, in))
306 out->format = KEY_FORMAT_LOCAL_BTREE;
308 bch2_bkey_unpack(src, (void *) out, in);
310 btree_keys_account_key_add(&nr, 0, out);
311 out = bkey_next(out);
314 dst->u64s = cpu_to_le16((u64 *) out - dst->_data);
318 /* Sort, repack, and merge: */
320 bch2_sort_repack_merge(struct bch_fs *c,
321 struct bset *dst, struct btree *src,
322 struct btree_node_iter *iter,
323 struct bkey_format *out_f,
324 bool filter_whiteouts)
326 struct bkey_packed *prev = NULL, *k_packed;
328 struct btree_nr_keys nr;
329 struct bkey unpacked;
331 memset(&nr, 0, sizeof(nr));
333 while ((k_packed = bch2_btree_node_iter_next_all(iter, src))) {
334 if (filter_whiteouts && bkey_whiteout(k_packed))
337 k = __bkey_disassemble(src, k_packed, &unpacked);
339 if (filter_whiteouts &&
340 bch2_bkey_normalize(c, k))
343 extent_sort_append(c, out_f, &nr, vstruct_last(dst), &prev, k);
346 extent_sort_advance_prev(out_f, &nr, vstruct_last(dst), &prev);
348 dst->u64s = cpu_to_le16((u64 *) prev - dst->_data);
352 static inline int sort_keys_cmp(struct btree *b,
353 struct bkey_packed *l,
354 struct bkey_packed *r)
356 return bkey_cmp_packed(b, l, r) ?:
357 (int) bkey_whiteout(r) - (int) bkey_whiteout(l) ?:
358 (int) l->needs_whiteout - (int) r->needs_whiteout;
361 unsigned bch2_sort_keys(struct bkey_packed *dst,
362 struct sort_iter *iter,
363 bool filter_whiteouts)
365 const struct bkey_format *f = &iter->b->format;
366 struct bkey_packed *in, *next, *out = dst;
368 sort_iter_sort(iter, sort_keys_cmp);
370 while ((in = sort_iter_next(iter, sort_keys_cmp))) {
371 if (bkey_whiteout(in) &&
372 (filter_whiteouts || !in->needs_whiteout))
375 if (bkey_whiteout(in) &&
376 (next = sort_iter_peek(iter)) &&
377 !bkey_cmp_packed(iter->b, in, next)) {
378 BUG_ON(in->needs_whiteout &&
379 next->needs_whiteout);
381 * XXX racy, called with read lock from write path
383 * leads to spurious BUG_ON() in bkey_unpack_key() in
386 next->needs_whiteout |= in->needs_whiteout;
390 if (bkey_whiteout(in)) {
391 memcpy_u64s(out, in, bkeyp_key_u64s(f, in));
392 set_bkeyp_val_u64s(f, out, 0);
396 out = bkey_next(out);
399 return (u64 *) out - (u64 *) dst;
402 static inline int sort_extents_cmp(struct btree *b,
403 struct bkey_packed *l,
404 struct bkey_packed *r)
406 return bkey_cmp_packed(b, l, r) ?:
407 (int) bkey_deleted(l) - (int) bkey_deleted(r);
410 unsigned bch2_sort_extents(struct bkey_packed *dst,
411 struct sort_iter *iter,
412 bool filter_whiteouts)
414 struct bkey_packed *in, *out = dst;
416 sort_iter_sort(iter, sort_extents_cmp);
418 while ((in = sort_iter_next(iter, sort_extents_cmp))) {
419 if (bkey_deleted(in))
422 if (bkey_whiteout(in) &&
423 (filter_whiteouts || !in->needs_whiteout))
427 out = bkey_next(out);
430 return (u64 *) out - (u64 *) dst;
433 static inline int sort_extent_whiteouts_cmp(struct btree *b,
434 struct bkey_packed *l,
435 struct bkey_packed *r)
437 struct bkey ul = bkey_unpack_key(b, l);
438 struct bkey ur = bkey_unpack_key(b, r);
440 return bkey_cmp(bkey_start_pos(&ul), bkey_start_pos(&ur));
443 unsigned bch2_sort_extent_whiteouts(struct bkey_packed *dst,
444 struct sort_iter *iter)
446 const struct bkey_format *f = &iter->b->format;
447 struct bkey_packed *in, *out = dst;
449 bool prev = false, l_packed = false;
450 u64 max_packed_size = bkey_field_max(f, BKEY_FIELD_SIZE);
451 u64 max_packed_offset = bkey_field_max(f, BKEY_FIELD_OFFSET);
454 max_packed_size = min_t(u64, max_packed_size, KEY_SIZE_MAX);
456 sort_iter_sort(iter, sort_extent_whiteouts_cmp);
458 while ((in = sort_iter_next(iter, sort_extent_whiteouts_cmp))) {
459 if (bkey_deleted(in))
462 EBUG_ON(bkeyp_val_u64s(f, in));
463 EBUG_ON(in->type != KEY_TYPE_discard);
465 r.k = bkey_unpack_key(iter->b, in);
468 bkey_cmp(l.k.p, bkey_start_pos(&r.k)) >= 0) {
469 if (bkey_cmp(l.k.p, r.k.p) >= 0)
473 ? min(max_packed_size, max_packed_offset -
474 bkey_start_offset(&l.k))
477 new_size = min(new_size, r.k.p.offset -
478 bkey_start_offset(&l.k));
480 BUG_ON(new_size < l.k.size);
482 bch2_key_resize(&l.k, new_size);
484 if (bkey_cmp(l.k.p, r.k.p) >= 0)
487 bch2_cut_front(l.k.p, &r);
491 if (!bch2_bkey_pack(out, &l, f)) {
495 out = bkey_next(out);
500 l_packed = bkey_packed(in);
504 if (!bch2_bkey_pack(out, &l, f)) {
508 out = bkey_next(out);
511 return (u64 *) out - (u64 *) dst;