Uncover the key differences between FreeBSD and Linux as we break down their features and use cases, helping users make well-informed decisions based on their specific requirements.
Basics of ZFS Snapshot Management
Basics of ZFS Snapshot Management
Let’s start with the basics: start with the basics: creating, using, and deleting file system snapshots.
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.
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.
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.
Like this article? Share it!
You might also be interested in
Getting expert FreeBSD advice is as easy as reaching out to us!
At Klara, we have an entire team dedicated to helping you with your FreeBSD projects. Whether you’re planning a FreeBSD project, or are in the middle of one and need a bit of extra insight, we’re here to help!
DTraceis a powerful tool for system administrators to diagnosis system issues without unduly impacting performance. DTrace became part of FreeBSD with the release of FreeBSD 7.1 in 2009—two years before Oracle began porting DTrace, and nine years before Oracle eventually solved the inherent CDDL vs GPL license conflict.
Pkgng became FreeBSD’s official package manager in FreeBSD 10 in 2014. Applications can be easily installed from either pkg—a system managing precompiled binary packages—or the ports tree, which automates building and installation of packages directly from their source code.