bkey_sort.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include "bcachefs.h"
  3. #include "bkey_buf.h"
  4. #include "bkey_cmp.h"
  5. #include "bkey_sort.h"
  6. #include "bset.h"
  7. #include "extents.h"
  8. typedef int (*sort_cmp_fn)(const struct btree *,
  9. const struct bkey_packed *,
  10. const struct bkey_packed *);
  11. static inline bool sort_iter_end(struct sort_iter *iter)
  12. {
  13. return !iter->used;
  14. }
  15. static inline void sort_iter_sift(struct sort_iter *iter, unsigned from,
  16. sort_cmp_fn cmp)
  17. {
  18. unsigned i;
  19. for (i = from;
  20. i + 1 < iter->used &&
  21. cmp(iter->b, iter->data[i].k, iter->data[i + 1].k) > 0;
  22. i++)
  23. swap(iter->data[i], iter->data[i + 1]);
  24. }
  25. static inline void sort_iter_sort(struct sort_iter *iter, sort_cmp_fn cmp)
  26. {
  27. unsigned i = iter->used;
  28. while (i--)
  29. sort_iter_sift(iter, i, cmp);
  30. }
  31. static inline struct bkey_packed *sort_iter_peek(struct sort_iter *iter)
  32. {
  33. return !sort_iter_end(iter) ? iter->data->k : NULL;
  34. }
  35. static inline void sort_iter_advance(struct sort_iter *iter, sort_cmp_fn cmp)
  36. {
  37. struct sort_iter_set *i = iter->data;
  38. BUG_ON(!iter->used);
  39. i->k = bkey_p_next(i->k);
  40. BUG_ON(i->k > i->end);
  41. if (i->k == i->end)
  42. array_remove_item(iter->data, iter->used, 0);
  43. else
  44. sort_iter_sift(iter, 0, cmp);
  45. }
  46. static inline struct bkey_packed *sort_iter_next(struct sort_iter *iter,
  47. sort_cmp_fn cmp)
  48. {
  49. struct bkey_packed *ret = sort_iter_peek(iter);
  50. if (ret)
  51. sort_iter_advance(iter, cmp);
  52. return ret;
  53. }
  54. /*
  55. * If keys compare equal, compare by pointer order:
  56. */
  57. static inline int key_sort_fix_overlapping_cmp(const struct btree *b,
  58. const struct bkey_packed *l,
  59. const struct bkey_packed *r)
  60. {
  61. return bch2_bkey_cmp_packed(b, l, r) ?:
  62. cmp_int((unsigned long) l, (unsigned long) r);
  63. }
  64. static inline bool should_drop_next_key(struct sort_iter *iter)
  65. {
  66. /*
  67. * key_sort_cmp() ensures that when keys compare equal the older key
  68. * comes first; so if l->k compares equal to r->k then l->k is older
  69. * and should be dropped.
  70. */
  71. return iter->used >= 2 &&
  72. !bch2_bkey_cmp_packed(iter->b,
  73. iter->data[0].k,
  74. iter->data[1].k);
  75. }
  76. struct btree_nr_keys
  77. bch2_key_sort_fix_overlapping(struct bch_fs *c, struct bset *dst,
  78. struct sort_iter *iter)
  79. {
  80. struct bkey_packed *out = dst->start;
  81. struct bkey_packed *k;
  82. struct btree_nr_keys nr;
  83. memset(&nr, 0, sizeof(nr));
  84. sort_iter_sort(iter, key_sort_fix_overlapping_cmp);
  85. while ((k = sort_iter_peek(iter))) {
  86. if (!bkey_deleted(k) &&
  87. !should_drop_next_key(iter)) {
  88. bkey_p_copy(out, k);
  89. btree_keys_account_key_add(&nr, 0, out);
  90. out = bkey_p_next(out);
  91. }
  92. sort_iter_advance(iter, key_sort_fix_overlapping_cmp);
  93. }
  94. dst->u64s = cpu_to_le16((u64 *) out - dst->_data);
  95. return nr;
  96. }
  97. /* Sort + repack in a new format: */
  98. struct btree_nr_keys
  99. bch2_sort_repack(struct bset *dst, struct btree *src,
  100. struct btree_node_iter *src_iter,
  101. struct bkey_format *out_f,
  102. bool filter_whiteouts)
  103. {
  104. struct bkey_format *in_f = &src->format;
  105. struct bkey_packed *in, *out = vstruct_last(dst);
  106. struct btree_nr_keys nr;
  107. bool transform = memcmp(out_f, &src->format, sizeof(*out_f));
  108. memset(&nr, 0, sizeof(nr));
  109. while ((in = bch2_btree_node_iter_next_all(src_iter, src))) {
  110. if (filter_whiteouts && bkey_deleted(in))
  111. continue;
  112. if (!transform)
  113. bkey_p_copy(out, in);
  114. else if (bch2_bkey_transform(out_f, out, bkey_packed(in)
  115. ? in_f : &bch2_bkey_format_current, in))
  116. out->format = KEY_FORMAT_LOCAL_BTREE;
  117. else
  118. bch2_bkey_unpack(src, (void *) out, in);
  119. out->needs_whiteout = false;
  120. btree_keys_account_key_add(&nr, 0, out);
  121. out = bkey_p_next(out);
  122. }
  123. dst->u64s = cpu_to_le16((u64 *) out - dst->_data);
  124. return nr;
  125. }
  126. static inline int keep_unwritten_whiteouts_cmp(const struct btree *b,
  127. const struct bkey_packed *l,
  128. const struct bkey_packed *r)
  129. {
  130. return bch2_bkey_cmp_packed_inlined(b, l, r) ?:
  131. (int) bkey_deleted(r) - (int) bkey_deleted(l) ?:
  132. (long) l - (long) r;
  133. }
  134. #include "btree_update_interior.h"
  135. /*
  136. * For sorting in the btree node write path: whiteouts not in the unwritten
  137. * whiteouts area are dropped, whiteouts in the unwritten whiteouts area are
  138. * dropped if overwritten by real keys:
  139. */
  140. unsigned bch2_sort_keys_keep_unwritten_whiteouts(struct bkey_packed *dst, struct sort_iter *iter)
  141. {
  142. struct bkey_packed *in, *next, *out = dst;
  143. sort_iter_sort(iter, keep_unwritten_whiteouts_cmp);
  144. while ((in = sort_iter_next(iter, keep_unwritten_whiteouts_cmp))) {
  145. if (bkey_deleted(in) && in < unwritten_whiteouts_start(iter->b))
  146. continue;
  147. if ((next = sort_iter_peek(iter)) &&
  148. !bch2_bkey_cmp_packed_inlined(iter->b, in, next))
  149. continue;
  150. bkey_p_copy(out, in);
  151. out = bkey_p_next(out);
  152. }
  153. return (u64 *) out - (u64 *) dst;
  154. }
  155. /*
  156. * Main sort routine for compacting a btree node in memory: we always drop
  157. * whiteouts because any whiteouts that need to be written are in the unwritten
  158. * whiteouts area:
  159. */
  160. unsigned bch2_sort_keys(struct bkey_packed *dst, struct sort_iter *iter)
  161. {
  162. struct bkey_packed *in, *out = dst;
  163. sort_iter_sort(iter, bch2_bkey_cmp_packed_inlined);
  164. while ((in = sort_iter_next(iter, bch2_bkey_cmp_packed_inlined))) {
  165. if (bkey_deleted(in))
  166. continue;
  167. bkey_p_copy(out, in);
  168. out = bkey_p_next(out);
  169. }
  170. return (u64 *) out - (u64 *) dst;
  171. }