summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-06-07 02:16:44 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2022-06-07 02:16:44 -0400
commitb6fc4864a7f0aea7fc0bf99e829ef678aa3723a3 (patch)
treecb91bf5f88701f9f8eeb76e15850b2a9757f2f5d
parentf682263a730f7cea86fcf6f13e959e66e7161f38 (diff)
Update bcachefs sources to c68fda3e8f bcachefs: Fix btree node read error path
-rw-r--r--.bcachefs_revision2
-rw-r--r--libbcachefs/btree_io.c25
-rw-r--r--libbcachefs/recovery.c132
-rw-r--r--libbcachefs/recovery.h9
4 files changed, 75 insertions, 93 deletions
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,30 +293,30 @@ 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)
+static void bch2_journal_iter_advance(struct journal_iter *iter)
+{
+ if (iter->idx < iter->keys->size) {
+ iter->idx++;
+ if (iter->idx == iter->keys->gap)
+ iter->idx += iter->keys->size - iter->keys->nr;
+ }
+}
+
+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->nr &&
+ while (k < iter->keys->d + iter->keys->size &&
k->btree_id == iter->btree_id &&
k->level == iter->level) {
if (!k->overwritten)
- return k->k;
+ return bkey_i_to_s_c(k->k);
- iter->idx++;
+ bch2_journal_iter_advance(iter);
k = iter->keys->d + iter->idx;
}
- return NULL;
-}
-
-static void bch2_journal_iter_advance(struct journal_iter *iter)
-{
- if (iter->idx < iter->keys->size) {
- iter->idx++;
- if (iter->idx == iter->keys->gap)
- iter->idx += iter->keys->size - iter->keys->nr;
- }
+ return bkey_s_c_null;
}
static void bch2_journal_iter_exit(struct journal_iter *iter)
@@ -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));
-
- if (btree_k.k && journal_k.k) {
- int cmp = bpos_cmp(btree_k.k->p, journal_k.k->p);
+ 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 (!cmp)
- bch2_journal_iter_advance_btree(iter);
+ 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);
- 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;
- }
+ ret = journal_k.k &&
+ (!btree_k.k || bpos_cmp(journal_k.k->p, btree_k.k->p) <= 0)
+ ? journal_k
+ : btree_k;
- ret = iter->last == journal ? journal_k : btree_k;
+ if (ret.k && iter->b && bpos_cmp(ret.k->p, iter->b->data->max_key) > 0)
+ ret = bkey_s_c_null;
- 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 (ret.k) {
+ iter->pos = ret.k->p;
+ if (bkey_deleted(ret.k)) {
+ bch2_btree_and_journal_iter_advance(iter);
+ goto again;
}
-
- 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 *,