9

I am hosting several virtual machines on a host running Hyper-V Server 2008 R2. The disks were originally provisioned on a different server (2008, not R2) about 16 months ago, and were migrated onto this server one year ago. Most guests are running Windows 7.

Recently I was comparing the VHD size to used space reported by the guest, and noticed that several machines had VHD files that were 50-100% larger than actually needed. So I decided to try compacting the VHD files to free up space on the host. I followed instructions I found on the internet, roughly as follows:

  1. Run CHKDSK in the guest machine
  2. Run a defrag in the guest machine (Windows built-in defrag)
  3. Shut down the guest
  4. Open "Edit Disk..." tool in Hyper-V Manager
  5. Select the VHD of interest and choose to compact it

The first time I tried this, it worked flawlessly and reduced the size of my VHD by about 50%. But for the disks of every other guest, I get this error message:

The server encountered an error trying to edit the virtual disk.

'The system failed to compact 'C:\example.vhd'. Error Code: The requested
operation could not be completed due to a file system limitation

No guests have NTFS compression enabled. There are no snapshots of these disks. What else could be causing this error?

Edit: Bonus points for anybody who describes a solution to keep dynamic VHD sizes in check automatically.

Nic
  • 13,425
  • 17
  • 61
  • 104

5 Answers5

8

In the interest of Internet search consolidation: Eventually found this link thas an approach that has worked when HyperV compact did not: https://fiddley.wordpress.com/2014/01/27/dynamically-expanding-vhd-not-compacting-in-hyper-v/

In Administrative command prompt, run DISKPART

At the DISKPART command prompt

select vdisk File=”I:\path\to\your.vhd”
attach vdisk readonly
compact vdisk
detach vdisk
Stan
  • 191
  • 1
  • 3
  • 1
    This series of commands worked for me, maybe because the guests are all linux. It's important to at least "Save" your VM before you try these, otherwise it will fail. And don't forgot to detach before you try starting your machine again :) – gcode Dec 30 '20 at 04:10
7

Remove the shadow copies from the guest. That will do it!

vssadmin delete shadows /all
Oliver Salzburg
  • 4,635
  • 17
  • 55
  • 82
tony roth
  • 3,884
  • 18
  • 14
1

Apart from the suggestion of deleting the shadow copies you should use SDelete for zeroing the empty space before compaction, since sometimes it allows compacting much more unused space. For example, for zeroing the empty space in C: you should run this from inside the virtual machine:

sdelete -z c:

In my case I had a virtual disk file with a total size of 80 GB, the first compaction reduced it only to 78 GB, deleting the shadows copies and compacting again reduced it to 72 GB, but after running sdelete the next compaction reduced the file size to 56 GB.

0

I just discovered another method that seems to reclaim all the unused space in the virtual hard disk, the methods in the other responses (included my previous response) sometimes doesn't liberate all the space.

This method, which I learned in this very fine article about compacting Hyper-V hard disks, uses the Powershell's Optimize-VHD cmdlet by Microsoft. You need to open a Powershell prompt with administrative privileges and then run the following commands:

Mount-VHD 'C:\Path to\Your disk file.vhdx' -ReadOnly
Optimize-VHD 'C:\Path to\Your disk file.vhdx' -Mode Full
Dismount-VHD 'C:\Path to\Your disk file.vhdx'

This also has the advantage of not needing to defrag the disk or zero the empty space before the compaction, because in full mode the cmdlet will search for all unused blocks (of course, you should clear caches, temporary files and shadow copies before compacting the disk to liberate more space).

0

All the above didn't work for me because I needed to defragment WSL vdisk first. I found a way, feel free to check it out: https://github.com/bendover94/reclaim_wsl_mem