The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Inventory physical volumes | sudo pvs -o \
pv_name,pv_uuid,vg_name,pv_size,pv_free,pv_attr,dev_size | View examples |
| Inventory volume groups | sudo vgs -o \
vg_name,vg_uuid,vg_size,vg_free,pv_count,lv_count,vg_attr | View examples |
| Inventory logical volumes | sudo lvs -a -o \
lv_full_name,lv_size,segtype,lv_attr,origin,pool_lv,data_percent,metadata_percent,devices | View examples |
| Export a structured report | sudo lvm fullreport --reportformat json_std | View examples |
| Initialize a physical volume | sudo pvcreate /dev/disk/by-id/wwn-0x5000c50012345678 | View examples |
| Create a volume group | sudo vgcreate vgdata \
/dev/disk/by-id/wwn-0x5000c50012345678 | View examples |
| Create a linear LV | sudo lvcreate --name app --size 100G vgdata | View examples |
| Extend an LV and filesystem | sudo lvextend --resizefs --size +20G /dev/vgdata/app | View examples |
| Consume remaining VG space | sudo lvextend --resizefs --extents +100%FREE \
/dev/vgdata/app | View examples |
| Grow a mounted XFS filesystem | sudo xfs_growfs /srv/app | View examples |
| Test an LV reduction plan | sudo lvreduce --test --size 80G /dev/vgdata/archive | View examples |
| Reduce an LV after its filesystem | sudo lvreduce --size 80G /dev/vgdata/archive | View examples |
| Create a thin pool | sudo lvcreate --type thin-pool --name pool0 --size 500G \
vgdata | View examples |
| Create a thin LV | sudo lvcreate --type thin --name tenant1 --virtualsize \
2T --thinpool vgdata/pool0 | View examples |
| Monitor thin-pool utilization | sudo lvs -o \
lv_full_name,segtype,lv_size,data_percent,metadata_percent,pool_lv,discards | View examples |
| Extend thin-pool data | sudo lvextend --size +100G vgdata/pool0 | View examples |
| Extend thin-pool metadata | sudo lvextend --poolmetadatasize +1G vgdata/pool0 | View examples |
| Create a COW snapshot | sudo lvcreate --snapshot --name app-prechange --size 20G \
/dev/vgdata/app | View examples |
| Monitor snapshot consumption | sudo lvs -o \
lv_full_name,origin,lv_size,data_percent,lv_attr | View examples |
| Merge a snapshot | sudo lvconvert --merge /dev/vgdata/app-prechange | View examples |
| Move extents between PVs | sudo pvmove /dev/disk/by-id/wwn-0x5000c50011111111 \
/dev/disk/by-id/wwn-0x5000c50022222222 | View examples |
| Remove an empty PV from a VG | sudo vgreduce vgdata \
/dev/disk/by-id/wwn-0x5000c50011111111 | View examples |
| Tag a logical volume | sudo lvchange --addtag production vgdata/app | View examples |
| Select LVs by tag | sudo lvs -o lv_full_name,lv_tags -S 'tags={production}' | View examples |
| Activate one LV | sudo lvchange --activate y vgdata/app | View examples |
| Deactivate one LV | sudo lvchange --activate n vgdata/app | View examples |
| Disable LV autoactivation | sudo lvchange --setautoactivation n vgdata/app | View examples |
| Back up VG metadata | sudo vgcfgbackup --file /var/backups/lvm/vgdata.conf \
vgdata | View examples |
| List metadata archives | sudo vgcfgrestore --list vgdata | View examples |
| Test metadata restoration | sudo vgcfgrestore --test --file \
/var/backups/lvm/vgdata.conf vgdata | View examples |
| List the LVM devices file | sudo lvmdevices | View examples |
| Check device-file entries | sudo lvmdevices --check | View examples |
| Set thin-pool discard mode | sudo lvchange --discards nopassdown vgdata/pool0 | View examples |
| Report VG ownership and locking | sudo vgs -o \
vg_name,vg_uuid,vg_attr,vg_systemid,vg_locktype | View examples |
| Start shared-VG locking | sudo vgchange --lockstart vgshared | View examples |
LVM separates physical devices, allocation pools, and virtual block devices into PV, VG, and LV layers. That flexibility also makes an incorrect target or resize permanently destructive. Resolve stable device identities, capture current reports and VG metadata, verify backups, and coordinate every LV change with its filesystem or application. Never paste create, reduce, remove, restore, snapshot-merge, or migration commands until the exact devices and recovery plan have been independently reviewed.
Step by step
Detailed examples
Inventory every LVM layer before changing one
PVs are initialized block devices, VGs pool their physical extents, and LVs map selected extents into virtual block devices. Collect UUIDs, sizes, free space, attributes, segment types, origins, pools, and backing devices together. Use explicit report columns because defaults evolve, include hidden LVs with -a, and correlate the result with lsblk, findmnt, and stable /dev/disk/by-id identities. The /dev/VG/LV path is the supported path for scripts; encoded /dev/mapper names are an implementation detail.
sudo pvs -o pv_name,pv_uuid,vg_name,pv_size,pv_free,pv_attr,dev_size
sudo vgs -o vg_name,vg_uuid,vg_size,vg_free,pv_count,lv_count,vg_attr
sudo lvs -a -o lv_full_name,lv_size,segtype,lv_attr,origin,pool_lv,data_percent,metadata_percent,devices
lsblk -o NAME,PATH,TYPE,SIZE,FSTYPE,UUID,MOUNTPOINTS
findmnt --real --output TARGET,SOURCE,FSTYPE,OPTIONS sudo lvm fullreport --reportformat json_std Create PV, VG, and LV layers only from verified devices
pvcreate writes an LVM label and metadata areas, so a wrong path can make existing data inaccessible. Resolve the intended serial or WWID, compare capacity and topology against infrastructure records, use wipefs only in no-act mode during inspection, and verify that the device is not mounted, held by multipath, RAID, encryption, or another VG. Avoid -ff and unattended confirmation flags: they bypass protections. Decide metadata size and data alignment at PV creation because some layout properties cannot be enlarged later.
device=/dev/disk/by-id/wwn-0x5000c50012345678
readlink --canonicalize "$device"
lsblk -o NAME,PATH,TYPE,SIZE,FSTYPE,UUID,MOUNTPOINTS "$device"
sudo wipefs --no-act "$device"
sudo pvs --all -o pv_name,pv_uuid,vg_name "$device" sudo pvcreate /dev/disk/by-id/wwn-0x5000c50012345678
sudo vgcreate vgdata /dev/disk/by-id/wwn-0x5000c50012345678
sudo lvcreate --name app --size 100G vgdata
sudo lvs -o lv_full_name,lv_size,segtype,devices vgdata Note: These commands write storage metadata. Run them only after independent target verification and a tested recovery plan.
Grow the block device before growing the filesystem
Confirm VG free space, the LV segment type, the filesystem, and its supported growth method. lvextend --resizefs delegates filesystem handling to fsadm and is convenient only when that stack supports the filesystem and mount state. An explicit workflow makes boundaries visible: extend the LV, confirm the new block-device size, then grow ext4 with resize2fs or mounted XFS with xfs_growfs using its mount point. Growth is usually online but remains a change requiring backup, capacity, and failure planning.
findmnt --target /srv/app --output TARGET,SOURCE,FSTYPE,OPTIONS
sudo vgs vgdata -o vg_name,vg_free
sudo lvextend --size +20G /dev/vgdata/app
sudo resize2fs /dev/vgdata/app
findmnt --target /srv/app --output TARGET,SOURCE,FSTYPE,SIZE,USED,AVAIL findmnt --target /srv/app --output TARGET,SOURCE,FSTYPE,OPTIONS
sudo vgs vgdata -o vg_name,vg_free
sudo lvextend --size +20G /dev/vgdata/app
sudo xfs_growfs /srv/app
xfs_info /srv/app Shrink the filesystem first, and never shrink XFS
Reducing an LV removes trailing extents immediately; LVM cannot know whether a filesystem still owns blocks there. XFS has no shrink operation, so migrate its data to a smaller filesystem instead. For a shrink-capable filesystem such as ext4, take and test a backup, stop writers, unmount, run its mandatory check, shrink the filesystem below the intended LV boundary, then reduce the LV. Recheck and expand the filesystem to the new device boundary afterward. --test exercises LVM metadata logic only and is not evidence that data fits.
findmnt --source /dev/vgdata/archive --output TARGET,SOURCE,FSTYPE,OPTIONS
sudo lvs /dev/vgdata/archive -o lv_full_name,lv_size,segtype,lv_attr
sudo lvreduce --test --size 80G /dev/vgdata/archive sudo umount /srv/archive
sudo e2fsck -f /dev/vgdata/archive
sudo resize2fs /dev/vgdata/archive 78G
sudo lvreduce --size 80G /dev/vgdata/archive
sudo resize2fs /dev/vgdata/archive
sudo e2fsck -f /dev/vgdata/archive
sudo mount /srv/archive Note: This permanently discards LV extents. Substitute sizes only from a reviewed runbook, and restore rather than improvise if any step fails.
Treat thin-pool data and metadata as separate exhaustion risks
A thin LV advertises virtual capacity while physical chunks are allocated from its pool as written. Virtual sizes may exceed the pool, so filesystem free space is not physical headroom. Monitor data_percent and metadata_percent, preserve VG extents for emergency extension, enable dmeventd monitoring, and alert well before either approaches exhaustion. Configure tested thin_pool_autoextend thresholds and ensure dmeventd can see every required device. Redundant, fast metadata storage and the automatically maintained pool metadata spare reduce—but do not remove—recovery risk.
sudo lvcreate --type thin-pool --name pool0 --size 500G vgdata
sudo lvcreate --type thin --name tenant1 --virtualsize 2T --thinpool vgdata/pool0
sudo lvchange --monitor y vgdata/pool0
sudo lvs -o lv_full_name,segtype,lv_size,data_percent,metadata_percent,pool_lv,discards activation {
thin_pool_autoextend_threshold = 70
thin_pool_autoextend_percent = 20
} Note: Size the threshold and reserved VG space from measured growth, then test dmeventd behavior and alerting before production use.
Quiesce writers and budget snapshot change rate
An LVM snapshot is crash-consistent at the block layer, not automatically application-consistent. Ask the database or application to flush and pause writes; fsfreeze can bound filesystem writes but does not replace application-specific consistency controls. Classic COW snapshots require allocated exception space and become invalid if it fills, so monitor data_percent. A snapshot is not an independent backup. Merging rolls the origin back, destroys post-snapshot changes, and consumes the snapshot; if either LV is open, the merge can wait for a later activation when both are closed.
set -euo pipefail
frozen=0
unfreeze() {
if [ "$frozen" -eq 1 ]; then
sudo fsfreeze --unfreeze /srv/app
fi
}
trap unfreeze EXIT
sudo fsfreeze --freeze /srv/app
frozen=1
sudo lvcreate --snapshot --name app-prechange --size 20G /dev/vgdata/app
sudo fsfreeze --unfreeze /srv/app
frozen=0
trap - EXIT Note: Coordinate application-level quiescing separately and keep the freeze window short.
sudo lvs /dev/vgdata/app /dev/vgdata/app-prechange -o lv_full_name,origin,lv_size,data_percent,lv_attr
findmnt --source /dev/vgdata/app
sudo lvconvert --test --merge /dev/vgdata/app-prechange Note: A real merge discards all origin changes made after snapshot creation. Stop consumers and obtain explicit rollback approval first.
Move extents before retiring a physical volume
pvmove mirrors allocated extents to destination PVs and updates VG metadata as regions complete. Confirm destination capacity, allocation constraints, redundancy, health, and power-loss behavior; a move is not a backup. Track placement during the operation, allow polling to finish, and do not remove either device while it is active. Only after pv_used reaches zero should vgreduce detach the source. pvremove then erases its LVM label and must wait until the device is definitively outside the VG.
source_pv=/dev/disk/by-id/wwn-0x5000c50011111111
destination_pv=/dev/disk/by-id/wwn-0x5000c50022222222
sudo pvs -o pv_name,pv_uuid,vg_name,pv_size,pv_free,pv_used "$source_pv" "$destination_pv"
sudo pvmove "$source_pv" "$destination_pv"
sudo pvs -o pv_name,vg_name,pv_size,pv_free,pv_used "$source_pv" "$destination_pv" source_pv=/dev/disk/by-id/wwn-0x5000c50011111111
sudo pvs --select "pv_name=$source_pv" -o pv_name,vg_name,pv_used,pv_free
sudo vgreduce --test vgdata "$source_pv" Note: After confirming pv_used is zero, the real vgreduce is destructive metadata work and needs a fresh backup and approval.
Use tags and selections to describe scope, not to replace review
Tags live in LVM metadata and can group PVs, VGs, or LVs independently of their names. Report selection supports typed comparisons, Boolean expressions, regular expressions, and list containment. First display the rows selected by an expression, then use the identical expression for a modifying command. Tags can drift, commands using broad tags may touch many objects, and selection may require scanning all visible VGs, so automation still needs allowlists, audit output, and change limits.
sudo lvchange --addtag production vgdata/app
sudo lvs -o lv_full_name,lv_size,lv_tags -S 'tags={production}' sudo lvs -o lv_full_name,lv_size,lv_tags -S 'tags={production} && lv_size>=100g' Note: Never translate a report selection directly into a bulk modifying command without reviewing the complete selected set.
Separate visibility, activation, and safe application access
An active LV has a device-mapper mapping and /dev/VG/LV link; activation does not mount a filesystem or make concurrent access safe. Before deactivation, stop services, unmount filesystems, close encrypted mappings, and check for holders. Autoactivation is a distinct policy used during discovery and boot. Disabling it can prevent an LV appearing automatically but does not block an administrator from explicitly activating it. Partial or degraded activation is a recovery technique, not a routine way around missing devices.
findmnt --source /dev/vgdata/app
lsblk -o NAME,PATH,TYPE,FSTYPE,MOUNTPOINTS /dev/vgdata/app
sudo dmsetup ls --tree
sudo lvchange --test --activate n vgdata/app sudo lvs vgdata/app -o lv_full_name,lv_attr,lv_active,autoactivation
sudo lvchange --setautoactivation n vgdata/app
sudo lvs vgdata/app -o lv_full_name,lv_active,autoactivation Back up VG metadata outside the VG and restore only matching history
LVM automatically archives metadata around many changes, but copies under /etc/lvm are lost with the host and do not contain LV payload data. Export vgcfgbackup files to protected storage alongside inventory and filesystem backups. Before recovery, list versions and verify VG UUID, PV UUIDs, device identities, and the point in the change history. vgcfgrestore rewrites VG metadata and an incorrect version can make current layouts inaccessible. Thin-pool transaction state can diverge from VG metadata, so the tool warns that restoration involving thin pools may require force and specialist recovery.
sudo vgs vgdata -o vg_name,vg_uuid,vg_seqno,vg_attr
sudo pvs --select 'vg_name=vgdata' -o pv_name,pv_uuid,vg_name
sudo vgcfgbackup --file /var/backups/lvm/vgdata.conf vgdata
sudo vgcfgrestore --list vgdata sudo vgchange --activate n vgdata
sudo vgcfgrestore --test --file /var/backups/lvm/vgdata.conf vgdata Note: Deactivation is disruptive and the actual restore rewrites metadata. Validate payload backups and obtain expert review, especially for thin pools.
Constrain device discovery and choose discard propagation deliberately
Current LVM can use /etc/lvm/devices/system.devices as an allowlist managed by lvmdevices; do not edit its hashed contents by hand. With stable IDs, commands avoid devices outside the file. When the devices-file feature is disabled, LVM falls back to the lvm.conf regex filter; when it is enabled, normal commands ignore that filter. Thin-pool discard modes are independent: ignore keeps freed chunks allocated, nopassdown reclaims them only inside the pool, and passdown also forwards discards. Choose from security, device capability, latency, and storage-array guidance, then measure fstrim impact.
sudo lvmdevices
sudo lvmdevices --check
sudo lvmconfig --type current devices/use_devicesfile devices/filter sudo lvs vgdata/pool0 -o lv_full_name,segtype,discards
sudo lvchange --discards nopassdown vgdata/pool0
sudo lvs vgdata/pool0 -o lv_full_name,discards Note: Changing discard propagation affects performance and lower-layer behavior; validate it with the storage owner before deployment.
Shared storage requires lvmlockd and a cluster-safe upper layer
A shared VG is not made safe by exposing the same disks to multiple hosts. It requires lvmlockd plus sanlock or DLM, a tested fencing and recovery design, and the required startup sequence before VG modifications or LV activation. Exclusive activation is the default; shared activation is only for an application or filesystem explicitly designed for concurrent multi-host access. Thin, cache, RAID, mirror, and snapshot LVs cannot be concurrently activated in shared mode. pvmove also has shared-VG restrictions. Never bypass locking or force a lock-type conversion as routine remediation.
sudo lvm version
systemctl status lvmlockd --no-pager
sudo vgs -o vg_name,vg_uuid,vg_attr,vg_systemid,vg_locktype
sudo lvmlockctl --info sudo vgchange --lockstart vgshared
sudo vgs vgshared -o vg_name,vg_locktype,vg_attr
sudo lvs vgshared -o lv_full_name,lv_attr,segtype Note: Run this only after the external lock manager, fencing, host membership, and storage visibility have been validated.
Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
- LVM2 Projectlvm(8) — LVM tools and object modelman7.org
- LVM2 Projectlvcreate(8) — create logical volumesman7.org
- LVM2 Projectlvreduce(8) — reduce logical volume sizeman7.org
- LVM2 Projectlvconvert(8) — convert and merge logical volumesman7.org
- LVM2 Projectlvmthin(7) — LVM thin provisioningman7.org
- LVM2 Projectpvmove(8) — move physical extentsman7.org
- LVM2 Projectlvmreport(7) — reporting and selectionman7.org
- LVM2 Projectlvmdevices(8) — manage the devices fileman7.org
- LVM2 Projectvgcfgrestore(8) — restore volume group metadataman7.org
- LVM2 Projectlvmlockd(8) — shared LVM lockingman7.org
Help us improve
Found a typo or missing example?
Tell us what would make this cheat sheet clearer, more complete, or more useful.



