diff --git a/sys/dev/nvme/nvme_qpair.c b/sys/dev/nvme/nvme_qpair.c --- a/sys/dev/nvme/nvme_qpair.c +++ b/sys/dev/nvme/nvme_qpair.c @@ -945,6 +945,15 @@ { struct nvme_tracker *tr; + /* + * nvme_complete_tracker must be called without the qpair lock held. It + * takes the lock to adjust outstanding_tr list, so make sure we don't + * have it yet (since this is a general purpose routine). Since we + * restart the list scan when we complete one tracker, it's safe to do + * this w/o the lock. + */ + mtx_assert(&qpair->lock, MA_UNOWNED); + tr = TAILQ_FIRST(&qpair->outstanding_tr); while (tr != NULL) { if (tr->req->cmd.opc == NVME_OPC_ASYNC_EVENT_REQUEST) { @@ -961,6 +970,7 @@ void nvme_admin_qpair_destroy(struct nvme_qpair *qpair) { + mtx_assert(&qpair->lock, MA_UNOWNED); nvme_admin_qpair_abort_aers(qpair); nvme_qpair_destroy(qpair); @@ -1410,12 +1420,13 @@ nvme_admin_qpair_disable(struct nvme_qpair *qpair) { mtx_lock(&qpair->recovery); - mtx_lock(&qpair->lock); + mtx_lock(&qpair->lock); nvme_qpair_disable(qpair); + mtx_unlock(&qpair->lock); + nvme_admin_qpair_abort_aers(qpair); - mtx_unlock(&qpair->lock); mtx_unlock(&qpair->recovery); }