Back to Cheatsheets
Cheatsheet

LVM Storage Management Cheatsheet

A practical reference for Linux Logical Volume Manager (LVM) covering PV → VG → LV layers.

LVM Architecture

# Disk → Partition → PV → VG → LV → mkfs → mount
# PE (Physical Extent): smallest allocatable unit (default 4 MiB)
 
# Device paths:
/dev/mapper/vg-name-lv-name              # Device mapper path
/dev/vg-name/lv-name                     # Alternative symlink
 
# Config:
/etc/lvm/lvm.conf                         # LVM configuration
/etc/lvm/archive/                         # Auto metadata archives
/etc/lvm/backup/                          # Manual metadata backups

Physical Volume (PV)

Create

pvcreate /dev/sdb                        # PV on whole disk
pvcreate /dev/sdc1                       # PV on partition
pvcreate /dev/sdd /dev/sde               # Multiple at once
pvcreate --dataalignment 1M /dev/sdf     # Align for 4K sectors

Display & Scan

pvdisplay                                # Detailed PV info
pvdisplay -m                             # Show PE allocation
pvs                                      # Compact summary
pvs -o pv_name,pv_size,pv_free --units g # Custom columns
pvscan                                   # Scan for PVs

Remove

pvremove /dev/sdb                        # Remove PV label
pvremove -ff /dev/sdb                    # Force removal

Volume Group (VG)

Create & Extend

vgcreate vg_data /dev/sdb                # Create VG
vgcreate -s 16M vg_data /dev/sdd         # Custom PE size
vgextend vg_data /dev/sdc                # Add PV to VG
vgextend vg_data /dev/sdd /dev/sde      # Add multiple PVs

Display & Reduce

vgdisplay vg_data                        # Detailed VG info
vgs                                      # Compact summary
vgs -o vg_name,vg_size,vg_free           # Custom columns
vgscan                                   # Scan for VGs
vgreduce vg_data /dev/sdc                # Remove PV from VG
vgreduce --removemissing vg_data         # Remove missing PVs

Activate & Rename

vgchange -a y vg_data                    # Activate all LVs
vgchange -a n vg_data                    # Deactivate all LVs
vgrename vg_data vg_prod                # Rename VG
vgremove vg_data                         # Remove VG (no LVs)

Backup

vgcfgbackup vg_data                      # Backup metadata
vgcfgbackup -f /tmp/vg.bak vg_data       # Save to file
vgcfgrestore vg_data -f /tmp/vg.bak      # Restore from file

Logical Volume (LV)

Create

lvcreate -L 100G -n lv_data vg_data      # 100GB LV
lvcreate -l 100%FREE -n lv_home vg_data  # All remaining space
lvcreate -l 50%VG -n lv_apps vg_data     # 50% of VG
lvcreate -L 50G -n lv_fast vg_data /dev/sdd  # Specific PV

Display

lvdisplay vg_data/lv_data               # Detailed LV info
lvs                                      # Compact summary
lvs -a                                   # Show all (incl. internal)
lvs -o lv_name,lv_size,lv_attr           # Custom columns
lvscan                                   # Scan for LVs

Extend & Reduce

lvextend -L +50G vg_data/lv_data         # Grow by 50GB
lvextend -L 200G vg_data/lv_data         # Grow to 200GB
lvextend -l +100%FREE vg_data/lv_data    # Fill VG
lvextend -r vg_data/lv_data              # Extend + resize fs
 
# Shrink: fs first, then LV
lvreduce -L -20G vg_data/lv_data         # Shrink by 20GB
lvreduce --fsck -r -L -10G vg_data/lv_data  # Check + shrink

Resize (Grow/Shrink)

lvresize -L +50G vg_data/lv_data         # Grow
lvresize -L 150G vg_data/lv_data         # Exact size
lvresize -r -L -20G vg_data/lv_data      # Shrink with fs

Remove & Rename

lvremove vg_data/lv_data                 # Remove LV
lvremove -f vg_data/lv_data              # Force
lvrename vg_data lv_data lv_storage     # Rename
lvchange -a y vg_data/lv_data            # Activate
lvchange -a n vg_data/lv_data            # Deactivate

Filesystem Resize

XFS (grow only)

lvextend -L +50G vg_data/lv_data         # 1. Extend LV
xfs_growfs /mount/point                  # 2. Grow XFS to fill

ext4 (grow and shrink)

# Grow:
lvextend -L +50G vg_data/lv_data         # 1. Extend LV
resize2fs /dev/vg_data/lv_data           # 2. Grow filesystem
 
# Shrink:
e2fsck -f /dev/vg_data/lv_data           # 1. Force fsck
resize2fs /dev/vg_data/lv_data 80G       # 2. Shrink fs to 80G
lvreduce -L 80G vg_data/lv_data          # 3. Reduce LV

Snapshots

Create Snapshot

lvcreate -L 10G -s -n lv_root_snap /dev/vg_data/lv_root
# -L = COW storage size (estimate changes × duration)
# Too small = snapshot invalidates (100% used)

Monitor & Extend

lvs -a -o lv_name,lv_size,origin,snap_percent
# snap_percent = COW space used (100% = invalid)
lvextend -L +5G vg_data/lv_root_snap     # Extend COW storage

Merge & Remove

lvconvert --merge vg_data/lv_root_snap   # Restore to original
# Merge completes when LV is deactivated next
lvremove vg_data/lv_root_snap            # Delete snapshot

Thin Snapshots

# Require thin pool — instant and space-efficient
lvcreate -s -n thin_snap vg_data/lv_thin_vol
# No -L needed — shares data blocks

Thin Provisioning

Create Thin Pool

lvcreate -L 500G --thinpool vg_data/thinpool       # Auto metadata
lvcreate --size 5G --thinpool vg_data/thinpool     # Custom metadata

Create Thin Volumes

lvcreate -V 50G --thin -n lv_thin_vol vg_data/thinpool  # 50GB virtual
lvcreate -V 100%FREE --thin -n lv_max vg_data/thinpool

Monitor & Auto-extend

lvs -a -o lv_name,data_percent,metadata_percent
# data_percent = pool usage, metadata_percent = metadata usage
 
# Auto-extend in /etc/lvm/lvm.conf:
thin_pool_autoextend_threshold = 80      # % full to trigger
thin_pool_autoextend_percent = 20        # % to extend by

Discard

mount -o discard /dev/vg_data/lv_thin_vol /mnt  # Online discard
fstrim -v /mnt                            # Manual discard

Caching

Setup Cache (SSD + HDD)

# One-liner: create cache pool and attach
lvcreate -L 50G -n lv_cache_pool vg_ssd
lvconvert --type cache --cachepool vg_ssd/lv_cache_pool \
  vg_hdd/lv_slow_data

Cache Modes

lvchange --cachemode writeback vg_hdd/lv_slow_data   # Fast, risk on crash
lvchange --cachemode writethrough vg_hdd/lv_slow_data # Safe, slower writes

Monitor & Detach

lvs -a -o+cache_read_hits,cache_read_misses
dmsetup status vg_hdd-lv_slow_data-cache
lvconvert --splitcache vg_hdd/lv_slow_data  # Detach cache

Striping & RAID

Striped (RAID 0)

lvcreate -L 100G -i 2 -I 64 -n lv_striped vg_data
# -i 2 = 2 stripes (2+ PVs), -I 64 = 64KB stripe size

RAID 1 (Mirror)

lvcreate -L 100G -m1 -n lv_mirror vg_data    # 1 mirror = 2 copies
lvcreate -L 100G -m2 -n lv_mirror2 vg_data   # 2 mirrors = 3 copies

RAID 5/6/10

lvcreate -L 200G --type raid5 -i 3 -n lv_raid5 vg_data   # 3+ PVs
lvcreate -L 200G --type raid6 -i 4 -n lv_raid6 vg_data   # 4+ PVs
lvcreate -L 200G --type raid10 -i 2 -n lv_raid10 vg_data # 4+ PVs

Monitor & Repair

lvs -a -o lv_name,lv_health_status,raid_sync_action
# health_status: healthy / partial / failed
 
# Replace failed disk:
pvcreate /dev/sdf && vgextend vg_data /dev/sdf
lvconvert --repair vg_data/lv_raid5
vgreduce vg_data /dev/sdc                  # Remove failed PV

LVM Tags & Automation

pvchange --addtag ssd /dev/sdb            # Tag PV
vgchange --addtag production vg_data      # Tag VG
lvchange --addtag critical vg_data/lv_db  # Tag LV
 
systemctl enable lvm2-monitor              # Auto-activate LVs
# Configure: /etc/lvm/lvm.conf → auto_activation_volume_list

pvmove (Online Migration)

pvmove /dev/sdb                           # Move all data off PV
pvmove /dev/sdb /dev/sde                  # To specific target
pvmove -n vg_data/lv_data /dev/sdb        # Move only one LV
pvmove -b /dev/sdb                        # Background mode
pvmove -i 5 /dev/sdb                      # Report every 5 sec
pvmove --abort                            # Cancel migration

Troubleshooting

Full VG

vgs vg_data                               # Check free space
# Solutions:
pvcreate /dev/sdf && vgextend vg_data /dev/sdf   # Add PV
lvextend -L +100G vg_data/thinpool_tdata         # Extend pool
lvremove vg_data/old_snap                         # Remove snapshots

Missing PV / Failed Disk

vgs -o+missing_pv_count                    # Check missing PVs
vgreduce --removemissing vg_data           # Remove missing PV
# Partial recovery:
vgchange -a y --activationmode partial vg_data

Recover with pvck & vgcfgrestore

pvck /dev/sdb                             # Scan for metadata
# Restore from backup:
vgcfgrestore --list vg_data               # List available backups
vgcfgrestore vg_data -f /etc/lvm/archive/vg_data_000123.vg

Metadata Corruption

vgscan --cache                            # Refresh cache
vgck vg_data                              # Check VG metadata
vgcfgrestore vg_data                      # Restore latest backup
vgscan --mknodes                          # Recreate device nodes

Thin Pool Overflow

lvextend -L +50G vg_data/thinpool_tdata   # Extend data
lvextend -L +1G vg_data/thinpool_tmeta    # Extend metadata
systemctl enable lvm2-monitor             # Enable auto-extend

Split Brain (Duplicate VG Names)

vgs -o+vg_uuid                            # Show UUIDs
vgrename VDpp5C-XXXX-XXXX vg_imported     # Rename by UUID