bcachefs: Don't issue btree writes that weren't journalled

If we have an error in the btree interior update path that prevents us
from journalling the update, we can't issue the corresponding btree node
write - we didn't get a journal sequence number that would cause it to
be ignored in recovery.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2020-12-03 16:20:18 -05:00 committed by Kent Overstreet
parent afa7cb0c36
commit 5db43418d5
3 changed files with 25 additions and 5 deletions

View File

@ -1499,6 +1499,9 @@ void __bch2_btree_node_write(struct bch_fs *c, struct btree *b,
if (!btree_node_may_write(b))
return;
if (old & (1 << BTREE_NODE_never_write))
return;
if (old & (1 << BTREE_NODE_write_in_flight)) {
btree_node_wait_on_io(b);
continue;
@ -1545,6 +1548,8 @@ void __bch2_btree_node_write(struct bch_fs *c, struct btree *b,
seq = max(seq, le64_to_cpu(i->journal_seq));
}
BUG_ON(b->written && !seq);
/* bch2_varint_decode may read up to 7 bytes past the end of the buffer: */
bytes += 8;

View File

@ -415,6 +415,7 @@ enum btree_flags {
BTREE_NODE_fake,
BTREE_NODE_old_extent_overwrite,
BTREE_NODE_need_rewrite,
BTREE_NODE_never_write,
};
BTREE_FLAG(read_in_flight);
@ -429,6 +430,7 @@ BTREE_FLAG(dying);
BTREE_FLAG(fake);
BTREE_FLAG(old_extent_overwrite);
BTREE_FLAG(need_rewrite);
BTREE_FLAG(never_write);
static inline struct btree_write *btree_current_write(struct btree *b)
{

View File

@ -603,17 +603,30 @@ err:
list_del(&as->write_blocked_list);
if (!ret && as->b == b) {
/*
* Node might have been freed, recheck under
* btree_interior_update_lock:
*/
if (as->b == b) {
struct bset *i = btree_bset_last(b);
BUG_ON(!b->c.level);
BUG_ON(!btree_node_dirty(b));
i->journal_seq = cpu_to_le64(
max(journal_seq,
le64_to_cpu(i->journal_seq)));
if (!ret) {
i->journal_seq = cpu_to_le64(
max(journal_seq,
le64_to_cpu(i->journal_seq)));
bch2_btree_add_journal_pin(c, b, journal_seq);
bch2_btree_add_journal_pin(c, b, journal_seq);
} else {
/*
* If we didn't get a journal sequence number we
* can't write this btree node, because recovery
* won't know to ignore this write:
*/
set_btree_node_never_write(b);
}
}
mutex_unlock(&c->btree_interior_update_lock);