38

Is there any way to shrink qcow2 image without converting it raw?

I cannot convert it to raw because I don't have disk space enough for raw image.

YOU
  • 541
  • 1
  • 6
  • 9

5 Answers5

43

Noop conversion (qcow2-to-qcow2) removes sparse space:

qemu-img convert -O qcow2 source.qcow2 shrunk.qcow2

You can also try add compression (-c) to the output image:

qemu-img convert -c -O qcow2 source.qcow2 shrunk.qcow2

Before running above command be sure to shutdown the VM. After you are satisfied with the result, you can rename shrunk.qcow2 to original name your VM config wants.

uvsmtid
  • 897
  • 1
  • 6
  • 13
SZ Quadri
  • 431
  • 3
  • 2
  • 4
    the -c flag in qemu-img convert -c -O is for compression, not shrink... and it can decrease the disk speed... – Anton Anikin Jul 04 '14 at 14:41
  • 1
    This creates a second file, though, so you need twice as much free space as the image? Is there a way to shrink it in-place? – endolith Feb 13 '19 at 16:37
  • 1
    I doubt this is going to shrink much if you do not zero-out the free disk space first. zero-out the free disk space takes very long time and host disk space. – Wang Aug 17 '20 at 13:30
  • @Wang if you enable TRIM support first then it should be able to compress better. https://pve.proxmox.com/wiki/Shrink_Qcow2_Disk_Files – Wes Dec 15 '20 at 16:14
  • 3
    Important to note: this procedure doesn't preserve internal qcow2 snapshots, if you have any. I learned it the hard way, after deleting the original file. – ku1ik Jan 14 '23 at 20:45
  • As @Wang noted, this will not reduce the .qcow2 image unless the free disk space has first been freed up or zeroed with a separate utility, e.g., `fstrim` or `virt-sparsify`. – oemb1905 Jun 12 '23 at 03:40
21

Try virt-sparsify - it will zerofill the unused blocks in the image and then deduplicate the zeroes.

Cristian Ciupitu
  • 6,396
  • 2
  • 42
  • 56
dyasny
  • 18,802
  • 6
  • 49
  • 64
  • Thanks for you answer, but [virt-sparsify](http://libguestfs.org/virt-sparsify.1.html) said it cannot resize disk images and I found [virt-resize](http://libguestfs.org/virt-resize.1.html) from that, but looks like I still need to allocate spaces to expand (that I don't have enough spaces on my harddisk). Anyway, Thank you very much for you info. – YOU Sep 27 '12 at 08:17
  • 3
    @YOU Current versions of virt-sparsify can work in-place without allocating space for a complete copy of the disk image. – Michael Hampton Feb 20 '18 at 05:07
  • 1
    From man: Since virt-sparsify ≥ 1.26, you can now sparsify a disk image in place by doing: virt-sparsify --in-place disk.img – Oleg Neumyvakin Feb 14 '22 at 15:18
  • This will not free up space on the host OS. It will only free up space within the guest OS that can potentially be claimed by the host OS with another tool. – oemb1905 Jun 12 '23 at 03:38
8

I use virt-sparsify:

virt-sparsify /path/to/source.qcow2 --compress /path/to/output.qcow2
Mohamed Elbahja
  • 181
  • 1
  • 1
  • This method is applying qcow2 compression to the output file after freeing up unused blocks within the image. The freed blocks, however, will continue to consume space on the host OS. – oemb1905 Jun 12 '23 at 03:37
5

I have been successfully using this procedure many times now. In short, first in the virtual guest fill all free space on all partitions with zeroes:

dd if=/dev/zero of=zerofile bs=1M

When done, empty the disk cache with sync, remove the zerofile(s) and shut down the guest. On the host side convert the image (raw to qcow2 in this example):

qemu-img convert -f raw -O qcow2 guest.img guest-copy.qcow2

This will automatically sparsify the image. Also remember to update the vm definition file if the image file suffix is changed.

A benefit of this method over virt-sparsify is that in this method the guest can be up while the zeros are written, and hence the downtime is shorter. If you can afford a longer downtime, then use virt-sparsify, as it takes care of the whole process with just one command, and also gives useful feedback during the process.

Jussi Hirvi
  • 161
  • 1
  • 4
  • What exactly do you mean by "remove the zerofile(s)" ? – Rino Bino Sep 20 '22 at 23:29
  • The zerofile is produced by the `dd` command at the beginning of the recipe. The filename in this case is `zerofile`, so you must do `rm zerofile`. – Jussi Hirvi Sep 22 '22 at 05:12
  • This will also work and uses stock `dd` to free up the unused blocks instead of `fstrim` and/or `virt-sparsify` which perform equivalent tasks to how `dd` is being used here. Nice old school method! – oemb1905 Jun 12 '23 at 03:35
3

First, shrink the partition & filesystem from inside the VM. Windows guests can do this from Disk Management. Linux can do this with resize2fs and fdisk. If you are not comfortable with this process use a bootable ISO like gparted instead.

When you are done there should be unused space AT THE END of the disk. For example, in Windows this is what is looks like to have 11MB of free space at the end of the disk (in a real example you should have more than 11MB): Disk Management showing 11mb of unallocated space at the end of the disk

Now that we have moved all your data to the front of the disk we are going to chop off the end. You should be 100% sure you are not about to chop off real data. Some tools count GB/GiB differently so you should probably give yourself some padding (ex shrink partition by 60GB then chop off 50GB). You can always re-grow the partition after the chop.

This command will resize myhd.qcow2 to 200GB, chopping off any data that comes after the first 200GB:

qemu-img resize --shrink myhd.qcow2 200G
9072997
  • 171
  • 1
  • 11
  • https://qemu.readthedocs.io/en/latest/tools/qemu-img.html#cmdoption-qemu-img-commands-arg-resize – Thorsten Schöning Apr 01 '23 at 08:59
  • This is not freeing up space within a dynamic disk image, but is instead reducing the size of the image itself. Some folks may not want to alter the virtual hard disk, only free up unused space consumed by it on the host OS. Just making sure passerby are aware of the difference. – oemb1905 Jun 12 '23 at 03:45