Short answer
/ without a reboot.lsblk # find the disk, the PV partition and the LV
sudo growpart /dev/vda 3 # grow partition 3 into the new space
sudo pvresize /dev/vda3 # tell LVM the partition is bigger
sudo lvextend -r -l +100%FREE ubuntu-vg/ubuntu-lv # grow the LV and its file system
df -h /Key facts
- Package
- lvm2Debian, Ubuntu, Fedora, RHEL, Alma, Rocky
- Layers
- PV → VG → LV
- Default extent size
- 4 MiBvgcreate -s changes it
- LV device paths
- /dev/VG/LV, /dev/mapper/VG-LV
- Grow LV and file system
- lvextend -rext4 and XFS grow while mounted
- Shrink
- ext4 offline only, XFS not at all
- Metadata backups
- /etc/lvm/backup, /etc/lvm/archive
- growpart package
- cloud-guest-utilscloud-utils-growpart on RHEL family
Names in the examples (/dev/vda, ubuntu-vg) come from an Ubuntu Server install on a virtio disk; yours may differ, so always take them from lsblk and sudo lvs on your own machine. The growpart, resize2fs and e2fsck output quoted below is from our own run against image files; the LVM commands follow the lvm2 man pages (see how we tested).
How LVM works: PV, VG and LV
| Layer | What it is | Create | List |
|---|---|---|---|
| Physical volume (PV) | A disk or partition that LVM has labelled for its own use | pvcreate /dev/vdb | pvs |
| Volume group (VG) | A pool made of one or more PVs, split into extents (4 MiB by default) | vgcreate data /dev/vdb | vgs |
| Logical volume (LV) | A block device cut from the VG; you put a file system or swap on it | lvcreate -n files -L 20G data | lvs |
An LV does not have to sit in one piece on one disk. LVM maps its extents wherever the VG has free ones, which is why an LV can grow past the end of the disk it started on, and why pvmove can move data off a disk while the file system stays mounted. The same layer makes snapshots possible. What LVM does not add is redundancy: a plain LV spread over two disks is lost when either disk fails. Mirroring needs RAID, either mdadm under the PVs or LVM’s own --type raid1.
Two more LV types come up in every LVM overview. A striped LV (lvcreate -i 2 -I 64k) writes its extents to two or more PVs in turn, which adds throughput only when those PVs are separate physical disks, and keeps the same no-redundancy caveat. A thin pool (lvcreate --type thin-pool -L 50G -n pool data) hands out space only when it is written, so the thin volumes made from it with lvcreate -n vm1 -V 100G --thinpool pool data can add up to more than the pool holds; when the pool runs full, writes to every volume in it stall or fail.
Every change rewrites the VG metadata, and LVM keeps the previous copy: the current layout sits in /etc/lvm/backup, older versions in /etc/lvm/archive. vgcfgrestore can put back a layout after a mistake, but only the metadata, never the data that was written in the meantime.
Check whether your server uses LVM
Many VPS images use none. Cloud images of Ubuntu and Debian put ext4 straight on a partition, while the installers that run from an ISO often choose LVM: Ubuntu Server’s guided install ticks “Set up this disk as an LVM group” by default, and Fedora Server, RHEL, AlmaLinux and Rocky Linux install onto LVM as well. Do not guess, ask the system:
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS
sudo pvs
sudo vgs
sudo lvsNAME SIZE TYPE FSTYPE MOUNTPOINTS
vda 40G disk
├─vda1 1M part
├─vda2 2G part ext4 /boot
└─vda3 38G part LVM2_member
└─ubuntu--vg-ubuntu--lv 19G lvm ext4 /
PV VG Fmt Attr PSize PFree
/dev/vda3 ubuntu-vg lvm2 a-- <38.00g 19.00g
VG #PV #LV #SN Attr VSize VFree
ubuntu-vg 1 1 0 wz--n- <38.00g 19.00g
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
ubuntu-lv ubuntu-vg -wi-ao---- <19.00g- TYPE lvm in lsblk means LVM is in use. The partition under it shows
LVM2_memberas its file system type: that is the PV. - Doubled dashes in
ubuntu--vg-ubuntu--lvare not a typo. The device mapper joins VG and LV with one dash and doubles every dash inside the names. The same LV is/dev/ubuntu-vg/ubuntu-lvand/dev/mapper/ubuntu--vg-ubuntu--lv. - Need more detail?
sudo pvdisplay,sudo vgdisplayandsudo lvdisplayprint one block per object instead of one line: extent size, Total PE and Free PE, the LV Path and the UUIDs.pvs,vgsandlvsare the compact form and easier to script (-o +fieldadds columns). - VFree is space in the volume group that no LV uses yet. In the example it is half the disk; see the next section before you buy more storage.
- No lvm rows, and pvs says command not found or prints nothing: no LVM. Grow a plain partition with
growpartandresize2fsas shown in what is block storage.
Free space you already have
Ubuntu Server’s guided LVM layout often leaves part of the volume group unallocated, so a 40 GB disk can show a 19 GB root file system while df -h reports it full. If vgs shows space under VFree, there is nothing to resize below LVM: run the last step of the next section on its own.
sudo lvextend -r -l +100%FREE ubuntu-vg/ubuntu-lv
df -h /Extend the root volume after a disk resize
When your provider enlarges the virtual disk, the new space appears at the end of the disk and nothing else changes. It has to be passed up through every layer: partition, PV, LV, file system. Each step below is safe on a running server, and each one is visible in lsblk before you move on.
- 1Confirm that the kernel sees the bigger disk
any Linux lsblk /dev/vda # the disk line should show the new sizeVirtio disks usually report a new size to the guest at once. A SCSI disk may need a rescan:
echo 1 | sudo tee /sys/class/block/sda/device/rescan. If the disk line still shows the old size, a reboot is the simplest fix. - 2Grow the partition that holds the PV
Debian · Ubuntu (Fedora, RHEL, Alma, Rocky: sudo dnf install cloud-utils-growpart) sudo apt install -y cloud-guest-utils sudo growpart --dry-run /dev/vda 3 # shows what it would change sudo growpart /dev/vda 3 # disk and partition number, with a spacegrowpartmoves the end of the partition to the end of the disk (or to the start of the next partition) and leaves the data in it alone. On our 10 GiB test image grown to 20 GiB it answered:growpart (cloud-guest-utils 0.33) on a GPT test image CHANGED: partition=1 start=2048 old: size=16777216 end=16779263 new: size=41940959 end=41943006Run it again and it prints
NOCHANGE: partition 1 is size 41940959. it cannot be grownand exits with status 1, so a script can tell “nothing to do” from success. The PV partition must be the last one on the disk (or be followed by free space); on the Ubuntu layout above it is. - 3Resize the physical volume
any Linux with LVM sudo pvresize /dev/vda3 sudo pvs # PSize and PFree now include the new spacepvresizewithout a size takes the size of the device, and it works while LVs on the PV are active and mounted. If you skip this step,vgsshows no new free space and the next command fails with one of the errors listed below. - 4Extend the logical volume and its file system in one go
any Linux with LVM sudo lvextend -r -l +100%FREE ubuntu-vg/ubuntu-lv df -h /-l +100%FREEadds every free extent in the VG;-L +10Gadds a fixed amount instead. The plus sign matters:-L 10Gmeans “make it 10 GiB”, which fails on an LV that is already larger. LVM sizes are always powers of two, soGandgboth mean GiB.-r(--resizefs) grows the file system right after the LV, withresize2fsfor ext4 andxfs_growfsfor XFS, both while mounted. Since lvm2 2.03.17 (Debian 13, current RHEL 9)-ris the same as--fs resize. Older releases, such as Debian 12 and Ubuntu 24.04 (2.03.16) or Ubuntu 22.04 (2.03.11), hand the job tofsadmand have no--fsoption at all, so stick to-r: it works on both.
Forgot -r? The LV is bigger but df still shows the old size. Grow the file system by hand: sudo resize2fs /dev/ubuntu-vg/ubuntu-lv for ext4, or sudo xfs_growfs / for XFS, which takes the mount point. Our ext4 test image, grown from 2 to 4 GiB, reported:
resize2fs 1.47.0 (5-Feb-2023)
Resizing the filesystem on fs.img to 1048576 (4k) blocks.
The filesystem on fs.img is now 1048576 (4k) blocks long.Set up LVM on a new disk
For a second disk that should hold data of its own, for example /srv or a database directory, give it its own volume group. That keeps the system disk out of it, and the new volume can still grow later.
sudo apt install -y lvm2
sudo pvcreate /dev/vdb
sudo vgcreate data /dev/vdb
sudo lvcreate -n files -l 80%FREE data # leave 20 % free for snapshots and growth
sudo mkfs.ext4 -L files /dev/data/files
sudo mkdir -p /srv/files
echo "/dev/data/files /srv/files ext4 defaults,nofail 0 2" | sudo tee -a /etc/fstab
sudo systemctl daemon-reload && sudo mount -a && df -h /srv/filesLV paths such as /dev/data/files stay stable across reboots, so they are safe in /etc/fstab; a UUID= line works as well. Using the whole disk as a PV without a partition table is fine. If you prefer a partition, create it first and run pvcreate on /dev/vdb1. Leaving part of the VG unallocated costs nothing: it is what a snapshot needs later, and lvextend -r hands it out in seconds when a volume fills.
Add a disk to an existing volume group
To make an existing volume, including /, bigger with a second disk, add the disk to its volume group:
sudo pvcreate /dev/vdb
sudo vgextend ubuntu-vg /dev/vdb
sudo vgs # #PV is now 2, VFree has grown
sudo lvextend -r -l +100%FREE ubuntu-vg/ubuntu-lvThis is quick, and it ties the file system to both disks: if either fails, the LV is gone. On a VPS where both disks sit on the same storage that risk is small, but backups still have to cover the whole volume. When the provider can simply enlarge the existing disk, growing the partition as above is the cleaner path, because it keeps one disk under /.
Take a disk out of a volume group
sudo pvs -o+pv_used # how much data sits on /dev/vdb
sudo pvmove /dev/vdb # move its extents to the other PVs (online)
sudo vgreduce ubuntu-vg /dev/vdb
sudo pvremove /dev/vdbpvmove needs as much free space on the remaining PVs as the disk holds; if the VG has none, shrink a volume first (only possible with ext4, see below) or add a replacement disk before you remove the old one. vgreduce refuses a PV that still holds extents, which is your safety net.
Remove or rename a logical volume and volume group
Removal runs top down, the reverse of the setup: whatever uses the file system, then the LV, the VG and finally the PV label. lvremove asks before it removes an active volume, and vgremove asks for every LV still in the group.
sudo lvdisplay data/files # right LV in the right VG?
sudo umount /srv/files # and delete its line in /etc/fstab
sudo lvremove data/files
sudo vgremove data
sudo pvremove /dev/vdb # the disk carries no LVM label any moresudo lvrename data files archive renames an LV, vgrename a VG; update /etc/fstab and anything else that names the old path. Leave the names of the VG and LV that hold / alone: the root device is also written into the GRUB configuration and the initramfs, and a rename that misses one of them stops the next boot.
LVM snapshots before an upgrade
A snapshot freezes an LV at one moment. Afterwards, the first write to any block of the origin copies the old block into the snapshot (copy on write), so the snapshot only needs room for what changes, not for the whole volume. That makes it a good undo button for a release upgrade such as Debian 12 to 13:
sudo vgs # VFree must cover the snapshot size
sudo du -sh /usr # rough size of what a release upgrade rewrites
sudo tar -czf /root/boot-before-upgrade.tgz /boot
sudo lvcreate -s -n root-pre-upgrade -L 8G ubuntu-vg/ubuntu-lv
sudo lvs # Data% shows how full the snapshot isThe space cost is real and comes out of the volume group, not the file system. A release upgrade replaces most of /usr and downloads its packages into /var/cache, so size the snapshot at least as large as du -sh /usr plus a few gigabytes. The lvcreate man page says 20 % of the origin is often enough for normal operation; an upgrade is not normal operation. Watch Data% in lvs while the upgrade runs, and grow the snapshot with sudo lvextend -L +4G ubuntu-vg/root-pre-upgrade if it climbs.
Roll back, or keep the upgrade
# drop the snapshot, its space returns to the VG
sudo lvremove ubuntu-vg/root-pre-upgradesudo lvconvert --merge ubuntu-vg/root-pre-upgrade
sudo find /boot -maxdepth 1 -type f -newer /root/boot-before-upgrade.tgz -delete
sudo tar -xzf /root/boot-before-upgrade.tgz -C / --exclude=boot/grub --exclude=boot/efi
sudo update-grub # menu now starts the old kernel
sudo rebootThe merge of a volume that is in use, such as /, is deferred until the origin is next activated, which for the root volume means the next boot; afterwards the snapshot disappears and the LV keeps its name. Two things the snapshot does not roll back:
- /boot on its own partition. On the Ubuntu layout above,
/bootis not on LVM. Reboot straight after the merge and the old/lib/modulescomes back while GRUB still starts the new kernel and initramfs, so the system can come up without network or other modules. That is why the rollback block puts/bootback before the reboot:finddeletes the kernel files the upgrade wrote,tarrestores the old ones from the archive made earlier, andupdate-grubrebuilds the menu around them. GRUB’s own files stay at the upgraded version on purpose, because the upgrade has usually reinstalled the boot loader and old GRUB modules do not load into a new one. Once the old system is up, reinstall the boot loader from it (on BIOS bootsudo grub-install /dev/vda, thensudo update-grub). If the old kernel package is still installed, choosing it under “Advanced options” in the GRUB menu on that reboot is the quick alternative. - Other volumes and other servers. A database on a separate LV, or anything the upgrade changed elsewhere, stays at its new state.
A snapshot lives in the same volume group, on the same disks, as the data it protects, so it is no backup; the block storage guide explains the difference. To read files from a snapshot without merging it, mount it read-only: sudo mount -o ro /dev/ubuntu-vg/root-pre-upgrade /mnt. For XFS add nouuid to the options, because the snapshot carries the same file system UUID as the mounted origin. Thin volumes, which Proxmox VE uses for its local-lvm storage, work differently: a thin snapshot takes no size and shares the pool’s free space.
Shrink a logical volume: ext4 yes, XFS no
| ext4 | XFS | |
|---|---|---|
| Grow while mounted | Yes | Yes |
| Shrink while mounted | No | No |
| Shrink while unmounted | Yes | No |
| Grow command | resize2fs /dev/VG/LV | xfs_growfs /mountpoint |
| lvextend -r | Yes | Yes |
| lvreduce -r | Yes, unmounted | No |
| Default on | Debian, Ubuntu | Fedora Server, RHEL, Alma, Rocky |
ext4 can be shrunk only while it is not mounted, and the file system has to shrink before the LV does, or the end of it is cut off. lvreduce -r does both in the right order: it checks the file system, shrinks it with resize2fs, then shrinks the LV, and stops if resize2fs refuses the size:
sudo umount /srv/files
sudo lvreduce -r -L 15G data/files # file system first, then the LV
sudo mount /srv/filesWith lvm2 2.03.17 or later, lvreduce -r would also unmount and remount a mounted ext4 volume on its own (its default --fsmode manage); the explicit umount above works on every release and stops with “target is busy” while something still uses the volume. Done by hand, the order is e2fsck -f, then resize2fs to the new size, then lvreduce. In our test, resize2fs stopped a shrink below the space in use with resize2fs: New size smaller than minimum (26205), and resize2fs -P prints that minimum before you try. Run lvreduce without -r before the file system has shrunk and, in the words of its man page, the data in the reduced area is lost.
The root file system cannot be unmounted on a running server, so shrinking / means booting another system first. XFS cannot be shrunk at all: the way back to a smaller XFS volume is a new, smaller LV, a copy of the data (xfsdump and xfsrestore, or rsync -aHAX) and a switch in /etc/fstab. In practice, on a server, plan to grow and keep free extents in the VG instead.
Common LVM errors
Symptom, cause, fix
Symptom:
Insufficient free space: 4863 extents needed, but only 0 available- Cause
- The VG has no free extents: pvresize was not run after the partition grew, the disk was never enlarged, or -L was given without + and asked for a total size that does not fit.
- Fix
- Check
sudo vgs(VFree). Rungrowpartandpvresizefirst, or add a disk withvgextend, and write the size as-L +10Gor-l +100%FREE.
Symptom:
New size (N extents) matches existing size (N extents).orNew size given (N extents) not larger than existing size- Cause
- There is nothing to add: +100%FREE on a VG with no free space, or an absolute -L size that is not bigger than the LV already is.
- Fix
- Same checks as above:
sudo pvsandsudo vgsshow where the free space is (or is not).
Symptom: lvextend reports success, but df -h still shows the old size
- Cause
- The LV grew without -r, so the file system inside it did not.
- Fix
ext4 · XFS sudo resize2fs /dev/ubuntu-vg/ubuntu-lv # ext4 sudo xfs_growfs / # XFS: give the mount point
Symptom:
NOCHANGE: partition 3 is size N. it cannot be grown- Cause
- growpart found no free space after the partition: the kernel still sees the old disk size, or another partition follows it.
- Fix
- Check the disk line in
lsblk; rescan or reboot if it is the old size. If a swap partition sits after the PV, the partition cannot grow in place: add the new space as a new partition andvgextendwith it instead.
Symptom:
Logical volume data/files contains a filesystem in use.orCan't remove open logical volume- Cause
- The LV is still mounted, or a process, container or another mount keeps the device open.
- Fix
any Linux findmnt /dev/data/files sudo fuser -vm /dev/data/files sudo umount /srv/files && sudo lvremove data/files
Symptom:
Cannot use /dev/vdb: device is partitioned(older lvm2 2.02, or a filter in lvm.conf:Device /dev/vdb excluded by a filter.ordevice is rejected by filter config)- Cause
- pvcreate was pointed at a whole disk that carries a partition table, so LVM refuses to overwrite it (since lvm2 2.03.27 only a table that actually has partitions counts). The filter variants mean a filter or global_filter line in /etc/lvm/lvm.conf hides the device.
- Fix
- Run
lsblk /dev/vdbandsudo wipefs /dev/vdbto see what is there. To use a partition, runpvcreateon/dev/vdb1. Only if the disk is truly unused, clear the table withsudo wipefs -a /dev/vdband runpvcreateagain. For the filter variants, fix the filter line instead.
A volume that filled up before you could grow it shows its own errors in applications and logs; no space left on device covers those, and checking disk usage finds what is using the space, which is often cheaper than adding more.
LVM on a VMHeaven VPS
Extra storage on a VMHeaven VPS, added from the panel in fixed blocks on a running server, enlarges the existing virtual disk instead of attaching a second one. On an LVM install, that is exactly the grow the root volume case: growpart, pvresize, lvextend -r, no reboot. Without LVM, the same new space goes to a plain partition with growpart and resize2fs. If an /etc/fstab change for a new volume stops the boot, the VNC console in the panel still reaches the server.
Before a release upgrade, the simpler undo is a snapshot in the VPS panel. It covers the whole disk, /boot included, so none of the kernel steps from the rollback section apply. Take one by hand before you start, or let the panel take them on a daily, weekly or monthly schedule, and restore it when the upgrade goes wrong. The LVM snapshot stays the in-guest option, for a single volume or a quick undo without leaving the shell. A Standard KVM VPS is enough for every command in this guide; the line you choose decides vCores and RAM, and the disk follows your data.
How we tested
- OS image
- Debian 12
- Versions
- cloud-guest-utils 0.33e2fsprogs 1.47.0util-linux 2.38.1
- Tested on
- Method
- growpart, sfdisk, resize2fs and e2fsck run against sparse image files in a scratch folder: a 10 GiB GPT image grown to 20 GiB, and an ext4 image grown from 2 to 4 GiB, shrunk to 3 GiB and refused below its minimum. The LVM commands (pvresize, lvextend, lvcreate, lvconvert, lvreduce, lvremove, vgremove, lvrename) were not run; the /boot restore order (find -newer, tar --exclude) was checked on scratch files only; their syntax and behaviour are from the lvm2 man pages (LVM tools 2.03.42) and lvm.conf defaults.
Frequently asked
What is LVM in Linux?
LVM (Logical Volume Manager, package lvm2) is a layer between disks and file systems. Disks or partitions become physical volumes (PVs), PVs are pooled into a volume group (VG), and logical volumes (LVs) are cut from the VG and formatted like partitions. LVs can grow across disks, be resized while mounted and be snapshotted.
How do I extend an LVM partition after the disk was enlarged?
Pass the new space up through each layer: grow the partition that holds the PV with 'sudo growpart /dev/vda 3', resize the PV with 'sudo pvresize /dev/vda3', then grow the logical volume and its file system with 'sudo lvextend -r -l +100%FREE vg/lv'. All three steps work while the server is running; check the result with df -h.
Why does df not show the new size after lvextend?
lvextend without -r grows only the logical volume, not the file system inside it. Run 'sudo resize2fs /dev/vg/lv' for ext4 or 'sudo xfs_growfs /mountpoint' for XFS; both work while mounted. Next time add -r (--resizefs) to lvextend to do both in one step.
Can I shrink an LVM logical volume?
With ext4, yes, but only while it is unmounted: 'sudo lvreduce -r -L 15G vg/lv' checks and shrinks the file system first, then the LV. XFS cannot be shrunk; copy the data to a new, smaller LV instead. Shrinking the LV before the file system destroys the data in the removed part.
How much space does an LVM snapshot need?
A copy-on-write snapshot needs free extents in the volume group, enough for every block that changes while it exists. The lvcreate man page says 20 % of the origin is often enough; a release upgrade rewrites most of /usr, so size it at least as large as 'du -sh /usr' plus a few gigabytes. A snapshot that reaches 100 % becomes invalid.