Comments
Patch
@@ -378,6 +378,47 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd,
return ret;
}
+static void nvme_dsm_dealloc(NvmeNamespace *ns, uint64_t slba, uint64_t nlb)
+{
+ uint64_t nr;
+ uint64_t elba = nlb + slba;
+ unsigned long *addr = ns->util;
+ for (nr = slba; nr < elba; nr++) {
+ if (test_and_clear_bit(nr, addr)) {
+ assert(ns->id_ns.nuse > 0);
+ --ns->id_ns.nuse;
+ }
+ }
+}
+
+static uint16_t nvme_dsm(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd,
+ NvmeRequest *req)
+{
+ uint16_t nr = (cmd->cdw10 & 0xff) + 1;
+ NvmeDsmRange range[nr];
+
+ if (nvme_dma_prp(cmd->prp1, cmd->prp2, sizeof(range), n, (uint8_t *)range,
+ DMA_DIRECTION_TO_DEVICE)) {
+ return NVME_INVALID_FIELD | NVME_DNR;
+ }
+
+ if (cmd->cdw11 & NVME_DSMGMT_AD) {
+ int i;
+ uint64_t slba;
+ uint32_t nlb;
+ for (i = 0; i < nr; i++) {
+ slba = range[i].slba;
+ nlb = range[i].nlb;
+ if (slba + nlb > ns->id_ns.ncap) {
+ return NVME_LBA_RANGE | NVME_DNR;
+ }
+ nvme_dsm_dealloc(ns, slba, nlb);
+ /* TODO: send bdrv_aio_discard request */
+ }
+ }
+ return NVME_SUCCESS;
+}
+
static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
{
NvmeNamespace *ns;
@@ -392,6 +433,10 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
case NVME_CMD_WRITE:
case NVME_CMD_READ:
return nvme_rw(n, ns, cmd, req);
+ case NVME_CMD_DSM:
+ return nvme_dsm(n, ns, cmd, req);
+ case NVME_CMD_COMPARE:
+ case NVME_CMD_WRITE_UNCOR:
default:
return NVME_INVALID_OPCODE | NVME_DNR;
}
@@ -1345,6 +1390,7 @@ static int nvme_init(PCIDevice *pci_dev)
id->sqes = n->max_sqes << 4 | 0x6;
id->cqes = n->max_cqes << 4 | 0x4;
id->nn = n->num_namespaces;
+ id->oncs = NVME_ONCS_DSM;
id->vwc = n->vwc;
snprintf((char *)id->mn, sizeof(id->mn), "QEMU NVMe Ctrl");
snprintf((char *)id->fr, sizeof(id->fr), "1.0");
This adds support for the optional data-set-management command. Action is only done for the deallocate option. Signed-off-by: Keith Busch <keith.busch@intel.com> --- hw/nvme.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 46 insertions(+), 0 deletions(-)