LVM Fundamentals: Physical Volumes, Volume Groups, and Logical Volumes¶
LVM (Logical Volume Manager) decouples "how big is this filesystem" from "which physical disk is it on." It's the reason you can grow a filesystem on a production server without taking it offline, add a new disk and extend an existing volume across it, or take an atomic snapshot before a risky upgrade.
About the examples on this page
The commands below are accurate LVM syntax and are safe to run on a spare disk or a throwaway virtual machine — follow the practical exercise using a loopback file, not your production root disk. No output on this page is from running these commands against this wiki's own infrastructure.
How it works¶
LVM has three layers:
Physical Volume (PV) → Volume Group (VG) → Logical Volume (LV)
(a real disk/ (a pool combining (a resizable "virtual
partition) one or more PVs) partition" carved
from the VG)
A filesystem (ext4, XFS, etc.) is created on top of a Logical Volume, exactly as it would be on top of a raw partition — LVM is a layer underneath the filesystem, not a replacement for one.
Creating the stack¶
# Turn a raw block device into a Physical Volume
sudo pvcreate /dev/sdb
# Combine it into a Volume Group named "data"
sudo vgcreate data /dev/sdb
# Carve out a 20G Logical Volume from that group
sudo lvcreate -n app_lv -L 20G data
# Put a filesystem on it
sudo mkfs.ext4 /dev/data/app_lv
# Mount it
sudo mkdir -p /mnt/app
sudo mount /dev/data/app_lv /mnt/app
pvcreate writes an LVM label and metadata to the device — this is destructive to whatever was on it before. vgcreate <name> <device(s)> can take multiple PVs at once, pooling their capacity. -L 20G requests a fixed size; -l 100%FREE instead allocates every remaining byte in the VG.
Extending a Logical Volume online¶
This is LVM's headline feature — growing a filesystem without unmounting it:
sudo lvextend -L +10G /dev/data/app_lv
sudo resize2fs /dev/data/app_lv # ext4; use `xfs_growfs /mnt/app` for XFS
lvextend grows the block device; the filesystem itself still thinks it's the old size until you run the filesystem-specific grow command (resize2fs for ext2/3/4, xfs_growfs for XFS — note XFS can only grow, never shrink, while ext4 can do both offline).
Checking what you have¶
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 40G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 39G 0 part
└─ubuntu--vg-root 253:0 0 39G 0 lvm /
sdb 8:16 0 50G 0 disk
└─data-app_lv 253:1 0 30G 0 lvm /mnt/app
lsblk shows the full stack in one view: physical disks (sda, sdb), partitions, and the LVM logical volumes layered on top (indented, prefixed with the VG name).
Snapshots¶
A snapshot is a point-in-time, read-writable copy that only stores differences from the original (copy-on-write). Useful before a schema migration or risky upgrade — if it goes wrong, lvconvert --merge rolls the original back to the snapshot's state. The -L 2G here is the snapshot's own space for storing changed blocks, not the size of the data being snapshotted — if more than 2G worth of blocks change before you remove the snapshot, it overflows and becomes unusable, so size it generously relative to expected write volume during its lifetime.
Software RAID with mdadm (an alternative/complement to LVM)¶
LVM itself is not redundancy — a PV failing takes its VG down with it unless the underlying device is itself redundant. mdadm builds Linux software RAID arrays, which can then be used as a PV:
sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdc /dev/sdd
sudo pvcreate /dev/md0
sudo vgcreate data /dev/md0
--level=1 is mirroring (every write goes to both disks); --level=5 is parity-based striping needing at least 3 disks, trading some capacity for the ability to survive one disk failure. Check array health with cat /proc/mdstat or mdadm --detail /dev/md0.
After creating an array, record it so it assembles at boot: sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf, then sudo update-initramfs -u (Debian/Ubuntu; RHEL-family uses /etc/mdadm.conf and sudo dracut --force). RAID is availability, not backup — it faithfully mirrors an accidental rm to every disk.
Ubuntu/Debian vs. RHEL-family differences¶
LVM commands and behavior are identical — it's the same upstream lvm2 package on both. The main practical difference is installer defaults: RHEL-family installers put the root filesystem on LVM out of the box (visible as rhel-root style VG/LV names), and so does Ubuntu Server's guided install (ubuntu-vg). Debian's guided partitioning defaults to plain partitions unless you pick an LVM layout.
Practical exercise¶
Use loopback files instead of real disks — completely safe, no real hardware involved:
sudo dd if=/dev/zero of=/tmp/disk1.img bs=1M count=512
sudo losetup -fP /tmp/disk1.img
losetup -a # note which /dev/loopN was assigned
sudo pvcreate /dev/loopN
sudo vgcreate test_vg /dev/loopN
sudo lvcreate -n test_lv -L 200M test_vg
sudo mkfs.ext4 /dev/test_vg/test_lv
When you are done, tear the lab down in reverse order (replace /dev/loopN with the device from losetup -a):
sudo lvremove test_vg/test_lv
sudo vgremove test_vg
sudo pvremove /dev/loopN
sudo losetup -d /dev/loopN
rm /tmp/disk1.img
How to verify you did it correctly¶
sudo vgsshould listtest_vgwithVSizeclose to 512M andVFreereduced by roughly 200M.sudo lvsshould listtest_lvwithLSizeof200.00m.lsblkshould show the loop device with the LV nested under it.
Common mistakes¶
- Forgetting the filesystem-level resize after
lvextend— the block device grows,df -hstill shows the old size, because the filesystem metadata itself wasn't told. - Undersizing a snapshot's own space, causing it to silently become
Invalidonce enough blocks change — always checklvsfor the snapshot'sData%usage, not just that it was created. - Running
vgextend/pvcreateagainst the wrong device.pvcreatehappily wipes an existing filesystem's superblock with no interactive confirmation by default — alwayslsblkand triple-check the device name first.
⚠ Dangerous commands¶
pvcreate/vgcreate/mkfs.*against a device that's actually in use (a mounted filesystem, the wrong loop device, a disk you meant to leave alone) destroys the data on it with no undo. Always confirm withlsblkandmountfirst.lvremovedeletes a logical volume and everything on it immediately — there's a-y/force flag that skips even the interactive "are you sure" prompt; never script that flag against anything you haven't double-checked.mdadm --createon devices that already contain data from a previous array will usually prompt about existing superblocks — don't dismiss that prompt without reading it; it's often the only warning you get before silently reassembling the wrong array.
Related articles¶
Review questions¶
- What is the actual relationship between a Physical Volume, a Volume Group, and a Logical Volume?
- Why does growing a Logical Volume with
lvextendnot automatically grow the filesystem on it? - What's the practical difference between RAID 1 and RAID 5 in terms of capacity and fault tolerance?
- What happens to an LVM snapshot if the amount of changed data exceeds the space you allocated for it?