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@redhat.com>
---
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