An LVM snapshot is a point-in-time copy of a Logical Volume — created instantly, requiring only a small amount of extra space to store changes made after the snapshot was taken. Snapshots are the foundation of consistent online backups, safe system updates, and rapid rollback capability.
LVM uses a Copy-on-Write (CoW) mechanism — when a block is modified in the original LV after the snapshot is taken, the original data is copied to the snapshot space before the new data is written. The snapshot always reflects the state at the moment it was created, while the original LV continues to change normally.
At snapshot creation time: [ Original LV: /dev/vg_data/lv_home ] [ Snapshot: lv_home_snap (empty CoW store) ] After a file is modified in the original: [ Original LV: block 4 = NEW DATA ] [ Snapshot CoW store: block 4 = OLD DATA ] Reading snapshot always returns original state: [ Original LV: reads current data ] [ Snapshot: reads CoW store for changed blocks ]Snapshot space usage grows as original changes — monitor it!
Creating a snapshot is instantaneous regardless of LV size:
# Create a snapshot of lv_home with 5GB CoW space sudo lvcreate -s -L 5G -n lv_home_snap /dev/vg_data/lv_home # Snapshot naming convention — append date for clarity sudo lvcreate -s -L 5G \ -n lv_home_snap_$(date +%Y%m%d) \ /dev/vg_data/lv_home # Verify snapshot created sudo lvs sudo lvdisplay /dev/vg_data/lv_home_snaplvs output showing snapshot:
owi-aos on the origin = "origin with snapshot."
swi-a-s on the snapshot = "snapshot, writeable, active."
The Data% column shows how full the CoW store is —
watch this number. If it hits 100% the snapshot becomes invalid.
lvs and extend if needed.
Mount a snapshot read-only to browse files at the point-in-time state, or read-write for testing changes without touching the original:
# Mount snapshot read-only (safest — preserves snapshot integrity) sudo mkdir -p /mnt/snapshot sudo mount -o ro /dev/vg_data/lv_home_snap /mnt/snapshot # Browse files as they were at snapshot time ls /mnt/snapshot diff /mnt/snapshot/etc/passwd /etc/passwd # Mount snapshot read-write (for testing) sudo mount /dev/vg_data/lv_home_snap /mnt/snapshot # XFS snapshots require nouuid option (duplicate UUID issue) sudo mount -o ro,nouuid /dev/vg_data/lv_home_snap /mnt/snapshot # Unmount when done sudo umount /mnt/snapshot
nouuid
to the mount options for XFS snapshots.
If a snapshot's CoW store fills up it becomes invalid and is automatically deactivated. Monitor and extend before that happens:
# Check snapshot fill level sudo lvs | grep snap sudo lvdisplay /dev/vg_data/lv_home_snap | grep "Allocated" # Watch snapshot usage live sudo watch -n10 'sudo lvs | grep snap' # Extend snapshot CoW space before it fills sudo lvextend -L +2G /dev/vg_data/lv_home_snap # Configure LVM to auto-extend snapshots (lvm.conf) sudo vi /etc/lvm/lvm.conf # Find and set: # snapshot_autoextend_threshold = 70 (extend when 70% full) # snapshot_autoextend_percent = 20 (extend by 20%)lvdisplay snapshot fill level:
lvm.conf for long-running snapshots.
Merging a snapshot reverts the original LV to the snapshot's state — useful for undoing a bad system update or failed migration:
# Unmount the origin LV first if possible sudo umount /home # Merge snapshot back into origin (schedules the merge) sudo lvconvert --merge /dev/vg_data/lv_home_snap # If the LV is in use (e.g., root filesystem), merge happens on next boot # LVM will automatically complete the merge during next activation sudo reboot # After reboot — verify merge completed (snapshot LV will be gone) sudo lvs # lv_home_snap should no longer appear
lvremoveWhen a snapshot is no longer needed, remove it to free the CoW space:
# Unmount first if mounted sudo umount /mnt/snapshot # Remove the snapshot LV sudo lvremove /dev/vg_data/lv_home_snap # Remove without interactive confirmation (for scripts) sudo lvremove -f /dev/vg_data/lv_home_snap # Verify it is gone and space is returned sudo lvs sudo vgs # VFree should increase by the snapshot CoW size
The classic use case — take a snapshot, back it up, remove it. Gives you a consistent backup of a live filesystem:
#!/bin/bash # lvm-snapshot-backup.sh # Consistent online backup using LVM snapshot LV_ORIGIN="/dev/vg_data/lv_home" LV_SNAP="/dev/vg_data/lv_home_snap" SNAP_SIZE="5G" SNAP_MOUNT="/mnt/snap_backup" BACKUP_DEST="/backup/home_$(date +%Y%m%d_%H%M%S).tar.gz" echo "=== LVM Snapshot Backup ===" echo "Origin: $LV_ORIGIN" echo "Dest: $BACKUP_DEST" echo "" # Step 1: Create snapshot echo "Creating snapshot..." sudo lvcreate -s -L "$SNAP_SIZE" -n lv_home_snap "$LV_ORIGIN" # Step 2: Mount snapshot read-only sudo mkdir -p "$SNAP_MOUNT" sudo mount -o ro "$LV_SNAP" "$SNAP_MOUNT" # Step 3: Backup the snapshot (consistent point-in-time) echo "Backing up..." sudo tar -czf "$BACKUP_DEST" -C "$SNAP_MOUNT" . BACKUP_EXIT=$? # Step 4: Unmount and remove snapshot (always — even if backup failed) sudo umount "$SNAP_MOUNT" sudo lvremove -f "$LV_SNAP" # Step 5: Report if [ $BACKUP_EXIT -eq 0 ]; then echo "Backup complete: $BACKUP_DEST" ls -lh "$BACKUP_DEST" else echo "ERROR: Backup failed (exit code $BACKUP_EXIT)" >&2 exit 1 fi
For databases, flush and lock before snapshotting to guarantee a clean, consistent state:
#!/bin/bash # Database-consistent LVM snapshot for MySQL/MariaDB DB_USER="root" DB_PASS="$MYSQL_ROOT_PASSWORD" LV_ORIGIN="/dev/vg_data/lv_mysql" SNAP_NAME="lv_mysql_snap_$(date +%Y%m%d)" echo "Flushing and locking MySQL tables..." # Step 1: Flush tables and acquire read lock mysql -u"$DB_USER" -p"$DB_PASS" -e "FLUSH TABLES WITH READ LOCK;" # Step 2: Create snapshot immediately (while lock is held) sudo lvcreate -s -L 10G -n "$SNAP_NAME" "$LV_ORIGIN" # Step 3: Release the lock — DB is fully operational again mysql -u"$DB_USER" -p"$DB_PASS" -e "UNLOCK TABLES;" echo "Lock released. Snapshot: $SNAP_NAME" echo "DB fully operational — backup from snapshot at leisure." # Step 4: Mount and backup the snapshot sudo mkdir -p /mnt/dbsnap sudo mount -o ro /dev/vg_data/"$SNAP_NAME" /mnt/dbsnap sudo rsync -av /mnt/dbsnap/ /backup/mysql_$(date +%Y%m%d)/ # Step 5: Cleanup sudo umount /mnt/dbsnap sudo lvremove -f /dev/vg_data/"$SNAP_NAME" echo "Done."
UNLOCK TABLES the database is fully operational while
the backup of the snapshot proceeds at whatever pace is needed.
This technique is standard for zero-downtime MySQL/MariaDB backups.
Thin-provisioned LVs and their snapshots are more space-efficient for environments with many snapshots of the same origin:
# Create a thin pool LV (the backing store) sudo lvcreate -L 500G --thinpool tp_pool vg_data # Create a thin LV from the pool (no fixed size commitment) sudo lvcreate -V 200G --thin -n lv_thin_home vg_data/tp_pool # Format and mount as normal sudo mkfs.xfs /dev/vg_data/lv_thin_home sudo mount /dev/vg_data/lv_thin_home /home # Create a thin snapshot (much more efficient than classic snapshots) sudo lvcreate -s -n lv_thin_home_snap vg_data/lv_thin_home # Thin snapshots share unchanged blocks — no CoW size needed sudo lvs sudo lvs -o name,attr,size,pool_lv,origin,data_percentlvs showing thin pool and snapshots:
| Command | What it does |
|---|---|
| lvcreate -s -L 5G -n snap /dev/vg/lv | Create a 5GB snapshot of lv |
| lvs | List LVs — shows snapshot Data% fill level |
| lvdisplay /dev/vg/snap | Detailed snapshot info including fill % |
| mount -o ro /dev/vg/snap /mnt/snap | Mount snapshot read-only |
| mount -o ro,nouuid /dev/vg/snap /mnt/snap | Mount XFS snapshot (duplicate UUID fix) |
| umount /mnt/snap | Unmount snapshot |
| lvextend -L +2G /dev/vg/snap | Extend snapshot CoW space |
| lvconvert --merge /dev/vg/snap | Rollback — merge snapshot to origin |
| lvremove /dev/vg/snap | Remove snapshot (does not affect origin) |
| lvcreate -s -n snap vg/thin_lv | Create thin snapshot (no size needed) |
| Use Case | Approach |
|---|---|
| Online filesystem backup | Snapshot → mount ro → tar/rsync → remove snapshot |
| Database backup | FLUSH + LOCK → snapshot → UNLOCK → backup snapshot → remove |
| Safe system update | Snapshot before update → update → if OK remove, if bad merge |
| Testing config changes | Snapshot → make changes → if OK remove, if bad merge |
| Many long-term snapshots | Use thin provisioning — more space-efficient |
| Recover deleted file | Snapshot → mount ro → copy file back → unmount → remove |