Commit 5f43b013 authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: btree node prefetching in check_topology

btree_and_journal_iter is old code that we want to get rid of, but we're
not ready to yet.

lack of btree node prefetching is, it turns out, a real performance
issue for fsck on spinning rust, so - add it.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent fc634d8e
...@@ -711,6 +711,9 @@ static noinline struct btree *bch2_btree_node_fill(struct btree_trans *trans, ...@@ -711,6 +711,9 @@ static noinline struct btree *bch2_btree_node_fill(struct btree_trans *trans,
b = bch2_btree_node_mem_alloc(trans, level != 0); b = bch2_btree_node_mem_alloc(trans, level != 0);
if (bch2_err_matches(PTR_ERR_OR_ZERO(b), ENOMEM)) { if (bch2_err_matches(PTR_ERR_OR_ZERO(b), ENOMEM)) {
if (!path)
return b;
trans->memory_allocation_failure = true; trans->memory_allocation_failure = true;
trace_and_count(c, trans_restart_memory_allocation_failure, trans, _THIS_IP_, path); trace_and_count(c, trans_restart_memory_allocation_failure, trans, _THIS_IP_, path);
return ERR_PTR(btree_trans_restart(trans, BCH_ERR_transaction_restart_fill_mem_alloc_fail)); return ERR_PTR(btree_trans_restart(trans, BCH_ERR_transaction_restart_fill_mem_alloc_fail));
...@@ -760,7 +763,8 @@ static noinline struct btree *bch2_btree_node_fill(struct btree_trans *trans, ...@@ -760,7 +763,8 @@ static noinline struct btree *bch2_btree_node_fill(struct btree_trans *trans,
} }
if (!six_relock_type(&b->c.lock, lock_type, seq)) { if (!six_relock_type(&b->c.lock, lock_type, seq)) {
if (path) BUG_ON(!path);
trace_and_count(c, trans_restart_relock_after_fill, trans, _THIS_IP_, path); trace_and_count(c, trans_restart_relock_after_fill, trans, _THIS_IP_, path);
return ERR_PTR(btree_trans_restart(trans, BCH_ERR_transaction_restart_relock_after_fill)); return ERR_PTR(btree_trans_restart(trans, BCH_ERR_transaction_restart_relock_after_fill));
} }
...@@ -1096,7 +1100,7 @@ int bch2_btree_node_prefetch(struct btree_trans *trans, ...@@ -1096,7 +1100,7 @@ int bch2_btree_node_prefetch(struct btree_trans *trans,
struct btree_cache *bc = &c->btree_cache; struct btree_cache *bc = &c->btree_cache;
struct btree *b; struct btree *b;
BUG_ON(trans && !btree_node_locked(path, level + 1)); BUG_ON(path && !btree_node_locked(path, level + 1));
BUG_ON(level >= BTREE_MAX_DEPTH); BUG_ON(level >= BTREE_MAX_DEPTH);
b = btree_cache_find(bc, k); b = btree_cache_find(bc, k);
......
...@@ -390,6 +390,7 @@ static int bch2_btree_repair_topology_recurse(struct btree_trans *trans, struct ...@@ -390,6 +390,7 @@ static int bch2_btree_repair_topology_recurse(struct btree_trans *trans, struct
bch2_bkey_buf_init(&prev_k); bch2_bkey_buf_init(&prev_k);
bch2_bkey_buf_init(&cur_k); bch2_bkey_buf_init(&cur_k);
bch2_btree_and_journal_iter_init_node_iter(trans, &iter, b); bch2_btree_and_journal_iter_init_node_iter(trans, &iter, b);
iter.prefetch = true;
while ((k = bch2_btree_and_journal_iter_peek(&iter)).k) { while ((k = bch2_btree_and_journal_iter_peek(&iter)).k) {
BUG_ON(bpos_lt(k.k->p, b->data->min_key)); BUG_ON(bpos_lt(k.k->p, b->data->min_key));
...@@ -479,6 +480,7 @@ static int bch2_btree_repair_topology_recurse(struct btree_trans *trans, struct ...@@ -479,6 +480,7 @@ static int bch2_btree_repair_topology_recurse(struct btree_trans *trans, struct
bch2_btree_and_journal_iter_exit(&iter); bch2_btree_and_journal_iter_exit(&iter);
bch2_btree_and_journal_iter_init_node_iter(trans, &iter, b); bch2_btree_and_journal_iter_init_node_iter(trans, &iter, b);
iter.prefetch = true;
while ((k = bch2_btree_and_journal_iter_peek(&iter)).k) { while ((k = bch2_btree_and_journal_iter_peek(&iter)).k) {
bch2_bkey_buf_reassemble(&cur_k, c, k); bch2_bkey_buf_reassemble(&cur_k, c, k);
...@@ -964,6 +966,7 @@ static int bch2_gc_btree_init_recurse(struct btree_trans *trans, struct btree *b ...@@ -964,6 +966,7 @@ static int bch2_gc_btree_init_recurse(struct btree_trans *trans, struct btree *b
if (b->c.level > target_depth) { if (b->c.level > target_depth) {
bch2_btree_and_journal_iter_exit(&iter); bch2_btree_and_journal_iter_exit(&iter);
bch2_btree_and_journal_iter_init_node_iter(trans, &iter, b); bch2_btree_and_journal_iter_init_node_iter(trans, &iter, b);
iter.prefetch = true;
while ((k = bch2_btree_and_journal_iter_peek(&iter)).k) { while ((k = bch2_btree_and_journal_iter_peek(&iter)).k) {
struct btree *child; struct btree *child;
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include "bcachefs.h" #include "bcachefs.h"
#include "bkey_buf.h"
#include "bset.h" #include "bset.h"
#include "btree_cache.h"
#include "btree_journal_iter.h" #include "btree_journal_iter.h"
#include "journal_io.h" #include "journal_io.h"
...@@ -334,9 +336,38 @@ void bch2_btree_and_journal_iter_advance(struct btree_and_journal_iter *iter) ...@@ -334,9 +336,38 @@ void bch2_btree_and_journal_iter_advance(struct btree_and_journal_iter *iter)
iter->pos = bpos_successor(iter->pos); iter->pos = bpos_successor(iter->pos);
} }
static void btree_and_journal_iter_prefetch(struct btree_and_journal_iter *_iter)
{
struct btree_and_journal_iter iter = *_iter;
struct bch_fs *c = iter.trans->c;
unsigned level = iter.journal.level;
struct bkey_buf tmp;
unsigned nr = test_bit(BCH_FS_started, &c->flags)
? (level > 1 ? 0 : 2)
: (level > 1 ? 1 : 16);
iter.prefetch = false;
bch2_bkey_buf_init(&tmp);
while (nr--) {
bch2_btree_and_journal_iter_advance(&iter);
struct bkey_s_c k = bch2_btree_and_journal_iter_peek(&iter);
if (!k.k)
break;
bch2_bkey_buf_reassemble(&tmp, c, k);
bch2_btree_node_prefetch(iter.trans, NULL, tmp.k, iter.journal.btree_id, level - 1);
}
bch2_bkey_buf_exit(&tmp, c);
}
struct bkey_s_c bch2_btree_and_journal_iter_peek(struct btree_and_journal_iter *iter) struct bkey_s_c bch2_btree_and_journal_iter_peek(struct btree_and_journal_iter *iter)
{ {
struct bkey_s_c btree_k, journal_k, ret; struct bkey_s_c btree_k, journal_k, ret;
if (iter->prefetch && iter->journal.level)
btree_and_journal_iter_prefetch(iter);
again: again:
if (iter->at_end) if (iter->at_end)
return bkey_s_c_null; return bkey_s_c_null;
......
...@@ -23,6 +23,7 @@ struct btree_and_journal_iter { ...@@ -23,6 +23,7 @@ struct btree_and_journal_iter {
struct journal_iter journal; struct journal_iter journal;
struct bpos pos; struct bpos pos;
bool at_end; bool at_end;
bool prefetch;
}; };
struct bkey_i *bch2_journal_keys_peek_upto(struct bch_fs *, enum btree_id, struct bkey_i *bch2_journal_keys_peek_upto(struct bch_fs *, enum btree_id,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment