mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-23 00:00:02 +03:00
Update bcachefs sources to c68fda3e8f bcachefs: Fix btree node read error path
This commit is contained in:
parent
f682263a73
commit
b6fc4864a7
@ -1 +1 @@
|
|||||||
600598598b7c6d2069a374a14ad4925f39a30faa
|
c68fda3e8f4106f1e1881e650f702d5bc2d301cb
|
||||||
|
@ -1488,23 +1488,32 @@ void bch2_btree_node_read(struct bch_fs *c, struct btree *b,
|
|||||||
struct btree_read_bio *rb;
|
struct btree_read_bio *rb;
|
||||||
struct bch_dev *ca;
|
struct bch_dev *ca;
|
||||||
struct bio *bio;
|
struct bio *bio;
|
||||||
struct printbuf buf = PRINTBUF;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
btree_pos_to_text(&buf, c, b);
|
|
||||||
trace_btree_read(c, b);
|
trace_btree_read(c, b);
|
||||||
|
|
||||||
if (bch2_verify_all_btree_replicas &&
|
if (bch2_verify_all_btree_replicas &&
|
||||||
!btree_node_read_all_replicas(c, b, sync))
|
!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),
|
ret = bch2_bkey_pick_read_device(c, bkey_i_to_s_c(&b->key),
|
||||||
NULL, &pick);
|
NULL, &pick);
|
||||||
if (bch2_fs_fatal_err_on(ret <= 0, c,
|
|
||||||
"btree node read error: no device to read from\n"
|
if (ret <= 0) {
|
||||||
" at %s", buf.buf)) {
|
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);
|
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);
|
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
|
else
|
||||||
queue_work(c->io_complete_wq, &rb->work);
|
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,
|
int bch2_btree_root_read(struct bch_fs *c, enum btree_id id,
|
||||||
|
@ -153,21 +153,17 @@ static void journal_iters_fix(struct bch_fs *c)
|
|||||||
{
|
{
|
||||||
struct journal_keys *keys = &c->journal_keys;
|
struct journal_keys *keys = &c->journal_keys;
|
||||||
/* The key we just inserted is immediately before the gap: */
|
/* 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);
|
size_t gap_end = keys->gap + (keys->size - keys->nr);
|
||||||
struct btree_and_journal_iter *iter;
|
struct btree_and_journal_iter *iter;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If an iterator points one after the key we just inserted,
|
* If an iterator points one after the key we just inserted, decrement
|
||||||
* and the key we just inserted compares > the iterator's position,
|
* the iterator so it points at the key we just inserted - if the
|
||||||
* decrement the iterator so it points at the key we just inserted:
|
* decrement was unnecessary, bch2_btree_and_journal_iter_peek() will
|
||||||
|
* handle that:
|
||||||
*/
|
*/
|
||||||
list_for_each_entry(iter, &c->journal_iters, journal.list)
|
list_for_each_entry(iter, &c->journal_iters, journal.list)
|
||||||
if (iter->journal.idx == gap_end &&
|
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)
|
|
||||||
iter->journal.idx = keys->gap - 1;
|
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;
|
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)
|
static void bch2_journal_iter_advance(struct journal_iter *iter)
|
||||||
{
|
{
|
||||||
if (iter->idx < iter->keys->size) {
|
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)
|
static void bch2_journal_iter_exit(struct journal_iter *iter)
|
||||||
{
|
{
|
||||||
list_del(&iter->list);
|
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)
|
void bch2_btree_and_journal_iter_advance(struct btree_and_journal_iter *iter)
|
||||||
{
|
{
|
||||||
switch (iter->last) {
|
if (!bpos_cmp(iter->pos, SPOS_MAX))
|
||||||
case none:
|
iter->at_end = true;
|
||||||
break;
|
else
|
||||||
case btree:
|
iter->pos = bpos_successor(iter->pos);
|
||||||
bch2_journal_iter_advance_btree(iter);
|
|
||||||
break;
|
|
||||||
case journal:
|
|
||||||
bch2_journal_iter_advance(&iter->journal);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
iter->last = none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bkey_s_c bch2_btree_and_journal_iter_peek(struct btree_and_journal_iter *iter)
|
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) {
|
while ((btree_k = bch2_journal_iter_peek_btree(iter)).k &&
|
||||||
struct bkey_s_c btree_k =
|
bpos_cmp(btree_k.k->p, iter->pos) < 0)
|
||||||
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);
|
|
||||||
|
|
||||||
if (!cmp)
|
|
||||||
bch2_journal_iter_advance_btree(iter);
|
bch2_journal_iter_advance_btree(iter);
|
||||||
|
|
||||||
iter->last = cmp < 0 ? btree : journal;
|
while ((journal_k = bch2_journal_iter_peek(&iter->journal)).k &&
|
||||||
} else if (btree_k.k) {
|
bpos_cmp(journal_k.k->p, iter->pos) < 0)
|
||||||
iter->last = btree;
|
bch2_journal_iter_advance(&iter->journal);
|
||||||
} else if (journal_k.k) {
|
|
||||||
iter->last = journal;
|
|
||||||
} else {
|
|
||||||
iter->last = none;
|
|
||||||
return bkey_s_c_null;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = iter->last == journal ? journal_k : btree_k;
|
ret = journal_k.k &&
|
||||||
|
(!btree_k.k || bpos_cmp(journal_k.k->p, btree_k.k->p) <= 0)
|
||||||
|
? journal_k
|
||||||
|
: btree_k;
|
||||||
|
|
||||||
if (iter->b &&
|
if (ret.k && iter->b && bpos_cmp(ret.k->p, iter->b->data->max_key) > 0)
|
||||||
bpos_cmp(ret.k->p, iter->b->data->max_key) > 0) {
|
ret = bkey_s_c_null;
|
||||||
iter->journal.idx = iter->journal.keys->nr;
|
|
||||||
iter->last = none;
|
|
||||||
return bkey_s_c_null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bkey_deleted(ret.k))
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
if (ret.k) {
|
||||||
|
iter->pos = ret.k->p;
|
||||||
|
if (bkey_deleted(ret.k)) {
|
||||||
bch2_btree_and_journal_iter_advance(iter);
|
bch2_btree_and_journal_iter_advance(iter);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iter->pos = SPOS_MAX;
|
||||||
|
iter->at_end = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
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)
|
void bch2_btree_and_journal_iter_exit(struct btree_and_journal_iter *iter)
|
||||||
{
|
{
|
||||||
bch2_journal_iter_exit(&iter->journal);
|
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;
|
iter->node_iter = node_iter;
|
||||||
bch2_journal_iter_init(c, &iter->journal, b->c.btree_id, b->c.level, pos);
|
bch2_journal_iter_init(c, &iter->journal, b->c.btree_id, b->c.level, pos);
|
||||||
INIT_LIST_HEAD(&iter->journal.list);
|
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;
|
blacklist_seq = journal_seq = le64_to_cpu(clean->journal_seq) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->opts.read_journal_only)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (c->opts.reconstruct_alloc) {
|
if (c->opts.reconstruct_alloc) {
|
||||||
c->sb.compat &= ~(1ULL << BCH_COMPAT_alloc_info);
|
c->sb.compat &= ~(1ULL << BCH_COMPAT_alloc_info);
|
||||||
drop_alloc_keys(&c->journal_keys);
|
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);
|
ret = bch2_fs_journal_start(&c->journal, journal_seq);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -20,12 +20,8 @@ struct btree_and_journal_iter {
|
|||||||
struct bkey unpacked;
|
struct bkey unpacked;
|
||||||
|
|
||||||
struct journal_iter journal;
|
struct journal_iter journal;
|
||||||
|
struct bpos pos;
|
||||||
enum last_key_returned {
|
bool at_end;
|
||||||
none,
|
|
||||||
btree,
|
|
||||||
journal,
|
|
||||||
} last;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bkey_i *bch2_journal_keys_peek_upto(struct bch_fs *, enum btree_id,
|
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 *);
|
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_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_exit(struct btree_and_journal_iter *);
|
||||||
void __bch2_btree_and_journal_iter_init_node_iter(struct btree_and_journal_iter *,
|
void __bch2_btree_and_journal_iter_init_node_iter(struct btree_and_journal_iter *,
|
||||||
|
Loading…
Reference in New Issue
Block a user