When working with ZFS snapshots and clones, we often encounter complex dependency chains where destroying a snapshot requires understanding its relationships with both filesystems and other snapshots. Let's analyze the given scenario:
# zfs list -t all -o name,origin,clones
tank/containers/five tank/containers/two@B -
tank/containers/two tank/containers/six@A -
tank/containers/six tank/containers/three@F -
tank/containers/three tank/containers/one@E -
tank/containers/one@E - tank/containers/three
tank/containers/two@B - tank/containers/five
tank/containers/six@A - tank/containers/two
tank/containers/six@C - tank/containers/four
tank/containers/three@F - tank/containers/six
The fundamental problem is that ZFS prevents snapshot deletion when clones exist, even if those clones are themselves snapshots. This creates a catch-22 situation where we want to:
- Delete all snapshots (A, B, C, E, F)
- Preserve all active filesystems (one, two, three, four, five, six)
- Handle the interdependencies gracefully
The promotion strategy needs to be applied systematically. Here's a step-by-step method that works with this dependency chain:
# First promote all cloned filesystems to break dependencies
zfs promote tank/containers/five
zfs promote tank/containers/two
zfs promote tank/containers/six
zfs promote tank/containers/three
# Verify the new relationships
zfs list -t all -o name,origin,clones
# Now attempt to destroy snapshots in reverse dependency order
zfs destroy tank/containers/three@F
zfs destroy tank/containers/six@A
zfs destroy tank/containers/six@C
zfs destroy tank/containers/two@B
zfs destroy tank/containers/one@E
Some scenarios require additional care. For example, when dealing with snapshot clones of snapshots:
# When encountering snapshot clones like tank/containers/two@B
# You'll need to first promote its clone (tank/containers/five)
# Then destroy the intermediate snapshot:
zfs promote tank/containers/five
zfs destroy tank/containers/two@B
For more complex scenarios, consider using bookmarks as an intermediate step:
# Create bookmarks for critical points
zfs bookmark tank/containers/three@F tank/containers/three#F
zfs bookmark tank/containers/six@A tank/containers/six#A
# Then promote and destroy as needed
zfs promote tank/containers/six
zfs destroy tank/containers/three@F
After completing the operations, verify the filesystem integrity:
# Check remaining snapshots
zfs list -t snapshot
# Verify filesystems are intact
zfs list -t filesystem
# Optional: Recreate any needed snapshots
zfs snapshot tank/containers/one@clean
zfs snapshot tank/containers/two@clean
For environments with frequent snapshot rotations, consider scripting this process:
#!/bin/bash
# Sample automation script for snapshot cleanup
for fs in $(zfs list -H -o name -t filesystem | grep "^tank/containers/"); do
zfs promote "$fs" 2>/dev/null
done
for snap in $(zfs list -H -o name -t snapshot | grep "^tank/containers/"); do
zfs destroy -v "$snap"
done
When working with ZFS snapshots and clones, you'll often encounter complex dependency chains that prevent straightforward deletion. Let's analyze the specific case:
tank/containers/one@E → tank/containers/three → tank/containers/three@F → tank/containers/six
tank/containers/six@A → tank/containers/two → tank/containers/two@B → tank/containers/five
tank/containers/six@C → tank/containers/four
The main issue arises when trying to delete snapshots that have active clones. ZFS rightfully prevents this to maintain data integrity. The error message:
# zfs destroy tank/containers/six@A
cannot destroy 'tank/containers/six@A': snapshot has dependent clones
use '-R' to destroy the following datasets:
tank/containers/five
tank/containers/two@B
tank/containers/two
Here's how to safely remove all snapshots while preserving the filesystems:
# First, promote all clones to break dependencies
zfs promote tank/containers/five
zfs promote tank/containers/two
zfs promote tank/containers/four
zfs promote tank/containers/six
zfs promote tank/containers/three
# Verify the promotion worked
zfs list -t all -o name,origin,clones
# Now safely delete all snapshots
zfs destroy tank/containers/one@E
zfs destroy tank/containers/three@F
zfs destroy tank/containers/six@A
zfs destroy tank/containers/six@C
zfs destroy tank/containers/two@B
1. Promotion Order Matters: Always promote from the most dependent clone upward
2. Verify Filesystem Integrity: After promotion, check that all data remains accessible
3. Space Implications: Promoting clones may temporarily increase storage usage
If you're comfortable with a more aggressive approach (and have verified backups):
# Destroy all snapshots recursively while preserving filesystems
for snap in $(zfs list -H -t snapshot -o name | grep 'tank/containers'); do
zfs destroy -R $snap 2>/dev/null
done
# Then clean up any remaining dependencies
zfs list -t all -o name,origin | grep -v "-" | awk '{print $1}' | while read fs; do
zfs promote $fs
done
For systems with frequent snapshot cleanup needs, consider this bash function:
function zfs_clean_snapshots() {
local pool=$1
zfs list -H -t snapshot -o name $pool | while read snap; do
if ! zfs destroy -vn $snap | grep -q "would destroy"; then
zfs list -H -o name,origin | grep "$snap" | cut -f1 | while read clone; do
zfs promote $clone
done
zfs destroy $snap
fi
done
}