diff options
Diffstat (limited to 'hw/nvme/ctrl.c')
-rw-r--r-- | hw/nvme/ctrl.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index e031c2250a..355668bdf8 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -2855,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; @@ -3167,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; |