Friday, November 18, 2011

Solaris: zfs snapshot

ZFS is a great filesystem. Amongst its many features, it has snapshots. Let’s see how to use them.

What are snapshots ?

Snapshots are instant copies of your filesystem at a fixed past time. They are designed so that they are lightning fast to create, and they use a minimal amount of disk thanks to the COW (Copy On Write) optimization.
Basically, when you take a snapshot of a ZFS filesystem, only the filesystem structure is copied, not the file data blocks. Afterwards, anytime the data of a file is going to be modified, the data block is copied first the snapshot will reference the copy instead of the current data block. This is the Copy-On-Write.
The volume occupied by the snapshot is merely the volume of the data blocks which have been modified since the snapshot was taken.

Snapshots in ZFS

To create a snapshot, issue the following command :
prodigy# zfs snapshot poolName/fileSystem@labelName
You can see that the snapshot was taken with zfs list :
# zfs list
NAME                          USED  AVAIL  REFER  MOUNTPOINT
poolName                       5.63G   141G  27.5K  /poolName
poolName/fileSystem       2.97G   141G  1.92G  /poolName/fileSystem
poolName/fileSystem@label           0      -  1.92G  -
prodigy# 
To access the files of the snapshot, you can simply go in the .zfs/snapshot directory which is at the top level of your fileSystem. Take care, the .zfs directory is invisible by default.
At last, to delete the snapshot, simply use the zfs destroy command :
# zfs destroy poolName/fileSystem@label
# 

  • The following syntax creates recursive snapshots of all home directories in the tank/home file system. Then, you can use the zfs send -R command to create a recursive stream of the recursive home directory snapshot, which also includes the individual file system property settings.
# zfs snapshot -r tank/home@monday
# zfs send -R tank/home/@monday | ssh remote-system zfs receive -dvu pool

ZFS Clone

Clones can be only created from snapshot and they are actually new FS with initial content as original FS, so they are writable. 
# zfs list
NAME                       USED  AVAIL  REFER  MOUNTPOINT
mypool                    1.49G   527M   528M  /mypool
mypool/home                993M   527M    20K  /mypool/home
mypool/home/user1          993M   527M   993M  /mypool/home/user1
mypool/home/user1@Monday      0      -   993M  -

# zfs clone mypool/home/user1@Monday mypool/home/user2

# zfs list
NAME                       USED  AVAIL  REFER  MOUNTPOINT
mypool                    1.49G   527M   528M  /mypool
mypool/home                993M   527M    20K  /mypool/home
mypool/home/user1          993M   527M   993M  /mypool/home/user1
mypool/home/user1@Monday      0      -   993M  -
mypool/home/user2             0   527M   993M  /mypool/home/user2
Once clone is created from snapshot, the snapshot can not be deleted until clone exists.
# zfs get origin mypool/home/user2
NAME               PROPERTY  VALUE                      SOURCE
mypool/home/user2  origin    mypool/home/user1@Monday  -

# zfs destroy mypool/home/user1@Monday
cannot destroy 'mypool/home/user1@Monday': snapshot has dependent clones
use '-R' to destroy the following datasets:
mypool/home/user2

ZFS Snapshot

ZFS snapshot is read-only copy of the file system. 

When taken, it consumes no additional disk space, but when data changes, snapshot is growing since references to old data (unique to snapshot), so space cannot be freed. 

Let's take snapshot of FS mypool/home/user1. Snapshot name is Monday. So you can see what's command's syntax. 
# zfs snapshot mypool/home/user1@Monday

# zfs list
NAME                       USED  AVAIL  REFER  MOUNTPOINT
mypool                    1.49G   527M   528M  /mypool
mypool/home                993M   527M    20K  /mypool/home
mypool/home/user1          993M   527M   993M  /mypool/home/user1
mypool/home/user1@Monday      0      -   993M  -   (consumes no additional data within zpool)
You even cannot destroy FS if it has any snapshot.
# zfs destroy mypool/home/user1
cannot destroy 'mypool/home/user1': filesystem has children
use '-r' to destroy the following datasets:
mypool/home/user1@Monday
Let’s change some data and see now that used data of snapshot is growing.
# zfs list
NAME                       USED  AVAIL  REFER  MOUNTPOINT
mypool                    1.49G   527M   528M  /mypool
mypool/home                993M   527M    20K  /mypool/home
mypool/home/user1          993M   527M   993M  /mypool/home/user1
mypool/home/user1@Monday    28K      -   993M  -
Snapshot(s) is stored in hidden directory named .zfs/snapshot/, located in the root of FS. So you can go there and restore files if needed, remember it is read-only copy of FS.
# /mypool/home/user1/.zfs/snapshot> ls
total 3
dr-xr-xr-x   2 root     root           2 Nov 16 13:23 .
dr-xr-xr-x   3 root     root           3 Nov 16 13:23 ..
drwxr-xr-x   3 root     root           6 Nov 16 17:09 Monday
Beside restoring individual files from snapshot, you can roll back whole FS to previously taken snapshot.
# zfs list -t snapshot
NAME                       USED  AVAIL  REFER  MOUNTPOINT
mypool/home/user1@Monday   993M      -   993M  -

# zfs rollback mypool/home/user1@Monday
And all changes since snapshot Monday has been taken up to now are deleted and FS is same as it was on that Monday.