block/nvme: separate nvme_get_free_req cases for coroutine/non-coroutine context
nvme_get_free_req has very difference semantics when called in coroutine context (where it waits) and in non-coroutine context (where it doesn't). Split the two cases to make it clear what is being requested. Cc: qemu-block@nongnu.org Reviewed-by: Alberto Faria <afaria@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Message-Id: <20220922084924.201610-2-pbonzini@redhat.com> [kwolf: Fixed up coding style] Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
ef770f8101
commit
82c45371ba
48
block/nvme.c
48
block/nvme.c
|
@ -293,34 +293,42 @@ static void nvme_kick(NVMeQueuePair *q)
|
||||||
q->need_kick = 0;
|
q->need_kick = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find a free request element if any, otherwise:
|
static NVMeRequest *nvme_get_free_req_nofail_locked(NVMeQueuePair *q)
|
||||||
* a) if in coroutine context, try to wait for one to become available;
|
|
||||||
* b) if not in coroutine, return NULL;
|
|
||||||
*/
|
|
||||||
static NVMeRequest *nvme_get_free_req(NVMeQueuePair *q)
|
|
||||||
{
|
{
|
||||||
NVMeRequest *req;
|
NVMeRequest *req;
|
||||||
|
|
||||||
qemu_mutex_lock(&q->lock);
|
|
||||||
|
|
||||||
while (q->free_req_head == -1) {
|
|
||||||
if (qemu_in_coroutine()) {
|
|
||||||
trace_nvme_free_req_queue_wait(q->s, q->index);
|
|
||||||
qemu_co_queue_wait(&q->free_req_queue, &q->lock);
|
|
||||||
} else {
|
|
||||||
qemu_mutex_unlock(&q->lock);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req = &q->reqs[q->free_req_head];
|
req = &q->reqs[q->free_req_head];
|
||||||
q->free_req_head = req->free_req_next;
|
q->free_req_head = req->free_req_next;
|
||||||
req->free_req_next = -1;
|
req->free_req_next = -1;
|
||||||
|
|
||||||
qemu_mutex_unlock(&q->lock);
|
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return a free request element if any, otherwise return NULL. */
|
||||||
|
static NVMeRequest *nvme_get_free_req_nowait(NVMeQueuePair *q)
|
||||||
|
{
|
||||||
|
QEMU_LOCK_GUARD(&q->lock);
|
||||||
|
if (q->free_req_head == -1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return nvme_get_free_req_nofail_locked(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for a free request to become available if necessary, then
|
||||||
|
* return it.
|
||||||
|
*/
|
||||||
|
static coroutine_fn NVMeRequest *nvme_get_free_req(NVMeQueuePair *q)
|
||||||
|
{
|
||||||
|
QEMU_LOCK_GUARD(&q->lock);
|
||||||
|
|
||||||
|
while (q->free_req_head == -1) {
|
||||||
|
trace_nvme_free_req_queue_wait(q->s, q->index);
|
||||||
|
qemu_co_queue_wait(&q->free_req_queue, &q->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nvme_get_free_req_nofail_locked(q);
|
||||||
|
}
|
||||||
|
|
||||||
/* With q->lock */
|
/* With q->lock */
|
||||||
static void nvme_put_free_req_locked(NVMeQueuePair *q, NVMeRequest *req)
|
static void nvme_put_free_req_locked(NVMeQueuePair *q, NVMeRequest *req)
|
||||||
{
|
{
|
||||||
|
@ -506,7 +514,7 @@ static int nvme_admin_cmd_sync(BlockDriverState *bs, NvmeCmd *cmd)
|
||||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||||
NVMeRequest *req;
|
NVMeRequest *req;
|
||||||
int ret = -EINPROGRESS;
|
int ret = -EINPROGRESS;
|
||||||
req = nvme_get_free_req(q);
|
req = nvme_get_free_req_nowait(q);
|
||||||
if (!req) {
|
if (!req) {
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue