Problem
The FreeBSD 5 UFS2
filesystem provides the possibility to create
snapshots of life filesystems. It is already best
known (and can be easily used) for allowing fsck(8)
to run in the background
(see rc.conf variable background_fsck)
and for allowing to create consistent filesystem dumps (see
dump(8) option -L).
Additionally, with the help of md(4)
and mdconfig(8)
you can mount snapshots as read-only filesystems, too.
For illustration purposes, look at this sample session where a snapshot of
/tmp is created:
# echo "before" >/tmp/foo.txt
# ls -l /tmp/foo.txt
-rw-r--r-- 1 root wheel 7 Sep 3 09:48 /tmp/foo.txt
# test -d /tmp/.snap || mkdir /tmp/.snap
# mount -u -o snapshot /tmp/.snap/test /tmp
# ls -l /tmp/.snap/test
# echo "after" >/tmp/foo.txt
# ls -l /tmp/foo.txt
-rw-r--r-- 1 root wheel 7 Sep 3 09:48 /tmp/foo.txt
# mdconfig -a -t vnode -f /tmp/.snap/test -u 1
# mount -o ro /dev/md1 /mnt
# ls -l /mnt/foo.txt /tmp/foo.txt
-rw-r--r-- 1 root wheel 7 Sep 3 09:48 /mnt/foo.txt
-rw-r--r-- 1 root wheel 7 Sep 3 09:48 /tmp/foo.txt
# cat /mnt/foo.txt /tmp/foo.txt
before
after
# umount /mnt
# mdconfig -d -u 1
# rm -f /tmp/.snap/test
As you can see, one can easily create a snapshot and use it to
recover older states of files. Unfortunately, this is all which
currently is provided by FreeBSD out-of-the-box. There is neither an
easy way provided to regularily create new and expire old snapshots
nor an easy or even unpriviledged way to access the snapshot data.
Additionally, although the involved steps and commands are not too
complicated, they are not convenient enough for the daily work.
Keep in mind that regular filesystem backup snapshots are a great
solution for easily recovering old file states within a small time
frame. But only if the interface for the user follows the KISS
principle. And at least this is not the case under our FreeBSD until now.
On the other hand, at work my home directory is placed on an
NFS mounted WAFL filesystem provided by an ONTAP based Filer
from Network Appliance. For instance, after you have configured
scheduled snapshots with the ONTAP command "snap sched 0 0
4", you can easily recover old states (as a regular
user) in hourly steps for the last 4 hours:
$ echo "before" >foo.txt
$ sleep 3601
$ echo "middle" >foo.txt
$ sleep 3601
$ echo "after" >foo.txt
$ ls -la | grep .snapshot
$ cat .snapshot/hourly.1/foo.txt .snapshot/hourly.0/foo.txt foo.txt
before
middle
after
Solution
A similar service should be also provided to our users under FreeBSD, of course.
We achieve this by implementing three solutions:
- Convenience Administration Frontend
The involved commands should be wrapped by a frontend utility
snapshot(8) which provides a more simple and convenient way to
create, expire, mount and unmount snaphots.
# snapshot list /tmp
# snapshot make -g3 /tmp:test
# snapshot list /tmp
/tmp test.0
# snapshot make -g3 /tmp:test
# snapshot make -g3 /tmp:test
# snapshot list /tmp
/tmp test.0
/tmp test.1
/tmp test.2
# snapshot make -g3 /tmp:test
# snapshot make -g3 /tmp:test
# snapshot list /tmp
/tmp test.0
/tmp test.1
/tmp test.2
# snapshot mount /tmp:test.0 /mnt
# snapshot umount /mnt
# snapshot make -g0 /tmp:test
# snapshot list /tmp
- Periodic and Flexible Backup Snapshot Creation
There has to be a flexible and easy way to configure
periodically creasted backup snapshots. For instance to have available
two "daily" snapshots for / and /usr, two daily
and four hourly (created every hour) for
/var and two weekly, seven daily and 8 hourly (created at
times 08:00, 12:00, 16:00 and 20:00) snapshots for /home/ all
which is required should be (similar to the syntax of the ONTAP
"snap sched" command):
$ grep ^snapshot_ /etc/periodic.conf
snapshot_enable="YES"
snapshot_schedule="/,/usr:0:2:0 /var:0:2:4 /home:2:7:8@8,12,16,20"
- Easy Access to Backup Snapshot Data
There has to be an easy way to access the data of an arbitrary
backup snapshot as a regular user. Mostly similar to the
.snapshot sub-directory feature on WAFL (we use a
top-level /snap directly here because this is what
can be provided by amd(8) easily and without any performance
penalties and stability issues):
$ cd /home/rse
$ echo "before" >foo.txt
$ sleep 3601
$ echo "middle" >foo.txt
$ sleep 3601
$ echo "after" >foo.txt
$ cat /snap/home:hourly.1/rse/foo.txt /snap/home:hourly.0/rse/foo.txt foo.txt
before
after
middle
With those three solutions, FreeBSD UFS2 snapshots are also available to
our unprivileged users as a short-time backup solution
allowing an easy way to recover older file states.
Implementation
The implementation is straight-forward and based on mount(8), mdconfig(8), amd(8) and cron(8):
- Convenience Administration Frontend
First, I've implemented a little utility /usr/sbin/snapshot
(and corresponding manual page /usr/share/man/man8/snapshot.8)
which provides the convenience frontend for creating,
expiring, mounting and unmounting snapshots.
- Periodic and Flexible Backup Snapshot Creation
Second, I've implemented a periodic scheduler periodic-snapshot
(and corresponding manual page /usr/share/man/man8/periodic-snapshot.8) which is called from /etc/crontab (periodic(8)
cannot be used here because we need hourly runs and at exact
times to not confuse users) and runs the "snapshot
make" commands according to the configuration provided in
/etc/periodic.conf.
- Easy Access to Backup Snapshot Data
Third, I've setup a amd(8) map /etc/amd.map.snap
in /etc/rc.conf which
performs the "snapshot mount" and "snapshot
umount" commands when a user accesses directories under
/snap.
In order to easily integrate this implementation into
a FreeBSD 5-STABLE installation, download the latest tarball
here
and install it as following:
# tar zxf freebsd-snapshot-*.tar.gz
# cd freebsd-snapshot-*
# sh install.sh
References
See the following URLs for further details: