Skip to content

Commit b76cce1

Browse files
author
Kent Overstreet
committed
bcachefs: Add more flags to btree nodes for rewrite reason
It seems excessive forced btree node rewrites can cause interior btree updates to become wedged during recovery, before we're using the write buffer for backpointer updates. Add more flags so we can determine where these are coming from. Signed-off-by: Kent Overstreet <[email protected]>
1 parent c7e351b commit b76cce1

File tree

4 files changed

+48
-6
lines changed

4 files changed

+48
-6
lines changed

fs/bcachefs/btree_io.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,7 @@ static int validate_bset_keys(struct bch_fs *c, struct btree *b,
10451045
le16_add_cpu(&i->u64s, -next_good_key);
10461046
memmove_u64s_down(k, (u64 *) k + next_good_key, (u64 *) vstruct_end(i) - (u64 *) k);
10471047
set_btree_node_need_rewrite(b);
1048+
set_btree_node_need_rewrite_error(b);
10481049
}
10491050
fsck_err:
10501051
printbuf_exit(&buf);
@@ -1305,6 +1306,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
13051306
(u64 *) vstruct_end(i) - (u64 *) k);
13061307
set_btree_bset_end(b, b->set);
13071308
set_btree_node_need_rewrite(b);
1309+
set_btree_node_need_rewrite_error(b);
13081310
continue;
13091311
}
13101312
if (ret)
@@ -1329,12 +1331,16 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
13291331
bkey_for_each_ptr(bch2_bkey_ptrs(bkey_i_to_s(&b->key)), ptr) {
13301332
struct bch_dev *ca2 = bch2_dev_rcu(c, ptr->dev);
13311333

1332-
if (!ca2 || ca2->mi.state != BCH_MEMBER_STATE_rw)
1334+
if (!ca2 || ca2->mi.state != BCH_MEMBER_STATE_rw) {
13331335
set_btree_node_need_rewrite(b);
1336+
set_btree_node_need_rewrite_degraded(b);
1337+
}
13341338
}
13351339

1336-
if (!ptr_written)
1340+
if (!ptr_written) {
13371341
set_btree_node_need_rewrite(b);
1342+
set_btree_node_need_rewrite_ptr_written_zero(b);
1343+
}
13381344
fsck_err:
13391345
mempool_free(iter, &c->fill_iter);
13401346
printbuf_exit(&buf);

fs/bcachefs/btree_types.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,9 @@ enum btree_write_type {
617617
x(dying) \
618618
x(fake) \
619619
x(need_rewrite) \
620+
x(need_rewrite_error) \
621+
x(need_rewrite_degraded) \
622+
x(need_rewrite_ptr_written_zero) \
620623
x(never_write) \
621624
x(pinned)
622625

@@ -641,6 +644,32 @@ static inline void clear_btree_node_ ## flag(struct btree *b) \
641644
BTREE_FLAGS()
642645
#undef x
643646

647+
#define BTREE_NODE_REWRITE_REASON() \
648+
x(none) \
649+
x(unknown) \
650+
x(error) \
651+
x(degraded) \
652+
x(ptr_written_zero)
653+
654+
enum btree_node_rewrite_reason {
655+
#define x(n) BTREE_NODE_REWRITE_##n,
656+
BTREE_NODE_REWRITE_REASON()
657+
#undef x
658+
};
659+
660+
static inline enum btree_node_rewrite_reason btree_node_rewrite_reason(struct btree *b)
661+
{
662+
if (btree_node_need_rewrite_ptr_written_zero(b))
663+
return BTREE_NODE_REWRITE_ptr_written_zero;
664+
if (btree_node_need_rewrite_degraded(b))
665+
return BTREE_NODE_REWRITE_degraded;
666+
if (btree_node_need_rewrite_error(b))
667+
return BTREE_NODE_REWRITE_error;
668+
if (btree_node_need_rewrite(b))
669+
return BTREE_NODE_REWRITE_unknown;
670+
return BTREE_NODE_REWRITE_none;
671+
}
672+
644673
static inline struct btree_write *btree_current_write(struct btree *b)
645674
{
646675
return b->writes + btree_node_write_idx(b);

fs/bcachefs/btree_update_interior.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,13 @@ static void bch2_btree_update_done(struct btree_update *as, struct btree_trans *
11381138
start_time);
11391139
}
11401140

1141+
static const char * const btree_node_reawrite_reason_strs[] = {
1142+
#define x(n) #n,
1143+
BTREE_NODE_REWRITE_REASON()
1144+
#undef x
1145+
NULL,
1146+
};
1147+
11411148
static struct btree_update *
11421149
bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
11431150
unsigned level_start, bool split,
@@ -1235,7 +1242,7 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
12351242
struct btree *b = btree_path_node(path, path->level);
12361243
as->node_start = b->data->min_key;
12371244
as->node_end = b->data->max_key;
1238-
as->node_needed_rewrite = btree_node_need_rewrite(b);
1245+
as->node_needed_rewrite = btree_node_rewrite_reason(b);
12391246
as->node_written = b->written;
12401247
as->node_sectors = btree_buf_bytes(b) >> 9;
12411248
as->node_remaining = __bch2_btree_u64s_remaining(b,
@@ -2699,11 +2706,11 @@ static void bch2_btree_update_to_text(struct printbuf *out, struct btree_update
26992706
bch2_bpos_to_text(out, as->node_start);
27002707
prt_char(out, ' ');
27012708
bch2_bpos_to_text(out, as->node_end);
2702-
prt_printf(out, "\nwritten %u/%u u64s_remaining %u need_rewrite %u",
2709+
prt_printf(out, "\nwritten %u/%u u64s_remaining %u need_rewrite %s",
27032710
as->node_written,
27042711
as->node_sectors,
27052712
as->node_remaining,
2706-
as->node_needed_rewrite);
2713+
btree_node_reawrite_reason_strs[as->node_needed_rewrite]);
27072714

27082715
prt_printf(out, "\nmode=%s nodes_written=%u cl.remaining=%u journal_seq=%llu\n",
27092716
bch2_btree_update_modes[as->mode],

fs/bcachefs/btree_update_interior.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ struct btree_update {
5959
enum btree_id btree_id;
6060
struct bpos node_start;
6161
struct bpos node_end;
62-
bool node_needed_rewrite;
62+
enum btree_node_rewrite_reason node_needed_rewrite;
6363
u16 node_written;
6464
u16 node_sectors;
6565
u16 node_remaining;

0 commit comments

Comments
 (0)