Working With ZFS Snapshots and Clones

This chapter describes how to create and manage ZFS snapshots and clones. Information about saving snapshots is also provided in this chapter.

The following sections are provided in this chapter:

Overview of ZFS Snapshots

A snapshot is a read-only copy of a file system or volume. Snapshots can be created almost instantly, and initially consume no additional disk space within the pool. However, as data within the active dataset changes, the snapshot consumes disk space by continuing to reference the old data and so prevents the space from being freed.

ZFS snapshots include the following features:

Snapshots of volumes cannot be accessed directly, but they can be cloned, backed up, rolled back to, and so on. For information about backing up a ZFS snapshot, see Saving and Restoring ZFS Data.

Creating and Destroying ZFS Snapshots

Snapshots are created by using the zfs snapshot command, which takes as its only argument the name of the snapshot to create. The snapshot name is specified as follows:

filesystem@snapname
volume@snapname

The snapshot name must satisfy the naming conventions defined in ZFS Component Naming Requirements.

In the following example, a snapshot of tank/home/ahrens that is named friday is created.

# zfs snapshot tank/home/ahrens@friday

You can create snapshots for all descendent file systems by using the -r option. For example:

# zfs snapshot -r tank/home@now
# zfs list -t snapshot
NAME                   USED  AVAIL  REFER  MOUNTPOINT
tank/home@now             0      -  29.5K  -
tank/home/ahrens@now      0      -  2.15M  -
tank/home/anne@now        0      -  1.89M  -
tank/home/bob@now         0      -  1.89M  -
tank/home/cindys@now      0      -  2.15M  -

Snapshots have no modifiable properties. Nor can dataset properties be applied to a snapshot.

# zfs set compression=on tank/home/ahrens@tuesday
cannot set compression property for 'tank/home/ahrens@tuesday': snapshot
properties cannot be modified

Snapshots are destroyed by using the zfs destroy command. For example:

# zfs destroy tank/home/ahrens@friday

A dataset cannot be destroyed if snapshots of the dataset exist. For example:

# zfs destroy tank/home/ahrens
cannot destroy 'tank/home/ahrens': filesystem has children
use '-r' to destroy the following datasets:
tank/home/ahrens@tuesday
tank/home/ahrens@wednesday
tank/home/ahrens@thursday

In addition, if clones have been created from a snapshot, then they must be destroyed before the snapshot can be destroyed.

For more information about the destroy subcommand, see Destroying a ZFS File System.

Renaming ZFS Snapshots

You can rename snapshots but they must be renamed within the pool and dataset from which they were created. For example:

# zfs rename tank/home/cindys@083006 tank/home/cindys@today

In addition, the following shortcut syntax provides equivalent snapshot renaming syntax as the example above.

# zfs rename tank/home/cindys@083006 today

The following snapshot rename operation is not supported because the target pool and file system name are different from the pool and file system where the snapshot was created.

# zfs rename tank/home/cindys@today pool/home/cindys@saturday
cannot rename to 'pool/home/cindys@today': snapshots must be part of same 
dataset

You can recursively rename snapshots with the zfs rename -r command. For example:

# zfs list
NAME                         USED  AVAIL  REFER  MOUNTPOINT
users                        270K  16.5G    22K  /users
users/home                    76K  16.5G    22K  /users/home
users/home@yesterday            0      -    22K  -
users/home/markm              18K  16.5G    18K  /users/home/markm
users/home/markm@yesterday      0      -    18K  -
users/home/marks              18K  16.5G    18K  /users/home/marks
users/home/marks@yesterday      0      -    18K  -
users/home/neil               18K  16.5G    18K  /users/home/neil
users/home/neil@yesterday       0      -    18K  -
# zfs rename -r users/home@yesterday @2daysago
# zfs list -r users/home
NAME                        USED  AVAIL  REFER  MOUNTPOINT
users/home                   76K  16.5G    22K  /users/home
users/home@2daysago            0      -    22K  -
users/home/markm             18K  16.5G    18K  /users/home/markm
users/home/markm@2daysago      0      -    18K  -
users/home/marks             18K  16.5G    18K  /users/home/marks
users/home/marks@2daysago      0      -    18K  -
users/home/neil              18K  16.5G    18K  /users/home/neil
users/home/neil@2daysago       0      -    18K  -

Displaying and Accessing ZFS Snapshots

Snapshots of file systems are accessible in the .zfs/snapshot directory within the root of the containing file system. For example, if tank/home/ahrens is mounted on /home/ahrens, then the tank/home/ahrens@thursday snapshot data is accessible in the /home/ahrens/.zfs/snapshot/thursday directory.

# ls /tank/home/ahrens/.zfs/snapshot
tuesday wednesday thursday

You can list snapshots as follows:

# zfs list -t snapshot
NAME                        USED  AVAIL  REFER  MOUNTPOINT
pool/home/anne@monday          0      -   780K  -
pool/home/bob@monday           0      -  1.01M  -
tank/home/ahrens@tuesday   8.50K      -   780K  -
tank/home/ahrens@wednesday 8.50K      -  1.01M  -
tank/home/ahrens@thursday      0      -  1.77M  -
tank/home/cindys@today     8.50K      -   524K  -

You can list snapshots that were created for a particular file system as follows:

# zfs list -r -t snapshot -o name,creation tank/home
NAME                       CREATION
tank/home@now               Wed Aug 30 10:53 2006
tank/home/ahrens@tuesday    Wed Aug 30 10:53 2006
tank/home/ahrens@wednesday  Wed Aug 30 10:54 2006
tank/home/ahrens@thursday   Wed Aug 30 10:53 2006
tank/home/cindys@now        Wed Aug 30 10:57 2006

Snapshot Space Accounting

When a snapshot is created, its space is initially shared between the snapshot and the file system, and possibly with previous snapshots. As the file system changes, space that was previously shared becomes unique to the snapshot, and thus is counted in the snapshot's used property. Additionally, deleting snapshots can increase the amount of space unique to (and thus used by) other snapshots.

A snapshot's space referenced property is the same as the file system's was when the snapshot was created.

Rolling Back to a ZFS Snapshot

The zfs rollback command can be used to discard all changes made since a specific snapshot. The file system reverts to its state at the time the snapshot was taken. By default, the command cannot roll back to a snapshot other than the most recent snapshot.

To roll back to an earlier snapshot, all intermediate snapshots must be destroyed. You can destroy earlier snapshots by specifying the -r option.

If clones of any intermediate snapshots exist, the -R option must be specified to destroy the clones as well.

The file system that you want to roll back must be unmounted and remounted, if it is currently mounted. If the file system cannot be unmounted, the rollback fails. The -f option forces the file system to be unmounted, if necessary.

In the following example, the tank/home/ahrens file system is rolled back to the tuesday snapshot:

# zfs rollback tank/home/ahrens@tuesday
cannot rollback to 'tank/home/ahrens@tuesday': more recent snapshots exist
use '-r' to force deletion of the following snapshots:
tank/home/ahrens@wednesday
tank/home/ahrens@thursday
# zfs rollback -r tank/home/ahrens@tuesday

In the above example, the wednesday and thursday snapshots are removed because you rolled back to the previous tuesday snapshot.

# zfs list -r -t snapshot -o name,creation tank/home/ahrens
NAME                      CREATION
tank/home/ahrens@tuesday  Wed Aug 30 10:53 2006

Overview of ZFS Clones

A clone is a writable volume or file system whose initial contents are the same as the dataset from which it was created. As with snapshots, creating a clone is nearly instantaneous, and initially consumes no additional disk space. In addition, you can snapshot a clone.

Clones can only be created from a snapshot. When a snapshot is cloned, an implicit dependency is created between the clone and snapshot. Even though the clone is created somewhere else in the dataset hierarchy, the original snapshot cannot be destroyed as long as the clone exists. The origin property exposes this dependency, and the zfs destroy command lists any such dependencies, if they exist.

Clones do not inherit the properties of the dataset from which it was created. Use the zfs get and zfs set commands to view and change the properties of a cloned dataset. For more information about setting ZFS dataset properties, see Setting ZFS Properties.

Because a clone initially shares all its disk space with the original snapshot, its used property is initially zero. As changes are made to the clone, it uses more space. The used property of the original snapshot does not consider the disk space consumed by the clone.

Creating a ZFS Clone

To create a clone, use the zfs clone command, specifying the snapshot from which to create the clone, and the name of the new file system or volume. The new file system or volume can be located anywhere in the ZFS hierarchy. The type of the new dataset (for example, file system or volume) is the same type as the snapshot from which the clone was created. You cannot create clone of a file system in a pool that is different from where the original file system snapshot resides.

In the following example, a new clone named tank/home/ahrens/bug123 with the same initial contents as the snapshot tank/ws/gate@yesterday is created.

# zfs snapshot tank/ws/gate@yesterday
# zfs clone tank/ws/gate@yesterday tank/home/ahrens/bug123

In the following example, a cloned workspace is created from the projects/newproject@today snapshot for a temporary user as projects/teamA/tempuser. Then, properties are set on the cloned workspace.

# zfs snapshot projects/newproject@today
# zfs clone projects/newproject@today projects/teamA/tempuser
# zfs set sharenfs=on projects/teamA/tempuser
# zfs set quota=5G projects/teamA/tempuser

Destroying a ZFS Clone

ZFS clones are destroyed by using the zfs destroy command. For example:

# zfs destroy tank/home/ahrens/bug123

Clones must be destroyed before the parent snapshot can be destroyed.

Replacing a ZFS File System With a ZFS Clone

You can use the zfs promote command to replace an active ZFS file system with a clone of that file system. This feature facilitates the ability to clone and replace file systems so that the “origin” file system become the clone of the specified file system. In addition, this feature makes it possible to destroy the file system from which the clone was originally created. Without clone promotion, you cannot destroy a “origin” file system of active clones. For more information about destroying clones, see Destroying a ZFS Clone.

In the following example, the tank/test/productA file system is cloned and then the clone file system, tank/test/productAbeta becomes the tank/test/productA file system.

# zfs create tank/test
# zfs create tank/test/productA
# zfs snapshot tank/test/productA@today
# zfs clone tank/test/productA@today tank/test/productAbeta
# zfs list -r tank/test
NAME                   USED  AVAIL  REFER  MOUNTPOINT
tank/test              314K  8.24G  25.5K  /tank/test
tank/test/productA     288K  8.24G   288K  /tank/test/productA
tank/test/productA@today      0      -   288K  -
tank/test/productAbeta      0  8.24G   288K  /tank/test/productAbeta
# zfs promote tank/test/productAbeta
# zfs list -r tank/test
NAME                   USED  AVAIL  REFER  MOUNTPOINT
tank/test              316K  8.24G  27.5K  /tank/test
tank/test/productA        0  8.24G   288K  /tank/test/productA
tank/test/productAbeta   288K  8.24G   288K  /tank/test/productAbeta
tank/test/productAbeta@today      0      -   288K  -

In the above zfs -list output, you can see that the space accounting of the original productA file system has been replaced with the productAbeta file system.

Complete the clone replacement process by renaming the file systems. For example:

# zfs rename tank/test/productA tank/test/productAlegacy
# zfs rename tank/test/productAbeta tank/test/productA
# zfs list -r tank/test
NAME                   USED  AVAIL  REFER  MOUNTPOINT
tank/test              316K  8.24G  27.5K  /tank/test
tank/test/productA     288K  8.24G   288K  /tank/test/productA
tank/test/productA@today      0      -   288K  -
tank/test/productAlegacy      0  8.24G   288K  /tank/test/productAlegacy

Optionally, you can remove the legacy file system. For example:

# zfs destroy tank/test/productAlegacy

Saving and Restoring ZFS Data

The zfs send command creates a stream representation of a snapshot that is written to standard output. By default, a full stream is generated. You can redirect the output to a file or to a different system. The zfs receive command creates a snapshot whose contents are specified in the stream that is provided on standard input. If a full stream is received, a new file system is created as well. You can save ZFS snapshot data and restore ZFS snapshot data and file systems with these commands. See the examples in the next section.

The following solutions for saving ZFS data are provided:

Consider the following when choosing a solution for saving ZFS data:

Saving ZFS Data With Other Backup Products

In addition to the zfs send and zfs receive commands, you can also use archive utilities, such as tar(1) and cpio(1), to save ZFS files. All of these utilities save and restore ZFS file attributes and ACLs. Check the appropriate options for the tar and cpio commands.

For up-to-date information about issues with ZFS and third-party backup products, please see the Solaris Express Developer Edition release notes.

http://opensolaris.org/os/community/zfs/faq/#backupsoftware

Saving a ZFS Snapshot

The most common use of the zfs send command is to save a copy of a snapshot and receive the snapshot on another system that is used to store backup data. For example:

host1# zfs send tank/dana@snap1 | ssh host2 zfs recv newtank/dana

When sending a full stream, the destination file system must not exist.

You can save incremental data by using the zfs send -i option. For example:

host1# zfs send -i tank/dana@snap1 tank/dana@snap2 | ssh host2 zfs recv newtank/dana

Note that the first argument is the earlier snapshot and the second argument is the later snapshot. In this case, the newtank/dana file system must exist for the incremental receive to be successful.

The incremental snapshot1 source can be specified as the last component of the snapshot name. This shortcut means you only have to specify the name after the @ sign for snapshot1, which is assumed to be from the same file system as snapshot2. For example:

host1# zfs send -i snap1 tank/dana@snap2 > ssh host2 zfs recv newtank/dana

This syntax is equivalent to the above example of the incremental syntax.

The following message is displayed if you attempt to generate an incremental stream from a different file system snapshot1:

cannot send 'pool/fs@name': not an earlier snapshot from the same fs

If you need to store many copies, you might consider compressing a ZFS snapshot stream representation with the gzip command. For example:

# zfs send pool/fs@snap | gzip > backupfile.gz

Restoring a ZFS Snapshot

Keep the following key points in mind when you restore a file system snapshot:

For example:

# zfs send tank/gozer@0830 > /bkups/gozer.083006
# zfs receive tank/gozer2@today < /bkups/gozer.083006
# zfs rename tank/gozer tank/gozer.old
# zfs rename tank/gozer2 tank/gozer

You can use zfs recv as an alias for the zfs receive command.

If you make a change to the file system and you want to do another incremental send of a snapshot, you must first rollback the receiving file system.

For example, if you make a change to the file system as follows:

host2# rm newtank/dana/file.1

And you do an incremental send of tank/dana@snap3, you must first rollback the receiving file system to receive the new incremental snapshot. You can eliminate the rollback step by using the -F option. For example:

host1# zfs send -i tank/dana@snap2 tank/dana@snap3 | ssh host2 zfs recv -F newtank/dana

When you receive an incremental snapshot, the destination file system must already exist.

If you make changes to the file system and you do not rollback the receiving file system to receive the new incremental snapshot or you do not use the -F option, you will see the following message:

host1# zfs send -i tank/dana@snap4 tank/dana@snap5 | ssh host2 zfs recv newtank/dana
cannot receive: destination has been modified since most recent snapshot

The following checks are performed before the -F option is successful:

Sending and Receiving Complex ZFS Snapshot Streams

This section describes how to use the zfs send -I and -R options to send and receive more complex snapshot streams.

Examples—Sending and Receiving Complex ZFS Snapshot Streams

A group of incremental snapshots can be combined into one snapshot by using the zfs send -I option. For example:

# zfs send -I pool/fs@snapA pool/fs@snapD > /snaps/fs@all-I

Remove snapshots B, C, and D.

# zfs destroy pool/fs@snapB
# zfs destroy pool/fs@snapC
# zfs destroy pool/fs@snapD

Restore the combined snapshot.

# zfs receive -d -F pool/fs < /snaps/fs@all-I
# zfs list
NAME                      USED  AVAIL  REFER  MOUNTPOINT
pool                      428K  16.5G    20K  /pool
pool/fs                    71K  16.5G    21K  /pool/fs
pool/fs@snapA              16K      -  18.5K  -
pool/fs@snapB              17K      -    20K  -
pool/fs@snapC              17K      -  20.5K  -
pool/fs@snapD                0      -    21K  -

You can also use the zfs send -I command to combine a snapshot and a clone snapshot to create a combined dataset. For example:

# zfs create pool/fs
# zfs snapshot pool/fs@snap1
# zfs clone pool/fs@snap1 pool/clone
# zfs snapshot pool/clone@snapA
# zfs send -I pool/fs@snap1 pool/clone@snapA > /snaps/fsclonesnap-I
# zfs destroy pool/clone@snapA
# zfs destroy pool/clone
# zfs receive -F pool/clone < /snaps/fsclonesnap-I

Use the zfs send -R command to replicate a ZFS file system and all descendent file systems, up to the named snapshot. When received, all properties, snapshots, descendent file systems, and clones are preserved.

In the following example, snapshots are created of user file systems. One replication stream is created of all user snapshots. Then, the original file systems and snapshots are destroyed and recovered.

# zfs snapshot -r users@today
# zfs list
NAME                USED  AVAIL  REFER  MOUNTPOINT
users               187K  33.2G    22K  /users
users@today            0      -    22K  -
users/user1          18K  33.2G    18K  /users/user1
users/user1@today      0      -    18K  -
users/user2          18K  33.2G    18K  /users/user2
users/user2@today      0      -    18K  -
users/user3          18K  33.2G    18K  /users/user3
users/user3@today      0      -    18K  -
# zfs send -R users@today > /snaps/users-R
# zfs destroy -r users
# zfs receive -F -d users < /snaps/users-R
# zfs list
NAME                USED  AVAIL  REFER  MOUNTPOINT
users               196K  33.2G    22K  /users
users@today            0      -    22K  -
users/user1          18K  33.2G    18K  /users/user1
users/user1@today      0      -    18K  -
users/user2          18K  33.2G    18K  /users/user2
users/user2@today      0      -    18K  -
users/user3          18K  33.2G    18K  /users/user3
users/user3@today      0      -    18K  -

You can use the zfs send R command to replicate the users dataset and its descendents and send the replicated stream to another pool, users2.

# zfs create users2 mirror c0t1d0 c1t1d0
# zfs receive -F -d users2 < /snaps/users-R
# zfs list
NAME                 USED  AVAIL  REFER  MOUNTPOINT
users                224K  33.2G    22K  /users
users@today             0      -    22K  -
users/user1           33K  33.2G    18K  /users/user1
users/user1@today     15K      -    18K  -
users/user2           18K  33.2G    18K  /users/user2
users/user2@today       0      -    18K  -
users/user3           18K  33.2G    18K  /users/user3
users/user3@today       0      -    18K  -
users2               188K  16.5G    22K  /users2
users2@today            0      -    22K  -
users2/user1          18K  16.5G    18K  /users2/user1
users2/user1@today      0      -    18K  -
users2/user2          18K  16.5G    18K  /users2/user2
users2/user2@today      0      -    18K  -
users2/user3          18K  16.5G    18K  /users2/user3
users2/user3@today      0      -    18K  -

Remote Replication of ZFS Data

You can use the zfs send and zfs recv commands to remotely copy a snapshot stream representation from one system to another system. For example:

# zfs send tank/cindy@today | ssh newsys zfs recv sandbox/restfs@today

This command saves the tank/cindy@today snapshot data and restores it into the sandbox/restfs file system and also creates a restfs@today snapshot on the newsys system. In this example, the user has been configured to use ssh on the remote system.