diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2021-06-23 04:51:17 +0300 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-23 00:09:07 +0300 |
commit | 50ad5d097977dc5c688e7a1a6dc2e74c37da5adf (patch) | |
tree | ae5ea1efeba4055d07f9edc0082a2026e6199763 /fs/bcachefs/btree_io.c | |
parent | d976a84e3b486b04314dcf5183af3123549cda95 (diff) | |
download | linux-50ad5d097977dc5c688e7a1a6dc2e74c37da5adf.tar.xz |
bcachefs: Fix btree_node_read_all_replicas() error handling
We weren't checking bch2_btree_node_read_done() for errors, oops.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Diffstat (limited to 'fs/bcachefs/btree_io.c')
-rw-r--r-- | fs/bcachefs/btree_io.c | 39 |
1 files changed, 20 insertions, 19 deletions
diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c index 4ffdc11f4d9a..6274211d09f1 100644 --- a/fs/bcachefs/btree_io.c +++ b/fs/bcachefs/btree_io.c @@ -1187,31 +1187,27 @@ static void btree_node_read_all_replicas_done(struct closure *cl) container_of(cl, struct btree_node_read_all, cl); struct bch_fs *c = ra->c; struct btree *b = ra->b; - bool have_good_copy = false; bool dump_bset_maps = false; bool have_retry = false; - int ret = 0, write = READ; + int ret = 0, best = -1, write = READ; unsigned i, written, written2; __le64 seq = b->key.k.type == KEY_TYPE_btree_ptr_v2 ? bkey_i_to_btree_ptr_v2(&b->key)->v.seq : 0; for (i = 0; i < ra->nr; i++) { + struct btree_node *bn = ra->buf[i]; + if (ra->err[i]) continue; - if (!have_good_copy) { - memcpy(b->data, ra->buf[i], btree_bytes(c)); - have_good_copy = true; - written = btree_node_sectors_written(c, b->data); - } + if (le64_to_cpu(bn->magic) != bset_magic(c) || + (seq && seq != bn->keys.seq)) + continue; - /* Try to get the right btree node: */ - if (have_good_copy && - seq && - b->data->keys.seq != seq && - ((struct btree_node *) ra->buf[i])->keys.seq == seq) { - memcpy(b->data, ra->buf[i], btree_bytes(c)); - written = btree_node_sectors_written(c, b->data); + if (best < 0) { + best = i; + written = btree_node_sectors_written(c, bn); + continue; } written2 = btree_node_sectors_written(c, ra->buf[i]); @@ -1221,14 +1217,14 @@ static void btree_node_read_all_replicas_done(struct closure *cl) btree_err_on(btree_node_has_extra_bsets(c, written2, ra->buf[i]), BTREE_ERR_FIXABLE, c, NULL, b, NULL, "found bset signature after last bset") || - btree_err_on(memcmp(b->data, ra->buf[i], written << 9), + btree_err_on(memcmp(ra->buf[best], ra->buf[i], written << 9), BTREE_ERR_FIXABLE, c, NULL, b, NULL, "btree node replicas content mismatch")) dump_bset_maps = true; if (written2 > written) { written = written2; - memcpy(b->data, ra->buf[i], btree_bytes(c)); + best = i; } } fsck_err: @@ -1281,9 +1277,14 @@ fsck_err: } } - if (have_good_copy) - bch2_btree_node_read_done(c, NULL, b, false); - else + if (best >= 0) { + memcpy(b->data, ra->buf[best], btree_bytes(c)); + ret = bch2_btree_node_read_done(c, NULL, b, false); + } else { + ret = -1; + } + + if (ret) set_btree_node_read_error(b); for (i = 0; i < ra->nr; i++) { |