Similarly to 'virtio-blk' users can map multiple iothreads and pin them appropriately for 'virtio-scsi' controllers to ensure the best performance. Implement the validation and command line generation based on the helpers we have for 'virtio-blk'. Signed-off-by: Peter Krempa <pkrempa@xxxxxxxxxx> --- src/qemu/qemu_command.c | 22 ++++++++++++++++++++++ src/qemu/qemu_command.h | 2 ++ src/qemu/qemu_validate.c | 34 +++++++++++++++++++++++++++------- 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 14d62b98e4..fc0712f836 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1657,6 +1657,15 @@ qemuCommandGetVirtioIothreadMapVirtioBlk(const virDomainDiskDef *disk) } +GHashTable * +qemuCommandGetVirtioIothreadMapVirtioSCSI(const virDomainControllerDef *def) +{ + const char *internal_queues[] = { "ctrl", "event", NULL }; + + return qemuCommandGetVirtioIothreadMap(def->queues, internal_queues); +} + + virJSONValue * qemuBuildDiskDeviceProps(const virDomainDef *def, virDomainDiskDef *disk, @@ -2558,6 +2567,7 @@ qemuBuildControllerSCSIDevProps(virDomainControllerDef *def, virQEMUCaps *qemuCaps) { g_autoptr(virJSONValue) props = NULL; + g_autoptr(virJSONValue) iothreadsMapping = NULL; g_autofree char *iothread = NULL; const char *driver = NULL; @@ -2569,6 +2579,17 @@ qemuBuildControllerSCSIDevProps(virDomainControllerDef *def, qemuCaps))) return NULL; + if (def->iothreads) { + g_autoptr(GHashTable) queueMap = NULL; + + if (def->queues > 0) + queueMap = qemuCommandGetVirtioIothreadMapVirtioSCSI(def); + + if (!(iothreadsMapping = qemuBuildIothreadMappingProps(def->iothreads, + queueMap))) + return NULL; + } + if (def->iothread > 0) iothread = g_strdup_printf("iothread%u", def->iothread); @@ -2576,6 +2597,7 @@ qemuBuildControllerSCSIDevProps(virDomainControllerDef *def, "S:iothread", iothread, "s:id", def->info.alias, "p:num_queues", def->queues, + "A:iothread-vq-mapping", &iothreadsMapping, "p:cmd_per_lun", def->cmd_per_lun, "p:max_sectors", def->max_sectors, "T:ioeventfd", def->ioeventfd, diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 636c2571d4..d69fd793c4 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -280,3 +280,5 @@ struct qemuVirtioIothreadMap { GHashTable * qemuCommandGetVirtioIothreadMapVirtioBlk(const virDomainDiskDef *disk); +GHashTable * +qemuCommandGetVirtioIothreadMapVirtioSCSI(const virDomainControllerDef *def); diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index f8586a7dff..364bc59cba 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -3641,9 +3641,10 @@ qemuValidateDomainDeviceDefControllerIDE(const virDomainControllerDef *controlle */ static int qemuValidateCheckSCSIControllerIOThreads(const virDomainControllerDef *controller, - const virDomainDef *def) + const virDomainDef *def, + virQEMUCaps *qemuCaps) { - if (!controller->iothread) + if (controller->iothread == 0 && !controller->iothreads) return 0; if (controller->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && @@ -3654,8 +3655,24 @@ qemuValidateCheckSCSIControllerIOThreads(const virDomainControllerDef *controlle return -1; } - /* Can we find the controller iothread in the iothreadid list? */ - if (!virDomainIOThreadIDFind(def, controller->iothread)) { + if (controller->iothreads) { + g_autoptr(GHashTable) queueMap = NULL; + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_SCSI_IOTHREAD_MAPPING)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("IOThread mapping for virtio-scsi controllers is not available with this QEMU binary")); + return -1; + } + + if (controller->queues > 0) + queueMap = qemuCommandGetVirtioIothreadMapVirtioSCSI(controller); + + if (qemuDomainValidateIothreadMapping(def, controller->iothreads, queueMap) < 0) + return -1; + } + + if (controller->iothread > 0 && + !virDomainIOThreadIDFind(def, controller->iothread)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("controller iothread '%1$u' not defined in iothreadid"), controller->iothread); @@ -3668,13 +3685,15 @@ qemuValidateCheckSCSIControllerIOThreads(const virDomainControllerDef *controlle static int qemuValidateDomainDeviceDefControllerSCSI(const virDomainControllerDef *controller, - const virDomainDef *def) + const virDomainDef *def, + virQEMUCaps *qemuCaps) { switch ((virDomainControllerModelSCSI) controller->model) { case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI: case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_TRANSITIONAL: case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_NON_TRANSITIONAL: - if (qemuValidateCheckSCSIControllerIOThreads(controller, def) < 0) + if (qemuValidateCheckSCSIControllerIOThreads(controller, def, + qemuCaps) < 0) return -1; break; @@ -4348,7 +4367,8 @@ qemuValidateDomainDeviceDefController(const virDomainControllerDef *controller, break; case VIR_DOMAIN_CONTROLLER_TYPE_SCSI: - ret = qemuValidateDomainDeviceDefControllerSCSI(controller, def); + ret = qemuValidateDomainDeviceDefControllerSCSI(controller, def, + qemuCaps); break; case VIR_DOMAIN_CONTROLLER_TYPE_PCI: -- 2.48.1