]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Implement support for iothread <-> virtqueue mapping for 'virtio-scsi' controllers
authorPeter Krempa <pkrempa@redhat.com>
Fri, 14 Feb 2025 14:13:36 +0000 (15:13 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Wed, 19 Mar 2025 14:38:00 +0000 (15:38 +0100)
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>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
src/qemu/qemu_command.c
src/qemu/qemu_validate.c

index 84ff62cd6c91cbf9edaa591e9c5da55f11c501c3..7ec1ffc1529f5acf215f9a173c35d3e286a7ea9a 100644 (file)
@@ -2498,6 +2498,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;
 
@@ -2509,6 +2510,10 @@ qemuBuildControllerSCSIDevProps(virDomainControllerDef *def,
                                               qemuCaps)))
             return NULL;
 
+        if (def->iothreads &&
+            !(iothreadsMapping = qemuBuildIothreadMappingProps(def->iothreads)))
+            return NULL;
+
         if (def->iothread > 0)
             iothread = g_strdup_printf("iothread%u", def->iothread);
 
@@ -2516,6 +2521,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,
index 19af0f02099b1e9ebe6f4ef0a627d9004a70f31c..b2c3c9e2f63170b2baf2e52d66539cfec001b1e1 100644 (file)
@@ -3657,9 +3657,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 &&
@@ -3670,8 +3671,20 @@ qemuValidateCheckSCSIControllerIOThreads(const virDomainControllerDef *controlle
        return -1;
     }
 
-    /* Can we find the controller iothread in the iothreadid list? */
-    if (!virDomainIOThreadIDFind(def, controller->iothread)) {
+    if (controller->iothreads) {
+        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 (qemuDomainValidateIothreadMapping(def, controller->iothreads,
+                                              controller->queues) < 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);
@@ -3684,13 +3697,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;
 
@@ -4364,7 +4379,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: