Skip to content

Commit 6ec8623

Browse files
author
Kent Overstreet
committed
bcachefs: btree node scan: fall back to comparing by journal seq
highly damaged filesystems, or filesystems that have been damaged and repair and damaged again, may have sequence numbers we can't fully trust - which in itself is something we need to debug. Add a journal_seq fallback so that repair doesn't get stuck. Signed-off-by: Kent Overstreet <[email protected]>
1 parent 375476c commit 6ec8623

File tree

3 files changed

+41
-15
lines changed

3 files changed

+41
-15
lines changed

fs/bcachefs/btree_io.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
10061006
BTREE_PTR_RANGE_UPDATED(&bkey_i_to_btree_ptr_v2(&b->key)->v);
10071007
unsigned u64s;
10081008
unsigned ptr_written = btree_ptr_sectors_written(bkey_i_to_s_c(&b->key));
1009+
u64 max_journal_seq = 0;
10091010
struct printbuf buf = PRINTBUF;
10101011
int ret = 0, retry_read = 0, write = READ;
10111012
u64 start_time = local_clock();
@@ -1181,6 +1182,8 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
11811182
sort_iter_add(iter,
11821183
vstruct_idx(i, 0),
11831184
vstruct_last(i));
1185+
1186+
max_journal_seq = max(max_journal_seq, le64_to_cpu(i->journal_seq));
11841187
}
11851188

11861189
if (ptr_written) {
@@ -1217,6 +1220,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
12171220
swap(sorted, b->data);
12181221
set_btree_bset(b, b->set, &b->data->keys);
12191222
b->nsets = 1;
1223+
b->data->keys.journal_seq = cpu_to_le64(max_journal_seq);
12201224

12211225
BUG_ON(b->nr.live_u64s != u64s);
12221226

fs/bcachefs/btree_node_scan.c

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ struct find_btree_nodes_worker {
2222

2323
static void found_btree_node_to_text(struct printbuf *out, struct bch_fs *c, const struct found_btree_node *n)
2424
{
25-
prt_printf(out, "%s l=%u seq=%u cookie=%llx ", bch2_btree_id_str(n->btree_id), n->level, n->seq, n->cookie);
25+
prt_printf(out, "%s l=%u seq=%u journal_seq=%llu cookie=%llx ",
26+
bch2_btree_id_str(n->btree_id), n->level, n->seq,
27+
n->journal_seq, n->cookie);
2628
bch2_bpos_to_text(out, n->min_key);
2729
prt_str(out, "-");
2830
bch2_bpos_to_text(out, n->max_key);
@@ -63,19 +65,37 @@ static void found_btree_node_to_key(struct bkey_i *k, const struct found_btree_n
6365
memcpy(bp->v.start, f->ptrs, sizeof(struct bch_extent_ptr) * f->nr_ptrs);
6466
}
6567

68+
static inline u64 bkey_journal_seq(struct bkey_s_c k)
69+
{
70+
switch (k.k->type) {
71+
case KEY_TYPE_inode_v3:
72+
return le64_to_cpu(bkey_s_c_to_inode_v3(k).v->bi_journal_seq);
73+
default:
74+
return 0;
75+
}
76+
}
77+
6678
static bool found_btree_node_is_readable(struct btree_trans *trans,
6779
struct found_btree_node *f)
6880
{
69-
struct { __BKEY_PADDED(k, BKEY_BTREE_PTR_VAL_U64s_MAX); } k;
81+
struct { __BKEY_PADDED(k, BKEY_BTREE_PTR_VAL_U64s_MAX); } tmp;
7082

71-
found_btree_node_to_key(&k.k, f);
83+
found_btree_node_to_key(&tmp.k, f);
7284

73-
struct btree *b = bch2_btree_node_get_noiter(trans, &k.k, f->btree_id, f->level, false);
85+
struct btree *b = bch2_btree_node_get_noiter(trans, &tmp.k, f->btree_id, f->level, false);
7486
bool ret = !IS_ERR_OR_NULL(b);
7587
if (!ret)
7688
return ret;
7789

7890
f->sectors_written = b->written;
91+
f->journal_seq = le64_to_cpu(b->data->keys.journal_seq);
92+
93+
struct bkey_s_c k;
94+
struct bkey unpacked;
95+
struct btree_node_iter iter;
96+
for_each_btree_node_key_unpack(b, k, &iter, &unpacked)
97+
f->journal_seq = max(f->journal_seq, bkey_journal_seq(k));
98+
7999
six_unlock_read(&b->c.lock);
80100

81101
/*
@@ -84,7 +104,7 @@ static bool found_btree_node_is_readable(struct btree_trans *trans,
84104
* this node
85105
*/
86106
if (b != btree_node_root(trans->c, b))
87-
bch2_btree_node_evict(trans, &k.k);
107+
bch2_btree_node_evict(trans, &tmp.k);
88108
return ret;
89109
}
90110

@@ -105,7 +125,8 @@ static int found_btree_node_cmp_cookie(const void *_l, const void *_r)
105125
static int found_btree_node_cmp_time(const struct found_btree_node *l,
106126
const struct found_btree_node *r)
107127
{
108-
return cmp_int(l->seq, r->seq);
128+
return cmp_int(l->seq, r->seq) ?:
129+
cmp_int(l->journal_seq, r->journal_seq);
109130
}
110131

111132
static int found_btree_node_cmp_pos(const void *_l, const void *_r)
@@ -309,15 +330,15 @@ static int handle_overwrites(struct bch_fs *c,
309330
} else if (n->level) {
310331
n->overwritten = true;
311332
} else {
312-
struct printbuf buf = PRINTBUF;
313-
314-
prt_str(&buf, "overlapping btree nodes with same seq! halting\n ");
315-
found_btree_node_to_text(&buf, c, start);
316-
prt_str(&buf, "\n ");
317-
found_btree_node_to_text(&buf, c, n);
318-
bch_err(c, "%s", buf.buf);
319-
printbuf_exit(&buf);
320-
return -BCH_ERR_fsck_repair_unimplemented;
333+
if (bpos_cmp(start->max_key, n->max_key) >= 0)
334+
n->overwritten = true;
335+
else {
336+
n->range_updated = true;
337+
n->min_key = bpos_successor(start->max_key);
338+
n->range_updated = true;
339+
bubble_up(n, end);
340+
goto again;
341+
}
321342
}
322343
}
323344

fs/bcachefs/btree_node_scan_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ struct found_btree_node {
1111
u8 level;
1212
unsigned sectors_written;
1313
u32 seq;
14+
u64 journal_seq;
1415
u64 cookie;
1516

1617
struct bpos min_key;

0 commit comments

Comments
 (0)