[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v2 17/51] hw/nvme: fix aio cancel in format
From: |
Juan Quintela |
Subject: |
[PATCH v2 17/51] hw/nvme: fix aio cancel in format |
Date: |
Mon, 5 Dec 2022 10:51:54 +0100 |
From: Klaus Jensen <k.jensen@samsung.com>
There are several bugs in the async cancel code for the Format command.
Firstly, cancelling a format operation neglects to set iocb->ret as well
as clearing the iocb->aiocb after cancelling the underlying aiocb which
causes the aio callback to ignore the cancellation. Trivial fix.
Secondly, and worse, because the request is queued up for posting to the
CQ in a bottom half, if the cancellation is due to the submission queue
being deleted (which calls blk_aio_cancel), the req structure is
deallocated in nvme_del_sq prior to the bottom half being schedulued.
Fix this by simply removing the bottom half, there is no reason to defer
it anyway.
Fixes: 3bcf26d3d619 ("hw/nvme: reimplement format nvm to allow cancellation")
Reported-by: Jonathan Derrick <jonathan.derrick@linux.dev>
Reviewed-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
---
hw/nvme/ctrl.c | 28 ++++++++++++----------------
1 file changed, 12 insertions(+), 16 deletions(-)
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index ac3885ce50..9bc56075f6 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -5741,7 +5741,6 @@ static uint16_t nvme_ns_attachment(NvmeCtrl *n,
NvmeRequest *req)
typedef struct NvmeFormatAIOCB {
BlockAIOCB common;
BlockAIOCB *aiocb;
- QEMUBH *bh;
NvmeRequest *req;
int ret;
@@ -5756,14 +5755,15 @@ typedef struct NvmeFormatAIOCB {
uint8_t pil;
} NvmeFormatAIOCB;
-static void nvme_format_bh(void *opaque);
-
static void nvme_format_cancel(BlockAIOCB *aiocb)
{
NvmeFormatAIOCB *iocb = container_of(aiocb, NvmeFormatAIOCB, common);
+ iocb->ret = -ECANCELED;
+
if (iocb->aiocb) {
blk_aio_cancel_async(iocb->aiocb);
+ iocb->aiocb = NULL;
}
}
@@ -5787,13 +5787,17 @@ static void nvme_format_set(NvmeNamespace *ns, uint8_t
lbaf, uint8_t mset,
nvme_ns_init_format(ns);
}
+static void nvme_do_format(NvmeFormatAIOCB *iocb);
+
static void nvme_format_ns_cb(void *opaque, int ret)
{
NvmeFormatAIOCB *iocb = opaque;
NvmeNamespace *ns = iocb->ns;
int bytes;
- if (ret < 0) {
+ if (iocb->ret < 0) {
+ goto done;
+ } else if (ret < 0) {
iocb->ret = ret;
goto done;
}
@@ -5817,8 +5821,7 @@ static void nvme_format_ns_cb(void *opaque, int ret)
iocb->offset = 0;
done:
- iocb->aiocb = NULL;
- qemu_bh_schedule(iocb->bh);
+ nvme_do_format(iocb);
}
static uint16_t nvme_format_check(NvmeNamespace *ns, uint8_t lbaf, uint8_t pi)
@@ -5842,9 +5845,8 @@ static uint16_t nvme_format_check(NvmeNamespace *ns,
uint8_t lbaf, uint8_t pi)
return NVME_SUCCESS;
}
-static void nvme_format_bh(void *opaque)
+static void nvme_do_format(NvmeFormatAIOCB *iocb)
{
- NvmeFormatAIOCB *iocb = opaque;
NvmeRequest *req = iocb->req;
NvmeCtrl *n = nvme_ctrl(req);
uint32_t dw10 = le32_to_cpu(req->cmd.cdw10);
@@ -5882,11 +5884,7 @@ static void nvme_format_bh(void *opaque)
return;
done:
- qemu_bh_delete(iocb->bh);
- iocb->bh = NULL;
-
iocb->common.cb(iocb->common.opaque, iocb->ret);
-
qemu_aio_unref(iocb);
}
@@ -5905,7 +5903,6 @@ static uint16_t nvme_format(NvmeCtrl *n, NvmeRequest *req)
iocb = qemu_aio_get(&nvme_format_aiocb_info, NULL, nvme_misc_cb, req);
iocb->req = req;
- iocb->bh = qemu_bh_new(nvme_format_bh, iocb);
iocb->ret = 0;
iocb->ns = NULL;
iocb->nsid = 0;
@@ -5934,14 +5931,13 @@ static uint16_t nvme_format(NvmeCtrl *n, NvmeRequest
*req)
}
req->aiocb = &iocb->common;
- qemu_bh_schedule(iocb->bh);
+ nvme_do_format(iocb);
return NVME_NO_COMPLETE;
out:
- qemu_bh_delete(iocb->bh);
- iocb->bh = NULL;
qemu_aio_unref(iocb);
+
return status;
}
--
2.38.1
- [PATCH v2 07/51] hw/display/qxl: Avoid buffer overrun in qxl_phys2virt (CVE-2022-4144), (continued)
- [PATCH v2 07/51] hw/display/qxl: Avoid buffer overrun in qxl_phys2virt (CVE-2022-4144), Juan Quintela, 2022/12/05
- [PATCH v2 08/51] hw/display/qxl: Assert memory slot fits in preallocated MemoryRegion, Juan Quintela, 2022/12/05
- [PATCH v2 09/51] block-backend: avoid bdrv_unregister_buf() NULL pointer deref, Juan Quintela, 2022/12/05
- [PATCH v2 10/51] target/arm: Set TCGCPUOps.restore_state_to_opc for v7m, Juan Quintela, 2022/12/05
- [PATCH v2 11/51] Update VERSION for v7.2.0-rc3, Juan Quintela, 2022/12/05
- [PATCH v2 12/51] tests/qtests: override "force-legacy" for gpio virtio-mmio tests, Juan Quintela, 2022/12/05
- [PATCH v2 13/51] vhost: enable vrings in vhost_dev_start() for vhost-user devices, Juan Quintela, 2022/12/05
- [PATCH v2 15/51] hw/virtio: generalise CHR_EVENT_CLOSED handling, Juan Quintela, 2022/12/05
- [PATCH v2 14/51] hw/virtio: add started_vu status field to vhost-user-gpio, Juan Quintela, 2022/12/05
- [PATCH v2 16/51] include/hw: VM state takes precedence in virtio_device_should_start, Juan Quintela, 2022/12/05
- [PATCH v2 17/51] hw/nvme: fix aio cancel in format,
Juan Quintela <=
- [PATCH v2 18/51] hw/nvme: fix aio cancel in flush, Juan Quintela, 2022/12/05
- [PATCH v2 19/51] hw/nvme: fix aio cancel in zone reset, Juan Quintela, 2022/12/05
- [PATCH v2 20/51] hw/nvme: fix aio cancel in dsm, Juan Quintela, 2022/12/05
- [PATCH v2 21/51] hw/nvme: remove copy bh scheduling, Juan Quintela, 2022/12/05
- [PATCH v2 23/51] target/i386: Always completely initialize TranslateFault, Juan Quintela, 2022/12/05
- [PATCH v2 22/51] target/i386: allow MMX instructions with CR4.OSFXSR=0, Juan Quintela, 2022/12/05
- [PATCH v2 24/51] hw/loongarch/virt: Add cfi01 pflash device, Juan Quintela, 2022/12/05
- [PATCH v2 25/51] tests/qtest/migration-test: Fix unlink error and memory leaks, Juan Quintela, 2022/12/05
- [PATCH v2 26/51] target/s390x/tcg: Fix and improve the SACF instruction, Juan Quintela, 2022/12/05
- [PATCH v2 27/51] hw/display/next-fb: Fix comment typo, Juan Quintela, 2022/12/05