hw/nvme: actually implement abort

Abort was not implemented previously, but we can implement it for AERs
and asynchrnously for I/O.

Signed-off-by: Ayush Mishra <ayush.m55@samsung.com>
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
This commit is contained in:
Ayush Mishra 2024-07-02 13:32:32 +05:30 committed by Klaus Jensen
parent d522aef88d
commit 75209c071a

View File

@ -1758,6 +1758,10 @@ static void nvme_aio_err(NvmeRequest *req, int ret)
break;
}
if (ret == -ECANCELED) {
status = NVME_CMD_ABORT_REQ;
}
trace_pci_nvme_err_aio(nvme_cid(req), strerror(-ret), status);
error_setg_errno(&local_err, -ret, "aio failed");
@ -5950,12 +5954,40 @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeRequest *req)
static uint16_t nvme_abort(NvmeCtrl *n, NvmeRequest *req)
{
uint16_t sqid = le32_to_cpu(req->cmd.cdw10) & 0xffff;
uint16_t cid = (le32_to_cpu(req->cmd.cdw10) >> 16) & 0xffff;
NvmeSQueue *sq = n->sq[sqid];
NvmeRequest *r, *next;
int i;
req->cqe.result = 1;
if (nvme_check_sqid(n, sqid)) {
return NVME_INVALID_FIELD | NVME_DNR;
}
if (sqid == 0) {
for (i = 0; i < n->outstanding_aers; i++) {
NvmeRequest *re = n->aer_reqs[i];
if (re->cqe.cid == cid) {
memmove(n->aer_reqs + i, n->aer_reqs + i + 1,
(n->outstanding_aers - i - 1) * sizeof(NvmeRequest *));
n->outstanding_aers--;
re->status = NVME_CMD_ABORT_REQ;
req->cqe.result = 0;
nvme_enqueue_req_completion(&n->admin_cq, re);
return NVME_SUCCESS;
}
}
}
QTAILQ_FOREACH_SAFE(r, &sq->out_req_list, entry, next) {
if (r->cqe.cid == cid) {
if (r->aiocb) {
blk_aio_cancel_async(r->aiocb);
}
break;
}
}
return NVME_SUCCESS;
}