Support KVM storage implementations controlling logical/physical block io size (#8724)

* Support KVM storage implementations controlling logical/physical block io size

* Support custom block size during disk attach

---------

Co-authored-by: Marcus Sorensen <mls@apple.com>
This commit is contained in:
Marcus Sorensen 2024-03-15 01:36:25 -07:00 committed by GitHub
parent db564b12b6
commit 92bfb4dcaa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 87 additions and 0 deletions

View File

@ -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();

View File

@ -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("<blockio ");
if (logicalBlockIOSize != null) {
diskBuilder.append(String.format("logical_block_size='%s' ", logicalBlockIOSize));
}
if (physicalBlockIOSize != null) {
diskBuilder.append(String.format("physical_block_size='%s' ", physicalBlockIOSize));
}
diskBuilder.append("/>\n");
}
if (_serial != null && !_serial.isEmpty() && _deviceType != DeviceType.LUN) {
diskBuilder.append("<serial>" + _serial + "</serial>\n");
}

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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 = "<disk device='disk' type='file'>\n<driver name='qemu' type='" + type.toString() + "' cache='" + cacheMode.toString() + "' />\n" +
"<source file='" + filePath + "'/>\n<target dev='" + diskLabel + "' bus='" + bus.toString() + "'/>\n<blockio logical_block_size='4096' />\n</disk>\n";
assertEquals(expectedXmlLogical, disk.toString());
String expectedXmlPhysical = "<disk device='disk' type='file'>\n<driver name='qemu' type='" + type.toString() + "' cache='" + cacheMode.toString() + "' />\n" +
"<source file='" + filePath + "'/>\n<target dev='" + diskLabel + "' bus='" + bus.toString() + "'/>\n<blockio physical_block_size='4096' />\n</disk>\n";
disk.setLogicalBlockIOSize(null);
disk.setPhysicalBlockIOSize(DiskDef.BlockIOSize.SIZE_4K);
assertEquals(expectedXmlPhysical, disk.toString());
disk.setLogicalBlockIOSize(DiskDef.BlockIOSize.SIZE_512);
String expectedXml = "<disk device='disk' type='file'>\n<driver name='qemu' type='" + type.toString() + "' cache='" + cacheMode.toString() + "' />\n" +
"<source file='" + filePath + "'/>\n<target dev='" + diskLabel + "' bus='" + bus.toString() + "'/>\n<blockio logical_block_size='512' physical_block_size='4096' />\n</disk>\n";
assertEquals(expectedXml, disk.toString());
}
@Test
public void testDiskDefWithMultipleHosts() {
String path = "/mnt/primary1";