diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 64a2883b7924..31420c7d2932 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -253,6 +253,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv protected static final String DEFAULT_OVS_VIF_DRIVER_CLASS_NAME = "com.cloud.hypervisor.kvm.resource.OvsVifDriver"; protected static final String DEFAULT_BRIDGE_VIF_DRIVER_CLASS_NAME = "com.cloud.hypervisor.kvm.resource.BridgeVifDriver"; + private final static long HYPERVISOR_LIBVIRT_VERSION_SUPPORTS_IO_URING = 6003000; + private final static long HYPERVISOR_QEMU_VERSION_SUPPORTS_IO_URING = 5000000; protected HypervisorType _hypervisorType; protected String _hypervisorURI; @@ -342,6 +344,14 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv protected MemStat _memStat = new MemStat(_dom0MinMem, _dom0OvercommitMem); private final LibvirtUtilitiesHelper libvirtUtilitiesHelper = new LibvirtUtilitiesHelper(); + protected long getHypervisorLibvirtVersion() { + return _hypervisorLibvirtVersion; + } + + protected long getHypervisorQemuVersion() { + return _hypervisorQemuVersion; + } + @Override public ExecutionResult executeInVR(final String routerIp, final String script, final String args) { return executeInVR(routerIp, script, args, _timeout); @@ -2619,6 +2629,8 @@ public int compare(final DiskTO arg0, final DiskTO arg1) { disk.setDiscard(DiscardType.UNMAP); } + setDiskIoDriver(disk); + if (pool.getType() == StoragePoolType.RBD) { /* For RBD pools we use the secret mechanism in libvirt. @@ -2719,6 +2731,18 @@ private KVMPhysicalDisk getPhysicalDiskPrimaryStore(PrimaryDataStoreTO primaryDa return storagePool.getPhysicalDisk(data.getPath()); } + /** + * Set Disk IO Driver, if supported by the Libvirt/Qemu version. + * IO Driver works for: + * (i) Qemu >= 5.0; + * (ii) Libvirt >= 6.3.0 + */ + protected void setDiskIoDriver(DiskDef disk) { + if (getHypervisorLibvirtVersion() >= HYPERVISOR_LIBVIRT_VERSION_SUPPORTS_IO_URING && getHypervisorQemuVersion() >= HYPERVISOR_QEMU_VERSION_SUPPORTS_IO_URING) { + disk.setIoDriver(DiskDef.IoDriver.IOURING); + } + } + private KVMPhysicalDisk getPhysicalDiskFromNfsStore(String dataStoreUrl, DataTO data) { final String volPath = dataStoreUrl + File.separator + data.getPath(); final int index = volPath.lastIndexOf("/"); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java index e2d506ce09fb..49a17ef344b2 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java @@ -651,6 +651,26 @@ public String toString() { } + /** + * This enum specifies IO Drivers, each option controls specific policies on I/O. + * Qemu guests support "threads" and "native" options Since 0.8.8 ; "io_uring" is supported Since 6.3.0 (QEMU 5.0). + */ + public enum IoDriver { + NATIVE("native"), + THREADS("threads"), + IOURING("io_uring"); + String ioDriver; + + IoDriver(String driver) { + ioDriver = driver; + } + + @Override + public String toString() { + return ioDriver; + } + } + private DeviceType _deviceType; /* floppy, disk, cdrom */ private DiskType _diskType; private DiskProtocol _diskProtocol; @@ -681,6 +701,7 @@ public String toString() { private String _serial; private boolean qemuDriver = true; private DiscardType _discard = DiscardType.IGNORE; + private IoDriver ioDriver; public DiscardType getDiscard() { return _discard; @@ -690,6 +711,14 @@ public void setDiscard(DiscardType discard) { this._discard = discard; } + public DiskDef.IoDriver getIoDriver() { + return ioDriver; + } + + public void setIoDriver(IoDriver ioDriver) { + this.ioDriver = ioDriver; + } + public void setDeviceType(DeviceType deviceType) { _deviceType = deviceType; } @@ -1001,6 +1030,11 @@ public String toString() { if(_discard != null && _discard != DiscardType.IGNORE) { diskBuilder.append("discard='" + _discard.toString() + "' "); } + + if(ioDriver != null) { + diskBuilder.append(String.format("io='%s'", ioDriver)); + } + diskBuilder.append("/>\n"); } diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index bd651f4c02c2..61572554d9e9 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -202,6 +202,9 @@ public class LibvirtComputingResourceTest { @Mock LibvirtVMDef vmDef; + private final static long HYPERVISOR_LIBVIRT_VERSION_SUPPORTS_IOURING = 6003000; + private final static long HYPERVISOR_QEMU_VERSION_SUPPORTS_IOURING = 5000000; + String hyperVisorType = "kvm"; Random random = new Random(); final String memInfo = "MemTotal: 5830236 kB\n" + @@ -5209,4 +5212,37 @@ public void testAddExtraConfigComponentNotEmptyExtraConfig() { libvirtComputingResource.addExtraConfigComponent(extraConfig, vmDef); Mockito.verify(vmDef, times(1)).addComp(any()); } + + @Test + public void setDiskIoDriverTestIoUring() { + DiskDef diskDef = configureAndTestSetDiskIoDriverTest(HYPERVISOR_LIBVIRT_VERSION_SUPPORTS_IOURING, HYPERVISOR_QEMU_VERSION_SUPPORTS_IOURING); + Assert.assertEquals(DiskDef.IoDriver.IOURING, diskDef.getIoDriver()); + } + + @Test + public void setDiskIoDriverTestLibvirtSupportsIoUring() { + DiskDef diskDef = configureAndTestSetDiskIoDriverTest(123l, HYPERVISOR_QEMU_VERSION_SUPPORTS_IOURING); + Assert.assertNotEquals(DiskDef.IoDriver.IOURING, diskDef.getIoDriver()); + } + + @Test + public void setDiskIoDriverTestQemuSupportsIoUring() { + DiskDef diskDef = configureAndTestSetDiskIoDriverTest(HYPERVISOR_LIBVIRT_VERSION_SUPPORTS_IOURING, 123l); + Assert.assertNotEquals(DiskDef.IoDriver.IOURING, diskDef.getIoDriver()); + } + + @Test + public void setDiskIoDriverTestNoSupportToIoUring() { + DiskDef diskDef = configureAndTestSetDiskIoDriverTest(123l, 123l); + Assert.assertNotEquals(DiskDef.IoDriver.IOURING, diskDef.getIoDriver()); + } + + private DiskDef configureAndTestSetDiskIoDriverTest(long hypervisorLibvirtVersion, long hypervisorQemuVersion) { + DiskDef diskDef = new DiskDef(); + LibvirtComputingResource libvirtComputingResourceSpy = Mockito.spy(new LibvirtComputingResource()); + Mockito.when(libvirtComputingResourceSpy.getHypervisorLibvirtVersion()).thenReturn(hypervisorLibvirtVersion); + Mockito.when(libvirtComputingResourceSpy.getHypervisorQemuVersion()).thenReturn(hypervisorQemuVersion); + libvirtComputingResourceSpy.setDiskIoDriver(diskDef); + return diskDef; + } }