Securing ZFS data by mirroring them

This article is a follow-up of an earlier post about ZFS on FreeBSD. We have created a ZFS pool with one disk and put some data on it. Now we want to mirror the data to safeguard them from disk failure.

In my virtual machine I created a new disk of the same size than previous ZFS dedicated disk and fire-up the machine.

Creating a dataset with 2 internal copies for each file

But before I added the second disk, I decided to create a dataset (of the file system type) inside the pool I have created in previous article. The dataset will be configured to replicate internally the data for safety. This is an entirely optional step which I did just to experiment with ZFS.

The reader should notice that my pool had only 1 drive which means that each file in this dataset will appear twice on the same drive. If the drive fails, everything is lost. It just help if one version of the file gets corrupted, ZFS will detect it and use the (hopefully) uncorrupted copy to restore the file.

# zfs create -o copies=2 laug/safe

Note about: mirror/striped pools and dataset copies

Dataset copies are in addition to any pool configuration such as mirroring or RAID-Z. In case of a stripped pool (the case if you use zpool add command), ZFS will try to use different disks in the pool for each copy, if it can! In case of mirrors (the case if you use zpool attach command) or RAID-Z, in addition to the pool duplication of data, ZFS will try to keep extra copies on different drives.

Preparing the second ZFS drive and adding it as a mirror to the existing pool

As the hard disk is exactly of the same size (same disk space and number of sectors) I can reuse the commands from the previous articles:

gpart create -s gpt ada2
gpart add -b 2048 -s 41932733 -t freebsd-zfs -l disk01 ada2

But now we are going to add the new disk to the existing pool in a mirror configuration. For this we use zpool attach:

# zpool attach laug ada1p1 ada2p1
# zpool status
  pool: laug
 state: ONLINE
 scan: resilvered 1.37M in 0h0m with 0 errors on Tue Jul 31 18:16:43 2012
config:

        NAME        STATE     READ WRITE CKSUM
        laug        ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            ada1p1  ONLINE       0     0     0
            ada2p1  ONLINE       0     0     0

errors: No known data errors

As I don’t have much data on my pool, the resilvering was fast (see the scan message). In addition, one can see that the 2 disk partitions are now inside a mirror.

I really like ZFS, the command line interface is clean, it is easy to manage and it is powerful.

ZFS on FreeBSD 9

I have created a VM with 2 hard disks. Did a standard installation of FreeBSD on the first hard disk (ada0) and decided to play around with ZFS on the second hard disk.

First of all, I destroyed any existing partitions on the second disk (warning the next command is dangerous, it will destroy all the data on the hard disk):

# gpart destroy -F ada1

I then went on to create a ZFS partition and pool. Note: I did not use the full disk size, in case I want to switch to RAID*. A prerequisite for ZFS in this case is that any newer disk should be at least the same size of the existing ones. This is not guaranteed by hard disk manufacturers that two 2TB hard disks have the same exact size.

# gpart create -s gpt ada1
# gpart show ada1
=>      34  41942973  ada1  GPT  (20G)
        34  41942973        - free -  (20G)
# camcontrol identify ada1
...
protocol              ATA/ATAPI-6 SATA 2.x
device model          VBOX HARDDISK
...
sector size logical 512, physical 512, offset 0
DMA supported         WDMA2 UDMA6

The 2 last commands gave me the partition size and sector size (in bold). I use this information to leave a bit of space after the ZFS partition. In addition, it is recommended to try to align the partitions to the sectors correctly. When using a physical hard disk for which you know the real sector size (note: sometimes the hardware is lying to you, which is the case of the 4K 512e HDD!!) you can directly use the corresponding alignment (i.e. 512 or 4k), but when using virtual HDD either as files (e.g. vdi, qcow2, etc.) or partitions (e.g. an LVM logical volume), it is better to use a 1MB aligment (1m), so adapt the “-a” option in the following command.

# gpart add -b 2048 -s 41932733 -a 1m -t freebsd-zfs -l disk00 ada1
ada1p1 added
# gpart show ada1
=>      34  41942973  ada1  GPT  (20G)
        34      2014        - free -  (1M)
      2048  41932733     1  freebsd-zfs  (20G)
  41934781      8226        - free -  (4.0M)

# zpool create laug ada1p1
# zfs set compression=lzjb laug
# zpool status
  pool: laug
 state: ONLINE
 scan: none requested
config:

        NAME        STATE     READ WRITE CKSUM
        laug        ONLINE       0     0     0
          ada1p1    ONLINE       0     0     0

errors: No known data errors
# df -Th
Filesystem   Type     Size    Used   Avail Capacity  Mounted on
/dev/ada0p2  ufs       18G    2.6G     14G    15%    /
devfs        devfs    1.0k    1.0k      0B   100%    /dev
laug         zfs       19G     31k     19G     0%    /laug

Et voilà, a nice ZFS pool which is using compression (lzjb algorithm).