ZFS offers many interesting features, and one of the most widely used is the ability to create and transfer snapshots of entire datasets, even recursively. This approach is useful for backups or maintaining a specific “point in time” for datasets. For example, on FreeBSD, automatic snapshots of the dataset containing the root file system have been taken with each system upgrade for several releases. This way, thanks to Boot Environments, if there are any problems, it is possible to reboot from a previous clone.
However, sometimes we might need something more. Local snapshots do not protect against the deletion of entire datasets or the activation of new features that could potentially cause problems or incompatibilities.
A very useful tool that I have successfully used for some time is the pool checkpoint feature. This feature, imported from Illumos to FreeBSD in 2018, allows creating a sort of snapshot of the entire pool, including features, metadata, etc.
The checkpoint is different from snapshots of individual datasets. It is not possible to have more than one checkpoint, and some operations like remove
, attach
, detach
, split
, and reguid
will be impossible when a checkpoint exists. This also has a side effect: if there is a checkpoint, deleting a dataset will not release free space because the data will still be physically present in the storage thanks to the checkpoint.
Additionally, checkpoints are detected by the FreeBSD boot loader. When booting the system, the boot loader will offer the option to perform a "Rewind ZFS checkpoint" and boot from that point, effectively discarding everything that occurred after the checkpoint. This option can be particularly useful in emergencies or when you need to quickly undo recent changes.
Creating a checkpoint is very simple. Just use the command:
zpool checkpoint <pool>
The operation is usually quick. When a checkpoint is present, the command zpool status
will show its details. For example:
pool: zroot
state: ONLINE
scan: scrub repaired 0B in 00:00:12 with 0 errors on Fri May 17 13:27:14 2024
checkpoint: created Sun Jun 30 12:30:51 2024, consumes 1.34M
config:
NAME STATE READ WRITE CKSUM
zroot ONLINE 0 0 0
ada1p4 ONLINE 0 0 0
errors: No known data errors
To delete the checkpoint, you can use the command:
zpool checkpoint -d <pool>
To rollback state to checkpoint and remove the checkpoint:
zpool import --rewind-to-checkpoint <pool>
To mount the pool read only (without rolling back the data):
zpool import --read-only=on --rewind-to-checkpoint <pool>
It is therefore possible to generate a checkpoint automatically via cron or manually when necessary, for example, before an operating system upgrade.
For more technical details, I suggest reading this excellent article by Serapheim Dimitropoulos, published in the FreeBSD Journal in January 2019.