Save to My DOJO
Table of contents
- The VHDX “Shrink” Operation Means Something Different than “Compact”
- Practical Use for VHDX Shrink
- You Cannot Shrink a VHDX that Contains a Dynamic Logical Disk
- You Cannot Shrink a VHD
- How to Determine a VHDX’s Eligibility for Shrinking
- How to Prepare a Guest’s File System for Shrinking
- How to Shrink a VHDX
- Troubleshooting Unexpected Shrink Results
- Do Not Overuse Shrink
I have a standing recommendation for virtual machine resource allocation: start small. You can add or grow almost all virtual resources with very little, and sometimes no impact. On the other hand, you have more work to do if you need to take resources away. The most difficult resource to remove from a Hyper-V virtual machine is drive space. If need to remove an entire disk, you can do that easily. Making a virtual hard disk smaller requires a significant level of effort.
The VHDX “Shrink” Operation Means Something Different than “Compact”
Lots of people confuse “shrink” with “compact” for virtual hard disks. The “compact” operation squeezes the empty bits out of a dynamically expanding hard disk to reduce the amount of space that it consumes on physical disk. Compacting does not alter the maximum size of the disk, nor does it report anything different to the guest operating system. Furthermore, “compact” does not work on fixed VHDX at all. The “shrink” operation, the topic of this article, reduces the physical consumption of a VHDX and reduces the disk size reported to the guest OS.
The above image shows a theoretical comparison to illustrate the differences. Shrinking a fixed VHDX always reduces its size on disk. Reducing a dynamically-expanding VHDX might, if it had expanded beyond the new shrink size.
What to remember: A compact operation reclaims the space from empty blocks. A shrink operation reclaims the space from unallocated blocks. We will make the distinction more obvious when we look at the shrink operation. If you want to know how to compact a dynamically-expanding VHDX, we have a different article for you.
Practical Use for VHDX Shrink
Let’s look at it from the perspective of a virtual machine:
The above image represents a plausible scenario. Let’s say you’ve got a brand new systems administrator that created a new virtual machine using Hyper-V Manager’s wizard and just accepted all the defaults. If you’ve ever done that, then you know that this VM was born with a 127 GB virtual hard disk. That’s probably an excessive amount unless you also intend to install applications on its boot partition. You could just leave it alone. If that admin used defaults, then this disk is dynamically expanding. If it only has an operating system, it will probably never grow past 30 or 40 GB.
But, you have two potential issues: just because it probably won’t expand much doesn’t preclude the possibility that it might. If you set it to a more reasonable maximum, you’d worry less. Second, new administrators might believe everything that they read on the Internet, so they might convert the disk to fixed mode based on the plentiful FUD on the matter. That will leave you with 90GB or so of completely wasted space.
You will encounter other scenarios. What to remember: The shrink operation works best for a VHDX that was over-allocated at creation time.
You Cannot Shrink a VHDX that Contains a Dynamic Logical Disk
If the logical disk inside the VHDX that you’re working with is Dynamic, then you can’t shrink it. Do not confuse the Dynamic logical disk with dynamically expanding VHDX, as they are dramatically different things. The quick way to tell the difference is in the guest’s Disk Management display:
The tell-tale signs are the word “Dynamic” in the Type column and in the disk descriptor field at the far left as well as the sickly yellow-green coloration of the volumes’ bars. The disk also won’t appear when you run PowerShell’s “Get-Disk”. Apparently, that was intentional. Diskpart will still work, though:
diskpart select disk 0 list partition
Your output will display Dynamic Data for Type:
The moral of the story: don’t use Dynamic logical disks. Hyper-V isn’t the only thing that doesn’t know what to do with them. Unfortunately, some products out there require Dynamic disks. Even at Microsoft, at least one team hasn’t yet gotten the memo to stop using Dynamic disks. So, the secondary moral: if you must use Dynamic logical disks, provision small because you can always grow them. If that sounds familiar, that’s because I gave you the same moral at the start of the article.
You Cannot Shrink a VHD
No official tool exists to shrink a VHD. I have seen a tool that would, but all of the links that I can find have gone stale. It never had official support.
How to Determine a VHDX’s Eligibility for Shrinking
You can find out very easily if you can shrink a virtual disk and, if so, just how much you can shrink it. Use Get-VHD on the target virtual disk file. Look for the Size and MinimumSize fields.
If the MinimumSize field is empty, as in the following screenshot, then the contained logical disk is likely Dynamic (again, not to be confused with dynamically expanding). Another possibility is that the file system is corrupt. This field also starts out as empty until an operating system has initialized the contained disk.
A more normal output looks like the following:
Notice that the VhdType here is Dynamic, for dynamically expanding. That won’t stop you from shrinking it. However, this disk is not eligible to be shrunk either, because its MinimumSize and Size are identical. This disk is almost entirely empty; just look at FileSize. Even that probably has a lot of empty blocks. The issue here is the difference between used and allocated. Inside the virtual machine, or, more accurately, inside the contained disk’s allocation table, all the space has been claimed (allocated) even though most of it is empty. To make this disk eligible for shrinking, the MinimumSize must be smaller than the Size.
How to Prepare a Guest’s File System for Shrinking
Before you can shrink the VHDX itself, you must de-allocate space on the guest’s logical disk. These instructions work for Windows only. You can shrink Linux file systems as well, but the tools and techniques vary based on the file system and distribution. Locate instructions that pertain to your setup (readers have supplied some in the comments below!), follow them, and then jump to the next sections here to shrink the VHDX itself.
In order to shrink the VHDX, you must delete the partition or volume at the very end of a logical disk, or you must shrink it. Deleting a partition or volume is easy; these instructions will only show how to shrink them. Remember: Only the space at the END of a disk can be reclaimed by a shrink operation. Deleting or shrinking a partition or volume from the beginning or the middle will not give the shrink operation any space to work with.
As a general rule, you should always take a fresh backup before performing any operation on a disk.
How to Shrink a Volume with Disk Management
- In Disk Management inside the guest, right-click on the volume or partition at the end of the disk and click Shrink Volume.
- The system will determine how much the the volume can shrink. How long this takes depends on disk activity and your hardware.
- Pay attention! What you see now must surely rank highly on any list of the most confusing dialog boxes in history. The first field is the only one that’s straightforward: the current size of the volume. The second field isn’t too bad, but to be clear, it is telling you how much space can be taken away. It is not telling you the minimum size. The next two fields catch many people by surprise. The field that you can type in is not what you want the final size of the disk to be. It represents the amount of space that you want to remove. The bottom field auto-calculates as you change the number, showing you the projected final size of the disk. Some people that read the dialog figure it out from the wording, but they’re in the minority. Most people skip the reading part and just type in the desired final size and wind up with a disk of unexpected size. So, break out your calculator and subtract the amount that you want from the top number. Enter the result in the text field. In my case, I want the final volume to be 60GB in size, so:
- After clicking Shrink and a brief delay, you should see something like this:
The VHD will now have available space for shrinking, which you can verify with Get-VHD.
How to Shrink a Volume with PowerShell
The PowerShell procedure to shrink a volume is far quicker and easier than Disk Management.
- Find out how far you can shrink the volume with Get-PartitionSupportedSize. You can use Get-Help to discover all the ways that you can use this cmdlet, but Get-PartitionSupportedSize -DriveLetter is probably the easiest.
- Now just finish up with Resize-Partition and the Size parameter. In order to specify which partition you want, DriveLetter works again, but you can use all the same selectors that you had with Get-PartitionSupportedSize. Of course, you can use Get-Help to see them. You don’t have to do any math; let PowerShell do the heavy lifting with suffixes:
Verify your changes with Get-PartitionSupportedSize or Disk Management.
[thrive_leads id=’17165′]
How to Shrink a Volume with DISKPART
DISKPART is the hardest way of the three shown methods, so only use it on systems that don’t have Disk Management or PowerShell.
- At an elevated command prompt, type DISKPART and press [Enter] to start the interactive shell (you cannot do this in a remote PowerShell session).
- At the DISKPART prompt, type list disk and press [Enter].
- In the Disk ### column, find the number of the disk you want to use. Select that disk number as follows: select disk 0.
- Now run list volume.
- You can identify the volume by letter, label, or size. Select it as you selected the disk, ex: select volume 2 (not shown).
- To determine how much you can shrink the volume, enter shrink querymax.
- Actually shrinking the volume is much like it is in Disk Management. You have to do math to figure out how much you want to shrink it and use that with “shrink desired” and the number, in megabytes, that you want to remove. For mine, it’s shrink desired=68256. If you didn’t query it first and don’t know how much you’re allowed to remove, you’ll want to specify “minimum” as well or it might not give you all the space that you need. DISKPART will throw an error if it can’t satisfy the minimum. If minimum is not specified and it can’t shrink to the desired amount, it will get as close as it can.
- Type exit to leave DISKPART.
You can now shrink the VHDX.
How to Shrink a VHDX
The good news: you did all the hard work. PowerShell is the only tool that you can use for this last part. Open an elevated PowerShell prompt on a Hyper-V host that has access to the VHDX file. A remote PowerShell session to a suitable host will also work. If the target volume is on an SMB share, be aware that a remote session to the host will be subjected to the double-hop issue. If you haven’t/don’t want to configure constrained delegation, run directly on the system that holds the target file.
- The VM must be in the Off state before you can proceed. Online resize is supported only for growth operations.
- Use Get-VHD as described above to verify that the MinimumSize is present and is smaller than the Size.
- Use Resize-VHD to finish up. Your best option is to use the -ToMinimumSize parameter, although you have other options, viewable in Get-Help .
Verify the results in the VM’s Disk Management tool or Get-Volume.
Troubleshooting Unexpected Shrink Results
I have never seen a catastrophic outcome from a shrink. However, shrink does not always work as expected. The cases that I’ve seen involve an insufficient level of shrinkage. This has two potential causes. The first cause: the disk has no unallocated space at the end. I will not rehash the parts about the reported minimum size; if you missed that part, scroll up and read it. The second cause: you cannot de-allocate as much space as you need. Use a defragmentation tool to address that.
Yes, I have a near fanatical opposition to defragmentation. No, this does not represent a change of my stance. Defragmentation has a handful of valid uses, including cleaning up volumes from shrinking. Try a standard Windows defrag pass first. Other tools might do a better job. You only want to move files from the end of the disk toward the front. You might need to delete some unneeded files to make room first. You have one goal here: clear as much space as possible from the end of the volume. A volume can only shrink to the last non-empty block, even if earlier blocks have no data.
If that doesn’t help, you might need to use a data-moving tool. Create a new VHDX of the desired size and use something like robocopy to transfer the contents of the old disk to the new. I would not use this for operating system volumes, but it works well for data-only volumes. In fact, you could take these steps:
- Turn off the owning VM
- Disconnect the VHDX
- Mount the old VHDX and the new in the management operating system
- Use robocopy or a similar tool to transfer the files
- Dismount both VHDXs from the management operating system
- Attach the new VHDX to the VM in place of the old
Robocopy has switches to copy ACLs and file descriptors. You will need to double-check that the operating system reconnects any shared folders, though.
Do Not Overuse Shrink
Do not treat shrink like a regular maintenance tool. It works best on disks that were dramatically over-allocated at the start.
Not a DOJO Member yet?
Join thousands of other IT pros and receive a weekly roundup email with the latest content & updates!
257 thoughts on "How to Shrink a Hyper-V Virtual Disk (VHDX)"
Just the guide we needed. Very clear.!
Another great guide, thanks. If my VM has replication enabled can I shrink the disk and expect the replica to follow suit? Or do I have to break the replica, shrink the disk and then set up a new replica from scratch? I suspect I have to break the replica but maybe you will surprise me.
I actually don’t know the answer to that. I’ll have to test it. Breaking the replica is the safe way.
Great article. Too bad the PowerShell cmdlets don’t exist on Windows Server 2008, we have pretty old VMs around !
great post. thanks.
we have been using altaro since v4.
i found this post because some IT kid setup the disk inside a vm as dynamic, and was trying to shrink it. I already shrink inside the vm, but was you said on the post, hyper-v wont allow it.
now: what if I clone some of the partitions to another vidisk? and then change the vdisk?
will I be able to clone some partitions having the destination vdisk with non-dynamic disk (basic disk)?
thanks
I don’t know of any clean way to get a Dynamic disk back to a Basic disk. Cloning it will still bring the Dynamic volume state. XCOPY/Robocopy into an empty Basic disk is the only thing that I know to do.
great post. thanks.
we have been using altaro since v4.
i found this post because some IT kid setup the disk inside a vm as dynamic, and was trying to shrink it. I already shrink inside the vm, but was you said on the post, hyper-v wont allow it.
now: what if I clone some of the partitions to another vidisk? and then change the vdisk?
will I be able to clone some partitions having the destination vdisk with non-dynamic disk (basic disk)?
thanks
I’m having an issue shrinking VHDX files that have multiple partitions. The C Drive partition will shrink fine, but if I have a D and E partition, and I have 40GB and 80GB unallocated spaces on each partition respectively, those will not shrink. Is there something that could enable me to shrink 2nd and 3rd partitions on a single VHDX? So just to be clear, it’s a single VHDX file with 3 partitions, C, D and E. C shrunk, and D and E did not.
You must shrink the partitions from within the guest operating system using one of the techniques shown in the article. The instructions are not different just because a partition has a different letter.
Hi Eric,
I have already performed the shrinking of the volumes through Disk Management. Now I’m left with 40GB on the D drive and 80GB on the E drive. I have also resized C drive, and after the shrinking of the VHDX through powershell, it only shrunk the VHDX for the C drive. Please keep in mind that this was a single 300GB VHDX with 3 x 100GB partitions. I wanted to end up with 50GB, 60GB, 20GB, but I ended up with 50GB, 60GB (40GB unallocated), 20GB (80GB unallocated). The methods you’re talking about are only for the shrinking of the volume. As far as I’m aware you cannot provide a partition Drive letter to shrink when it shrinks the VHDX file, so I’m thinking I’m stuck with 2 options:
1). Use disk2vhd to convert the partition into a separate vhdx disk then resize that and attach it to the vm as a unique disk.
2). Use some other software to shrink the partition or reorder the partition so the unallocated space ends up on the C drive so I would be able to shrink with the VHDX shrink cmdlet through Powershell.
Peter, the Resize-VHD cmdlet only knows allocated blocks from unallocated blocks. It doesn’t know or care if the blocks were released from C: or D: or were intentionally left blank or whatever else might have happened. I can believe that Microsoft committed an oversight and the shrink process isn’t smart enough to reclaim space between two partitions, but it has nothing to do with what drive letters are used.
For example, when you say: “it only shrunk the VHDX for the C drive,” that can only happen if the C: drive is in a VHDX all by itself. Even then, it would only be taking space from a VHDX that also happens to contain the partition that you call C:. Therefore, an operation with the goal of “… the unallocated space ends up on the C drive…”, will not help you at all. Resize-VHD cannot reclaim any space allocated to any volume. Any space to be reclaimed must be marked as unused in the partition table. It cannot be associated in any way with any drive letter or volume or anything of the kind.
Totally makes sense, thanks for pointing that information out. 🙂 I appreciate it!
Hello, Great guide!
I have run into an issue.
I went through your very detailed steps.
The VM OS basic (not dynamic) Disk 0 now shows unallocated space of 39.06gb.
But on the host, get-VHD of the vhdx reports Size == MinimumSize.
What could be causing this?
Most likely causes are that the unallocated space is not at the end of the drive or that the file is still in use.
Hello, Great guide!
I have run into an issue.
I went through your very detailed steps.
The VM OS basic (not dynamic) Disk 0 now shows unallocated space of 39.06gb.
But on the host, get-VHD of the vhdx reports Size == MinimumSize.
What could be causing this?
How can i do for shrink the file size vhdx value ?
I use this methode to shrink a vhdx file 1.5 TB to 1TB and in finally all is good for me.
My guest os say disk is 1TB, when i do the “get-vhd” commande the minimum size is 1TB, but filesize value is 1.5TB and in my Hyper v server the vhdx filesize value don t change it s always 1.5TB so i cant win the 500 GB free space
Can you explain me ?
If you followed all of the directions, then no, I don’t know why it is not shrinking.
I seem to be experiencing the same issue after a successful shrink on the OS and Hyper-V edit disk shrink as giulian and philipp.
When I inspect the VHDX (via Hyper-V Manager or via Explorer) on the host it shows that the current file size is much larger than the maximum disk size shown in the inspection window and the actual shrunk size in the VM host OS.
i.e.
Original VHDX size 171GB and VM host OS size 171GB
Size after Shrink in VM OS following the provided steps 142GB
Inspect the VHDX in Hyper-V Management console
Current File Size: 171GB
Maximum Disk Size: 142GB
Trying to free up Host storage to run Backups seems to be somewhat of a mission.
Another odd occurrence is when running “shrink querymax” it displays 112GB but when trying to shrink only half of that “shrink desired=68256” I get
“Virtual Disk Service error:”
“The specified shrink size is too big and will cause the volume to be
“smaller than the minimum volume size.”
I have followed the guide from disk-partition.com which provided no results.
https://www.disk-partition.com/articles/shrink-volume-not-enough-space-4348.html
Any knowledge to resolve these issues would greatly be appreciated.
How can i do for shrink the file size vhdx value ?
I use this methode to shrink a vhdx file 1.5 TB to 1TB and in finally all is good for me.
My guest os say disk is 1TB, when i do the “get-vhd” commande the minimum size is 1TB, but filesize value is 1.5TB and in my Hyper v server the vhdx filesize value don t change it s always 1.5TB so i cant win the 500 GB free space
Can you explain me ?
hi,
how did you solved your problem? i have exact same issue. shrinking was done- maximum size = minimum size 712Gb- which is shown correct in VM as disk size as well, but vhdx file itself is still 1,14TB on as bevore shrinking
I have samme issue but if i do a live storage migration the new file will be the expected size otherwise i think the offline compact command is the only way to actually shrink the file.
do you think replica option can make some trouble in this shrink method ?
That’s a strong possibility. I do not know.
i have shrink the vm
converted to fixed disk
still showing unallocated space 44gb
i have shrink the vm
converted to fixed disk
still showing unallocated space 44gb
Hi and thanks for the article.
you mention that online shrinking isn’t supported, but in hyper-v 12r2 you can do online shrinking for VHDX that is attached to a SCSI controller. if it’s a gen2 VM, you can do it even for a VHDX holding the system drive since IDE controllers are gone in gen 2 and everything is connected to SCSI. worth mentioning that in the article.
If above does not work, there is too much whitespace in the vhdx, use this to clean it up.
Diskpart
select vdisk file=D:Hyper-VVirtual Hard Disks<>.vhdx
attach vdisk readonly
compact vdisk
detach vdisk
You need to run a defraggler on your drive to bring all bits to the front of the partition. If you have a used block near the middle or end the minimum size will only shrink to that bit block. So even if you recover 50GB but the last used block is near the 45GB mark, you will shrink to the minimum size of 45GB
Hi,
Ran into the same issue as previously described by giulian and JimE.
The only missing command is to optimize the vhdx using this command:
Optimize-VHD -Path
Once done, the size of the file shrunk as expected.
Hope this helps.
Regards,
Z.
Preparing Ubuntu Guest for Shrinking:
Download an Ubuntu Desktop ISO to your server.
Under the VHDX settings move the boot order to DVD first
Set the DVD location to the ISO File
Save and Start VM
Choose GParted from start menu.
Select partition and resize. Ensure that unallocated space is at the end (right) of the partition(s).
Exit Ubuntu
You may now Shrink via the Edit Disk or via Powershell.
Your GPT table and MBR on Ubuntu is now corrupt and will not boot.
Again:
Under the VHDX settings move the boot order to DVD first
Set the DVD location to the ISO File
Save and Start VM
Open a Terminal
sudo gdisk /dev/sda
choose v to verify disk partitions and see errors.
choose r to access recovery commands
choose e to fix the partitions
select Y
choose w to write fixes
select Y
sudo fdisk -l
This will show your partitions are recovered or you may open GParted to view as well.
Exit Ubuntu
Under the VHDX settings move the boot order to DVD second with File first.
Save and Start VM
You have now shrunk Ubuntu Guest on VHDX
This solved my issue! I couldn’t boot my Ubuntu virtual machine after shrinking the VM, but your instructions on repairing the partition table in gdisk worked perfectly! Thanks!