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 0a253878daf..7ba75d65466 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
@@ -3058,6 +3058,13 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
disk.setBusType(DiskDef.DiskBus.SCSI);
}
} else {
+ if (pool == null) {
+ throw new CloudRuntimeException(String.format("Found null pool for volume %s", volume));
+ }
+
+ disk.setLogicalBlockIOSize(pool.getSupportedLogicalBlockSize());
+ disk.setPhysicalBlockIOSize(pool.getSupportedPhysicalBlockSize());
+
if (diskBusType == DiskDef.DiskBus.SCSI ) {
disk.setQemuDriver(true);
disk.setDiscard(DiscardType.UNMAP);
@@ -3486,6 +3493,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
if (cacheMode != null) {
diskdef.setCacheMode(DiskDef.DiskCacheMode.valueOf(cacheMode.toUpperCase()));
}
+
+ diskdef.setPhysicalBlockIOSize(attachingPool.getSupportedPhysicalBlockSize());
+ diskdef.setLogicalBlockIOSize(attachingPool.getSupportedLogicalBlockSize());
}
final String xml = diskdef.toString();
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 09071ed6cdb..5e0c9044228 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
@@ -700,6 +700,18 @@ public class LibvirtVMDef {
}
+ public enum BlockIOSize {
+ SIZE_512("512"), SIZE_4K("4096");
+ final String blockSize;
+
+ BlockIOSize(String size) { this.blockSize = size; }
+
+ @Override
+ public String toString() {
+ return blockSize;
+ }
+ }
+
private DeviceType _deviceType; /* floppy, disk, cdrom */
private DiskType _diskType;
private DiskProtocol _diskProtocol;
@@ -733,6 +745,8 @@ public class LibvirtVMDef {
private IoDriverPolicy ioDriver;
private LibvirtDiskEncryptDetails encryptDetails;
private boolean isIothreadsEnabled;
+ private BlockIOSize logicalBlockIOSize = null;
+ private BlockIOSize physicalBlockIOSize = null;
public DiscardType getDiscard() {
return _discard;
@@ -758,6 +772,10 @@ public class LibvirtVMDef {
this.isIothreadsEnabled = isIothreadsEnabled;
}
+ public void setPhysicalBlockIOSize(BlockIOSize size) { this.physicalBlockIOSize = size; }
+
+ public void setLogicalBlockIOSize(BlockIOSize size) { this.logicalBlockIOSize = size; }
+
public void defFileBasedDisk(String filePath, String diskLabel, DiskBus bus, DiskFmtType diskFmtType) {
_diskType = DiskType.FILE;
_deviceType = DeviceType.DISK;
@@ -1156,6 +1174,17 @@ public class LibvirtVMDef {
}
diskBuilder.append("/>\n");
+ if (logicalBlockIOSize != null || physicalBlockIOSize != null) {
+ diskBuilder.append("\n");
+ }
+
if (_serial != null && !_serial.isEmpty() && _deviceType != DeviceType.LUN) {
diskBuilder.append("" + _serial + "\n");
}
diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePool.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePool.java
index 43a09ccf2bf..43547e7c7d1 100644
--- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePool.java
+++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePool.java
@@ -21,6 +21,7 @@ import java.util.Map;
import com.cloud.agent.properties.AgentProperties;
import com.cloud.agent.properties.AgentPropertiesFileHandler;
+import com.cloud.hypervisor.kvm.resource.LibvirtVMDef;
import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
import org.joda.time.Duration;
@@ -99,4 +100,12 @@ public interface KVMStoragePool {
public Boolean checkingHeartBeat(HAStoragePool pool, HostTO host);
public Boolean vmActivityCheck(HAStoragePool pool, HostTO host, Duration activityScriptTimeout, String volumeUUIDListString, String vmActivityCheckPath, long duration);
+
+ default LibvirtVMDef.DiskDef.BlockIOSize getSupportedLogicalBlockSize() {
+ return null;
+ }
+
+ default LibvirtVMDef.DiskDef.BlockIOSize getSupportedPhysicalBlockSize() {
+ return null;
+ }
}
diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
index c7261f30e8a..ce52c47119d 100644
--- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
+++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
@@ -1482,6 +1482,8 @@ public class KVMStorageProcessor implements StorageProcessor {
if (ioDriver != null) {
resource.setDiskIoDriver(diskdef, resource.getIoDriverForTheStorage(ioDriver.toUpperCase()));
}
+ diskdef.setPhysicalBlockIOSize(attachingPool.getSupportedPhysicalBlockSize());
+ diskdef.setLogicalBlockIOSize(attachingPool.getSupportedLogicalBlockSize());
}
attachOrDetachDevice(conn, attach, vmName, diskdef, waitDetachDevice);
diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java
index 5bc25167355..3e1df81713c 100644
--- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java
+++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java
@@ -280,6 +280,43 @@ public class LibvirtVMDefTest extends TestCase {
assertEquals(expectedXML, disk.toString());
}
+ @Test
+ public void testDiskDefWithBlockIO() {
+ String filePath = "/var/lib/libvirt/images/disk.qcow2";
+ String diskLabel = "vda";
+
+ DiskDef disk = new DiskDef();
+ DiskDef.DiskBus bus = DiskDef.DiskBus.VIRTIO;
+ DiskDef.DiskFmtType type = DiskDef.DiskFmtType.QCOW2;
+ DiskDef.DiskCacheMode cacheMode = DiskDef.DiskCacheMode.WRITEBACK;
+
+ disk.defFileBasedDisk(filePath, diskLabel, bus, type);
+ disk.setCacheMode(cacheMode);
+ disk.setLogicalBlockIOSize(DiskDef.BlockIOSize.SIZE_4K);
+
+ assertEquals(filePath, disk.getDiskPath());
+ assertEquals(diskLabel, disk.getDiskLabel());
+ assertEquals(bus, disk.getBusType());
+ assertEquals(DiskDef.DeviceType.DISK, disk.getDeviceType());
+
+ String expectedXmlLogical = "\n\n" +
+ "\n\n\n\n";
+
+ assertEquals(expectedXmlLogical, disk.toString());
+
+ String expectedXmlPhysical = "\n\n" +
+ "\n\n\n\n";
+
+ disk.setLogicalBlockIOSize(null);
+ disk.setPhysicalBlockIOSize(DiskDef.BlockIOSize.SIZE_4K);
+ assertEquals(expectedXmlPhysical, disk.toString());
+
+ disk.setLogicalBlockIOSize(DiskDef.BlockIOSize.SIZE_512);
+ String expectedXml = "\n\n" +
+ "\n\n\n\n";
+ assertEquals(expectedXml, disk.toString());
+ }
+
@Test
public void testDiskDefWithMultipleHosts() {
String path = "/mnt/primary1";