diff options
Diffstat (limited to 'hw/nvme/ctrl.c')
-rw-r--r-- | hw/nvme/ctrl.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index fd917fcda1..355668bdf8 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -43,7 +43,14 @@ * subsys=<subsys_id> * -device nvme-ns,drive=<drive_id>,bus=<bus_name>,nsid=<nsid>,\ * zoned=<true|false[optional]>, \ - * subsys=<subsys_id>,detached=<true|false[optional]> + * subsys=<subsys_id>,shared=<true|false[optional]>, \ + * detached=<true|false[optional]>, \ + * zoned.zone_size=<N[optional]>, \ + * zoned.zone_capacity=<N[optional]>, \ + * zoned.descr_ext_size=<N[optional]>, \ + * zoned.max_active=<N[optional]>, \ + * zoned.max_open=<N[optional]>, \ + * zoned.cross_read=<true|false[optional]> * * Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at * offset 0 in BAR2 and supports only WDS, RDS and SQS for now. By default, the @@ -1748,6 +1755,7 @@ static void nvme_aio_err(NvmeRequest *req, int ret) case NVME_CMD_WRITE: case NVME_CMD_WRITE_ZEROES: case NVME_CMD_ZONE_APPEND: + case NVME_CMD_COPY: status = NVME_WRITE_FAULT; break; default: @@ -2847,6 +2855,25 @@ static void nvme_copy_source_range_parse(void *ranges, int idx, uint8_t format, } } +static inline uint16_t nvme_check_copy_mcl(NvmeNamespace *ns, + NvmeCopyAIOCB *iocb, uint16_t nr) +{ + uint32_t copy_len = 0; + + for (int idx = 0; idx < nr; idx++) { + uint32_t nlb; + nvme_copy_source_range_parse(iocb->ranges, idx, iocb->format, NULL, + &nlb, NULL, NULL, NULL); + copy_len += nlb + 1; + } + + if (copy_len > ns->id_ns.mcl) { + return NVME_CMD_SIZE_LIMIT | NVME_DNR; + } + + return NVME_SUCCESS; +} + static void nvme_copy_out_completed_cb(void *opaque, int ret) { NvmeCopyAIOCB *iocb = opaque; @@ -3159,6 +3186,11 @@ static uint16_t nvme_copy(NvmeCtrl *n, NvmeRequest *req) } } + status = nvme_check_copy_mcl(ns, iocb, nr); + if (status) { + goto invalid; + } + iocb->req = req; iocb->ret = 0; iocb->nr = nr; |