]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
bcachefs: Coalesce accounting keys before journal replay
authorKent Overstreet <kent.overstreet@linux.dev>
Tue, 4 Jun 2024 22:31:13 +0000 (18:31 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 14 Jul 2024 23:00:13 +0000 (19:00 -0400)
This fixes a performance regression in journal replay; without
colaescing accounting keys we have multiple keys at the same position,
which means journal_keys_peek_upto() has to skip past many overwritten
keys - turning journal replay into an O(n^2) algorithm.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_journal_iter.h
fs/bcachefs/disk_accounting.c

index 5b66c8f85fc1ba02bc0df821b38f24227897eb65..1653de9d609bc71d75f50210a67aee14ede1cdda 100644 (file)
@@ -2,6 +2,8 @@
 #ifndef _BCACHEFS_BTREE_JOURNAL_ITER_H
 #define _BCACHEFS_BTREE_JOURNAL_ITER_H
 
+#include "bkey.h"
+
 struct journal_iter {
        struct list_head        list;
        enum btree_id           btree_id;
index 2cc2e0f8cb538d4d27083f1bd333f012e78d51b1..dbdc16f2fc1c857660e341ee27c3f1146b7e2fa9 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "bcachefs.h"
 #include "bcachefs_ioctl.h"
+#include "btree_journal_iter.h"
 #include "btree_update.h"
 #include "btree_write_buffer.h"
 #include "buckets.h"
@@ -344,7 +345,9 @@ int bch2_accounting_read(struct bch_fs *c)
                goto err;
 
        struct journal_keys *keys = &c->journal_keys;
+       struct journal_key *dst = keys->data;
        move_gap(keys, keys->nr);
+
        darray_for_each(*keys, i) {
                if (i->k->k.type == KEY_TYPE_accounting) {
                        struct bkey_s_c k = bkey_i_to_s_c(i->k);
@@ -358,11 +361,26 @@ int bch2_accounting_read(struct bch_fs *c)
                        if (applied)
                                continue;
 
+                       if (i + 1 < &darray_top(*keys) &&
+                           i[1].k->k.type == KEY_TYPE_accounting &&
+                           !journal_key_cmp(i, i + 1)) {
+                               BUG_ON(bversion_cmp(i[0].k->k.version, i[1].k->k.version) >= 0);
+
+                               i[1].journal_seq = i[0].journal_seq;
+
+                               bch2_accounting_accumulate(bkey_i_to_accounting(i[1].k),
+                                                          bkey_s_c_to_accounting(k));
+                               continue;
+                       }
+
                        ret = accounting_read_key(c, k);
                        if (ret)
                                goto err;
                }
+
+               *dst++ = *i;
        }
+       keys->gap = keys->nr = dst - keys->data;
 
        percpu_down_read(&c->mark_lock);
        preempt_disable();