diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2022-04-12 03:28:13 +0300 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-23 00:09:31 +0300 |
commit | 5650bb46be89a1254609d47e4c87d1e9cf9121fb (patch) | |
tree | 73506214235f46eed04b2e4675463db1b38b2ea4 | |
parent | 9b93596c33f6c23de96c05dce82b9aead271a286 (diff) | |
download | linux-5650bb46be89a1254609d47e4c87d1e9cf9121fb.tar.xz |
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: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r-- | fs/bcachefs/btree_iter.c | 15 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_leaf.c | 9 | ||||
-rw-r--r-- | fs/bcachefs/recovery.c | 22 | ||||
-rw-r--r-- | fs/bcachefs/recovery.h | 6 |
4 files changed, 31 insertions, 21 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index 1c0560ecd120..80ea97e21cf3 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -2225,10 +2225,10 @@ static noinline struct bkey_s_c btree_trans_peek_slot_journal(struct btree_trans *trans, struct btree_iter *iter) { - struct bkey_i *k = bch2_journal_keys_peek(trans->c, iter->btree_id, 0, - iter->path->pos); + struct bkey_i *k = bch2_journal_keys_peek_slot(trans->c, iter->btree_id, + 0, iter->path->pos); - if (k && !bpos_cmp(k->k.p, iter->path->pos)) { + if (k) { iter->k = k->k; return bkey_i_to_s_c(k); } else { @@ -2242,12 +2242,11 @@ struct bkey_s_c btree_trans_peek_journal(struct btree_trans *trans, struct bkey_s_c k) { struct bkey_i *next_journal = - bch2_journal_keys_peek(trans->c, iter->btree_id, 0, - iter->path->pos); + bch2_journal_keys_peek_upto(trans->c, iter->btree_id, 0, + iter->path->pos, + k.k ? k.k->p : iter->path->l[0].b->key.k.p); - if (next_journal && - bpos_cmp(next_journal->k.p, - k.k ? k.k->p : iter->path->l[0].b->key.k.p) <= 0) { + if (next_journal) { iter->k = next_journal->k; k = bkey_i_to_s_c(next_journal); } diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index bc7faf29b3bc..a63c2f36bae4 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -670,9 +670,10 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, if (unlikely(!test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags))) { 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_v = &j_k->v; } @@ -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)) { 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_v = &j_k->v; } diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c index 9269cb686e4d..16ba5d24a86d 100644 --- a/fs/bcachefs/recovery.c +++ b/fs/bcachefs/recovery.c @@ -109,26 +109,34 @@ size_t bch2_journal_key_search(struct journal_keys *keys, return idx_to_pos(keys, l); } -struct bkey_i *bch2_journal_keys_peek(struct bch_fs *c, enum btree_id btree_id, - unsigned level, struct bpos pos) +struct bkey_i *bch2_journal_keys_peek_upto(struct bch_fs *c, enum btree_id btree_id, + unsigned level, struct bpos pos, + struct bpos end_pos) { struct journal_keys *keys = &c->journal_keys; size_t idx = bch2_journal_key_search(keys, btree_id, level, pos); 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++; if (idx == keys->gap) 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; } +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) { struct journal_keys *keys = &c->journal_keys; diff --git a/fs/bcachefs/recovery.h b/fs/bcachefs/recovery.h index ab8b116ac7db..e05aac64185d 100644 --- a/fs/bcachefs/recovery.h +++ b/fs/bcachefs/recovery.h @@ -30,8 +30,10 @@ struct btree_and_journal_iter { size_t bch2_journal_key_search(struct journal_keys *, enum btree_id, unsigned, struct bpos); -struct bkey_i *bch2_journal_keys_peek(struct bch_fs *, enum btree_id, - unsigned, struct bpos pos); +struct bkey_i *bch2_journal_keys_peek_upto(struct bch_fs *, enum btree_id, + 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, unsigned, struct bkey_i *); |