First of all I feel bad, because I promised John Goerzen to share my experiences, but as with other things I am lagging behind.
Still better late than never.

A few words on rsnapshot

rsnapshot is a great tool for making efficient backups. It basically creates directories like

daily.0
daily.1
daily.2
daily.3
...
daily.6

The directory contents are hard linked on each other and then it is overwritten when the contents (files) are changed.

The way this is achived is by cp -al daily.0 daily.1 then rsync-ing the fresh content to the pre-populated directories. Sometimes rm -rf daily.N (where N is the number of days you want to keep) is run remove old content. (For simplicity I do not talk about weekly and monthly features of rsnapshot).

There is also a rollback mechanism in place if the backup fail to get the last consistent state for the next run as a base.

The problem is that cp -al and rm -rf and the rollback mechanism itself is an expensive operation and does not use the possibilities of ZFS.

ZFS snapshots

ZFS have a convenient way to create snapshots of datasets which are consistent point-in-time state of the filesystem. The snapshots are read-only, mountable and almost free with zfs. As ZFS is a copy-on-write filesystem when you modify a file it is copied first and when you have a snapshot the original is kept after it is changed. Only the changed content takes space.

ZFS and rsnapshot

I choose an easy and convenient way to integrate the ZFS snapshotting from rsnapshot some may call it a hack.

There is a cmd_cp configuration parameter and I wrote the script that does the job for me:

#!/usr/local/bin/bash

#echo "snapshot created at $(date)" > $2/info

# name of the volume
zname=$(dirname $(echo $2 | cut -b 2-))

# name of the future snapshot
bsname="$zname@rsnap-$(date +%F)"

sname=$bsname
for i in 1 2 3 4 5
do
  # exit if success
  zfs snapshot $sname 
  if [ "x$?" == "x0" ]; then
    echo "backup started at $(date)" > $2/info
    exit 0
  fi
  # iterate over it if already exists
  sname=$bsname-v$i
done

echo ERROR zfs_cp: something is really broken
exit 1

So every rsnapshot directory is a seperate dataset and when the rsnapshot starts the tedius work and of running cp is eliminated. I will always only have daily.0 there never will be a daily.1 as my script never creates it. This way the rm -rf and the rollback part is also eliminated as there is nothing to delete and nothing to rollback to. If a backup does not complete for one reason or another the next one supposed to correct it.

One thing that is missing: Eliminating and removing of old snapshots. I to keep the 7 recent backup then keeping 4 weekly is fine and 6 monthly. There are tools available to do that I need to look at that.

zfs list -t all sniplet:

NAME                                                  USED  AVAIL  REFER  MOUNTPOINT
...
backup14q1/rsnapshot_1                               1.85T  15.6T  1.45T  /backup14q1/rsnapshot_1
backup14q1/rsnapshot_1@rsnap-2014-01-08              5.38G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-09              3.82G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-10              3.82G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-11              4.06G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-12              3.86G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-13              5.72G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-14              3.89G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-15              3.90G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-15-v1           3.66G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-17              3.89G      -  1.45T  -
...
backup14q1/rsnapshot_1@rsnap-2014-02-12              4.21G      -  1.45T  -
backup14q1/rsnapshot_1@rsnap-2014-02-13              4.19G      -  1.45T  -

Summary

Some features of rsnapshot like:

  • weekly, monthly snapshots
  • rollback in case of failures

are lost in the process, but overall I am satisfied with the end results. Further improvements are possible.