Skip to content

L6 – VM Disk Image Formats: Cross-Platform Cheat Sheet

cpx June 12, 2026 13 min read Virtualization Platforms

Pragmatic reference for creating, converting, mounting, resizing, shrinking, and migrating virtual machine disk images on Windows, Linux, and macOS, anchored to a logical architecture model.


1. Logical architecture

A disk image is a block device serialized into a file, wrapped in container metadata. Every operation in this sheet acts on exactly one layer of the stack below. Knowing which layer you are touching prevents most accidents.

┌─────────────────────────────────────────────────────────────────┐
│ L7  Guest files              /etc/fstab, C:\Windows\...          │
│ L6  Guest filesystem         ext4, XFS, NTFS, ReFS, APFS         │
│ L5  Guest volume management  LVM, Storage Spaces, APFS container │
│ L4  Guest partition table    GPT or MBR                          │
╞═════════════════════════════ guest / host boundary ═════════════╡
│ L3  Virtual block device     virtio-blk/scsi, NVMe, SATA, IDE    │
│ L2  Image container format   raw, qcow2, VMDK, VHD/VHDX, VDI     │
│     (allocation map, CoW clusters, snapshots, backing chain)     │
│ L1  Host volume / filesystem ext4, XFS, NTFS, APFS, ZFS, LVM     │
│ L0  Physical media           NVMe, SATA SSD, HDD, SAN/NAS        │
└─────────────────────────────────────────────────────────────────┘

Five working principles

#PrinciplePractical consequence
1The container (L2) wraps the byte stream the guest sees at L3. Everything from L4 upward belongs to the guest.Format conversion never touches partitions, filesystems, or the installed OS. The guest data stays bit-identical.
2Conversion changes only L2.qemu-img convert rewrites allocation metadata and re-packs allocated clusters. It also restores sparseness by skipping zero clusters.
3Mounting an image on the host means re-implementing L3 in the host kernel.Linux: loop or nbd device. Windows: Attach VHD. macOS: hdiutil attach. The host then parses L4 to L6 like any physical disk.
4Space reclamation must traverse the full stack.Guest trim (L6) → discard on the virtual controller (L3) → cluster unmap in the container (L2) → hole punch on the host FS (L1). Any layer that drops the discard leaves the file bloated.
5Copy-on-write can live at L2 (qcow2, VMDK deltas, AVHDX), at L1 (ZFS, Btrfs, LVM-thin), or both.Pick one layer to own snapshots. Stacked CoW multiplies write amplification and fragmentation.

2. Format reference

FormatExtensionNative ecosystemMax virtual sizeAllocationSnapshot mechanismqemu-img driver nameNotes
Raw.img, .rawUniversal (every hypervisor, dd, loop)Host FS limitSparse via FS holes, or fully preallocatedNone at L2; use LVM/ZFS/FS at L1rawZero metadata overhead, fastest, trivially mountable. Sparseness is fragile in transit.
QCOW2.qcow2QEMU/KVM, Proxmox, UTM, libvirtEffectively unlimited (EB scale)CoW clusters, 64 KiB defaultInternal snapshots and external overlays with backing filesqcow2Compression (zlib, zstd), LUKS encryption, dirty bitmaps for incremental backup. The feature-rich choice.
VMDK.vmdkVMware ESXi, Workstation, Fusion62 TB (ESXi 5.5+)Sparse (growable) or flat; thin, lazy zeroed, eager zeroed on VMFSDelta extents (disk-000001.vmdk)vmdkA descriptor plus one or more extents. Subformat matters: monolithicSparse, monolithicFlat, twoGbMaxExtentSparse/Flat, streamOptimized (the OVA payload).
VHD.vhdLegacy Microsoft, Azure upload2040 GB (~2 TB)Fixed, dynamic, differencingDifferencing disks (parent/child)vpcFooter at end of file. Azure still requires fixed-size VHD for image upload.
VHDX.vhdxHyper-V 2012+, native Windows mount64 TBFixed, dynamic, differencingAVHDX checkpoint chainvhdxInternal log makes it resilient to power loss. Supports 4 KiB logical sectors. WSL2 distro disks are VHDX.
VDI.vdiVirtualBoxMulti-TBDynamic or fixedVirtualBox snapshot machineryvdiSimple and fine inside VirtualBox; convert when leaving the ecosystem.
Parallels HDD.hdd (inside .pvm bundle)Parallels Desktop (macOS)Multi-TBExpanding or plainParallels snapshots in the .pvm bundleparallelsManaged with prl_disk_tool.
DMG family.dmg, .sparseimage, .sparsebundlemacOS disk images (not hypervisor formats, same L2 idea)FS limitUDZO compressed, UDRW read-write, sparse, sparse bundle (banded files)Nonedmg (read-only)Sparse bundles store data in 8 MB bands, which syncs and backs up well.
ASIF.asifApple Virtualization framework, macOS 26 TahoeMulti-TBSparseNonen/aNew Apple sparse format for VMs and containers; created with diskutil image create blank --format ASIF.

Choosing a format

If you runPickWhy
KVM, QEMU, Proxmox, UTMqcow2Snapshots, backing files, compression, thin by default
KVM with maximum I/O performanceraw on LVM-thin or a ZFS zvolNo container overhead; snapshots move to L1
Hyper-VVHDX dynamicPower-loss resilience, 64 TB, double-click mount in Windows
Azure image uploadVHD fixedHard platform requirement
VMware ESXiVMDK thin on VMFSNative; manage with vmkfstools
VMware Workstation or FusionVMDK monolithicSparseDefault, full snapshot support
VirtualBoxVDI (or VMDK for dual use with VMware)Native
Shipping or archiving an applianceOVA (streamOptimized VMDK inside) or compressed qcow2Smallest portable form
Physical disk imaging, forensicsrawUniversal and tool-agnostic

3. The universal tool: qemu-img

One tool reads and writes nearly every format on all three operating systems. Learn it once.

OSInstall
Linuxapt install qemu-utils / dnf install qemu-img
macOSbrew install qemu
Windowswinget install qemu (or the official QEMU for Windows installer); qemu-img.exe lands in the install directory
TaskCommand
Identify any image, virtual vs actual sizeqemu-img info disk.qcow2
Show a full snapshot/backing chainqemu-img info --backing-chain top.qcow2
Create a 100 GB thin qcow2qemu-img create -f qcow2 disk.qcow2 100G
Create fully preallocatedqemu-img create -f qcow2 -o preallocation=full disk.qcow2 100G
Create an overlay on a base imageqemu-img create -f qcow2 -b base.qcow2 -F qcow2 overlay.qcow2
Convert between formats (progress bar)qemu-img convert -p -f vmdk -O qcow2 in.vmdk out.qcow2
Convert with compression (qcow2 target)qemu-img convert -p -c -O qcow2 in.raw out.qcow2
Grow an imageqemu-img resize disk.qcow2 +50G
Shrink an image (dangerous, see section 7)qemu-img resize --shrink disk.qcow2 80G
List / create / apply / delete internal snapshotsqemu-img snapshot -l/-c NAME/-a NAME/-d NAME disk.qcow2
Check and repair qcow2 metadataqemu-img check -r all disk.qcow2
Repoint an overlay to a moved backing fileqemu-img rebase -u -b /new/path/base.qcow2 -F qcow2 overlay.qcow2
Merge an overlay down into its backing fileqemu-img commit overlay.qcow2
Predict required size before convertingqemu-img measure -O qcow2 in.vmdk
Compare two images content-wiseqemu-img compare a.qcow2 b.raw

Preallocation modes for -o preallocation=: off (thin), metadata (qcow2 tables only), falloc (fast reserve), full (write zeros, best latency).


4. Per-OS toolbox

4.1 Windows

VHD and VHDX are first-class citizens: Explorer mounts them on double-click, Disk Management has Attach VHD, and the Hyper-V PowerShell module does the rest. Everything else gets handled by qemu-img.

TaskCommand (elevated PowerShell unless noted)
Create dynamic VHDXNew-VHD -Path D:\vm\d.vhdx -SizeBytes 100GB -Dynamic
Convert VHD to VHDXConvert-VHD -Path a.vhd -DestinationPath a.vhdx -VHDType Dynamic
Convert dynamic to fixed (e.g. for Azure, target VHD)Convert-VHD -Path a.vhdx -DestinationPath a.vhd -VHDType Fixed
GrowResize-VHD -Path d.vhdx -SizeBytes 200GB
Shrink container to minimum possibleResize-VHD -Path d.vhdx -ToMinimumSize (shrink the guest partition first)
Compact a dynamic VHDXOptimize-VHD -Path d.vhdx -Mode Full (detach from the VM first; mounting read-only beforehand improves results)
Mount / unmountMount-VHD -Path d.vhdx [-ReadOnly] / Dismount-VHD -Path d.vhdx
Merge a checkpoint chain (AVHDX into parent)Merge-VHD -Path child.avhdx -DestinationPath parent.vhdx
diskpart equivalents (no Hyper-V module needed)diskpartselect vdisk file="C:\d.vhdx"attach vdisk / compact vdisk / expand vdisk maximum=200000 / detach vdisk
Physical to virtual (P2V)Sysinternals Disk2vhd → produces VHDX from a live machine
Inspect or convert foreign formatsqemu-img info x.qcow2, qemu-img convert -p -O vhdx -o subformat=dynamic x.qcow2 x.vhdx
Quick read-only file extraction from VMDK/VHD/VDIOpen the image in 7-Zip and copy files out

WSL2 disk maintenance (the distro lives in an ext4.vhdx):

wsl --shutdown
# Option A (modern WSL): keep it sparse automatically
wsl --manage <DistroName> --set-sparse true
# Option B: one-off compaction
Optimize-VHD -Path "$env:LOCALAPPDATA\...\ext4.vhdx" -Mode Full
# Option C without Hyper-V module: diskpart -> select vdisk -> compact vdisk

4.2 Linux

TaskCommand
Install the toolboxapt install qemu-utils libguestfs-tools
Mount a qcow2/vmdk/vhdx via NBDmodprobe nbd max_part=16qemu-nbd -c /dev/nbd0 disk.qcow2mount /dev/nbd0p2 /mntumount /mnt && qemu-nbd -d /dev/nbd0
Mount a raw image with partitionslosetup -fP --show disk.img → mount /dev/loopXp1
Mount any format without root, auto-detect OS partitionsguestmount -a disk.qcow2 -i --ro /mnt/vmguestunmount /mnt/vm
List partitions and filesystems inside an imagevirt-filesystems -a disk.img --all --long
Free space inside an image without booting itvirt-df -a disk.qcow2 -h
Copy files out without mountingguestfish --ro -a win.vmdk -i copy-out /Users/lp/Documents /tmp/out
Resize image and grow the partition in one passvirt-resize --expand /dev/sda2 old.img new.img
Re-sparsify in place (after trim or zeroing)virt-sparsify --in-place disk.qcow2
Punch holes in a raw file whose guest zeroed spacefallocate --dig-holes disk.img
Copy while preserving sparsenesscp --sparse=always src.img dst.img or rsync -S
Full cross-hypervisor migration incl. driver fixesvirt-v2v -i vmx guest.vmx -o local -os /var/lib/libvirt/images (also accepts -i ova)
Avoid CoW-on-CoW on Btrfs hostschattr +C /var/lib/libvirt/images before creating images there

Discard path on KVM so trims reach the host: virtio-scsi or modern virtio-blk, discard=unmap on the drive, then fstrim -av inside the guest.

4.3 macOS

TaskCommand
Get qemu-imgbrew install qemu (identical syntax to Linux/Windows)
Create a sparse bundlehdiutil create -size 100g -type SPARSEBUNDLE -fs APFS -volname Data data.sparsebundle
Attach / detach an imagehdiutil attach data.sparsebundle / hdiutil detach /dev/diskN
Attach a raw VM imagehdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount disk.img then diskutil mountDisk /dev/diskN
Reclaim space in a sparse imagehdiutil compact data.sparseimage
Convert between DMG variantshdiutil convert in.dmg -format UDSB -o out.sparsebundle
New Apple sparse VM format (macOS 26)diskutil image create blank --format ASIF --size 100G disk.asif
Parallels: compact an expanding diskprl_disk_tool compact --hdd "~/Parallels/Win11.pvm/harddisk.hdd"
Parallels: resizeprl_disk_tool resize --hdd harddisk.hdd --size 200G
Parallels: plain ↔ expandingprl_disk_tool convert --hdd harddisk.hdd --expanding (or --plain)

Practical notes for macOS:

TopicGuidance
UTMQEMU backend uses qcow2; the Apple Virtualization backend uses raw .img (and ASIF on Tahoe). Both sit inside the .utm bundle.
Mounting qcow2 on the hostNo nbd kernel driver exists. Convert to raw and hdiutil attach, or run guestmount inside a Lima/Docker Linux VM, or attach the disk to a throwaway UTM VM.
Guest trimWorks in UTM/QEMU with virtio and discard enabled, then fstrim (Linux guest) or defrag /L (Windows guest), then re-sparsify or compact on the host.

5. Conversion

Pre-flight checklist

StepWhy
Shut the VM down cleanlyConverting a running or crash-state disk produces a dirty filesystem
Consolidate or delete snapshots firstConverters typically read one layer; orphaned chains lose data or fail
Record firmware type (BIOS vs UEFI) and controller typeMore migrations break on firmware and driver mismatch than on disk bits
Install target-platform drivers in advance (virtio-win, Hyper-V ICs, VMware Tools) or plan to use virt-v2vA Windows guest without the boot-critical storage driver blue-screens with INACCESSIBLE_BOOT_DEVICE
Verify free space ≥ virtual size of the sourceqemu-img measure predicts the target size
Work on a copyConversion is read-only on the source, but mistakes with paths are not

Conversion matrix (qemu-img does almost everything)

TargetCommand
→ qcow2qemu-img convert -p -O qcow2 src.vmdk dst.qcow2
→ qcow2 compressedqemu-img convert -p -c -O qcow2 src.img dst.qcow2
→ rawqemu-img convert -p -O raw src.qcow2 dst.img
→ VHDX (Hyper-V)qemu-img convert -p -O vhdx -o subformat=dynamic src.qcow2 dst.vhdx
→ VHD fixed (Azure)qemu-img convert -p -O vpc -o subformat=fixed,force_size src.qcow2 dst.vhd
→ VMDK for Workstation/Fusionqemu-img convert -p -O vmdk -o subformat=monolithicSparse src.qcow2 dst.vmdk
→ VMDK for OVA packagingqemu-img convert -p -O vmdk -o subformat=streamOptimized src.qcow2 dst.vmdk
→ VDIqemu-img convert -p -O vdi src.vmdk dst.vdi

Ecosystem-native alternatives and special cases

CaseCommand
VirtualBox clone/convertVBoxManage clonemedium disk in.vdi out.vmdk --format VMDK (formats: VDI, VMDK, VHD, RAW)
VHD ↔ VHDX with Microsoft toolingConvert-VHD (section 4.1)
Unpack an OVAtar xf appliance.ova → convert the inner streamOptimized VMDK before running it on non-VMware platforms
Import a VMDK onto ESXi datastore properlyvmkfstools -i uploaded.vmdk thin.vmdk -d thin (uploaded streamOptimized/sparse images are not runnable as-is on VMFS)
VMware Workstation/Fusion defragment+shrinkvmware-vdiskmanager -k disk.vmdk; convert type with vmware-vdiskmanager -r src.vmdk -t 0 dst.vmdk
Full migration with driver injectionvirt-v2v (reads VMware vmx/ova, fixes virtio drivers, outputs libvirt/qcow2)

6. Mounting and inspecting on the host (summary)

HostRaw .imgqcow2VMDKVHD/VHDXRead-only quick look
Linuxlosetup -fPqemu-nbd or guestmountqemu-nbd or guestmountqemu-nbd or guestmountvirt-ls, guestfish
WindowsConvert first, or 7-ZipConvert first, or 7-ZipVMware Workstation map drive, or 7-ZipNative: Explorer double-click, Mount-VHD, diskpart7-Zip opens most containers
macOShdiutil attach (CRawDiskImage)Convert to raw first, or Linux helper VMConvert, or FusionConverthdiutil imageinfo, qemu-img info

Identification: qemu-img info is authoritative for container type; file disk.img gives a fast hint.


7. Resizing and shrinking

Growing is safe and bottom-up. Shrinking is risky and top-down. Order is everything.

Grow (safe)

StepLayerTool examples
1. Grow the containerL2qemu-img resize +50G, Resize-VHD, VBoxManage modifymedium --resize <MB>, prl_disk_tool resize
2. Grow the partitionL4growpart /dev/vda 2, GParted, Windows Disk Management, diskutil
3. Grow the filesystemL6resize2fs, xfs_growfs, NTFS extends with the partition, diskutil apfs resizeContainer

Shrink (reverse order, always on a backup copy)

StepLayerNotes
1. Shrink the guest filesystemL6resize2fs /dev/vda2 80G (XFS cannot shrink), Windows Disk Management shrink volume
2. Shrink the partition to matchL4GParted or diskpart; leave a safety margin
3. Shrink the containerL2qemu-img resize --shrink disk.qcow2 81G; Resize-VHD -ToMinimumSize

Cutting L2 below the end of valid L4 data destroys the guest. The --shrink flag exists precisely because this is irreversible.

Compact / reclaim (thin images that grew fat)

Universal principle: make free space zero or trimmed inside the guest, then compact at L2.

FormatZero/trim step (in guest)Compact step (on host)
qcow2fstrim -av (with discard=unmap) or zero-fillvirt-sparsify --in-place disk.qcow2, or qemu-img convert to a fresh file
VHDXdefrag C: /L or sdelete -z C:Optimize-VHD -Mode Full or diskpart compact vdisk
VDIzerofree (Linux) / sdelete -z (Windows)VBoxManage modifymedium disk.vdi --compact
VMDK (Workstation/Fusion)VMware Tools shrink or sdelete -zvmware-vdiskmanager -k disk.vmdk
VMDK (ESXi)fstrim / sdelete -zvmkfstools --punchzero disk.vmdk or Storage vMotion
Parallels HDDBuilt-in Reclaim, or trim in guestprl_disk_tool compact
rawfstrim with discard, or zero-fillfallocate --dig-holes disk.img

8. Snapshots, backing files, and chains

OperationCommand
Internal qcow2 snapshot (create/list/revert/delete)qemu-img snapshot -c clean / -l / -a clean / -d clean disk.qcow2
External overlay (base stays read-only)qemu-img create -f qcow2 -b base.qcow2 -F qcow2 top.qcow2
Inspect the whole chainqemu-img info --backing-chain top.qcow2
Merge overlay down into baseqemu-img commit top.qcow2
Repoint after moving the baseqemu-img rebase -u -b /new/base.qcow2 -F qcow2 top.qcow2
Hyper-V: collapse checkpointsDelete the checkpoint in Hyper-V Manager (auto-merges AVHDX), or Merge-VHD
VMware: consolidate deltasSnapshot Manager → Delete All, or vmkfstools clone of the current state

Chain hygiene

RuleReason
Keep production chains shallow (≤ 3 links)Every read may traverse the whole chain
Never rename or move a backing file without rebase -uOverlays store the backing path; the chain silently breaks
Never plain-copy the disk of a running VMThe result is crash-consistent at best; snapshot first or use backup APIs/bitmaps
Backing chains are also a featureOne golden base + N overlays = instant linked clones for labs

9. Gotchas and performance notes

GotchaMitigation
Sparse files balloon to full size over scp/SMB/USB copiesrsync -S, cp --sparse=always, tar with -S, or convert/compress for transport
qcow2 on Btrfs or ZFS doubles CoWchattr +C on the images directory (Btrfs), or use raw on a zvol and let ZFS own snapshots
Trim never reaches the host fileEnable discard on the virtual controller (virtio-scsi discard=unmap), then trim in the guest, then sparsify/compact
streamOptimized VMDK refuses to bootIt is a transport subformat; convert to monolithicSparse or import with vmkfstools -i
Windows guest BSOD INACCESSIBLE_BOOT_DEVICE after moving hypervisorsInject the target storage driver beforehand (virtio-win, Hyper-V ICs) or migrate with virt-v2v
BIOS/UEFI mismatch after migrationRecreate the VM with the same firmware as the source; converting MBR↔GPT is a separate guest-side task
BitLocker/TPM-bound guestsSuspend BitLocker before migration; vTPM state does not travel with the disk file
VHD 2 TB ceiling hit mid-growthConvert to VHDX first, then grow
Azure upload rejectedMust be VHD, fixed, size aligned to 1 MiB; use the vpc + force_size recipe above
Deep snapshot chains crawlCommit/consolidate regularly; monitor with qemu-img info --backing-chain
Old XP-era images misaligned (63-sector offset)Realign once (virt-resize rebuilds layout) or accept the read-modify-write penalty
Network or USB-attached host storage for live imagesLatency and locking issues; keep active images on local storage, archives anywhere

10. One-glance command crib

IntentLinux/macOSWindows
What is this file?qemu-img info xqemu-img info x
Convertqemu-img convert -p -O <fmt> in outsame, or Convert-VHD for VHD↔VHDX
Mountguestmount -a x -i /mnt (Linux), hdiutil attach (macOS raw)Double-click VHDX / Mount-VHD
Growqemu-img resize x +20GResize-VHD -SizeBytes
Reclaim spacetrim in guest → virt-sparsifysdelete -zOptimize-VHD
Snapshotqemu-img snapshot -c name xHyper-V checkpoint
P2Vdd to raw, then convert; or virt-p2vDisk2vhd

0 0 votes
Article Rating
guest

0 Comments
Oldest
Newest Most Voted
0
Would love your thoughts, please comment.x
()
x