Commit 2e2b31d
committed
nvme: deadlock enabling doorbell buffer while doing I/O
9a3a93a introduced a bug in the previously-okay SubQueue::pop; before,
acc_mem.access() would go through MemAccessor, acquire a reference on
the underlying MemCtx (an Arc refcount bump), drop the lock, and
continue. immediately after, SubQueue::pop would lock the SubQueue's
state and actually perform the pop.
this ordering is backwards from set_db_buf, which locks the SubQueue's
state *then* conditionally performs acc_mem.access() if the buffer is
set up as part of an import.
after 9a3a93a, SubQueue::pop uses access_borrowed() to avoid contention
on the refcount for MemCtx, the cost of retaining the lock on the
SubQueue's MemAccessor node while taking the lock on the same queue's
SubQueueState. at this point a concurrent SubQueue::pop and
SubQueue::set_db_buf could deadlock; one holds the queue state lock, the
other holds the accessor node lock, and both will try to take the other.
resolve this tension by picking a consistent ordering for the SubQueue
state and acc_mem locks: SubQueueState first, then
acc_mem.{access,_borrow}(). this was already the ordering in
SubQueueState::push and set_db_buf, so pop() gets the trivial change.1 parent 29e9cf7 commit 2e2b31d
1 file changed
Lines changed: 3 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
649 | 649 | | |
650 | 650 | | |
651 | 651 | | |
652 | | - | |
653 | | - | |
654 | | - | |
655 | 652 | | |
656 | 653 | | |
657 | 654 | | |
658 | 655 | | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
659 | 659 | | |
660 | 660 | | |
661 | 661 | | |
| |||
0 commit comments