Commit 39dcace8 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Fix locking in btree_node_write_done()

There was a rare recursive locking bug, in __bch2_btree_node_write()
nowrite path -> btree_node_write_done(), in the path that kicks off
another write.

This splits out an inner __btree_node_write_done() that expects to be
run with the btree node lock held.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@gmail.com>
parent 75ef2c59
......@@ -1592,29 +1592,13 @@ void bch2_btree_complete_write(struct bch_fs *c, struct btree *b,
bch2_journal_pin_drop(&c->journal, &w->journal);
}
static void btree_node_write_done(struct bch_fs *c, struct btree *b)
static void __btree_node_write_done(struct bch_fs *c, struct btree *b)
{
struct btree_write *w = btree_prev_write(b);
unsigned long old, new, v;
bch2_btree_complete_write(c, b, w);
v = READ_ONCE(b->flags);
do {
old = new = v;
if (old & (1U << BTREE_NODE_need_write))
goto do_write;
new &= ~(1U << BTREE_NODE_write_in_flight);
new &= ~(1U << BTREE_NODE_write_in_flight_inner);
} while ((v = cmpxchg(&b->flags, old, new)) != old);
wake_up_bit(&b->flags, BTREE_NODE_write_in_flight);
return;
do_write:
six_lock_read(&b->c.lock, NULL, NULL);
v = READ_ONCE(b->flags);
do {
old = new = v;
......@@ -1637,7 +1621,12 @@ static void btree_node_write_done(struct bch_fs *c, struct btree *b)
if (new & (1U << BTREE_NODE_write_in_flight))
__bch2_btree_node_write(c, b, true);
}
static void btree_node_write_done(struct bch_fs *c, struct btree *b)
{
six_lock_read(&b->c.lock, NULL, NULL);
__btree_node_write_done(c, b);
six_unlock_read(&b->c.lock);
}
......@@ -1992,7 +1981,7 @@ void __bch2_btree_node_write(struct bch_fs *c, struct btree *b, bool already_sta
b->written += sectors_to_write;
nowrite:
btree_bounce_free(c, bytes, used_mempool, data);
btree_node_write_done(c, b);
__btree_node_write_done(c, b);
}
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment