LVM offers two snapshot mechanisms that look similar from the command line but fail in fundamentally different ways. The choice between them is about which failure mode you inherit when something goes wrong.
Old-style COW (copy-on-write) snapshots allocate a fixed exception store at creation time. When that store fills to 100%, the snapshot is invalidated permanently and silently. The origin volume continues running. You lose the snapshot and whatever backup or rollback point it represented, but production keeps going.
Thin snapshots share the thin pool and have no separate exception store. When the pool runs out of data or metadata space, every thin volume in the pool freezes at once. That includes the origin, every snapshot, and every other thin LV sharing the pool. The blast radius is wider, recovery is harder, and metadata exhaustion can corrupt the pool in ways that are not always recoverable.
How each snapshot type works
Old-style COW snapshots are created with --size:
# Create a COW snapshot with a 1 GiB exception store
lvcreate --snapshot --size 1G --name snap1 vg0/origin_lv
The --size argument allocates a fixed exception store from VG free extents. This store holds the original copy of every block overwritten in the origin after snapshot creation. Each write to the origin triggers a three-step copy-on-write operation: read the original block from the origin, write it to the exception store, then write the new data to the origin. This triples I/O per origin write while the snapshot exists.
Multiple snapshots on the same origin compound this overhead. Three snapshots on one origin means every origin write triggers three independent COW operations. Write latency doubles or more, and system I/O throughput drops until the snapshot is removed or invalidated.
Thin snapshots are created without --size:
# Create a thin snapshot (no --size)
lvcreate --snapshot --name snap1 vg0/thin_lv
The snapshot shares the thin pool’s data and metadata space with the origin and all other thin volumes in the pool. There is no separate exception store. Copy-on-write data lands in the same pool as everything else. The snapshot is effectively another thin LV that tracks divergent blocks from its origin.
Thin snapshots avoid the COW write amplification problem entirely. They also support snapshot-of-snapshot chains, since everything shares the same pool. Removing the origin of a thin snapshot does not destroy the snapshot: each snapshot becomes an independent thin-provisioned volume. This is different from old-style snapshots, where the origin cannot be removed while snapshots exist.
flowchart TD
subgraph COW["Old-style COW snapshot"]
A1["Write to origin"] --> A2["Copy old block to exception store"]
A2 --> A3{"Exception store full?"}
A3 -->|"No"| A4["Snapshot stays valid"]
A3 -->|"Yes"| A5["Snapshot invalidated - permanent, silent"]
A5 --> A6["Origin unaffected"]
end
subgraph Thin["Thin snapshot"]
B1["Write to any thin LV"] --> B2["Allocate from shared pool"]
B2 --> B3{"Pool has space?"}
B3 -->|"Yes"| B4["All volumes normal"]
B3 -->|"No data space"| B5["All thin LVs freeze (60s queue, then errors)"]
B3 -->|"No metadata space"| B6["Pool may corrupt - recovery not guaranteed"]
endThe failure mode COW snapshots inherit: silent invalidation
When the COW exception store fills to 100%, the snapshot is immediately and irreversibly invalidated. The kernel marks it invalid (the lv_attr field shows I in position 5). The snapshot does not disappear from lvs output; it remains listed but is dead.
Key characteristics:
- Silent: No error reaches the application. The origin continues serving I/O. The kernel stops tracking changes for that snapshot.
- Permanent: An invalidated snapshot cannot be repaired, extended, or recovered. The only option is to remove it with
lvremoveand recreate from scratch. - Scoped: Only the single snapshot is lost. Other snapshots on the same origin, the origin itself, and all other LVs in the VG are unaffected.
- Driven by origin writes: The exception store fills based on writes to the origin, not writes to the snapshot. A snapshot of a quiescent volume can sit at 0% indefinitely. A snapshot of an active database can fill in minutes.
The practical consequence: if a backup process was reading from this snapshot, the backup silently becomes incomplete or corrupt. The backup process may not notice because the origin remains available. The first sign of trouble is often a failed restore months later.
snap_percent is the monitoring signal. It jumps in chunks because exception store allocation happens in blocks, so the value may advance several percent at once. You cannot precisely predict the exact moment of overflow.
The failure mode thin snapshots inherit: pool exhaustion
Thin snapshots do not have a fixed COW area, so they avoid the invalidation problem. But they inherit the thin pool’s exhaustion behavior, which is a different and potentially more severe failure mode.
When the thin pool’s data space fills to 100%, behavior depends on the pool’s “when full” policy:
error_if_no_space: writes fail immediately.queue_if_no_space: writes to all thin LVs in the pool are queued for up to 60 seconds, controlled by the kernelno_space_timeoutparameter with a default of 60 combined withdm_thin_poolmetadata. If space is not freed within that window, writes fail with errors.
You set the policy when creating the pool:
# Create thin pool with error mode (writes fail immediately when full)
lvcreate --type thin-pool --poolmetadatasize 1G --size 100G \
--discards passdown vg0/thinpool
# Check or change the current policy on an existing pool
# The policy is stored in lvm.conf: activation/thin_pool_autoextend_threshold
# Verify current runtime policy:
dmsetup status vg0-thinpool
# Look for "queue_if_no_space" or "error_if_no_space" in the output
In queue mode, processes doing I/O to any thin LV in the pool enter D state (uninterruptible sleep). The system can appear completely hung. If the root filesystem is on a thin LV in the affected pool, the system may become unresponsive to all interaction, including SSH.
When the thin pool’s metadata space fills to 100%, the situation is worse. The man page warns that metadata space exhaustion can lead to inconsistent thin pool metadata and inconsistent filesystems, and that data from thin LVs may be unrecoverable. Recovery requires deactivation, lvconvert --repair (which uses thin_repair and the pmspare LV), and is not guaranteed to succeed.
Key characteristics:
- Wide blast radius: Every thin LV in the pool is affected simultaneously. The origin, all snapshots, and all other thin volumes freeze or error together.
- Two independent exhaustion dimensions: Data space and metadata space can fill independently. Metadata can reach 100% while data usage is under 50%. Operators monitoring only
data_percentmiss this entirely. - Metadata is not reclaimable: Unlike data space, which can be reclaimed via
fstrimor discard on thin LV filesystems, metadata space does not decrease through normal operation. Metadata consumption depends on unique block writes, not data volume. High random I/O consumes metadata faster than sequential I/O. - Recovery is hard: Extending the pool requires VG free space. If the VG is also full, you need to add a PV first. If metadata exhaustion has already corrupted the pool,
lvconvert --repairmay fail.
Side-by-side: which failure mode you inherit
| Dimension | Old-style COW snapshot | Thin snapshot |
|---|---|---|
| What fills up | Fixed exception store (VG extents) | Shared thin pool data and metadata |
| Failure at 100% | Single snapshot invalidated permanently | All thin LVs in pool freeze or error |
| Origin impact | None after invalidation | Origin is in the pool, freezes too |
| Other LVs affected | No | Yes, all thin LVs sharing the pool |
| Recoverability | Snapshot is gone, recreate only | Extend pool if VG has space; metadata corruption may not be repairable |
| Warning signal | snap_percent approaching 100% | data_percent and metadata_percent approaching 100% |
| Speed of failure | Instant invalidation at 100% | 60s write queue (if queued mode), then errors |
| Write amplification | 3x or more per origin write, per snapshot | Minimal COW overhead on origin |
| Snapshot of snapshot | Not supported | Supported, shares the same pool |
| Origin can be removed | No, not while snapshots exist | Yes, snapshots become independent thin LVs |
Which to choose
The decision depends on your workload and your tolerance for each failure mode.
Use old-style COW snapshots when:
- Short-lived backup snapshots: You create, read, and remove within a known window. Size the exception store for the expected write volume during that window.
- Isolation matters: If the snapshot dies, only the backup or restore point is lost. Production continues without interruption.
- You can tolerate write amplification: The origin sees 3x or higher write overhead per snapshot during the snapshot’s lifetime.
Use thin snapshots when:
- Long-lived snapshots: You need rollback points or test environments that persist for hours or days.
- You already monitor the thin pool: You track both
data_percentandmetadata_percentand have auto-extend properly configured. - You can accept the blast radius: A full pool affects all thin volumes, not just the snapshot.
- Multiple snapshots on one origin: Thin snapshots do not compound COW overhead the way old-style snapshots do.
Do not mix them unknowingly. The --size trap means a single command can create the wrong type. Verify with lvs what type each snapshot actually is before relying on it.
The creation trap: –size creates a COW snapshot
The most common operator mistake is passing --size when creating a snapshot of a thin LV. The lvmthin(7) man page is explicit: specifying -L or --size when creating a thin snapshot causes an old-style COW snapshot to be created instead.
# Correct: thin snapshot shares the pool, no --size
lvcreate --snapshot --name snap1 vg0/thin_lv
# Wrong: creates an old-style COW snapshot with a fixed exception store
lvcreate --snapshot --size 1G --name snap1 vg0/thin_lv
The wrong command succeeds without error or warning. You end up with a snapshot that has a fixed exception store allocated from VG extents and will be silently invalidated when it fills. You may believe you are using thin snapshots (which share the pool and do not invalidate) when you are actually running old-style snapshots that can die at any moment.
To verify which type you have, check whether the snapshot references a pool:
# Identify snapshot type - pool_lv presence indicates thin snapshot
lvs -o lv_name,origin,seg_type,pool_lv,snap_percent
A snapshot with a pool_lv value is a thin snapshot sharing a thin pool. A snapshot with no pool_lv and a seg_type of snapshot is an old-style COW snapshot with a fixed exception store and its own invalidation risk.
Signals to watch in production
| Signal | Applies to | Why it matters | Warning sign |
|---|---|---|---|
snap_percent | COW snapshots | Approaches 100% means imminent invalidation | Above 80% on an active origin |
lv_attr position 5 = I | COW snapshots | Snapshot already invalidated, backup lost | Any I value |
data_percent (thin pool) | Thin snapshots | Approaches 100% means all thin LVs freeze | Above 85% |
metadata_percent (thin pool) | Thin snapshots | Approaches 100% means potential pool corruption | Above 75% |
lv_attr position 9 = D | Thin snapshots | Pool out of data space, writes failing or queued | Any D value |
lv_attr position 9 = F | Thin snapshots | Pool in failed state, repair needed | Any F value |
lv_attr position 9 = M | Thin snapshots | Metadata read-only mode | Any M value |
| Origin LV write latency | Both (COW mainly) | COW overhead from active snapshots | 2x baseline or higher |
vg_free_percent | Both | Low VG space prevents extension or pool growth | Below 10% |
thin_pool_autoextend_threshold | Thin snapshots | Default 100 means auto-extend is disabled | Verify value is below 100 |
| dmeventd running | Thin snapshots | Required for auto-extend to fire | Process absent |
Two operational notes on these signals.
First, the thin pool auto-extend threshold defaults to 100, which means disabled. Many operators assume their thin pools will auto-grow, but the default configuration does nothing. The first test of auto-extend is usually the production incident. Verify explicitly in /etc/lvm/lvm.conf that thin_pool_autoextend_threshold is set below 100 and that thin_pool_autoextend_percent is greater than 0.
# Check current auto-extend configuration
grep -E 'thin_pool_autoextend' /etc/lvm/lvm.conf
Second, thin pool data usage is updated periodically by the kernel, not on every write. It can be tens of seconds behind actual state. This makes sub-second alerting unreliable for thin pool metrics. Trend-based alerting with rate-of-change calculation is more useful than instantaneous threshold checks for pool exhaustion. For old-style snapshots, snap_percent also jumps in chunks rather than climbing smoothly, because exception store allocation happens in blocks.
How Netdata helps
- Per-second collection of thin pool
data_percentandmetadata_percent, giving earlier visibility into growth trends than periodiclvspolling. snap_percenttracking for old-style snapshots with anomaly detection on growth rate, so a write burst on the origin triggers an alert before the exception store fills.- LV health attribute monitoring (
lv_attrposition 9:D,F,Mflags) that surfaces pool failure states the moment they appear in kernel device-mapper. - Correlation of VG free space with thin pool usage, showing whether auto-extend can actually succeed when it fires.
- D-state process count and dm device latency correlation, so you can distinguish snapshot COW overhead from thin pool exhaustion during an incident.
- Kernel log (dmesg) event collection alongside LVM metrics, so invalidation messages and I/O errors appear in the same timeline as the metrics that explain them.
Related guides
- LVM cannot extend a logical volume: adding a PV when the VG is full
- LVM filesystem full while the volume group has space: the resize step everyone forgets
- How LVM actually works in production: a mental model for operators
- LVM Insufficient free extents: the volume group is out of space
- LVM monitoring checklist: the signals every production volume manager needs
- LVM monitoring maturity model: from survival to expert
- LVM reached low water mark for data device: the thin pool warning before the freeze
- LVM thin pool space not reclaimed: discard, TRIM, and fstrim
- LVM thin pool auto-extend not working: threshold 100 means disabled
- LVM thin pool out of data space: every thin volume freezes at once
- LVM thin pool metadata full: the exhaustion that can corrupt the pool
- LVM thin pool check needed: thin_check and lvconvert –repair






