Skip to content

ZFS On-Disk Format

This documentation describes the on-disk format of ZFS as implemented in OpenZFS. It is an independently written description derived from the publicly available OpenZFS source code.

Overview

ZFS is a filesystem and volume manager that provides 128-bit addressability, provable data integrity through checksumming, a copy-on-write (COW) transactional model, and integrated volume management. Unlike traditional filesystems, ZFS eliminates the concept of volumes by grouping storage devices into a shared pool from which filesystems draw space dynamically.

The copy-on-write design ensures that on-disk data is never overwritten in place. All updates are written to new locations and committed atomically in transaction groups, guaranteeing a consistent on-disk state at all times.

Architecture

The ZFS on-disk format is defined by seven layered software components:

graph TD
    ZPL["ZPL<br/>ZFS POSIX Layer"]
    ZVOL["ZVOL<br/>ZFS Volumes"]
    ZIL["ZIL<br/>ZFS Intent Log"]
    DSL["DSL<br/>Dataset & Snapshot Layer"]
    ZAP["ZAP<br/>ZFS Attribute Processor"]
    DMU["DMU<br/>Data Management Unit"]
    SPA["SPA<br/>Storage Pool Allocator"]

    ZPL --> DMU
    ZVOL --> DMU
    ZPL --> ZIL
    ZPL --> ZAP
    DSL --> DMU
    ZAP --> DMU
    ZIL --> SPA
    DMU --> SPA
Layer Purpose Chapters
SPA (Storage Pool Allocator) Manages vdevs, labels, uberblocks, block allocation, and I/O Chapter 1, Chapter 2, Chapter 9, Chapter 11, Chapter 12, Chapter 15, Chapter 16
DMU (Data Management Unit) Groups blocks into objects and object sets Chapter 3
DSL (Dataset and Snapshot Layer) Manages datasets, snapshots, clones, and their relationships Chapter 4
ZAP (ZFS Attribute Processor) Stores name-value pair attributes in objects Chapter 5
ZPL (ZFS POSIX Layer) Presents DMU objects as a POSIX filesystem Chapter 6
ZIL (ZFS Intent Log) Records synchronous operations for crash recovery Chapter 7
ZVOL (ZFS Volume) Exports an object set as a block device Chapter 8

How Data is Located

The path from raw storage to user data follows a fixed traversal:

  1. Vdev Labels (256 KB structures at known positions on each device) contain the pool configuration and an array of uberblocks.
  2. The Uberblock with the highest valid transaction group number (ub_txg) and a valid ub_magic is the active uberblock. If multiple uberblocks share the same ub_txg, the one with the latest ub_timestamp wins; when both are equal, the higher MMP sequence number is the final tiebreaker. Its ub_rootbp field is a block pointer to the Meta Object Set (MOS).
  3. The MOS (type DMU_OST_META) contains the object directory at object number 1. The object directory is a ZAP object with entries for root_dataset, config, and other pool-wide metadata.
  4. The root_dataset entry points to the root DSL directory, from which all datasets (filesystems, snapshots, volumes) can be reached.
  5. Each dataset points to an object set containing the actual filesystem objects (files, directories, etc.).
graph LR
    VL["Vdev Label"] --> UB["Uberblock"]
    UB -->|ub_rootbp| MOS["Meta Object Set"]
    MOS -->|object 1| OD["Object Directory<br/>(ZAP)"]
    OD -->|root_dataset| RD["Root DSL Dir"]
    RD --> DS["Datasets"]
    DS --> OS["Object Sets<br/>(filesystems, volumes)"]

Reference Files

All source references in this documentation point to files in the OpenZFS source tree:

  • Headers: include/sys/*.h
  • Implementation: module/zfs/*.c
  • Common definitions: module/zcommon/*.c

Document Organization