How to use file system snapshots in NetBSD

  1. Overview
  2. Persistent snapshots with fss(4)
    1. Example: Taking a snapshot
    2. Example: Recovering from a snapshot
    3. Example: Discarding a persistent snapshot
    4. Example: Single-use snapshot to take a backup
  3. External snapshots with fss(4)
    1. Example: Taking a snapshot
  4. zfs snapshots
    1. Example: Taking a snapshot
    2. Example: Recovering from a snapshot

Overview

A snapshot is a consistent view of a file system at a certain point in time. If you take a snapshot of a file system, and then create a new file or modify an existing one or make any other changes to the file system, and the snapshot will still have the old version of the file system without the changes. Unlike copies, snapshots don't take much extra space.

Snapshots are often used to take backups. For example, the dump(8) tool for dumping a file system backup can take a snapshot with the -x or -X options (q.v.) to ensure that files such as sqlite3 databases aren't concurrently modified while it is trying to read them. Snapshots can also be mounted like regular file systems to give read-only views of past states of file systems.

On some file systems—ffs and zfs—snapshots can be persistent: you can take a snapshot, and it will persist until it is explicitly deleted, even if the system is rebooted. Most other file systems only support external snapshots which don't persist past reboot.

Persistent snapshots with fss(4)

Persistent snapshots are currently supported for ffs file systems only—not to be confused with the fss file system snapshot device.

A persistent snapshot of a file system is represented by a regular file inside the file system, with a special flag (so it can't be read or written normally), and persists until the file is unlinked. This file is used as a backing store for the snapshot, to save any data overwritten later in the file system. Snapshots can be created with or loaded back into fss(4) devices in order to mount them. Active snapshots are managed with the fssconfig(8) command.

File systems may impose a limit on the number of snapshots that can be stored at any time. For ffs, this limit is 20.

Example: Taking a snapshot

To create and mount a persistent snapshot of the /home file system, via /dev/fss0:

# fssconfig fss0 /home /home/.snap/20260706.store
# mkdir /home/.snap/20260706
# mount /dev/fss0 /home/.snap/20260706

Users can then browse their home directories in /home/.snap as they existed at the time the snapshot was taken. There's nothing special about the directory name .snap; you can store snapshots anywhere in the file system.

The snapshot can be unmounted and unconfigured:

# umount /home/.snap/20260706
# fssconfig -u fss0

But the snapshot will persist at /home/.snap/20260706.store, even after a reboot, and can be configured and mounted again:

# fssconfig fss0 /home /home/.snap/20260706.store
# mount /dev/fss0 /home/.snap/20260706

Example: Recovering from a snapshot

If you made a mistake and need to recover from the snapshot, you can use, e.g., rsync (pkgsrc net/rsync) to revert files back to what they were in the snapshot:

# rsync -aHc --delete /home/.snap/20260706/bofh/. /home/bofh/.

It is better to use rsync rather than tar(1) for this purpose, in order to avoid writing unchanged content back to the file system, since that would take up space in the snapshot backing store.

Example: Discarding a persistent snapshot

When done with a snapshot, after unmounting and unconfiguring the fss(4), you can unlink the snapshot's backing store file to irrevocably discard it and free up any space it was using in the file system:

# umount /home/.snap/20260706
# fssconfig -u fss0
# rm /home/.snap/20260706

Example: Single-use snapshot to take a backup

You can also take a “persistent” snapshot of a file system and immediately unlink it while it is still configured. That way, any storage it uses will be released as soon as the fss(4) device is unconfigured, and (unlike for external fss(4) snapshots) you don't need any backing store outside the file system. For example, to take an anonymous persistent snapshot of the file system /var and mount it at /var/.snapshot:

# fssconfig fss3 /var /var/
# mkdir /var/.snapshot
# mount /dev/fss3 /var/.snapshot

Then you can take a backup of /var from the snapshot with your favourite backup archiving tool:

# tar -C /var/.snapshot -cf - . | ...
# tarsnap -C /var/.snapshot -cf var-20260706 .
# (cd /var/.snapshot && \
      borg create borghost:/path/to/repo::var-20260706 .)
# ssh rsynchost mkdir /backups/$(hostname)/var/20260706 &&
  rsync -aHc --link-dest=/backups/$(hostname)/var/latest/. \
      /var/.snapshot/. rsynchost:/backups/$(hostname)/var/. &&
  ssh rsynchost ln -sfn 20260706 /backups/$(hostname)/var/latest

(Note that if you use dump(8) and restore(8) for backups, dump(8) can automatically take a snapshot itself with the -x or -X option; you don't need to use fssconfig(8) at all.)

When the snapshot is unmounted and unconfigured, the backing store will automatically be discarded:

# umount /var/.snapshot
# fssconfig -u fss3

External snapshots with fss(4)

Any file system mounted from a disk device, such as ext2fs and msdosfs (but not tmpfs, not virtual file systems such as procfs or ptyfs, and not zfs), can have can have snapshots taken with fss(4).

A (non-persistent) fss(4) snapshot of a file system requires a backing store outside the file system, where any existing data in the file system will be saved if later overwritten while the snapshot is active. The backing store can be either a raw character disk device or a regular file in another file system.

Example: Taking a snapshot

To create a snapshot of the /boot directory, using a temporary file in /var/tmp for saving any data overwritten while the snapshot is active, and then mount it at /mnt:

# fssconfig fss1 /boot /var/tmp/
# mount /dev/fss1 /mnt

fssconfig(8) will create a temporary file with an unpredictable name in /var/tmp/ as the backing store for the snapshot, and immediately unlink it; it will be discarded when the snapshot is unconfigured.

A snapshot can also use a raw character disk device as the backing store:

# fssconfig fss1 /boot /dev/rld0e

When done, you can unmount the snapshot and unconfigure it:

# umount /mnt
# fssconfig -u fss1

zfs snapshots

In a zfs zpool, any dataset—a mountable file system or a zvol block device—can be snapshotted with the zfs snapshot command; see zfs(8) for details. The snapshots for a dataset <pool>/<datasetpath> are named <pool>/<datasetpath>@<snapname>. Datasets can be rolled back to a snapshot with zfs rollback, or cloned from a snapshot with zfs clone.

The snapshots of a file system are available as subdirectories of its .zfs/snapshot directory, at the root of the file system. The .zfs/ directory is hidden from directory listings by default, but it can be exposed with zfs set snapdir=visible <pool>/<fs>.

The snapshots of a zvol are available at /dev/zvol/dsk/<pool>/<zvol>@<snapname> (block device) and /dev/zvol/rdsk/<pool>/<zvol>@<snapname> (raw character device).

Example: Taking a snapshot

To create a snapshot of a dataset, and all datasets under it atomically:

# zfs snapshot -r rpool/home@20260706

The current state of /home will now be visible under /home/.zfs/snapshot/20260706. If you have a separate zfs file system for each user's home directory, the current state of jruser's home directory will be visible under /home/jruser/.zfs/snapshot/20260706 (NOTE: not under /home/.zfs/snapshot/20260706/jruser, which will just appear as an empty directory).

Example: Recovering from a snapshot

You can recover individual files from the .zfs/snapshot/<snapname>/ directory, but you can also roll back a whole file system to the latest snapshot with zfs rollback:

# zfs rollback rpool/home/jruser@20260706