Commit 0c5dc32f63 for qemu.org

commit 0c5dc32f63d026e8333fc5c5438a95f74427501a
Author: Sanne Raymaekers <sraymaek@redhat.com>
Date:   Fri Oct 16 14:37:48 2026 +0200

    block/vmdk: Don't preallocate full 64k for compressed data grains

    For stream optimized disks the spec notes: "Each marker and its
    associated block begin on a sector or 512‐byte boundary... There are
    five types of markers: compressed grain markers,..." [^1]

    This means that instead of pre-zeroing grains with their typical size
    (64K), in stream optimized disks, only the real size of the compressed
    grains should be written. Writing zeroes is not necessary and wasted
    work, though usually the zeros are immediately overwritten with the next
    compressed clusters and nothing is lost; near the end of the image, it
    could mean that the image became larger than expected.

    [^1] Virtual Disk Format 5.0 Technical Note.

    Signed-off-by: Sanne Raymaekers <sraymaek@redhat.com>
    Message-ID: <20261016123750.94769-2-sraymaek@redhat.com>
    Reviewed-by: Kevin Wolf <kwolf@redhat.com>
    Signed-off-by: Kevin Wolf <kwolf@redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index cd8b4ec7c8..7ca030c5fe 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1730,16 +1730,25 @@ get_cluster_offset(BlockDriverState *bs, VmdkExtent *extent,
         cluster_sector = extent->next_cluster_sector;
         extent->next_cluster_sector += extent->cluster_sectors;

-        /* First of all we write grain itself, to avoid race condition
-         * that may to corrupt the image.
-         * This problem may occur because of insufficient space on host disk
-         * or inappropriate VM shutdown.
+        /*
+         * Stream optimized (compressed) extents do not have to be
+         * pre-allocated, as compressed writes always cover the whole
+         * cluster, and will align on 512 byte chunks.
          */
-        ret = get_whole_cluster(bs, extent, cluster_sector * BDRV_SECTOR_SIZE,
-                                offset, skip_start_bytes, skip_end_bytes,
-                                zeroed);
-        if (ret) {
-            return ret;
+        if (!extent->compressed) {
+            /*
+             * First of all we write grain itself, to avoid race condition
+             * that may to corrupt the image.
+             * This problem may occur because of insufficient space on host disk
+             * or inappropriate VM shutdown.
+             */
+            ret = get_whole_cluster(bs, extent,
+                                    cluster_sector * BDRV_SECTOR_SIZE,
+                                    offset, skip_start_bytes, skip_end_bytes,
+                                    zeroed);
+            if (ret) {
+                return ret;
+            }
         }
         if (m_data) {
             m_data->new_allocation = true;