@@ -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;