mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 21:51:40 +00:00
bcachefs: Fix assertion popping in transaction commit path
We can't be holding read locks on btree nodes when we go to take write locks: this would deadlock if another thread is holding an intent lock on the node we have a read lock on, and it tries to commit and upgrade to a write lock. But instead of triggering an assertion, if this happens we can just upgrade the read lock to an intent lock. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
f3721e12d0
commit
aa8889c07a
@ -503,6 +503,10 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans,
|
||||
|
||||
/*
|
||||
* Can't be holding any read locks when we go to take write locks:
|
||||
* another thread could be holding an intent lock on the same node we
|
||||
* have a read lock on, and it'll block trying to take a write lock
|
||||
* (because we hold a read lock) and it could be blocking us by holding
|
||||
* its own read lock (while we're trying to to take write locks).
|
||||
*
|
||||
* note - this must be done after bch2_trans_journal_preres_get_cold()
|
||||
* or anything else that might call bch2_trans_relock(), since that
|
||||
@ -510,9 +514,15 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans,
|
||||
*/
|
||||
trans_for_each_iter(trans, iter) {
|
||||
if (iter->nodes_locked != iter->nodes_intent_locked) {
|
||||
EBUG_ON(iter->flags & BTREE_ITER_KEEP_UNTIL_COMMIT);
|
||||
EBUG_ON(trans->iters_live & (1ULL << iter->idx));
|
||||
bch2_btree_iter_unlock_noinline(iter);
|
||||
if ((iter->flags & BTREE_ITER_KEEP_UNTIL_COMMIT) ||
|
||||
(trans->iters_live & (1ULL << iter->idx))) {
|
||||
if (!bch2_btree_iter_upgrade(iter, 1)) {
|
||||
trace_trans_restart_upgrade(trans->ip);
|
||||
return -EINTR;
|
||||
}
|
||||
} else {
|
||||
bch2_btree_iter_unlock_noinline(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user