Klara

OpenZFS stands out in its snapshot design, providing powerful and easy-to-use tools for managing snapshots. Snapshots complement a backup strategy, as they are instantaneous and don’t require a backup window. Since snapshots are atomic, they are not affected by other processes and you don’t have to stop any running applications before taking a snapshot.

What exactly is a snapshot? zfs(8) defines it as a “Read-only version of a file system ... at a given point in time”. This is a powerful feature as there are many scenarios where it is convenient to access files from a certain point in time.

Imagine taking a snapshot of your home directory at the beginning of the work day, and perhaps another one after lunch. Need a copy of that file you deleted last Tuesday? No problem. Perhaps you’re considering updating an application but fear the pain of clobbered libraries. Need to test some configuration changes but don’t want to permanently muck up the system? Or perhaps you’re preparing for an operating system upgrade and want a quick way to revert to the pre-upgrade version should things go terribly wrong. Restoring data from a snapshot is quicker than restoring from a backup or waiting for a system administrator to restore a backup for you.

While snapshots do not replace backups, they provide a quick and convenient method for accessing files from a specific point in time.

The ability to access files from a certain point in time sounds great, but doesn’t that take a lot of storage space? Not necessarily. Because ZFS is a COW (copy-on-write) file system, the initial size of a snapshot is 0 bytes. Since snapshots record the differences between the time the snapshot was taken and the current state of the file system, the size of a snapshot increases over time, reflecting the size of the changes.

In this article we’ll start with the basics: creating, using, and deleting file system snapshots. Subsequent articles will demonstrate snapshot clones, rollback, and other advanced features of snapshots.

Creating a Snapshot

Since snapshot operations occur on a file system, rather than on the disks that comprise a pool, the zfs command is used to manage snapshots.

To create a snapshot, use the zfs snapshot subcommand. At its simplest, this command takes one argument: the name of the snapshot, where the @ symbol separates the name of the file system from the name of its snapshot. Think of it as specified-filesystem@named-point-in-time.

While you can name the snapshot portion anything that makes sense to you in order to describe why or when the snapshot was taken, you must use the full ZFS name for the file system. To list the available file systems, use zfs list. Here, I’m interested in determining the file system name for my home directory:

zfs list | grep dru
tank/usr/home/dru		2.65G	272G	2.64G	/usr/home/dru

Next, I’ll become the superuser and take a test snapshot of my home directory. I specify the file system exactly as it appears in the above listing (tank/usr/home/dru) and name the snapshot test1-snapshot:

su -
Password:
zfs snapshot tank/usr/home/dru@test1-snapshot

I can now list the new snapshot, along with any other existing snapshots, by specifying the snapshot type (-t):

zfs list -t snapshot
NAME							USED	AVAIL		REFER		MOUNTPOINT
tank/usr/home/dru@test1-snapshot	   	   0     -      2.64G		-

The initial size (USED) of the snapshot is 0, though it refers to the 2.64G worth of data shown in the previous file system listing. That size only grows as the "real" filesystem removes or changes data that the snapshot itself preserves in its original form.

The amount of writable disk space available (AVAIL) to the snapshot is not applicable as snapshots are read-only and the snapshot is not directly mounted.

A more useful snapshot name could be the hostname with the current date and time:

zfs snapshot tank/usr/home/dru@`hostname`_`date +%y%m%d%H%M`
zfs list -t snapshot
NAME							USED	AVAIL		REFER		MOUNTPOINT
tank/usr/home/dru@test1-snapshot	   	   0     -      2.64G		-
tank/usr/home/dru@myhostname_2104290946  0     -      2.64G	

Did you know?

Getting your ZFS infrastructure up to date has never been easier!

Our team provides consistent, expert advice tailored to your business.

Find out more

To give regular users the ability to snapshot their home directory without using sudo or su, assign them the snapshot permission. Take care to only assign permission for the specific file system. In this example, the root user allows dru permission to snapshot only her home directory:

zfs allow dru snapshot tank/usr/home/dru

su dru
zfs snapshot tank/usr/home/dru@permtest1
zfs list -t snapshot | grep permlist
tank/usr/home/dru@permtest1		  0	   -		2.64G		-

zfs snapshot tank/usr/home@permtest2
cannot create snapshots : permission denied

zfs snapshot tank@permtest3
cannot create snapshots : permission denied

This is working as expected: dru can now snapshot her home directory—but not any other user’s home directory, nor the pool named tank.

Creating a Recursive Snapshot

It is convenient for a system administrator to take a snapshot of an entire pool, especially before performing an operation such as an application install or an operating system upgrade. This method ensures the snapshots are of the exact same point-in-time on each filesystem. To accomplish this, the root user can specify the pool name and use the recursive (-r) switch:

zfs snapshot -r tank@testpool

This should yield a listing similar to this one:


zfs list -t snapshot | grep testpool
tank@testpool                                           0      -    88K  -
tank/ROOT@testpool                                      0      -    88K  -
tank/tmp@testpool                                       0      -  2.98M  -
tank/usr@testpool                                       0      -    88K  -
tank/usr/home@testpool                                  0      -    88K  -
tank/usr/home/dru@testpool                              0      -  2.64G  -
tank/usr/local@testpool                                 0      -    88K  -
tank/usr/local/share@testpool                           0      -    88K  -
tank/usr/local/share/doc@testpool                       0      -   344M  -
tank/usr/obj@testpool                                   0      -  6.41G  -
tank/usr/ports@testpool                                 0      -  9.00G  -
tank/usr/src@testpool                                   0      -  4.18G  -
tank/var@testpool                                       0      -    88K  -
tank/var/audit@testpool                                 0      -    88K  -
tank/var/log@testpool                                   0      -  22.4M  -
tank/var/mail@testpool                                  0      -   239M  -
tank/var/tmp@testpool                                   0      -  24.4M  -

Restoring Files from a Snapshot

As you can see, it is very easy to create a snapshot. But how do you access the files within that snapshot? If you just want to restore a few deleted files or grab the version of a file from a certain date, simply copy them from the snapshot’s hidden directory.

In this example, I’ll create two files in my home directory, with the intention of deleting one and modifying the other:

pwd
/usr/home/dru
cp .cshrc deleteme
cp .cshrc modifyme

If I make a snapshot now, it will include these 2 new files:

zfs snapshot tank/usr/home/dru@beforechanges

Next, I’ll delete the first file and overwrite the contents of the second file:

rm deleteme
echo oops > modifyme
more modifyme
oops

zfs diff can be used to list the differences between the time the /tank/usr/home/dru@beforechanges snapshot was taken and the current state of my home directory:

zfs diff tank/usr/home/dru@beforechanges
internal error: Invalid argument
Abort

This error occurred because the dru user account lacks sufficient permission to execute this command. Let’s have the root user assign the diff permission to dru for just her home directory, then try again:

su -
Password
zfs allow dru diff tank/usr/home/dru
exit
zfs diff tank/usr/home/dru@beforechanges
-	/usr/home/dru/deleteme
M	/usr/home/dru/modifyme

As expected, the - indicates that the deleteme file was deleted and the M indicates that the modifyme file was modified.

Now comes the exciting part. To view the snapshot version of those files, I specify the snapshot portion of the name when running the following commands. Both commands display the contents of my .cshrc file, the original source of the two files:

more ~/.zfs/snapshot/beforechanges/modifyme
more ~/.zfs/snapshot/beforechanges/deleteme

ZFS does something interesting here: by default, running ls -a in my home directory won’t show the hidden .zfs directory, but if I know it exists I can ls or cd into its directory structure. Every file system that has a snapshot will have this somewhat hidden directory. So, if I’m interested in the snapshots of my home directory, I look at the contents of ~/.zfs/snapshot.

Did you know?

Want to learn more about ZFS? We consistently write about the awesome powers of OpenZFS in our article series.

Read More >

Restoring the deleteme file from the beforechanges snapshot to my home directory is as simple as:

cp ~/.zfs/snapshot/beforechanges/deleteme ~

I might be a bit more careful in restoring the modified file so as not to overwrite the current version:

cp ~/.zfs/snapshot/beforechanges/modifyme ~/modifyme.orig

Note that we can use cp or similar commands like rsync to copy files, but not mv to move them. Using mv should fail as the move operation attempts to delete a file from the read-only snapshot:

mv ~/.zfs/snapshot/beforechanges/deleteme ~
mv: rename /home/dru/.zfs/snapshot/beforechanges/deleteme to /home/dru/deleteme: Read-only file system

Deleting a Snapshot

The rather scary sounding zfs destroy command is used to delete snapshots. In this example, I tried to remove the permtest1 snapshot after running the permissions test in the earlier example:

zfs destroy tank/usr/home/dru@permtest1
cannot destroy snapshots: permission denied

The superuser will need to assign me permission to mount and destroy on my home directory:

su -
Password:
zfs allow dru destroy,mount tank/usr/home/dru

exit
zfs destroy tank/usr/home/dru@permtest1

Time for a big cautionary note! The permission to destroy is automatically granted to the root user and can be assigned to other users. As the name suggests, this action is destructive. In this case, I destroyed a snapshot I no longer needed. When destroying snapshots, especially as the root user, make sure there is an @ in the name portion of the command. Otherwise, you are destroying the underlying file system! There is a big difference between tank/usr/home/dru and tank/usr/home/dru@permtest1.

You can determine the size benefit before deleting a snapshot by issuing a verbose (-v) dry run (-n):

zfs destroy -nv tank/usr/home/dru@beforechanges

would destroy tank/usr/home/dru@beforechanges
would reclaim 38.4M

This doesn’t actually delete the snapshot, but indicates that its deletion would free up 38.4M of space. In the example of the recursive snapshot taken by the root user, also adding the recursive (-r) switch shows the space used by all of the recursive snapshots:

zfs destroy -rnv tank@testpool
would destroytank@testpool                                           
would tank/ROOT@testpool                                      
would tank/tmp@testpool                                       
would tank/usr@testpool                                     
<SNIP>
would reclaim 42.3M

The root user could reclaim this space and remove all of the listed snapshots in one go by issuing the zfs destroy -r tank@testpool command.

Tips for Success

Get in the habit of taking a snapshot before performing any install or update operation or whenever you plan on making changes to files. It doesn’t cost anything time-wise and if it turns out you don’t need the snapshot, it’s just as quick to delete it.

While snapshots are trivial to create and start out at 0 bytes, they do grow in size over time. Get in the habit of listing your snapshots and removing any unneeded snapshots to free up space.

Topics / Tags
Back to Articles

Getting expert ZFS advice is as easy as reaching out to us!

At Klara, we have an entire team dedicated to helping you with your ZFS Projects. Whether you’re planning a ZFS project or are in the middle of one and need a bit of extra insight, we are here to help!