Guides

LVM in Linux: extend a logical volume, add a disk, snapshots and shrink rules

LVM in Linux: check if your server uses it, grow the root volume after a disk resize with growpart, pvresize and lvextend -r, snapshots, shrink rules.

Published ~12 min read
On this page

Short answer

LVM (Logical Volume Manager) puts a layer between disks and file systems: disks or partitions become physical volumes, they are pooled into a volume group, and you cut logical volumes from that pool and format them like partitions. The payoff is resizing: after a disk grows, three commands give the space to / without a reboot.
any Linux with LVM · grow / after the disk was enlarged (example names)
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

LayerWhat it isCreateList
Physical volume (PV)A disk or partition that LVM has labelled for its own usepvcreate /dev/vdbpvs
Volume group (VG)A pool made of one or more PVs, split into extents (4 MiB by default)vgcreate data /dev/vdbvgs
Logical volume (LV)A block device cut from the VG; you put a file system or swap on itlvcreate -n files -L 20G datalvs

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:

any Linux
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS
sudo pvs
sudo vgs
sudo lvs
Example output · Ubuntu Server ISO install with LVM, 40 GB disk
NAME                        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_member as its file system type: that is the PV.
  • Doubled dashes in ubuntu--vg-ubuntu--lv are 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-lv and /dev/mapper/ubuntu--vg-ubuntu--lv.
  • Need more detail? sudo pvdisplay, sudo vgdisplay and sudo lvdisplay print one block per object instead of one line: extent size, Total PE and Free PE, the LV Path and the UUIDs. pvs, vgs and lvs are the compact form and easier to script (-o +field adds 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 growpart and resize2fs as 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.

any Linux with LVM · use the VG's free space for /
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.

  1. 1Confirm that the kernel sees the bigger disk
    any Linux
    lsblk /dev/vda            # the disk line should show the new size

    Virtio 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.

  2. 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 space

    growpart moves 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=41943006

    Run it again and it prints NOCHANGE: partition 1 is size 41940959. it cannot be grown and 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.

  3. 3Resize the physical volume
    any Linux with LVM
    sudo pvresize /dev/vda3
    sudo pvs                                # PSize and PFree now include the new space

    pvresize without 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, vgs shows no new free space and the next command fails with one of the errors listed below.

  4. 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%FREE adds every free extent in the VG; -L +10G adds a fixed amount instead. The plus sign matters: -L 10G means “make it 10 GiB”, which fails on an LV that is already larger. LVM sizes are always powers of two, so G and g both mean GiB. -r (--resizefs) grows the file system right after the LV, with resize2fs for ext4 and xfs_growfs for XFS, both while mounted. Since lvm2 2.03.17 (Debian 13, current RHEL 9) -r is 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 to fsadm and have no --fs option 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 on a test image
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.

Debian · Ubuntu (Fedora, RHEL, Alma, Rocky: sudo dnf install lvm2)
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/files

LV 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:

any Linux with LVM
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-lv

This 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

any Linux with LVM
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/vdb

pvmove 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.

any Linux with LVM · remove the data volume from the setup above
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 more

sudo 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:

any Linux with LVM · before the upgrade
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 is

The 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

any Linux with LVM · upgrade went fine
# drop the snapshot, its space returns to the VG
sudo lvremove ubuntu-vg/root-pre-upgrade
Debian · Ubuntu · upgrade went wrong: merge, put the old kernel back, then reboot
sudo 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 reboot

The 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, /boot is not on LVM. Reboot straight after the merge and the old /lib/modules comes 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 /boot back before the reboot: find deletes the kernel files the upgrade wrote, tar restores the old ones from the archive made earlier, and update-grub rebuilds 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 boot sudo grub-install /dev/vda, then sudo 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

ext4XFS
Grow while mountedYesYes
Shrink while mountedNoNo
Shrink while unmountedYesNo
Grow commandresize2fs /dev/VG/LVxfs_growfs /mountpoint
lvextend -rYesYes
lvreduce -rYes, unmountedNo
Default onDebian, UbuntuFedora Server, RHEL, Alma, Rocky
From resize2fs(8) in e2fsprogs 1.47.0, xfs_growfs(8) and lvreduce(8), checked 02.11.2026. xfs_growfs can shrink only the last allocation group without removing it, which is not a general shrink.

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:

any Linux with LVM · ext4 data volume
sudo umount /srv/files
sudo lvreduce -r -L 15G data/files          # file system first, then the LV
sudo mount /srv/files

With 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

  1. 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). Run growpart and pvresize first, or add a disk with vgextend, and write the size as -L +10G or -l +100%FREE.
  2. Symptom: New size (N extents) matches existing size (N extents). or New 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 pvs and sudo vgs show where the free space is (or is not).
  3. 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
  4. 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 and vgextend with it instead.
  5. Symptom: Logical volume data/files contains a filesystem in use. or Can'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
  6. 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. or device 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/vdb and sudo wipefs /dev/vdb to see what is there. To use a partition, run pvcreate on /dev/vdb1. Only if the disk is truly unused, clear the table with sudo wipefs -a /dev/vdb and run pvcreate again. 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.

Related articles

All guides