Commit 5650bb46 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Introduce bch2_journal_keys_peek_(upto|slot)()

When many journal replay keys have been overwritten,
bch2_journal_keys_peek() was taking excessively long to scan before it
found a key to return.

Fix this by introducing bch2_journal_keys_peek_upto() which takes a
parameter for the end of the range we want, so that we can terminate the
search much sooner, and replace all uses of bch2_journal_keys_peek()
with peek_upto() or peek_slot().
Signed-off-by: default avatarKent Overstreet <kent.overstreet@gmail.com>
parent 9b93596c
...@@ -2225,10 +2225,10 @@ static noinline ...@@ -2225,10 +2225,10 @@ static noinline
struct bkey_s_c btree_trans_peek_slot_journal(struct btree_trans *trans, struct bkey_s_c btree_trans_peek_slot_journal(struct btree_trans *trans,
struct btree_iter *iter) struct btree_iter *iter)
{ {
struct bkey_i *k = bch2_journal_keys_peek(trans->c, iter->btree_id, 0, struct bkey_i *k = bch2_journal_keys_peek_slot(trans->c, iter->btree_id,
iter->path->pos); 0, iter->path->pos);
if (k && !bpos_cmp(k->k.p, iter->path->pos)) { if (k) {
iter->k = k->k; iter->k = k->k;
return bkey_i_to_s_c(k); return bkey_i_to_s_c(k);
} else { } else {
...@@ -2242,12 +2242,11 @@ struct bkey_s_c btree_trans_peek_journal(struct btree_trans *trans, ...@@ -2242,12 +2242,11 @@ struct bkey_s_c btree_trans_peek_journal(struct btree_trans *trans,
struct bkey_s_c k) struct bkey_s_c k)
{ {
struct bkey_i *next_journal = struct bkey_i *next_journal =
bch2_journal_keys_peek(trans->c, iter->btree_id, 0, bch2_journal_keys_peek_upto(trans->c, iter->btree_id, 0,
iter->path->pos); iter->path->pos,
k.k ? k.k->p : iter->path->l[0].b->key.k.p);
if (next_journal && if (next_journal) {
bpos_cmp(next_journal->k.p,
k.k ? k.k->p : iter->path->l[0].b->key.k.p) <= 0) {
iter->k = next_journal->k; iter->k = next_journal->k;
k = bkey_i_to_s_c(next_journal); k = bkey_i_to_s_c(next_journal);
} }
......
...@@ -670,9 +670,10 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, ...@@ -670,9 +670,10 @@ bch2_trans_commit_write_locked(struct btree_trans *trans,
if (unlikely(!test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags))) { if (unlikely(!test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags))) {
struct bkey_i *j_k = struct bkey_i *j_k =
bch2_journal_keys_peek(c, i->btree_id, i->level, i->k->k.p); bch2_journal_keys_peek_slot(c, i->btree_id, i->level,
i->k->k.p);
if (j_k && !bpos_cmp(j_k->k.p, i->k->k.p)) { if (j_k) {
i->old_k = j_k->k; i->old_k = j_k->k;
i->old_v = &j_k->v; i->old_v = &j_k->v;
} }
...@@ -1550,9 +1551,9 @@ bch2_trans_update_by_path_trace(struct btree_trans *trans, struct btree_path *pa ...@@ -1550,9 +1551,9 @@ bch2_trans_update_by_path_trace(struct btree_trans *trans, struct btree_path *pa
if (unlikely(trans->journal_replay_not_finished)) { if (unlikely(trans->journal_replay_not_finished)) {
struct bkey_i *j_k = struct bkey_i *j_k =
bch2_journal_keys_peek(c, n.btree_id, n.level, k->k.p); bch2_journal_keys_peek_slot(c, n.btree_id, n.level, k->k.p);
if (j_k && !bpos_cmp(j_k->k.p, i->k->k.p)) { if (j_k) {
i->old_k = j_k->k; i->old_k = j_k->k;
i->old_v = &j_k->v; i->old_v = &j_k->v;
} }
......
...@@ -109,26 +109,34 @@ size_t bch2_journal_key_search(struct journal_keys *keys, ...@@ -109,26 +109,34 @@ size_t bch2_journal_key_search(struct journal_keys *keys,
return idx_to_pos(keys, l); return idx_to_pos(keys, l);
} }
struct bkey_i *bch2_journal_keys_peek(struct bch_fs *c, enum btree_id btree_id, struct bkey_i *bch2_journal_keys_peek_upto(struct bch_fs *c, enum btree_id btree_id,
unsigned level, struct bpos pos) unsigned level, struct bpos pos,
struct bpos end_pos)
{ {
struct journal_keys *keys = &c->journal_keys; struct journal_keys *keys = &c->journal_keys;
size_t idx = bch2_journal_key_search(keys, btree_id, level, pos); size_t idx = bch2_journal_key_search(keys, btree_id, level, pos);
while (idx < keys->size && while (idx < keys->size &&
keys->d[idx].overwritten) { keys->d[idx].btree_id == btree_id &&
keys->d[idx].level == level &&
bpos_cmp(keys->d[idx].k->k.p, end_pos) <= 0) {
if (!keys->d[idx].overwritten)
return keys->d[idx].k;
idx++; idx++;
if (idx == keys->gap) if (idx == keys->gap)
idx += keys->size - keys->nr; idx += keys->size - keys->nr;
} }
if (idx < keys->size &&
keys->d[idx].btree_id == btree_id &&
keys->d[idx].level == level)
return keys->d[idx].k;
return NULL; return NULL;
} }
struct bkey_i *bch2_journal_keys_peek_slot(struct bch_fs *c, enum btree_id btree_id,
unsigned level, struct bpos pos)
{
return bch2_journal_keys_peek_upto(c, btree_id, level, pos, pos);
}
static void journal_iters_fix(struct bch_fs *c) static void journal_iters_fix(struct bch_fs *c)
{ {
struct journal_keys *keys = &c->journal_keys; struct journal_keys *keys = &c->journal_keys;
......
...@@ -30,8 +30,10 @@ struct btree_and_journal_iter { ...@@ -30,8 +30,10 @@ struct btree_and_journal_iter {
size_t bch2_journal_key_search(struct journal_keys *, enum btree_id, size_t bch2_journal_key_search(struct journal_keys *, enum btree_id,
unsigned, struct bpos); unsigned, struct bpos);
struct bkey_i *bch2_journal_keys_peek(struct bch_fs *, enum btree_id, struct bkey_i *bch2_journal_keys_peek_upto(struct bch_fs *, enum btree_id,
unsigned, struct bpos pos); unsigned, struct bpos, struct bpos);
struct bkey_i *bch2_journal_keys_peek_slot(struct bch_fs *, enum btree_id,
unsigned, struct bpos);
int bch2_journal_key_insert_take(struct bch_fs *, enum btree_id, int bch2_journal_key_insert_take(struct bch_fs *, enum btree_id,
unsigned, struct bkey_i *); unsigned, struct bkey_i *);
......
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