ZFS: Snapshots and clones on zfs filesystems


ZFS: Snapshots and clones on zfs filesystems

# Tested on RHEL 6 & 7

# A snapshot is an only-read photograph of a filesystem. When taking a snapshot, it is
# stored in a way so further transactions on filesystem will only be carried out on origin
# filesystem and not on snapshot itself. This way it will be possible to get back to
# previous status by doing a "rollback"

# A clone is equivalent to a read-write copy of the snapshot

# Clones and snapshots are not data copies but state ones, so they don't use any space when
# created. It is when origin filesystem is modified when differences are being stored, thus
# consuming disk space. If a rollback is done, these differences are overwritten and space
# is freed-up again.

# Note: Clones may be created only from existing snapshots. First we take the "photo" of
# the origin filesystem and then we create the clone.

# Snapshots are very useful, for instance to carry out tests without being afraid of losing
# important data.



# Given following zfs

zfs list
   NAME           USED  AVAIL  REFER  MOUNTPOINT
   c_pool        2.15M  3.84G    19K  /c_pool
   c_pool/zfs01  2.02M  3.84G  2.02M  /zfs01   <---




# Create a snapshot from a ZFS
# ------------------------------------------------------------------------------------------

zfs snapshot c_pool/zfs01@snapshot01


zfs list -t all
   NAME                      USED  AVAIL  REFER  MOUNTPOINT
   c_pool                   2.50M  3.84G    19K  /c_pool
   c_pool/zfs01             2.02M  3.84G  2.02M  /zfs01
   c_pool/zfs01@snapshot01      0      -  2.02M  -         <---




# Rollback a ZFS to a previous state
# ------------------------------------------------------------------------------------------

# First we do some modifications on filesystem

cd /zfs01


dd if=/dev/urandom of=temp.file.01 bs=1M count=2
   2+0 records in
   2+0 records out
   2097152 bytes (2.1 MB) copied, 24.7394 s, 84.8 kB/s


dd if=/dev/urandom of=temp.file.02 bs=1M count=2
   2+0 records in
   2+0 records out
   2097152 bytes (2.1 MB) copied, 25.3346 s, 82.8 kB/s


ls -lrt
   total 4101
   -rw-r--r-- 1 root root 2097152 Feb  3 17:10 temp.file.01
   -rw-r--r-- 1 root root 2097152 Feb  3 17:11 temp.file.02


zfs list -t all
   NAME                      USED  AVAIL  REFER  MOUNTPOINT
   c_pool                   4.18M  3.84G    19K  /c_pool
   c_pool/zfs01             4.03M  3.84G  4.02M  /zfs01
   c_pool/zfs01@snapshot01     9K      -    19K  -
             <---- note the differences


# and then, rollback

zfs rollback c_pool/zfs01@snapshot01


zfs list -t all
   NAME                      USED  AVAIL  REFER  MOUNTPOINT
   c_pool                    176K  3.84G    19K  /c_pool
   c_pool/zfs01               20K  3.84G    19K  /zfs01
   c_pool/zfs01@snapshot01     1K      -    19K  -             <---


# files have disappeared:

ls -lrt
   total 0



# Remove a snapshot
# ------------------------------------------------------------------------------------------

zfs destroy c_pool/zfs01@snapshot01


zfs list -t all
   NAME           USED  AVAIL  REFER  MOUNTPOINT
   c_pool         174K  3.84G    19K  /c_pool
   c_pool/zfs01    19K  3.84G    19K  /zfs01




# To have different points of restoration, several snapshots may be taken at different times
# ------------------------------------------------------------------------------------------

dd if=/dev/urandom of=temp.file.00 bs=1M count=2
   2+0 records in
   2+0 records out
   2097152 bytes (2.1 MB) copied, 25.2053 s, 83.2 kB/s


ls -lrt
   total 2051
   -rw-r--r-- 1 root root 2097152 Feb  3 16:57 temp.file.00


zfs snapshot c_pool/zfs01@snapshot01


dd if=/dev/urandom of=temp.file.01 bs=1M count=2
   2+0 records in
   2+0 records out
   2097152 bytes (2.1 MB) copied, 25.9611 s, 80.8 kB/s


ls -lrt
   total 4101
   -rw-r--r-- 1 root root 2097152 Feb  3 16:57 temp.file.00
   -rw-r--r-- 1 root root 2097152 Feb  3 16:58 temp.file.01


zfs snapshot c_pool/zfs01@snapshot02


dd if=/dev/urandom of=temp.file.02 bs=1M count=2
   2+0 records in
   2+0 records out
   2097152 bytes (2.1 MB) copied, 25.5691 s, 82.0 kB/s


ls -lrt
   total 6152
   -rw-r--r-- 1 root root 2097152 Feb  3 16:57 temp.file.00
   -rw-r--r-- 1 root root 2097152 Feb  3 16:58 temp.file.01
   -rw-r--r-- 1 root root 2097152 Feb  3 16:59 temp.file.02



zfs list -t all
   NAME                      USED  AVAIL  REFER  MOUNTPOINT
   c_pool                   6.17M  3.84G    19K  /c_pool
   c_pool/zfs01             6.04M  3.84G  6.03M  /zfs01
   c_pool/zfs01@snapshot01     9K      -  2.02M  -
   c_pool/zfs01@snapshot02     9K      -  4.02M  -



# If we try to rollback to oldest snapshot:

zfs rollback c_pool/zfs01@snapshot01
   cannot rollback to 'c_pool/zfs01@snapshot01': more recent snapshots or bookmarks exist
   use '-r' to force deletion of the following snapshots and bookmarks:
   c_pool/zfs01@snapshot02


# If we need to rollback to first snapshot, first we have to rollback to the newer one,
# destroy it and, then, rollback to the oldest snapshot

zfs rollback c_pool/zfs01@snapshot02


ll
   total 4101
   -rw-r--r-- 1 root root 2097152 Feb  3 16:57 temp.file.00
   -rw-r--r-- 1 root root 2097152 Feb  3 16:58 temp.file.01


zfs rollback c_pool/zfs01@snapshot01
   cannot rollback to 'c_pool/zfs01@snapshot01': more recent snapshots or bookmarks exist
   use '-r' to force deletion of the following snapshots and bookmarks:
   c_pool/zfs01@snapshot02


zfs destroy c_pool/zfs01@snapshot02


zfs rollback c_pool/zfs01@snapshot01


ls -lrt
   total 2051
   -rw-r--r-- 1 root root 2097152 Feb  3 16:57 temp.file.00



# Otherwise, we could have used '-r' option to recursively rollback to desired snapshot.
# This will destroy all intermediate snapshots.

zfs rollback -r c_pool/zfs01@snapshot01



zfs list -t all
   NAME                      USED  AVAIL  REFER  MOUNTPOINT
   c_pool                   2.15M  3.84G    19K  /c_pool
   c_pool/zfs01             2.02M  3.84G  2.02M  /zfs01
   c_pool/zfs01@snapshot01     1K      -  2.02M  -




# Displaying snapshots
# ------------------------------------------------------------------------------------------

zfs list -t snapshot
   NAME                      USED  AVAIL  REFER  MOUNTPOINT
   c_pool/zfs01@snapshot01     1K      -  2.02M  -




# Accessing snapshot contents
# ------------------------------------------------------------------------------------------

# As long as zfs "snapdir" property is set to "visible", snapshot's contents should be
# accessible by entering ".zfs" directory under zfs's mount point.

# There should be one directory per snapshot containing directory/file structures existing
# at the moment snapshot was taken

zfs list -t all
   NAME                      USED  AVAIL  REFER  MOUNTPOINT
   c_pool                   8.15M  9.62G    19K  /c_pool
   c_pool/zfs01             8.05M  9.62G  8.03M  /zfs01
   c_pool/zfs01@snapshot01    10K      -  4.02M  -
   c_pool/zfs01@snapshot02    11K      -  6.03M  -


zfs get all  c_pool/zfs01 | grep snapdir
   c_pool/zfs01  snapdir               visible                local


cd /zfs01/.zfs/snapshot

ls -l
   total 1
   drwxr-xr-x. 2 root root 3 Feb  3 21:55 snapshot01
   drwxr-xr-x. 2 root root 4 Feb  3 21:55 snapshot02

# Each of the directories contains directory/file structures existing at the moment when
# snapshot was taken:

ls -lR
   .:
   total 1
   drwxr-xr-x. 2 root root 3 Feb  3 21:55 snapshot01
   drwxr-xr-x. 2 root root 4 Feb  3 21:55 snapshot02

   ./snapshot01:
   total 2051
   -rw-r--r--. 1 root root 2097152 Feb  3 21:51 temp.file.01

   ./snapshot02:
   total 4101
   -rw-r--r--. 1 root root 2097152 Feb  3 21:51 temp.file.01
   -rw-r--r--. 1 root root 2097152 Feb  3 21:55 temp.file.02


# I experienced some troubles while trying to access snapshot contents on virtual systems
# (both VMWare and Oracle VM VirtualBox virtual systems). For the moment, I'll let it drop
# because virtual servers are not the main target of this procedure.




# Cloning a snapshot
# ----------
--------------------------------------------------------------------------------

# Let's create one zpool, with one zfs and one snapshot

zpool create c_pool sdb sdc
zfs create -o mountpoint=/zfs01 c_pool/zfs01
cd /zfs01
dd if=/dev/urandom of=temp.file.00 bs=1M count=2
zfs snapshot c_pool/zfs01@snapshot01
dd if=/dev/urandom of=temp.file.01 bs=1M count=2


zfs list -t all
   NAME                      USED  AVAIL  REFER  MOUNTPOINT
   c_pool                   4.21M  3.84G    19K  /c_pool
   c_pool/zfs01             4.03M  3.84G  4.02M  /zfs01
   c_pool/zfs01@snapshot01     9K      -  2.02M  -


zfs clone c_pool/zfs01@snapshot01 c_pool/zfs02


# Snapshot c_pool/zfs01@snapshot01 has been copied and will be writeable on
# c_pool/zfs02 clone

zfs list -t all
   NAME                      USED  AVAIL  REFER  MOUNTPOINT
   c_pool                   4.22M  3.84G    19K  /c_pool
   c_pool/zfs01             4.03M  3.84G  4.02M  /zfs01
   c_pool/zfs01@snapshot01     9K      -  2.02M  -
   c_pool/zfs02                1K  3.84G  2.02M  /c_pool/zfs02


ls -lrt /zfs01
   total 4101
   -rw-r--r-- 1 root root 2097152 Feb  3 17:15 temp.file.00
   -rw-r--r-- 1 root root 2097152 Feb  3 17:15 temp.file.01


ls -lrt /c_pool/zfs02
   total 2051
   -rw-r--r-- 1 root root 2097152 Feb  3 17:15 temp.file.00


dd if=/dev/urandom of=/c_pool/zfs02/temp.file.02 bs=1M count=2
   2+0 records in
   2+0 records out
   2097152 bytes (2.1 MB) copied, 25.0426 s, 83.7 kB/s


ls -lrt /c_pool/zfs02
   total 4101
   -rw-r--r-- 1 root root 2097152 Feb  3 17:15 temp.file.00
   -rw-r--r-- 1 root root 2097152 Feb  3 17:17 temp.file.02


zfs list -t all
   NAME                      USED  AVAIL  REFER  MOUNTPOINT
   c_pool                   6.23M  3.84G    19K  /c_pool
   c_pool/zfs01             4.03M  3.84G  4.02M  /zfs01
   c_pool/zfs01@snapshot01     9K      -  2.02M  -
   c_pool/zfs02             2.01M  3.84G  4.02M  /c_pool/zfs02



# Removing a clone/snapshot
# ------------------------------------------------------------------------------------------

zfs destroy c_pool/zfs02


zfs list -t all
   NAME                      USED  AVAIL  REFER  MOUNTPOINT
   c_pool                   4.22M  3.84G    19K  /c_pool
   c_pool/zfs01             4.03M  3.84G  4.02M  /zfs01
   c_pool/zfs01@snapshot01     9K      -  2.02M  -


# Note: If a snapshot has one or more clones we won't be able to destroy it unless clones
#       are destroyed first:

zfs list -t all
   NAME                      USED  AVAIL  REFER  MOUNTPOINT
   c_pool                   4.23M  3.84G    19K  /c_pool
   c_pool/zfs01             4.03M  3.84G  4.02M  /zfs01
   c_pool/zfs01@snapshot01     9K      -  2.02M  -
   c_pool/zfs02                1K  3.84G  2.02M  /c_pool/zfs02


zfs destroy c_pool/zfs01@snapshot01
   cannot destroy 'c_pool/zfs01@snapshot01': snapshot has dependent clones
   use '-R' to destroy the following datasets:
   c_pool/zfs02


zfs destroy c_pool/zfs02

zfs destroy c_pool/zfs01@snapshot01

zfs list -t all
   NAME           USED  AVAIL  REFER  MOUNTPOINT
   c_pool        4.15M  3.84G    19K  /c_pool
   c_pool/zfs01  4.02M  3.84G  4.02M  /zfs01



# Promoting a clone
# ------------------------------------------------------------------------------------------

# Once a clone in place, we can use to replace original dataset. We will make clone
# independent of the snapshot it was created from and, then, remove snapshot(s) and
# origin filesystem so our clone will replace it


zfs list -t all
   NAME             USED  AVAIL  REFER  MOUNTPOINT
   c_pool          4.16M  3.84G    19K  /c_pool
   c_pool/product  4.02M  3.84G  4.02M  /product    <----


ll /product
   total 4101
   -rw-r--r-- 1 root root 2097152 Feb  3 17:15 temp.file.00
   -rw-r--r-- 1 root root 2097152 Feb  3 17:20 temp.file.01


zfs snapshot c_pool/product@snapshot01


zfs list -t all
   NAME                        USED  AVAIL  REFER  MOUNTPOINT
   c_pool                     4.16M  3.84G    19K  /c_pool
   c_pool/product             4.02M  3.84G  4.02M  /product
   c_pool/product@snapshot01      0      -  4.02M  -            <----


zfs clone -o mountpoint=/clone c_pool/product@snapshot01 c_pool/clone

zfs list -t all
   NAME                        USED  AVAIL  REFER  MOUNTPOINT
   c_pool                     4.19M  3.84G    19K  /c_pool
   c_pool/clone                  1K  3.84G  4.02M  /clone            <----
   c_pool/product             4.02M  3.84G  4.02M  /product
   c_pool/product@snapshot01      0      -  4.02M  -


# Make some modifications to clone (this is clone's purpose indeed)

vi /clone/mynewfile
   [...]


ll /product /clone
   /product:
   total 4101
   -rw-r--r-- 1 root root 2097152 Feb  3 17:15 temp.file.00
   -rw-r--r-- 1 root root 2097152 Feb  3 17:20 temp.file.01

   /clone:
   total 4102
   -rw-r--r-- 1 root root      20 Feb  3 17:23 mynewfile
   -rw-r--r-- 1 root root 2097152 Feb  3 17:15 temp.file.00
   -rw-r--r-- 1 root root 2097152 Feb  3 17:20 temp.file.01



# Promote the clone

zfs promote c_pool/clone



# Among other things, the existing snapshot becomes dependent of the clone that has been
# promoted.
# Take a look to new "USED" space value for the clone too (It's not a copy of the clone
# anymore but an independent dataset)

zfs list -t all
   NAME                        USED  AVAIL  REFER  MOUNTPOINT
   c_pool                     4.55M  3.84G    19K  /c_pool
   c_pool/clone               4.03M  3.84G  4.02M  /clone    <----
   c_pool/clone@snapshot01       9K      -  4.02M  -         <----
   c_pool/product                 0  3.84G  4.02M  /product


# If we try, for instance, to remove the promoted clone we won't be able because now
# it has a dependent snapshot:

zfs destroy c_pool/clone
   cannot destroy 'c_pool/clone': filesystem has children
   use '-r' to destroy the following datasets:
   c_pool/clone@snapshot01

# Should we need a current snapshot of promoted clone, we have to create a new one because
# the existing one is a snapshot from the original contents


# Now we are ready to replace the original dataset with the new one (promoted clone).
# Take into account that to be able to rename mountpoints (if needed) we'll have to
# remount the datasets

zfs rename c_pool/product c_pool/product.orig

zfs get all c_pool/product.orig | grep mountpoint
   c_pool/product.orig  mountpoint            /product                   local

zfs set mountpoint=/product.orig c_pool/product.orig

# On RHEL 7 F.S. has been already mounted so following two lines are not necessary:
mkdir /product.orig
zfs mount c_pool/product.orig

zfs list
   NAME                  USED  AVAIL  REFER  MOUNTPOINT
   c_pool               4.62M  3.84G    19K  /c_pool
   c_pool/clone         4.03M  3.84G  4.02M  /clone
   c_pool/product.orig     9K  3.84G  4.02M  /product.orig


zfs rename c_pool/clone c_pool/product

zfs set mountpoint=/product c_pool/product


# On RHEL 7 F.S. has been already mounted so following lines is not necessary:
zfs mount c_pool/product

zfs list -t all
   NAME                        USED  AVAIL  REFER  MOUNTPOINT
   c_pool                     4.24M  3.84G    19K  /c_pool
   c_pool/product             4.03M  3.84G  4.02M  /product
   c_pool/product@snapshot01     9K      -  4.02M  -
   c_pool/product.orig           9K  3.84G  4.02M  /product.orig


Article Number: 185
Posted: Sun, Jun 3, 2018 9:13 AM
Last Updated: Sun, Jun 3, 2018 9:13 AM

Online URL: http://kb.ictbanking.net/article.php?id=185