Skip to content

Logical Volume Management (LVM)

LVM (Logical Volume Management) is a storage abstraction layer built into the Linux kernel (via the device mapper framework). Instead of working directly with fixed partitions, LVM lets you:

  • Pool multiple physical drives/partitions into a single storage group
  • Carve flexible logical volumes from that pool - resized, moved, or snapshotted while online
  • Name volumes meaningfully: databases, backups, www

The current implementation is LVM2, which is what all modern Linux distributions use.

ProblemLVM Solution
”Disk is full, but I can’t resize the partition”Add a new disk to the volume group and extend the LV online
”I need to take a snapshot before upgrading”LVM snapshots are instant and space-efficient
”I want data spread across multiple disks”LVM striping (like RAID 0)
“I need redundancy”LVM mirroring
”I need to migrate data off a failing disk”pvmove migrates data live without downtime

LVM layers abstractions on top of physical storage:

Physical Disks / Partitions
|
Physical Volumes (PV) - Raw storage marked for LVM use
|
Volume Group (VG) - Pool combining one or more PVs
|
Logical Volumes (LV) - Flexible "virtual partitions" carved from VG
|
Filesystem (ext4, xfs) - Formatted and mounted like any partition
LayerCommand prefixDescription
Physical Volume (PV)pv...A disk, partition, or RAID array marked for LVM. LVM writes a PV header to claim it.
Volume Group (VG)vg...A pool combining one or more PVs. Presents unified storage.
Logical Volume (LV)lv...A slice of a VG. Acts like a partition - you format and mount it.

Each volume is carved into small, fixed-size chunks called extents:

  • Physical extents (PE) on PVs
  • Logical extents (LE) on LVs
  • All volumes in a VG share the same extent size (default: 4 MB)

An LV is simply a mapping from logical extents to physical extents. This mapping can be:

  • Linear: extents in sequence (default)
  • Striped: extents alternating across multiple PVs (performance)
  • Mirrored: extents duplicated across PVs (redundancy)

Because extents are the unit of allocation, LVM can expand, shrink, or move an LV simply by adjusting these mappings - even while the LV is mounted.


Terminal window
# Scan for available block devices LVM can use
sudo lvmdiskscan
# Mark devices as physical volumes
sudo pvcreate /dev/sda /dev/sdb
# Check PV status
sudo pvs # brief summary
sudo pvdisplay # detailed info
sudo pvdisplay /dev/sda # specific PV
PV VG Fmt Attr PSize PFree
/dev/sda lvm2 --- 200.00g 200.00g
/dev/sdb lvm2 --- 100.00g 100.00g
Terminal window
# Create VG named LVMVolGroup from both PVs
sudo vgcreate LVMVolGroup /dev/sda /dev/sdb
# View VG status
sudo vgs # brief
sudo vgdisplay # detailed
sudo vgdisplay LVMVolGroup
# Add a new PV to an existing VG later
sudo vgextend LVMVolGroup /dev/sdc
# Remove a PV from a VG (must evacuate first)
sudo pvmove /dev/sda # move all data off /dev/sda
sudo vgreduce LVMVolGroup /dev/sda

Unlike partitions, you don’t need to know disk layout - LVM handles placement.

Terminal window
# Create LVs with fixed size (-L) and name (-n)
sudo lvcreate -L 10G -n projects LVMVolGroup
sudo lvcreate -L 5G -n www LVMVolGroup
sudo lvcreate -L 20G -n db LVMVolGroup
# Allocate remaining free space
sudo lvcreate -l 100%FREE -n workspace LVMVolGroup
# View LV status
sudo lvs # brief
sudo lvdisplay # detailed
sudo vgs -o +lv_size,lv_name # VG view with LV details
LV VG Attr LSize
projects LVMVolGroup -wi-a----- 10.00g
www LVMVolGroup -wi-a----- 5.00g
db LVMVolGroup -wi-a----- 20.00g
workspace LVMVolGroup -wi-a----- 264.99g

LV device paths:

  • /dev/LVMVolGroup/projects
  • /dev/mapper/LVMVolGroup-projects (same device, two paths)
Terminal window
# Format
sudo mkfs.ext4 /dev/LVMVolGroup/projects
sudo mkfs.xfs /dev/LVMVolGroup/db # XFS is a good choice for databases
# Create mount points and mount
sudo mkdir -p /mnt/{projects,www,db,workspace}
sudo mount /dev/LVMVolGroup/projects /mnt/projects
sudo mount /dev/LVMVolGroup/www /mnt/www
sudo mount /dev/LVMVolGroup/db /mnt/db
sudo mount /dev/LVMVolGroup/workspace /mnt/workspace
/dev/LVMVolGroup/projects /mnt/projects ext4 defaults,nofail 0 2
/dev/LVMVolGroup/www /mnt/www ext4 defaults,nofail 0 2
/dev/LVMVolGroup/db /mnt/db xfs defaults,nofail 0 2
/dev/LVMVolGroup/workspace /mnt/workspace ext4 defaults,nofail 0 2

This is one of LVM’s most powerful features - you can grow a volume while it is mounted and in use.

Terminal window
# 1. Extend the LV
sudo lvextend -L +10G /dev/LVMVolGroup/projects # add 10G
sudo lvextend -L 50G /dev/LVMVolGroup/projects # set absolute size to 50G
sudo lvextend -l +100%FREE /dev/LVMVolGroup/projects # use all free space
# 2. Resize the filesystem (must be done separately)
sudo resize2fs /dev/LVMVolGroup/projects # ext4 (online resize OK)
sudo xfs_growfs /mnt/db # XFS (must be mounted)
# Or do both in one step (-r extends filesystem automatically)
sudo lvextend -r -L +10G /dev/LVMVolGroup/projects
Terminal window
# 1. Unmount
sudo umount /mnt/projects
# 2. Check filesystem
sudo e2fsck -f /dev/LVMVolGroup/projects
# 3. Shrink filesystem FIRST (leave some buffer)
sudo resize2fs /dev/LVMVolGroup/projects 8G
# 4. Then shrink the LV
sudo lvreduce -L 8G /dev/LVMVolGroup/projects
# 5. Remount
sudo mount /dev/LVMVolGroup/projects /mnt/projects

Always shrink the filesystem before shrinking the LV. Shrink the LV before removing space from the VG.


A snapshot creates an instant point-in-time copy of an LV. Under the hood, LVM uses Copy-on-Write (CoW): the snapshot initially shares all data blocks with the origin. When blocks are modified in the origin, LVM copies the original version to the snapshot before overwriting.

Terminal window
# Create a 5G snapshot of the 'db' LV
sudo lvcreate -s -L 5G -n db_snapshot /dev/LVMVolGroup/db
# Mount the snapshot (read-only for backups is safest)
sudo mount -o ro /dev/LVMVolGroup/db_snapshot /mnt/db_snapshot
# Take a backup from the snapshot (database is still running normally)
sudo tar -czf /backup/db_$(date +%Y%m%d).tar.gz /mnt/db_snapshot
# After backup, unmount and remove snapshot
sudo umount /mnt/db_snapshot
sudo lvremove /dev/LVMVolGroup/db_snapshot

Terminal window
# Move data from one PV to another (online, no downtime)
sudo pvmove /dev/sda # move all from sda to other PVs in VG
sudo pvmove /dev/sda /dev/sdc # move sda data specifically to sdc
# Rename a VG
sudo vgrename OldName NewName
# Rename an LV
sudo lvrename LVMVolGroup old-lv new-lv
# Remove an LV (must be unmounted)
sudo umount /mnt/projects
sudo lvremove /dev/LVMVolGroup/projects
# Remove a VG (all LVs must be removed first)
sudo vgremove LVMVolGroup
# Remove PV label (must be out of all VGs first)
sudo pvremove /dev/sda

CategoryCommandDescription
PVpvcreate /dev/sdXInitialize PV
pvsBrief PV list
pvdisplayDetailed PV info
pvmove /dev/sdXMigrate data off a PV
VGvgcreate name /dev/sdXCreate VG
vgsBrief VG list
vgdisplayDetailed VG info
vgextend name /dev/sdXAdd PV to VG
vgreduce name /dev/sdXRemove PV from VG
LVlvcreate -L size -n name VGCreate LV
lvsBrief LV list
lvdisplayDetailed LV info
lvextend -r -L +size /dev/VG/LVGrow LV + filesystem
lvreduce -L size /dev/VG/LVShrink LV (unmount first!)
lvcreate -s -L size -n snap /dev/VG/LVCreate snapshot
lvremove /dev/VG/LVDelete LV
ScanlvmdiskscanFind available block devices
lvs -aList all LVs including internal