btrfs vs LVM: which one can shrink on a cloud VM?

Both grow while mounted. What decides whether a disk can leave again, and why the filesystem matters more than LVM.

Published 1 November 2026 · By Sourabh Singh (opens in a new tab), Senior software engineer, Zoorik · Published by Zoorik

btrfs vs LVM: btrfs frees a disk directly, while LVM must shrink the filesystem first

Short answer. In btrfs vs LVM, both can empty a disk while mounted, but only btrfs uses its own free space as room for that disk’s data. LVM’s pvmove needs free extents, and making them means shrinking the filesystem first: ext4 only while unmounted, XFS not in any useful way.

On a cloud VM, you pay for fewer GiB only when a disk leaves

Picture an Azure VM whose data mount spans four 512 GiB managed disks, 2,048 GiB in all, holding 1,000 GiB. You pay for all 2,048 GiB.

btrfs can empty one disk and let it go while mounted. LVM, with all four disks in one logical volume, can’t until the filesystem and the logical volume shrink.

Azure charges for managed disks “according to their provisioned size”. Its example adds “regardless of the amount of data written to the disk”. The Azure disk pricing calculator shows what that empty space costs.

Neither cloud shrinks a disk in place. Microsoft Learn says shrinking an existing disk “isn’t supported and might result in data loss”. The Amazon Elastic Block Store (EBS) guide says “You can’t decrease the volume size”.

So on a running VM, paying for fewer GiB takes three steps:

  1. Empty a whole disk.
  2. Take it out of the stack.
  3. Detach and delete it.

The Logical Volume Manager (LVM) pools block devices in layers:

  • Each disk becomes a physical volume (PV).
  • PVs join a volume group (VG).
  • You carve logical volumes (LVs) out of the VG.

An LV is a block device, so it still needs a filesystem such as ext4 or XFS on top.

A btrfs filesystem does both jobs in one. It “can be created on top of single or multiple block devices”. Its device management “works on a mounted filesystem”.

What you decide onLVM with ext4 or XFSbtrfs
Layers
PVs, a VG and LVs, then a filesystem on each LV
One filesystem across one or more devices
Use a cloud disk you made larger
pvresize, then lvextend --resizefs, while mounted
btrfs filesystem resize <devid>:max, while mounted
Add a disk
pvcreate, vgextend, then lvextend --resizefs
btrfs device add, while mounted
Empty a disk and take it out
pvmove, vgreduce, pvremove, while the disks are in use
btrfs device remove, while mounted
Where the disk’s data goes
Free extents on the other PVs
Free space on the other devices, within the profile’s rules
Making that room
Shrink an LV and its filesystem first: ext4 only unmounted, XFS can’t
Nothing extra, unused space in the filesystem is the room
Splitting space between mounts
LVs, each with its own fixed size
Subvolumes, which share the filesystem’s free space
Snapshots
Thick: space set aside up front. Thin: from a thin pool, no size
A subvolume that starts out sharing its data blocks with the source

btrfs vs LVM with ext4 or XFS: the filesystem decides the shrink

Red Hat’s guide says “you can move data while your system is active using the pvmove command”. So emptying a PV while its filesystem stays mounted is routine.

These commands take a disk out of LVM, so run them only on the disk you mean to delete. Before vgreduce, check in pvs that the disk’s PFree equals its PSize:

sudo pvs
sudo pvmove /dev/<old-disk>
sudo pvs
sudo vgreduce <vg-name> /dev/<old-disk>
sudo pvremove /dev/<old-disk>

The catch: pvmove needs free extents on the other PVs for that disk’s data. Red Hat’s procedure adds a new PV first “If there are not enough free extents on the other physical volumes in the existing volume group”.

LVM sees extents, not files. Say you once ran lvextend to give an LV the whole VG. Then every extent belongs to that LV, even when the filesystem inside it is mostly empty.

Free space in the filesystem isn’t free space in the VG.

On btrfs with single data (one copy), the roughly 2,048 − 1,000 = 1,048 GiB free is the room. The 1,000 GiB fits on three disks with roughly 1,536 − 1,000 = 536 GiB to spare. With disk 4 deleted, you pay for 1,536 GiB of data disks instead of 2,048.

On LVM, one LV holds every extent in the VG. So pvmove finds 0 GiB free until the filesystem and the LV shrink.

btrfs can use its free space to empty a disk, pvmove can't Two groups drawn to one scale from 0 to 2,048 GiB, ticked every 512 GiB, each standing on four disks of 512 GiB, disk 1 to disk 4. In the LVM group, with one LV across the whole VG, the filesystem holds data of 1,000 GiB and free space of about 1,048 GiB, and it sits on one LV that holds every extent of all four disks. The free extents in the VG are 0 GiB, so disk 4 stays, because pvmove has nowhere to move it. In the btrfs group, with single data, the filesystem holds the same 1,000 GiB of data and about 1,048 GiB free, and it stands straight on the disks with no LV. A bracket over disks 1 to 3 says 3 disks stay, 1,536 GiB, room for the 1,000 GiB, and disk 4, dashed, can leave while mounted. btrfs can use its free space to empty a disk, pvmove can't LVM, one LV across the whole VGfilesystemLVdisks512 GiB eachdata 1,000 GiBfree in the filesystem, about 1,048 GiBone LV holds every extentdisk 1disk 2disk 3disk 4stays: pvmove has nowhere to move itfree extents in the VG: 0 GiBbtrfs, single datafilesystemno LVdisksdata 1,000 GiBfree, about 1,048 GiB3 disks stay: 1,536 GiB, room for the 1,000 GiBdisk 1disk 2disk 3disk 4can leave while mounted05121,0241,5362,048GiB
Both groups are drawn to one scale from the four-disk case, and the bars show totals, since the blocks themselves can sit on any disk.

So making room means shrinking the LV, and an LV can only shrink after its filesystem does. Red Hat warns that the filesystem must not be “using the space in the logical volume that is being reduced”.

To keep pvmove possible, leave free extents in the VG and grow each LV with lvextend --resizefs only as its data needs. That helps until the data shrinks, because the LV doesn’t shrink with it. Removing a disk from LVM walks through both cases.

LVM with ext4: shrink only while unmounted

The resize2fs man page says it can “enlarge or shrink an unmounted file system”. On a mounted one, it can only expand.

Red Hat’s shrink procedure follows from that:

  1. Unmount the LV.
  2. Run e2fsck -f.
  3. Run lvreduce --size <new-size> --resizefs.
  4. Mount it again.

Every service on that mount stops for the check and the resize. The steps and the minimum size are in shrinking ext4 with resize2fs.

LVM with XFS: only a copy gives the space back

Red Hat states that “XFS does not support reducing the size of a volume formatted with an XFS file system”. With XFS on the LV, no LVM command can free those extents without losing data.

The route is a copy onto a new, smaller filesystem, with a stop while you switch over. Shrinking an XFS filesystem covers it.

btrfs takes a disk out while it stays mounted

A btrfs filesystem has no second layer to keep in step. Adding a device “is instant and does not affect existing data”. Removing one moves its data onto the others.

The docs warn “The operation can take long as it needs to move all data from the device”. Two rules decide whether a removal works:

  • Space. The data has to fit on the devices that stay, with unallocated space to spare.
  • Profile. The docs say “Device removal must satisfy the profile constraints, otherwise the command fails”. A profile is btrfs’s allocation policy for data and metadata, such as single or RAID1. In the docs’ example, a RAID1 filesystem can’t drop to one device until it’s converted to another profile. The error reads “unable to go below two devices on raid1”. For the profiles, see btrfs on multiple disks.

The removal moves every block off the device you name. So check the space first, and name only the disk you mean to delete:

sudo btrfs filesystem usage <mount-point>
sudo btrfs device remove /dev/<old-disk> <mount-point>
sudo btrfs filesystem show <mount-point>

Check that btrfs filesystem show no longer lists the device. Deleting is permanent, so first confirm the cloud disk’s name and resource ID, then detach and delete it.

Charges end with the delete, because Azure prorates a disk hourly, whatever it holds. The full steps are in btrfs device remove.

The docs say “The resize command does not manipulate the size of underlying partition”. Under it, the cloud disk can’t shrink at all. One btrfs filesystem across several smaller disks is the layout that pays.

btrfs subvolumes vs LVM logical volumes

LVM splits a VG into LVs, each a block device with its own size. Space one LV holds is free for another only after lvreduce, when “the freed up logical extents are returned to the volume group”.

btrfs subvolumes share the single storage pool of the whole filesystem instead. On a VM with several data mounts, they all draw on one pool of free space, not one per LV.

A subvolume looks like a directory and mounts on its own with the subvol or subvolid option. Capacity limits come from quota groups if you want them.

LVM vs btrfs snapshots, and why LVM thin still needs free extents

LVM has two kinds of snapshot, and btrfs has one:

  • LVM thick snapshot. It “requires you to allocate some amount of storage space upfront”. Red Hat also warns “If a snapshot reaches 100% of its allocated space, it will become invalid”.
  • LVM thin snapshot. Made from a thin LV, it needs nothing set aside and shares the same data blocks as its origin until the origin changes.
  • btrfs snapshot. It’s “a subvolume like any other, with given initial content”. It starts out sharing all its data blocks with the original through copy-on-write.

On LVM thin vs btrfs, thin provisioning comes close to what btrfs does with subvolumes. Its LVs can be “larger than the available physical storage”, and “A thin pool allocates space on-demand to its LVs”.

What it doesn’t change is the cloud disk. The thin pool sits on PVs on managed disks or EBS volumes, charged at their provisioned size. Taking a disk out from under it is still a pvmove that needs free extents.

In a thin pool and in btrfs alike, a snapshot goes on referencing the blocks it shares with its origin. So deleting files that were there when you took it doesn’t give their space back while the snapshot exists.

btrfs or LVM: which to choose on a cloud VM

Of the stacks here, only btrfs across several disks hands a disk back with nothing unmounted, however large the data once grew.

Only btrfs takes a disk out with nothing unmounted Three columns of numbered steps, read top to bottom. LVM with ext4 takes 7 steps: 1 stop services and unmount, 2 check the filesystem, 3 shrink the filesystem and the LV, 4 mount and start services again, 5 move the disk's extents to the other disks, 6 take the disk out of the VG, 7 detach and delete the disk. A red bracket beside steps 1 to 4 reads services stopped. LVM with XFS, where XFS can't shrink in place, takes 3 steps: 1 copy onto a new, smaller filesystem, 2 stop services and switch over, 3 detach and delete the old disks. A red bracket beside step 2 reads services stopped. btrfs takes 2 steps: 1 move the disk's data onto the others, 2 detach and delete the disk. A bracket beside both reads stays mounted. Only btrfs takes a disk out with nothing unmounted LVM with ext41stop services and unmount2check the filesystem3shrink the filesystemand the LV4mount and startservices again5move the disk's extentsto the other disks6take the disk out of the VG7detach and delete the diskLVM with XFSXFS can't shrink in place1copy onto a new,smaller filesystem2stop servicesand switch over3detach and deletethe old disksbtrfs1move the disk'sdata onto the others2detach and delete the diskservices stoppedservices stoppedstays mounted
Each column lists the steps to take one disk out, in order. The brackets mark the steps during which the mount’s services are stopped or stay running.
  • Data whose size moves both ways. Pick btrfs over several disks.
  • Data that only grows, or a mount that can take a planned stop. LVM with ext4 suits it.
  • LVM with XFS. It’s one-way. Size it for growth, and plan a copy if the data ever shrinks a lot.

Before you pick btrfs, check that your distribution ships it in its kernel, with the btrfs-progs tools. You must also trust the profile you plan to use, which how stable btrfs is goes through.

Moving an existing ext4 or XFS mount onto a new btrfs filesystem is a copy with a short stop at the switch. It’s the same route as moving to a smaller Azure disk.

How Amoeba uses a btrfs pool

Amoeba optimizes block storage on Azure and AWS, on the btrfs side of this comparison. It works on the data disks of running Windows and Linux VMs, and never touches the OS disk.

Amoeba moves a VM’s data disks onto one btrfs pool sized to your data, with room to grow. Each data mount becomes a subvolume on the pool, mounted at its old path. So applications read and write where they did.

The mounts it moves can be ext4, XFS or another block-backed filesystem, on LVM or not. Every disk under them must be a cloud data disk.

Getting there takes one copy, which Amoeba makes while your services run. Then it switches each mount to the pool, with a short restart of the services that use it.

Growing and shrinking the pool

After the move, the pool changes size while it stays mounted:

  • Data grows. Amoeba grows the pool before it fills, and sooner when data arrives fast. It grows the pool’s disks or adds new ones, and the space goes in at once.
  • Data shrinks. When your data goes down and stays down, Amoeba shrinks the pool one disk at a time. It moves that disk’s data onto the others with btrfs device remove. Then it detaches the empty disk and deletes it, with no snapshot, so its charges stop.
  • The limit. Amoeba never detaches a disk while the pool is nearly full, or while an urgent expand runs.

On Linux, the VM needs a recent kernel with btrfs. Every service that keeps a data mount open must run under systemd, so Amoeba can stop it and start it again at the switch. The VM also needs a few free disk slots for the pool.

The pages on Azure managed disk cost optimization and EBS cost optimization cover each cloud in full.

Sources: BTRFS documentation, “btrfs-device(8)” (opens in a new tab); BTRFS documentation, “btrfs-filesystem(8)” (opens in a new tab); BTRFS documentation, “Subvolumes” (opens in a new tab); Red Hat, “Configuring and managing logical volumes” (opens in a new tab) (RHEL 9); man7.org, “resize2fs(8)” (opens in a new tab); Microsoft Learn, “Expand virtual hard disks on a Linux VM” (opens in a new tab); Microsoft Learn, “Select a disk type for Azure IaaS VMs” (opens in a new tab); AWS, “Modify an Amazon EBS volume using Elastic Volumes operations” (opens in a new tab).

Find your own number

One line in your cloud console. One PDF report with your estimated saving at list price.

Estimate your saving

Talk to the builders

Thirty minutes with the people who build Amoeba.

Book a demo (opens in a new tab)

Or write to founders@zoorik.com