mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 20:22:09 +00:00
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:
parent
afa7cb0c36
commit
5db43418d5
@ -1499,6 +1499,9 @@ void __bch2_btree_node_write(struct bch_fs *c, struct btree *b,
|
|||||||
if (!btree_node_may_write(b))
|
if (!btree_node_may_write(b))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (old & (1 << BTREE_NODE_never_write))
|
||||||
|
return;
|
||||||
|
|
||||||
if (old & (1 << BTREE_NODE_write_in_flight)) {
|
if (old & (1 << BTREE_NODE_write_in_flight)) {
|
||||||
btree_node_wait_on_io(b);
|
btree_node_wait_on_io(b);
|
||||||
continue;
|
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));
|
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: */
|
/* bch2_varint_decode may read up to 7 bytes past the end of the buffer: */
|
||||||
bytes += 8;
|
bytes += 8;
|
||||||
|
|
||||||
|
@ -415,6 +415,7 @@ enum btree_flags {
|
|||||||
BTREE_NODE_fake,
|
BTREE_NODE_fake,
|
||||||
BTREE_NODE_old_extent_overwrite,
|
BTREE_NODE_old_extent_overwrite,
|
||||||
BTREE_NODE_need_rewrite,
|
BTREE_NODE_need_rewrite,
|
||||||
|
BTREE_NODE_never_write,
|
||||||
};
|
};
|
||||||
|
|
||||||
BTREE_FLAG(read_in_flight);
|
BTREE_FLAG(read_in_flight);
|
||||||
@ -429,6 +430,7 @@ BTREE_FLAG(dying);
|
|||||||
BTREE_FLAG(fake);
|
BTREE_FLAG(fake);
|
||||||
BTREE_FLAG(old_extent_overwrite);
|
BTREE_FLAG(old_extent_overwrite);
|
||||||
BTREE_FLAG(need_rewrite);
|
BTREE_FLAG(need_rewrite);
|
||||||
|
BTREE_FLAG(never_write);
|
||||||
|
|
||||||
static inline struct btree_write *btree_current_write(struct btree *b)
|
static inline struct btree_write *btree_current_write(struct btree *b)
|
||||||
{
|
{
|
||||||
|
@ -603,17 +603,30 @@ err:
|
|||||||
|
|
||||||
list_del(&as->write_blocked_list);
|
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);
|
struct bset *i = btree_bset_last(b);
|
||||||
|
|
||||||
BUG_ON(!b->c.level);
|
BUG_ON(!b->c.level);
|
||||||
BUG_ON(!btree_node_dirty(b));
|
BUG_ON(!btree_node_dirty(b));
|
||||||
|
|
||||||
i->journal_seq = cpu_to_le64(
|
if (!ret) {
|
||||||
max(journal_seq,
|
i->journal_seq = cpu_to_le64(
|
||||||
le64_to_cpu(i->journal_seq)));
|
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);
|
mutex_unlock(&c->btree_interior_update_lock);
|
||||||
|
Loading…
Reference in New Issue
Block a user