diff options
Diffstat (limited to 'libbcachefs/btree_journal_iter.c')
-rw-r--r-- | libbcachefs/btree_journal_iter.c | 37 |
1 files changed, 29 insertions, 8 deletions
diff --git a/libbcachefs/btree_journal_iter.c b/libbcachefs/btree_journal_iter.c index a41fabd0..341d31b3 100644 --- a/libbcachefs/btree_journal_iter.c +++ b/libbcachefs/btree_journal_iter.c @@ -137,12 +137,15 @@ struct bkey_i *bch2_journal_keys_peek_prev_min(struct bch_fs *c, enum btree_id b struct journal_key *k; BUG_ON(*idx > keys->nr); + + if (!keys->nr) + return NULL; search: if (!*idx) *idx = __bch2_journal_key_search(keys, btree_id, level, pos); while (*idx < keys->nr && - __journal_key_cmp(btree_id, level, end_pos, idx_to_key(keys, *idx - 1)) >= 0) { + __journal_key_cmp(btree_id, level, end_pos, idx_to_key(keys, *idx)) >= 0) { (*idx)++; iters++; if (iters == 10) { @@ -151,18 +154,23 @@ search: } } + if (*idx == keys->nr) + --(*idx); + struct bkey_i *ret = NULL; rcu_read_lock(); /* for overwritten_ranges */ - while ((k = *idx < keys->nr ? idx_to_key(keys, *idx) : NULL)) { + while (true) { + k = idx_to_key(keys, *idx); if (__journal_key_cmp(btree_id, level, end_pos, k) > 0) break; if (k->overwritten) { if (k->overwritten_range) - *idx = rcu_dereference(k->overwritten_range)->start - 1; - else - *idx -= 1; + *idx = rcu_dereference(k->overwritten_range)->start; + if (!*idx) + break; + --(*idx); continue; } @@ -171,6 +179,8 @@ search: break; } + if (!*idx) + break; --(*idx); iters++; if (iters == 10) { @@ -707,6 +717,18 @@ static void __journal_keys_sort(struct journal_keys *keys) keys->nr = dst - keys->data; } +static bool should_rewind_entry(struct bch_fs *c, struct jset_entry *entry) +{ + if (entry->level) + return false; + if (btree_id_is_alloc(entry->btree_id)) + return false; + if (c->opts.journal_rewind_no_extents && + entry->btree_id == BTREE_ID_extents) + return false; + return true; +} + int bch2_journal_keys_sort(struct bch_fs *c) { struct genradix_iter iter; @@ -725,9 +747,8 @@ int bch2_journal_keys_sort(struct bch_fs *c) cond_resched(); vstruct_for_each(&i->j, entry) { - bool rewind = !entry->level && - !btree_id_is_alloc(entry->btree_id) && - le64_to_cpu(i->j.seq) >= rewind_seq; + bool rewind = le64_to_cpu(i->j.seq) >= rewind_seq && + should_rewind_entry(c, entry); if (entry->type != (rewind ? BCH_JSET_ENTRY_overwrite |