The essentials

Quick reference

One focused task per row. Jump to the related section for complete, working examples.

UseSyntaxExamples
Inventory physical volumessudo pvs -o \ pv_name,pv_uuid,vg_name,pv_size,pv_free,pv_attr,dev_sizeView examples
Inventory volume groupssudo vgs -o \ vg_name,vg_uuid,vg_size,vg_free,pv_count,lv_count,vg_attrView examples
Inventory logical volumessudo lvs -a -o \ lv_full_name,lv_size,segtype,lv_attr,origin,pool_lv,data_percent,metadata_percent,devicesView examples
Export a structured reportsudo lvm fullreport --reportformat json_stdView examples
Initialize a physical volumesudo pvcreate /dev/disk/by-id/wwn-0x5000c50012345678View examples
Create a volume groupsudo vgcreate vgdata \ /dev/disk/by-id/wwn-0x5000c50012345678View examples
Create a linear LVsudo lvcreate --name app --size 100G vgdataView examples
Extend an LV and filesystemsudo lvextend --resizefs --size +20G /dev/vgdata/appView examples
Consume remaining VG spacesudo lvextend --resizefs --extents +100%FREE \ /dev/vgdata/appView examples
Grow a mounted XFS filesystemsudo xfs_growfs /srv/appView examples
Test an LV reduction plansudo lvreduce --test --size 80G /dev/vgdata/archiveView examples
Reduce an LV after its filesystemsudo lvreduce --size 80G /dev/vgdata/archiveView examples
Create a thin poolsudo lvcreate --type thin-pool --name pool0 --size 500G \ vgdataView examples
Create a thin LVsudo lvcreate --type thin --name tenant1 --virtualsize \ 2T --thinpool vgdata/pool0View examples
Monitor thin-pool utilizationsudo lvs -o \ lv_full_name,segtype,lv_size,data_percent,metadata_percent,pool_lv,discardsView examples
Extend thin-pool datasudo lvextend --size +100G vgdata/pool0View examples
Extend thin-pool metadatasudo lvextend --poolmetadatasize +1G vgdata/pool0View examples
Create a COW snapshotsudo lvcreate --snapshot --name app-prechange --size 20G \ /dev/vgdata/appView examples
Monitor snapshot consumptionsudo lvs -o \ lv_full_name,origin,lv_size,data_percent,lv_attrView examples
Merge a snapshotsudo lvconvert --merge /dev/vgdata/app-prechangeView examples
Move extents between PVssudo pvmove /dev/disk/by-id/wwn-0x5000c50011111111 \ /dev/disk/by-id/wwn-0x5000c50022222222View examples
Remove an empty PV from a VGsudo vgreduce vgdata \ /dev/disk/by-id/wwn-0x5000c50011111111View examples
Tag a logical volumesudo lvchange --addtag production vgdata/appView examples
Select LVs by tagsudo lvs -o lv_full_name,lv_tags -S 'tags={production}'View examples
Activate one LVsudo lvchange --activate y vgdata/appView examples
Deactivate one LVsudo lvchange --activate n vgdata/appView examples
Disable LV autoactivationsudo lvchange --setautoactivation n vgdata/appView examples
Back up VG metadatasudo vgcfgbackup --file /var/backups/lvm/vgdata.conf \ vgdataView examples
List metadata archivessudo vgcfgrestore --list vgdataView examples
Test metadata restorationsudo vgcfgrestore --test --file \ /var/backups/lvm/vgdata.conf vgdataView examples
List the LVM devices filesudo lvmdevicesView examples
Check device-file entriessudo lvmdevices --checkView examples
Set thin-pool discard modesudo lvchange --discards nopassdown vgdata/pool0View examples
Report VG ownership and lockingsudo vgs -o \ vg_name,vg_uuid,vg_attr,vg_systemid,vg_locktypeView examples
Start shared-VG lockingsudo vgchange --lockstart vgsharedView 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

01

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.

Capture human-readable topology
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
Save a machine-readable baseline
sudo lvm fullreport --reportformat json_std
Back to quick reference ↑
02

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.

Inspect a stable device before initialization
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"
Destructive creation sequence after approval
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.

Back to quick reference ↑
03

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.

Grow ext4 after extending its LV
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
Grow mounted XFS after extending its LV
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
Back to quick reference ↑
04

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.

Inspect and simulate before any shrink
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
Destructive offline ext4 shrink with a safety margin
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.

Back to quick reference ↑
05

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.

Create and monitor a thin-provisioned LV
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
Configure proactive pool extension
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.

Back to quick reference ↑
06

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.

Freeze briefly while creating a classic snapshot
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.

Review a rollback before snapshot merge
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.

Back to quick reference ↑
07

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.

Migrate a PV using stable identifiers
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"
Detach only an empty source 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.

Back to quick reference ↑
08

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.

Tag and report production LVs
sudo lvchange --addtag production vgdata/app
sudo lvs -o lv_full_name,lv_size,lv_tags -S 'tags={production}'
Preview a compound capacity selection
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.

Back to quick reference ↑
09

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.

Find consumers before deactivation
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
Inspect activation policy and state
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 to quick reference ↑
10

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.

Capture metadata and identify the exact VG
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
Test a selected metadata restore
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.

Back to quick reference ↑
11

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.

Audit active device-discovery policy
sudo lvmdevices
sudo lvmdevices --check
sudo lvmconfig --type current devices/use_devicesfile devices/filter
Inspect and change thin-pool discard handling
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.

Back to quick reference ↑
12

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.

Inspect shared-VG prerequisites
sudo lvm version
systemctl status lvmlockd --no-pager
sudo vgs -o vg_name,vg_uuid,vg_attr,vg_systemid,vg_locktype
sudo lvmlockctl --info
Start an approved shared VG lockspace
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.

Back to quick reference ↑

Sources and further reading

References

Authoritative documentation used to verify and expand this cheat sheet.

  1. LVM2 Projectlvm(8) — LVM tools and object modelman7.org
  2. LVM2 Projectlvcreate(8) — create logical volumesman7.org
  3. LVM2 Projectlvreduce(8) — reduce logical volume sizeman7.org
  4. LVM2 Projectlvconvert(8) — convert and merge logical volumesman7.org
  5. LVM2 Projectlvmthin(7) — LVM thin provisioningman7.org
  6. LVM2 Projectpvmove(8) — move physical extentsman7.org
  7. LVM2 Projectlvmreport(7) — reporting and selectionman7.org
  8. LVM2 Projectlvmdevices(8) — manage the devices fileman7.org
  9. LVM2 Projectvgcfgrestore(8) — restore volume group metadataman7.org
  10. 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.

Share feedback