summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/bcachefs/ec.c46
-rw-r--r--fs/bcachefs/recovery.c36
-rw-r--r--fs/bcachefs/recovery.h11
3 files changed, 82 insertions, 11 deletions
diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c
index 42bca2b413e3..de31ea6c20de 100644
--- a/fs/bcachefs/ec.c
+++ b/fs/bcachefs/ec.c
@@ -1267,10 +1267,10 @@ int bch2_stripes_write(struct bch_fs *c, unsigned flags, bool *wrote)
int bch2_stripes_read(struct bch_fs *c, struct journal_keys *journal_keys)
{
- struct journal_key *i;
struct btree_trans trans;
- struct btree_iter *iter;
- struct bkey_s_c k;
+ struct btree_iter *btree_iter;
+ struct journal_iter journal_iter;
+ struct bkey_s_c btree_k, journal_k, k;
int ret;
ret = bch2_fs_ec_start(c);
@@ -1279,10 +1279,41 @@ int bch2_stripes_read(struct bch_fs *c, struct journal_keys *journal_keys)
bch2_trans_init(&trans, c, 0, 0);
- for_each_btree_key(&trans, iter, BTREE_ID_EC, POS_MIN, 0, k, ret)
+ btree_iter = bch2_trans_get_iter(&trans, BTREE_ID_EC, POS_MIN, 0);
+ journal_iter = bch2_journal_iter_init(journal_keys, BTREE_ID_EC);
+
+ btree_k = bch2_btree_iter_peek(btree_iter);
+ journal_k = bch2_journal_iter_peek(&journal_iter);
+
+ while (1) {
+ if (btree_k.k && journal_k.k) {
+ int cmp = bkey_cmp(btree_k.k->p, journal_k.k->p);
+
+ if (cmp < 0) {
+ k = btree_k;
+ btree_k = bch2_btree_iter_next(btree_iter);
+ } else if (cmp == 0) {
+ btree_k = bch2_btree_iter_next(btree_iter);
+ k = journal_k;
+ journal_k = bch2_journal_iter_next(&journal_iter);
+ } else {
+ k = journal_k;
+ journal_k = bch2_journal_iter_next(&journal_iter);
+ }
+ } else if (btree_k.k) {
+ k = btree_k;
+ btree_k = bch2_btree_iter_next(btree_iter);
+ } else if (journal_k.k) {
+ k = journal_k;
+ journal_k = bch2_journal_iter_next(&journal_iter);
+ } else {
+ break;
+ }
+
bch2_mark_key(c, k, 0, NULL, 0,
BCH_BUCKET_MARK_ALLOC_READ|
BCH_BUCKET_MARK_NOATOMIC);
+ }
ret = bch2_trans_exit(&trans) ?: ret;
if (ret) {
@@ -1290,13 +1321,6 @@ int bch2_stripes_read(struct bch_fs *c, struct journal_keys *journal_keys)
return ret;
}
- for_each_journal_key(*journal_keys, i)
- if (i->btree_id == BTREE_ID_EC)
- bch2_mark_key(c, bkey_i_to_s_c(i->k),
- 0, NULL, 0,
- BCH_BUCKET_MARK_ALLOC_READ|
- BCH_BUCKET_MARK_NOATOMIC);
-
return 0;
}
diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c
index e0df2c0a4fdf..92867b5c078f 100644
--- a/fs/bcachefs/recovery.c
+++ b/fs/bcachefs/recovery.c
@@ -24,6 +24,42 @@
#define QSTR(n) { { { .len = strlen(n) } }, .name = n }
+/* iterate over keys read from the journal: */
+
+struct journal_iter bch2_journal_iter_init(struct journal_keys *keys,
+ enum btree_id id)
+{
+ return (struct journal_iter) {
+ .keys = keys,
+ .k = keys->d,
+ .btree_id = id,
+ };
+}
+
+struct bkey_s_c bch2_journal_iter_peek(struct journal_iter *iter)
+{
+ while (1) {
+ if (iter->k == iter->keys->d + iter->keys->nr)
+ return bkey_s_c_null;
+
+ if (iter->k->btree_id == iter->btree_id)
+ return bkey_i_to_s_c(iter->k->k);
+
+ iter->k++;
+ }
+
+ return bkey_s_c_null;
+}
+
+struct bkey_s_c bch2_journal_iter_next(struct journal_iter *iter)
+{
+ if (iter->k == iter->keys->d + iter->keys->nr)
+ return bkey_s_c_null;
+
+ iter->k++;
+ return bch2_journal_iter_peek(iter);
+}
+
/* sort and dedup all keys in the journal: */
static void journal_entries_free(struct list_head *list)
diff --git a/fs/bcachefs/recovery.h b/fs/bcachefs/recovery.h
index a69260d6165a..479ea46f8dcb 100644
--- a/fs/bcachefs/recovery.h
+++ b/fs/bcachefs/recovery.h
@@ -18,6 +18,17 @@ struct journal_keys {
#define for_each_journal_key(keys, i) \
for (i = (keys).d; i < (keys).d + (keys).nr; (i)++)
+struct journal_iter {
+ struct journal_keys *keys;
+ struct journal_key *k;
+ enum btree_id btree_id;
+};
+
+struct journal_iter bch2_journal_iter_init(struct journal_keys *,
+ enum btree_id);
+struct bkey_s_c bch2_journal_iter_peek(struct journal_iter *);
+struct bkey_s_c bch2_journal_iter_next(struct journal_iter *);
+
int bch2_fs_recovery(struct bch_fs *);
int bch2_fs_initialize(struct bch_fs *);