diff --git a/.bcachefs_revision b/.bcachefs_revision index 5eb25511..0e58a6dd 100644 --- a/.bcachefs_revision +++ b/.bcachefs_revision @@ -1 +1 @@ -600598598b7c6d2069a374a14ad4925f39a30faa +c68fda3e8f4106f1e1881e650f702d5bc2d301cb diff --git a/libbcachefs/btree_io.c b/libbcachefs/btree_io.c index 4629617b..a04d48ae 100644 --- a/libbcachefs/btree_io.c +++ b/libbcachefs/btree_io.c @@ -1488,23 +1488,32 @@ void bch2_btree_node_read(struct bch_fs *c, struct btree *b, struct btree_read_bio *rb; struct bch_dev *ca; struct bio *bio; - struct printbuf buf = PRINTBUF; int ret; - btree_pos_to_text(&buf, c, b); trace_btree_read(c, b); if (bch2_verify_all_btree_replicas && !btree_node_read_all_replicas(c, b, sync)) - goto out; + return; ret = bch2_bkey_pick_read_device(c, bkey_i_to_s_c(&b->key), NULL, &pick); - if (bch2_fs_fatal_err_on(ret <= 0, c, - "btree node read error: no device to read from\n" - " at %s", buf.buf)) { + + if (ret <= 0) { + struct printbuf buf = PRINTBUF; + + pr_buf(&buf, "btree node read error: no device to read from\n at "); + btree_pos_to_text(&buf, c, b); + bch_err(c, "%s", buf.buf); + + if (test_bit(BCH_FS_TOPOLOGY_REPAIR_DONE, &c->flags)) + bch2_fatal_error(c); + set_btree_node_read_error(b); - goto out; + clear_btree_node_read_in_flight(b); + wake_up_bit(&b->flags, BTREE_NODE_read_in_flight); + printbuf_exit(&buf); + return; } ca = bch_dev_bkey_exists(c, pick.ptr.dev); @@ -1546,8 +1555,6 @@ void bch2_btree_node_read(struct bch_fs *c, struct btree *b, else queue_work(c->io_complete_wq, &rb->work); } -out: - printbuf_exit(&buf); } int bch2_btree_root_read(struct bch_fs *c, enum btree_id id, diff --git a/libbcachefs/recovery.c b/libbcachefs/recovery.c index 04afe245..1f14c0b6 100644 --- a/libbcachefs/recovery.c +++ b/libbcachefs/recovery.c @@ -153,21 +153,17 @@ static void journal_iters_fix(struct bch_fs *c) { struct journal_keys *keys = &c->journal_keys; /* The key we just inserted is immediately before the gap: */ - struct journal_key *n = &keys->d[keys->gap - 1]; size_t gap_end = keys->gap + (keys->size - keys->nr); struct btree_and_journal_iter *iter; /* - * If an iterator points one after the key we just inserted, - * and the key we just inserted compares > the iterator's position, - * decrement the iterator so it points at the key we just inserted: + * If an iterator points one after the key we just inserted, decrement + * the iterator so it points at the key we just inserted - if the + * decrement was unnecessary, bch2_btree_and_journal_iter_peek() will + * handle that: */ list_for_each_entry(iter, &c->journal_iters, journal.list) - if (iter->journal.idx == gap_end && - iter->last && - iter->b->c.btree_id == n->btree_id && - iter->b->c.level == n->level && - bpos_cmp(n->k->k.p, iter->unpacked.p) > 0) + if (iter->journal.idx == gap_end) iter->journal.idx = keys->gap - 1; } @@ -297,23 +293,6 @@ void bch2_journal_key_overwritten(struct bch_fs *c, enum btree_id btree, keys->d[idx].overwritten = true; } -static struct bkey_i *bch2_journal_iter_peek(struct journal_iter *iter) -{ - struct journal_key *k = iter->keys->d + iter->idx; - - while (k < iter->keys->d + iter->keys->nr && - k->btree_id == iter->btree_id && - k->level == iter->level) { - if (!k->overwritten) - return k->k; - - iter->idx++; - k = iter->keys->d + iter->idx; - } - - return NULL; -} - static void bch2_journal_iter_advance(struct journal_iter *iter) { if (iter->idx < iter->keys->size) { @@ -323,6 +302,23 @@ static void bch2_journal_iter_advance(struct journal_iter *iter) } } +struct bkey_s_c bch2_journal_iter_peek(struct journal_iter *iter) +{ + struct journal_key *k = iter->keys->d + iter->idx; + + while (k < iter->keys->d + iter->keys->size && + k->btree_id == iter->btree_id && + k->level == iter->level) { + if (!k->overwritten) + return bkey_i_to_s_c(k->k); + + bch2_journal_iter_advance(iter); + k = iter->keys->d + iter->idx; + } + + return bkey_s_c_null; +} + static void bch2_journal_iter_exit(struct journal_iter *iter) { list_del(&iter->list); @@ -352,71 +348,49 @@ static void bch2_journal_iter_advance_btree(struct btree_and_journal_iter *iter) void bch2_btree_and_journal_iter_advance(struct btree_and_journal_iter *iter) { - switch (iter->last) { - case none: - break; - case btree: - bch2_journal_iter_advance_btree(iter); - break; - case journal: - bch2_journal_iter_advance(&iter->journal); - break; - } - - iter->last = none; + if (!bpos_cmp(iter->pos, SPOS_MAX)) + iter->at_end = true; + else + iter->pos = bpos_successor(iter->pos); } struct bkey_s_c bch2_btree_and_journal_iter_peek(struct btree_and_journal_iter *iter) { - struct bkey_s_c ret; + struct bkey_s_c btree_k, journal_k, ret; +again: + if (iter->at_end) + return bkey_s_c_null; - while (1) { - struct bkey_s_c btree_k = - bch2_journal_iter_peek_btree(iter); - struct bkey_s_c journal_k = - bkey_i_to_s_c(bch2_journal_iter_peek(&iter->journal)); + while ((btree_k = bch2_journal_iter_peek_btree(iter)).k && + bpos_cmp(btree_k.k->p, iter->pos) < 0) + bch2_journal_iter_advance_btree(iter); - if (btree_k.k && journal_k.k) { - int cmp = bpos_cmp(btree_k.k->p, journal_k.k->p); + while ((journal_k = bch2_journal_iter_peek(&iter->journal)).k && + bpos_cmp(journal_k.k->p, iter->pos) < 0) + bch2_journal_iter_advance(&iter->journal); - if (!cmp) - bch2_journal_iter_advance_btree(iter); + ret = journal_k.k && + (!btree_k.k || bpos_cmp(journal_k.k->p, btree_k.k->p) <= 0) + ? journal_k + : btree_k; - iter->last = cmp < 0 ? btree : journal; - } else if (btree_k.k) { - iter->last = btree; - } else if (journal_k.k) { - iter->last = journal; - } else { - iter->last = none; - return bkey_s_c_null; + if (ret.k && iter->b && bpos_cmp(ret.k->p, iter->b->data->max_key) > 0) + ret = bkey_s_c_null; + + if (ret.k) { + iter->pos = ret.k->p; + if (bkey_deleted(ret.k)) { + bch2_btree_and_journal_iter_advance(iter); + goto again; } - - ret = iter->last == journal ? journal_k : btree_k; - - if (iter->b && - bpos_cmp(ret.k->p, iter->b->data->max_key) > 0) { - iter->journal.idx = iter->journal.keys->nr; - iter->last = none; - return bkey_s_c_null; - } - - if (!bkey_deleted(ret.k)) - break; - - bch2_btree_and_journal_iter_advance(iter); + } else { + iter->pos = SPOS_MAX; + iter->at_end = true; } return ret; } -struct bkey_s_c bch2_btree_and_journal_iter_next(struct btree_and_journal_iter *iter) -{ - bch2_btree_and_journal_iter_advance(iter); - - return bch2_btree_and_journal_iter_peek(iter); -} - void bch2_btree_and_journal_iter_exit(struct btree_and_journal_iter *iter) { bch2_journal_iter_exit(&iter->journal); @@ -434,6 +408,8 @@ void __bch2_btree_and_journal_iter_init_node_iter(struct btree_and_journal_iter iter->node_iter = node_iter; bch2_journal_iter_init(c, &iter->journal, b->c.btree_id, b->c.level, pos); INIT_LIST_HEAD(&iter->journal.list); + iter->pos = b->data->min_key; + iter->at_end = false; } /* @@ -1169,9 +1145,6 @@ use_clean: blacklist_seq = journal_seq = le64_to_cpu(clean->journal_seq) + 1; } - if (c->opts.read_journal_only) - goto out; - if (c->opts.reconstruct_alloc) { c->sb.compat &= ~(1ULL << BCH_COMPAT_alloc_info); drop_alloc_keys(&c->journal_keys); @@ -1202,6 +1175,13 @@ use_clean: } } + /* + * note: cmd_list_journal needs the blacklist table fully up to date so + * it can asterisk ignored journal entries: + */ + if (c->opts.read_journal_only) + goto out; + ret = bch2_fs_journal_start(&c->journal, journal_seq); if (ret) goto err; diff --git a/libbcachefs/recovery.h b/libbcachefs/recovery.h index 52db06b2..8c0348e8 100644 --- a/libbcachefs/recovery.h +++ b/libbcachefs/recovery.h @@ -20,12 +20,8 @@ struct btree_and_journal_iter { struct bkey unpacked; struct journal_iter journal; - - enum last_key_returned { - none, - btree, - journal, - } last; + struct bpos pos; + bool at_end; }; struct bkey_i *bch2_journal_keys_peek_upto(struct bch_fs *, enum btree_id, @@ -44,7 +40,6 @@ void bch2_journal_key_overwritten(struct bch_fs *, enum btree_id, void bch2_btree_and_journal_iter_advance(struct btree_and_journal_iter *); struct bkey_s_c bch2_btree_and_journal_iter_peek(struct btree_and_journal_iter *); -struct bkey_s_c bch2_btree_and_journal_iter_next(struct btree_and_journal_iter *); void bch2_btree_and_journal_iter_exit(struct btree_and_journal_iter *); void __bch2_btree_and_journal_iter_init_node_iter(struct btree_and_journal_iter *,