Compacting a Linux VHD

When you compact a Linux dynamic virtual disk in Windows Virtual PC you’ll find that almost no space is saved. This is because the compact routine only compacts disk area that is filled with zeros. For Windows guest OS’s Microsoft provides a Precompactor tool that zeroes out the unused space so that compaction works.

I thought I’d found a solution in  Ben Armstrong’s MSDN Blog, Compacting the virtual hard disk of a Linux virtual machine. You run the following command, turn off the VM and then run the Compact virtual hard disk function.

cat /dev/zero > zero.dat ; sync ; sleep 1 ; sync ; rm zero.dat

It didn’t work for me then I thought, probably needs a sudo before the commands but that didn’t seem to work either. Searching around the net I found many sites suggesting the same or similar commands and others suggesting dd to do the job. After reading a lot of information I came to the conclusion that these methods are more of a hack than an elegant solution and there are quite a few technical reasons why they are sub-optimal.

That’s when I learned about the zerofree program for Linux from Ron Yorston. Read about this nice utility at his Keeping filesystem images sparse page.

Searching for use case examples for zerofree yielded many different recommendations most of which involved what seemed like unnecessary complications. These include installing zerofree on the system you want to run it, restarting in single user mode and remounting the file system read-only to run it.

Then I saw some sites saying to run zerofree from a Linux live CD and that struck me as the smartest and fastest way to do this process. The SystemRescueCd, a great live CD that I’ve used before, includes zerofree and nearly every other Linux disk utility there is.

Here is the process I came up with that is fast and really shrinks your Linux virtual hard disk.

  1. Shut down the virtual machine and if you have the undo disk feature enabled apply or discard the changes and then disable the feature.
  2. Backup the VHD file because low level manipulation of the disk file system could break it.
  3. Boot the virtual machine from the SystemRescueCd ISO.
  4. Check the file system before zeroing it out.
    fsck /dev/sda1
  5. Zero out the file system, it took 13 minutes to complete on my VHD.
    zerofree -v /dev/sda1
  6. Check the file system after zeroing it out.
    fsck /dev/sda1
  7. Shut down the VM.
    poweroff
  8. Compact the VHD, Settings -> Hard Disk 1 -> Modify button -> Compact virtual hard disk button and remove the ISO from the DVD Drive setting.

That’s all there is to it, I think this is by far the fastest and easiest way of getting this done.