diff options
-rw-r--r-- | fs/bcachefs/ec.c | 46 | ||||
-rw-r--r-- | fs/bcachefs/recovery.c | 36 | ||||
-rw-r--r-- | fs/bcachefs/recovery.h | 11 |
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 *); |