Skip to content

Commit 27f23f4

Browse files
authored
linstor: Improve copyPhysicalDisk performance (#9417)
Tell qemu-img that we don't want to use a write cache (we are a block device) and also specify that we have zeroed devices in most cases.
1 parent 2e0024e commit 27f23f4

File tree

1 file changed

+38
-1
lines changed

1 file changed

+38
-1
lines changed

plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import com.linbit.linstor.api.model.ResourceMakeAvailable;
5555
import com.linbit.linstor.api.model.ResourceWithVolumes;
5656
import com.linbit.linstor.api.model.StoragePool;
57+
import com.linbit.linstor.api.model.Volume;
5758
import com.linbit.linstor.api.model.VolumeDefinition;
5859

5960
@StorageAdaptorInfo(storagePoolType=Storage.StoragePoolType.Linstor)
@@ -473,6 +474,40 @@ public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name, KVMSt
473474
return copyPhysicalDisk(disk, name, destPool, timeout, null, null, null);
474475
}
475476

477+
/**
478+
* Checks if all diskful resource are on a zeroed block device.
479+
* @param destPool Linstor pool to use
480+
* @param resName Linstor resource name
481+
* @return true if all resources are on a provider with zeroed blocks.
482+
*/
483+
private boolean resourceSupportZeroBlocks(KVMStoragePool destPool, String resName) {
484+
final DevelopersApi api = getLinstorAPI(destPool);
485+
486+
try {
487+
List<ResourceWithVolumes> resWithVols = api.viewResources(
488+
Collections.emptyList(),
489+
Collections.singletonList(resName),
490+
Collections.emptyList(),
491+
Collections.emptyList(),
492+
null,
493+
null);
494+
495+
if (resWithVols != null) {
496+
return resWithVols.stream()
497+
.allMatch(res -> {
498+
Volume vol0 = res.getVolumes().get(0);
499+
return vol0 != null && (vol0.getProviderKind() == ProviderKind.LVM_THIN ||
500+
vol0.getProviderKind() == ProviderKind.ZFS ||
501+
vol0.getProviderKind() == ProviderKind.ZFS_THIN ||
502+
vol0.getProviderKind() == ProviderKind.DISKLESS);
503+
} );
504+
}
505+
} catch (ApiException apiExc) {
506+
s_logger.error(apiExc.getMessage());
507+
}
508+
return false;
509+
}
510+
476511
@Override
477512
public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name, KVMStoragePool destPools, int timeout, byte[] srcPassphrase, byte[] destPassphrase, Storage.ProvisioningType provisioningType)
478513
{
@@ -489,8 +524,10 @@ public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name, KVMSt
489524
destFile.setFormat(dstDisk.getFormat());
490525
destFile.setSize(disk.getVirtualSize());
491526

527+
boolean zeroedDevice = resourceSupportZeroBlocks(destPools, LinstorUtil.RSC_PREFIX + name);
528+
492529
try {
493-
final QemuImg qemu = new QemuImg(timeout);
530+
final QemuImg qemu = new QemuImg(timeout, zeroedDevice, true);
494531
qemu.convert(srcFile, destFile);
495532
} catch (QemuImgException | LibvirtException e) {
496533
s_logger.error(e);

0 commit comments

Comments
 (0)