36

My dynamically growing virtual disks (VDI) from various Ubuntu installations in Virtual Box are actually steadily "growing" indeed.

Deleting of files in the virtual machine does not free the space my VDI file took from the host hard disk space.

How do I shrink these files to give the unused hard disk space back to the host?

Takkat
  • 142,284

2 Answers2

35

A dynamically growing Virtual Box virtual hard drive file is capable of growing on demand of the virtual machine up to the maximum size we defined in setting up this file. It does not however free the space of files we deleted in the guest OS.

In case the disk had grown too much we can compact it again, provided the unused space is filled with zeros, and the drive is in VDI format.

For an ext2 to ext 4 filesystem this can be done from the Ubuntu guest with the command line utility zerofree Install zerofree * .

zerofree /dev/sdxX

This needs the drive to not be in use, and to be unmounted. We therefore may have to bind it temporarily to another VM we had created for this purpose, or we need to boot an Ubuntu live environment on this VM.

Replace /dev/sdxX with the ext2, ext3 or ext4 formatted partition in question.

On more than one partition we my have to repeat zerofree for each partition. Keep in mind that by filling with zeros the virtual file will temporarily grow up to it's maximum size.

Once all unused drive space is filled with zeros we then shrink the drive with

VBoxManage modifyhd <name>.vdi --compact

This will considerably decrease the file size of our VDI file.

* In a Windows guest we can replace unused space with the utility sdelete.

Takkat
  • 142,284
  • Will this also work for an encrypted filesystem within the guest? – smichak Jan 06 '15 at 06:20
  • Sure. If you're using ecryptfs, the encrypted files look like normal files to disk utilities, and this will work. If you're using full-disk encryption, it won't be recognized as an ext-formatted partition anyway :) – chronospoon Jan 09 '15 at 18:34
  • I'm using ext4 partition on a dm-crypt block device... I tried the method and I don't see the .vdi file as smaller after compaction. I think that the zero blocks are saved as non-zero blocks on the block device under the dm-crypt. – smichak Jan 13 '15 at 13:33
  • 2
    @smichak: that's the point of encryption. It will encrypt all of your drive to also make sure we can not see file boundaries. – Takkat Jan 13 '15 at 13:42
  • Right. But I was wondering if there's a chance to make compaction work in spite of the encryption. For instance, if the top level file system could notify the underlying block device of unused blocks and write them as zero blocks past the dm-crypt layer then it would be the same, right? So I need a way to somehow make dm-crypt honor such 'discards' and pass them to the low level block device. – smichak Jan 13 '15 at 13:51
  • It may be easier and less time comsuming to just clone the VDI - but I have no experience with encryption, really. – Takkat Jan 13 '15 at 14:00
  • You can also get access to the VDI as an unmounted block device from a Linux host - http://askubuntu.com/questions/326060/how-to-mount-a-vdi-file-in-ubuntu-13-10 – sylvain.joyeux Jun 17 '15 at 13:49
  • 3
    If you don't want to attach your VDI to another machine, you can boot into recovery mode, and mount the disk readonly mount -n -o remount,ro -t ext4 /dev/sda1 and then zerofree -v /dev/sda1. – Hamid Nazari Jul 07 '15 at 02:38
  • Nice one, Hamid. That worked perfectly. – Kaitain Mar 11 '17 at 18:25
1

Here are some alternative ways to zero the free disk space (which can be the most time-consuming part). Afterwards, you will still have to run VBoxManage modifyhd <disk> --compact to compact the actual disk file.


This command can zero the disk while it is unmounted:
apt-get install zerofree
zerofree -v /dev/sdxN


Here's an example of how to get dd to periodically print output:
dd if=/dev/zero of=temp-file-on-disk bs=20M

# run this to get the process ID of the dd command
pgrep -l '^dd$'
# then put the process ID on the command line to "kill -USR1"
# this will tell dd to print the current status (in another terminal)
kill -USR1 $(pgrep -l '^dd$' | awk '{print $1}')


Here's a dd-like program that will automatically print output periodically:
apt-get install dcfldd
dcfldd if=/dev/zero of=temp-file-on-disk bs=20M
chronospoon
  • 582
  • 1
  • 3
  • 9
  • 1
    I've seen zerofree used on a mounted filesystem, but when it was mounted readonly. Even for root FS: sudo mount -o remount,ro / - but in a GUI session the root will be busy, so it will fail. But it is possible in runlevel 1 (telinit 1), so you won't need to boot from a live CD to do it. – Tomasz Gandor May 07 '16 at 23:25