summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-04-12 03:28:13 +0300
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-23 00:09:31 +0300
commit5650bb46be89a1254609d47e4c87d1e9cf9121fb (patch)
tree73506214235f46eed04b2e4675463db1b38b2ea4
parent9b93596c33f6c23de96c05dce82b9aead271a286 (diff)
downloadlinux-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.c15
-rw-r--r--fs/bcachefs/btree_update_leaf.c9
-rw-r--r--fs/bcachefs/recovery.c22
-rw-r--r--fs/bcachefs/recovery.h6
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 *);