mirror of https://github.com/apache/cloudstack.git
kvmk: KVM NFS disk IO driver supporting IO_URING (#5012)
Currently there is no disk IO driver configuration for VMs running on KVM. That's OK for most the cases; however, recently there have been added some quite interesting optimizations with the IO driver io_uring. Note that IO URING requires: Qemu >= 5.0, and Libvirt >= 6.3.0. By using io_uring we can see a massive I/O performance improvement within Virtual Machines running from Local and/or NFS storage. This implementation enhances the KVM disk configuration by adding workflow for setting the disk IO drivers. Additionally, if the Qemu and Libvirt versions matches with the required for having io_uring we are going to set it on the VM. If there is no support for such driver we keep it as it is nowadays, without any IO driver configured. Fixes: #4883
This commit is contained in:
parent
cc27c70e5f
commit
1d831a32a9
|
|
@ -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);
|
||||
|
|
@ -2613,6 +2623,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
disk.setDiscard(DiscardType.UNMAP);
|
||||
}
|
||||
|
||||
setDiskIoDriver(disk);
|
||||
|
||||
if (pool.getType() == StoragePoolType.RBD) {
|
||||
/*
|
||||
For RBD pools we use the secret mechanism in libvirt.
|
||||
|
|
@ -2713,6 +2725,18 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
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("/");
|
||||
|
|
|
|||
|
|
@ -651,6 +651,26 @@ public class LibvirtVMDef {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class LibvirtVMDef {
|
|||
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 class LibvirtVMDef {
|
|||
this._discard = discard;
|
||||
}
|
||||
|
||||
public DiskDef.IoDriver getIoDriver() {
|
||||
return ioDriver;
|
||||
}
|
||||
|
||||
public void setIoDriver(IoDriver ioDriver) {
|
||||
this.ioDriver = ioDriver;
|
||||
}
|
||||
|
||||
public void setDeviceType(DeviceType deviceType) {
|
||||
_deviceType = deviceType;
|
||||
}
|
||||
|
|
@ -1004,6 +1033,11 @@ public class LibvirtVMDef {
|
|||
if(_discard != null && _discard != DiscardType.IGNORE) {
|
||||
diskBuilder.append("discard='" + _discard.toString() + "' ");
|
||||
}
|
||||
|
||||
if(ioDriver != null) {
|
||||
diskBuilder.append(String.format("io='%s'", ioDriver));
|
||||
}
|
||||
|
||||
diskBuilder.append("/>\n");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 class LibvirtComputingResourceTest {
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue