diff options
| author | Stefan Hajnoczi | 2020-06-17 15:21:55 +0200 |
|---|---|---|
| committer | Stefan Hajnoczi | 2020-06-23 16:46:08 +0200 |
| commit | 2446e0e2e9c9aaa5f8e8c7ef9a41fe8516054831 (patch) | |
| tree | cf7b49f174a5c6880ec9e9992c1ae86a4d5a5370 /block | |
| parent | check-block: enable iotests with SafeStack (diff) | |
| download | qemu-2446e0e2e9c9aaa5f8e8c7ef9a41fe8516054831.tar.gz qemu-2446e0e2e9c9aaa5f8e8c7ef9a41fe8516054831.tar.xz qemu-2446e0e2e9c9aaa5f8e8c7ef9a41fe8516054831.zip | |
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 <stefanha@redhat.com>
Reviewed-by: Sergio Lopez <slp@redhat.com>
Message-id: 20200617132201.1832152-2-stefanha@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block')
| -rw-r--r-- | block/nvme.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/block/nvme.c b/block/nvme.c index eb2f54dd9d..e4375ec245 100644 --- a/block/nvme.c +++ b/block/nvme.c @@ -512,6 +512,18 @@ static bool nvme_poll_queues(BDRVNVMeState *s) for (i = 0; i < s->nr_queues; i++) { NVMeQueuePair *q = s->queues[i]; + const size_t cqe_offset = q->cq.head * NVME_CQ_ENTRY_BYTES; + NvmeCqe *cqe = (NvmeCqe *)&q->cq.queue[cqe_offset]; + + /* + * Do an early check for completions. q->lock isn't needed because + * nvme_process_completion() only runs in the event loop thread and + * cannot race with itself. + */ + if ((le16_to_cpu(cqe->status) & 0x1) == q->cq_phase) { + continue; + } + qemu_mutex_lock(&q->lock); while (nvme_process_completion(s, q)) { /* Keep polling */ |
