How to Set Up LVM (Logical Volume Management) on Linux
A complete walkthrough from raw disks to a mounted, resizable logical volume — physical volumes, volume groups, and logical volumes explained as you build them.
LVM adds a flexible layer between raw disks and filesystems — letting you resize, add, or remove storage without the rigid constraints of working with partitions directly. This walks through the three-layer structure LVM is built from, from the ground up.
Step 1: install LVM tools
sudo apt install lvm2 # Debian/Ubuntu
sudo dnf install lvm2 # Fedora/RHEL
Step 2: create physical volumes from raw disks or partitions
sudo pvcreate /dev/sdb /dev/sdc
A physical volume (PV) is LVM’s basic building block — a whole disk or a partition, marked for LVM to manage. This step doesn’t create any usable storage yet; it just registers these devices as available.
Step 3: verify the physical volumes
sudo pvs
sudo pvdisplay
Step 4: combine physical volumes into a volume group
sudo vgcreate data-vg /dev/sdb /dev/sdc
A volume group (VG) pools one or more physical volumes into a single space to allocate storage from — this is what makes it possible to later grow a logical volume beyond the size of any single physical disk, simply by adding another PV to the group.
Step 5: create a logical volume from the volume group
sudo lvcreate -L 100G -n mydata data-vg
A logical volume (LV) is what actually gets formatted and mounted — think of it as a flexible, resizable “virtual partition” carved out of the volume group’s pooled space.
Step 6: format and mount the logical volume
sudo mkfs.ext4 /dev/data-vg/mydata
sudo mkdir /mnt/mydata
sudo mount /dev/data-vg/mydata /mnt/mydata
Step 7: grow the logical volume later, without unmounting
sudo lvextend -L +50G /dev/data-vg/mydata
sudo resize2fs /dev/data-vg/mydata
This is LVM’s headline practical benefit: growing storage on a live, mounted filesystem, as long as the volume group has (or gains, via vgextend and another physical volume) enough free space to grow into.
Step 8: add more physical storage to the volume group later
sudo pvcreate /dev/sdd
sudo vgextend data-vg /dev/sdd
Adding a new disk to an existing volume group makes its space available for logical volumes to grow into — without needing to migrate data or reformat anything already in use.
Step 9: persist the mount across reboots
# /etc/fstab
/dev/data-vg/mydata /mnt/mydata ext4 defaults 0 2
Why the three-layer structure is worth understanding, not just memorizing commands for
Physical volumes, volume groups, and logical volumes map directly onto the three problems LVM solves: PVs abstract away which physical disk storage actually lives on, VGs pool that storage into a single resizable space, and LVs carve out flexible, growable pieces of that pool for actual use. Understanding which layer a given command operates on — rather than treating pvcreate/vgcreate/lvcreate as an arbitrary sequence to memorize — makes it much easier to reason about what’s actually possible (growing an LV needs free space in its VG; growing a VG needs another PV) when planning storage changes later.
Taking a snapshot before a risky change
sudo lvcreate -L 10G -s -n mydata-snap /dev/data-vg/mydata
An LVM snapshot captures the logical volume’s state at the exact moment it’s created, using copy-on-write: the snapshot itself only stores blocks as they change on the original volume afterward, which is why a snapshot can be allocated a fraction of the original volume’s size (10G here, for a much larger mydata) rather than needing a full duplicate. This makes a snapshot genuinely useful as a safety net immediately before a risky operation — a major application upgrade, a database schema migration — since reverting is a single command if something goes wrong:
sudo umount /mnt/mydata
sudo lvconvert --merge /dev/data-vg/mydata-snap
A snapshot isn’t a backup on its own, though: it lives in the same volume group as the original and depends on the same underlying physical disks, so it protects against a bad software change but not against the disk itself failing — genuine backups still need to live somewhere physically separate.
Thin provisioning: allocating more than you currently have
sudo lvcreate -L 500G -T data-vg/thinpool
sudo lvcreate -V 200G -T data-vg/thinpool -n thinvol1
sudo lvcreate -V 200G -T data-vg/thinpool -n thinvol2
A thin pool lets you create logical volumes whose combined advertised size (400G across the two volumes above) exceeds the pool’s actual allocated size (500G total pool, but only space actually written to is consumed) — useful when several volumes each need headroom to grow but rarely all grow to their full advertised size simultaneously, similar in spirit to how a cloud provider overcommits storage. The real risk this introduces is the pool itself running out of physical space if usage grows faster than expected across all thin volumes combined, at which point every thin volume in that pool can fail writes simultaneously regardless of what any individual volume’s own advertised size implies — monitoring the pool’s actual data usage (lvs -o+data_percent) is essential precisely because the advertised per-volume sizes no longer tell you how much real room is left, and by the time df on an individual thin volume shows a problem, the underlying pool may already be critically full for every volume drawing from it simultaneously.
Related:
- How to Set Up Full-Disk Encryption on Linux with LUKS
- Fixing ‘Disk Full’ on Linux When df Shows Space Available
Sources: