bcachefs: Flag btrees with missing data

We need this to know when we should attempt to reconstruct the snapshots
btree

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2024-03-15 23:03:42 -04:00
parent 43f5ea4646
commit 55936afe11
6 changed files with 44 additions and 5 deletions

View File

@ -797,6 +797,7 @@ struct bch_fs {
u64 features;
u64 compat;
unsigned long errors_silent[BITS_TO_LONGS(BCH_SB_ERR_MAX)];
u64 btrees_lost_data;
} sb;

View File

@ -818,6 +818,7 @@ struct bch_sb_field_ext {
struct bch_sb_field field;
__le64 recovery_passes_required[2];
__le64 errors_silent[8];
__le64 btrees_lost_data;
};
struct bch_sb_field_downgrade_entry {

View File

@ -1264,10 +1264,12 @@ out:
return retry_read;
fsck_err:
if (ret == -BCH_ERR_btree_node_read_err_want_retry ||
ret == -BCH_ERR_btree_node_read_err_must_retry)
ret == -BCH_ERR_btree_node_read_err_must_retry) {
retry_read = 1;
else
} else {
set_btree_node_read_error(b);
bch2_btree_lost_data(c, b->c.btree_id);
}
goto out;
}
@ -1328,6 +1330,7 @@ start:
if (!can_retry) {
set_btree_node_read_error(b);
bch2_btree_lost_data(c, b->c.btree_id);
break;
}
}
@ -1527,9 +1530,10 @@ fsck_err:
ret = -1;
}
if (ret)
if (ret) {
set_btree_node_read_error(b);
else if (*saw_error)
bch2_btree_lost_data(c, b->c.btree_id);
} else if (*saw_error)
bch2_btree_node_rewrite_async(c, b);
for (i = 0; i < ra->nr; i++) {
@ -1665,6 +1669,7 @@ void bch2_btree_node_read(struct btree_trans *trans, struct btree *b,
bch2_fatal_error(c);
set_btree_node_read_error(b);
bch2_btree_lost_data(c, b->c.btree_id);
clear_btree_node_read_in_flight(b);
wake_up_bit(&b->flags, BTREE_NODE_read_in_flight);
printbuf_exit(&buf);

View File

@ -33,6 +33,20 @@
#define QSTR(n) { { { .len = strlen(n) } }, .name = n }
void bch2_btree_lost_data(struct bch_fs *c, enum btree_id btree)
{
u64 b = BIT_ULL(btree);
if (!(c->sb.btrees_lost_data & b)) {
bch_err(c, "flagging btree %s lost data", bch2_btree_id_str(btree));
mutex_lock(&c->sb_lock);
bch2_sb_field_get(c->disk_sb.sb, ext)->btrees_lost_data |= cpu_to_le64(b);
bch2_write_super(c);
mutex_unlock(&c->sb_lock);
}
}
static bool btree_id_is_alloc(enum btree_id id)
{
switch (id) {
@ -470,6 +484,7 @@ static int read_btree_roots(struct bch_fs *c)
}
ret = 0;
bch2_btree_lost_data(c, i);
}
}
@ -848,6 +863,14 @@ use_clean:
write_sb = true;
}
if (c->opts.fsck &&
!test_bit(BCH_FS_error, &c->flags) &&
c->recovery_pass_done == BCH_RECOVERY_PASS_NR - 1 &&
ext->btrees_lost_data) {
ext->btrees_lost_data = 0;
write_sb = true;
}
if (c->opts.fsck &&
!test_bit(BCH_FS_error, &c->flags) &&
!test_bit(BCH_FS_errors_not_fixed, &c->flags)) {

View File

@ -2,6 +2,8 @@
#ifndef _BCACHEFS_RECOVERY_H
#define _BCACHEFS_RECOVERY_H
void bch2_btree_lost_data(struct bch_fs *, enum btree_id);
int bch2_journal_replay(struct bch_fs *);
int bch2_fs_recovery(struct bch_fs *);

View File

@ -527,9 +527,11 @@ static void bch2_sb_update(struct bch_fs *c)
memset(c->sb.errors_silent, 0, sizeof(c->sb.errors_silent));
struct bch_sb_field_ext *ext = bch2_sb_field_get(src, ext);
if (ext)
if (ext) {
le_bitvector_to_cpu(c->sb.errors_silent, (void *) ext->errors_silent,
sizeof(c->sb.errors_silent) * 8);
c->sb.btrees_lost_data = le64_to_cpu(ext->btrees_lost_data);
}
for_each_member_device(c, ca) {
struct bch_member m = bch2_sb_member_get(src, ca->dev_idx);
@ -1162,6 +1164,11 @@ static void bch2_sb_ext_to_text(struct printbuf *out, struct bch_sb *sb,
kfree(errors_silent);
}
prt_printf(out, "Btrees with missing data:");
prt_tab(out);
prt_bitflags(out, __bch2_btree_ids, le64_to_cpu(e->btrees_lost_data));
prt_newline(out);
}
static const struct bch_sb_field_ops bch_sb_field_ops_ext = {