Skip to content

Commit 2446e0e

Browse files
committed
block/nvme: poll queues without q->lock
A lot of CPU time is spent simply locking/unlocking q->lock during polling. Check for completion outside the lock to make q->lock disappear from the profile. Signed-off-by: Stefan Hajnoczi <[email protected]> Reviewed-by: Sergio Lopez <[email protected]> Message-id: [email protected] Signed-off-by: Stefan Hajnoczi <[email protected]>
1 parent d6d1a65 commit 2446e0e

File tree

1 file changed

+12
-0
lines changed

1 file changed

+12
-0
lines changed

block/nvme.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,18 @@ static bool nvme_poll_queues(BDRVNVMeState *s)
512512

513513
for (i = 0; i < s->nr_queues; i++) {
514514
NVMeQueuePair *q = s->queues[i];
515+
const size_t cqe_offset = q->cq.head * NVME_CQ_ENTRY_BYTES;
516+
NvmeCqe *cqe = (NvmeCqe *)&q->cq.queue[cqe_offset];
517+
518+
/*
519+
* Do an early check for completions. q->lock isn't needed because
520+
* nvme_process_completion() only runs in the event loop thread and
521+
* cannot race with itself.
522+
*/
523+
if ((le16_to_cpu(cqe->status) & 0x1) == q->cq_phase) {
524+
continue;
525+
}
526+
515527
qemu_mutex_lock(&q->lock);
516528
while (nvme_process_completion(s, q)) {
517529
/* Keep polling */

0 commit comments

Comments
 (0)