bcachefs: Re-implement extent merging in transaction commit path
authorKent Overstreet <kent.overstreet@gmail.com>
Thu, 29 Apr 2021 03:52:19 +0000 (23:52 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:06 +0000 (17:09 -0400)
We haven't had extent merging in quite some time. It used to be done by
the btree code when sorting btree nodes, but that was eliminated as part
of the work to separate extent handling from core btree code.

This patch re-implements extent merging in the transaction commit path.
We don't currently have the ability to merge reflink pointers, we need
to do some work on the triggers code to be able to do that without
ending up with incorrect refcounts.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
fs/bcachefs/bkey_methods.c
fs/bcachefs/bkey_methods.h
fs/bcachefs/btree_update_leaf.c

index ff9d770aabea452e738884a8670d09e99c9ce8b9..1ad6a9d30bb54c37cca80bac1bda253fab98a49b 100644 (file)
@@ -296,7 +296,11 @@ bool bch2_bkey_merge(struct bch_fs *c, struct bkey_s l, struct bkey_s_c r)
 {
        const struct bkey_ops *ops = &bch2_bkey_ops[l.k->type];
 
-       return bch2_bkey_maybe_mergable(l.k, r.k) && ops->key_merge(c, l, r);
+       return bch2_bkey_maybe_mergable(l.k, r.k) &&
+               (u64) l.k->size + r.k->size <= KEY_SIZE_MAX &&
+               bch2_bkey_ops[l.k->type].key_merge &&
+               !bch2_key_merging_disabled &&
+               ops->key_merge(c, l, r);
 }
 
 static const struct old_bkey_type {
index 3012035db1a33b3acd902563c0a7ea70c2718108..4e316c2f695411da7245b3e9bf2b5807d451e2b5 100644 (file)
@@ -51,10 +51,7 @@ static inline bool bch2_bkey_maybe_mergable(const struct bkey *l, const struct b
 {
        return l->type == r->type &&
                !bversion_cmp(l->version, r->version) &&
-               !bpos_cmp(l->p, bkey_start_pos(r)) &&
-               (u64) l->size + r->size <= KEY_SIZE_MAX &&
-               bch2_bkey_ops[l->type].key_merge &&
-               !bch2_key_merging_disabled;
+               !bpos_cmp(l->p, bkey_start_pos(r));
 }
 
 bool bch2_bkey_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c);
index 1c12a11e45f7a28141ebd84dd1aad950fa0c6b67..4040771d645bacb2b39c23d69742953d38b21257 100644 (file)
@@ -797,9 +797,38 @@ static int __btree_delete_at(struct btree_trans *trans, enum btree_id btree_id,
        return 0;
 }
 
+static noinline int extent_front_merge(struct btree_trans *trans,
+                                      struct bkey_s_c k,
+                                      struct btree_insert_entry *i)
+{
+       struct bch_fs *c = trans->c;
+       struct bpos l_pos = k.k->p;
+       struct bkey_i *update;
+       int ret;
+
+       update = bch2_trans_kmalloc(trans, bkey_bytes(k.k));
+       ret = PTR_ERR_OR_ZERO(update);
+       if (ret)
+               return ret;
+
+       bkey_reassemble(update, k);
+
+       if (bch2_bkey_merge(c, bkey_i_to_s(update), bkey_i_to_s_c(i->k))) {
+               ret = __btree_delete_at(trans, i->btree_id, l_pos,
+                                       i->trigger_flags);
+               if (ret)
+                       return ret;
+
+               i->k = update;
+       }
+
+       return 0;
+}
+
 static int extent_handle_overwrites(struct btree_trans *trans,
                                    struct btree_insert_entry *i)
 {
+       struct bch_fs *c = trans->c;
        struct btree_iter *iter, *update_iter;
        struct bpos start = bkey_start_pos(&i->k->k);
        struct bkey_i *update;
@@ -814,8 +843,15 @@ static int extent_handle_overwrites(struct btree_trans *trans,
        if (!k.k || (ret = bkey_err(k)))
                goto out;
 
-       if (!bkey_cmp(k.k->p, bkey_start_pos(&i->k->k)))
+       if (!bkey_cmp(k.k->p, bkey_start_pos(&i->k->k))) {
+               if (bch2_bkey_maybe_mergable(k.k, &i->k->k)) {
+                       ret = extent_front_merge(trans, k, i);
+                       if (ret)
+                               goto out;
+               }
+
                goto next;
+       }
 
        while (bkey_cmp(i->k->k.p, bkey_start_pos(k.k)) > 0) {
                if (bkey_cmp(bkey_start_pos(k.k), start) < 0) {
@@ -862,6 +898,9 @@ next:
                if (!k.k || (ret = bkey_err(k)))
                        goto out;
        }
+
+       if (bch2_bkey_maybe_mergable(&i->k->k, k.k))
+               bch2_bkey_merge(c, bkey_i_to_s(i->k), k);
 out:
        bch2_trans_iter_put(trans, iter);