Clone Anything
Instant copies in milliseconds — not minutes. ZFS clones let you duplicate datasets, VM disks, and home directories at near-zero cost.
The short version: a ZFS clone is an instant, read-write copy of a dataset that starts by sharing all the original data. No bytes are duplicated until something actually changes. A 100 GB dataset clones in under a second and costs almost nothing until you start modifying the copy.
Why clones are different from copies
The old way — cp -r
Reads every file from disk, writes a full duplicate. A 100 GB dataset takes 5–20 minutes, uses 100 GB more disk space immediately, and the copy starts from scratch every time.
cp -r /data /data-copy# 15 minutes later...# -rw-r--r-- 100GB /data-copy
The ZFS way — zfs clone
Creates a new dataset that points to the same blocks. No data is copied. Instant at any size. The clone only uses space for blocks that differ from the original — everything else is shared.
zfs snapshot rpool/data@nowzfs clone rpool/data@now rpool/data-copy# Done in < 1 second.
Copy-on-Write (CoW) — the magic behind it
ZFS uses a technique called Copy-on-Write. When you clone a dataset, both the original and the clone point to the same physical blocks on disk. When you write to the clone, ZFS writes the new data to a new block and updates only the clone's pointer. The original is never touched. This is why a clone is instant — nothing is actually copied until something changes.
Clone a dataset
The basic pattern is always the same: take a snapshot, then clone from that snapshot. This is a fundamental ZFS rule — you cannot clone a dataset directly; you must clone from a snapshot. kldload's kclone wrapper hides this step from you; the native commands make it explicit.
# The kldload way — snapshot + clone in one command
kclone /data /data-copy
# The native ZFS way — two explicit steps
# Step 1: Take a snapshot (required — clones must come from a snapshot)
zfs snapshot rpool/data@before-test
# Step 2: Clone it — this is instant regardless of size
zfs clone rpool/data@before-test rpool/data-copy
# Step 3: Verify both exist
zfs list rpool/data rpool/data-copy
Why does native ZFS require a snapshot first?
A ZFS clone is defined as a writable snapshot. There is no way to clone a live dataset in one atomic operation — you must freeze a point in time (the snapshot) and clone from that frozen state. The snapshot becomes the shared ancestor that both the original and the clone inherit their data from. kclone takes the snapshot automatically before cloning, which is why you don’t have to think about it.
NAME USED AVAIL REFER MOUNTPOINT
rpool/data 78.3M 412G 78.3M /rpool/data
rpool/data-copy 192K 412G 78.3M /rpool/data-copy
Notice: data-copy shows only 192K used — that's just metadata. The 78.3 MB of actual data is shared with the original and counted once.
Clone a VM disk
This is one of the most useful things you can do. Create a "golden" VM image once, then clone it to spin up new VMs instantly:
# The kldload way
kclone /vms/golden /vms/test-vm-1
kclone /vms/golden /vms/test-vm-2
# The native ZFS way
# Take a snapshot of the golden VM disk
zfs snapshot rpool/vms/golden@ready
# Clone it to create a new test VM — instant
zfs clone rpool/vms/golden@ready rpool/vms/test-vm-1
# Clone it again for another VM — still instant (clones from same snapshot)
zfs clone rpool/vms/golden@ready rpool/vms/test-vm-2
Each clone starts as a full copy of the golden image, but uses almost zero extra disk space until the VMs diverge. This is how you can spin up 10 VMs in the time it used to take to copy one disk image.
# Check how much space each VM actually uses vs references
zfs list -o name,used,refer rpool/vms
NAME USED REFER
rpool/vms 20.1G 96K
rpool/vms/golden 20.0G 20.0G
rpool/vms/test-vm-1 312K 20.0G
rpool/vms/test-vm-2 204K 20.0G
REFER is what the dataset sees (the full 20 GB image). USED is what it actually owns on disk (just the changes so far). The golden image is stored once.
Clone a user's home directory
Useful for testing, creating sandbox environments, or giving a user a safe copy to experiment in:
# The kldload way — finds the ZFS dataset for the path, snapshots, and clones
kclone /home/admin /home/admin-backup
kclone /home/admin /home/admin-test
# The native ZFS way
# Snapshot the current state of admin's home
zfs snapshot rpool/home/admin@2026-03-26
# Clone it as a backup the user can browse
zfs clone rpool/home/admin@2026-03-26 rpool/home/admin-backup
# Or clone it as a separate sandbox
zfs clone rpool/home/admin@2026-03-26 rpool/home/admin-test
# Set permissions on the copies so the user owns them
chown -R admin:admin /rpool/home/admin-backup
The cloned home directory is fully writable. The user can delete, modify, or break things in their test copy without affecting their real home directory.
What kclone adds over zfs snapshot + zfs clone
• Path resolution — you give it a filesystem path (/home/admin); it figures out the ZFS dataset name (rpool/home/admin). With native ZFS you need to know the dataset name.
• Automatic snapshot — no need to run zfs snapshot first; kclone does it immediately before cloning so the two steps are atomic from your perspective.
• One command instead of two — less chance of cloning an outdated snapshot by accident.
• Works for any path — kclone /srv/production /srv/staging or kclone /var/lib/postgres /var/lib/postgres-test without knowing the underlying ZFS layout.
Clean up when you're done
Clones are just datasets — delete them with zfs destroy when you no longer need them:
# Delete a clone
zfs destroy rpool/data-copy
# If the clone has its own snapshots, add -r to remove those too
zfs destroy -r rpool/vms/test-vm-1
One rule: you can't delete the snapshot while clones depend on it
The original snapshot (rpool/data@before-test) must exist as long as clones depend on it. If you try to delete it, ZFS will refuse. You can either delete the clone first, or use zfs promote to make the clone independent — then the original becomes the dependent instead.
Quick reference
Clone any dataset — kldload way
One command. kclone resolves the path, snapshots, and clones.
Clone any dataset — native ZFS
Two explicit steps. You supply the dataset name, not the path.
zfs clone rpool/data@snap rpool/data-copy
See how much space clones use
USED = unique blocks this clone owns. REFER = total data it sees (shared + owned).
Delete a clone
Just like any other dataset. The original is unaffected.
Make a clone independent (promote)
Reverses the parent-child relationship. The clone becomes the primary dataset; the original becomes the dependent.
kldload vs native — quick reference table
| Task | kldload | Native ZFS | What k* adds |
|---|---|---|---|
| Clone a dataset by path | kclone /source /dest | zfs snapshot ds@snap && zfs clone ds@snap ds-copy | Path-to-dataset resolution, automatic snapshot, one step |
| Clone a VM disk | kclone /vms/golden /vms/new-vm | zfs snapshot rpool/vms/golden@ready && zfs clone rpool/vms/golden@ready rpool/vms/new-vm | No need to know the ZFS dataset path for the VM disk |
| Check clone space usage | (use native) | zfs list -o name,used,refer | No wrapper needed — zfs list is already readable |
| Delete a clone | (use native) | zfs destroy rpool/data-copy | No wrapper needed — zfs destroy is direct |
| Make clone independent | (use native) | zfs promote rpool/data-copy | No wrapper — zfs promote is a single clear command |