Native ZFS on Linux

One of the interface layers available in the ZFS on Linux port is the ZVOL. The ZVOL layer allows you to create a virtual block device in a ZFS storage pool. While this may not immediately seem like a big deal it does open up some interesting possibilities. For example, your virtual block device is now backed by whatever level of ZFS data replication you like (mirror, raidz, raidz2, etc) all with online scrubbing. Your virtual block device also has fast snapshots due to ZFS’s copy on write transaction model. This allows you do some interesting things like format an ext2 file system which uses a ZVOL based block device and mount it on your system. Here’s an example how.

Create the tank zpool containing a raidz vdev spread over 3 devices. It is recommended that you use the persistent /dev/disk/by-id/* device names when creating your pool to avoid any device reordering issues latter. Your device names will of course be different.

$ sudo zpool create tank raidz scsi-SATA_Maxtor_7Y250M0_Y638RXME
  scsi-SATA_Maxtor_7Y250M0_Y638S56E scsi-SATA_Maxtor_7Y250M0_Y638TJFE
$ sudo zpool status tank
  pool: tank
 state: ONLINE
  scan: none requested

        NAME                                   STATE     READ WRITE CKSUM
        tank                                   ONLINE       0     0     0
          raidz1-0                             ONLINE       0     0     0
            scsi-SATA_Maxtor_7Y250M0_Y638RXME  ONLINE       0     0     0
            scsi-SATA_Maxtor_7Y250M0_Y638S56E  ONLINE       0     0     0
            scsi-SATA_Maxtor_7Y250M0_Y638TJFE  ONLINE       0     0     0

errors: No known data errors

Create a 100G block device named fish in the tank zpool.

$ sudo zfs create -V 100G tank/fish
$ sudo zfs list

tank          103G   356G  38.6K  /tank
tank/fish     103G   459G  21.3K  -

Each ZVOL block device will appear as a zd device in /dev/, a symlink with the pool and dataset name will be automatically created under /dev/zvol/. This behavior should be familiar because the standard Linux /dev/disk/ symlinks are managed in fundamentally the same way. Next we can partition the new /dev/zvol/tank/fish block device.

$ sudo sfdisk -q /dev/zvol/tank/fish << EOF

Disk /dev/zvol/tank/fish: 208050 cylinders, 16 heads, 63 sectors/track

sfdisk: ERROR: sector 0 does not have an msdos signature
 /dev/zvol/tank/fish: unrecognized partition table type
Old situation:
No partitions found
New situation:
Units = cylinders of 516096 bytes, blocks of 1024 bytes, counting from 0

   Device Boot Start     End   #cyls    #blocks   Id  System
/dev/zvol/tank/fish1          0+ 208049  208050- 104857199+  83  Linux
/dev/zvol/tank/fish2          0       -       0          0    0  Empty
/dev/zvol/tank/fish3          0       -       0          0    0  Empty
/dev/zvol/tank/fish4          0       -       0          0    0  Empty
Successfully wrote the new partition table

Re-reading the partition table ...

Format the /dev/zvol/tank/fish-part1 partition with ext2 and mount it under /mnt/tank/fish-part1.

$ sudo mkfs.ext2 -q /dev/zvol/tank/fish-part1
$ sudo mkdir -p /mnt/tank/fish-part1
$ sudo mount /dev/zvol/tank/fish-part1 /mnt/tank/fish-part1
$ ls /mnt/tank/fish-part1


Take a snapshot of the pristine ext2 filesystem and mount it read-only.

$ sudo zfs snapshot tank/fish@pristine
$ sudo mkdir /mnt/tank/fish@pristine-part1
$ sudo mount /dev/zvol/tank/fish\@pristine-part1 /mnt/tank/fish\@pristine-part1
$ ls /mnt/tank/fish\@pristine-part1


Changes made to tank/fish-part1 do not appear in the pristine snapshot tank/fish@pristine-part1

$ sudo touch /mnt/tank/fish-part1/foo
$ ls /mnt/tank/fish-part1/

foo  lost+found

$ ls /mnt/tank/fish\@pristine-part1