[PATCH 4/7] qemu: Add VIR_DOMAIN_BLOCK_COPY_TARGET_ZEROED flag for virDomainBlockCopy

Peter Krempa via Devel posted 7 patches 5 days, 6 hours ago
[PATCH 4/7] qemu: Add VIR_DOMAIN_BLOCK_COPY_TARGET_ZEROED flag for virDomainBlockCopy
Posted by Peter Krempa via Devel 5 days, 6 hours ago
From: Peter Krempa <pkrempa@redhat.com>

Allow the hypervisor to assume that the user already passed a zeroed-out
image to optimize the copy. Implement the feature for the qemu driver.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
---
 include/libvirt/libvirt-domain.h |  7 +++++++
 src/libvirt-domain.c             |  4 ++++
 src/qemu/qemu_driver.c           | 16 +++++++++++++---
 3 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index ccc2c87ea8..a0e0b84eb9 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -5004,6 +5004,13 @@ typedef enum {
      * Since: 8.0.0
      */
     VIR_DOMAIN_BLOCK_COPY_SYNCHRONOUS_WRITES = 1 << 3,
+
+    /* Destination of the copy is zeroed (any read returns only 0x00 bytes) so
+     * the hypervisor may optimize out clearing of the target image.
+     *
+     * Since: 12.2.0 */
+    VIR_DOMAIN_BLOCK_COPY_TARGET_ZEROED = 1 << 4,
+
 } virDomainBlockCopyFlags;

 /**
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 6b8783d57f..e1571cbda7 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -11261,6 +11261,10 @@ virDomainBlockRebase(virDomainPtr dom, const char *disk,
  * the destination storage is slower. This may impact performance of writes
  * while the blockjob is running.
  *
+ * If @flags contains VIR_DOMAIN_BLOCK_COPY_TARGET_ZEROED the hypervisor may
+ * assume that the target image was already zeroed out (any read will return
+ * 0x00 bytes) and thus may skip this step.
+ *
  * The @disk parameter is either an unambiguous source name of the
  * block device (the <source file='...'/> sub-element, such as
  * "/path/to/image"), or the device target shorthand (the
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0ba40e0665..42d0f46405 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -14285,13 +14285,15 @@ qemuDomainBlockCopyCommon(virDomainObj *vm,
     virStorageSource *mirrorBacking = NULL;
     g_autoptr(GHashTable) blockNamedNodeData = NULL;
     bool syncWrites = !!(flags & VIR_DOMAIN_BLOCK_COPY_SYNCHRONOUS_WRITES);
+    bool targetIsZero = !!(flags & VIR_DOMAIN_BLOCK_COPY_TARGET_ZEROED);
     int rc = 0;

     /* Preliminaries: find the disk we are editing, sanity checks */
     virCheckFlags(VIR_DOMAIN_BLOCK_COPY_SHALLOW |
                   VIR_DOMAIN_BLOCK_COPY_REUSE_EXT |
                   VIR_DOMAIN_BLOCK_COPY_TRANSIENT_JOB |
-                  VIR_DOMAIN_BLOCK_COPY_SYNCHRONOUS_WRITES, -1);
+                  VIR_DOMAIN_BLOCK_COPY_SYNCHRONOUS_WRITES |
+                  VIR_DOMAIN_BLOCK_COPY_TARGET_ZEROED, -1);

     if (virStorageSourceIsRelative(mirror)) {
         virReportError(VIR_ERR_INVALID_ARG, "%s",
@@ -14327,6 +14329,13 @@ qemuDomainBlockCopyCommon(virDomainObj *vm,
         goto endjob;
     }

+    if (targetIsZero &&
+        !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_MIRROR_TARGET_IS_ZERO)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("this qemu doesn't support 'VIR_DOMAIN_BLOCK_COPY_TARGET_ZEROED'"));
+        goto endjob;
+    }
+
     if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN &&
         virDomainDiskDefSourceLUNValidate(mirror) < 0)
         goto endjob;
@@ -14535,7 +14544,7 @@ qemuDomainBlockCopyCommon(virDomainObj *vm,
                                     qemuBlockStorageSourceGetEffectiveNodename(disk->src),
                                     bandwidth,
                                     granularity, buf_size, mirror_shallow,
-                                    syncWrites, false);
+                                    syncWrites, targetIsZero);

     virDomainAuditDisk(vm, NULL, mirror, "mirror", ret >= 0);
     qemuDomainObjExitMonitor(vm);
@@ -14670,7 +14679,8 @@ qemuDomainBlockCopy(virDomainPtr dom,
     virCheckFlags(VIR_DOMAIN_BLOCK_COPY_SHALLOW |
                   VIR_DOMAIN_BLOCK_COPY_REUSE_EXT |
                   VIR_DOMAIN_BLOCK_COPY_TRANSIENT_JOB |
-                  VIR_DOMAIN_BLOCK_COPY_SYNCHRONOUS_WRITES, -1);
+                  VIR_DOMAIN_BLOCK_COPY_SYNCHRONOUS_WRITES |
+                  VIR_DOMAIN_BLOCK_COPY_TARGET_ZEROED, -1);

     if (virTypedParamsValidate(params, nparams,
                                VIR_DOMAIN_BLOCK_COPY_BANDWIDTH,
-- 
2.53.0