This is an exercise I made, just to remind myself of how snapshots and clones work in ZFS. Also, how to properly get rid of them when you’re short of diskspace, or the dataset listing is too long, etc.

First, we have the shell script that demonstrates the rise and fall of the initial dataset, and the intermediary snapshots and clones.

#!/bin/sh
set -x

zfs create zroot/clones
zfs list -rt all zroot/clones

zfs create zroot/clones/a
zfs list -rt all zroot/clones

zfs snapshot zroot/clones/a@b
zfs list -rt all zroot/clones

zfs clone zroot/clones/a@b zroot/clones/b
zfs list -rt all zroot/clones

zfs snapshot zroot/clones/b@c
zfs list -rt all zroot/clones

zfs clone zroot/clones/b@c zroot/clones/c
zfs list -rt all zroot/clones

zfs snapshot zroot/clones/c@d
zfs list -rt all zroot/clones

zfs clone zroot/clones/c@d zroot/clones/d
zfs list -rt all zroot/clones

zfs snapshot zroot/clones/d@e
zfs list -rt all zroot/clones

zfs clone zroot/clones/d@e zroot/clones/e
zfs list -rt all zroot/clones

zfs promote zroot/clones/b
zfs list -rt all zroot/clones

zfs promote zroot/clones/c
zfs list -rt all zroot/clones

zfs promote zroot/clones/d
zfs list -rt all zroot/clones

zfs promote zroot/clones/e
zfs list -rt all zroot/clones

zfs destroy -v zroot/clones/a
zfs list -rt all zroot/clones

zfs destroy -v zroot/clones/b
zfs list -rt all zroot/clones

zfs destroy -v zroot/clones/c
zfs list -rt all zroot/clones

zfs destroy -v zroot/clones/d
zfs list -rt all zroot/clones

zfs destroy -v zroot/clones/e@b
zfs list -rt all zroot/clones

zfs destroy -v zroot/clones/e@c
zfs list -rt all zroot/clones

zfs destroy -v zroot/clones/e@d
zfs list -rt all zroot/clones

zfs destroy -v zroot/clones/e@e
zfs list -rt all zroot/clones

zfs destroy -v zroot/clones/e
zfs list -rt all zroot/clones

zfs destroy -v zroot/clones


Here we go into more detail. First, let’s create a sandbox to play in.

zfs create zroot/clones
zfs list -rt all zroot/clones
NAME           USED  AVAIL  REFER  MOUNTPOINT
zroot/clones    96K  15.4G    96K  legacy

Now, we create the initial dataset. This would typically be the dataset created by FreeBSD Installer, e.g. zroot/ROOT/default.

zfs create zroot/clones/a
zfs list -rt all zroot/clones
NAME             USED  AVAIL  REFER  MOUNTPOINT
zroot/clones     192K  15.4G    96K  legacy
zroot/clones/a    96K  15.4G    96K  legacy

It’s time to create a snapshot of the current dataset.

zfs snapshot zroot/clones/a@b
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       192K  15.4G    96K  legacy
zroot/clones/a      96K  15.4G    96K  legacy
zroot/clones/a@b      0      -    96K  -

Next, we create a clone with the previous snapshot as its origin.

zfs clone zroot/clones/a@b zroot/clones/b
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       200K  15.4G    96K  legacy
zroot/clones/a      96K  15.4G    96K  legacy
zroot/clones/a@b      0      -    96K  -
zroot/clones/b       8K  15.4G    96K  legacy

Let’s create a snapshot of the first clone.

zfs snapshot zroot/clones/b@c
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       200K  15.4G    96K  legacy
zroot/clones/a      96K  15.4G    96K  legacy
zroot/clones/a@b      0      -    96K  -
zroot/clones/b       8K  15.4G    96K  legacy
zroot/clones/b@c      0      -    96K  -

This is our second clone.

zfs clone zroot/clones/b@c zroot/clones/c
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       208K  15.4G    96K  legacy
zroot/clones/a      96K  15.4G    96K  legacy
zroot/clones/a@b      0      -    96K  -
zroot/clones/b       8K  15.4G    96K  legacy
zroot/clones/b@c      0      -    96K  -
zroot/clones/c       8K  15.4G    96K  legacy

Another snapshot.

zfs snapshot zroot/clones/c@d
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       208K  15.4G    96K  legacy
zroot/clones/a      96K  15.4G    96K  legacy
zroot/clones/a@b      0      -    96K  -
zroot/clones/b       8K  15.4G    96K  legacy
zroot/clones/b@c      0      -    96K  -
zroot/clones/c       8K  15.4G    96K  legacy
zroot/clones/c@d      0      -    96K  -

Our third clone.

zfs clone zroot/clones/c@d zroot/clones/d
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       216K  15.4G    96K  legacy
zroot/clones/a      96K  15.4G    96K  legacy
zroot/clones/a@b      0      -    96K  -
zroot/clones/b       8K  15.4G    96K  legacy
zroot/clones/b@c      0      -    96K  -
zroot/clones/c       8K  15.4G    96K  legacy
zroot/clones/c@d      0      -    96K  -
zroot/clones/d       8K  15.4G    96K  legacy

The last snapshot in this exercise.

zfs snapshot zroot/clones/d@e
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       216K  15.4G    96K  legacy
zroot/clones/a      96K  15.4G    96K  legacy
zroot/clones/a@b      0      -    96K  -
zroot/clones/b       8K  15.4G    96K  legacy
zroot/clones/b@c      0      -    96K  -
zroot/clones/c       8K  15.4G    96K  legacy
zroot/clones/c@d      0      -    96K  -
zroot/clones/d       8K  15.4G    96K  legacy
zroot/clones/d@e      0      -    96K  -

The last clone in this exercise.

zfs clone zroot/clones/d@e zroot/clones/e
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       224K  15.4G    96K  legacy
zroot/clones/a      96K  15.4G    96K  legacy
zroot/clones/a@b      0      -    96K  -
zroot/clones/b       8K  15.4G    96K  legacy
zroot/clones/b@c      0      -    96K  -
zroot/clones/c       8K  15.4G    96K  legacy
zroot/clones/c@d      0      -    96K  -
zroot/clones/d       8K  15.4G    96K  legacy
zroot/clones/d@e      0      -    96K  -
zroot/clones/e       8K  15.4G    96K  legacy

Now, we want to clean up this mess, with the goal of having only zroot/clones/e. We start by promoting the first clone created. Notice the initial snapshot now belongs to the first clone.

zfs promote zroot/clones/b
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       224K  15.4G    96K  legacy
zroot/clones/a        0  15.4G    96K  legacy
zroot/clones/b     104K  15.4G    96K  legacy
zroot/clones/b@b     8K      -    96K  -
zroot/clones/b@c      0      -    96K  -
zroot/clones/c       8K  15.4G    96K  legacy
zroot/clones/c@d      0      -    96K  -
zroot/clones/d       8K  15.4G    96K  legacy
zroot/clones/d@e      0      -    96K  -
zroot/clones/e       8K  15.4G    96K  legacy

You can reverse the promotion of zroot/clones/b by promoting zroot/clones/a, the snapshot zroot/clones/b@b becomes zroot/clones/a@b. At this point we could destroy zroot/clones/a and zroot/clones/b@b, in that order, and gain some diskspace. We’ll continue until zroot/clones/e is an independent dataset.


Let’s promote the second clone. The snapshots keep bubbling downwards.

zfs promote zroot/clones/c
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       224K  15.4G    96K  legacy
zroot/clones/a        0  15.4G    96K  legacy
zroot/clones/b        0  15.4G    96K  legacy
zroot/clones/c     112K  15.4G    96K  legacy
zroot/clones/c@b     8K      -    96K  -
zroot/clones/c@c     8K      -    96K  -
zroot/clones/c@d      0      -    96K  -
zroot/clones/d       8K  15.4G    96K  legacy
zroot/clones/d@e      0      -    96K  -
zroot/clones/e       8K  15.4G    96K  legacy

Now we promote the third clone. Bubble, bubble, bubble, …

zfs promote zroot/clones/d
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       224K  15.4G    96K  legacy
zroot/clones/a        0  15.4G    96K  legacy
zroot/clones/b        0  15.4G    96K  legacy
zroot/clones/c        0  15.4G    96K  legacy
zroot/clones/d     120K  15.4G    96K  legacy
zroot/clones/d@b     8K      -    96K  -
zroot/clones/d@c     8K      -    96K  -
zroot/clones/d@d     8K      -    96K  -
zroot/clones/d@e      0      -    96K  -
zroot/clones/e       8K  15.4G    96K  legacy

Here we promote the fourth and last clone. Notice that all snapshots now belong to the newest clone.

zfs promote zroot/clones/e
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       224K  15.4G    96K  legacy
zroot/clones/a        0  15.4G    96K  legacy
zroot/clones/b        0  15.4G    96K  legacy
zroot/clones/c        0  15.4G    96K  legacy
zroot/clones/d        0  15.4G    96K  legacy
zroot/clones/e     128K  15.4G    96K  legacy
zroot/clones/e@b     8K      -    96K  -
zroot/clones/e@c     8K      -    96K  -
zroot/clones/e@d     8K      -    96K  -
zroot/clones/e@e     8K      -    96K  -

It’s time to get rid of the initial dataset.

zfs destroy -v zroot/clones/a
will destroy zroot/clones/a
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       224K  15.4G    96K  legacy
zroot/clones/b        0  15.4G    96K  legacy
zroot/clones/c        0  15.4G    96K  legacy
zroot/clones/d        0  15.4G    96K  legacy
zroot/clones/e     128K  15.4G    96K  legacy
zroot/clones/e@b     8K      -    96K  -
zroot/clones/e@c     8K      -    96K  -
zroot/clones/e@d     8K      -    96K  -
zroot/clones/e@e     8K      -    96K  -

Here goes the first clone.

zfs destroy -v zroot/clones/b
will destroy zroot/clones/b
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       224K  15.4G    96K  legacy
zroot/clones/c        0  15.4G    96K  legacy
zroot/clones/d        0  15.4G    96K  legacy
zroot/clones/e     128K  15.4G    96K  legacy
zroot/clones/e@b     8K      -    96K  -
zroot/clones/e@c     8K      -    96K  -
zroot/clones/e@d     8K      -    96K  -
zroot/clones/e@e     8K      -    96K  -

Now we rid us of the second clone.

zfs destroy -v zroot/clones/c
will destroy zroot/clones/c
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       224K  15.4G    96K  legacy
zroot/clones/d        0  15.4G    96K  legacy
zroot/clones/e     128K  15.4G    96K  legacy
zroot/clones/e@b     8K      -    96K  -
zroot/clones/e@c     8K      -    96K  -
zroot/clones/e@d     8K      -    96K  -
zroot/clones/e@e     8K      -    96K  -

And the third clone.

zfs destroy -v zroot/clones/d
will destroy zroot/clones/d
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       224K  15.4G    96K  legacy
zroot/clones/e     128K  15.4G    96K  legacy
zroot/clones/e@b     8K      -    96K  -
zroot/clones/e@c     8K      -    96K  -
zroot/clones/e@d     8K      -    96K  -
zroot/clones/e@e     8K      -    96K  -

To really reclaim disk space, the snapshots will have to go. Off with the first snapshot.

zfs destroy -v zroot/clones/e@b
will destroy zroot/clones/e@b
will reclaim 8K
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       216K  15.4G    96K  legacy
zroot/clones/e     120K  15.4G    96K  legacy
zroot/clones/e@c     8K      -    96K  -
zroot/clones/e@d     8K      -    96K  -
zroot/clones/e@e     8K      -    96K  -

Now the second snapshot.

zfs destroy -v zroot/clones/e@c
will destroy zroot/clones/e@c
will reclaim 8K
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       208K  15.4G    96K  legacy
zroot/clones/e     112K  15.4G    96K  legacy
zroot/clones/e@d     8K      -    96K  -
zroot/clones/e@e     8K      -    96K  -

The third snapshot.

zfs destroy -v zroot/clones/e@d
will destroy zroot/clones/e@d
will reclaim 8K
zfs list -rt all zroot/clones
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot/clones       200K  15.4G    96K  legacy
zroot/clones/e     104K  15.4G    96K  legacy
zroot/clones/e@e     8K      -    96K  -

And finally the fourth and last snapshot.

zfs destroy -v zroot/clones/e@e
will destroy zroot/clones/e@e
will reclaim 8K
zfs list -rt all zroot/clones
NAME             USED  AVAIL  REFER  MOUNTPOINT
zroot/clones     192K  15.4G    96K  legacy
zroot/clones/e    96K  15.4G    96K  legacy

As part of this exercise, we destroy the newest clone, which is now a truly independent dataset.

zfs destroy -v zroot/clones/e
will destroy zroot/clones/e
zfs list -rt all zroot/clones
NAME           USED  AVAIL  REFER  MOUNTPOINT
zroot/clones    96K  15.4G    96K  legacy

Let’s get rid of the sandbox as well.

zfs destroy -v zroot/clones
will destroy zroot/clones

Thank you, and good night.