summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/md/bcache/bset.c100
1 files changed, 73 insertions, 27 deletions
diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c
index 50964d1473ec..494622b0bb97 100644
--- a/drivers/md/bcache/bset.c
+++ b/drivers/md/bcache/bset.c
@@ -1312,17 +1312,18 @@ int bch_bset_sort_state_init(struct bset_sort_state *state, unsigned page_order)
}
EXPORT_SYMBOL(bch_bset_sort_state_init);
+/* No repacking: */
static void btree_mergesort_simple(struct btree_keys *b, struct bset *bset,
struct btree_node_iter *iter)
{
- struct bkey_packed *k, *out = bset->start;
+ struct bkey_packed *in, *out = bset->start;
while (!bch_btree_node_iter_end(iter)) {
- k = bch_btree_node_iter_next_all(iter, b);
+ in = bch_btree_node_iter_next_all(iter, b);
- if (!bkey_deleted(k)) {
+ if (!bkey_deleted(in)) {
/* XXX: need better bkey_copy */
- memcpy(out, k, bkey_bytes(k));
+ memcpy(out, in, bkey_bytes(in));
out = bkey_next(out);
}
}
@@ -1332,6 +1333,7 @@ static void btree_mergesort_simple(struct btree_keys *b, struct bset *bset,
pr_debug("sorted %i keys", bset->u64s);
}
+/* Sort + repack in a new format: */
static void btree_mergesort(struct btree_keys *dst,
struct bset *dst_set,
struct btree_keys *src,
@@ -1340,11 +1342,55 @@ static void btree_mergesort(struct btree_keys *dst,
{
struct bkey_format *in_f = &src->format;
struct bkey_format *out_f = &dst->format;
+ struct bkey_packed *in, *out = dst_set->start;
+
+ BUG_ON(filter);
+ EBUG_ON(filter && !dst->ops->is_extents);
+
+ dst->nr_packed_keys = 0;
+ dst->nr_unpacked_keys = 0;
+
+ while (!bch_btree_node_iter_end(iter)) {
+ in = bch_btree_node_iter_next_all(iter, src);
+
+ if (bkey_deleted(in))
+ continue;
+
+ if (bch_bkey_transform(out_f, out, bkey_packed(in)
+ ? in_f : &bch_bkey_format_current, in)) {
+ out->format = KEY_FORMAT_LOCAL_BTREE;
+ dst->nr_packed_keys++;
+ } else {
+ bkey_unpack((void *) out, in_f, in);
+ dst->nr_unpacked_keys++;
+ }
+
+ out = bkey_next(out);
+
+ BUG_ON((void *) out >
+ (void *) dst_set + (PAGE_SIZE << dst->page_order));
+ }
+
+ dst_set->u64s = (u64 *) out - dst_set->_data;
+ dst->nr_live_u64s = dst_set->u64s;
+
+ pr_debug("sorted %i keys", dst_set->u64s);
+}
+
+/* Sort, repack, and merge extents */
+static void btree_mergesort_extents(struct btree_keys *dst,
+ struct bset *dst_set,
+ struct btree_keys *src,
+ struct btree_node_iter *iter,
+ ptr_filter_fn filter)
+{
+ struct bkey_format *in_f = &src->format;
+ struct bkey_format *out_f = &dst->format;
struct bkey_packed *k, *prev = NULL, *out = dst_set->start;
struct bkey_tup tup;
BKEY_PADDED(k) tmp;
- EBUG_ON(filter && !dst->ops->is_extents);
+ EBUG_ON(!dst->ops->is_extents);
dst->nr_packed_keys = 0;
dst->nr_unpacked_keys = 0;
@@ -1355,26 +1401,21 @@ static void btree_mergesort(struct btree_keys *dst,
if (bkey_deleted(k))
continue;
- if (dst->ops->is_extents) {
- /*
- * For extents, the filter might modify pointers, so we
- * have to unpack the key and values to &tmp.k.
- */
- bkey_unpack(&tmp.k, in_f, k);
+ /*
+ * The filter might modify pointers, so we have to unpack the
+ * key and values to &tmp.k:
+ */
+ bkey_unpack(&tmp.k, in_f, k);
- if (filter && filter(src, bkey_i_to_s(&tmp.k)))
- continue;
+ if (filter && filter(src, bkey_i_to_s(&tmp.k)))
+ continue;
- if (prev &&
- src->ops->key_merge &&
- bch_bkey_try_merge(src, (void *) prev, &tmp.k))
- continue;
+ if (prev &&
+ src->ops->key_merge &&
+ bch_bkey_try_merge(src, (void *) prev, &tmp.k))
+ continue;
- bkey_disassemble(&tup, in_f, bkey_to_packed(&tmp.k));
- } else {
- /* We're not touching values -- only copy the key */
- bkey_disassemble(&tup, in_f, k);
- }
+ bkey_disassemble(&tup, in_f, bkey_to_packed(&tmp.k));
if (prev) {
if (bkey_pack(prev, (void *) prev, out_f))
@@ -1441,15 +1482,16 @@ static void __btree_sort(struct btree_keys *b, struct btree_node_iter *iter,
*/
if (sort)
sort(b, out, iter);
- else if (start)
- btree_mergesort_simple(b, out, iter);
+ else if (b->ops->is_extents && !start)
+ btree_mergesort_extents(b, out, b, iter, NULL);
else
- btree_mergesort(b, out, b, iter, NULL);
+ btree_mergesort_simple(b, out, iter);
BUG_ON(set_bytes(out) > (PAGE_SIZE << b->page_order));
b->nsets = start;
+ /* XXX: reenable */
if (0 && !start && order == b->page_order) {
unsigned u64s = out->u64s;
/*
@@ -1530,8 +1572,12 @@ void bch_btree_sort_into(struct btree_keys *dst,
bch_btree_node_iter_init_from_start(&iter, src);
- btree_mergesort(dst, dst->set->data,
- src, &iter, filter);
+ if (!dst->ops->is_extents)
+ btree_mergesort(dst, dst->set->data,
+ src, &iter, filter);
+ else
+ btree_mergesort_extents(dst, dst->set->data,
+ src, &iter, filter);
BUG_ON(set_bytes(dst->set->data) > (PAGE_SIZE << dst->page_order));