ZFS on Linux

Overview

ZFS (Zettabyte File System) is both a filesystem and a volume manager. This means it handles disk management (like RAID, partitioning) and data layout (like EXT4 or Btrfs) in a unified way.

Core Concepts

Pool (zpool) Group of physical disks, managed as a unit.
Vdev Virtual device; pools are made of vdevs. Can be single, mirror, RAID-Z, etc.
Dataset A ZFS-managed filesystem, like a subvolume or folder with its own settings.
Snapshot A read-only, point-in-time copy of a dataset.
Clone A writable copy of a snapshot.
Volume (zvol) Block device managed by ZFS (e.g. for iSCSI or swap).

Installing ZFS

Ubuntu Server

sudo apt update
sudo apt install zfsutils-linux
sudo modprobe zfs

Arch Linux

Install required packages:

sudo pacman -S zfs-dkms zfs-utils

Load kernel module:

sudo modprobe zfs
If using a custom kernel, ensure you match with the right `dkms` version.

Creating a ZFS Pool

Basic Single Disk Pool

sudo zpool create mypool /dev/sdX

With Options:

sudo zpool create \
  -o ashift=12 \
  -o autotrim=on \
  -O compression=lz4 \
  -O normalization=formD \
  -O atime=off \
  mypool /dev/sdX
Option Description
-o ashift=12 Aligns to 4K sectors. Recommended for modern HDDs/SSDs.
-o autotrim=on Enables SSD TRIM support.
-O compression=lz4 Enables lightweight compression.
-O normalization=formD Unicode normalization, important for international filenames.
-O atime=off Disables access time updates for better performance.

RAID-Z Pool

sudo zpool create myraid raidz /dev/sd{b,c,d}

Mirror Pool (RAID-1)

sudo zpool create mymirror mirror /dev/sdX /dev/sdY

📂 Creating Datasets

A dataset is a ZFS-managed subvolume with independent settings.

sudo zfs create mypool/mydataset

Common Dataset Options

sudo zfs set \
  compression=zstd \
  atime=off \
  quota=20G \
  recordsize=1M \
  mountpoint=/mnt/mydataset \
  mypool/mydataset
Property Description
compression=zstd Transparent compression using Zstandard.
atime=off Disables last-accessed time.
quota=20G Limits dataset to 20GB.
recordsize=1M Optimize for large files (default is 128K, change based on workload).
mountpoint=/mnt/mydataset Auto-mount location.

To open/edit files:

vim /mnt/mydataset/config.json

Snapshots and Clones

Create a Snapshot

sudo zfs snapshot mypool/mydataset@before-upgrade

List Snapshots

zfs list -t snapshot

Roll Back to Snapshot

sudo zfs rollback mypool/mydataset@before-upgrade
Note: This will destroy any changes made since that snapshot.

Clone a Snapshot (Writable)

sudo zfs clone mypool/mydataset@before-upgrade mypool/mydataset-clone

Creating Zvols (Block Devices)

Zvols are used for swap, VM disks, iSCSI, etc.

sudo zfs create -V 8G mypool/vm_swap
sudo mkswap /dev/zvol/mypool/vm_swap
sudo swapon /dev/zvol/mypool/vm_swap

🔧 Maintenance Tasks

Check Pool Health

sudo zpool status

Scrub Pool (verify checksums)

sudo zpool scrub mypool
Use `zpool status` afterward to see scrub results.

Export / Import

sudo zpool export mypool
sudo zpool import mypool

Destroy Datasets or Pools

sudo zfs destroy mypool/mydataset
sudo zpool destroy mypool

📊 EXT4 vs Btrfs vs ZFS

Feature EXT4 Btrfs ZFS
Snapshots ❌ No ✅ Native ✅ Native
Checksumming Metadata only ✅ Data + Metadata ✅ Data + Metadata
Compression ❌ No ✅ (zlib, zstd, lzo) ✅ (lz4, zstd, gzip)
RAID Support ❌ External only ✅ (limited, flaky) ✅ RAID-Z, mirror, etc.
Deduplication ❌ No ⚠️ Experimental ✅ (RAM intensive)
Scrubbing ❌ No
Max Volume Size 1 EiB 16 EiB 256 ZiB
Encryption ❌ LUKS only ✅ Native ✅ Native
Performance ✅ High ⚠️ Varies ⚠️ Needs RAM, very fast

Sample Workflow Script

# Create pool with good defaults
sudo zpool create -o ashift=12 \
  -O compression=lz4 \
  -O atime=off \
  -O normalization=formD \
  mypool /dev/sdX

# Create dataset for backups
sudo zfs create mypool/backups
sudo zfs set quota=100G mypool/backups
sudo zfs set mountpoint=/mnt/backups mypool/backups

# Take daily snapshot (use cron)
sudo zfs snapshot mypool/backups@$(date +%Y-%m-%d)

# Optional scrub every Sunday (via cron)
sudo zpool scrub mypool

snippet.cpp
by:
▖     ▘▖▖
▌ ▌▌▛▘▌▙▌
▙▖▙▌▙▖▌ ▌
 
edited: June 2025